1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456 |
- % Copyright (C) 1996-2003 artofcode LLC. 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: gs_ttf.ps,v 1.48 2005/09/22 16:11:37 ray Exp $
- % Support code for direct use of TrueType fonts.
- % (Not needed for Type 42 fonts.)
- % Note that if you want to use this file without including the ttfont.dev
- % option when you built Ghostscript, you will need to load the following
- % files before this one:
- % lib/gs_mgl_e.ps
- % lib/gs_mro_e.ps
- % lib/gs_wan_e.ps
- % Thanks to B. Jackowski and GUST (the Polish TeX Users' Group) for
- % the glyf-splitting code.
- % ---------------- Font loading machinery ---------------- %
- % Augment the FONTPATH machinery so it recognizes TrueType fonts.
- /.scanfontheaders where {
- pop /.scanfontheaders [
- .scanfontheaders aload pop (\000\001\000\000*) (true*)
- ] def
- } if
- % <file> <key> .findfontvalue <value> true
- % <file> <key> .findfontvalue false
- % Closes the file in either case.
- /.findnonttfontvalue /.findfontvalue load def
- /.findfontvalue {
- 1 index read {
- 2 index 1 index unread
- % beginning with binary 0 or 't' (TrueType), or 'O' (OpenType)
- dup 0 eq 1 index (O) 0 get eq or exch (t) 0 get eq or {
- % If this is a font at all, it's a TrueType font.
- dup /FontType eq {
- pop closefile 42 true
- } {
- dup /FontName eq { pop .findttfontname } { pop closefile false } ifelse
- } ifelse
- } {
- % Not a TrueType font.
- .findnonttfontvalue
- } ifelse
- } { pop closefile false } ifelse
- } bind def
- % <file> .findttfontname <fname> true
- % <file> .findttfontname false
- % Closes the file in either case.
- /.findttfontname {
- //true 0 .loadttfonttables
- tabdict /name .knownget {
- dup 8 getu32 f exch setfileposition
- 12 getu32 string f exch readstring pop
- 6 findname
- } {
- false
- } ifelse
- f closefile end end
- } bind def
- % Load a font file that might be a TrueType font.
- % <file> .loadfontfile -
- /.loadnonttfontfile /.loadfontfile load def
- /.loadfontfile {
- dup read pop 2 copy unread 0 eq {
- % If this is a font at all, it's a TrueType font.
- .loadttfont pop
- } {
- % Not a TrueType font.
- .loadnonttfontfile
- } ifelse
- } bind def
- % ---------------- Automatic Type 42 generation ---------------- %
- % Load a TrueType font from a file as a Type 42 PostScript font.
- % The thing that makes this really messy is the handling of encodings.
- % There are 2 interacting tables that affect the encoding:
- % 'cmap' provides multiple maps from character codes to glyph indices
- % 'post' maps glyph indices to glyph names (if present)
- % What we need to get out of this is:
- % Encoding mapping character codes to glyph names
- % (the composition of cmap and post)
- % CharStrings mapping glyph names to glyph indices
- % (the inverse of post)
- % If the post table is missing, we have to take a guess based on the cmap
- % table.
- /.loadttfontdict 50 dict dup begin
- /orgXUID AladdinEnterprisesXUID def
- /maxstring 32764 def % half the maximum length of a PostScript string,
- % must be a multiple of 4 (for hmtx / loca / vmtx)
- /.invert_encoding % <array> invert_encoding <dict>
- { dup 256 dict exch
- 0 exch 1 exch length 1 sub { % [] <> i
- dup 3 index exch get % [] <> i v
- dup /.notdef ne {
- exch 2 index 2 index .knownget {
- dup type /arraytype eq {
- [ exch aload pop counttomark 2 add -1 roll ]
- } {
- exch 2 array astore
- } ifelse
- } if 2 index 3 1 roll put
- } {
- pop pop
- } ifelse
- } for
- exch pop
- } bind def
- % Define the Macintosh standard mapping from characters to glyph indices.
- /MacRomanEncoding dup .findencoding def
- /MacGlyphEncoding dup .findencoding def
- % Invert the MacRomanEncoding.
- /.romanmacdict MacRomanEncoding .invert_encoding def
- % Define remapping for misnamed glyphs in TrueType 'post' tables.
- % There are probably a lot more than this!
- /postremap mark
- /Cdot /Cdotaccent
- /Edot /Edotaccent
- /Eoverdot /Edotaccent
- /Gdot /Gdotaccent
- /Ldot /Ldotaccent
- /Zdot /Zdotaccent
- /cdot /cdotaccent
- /edot /edotaccent
- /eoverdot /edotaccent
- /gdot /gdotaccent
- /ldot /ldotaccent
- /zdot /zdotaccent
- .dicttomark readonly def
- % Array used for fast pre-filling of cmap array
- /.array1024z [ 1024 { 0 } repeat ] def
- % ---- Utilities ---- %
- % Define a serial number for creating unique XUIDs for TrueType fonts.
- % We used to use the checkSumAdjustment value from the font, but this is
- % not reliable, since some fonts don't set it correctly.
- % Note that we must do this in a string to make it immune to save/restore.
- /xuidstring <80000000> def
- /curxuid { % - curxuid <int>
- 0 xuidstring { exch 8 bitshift exch add } forall
- } bind def
- /nextxuid { % - nextxuid -
- 3 -1 0 {
- xuidstring 1 index 2 copy get dup 255 ne {
- 1 add put pop exit
- } if pop 0 put pop
- } for
- } bind def
- % <string> <index> getu16 <integer>
- /getu16 {
- 2 copy get 8 bitshift 3 1 roll 1 add get add
- } bind def
- % <string> <index> gets16 <integer>
- /gets16 {
- getu16 16#8000 xor 16#8000 sub
- } bind def
- % <string> <index> getu32 <integer>
- /getu32 {
- 2 copy getu16 16 bitshift 3 1 roll 2 add getu16 add
- } bind def
- % <string> <index> gets32 <integer>
- /gets32 {
- 2 copy gets16 16 bitshift 3 1 roll 2 add getu16 add
- } bind def
- 16#ffffffff 0 gt { % 64-bit sign extension
- { /curxuid /gets32 } {
- mark 1 index load aload pop { 16#80000000 xor 16#80000000 sub } aload pop
- .packtomark cvx def
- } bind forall
- } if
- % <string> <index> <integer> putu16 -
- /putu16 {
- 3 copy -8 bitshift put
- exch 1 add exch 16#ff and put
- } bind def
- % <string> <index> <integer> putu32 -
- /putu32 {
- 3 copy -16 bitshift putu16
- exch 2 add exch 16#ffff and putu16
- } bind def
- % <nametable> <nameid> findname <string> true
- % <nametable> <nameid> findname false
- /findname {
- TTFDEBUG { (findname: ) print dup =only } if
- false 3 1 roll
- 1 index length 0 gt { % check for zero length name table
- 0 1 3 index 2 getu16 1 sub {
- % Stack: false table id index
- 12 mul 6 add 2 index exch 12 getinterval
- dup 6 getu16 2 index eq {
- % We found the name we want.
- exch pop
- % Stack: false table record
- dup 10 getu16 2 index 4 getu16 add
- 1 index 8 getu16 4 -1 roll 3 1 roll
- 3 copy add 1 index length
- le {
- pop
- getinterval exch
- % Stack: false string record
- % Check for 8- vs. 16-bit characters.
- is2byte { string2to1 } if true null 4 -1 roll exit
- } {
- pop pop pop pop
- false
- exit
- } ifelse
- } if pop
- } for
- } if
- pop pop
- TTFDEBUG {
- dup { ( = ) print 1 index == } { ( not found) = } ifelse
- } if
- } bind def
- % <namerecord> is2byte <bool>
- /is2byte {
- dup 0 getu16 {
- { pop true } % Apple Unicode
- { pop false } % Macintosh Script manager
- { 1 getu16 1 eq } % ISO
- { 1 getu16 1 eq } % Microsoft
- } exch get exec
- } bind def
- % <string2> string2to1 <string>
- /string2to1 {
- dup length 2 idiv string dup
- 0 1 3 index length 1 sub {
- 3 index 1 index 2 mul 1 add get put dup
- } for pop exch pop
- } bind def
- % Each procedure in this dictionary is called as follows:
- % <encodingtable> proc <glypharray>
- /cmapformats mark
- 0 { % Apple standard 1-to-1 mapping.
- 6 256 getinterval { } forall 256 packedarray
- } bind
- 2 { % Apple 16bit CJK (ShiftJIS etc)
- % /sHK_sz subHeaderKey_size % 1 * uint16
- % /sH_sz subHeader_size % 4 * uint16
- % /sH_len subHeader_length
- % /cmapf2_tblen total table length
- % /cmapf2_lang language code (not used)
- % /sHKs subHeaderKeys
- /sHK_sz 2 def
- /sH_sz 8 def
- dup 2 getu16 /cmapf2_tblen exch def
- dup 4 getu16 /cmapf2_lang exch def
- dup 6 256 sHK_sz mul getinterval /sHKs exch def
- 0 % initialization value for /sH_len
- 0 1 255 {
- sHKs exch
- 2 mul getu16
- 1 index % get current max
- 1 index % get current subHeaderKey
- lt {exch} if pop
- } for
- /sH_len exch def
- dup 6 256 sHK_sz mul add
- cmapf2_tblen 1 index sub getinterval
- /sH_gIA exch def
- /cmapf2_glyph_array 65535 array def
- /.cmapf2_putGID {
- /cmapf2_ch cmapf2_ch_hi 8 bitshift cmapf2_ch_lo add def
- firstCode cmapf2_ch_lo le
- cmapf2_ch_lo firstCode entryCount add lt
- and { % true: j is inside
- sH_offset idRangeOffset add % offset to gI
- cmapf2_ch_lo firstCode sub 2 mul % rel. pos. in range
- add 6 add % offset in sH_gIA
- sH_gIA exch getu16
- dup 0 gt { %
- idDelta add
- cmapf2_glyph_array exch cmapf2_ch exch put
- } {
- pop
- % cmapf2_glyph_array cmapf2_ch 0 put
- } ifelse
- } { % false: j is outside
- % cmapf2_glyph_array cmapf2_ch 0 put
- } ifelse
- } def
- 16#00 1 16#ff { % hi_byte scan
- /cmapf2_ch_hi exch def
- sHKs cmapf2_ch_hi sHK_sz mul getu16
- /sH_offset exch def
- sH_gIA sH_offset sH_sz getinterval
- dup 0 getu16 /firstCode exch def
- dup 2 getu16 /entryCount exch def
- dup 4 gets16 /idDelta exch def
- dup 6 getu16 /idRangeOffset exch def
- pop
- sH_offset 0 eq {
- /cmapf2_ch_lo cmapf2_ch_hi def
- /cmapf2_ch_hi 0 def
- .cmapf2_putGID
- } {
- 16#00 1 16#ff { % lo_byte scan
- /cmapf2_ch_lo exch def
- .cmapf2_putGID
- } for
- } ifelse
- } for
- pop
- 0 1 cmapf2_glyph_array length 1 sub { % rewrite null -> 0.
- dup cmapf2_glyph_array exch get
- null eq { cmapf2_glyph_array exch 0 put } {pop} ifelse
- } for
- cmapf2_glyph_array
- } bind
- 4 { % Microsoft/Adobe segmented mapping.
- /etab exch def
- /nseg2 etab 6 getu16 def
- 14 /endc etab 2 index nseg2 getinterval def
- % The Apple TrueType documentation omits the 2-byte
- % 'reserved pad' that follows the endCount vector!
- 2 add
- nseg2 add /startc etab 2 index nseg2 getinterval def
- nseg2 add /iddelta etab 2 index nseg2 getinterval def
- nseg2 add /idroff etab 2 index nseg2 getinterval def
- % The following hack allows us to properly handle
- % idiosyncratic fonts that start at 0xf000:
- pop
- /firstcode startc 0 getu16 16#ff00 and dup 16#f000 ne { pop 0 } if def
- /putglyph {
- glyphs code 3 -1 roll put /code code 1 add def
- } bind def
- % Do a first pass to compute the size of the glyphs array.
- /numcodes 0 def /glyphs 0 0 2 nseg2 3 sub {
- % Stack: /glyphs numglyphs i2
- /i2 exch def
- /scode startc i2 getu16 def
- /ecode endc i2 getu16 def
- numcodes scode firstcode sub
- % Hack for fonts that have only 0x0000 and 0xf000 ranges
- %dup 16#e000 ge { 255 and } if
- % the previous line is obstructive to CJK fonts, so it was removed
- exch sub 0 .max ecode scode sub 1 add add
- exch 1 index add exch
- numcodes add /numcodes exch def
- } for array def
- % prefill the array with 0's faster than a { 0 putglyph } repeat
- glyphs length 1024 ge {
- .array1024z 0 1024 glyphs length 1023 sub { glyphs exch 2 index putinterval } for
- glyphs dup length 1024 sub 3 -1 roll
- putinterval
- } {
- 0 1 glyphs length 1 sub { glyphs exch 0 put } for
- } ifelse
- % Now fill in the array.
- /numcodes 0 def /code 0 def
- 0 2 nseg2 3 sub {
- /i2 exch def
- /scode startc i2 getu16 def
- /ecode endc i2 getu16 def
- numcodes scode firstcode sub
- % Hack for fonts that have only 0x0000 and 0xf000 ranges
- %dup 16#e000 ge { 255 and } if
- % the previous line is obstructive to CJK fonts, so it was removed
- exch sub 0 .max dup /code exch code exch add def
- ecode scode sub 1 add add numcodes add /numcodes exch def
- /delta iddelta i2 gets16 def
- TTFDEBUG {
- (scode=) print scode =only
- ( ecode=) print ecode =only
- ( delta=) print delta =only
- ( droff=) print idroff i2 getu16 =
- } if
- idroff i2 getu16 dup 0 eq {
- pop scode delta add 65535 and 1 ecode delta add 65535 and
- { putglyph } for
- } { % The +2 is for the 'reserved pad'.
- /gloff exch 14 nseg2 3 mul add 2 add i2 add add def
- 0 1 ecode scode sub {
- 2 mul gloff add etab exch getu16
- dup 0 ne { delta add 65535 and } if putglyph
- } for
- } ifelse
- } for glyphs /glyphs null def % for GC
- } bind
- 6 { % Single interval lookup.
- dup 6 getu16 /firstcode exch def dup 8 getu16 /ng exch def
- firstcode ng add array
- % Stack: tab array
- % Fill elements 0 .. firstcode-1 with 0
- 0 1 firstcode 1 sub { 2 copy 0 put pop } for
- dup firstcode ng getinterval
- % Stack: tab array subarray
- % Fill elements firstcode .. firstcode+nvalue-1 with glyph values
- 0 1 ng 1 sub {
- dup 2 mul 10 add 4 index exch getu16 3 copy put pop pop
- } for pop exch pop
- } bind
- .dicttomark readonly def % cmapformats
- % <cmaptab> cmaparray <glypharray>
- /cmaparray {
- dup 0 getu16 cmapformats exch .knownget {
- TTFDEBUG {
- (cmap: format ) print 1 index 0 getu16 = flush
- } if exec
- } {
- (Can't handle format ) print 0 getu16 = flush
- 0 1 255 { } for 256 packedarray
- } ifelse
- TTFDEBUG {
- (cmap: length=) print dup length = dup ==
- } if
- } bind def
- /get_from_stringarray % <array|string> <offset> get_from_stringarray <int>
- { 1 index type /stringtype eq {
- get
- } {
- exch { % o ()
- 2 copy length gt {
- length sub
- } {
- exch get exit
- } ifelse
- } forall
- } ifelse
- } bind def
- /getinterval_from_stringarray % <array|string> <offset> <length> getinterval_from_stringarray <string>
- { % May allocate a string in VM.
- 2 index type /stringtype eq {
- getinterval
- } {
- string exch 0 % [] s o p
- 4 3 roll { % s o p Si
- dup length % s o p Si lSi
- dup 4 index lt {
- 3 index exch sub % s o p Si o'
- exch pop 3 1 roll exch pop % s o' p
- } { % s o p Si lSi
- dup 3 1 roll % s o p lSi Si lSi
- 4 index sub % s o p lSi Si lSi-o
- 5 index length 4 index sub % s o p lSi Si lSi-o ls-p
- 2 copy gt { exch } if pop % s o p lSi Si minl
- dup 3 1 roll % s o p lSi minl Si minl
- 5 index exch getinterval % s o p lSi minl from
- 5 index 4 index 3 index % s o p lSi minl from s p minl
- getinterval % s o p lSi minl from to
- copy pop % s o p lSi minl
- 3 1 roll % s o minl p lSi
- sub % s o minl p'
- 3 1 roll add % s p' o'
- dup 3 index length ge {
- exch exit % s o p'
- } if
- exch % s o' p'
- } ifelse
- } forall
- pop pop % s
- } ifelse
- } bind def
- /string_array_size % <array|string> string_array_size <int>
- { dup type /stringtype eq {
- length
- } {
- 0 exch { length add } forall
- } ifelse
- } bind def
- % Each procedure in this dictionary is called as follows:
- % posttable <<proc>> glyphencoding
- /postformats mark
- 16#00010000 { % 258 standard Macintosh glyphs.
- pop MacGlyphEncoding
- }
- 16#00020000 { % Detailed map, required by Microsoft fonts.
- dup dup type /arraytype eq { 0 get } if length 36 lt {
- TTFDEBUG { (post format 2.0 invalid.) = flush } if
- pop [ ]
- } {
- /postglyphs exch def
- /post_first postglyphs dup type /arraytype eq { 0 get } if def
- post_first 32 getu16 /numglyphs exch def
- /glyphnames numglyphs 2 mul 34 add def
- % Build names array in the order they occur in the 'post' table
- /postpos glyphnames def
- /total_length postglyphs //string_array_size exec def
- [ numglyphs 1 sub {
- postpos total_length ge { exit } if
- % No name available, /postnames will be defined as an empty
- % array and the glyph won't get a name attached.
- postglyphs postpos //get_from_stringarray exec
- postglyphs postpos 1 add 2 index //getinterval_from_stringarray exec cvn
- exch postpos add 1 add /postpos exch def
- } repeat
- ] /postnames exch def
- [ 0 1 numglyphs 1 sub {
- 2 mul 34 add post_first exch getu16
- dup 258 lt {
- MacGlyphEncoding exch get
- } {
- dup 32768 ge {
- % According to the published TrueType spec, such values are
- % "reserved for future use", but at least some PDF files
- % produced by the Adobe PDF library contain entries with a
- % value of 16#ffff.
- pop /.notdef
- } {
- % Get the name for this glyph
- 258 sub dup postnames length ge {
- TTFDEBUG { ( *** warning: glyph index past end of 'post' table) = flush } if
- exit
- } if
- postnames exch get
- % At least some of Microsoft's TrueType fonts use incorrect
- % (Adobe-incompatible) names for some glyphs.
- % Correct for this here.
- postremap 1 index .knownget { exch pop } if
- } ifelse
- } ifelse
- } for ]
- }
- ifelse
- } bind
- 16#00030000 { % No map.
- pop [ ]
- } bind
- .dicttomark readonly def % postformats
- /call.readtable
- { .readtable
- } bind def
- /call.readbigtable
- { .readbigtable
- } bind def
- % Each procedure in this dictionary is called as follows:
- % <file> <length> -proc- <string|array_of_strings>
- % Note that each table must have an even length, because of a strange
- % Adobe requirement that each sfnts entry have even length.
- /readtables mark
- % Ordinary tables
- (cmap) //call.readtable
- (head) 1 index
- (hhea) 1 index
- (maxp) 1 index
- (name) 1 index
- (OS/2) 1 index
- (post) //call.readbigtable
- (vhea) //call.readtable
- % Big tables
- (glyf) //call.readbigtable
- (loca) 1 index
- (hmtx) 1 index
- (vmtx) 1 index
- % Tables only needed for embedding in PDF files
- (cvt ) //call.readtable
- (fpgm) 1 index
- (prep) 1 index
- .dicttomark
- % Normally there would be a 'readonly' here, but the ttf2pf utility wants
- % to include the 'kern' table as well, so we leave the readtables dictionary
- % writable.
- def % readtables
- /readtables_stripped readtables dup length dict copy
- dup (loca) { .skiptable } put
- dup (glyf) { .skiptable } put
- def
- % Read a table as a single string.
- % <file> <length> .skiptable <string>
- /.skiptable {
- pop pop ()
- } bind def
- % Read a table as a single string.
- % <file> <length> .readtable <string>
- /.readtable {
- dup dup 1 and add string
- % Stack: f len str
- dup 0 4 -1 roll getinterval
- % Stack: f str str1
- % Because of the absurd PostScript specification that gives an
- % error for reading into an empty string, we have to check for
- % this explicitly here.
- 3 -1 roll exch
- dup () ne { readstring } if pop pop
- } bind def
- % Read a big table (one that may exceed 64K).
- % <file> <length> .readbigtable <string[s]>
- /.readbigtable {
- dup 65400 lt {
- .readtable
- } {
- currentuserparams /VMReclaim get -2 vmreclaim
- [ 4 2 roll {
- % Stack: mark ... f left
- dup maxstring le { exit } if
- 1 index maxstring string readstring pop 3 1 roll maxstring sub
- } loop .readtable ]
- exch vmreclaim
- } ifelse
- } bind def
- end readonly def % .loadttfontdict
- % <tab> .printtab -
- /.printtab {
- dup 0 4 getinterval print ( ) print
- dup 8 getu32 =only ( ) print
- 12 getu32 =
- } bind def
- % <file> <bool> <SubfontID> .loadttfonttables -
- % Pushes .loadttfontdict & scratch dict on d-stack.
- % Defines f, offsets, tables, tabdict, tabs.
- % Skips loca and glyf if <bool> is true.
- /.loadttfonttables {
- .loadttfontdict begin
- 40 dict begin
- /SubfontID exch def
- /load_stripped exch def
- /f exch def
- /offsets f 12 string readstring pop def
- load_stripped { readtables_stripped } { readtables } ifelse /readtables_ exch def
- offsets 0 4 getinterval (ttcf) eq {
- % We need to handle TT collections with disk fonts only.
- % Therefore the file is a disk file and it can be positioned.
- offsets 8 getu32 /num_fonts exch def
- SubfontID num_fonts ge {
- QUIET not { (True Type collection contains insufficient fonts.) = } if
- /.loadttfonttables cvx /invalidfont signalerror
- } if
- SubfontID 4 mul 12 add f exch setfileposition
- f 4 string readstring pop 0
- getu32 /ttc_offset exch def
- f ttc_offset setfileposition
- /offsets f 12 string readstring pop def
- } {
- SubfontID 0 gt {
- QUIET not { (SubfontID > 0 with a True Type file which is not a collection.) = } if
- /.loadttfonttables cvx /invalidfont signalerror
- } if
- /ttc_offset 0 def
- } ifelse
- /tables f offsets 4 getu16 16 mul string readstring pop def
- /tabdict tables length 16 idiv dict def
- % tabs = tables we want to keep, sorted by file position.
- /tabs [ 0 16 tables length 1 sub {
- tables exch 16 getinterval
- TTFDEBUG { dup .printtab } if
- dup 0 4 getinterval readtables_ 1 index known {
- % put all 0 length tables at 0 to avoid overlap
- 1 index 12 getu32 0 eq { 1 index 8 0 putu32 } if
- tabdict exch 2 index put
- } {
- pop pop
- } ifelse
- } for ] {
- exch 8 getu32 exch 8 getu32 lt
- } .sort def
- % In certain malformed TrueType fonts, tables overlap.
- % Truncate tables if necessary.
- 0 1 tabs length 2 sub {
- dup tabs exch get exch 1 add tabs exch get
- 1 index 8 getu32 2 index 12 getu32 add
- 1 index 8 getu32 gt {
- (**** Warning: ) print 1 index 0 4 getinterval print
- ( overlaps ) print dup 0 4 getinterval print
- (, truncating.) = flush
- dup 8 getu32 2 index 8 getu32 sub
- 2 index 12 3 -1 roll putu32
- } if pop pop
- } for
- } bind def
- /.file_table_pos_names
- mark
- /glyf 0
- /loca 0
- .dicttomark readonly def
- % - .readttdata -
- % Read data. Updates offsets, tabs; stores data in tabdict.
- /.readttdata {
- /file_table_pos 10 dict def
- /fpos offsets length tables length add ttc_offset add def
- /sfpos offsets length tabs length 16 mul add def
- offsets 4 tabs length putu16
- tabs {
- dup 0 4 getinterval /tname exch def
- dup 8 getu32 /tpos exch def
- dup 12 getu32 /tlen exch def
- load_stripped //.file_table_pos_names tname known and {
- pop
- file_table_pos tname [tpos tlen] put
- tabdict tname () put
- } {
- 8 sfpos putu32
- % Skip data between the end of the previous table and
- % the beginning of this one, if any.
- tpos fpos gt {
- load_stripped {
- % 'setfileposition' is faster for skipping a big data.
- f tpos setfileposition
- } {
- f tpos fpos sub () /SubFileDecode filter dup flushfile closefile
- /fpos tpos def
- } ifelse
- } if
- f tlen readtables_ tname get exec
- tabdict tname 3 -1 roll put
- % Round up the table length to an even value.
- /sfpos sfpos tlen dup 1 and add add def
- } ifelse
- /fpos fpos tlen add def
- } forall
- } bind def
- % Find the string in a list of strings that includes a given index.
- % <strings> <index> .findseg <string> <index'>
- /.findseg {
- exch {
- dup length 2 index gt { exch exit } if
- length sub
- } forall
- } bind def
- % - .makesfnts -
- % Defines checksum, getloca, head, locatable, numloca, post, sfnts, upem
- % Note that the 'loca' table may be out of order. This is handled when
- % needed in .dividesfnts
- /.makesfnts {
- .readttdata
- /head tabdict /head get def
- /post tabdict /post .knownget {
- dup 0 get /post_first_part exch def
- } {
- null
- } ifelse def
- load_stripped not {
- /locatable tabdict /loca get def
- /numloca
- locatable dup type /stringtype eq
- { length }
- { 0 exch { length add } forall }
- ifelse % no def yet
- locatable type /stringtype eq {
- /.indexloca {} def
- } {
- /.indexloca /.findseg load def
- } ifelse
- head 50 getu16 0 ne {
- /getloca {
- 2 bitshift locatable exch .indexloca getu32
- } def
- 4 idiv 1 sub
- } {
- /getloca {
- dup add locatable exch .indexloca getu16 dup add
- } def
- 2 idiv 1 sub
- } ifelse def % numloca
- % If necessary, re-partition the glyfs.
- tabdict /glyf get dup type /stringtype ne {
- .dividesfnts tabdict /glyf 3 -1 roll put
- } {
- pop
- } ifelse
- } {
- % We did not load loca, take the number of glyphs from maxp.
- /numloca tabdict /maxp get 4 getu16 def
- } ifelse
- /sfnts [
- offsets tabs { concatstrings } forall
- tabs {
- 0 4 getinterval tabdict exch get
- dup type /stringtype ne { aload pop } if
- } forall
- ] def
- } bind def
- % <glyfs> .dividesfnts <glyfs'>
- /.dividesfnts {
- /glyfs exch def
- /len1 0 glyfs { length add } forall def
- % Determine where to split the glyfs by scanning the sorted locatable
- % The very last entry in loca may be bogus.
- % Note that some loca entries may be odd, but we can only
- % split at even positions.
- %
- % Construct splitarray, the array of final lengths of
- % the sfnts entries covering the glyfs (i.e., all but
- % the first and last sfnts entries).
- /prevsplit 0 def
- /prevboundary 0 def
- % sort the locatable in case it is out of order
- % Note the 'loca' table remains unchanged
- /needsort false def
- numloca array % the array of 'loca' entries (may be out of order)
- -1 % initial values for in order check
- 0 1 numloca 1 sub {
- dup getloca dup
- 4 -1 roll lt { /needsort true def } if
- 3 copy put exch pop
- } for pop % discard inorder check value
- needsort {
- { lt } bind .sort % stack: locatable_array
- } if
- /splitarray [
- 3 -1 roll 0 1 numloca 1 sub {
- % stack: /splitarray -mark- { splitlen splitlen ... } locatable_array index
- 1 index exch get dup prevsplit maxstring add gt {
- prevboundary prevsplit sub exch
- /prevsplit prevboundary def
- } if
- dup 1 and 0 eq { /prevboundary exch def } { pop } ifelse
- dup type /arraytype ne { exch } if % keep locatable_array on top
- } for
- len1 prevsplit sub
- exch pop % discard locatable_array
- ] def
- currentuserparams /VMReclaim get -2 vmreclaim
- [
- % Re-split the sfnts glyfs strings according to splitarray.
- % We do this by iterating over the final segments defined
- % by splitarray, and constructing them from pieces of the
- % current glyfs strings. We recycle the current strings
- % when possible, to avoid stressing the allocator.
- /sfnt_idx 0 def
- /strpos 0 def
- /avail () def
- splitarray {
- /seglen exch def
- /segpos 0 def
- avail length seglen ge
- { avail 0 seglen getinterval /avail () def } { seglen string }
- ifelse
- {
- /str glyfs sfnt_idx get def
- /strlen str length def
- /strleft strlen strpos sub def
- seglen segpos sub strleft lt { exit } if
- % Copy the (rest of the) string into the new segment.
- % We know strleft <= segleft.
- dup segpos str strpos strleft getinterval putinterval
- /segpos segpos strleft add def
- /avail str def
- /sfnt_idx sfnt_idx 1 add def
- /strpos 0 def
- segpos seglen eq { exit } if
- } loop
- % Fill up the segment with an initial piece of the next
- % existing glyfs string. We know strleft > segleft.
- /segleft seglen segpos sub def
- dup segpos str strpos segleft getinterval putinterval
- /strpos strpos segleft add def
- } forall
- ]
- exch vmreclaim
- } bind def
- /first_post_string % - first_post_string <string>
- {
- post dup type /arraytype eq { 0 get } if
- } bind def
- % - .getpost -
- % Uses post, defines glyphencoding
- /.getpost {
- /glyphencoding post null eq {
- TTFDEBUG { (post missing) = flush } if [ ]
- } {
- postformats first_post_string 0 getu32 .knownget {
- TTFDEBUG {
- (post: format ) print
- first_post_string
- dup 0 getu16 =only (,) print 2 getu16 = flush
- } if
- post exch exec
- } {
- TTFDEBUG { (post: unknown format ) print post 0 getu32 = flush } if [ ]
- } ifelse
- } ifelse
- TTFDEBUG { (post=) print dup == } if
- def
- } bind def
- % - .ttkeys <key> <value> ...
- /.ttkeys {
- count /ttkeycount exch def
- /upem head 18 getu16 def
- /FontMatrix matrix
- /FontBBox [ 36 2 42 { head exch gets16 upem div } for ]
- nextxuid
- tabdict /name .knownget {
- % Find the names from the 'name' table.
- /names exch def
- /FontName names 6 findname not { curxuid 16 8 string cvrs } if
- /fontname 1 index def
- /FontInfo mark
- names 0 findname { /Notice exch } if
- names 1 findname { /FamilyName exch } if
- names 4 findname { /FullName exch } if
- names 5 findname { /Version exch } if
- } {
- % No name table, fabricate a FontName.
- /FontName curxuid 16 8 string cvrs
- /fontname 1 index def
- /FontInfo mark
- } ifelse
- % Stack: ... /FontInfo mark key1 value1 ...
- post null ne {
- /ItalicAngle first_post_string 4 gets32 65536.0 div
- /isFixedPitch first_post_string 12 getu32 0 ne
- /UnderlinePosition first_post_string 8 gets16 upem div
- /UnderlineThickness first_post_string 10 gets16 upem div
- } if
- counttomark 0 ne { .dicttomark } { pop pop } ifelse
- /XUID [orgXUID 42 curxuid]
- TTFDEBUG {
- tabs { .printtab } forall
- [ sfnts { length } forall ] ==
- count ttkeycount sub array astore dup { == } forall aload pop
- } if
- /sfnts sfnts
- } bind def
- % ---------------- Standard TrueType font loading ---------------- %
- % - .pickcmap_with_no_xlatmap -
- % Defines cmapsub, cmaptab
- /.pickcmap_with_no_xlatmap {
- tabdict /cmap get
- % The Apple cmap format is no help in determining the encoding.
- % Look for a Microsoft table. If we can't find one,
- % just use the first table, whatever it is.
- dup 4 8 getinterval exch % the default
- 0 1 2 index 2 getu16 1 sub {
- 8 mul 4 add 1 index exch 8 getinterval
- TTFDEBUG {
- (cmap: platform ) print dup 0 getu16 =only
- ( encoding ) print dup 2 getu16 = flush
- } if
- dup 0 getu16 3 eq { exch 3 -1 roll pop exit } if pop
- } for
- % Stack: subentry table
- /cmapsub 2 index def
- exch 4 getu32 1 index length 1 index sub getinterval
- /cmaptab exch def
- } bind def
- % - .pickcmap_with_xlatmap -
- % Defines cmapsub, cmaptab
- /.pickcmap_with_xlatmap {
- .xlatmap_dict /TrueType known not {
- (Emulating a CID font with a True Type file, ) print
- (the file gs/lib/xlatmap must contain /TrueType key.) =
- /.pickcmap_with_xlatmap cvx /configurationerror signalerror
- } if
- false
- .xlatmap_dict /TrueType get
- dup length 2 sub 0 exch 2 exch { % bool [] i
- 2 copy get % bool [] i ()
- (.) search { % bool [] i post match pre
- cvi exch pop exch cvi % bool [] i PlatID SpecID
- } {
- (gs/lib/xlatmap containg a record with an invalid (PlatformID.SpecificID)) =
- /.pickcmap_with_xlatmap cvx /configurationerror signalerror
- } ifelse
- TTFDEBUG {
- (Seeking a cmap for platform=) print 1 index =only ( encoding=) print dup =
- } if
- tabdict /cmap get % bool [] i PlatID SpecID (cmap)
- dup /cmaptab exch def % temporary
- 0 1 2 index 2 getu16 1 sub { % bool [] i PlatID SpecID (cmap) j
- 8 mul 4 add 1 index exch 8 getinterval % bool [] i PlatID SpecID (cmap) (cmapsub)
- TTFDEBUG {
- (cmap: platform ) print dup 0 getu16 =only
- ( encoding ) print dup 2 getu16 = flush
- } if
- dup 0 getu16 4 index eq {
- dup 2 getu16 3 index eq { % bool [] i PlatID SpecID (cmap) (cmapsub)
- TTFDEBUG {
- (Choosen a cmap for platform=) print 3 index =only
- ( encoding=) print 2 index =
- } if
- /cmapsub 1 index def
- dup 4 getu32 % bool [] i PlatID SpecID (cmap) (cmapsub) p
- cmaptab length 1 index sub % bool [] i PlatID SpecID (cmap) (cmapsub) p l
- cmaptab 3 1 roll getinterval
- /cmaptab exch def % bool [] i PlatID SpecID (cmap) (cmapsub)
- 5 index 5 index 1 add get % bool [] i PlatID SpecID (cmap) (cmapsub) /Decoding
- /Decoding exch def % bool [] i PlatID SpecID (cmap) (cmapsub)
- 7 -1 roll pop true 7 1 roll % true [] i PlatID SpecID (cmap) (cmapsub)
- } if
- } if
- pop % true [] i PlatID SpecID (cmap)
- 5 index { exit } if
- } for % bool [] i PlatID SpecID (cmap)
- pop pop pop pop % bool []
- 1 index { exit } if
- } for % bool []
- pop % bool
- not {
- QUIET not { (True Type font doesn't contain a charset listed in gs/lib/xlatmap.) = } if
- /.pickcmap_with_xlatmap cvx /invalidfont signalerror
- } if %
- } bind def
- % - .pickcmap -
- % Defines cmapsub, cmaptab
- /.pickcmap {
- % Currently we use xlatmap only for emulation CIDFontType 2 with
- % a disk True Type font files, and use load_stripped
- % to check this regime. We would like to do so
- % while emulating a Type 42, but first the old code
- % about handling them to be changed
- % with adding a handling of a Decoding.
- % fixme : A correct way to fix this is to implenent
- % the Type 42 emulation with gs_fntem.ps .
- % Also note that PDF embedded fonts probably don't need a xlatmap -
- % see PDF spec, "Encodings for True Type fonts".
- load_stripped {
- //.pickcmap_with_xlatmap exec
- } {
- //.pickcmap_with_no_xlatmap exec
- } ifelse
- } bind def
- % <glyph> .nname <_name>
- /.nname {
- =string cvs (_) exch concatstrings cvn
- } bind def
- % - .charkeys /CharStrings <charstrings> /Encoding <encoding>
- % Resets glyphencoding
- /.charkeys {
- TTFDEBUG {
- (glyphencoding: length=) print glyphencoding dup length = === flush
- } if
- % Hack: if there is no usable post table but the cmap uses
- % the Microsoft Unicode encoding, use ISOLatin1Encoding.
- glyphencoding length 0 eq {
- cmapsub 0 4 getinterval <00030001> eq {
- PDFDEBUG { (No post but have cmap 3.1, so use ISOLatin1Encoding) } if
- /glyphencoding ISOLatin1Encoding dup length array copy def
- } {
- PDFDEBUG { (No encoding info, use .GS_extended_SymbolEncoding) } if
- /glyphencoding /.GS_extended_SymbolEncoding findencoding dup length array copy def
- } ifelse
- } if
- % If necessary, fabricate additional glyphencoding entries
- % to cover all of loca, or truncate glyphencoding.
- glyphencoding length numloca lt {
- /glyphencoding numloca array
- glyphencoding length dup 1 sub 0 1 3 2 roll {
- dup glyphencoding exch get
- 3 index 3 1 roll put
- } for
- % /glyphencoding <newarray> <glyphencoding length>
- 1 numloca 1 sub {
- 1 index exch dup .nname put
- } for
- def
- } {
- /glyphencoding glyphencoding 0 numloca getinterval def
- } ifelse
- % Some badly designed Chinese fonts have a post table
- % in which all glyphs other than 0 are named .null.
- % Use CharStrings to keep track of the reverse map from
- % names to glyphs, and don't let any name be used for
- % more than one glyph.
- /CharStrings glyphencoding dup length 1 add dict % +1 for .notdef
- 0 1 3 index length 1 sub {
- % Stack: glyphencoding dict index
- 2 index 1 index get 2 index 1 index known {
- % The same name maps to more than one glyph.
- % Change the name.
- pop dup .nname 3 index 2 index 2 index put
- } if
- 2 index exch 3 -1 roll put
- } for exch pop
- % If there is no .notdef entry, map it to glyph 0.
- dup /.notdef known not { dup /.notdef 0 put } if
- readonly
- /Encoding
- [ cmaptab cmaparray dup length 256 gt { 0 256 getinterval } if
- { glyphencoding exch get } forall
- counttomark 256 exch sub { /.notdef } repeat ]
- TTFDEBUG { (Encoding: ) print dup === flush } if
- } bind def
- % -mark- <key> <value> ... .definettfont <font>
- /.definettfont {
- /FontType 42
- /PaintType 0
- TTFDEBUG {
- (numloca=) print numloca =
- } if
- .dicttomark
- end end dup /FontName get exch definefont
- } bind def
- % <file> .loadttfont <type42font>
- /.loadttfont {
- //false 0 .loadttfonttables
- .makesfnts
- .getpost
- .pickcmap
- mark
- .charkeys
- .ttkeys
- .definettfont
- } bind def
- % ---------------- CIDFontType 2 font loading ---------------- %
- % Fill a string with sequential CIDs starting from the initial value.
- % <string> <value> .fill_identity_cmap <string>
- /.fill_identity_cmap { % () v
- 1 index length 2 sub % () v n-2
- 0 2 3 2 roll { % () v 0 2 n-1
- 3 copy exch % () v i () i v
- -8 bitshift % () v i () i v>>8
- put % () v i
- 3 copy 1 add % () v i () v i+1
- exch 255 and % () v i () i+1 v&255
- put % () v i
- pop 1 add % () v+1
- } for
- pop
- } bind def
- % -mark- <key> <value> ... .definettcidfont <font>
- /.definettcidfont {
- /CIDFontName fontname
- /CIDFontType 2
- /CIDSystemInfo mark
- /Registry (Adobe)
- /Ordering (Japan1) % adhoc
- /Supplement 0
- .dicttomark
- /CharStrings mark /.notdef 0 .dicttomark
- % The cmap isn't of any use even if it is present.
- % Just construct an identity CIDMap covering all the glyphs.
- /CIDCount numloca % Wrong if a CIDFontType2 embedded into PDF with a non-Identity CIDToGIDMap.
- % processCIDToGIDMap may replace.
- /CIDMap numloca maxstring le {
- % Use a single string.
- numloca 2 mul string 0 .fill_identity_cmap
- } {
- % We must use 2 strings.
- maxstring 2 mul string 0 .fill_identity_cmap
- numloca maxstring sub 2 mul string maxstring .fill_identity_cmap
- 2 array astore
- } ifelse
- /GDBytes 2
- .dicttomark
- end end dup /CIDFontName get exch /CIDFont defineresource
- } bind def
- % <file> .loadttcidfont <cidtype2font>
- /.loadttcidfont {
- //false 0 .loadttfonttables
- .makesfnts
- % CIDFontType2 fonts don't have a cmap: they are indexed by CID.
- mark
- .ttkeys
- .definettcidfont
- } bind def
- % <file> <SubfontID> .load_tt_font_stripped <font_data>
- % The font_data includes sfnts, NumGlyphs, TT_cmap, file_table_pos, Decoding.
- % CIDMap to be created later from TT_cmap.
- /.load_tt_font_stripped {
- //true exch .loadttfonttables
- .makesfnts
- .pickcmap
- mark
- .ttkeys
- /NumGlyphs numloca
- /TT_cmap cmaptab cmaparray
- /file_table_pos file_table_pos
- /Decoding Decoding
- .dicttomark
- end end
- } bind def
- % ---------------- PDF TrueType font loading ---------------- %
- % Strictly speaking, this code should be loaded only if we have a PDF
- % interpreter, but it's so closely tied to the rest of the code in this
- % file that we always include it.
- % <plat+enc> .findcmap <subtable> true
- % <plat+enc> .findcmap false
- /.findcmap {
- false exch tabdict /cmap get
- % Some fonts have multiple cmaps with the same platform and
- % encoding. Use the first one we find.
- 0 1 2 index 2 getu16 1 sub {
- % Stack: false plat+enc cmap index
- 8 mul 4 add 1 index exch 8 getinterval
- dup 0 4 getinterval 3 index eq {
- 4 getu32 1 index exch 1 index length 1 index sub getinterval
- 4 -1 roll not 4 2 roll exit
- } if pop
- } for
- % Stack: false plat+enc cmap || subtable true plat+enc cmap
- pop pop
- } bind def
- % Build .symbol_list for .pdfcharkeys .
- % It is a dictionary containing all SymbolEncoding glyph names
- % and random names for filling gaps in the character code range.
- /.symbol_list 256 dict def
- {
- =string 0 (x) 0 get put
- /SymbolEncoding .findencoding
- 0 1 255 {
- dup 2 index exch get
- dup /.notdef eq {
- pop dup
- =string 1 3 getinterval cvs length 1 add
- =string exch 0 exch getinterval cvn
- } if
- exch //.symbol_list 3 1 roll put
- } for
- pop
- } bind exec
- % Create .GS_extended_SymbolEncoding as inverse of .symbol_list .
- {
- /.GS_extended_SymbolEncoding 256 array
- //.symbol_list {
- exch 2 index 3 1 roll put
- } forall
- .defineencoding
- } bind exec
- /.addglyph % <name> <glyph#> .addglyph <name> <glyph#>
- % <name> <glyph#> .addglyph -
- {
- dup cmapencoding length lt {
- cmapencoding exch get dup 0 eq {
- pop pop
- } if
- } {
- pop pop
- } ifelse
- } bind def
- % <subcmap> <chartoglyphmap> .pdfmapchars
- % /CharStrings <charstrings>
- /.pdfmapchars {
- exch cmaparray /cmapencoding exch def
- /CharStrings mark
- % Add glyphs of <chartoglyphmap>*<subcmap> :
- 3 2 roll {
- dup type /arraytype eq {
- exch /.name exch def
- { .name exch //.addglyph exec
- } forall
- currentdict /.name undef
- } {
- //.addglyph exec
- } ifelse
- } forall
- % stack: /CharStrings mark /name1 glyph#1 /name2 glyph#2 ... /namen glyph#n
- % Stack depth is restricted with AdobeGlyphList size.
- % Add glyphs of 'post' (with lower priority, see .dicttomark) :
- 0 1 glyphencoding length 1 sub {
- dup glyphencoding exch get exch
- dup 0 eq {
- pop pop
- } if
- } for
- /.notdef 0
- .dicttomark
- } bind def
- % - .pdfcharkeys /CharStrings <charstrings> /Encoding <encoding>
- /.pdfcharkeys {
- % The following algorithms are per the PDF Reference, Second Edition
- % (PDF 1.3 reference manual).
-
- is_symbolic {
- <00030001> .findcmap {
- %
- % Adobe PDF spec says that symbolic fonts should contain exactly one
- % cmap subtable for Platform=1, Encoding=0.
- % Perhaps "Adobe Acrobat PDFWriter 4.0 for Windows" sometimes embeds
- % fonts with both subtables 3.1 and 1.0 (see comparefiles/159.pdf,
- % the font "Arial,Bold" with the character "registered"),
- % and both Acrobat Reader 4.0 and 5.0 choose 3.1.
- % Therefore we try 3.1 first.
- %
- ( **** Warning: Embedded symbolic TT fonts should not contain a cmap for Platform=3 Encoding=1.\n)
- pdfformaterror
- TTFDEBUG { (Using cmap 3.1) = } if
- AdobeGlyphList .pdfmapchars
- /Encoding /WinAnsiEncoding .findencoding
- } {
- %
- % Adobe PDF spec says that in this case PDF interpreter should
- % map character codes directly to glyphs using
- % the cmap <00010000>. But we use PS interpreter to emulate
- % a PDF interpreter. Therefore we need to construct
- % a type 42 font, which requires an Encoding and a Charstrings.
- % We construct them with symbol_list, which
- % includes all glyphs from SymbolEncoding and additional
- % random names for 1-to-1 mapping.
- %
- % A real TT font may use a different characters than
- % the Symbol charaster set. Perhaps our code
- % will give a correct printing, because glyph names are not
- % important for symbolic fonts in PDF.
- %
- <00010000> .findcmap {
- prebuilt_encoding null ne {
- TTFDEBUG { (Using cmap 1.0 with prebuilt_encoding.) = } if
- prebuilt_encoding .invert_encoding .pdfmapchars
- /Encoding prebuilt_encoding
- } {
- % This is a case, in which an obsolete software could stupidly specify Macintosh Roman
- % for a random encoding. Particulatrly GPL Ghostscript 7.06 does so.
- % Trying to recover with 'post'.
- pop % The table itself doesn't contain useful data.
- TTFDEBUG { (Using cmap 1.0 with post or .GS_extended_SymbolEncoding) = } if
- .charkeys
- } ifelse
- } {
- % This is illegal with PDF spec.
- ( **** Warning: Embedded symbolic TT fonts must contain a cmap for Platform=1 Encoding=0.\n)
- pdfformaterror
- % Try to map Unicode to SymbolEncoding
- <00030001> .findcmap {
- TTFDEBUG { (Using cmap 3.1) = } if
- AdobeGlyphList .pdfmapchars
- /Encoding /SymbolEncoding .findencoding
- } {
- % Apply the default algorithm. Hopely it has 'post'.
- .charkeys
- % check if the CharStrings dict contains glyphs needed by the
- % prebuilt_encoding otherwise try the 3,0 cmap.
- prebuilt_encoding null ne {
- false prebuilt_encoding { % false means no missing glyphs
- 4 index exch known not { pop true exit } if
- } forall
- {
- ( **** Warning: Encoding derived from 'post' is incomplete.\n)
- pdfformaterror
- % Try another cmap format 3,0 -- Adobe doesn't mention it, but does
- % use it apparently (empirically determined).
- <00030000> .findcmap {
- TTFDEBUG { (Adding cmap 3.0) = } if
- 5 1 roll pop pop pop pop
- prebuilt_encoding null ne {
- prebuilt_encoding .invert_encoding .pdfmapchars
- /Encoding prebuilt_encoding
- } {
- AdobeGlyphList .pdfmapchars
- /Encoding /SymbolEncoding .findencoding
- } ifelse
- } if
- }if
- } if
- } ifelse
- } ifelse
- } ifelse
- } {
- <00030001> .findcmap {
- TTFDEBUG { (Using cmap 3.1 for non-symbolic.) = } if
- AdobeGlyphList .pdfmapchars
- /Encoding /WinAnsiEncoding .findencoding
- % WinAnsiEncoding is just a stub here.
- % It will be replaced with one from font resource,
- % because PDF spec requires it.
- } {
- <00010000> .findcmap {
- TTFDEBUG { (Using cmap 1.0 for non-symbolic.) = } if
- .romanmacdict .pdfmapchars
- /Encoding /MacRomanEncoding .findencoding
- } {
- % Apply the default algorithm for using the 'post'.
- .charkeys
- } ifelse
- } ifelse
- } ifelse
- } bind def
- % <file> <is_symbolic> <Encoding|null> .loadpdfttfont <type42font>
- /.loadpdfttfont {
- /prebuilt_encoding exch def % for .pdfcharkeys
- /is_symbolic exch def
- //false 0 .loadttfonttables
- .makesfnts
- .getpost
- .pickcmap
- mark
- .pdfcharkeys
- .ttkeys
- .definettfont
- } bind def
|