@@ -88,14 +88,16 @@ def _move_path_to_path_or_stream(src, dst):
8888        shutil .move (src , dst , copy_function = shutil .copyfile )
8989
9090
91- def  _font_to_ps_type3 (font_path , glyph_indices ):
91+ def  _font_to_ps_type3 (font_path , subset_index ,  glyph_indices ):
9292    """ 
9393    Subset *glyphs_indices* from the font at *font_path* into a Type 3 font. 
9494
9595    Parameters 
9696    ---------- 
9797    font_path : path-like 
9898        Path to the font to be subsetted. 
99+     subset_index : int 
100+         The subset of the above font being created. 
99101    glyph_indices : set[int] 
100102        The glyphs to include in the subsetted font. 
101103
@@ -111,15 +113,15 @@ def _font_to_ps_type3(font_path, glyph_indices):
111113
112114%%Creator: Converted from TrueType to Type 3 by Matplotlib. 
11311510 dict begin 
114- /FontName /{font_name} def 
116+ /FontName /{font_name}-{subset}  def 
115117/PaintType 0 def 
116118/FontMatrix [{inv_units_per_em} 0 0 {inv_units_per_em} 0 0] def 
117119/FontBBox [{bbox}] def 
118120/FontType 3 def 
119121/Encoding [{encoding}] def 
120122/CharStrings {num_glyphs} dict dup begin 
121123/.notdef 0 def 
122- """ .format (font_name = font .postscript_name ,
124+ """ .format (font_name = font .postscript_name ,  subset = subset_index , 
123125           inv_units_per_em = 1  /  font .units_per_EM ,
124126           bbox = " " .join (map (str , font .bbox )),
125127           encoding = " " .join (f"/{ font .get_glyph_name (glyph_index )}  
@@ -168,20 +170,22 @@ def _font_to_ps_type3(font_path, glyph_indices):
168170    return  preamble  +  "\n " .join (entries ) +  postamble 
169171
170172
171- def  _font_to_ps_type42 (font_path , glyph_indices , fh ):
173+ def  _font_to_ps_type42 (font_path , subset_index ,  glyph_indices , fh ):
172174    """ 
173175    Subset *glyph_indices* from the font at *font_path* into a Type 42 font at *fh*. 
174176
175177    Parameters 
176178    ---------- 
177179    font_path : path-like 
178180        Path to the font to be subsetted. 
181+     subset_index : int 
182+         The subset of the above font being created. 
179183    glyph_indices : set[int] 
180184        The glyphs to include in the subsetted font. 
181185    fh : file-like 
182186        Where to write the font. 
183187    """ 
184-     _log .debug ("SUBSET %s characters: %s" , font_path , glyph_indices )
188+     _log .debug ("SUBSET %s:%d  characters: %s" , font_path ,  subset_index , glyph_indices )
185189    try :
186190        kw  =  {}
187191        # fix this once we support loading more fonts from a collection 
@@ -192,25 +196,27 @@ def _font_to_ps_type42(font_path, glyph_indices, fh):
192196              _backend_pdf_ps .get_glyphs_subset (font_path , glyph_indices ) as  subset ):
193197            fontdata  =  _backend_pdf_ps .font_as_file (subset ).getvalue ()
194198            _log .debug (
195-                 "SUBSET %s %d -> %d" , font_path , os . stat ( font_path ). st_size ,
196-                 len (fontdata )
199+                 "SUBSET %s:%d  %d -> %d" , font_path , subset_index ,
200+                 os . stat ( font_path ). st_size ,  len (fontdata )
197201            )
198-             fh .write (_serialize_type42 (font , subset , fontdata ))
202+             fh .write (_serialize_type42 (font , subset_index ,  subset , fontdata ))
199203    except  RuntimeError :
200204        _log .warning (
201205            "The PostScript backend does not currently support the selected font (%s)." ,
202206            font_path )
203207        raise 
204208
205209
206- def  _serialize_type42 (font , subset , fontdata ):
210+ def  _serialize_type42 (font , subset_index ,  subset , fontdata ):
207211    """ 
208212    Output a PostScript Type-42 format representation of font 
209213
210214    Parameters 
211215    ---------- 
212216    font : fontTools.ttLib.ttFont.TTFont 
213217        The original font object 
218+     subset_index : int 
219+         The subset of the above font to be created. 
214220    subset : fontTools.ttLib.ttFont.TTFont 
215221        The subset font object 
216222    fontdata : bytes 
@@ -231,7 +237,7 @@ def _serialize_type42(font, subset, fontdata):
231237        10 dict begin 
232238        /FontType 42 def 
233239        /FontMatrix [1 0 0 1 0 0] def 
234-         /FontName /{ name .getDebugName (6 )}  
240+         /FontName /{ name .getDebugName (6 )} - { subset_index }  
235241        /FontInfo 7 dict dup begin 
236242        /FullName ({ name .getDebugName (4 )}  
237243        /FamilyName ({ name .getDebugName (1 )}  
@@ -425,7 +431,8 @@ def __init__(self, width, height, pswriter, imagedpi=72):
425431        self ._clip_paths  =  {}
426432        self ._path_collection_id  =  0 
427433
428-         self ._character_tracker  =  _backend_pdf_ps .CharacterTracker ()
434+         self ._character_tracker  =  _backend_pdf_ps .CharacterTracker (
435+             _backend_pdf_ps ._FONT_MAX_GLYPH .get (mpl .rcParams ['ps.fonttype' ], 0 ))
429436        self ._logwarn_once  =  functools .cache (_log .warning )
430437
431438    def  _is_transparent (self , rgb_or_rgba ):
@@ -793,12 +800,16 @@ def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None):
793800        else :
794801            language  =  mtext .get_language () if  mtext  is  not None  else  None 
795802            font  =  self ._get_font_ttf (prop )
796-             self ._character_tracker .track (font , s )
797803            for  item  in  _text_helpers .layout (s , font , language = language ):
804+                 # NOTE: We ignore the character code in the subset, because PS uses the 
805+                 # glyph name to write text. The subset is only used to ensure that each 
806+                 # one does not overflow format limits. 
807+                 subset , _  =  self ._character_tracker .track_glyph (
808+                     item .ft_object , item .char , item .glyph_index )
798809                ps_name  =  (item .ft_object .postscript_name 
799810                           .encode ("ascii" , "replace" ).decode ("ascii" ))
800811                glyph_name  =  item .ft_object .get_glyph_name (item .glyph_index )
801-                 stream .append ((ps_name , item .x , glyph_name ))
812+                 stream .append ((f' { ps_name } - { subset } ' item .x , glyph_name ))
802813        self .set_color (* gc .get_rgb ())
803814
804815        for  ps_name , group  in  itertools . \
@@ -827,11 +838,15 @@ def draw_mathtext(self, gc, x, y, s, prop, angle):
827838            f"{ angle :g} \n " )
828839        lastfont  =  None 
829840        for  font , fontsize , ccode , glyph_index , ox , oy  in  glyphs :
830-             self ._character_tracker .track_glyph (font , ccode , glyph_index )
831-             if  (font .postscript_name , fontsize ) !=  lastfont :
832-                 lastfont  =  font .postscript_name , fontsize 
841+             # NOTE: We ignore the character code in the subset, because PS uses the 
842+             # glyph name to write text. The subset is only used to ensure that each one 
843+             # does not overflow format limits. 
844+             subset , _  =  self ._character_tracker .track_glyph (
845+                 font , ccode , glyph_index )
846+             if  (font .postscript_name , subset , fontsize ) !=  lastfont :
847+                 lastfont  =  font .postscript_name , subset , fontsize 
833848                self ._pswriter .write (
834-                     f"/{ font .postscript_name } { fontsize } \n " )
849+                     f"/{ font .postscript_name } - { subset } { fontsize } \n " )
835850            glyph_name  =  font .get_glyph_name (glyph_index )
836851            self ._pswriter .write (
837852                f"{ ox :g} { oy :g} \n " 
@@ -1071,18 +1086,15 @@ def print_figure_impl(fh):
10711086            print ("\n " .join (_psDefs ), file = fh )
10721087            if  not  mpl .rcParams ['ps.useafm' ]:
10731088                for  font , subsets  in  ps_renderer ._character_tracker .used .items ():
1074-                     for  charmap  in  subsets :
1089+                     for  subset ,  charmap  in  enumerate ( subsets ) :
10751090                        if  not  charmap :
10761091                            continue 
10771092                        fonttype  =  mpl .rcParams ['ps.fonttype' ]
1078-                         # Can't use more than 255 chars from a single Type 3 font. 
1079-                         if  len (charmap ) >  255 :
1080-                             fonttype  =  42 
10811093                        fh .flush ()
10821094                        if  fonttype  ==  3 :
1083-                             fh .write (_font_to_ps_type3 (font , charmap .values ()))
1095+                             fh .write (_font_to_ps_type3 (font , subset ,  charmap .values ()))
10841096                        else :  # Type 42 only. 
1085-                             _font_to_ps_type42 (font , charmap .values (), fh )
1097+                             _font_to_ps_type42 (font , subset ,  charmap .values (), fh )
10861098            print ("end" , file = fh )
10871099            print ("%%EndProlog" , file = fh )
10881100
0 commit comments