From: <ef...@us...> - 2007-08-14 07:07:48
|
Revision: 3707 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3707&view=rev Author: efiring Date: 2007-08-14 00:07:45 -0700 (Tue, 14 Aug 2007) Log Message: ----------- Use pickle to cache entire fontManager instance. Call font_manager.findfont() instead of font_manager.fontManager.findfont(). Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/examples/fonts_demo.py trunk/matplotlib/examples/fonts_demo_kw.py trunk/matplotlib/lib/matplotlib/backends/backend_agg.py trunk/matplotlib/lib/matplotlib/backends/backend_agg2.py trunk/matplotlib/lib/matplotlib/backends/backend_emf.py trunk/matplotlib/lib/matplotlib/backends/backend_gd.py trunk/matplotlib/lib/matplotlib/backends/backend_paint.py trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py trunk/matplotlib/lib/matplotlib/backends/backend_ps.py trunk/matplotlib/lib/matplotlib/backends/backend_qt.py trunk/matplotlib/lib/matplotlib/backends/backend_qt4.py trunk/matplotlib/lib/matplotlib/backends/backend_svg.py trunk/matplotlib/lib/matplotlib/font_manager.py trunk/matplotlib/lib/matplotlib/mathtext.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2007-08-13 15:19:11 UTC (rev 3706) +++ trunk/matplotlib/CHANGELOG 2007-08-14 07:07:45 UTC (rev 3707) @@ -1,3 +1,7 @@ +2007-08-13 Use pickle to cache entire fontManager; change to using + font_manager module-level function findfont wrapper for + the fontManager.findfont method - EF + 2007-08-11 Numpification and cleanup of mlab.py and some examples - EF 2007-08-06 Removed mathtext2 Modified: trunk/matplotlib/examples/fonts_demo.py =================================================================== --- trunk/matplotlib/examples/fonts_demo.py 2007-08-13 15:19:11 UTC (rev 3706) +++ trunk/matplotlib/examples/fonts_demo.py 2007-08-14 07:07:45 UTC (rev 3707) @@ -3,9 +3,9 @@ Show how to set custom font properties. For interactive users, you can also use kwargs to the text command, -which requires less typing. See exampes/fonts_demo_kw.py +which requires less typing. See examples/fonts_demo_kw.py """ -from matplotlib.font_manager import fontManager, FontProperties +from matplotlib.font_manager import FontProperties from pylab import * subplot(111, axisbg='w') Modified: trunk/matplotlib/examples/fonts_demo_kw.py =================================================================== --- trunk/matplotlib/examples/fonts_demo_kw.py 2007-08-13 15:19:11 UTC (rev 3706) +++ trunk/matplotlib/examples/fonts_demo_kw.py 2007-08-14 07:07:45 UTC (rev 3707) @@ -4,7 +4,7 @@ style of coding, see examples/fonts_demo.py. """ -from matplotlib.font_manager import fontManager, FontProperties +from matplotlib.font_manager import FontProperties from pylab import * subplot(111, axisbg='w') Modified: trunk/matplotlib/lib/matplotlib/backends/backend_agg.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_agg.py 2007-08-13 15:19:11 UTC (rev 3706) +++ trunk/matplotlib/lib/matplotlib/backends/backend_agg.py 2007-08-14 07:07:45 UTC (rev 3707) @@ -81,7 +81,7 @@ GraphicsContextBase, FigureManagerBase, FigureCanvasBase from matplotlib.cbook import enumerate, is_string_like, exception_to_str from matplotlib.figure import Figure -from matplotlib.font_manager import fontManager +from matplotlib.font_manager import findfont from matplotlib.ft2font import FT2Font, LOAD_DEFAULT from matplotlib.mathtext import math_parse_s_ft2font from matplotlib.transforms import lbwh_to_bbox @@ -175,7 +175,7 @@ 'debug-annoying') width, height, fonts, used_characters = math_parse_s_ft2font( s, self.dpi.get(), prop) - + if angle == 90: width, height = height, width for font in fonts: @@ -297,7 +297,7 @@ font = _fontd.get(key) if font is None: - fname = fontManager.findfont(prop) + fname = findfont(prop) font = FT2Font(str(fname)) _fontd[key] = font Modified: trunk/matplotlib/lib/matplotlib/backends/backend_agg2.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_agg2.py 2007-08-13 15:19:11 UTC (rev 3706) +++ trunk/matplotlib/lib/matplotlib/backends/backend_agg2.py 2007-08-14 07:07:45 UTC (rev 3707) @@ -15,7 +15,6 @@ from matplotlib.cbook import enumerate, is_string_like, exception_to_str from matplotlib.figure import Figure -from matplotlib.font_manager import fontManager from matplotlib.ft2font import FT2Font from matplotlib.mathtext import math_parse_s_ft2font Modified: trunk/matplotlib/lib/matplotlib/backends/backend_emf.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_emf.py 2007-08-13 15:19:11 UTC (rev 3706) +++ trunk/matplotlib/lib/matplotlib/backends/backend_emf.py 2007-08-14 07:07:45 UTC (rev 3707) @@ -23,7 +23,7 @@ from matplotlib.figure import Figure from matplotlib.transforms import Bbox -from matplotlib.font_manager import fontManager, FontProperties +from matplotlib.font_manager import findfont, FontProperties from matplotlib.ft2font import FT2Font, KERNING_UNFITTED, KERNING_DEFAULT, KERNING_UNSCALED # Font handling stuff snarfed from backend_ps, but only using TTF fonts @@ -473,7 +473,7 @@ key = hash(prop) font = _fontd.get(key) if font is None: - fname = fontManager.findfont(prop) + fname = findfont(prop) if debugText: print "_get_font_ttf: name=%s" % fname font = FT2Font(str(fname)) _fontd[key] = font Modified: trunk/matplotlib/lib/matplotlib/backends/backend_gd.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_gd.py 2007-08-13 15:19:11 UTC (rev 3706) +++ trunk/matplotlib/lib/matplotlib/backends/backend_gd.py 2007-08-14 07:07:45 UTC (rev 3707) @@ -22,7 +22,7 @@ from matplotlib.colors import colorConverter from matplotlib.figure import Figure from matplotlib.transforms import Bbox -from matplotlib.font_manager import fontManager +from matplotlib.font_manager import findfont # support old font names if (os.environ.has_key('GDFONTPATH') and not os.environ.has_key('TTFPATH')): @@ -66,7 +66,7 @@ """ size = prop.get_size_in_points() - font = fontManager.findfont(prop) + font = findfont(prop) scale = self.get_text_scale() try: @@ -176,7 +176,7 @@ """ size = prop.get_size_in_points() - font = fontManager.findfont(prop) + font = findfont(prop) x = int(x) y = int(y) Modified: trunk/matplotlib/lib/matplotlib/backends/backend_paint.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_paint.py 2007-08-13 15:19:11 UTC (rev 3706) +++ trunk/matplotlib/lib/matplotlib/backends/backend_paint.py 2007-08-14 07:07:45 UTC (rev 3707) @@ -28,7 +28,7 @@ from matplotlib.figure import Figure from matplotlib.text import Text, _process_text_args -from matplotlib.font_manager import fontManager +from matplotlib.font_manager import findfont """ @@ -106,7 +106,7 @@ Get the paint font for text instance t, cacheing for efficiency """ - fname = fontManager.findfont(prop) + fname = findfont(prop) size = self.get_text_scale() * prop.get_size_in_points() props = fname, size, angle Modified: trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py 2007-08-13 15:19:11 UTC (rev 3706) +++ trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py 2007-08-14 07:07:45 UTC (rev 3707) @@ -24,7 +24,7 @@ FigureManagerBase, FigureCanvasBase from matplotlib.cbook import Bunch, enumerate, is_string_like, reverse_dict, get_realpath_and_stat from matplotlib.figure import Figure -from matplotlib.font_manager import fontManager +from matplotlib.font_manager import findfont from matplotlib.afm import AFM from matplotlib.dviread import Dvi from matplotlib.ft2font import FT2Font, FIXED_WIDTH, ITALIC, LOAD_NO_SCALE, \ @@ -441,9 +441,9 @@ if is_string_like(fontprop): filename = fontprop elif rcParams['pdf.use14corefonts']: - filename = fontManager.findfont(fontprop, fontext='afm') + filename = findfont(fontprop, fontext='afm') else: - filename = fontManager.findfont(fontprop) + filename = findfont(fontprop) Fx = self.fontNames.get(filename) if Fx is None: @@ -484,7 +484,7 @@ return "%s-%s" % ( os.path.splitext(os.path.basename(filename))[0], symbol_name) - + def embedTTF(self, filename, characters): """Embed the TTF font from the named file into the document.""" @@ -499,7 +499,7 @@ # boxes and the like if value < 0: return floor(value) else: return ceil(value) - + def embedTTFType3(font, characters, descriptor): """The Type 3-specific part of embedding a Truetype font""" widthsObject = self.reserveObject('font widths') @@ -509,7 +509,7 @@ differencesArray = [] firstchar, lastchar = 0, 255 bbox = [cvt(x, nearest=False) for x in font.bbox] - + fontdict = { 'Type' : Name('Font'), 'BaseFont' : ps_name, @@ -667,7 +667,7 @@ max_ccode = max(ccode, max_ccode) widths.sort() cid_to_gid_map = cid_to_gid_map[:max_ccode + 1] - + last_ccode = -2 w = [] max_width = 0 @@ -689,7 +689,7 @@ self.endStream() descriptor['MaxWidth'] = max_width - + # Write everything out self.writeObject(cidFontDictObject, cidFontDict) self.writeObject(type0FontDictObject, type0FontDict) @@ -699,7 +699,7 @@ return type0FontDictObject # Beginning of main embedTTF function... - + # You are lost in a maze of TrueType tables, all different... ps_name = Name(font.get_sfnt()[(1,0,0,6)]) pclt = font.get_sfnt_table('pclt') \ @@ -737,7 +737,7 @@ return embedTTFType3(font, characters, descriptor) elif fonttype == 42: return embedTTFType42(font, characters, descriptor) - + def alphaState(self, alpha): """Return name of an ExtGState that sets alpha to the given value""" @@ -987,7 +987,7 @@ self.encode_string = self.encode_string_type3 else: self.encode_string = self.encode_string_type42 - + def finalize(self): self.gc.finalize() del self.truetype_font_cache @@ -1020,7 +1020,7 @@ used_characters = self.used_characters.setdefault( stat_key, (realpath, Set())) used_characters[1].update(set) - + def draw_arc(self, gcEdge, rgbFace, x, y, width, height, angle1, angle2, rotation): """ @@ -1187,7 +1187,7 @@ self.file.output(Op.gsave) self.file.output(cos(a), sin(a), -sin(a), cos(a), x, y, Op.concat_matrix) - + self.check_gc(gc, gc._rgb) self.file.output(Op.begin_text) prev_font = None, None @@ -1279,7 +1279,7 @@ def encode_string_type3(self, s): return s.encode('cp1252', 'replace') - + def encode_string_type42(self, s): return s.encode('utf-16be', 'replace') @@ -1296,7 +1296,7 @@ # use XObject command (Do). If using Type 42 fonts, all of # this complication is avoided, but of course, those fonts can # not be subsetted. - + if ismath: return self.draw_mathtext(gc, x, y, s, prop, angle) self.check_gc(gc, gc._rgb) @@ -1344,7 +1344,7 @@ Op.selectfont) self._setup_textpos(x, y, angle) self.file.output(self.encode_string(s), Op.show, Op.end_text) - + def draw_text_woven(chunks): """Outputs text using the woven method, alternating between chunks of 1-byte characters and 2-byte characters. @@ -1375,7 +1375,7 @@ self._setup_textpos(newx, 0, 0, oldx, 0, 0) self.file.output(self.encode_string(chunk), Op.show) oldx = newx - + lastgind = None for c in chunk: ccode = ord(c) @@ -1413,7 +1413,7 @@ return draw_text_simple() else: return draw_text_woven(chunks) - + def get_text_width_height(self, s, prop, ismath): # FT2Font can handle unicode, and so can we # if isinstance(s, unicode): @@ -1443,7 +1443,7 @@ key = hash(prop) font = self.afm_font_cache.get(key) if font is None: - filename = fontManager.findfont(prop, fontext='afm') + filename = findfont(prop, fontext='afm') fh = file(filename) font = AFM(fh) fh.close() @@ -1454,7 +1454,7 @@ key = hash(prop) font = self.truetype_font_cache.get(key) if font is None: - filename = fontManager.findfont(prop) + filename = findfont(prop) font = FT2Font(str(filename)) self.truetype_font_cache[key] = font font.clear() Modified: trunk/matplotlib/lib/matplotlib/backends/backend_ps.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_ps.py 2007-08-13 15:19:11 UTC (rev 3706) +++ trunk/matplotlib/lib/matplotlib/backends/backend_ps.py 2007-08-14 07:07:45 UTC (rev 3707) @@ -18,7 +18,7 @@ from matplotlib.cbook import is_string_like, izip, get_realpath_and_stat from matplotlib.figure import Figure -from matplotlib.font_manager import fontManager +from matplotlib.font_manager import findfont from matplotlib.ft2font import FT2Font, KERNING_DEFAULT, LOAD_NO_HINTING from matplotlib.ttconv import convert_ttf_to_ps from matplotlib.mathtext import math_parse_s_ps @@ -158,7 +158,7 @@ used_characters = self.used_characters.setdefault( stat_key, (realpath, Set())) used_characters[1].update(set) - + def set_color(self, r, g, b, store=1): if (r,g,b) != self.color: if r==g and r==b: @@ -307,7 +307,7 @@ key = hash(prop) font = self.afmfontd.get(key) if font is None: - font = AFM(file(fontManager.findfont(prop, fontext='afm'))) + font = AFM(file(findfont(prop, fontext='afm'))) self.afmfontd[key] = font return font @@ -315,7 +315,7 @@ key = hash(prop) font = self.fontd.get(key) if font is None: - fname = fontManager.findfont(prop) + fname = findfont(prop) font = FT2Font(str(fname)) self.fontd[key] = font font.clear() Modified: trunk/matplotlib/lib/matplotlib/backends/backend_qt.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_qt.py 2007-08-13 15:19:11 UTC (rev 3706) +++ trunk/matplotlib/lib/matplotlib/backends/backend_qt.py 2007-08-14 07:07:45 UTC (rev 3707) @@ -6,7 +6,6 @@ import matplotlib from matplotlib import verbose from matplotlib.cbook import is_string_like, enumerate, onetrue -from matplotlib.font_manager import fontManager from matplotlib.backend_bases import RendererBase, GraphicsContextBase, \ FigureManagerBase, FigureCanvasBase, NavigationToolbar2, cursors from matplotlib._pylab_helpers import Gcf Modified: trunk/matplotlib/lib/matplotlib/backends/backend_qt4.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_qt4.py 2007-08-13 15:19:11 UTC (rev 3706) +++ trunk/matplotlib/lib/matplotlib/backends/backend_qt4.py 2007-08-14 07:07:45 UTC (rev 3707) @@ -6,7 +6,6 @@ import matplotlib from matplotlib import verbose from matplotlib.cbook import is_string_like, enumerate, onetrue -from matplotlib.font_manager import fontManager from matplotlib.backend_bases import RendererBase, GraphicsContextBase, \ FigureManagerBase, FigureCanvasBase, NavigationToolbar2, cursors from matplotlib._pylab_helpers import Gcf Modified: trunk/matplotlib/lib/matplotlib/backends/backend_svg.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_svg.py 2007-08-13 15:19:11 UTC (rev 3706) +++ trunk/matplotlib/lib/matplotlib/backends/backend_svg.py 2007-08-14 07:07:45 UTC (rev 3707) @@ -7,7 +7,7 @@ FigureManagerBase, FigureCanvasBase from matplotlib.colors import rgb2hex from matplotlib.figure import Figure -from matplotlib.font_manager import fontManager, FontProperties +from matplotlib.font_manager import findfont, FontProperties from matplotlib.ft2font import FT2Font, KERNING_DEFAULT, LOAD_NO_HINTING from matplotlib.mathtext import math_parse_s_ft2font_svg @@ -57,7 +57,7 @@ key = hash(prop) font = _fontd.get(key) if font is None: - fname = fontManager.findfont(prop) + fname = findfont(prop) font = FT2Font(str(fname)) _fontd[key] = font font.clear() @@ -275,9 +275,9 @@ lastgind = gind currx += kern/64.0 - svg.append('<use xlink:href="#%s" transform="translate(%s)"/>\n' + svg.append('<use xlink:href="#%s" transform="translate(%s)"/>\n' % (charid, currx)) - + currx += (glyph.linearHoriAdvance / 65536.0) svg.append('</g>\n') svg = ''.join(svg) @@ -309,17 +309,17 @@ currx, curry = 0.0, 0.0 for step in glyph.path: if step[0] == 0: # MOVE_TO - path_data.append("m%s %s" % + path_data.append("m%s %s" % (step[1] - currx, -step[2] - curry)) elif step[0] == 1: # LINE_TO - path_data.append("l%s %s" % + path_data.append("l%s %s" % (step[1] - currx, -step[2] - curry)) elif step[0] == 2: # CURVE3 - path_data.append("q%s %s %s %s" % + path_data.append("q%s %s %s %s" % (step[1] - currx, -step[2] - curry, step[3] - currx, -step[4] - curry)) elif step[0] == 3: # CURVE4 - path_data.append("c%s %s %s %s %s %s" % + path_data.append("c%s %s %s %s %s %s" % (step[1] - currx, -step[2] - curry, step[3] - currx, -step[4] - curry, step[5] - currx, -step[6] - curry)) @@ -356,8 +356,8 @@ for font, fontsize, thetext, new_x, new_y_mtc, metrics in svg_glyphs: charid = self._add_char_def(font, thetext) - - svg.append('<use xlink:href="#%s" transform="translate(%s, %s) scale(%s)"/>\n' % + + svg.append('<use xlink:href="#%s" transform="translate(%s, %s) scale(%s)"/>\n' % (charid, new_x, -new_y_mtc, fontsize / self.FONT_SCALE)) svg.append('</g>\n') else: # not rcParams['svg.embed_char_paths'] @@ -373,7 +373,7 @@ for font, fontsize, thetext, new_x, new_y_mtc, metrics in svg_glyphs: new_y = - new_y_mtc - svg.append('<tspan style="font-size: %f; font-family: %s"' % + svg.append('<tspan style="font-size: %f; font-family: %s"' % (fontsize, font.family_name)) xadvance = metrics.advance svg.append(' textLength="%f"' % xadvance) @@ -387,7 +387,7 @@ svg.append(' dy="%f"' % dy) thetext = escape_xml_text(thetext) - + svg.append('>%s</tspan>\n' % thetext) curr_x = new_x + xadvance @@ -407,7 +407,7 @@ for x, y, width, height in svg_rects: svg.append('<rect x="%s" y="%s" width="%s" height="%s" fill="black" stroke="none" />' % (x, -y + height, width, height)) svg.append("</g>") - + self._svgwriter.write (''.join(svg)) self.close_group("mathtext") Modified: trunk/matplotlib/lib/matplotlib/font_manager.py =================================================================== --- trunk/matplotlib/lib/matplotlib/font_manager.py 2007-08-13 15:19:11 UTC (rev 3706) +++ trunk/matplotlib/lib/matplotlib/font_manager.py 2007-08-14 07:07:45 UTC (rev 3707) @@ -2,7 +2,7 @@ A module for finding, managing, and using fonts across-platforms. This module provides a single FontManager that can be shared across -backends and platforms. The findfont() method returns the best +backends and platforms. The findfont() function returns the best TrueType (TTF) font file in the local or system font path that matches the specified FontProperties. The FontManager also handles Adobe Font Metrics (AFM) font files for use by the PostScript backend. @@ -231,10 +231,10 @@ if sys.platform == 'darwin': for f in OSXInstalledFonts(): fontfiles[f] = 1 - + for f in get_fontconfig_fonts(fontext): fontfiles[f] = 1 - + elif isinstance(fontpaths, (str, unicode)): fontpaths = [fontpaths] @@ -654,7 +654,7 @@ def get_name(self): """Return the name of the font that best matches the font properties.""" - return ft2font.FT2Font(str(fontManager.findfont(self))).family_name + return ft2font.FT2Font(str(findfont(self))).family_name def get_style(self): """Return the font style. Values are: normal, italic or oblique.""" @@ -849,42 +849,23 @@ # use anything self.defaultFont = self.ttffiles[0] - cache_message = \ -"""Saving TTF font cache for non-PS backends to %s. -Delete this file to have matplotlib rebuild the cache.""" + self.ttfdict = createFontDict(self.ttffiles) - oldcache = os.path.join(get_home(), 'ttffont.cache') - ttfcache = os.path.join(get_configdir(), 'ttffont.cache') - if os.path.exists(oldcache): - print >> sys.stderr, 'Moving old ttfcache location "%s" to new location "%s"'%(oldcache, ttfcache) - shutil.move(oldcache, ttfcache) - - def rebuild(): - self.ttfdict = createFontDict(self.ttffiles) - pickle_dump(self.ttfdict, ttfcache) - verbose.report(cache_message % ttfcache) - - try: - self.ttfdict = pickle_load(ttfcache) - except: - rebuild() + if rcParams['pdf.use14corefonts']: + # Load only the 14 PDF core fonts. These fonts do not need to be + # embedded; every PDF viewing application is required to have them: + # Helvetica, Helvetica-Bold, Helvetica-Oblique, Helvetica-BoldOblique, + # Courier, Courier-Bold, Courier-Oblique, Courier-BoldOblique, + # Times-Roman, Times-Bold, Times-Italic, Times-BoldItalic, Symbol, + # ZapfDingbats. + afmpath = os.path.join(rcParams['datapath'],'fonts','pdfcorefonts') + afmfiles = findSystemFonts(afmpath, fontext='afm') + self.afmdict = createFontDict(afmfiles, fontext='afm') else: - # verify all the cached fnames still exist; if not rebuild - for fname in ttfdict_to_fnames(self.ttfdict): - if not os.path.exists(fname): - rebuild() - break - verbose.report('loaded ttfcache file %s'%ttfcache) + self.afmfiles = findSystemFonts(paths, fontext='afm') + \ + findSystemFonts(fontext='afm') + self.afmdict = createFontDict(self.afmfiles, fontext='afm') - #self.ttfdict = createFontDict(self.ttffiles) - - # Load AFM fonts for PostScript - # Only load file names at this stage, the font dictionary will be - # created when needed. - self.afmfiles = findSystemFonts(paths, fontext='afm') + \ - findSystemFonts(fontext='afm') - self.afmdict = {} - def get_default_weight(self): "Return the default font weight." return self.__default_weight @@ -930,8 +911,6 @@ return fname if fontext == 'afm': - if len(self.afmdict) == 0: - self.afmdict = self._get_afm_font_dict() fontdict = self.afmdict else: fontdict = self.ttfdict @@ -1009,7 +988,7 @@ return fname font_family_aliases = ['serif', 'sans-serif', 'cursive', 'fantasy', 'monospace'] - + for name in prop.get_family(): if name in font_family_aliases: for name2 in rcParams['font.' + name]: @@ -1028,37 +1007,29 @@ return self.defaultFont return fname - def _get_afm_font_dict(self): - cache_message = "Saving AFM font cache for PS and PDF backends to %s.\n" \ - "Delete this file to have matplotlib rebuild the cache." - if rcParams['pdf.use14corefonts']: - # Load only the 14 PDF core fonts. These fonts do not need to be - # embedded; every PDF viewing application is required to have them: - # Helvetica, Helvetica-Bold, Helvetica-Oblique, Helvetica-BoldOblique, - # Courier, Courier-Bold, Courier-Oblique, Courier-BoldOblique, - # Times-Roman, Times-Bold, Times-Italic, Times-BoldItalic, Symbol, - # ZapfDingbats. - afmcache = os.path.join(get_configdir(), 'pdfcorefont.cache') - try: - fontdict = pickle_load(afmcache) - except: - afmpath = os.path.join(rcParams['datapath'],'fonts','pdfcorefonts') - afmfiles = findSystemFonts(afmpath, fontext='afm') - fontdict = createFontDict(afmfiles, fontext='afm') - pickle_dump(fontdict, afmcache) - verbose.report(cache_message % afmcache) - else: - # Load all available AFM fonts - afmcache = os.path.join(get_configdir(), '.afmfont.cache') - try: - fontdict = pickle_load(afmcache) - except: - fontdict = createFontDict(self.afmfiles, fontext='afm') - pickle_dump(fontdict, afmcache) - verbose.report(cache_message % afmcache) +_fmcache = os.path.join(get_configdir(), 'fontManager.cache') - return fontdict +fontManager = None +def _rebuild(): + global fontManager + fontManager = FontManager() + pickle_dump(fontManager, _fmcache) + verbose.report("generated new fontManager") -fontManager = FontManager() +try: + fontManager = pickle_load(_fmcache) + verbose.report("Using fontManager instance from %s" % _fmcache) +except: + _rebuild() + +def findfont(prop, **kw): + global fontManager + font = fontManager.findfont(prop, **kw) + if not os.path.exists(font): + verbose.report("%s returned by pickled fontManager does not exist" % font) + _rebuild() + font = fontManager.findfont(prop, **kw) + return font + Modified: trunk/matplotlib/lib/matplotlib/mathtext.py =================================================================== --- trunk/matplotlib/lib/matplotlib/mathtext.py 2007-08-13 15:19:11 UTC (rev 3706) +++ trunk/matplotlib/lib/matplotlib/mathtext.py 2007-08-14 07:07:45 UTC (rev 3707) @@ -71,7 +71,7 @@ Allowed TeX symbols: [MGDTODO: This list is no longer exhaustive and needs to be updated] - + \/ \Delta \Downarrow \Gamma \Im \LEFTangle \LEFTbrace \LEFTbracket \LEFTparen \Lambda \Leftarrow \Leftbrace \Leftbracket \Leftparen \Leftrightarrow \Omega \P \Phi \Pi \Psi \RIGHTangle \RIGHTbrace @@ -120,7 +120,7 @@ The *Unicode* classes were incomplete when I found them, and have not been refactored to support intermingling of regular text and math text yet. They are most likely broken. -- Michael Droettboom, July 2007 - + Author : John Hunter <jdh...@ac...> Michael Droettboom <md...@st...> (rewrite based on TeX box layout algorithms) @@ -149,14 +149,14 @@ from matplotlib.cbook import enumerate, iterable, Bunch, get_realpath_and_stat, \ is_string_like from matplotlib.ft2font import FT2Font, KERNING_DEFAULT, LOAD_DEFAULT, LOAD_NO_HINTING -from matplotlib.font_manager import fontManager, FontProperties +from matplotlib.font_manager import findfont, FontProperties from matplotlib._mathtext_data import latex_to_bakoma, \ latex_to_standard, tex2uni, type12uni, tex2type1, uni2type1 from matplotlib import get_data_path, rcParams #################### - + # a character over another character charOverChars = { # The first 2 entires in the tuple are (font, char, sizescale) for @@ -240,7 +240,7 @@ def get_hinting_type(self): return LOAD_NO_HINTING - + class MathtextBackendAgg(MathtextBackend): def set_canvas_size(self, w, h): MathtextBackend.set_canvas_size(self, w, h) @@ -263,17 +263,17 @@ def get_hinting_type(self): return LOAD_DEFAULT - + class MathtextBackendPs(MathtextBackend): def __init__(self): self.pswriter = StringIO() - + def render_glyph(self, ox, oy, info): oy = self.height - oy + info.offset postscript_name = info.postscript_name fontsize = info.fontsize symbol_name = info.symbol_name - + ps = """/%(postscript_name)s findfont %(fontsize)s scalefont setfont @@ -291,12 +291,12 @@ self.height, self.pswriter, self.fonts_object.get_used_characters()) - + class MathtextBackendPdf(MathtextBackend): def __init__(self): self.glyphs = [] self.rects = [] - + def render_glyph(self, ox, oy, info): filename = info.font.fname oy = self.height - oy + info.offset @@ -318,7 +318,7 @@ def __init__(self): self.svg_glyphs = [] self.svg_rects = [] - + def render_glyph(self, ox, oy, info): oy = self.height - oy + info.offset thetext = unichr(info.num) @@ -341,7 +341,7 @@ def __init__(self): self.glyphs = [] self.rects = [] - + def render_glyph(self, ox, oy, info): oy = oy - info.offset - self.height thetext = unichr(info.num) @@ -357,7 +357,7 @@ self.height, self.glyphs, self.rects) - + class Fonts(object): """ An abstract base class for fonts that want to render mathtext @@ -378,7 +378,7 @@ # Make these classes doubly-linked self.mathtext_backend.fonts_object = self self.used_characters = {} - + def get_kern(self, font1, sym1, fontsize1, font2, sym2, fontsize2, dpi): """ @@ -389,7 +389,7 @@ symX: a symbol in raw TeX form. e.g. '1', 'x' or '\sigma' fontsizeX: the fontsize in points dpi: the current dots-per-inch - + sym is a single symbol(alphanum, punct) or a special symbol like \sigma. @@ -435,7 +435,7 @@ def get_underline_thickness(self, font, fontsize, dpi): raise NotImplementedError() - + def get_used_characters(self): return self.used_characters @@ -446,7 +446,7 @@ """Override if your font provides multiple sizes of the same symbol.""" return [(fontname, sym)] - + class TruetypeFonts(Fonts): """ A generic base class for all font setups that use Truetype fonts @@ -467,17 +467,17 @@ def __repr__(self): return repr(self.font) - + def __init__(self, default_font_prop, mathtext_backend): Fonts.__init__(self, default_font_prop, mathtext_backend) self.glyphd = {} self.fonts = {} - filename = fontManager.findfont(default_font_prop) + filename = findfont(default_font_prop) default_font = self.CachedFont(FT2Font(str(filename))) - + self.fonts['default'] = default_font - + def _get_font(self, font): """Looks up a CachedFont with its charmap and inverse charmap. font may be a TeX font name (cal, rm, it etc.), or postscript name.""" @@ -500,7 +500,7 @@ def _get_offset(self, cached_font, glyph, fontsize, dpi): return 0. - + def _get_info (self, fontname, sym, fontsize, dpi, mark_as_used=True): 'load the cmfont, metrics and glyph with caching' key = fontname, sym, fontsize, dpi @@ -567,7 +567,7 @@ font = info1.font return font.get_kerning(info1.num, info2.num, KERNING_DEFAULT) / 64.0 return 0.0 - + class BakomaFonts(TruetypeFonts): """ Use the Bakoma true type fonts for rendering @@ -581,7 +581,7 @@ 'ex' : 'cmex10' } fontmap = {} - + def __init__(self, *args, **kwargs): TruetypeFonts.__init__(self, *args, **kwargs) if not len(self.fontmap): @@ -589,14 +589,14 @@ 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 return 0. _slanted_symbols = Set(r"\int \oint".split()) - + 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] @@ -664,19 +664,19 @@ ('\leftbracket', '['), ('\rightbracket', ']')]: _size_alternatives[alias] = _size_alternatives[target] - + def get_sized_alternatives_for_symbol(self, fontname, sym): alternatives = self._size_alternatives.get(sym) if alternatives: return alternatives return [(fontname, sym)] - + class UnicodeFonts(TruetypeFonts): """An abstract base class for handling Unicode fonts. """ fontmap = {} - + def __init__(self, *args, **kwargs): # This must come first so the backend's owner is set correctly if rcParams['mathtext.fallback_to_cm']: @@ -689,15 +689,15 @@ setting = rcParams['mathtext.' + texfont] family, weight, style = setting prop = FontProperties(family=family, weight=weight, style=style) - font = fontManager.findfont(prop) + font = findfont(prop) self.fontmap[texfont] = font - + def _get_offset(self, cached_font, glyph, fontsize, dpi): return 0. def _get_glyph(self, fontname, sym, fontsize): found_symbol = False - + try: uniindex = get_unicode_index(sym) found_symbol = True @@ -743,7 +743,7 @@ 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 @@ -752,7 +752,7 @@ 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: @@ -766,7 +766,7 @@ 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 @@ -778,7 +778,7 @@ fontmap = { 'cal' : 'pzcmi8a', # Zapf Chancery 'rm' : 'pncr8a', # New Century Schoolbook - 'tt' : 'pcrr8a', # Courier + 'tt' : 'pcrr8a', # Courier 'it' : 'pncri8a', # New Century Schoolbook Italic 'sf' : 'phvr8a', # Helvetica 'bf' : 'pncb8a', # New Century Schoolbook Bold @@ -790,13 +790,13 @@ self.glyphd = {} self.fonts = {} - filename = fontManager.findfont(default_font_prop, fontext='afm') + filename = findfont(default_font_prop, fontext='afm') default_font = AFM(file(filename, 'r')) default_font.fname = filename - + self.fonts['default'] = default_font self.pswriter = StringIO() - + def _get_font(self, font): if font in self.fontmap: basename = self.fontmap[font] @@ -814,7 +814,7 @@ def get_fonts(self): return list(set(self.fonts.values())) - + def _get_info (self, fontname, sym, fontsize, dpi): 'load the cmfont, metrics and glyph with caching' key = fontname, sym, fontsize, dpi @@ -831,7 +831,7 @@ fontname = 'rm' found_symbol = False - + if latex_to_standard.has_key(sym): fontname, num = latex_to_standard[sym] glyph = chr(num) @@ -845,7 +845,7 @@ MathTextWarning) slanted = (fontname == 'it') - font = self._get_font(fontname) + font = self._get_font(fontname) if found_symbol: try: @@ -860,7 +860,7 @@ glyph = sym = '?' num = ord(glyph) symbol_name = font.get_name_char(glyph) - + offset = 0 scale = 0.001 * fontsize @@ -890,7 +890,7 @@ glyph = glyph, offset = offset ) - + return self.glyphd[key] def get_kern(self, font1, sym1, fontsize1, @@ -910,7 +910,7 @@ def get_underline_thickness(self, font, fontsize, dpi): cached_font = self._get_font(font) return cached_font.get_underline_thickness() * 0.001 * fontsize - + ############################################################################## # TeX-LIKE BOX MODEL @@ -951,17 +951,17 @@ SUB1 = 0.0 # Percentage of x-height that superscripts are offset relative to the subscript DELTA = 0.18 - + class MathTextWarning(Warning): pass - + class Node(object): """A node in the TeX box model @133 """ def __init__(self): self.size = 0 - + def __repr__(self): return self.__internal_repr__() @@ -980,7 +980,7 @@ """Grows one level larger. There is no limit to how big something can get.""" self.size -= 1 - + def render(self, x, y): pass @@ -1005,7 +1005,7 @@ self.width *= GROW_FACTOR self.height *= GROW_FACTOR self.depth *= GROW_FACTOR - + def render(self, x1, y1, x2, y2): pass @@ -1016,7 +1016,7 @@ class Hbox(Box): def __init__(self, width): Box.__init__(self, width, 0., 0.) - + class Char(Node): """Represents a single character. Unlike TeX, the font information and metrics are stored with each Char to make it @@ -1038,7 +1038,7 @@ # The real width, height and depth will be set during the # pack phase, after we know the real fontsize self._update_metrics() - + def __internal_repr__(self): return '`%s`' % self.c @@ -1054,7 +1054,7 @@ def is_slanted(self): return self._metrics.slanted - + def get_kerning(self, next): """Return the amount of kerning between this and the given character. Called when characters are strung together into @@ -1067,7 +1067,7 @@ next.font, next.c, next.fontsize, self.dpi) return advance + kern - + def render(self, x, y): """Render the character to the canvas""" self.font_output.render_glyph( @@ -1088,7 +1088,7 @@ self.width *= GROW_FACTOR self.height *= GROW_FACTOR self.depth *= GROW_FACTOR - + class Accent(Char): """The font metrics need to be dealt with differently for accents, since they are already offset correctly from the baseline in TrueType fonts.""" @@ -1102,17 +1102,17 @@ def shrink(self): Char.shrink(self) self._update_metrics() - + def grow(self): Char.grow(self) self._update_metrics() - + def render(self, x, y): """Render the character to the canvas""" self.font_output.render_glyph( x - self._metrics.xmin, y + self._metrics.ymin, self.font, self.c, self.fontsize, self.dpi) - + class List(Box): """A list of nodes (either horizontal or vertical). @135""" @@ -1170,7 +1170,7 @@ Box.grow(self) self.shift_amount *= GROW_FACTOR self.glue_set *= GROW_FACTOR - + class Hlist(List): """A horizontal list of boxes. @135""" @@ -1260,7 +1260,7 @@ self._set_glue(x, 1, total_stretch, "Overfull") else: self._set_glue(x, -1, total_shrink, "Underfull") - + class Vlist(List): """A vertical list of boxes. @137""" @@ -1308,7 +1308,7 @@ d = 0. elif isinstance(p, Char): raise RuntimeError("Internal mathtext error: Char node found in Vlist.") - + self.width = w if d > l: x += d - l @@ -1331,7 +1331,7 @@ self._set_glue(x, 1, total_stretch, "Overfull") else: self._set_glue(x, -1, total_shrink, "Underfull") - + class Rule(Box): """A Rule node stands for a solid black rectangle; it has width, depth, and height fields just as in an Hlist. However, if any of these @@ -1343,10 +1343,10 @@ def __init__(self, width, height, depth, state): Box.__init__(self, width, height, depth) self.font_output = state.font_output - + def render(self, x, y, w, h): self.font_output.render_rect_filled(x, y, x + w, y + h) - + class Hrule(Rule): """Convenience class to create a horizontal rule.""" def __init__(self, state): @@ -1361,7 +1361,7 @@ thickness = state.font_output.get_underline_thickness( state.font, state.fontsize, state.dpi) Rule.__init__(self, thickness, inf, inf, state) - + class Glue(Node): """Most of the information in this object is stored in the underlying GlueSpec class, which is shared between multiple glue objects. (This @@ -1393,7 +1393,7 @@ if self.glue_spec.width != 0.: self.glue_spec = self.glue_spec.copy() self.glue_spec.width *= GROW_FACTOR - + class GlueSpec(object): """@150, @151""" def __init__(self, width=0., stretch=0., stretch_order=0, shrink=0., shrink_order=0): @@ -1410,11 +1410,11 @@ self.stretch_order, self.shrink, self.shrink_order) - + def factory(cls, glue_type): return cls._types[glue_type] factory = classmethod(factory) - + GlueSpec._types = { 'fil': GlueSpec(0., 1., 1, 0., 0), 'fill': GlueSpec(0., 1., 2, 0., 0), @@ -1451,24 +1451,24 @@ class NegFilll(Glue): def __init__(self): Glue.__init__(self, 'neg_filll') - + class SsGlue(Glue): def __init__(self): Glue.__init__(self, 'ss') - + class HCentered(Hlist): """A convenience class to create an Hlist whose contents are centered within its enclosing box.""" def __init__(self, elements): Hlist.__init__(self, [SsGlue()] + elements + [SsGlue()], do_kern=False) - + class VCentered(Hlist): """A convenience class to create an Vlist whose contents are centered within its enclosing box.""" def __init__(self, elements): Vlist.__init__(self, [SsGlue()] + elements + [SsGlue()]) - + class Kern(Node): """A Kern node has a width field to specify a (normally negative) amount of spacing. This spacing correction appears in horizontal lists @@ -1483,7 +1483,7 @@ def __repr__(self): return "k%.02f" % self.width - + def shrink(self): Node.shrink(self) if self.size < NUM_SIZE_LEVELS: @@ -1492,7 +1492,7 @@ def grow(self): Node.grow(self) self.width *= GROW_FACTOR - + class SubSuperCluster(Hlist): """This class is a sort of hack to get around that fact that this code doesn't parse to an mlist and then an hlist, but goes directly @@ -1526,7 +1526,7 @@ factor = target_total / (char.height + char.depth) state.fontsize *= factor char = Char(sym, state) - + shift = (depth - char.depth) Hlist.__init__(self, [char]) self.shift_amount = shift @@ -1551,9 +1551,9 @@ factor = width / char.width state.fontsize *= factor char = char_class(sym, state) - + Hlist.__init__(self, [char]) - + class Ship(object): """Once the boxes have been set up, this sends them to output. Since boxes can be inside of boxes inside of boxes, the main @@ -1578,7 +1578,7 @@ return 1000000000. return value clamp = staticmethod(clamp) - + def hlist_out(self, box): cur_g = 0 cur_glue = 0. @@ -1697,7 +1697,7 @@ elif isinstance(p, Char): raise RuntimeError("Internal mathtext error: Char node found in vlist") self.cur_s -= 1 - + ship = Ship() ############################################################################## @@ -1760,7 +1760,7 @@ ) _dropsub_symbols = Set(r'''\int \oint'''.split()) - + def __init__(self): # All forward declarations are here font = Forward().setParseAction(self.font).setName("font") @@ -1873,7 +1873,7 @@ ).setParseAction(self.sqrt).setName("sqrt") placeable <<(accent - ^ function + ^ function ^ symbol ^ rightBracket ^ group @@ -1888,7 +1888,7 @@ subsuperop =(Literal("_") | Literal("^") - ) + ) subsuper << Group( ( Optional(placeable) @@ -1911,9 +1911,9 @@ autoDelim ^ OneOrMore(simple)) + Suppress(Literal(r"\right")) - + (rightDelim | ambiDelim) + + (rightDelim | ambiDelim) ) - + math = OneOrMore( autoDelim | simple @@ -1941,7 +1941,7 @@ self._expr = None self._state_stack = None self._em_width_cache = {} - + def parse(self, s, fonts_object, fontsize, dpi): self._state_stack = [self.State(fonts_object, 'default', fontsize, dpi)] self._expression.parseString(s) @@ -1964,7 +1964,7 @@ self.font, self.fontsize, self.dpi) - + def get_state(self): return self._state_stack[-1] @@ -1973,11 +1973,11 @@ def push_state(self): self._state_stack.append(self.get_state().copy()) - + def finish(self, s, loc, toks): self._expr = Hlist(toks) return [self._expr] - + def math(self, s, loc, toks): #~ print "math", toks hlist = Hlist(toks) @@ -2056,7 +2056,7 @@ } _wide_accents = Set(r"\widehat \widetilde".split()) - + def accent(self, s, loc, toks): assert(len(toks)==1) state = self.get_state() @@ -2087,14 +2087,14 @@ self.pop_state() hlist.function_name = toks[0] return hlist - + def start_group(self, s, loc, toks): self.push_state() # Deal with LaTeX-style font tokens if len(toks): self.get_state().font = toks[0][4:] return [] - + def group(self, s, loc, toks): grp = Hlist(toks[0]) return [grp] @@ -2102,7 +2102,7 @@ def end_group(self, s, loc, toks): self.pop_state() return [] - + def font(self, s, loc, toks): assert(len(toks)==1) name = toks[0] @@ -2125,7 +2125,7 @@ if isinstance(nucleus, Char): return nucleus.is_slanted() return False - + def subsuperscript(self, s, loc, toks): assert(len(toks)==1) # print 'subsuperscript', toks @@ -2133,7 +2133,7 @@ nucleus = None sub = None super = None - + if len(toks[0]) == 1: return toks[0].asList() elif len(toks[0]) == 2: @@ -2164,13 +2164,13 @@ sub = next2 else: raise ParseFatalException("Subscript/superscript sequence is too long.") - + state = self.get_state() rule_thickness = state.font_output.get_underline_thickness( state.font, state.fontsize, state.dpi) xHeight = state.font_output.get_xheight( state.font, state.fontsize, state.dpi) - + if self.is_overunder(nucleus): vlist = [] shift = 0. @@ -2181,7 +2181,7 @@ if sub is not None: sub.shrink() width = max(width, sub.width) - + if super is not None: hlist = HCentered([super]) hlist.hpack(width, 'exactly') @@ -2248,7 +2248,7 @@ state = self.get_state() thickness = state.font_output.get_underline_thickness( state.font, state.fontsize, state.dpi) - + num, den = toks[0] num.shrink() den.shrink() @@ -2316,14 +2316,14 @@ # The value of 0.6 is a hard-coded hack ;) root_vlist = Vlist([Hlist([root])]) root_vlist.shift_amount = -height * 0.6 - + hlist = Hlist([root_vlist, # Root # Negative kerning to put root over tick - Kern(-check.width * 0.5), + Kern(-check.width * 0.5), check, # Check rightside]) # Body return [hlist] - + def auto_sized_delimiter(self, s, loc, toks): #~ print "auto_sized_delimiter", toks front, middle, back = toks @@ -2339,12 +2339,12 @@ parts.append(AutoHeightChar(back, height, depth, state)) hlist = Hlist(parts) return hlist - + #### ############################################################################## # MAIN - + class math_parse_s_ft2font_common: """ Parse the math expression s, return the (bbox, fonts) tuple needed @@ -2367,7 +2367,7 @@ 'SVG' : MathtextBackendSvg, 'Cairo' : MathtextBackendCairo } - + def __init__(self, output): self.output = output self.cache = {} @@ -2404,7 +2404,7 @@ font_output.mathtext_backend.fonts_object = None return result - + math_parse_s_ft2font = math_parse_s_ft2font_common('Agg') math_parse_s_ft2font_svg = math_parse_s_ft2font_common('SVG') math_parse_s_ps = math_parse_s_ft2font_common('PS') This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |