summaryrefslogtreecommitdiff
path: root/Master/tlpkg/tlgs/Resource/Init/pdf_font.ps
diff options
context:
space:
mode:
Diffstat (limited to 'Master/tlpkg/tlgs/Resource/Init/pdf_font.ps')
-rw-r--r--Master/tlpkg/tlgs/Resource/Init/pdf_font.ps2526
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