shithub: riscv

ref: 37b86df09ff381bcc4f60802d43e57bd9bfcac73
dir: /sys/src/cmd/gs/lib/pdf_font.ps/

View raw version
%    Copyright (C) 1994, 2000 Aladdin Enterprises.  All rights reserved.
% 
% This software is provided AS-IS with no warranty, either express or
% implied.
% 
% This software is distributed under license and may not be copied,
% modified or distributed except as expressly authorized under the terms
% of the license contained in the file LICENSE in this distribution.
% 
% For more information about licensing, please refer to
% http://www.ghostscript.com/licensing/. For information on
% commercial licensing, go to http://www.artifex.com/licensing/ or
% contact Artifex Software, Inc., 101 Lucas Valley Road #110,
% San Rafael, CA  94903, U.S.A., +1(415)492-9861.

% $Id: pdf_font.ps,v 1.80 2005/09/29 15:24:53 leonardo Exp $
% PDF font operations.

% Finding a font by name can't give a proper result when PDF font names aren't unique.
% But it is only the way to obtain a font in Postscript after a font file is executed.
% Therefore using a FontName (and findfont) is allowed only
% immediately after a font file is executed.
% In all other cases the font to be found by a pointer through PDF structures.
%
% This ideal logics can't work for documents,
% which define a font resource with an embedded font,
% and another font resource with same BaseFont but with no embedded font
% (and possibly with no font descriptor).
% Our testbase does contain such examples.
% In this case we do find font by FontName (with findfont),
% since there is no other way to get a reasonable result.

/.setlanguagelevel where { pop 2 .setlanguagelevel } if
.currentglobal true .setglobal
/pdfdict where { pop } { /pdfdict 100 dict def } ifelse
GS_PDF_ProcSet begin
pdfdict begin

% We cache the PostScript font in an additional element of the
% font resource dictionary, called PSFont.

% ---------------- Encodings ---------------- %

/.notdefEncoding 256 { /.notdef } repeat 256 packedarray def

% Apply a list of differences to an Encoding.
% Note that the differences may cause the array to grow.
/updateencoding {	% <encoding|null> <differences> updateencoding <enc'>
	% Calculate the length of the result.
  % in case the incoming Encoding is null, use .notdefEncoding
  exch dup null eq { pop .notdefEncoding } if
  0 0 3 index {
    dup type /nametype ne { exch pop oforce } { pop 1 add } ifelse
    % Differences list may not be in order, update the largest_index
    % stack: <Differences> <encoding> <largest_index> <at_index>
    2 copy lt { exch pop dup } if	% at_index is new largest
  } forall
  pop 1 index length .max array dup 0 4 -1 roll putinterval
  exch 0 exch {
		% Stack: enc' code element
    dup type /nametype ne
      { exch pop oforce }
      { 3 copy put pop 1 add }
    ifelse
  } forall pop
} bdef

% Get the Encoding for a font.
/getencoding		% <base-encoding> <font-resource> getencoding <enc>
 { /Encoding knownoget
    { dup type /nametype eq
       {
         % The published PDF specification says the Encoding name
         % "must be" one of the 3 predefined Encodings, implying
         % that an error should occur if it isn't.  However, Acrobat
         % Reader simply ignores unknown names, and since there are
         % some buggy applications that rely on this, we do the same.

         dup dup dup /MacRomanEncoding eq
         exch /MacExpertEncoding eq or 
         exch /WinAnsiEncoding eq or
           { exch pop findencoding
           }
           { pop
           }
         ifelse
       }
       { dup /BaseEncoding knownoget
	   {
             dup / eq
               { pop
                 (   **** Warning: Ignoring bad BaseEncoding name.\n)  pdfformaterror
                 % as found in a PDF file from J.D.Edwards OneWorld (B7333), bug 687786
               }
               {
                 findencoding 3 -1 roll pop exch
               }
             ifelse
	   }
	 if
	 /Differences knownoget { updateencoding } if
       }
      ifelse
    }
   if
 } bdef

/checkGlyphNames2Unicode % <dict> checkGlyphNames2Unicode -
{
  PDFDEBUG {
    dup /FontInfo .knownget { 
      /GlyphNames2Unicode .knownget { 
        (Has GlyphNames2Unicode) =
        pop % { exch == ==} forall 
      } if 
    } if
  } if
  pop
} bind def

% Define a font using it's FontName as the key.
% Adjust a font according to the Encoding and Widths in the font resource.
/adjustfont {		% <font-resource> <font> adjustfont <font'>
  getfontencoding
  3 copy .processToUnicode
  getfontmetrics 5 -1 roll pop .updatefont { dup /FontName get exch definefont } if
} bind def

% Get the (possibly modified) encoding of a font.
/getfontencoding {	% <font-resource> <font> getfontencoding
			%   <font-resource> <font> <Encoding|null>
  1 index /Encoding known {
    dup /Encoding knownoget { 2 index getencoding } { null } ifelse
  } {
    null
  } ifelse
} bdef

% Returns true if the current glyph is in the Differences array at
% the specified index value. This is needed because the Widths
% array may map to the same glyph at different positions from the
% Encoding. We want to use the Width that was associated with the
% one specified in the Encoding::Differences list.
/match_in_diff     % <Differences> <index> <glyphname> match_in_diff <bool>
{ false 4 1 roll 0 4 -1 roll	% stack: false index glyphname at_index==0 Differences
  { exch 1 index type /nametype ne {
      % stack: false index glyphname Diff_element at_index 
      pop	% Diff_element is new at_index
    } {
      % stack: false index glyphname Diff_element at_index 
      exch 2 index eq {
        % stack: false index glyphname at_index 
	dup 3 index eq {
          true 5 1 roll	% stack: true false index glyphname at_index
          pop exit
        } if
      } if
      1 add		% at_index++ stack: false index glyphname at_index' 
    } ifelse
  } forall
  % stack: true  false index     glyphname
  %  or  : false index glyphname at_index
  pop pop pop
} bdef

/unique_name {  % <dict> </root> unique_name </unique> 
  %
  %  Note : this function interacts with pdf_write_encoding in src/gdevpdtw.c
  %  and with copied_drop_extension_glyphs in src\gxfcopy.c
  %  by adding a reserved substring (~GS~).
  %
  .namestring       % <<>> (root)
  0 1 65535 {
    5 string cvs    % <<>> (root) (0)
    (~GS~) exch concatstrings
    1 index exch    % <<>> (root) (root) (~GS~0)
    concatstrings   % <<>> (root) (root~GS~0)
    dup             % <<>> (root) (root~GS~0) (root~GS~0)
    3 index exch    % <<>> (root) (root~GS~0) <<>> (root~GS~0)
    known not {
      exch pop exit % <<>> (root~GS~0)
    } if
    pop
  } for
  exch pop cvn      % /root0
} bdef
                               
