diff options
Diffstat (limited to 'gs/lib/t1tot2.ps')
-rw-r--r-- | gs/lib/t1tot2.ps | 485 |
1 files changed, 485 insertions, 0 deletions
diff --git a/gs/lib/t1tot2.ps b/gs/lib/t1tot2.ps new file mode 100644 index 000000000..e41638797 --- /dev/null +++ b/gs/lib/t1tot2.ps @@ -0,0 +1,485 @@ +% Copyright (C) 1997 Aladdin Enterprises. All rights reserved. +% +% This file is part of Aladdin Ghostscript. +% +% Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author +% or distributor accepts any responsibility for the consequences of using it, +% or for whether it serves any particular purpose or works at all, unless he +% or she says so in writing. Refer to the Aladdin Ghostscript Free Public +% License (the "License") for full details. +% +% Every copy of Aladdin Ghostscript must include a copy of the License, +% normally in a plain ASCII text file named PUBLIC. The License grants you +% the right to copy, modify and redistribute Aladdin Ghostscript, but only +% under certain conditions described in the License. Among other things, the +% License requires that the copyright notice and this notice be preserved on +% all copies. + +% t1tot2.ps +% Convert a Type 1 font with Type 1 CharStrings to Type 2. +% **************** THIS FILE DOES NOT WORK. **************** +% **************** DON'T TRY TO USE IT. **************** + +(type1ops.ps) runlibfile + +% ---------------- CharString conversion ---------------- % + +% In the following lists, implemented conversions are marked with a +. +% The following conversions are required for each CharString: +% + Remove lenIV initial bytes and decrypt. +% + Move width to first stem/moveto. +% + Move all hstem/vstem commands to the beginning, +% including any from subroutines. +% Fold side bearing into first moveto. +% + Adjust Subr indices for bias. +% + Remove all closepath. +% Convert Flex othersubrs to new flex commands. +% Convert hint replacement to -hm and hintmask. +% Convert MM blend othersubrs to new blend command. +% For seac, convert char bodies to subrs, add hint replacement. +% + Make width relative to nominalWidthX, or omit if equal to +% defaultWidthX. +% The following patterns allow shortening CharStrings: +% + rlineto+ => rlineto +% + rlineto+ (hlineto | vlineto) rlineto+ => rlineto +% + vlineto (hlineto vlineto)* [hlineto] => vlineto +% + hlineto (vlineto hlineto)* [vlineto] => hlineto +% + rrcurveto+ => rrcurveto +% + rrcurveto+ rlineto => rcurveline +% + rlineto+ rrcurveto => rlinecurve +% + (vhcurveto hvcurveto)* [vhcurveto ["hrcurveto"] | "vrcurveto"] => +% vhcurveto +% + (hvcurveto vhcurveto)* [hvcurveto ["vrcurveto"] | "hrcurveto"] => +% hvcurveto +% "rvcurveto" (0 y1 x2 y2 0 y3 rrcurveto)* => vvcurveto +% "hrcurveto" (x1 0 x2 y2 x3 0 rrcurveto)* => hhcurveto + +% Convert a CharString from Type 1 to Type 2. +% Free variables: font, subrmap. + +/t1tot2cs { % <charstring1> <forsubr> t1tot2cs <charstring2> + 10 dict begin + /forsubr exch def + % Collect the hints, side bearing, and width. + /vhints 10 dict def + /hhints 10 dict def + /hmcount null def + /lsb null def + /width null def + forsubr not { + dup t1hintops t1scan pop + } if + t1t2ops t1scan + [ + forsubr not { + % Insert the hints and width at the beginning. + width dup font /nominalWidthX .knownget { sub } if + exch font /defaultWidthX .knownget not { 0 } if + eq { pop } if + /hstem hhints hintlist + /vstem vhints hintlist + } if + counttomark 2 add -1 roll aload pop ] + % Convert the string back to encoded form. + DEBUG { + (++++ ) print [ 1 index { dup null eq { pop } if } forall ] == flush + } if + /lenIV 0 def % for charproc_string + charproc_string end +} bind def +/hintlist { % <hintop> <dict> hintlist - + dup length 0 eq { + pop pop + } { + dup length array dup 3 -1 roll { + exch put dup + } forall pop + % ****** SORT THE HINTS BY INCREASING v ****** + { dup length 24 le { exit } if + dup 0 24 getinterval { aload pop 4 2 roll } forall + dup length 24 sub 24 exch getinterval + } loop + { aload pop 3 2 roll } forall + } ifelse +} bind def +/uneexec { % <string> <lenIV> uneexec <string> + dup 0 ge { + 2 copy mark /seed 4330 /lenIV 5 -1 roll .dicttomark /eexecDecode filter + % Stack: string lenIV filter + dup 4 -1 roll length 4 -1 roll sub string readstring pop + exch closefile + } { + pop + } ifelse +} bind def +/t1scan { % <charstring> <opsdict> t1scan <tokens> + 5 dict begin + /opsdict exch def + % Remove encryption and convert to symbolic form for processing. + font /lenIV .knownget not { 4 } if uneexec + 0 () /SubFileDecode filter /f exch def + /cstr [ 20 { null } repeat f charstack_read /END 20 { null } repeat ] def + DEBUG { + (**** ) print [ cstr { dup null eq { pop } if } forall ] == flush + } if + % Scan the unpacked string. + /i 20 def { + % The /END token will exit from this loop. + opsdict cstr i get .knownget { exec } if + /i i 1 add def + } loop + f closefile cstr end +} bind def +/ciget { % <di> ciget <token> + i add cstr exch get +} bind def +/ciput { % <di> <token> ciput - + exch i add exch cstr 3 1 roll put +} bind def +/ciswap { % <di> <dj> ciswap - + 2 copy exch ciget exch ciget 3 1 roll ciput ciput +} bind def +/ciskip { % <di> ciskip - + i add /i exch def +} bind def + +% Hint scanning procedures. +/addhint { % [<v> <dv>] <hintdict> addhint - + dup 2 index known { pop pop } { dup length 3 -1 roll exch put } ifelse +} bind def + +/t1hintops mark /END { 0 null ciput exit } bind + +/vstem { + cstr i 2 sub 2 getinterval vhints addhint +} bind +/hstem { + cstr i 2 sub 2 getinterval hhints addhint +} bind +/callsubr { + %**** DOESN'T HANDLE FLEX YET **** + -1 ciget /pop eq { + % This must be a <#> 1 3 /callothersubr /pop /callsubr sequence. + hmcount null eq { /hmcount [ vhints length hhints length ] store } if + -5 ciget + } { + -1 ciget + } ifelse + subrmap 1 index .knownget { exch pop } if + dup null eq { pop } { + font /Private get /Subrs get exch get + t1hintops t1scan pop + } ifelse +} bind +/hsbw { + /lsb -2 ciget store + /width -1 ciget store +} bind +/vstem3 { + [ -6 ciget -5 ciget ] vhints addhint + [ -4 ciget -3 ciget ] vhints addhint + [ -2 ciget -1 ciget ] vhints addhint +} bind +/hstem3 { + [ -6 ciget -5 ciget ] hhints addhint + [ -4 ciget -3 ciget ] hhints addhint + [ -2 ciget -1 ciget ] hhints addhint +} bind +/sbw { + %**** WHAT ABOUT Y? **** + /lsb -4 ciget store + /width -2 ciget store +} bind + +.dicttomark readonly def % t1hintops + +% Conversion procedures. +/t1t2ops mark /END { 0 null ciput exit } bind + +/hstem { + % We handled the hints separately, drop them here. + -2 1 0 { null ciput } for +} bind +/vstem 1 index +/rlineto { + 3 ciget /rlineto eq { + 0 null ciput + } { + 7 ciget /rrcurveto eq { + 0 null ciput + 7 /rlinecurve ciput + } { + 5 ciget /rlineto eq { + 2 ciget /hlineto eq { + 0 null ciput + 2 0 ciput + } { + 2 ciget /vlineto eq { + 0 0 ciput + 2 null ciput + } if + } ifelse + } if + } ifelse + } ifelse +} bind +/vlineto { + 2 ciget /hlineto eq { + 0 null ciput + 2 4 ciget /vlineto eq { null } { /vlineto } ifelse ciput + } if +} bind +/hlineto { + 2 ciget /vlineto eq { + 0 null ciput + 2 4 ciget /hlineto eq { null } { /hlineto } ifelse ciput + } if +} bind +/rrcurveto { + 7 ciget /rrcurveto eq { + 0 null ciput + } { + 3 ciget /rlineto eq { + 0 null ciput + 3 /rcurveline ciput + } { + %**** WRONG IF MULTIPLE RRCURVETO **** + -6 ciget 0 eq { + -6 null ciput + 0 /vhcurveto ciput + } { + -5 ciget 0 eq { + -5 null ciput + -1 -2 ciswap + 0 /hvcurveto ciput + } if + } ifelse + } ifelse + } ifelse +} bind +/callsubr { + -1 ciget subrmap 1 index .knownget { exch pop } if + % If the Subr was deleted because it was empty, delete the call. + dup null eq { + 0 null ciput + } { + % Subtract the subroutineNumberBias. + 107 sub + } ifelse -1 exch ciput +} bind +/vhcurveto { + 5 ciget /hvcurveto eq { + 0 null ciput + 10 ciget /vhcurveto eq { + 5 null ciput + } { + 12 ciget /rrcurveto eq 6 ciget 0 eq and { + 5 null ciput + 6 null ciput + 12 /vhcurveto ciput + 12 ciskip + } { + 5 /vhcurveto ciput + 5 ciskip + } ifelse + } ifelse + } { + 7 ciget /rrcurveto eq { + 1 ciget 0 eq { + 0 null ciput + 1 null ciput + 5 6 ciswap + 7 /vhcurveto ciput + 7 ciskip + } if + } if + } ifelse +} bind +/hvcurveto { + 5 ciget /vhcurveto eq { + 0 null ciput + 10 ciget /hvcurveto eq { + 5 null ciput + } { + 12 ciget /rrcurveto eq 7 ciget 0 eq and { + 5 null ciput + 7 null ciput + 10 11 ciswap + 12 /hvcurveto ciput + 12 ciskip + } { + 5 /hvcurveto ciput + 5 ciskip + } ifelse + } ifelse + } { + 7 ciget /rrcurveto eq { + 2 ciget 0 eq { + 0 null ciput + 2 null ciput + 7 /hvcurveto ciput + 7 ciskip + } if + } if + } ifelse +} bind +/closepath { + 0 null ciput +} bind +/hsbw { + % We handled this separately, drop it. + -2 1 0 { null ciput } for +} bind +/dotsection { + %**************** NYI **************** +} bind +/vstem3 { + % We handled the hints separately, drop them here. + -6 1 0 { null ciput } for +} bind +/hstem3 1 index +/seac { + %**************** NYI **************** +} bind +/sbw { + % We handled this separately, drop it. + -4 1 0 { null ciput } for +} bind +/callothersubr { + -1 ciget 3 eq { + %**** HANDLE HINT REPLACEMENT **** + -2 ciget 1 eq 1 ciget /pop eq and 2 ciget /callsubr eq and { + 1 -3 ciget ciput + -3 1 0 { null ciput } for + } { + (**************** 3 callothersubr -- invalid call\n) print + /t1tot2cs cvx /rangecheck signalerror + } ifelse + } if +} bind +/pop { + %**************** NYI **************** +} bind +/setcurrentpoint { + %**************** NYI **************** +} bind + +.dicttomark readonly def % t1t2ops + +% ---------------- Font conversion ---------------- % + +% Copy a font, and remove eexec encryption from it. +/decryptfont { % <font> decryptfont <font'> + % Copy the font, CharStrings, Private, and Private.Subrs + dup length dict copy + dup /CharStrings 2 copy get dup length dict copy put + dup /Private 2 copy get dup length dict copy + dup /Subrs 2 copy get dup length array copy put + put + dup /lenIV .knownget not { 4 } if + 1 index /CharStrings get + % Stack: font' lenIV chars' + dup { 3 index uneexec 2 index 3 1 roll put } forall pop + 1 index /Private get /Subrs get + % Stack: font' lenIV Subrs' + 0 1 2 index length 1 sub { + 2 copy get dup type /stringtype eq { + % Stack: font' lenIV Subrs' index subr + 3 index uneexec + } if 2 index 3 1 roll put + } for pop pop dup /lenIV -1 put +} def + +% Convert an entire font from Type 1 to Type 2. +/t1tot2font { % <font> t1tot2font <font'> + 10 dict begin + /font exch def + /niv font /lenIV .knownget not { 4 } if def + + % Print initial statistics. + + (lenIV = ) print niv = + font /CharStrings get + dup length =only ( CharStrings, ) print + 0 exch { exch pop length add } forall =only ( bytes) = + font /Private get /Subrs get + dup length =only ( Subrs, ) print + 0 exch { length add } forall =only ( bytes) = + flush + + % Remove CharString encryption from the font. + + /font font decryptfont def + /chars font /CharStrings get dup length dict copy def + /subrs font /Private get /Subrs get def + + % Remove empty Subrs, including Subrs 0-3. + + /subrmap subrs length dict def + 0 1 3 { subrs exch <0b> put } for + 0 1 subrs length 1 sub { + subrs 1 index get true t1tot2cs + length 1 eq { + subrs 1 index null put + subrmap exch null put + } { + pop + } ifelse + } for + + % Remove duplicate Subrs (!). + + % Make an entry in subrdict for each distinct Subr: + % key = Subr charstring, value = (lowest) Subr index. + % At the same time, make entries in subrmap for any duplicates: + % key = higher index, value = lowest index. + /subrdict subrs length dict def + 0 0 1 subrs length 1 sub { + % Stack: toindex fromindex + subrs 1 index get subrdict 1 index .knownget { + % Stack: toindex fromindex subr firstindex + subrmap 4 -1 roll 3 -1 roll put pop + } { + dup null ne { + % Stack: toindex fromindex subr + subrmap 3 -1 roll 3 index put % fromindex => toindex + subrdict 1 index 3 index put % subr => toindex + subrs 2 index 3 -1 roll put % toindex => subr + 1 add + } { + pop pop + } ifelse + } ifelse + } for + /subrs1 subrs 0 4 -1 roll getinterval def + font /Private get /Subrs subrs1 put + + % Convert the font. + + /chars2 chars length dict def + chars { false t1tot2cs chars2 3 1 roll put } forall + /subrs2 subrs1 length array def + 0 1 subrs1 length 1 sub { + subrs1 1 index get true t1tot2cs + subrs2 3 1 roll put + } for + font /Private get /Subrs subrs2 put + + % Print final statistics. + + (CharStrings => ) print 0 chars2 { exch pop length add } forall =only + ( bytes) = + subrs2 length =only ( Subrs, ) print + 0 subrs2 { length add } forall =only ( bytes) = + flush + + % Clean up the font. + + font /lenIV undef + font /UniqueID undef + font /FID undef + font /CharStrings chars2 put + font /CharstringType 2 put + + font end +} bind def |