home *** CD-ROM | disk | FTP | other *** search
/ Acorn User 10 / AU_CD10.iso / Updates / GhostScript / !GhostScr / 6_01 / lib / gs_cidfn.ps < prev    next >
Text File  |  2000-03-29  |  15KB  |  465 lines

  1. %    Copyright (C) 1995, 2000 Aladdin Enterprises.  All rights reserved.
  2. % This file is part of Aladdin Ghostscript.
  3. % Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author
  4. % or distributor accepts any responsibility for the consequences of using it,
  5. % or for whether it serves any particular purpose or works at all, unless he
  6. % or she says so in writing.  Refer to the Aladdin Ghostscript Free Public
  7. % License (the "License") for full details.
  8. % Every copy of Aladdin Ghostscript must include a copy of the License,
  9. % normally in a plain ASCII text file named PUBLIC.  The License grants you
  10. % the right to copy, modify and redistribute Aladdin Ghostscript, but only
  11. % under certain conditions described in the License.  Among other things, the
  12. % License requires that the copyright notice and this notice be preserved on
  13. % all copies.
  14.  
  15. % $Id: gs_cidfn.ps,v 1.3 2000/03/10 04:53:25 lpd Exp $
  16. % ProcSet for implementing CIDFont and CIDMap resources.
  17. % When this is run, systemdict is still writable.
  18.  
  19. % ---------------- Defining CIDFont resources ---------------- %
  20.  
  21. % Define a CIDFont resource.  This is the defineresource implementation for
  22. % the CIDFont resource category.
  23.  
  24. /.cidfonttypes where { pop } { /.cidfonttypes 6 dict def } ifelse
  25. .cidfonttypes begin
  26.  
  27. % The key in .cidfonttypes is the CIDFontType value;
  28. % the value is a procedure that takes a font name and the CIDFont dictionary
  29. % and replaces the latter with a real font.
  30.  
  31. 0 {    % CIDFontType 0 = FontType 9
  32.   currentglobal 3 1 roll dup gcheck setglobal
  33.   dup /FontType 9 put
  34.   dup /FontMatrix known not {
  35.     dup /FontMatrix [0.001 0 0 0.001 0 0] put
  36.     dup /FDArray get {
  37.       /FontMatrix get [1000 0 0 1000 0 0] 1 index concatmatrix pop
  38.     } forall
  39.   } if
  40.   dup /FDArray get mark exch {
  41.         % Add pro forma entries
  42.     currentglobal exch dup gcheck setglobal
  43.     dup /FontType 1 put
  44.     dup /CharStrings mark /.notdef () .dicttomark put
  45.     dup /Encoding [] put
  46.         % Create a dummy Subrs array now, if there isn't one here
  47.         % already (which can only happen if we're giving another
  48.         % name to an existing font).
  49.     dup /Private get dup /Subrs known not {
  50.       dup /SubrCount .knownget {
  51.     array 1 index /Subrs 3 -1 roll put
  52.       } if readonly
  53.     } if pop
  54.     exch setglobal
  55.     dup /FontName .knownget not { () } if exch .buildfont1 exch pop
  56.   } forall ] 1 index /FDepVector 3 -1 roll put
  57.   3 -1 roll setglobal
  58.   1 index exch .buildfont9 exch pop
  59. } bind def
  60.  
  61. 1 {    % CIDFontType 1 = FontType 10
  62.   dup /FontType 10 put
  63.   1 index exch .buildfont10 exch pop
  64. } bind def
  65.  
  66. 2 {    % CIDFontType 2 = FontType 11
  67.   dup /FontType 11 put
  68.   1 index exch .buildfont11 exch pop
  69. } bind def
  70.  
  71. end        % .cidfonttypes
  72.  
  73. % ---------------- Reading CIDFontType 0 files ---------------- %
  74.  
  75. 30 dict begin
  76.  
  77. % We add the following entries to the CIDFont dictionary, in addition to
  78. % the ones documented by Adobe:
  79. %    ReadString - procedure for reading a string from the binary data
  80. %    SubrCache - dictionary for caching Subr arrays
  81. % For CIDFonts where we read the data from disk incrementally:
  82. %    DataOffset - starting position of data in file
  83. %    (if data are in hex) OffsetMap - map from logical data positions to
  84. %      physical positions in file
  85.  
  86. /StartData        % <(Binary)|(Hex)> <datalength> StartData -
  87.             %   (currentdict is CID font dict)
  88. {        % If we're loading a resource file, we can just save a
  89.         % pointer to the binary data and load it incrementally.
  90.         % Check for this by opening the resource file,
  91.         % positioning it to currentfile's position plus the
  92.         % data length, and checking for %%EndData.
  93.    mark
  94.     { currentfile fileposition
  95.       CIDFontName 100 string ResourceFileName (r) file
  96.        mark
  97.     {        % Stack: (Binary)|(Hex) length -mark- pos resfile
  98.             %   -mark-
  99.       5 index (Hex) eq
  100.        { 1 index 3 index setfileposition
  101.          1 index 5 index .skiphex
  102.             %**************** SKIP > AND WHITESPACE SOMEHOW
  103.        }
  104.        { 1 index 3 index 6 index add setfileposition
  105.        }
  106.       ifelse
  107.       1 index 9 string readstring pop (%%EndData) ne { stop } if
  108.     }
  109.        .internalstopped { cleartomark closefile stop } if
  110.        pop        % pop the mark
  111.     }
  112.    .internalstopped
  113.    {        % File is not positionable, load the data now.
  114.      cleartomark exch (Hex) eq
  115.       { { currentfile exch readhexstring pop } }
  116.       { { currentfile exch readstring pop } }
  117.      ifelse /ReadString exch def
  118.      dup 65535 le {
  119.         % readstring with a 0-length string causes a rangecheck,
  120.         % but a data length of 0 is allowed.
  121.        string dup () ne { ReadString } if
  122.      } {
  123.        mark exch
  124.      { dup 0 eq { pop exit } if
  125.        dup 65535 min dup string ReadString
  126.        3 1 roll sub
  127.      }
  128.     loop ]
  129.      } ifelse
  130.      /GlyphData exch def
  131.         % If we were reading hex data, skip past the >.
  132.      /ReadString load 2 get { readhexstring } 0 get eq {
  133.        currentfile 0 (>) /SubFileDecode filter dup flushfile closefile
  134.      } if
  135.      /.vmreadstring cvx
  136.    }
  137.    {        % File is positionable, just save a pointer.
  138.         % Stack: (Binary)|(Hex) length -mark- pos file
  139.      4 1 roll
  140.      /DataOffset exch def
  141.      pop /GlyphData exch def
  142.      exch (Hex) eq
  143.       {        % Hex data, build the offset map.
  144.     .buildoffsetmap
  145.     /.hexreadstring
  146.       }
  147.       {        % Binary data, just skip over it.
  148.     currentfile DataOffset GlyphData add setfileposition
  149.     /.binaryreadstring
  150.       }
  151.      ifelse cvx
  152.      2 packedarray cvx
  153.    }
  154.   ifelse /ReadString exch def
  155.   /SubrCache 10 dict def
  156.   CIDFontName currentdict /CIDFont defineresource pop
  157.   end            % CID font dict
  158.   end            % resource category dict
  159. } bind def
  160.  
  161. % Skip a given distance in an ASCIIHex encoded file.  We use this at
  162. % rendering time as well.
  163. /.skiphex        % <file> <count> .skiphex -
  164. { exch /ASCIIHexDecode filter dup 3 -1 roll () /SubFileDecode filter
  165.   dup flushfile closefile closefile
  166. } bind def
  167.  
  168. % Build the map from logical offsets to physical offsets in ASCIIHex
  169. % encoded data.
  170. /.buildoffsetmap
  171. { /OffsetMap GlyphData 256 idiv 8000 min array def
  172.   2 dict begin
  173.      /block GlyphData OffsetMap length idiv def
  174.      0 1 OffsetMap length 1 sub
  175.       { OffsetMap exch currentfile fileposition put
  176.     currentfile block .skiphex
  177.       }
  178.      for
  179.      GlyphData block mod dup 0 eq
  180.       { pop }
  181.       { currentfile exch .skiphex }
  182.      ifelse
  183.   end            % scratch dict
  184. } bind def
  185.  
  186. % Some Adobe fonts include the line
  187. %   /Setup /cid_Setup load def
  188. % This is apparently included only to prevent proper, conforming PostScript
  189. % interpreters (as opposed to ATM or a special Adobe font loader) from
  190. % loading the font, since Setup is not referenced anywhere else in the file.
  191. %/cid_Setup { } def
  192.  
  193. currentdict end
  194.  
  195. % ---------------- Rendering ---------------- %
  196.  
  197. % ------ Generic ------ %
  198.  
  199. % Read a string at a given offset in a "file" (binary file, ASCII hex file,
  200. % or GlyphData in RAM).
  201. /.binaryreadstring    % <pos> <string> <file> .binaryreadstring <string>
  202.  { dup 4 -1 roll DataOffset add setfileposition exch readstring pop
  203.  } bind def
  204. /.hexreadstring        % <pos> <string> <file> .hexreadstring <string>
  205. {        % Use the OffsetMap to get to the block of hex data,
  206.         % then skip to the correct position by reading.
  207.   GlyphData OffsetMap length idiv
  208.         % Stack: pos string file blocklen
  209.   3 index 1 index idiv OffsetMap exch get
  210.   2 index exch setfileposition
  211.         % Skip the next (pos % blocklen) hex bytes.
  212.   4 -1 roll exch mod 1 index exch .skiphex
  213.         % Stack: string file
  214.   exch readhexstring pop  
  215. } bind def
  216. /.vmreadstring        % <pos> <string> .vmreadstring <vmstring>
  217. { GlyphData .stringsreadstring
  218. } bind def
  219. /.stringsreadstring    % <pos> <string> <strings> .stringsreadstring
  220.             %   <vmstring>
  221. { dup type /stringtype eq
  222.    { 3 1 roll length getinterval
  223.    }
  224.    {  {        % Stack: pos string glyphdata
  225.     dup 0 get length dup 4 index gt { exit } if
  226.     4 -1 roll exch sub 3 1 roll
  227.     dup length 1 sub 1 exch getinterval
  228.       }
  229.      loop
  230.         % Stack: pos string glyphdata glyphdata[0]length
  231.         % We know no request can span more than 2 strings.
  232.      3 index 3 index length add 1 index le
  233.       {        % Request fits in a single string: just return a substring.
  234.     pop 0 get 3 1 roll length getinterval
  235.       }
  236.       {        % Request spans 2 strings.  Copy the first part.
  237.     1 index 0 get 4 index 3 -1 roll 1 index sub getinterval
  238.     2 index copy
  239.         % Copy the second part.
  240.         % Stack: pos str glyphdata str1
  241.     length exch 1 get 0 3 index length
  242.     3 index sub getinterval 2 index 3 1 roll putinterval
  243.     exch pop
  244.       }
  245.      ifelse
  246.    }
  247.   ifelse
  248. } bind def
  249.  
  250. % Interpret a byte string as a (big-endian) integer.
  251. /.cvbsi            % <bytes> .cvbsi <int>
  252. { 0 exch { exch 8 bitshift add } forall
  253. } bind def
  254.  
  255. % Read an integer from binary data.
  256. /.readint        % <pos> <nbytes> .readint <int>
  257. { string ReadString .cvbsi
  258. } bind def
  259.  
  260. % Read the glyph data for a given CID.  The CIDFont is currentdict.
  261. % Note that the data must be read into the same VM as the CharStrings
  262. % dictionary of the selected subfont.
  263. /.readglyphdata {    % <cid> .readglyphdata <subfont> <string|null>
  264.   currentdict /GlyphDirectory .knownget {
  265.     dup type /arraytype eq {
  266.       1 index get
  267.     } {
  268.       1 index .knownget not { null } if
  269.     } ifelse
  270.             % Stack: cid string|null
  271.     dup null ne { exch pop .readgdirdata } { pop .readbytedata } ifelse
  272.   } {
  273.             % Stack: cid
  274.     .readbytedata
  275.   } ifelse
  276. } bind def
  277. /.readgdirdata {    % <string|null> .readgdirdata <subfont> <string|null>
  278.   dup null eq {
  279.     FDepVector 0 get exch
  280.   } {
  281.     FDBytes 0 eq {
  282.       FDepVector 0 get exch
  283.     } {
  284.             % Note: FDBytes > 1 is not supported.
  285.       dup 0 get FDepVector exch get
  286.       exch dup length 1 sub 1 exch getinterval
  287.     }    ifelse
  288.   } ifelse
  289. } bind def
  290. /.readbytedata {    % <cid> .readbytedata <subfont> <string|null>
  291.   dup dup 0 ge exch CIDCount lt and {
  292.     FDBytes GDBytes add mul CIDMapOffset add
  293.     dup FDBytes .readint exch
  294.     FDBytes add dup GDBytes .readint
  295.     exch GDBytes add FDBytes add GDBytes .readint
  296.             % Stack: fd pos nextpos
  297.     1 index sub dup 0 eq {
  298.       pop pop pop FDepVector 0 get null
  299.     } {
  300.             % Stack: fd pos len
  301.       FDepVector 4 -1 roll get
  302.       dup /CharStrings get gcheck .currentglobal exch .setglobal
  303.             % Stack: pos len subfont global
  304.       4 2 roll string ReadString exch .setglobal
  305.     } ifelse
  306.   } {
  307.     pop FDepVector 0 get null
  308.   } ifelse
  309. } bind def
  310.  
  311. % ------ CIDFontType 0 ------ %
  312.  
  313. % Read some Subrs for the current Type 1 subfont.
  314. % The subfont's Private dict is currentdict; the CIDFont itself is the
  315. % next dictionary on the stack.
  316. /.readsubrs {        % <Subrs> <start> .readsubrs <Subrs>
  317.   1 SubrCount 1 sub {
  318.     dup SDBytes mul SubrMapOffset add
  319.     dup SDBytes .readint exch SDBytes add SDBytes .readint
  320.     1 index sub string ReadString 2 index 3 1 roll put
  321.   } for
  322. } bind def
  323.  
  324. % Ensure that all the Subrs for the current Type 1 subfont are loaded.
  325. % The subfont's Private dict is currentdict; the CIDFont itself is the
  326. % next dictionary on the stack.
  327. /.loadsubrs {
  328.   currentdict /SubrMapOffset .knownget {
  329.     Subrs length 0 eq { true } { Subrs 0 get null ne } ifelse {
  330.       pop        % We've already loaded the Subrs.
  331.     } {
  332.       currentglobal exch currentdict gcheck setglobal
  333.       SubrCache 1 index .knownget {
  334.             % We've already loaded some Subrs at this offset.
  335.             % Make sure we've got as many as we need.
  336.     dup length SubrCount lt {
  337.             % We need to load more.
  338.       SubrCount array exch 1 index copy length .readsubrs
  339.       SubrCache 3 -1 roll 2 index put
  340.     } if
  341.       } {
  342.             % We haven't loaded any Subrs at this offset yet.
  343.     SubrCount array 0 .readsubrs
  344.     SubrCache 3 -1 roll 2 index put
  345.       } ifelse
  346.       Subrs copy pop setglobal
  347.     } ifelse
  348.   } if
  349. } bind def
  350.  
  351. % BuildGlyph procedure for CIDFontType 0.
  352. % ****** WHY NOT USE .type1execchar FOR THIS? ******
  353. % The name %Type9BuildGlyph is known to the interpreter.
  354. /.cid0buildstring 10 string def
  355. (%Type9BuildGlyph) cvn {    % <cidfont> <cid> %Type9BuildGlyph -
  356.   .currentglobal 3 1 roll 1 index gcheck .setglobal
  357.   1 index begin
  358.   dup .readglyphdata dup null eq {
  359.         % Substitute CID 0. **** WRONG ****
  360.     pop pop 0 .readglyphdata
  361.   } if
  362.             % Stack: cidfont cid subfont charstring
  363. dup null eq { pop pop pop pop } {    %**** WRONG ****
  364.   4 -1 roll pop
  365.   exch dup /Private get begin .loadsubrs end
  366.   3 -1 roll //.cid0buildstring cvs cvn 3 1 roll
  367.   dup /CharStrings get 3 index 4 -1 roll put
  368.   setfont
  369.   dup .glyphwidth setcharwidth
  370.   0 0 moveto glyphshow
  371. } ifelse    %**** WRONG ****
  372.   end
  373.   .setglobal
  374. } bind def
  375.  
  376. % ------ CIDFontType 2 ------ %
  377.  
  378. % BuildGlyph procedure for CIDFontType 2.
  379. % ****** ADD THE OUTLINE STRING AS AN ARGUMENT TO .type42execchar. ******
  380. % The name %Type11BuildGlyph is known to the interpreter.
  381. (%Type11BuildGlyph) cvn {    % <cidfont> <cid> %Type11BuildGlyph -
  382.   .currentglobal 3 1 roll 1 index gcheck .setglobal
  383.   1 index begin
  384.         % We must be prepared for out-of-range CIDs.
  385.   dup GDBytes mul GDBytes string CIDMap
  386.   mark 4 1 roll { .stringsreadstring } .internalstopped {
  387.         %**** 0 IS WRONG
  388.     cleartomark 0 GDBytes string CIDMap .stringsreadstring
  389.   } {
  390.     exch pop
  391.   } ifelse .cvbsi
  392.             % Stack: cidfont cid glyphindex
  393.   1 index exch .type42execchar
  394.   end
  395.   .setglobal
  396. } bind def
  397.  
  398. % ---------------- Define resources ---------------- %
  399.  
  400. languagelevel exch 2 .setlanguagelevel
  401.  
  402. % Define the CIDInit ProcSet resource.
  403. % The ProcSet dictionary is still on the stack.
  404.  
  405. /CMap /Generic /Category findresource dup length dict .copydict
  406. /Category defineresource pop
  407.     % We might have loaded CMap support already.
  408. /CIDInit /ProcSet 2 copy resourcestatus {
  409.   pop pop findresource dup length 4 index length add dict .copydict
  410.   4 -1 roll exch .copydict
  411. } {
  412.   3 -1 roll
  413. } ifelse exch defineresource pop
  414.  
  415. % Define the CIDFont resource category.
  416. % We break out .buildcidfont because it appears that at least for
  417. % Type 32 (CIDFontType 4) fonts, the font can be registered in the Font
  418. % category with only a CIDFontType and no FontType.
  419. /.buildcidfont {        % <name> <fontdict> .buildcidfont
  420.                 %   <name> <cidfont>
  421.   dup /CIDFontType get //.cidfonttypes exch get exec
  422. } odef
  423.  
  424. /CIDFont /Generic /Category findresource dup length dict .copydict
  425. dup /InstanceType /dicttype put
  426. dup /DefineResource {
  427.   .buildcidfont
  428.   /Generic /Category findresource /DefineResource get exec
  429. } put
  430. /Category defineresource pop
  431.  
  432. % Add the new FontType resources.
  433.  
  434. 9 1 11 { dup /FontType defineresource pop } for
  435.  
  436. % Add the new FMapType resource.
  437.  
  438. 9 dup /FMapType defineresource pop
  439.  
  440. % Define the CIDMap resource category.
  441. % These aren't documented, but it's clear what they are for:
  442. % to give names to CIDMaps for CIDFontType 2 fonts.
  443.  
  444. /CIDMap /Generic /Category findresource dup length dict .copydict
  445. dup /.CheckResource {
  446.     % Allow either a string or an array of strings.
  447.   dup type dup /stringtype eq
  448.    { pop true
  449.    }
  450.    { dup /arraytype eq exch /packedarraytype eq or
  451.       { true exch { type /stringtype ne { pop false exit } if } forall
  452.       }
  453.       { false
  454.       }
  455.      ifelse
  456.    }
  457.   ifelse
  458. } bind put
  459. /Category defineresource pop
  460.  
  461. .setlanguagelevel
  462.