From: <md...@us...> - 2007-12-05 20:28:32
|
Revision: 4633 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4633&view=rev Author: mdboom Date: 2007-12-05 12:28:28 -0800 (Wed, 05 Dec 2007) Log Message: ----------- Fix bug where font files were opened many more times than they need to be. Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/backends/backend_agg.py trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py trunk/matplotlib/lib/matplotlib/backends/backend_ps.py trunk/matplotlib/lib/matplotlib/backends/backend_svg.py trunk/matplotlib/lib/matplotlib/font_manager.py Modified: trunk/matplotlib/lib/matplotlib/backends/backend_agg.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_agg.py 2007-12-05 19:36:36 UTC (rev 4632) +++ trunk/matplotlib/lib/matplotlib/backends/backend_agg.py 2007-12-05 20:28:28 UTC (rev 4633) @@ -80,7 +80,8 @@ from matplotlib._pylab_helpers import Gcf from matplotlib.backend_bases import RendererBase,\ GraphicsContextBase, FigureManagerBase, FigureCanvasBase -from matplotlib.cbook import enumerate, is_string_like, exception_to_str +from matplotlib.cbook import enumerate, is_string_like, exception_to_str, \ + maxdict from matplotlib.figure import Figure from matplotlib.font_manager import findfont from matplotlib.ft2font import FT2Font, LOAD_FORCE_AUTOHINT @@ -98,7 +99,8 @@ """ debug=1 - texd = {} # a cache of tex image rasters + texd = maxdict(50) # a cache of tex image rasters + _fontd = maxdict(50) def __init__(self, width, height, dpi): if __debug__: verbose.report('RendererAgg.__init__', 'debug-annoying') RendererBase.__init__(self) @@ -125,7 +127,6 @@ self.copy_from_bbox = self._renderer.copy_from_bbox self.restore_region = self._renderer.restore_region self.mathtext_parser = MathTextParser('Agg') - self._fontd = {} self.bbox = lbwh_to_bbox(0,0, self.width, self.height) if __debug__: verbose.report('RendererAgg.__init__ done', @@ -272,7 +273,10 @@ if font is None: fname = findfont(prop) - font = FT2Font(str(fname)) + font = self._fontd.get(fname) + if font is None: + font = FT2Font(str(fname)) + self._fontd[fname] = font self._fontd[key] = font font.clear() Modified: trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py 2007-12-05 19:36:36 UTC (rev 4632) +++ trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py 2007-12-05 20:28:28 UTC (rev 4633) @@ -25,7 +25,7 @@ from matplotlib.backend_bases import RendererBase, GraphicsContextBase,\ FigureManagerBase, FigureCanvasBase from matplotlib.cbook import Bunch, enumerate, is_string_like, reverse_dict, \ - get_realpath_and_stat, is_writable_file_like + get_realpath_and_stat, is_writable_file_like, maxdict from matplotlib.figure import Figure from matplotlib.font_manager import findfont, is_opentype_cff_font from matplotlib.afm import AFM @@ -1147,13 +1147,13 @@ self.write("\nstartxref\n%d\n%%%%EOF\n" % self.startxref) class RendererPdf(RendererBase): + truetype_font_cache = maxdict(50) + afm_font_cache = maxdict(50) def __init__(self, file, dpi): RendererBase.__init__(self) self.file = file self.gc = self.new_gc() - self.truetype_font_cache = {} - self.afm_font_cache = {} self.file.used_characters = self.used_characters = {} self.mathtext_parser = MathTextParser("Pdf") self.image_magnification = dpi/72.0 @@ -1161,8 +1161,6 @@ def finalize(self): self.gc.finalize() - del self.truetype_font_cache - del self.afm_font_cache def check_gc(self, gc, fillcolor=None): orig_fill = gc._fillcolor @@ -1679,9 +1677,12 @@ font = self.afm_font_cache.get(key) if font is None: filename = findfont(prop, fontext='afm') - fh = file(filename) - font = AFM(fh) - fh.close() + font = self.afm_font_cache.get(filename) + if font is None: + fh = file(filename) + font = AFM(fh) + self.afm_font_cache[filename] = font + fh.close() self.afm_font_cache[key] = font return font @@ -1690,7 +1691,10 @@ font = self.truetype_font_cache.get(key) if font is None: filename = findfont(prop) - font = FT2Font(str(filename)) + font = self.truetype_font_cache.get(filename) + if font is None: + font = FT2Font(str(filename)) + self.truetype_font_cache[filename] = font self.truetype_font_cache[key] = font font.clear() font.set_size(prop.get_size_in_points(), 72.0) Modified: trunk/matplotlib/lib/matplotlib/backends/backend_ps.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_ps.py 2007-12-05 19:36:36 UTC (rev 4632) +++ trunk/matplotlib/lib/matplotlib/backends/backend_ps.py 2007-12-05 20:28:28 UTC (rev 4633) @@ -16,7 +16,7 @@ FigureManagerBase, FigureCanvasBase from matplotlib.cbook import is_string_like, izip, get_realpath_and_stat, \ - is_writable_file_like + is_writable_file_like, maxdict from matplotlib.figure import Figure from matplotlib.font_manager import findfont, is_opentype_cff_font @@ -123,6 +123,9 @@ context instance that controls the colors/styles. """ + fontd = maxdict(50) + afmfontd = maxdict(50) + def __init__(self, width, height, pswriter, dpi=72): RendererBase.__init__(self) self.width = width @@ -143,8 +146,6 @@ self.hatch = None self.image_magnification = dpi/72.0 - self.fontd = {} - self.afmfontd = {} self.used_characters = {} self.mathtext_parser = MathTextParser("PS") @@ -315,7 +316,11 @@ key = hash(prop) font = self.afmfontd.get(key) if font is None: - font = AFM(file(findfont(prop, fontext='afm'))) + fname = findfont(prop, fontext='afm') + font = self.afmfontd.get(fname) + if font is None: + font = AFM(file(findfont(prop, fontext='afm'))) + self.afmfontd[fname] = font self.afmfontd[key] = font return font @@ -324,13 +329,16 @@ font = self.fontd.get(key) if font is None: fname = findfont(prop) - font = FT2Font(str(fname)) + font = self.fontd.get(fname) + if font is None: + font = FT2Font(str(fname)) + self.fontd[fname] = font self.fontd[key] = font font.clear() size = prop.get_size_in_points() font.set_size(size, 72.0) return font - + def draw_arc(self, gc, rgbFace, x, y, width, height, angle1, angle2, rotation): """ Draw an arc centered at x,y with width and height and angles @@ -524,12 +532,12 @@ ps_cmd = [] ps_cmd.append('newpath') - + while 1: code, xp, yp = path.vertex() #print code, xp, yp - + if code == agg.path_cmd_stop: ps_cmd.append('closepath') # Hack, path_cmd_end_poly not found break @@ -742,7 +750,7 @@ elif isinstance(s, unicode): return self.draw_unicode(gc, x, y, s, prop, angle) - + elif rcParams['ps.useafm']: font = self._get_font_afm(prop) @@ -826,7 +834,7 @@ kern = 0 last_name = name thisx += kern * scale - + lines.append('%f %f m /%s glyphshow'%(thisx, thisy, name)) thisx += width * scale @@ -843,7 +851,7 @@ grestore """ % locals() self._pswriter.write(ps) - + else: font = self._get_font_ttf(prop) @@ -949,7 +957,7 @@ write("stroke\n") else: write("newpath\n") - + if cliprect: write("grestore\n") @@ -999,16 +1007,16 @@ filetypes = {'ps' : 'Postscript', 'eps' : 'Encapsulated Postscript'} - + def get_default_filetype(self): return 'ps' - + def print_ps(self, outfile, *args, **kwargs): return self._print_ps(outfile, 'ps', *args, **kwargs) def print_eps(self, outfile, *args, **kwargs): return self._print_ps(outfile, 'eps', *args, **kwargs) - + def _print_ps(self, outfile, format, *args, **kwargs): papertype = kwargs.get("papertype", rcParams['ps.papersize']) papertype = papertype.lower() @@ -1017,7 +1025,7 @@ elif papertype not in papersize: raise RuntimeError( '%s is not a valid papertype. Use one \ of %s'% (papertype, ', '.join( papersize.keys() )) ) - + orientation = kwargs.get("orientation", "portrait").lower() if orientation == 'landscape': isLandscape = True elif orientation == 'portrait': isLandscape = False @@ -1027,14 +1035,14 @@ dpi = kwargs.get("dpi", 72) facecolor = kwargs.get("facecolor", "w") edgecolor = kwargs.get("edgecolor", "w") - + if rcParams['text.usetex']: self._print_figure_tex(outfile, format, dpi, facecolor, edgecolor, orientation, isLandscape, papertype) else: self._print_figure(outfile, format, dpi, facecolor, edgecolor, orientation, isLandscape, papertype) - + def _print_figure(self, outfile, format, dpi=72, facecolor='w', edgecolor='w', orientation='portrait', isLandscape=False, papertype=None): """ @@ -1643,5 +1651,5 @@ -0.552284749831 -1.0 -1.0 -0.552284749831 -1.0 0.0 curveto closepath } bind def""", - + ] Modified: trunk/matplotlib/lib/matplotlib/backends/backend_svg.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_svg.py 2007-12-05 19:36:36 UTC (rev 4632) +++ trunk/matplotlib/lib/matplotlib/backends/backend_svg.py 2007-12-05 20:28:28 UTC (rev 4633) @@ -5,7 +5,7 @@ from matplotlib import verbose, __version__, rcParams from matplotlib.backend_bases import RendererBase, GraphicsContextBase,\ FigureManagerBase, FigureCanvasBase -from matplotlib.cbook import is_string_like, is_writable_file_like +from matplotlib.cbook import is_string_like, is_writable_file_like, maxdict from matplotlib.colors import rgb2hex from matplotlib.figure import Figure from matplotlib.font_manager import findfont, FontProperties @@ -27,6 +27,7 @@ _capstyle_d = {'projecting' : 'square', 'butt' : 'butt', 'round': 'round',} class RendererSVG(RendererBase): FONT_SCALE = 100.0 + fontd = maxdict(50) def __init__(self, width, height, svgwriter, basename=None): self.width=width @@ -41,7 +42,6 @@ self._clipd = {} self._char_defs = {} self.mathtext_parser = MathTextParser('SVG') - self.fontd = {} svgwriter.write(svgProlog%(width,height,width,height)) def _draw_svg_element(self, element, details, gc, rgbFace): @@ -60,7 +60,10 @@ font = self.fontd.get(key) if font is None: fname = findfont(prop) - font = FT2Font(str(fname)) + font = self.fontd.get(fname) + if font is None: + font = FT2Font(str(fname)) + self.fontd[fname] = font self.fontd[key] = font font.clear() size = prop.get_size_in_points() @@ -245,7 +248,7 @@ font = self._get_font(prop) font.set_text(s, 0.0, flags=LOAD_NO_HINTING) y -= font.get_descent() / 64.0 - + fontsize = prop.get_size_in_points() color = rgb2hex(gc.get_rgb()) @@ -386,7 +389,7 @@ for font, fontsize, thetext, new_x, new_y_mtc, metrics in svg_glyphs: new_y = - new_y_mtc style = "font-size: %f; font-family: %s" % (fontsize, font.family_name) - + svg.append('<tspan style="%s"' % style) xadvance = metrics.advance svg.append(' textLength="%s"' % xadvance) @@ -468,7 +471,7 @@ else: raise ValueError("filename must be a path or a file-like object") return self._print_svg(filename, svgwriter, fh_to_close) - + def print_svgz(self, filename, *args, **kwargs): if is_string_like(filename): gzipwriter = gzip.GzipFile(filename, 'w') @@ -479,7 +482,7 @@ else: raise ValueError("filename must be a path or a file-like object") return self._print_svg(filename, svgwriter, fh_to_close) - + def _print_svg(self, filename, svgwriter, fh_to_close=None): self.figure.dpi.set(72) width, height = self.figure.get_size_inches() @@ -490,10 +493,10 @@ renderer.finish() if fh_to_close is not None: svgwriter.close() - + def get_default_filetype(self): return 'svg' - + class FigureManagerSVG(FigureManagerBase): pass Modified: trunk/matplotlib/lib/matplotlib/font_manager.py =================================================================== --- trunk/matplotlib/lib/matplotlib/font_manager.py 2007-12-05 19:36:36 UTC (rev 4632) +++ trunk/matplotlib/lib/matplotlib/font_manager.py 2007-12-05 20:28:28 UTC (rev 4633) @@ -36,7 +36,7 @@ import os, sys, glob, shutil from sets import Set import matplotlib -from matplotlib import afm +from matplotlib import afm from matplotlib import ft2font from matplotlib import rcParams, get_home, get_configdir from matplotlib.cbook import is_string_like @@ -49,7 +49,7 @@ import pickle USE_FONTCONFIG = False - + verbose = matplotlib.verbose font_scalings = {'xx-small': 0.579, 'x-small': 0.694, 'small': 0.833, @@ -98,7 +98,7 @@ def get_fontext_synonyms(fontext): return {'ttf': ('ttf', 'otf'), 'afm': ('afm',)}[fontext] - + def win32FontDirectory(): """Return the user-specified font directory for Win32.""" @@ -126,7 +126,7 @@ directory = win32FontDirectory() fontext = get_fontext_synonyms(fontext) - + key, items = None, {} for fontdir in MSFontDirectories: try: @@ -178,7 +178,7 @@ directory = OSXFontDirectory() fontext = get_fontext_synonyms(fontext) - + files = [] for path in directory: if fontext is None: @@ -214,7 +214,7 @@ return {} fontext = get_fontext_synonyms(fontext) - + fontfiles = {} status, output = commands.getstatusoutput("fc-list file") if status == 0: @@ -236,7 +236,7 @@ """ fontfiles = {} fontexts = get_fontext_synonyms(fontext) - + if fontpaths is None: if sys.platform == 'win32': fontdir = win32FontDirectory() @@ -635,7 +635,7 @@ stretch = [rcParams['font.stretch']] size = [rcParams['font.size']] file = None - + def __init__(self, family = None, style = None, @@ -653,7 +653,7 @@ if _init is not None: self.__props.__dict__.update(_init) return - + if is_string_like(family): # Treat family as a fontconfig pattern if it is the only # parameter provided. @@ -674,16 +674,16 @@ self.set_stretch(stretch) self.set_file(fname) self.set_size(size) - + def _parse_fontconfig_pattern(self, pattern): return parse_fontconfig_pattern(pattern) def __hash__(self): - return hash(repr(self.__props)) + return hash(repr(self.__props.__dict__)) def __str__(self): return self.get_fontconfig_pattern() - + def get_family(self): """Return a list of font names that comprise the font family. """ @@ -727,7 +727,7 @@ def get_fontconfig_pattern(self): return generate_fontconfig_pattern(self.__props.__dict__) - + def set_family(self, family): """ Change the font family. May be either an alias (generic name @@ -741,7 +741,7 @@ family = [family] self.__props.family = family set_name = set_family - + def set_style(self, style): """Set the font style. Values are: normal, italic or oblique.""" if style is None: @@ -812,7 +812,7 @@ def add_property_pair(self, key, val): self.__props.setdefault(key, []).append(val) - + def copy(self): """Return a deep copy of self""" return FontProperties(_init = self.__props.__dict__) @@ -862,7 +862,7 @@ def __init__(self, size=None, weight='normal'): self.__default_weight = weight self.default_size = size - + paths = [os.path.join(rcParams['datapath'],'fonts','ttf'), os.path.join(rcParams['datapath'],'fonts','afm')] @@ -1076,8 +1076,8 @@ _is_opentype_cff_font_cache[filename] = result return result return False - - + + if USE_FONTCONFIG and sys.platform != 'win32': import re @@ -1095,7 +1095,7 @@ _fc_match_regex = re.compile(r'\sfile:\s+"([^"]*)"') _fc_match_cache = {} - + def findfont(prop, fontext='ttf'): if not is_string_like(prop): prop = prop.get_fontconfig_pattern() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |