99import re
1010import sys
1111import time
12+ import warnings
1213import zlib
1314
1415import numpy as npy
2526 FigureManagerBase , FigureCanvasBase
2627from matplotlib .cbook import Bunch , enumerate , is_string_like , reverse_dict , get_realpath_and_stat
2728from matplotlib .figure import Figure
28- from matplotlib .font_manager import findfont
29+ from matplotlib .font_manager import findfont , is_opentype_cff_font
2930from matplotlib .afm import AFM
3031import matplotlib .type1font as type1font
3132import matplotlib .dviread as dviread
@@ -786,7 +787,8 @@ def embedTTFType42(font, characters, descriptor):
786787 glyph = font .load_char (ccode , flags = LOAD_NO_HINTING )
787788 # Why divided by 3.0 ??? Wish I knew... MGD
788789 widths .append ((ccode , cvt (glyph .horiAdvance ) / 3.0 ))
789- cid_to_gid_map [ccode ] = unichr (gind )
790+ if ccode < 65536 :
791+ cid_to_gid_map [ccode ] = unichr (gind )
790792 max_ccode = max (ccode , max_ccode )
791793 widths .sort ()
792794 cid_to_gid_map = cid_to_gid_map [:max_ccode + 1 ]
@@ -876,6 +878,15 @@ def embedTTFType42(font, characters, descriptor):
876878 'StemV' : 0 # ???
877879 }
878880
881+ # The font subsetting to a Type 3 font does not work for
882+ # OpenType (.otf) that embed a Postscript CFF font, so avoid that --
883+ # save as a (non-subsetted) Type 42 font instead.
884+ if is_opentype_cff_font (filename ):
885+ fonttype = 42
886+ warnings .warn (("'%s' can not be subsetted into a Type 3 font. " +
887+ "The entire font will be embedded in the output." ) %
888+ os .path .basename (filename ))
889+
879890 if fonttype == 3 :
880891 return embedTTFType3 (font , characters , descriptor )
881892 elif fonttype == 42 :
@@ -1134,10 +1145,6 @@ def __init__(self, file, dpi):
11341145 self .truetype_font_cache = {}
11351146 self .afm_font_cache = {}
11361147 self .file .used_characters = self .used_characters = {}
1137- if rcParams ['pdf.fonttype' ] == 3 :
1138- self .encode_string = self .encode_string_type3
1139- else :
1140- self .encode_string = self .encode_string_type42
11411148 self .mathtext_parser = MathTextParser ("Pdf" )
11421149 self .image_magnification = dpi / 72.0
11431150 self .tex_font_map = None
@@ -1344,7 +1351,7 @@ def draw_mathtext(self, gc, x, y, s, prop, angle):
13441351 # When using Type 3 fonts, we can't use character codes higher
13451352 # than 255, so we use the "Do" command to render those
13461353 # instead.
1347- fonttype = rcParams ['pdf.fonttype' ]
1354+ global_fonttype = rcParams ['pdf.fonttype' ]
13481355
13491356 # Set up a global transformation matrix for the whole math expression
13501357 a = angle / 180.0 * pi
@@ -1357,21 +1364,31 @@ def draw_mathtext(self, gc, x, y, s, prop, angle):
13571364 prev_font = None , None
13581365 oldx , oldy = 0 , 0
13591366 for ox , oy , fontname , fontsize , num , symbol_name in glyphs :
1367+ if is_opentype_cff_font (fontname ):
1368+ fonttype = 42
1369+ else :
1370+ fonttype = global_fonttype
1371+
13601372 if fonttype == 42 or num <= 255 :
13611373 self ._setup_textpos (ox , oy , 0 , oldx , oldy )
13621374 oldx , oldy = ox , oy
13631375 if (fontname , fontsize ) != prev_font :
13641376 self .file .output (self .file .fontName (fontname ), fontsize ,
13651377 Op .selectfont )
13661378 prev_font = fontname , fontsize
1367- self .file .output (self .encode_string (unichr (num )), Op .show )
1379+ self .file .output (self .encode_string (unichr (num ), fonttype ), Op .show )
13681380 self .file .output (Op .end_text )
13691381
13701382 # If using Type 3 fonts, render all of the two-byte characters
13711383 # as XObjects using the 'Do' command.
1372- if fonttype == 3 :
1384+ if global_fonttype == 3 :
13731385 for ox , oy , fontname , fontsize , num , symbol_name in glyphs :
1374- if num > 255 :
1386+ if is_opentype_cff_font (fontname ):
1387+ fonttype = 42
1388+ else :
1389+ fonttype = global_fonttype
1390+
1391+ if fonttype == 3 and num > 255 :
13751392 self .file .output (Op .gsave ,
13761393 0.001 * fontsize , 0 ,
13771394 0 , 0.001 * fontsize ,
@@ -1471,10 +1488,9 @@ def mytrans(x1, y1, x=x, y=y, a=angle / 180.0 * pi):
14711488 self .draw_polygon (boxgc , gc ._rgb ,
14721489 ((x1 ,y1 ), (x2 ,y2 ), (x3 ,y3 ), (x4 ,y4 )))
14731490
1474- def encode_string_type3 (self , s ):
1475- return s .encode ('cp1252' , 'replace' )
1476-
1477- def encode_string_type42 (self , s ):
1491+ def encode_string (self , s , fonttype ):
1492+ if fonttype == 3 :
1493+ return s .encode ('cp1252' , 'replace' )
14781494 return s .encode ('utf-16be' , 'replace' )
14791495
14801496 def draw_text (self , gc , x , y , s , prop , angle , ismath = False ):
@@ -1500,20 +1516,29 @@ def draw_text(self, gc, x, y, s, prop, angle, ismath=False):
15001516 font = self ._get_font_afm (prop )
15011517 l , b , w , h = font .get_str_bbox (s )
15021518 y -= b * fontsize / 1000
1519+ fonttype = 42
15031520 else :
15041521 font = self ._get_font_ttf (prop )
15051522 self .track_characters (font , s )
15061523 font .set_text (s , 0.0 , flags = LOAD_NO_HINTING )
15071524 y += font .get_descent () / 64.0
15081525
1526+ fonttype = rcParams ['pdf.fonttype' ]
1527+
1528+ # We can't subset all OpenType fonts, so switch to Type 42
1529+ # in that case.
1530+ if is_opentype_cff_font (font .fname ):
1531+ fonttype = 42
1532+
15091533 def check_simple_method (s ):
15101534 """Determine if we should use the simple or woven method
1511- to output this text, and chunks the string into 1-bit and
1512- 2-bit sections if necessary."""
1535+ to output this text, and chunks the string into 1-byte and
1536+ 2-byte sections if necessary."""
15131537 use_simple_method = True
15141538 chunks = []
1515- if rcParams ['pdf.fonttype' ] == 3 :
1516- if not isinstance (s , str ) and len (s ) != 0 :
1539+
1540+ if not rcParams ['pdf.use14corefonts' ]:
1541+ if fonttype == 3 and not isinstance (s , str ) and len (s ) != 0 :
15171542 # Break the string into chunks where each chunk is either
15181543 # a string of chars <= 255, or a single character > 255.
15191544 s = unicode (s )
@@ -1537,7 +1562,7 @@ def draw_text_simple():
15371562 prop .get_size_in_points (),
15381563 Op .selectfont )
15391564 self ._setup_textpos (x , y , angle )
1540- self .file .output (self .encode_string (s ), Op .show , Op .end_text )
1565+ self .file .output (self .encode_string (s , fonttype ), Op .show , Op .end_text )
15411566
15421567 def draw_text_woven (chunks ):
15431568 """Outputs text using the woven method, alternating
@@ -1567,7 +1592,7 @@ def draw_text_woven(chunks):
15671592 for chunk_type , chunk in chunks :
15681593 if mode == 1 and chunk_type == 1 :
15691594 self ._setup_textpos (newx , 0 , 0 , oldx , 0 , 0 )
1570- self .file .output (self .encode_string (chunk ), Op .show )
1595+ self .file .output (self .encode_string (chunk , fonttype ), Op .show )
15711596 oldx = newx
15721597
15731598 lastgind = None
0 commit comments