% Get the metrics of a font, if specified.
/getfontmetrics {	% <font-resource> <font> <Encoding|null> getfontmetrics
			%   <font-resource> <font> <Encoding|null>
			%   <Metrics|null> <GlyphMap|null>
  2 index /Widths known {
    dup null eq { pop dup /Encoding get } if
    4 dict begin
      dup length dict
      /Metrics exch def
      /Encoding exch def
      /GlyphMap //null def
      exch
      dup /Widths oget /Widths exch def
		% Stack: font font-res
		% Note that widths are always based on a 1000-unit
		% character space, but the FontMatrix may specify
		% some other scale factor.  Compensate for this here,
		% by scaling the Widths if necessary.
      0.001 2 index /FontMatrix get 0 get div
		% Stack: font font-res mscale
      1 index /FirstChar oget dup 1 4 index /LastChar oget
       {	% Stack: font font-res mscale first-char index
	 Encoding 1 index dup 2 index length ge {
           (   **** Warning: Font Encoding array size is smaller than character range.\n)
           pdfformaterror
	   pop pop /.notdef
         } {
	   get
	 } ifelse
	 Widths 2 index 4 index sub dup 2 index length ge {
           (   **** Warning: Font Widths array size is smaller than character range.\n)
           pdfformaterror
           % use MissingWidth if it's available, if not, default to 1000 (full width)
	   pop pop 4 index /FontDescriptor knownoget {
	     /MissingWidth knownoget not { 1000	} if
	   } { 1000 } ifelse
         } {
	   oget
	 } ifelse
	 	% Stack: font font-res mscale first-char index charname width
	 4 index mul
		% The following 'loop' is only context for 'exit'.
	 {	
		% Work around a bug in pdfTeX, which can generate Encoding
		% vectors containing nulls :
	   1 index //null eq { exit } if
           Metrics 2 index .knownget {
             1 index ne
           } {
             //false
           } ifelse {
             % Two or more Encoding elements refer same glyph name,
             % and Widths specify different wihts for it.
             % Since a Postscript font can't have different 
             % Metrics for same glyph name, 
             % we generate an unique name, and create a new 
             % Charstrings entry with same glyph value.
             GlyphMap //null eq {
               /Encoding Encoding dup length array copy def
               /GlyphMap 4 dict def
             } if
             % To prevent too many new names, check whether
             % we can use one already created for same glyph.
             //true
             GlyphMap {                           % f r s c i n w b n1 n2
               4 index eq {                       % f r s c i n w b n1
                 dup Metrics exch get             % f r s c i n w b n1 w1
                 3 index eq {                     % f r s c i n w b n1
                   4 3 roll pop                   % f r s c i w b n1
                   3 1 roll pop                   % f r s c i n1 w
                   Encoding 3 index 3 index put
                   //false                        % f r s c i n1 w b
                   exit
                 } {
                   pop
                 } ifelse
               } {                                % f r s c i n w b n1
                 pop
               } ifelse
             } forall                             % f r s c i n w b
             { % Do create a new name.
               Metrics 2 index //unique_name exec % f r s c i n w nn
               Encoding 4 index 2 index put
               GlyphMap 1 index 5 -1 roll put     % f r s c i w nn
               exch
                  % Stack: font font-res mscale first-char index new_name width
             } if
           } if
           2 copy Metrics 3 1 roll put
	   exit
	 } loop
	 pop pop pop
       }
      for pop
		% Now fill in the MissingWidth for any encoded characters
		% that aren't in Metrics already.  Note that built-in
		% fonts may have Widths/FirstChar/LastChar but no
		% FontDescriptor, so we must check for this.
		% Stack: font font-res mscale
      1 index /FontDescriptor knownoget {
	Metrics exch
	/MissingWidth knownoget { 2 index mul } { 0 } ifelse exch
	Encoding {
		% Stack: font font-res mscale missing-width metrics charname
		% Work around the abovementioned pdfTeX bug.
	  dup //null ne {
	    2 copy known not { 2 copy 4 index put } if pop
	  } {
	    pop
	  } ifelse
	} forall pop pop pop
      } {
	pop
      } ifelse
    exch Encoding Metrics GlyphMap end
  } {
    //null //null
  } ifelse
} bdef

currentdict /unique_name undef
currentdict /match_in_diff undef

/ToUnicodeCMapReader 3 dict def
//ToUnicodeCMapReader begin
  /defineresource % <name> <dict> <cat-name> defineresource <dict> 
  {
    pop 
    dup userdict exch /.lastToUnicode exch put
    exch pop
  } bind def
  /CIDSystemInfo 
  { 
    (   **** Warning: ToUnicode CMap has invalid syntax near CIDSystemInfo.\n)  pdfformaterror
    /CIDSystemInfo 
  } bind def % A work around a bug in Altona.Page_3.2002-09-27.pdf - a slash is missed.
end

/string2number     % <string> string2number <number>
{ 0 exch dup 0 exch 1 exch length 1 sub {     % n () i
    1 index exch get                          % n () v
    3 2 roll 256 mul add exch                 % v+n*256 ()
  } for
  pop                                         % N
} bind def

/copy&def    % <key> <value> <bool> copy&def -
{
  { true
  } {
    currentdict gcheck { 
      dup gcheck not
    } {
      false
    } ifelse
  } ifelse
  { currentglobal currentdict gcheck setglobal 
    exch dup length string copy exch 
    setglobal
  } if
  def
} bind def

