1207 lines · 42.8 KB · Text
RawDownload
%    Copyright (C) 1990-2003 artofcode LLC.  All rights reserved.% % This software is provided AS-IS with no warranty, either express or% implied.% % This software is distributed under license and may not be copied,% modified or distributed except as expressly authorized under the terms% of the license contained in the file LICENSE in this distribution.% % For more information about licensing, please refer to% http://www.ghostscript.com/licensing/. For information on% commercial licensing, go to http://www.artifex.com/licensing/ or% contact Artifex Software, Inc., 101 Lucas Valley Road #110,% San Rafael, CA  94903, U.S.A., +1(415)492-9861. % $Id: gs_fonts.ps,v 1.48 2004/11/24 20:09:01 ghostgum Exp $% Font initialization and management code. % Define the default font./defaultfontname /Courier def % Define the name of the font map file.% Note that the "%%Replace " comment below provides the font map file name% for compiling initialization files into executable. Most likely it should be% consistent with the one specified here./defaultfontmap (Fontmap) def /defaultfontmap_content 50 dict1 dict begin/; { 2 index 3 1 roll .growput } bind def%% Replace 0 (Fontmap)end def % ------ End of editable parameters ------ % % Define the UniqueIDs and organization XUID assigned to Aladdin.% UniqueIDs 5,066,501 - 5,066,580 are assigned as follows:%   01 and 02 for shareware Cyrillic%   33 through 67 for Type 1 versions of the Hershey fonts% UniqueIDs 5,115,501 - 5,115,600 are currently unassigned./AladdinEnterprisesXUID 107 def % 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 8192 string def % Split up a search path into individual directories or files./.pathlist              % <path> .pathlist <dir1|file1> ... {  { 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 {         % <file> .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                % ones within the same file.   50 dict exch .readFontmap    { .definefontmap } forall} bind def/.readFontmap {         % <dict> <file> .readFontmap <dict>    { 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.) = 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.) = 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.) = 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                 % <fontname> <file|alias> .definefontmap - {              % Since Fontmap is global, make sure the values are storable.   % If the fontname contains Unicode (first byte == \000) and   % this is not an alias definition, define an alias using ASCII   % (stripping out the high \000 bytes). Observed with some TT fonts.   1 index 100 string cvs 0 get 0 eq 1 index type /nametype ne and {     1 index 100 string cvs dup length 2 div cvi string true exch     0 1 2 index length 1 sub {       % stack: fontname filename fontnamestring addflag newstring index       dup 4 index exch 2 mul get 0 ne {	 % High byte of pair is not \000	 pop pop false exch         exit       } if       dup 4 index exch 2 mul 1 add get 2 index 3 1 roll put     } for     exch {       DEBUG { (\nAdding alias for: ) print 1 index ==only ( as: ) print dup == flush } if         cvn exch cvn .definefontmap	% recurse with an alias     } {       pop pop	% discard the name     } ifelse   } if   .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 {       % <file> <key> .findfontvalue <value> true                        % <file> <key> .findfontvalue false                        % Closes the file in either case.  exch dup read {    2 copy unread 16#80 eq {      dup (xxxxxx) readstring pop pop             % skip .PFB header    } if    {           % Stack: key file                % Protect ourselves against syntax errors here.      dup { token } stopped { pop false exit } if      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  } { closefile pop false } ifelse} 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 }ifelseFONTPATH 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           % <string> .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 {       % <dir.../base.extn> .basename <base> <extn>                % 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 8192 string def% %%BeginFont: is not per Adobe documentation, but a few fonts have it./.scanfontheaders [(%!PS-Adobe*) (%!FontType*) (%%BeginFont:*)] def0 .scanfontheaders { length .max } forall 6 add % extra for PFB header/.scan1fontfirst exch string def/.scanfontdir           % <dirname> .scanfontdir - { currentglobal exch true setglobal   QUIET not { (Scanning ) print dup print ( for fonts...) print flush } if   [ 1 index ] (*) .generate_dir_list_templates   0 0 0 4 -1 roll      % found scanned files    {           % stack: <fontcount> <scancount> <filecount> <filename>      exch 1 add exch                   % increment filecount      dup .splitfilename .fonttempstring copy .lowerstring                % stack: <fontcount> <scancount> <filecount+1> <filename>                %       <BASE> <ext>      .scanfontskip exch known exch .scanfontdict exch known or       { pop                % stack: <fontcount> <scancount> <filecount+1>       }       { 3 -1 roll 1 add 3 1 roll                % stack: <fontcount> <scancount+1> <filecount+1> <filename>         dup (r) { file } .internalstopped          { pop pop null ()                % stack: <fontcount> <scancount+1> <filecount+1> <filename>                %       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: <fontcount> <scancount+1> <filecount+1>                %       <filename> <file> <header>          }         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: <fontcount> <scancount+1> <filecount+1> <filename>                %       <file>            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.) = flush    }   ifelse   pop   setglobal } bind def %END FONTPATH % Try to enumerate native fonts registered with the os% and add them to the fontmap. This relies on a custom% operator which calls platform-specific C code. It% returns an array of arrays, each containing a pair% of strings: what the system thinks is the ps name,% and the access path./.setnativefontmapbuilt { % set whether we've been run  systemdict exch /.nativefontmapbuilt exch .forceput } .bind executeonly deffalse .setnativefontmapbuilt/.buildnativefontmap {   % - .buildnativefontmap <bool>  QUIET not {    (Querying operating system for font files...\n)    print flush  } if  .getnativefonts dup  {    exch    {      % stack: [ (name) (path) ]      % verify the font name ourselves      dup 1 get (r) { file } stopped      {        % skip the entry if we can't open the returned path         pop pop pop      }{        % we could open the font file        .findfontname        not { dup 0 get } if  % stack: (newname) [ (name) (path) ]        % DEBUG { (  found ) print dup print (\n) print flush } if         % add entry to the fontmap        1 index exch 0 exch dup type /nametype ne {cvn} if put        aload pop .definefontmap      } ifelse    } forall  } if  % record that we've been run  true .setnativefontmapbuilt} bind def % 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      dup /.OrigFont known not {        dup dup /.OrigFont exch .growput      } if      true exch                % If this is a CIDFont, CIDFontType takes precedence                % over FontType.      dup /CIDFontType known {        /.buildcidfont where {          pop exch not exch     % true => false        } 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      systemdict /ProvideUnicode .knownget not { false } if {        /FontEmulationProcs /ProcSet findresource        /ProvideUnicodeDecoding get exec      } 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                % If the font originated as a resource, register it.   currentfile .currentresourcefile eq { dup .registerfont } if } 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             % <name> <font> .aliasfont <newFont> { .currentglobal 3 1 roll dup .gcheck .setglobal                             % <bool> <name> <font>   dup length 2 add dict     % <bool> <name> <font> <dict>   dup 3 -1 roll             % <bool> <name> <dict> <dict> <font>   { 1 index /FID eq { pop pop } { put dup } ifelse } forall                             % <bool> <name> <dict> <dict>                % Stack: global fontname newfont newfont.

Lines 1–500 of 1207.