[Gs-devel] font map format design problem

mpsuzuki at hiroshima-u.ac.jp mpsuzuki at hiroshima-u.ac.jp
Fri Nov 16 09:15:28 PST 2001


Dear Mr. Melichev,

As a sample material for discussion, I attached CIDFnmap
patch against HEAD at sourceforge cvs. I didn't remove
support for TTF/TTC, so undefined ".loadcjkvttcidfont"
procedure (which is defined in gs_ttf.ps of jumbo patch)
is included.

>So now there are alternatives for CIDFnmap/HEAD :
>
>1. Use 3 different formats for native fonts, for FAPI fonts,
>   and for CID fonts;
>2. Unify native fonts and CID fonts like gs-cjk did.
>   Not sure that will not cause problems in future,
>   if more attributes appear.
>3. Unify CIDFnmap and FAPI map as shown above;
>   This is pretty flexible thing, rather few more typing.
>4. Develop an unified language for all 3 things,
>   so as the old fontmap language is a subset of it.
>   Perhaps no time for this now.
>
>I would prefer to go with (3) and switch from it to (4)
>when a necessity appears.
>At least this doesn't require a special parser for now,
>and enough flexible for future.

Also I think (3) is best. In fact, using dictionary object
as fontmap for CID-keyed font was discussed in gs-cjk (but,
gs-cjk choosed simularity to Fontmap syntax).

Regards,

mpsuzuki


diff -PNu gs/lib/gs_init.ps gs-cjk/lib/gs_init.ps
--- gs/lib/gs_init.ps	Sat Nov 10 20:32:59 2001
+++ gs-cjk/lib/gs_init.ps	Sat Nov 17 01:32:06 2001
@@ -116,6 +116,7 @@
 currentdict /NOCIE known   /NOCIE exch def
 currentdict /NODISPLAY known   not /DISPLAYING exch def
 currentdict /NOFONTMAP known   /NOFONTMAP exch def
+currentdict /NOCIDFONTMAP known /NOCIDFONTMAP exch def
 currentdict /NOFONTPATH known   /NOFONTPATH exch def
 currentdict /NOGC known   /NOGC exch def
 currentdict /NOINTERPOLATE .knownget { /INTERPOLATE exch not def } if
diff -PNu gs/lib/gs_cidcm.ps gs-cjk/lib/gs_cidcm.ps
--- gs/lib/gs_cidcm.ps	Sat Nov 10 20:32:58 2001
+++ gs-cjk/lib/gs_cidcm.ps	Sat Nov 17 01:32:03 2001
@@ -163,7 +163,21 @@
         { (r) file                            % CSIs /InstName g [ file
           //GetCIDSystemInfoFromFile exec     % CSIs /InstName g [ CSI
         } stopped {
-          cleartomark //.prs_empty             
+	  % Cannot find file from Resource directory
+          cleartomark
+	  % Try to find file from CIDFontmap
+	  % Stack: CSIs /InstName g
+	  1 index dup .CIDFontmapKnownget {
+	      % Stack: CSIs /InstName g /InstName ValueInCIDFontmap
+	      % We do look at CIDFontmap in global space.
+	      % (When stopped, the space is set to local.)
+	      true setglobal
+	      1 index 3 1 roll
+	      .CIDFontmapRunHandler
+	      /CIDFont findresource /CIDSystemInfo get
+	  } {
+	      pop //.prs_empty             
+	  } ifelse
         } {
           exch pop
         } ifelse                              % CSIs /InstName g CSI
diff -PNu gs/lib/gs_cidfn.ps gs-cjk/lib/gs_cidfn.ps
--- gs/lib/gs_cidfn.ps	Sat Nov 10 20:32:58 2001
+++ gs-cjk/lib/gs_cidfn.ps	Sat Nov 17 01:32:03 2001
@@ -337,26 +337,333 @@
   dup /CIDFontType get //.cidfonttypes exch get exec
 } odef
 
