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.
-------------------------------------------------------------------------
SF.Net email is sponsored by: The Future of Linux Business White Paper
from Novell. From the desktop to the data center, Linux is going
mainstream. Let it simplify your IT future.
http://altfarm.mediaplex.com/ad/ck/8857-50307-18918-4
_______________________________________________
Matplotlib-checkins mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/matplotlib-checkins