From: <md...@us...> - 2009-11-12 20:53:44
|
Revision: 7956 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7956&view=rev Author: mdboom Date: 2009-11-12 20:53:36 +0000 (Thu, 12 Nov 2009) Log Message: ----------- Fix a number of font manager issues: 1) AFM fonts now store stretch information in the FontManager database 2) pdf.use14corefonts and ps.useafm will now only use the afm files for their respective formats 3) The fontList.cache file is now versioned -- if the version doesn't match the current version of matplotlib it is thrown away and regenerated Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py trunk/matplotlib/lib/matplotlib/backends/backend_ps.py trunk/matplotlib/lib/matplotlib/font_manager.py trunk/matplotlib/lib/matplotlib/mathtext.py Modified: trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py 2009-11-12 17:57:13 UTC (rev 7955) +++ trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py 2009-11-12 20:53:36 UTC (rev 7956) @@ -363,6 +363,8 @@ else: raise ValueError("filename must be a path or a file-like object") + self._core14fontdir = os.path.join( + rcParams['datapath'], 'fonts', 'pdfcorefonts') self.fh = fh self.currentstream = None # stream object to write to, if any fh.write("%PDF-1.4\n") # 1.4 is the first version to have alpha @@ -507,7 +509,11 @@ if is_string_like(fontprop): filename = fontprop elif rcParams['pdf.use14corefonts']: - filename = findfont(fontprop, fontext='afm') + filename = findfont( + fontprop, fontext='afm', directory=self._core14fontdir) + if filename is None: + filename = findfont( + "Helvetica", fontext='afm', directory=self._core14fontdir) else: filename = findfont(fontprop) @@ -1743,7 +1749,12 @@ key = hash(prop) font = self.afm_font_cache.get(key) if font is None: - filename = findfont(prop, fontext='afm') + filename = findfont( + prop, fontext='afm', directory=self.file._core14fontdir) + if filename is None: + filename = findfont( + "Helvetica", fontext='afm', + directory=self.file._core14fontdir) font = self.afm_font_cache.get(filename) if font is None: fh = file(filename) Modified: trunk/matplotlib/lib/matplotlib/backends/backend_ps.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_ps.py 2009-11-12 17:57:13 UTC (rev 7955) +++ trunk/matplotlib/lib/matplotlib/backends/backend_ps.py 2009-11-12 20:53:36 UTC (rev 7956) @@ -170,6 +170,9 @@ self.used_characters = {} self.mathtext_parser = MathTextParser("PS") + self._afm_font_dir = os.path.join( + rcParams['datapath'], 'fonts', 'afm') + def track_characters(self, font, s): """Keeps track of which characters are required from each font.""" @@ -312,10 +315,13 @@ key = hash(prop) font = self.afmfontd.get(key) if font is None: - fname = findfont(prop, fontext='afm') + fname = findfont(prop, fontext='afm', directory=self._afm_font_dir) + if fname is None: + fname = findfont( + "Helvetica", fontext='afm', directory=self._afm_font_dir) font = self.afmfontd.get(fname) if font is None: - font = AFM(file(findfont(prop, fontext='afm'))) + font = AFM(file(fname)) self.afmfontd[fname] = font self.afmfontd[key] = font return font Modified: trunk/matplotlib/lib/matplotlib/font_manager.py =================================================================== --- trunk/matplotlib/lib/matplotlib/font_manager.py 2009-11-12 17:57:13 UTC (rev 7955) +++ trunk/matplotlib/lib/matplotlib/font_manager.py 2009-11-12 20:53:36 UTC (rev 7956) @@ -301,7 +301,7 @@ except OSError: # Calling fc-list did not work, so we'll just return nothing return fontfiles - + if pipe.returncode == 0: for line in output.split('\n'): fname = line.split(':')[0] @@ -463,8 +463,7 @@ # Relative stretches are: wider, narrower # Child value is: inherit - # !!!! Incomplete - if sfnt4.find('narrow') >= 0 or sfnt4.find('condensed') >= 0 or \ + if sfnt4.find('narrow') >= 0 or sfnt4.find('condensed') >= 0 or \ sfnt4.find('cond') >= 0: stretch = 'condensed' elif sfnt4.find('demi cond') >= 0: @@ -502,6 +501,7 @@ """ name = font.get_familyname() + fontname = font.get_fontname().lower() # Styles are: italic, oblique, and normal (default) @@ -532,10 +532,16 @@ # and ultra-expanded. # Relative stretches are: wider, narrower # Child value is: inherit + if fontname.find('narrow') >= 0 or fontname.find('condensed') >= 0 or \ + fontname.find('cond') >= 0: + stretch = 'condensed' + elif fontname.find('demi cond') >= 0: + stretch = 'semi-condensed' + elif fontname.find('wide') >= 0 or fontname.find('expanded') >= 0: + stretch = 'expanded' + else: + stretch = 'normal' - # !!!! Incomplete - stretch = 'normal' - # Sizes can be absolute and relative. # Absolute sizes are: xx-small, x-small, small, medium, large, x-large, # and xx-large. @@ -960,12 +966,20 @@ matches the specification. If no good enough match is found, a default font is returned. """ + # Increment this version number whenever the font cache data + # format or behavior has changed and requires a existing font + # cache files to be rebuilt. + __version__ = 5 + def __init__(self, size=None, weight='normal'): + self._version = self.__version__ + self.__default_weight = weight self.default_size = size paths = [os.path.join(rcParams['datapath'], 'fonts', 'ttf'), - os.path.join(rcParams['datapath'], 'fonts', 'afm')] + os.path.join(rcParams['datapath'], 'fonts', 'afm'), + os.path.join(rcParams['datapath'], 'fonts', 'pdfcorefonts')] # Create list of font paths for pathname in ['TTFPATH', 'AFMPATH']: @@ -982,32 +996,23 @@ # Load TrueType fonts and create font dictionary. self.ttffiles = findSystemFonts(paths) + findSystemFonts() + self.defaultFont = {} for fname in self.ttffiles: verbose.report('trying fontname %s' % fname, 'debug') if fname.lower().find('vera.ttf')>=0: - self.defaultFont = fname + self.defaultFont['ttf'] = fname break else: # use anything - self.defaultFont = self.ttffiles[0] + self.defaultFont['ttf'] = self.ttffiles[0] self.ttflist = createFontList(self.ttffiles) - 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.afmlist = createFontList(afmfiles, fontext='afm') - else: - self.afmfiles = findSystemFonts(paths, fontext='afm') + \ - findSystemFonts(fontext='afm') - self.afmlist = createFontList(self.afmfiles, fontext='afm') + self.afmfiles = findSystemFonts(paths, fontext='afm') + \ + findSystemFonts(fontext='afm') + self.afmlist = createFontList(self.afmfiles, fontext='afm') + self.defaultFont['afm'] = None self.ttf_lookup_cache = {} self.afm_lookup_cache = {} @@ -1151,7 +1156,7 @@ return 1.0 return abs(sizeval1 - sizeval2) / 72.0 - def findfont(self, prop, fontext='ttf'): + def findfont(self, prop, fontext='ttf', directory=None): """ Search the font list for the font that most closely matches the :class:`FontProperties` *prop*. @@ -1162,6 +1167,9 @@ returned. If no matches below a certain threshold are found, the default font (usually Vera Sans) is returned. + `directory`, is specified, will only return fonts from the + given directory (or subdirectory of that directory). + The result is cached, so subsequent lookups don't have to perform the O(n) nearest neighbor search. @@ -1194,6 +1202,10 @@ best_font = None for font in fontlist: + if (directory is not None and + os.path.commonprefix([font.fname, directory]) != directory): + print directory, font.fname, os.path.commonprefix([font.fname, directory]) + continue # Matching family should have highest priority, so it is multiplied # by 10.0 score = \ @@ -1211,8 +1223,8 @@ if best_font is None or best_score >= 10.0: verbose.report('findfont: Could not match %s. Returning %s' % - (prop, self.defaultFont)) - result = self.defaultFont + (prop, self.defaultFont[fontext])) + result = self.defaultFont[fontext] else: verbose.report('findfont: Matching %s to %s (%s) with score of %f' % (prop, best_font.name, best_font.fname, best_score)) @@ -1289,16 +1301,16 @@ try: fontManager = pickle_load(_fmcache) - fontManager.default_size = None - verbose.report("Using fontManager instance from %s" % _fmcache) + if (not hasattr(fontManager, '_version') or + fontManager._version != FontManager.__version__): + _rebuild() + else: + fontManager.default_size = None + 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 2009-11-12 17:57:13 UTC (rev 7955) +++ trunk/matplotlib/lib/matplotlib/mathtext.py 2009-11-12 20:53:36 UTC (rev 7956) @@ -1032,7 +1032,11 @@ self.glyphd = {} self.fonts = {} - filename = findfont(default_font_prop, fontext='afm') + filename = findfont(default_font_prop, fontext='afm', + directory=self.basepath) + if filename is None: + filename = findfont('Helvetica', fontext='afm', + directory=self.basepath) default_font = AFM(file(filename, 'r')) default_font.fname = filename This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |