1576 lines · 52.2 KB · Text
RawDownload
%    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 } ifelseGS_PDF_ProcSet beginpdfdict 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 undefcurrentdict /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 ---------------- %

Lines 1–500 of 1576.