summaryrefslogtreecommitdiff
path: root/Master/tlpkg/tlgs/lib/pdf_font.ps
diff options
context:
space:
mode:
Diffstat (limited to 'Master/tlpkg/tlgs/lib/pdf_font.ps')
-rw-r--r--Master/tlpkg/tlgs/lib/pdf_font.ps1557
1 files changed, 1557 insertions, 0 deletions
diff --git a/Master/tlpkg/tlgs/lib/pdf_font.ps b/Master/tlpkg/tlgs/lib/pdf_font.ps
new file mode 100644
index 00000000000..d9cf7adb199
--- /dev/null
+++ b/Master/tlpkg/tlgs/lib/pdf_font.ps
@@ -0,0 +1,1557 @@
+% Copyright (C) 1994, 2000 Aladdin Enterprises. All rights reserved.
+%
+% This software is provided AS-IS with no warranty, either express or
+% implied.
+%
+% This software is distributed under license and may not be copied,
+% modified or distributed except as expressly authorized under the terms
+% of the license contained in the file LICENSE in this distribution.
+%
+% For more information about licensing, please refer to
+% http://www.ghostscript.com/licensing/. For information on
+% commercial licensing, go to http://www.artifex.com/licensing/ or
+% contact Artifex Software, Inc., 101 Lucas Valley Road #110,
+% San Rafael, CA 94903, U.S.A., +1(415)492-9861.
+
+% $Id: pdf_font.ps 8093 2007-06-30 23:46:18Z alexcher $
+% PDF font operations.
+
+% Finding a font by name can't give a proper result when PDF font names aren't unique.
+% But it is only the way to obtain a font in Postscript after a font file is executed.
+% Therefore using a FontName (and findfont) is allowed only
+% immediately after a font file is executed.
+% In all other cases the font to be found by a pointer through PDF structures.
+%
+% This ideal logics can't work for documents,
+% which define a font resource with an embedded font,
+% and another font resource with same BaseFont but with no embedded font
+% (and possibly with no font descriptor).
+% Our testbase does contain such examples.
+% In this case we do find font by FontName (with findfont),
+% since there is no other way to get a reasonable result.
+
+/.setlanguagelevel where { pop 2 .setlanguagelevel } if
+.currentglobal true .setglobal
+/pdfdict where { pop } { /pdfdict 100 dict def } ifelse
+GS_PDF_ProcSet begin
+pdfdict begin
+
+% We cache the PostScript font in an additional element of the
+% font resource dictionary, called PSFont.
+
+% ---------------- Encodings ---------------- %
+
+/.notdefEncoding 256 { /.notdef } repeat 256 packedarray def
+
+% Apply a list of differences to an Encoding.
+% Note that the differences may cause the array to grow.
+/updateencoding { % <encoding|null> <differences> updateencoding <enc'>
+ % Calculate the length of the result.
+ % in case the incoming Encoding is null, use .notdefEncoding
+ exch dup null eq { pop .notdefEncoding } if
+ 0 0 3 index {
+ dup type /nametype ne { exch pop oforce } { pop 1 add } ifelse
+ % Differences list may not be in order, update the largest_index
+ % stack: <Differences> <encoding> <largest_index> <at_index>
+ 2 copy lt { exch pop dup } if % at_index is new largest
+ } forall
+ pop 1 index length .max array dup 0 4 -1 roll putinterval
+ exch 0 exch {
+ % Stack: enc' code element
+ dup type /nametype ne
+ { exch pop oforce }
+ { 3 copy put pop 1 add }
+ ifelse
+ } forall pop
+} bdef
+
+% Get the Encoding for a font.
+/getencoding % <base-encoding> <font-resource> getencoding <enc>
+ { /Encoding knownoget
+ { dup type /nametype eq
+ {
+ % The published PDF specification says the Encoding name
+ % "must be" one of the 3 predefined Encodings, implying
+ % that an error should occur if it isn't. However, Acrobat
+ % Reader simply ignores unknown names, and since there are
+ % some buggy applications that rely on this, we do the same.
+
+ dup dup dup /MacRomanEncoding eq
+ exch /MacExpertEncoding eq or
+ exch /WinAnsiEncoding eq or
+ { exch pop findencoding }
+ { pop }
+ ifelse
+ }
+ { dup type /arraytype eq
+ { exch pop
+ ( **** Warning: Encoding is an array, not name or dictionary.\n) pdfformaterror
+ }
+ { dup /BaseEncoding knownoget
+ { dup / eq
+ { pop
+ ( **** Warning: Ignoring bad BaseEncoding name.\n) pdfformaterror
+ % as found in a PDF file from J.D.Edwards OneWorld (B7333), bug 687786
+ }
+ { findencoding 3 -1 roll pop exch }
+ ifelse
+ }
+ if
+ /Differences knownoget { updateencoding } if
+ }
+ ifelse
+ }
+ ifelse
+ } {
+ ( **** Warning: Encoding not present.\n) pdfformaterror
+ }
+ ifelse
+ } bdef
+
+/checkGlyphNames2Unicode % <dict> checkGlyphNames2Unicode -
+{
+ PDFDEBUG {
+ dup /FontInfo .knownget {
+ /GlyphNames2Unicode .knownget {
+ (Has GlyphNames2Unicode) =
+ pop % { exch == ==} forall
+ } if
+ } if
+ } if
+ pop
+} bind def
+
+% Define a font using it's FontName as the key.
+% Adjust a font according to the Encoding and Widths in the font resource.
+/adjustfont { % <font-resource> <font> adjustfont <font'>
+ getfontencoding
+ 3 copy .processToUnicode
+ getfontmetrics 5 -1 roll pop .updatefont { dup /FontName get exch definefont } if
+} bind def
+
+% Get the (possibly modified) encoding of a font.
+/getfontencoding { % <font-resource> <font> getfontencoding
+ % <font-resource> <font> <Encoding|null>
+ //systemdict /IgnoreTTEncoding .knownget not { //false } if {
+ 1 index /Subtype get /TrueType eq } { //false } ifelse {
+ //null
+ } {
+ 1 index /Encoding known {
+ dup /Encoding knownoget { 2 index getencoding } { //null } ifelse
+ } {
+ //null
+ } 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 known {
+ 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 div
+ % Stack: font font-res mscale
+ /FirstChar 2 index /FirstChar oget def
+ /LastChar 2 index /LastChar oget def
+
+ Encoding length LastChar le {
+ ( **** Warning: Font Encoding array size is smaller than character range.\n)
+ pdfformaterror
+ } 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)
+ pdfformaterror
+ /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
+
+ % 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 3 dict begin
+ /defineresource % <name> <dict> <cat-name> defineresource <dict>
+ {
+ pop
+ dup userdict exch /.lastToUnicode exch put
+ exch pop
+ } bind def
+ /CIDSystemInfo
+ {
+ ( **** Warning: ToUnicode CMap has invalid syntax near CIDSystemInfo.\n) pdfformaterror
+ /CIDSystemInfo
+ } bind def % A work around a bug in Altona.Page_3.2002-09-27.pdf - a slash is missed.
+ /CMapName
+ {
+ ( **** Warning: ToUnicode CMap has no CMapName.\n\
+ See the comment to revision 6201 in gs/doc/ps2pdf.htm#Problems .\n) pdfformaterror
+ /CMap1 % arbitrary, PDF defineresource tolerates non-unique names
+ } bind def % A work around incorrect ToUnicode CMap generated by GS before rev. 6201.
+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 -
+{
+ PDFDEBUG {
+ (.convert_ToUnicode-into-g2u beg) =
+ } if
+ 3 2 roll begin
+ /.CodeMapData get % About the data format see gs_cmap.ps, the comment after "CMap operators".
+ 1 get % code maps
+ {
+ PDFDEBUG {
+ dup ==
+ } if
+ dup length 1 sub 0 exch 5 exch { % e [] i
+ 2 copy get % e [] i (prefix)
+ string2number % e [] i prefix
+ 2 index 2 index 1 add get % e [] i prefix (key_size,?is_range,value_type,value_size)
+ dup 0 get 8 mul % e [] i prefix (key_size,?is_range,value_type,value_size) key_size*8
+ 3 2 roll exch bitshift exch % e [] i prefix<<key_size*8 (key_size,?is_range,value_type,value_size)
+ dup 0 get exch 3 get % e [] i offset key_size value_size
+ 4 index 4 index 2 add get % e [] i offset key_size value_size (keys)
+ 5 index 5 index 3 add get % e [] i offset key_size value_size (keys) (values)
+ PDFDEBUG {
+ ( offset=) print 4 index =string cvs print
+ ( key_size=) print 3 index =string cvs print
+ ( value_size=) print 2 index =
+ ( keys=) print 1 index ==
+ ( values=) print dup ==
+ } if
+ 1 index length 0 eq {
+ % A single pair.
+ exch pop exch pop exch pop exch % e [] i (values) offset
+ 4 index null ne {
+ 4 index length 1 index gt {
+ 4 index exch get
+ } if
+ } if % e [] i (values) cid|name
+ exch
+ PDFDEBUG {
+ ( defined single: ) print 1 index =string cvs print ( ) print dup ==
+ } if
+ false copy&def % e [] i
+ pop % e []
+ } {
+ % A range. % e [] i offset key_size value_size (keys) (values)
+ dup length string copy % protect the original string from modifications below.
+ 0 4 index 2 mul 3 index length 1 sub { % e [] i offset key_size value_size (keys) (values) j
+ 2 index 1 index 6 index getinterval
+ string2number % e [] i offset key_size value_size (keys) (values) j keyL
+ PDFDEBUG {
+ ( keyL=) print dup =string cvs print
+ } if
+ 3 index 2 index 7 index add 7 index getinterval
+ string2number % e [] i offset key_size value_size (keys) (values) j keyL keyH
+ PDFDEBUG {
+ ( keyH=) print dup =
+ } if
+ 3 2 roll 6 index idiv 5 index mul % e [] i offset key_size value_size (keys) (values) keyL keyH J
+ 3 index exch 6 index getinterval % e [] i offset key_size value_size (keys) (values) keyL keyH (valueL)
+ 3 1 roll 1 exch { % e [] i offset key_size value_size (keys) (values) (value) k
+ 9 index null ne {
+ 9 index exch get % e [] i offset key_size value_size (keys) (values) (value) name
+ } if % e [] i offset key_size value_size (keys) (values) (value) cid|name
+ 1 index % e [] i offset key_size value_size (keys) (values) (value) cid|name (value)
+ PDFDEBUG {
+ ( defined from range: ) print 1 index =string cvs print ( ) print dup ==
+ } if
+ true copy&def % e [] i offset key_size value_size (keys) (values) (value)
+ % Assuming the lowest byte of 'value' changes, others don't.
+ dup dup length 1 sub % e [] i offset key_size value_size (keys) (values) (value) (value) l
+ 2 copy get % e [] i offset key_size value_size (keys) (values) (value) (value) l v
+ % Modulo 256 increment prevents a rangecheck error when the result is stored in a string.
+ % The adjustment can happen only at the end of the loop where the string is discarded. Bug 688535.
+ 1 add 255 and put % e [] i offset key_size value_size (keys) (values) (value')
+ } for % e [] i offset key_size value_size (keys) (values) (value)
+ } for
+ pop pop pop pop pop pop pop % e []
+ } ifelse
+ } for
+ pop % e
+ } forall
+ end
+ pop %
+ PDFDEBUG {
+ (.convert_ToUnicode-into-g2u end) =
+ } if
+} bind def
+
+/.processToUnicode % <font-resource> <font-dict> <encoding|null> .processToUnicode -
+{
+ % Currently pdfwrite is only device which can handle GlyphNames2Unicoide to
+ % generate a ToUnicode CMaps. So don't bother with other devices.
+ currentdevice .devicename /pdfwrite eq {
+ PDFDEBUG {
+ (.processToUnicode beg) =
+ } if
+ 2 index /ToUnicode knownoget {
+ dup type /nametype eq {
+ % Bug687351.pdf defines /ToUnicode /Identity-H, what is incorrect.
+ ( **** Warning: Ignoring bad ToUnicode CMap.\n) pdfformaterror
+ pop
+ } {
+ PDFfile fileposition exch
+ false resolvestream
+
+ //ToUnicodeCMapReader begin
+ % Following Acrobat we ignore everything outside begincmap..endcmap.
+ dup 0 (begincmap) /SubFileDecode filter flushfile
+ /CIDInit /ProcSet findresource begin 12 dict begin
+ 0 (endcmap) /SubFileDecode filter cvx /begincmap cvx exch 2 .execn
+ endcmap
+ userdict /.lastToUnicode currentdict put
+ end end end
+
+ PDFfile exch setfileposition
+ 1 index /FontInfo .knownget not {
+ 1 index /FontInfo 5 dict dup 4 1 roll put
+ } if
+ dup /GlyphNames2Unicode .knownget not {
+ currentglobal exch dup gcheck setglobal
+ dup /GlyphNames2Unicode 100 dict dup 4 1 roll .forceput
+ 3 2 roll setglobal
+ } if % font-res font-dict encoding|null font-info g2u
+ exch pop exch % font-res font-dict g2u encoding|null
+ userdict /.lastToUnicode get % font-res font-dict g2u Encoding|null CMap
+ .convert_ToUnicode-into-g2u % font-res font-dict
+ null % font-res font-dict null
+ } ifelse
+ } if
+ PDFDEBUG {
+ (.processToUnicode end) =
+ } if
+ } if
+ pop pop pop
+} bind def
+
+% ---------------- Descriptors ---------------- %
+
+% Partial descriptors for the 14 built-in fonts. Note that
+% from PDF 1.1 to PDF 1.2, the meaning of the Flag 6 in the FontDescriptor
+% object has undergone a subtle change in its meaning which has serious
+% consequences for searching with Acrobat:
+% In PDF 1.1, the flag meant: Font has StandardEncoding
+% In PDF 1.2, the flag means: Font has (subset of) StandardRomanCharacterSet
+/standardfontdescriptors mark
+ /Courier mark /Flags 16#23 .dicttomark
+ /Courier-Oblique 1 index
+ /Courier-Bold 1 index
+ /Courier-BoldOblique 1 index
+ /Helvetica mark /Flags 16#20 .dicttomark
+ /Helvetica-Oblique 1 index
+ /Helvetica-Bold 1 index
+ /Helvetica-BoldOblique 1 index
+ /Times-Roman mark /Flags 16#22 .dicttomark
+ /Times-Bold 1 index
+ /Times-Italic mark /Flags 16#62 .dicttomark
+ /Times-BoldItalic 1 index
+ /Symbol mark /Flags 16#4 .dicttomark
+ /ZapfDingbats 1 index
+.dicttomark readonly def
+
+% ---------------- Utilities ---------------- %
+
+
+/.pdforigfontcache_g 20 dict def
+currentglobal false setglobal
+systemdict /.pdforigfontcache_l 20 dict .forceput
+setglobal
+
+% Find an original font, using cache to prevent adjustfont to accumulate changes.
+/pdffindcachedfont { % <font_name> pdffindcachedfont <font>
+ dup //.pdforigfontcache_g exch .knownget {
+ exch pop
+ } {
+ dup .pdforigfontcache_l exch .knownget {
+ exch pop
+ } {
+ dup findfont dup
+ dup gcheck { //.pdforigfontcache_g } { .pdforigfontcache_l } ifelse
+ % Stack : font_name font font cache
+ 4 2 roll .growput
+ } ifelse
+ } ifelse
+} bind def
+
+% Add original font to cache to prevent adjustfont to accumulate changes.
+/pdfaddcachedfont { % <font_name> pdfaddcachedfont <font>
+ dup findfont dup % name font font
+ dup gcheck { //.pdforigfontcache_g } {.pdforigfontcache_l} ifelse
+ 4 2 roll % font d name font
+ put % font
+} bind def
+
+/.remove_font_name_prefix { % <name> .remove_font_name_prefix <name>
+ dup .namestring (+) search {
+ true exch
+ { dup 65 lt exch 90 gt or {
+ pop false exit
+ } if
+ } forall
+ { pop exch pop cvn
+ } {
+ pop pop
+ } ifelse
+ } {
+ pop
+ } ifelse
+} bind def
+
+% Find a font (except for embedded ones), and adjust its encoding if necessary.
+/.pdfdfndict mark
+ /defaultfontname /Helvetica
+.dicttomark readonly def
+/pdffindfont { % <font-resource> <fontname> pdffindfont <font>
+ % If the font isn't available, synthesize one based on
+ % its descriptor.
+ dup /Font resourcestatus {
+ pop pop pdffindcachedfont
+ } {
+ 1 index /FontDescriptor knownoget {
+ % Stack: font-res fontname fontdesc
+ dup /Flags oget
+ dup 16#40 and -6 bitshift % 1, oblique/italic
+ 1 index 16#40000 and -17 bitshift add % 2, bold
+ exch 16#2 and 2 bitshift add % 8, serif
+ % We should look at the fixed flag, too.
+ % Stack: font-res fontname fontdesc properties
+
+ % Even though /FontName is a required key in FontDescriptor dict
+ % (As of the PDF 1.4 Reference Manual), In the case of missing
+ % /FontName key, we substitue /BaseFont for the value of /FontName.
+ % Yet another case of broken PDF's that Adobe Reader accepts.
+ 1 index dup /FontName known {
+ /FontName oget
+ } {
+ ( **** FontDescriptor missing required /FontName key. BaseFont name used.\n)
+ pdfformaterror
+ pop 2 index % grab the BaseFont from the stack.
+ } ifelse
+ .remove_font_name_prefix
+ exch
+ % Analyzes font name and extract "Bold" and "Narrow" properties
+ % which are not described by the FontDescriptor Flags.
+ 0 2 index .fontnameproperties 6 and or
+ % Rebind the default font name to Helvetica so that
+ % fonts with no properties are handled correctly.
+ //.pdfdfndict begin .substitutefontname end
+ % Stack: font-res fontname fontdesc substname|null
+ Fontmap 1 index known not {
+ % No available good substitution, use the standard one.
+ pop 1 index .substitutefont
+ } if
+ dup 3 index ne QUIET not and {
+ (Substituting font ) print dup =only
+ ( for ) print 2 index =only (.) = flush
+ } if
+ pdffindcachedfont
+ % Stack: font-res fontname fontdesc font
+ % If this is a small-caps font, replace the CharString
+ % entries for a..z.
+ exch /Flags oget 16#20000 and 0 ne {
+ true .copyfontdict
+ dup /CharStrings 2 copy get dup length dict .copydict
+ % stack: font-res fontname font font /CharStrings CharStringsdict
+ 5 index /FirstChar get 97 .max
+ 6 index /LastChar get 122 .min 1 exch {
+ % Stack: font-res fontname font' font' /CharStrings charstrings code
+ % Note that this only remaps a-z, not accented characters.
+ 6 index /Widths oget 1 index 8 index /FirstChar get sub oget
+ 1 string dup 0 5 -1 roll put
+ % Stack: font-res font' font' /CharStrings charstrings code
+ % width (x)
+ 2 index exch dup cvn exch
+ dup 0 2 copy get 32 sub put 4 -1 roll {
+ % Stack: operand (X) width
+ 0 setcharwidth exch pop
+ currentfont /FontMatrix get matrix invertmatrix concat
+ 0.7 dup scale 0 0 moveto show
+ } /exec cvx 4 packedarray cvx put
+ } for put
+ } if
+ dup /FontName get 2 index ne {
+ true .copyfontdict
+ 2 copy exch /FontName exch put
+ } if
+ definefont
+ } {
+ % No descriptor available, use the default algorithm.
+ pdffindcachedfont
+ } ifelse
+ } ifelse
+ exch pop
+} bdef
+
+% ---------------- Type 1 fonts ---------------- %
+
+/buildType1 % <Type1-font-resource> buildType1 <font>
+ { dup /BaseFont get pdffindfont
+ } bdef
+
+% Read an embedded Type 1 font.
+/readfontfilter { % <proc> readfontfilter <filter>
+ 0 () /SubFileDecode filter
+} bdef
+
+% 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 5 dict dup begin
+ /definefont {
+ dup topFontDict eq topFontDict null eq or {
+ dup wcheck not { dup length dict copy } if
+ exch pop savedFontName exch
+ } if
+ //systemdict /definefont get exec
+ } bdef
+
+ /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_param_dict /eexecDecode filter
+
+ //missing-type1-procs begin
+ /userdict .systemvar begin
+ //systemdict begin
+ readtype1dictcopy begin cvx stopped
+
+ { currentdict end //missing-type1-procs eq { exit } if } loop
+ { stop } if
+ } bdef
+
+ currentdict dup
+ /undef_proc_warning undef
+ /missing-type1-procs undef
+
+end readonly def
+
+/readtype1 { % <font-resource> <stream-dict> readtype1 <font>
+ 1 index exch % res res stream
+ PDFfile fileposition 3 1 roll % res pos res stream
+ dup /PFB known exch % res pos res pfb? stream
+ true resolvestream % res pos res pfb? file
+ exch {
+ //false /PFBDecode filter
+ } 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
+ % The PDF specification is somewhat muddy about whether
+ % an embedded font's name is supposed to be the BaseFont
+ % from the Font object or the FontName from the descriptor.
+ % Acrobat Distiller requires the former. Save away the
+ % name so we can substitute it at definefont time.
+ //readtype1dict dup length 3 add dict copy begin
+ 1 index /BaseFont oget /savedFontName exch def
+ /topFontDict null def
+ /readtype1dictcopy currentdict def
+ { cvx exec } aload pop count 2 sub 3 packedarray cvx exec
+ % clean up the dictstack
+ { currentdict /topFontDict known not { end } { end end exit } ifelse } loop
+ count exch sub { pop } repeat
+ PDFfile 3 -1 roll setfileposition
+ /BaseFont oget pdfaddcachedfont
+ exch pop
+ } bdef
+
+% ---------------- Type 3 fonts ---------------- %
+
+/buildType3 { % <Type3-font-resource> buildType3 <font>
+ 8 dict begin
+ /FontType 3 def
+ % If the font does not contain a Resources entry, then we use
+ % the resources from our current context. Page 391 of the PDF
+ % 1.6 spec says that the Resources dict is optional and if not
+ % present then we should use the Resources for the page.
+ % However we have a test file (687989) which uses a Type3 font
+ % inside a form XObject and the desired Resources are in the
+ % XObject dict and not in the Page dict. So we are going to
+ % the parent object to find resources instead of only going to
+ % the page dict when a font does not specify its required
+ % resources.
+ /Resources 1 index /Resources knownoget {
+ oforce
+ } {
+ LocalResources
+ } ifelse def
+ /FontBBox 1 index /FontBBox get cvx def
+ /FontMatrix 1 index /FontMatrix oget def
+ /CharProcs 1 index /CharProcs oget def
+ 1 index /Widths knownoget {
+ /Widths exch def
+ /FirstChar 1 index /FirstChar oget def
+ /LastChar 1 index /LastChar oget def
+ } if
+ /FontName 1 index /Name .knownget not {
+ PDFfile fileposition 16 32 string cvrs cvn
+ } if def
+
+ /Encoding .notdefEncoding 2 index getencoding def
+ % We have to define BuildChar rather than BuildGlyph:
+ % there is no PDF equivalent of glyphshow, and we need
+ % the character code to access the Widths.
+ /BuildChar {
+ % Stack: font charcode
+ 1 index begin 3 dict begin
+ /Font 3 -1 roll def /CharCode 1 index def
+ % Make unknown characters map to /.notdef
+ Encoding exch get dup CharProcs exch known
+ { CharProcs exch oget }
+ { pop CharProcs /.notdef oget }
+ ifelse
+ PDFfile fileposition exch
+ false resolvestream
+ % Stack: filepos stream
+ % Don't let setgcolor set the color inside the BuildGlyph
+ % procedure, because this causes an /undefined error.
+ q null /FillColor gput null /StrokeColor gput
+ Font /Resources get exch pdfopdict .pdfruncontext
+ Q
+ PDFfile exch setfileposition
+ end end
+ } bdef
+ dup currentdict Encoding .processToUnicode
+ FontName currentdict end definefont exch pop
+} bdef
+/.adjustcharwidth { % <wx> <wy> .adjustcharwidth <wx'> <wy'>
+ /Widths where {
+ begin
+ CharCode FirstChar ge CharCode LastChar le and {
+ exch pop Widths CharCode FirstChar sub get exch
+ } if end
+ } if
+} bdef
+
+% ---------------- TrueType fonts ---------------- %
+
+/TTfonts mark
+ /Arial /Helvetica
+ /Arial,Italic /Helvetica-Oblique
+ /Arial,Bold /Helvetica-Bold
+ /Arial,BoldItalic /Helvetica-BoldOblique
+ /CourierNew /Courier
+ /CourierNew,Bold /Courier-Bold
+ /TimesNewRoman /Times-Roman
+ /TimesNewRoman,Italic /Times-Italic
+ /TimesNewRoman,Bold /Times-Bold
+ /TimesNewRoman,BoldItalic /Times-BoldItalic
+.dicttomark readonly def
+
+/buildTrueType { % <TrueType-font-resource> buildTrueType <font>
+ dup /BaseFont oget
+ /Repaired true store % flag that we had warnings
+ TTFWarnList 1 index true put % Add fontname to the list
+ dup /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
+ definefont
+ } {
+ 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 /Subtype get /CIDFontType2 eq {
+ .loadttcidfont
+ % Stack: filepos fontres cidfont
+ } {
+ % filepos fontres stream
+ 1 index /FontDescriptor oget % filepos fontres stream fd
+ /Flags get 4 and 0 ne % filepos fontres stream is_symbolic
+ dup { //null } { StandardEncoding } ifelse
+ 3 index /Encoding known {
+ 3 index getencoding
+ } if % filepos fontres stream is_symbolic Encoding
+ dup 4 index exch % filepos fontres stream is_symbolic Encoding fontres Encoding
+ /prebuilt_encoding exch put % filepos fontres stream is_symbolic Encoding
+ .loadpdfttfont
+ } ifelse
+ exch pop
+ PDFfile 3 -1 roll setfileposition
+ % Ignore both the Encoding and the Widths.
+ exch pop
+} bdef
+
+% ---------------- Type 0 fonts ---------------- %
+
+% Predefine the known CMaps, but only create them on demand.
+/knownCMaps mark
+ /Identity-H { /Identity-H 0 makeIdentityCMap }
+ /Identity-V { /Identity-V 1 makeIdentityCMap }
+.dicttomark def
+
+/makeIdentityCMap { % <cmapname> <wmode> .makeIdentityCMap -
+ .currentglobal true .setglobal 3 1 roll
+ /CIDInit /ProcSet findresource begin
+ 12 dict begin
+ begincmap
+ /WMode exch def
+ /CMapName exch def
+ /CIDSystemInfo 3 dict dup begin
+ /Registry (Adobe) def
+ /Ordering (Identity) def
+ /Supplement 0 def
+ end def
+ %/CMapName (see above)
+ /CMapVersion 1 def
+ /CMapType 1 def
+ %WMode (see above)
+ % The PDF documentation says that these CMaps map CIDs
+ % "1 to 65,536". This is a misprint for 0 to 65,535.
+ 1 begincodespacerange
+ % <0001> <00ff> <0100> <ffff>
+ <0000> <ffff>
+ endcodespacerange
+ 1 begincidrange
+ % <0001> <00ff> 1 <0100> <ffff> 256
+ <0000> <ffff> 0
+ endcidrange
+ endcmap
+ CMapName currentdict /CMap defineresource
+ knownCMaps CMapName 2 index put
+ end % CMap
+ end % CIDInit ProcSet
+ exch .setglobal
+} bdef
+
+/buildType0 { % <Type0-font-resource> buildType0 <font>
+ dup /BaseFont get % FontName
+ 1 index /Encoding oget
+ dup type /nametype eq {
+ dup /CMap resourcestatus {
+ pop pop /CMap findresource
+ } {
+ knownCMaps 1 index .knownget
+ { exch pop exec } { /undefined signalerror } ifelse
+ } ifelse
+ } {
+ PDFfile fileposition exch
+ dup /CMapName get exch true resolvestream cvx exec
+ /CMap findresource
+ exch PDFfile exch setfileposition
+ } ifelse % CMap
+ [
+ 3 index /DescendantFonts oget { exec resourcefont } forall
+ ] % subfonts
+ .composefontdict % composefont must insert FontInfo dictionary - see gs_cmap.ps .
+ % Stack: fontres name font
+ 3 copy exch pop null .processToUnicode
+ /Font defineresource % 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 definefont
+ } {
+ pop
+ } ifelse
+ } if exch pop
+} bdef
+
+% ---------------- CIDFontType0/2 fonts ---------------- %
+
+% Insert metrics into a CIDFont, by saving the PDF W, W2, DW, and DW2
+% arrays and using a (currently very inefficient) CDevProc.
+% For detail, refer "PDF Reference" 2nd ed., p314 "5.6.3 CIDFonts".
+% It notes default DW is 0, but Acrobat Reader uses 1000 as default.
+% If DW is 0, currentpoint does not move by default in rendering text
+% horizontally, the result is unreadable. You can check it by Acrobat.
+
+/.pdfDefaultDW 1000 def
+/.pdfDefaultDW2 [ 880 -1000 ] def
+
+/addCIDmetrics { % <CIDFont-resource> <CIDFont> addCIDmetrics <fontdict>
+ dup length 5 add dict .copydict
+ dup /FID undef
+ dup /UniqueID undef
+ dup /XUID undef
+ % Insert the widths into the font.
+
+ % Stack: pdfresource newfont
+
+ 1 index /DW knownoget {
+ 1 index /DW 3 -1 roll put
+ } {
+ dup /DW .pdfDefaultDW put
+ } ifelse
+
+ 1 index /W knownoget {
+ 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 {
+ dup 2 index /W2 3 -1 roll put
+ .pdfMakeInternalW2 1 index /.internalW2 3 -1 roll put
+ } if
+
+ dup /CDevProc 1 index /CIDWProc load /exec load 3 packedarray cvx put
+ exch pop
+} bdef
+
+/.pdfMakeInternalMTXArray { % <mtx_array> <item_size> .pdfConvertInternalW <mtx_array'>
+
+ % convert /W or /W2 to internal expression
+ %
+ % mtx_array: original /W or /W2 array
+ % item_size: number of metrics values per CID
+ %
+ % for detail of the metrics list format in PDF,
+ % refer PDF Ref. p.317 "Glyph Metrics in CIDFonts".
+ %
+ % format of single entry in internal expression
+ %
+ % [
+ % [cid_begin cid_end]
+ % value_is_varied (bool)
+ % [ [values for cid_begin...]
+ % [values for cid_begin + 1]
+ % ... ]
+ % ]
+ %
+
+ 7 dict
+ begin
+ /itemSize exch def
+ /M exch def % original /W or /W2
+ /Msize M length def
+ /Mi { M i get } def % W[i]
+ /Mi1 { M i 1 add get } def % W[i + 1]
+ /putMTXEntry <<
+ /arraytype {
+ [
+ [Mi Mi Mi1 length itemSize idiv add 1 sub]
+ true
+ [
+ 0 itemSize Mi1 length 1 sub {
+ [ exch 1 1 index itemSize add 1 sub { Mi1 exch get } for ]
+ } for
+ ]
+ ]
+ /i i 2 add def
+ }
+ /integertype {
+ [
+ [Mi Mi1]
+ false
+ [[ i 2 add 1 i 1 add itemSize add { M exch get } for ]]
+ ]
+ /i i 3 add def
+ }
+ >> def
+
+ /i 0 def
+
+ [ { putMTXEntry Mi1 type get exec i Msize ge { exit } if } loop ]
+ end
+} def
+
+/.pdfMakeInternalW { dup length 0 gt { 1 .pdfMakeInternalMTXArray } if } def
+/.pdfMakeInternalW2 { dup length 0 gt { 3 .pdfMakeInternalMTXArray } if } def
+
+/.pdfGetMTXByCID { % <internalMTXArray> <cid>
+ % .pdfGetMTXByCID
+ % { <MTXEntry> true | false }
+
+ % get values for given CID from internal format of /W or /W2
+
+ exch
+ {
+ {
+ dup 0 get {} forall % Stack: <cid> <entry> <cid_0> <cid_1>
+ 3 index lt { pop pop false exit } if
+ 2 index exch sub dup 0 lt { pop pop false exit } if
+ 1 index 1 get not { pop 0 } if
+ exch 2 get exch get true exit
+ } loop
+ { exit } if
+ } forall
+ dup type /arraytype eq { exch pop true } { pop false } ifelse
+} def
+
+
+% Apply the [D]W[2] metrics to a character before displaying.
+/CIDWProc { % <w0x> <w0y> <llx> <lly> <urx> <ury>
+ % <w1x> <w1y> <vx> <vy> <cid> <font> CIDWproc
+ % <w0x'> ... <vy'>
+ begin % push <font> to currentdict
+ % <w1x> <w1y> <vx> <vy> won't be used and replaced, discard now
+ 5 1 roll pop pop pop pop
+
+ {
+ currentdict /DW .knownget not { % no DW
+ .pdfDefaultDW exit % replace <w0x> by defaultDW
+ } if
+
+ currentdict /.internalW .knownget not { % no W
+ exit % use already-stacked DW
+ } if
+
+ dup length 0 eq { % W is null array
+ pop % discard unusable W
+ exit % use already-stacked DW
+ } if
+
+ % W is finite array, try to get W_cid
+ 2 index .pdfGetMTXByCID { % got W, discard DW
+ exch pop {} forall
+ exit
+ } if
+
+ exit
+ } loop
+
+ FontType 11 eq {
+ 1000 div % <w0x'> (normalized W)
+ } if
+ 0 % <w0y'>
+
+ % Stack: <w0x> <w0y> <llx> <lly> <urx> <ury> <cid> <w0x'> <w0y'>
+ 9 -2 roll pop pop % discard <w0x> <w0y>
+ 7 2 roll % put <w0x'> <w0y'>
+
+ % Stack: <w0x'> <w0y'> <llx> <lly> <urx> <ury> <cid>
+ 0 % <w1x'>
+ exch % put <w1x'>
+
+ % Stack: <w0x'> <w0y'> <llx> <lly> <urx> <ury> <w1x'> <cid>
+ {
+ currentdict /DW2 .knownget not { % no DW2, use defaultDW2
+ .pdfDefaultDW2 exit
+ } if
+
+ currentdict /.internalW2 .knownget not { % has DW2, no W2
+ exit % use already-stacked DW2
+ } if
+
+ dup length 0 eq { % W2 is null array
+ pop % discard unusable W2
+ exit % use already-stacked DW2
+ } if
+
+ 2 index .pdfGetMTXByCID { % got W2_cid, discard DW2
+ exch pop
+ exit
+ } if
+
+ % could not get W2_cid
+ exit
+
+ } loop
+
+ exch pop % discard <cid>
+
+ % Stack: <w0x'> <w0y'> <llx> <lly> <urx> <ury> <w1x'> { [<vy'> <w1y'>] | [<w1y'> <vx'> <vy'>] }
+ dup length 2 eq { % this is DW2
+ FontType 11 eq {{1000 div}} {{}} ifelse forall exch
+ 8 index 2 div % <vx'> = <w0x'> / 2
+ exch
+ }{ % assume W2
+ FontType 11 eq {{1000 div}} {{}} ifelse forall
+ } ifelse
+ end % recover currentdict
+
+} def
+
+% <string> <match> tailmatch ==> <pre> true
+% ==> <string> false
+/tailmatch {
+ 2 copy length 1 index length .min
+ dup 2 index length exch sub exch getinterval
+ 1 index eq {
+ length 1 index length exch sub
+ 0 exch getinterval true
+ } {
+ pop false
+ } ifelse
+} bind def
+
+/makeboldfont {
+ 16 dict begin
+ /strokewidth exch def
+ /basecidfont exch def
+ /FontMatrix [ 1 0 0 1 0 0 ] def
+
+ /CIDFontName /.boldfont def
+ /CIDFontType 1 def
+
+ /basefont-H /.basefont-H /Identity-H [ basecidfont ] composefont def
+ /basefont-V /.basefont-V /Identity-V [ basecidfont ] composefont def
+
+ /CIDSystemInfo dup basecidfont exch get def
+ /FontBBox [ basecidfont /FontBBox get cvx exec
+ 4 2 roll basecidfont /FontMatrix get transform
+ 4 2 roll basecidfont /FontMatrix get transform
+ ] def
+
+ /tmpstr 2 string def
+ /BuildGlyph {
+ gsave
+ exch begin
+ dup 256 idiv tmpstr exch 0 exch put
+ 256 mod tmpstr exch 1 exch put
+ rootfont /WMode known { rootfont /WMode get 1 eq } { false } ifelse
+ { basefont-V } { basefont-H } ifelse setfont
+ strokewidth setlinewidth
+ 1 setlinejoin
+ newpath
+ 0 0 moveto tmpstr false charpath stroke
+ 0 0 moveto tmpstr show
+ currentpoint setcharwidth
+ end
+ grestore
+ } bind def
+
+ currentdict
+ end
+ dup /CIDFontName get exch /CIDFont defineresource
+} bind def
+
+% <CIDFont-resource> <CIDFontName> findCIDFont <CIDFont-resource> <font>
+% CIDFont-resource is not modified.
+/findCIDFont {
+ {
+ dup /CIDFont resourcestatus {
+ pop pop /CIDFont findresource
+ exit
+ } if
+ .remove_font_name_prefix
+ dup dup length string cvs
+ (,Bold) tailmatch {
+ exch pop
+ cvn findCIDFont 0.03 makeboldfont
+ exit
+ } if
+ (,Italic) tailmatch {
+ exch pop
+ cvn findCIDFont
+ [ 1 0 0.3 1 0 0 ] makefont
+ exit
+ } if
+ (,BoldItalic) tailmatch {
+ exch pop
+ cvn findCIDFont 0.03 makeboldfont
+ [ 1 0 0.3 1 0 0 ] makefont
+ exit
+ } if
+ pop
+
+ 1 index /CIDSystemInfo oget begin Registry (-) Ordering end
+ concatstrings concatstrings
+ cvn
+ QUIET not {
+ (Substituting CID font resource) print dup ==only
+ ( for ) print 1 index ==only (.\n) print
+ } if
+ exch pop
+ /CIDFont findresource
+ exit
+ } loop
+} bdef
+
+/buildCIDType0 { % <CIDFontType0-font-resource> buildCIDType0 <font>
+ dup /BaseFont get findCIDFont exch pop
+} bdef
+
+/buildCIDType2 { % <CIDFontType2-font-resource> buildCIDType2 <font>
+ dup /BaseFont get findCIDFont exch pop
+} bdef
+
+/processCIDToGIDMap { % <fontres> <cidfont> processCIDToGIDMap <fontres> <cidfont>
+ 1 index /CIDToGIDMap knownoget {
+ PDFfile fileposition 4 1 roll
+ dup /Identity eq {
+ pop
+ } {
+ true resolvestream
+ % Stack: filepos fontres font mapstream
+ % Can't know the length of the decompressed stream, so allocate a big buffer...
+ dup 65534 string readstring {
+ % Length exceeded max string size, use an array of two strings
+ 1 index 65534 string readstring pop % maybe a null string - not important.
+ 2 array astore
+ % Stack: filepos fontres font mapstream array
+ dup 1 get length 65534 add
+ } {
+ dup length
+ } ifelse
+ 2 idiv
+ % Stack: filepos fontres font mapstream array/string CIDCount
+ 3 index exch /CIDCount exch put
+ exch closefile exch
+ dup /CIDMap 4 -1 roll put
+ } ifelse
+ 3 2 roll PDFfile exch setfileposition
+ } if
+} bdef
+
+% Adjust a CIDFontType0 DW[2] in the font resource.
+/adjustCIDType0 { % <font-resource> <font> adjustfont <font'>
+ addCIDmetrics
+ dup /CIDFontName get exch /CIDFont defineresource
+} bind def
+
+% Adjust a CIDFontType2 DW[2] and CIDToGIDMap in the font resource.
+/adjustCIDType2 { % <font-resource> <font> adjustfont <font'>
+ addCIDmetrics
+ processCIDToGIDMap
+ dup /CIDFontName get exch /CIDFont defineresource
+} bind def
+
+% ---------------- Other embedded fonts ---------------- %
+
+/fontloadprocs mark
+ /Type1C /readType1C cvx
+ /CIDFontType0C /readCIDFontType0C cvx
+.dicttomark readonly def
+
+% Read an embedded compressed font.
+/readType1C { % <font-resource> <stream-dict> readType1C <font>
+ 1 index exch
+ PDFfile fileposition 3 1 roll
+ dup true resolvestream dup readfontfilter
+ % Stack: pos resource streamdict stream filter
+ 3 index /FontDescriptor oget /FontName oget
+ 1 index FRD
+ closefile closefile pop
+ PDFfile 3 -1 roll setfileposition
+ /FontDescriptor oget /FontName oget pdfaddcachedfont
+ exch pop
+} bdef
+
+% Read an embedded CFF CIDFont.
+/readCIDFontType0C { % <font-resource> <stream-dict> readCIDFontType0C <font>
+ PDFfile fileposition 3 1 roll
+ dup true resolvestream dup readfontfilter
+ % Stack: pos resource streamdict stream filter
+ 3 index /FontDescriptor oget /FontName oget
+ 1 index FRD
+ closefile closefile pop
+ PDFfile 3 -1 roll setfileposition
+ % Some broken Adobe software produces PDF files in which
+ % the FontName of the CFF font and the FontName in the
+ % FontDescriptor don't match the BaseFont in the font.
+ % Use the FontName, rather than the BaseFont, here.
+ dup /FontDescriptor oget /FontName oget /CIDFont findresource
+ addCIDmetrics dup /CIDFontName get exch /CIDFont defineresource
+} bdef
+
+% Read an embedded OpenType font.
+/readOTTOfont { % <font-resource> <stream-dict> readOTTOfont <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
+ .init_otto_font_file //true ReadData
+ closefile closefile pop
+ PDFfile 3 -1 roll setfileposition
+ /FontDescriptor oget /FontName oget pdfaddcachedfont
+ exch pop
+} 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
+
+% 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
+ dup /Subtype get % res res /subtype
+ fonttypeprocs exch dup / eq {
+ ( **** Warning: Font missing required Subtype, /Type1 assumed.\n)
+ pdfformaterror
+ pop /Type1
+ } if
+ get exec
+ } bdef
+
+ /bad_stream
+ { ( **** Warning: Error reading font stream, loading font by the name\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
+ { exch pop
+ dup /Subtype get
+ fontloadprocs exch get exec
+ } 4 bndef
+
+ <00010000> (true) (typ1) (ttcf) % TrueType OpenType
+ { exch pop readtruetype
+ } 4 bndef
+
+ (OTTO)
+ { exch pop
+ readOTTOfont
+ } bdef
+
+
+currentdict end readonly def
+currentdict /bndef undef
+
+/resourcefont % <font-resource> resourcefont <font>
+{ dup /PSFont .knownget {
+ /FID knownoget { type /fonttype eq } { //false } ifelse
+ } {
+ //false
+ } ifelse {
+ /PSFont get
+ } {
+ dup dup /FontDescriptor knownoget {
+ % font-res font-res font-desc
+
+ dup /FontObject .knownget dup { % font-res font-res font-desc font? bool bool
+ % Check that the cached FontObject has the right resource type
+ % The same font descriptor can be reused in a CID and non-CID contexts. bug 689301
+ 3 index /Subtype knownoget not { /Type1 } if
+ dup /CIDFontType0 eq exch /CIDFontType2 eq or % font-res font-res font-desc font bool is_cid
+ 2 index /CIDFontType known xor {
+ pop pop //false % font-res font-res font-desc false
+ } if
+ } if {
+ % res res desc obj
+ 3 1 roll pop pop % res obj
+ } {
+ dup /FontFile knownoget not {
+ dup /FontFile2 knownoget not {
+ dup /FontFile3 knownoget not {
+ //null
+ } if
+ } if
+ } if
+ % res res desc stream
+ dup //null ne {
+ PDFfile fileposition
+ 1 index //true resolvestream dup
+ 4 string readstring not { /bad_stream } if
+ exch closefile
+ PDFfile 3 -1 roll setfileposition
+ dup length 4 lt { pop /bad_stream } if
+ } {
+ /no_stream
+ } ifelse
+ % res res desc stream tag
+
+ //font_tag_dict 1 index known not {
+ dup 0 2 getinterval <8001> eq {
+ 0 2 getinterval % res res desc stream pfb_tag
+ } {
+ (12345678>\n) dup /ASCIIHexEncode filter dup 4 -1 roll writestring closefile
+ ( **** Warning: unrecognized font file starts with <) exch concatstrings
+ pdfformaterror
+ /no_stream % res res desc stream unknown_tag
+ } ifelse
+ } if
+
+ //font_tag_dict exch get exec
+
+ 1 index /FontDescriptor oget % res font desc
+ 1 index /FontObject exch put % Save pointer to the font
+ } ifelse
+ } {
+ dup /Subtype get fonttypeprocs exch dup / eq {
+ ( **** Warning: Font missing required Subtype, /Type1 assumed.\n)
+ pdfformaterror
+ pop /Type1
+ } if
+ get exec
+ } ifelse
+ % Stack: font-res font
+ 1 index 3 1 roll
+ 1 index /Subtype get
+ //adjustfonttypes exch .knownget { exec } { exch pop } ifelse
+ dup 3 1 roll /PSFont exch put
+ } ifelse
+ dup checkGlyphNames2Unicode
+} bdef
+
+currentdict /font_tag_dict undef
+
+drawopdict begin
+ /d0 {
+ .adjustcharwidth setcharwidth
+ } bdef
+ /d1 {
+ 4 index 0 ne {
+ % invalid wy parameter for d1 in Type3 font (must be 0)
+ % Even though the PDF 1.4 specification states that this must be 0,
+ % Distiller sometimes creates Type3 fonts with non-zero wy. We set
+ % it to 0 since this is apparently what Acrobat Reader 4 and 5 do,
+ % but if the specification is ever changed to allow non-zero wy, this
+ % will not work.
+ 5 -1 roll pop 0 5 1 roll % set wy to 0
+ } if
+
+ 2 copy % ... llx lly urx ury | urx ury
+ 0 ne exch 0 ne % ... llx lly urx ury | ury!=0 urx!=0
+ 3 index 6 index eq and % ... llx lly urx ury | ury!=0 (urx!=0 && llx==urx)
+ exch 2 index 5 index eq and or { % ... llx lly urx ury | (urx!=0 && llx==urx) || (ury!=0 && lly==ury)
+ % The bounding box is empty and likely incorrect. Don't cache.
+ pop pop pop pop .adjustcharwidth setcharwidth
+ } {
+ 6 -2 roll .adjustcharwidth 6 2 roll setcachedevice
+ } ifelse
+ } bdef
+ /Tf {
+ 1 index Page /Font rget {
+ resourcefont exch Tf pop
+ }
+ { % Bug 689037
+ ( **** Warning: Tf refers to an unknown resource name: ) pdfformaterror
+ 1 index .namestring pdfformaterror
+ ( Assuming it's a font name.\n) pdfformaterror
+ Tf
+ } ifelse
+ } bdef
+end
+
+end % pdfdict
+end % GS_PDF_ProcSet
+.setglobal