% 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. Load more
% 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 ---------------- %