home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / share / gs-esp / 8.15 / lib / pdf_font.ps < prev    next >
Encoding:
Text File  |  2006-07-06  |  44.4 KB  |  1,382 lines

  1. %    Copyright (C) 1994, 2000 Aladdin Enterprises.  All rights reserved.
  2. % This software is provided AS-IS with no warranty, either express or
  3. % implied.
  4. % This software is distributed under license and may not be copied,
  5. % modified or distributed except as expressly authorized under the terms
  6. % of the license contained in the file LICENSE in this distribution.
  7. % For more information about licensing, please refer to
  8. % http://www.ghostscript.com/licensing/. For information on
  9. % commercial licensing, go to http://www.artifex.com/licensing/ or
  10. % contact Artifex Software, Inc., 101 Lucas Valley Road #110,
  11. % San Rafael, CA  94903, U.S.A., +1(415)492-9861.
  12.  
  13. % $Id: pdf_font.ps,v 1.53.2.12 2005/01/10 15:15:41 alexcher Exp $
  14. % PDF font operations.
  15.  
  16. % Finding a font by name can't give a proper result when PDF font names aren't unique.
  17. % But it is only the way to obtain a font in Postscript after a font file is executed.
  18. % Therefore using a FontName (and findfont) is allowed only
  19. % immediately after a font file is executed.
  20. % In all other cases the font to be found by a pointer through PDF structures.
  21. % This ideal logics can't work for documents,
  22. % which define a font resource with an embedded font,
  23. % and another font resource with same BaseFont but with no embedded font
  24. % (and possibly with no font descriptor).
  25. % Our testbase does contain such examples.
  26. % In this case we do find font by FontName (with findfont),
  27. % since there is no other way to get a reasonable result.
  28.  
  29. /.setlanguagelevel where { pop 2 .setlanguagelevel } if
  30. .currentglobal true .setglobal
  31. /pdfdict where { pop } { /pdfdict 100 dict def } ifelse
  32. GS_PDF_ProcSet begin
  33. pdfdict begin
  34.  
  35. % We cache the PostScript font in an additional element of the
  36. % font resource dictionary, called PSFont.
  37.  
  38. % ---------------- Encodings ---------------- %
  39.  
  40. /.notdefEncoding 256 { /.notdef } repeat 256 packedarray def
  41.  
  42. % Apply a list of differences to an Encoding.
  43. % Note that the differences may cause the array to grow.
  44. /updateencoding {    % <encoding|null> <differences> updateencoding <enc'>
  45.     % Calculate the length of the result.
  46.   % in case the incoming Encoding is null, use .notdefEncoding
  47.   exch dup null eq { pop .notdefEncoding } if
  48.   0 0 3 index {
  49.     dup type /nametype ne { exch pop oforce } { pop 1 add } ifelse
  50.     % Differences list may not be in order, update the largest_index
  51.     % stack: <Differences> <encoding> <largest_index> <at_index>
  52.     2 copy lt { exch pop dup } if    % at_index is new largest
  53.   } forall
  54.   pop 1 index length .max array dup 0 4 -1 roll putinterval
  55.   exch 0 exch {
  56.         % Stack: enc' code element
  57.     dup type /nametype ne
  58.       { exch pop oforce }
  59.       { 3 copy put pop 1 add }
  60.     ifelse
  61.   } forall pop
  62. } bdef
  63.  
  64. % Get the Encoding for a font.
  65. /getencoding        % <base-encoding> <font-resource> getencoding <enc>
  66.  { /Encoding knownoget
  67.     { dup type /nametype eq
  68.        {
  69.          % The published PDF specification says the Encoding name
  70.          % "must be" one of the 3 predefined Encodings, implying
  71.          % that an error should occur if it isn't.  However, Acrobat
  72.          % Reader simply ignores unknown names, and since there are
  73.          % some buggy applications that rely on this, we do the same.
  74.  
  75.          dup dup dup /MacRomanEncoding eq
  76.          exch /MacExpertEncoding eq or 
  77.          exch /WinAnsiEncoding eq or
  78.            { exch pop findencoding
  79.            }
  80.            { pop
  81.            }
  82.          ifelse
  83.        }
  84.        { dup /BaseEncoding knownoget
  85.        {
  86.              dup / eq
  87.                { pop
  88.                  (   **** Warning: Ignoring bad BaseEncoding name.\n)  pdfformaterror
  89.                  % as found in a PDF file from J.D.Edwards OneWorld (B7333), bug 687786
  90.                }
  91.                {
  92.                  findencoding 3 -1 roll pop exch
  93.                }
  94.              ifelse
  95.       }
  96.      if
  97.      /Differences knownoget { updateencoding } if
  98.        }
  99.       ifelse
  100.     }
  101.    if
  102.  } bdef
  103.  
  104. % Define a font using it's FontName as the key.
  105. % Adjust a font according to the Encoding and Widths in the font resource.
  106. /adjustfont {        % <font-resource> <font> adjustfont <font'>
  107.   getfontencoding
  108.   getfontmetrics 5 -1 roll pop .updatefont { dup /FontName get exch definefont } if
  109. } bind def
  110.  
  111. % Get the (possibly modified) encoding of a font.
  112. /getfontencoding {    % <font-resource> <font> getfontencoding
  113.             %   <font-resource> <font> <Encoding|null>
  114.   1 index /Encoding known {
  115.     dup /Encoding knownoget { 2 index getencoding } { null } ifelse
  116.   } {
  117.     null
  118.   } ifelse
  119. } bdef
  120.  
  121. % Returns true if the current glyph is in the Differences array at
  122. % the specified index value. This is needed because the Widths
  123. % array may map to the same glyph at different positions from the
  124. % Encoding. We want to use the Width that was associated with the
  125. % one specified in the Encoding::Differences list.
  126. /match_in_diff     % <Differences> <index> <glyphname> match_in_diff <bool>
  127. { false 4 1 roll 0 4 -1 roll    % stack: false index glyphname at_index==0 Differences
  128.   { exch 1 index type /nametype ne {
  129.       % stack: false index glyphname Diff_element at_index 
  130.       pop    % Diff_element is new at_index
  131.     } {
  132.       % stack: false index glyphname Diff_element at_index 
  133.       exch 2 index eq {
  134.         % stack: false index glyphname at_index 
  135.     dup 3 index eq {
  136.           true 5 1 roll    % stack: true false index glyphname at_index
  137.           pop exit
  138.         } if
  139.       } if
  140.       1 add        % at_index++ stack: false index glyphname at_index' 
  141.     } ifelse
  142.   } forall
  143.   % stack: true  false index     glyphname
  144.   %  or  : false index glyphname at_index
  145.   pop pop pop
  146. } bdef
  147.  
  148. /unique_name {  % <dict> </root> unique_name </unique>
  149.   %
  150.   %  Note : this function interacts with pdf_write_encoding in src/gdevpdtw.c
  151.   %  and with copied_drop_extension_glyphs in src\gxfcopy.c
  152.   %  by adding a reserved substring (~GS~).
  153.   %
  154.   .namestring       % <<>> (root)
  155.   0 1 65535 {
  156.     5 string cvs    % <<>> (root) (0)
  157.     (~GS~) exch concatstrings
  158.     1 index exch    % <<>> (root) (root) (~GS~0)
  159.     concatstrings   % <<>> (root) (root~GS~0)
  160.     dup             % <<>> (root) (root~GS~0) (root~GS~0)
  161.     3 index exch    % <<>> (root) (root~GS~0) <<>> (root~GS~0)
  162.     known not {
  163.       exch pop exit % <<>> (root~GS~0)
  164.     } if
  165.     pop
  166.   } for
  167.   exch pop cvn      % /root0
  168. } bdef
  169.                                
  170. % Get the metrics of a font, if specified.
  171. /getfontmetrics {    % <font-resource> <font> <Encoding|null> getfontmetrics
  172.             %   <font-resource> <font> <Encoding|null>
  173.             %   <Metrics|null> <GlyphMap|null>
  174.   2 index /Widths known {
  175.     dup null eq { pop dup /Encoding get } if
  176.     4 dict begin
  177.       dup length dict
  178.       /Metrics exch def
  179.       /Encoding exch def
  180.       /GlyphMap //null def
  181.       exch
  182.       dup /Widths oget /Widths exch def
  183.         % Stack: font font-res
  184.         % Note that widths are always based on a 1000-unit
  185.         % character space, but the FontMatrix may specify
  186.         % some other scale factor.  Compensate for this here,
  187.         % by scaling the Widths if necessary.
  188.       0.001 2 index /FontMatrix get 0 get div
  189.         % Stack: font font-res mscale
  190.       1 index /FirstChar oget dup 1 4 index /LastChar oget
  191.        {    % Stack: font font-res mscale first-char index
  192.      Encoding 1 index dup 2 index length ge {
  193.            (   **** Warning: Font Encoding array size is smaller than character range.\n)
  194.            pdfformaterror
  195.        pop pop /.notdef
  196.          } {
  197.        get
  198.      } ifelse
  199.      Widths 2 index 4 index sub dup 2 index length ge {
  200.            (   **** Warning: Font Widths array size is smaller than character range.\n)
  201.            pdfformaterror
  202.            % use MissingWidth if it's available, if not, default to 1000 (full width)
  203.        pop pop 4 index /FontDescriptor knownoget {
  204.          /MissingWidth knownoget not { 1000    } if
  205.        } { 1000 } ifelse
  206.          } {
  207.        get
  208.      } ifelse
  209.          % Stack: font font-res mscale first-char index charname width
  210.      4 index mul
  211.         % The following 'loop' is only context for 'exit'.
  212.      {    
  213.         % Work around a bug in pdfTeX, which can generate Encoding
  214.         % vectors containing nulls :
  215.        1 index //null eq { exit } if
  216.            Metrics 2 index .knownget {
  217.              1 index ne
  218.            } {
  219.              //false
  220.            } ifelse {
  221.              % Two or more Encoding elements refer same glyph name,
  222.              % and Widths specify different wihts for it.
  223.              % Since a Postscript font can't have different 
  224.              % Metrics for same glyph name, 
  225.              % we generate an unique name, and create a new 
  226.              % Charstrings entry with same glyph value.
  227.              GlyphMap //null eq {
  228.                /Encoding Encoding dup length array copy def
  229.                /GlyphMap 4 dict def
  230.              } if
  231.              % To prevent too many new names, check whether
  232.              % we can use one already created for same glyph.
  233.              //true
  234.              GlyphMap {                           % f r s c i n w b n1 n2
  235.                4 index eq {                       % f r s c i n w b n1
  236.                  dup Metrics exch get             % f r s c i n w b n1 w1
  237.                  3 index eq {                     % f r s c i n w b n1
  238.                    4 3 roll pop                   % f r s c i w b n1
  239.                    3 1 roll pop                   % f r s c i n1 w
  240.                    Encoding 3 index 3 index put
  241.                    //false                        % f r s c i n1 w b
  242.                    exit
  243.                  } {
  244.                    pop
  245.                  } ifelse
  246.                } {                                % f r s c i n w b n1
  247.                  pop
  248.                } ifelse
  249.              } forall                             % f r s c i n w b
  250.              { % Do create a new name.
  251.                Metrics 2 index //unique_name exec % f r s c i n w nn
  252.              Encoding 4 index 2 index put
  253.                GlyphMap 1 index 5 -1 roll put     % f r s c i w nn
  254.              exch
  255.                 % Stack: font font-res mscale first-char index new_name width
  256.              } if
  257.            } if
  258.            2 copy Metrics 3 1 roll put
  259.        exit
  260.      } loop
  261.      pop pop pop
  262.        }
  263.       for pop
  264.         % Now fill in the MissingWidth for any encoded characters
  265.         % that aren't in Metrics already.  Note that built-in
  266.         % fonts may have Widths/FirstChar/LastChar but no
  267.         % FontDescriptor, so we must check for this.
  268.         % Stack: font font-res mscale
  269.       1 index /FontDescriptor knownoget {
  270.     Metrics exch
  271.     /MissingWidth knownoget { 2 index mul } { 0 } ifelse exch
  272.     Encoding {
  273.         % Stack: font font-res mscale missing-width metrics charname
  274.         % Work around the abovementioned pdfTeX bug.
  275.       dup //null ne {
  276.         2 copy known not { 2 copy 4 index put } if pop
  277.       } {
  278.         pop
  279.       } ifelse
  280.     } forall pop pop pop
  281.       } {
  282.     pop
  283.       } ifelse
  284.     exch Encoding Metrics GlyphMap end
  285.   } {
  286.     //null //null
  287.   } ifelse
  288. } bdef
  289.  
  290. currentdict /unique_name undef
  291. currentdict /match_in_diff undef
  292.  
  293. % ---------------- Descriptors ---------------- %
  294.  
  295. % Partial descriptors for the 14 built-in fonts.  Note that
  296. % from PDF 1.1 to PDF 1.2, the meaning of the Flag 6 in the FontDescriptor
  297. % object has undergone a subtle change in its meaning which has serious
  298. % consequences for searching with Acrobat:
  299. % In PDF 1.1, the flag meant: Font has StandardEncoding
  300. % In PDF 1.2, the flag means: Font has (subset of) StandardRomanCharacterSet
  301. /standardfontdescriptors mark
  302.   /Courier mark /Flags 16#23 .dicttomark
  303.   /Courier-Oblique 1 index
  304.   /Courier-Bold 1 index
  305.   /Courier-BoldOblique 1 index
  306.   /Helvetica mark /Flags 16#20 .dicttomark
  307.   /Helvetica-Oblique 1 index
  308.   /Helvetica-Bold 1 index
  309.   /Helvetica-BoldOblique 1 index
  310.   /Times-Roman mark /Flags 16#22 .dicttomark
  311.   /Times-Bold 1 index
  312.   /Times-Italic mark /Flags 16#62 .dicttomark
  313.   /Times-BoldItalic 1 index
  314.   /Symbol mark /Flags 16#4 .dicttomark
  315.   /ZapfDingbats 1 index
  316. .dicttomark readonly def
  317.  
  318. % ---------------- Utilities ---------------- %
  319.  
  320.  
  321. /.pdforigfontcache_g 20 dict def
  322. currentglobal false setglobal
  323. systemdict /.pdforigfontcache_l 20 dict .forceput
  324. setglobal
  325.  
  326. % Find an original font, using cache to prevent adjustfont to accumulate changes.
  327. /pdffindcachedfont {   % <font_name> pdffindcachedfont <font>
  328.   dup //.pdforigfontcache_g exch .knownget {
  329.     exch pop
  330.   } {
  331.     dup .pdforigfontcache_l exch .knownget {
  332.       exch pop
  333.     } {
  334.       dup findfont dup    
  335.       dup gcheck { //.pdforigfontcache_g } { .pdforigfontcache_l } ifelse
  336.                      % Stack : font_name font font cache
  337.       4 2 roll .growput
  338.     } ifelse
  339.   } ifelse
  340. } bind def
  341.  
  342. % Add original font to cache to prevent adjustfont to accumulate changes.
  343. /pdfaddcachedfont {   % <font_name> pdfaddcachedfont <font>
  344.   dup findfont dup                   % name font font
  345.   dup gcheck { //.pdforigfontcache_g } {.pdforigfontcache_l} ifelse
  346.   4 2 roll                           % font d name font
  347.   put                                % font
  348. } bind def
  349.  
  350. /.remove_font_name_prefix {  % <name>  .remove_font_name_prefix <name>
  351.   dup .namestring (+) search {
  352.     true exch
  353.     { dup 65 lt exch 90 gt or {
  354.         pop false exit
  355.       } if
  356.     } forall
  357.     { pop exch pop cvn
  358.     } {
  359.       pop pop
  360.     } ifelse
  361.   } {
  362.     pop
  363.   } ifelse
  364. } bind def
  365.  
  366. % Find a font (except for embedded ones), and adjust its encoding if necessary.
  367. /.pdfdfndict mark
  368.   /defaultfontname /Helvetica
  369. .dicttomark readonly def
  370. /pdffindfont {        % <font-resource> <fontname> pdffindfont <font>
  371.         % If the font isn't available, synthesize one based on
  372.         % its descriptor.
  373.   dup /Font resourcestatus {
  374.     pop pop pdffindcachedfont
  375.   } {
  376.     1 index /FontDescriptor knownoget {
  377.         % Stack: font-res fontname fontdesc
  378.       dup /Flags oget
  379.       dup 16#40 and -6 bitshift        % 1, oblique/italic
  380.       1 index 16#40000 and -17 bitshift add    % 2, bold
  381.       exch 16#2 and 2 bitshift add    % 8, serif
  382.         % We should look at the fixed flag, too.
  383.         % Stack: font-res fontname fontdesc properties
  384.  
  385.                 % Even though /FontName is a required key in FontDescriptor dict
  386.                 % (As of the PDF 1.4 Reference Manual), In the case of missing 
  387.                 % /FontName key, we substitue /BaseFont for the value of /FontName.
  388.                 % Yet another case of broken PDF's that Adobe Reader accepts.
  389.       1 index dup /FontName known {
  390.         /FontName oget
  391.       } {
  392.         (   **** FontDescriptor missing required /FontName key. BaseFont name used.\n)
  393.         pdfformaterror
  394.         pop 2 index        % grab the BaseFont from the stack.
  395.       } ifelse
  396.       .remove_font_name_prefix
  397.       exch
  398.         % Analyzes font name and extract "Narrow" property
  399.         % which is not described by the FontDescriptor Flags.
  400.       0 2 index .fontnameproperties 4 and or
  401.         % Rebind the default font name to Helvetica so that
  402.         % fonts with no properties are handled correctly.
  403.       //.pdfdfndict begin .substitutefontname end
  404.         % Stack: font-res fontname fontdesc substname|null
  405.       Fontmap 1 index known not {
  406.         % No available good substitution, use the standard one.
  407.     pop 1 index .substitutefont
  408.       } if
  409.       dup 3 index ne QUIET not and {
  410.     (Substituting font ) print dup =only
  411.     ( for ) print 2 index =only (.) = flush
  412.       } if
  413.       pdffindcachedfont
  414.         % Stack: font-res fontname fontdesc font
  415.         % If this is a small-caps font, replace the CharString
  416.         % entries for a..z.
  417.       exch /Flags oget 16#20000 and 0 ne {
  418.     true .copyfontdict
  419.     dup /CharStrings 2 copy get dup length dict .copydict
  420.     % stack: font-res fontname font font /CharStrings CharStringsdict
  421.     5 index /FirstChar get 97 .max
  422.     6 index /LastChar get 122 .min 1 exch {
  423.         % Stack: font-res fontname font' font' /CharStrings charstrings code
  424.         % Note that this only remaps a-z, not accented characters.
  425.       6 index /Widths oget 1 index 8 index /FirstChar get sub oget
  426.       1 string dup 0 5 -1 roll put
  427.         % Stack: font-res font' font' /CharStrings charstrings code
  428.         %   width (x)
  429.       2 index exch dup cvn exch
  430.       dup 0 2 copy get 32 sub put 4 -1 roll {
  431.             % Stack: operand (X) width
  432.         0 setcharwidth exch pop
  433.         currentfont /FontMatrix get matrix invertmatrix concat
  434.         0.7 dup scale 0 0 moveto show
  435.       } /exec cvx 4 packedarray cvx put
  436.     } for put
  437.       } if
  438.       dup /FontName get 2 index ne {
  439.         true .copyfontdict
  440.         2 copy exch /FontName exch put
  441.       } if
  442.       definefont
  443.     } {
  444.         % No descriptor available, use the default algorithm.
  445.       pdffindcachedfont
  446.     } ifelse
  447.   } ifelse
  448.   exch pop
  449. } bdef
  450.  
  451. % ---------------- Type 1 fonts ---------------- %
  452.  
  453. /buildType1        % <Type1-font-resource> buildType1 <font>
  454.  { dup /BaseFont get pdffindfont
  455.  } bdef
  456.  
  457. % The state dictionary for the embedded Type 1 font reading procedure
  458. % has the following keys and values:
  459. %    data - stream (filter)
  460. %    buffer, buffer2 - string
  461. %    hexify - procedure to convert buffer to hex if needed
  462. %    leftstr - string containing (non-negative) integer
  463. %    sectionstr - string containing a character 0 .. 3
  464. %    stream - (stream) dictionary
  465. %    proc - procedure of the form {-dict- type1read}
  466. %       pfbhdr - string containing 16#80 if PFB, 0 otherwise
  467. % When the procedure is executing, this dictionary is current.
  468. % leftstr and sectionstr are strings so that we can change their values
  469. % reliably in case the font executes a restore!
  470. % We also have to do something special about embedded fonts that
  471. % execute definefont more than once -- that is the function of topFontDict.
  472.  
  473. % Read an embedded Type 1 font.
  474. /readfontfilter {    % <proc> readfontfilter <filter>
  475.   0 () /SubFileDecode filter
  476. } bdef
  477. /readtype1dict 5 dict dup begin
  478.   /definefont {
  479.     dup topFontDict eq topFontDict null eq or {
  480.       dup wcheck not { dup length dict copy } if
  481.       exch pop savedFontName exch
  482.     } if
  483.     //systemdict /definefont get exec
  484.   } bdef
  485.   /eexec {
  486.     % Assume the font dictionary is directly below the file on the stack
  487.     count 0 gt { /topFontDict 2 index cvlit store } if
  488.     //.eexec_param_dict /eexecDecode filter
  489.     //systemdict begin readtype1dictcopy begin cvx stopped
  490.     currentdict readtype1dictcopy eq { end } if
  491.     currentdict //systemdict eq { end } if
  492.      { stop } if
  493.   } bdef
  494.  
  495.   /undef_proc_warning {
  496.     (   **** Embedded font uses undefined procedure ) pdfformaterror
  497.         .namestring pdfformaterror (\n) pdfformaterror
  498.   } bdef
  499.  
  500.   /-| { string currentfile exch readstring pop /-| undef_proc_warning } executeonly bdef
  501.   /RD { string currentfile exch readstring pop /RD undef_proc_warning } executeonly bdef
  502.   /|- { noaccess def /|- undef_proc_warning } executeonly bdef
  503.   /ND { noaccess def /ND undef_proc_warning } executeonly bdef
  504.   /|  { noaccess put /|  undef_proc_warning } executeonly bdef
  505.   /NP { noaccess put /NP undef_proc_warning } executeonly bdef
  506.  
  507. end readonly def
  508. /readtype1 {        % <font-resource> <stream-dict> readtype1 <font>
  509.         % Read the definition, using a procedure-based filter
  510.         % that turns binary/hex conversion on and off
  511.         % at the right times.
  512.    1 index exch
  513.    PDFfile fileposition 3 1 roll
  514.    11 dict begin
  515.      /leftstr (          ) 10 string copy def
  516.        dup /Length1 oget leftstr cvs pop
  517.      /sectionstr <00> 1 string copy def
  518.      /pfbhdr <00> 1 string copy def
  519.      /stream 1 index def
  520.      true resolvestream /data exch def
  521.      /buffer 1000 string def        % arbitrary
  522.      /buffer2 buffer length 2.1 div cvi 1 sub string def
  523.      /hexify /buf2hex load def
  524.    currentdict end
  525.    /type1read cvx 2 array astore cvx dup 0 get /proc 2 index put
  526.    readfontfilter
  527.         % Some buggy embedded fonts leave extra junk on the stack,
  528.         % so we have to make a closure that records the stack depth
  529.         % in a fail-safe way. Also restore dictstack depth.
  530.    //systemdict begin
  531.         % The PDF specification is somewhat muddy about whether
  532.         % an embedded font's name is supposed to be the BaseFont
  533.         % from the Font object or the FontName from the descriptor.
  534.         % Acrobat Distiller requires the former.  Save away the
  535.         % name so we can substitute it at definefont time.
  536.    //readtype1dict dup length 3 add dict copy begin
  537.    1 index /BaseFont oget /savedFontName exch def
  538.    /topFontDict null def
  539.    /readtype1dictcopy currentdict def
  540.     { run } aload pop count 1 sub 2 packedarray cvx exec
  541.     % clean up the dictstack
  542.     { currentdict /topFontDict known not { end } { end end exit } ifelse } loop
  543.    count exch sub { pop } repeat
  544.    PDFfile 3 -1 roll setfileposition
  545.    /BaseFont oget pdfaddcachedfont
  546.    exch pop
  547.  } bdef
  548.  
  549. % Execute the appropriate reading procedure.
  550. /type1read        % <dict> type1read <string>
  551.  { begin leftstr cvi
  552.     { type1read0 type1read1 type1read2 type1read3 } sectionstr 0 get get exec
  553.    (          ) leftstr copy cvs pop end
  554.  } bdef
  555.  
  556. % Read the next block of data into the buffer.
  557. /type1readdata        % <left> <buffer> type1readdata <substring> <left'>
  558.  { 0 2 index 2 index length .min getinterval
  559.         % Adobe requires readstring to signal an error if given
  560.         % an empty string.  Work around this nonsense here.
  561.    dup length 0 ne { data exch readstring pop } if
  562.    dup length 3 -1 roll exch sub
  563.    PDFDEBUG
  564.     { dup =only ( read ) print
  565.       1 index length =only (: ) print
  566.       1 index == flush
  567.     } if
  568.  } bdef
  569.  
  570. % Read the initial byte to see if we need to skip a 6 byte PFB header
  571. /type1read0 {         % <left> type1read0 <string> <left'>
  572.   sectionstr 0 1 put    % either way we go to the next stage
  573.   pfbhdr type1readdata
  574.   1 index 0 get 16#80 eq {
  575.     (   **** Warning: Embedded Type1 font in PFB format is not valid PDF.\n)
  576.     pdfformaterror
  577.     PDFDEBUG { (skipping PFB header) = flush } if
  578.     exch pop buffer 0 5 getinterval type1readdata exch
  579.     dup 4 get 256 mul 1 index 3 get add 256 mul
  580.     1 index 2 get add 256 mul 1 index 1 get add
  581.     PDFDEBUG { (PFB segment length = ) print dup = } if
  582.     exch pop  % discard the string keeping the PFB segment length
  583.     2 copy ne {
  584.       (   **** Warning: Type 1 PFB segment length and Length 1 value do not match.\n)
  585.       pdfformaterror
  586.       exch     % keep the PFB length instead
  587.     } if
  588.     pop
  589.     buffer type1readdata    % go ahead and read a block
  590.   }
  591.   if    % if not PFB, return pfbhdr string (first char of file, usually %).
  592. } bdef
  593.  
  594. % Read the next block of the initial text portion.
  595. /type1read1 {        % <left> type1read1 <string> <left'>
  596.   PDFDEBUG { (read1 ) print } if
  597.   dup 0 eq {
  598.     pop sectionstr 0 2 put
  599.     stream /Length2 oget
  600.             % Determine whether to hexify data for eexec.
  601.     dup 8 lt {
  602.       type1read2    % Hexify.
  603.     } {
  604.       PDFDEBUG { (read2 ) print } if
  605.       pfbhdr 0 get 16#80 eq {
  606.         % eat 6 more bytes of PFB junk before proceeding
  607.     PDFDEBUG { (skipping PFB header in segment 2) = flush } if
  608.     buffer 0 6 getinterval type1readdata exch
  609.         dup 5 get 256 mul 1 index 4 get add 256 mul
  610.     1 index 3 get add 256 mul 1 index 2 get add
  611.         PDFDEBUG { (PFB segment length = ) print dup = } if
  612.     exch pop  % discard the string keeping the PFB segment length
  613.     2 copy ne {
  614.           (   **** Warning: Type 1 PFB segment length and Length 2 value do not match.\n)
  615.           pdfformaterror
  616.       exch         % keep the PFB length instead
  617.     } if
  618.       pop
  619.       } if
  620.       buffer2 type1readdata exch
  621.             % The check doesn't have to be 100% accurate:
  622.             % hexifying is always OK.
  623.       dup 0 8 getinterval 0 exch { or } forall
  624.       128 ge {
  625.     /hexify { } store
  626.     /buffer2 buffer def    % We don't need an intermediate buffer.
  627.       } if hexify exch
  628.     } ifelse
  629.   } {
  630.     buffer type1readdata
  631.   } ifelse
  632. } bdef
  633.  
  634. % Convert a string from binary to hex for eexec.
  635. % Free variables: buffer.
  636. /buf2hex {        % <string> buf2hex <hexstring>
  637.   buffer /ASCIIHexEncode filter dup 3 -1 roll writestring closefile
  638.   buffer (>) search pop exch pop exch pop
  639. } bdef
  640.  
  641. % Read the next block of the encrypted portion.
  642. /type1trailer
  643. (0000000000000000000000000000000000000000000000000000000000000000\n\
  644. 0000000000000000000000000000000000000000000000000000000000000000\n\
  645. 0000000000000000000000000000000000000000000000000000000000000000\n\
  646. 0000000000000000000000000000000000000000000000000000000000000000\n\
  647. 0000000000000000000000000000000000000000000000000000000000000000\n\
  648. 0000000000000000000000000000000000000000000000000000000000000000\n\
  649. 0000000000000000000000000000000000000000000000000000000000000000\n\
  650. 0000000000000000000000000000000000000000000000000000000000000000\n\
  651. cleartomark\n)
  652. readonly def
  653. /type1read2 {        % <left> type1read2 <string> <left'>
  654.   PDFDEBUG { (read2 ) print } if
  655.    dup 0 eq
  656.     { pop sectionstr 0 3 put
  657.       stream /Length3 oget
  658.       dup 0 eq
  659.        { PDFDEBUG { (trailer ) print } if
  660.      type1trailer exch
  661.        }
  662.        { 
  663.          pfbhdr 0 get 16#80 eq {
  664.            % eat 6 more bytes of PFB junk before proceeding
  665.        PDFDEBUG { (skipping PFB header in segment 3) = flush } if
  666.        buffer 0 6 getinterval type1readdata exch
  667.            dup 5 get 256 mul 1 index 4 get add 256 mul
  668.        1 index 3 get add 256 mul 1 index 2 get add
  669.            PDFDEBUG { (PFB segment length = ) print dup = } if
  670.        exch pop  % discard the string keeping the PFB segment length
  671.        2 copy ne {
  672.            (   **** Warning: Type 1 PFB segment length and Length 3 value do not match.\n)
  673.            pdfformaterror
  674.          exch     % keep the PFB length instead
  675.        } if
  676.        pop
  677.          } if
  678.          type1read3
  679.        }
  680.       ifelse
  681.     }
  682.     { buffer2 type1readdata exch hexify exch
  683.     }
  684.    ifelse
  685. } bdef
  686.  
  687. % Read the next block of the final text portion.
  688. % When finished, this procedure returns an empty string.
  689. /type1read3        % <left> type1read3 <string> <left'>
  690.  { PDFDEBUG { (read3 ) print } if
  691.    buffer type1readdata
  692.  } bdef
  693.  
  694. % ---------------- Type 3 fonts ---------------- %
  695.  
  696. /buildType3 {        % <Type3-font-resource> buildType3 <font>
  697.   8 dict begin
  698.     /FontType 3 def
  699.     /Resources 1 index /Resources knownoget { oforce } { 0 dict } ifelse def
  700.     /FontBBox 1 index /FontBBox get cvx def
  701.     /FontMatrix 1 index /FontMatrix oget def
  702.     /CharProcs 1 index /CharProcs oget def
  703.     1 index /Widths knownoget {
  704.       /Widths exch def
  705.       /FirstChar 1 index /FirstChar oget def
  706.       /LastChar 1 index /LastChar oget def
  707.     } if
  708.     /FontName 1 index /Name .knownget not { 
  709.        PDFfile fileposition 16 10 string cvrs cvn
  710.     } if def
  711.  
  712.     /Encoding .notdefEncoding 2 index getencoding def
  713.         % We have to define BuildChar rather than BuildGlyph:
  714.         % there is no PDF equivalent of glyphshow, and we need
  715.         % the character code to access the Widths.
  716.     /BuildChar {
  717.         % Stack: font charcode
  718.       1 index begin 3 dict begin
  719.       /Font 3 -1 roll def /CharCode 1 index def
  720.       % Make unknown characters map to /.notdef
  721.       Encoding exch get dup CharProcs exch known
  722.         { CharProcs exch oget }
  723.     { pop CharProcs /.notdef oget }
  724.       ifelse
  725.       PDFfile fileposition exch
  726.       false resolvestream
  727.         % Stack: filepos stream
  728.         % Don't let setgcolor set the color inside the BuildGlyph
  729.         % procedure, because this causes an /undefined error.
  730.       q null /FillColor gput null /StrokeColor gput
  731.       Font /Resources get exch pdfopdict .pdfruncontext
  732.       Q
  733.       PDFfile exch setfileposition
  734.       end end
  735.     } bdef
  736.     FontName currentdict end definefont exch pop
  737. } bdef
  738. /.adjustcharwidth {    % <wx> <wy> .adjustcharwidth <wx'> <wy'>
  739.   /Widths where {
  740.     begin
  741.     CharCode FirstChar ge CharCode LastChar le and {
  742.       exch pop Widths CharCode FirstChar sub get exch
  743.     } if end
  744.   } if
  745. } bdef
  746.  
  747. % ---------------- TrueType fonts ---------------- %
  748.  
  749. /TTfonts mark
  750.   /Arial /Helvetica
  751.   /Arial,Italic /Helvetica-Oblique
  752.   /Arial,Bold /Helvetica-Bold
  753.   /Arial,BoldItalic /Helvetica-BoldOblique
  754.   /CourierNew /Courier
  755.   /CourierNew,Bold /Courier-Bold
  756.   /TimesNewRoman /Times-Roman
  757.   /TimesNewRoman,Italic /Times-Italic
  758.   /TimesNewRoman,Bold /Times-Bold
  759.   /TimesNewRoman,BoldItalic /Times-BoldItalic
  760. .dicttomark readonly def
  761.  
  762. /buildTrueType {    % <TrueType-font-resource> buildTrueType <font>
  763.   dup /BaseFont oget
  764.   (   **** Warning: Fonts with Subtype = /TrueType should be embedded.\n) pdfformaterror
  765.   (                 But ) pdfformaterror dup =string cvs pdfformaterror ( is not embedded.\n) pdfformaterror
  766.   dup TTfonts exch .knownget {
  767.     QUIET not {
  768.       (Substituting font ) print dup =only
  769.       ( for ) print 1 index =only (.) = flush
  770.     } if
  771.     exch 3 1 roll pdffindfont
  772.     true .copyfontdict
  773.     2 copy exch /FontName exch put
  774.     definefont
  775.   } {
  776.     pdffindfont
  777.   } ifelse
  778. } bdef
  779.  
  780. % Read an embedded TrueType font.
  781. /readtruetype {        % <font-resource> <stream-dict> readtruetype <font>
  782.         % This is much simpler than readtype1, because we don't
  783.         % have to deal with the tripartite .PFB format.
  784.   1 index exch
  785.   PDFfile fileposition 3 1 roll
  786.   true resolvestream readfontfilter
  787.         % Stack: filepos fontres stream
  788.   1 index /Subtype get /CIDFontType2 eq {
  789.     .loadttcidfont
  790.         % Stack: filepos fontres cidfont
  791.   } {
  792.                                   % filepos fontres stream
  793.     1 index /FontDescriptor oget          % filepos fontres stream fd   
  794.     /Flags get 4 and 0 ne                 % filepos fontres stream is_symbolic
  795.     dup {
  796.       2 index null exch getencoding       % filepos fontres stream is_symbolic Encoding
  797.       dup 4 index exch                    % filepos fontres stream is_symbolic Encoding fontres Encoding
  798.       /prebuilt_encoding exch put         % filepos fontres stream is_symbolic Encoding
  799.     } {
  800.       null
  801.     } ifelse
  802.     .loadpdfttfont
  803.   } ifelse
  804.   exch pop
  805.   PDFfile 3 -1 roll setfileposition
  806.         % Ignore both the Encoding and the Widths.
  807.   exch pop
  808. } bdef
  809.  
  810. % ---------------- Type 0 fonts ---------------- %
  811.  
  812. % Predefine the known CMaps, but only create them on demand.
  813. /knownCMaps mark
  814.   /Identity-H { /Identity-H 0 makeIdentityCMap }
  815.   /Identity-V { /Identity-V 1 makeIdentityCMap }
  816. .dicttomark def
  817.  
  818. /makeIdentityCMap {        % <cmapname> <wmode> .makeIdentityCMap -
  819.   .currentglobal true .setglobal 3 1 roll
  820.   /CIDInit /ProcSet findresource begin
  821.   12 dict begin
  822.     begincmap
  823.     /WMode exch def
  824.     /CMapName exch def
  825.     /CIDSystemInfo 3 dict dup begin
  826.       /Registry (Adobe) def
  827.       /Ordering (Identity) def
  828.       /Supplement 0 def
  829.     end def
  830.     %/CMapName (see above)
  831.     /CMapVersion 1 def
  832.     /CMapType 1 def
  833.     %WMode (see above)
  834.     % The PDF documentation says that these CMaps map CIDs
  835.     % "1 to 65,536".  This is a misprint for 0 to 65,535.
  836.     1 begincodespacerange
  837.     % <0001> <00ff>  <0100> <ffff>
  838.       <0000> <ffff>
  839.     endcodespacerange
  840.     1 begincidrange
  841.     % <0001> <00ff> 1   <0100> <ffff> 256
  842.       <0000> <ffff> 0
  843.     endcidrange
  844.     endcmap
  845.     CMapName currentdict /CMap defineresource
  846.     knownCMaps CMapName 2 index put
  847.   end        % CMap
  848.   end        % CIDInit ProcSet
  849.   exch .setglobal
  850. } bdef
  851.  
  852. /buildType0 {        % <Type0-font-resource> buildType0 <font>
  853.   dup /BaseFont get    % FontName
  854.   1 index /Encoding oget
  855.   dup type /nametype eq {
  856.     dup /CMap resourcestatus {
  857.     pop pop /CMap findresource
  858.     } {
  859.     knownCMaps 1 index .knownget
  860.       { exch pop exec } { /undefined signalerror } ifelse
  861.     } ifelse
  862.   } {
  863.     PDFfile fileposition exch
  864.     dup /CMapName get exch true resolvestream cvx exec
  865.     /CMap findresource
  866.     exch PDFfile exch setfileposition
  867.   } ifelse        % CMap
  868.   [
  869.     3 index /DescendantFonts oget { exec resourcefont } forall
  870.   ]            % subfonts
  871.   composefont
  872.         % Stack: fontres font
  873.   1 index /FontMatrix knownoget {
  874.     dup aload pop true {0 0 1 0 0 1} {3 -1 roll eq and} forall {
  875.       1 index exch makefont exch /FontName get exch definefont
  876.     } {
  877.       pop
  878.     } ifelse
  879.   } if exch pop
  880. } bdef
  881.  
  882. % ---------------- CIDFontType0/2 fonts ---------------- %
  883.  
  884. % Insert metrics into a CIDFont, by saving the PDF W, W2, DW, and DW2
  885. % arrays and using a (currently very inefficient) CDevProc.
  886. % For detail, refer "PDF Reference" 2nd ed., p314 "5.6.3 CIDFonts".
  887. % It notes default DW is 0, but Acrobat Reader uses 1000 as default.
  888. % If DW is 0, currentpoint does not move by default in rendering text
  889. % horizontally, the result is unreadable. You can check it by Acrobat.
  890.  
  891. /.pdfDefaultDW  1000 def
  892. /.pdfDefaultDW2 [ 880 -1000 ] def
  893.  
  894. /addCIDmetrics {    % <CIDFont-resource> <CIDFont> addCIDmetrics <fontdict>
  895.   dup length 5 add dict .copydict
  896.   dup /FID undef
  897.   dup /UniqueID undef
  898.   dup /XUID undef
  899.     % Insert the widths into the font.
  900.  
  901.         % Stack: pdfresource newfont
  902.  
  903.   1 index /DW .knownget {
  904.     1 index /DW 3 -1 roll put
  905.   } {
  906.     dup /DW .pdfDefaultDW put
  907.   } ifelse
  908.  
  909.   1 index /W .knownget {
  910.     dup 2 index /W 3 -1 roll put
  911.     .pdfMakeInternalW 1 index /.internalW 3 -1 roll put
  912.   } if
  913.  
  914.   1 index /DW2 .knownget {
  915.     1 index /DW2 3 -1 roll put
  916.   } {
  917.     dup /DW2 .pdfDefaultDW2 put
  918.   } ifelse
  919.  
  920.   1 index /W2 .knownget {
  921.     dup 2 index /W2 3 -1 roll put
  922.     .pdfMakeInternalW2 1 index /.internalW2 3 -1 roll put
  923.   } if
  924.  
  925.   dup /CDevProc 1 index /CIDWProc load /exec load 3 packedarray cvx put
  926.   exch pop
  927. } bdef
  928.  
  929. /.pdfMakeInternalMTXArray { % <mtx_array> <item_size> .pdfConvertInternalW <mtx_array'>
  930.  
  931.   % convert /W or /W2 to internal expression
  932.   %
  933.   %   mtx_array: original /W or /W2 array
  934.   %   item_size: number of metrics values per CID
  935.   %
  936.   %   for detail of the metrics list format in PDF,
  937.   %   refer PDF Ref. p.317 "Glyph Metrics in CIDFonts".
  938.   % 
  939.   %   format of single entry in internal expression
  940.   %
  941.   %     [
  942.   %       [cid_begin cid_end]
  943.   %       value_is_varied (bool)
  944.   %       [ [values for cid_begin...]
  945.   %         [values for cid_begin + 1]
  946.   %         ... ]
  947.   %     ]
  948.   %
  949.  
  950.   7 dict
  951.   begin
  952.     /itemSize exch def
  953.     /M exch def            % original /W or /W2
  954.     /Msize M length def
  955.     /Mi { M i get } def        % W[i]
  956.     /Mi1 { M i 1 add get } def    % W[i + 1]
  957.     /putMTXEntry <<
  958.       /arraytype   {
  959.          [
  960.            [Mi Mi Mi1 length itemSize idiv add 1 sub]
  961.            true
  962.            [
  963.              0 itemSize Mi1 length 1 sub {
  964.                [ exch 1 1 index itemSize add 1 sub { Mi1 exch get } for ]
  965.              } for
  966.            ]
  967.          ]
  968.          /i i 2 add def
  969.       }
  970.       /integertype {
  971.          [
  972.            [Mi Mi1]
  973.            false
  974.            [[ i 2 add 1 i 1 add itemSize add { M exch get } for ]]
  975.          ]
  976.          /i i 3 add def
  977.       }
  978.     >> def
  979.  
  980.     /i 0 def
  981.  
  982.     [ { putMTXEntry Mi1 type get exec i Msize ge { exit } if } loop ]
  983.   end
  984. } def
  985.  
  986. /.pdfMakeInternalW  { dup length 0 gt { 1 .pdfMakeInternalMTXArray } if } def
  987. /.pdfMakeInternalW2 { dup length 0 gt { 3 .pdfMakeInternalMTXArray } if } def
  988.  
  989. /.pdfGetMTXByCID { % <internalMTXArray> <cid>
  990.                    %     .pdfGetMTXByCID
  991.                    %         { <MTXEntry> true | false }
  992.  
  993.   % get values for given CID from internal format of /W or /W2
  994.  
  995.   exch
  996.   {
  997.     {
  998.       dup 0 get {} forall      % Stack: <cid> <entry> <cid_0> <cid_1>
  999.       3 index lt { pop pop false exit } if
  1000.       2 index exch sub dup 0 lt { pop pop false exit } if
  1001.       1 index 1 get not { pop 0 } if
  1002.       exch 2 get exch get true exit
  1003.     } loop
  1004.     { exit } if
  1005.   } forall
  1006.   dup type /arraytype eq { exch pop true } { pop false } ifelse
  1007. } def
  1008.  
  1009.  
  1010. % Apply the [D]W[2] metrics to a character before displaying.
  1011. /CIDWProc {        % <w0x> <w0y> <llx> <lly> <urx> <ury>
  1012.             %   <w1x> <w1y> <vx> <vy> <cid> <font> CIDWproc
  1013.             %   <w0x'> ... <vy'>
  1014.   begin % push <font> to currentdict
  1015.     % <w1x> <w1y> <vx> <vy> won't be used and replaced, discard now
  1016.     5 1 roll pop pop pop pop
  1017.  
  1018.     {
  1019.       currentdict /DW .knownget not {   % no DW
  1020.         .pdfDefaultDW exit              % replace <w0x> by defaultDW
  1021.       } if
  1022.  
  1023.       currentdict /.internalW .knownget not {    % no W
  1024.         exit                            % use already-stacked DW
  1025.       } if
  1026.  
  1027.       dup length 0 eq {                 % W is null array
  1028.         pop                             % discard unusable W
  1029.         exit                            % use already-stacked DW
  1030.       } if
  1031.  
  1032.       % W is finite array, try to get W_cid
  1033.       2 index .pdfGetMTXByCID {           % got W, discard DW
  1034.         exch pop {} forall
  1035.         exit
  1036.       } if
  1037.  
  1038.       exit
  1039.     } loop
  1040.  
  1041.     FontType 11 eq {
  1042.       1000 div                  % <w0x'> (normalized W)
  1043.     } if
  1044.     0                           % <w0y'>
  1045.  
  1046.     % Stack: <w0x> <w0y> <llx> <lly> <urx> <ury> <cid> <w0x'> <w0y'>
  1047.     9 -2 roll pop pop           % discard <w0x> <w0y>
  1048.     7  2 roll                   % put <w0x'> <w0y'>
  1049.  
  1050.     % Stack: <w0x'> <w0y'> <llx> <lly> <urx> <ury> <cid>
  1051.     0                           % <w1x'>
  1052.     exch                        % put <w1x'>
  1053.  
  1054.     % Stack: <w0x'> <w0y'> <llx> <lly> <urx> <ury> <w1x'> <cid>
  1055.     {
  1056.       currentdict /DW2 .knownget not {  % no DW2, use defaultDW2
  1057.         .pdfDefaultDW2 exit
  1058.       } if
  1059.  
  1060.       currentdict /.internalW2 .knownget not {   % has DW2, no W2
  1061.         exit                            % use already-stacked DW2
  1062.       } if
  1063.  
  1064.       dup length 0 eq {                 % W2 is null array
  1065.         pop                             % discard unusable W2
  1066.         exit                            % use already-stacked DW2
  1067.       } if
  1068.  
  1069.       2 index .pdfGetMTXByCID {        % got W2_cid, discard DW2
  1070.         exch pop
  1071.         exit
  1072.       } if
  1073.  
  1074.       % could not get W2_cid
  1075.       exit
  1076.  
  1077.     } loop
  1078.  
  1079.     exch pop                            % discard <cid>
  1080.  
  1081.     % Stack: <w0x'> <w0y'> <llx> <lly> <urx> <ury> <w1x'> { [<vy'> <w1y'>] | [<w1y'> <vx'> <vy'>] }
  1082.     dup length 2 eq {                   % this is DW2
  1083.       FontType 11 eq {{1000 div}} {{}} ifelse forall exch
  1084.       8 index 2 div                     % <vx'> = <w0x'> / 2
  1085.       exch
  1086.     }{                                  % assume W2
  1087.       FontType 11 eq {{1000 div}} {{}} ifelse forall
  1088.     } ifelse
  1089.   end                                   % recover currentdict
  1090.  
  1091. } def
  1092.  
  1093. % <string> <match> tailmatch ==> <pre> true
  1094. %                            ==> <string> false
  1095. /tailmatch {
  1096.   2 copy length 1 index length .min
  1097.   dup 2 index length exch sub exch getinterval
  1098.   1 index eq {
  1099.     length 1 index length exch sub
  1100.     0 exch getinterval true
  1101.   } {
  1102.     pop false
  1103.   } ifelse
  1104. } bind def
  1105.  
  1106. /makeboldfont {
  1107.   16 dict begin
  1108.     /strokewidth exch def
  1109.     /basecidfont exch def
  1110.     /FontMatrix [ 1 0 0 1 0 0 ] def
  1111.  
  1112.     /CIDFontName /.boldfont def
  1113.     /CIDFontType 1 def
  1114.  
  1115.     /basefont-H /.basefont-H /Identity-H [ basecidfont ] composefont def
  1116.     /basefont-V /.basefont-V /Identity-V [ basecidfont ] composefont def
  1117.  
  1118.     /CIDSystemInfo dup basecidfont exch get def
  1119.     /FontBBox [ basecidfont /FontBBox get cvx exec
  1120.       4 2 roll basecidfont /FontMatrix get transform
  1121.       4 2 roll basecidfont /FontMatrix get transform
  1122.     ] def
  1123.  
  1124.     /tmpstr 2 string def
  1125.     /BuildGlyph {
  1126.       gsave
  1127.       exch begin
  1128.         dup 256 idiv tmpstr exch 0 exch put
  1129.         256 mod tmpstr exch 1 exch put
  1130.         rootfont /WMode known { rootfont /WMode get 1 eq } { false } ifelse
  1131.         { basefont-V } { basefont-H } ifelse setfont
  1132.         strokewidth setlinewidth
  1133.         1 setlinejoin
  1134.         newpath
  1135.         0 0 moveto tmpstr false charpath stroke
  1136.         0 0 moveto tmpstr show
  1137.         currentpoint setcharwidth
  1138.       end
  1139.       grestore
  1140.     } bind def
  1141.  
  1142.    currentdict
  1143.   end
  1144.   dup /CIDFontName get exch /CIDFont defineresource
  1145. } bind def
  1146.  
  1147. % <CIDFont-resource> <CIDFontName> findCIDFont <CIDFont-resource> <font>
  1148. %   CIDFont-resource is not modified.
  1149. /findCIDFont {
  1150.   {
  1151.     dup /CIDFont resourcestatus {
  1152.       pop pop /CIDFont findresource
  1153.       exit
  1154.     } if
  1155.     .remove_font_name_prefix
  1156.     dup dup length string cvs
  1157.     (,Bold) tailmatch {
  1158.       exch pop
  1159.       cvn findCIDFont 0.03 makeboldfont
  1160.       exit
  1161.     } if
  1162.     (,Italic) tailmatch {
  1163.       exch pop
  1164.       cvn findCIDFont
  1165.       [ 1 0 0.3 1 0 0 ] makefont
  1166.       exit
  1167.     } if
  1168.     (,BoldItalic) tailmatch {
  1169.       exch pop
  1170.       cvn findCIDFont 0.03 makeboldfont
  1171.       [ 1 0 0.3 1 0 0 ] makefont
  1172.       exit
  1173.     } if
  1174.     pop
  1175.  
  1176.     1 index /CIDSystemInfo get begin Registry (-) Ordering end
  1177.     concatstrings concatstrings
  1178.     cvn
  1179.     QUIET not {
  1180.       (Substituting CID font resource) print dup ==only
  1181.       ( for ) print 1 index ==only (.\n) print
  1182.     } if
  1183.     exch pop
  1184.     /CIDFont findresource
  1185.     exit
  1186.   } loop
  1187. } bdef
  1188.  
  1189. /buildCIDType0 {    % <CIDFontType0-font-resource> buildCIDType0 <font>
  1190.   dup /BaseFont get findCIDFont exch pop
  1191. } bdef
  1192.  
  1193. /buildCIDType2 {    % <CIDFontType2-font-resource> buildCIDType2 <font>
  1194.   dup /BaseFont get findCIDFont exch pop
  1195. } bdef
  1196.  
  1197. /processCIDToGIDMap { % <fontres> <cidfont> processCIDToGIDMap <fontres> <cidfont>
  1198.   1 index /CIDToGIDMap knownoget {
  1199.     PDFfile fileposition 4 1 roll
  1200.     dup /Identity eq {
  1201.       pop
  1202.     } {
  1203.       true resolvestream
  1204.         % Stack: filepos fontres font mapstream
  1205.     % Can't know the length of the decompressed stream, so allocate a big buffer...
  1206.       dup 65534 string readstring {
  1207.       % Length exceeded max string size, use an array of two strings
  1208.         1 index 65534 string readstring pop   % maybe a null string - not important.
  1209.         2 array astore
  1210.                     % Stack: filepos fontres font mapstream array
  1211.            dup 1 get length 65534 add
  1212.       } {
  1213.         dup length
  1214.         } ifelse
  1215.       2 idiv
  1216.         % Stack: filepos fontres font mapstream array/string CIDCount
  1217.       3 index exch /CIDCount exch put
  1218.       exch closefile exch
  1219.       dup /CIDMap 4 -1 roll put
  1220.     } ifelse
  1221.     3 2 roll PDFfile exch setfileposition
  1222.   } if
  1223. } bdef
  1224.  
  1225. % Adjust a CIDFontType0 DW[2] in the font resource.
  1226. /adjustCIDType0 {        % <font-resource> <font> adjustfont <font'>
  1227.   addCIDmetrics
  1228.   dup /CIDFontName get exch /CIDFont defineresource
  1229. } bind def
  1230.  
  1231. % Adjust a CIDFontType2 DW[2] and CIDToGIDMap in the font resource.
  1232. /adjustCIDType2 {        % <font-resource> <font> adjustfont <font'>
  1233.   addCIDmetrics
  1234.   processCIDToGIDMap
  1235.   dup /CIDFontName get exch /CIDFont defineresource
  1236. } bind def
  1237.  
  1238. % ---------------- Other embedded fonts ---------------- %
  1239.  
  1240. /fontloadprocs mark
  1241.   /Type1C /readType1C cvx
  1242.   /CIDFontType0C /readCIDFontType0C cvx
  1243. .dicttomark readonly def
  1244.  
  1245. % Read an embedded compressed font.
  1246. /readType1C {        % <font-resource> <stream-dict> readType1C <font>
  1247.   1 index exch
  1248.   PDFfile fileposition 3 1 roll
  1249.   dup true resolvestream dup readfontfilter
  1250.         % Stack: pos resource streamdict stream filter
  1251.   3 index /FontDescriptor oget /FontName oget
  1252.   1 index FRD
  1253.   closefile closefile pop
  1254.   PDFfile 3 -1 roll setfileposition
  1255.   /FontDescriptor oget /FontName oget pdfaddcachedfont
  1256.   exch pop
  1257. } bdef
  1258.  
  1259. % Read an embedded CFF CIDFont.
  1260. /readCIDFontType0C {  % <font-resource> <stream-dict> readCIDFontType0C <font>
  1261.   PDFfile fileposition 3 1 roll
  1262.   dup true resolvestream dup readfontfilter
  1263.         % Stack: pos resource streamdict stream filter
  1264.   3 index /FontDescriptor oget /FontName oget
  1265.   1 index FRD
  1266.   closefile closefile pop
  1267.   PDFfile 3 -1 roll setfileposition
  1268.         % Some broken Adobe software produces PDF files in which
  1269.         % the FontName of the CFF font and the FontName in the
  1270.         % FontDescriptor don't match the BaseFont in the font.
  1271.         % Use the FontName, rather than the BaseFont, here.
  1272.   dup /FontDescriptor oget /FontName oget /CIDFont findresource
  1273.   addCIDmetrics dup /CIDFontName get exch /CIDFont defineresource
  1274. } bdef
  1275.  
  1276. % ---------------- Font lookup ---------------- %
  1277.  
  1278. /fonttypeprocs mark        % <font-resource> -proc- <font>
  1279.   /Type0 //buildType0
  1280.   /Type1 //buildType1
  1281.   /MMType1 //buildType1
  1282.   /Type3 //buildType3
  1283.   /TrueType //buildTrueType
  1284.   /CIDFontType0 //buildCIDType0
  1285.   /CIDFontType2 //buildCIDType2
  1286. .dicttomark readonly def
  1287.  
  1288. /adjustfonttypes mark
  1289.   /Type1 //adjustfont
  1290.   /MMType1 //adjustfont
  1291.   /TrueType //adjustfont
  1292.   /CIDFontType0 //adjustCIDType0
  1293.   /CIDFontType2 //adjustCIDType2
  1294. .dicttomark readonly def
  1295.  
  1296. /resourcefont            % <font-resource> resourcefont <font>
  1297. { dup /PSFont .knownget
  1298.   { /FID knownoget { type /fonttype eq } { //false } ifelse }
  1299.   { //false }
  1300.   ifelse
  1301.   { /PSFont get }
  1302.   { dup dup /FontDescriptor knownoget {    % Stack: font-res font-res font-desc
  1303.       dup /FontObject .knownget {
  1304.     3 1 roll pop pop
  1305.       } {
  1306.     dup /FontFile knownoget
  1307.     { dup /Length oget 0 eq
  1308.       { pop pop dup /Subtype get fonttypeprocs exch get exec }
  1309.       { exch pop readtype1 }
  1310.       ifelse
  1311.     }
  1312.     {
  1313.       dup /FontFile2 knownoget
  1314.       { exch pop readtruetype }
  1315.       { /FontFile3 knownoget
  1316.         { dup /Subtype get fontloadprocs exch get exec }
  1317.             { dup /Subtype get fonttypeprocs exch get exec }
  1318.         ifelse
  1319.       }
  1320.       ifelse
  1321.     }
  1322.     ifelse
  1323.     1 index /FontDescriptor oget
  1324.     1 index /FontObject exch put        % Save pointer to the font
  1325.       }
  1326.       ifelse
  1327.     }
  1328.     { dup /Subtype get fonttypeprocs exch dup () cvn eq {
  1329.         (   **** Warning: Font missing required Subtype, /Type1 assumed.\n)
  1330.         pdfformaterror
  1331.         pop /Type1
  1332.       } if get exec
  1333.     }
  1334.     ifelse
  1335.     % Stack: font-res font
  1336.     1 index 3 1 roll
  1337.     1 index /Subtype get
  1338.     //adjustfonttypes exch .knownget { exec } { exch pop } ifelse
  1339.     dup 3 1 roll /PSFont exch put
  1340.   }
  1341.   ifelse
  1342. } bdef
  1343.  
  1344. drawopdict begin
  1345.   /d0 {
  1346.     .adjustcharwidth setcharwidth
  1347.   } bdef
  1348.   /d1 {
  1349.     4 index 0 ne {
  1350.       % invalid wy parameter for d1 in Type3 font (must be 0)
  1351.       % Even though the PDF 1.4 specification states that this must be 0,
  1352.       % Distiller sometimes creates Type3 fonts with non-zero wy. We set
  1353.       % it to 0 since this is apparently what Acrobat Reader 4 and 5 do,
  1354.       % but if the specification is ever changed to allow non-zero wy, this
  1355.       % will not work.
  1356.       5 -1 roll pop 0 5 1 roll      % set wy to 0
  1357.     } if
  1358.  
  1359.     2 copy                           % ... llx lly urx ury | urx ury 
  1360.     0 ne exch 0 ne                   % ... llx lly urx ury | ury!=0 urx!=0
  1361.     3 index 6 index eq and           % ... llx lly urx ury | ury!=0 (urx!=0 && llx==urx)
  1362.     exch 2 index 5 index eq and or { % ... llx lly urx ury | (urx!=0 && llx==urx) || (ury!=0 && lly==ury)
  1363.       % The bounding box is empty and likely incorrect. Don't cache.
  1364.       pop pop pop pop .adjustcharwidth setcharwidth
  1365.     } {
  1366.       6 -2 roll .adjustcharwidth 6 2 roll setcachedevice
  1367.     } ifelse
  1368.   } bdef
  1369.   /Tf {
  1370.     1 index Page /Font rget not { 1 index /invalidfont signalerror } if
  1371.     resourcefont exch Tf pop
  1372.   } bdef
  1373. end
  1374.  
  1375. end            % pdfdict
  1376. end            % GS_PDF_ProcSet
  1377. .setglobal
  1378.