666 lines
18 KiB
PostScript
666 lines
18 KiB
PostScript
% Copyright (C) 1991, 1995, 1996, 2002 Aladdin Enterprises. All rights reserved.
|
|
%
|
|
% This software is provided AS-IS with no warranty, either express or
|
|
% implied.
|
|
%
|
|
% This software is distributed under license and may not be copied,
|
|
% modified or distributed except as expressly authorized under the terms
|
|
% of the license contained in the file LICENSE in this distribution.
|
|
%
|
|
% For more information about licensing, please refer to
|
|
% http://www.ghostscript.com/licensing/. For information on
|
|
% commercial licensing, go to http://www.artifex.com/licensing/ or
|
|
% contact Artifex Software, Inc., 101 Lucas Valley Road #110,
|
|
% San Rafael, CA 94903, U.S.A., +1(415)492-9861.
|
|
|
|
% $Id: wrfont.ps,v 1.5 2002/04/19 06:52:25 lpd Exp $
|
|
% wrfont.ps
|
|
% Write out a Type 1 font in readable, reloadable form.
|
|
% Note that this does NOT work on protected fonts, such as Adobe fonts
|
|
% (unless you have loaded unprot.ps first, in which case you may be
|
|
% violating the Adobe license).
|
|
|
|
% ****** NOTE: This file must be kept consistent with gs_pfile.ps.
|
|
|
|
/wrfont_dict 100 dict def
|
|
wrfont_dict begin
|
|
|
|
% ------ Options ------ %
|
|
|
|
% Define whether to use eexec encryption for the font.
|
|
% eexec encryption is only useful for compatibility with Adobe Type Manager
|
|
% and other programs; it only slows Ghostscript down.
|
|
/eexec_encrypt false def
|
|
|
|
% Define whether to write out the CharStrings in binary or in hex.
|
|
% Binary takes less space on the file, but isn't guaranteed portable.
|
|
/binary_CharStrings false def
|
|
|
|
% Define whether to use binary token encodings when possible.
|
|
% Binary tokens are smaller and load faster, but are a Level 2 feature.
|
|
/binary_tokens false def
|
|
|
|
% Define whether to encrypt the CharStrings on the file. (CharStrings
|
|
% are always encrypted in memory.) Unencrypted CharStrings load about
|
|
% 20% slower, but make the files compress much better for transport.
|
|
/encrypt_CharStrings true def
|
|
|
|
% Define whether the font must provide standard PostScript language
|
|
% equivalents for any facilities it uses that are provided in Ghostscript
|
|
% but are not part of the standard PostScript language.
|
|
/standard_only true def
|
|
|
|
% Define the value of lenIV to use in writing out the font.
|
|
% use_lenIV = 0 produces the smallest output, but this may not be
|
|
% compatible with old Adobe interpreters. use_lenIV = -1 means
|
|
% use the value of lenIV from the font.
|
|
/use_lenIV -1 def
|
|
|
|
% Define whether to produce the smallest possible output, relying
|
|
% as much as possible on Ghostscript-specific support code.
|
|
% Taking full advantage of this requires the following settings:
|
|
% binary_CharStrings = true, binary_tokens = true, standard_only = false.
|
|
/smallest_output false def
|
|
|
|
% Define whether to write out all currently known Encodings by name,
|
|
% or only StandardEncoding and ISOLatin1Encoding.
|
|
/name_all_Encodings false def
|
|
|
|
% ---------------- Runtime support ---------------- %
|
|
|
|
/.packedfilefilter where
|
|
{ pop }
|
|
{ (gs_pfile.ps) runlibfile }
|
|
ifelse
|
|
|
|
% ------ Output utilities ------ %
|
|
|
|
% By convention, the output file is named psfile.
|
|
|
|
% Define some utilities for writing the output file.
|
|
/wtstring 2000 string def
|
|
/wb {psfile exch write} bind def
|
|
/wnb {/wb load repeat} bind def
|
|
/w1 {psfile exch write} bind def
|
|
/ws {psfile exch writestring} bind def
|
|
/wl {ws (\n) ws} bind def
|
|
/wt {wtstring cvs ws ( ) ws} bind def
|
|
/wd % Write a dictionary.
|
|
{ dup length wo {dict dup begin} wol { we } forall
|
|
{end} wol
|
|
} bind def
|
|
/wld % Write a large dictionary more efficiently.
|
|
% Ignore the readonly attributes.
|
|
{ dup length wo {dict dup begin} wol
|
|
0 exch
|
|
{ exch wo wo () wl
|
|
1 add dup 200 eq
|
|
{ wo ({def} repeat) wl 0 }
|
|
if
|
|
}
|
|
forall
|
|
dup 0 ne
|
|
{ wo ({def} repeat) wl }
|
|
{ pop }
|
|
ifelse
|
|
(end) ws
|
|
} bind def
|
|
/we % Write a dictionary entry.
|
|
{ exch wo wo /def cvx wo (\n) ws
|
|
} bind def
|
|
/wcs % Write a CharString (or Subrs entry)
|
|
{ dup type /stringtype eq
|
|
{ 4330 exch changelenIV 0 ge
|
|
{ % Add some leading garbage bytes.
|
|
wtstring changelenIV 2 index length getinterval
|
|
.type1decrypt exch pop
|
|
wtstring exch 0 exch length changelenIV add getinterval
|
|
}
|
|
{ % Drop some leading garbage bytes.
|
|
wtstring .type1decrypt exch pop
|
|
changelenIV neg 1 index length 1 index sub getinterval
|
|
}
|
|
ifelse
|
|
binary_tokens encrypt_CharStrings and
|
|
{ % Suppress recognizing the readonly status of the string.
|
|
4330 exch dup .type1encrypt exch pop wo
|
|
}
|
|
{ encrypt_CharStrings
|
|
{ 4330 exch dup .type1encrypt exch pop
|
|
} if
|
|
smallest_output
|
|
{ wo
|
|
}
|
|
{ readonly dup length wo
|
|
binary_tokens not { ( ) ws } if
|
|
readproc ws wx
|
|
}
|
|
ifelse
|
|
}
|
|
ifelse
|
|
}
|
|
{ wo % PostScript procedure
|
|
}
|
|
ifelse
|
|
} bind def
|
|
|
|
% Construct the inversion of the system name table.
|
|
(\210\001) token pop exch pop 1 eq { % i.e., do we have binary tokens?
|
|
/snit 256 dict def
|
|
0 1 255 {
|
|
(\221 ) dup 1 3 index put
|
|
{ token } stopped {
|
|
pop pop
|
|
} {
|
|
% Stack: char () token true
|
|
pop exch pop exch snit 3 1 roll put
|
|
} ifelse
|
|
} for
|
|
} {
|
|
/snit 1 dict def
|
|
} ifelse
|
|
|
|
% Write an object, using binary tokens if requested and possible.
|
|
/woa % write in ascii
|
|
{ psfile exch write==only
|
|
} bind def
|
|
|
|
% Lookup table for ASCII output.
|
|
|
|
/intbytes % int nbytes -> byte*
|
|
{ { dup 255 and exch -8 bitshift } repeat pop
|
|
} bind def
|
|
/wotta 10 dict dup begin
|
|
{ /booleantype /integertype }
|
|
{ { ( ) ws woa } def }
|
|
forall
|
|
% Iterate over arrays so we can print operators.
|
|
/arraytype
|
|
{ dup xcheck {(}) ({)} {(]) ([)} ifelse ws exch dup wol exch ws wop
|
|
} bind def
|
|
/dicttype
|
|
{ ( ) ws wd } def
|
|
/nametype
|
|
{ dup xcheck { ( ) ws } if woa
|
|
} bind def
|
|
% Map back operators to their names,
|
|
% so we can write procedures.
|
|
/nulltype
|
|
{ pop ( null) ws
|
|
} bind def
|
|
/operatortype
|
|
{ wtstring cvs cvn cvx wo
|
|
} bind def
|
|
% Convert reals to integers if possible.
|
|
/realtype
|
|
{ dup cvi 1 index eq { cvi wo } { ( ) ws woa } ifelse
|
|
} bind def
|
|
% == truncates strings longer than 200 characters!
|
|
/stringtype
|
|
{ (\() ws dup
|
|
{ dup dup 32 lt exch 127 ge or
|
|
{ (\\) ws dup -6 bitshift 48 add w1
|
|
dup -3 bitshift 7 and 48 add w1
|
|
7 and 48 add
|
|
}
|
|
{ dup dup -2 and 40 eq exch 92 eq or {(\\) ws} if
|
|
}
|
|
ifelse w1
|
|
}
|
|
forall
|
|
(\)) ws wop
|
|
} bind def
|
|
/packedarraytype
|
|
{ ([) ws dup { wo } forall
|
|
encodingnames 1 index known
|
|
% This is an encoding, but not one of the standard ones.
|
|
% Use the built-in encoding only if it is available.
|
|
{ encodingnames exch get wo
|
|
({findencoding}stopped{pop) ws
|
|
(}{counttomark 1 add 1 roll cleartomark}ifelse)
|
|
}
|
|
{ pop ()
|
|
}
|
|
ifelse
|
|
(/packedarray where{pop counttomark packedarray exch pop}{]readonly}ifelse) ws
|
|
wl
|
|
}
|
|
def
|
|
end def
|
|
|
|
% Lookup table for binary output.
|
|
|
|
/wottb 8 dict dup begin
|
|
wotta currentdict copy pop
|
|
/integertype
|
|
{ dup dup 127 le exch -128 ge and
|
|
{ 136 wb 255 and wb }
|
|
{ dup dup 32767 le exch -32768 ge and
|
|
{ 134 wb 2 intbytes wb wb }
|
|
{ 132 wb 4 intbytes wb wb wb wb }
|
|
ifelse
|
|
}
|
|
ifelse
|
|
} bind def
|
|
/nametype
|
|
{ dup snit exch known
|
|
{ dup xcheck { 146 } { 145 } ifelse wb
|
|
snit exch get wb
|
|
}
|
|
{ wotta /nametype get exec
|
|
}
|
|
ifelse
|
|
} bind def
|
|
/stringtype
|
|
{ dup dup length dup 255 le { 142 2 } { 2 intbytes 143 3 } ifelse wnb
|
|
ws wop
|
|
} bind def
|
|
end def
|
|
|
|
/wop % Write object protection
|
|
{ wcheck not { /readonly cvx wo } if
|
|
} bind def
|
|
/wo % Write an object.
|
|
{ dup type binary_tokens { wottb } { wotta } ifelse
|
|
exch get exec
|
|
} bind def
|
|
/wol % Write a list of objects.
|
|
{ { wo } forall
|
|
} bind def
|
|
|
|
% Write a hex string for Subrs or CharStrings.
|
|
/wx % string ->
|
|
{ binary_CharStrings
|
|
{ ws
|
|
}
|
|
{ % Some systems choke on very long lines, so
|
|
% we break up the hexstring into chunks of 50 characters.
|
|
{ dup length 25 le {exit} if
|
|
dup 0 25 getinterval psfile exch writehexstring (\n) ws
|
|
dup length 25 sub 25 exch getinterval
|
|
} loop
|
|
psfile exch writehexstring
|
|
} ifelse
|
|
} bind def
|
|
|
|
% ------ CharString encryption utilities ------ %
|
|
|
|
/enc_dict 20 dict def
|
|
1 dict begin
|
|
/bind { } def % make sure we can print out the procedures
|
|
enc_dict begin
|
|
|
|
(type1enc.ps) runlibfile
|
|
enc_dict /.type1decrypt undef % we don't need this
|
|
|
|
end end
|
|
|
|
enc_dict { 1 index where { pop pop pop } { def } ifelse } forall
|
|
|
|
% ------ Other utilities ------ %
|
|
|
|
% Test whether two values are equal (for default dictionary entries).
|
|
/valueeq % <obj1> <obj2> valueeq <bool>
|
|
{ 2 copy eq
|
|
{ pop pop true }
|
|
{ % Special hack for comparing FontMatrix values
|
|
dup type /arraytype eq 2 index type /arraytype eq and
|
|
{ dup length 2 index length eq
|
|
{ true 0 1 3 index length 1 sub
|
|
{ % Stack: arr1 arr2 true index
|
|
3 index 1 index get 3 index 3 -1 roll get eq not
|
|
{ pop false exit }
|
|
if
|
|
}
|
|
for 3 1 roll pop pop
|
|
}
|
|
{ pop pop false
|
|
}
|
|
ifelse
|
|
}
|
|
{ pop pop false
|
|
}
|
|
ifelse
|
|
}
|
|
ifelse
|
|
} bind def
|
|
|
|
% ------ The main program ------ %
|
|
|
|
% Define the dictionary of keys to skip because they are treated specially.
|
|
/.fontskipkeys mark
|
|
/CharStrings dup
|
|
/Encoding dup
|
|
/FDepVector dup
|
|
/FID dup
|
|
/FontInfo dup
|
|
/Metrics dup
|
|
/Metrics2 dup
|
|
/Private dup
|
|
.dicttomark def
|
|
/.minfontskipkeys mark
|
|
.fontskipkeys { } forall
|
|
/FontName dup
|
|
/UniqueID dup
|
|
.dicttomark def
|
|
/.privateskipkeys mark
|
|
/ND dup
|
|
/NP dup
|
|
/RD dup
|
|
/Subrs dup
|
|
.dicttomark def
|
|
/.minprivateskipkeys mark
|
|
.privateskipkeys { } forall
|
|
/MinFeature dup
|
|
/Password dup
|
|
/UniqueID dup
|
|
.dicttomark def
|
|
|
|
% Define the procedures for the Private dictionary.
|
|
% These must be defined without `bind',
|
|
% for the sake of the DISKFONTS feature.
|
|
4 dict begin
|
|
/-! {string currentfile exch readhexstring pop} def
|
|
/-| {string currentfile exch readstring pop} def
|
|
/|- {readonly def} def
|
|
/| {readonly put} def
|
|
currentdict end /encrypted_procs exch def
|
|
4 dict begin
|
|
/-! {string currentfile exch readhexstring pop
|
|
4330 exch dup .type1encrypt exch pop} def
|
|
/-| {string currentfile exch readstring pop
|
|
4330 exch dup .type1encrypt exch pop} def
|
|
/|- {readonly def} def
|
|
/| {readonly put} def
|
|
currentdict end /unencrypted_procs exch def
|
|
|
|
% Construct an inverse dictionary of encodings.
|
|
/encodingnames mark
|
|
StandardEncoding /StandardEncoding
|
|
ISOLatin1Encoding /ISOLatin1Encoding
|
|
SymbolEncoding /SymbolEncoding
|
|
DingbatsEncoding /DingbatsEncoding
|
|
/resourceforall where
|
|
{ pop (*) { cvn dup findencoding exch } 100 string /Encoding resourceforall }
|
|
if
|
|
.dicttomark def
|
|
|
|
% Invert the standard encodings.
|
|
.knownEncodings length 256 mul dict begin
|
|
0 .knownEncodings
|
|
{ { currentdict 1 index known { pop } { 1 index def } ifelse
|
|
1 add
|
|
}
|
|
forall
|
|
}
|
|
forall pop
|
|
currentdict end /inverseencodings exch def
|
|
|
|
/writefont % <psfile> writefont - (writes the current font)
|
|
{ /psfile exch def
|
|
/Font currentfont def
|
|
/FontInfo Font /FontInfo .knownget not { 0 dict } if def
|
|
/FontType Font /FontType get def
|
|
/hasPrivate Font /Private known def
|
|
/Private hasPrivate { Font /Private get } { 0 dict } ifelse def
|
|
/readproc binary_CharStrings { (-| ) } { (-! ) } ifelse def
|
|
/privateprocs
|
|
encrypt_CharStrings binary_tokens not and
|
|
{ encrypted_procs } { unencrypted_procs } ifelse
|
|
def
|
|
/addlenIV false def
|
|
/changelenIV use_lenIV 0 lt
|
|
{ 0 }
|
|
{ use_lenIV Private /lenIV .knownget not
|
|
{ 4 /addlenIV use_lenIV 4 ne def } if sub }
|
|
ifelse def
|
|
/minimize
|
|
smallest_output
|
|
FontType 1 eq and
|
|
Font /UniqueID known and
|
|
def
|
|
(%!FontType) ws FontType wtstring cvs ws (-1.0: ) ws
|
|
currentfont /FontName get wt
|
|
FontInfo /version .knownget not { (001.001) } if wl
|
|
FontInfo /CreationDate .knownget { (%%Creation Date: ) ws wl } if
|
|
FontInfo /VMusage .knownget
|
|
{ (%%VMusage: ) ws dup wt wtstring cvs wl }
|
|
if
|
|
(systemdict begin) wl
|
|
|
|
% If we're going to use eexec, create the filters now.
|
|
/realpsfile psfile def
|
|
eexec_encrypt
|
|
{ /eexecfilter psfile binary_CharStrings not
|
|
{ pop /bxstring 35 string def
|
|
{ pop dup length 0 ne
|
|
{ realpsfile exch writehexstring realpsfile (\n) writestring }
|
|
{ pop }
|
|
ifelse bxstring
|
|
}
|
|
/NullEncode filter dup /hexfilter exch def
|
|
}
|
|
if 55665 /eexecEncode filter def
|
|
}
|
|
if
|
|
|
|
% Turn on binary tokens if relevant.
|
|
binary_tokens { (currentobjectformat 1 setobjectformat) wl } if
|
|
|
|
% If the file has a UniqueID, write out a check against loading it twice.
|
|
minimize
|
|
{ Font /FontName get wo
|
|
Font /UniqueID get wo
|
|
Private length addlenIV { 1 add } if wo
|
|
Font length 1 add wo % +1 for FontFile
|
|
( .checkexistingfont) wl
|
|
}
|
|
{ Font /UniqueID known
|
|
{ ({} FontDirectory) ws Font /FontName get dup wo ( known) wl
|
|
( {) ws wo ( findfont dup /UniqueID known) wl
|
|
( { dup /UniqueID get) ws Font /UniqueID get wo ( eq exch /FontType get 1 eq and }) wl
|
|
( { pop false } ifelse) wl
|
|
( { pop save /restore load } if) wl
|
|
( } if) wl
|
|
}
|
|
if
|
|
}
|
|
ifelse
|
|
|
|
% If we are writing unencrypted CharStrings for a standard environment,
|
|
% write out the encryption procedures.
|
|
privateprocs unencrypted_procs eq standard_only and
|
|
{ (systemdict /.type1encrypt known) wl
|
|
( { save /restore load } { { } } ifelse) wl
|
|
(userdict begin) wl
|
|
enc_dict { we } forall
|
|
(end exec) wl
|
|
}
|
|
if
|
|
|
|
% Write out the creation of the font dictionary and FontInfo.
|
|
minimize not
|
|
{ Font length 1 add wo {dict begin} wol % +1 for FontFile
|
|
}
|
|
if
|
|
(/FontInfo ) ws FontInfo wd {readonly def} wol
|
|
|
|
% Write out the other fixed entries in the font dictionary.
|
|
Font begin
|
|
Font
|
|
{ minimize
|
|
{ .minfontskipkeys 2 index known
|
|
{ pop pop
|
|
}
|
|
{ //.compactfontdefault 2 index .knownget
|
|
{ 1 index valueeq { pop pop } { we } ifelse }
|
|
{ we }
|
|
ifelse
|
|
}
|
|
ifelse
|
|
}
|
|
{ .fontskipkeys 2 index known { pop pop } { we } ifelse
|
|
}
|
|
ifelse
|
|
} forall
|
|
/Encoding
|
|
encodingnames Encoding known
|
|
name_all_Encodings
|
|
Encoding StandardEncoding eq or
|
|
Encoding ISOLatin1Encoding eq or and
|
|
{ encodingnames Encoding get cvx }
|
|
{ Encoding }
|
|
ifelse
|
|
dup /StandardEncoding cvx eq minimize and
|
|
{ pop pop }
|
|
{ we }
|
|
ifelse
|
|
|
|
% Write the FDepVector, if any.
|
|
Font /FDepVector .knownget
|
|
{ {/FDepVector [} wol
|
|
{ /FontName get wo {findfont} wol () wl } forall
|
|
{] readonly def} wol
|
|
}
|
|
if
|
|
|
|
% Write out the Metrics, if any.
|
|
Font /Metrics .knownget
|
|
{ (/Metrics ) ws wld {readonly def} wol
|
|
}
|
|
if
|
|
Font /Metrics2 .knownget
|
|
{ (/Metrics2 ) ws wld {readonly def} wol
|
|
}
|
|
if
|
|
|
|
% Start the eexec-encrypted section, if applicable.
|
|
eexec_encrypt
|
|
{ {currentdict currentfile eexec} wol () wl
|
|
/psfile eexecfilter store
|
|
(\000\000\000\000) ws {begin} wol
|
|
}
|
|
if
|
|
|
|
% Create and initialize the Private dictionary, if any.
|
|
hasPrivate
|
|
{
|
|
Private
|
|
minimize
|
|
{ begin {Private dup begin}
|
|
}
|
|
{ dup length privateprocs length add dict copy begin
|
|
privateprocs { readonly def } forall
|
|
/Private wo
|
|
currentdict length 1 add wo {dict dup begin}
|
|
}
|
|
ifelse wol () wl
|
|
currentdict
|
|
{ 1 index minimize { .minprivateskipkeys } { .privateskipkeys } ifelse
|
|
exch known
|
|
{ pop pop }
|
|
{ 1 index /lenIV eq use_lenIV 0 ge and { pop use_lenIV } if we }
|
|
ifelse
|
|
} forall
|
|
addlenIV { /lenIV use_lenIV we } if
|
|
}
|
|
if
|
|
|
|
% Write the Subrs entries, if any.
|
|
currentdict /Subrs known
|
|
{ (/Subrs[) wl
|
|
Subrs
|
|
{ dup null ne
|
|
{ wcs minimize not { () wl } if }
|
|
{ pop /null cvx wo }
|
|
ifelse
|
|
} forall
|
|
{] dup {readonly pop} forall readonly def} wol () wl
|
|
}
|
|
if
|
|
|
|
% Wrap up the Private dictionary.
|
|
hasPrivate
|
|
{ end % Private
|
|
minimize
|
|
{ {end readonly pop} } % Private
|
|
{ {end readonly def} } % Private in font
|
|
ifelse wol
|
|
}
|
|
if
|
|
|
|
% Write the CharStrings entries.
|
|
% Detect identical (eq) entries, which bdftops produces.
|
|
currentdict /CharStrings known
|
|
{
|
|
/CharStrings wo CharStrings length wo
|
|
minimize
|
|
{ encrypt_CharStrings not wo ( .readCharStrings) wl
|
|
CharStrings length dict
|
|
CharStrings
|
|
{ exch inverseencodings 1 index .knownget not { dup } if wo
|
|
% Stack: vdict value key
|
|
3 copy pop .knownget { wo pop pop } { 3 copy put pop wcs } ifelse
|
|
} forall
|
|
}
|
|
{ {dict dup Private begin begin} wol () wl
|
|
CharStrings length dict
|
|
CharStrings
|
|
{ 2 index 1 index known
|
|
{ exch wo 1 index exch get wo {load def} wol () wl
|
|
}
|
|
{ 2 index 1 index 3 index put
|
|
exch wo wcs ( |-) wl
|
|
}
|
|
ifelse
|
|
} forall
|
|
{end end} wol
|
|
}
|
|
ifelse
|
|
pop
|
|
{ readonly def } % CharStrings in font
|
|
wol
|
|
}
|
|
if
|
|
|
|
% Terminate the output.
|
|
end % Font
|
|
eexec_encrypt
|
|
{ {end mark currentfile closefile} wol () wl
|
|
eexecfilter dup flushfile closefile % psfile is eexecfilter
|
|
binary_CharStrings not { hexfilter dup flushfile closefile } if
|
|
/psfile realpsfile store
|
|
8
|
|
{ (0000000000000000000000000000000000000000000000000000000000000000)
|
|
wl
|
|
}
|
|
repeat {cleartomark} wol
|
|
}
|
|
if
|
|
{ FontName currentdict end definefont pop
|
|
}
|
|
wol
|
|
Font /UniqueID known { /exec cvx wo } if
|
|
binary_tokens { /setobjectformat cvx wo } if
|
|
( end) wl % systemdict
|
|
|
|
} bind def
|
|
|
|
% ------ Other utilities ------ %
|
|
|
|
% Prune garbage characters and OtherSubrs out of the current font,
|
|
% if the relevant dictionaries are writable.
|
|
/prunefont
|
|
{ currentfont /CharStrings get wcheck
|
|
{ currentfont /CharStrings get dup [ exch
|
|
{ pop dup (S????00?) .stringmatch not { pop } if
|
|
} forall
|
|
] { 2 copy undef pop } forall pop
|
|
}
|
|
if
|
|
} bind def
|
|
|
|
end % wrfont_dict
|
|
|
|
/writefont { wrfont_dict begin writefont end } def
|