Documente Academic
Documente Profesional
Documente Cultură
%
% 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.
% 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.
/.scanfontheaders where {
pop /.scanfontheaders [
.scanfontheaders aload pop (\000\001\000\000*) (true*)
] def
} if
% <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
% 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
/sHK_sz 2 def
/sH_sz 8 def
dup 2 getu16 /cmapf2_tblen exch 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
% <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 nd 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 {
1 index 12 4 getinterval (\0\0\0\0) eq {
pop pop % Ignore zero-length table
} {
tabdict exch 2 index put
} ifelse
} {
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
% - .getpost -
% Uses post, defines glyphencoding
/.getpost {
/glyphencoding post null eq {
TTFDEBUG { (post missing) = flush } if [ ]
} {
postformats post 0 getu32 .knownget {
TTFDEBUG {
(post: format ) print
post 0 getu16 =only (,) print post 2 getu16 = flush
} if
post exch exec
} {
TTFDEBUG { (post: unknown format ) print post 0 getu32 = flush } if [ ]
} ifelse
} ifelse def
} bind def
% - .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
% 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
/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
% stack: /CharStrings mark /name1 glyph#1 /name2 glyph#2 ... /namen glyph#n
% Stack depth is restricted with AdobeGlyphList size.
/.notdef 0
.dicttomark
} bind def
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
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 {
prebuilt_encoding .invert_encoding .pdfmapchars
/Encoding prebuilt_encoding
} {
.symbol_list .pdfmapchars
/Encoding /.GS_extended_SymbolEncoding .findencoding
} 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 {
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 {
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 {
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 {
.romanmacdict .pdfmapchars
/Encoding /MacRomanEncoding .findencoding
} {
% Apply the default algorithm for using the 'post'.
.charkeys
} ifelse
} ifelse
} ifelse
} bind def