Font Ttf Low Unicode By Kiva
Font Ttf Low Unicode By Kiva 3,9/5 613 votes
Download koleksi font ttf unicode terbaik. Rock n roll v7x mod by kiva unicode. Free download gratis kumpulan font ttf unicode. Terbaru high memori and low.
PermalinkJoin GitHub today
![Kiva Kiva](https://linux-cdn.softpedia.com/screenshots/Nithyananda-Hindi-Unicode-Font_3.png)
Unicode Font Converter
GitHub is home to over 36 million developers working together to host and review code, manage projects, and build software together.
![Font Ttf Low Unicode By Kiva Font Ttf Low Unicode By Kiva](https://i0.wp.com/blog.fontlab.com/wp-content/uploads/2014/04/fls5hinting_15_FontInfoTTSmoothingGasp.png)
Branch:master
Find file Copy path
Cannot retrieve contributors at this time
Ttf Fonts Pack Free Download
'' |
####### NOTE ####### |
This is based heavily on matplotlib's font_manager.py rev 8713, |
but has been modified to not use other matplotlib modules |
#################### |
A module for finding, managing, and using fonts across platforms. |
This module provides a single :class:`FontManager` instance that can |
be shared across backends and platforms. The :func:`findfont` |
function returns the best TrueType (TTF) font file in the local or |
system font path that matches the specified :class:`FontProperties` |
instance. The :class:`FontManager` also handles Adobe Font Metrics |
(AFM) font files for use by the PostScript backend. |
The design is based on the `W3C Cascading Style Sheet, Level 1 (CSS1) |
font specification <http://www.w3.org/TR/1998/REC-CSS2-19980512/>`_. |
Future versions may implement the Level 2 or 2.1 specifications. |
Experimental support is included for using `fontconfig` on Unix |
variant platforms (Linux, OS X, Solaris). To enable it, set the |
constant ``USE_FONTCONFIG`` in this file to ``True``. Fontconfig has |
the advantage that it is the standard way to look up fonts on X11 |
platforms, so if a font is installed, it is much more likely to be |
found. |
KNOWN ISSUES |
- documentation |
- font variant is untested |
- font stretch is incomplete |
- font size is incomplete |
- font size_adjust is incomplete |
- default font algorithm needs improvement and testing |
- setWeights function needs improvement |
- 'light' is an invalid weight value, remove it. |
- update_fonts not implemented |
Authors : John Hunter <jdhunter@ace.bsd.uchicago.edu> |
Paul Barrett <Barrett@STScI.Edu> |
Michael Droettboom <mdroe@STScI.edu> |
Copyright : John Hunter (2004,2005), Paul Barrett (2004,2005) |
License : matplotlib license (PSF compatible) |
The font directory code is from ttfquery, |
see license/LICENSE_TTFQUERY. |
'' |
from__future__import absolute_import, print_function |
import logging |
import os |
import sys |
import glob |
import subprocess |
import warnings |
import tempfile |
import errno |
import six |
import six.moves as sm |
from fontTools.ttLib import TTCollection, TTFont, TTLibError |
from traits.etsconfig.api import ETSConfig |
from . import afm |
logger = logging.getLogger(__name__) |
USE_FONTCONFIG=False |
font_scalings = { |
'xx-small': 0.579, |
'x-small': 0.694, |
'small': 0.833, |
'medium': 1.0, |
'large': 1.200, |
'x-large': 1.440, |
'xx-large': 1.728, |
'larger': 1.2, |
'smaller': 0.833, |
None: 1.0 |
} |
stretch_dict = { |
'ultra-condensed': 100, |
'extra-condensed': 200, |
'condensed': 300, |
'semi-condensed': 400, |
'normal': 500, |
'semi-expanded': 600, |
'expanded': 700, |
'extra-expanded': 800, |
'ultra-expanded': 900 |
} |
weight_dict = { |
'ultralight': 100, |
'light': 200, |
'normal': 400, |
'regular': 400, |
'book': 400, |
'medium': 500, |
'roman': 500, |
'semibold': 600, |
'demibold': 600, |
'demi': 600, |
'bold': 700, |
'heavy': 800, |
'extra bold': 800, |
'black': 900 |
} |
font_family_aliases =set(['serif', 'sans-serif', 'sans serif', 'cursive', |
'fantasy', 'monospace', 'sans', 'modern']) |
# OS Font paths |
MSFolders = |
r'SoftwareMicrosoftWindowsCurrentVersionExplorerShell Folders' |
MSFontDirectories = [ |
r'SOFTWAREMicrosoftWindows NTCurrentVersionFonts', |
r'SOFTWAREMicrosoftWindowsCurrentVersionFonts' |
] |
X11FontDirectories = [ |
# an old standard installation point |
'/usr/X11R6/lib/X11/fonts/TTF/', |
# here is the new standard location for fonts |
'/usr/share/fonts/', |
# documented as a good place to install new fonts |
'/usr/local/share/fonts/', |
# common application, not really useful |
'/usr/lib/openoffice/share/fonts/truetype/', |
] |
OSXFontDirectories = [ |
'/Library/Fonts/', |
'/Network/Library/Fonts/', |
'/System/Library/Fonts/' |
] |
ifnotUSE_FONTCONFIG: |
home = os.environ.get('HOME') |
if home isnotNone: |
# user fonts on OSX |
path = os.path.join(home, 'Library', 'Fonts') |
OSXFontDirectories.append(path) |
path = os.path.join(home, '.fonts') |
X11FontDirectories.append(path) |
############################################################################### |
# functions to replace those that matplotlib ship in different modules |
############################################################################### |
preferred_fonts = { |
'fantasy': ['Comic Sans MS', 'Chicago', 'Charcoal', 'ImpactWestern', |
'fantasy'], |
'cursive': ['Apple Chancery', 'Textile', 'Zapf Chancery', 'Sand', |
'cursive'], |
'monospace': ['Bitstream Vera Sans Mono', 'DejaVu Sans Mono', |
'Andale Mono', 'Nimbus Mono L', 'Courier New', 'Courier', |
'Fixed', 'Terminal', 'monospace'], |
'serif': ['Bitstream Vera Serif', 'DejaVu Serif', 'New Century Schoolbook', |
'Century Schoolbook L', 'Utopia', 'ITC Bookman', 'Bookman', |
'Nimbus Roman No9 L', 'Times New Roman', 'Times', 'Palatino', |
'Charter', 'serif'], |
'sans-serif': ['Bitstream Vera Sans', 'DejaVu Sans', 'Lucida Grande', |
'Verdana', 'Geneva', 'Lucid', 'Arial', 'Helvetica', |
'Avant Garde', 'sans-serif'] |
} |
def_is_writable_dir(p): |
'' |
p is a string pointing to a putative writable dir -- return True p |
is such a string, else False |
'' |
ifnotisinstance(p, six.string_types): |
returnFalse |
try: |
t = tempfile.TemporaryFile(dir=p) |
t.write(b'kiva.test') |
t.close() |
exceptOSError: |
returnFalse |
else: |
returnTrue |
defget_configdir(): |
'' |
Return the string representing the configuration dir. If s is the |
special string _default_, use HOME/.kiva. s must be writable |
'' |
p = os.path.join(ETSConfig.application_data, 'kiva') |
try: |
os.makedirs(p) |
exceptOSErroras e: |
if e.errno != errno.EEXIST: |
raise |
ifnot _is_writable_dir(p): |
raiseIOError('Configuration directory %s must be writable'% p) |
return p |
defis_string_like(obj): |
'Return True if *obj* looks like a string' |
from numpy import ma |
ifisinstance(obj, six.string_types): |
returnTrue |
# numpy strings are subclass of str, ma strings are not |
if ma.isMaskedArray(obj): |
if obj.ndim 0and obj.dtype.kind in'SU': |
returnTrue |
else: |
returnFalse |
try: |
obj +'' |
except: |
returnFalse |
returnTrue |
defgetPropDict(font): |
n = font['name'] |
propdict = {} |
for prop in n.names: |
prop_key = (prop.platformID, prop.platEncID, prop.langID, prop.nameID) |
propdict[prop_key] = prop.string |
return propdict |
############################################################################### |
# matplotlib code below |
############################################################################### |
synonyms = {'ttf': ('ttf', 'otf', 'ttc'), |
'otf': ('ttf', 'otf', 'ttc'), |
'ttc': ('ttf', 'otf', 'ttc'), |
'afm': ('afm',)} |
defget_fontext_synonyms(fontext): |
'' |
Return a list of file extensions extensions that are synonyms for |
the given file extension *fileext*. |
'' |
return synonyms[fontext] |
defwin32FontDirectory(): |
'' |
Return the user-specified font directory for Win32. This is |
looked up from the registry key:: |
HKEY_CURRENT_USERSoftwareMicrosoftWindowsCurrentVersionExplorerShell FoldersFonts # noqa |
If the key is not found, $WINDIR/Fonts will be returned. |
'' |
try: |
from six.moves import winreg |
exceptImportError: |
pass# Fall through to default |
else: |
try: |
user = winreg.OpenKey(winreg.HKEY_CURRENT_USER, MSFolders) |
try: |
try: |
return winreg.QueryValueEx(user, 'Fonts')[0] |
exceptOSError: |
pass# Fall through to default |
finally: |
winreg.CloseKey(user) |
exceptOSError: |
pass# Fall through to default |
return os.path.join(os.environ['WINDIR'], 'Fonts') |
defwin32InstalledFonts(directory=None, fontext='ttf'): |
'' |
Search for fonts in the specified font directory, or use the |
system directories if none given. A list of TrueType font |
filenames are returned by default, or AFM fonts if *fontext* |
'afm'. |
'' |
from six.moves import winreg |
if directory isNone: |
directory = win32FontDirectory() |
fontext = get_fontext_synonyms(fontext) |
key, items =None, {} |
for fontdir in MSFontDirectories: |
try: |
local = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, fontdir) |
exceptOSError: |
continue |
ifnot local: |
files = [] |
for ext in fontext: |
files.extend(glob.glob(os.path.join(directory, '*.'+ext))) |
return files |
try: |
for j in sm.range(winreg.QueryInfoKey(local)[1]): |
try: |
key, direc, any= winreg.EnumValue(local, j) |
ifnot os.path.dirname(direc): |
direc = os.path.join(directory, direc) |
direc = os.path.abspath(direc).lower() |
if os.path.splitext(direc)[1][1:] in fontext: |
items[direc] =1 |
exceptEnvironmentError: |
continue |
exceptWindowsError: |
continue |
returnlist(items.keys()) |
finally: |
winreg.CloseKey(local) |
returnNone |
defOSXFontDirectory(): |
'' |
Return the system font directories for OS X. This is done by |
starting at the list of hardcoded paths in |
:attr:`OSXFontDirectories` and returning all nested directories |
within them. |
'' |
fontpaths = [] |
for fontdir in OSXFontDirectories: |
try: |
if os.path.isdir(fontdir): |
fontpaths.append(fontdir) |
for dirpath, dirs, _files in os.walk(fontdir): |
fontpaths.extend([os.path.join(dirpath, d) for d in dirs]) |
except (IOError, OSError, TypeError, ValueError): |
pass |
return fontpaths |
defOSXInstalledFonts(directory=None, fontext='ttf'): |
'' |
Get list of font files on OS X - ignores font suffix by default. |
'' |
if directory isNone: |
directory = OSXFontDirectory() |
fontext = get_fontext_synonyms(fontext) |
files = [] |
for path in directory: |
if fontext isNone: |
files.extend(glob.glob(os.path.join(path, '*'))) |
else: |
for ext in fontext: |
files.extend(glob.glob(os.path.join(path, '*.'+ext))) |
files.extend(glob.glob(os.path.join(path, '*.'+ext.upper()))) |
return files |
defx11FontDirectory(): |
'' |
Return the system font directories for X11. This is done by |
starting at the list of hardcoded paths in |
:attr:`X11FontDirectories` and returning all nested directories |
within them. |
'' |
fontpaths = [] |
for fontdir in X11FontDirectories: |
try: |
if os.path.isdir(fontdir): |
fontpaths.append(fontdir) |
for dirpath, dirs, _files in os.walk(fontdir): |
fontpaths.extend([os.path.join(dirpath, d) for d in dirs]) |
except (IOError, OSError, TypeError, ValueError): |
pass |
return fontpaths |
defget_fontconfig_fonts(fontext='ttf'): |
'' |
Grab a list of all the fonts that are being tracked by fontconfig |
by making a system call to ``fc-list``. This is an easy way to |
grab all of the fonts the user wants to be made available to |
applications, without needing knowing where all of them reside. |
'' |
fontext = get_fontext_synonyms(fontext) |
fontfiles = {} |
try: |
pipe = subprocess.Popen(['fc-list', '', 'file'], |
stdout=subprocess.PIPE) |
output = pipe.communicate()[0] |
exceptOSError: |
# Calling fc-list did not work, so we'll just return nothing |
return fontfiles |
output = output.decode('utf8') |
if pipe.returncode 0: |
for line in output.split('n'): |
fname = line.split(':')[0] |
if (os.path.splitext(fname)[1][1:] in fontext and |
os.path.exists(fname)): |
fontfiles[fname] =1 |
return fontfiles |
deffindSystemFonts(fontpaths=None, fontext='ttf'): |
'' |
Search for fonts in the specified font paths. If no paths are |
given, will use a standard set of system paths, as well as the |
list of fonts tracked by fontconfig if fontconfig is installed and |
available. A list of TrueType fonts are returned by default with |
AFM fonts as an option. |
'' |
fontfiles = {} |
fontexts = get_fontext_synonyms(fontext) |
if fontpaths isNone: |
if sys.platform 'win32': |
fontdir = win32FontDirectory() |
fontpaths = [fontdir] |
# now get all installed fonts directly... |
for f in win32InstalledFonts(fontdir): |
base, ext = os.path.splitext(f) |
iflen(ext) >1and ext[1:].lower() in fontexts: |
fontfiles[f] =1 |
else: |
# check for OS X & load its fonts if present |
if sys.platform 'darwin': |
fontpaths = [] |
for f in OSXInstalledFonts(fontext=fontext): |
fontfiles[f] =1 |
else: |
# Otherwise, check X11. |
fontpaths = x11FontDirectory() |
for f in get_fontconfig_fonts(fontext): |
fontfiles[f] =1 |
elifisinstance(fontpaths, six.string_types): |
fontpaths = [fontpaths] |
for path in fontpaths: |
files = [] |
for ext in fontexts: |
files.extend(glob.glob(os.path.join(path, '*.'+ext))) |
files.extend(glob.glob(os.path.join(path, '*.'+ext.upper()))) |
for fname in files: |
abs_path = os.path.abspath(fname) |
# Handle dirs which look like font files, but may contain font |
# files |
if os.path.isdir(abs_path): |
fontpaths.append(abs_path) |
else: |
fontfiles[abs_path] =1 |
return [fname for fname in fontfiles.keys() if os.path.exists(fname)] |
defweight_as_number(weight): |
'' |
Return the weight property as a numeric value. String values |
are converted to their corresponding numeric value. |
'' |
ifisinstance(weight, str): |
try: |
weight = weight_dict[weight.lower()] |
exceptKeyError: |
weight =400 |
elif weight inrange(100, 1000, 100): |
pass |
else: |
raiseValueError('weight not a valid integer') |
return weight |
classFontEntry(object): |
'' |
A class for storing Font properties. It is used when populating |
the font lookup dictionary. |
'' |
def__init__(self, fname='', name='', style='normal', variant='normal', |
weight='normal', stretch='normal', size='medium'): |
self.fname = fname |
self.name = name |
self.style = style |
self.variant = variant |
self.weight = weight |
self.stretch = stretch |
try: |
self.size =str(float(size)) |
exceptValueError: |
self.size = size |
def__repr__(self): |
return'<Font '%s' (%s) %s%s%s%s>'% ( |
self.name, os.path.basename(self.fname), self.style, self.variant, |
self.weight, self.stretch) |
defttfFontProperty(fpath, font): |
'' |
A function for populating the :class:`FontKey` by extracting |
information from the TrueType font file. |
*font* is a :class:`FT2Font` instance. |
'' |
props = getPropDict(font) |
name = props[(1, 0, 0, 1)].decode() |
# Styles are: italic, oblique, and normal (default) |
try: |
sfnt2 = props[(1, 0, 0, 2)] |
except: |
sfnt2 =None |
try: |
sfnt4 = props[(1, 0, 0, 4)] |
except: |
sfnt4 =None |
if sfnt2: |
sfnt2 = sfnt2.lower().decode() |
else: |
sfnt2 ='' |
if sfnt4: |
sfnt4 = sfnt4.lower().decode() |
else: |
sfnt4 ='' |
if sfnt4.find('oblique') >=0: |
style ='oblique' |
elif sfnt4.find('italic') >=0: |
style ='italic' |
elif sfnt2.find('regular') >=0: |
style ='normal' |
else: |
style ='normal' |
# Variants are: small-caps and normal (default) |
# !!!! Untested |
if name.lower() in ['capitals', 'small-caps']: |
variant ='small-caps' |
else: |
variant ='normal' |
# Weights are: 100, 200, 300, 400 (normal: default), 500 (medium), |
# 600 (semibold, demibold), 700 (bold), 800 (heavy), 900 (black) |
# lighter and bolder are also allowed. |
weight =None |
for w in weight_dict.keys(): |
if sfnt4.find(w) >=0: |
weight = w |
break |
ifnot weight: |
weight =400 |
weight = weight_as_number(weight) |
# Stretch can be absolute and relative |
# Absolute stretches are: ultra-condensed, extra-condensed, condensed, |
# semi-condensed, normal, semi-expanded, expanded, extra-expanded, |
# and ultra-expanded. |
# Relative stretches are: wider, narrower |
# Child value is: inherit |
if (sfnt4.find('narrow') >=0or sfnt4.find('condensed') >=0or |
sfnt4.find('cond') >=0): |
stretch ='condensed' |
elif sfnt4.find('demi cond') >=0: |
stretch ='semi-condensed' |
elif sfnt4.find('wide') >=0or sfnt4.find('expanded') >=0: |
stretch ='expanded' |
else: |
stretch ='normal' |
# Sizes can be absolute and relative. |
# Absolute sizes are: xx-small, x-small, small, medium, large, x-large, |
# and xx-large. |
# Relative sizes are: larger, smaller |
# Length value is an absolute font size, e.g. 12pt |
# Percentage values are in 'em's. Most robust specification. |
# !!!! Incomplete |
size ='scalable' |
return FontEntry(fpath, name, style, variant, weight, stretch, size) |
defafmFontProperty(fontpath, font): |
'' |
A function for populating a :class:`FontKey` instance by |
extracting information from the AFM font file. |
*font* is a class:`AFM` instance. |
'' |
name = font.get_familyname() |
fontname = font.get_fontname().lower() |
# Styles are: italic, oblique, and normal (default) |
if font.get_angle() !=0or name.lower().find('italic') >=0: |
style ='italic' |
elif name.lower().find('oblique') >=0: |
style ='oblique' |
else: |
style ='normal' |
# Variants are: small-caps and normal (default) |
# !!!! Untested |
if name.lower() in ['capitals', 'small-caps']: |
variant ='small-caps' |
else: |
variant ='normal' |
# Weights are: 100, 200, 300, 400 (normal: default), 500 (medium), |
# 600 (semibold, demibold), 700 (bold), 800 (heavy), 900 (black) |
# lighter and bolder are also allowed. |
weight = weight_as_number(font.get_weight().lower()) |
# Stretch can be absolute and relative |
# Absolute stretches are: ultra-condensed, extra-condensed, condensed, |
# semi-condensed, normal, semi-expanded, expanded, extra-expanded, |
# and ultra-expanded. |
# Relative stretches are: wider, narrower |
# Child value is: inherit |
if (fontname.find('narrow') >=0or fontname.find('condensed') >=0or |
fontname.find('cond') >=0): |
stretch ='condensed' |
elif fontname.find('demi cond') >=0: |
stretch ='semi-condensed' |
elif fontname.find('wide') >=0or fontname.find('expanded') >=0: |
stretch ='expanded' |
else: |
stretch ='normal' |
# Sizes can be absolute and relative. |
# Absolute sizes are: xx-small, x-small, small, medium, large, x-large, |
# and xx-large. |
# Relative sizes are: larger, smaller |
# Length value is an absolute font size, e.g. 12pt |
# Percentage values are in 'em's. Most robust specification. |
# All AFM fonts are apparently scalable. |
size ='scalable' |
return FontEntry(fontpath, name, style, variant, weight, stretch, size) |
defcreateFontList(fontfiles, fontext='ttf'): |
'' |
A function to create a font lookup list. The default is to create |
a list of TrueType fonts. An AFM font list can optionally be |
created. |
'' |
#FIXME: This function is particularly difficult to debug |
fontlist = [] |
# Add fonts from list of known font files. |
seen = {} |
for fpath in fontfiles: |
logger.debug('createFontDict %s', fpath) |
fname = os.path.split(fpath)[1] |
if fname in seen: |
continue |
else: |
seen[fname] =1 |
if fontext 'afm': |
try: |
fh =open(fpath, 'r') |
except: |
logger.error( |
'Could not open font file %s', fpath, exc_info=True) |
continue |
try: |
try: |
font = afm.AFM(fh) |
finally: |
fh.close() |
exceptRuntimeError: |
logger.error( |
'Could not parse font file %s', fpath, exc_info=True) |
continue |
try: |
prop = afmFontProperty(fpath, font) |
exceptException: |
logger.error( |
'Could not covert font to FontEntry for file %s', fpath, |
exc_info=True |
) |
continue |
else: |
_, ext = os.path.splitext(fpath) |
try: |
if ext.lower() '.ttc': |
collection = TTCollection(str(fpath)) |
try: |
props = [] |
for font in collection.fonts: |
props.append(ttfFontProperty(fpath, font)) |
fontlist.extend(props) |
continue |
exceptException: |
logger.error( |
'Could not covert font to FontEntry for file %s', |
fpath, exc_info=True |
) |
continue |
else: |
font = TTFont(str(fpath)) |
except (RuntimeError, TTLibError): |
logger.error( |
'Could not open font file %s', fpath, exc_info=True) |
continue |
exceptUnicodeError: |
logger.error( |
'Cannot handle unicode file: %s', fpath, exc_info=True) |
continue |
try: |
prop = ttfFontProperty(fpath, font) |
exceptException: |
logger.error( |
'Could not covert font to FontEntry for file %s', fpath, |
exc_info=True |
) |
continue |
fontlist.append(prop) |
return fontlist |
classFontProperties(object): |
'' |
A class for storing and manipulating font properties. |
The font properties are those described in the `W3C Cascading |
Style Sheet, Level 1 |
<http://www.w3.org/TR/1998/REC-CSS2-19980512/>`_ font |
specification. The six properties are: |
- family: A list of font names in decreasing order of priority. |
The items may include a generic font family name, either |
'serif', 'sans-serif', 'cursive', 'fantasy', or 'monospace'. |
In that case, the actual font to be used will be looked up |
from the associated rcParam in :file:`matplotlibrc`. |
- style: Either 'normal', 'italic' or 'oblique'. |
- variant: Either 'normal' or 'small-caps'. |
- stretch: A numeric value in the range 0-1000 or one of |
'ultra-condensed', 'extra-condensed', 'condensed', |
'semi-condensed', 'normal', 'semi-expanded', 'expanded', |
'extra-expanded' or 'ultra-expanded' |
- weight: A numeric value in the range 0-1000 or one of |
'ultralight', 'light', 'normal', 'regular', 'book', 'medium', |
'roman', 'semibold', 'demibold', 'demi', 'bold', 'heavy', |
'extra bold', 'black' |
- size: Either an relative value of 'xx-small', 'x-small', |
'small', 'medium', 'large', 'x-large', 'xx-large' or an |
absolute font size, e.g. 12 |
The default font property for TrueType fonts (as specified in the |
default :file:`matplotlibrc` file) is:: |
sans-serif, normal, normal, normal, normal, scalable. |
Alternatively, a font may be specified using an absolute path to a |
.ttf file, by using the *fname* kwarg. |
The preferred usage of font sizes is to use the relative values, |
e.g. 'large', instead of absolute font sizes, e.g. 12. This |
approach allows all text sizes to be made larger or smaller based |
on the font manager's default font size. |
This class will also accept a `fontconfig |
<http://www.fontconfig.org/>`_ pattern, if it is the only argument |
provided. See the documentation on `fontconfig patterns |
<http://www.fontconfig.org/fontconfig-user.html>`_. This support |
does not require fontconfig to be installed. We are merely |
borrowing its pattern syntax for use here. |
Note that matplotlib's internal font manager and fontconfig use a |
different algorithm to lookup fonts, so the results of the same pattern |
may be different in matplotlib than in other applications that use |
fontconfig. |
'' |
def__init__(self, family=None, style=None, variant=None, weight=None, |
stretch=None, size=None, fname=None, _init=None): |
# if fname is set, it's a hardcoded filename to use |
# _init is used only by copy() |
self._family =None |
self._slant =None |
self._variant =None |
self._weight =None |
self._stretch =None |
self._size =None |
self._file =None |
# This is used only by copy() |
if _init isnotNone: |
self.__dict__.update(_init.__dict__) |
return |
if is_string_like(family): |
# Treat family as a fontconfig pattern if it is the only |
# parameter provided. |
if (style isNoneand variant isNoneand weight isNoneand |
stretch isNoneand size isNoneand fname isNone): |
self.set_fontconfig_pattern(family) |
return |
self.set_family(family) |
self.set_style(style) |
self.set_variant(variant) |
self.set_weight(weight) |
self.set_stretch(stretch) |
self.set_file(fname) |
self.set_size(size) |
def__hash__(self): |
l = [(k, getattr(self, 'get'+ k)()) for k insorted(self.__dict__)] |
returnhash(repr(l)) |
def__str__(self): |
returnstr((self._family, self._slant, self._variant, |
self._weight, self._stretch, self._size)) |
defget_family(self): |
'' |
Return a list of font names that comprise the font family. |
'' |
returnself._family |
defget_name(self): |
'' |
Return the name of the font that best matches the font |
properties. |
'' |
filename =str(fontManager.findfont(self)) |
if filename.endswith('.afm'): |
return afm.AFM(open(filename)).get_familyname() |
font = fontManager.findfont(self) |
return getPropDict(TTFont(str(font)))[(1, 0, 0, 1)] |
defget_style(self): |
'' |
Return the font style. Values are: 'normal', 'italic' or |
'oblique'. |
'' |
returnself._slant |
get_slant = get_style |
defget_variant(self): |
'' |
Return the font variant. Values are: 'normal' or |
'small-caps'. |
'' |
returnself._variant |
defget_weight(self): |
'' |
Set the font weight. Options are: A numeric value in the |
range 0-1000 or one of 'light', 'normal', 'regular', 'book', |
'medium', 'roman', 'semibold', 'demibold', 'demi', 'bold', |
'heavy', 'extra bold', 'black' |
'' |
returnself._weight |
defget_stretch(self): |
'' |
Return the font stretch or width. Options are: 'ultra-condensed', |
'extra-condensed', 'condensed', 'semi-condensed', 'normal', |
'semi-expanded', 'expanded', 'extra-expanded', 'ultra-expanded'. |
'' |
returnself._stretch |
defget_size(self): |
'' |
Return the font size. |
'' |
returnself._size |
defget_size_in_points(self): |
ifself._size isnotNone: |
try: |
returnfloat(self._size) |
exceptValueError: |
pass |
default_size = fontManager.get_default_size() |
return default_size * font_scalings.get(self._size) |
defget_file(self): |
'' |
Return the filename of the associated font. |
'' |
returnself._file |
defset_family(self, family): |
'' |
Change the font family. May be either an alias (generic name |
is CSS parlance), such as: 'serif', 'sans-serif', 'cursive', |
'fantasy', or 'monospace', or a real font name. |
'' |
if family isNone: |
self._family =None |
else: |
if''!=b''andisinstance(family, bytes): |
family = family.decode('utf8') |
if is_string_like(family): |
family = [family] |
self._family = family |
set_name = set_family |
defset_style(self, style): |
'' |
Set the font style. Values are: 'normal', 'italic' or |
'oblique'. |
'' |
if style notin ('normal', 'italic', 'oblique', None): |
raiseValueError('style must be normal, italic or oblique') |
self._slant = style |
set_slant = set_style |
defset_variant(self, variant): |
'' |
Set the font variant. Values are: 'normal' or 'small-caps'. |
'' |
if variant notin ('normal', 'small-caps', None): |
raiseValueError('variant must be normal or small-caps') |
self._variant = variant |
defset_weight(self, weight): |
'' |
Set the font weight. May be either a numeric value in the |
range 0-1000 or one of 'ultralight', 'light', 'normal', |
'regular', 'book', 'medium', 'roman', 'semibold', 'demibold', |
'demi', 'bold', 'heavy', 'extra bold', 'black' |
'' |
if weight isnotNone: |
try: |
weight =int(weight) |
if weight <0or weight >1000: |
raiseValueError() |
exceptValueError: |
if weight notin weight_dict: |
raiseValueError('weight is invalid') |
self._weight = weight |
defset_stretch(self, stretch): |
'' |
Set the font stretch or width. Options are: 'ultra-condensed', |
'extra-condensed', 'condensed', 'semi-condensed', 'normal', |
'semi-expanded', 'expanded', 'extra-expanded' or |
'ultra-expanded', or a numeric value in the range 0-1000. |
'' |
if stretch isnotNone: |
try: |
stretch =int(stretch) |
if stretch <0or stretch >1000: |
raiseValueError() |
exceptValueError: |
if stretch notin stretch_dict: |
raiseValueError('stretch is invalid') |
else: |
stretch =500 |
self._stretch = stretch |
defset_size(self, size): |
'' |
Set the font size. Either an relative value of 'xx-small', |
'x-small', 'small', 'medium', 'large', 'x-large', 'xx-large' |
or an absolute font size, e.g. 12. |
'' |
if size isnotNone: |
try: |
size =float(size) |
exceptValueError: |
if size isnotNoneand size notin font_scalings: |
raiseValueError('size is invalid') |
self._size = size |
defset_file(self, file): |
'' |
Set the filename of the fontfile to use. In this case, all |
other properties will be ignored. |
'' |
self._file =file |
defcopy(self): |
''Return a deep copy of self'' |
return FontProperties(_init=self) |
defttfdict_to_fnames(d): |
'' |
flatten a ttfdict to all the filenames it contains |
'' |
fnames = [] |
for named in d.values(): |
for styled in named.values(): |
for variantd in styled.values(): |
for weightd in variantd.values(): |
for stretchd in weightd.values(): |
for fname in stretchd.values(): |
fnames.append(fname) |
return fnames |
defpickle_dump(data, filename): |
'' |
Equivalent to pickle.dump(data, open(filename, 'wb')) |
but closes the file to prevent filehandle leakage. |
'' |
fh =open(filename, 'wb') |
try: |
sm.cPickle.dump(data, fh) |
finally: |
fh.close() |
defpickle_load(filename): |
'' |
Equivalent to pickle.load(open(filename, 'rb')) |
but closes the file to prevent filehandle leakage. |
'' |
fh =open(filename, 'rb') |
try: |
data = sm.cPickle.load(fh) |
finally: |
fh.close() |
return data |
classFontManager: |
'' |
On import, the :class:`FontManager` singleton instance creates a |
list of TrueType fonts based on the font properties: name, style, |
variant, weight, stretch, and size. The :meth:`findfont` method |
does a nearest neighbor search to find the font that most closely |
matches the specification. If no good enough match is found, a |
default font is returned. |
'' |
# Increment this version number whenever the font cache data |
# format or behavior has changed and requires a existing font |
# cache files to be rebuilt. |
__version__=7 |
def__init__(self, size=None, weight='normal'): |
self._version =self.__version__ |
self.__default_weight = weight |
self.default_size = size |
paths = [] |
# Create list of font paths |
for pathname in ['TTFPATH', 'AFMPATH']: |
if pathname in os.environ: |
ttfpath = os.environ[pathname] |
if ttfpath.find(';') >=0: # win32 style |
paths.extend(ttfpath.split(';')) |
elif ttfpath.find(':') >=0: # unix style |
paths.extend(ttfpath.split(':')) |
else: |
paths.append(ttfpath) |
logger.debug('font search path %s', str(paths)) |
# Load TrueType fonts and create font dictionary. |
self.ttffiles = findSystemFonts(paths) + findSystemFonts() |
self.defaultFamily = { |
'ttf': 'Bitstream Vera Sans', |
'afm': 'Helvetica'} |
self.defaultFont = {} |
for fname inself.ttffiles: |
logger.debug('trying fontname %s', fname) |
if fname.lower().find('vera.ttf') >=0: |
self.defaultFont['ttf'] = fname |
break |
else: |
# use anything |
self.defaultFont['ttf'] =self.ttffiles[0] |
self.ttflist = createFontList(self.ttffiles) |
self.afmfiles = findSystemFonts(paths, fontext='afm') + |
findSystemFonts(fontext='afm') |
self.afmlist = createFontList(self.afmfiles, fontext='afm') |
self.defaultFont['afm'] =None |
self.ttf_lookup_cache = {} |
self.afm_lookup_cache = {} |
defget_default_weight(self): |
'' |
Return the default font weight. |
'' |
returnself.__default_weight |
defget_default_size(self): |
'' |
Return the default font size. |
'' |
returnself.default_size |
defset_default_weight(self, weight): |
'' |
Set the default font weight. The initial value is 'normal'. |
'' |
self.__default_weight = weight |
defupdate_fonts(self, filenames): |
'' |
Update the font dictionary with new font files. |
Currently not implemented. |
'' |
# !!!! Needs implementing |
raiseNotImplementedError |
# Each of the scoring functions below should return a value between |
# 0.0 (perfect match) and 1.0 (terrible match) |
defscore_family(self, families, family2): |
'' |
Returns a match score between the list of font families in |
*families* and the font family name *family2*. |
An exact match anywhere in the list returns 0.0. |
A match by generic font name will return 0.1. |
No match will return 1.0. |
'' |
global preferred_fonts |
family2 = family2.lower() |
for i, family1 inenumerate(families): |
family1 = family1.lower() |
if family1 in font_family_aliases: |
if family1 in ('sans', 'sans serif', 'modern'): |
family1 ='sans-serif' |
options = preferred_fonts[family1] |
options = [x.lower() for x in options] |
if family2 in options: |
idx = options.index(family2) |
return0.1* (float(idx) /len(options)) |
elif family1 family2: |
return0.0 |
return1.0 |
defscore_style(self, style1, style2): |
'' |
Returns a match score between *style1* and *style2*. |
An exact match returns 0.0. |
A match between 'italic' and 'oblique' returns 0.1. |
No match returns 1.0. |
'' |
if style1 style2: |
return0.0 |
elif style1 in ('italic', 'oblique') and |
style2 in ('italic', 'oblique'): |
return0.1 |
return1.0 |
defscore_variant(self, variant1, variant2): |
'' |
Returns a match score between *variant1* and *variant2*. |
An exact match returns 0.0, otherwise 1.0. |
'' |
if variant1 variant2: |
return0.0 |
else: |
return1.0 |
defscore_stretch(self, stretch1, stretch2): |
'' |
Returns a match score between *stretch1* and *stretch2*. |
The result is the absolute value of the difference between the |
CSS numeric values of *stretch1* and *stretch2*, normalized |
between 0.0 and 1.0. |
'' |
try: |
stretchval1 =int(stretch1) |
exceptValueError: |
stretchval1 = stretch_dict.get(stretch1, 500) |
try: |
stretchval2 =int(stretch2) |
exceptValueError: |
stretchval2 = stretch_dict.get(stretch2, 500) |
returnabs(stretchval1 - stretchval2) /1000.0 |
defscore_weight(self, weight1, weight2): |
'' |
Returns a match score between *weight1* and *weight2*. |
The result is the absolute value of the difference between the |
CSS numeric values of *weight1* and *weight2*, normalized |
between 0.0 and 1.0. |
'' |
try: |
weightval1 =int(weight1) |
exceptValueError: |
weightval1 = weight_dict.get(weight1, 500) |
try: |
weightval2 =int(weight2) |
exceptValueError: |
weightval2 = weight_dict.get(weight2, 500) |
returnabs(weightval1 - weightval2) /1000.0 |
defscore_size(self, size1, size2): |
'' |
Returns a match score between *size1* and *size2*. |
If *size2* (the size specified in the font file) is 'scalable', this |
function always returns 0.0, since any font size can be generated. |
Otherwise, the result is the absolute distance between *size1* and |
*size2*, normalized so that the usual range of font sizes (6pt - |
72pt) will lie between 0.0 and 1.0. |
'' |
if size2 'scalable': |
return0.0 |
# Size value should have already been |
try: |
sizeval1 =float(size1) |
exceptValueError: |
sizeval1 =self.default_size * font_scalings(size1) |
try: |
sizeval2 =float(size2) |
exceptValueError: |
return1.0 |
returnabs(sizeval1 - sizeval2) /72.0 |
deffindfont(self, prop, fontext='ttf', directory=None, |
fallback_to_default=True, rebuild_if_missing=True): |
'' |
Search the font list for the font that most closely matches |
the :class:`FontProperties` *prop*. |
:meth:`findfont` performs a nearest neighbor search. Each |
font is given a similarity score to the target font |
properties. The first font with the highest score is |
returned. If no matches below a certain threshold are found, |
the default font (usually Vera Sans) is returned. |
`directory`, is specified, will only return fonts from the |
given directory (or subdirectory of that directory). |
The result is cached, so subsequent lookups don't have to |
perform the O(n) nearest neighbor search. |
If `fallback_to_default` is True, will fallback to the default |
font family (usually 'Bitstream Vera Sans' or 'Helvetica') if |
the first lookup hard-fails. |
See the `W3C Cascading Style Sheet, Level 1 |
<http://www.w3.org/TR/1998/REC-CSS2-19980512/>`_ documentation |
for a description of the font finding algorithm. |
'' |
ifnotisinstance(prop, FontProperties): |
prop = FontProperties(prop) |
fname = prop.get_file() |
if fname isnotNone: |
logger.debug('findfont returning %s', fname) |
return fname |
if fontext 'afm': |
font_cache =self.afm_lookup_cache |
fontlist =self.afmlist |
else: |
font_cache =self.ttf_lookup_cache |
fontlist =self.ttflist |
if directory isNone: |
cached = font_cache.get(hash(prop)) |
if cached: |
return cached |
best_score =1e64 |
best_font =None |
for font in fontlist: |
fname = font.fname |
if (directory isnotNoneand |
os.path.commonprefix([fname, directory]) != directory): |
continue |
# Matching family should have highest priority, so it is multiplied |
# by 10.0 |
score = |
self.score_family(prop.get_family(), font.name) *10.0+ |
self.score_style(prop.get_style(), font.style) + |
self.score_variant(prop.get_variant(), font.variant) + |
self.score_weight(prop.get_weight(), font.weight) + |
self.score_stretch(prop.get_stretch(), font.stretch) + |
self.score_size(prop.get_size(), font.size) |
if score < best_score: |
best_score = score |
best_font = font |
if score 0: |
break |
if best_font isNoneor best_score >=10.0: |
if fallback_to_default: |
warnings.warn( |
'findfont: Font family %s not found. Falling back to %s'% |
(prop.get_family(), self.defaultFamily[fontext])) |
default_prop = prop.copy() |
default_prop.set_family(self.defaultFamily[fontext]) |
returnself.findfont(default_prop, fontext, directory, False) |
else: |
# This is a hard fail -- we can't find anything reasonable, |
# so just return the vera.ttf |
warnings.warn( |
'findfont: Could not match %s. Returning %s'% |
(prop, self.defaultFont[fontext]), |
UserWarning) |
result =self.defaultFont[fontext] |
else: |
logger.debug( |
'findfont: Matching %s to %s (%s) with score of %f', |
prop, best_font.name, best_font.fname, best_score |
) |
result = best_font.fname |
ifnot os.path.isfile(result): |
if rebuild_if_missing: |
logger.debug( |
'findfont: Found a missing font file. Rebuilding cache.') |
_rebuild() |
return fontManager.findfont( |
prop, fontext, directory, True, False) |
else: |
raiseValueError('No valid font could be found') |
if directory isNone: |
font_cache[hash(prop)] = result |
return result |
_is_opentype_cff_font_cache = {} |
defis_opentype_cff_font(filename): |
'' |
Returns True if the given font is a Postscript Compact Font Format |
Font embedded in an OpenType wrapper. Used by the PostScript and |
PDF backends that can not subset these fonts. |
'' |
if os.path.splitext(filename)[1].lower() '.otf': |
result = _is_opentype_cff_font_cache.get(filename) |
if result isNone: |
fd =open(filename, 'rb') |
tag = fd.read(4) |
fd.close() |
result = (tag 'OTTO') |
_is_opentype_cff_font_cache[filename] = result |
return result |
returnFalse |
fontManager =None |
_fmcache = os.path.join(get_configdir(), 'fontList.cache') |
def_rebuild(): |
global fontManager |
fontManager = FontManager() |
pickle_dump(fontManager, _fmcache) |
logger.debug('generated new fontManager') |
# The experimental fontconfig-based backend. |
ifUSE_FONTCONFIGand sys.platform !='win32': |
import re |
deffc_match(pattern, fontext): |
fontexts = get_fontext_synonyms(fontext) |
try: |
pipe = subprocess.Popen(['fc-match', '-sv', pattern], |
stdout=subprocess.PIPE) |
output = pipe.communicate()[0] |
exceptOSError: |
returnNone |
if pipe.returncode 0: |
for match in _fc_match_regex.finditer(output): |
file= match.group(1) |
if os.path.splitext(file)[1][1:] in fontexts: |
returnfile |
returnNone |
_fc_match_regex = re.compile(r'sfile:s+'([^']*)'') |
_fc_match_cache = {} |
deffindfont(prop, fontext='ttf'): |
ifnot is_string_like(prop): |
prop = prop.get_fontconfig_pattern() |
cached = _fc_match_cache.get(prop) |
if cached isnotNone: |
return cached |
result = fc_match(prop, fontext) |
if result isNone: |
result = fc_match(':', fontext) |
_fc_match_cache[prop] = result |
return result |
else: |
try: |
fontManager = pickle_load(_fmcache) |
if (nothasattr(fontManager, '_version') or |
fontManager._version != FontManager.__version__): |
_rebuild() |
else: |
fontManager.default_size =None |
logger.debug('Using fontManager instance from %s', _fmcache) |
except: |
_rebuild() |
deffindfont(prop, **kw): |
global fontManager |
font = fontManager.findfont(prop, **kw) |
return font |
Copy lines Copy permalink