]> git.lizzy.rs Git - plan9front.git/blob - sys/lib/ghostscript/gs_cidcm.ps
update colemak kbmap, simpler version with scroll working (thanks jeremy)
[plan9front.git] / sys / lib / ghostscript / gs_cidcm.ps
1 %    Copyright (C) 2000 artofcode LLC.  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_cidcm.ps,v 1.12 2004/10/25 15:11:37 igor Exp $
17 % Extending Font resource category with CIDFont-CMap fonts.
18
19 languagelevel 2 .setlanguagelevel currentglobal true setglobal
20
21
22 % In the comments below, 'CSI' is an abbreviation/acronym for CIDSystemInfo.
23 % We pre-scan resource files to retrieve the CSI from them.
24 % First we define a hidden procset .prs_dict containing
25 % necessary variables and procedures.
26 % Then we redefine the old /Font category using this procset.
27
28 % We maintain internal caches for the CSI values retrieved from
29 % resource files. This supposes that document doesn't uninstall
30 % resource files. To disable caching, set enable_cache to false.
31
32 % We assume that names starting with '.prs' do not appear in resource files.
33 % If this causes any problem, this prefix should be systematically changed
34 % in this file.  ('prs' is an abbreviation for 'prescan'.)
35
36 25 dict begin
37
38 % Define local variables :
39
40 /.prs_dict currentdict def       % self-reference (constant)
41 /.prs_empty 0 dict readonly def  
42 /path_buffer 8192 string def
43 /name_buffer 1024 string def
44 /minus (-) 0 get def             % character code constant for '-'
45 /period (.) 0 get def            % character code constant for '.'
46 /CMap 10 dict def                % CSI cache for CMaps
47 /CIDFont 10 dict def             % CSI cache for CIDFonts
48 /enable_cache true def           % set false to disable cache
49
50 % The folloving variables are just placeholders for ones to be set
51 % dynamically :
52 /.prsFile 0 def                   % file to prescan
53 /.prsResult 0 def                 % result of prescan
54 /.prsDictCount 0 def              % save the dictionary stack depth
55
56 % Define a dummy CIDInit procset to use while pre-scanning :
57
58 /DummyCIDInit 15 dict 
59 begin
60
61   /begincmap {} def
62   /usecmap {pop} bind def
63
64   {stop} bind
65   [ /begincodespacerange /endcodespacerange /beginnotdefchar /endnotdefchar
66     /beginnotdefrange /endnotdefrange /begincidchar /endcidchar /begincidrange 
67     /endcidrange /endcmap /usefont /StartData
68   ] {
69     1 index def
70   } bind forall
71   pop
72
73 currentdict end def
74
75 % Define a local 'findresource' for pre-scanning :
76 % (it returns the dummy CIDInit instead of the regular CIDInit ProcSet)
77
78 /findresource { % <InstName> <CatName> findresource <inst>
79   2 copy /ProcSet eq exch             % /InstName /CatName bool /InstName
80   /CIDInit eq and {
81     pop pop //DummyCIDInit
82   } {
83     //findresource exec
84   } ifelse
85 } bind def
86
87 % Define procedures for pre-scanning :
88
89 /StopIfCSIDefined {   % - StopIfCSIDefined -
90   
91   % Check if the dictionary stack contains a dictionary containing /CIDSystemInfo. 
92   % The search is limited to the top .prsDictCount dictionaries in the stack.
93   % If so, retrieve the CSI, and execute stop to terminate the pre-scanning of the file.
94   % Otherwise, do nothing, so the pre-scanning continues.
95
96   countdictstack //.prs_dict /.prsDictCount get sub dup {
97     currentdict /CIDSystemInfo .knownget {
98       //.prs_dict exch /.prsResult exch put
99       stop
100     } if
101     currentdict exch end
102   } repeat {
103     begin
104   } repeat
105 } bind def
106
107 /PrescanFile {     % - PrescanFile -
108   { //.prs_dict /.prsFile get token {      
109       dup type                          % token type
110       dup /nametype eq exch /operatortype eq or {
111         dup xcheck {
112           exec
113           //StopIfCSIDefined exec
114         } if
115       } if
116     } {
117       stop
118     } ifelse
119   } loop
120 } bind odef
121
122 /GetCIDSystemInfoFromFile { % <file> GetCIDSystemInfoFromFile <CSI>
123   
124   % This procedure reads resource files with 'token',
125   % executing the tokens untill /CIDSystemInfo appears to be defined.
126   % Normally the resource file creates a new dictionary on
127   % dictionary stack and defines /CIDSystemInfo in it.
128   %
129   % Returns an empty dictionary if no CIDSystemInfo is found.
130
131   RESMPDEBUG { (cidcm GetCIDSystemInfoFromFile beg) = } if
132   //.prs_dict begin
133   /.prsFile exch def
134   /.prsResult //.prs_empty def
135   /.prsDictCount countdictstack def
136   RESMPDEBUG { (cidcm GetCIDSystemInfoFromFile will PrescanFile.) = } if
137   { //PrescanFile } stopped pop
138   //.prs_dict /.prsResult get
139   end
140   RESMPDEBUG { (cidcm GetCIDSystemInfoFromFile end) = } if
141 } bind def
142
143 /GetCIDSystemInfo {     % <InstName> <CatName> GetCIDSystemInfo <CSI>
144   
145   % Retrieve CSI, using caches.
146
147   RESMPDEBUG { (cidcm GetCIDSystemInfo beg) = } if
148   /Category findresource begin                % /InstName
149   dup ResourceStatus 
150   {
151     pop 2 lt {
152       FindResource /CIDSystemInfo .knownget not {
153         //.prs_empty
154       } if                                    % CSI
155     } {                                       % /InstName
156       currentdict /GetCIDSystemInfoFromMap .knownget {
157         exec
158       } if
159       dup type /nametype eq
160       {
161         RESMPDEBUG { (cidcm GetCIDSystemInfo got a name.) = } if
162         //.prs_dict Category get              % /InstName CSIs
163         dup 2 index known
164         //enable_cache and {
165           RESMPDEBUG { (cidcm GetCIDSystemInfo from cache.) = } if
166           exch get                            % CSI
167         } {
168           RESMPDEBUG { (cidcm GetCIDSystemInfo from file.) = } if
169           exch                                % CSIs /InstName
170           dup //path_buffer ResourceFileName  % CSIs /InstName (path)
171           RESMPDEBUG { (cidcm GetCIDSystemInfo from file ) print dup = } if
172           currentglobal exch true setglobal   % CSIs /InstName g (path)
173           mark exch                           % CSIs /InstName g [ (path)
174           { (r) file                          % CSIs /InstName g [ file
175             //GetCIDSystemInfoFromFile exec   % CSIs /InstName g [ CSI
176           } stopped {
177             cleartomark //.prs_empty             
178           } {
179             exch pop
180           } ifelse                            % CSIs /InstName g CSI
181           exch setglobal                      % CSIs /InstName CSI
182           dup 4 1 roll                        % CSI CSIs /InstName CSI
183           put                                 % CSI
184           RESMPDEBUG {
185             (cidcm GetCIDSystemInfo got from file : <<) print
186             dup { exch //=string cvs print ( ) print
187                        //=string cvs print ( ) print
188             } forall
189             (>>) =
190           } if
191         } ifelse
192       } if
193     } ifelse
194   } {
195     pop //.prs_empty
196   } ifelse
197   end
198   RESMPDEBUG { (cidcm GetCIDSystemInfo end) = } if
199 } bind def
200
201 /IsCompatibleCSI {  % <CSI-M> <CSI-F> IsCompatibleCSI <bool>
202   
203   % The CSI in a CIDFont may be an array, a dict, or null.
204   % If it is an array, it must be of 1 element, which is a dict.
205   % In this case the dict is used for testing the compatibility.
206   % Two dicts are compatible iff they contain same /Ordering and /Registry.
207
208   exch                                  % CSI-F CSI-M
209   { dup type /arraytype eq {
210       dup length 1 ne {
211         pop pop false exit
212       } if
213       0 get
214     } if                                % CSI-F CSI-M
215     dup type /dicttype ne {
216       pop pop false exit
217     } if                                % CSI-F <<CSI-M>>
218     exch                                % <<CSI-M>> CSI-F
219     dup type /dicttype ne {
220       pop pop false exit
221     } if                                % <<CSI-M>> <<CSI-F>>
222     true                                % <<CSI-M>> <<CSI-F>> bEQ
223     [/Registry /Ordering] {                    
224       2 index 1 index .knownget not {
225         1234567
226       } if                              % <<CSI-M>> <<CSI-F>> bEQ /key vF
227       exch                              % <<CSI-M>> <<CSI-F>> bEQ vF /key
228       4 index exch .knownget not {
229         7654321
230       } if                              % <<CSI-M>> <<CSI-F>> bEQ vF vM
231       eq and                            % <<CSI-M>> <<CSI-F>> bEQ
232     } forall
233     exch pop exch pop                   % bEQ
234     exit
235   } loop
236 } bind def
237
238 /IsWellComposed {     % <CIDFontName> <CMapName> IsWellComposed <bool>
239   
240   % Check if the given CIDFont and CMap have compatible CSIs.
241   exch                                  % /CMapName /CIDFontName
242   /CIDFont //GetCIDSystemInfo exec      % /CMapName CSI-F
243   dup type /dicttype eq {
244     dup length 0 ne {                          
245       exch                              % CSI-F /CMapName
246       /CMap //GetCIDSystemInfo exec     % CSI-F CSI-M
247       //IsCompatibleCSI exec            % bool
248     } {
249       pop pop false
250     } ifelse
251   } {
252     pop pop false
253   } ifelse
254 } bind def
255
256 /IsComposedFont {   % <FontName> IsComposedFont <CIDFontName> <CMapName> true
257                     % <FontName> IsComposedFont false
258   
259   % Check if the given font name may be decomposed into CIDFont.CMap, CIDFont-CMap
260   % or into CIDFont--CMap, such that CIDFont and CMap have compatible CSIs.
261                                         % FontName
262   dup type /stringtype ne {
263     //name_buffer cvs
264   } if                                  % (FontName)
265   { dup length 2 sub -1 1 {
266                                         % (FontName) i
267       2 copy get dup //minus eq exch //period eq or {                
268         2 copy 2 copy                   % (FontName) i (FontName) i (FontName) i
269         2 copy get //minus eq {
270           2 copy 1 sub get //minus eq {
271             1 sub
272           } if
273         } if                            % (FontName) i (FontName) i (FontName) i0
274         0 exch getinterval cvn          % (FontName) i (FontName) i /CIDFontName
275         3 1 roll                        % (FontName) i /CIDFontName (FontName) i
276         1 add dup                       % (FontName) i /CIDFontName (FontName) i1 i1
277         5 index length                  % (FontName) i /CIDFontName (FontName) i1 i1 l
278         exch sub getinterval cvn        % (FontName) i /CIDFontName /CMapName
279         2 copy //IsWellComposed exec {  % (FontName) i /CIDFontName /CMapName 
280           4 2 roll pop pop              % /CIDFontName /CMapName
281           stop
282         } if
283         pop pop pop
284       } {
285         pop
286       } ifelse                          % (FontName)
287     } for
288     pop
289   } stopped
290 } bind def
291
292 /ComposeName { % <CIDFont> <CMap> <scr> ComposeName <CIDFont-CMap>
293   dup dup 5 2 roll                        % (scr) (scr) /CIDFont /CMap (scr)
294   3 2 roll exch cvs length dup            % (scr) (scr) /CMap l0 l0
295   4 -1 roll exch //minus put              % (scr) /CMap l0
296   1 add dup                               % (scr) /CMap l1 l1
297   3 index dup length                      % (scr) /CMap l1 l1 (scr) L
298   2 index sub                             % (scr) /CMap l1 l1 (scr) LT
299   3 2 roll                                % (scr) /CMap l1 (scr) LT l1
300   exch getinterval                        % (scr) /CMap l1 (scrT)
301   3 2 roll exch cvs length                % (scr) l1 l2
302   add 0 exch getinterval                  % (CIDFont-CMap)
303 } bind def
304
305 % Redefine the /Font category with CIDFont-CMap construction :
306
307 % The following code supposes that the following names are not
308 % defined in the old /Font category dictionary :
309 % /IsComposedFont, /IsWellComposed .
310
311
312 /Font /Category findresource dup length dict copy begin
313
314 /FindResource {  % <InstName> FindResource <inst>
315   dup //ResourceStatus exec {
316     pop pop //FindResource exec
317   } {                                                
318     dup //IsComposedFont exec {          % /FontName /CIDFontName /CMapName 
319       exch [ exch ] composefont          % inst
320     } {
321       //FindResource exec
322     } ifelse
323   } ifelse
324 } bind def
325
326 /ResourceStatus {  % <InstName> ResourceStatus <nStatus> <nSize> true
327                    % <InstName> ResourceStatus false
328   dup //ResourceStatus exec {                    
329     3 2 roll pop true                     % nStatus nSize true
330   } {
331     //IsComposedFont exec {               % /CIDFontName /CMapName 
332       /CMap resourcestatus {              % /CIDFontName nStatusM nSizeM 
333         exch pop exch                     % nSizeM /CIDFontName 
334         /CIDFont resourcestatus {         % nSizeM nStatusF nSizeF 
335           exch pop                        % nSizeF nSizeM
336           dup 0 ge {
337             exch dup 0 ge {
338               add
339             } {
340               exch pop
341             } ifelse
342           } {
343             pop
344           } ifelse                        % nSize
345           2 exch true                     % nStatus nSize true
346         } {                        
347           pop pop pop false  % work around buggy resource file
348         } ifelse
349       } {                            
350         pop pop pop false    % work around buggy resource file
351       } ifelse
352     } {
353       false
354     } ifelse
355   } ifelse
356 } bind def
357
358 /ResourceForAll { % <template> <proc> <scratch> ResourceForAll - 
359
360   % We suppose that the resourceforall procedure does not 
361   % define or install new fonts, CMaps, and/or CIDFonts.
362
363   % First we create 3 temporary dictionaries to store temporary data
364   % about fonts, CMaps and CIDFonts.
365   % These dictionaries must be created dynamically, to allow for a possible 
366   % recursive call to resourceforall from the resourceforall procedure.
367   currentglobal false setglobal
368   20 dict 20 dict 20 dict
369
370   4 -1 roll setglobal                     % (templ) proc (scr) <<CIDFont>> <<CMap>> <<Fonts>>
371
372   % Store resource identifiers into local dictionaries
373   % A resource instance can have a key that is not a name or a string. In this
374   % case, resourceforall passes the key directly to proc instead of copying it
375   % into the scratch string. This case can arise only for a resource instance
376   % defined in virtual memory by a previous defineresource
377
378   % Discard non-string keys of CIDFont and CMap because <CIDFontName>- -<CMapName>
379   % is only defined for names.
380
381   { /.DisableResourceOrdering pop % gs_resmp accesses this through execstack - don't remove !
382
383     5 index [ 2 index {exch //null put} aload pop ] cvx bind 5 index //ResourceForAll exec
384
385     (*) [ 3 index {exch dup type /stringtype eq { cvn dup put } { pop pop } ifelse } aload pop
386         ] cvx bind 5 index /CMap resourceforall
387
388     (*) [ 4 index {exch dup type /stringtype eq { cvn dup put } { pop pop } ifelse } aload pop
389         ] cvx bind 5 index /CIDFont resourceforall
390
391     exit
392   } loop % This loop is a pattern for execstack_lookup - don't remove !
393
394   %% Make the list of fonts in the form (/Name status) :
395
396                                           % (templ) proc (scr) <<CIDFont>> <<CMap>> <<Fonts>>
397   dup {                                              
398     pop dup
399     //ResourceStatus exec {                        
400       pop 2 index                         % (templ) proc (scr) <<CIDFont>> <<CMap>> <<Fonts>> /Name nStatus <<Font>>
401       3 1 roll put                        % (templ) proc (scr) <<CIDFont>> <<CMap>> <<Fonts>>
402     } {
403       pop
404     } ifelse
405   } forall                                % (templ) proc (scr) <<CIDFont>> <<CMap>> <<Fonts>>
406  
407   %% Add CIDFont-CMap to it (filtering duplicates) :
408  
409   3 2 roll  {                                        
410     3 index {                                        
411       3 1 roll                            % (templ) proc (scr) <<CMap>> <<Font>> /CIDFont /CMap /CIDFont /CMap
412       6 index //ComposeName exec          % (templ) proc (scr) <<CMap>> <<Font>> /CIDFont /CMap (Font)
413       dup 8 index .stringmatch {              
414         cvn                               % (templ) proc (scr) <<CMap>> <<Font>> /CIDFont /CMap /Font
415         dup 4 index exch known {
416           pop pop
417         } {                                            
418           2 index                         % (templ) proc (scr) <<CMap>> <<Font>> /CIDFont /CMap /Font /CIDFont
419           4 2 roll                        % (templ) proc (scr) <<CMap>> <<Font>> /Font /CIDFont /CIDFont /CMap
420           //IsWellComposed exec {                
421             exch 2 index exch 2 put       % (templ) proc (scr) <<CMap>> <<Font>> /CIDFont
422           } {
423             exch pop
424           } ifelse
425         } ifelse
426       } {
427         pop pop
428       } ifelse
429       dup                                 % (templ) proc (scr) <<CMap>> <<Font>> /CIDFont /CIDFont
430     } forall
431     pop pop                               % (templ) proc (scr) <<CMap>> <<Font>>
432   } forall                                % (templ) proc (scr) <<CMap>> <<Font>>
433   exch pop                                % (templ) proc (scr) <<Font>>
434   4 3 roll pop                            % proc (scr) <<Font>>
435
436   % Make the enumerator and apply it :
437   /MappedCategoryRedefiner /ProcSet findresource /MakeResourceEnumerator get exec exec
438
439 } bind def
440
441
442 currentdict end /Font exch /Category defineresource pop
443 end
444 setglobal .setlanguagelevel