% Copyright (C) 2000 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. % % 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_fapi.ps 8022 2007-06-05 22:23:38Z giles $ % Redefine Font and CIDFont categories with FAPI-handeled fonts. systemdict /.FAPIavailable known { .FAPIavailable } { false } ifelse not { (%END FAPI) .skipeof } if languagelevel 2 .setlanguagelevel %==================================================================== % Redefine Font category with FAPIfontmap and CIDFont with FAPIfontmap : 15 dict begin % a temporary dictionary for local binding. /EmbedFontObjectsQuery mark /.EmbedFontObjects 0 .dicttomark def /is_device_compatible_to_FAPI % - is_device_compatible_to_FAPI { currentdevice //EmbedFontObjectsQuery .getdeviceparams % ... dup mark eq { pop true } { exch pop exch pop 0 eq } ifelse % The code above assumes that only the requested parameter is rendered. % The commented-out code below may be useful for general case. % Keeping it for a while. % counttomark 2 idiv { % exch /.EmbedFontObjects eq { % counttomark 1 add 1 roll cleartomark % 0 eq exit % } if % } repeat % dup mark eq { % pop true % } if } bind def %----------------------------- Process FAPIconfig ----------------------- /Config << systemdict /FAPIconfig known {/FAPIconfig .systemvar} {(FAPIconfig)} ifelse .runlibfile /ServerOptions 2 dict >> def systemdict /.FAPIconfig //Config put () systemdict /UFST_SSdir .knownget { (UFST_SSdir=) exch concatstrings concatstrings } if systemdict /UFST_PlugIn .knownget { 1 index length 0 ne { exch .filenamelistseparator concatstrings exch } if (UFST_PlugIn=) exch concatstrings concatstrings } if dup length 0 ne { //Config /ServerOptions get exch /UFST exch put } { pop } ifelse %------------------Copy the FontEmulationProcs here : ------------------- /FontEmulationProcs /ProcSet findresource { def } forall currentdict /super.complete_instance currentdict /complete_instance get put %-----------FAPI-specific methods for category redefinition : ----------- /RefinePath % /key RefinePath { exch begin //Config exch get /Path exch Path false .file_name_combine not { exch (Can't combine paths ) print print ( and ) print = /RefinePath cvx /configurationerror signalerror } if def currentdict end } bind def /complete_instance % complete_FAPI_Font { //super.complete_instance exec dup /CIDFontName known { /CIDFontPath } { /FontPath } ifelse //RefinePath exec } bind def /IsMyRecord % -> bool { dup type /dicttype eq { dup /FAPI known } { false } ifelse } bind def /IsActive % IsActive { pop //is_device_compatible_to_FAPI exec } bind def /FontRecordVirtualMethods //RecordVirtualMethodsStub dup length 2 add dict copy begin /IsActive //IsActive def /MakeInstance % MakeInstance { currentglobal 3 1 roll true setglobal //FontOptions //complete_instance exec 2 copy //GetSize exec 4 3 roll setglobal } bind def currentdict end def /CIDFontRecordVirtualMethods //RecordVirtualMethodsStub dup length 3 add dict copy begin /GetCSI //TranslateCSI def /IsActive //IsActive def /MakeInstance % MakeInstance { currentglobal 3 1 roll true setglobal //CIDFontOptions //complete_instance exec 2 copy //GetSize exec 4 3 roll setglobal } bind def currentdict end def /ReadFCOfontmap: % ReadFCOfontmap: name dict ... { /fontfile exch def { currentfile =string readline not { pop exit } if dup length 0 ne { 0 () /SubFileDecode filter dup token not { % A comment line closefile } { dup /EndFCOfontmap cvx eq { pop closefile exit } if exch dup token not { /ReadFCOfontmap: cvx /rangecheck signalerror } if exch dup token not { /StandardEncoding } { dup type /nametype ne { /ReadFCOfontmap: cvx /rangecheck signalerror } if } ifelse findencoding exch dup token not { null } { dup type /nametype ne { /ReadFCOfontmap: cvx /rangecheck signalerror } if /Decoding findresource } ifelse exch closefile % index name enc dec|null 4 3 roll % name enc dec|null index << /Path fontfile /FontType 1 /FAPI /UFST /SubfontId counttomark 2 add -1 roll /Decoding counttomark 2 add -1 roll dup null eq { pop pop } if /Encoding counttomark 2 add -1 roll >> % dup { exch == = } forall } ifelse } { pop } ifelse } loop currentdict /fontfile undef } bind def %----------------------------------The Redefintion--------------------- /MappedCategoryRedefiner /ProcSet findresource /Redefine get /Redefine exch def % Redefine the /Font category : 4 dict begin /CategoryName /Font def /MapFileName systemdict /FAPIfontmap known {/FAPIfontmap .systemvar} {(FAPIfontmap)} ifelse def /VerifyMap { pop } bind def /PreprocessRecord % PreprocessRecord { //IsMyRecord exec dup { pop dup /RecordVirtualMethods //FontRecordVirtualMethods put true } if } bind def currentdict end Redefine % Redefine the /CIDFont category : 4 dict begin /CategoryName /CIDFont def /MapFileName systemdict /FAPIcidfmap known {/FAPIcidfmap .systemvar} {(FAPIcidfmap)} ifelse def /VerifyMap { pop } bind def /PreprocessRecord % PreprocessRecord { //IsMyRecord exec dup { pop dup /RecordVirtualMethods //CIDFontRecordVirtualMethods put true } if } bind def currentdict end Redefine %==================== A hook for buildfont* operators ==================== % The procedure .FAPIhook redirects PS fonts to FAPI on necessity. % This depends on the following conditions : % % 1. If font dictionary has /FAPI entry, it is a font listed in FAPIconfig.FontPath, % and must be build with .FAPIrebuildfont, or a copy of a font, which was % built with .FAPIrebuildfont . % % 2. If the font dictionary has /PathLoad entry, and has no /FAPI entry, % it is an installed PS font, which is described in lib/fontmap or % in GS_FONTPATH. .loadfont inserts /PathLoad entry for this case % (see gs_fonts.ps). % % Installed fonts are being loaded with GS font loader, % the they are passed to FAPI is same way as embedded fonts are. % We do so because UFST cannot read fonts, which don't % follow Type 1/42 file format strongly. % % 3. Executing .loadfont, we place /FAPI_hook_disable in the 0th % element of some procedure on the execution stack - see gs_fonts.ps . % If FAPI_hook finds /FAPI_hook_disable in there, % it knows that it is called for a disk font during % its internal definefont. % % 4. If font dictionary has no /FAPI entry, and has no /Path entry, % and if we are not in .loadfont context, it is an embedded font. % % 5. Two entries to be defined in lib/FAPIconfig to control the hooking of PS fonts : % HookDiskFonts and HookEmbeddedFonts . % They specify arrays of font types (integers) to be redirected with FAPI. % HookDiskFonts controls disk PS fonts (which fall into (2) and (3) ). % HookEmbeddedFonts controls fonts being embedded into documents. % % 7. We apply the operator .passtoFAPI for checking whether FAPI can handle a font. % If so, we insert /FAPI entry into the font dictionary and convert it % with .FAPIrebuildfont . Otherwise the font is handled with the native GS font renderer. /FAPI_hook_debug % FAPI_hook_debug - FAPIDEBUG { {exec} } { {pop} } ifelse bind def /FAPI_hook_warn % FAPI_hook_debug - QUIET { {pop} } { {exec} } ifelse bind def /FAPI_is_hook_disabled % - FAPI_is_hook_disabled { % checks whether execution stack contains packedarray started with /FAPI_hook_disable . /FAPI_hook_disable /MappedCategoryRedefiner /ProcSet findresource /execstack_lookup get exec null ne } bind def /FAPIhook_aux % .FAPIhook { % name <> { (FAPIhook ) print 1 index = } //FAPI_hook_debug exec dup /FAPI known { { //PrintFontRef exec ( is mapped to FAPI=) print dup /FAPI get = } //FAPI_hook_warn exec true //.FAPIrebuildfont //ChooseDecoding exec } { dup /PathLoad known dup { { (PathLoad known for the font ) print //PrintFontRef exec (.) = } //FAPI_hook_debug exec } { pop //FAPI_is_hook_disabled exec dup { pop { (FAPIhook is in .loadfont context for the font ) print //PrintFontRef exec (.) = } //FAPI_hook_debug exec true } if } ifelse { /HookDiskFonts } { /HookEmbeddedFonts } ifelse //Config exch get % name <> [types] 1 index //GetFontType exec //FindInArray exec % name <> bHook { { (Trying to render the font ) print //PrintFontRef exec ( with FAPI...) = } //FAPI_hook_debug exec //.FAPIpassfont { { //PrintFontRef exec ( is being rendered with FAPI=) print dup /FAPI get = } //FAPI_hook_warn exec false //.FAPIrebuildfont //ChooseDecoding exec } { { (Can't render ) print //PrintFontRef exec ( with FAPI, will do with native GS renderer.) = } //FAPI_hook_warn exec } ifelse } { { (The font ) print //PrintFontRef exec ( doesn't need to render with FAPI.) = } //FAPI_hook_debug exec } ifelse } ifelse } bind def /FAPIhook % .FAPIhook { //is_device_compatible_to_FAPI exec { //FAPIhook_aux exec } { { (FAPIhook is disabled for the current device.) = } //FAPI_hook_debug exec } ifelse } bind def % ------------------ Redefine .buildfont* with FAPI : ----------------------- /.buildfont1 { //.buildfont1 exec //FAPIhook exec } bind % 'odef' is below. /.buildfont2 { //.buildfont2 exec //FAPIhook exec } bind % 'odef' is below. /.buildfont42 { //.buildfont42 exec //FAPIhook exec } bind % 'odef' is below. /.buildfont9 { //.buildfont9 exec //FAPIhook exec } bind % 'odef' is below. /.buildfont10 { //.buildfont10 exec //FAPIhook exec } bind % 'odef' is below. /.buildfont11 { //.buildfont11 exec //FAPIhook exec } bind % 'odef' is below. end % the temporary dictionary for local binding. odef odef odef odef odef odef .setlanguagelevel %END FAPI