gs_ttf.ps 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935
  1. % Copyright (C) 1996, 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: gs_ttf.ps,v 1.9 2001/07/08 15:24:11 lpd Exp $
  18. % Support code for direct use of TrueType fonts.
  19. % (Not needed for Type 42 fonts.)
  20. % Note that if you want to use this file without including the ttfont.dev
  21. % option when you built Ghostscript, you will need to load the following
  22. % files before this one:
  23. % lib/gs_mgl_e.ps
  24. % lib/gs_mro_e.ps
  25. % lib/gs_wan_e.ps
  26. % Thanks to B. Jackowski and GUST (the Polish TeX Users' Group) for
  27. % the glyf-splitting code.
  28. % ---------------- Font loading machinery ---------------- %
  29. % Augment the FONTPATH machinery so it recognizes TrueType fonts.
  30. /.scanfontheaders where {
  31. pop /.scanfontheaders [
  32. .scanfontheaders aload pop (\000\001\000\000*) (true*)
  33. ] def
  34. } if
  35. % <file> <key> .findfontvalue <value> true
  36. % <file> <key> .findfontvalue false
  37. % Closes the file in either case.
  38. /.findnonttfontvalue /.findfontvalue load def
  39. /.findfontvalue {
  40. 1 index read pop 2 index 1 index unread
  41. dup 0 eq exch (t) 0 get eq or {
  42. % If this is a font at all, it's a TrueType font.
  43. dup /FontType eq {
  44. pop closefile 42 true
  45. } {
  46. dup /FontName eq { pop .findttfontname } { pop closefile false } ifelse
  47. } ifelse
  48. } {
  49. % Not a TrueType font.
  50. .findnonttfontvalue
  51. } ifelse
  52. } bind def
  53. % <file> .findttfontname <fname> true
  54. % <file> .findttfontname false
  55. % Closes the file in either case.
  56. /.findttfontname {
  57. .loadttfonttables
  58. tabdict /name .knownget {
  59. dup 8 getu32 f exch setfileposition
  60. 12 getu32 string f exch readstring pop
  61. 6 findname
  62. } {
  63. false
  64. } ifelse
  65. f closefile end end
  66. } bind def
  67. % Load a font file that might be a TrueType font.
  68. % <file> .loadfontfile -
  69. /.loadnonttfontfile /.loadfontfile load def
  70. /.loadfontfile {
  71. dup read pop 2 copy unread 0 eq {
  72. % If this is a font at all, it's a TrueType font.
  73. .loadttfont pop
  74. } {
  75. % Not a TrueType font.
  76. .loadnonttfontfile
  77. } ifelse
  78. } bind def
  79. % ---------------- Automatic Type 42 generation ---------------- %
  80. % Load a TrueType font from a file as a Type 42 PostScript font.
  81. % The thing that makes this really messy is the handling of encodings.
  82. % There are 2 interacting tables that affect the encoding:
  83. % 'cmap' provides multiple maps from character codes to glyph indices
  84. % 'post' maps glyph indices to glyph names (if present)
  85. % What we need to get out of this is:
  86. % Encoding mapping character codes to glyph names
  87. % (the composition of cmap and post)
  88. % CharStrings mapping glyph names to glyph indices
  89. % (the inverse of post)
  90. % If the post table is missing, we have to take a guess based on the cmap
  91. % table.
  92. /.loadttfontdict 50 dict dup begin
  93. /orgXUID AladdinEnterprisesXUID def
  94. /maxstring 32000 def % half the maximum length of a PostScript string,
  95. % must be a multiple of 4 (for hmtx / loca / vmtx)
  96. % Define the Macintosh standard mapping from characters to glyph indices.
  97. /MacRomanEncoding dup .findencoding def
  98. /MacGlyphEncoding dup .findencoding def
  99. % Invert the MacRomanEncoding.
  100. /.romanmacdict 300 dict
  101. 0 1 MacRomanEncoding length 1 sub {
  102. MacRomanEncoding 1 index get
  103. % Stack: dict index charname
  104. dup /.notdef ne {
  105. exch 2 index 2 index .knownget {
  106. dup type /arraytype eq {
  107. [ exch aload pop counttomark 2 add -1 roll ]
  108. } {
  109. exch 2 array astore
  110. } ifelse
  111. } if 2 index 3 1 roll put
  112. } {
  113. pop pop
  114. } ifelse
  115. } for def
  116. % Define remapping for misnamed glyphs in TrueType 'post' tables.
  117. % There are probably a lot more than this!
  118. /postremap mark
  119. /Cdot /Cdotaccent
  120. /Edot /Edotaccent
  121. /Eoverdot /Edotaccent
  122. /Gdot /Gdotaccent
  123. /Ldot /Ldotaccent
  124. /Zdot /Zdotaccent
  125. /cdot /cdotaccent
  126. /edot /edotaccent
  127. /eoverdot /edotaccent
  128. /gdot /gdotaccent
  129. /ldot /ldotaccent
  130. /zdot /zdotaccent
  131. .dicttomark readonly def
  132. % ---- Utilities ---- %
  133. % Define a serial number for creating unique XUIDs for TrueType fonts.
  134. % We used to use the checkSumAdjustment value from the font, but this is
  135. % not reliable, since some fonts don't set it correctly.
  136. % Note that we must do this in a string to make it immune to save/restore.
  137. /xuidstring <80000000> def
  138. /curxuid { % - curxuid <int>
  139. 0 xuidstring { exch 8 bitshift exch add } forall
  140. } bind def
  141. /nextxuid { % - nextxuid -
  142. 3 -1 0 {
  143. xuidstring 1 index 2 copy get dup 255 ne {
  144. 1 add put pop exit
  145. } if pop 0 put pop
  146. } for
  147. } bind def
  148. % <string> <index> getu16 <integer>
  149. /getu16 {
  150. 2 copy get 8 bitshift 3 1 roll 1 add get add
  151. } bind def
  152. % <string> <index> gets16 <integer>
  153. /gets16 {
  154. getu16 16#8000 xor 16#8000 sub
  155. } bind def
  156. % <string> <index> getu32 <integer>
  157. /getu32 {
  158. 2 copy getu16 16 bitshift 3 1 roll 2 add getu16 add
  159. } bind def
  160. % <string> <index> gets32 <integer>
  161. /gets32 {
  162. 2 copy gets16 16 bitshift 3 1 roll 2 add getu16 add
  163. } bind def
  164. % <string> <index> <integer> putu16 -
  165. /putu16 {
  166. 3 copy -8 bitshift put
  167. exch 1 add exch 16#ff and put
  168. } bind def
  169. % <string> <index> <integer> putu32 -
  170. /putu32 {
  171. 3 copy -16 bitshift putu16
  172. exch 2 add exch 16#ffff and putu16
  173. } bind def
  174. % <nametable> <nameid> findname <string> true
  175. % <nametable> <nameid> findname false
  176. /findname {
  177. DEBUG { (findname: ) print dup =only } if
  178. false 3 1 roll 0 1 3 index 2 getu16 1 sub {
  179. % Stack: false table id index
  180. 12 mul 6 add 2 index exch 12 getinterval
  181. dup 6 getu16 2 index eq {
  182. % We found the name we want.
  183. exch pop
  184. % Stack: false table record
  185. dup 10 getu16 2 index 4 getu16 add
  186. 1 index 8 getu16 4 -1 roll 3 1 roll getinterval exch
  187. % Stack: false string record
  188. % Check for 8- vs. 16-bit characters.
  189. is2byte { string2to1 } if true null 4 -1 roll exit
  190. } if pop
  191. } for pop pop
  192. DEBUG {
  193. dup { ( = ) print 1 index == } { ( not found) = } ifelse
  194. } if
  195. } bind def
  196. % <namerecord> is2byte <bool>
  197. /is2byte {
  198. dup 0 getu16 {
  199. { pop true } % Apple Unicode
  200. { pop false } % Macintosh Script manager
  201. { 1 getu16 1 eq } % ISO
  202. { 1 getu16 1 eq } % Microsoft
  203. } exch get exec
  204. } bind def
  205. % <string2> string2to1 <string>
  206. /string2to1 {
  207. dup length 2 idiv string dup
  208. 0 1 3 index length 1 sub {
  209. 3 index 1 index 2 mul 1 add get put dup
  210. } for pop exch pop
  211. } bind def
  212. % <array> <lt-proc> sort <array>
  213. /sort {
  214. 1 index length 1 sub -1 1 {
  215. 2 index exch 2 copy get 3 copy % arr proc arr i arr[i] arr i arr[i]
  216. 0 1 3 index 1 sub {
  217. 3 index 1 index get % arr proc arr i arr[i] arr imax amax j arr[j]
  218. 2 index 1 index 10 index exec { % ... amax < arr[j]
  219. 4 2 roll
  220. } if pop pop
  221. } for % arr proc arr i arr[i] arr imax amax
  222. 4 -1 roll exch 4 1 roll put put
  223. } for pop
  224. } def
  225. % Each procedure in this dictionary is called as follows:
  226. % <encodingtable> proc <glypharray>
  227. /cmapformats mark
  228. 0 { % Apple standard 1-to-1 mapping.
  229. 6 256 getinterval { } forall 256 packedarray
  230. } bind
  231. 4 { % Microsoft/Adobe segmented mapping.
  232. /etab exch def
  233. /nseg2 etab 6 getu16 def
  234. 14 /endc etab 2 index nseg2 getinterval def
  235. % The Apple TrueType documentation omits the 2-byte
  236. % 'reserved pad' that follows the endCount vector!
  237. 2 add
  238. nseg2 add /startc etab 2 index nseg2 getinterval def
  239. nseg2 add /iddelta etab 2 index nseg2 getinterval def
  240. nseg2 add /idroff etab 2 index nseg2 getinterval def
  241. % The following hack allows us to properly handle
  242. % idiosyncratic fonts that start at 0xf000:
  243. pop
  244. /firstcode startc 0 getu16 16#ff00 and dup 16#f000 ne { pop 0 } if def
  245. /putglyph {
  246. glyphs code 3 -1 roll put /code code 1 add def
  247. } bind def
  248. % Do a first pass to compute the size of the glyphs array.
  249. /numcodes 0 def /glyphs 0 0 2 nseg2 3 sub {
  250. % Stack: /glyphs numglyphs i2
  251. /i2 exch def
  252. /scode startc i2 getu16 def
  253. /ecode endc i2 getu16 def
  254. numcodes scode firstcode sub
  255. % Hack for fonts that have only 0x0000 and 0xf000 ranges
  256. dup 16#e000 ge { 255 and } if
  257. exch sub 0 max ecode scode sub 1 add add
  258. exch 1 index add exch
  259. numcodes add /numcodes exch def
  260. } for array def
  261. % Now fill in the array.
  262. /numcodes 0 def /code 0 def
  263. 0 2 nseg2 3 sub {
  264. /i2 exch def
  265. /scode startc i2 getu16 def
  266. /ecode endc i2 getu16 def
  267. numcodes scode firstcode sub
  268. % Hack for fonts that have only 0x0000 and 0xf000 ranges
  269. dup 16#e000 ge { 255 and } if
  270. exch sub 0 max dup { 0 putglyph } repeat
  271. ecode scode sub 1 add add numcodes add /numcodes exch def
  272. /delta iddelta i2 gets16 def
  273. DEBUG {
  274. (scode=) print scode =only
  275. ( ecode=) print ecode =only
  276. ( delta=) print delta =only
  277. ( droff=) print idroff i2 getu16 =
  278. } if
  279. idroff i2 getu16 dup 0 eq {
  280. pop scode delta add 65535 and 1 ecode delta add 65535 and
  281. { putglyph } for
  282. } { % The +2 is for the 'reserved pad'.
  283. /gloff exch 14 nseg2 3 mul add 2 add i2 add add def
  284. 0 1 ecode scode sub {
  285. 2 mul gloff add etab exch getu16
  286. dup 0 ne { delta add 65535 and } if putglyph
  287. } for
  288. } ifelse
  289. } for glyphs /glyphs null def % for GC
  290. } bind
  291. 6 { % Single interval lookup.
  292. dup 6 getu16 /firstcode exch def dup 8 getu16 /ng exch def
  293. firstcode ng add array
  294. % Stack: tab array
  295. % Fill elements 0 .. firstcode-1 with 0
  296. 0 1 firstcode 1 sub { 2 copy 0 put pop } for
  297. dup firstcode ng getinterval
  298. % Stack: tab array subarray
  299. % Fill elements firstcode .. firstcode+nvalue-1 with glyph values
  300. 0 1 ng 1 sub {
  301. dup 2 mul 10 add 4 index exch getu16 3 copy put pop pop
  302. } for pop exch pop
  303. } bind
  304. .dicttomark readonly def % cmapformats
  305. % <cmaptab> cmaparray <glypharray>
  306. /cmaparray {
  307. dup 0 getu16 cmapformats exch .knownget {
  308. DEBUG {
  309. (cmap: format ) print 1 index 0 getu16 = flush
  310. } if exec
  311. } {
  312. (Can't handle format ) print 0 getu16 = flush
  313. 0 1 255 { } for 256 packedarray
  314. } ifelse
  315. DEBUG {
  316. (cmap: length=) print dup length = dup ==
  317. } if
  318. } bind def
  319. % Each procedure in this dictionary is called as follows:
  320. % posttable <<proc>> glyphencoding
  321. /postformats mark
  322. 16#00010000 { % 258 standard Macintosh glyphs.
  323. pop MacGlyphEncoding
  324. }
  325. 16#00020000 { % Detailed map, required by Microsoft fonts.
  326. /postglyphs exch def
  327. postglyphs 32 getu16 /numglyphs exch def
  328. /glyphnames numglyphs 2 mul 34 add def
  329. [ 0 1 numglyphs 1 sub {
  330. 2 mul 34 add postglyphs exch getu16
  331. dup 258 lt {
  332. MacGlyphEncoding exch get
  333. } {
  334. dup 32768 ge {
  335. % According to the published TrueType spec, such values are
  336. % "reserved for future use", but at least some PDF files
  337. % produced by the Adobe PDF library contain entries with a
  338. % value of 16#ffff.
  339. pop /.notdef
  340. } {
  341. 258 sub glyphnames exch {
  342. postglyphs 1 index get 1 add add
  343. } repeat
  344. 1 add postglyphs exch 2 copy 1 sub get getinterval cvn
  345. % At least some of Microsoft's TrueType fonts use incorrect
  346. % (Adobe-incompatible) names for some glyphs.
  347. % Correct for this here.
  348. postremap 1 index .knownget { exch pop } if
  349. } ifelse
  350. } ifelse
  351. } for ]
  352. } bind
  353. 16#00030000 { % No map.
  354. pop [ ]
  355. } bind
  356. .dicttomark readonly def % postformats
  357. % Each procedure in this dictionary is called as follows:
  358. % <file> <length> -proc- <string|array_of_strings>
  359. % Note that each table must have an even length, because of a strange
  360. % Adobe requirement that each sfnts entry have even length.
  361. /readtables mark
  362. % Ordinary tables
  363. (cmap) { .readtable }
  364. (head) 1 index
  365. (hhea) 1 index
  366. (maxp) 1 index
  367. (name) 1 index
  368. (OS/2) 1 index
  369. (post) 1 index
  370. (vhea) 1 index
  371. % Big tables
  372. (glyf) { .readbigtable }
  373. (loca) 1 index
  374. (hmtx) 1 index
  375. (vmtx) 1 index
  376. % Tables only needed for embedding in PDF files
  377. (cvt ) { .readtable }
  378. (fpgm) 1 index
  379. (prep) 1 index
  380. .dicttomark
  381. % Normally there would be a 'readonly' here, but the ttf2pf utility wants
  382. % to include the 'kern' table as well, so we leave the readtables dictionary
  383. % writable.
  384. def % readtables
  385. % Read a table as a single string.
  386. % <file> <length> .readtable <string>
  387. /.readtable {
  388. dup dup 1 and add string
  389. % Stack: f len str
  390. dup 0 4 -1 roll getinterval
  391. % Stack: f str str1
  392. % Because of the absurd PostScript specification that gives an
  393. % error for reading into an empty string, we have to check for
  394. % this explicitly here.
  395. 3 -1 roll exch
  396. dup () ne { readstring } if pop pop
  397. } bind def
  398. % Read a big table (one that may exceed 64K).
  399. % <file> <length> .readbigtable <string[s]>
  400. /.readbigtable {
  401. dup 65400 lt {
  402. .readtable
  403. } {
  404. currentuserparams /VMReclaim get -2 vmreclaim
  405. [ 4 2 roll {
  406. % Stack: mark ... f left
  407. dup maxstring le { exit } if
  408. 1 index maxstring string readstring pop 3 1 roll maxstring sub
  409. } loop .readtable ]
  410. exch vmreclaim
  411. } ifelse
  412. } bind def
  413. end readonly def % .loadttfontdict
  414. % <tab> .printtab -
  415. /.printtab {
  416. dup 0 4 getinterval print ( ) print
  417. dup 8 getu32 =only ( ) print
  418. 12 getu32 =
  419. } bind def
  420. % <file> .loadttfonttables -
  421. % Pushes .loadttfontdict & scratch dict on d-stack.
  422. % Defines f, offsets, tables, tabdict, tabs.
  423. /.loadttfonttables {
  424. .loadttfontdict begin
  425. 40 dict begin
  426. /f exch def
  427. /offsets f 12 string readstring pop def
  428. /tables f offsets 4 getu16 16 mul string readstring pop def
  429. /tabdict tables length 16 idiv dict def
  430. % tabs = tables we want to keep, sorted by file position.
  431. /tabs [ 0 16 tables length 1 sub {
  432. tables exch 16 getinterval
  433. DEBUG { dup .printtab } if
  434. dup 0 4 getinterval readtables 1 index known {
  435. tabdict exch 2 index put
  436. } {
  437. pop pop
  438. } ifelse
  439. } for ] {
  440. exch 8 getu32 exch 8 getu32 lt
  441. } sort def
  442. % In certain malformed TrueType fonts, tables overlap.
  443. % Truncate tables if necessary.
  444. 0 1 tabs length 2 sub {
  445. dup tabs exch get exch 1 add tabs exch get
  446. 1 index 8 getu32 2 index 12 getu32 add
  447. 1 index 8 getu32 gt {
  448. (**** Warning: ) print 1 index 0 4 getinterval print
  449. ( overlaps ) print dup 0 4 getinterval print
  450. (, truncating.) = flush
  451. dup 8 getu32 2 index 8 getu32 sub
  452. 2 index 12 3 -1 roll putu32
  453. } if pop pop
  454. } for
  455. } bind def
  456. % - .readttdata -
  457. % Read data. Updates offsets, tabs; stores data in tabdict.
  458. /.readttdata {
  459. /fpos offsets length tables length add def
  460. /sfpos offsets length tabs length 16 mul add def
  461. offsets 4 tabs length putu16
  462. tabs {
  463. dup 0 4 getinterval /tname exch def
  464. dup 8 getu32 /tpos exch def
  465. dup 12 getu32 /tlen exch def
  466. 8 sfpos putu32
  467. % Skip data between the end of the previous table and
  468. % the beginning of this one, if any.
  469. tpos fpos gt {
  470. f tpos fpos sub () /SubFileDecode filter dup flushfile closefile
  471. /fpos tpos def
  472. } if
  473. f tlen readtables tname get exec
  474. tabdict tname 3 -1 roll put
  475. /fpos fpos tlen add def
  476. % Round up the table length to an even value.
  477. /sfpos sfpos tlen dup 1 and add add def
  478. } forall
  479. } bind def
  480. % Find the string in a list of strings that includes a given index.
  481. % <strings> <index> .findseg <string> <index'>
  482. /.findseg {
  483. exch {
  484. dup length 2 index gt { exch exit } if
  485. length sub
  486. } forall
  487. } bind def
  488. % - .makesfnts -
  489. % Defines checksum, getloca, head, locatable, numloca, post, sfnts, upem
  490. /.makesfnts {
  491. .readttdata
  492. /head tabdict /head get def
  493. /locatable tabdict /loca get def
  494. /post tabdict /post .knownget not { null } if def
  495. /numloca
  496. locatable dup type /stringtype eq
  497. { length }
  498. { 0 exch { length add } forall }
  499. ifelse % no def yet
  500. locatable type /stringtype eq {
  501. /.indexloca {} def
  502. } {
  503. /.indexloca /.findseg load def
  504. } ifelse
  505. head 50 getu16 0 ne {
  506. /getloca {
  507. 2 bitshift locatable exch .indexloca getu32
  508. } def
  509. 4 idiv 1 sub
  510. } {
  511. /getloca {
  512. dup add locatable exch .indexloca getu16 dup add
  513. } def
  514. 2 idiv 1 sub
  515. } ifelse def % numloca
  516. % If necessary, re-partition the glyfs.
  517. tabdict /glyf get dup type /stringtype ne {
  518. .dividesfnts tabdict /glyf 3 -1 roll put
  519. } {
  520. pop
  521. } ifelse
  522. /sfnts [
  523. offsets tabs { concatstrings } forall
  524. tabs {
  525. 0 4 getinterval tabdict exch get
  526. dup type /stringtype ne { aload pop } if
  527. } forall
  528. ] def
  529. } bind def
  530. % <glyfs> .dividesfnts <glyfs'>
  531. /.dividesfnts {
  532. /glyfs exch def
  533. /len1 0 glyfs { length add } forall def
  534. % Determine where to split the glyfs by scanning loca.
  535. % The very last entry in loca may be bogus.
  536. % Note that some loca entries may be odd, but we can only
  537. % split at even positions.
  538. %
  539. % Construct splitarray, the array of final lengths of
  540. % the sfnts entries covering the glyfs (i.e., all but
  541. % the first and last sfnts entries).
  542. /prevsplit 0 def
  543. /prevboundary 0 def
  544. /splitarray [
  545. 0 1 numloca 1 sub {
  546. getloca dup prevsplit maxstring add gt {
  547. prevboundary prevsplit sub exch
  548. /prevsplit prevboundary def
  549. } if
  550. dup 1 and 0 eq { /prevboundary exch def } { pop } ifelse
  551. } for
  552. len1 prevsplit sub
  553. ] def
  554. currentuserparams /VMReclaim get -2 vmreclaim
  555. [
  556. % Re-split the sfnts glyfs strings according to splitarray.
  557. % We do this by iterating over the final segments defined
  558. % by splitarray, and constructing them from pieces of the
  559. % current glyfs strings. We recycle the current strings
  560. % when possible, to avoid stressing the allocator.
  561. /sfnt_idx 0 def
  562. /strpos 0 def
  563. /avail () def
  564. splitarray {
  565. /seglen exch def
  566. /segpos 0 def
  567. avail length seglen ge
  568. { avail 0 seglen getinterval /avail () def } { seglen string }
  569. ifelse
  570. {
  571. /str glyfs sfnt_idx get def
  572. /strlen str length def
  573. /strleft strlen strpos sub def
  574. seglen segpos sub strleft lt { exit } if
  575. % Copy the (rest of the) string into the new segment.
  576. % We know strleft <= segleft.
  577. dup segpos str strpos strleft getinterval putinterval
  578. /segpos segpos strleft add def
  579. /avail str def
  580. /sfnt_idx sfnt_idx 1 add def
  581. /strpos 0 def
  582. segpos seglen eq { exit } if
  583. } loop
  584. % Fill up the segment with an initial piece of the next
  585. % existing glyfs string. We know strleft > segleft.
  586. /segleft seglen segpos sub def
  587. dup segpos str strpos segleft getinterval putinterval
  588. /strpos strpos segleft add def
  589. } forall
  590. ]
  591. exch vmreclaim
  592. } bind def
  593. % - .getpost -
  594. % Uses post, defines glyphencoding
  595. /.getpost {
  596. /glyphencoding post null eq {
  597. DEBUG { (post missing) = flush } if [ ]
  598. } {
  599. postformats post 0 getu32 .knownget {
  600. DEBUG {
  601. (post: format ) print
  602. post 0 getu16 =only (,) print post 2 getu16 = flush
  603. } if
  604. post exch exec
  605. } {
  606. DEBUG { (post: unknown format ) print post 0 getu32 = flush } if [ ]
  607. } ifelse
  608. } ifelse def
  609. } bind def
  610. % - .ttkeys <key> <value> ...
  611. /.ttkeys {
  612. count /ttkeycount exch def
  613. /upem head 18 getu16 def
  614. /FontMatrix matrix
  615. /FontBBox [ 36 2 42 { head exch gets16 upem div } for ]
  616. nextxuid
  617. tabdict /name .knownget {
  618. % Find the names from the 'name' table.
  619. /names exch def
  620. /FontName names 6 findname not { curxuid 16 8 string cvrs } if
  621. /fontname 1 index def
  622. /FontInfo mark
  623. names 0 findname { /Notice exch } if
  624. names 1 findname { /FamilyName exch } if
  625. names 4 findname { /FullName exch } if
  626. names 5 findname { /Version exch } if
  627. } {
  628. % No name table, fabricate a FontName.
  629. /FontName curxuid 16 8 string cvrs
  630. /fontname 1 index def
  631. /FontInfo mark
  632. } ifelse
  633. % Stack: ... /FontInfo mark key1 value1 ...
  634. post null ne {
  635. /ItalicAngle post 4 gets32 65536.0 div
  636. /isFixedPitch post 12 getu32 0 ne
  637. /UnderlinePosition post 8 gets16 upem div
  638. /UnderlineThickness post 10 gets16 upem div
  639. } if
  640. counttomark 0 ne { .dicttomark } { pop pop } ifelse
  641. /XUID [orgXUID 42 curxuid]
  642. DEBUG {
  643. tabs { .printtab } forall
  644. [ sfnts { length } forall ] ==
  645. count ttkeycount sub array astore dup { == } forall aload pop
  646. } if
  647. /sfnts sfnts
  648. } bind def
  649. % ---------------- Standard TrueType font loading ---------------- %
  650. % - .pickcmap -
  651. % Defines cmapsub, cmaptab
  652. /.pickcmap {
  653. tabdict /cmap get
  654. % The Apple cmap format is no help in determining the encoding.
  655. % Look for a Microsoft table. If we can't find one,
  656. % just use the first table, whatever it is.
  657. dup 4 8 getinterval exch % the default
  658. 0 1 2 index 2 getu16 1 sub {
  659. 8 mul 4 add 1 index exch 8 getinterval
  660. DEBUG {
  661. (cmap: platform ) print dup 0 getu16 =only
  662. ( encoding ) print dup 2 getu16 = flush
  663. } if
  664. dup 0 getu16 3 eq { exch 3 -1 roll pop exit } if pop
  665. } for
  666. % Stack: subentry table
  667. /cmapsub 2 index def
  668. exch 4 getu32 1 index length 1 index sub getinterval
  669. /cmaptab exch def
  670. } bind def
  671. % <glyph> .nname <_name>
  672. /.nname {
  673. =string cvs (_) exch concatstrings cvn
  674. } bind def
  675. % - .charkeys /CharStrings <charstrings> /Encoding <encoding>
  676. % Resets glyphencoding
  677. /.charkeys {
  678. DEBUG {
  679. (glyphencoding: length=) print glyphencoding dup length = === flush
  680. } if
  681. % Hack: if there is no usable post table but the cmap uses
  682. % the Microsoft Unicode encoding, use ISOLatin1Encoding.
  683. glyphencoding length 0 eq cmapsub 0 4 getinterval <00030001> eq and {
  684. /glyphencoding ISOLatin1Encoding dup length array copy def
  685. } if
  686. % If necessary, fabricate additional glyphencoding entries
  687. % to cover all of loca, or truncate glyphencoding.
  688. glyphencoding length numloca lt {
  689. /glyphencoding [ glyphencoding aload pop
  690. counttomark 1 numloca 1 sub { .nname } for ] def
  691. } {
  692. /glyphencoding glyphencoding 0 numloca getinterval def
  693. } ifelse
  694. % Some badly designed Chinese fonts have a post table
  695. % in which all glyphs other than 0 are named .null.
  696. % Use CharStrings to keep track of the reverse map from
  697. % names to glyphs, and don't let any name be used for
  698. % more than one glyph.
  699. /CharStrings glyphencoding dup length 1 add dict % +1 for .notdef
  700. 0 1 3 index length 1 sub {
  701. % Stack: glyphencoding dict index
  702. 2 index 1 index get 2 index 1 index known {
  703. % The same name maps to more than one glyph.
  704. % Change the name.
  705. pop dup .nname 3 index 2 index 2 index put
  706. } if
  707. 2 index exch 3 -1 roll put
  708. } for exch pop
  709. % If there is no .notdef entry, map it to glyph 0.
  710. dup /.notdef known not { dup /.notdef 0 put } if
  711. readonly
  712. /Encoding
  713. [ cmaptab cmaparray dup length 256 gt { 0 256 getinterval } if
  714. { glyphencoding exch get } forall
  715. counttomark 256 exch sub { /.notdef } repeat ]
  716. DEBUG { (Encoding: ) print dup === flush } if
  717. } bind def
  718. % -mark- <key> <value> ... .definettfont <font>
  719. /.definettfont {
  720. /FontType 42
  721. /PaintType 0
  722. DEBUG {
  723. (numloca=) print numloca =
  724. } if
  725. .dicttomark
  726. end end dup /FontName get exch definefont
  727. } bind def
  728. % <file> .loadttfont <type42font>
  729. /.loadttfont {
  730. .loadttfonttables
  731. .makesfnts
  732. .getpost
  733. .pickcmap
  734. mark
  735. .charkeys
  736. .ttkeys
  737. .definettfont
  738. } bind def
  739. % ---------------- CIDFontType 2 font loading ---------------- %
  740. % Create a string with N CIDs from the top of the stack.
  741. % <cid1> ... <cidN> <N> .makecidmap <string>
  742. /.makecidmap {
  743. dup 2 mul string dup 3 -1 roll 1 sub 2 mul -2 0 {
  744. % Stack: cids str str i2
  745. 2 copy 5 index -8 bitshift put
  746. 1 add 4 -1 roll 16#ff and put dup
  747. } for pop
  748. } bind def
  749. % -mark- <key> <value> ... .definettcidfont <font>
  750. /.definettcidfont {
  751. /CIDFontName fontname
  752. /CIDFontType 2
  753. /CIDSystemInfo mark
  754. /Registry (Adobe)
  755. /Ordering (Japan1) % adhoc
  756. /Supplement 0
  757. .dicttomark
  758. /CharStrings mark /.notdef 0 .dicttomark
  759. % The cmap isn't of any use even if it is present.
  760. % Just construct an identity CIDMap covering all the glyphs.
  761. mark 0 1 numloca 1 sub { } for
  762. counttomark /cidcount exch def
  763. cidcount maxstring le {
  764. % Use a single string.
  765. cidcount .makecidmap exch pop
  766. } {
  767. % We must use 2 strings.
  768. maxstring .makecidmap counttomark 1 add 1 roll
  769. counttomark .makecidmap exch pop exch 2 array astore
  770. } ifelse
  771. /CIDMap exch
  772. /CIDCount cidcount
  773. /GDBytes 2
  774. .dicttomark
  775. end end dup /CIDFontName get exch /CIDFont defineresource
  776. } bind def
  777. % <file> .loadttcidfont <cidtype2font>
  778. /.loadttcidfont {
  779. .loadttfonttables
  780. .makesfnts
  781. % CIDFontType2 fonts don't have a cmap: they are indexed by CID.
  782. mark
  783. .ttkeys
  784. .definettcidfont
  785. } bind def
  786. % ---------------- PDF TrueType font loading ---------------- %
  787. % Strictly speaking, this code should be loaded only if we have a PDF
  788. % interpreter, but it's so closely tied to the rest of the code in this
  789. % file that we always include it.
  790. % <plat+enc> .findcmap <subtable> true
  791. % <plat+enc> .findcmap false
  792. /.findcmap {
  793. false exch tabdict /cmap get
  794. % Some fonts have multiple cmaps with the same platform and
  795. % encoding. Use the first one we find.
  796. 0 1 2 index 2 getu16 1 sub {
  797. % Stack: false plat+enc cmap index
  798. 8 mul 4 add 1 index exch 8 getinterval
  799. dup 0 4 getinterval 3 index eq {
  800. 4 getu32 1 index exch 1 index length 1 index sub getinterval
  801. 4 -1 roll not 4 2 roll exit
  802. } if pop
  803. } for
  804. % Stack: false plat+enc cmap || subtable true plat+enc cmap
  805. pop pop
  806. } bind def
  807. % <subcmap> <chartoglyphmap> .pdfmapchars
  808. % /CharStrings <charstrings> /Encoding <encoding>
  809. % Uses encoding
  810. /.pdfmapchars {
  811. exch cmaparray /cmapencoding exch def
  812. % Invert glyphencoding (post).
  813. /inversepost glyphencoding length dict def
  814. 0 1 glyphencoding length 1 sub {
  815. glyphencoding 1 index get exch inversepost 3 1 roll put
  816. } for
  817. /CharStrings mark 3 -1 roll {
  818. dup type /arraytype eq {
  819. exch /ch exch def { ch exch .pdfaddchar } forall
  820. } {
  821. .pdfaddchar
  822. } ifelse
  823. } forall
  824. % Add a .notdef => 0 entry if needed. Per Adobe's spec,
  825. % .dicttomark (>>) adds pairs in top-to-bottom order.
  826. /.notdef 0
  827. .dicttomark
  828. /Encoding encoding
  829. } bind def
  830. % <charname> <charcode> .pdfaddchar <charname> <glyph#>
  831. % <charname> <charcode> .pdfaddchar -
  832. /.pdfaddchar {
  833. dup cmapencoding length lt {
  834. cmapencoding exch get dup 0 eq {
  835. pop .pdfaddpost
  836. } if
  837. } {
  838. pop .pdfaddpost
  839. } ifelse
  840. } bind def
  841. % <charname> .pdfaddpost <charname> <glyph#>
  842. % <charname> .pdfaddpost -
  843. /.pdfaddpost {
  844. inversepost 1 index .knownget not { pop } if
  845. } bind def
  846. % - .pdfcharkeys /CharStrings <charstrings> /Encoding <encoding>
  847. /.pdfcharkeys {
  848. % The following algorithms are per the PDF Reference, Second Edition
  849. % (PDF 1.3 reference manual).
  850. encoding null eq {
  851. .charkeys % use default algorithm
  852. } {
  853. <00030001> .findcmap {
  854. AdobeGlyphList .pdfmapchars
  855. } {
  856. <00010000> .findcmap {
  857. .romanmacdict .pdfmapchars
  858. } {
  859. .charkeys % use default algorithm
  860. } ifelse
  861. } ifelse
  862. } ifelse
  863. } bind def
  864. % <file> <encoding|null> .loadpdfttfont <type42font>
  865. /.loadpdfttfont {
  866. exch .loadttfonttables
  867. /encoding exch def
  868. .makesfnts
  869. .getpost
  870. .pickcmap
  871. mark
  872. .pdfcharkeys
  873. .ttkeys
  874. .definettfont
  875. } bind def