% Copyright (C) 1995, 1996, 1997, 1998, 1999 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. % $Id: gs_cmap.ps,v 1.1 2000/03/09 08:40:39 lpd Exp $ % ProcSet for implementing CMap resources. % When this is run, systemdict is still writable. % NOTE: Rearranged fonts are not implemented yet. % ---------------- Public operators ---------------- % % composefont doesn't appear in CMap files -- it's documented in % the "PostScript Language Reference Manual Supplement". /composefont { % composefont 10 dict begin /CMap 2 index dup type /dicttype ne { /CMap findresource } if def /FDepVector 1 index cvlit def % temporarily /Encoding [ 0 1 FDepVector length 1 sub { } for ] def /FDepVector [ 0 1 FDepVector length 1 sub { % Stack: name cmap[name] fonts /FDepVector [ fonts... i FDepVector 1 index get dup type /dicttype ne { dup /CIDFont resourcestatus { pop pop /CIDFont findresource } { /Font findresource } ifelse } if exch CMap /FontMatrices get dup length 2 index gt { exch get dup null eq { pop } { makefont } ifelse } { pop pop } ifelse } for ] readonly def /FMapType 9 def /FontMatrix matrix def /FontName 3 index def /CMap load /WMode .knownget { /WMode exch def } if /FontType 0 def pop pop currentdict end /Font defineresource } bind odef % ---------------- CMap operators ---------------- % 40 dict begin % Our internal .CodeMaps structure is an array of two arrays: array 0 % is the map for defined characters, array 1 is the map for notdefs. % Both are multi-level arrays indexed by the successive bytes of the % character code. Each value is either a sub-array, null, a character name, % a CID (an integer), or a character code (expressed as a byte string). % .FontIndices is a similar array holding the corresponding usefont values, % except that if the only font index is 0, the .FontIndices element is 0. % FontMatrices is the array of matrices defined by begin/endusematrix. % All of the arrays and strings are read-only after they have been built. % % Note that the code in zfcmap.c that constructs the C structures from % the PostScript structures has intimate knowledge of the above format. % ------ Font-level operators ------ % /begincmap { % - begincmap - /.CodeMaps [256 array 256 array] def /.FontIndices [0 0] def /FontMatrices [] def /.FontIndex 0 def } bind def /endcmap { % - endcmap - /.CodeMaps .CodeMaps .endmap def /.FontIndices .FontIndices .endmap def /FontMatrices FontMatrices .endmap def /CodeMap null def % for .buildcmap currentdict end .buildcmap begin } bind def /begincodespacerange { % begincodespacerange - pop mark } bind def /endcodespacerange { % ... endcodespacerange - counttomark 2 idiv { .CodeMaps { 3 copy .addcodespacerange pop } forall pop pop } repeat pop } bind def /.addcodespacerange { % .addcodespacerange - 2 index length 1 eq { 2 { 3 -1 roll 0 get } repeat 1 exch { 2 copy 0 put pop } for pop } { 2 index 0 get 1 3 index 0 get 6 -2 roll 2 { 1 1 index length 1 sub getinterval 6 1 roll } repeat % Stack: lo hi map lo0 1 hi0 { 2 copy get null eq { 2 copy 256 array put } if 4 copy get .addcodespacerange pop } for pop pop pop } ifelse } bind def /.endmap { % .endmap dup type /arraytype eq { % This might be a shared read-only array inherited via usecmap. % Don't try to update its elements if this is the case. dup wcheck { dup { .endmap exch } forall astore readonly } if } { dup type /stringtype eq { readonly } if } ifelse } bind def /usecmap { % usecmap - /CMap findresource dup /.CodeMaps get dup length array copy /.CodeMaps exch def /.FontIndices get /.FontIndices exch def } bind def /usefont { % usefont - /.FontIndex exch def } bind def /beginusematrix { % beginusematrix - FontMatrices wcheck not FontMatrices length 2 index le or { FontMatrices length 1 index 1 add .max array dup 0 FontMatrices putinterval /FontMatrices exch def } if } bind def /endusematrix { % endusematrix - FontMatrices 3 1 roll put } bind def % ------ Rearranged font operators ------ % /beginrearrangedfont { % beginrearrangedfont - 10 dict begin /.FontNames exch def /.FontName exch def begincmap } bind def /endrearrangedfont { % - endrearrangedfont - (REARRANGED FONTS NOT IMPLEMENTED YET.) = flush FontName .FontNames 0 get findfont end definefont pop } bind def % ------ Character name/code selector operators ------ % /beginbfchar { % beginbfchar - pop mark } bind def /endbfchar { % ... endbfchar .endmapchar } bind def /beginbfrange { % beginbfrange - pop mark } bind def /endbfrange { % ... % endbfrange - counttomark 3 idiv { counttomark -3 roll % process in correct order .addbfrange } repeat pop } bind def /.addbfrange { % % .addbfrange dup type /stringtype eq { { dup length string copy dup dup length 1 sub 2 copy get 1 add put } .addcharrange } { 2 dict begin /codes 1 index def 0 get { pop codes dup dup length 1 sub 1 exch getinterval /codes exch def dup length 0 gt { 0 get } if } .addcharrange end } ifelse } bind def % ------ CID selector operators ------ % /begincidchar { % begincidchar - pop mark } bind def /endcidchar { % ... endcidchar - .endmapchar } bind def /begincidrange { % begincidrange - pop mark } bind def /endcidrange { % ... endcidrange - counttomark 3 idiv { counttomark -3 roll % process in correct order { 1 add } .addcharrange } repeat pop } bind def /.endmapchar { % -mark- ... .endmapchar - counttomark 2 idiv { counttomark -2 roll % process in correct order 1 index exch { } .addcharrange } repeat pop } bind def /.addcharrange { % % .addcharrange - 0 .putmaprange } bind def /.putmaprange { % <0|1> % .putmaprange - 5 1 roll % Most CMaps don't involve multiple fonts. % For this reason, we create .FontIndices lazily. .FontIndices 5 index get 0 eq .FontIndex 0 ne and { % Create .FontIndices now. .CodeMaps 5 index get .makecodespace .FontIndices 6 index 3 -1 roll put } if .FontIndices 5 index get 0 ne { 3 index 3 index .FontIndex { } .FontIndices 9 index get .addmaprange .FontIndices 7 index 3 -1 roll put pop } if .CodeMaps 5 index get .addmaprange .CodeMaps 3 index 3 -1 roll put pop pop } bind def /.makecodespace { % .makecodespace - dup type /arraytype eq { [ exch { .makecodespace } forall ] } { pop 0 } ifelse } bind def /.addmaprange { % % .addmaprange % We may be updating a (partly) read-only map from another CMap. % If so, implement copy-on-write. dup wcheck not { dup length array copy } if 4 index length 1 eq { 2 { 5 -1 roll 0 get } repeat 1 exch { % Stack: value proc map code 2 copy 5 index put pop 3 -1 roll 2 index exec 3 1 roll } for } { 4 index 0 get 1 5 index 0 get 8 -2 roll 2 { 1 1 index length 1 sub getinterval 8 1 roll } repeat % Stack: lo hi next proc map lo0 1 hi0 { 6 copy get .addmaprange % Stack: lo hi oldnext proc map i next submap exch 6 1 roll 5 -1 roll pop % Stack: lo hi next proc map i submap 3 copy put pop pop } for 5 -2 roll pop pop } ifelse exch pop } bind def % ------ notdef operators ------ % /beginnotdefchar { % beginnotdefchar - pop mark } bind def /endnotdefchar { % ... endnotdefchar - counttomark 2 idiv { counttomark -2 roll % process in correct order 1 index exch .addnotdefrange } repeat pop } bind def /beginnotdefrange { % beginnotdefrange - pop mark } bind def /endnotdefrange { % ... endnotdefrange - counttomark 3 idiv { counttomark -3 roll % process in correct order .addnotdefrange } repeat pop } bind def /.addnotdefrange { % .addnotdefrange - { } 1 .putmaprange } bind def % ---------------- Resource category definition ---------------- % currentdict end languagelevel exch 2 .setlanguagelevel /CMap /Generic /Category findresource dup length dict .copydict /Category defineresource pop % We might have loaded CID font support already. /CIDInit /ProcSet 2 copy { findresource } .internalstopped % An interior `stopped' might have reset VM allocation to local. true .setglobal { pop pop 3 -1 roll } { dup length 4 index length add dict .copydict 4 -1 roll exch .copydict } ifelse exch defineresource pop .setlanguagelevel