pdf_font.ps 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957
  1. % Copyright (C) 1994, 2000 Aladdin Enterprises. All rights reserved.
  2. %
  3. % This file is part of AFPL Ghostscript.
  4. %
  5. % AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author or
  6. % distributor accepts any responsibility for the consequences of using it, or
  7. % for whether it serves any particular purpose or works at all, unless he or
  8. % she says so in writing. Refer to the Aladdin Free Public License (the
  9. % "License") for full details.
  10. %
  11. % Every copy of AFPL Ghostscript must include a copy of the License, normally
  12. % in a plain ASCII text file named PUBLIC. The License grants you the right
  13. % to copy, modify and redistribute AFPL Ghostscript, but only under certain
  14. % conditions described in the License. Among other things, the License
  15. % requires that the copyright notice and this notice be preserved on all
  16. % copies.
  17. % $Id: pdf_font.ps,v 1.23 2001/10/19 16:42:47 masata-y Exp $
  18. % pdf_font.ps
  19. % PDF font operations.
  20. /.setlanguagelevel where { pop 2 .setlanguagelevel } if
  21. .currentglobal true .setglobal
  22. /pdfdict where { pop } { /pdfdict 100 dict def } ifelse
  23. GS_PDF_ProcSet begin
  24. pdfdict begin
  25. % We cache the PostScript font in an additional element of the
  26. % font resource dictionary, called PSFont.
  27. % ---------------- Encodings ---------------- %
  28. % Apply a list of differences to an Encoding.
  29. % Note that the differences may cause the array to grow.
  30. /updateencoding { % <encoding> <differences> updateencoding <enc'>
  31. % Calculate the length of the result.
  32. exch 0 2 index {
  33. dup type /nametype ne { exch pop } { pop 1 add } ifelse
  34. } forall
  35. 1 index length .max array dup 0 4 -1 roll putinterval
  36. exch 0 exch {
  37. % Stack: enc' code element
  38. dup type /nametype ne
  39. { exch pop }
  40. { 3 copy put pop 1 add }
  41. ifelse
  42. } forall pop
  43. } bdef
  44. % Get the Encoding for a font.
  45. /getencoding % <base-encoding> <font-resource> getencoding <enc>
  46. { /Encoding knownoget
  47. { dup type /nametype eq
  48. {
  49. % The published PDF specification says the Encoding name
  50. % "must be" one of the 3 predefined Encodings, implying
  51. % that an error should occur if it isn't. However, Acrobat
  52. % Reader simply ignores unknown names, and since there are
  53. % some buggy applications that rely on this, we do the same.
  54. dup dup dup /MacRomanEncoding eq
  55. exch /MacExpertEncoding eq or
  56. exch /WinAnsiEncoding eq or
  57. { exch pop findencoding
  58. }
  59. { pop
  60. }
  61. ifelse
  62. }
  63. { dup /BaseEncoding knownoget
  64. { findencoding 3 -1 roll pop exch
  65. }
  66. if
  67. /Differences knownoget { updateencoding } if
  68. }
  69. ifelse
  70. }
  71. if
  72. } bdef
  73. % Rename a font with a generated name.
  74. /renamefont { % <fontdict> renamefont <font'>
  75. dup /FontName 2 copy get genfontname dup 5 1 roll put definefont
  76. } bind def
  77. % Adjust a font according to the Encoding and Widths in the font resource.
  78. /adjustfont { % <font-resource> <font> adjustfont <font'>
  79. getfontencoding
  80. getfontmetrics 4 -1 roll pop .updatefont { renamefont } if
  81. } bind def
  82. % Get the (possibly modified) encoding of a font.
  83. /getfontencoding { % <font-resource> <font> getfontencoding
  84. % <font-resource> <font> <Encoding|null>
  85. 1 index /Encoding known {
  86. dup /Encoding .knownget { 2 index getencoding } { null } ifelse
  87. } {
  88. null
  89. } ifelse
  90. } bdef
  91. /find_in_diff % <Differences> <index> find_in_diff <bool>
  92. { false exch 0 4 3 roll
  93. { dup type /nametype ne { exch pop } { pop 1 add } ifelse
  94. 2 copy eq {
  95. pop pop pop true 0 0 exit
  96. } if
  97. } forall
  98. pop pop
  99. } bdef
  100. % Get the metrics of a font, if specified.
  101. /getfontmetrics { % <font-resource> <font> <Encoding|null> getfontmetrics
  102. % <font-resource> <font> <Encoding|null>
  103. % <Metrics|null>
  104. 2 index /Widths known {
  105. dup null eq { pop dup /Encoding get } if
  106. 4 dict begin
  107. /Encoding exch def
  108. /Metrics Encoding length dict def
  109. exch
  110. dup /Widths oget /Widths exch def
  111. % Stack: font font-res
  112. % Note that widths are always based on a 1000-unit
  113. % character space, but the FontMatrix may specify
  114. % some other scale factor. Compensate for this here,
  115. % by scaling the Widths if necessary.
  116. 0.001 2 index /FontMatrix get 0 get div
  117. % Stack: font font-res mscale
  118. 1 index /FirstChar oget dup 1 4 index /LastChar oget
  119. { % Stack: font font-res mscale first-char index
  120. Encoding 1 index get
  121. Widths 2 index 4 index sub oget
  122. % Stack: font font-res mscale first-char index charname width
  123. 4 index mul
  124. % The following 'loop' is only context for 'exit'.
  125. {
  126. % Work around a bug in pdfTeX, which can generate Encoding
  127. % vectors containing nulls :
  128. 1 index null eq { exit } if
  129. % There is a hack here to deal with encodings where the
  130. % same character appears more than once, because the Metrics
  131. % dictionary works by character name, not by character code.
  132. % We prefer to take (1) non-zero width, and (2) width for
  133. % the character code which appears in Differences.
  134. Metrics 2 index .knownget not { 0 } if 0 ne {
  135. 5 index /Encoding knownoget not { exit } if
  136. dup type /dicttype ne { pop exit } if
  137. /Differences knownoget not { exit } if
  138. 3 index //find_in_diff exec not { exit } if
  139. } if
  140. 2 copy Metrics 3 1 roll put
  141. exit
  142. } loop
  143. pop pop pop
  144. }
  145. for pop
  146. % Now fill in the MissingWidth for any encoded characters
  147. % that aren't in Metrics already. Note that built-in
  148. % fonts may have Widths/FirstChar/LastChar but no
  149. % FontDescriptor, so we must check for this.
  150. % Stack: font font-res mscale
  151. 1 index /FontDescriptor knownoget {
  152. Metrics exch
  153. /MissingWidth knownoget { 2 index mul } { 0 } ifelse exch
  154. Encoding {
  155. % Stack: font font-res mscale missing-width metrics charname
  156. % Work around the abovementioned pdfTeX bug.
  157. dup null ne {
  158. 2 copy known not { 2 copy 4 index put } if pop
  159. } {
  160. pop
  161. } ifelse
  162. } forall pop pop pop
  163. } {
  164. pop
  165. } ifelse
  166. exch Encoding Metrics end
  167. } {
  168. null
  169. } ifelse
  170. } bdef
  171. currentdict /find_in_diff undef
  172. % ---------------- Descriptors ---------------- %
  173. % Partial descriptors for the 14 built-in fonts. Note that
  174. % from PDF 1.1 to PDF 1.2, the meaning of the Flag 6 in the FontDescriptor
  175. % object has undergone a subtle change in its meaning which has serious
  176. % consequences for searching with Acrobat:
  177. % In PDF 1.1, the flag meant: Font has StandardEncoding
  178. % In PDF 1.2, the flag means: Font has (subset of) StandardRomanCharacterSet
  179. /standardfontdescriptors mark
  180. /Courier mark /Flags 16#23 .dicttomark
  181. /Courier-Oblique 1 index
  182. /Courier-Bold 1 index
  183. /Courier-BoldOblique 1 index
  184. /Helvetica mark /Flags 16#20 .dicttomark
  185. /Helvetica-Oblique 1 index
  186. /Helvetica-Bold 1 index
  187. /Helvetica-BoldOblique 1 index
  188. /Times-Roman mark /Flags 16#22 .dicttomark
  189. /Times-Bold 1 index
  190. /Times-Italic mark /Flags 16#62 .dicttomark
  191. /Times-BoldItalic 1 index
  192. /Symbol mark /Flags 16#4 .dicttomark
  193. /ZapfDingbats 1 index
  194. .dicttomark readonly def
  195. % ---------------- Utilities ---------------- %
  196. % Fabricate a font name by adding ?'s on the end.
  197. /genfontname % <name> genfontname <name>
  198. { dup length string cvs
  199. { (?) concatstrings
  200. dup cvn FontDirectory exch known not { cvn exit } if
  201. }
  202. loop
  203. } bdef
  204. % Find a font, and adjust its encoding if necessary.
  205. /.pdfdfndict mark
  206. /defaultfontname /Helvetica
  207. .dicttomark readonly def
  208. /pdffindfont { % <font-resource> <fontname> pdffindfont <font>
  209. % If the font isn't available, synthesize one based on
  210. % its descriptor.
  211. dup /Font resourcestatus {
  212. pop pop findfont
  213. } {
  214. 1 index /FontDescriptor knownoget {
  215. % Stack: font-res fontname fontdesc
  216. dup /Flags oget
  217. dup 16#40 and -6 bitshift % 1, oblique/italic
  218. 1 index 16#40000 and -17 bitshift add % 2, bold
  219. exch 16#2 and 2 bitshift add % 8, serif
  220. % We should look at the fixed flag, too.
  221. % Stack: font-res fontname fontdesc properties
  222. 1 index /FontName oget exch
  223. % Analyzes font name and extract "Narrow" property
  224. % which is not described by the FontDescriptor Flags.
  225. 0 2 index .fontnameproperties 4 and or
  226. % Rebind the default font name to Helvetica so that
  227. % fonts with no properties are handled correctly.
  228. //.pdfdfndict begin .substitutefontname end
  229. % Stack: font-res fontname fontdesc substname|null
  230. Fontmap 1 index known not {
  231. % No available good substitution, use the standard one.
  232. pop 1 index .substitutefont
  233. } if
  234. QUIET not {
  235. (Substituting font ) print dup =only
  236. ( for ) print 2 index =only (.) = flush
  237. } if
  238. 3 -1 roll pop findfont
  239. % Stack: font-res fontdesc font
  240. % If this is a small-caps font, replace the CharString
  241. % entries for a..z.
  242. exch /Flags oget 16#20000 and 0 ne {
  243. true .copyfontdict
  244. dup /CharStrings 2 copy get dup length dict .copydict
  245. 4 index /FirstChar get 97 .max
  246. 5 index /LastChar get 122 .min 1 exch {
  247. % Stack: font-res font' font' /CharStrings charstrings code
  248. % Note that this only remaps a-z, not accented characters.
  249. 5 index /Widths oget 1 index 7 index /FirstChar get sub oget
  250. 1 string dup 0 5 -1 roll put
  251. % Stack: font-res font' font' /CharStrings charstrings code
  252. % width (x)
  253. 2 index exch dup cvn exch
  254. dup 0 2 copy get 32 sub put 4 -1 roll {
  255. % Stack: operand (X) width
  256. 0 setcharwidth exch pop
  257. currentfont /FontMatrix get matrix invertmatrix concat
  258. 0.7 dup scale 0 0 moveto show
  259. } /exec cvx 4 packedarray cvx put
  260. } for put
  261. renamefont
  262. } if
  263. } {
  264. % No descriptor available, use the default algorithm.
  265. findfont
  266. } ifelse
  267. } ifelse adjustfont
  268. } bdef
  269. % ---------------- Type 1 fonts ---------------- %
  270. /buildType1 % <Type1-font-resource> buildType1 <font>
  271. { dup /BaseFont get pdffindfont
  272. } bdef
  273. % The state dictionary for the embedded Type 1 font reading procedure
  274. % has the following keys and values:
  275. % data - stream (filter)
  276. % buffer, buffer2 - string
  277. % hexify - procedure to convert buffer to hex if needed
  278. % leftstr - string containing (non-negative) integer
  279. % sectionstr - string containing a character 0 .. 3
  280. % stream - (stream) dictionary
  281. % proc - procedure of the form {-dict- type1read}
  282. % pfbhdr - string containing 16#80 if PFB, 0 otherwise
  283. % When the procedure is executing, this dictionary is current.
  284. % leftstr and sectionstr are strings so that we can change their values
  285. % reliably in case the font executes a restore!
  286. % We also have to do something special about embedded fonts that
  287. % execute definefont more than once -- that is the function of topFontDict.
  288. % Read an embedded Type 1 font.
  289. /readfontfilter { % <proc> readfontfilter <filter>
  290. 0 () /SubFileDecode filter
  291. } bdef
  292. /readtype1dict 5 dict dup begin
  293. /definefont {
  294. dup topFontDict eq topFontDict null eq or {
  295. dup wcheck not { dup length dict copy } if
  296. exch pop savedFontName exch
  297. } if
  298. //systemdict /definefont get exec
  299. } bdef
  300. /eexec {
  301. % Assume the font dictionary is directly below the file on the stack
  302. count 0 gt { /topFontDict 2 index cvlit store } if
  303. 55665 /eexecDecode filter
  304. //systemdict begin readtype1dictcopy begin cvx stopped
  305. currentdict readtype1dictcopy eq { end } if
  306. currentdict //systemdict eq { end } if
  307. { stop } if
  308. } bdef
  309. end readonly def
  310. /readtype1 { % <font-resource> <stream-dict> readtype1 <font>
  311. % Read the definition, using a procedure-based filter
  312. % that turns binary/hex conversion on and off
  313. % at the right times.
  314. 1 index exch
  315. PDFfile fileposition 3 1 roll
  316. 11 dict begin
  317. /leftstr ( ) 10 string copy def
  318. dup /Length1 oget leftstr cvs pop
  319. /sectionstr <00> 1 string copy def
  320. /pfbhdr <00> 1 string copy def
  321. /stream 1 index def
  322. true resolvestream /data exch def
  323. /buffer 1000 string def % arbitrary
  324. /buffer2 buffer length 2.1 div cvi 1 sub string def
  325. /hexify /buf2hex load def
  326. currentdict end
  327. /type1read cvx 2 array astore cvx dup 0 get /proc 2 index put
  328. readfontfilter
  329. % Some buggy embedded fonts leave extra junk on the stack,
  330. % so we have to make a closure that records the stack depth
  331. % in a fail-safe way.
  332. //systemdict begin
  333. % The PDF specification is somewhat muddy about whether
  334. % an embedded font's name is supposed to be the BaseFont
  335. % from the Font object or the FontName from the descriptor.
  336. % Acrobat Distiller requires the former. Save away the
  337. % name so we can substitute it at definefont time.
  338. //readtype1dict dup length 3 add dict copy begin
  339. 1 index /BaseFont oget /savedFontName exch def
  340. /topFontDict null def
  341. /readtype1dictcopy currentdict def
  342. { run } aload pop count 1 sub 2 packedarray cvx exec
  343. end end
  344. count exch sub { pop } repeat
  345. PDFfile 3 -1 roll setfileposition
  346. /BaseFont oget findfont
  347. adjustfont
  348. } bdef
  349. % Execute the appropriate reading procedure.
  350. /type1read % <dict> type1read <string>
  351. { begin leftstr cvi
  352. { type1read0 type1read1 type1read2 type1read3 } sectionstr 0 get get exec
  353. ( ) leftstr copy cvs pop end
  354. } bdef
  355. % Read the next block of data into the buffer.
  356. /type1readdata % <left> <buffer> type1readdata <substring> <left'>
  357. { 0 2 index 2 index length min getinterval
  358. % Adobe requires readstring to signal an error if given
  359. % an empty string. Work around this nonsense here.
  360. dup length 0 ne { data exch readstring pop } if
  361. dup length 3 -1 roll exch sub
  362. DEBUG
  363. { dup =only ( read ) print
  364. 1 index length =only (: ) print
  365. 1 index == flush
  366. } if
  367. } bdef
  368. % Read the initial byte to see if we need to skip a 6 byte PFB header
  369. /type1read0 { % <left> type1read0 <string> <left'>
  370. sectionstr 0 1 put % either way we go to the next stage
  371. pfbhdr type1readdata
  372. 1 index 0 get 16#80 eq {
  373. (\n **** Warning: Embedded Type1 font in PFB format is not valid PDF.)
  374. pdfformaterror
  375. DEBUG { (skipping PFB header) = flush } if
  376. exch pop buffer 0 5 getinterval type1readdata exch
  377. dup 4 get 256 mul 1 index 3 get add 256 mul
  378. 1 index 2 get add 256 mul 1 index 1 get add
  379. DEBUG { (PFB segment length = ) print dup = } if
  380. exch pop % discard the string keeping the PFB segment length
  381. 2 copy ne {
  382. (\n **** Warning: Type 1 PFB segment length and Length 1 value do not match.)
  383. pdfformaterror
  384. exch % keep the PFB length instead
  385. } if
  386. pop
  387. buffer type1readdata % go ahead and read a block
  388. }
  389. if % if not PFB, return pfbhdr string (first char of file, usually %).
  390. } bdef
  391. % Read the next block of the initial text portion.
  392. /type1read1 { % <left> type1read1 <string> <left'>
  393. DEBUG { (read1 ) print } if
  394. dup 0 eq {
  395. pop sectionstr 0 2 put
  396. stream /Length2 oget
  397. % Determine whether to hexify data for eexec.
  398. dup 8 lt {
  399. type1read2 % Hexify.
  400. } {
  401. DEBUG { (read2 ) print } if
  402. pfbhdr 0 get 16#80 eq {
  403. % eat 6 more bytes of PFB junk before proceeding
  404. DEBUG { (skipping PFB header in segment 2) = flush } if
  405. buffer 0 6 getinterval type1readdata exch
  406. dup 5 get 256 mul 1 index 4 get add 256 mul
  407. 1 index 3 get add 256 mul 1 index 2 get add
  408. DEBUG { (PFB segment length = ) print dup = } if
  409. exch pop % discard the string keeping the PFB segment length
  410. 2 copy ne {
  411. (\n **** Warning: Type 1 PFB segment length and Length 2 value do not match.)
  412. pdfformaterror
  413. dup =
  414. exch % keep the PFB length instead
  415. } if
  416. pop
  417. } if
  418. buffer2 type1readdata exch
  419. % The check doesn't have to be 100% accurate:
  420. % hexifying is always OK.
  421. dup 0 8 getinterval 0 exch { or } forall
  422. 128 ge {
  423. /hexify { } store
  424. /buffer2 buffer def % We don't need an intermediate buffer.
  425. } if hexify exch
  426. } ifelse
  427. } {
  428. buffer type1readdata
  429. } ifelse
  430. } bdef
  431. % Convert a string from binary to hex for eexec.
  432. % Free variables: buffer.
  433. /buf2hex { % <string> buf2hex <hexstring>
  434. buffer /ASCIIHexEncode filter dup 3 -1 roll writestring closefile
  435. buffer (>) search pop exch pop exch pop
  436. } bdef
  437. % Read the next block of the encrypted portion.
  438. /type1trailer
  439. (0000000000000000000000000000000000000000000000000000000000000000\n\
  440. 0000000000000000000000000000000000000000000000000000000000000000\n\
  441. 0000000000000000000000000000000000000000000000000000000000000000\n\
  442. 0000000000000000000000000000000000000000000000000000000000000000\n\
  443. 0000000000000000000000000000000000000000000000000000000000000000\n\
  444. 0000000000000000000000000000000000000000000000000000000000000000\n\
  445. 0000000000000000000000000000000000000000000000000000000000000000\n\
  446. 0000000000000000000000000000000000000000000000000000000000000000\n\
  447. cleartomark\n)
  448. readonly def
  449. /type1read2 { % <left> type1read2 <string> <left'>
  450. DEBUG { (read2 ) print } if
  451. dup 0 eq
  452. { pop sectionstr 0 3 put
  453. stream /Length3 oget
  454. dup 0 eq
  455. { DEBUG { (trailer ) print } if
  456. type1trailer exch
  457. }
  458. {
  459. pfbhdr 0 get 16#80 eq {
  460. % eat 6 more bytes of PFB junk before proceeding
  461. DEBUG { (skipping PFB header in segment 3) = flush } if
  462. buffer 0 6 getinterval type1readdata exch
  463. dup 5 get 256 mul 1 index 4 get add 256 mul
  464. 1 index 3 get add 256 mul 1 index 2 get add
  465. DEBUG { (PFB segment length = ) print dup = } if
  466. exch pop % discard the string keeping the PFB segment length
  467. 2 copy ne {
  468. (\n **** Warning: Type 1 PFB segment length and Length 3 value do not match.)
  469. pdfformaterror
  470. exch % keep the PFB length instead
  471. } if
  472. pop
  473. (\n) pdfformaterror
  474. } if
  475. type1read3
  476. }
  477. ifelse
  478. }
  479. { buffer2 type1readdata exch hexify exch
  480. }
  481. ifelse
  482. } bdef
  483. % Read the next block of the final text portion.
  484. % When finished, this procedure returns an empty string.
  485. /type1read3 % <left> type1read3 <string> <left'>
  486. { DEBUG { (read3 ) print } if
  487. buffer type1readdata
  488. } bdef
  489. % ---------------- Type 3 fonts ---------------- %
  490. /.notdefEncoding 256 { /.notdef } repeat 256 packedarray def
  491. /buildType3 { % <Type3-font-resource> buildType3 <font>
  492. 8 dict begin
  493. /FontType 3 def
  494. /Resources 1 index /Resources knownoget { oforce } { 0 dict } ifelse def
  495. /FontBBox 1 index /FontBBox get cvx def
  496. /FontMatrix 1 index /FontMatrix oget def
  497. /CharProcs 1 index /CharProcs oget def
  498. 1 index /Widths knownoget {
  499. /Widths exch def
  500. /FirstChar 1 index /FirstChar oget def
  501. /LastChar 1 index /LastChar oget def
  502. } if
  503. /FontName 1 index /Name get genfontname def
  504. /Encoding .notdefEncoding 2 index getencoding def
  505. % We have to define BuildChar rather than BuildGlyph:
  506. % there is no PDF equivalent of glyphshow, and we need
  507. % the character code to access the Widths.
  508. /BuildChar {
  509. % Stack: font charcode
  510. 1 index begin 3 dict begin
  511. /Font 3 -1 roll def /CharCode 1 index def
  512. % Make unknown characters map to /.notdef
  513. Encoding exch get dup CharProcs exch known
  514. { CharProcs exch oget }
  515. { pop CharProcs /.notdef oget }
  516. ifelse
  517. PDFfile fileposition exch
  518. false resolvestream
  519. % Stack: filepos stream
  520. % Don't let setgcolor set the color inside the BuildGlyph
  521. % procedure, because this causes an /undefined error.
  522. q null /FillColor gput null /StrokeColor gput
  523. Font /Resources get exch pdfopdict .pdfruncontext
  524. Q
  525. PDFfile exch setfileposition
  526. end end
  527. } bdef
  528. FontName currentdict end definefont exch pop
  529. } bdef
  530. /.adjustcharwidth { % <wx> <wy> .adjustcharwidth <wx'> <wy'>
  531. /Widths where {
  532. begin
  533. CharCode FirstChar ge CharCode LastChar le and {
  534. exch pop Widths CharCode FirstChar sub get exch
  535. } if end
  536. } if
  537. } bdef
  538. % ---------------- TrueType fonts ---------------- %
  539. /TTfonts mark
  540. /Arial /Helvetica
  541. /Arial,Italic /Helvetica-Oblique
  542. /Arial,Bold /Helvetica-Bold
  543. /Arial,BoldItalic /Helvetica-BoldOblique
  544. /CourierNew /Courier
  545. /CourierNew,Bold /Courier-Bold
  546. /TimesNewRoman /Times-Roman
  547. /TimesNewRoman,Italic /Times-Italic
  548. /TimesNewRoman,Bold /Times-Bold
  549. /TimesNewRoman,BoldItalic /Times-BoldItalic
  550. .dicttomark readonly def
  551. /buildTrueType { % <TrueType-font-resource> buildTrueType <font>
  552. dup /BaseFont get
  553. dup TTfonts exch .knownget {
  554. exch pop
  555. % Hack required by the PDF specification: if the
  556. % font resource has Subtype = /TrueType but the actual
  557. % (installed) font is not a TrueType font, ignore the
  558. % Encoding in the font resource. However, all current
  559. % versions of Acrobat Reader have the 14 base TrueType
  560. % fonts built in, so this produces incorrect output for
  561. % badly designed PDF files that specify these file names
  562. % with /Subtype = /TrueType but no embedded definition.
  563. % Compensate for this by removing the /Subtype key when
  564. % looking up the font.
  565. exch dup length dict copy dup /Subtype null put exch
  566. } if pdffindfont
  567. } bdef
  568. % Read an embedded TrueType font.
  569. /readtruetype { % <font-resource> <stream-dict> readtruetype <font>
  570. % This is much simpler than readtype1, because we don't
  571. % have to deal with the tripartite .PFB format.
  572. 1 index exch
  573. PDFfile fileposition 3 1 roll
  574. true resolvestream readfontfilter
  575. % Stack: filepos fontres stream
  576. 1 index /Subtype get /CIDFontType2 eq {
  577. .loadttcidfont
  578. % Stack: filepos fontres cidfont
  579. 1 index /CIDToGIDMap knownoget {
  580. dup /Identity eq {
  581. pop
  582. } {
  583. true resolvestream
  584. % The following doesn't work for CIDToGIDMaps with more
  585. % than 32K-1 entries. We'll fix it later if necessary.
  586. % Stack: filepos fontres font mapstream
  587. dup 2 index /CIDCount oget 2 mul string readstring pop exch closefile
  588. exch dup length 5 add dict .copydict
  589. dup /FID undef
  590. dup /CIDMap 4 -1 roll put
  591. dup /CIDFontName get exch /CIDFont defineresource
  592. } ifelse
  593. } if
  594. } {
  595. null 2 index getencoding .loadpdfttfont
  596. } ifelse
  597. exch pop
  598. PDFfile 3 -1 roll setfileposition
  599. % Ignore both the Encoding and the Widths.
  600. exch pop
  601. } bdef
  602. % ---------------- Type 0 fonts ---------------- %
  603. % Predefine the known CMaps, but only create them on demand.
  604. /knownCMaps mark
  605. /Identity-H { /Identity-H 0 makeIdentityCMap }
  606. /Identity-V { /Identity-V 1 makeIdentityCMap }
  607. .dicttomark def
  608. /makeIdentityCMap { % <cmapname> <wmode> .makeIdentityCMap -
  609. .currentglobal true .setglobal 3 1 roll
  610. /CIDInit /ProcSet findresource begin
  611. 12 dict begin
  612. begincmap
  613. /WMode exch def
  614. /CMapName exch def
  615. /CIDSystemInfo 3 dict dup begin
  616. /Registry (Adobe) def
  617. /Ordering (Identity) def
  618. /Supplement 0 def
  619. end def
  620. %/CMapName (see above)
  621. /CMapVersion 1 def
  622. /CMapType 1 def
  623. %WMode (see above)
  624. % The PDF documentation says that these CMaps map CIDs
  625. % "1 to 65,536". This is a misprint for 0 to 65,535.
  626. 1 begincodespacerange
  627. % <0001> <00ff> <0100> <ffff>
  628. <0000> <ffff>
  629. endcodespacerange
  630. 1 begincidrange
  631. % <0001> <00ff> 1 <0100> <ffff> 256
  632. <0000> <ffff> 0
  633. endcidrange
  634. endcmap
  635. CMapName currentdict /CMap defineresource
  636. knownCMaps CMapName 2 index put
  637. end % CMap
  638. end % CIDInit ProcSet
  639. exch .setglobal
  640. } bdef
  641. /buildType0 { % <Type0-font-resource> buildType0 <font>
  642. dup /BaseFont get % FontName
  643. 1 index /Encoding oget
  644. dup type /nametype eq {
  645. dup /CMap resourcestatus {
  646. pop pop /CMap findresource
  647. } {
  648. knownCMaps 1 index .knownget
  649. { exch pop exec } { /undefined signalerror } ifelse
  650. } ifelse
  651. } {
  652. PDFfile fileposition exch
  653. dup /CMapName get exch true resolvestream cvx exec
  654. /CMap findresource
  655. exch PDFfile exch setfileposition
  656. } ifelse % CMap
  657. [
  658. 3 index /DescendantFonts oget { exec resourcefont } forall
  659. ] % subfonts
  660. composefont
  661. % Stack: fontres font
  662. 1 index /FontMatrix knownoget {
  663. dup aload pop true {0 0 1 0 0 1} {3 -1 roll eq and} forall {
  664. 1 index exch makefont exch /FontName get exch definefont
  665. } {
  666. pop
  667. } ifelse
  668. } if exch pop
  669. } bdef
  670. % ---------------- CIDFontType0/2 fonts ---------------- %
  671. % Insert metrics into a CIDFont, by saving the PDF W, W2, DW, and DW2
  672. % arrays and using a (currently very inefficient) CDevProc.
  673. /addCIDmetrics { % <CIDFont-resource> <CIDFont> addCIDmetrics <fontdict>
  674. dup length 5 add dict .copydict
  675. dup /FID undef
  676. dup /UniqueID undef
  677. dup /XUID undef
  678. % Insert the widths into the font.
  679. {W W2 DW DW2} {
  680. % Stack: pdfresource newfont key
  681. 2 index 1 index .knownget {
  682. 2 index 3 1 roll put
  683. } {
  684. pop
  685. } ifelse
  686. } forall
  687. dup /CDevProc 1 index /CIDWProc load /exec load 3 packedarray cvx put
  688. exch pop
  689. } bdef
  690. % Apply the [D]W[2] metrics to a character before displaying.
  691. /CIDWProc { % <w0x> <w0y> <llx> <lly> <urx> <ury>
  692. % <w1x> <w1y> <vx> <vy> <cid> <font> CIDWproc
  693. % <w0x'> ... <vy'>
  694. begin
  695. % Look up and apply [D]W
  696. 10 index
  697. currentdict /DW .knownget { 1000 div exch pop } if
  698. currentdict /W .knownget {
  699. % Search the W array for the CID.
  700. % ****** NOT IMPLEMENTED YET ******
  701. pop
  702. } if
  703. 0 13 2 roll 11 -2 roll pop pop
  704. % Look up and apply [D]W2
  705. % ****** NOT IMPLEMENTED YET ******
  706. pop end
  707. } bdef
  708. % <string> <match> tailmatch ==> <pre> true
  709. % ==> <string> false
  710. /tailmatch {
  711. 2 copy length 1 index length min
  712. dup 2 index length exch sub exch getinterval
  713. 1 index eq {
  714. length 1 index length exch sub
  715. 0 exch getinterval true
  716. } {
  717. pop false
  718. } ifelse
  719. } bind def
  720. /makeboldfont {
  721. 16 dict begin
  722. /strokewidth exch def
  723. /basecidfont exch def
  724. /FontMatrix [ 1 0 0 1 0 0 ] def
  725. /CIDFontName /.boldfont def
  726. /CIDFontType 1 def
  727. /basefont-H /.basefont-H /Identity-H [ basecidfont ] composefont def
  728. /basefont-V /.basefont-V /Identity-V [ basecidfont ] composefont def
  729. /CIDSystemInfo dup basecidfont exch get def
  730. /FontBBox [ basecidfont /FontBBox get cvx exec
  731. 4 2 roll basecidfont /FontMatrix get transform
  732. 4 2 roll basecidfont /FontMatrix get transform
  733. ] def
  734. /tmpstr 2 string def
  735. /BuildGlyph {
  736. gsave
  737. exch begin
  738. dup 256 idiv tmpstr exch 0 exch put
  739. 256 mod tmpstr exch 1 exch put
  740. rootfont /WMode known { rootfont /WMode get 1 eq } { false } ifelse
  741. { basefont-V } { basefont-H } ifelse setfont
  742. strokewidth setlinewidth
  743. 1 setlinejoin
  744. newpath
  745. 0 0 moveto tmpstr false charpath stroke
  746. 0 0 moveto tmpstr show
  747. currentpoint setcharwidth
  748. end
  749. grestore
  750. } bind def
  751. currentdict
  752. end
  753. dup /CIDFontName get exch /CIDFont defineresource
  754. } bind def
  755. % <CIDFont-resource> <CIDFontName> findCIDFont <CIDFont-resource> <font>
  756. % CIDFont-resource is not modified.
  757. /findCIDFont {
  758. {
  759. dup /CIDFont resourcestatus {
  760. pop pop /CIDFont findresource
  761. exit
  762. } if
  763. dup dup length string cvs
  764. (,Bold) tailmatch {
  765. exch pop
  766. cvn findCIDFont 0.03 makeboldfont
  767. exit
  768. } if
  769. (,Italic) tailmatch {
  770. exch pop
  771. cvn findCIDFont
  772. [ 1 0 0.3 1 0 0 ] makefont
  773. exit
  774. } if
  775. (,BoldItalic) tailmatch {
  776. exch pop
  777. cvn findCIDFont 0.03 makeboldfont
  778. [ 1 0 0.3 1 0 0 ] makefont
  779. exit
  780. } if
  781. pop
  782. 1 index /CIDSystemInfo get begin Registry (-) Ordering end
  783. concatstrings concatstrings
  784. cvn
  785. QUIET not {
  786. (Substituting ) print dup ==only
  787. ( for ) print 1 index ==only (.\n) print
  788. } if
  789. exch pop
  790. /CIDFont findresource
  791. exit
  792. } loop
  793. } bdef
  794. /buildCIDType0 { % <CIDFontType0-font-resource> buildCIDType0 <font>
  795. dup /BaseFont get exch 1 index findCIDFont
  796. addCIDmetrics /CIDFont defineresource
  797. } bdef
  798. /buildCIDType2 { % <CIDFontType2-font-resource> buildCIDType2 <font>
  799. dup /BaseFont get exch 1 index findCIDFont
  800. addCIDmetrics /CIDFont defineresource
  801. } bdef
  802. % ---------------- Other embedded fonts ---------------- %
  803. /fontloadprocs mark
  804. /Type1C /readType1C cvx
  805. /CIDFontType0C /readCIDFontType0C cvx
  806. .dicttomark readonly def
  807. % Read an embedded compressed font.
  808. /readType1C { % <font-resource> <stream-dict> readType1C <font>
  809. 1 index exch
  810. PDFfile fileposition 3 1 roll
  811. dup true resolvestream dup readfontfilter
  812. % Stack: pos resource streamdict stream filter
  813. 3 index /FontDescriptor oget /FontName oget
  814. 1 index FRD
  815. closefile closefile pop
  816. PDFfile 3 -1 roll setfileposition
  817. /FontDescriptor oget /FontName oget findfont
  818. adjustfont
  819. } bdef
  820. % Read an embedded CFF CIDFont.
  821. /readCIDFontType0C { % <font-resource> <stream-dict> readCIDFontType0C <font>
  822. PDFfile fileposition 3 1 roll
  823. dup true resolvestream dup readfontfilter
  824. % Stack: pos resource streamdict stream filter
  825. 3 index /FontDescriptor oget /FontName oget
  826. 1 index FRD
  827. closefile closefile pop
  828. PDFfile 3 -1 roll setfileposition
  829. % Some broken Adobe software produces PDF files in which
  830. % the FontName of the CFF font and the FontName in the
  831. % FontDescriptor don't match the BaseFont in the font.
  832. % Use the FontName, rather than the BaseFont, here.
  833. dup /FontDescriptor oget /FontName oget /CIDFont findresource
  834. addCIDmetrics dup /CIDFontName get exch /CIDFont defineresource
  835. } bdef
  836. % ---------------- Font lookup ---------------- %
  837. /fonttypeprocs mark % <font-resource> -proc- <font>
  838. /Type0 /buildType0 cvx
  839. /Type1 /buildType1 cvx
  840. /MMType1 1 index
  841. /Type3 /buildType3 cvx
  842. /TrueType /buildTrueType cvx
  843. /CIDFontType0 /buildCIDType0 cvx
  844. /CIDFontType2 /buildCIDType2 cvx
  845. .dicttomark readonly def
  846. /resourcefont % <font-resource> resourcefont <font>
  847. { dup /PSFont .knownget
  848. { /FID .knownget { type /fonttype eq } { false } ifelse }
  849. { false }
  850. ifelse
  851. { /PSFont get
  852. }
  853. { dup dup /FontDescriptor knownoget
  854. { % Stack: font-res font-res font-desc
  855. dup /FontFile knownoget
  856. { exch pop readtype1 true }
  857. { dup /FontFile2 knownoget
  858. { exch pop readtruetype true }
  859. { /FontFile3 knownoget
  860. { dup /Subtype get fontloadprocs exch get exec true }
  861. { false }
  862. ifelse
  863. }
  864. ifelse
  865. }
  866. ifelse
  867. }
  868. { false }
  869. ifelse
  870. % Stack: font-res font-res false
  871. % -or-: font-res font true
  872. not
  873. { dup /Subtype get fonttypeprocs exch get exec }
  874. if
  875. 2 copy /PSFont exch put
  876. exch pop
  877. }
  878. ifelse
  879. } bdef
  880. drawopdict begin
  881. /d0 {
  882. .adjustcharwidth setcharwidth
  883. } bdef
  884. /d1 {
  885. 6 -2 roll .adjustcharwidth 6 2 roll setcachedevice
  886. } bdef
  887. /Tf {
  888. 1 index Page /Font rget not { 1 index /invalidfont signalerror } if
  889. resourcefont exch Tf pop
  890. } bdef
  891. end
  892. end % pdfdict
  893. end % GS_PDF_ProcSet
  894. .setglobal