% Copyright (C) 1990, 1992 Aladdin Enterprises. All rights reserved. % Distributed by Free Software Foundation, Inc. % % This file is part of Ghostscript. % % Ghostscript is distributed in the hope that it will be useful, but % WITHOUT ANY WARRANTY. No author or distributor accepts responsibility % to anyone for the consequences of using it or for whether it serves any % particular purpose or works at all, unless he says so in writing. Refer % to the Ghostscript General Public License for full details. % % Everyone is granted permission to copy, modify and redistribute % Ghostscript, but only under the conditions described in the Ghostscript % General Public License. A copy of this license is supposed to have been % given to you along with Ghostscript so you can know your rights and % responsibilities. It should be in a file named COPYING. Among other % things, the copyright notice and this notice must be preserved on all % copies. % Font initialization for Ghostscript. % Ghostscript fonts have essentially the same contents as Adobe Type 1 fonts, % except that the external form doesn't use eexec encryption. % Someday there may be GNU documentation that describes this format. % Until then, you'll have to either get a copy of Adobe's book, or read % the Ghostscript code. The interpreter for Type 1 fonts, which reveals % most of their structure, is in the file gstype1.c. % Define the default font. /defaultfontname /Ugly def % Load the font name -> font file name map. FontDirectory maxlength dict 2 dict begin mark 1 index /; { % The stack contains a mark, the dictionary, the font name, % the file or alias name, and possibly additional information % about the font. counttomark 3 sub { pop } repeat put 1 index } bind def (Fontmap) run end pop pop % pop the mark and the copy of the dictionary userdict exch /Fontmap exch put % Ghostscript optionally can load individual CharStrings as they are needed. % (This is intended primarily for machines with very small memories.) % This happens if DISKFONTS is true. In this case, we define another % dictionary parallel to FontDirectory that retains an open file % for every font loaded. DISKFONTS { /FontFileDirectory FontDirectory maxlength dict def } if % Define an augmented version of .buildfont1 that inserts UnderlinePosition % and UnderlineThickness entries in FontInfo if they aren't there already. % (This works around the incorrect assumption, made by many word processors, % that these entries are present in the built-in fonts.) /.buildfont1x { dup /FontInfo known not { dup /FontInfo 2 dict put } if dup dup /FontInfo get dup dup /UnderlinePosition known exch /UnderlineThickness known and { pop pop % entries already present } { dup length 2 add dict copy dup /UnderlinePosition known not { dup /UnderlinePosition 3 index /FontBBox get 1 get 2 div put % 1/2 the font descent } if dup /UnderlineThickness known not { dup /UnderlineThickness 3 index /FontBBox get dup 3 get exch 1 get sub 20 div put % 1/20 the font height } if 1 index /FontInfo get wcheck not { readonly } if /FontInfo exch put } ifelse .buildfont1 } bind def % Define definefont. This is a procedure built on an operator that % does all the error checking and key insertion. /.buildfontdict 3 dict /.buildfont0 where { pop dup 0 /.buildfont0 load put } if /.buildfont1 where { pop dup 1 /.buildfont1x load put } if /.buildfont3 where { pop dup 3 /.buildfont3 load put } if def /definefont { 1 dict begin count /d exch def % save stack depth in case of error { dup /FontType get .buildfontdict exch get exec DISKFONTS { FontFileDirectory 2 index known { dup /FontFile FontFileDirectory 4 index get put } if } if readonly } stopped { count d sub { pop } repeat end /invalidfont signalerror } { end dup FontDirectory 4 2 roll put } ifelse } odef % Ghostscript optionally can load individual CharStrings as they are needed. % (This is intended primarily for machines with very small memories.) % Initially, the character definition is the file position of the definition; % this gets replaced with the actual CharString. % Note that if we are loading characters lazily, CharStrings is writable. % _Cstring must be long enough to hold the longest CharString for % a character defined using seac. This is lenIV + 4 * 5 (for the operands % of sbw, assuming div is not used) + 2 (for sbw) + 3 * 5 (for the operands % of seac other than the character codes) + 2 * 2 (for the character codes) % + 2 (for seac), i.e., lenIV + 43. /_Cstring 60 string def % When we initially load the font, we call % /readstring|/readhexstring skip_C % to skip over each character definition and return the file position instead. % This substitutes for the procedure % string currentfile exch read[hex]string pop % What we actually store is fileposition * 1000 + length, % negated if the string is stored in binary form. /skip_C { load exch dup 1000 ge 3 index type /nametype ne or { % This is a Subrs string, or the string is so long we can't represent % its length. Load it now. currentfile 3 1 roll string exch exec pop } { % Record the position and length, and skip the string. dup currentfile fileposition 1000 mul add 2 index /readstring load eq { neg } if 3 1 roll dup _Cstring length idiv { currentfile _Cstring 3 index exec pop pop } repeat _Cstring length mod _Cstring exch 0 exch getinterval currentfile exch 3 -1 roll exec pop pop } ifelse } bind def % Type1BuildChar calls load_C to actually load the character definition. /load_C % charindex fileposandlength -> { exch Encoding exch get exch read_C type1addpath } bind def /read_C % charname fileposandlength -> charstring { dup abs 1000 idiv FontFile exch setfileposition CharStrings 3 1 roll dup 0 lt { neg 1000 mod string FontFile exch readstring } { 1000 mod string FontFile exch readhexstring } ifelse pop dup 4 1 roll put % If the character is defined with seac, load its components now. dup mark exch seac_C counttomark { StandardEncoding exch get dup CharStrings exch get dup type /integertype eq { read_C } { pop } ifelse pop } repeat pop % the mark } bind def /seac_C % charstring -> achar bchar ..or nothing.. { dup length _Cstring length le { 4330 exch _Cstring type1decrypt exch pop dup dup length 2 sub 2 getinterval <0c06> eq % seac { dup length Private /lenIV known { Private /lenIV get } { 4 } ifelse exch 1 index sub getinterval % Parse the string just enough to extract the seac information. % We assume that the only possible operators are hsbw, sbw, and seac, % and that there are no 5-byte numbers. mark 0 3 -1 roll { exch { { dup 32 lt { pop 0 } { dup 247 lt { 139 sub 0 } { dup 251 lt { 247 sub 256 mul 108 add 1 1 } { 251 sub -256 mul -108 add -1 1 } ifelse } ifelse } ifelse } % 0 { mul add 0 } % 1 } exch get exec } forall pop counttomark 1 add 2 roll cleartomark % pop all but achar bchar } { pop % not seac } ifelse } { pop % punt } ifelse } bind def % Define an auxiliary procedure for loading a font. % If DISKFONTS is true: % - Prevent the CharStrings from being made read-only. % - Substitute a different CharString-reading procedure. % If the body of the font is encrypted with eexec, this is disabled, % because the implicit 'systemdict begin' hides the redefinitions. % We assume that: % - The magic procedures (-|, -!, |-, and |) are defined with % executeonly or readonly; % - The contents of the reading procedures are as defined in bdftops.ps; % - The font ends with % % readonly put noaccess|readonly put 4 dict begin /dict % leave room for FontFile { 1 add dict } bind def /executeonly % for reading procedures { readonly } def /noaccess % for Subrs strings and Private dictionary { readonly } def /readonly % for procedures and CharStrings dictionary { % We want to take the following non-standard actions here: % - If the operand is the CharStrings dictionary, do nothing; % - If the operand is a number (a file position replacing the % actual CharString), do nothing; % - If the operand is either of the reading procedures (-| or -!), % substitute a different one. dup type /dicttype eq % CharStrings or Private { 1 index /CharStrings ne { readonly } if } { dup type /arraytype eq % procedure or data array { dup length 5 eq 1 index xcheck and { dup 0 get /string eq 1 index 1 get /currentfile eq and 1 index 2 get /exch eq and 1 index 3 get dup /readstring eq exch /readhexstring eq or and 1 index 4 get /pop eq and { 3 get cvlit /skip_C cvx 2 packedarray cvx } { readonly } ifelse } { readonly } ifelse } { dup type /stringtype eq % must be a Subr string { readonly } if } ifelse } ifelse } bind def currentdict end /.loadfontdict exch def /.loadfont % .loadfont -> { mark exch systemdict begin % We really would just like systemdict on the stack, % but fonts produced by Fontographer require a writable dictionary.... userdict begin DISKFONTS { .loadfontdict begin } if % We can't just use `run', because we want to check for % .PFB files. We can't save the packing status anywhere, % so we need two separate control paths. % Also, we would like to use `false /PFBDecode filter', % but this occasionally produces a whitespace character as % the first of an eexec section, so we can't do it. currentpacking { false setpacking { dup read not { -1 } if 2 copy unread 16#80 eq { true /PFBDecode filter } if cvx exec } stopped % split up `execute' true setpacking $error /newerror get and {handleerror} if } { { dup read not { -1 } if 2 copy unread 16#80 eq { true /PFBDecode filter } if cvx exec } execute } ifelse DISKFONTS { end } if end end cleartomark } bind def % Define findfont so it tries to load a font if it's not found. /findfont { % Since PostScript has no concept of goto, or even blocks with % exits, we use a loop as a way to get an exitable scope. % The loop is never executed more than twice. { dup type /nametype ne % Convert the key to a name for lookup. { cvn } if dup FontDirectory exch known % Already loaded? { FontDirectory exch get exit } if dup Fontmap exch known not % Unknown font name. { dup defaultfontname eq { (Default font ) print cvx =only ( not found in Fontmap! Giving up.\n) print flush 1 .quit } if QUIET not { (Substituting ) print defaultfontname cvx =only ( for unknown font ) print dup == flush } if pop defaultfontname findfont exit } if dup Fontmap exch get % Check for a font alias. dup type /nametype eq { findfont FontDirectory 2 index 2 index put exch pop exit } if % If we can't find the file, substitute for the font. findlibfile { % Stack: fontname fontfilename fontfile DISKFONTS { 1 index (r) file FontFileDirectory exch 4 index exch put } if QUIET not { (Loading ) print 2 index =only ( font from ) print exch print (... ) print flush } { exch pop } ifelse .loadfont QUIET not { vmstatus 3 { =only ( ) print } repeat (done.\n) print flush } if % Check to make sure the font was actually loaded. dup FontDirectory exch known { findfont exit } if (Loading ) print cvx =only ( font failed, substituting ) print defaultfontname cvx =only (.\n) print flush defaultfontname findfont exit } if % findlibfile failed, substitute the default font. % Stack: fontname fontfilename (Can't find font file ) print print dup defaultfontname eq { ( for default font \() print cvx =only (\)! Giving up.\n) print flush 1 .quit } { ( for font ) print cvx =only (, substituting ) print defaultfontname cvx =only (.\n) print flush defaultfontname findfont } ifelse exit } loop % end of loop } odef % bind def % The CharStrings for a Ghostscript font are a dictionary in which % the key is the character name, and the value is a compressed % representation of a path, as produced by type1imagepath. % For detailed information, see the book % "Adobe Type 1 Font Format", published by Adobe Systems Inc. % Here is the BuildChar implementation % for Type 1 (Ghostscript standard) fonts. % The name Type1BuildChar is known to the interpreter. /Type1BuildChar { exch begin dup Encoding exch get dup CharStrings exch known not { QUIET not { (Substituting .notdef for ) print = flush } { pop } ifelse /.notdef } if currentdict /Metrics known { dup Metrics exch known { dup Metrics exch get .setmetrics } if } if CharStrings exch get PaintType 0 ne { 1 setmiterlimit 1 setlinejoin 1 setlinecap currentdict /StrokeWidth known { StrokeWidth } { 0 } ifelse setlinewidth } if dup type /stringtype eq % encoded outline { type1addpath pop } % does a fill or stroke { dup type /integertype eq % file position for lazy loading { load_C } { currentdict end systemdict begin begin exec end } ifelse } ifelse end } bind def % Find all the precompiled font operators in systemdict. systemdict { exch =string cvs (.font_) anchorsearch { pop pop exec % execute the operator, returns the font dictionary dup begin Encoding type /stringtype eq { Encoding cvn cvx exec /Encoding exch def } if FontName exch end definefont pop } { pop pop } ifelse } forall % Define a procedure to load all known fonts. % This isn't likely to be very useful. /loadallfonts { Fontmap { pop findfont pop } forall } bind def