]> git.lizzy.rs Git - plan9front.git/blob - sys/lib/ghostscript/gs_cmap.ps
aux/cpuid: decode family and model bitfields
[plan9front.git] / sys / lib / ghostscript / gs_cmap.ps
1 %    Copyright (C) 1995, 2000 Aladdin Enterprises.  All rights reserved.
2
3 % This software is provided AS-IS with no warranty, either express or
4 % implied.
5
6 % This software is distributed under license and may not be copied,
7 % modified or distributed except as expressly authorized under the terms
8 % of the license contained in the file LICENSE in this distribution.
9
10 % For more information about licensing, please refer to
11 % http://www.ghostscript.com/licensing/. For information on
12 % commercial licensing, go to http://www.artifex.com/licensing/ or
13 % contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14 % San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15
16 % $Id: gs_cmap.ps,v 1.19 2005/08/17 21:54:55 igor Exp $
17 % ProcSet for implementing CMap resources.
18 % When this is run, systemdict is still writable.
19
20 % NOTE: Rearranged fonts are not implemented yet.
21
22 [
23    /CMERGE_DEBUG
24    /USE_CIDCHAR_AS_RANGE
25 ] {dup where {pop pop} { currentdict exch //false def pop } ifelse} forall
26
27 % ---------------- Public operators ---------------- %
28
29 /.rewriteTempMapsNotDef {
30   %
31   % Before building .CodeMapData from .TempMaps,
32   % we need to replace dst type codes in the notdef map with the value 3,
33   % which corresponds to CODE_VALUE_NOTDEF, see gxfcmap.h .
34   %
35   CMAPDEBUG { (rewriting TempMapsNotDef\n) print flush } if
36   .TempMaps 2 get
37   dup length 0 gt {
38     0 get
39     CMAPDEBUG { (...original...\n) print flush } if
40     1 5 2 index length 1 sub {
41       { 1 index exch get 2 3 put } stopped
42       { CMAPDEBUG { (cannot rewrite\n) print flush } if }
43       { CMAPDEBUG { (rewrite\n) print flush } if } ifelse
44     } for
45   } if
46   pop
47   CMAPDEBUG { (...FINISHED...\n) print } if
48 } bind def
49
50 % composefont doesn't appear in CMap files -- it's documented in
51 % the "PostScript Language Reference Manual Supplement".
52 /composefont {          % <name> <cmap|cmapname> <fonts> composefont <font>
53   10 dict begin
54     /CMap 2 index dup type /dicttype ne { /CMap findresource } if def
55     /FDepVector 1 index cvlit def       % temporarily
56     /Encoding [ 0 1 FDepVector length 1 sub { } for ] def
57     /FontInfo 1 dict def % for .processToUnicode in pdf_font.ps .
58     /FDepVector [ 0 1 FDepVector length 1 sub {
59                 % Stack: name cmap[name] fonts /FDepVector [ fonts... i
60       FDepVector 1 index get
61       dup type /dicttype ne {
62         dup /CIDFont resourcestatus {
63           pop pop /CIDFont
64         } {
65           /Font
66         } ifelse findresource
67       } if
68       exch CMap /FontMatrices get dup length 2 index gt {
69         exch get dup //null eq { pop } { makefont } ifelse
70       } {
71         pop pop
72       } ifelse
73     } for ] readonly def
74     /FMapType 9 def
75     /FontMatrix matrix def
76     /FontName 3 index def
77     CMap /WMode .knownget { /WMode exch def } if
78     /FontType 0 def
79   pop pop currentdict end /Font defineresource
80 } bind odef
81
82 % ---------------- CMap operators ---------------- %
83
84 40 dict begin
85
86 % Our internal .CodeMapData structure closely mirrors the structures
87 % defined in gxfcmap.h (q.v.).  () indicate a string, [] indicate an array,
88 % ? indicates a Boolean, # indicates an integer, {} for grouping.
89 %       [[[(first) (last) ...]+]                % code space ranges
90 %        [[(prefix) (key_size,?is_range,value_type,value_size) (keys...)
91 %          {(values...) | [value ...]} #font_index ]+]  % code mappings
92 %         ...]
93 %        <<same>>               % notdef mappings
94 %       ]
95 % FontMatrices is the array of matrices defined by begin/endusematrix.
96 % All of the arrays and strings are read-only after they have been built.
97 %
98 % Note that the code in zfcmap.c that constructs the C structures from
99 % the PostScript structures has intimate knowledge of the above format.
100
101 % ****** NOTE: The code currently only handles "well-behaved" CMaps:
102 %       - CID values only (no bfchars), 16-bit
103 %       - Entries (both code space and map) must be sorted
104 %       - Only the last byte must vary in each map range, except for
105 %       the identity mapping
106
107 % ------ Font-level operators ------ %
108
109 /begincmap {            % - begincmap -
110   /.CodeMapData [[[]] [[]] [[]]] def
111   /FontMatrices [] def
112   /.FontIndex 0 def
113   /.TempMaps [20 dict 50 dict 50 dict] def
114   /CodeMap //null def           % for .buildcmap
115 } bind def
116
117 /endcmap {              % - endcmap -
118   .rewriteTempMapsNotDef
119
120   CMAPDEBUG {
121     2 (*** undefined charmap ***)
122     1 (*** defined charmap ***)
123     0 (*** code space ranges ***)
124     3 { =
125       .TempMaps exch get
126       0 1 2 index length 1 sub {
127         dup == (\t) print
128         1 index exch get ==
129       } for
130       pop
131     } repeat
132   } if
133   
134   /.CodeMapData dup load [ exch
135     .TempMaps aload pop begin begin begin 
136     {
137       [ exch aload pop
138         0 1 currentdict length 1 sub { 
139            currentdict exch get 
140         } for 
141       ]
142       end
143     } forall
144   ] .endmap def
145
146   CMAPDEBUG {
147     (*** Content of .CodeMapData ***) =
148     0 .CodeMapData { exch dup == 1 add exch (\t) print == } forall
149     pop
150   } if
151
152   currentdict /.TempMaps undef
153   /FontMatrices FontMatrices .endmap def
154 } bind def
155
156 /.endmap {              % <map> .endmap <map>
157   dup type /arraytype eq {
158         % This might be a shared read-only array inherited via usecmap.
159         % Don't try to update its elements if this is the case.
160     dup wcheck {
161       0 1 2 index length 1 sub {
162         2 copy 2 copy get .endmap put pop
163       } for readonly
164     } if
165   } {
166     dup type /stringtype eq { readonly } if
167   } ifelse
168 } bind def
169
170 /.appendmap {           % -mark- <elt> ... <array#> .appendmap -
171   .TempMaps exch get counttomark 1 add 1 roll
172   ] 1 index length exch put
173 } bind def
174
175 /begincodespacerange {  % <count> begincodespacerange -
176   pop mark
177 } bind def
178
179 /endcodespacerange {    % <code_lo> <code_hi> ... endcodespacerange -
180   0 .appendmap
181 } bind def
182
183 /usecmap {              % <CMap_name> usecmap -
184   /CMap findresource dup
185                 % Copy the top level of .CodeMapData
186   /.CodeMapData exch /.CodeMapData get copyarray def
187   /FontMatrices exch /FontMatrices get copyarray def
188 } bind def
189
190 /usefont {              % <fontID> usefont -
191   /.FontIndex exch def
192 } bind def
193
194 /beginusematrix {       % <fontID> beginusematrix -
195   FontMatrices wcheck not FontMatrices length 2 index le or {
196     FontMatrices length 1 index 1 add .max array
197     dup 0 FontMatrices putinterval
198     /FontMatrices exch def
199   } if
200 } bind def
201
202 /endusematrix {         % <matrix> endusematrix -
203   FontMatrices 3 1 roll put
204 } bind def
205
206 % ------ Rearranged font operators ------ %
207
208 /beginrearrangedfont {  % <font_name> <font*> beginrearrangedfont -
209   10 dict begin
210   /.FontNames exch def
211   /.FontName exch def
212   begincmap
213 } bind def
214 /endrearrangedfont {    % - endrearrangedfont -
215   (REARRANGED FONTS NOT IMPLEMENTED YET.) = flush
216   FontName .FontNames 0 get findfont end definefont pop
217 } bind def
218
219 % ------ Character name/code selector operators ------ %
220
221 /beginbfchar {          % <count> beginbfchar -
222   pop mark
223 } bind def
224 /endbfchar {            % <code> <to_code|charname> ... endbfchar
225   counttomark 2 idiv {
226     counttomark -2 roll         % process in correct order
227     .addbfchar
228   } repeat 1 .appendmap
229 } bind def
230
231 /beginbfrange {         % <count> beginbfrange -
232   pop mark
233 } bind def
234 /endbfrange {           % <code_lo> <code_hi> <to_code|(charname*)> ...
235                         %   endbfrange -
236   counttomark 3 idiv {
237     counttomark -3 roll         % process in correct order
238     dup type dup /arraytype eq exch /packedarraytype eq or {
239                         % Array value, split up.
240       exch pop {
241                         % Stack: code to_code|charname
242         1 index exch .addbfchar
243                         % Increment the code.  As noted above, we require
244                         % that only the last byte vary, but we still must
245                         % mask it after incrementing, in case the last
246                         % value was 0xff.
247                         % Stack: code prefix params key value fontindex
248         6 -1 roll dup length string copy
249         dup dup length 1 sub 2 copy get 1 add 255 and put
250       } forall pop
251     } {
252                         % Single value, handle directly.
253       .addbfrange
254     } ifelse
255   } repeat 1 .appendmap
256 } bind def
257
258 /.addbfchar {           % <code> <to_code|charname> .addbfchar
259                         %   <prefix> <params> <key> <value> <font_index>
260   1 index exch .addbfrange
261 } bind def
262 /.addbfrange {          % <code_lo> <code_hi> <to_code|charname>
263                         %   .addbfrange <<same as .addbfchar>>
264   4 string dup 3
265   3 index type /nametype eq {
266     2 index 2 1 put % dst = CODE_VALUE_GLYPH, see gxfcmap.h .
267     4 -1 roll 1 array astore 4 1 roll 4
268   } {
269     2 index 2 2 put % dst = CODE_VALUE_CHARS, see gxfcmap.h .
270     3 index length
271   } ifelse put
272                         % Stack: code_lo code_hi value params
273   3 index 3 index eq {
274                         % Single value.
275     3 -1 roll pop exch () exch
276   } {
277                         % Range.
278     dup 0 1 put dup 1 1 put
279     4 2 roll
280     dup dup length 1 sub 0 exch getinterval 5 1 roll    % prefix
281                         % Stack: prefix value params code_lo code_hi
282     2 { exch dup length 1 sub 1 getinterval } repeat concatstrings
283     3 -1 roll
284   } ifelse
285   .FontIndex
286 } bind def
287
288 % ------ CID selector operators ------ %
289
290 /begincidchar {         % <count> begincidchar -
291   pop mark
292 } bind def
293 /endcidchar {           % <code> <cid> ... endcidchar -
294   1 .endmapchars
295 } bind def
296
297 /begincidrange {        % <count> begincidrange -
298   pop mark
299 } bind def
300 /endcidrange {          % <code_lo> <code_hi> <cid_base> ... endcidrange -
301   1 .endmapranges
302 } bind def
303
304 /.endmapchars {         % -mark- <code> <cid> ... <map#> .endmapchars -
305   counttomark 1 add 1 roll
306   counttomark 2 idiv {
307     counttomark -2 roll         % process in correct order
308     exch        % <cid> <code>
309                 % Construct prefix, params, key, value, font_index
310     dup length 1 eq {   % 1-byte
311       <00 00 00 02> ()  % <prefix> <param> <null_key>
312     } {                 % N-byte
313       dup 0 1 getinterval exch  % make 1-byte prefix
314       4 string dup 0
315       USE_CIDCHAR_AS_RANGE {
316         <00 01 00 02>   % skelton for param
317       } {
318         <00 00 00 02>   % skelton for param
319       } ifelse
320       putinterval
321       exch              % <prefix> <param> <code>
322       dup length        % <prefix> <param> <code> N
323       1 sub             % <prefix> <param> <code> N-1
324       dup               % <prefix> <param> <code> N-1 N-1
325       3 index           % <prefix> <param> <code> N-1 N-1 <param>
326       exch              % <prefix> <param> <code> N-1 <param> N-1
327       0 exch            % <prefix> <param> <code> N-1 <param> 0 N-1
328       put               % <prefix> <param'> <code> N-1
329       1 exch            % <prefix> <param'> <code> 1 N-1
330       getinterval       % <prefix> <param'> <key>
331
332       USE_CIDCHAR_AS_RANGE {
333         dup length 2 mul string % <key> <dkey>
334         dup                     % <key> <dkey> <dkey>
335         2 index                 % <key> <dkey> <dkey> <key>
336         0 exch putinterval      % <key> <dkey'>
337         dup                     % <key> <dkey'> <dkey'>
338         3 -1 roll               % <dkey'> <dkey'> <key>
339         dup length              % <dkey'> <dkey'> <key> N-1
340         exch putinterval        % <dkey''>
341       } if
342
343     } ifelse
344
345     4 -1 roll           % <prefix> <param'> <key> <cid>
346     .endmapvalue        % <prefix> <param'> <key> <hex_cid> <font_idx>
347     % prefix params keys value fontindex
348     counttomark 5 gt { % 2 (or more) ranges (1 range = 5 item)
349        4 index 10 index eq      % compare prefix
350        4 index 10 index eq and  % compare params
351        1 index 7 index eq and   % compare fontindex
352         {
353           CMAPDEBUG { (merge! char\n) print } if
354           pop 4 2 roll pop pop
355            % prefix params keys value fontindex keys2 value2
356           5 -1 roll 3 -1 roll concatstrings
357            % prefix params value fontindex value2 keys'
358           4 -1 roll 3 -1 roll concatstrings
359            % prefix params fontindex keys' values'
360           3 -1 roll
361         } if
362      } if % end of 2 (or more) ranges
363     CMERGE_DEBUG {
364     ( prefix:) print 4 index =only
365     ( param:) print 3 index =only
366     ( key:) print 2 index =only
367     ( hex_cid:) print 1 index =only
368     ( font_idx:) print 0 index == flush
369     } if
370   } repeat
371   counttomark 2 add -1 roll .appendmap
372 } bind def
373
374 /.endmapranges {        % -mark- <code_lo> <code_hi> <cid_base> ... <map#>
375                         %   .endmapranges -
376   counttomark 1 add 1 roll
377   counttomark 3 idiv {
378     counttomark -3 roll         % process in correct order
379                 % Construct prefix, params, key_lo, key_hi, value, font_index
380     3 1 roll    % <cid_base> <code_lo> <code_hi>
381                 %               prefix  key
382                 % 1-byte code:  ()      .
383                 % 1-byte range: ()      .
384                 % N-byte code:  .       (*)
385                 % N-byte range: (*)     (*)
386     dup 2 index eq {    % <code_lo> == <code_hi>
387                         % 0: prefix_len for 1-byte code
388                         % 1: prefix_len for N-byte code
389        dup length 1 eq { 0 } { 1 } ifelse
390     } {                 % <code_lo> != <code_hi>
391                         % calculate prefix_len for *-byte range
392        dup length 1 sub % <cid_base> <code_lo> <code_hi> <code_len-1>
393        0                % initial value for N
394        {                % <cid_base> <code_lo> <code_hi> (code_len-1)  N
395            dup 2 index ge { exit } if % if (N >= len - 1) exit
396            3 index 1 index get  % N-th byte of code_lo
397            3 index 2 index get  % N-th byte of code_hi
398            eq { 1 add } { exit } ifelse
399        } loop
400        exch pop         % discard <code_len-1>
401     } ifelse
402                                 % cid_base code_lo code_hi prefix_len
403
404     % Althogh Adobe CPSI with native CID/CMap support accept
405     % multi-dimensional range specification in notdef & cidrange
406     % (and CID is calculated as relative position in multi-dimensional
407     % range), but older CPSI & ATM cannot handle it.
408     % 
409     % GS accepts such specification, but it's recommended to keep
410     % from using this feature for notdef & cidrange.
411     % Following is a disabler of this feature.
412     % -------------------------------------------------------------
413     % counttomark 1 add index   % get map#
414     % 0 ne {                    % if not codespacerange
415     %   1 index length          % get code length
416     %   1 index                         % get prefix length
417     %   sub                     % calculate key length
418     %   1 gt {                  % if (key_len > 1),
419     %      (.endmapranges error) = flush
420     %      (multi-dimensional range specification is used out of codespacerange)
421     %      = flush
422     %      (/) =only
423     %      CMapName CMapName length string cvs =only
424     %      (: <) =only
425     %      2 index (%stdout) (w) file exch writehexstring
426     %      (> <) =only
427     %      1 index (%stdout) (w) file exch writehexstring
428     %      (>\n) =only flush
429     %      quit
430     %   } if
431     % } if
432     % -------------------------------------------------------------
433
434     1 index exch 0 exch getinterval
435                                 % cid_base code_lo code_hi prefix
436     dup length 3 index length exch sub
437                                 % cid_base code_lo code_hi prefix range_len
438     dup 255 gt {
439        (too long coderange specification for current GS\n) print
440        signalerror
441     } if
442     <00 01 00 02> 4 string copy % create initialized param
443     dup 0 4 -1 roll put         % put range_len into param
444
445     % get key_hi
446     3 -1 roll dup length 3 index length dup 3 1 roll sub getinterval
447
448     % get key_lo
449     4 -1 roll dup length 4 index length dup 3 1 roll sub getinterval
450
451     % make "keys" (concatenated key_lo + key_hi)
452     exch concatstrings
453
454     % 
455     4 -1 roll
456     .endmapvalue
457
458                 % See if we can merge with the previous value.
459                 % The prefix, params, and font index must match.
460     % prefix params keys value fontindex
461     counttomark 5 gt { % 2 (or more) ranges (1 range = 5 item)
462        4 index 10 index eq      % compare prefix
463        4 index 10 index eq and  % compare params
464        1 index 7 index eq and   % compare fontindex
465         {
466           CMAPDEBUG { (merge!\n) print } if
467           pop 4 2 roll pop pop
468            % prefix params keys value fontindex keys2 value2
469           5 -1 roll 3 -1 roll concatstrings
470            % prefix params value fontindex value2 keys'
471           4 -1 roll 3 -1 roll concatstrings
472            % prefix params fontindex keys' values'
473           3 -1 roll
474         } if
475      } if % end of 2 (or more) ranges
476   } repeat
477   counttomark 2 add -1 roll .appendmap
478 } bind def
479
480 /.endmapvalue {         % <cid> .endmapvalue (hi,lo) .FontIndex
481   2 string dup 0 3 index -8 bitshift put        % value
482   dup 1 4 -1 roll 255 and put
483   .FontIndex            % font_index
484 } bind def
485
486 % ------ notdef operators ------ %
487
488 /beginnotdefchar {      % <count> beginnotdefchar -
489   pop mark
490 } bind def
491 /endnotdefchar {        % <code> <cid> ... endnotdefchar -
492   2 .endmapchars
493 } bind def
494
495 /beginnotdefrange {     % <count> beginnotdefrange -
496   pop mark
497 } bind def
498 /endnotdefrange {       % <code_lo> <code_hi> <cid> ... endnotdefrange -
499   2 .endmapranges
500 } bind def
501
502 % ---------------- Resource category definition ---------------- %
503
504 currentdict end
505
506 languagelevel exch 2 .setlanguagelevel
507
508 /CMap /Generic /Category findresource dup length dict .copydict
509 dup /InstanceType /dicttype put
510 dup /DefineResource {
511                 % The AdobePS5 Windows driver emits code that attempts to
512                 % create CMaps without the required CMapName entry.
513                 % Work around this here.
514   dup /CMapName known not {
515     dup wcheck not {
516       .currentglobal exch dup wcheck .setglobal
517       dup length dict .copydict exch .setglobal
518     } if
519     dup gcheck 2 index gcheck not and {
520       exch .currentglobal exch //true .setglobal
521       dup length string copy exch .setglobal exch
522     } if dup /CMapName 3 index put
523   } if
524   dup /CodeMap get //null eq { .buildcmap } if
525   /Generic /Category findresource /DefineResource get exec
526 } put
527 /Category defineresource pop
528         % We might have loaded CID font support already.
529 /CIDInit /ProcSet 2 copy { findresource } .internalstopped
530         % An interior `stopped' might have reset VM allocation to local.
531 //true .setglobal
532  { pop pop 3 -1 roll }
533  { dup length 4 index length add dict .copydict 4 -1 roll exch .copydict }
534 ifelse exch defineresource pop
535
536 .setlanguagelevel