星火微课系统客户端
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.

gs_fonts.ps 43KB

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