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