@@ -20,7 +20,8 @@ def _fn_name(): return sys._getframe(1).f_code.co_name
2020
2121from matplotlib .font_manager import fontManager
2222from matplotlib .ft2font import FT2Font , KERNING_UNFITTED , KERNING_DEFAULT , KERNING_UNSCALED
23- from matplotlib .mathtext import math_parse_s_ps , bakoma_fonts
23+ from matplotlib .ttf2ps import convert_ttf_to_ps
24+ from matplotlib .mathtext import math_parse_s_ps
2425from matplotlib .text import Text
2526
2627from matplotlib .transforms import get_vec6_scales
@@ -29,6 +30,7 @@ def _fn_name(): return sys._getframe(1).f_code.co_name
2930 fromstring , nonzero , ones , put , take , where , isnan
3031import binascii
3132import re
33+ import sets
3234
3335if sys .platform .startswith ('win' ): cmd_split = '&'
3436else : cmd_split = ';'
@@ -97,11 +99,6 @@ def quote_ps_string(s):
9799 return s
98100
99101
100- _fontd = {}
101- _afmfontd = {}
102- _type42 = []
103-
104-
105102def seq_allequal (seq1 , seq2 ):
106103 """
107104 seq1 and seq2 are either None or sequences or numerix arrays
@@ -145,6 +142,17 @@ def __init__(self, width, height, pswriter, dpi=72):
145142 self .hatch = None
146143 self .image_magnification = dpi / 72.0
147144
145+ self .fontd = {}
146+ self .afmfontd = {}
147+ self .used_characters = {}
148+
149+ def track_characters (self , font , s ):
150+ """Keeps track of which characters are required from
151+ each font."""
152+ fname = font .fname
153+ used_characters = self .used_characters .setdefault (fname , sets .Set ())
154+ used_characters .update (s )
155+
148156 def set_color (self , r , g , b , store = 1 ):
149157 if (r ,g ,b ) != self .color :
150158 if r == g and r == b :
@@ -264,7 +272,7 @@ def get_text_width_height(self, s, prop, ismath):
264272
265273 if ismath :
266274 width , height , pswriter = math_parse_s_ps (
267- s , 72 , prop .get_size_in_points ())
275+ s , 72 , prop .get_size_in_points (), 0 , self . track_characters )
268276 return width , height
269277
270278 if rcParams ['ps.useafm' ]:
@@ -291,21 +299,19 @@ def flipy(self):
291299
292300 def _get_font_afm (self , prop ):
293301 key = hash (prop )
294- font = _afmfontd .get (key )
302+ font = self . afmfontd .get (key )
295303 if font is None :
296304 font = AFM (file (fontManager .findfont (prop , fontext = 'afm' )))
297- _afmfontd [key ] = font
305+ self . afmfontd [key ] = font
298306 return font
299307
300308 def _get_font_ttf (self , prop ):
301309 key = hash (prop )
302- font = _fontd .get (key )
310+ font = self . fontd .get (key )
303311 if font is None :
304312 fname = fontManager .findfont (prop )
305313 font = FT2Font (str (fname ))
306- _fontd [key ] = font
307- if fname not in _type42 :
308- _type42 .append (fname )
314+ self .fontd [key ] = font
309315 font .clear ()
310316 size = prop .get_size_in_points ()
311317 font .set_size (size , 72.0 )
@@ -727,6 +733,7 @@ def draw_text(self, gc, x, y, s, prop, angle, ismath):
727733 else :
728734 font = self ._get_font_ttf (prop )
729735 font .set_text (s ,0 )
736+ self .track_characters (font , s )
730737
731738 self .set_color (* gc .get_rgb ())
732739 self .set_font (font .get_sfnt ()[(1 ,0 ,0 ,6 )], prop .get_size_in_points ())
@@ -753,6 +760,7 @@ def draw_unicode(self, gc, x, y, s, prop, angle):
753760
754761 self .set_color (* gc .get_rgb ())
755762 self .set_font (font .get_sfnt ()[(1 ,0 ,0 ,6 )], prop .get_size_in_points ())
763+ self .track_characters (font , s )
756764
757765 cmap = font .get_charmap ()
758766 lastgind = None
@@ -800,7 +808,7 @@ def draw_mathtext(self, gc,
800808 self ._pswriter .write ("% mathtext\n " )
801809
802810 fontsize = prop .get_size_in_points ()
803- width , height , pswriter = math_parse_s_ps (s , 72 , fontsize )
811+ width , height , pswriter = math_parse_s_ps (s , 72 , fontsize , angle , self . track_characters )
804812 self .set_color (* gc .get_rgb ())
805813 thetext = pswriter .getvalue ()
806814 ps = """gsave
@@ -873,7 +881,6 @@ def push_gc(self, gc, store=1):
873881
874882## write("\n")
875883
876-
877884class GraphicsContextPS (GraphicsContextBase ):
878885 def get_capstyle (self ):
879886 return {'butt' :0 ,
@@ -893,85 +900,6 @@ def new_figure_manager(num, *args, **kwargs):
893900 manager = FigureManagerPS (canvas , num )
894901 return manager
895902
896- def encodeTTFasPS (fontfile ):
897- """
898- Encode a TrueType font file for embedding in a PS file.
899- """
900- font = file (fontfile , 'rb' )
901- hexdata , data = [], font .read (65520 )
902- b2a_hex = binascii .b2a_hex
903- while data :
904- hexdata .append ('<%s>\n ' %
905- '\n ' .join ([b2a_hex (data [j :j + 36 ]).upper ()
906- for j in range (0 , len (data ), 36 )]) )
907- data = font .read (65520 )
908-
909- hexdata = '' .join (hexdata )[:- 2 ] + '00>'
910- font = FT2Font (str (fontfile ))
911-
912- headtab = font .get_sfnt_table ('head' )
913- version = '%d.%d' % headtab ['version' ]
914- revision = '%d.%d' % headtab ['fontRevision' ]
915-
916- dictsize = 8
917- fontname = font .postscript_name
918- encoding = 'StandardEncoding'
919- fontbbox = '[%d %d %d %d]' % font .bbox
920-
921- posttab = font .get_sfnt_table ('post' )
922- minmemory = posttab ['minMemType42' ]
923- maxmemory = posttab ['maxMemType42' ]
924-
925- infosize = 7
926- sfnt = font .get_sfnt ()
927- notice = sfnt [(1 ,0 ,0 ,0 )]
928- family = sfnt [(1 ,0 ,0 ,1 )]
929- fullname = sfnt [(1 ,0 ,0 ,4 )]
930- iversion = sfnt [(1 ,0 ,0 ,5 )]
931- fixpitch = str (bool (posttab ['isFixedPitch' ])).lower ()
932- ulinepos = posttab ['underlinePosition' ]
933- ulinethk = posttab ['underlineThickness' ]
934- italicang = '(%d.%d)' % posttab ['italicAngle' ]
935-
936- numglyphs = font .num_glyphs
937- glyphs = []
938- for j in range (numglyphs ):
939- glyphs .append ('/%s %d def' % (font .get_glyph_name (j ), j ))
940- if j != 0 and j % 4 == 0 :
941- glyphs .append ('\n ' )
942- else :
943- glyphs .append (' ' )
944- glyphs = '' .join (glyphs )
945- data = ['%%!PS-TrueType-%(version)s-%(revision)s\n ' % locals ()]
946- if maxmemory :
947- data .append ('%%%%VMusage: %(minmemory)d %(maxmemory)d' % locals ())
948- data .append ("""%(dictsize)d dict begin
949- /FontName /%(fontname)s def
950- /FontMatrix [1 0 0 1 0 0] def
951- /FontType 42 def
952- /Encoding %(encoding)s def
953- /FontBBox %(fontbbox)s def
954- /PaintType 0 def
955- /FontInfo %(infosize)d dict dup begin
956- /Notice (%(notice)s) def
957- /FamilyName (%(family)s) def
958- /FullName (%(fullname)s) def
959- /version (%(iversion)s) def
960- /isFixedPitch %(fixpitch)s def
961- /UnderlinePosition %(ulinepos)s def
962- /UnderlineThickness %(ulinethk)s def
963- end readonly def
964- /sfnts [
965- %(hexdata)s
966- ] def
967- /CharStrings %(numglyphs)d dict dup begin
968- %(glyphs)s
969- end readonly def
970- FontName currentdict end definefont pop""" % locals ())
971- return '' .join (data )
972-
973-
974-
975903class FigureCanvasPS (FigureCanvasBase ):
976904 def draw (self ):
977905 pass
@@ -1091,20 +1019,24 @@ def print_figure(self, outfile, dpi=72, facecolor='w', edgecolor='w',
10911019
10921020 Ndict = len (psDefs )
10931021 print >> fh , "%%BeginProlog"
1094- type42 = _type42 + bakoma_fonts
10951022 if not rcParams ['ps.useafm' ]:
1096- Ndict += len (type42 )
1023+ Ndict += len (renderer . used_characters )
10971024 print >> fh , "/mpldict %d dict def" % Ndict
10981025 print >> fh , "mpldict begin"
10991026 for d in psDefs :
11001027 d = d .strip ()
11011028 for l in d .split ('\n ' ):
11021029 print >> fh , l .strip ()
11031030 if not rcParams ['ps.useafm' ]:
1104- for font in type42 :
1105- print >> fh , "%%BeginFont: " + FT2Font (str (font )).postscript_name
1106- print >> fh , encodeTTFasPS (font )
1107- print >> fh , "%%EndFont"
1031+ for font_filename , chars in renderer .used_characters .items ():
1032+ font = FT2Font (font_filename )
1033+ cmap = font .get_charmap ()
1034+ glyph_ids = []
1035+ for c in chars :
1036+ ccode = ord (c )
1037+ gind = cmap .get (ccode ) or 0
1038+ glyph_ids .append (gind )
1039+ convert_ttf_to_ps (font_filename , fh , rcParams ['ps.fonttype' ], glyph_ids )
11081040 print >> fh , "end"
11091041 print >> fh , "%%EndProlog"
11101042
0 commit comments