/.convert_ToUnicode-into-g2u % <GlyphNames2Unicode> <Encoding|null> <CMap> .convert_ToUnicode-into-g2u -
{
  PDFDEBUG {
    (.convert_ToUnicode-into-g2u beg) =
  } if
  3 2 roll begin
  /.CodeMapData get % About the data format see gs_cmap.ps, the comment after "CMap operators".
  1 get % code maps
  { 
    PDFDEBUG {
      dup ==
    } if
    dup length 1 sub 0 exch 5 exch {           % e [] i
      2 copy get                               % e [] i (prefix)
      string2number                            % e [] i prefix
      2 index 2 index 1 add get                % e [] i prefix (key_size,?is_range,value_type,value_size)
      dup 0 get 8 mul                          % e [] i prefix (key_size,?is_range,value_type,value_size) key_size*8
      3 2 roll exch bitshift exch              % e [] i prefix<<key_size*8 (key_size,?is_range,value_type,value_size)
      dup 0 get exch 3 get                     % e [] i offset key_size value_size
      4 index 4 index 2 add get                % e [] i offset key_size value_size (keys)
      5 index 5 index 3 add get                % e [] i offset key_size value_size (keys) (values)
      PDFDEBUG {
        ( offset=) print 4 index =string cvs print
        ( key_size=) print 3 index =string cvs print
        ( value_size=) print 2 index =
        ( keys=)   print 1 index ==
        ( values=) print dup ==
      } if
      1 index length 0 eq {
        % A single pair.
        exch pop exch pop exch pop exch        % e [] i (values) offset
        4 index null ne {
          4 index exch get
        } if                                   % e [] i (values) cid|name
        exch 
        PDFDEBUG {
          ( defined single: ) print 1 index =string cvs print ( ) print dup ==
        } if
        false copy&def                         % e [] i
        pop                                    % e []
      } {
        % A range.                             % e [] i offset key_size value_size (keys) (values)
        dup length string copy % protect the original string from modifications below.
        0 4 index 2 mul 3 index length 1 sub { % e [] i offset key_size value_size (keys) (values) j
          2 index 1 index 6 index getinterval          
          string2number                        % e [] i offset key_size value_size (keys) (values) j keyL
          PDFDEBUG {
              ( keyL=) print dup =string cvs print
          } if
          3 index 2 index 7 index add 7 index getinterval
          string2number                        % e [] i offset key_size value_size (keys) (values) j keyL keyH
          PDFDEBUG {
              ( keyH=) print dup =
          } if
          3 2 roll 6 index idiv 5 index mul    % e [] i offset key_size value_size (keys) (values) keyL keyH J
          3 index exch 6 index getinterval     % e [] i offset key_size value_size (keys) (values) keyL keyH (valueL)
          3 1 roll 1 exch {                    % e [] i offset key_size value_size (keys) (values) (value) k
            9 index null ne {
              9 index exch get                 % e [] i offset key_size value_size (keys) (values) (value) name
            } if                               % e [] i offset key_size value_size (keys) (values) (value) cid|name
            1 index                            % e [] i offset key_size value_size (keys) (values) (value) cid|name (value)
            PDFDEBUG {
              ( defined from range: ) print 1 index =string cvs print ( ) print dup ==
            } if
            true copy&def                      % e [] i offset key_size value_size (keys) (values) (value)
            % Assuming the lowest byte of 'value' changes, others don't.
            dup dup length 1 sub               % e [] i offset key_size value_size (keys) (values) (value) (value) l
            2 copy get                         % e [] i offset key_size value_size (keys) (values) (value) (value) l v
            1 add put                          % e [] i offset key_size value_size (keys) (values) (value')
          } for                                % e [] i offset key_size value_size (keys) (values) (value)
        } for
        pop pop pop pop pop pop pop            % e []
      } ifelse
    } for
    pop                                        % e
  } forall
  end
  pop                                          %
  PDFDEBUG {
    (.convert_ToUnicode-into-g2u end) =
  } if
} bind def

/.processToUnicode   % <font-resource> <font-dict> <encoding|null> .processToUnicode -
{
  % Currently pdfwrite is only device which can handle GlyphNames2Unicoide to 
  % generate a ToUnicode CMaps. So don't bother with other devices.
  currentdevice .devicename /pdfwrite eq {
    PDFDEBUG {
      (.processToUnicode beg) =
    } if
    2 index /ToUnicode knownoget {
      dup type /nametype eq {
        % Bug687351.pdf defines /ToUnicode /Identity-H, what is incorrect.
        (   **** Warning: Ignoring bad ToUnicode CMap.\n)  pdfformaterror
        pop
      } {
        PDFfile fileposition exch
        false resolvestream
        //ToUnicodeCMapReader begin
          cvx exec
        end
        PDFfile exch setfileposition
        1 index /FontInfo .knownget not {
          1 index /FontInfo 5 dict dup 4 1 roll put
        } if
        dup /GlyphNames2Unicode .knownget not {
          currentglobal exch dup gcheck setglobal
          dup /GlyphNames2Unicode 100 dict dup 4 1 roll .forceput
          3 2 roll setglobal
        } if                                 % font-res font-dict encoding|null font-info g2u
        exch pop exch                        % font-res font-dict g2u encoding|null
        userdict /.lastToUnicode get         % font-res font-dict g2u Encoding|null CMap
        .convert_ToUnicode-into-g2u          % font-res font-dict
        null                                 % font-res font-dict null
      } ifelse
    } if
    PDFDEBUG {
      (.processToUnicode end) =
    } if
  } if
  pop pop pop
} bind def

% ---------------- Descriptors ---------------- %

% Partial descriptors for the 14 built-in fonts.  Note that
% from PDF 1.1 to PDF 1.2, the meaning of the Flag 6 in the FontDescriptor
% object has undergone a subtle change in its meaning which has serious
% consequences for searching with Acrobat:
% In PDF 1.1, the flag meant: Font has StandardEncoding
% In PDF 1.2, the flag means: Font has (subset of) StandardRomanCharacterSet
/standardfontdescriptors mark
  /Courier mark /Flags 16#23 .dicttomark
  /Courier-Oblique 1 index
  /Courier-Bold 1 index
  /Courier-BoldOblique 1 index
  /Helvetica mark /Flags 16#20 .dicttomark
  /Helvetica-Oblique 1 index
  /Helvetica-Bold 1 index
  /Helvetica-BoldOblique 1 index
  /Times-Roman mark /Flags 16#22 .dicttomark
  /Times-Bold 1 index
  /Times-Italic mark /Flags 16#62 .dicttomark
  /Times-BoldItalic 1 index
  /Symbol mark /Flags 16#4 .dicttomark
  /ZapfDingbats 1 index
.dicttomark readonly def

% ---------------- Utilities ---------------- %


/.pdforigfontcache_g 20 dict def
currentglobal false setglobal
systemdict /.pdforigfontcache_l 20 dict .forceput
setglobal

% Find an original font, using cache to prevent adjustfont to accumulate changes.
/pdffindcachedfont {   % <font_name> pdffindcachedfont <font>
  dup //.pdforigfontcache_g exch .knownget {
    exch pop
  } {
    dup .pdforigfontcache_l exch .knownget {
      exch pop
    } {
      dup findfont dup    
      dup gcheck { //.pdforigfontcache_g } { .pdforigfontcache_l } ifelse
                     % Stack : font_name font font cache
      4 2 roll .growput
    } ifelse
  } ifelse
} bind def

% Add original font to cache to prevent adjustfont to accumulate changes.
/pdfaddcachedfont {   % <font_name> pdfaddcachedfont <font>
  dup findfont dup                   % name font font
  dup gcheck { //.pdforigfontcache_g } {.pdforigfontcache_l} ifelse
  4 2 roll                           % font d name font
  put                                % font
} bind def

/.remove_font_name_prefix {  % <name>  .remove_font_name_prefix <name>
  dup .namestring (+) search {
    true exch
    { dup 65 lt exch 90 gt or {
        pop false exit
      } if
    } forall
    { pop exch pop cvn
    } {
      pop pop
    } ifelse
  } {
    pop
  } ifelse
} bind def

% Find a font (except for embedded ones), and adjust its encoding if necessary.
/.pdfdfndict mark
  /defaultfontname /Helvetica
.dicttomark readonly def
/pdffindfont {		% <font-resource> <fontname> pdffindfont <font>
		% If the font isn't available, synthesize one based on
		% its descriptor.
  dup /Font resourcestatus {
    pop pop pdffindcachedfont
  } {
    1 index /FontDescriptor knownoget {
		% Stack: font-res fontname fontdesc
      dup /Flags oget
      dup 16#40 and -6 bitshift		% 1, oblique/italic
      1 index 16#40000 and -17 bitshift add	% 2, bold
      exch 16#2 and 2 bitshift add	% 8, serif
		% We should look at the fixed flag, too.
		% Stack: font-res fontname fontdesc properties

                % Even though /FontName is a required key in FontDescriptor dict
                % (As of the PDF 1.4 Reference Manual), In the case of missing 
                % /FontName key, we substitue /BaseFont for the value of /FontName.
                % Yet another case of broken PDF's that Adobe Reader accepts.
      1 index dup /FontName known {
        /FontName oget
      } {
        (   **** FontDescriptor missing required /FontName key. BaseFont name used.\n)
        pdfformaterror
        pop 2 index		% grab the BaseFont from the stack.
      } ifelse
      .remove_font_name_prefix
      exch
		% Analyzes font name and extract "Narrow" property
		% which is not described by the FontDescriptor Flags.
      0 2 index .fontnameproperties 4 and or
		% Rebind the default font name to Helvetica so that
		% fonts with no properties are handled correctly.
      //.pdfdfndict begin .substitutefontname end
		% Stack: font-res fontname fontdesc substname|null
      Fontmap 1 index known not {
		% No available good substitution, use the standard one.
	pop 1 index .substitutefont
      } if
      dup 3 index ne QUIET not and {
	(Substituting font ) print dup =only
	( for ) print 2 index =only (.) = flush
      } if
      pdffindcachedfont
		% Stack: font-res fontname fontdesc font
		% If this is a small-caps font, replace the CharString
		% entries for a..z.
      exch /Flags oget 16#20000 and 0 ne {
	true .copyfontdict
	dup /CharStrings 2 copy get dup length dict .copydict
	% stack: font-res fontname font font /CharStrings CharStringsdict
	5 index /FirstChar get 97 .max
	6 index /LastChar get 122 .min 1 exch {
		% Stack: font-res fontname font' font' /CharStrings charstrings code
		% Note that this only remaps a-z, not accented characters.
	  6 index /Widths oget 1 index 8 index /FirstChar get sub oget
	  1 string dup 0 5 -1 roll put
		% Stack: font-res font' font' /CharStrings charstrings code
		%   width (x)
	  2 index exch dup cvn exch
	  dup 0 2 copy get 32 sub put 4 -1 roll {
			% Stack: operand (X) width
	    0 setcharwidth exch pop
	    currentfont /FontMatrix get matrix invertmatrix concat
	    0.7 dup scale 0 0 moveto show
	  } /exec cvx 4 packedarray cvx put
	} for put
      } if
      dup /FontName get 2 index ne {
        true .copyfontdict
        2 copy exch /FontName exch put
      } if
      definefont
    } {
		% No descriptor available, use the default algorithm.
      pdffindcachedfont
    } ifelse
  } ifelse
  exch pop
} bdef

% ---------------- Type 1 fonts ---------------- %

/buildType1		% <Type1-font-resource> buildType1 <font>
 { dup /BaseFont get pdffindfont
 } bdef

% The state dictionary for the embedded Type 1 font reading procedure
% has the following keys and values:
%	data - stream (filter)
%	buffer, buffer2 - string
%	hexify - procedure to convert buffer to hex if needed
%	leftstr - string containing (non-negative) integer
%	sectionstr - string containing a character 0 .. 3
%	stream - (stream) dictionary
%	proc - procedure of the form {-dict- type1read}
%       pfbhdr - string containing 16#80 if PFB, 0 otherwise
% When the procedure is executing, this dictionary is current.
% leftstr and sectionstr are strings so that we can change their values
% reliably in case the font executes a restore!
% We also have to do something special about embedded fonts that
% execute definefont more than once -- that is the function of topFontDict.

% Read an embedded Type 1 font.
/readfontfilter {	% <proc> readfontfilter <filter>
  0 () /SubFileDecode filter
} bdef
/readtype1dict 5 dict dup begin
  /definefont {
    dup topFontDict eq topFontDict null eq or {
      dup wcheck not { dup length dict copy } if
      exch pop savedFontName exch
    } if
    //systemdict /definefont get exec
  } bdef
  /eexec {
	% Assume the font dictionary is directly below the file on the stack
    count 0 gt { /topFontDict 2 index cvlit store } if
    //.eexec_param_dict /eexecDecode filter
    //systemdict begin readtype1dictcopy begin cvx stopped
    currentdict readtype1dictcopy eq { end } if
    currentdict //systemdict eq { end } if
     { stop } if
  } bdef

  /undef_proc_warning {
    /Repaired true store	% flag that we have warnings
    UndefProcList exch 2 copy .knownget { 1 add } { 1 } ifelse put
  } bdef

  /-| { string currentfile exch readstring pop /-| undef_proc_warning } executeonly bdef
  /RD { string currentfile exch readstring pop /RD undef_proc_warning } executeonly bdef
  /|- { noaccess def /|- undef_proc_warning } executeonly bdef
  /ND { noaccess def /ND undef_proc_warning } executeonly bdef
  /|  { noaccess put /|  undef_proc_warning } executeonly bdef
  /NP { noaccess put /NP undef_proc_warning } executeonly bdef

end readonly def
/readtype1 {		% <font-resource> <stream-dict> readtype1 <font>
		% Read the definition, using a procedure-based filter
		% that turns binary/hex conversion on and off
		% at the right times.
   1 index exch
   PDFfile fileposition 3 1 roll
   11 dict begin
     /leftstr (          ) 10 string copy def
       dup /Length1 oget leftstr cvs pop
     /sectionstr <00> 1 string copy def
     /pfbhdr <00> 1 string copy def
     /stream 1 index def
     true resolvestream /data exch def
     /buffer 1000 string def		% arbitrary
     /buffer2 buffer length 2.1 div cvi 1 sub string def
     /hexify /buf2hex load def
   currentdict end
   /type1read cvx 2 array astore cvx dup 0 get /proc 2 index put
   readfontfilter
		% Some buggy embedded fonts leave extra junk on the stack,
		% so we have to make a closure that records the stack depth
		% in a fail-safe way. Also restore dictstack depth.
   //systemdict begin
		% The PDF specification is somewhat muddy about whether
		% an embedded font's name is supposed to be the BaseFont
		% from the Font object or the FontName from the descriptor.
		% Acrobat Distiller requires the former.  Save away the
		% name so we can substitute it at definefont time.
   //readtype1dict dup length 3 add dict copy begin
   1 index /BaseFont oget /savedFontName exch def
   /topFontDict null def
   /readtype1dictcopy currentdict def
    { run } aload pop count 1 sub 2 packedarray cvx exec
    % clean up the dictstack
    { currentdict /topFontDict known not { end } { end end exit } ifelse } loop
   count exch sub { pop } repeat
   PDFfile 3 -1 roll setfileposition
   /BaseFont oget pdfaddcachedfont
   exch pop
 } bdef

% Execute the appropriate reading procedure.
/type1read		% <dict> type1read <string>
 { begin leftstr cvi
    { type1read0 type1read1 type1read2 type1read3 } sectionstr 0 get get exec
   (          ) leftstr copy cvs pop end
 } bdef

% Read the next block of data into the buffer.
/type1readdata		% <left> <buffer> type1readdata <substring> <left'>
 { 0 2 index 2 index length .min getinterval
		% Adobe requires readstring to signal an error if given
		% an empty string.  Work around this nonsense here.
   dup length 0 ne { data exch readstring pop } if
   dup length 3 -1 roll exch sub
   PDFDEBUG
    { dup =only ( read ) print
      1 index length =only (: ) print
      1 index == flush
    } if
 } bdef

% Read the initial byte to see if we need to skip a 6 byte PFB header
/type1read0 { 		% <left> type1read0 <string> <left'>
  sectionstr 0 1 put	% either way we go to the next stage
  pfbhdr type1readdata
  1 index 0 get 16#80 eq {
    (   **** Warning: Embedded Type1 font in PFB format is not valid PDF.\n)
    pdfformaterror
    PDFDEBUG { (skipping PFB header) = flush } if
    exch pop buffer 0 5 getinterval type1readdata exch
    dup 4 get 256 mul 1 index 3 get add 256 mul
    1 index 2 get add 256 mul 1 index 1 get add
    PDFDEBUG { (PFB segment length = ) print dup = } if
    exch pop  % discard the string keeping the PFB segment length
    2 copy ne {
      (   **** Warning: Type 1 PFB segment length and Length 1 value do not match.\n)
      pdfformaterror
      exch 	% keep the PFB length instead
    } if
    pop
    buffer type1readdata	% go ahead and read a block
  }
  if	% if not PFB, return pfbhdr string (first char of file, usually %).
} bdef

