1 % Copyright (C) 1991, 1995, 1996, 2002 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: wrfont.ps,v 1.5 2002/04/19 06:52:25 lpd Exp $
18 % Write out a Type 1 font in readable, reloadable form.
19 % Note that this does NOT work on protected fonts, such as Adobe fonts
20 % (unless you have loaded unprot.ps first, in which case you may be
21 % violating the Adobe license).
23 % ****** NOTE: This file must be kept consistent with gs_pfile.ps.
25 /wrfont_dict 100 dict def
28 % ------ Options ------ %
30 % Define whether to use eexec encryption for the font.
31 % eexec encryption is only useful for compatibility with Adobe Type Manager
32 % and other programs; it only slows Ghostscript down.
33 /eexec_encrypt false def
35 % Define whether to write out the CharStrings in binary or in hex.
36 % Binary takes less space on the file, but isn't guaranteed portable.
37 /binary_CharStrings false def
39 % Define whether to use binary token encodings when possible.
40 % Binary tokens are smaller and load faster, but are a Level 2 feature.
41 /binary_tokens false def
43 % Define whether to encrypt the CharStrings on the file. (CharStrings
44 % are always encrypted in memory.) Unencrypted CharStrings load about
45 % 20% slower, but make the files compress much better for transport.
46 /encrypt_CharStrings true def
48 % Define whether the font must provide standard PostScript language
49 % equivalents for any facilities it uses that are provided in Ghostscript
50 % but are not part of the standard PostScript language.
51 /standard_only true def
53 % Define the value of lenIV to use in writing out the font.
54 % use_lenIV = 0 produces the smallest output, but this may not be
55 % compatible with old Adobe interpreters. use_lenIV = -1 means
56 % use the value of lenIV from the font.
59 % Define whether to produce the smallest possible output, relying
60 % as much as possible on Ghostscript-specific support code.
61 % Taking full advantage of this requires the following settings:
62 % binary_CharStrings = true, binary_tokens = true, standard_only = false.
63 /smallest_output false def
65 % Define whether to write out all currently known Encodings by name,
66 % or only StandardEncoding and ISOLatin1Encoding.
67 /name_all_Encodings false def
69 % ---------------- Runtime support ---------------- %
71 /.packedfilefilter where
73 { (gs_pfile.ps) runlibfile }
76 % ------ Output utilities ------ %
78 % By convention, the output file is named psfile.
80 % Define some utilities for writing the output file.
81 /wtstring 2000 string def
82 /wb {psfile exch write} bind def
83 /wnb {/wb load repeat} bind def
84 /w1 {psfile exch write} bind def
85 /ws {psfile exch writestring} bind def
86 /wl {ws (\n) ws} bind def
87 /wt {wtstring cvs ws ( ) ws} bind def
88 /wd % Write a dictionary.
89 { dup length wo {dict dup begin} wol { we } forall
92 /wld % Write a large dictionary more efficiently.
93 % Ignore the readonly attributes.
94 { dup length wo {dict dup begin} wol
98 { wo ({def} repeat) wl 0 }
103 { wo ({def} repeat) wl }
108 /we % Write a dictionary entry.
109 { exch wo wo /def cvx wo (\n) ws
111 /wcs % Write a CharString (or Subrs entry)
112 { dup type /stringtype eq
113 { 4330 exch changelenIV 0 ge
114 { % Add some leading garbage bytes.
115 wtstring changelenIV 2 index length getinterval
116 .type1decrypt exch pop
117 wtstring exch 0 exch length changelenIV add getinterval
119 { % Drop some leading garbage bytes.
120 wtstring .type1decrypt exch pop
121 changelenIV neg 1 index length 1 index sub getinterval
124 binary_tokens encrypt_CharStrings and
125 { % Suppress recognizing the readonly status of the string.
126 4330 exch dup .type1encrypt exch pop wo
128 { encrypt_CharStrings
129 { 4330 exch dup .type1encrypt exch pop
134 { readonly dup length wo
135 binary_tokens not { ( ) ws } if
142 { wo % PostScript procedure
147 % Construct the inversion of the system name table.
148 (\210\001) token pop exch pop 1 eq { % i.e., do we have binary tokens?
151 (\221 ) dup 1 3 index put
155 % Stack: char () token true
156 pop exch pop exch snit 3 1 roll put
163 % Write an object, using binary tokens if requested and possible.
164 /woa % write in ascii
165 { psfile exch write==only
168 % Lookup table for ASCII output.
170 /intbytes % int nbytes -> byte*
171 { { dup 255 and exch -8 bitshift } repeat pop
173 /wotta 10 dict dup begin
174 { /booleantype /integertype }
175 { { ( ) ws woa } def }
177 % Iterate over arrays so we can print operators.
179 { dup xcheck {(}) ({)} {(]) ([)} ifelse ws exch dup wol exch ws wop
184 { dup xcheck { ( ) ws } if woa
186 % Map back operators to their names,
187 % so we can write procedures.
192 { wtstring cvs cvn cvx wo
194 % Convert reals to integers if possible.
196 { dup cvi 1 index eq { cvi wo } { ( ) ws woa } ifelse
198 % == truncates strings longer than 200 characters!
201 { dup dup 32 lt exch 127 ge or
202 { (\\) ws dup -6 bitshift 48 add w1
203 dup -3 bitshift 7 and 48 add w1
206 { dup dup -2 and 40 eq exch 92 eq or {(\\) ws} if
214 { ([) ws dup { wo } forall
215 encodingnames 1 index known
216 % This is an encoding, but not one of the standard ones.
217 % Use the built-in encoding only if it is available.
218 { encodingnames exch get wo
219 ({findencoding}stopped{pop) ws
220 (}{counttomark 1 add 1 roll cleartomark}ifelse)
225 (/packedarray where{pop counttomark packedarray exch pop}{]readonly}ifelse) ws
231 % Lookup table for binary output.
233 /wottb 8 dict dup begin
234 wotta currentdict copy pop
236 { dup dup 127 le exch -128 ge and
237 { 136 wb 255 and wb }
238 { dup dup 32767 le exch -32768 ge and
239 { 134 wb 2 intbytes wb wb }
240 { 132 wb 4 intbytes wb wb wb wb }
246 { dup snit exch known
247 { dup xcheck { 146 } { 145 } ifelse wb
250 { wotta /nametype get exec
255 { dup dup length dup 255 le { 142 2 } { 2 intbytes 143 3 } ifelse wnb
260 /wop % Write object protection
261 { wcheck not { /readonly cvx wo } if
263 /wo % Write an object.
264 { dup type binary_tokens { wottb } { wotta } ifelse
267 /wol % Write a list of objects.
271 % Write a hex string for Subrs or CharStrings.
276 { % Some systems choke on very long lines, so
277 % we break up the hexstring into chunks of 50 characters.
278 { dup length 25 le {exit} if
279 dup 0 25 getinterval psfile exch writehexstring (\n) ws
280 dup length 25 sub 25 exch getinterval
282 psfile exch writehexstring
286 % ------ CharString encryption utilities ------ %
288 /enc_dict 20 dict def
290 /bind { } def % make sure we can print out the procedures
293 (type1enc.ps) runlibfile
294 enc_dict /.type1decrypt undef % we don't need this
298 enc_dict { 1 index where { pop pop pop } { def } ifelse } forall
300 % ------ Other utilities ------ %
302 % Test whether two values are equal (for default dictionary entries).
303 /valueeq % <obj1> <obj2> valueeq <bool>
306 { % Special hack for comparing FontMatrix values
307 dup type /arraytype eq 2 index type /arraytype eq and
308 { dup length 2 index length eq
309 { true 0 1 3 index length 1 sub
310 { % Stack: arr1 arr2 true index
311 3 index 1 index get 3 index 3 -1 roll get eq not
328 % ------ The main program ------ %
330 % Define the dictionary of keys to skip because they are treated specially.
341 /.minfontskipkeys mark
342 .fontskipkeys { } forall
346 /.privateskipkeys mark
352 /.minprivateskipkeys mark
353 .privateskipkeys { } forall
359 % Define the procedures for the Private dictionary.
360 % These must be defined without `bind',
361 % for the sake of the DISKFONTS feature.
363 /-! {string currentfile exch readhexstring pop} def
364 /-| {string currentfile exch readstring pop} def
365 /|- {readonly def} def
366 /| {readonly put} def
367 currentdict end /encrypted_procs exch def
369 /-! {string currentfile exch readhexstring pop
370 4330 exch dup .type1encrypt exch pop} def
371 /-| {string currentfile exch readstring pop
372 4330 exch dup .type1encrypt exch pop} def
373 /|- {readonly def} def
374 /| {readonly put} def
375 currentdict end /unencrypted_procs exch def
377 % Construct an inverse dictionary of encodings.
379 StandardEncoding /StandardEncoding
380 ISOLatin1Encoding /ISOLatin1Encoding
381 SymbolEncoding /SymbolEncoding
382 DingbatsEncoding /DingbatsEncoding
383 /resourceforall where
384 { pop (*) { cvn dup findencoding exch } 100 string /Encoding resourceforall }
388 % Invert the standard encodings.
389 .knownEncodings length 256 mul dict begin
391 { { currentdict 1 index known { pop } { 1 index def } ifelse
397 currentdict end /inverseencodings exch def
399 /writefont % <psfile> writefont - (writes the current font)
401 /Font currentfont def
402 /FontInfo Font /FontInfo .knownget not { 0 dict } if def
403 /FontType Font /FontType get def
404 /hasPrivate Font /Private known def
405 /Private hasPrivate { Font /Private get } { 0 dict } ifelse def
406 /readproc binary_CharStrings { (-| ) } { (-! ) } ifelse def
408 encrypt_CharStrings binary_tokens not and
409 { encrypted_procs } { unencrypted_procs } ifelse
412 /changelenIV use_lenIV 0 lt
414 { use_lenIV Private /lenIV .knownget not
415 { 4 /addlenIV use_lenIV 4 ne def } if sub }
420 Font /UniqueID known and
422 (%!FontType) ws FontType wtstring cvs ws (-1.0: ) ws
423 currentfont /FontName get wt
424 FontInfo /version .knownget not { (001.001) } if wl
425 FontInfo /CreationDate .knownget { (%%Creation Date: ) ws wl } if
426 FontInfo /VMusage .knownget
427 { (%%VMusage: ) ws dup wt wtstring cvs wl }
429 (systemdict begin) wl
431 % If we're going to use eexec, create the filters now.
432 /realpsfile psfile def
434 { /eexecfilter psfile binary_CharStrings not
435 { pop /bxstring 35 string def
436 { pop dup length 0 ne
437 { realpsfile exch writehexstring realpsfile (\n) writestring }
441 /NullEncode filter dup /hexfilter exch def
443 if 55665 /eexecEncode filter def
447 % Turn on binary tokens if relevant.
448 binary_tokens { (currentobjectformat 1 setobjectformat) wl } if
450 % If the file has a UniqueID, write out a check against loading it twice.
452 { Font /FontName get wo
453 Font /UniqueID get wo
454 Private length addlenIV { 1 add } if wo
455 Font length 1 add wo % +1 for FontFile
456 ( .checkexistingfont) wl
458 { Font /UniqueID known
459 { ({} FontDirectory) ws Font /FontName get dup wo ( known) wl
460 ( {) ws wo ( findfont dup /UniqueID known) wl
461 ( { dup /UniqueID get) ws Font /UniqueID get wo ( eq exch /FontType get 1 eq and }) wl
462 ( { pop false } ifelse) wl
463 ( { pop save /restore load } if) wl
470 % If we are writing unencrypted CharStrings for a standard environment,
471 % write out the encryption procedures.
472 privateprocs unencrypted_procs eq standard_only and
473 { (systemdict /.type1encrypt known) wl
474 ( { save /restore load } { { } } ifelse) wl
476 enc_dict { we } forall
481 % Write out the creation of the font dictionary and FontInfo.
483 { Font length 1 add wo {dict begin} wol % +1 for FontFile
486 (/FontInfo ) ws FontInfo wd {readonly def} wol
488 % Write out the other fixed entries in the font dictionary.
492 { .minfontskipkeys 2 index known
495 { //.compactfontdefault 2 index .knownget
496 { 1 index valueeq { pop pop } { we } ifelse }
502 { .fontskipkeys 2 index known { pop pop } { we } ifelse
507 encodingnames Encoding known
509 Encoding StandardEncoding eq or
510 Encoding ISOLatin1Encoding eq or and
511 { encodingnames Encoding get cvx }
514 dup /StandardEncoding cvx eq minimize and
519 % Write the FDepVector, if any.
520 Font /FDepVector .knownget
521 { {/FDepVector [} wol
522 { /FontName get wo {findfont} wol () wl } forall
527 % Write out the Metrics, if any.
528 Font /Metrics .knownget
529 { (/Metrics ) ws wld {readonly def} wol
532 Font /Metrics2 .knownget
533 { (/Metrics2 ) ws wld {readonly def} wol
537 % Start the eexec-encrypted section, if applicable.
539 { {currentdict currentfile eexec} wol () wl
540 /psfile eexecfilter store
541 (\000\000\000\000) ws {begin} wol
545 % Create and initialize the Private dictionary, if any.
550 { begin {Private dup begin}
552 { dup length privateprocs length add dict copy begin
553 privateprocs { readonly def } forall
555 currentdict length 1 add wo {dict dup begin}
559 { 1 index minimize { .minprivateskipkeys } { .privateskipkeys } ifelse
562 { 1 index /lenIV eq use_lenIV 0 ge and { pop use_lenIV } if we }
565 addlenIV { /lenIV use_lenIV we } if
569 % Write the Subrs entries, if any.
570 currentdict /Subrs known
574 { wcs minimize not { () wl } if }
578 {] dup {readonly pop} forall readonly def} wol () wl
582 % Wrap up the Private dictionary.
586 { {end readonly pop} } % Private
587 { {end readonly def} } % Private in font
592 % Write the CharStrings entries.
593 % Detect identical (eq) entries, which bdftops produces.
594 currentdict /CharStrings known
596 /CharStrings wo CharStrings length wo
598 { encrypt_CharStrings not wo ( .readCharStrings) wl
599 CharStrings length dict
601 { exch inverseencodings 1 index .knownget not { dup } if wo
602 % Stack: vdict value key
603 3 copy pop .knownget { wo pop pop } { 3 copy put pop wcs } ifelse
606 { {dict dup Private begin begin} wol () wl
607 CharStrings length dict
609 { 2 index 1 index known
610 { exch wo 1 index exch get wo {load def} wol () wl
612 { 2 index 1 index 3 index put
621 { readonly def } % CharStrings in font
626 % Terminate the output.
629 { {end mark currentfile closefile} wol () wl
630 eexecfilter dup flushfile closefile % psfile is eexecfilter
631 binary_CharStrings not { hexfilter dup flushfile closefile } if
632 /psfile realpsfile store
634 { (0000000000000000000000000000000000000000000000000000000000000000)
637 repeat {cleartomark} wol
640 { FontName currentdict end definefont pop
643 Font /UniqueID known { /exec cvx wo } if
644 binary_tokens { /setobjectformat cvx wo } if
645 ( end) wl % systemdict
649 % ------ Other utilities ------ %
651 % Prune garbage characters and OtherSubrs out of the current font,
652 % if the relevant dictionaries are writable.
654 { currentfont /CharStrings get wcheck
655 { currentfont /CharStrings get dup [ exch
656 { pop dup (S????00?) .stringmatch not { pop } if
658 ] { 2 copy undef pop } forall pop
665 /writefont { wrfont_dict begin writefont end } def