home *** CD-ROM | disk | FTP | other *** search
/ Chip 2002 October / Chip_2002-10_cd1.bin / zkuste / pdf / download / gs704w32.exe / gs7.04 / lib / gs_cff.ps < prev    next >
Encoding:
Text File  |  2002-01-31  |  21.7 KB  |  760 lines

  1. %    Copyright (C) 1997, 1998, 1999, 2000 Aladdin Enterprises.  All rights reserved.
  2. % This file is part of AFPL Ghostscript.
  3. % AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author or
  4. % distributor accepts any responsibility for the consequences of using it, or
  5. % for whether it serves any particular purpose or works at all, unless he or
  6. % she says so in writing.  Refer to the Aladdin Free Public License (the
  7. % "License") for full details.
  8. % Every copy of AFPL Ghostscript must include a copy of the License, normally
  9. % in a plain ASCII text file named PUBLIC.  The License grants you the right
  10. % to copy, modify and redistribute AFPL Ghostscript, but only under certain
  11. % conditions described in the License.  Among other things, the License
  12. % requires that the copyright notice and this notice be preserved on all
  13. % copies.
  14.  
  15. % $Id: gs_cff.ps,v 1.10 2001/10/12 08:52:14 igorm Exp $
  16. % Loader for CFF (compressed) fonts, including OpenType CFFs.
  17. % The following are not implemented yet:
  18. %    Deleted entries in the Name Index
  19. %    Embedded PostScript
  20. %    Multiple Master fonts
  21. %    Chameleon fonts
  22. %    Synthetic fonts
  23.  
  24. % ---------------- Font loading machinery ---------------- %
  25.  
  26. % Augment the FONTPATH machinery so it recognizes OpenType CFF font sets.
  27.  
  28. /.scanfontheaders where {
  29.   pop /.scanfontheaders [
  30.    .scanfontheaders aload pop (OTTO*)
  31.   ] def
  32. } if
  33.  
  34. % Load a font file that might be an OpenType CFF font set.
  35.  
  36. % <file> .loadfontfile -
  37. /.loadnonottofontfile /.loadfontfile load def
  38. /.loadfontfile {
  39.   dup 4 string .peekstring pop (OTTO) eq {
  40.         % If this is a font at all, it's an OpenType CFF font set.
  41.     .loadottofontfile
  42.   } {
  43.         % Not a TrueType font.
  44.     .loadnonottofontfile
  45.   } ifelse
  46. } bind def
  47.  
  48. % <file> .loadottofontfile -
  49. /.loadottofontfile {
  50.   /FontSetInit /ProcSet findresource begin
  51.   2 dict begin
  52.   /f exch def /cff null def
  53.   card32 pop card16 6 { next pop } repeat dup {
  54.         % Stack: numtables tablesleft
  55.     dup 0 eq {
  56.       pop pop /.loadottofontfile cvx /invalidfont signalerror
  57.     } if
  58.     f 4 string readstring pop (CFF ) eq { sub exit } if
  59.     1 sub
  60.   } loop
  61.         % Stack: tablesread
  62.   card32 pop card32 card32
  63.         % Stack: tablesread start length
  64.   exch 3 -1 roll 1 add 16 mul 12 add sub
  65.   f exch subfilefilter flushfile    % skip to start
  66.   f exch subfilefilter end
  67.     % Use a random FontSet resource name.  ****** WRONG ******
  68.   realtime rand xor =string cvs exch false
  69.   ReadData
  70. } bind def
  71.  
  72. 30 dict begin
  73.  
  74. % ---------------- Standard strings (actually names) ---------------- %
  75.  
  76. /StandardStrings mark
  77.     % The initial StandardStrings that that denote characters are
  78.     % defined as a pseudo-Encoding.
  79. % 0
  80.   /CFFStandardStrings .findencoding aload pop
  81. % 379
  82.   (001.000)
  83. % 380
  84.   (001.001) (001.002) (001.003) /Black /Bold
  85.   /Book /Light /Medium /Regular /Roman
  86.   /Semibold
  87. .packtomark def
  88.  
  89. % ---------------- Standard encodings ---------------- %
  90.  
  91. /StandardEncodings [
  92.  
  93. % StandardEncoding
  94. mark
  95.   0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
  96.   0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
  97.   1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
  98.   17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
  99.   33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
  100.   49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
  101.   65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
  102.   81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 0
  103.   0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
  104.   0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
  105.   0 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
  106.   0 111 112 113 114 0 115 116 117 118 119 120 121 122 0 123
  107.   0 124 125 126 127 128 129 130 131 0 132 133 0 134 135 136
  108.   137 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
  109.   0 138 0 139 0 0 0 0 140 141 142 143 0 0 0 0
  110.   0 144 0 0 0 145 0 0 146 147 148 149 0 0 0 0
  111. .packtomark
  112.  
  113. % ExpertEncoding
  114. mark
  115.   0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
  116.   0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
  117.   1 229 230 0 231 232 233 234 235 236 237 238 13 14 15 99
  118.   239 240 241 242 243 244 245 246 247 248 27 28 249 250 251 252
  119.   0 253 254 255 256 257 0 0 0 258 0 0 259 260 261 262
  120.   0 0 263 264 265 0 266 109 110 267 268 269 0 270 271 272
  121.   273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288
  122.   289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 0
  123.   0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
  124.   0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
  125.   0 304 305 306 0 0 307 308 309 310 311 0 312 0 0 313
  126.   0 0 314 315 0 0 316 317 318 0 0 0 158 155 163 319
  127.   320 321 322 323 324 325 0 0 326 150 164 169 327 328 329 330
  128.   331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346
  129.   347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362
  130.   363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378
  131. .packtomark
  132.  
  133. ] readonly def
  134.  
  135. % ---------------- Standard Charsets ---------------- %
  136.  
  137. % We include an explicit 0 at the beginning of each charset.
  138.  
  139. /StandardCharsets [
  140.  
  141. % ISOAdobe
  142. mark
  143.   0
  144.   1 1 228 { } for
  145. .packtomark
  146.  
  147. % Expert
  148. mark
  149.   0
  150.   1 229 230 231 232 233 234 235 236 237 238 13 14 15 99 239
  151.   240 241 242 243 244 245 246 247 248 27 28 249 250 251 252 253
  152.   254 255 256 257 258 259 260 261 262 263 264 265 266 109 110 267
  153.   268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283
  154.   284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299
  155.   300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315
  156.   316 317 318 158 155 163 319 320 321 322 323 324 325 326 150 164
  157.   169 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341
  158.   342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357
  159.   358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373
  160.   374 375 376 377 378
  161. .packtomark
  162.  
  163. % ExpertSubset
  164. mark
  165.   0
  166.   1 231 232 235 236 237 238 13 14 15 99 239 240 241 242 243
  167.   244 245 246 247 248 27 28 249 250 251 253 254 255 256 257 258
  168.   259 260 261 262 263 264 265 266 109 110 267 268 269 270 272 300
  169.   301 302 305 314 315 158 155 163 320 321 322 323 324 325 326 150
  170.   164 169 327 328 329 330 331 332 333 334 335 336 337 338 339 340
  171.   341 342 343 344 345 346
  172. .packtomark
  173.  
  174. ] readonly def
  175.  
  176. % ---------------- Font loading ---------------- %
  177.  
  178. % ------ Utilities ------ %
  179.  
  180. /advance {    % <n> advance -
  181.   f cff eq { pos add /pos exch store } { pop } ifelse
  182. } bind def
  183. /next {        % - next <byte>
  184.   f read {
  185.     1 advance
  186.     DEBUG { (  ) print dup = } if
  187.   } if
  188. } bind def
  189. /next2 {    % - next2 <byte1> <byte2>
  190.   f read {
  191.     f read {
  192.       2 advance
  193.       DEBUG { (  ) print 1 index =only (,) print dup = } if
  194.     } {
  195.       1 advance
  196.       DEBUG { (  ) print dup = } if
  197.     } ifelse
  198.   } if
  199. } bind def
  200. /nextstring {    % <length> nextstring <string>
  201.   dup 0 eq {
  202.     pop ()
  203.   } {
  204.     string f exch readstring pop dup length advance
  205.     DEBUG { (  ) print dup == } if
  206.   } ifelse
  207. } bind def
  208. /card8        % - card8 <card8>
  209.  /next load
  210. def
  211. /card16 {    % - card16 <card16>
  212.   next2 exch 8 bitshift add
  213. } bind def
  214. /card32 {    % - card32 <card32>
  215.   card16 16 bitshift card16 add
  216. } bind def
  217. /offsetprocs [
  218.   /card8 load
  219.   /card16 load
  220.   { card8 16 bitshift card16 add } bind
  221.   /card32 load
  222. ] readonly def
  223. /offsetproc {    % <offsize> offsetproc <proc>
  224.   1 sub //offsetprocs exch get
  225. } bind def
  226. /offset {    % <offsize> offset <offset>
  227.   offsetproc exec
  228. } bind def
  229. /sid        % - <sid> sid
  230.   /card16 load
  231. def
  232. /Index {    % - Index <array>
  233.   mark card16 dup 0 ne {
  234.     1 exch next offsetproc dup exec pop exch {
  235.       dup exec dup 4 -1 roll sub 3 1 roll exch
  236.     } repeat pop
  237.   } if pop .packtomark
  238.   [ exch { nextstring } forall ] readonly
  239. } bind def
  240. /tokens {    % - tokens <num1> ... <op#> (op# = 12 means EOF)
  241.   {
  242.     f read not { 12 exit } if
  243.     DEBUG { (..) print dup = } if
  244.     1 advance
  245.     dup 12 eq { pop next 32 add exit } if
  246.     dup 28 lt { exit } if
  247.     dup 32 lt {
  248.       28 sub {
  249.     { card16 32768 xor 32768 sub }
  250.     { 4 offset dup 16#7fffffff gt { -1 32 bitshift add } if }
  251.     { tokenreal }
  252.     { 31 exit }
  253.       } exch get exec
  254.     } {
  255.       dup 247 lt {
  256.     139 sub
  257.       } {
  258.     247 sub {
  259.       { next 108 add }
  260.       { next 364 add }
  261.       { next 620 add }
  262.       { next 876 add }
  263.       { next 108 add neg }
  264.       { next 364 add neg }
  265.       { next 620 add neg }
  266.       { next 876 add neg }
  267.       % 255 is deliberately omitted and will cause a rangecheck
  268.     } exch get exec
  269.       } ifelse
  270.     } ifelse
  271.   } loop
  272. } bind def
  273. /tokenbuf 100 string def
  274. /tokenput {    % <index> <char> tokenput <index+1>
  275.   tokenbuf 2 index 3 -1 roll put 1 add
  276. } bind def
  277. /tokenrealarray [
  278.  (0123456789.E) { } forall
  279.  [(E) 0 get /tokenput cvx (-) 0 get] cvx
  280.  null        % will give an error
  281.  (-) 0 get
  282.  { exit }
  283. ] readonly def
  284. /tokenreal {    % - tokenreal <float>
  285.   0 {
  286.     next exch 1 index -4 bitshift tokenrealarray exch get exec tokenput
  287.         % We must leave the byte on the stack temporarily so that
  288.         % the exit will see a consistent stack state.
  289.     1 index 15 and tokenrealarray exch get exec tokenput exch pop
  290.   } loop
  291.   tokenbuf 0 3 -1 roll getinterval cvr exch pop
  292. } bind def
  293. /Dict {        % <opsdict> Dict -
  294.   /opdict exch store {
  295.     mark tokens
  296.     DEBUG { (tokens: ) print ] dup === mark exch aload pop } if
  297.     opdict exch .knownget { exec } if cleartomark
  298.   } loop cleartomark
  299. } bind def
  300. /idstring {    % <sid> idstring <string|name>
  301.   dup 391 lt { //StandardStrings } { 391 sub strings } ifelse exch get
  302. } bind def
  303. /idname {    % <sid> idname <name>
  304.   idstring dup type /nametype ne { cvn } if
  305. } bind def
  306. /subfilefilter {    % <file> <length> subfilefilter <filter>
  307.     % SubFileDecode interprets a length of 0 as infinite.
  308.   dup 0 le { pop pop () 0 } if () /SubFileDecode filter
  309. } bind def
  310.  
  311. % ------ Top dictionary ------ %
  312.  
  313. /offput {    % <offset> <proc> offput -
  314.   DEBUG { (queued: ) print 1 index =only ( ) print dup === } if
  315.   currentdict exch aload length 1 add packedarray cvx
  316.   offsets 3 1 roll put
  317. } bind def
  318. /queueput {    % <font> <proc> queueput -
  319.   16#7fffffff offsets { pop .min } forall
  320.   pos sub nextstring
  321.   3 1 roll aload length 2 add packedarray cvx
  322.   [ queued aload pop counttomark 2 add -1 roll ]
  323.   /queued exch store
  324. } bind def
  325. /xxput {    % <value> <key> <dict> xxput -
  326.   3 1 roll exch put
  327. } bind def
  328. /putfi {    % <value> <key> putfi -
  329.   FontInfo xxput
  330. } bind def
  331. /xdef {        % <value> <key> xdef -
  332.   exch def
  333. } bind def
  334. /topdictops mark
  335.   12 { exit }
  336.   0 { idstring /version putfi }
  337.   1 { idstring /Notice putfi }
  338.   32 { idstring /Copyright putfi }
  339.   2 { idstring /FullName putfi }
  340.   3 { idstring /FamilyName putfi }
  341.   4 { idstring /Weight putfi }
  342.   33 { 0 ne /isFixedPitch putfi }
  343.   34 { /ItalicAngle putfi }
  344.   35 { /UnderlinePosition putfi }
  345.   36 { /UnderlineThickness putfi }
  346.   37 { /PaintType xdef }
  347.   38 { /FontType xdef }        % actually CharstringType
  348.   39 { counttomark array astore /FontMatrix xdef }
  349.   13 { /UniqueID xdef }
  350.   5 { counttomark array astore /FontBBox xdef }
  351.   40 { /StrokeWidth xdef }
  352.   14 { counttomark array astore /XUID xdef }
  353.   15 {
  354.     dup StandardCharsets length lt {
  355.       StandardCharsets exch get /charset xdef
  356.     } {
  357.       { queuecharset } offput
  358.     } ifelse
  359.   }
  360.   16 {
  361.     dup StandardEncodings length lt {
  362.       /Encoding xdef
  363.     } {
  364.       { queueEncoding } offput
  365.     } ifelse
  366.   }
  367.   17 { { readCharStrings } offput }
  368.   18 { exch /readPrivate cvx 2 packedarray offput }
  369.     % CIDFont operators
  370.   62 {        % ROS, must be first in a CIDFont
  371.     currentdict /FontType undef
  372.     currentdict /Encoding undef
  373.     currentdict /FontMatrix undef
  374.     /CIDFontVersion 0 def
  375.     /CIDFontRevision 0 def
  376.     /CIDFontType 0 def
  377.     /CIDCount 8720 def % Default value defined in CFF spec.
  378.     3 dict begin
  379.     /Supplement xdef
  380.     idstring /Ordering xdef
  381.     idstring /Registry xdef
  382.     /CIDSystemInfo currentdict end def
  383.   }
  384.   63 { /CIDFontVersion xdef }
  385.   64 { /CIDFontRevision xdef }
  386.   65 { /CIDFontType xdef }
  387.   66 { /CIDCount xdef }
  388.   67 { /UIDBase xdef }
  389.   68 { { readFDArray } offput }
  390.   69 { { readFDSelect } offput }
  391.     % This operator only appears in a FDArray element.
  392.   70 { idstring /FontName exch def }
  393. .dicttomark readonly def
  394.  
  395. % readcharset and readFDSelect may require the length of CharStringArray,
  396. % but these structures may occur in the file before the CharStrings.
  397. % If that happens, use a hack: assume that all the data up to the next
  398. % queued read should be read.
  399.  
  400. /charstringcount {    % <font> charstringcount <count> true
  401.             % <font> charstringcount <length> false
  402.   /CharStringArray .knownget {
  403.     length true
  404.   } {
  405.     % Hack: look for the next queued read.
  406.     16#7fffffff offsets { pop .min } forall
  407.     pos sub false
  408.   } ifelse
  409. } bind def
  410.  
  411. /readCharStrings {    % <font> readCharStrings -
  412.   /CharStringArray Index put
  413. } bind def
  414.  
  415. % ------ Charsets and encodings ------ %
  416.  
  417. % Note: formats 1 and 2 can overflow the operand stack.
  418. % We'll fix this if it ever becomes necessary.
  419. /charsetcount {
  420.   charstringcount { 1 sub } { 2 idiv } ifelse
  421. } bind def
  422. /charsetformats [
  423. { [ 0 3 -1 roll charsetcount { sid } repeat ]
  424. } bind
  425. { [ 0 3 -1 roll charsetcount {
  426.     dup 0 eq { pop exit } if
  427.     sid card8 1 add 2 index .min { exch 1 sub 1 index 1 add } repeat pop
  428.   } loop ]
  429. } bind
  430. { [ 0 3 -1 roll charsetcount {
  431.     dup 0 eq { pop exit } if
  432.     sid card16 1 add 2 index .min { exch 1 sub 1 index 1 add } repeat pop
  433.   } loop ]
  434. } bind
  435. ] readonly def
  436. /queuecharset {        % <font> queuecharset -
  437.   { readcharset } queueput
  438. } bind def
  439. /readcharset {        % <data> <font> readcharset -
  440.   begin 0 () /SubFileDecode filter /f exch store
  441.   charsetformats next get currentdict exch exec /charset exch def end
  442. } bind def
  443.  
  444. /encodingformats [
  445. { 1 1 next { next exch Encoding 3 1 roll put } for
  446. } bind
  447. { 1 next {
  448.     next next 1 add {
  449.             % Stack: gid code
  450.       Encoding 1 index 3 index put
  451.       exch 1 add exch 1 add
  452.     } repeat pop
  453.   } repeat pop
  454. } bind
  455. ] readonly def
  456. /queueEncoding {    % <font> queueEncoding -
  457.   { readEncoding } queueput
  458. } bind def
  459. /readEncoding {        % <data> <font> readEncoding -
  460.   begin 0 () /SubFileDecode filter /f exch store
  461.   /Encoding [ 256 { /.notdef } repeat ] def
  462.   next encodingformats 1 index 127 and get exec
  463.   128 ge {
  464.             % Read supplementary encodings.
  465.     next {
  466.       Encoding next sid idname put
  467.     } repeat
  468.   } if end
  469. } bind def
  470.  
  471. % ------ FDArray and FDSelect ------ %
  472.  
  473. /readFDArray {        % <font> readFDArray -
  474.   Index exch
  475.   2 dict begin /f null def begin
  476.   [ exch {
  477.     dup length subfilefilter /f exch store
  478.     10 dict begin
  479.     /FontType 2 def
  480.     /PaintType 0 def
  481.     /FontMatrix [0.001 0 0 0.001 0 0] def
  482.     /Private 20 dict def
  483.     //topdictops Dict currentdict end
  484.   } forall ] /FDArray xdef end end
  485. } bind def
  486.  
  487. % Note: this implementation can overflow the operand stack.
  488. % We'll fix this if it ever becomes necessary.
  489. /fdselectformats [
  490. { [ exch charstringcount pop { card8 } repeat ] } bind
  491. { /FDSelect cvx /invalidfont signalerror } bind
  492. dup
  493. { pop [ card16 card16 exch {
  494.         % Stack: previndex
  495.     card8 card16 dup 4 1 roll 3 -1 roll sub 1 sub {
  496.       exch 1 index
  497.     } repeat exch
  498.   } repeat pop ]
  499. } bind
  500. ] readonly def
  501.  
  502. /readFDSelect {        % <font> readFDSelect -
  503.   begin fdselectformats next get currentdict exch exec /FDSelect exch def end
  504. } bind def
  505.  
  506.  
  507. % ------ Private dictionary ------ %
  508.  
  509. /deltarray {        % -mark- <num1> ... deltarray <num1'> ...
  510.   0 counttomark 1 sub { counttomark -1 roll add dup } repeat pop
  511.   counttomark array astore
  512. } bind def
  513.  
  514. /privatedictops mark
  515.   12 { exit }
  516.   6 { deltarray /BlueValues xdef }
  517.   7 { deltarray /OtherBlues xdef }
  518.   8 { deltarray /FamilyBlues xdef }
  519.   9 { deltarray /FamilyOtherBlues xdef }
  520.   41 { /BlueScale xdef }
  521.   42 { /BlueShift xdef }
  522.   43 { /BlueFuzz xdef }
  523.   10 { 1 array astore /StdHW xdef }
  524.   11 { 1 array astore /StdVW xdef }
  525.   44 { deltarray /StemSnapH xdef }
  526.   45 { deltarray /StemSnapV xdef }
  527.   46 { 0 ne /ForceBold xdef }
  528.   47 { /ForceBoldThreshold xdef }
  529.   48 { /lenIV xdef }
  530.   49 { /LanguageGroup xdef }
  531.   50 { /ExpansionFactor xdef }
  532.   51 { /initialRandomSeed xdef }
  533.   19 { PrivateStart add { readSubrs } offput }
  534.   20 { /defaultWidthX xdef }
  535.   21 { /nominalWidthX xdef }
  536.     % Multiple Master fonts only
  537.   59 { /NDV xdef }
  538.   60 { /CDV xdef }
  539.   61 { /lenBuildCharArray xdef }
  540. .dicttomark readonly def
  541.  
  542. /readPrivate {        % <font> <size> readPrivate -
  543.   2 dict begin
  544.   /PrivateStart pos def
  545.   f 3 1 roll exch 1 index f exch subfilefilter /f exch store
  546.   dup /FontType get exch
  547.   /Private get begin
  548.         % Default lenIV to -1 even for Type 1 CharStrings.
  549.   2 ne { /lenIV -1 def } if
  550.   //privatedictops Dict end
  551.   exch /f exch store advance
  552.   end
  553. } bind def
  554.  
  555. /readSubrs {        % <font> readSubrs -
  556.   /Subrs Index put
  557. } bind def
  558.  
  559. % ------ Main program ------ %
  560.  
  561. % Clean up after finishing a font.
  562. /cleanupFont {        % (currentdict) cleanupFont -
  563.         % Remove unwanted entries.
  564.   currentdict /charset undef
  565.   currentdict /CharStringArray undef
  566. } bind def
  567.  
  568. % Update the Encoding and CharStrings for a real font.
  569. /finishFont {        % (currentdict) finishFont -
  570.         % Construct the real Encoding.
  571.         % The value of Encoding is either a number, for predefined
  572.         % encodings, or an array of mixed GIDs and names.
  573.   /Encoding mark Encoding
  574.   DEBUG { (Encoding: ) print dup === flush } if
  575.   dup type /integertype eq {
  576.     StandardEncodings exch get { idname } forall
  577.   } {
  578.     {
  579.       dup type /integertype eq { charset exch get idname } if
  580.     } forall
  581.   } ifelse .packtomark def
  582.         % Construct the CharStrings.
  583.         % Note that they may only correspond to an initial
  584.         % subset of the charset.
  585.   /CharStrings charset length CharStringArray length .min dict def
  586.   DEBUG {
  587.     charset length =only ( charset ) print
  588.     CharStringArray length =only ( CharStringArray) =
  589.     charset == flush
  590.   } if
  591.   0 1 CharStrings maxlength 1 sub {
  592.     dup CharStringArray exch get
  593.     exch charset exch get idstring CharStrings xxput
  594.   } for
  595.   cleanupFont
  596. } bind def
  597.  
  598. % Replace CharStrings with GlyphDirectory for a CIDFont;
  599. % Move GlobalSubrs to descendent fonts.
  600. /finishCIDFont {    % (currentdict) finishCIDFont -
  601.         % Construct the GlyphDirectory, similar to CharStrings.
  602.   /FDBytes FDArray length 1 gt { 1 } { 0 } ifelse def
  603.   /GlyphDirectory charset length CharStringArray length .min dict def
  604.   DEBUG {
  605.     charset length =only ( charset ) print
  606.     CharStringArray length =only ( CharStringArray) =
  607.     charset == flush
  608.   } if
  609.   0 1 GlyphDirectory maxlength 1 sub {
  610.     dup CharStringArray exch get
  611.         % If there is more than one FDArray entry, add the font
  612.         % index to the beginning of each charstring.
  613.     FDBytes 1 eq {
  614.       FDSelect 2 index get
  615.       1 string dup 0 4 -1 roll put exch concatstrings
  616.     } if
  617.     exch charset exch get GlyphDirectory xxput
  618.   } for
  619.  
  620.   Private /GlobalSubrs .knownget {
  621.     FDArray {
  622.     /Private get /GlobalSubrs 2 index put
  623.     } forall
  624.     pop
  625.     Private /GlobalSubrs undef
  626.   } if
  627.  
  628.         % Clean up.
  629.   currentdict /FDSelect undef
  630.   cleanupFont
  631. } bind def
  632. % We need to pass the file as a parameter for the sake of the PDF
  633. % interpreter. Also for the sake of PDF, a flag forces the font
  634. % to be defined as <resname> instead of the name embedded in the data.
  635. % This is needed for subsetted fonts; it is valid if the CFF
  636. % contains only a single font.
  637. /StartData {          % <resname> <nbytes> StartData -
  638.   currentfile exch subfilefilter false ReadData
  639. } bind def
  640. /ReadData {           % <resname> <file> <forceresname> ReadData -
  641.  
  642.     % Initialize.
  643.  
  644.   30 dict begin
  645.   /forceresname exch def
  646.   /cff exch def
  647.   /pos 0 def
  648.   /resname exch cvlit def
  649.   /DEBUG DEBUG def    % bring the binding closer
  650.  
  651.     % Read the header.
  652.  
  653.   /f cff def
  654.   /vmajor next def
  655.   /vminor next def
  656.   /hdrsize next def
  657.   /aoffsize next def
  658.  
  659.     % Read the Indexes.
  660.  
  661.   /names Index def
  662.   /topdicts Index def
  663.   /strings Index def
  664.   /gsubrs Index def
  665.  
  666.     % Read the top Dicts.
  667.  
  668.   /offsets 50 dict def
  669.   /queued [] def
  670.   /opdict null def        % reserve a slot
  671.   /fonts [ topdicts {
  672.     0 () /SubFileDecode filter /f exch def
  673.     40 dict begin
  674.         % Preload defaults that differ from PostScript defaults,
  675.         % or that are required.
  676.       /FontType 2 def
  677.       /PaintType 0 def
  678.       /FontMatrix [0.001 0 0 0.001 0 0] def
  679.       /charset StandardCharsets 0 get def
  680.       /Encoding 0 def
  681.       /FontInfo 10 dict
  682.     dup /UnderlinePosition -100 put
  683.     dup /UnderlineThickness 50 put
  684.       def
  685.       /Private 20 dict
  686.     gsubrs length 0 ne { dup /GlobalSubrs gsubrs put } if
  687.       def
  688.       //topdictops Dict
  689.     currentdict end
  690.   } forall ] def
  691.  
  692.     % Read other tables with queued offsets.
  693.  
  694.   DEBUG { (offsets: ) print [ offsets { pop } forall ] == } if
  695.   { /f cff def
  696.     DEBUG { (pos=) print pos = } if
  697.     offsets pos 2 copy .knownget not { pop pop exit } if
  698.     3 1 roll undef
  699.     DEBUG { (exec queued: ) print dup == } if
  700.     exec
  701.   } loop
  702.   offsets length 0 ne {
  703.     (Error: missing tables at ) print [ offsets { pop } forall ] ==
  704.     (Current position is ) print pos ==
  705.     flush stop
  706.   } if
  707.  
  708.     % Process out-of-order tables.
  709.  
  710.   DEBUG { queued length =only ( queued) = flush } if
  711.   queued { exec } forall
  712.  
  713.     % Update Encoding and CharStrings.
  714.  
  715.   fonts {
  716.     begin
  717.     currentdict /CIDFontType known { finishCIDFont } { finishFont } ifelse
  718.     end
  719.   } forall
  720.  
  721.     % Wrap up.
  722.  
  723.   resname mark 0 1 fonts length 1 sub {
  724.     DEBUG { dup =only ( ) print flush } if
  725.     dup names exch get
  726.     forceresname { pop resname } if
  727.     DEBUG { dup == flush } if
  728.     exch fonts exch get
  729.     dup /CIDFontType known {
  730.         % This is a CIDFont.
  731.       dup /CIDFontName 3 index put
  732.       1 index exch /CIDFont defineresource
  733.     } {
  734.         % This is a font.
  735.       dup /FontName 3 index put
  736.       1 index exch definefont
  737.     } ifelse
  738.   } for .dicttomark
  739.   end        % temporary dict
  740.   end        % FontSetInit ProcSet
  741.   /FontSet defineresource pop
  742.  
  743. } bind def
  744.  
  745. % ---------------- Resource category definition ---------------- %
  746.  
  747. currentdict end readonly
  748.  
  749. languagelevel exch 2 .setlanguagelevel
  750.  
  751. /FontSet /Generic /Category findresource dup length dict .copydict
  752. /Category defineresource pop
  753.  
  754. /FontSetInit exch /ProcSet defineresource pop
  755.  
  756. .setlanguagelevel
  757.