% Read the next block of the initial text portion.
/type1read1 {		% <left> type1read1 <string> <left'>
  PDFDEBUG { (read1 ) print } if
  dup 0 eq {
    pop sectionstr 0 2 put
    stream /Length2 oget
			% Determine whether to hexify data for eexec.
    dup 8 lt {
      type1read2	% Hexify.
    } {
      PDFDEBUG { (read2 ) print } if
      pfbhdr 0 get 16#80 eq {
        % eat 6 more bytes of PFB junk before proceeding
	PDFDEBUG { (skipping PFB header in segment 2) = flush } if
	buffer 0 6 getinterval type1readdata exch
        dup 5 get 256 mul 1 index 4 get add 256 mul
	1 index 3 get add 256 mul 1 index 2 get add
        PDFDEBUG { (PFB segment length = ) print dup = } if
	exch pop  % discard the string keeping the PFB segment length
	2 copy ne {
          (   **** Warning: Type 1 PFB segment length and Length 2 value do not match.\n)
          pdfformaterror
	  exch 		% keep the PFB length instead
	} if
	  pop
      } if
      buffer2 type1readdata exch
			% The check doesn't have to be 100% accurate:
			% hexifying is always OK.
      dup 0 8 getinterval 0 exch { or } forall
      128 ge {
	/hexify { } store
	/buffer2 buffer def	% We don't need an intermediate buffer.
      } if hexify exch
    } ifelse
  } {
    buffer type1readdata
  } ifelse
} bdef