+/.loadcidfontwithoutpop {
+    dup 4 string .peekstring pop dup (ttcf) eq exch (\000\001\000\000) eq or {
+    .loadcjkvttcidfont
+  } {
+    /CIDFont /Category findresource /.Instances get
+    dup length 2 div cvi dict .copydict exch
+    .loadfont
+    % Stack: <<original-.Instances>>
+    /CIDFont /Category findresource /.Instances get {% forall
+	% <<original-.Instances>> key value
+	2 index 2 index known {
+	    pop pop
+	} {
+	    pop exch pop /CIDFont findresource exit
+	} ifelse
+    } forall
+    dup /CIDFontName known not {
+	{Internal Error in .loadcidfontwithoutpop} stop
+    } if
+  } ifelse
+} bind def
+
+/.loadcidfont {
+  .loadcidfontwithoutpop pop
+} bind def
+
+% Define the name of the CID font map file.
+/defaultcidfontmap (CIDFnmap) def
+userdict /CIDFontmap 10 dict put
+
+% <dict> <file> .readCIDFontmap <dict>
+% Code from gs_fonts.ps::.readFontmap
+/.readCIDFontmap {
+    { dup token not { closefile exit } if
+      % This is a hack to get around the absurd habit of MS-DOS editors
+      % of adding an EOF character at the end of the file.
+      dup (\032) eq { pop closefile exit } if
+      1 index token not
+       { (CIDFontmap entry for ) print dup =only
+	 ( has no associated file or alias name!  Giving up.) = flush
+	 {.readCIDFontmap} 0 get 1 .quit
+       } if
+      dup type dup /stringtype eq exch /nametype eq or not
+       { (CIDFontmap entry for ) print 1 index =only
+	 ( has an invalid file or alias name!  Giving up.) = flush
+	 {.readCIDFontmap} 0 get 1 .quit
+       } if
+		% stack: dict file cidfontname filename|aliasname
+      1 index type /stringtype eq
+      1 index type /nametype eq and 1 index xcheck and
+      1 index /run eq 2 index /.runlibfile eq or and {
+		% This is an inclusion entry.
+	pop findlibfile { exch pop } { file } ifelse
+	2 index exch .readCIDFontmap pop
+      } {
+		% This is a real entry.
+		% stack: dict file cidfontname filename|aliasname
+
+		% Before staring a game, we need a hack.
+		% Some CJK pdf file contains a cidfontname that cannot 
+		% be represented as a nametype literal. Instead, the
+		% cidfontname is represented as a string literal.
+		% If a cidfontname is represented as a stringtype object,
+		% it must be converted to a nametype object. 
+		% We handle such a case here.
+	exch dup type /stringtype eq {cvn} if exch
+
+	        % stack: dict file cidfontname filename|aliasname
+		% Read and pop tokens until a semicolon.
+       { 2 index token not
+	  { (CIDFontmap entry for ) print 1 index =only
+	    ( ends prematurely!  Giving up.) = flush
+	    {.readCIDFontmap} 0 get 1 .quit
+	  } if
+	 dup /; eq { pop 3 index 3 1 roll .growput exit } if
+	 % Format:
+	 %   /CIDFontname (file) ttc-index ;
+	 %   /CIDFontname (file) /Code->CID-dict ;
+	 %   /CIDFontname (file) ttc-index /Code->CID-dict ;
+	 %
+	 % e.g.
+	 %   /HG-MinchoL     (hgminchol.ttc) 1 /Adobe-Japan1-Unicode ;
+	 %   /HG-PMinchoL    (hgminchol.ttc) 2 /Adobe-Japan1-Unicode ;
+	 %   /HG-MinchoL-J2  (hgminchol.ttc) 1 /Adobe-Japan2-Unicode ;
+	 %   /HG-PGothicB    (hggothicb.ttc) 2 ;
+	 %   /HG-GothicB-J2  (hggothicb.ttc) /Adobe-Japan2-Unicode ;
+	 % 
+	 % CID Fontmap entry is stored into CIDFontmap dict as an array.
+	 % Array format:
+	 %   [filename ttc-index]
+	 %   [filename /Code->CID-dict]
+	 %   [filename ttc-index /Code->CID-dict]
+	 %
+	 % Type: 
+	 %   filename: string
+	 %   ttc-index: integer
+	 %   /Code->CID-dict: name
+	 %
+	 % stack: dict file cidfontname filename something
+	 1 index type /nametype eq {
+	   (CIDFontmap entry for ) print 2 index =only
+	   (defines an alias! Giving up.) = flush
+	   {.readCIDFontmap} 0 get 1 .quit
+	 } if
+	 % stack: dict file cidfontname filename something
+	 exch [ exch 3 -1 roll
+	 % stack: dict file cidfontname [ filename something 
+	 dup type /integertype eq {
+	   % stack: dict file cidfontname [ filename int
+	   % Read next token
+	   4 index token not
+	   { (CIDFontmap entry for ) print 3 index =only
+	     ( ends prematurely!  Giving up.) = flush
+	     {.readCIDFontmap} 0 get 1 .quit
+	   } if
+	 } if
+	 % stack: dict file cidfontname [ filename int something
+	 % or     dict file cidfontname [ filename something
+	 dup /; eq not 1 index type /nametype eq and {
+	   % stack: dict file cidfontname [ filename  /Code->CID
+	   % or     dict file cidfontname [ filename  int /Code->CID
+	   % Read next token
+	   counttomark 2 eq {4} {5} ifelse index token not
+	   { (CIDFontmap entry for ) print
+	     counttomark 2 eq {3} {4} ifelse index =only
+	     ( ends prematurely!  Giving up.) = flush
+	     {.readCIDFontmap} 0 get 1 .quit
+	   } if
+	 } if
+	 % stack: dict file cidfontname [ filename int /Code->CID something
+	 % or     dict file cidfontname [ filename /Code->CID something
+	 dup /; eq {
+	     pop ]
+	     3 index 3 1 roll .growput exit
+	 } if
+	 pop
+       } loop
+      } ifelse
+    } loop
+} bind def
+
+% <file> .loadCIDFontmap -
+/.loadCIDFontmap {
+    userdict /CIDFontmap get exch
+    .readCIDFontmap pop
+} bind def
+
+% Code from .loadinitialfonts
+/.loadinitialcidfonts
+ { NOCIDFONTMAP not
+    { /CIDFONTMAP where
+	  { pop [ CIDFONTMAP .pathlist ]
+	     { dup VMDEBUG findlibfile
+		{ exch pop .loadCIDFontmap }
+		{ /undefinedfilename signalerror }
+	       ifelse
+	     }
+	  }
+	  { LIBPATH
+	     { defaultcidfontmap 2 copy .filenamedirseparator
+	       exch concatstrings concatstrings dup VMDEBUG
+	       (r) { file } .internalstopped
+		{ pop pop } { .loadCIDFontmap } ifelse
+	     }
+	  }
+	 ifelse forall
+    }
+   if
+   %%% Do nothing
+ } bind def
+.loadinitialcidfonts
+
+/CIDFontmapHandler <<
+  /nametype {
+    /CIDFont findresource
+    /CIDFont defineresource pop
+  } bind
+  /stringtype {
+    findlibfile {
+      exch pop
+      % Define CIDFont with a name defined in the font file
+      .loadcidfontwithoutpop
+      % Define CIDFont with a name define in CIDFontmap
+      dup length 0 ne {
+	  dup /CIDFontName get 2 index eq {
+	      % Avoid duplicated defineresource for the same CIDFont
+	      pop pop
+	  } {
+	      % Give a name different from the name defined in the file
+	      /CIDFont defineresource pop
+	  } ifelse
+      } {
+	  pop pop
+      } ifelse
+    } {
+      /undefinedresource signalerror
+    } ifelse
+  } bind
+  /arraytype {
+  % Replace filename in the array with file
+      dup 0 get
+      findlibfile {
+	  3 1 roll pop
+	  copyarray dup 3 1 roll 0
+	  3 -1 roll put
+	  % Expand array
+	  aload pop .loadcjkvttcidfont
+	  /CIDFont defineresource pop
+      } {
+	  /undefinedresource signalerror
+      } ifelse
+  } bind
+>> def
+
+%%% CIDFontmap Public Interface
+% /CIDFontName .CIDFontmapKnown true|false
+/.CIDFontmapKnown {
+    userdict /CIDFontmap get exch known
+} bind def
+
+% /CIDFontName .CIDFontmapKnownget value true
+% /CIDFontName .CIDFontmapKnownget false
+/.CIDFontmapKnownget {
+    userdict /CIDFontmap get exch .knownget
+} bind def
+
+% /CIDFontName value .CIDFontmapRunHandler -
+/.CIDFontmapRunHandler {
+    dup CIDFontmapHandler exch type get .execasresource
+} bind def
+
+% proc .CIDFontmapForAll -
+/.CIDFontmapForAll {
+    CIDFontmap exch forall
+} bind def
+
+% proc .CIDFontmapForAllKey -
+/.CIDFontmapForAllKey {
+    [ /pop cvx 3 -1 roll /exec cvx ] cvx .CIDFontmapForAll
+} bind def
+
 /CIDFont /Generic /Category findresource dup length dict .copydict
 dup /InstanceType /dicttype put
 dup /DefineResource {
   .buildcidfont
   /Generic /Category findresource /DefineResource get exec
 } put
+/.originalresourceforall 1 index /ResourceForAll get def
+dup /ResourceForAll {
+    currentglobal false setglobal
+    % (template) (proc) (scratch) g
+    [           % (template) (proc) (scratch) g [
+	%
+	% 1. Gather CIDFont name in /Resource/CIDFont
+	%
+	4 index % (template) (proc) (scratch) g [ (template)
+	{cvn}      % (template) (proc) (scratch) g [ (template) {cvn}
+	4 index % (template) (proc) (scratch) g    [ (template) {cvn} (scratch)
+	.originalresourceforall
+	% (template) (proc) (scratch) g [ ...
+	%
+	% 2. Gather CIDFont name in CIDFontmap
+	%
+	{
+	    dup length string cvs
+	    dup     % (template) (proc) (scratch) g [ ... (Key) (Key)
+	    counttomark 4 add index
+	    % (template) (proc) (scratch) g [ ... (Key) (Key) (template)
+	    .stringmatch {
+		cvn
+		% (template) (proc) (scratch) g [ ... /Key
+		% 3. Remove duplicated /Key
+		counttomark -1 1  {
+		    index 1 index eq {
+			pop exit % Duplicated
+		    } if
+		} for
+	    } {
+		pop
+	    } ifelse
+	} .CIDFontmapForAllKey
+    ]
+    exch setglobal
+    %
+    % 4. Build extended procedure
+    %
+    % (template) (proc) (scratch) [CIDFontmapKeys]
+    4 -1 roll pop
+    % (proc) (scratch) [CIDFontmapKeys]
+    3 1 roll
+    % [CIDFontmapKeys] (proc) (scratch)
+    [ exch {cvs} aload pop
+    % [CIDFontmapKeys] (proc) [ (scratch) -cvs-
+    4 -1 roll aload pop ] cvx
+    % [CIDFontmapKeys] proc++
+    %
+    % 5. Exec
+    %
+    forall
+} put
+
 % CIDFonts may be defined in CFF OpenType files.
 % Check for this here.
 /.loadcidfontresource {
   dup .ResourceFile {
-    {.loadfont} .execasresource
+    {.loadcidfont} .execasresource
+  } {
+    pop dup
+    .CIDFontmapKnownget {
+      .CIDFontmapRunHandler
   } {
     dup /undefinedresource signalerror
   } ifelse
+  } ifelse
 } bind def
 dup /.LoadResource {
   currentglobal {
     .loadcidfontresource
   } {
     true setglobal {.loadcidfontresource} stopped false setglobal {stop} if
+  } ifelse
+} bind put
+dup /.ResourceFileStatus {
+    dup .CIDFontmapKnown {
+    pop 2 -1 true
+  } {
+    .ResourceFile { closefile 2 -1 true } { pop false } ifelse
   } ifelse
 } bind put
 




More information about the gs-devel mailing list