You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1375 lines
48 KiB

1 month ago
  1. % Copyright (C) 2001-2023 Artifex Software, Inc.
  2. % All Rights Reserved.
  3. %
  4. % This software is provided AS-IS with no warranty, either express or
  5. % implied.
  6. %
  7. % This software is distributed under license and may not be copied,
  8. % modified or distributed except as expressly authorized under the terms
  9. % of the license contained in the file LICENSE in this distribution.
  10. %
  11. % Refer to licensing information at http://www.artifex.com or contact
  12. % Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
  13. % CA 94129, USA, for further information.
  14. %
  15. % Font initialization and management code.
  16. % Define the default font.
  17. /defaultfontname /Courier def
  18. % Define the name of the font map file.
  19. % Note that the "%%Replace " comment below provides the font map file name
  20. % for compiling initialization files into executable. Most likely it should be
  21. % consistent with the one specified here.
  22. /FONTMAP where
  23. {/FONTMAP get /defaultfontmap exch def}
  24. {/defaultfontmap (Fontmap) def}
  25. ifelse
  26. % we have to set .languagelevel to 2 so the parser will accept the names
  27. % '<<' and '>>', then we use a local definition here.
  28. .languagelevel 2 .setlanguagelevel
  29. /defaultfontmap_content 50 dict
  30. 4 dict begin
  31. (<<) cvn /mark load def
  32. (>>) cvn /.dicttomark load def
  33. /; { 2 index 3 1 roll .growput }.internalbind def
  34. %% Replace 0 (Fontmap)
  35. end def
  36. .setlanguagelevel
  37. % ------ End of editable parameters ------ %
  38. % Define the UniqueIDs and organization XUID assigned to Artifex.
  39. % UniqueIDs 5,066,501 - 5,066,580 are assigned as follows:
  40. % 01 and 02 for shareware Cyrillic
  41. % 33 through 67 for Type 1 versions of the Hershey fonts
  42. % UniqueIDs 5,115,501 - 5,115,600 are currently unassigned.
  43. /AladdinEnterprisesXUID 107 def
  44. % If SUBSTFONT is defined, make it the default font.
  45. /SUBSTFONT where { pop /defaultfontname /SUBSTFONT load def } if
  46. % Define a reliable way of accessing FontDirectory in systemdict.
  47. /.FontDirectory
  48. { /FontDirectory .systemvar
  49. } .forcebind odef
  50. % Define a temporary string for local use, since using =string
  51. % interferes with some PostScript programs.
  52. /.fonttempstring 8192 string def
  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. }.internalbind def
  61. % <dir.../base.extn> .basename <dir>
  62. /.splitdirname {
  63. (/) rsearch { //true } { (\\) rsearch } ifelse
  64. {exch concatstrings exch pop //true}{//false} ifelse
  65. }.internalbind def
  66. % <dict> .addfontmappermitpaths
  67. % As fontmap can contain a *lot* of individual entries
  68. % we split off the filenames, and add directories to the
  69. % allowed paths.
  70. % We accumulate the paths in a dictionary, then iterate
  71. % the dictionary adding the paths to the PermitReading
  72. % list. This leverages the efficiency of dictionaries
  73. % handling duplicate keys.
  74. /.addfontmappermitpaths
  75. {
  76. dup length dict begin
  77. {
  78. exch pop dup type /stringtype eq
  79. {//.splitdirname exec {dup def} {pop} ifelse}
  80. {pop}
  81. ifelse
  82. } forall
  83. currentdict end
  84. {exch pop /PermitFileReading exch .addcontrolpath}forall
  85. }.internalbind def
  86. defaultfontmap_content length 0 gt
  87. {defaultfontmap_content .addfontmappermitpaths} if
  88. % Load a font name -> font file name map.
  89. userdict /Fontmap .FontDirectory maxlength dict put
  90. userdict /.nativeFontmap .FontDirectory maxlength dict put
  91. /.loadFontmap { % <file> .loadFontmap -
  92. % We would like to simply execute .definefontmap as we read,
  93. % but we have to maintain backward compatibility with an older
  94. % specification that makes later entries override earlier
  95. % ones within the same file.
  96. 50 dict exch .readFontmap
  97. dup //.addfontmappermitpaths exec
  98. { .definefontmap } forall
  99. }.internalbind def
  100. /.readFontmap { % <dict> <file> .readFontmap <dict>
  101. { dup token not { closefile exit } if
  102. % stack: dict file fontname
  103. % This is a hack to get around the absurd habit of MS-DOS editors
  104. % of adding an EOF character at the end of the file.
  105. dup (\032) eq { pop closefile exit } if
  106. 1 index token not
  107. { (Fontmap entry for ) print dup =only
  108. ( has no associated file or alias name! Giving up.) = flush
  109. {.readFontmap} 0 get 1 .quit
  110. } if
  111. dup type dup /stringtype eq exch /nametype eq or not
  112. { (Fontmap entry for ) print 1 index =only
  113. ( has an invalid file or alias name! Giving up.) = flush
  114. {.readFontmap} 0 get 1 .quit
  115. } if
  116. % stack: dict file fontname filename|aliasname
  117. dup type /nametype eq
  118. {
  119. dup (<<) cvn eq
  120. {
  121. pop mark
  122. {
  123. counttomark 2 add index token not {//false exit} if
  124. dup (>>) cvn eq {pop //true exit} if
  125. } loop
  126. { .dicttomark }{cleartomark} ifelse
  127. } if
  128. } if
  129. 1 index type /stringtype eq
  130. 1 index type /nametype eq and 1 index xcheck and
  131. 1 index /run eq 2 index /.runlibfile eq or and {
  132. % This is an inclusion entry.
  133. pop findlibfile { exch pop } { file } ifelse
  134. 2 index exch .readFontmap pop
  135. } {
  136. % This is a real entry.
  137. % Read and pop tokens until a semicolon.
  138. { 2 index token not
  139. { (Fontmap entry for ) print 1 index =only
  140. ( ends prematurely! Giving up.) = flush
  141. {//.loadFontmap exec} 0 get 1 .quit
  142. } if
  143. dup /; eq { pop 3 index 3 1 roll .growput exit } if
  144. pop
  145. } loop
  146. } ifelse
  147. } loop
  148. }.internalbind def
  149. % Add an entry in Fontmap. We redefine this if the Level 2
  150. % resource machinery is loaded.
  151. /.definefontmapaux % <bool> <fontname> <file|alias> .definefontmapaux -
  152. { % Since Fontmap is global, make sure the values are storable.
  153. % If the fontname contains Unicode (first byte == \000) and
  154. % this is not an alias definition, define an alias using ASCII
  155. % (stripping out the high \000 bytes). Observed with some TT fonts.
  156. 1 index 100 string cvs
  157. dup length 0 gt {
  158. 0 get 0 eq 1 index type /nametype ne and {
  159. 1 index 100 string cvs dup length 2 div cvi string //true exch
  160. 0 1 2 index length 1 sub {
  161. % stack: fontname filename fontnamestring addflag newstring index
  162. dup 4 index exch 2 mul get 0 ne {
  163. % High byte of pair is not \000
  164. pop pop //false exch
  165. exit
  166. } if
  167. dup 4 index exch 2 mul 1 add get 2 index 3 1 roll put
  168. } for
  169. exch {
  170. DEBUG { (\nAdding alias for: ) print 1 index ==only ( as: ) print dup //== exec flush } if
  171. cvn exch cvn .definefontmapaux % recurse with an alias
  172. } {
  173. pop pop % discard the name
  174. } ifelse
  175. } if
  176. } {
  177. pop
  178. } ifelse
  179. .currentglobal 3 1 roll //true .setglobal
  180. dup type /stringtype eq
  181. { dup .gcheck not { dup length string copy } if
  182. }
  183. if
  184. 4 -1 roll {.nativeFontmap}{Fontmap} ifelse
  185. 3 -1 roll 2 copy .knownget
  186. { % Add an element to the end of the existing value,
  187. % unless it's the same as the current last element.
  188. mark exch aload pop counttomark 4 add -1 roll
  189. 2 copy eq { cleartomark pop pop } { ] readonly .growput } ifelse
  190. }
  191. { % Make a new entry.
  192. mark 4 -1 roll ] readonly .growput
  193. }
  194. ifelse .setglobal
  195. }.internalbind def
  196. /.definefontmap % <fontname> <file|alias> .definefontmap -
  197. {
  198. //false 3 1 roll //.definefontmapaux exec
  199. }.internalbind def
  200. /.definenativefontmap % <fontname> <file|alias> .definenativefontmap -
  201. {
  202. //true 3 1 roll //.definefontmapaux exec
  203. }.internalbind def
  204. % Parse a font file just enough to find the FontName or FontType.
  205. /.findfontvalue { % <file> <key> .findfontvalue <value> true
  206. % <file> <key> .findfontvalue false
  207. % Closes the file in either case.
  208. exch dup read {
  209. 2 copy .unread 16#80 eq {
  210. dup (xxxxxx) readstring pop pop % skip .PFB header
  211. } if
  212. { % Stack: key file
  213. % Protect ourselves against syntax errors here.
  214. dup { token } stopped { //false exit } if
  215. not { //false exit } if % end of file
  216. dup /eexec eq { pop //false exit } if % reached eexec section
  217. dup /Subrs eq { pop //false exit } if % Subrs without eexec
  218. dup /CharStrings eq { pop //false exit } if % CharStrings without eexec
  219. dup 3 index eq
  220. { xcheck not { dup token exit } if } % found key
  221. { pop }
  222. ifelse
  223. } loop
  224. % Stack: key file value true (or)
  225. % Stack: key file false
  226. dup { 4 } { 3 } ifelse -2 roll closefile pop
  227. } { closefile pop //false } ifelse
  228. }.internalbind def
  229. /.findfontname
  230. { /FontName .findfontvalue
  231. }.internalbind def
  232. % If there is no FONTPATH, try to get one from the environment.
  233. NOFONTPATH { /FONTPATH () def } if
  234. /FONTPATH where
  235. { pop }
  236. { /FONTPATH (GS_FONTPATH) getenv not { () } if def }
  237. ifelse
  238. % The following are dummy definitions that, if we have a FONTPATH, will
  239. % be replaced in the following section.
  240. % They are here so immediately evaulation will work, and allow them to
  241. % undefined at the bottom of the file.
  242. /.scanfontbegin{}.internalbind def
  243. /.scanfontdir {}.internalbind def
  244. FONTPATH length 0 eq { (%END FONTPATH) .skipeof } if
  245. /FONTPATH [ FONTPATH .pathlist ] def
  246. FONTPATH
  247. {
  248. /PermitFileReading exch .addcontrolpath
  249. } forall
  250. % Scan directories looking for plausible fonts. "Plausible" means that
  251. % the file begins with %!PS-AdobeFont or %!FontType1, or with \200\001
  252. % followed by four arbitrary bytes and then either of these strings.
  253. % To speed up the search, we skip any file whose name appears in
  254. % the Fontmap (with any extension and upper/lower case variation) already,
  255. % and any file whose extension definitely indicates it is not a font.
  256. %
  257. % NOTE: The current implementation of this procedure is somewhat Unix/DOS-
  258. % specific. It assumes that '/' and '\' are directory separators, and that
  259. % the part of a file name following the last '.' is the extension.
  260. %
  261. /.lowerstring % <string> .lowerstring <lowerstring>
  262. { 0 1 2 index length 1 sub
  263. { 2 copy get dup 65 ge exch 90 le and
  264. { 2 copy 2 copy get 32 add put }
  265. if pop
  266. }
  267. for
  268. }.internalbind def
  269. /.splitfilename { % <dir.../base.extn> .basename <base> <extn>
  270. % Make the file name read-only to detect aliasing bugs.
  271. % We really don't like doing this, but we've had one
  272. % such bug already.
  273. readonly {
  274. (/) search { //true } { (\\) search } ifelse { pop pop } { exit } ifelse
  275. } loop
  276. dup { (.) search { pop pop } { exit } ifelse } loop
  277. 2 copy eq {
  278. pop ()
  279. } {
  280. exch dup length 2 index length 1 add sub 0 exch getinterval exch
  281. } ifelse
  282. }.internalbind def
  283. /.scanfontdict 1 dict def % establish a binding
  284. /.scanfontbegin
  285. { % Construct the table of all file names already in Fontmap.
  286. currentglobal //true setglobal
  287. //.scanfontdict dup maxlength Fontmap length 2 add .max .setmaxlength
  288. Fontmap
  289. { exch pop
  290. { dup type /stringtype eq
  291. { //.splitfilename exec pop //.fonttempstring copy //.lowerstring exec cvn
  292. //.scanfontdict exch //true put
  293. }
  294. { pop
  295. }
  296. ifelse
  297. }
  298. forall
  299. }
  300. forall
  301. setglobal
  302. }.internalbind def
  303. /.scanfontskip mark
  304. % Strings are converted to names anyway, so....
  305. /afm //true
  306. /bat //true
  307. /c //true
  308. /cmd //true
  309. /com //true
  310. /dir //true
  311. /dll //true
  312. /doc //true
  313. /drv //true
  314. /exe //true
  315. /fon //true
  316. /fot //true
  317. /h //true
  318. /o //true
  319. /obj //true
  320. /pfm //true
  321. /pss //true % Adobe Multiple Master font instances
  322. /txt //true
  323. .dicttomark def
  324. /.scan1fontstring 8192 string def
  325. % BeginFont: is not per Adobe documentation, but a few fonts have it.
  326. /.scanfontheaders [(%!PS-Adobe*) (%!FontType*) (%%BeginFont:*)] def
  327. 0 /.scanfontheaders .systemvar { length .max } forall 6 add % extra for PFB header
  328. /.scan1fontfirst exch string def
  329. /.scanfontdir % <dirname> .scanfontdir -
  330. { currentglobal exch //true setglobal
  331. QUIET not { (Scanning ) print dup print ( for fonts...) print flush } if
  332. [ 1 index ] (*) .generate_dir_list_templates
  333. 0 0 0 4 -1 roll % found scanned files
  334. { % stack: <fontcount> <scancount> <filecount> <filename>
  335. exch 1 add exch % increment filecount
  336. dup //.splitfilename exec //.fonttempstring copy //.lowerstring exec
  337. % stack: <fontcount> <scancount> <filecount+1> <filename>
  338. % <BASE> <ext>
  339. //.scanfontskip exch known exch //.scanfontdict exch known or
  340. { pop
  341. % stack: <fontcount> <scancount> <filecount+1>
  342. }
  343. { 3 -1 roll 1 add 3 1 roll
  344. % stack: <fontcount> <scancount+1> <filecount+1> <filename>
  345. dup (r) { file } //.internalstopped exec
  346. { pop pop //null ()
  347. % stack: <fontcount> <scancount+1> <filecount+1> <filename>
  348. % null ()
  349. }
  350. {
  351. % On some platforms, the file operator will open directories,
  352. % but an error will occur if we try to read from one.
  353. % Handle this possibility here.
  354. dup //.scan1fontfirst { readstring } //.internalstopped exec
  355. { pop pop () }
  356. { pop }
  357. ifelse
  358. % stack: <fontcount> <scancount+1> <filecount+1>
  359. % <filename> <file> <header>
  360. }
  361. ifelse
  362. % Check for PFB file header.
  363. dup (\200\001????*) .stringmatch
  364. { dup length 6 sub 6 exch getinterval }
  365. if
  366. % Check for font file headers.
  367. //false /.scanfontheaders .systemvar
  368. { 2 index exch .stringmatch or
  369. }
  370. forall exch pop
  371. { % stack: <fontcount> <scancount+1> <filecount+1> <filename>
  372. % <file>
  373. dup 0 setfileposition //.findfontname exec
  374. { dup .nativeFontmap exch known
  375. { pop pop
  376. }
  377. { exch
  378. dup length string copy % copy string
  379. exch
  380. DEBUG { ( ) print dup =only flush } if
  381. 1 index //.definenativefontmap exec
  382. //.splitfilename exec pop //true //.scanfontdict 3 1 roll .growput
  383. % Increment fontcount.
  384. 3 -1 roll 1 add 3 1 roll
  385. }
  386. ifelse
  387. }
  388. { pop
  389. }
  390. ifelse
  391. }
  392. % .findfontname will have done a closefile in the above case.
  393. { dup //null eq { pop } { closefile } ifelse pop
  394. }
  395. ifelse
  396. }
  397. ifelse
  398. }
  399. //.scan1fontstring filenameforall
  400. QUIET
  401. { pop pop pop }
  402. { ( ) print =only ( files, ) print =only ( scanned, ) print
  403. =only ( new fonts.) = flush
  404. }
  405. ifelse
  406. pop
  407. setglobal
  408. }.internalbind def
  409. %END FONTPATH
  410. /FONTMAP where
  411. {
  412. dup /FONTMAP get /FONTMAP exch [ exch //.pathlist exec] put
  413. /FONTMAP dup where pop exch get {/PermitFileReading exch .addcontrolpath} forall
  414. } if
  415. % Try to enumerate native fonts registered with the os
  416. % and add them to the fontmap. This relies on a custom
  417. % operator which calls platform-specific C code. It
  418. % returns an array of arrays, each containing a pair
  419. % of strings: what the system thinks is the ps name,
  420. % and the access path.
  421. /.setnativefontmapbuilt { % set whether we've been run
  422. dup type /booleantype eq {
  423. systemdict exch /.nativefontmapbuilt exch .forceput
  424. } executeonly
  425. {pop}
  426. ifelse
  427. } .forcebind odef
  428. systemdict /NONATIVEFONTMAP known .setnativefontmapbuilt
  429. /.buildnativefontmap { % - .buildnativefontmap <bool>
  430. systemdict /.nativefontmapbuilt .knownget not
  431. { //false} if
  432. {//false}
  433. {
  434. QUIET not {
  435. (Querying operating system for font files...\n)
  436. print flush
  437. } if
  438. .getnativefonts dup
  439. {
  440. exch
  441. {
  442. % stack: [ (name) (path) ]
  443. % verify the font name ourselves
  444. dup 1 get (r) { file } //.internalstopped exec
  445. {
  446. % skip the entry if we can't open the returned path
  447. pop pop pop
  448. }{
  449. % we could open the font file
  450. mark 2 1 roll
  451. {//.findfontname exec} //.internalstopped exec
  452. {
  453. cleartomark
  454. pop
  455. }
  456. {
  457. counttomark 1 add -1 roll pop
  458. not { dup 0 get } if % stack: (newname) [ (name) (path) ]
  459. % DEBUG { ( found ) print dup print (\n) print flush } if
  460. % add entry to the fontmap
  461. 1 index exch 0 exch dup type /nametype ne {cvn} if put
  462. aload pop //.definenativefontmap exec
  463. } ifelse
  464. } ifelse
  465. } forall
  466. } if
  467. % record that we've been run
  468. //true //.setnativefontmapbuilt
  469. } ifelse
  470. }.internalbind odef
  471. % Create the dictionary that registers the .buildfont procedure
  472. % (called by definefont) for each FontType.
  473. /buildfontdict 20 dict def
  474. % Register Type 3 fonts, which are always supported, for definefont.
  475. buildfontdict 3 /.buildfont3 cvx put
  476. % Register Type 0 fonts if they are supported. Strictly speaking,
  477. % we should do this in its own file (gs_type0.ps), but since this is
  478. % the only thing that would be in that file, it's simpler to put it here.
  479. /.buildfont0 where { pop buildfontdict 0 /.buildfont0 cvx put } if
  480. % Define definefont. This is a procedure built on a set of operators
  481. % that do all the error checking and key insertion.
  482. /.growfontdict
  483. { % Grow the font dictionary, if necessary, to ensure room for an
  484. % added entry, making sure there is at least one slot left for FID.
  485. dup maxlength 1 index length sub 2 lt
  486. { dup dup wcheck
  487. { //.growdict exec}
  488. { //.growdictlength exec dict .copydict }
  489. ifelse
  490. }
  491. { dup wcheck not { dup maxlength dict .copydict } if
  492. }
  493. ifelse
  494. }.internalbind def
  495. /.completefont {
  496. { % Check for disabled platform fonts.
  497. NOPLATFONTS
  498. { % Make sure we leave room for FID.
  499. //.growfontdict exec dup /ExactSize 0 put
  500. }
  501. { % Hack: if the Encoding looks like it might be the
  502. % Symbol or Dingbats encoding, load those now (for the
  503. % benefit of platform font matching) just in case
  504. % the font didn't actually reference them.
  505. % Note that some types of font don't have an Encoding.
  506. dup /Encoding .knownget {
  507. dup length 65 ge {
  508. 64 get
  509. dup /congruent eq { SymbolEncoding pop } if
  510. /a9 eq { DingbatsEncoding pop } if
  511. } {
  512. pop
  513. } ifelse
  514. } if
  515. }
  516. ifelse
  517. dup /OrigFont known not {
  518. dup dup /OrigFont exch .growput
  519. } if
  520. //true exch
  521. % If this is a CIDFont, CIDFontType takes precedence
  522. % over FontType.
  523. dup /CIDFontType known {
  524. /.buildcidfont where {
  525. pop exch not exch % true => false
  526. } if
  527. } if
  528. exch {
  529. dup /FontType get //buildfontdict exch get
  530. } {
  531. {.buildcidfont} % so it gets bound
  532. } ifelse
  533. } stopped { $error /command get /invalidfont signalerror } if
  534. % Execute the .buildxxxfontx outside the 'stopped', because we don't
  535. % want its errors converted to invalidfont.
  536. exec
  537. {
  538. systemdict /ProvideUnicode .knownget not { //false } if {
  539. /FontEmulationProcs /ProcSet findresource
  540. /ProvideUnicodeDecoding get exec
  541. } if
  542. readonly % stack: name fontdict
  543. } stopped { $error /command get /invalidfont signalerror } if
  544. }.internalbind odef
  545. /definefont
  546. { dup rcheck not {
  547. /definefont cvx /invalidaccess signalerror
  548. } if
  549. /definefont cvx {.completefont} .errorexec
  550. % If the current allocation mode is global, also enter
  551. % the font in LocalFontDirectory.
  552. .currentglobal
  553. { //systemdict /LocalFontDirectory .knownget
  554. { 2 index 2 index .forceput } % readonly
  555. if
  556. }
  557. if
  558. dup //.FontDirectory 4 -2 roll .forceput % readonly
  559. % If the font originated as a resource, register it.
  560. currentfile .currentresourcefile eq { dup .registerfont } if
  561. readonly
  562. } .forcebind odef
  563. % Define a procedure for defining aliased fonts.
  564. % We use this only for explicitly aliased fonts, not substituted fonts:
  565. % we think this matches the observed behavior of Adobe interpreters.
  566. /.aliasfont % <name> <font> .aliasfont <newFont>
  567. {
  568. currentglobal 3 1 roll dup gcheck setglobal
  569. % <bool> <name> <font>
  570. dup length 2 add dict % <bool> <name> <font> <dict>
  571. dup 3 -1 roll % <bool> <name> <dict> <dict> <font>
  572. { 1 index /FID eq { pop pop } { put dup } ifelse } forall
  573. % <bool> <name> <dict> <dict>
  574. % Stack: global fontname newfont newfont.
  575. % We might be defining a global font whose FontName
  576. % is a local string. This is weird, but legal,
  577. % and doesn't cause problems anywhere else:
  578. % to avoid any possible problems in this case, do a cvn.
  579. % We might also be defining (as an alias) a global font
  580. % whose FontName is a local non-string, if someone passed a
  581. % garbage value to findfont. In this case, just don't
  582. % call definefont at all.
  583. 2 index dup type /stringtype eq exch gcheck or 1 index gcheck not or
  584. { pop % <bool> <name> <dict>
  585. 1 index dup type /stringtype eq { cvn } if
  586. % <bool> <name> <dict> <name1>
  587. % HACK:
  588. % We want to know whether we alias a font,
  589. % because in this case its FontName to be replaced with the alias.
  590. % There is no simple way to know that at this point.
  591. % But if the original font has defaultfontname,
  592. % we probably substitute it rather than alias.
  593. % Using such condition as an approximation to the strong condition.
  594. %
  595. % Note it works wrongly if Fontmap maps something to defaultfontname like this :
  596. % /Courier /NimbusMonL-Regu ;
  597. % /Something /Courier ;
  598. % The FontName of Something will not be /Something. It will be /Courier .
  599. %
  600. 1 index /FontName get defaultfontname ne {
  601. 2 copy /FontName exch put
  602. } if
  603. 1 index exch /.Alias exch put % <bool> <name> <dict>
  604. dup dup /OrigFont exch .growput
  605. % Don't bind in definefont, since Level 2 redefines it.
  606. /definefont .systemvar exec
  607. }
  608. {
  609. /findfont cvx {.completefont} //.errorexec exec pop exch pop
  610. }
  611. ifelse
  612. exch setglobal
  613. }.internalbind odef % so findfont will bind it
  614. % Define .loadfontfile for loading a font. If we recognize Type 1 and/or
  615. % TrueType fonts, gs_type1.ps and/or gs_ttf.ps will redefine this.
  616. /.loadfontfile {
  617. % According to Ed Taft, Adobe interpreters push userdict
  618. % before loading a font, and pop it afterwards.
  619. userdict begin
  620. cvx exec
  621. end
  622. }.internalbind def
  623. /.setloadingfont {
  624. //systemdict /.loadingfont 3 -1 roll .forceput
  625. } .forcebind odef % .forceput must be bound and hidden
  626. /.loadfont
  627. { % Some buggy fonts leave extra junk on the stack,
  628. % so we have to make a closure that records the stack depth
  629. % in a fail-safe way.
  630. //true .setloadingfont
  631. { /FAPI_hook_disable pop % gs_fapi accesses this with execstack_lookup - don't remove !
  632. {{.loadfontfile} .execasresource} count 1 sub 2 .execn
  633. count exch sub { pop } repeat
  634. exit
  635. } loop % this loop is a pattern for execstack_lookup, don't remove !
  636. //false .setloadingfont
  637. }.internalbind def
  638. % Find an alternate font to substitute for an unknown one.
  639. % We go to some trouble to parse the font name and extract
  640. % properties from it. Later entries take priority over earlier.
  641. /.substitutefaces [
  642. % Define substitutes for the fonts we define in Fontmap.GS
  643. [(Charter) /Times 0]
  644. [(Utopia) /Times 0]
  645. [(Antiqua) /Times 0]
  646. [(Calligraphic) /Helvetica 0]
  647. [(Hershey) /Times 0]
  648. % Guess at suitable substitutions for random unknown fonts.
  649. [(Book) /NewCenturySchlbk 0]
  650. [(Grot) /Helvetica 0]
  651. [(Roman) /Times 0]
  652. [(Chancery) /ZapfChancery-MediumItalic 0]
  653. % If the family name appears in the font name,
  654. % use a font from that family.
  655. [(Arial) /Helvetica 0]
  656. [(Avant) /AvantGarde 0]
  657. [(Bookman) /Bookman 0]
  658. [(Century) /NewCenturySchlbk 0]
  659. [(Cour) /Courier 0]
  660. [(Frut) /Helvetica 0]
  661. [(Garamond) /Palatino 0]
  662. [(Geneva) /Helvetica 0]
  663. [(Helv) /Helvetica 0]
  664. [(NewYork) /Bookman 0]
  665. [(Pala) /Palatino 0]
  666. [(Schlbk) /NewCenturySchlbk 0]
  667. [(Swiss) /Helvetica 0]
  668. [(Symbol) /Symbol 0]
  669. [(Times) /Times 0]
  670. % Substitute for Adobe Multiple Master fonts.
  671. [(Minion) /Times 0]
  672. [(Myriad) /Helvetica 0]
  673. % If the font wants to be monospace, use Courier.
  674. [(Monospace) /Courier 0]
  675. [(Typewriter) /Courier 0]
  676. % Define substitutes for the other Adobe PostScript 3 fonts.
  677. % For some of them, the substitution is pretty bad!
  678. [(Albertus) /Palatino 0]
  679. [(AntiqueOlive) /Helvetica 0]
  680. [(Bodoni) /NewCenturySchlbk 0]
  681. [(Chicago) /Helvetica 2]
  682. [(Clarendon) /Bookman 0]
  683. [(Cooper) /NewCenturySchlbk 0]
  684. [(Copperplate) /AvantGarde 0] % inappropriate, small-cap font
  685. [(Coronet) /ZapfChancery-MediumItalic 0]
  686. [(Eurostile) /Helvetica 0]
  687. [(Geneva) /Courier 2] % should be fixed-pitch sans demi
  688. [(GillSans) /Helvetica 2]
  689. [(GillSans-Light) /Helvetica 0]
  690. [(Goudy) /Palatino 0]
  691. [(Hoefler) /NewCenturySchlbk 0]
  692. [(Joanna) /Times 0]
  693. [(LetterGothic) /Courier 0] % should be fixed-pitch sans
  694. [(LubalinGraph-Book) /Bookman 2]
  695. [(LubalinGraph-Demi) /Bookman 0]
  696. [(Marigold) /ZapfChancery-MediumItalic 0]
  697. [(MonaLisa-Recut) /Palatino 0] % inappropriate
  698. [(Monaco) /Courier 2] % should be fixed-pitch sans demi
  699. [(Optima) /Helvetica 0]
  700. [(Oxford) /ZapfChancery-MediumItalic 0]
  701. [(Tekton) /Helvetica 0]
  702. [(Univers) /Helvetica 0]
  703. ] readonly def
  704. /.substituteproperties [
  705. [(It) 1] [(Oblique) 1]
  706. [(Black) 2] [(Bd) 2] [(Bold) 2] [(bold) 2] [(Demi) 2] [(Heavy) 2] [(Sb) 2]
  707. [(Cn) 4] [(Cond) 4] [(Narrow) 4] [(Pkg) 4] [(Compr) 4]
  708. [(Serif) 8] [(Sans) -8]
  709. ] readonly def
  710. /.fontnamestring { % <fontname> .fontnamestring <string|name>
  711. dup type dup /nametype eq {
  712. pop .namestring
  713. } {
  714. /stringtype ne { pop () } if
  715. } ifelse
  716. }.internalbind def
  717. /.fontnameproperties { % <int> <string|name> .fontnameproperties
  718. % <int'>
  719. //.fontnamestring exec
  720. //.substituteproperties {
  721. 2 copy 0 get search {
  722. pop pop pop dup length 1 sub 1 exch getinterval 3 -1 roll exch {
  723. dup 0 ge { or } { neg not and } ifelse
  724. } forall exch
  725. } {
  726. pop pop
  727. } ifelse
  728. } forall pop
  729. }.internalbind def
  730. /.substitutefamilies mark
  731. /AvantGarde
  732. {/AvantGarde-Book /AvantGarde-BookOblique
  733. /AvantGarde-Demi /AvantGarde-DemiOblique}
  734. /Bookman
  735. {/Bookman-Demi /Bookman-DemiItalic /Bookman-Light /Bookman-LightItalic}
  736. /Courier
  737. {/Courier /Courier-Oblique /Courier-Bold /Courier-BoldOblique}
  738. /Helvetica
  739. {/Helvetica /Helvetica-Oblique /Helvetica-Bold /Helvetica-BoldOblique
  740. /Helvetica-Narrow /Helvetica-Narrow-Oblique
  741. /Helvetica-Narrow-Bold /Helvetica-Narrow-BoldOblique}
  742. /NewCenturySchlbk
  743. {/NewCenturySchlbk-Roman /NewCenturySchlbk-Italic
  744. /NewCenturySchlbk-Bold /NewCenturySchlbk-BoldItalic}
  745. /Palatino
  746. {/Palatino-Roman /Palatino-Italic /Palatino-Bold /Palatino-BoldItalic}
  747. /Symbol
  748. {/Symbol /Symbol /Symbol /Symbol}
  749. /Times
  750. {/Times-Roman /Times-Italic /Times-Bold /Times-BoldItalic}
  751. /ZapfChancery-MediumItalic
  752. {/ZapfChancery-MediumItalic}
  753. .dicttomark readonly def
  754. /.nametostring { % <name> .nametostring <string>
  755. % <other> .nametostring <other>
  756. dup type /nametype eq { .namestring } if
  757. }.internalbind def
  758. /.substitutefontname { % <fontname> <properties> .substitutefontname
  759. % <altname|null>
  760. % Look for properties and/or a face name in the font name.
  761. % If we find any, use Times (serif) or Helvetica (sans) as the
  762. % base font; otherwise, use the default font.
  763. % Note that the "substituted" font name may be the same as
  764. % the requested one; the caller must check this.
  765. exch //.fontnamestring exec {
  766. defaultfontname /Helvetica-Oblique /Helvetica-Bold /Helvetica-BoldOblique
  767. /Helvetica-Narrow /Helvetica-Narrow-Oblique
  768. /Helvetica-Narrow-Bold /Helvetica-Narrow-BoldOblique
  769. /Times-Roman /Times-Italic /Times-Bold /Times-BoldItalic
  770. /Helvetica-Narrow /Helvetica-Narrow-Oblique
  771. /Helvetica-Narrow-Bold /Helvetica-Narrow-BoldOblique
  772. } 3 1 roll
  773. % Stack: facelist properties fontname
  774. % Look for a face name.
  775. //.substitutefaces {
  776. 2 copy 0 get search {
  777. pop pop pop
  778. % Stack: facelist properties fontname [(pattern) family properties]
  779. dup 2 get 4 -1 roll or 3 1 roll
  780. 1 get //.substitutefamilies exch get
  781. 4 -1 roll pop 3 1 roll
  782. } {
  783. pop pop
  784. } ifelse
  785. } forall pop
  786. 1 index length mod get exec
  787. }.internalbind odef
  788. /.substitutefont { % <fontname> .substitutefont <altname>
  789. dup 0 exch //.fontnameproperties exec .substitutefontname
  790. % Only accept fonts known in the Fontmap.
  791. Fontmap 1 index known not
  792. {
  793. .nativeFontmap 1 index known not
  794. {pop defaultfontname } if
  795. } if
  796. }.internalbind odef
  797. % If requested, make (and recognize) fake entries in FontDirectory for fonts
  798. % present in Fontmap but not actually loaded. Thanks to Ray Johnston for
  799. % the idea behind this code.
  800. FAKEFONTS not { (%END FAKEFONTS) .skipeof } if
  801. % We use the presence or absence of the FontMatrix key to indicate whether
  802. % a font is real or fake. We must pop the arguments at the very end,
  803. % so that stack protection will be effective.
  804. /definefont { % <name> <font> definefont <font>
  805. dup /FontMatrix known {
  806. //definefont
  807. } {
  808. 2 copy /FontName get findfont //definefont exch pop exch pop
  809. } ifelse
  810. }.internalbind odef
  811. /scalefont { % <font> <scale> scalefont <font>
  812. 1 index /FontMatrix known {
  813. //scalefont
  814. } {
  815. 1 index /FontName get findfont 1 index //scalefont
  816. exch pop exch pop
  817. } ifelse
  818. }.internalbind odef
  819. /makefont { % <font> <matrix> makefont <font>
  820. 1 index /FontMatrix known {
  821. //makefont
  822. } {
  823. 1 index /FontName get findfont 1 index //makefont
  824. exch pop exch pop
  825. } ifelse
  826. }.internalbind odef
  827. /setfont { % <font> setfont -
  828. dup /FontMatrix known {
  829. //setfont
  830. } {
  831. dup /FontName get findfont //setfont pop
  832. } ifelse
  833. }.internalbind odef
  834. %END FAKEFONTS
  835. % Define findfont so it tries to load a font if it's not found.
  836. % The Red Book requires that findfont be a procedure, not an operator,
  837. % but it still needs to restore the stacks reliably if it fails,
  838. % so we do all the work in an operator.
  839. /.findfont { % <fontname> .findfont <font>
  840. mark 1 index % <fontname> mark <fontname>
  841. //systemdict begin .dofindfont
  842. % <fontname> mark <alias> ... <font>
  843. % Define any needed aliases.
  844. counttomark 1 sub { .aliasfont } repeat end
  845. % <fontname> mark <font>
  846. exch pop exch pop
  847. }.internalbind odef
  848. /findfont {
  849. .findfont
  850. }.internalbind def
  851. % Check whether the font name we are about to look for is already on the list
  852. % of aliases we're accumulating; if so, cause an error.
  853. /.checkalias % -mark- <alias1> ... <name> .checkalias <<same>>
  854. { counttomark 1 sub -1 1
  855. { index 1 index eq
  856. { pop QUIET not
  857. { (Unable to substitute for font.) = flush
  858. } if
  859. /findfont cvx /invalidfont signalerror
  860. }
  861. if
  862. }
  863. for
  864. }.internalbind def
  865. % Get a (non-fake) font if present in a FontDirectory.
  866. /.fontknownget % <fontdir> <fontname> .fontknownget <font> true
  867. % <fontdir> <fontname> .fontknownget false
  868. { .knownget
  869. { FAKEFONTS
  870. { dup /FontMatrix known { //true } { pop //false } ifelse }
  871. { //true }
  872. ifelse
  873. }
  874. { //false
  875. }
  876. ifelse
  877. }.internalbind def
  878. % This is the standard procedure for handling font substitution.
  879. % Its location is per an Adobe newsgroup posting.
  880. % It is called with the font name on the stack, standing in for findfont.
  881. /.stdsubstfont { % mark <alias1> ... <fontname> .stdsubstfont mark <alias1> ... <aliasN> <font>
  882. /SUBSTFONT where {
  883. pop QUIET not {
  884. (Substituting for font ) print dup =only
  885. (.) = flush
  886. } if
  887. % No aliasing.
  888. % This mode is incompatible with high level devices.
  889. defaultfontname /None eq { /findfont cvx /invalidfont signalerror } if
  890. cleartomark mark defaultfontname
  891. } {
  892. dup .substitutefont
  893. 2 copy eq {
  894. defaultfontname /None eq { /findfont cvx /invalidfont signalerror } if
  895. pop defaultfontname
  896. } if
  897. //.checkalias exec
  898. QUIET not {
  899. SHORTERRORS {
  900. (%%[) print 1 index =only
  901. ( not found, substituting ) print dup =only (]%%)
  902. } {
  903. (Substituting font ) print dup =only
  904. ( for ) print 1 index =only (.)
  905. } ifelse = flush
  906. } if
  907. } ifelse
  908. /Font findresource
  909. }.internalbind def
  910. % Default font substitution does {pop /Courier} om many implementations.
  911. % GS post-process font substitution in .stdsubstfont and uses {} for
  912. % backward compatibility
  913. $error /SubstituteFont { } put
  914. % Scan the next directory on FONTPATH.
  915. /.scannextfontdir { % - .scannextfontdir <bool>
  916. % If we haven't scanned all the directories in
  917. % FONTPATH, scan the next one.
  918. //null 0 1 FONTPATH length 1 sub {
  919. FONTPATH 1 index get //null ne { exch pop exit } if pop
  920. } for dup //null ne {
  921. dup 0 eq { //.scanfontbegin exec} if
  922. FONTPATH 1 index get //.scanfontdir exec
  923. FONTPATH exch //null put //true
  924. } {
  925. pop //false
  926. } ifelse
  927. }.internalbind def
  928. % Do the work of findfont, including substitution, defaulting, and
  929. % scanning of FONTPATH.
  930. /.dofindfont { % mark <fontname> .dofindfont % mark <alias> ... <font>
  931. .tryfindfont not {
  932. % We didn't find the font. If we haven't scanned
  933. % all the directories in FONTPATH, scan the next one
  934. % now and look for the font again.
  935. //.scannextfontdir exec {
  936. % Start over with an empty alias list.
  937. counttomark 1 sub { pop } repeat % mark <fontname>
  938. .dofindfont
  939. } {
  940. % No more directories to scan. Try building the native
  941. % font map entries if we haven't already done so.
  942. .buildnativefontmap {
  943. % Same stack as at the beginning of .dofindfont.
  944. .dofindfont % start over
  945. } {
  946. % No luck. Make sure we're not already
  947. % looking for the default font.
  948. QUIET not {
  949. (Didn't find this font on the system!\n)
  950. print
  951. } if
  952. dup defaultfontname eq {
  953. QUIET not {
  954. (Unable to load default font ) print
  955. dup =only (! Giving up.) = flush
  956. } if
  957. /findfont cvx /invalidfont signalerror
  958. } if
  959. % Substitute for the font. Don't alias.
  960. % Same stack as at the beginning of .dofindfont.
  961. $error /SubstituteFont get exec
  962. %
  963. % igorm: I guess the surrounding code assumes that .stdsubstfont
  964. % must ADD an alias to allow .checkalias and .findfont to work properly.
  965. % Also I guess that a trailing recursion is
  966. % used in .dofindfont and through .stdsubstfont
  967. % just to represent a simple iteration,
  968. % which accumulates the aliases after the mark.
  969. //.stdsubstfont exec
  970. } ifelse
  971. } ifelse
  972. } if
  973. }.internalbind def
  974. % any user of .putgstringcopy must use bind and executeonly
  975. /.putgstringcopy % <dict> <name> <string> .putgstringcopy -
  976. { 2 index gcheck currentglobal
  977. 2 copy eq {
  978. pop pop .forceput
  979. } executeonly {
  980. 5 1 roll setglobal
  981. dup length string copy
  982. .forceput setglobal
  983. } executeonly ifelse
  984. } .forcebind odef % must be bound and hidden for .forceput
  985. /.loadfontloop { % <fontname> <filename> <libflag> .loadfontloop
  986. % <font> true
  987. % -or-
  988. % <fontname> false
  989. % See above regarding the use of 'loop'.
  990. { % Is the font name a string?
  991. 1 index type /stringtype ne
  992. { pop
  993. QUIET not
  994. { (Can't find font with non-string name: ) print dup =only (.) = flush
  995. }
  996. if pop //false exit
  997. } if
  998. % check <libflag>
  999. {
  1000. findlibfile not
  1001. }
  1002. {
  1003. //true
  1004. } ifelse
  1005. % if findlibfile didn't work, try just opening the file direcly.
  1006. {
  1007. dup (r) { file } stopped {
  1008. pop pop //true
  1009. } {
  1010. //false
  1011. } ifelse
  1012. }
  1013. {
  1014. //false
  1015. }ifelse
  1016. % If just opening the file didn't work, try opening the file name
  1017. % in the font resource directory
  1018. {
  1019. dup
  1020. //.fonttempstring /FontResourceDir getsystemparam .genericrfn
  1021. (r) { file } stopped {
  1022. pop pop //true
  1023. } {
  1024. dup .filename
  1025. { 3 -1 roll pop exch }
  1026. { pop }
  1027. ifelse
  1028. //false
  1029. } ifelse
  1030. }
  1031. {
  1032. //false
  1033. }ifelse
  1034. {
  1035. QUIET not
  1036. { (Can't find \(or can't open\) font file ) print dup print
  1037. (.) = flush
  1038. }
  1039. if pop //false exit
  1040. } if
  1041. % Stack: fontname fontfilename fontfile
  1042. QUIET not
  1043. { (Loading ) print 2 index =only
  1044. ( font from ) print 1 index print (... ) print flush
  1045. }
  1046. if
  1047. % If LOCALFONTS isn't set, load the font into local or global
  1048. % VM according to FontType; if LOCALFONTS is set, load the font
  1049. % into the current VM, which is what Adobe printers (but not
  1050. % DPS or CPSI) do.
  1051. LOCALFONTS { //false } { /setglobal where } ifelse
  1052. { pop /FontType .findfontvalue { 1 eq } { //false } ifelse
  1053. % .setglobal, like setglobal, aliases FontDirectory to
  1054. % GlobalFontDirectory if appropriate. However, we mustn't
  1055. % allow the current version of .setglobal to be bound in,
  1056. % because it's different depending on language level.
  1057. .currentglobal exch /.setglobal .systemvar exec
  1058. % Remove the fake definition, if any.
  1059. //.FontDirectory 3 index .forceundef % readonly
  1060. 1 index (r) file .loadfont //.FontDirectory exch
  1061. /.setglobal .systemvar exec
  1062. } executeonly
  1063. { .loadfont //.FontDirectory
  1064. }
  1065. ifelse
  1066. % Stack: fontname fontfilename fontdirectory
  1067. QUIET not
  1068. { //systemdict /level2dict known
  1069. { .currentglobal //false .setglobal vmstatus
  1070. //true .setglobal vmstatus 3 -1 roll pop
  1071. 6 -1 roll .setglobal 5
  1072. }
  1073. { vmstatus 3
  1074. }
  1075. ifelse { =only ( ) print } repeat
  1076. (done.) = flush
  1077. } if
  1078. % Check to make sure the font was actually loaded.
  1079. dup 3 index //.fontknownget exec
  1080. { dup /PathLoad 4 index //.putgstringcopy
  1081. 4 1 roll pop pop pop //true exit
  1082. } executeonly if
  1083. % Maybe the file had a different FontName.
  1084. % See if we can get a FontName from the file, and if so,
  1085. % whether a font by that name exists now.
  1086. exch dup % Stack: origfontname fontdirectory path path
  1087. (r) file //.findfontname exec
  1088. { % Stack: origfontname fontdirectory path filefontname
  1089. 2 index 1 index //.fontknownget exec
  1090. { % Yes. Stack: origfontname fontdirectory path filefontname fontdict
  1091. dup 4 -1 roll /PathLoad exch //.putgstringcopy
  1092. % Stack: origfontname fontdirectory filefontname fontdict
  1093. 3 -1 roll pop
  1094. % Stack: origfontname filefontname fontdict
  1095. dup /FontName get dup //.FontDirectory exch .forceundef
  1096. /GlobalFontDirectory .systemvar exch .forceundef
  1097. dup length dict .copydict dup 3 index /FontName exch put
  1098. 2 index exch definefont
  1099. exch
  1100. QUIET
  1101. { pop
  1102. }
  1103. { (Using ) print =only
  1104. ( font for ) print 1 index =only
  1105. (.) = flush
  1106. }
  1107. ifelse % Stack: origfontname fontdict
  1108. exch pop //true exit
  1109. % Stack: fontdict
  1110. } executeonly
  1111. if pop % Stack: origfontname fontdirectory path
  1112. } executeonly
  1113. if pop pop % Stack: origfontname
  1114. % The font definitely did not load correctly.
  1115. QUIET not
  1116. { (Loading ) print dup =only
  1117. ( font failed.) = flush
  1118. } if
  1119. //false exit
  1120. } loop % end of loop
  1121. }.internalbind def % must be bound and hidden for .putgstringcopy
  1122. % Attempt to load a font from a file.
  1123. /.tryloadfont { % <fontname> .tryloadfont <font> true
  1124. % <fontname> .tryloadfont false
  1125. dup //.nametostring exec
  1126. % Hack: check for the presence of the resource machinery.
  1127. /.genericrfn where {
  1128. pop
  1129. pop dup //.fonttempstring /FontResourceDir getsystemparam .genericrfn
  1130. {//false //.loadfontloop exec} //.internalstopped exec {//false} if {
  1131. //true
  1132. } {
  1133. dup //.nametostring exec
  1134. {//true //.loadfontloop exec} //.internalstopped exec {//false} if
  1135. } ifelse
  1136. } {
  1137. {//true //.loadfontloop exec} //.internalstopped exec {//false} if
  1138. } ifelse
  1139. }.internalbind def
  1140. % Try to find a font using only the present contents of Fontmap.
  1141. /.tryfindfont { % <fontname> .tryfindfont <font> true
  1142. % <fontname> .tryfindfont false
  1143. //.FontDirectory 1 index //.fontknownget exec
  1144. { % Already loaded
  1145. exch pop //true
  1146. }
  1147. {
  1148. dup Fontmap exch .knownget
  1149. { //true //true }
  1150. { % Unknown font name. Look for a file with the
  1151. % same name as the requested font.
  1152. dup //.tryloadfont exec
  1153. { exch pop //true //false }
  1154. {
  1155. % if we can't load by name check the native font map
  1156. .nativeFontmap exch .knownget
  1157. { //true //true }
  1158. { //false //false } ifelse
  1159. } ifelse
  1160. } ifelse
  1161. { % Try each element of the Fontmap in turn.
  1162. pop
  1163. //false exch % (in case we exhaust the list)
  1164. % Stack: fontname false fontmaplist
  1165. { exch pop
  1166. dup type /nametype eq
  1167. { % Font alias
  1168. //.checkalias exec
  1169. dup .tryfindfont
  1170. {
  1171. % We don't want to reuse an embedded font as a substitute
  1172. % so make sure the font came from disk before using it.
  1173. dup /Path known
  1174. 1 index /PathLoad known or
  1175. { exch pop //true exit }
  1176. {
  1177. % if the candidate didn't come from disk, remove it from
  1178. % FontDirectory and try again.
  1179. pop dup undefinefont
  1180. .tryfindfont exit
  1181. }
  1182. ifelse
  1183. } if
  1184. }
  1185. { dup dup type dup /arraytype eq exch /packedarraytype eq or exch xcheck and
  1186. { % Font with a procedural definition
  1187. exec % The procedure will load the font.
  1188. % Check to make sure this really happened.
  1189. //.FontDirectory 1 index .knownget
  1190. { exch pop //true exit }
  1191. if
  1192. }
  1193. { % Font file name
  1194. dup type /dicttype eq
  1195. {
  1196. begin
  1197. Path
  1198. }
  1199. {
  1200. 1 dict begin
  1201. } ifelse
  1202. //true //.loadfontloop exec
  1203. end
  1204. { //true exit } if
  1205. }
  1206. ifelse
  1207. }
  1208. ifelse //false
  1209. }
  1210. forall
  1211. % Stack: font true -or- fontname false
  1212. { //true
  1213. }
  1214. { % None of the Fontmap entries worked.
  1215. % Try loading a file with the same name
  1216. % as the requested font.
  1217. //.tryloadfont exec
  1218. }
  1219. ifelse
  1220. }
  1221. if
  1222. }
  1223. ifelse
  1224. }.internalbind def
  1225. % Define a procedure to load all known fonts.
  1226. % This isn't likely to be very useful.
  1227. /loadallfonts
  1228. {
  1229. [Fontmap .nativeFontmap] { { pop findfont pop } forall } forall
  1230. }.internalbind def
  1231. % If requested, load all the fonts defined in the Fontmap into FontDirectory
  1232. % as "fake" fonts i.e., font dicts with only FontName and FontType defined.
  1233. % (We define FontType only for the sake of some questionable code in the
  1234. % Apple Printer Utility 2.0 font inquiry code.)
  1235. %
  1236. % Note that this procedure only creates fake fonts in the FontDirectory
  1237. % associated with the current VM. This is because in multi-context systems,
  1238. % creating the fake fonts in local VM leads to undesirable complications.
  1239. /.definefakefonts
  1240. {
  1241. }
  1242. {
  1243. (gs_fonts FAKEFONTS) VMDEBUG
  1244. [Fontmap .nativeFontmap ]
  1245. {
  1246. {
  1247. pop dup type /stringtype eq { cvn } if
  1248. //.FontDirectory 1 index known not {
  1249. 2 dict dup /FontName 3 index put
  1250. dup /FontType 1 put
  1251. //.FontDirectory 3 1 roll //.forceput exec % readonly
  1252. } {
  1253. pop
  1254. } ifelse
  1255. } forall
  1256. } forall
  1257. } executeonly % hide .forceput
  1258. FAKEFONTS { exch } if pop def % don't bind, .current/setglobal get redefined
  1259. % Install initial fonts from Fontmap.
  1260. /.loadinitialfonts
  1261. { NOFONTMAP not
  1262. { /FONTMAP where
  1263. { pop FONTMAP
  1264. { dup VMDEBUG findlibfile
  1265. { exch pop //.loadFontmap exec }
  1266. { /undefinedfilename signalerror }
  1267. ifelse
  1268. }
  1269. }
  1270. { LIBPATH
  1271. { defaultfontmap
  1272. //false .file_name_combine
  1273. {
  1274. dup VMDEBUG
  1275. (r) { file } //.internalstopped exec {
  1276. pop pop
  1277. defaultfontmap_content { .definefontmap } forall
  1278. } {
  1279. //.loadFontmap exec
  1280. } ifelse
  1281. } {
  1282. pop pop
  1283. } ifelse
  1284. }
  1285. }
  1286. ifelse forall
  1287. }
  1288. if
  1289. userdict /defaultfontmap_content .undef
  1290. //.definefakefonts exec % current VM is global
  1291. } def % don't bind, .current/setglobal get redefined
  1292. % Undef these, not needed outside this file
  1293. [
  1294. % /.fonttempstring /.scannextfontdir - are also used in gs_res.ps, so are undefined there
  1295. % /.scanfontheaders - used in gs_cff.ps, gs_ttf.ps
  1296. /.loadfontloop /.tryloadfont /.findfont /.pathlist /.loadFontmap /.lowerstring
  1297. /.splitfilename /.scanfontdict /.scanfontbegin
  1298. /.scanfontskip /.scan1fontstring
  1299. /.scan1fontfirst /.scanfontdir
  1300. /.setnativefontmapbuilt /.aliasfont
  1301. /.setloadingfont /.substitutefaces /.substituteproperties /.substitutefamilies
  1302. /.nametostring /.fontnamestring /.checkalias /.fontknownget /.stdsubstfont
  1303. /.putgstringcopy
  1304. /.definenativefontmap
  1305. /.findfontname /.addfontmappermitpaths /.splitdirname
  1306. ] systemdict .undefinternalnames