% Copyright (C) 1991 Aladdin Enterprises. All rights reserved.
% Distributed by Free Software Foundation, Inc.
% This file is part of Ghostscript.
% Ghostscript is distributed in the hope that it will be useful, but
% WITHOUT ANY WARRANTY. No author or distributor accepts responsibility
% to anyone for the consequences of using it or for whether it serves any
% particular purpose or works at all, unless he says so in writing. Refer
% to the Ghostscript General Public License for full details.
% Everyone is granted permission to copy, modify and redistribute
% Ghostscript, but only under the conditions described in the Ghostscript
% General Public License. A copy of this license is supposed to have been
% given to you along with Ghostscript so you can know your rights and
% responsibilities. It should be in a file named COPYING. Among other
% things, the copyright notice and this notice must be preserved on all
% 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).
% ------ Options ------ %
% Define whether to write out the CharStrings in binary or in hex.
% Binary takes less space on the file, but isn't guaranteed portable.
% Define whether to use binary token encodings for the CharStrings.
% Binary tokens are smaller and load faster, but are a Level 2 feature.
% ------ Output utilities ------ %
% By convention, the output file is named psfile.
% Define some utilities for writing the output file.
/wb {psfile exch write} bind def
/wnb {/wb load repeat} 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 wt (dict dup begin) wl { we } forall
/wld % Write a large dictionary more efficiently.
% Ignore the readonly attributes.
{ dup length wt (dict dup begin) wl
{ wo ({def} repeat) wl 0 }
/we % Write a dictionary entry.
{ exch wo wo /def cvx wo (\n) ws
% Construct the inversion of the system name table.
{ dup SystemNames exch get
dup null ne { exch snit 3 1 roll put } { pop pop } ifelse
% Write an object, using binary tokens if requested and possible.
{ psfile exch write==only
% Lookup table for ASCII output.
/intbytes % int nbytes -> byte*
{ exch { dup 255 and exch -8 bitshift } repeat pop
{ /booleantype /integertype /nulltype /realtype }
{ dup xcheck { ( ) ws } if woa
{ /arraytype /packedarraytype /stringtype }
% Lookup table for binary output.
wotta currentdict copy pop
{ dup dup 127 le exch -128 ge and
{ dup xcheck { 146 } { 145 } ifelse wb
{ wotta /nametype get exec
{ dup dup length dup 255 le { 142 2 } { 2 intbytes 143 3 } ifelse wnb
/wop % Write object protection
{ wcheck not { /readonly cvx wo } if
{ dup type binary_tokens { wottb } { wotta } ifelse
% Write a hex string for Subrs or CharStrings.
{ % 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
psfile exch writehexstring
% ------ The main program ------ %
% Define the dictionary of actions for special entries in the dictionaries.
% We lump the font and the Private dictionary together, because
% the set of keys doesn't overlap.
[/CharStrings /Encoding /FID /FontInfo /Metrics /Private /Subrs]
currentdict end /specialkeys exch def
% Define the procedures for the Private dictionary.
% These must be defined without being bound.
/-! {string currentfile exch readhexstring pop} def
/-| {string currentfile exch readstring pop} def
currentdict end /privateprocs exch def
% Construct an inverse dictionary of encodings.
StandardEncoding /StandardEncoding def
ISOLatin1Encoding /ISOLatin1Encoding def
SymbolEncoding /SymbolEncoding def
currentdict end /encodingnames exch def
/writefont % psfile -> [writes the current font]
/readproc binary { (-| ) } { (-! ) } ifelse def
% 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.
{ ({} 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
% Write out the creation of the font dictionary and FontInfo.
Font length 1 add wt (dict begin) wl % +1 for FontFile
(/FontInfo ) ws FontInfo wd ( readonly def) wl
% Write out the other fixed entries in the font dictionary.
{ 1 index specialkeys exch known
{ pop pop } { we } ifelse
encodingnames Encoding known
{ encodingnames Encoding get cvx }
% Write out the Metrics, if any.
{ (/Metrics ) ws Metrics wld ( readonly def) wl
% Close the font dictionary.
% The rest of the file could be in eexec form, but we don't see any point
% in doing this, because we aren't attempting to conceal it from anyone.
% Create and initialize the Private dictionary.
Private dup length privateprocs length add dict copy begin
privateprocs { readonly def } forall
(dup /Private ) ws currentdict length 1 add wt (dict dup begin) wl
{ 1 index specialkeys exch known
{ pop pop } { we } ifelse
% Write the Subrs entries, if any.
{ (/Subrs ) ws Subrs length wt (array) wl
{ dup Subrs exch get dup null ne
{ /dup cvx wo exch wo dup length wo ( ) ws readproc ws wx ( |) wl }
% Write the CharStrings entries.
(2 index /CharStrings ) ws
CharStrings length wt (dict dup begin) wl
{ % Suppress recognizing the readonly status of the string.
dup length string copy wo
{ dup length wo ( ) ws readproc ws wx
% Wrap up the private part of the font.
(readonly put) wl % CharStrings in font
(readonly put) wl % Private in font
(dup /FontName get exch definefont pop) wl
Font /UniqueID known { (exec) wl } if
binary_tokens { (setobjectformat) wl } if