% Convert a string from binary to hex for eexec.
% Free variables: buffer.
/buf2hex {		% <string> buf2hex <hexstring>
  buffer /ASCIIHexEncode filter dup 3 -1 roll writestring closefile
  buffer (>) search pop exch pop exch pop
} bdef

% Read the next block of the encrypted portion.
/type1trailer
(0000000000000000000000000000000000000000000000000000000000000000\n\
0000000000000000000000000000000000000000000000000000000000000000\n\
0000000000000000000000000000000000000000000000000000000000000000\n\
0000000000000000000000000000000000000000000000000000000000000000\n\
0000000000000000000000000000000000000000000000000000000000000000\n\
0000000000000000000000000000000000000000000000000000000000000000\n\
0000000000000000000000000000000000000000000000000000000000000000\n\
0000000000000000000000000000000000000000000000000000000000000000\n\
cleartomark\n)
readonly def
/type1read2 {		% <left> type1read2 <string> <left'>
  PDFDEBUG { (read2 ) print } if
   dup 0 eq
    { pop sectionstr 0 3 put
      stream /Length3 oget
      dup 0 eq
       { PDFDEBUG { (trailer ) print } if
	 type1trailer exch
       }
       { 
         pfbhdr 0 get 16#80 eq {
           % eat 6 more bytes of PFB junk before proceeding
	   PDFDEBUG { (skipping PFB header in segment 3) = flush } if
	   buffer 0 6 getinterval type1readdata exch
           dup 5 get 256 mul 1 index 4 get add 256 mul
	   1 index 3 get add 256 mul 1 index 2 get add
           PDFDEBUG { (PFB segment length = ) print dup = } if
	   exch pop  % discard the string keeping the PFB segment length
	   2 copy ne {
           (   **** Warning: Type 1 PFB segment length and Length 3 value do not match.\n)
           pdfformaterror
	     exch 	% keep the PFB length instead
	   } if
	   pop
         } if
         type1read3
       }
      ifelse
    }
    { buffer2 type1readdata exch hexify exch
    }
   ifelse
} bdef

% Read the next block of the final text portion.
% When finished, this procedure returns an empty string.
/type1read3		% <left> type1read3 <string> <left'>
 { PDFDEBUG { (read3 ) print } if
   buffer type1readdata
 } bdef

% ---------------- Type 3 fonts ---------------- %

/buildType3 {		% <Type3-font-resource> buildType3 <font>
  8 dict begin
    /FontType 3 def
		% If the font does not contain a Resources entry, then we use
		% the resources from our current context.  Page 391 of the PDF
		% 1.6 spec says that the Resources dict is optional and if not
		% present then we should use the Resources for the page.
		% However we have a test file (687989) which uses a Type3 font
		% inside a form XObject and the desired Resources are in the
		% XObject dict and not in the Page dict.  So we are going to
		% the parent object to find resources instead of only going to
		% the page dict when a font does not specify its required
		% resources.
    /Resources 1 index /Resources knownoget {
       oforce
    } {
       LocalResources
    } ifelse def
    /FontBBox 1 index /FontBBox get cvx def
    /FontMatrix 1 index /FontMatrix oget def
    /CharProcs 1 index /CharProcs oget def
    1 index /Widths knownoget {
      /Widths exch def
      /FirstChar 1 index /FirstChar oget def
      /LastChar 1 index /LastChar oget def
    } if
    /FontName 1 index /Name .knownget not { 
       PDFfile fileposition 16 10 string cvrs cvn
    } if def

    /Encoding .notdefEncoding 2 index getencoding def
		% We have to define BuildChar rather than BuildGlyph:
		% there is no PDF equivalent of glyphshow, and we need
		% the character code to access the Widths.
    /BuildChar {
		% Stack: font charcode
      1 index begin 3 dict begin
      /Font 3 -1 roll def /CharCode 1 index def
      % Make unknown characters map to /.notdef
      Encoding exch get dup CharProcs exch known
        { CharProcs exch oget }
	{ pop CharProcs /.notdef oget }
      ifelse
      PDFfile fileposition exch
      false resolvestream
		% Stack: filepos stream
		% Don't let setgcolor set the color inside the BuildGlyph
		% procedure, because this causes an /undefined error.
      q null /FillColor gput null /StrokeColor gput
      Font /Resources get exch pdfopdict .pdfruncontext
      Q
      PDFfile exch setfileposition
      end end
    } bdef
    dup currentdict Encoding .processToUnicode
    FontName currentdict end definefont exch pop
} bdef
/.adjustcharwidth {	% <wx> <wy> .adjustcharwidth <wx'> <wy'>
  /Widths where {
    begin
    CharCode FirstChar ge CharCode LastChar le and {
      exch pop Widths CharCode FirstChar sub get exch
    } if end
  } if
} bdef

