]> git.ipfire.org Git - thirdparty/cups.git/blame - pstoraster/gs_fonts.ps
Merge changes from 1.1 tree.
[thirdparty/cups.git] / pstoraster / gs_fonts.ps
CommitLineData
caddbb58 1% Copyright (C) 1990, 1995, 1996, 1997, 1998 Aladdin Enterprises. All rights reserved.
2777fb4c 2%
3% This file is part of GNU Ghostscript.
4%
5% GNU Ghostscript is distributed in the hope that it will be useful, but
caddbb58 6% WITHOUT ANY WARRANTY. No author or distributor accepts responsibility
7% to anyone for the consequences of using it or for whether it serves any
8% particular purpose or works at all, unless he says so in writing. Refer
9% to the GNU General Public License for full details.
2777fb4c 10%
11% Everyone is granted permission to copy, modify and redistribute GNU
12% Ghostscript, but only under the conditions described in the GNU General
caddbb58 13% Public License. A copy of this license is supposed to have been given
14% to you along with GNU Ghostscript so you can know your rights and
2777fb4c 15% responsibilities. It should be in a file named COPYING. Among other
16% things, the copyright notice and this notice must be preserved on all
17% copies.
18%
caddbb58 19% Aladdin Enterprises supports the work of the GNU Project, but is not
20% affiliated with the Free Software Foundation or the GNU Project. GNU
21% Ghostscript, as distributed by Aladdin Enterprises, does not require any
22% GNU software to build or run it.
2777fb4c 23
b5cb0608 24% $Id: gs_fonts.ps,v 1.2.2.1 2001/05/13 18:38:31 mike Exp $
2777fb4c 25% Font initialization and management code.
26
27% Define the default font.
28/defaultfontname /Courier def
29
30% Define the name of the font map file.
31/defaultfontmap (Fontmap) def
32
33% ------ End of editable parameters ------ %
34
caddbb58 35% If SUBSTFONT is defined, make it the default font.
36/SUBSTFONT where { pop /defaultfontname /SUBSTFONT load def } if
37
38% Define a reliable way of accessing FontDirectory in systemdict.
39/.FontDirectory
40{ /FontDirectory .systemvar
41} .bind odef
42
2777fb4c 43% If DISKFONTS is true, we load individual CharStrings as they are needed.
44% (This is intended primarily for machines with very small memories.)
45% In this case, we define another dictionary, parallel to FontDirectory,
46% that retains an open file for every font loaded.
47/FontFileDirectory 10 dict def
48
caddbb58 49% Define a temporary string for local use, since using =string
50% interferes with some PostScript programs.
51/.fonttempstring 128 string def
52
2777fb4c 53% Split up a search path into individual directories or files.
54/.pathlist % <path> .pathlist <dir1|file1> ...
55 { { dup length 0 eq { pop exit } if
56 .filenamelistseparator search not { exit } if
57 exch pop exch
58 }
59 loop
60 } bind def
61
62% Load a font name -> font file name map.
caddbb58 63userdict /Fontmap .FontDirectory maxlength dict put
2777fb4c 64/.loadFontmap % <file> .loadFontmap -
65 { % We would like to simply execute .definefontmap as we read,
66 % but we have to maintain backward compatibility with an older
67 % specification that makes later entries override earlier.
68 50 dict exch
69 { dup token not { closefile exit } if
70 % stack: <file> fontname
71 % This is a hack to get around the absurd habit of MS-DOS editors
72 % of adding an EOF character at the end of the file.
73 dup (\032) eq { pop closefile exit } if
74 1 index token not
75 { (Fontmap entry for ) print dup =only
76 ( has no associated file or alias name! Giving up.\n) print flush
77 {.loadFontmap} 0 get 1 .quit
78 } if
79 dup type dup /stringtype eq exch /nametype eq or not
80 { (Fontmap entry for ) print 1 index =only
81 ( has an invalid file or alias name! Giving up.\n) print flush
82 {.loadFontmap} 0 get 1 .quit
83 } if
84 % stack: dict file fontname filename|aliasname
85 % Read and pop tokens until a semicolon.
86 { 2 index token not
87 { (Fontmap entry for ) print 1 index =only
88 ( ends prematurely! Giving up.\n) print flush
89 {.loadFontmap} 0 get 1 .quit
90 } if
91 dup /; eq { pop 3 index 3 1 roll .growput exit } if
92 pop
93 } loop
94 } loop
95 { .definefontmap } forall
96 } bind def
97% Add an entry in Fontmap. We redefine this if the Level 2
98% resource machinery is loaded.
99/.definefontmap % <fontname> <file|alias> .definefontmap -
100 { % Since Fontmap is global, make sure the values are storable.
101 .currentglobal 3 1 roll true .setglobal
102 dup type /stringtype eq
103 { dup .gcheck not { dup length string copy } if
104 }
105 if
106 Fontmap 3 -1 roll 2 copy .knownget
107 { % Add an element to the end of the existing value,
108 % unless it's the same as the current last element.
109 mark exch aload pop counttomark 4 add -1 roll
110 2 copy eq { cleartomark pop pop } { ] readonly .growput } ifelse
111 }
112 { % Make a new entry.
113 mark 4 -1 roll ] readonly .growput
114 }
115 ifelse .setglobal
116 } bind def
117
118% Parse a font file just enough to find the FontName or FontType.
119/.findfontvalue % <file> <key> .findfontvalue <value> true
120 % <file> <key> .findfontvalue false
121 % Closes the file in either case.
122 { exch dup read not { -1 } if
123 2 copy unread 16#80 eq
124 { dup (xxxxxx) readstring pop pop } % skip .PFB header
125 if
126 % Stack: key file
127 { dup token not { false exit } if % end of file
128 dup /eexec eq { pop false exit } if % reached eexec section
129 dup /Subrs eq { pop false exit } if % Subrs without eexec
130 dup /CharStrings eq { pop false exit } if % CharStrings without eexec
131 dup 3 index eq
132 { xcheck not { dup token exit } if } % found key
133 { pop }
134 ifelse
135 } loop
136 % Stack: key file value true (or)
137 % Stack: key file false
138 dup { 4 } { 3 } ifelse -2 roll closefile pop
139 } bind def
140/.findfontname
141 { /FontName .findfontvalue
142 } bind def
143
144% If there is no FONTPATH, try to get one from the environment.
145NOFONTPATH { /FONTPATH () def } if
146/FONTPATH where
147 { pop }
148 { /FONTPATH (GS_FONTPATH) getenv not { () } if def }
149ifelse
150FONTPATH length 0 eq { (%END FONTPATH) .skipeof } if
151/FONTPATH [ FONTPATH .pathlist ] def
152
153% Scan directories looking for plausible fonts. "Plausible" means that
154% the file begins with %!PS-AdobeFont or %!FontType1, or with \200\001
155% followed by four arbitrary bytes and then either of these strings.
156% To speed up the search, we skip any file whose name appears in
157% the Fontmap (with any extension and upper/lower case variation) already,
158% and any file whose extension definitely indicates it is not a font.
159%
160% NOTE: The current implementation of this procedure is somewhat Unix/DOS-
161% specific. It assumes that '/' and '\' are directory separators, and that
162% the part of a file name following the last '.' is the extension.
163%
164/.lowerstring % <string> .lowerstring <lowerstring>
165 { 0 1 2 index length 1 sub
166 { 2 copy get dup 65 ge exch 90 le and
167 { 2 copy 2 copy get 32 add put }
168 if pop
169 }
170 for
171 } bind def
172/.splitfilename % <dir.../base.extn> .basename <base> <extn>
173 { { (/) search { true } { (\\) search } ifelse
174 { pop pop }
175 { exit }
176 ifelse
177 }
178 loop
179 dup { (.) search { pop pop } { exit } ifelse } loop
180 2 copy eq
181 { pop () }
182 { exch dup length 2 index length 1 add sub 0 exch getinterval exch }
183 ifelse
184% Following is debugging code.
185% (*** Split => ) print 2 copy exch ==only ( ) print ==only
186% ( ***\n) print flush
187 } bind def
188/.scanfontdict 1 dict def % establish a binding
189/.scanfontbegin
190 { % Construct the table of all file names already in Fontmap.
191 currentglobal true setglobal
192 .scanfontdict dup maxlength Fontmap length 2 add .max .setmaxlength
193 Fontmap
194 { exch pop
195 { dup type /stringtype eq
caddbb58 196 { .splitfilename pop .fonttempstring copy .lowerstring cvn
2777fb4c 197 .scanfontdict exch true put
198 }
199 { pop
200 }
201 ifelse
202 }
203 forall
204 }
205 forall
206 setglobal
207 } bind def
208/.scanfontskip mark
209 % Strings are converted to names anyway, so....
210 /afm true
211 /bat true
212 /c true
213 /cmd true
214 /com true
caddbb58 215 /dir true
2777fb4c 216 /dll true
217 /doc true
218 /drv true
219 /exe true
220 /fon true
221 /fot true
222 /h true
223 /o true
224 /obj true
225 /pfm true
caddbb58 226 /pss true % Adobe Multiple Master font instances
2777fb4c 227 /txt true
228.dicttomark def
229/.scan1fontstring 128 string def
caddbb58 230/.scanfontheaders [(%!PS-Adobe*) (%!FontType*)] def
2777fb4c 2310 .scanfontheaders { length max } forall 6 add % extra for PFB header
232/.scan1fontfirst exch string def
233/.scanfontdir % <dirname> .scanfontdir -
234 { currentglobal exch true setglobal
235 QUIET not { (Scanning ) print dup print ( for fonts...) print flush } if
236 (*) 2 copy .filenamedirseparator
237 dup (\\) eq { pop (\\\\) } if % double \ for pattern match
238 exch concatstrings concatstrings
239 0 0 0 4 -1 roll % found scanned files
240 { % stack: <fontcount> <scancount> <filecount> <filename>
241 exch 1 add exch % increment filecount
242 dup .splitfilename .lowerstring
243 % stack: <fontcount> <scancount> <filecount+1> <filename>
244 % <BASE> <ext>
245 .scanfontskip exch known exch .scanfontdict exch known or
246 { pop
247 % stack: <fontcount> <scancount> <filecount+1>
248 }
249 { 3 -1 roll 1 add 3 1 roll
250 % stack: <fontcount> <scancount+1> <filecount+1> <filename>
251 dup (r) { file } .internalstopped
252 { pop pop null ()
253 % stack: <fontcount> <scancount+1> <filecount+1> <filename>
254 % null ()
255 }
256 {
257 % On some platforms, the file operator will open directories,
258 % but an error will occur if we try to read from one.
259 % Handle this possibility here.
260 dup .scan1fontfirst { readstring } .internalstopped
261 { pop pop () }
262 { pop }
263 ifelse
264 % stack: <fontcount> <scancount+1> <filecount+1>
265 % <filename> <file> <header>
266 }
267 ifelse
268 % Check for PFB file header.
269 dup (\200\001????*) .stringmatch
270 { dup length 6 sub 6 exch getinterval }
271 if
272 % Check for font file headers.
273 false .scanfontheaders
274 { 2 index exch .stringmatch or
275 }
276 forall exch pop
277 { % stack: <fontcount> <scancount+1> <filecount+1> <filename>
278 % <file>
279 dup 0 setfileposition .findfontname
280 { dup Fontmap exch known
281 { pop pop
282 }
283 { exch copystring exch
b5cb0608 284 DEBUG { dup =only (\n) print flush } if
2777fb4c 285 1 index .definefontmap
286 .splitfilename pop true .scanfontdict 3 1 roll .growput
287 % Increment fontcount.
288 3 -1 roll 1 add 3 1 roll
289 }
290 ifelse
291 }
292 { pop
293 }
294 ifelse
295 }
296 % .findfontname will have done a closefile in the above case.
297 { dup null eq { pop } { closefile } ifelse pop
298 }
299 ifelse
300 }
301 ifelse
302 }
303 .scan1fontstring filenameforall
304 QUIET
305 { pop pop pop }
306 { ( ) print =only ( files, ) print =only ( scanned, ) print
307 =only ( new fonts.\n) print flush
308 }
309 ifelse
310 setglobal
311 } bind def
312
313%END FONTPATH
314
caddbb58 315% Create the dictionary that registers the .buildfont procedure (called by
316% definefont) for each FontType.
317/buildfontdict 20 dict def
318
319% Register Type 3 fonts, which are always supported, for definefont.
320buildfontdict 3 /.buildfont3 cvx put
321
322% Register Type 0 fonts if they are supported. Strictly speaking,
323% we should do this in its own file (gs_type0.ps), but since this is
324% the only thing that would be in that file, it's simpler to put it here.
325/.buildfont0 where { pop buildfontdict 0 /.buildfont0 cvx put } if
326
2777fb4c 327% Define definefont. This is a procedure built on a set of operators
328% that do all the error checking and key insertion.
2777fb4c 329/.growfontdict
330 { % Grow the font dictionary, if necessary, to ensure room for an
331 % added entry, making sure there is at least one slot left for FID.
332 dup maxlength 1 index length sub 2 lt
333 { dup dup wcheck
334 { .growdict }
335 { .growdictlength dict .copydict }
336 ifelse
337 }
338 { dup wcheck not { dup maxlength dict .copydict } if
339 }
340 ifelse
341 } bind def
caddbb58 342/.completefont {
343 { % Check for disabled platform fonts.
2777fb4c 344 NOPLATFONTS
345 { % Make sure we leave room for FID.
346 .growfontdict dup /ExactSize 0 put
347 }
348 { % Hack: if the Encoding looks like it might be the
349 % Symbol or Dingbats encoding, load those now (for the
350 % benefit of platform font matching) just in case
351 % the font didn't actually reference them.
caddbb58 352 % Note that some types of font don't have an Encoding.
353 dup /Encoding .knownget {
354 dup length 65 ge {
355 64 get
356 dup /congruent eq { SymbolEncoding pop } if
357 /a9 eq { DingbatsEncoding pop } if
358 } {
359 pop
360 } ifelse
361 } if
2777fb4c 362 }
363 ifelse
caddbb58 364 true exch
365 dup /FontType known not {
366 % This might be a CIDFont.
367 dup /CIDFontType known {
368 /.buildcidfont where {
369 pop exch pop false exch
370 } if
371 } if
372 } if
373 exch {
374 dup /FontType get //buildfontdict exch get exec
375 } {
376 .buildcidfont
377 } ifelse
378
2777fb4c 379 DISKFONTS
380 { FontFileDirectory 2 index known
381 { dup /FontFile FontFileDirectory 4 index get .growput
382 }
383 if
384 }
385 if
caddbb58 386 readonly % stack: name fontdict
387 } stopped { /invalidfont signalerror } if
388} bind odef
389/definefont
390 { .completefont
2777fb4c 391 % If the current allocation mode is global, also enter
392 % the font in LocalFontDirectory.
caddbb58 393 .currentglobal
394 { //systemdict /LocalFontDirectory .knownget
395 { 2 index 2 index .growput }
2777fb4c 396 if
2777fb4c 397 }
caddbb58 398 if
399 dup .FontDirectory 4 -2 roll .growput
2777fb4c 400 } odef
401
402% Define a procedure for defining aliased fonts.
caddbb58 403% We use this only for explicitly aliased fonts, not substituted fonts:
404% we think this matches the observed behavior of Adobe interpreters.
2777fb4c 405/.aliasfont % <name> <font> .aliasfont <newFont>
406 { .currentglobal 3 1 roll dup .gcheck .setglobal
407 dup length 2 add dict
408 dup 3 -1 roll { 1 index /FID eq { pop pop } { put dup } ifelse } forall
409 % Stack: global fontname newfont newfont.
410 % We might be defining a global font whose FontName
411 % is a local string. This is weird, but legal,
caddbb58 412 % and doesn't cause problems anywhere else:
413 % to avoid any possible problems in this case, do a cvn.
414 % We might also be defining (as an alias) a global font
415 % whose FontName is a local non-string, if someone passed a
416 % garbage value to findfont. In this case, just don't
417 % call definefont at all.
418 2 index dup type /stringtype eq exch .gcheck or 1 index .gcheck not or
419 { /FontName 3 index dup type /stringtype eq { cvn } if put
420 % Don't bind in definefont, since Level 2 redefines it.
421 /definefont .systemvar exec
2777fb4c 422 }
caddbb58 423 { .completefont pop exch pop
2777fb4c 424 }
caddbb58 425 ifelse exch .setglobal
2777fb4c 426 } odef % so findfont will bind it
427
428% Define .loadfontfile for loading a font. If we recognize Type 1 and/or
429% TrueType fonts, gs_type1.ps and/or gs_ttf.ps will redefine this.
caddbb58 430/.loadfontfile {
431 % According to Ed Taft, Adobe interpreters push userdict
432 % before loading a font, and pop it afterwards.
433 userdict begin
434 cvx exec
435 end
436} bind def
2777fb4c 437/.loadfont
438 { % Some buggy fonts leave extra junk on the stack,
439 % so we have to make a closure that records the stack depth
440 % in a fail-safe way.
441 /.loadfontfile cvx count 1 sub 2 packedarray cvx exec
442 count exch sub { pop } repeat
443 } bind def
444
445% Find an alternate font to substitute for an unknown one.
446% We go to some trouble to parse the font name and extract
447% properties from it. Later entries take priority over earlier.
448/.substitutefaces [
449 % Guess at suitable substitutions for random unknown fonts.
450 [(Grot) /Times]
451 [(Roman) /Times]
452 [(Book) /NewCenturySchlbk]
453 % If the family name appears in the font name,
454 % use a font from that family.
455 [(Arial) /Helvetica]
456 [(Avant) /AvantGarde]
457 [(Bookman) /Bookman]
458 [(Century) /NewCenturySchlbk]
459 [(Cour) /Courier]
caddbb58 460 [(Frut) /Helvetica]
2777fb4c 461 [(Geneva) /Helvetica]
462 [(Helv) /Helvetica]
463 [(NewYork) /Times]
464 [(Pala) /Palatino]
465 [(Sans) /Helvetica]
466 [(Schlbk) /NewCenturySchlbk]
467 [(Serif) /Times]
468 [(Swiss) /Helvetica]
469 [(Times) /Times]
caddbb58 470 [(Univers) /Helvetica]
2777fb4c 471 % Substitute for Adobe Multiple Master fonts.
caddbb58 472 [(Minion) /Times]
473 [(Myriad) /Helvetica]
474 [(MyriadPkg) /Helvetica-Narrow]
2777fb4c 475 % Condensed or narrow fonts map to the only narrow family we have.
476 [(Cond) /Helvetica-Narrow]
477 [(Narrow) /Helvetica-Narrow]
478 % If the font wants to be monospace, use Courier.
479 [(Monospace) /Courier]
480 [(Typewriter) /Courier]
481] readonly def
482/.substituteproperties [
483 [(It) 1] [(Oblique) 1]
484 [(Bd) 2] [(Bold) 2] [(bold) 2] [(Demi) 2] [(Heavy) 2] [(Sb) 2]
485] readonly def
486/.substitutefamilies mark
487 /AvantGarde
488 {/AvantGarde-Book /AvantGarde-BookOblique
489 /AvantGarde-Demi /AvantGarde-DemiOblique}
490 /Bookman
491 {/Bookman-Demi /Bookman-DemiItalic /Bookman-Light /Bookman-LightItalic}
492 /Courier
493 {/Courier /Courier-Oblique /Courier-Bold /Courier-BoldOblique}
494 /Helvetica
495 {/Helvetica /Helvetica-Oblique /Helvetica-Bold /Helvetica-BoldOblique}
496 /Helvetica-Narrow
497 {/Helvetica-Narrow /Helvetica-Narrow-Oblique
498 /Helvetica-Narrow-Bold /Helvetica-Narrow-BoldOblique}
499 /NewCenturySchlbk
500 {/NewCenturySchlbk-Roman /NewCenturySchlbk-Italic
501 /NewCenturySchlbk-Bold /NewCenturySchlbk-BoldItalic}
502 /Palatino
503 {/Palatino-Roman /Palatino-Italic /Palatino-Bold /Palatino-BoldItalic}
504 /Times
505 {/Times-Roman /Times-Italic /Times-Bold /Times-BoldItalic}
506.dicttomark readonly def
507/.substitutefont % <fontname> .substitutefont <altname>
508 { % Look for properties and/or a face name in the font name.
509 % If we find any, use Helvetica as the base font;
510 % otherwise, use the default font.
511 % Note that the "substituted" font name may be the same as
512 % the requested one; the caller must check this.
caddbb58 513 dup type dup /stringtype eq exch /nametype eq or
514 { dup length string cvs } { () } ifelse
2777fb4c 515 {defaultfontname /Helvetica-Oblique /Helvetica-Bold /Helvetica-BoldOblique}
516 exch 0 exch % stack: fontname facelist properties fontname
517 % Look for a face name.
518 .substitutefaces
519 { 2 copy 0 get search
520 { pop pop pop 1 get .substitutefamilies exch get
521 4 -1 roll pop 3 1 roll
522 }
523 { pop pop
524 }
525 ifelse
526 }
527 forall
528 .substituteproperties
529 { 2 copy 0 get search
530 { pop pop pop 1 get 3 -1 roll or exch }
531 { pop pop }
532 ifelse
533 }
caddbb58 534 forall pop get exec
2777fb4c 535 % Only accept fonts known in the Fontmap.
536 Fontmap 1 index known not { pop defaultfontname } if
537 } bind def
538
539% If requested, make (and recognize) fake entries in FontDirectory for fonts
540% present in Fontmap but not actually loaded. Thanks to Ray Johnston for
541% the idea behind this code.
542FAKEFONTS not { (%END FAKEFONTS) .skipeof } if
543
544% We use the presence or absence of the FontMatrix key to indicate whether
caddbb58 545% a font is real or fake. We must pop the arguments at the very end,
546% so that stack protection will be effective.
547
548/definefont { % <name> <font> definefont <font>
549 dup /FontMatrix known {
550 //definefont
551 } {
552 2 copy /FontName get findfont //definefont exch pop exch pop
553 } ifelse
554} bind odef
555
556/scalefont { % <font> <scale> scalefont <font>
557 1 index /FontMatrix known {
558 //scalefont
559 } {
560 1 index /FontName get findfont 1 index //scalefont
561 exch pop exch pop
562 } ifelse
563} bind odef
564
565/makefont { % <font> <matrix> makefont <font>
566 1 index /FontMatrix known {
567 //makefont
568 } {
569 1 index /FontName get findfont 1 index //makefont
570 exch pop exch pop
571 } ifelse
572} bind odef
573
574/setfont { % <font> setfont -
575 dup /FontMatrix known {
576 //setfont
577 } {
578 dup /FontName get findfont //setfont pop
579 } ifelse
580} bind odef
2777fb4c 581
582%END FAKEFONTS
583
584% Define findfont so it tries to load a font if it's not found.
caddbb58 585% The Red Book requires that findfont be a procedure, not an operator,
586% but it still needs to restore the stacks reliably if it fails,
587% so we do all the work in an operator.
588/.findfont {
589 mark 1 index
590 //systemdict begin .dofindfont
591 % Define any needed aliases.
592 counttomark 1 sub { .aliasfont } repeat end
593 exch pop exch pop
594} odef
595/findfont {
596 .findfont
597} bind def
2777fb4c 598% Check whether the font name we are about to look for is already on the list
599% of aliases we're accumulating; if so, cause an error.
600/.checkalias % -mark- <alias1> ... <name> .checkalias <<same>>
601 { counttomark 1 sub -1 1
602 { index 1 index eq
603 { pop QUIET not
604 { (Unable to substitute for font.\n) print flush
605 } if
606 /findfont cvx /invalidfont signalerror
607 }
608 if
609 }
610 for
611 } bind def
612% Get a (non-fake) font if present in a FontDirectory.
613/.fontknownget % <fontdir> <fontname> .fontknownget <font> true
614 % <fontdir> <fontname> .fontknownget false
615 { .knownget
616 { FAKEFONTS
617 { dup /FontMatrix known { true } { pop false } ifelse }
618 { true }
619 ifelse
620 }
621 { false
622 }
623 ifelse
624 } bind def
625% Do the work of findfont, including substitution, defaulting, and
626% scanning of FONTPATH.
627/.dofindfont % <fontname> .dofindfont <font>
628 { { .tryfindfont { exit } if
629 % We didn't find the font. If we haven't scanned
630 % all the directories in FONTPATH, scan the next one now,
631 % and look for the font again.
632 null 0 1 FONTPATH length 1 sub
633 { FONTPATH 1 index get null ne { exch pop exit } if pop
634 }
635 for dup null ne
636 { dup 0 eq { .scanfontbegin } if
637 FONTPATH 1 index get .scanfontdir
638 FONTPATH exch null put
639 % Start over with an empty alias list.
640 counttomark 1 sub { pop } repeat
641 .dofindfont exit
642 }
643 if pop
caddbb58 644 % No luck. Make sure we're not already
645 % looking for the default font.
2777fb4c 646 dup defaultfontname eq
647 { QUIET not
648 { (Unable to load default font ) print
649 dup =only (! Giving up.\n) print flush
650 }
651 if /findfont cvx /invalidfont signalerror
652 }
2777fb4c 653 if
caddbb58 654 % Substitute for the font. Don't alias.
655 /SUBSTFONT where {
656 pop QUIET not {
657 (Substituting for font ) print dup =only
658 (.\n) print flush
659 } if
660 cleartomark mark defaultfontname
661 } {
662 dup .substitutefont
663 2 copy eq { pop defaultfontname } if
664 .checkalias
665 QUIET not {
666 (Substituting font ) print dup =only ( for ) print
667 1 index =only (.\n) print flush
668 } if
669 % Remove all the accumulated aliases.
670 counttomark 1 add 1 roll cleartomark mark exch
671 } ifelse
2777fb4c 672 }
673 loop
674 } bind def
675% Try to find a font using only the present contents of Fontmap.
676/.tryfindfont % <fontname> .tryfindfont <font> true
677 % <fontname> .tryfindfont false
caddbb58 678 { .FontDirectory 1 index .fontknownget
2777fb4c 679 { % Already loaded
680 exch pop true
681 }
682 { dup Fontmap exch .knownget not
caddbb58 683 { % Unknown font name. Look for a file with the
684 % same name as the requested font.
685 dup dup type /nametype eq { .namestring } if .loadfontloop
2777fb4c 686 }
2777fb4c 687 { % Try each element of the Fontmap in turn.
caddbb58 688 false exch % (in case we exhaust the list)
689 % Stack: fontname false fontmaplist
2777fb4c 690 { exch pop
691 dup type /nametype eq
692 { % Font alias
693 .checkalias .tryfindfont exit
694 }
695 { dup dup type dup /arraytype eq exch /packedarraytype eq or exch xcheck and
696 { % Font with a procedural definition
697 exec % The procedure will load the font.
698 % Check to make sure this really happened.
caddbb58 699 .FontDirectory 1 index .knownget
2777fb4c 700 { exch pop true exit }
701 if
702 }
703 { % Font file name
704 .loadfontloop { true exit } if
705 }
706 ifelse
707 }
708 ifelse false
709 }
caddbb58 710 forall
711 % Stack: font true -or- fontname false
712 { true
713 }
714 { % None of the Fontmap entries worked.
715 % Try loading a file with the same name
716 % as the requested font.
717 dup dup type /nametype eq { .namestring } if .loadfontloop
718 }
719 ifelse
2777fb4c 720 }
721 ifelse
722 }
723 ifelse
724 } bind def
725% Attempt to load a font from a file.
726/.loadfontloop % <filename> .loadfontloop <font> true
727 % <filename> .loadfontloop false
728 { % See above regarding the use of 'loop'.
729
730 {
caddbb58 731 % Is the font name a string?
732 dup type /stringtype ne
733 { QUIET not
734 { (Can't find font with non-string name: ) print dup =only (.\n) print flush
735 }
736 if pop false exit
737 }
738 if
2777fb4c 739 % Can we open the file?
740 findlibfile not
741 { QUIET not
742 { (Can't find \(or can't open\) font file ) print dup print
743 (.\n) print flush
744 }
745 if pop false exit
746 }
747 if
748
749 % Stack: fontname fontfilename fontfile
750 DISKFONTS
751 { .currentglobal true .setglobal
752 2 index (r) file
753 FontFileDirectory exch 5 index exch .growput
754 .setglobal
755 }
756 if
757 QUIET not
758 { (Loading ) print 2 index =only
759 ( font from ) print 1 index print (... ) print flush
760 }
761 if
762 % If LOCALFONTS isn't set, load the font into local or global
763 % VM according to FontType; if LOCALFONTS is set, load the font
764 % into the current VM, which is what Adobe printers (but not
765 % DPS or CPSI) do.
766 LOCALFONTS { false } { /setglobal where } ifelse
767 { pop /FontType .findfontvalue { 1 eq } { false } ifelse
768 % .setglobal, like setglobal, aliases FontDirectory to
769 % GlobalFontDirectory if appropriate. However, we mustn't
770 % allow the current version of .setglobal to be bound in,
771 % because it's different depending on language level.
caddbb58 772 .currentglobal exch /.setglobal .systemvar exec
2777fb4c 773 % Remove the fake definition, if any.
caddbb58 774 .FontDirectory 3 index .undef
775 1 index (r) file .loadfont .FontDirectory exch
776 /.setglobal .systemvar exec
2777fb4c 777 }
caddbb58 778 { .loadfont .FontDirectory
2777fb4c 779 }
780 ifelse
781 % Stack: fontname fontfilename fontdirectory
782 QUIET not
783 { //systemdict /level2dict known
784 { .currentglobal false .setglobal vmstatus
785 true .setglobal vmstatus 3 -1 roll pop
786 6 -1 roll .setglobal 5
787 }
788 { vmstatus 3
789 }
790 ifelse { =only ( ) print } repeat
791 (done.\n) print flush
792 } if
793
794 % Check to make sure the font was actually loaded.
795 dup 3 index .fontknownget
796 { 4 1 roll pop pop pop true exit } if
797
798 % Maybe the file had a different FontName.
799 % See if we can get a FontName from the file, and if so,
800 % whether a font by that name exists now.
801 exch (r) file .findfontname
802 { 2 copy .fontknownget
803 { % Yes. Stack: origfontname fontdirectory filefontname fontdict
804 3 -1 roll pop exch
805 QUIET
806 { pop
807 }
808 { (Using ) print =only
809 ( font for ) print 1 index =only
810 (.\n) print flush
811 }
812 ifelse true exit
813 }
814 if pop
815 }
816 if pop
817
818 % The font definitely did not load correctly.
819 QUIET not
820 { (Loading ) print dup =only
821 ( font failed.\n) print flush
822 } if
823 false exit
824
825 } loop % end of loop
826
827 } bind def
828
829% Define a procedure to load all known fonts.
830% This isn't likely to be very useful.
831/loadallfonts
832 { Fontmap { pop findfont pop } forall
833 } bind def
834
835% If requested, load all the fonts defined in the Fontmap into FontDirectory
caddbb58 836% as "fake" fonts i.e., font dicts with only FontName and FontType defined.
837% (We define FontType only for the sake of some questionable code in the
838% Apple Printer Utility 2.0 font inquiry code.)
839%
840% Note that this procedure only creates fake fonts in the FontDirectory
841% associated with the current VM. This is because in multi-context systems,
842% creating the fake fonts in local VM leads to undesirable complications.
2777fb4c 843/.definefakefonts
844 {
845 }
caddbb58 846 {
847 (gs_fonts FAKEFONTS) VMDEBUG
848 Fontmap {
849 pop dup type /stringtype eq { cvn } if
850 .FontDirectory 1 index known not {
851 2 dict dup /FontName 3 index put
852 dup /FontType 1 put
853 .FontDirectory 3 1 roll put
854 } {
855 pop
856 } ifelse
857 } forall
2777fb4c 858 }
caddbb58 859FAKEFONTS { exch } if pop def % don't bind, .current/setglobal get redefined
2777fb4c 860
861% Install initial fonts from Fontmap.
862/.loadinitialfonts
863 { NOFONTMAP not
864 { /FONTMAP where
865 { pop [ FONTMAP .pathlist ]
866 { dup VMDEBUG findlibfile
867 { exch pop .loadFontmap }
868 { /undefinedfilename signalerror }
869 ifelse
870 }
871 }
872 { LIBPATH
873 { defaultfontmap 2 copy .filenamedirseparator
874 exch concatstrings concatstrings dup VMDEBUG
875 (r) { file } .internalstopped
876 { pop pop } { .loadFontmap } ifelse
877 }
878 }
879 ifelse forall
880 }
881 if
caddbb58 882 .definefakefonts % current VM is global
2777fb4c 883 } def % don't bind, .current/setglobal get redefined
caddbb58 884
885% ---------------- Synthetic font support ---------------- %
886
887% Create a new font by modifying an existing one. paramdict contains
888% entries with the same keys as the ones found in a Type 1 font;
889% it should also contain enough empty entries to allow adding the
890% corresponding non-overridden entries from the original font dictionary,
891% including FID. If paramdict includes a FontInfo entry, this will
892% also override the original font's FontInfo, entry by entry;
893% again, it must contain enough empty entries.
894
895% Note that this procedure does not perform a definefont.
896
897/.makemodifiedfont % <fontdict> <paramdict> .makemodifiedfont <fontdict'>
898 { exch
899 { % Stack: destdict key value
900 1 index /FID ne
901 { 2 index 2 index known
902 { % Skip fontdict entry supplied in paramdict, but
903 % handle FontInfo specially.
904 1 index /FontInfo eq
905 { 2 index 2 index get % new FontInfo
906 1 index % old FontInfo
907 { % Stack: destdict key value destinfo key value
908 2 index 2 index known
909 { pop pop }
910 { 2 index 3 1 roll put }
911 ifelse
912 }
913 forall pop
914 }
915 if
916 }
917 { % No override, copy the fontdict entry.
918 2 index 3 1 roll put
919 dup dup % to match pop pop below
920 }
921 ifelse
922 }
923 if
924 pop pop
925 } forall
926 } bind def
927
928% Make a modified font and define it. Note that unlike definefont,
929% this does not leave the font on the operand stack.
930
931/.definemodifiedfont % <fontdict> <paramdict> .definemodifiedfont -
932 { .makemodifiedfont
933 dup /FontName get exch definefont pop
934 } bind def