diff options
author | Reinhard Kotucha <reinhard.kotucha@web.de> | 2017-04-23 22:15:25 +0000 |
---|---|---|
committer | Reinhard Kotucha <reinhard.kotucha@web.de> | 2017-04-23 22:15:25 +0000 |
commit | 54448d6ab44d2033482fafa56ddc40d42a6815eb (patch) | |
tree | d4fdfff7b7f75c367a76f872e2986af75c5f81a3 /Master/tlpkg/tlgs/Resource/Init/pdf_font.ps | |
parent | f2a947f3017b82f1dfa1058d1d720fe11d298e92 (diff) |
Add files needed for CJK to tlgs, adapt runscript.tlu accordingly.
git-svn-id: svn://tug.org/texlive/trunk@43997 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/tlpkg/tlgs/Resource/Init/pdf_font.ps')
-rw-r--r-- | Master/tlpkg/tlgs/Resource/Init/pdf_font.ps | 2526 |
1 files changed, 2526 insertions, 0 deletions
diff --git a/Master/tlpkg/tlgs/Resource/Init/pdf_font.ps b/Master/tlpkg/tlgs/Resource/Init/pdf_font.ps new file mode 100644 index 00000000000..7060dbce6f0 --- /dev/null +++ b/Master/tlpkg/tlgs/Resource/Init/pdf_font.ps @@ -0,0 +1,2526 @@ +% Copyright (C) 2001-2012 Artifex Software, Inc. +% 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. +% +% Refer to licensing information at http://www.artifex.com or contact +% Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, San Rafael, +% CA 94903, U.S.A., +1(415)492-9861, for further information. +% + +% PDF font operations. + +% Since PDF font are not unique and can collide with external font resources +% or each other, use font dictionaries obtained from PDF directly, never +% register them as resources or look them up by name. Use findfont oparator +% for non-embedded fonts only. CIDFont resources still use the old logic +% described below. + +% 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 + +/good_encoding_names << + /MacRomanEncoding 0 /MacExpertEncoding 0 /WinAnsiEncoding 0 +>> readonly def + +/known_symbolic_fonts << + /Wingdings2 0 + /ZapfDingbats 0 +>> readonly def + +% Get the Encoding for a font. +/getencoding % <base-encoding> <font-resource> getencoding <enc> + { dup /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. + + //good_encoding_names 1 index known { + exch /BaseFont knownoget not { 0 } if + % Ignore named encodings for known symbolic fonts. See bug 690135. + //known_symbolic_fonts exch known { + pop + } { + exch pop findencoding + } ifelse + } { + pop pop + } ifelse + } + { exch pop + dup type /arraytype eq + { exch pop + ( **** Warning: Encoding is an array, not name or dictionary.\n) pdfformatwarning + } + { dup /BaseEncoding knownoget + { + %% Originally we ignored the specific invalid name '/' here from Bug #687786, however + %% Bug #696942 contains an invalid BaseEncoding '/utf-8', so now we check all BaseEncoding + %% against the permitted names, just as we do for Encodings. + //good_encoding_names 1 index known{ + findencoding 3 -1 roll pop exch + }{ + ( **** Error: Invalid BaseEncoding name ") print 256 string cvs print (" ignoring BaseEncoding.\n) pdfformaterror + ( Output may be incorrect.\n) pdfformaterror + }ifelse + } if + /Differences knownoget { updateencoding } if + } + ifelse + } + ifelse + } { + pop + ( **** Error: Encoding not present.\n) pdfformaterror + ( Output may be incorrect.\n) pdfformaterror + } + ifelse + } bdef + +currentdict /good_encoding_names undef +currentdict /known_symbolic_fonts undef + +/checkGlyphNames2Unicode % <dict> checkGlyphNames2Unicode - +{ + PDFDEBUG { + dup /FontInfo .knownget { + /GlyphNames2Unicode .knownget { + (Has GlyphNames2Unicode) = + pop % { exch //== exec //== exec} 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 { + %% Bug #696306 has a broken type 1 font where the eexec encrypted portion simply ends + %% leaving a partial glyph description and, more importantly, the Private dictionary + %% on the operand stack. Ths means the font dictonary does not contain a Private + %% dictionary which causes .buildfont1 to throw an error. .completefont calls .buildfont1 + %% (which is obscured by a definition in gs_type1.ps) so we need to check the reault + %% of .completefont. If it fails we must discard the font dictionary and use a fallback. + {.completefont} stopped { + (\n *** ERROR: The font ) print /FontName get 256 string cvs print ( is damaged and cannot be used. Switching to a\n) pdfformaterror + ( last-ditch fallback, text may not render correctly, or at all.\n\n) pdfformaterror + /Helvetica findfont + }if + } if +} bind def + +% Get the (possibly modified) encoding of a font. +/getfontencoding { % <font-resource> <font> getfontencoding + % <font-resource> <font> <Encoding|null> + % Ignore encoding when TrueType is requested + % and loaded from an embedded stream. + % All other cases are left unchanged. + dup /FontType get 42 eq 1 index /PathLoad known not and + 2 index /Subtype get /TrueType eq and { + //null + } { + % Acrobat appears to be always using StandardEcoding as the + % default encoding for some non-symbolic fonts (rather than, + % as the spec states, the encoding specified by the font). + % As this is contrary to spec, and we only have a CFF + % example, I've restricted this to fonts with Subtype Type1C + % *and* that result in a Type 2 PS font. + 1 index /FontDescriptor knownoget + { + dup + % Unfortunately, Acrobat doesn't enforce the meaning of + % FontFile[23] so whilst, in theory, Type1C should only + % occur in FontFile3, we can't rely on that. + dup /FontFile knownoget not + { + dup /FontFile2 knownoget not + { + dup /FontFile3 knownoget not {1 dict} if + } if + } if + exch pop /Subtype knownoget {/Type1C eq}{//false} ifelse + exch /Flags knownoget {4 and 4 eq not}{false}ifelse and + } {//false} ifelse + + 1 index /FontType get 2 eq and + { + 2 index /Encoding knownoget {pop StandardEncoding 2 index getencoding} { //null } ifelse + } + { + 2 index /Encoding known { + dup /Encoding knownoget { 2 index getencoding } { //null } ifelse + } { + //null + } ifelse + } ifelse + } 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 oknown { + dup //null eq { pop dup /Encoding get } if + 7 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 + dup 0 eq { + % FontMatrix.xx == 0, so we cannot scale down by xx. + % - FontMatrix[0] == 0 implies either FontMatrix[1] <> 0 or + % FontMatrix cannot be inverted. In the 1st case we have + % FontMatrixNonHV == true and will render text with cshow + xshow. + % In the 2nd case, metrics in the PDF Font object cannot be enforced + % [by altering metrics in PS glyph space]. + % HACK: + % - we scale down by FontMatrix[1]; + % - given the format of Metrics entries we use, wy = 0 in glyph space; + % - as a result, the cshow procedure receives as wy the value we + % need for wx (all of this in PS user space). + pop + 2 index /FontMatrix get 1 get + dup 0 eq { pop 1 } if % sorry, no way to enforce PDF metrics by altering the font + } if + div + % Stack: font font-res mscale + /FirstChar 2 index /FirstChar knownoget not { + ( **** Warning: /FirstChar attribute is missing, assuming 0.\n) pdfformatwarning + 0 + } if def + /LastChar 2 index /LastChar knownoget not { + ( **** Warning: /LastChar attribute is missing, assuming 255.\n) pdfformatwarning + 255 + } if def + + Encoding length LastChar le { + ( **** Warning: Font Encoding array size is smaller than character range.\n) + pdfformatwarning + } if + + 1 index /FontDescriptor knownoget { + /MissingWidth knownoget not { 0 } if + } + { 1000 + } + ifelse /MissingWidth exch def + + Widths length LastChar FirstChar sub le { + ( **** Warning: Font Widths array size is smaller than character range.\n) + pdfformatwarning + /Widths [Widths aload length LastChar FirstChar sub exch sub MissingWidth exch {dup} repeat] def + } if + FirstChar + + 0 Encoding + { % Stack: font font-res mscale first-char index charname + + 1 index FirstChar lt { MissingWidth } { + 1 index LastChar gt { MissingWidth } { Widths 2 index FirstChar sub get } ifelse + } ifelse + oforce + + % 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 + 1 add + } + forall pop pop pop + exch Encoding Metrics GlyphMap end + } { + //null //null + } ifelse +} bdef + +currentdict /unique_name undef +currentdict /match_in_diff undef + +/ToUnicodeCMapReader 4 dict begin + /defineresource % <name> <dict> <cat-name> defineresource <dict> + { + pop + dup userdict exch /.lastToUnicode exch put + exch pop + } bdef + + /CIDSystemInfo + { + ( **** Warning: ToUnicode CMap has invalid syntax near CIDSystemInfo.\n) pdfformatwarning + /CIDSystemInfo + } bdef % A work around a bug in Altona.Page_3.2002-09-27.pdf - a slash is missed. + + /CMapName + { + ( **** Warning: ToUnicode CMap has no CMapName.\n\ + See the comment to revision 6201 in gs/doc/ps2pdf.htm#Problems .\n) pdfformatwarning + /CMap1 % arbitrary, PDF defineresource tolerates non-unique names + } bdef % A work around incorrect ToUnicode CMap generated by GS before rev. 6201. + + % Split large ranges into smaller chunks to stay withing the limits + % of various PS% objects and speed up operand stack manipulation, + % esp. "counttomatk -3 roll". Bug 691908. + /beginbfrange { + { pop + mark + 256 { + currentfile token not { /endbfrange exit } if + dup /endbfrange eq { exit } if + currentfile token not { pop /endbfrange } if + currentfile token not { pop pop /endbfrange } if + dup ([) eq { + pop [ + { currentfile token not { exit } if + dup (]) eq { pop exit } if + } loop ] + } if + } repeat + dup /endbfrange eq { + pop endbfrange exit + } { + endbfrange + mark + } ifelse + } loop + } bdef +currentdict end readonly def + +/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 - +{ + CMAPDEBUG { + (.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 + { + CMAPDEBUG { + dup //== exec + } 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) + CMAPDEBUG { + ( offset=) print 4 index =string cvs print + ( key_size=) print 3 index =string cvs print + ( value_size=) print 2 index = + ( keys=) print 1 index //== exec + ( values=) print dup //== exec + } 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 length 1 index gt { + 4 index exch get + } if + } if % e [] i (values) cid|name + exch + CMAPDEBUG { + ( defined single: ) print 1 index =string cvs print ( ) print dup //== exec + } 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 + 6 index add + CMAPDEBUG { + ( 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 + 7 index add + CMAPDEBUG { + ( 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) + CMAPDEBUG { + ( defined from range: ) print 1 index =string cvs print ( ) print dup //== exec + } if + //true copy&def % e [] i offset key_size value_size (keys) (values) (value) + + %% Calculate the value from the last string + dup dup length 1 sub 0 exch 0 1 3 -1 roll + { + % (string) value index + exch 256 mul exch + 2 index exch get add + } for + + %% and increment the value for the next string + 1 add + + %% Now convert the value into a string of bytes. + 1 index length 1 sub 1 exch 0 1 3 -1 roll + { + % (string) value divisor index + 2 index 2 index idiv 255 and % (string) value divisor index byte + exch 4 index length 1 sub exch sub % (string) value divisor byte string_position + 5 index % (string) value divisor byte string_position (string) + exch 3 -1 roll put % (string) value divisor + 256 mul + } for + pop pop pop + } 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 % + CMAPDEBUG { + (.convert_ToUnicode-into-g2u end) = + } if +} bind def + +/.DoToUnicode? +{ + /IgnoreToUnicode where + {/IgnoreToUnicode get not} + {//true} ifelse +} bind def + +/.processToUnicode % <font-resource> <font-dict> <encoding|null> .processToUnicode - +{ + //.DoToUnicode? exec + { + currentdict count 1 sub /.stackdepth exch .forceput + currentdict countdictstack /.dstackdepth exch .forceput + { + 1 index /FontType get 0 eq + { + 1 index /FDepVector get 0 get + dup /FontType .knownget not + { + dup /CIDFontType .knownget + { dup 2 eq {pop 11} if } + {-1} % just some value that's not a valid font type + ifelse + }if + 11 eq + { /Path known} + {pop //false} + ifelse + } + {//false} ifelse + % Currently pdfwrite is only device which can handle GlyphNames2Unicoide to + % generate a ToUnicode CMaps. So don't bother with other devices. + /WantsToUnicode /GetDeviceParam .special_op { + exch pop + }{ + //false + }ifelse + or + { + PDFDEBUG { + (.processToUnicode beg) = + } if + 2 index /ToUnicode knownoget { + dup type /dicttype eq { dup /File known not } { //true } ifelse { + % We undefine wrong /Length and define /File in stream dictionaries. + % Bug687351.pdf defines /ToUnicode /Identity-H, what is incorrect. + ( **** Warning: Ignoring bad ToUnicode CMap.\n) pdfformatwarning + pop + } { + /PDFScanRules .getuserparam dup //null eq { + pop //PDFScanRules_null + } { + 1 dict dup /PDFScanRules 4 -1 roll put + } ifelse + //PDFScanRules_true setuserparams + PDFfile fileposition + 3 -1 roll + count 1 sub + countdictstack + { //false resolvestream + % Following Acrobat we ignore everything outside + % begincodespacerange .. endcmap. + dup 0 (begincodespacerange) /SubFileDecode filter flushfile + /CIDInit /ProcSet findresource begin + //ToUnicodeCMapReader begin + 12 dict begin + /CMapType 2 def + mark exch % emulate 'begincodespacerange' + 0 (endcmap) /SubFileDecode filter cvx /begincmap cvx exch 2 .execn + endcmap + userdict /.lastToUnicode currentdict put + end end end + } + + PDFSTOPONERROR { + { exec } 0 get + //false + 5 -2 roll + 5 + } { + { stopped } 0 get + 4 2 roll + 4 + } ifelse + array astore cvx exec + + countdictstack exch sub 0 .max { end } repeat + count exch sub 2 sub 0 .max { exch pop } repeat + 3 1 roll % Stach the stop flag. + PDFfile exch setfileposition + setuserparams + { + ( **** Warning: Failed to read ToUnicode CMap.\n) pdfformatwarning + } { + 1 index /FontInfo .knownget not { + currentglobal 2 index dup gcheck setglobal + /FontInfo 5 dict dup 5 1 roll .forceput + setglobal + } if + dup /GlyphNames2Unicode .knownget not { + //true % No existing G2U, make one + } { + dup wcheck { + //false % Existing, writeable G2U, don't make new one + } { + pop //true % Existing read only G2U, make new one + } ifelse + } ifelse + { + 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 + } ifelse + } if + PDFDEBUG { + (.processToUnicode end) = + } if + } if + } stopped + { + .dstackdepth 1 countdictstack 1 sub + {pop end} for + .stackdepth 1 count 3 sub + {pop pop} for + } if + pop pop pop + currentdict /.stackdepth .forceundef + currentdict /.dstackdepth .forceundef + } + {pop pop pop} + ifelse + +} bind def + +currentdict /.DoToUnicode? .forceundef + +% ---------------- 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 + dup type /nametype ne { + ( **** Error: /FontName in FontDescriptor is not a name.\n) + pdfformaterror + ( Output may be incorrect.\n) pdfformaterror + cvn + } if + } { + ( **** Error: FontDescriptor missing required /FontName key. BaseFont name used.\n) + pdfformaterror + ( Output may be incorrect.\n) pdfformaterror + pop 2 index % grab the BaseFont from the stack. + } ifelse + .remove_font_name_prefix + exch + % Analyzes font name and extract "Bold" and "Narrow" properties + % which are not described by the FontDescriptor Flags. + % We also allow the font name analysis to override the Flags setting + % for Italic/Oblique as this gives us results more consistent with + % Acrobat. + 0 2 index .fontnameproperties 7 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 + {//false} + { .buildnativefontmap pop NativeFontmap 1 index known not} ifelse + + { + % 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 + + % Some non-compliant files are missing FirstChar/LastChar, + % despite referencing a non-base14 font + 3 index /FirstChar knownoget + { + 0 % push an initial value for accumating the Widths + 0 string % and an empty string to interrogate the font + 7 index /Widths knownoget + { + 0 1 2 index length 1 sub + { + dup 2 index exch get dup 0 gt % We ignore entries of zero in the widths array + { + exch 5 index add % add FirstChar to the idx to get a char code + dup 64 gt 1 index 91 lt and % we only want to consider A~Z and.... + 1 index 96 gt 2 index 123 lt and or % ... a~z + { + exch + 5 -1 roll add 4 1 roll % add the width to the accumulator on the stack + 1 string dup 0 4 -1 roll put + 3 -1 roll concatstrings exch % add the char code to the string + } + { + pop pop + } ifelse + } + { + pop pop + } ifelse + } for + pop % get rid of the Widths array + 3 -1 roll pop % get rid of the FirstChar value + dup length dup 0 gt + { + 3 -1 roll exch div % calculate an average width from the Widths array + + gsave + 2 index 10 scalefont setfont + exch dup length exch stringwidth + grestore + pop 100 mul exch div div + % Only make the font smaller/narrower, not larger/wider + dup 1.0 lt + { + 0 0 2 index 0 0 6 array astore + exch //true .copyfontdict + dup /FontMatrix get 3 -1 roll matrix concatmatrix + exch dup 3 -1 roll /FontMatrix exch put + % we don't need to definfont here, we can leave that to .completefont below + } + { + pop + } ifelse + } + { + % no suitable Widths entries - carry on and hope for the best...... + pop pop pop + } ifelse + } + { + % Broken file: no Widths array for non-base14 font - carry on and hope for the best...... + ( **** Warning: Widths array missing in FontDescriptor for non-base14 font\n) + pdfformatwarning + pop pop pop + } ifelse + } + { + ( **** Warning: FirstChar value missing in FontDescriptor for non-base14 font\n) + pdfformatwarning + } ifelse + % 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 + exch pop .completefont + } { + % 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 + +% Read an embedded Type 1 font. +/readfontfilter { % <proc> readfontfilter <filter> + 0 () /SubFileDecode filter +} bdef + +% Adobe Acrobat doesn't skip space characters after eexec +/eexec_pdf_param_dict mark + .eexec_param_dict {} forall + /keep_spaces //true +.dicttomark readonly def + +% When Type 1 font reading procedure is executing, a copy of this dictionary is current. +% We have to do something special about embedded fonts that execute definefont +% more than once -- that is the function of topFontDict. +% The whole type1 stream can be executed directly. There's no need to process +% Length1, 2, 3 keys. + +/readtype1dict 10 dict dup begin + /definefont { + exch pop + + /topFontDict where { + { /FontType % in PLRM order + /FontMatrix + /FontName + /FontInfo + /WMode + /Encoding + /FontBBox + /UniqueID + /XUID + /PaintType + /StrokeWidth + /Metrics + /Metrics2 + /CDevProc + /CharStrings + /Private + /WeightVector + } { + 2 copy .knownget { + % Stack: font topFontDict /key val + 3 index 3 1 roll put + dup /MisplacedKey 0 put + } { + pop + } ifelse + } forall + /MisplacedKey known { + ( **** Warning: Type 1 font defines some of the keys in the external scope.\n) + pdfformatwarning + } if + } if + + dup /UniqueID .knownget { + dup dup 0 lt exch 16#ffffff gt or { + ( **** Warning: Ignoring invalid /UniqueID = ) exch =string cvs + concatstrings (\n) concatstrings pdfformatwarning + dup /UniqueID undef + } { + pop + } ifelse + } if + dup /CharStrings get /.notdef known not { + dup /CharStrings get + /.notdef <9E35CED7FFD3622F09> put + ( **** Warning: Type 1 font has no /.notdef entry in /CharString dictionary.\n) + pdfformatwarning + } if + .completefont + } bdef + + /undef_proc_warning { + /Repaired //true store % flag that we have warnings + UndefProcList exch 2 copy .knownget { 1 add } { 1 } ifelse put + } bdef + + /missing-type1-procs 6 dict begin + /-| { string currentfile exch readstring pop /-| //undef_proc_warning exec } executeonly bdef + /RD { string currentfile exch readstring pop /RD //undef_proc_warning exec } executeonly bdef + /|- { noaccess def /|- //undef_proc_warning exec } executeonly bdef + /ND { noaccess def /ND //undef_proc_warning exec } executeonly bdef + /| { noaccess put /| //undef_proc_warning exec } executeonly bdef + /NP { noaccess put /NP //undef_proc_warning exec } executeonly bdef + currentdict end readonly def + + /eexec { + % Assume the font dictionary is directly below the file on the stack + count 0 gt { /topFontDict 2 index cvlit store } if + //eexec_pdf_param_dict /eexecDecode filter + + //missing-type1-procs begin + /userdict .systemvar begin + //systemdict begin + readtype1dictcopy begin cvx stopped + + currentfile flushfile % Skip the trailer after return from eexec, bug 690701. + { currentdict end //missing-type1-procs eq { exit } if } loop + { stop } if + } bdef + + /readonly-op-dict << + /stringtype 0 + /arraytype 0 + /packedarraytype 0 + /dicttype 0 + >> readonly def + + /readonly { % bug 689617 + dup type //readonly-op-dict exch known not { + ( **** Warning: Type 1 font applies operator readonly to an invalid object type.\n) + pdfformatwarning + } if + } bdef + + /prev_get /get load def + + /get { + dup /FontName eq { + % No warning, probably FontName is defined elsewhere; see definefont above. + .knownget not { /Missing } if + } { + dup /UniqueID eq { + % We don't want fonts to check /UniqueID and do 'restore'. + pop pop 16#FEDCBA98 % Arbitrary and invalid value + } { + prev_get + } ifelse + } ifelse + } bdef + + /prev_begin /begin load def + + /begin { + dup //systemdict eq { pop 0 dict } if + prev_begin + } bdef + + { /undef_proc_warning /missing-type1-procs /readonly-op-dict } + { currentdict exch undef } forall + +end readonly def + +currentdict /eexec_pdf_param_dict .undef + +/readtype1 { % <font-resource> <stream-dict> readtype1 <font|null> + PDFfile fileposition 3 1 roll % pos res stream + dup /PFB known exch % pos res pfb? stream + //true resolvestream % pos res pfb? file + exch { + //false /PFBDecode filter % pos res file' + } if + % 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. This code also removes the mark when + % the implied cleartomark is not executed, i.e. Length3 == 0. + % Also restore dictstack depth. + % + //systemdict begin + //readtype1dict dup length 5 add dict copy begin % pos res file' + /file-position 4 -1 roll def % res file' + /stack-count count 3 sub def + 1 index /BaseFont oget /savedFontName exch def + /topFontDict //null def + /readtype1dictcopy currentdict def + cvx stopped + { currentdict /topFontDict known not { end } { exit } ifelse } loop + { /topFontDict //null def } if + PDFfile file-position setfileposition + count stack-count sub { pop } repeat + topFontDict end end + } 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 knownoget not { /PDFType3Untitled } 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 + Encoding exch get CharProcs exch knownoget { + { //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 fileposition 2 .execn % Keep pdfcount valid. + PDFfile exch setfileposition + } { + % PDF Type 3 fonts don't use .notdef + % d1 implementation adjusts the width as needed + 0 0 0 0 0 0 + pdfopdict /d1 get exec + } ifelse + end end + } bdef + dup currentdict Encoding .processToUnicode + currentdict end .completefont exch pop +} bdef +/.adjustcharwidth { % <wx> <wy> .adjustcharwidth <wx'> <wy'> + % Enforce the metrics, in glyph space, to the values found in the PDF Font object + % - force wy == 0 (assumed, and not stored in the PDF font) + % Even though PDF1.3-1.7 specifications state 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. + % PDF1.2 does not mention this restriction, it only says + % "see setcharwidth/ setcachedevice in the PostScript Reference". + % - get wx from the Widths array (do nothing if not present) + pop 0 + /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 + dup /font_name gput + + 1 index /FontDescriptor knownoget + { + /Flags knownoget + { + 4 and 0 ne + { //true } % symbolic + { 1 index /Encoding oknown not} % no encoding => symbolic + ifelse + } + {//false} + ifelse + } + {//false} + ifelse + + /is_symbolic gput + 1 index /Encoding oknown { + StandardEncoding + 3 index getencoding + } { + //null + } ifelse + /prebuilt_encoding gput + //false /.render_notdef gput % set the default + + dup /Font resourcestatus dup { exch pop exch pop } if not + TTfonts 2 index known and { + dup TTfonts exch get + 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 + exch pop .completefont + } { + pdffindfont + } ifelse +} bdef + +% Read an embedded TrueType font. +/readtruetype { % <font-resource> <stream-dict> readtruetype <font> + 1 index exch + PDFfile fileposition 3 1 roll + //true resolvestream readfontfilter + % Stack: filepos fontres stream + 1 index /CIDSystemInfo oknown { + 1 index /CIDSystemInfo get dup type /packedarraytype eq {exec}if + 3 1 roll + 1 index /Subtype knownoget { + /CIDFontType2 ne { + ( **** Error: Subtype of a TT CID font is not /CIDFontType2\n) pdfformaterror + 1 index /Subtype /CIDFontType2 put + ( Output may be incorrect.\n) pdfformaterror + } if + } { + ( **** Error: Subtype of a TT CID font is missing.\n) pdfformaterror + 1 index /Subtype /CIDFontType2 put + ( Output may be incorrect.\n) pdfformaterror + } ifelse + + 1 index /BaseFont get % Use the BaseFont name for the font. Otherwise we + % would use the name table, or a manufactured name. + .loadttcidfont + % Stack: filepos fontres cidfont + } { + % filepos fontres stream + 1 index /FontDescriptor oget + /Flags oget 4 and 0 ne { + //true % symbolic + } { + 1 index /Encoding oknown not % no encoding => symbolic + } ifelse + + 2 index /Encoding oknown { + StandardEncoding + 3 index getencoding + } { + //null + } ifelse + + dup 4 index exch % filepos fontres stream is_symbolic Encoding fontres Encoding + /prebuilt_encoding exch put % filepos fontres stream is_symbolic Encoding + 5 index /BaseFont get % Use the BaseFont name for the font. Otherwise we + % would use the name table, or a manufactured name. + .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 + +/CMap_read_dict 3 dict begin + /defineresource % <name> <dict> <cat-name> defineresource <dict> + { + pop + /.last_CMap_def 1 index store + exch pop + } bdef + /CIDSystemInfo + { + ( **** Error: CMap has invalid syntax near CIDSystemInfo.\n) pdfformaterror + ( Output may be incorrect.\n) pdfformaterror + /CIDSystemInfo + } bdef % A work around a bug in Altona.Page_3.2002-09-27.pdf - a slash is missed. + /CMapName + { + ( **** Error: CMap has no CMapName.\n\ + See the comment to revision 6201 in gs/doc/ps2pdf.htm#Problems .\n) pdfformaterror + ( Output may be incorrect.\n) pdfformaterror + /CMap1 % arbitrary, PDF defineresource tolerates non-unique names + } bdef % A work around incorrect ToUnicode CMap generated by GS before rev. 6201. +currentdict end readonly def + +% Read an embedded stream that we *hope* is a PostScript CMap. According +% to the spec, ths isn't legal, but 'Acrobat opens it'.... +% +/read_CMap { + dup mark exch 0 (begincodespacerange) /SubFileDecode filter cvx exec + cleartomark + {currentdict dup /CMapType known not {end}{pop exit} ifelse} loop + /CMapType 1 def + mark exch % emulate 'begincodespacerange' + 0 (endcmap) /SubFileDecode filter cvx /begincmap cvx exch 2 .execn + endcmap + currentdict end + dup /CMapName get exch + /CMap defineresource end +} bdef + +% Read embedded CMap stream. +% if the <wmode> parameter is null, it indicates there is no WMode, and we +% should not add one. +% Following Acrobat we ignore everything outside +% begincodespacerange .. endcmap. +/read_CMap_stream { % <info> <wmode> <name> <stream> read_CMap <CMap> + dup 0 (begincodespacerange) /SubFileDecode filter flushfile + //CMap_read_dict begin + /CIDInit /ProcSet findresource begin + 12 dict begin + 4 2 roll + dup //null eq { pop } { /WMode exch def } ifelse + dup //null eq { pop } { /CIDSystemInfo exch def } ifelse + /CMapType 1 def + /.last_CMap_def currentdict def % establish binding + mark exch % emulate 'begincodespacerange' + 0 (endcmap) /SubFileDecode filter cvx /begincmap cvx exch 2 .execn + endcmap + /.last_CMap_def load + { currentdict end //CMap_read_dict eq { exit } if } loop + dup /.last_CMap_def undef + /CMap defineresource +} bdef + +currentdict /CMap_read_dict undef + +/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 + } { + %% Bug #696449 Acrobat will read an embedded PostScript + %% CMap, whcih according to the spec is not valid, it needs + %% to be a PDF CMap stream. Here we check and see if it looks like a CMap + %% dictionary. If it is we proceed, if its some other kind of dictionary, + %% throw an error, if its neither, treat it as a stream and hope for the best. + dup /Type known { + dup /Type get /CMap eq { + PDFfile fileposition exch + dup /CIDSystemInfo knownoget { + << exch { oforce } forall >> + } { + //null + } ifelse exch + dup /WMode knownoget not {//null} if exch + dup /CMapName knownoget not {/null} if exch + //true resolvestream + read_CMap_stream + exch PDFfile exch setfileposition + } { + PDFSTOPONERROR { + /buildType0 cvx /syntaxerror signalerror + } if + } ifelse + }{ + PDFfile fileposition exch + //true resolvestream + read_CMap + exch PDFfile exch setfileposition + } ifelse + } ifelse % CMap + [ + 3 index /DescendantFonts oget { exec resourcefont } forall + ] % subfonts + .composefontdict % composefont must insert FontInfo dictionary - see gs_cmap.ps . + % Stack: fontres name font + 3 copy exch pop //null .processToUnicode + exch pop .completefont % Stack: fontres font + + 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 + exch pop .completefont + } { + 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 knownoget { + 1 index /DW 3 -1 roll put + } { + dup /DW .pdfDefaultDW put + } ifelse + + 1 index /W knownoget { + //false 1 index { xcheck or } forall { + oforce_array + } if + dup 2 index /W 3 -1 roll put + .pdfMakeInternalW 1 index /.internalW 3 -1 roll put + } if + + 1 index /DW2 knownoget { + 1 index /DW2 3 -1 roll put + } { + dup /DW2 .pdfDefaultDW2 put + } ifelse + + 1 index /W2 knownoget { + //false 1 index { xcheck or } forall { + oforce_array + } if + 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 2 add itemSize add def + } + >> def + + /i 0 def + + [ { putMTXEntry Mi1 type get exec i Msize ge { exit } if } loop ] + end +} def + +/.pdfMakeInternalW { dup length 0 gt { oforce_recursive 1 .pdfMakeInternalMTXArray } if } def +/.pdfMakeInternalW2 { dup length 0 gt { oforce_recursive 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 + + % get FontMatrix that applies to this CID + % (needs to convert [D]W[2] values to glyph space) + currentdict /FontMatrix get + % if the currentfont is a CIDFontType 0 CIDFont, + % we need FDArray font's FontMatrix too + FontType 9 eq { + currentdict 2 index .type9mapcid + % <w0x> <w0y> <llx> <lly> <urx> <ury> <cid> <FontMatrix> (charstring) <FDArray#> + exch pop currentdict /FDArray get exch get /FontMatrix get + % <w0x> <w0y> <llx> <lly> <urx> <ury> <cid> <FontMatrix> <FontMatrix2> + matrix concatmatrix + } if + % preserve this FontMatrix at bottom of the stack + 8 1 roll + % Stack: <FontMatrix> <w0x> <w0y> <llx> <lly> <urx> <ury> <cid> + + { + 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 + 0 % <w0y'> + + % Stack: <FontMatrix> <w0x> <w0y> <llx> <lly> <urx> <ury> <cid> <w0x'> <w0y'> + 9 -2 roll pop pop % discard <w0x> <w0y> + 7 2 roll % put <w0x'> <w0y'> + + % Stack: <FontMatrix> <w0x'> <w0y'> <llx> <lly> <urx> <ury> <cid> + 0 % <w1x'> + exch % put <w1x'> + + % Stack: <FontMatrix> <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: <FontMatrix> <w0x'> <w0y'> <llx> <lly> <urx> <ury> + % <w1x'> { [<vy'> <w1y'>] | [<w1y'> <vx'> <vy'>] } + dup length 2 eq { % this is DW2 + aload pop + exch 8 index 2 div % <vx'> = <w0x'> / 2 + exch + } { % assume W2 + aload pop + } ifelse + % Stack: <FontMatrix> <w0x'> <w0y'> <llx> <lly> <urx> <ury> <w1x'> <w1y'> <vx'> <vy'> + + % now, convert each metrics valude (1000th of text space) to glyph space + 10 -2 roll + % Stack: <FontMatrix> <llx> <lly> <urx> <ury> <w1x'> <w1y'> <vx'> <vy'> <w0x'> <w0y'> + 3 { + 10 index idtransform exch 1000 div exch 1000 div + 6 2 roll + } repeat + 10 2 roll + % Stack: <FontMatrix> <w0x'> <w0y'> <llx> <lly> <urx> <ury> <w1x'> <w1y'> <vx'> <vy'> + 11 -1 roll pop + % Stack: <w0x'> <w0y'> <llx> <lly> <urx> <ury> <w1x'> <w1y'> <vx'> <vy'> + 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 + % If we're substituting a standard weight font for a + % "Light,Bold" font, don't artificially bolden further + dup (Light) tailmatch + { + pop cvn findCIDFont dup /FontName .knownget + { + (Light) tailmatch exch pop + } + { + //true + } ifelse + + { + 0.03 makeboldfont + } if + } + { + pop + cvn findCIDFont 0.03 makeboldfont + } ifelse + exit + } if + (,Italic) tailmatch { + exch pop + cvn findCIDFont + [ 1 0 0.3 1 0 0 ] makefont + exit + } if + (,BoldItalic) tailmatch { + exch pop + % see above + dup (Light) tailmatch + { + pop cvn findCIDFont dup /FontName .knownget + { + (Light) tailmatch exch pop + } + { + //true + } ifelse + + { + 0.03 makeboldfont + } if + } + { + pop + cvn findCIDFont 0.03 makeboldfont + } ifelse + [ 1 0 0.3 1 0 0 ] makefont + exit + } if + QUIET not { + (Can't find CID font ") print dup =string cvs print (".) = flush + } if + pop + + 1 index /CIDSystemInfo oget begin Registry (-) Ordering end + concatstrings concatstrings + cvn + QUIET not { + (Attempting to substitute CID font ) print dup ==only + ( for ) print 1 index ==only (, see doc/Use.htm#CIDFontSubstitution.) = flush + } if + exch pop + dup /CIDFont resourcestatus { + pop pop /CIDFont { findresource } stopped + {pop}{exit} ifelse + } if + QUIET not { + (The substitute CID font ") print dup =string cvs print + (" is not provided either. ) print + } if + + PDFNOCIDFALLBACK { + PDFSTOPONERROR { + (Will exit with error.) = flush + } + { + (Will attempt to continue, but content may be missing.) = flush + } ifelse + exit + } if + + QUIET not { + (attempting to use fallback CIDFont.) print + (See doc/Use.htm#CIDFontSubstitution.) = flush + } if + + PDFNOCIDFALLBACK not { + % This previously worked by loading the substitute font, and using that + % as a "template" to create a new CIDFont dictionary with the CIDSystemInfo + % dict appropriate for the requested font. + % This, however, caused problems with the CIDMap and thus broke pdfwrite. + % Hence, we now modify the CIDFont resource .map dictionary on the fly + % so it includes an appropriate mapping, so the subsitute font is loaded + % from the beginning with the correct ordering and supplement settings. + /CIDFont /Category findresource /.map get dup /CIDFallBack .knownget { + dup type /dicttype eq { + dup /FileType get /TrueType eq { + currentglobal + 4 1 roll + dup gcheck setglobal + dup length dict copy dup + 6 index /CIDSystemInfo oget dup /Ordering oget exch /Supplement get + % we have to copy the string, for VM correctness + exch dup length string copy exch 2 array astore + /CSI exch put 2 index exch .forceput + exch setglobal + { + % This *should* not execute arbitrary Postscript, so we ought to + % be safe running in a stopped context, in knowledge we know how + % to clean up afterwards - this would not be safe if CIDFallBack + % were a "real" CIDFont. + /CIDFont findresource + } + % if the above fails, try just using the CIDFallBack font directly + stopped + { + pop + % First, since it didn't work, remove the entry from the CIDFont category + % .map dictionary. + currentglobal exch + /CIDFont /Category findresource /.map get + dup gcheck setglobal + exch undef + setglobal + + (Warning: falling back to Identity ordering\n) print flush + /CIDFallBack /CIDFont findresource + } if + exit + } if + } if + } if + + pop pop pop + /CIDFallBack + + QUIET not { + (The fallback CID font ") print dup =string cvs print + (" is not provided. ) print + ( Finally attempting to use ArtifexBullet.\n) print flush + }if + + % We'll just use Identity for this, we have only one glyph anyway. + /ArtifexBullet /CIDFont resourcestatus { + pop pop pop + /ArtifexBullet /CIDFont findresource + exit + } + { + pop /ArtifexBullet + } ifelse + + QUIET not { + (The CID font ") print dup =string cvs print + (" is not provided. ) print + PDFSTOPONERROR + { + (Will exit with error.) = flush + } + { + (Will continue, but content may be missing.) = flush + } ifelse + } if + } if + /findresource cvx /undefined signalerror + } 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 + [ + { counttomark 1 add index 32768 string readstring not { + counttomark 1 eq { + exch pop dup length + } { + ] dup 0 exch { length add } forall + } ifelse + exit + } if + } loop + 2 idiv + % Stack: filepos fontres font mapstream array/string CIDCount + dup 0 ne { + 3 index exch /CIDCount exch put + exch closefile exch + dup /CIDMap 4 -1 roll put + }{ + % If CIDCount is zero, ignore it + pop pop closefile + }ifelse + } ifelse + 3 2 roll PDFfile exch setfileposition + } if +} bdef + +% Adjust a CIDFontType0 DW[2] in the font resource. +/adjustCIDType0 { % <font-resource> <font> adjustfont <font'> + dup /FontType get 1 eq { + ( **** Error: Font resource has a wrong /Subtype.\n) pdfformaterror + ( Output may be incorrect.\n) pdfformaterror + adjustfont + } { + addCIDmetrics + dup /CIDFontName get exch /CIDFont defineresource + } ifelse +} bind def + +% Adjust a CIDFontType2 DW[2] and CIDToGIDMap in the font resource. +/adjustCIDType2 { % <font-resource> <font> adjustfont <font'> + dup /FontType get 1 eq { + ( **** Error: Font resource has a wrong /Subtype.\n) pdfformaterror + ( Output may be incorrect.\n) pdfformaterror + adjustfont + } { + addCIDmetrics + dup /CIDFontType get 2 eq { % OpenType CFF font converts to CIDFontType 0 + processCIDToGIDMap % that ignores CIDMap. + } if + dup /CIDFontName get exch /CIDFont defineresource + } ifelse +} bind def + +% ---------------- Other embedded fonts ---------------- % + +% 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 + /FontSetInit /ProcSet findresource begin //true //false ReadData + %% We need to be careful not to corrupt the stack if something went wrong. + %% Previously, if the dict was length 0 (an error occured) we would end up + %% unable to recover the stack in the calling procedure. + %% Bug #695819. + dup length 0 ne { + { exch pop exit } forall + 7 1 roll + }{ + /invalidfont signalerror + } ifelse + closefile closefile pop + PDFfile 3 -1 roll setfileposition + pop 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 + /FontSetInit /ProcSet findresource begin //true //true ReadData pop + 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 + +% Read an embedded OpenType font. +/readOTTOfont { % <font-resource> <stream-dict> readOTTOfont <font> + 1 index exch % res res strdict + PDFfile fileposition 3 1 roll % res pos res strdict + dup //true resolvestream % res pos res strdict stream + dup readfontfilter % res pos res strdict stream filter + 3 index /FontDescriptor oget + /FontName oget % res pos res strdict stream filter /name + 1 index .init_otto_font_file % res pos res strdict stream filter /name filter' + //true + 6 index /CIDSystemInfo known % res pos res strdict stream filter /name filter' bool bool + ReadData % res pos res strdict stream filter fontset + { exch pop exit } forall % res pos res strdict stream filter font + dup /FontType get 9 eq { + % OpenType may contain simple CFF font, which is accesed as a CIDFont by PDF. + % The font is converted to Type 9 CIDFont resource, which ignores CIDMap attribute. + % The following code just shuffles GlyphDirectory to the same effect. + 4 index /CIDToGIDMap knownoget { + dup type /dicttype eq { + 1 index /GlyphDirectory get exch % res pos res strdict stream filter font dir c2g + //true resolvestream % res pos res strdict stream filter font dir c2g_file + 256 dict begin + 0 2 index 0 get def % copy .notdef + 0 1 16#7fffffff { + 1 index read not { pop exit } if % res pos res strdict stream filter font dir c2g_file cid hi + 256 mul % res pos res strdict stream filter font dir c2g_file cid hi + 2 index read not { pop pop exit } if % res pos res strdict stream filter font dir c2g_file cid hi lo + add % res pos res strdict stream filter font dir c2g_file cid gid + dup 0 ne { + dup 4 index length lt { + 3 index exch get % res pos res strdict stream filter font dir c2g_file cid charstr + def % res pos res strdict stream filter font dir c2g_file + } { + pop pop + } ifelse + } { + pop pop + } ifelse + } for + closefile pop % res pos res strdict stream filter font + dup length dict copy % res pos res strdict stream filter font' + dup /GlyphDirectory currentdict put % res pos res strdict stream filter font' + end + dup /GlyphDirectory get 0 exch { + pop .max + } forall + 1 index exch /CIDCount exch 1 add put + } { + pop + } ifelse + } if + } if + 7 1 roll % font res pos res strdict stream filter + closefile closefile pop pop % font res pos + PDFfile exch setfileposition % font res + pop % font +} bdef + +% ---------------- Font lookup ---------------- % + +% Some PDF files mis-identify font type of the embedded font streams or +% include raw PFB font streams. Length1, Length2, Length3 may be wrong or +% missing. Adobe Acrobat corrects these errors transparently to the user. +% +% We ignore the font type keys and recognize the font type by the 1st 4 bytes +% of the font stream. The PFB stream is recognized by the 1st 2 bytes. + +/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 + +% Bind a proc and define n names +% /name ... /name {proc} n bndef - +/bndef + { exch bind exch + { dup 3 1 roll def } repeat + pop + } bdef + +% <res> run-fonttypeproc <font> +/run-fonttypeproc { + dup /Subtype knownoget not { 0 } if % res /subtype + //fonttypeprocs 1 index known not { + ( **** Error: Font /Subtype attribute is wrong or missing, /Type1 assumed.\n) + pdfformaterror + ( Output may be incorrect.\n) pdfformaterror + pop /Type1 + 2 copy /Subtype exch put + } if + //fonttypeprocs exch get exec +} bdef + +% Prototype for all procedures: <res> <desc> <stream> foo <font> +/font_tag_dict 13 dict begin + + % When the font stream is absent or cannot be read we load the font by the name. + /no_stream + { pop pop + run-fonttypeproc + } bdef + + /bad_stream + { ( **** Error: Error reading font stream, attempting to load the font using its name\n) + pdfformaterror + ( Output may be incorrect.\n) pdfformaterror + //no_stream exec + } bdef + + <8001> % PFB + { dup /PFB //true put + exch pop readtype1 + } bdef + + (%!PS) (%!Fo) % Type1 + { exch pop readtype1 + } 2 bndef + + <01000401> <01000402> <01000403> <01000404> % Type 1C + <01000C02> <01000C03> + { exch pop + 1 index /Subtype knownoget dup { pop /CIDFontType0 eq } if { + readCIDFontType0C + } { + readType1C + } ifelse + } 6 bndef + + <00010000> (true) (typ1) (ttcf) % TrueType OpenType + { exch pop readtruetype + } 4 bndef + + (OTTO) + { exch pop + readOTTOfont + } bdef + +currentdict end readonly def +currentdict /bndef undef + +% Used to create a hash for the XUID, ths combines the input PDF file name and the +% object number (currently the object number of the FontDescriptor). NB we *must* +% use an object number, as otherwise all fonts will have the same +% XUID and Ghostscript will think they are the same font. Ths routine must not +% be used unless we have an object number which is believed to be uniqe to +% a particular font instance. +/.CRCHashFilenameAndObject % object_number (filename) CRCHasFilename integer +{ + dup % object_number (filename) (filename) + length % object_number (filename) length + 0 exch % object_number (filename) hash length + 1 sub % object_number (filename) hash length-1 + 0 1 3 -1 roll % object_number (filename) hash 0 1 length-1 + { % object_number (filename) hash index + 2 index exch get % object_number (filename) hash char + exch % object_number (filename) char hash + dup 16#F8000000 and % object_number (filename) char hash top5bits + -27 bitshift % object_number (filename) char hash top5>>27 + exch 5 bitshift % object_number (filename) char top5>>27 hash<<5 + 16#7FFFFFFF and + xor % object_number (filename) char CRC<hash> + xor % object_number (filename) newhash + } for + exch pop % object_number newhash + dup 16#F8000000 and % object_number newhash top5bits + -27 bitshift % object_number newhash top5>>27 + exch 5 bitshift % object_number top5>>27 newhash<<5 + 16#7FFFFFFF and + xor % object_number CRC<newhash> + xor % final hashed value +}bind def + +% Either patch or create a new XUID based on the existing +% XUID or UniqueID and incorporating the PDF object number +% so we get an XUID we can use to improve cache efficiency +% in multipage documents. +/patch_font_XUID % <font dict> <patch> patch_font_XUID <font dict'> +{ + %% Allow users to specify that we should not care about font object numbers + %% that is, don't patch the XUID with the object number and filename. + /PDFDontUseFontObjectNum where {/PDFDontUseFontObjectNum get}{//false}ifelse + %% Do not modify the XUID if we don't have an object number (see above) + 1 index //null eq + or + {pop} + { + pdfdict /InputPDFFileName .knownget {.CRCHashFilenameAndObject} if + exch dup /.OrigUniqueIDXUID .knownget not + { + dup /XUID .knownget not + { + dup /UniqueID .knownget + {1 array astore}{ [] } ifelse + } if + } if + + dup //null eq + { + pop exch pop + } + { + [ 1000000 3 -1 roll 4 index exch {exch} forall ] + exch //true .copyfontdict + dup 3 -1 roll /XUID exch put + exch pop + .completefont + } ifelse + } ifelse +} bind def + +/resourcefont % <font-resource> resourcefont <font> +{ + dup /PSFont .knownget dup { + pop /FID knownoget dup { pop type /fonttype eq } if + } if { + /PSFont get + } { + + dup /Subtype get /Type0 eq { + % if the font was defined in-line, we won't have a object number + dup /.gs.pdfobj# .knownget not { //null } if + } { + dup /FontDescriptor knownoget { + % if the font was defined in-line, we won't have a object number + dup /.gs.pdfobj# .knownget not { //null }if + dup //null eq { + exch pop + }{ + exch dup /FontFile knownoget not { + dup /FontFile2 knownoget not { + dup /FontFile3 knownoget not { + pop pop //null + } {pop pop}ifelse + } {pop pop}ifelse + }{pop pop}ifelse + }ifelse + }{ + //null + } ifelse + } ifelse + 3 1 roll + + % In the event we have a Type 0 dictionary with a spurious + % FontDescriptor object, remove it here to prevent confusion + % later on. + % Bug 691589 + dup /Subtype get /Type0 eq 1 index /FontDescriptor known and + { + dup /FontDescriptor undef + }if + dup /CIDSystemInfo .knownget + { + oforce_recursive + 1 index exch /CIDSystemInfo exch put + } if + + dup dup /FontDescriptor knownoget { + % font-res font-res font-desc + % The same font descriptor can be reused in a CID and non-CID contexts. + % Store CID and non-CID fonts under different keys. Bug 689301 + 1 index /Subtype knownoget dup { + pop dup /CIDFontType0 eq exch /CIDFontType2 eq or + } if { /CIDFontObject } { /FontObject } ifelse + % font-res font-res font-desc /key + 2 index 1 index .knownget { + 4 1 roll pop pop pop % font-res obj + } { + 4 1 roll % /key font-res font-res font-desc + + dup /FontFile knownoget not { + dup /FontFile2 knownoget not { + dup /FontFile3 knownoget not { + //null + } if + } if + } if + % /key res res desc stream + dup //null ne { + PDFfile fileposition + mark { + 2 index //true resolvestream dup + 4 string readstring pop + exch closefile + } stopped { + cleartomark /bad_stream + } { + exch pop + } ifelse + PDFfile 3 -1 roll setfileposition + dup length 4 lt { pop /bad_stream } if + } { + /no_stream + } ifelse + % /key res res desc stream tag + + //font_tag_dict 1 index known not { + dup 0 2 getinterval <8001> eq { + 0 2 getinterval % /key res res desc stream pfb_tag + } { + (12345678>\n) dup /ASCIIHexEncode filter dup 4 -1 roll writestring closefile + ( **** Error: unrecognized font file starts with <) exch concatstrings + pdfformaterror + ( Output may be incorrect.\n) pdfformaterror + /no_stream % /key res res desc stream unknown_tag + } ifelse + } if + //font_tag_dict exch get % /key res res desc stream {proc} + { stopped } 0 get % /key res res desc stream {proc} --stopped-- + count % /key res res desc stream {proc} --stopped-- # + countdictstack % /key res res desc stream {proc} --stopped-- # ## + PDFfile fileposition % /key res res desc stream {proc} --stopped-- # ## ### + 5 array astore cvx % /key res res desc stream {{proc} --stopped-- # ## ###} + exec + 4 -1 roll { + PDFSTOPONERROR not { + PDFfile exch setfileposition + countdictstack exch sub 0 .max { end } repeat + count 4 add exch sub 0 .max { pop } repeat + //null + } { + /resourcefont cvx /undefinederror signalerror + } ifelse + } { + PDFfile exch setfileposition + countdictstack exch sub 0 .max { end } repeat + count 3 sub exch sub 0 .max { pop } repeat + } ifelse + dup //null eq { + PDFSTOPONERROR not { + pop + ( **** Error: can't process embedded font stream,\n attempting to load the font using its name.\n) + pdfformaterror + ( Output may be incorrect.\n) pdfformaterror + dup run-fonttypeproc % /key res font + } { + /resourcefont cvx /undefinederror signalerror + } ifelse + } if + 1 index % /key res font res + 4 -1 roll 2 index % res font desc /key font + put % Save pointer to the font. + } ifelse + } { + run-fonttypeproc + } ifelse + % Stack: font-res font + 1 index exch + 1 index /Subtype get + //adjustfonttypes exch .knownget { exec } { exch pop } ifelse + 4 -1 roll patch_font_XUID + dup 3 1 roll /PSFont exch put + } ifelse + dup checkGlyphNames2Unicode +} bdef + +currentdict /font_tag_dict .undef +currentdict /fonttypeprocs .undef +currentdict /adjustfonttypes .undef + +drawopdict begin + /d0 { + currentcolor currentcolorspace .swapcolors setcolorspace setcolor .swapcolors + .adjustcharwidth setcharwidth + } bdef + /d1 { + 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 + //d0 exec + } { + 6 -2 roll .adjustcharwidth 6 2 roll setcachedevice + } ifelse + } bdef + /Tf { + 1 index Page /Font rget { + dup type /dicttype eq { + resourcefont exch + Tf pop + } + { + PDFSTOPONERROR + { + /typecheck cvx signalerror + } + { + % Bug 689450 + type + ( **** Error: Tf refers to a resource key with an invalid value type: ) pdfformaterror + .namestring pdfformaterror + (. Assuming resource key: ) pdfformaterror + 1 index .namestring pdfformaterror + ( is a font name.\n) pdfformaterror + ( Output may be incorrect.\n) pdfformaterror + Tf + } ifelse + }ifelse + } + { + PDFSTOPONERROR + { + pop /undefined cvx signalerror + } + { + % Bug 689037 + ( **** Error: Tf refers to an unknown resource name: ) pdfformaterror + 1 index .namestring pdfformaterror + ( Assuming it's a font name.\n) pdfformaterror + ( Output may be incorrect.\n) pdfformaterror + Tf + } ifelse + } ifelse + } bdef +end + +end % pdfdict +end % GS_PDF_ProcSet +.setglobal |