From: <md...@us...> - 2007-08-06 20:53:37
|
Revision: 3677 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3677&view=rev Author: mdboom Date: 2007-08-06 13:53:11 -0700 (Mon, 06 Aug 2007) Log Message: ----------- Expose Unicode font functionality for mathtext through rcParams Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/_mathtext_data.py trunk/matplotlib/lib/matplotlib/mathtext.py trunk/matplotlib/lib/matplotlib/mpl-data/matplotlibrc trunk/matplotlib/lib/matplotlib/rcsetup.py trunk/matplotlib/matplotlibrc.template Modified: trunk/matplotlib/lib/matplotlib/_mathtext_data.py =================================================================== --- trunk/matplotlib/lib/matplotlib/_mathtext_data.py 2007-08-06 18:52:07 UTC (rev 3676) +++ trunk/matplotlib/lib/matplotlib/_mathtext_data.py 2007-08-06 20:53:11 UTC (rev 3677) @@ -2211,7 +2211,7 @@ '$': 36, '{': 123, '}': 125, -'imath': 0xfd, +'imath': 0x131, 'circumflexaccent' : 770, 'combiningbreve' : 774, 'combiningoverline' : 772, Modified: trunk/matplotlib/lib/matplotlib/mathtext.py =================================================================== --- trunk/matplotlib/lib/matplotlib/mathtext.py 2007-08-06 18:52:07 UTC (rev 3676) +++ trunk/matplotlib/lib/matplotlib/mathtext.py 2007-08-06 20:53:11 UTC (rev 3677) @@ -133,7 +133,7 @@ from cStringIO import StringIO from math import floor, ceil from sets import Set -from unicodedata import category +import unicodedata from warnings import warn from numpy import inf, isinf @@ -462,7 +462,7 @@ cached_font = self.fonts.get(basename) if cached_font is None: - font = FT2Font(os.path.join(self.basepath, basename + ".ttf")) + font = FT2Font(basename) cached_font = self.CachedFont(font) self.fonts[basename] = cached_font self.fonts[font.postscript_name] = cached_font @@ -545,15 +545,24 @@ """ Use the Bakoma true type fonts for rendering """ - fontmap = { 'cal' : 'cmsy10', - 'rm' : 'cmr10', - 'tt' : 'cmtt10', - 'it' : 'cmmi10', - 'bf' : 'cmb10', - 'sf' : 'cmss10', - 'ex' : 'cmex10' - } - + _fontmap = { 'cal' : 'cmsy10', + 'rm' : 'cmr10', + 'tt' : 'cmtt10', + 'it' : 'cmmi10', + 'bf' : 'cmb10', + 'sf' : 'cmss10', + 'ex' : 'cmex10' + } + fontmap = {} + + def __init__(self, *args, **kwargs): + TruetypeFonts.__init__(self, *args, **kwargs) + if not len(self.fontmap): + for key, val in self._fontmap.items(): + fullpath = os.path.join(self.basepath, val + ".ttf") + self.fontmap[key] = fullpath + self.fontmap[val] = fullpath + def _get_offset(self, cached_font, glyph, fontsize, dpi): if cached_font.font.postscript_name == 'Cmex10': return glyph.height/64.0/2.0 + 256.0/64.0 * dpi/72.0 @@ -564,7 +573,7 @@ def _get_glyph(self, fontname, sym, fontsize): if fontname in self.fontmap and latex_to_bakoma.has_key(sym): basename, num = latex_to_bakoma[sym] - slanted = basename == "cmmi10" or sym in self._slanted_symbols + slanted = (basename == "cmmi10") or sym in self._slanted_symbols cached_font = self._get_font(basename) symbol_name = cached_font.font.get_glyph_name(num) num = cached_font.glyphmap[num] @@ -638,15 +647,24 @@ class UnicodeFonts(TruetypeFonts): """An abstract base class for handling Unicode fonts. """ - fontmap = { 'cal' : 'cmsy10', - 'rm' : 'DejaVuSerif', - 'tt' : 'DejaVuSansMono', - 'it' : 'DejaVuSerif-Italic', - 'bf' : 'DejaVuSerif-Bold', - 'sf' : 'DejaVuSans', - None : 'DejaVuSerif-Italic' - } + fontmap = {} + + def __init__(self, *args, **kwargs): + # This must come first so the backend's owner is set correctly + if rcParams['mathtext.fallback_to_cm']: + self.cm_fallback = BakomaFonts(*args, **kwargs) + else: + self.cm_fallback = None + TruetypeFonts.__init__(self, *args, **kwargs) + if not len(self.fontmap): + for texfont in "cal rm tt it bf sf".split(): + setting = rcParams['mathtext.' + texfont] + family, weight, style = setting + prop = FontProperties(family=family, weight=weight, style=style) + font = fontManager.findfont(prop) + self.fontmap[texfont] = font + def _get_offset(self, cached_font, glyph, fontsize, dpi): return 0. @@ -662,34 +680,66 @@ uniindex = get_unicode_index(sym[4:]) fontsize *= GROW_FACTOR else: - warn("No TeX to unicode mapping for '%s'" % sym, + uniindex = ord('?') + warn("No TeX to unicode mapping for '%s'" % sym.encode('ascii', 'replace'), MathTextWarning) # Only characters in the "Letter" class should be italicized in 'it' - # mode. This class includes greek letters, of course. - if (fontname == 'it' - and not category(unichr(uniindex)).startswith("L")): - fontname = 'rm' + # mode. Greek capital letters should be Roman. + if found_symbol: + new_fontname = fontname - slanted = (fontname == 'it') - - cached_font = self._get_font(fontname) - if found_symbol: + if fontname == 'it': + unistring = unichr(uniindex) + if (not unicodedata.category(unistring).startswith("L") + or unicodedata.name(unistring).startswith("GREEK CAPITAL")): + new_fontname = 'rm' + + slanted = (new_fontname == 'it') + cached_font = self._get_font(new_fontname) try: glyphindex = cached_font.charmap[uniindex] except KeyError: warn("Font '%s' does not have a glyph for '%s'" % - (cached_font.font.postscript_name, sym), + (cached_font.font.postscript_name, sym.encode('ascii', 'replace')), MathTextWarning) found_symbol = False if not found_symbol: - uniindex = 0xA4 # currency character, for lack of anything better - glyphindex = cached_font.charmap[uniindex] + if self.cm_fallback: + warn("Substituting with a symbol from the Computer Modern family.", + MathTextWarning) + return self.cm_fallback._get_glyph(fontname, sym, fontsize) + else: + new_fontname = fontname + cached_font = self._get_font(fontname) + uniindex = 0xA4 # currency character, for lack of anything better + glyphindex = cached_font.charmap[uniindex] + slanted = False symbol_name = cached_font.font.get_glyph_name(glyphindex) return cached_font, uniindex, symbol_name, fontsize, slanted + + def set_canvas_size(self, w, h): + 'Dimension the drawing canvas; may be a noop' + TruetypeFonts.set_canvas_size(self, w, h) + if self.cm_fallback: + self.cm_fallback.set_canvas_size(w, h) + def get_used_characters(self): + used_characters = dict(self.used_characters) + if self.cm_fallback: + fallback_characters = self.cm_fallback.get_used_characters() + for key, val in fallback_characters: + used_characters.setdefault(key, Set()).update(val) + return used_characters + + def get_fonts(self): + fonts = [x.font for x in self.fonts.values()] + if self.cm_fallback: + fonts.extend(self.cm_fallback.get_fonts()) + return list(set(fonts)) + class StandardPsFonts(Fonts): """ Use the standard postscript fonts for rendering to backend_ps @@ -750,7 +800,7 @@ # This class includes greek letters, so we're ok if (fontname == 'it' and (len(sym) > 1 or - not category(unicode(sym)).startswith("L"))): + not unicodedata.category(unicode(sym)).startswith("L"))): fontname = 'rm' found_symbol = False @@ -2302,10 +2352,10 @@ font_output = StandardPsFonts(prop) else: backend = self._backend_mapping[self.output]() - font_output = BakomaFonts(prop, backend) - # When we have a decent Unicode font, we should test and - # then make this available as an option - #~ font_output = UnicodeFonts(prop, backend) + if rcParams['mathtext.use_cm']: + font_output = BakomaFonts(prop, backend) + else: + font_output = UnicodeFonts(prop, backend) fontsize = prop.get_size_in_points() if self._parser is None: Modified: trunk/matplotlib/lib/matplotlib/mpl-data/matplotlibrc =================================================================== --- trunk/matplotlib/lib/matplotlib/mpl-data/matplotlibrc 2007-08-06 18:52:07 UTC (rev 3676) +++ trunk/matplotlib/lib/matplotlib/mpl-data/matplotlibrc 2007-08-06 20:53:11 UTC (rev 3677) @@ -159,6 +159,22 @@ # In that case, all text will be sent to TeX for # processing. +# The following settings allow you to select the fonts in math mode. +# They map from a TeX font name to a 3-tuple of the form: +# (family, weight, style) +# These settings are only used if mathtext.use_cm is False, otherwise, the +# Bakoma TeX Computer Modern fonts are used. +#mathtext.cal : (['cursive'], 'normal', 'normal') +#mathtext.rm : (['serif'], 'normal', 'normal') +#mathtext.tt : (['monospace'], 'normal', 'normal') +#mathtext.it : (['serif'], 'normal', 'oblique') +#mathtext.bf : (['serif'], 'bold', 'normal') +#mathtext.sf : (['sans-serif'], 'normal', 'normal') +#mathtext.use_cm : True +#mathtext.fallback_to_cm : True # When True, use symbols from the Computer Modern + # fonts when a symbol can not be found in one of + # the user-specified math fonts. + ### AXES # default face and edge color, default tick sizes, # default fontsizes for ticklabels, and so on. See Modified: trunk/matplotlib/lib/matplotlib/rcsetup.py =================================================================== --- trunk/matplotlib/lib/matplotlib/rcsetup.py 2007-08-06 18:52:07 UTC (rev 3676) +++ trunk/matplotlib/lib/matplotlib/rcsetup.py 2007-08-06 20:53:11 UTC (rev 3677) @@ -198,6 +198,12 @@ except ValueError: raise ValueError('not a valid font size') +def validate_mathtext_font(s): + s = eval(s) + if type(s) in (list, tuple) and len(s) == 3: + return s + raise ValueError('Mathtext font specifier must be a 3-tuple of (family, weight, style)') + validate_markup = ValidateInStrings( 'markup', ['plain', 'tex'], @@ -357,6 +363,15 @@ 'text.fontsize' : ['medium', validate_fontsize], 'text.markup' : ['plain', validate_markup], + 'mathtext.cal' : [(['cursive'], 'normal', 'normal'), validate_mathtext_font], + 'mathtext.rm' : [(['serif'], 'normal', 'normal'), validate_mathtext_font], + 'mathtext.tt' : [(['monospace'], 'normal', 'normal'), validate_mathtext_font], + 'mathtext.it' : [(['serif'], 'normal', 'oblique'), validate_mathtext_font], + 'mathtext.bf' : [(['serif'], 'bold', 'normal'), validate_mathtext_font], + 'mathtext.sf' : [(['sans-serif'], 'normal', 'normal'), validate_mathtext_font], + 'mathtext.use_cm' : [True, validate_bool], + 'mathtext.fallback_to_cm' : [True, validate_bool], + 'image.aspect' : ['equal', validate_aspect], # equal, auto, a number 'image.interpolation' : ['bilinear', str], 'image.cmap' : ['jet', str], # one of gray, jet, etc Modified: trunk/matplotlib/matplotlibrc.template =================================================================== --- trunk/matplotlib/matplotlibrc.template 2007-08-06 18:52:07 UTC (rev 3676) +++ trunk/matplotlib/matplotlibrc.template 2007-08-06 20:53:11 UTC (rev 3677) @@ -159,6 +159,22 @@ # In that case, all text will be sent to TeX for # processing. +# The following settings allow you to select the fonts in math mode. +# They map from a TeX font name to a 3-tuple of the form: +# (family, weight, style) +# These settings are only used if mathtext.use_cm is False, otherwise, the +# Bakoma TeX Computer Modern fonts are used. +#mathtext.cal : (['cursive'], 'normal', 'normal') +#mathtext.rm : (['serif'], 'normal', 'normal') +#mathtext.tt : (['monospace'], 'normal', 'normal') +#mathtext.it : (['serif'], 'normal', 'oblique') +#mathtext.bf : (['serif'], 'bold', 'normal') +#mathtext.sf : (['sans-serif'], 'normal', 'normal') +#mathtext.use_cm : True +#mathtext.fallback_to_cm : True # When True, use symbols from the Computer Modern + # fonts when a symbol can not be found in one of + # the user-specified math fonts. + ### AXES # default face and edge color, default tick sizes, # default fontsizes for ticklabels, and so on. See This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |