1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
|
"""
Defines the Kiva Font class and a utility method to parse free-form font
specification strings into Font instances.
"""
import copy
from kiva.constants import DEFAULT, DECORATIVE, ROMAN, SCRIPT, \
SWISS, MODERN, TELETYPE, NORMAL, ITALIC, BOLD, BOLD_ITALIC
from font_manager import FontProperties, fontManager
# Various maps used by str_to_font
font_families = {
'default': DEFAULT,
'decorative': DECORATIVE,
'roman': ROMAN,
'script': SCRIPT,
'swiss': SWISS,
'modern': MODERN
}
font_styles = { 'italic': ITALIC }
font_weights = { 'bold': BOLD }
font_noise = [ 'pt', 'point', 'family' ]
def str_to_font(fontspec):
"""
Converts a string specification of a font into a Font instance.
string specifications are of the form: "modern 12", "9 roman italic",
and so on.
"""
point_size = 10
family = DEFAULT
style = NORMAL
weight = NORMAL
underline = 0
facename = []
for word in fontspec.split():
lword = word.lower()
if font_families.has_key( lword ):
family = font_families[ lword ]
elif font_styles.has_key( lword ):
style = font_styles[ lword ]
elif font_weights.has_key( lword ):
weight = font_weights[ lword ]
elif lword == 'underline':
underline = 1
elif lword not in font_noise:
try:
point_size = int( lword )
except:
facename.append( word )
return Font( size=point_size, family=family, weight=weight, style=style,
underline=underline, face_name=' '.join( facename ) )
class Font(object):
""" Font class for device independent font specification.
It is primarily based on wxPython, but looks to be similar to
the needs of Mac OS X, etc.
The family defaults to SWISS so that font rotation will work
correctly under wxPython. Revisit as we get more platforms
defined.
"""
# Maps the constants for font families to names to use when searching for
# fonts.
familymap = {DEFAULT : "serif",
SWISS : "sans-serif",
ROMAN : "serif",
MODERN : "sans-serif",
DECORATIVE : "fantasy",
SCRIPT : "script",
TELETYPE : "monospace" }
def __init__(self, face_name="", size = 12,family = SWISS, weight=NORMAL,
style=NORMAL, underline = 0, encoding=DEFAULT):
if (type(size) != int) or (type(family) != type(SWISS)) or \
(type(weight) != type(NORMAL)) or (type(style) != type(NORMAL)) or \
(type(underline) != int) or (not isinstance(face_name, basestring)) or \
(type(encoding) != type(DEFAULT)):
raise RuntimeError, "Bad value in Font() constructor."
### HACK: C++ stuff expects a string (not unicode) for the face_name, so fix
### if needed. See ticket #2111 in the CP Trac.
if isinstance(face_name, unicode):
face_name = face_name.encode("latin1")
self.size = size
self.family = family
self.weight = weight
self.style = style
self.underline = underline
self.face_name = face_name
self.encoding = encoding
def findfont(self):
""" Returns the file name containing the font that most closely matches
our font properties.
"""
fp = self._make_font_props()
return str(fontManager.findfont(fp))
def findfontname(self):
""" Returns the name of the font that most closely matches our font
properties
"""
fp = self._make_font_props()
return fp.get_name()
def _make_font_props(self):
""" Returns a font_manager.FontProperties object that encapsulates our
font properties
"""
# XXX: change the weight to a numerical value
if self.style == BOLD or self.style == BOLD_ITALIC:
weight = "bold"
else:
weight = "normal"
if self.style == ITALIC or self.style == BOLD_ITALIC:
style = "italic"
else:
style = "normal"
fp = FontProperties(family = self.familymap[self.family], style=style, weight=weight,
size = self.size)
if self.face_name != "":
fp.set_name(self.face_name)
return fp
def _get_name(self):
return self.face_name
def _set_name(self, val):
self.face_name = val
name = property(_get_name, _set_name)
def copy(self):
""" Returns a copy of the font object.
"""
return copy.deepcopy(self)
def __eq__(self, other):
result = False
try:
if (self.family == other.family and
self.size == other.size and
self.weight == other.weight and
self.style == other.style and
self.underline == other.underline and
self.face_name == other.face_name and
self.encoding == other.encoding):
result = True
except AttributeError:
pass
return result
def __ne__(self, other):
return not self.__eq__(other)
def __repr__(self):
return "Font(size=%d,family=%d,weight=%d, style=%d, face_name='%s',encoding=%d )" % \
(self.size, self.family, self.weight, self.style, self.face_name, self.encoding)
|