% ---------------- TrueType fonts ---------------- %

/TTfonts mark
  /Arial /Helvetica
  /Arial,Italic /Helvetica-Oblique
  /Arial,Bold /Helvetica-Bold
  /Arial,BoldItalic /Helvetica-BoldOblique
  /CourierNew /Courier
  /CourierNew,Bold /Courier-Bold
  /TimesNewRoman /Times-Roman
  /TimesNewRoman,Italic /Times-Italic
  /TimesNewRoman,Bold /Times-Bold
  /TimesNewRoman,BoldItalic /Times-BoldItalic
.dicttomark readonly def

/buildTrueType {	% <TrueType-font-resource> buildTrueType <font>
  dup /BaseFont oget
  /Repaired true store	% flag that we had warnings
  TTFWarnList 1 index true put	% Add fontname to the list
  dup TTfonts exch .knownget {
    QUIET not {
      (Substituting font ) print dup =only
      ( for ) print 1 index =only (.) = flush
    } if
    exch 3 1 roll pdffindfont
    true .copyfontdict
    2 copy exch /FontName exch put
    definefont
  } {
    pdffindfont
  } ifelse
} bdef

% Read an embedded TrueType font.
/readtruetype {		% <font-resource> <stream-dict> readtruetype <font>
		% This is much simpler than readtype1, because we don't
		% have to deal with the tripartite .PFB format.
  1 index exch
  PDFfile fileposition 3 1 roll
  true resolvestream readfontfilter
		% Stack: filepos fontres stream
  1 index /Subtype get /CIDFontType2 eq {
    .loadttcidfont
		% Stack: filepos fontres cidfont
  } {
		                          % filepos fontres stream
    1 index /FontDescriptor oget          % filepos fontres stream fd   
    /Flags get 4 and 0 ne                 % filepos fontres stream is_symbolic
    dup {
      2 index null exch getencoding       % filepos fontres stream is_symbolic Encoding
      dup 4 index exch                    % filepos fontres stream is_symbolic Encoding fontres Encoding
      /prebuilt_encoding exch put         % filepos fontres stream is_symbolic Encoding
    } {
      null
    } ifelse
    .loadpdfttfont
  } ifelse
  exch pop
  PDFfile 3 -1 roll setfileposition
		% Ignore both the Encoding and the Widths.
  exch pop
} bdef

% ---------------- Type 0 fonts ---------------- %

% Predefine the known CMaps, but only create them on demand.
/knownCMaps mark
  /Identity-H { /Identity-H 0 makeIdentityCMap }
  /Identity-V { /Identity-V 1 makeIdentityCMap }
.dicttomark def

/makeIdentityCMap {		% <cmapname> <wmode> .makeIdentityCMap -
  .currentglobal true .setglobal 3 1 roll
  /CIDInit /ProcSet findresource begin
  12 dict begin
    begincmap
    /WMode exch def
    /CMapName exch def
    /CIDSystemInfo 3 dict dup begin
      /Registry (Adobe) def
      /Ordering (Identity) def
      /Supplement 0 def
    end def
    %/CMapName (see above)
    /CMapVersion 1 def
    /CMapType 1 def
    %WMode (see above)
	% The PDF documentation says that these CMaps map CIDs
	% "1 to 65,536".  This is a misprint for 0 to 65,535.
    1 begincodespacerange
	% <0001> <00ff>  <0100> <ffff>
      <0000> <ffff>
    endcodespacerange
    1 begincidrange
	% <0001> <00ff> 1   <0100> <ffff> 256
      <0000> <ffff> 0
    endcidrange
    endcmap
    CMapName currentdict /CMap defineresource
    knownCMaps CMapName 2 index put
  end		% CMap
  end		% CIDInit ProcSet
  exch .setglobal
} bdef

/buildType0 {		% <Type0-font-resource> buildType0 <font>
  dup /BaseFont get	% FontName
  1 index /Encoding oget
  dup type /nametype eq {
    dup /CMap resourcestatus {
	pop pop /CMap findresource
    } {
	knownCMaps 1 index .knownget
	  { exch pop exec } { /undefined signalerror } ifelse
    } ifelse
  } {
    PDFfile fileposition exch
    dup /CMapName get exch true resolvestream cvx exec
    /CMap findresource
    exch PDFfile exch setfileposition
  } ifelse		% CMap
  [
    3 index /DescendantFonts oget { exec resourcefont } forall
  ]			% subfonts
  composefont   % composefont must insert FontInfo dictionary - see gs_cmap.ps .
		% Stack: fontres font
  2 copy null .processToUnicode
  1 index /FontMatrix knownoget {
    dup aload pop true {0 0 1 0 0 1} {3 -1 roll eq and} forall {
      1 index exch makefont exch /FontName get exch definefont
    } {
      pop
    } ifelse
  } if exch pop
} bdef

% ---------------- CIDFontType0/2 fonts ---------------- %

% Insert metrics into a CIDFont, by saving the PDF W, W2, DW, and DW2
% arrays and using a (currently very inefficient) CDevProc.
% For detail, refer "PDF Reference" 2nd ed., p314 "5.6.3 CIDFonts".
% It notes default DW is 0, but Acrobat Reader uses 1000 as default.
% If DW is 0, currentpoint does not move by default in rendering text
% horizontally, the result is unreadable. You can check it by Acrobat.

/.pdfDefaultDW  1000 def
/.pdfDefaultDW2 [ 880 -1000 ] def

/addCIDmetrics {	% <CIDFont-resource> <CIDFont> addCIDmetrics <fontdict>
  dup length 5 add dict .copydict
  dup /FID undef
  dup /UniqueID undef
  dup /XUID undef
	% Insert the widths into the font.

        % Stack: pdfresource newfont

  1 index /DW .knownget {
    1 index /DW 3 -1 roll put
  } {
    dup /DW .pdfDefaultDW put
  } ifelse

  1 index /W .knownget {
    dup 2 index /W 3 -1 roll put
    .pdfMakeInternalW 1 index /.internalW 3 -1 roll put
  } if

  1 index /DW2 .knownget {
    1 index /DW2 3 -1 roll put
  } {
    dup /DW2 .pdfDefaultDW2 put
  } ifelse

  1 index /W2 .knownget {
    dup 2 index /W2 3 -1 roll put
    .pdfMakeInternalW2 1 index /.internalW2 3 -1 roll put
  } if

  dup /CDevProc 1 index /CIDWProc load /exec load 3 packedarray cvx put
  exch pop
} bdef

