diff options
Diffstat (limited to 'Master/xemtex/gslib/pdf_font.ps')
-rw-r--r-- | Master/xemtex/gslib/pdf_font.ps | 1224 |
1 files changed, 1224 insertions, 0 deletions
diff --git a/Master/xemtex/gslib/pdf_font.ps b/Master/xemtex/gslib/pdf_font.ps new file mode 100644 index 00000000000..525ae34866e --- /dev/null +++ b/Master/xemtex/gslib/pdf_font.ps @@ -0,0 +1,1224 @@ +% Copyright (C) 1994-2002 artofcode LLC. All rights reserved. +% +% This program is free software; you can redistribute it and/or modify it +% under the terms of the GNU General Public License as published by the +% Free Software Foundation; either version 2 of the License, or (at your +% option) any later version. +% +% This program is distributed in the hope that it will be useful, but +% WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +% Public License for more details. +% +% You should have received a copy of the GNU General Public License along +% with this program; if not, write to the Free Software Foundation, Inc., +% 59 Temple Place, Suite 330, Boston, MA, 02111-1307. + +% $Id: pdf_font.ps,v 1.23.2.6.2.1 2003/04/12 14:02:39 giles Exp $ +% pdf_font.ps +% PDF font operations. + +/.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 ---------------- % + +% Apply a list of differences to an Encoding. +% Note that the differences may cause the array to grow. +/updateencoding { % <encoding> <differences> updateencoding <enc'> + % Calculate the length of the result. + exch 0 2 index { + dup type /nametype ne { exch pop } { pop 1 add } ifelse + } forall + 1 index length .max array dup 0 4 -1 roll putinterval + exch 0 exch { + % Stack: enc' code element + dup type /nametype ne + { exch pop } + { 3 copy put pop 1 add } + ifelse + } forall pop +} bdef + +% Get the Encoding for a font. +/getencoding % <base-encoding> <font-resource> getencoding <enc> + { /Encoding knownoget + { dup type /nametype eq + { + % The published PDF specification says the Encoding name + % "must be" one of the 3 predefined Encodings, implying + % that an error should occur if it isn't. However, Acrobat + % Reader simply ignores unknown names, and since there are + % some buggy applications that rely on this, we do the same. + + dup dup dup /MacRomanEncoding eq + exch /MacExpertEncoding eq or + exch /WinAnsiEncoding eq or + { exch pop findencoding + } + { pop + } + ifelse + } + { dup /BaseEncoding knownoget + { findencoding 3 -1 roll pop exch + } + if + /Differences knownoget { updateencoding } if + } + ifelse + } + if + } bdef + +% Rename a font with a generated name. +/renamefont { % <fontdict> renamefont <font'> + dup /FontName 2 copy get genfontname dup 5 1 roll put definefont +} bind def + +% Adjust a font according to the Encoding and Widths in the font resource. +/adjustfont { % <font-resource> <font> adjustfont <font'> + getfontencoding + getfontmetrics 4 -1 roll pop .updatefont { renamefont } if +} bind def + +% Get the (possibly modified) encoding of a font. +/getfontencoding { % <font-resource> <font> getfontencoding + % <font-resource> <font> <Encoding|null> + 1 index /Encoding known { + dup /Encoding .knownget { 2 index getencoding } { null } ifelse + } { + null + } ifelse +} bdef + +/find_in_diff % <Differences> <index> find_in_diff <bool> +{ false exch 0 4 3 roll + { dup type /nametype ne { exch pop } { pop 1 add } ifelse + 2 copy eq { + pop pop pop true 0 0 exit + } if + } forall + pop pop +} bdef + +% Get the metrics of a font, if specified. +/getfontmetrics { % <font-resource> <font> <Encoding|null> getfontmetrics + % <font-resource> <font> <Encoding|null> + % <Metrics|null> + 2 index /Widths known { + dup null eq { pop dup /Encoding get } if + 4 dict begin + /Encoding exch def + /Metrics Encoding length dict def + exch + dup /Widths oget /Widths exch def + % Stack: font font-res + % Note that widths are always based on a 1000-unit + % character space, but the FontMatrix may specify + % some other scale factor. Compensate for this here, + % by scaling the Widths if necessary. + 0.001 2 index /FontMatrix get 0 get div + % Stack: font font-res mscale + 1 index /FirstChar oget dup 1 4 index /LastChar oget + { % Stack: font font-res mscale first-char index + Encoding 1 index get + Widths 2 index 4 index sub oget + % 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 + % There is a hack here to deal with encodings where the + % same character appears more than once, because the Metrics + % dictionary works by character name, not by character code. + % We prefer to take (1) non-zero width, and (2) width for + % the character code which appears in Differences. + Metrics 2 index .knownget not { 0 } if 0 ne { + 5 index /Encoding knownoget not { exit } if + dup type /dicttype ne { pop exit } if + /Differences knownoget not { exit } if + 3 index //find_in_diff exec not { exit } if + } if + 2 copy Metrics 3 1 roll put + exit + } loop + pop pop pop + } + for pop + % Now fill in the MissingWidth for any encoded characters + % that aren't in Metrics already. Note that built-in + % fonts may have Widths/FirstChar/LastChar but no + % FontDescriptor, so we must check for this. + % Stack: font font-res mscale + 1 index /FontDescriptor knownoget { + Metrics exch + /MissingWidth knownoget { 2 index mul } { 0 } ifelse exch + Encoding { + % Stack: font font-res mscale missing-width metrics charname + % Work around the abovementioned pdfTeX bug. + dup null ne { + 2 copy known not { 2 copy 4 index put } if pop + } { + pop + } ifelse + } forall pop pop pop + } { + pop + } ifelse + exch Encoding Metrics end + } { + null + } ifelse +} bdef + +currentdict /find_in_diff undef + +% ---------------- 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 ---------------- % + +/.glyphpath { % <glyphname> <boolean> .glyphpath - + % another glyphpath written in addxchar.ps does not work here... + currentfont 3 1 roll exch + currentfont dup length dict begin + { 1 index /Encoding eq { pop [ 3 -1 roll ] def } { def } ifelse } forall + currentdict end /.glyphpathfont exch definefont + setfont <00> exch charpath setfont +} bdef + +/makeboldfont { % <basefont> <strokewidth> makeboldfont <boldfont> + 10 dict begin + /strokewidth exch def + /basefont exch def + /FontMatrix matrix def + %/FontName basefont /FontName get def + /FontName /.boldfont def + /FontType 3 def + /Encoding basefont /Encoding get def + /FontBBox [ basefont /FontBBox get cvx exec + 4 2 roll basefont /FontMatrix get transform + 4 2 roll basefont /FontMatrix get transform + ] def + /BuildGlyph { + gsave + exch begin + basefont setfont + strokewidth setlinewidth + 1 setlinejoin + newpath + 0 0 moveto dup false .glyphpath stroke + 0 0 moveto glyphshow + currentpoint setcharwidth + end + grestore + } bind def + currentdict + end + dup /FontName get exch definefont +} bind def + +% Fabricate a font name by adding ?'s on the end. +/genfontname % <name> genfontname <name> + { dup length string cvs + { (?) concatstrings + dup cvn FontDirectory exch known not { cvn exit } if + } + loop + } bdef + +% Find a font, 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 findfont + } { + 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 + 1 index /FontName oget exch + % Analyzes font name and extract "Narrow" property + % which is not described by the FontDescriptor Flags. + 0 2 index .fontnameproperties 4 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 + QUIET not { + (Substituting font ) print dup =only + ( for ) print 2 index =only (.) = flush + } if + 3 -1 roll pop findfont + % Stack: font-res 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 + 4 index /FirstChar get 97 .max + 5 index /LastChar get 122 .min 1 exch { + % Stack: font-res font' font' /CharStrings charstrings code + % Note that this only remaps a-z, not accented characters. + 5 index /Widths oget 1 index 7 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 + renamefont + } if + } { + % No descriptor available, use the default algorithm. + findfont + } ifelse + } ifelse adjustfont +} bdef +/findpdffont { % <font-resource> <fontname> findpdffont <font> + {} 3 1 roll % proc fnres fnname + [ + [ (,Bold) { .03 makeboldfont } ] + [ (,BoldItalic) { .03 makeboldfont [ 1 0 .3 1 0 0 ] makefont } bind ] + [ (,Italic) { [ 1 0 .3 1 0 0 ] makefont } bind ] + ] { + 1 index dup length string cvs + 1 index 0 get tailmatch { % proc fnres fnname [] + 3 -1 roll pop exch 1 get % proc fnres pre-fnname proc + 4 -1 roll pop 3 1 roll % proc fnres pre-fnname + exit + } { pop pop } ifelse % proc fnres fnname + } forall + pdffindfont exch exec +} bdef + +% ---------------- Type 1 fonts ---------------- % + +/buildType1 % <Type1-font-resource> buildType1 <font> + { dup /BaseFont get pdffindfont + } bdef + +% The state dictionary for the embedded Type 1 font reading procedure +% has the following keys and values: +% data - stream (filter) +% buffer, buffer2 - string +% hexify - procedure to convert buffer to hex if needed +% leftstr - string containing (non-negative) integer +% sectionstr - string containing a character 0 .. 3 +% stream - (stream) dictionary +% proc - procedure of the form {-dict- type1read} +% pfbhdr - string containing 16#80 if PFB, 0 otherwise +% When the procedure is executing, this dictionary is current. +% leftstr and sectionstr are strings so that we can change their values +% reliably in case the font executes a restore! +% We also have to do something special about embedded fonts that +% execute definefont more than once -- that is the function of topFontDict. + +% Read an embedded Type 1 font. +/readfontfilter { % <proc> readfontfilter <filter> + 0 () /SubFileDecode filter +} bdef +/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 + /eexec { + % Assume the font dictionary is directly below the file on the stack + count 0 gt { /topFontDict 2 index cvlit store } if + 55665 /eexecDecode filter + //systemdict begin readtype1dictcopy begin cvx stopped + currentdict readtype1dictcopy eq { end } if + currentdict //systemdict eq { end } if + { stop } if + } bdef +end readonly def +/readtype1 { % <font-resource> <stream-dict> readtype1 <font> + % Read the definition, using a procedure-based filter + % that turns binary/hex conversion on and off + % at the right times. + 1 index exch + PDFfile fileposition 3 1 roll + 11 dict begin + /leftstr ( ) 10 string copy def + dup /Length1 oget leftstr cvs pop + /sectionstr <00> 1 string copy def + /pfbhdr <00> 1 string copy def + /stream 1 index def + true resolvestream /data exch def + /buffer 1000 string def % arbitrary + /buffer2 buffer length 2.1 div cvi 1 sub string def + /hexify /buf2hex load def + currentdict end + /type1read cvx 2 array astore cvx dup 0 get /proc 2 index put + readfontfilter + % 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. + //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 + { run } aload pop count 1 sub 2 packedarray cvx exec + end end + count exch sub { pop } repeat + PDFfile 3 -1 roll setfileposition + /BaseFont oget findfont + adjustfont + } bdef + +% Execute the appropriate reading procedure. +/type1read % <dict> type1read <string> + { begin leftstr cvi + { type1read0 type1read1 type1read2 type1read3 } sectionstr 0 get get exec + ( ) leftstr copy cvs pop end + } bdef + +% Read the next block of data into the buffer. +/type1readdata % <left> <buffer> type1readdata <substring> <left'> + { 0 2 index 2 index length .min getinterval + % Adobe requires readstring to signal an error if given + % an empty string. Work around this nonsense here. + dup length 0 ne { data exch readstring pop } if + dup length 3 -1 roll exch sub + DEBUG + { dup =only ( read ) print + 1 index length =only (: ) print + 1 index == flush + } if + } bdef + +% Read the initial byte to see if we need to skip a 6 byte PFB header +/type1read0 { % <left> type1read0 <string> <left'> + sectionstr 0 1 put % either way we go to the next stage + pfbhdr type1readdata + 1 index 0 get 16#80 eq { + (\n **** Warning: Embedded Type1 font in PFB format is not valid PDF.) + pdfformaterror + DEBUG { (skipping PFB header) = flush } if + exch pop buffer 0 5 getinterval type1readdata exch + dup 4 get 256 mul 1 index 3 get add 256 mul + 1 index 2 get add 256 mul 1 index 1 get add + DEBUG { (PFB segment length = ) print dup = } if + exch pop % discard the string keeping the PFB segment length + 2 copy ne { + (\n **** Warning: Type 1 PFB segment length and Length 1 value do not match.) + pdfformaterror + exch % keep the PFB length instead + } if + pop + buffer type1readdata % go ahead and read a block + } + if % if not PFB, return pfbhdr string (first char of file, usually %). +} bdef + +% Read the next block of the initial text portion. +/type1read1 { % <left> type1read1 <string> <left'> + DEBUG { (read1 ) print } if + dup 0 eq { + pop sectionstr 0 2 put + stream /Length2 oget + % Determine whether to hexify data for eexec. + dup 8 lt { + type1read2 % Hexify. + } { + DEBUG { (read2 ) print } if + pfbhdr 0 get 16#80 eq { + % eat 6 more bytes of PFB junk before proceeding + DEBUG { (skipping PFB header in segment 2) = flush } if + buffer 0 6 getinterval type1readdata exch + dup 5 get 256 mul 1 index 4 get add 256 mul + 1 index 3 get add 256 mul 1 index 2 get add + DEBUG { (PFB segment length = ) print dup = } if + exch pop % discard the string keeping the PFB segment length + 2 copy ne { + (\n **** Warning: Type 1 PFB segment length and Length 2 value do not match.) + pdfformaterror + dup = + exch % keep the PFB length instead + } if + pop + } if + buffer2 type1readdata exch + % The check doesn't have to be 100% accurate: + % hexifying is always OK. + dup 0 8 getinterval 0 exch { or } forall + 128 ge { + /hexify { } store + /buffer2 buffer def % We don't need an intermediate buffer. + } if hexify exch + } ifelse + } { + buffer type1readdata + } ifelse +} bdef + +% Convert a string from binary to hex for eexec. +% Free variables: buffer. +/buf2hex { % <string> buf2hex <hexstring> + buffer /ASCIIHexEncode filter dup 3 -1 roll writestring closefile + buffer (>) search pop exch pop exch pop +} bdef + +% Read the next block of the encrypted portion. +/type1trailer +(0000000000000000000000000000000000000000000000000000000000000000\n\ +0000000000000000000000000000000000000000000000000000000000000000\n\ +0000000000000000000000000000000000000000000000000000000000000000\n\ +0000000000000000000000000000000000000000000000000000000000000000\n\ +0000000000000000000000000000000000000000000000000000000000000000\n\ +0000000000000000000000000000000000000000000000000000000000000000\n\ +0000000000000000000000000000000000000000000000000000000000000000\n\ +0000000000000000000000000000000000000000000000000000000000000000\n\ +cleartomark\n) +readonly def +/type1read2 { % <left> type1read2 <string> <left'> + DEBUG { (read2 ) print } if + dup 0 eq + { pop sectionstr 0 3 put + stream /Length3 oget + dup 0 eq + { DEBUG { (trailer ) print } if + type1trailer exch + } + { + pfbhdr 0 get 16#80 eq { + % eat 6 more bytes of PFB junk before proceeding + DEBUG { (skipping PFB header in segment 3) = flush } if + buffer 0 6 getinterval type1readdata exch + dup 5 get 256 mul 1 index 4 get add 256 mul + 1 index 3 get add 256 mul 1 index 2 get add + DEBUG { (PFB segment length = ) print dup = } if + exch pop % discard the string keeping the PFB segment length + 2 copy ne { + (\n **** Warning: Type 1 PFB segment length and Length 3 value do not match.) + pdfformaterror + exch % keep the PFB length instead + } if + pop + (\n) pdfformaterror + } if + type1read3 + } + ifelse + } + { buffer2 type1readdata exch hexify exch + } + ifelse +} bdef + +% Read the next block of the final text portion. +% When finished, this procedure returns an empty string. +/type1read3 % <left> type1read3 <string> <left'> + { DEBUG { (read3 ) print } if + buffer type1readdata + } bdef + +% ---------------- Type 3 fonts ---------------- % + +/.notdefEncoding 256 { /.notdef } repeat 256 packedarray def + +/buildType3 { % <Type3-font-resource> buildType3 <font> + 8 dict begin + /FontType 3 def + /Resources 1 index /Resources knownoget { oforce } { 0 dict } 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 get genfontname 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 + 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 + % + /ArialBlack,Italic /Arial-BlackItalic + /ArialNarrow,Bold /ArialNarrow-Bold + /ArialNarrow,BoldItalic /ArialNarrow-BoldItalic + /ArialNarrow,Italic /ArialNarrow-Italic + /BookAntiqua,Bold /BookAntiqua-Bold + /BookAntiqua,BoldItalic /BookAntiqua-BoldItalic + /BookAntiqua,Italic /BookAntiqua-Italic + /BookmanOldStyle,Bold /BookmanOldStyle-Bold + /BookmanOldStyle,BoldItalic /BookmanOldStyle-BoldItalic + /BookmanOldStyle,Italic /BookmanOldStyle-Italic + /CenturyGothic,Bold /CenturyGothic-Bold + /CenturyGothic,BoldItalic /CenturyGothic-BoldItalic + /CenturyGothic,Italic /CenturyGothic-Italic + /ComicSansMS,Bold /ComicSansMS-Bold + /CourierNew,Bold /CourierNewPS-BoldMT + /CourierNew,BoldItalic /CourierNewPS-BoldItalicMT + /CourierNew,Italic /CourierNewPS-ItalicMT + /FranklinGothicMedium,Italic /FranklinGothic-MediumItalic + /Garamond,Bold /Garamond-Bold + /Garamond,Italic /Garamond-Italic + /Georgia,Bold /Georgia-Bold + /Georgia,BoldItalic /Georgia-BoldItalic + /Georgia,Italic /Georgia-Italic + /Tahoma,Bold /Tahoma-Bold + /TrebuchetMS,Bold /TrebuchetMS-Bold + /TrebuchetMS,BoldItalic /Trebuchet-BoldItalic + /TrebuchetMS,Italic /TrebuchetMS-Italic + /Verdana,Bold /Verdana-Bold + /Verdana,BoldItalic /Verdana-BoldItalic + /Verdana,Italic /Verdana-Italic +.dicttomark readonly def + +/buildTrueType { % <TrueType-font-resource> buildTrueType <font> + dup /BaseFont get + dup TTfonts exch .knownget { + exch pop + % Hack required by the PDF specification: if the + % font resource has Subtype = /TrueType but the actual + % (installed) font is not a TrueType font, ignore the + % Encoding in the font resource. However, all current + % versions of Acrobat Reader have the 14 base TrueType + % fonts built in, so this produces incorrect output for + % badly designed PDF files that specify these file names + % with /Subtype = /TrueType but no embedded definition. + % Compensate for this by removing the /Subtype key when + % looking up the font. + exch dup length dict copy dup /Subtype null put exch + } if + pdffindfont % findfont for PDF + % disable the auto-bold and auto-italic since it sometimes applies + % so an already bold or italic substitute font + %findpdffont % findfont and auto-bold and/or auto-italic font for PDF +} bdef + +% Read an embedded TrueType font. +/readtruetype { % <font-resource> <stream-dict> readtruetype <font> + % This is much simpler than readtype1, because we don't + % have to deal with the tripartite .PFB format. + 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 + 1 index /CIDToGIDMap knownoget { + dup /Identity eq { + pop + } { + true resolvestream + % The following doesn't work for CIDToGIDMaps with more + % than 32K-1 entries. We'll fix it later if necessary. + % Stack: filepos fontres font mapstream + dup 2 index /CIDCount oget 2 mul string readstring pop exch closefile + exch dup length 5 add dict .copydict + dup /FID undef + dup /CIDMap 4 -1 roll put + dup /CIDFontName get exch /CIDFont defineresource + } ifelse + } if + } { + null 2 index getencoding .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 + composefont + % 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" third edition, p. 337, +% "5.6.3 CIDFonts" and table "Entries in a CIDFont dictionary". + +/.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 .knownget { + 1 index /DW 3 -1 roll put + } { + dup /DW .pdfDefaultDW put + } ifelse + + + 1 index /W .knownget { + dup 2 index /W 3 -1 roll put + .pdfMakeInternalW 1 index /.internalW 3 -1 roll put + } if + + + 1 index /DW2 .knownget { + 1 index /DW2 3 -1 roll put + } { + dup /DW2 .pdfDefaultDW2 put + } ifelse + + + 1 index /W2 .knownget { + 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 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 + + 1000 div % <w0x'> (normalized W) + 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 + {1000 div} forall exch + 4 index 7 index add 2 div % <vx'> = (<urx> + <llx>) / 2 + exch + }{ % assume W2 + {1000 div} 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 + +/makeboldcidfont { + 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 + + dup dup length string cvs + (,Bold) tailmatch { + exch pop + cvn findCIDFont 0.03 makeboldcidfont + 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 makeboldcidfont + [ 1 0 0.3 1 0 0 ] makefont + exit + } if + pop + + 1 index /CIDSystemInfo get begin Registry (-) Ordering end + concatstrings concatstrings + cvn + QUIET not { + (Substituting ) 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 exch 1 index findCIDFont + addCIDmetrics /CIDFont defineresource +} bdef + +/buildCIDType2 { % <CIDFontType2-font-resource> buildCIDType2 <font> + dup /BaseFont get exch 1 index findCIDFont + addCIDmetrics /CIDFont defineresource +} bdef + +% ---------------- 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 findfont + adjustfont +} 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 + +% ---------------- Font lookup ---------------- % + +/fonttypeprocs mark % <font-resource> -proc- <font> + /Type0 /buildType0 cvx + /Type1 /buildType1 cvx + /MMType1 1 index + /Type3 /buildType3 cvx + /TrueType /buildTrueType cvx + /CIDFontType0 /buildCIDType0 cvx + /CIDFontType2 /buildCIDType2 cvx +.dicttomark readonly def + +/resourcefont % <font-resource> resourcefont <font> + { dup /PSFont .knownget + { /FID .knownget { type /fonttype eq } { false } ifelse } + { false } + ifelse + { /PSFont get + } + { dup dup /FontDescriptor knownoget + { % Stack: font-res font-res font-desc + dup /FontFile knownoget + { exch pop readtype1 true } + { dup /FontFile2 knownoget + { exch pop readtruetype true } + { /FontFile3 knownoget + { dup /Subtype get fontloadprocs exch get exec true } + { false } + ifelse + } + ifelse + } + ifelse + } + { false } + ifelse + % Stack: font-res font-res false + % -or-: font-res font true + not + { dup /Subtype get fonttypeprocs exch get exec } + if + 2 copy /PSFont exch put + exch pop + } + ifelse + } bdef + +drawopdict begin + /d0 { + .adjustcharwidth setcharwidth + } bdef + /d1 { + 6 -2 roll .adjustcharwidth 6 2 roll setcachedevice + } bdef + /Tf { + 1 index Page /Font rget not { 1 index /invalidfont signalerror } if + resourcefont exch Tf pop + } bdef +end + +end % pdfdict +end % GS_PDF_ProcSet +.setglobal |