% Copyright (C) 1990, 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises. All rights reserved. % % This file is part of Aladdin Ghostscript. % % Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author % or distributor accepts any responsibility for the consequences of using it, % or for whether it serves any particular purpose or works at all, unless he % or she says so in writing. Refer to the Aladdin Ghostscript Free Public % License (the "License") for full details. % % Every copy of Aladdin Ghostscript must include a copy of the License, % normally in a plain ASCII text file named PUBLIC. The License grants you % the right to copy, modify and redistribute Aladdin Ghostscript, but only % under certain conditions described in the License. Among other things, the % License requires that the copyright notice and this notice be preserved on % all copies. % Font initialization and management code. % Define the default font. /defaultfontname /Courier def % Define the name of the font map file. /defaultfontmap (Fontmap) def % ------ End of editable parameters ------ % % If SUBSTFONT is defined, make it the default font. /SUBSTFONT where { pop /defaultfontname /SUBSTFONT load def } if % Define a reliable way of accessing FontDirectory in systemdict. /.FontDirectory { /FontDirectory .systemvar } .bind odef % If DISKFONTS is true, we load individual CharStrings as they are needed. % (This is intended primarily for machines with very small memories.) % In this case, we define another dictionary, parallel to FontDirectory, % that retains an open file for every font loaded. /FontFileDirectory 10 dict def % Define a temporary string for local use, since using =string % interferes with some PostScript programs. /.fonttempstring 128 string def % Split up a search path into individual directories or files. /.pathlist % .pathlist ... { { dup length 0 eq { pop exit } if .filenamelistseparator search not { exit } if exch pop exch } loop } bind def % Load a font name -> font file name map. userdict /Fontmap .FontDirectory maxlength dict put /.loadFontmap { % .loadFontmap - % We would like to simply execute .definefontmap as we read, % but we have to maintain backward compatibility with an older % specification that makes later entries override earlier. 50 dict exch .readFontmap { .definefontmap } forall } bind def /.readFontmap { % .readFontmap { dup token not { closefile exit } if % stack: dict file fontname % This is a hack to get around the absurd habit of MS-DOS editors % of adding an EOF character at the end of the file. dup (\032) eq { pop closefile exit } if 1 index token not { (Fontmap entry for ) print dup =only ( has no associated file or alias name! Giving up.\n) print flush {.readFontmap} 0 get 1 .quit } if dup type dup /stringtype eq exch /nametype eq or not { (Fontmap entry for ) print 1 index =only ( has an invalid file or alias name! Giving up.\n) print flush {.readFontmap} 0 get 1 .quit } if % stack: dict file fontname filename|aliasname 1 index type /stringtype eq 1 index type /nametype eq and 1 index xcheck and 1 index /run eq 2 index /.runlibfile eq or and { % This is an inclusion entry. pop findlibfile { exch pop } { file } ifelse 2 index exch .readFontmap pop } { % This is a real entry. % Read and pop tokens until a semicolon. { 2 index token not { (Fontmap entry for ) print 1 index =only ( ends prematurely! Giving up.\n) print flush {.loadFontmap} 0 get 1 .quit } if dup /; eq { pop 3 index 3 1 roll .growput exit } if pop } loop } ifelse } loop } bind def % Add an entry in Fontmap. We redefine this if the Level 2 % resource machinery is loaded. /.definefontmap % .definefontmap - { % Since Fontmap is global, make sure the values are storable. .currentglobal 3 1 roll true .setglobal dup type /stringtype eq { dup .gcheck not { dup length string copy } if } if Fontmap 3 -1 roll 2 copy .knownget { % Add an element to the end of the existing value, % unless it's the same as the current last element. mark exch aload pop counttomark 4 add -1 roll 2 copy eq { cleartomark pop pop } { ] readonly .growput } ifelse } { % Make a new entry. mark 4 -1 roll ] readonly .growput } ifelse .setglobal } bind def % Parse a font file just enough to find the FontName or FontType. /.findfontvalue % .findfontvalue true % .findfontvalue false % Closes the file in either case. { exch dup read not { -1 } if 2 copy unread 16#80 eq { dup (xxxxxx) readstring pop pop } % skip .PFB header if % Stack: key file { dup token not { false exit } if % end of file dup /eexec eq { pop false exit } if % reached eexec section dup /Subrs eq { pop false exit } if % Subrs without eexec dup /CharStrings eq { pop false exit } if % CharStrings without eexec dup 3 index eq { xcheck not { dup token exit } if } % found key { pop } ifelse } loop % Stack: key file value true (or) % Stack: key file false dup { 4 } { 3 } ifelse -2 roll closefile pop } bind def /.findfontname { /FontName .findfontvalue } bind def % If there is no FONTPATH, try to get one from the environment. NOFONTPATH { /FONTPATH () def } if /FONTPATH where { pop } { /FONTPATH (GS_FONTPATH) getenv not { () } if def } ifelse FONTPATH length 0 eq { (%END FONTPATH) .skipeof } if /FONTPATH [ FONTPATH .pathlist ] def % Scan directories looking for plausible fonts. "Plausible" means that % the file begins with %!PS-AdobeFont or %!FontType1, or with \200\001 % followed by four arbitrary bytes and then either of these strings. % To speed up the search, we skip any file whose name appears in % the Fontmap (with any extension and upper/lower case variation) already, % and any file whose extension definitely indicates it is not a font. % % NOTE: The current implementation of this procedure is somewhat Unix/DOS- % specific. It assumes that '/' and '\' are directory separators, and that % the part of a file name following the last '.' is the extension. % /.lowerstring % .lowerstring { 0 1 2 index length 1 sub { 2 copy get dup 65 ge exch 90 le and { 2 copy 2 copy get 32 add put } if pop } for } bind def /.splitfilename { % .basename % Make the file name read-only to detect aliasing bugs. % We really don't like doing this, but we've had one % such bug already. readonly { (/) search { true } { (\\) search } ifelse { pop pop } { exit } ifelse } loop dup { (.) search { pop pop } { exit } ifelse } loop 2 copy eq { pop () } { exch dup length 2 index length 1 add sub 0 exch getinterval exch } ifelse } bind def /.scanfontdict 1 dict def % establish a binding /.scanfontbegin { % Construct the table of all file names already in Fontmap. currentglobal true setglobal .scanfontdict dup maxlength Fontmap length 2 add .max .setmaxlength Fontmap { exch pop { dup type /stringtype eq { .splitfilename pop .fonttempstring copy .lowerstring cvn .scanfontdict exch true put } { pop } ifelse } forall } forall setglobal } bind def /.scanfontskip mark % Strings are converted to names anyway, so.... /afm true /bat true /c true /cmd true /com true /dir true /dll true /doc true /drv true /exe true /fon true /fot true /h true /o true /obj true /pfm true /pss true % Adobe Multiple Master font instances /txt true .dicttomark def /.scan1fontstring 128 string def /.scanfontheaders [(%!PS-Adobe*) (%!FontType*)] def 0 .scanfontheaders { length max } forall 6 add % extra for PFB header /.scan1fontfirst exch string def /.scanfontdir % .scanfontdir - { currentglobal exch true setglobal QUIET not { (Scanning ) print dup print ( for fonts...) print flush } if (*) 2 copy .filenamedirseparator dup (\\) eq { pop (\\\\) } if % double \ for pattern match exch concatstrings concatstrings 0 0 0 4 -1 roll % found scanned files { % stack: exch 1 add exch % increment filecount dup .splitfilename .fonttempstring copy .lowerstring % stack: % .scanfontskip exch known exch .scanfontdict exch known or { pop % stack: } { 3 -1 roll 1 add 3 1 roll % stack: dup (r) { file } .internalstopped { pop pop null () % stack: % null () } { % On some platforms, the file operator will open directories, % but an error will occur if we try to read from one. % Handle this possibility here. dup .scan1fontfirst { readstring } .internalstopped { pop pop () } { pop } ifelse % stack: %
} ifelse % Check for PFB file header. dup (\200\001????*) .stringmatch { dup length 6 sub 6 exch getinterval } if % Check for font file headers. false .scanfontheaders { 2 index exch .stringmatch or } forall exch pop { % stack: % dup 0 setfileposition .findfontname { dup Fontmap exch known { pop pop } { exch copystring exch DEBUG { ( ) print dup =only flush } if 1 index .definefontmap .splitfilename pop true .scanfontdict 3 1 roll .growput % Increment fontcount. 3 -1 roll 1 add 3 1 roll } ifelse } { pop } ifelse } % .findfontname will have done a closefile in the above case. { dup null eq { pop } { closefile } ifelse pop } ifelse } ifelse } .scan1fontstring filenameforall QUIET { pop pop pop } { ( ) print =only ( files, ) print =only ( scanned, ) print =only ( new fonts.\n) print flush } ifelse setglobal } bind def %END FONTPATH % Create the dictionary that registers the .buildfont procedure (called by % definefont) for each FontType. /buildfontdict 20 dict def % Register Type 3 fonts, which are always supported, for definefont. buildfontdict 3 /.buildfont3 cvx put % Register Type 0 fonts if they are supported. Strictly speaking, % we should do this in its own file (gs_type0.ps), but since this is % the only thing that would be in that file, it's simpler to put it here. /.buildfont0 where { pop buildfontdict 0 /.buildfont0 cvx put } if % Define definefont. This is a procedure built on a set of operators % that do all the error checking and key insertion. /.growfontdict { % Grow the font dictionary, if necessary, to ensure room for an % added entry, making sure there is at least one slot left for FID. dup maxlength 1 index length sub 2 lt { dup dup wcheck { .growdict } { .growdictlength dict .copydict } ifelse } { dup wcheck not { dup maxlength dict .copydict } if } ifelse } bind def /.completefont { { % Check for disabled platform fonts. NOPLATFONTS { % Make sure we leave room for FID. .growfontdict dup /ExactSize 0 put } { % Hack: if the Encoding looks like it might be the % Symbol or Dingbats encoding, load those now (for the % benefit of platform font matching) just in case % the font didn't actually reference them. % Note that some types of font don't have an Encoding. dup /Encoding .knownget { dup length 65 ge { 64 get dup /congruent eq { SymbolEncoding pop } if /a9 eq { DingbatsEncoding pop } if } { pop } ifelse } if } ifelse true exch dup /FontType known not { % This might be a CIDFont. dup /CIDFontType known { /.buildcidfont where { pop exch pop false exch } if } if } if exch { dup /FontType get //buildfontdict exch get exec } { .buildcidfont } ifelse DISKFONTS { FontFileDirectory 2 index known { dup /FontFile FontFileDirectory 4 index get .growput } if } if readonly % stack: name fontdict } stopped { /invalidfont signalerror } if } bind odef /definefont { .completefont % If the current allocation mode is global, also enter % the font in LocalFontDirectory. .currentglobal { //systemdict /LocalFontDirectory .knownget { 2 index 2 index .growput } if } if dup .FontDirectory 4 -2 roll .growput } odef % Define a procedure for defining aliased fonts. % We use this only for explicitly aliased fonts, not substituted fonts: % we think this matches the observed behavior of Adobe interpreters. /.aliasfont % .aliasfont { .currentglobal 3 1 roll dup .gcheck .setglobal dup length 2 add dict dup 3 -1 roll { 1 index /FID eq { pop pop } { put dup } ifelse } forall % Stack: global fontname newfont newfont. % We might be defining a global font whose FontName % is a local string. This is weird, but legal, % and doesn't cause problems anywhere else: % to avoid any possible problems in this case, do a cvn. % We might also be defining (as an alias) a global font % whose FontName is a local non-string, if someone passed a % garbage value to findfont. In this case, just don't % call definefont at all. 2 index dup type /stringtype eq exch .gcheck or 1 index .gcheck not or { /FontName 3 index dup type /stringtype eq { cvn } if put % Don't bind in definefont, since Level 2 redefines it. /definefont .systemvar exec } { .completefont pop exch pop } ifelse exch .setglobal } odef % so findfont will bind it % Define .loadfontfile for loading a font. If we recognize Type 1 and/or % TrueType fonts, gs_type1.ps and/or gs_ttf.ps will redefine this. /.loadfontfile { % According to Ed Taft, Adobe interpreters push userdict % before loading a font, and pop it afterwards. userdict begin cvx exec end } bind def /.loadfont { % Some buggy fonts leave extra junk on the stack, % so we have to make a closure that records the stack depth % in a fail-safe way. /.loadfontfile cvx count 1 sub 2 packedarray cvx exec count exch sub { pop } repeat } bind def % Find an alternate font to substitute for an unknown one. % We go to some trouble to parse the font name and extract % properties from it. Later entries take priority over earlier. /.substitutefaces [ % Guess at suitable substitutions for random unknown fonts. [(Grot) /Times] [(Roman) /Times] [(Book) /NewCenturySchlbk] % If the family name appears in the font name, % use a font from that family. [(Arial) /Helvetica] [(Avant) /AvantGarde] [(Bookman) /Bookman] [(Century) /NewCenturySchlbk] [(Cour) /Courier] [(Frut) /Helvetica] [(Geneva) /Helvetica] [(Helv) /Helvetica] [(NewYork) /Times] [(Pala) /Palatino] [(Sans) /Helvetica] [(Schlbk) /NewCenturySchlbk] [(Serif) /Times] [(Swiss) /Helvetica] [(Symbol) /Symbol] [(Times) /Times] [(Univers) /Helvetica] % Substitute for Adobe Multiple Master fonts. [(Minion) /Times] [(Myriad) /Helvetica] % If the font wants to be monospace, use Courier. [(Monospace) /Courier] [(Typewriter) /Courier] ] readonly def /.substituteproperties [ [(It) 9] [(Oblique) 1] [(Black) 2] [(Bd) 2] [(Bold) 2] [(bold) 2] [(Demi) 2] [(Heavy) 2] [(Sb) 2] [(Cn) 4] [(Cond) 4] [(Narrow) 4] [(Pkg) 4] % 8 is serif, currently only used in PDF and for (It) ] readonly def /.fontnameproperties { % .fontnameproperties .fontnamestring 0 exch .substituteproperties { 2 copy 0 get search { pop pop pop 1 get 3 -1 roll or exch } { pop pop } ifelse } forall pop } bind def /.substitutefamilies mark /AvantGarde {/AvantGarde-Book /AvantGarde-BookOblique /AvantGarde-Demi /AvantGarde-DemiOblique} /Bookman {/Bookman-Demi /Bookman-DemiItalic /Bookman-Light /Bookman-LightItalic} /Courier {/Courier /Courier-Oblique /Courier-Bold /Courier-BoldOblique} /Helvetica {/Helvetica /Helvetica-Oblique /Helvetica-Bold /Helvetica-BoldOblique /Helvetica-Narrow /Helvetica-Narrow-Oblique /Helvetica-Narrow-Bold /Helvetica-Narrow-BoldOblique} /NewCenturySchlbk {/NewCenturySchlbk-Roman /NewCenturySchlbk-Italic /NewCenturySchlbk-Bold /NewCenturySchlbk-BoldItalic} /Palatino {/Palatino-Roman /Palatino-Italic /Palatino-Bold /Palatino-BoldItalic} /Symbol {/Symbol /Symbol /Symbol /Symbol} /Times {/Times-Roman /Times-Italic /Times-Bold /Times-BoldItalic} .dicttomark readonly def /.fontnamestring { % .fontnamestring dup type dup /nametype eq { pop .namestring } { /stringtype ne { pop () } if } ifelse } bind def /.substitutefontname { % .substitutefontname % % Look for properties and/or a face name in the font name. % If we find any, use Times (serif) or Helvetica (sans) as the % base font; otherwise, use the default font. % Note that the "substituted" font name may be the same as % the requested one; the caller must check this. exch .fontnamestring { defaultfontname /Helvetica-Oblique /Helvetica-Bold /Helvetica-BoldOblique /Helvetica-Narrow /Helvetica-Narrow-Oblique /Helvetica-Narrow-Bold /Helvetica-Narrow-BoldOblique /Times-Roman /Times-Italic /Times-Bold /Times-BoldItalic /Helvetica-Narrow /Helvetica-Narrow-Oblique /Helvetica-Narrow-Bold /Helvetica-Narrow-BoldOblique } exch 3 -1 roll exch % Stack: facelist properties fontname % Look for a face name. .substitutefaces { 2 copy 0 get search { pop pop pop 1 get .substitutefamilies exch get 4 -1 roll pop 3 1 roll } { pop pop } ifelse } forall pop 1 index length mod get exec } bind def /.substitutefont { % .substitutefont dup .fontnameproperties .substitutefontname % Only accept fonts known in the Fontmap. Fontmap 1 index known not { pop defaultfontname } if } bind def % If requested, make (and recognize) fake entries in FontDirectory for fonts % present in Fontmap but not actually loaded. Thanks to Ray Johnston for % the idea behind this code. FAKEFONTS not { (%END FAKEFONTS) .skipeof } if % We use the presence or absence of the FontMatrix key to indicate whether % a font is real or fake. We must pop the arguments at the very end, % so that stack protection will be effective. /definefont { % definefont dup /FontMatrix known { //definefont } { 2 copy /FontName get findfont //definefont exch pop exch pop } ifelse } bind odef /scalefont { % scalefont 1 index /FontMatrix known { //scalefont } { 1 index /FontName get findfont 1 index //scalefont exch pop exch pop } ifelse } bind odef /makefont { % makefont 1 index /FontMatrix known { //makefont } { 1 index /FontName get findfont 1 index //makefont exch pop exch pop } ifelse } bind odef /setfont { % setfont - dup /FontMatrix known { //setfont } { dup /FontName get findfont //setfont pop } ifelse } bind odef %END FAKEFONTS % Define findfont so it tries to load a font if it's not found. % The Red Book requires that findfont be a procedure, not an operator, % but it still needs to restore the stacks reliably if it fails, % so we do all the work in an operator. /.findfont { mark 1 index //systemdict begin .dofindfont % Define any needed aliases. counttomark 1 sub { .aliasfont } repeat end exch pop exch pop } odef /findfont { .findfont } bind def % Check whether the font name we are about to look for is already on the list % of aliases we're accumulating; if so, cause an error. /.checkalias % -mark- ... .checkalias <> { counttomark 1 sub -1 1 { index 1 index eq { pop QUIET not { (Unable to substitute for font.\n) print flush } if /findfont cvx /invalidfont signalerror } if } for } bind def % Get a (non-fake) font if present in a FontDirectory. /.fontknownget % .fontknownget true % .fontknownget false { .knownget { FAKEFONTS { dup /FontMatrix known { true } { pop false } ifelse } { true } ifelse } { false } ifelse } bind def % This is the standard procedure for handling font substitution. % Its location is per an Adobe newsgroup posting. % It is called with the font name on the stack, standing in for findfont. /.stdsubstfont { % mark ... .stdsubstfont /SUBSTFONT where { pop QUIET not { (Substituting for font ) print dup =only (.\n) print flush } if % No aliasing. cleartomark mark defaultfontname } { dup .substitutefont 2 copy eq { pop defaultfontname } if .checkalias QUIET not { SHORTERRORS { (%%[) print 1 index =only ( not found, substituting ) print dup =only (]%%) } { (Substituting font ) print dup =only ( for ) print 1 index =only (.) } ifelse = flush } if % Remove all the accumulated aliases. counttomark 1 add 1 roll cleartomark mark exch } ifelse .dofindfont } bind def $error /SubstituteFont { .stdsubstfont } put % Do the work of findfont, including substitution, defaulting, and % scanning of FONTPATH. /.dofindfont { % .dofindfont .tryfindfont not { % We didn't find the font. If we haven't scanned % all the directories in FONTPATH, scan the next one % now and look for the font again. null 0 1 FONTPATH length 1 sub { FONTPATH 1 index get null ne { exch pop exit } if pop } for dup null ne { dup 0 eq { .scanfontbegin } if FONTPATH 1 index get .scanfontdir FONTPATH exch null put % Start over with an empty alias list. counttomark 1 sub { pop } repeat .dofindfont } { pop % No luck. Make sure we're not already % looking for the default font. dup defaultfontname eq { QUIET not { (Unable to load default font ) print dup =only (! Giving up.\n) print flush } if /findfont cvx /invalidfont signalerror } if % Substitute for the font. Don't alias. $error /SubstituteFont get exec } ifelse } if } bind def % Try to find a font using only the present contents of Fontmap. /.tryfindfont % .tryfindfont true % .tryfindfont false { .FontDirectory 1 index .fontknownget { % Already loaded exch pop true } { dup Fontmap exch .knownget not { % Unknown font name. Look for a file with the % same name as the requested font. dup dup type /nametype eq { .namestring } if .loadfontloop } { % Try each element of the Fontmap in turn. false exch % (in case we exhaust the list) % Stack: fontname false fontmaplist { exch pop dup type /nametype eq { % Font alias .checkalias .tryfindfont exit } { dup dup type dup /arraytype eq exch /packedarraytype eq or exch xcheck and { % Font with a procedural definition exec % The procedure will load the font. % Check to make sure this really happened. .FontDirectory 1 index .knownget { exch pop true exit } if } { % Font file name .loadfontloop { true exit } if } ifelse } ifelse false } forall % Stack: font true -or- fontname false { true } { % None of the Fontmap entries worked. % Try loading a file with the same name % as the requested font. dup dup type /nametype eq { .namestring } if .loadfontloop } ifelse } ifelse } ifelse } bind def % Attempt to load a font from a file. /.loadfontloop % .loadfontloop true % .loadfontloop false { % See above regarding the use of 'loop'. { % Is the font name a string? dup type /stringtype ne { QUIET not { (Can't find font with non-string name: ) print dup =only (.\n) print flush } if pop false exit } if % Can we open the file? findlibfile not { QUIET not { (Can't find \(or can't open\) font file ) print dup print (.\n) print flush } if pop false exit } if % Stack: fontname fontfilename fontfile DISKFONTS { .currentglobal true .setglobal 2 index (r) file FontFileDirectory exch 5 index exch .growput .setglobal } if QUIET not { (Loading ) print 2 index =only ( font from ) print 1 index print (... ) print flush } if % If LOCALFONTS isn't set, load the font into local or global % VM according to FontType; if LOCALFONTS is set, load the font % into the current VM, which is what Adobe printers (but not % DPS or CPSI) do. LOCALFONTS { false } { /setglobal where } ifelse { pop /FontType .findfontvalue { 1 eq } { false } ifelse % .setglobal, like setglobal, aliases FontDirectory to % GlobalFontDirectory if appropriate. However, we mustn't % allow the current version of .setglobal to be bound in, % because it's different depending on language level. .currentglobal exch /.setglobal .systemvar exec % Remove the fake definition, if any. .FontDirectory 3 index .undef 1 index (r) file .loadfont .FontDirectory exch /.setglobal .systemvar exec } { .loadfont .FontDirectory } ifelse % Stack: fontname fontfilename fontdirectory QUIET not { //systemdict /level2dict known { .currentglobal false .setglobal vmstatus true .setglobal vmstatus 3 -1 roll pop 6 -1 roll .setglobal 5 } { vmstatus 3 } ifelse { =only ( ) print } repeat (done.\n) print flush } if % Check to make sure the font was actually loaded. dup 3 index .fontknownget { 4 1 roll pop pop pop true exit } if % Maybe the file had a different FontName. % See if we can get a FontName from the file, and if so, % whether a font by that name exists now. exch (r) file .findfontname { 2 copy .fontknownget { % Yes. Stack: origfontname fontdirectory filefontname fontdict 3 -1 roll pop exch QUIET { pop } { (Using ) print =only ( font for ) print 1 index =only (.\n) print flush } ifelse true exit } if pop } if pop % The font definitely did not load correctly. QUIET not { (Loading ) print dup =only ( font failed.\n) print flush } if false exit } loop % end of loop } bind def % Define a procedure to load all known fonts. % This isn't likely to be very useful. /loadallfonts { Fontmap { pop findfont pop } forall } bind def % If requested, load all the fonts defined in the Fontmap into FontDirectory % as "fake" fonts i.e., font dicts with only FontName and FontType defined. % (We define FontType only for the sake of some questionable code in the % Apple Printer Utility 2.0 font inquiry code.) % % Note that this procedure only creates fake fonts in the FontDirectory % associated with the current VM. This is because in multi-context systems, % creating the fake fonts in local VM leads to undesirable complications. /.definefakefonts { } { (gs_fonts FAKEFONTS) VMDEBUG Fontmap { pop dup type /stringtype eq { cvn } if .FontDirectory 1 index known not { 2 dict dup /FontName 3 index put dup /FontType 1 put .FontDirectory 3 1 roll put } { pop } ifelse } forall } FAKEFONTS { exch } if pop def % don't bind, .current/setglobal get redefined % Install initial fonts from Fontmap. /.loadinitialfonts { NOFONTMAP not { /FONTMAP where { pop [ FONTMAP .pathlist ] { dup VMDEBUG findlibfile { exch pop .loadFontmap } { /undefinedfilename signalerror } ifelse } } { LIBPATH { defaultfontmap 2 copy .filenamedirseparator exch concatstrings concatstrings dup VMDEBUG (r) { file } .internalstopped { pop pop } { .loadFontmap } ifelse } } ifelse forall } if .definefakefonts % current VM is global } def % don't bind, .current/setglobal get redefined % ---------------- Synthetic font support ---------------- % % Create a new font by modifying an existing one. paramdict contains % entries with the same keys as the ones found in a Type 1 font; % it should also contain enough empty entries to allow adding the % corresponding non-overridden entries from the original font dictionary, % including FID. If paramdict includes a FontInfo entry, this will % also override the original font's FontInfo, entry by entry; % again, it must contain enough empty entries. % Note that this procedure does not perform a definefont. /.makemodifiedfont % .makemodifiedfont { exch { % Stack: destdict key value 1 index /FID ne { 2 index 2 index known { % Skip fontdict entry supplied in paramdict, but % handle FontInfo specially. 1 index /FontInfo eq { 2 index 2 index get % new FontInfo 1 index % old FontInfo { % Stack: destdict key value destinfo key value 2 index 2 index known { pop pop } { 2 index 3 1 roll put } ifelse } forall pop } if } { % No override, copy the fontdict entry. 2 index 3 1 roll put dup dup % to match pop pop below } ifelse } if pop pop } forall } bind def % Make a modified font and define it. Note that unlike definefont, % this does not leave the font on the operand stack. /.definemodifiedfont % .definemodifiedfont - { .makemodifiedfont dup /FontName get exch definefont pop } bind def