% Copyright (C) 2001-2023 Artifex Software, Inc.
% 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.
%
% Refer to licensing information at http://www.artifex.com or contact
% Artifex Software, Inc.,  39 Mesa Street, Suite 108A, San Francisco,
% CA 94129, USA, for further information.

% $Id: GenSubstCID.ps 8648 2008-04-19 04:49:20Z alexcher

% Usage: gs -- Usage: gs -- toolbin/GenSubstCID.ps
% Generate a SubstCID resource for WMode substitution from vertical CMap files.
% See the list of CMap mfiles at the end of this file.
% We assume that the CMap immediately defines "vertical" CIDs only
% and takes others from another CMap with usecmap.

/GenerateSubst   % <CMap file path name> GenerateSubst -
{
  dup =
  /filename exch def

  /.CMap 100 dict def
  /.CMap-1 100 dict def
  /.condition { true } def

  /usecmap { userdict exch /.usecmap exch =string cvs dup length string copy put } bind def
  /begincmap {} def
  /endcmap {} def
  /findresource { pop pop 20 dict } def
  /begincidrange { pop [ } bind def
  /begincodespacerange { pop mark } bind def
  /endcodespacerange { cleartomark } def
  /beginnotdefrange { pop mark } bind def
  /endnotdefrange { cleartomark } bind def
  /.StringToInt     % <string> .StringToInt <integer>
    { 0 exch { exch 8 bitshift add } forall
    } bind def
  /out { File exch writestring } bind def
  /outl { out linebreak out } bind def
  /endcidrange {
    ]
    { dup type /stringtype eq {
        currentdict /b known {
          .StringToInt /e exch def
        } {
          .StringToInt /b exch def
        } ifelse
      } {
        b 1 e {
          .condition {
            2 copy .CMap 3 1 roll exch put
            2 copy .CMap-1 3 1 roll put
            2 copy =string cvs print ( ) print =
            pop
          } {
            pop
          } ifelse
          1 add
        } for
        pop
        currentdict /b undef
        currentdict /e undef
      } ifelse
    } forall
    CIDSystemInfo /Ordering get userdict exch /Ordering exch put
  } bind def

  % Compute the platform line break :
  filename (r) file dup
  200 string readstring pop
  /str exch def
  closefile

  str (\r) search {
    pop pop pop /r true def
  } {
    /r false def
  } ifelse
  str (\n) search {
    pop pop pop /n true def
  } {
    /n false def
  } ifelse
  r {
    n {
      /linebreak (\r\n) def
    } {
      /linebreak (\r) def
    } ifelse
  } {
    /linebreak (\n) def
  } ifelse

  % parse the top level CMap and create .CMap  :
  filename (r) file run
  /vCMap .CMap dup length dict copy def % save the result.
  /vCMap-1 .CMap-1 dup length dict copy def % save the result.
  % Would like to purge .CMap here, but really no neccessity.

  % Compute the usecmap file name :

  () filename                     % s p
  { .file_name_separator search { % s p' / n
      4 3 roll                    % p' / n s
     dup length 0 gt {
        .file_name_separator concatstrings
      } if
      exch concatstrings          % p' / s/n
      exch pop exch               % s/n p'
    } {
      exit
    } ifelse
  } loop
  pop .file_name_separator concatstrings .usecmap concatstrings

  % Set new filter conditiopn ;
  /.condition { vCMap 1 index known } bind def

  % run the referenced CMap file :
  dup (Running the file ) print =
  (r) file run

  % Write the substitution file header :
  /SubstName Ordering =string cvs (-WMode) concatstrings def
  /File SubstName =string cvs (w) file def
  currentfile .filename pop (r) file
  { dup =string readline not {
      exit
    } if
    ($Id) search {
      pop pop pop exit
    } {
      out linebreak out
    } ifelse
  } loop
  closefile

  (% $Id:) outl
  (% Horizontal to Vertical CID substitution resource for Ordering=) out Ordering =string cvs outl
  linebreak out
  (/) out SubstName out ( 3 dict begin) outl
  (/Ordering \() out Ordering out (\) def) outl
  (/Switch /WMode def) outl

  % Sata for generating the substitution :
  /vCID vCMap-1 length array def
  /hCID vCMap-1 length array def
  /hCMap vCMap length dict def
  /hCMap-1 vCMap-1 length dict def

  % Sort V table :
  0 vCMap-1 {
    pop
    vCID exch 2 index exch put
    1 add
  } forall
  pop
  /vCID vCID { lt } .sort def

  % Write the vertical table :
  (1 [) outl
  vCID {
    dup vCMap-1 exch get dup   % vcid cc cc
    .CMap exch get             % vcid cc hcid
    3 2 roll                   % cc hcid vcid
    hCMap 3 index 3 index put          % fill hCMap
    hCMap-1 3 index 3 index exch put   % fill hCMap-1
    =string cvs out
    ( ) out
    =string cvs out
    ( % ) out
    =string cvs outl
  } forall
  (] def) outl

  % The following code almost duplicates one above, would like to define a procedure.

  % Sort H table :
  0 hCMap-1 {
    pop
    hCID exch 2 index exch put
    1 add
  } forall
  pop
  /hCID hCID { lt } .sort def

  % Write the vertical table :
  (0 [) outl
  hCID {
    dup hCMap-1 exch get dup  % hcid cc cc
    vCMap exch get            % hcid cc vcid
    3 2 roll                  % cc vcid hcid
    =string cvs out
    ( ) out
    =string cvs out
    ( % ) out
    =string cvs outl
  } forall
  (] def) outl

  % Write the trailer :
  (currentdict end /SubstCID defineresource pop) outl
  (%EOF) outl
} bind def

(../../gs-hd/Resource/CMap/V) GenerateSubst
(../../gs-hd/Resource/CMap/B5-V) GenerateSubst
(../../gs-hd/Resource/CMap/GB-V) GenerateSubst
(../../gs-hd/Resource/CMap/KSC-V) GenerateSubst

%EOF