1 % Copyright (C) 1997, 1998, 1999, 2000 Aladdin Enterprises. All rights reserved.
3 % This software is provided AS-IS with no warranty, either express or
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.
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.
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
21 % Multiple Master fonts
25 % ---------------- Font loading machinery ---------------- %
27 % Augment the FONTPATH machinery so it recognizes OpenType CFF font sets.
29 /.scanfontheaders where {
30 pop /.scanfontheaders [
31 .scanfontheaders aload pop (OTTO*)
35 % Load a font file that might be an OpenType CFF font set.
37 % <file> .loadfontfile -
38 /.loadnonottofontfile /.loadfontfile load def
40 dup 4 string .peekstring pop (OTTO) eq {
41 % If this is a font at all, it's an OpenType CFF font set.
44 % Not a TrueType font.
49 % <file> .loadottofontfile -
51 /FontSetInit /ProcSet findresource begin
53 /f exch def /cff null def
54 card32 pop card16 6 { next pop } repeat dup {
55 % Stack: numtables tablesleft
57 pop pop /.loadottofontfile cvx /invalidfont signalerror
59 f 4 string readstring pop (CFF ) eq { sub exit } if
60 f 12 string readstring pop pop 1 sub % skip to next table
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
75 % ---------------- Standard strings (actually names) ---------------- %
78 % The initial StandardStrings that that denote characters are
79 % defined as a pseudo-Encoding.
81 /CFFStandardStrings .findencoding aload pop
85 (001.001) (001.002) (001.003) /Black /Bold
86 /Book /Light /Medium /Regular /Roman
90 % ---------------- Standard encodings ---------------- %
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
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
136 % ---------------- Standard Charsets ---------------- %
138 % We include an explicit 0 at the beginning of each charset.
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
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
177 % ---------------- Font loading ---------------- %
179 % ------ Utilities ------ %
181 /advance { % <n> advance -
182 f cff eq { pos add /pos exch store } { pop } ifelse
184 /next { % - next <byte>
187 CFFDEBUG { ( ) print dup = } if
190 /next2 { % - next2 <byte1> <byte2>
194 CFFDEBUG { ( ) print 1 index =only (,) print dup = } if
197 CFFDEBUG { ( ) print dup = } if
201 /nextstring { % <length> nextstring <string>
205 string f exch readstring pop dup length advance
206 CFFDEBUG { ( ) print dup == } if
209 /card8 % - card8 <card8>
212 /card16 { % - card16 <card16>
213 next2 exch 8 bitshift add
215 /card32 { % - card32 <card32>
216 card16 16 bitshift card16 add
221 { card8 16 bitshift card16 add } bind
224 /offsetproc { % <offsize> offsetproc <proc>
225 1 sub //offsetprocs exch get
227 /offset { % <offsize> offset <offset>
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
240 CFFDEBUG { (% Index lengths = ) print dup === } if
241 [ exch { nextstring } forall ] readonly
243 /tokens { % - tokens <num1> ... <op#> (op# = 12 means EOF)
245 f read not { 12 exit } if
246 CFFDEBUG { (..) print dup = } if
248 dup 12 eq { pop next 32 add exit } if
249 dup 28 lt { exit } if
252 { card16 32768 xor 32768 sub }
253 { 4 offset dup 16#7fffffff gt { -1 32 bitshift add } if }
270 % 255 is deliberately omitted and will cause a rangecheck
276 /tokenbuf 100 string def
277 /tokenput { % <index> <char> tokenput <index+1>
278 tokenbuf 2 index 3 -1 roll put 1 add
281 (0123456789.E) { } forall
282 [(E) 0 get /tokenput cvx (-) 0 get] cvx
283 null % will give an error
287 /tokenreal { % - tokenreal <float>
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
294 tokenbuf 0 3 -1 roll getinterval cvr exch pop
296 /Dict { % <opsdict> Dict -
299 CFFDEBUG { (tokens: ) print ] dup === mark exch aload pop } if
300 opdict exch .knownget { exec } if cleartomark
303 /idstring { % <sid> idstring <string|name>
304 dup 391 lt { //StandardStrings } { 391 sub strings } ifelse exch get
306 /idname { % <sid> idname <name>
307 idstring dup type /nametype ne { cvn } if
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
314 % ------ Top dictionary ------ %
316 /offput { % <offset> <proc> offput -
318 CFFDEBUG { dup { (not ) print } if (queued: ) print 2 index =only ( ) print 1 index === } if
321 { currentdict exch aload length 1 add packedarray cvx
326 /queueput { % <font> <proc> queueput -
327 16#7fffffff offsets { pop .min } forall
329 3 1 roll aload length 2 add packedarray cvx
330 [ queued aload pop counttomark 2 add -1 roll ]
333 /printvk { % <value> <key> printvk <value> <key>
334 CFFDEBUG { (\t% ) print dup =only ( = ) print 1 index === } if
336 /xxput { % <value> <key> <dict> xxput -
339 /putfi { % <value> <key> putfi -
340 printvk FontInfo xxput
342 /xdef { % <value> <key> xdef -
345 /pxdef { % <value> <key> pxdef -
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 }
369 dup StandardCharsets length lt {
370 StandardCharsets exch get /charset xdef
372 { queuecharset } offput
376 /Encoding printvk pop
377 dup StandardEncodings length lt {
380 { queueEncoding } offput
383 17 { { readCharStrings } offput }
384 18 { exch /readPrivate cvx 2 packedarray offput }
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
393 /CIDCount 8720 def % Default value defined in CFF spec.
396 idstring /Ordering pxdef
397 idstring /Registry pxdef
398 /CIDSystemInfo currentdict end def
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
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.
417 /charstringcount { % <font> charstringcount <count> true
418 % <font> charstringcount <length> false
419 /CharStringArray .knownget {
422 % Hack: look for the next queued read.
423 16#7fffffff offsets { pop .min } forall
428 /readCharStrings { % <font> readCharStrings -
429 /CharStringArray Index put
432 % ------ Charsets and encodings ------ %
434 % Note: formats 1 and 2 can overflow the operand stack.
435 % We'll fix this if it ever becomes necessary.
437 charstringcount { 1 sub } { 2 idiv } ifelse
440 { [ 0 3 -1 roll charsetcount { sid } repeat ]
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
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
453 /queuecharset { % <font> queuecharset -
454 { readcharset } queueput
456 /readcharset { % <data> <font> readcharset -
457 begin 0 () /SubFileDecode filter /f exch store
458 charsetformats next get currentdict exch exec /charset exch def end
462 { 1 1 next { next exch Encoding 3 1 roll put } for
467 Encoding 1 index 3 index put
468 exch 1 add exch 1 add
473 /queueEncoding { % <font> queueEncoding -
474 { readEncoding } queueput
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
481 % Read supplementary encodings.
483 Encoding next sid idname put
488 % ------ FDArray and FDSelect ------ %
490 /readFDArray { % <font> readFDArray -
491 /FDarray Index exch pop exch
492 2 dict begin /f null def begin
494 dup length subfilefilter /f exch store
498 /FontMatrix [0.001 0 0 0.001 0 0] def
500 //topdictops Dict currentdict end
501 } forall ] /FDArray xdef end end
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
510 % The following procedure does not use excessive op-stack space.
511 { pop 65535 array card16 card16 exch % Format 3
512 { % Stack: array previndex
514 exch 1 index 4 -1 roll
516 { 3 index exch 2 index put } for pop
518 % now resize the array to the final index.
523 /readFDSelect { % <font> readFDSelect -
524 begin fdselectformats next get currentdict exch exec /FDSelect exch def end
528 % ------ Private dictionary ------ %
530 /deltarray { % -mark- <num1> ... deltarray <num1'> ...
531 0 counttomark 1 sub { counttomark -1 roll add dup } repeat pop
532 counttomark array astore
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 }
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
560 61 { /lenBuildCharArray pxdef }
561 .dicttomark readonly def
563 /readPrivate { % <font> <size> readPrivate -
565 /PrivateStart pos def
566 f 3 1 roll exch 1 index f exch subfilefilter /f exch store
567 dup /FontType get exch
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
576 /readSubrs { % <font> readSubrs -
580 % ------ Main program ------ %
582 % Clean up after finishing a font.
583 /cleanupFont { % (currentdict) cleanupFont -
584 % Remove unwanted entries.
585 currentdict /charset undef
586 currentdict /CharStringArray undef
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
600 dup type /integertype eq { charset exch get idname } if
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
608 charset length =only ( charset ) print
609 CharStringArray length =only ( CharStringArray) =
612 0 1 CharStrings maxlength 1 sub {
613 dup CharStringArray exch get
614 exch charset exch get idstring CharStrings xxput
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
626 charset length =only ( charset ) print
627 CharStringArray length =only ( CharStringArray) =
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.
636 1 string dup 0 4 -1 roll put exch concatstrings
638 exch charset exch get GlyphDirectory xxput
641 Private /GlobalSubrs .knownget {
643 /Private get /GlobalSubrs 2 index put
646 Private /GlobalSubrs undef
650 currentdict /FDSelect undef
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
661 /ReadData { % <resname> <file> <forceresname> ReadData -
666 /forceresname exch def
669 /resname exch cvlit def
670 /DEBUG CFFDEBUG def % bring the binding closer
687 % Read the top Dicts.
691 /opdict null def % reserve a slot
693 0 () /SubFileDecode filter /f exch def
695 % Preload defaults that differ from PostScript defaults,
696 % or that are required.
699 /FontMatrix [0.001 0 0 0.001 0 0] def
700 /charset StandardCharsets 0 get def
703 dup /UnderlinePosition -100 put
704 dup /UnderlineThickness 50 put
707 gsubrs length 0 ne { dup /GlobalSubrs gsubrs put } if
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
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
727 offsets length 0 eq { exit } if
730 % Process out-of-order tables.
732 CFFDEBUG { queued length =only ( queued) = flush } if
733 queued { exec } forall
735 % Update Encoding and CharStrings.
739 currentdict /CIDFontType known { finishCIDFont } { finishFont } ifelse
745 resname mark 0 1 fonts length 1 sub {
746 CFFDEBUG { dup =only ( ) print flush } if
748 forceresname { pop resname } if
749 CFFDEBUG { dup == flush } if
751 dup /CIDFontType known {
753 dup /CIDFontName 3 index put
754 1 index exch /CIDFont defineresource
757 dup /FontName 3 index put
758 1 index exch definefont
762 end % FontSetInit ProcSet
763 /FontSet defineresource pop
767 % ---------------- Resource category definition ---------------- %
769 currentdict end readonly
771 languagelevel exch 2 .setlanguagelevel
773 /FontSet /Generic /Category findresource dup length dict .copydict
774 /Category defineresource pop
776 /FontSetInit exch /ProcSet defineresource pop