11from collections import OrderedDict
2+ import functools
23import urllib .parse
34import warnings
45
56import numpy as np
67
7- from matplotlib .path import Path
8- from matplotlib import rcParams
9- import matplotlib .font_manager as font_manager
10- from matplotlib .ft2font import KERNING_DEFAULT , LOAD_NO_HINTING
11- from matplotlib .ft2font import LOAD_TARGET_LIGHT
12- from matplotlib .mathtext import MathTextParser
13- import matplotlib .dviread as dviread
8+ from matplotlib import cbook , dviread , font_manager , rcParams
149from matplotlib .font_manager import FontProperties , get_font
10+ from matplotlib .ft2font import (
11+ KERNING_DEFAULT , LOAD_NO_HINTING , LOAD_TARGET_LIGHT )
12+ from matplotlib .mathtext import MathTextParser
13+ from matplotlib .path import Path
1514from matplotlib .transforms import Affine2D
1615
1716
17+ @functools .lru_cache (1 )
18+ def _get_adobe_standard_encoding ():
19+ enc_name = dviread .find_tex_file ('8a.enc' )
20+ enc = dviread .Encoding (enc_name )
21+ return {c : i for i , c in enumerate (enc .encoding )}
22+
23+
1824class TextToPath (object ):
1925 """
2026 A class that convert a given text to a path using ttf fonts.
@@ -25,19 +31,12 @@ class TextToPath(object):
2531
2632 def __init__ (self ):
2733 self .mathtext_parser = MathTextParser ('path' )
28- self .tex_font_map = None
29-
30- from matplotlib .cbook import maxdict
31- self ._ps_fontd = maxdict (50 )
32-
3334 self ._texmanager = None
3435
35- self ._adobe_standard_encoding = None
36-
37- def _get_adobe_standard_encoding (self ):
38- enc_name = dviread .find_tex_file ('8a.enc' )
39- enc = dviread .Encoding (enc_name )
40- return {c : i for i , c in enumerate (enc .encoding )}
36+ @property
37+ @cbook .deprecated ("3.0" )
38+ def tex_font_map (self ):
39+ return dviread .PsfontsMap (dviread .find_tex_file ('pdftex.map' ))
4140
4241 def _get_font (self , prop ):
4342 """
@@ -281,13 +280,6 @@ def get_glyphs_tex(self, prop, s, glyph_map=None,
281280
282281 texmanager = self .get_texmanager ()
283282
284- if self .tex_font_map is None :
285- self .tex_font_map = dviread .PsfontsMap (
286- dviread .find_tex_file ('pdftex.map' ))
287-
288- if self ._adobe_standard_encoding is None :
289- self ._adobe_standard_encoding = self ._get_adobe_standard_encoding ()
290-
291283 fontsize = prop .get_size_in_points ()
292284 if hasattr (texmanager , "get_dvi" ):
293285 dvifilelike = texmanager .get_dvi (s , self .FONT_SCALE )
@@ -312,46 +304,7 @@ def get_glyphs_tex(self, prop, s, glyph_map=None,
312304 # characters into strings.
313305 # oldfont, seq = None, []
314306 for x1 , y1 , dvifont , glyph , width in page .text :
315- font_and_encoding = self ._ps_fontd .get (dvifont .texname )
316- font_bunch = self .tex_font_map [dvifont .texname ]
317-
318- if font_and_encoding is None :
319- if font_bunch .filename is None :
320- raise ValueError (
321- ("No usable font file found for %s (%s). "
322- "The font may lack a Type-1 version." )
323- % (font_bunch .psname , dvifont .texname ))
324-
325- font = get_font (font_bunch .filename )
326-
327- for charmap_name , charmap_code in [("ADOBE_CUSTOM" ,
328- 1094992451 ),
329- ("ADOBE_STANDARD" ,
330- 1094995778 )]:
331- try :
332- font .select_charmap (charmap_code )
333- except (ValueError , RuntimeError ):
334- pass
335- else :
336- break
337- else :
338- charmap_name = ""
339- warnings .warn ("No supported encoding in font (%s)." %
340- font_bunch .filename )
341-
342- if charmap_name == "ADOBE_STANDARD" and font_bunch .encoding :
343- enc0 = dviread .Encoding (font_bunch .encoding )
344- enc = {i : self ._adobe_standard_encoding .get (c , None )
345- for i , c in enumerate (enc0 .encoding )}
346- else :
347- enc = {}
348- self ._ps_fontd [dvifont .texname ] = font , enc
349-
350- else :
351- font , enc = font_and_encoding
352-
353- ft2font_flag = LOAD_TARGET_LIGHT
354-
307+ font , enc = self ._get_ps_font_and_encoding (dvifont .texname )
355308 char_id = self ._get_char_id_ps (font , glyph )
356309
357310 if char_id not in glyph_map :
@@ -362,12 +315,13 @@ def get_glyphs_tex(self, prop, s, glyph_map=None,
362315 else :
363316 charcode = glyph
364317
318+ ft2font_flag = LOAD_TARGET_LIGHT
365319 if charcode is not None :
366320 glyph0 = font .load_char (charcode , flags = ft2font_flag )
367321 else :
368322 warnings .warn ("The glyph (%d) of font (%s) cannot be "
369323 "converted with the encoding. Glyph may "
370- "be wrong" % (glyph , font_bunch . filename ))
324+ "be wrong" % (glyph , font . fname ))
371325
372326 glyph0 = font .load_char (glyph , flags = ft2font_flag )
373327
@@ -391,6 +345,41 @@ def get_glyphs_tex(self, prop, s, glyph_map=None,
391345 return (list (zip (glyph_ids , xpositions , ypositions , sizes )),
392346 glyph_map_new , myrects )
393347
348+ @staticmethod
349+ @functools .lru_cache (50 )
350+ def _get_ps_font_and_encoding (texname ):
351+ tex_font_map = dviread .PsfontsMap (dviread .find_tex_file ('pdftex.map' ))
352+ font_bunch = tex_font_map [texname ]
353+ if font_bunch .filename is None :
354+ raise ValueError (
355+ ("No usable font file found for %s (%s). "
356+ "The font may lack a Type-1 version." )
357+ % (font_bunch .psname , texname ))
358+
359+ font = get_font (font_bunch .filename )
360+
361+ for charmap_name , charmap_code in [("ADOBE_CUSTOM" , 1094992451 ),
362+ ("ADOBE_STANDARD" , 1094995778 )]:
363+ try :
364+ font .select_charmap (charmap_code )
365+ except (ValueError , RuntimeError ):
366+ pass
367+ else :
368+ break
369+ else :
370+ charmap_name = ""
371+ warnings .warn ("No supported encoding in font (%s)." %
372+ font_bunch .filename )
373+
374+ if charmap_name == "ADOBE_STANDARD" and font_bunch .encoding :
375+ enc0 = dviread .Encoding (font_bunch .encoding )
376+ enc = {i : _get_adobe_standard_encoding ().get (c , None )
377+ for i , c in enumerate (enc0 .encoding )}
378+ else :
379+ enc = {}
380+
381+ return font , enc
382+
394383
395384text_to_path = TextToPath ()
396385
0 commit comments