401 lines · 12.3 KB · Text
RawDownload
%    Copyright (C) 1995, 2000 Aladdin Enterprises.  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_cidfn.ps,v 1.27 2003/05/23 09:57:34 igor 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. /.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} bind def /.cidfonttypes where { pop } { /.cidfonttypes 6 dict def } ifelse.cidfonttypes 30 dict 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. % ------ 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 {    /CIDInit /ProcSet findresource begin    .completefont9    end  } if  1 index exch .buildfont9 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 not {    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  } if  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} bind 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} 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 {  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} bind def % ------ CIDFontType 1 (FontType 10) ------ % dup 1 {  10 .checkfonttype pop  1 index exch .buildfont10 exch pop} put % Don't bind it here because gs_fapi.ps redefines .buildfont10 % ------ CIDFontType 2 (FontType 11) ------ % dup 2 {  11 .checkfonttype pop  1 index exch .buildfont11 exch pop} put % Don't bind it here because gs_fapi.ps redefines .buildfont11 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.    currentdevice .devicename /pdfwrite eq { stop } if    currentfile fileposition  } .internalstopped {		% File is not positionable, or uses hex data.		% Load the data now.    cleartomark exch (Hex) eq      { { currentfile exch readhexstring pop } }      { { currentfile exch readstring pop } }    ifelse exch		% Stack: readproc 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 exec } if    } {      mark 3 1 roll {		% Stack: mark str ... readproc length	dup 0 eq { pop exit } if	dup 65400 .min dup string 3 index exec		% Stack: mark str ... readproc length newstrlen newstr	4 1 roll sub      } loop      counttomark 1 add 1 roll ]    } ifelse    /GlyphData exch def		% If we were reading hex data, skip past the >.    2 get { readhexstring } 0 get eq {      currentfile 0 (>) .subfiledecode dup flushfile closefile    } if  } {		% 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} 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 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} 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 % ------ CIDFontType 0 ------ % /.readglyphdata {  currentfont exch .type9mapcid  FDArray exch get exch} bind 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 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    3 1 roll exch dup 4 -1 roll 0 0 moveto    3 index /FontType get 2 eq { .type2execchar } { .type1execchar } ifelse  } ifelse	%**** WRONG ****  end  .setglobal} bind 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 {    pop /CharStrings get /.notdef get  } if			% Stack: cidfont cid glyphindex  1 index exch .type42execchar} bind 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} odef /CIDFont /Generic /Category findresource dup length dict .copydictdup /InstanceType /dicttype putdup /DefineResource {  .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} bind defdup /.LoadResource {  currentglobal {    .loadcidfontresource  } {    true setglobal {.loadcidfontresource} stopped false setglobal {stop} if  } ifelse} bind 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} bind put/Category defineresource pop .setlanguagelevel %% Replace 1 (gs_ciddc.ps)(gs_ciddc.ps) runlibfile