/.pdfMakeInternalMTXArray { % <mtx_array> <item_size> .pdfConvertInternalW <mtx_array'>

  % convert /W or /W2 to internal expression
  %
  %   mtx_array: original /W or /W2 array
  %   item_size: number of metrics values per CID
  %
  %   for detail of the metrics list format in PDF,
  %   refer PDF Ref. p.317 "Glyph Metrics in CIDFonts".
  % 
  %   format of single entry in internal expression
  %
  %     [
  %       [cid_begin cid_end]
  %       value_is_varied (bool)
  %       [ [values for cid_begin...]
  %         [values for cid_begin + 1]
  %         ... ]
  %     ]
  %

  7 dict
  begin
    /itemSize exch def
    /M exch def			% original /W or /W2
    /Msize M length def
    /Mi { M i get } def		% W[i]
    /Mi1 { M i 1 add get } def	% W[i + 1]
    /putMTXEntry <<
      /arraytype   {
         [
           [Mi Mi Mi1 length itemSize idiv add 1 sub]
           true
           [
             0 itemSize Mi1 length 1 sub {
               [ exch 1 1 index itemSize add 1 sub { Mi1 exch get } for ]
             } for
           ]
         ]
         /i i 2 add def
      }
      /integertype {
         [
           [Mi Mi1]
           false
           [[ i 2 add 1 i 1 add itemSize add { M exch get } for ]]
         ]
         /i i 3 add def
      }
    >> def

    /i 0 def

    [ { putMTXEntry Mi1 type get exec i Msize ge { exit } if } loop ]
  end
} def

/.pdfMakeInternalW  { dup length 0 gt { 1 .pdfMakeInternalMTXArray } if } def
/.pdfMakeInternalW2 { dup length 0 gt { 3 .pdfMakeInternalMTXArray } if } def

/.pdfGetMTXByCID { % <internalMTXArray> <cid>
                   %     .pdfGetMTXByCID
                   %         { <MTXEntry> true | false }

  % get values for given CID from internal format of /W or /W2

  exch
  {
    { 
      dup 0 get {} forall      % Stack: <cid> <entry> <cid_0> <cid_1>
      3 index lt { pop pop false exit } if
      2 index exch sub dup 0 lt { pop pop false exit } if
      1 index 1 get not { pop 0 } if
      exch 2 get exch get true exit
    } loop
    { exit } if
  } forall
  dup type /arraytype eq { exch pop true } { pop false } ifelse
} def


% Apply the [D]W[2] metrics to a character before displaying.
/CIDWProc {		% <w0x> <w0y> <llx> <lly> <urx> <ury>
			%   <w1x> <w1y> <vx> <vy> <cid> <font> CIDWproc
			%   <w0x'> ... <vy'>
  begin % push <font> to currentdict
    % <w1x> <w1y> <vx> <vy> won't be used and replaced, discard now
    5 1 roll pop pop pop pop

    {
      currentdict /DW .knownget not {   % no DW
        .pdfDefaultDW exit              % replace <w0x> by defaultDW
      } if

      currentdict /.internalW .knownget not {    % no W
        exit                            % use already-stacked DW
      } if

      dup length 0 eq {                 % W is null array
        pop                             % discard unusable W
        exit                            % use already-stacked DW
      } if

      % W is finite array, try to get W_cid
      2 index .pdfGetMTXByCID {           % got W, discard DW
        exch pop {} forall
        exit
      } if

      exit
    } loop

    FontType 11 eq {
      1000 div                  % <w0x'> (normalized W)
    } if
    0                           % <w0y'>

    % Stack: <w0x> <w0y> <llx> <lly> <urx> <ury> <cid> <w0x'> <w0y'>
    9 -2 roll pop pop           % discard <w0x> <w0y>
    7  2 roll                   % put <w0x'> <w0y'>

    % Stack: <w0x'> <w0y'> <llx> <lly> <urx> <ury> <cid>
    0                           % <w1x'>
    exch                        % put <w1x'>

    % Stack: <w0x'> <w0y'> <llx> <lly> <urx> <ury> <w1x'> <cid>
    {
      currentdict /DW2 .knownget not {  % no DW2, use defaultDW2
        .pdfDefaultDW2 exit
      } if

      currentdict /.internalW2 .knownget not {   % has DW2, no W2
        exit                            % use already-stacked DW2
      } if

      dup length 0 eq {                 % W2 is null array
        pop                             % discard unusable W2
        exit                            % use already-stacked DW2
      } if

      2 index .pdfGetMTXByCID {		% got W2_cid, discard DW2
        exch pop
        exit
      } if

      % could not get W2_cid
      exit

    } loop

    exch pop                            % discard <cid>

    % Stack: <w0x'> <w0y'> <llx> <lly> <urx> <ury> <w1x'> { [<vy'> <w1y'>] | [<w1y'> <vx'> <vy'>] }
    dup length 2 eq {                   % this is DW2
      FontType 11 eq {{1000 div}} {{}} ifelse forall exch
      8 index 2 div                     % <vx'> = <w0x'> / 2
      exch
    }{                                  % assume W2
      FontType 11 eq {{1000 div}} {{}} ifelse forall
    } ifelse
  end                                   % recover currentdict

} def

% <string> <match> tailmatch ==> <pre> true
%                            ==> <string> false
/tailmatch {
  2 copy length 1 index length .min
  dup 2 index length exch sub exch getinterval
  1 index eq {
    length 1 index length exch sub
    0 exch getinterval true
  } {
    pop false
  } ifelse
} bind def

/makeboldfont {
  16 dict begin
    /strokewidth exch def
    /basecidfont exch def
    /FontMatrix [ 1 0 0 1 0 0 ] def

    /CIDFontName /.boldfont def
    /CIDFontType 1 def

    /basefont-H /.basefont-H /Identity-H [ basecidfont ] composefont def
    /basefont-V /.basefont-V /Identity-V [ basecidfont ] composefont def

    /CIDSystemInfo dup basecidfont exch get def
    /FontBBox [ basecidfont /FontBBox get cvx exec
      4 2 roll basecidfont /FontMatrix get transform
      4 2 roll basecidfont /FontMatrix get transform
    ] def

    /tmpstr 2 string def
    /BuildGlyph {
      gsave
      exch begin
        dup 256 idiv tmpstr exch 0 exch put
        256 mod tmpstr exch 1 exch put
        rootfont /WMode known { rootfont /WMode get 1 eq } { false } ifelse
        { basefont-V } { basefont-H } ifelse setfont
        strokewidth setlinewidth
        1 setlinejoin
        newpath
        0 0 moveto tmpstr false charpath stroke
        0 0 moveto tmpstr show
        currentpoint setcharwidth
      end
      grestore
    } bind def

   currentdict
  end
  dup /CIDFontName get exch /CIDFont defineresource
} bind def

% <CIDFont-resource> <CIDFontName> findCIDFont <CIDFont-resource> <font>
%   CIDFont-resource is not modified.
/findCIDFont {
  {
    dup /CIDFont resourcestatus {
      pop pop /CIDFont findresource
      exit
    } if
    .remove_font_name_prefix
    dup dup length string cvs
    (,Bold) tailmatch {
      exch pop
      cvn findCIDFont 0.03 makeboldfont
      exit
    } if
    (,Italic) tailmatch {
      exch pop
      cvn findCIDFont
      [ 1 0 0.3 1 0 0 ] makefont
      exit
    } if
    (,BoldItalic) tailmatch {
      exch pop
      cvn findCIDFont 0.03 makeboldfont
      [ 1 0 0.3 1 0 0 ] makefont
      exit
    } if
    pop

    1 index /CIDSystemInfo get begin Registry (-) Ordering end
    concatstrings concatstrings
    cvn
    QUIET not {
      (Substituting CID font resource) print dup ==only
      ( for ) print 1 index ==only (.\n) print
    } if
    exch pop
    /CIDFont findresource
    exit
  } loop
} bdef

