summaryrefslogtreecommitdiff
path: root/gs/lib/gs_cidfn.ps
diff options
context:
space:
mode:
Diffstat (limited to 'gs/lib/gs_cidfn.ps')
-rw-r--r--gs/lib/gs_cidfn.ps428
1 files changed, 428 insertions, 0 deletions
diff --git a/gs/lib/gs_cidfn.ps b/gs/lib/gs_cidfn.ps
new file mode 100644
index 000000000..557065b7c
--- /dev/null
+++ b/gs/lib/gs_cidfn.ps
@@ -0,0 +1,428 @@
+% Copyright (C) 1995, 1996, 1997 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.
+
+% 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.
+
+/.definecidfont [
+
+% CIDFontType 0
+{ 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
+ dup /FontType 1 put
+ dup /CharStrings 10 dict put
+ dup /Encoding [] put
+ % Create a dummy Subrs array now.
+ dup /Private get dup /SubrCount .knownget
+ { array 1 index /Subrs 3 -1 roll put }
+ if pop
+ dup /FontName .knownget not { () } if exch .buildfont1 exch pop
+ }
+ forall ] 1 index /FDepVector 3 -1 roll put
+ 1 index exch .buildfont9 exch pop
+} bind
+
+% CIDFontType 1
+{ 1 index exch .buildfont10 exch pop
+} bind
+
+% CIDFontType 2
+{ 1 index exch .buildfont11 exch pop
+} bind
+
+] def
+
+% ---------------- 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
+ { string ReadString
+ }
+ { mark exch
+ { dup 0 eq { pop exit } if
+ dup 65535 min dup string ReadString
+ 3 1 roll sub
+ }
+ loop ]
+ }
+ ifelse
+ /GlyphData exch def
+ /.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
+
+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.
+/.readglyphdata % <cid> .readglyphdata <subfont> <string|null>
+{ currentdict /GlyphDirectory .knownget
+ { dup type /arraytype eq
+ { 1 index exch get }
+ { 1 index exch .knownget not { null } if }
+ ifelse
+ 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
+ }
+ { 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 }
+ { string ReadString exch FDepVector exch get exch }
+ ifelse
+ }
+ 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 0 get null ne
+ { pop % We've already loaded the Subrs.
+ }
+ { 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
+ }
+ 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
+ { %**** HANDLE NOTDEF ****
+ }
+ 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
+ 1000 0 setcharwidth %**** WRONG ****
+ 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
+ dup GDBytes mul GDBytes string CIDMap .stringsreadstring .cvbsi
+ % Stack: cidfont cid glyphindex
+%**************** GlyphDirectory is not supported yet.
+(
+ currentdict /GlyphDirectory .knownget
+) pop false
+ { dup type /arraytype eq
+ { 1 index exch get }
+ { 1 index exch .knownget not { null } if }
+ ifelse
+ dup null eq
+ { %**** HANDLE NOTDEF
+ }
+ if
+ 1 index exch .type42execchar
+ }
+ { 1 index exch .type42execchar
+ }
+ ifelse
+ 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.
+
+/CIDFont /Generic /Category findresource dup length dict .copydict
+dup /InstanceType /dicttype put
+dup /DefineResource {
+ dup /CIDFontType get dup 9 add /FontType exch 3 index 3 1 roll put
+ //.definecidfont exch get exec
+ /Generic /Category findresource /DefineResource get exec
+} put
+/Category defineresource pop
+
+currentdict /.definecidfont undef
+
+% 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