gs_ttf.ps 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456
  1. % Copyright (C) 1996-2003 artofcode LLC. 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_ttf.ps,v 1.48 2005/09/22 16:11:37 ray Exp $
  16. % Support code for direct use of TrueType fonts.
  17. % (Not needed for Type 42 fonts.)
  18. % Note that if you want to use this file without including the ttfont.dev
  19. % option when you built Ghostscript, you will need to load the following
  20. % files before this one:
  21. % lib/gs_mgl_e.ps
  22. % lib/gs_mro_e.ps
  23. % lib/gs_wan_e.ps
  24. % Thanks to B. Jackowski and GUST (the Polish TeX Users' Group) for
  25. % the glyf-splitting code.
  26. % ---------------- Font loading machinery ---------------- %
  27. % Augment the FONTPATH machinery so it recognizes TrueType fonts.
  28. /.scanfontheaders where {
  29. pop /.scanfontheaders [
  30. .scanfontheaders aload pop (\000\001\000\000*) (true*)
  31. ] def
  32. } if
  33. % <file> <key> .findfontvalue <value> true
  34. % <file> <key> .findfontvalue false
  35. % Closes the file in either case.
  36. /.findnonttfontvalue /.findfontvalue load def
  37. /.findfontvalue {
  38. 1 index read {
  39. 2 index 1 index unread
  40. % beginning with binary 0 or 't' (TrueType), or 'O' (OpenType)
  41. dup 0 eq 1 index (O) 0 get eq or 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. } { pop closefile false } ifelse
  53. } bind def
  54. % <file> .findttfontname <fname> true
  55. % <file> .findttfontname false
  56. % Closes the file in either case.
  57. /.findttfontname {
  58. //true 0 .loadttfonttables
  59. tabdict /name .knownget {
  60. dup 8 getu32 f exch setfileposition
  61. 12 getu32 string f exch readstring pop
  62. 6 findname
  63. } {
  64. false
  65. } ifelse
  66. f closefile end end
  67. } bind def
  68. % Load a font file that might be a TrueType font.
  69. % <file> .loadfontfile -
  70. /.loadnonttfontfile /.loadfontfile load def
  71. /.loadfontfile {
  72. dup read pop 2 copy unread 0 eq {
  73. % If this is a font at all, it's a TrueType font.
  74. .loadttfont pop
  75. } {
  76. % Not a TrueType font.
  77. .loadnonttfontfile
  78. } ifelse
  79. } bind def
  80. % ---------------- Automatic Type 42 generation ---------------- %
  81. % Load a TrueType font from a file as a Type 42 PostScript font.
  82. % The thing that makes this really messy is the handling of encodings.
  83. % There are 2 interacting tables that affect the encoding:
  84. % 'cmap' provides multiple maps from character codes to glyph indices
  85. % 'post' maps glyph indices to glyph names (if present)
  86. % What we need to get out of this is:
  87. % Encoding mapping character codes to glyph names
  88. % (the composition of cmap and post)
  89. % CharStrings mapping glyph names to glyph indices
  90. % (the inverse of post)
  91. % If the post table is missing, we have to take a guess based on the cmap
  92. % table.
  93. /.loadttfontdict 50 dict dup begin
  94. /orgXUID AladdinEnterprisesXUID def
  95. /maxstring 32764 def % half the maximum length of a PostScript string,
  96. % must be a multiple of 4 (for hmtx / loca / vmtx)
  97. /.invert_encoding % <array> invert_encoding <dict>
  98. { dup 256 dict exch
  99. 0 exch 1 exch length 1 sub { % [] <> i
  100. dup 3 index exch get % [] <> i v
  101. dup /.notdef ne {
  102. exch 2 index 2 index .knownget {
  103. dup type /arraytype eq {
  104. [ exch aload pop counttomark 2 add -1 roll ]
  105. } {
  106. exch 2 array astore
  107. } ifelse
  108. } if 2 index 3 1 roll put
  109. } {
  110. pop pop
  111. } ifelse
  112. } for
  113. exch pop
  114. } bind def
  115. % Define the Macintosh standard mapping from characters to glyph indices.
  116. /MacRomanEncoding dup .findencoding def
  117. /MacGlyphEncoding dup .findencoding def
  118. % Invert the MacRomanEncoding.
  119. /.romanmacdict MacRomanEncoding .invert_encoding def
  120. % Define remapping for misnamed glyphs in TrueType 'post' tables.
  121. % There are probably a lot more than this!
  122. /postremap mark
  123. /Cdot /Cdotaccent
  124. /Edot /Edotaccent
  125. /Eoverdot /Edotaccent
  126. /Gdot /Gdotaccent
  127. /Ldot /Ldotaccent
  128. /Zdot /Zdotaccent
  129. /cdot /cdotaccent
  130. /edot /edotaccent
  131. /eoverdot /edotaccent
  132. /gdot /gdotaccent
  133. /ldot /ldotaccent
  134. /zdot /zdotaccent
  135. .dicttomark readonly def
  136. % Array used for fast pre-filling of cmap array
  137. /.array1024z [ 1024 { 0 } repeat ] def
  138. % ---- Utilities ---- %
  139. % Define a serial number for creating unique XUIDs for TrueType fonts.
  140. % We used to use the checkSumAdjustment value from the font, but this is
  141. % not reliable, since some fonts don't set it correctly.
  142. % Note that we must do this in a string to make it immune to save/restore.
  143. /xuidstring <80000000> def
  144. /curxuid { % - curxuid <int>
  145. 0 xuidstring { exch 8 bitshift exch add } forall
  146. } bind def
  147. /nextxuid { % - nextxuid -
  148. 3 -1 0 {
  149. xuidstring 1 index 2 copy get dup 255 ne {
  150. 1 add put pop exit
  151. } if pop 0 put pop
  152. } for
  153. } bind def
  154. % <string> <index> getu16 <integer>
  155. /getu16 {
  156. 2 copy get 8 bitshift 3 1 roll 1 add get add
  157. } bind def
  158. % <string> <index> gets16 <integer>
  159. /gets16 {
  160. getu16 16#8000 xor 16#8000 sub
  161. } bind def
  162. % <string> <index> getu32 <integer>
  163. /getu32 {
  164. 2 copy getu16 16 bitshift 3 1 roll 2 add getu16 add
  165. } bind def
  166. % <string> <index> gets32 <integer>
  167. /gets32 {
  168. 2 copy gets16 16 bitshift 3 1 roll 2 add getu16 add
  169. } bind def
  170. 16#ffffffff 0 gt { % 64-bit sign extension
  171. { /curxuid /gets32 } {
  172. mark 1 index load aload pop { 16#80000000 xor 16#80000000 sub } aload pop
  173. .packtomark cvx def
  174. } bind forall
  175. } if
  176. % <string> <index> <integer> putu16 -
  177. /putu16 {
  178. 3 copy -8 bitshift put
  179. exch 1 add exch 16#ff and put
  180. } bind def
  181. % <string> <index> <integer> putu32 -
  182. /putu32 {
  183. 3 copy -16 bitshift putu16
  184. exch 2 add exch 16#ffff and putu16
  185. } bind def
  186. % <nametable> <nameid> findname <string> true
  187. % <nametable> <nameid> findname false
  188. /findname {
  189. TTFDEBUG { (findname: ) print dup =only } if
  190. false 3 1 roll
  191. 1 index length 0 gt { % check for zero length name table
  192. 0 1 3 index 2 getu16 1 sub {
  193. % Stack: false table id index
  194. 12 mul 6 add 2 index exch 12 getinterval
  195. dup 6 getu16 2 index eq {
  196. % We found the name we want.
  197. exch pop
  198. % Stack: false table record
  199. dup 10 getu16 2 index 4 getu16 add
  200. 1 index 8 getu16 4 -1 roll 3 1 roll
  201. 3 copy add 1 index length
  202. le {
  203. pop
  204. getinterval exch
  205. % Stack: false string record
  206. % Check for 8- vs. 16-bit characters.
  207. is2byte { string2to1 } if true null 4 -1 roll exit
  208. } {
  209. pop pop pop pop
  210. false
  211. exit
  212. } ifelse
  213. } if pop
  214. } for
  215. } if
  216. pop pop
  217. TTFDEBUG {
  218. dup { ( = ) print 1 index == } { ( not found) = } ifelse
  219. } if
  220. } bind def
  221. % <namerecord> is2byte <bool>
  222. /is2byte {
  223. dup 0 getu16 {
  224. { pop true } % Apple Unicode
  225. { pop false } % Macintosh Script manager
  226. { 1 getu16 1 eq } % ISO
  227. { 1 getu16 1 eq } % Microsoft
  228. } exch get exec
  229. } bind def
  230. % <string2> string2to1 <string>
  231. /string2to1 {
  232. dup length 2 idiv string dup
  233. 0 1 3 index length 1 sub {
  234. 3 index 1 index 2 mul 1 add get put dup
  235. } for pop exch pop
  236. } bind def
  237. % Each procedure in this dictionary is called as follows:
  238. % <encodingtable> proc <glypharray>
  239. /cmapformats mark
  240. 0 { % Apple standard 1-to-1 mapping.
  241. 6 256 getinterval { } forall 256 packedarray
  242. } bind
  243. 2 { % Apple 16bit CJK (ShiftJIS etc)
  244. % /sHK_sz subHeaderKey_size % 1 * uint16
  245. % /sH_sz subHeader_size % 4 * uint16
  246. % /sH_len subHeader_length
  247. % /cmapf2_tblen total table length
  248. % /cmapf2_lang language code (not used)
  249. % /sHKs subHeaderKeys
  250. /sHK_sz 2 def
  251. /sH_sz 8 def
  252. dup 2 getu16 /cmapf2_tblen exch def
  253. dup 4 getu16 /cmapf2_lang exch def
  254. dup 6 256 sHK_sz mul getinterval /sHKs exch def
  255. 0 % initialization value for /sH_len
  256. 0 1 255 {
  257. sHKs exch
  258. 2 mul getu16
  259. 1 index % get current max
  260. 1 index % get current subHeaderKey
  261. lt {exch} if pop
  262. } for
  263. /sH_len exch def
  264. dup 6 256 sHK_sz mul add
  265. cmapf2_tblen 1 index sub getinterval
  266. /sH_gIA exch def
  267. /cmapf2_glyph_array 65535 array def
  268. /.cmapf2_putGID {
  269. /cmapf2_ch cmapf2_ch_hi 8 bitshift cmapf2_ch_lo add def
  270. firstCode cmapf2_ch_lo le
  271. cmapf2_ch_lo firstCode entryCount add lt
  272. and { % true: j is inside
  273. sH_offset idRangeOffset add % offset to gI
  274. cmapf2_ch_lo firstCode sub 2 mul % rel. pos. in range
  275. add 6 add % offset in sH_gIA
  276. sH_gIA exch getu16
  277. dup 0 gt { %
  278. idDelta add
  279. cmapf2_glyph_array exch cmapf2_ch exch put
  280. } {
  281. pop
  282. % cmapf2_glyph_array cmapf2_ch 0 put
  283. } ifelse
  284. } { % false: j is outside
  285. % cmapf2_glyph_array cmapf2_ch 0 put
  286. } ifelse
  287. } def
  288. 16#00 1 16#ff { % hi_byte scan
  289. /cmapf2_ch_hi exch def
  290. sHKs cmapf2_ch_hi sHK_sz mul getu16
  291. /sH_offset exch def
  292. sH_gIA sH_offset sH_sz getinterval
  293. dup 0 getu16 /firstCode exch def
  294. dup 2 getu16 /entryCount exch def
  295. dup 4 gets16 /idDelta exch def
  296. dup 6 getu16 /idRangeOffset exch def
  297. pop
  298. sH_offset 0 eq {
  299. /cmapf2_ch_lo cmapf2_ch_hi def
  300. /cmapf2_ch_hi 0 def
  301. .cmapf2_putGID
  302. } {
  303. 16#00 1 16#ff { % lo_byte scan
  304. /cmapf2_ch_lo exch def
  305. .cmapf2_putGID
  306. } for
  307. } ifelse
  308. } for
  309. pop
  310. 0 1 cmapf2_glyph_array length 1 sub { % rewrite null -> 0.
  311. dup cmapf2_glyph_array exch get
  312. null eq { cmapf2_glyph_array exch 0 put } {pop} ifelse
  313. } for
  314. cmapf2_glyph_array
  315. } bind
  316. 4 { % Microsoft/Adobe segmented mapping.
  317. /etab exch def
  318. /nseg2 etab 6 getu16 def
  319. 14 /endc etab 2 index nseg2 getinterval def
  320. % The Apple TrueType documentation omits the 2-byte
  321. % 'reserved pad' that follows the endCount vector!
  322. 2 add
  323. nseg2 add /startc etab 2 index nseg2 getinterval def
  324. nseg2 add /iddelta etab 2 index nseg2 getinterval def
  325. nseg2 add /idroff etab 2 index nseg2 getinterval def
  326. % The following hack allows us to properly handle
  327. % idiosyncratic fonts that start at 0xf000:
  328. pop
  329. /firstcode startc 0 getu16 16#ff00 and dup 16#f000 ne { pop 0 } if def
  330. /putglyph {
  331. glyphs code 3 -1 roll put /code code 1 add def
  332. } bind def
  333. % Do a first pass to compute the size of the glyphs array.
  334. /numcodes 0 def /glyphs 0 0 2 nseg2 3 sub {
  335. % Stack: /glyphs numglyphs i2
  336. /i2 exch def
  337. /scode startc i2 getu16 def
  338. /ecode endc i2 getu16 def
  339. numcodes scode firstcode sub
  340. % Hack for fonts that have only 0x0000 and 0xf000 ranges
  341. %dup 16#e000 ge { 255 and } if
  342. % the previous line is obstructive to CJK fonts, so it was removed
  343. exch sub 0 .max ecode scode sub 1 add add
  344. exch 1 index add exch
  345. numcodes add /numcodes exch def
  346. } for array def
  347. % prefill the array with 0's faster than a { 0 putglyph } repeat
  348. glyphs length 1024 ge {
  349. .array1024z 0 1024 glyphs length 1023 sub { glyphs exch 2 index putinterval } for
  350. glyphs dup length 1024 sub 3 -1 roll
  351. putinterval
  352. } {
  353. 0 1 glyphs length 1 sub { glyphs exch 0 put } for
  354. } ifelse
  355. % Now fill in the array.
  356. /numcodes 0 def /code 0 def
  357. 0 2 nseg2 3 sub {
  358. /i2 exch def
  359. /scode startc i2 getu16 def
  360. /ecode endc i2 getu16 def
  361. numcodes scode firstcode sub
  362. % Hack for fonts that have only 0x0000 and 0xf000 ranges
  363. %dup 16#e000 ge { 255 and } if
  364. % the previous line is obstructive to CJK fonts, so it was removed
  365. exch sub 0 .max dup /code exch code exch add def
  366. ecode scode sub 1 add add numcodes add /numcodes exch def
  367. /delta iddelta i2 gets16 def
  368. TTFDEBUG {
  369. (scode=) print scode =only
  370. ( ecode=) print ecode =only
  371. ( delta=) print delta =only
  372. ( droff=) print idroff i2 getu16 =
  373. } if
  374. idroff i2 getu16 dup 0 eq {
  375. pop scode delta add 65535 and 1 ecode delta add 65535 and
  376. { putglyph } for
  377. } { % The +2 is for the 'reserved pad'.
  378. /gloff exch 14 nseg2 3 mul add 2 add i2 add add def
  379. 0 1 ecode scode sub {
  380. 2 mul gloff add etab exch getu16
  381. dup 0 ne { delta add 65535 and } if putglyph
  382. } for
  383. } ifelse
  384. } for glyphs /glyphs null def % for GC
  385. } bind
  386. 6 { % Single interval lookup.
  387. dup 6 getu16 /firstcode exch def dup 8 getu16 /ng exch def
  388. firstcode ng add array
  389. % Stack: tab array
  390. % Fill elements 0 .. firstcode-1 with 0
  391. 0 1 firstcode 1 sub { 2 copy 0 put pop } for
  392. dup firstcode ng getinterval
  393. % Stack: tab array subarray
  394. % Fill elements firstcode .. firstcode+nvalue-1 with glyph values
  395. 0 1 ng 1 sub {
  396. dup 2 mul 10 add 4 index exch getu16 3 copy put pop pop
  397. } for pop exch pop
  398. } bind
  399. .dicttomark readonly def % cmapformats
  400. % <cmaptab> cmaparray <glypharray>
  401. /cmaparray {
  402. dup 0 getu16 cmapformats exch .knownget {
  403. TTFDEBUG {
  404. (cmap: format ) print 1 index 0 getu16 = flush
  405. } if exec
  406. } {
  407. (Can't handle format ) print 0 getu16 = flush
  408. 0 1 255 { } for 256 packedarray
  409. } ifelse
  410. TTFDEBUG {
  411. (cmap: length=) print dup length = dup ==
  412. } if
  413. } bind def
  414. /get_from_stringarray % <array|string> <offset> get_from_stringarray <int>
  415. { 1 index type /stringtype eq {
  416. get
  417. } {
  418. exch { % o ()
  419. 2 copy length gt {
  420. length sub
  421. } {
  422. exch get exit
  423. } ifelse
  424. } forall
  425. } ifelse
  426. } bind def
  427. /getinterval_from_stringarray % <array|string> <offset> <length> getinterval_from_stringarray <string>
  428. { % May allocate a string in VM.
  429. 2 index type /stringtype eq {
  430. getinterval
  431. } {
  432. string exch 0 % [] s o p
  433. 4 3 roll { % s o p Si
  434. dup length % s o p Si lSi
  435. dup 4 index lt {
  436. 3 index exch sub % s o p Si o'
  437. exch pop 3 1 roll exch pop % s o' p
  438. } { % s o p Si lSi
  439. dup 3 1 roll % s o p lSi Si lSi
  440. 4 index sub % s o p lSi Si lSi-o
  441. 5 index length 4 index sub % s o p lSi Si lSi-o ls-p
  442. 2 copy gt { exch } if pop % s o p lSi Si minl
  443. dup 3 1 roll % s o p lSi minl Si minl
  444. 5 index exch getinterval % s o p lSi minl from
  445. 5 index 4 index 3 index % s o p lSi minl from s p minl
  446. getinterval % s o p lSi minl from to
  447. copy pop % s o p lSi minl
  448. 3 1 roll % s o minl p lSi
  449. sub % s o minl p'
  450. 3 1 roll add % s p' o'
  451. dup 3 index length ge {
  452. exch exit % s o p'
  453. } if
  454. exch % s o' p'
  455. } ifelse
  456. } forall
  457. pop pop % s
  458. } ifelse
  459. } bind def
  460. /string_array_size % <array|string> string_array_size <int>
  461. { dup type /stringtype eq {
  462. length
  463. } {
  464. 0 exch { length add } forall
  465. } ifelse
  466. } bind def
  467. % Each procedure in this dictionary is called as follows:
  468. % posttable <<proc>> glyphencoding
  469. /postformats mark
  470. 16#00010000 { % 258 standard Macintosh glyphs.
  471. pop MacGlyphEncoding
  472. }
  473. 16#00020000 { % Detailed map, required by Microsoft fonts.
  474. dup dup type /arraytype eq { 0 get } if length 36 lt {
  475. TTFDEBUG { (post format 2.0 invalid.) = flush } if
  476. pop [ ]
  477. } {
  478. /postglyphs exch def
  479. /post_first postglyphs dup type /arraytype eq { 0 get } if def
  480. post_first 32 getu16 /numglyphs exch def
  481. /glyphnames numglyphs 2 mul 34 add def
  482. % Build names array in the order they occur in the 'post' table
  483. /postpos glyphnames def
  484. /total_length postglyphs //string_array_size exec def
  485. [ numglyphs 1 sub {
  486. postpos total_length ge { exit } if
  487. % No name available, /postnames will be defined as an empty
  488. % array and the glyph won't get a name attached.
  489. postglyphs postpos //get_from_stringarray exec
  490. postglyphs postpos 1 add 2 index //getinterval_from_stringarray exec cvn
  491. exch postpos add 1 add /postpos exch def
  492. } repeat
  493. ] /postnames exch def
  494. [ 0 1 numglyphs 1 sub {
  495. 2 mul 34 add post_first exch getu16
  496. dup 258 lt {
  497. MacGlyphEncoding exch get
  498. } {
  499. dup 32768 ge {
  500. % According to the published TrueType spec, such values are
  501. % "reserved for future use", but at least some PDF files
  502. % produced by the Adobe PDF library contain entries with a
  503. % value of 16#ffff.
  504. pop /.notdef
  505. } {
  506. % Get the name for this glyph
  507. 258 sub dup postnames length ge {
  508. TTFDEBUG { ( *** warning: glyph index past end of 'post' table) = flush } if
  509. exit
  510. } if
  511. postnames exch get
  512. % At least some of Microsoft's TrueType fonts use incorrect
  513. % (Adobe-incompatible) names for some glyphs.
  514. % Correct for this here.
  515. postremap 1 index .knownget { exch pop } if
  516. } ifelse
  517. } ifelse
  518. } for ]
  519. }
  520. ifelse
  521. } bind
  522. 16#00030000 { % No map.
  523. pop [ ]
  524. } bind
  525. .dicttomark readonly def % postformats
  526. /call.readtable
  527. { .readtable
  528. } bind def
  529. /call.readbigtable
  530. { .readbigtable
  531. } bind def
  532. % Each procedure in this dictionary is called as follows:
  533. % <file> <length> -proc- <string|array_of_strings>
  534. % Note that each table must have an even length, because of a strange
  535. % Adobe requirement that each sfnts entry have even length.
  536. /readtables mark
  537. % Ordinary tables
  538. (cmap) //call.readtable
  539. (head) 1 index
  540. (hhea) 1 index
  541. (maxp) 1 index
  542. (name) 1 index
  543. (OS/2) 1 index
  544. (post) //call.readbigtable
  545. (vhea) //call.readtable
  546. % Big tables
  547. (glyf) //call.readbigtable
  548. (loca) 1 index
  549. (hmtx) 1 index
  550. (vmtx) 1 index
  551. % Tables only needed for embedding in PDF files
  552. (cvt ) //call.readtable
  553. (fpgm) 1 index
  554. (prep) 1 index
  555. .dicttomark
  556. % Normally there would be a 'readonly' here, but the ttf2pf utility wants
  557. % to include the 'kern' table as well, so we leave the readtables dictionary
  558. % writable.
  559. def % readtables
  560. /readtables_stripped readtables dup length dict copy
  561. dup (loca) { .skiptable } put
  562. dup (glyf) { .skiptable } put
  563. def
  564. % Read a table as a single string.
  565. % <file> <length> .skiptable <string>
  566. /.skiptable {
  567. pop pop ()
  568. } bind def
  569. % Read a table as a single string.
  570. % <file> <length> .readtable <string>
  571. /.readtable {
  572. dup dup 1 and add string
  573. % Stack: f len str
  574. dup 0 4 -1 roll getinterval
  575. % Stack: f str str1
  576. % Because of the absurd PostScript specification that gives an
  577. % error for reading into an empty string, we have to check for
  578. % this explicitly here.
  579. 3 -1 roll exch
  580. dup () ne { readstring } if pop pop
  581. } bind def
  582. % Read a big table (one that may exceed 64K).
  583. % <file> <length> .readbigtable <string[s]>
  584. /.readbigtable {
  585. dup 65400 lt {
  586. .readtable
  587. } {
  588. currentuserparams /VMReclaim get -2 vmreclaim
  589. [ 4 2 roll {
  590. % Stack: mark ... f left
  591. dup maxstring le { exit } if
  592. 1 index maxstring string readstring pop 3 1 roll maxstring sub
  593. } loop .readtable ]
  594. exch vmreclaim
  595. } ifelse
  596. } bind def
  597. end readonly def % .loadttfontdict
  598. % <tab> .printtab -
  599. /.printtab {
  600. dup 0 4 getinterval print ( ) print
  601. dup 8 getu32 =only ( ) print
  602. 12 getu32 =
  603. } bind def
  604. % <file> <bool> <SubfontID> .loadttfonttables -
  605. % Pushes .loadttfontdict & scratch dict on d-stack.
  606. % Defines f, offsets, tables, tabdict, tabs.
  607. % Skips loca and glyf if <bool> is true.
  608. /.loadttfonttables {
  609. .loadttfontdict begin
  610. 40 dict begin
  611. /SubfontID exch def
  612. /load_stripped exch def
  613. /f exch def
  614. /offsets f 12 string readstring pop def
  615. load_stripped { readtables_stripped } { readtables } ifelse /readtables_ exch def
  616. offsets 0 4 getinterval (ttcf) eq {
  617. % We need to handle TT collections with disk fonts only.
  618. % Therefore the file is a disk file and it can be positioned.
  619. offsets 8 getu32 /num_fonts exch def
  620. SubfontID num_fonts ge {
  621. QUIET not { (True Type collection contains insufficient fonts.) = } if
  622. /.loadttfonttables cvx /invalidfont signalerror
  623. } if
  624. SubfontID 4 mul 12 add f exch setfileposition
  625. f 4 string readstring pop 0
  626. getu32 /ttc_offset exch def
  627. f ttc_offset setfileposition
  628. /offsets f 12 string readstring pop def
  629. } {
  630. SubfontID 0 gt {
  631. QUIET not { (SubfontID > 0 with a True Type file which is not a collection.) = } if
  632. /.loadttfonttables cvx /invalidfont signalerror
  633. } if
  634. /ttc_offset 0 def
  635. } ifelse
  636. /tables f offsets 4 getu16 16 mul string readstring pop def
  637. /tabdict tables length 16 idiv dict def
  638. % tabs = tables we want to keep, sorted by file position.
  639. /tabs [ 0 16 tables length 1 sub {
  640. tables exch 16 getinterval
  641. TTFDEBUG { dup .printtab } if
  642. dup 0 4 getinterval readtables_ 1 index known {
  643. % put all 0 length tables at 0 to avoid overlap
  644. 1 index 12 getu32 0 eq { 1 index 8 0 putu32 } if
  645. tabdict exch 2 index put
  646. } {
  647. pop pop
  648. } ifelse
  649. } for ] {
  650. exch 8 getu32 exch 8 getu32 lt
  651. } .sort def
  652. % In certain malformed TrueType fonts, tables overlap.
  653. % Truncate tables if necessary.
  654. 0 1 tabs length 2 sub {
  655. dup tabs exch get exch 1 add tabs exch get
  656. 1 index 8 getu32 2 index 12 getu32 add
  657. 1 index 8 getu32 gt {
  658. (**** Warning: ) print 1 index 0 4 getinterval print
  659. ( overlaps ) print dup 0 4 getinterval print
  660. (, truncating.) = flush
  661. dup 8 getu32 2 index 8 getu32 sub
  662. 2 index 12 3 -1 roll putu32
  663. } if pop pop
  664. } for
  665. } bind def
  666. /.file_table_pos_names
  667. mark
  668. /glyf 0
  669. /loca 0
  670. .dicttomark readonly def
  671. % - .readttdata -
  672. % Read data. Updates offsets, tabs; stores data in tabdict.
  673. /.readttdata {
  674. /file_table_pos 10 dict def
  675. /fpos offsets length tables length add ttc_offset add def
  676. /sfpos offsets length tabs length 16 mul add def
  677. offsets 4 tabs length putu16
  678. tabs {
  679. dup 0 4 getinterval /tname exch def
  680. dup 8 getu32 /tpos exch def
  681. dup 12 getu32 /tlen exch def
  682. load_stripped //.file_table_pos_names tname known and {
  683. pop
  684. file_table_pos tname [tpos tlen] put
  685. tabdict tname () put
  686. } {
  687. 8 sfpos putu32
  688. % Skip data between the end of the previous table and
  689. % the beginning of this one, if any.
  690. tpos fpos gt {
  691. load_stripped {
  692. % 'setfileposition' is faster for skipping a big data.
  693. f tpos setfileposition
  694. } {
  695. f tpos fpos sub () /SubFileDecode filter dup flushfile closefile
  696. /fpos tpos def
  697. } ifelse
  698. } if
  699. f tlen readtables_ tname get exec
  700. tabdict tname 3 -1 roll put
  701. % Round up the table length to an even value.
  702. /sfpos sfpos tlen dup 1 and add add def
  703. } ifelse
  704. /fpos fpos tlen add def
  705. } forall
  706. } bind def
  707. % Find the string in a list of strings that includes a given index.
  708. % <strings> <index> .findseg <string> <index'>
  709. /.findseg {
  710. exch {
  711. dup length 2 index gt { exch exit } if
  712. length sub
  713. } forall
  714. } bind def
  715. % - .makesfnts -
  716. % Defines checksum, getloca, head, locatable, numloca, post, sfnts, upem
  717. % Note that the 'loca' table may be out of order. This is handled when
  718. % needed in .dividesfnts
  719. /.makesfnts {
  720. .readttdata
  721. /head tabdict /head get def
  722. /post tabdict /post .knownget {
  723. dup 0 get /post_first_part exch def
  724. } {
  725. null
  726. } ifelse def
  727. load_stripped not {
  728. /locatable tabdict /loca get def
  729. /numloca
  730. locatable dup type /stringtype eq
  731. { length }
  732. { 0 exch { length add } forall }
  733. ifelse % no def yet
  734. locatable type /stringtype eq {
  735. /.indexloca {} def
  736. } {
  737. /.indexloca /.findseg load def
  738. } ifelse
  739. head 50 getu16 0 ne {
  740. /getloca {
  741. 2 bitshift locatable exch .indexloca getu32
  742. } def
  743. 4 idiv 1 sub
  744. } {
  745. /getloca {
  746. dup add locatable exch .indexloca getu16 dup add
  747. } def
  748. 2 idiv 1 sub
  749. } ifelse def % numloca
  750. % If necessary, re-partition the glyfs.
  751. tabdict /glyf get dup type /stringtype ne {
  752. .dividesfnts tabdict /glyf 3 -1 roll put
  753. } {
  754. pop
  755. } ifelse
  756. } {
  757. % We did not load loca, take the number of glyphs from maxp.
  758. /numloca tabdict /maxp get 4 getu16 def
  759. } ifelse
  760. /sfnts [
  761. offsets tabs { concatstrings } forall
  762. tabs {
  763. 0 4 getinterval tabdict exch get
  764. dup type /stringtype ne { aload pop } if
  765. } forall
  766. ] def
  767. } bind def
  768. % <glyfs> .dividesfnts <glyfs'>
  769. /.dividesfnts {
  770. /glyfs exch def
  771. /len1 0 glyfs { length add } forall def
  772. % Determine where to split the glyfs by scanning the sorted locatable
  773. % The very last entry in loca may be bogus.
  774. % Note that some loca entries may be odd, but we can only
  775. % split at even positions.
  776. %
  777. % Construct splitarray, the array of final lengths of
  778. % the sfnts entries covering the glyfs (i.e., all but
  779. % the first and last sfnts entries).
  780. /prevsplit 0 def
  781. /prevboundary 0 def
  782. % sort the locatable in case it is out of order
  783. % Note the 'loca' table remains unchanged
  784. /needsort false def
  785. numloca array % the array of 'loca' entries (may be out of order)
  786. -1 % initial values for in order check
  787. 0 1 numloca 1 sub {
  788. dup getloca dup
  789. 4 -1 roll lt { /needsort true def } if
  790. 3 copy put exch pop
  791. } for pop % discard inorder check value
  792. needsort {
  793. { lt } bind .sort % stack: locatable_array
  794. } if
  795. /splitarray [
  796. 3 -1 roll 0 1 numloca 1 sub {
  797. % stack: /splitarray -mark- { splitlen splitlen ... } locatable_array index
  798. 1 index exch get dup prevsplit maxstring add gt {
  799. prevboundary prevsplit sub exch
  800. /prevsplit prevboundary def
  801. } if
  802. dup 1 and 0 eq { /prevboundary exch def } { pop } ifelse
  803. dup type /arraytype ne { exch } if % keep locatable_array on top
  804. } for
  805. len1 prevsplit sub
  806. exch pop % discard locatable_array
  807. ] def
  808. currentuserparams /VMReclaim get -2 vmreclaim
  809. [
  810. % Re-split the sfnts glyfs strings according to splitarray.
  811. % We do this by iterating over the final segments defined
  812. % by splitarray, and constructing them from pieces of the
  813. % current glyfs strings. We recycle the current strings
  814. % when possible, to avoid stressing the allocator.
  815. /sfnt_idx 0 def
  816. /strpos 0 def
  817. /avail () def
  818. splitarray {
  819. /seglen exch def
  820. /segpos 0 def
  821. avail length seglen ge
  822. { avail 0 seglen getinterval /avail () def } { seglen string }
  823. ifelse
  824. {
  825. /str glyfs sfnt_idx get def
  826. /strlen str length def
  827. /strleft strlen strpos sub def
  828. seglen segpos sub strleft lt { exit } if
  829. % Copy the (rest of the) string into the new segment.
  830. % We know strleft <= segleft.
  831. dup segpos str strpos strleft getinterval putinterval
  832. /segpos segpos strleft add def
  833. /avail str def
  834. /sfnt_idx sfnt_idx 1 add def
  835. /strpos 0 def
  836. segpos seglen eq { exit } if
  837. } loop
  838. % Fill up the segment with an initial piece of the next
  839. % existing glyfs string. We know strleft > segleft.
  840. /segleft seglen segpos sub def
  841. dup segpos str strpos segleft getinterval putinterval
  842. /strpos strpos segleft add def
  843. } forall
  844. ]
  845. exch vmreclaim
  846. } bind def
  847. /first_post_string % - first_post_string <string>
  848. {
  849. post dup type /arraytype eq { 0 get } if
  850. } bind def
  851. % - .getpost -
  852. % Uses post, defines glyphencoding
  853. /.getpost {
  854. /glyphencoding post null eq {
  855. TTFDEBUG { (post missing) = flush } if [ ]
  856. } {
  857. postformats first_post_string 0 getu32 .knownget {
  858. TTFDEBUG {
  859. (post: format ) print
  860. first_post_string
  861. dup 0 getu16 =only (,) print 2 getu16 = flush
  862. } if
  863. post exch exec
  864. } {
  865. TTFDEBUG { (post: unknown format ) print post 0 getu32 = flush } if [ ]
  866. } ifelse
  867. } ifelse
  868. TTFDEBUG { (post=) print dup == } if
  869. def
  870. } bind def
  871. % - .ttkeys <key> <value> ...
  872. /.ttkeys {
  873. count /ttkeycount exch def
  874. /upem head 18 getu16 def
  875. /FontMatrix matrix
  876. /FontBBox [ 36 2 42 { head exch gets16 upem div } for ]
  877. nextxuid
  878. tabdict /name .knownget {
  879. % Find the names from the 'name' table.
  880. /names exch def
  881. /FontName names 6 findname not { curxuid 16 8 string cvrs } if
  882. /fontname 1 index def
  883. /FontInfo mark
  884. names 0 findname { /Notice exch } if
  885. names 1 findname { /FamilyName exch } if
  886. names 4 findname { /FullName exch } if
  887. names 5 findname { /Version exch } if
  888. } {
  889. % No name table, fabricate a FontName.
  890. /FontName curxuid 16 8 string cvrs
  891. /fontname 1 index def
  892. /FontInfo mark
  893. } ifelse
  894. % Stack: ... /FontInfo mark key1 value1 ...
  895. post null ne {
  896. /ItalicAngle first_post_string 4 gets32 65536.0 div
  897. /isFixedPitch first_post_string 12 getu32 0 ne
  898. /UnderlinePosition first_post_string 8 gets16 upem div
  899. /UnderlineThickness first_post_string 10 gets16 upem div
  900. } if
  901. counttomark 0 ne { .dicttomark } { pop pop } ifelse
  902. /XUID [orgXUID 42 curxuid]
  903. TTFDEBUG {
  904. tabs { .printtab } forall
  905. [ sfnts { length } forall ] ==
  906. count ttkeycount sub array astore dup { == } forall aload pop
  907. } if
  908. /sfnts sfnts
  909. } bind def
  910. % ---------------- Standard TrueType font loading ---------------- %
  911. % - .pickcmap_with_no_xlatmap -
  912. % Defines cmapsub, cmaptab
  913. /.pickcmap_with_no_xlatmap {
  914. tabdict /cmap get
  915. % The Apple cmap format is no help in determining the encoding.
  916. % Look for a Microsoft table. If we can't find one,
  917. % just use the first table, whatever it is.
  918. dup 4 8 getinterval exch % the default
  919. 0 1 2 index 2 getu16 1 sub {
  920. 8 mul 4 add 1 index exch 8 getinterval
  921. TTFDEBUG {
  922. (cmap: platform ) print dup 0 getu16 =only
  923. ( encoding ) print dup 2 getu16 = flush
  924. } if
  925. dup 0 getu16 3 eq { exch 3 -1 roll pop exit } if pop
  926. } for
  927. % Stack: subentry table
  928. /cmapsub 2 index def
  929. exch 4 getu32 1 index length 1 index sub getinterval
  930. /cmaptab exch def
  931. } bind def
  932. % - .pickcmap_with_xlatmap -
  933. % Defines cmapsub, cmaptab
  934. /.pickcmap_with_xlatmap {
  935. .xlatmap_dict /TrueType known not {
  936. (Emulating a CID font with a True Type file, ) print
  937. (the file gs/lib/xlatmap must contain /TrueType key.) =
  938. /.pickcmap_with_xlatmap cvx /configurationerror signalerror
  939. } if
  940. false
  941. .xlatmap_dict /TrueType get
  942. dup length 2 sub 0 exch 2 exch { % bool [] i
  943. 2 copy get % bool [] i ()
  944. (.) search { % bool [] i post match pre
  945. cvi exch pop exch cvi % bool [] i PlatID SpecID
  946. } {
  947. (gs/lib/xlatmap containg a record with an invalid (PlatformID.SpecificID)) =
  948. /.pickcmap_with_xlatmap cvx /configurationerror signalerror
  949. } ifelse
  950. TTFDEBUG {
  951. (Seeking a cmap for platform=) print 1 index =only ( encoding=) print dup =
  952. } if
  953. tabdict /cmap get % bool [] i PlatID SpecID (cmap)
  954. dup /cmaptab exch def % temporary
  955. 0 1 2 index 2 getu16 1 sub { % bool [] i PlatID SpecID (cmap) j
  956. 8 mul 4 add 1 index exch 8 getinterval % bool [] i PlatID SpecID (cmap) (cmapsub)
  957. TTFDEBUG {
  958. (cmap: platform ) print dup 0 getu16 =only
  959. ( encoding ) print dup 2 getu16 = flush
  960. } if
  961. dup 0 getu16 4 index eq {
  962. dup 2 getu16 3 index eq { % bool [] i PlatID SpecID (cmap) (cmapsub)
  963. TTFDEBUG {
  964. (Choosen a cmap for platform=) print 3 index =only
  965. ( encoding=) print 2 index =
  966. } if
  967. /cmapsub 1 index def
  968. dup 4 getu32 % bool [] i PlatID SpecID (cmap) (cmapsub) p
  969. cmaptab length 1 index sub % bool [] i PlatID SpecID (cmap) (cmapsub) p l
  970. cmaptab 3 1 roll getinterval
  971. /cmaptab exch def % bool [] i PlatID SpecID (cmap) (cmapsub)
  972. 5 index 5 index 1 add get % bool [] i PlatID SpecID (cmap) (cmapsub) /Decoding
  973. /Decoding exch def % bool [] i PlatID SpecID (cmap) (cmapsub)
  974. 7 -1 roll pop true 7 1 roll % true [] i PlatID SpecID (cmap) (cmapsub)
  975. } if
  976. } if
  977. pop % true [] i PlatID SpecID (cmap)
  978. 5 index { exit } if
  979. } for % bool [] i PlatID SpecID (cmap)
  980. pop pop pop pop % bool []
  981. 1 index { exit } if
  982. } for % bool []
  983. pop % bool
  984. not {
  985. QUIET not { (True Type font doesn't contain a charset listed in gs/lib/xlatmap.) = } if
  986. /.pickcmap_with_xlatmap cvx /invalidfont signalerror
  987. } if %
  988. } bind def
  989. % - .pickcmap -
  990. % Defines cmapsub, cmaptab
  991. /.pickcmap {
  992. % Currently we use xlatmap only for emulation CIDFontType 2 with
  993. % a disk True Type font files, and use load_stripped
  994. % to check this regime. We would like to do so
  995. % while emulating a Type 42, but first the old code
  996. % about handling them to be changed
  997. % with adding a handling of a Decoding.
  998. % fixme : A correct way to fix this is to implenent
  999. % the Type 42 emulation with gs_fntem.ps .
  1000. % Also note that PDF embedded fonts probably don't need a xlatmap -
  1001. % see PDF spec, "Encodings for True Type fonts".
  1002. load_stripped {
  1003. //.pickcmap_with_xlatmap exec
  1004. } {
  1005. //.pickcmap_with_no_xlatmap exec
  1006. } ifelse
  1007. } bind def
  1008. % <glyph> .nname <_name>
  1009. /.nname {
  1010. =string cvs (_) exch concatstrings cvn
  1011. } bind def
  1012. % - .charkeys /CharStrings <charstrings> /Encoding <encoding>
  1013. % Resets glyphencoding
  1014. /.charkeys {
  1015. TTFDEBUG {
  1016. (glyphencoding: length=) print glyphencoding dup length = === flush
  1017. } if
  1018. % Hack: if there is no usable post table but the cmap uses
  1019. % the Microsoft Unicode encoding, use ISOLatin1Encoding.
  1020. glyphencoding length 0 eq {
  1021. cmapsub 0 4 getinterval <00030001> eq {
  1022. PDFDEBUG { (No post but have cmap 3.1, so use ISOLatin1Encoding) } if
  1023. /glyphencoding ISOLatin1Encoding dup length array copy def
  1024. } {
  1025. PDFDEBUG { (No encoding info, use .GS_extended_SymbolEncoding) } if
  1026. /glyphencoding /.GS_extended_SymbolEncoding findencoding dup length array copy def
  1027. } ifelse
  1028. } if
  1029. % If necessary, fabricate additional glyphencoding entries
  1030. % to cover all of loca, or truncate glyphencoding.
  1031. glyphencoding length numloca lt {
  1032. /glyphencoding numloca array
  1033. glyphencoding length dup 1 sub 0 1 3 2 roll {
  1034. dup glyphencoding exch get
  1035. 3 index 3 1 roll put
  1036. } for
  1037. % /glyphencoding <newarray> <glyphencoding length>
  1038. 1 numloca 1 sub {
  1039. 1 index exch dup .nname put
  1040. } for
  1041. def
  1042. } {
  1043. /glyphencoding glyphencoding 0 numloca getinterval def
  1044. } ifelse
  1045. % Some badly designed Chinese fonts have a post table
  1046. % in which all glyphs other than 0 are named .null.
  1047. % Use CharStrings to keep track of the reverse map from
  1048. % names to glyphs, and don't let any name be used for
  1049. % more than one glyph.
  1050. /CharStrings glyphencoding dup length 1 add dict % +1 for .notdef
  1051. 0 1 3 index length 1 sub {
  1052. % Stack: glyphencoding dict index
  1053. 2 index 1 index get 2 index 1 index known {
  1054. % The same name maps to more than one glyph.
  1055. % Change the name.
  1056. pop dup .nname 3 index 2 index 2 index put
  1057. } if
  1058. 2 index exch 3 -1 roll put
  1059. } for exch pop
  1060. % If there is no .notdef entry, map it to glyph 0.
  1061. dup /.notdef known not { dup /.notdef 0 put } if
  1062. readonly
  1063. /Encoding
  1064. [ cmaptab cmaparray dup length 256 gt { 0 256 getinterval } if
  1065. { glyphencoding exch get } forall
  1066. counttomark 256 exch sub { /.notdef } repeat ]
  1067. TTFDEBUG { (Encoding: ) print dup === flush } if
  1068. } bind def
  1069. % -mark- <key> <value> ... .definettfont <font>
  1070. /.definettfont {
  1071. /FontType 42
  1072. /PaintType 0
  1073. TTFDEBUG {
  1074. (numloca=) print numloca =
  1075. } if
  1076. .dicttomark
  1077. end end dup /FontName get exch definefont
  1078. } bind def
  1079. % <file> .loadttfont <type42font>
  1080. /.loadttfont {
  1081. //false 0 .loadttfonttables
  1082. .makesfnts
  1083. .getpost
  1084. .pickcmap
  1085. mark
  1086. .charkeys
  1087. .ttkeys
  1088. .definettfont
  1089. } bind def
  1090. % ---------------- CIDFontType 2 font loading ---------------- %
  1091. % Fill a string with sequential CIDs starting from the initial value.
  1092. % <string> <value> .fill_identity_cmap <string>
  1093. /.fill_identity_cmap { % () v
  1094. 1 index length 2 sub % () v n-2
  1095. 0 2 3 2 roll { % () v 0 2 n-1
  1096. 3 copy exch % () v i () i v
  1097. -8 bitshift % () v i () i v>>8
  1098. put % () v i
  1099. 3 copy 1 add % () v i () v i+1
  1100. exch 255 and % () v i () i+1 v&255
  1101. put % () v i
  1102. pop 1 add % () v+1
  1103. } for
  1104. pop
  1105. } bind def
  1106. % -mark- <key> <value> ... .definettcidfont <font>
  1107. /.definettcidfont {
  1108. /CIDFontName fontname
  1109. /CIDFontType 2
  1110. /CIDSystemInfo mark
  1111. /Registry (Adobe)
  1112. /Ordering (Japan1) % adhoc
  1113. /Supplement 0
  1114. .dicttomark
  1115. /CharStrings mark /.notdef 0 .dicttomark
  1116. % The cmap isn't of any use even if it is present.
  1117. % Just construct an identity CIDMap covering all the glyphs.
  1118. /CIDCount numloca % Wrong if a CIDFontType2 embedded into PDF with a non-Identity CIDToGIDMap.
  1119. % processCIDToGIDMap may replace.
  1120. /CIDMap numloca maxstring le {
  1121. % Use a single string.
  1122. numloca 2 mul string 0 .fill_identity_cmap
  1123. } {
  1124. % We must use 2 strings.
  1125. maxstring 2 mul string 0 .fill_identity_cmap
  1126. numloca maxstring sub 2 mul string maxstring .fill_identity_cmap
  1127. 2 array astore
  1128. } ifelse
  1129. /GDBytes 2
  1130. .dicttomark
  1131. end end dup /CIDFontName get exch /CIDFont defineresource
  1132. } bind def
  1133. % <file> .loadttcidfont <cidtype2font>
  1134. /.loadttcidfont {
  1135. //false 0 .loadttfonttables
  1136. .makesfnts
  1137. % CIDFontType2 fonts don't have a cmap: they are indexed by CID.
  1138. mark
  1139. .ttkeys
  1140. .definettcidfont
  1141. } bind def
  1142. % <file> <SubfontID> .load_tt_font_stripped <font_data>
  1143. % The font_data includes sfnts, NumGlyphs, TT_cmap, file_table_pos, Decoding.
  1144. % CIDMap to be created later from TT_cmap.
  1145. /.load_tt_font_stripped {
  1146. //true exch .loadttfonttables
  1147. .makesfnts
  1148. .pickcmap
  1149. mark
  1150. .ttkeys
  1151. /NumGlyphs numloca
  1152. /TT_cmap cmaptab cmaparray
  1153. /file_table_pos file_table_pos
  1154. /Decoding Decoding
  1155. .dicttomark
  1156. end end
  1157. } bind def
  1158. % ---------------- PDF TrueType font loading ---------------- %
  1159. % Strictly speaking, this code should be loaded only if we have a PDF
  1160. % interpreter, but it's so closely tied to the rest of the code in this
  1161. % file that we always include it.
  1162. % <plat+enc> .findcmap <subtable> true
  1163. % <plat+enc> .findcmap false
  1164. /.findcmap {
  1165. false exch tabdict /cmap get
  1166. % Some fonts have multiple cmaps with the same platform and
  1167. % encoding. Use the first one we find.
  1168. 0 1 2 index 2 getu16 1 sub {
  1169. % Stack: false plat+enc cmap index
  1170. 8 mul 4 add 1 index exch 8 getinterval
  1171. dup 0 4 getinterval 3 index eq {
  1172. 4 getu32 1 index exch 1 index length 1 index sub getinterval
  1173. 4 -1 roll not 4 2 roll exit
  1174. } if pop
  1175. } for
  1176. % Stack: false plat+enc cmap || subtable true plat+enc cmap
  1177. pop pop
  1178. } bind def
  1179. % Build .symbol_list for .pdfcharkeys .
  1180. % It is a dictionary containing all SymbolEncoding glyph names
  1181. % and random names for filling gaps in the character code range.
  1182. /.symbol_list 256 dict def
  1183. {
  1184. =string 0 (x) 0 get put
  1185. /SymbolEncoding .findencoding
  1186. 0 1 255 {
  1187. dup 2 index exch get
  1188. dup /.notdef eq {
  1189. pop dup
  1190. =string 1 3 getinterval cvs length 1 add
  1191. =string exch 0 exch getinterval cvn
  1192. } if
  1193. exch //.symbol_list 3 1 roll put
  1194. } for
  1195. pop
  1196. } bind exec
  1197. % Create .GS_extended_SymbolEncoding as inverse of .symbol_list .
  1198. {
  1199. /.GS_extended_SymbolEncoding 256 array
  1200. //.symbol_list {
  1201. exch 2 index 3 1 roll put
  1202. } forall
  1203. .defineencoding
  1204. } bind exec
  1205. /.addglyph % <name> <glyph#> .addglyph <name> <glyph#>
  1206. % <name> <glyph#> .addglyph -
  1207. {
  1208. dup cmapencoding length lt {
  1209. cmapencoding exch get dup 0 eq {
  1210. pop pop
  1211. } if
  1212. } {
  1213. pop pop
  1214. } ifelse
  1215. } bind def
  1216. % <subcmap> <chartoglyphmap> .pdfmapchars
  1217. % /CharStrings <charstrings>
  1218. /.pdfmapchars {
  1219. exch cmaparray /cmapencoding exch def
  1220. /CharStrings mark
  1221. % Add glyphs of <chartoglyphmap>*<subcmap> :
  1222. 3 2 roll {
  1223. dup type /arraytype eq {
  1224. exch /.name exch def
  1225. { .name exch //.addglyph exec
  1226. } forall
  1227. currentdict /.name undef
  1228. } {
  1229. //.addglyph exec
  1230. } ifelse
  1231. } forall
  1232. % stack: /CharStrings mark /name1 glyph#1 /name2 glyph#2 ... /namen glyph#n
  1233. % Stack depth is restricted with AdobeGlyphList size.
  1234. % Add glyphs of 'post' (with lower priority, see .dicttomark) :
  1235. 0 1 glyphencoding length 1 sub {
  1236. dup glyphencoding exch get exch
  1237. dup 0 eq {
  1238. pop pop
  1239. } if
  1240. } for
  1241. /.notdef 0
  1242. .dicttomark
  1243. } bind def
  1244. % - .pdfcharkeys /CharStrings <charstrings> /Encoding <encoding>
  1245. /.pdfcharkeys {
  1246. % The following algorithms are per the PDF Reference, Second Edition
  1247. % (PDF 1.3 reference manual).
  1248. is_symbolic {
  1249. <00030001> .findcmap {
  1250. %
  1251. % Adobe PDF spec says that symbolic fonts should contain exactly one
  1252. % cmap subtable for Platform=1, Encoding=0.
  1253. % Perhaps "Adobe Acrobat PDFWriter 4.0 for Windows" sometimes embeds
  1254. % fonts with both subtables 3.1 and 1.0 (see comparefiles/159.pdf,
  1255. % the font "Arial,Bold" with the character "registered"),
  1256. % and both Acrobat Reader 4.0 and 5.0 choose 3.1.
  1257. % Therefore we try 3.1 first.
  1258. %
  1259. ( **** Warning: Embedded symbolic TT fonts should not contain a cmap for Platform=3 Encoding=1.\n)
  1260. pdfformaterror
  1261. TTFDEBUG { (Using cmap 3.1) = } if
  1262. AdobeGlyphList .pdfmapchars
  1263. /Encoding /WinAnsiEncoding .findencoding
  1264. } {
  1265. %
  1266. % Adobe PDF spec says that in this case PDF interpreter should
  1267. % map character codes directly to glyphs using
  1268. % the cmap <00010000>. But we use PS interpreter to emulate
  1269. % a PDF interpreter. Therefore we need to construct
  1270. % a type 42 font, which requires an Encoding and a Charstrings.
  1271. % We construct them with symbol_list, which
  1272. % includes all glyphs from SymbolEncoding and additional
  1273. % random names for 1-to-1 mapping.
  1274. %
  1275. % A real TT font may use a different characters than
  1276. % the Symbol charaster set. Perhaps our code
  1277. % will give a correct printing, because glyph names are not
  1278. % important for symbolic fonts in PDF.
  1279. %
  1280. <00010000> .findcmap {
  1281. prebuilt_encoding null ne {
  1282. TTFDEBUG { (Using cmap 1.0 with prebuilt_encoding.) = } if
  1283. prebuilt_encoding .invert_encoding .pdfmapchars
  1284. /Encoding prebuilt_encoding
  1285. } {
  1286. % This is a case, in which an obsolete software could stupidly specify Macintosh Roman
  1287. % for a random encoding. Particulatrly GPL Ghostscript 7.06 does so.
  1288. % Trying to recover with 'post'.
  1289. pop % The table itself doesn't contain useful data.
  1290. TTFDEBUG { (Using cmap 1.0 with post or .GS_extended_SymbolEncoding) = } if
  1291. .charkeys
  1292. } ifelse
  1293. } {
  1294. % This is illegal with PDF spec.
  1295. ( **** Warning: Embedded symbolic TT fonts must contain a cmap for Platform=1 Encoding=0.\n)
  1296. pdfformaterror
  1297. % Try to map Unicode to SymbolEncoding
  1298. <00030001> .findcmap {
  1299. TTFDEBUG { (Using cmap 3.1) = } if
  1300. AdobeGlyphList .pdfmapchars
  1301. /Encoding /SymbolEncoding .findencoding
  1302. } {
  1303. % Apply the default algorithm. Hopely it has 'post'.
  1304. .charkeys
  1305. % check if the CharStrings dict contains glyphs needed by the
  1306. % prebuilt_encoding otherwise try the 3,0 cmap.
  1307. prebuilt_encoding null ne {
  1308. false prebuilt_encoding { % false means no missing glyphs
  1309. 4 index exch known not { pop true exit } if
  1310. } forall
  1311. {
  1312. ( **** Warning: Encoding derived from 'post' is incomplete.\n)
  1313. pdfformaterror
  1314. % Try another cmap format 3,0 -- Adobe doesn't mention it, but does
  1315. % use it apparently (empirically determined).
  1316. <00030000> .findcmap {
  1317. TTFDEBUG { (Adding cmap 3.0) = } if
  1318. 5 1 roll pop pop pop pop
  1319. prebuilt_encoding null ne {
  1320. prebuilt_encoding .invert_encoding .pdfmapchars
  1321. /Encoding prebuilt_encoding
  1322. } {
  1323. AdobeGlyphList .pdfmapchars
  1324. /Encoding /SymbolEncoding .findencoding
  1325. } ifelse
  1326. } if
  1327. }if
  1328. } if
  1329. } ifelse
  1330. } ifelse
  1331. } ifelse
  1332. } {
  1333. <00030001> .findcmap {
  1334. TTFDEBUG { (Using cmap 3.1 for non-symbolic.) = } if
  1335. AdobeGlyphList .pdfmapchars
  1336. /Encoding /WinAnsiEncoding .findencoding
  1337. % WinAnsiEncoding is just a stub here.
  1338. % It will be replaced with one from font resource,
  1339. % because PDF spec requires it.
  1340. } {
  1341. <00010000> .findcmap {
  1342. TTFDEBUG { (Using cmap 1.0 for non-symbolic.) = } if
  1343. .romanmacdict .pdfmapchars
  1344. /Encoding /MacRomanEncoding .findencoding
  1345. } {
  1346. % Apply the default algorithm for using the 'post'.
  1347. .charkeys
  1348. } ifelse
  1349. } ifelse
  1350. } ifelse
  1351. } bind def
  1352. % <file> <is_symbolic> <Encoding|null> .loadpdfttfont <type42font>
  1353. /.loadpdfttfont {
  1354. /prebuilt_encoding exch def % for .pdfcharkeys
  1355. /is_symbolic exch def
  1356. //false 0 .loadttfonttables
  1357. .makesfnts
  1358. .getpost
  1359. .pickcmap
  1360. mark
  1361. .pdfcharkeys
  1362. .ttkeys
  1363. .definettfont
  1364. } bind def