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