1
1
from collections import OrderedDict
2
+ import functools
2
3
import urllib .parse
3
4
import warnings
4
5
5
6
import numpy as np
6
7
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
14
9
from 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
15
14
from matplotlib .transforms import Affine2D
16
15
17
16
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
+
18
24
class TextToPath (object ):
19
25
"""
20
26
A class that convert a given text to a path using ttf fonts.
@@ -25,19 +31,12 @@ class TextToPath(object):
25
31
26
32
def __init__ (self ):
27
33
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
-
33
34
self ._texmanager = None
34
35
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' ))
41
40
42
41
def _get_font (self , prop ):
43
42
"""
@@ -281,13 +280,6 @@ def get_glyphs_tex(self, prop, s, glyph_map=None,
281
280
282
281
texmanager = self .get_texmanager ()
283
282
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
-
291
283
fontsize = prop .get_size_in_points ()
292
284
if hasattr (texmanager , "get_dvi" ):
293
285
dvifilelike = texmanager .get_dvi (s , self .FONT_SCALE )
@@ -312,46 +304,7 @@ def get_glyphs_tex(self, prop, s, glyph_map=None,
312
304
# characters into strings.
313
305
# oldfont, seq = None, []
314
306
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 )
355
308
char_id = self ._get_char_id_ps (font , glyph )
356
309
357
310
if char_id not in glyph_map :
@@ -362,12 +315,13 @@ def get_glyphs_tex(self, prop, s, glyph_map=None,
362
315
else :
363
316
charcode = glyph
364
317
318
+ ft2font_flag = LOAD_TARGET_LIGHT
365
319
if charcode is not None :
366
320
glyph0 = font .load_char (charcode , flags = ft2font_flag )
367
321
else :
368
322
warnings .warn ("The glyph (%d) of font (%s) cannot be "
369
323
"converted with the encoding. Glyph may "
370
- "be wrong" % (glyph , font_bunch . filename ))
324
+ "be wrong" % (glyph , font . fname ))
371
325
372
326
glyph0 = font .load_char (glyph , flags = ft2font_flag )
373
327
@@ -391,6 +345,41 @@ def get_glyphs_tex(self, prop, s, glyph_map=None,
391
345
return (list (zip (glyph_ids , xpositions , ypositions , sizes )),
392
346
glyph_map_new , myrects )
393
347
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
+
394
383
395
384
text_to_path = TextToPath ()
396
385
0 commit comments