home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Acorn User 10
/
AU_CD10.iso
/
Updates
/
GhostScript
/
!GhostScr
/
6_01
/
lib
/
gs_cidfn.ps
< prev
next >
Wrap
Text File
|
2000-03-29
|
15KB
|
465 lines
% Copyright (C) 1995, 2000 Aladdin Enterprises. All rights reserved.
%
% This file is part of Aladdin Ghostscript.
%
% Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author
% or distributor accepts any responsibility for the consequences of using it,
% or for whether it serves any particular purpose or works at all, unless he
% or she says so in writing. Refer to the Aladdin Ghostscript Free Public
% License (the "License") for full details.
%
% Every copy of Aladdin Ghostscript must include a copy of the License,
% normally in a plain ASCII text file named PUBLIC. The License grants you
% the right to copy, modify and redistribute Aladdin Ghostscript, but only
% under certain conditions described in the License. Among other things, the
% License requires that the copyright notice and this notice be preserved on
% all copies.
% $Id: gs_cidfn.ps,v 1.3 2000/03/10 04:53:25 lpd Exp $
% ProcSet for implementing CIDFont and CIDMap resources.
% When this is run, systemdict is still writable.
% ---------------- Defining CIDFont resources ---------------- %
% Define a CIDFont resource. This is the defineresource implementation for
% the CIDFont resource category.
/.cidfonttypes where { pop } { /.cidfonttypes 6 dict def } ifelse
.cidfonttypes begin
% The key in .cidfonttypes is the CIDFontType value;
% the value is a procedure that takes a font name and the CIDFont dictionary
% and replaces the latter with a real font.
0 { % CIDFontType 0 = FontType 9
currentglobal 3 1 roll dup gcheck setglobal
dup /FontType 9 put
dup /FontMatrix known not {
dup /FontMatrix [0.001 0 0 0.001 0 0] put
dup /FDArray get {
/FontMatrix get [1000 0 0 1000 0 0] 1 index concatmatrix pop
} forall
} if
dup /FDArray get mark exch {
% Add pro forma entries
currentglobal exch dup gcheck setglobal
dup /FontType 1 put
dup /CharStrings mark /.notdef () .dicttomark put
dup /Encoding [] put
% Create a dummy Subrs array now, if there isn't one here
% already (which can only happen if we're giving another
% name to an existing font).
dup /Private get dup /Subrs known not {
dup /SubrCount .knownget {
array 1 index /Subrs 3 -1 roll put
} if readonly
} if pop
exch setglobal
dup /FontName .knownget not { () } if exch .buildfont1 exch pop
} forall ] 1 index /FDepVector 3 -1 roll put
3 -1 roll setglobal
1 index exch .buildfont9 exch pop
} bind def
1 { % CIDFontType 1 = FontType 10
dup /FontType 10 put
1 index exch .buildfont10 exch pop
} bind def
2 { % CIDFontType 2 = FontType 11
dup /FontType 11 put
1 index exch .buildfont11 exch pop
} bind def
end % .cidfonttypes
% ---------------- Reading CIDFontType 0 files ---------------- %
30 dict begin
% We add the following entries to the CIDFont dictionary, in addition to
% the ones documented by Adobe:
% ReadString - procedure for reading a string from the binary data
% SubrCache - dictionary for caching Subr arrays
% For CIDFonts where we read the data from disk incrementally:
% DataOffset - starting position of data in file
% (if data are in hex) OffsetMap - map from logical data positions to
% physical positions in file
/StartData % <(Binary)|(Hex)> <datalength> StartData -
% (currentdict is CID font dict)
{ % If we're loading a resource file, we can just save a
% pointer to the binary data and load it incrementally.
% Check for this by opening the resource file,
% positioning it to currentfile's position plus the
% data length, and checking for %%EndData.
mark
{ currentfile fileposition
CIDFontName 100 string ResourceFileName (r) file
mark
{ % Stack: (Binary)|(Hex) length -mark- pos resfile
% -mark-
5 index (Hex) eq
{ 1 index 3 index setfileposition
1 index 5 index .skiphex
%**************** SKIP > AND WHITESPACE SOMEHOW
}
{ 1 index 3 index 6 index add setfileposition
}
ifelse
1 index 9 string readstring pop (%%EndData) ne { stop } if
}
.internalstopped { cleartomark closefile stop } if
pop % pop the mark
}
.internalstopped
{ % File is not positionable, load the data now.
cleartomark exch (Hex) eq
{ { currentfile exch readhexstring pop } }
{ { currentfile exch readstring pop } }
ifelse /ReadString exch def
dup 65535 le {
% readstring with a 0-length string causes a rangecheck,
% but a data length of 0 is allowed.
string dup () ne { ReadString } if
} {
mark exch
{ dup 0 eq { pop exit } if
dup 65535 min dup string ReadString
3 1 roll sub
}
loop ]
} ifelse
/GlyphData exch def
% If we were reading hex data, skip past the >.
/ReadString load 2 get { readhexstring } 0 get eq {
currentfile 0 (>) /SubFileDecode filter dup flushfile closefile
} if
/.vmreadstring cvx
}
{ % File is positionable, just save a pointer.
% Stack: (Binary)|(Hex) length -mark- pos file
4 1 roll
/DataOffset exch def
pop /GlyphData exch def
exch (Hex) eq
{ % Hex data, build the offset map.
.buildoffsetmap
/.hexreadstring
}
{ % Binary data, just skip over it.
currentfile DataOffset GlyphData add setfileposition
/.binaryreadstring
}
ifelse cvx
2 packedarray cvx
}
ifelse /ReadString exch def
/SubrCache 10 dict def
CIDFontName currentdict /CIDFont defineresource pop
end % CID font dict
end % resource category dict
} bind def
% Skip a given distance in an ASCIIHex encoded file. We use this at
% rendering time as well.
/.skiphex % <file> <count> .skiphex -
{ exch /ASCIIHexDecode filter dup 3 -1 roll () /SubFileDecode filter
dup flushfile closefile closefile
} bind def
% Build the map from logical offsets to physical offsets in ASCIIHex
% encoded data.
/.buildoffsetmap
{ /OffsetMap GlyphData 256 idiv 8000 min array def
2 dict begin
/block GlyphData OffsetMap length idiv def
0 1 OffsetMap length 1 sub
{ OffsetMap exch currentfile fileposition put
currentfile block .skiphex
}
for
GlyphData block mod dup 0 eq
{ pop }
{ currentfile exch .skiphex }
ifelse
end % scratch dict
} bind def
% Some Adobe fonts include the line
% /Setup /cid_Setup load def
% This is apparently included only to prevent proper, conforming PostScript
% interpreters (as opposed to ATM or a special Adobe font loader) from
% loading the font, since Setup is not referenced anywhere else in the file.
%/cid_Setup { } def
currentdict end
% ---------------- Rendering ---------------- %
% ------ Generic ------ %
% Read a string at a given offset in a "file" (binary file, ASCII hex file,
% or GlyphData in RAM).
/.binaryreadstring % <pos> <string> <file> .binaryreadstring <string>
{ dup 4 -1 roll DataOffset add setfileposition exch readstring pop
} bind def
/.hexreadstring % <pos> <string> <file> .hexreadstring <string>
{ % Use the OffsetMap to get to the block of hex data,
% then skip to the correct position by reading.
GlyphData OffsetMap length idiv
% Stack: pos string file blocklen
3 index 1 index idiv OffsetMap exch get
2 index exch setfileposition
% Skip the next (pos % blocklen) hex bytes.
4 -1 roll exch mod 1 index exch .skiphex
% Stack: string file
exch readhexstring pop
} bind def
/.vmreadstring % <pos> <string> .vmreadstring <vmstring>
{ GlyphData .stringsreadstring
} bind def
/.stringsreadstring % <pos> <string> <strings> .stringsreadstring
% <vmstring>
{ dup type /stringtype eq
{ 3 1 roll length getinterval
}
{ { % Stack: pos string glyphdata
dup 0 get length dup 4 index gt { exit } if
4 -1 roll exch sub 3 1 roll
dup length 1 sub 1 exch getinterval
}
loop
% Stack: pos string glyphdata glyphdata[0]length
% We know no request can span more than 2 strings.
3 index 3 index length add 1 index le
{ % Request fits in a single string: just return a substring.
pop 0 get 3 1 roll length getinterval
}
{ % Request spans 2 strings. Copy the first part.
1 index 0 get 4 index 3 -1 roll 1 index sub getinterval
2 index copy
% Copy the second part.
% Stack: pos str glyphdata str1
length exch 1 get 0 3 index length
3 index sub getinterval 2 index 3 1 roll putinterval
exch pop
}
ifelse
}
ifelse
} bind def
% Interpret a byte string as a (big-endian) integer.
/.cvbsi % <bytes> .cvbsi <int>
{ 0 exch { exch 8 bitshift add } forall
} bind def
% Read an integer from binary data.
/.readint % <pos> <nbytes> .readint <int>
{ string ReadString .cvbsi
} bind def
% Read the glyph data for a given CID. The CIDFont is currentdict.
% Note that the data must be read into the same VM as the CharStrings
% dictionary of the selected subfont.
/.readglyphdata { % <cid> .readglyphdata <subfont> <string|null>
currentdict /GlyphDirectory .knownget {
dup type /arraytype eq {
1 index get
} {
1 index .knownget not { null } if
} ifelse
% Stack: cid string|null
dup null ne { exch pop .readgdirdata } { pop .readbytedata } ifelse
} {
% Stack: cid
.readbytedata
} ifelse
} bind def
/.readgdirdata { % <string|null> .readgdirdata <subfont> <string|null>
dup null eq {
FDepVector 0 get exch
} {
FDBytes 0 eq {
FDepVector 0 get exch
} {
% Note: FDBytes > 1 is not supported.
dup 0 get FDepVector exch get
exch dup length 1 sub 1 exch getinterval
} ifelse
} ifelse
} bind def
/.readbytedata { % <cid> .readbytedata <subfont> <string|null>
dup dup 0 ge exch CIDCount lt and {
FDBytes GDBytes add mul CIDMapOffset add
dup FDBytes .readint exch
FDBytes add dup GDBytes .readint
exch GDBytes add FDBytes add GDBytes .readint
% Stack: fd pos nextpos
1 index sub dup 0 eq {
pop pop pop FDepVector 0 get null
} {
% Stack: fd pos len
FDepVector 4 -1 roll get
dup /CharStrings get gcheck .currentglobal exch .setglobal
% Stack: pos len subfont global
4 2 roll string ReadString exch .setglobal
} ifelse
} {
pop FDepVector 0 get null
} ifelse
} bind def
% ------ CIDFontType 0 ------ %
% Read some Subrs for the current Type 1 subfont.
% The subfont's Private dict is currentdict; the CIDFont itself is the
% next dictionary on the stack.
/.readsubrs { % <Subrs> <start> .readsubrs <Subrs>
1 SubrCount 1 sub {
dup SDBytes mul SubrMapOffset add
dup SDBytes .readint exch SDBytes add SDBytes .readint
1 index sub string ReadString 2 index 3 1 roll put
} for
} bind def
% Ensure that all the Subrs for the current Type 1 subfont are loaded.
% The subfont's Private dict is currentdict; the CIDFont itself is the
% next dictionary on the stack.
/.loadsubrs {
currentdict /SubrMapOffset .knownget {
Subrs length 0 eq { true } { Subrs 0 get null ne } ifelse {
pop % We've already loaded the Subrs.
} {
currentglobal exch currentdict gcheck setglobal
SubrCache 1 index .knownget {
% We've already loaded some Subrs at this offset.
% Make sure we've got as many as we need.
dup length SubrCount lt {
% We need to load more.
SubrCount array exch 1 index copy length .readsubrs
SubrCache 3 -1 roll 2 index put
} if
} {
% We haven't loaded any Subrs at this offset yet.
SubrCount array 0 .readsubrs
SubrCache 3 -1 roll 2 index put
} ifelse
Subrs copy pop setglobal
} ifelse
} if
} bind def
% BuildGlyph procedure for CIDFontType 0.
% ****** WHY NOT USE .type1execchar FOR THIS? ******
% The name %Type9BuildGlyph is known to the interpreter.
/.cid0buildstring 10 string def
(%Type9BuildGlyph) cvn { % <cidfont> <cid> %Type9BuildGlyph -
.currentglobal 3 1 roll 1 index gcheck .setglobal
1 index begin
dup .readglyphdata dup null eq {
% Substitute CID 0. **** WRONG ****
pop pop 0 .readglyphdata
} if
% Stack: cidfont cid subfont charstring
dup null eq { pop pop pop pop } { %**** WRONG ****
4 -1 roll pop
exch dup /Private get begin .loadsubrs end
3 -1 roll //.cid0buildstring cvs cvn 3 1 roll
dup /CharStrings get 3 index 4 -1 roll put
setfont
dup .glyphwidth setcharwidth
0 0 moveto glyphshow
} ifelse %**** WRONG ****
end
.setglobal
} bind def
% ------ CIDFontType 2 ------ %
% BuildGlyph procedure for CIDFontType 2.
% ****** ADD THE OUTLINE STRING AS AN ARGUMENT TO .type42execchar. ******
% The name %Type11BuildGlyph is known to the interpreter.
(%Type11BuildGlyph) cvn { % <cidfont> <cid> %Type11BuildGlyph -
.currentglobal 3 1 roll 1 index gcheck .setglobal
1 index begin
% We must be prepared for out-of-range CIDs.
dup GDBytes mul GDBytes string CIDMap
mark 4 1 roll { .stringsreadstring } .internalstopped {
%**** 0 IS WRONG
cleartomark 0 GDBytes string CIDMap .stringsreadstring
} {
exch pop
} ifelse .cvbsi
% Stack: cidfont cid glyphindex
1 index exch .type42execchar
end
.setglobal
} bind def
% ---------------- Define resources ---------------- %
languagelevel exch 2 .setlanguagelevel
% Define the CIDInit ProcSet resource.
% The ProcSet dictionary is still on the stack.
/CMap /Generic /Category findresource dup length dict .copydict
/Category defineresource pop
% We might have loaded CMap support already.
/CIDInit /ProcSet 2 copy resourcestatus {
pop pop findresource dup length 4 index length add dict .copydict
4 -1 roll exch .copydict
} {
3 -1 roll
} ifelse exch defineresource pop
% Define the CIDFont resource category.
% We break out .buildcidfont because it appears that at least for
% Type 32 (CIDFontType 4) fonts, the font can be registered in the Font
% category with only a CIDFontType and no FontType.
/.buildcidfont { % <name> <fontdict> .buildcidfont
% <name> <cidfont>
dup /CIDFontType get //.cidfonttypes exch get exec
} odef
/CIDFont /Generic /Category findresource dup length dict .copydict
dup /InstanceType /dicttype put
dup /DefineResource {
.buildcidfont
/Generic /Category findresource /DefineResource get exec
} put
/Category defineresource pop
% Add the new FontType resources.
9 1 11 { dup /FontType defineresource pop } for
% Add the new FMapType resource.
9 dup /FMapType defineresource pop
% Define the CIDMap resource category.
% These aren't documented, but it's clear what they are for:
% to give names to CIDMaps for CIDFontType 2 fonts.
/CIDMap /Generic /Category findresource dup length dict .copydict
dup /.CheckResource {
% Allow either a string or an array of strings.
dup type dup /stringtype eq
{ pop true
}
{ dup /arraytype eq exch /packedarraytype eq or
{ true exch { type /stringtype ne { pop false exit } if } forall
}
{ false
}
ifelse
}
ifelse
} bind put
/Category defineresource pop
.setlanguagelevel