Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
 
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
 
124
    3 { =
125
      .TempMaps exch get
126
 
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
 
139
           currentdict exch get 
140
        } for 
141
      ]
142
      end
143
    } forall
144
  ] .endmap def
145
 
146
  CMAPDEBUG {
147
    (*** Content of .CodeMapData ***) =
148
 
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
 
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
 
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
 
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
 
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
 
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