536 lines · 16.8 KB · Text
RawDownload
%    Copyright (C) 1995, 2000 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: gs_cmap.ps,v 1.19 2005/08/17 21:54:55 igor Exp $% ProcSet for implementing CMap resources.% When this is run, systemdict is still writable. % NOTE: Rearranged fonts are not implemented yet. [   /CMERGE_DEBUG   /USE_CIDCHAR_AS_RANGE] {dup where {pop pop} { currentdict exch //false def pop } ifelse} forall % ---------------- Public operators ---------------- % /.rewriteTempMapsNotDef {  %  % Before building .CodeMapData from .TempMaps,  % we need to replace dst type codes in the notdef map with the value 3,  % which corresponds to CODE_VALUE_NOTDEF, see gxfcmap.h .  %  CMAPDEBUG { (rewriting TempMapsNotDef\n) print flush } if  .TempMaps 2 get  dup length 0 gt {    0 get    CMAPDEBUG { (...original...\n) print flush } if    1 5 2 index length 1 sub {      { 1 index exch get 2 3 put } stopped      { CMAPDEBUG { (cannot rewrite\n) print flush } if }      { CMAPDEBUG { (rewrite\n) print flush } if } ifelse    } for  } if  pop  CMAPDEBUG { (...FINISHED...\n) print } if} bind def % composefont doesn't appear in CMap files -- it's documented in% the "PostScript Language Reference Manual Supplement"./composefont {		% <name> <cmap|cmapname> <fonts> composefont <font>  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    /FontInfo 1 dict def % for .processToUnicode in pdf_font.ps .    /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	} {	  /Font	} ifelse findresource      } 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 /WMode .knownget { /WMode exch def } if    /FontType 0 def  pop pop currentdict end /Font defineresource} bind odef % ---------------- CMap operators ---------------- % 40 dict begin % Our internal .CodeMapData structure closely mirrors the structures% defined in gxfcmap.h (q.v.).  () indicate a string, [] indicate an array,% ? indicates a Boolean, # indicates an integer, {} for grouping.%	[[[(first) (last) ...]+]		% code space ranges%	 [[(prefix) (key_size,?is_range,value_type,value_size) (keys...)%	   {(values...) | [value ...]} #font_index ]+]	% code mappings%	  ...]%	 <<same>>		% notdef mappings%	]% 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. % ****** NOTE: The code currently only handles "well-behaved" CMaps:%	- CID values only (no bfchars), 16-bit%	- Entries (both code space and map) must be sorted%	- Only the last byte must vary in each map range, except for%	the identity mapping % ------ Font-level operators ------ % /begincmap {		% - begincmap -  /.CodeMapData [[[]] [[]] [[]]] def  /FontMatrices [] def  /.FontIndex 0 def  /.TempMaps [20 dict 50 dict 50 dict] def  /CodeMap //null def		% for .buildcmap} bind def /endcmap {		% - endcmap -  .rewriteTempMapsNotDef   CMAPDEBUG {    2 (*** undefined charmap ***)    1 (*** defined charmap ***)    0 (*** code space ranges ***)    3 { =      .TempMaps exch get      0 1 2 index length 1 sub {        dup == (\t) print        1 index exch get ==      } for      pop    } repeat  } if    /.CodeMapData dup load [ exch    .TempMaps aload pop begin begin begin     {      [ exch aload pop        0 1 currentdict length 1 sub {            currentdict exch get         } for       ]      end    } forall  ] .endmap def   CMAPDEBUG {    (*** Content of .CodeMapData ***) =    0 .CodeMapData { exch dup == 1 add exch (\t) print == } forall    pop  } if   currentdict /.TempMaps undef  /FontMatrices FontMatrices .endmap def} bind def /.endmap {		% <map> .endmap <map>  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 {      0 1 2 index length 1 sub {	2 copy 2 copy get .endmap put pop      } for readonly    } if  } {    dup type /stringtype eq { readonly } if  } ifelse} bind def /.appendmap {		% -mark- <elt> ... <array#> .appendmap -  .TempMaps exch get counttomark 1 add 1 roll  ] 1 index length exch put} bind def /begincodespacerange {	% <count> begincodespacerange -  pop mark} bind def /endcodespacerange {	% <code_lo> <code_hi> ... endcodespacerange -  0 .appendmap} bind def /usecmap {		% <CMap_name> usecmap -  /CMap findresource dup		% Copy the top level of .CodeMapData  /.CodeMapData exch /.CodeMapData get copyarray def  /FontMatrices exch /FontMatrices get copyarray def} bind def /usefont {		% <fontID> usefont -  /.FontIndex exch def} bind def /beginusematrix {	% <fontID> 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 {		% <matrix> endusematrix -  FontMatrices 3 1 roll put} bind def % ------ Rearranged font operators ------ % /beginrearrangedfont {	% <font_name> <font*> 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 {		% <count> beginbfchar -  pop mark} bind def/endbfchar {		% <code> <to_code|charname> ... endbfchar  counttomark 2 idiv {    counttomark -2 roll		% process in correct order    .addbfchar  } repeat 1 .appendmap} bind def /beginbfrange {		% <count> beginbfrange -  pop mark} bind def/endbfrange {		% <code_lo> <code_hi> <to_code|(charname*)> ...			%   endbfrange -  counttomark 3 idiv {    counttomark -3 roll		% process in correct order    dup type dup /arraytype eq exch /packedarraytype eq or {			% Array value, split up.      exch pop {			% Stack: code to_code|charname	1 index exch .addbfchar			% Increment the code.  As noted above, we require			% that only the last byte vary, but we still must			% mask it after incrementing, in case the last			% value was 0xff.			% Stack: code prefix params key value fontindex	6 -1 roll dup length string copy	dup dup length 1 sub 2 copy get 1 add 255 and put      } forall pop    } {			% Single value, handle directly.      .addbfrange    } ifelse  } repeat 1 .appendmap} bind def /.addbfchar {		% <code> <to_code|charname> .addbfchar			%   <prefix> <params> <key> <value> <font_index>  1 index exch .addbfrange} bind def/.addbfrange {		% <code_lo> <code_hi> <to_code|charname>			%   .addbfrange <<same as .addbfchar>>  4 string dup 3  3 index type /nametype eq {    2 index 2 1 put % dst = CODE_VALUE_GLYPH, see gxfcmap.h .    4 -1 roll 1 array astore 4 1 roll 4  } {    2 index 2 2 put % dst = CODE_VALUE_CHARS, see gxfcmap.h .    3 index length  } ifelse put			% Stack: code_lo code_hi value params  3 index 3 index eq {			% Single value.    3 -1 roll pop exch () exch  } {			% Range.    dup 0 1 put dup 1 1 put    4 2 roll    dup dup length 1 sub 0 exch getinterval 5 1 roll	% prefix			% Stack: prefix value params code_lo code_hi    2 { exch dup length 1 sub 1 getinterval } repeat concatstrings    3 -1 roll  } ifelse  .FontIndex} bind def % ------ CID selector operators ------ % /begincidchar {		% <count> begincidchar -  pop mark} bind def/endcidchar {		% <code> <cid> ... endcidchar -  1 .endmapchars} bind def /begincidrange {	% <count> begincidrange -  pop mark} bind def/endcidrange {		% <code_lo> <code_hi> <cid_base> ... endcidrange -  1 .endmapranges} bind def /.endmapchars {         % -mark- <code> <cid> ... <map#> .endmapchars -  counttomark 1 add 1 roll  counttomark 2 idiv {    counttomark -2 roll         % process in correct order    exch        % <cid> <code>                % Construct prefix, params, key, value, font_index    dup length 1 eq {   % 1-byte      <00 00 00 02> ()  % <prefix> <param> <null_key>    } {                 % N-byte      dup 0 1 getinterval exch  % make 1-byte prefix      4 string dup 0      USE_CIDCHAR_AS_RANGE {        <00 01 00 02>   % skelton for param      } {        <00 00 00 02>   % skelton for param      } ifelse      putinterval      exch              % <prefix> <param> <code>      dup length        % <prefix> <param> <code> N      1 sub             % <prefix> <param> <code> N-1      dup               % <prefix> <param> <code> N-1 N-1      3 index           % <prefix> <param> <code> N-1 N-1 <param>      exch              % <prefix> <param> <code> N-1 <param> N-1      0 exch            % <prefix> <param> <code> N-1 <param> 0 N-1      put               % <prefix> <param'> <code> N-1      1 exch            % <prefix> <param'> <code> 1 N-1      getinterval       % <prefix> <param'> <key>       USE_CIDCHAR_AS_RANGE {        dup length 2 mul string % <key> <dkey>        dup                     % <key> <dkey> <dkey>        2 index                 % <key> <dkey> <dkey> <key>        0 exch putinterval      % <key> <dkey'>        dup                     % <key> <dkey'> <dkey'>        3 -1 roll               % <dkey'> <dkey'> <key>        dup length              % <dkey'> <dkey'> <key> N-1        exch putinterval        % <dkey''>      } if     } ifelse     4 -1 roll           % <prefix> <param'> <key> <cid>    .endmapvalue        % <prefix> <param'> <key> <hex_cid> <font_idx>    % prefix params keys value fontindex    counttomark 5 gt { % 2 (or more) ranges (1 range = 5 item)       4 index 10 index eq      % compare prefix       4 index 10 index eq and  % compare params       1 index 7 index eq and   % compare fontindex        {          CMAPDEBUG { (merge! char\n) print } if          pop 4 2 roll pop pop           % prefix params keys value fontindex keys2 value2          5 -1 roll 3 -1 roll concatstrings           % prefix params value fontindex value2 keys'          4 -1 roll 3 -1 roll concatstrings           % prefix params fontindex keys' values'          3 -1 roll        } if     } if % end of 2 (or more) ranges    CMERGE_DEBUG {    ( prefix:) print 4 index =only    ( param:) print 3 index =only    ( key:) print 2 index =only    ( hex_cid:) print 1 index =only    ( font_idx:) print 0 index == flush    } if  } repeat  counttomark 2 add -1 roll .appendmap} bind def /.endmapranges {	% -mark- <code_lo> <code_hi> <cid_base> ... <map#>			%   .endmapranges -  counttomark 1 add 1 roll  counttomark 3 idiv {    counttomark -3 roll		% process in correct order		% Construct prefix, params, key_lo, key_hi, value, font_index    3 1 roll	% <cid_base> <code_lo> <code_hi>		%		prefix	key		% 1-byte code:	()	.		% 1-byte range:	()	.		% N-byte code:	.	(*)		% N-byte range:	(*)	(*)    dup 2 index eq {	% <code_lo> == <code_hi>           		% 0: prefix_len for 1-byte code           		% 1: prefix_len for N-byte code       dup length 1 eq { 0 } { 1 } ifelse    } {			% <code_lo> != <code_hi>     			% calculate prefix_len for *-byte range       dup length 1 sub % <cid_base> <code_lo> <code_hi> <code_len-1>       0		% initial value for N       {		% <cid_base> <code_lo> <code_hi> (code_len-1)  N           dup 2 index ge { exit } if % if (N >= len - 1) exit           3 index 1 index get	% N-th byte of code_lo           3 index 2 index get	% N-th byte of code_hi           eq { 1 add } { exit } ifelse       } loop       exch pop 	% discard <code_len-1>    } ifelse				% cid_base code_lo code_hi prefix_len     % Althogh Adobe CPSI with native CID/CMap support accept    % multi-dimensional range specification in notdef & cidrange    % (and CID is calculated as relative position in multi-dimensional    % range), but older CPSI & ATM cannot handle it.    %     % GS accepts such specification, but it's recommended to keep    % from using this feature for notdef & cidrange.    % Following is a disabler of this feature.    % -------------------------------------------------------------    % counttomark 1 add index 	% get map#    % 0 ne {			% if not codespacerange    %   1 index length 		% get code length    %   1 index 			% get prefix length    %   sub			% calculate key length    %   1 gt {			% if (key_len > 1),    %      (.endmapranges error) = flush    %      (multi-dimensional range specification is used out of codespacerange)    %      = flush    %      (/) =only    %      CMapName CMapName length string cvs =only    %      (: <) =only    %      2 index (%stdout) (w) file exch writehexstring    %      (> <) =only    %      1 index (%stdout) (w) file exch writehexstring    %      (>\n) =only flush    %      quit    %   } if    % } if    % -------------------------------------------------------------     1 index exch 0 exch getinterval				% cid_base code_lo code_hi prefix    dup length 3 index length exch sub				% cid_base code_lo code_hi prefix range_len    dup 255 gt {       (too long coderange specification for current GS\n) print       signalerror    } if    <00 01 00 02> 4 string copy	% create initialized param    dup 0 4 -1 roll put		% put range_len into param     % get key_hi    3 -1 roll dup length 3 index length dup 3 1 roll sub getinterval     % get key_lo    4 -1 roll dup length 4 index length dup 3 1 roll sub getinterval     % make "keys" (concatenated key_lo + key_hi)    exch concatstrings     %     4 -1 roll    .endmapvalue 		% See if we can merge with the previous value.		% The prefix, params, and font index must match.    % prefix params keys value fontindex    counttomark 5 gt { % 2 (or more) ranges (1 range = 5 item)       4 index 10 index eq	% compare prefix       4 index 10 index eq and	% compare params       1 index 7 index eq and	% compare fontindex	{          CMAPDEBUG { (merge!\n) print } if	  pop 4 2 roll pop pop           % prefix params keys value fontindex keys2 value2	  5 -1 roll 3 -1 roll concatstrings           % prefix params value fontindex value2 keys'	  4 -1 roll 3 -1 roll concatstrings           % prefix params fontindex keys' values'	  3 -1 roll	} if     } if % end of 2 (or more) ranges  } repeat  counttomark 2 add -1 roll .appendmap} bind def /.endmapvalue {		% <cid> .endmapvalue (hi,lo) .FontIndex  2 string dup 0 3 index -8 bitshift put	% value  dup 1 4 -1 roll 255 and put  .FontIndex		% font_index} bind def % ------ notdef operators ------ % /beginnotdefchar {	% <count> beginnotdefchar -  pop mark} bind def/endnotdefchar {	% <code> <cid> ... endnotdefchar -  2 .endmapchars} bind def /beginnotdefrange {	% <count> beginnotdefrange -  pop mark} bind def/endnotdefrange {	% <code_lo> <code_hi> <cid> ... endnotdefrange -  2 .endmapranges} bind def

Lines 1–500 of 536.