|
|
% Copyright (C) 2001-2023 Artifex Software, Inc.
% 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.
%
% Refer to licensing information at http://www.artifex.com or contact
% Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
% CA 94129, USA, for further information.
%
% 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.
/.checkfonttype { % <cidfont> <fonttype> .checkfonttype <cidfont> <new?>
1 index /FID known { 1 index /FontType get ne { /definefont cvx /invalidfont signalerror } if //false } { 1 index /FontType 3 -1 roll put //true } ifelse} .internalbind def
/.cidfonttypes where { pop } { /.cidfonttypes 6 dict def } ifelse.cidfonttypes
30 dict begin
/.gcompatstringcopy % <string> <global> .gcompatstringcopy <string>
{ dup 2 index gcheck eq { pop } { currentglobal 3 1 roll setglobal dup length string copy exch setglobal } ifelse} .internalbind def
% 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.
% ------ CIDFontType 0 (FontType 9) ------ %
% We add the following entries to the CIDFont dictionary, in addition to
% the ones documented by Adobe:
% SubrCache - dictionary for caching Subr arrays
% For CIDFonts where we read the data from disk incrementally:
% GlyphData is 0 (arbitrary)
% DataSource - a ReusableStreamDecode filter for the data
% We also add a FID entry, and possibly a Subrs entry, to each element of
% FDArray.
dup 0 { 9 //.checkfonttype exec { /CIDInit /ProcSet findresource begin .completefont9 end } if 1 index exch .buildfont9 .currentresourcefile dup type /filetype eq { //.filename {1 index gcheck //.gcompatstringcopy exec 1 index exch /ResourcePath exch put} if }{ pop} ifelse exch pop} put % Don't bind it here, because gs_fapi.ps redefines .buildfont9
% Add entries to a new CIDFontType 0 font per documentation (FontMatrix)
% or for .buildfont9 (FDArray.Private.Subrs).
/.completefont9 { % <cidfont0> .completefont9 <cidfont0>
currentglobal 3 1 roll dup gcheck setglobal dup /FontMatrix known { dup /FDArray get { dup /FontMatrix get 0 get 1000000 ge { /FontMatrix matrix put % Bug 688517
} { pop } ifelse } forall } { dup /FontMatrix [0.001 0 0 0.001 0 0] put dup /FDArray get { currentglobal exch dup gcheck setglobal dup /FontMatrix get {1000 0 0 1000 0 0} matrix concatmatrix /FontMatrix exch put setglobal } forall } ifelse dup /FDArray get { % Read the Subrs if necessary.
dup /Private get dup /Subrs known not { dup /SubrCount .knownget { % Stack: font Private SubrCount
currentglobal 3 1 roll 1 index gcheck setglobal array 1 index /Subrs 3 -1 roll put % Stack: font global Private
2 index begin begin .loadsubrs end end setglobal } { pop } ifelse readonly pop } { pop pop } ifelse } forall 3 -1 roll setglobal} .internalbind def
% 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} .internalbind 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 { Subrs length 0 ne { SubrCache SubrMapOffset .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 SubrMapOffset 2 index put } if } { % We haven't loaded any Subrs at this offset yet.
SubrCount array 0 .readsubrs SubrCache SubrMapOffset 2 index put } ifelse Subrs copy pop } if} .internalbind def
% ------ CIDFontType 1 (FontType 10) ------ %
dup 1 { 10 //.checkfonttype exec pop 1 index exch .buildfont10 .currentresourcefile dup type /filetype eq { //.filename {1 index gcheck //.gcompatstringcopy exec 1 index exch /ResourcePath exch put} if }{ pop} ifelse exch pop} put % Don't bind it here because gs_fapi.ps redefines .buildfont10
% ------ CIDFontType 2 (FontType 11) ------ %
dup 2 { 11 //.checkfonttype exec pop 1 index exch .buildfont11 .currentresourcefile dup type /filetype eq { //.filename {1 index gcheck //.gcompatstringcopy exec 1 index exch /ResourcePath exch put} if }{ pop} ifelse exch pop} put % Don't bind it here because gs_fapi.ps redefines .buildfont11
currentdict /.gcompatstringcopy .undef
pop % .cidfonttypes
% ---------------- Reading CIDFontType 0 files ---------------- %
/StartData { % <(Binary)|(Hex)> <datalength> StartData -
% (currentdict is CID font dict)
% If we're loading a resource file and the data format is
% binary, we can just save a pointer to the data and load it
% incrementally.
mark { % Previous versions of this code made provisions for
% reading hex-encoded data incrementally. Since hex data
% doesn't seem to be used in practice, we no longer bother.
2 index (Binary) ne { stop } if currentfile .currentresourcefile ne { stop } if % Hack: the pdfwrite driver relies on finalization to write
% out fonts. However, the font may be finalized after the
% resource file, in which case the resource file will be
% closed. So if the current output device is pdfwrite,
% don't use incremental loading.
/AllowIncrementalCFF /GetDeviceParam .special_op { exch pop {stop}if }if currentfile fileposition } //.internalstopped exec { % File is not positionable, or uses hex data.
% Load the data now.
cleartomark exch currentfile exch (Hex) eq { /ASCIIHexDecode filter } if exch % Stack: file length
dup 65400 le { % readstring with a 0-length string causes a rangecheck,
% but a data length of 0 is allowed.
string dup () ne { 1 index exch readstring pop } if } { mark 3 1 roll { % Stack: mark str ... file length
dup 0 eq { pop exit } if dup 65400 .min dup string 3 index exch readstring pop % Stack: mark str ... file length newstrlen newstr
4 1 roll sub } loop counttomark 1 add 1 roll ] } ifelse /GlyphData exch def dup currentfile eq { pop } { closefile } ifelse } { % File is positionable and binary, just save a pointer.
% Stack: (Binary) length -mark- pos
/GlyphData 0 def exch pop 3 -1 roll pop exch % Stack: pos length
/DataSource currentfile 2 index () .subfiledecode //true .reusablestream def currentfile 3 1 roll add setfileposition } ifelse /SubrCache 10 dict def CIDFontName currentdict /CIDFont defineresource pop end % CID font dict
end % resource category dict
} .internalbind 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
% ------ Generic ------ %
% Read a string at a given offset in a "file" (binary file or
% GlyphData in RAM).
/ReadString { % <pos> <string> ReadString <string>
GlyphData 0 eq { % Read from the file.
DataSource 3 -1 roll setfileposition DataSource exch readstring pop } { % Read from a string or an array of strings.
GlyphData .stringsreadstring } ifelse} .internalbind 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} .internalbind def
% Interpret a byte string as a (big-endian) integer.
/.cvbsi % <bytes> .cvbsi <int>
{ 0 exch { exch 8 bitshift add } forall} .internalbind def
% Read an integer from binary data.
/.readint % <pos> <nbytes> .readint <int>
{ string ReadString .cvbsi} .internalbind def
currentdict end
% ---------------- Rendering ---------------- %
% ------ CIDFontType 0 ------ %
/.readglyphdata { currentfont exch .type9mapcid FDArray exch get exch} .internalbind executeonly def
% BuildGlyph procedure for CIDFontType 0.
% 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 exec dup //null eq { % Substitute CID 0. **** WRONG ****
pop pop 0 //.readglyphdata exec } if % Stack: cidfont cid subfont charstring
dup //null eq { pop pop pop pop } { %**** WRONG ****
4 -1 roll pop 3 1 roll exch dup 4 -1 roll 0 0 moveto 3 index /FontType get 2 eq { .type2execchar } { .type1execchar } ifelse } ifelse %**** WRONG ****
end .setglobal} .internalbind executeonly def
% ------ CIDFontType 2 ------ %
% BuildGlyph procedure for CIDFontType 2.
% The name %Type11BuildGlyph is known to the interpreter.
(%Type11BuildGlyph) cvn { % <cidfont> <cid> %Type11BuildGlyph -
% We must be prepared for out-of-range CIDs.
2 copy { .type11mapcid } //.internalstopped exec { pop /CharStrings get /.notdef get } if % Stack: cidfont cid glyphindex
1 index exch .type42execchar} .internalbind executeonly def
% ---------------- Define resources ---------------- %
languagelevel exch 2 .setlanguagelevel
% Define the CIDInit ProcSet resource.
% The ProcSet dictionary is still on the stack.
% We might have loaded CMap support already. However, Adobe's
% protected font downloader defines a CIDInit ProcSet that will be
% loaded from the filesystem later, so we must check specifically
% for the ProcSet being defined in VM.
/CIDInit /ProcSet 2 copy resourcestatus { pop 0 eq } { //false } ifelse { 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>
systemdict /ProvideUnicode .knownget not { //false } if { /FontEmulationProcs /ProcSet findresource /ProvideUnicodeDecoding get exec } if dup /CIDFontType get //.cidfonttypes exch get exec} .internalbind executeonly odef
/CIDFont /Generic /Category findresource dup length dict .copydictdup /InstanceType /dicttype putdup /DefineResource { dup /OrigFont known not { dup dup /OrigFont exch .growput % CPSI does it. Adding just for CET 33_all.PS conformity.
} if dup /PaintType known not { dup /PaintType 0 .growput % CPSI does it. Adding just for CET 33_all.PS conformity.
} if .buildcidfont /Generic /Category findresource /DefineResource get exec} put% CIDFonts may be defined in CFF OpenType files.
% Check for this here.
/.loadcidfontresource { dup .ResourceFile { {.loadfont} .execasresource } { dup /undefinedresource signalerror } ifelse} .internalbind defdup /.LoadResource { currentglobal { //.loadcidfontresource exec } { //true setglobal {//.loadcidfontresource exec} stopped //false setglobal {stop} if } ifelse} .internalbind 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 .copydictdup /.CheckResource { % Allow a string, an array of strings, or (as of Adobe release 3011)
% a dictionary.
dup type dup dup /stringtype eq exch /dicttype eq or { pop //true } { dup /arraytype eq exch /packedarraytype eq or { //true exch { type /stringtype eq and } forall } { //false } ifelse } ifelse} .internalbind put/Category defineresource pop
.setlanguagelevel
%% Replace 1 (gs_ciddc.ps)
(gs_ciddc.ps) runlibfile
% Undef these, not needed outside this file
[ /.checkfonttype /.loadcidfontresource /.readglyphdata] systemdict .undefinternalnames
|