/buildCIDType0 {	% <CIDFontType0-font-resource> buildCIDType0 <font>
  dup /BaseFont get findCIDFont exch pop
} bdef

/buildCIDType2 {	% <CIDFontType2-font-resource> buildCIDType2 <font>
  dup /BaseFont get findCIDFont exch pop
} bdef

/processCIDToGIDMap { % <fontres> <cidfont> processCIDToGIDMap <fontres> <cidfont>
  1 index /CIDToGIDMap knownoget {
    PDFfile fileposition 4 1 roll
    dup /Identity eq {
      pop
    } {
      true resolvestream
		% Stack: filepos fontres font mapstream
	% Can't know the length of the decompressed stream, so allocate a big buffer...
      dup 65534 string readstring {
   	% Length exceeded max string size, use an array of two strings
   	1 index 65534 string readstring pop   % maybe a null string - not important.
      	2 array astore
      	        % Stack: filepos fontres font mapstream array 
      	dup 1 get length 65534 add
      } {
        dup length
      } ifelse
      2 idiv
    	% Stack: filepos fontres font mapstream array/string CIDCount
      3 index exch /CIDCount exch put
      exch closefile exch
      dup /CIDMap 4 -1 roll put
    } ifelse
    3 2 roll PDFfile exch setfileposition
  } if
} bdef

% Adjust a CIDFontType0 DW[2] in the font resource.
/adjustCIDType0 {		% <font-resource> <font> adjustfont <font'>
  addCIDmetrics
  dup /CIDFontName get exch /CIDFont defineresource
} bind def

% Adjust a CIDFontType2 DW[2] and CIDToGIDMap in the font resource.
/adjustCIDType2 {		% <font-resource> <font> adjustfont <font'>
  addCIDmetrics
  processCIDToGIDMap
  dup /CIDFontName get exch /CIDFont defineresource
} bind def

% ---------------- Other embedded fonts ---------------- %

/fontloadprocs mark
  /Type1C /readType1C cvx
  /CIDFontType0C /readCIDFontType0C cvx
.dicttomark readonly def

% Read an embedded compressed font.
/readType1C {		% <font-resource> <stream-dict> readType1C <font>
  1 index exch
  PDFfile fileposition 3 1 roll
  dup true resolvestream dup readfontfilter
		% Stack: pos resource streamdict stream filter
  3 index /FontDescriptor oget /FontName oget
  1 index FRD
  closefile closefile pop
  PDFfile 3 -1 roll setfileposition
  /FontDescriptor oget /FontName oget pdfaddcachedfont
  exch pop
} bdef

% Read an embedded CFF CIDFont.
/readCIDFontType0C {  % <font-resource> <stream-dict> readCIDFontType0C <font>
  PDFfile fileposition 3 1 roll
  dup true resolvestream dup readfontfilter
		% Stack: pos resource streamdict stream filter
  3 index /FontDescriptor oget /FontName oget
  1 index FRD
  closefile closefile pop
  PDFfile 3 -1 roll setfileposition
		% Some broken Adobe software produces PDF files in which
		% the FontName of the CFF font and the FontName in the
		% FontDescriptor don't match the BaseFont in the font.
		% Use the FontName, rather than the BaseFont, here.
  dup /FontDescriptor oget /FontName oget /CIDFont findresource
  addCIDmetrics dup /CIDFontName get exch /CIDFont defineresource
} bdef

% ---------------- Font lookup ---------------- %

/fonttypeprocs mark		% <font-resource> -proc- <font>
  /Type0 //buildType0
  /Type1 //buildType1
  /MMType1 //buildType1
  /Type3 //buildType3
  /TrueType //buildTrueType
  /CIDFontType0 //buildCIDType0
  /CIDFontType2 //buildCIDType2
.dicttomark readonly def

/adjustfonttypes mark
  /Type1 //adjustfont
  /MMType1 //adjustfont
  /TrueType //adjustfont
  /CIDFontType0 //adjustCIDType0
  /CIDFontType2 //adjustCIDType2
.dicttomark readonly def

/resourcefont			% <font-resource> resourcefont <font>
{ dup /PSFont .knownget
  { /FID knownoget { type /fonttype eq } { //false } ifelse }
  { //false }
  ifelse
  { /PSFont get }
  { dup dup /FontDescriptor knownoget {	% Stack: font-res font-res font-desc
      dup /FontObject .knownget {
	3 1 roll pop pop
      } {
	dup /FontFile knownoget
	{ dup /Length oget 0 eq
	  { pop pop dup /Subtype get fonttypeprocs exch get exec }
	  { exch pop readtype1 }
	  ifelse
	}
	{
	  dup /FontFile2 knownoget
	  { exch pop readtruetype }
	  { /FontFile3 knownoget
	    { dup /Subtype get fontloadprocs exch get exec }
            { dup /Subtype get fonttypeprocs exch get exec }
	    ifelse
	  }
	  ifelse
	}
	ifelse
	1 index /FontDescriptor oget
	1 index /FontObject exch put	    % Save pointer to the font
      }
      ifelse
    }
    { dup /Subtype get fonttypeprocs exch dup () cvn eq {
        (   **** Warning: Font missing required Subtype, /Type1 assumed.\n)
        pdfformaterror
        pop /Type1
      } if get exec
    }
    ifelse
	% Stack: font-res font
    1 index 3 1 roll
    1 index /Subtype get
    //adjustfonttypes exch .knownget { exec } { exch pop } ifelse
    dup 3 1 roll /PSFont exch put
  }
  ifelse
  dup checkGlyphNames2Unicode
} bdef

drawopdict begin
  /d0 {
    .adjustcharwidth setcharwidth
  } bdef
  /d1 {
    4 index 0 ne {
      % invalid wy parameter for d1 in Type3 font (must be 0)
      % Even though the PDF 1.4 specification states that this must be 0,
      % Distiller sometimes creates Type3 fonts with non-zero wy. We set
      % it to 0 since this is apparently what Acrobat Reader 4 and 5 do,
      % but if the specification is ever changed to allow non-zero wy, this
      % will not work.
      5 -1 roll pop 0 5 1 roll	  % set wy to 0
    } if

    2 copy                           % ... llx lly urx ury | urx ury 
    0 ne exch 0 ne                   % ... llx lly urx ury | ury!=0 urx!=0
    3 index 6 index eq and           % ... llx lly urx ury | ury!=0 (urx!=0 && llx==urx)
    exch 2 index 5 index eq and or { % ... llx lly urx ury | (urx!=0 && llx==urx) || (ury!=0 && lly==ury)
      % The bounding box is empty and likely incorrect. Don't cache.
      pop pop pop pop .adjustcharwidth setcharwidth
    } {
      6 -2 roll .adjustcharwidth 6 2 roll setcachedevice
    } ifelse
  } bdef
  /Tf {
    1 index Page /Font rget not { 1 index /invalidfont signalerror } if
    resourcefont exch Tf pop
  } bdef
end

end			% pdfdict
end			% GS_PDF_ProcSet
.setglobal