summaryrefslogtreecommitdiff
path: root/Master/xemtex/gslib/gs_cidcm.ps
diff options
context:
space:
mode:
Diffstat (limited to 'Master/xemtex/gslib/gs_cidcm.ps')
-rw-r--r--Master/xemtex/gslib/gs_cidcm.ps511
1 files changed, 511 insertions, 0 deletions
diff --git a/Master/xemtex/gslib/gs_cidcm.ps b/Master/xemtex/gslib/gs_cidcm.ps
new file mode 100644
index 00000000000..b965e5cbe33
--- /dev/null
+++ b/Master/xemtex/gslib/gs_cidcm.ps
@@ -0,0 +1,511 @@
+% Copyright (C) 2000 artofcode LLC. All rights reserved.
+%
+% This program is free software; you can redistribute it and/or modify it
+% under the terms of the GNU General Public License as published by the
+% Free Software Foundation; either version 2 of the License, or (at your
+% option) any later version.
+%
+% This program is distributed in the hope that it will be useful, but
+% WITHOUT ANY WARRANTY; without even the implied warranty of
+% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+% Public License for more details.
+%
+% You should have received a copy of the GNU General Public License along
+% with this program; if not, write to the Free Software Foundation, Inc.,
+% 59 Temple Place, Suite 330, Boston, MA, 02111-1307.
+
+% $Id: gs_cidcm.ps,v 1.5.2.2.2.1 2003/04/12 14:02:38 giles Exp $
+% Extending Font resource category with CIDFont-CMap fonts.
+
+languagelevel 2 .setlanguagelevel currentglobal true setglobal
+
+
+% In the comments below, 'CSI' is an abbreviation/acronym for CIDSystemInfo.
+% We pre-scan resource files to retrieve the CSI from them.
+% First we define a hidden procset .prs_dict containing
+% necessary variables and procedures.
+% Then we redefine the old /Font category using this procset.
+
+% We maintain internal caches for the CSI values retrieved from
+% resource files. This supposes that document doesn't uninstall
+% resource files. To disable caching, set enable_cache to false.
+
+% We suppose that names starting with '.prs' do not appear in resource files.
+% If this causes any problem, this prefix should be systematically changed
+% in this file. ('prs' is an abbreviation for 'prescan'.)
+
+25 dict begin
+
+% Define local variables :
+
+/.prs_dict currentdict def % self-reference (constant)
+/.prs_empty 0 dict readonly def
+/path_buffer 255 string def
+/name_buffer 255 string def
+/minus (-) 0 get def % character code constant for '-'
+/period (.) 0 get def % character code constant for '.'
+/CMap 10 dict def % CSI cache for CMaps
+/CIDFont 10 dict def % CSI cache for CIDFonts
+/enable_cache true def % set false to disable cache
+
+% The folloving variables are just placeholders for ones to be set
+% dynamically :
+/.prsFile 0 def % file to prescan
+/.prsResult 0 def % result of prescan
+/.prsDictCount 0 def % save the dictionary stack depth
+
+% Define a dummy CIDInit procset to use while pre-scanning :
+
+/DummyCIDInit 15 dict
+begin
+
+ /begincmap {} def
+ /usecmap {pop} bind def
+
+ {stop} bind
+ [ /begincodespacerange /endcodespacerange /beginnotdefchar /endnotdefchar
+ /beginnotdefrange /endnotdefrange /begincidchar /endcidchar /begincidrange
+ /endcidrange /endcmap /usefont /StartData
+ ] {
+ 1 index def
+ } bind forall
+ pop
+
+currentdict end def
+
+% Define a local 'findresource' for pre-scanning :
+% (it returns the dummy CIDInit instead of the regular CIDInit ProcSet)
+
+/findresource { % <InstName> <CatName> findresource <inst>
+ 2 copy /ProcSet eq exch % /InstName /CatName bool /InstName
+ /CIDInit eq and {
+ pop pop //DummyCIDInit
+ } {
+ //findresource exec
+ } ifelse
+} bind def
+
+% Define procedures for pre-scanning :
+
+/StopIfCSIDefined { % - StopIfCSIDefined -
+
+ % Check if the dictionary stack contains a dictionary containing /CIDSystemInfo.
+ % The search is limited to the top .prsDictCount dictionaries in the stack.
+ % If so, retrieve the CSI, and execute stop to terminate the pre-scanning of the file.
+ % Otherwise, do nothing, so the pre-scanning continues.
+
+ countdictstack //.prs_dict /.prsDictCount get sub dup {
+ currentdict /CIDSystemInfo .knownget {
+ //.prs_dict exch /.prsResult exch put
+ stop
+ } if
+ currentdict exch end
+ } repeat {
+ begin
+ } repeat
+} bind def
+
+/PrescanFile { % - PrescanFile -
+ { //.prs_dict /.prsFile get token {
+ dup type % token type
+ dup /nametype eq exch /operatortype eq or {
+ dup xcheck {
+ exec
+ //StopIfCSIDefined exec
+ } if
+ } if
+ } {
+ stop
+ } ifelse
+ } loop
+} bind odef
+
+/GetCIDSystemInfoFromFile { % <file> GetCIDSystemInfoFromFile <CSI>
+
+ % This procedure reads resource files with 'token',
+ % executing the tokens untill /CIDSystemInfo appears to be defined.
+ % Normally the resource file creates a new dictionary on
+ % dictionary stack and defines /CIDSystemInfo in it.
+ %
+ % Returns an empty dictionary if no CIDSystemInfo is found.
+
+ //.prs_dict begin
+ /.prsFile exch def
+ /.prsResult //.prs_empty def
+ /.prsDictCount countdictstack def
+ { //PrescanFile } stopped pop
+ //.prs_dict /.prsResult get
+ end
+} bind def
+
+/GetCIDSystemInfo { % <InstName> <CatName> GetCIDSystemInfo <CSI>
+
+ % Retrieve CSI, using caches.
+
+ 2 copy resourcestatus {
+ pop 2 lt {
+ findresource /CIDSystemInfo .knownget not {
+ //.prs_empty
+ } if
+ } {
+ dup //.prs_dict exch get % /InstName /CatName CSIs
+ dup 3 index known
+ //enable_cache and {
+ exch pop exch get % CSI
+ } {
+ 3 1 roll % CSIs /InstName /CatName
+ /Category findresource begin % CSIs /InstName
+ dup //path_buffer ResourceFileName % CSIs /InstName (path)
+ end
+ currentglobal exch true setglobal % CSIs /InstName g
+ mark exch % CSIs /InstName g [ (path)
+ { (r) file % CSIs /InstName g [ file
+ //GetCIDSystemInfoFromFile exec % CSIs /InstName g [ CSI
+ } stopped {
+ % Cannot find file from Resource directory
+ cleartomark
+ % Try to find file from CIDFontmap
+ % Stack: CSIs /InstName g
+ 1 index dup .CIDFontmapKnownget {
+ % Stack: CSIs /InstName g /InstName ValueInCIDFontmap
+ % We do look at CIDFontmap in global space.
+ % (When stopped, the space is set to local.)
+ true setglobal
+ 1 index 3 1 roll
+ .CIDFontmapRunHandler
+ /CIDFont findresource /CIDSystemInfo get
+ } {
+ pop //.prs_empty
+ } ifelse
+ } {
+ exch pop
+ } ifelse % CSIs /InstName g CSI
+ exch setglobal % CSIs /InstName CSI
+ dup 4 1 roll % CSI CSIs /InstName CSI
+ put % CSI
+ } ifelse
+ } ifelse
+ } {
+ pop pop //.prs_empty
+ } ifelse
+} bind def
+
+/IsCompatibleCSI { % <CSI-M> <CSI-F> IsCompatibleCSI <bool>
+
+ % The CSI in a CIDFont may be an array, a dict, or null.
+ % If it is an array, it must be of 1 element, which is a dict.
+ % In this case the dict is used for testing the compatibility.
+ % Two dicts are compatible iff they contain same /Ordering and /Registry.
+
+ exch % CSI-F CSI-M
+ { dup type /arraytype eq {
+ dup length 1 ne {
+ pop pop false exit
+ } if
+ 0 get
+ } if % CSI-F CSI-M
+ dup type /dicttype ne {
+ pop pop false exit
+ } if % CSI-F <<CSI-M>>
+ exch % <<CSI-M>> CSI-F
+ dup type /dicttype ne {
+ pop pop false exit
+ } if % <<CSI-M>> <<CSI-F>>
+ true % <<CSI-M>> <<CSI-F>> bEQ
+ [/Registry /Ordering] {
+ 2 index 1 index .knownget not {
+ 1234567
+ } if % <<CSI-M>> <<CSI-F>> bEQ /key vF
+ exch % <<CSI-M>> <<CSI-F>> bEQ vF /key
+ 4 index exch .knownget not {
+ 7654321
+ } if % <<CSI-M>> <<CSI-F>> bEQ vF vM
+ eq and % <<CSI-M>> <<CSI-F>> bEQ
+ } forall
+ exch pop exch pop % bEQ
+ exit
+ } loop
+} bind def
+
+/IsComposedOK { % <CIDFontName> <CMapName> IsComposedOK <bool>
+
+ % Check if the given CIDFont and CMap have compatible CSIs.
+
+ exch % /CMapName /CIDFontName
+ /CIDFont //GetCIDSystemInfo exec % /CMapName CSI-F
+ dup type /dicttype eq {
+ dup length 0 ne {
+ exch % CSI-F /CMapName
+ /CMap //GetCIDSystemInfo exec % CSI-F CSI-M
+ //IsCompatibleCSI exec % bool
+ } {
+ pop pop false
+ } ifelse
+ } {
+ pop pop false
+ } ifelse
+} bind def
+
+/IsComposedFont { % <FontName> IsComposedFont <CIDFontName> <CMapName> true
+ % <FontName> IsComposedFont false
+
+ % Check if the given font name may be decomposed into CIDFont.CMap, CIDFont-CMap
+ % or into CIDFont--CMap, such that CIDFont and CMap have compatible CSIs.
+ % FontName
+ dup type /stringtype ne {
+ //name_buffer cvs
+ } if % (FontName)
+ { dup length 2 sub -1 1 {
+ % (FontName) i
+ 2 copy get dup //minus eq exch //period eq or {
+ 2 copy 2 copy % (FontName) i (FontName) i (FontName) i
+ 2 copy get //minus eq {
+ 2 copy 1 sub get //minus eq {
+ 1 sub
+ } if
+ } if % (FontName) i (FontName) i (FontName) i0
+ 0 exch getinterval cvn % (FontName) i (FontName) i /CIDFontName
+ 3 1 roll % (FontName) i /CIDFontName (FontName) i
+ 1 add dup % (FontName) i /CIDFontName (FontName) i1 i1
+ 5 index length % (FontName) i /CIDFontName (FontName) i1 i1 l
+ exch sub getinterval cvn % (FontName) i /CIDFontName /CMapName
+ 2 copy //IsComposedOK exec { % (FontName) i /CIDFontName /CMapName
+ 4 2 roll pop pop % /CIDFontName /CMapName
+ stop
+ } if
+ pop pop pop
+ } {
+ pop
+ } ifelse % (FontName)
+ } for
+ pop
+ } stopped
+} bind def
+
+/ComposeName { % <CIDFont> <CMap> <scr> ComposeName <CIDFont-CMap>
+ dup dup 5 2 roll % (scr) (scr) /CIDFont /CMap (scr)
+ 3 2 roll exch cvs length dup % (scr) (scr) /CMap l0 l0
+ 4 -1 roll exch //minus put % (scr) /CMap l0
+ 1 add dup % (scr) /CMap l1 l1
+ 3 index dup length % (scr) /CMap l1 l1 (scr) L
+ 2 index sub % (scr) /CMap l1 l1 (scr) LT
+ 3 2 roll % (scr) /CMap l1 (scr) LT l1
+ exch getinterval % (scr) /CMap l1 (scrT)
+ 3 2 roll exch cvs length % (scr) l1 l2
+ add 0 exch getinterval % (CIDFont-CMap)
+} bind def
+
+
+% Define a few procedure templates to be modified dynamically :
+
+currentpacking false setpacking
+
+/BindAux { % <proc> BindAux <proc>
+ 0 exec
+} bind def
+
+/EnumerateFontNames { % - EnumerateFontNames ...
+
+ % This is a pattern for enumeration procedure to be built dynamically,
+ % using Bind with a temporary dictionary.
+ % The following names will be replaced with specific objects
+ % during Bind : en_local_dict, scr, proc, Fonts, Category .
+
+ end % Category
+ {
+ 0 1 2 {
+ en_local_dict exch /status exch put
+ Fonts {
+ en_local_dict /status get eq {
+ scr cvs % ... (Font)
+ proc exec %
+ } {
+ pop
+ } ifelse % ...
+ } forall
+ } for % ...
+ } stopped
+ Category begin
+ { stop } if
+} bind def
+
+setpacking
+
+/Bind { % <proc> Bind <proc>
+
+ % Make a copy of the given procedure, binding in the values of all names
+ % defined in currentdict.
+ % Caution : this code cannot handle procedures that were already
+ % bound recursively.
+
+ dup length array copy
+ dup length 1 sub -1 0 {
+ 2 copy get % {precopy} i {elem}
+ dup dup type /arraytype eq exch xcheck and {
+ % {precopy} i {elem}
+ //BindAux exec % {precopy} i {elem_copy}
+ 2 index 3 1 roll put % {precopy}
+ } {
+ dup dup type /nametype eq exch xcheck and {
+ % {precopy} i {elem}
+ currentdict exch .knownget {
+ 2 index 3 1 roll put % {precopy}
+ } {
+ pop
+ } ifelse
+ } {
+ pop pop
+ } ifelse
+ } ifelse % {precopy}
+ } for % {copy}
+ cvx
+} bind def
+
+//BindAux 0 //Bind put % bind the recursive call in 'Bind'.
+
+
+
+% Redefine the /Font category with CIDFont-CMap construction :
+
+% The following code supposes that the following names are not
+% defined in the old /Font category dictionary :
+% /IsComposedFont, /Bind, /IsComposedOK, /EnumerateFontNames .
+
+
+/Font /Category findresource dup length dict copy begin
+
+/FindResource { % <InstName> FindResource <inst>
+ dup //ResourceStatus exec {
+ pop pop //FindResource exec
+ } {
+ dup //IsComposedFont exec { % /FontName /CIDFontName /CMapName
+ exch [ exch ] composefont % inst
+ } {
+ //FindResource exec
+ } ifelse
+ } ifelse
+} bind def
+
+/ResourceStatus { % <InstName> ResourceStatus <nStatus> <nSize> true
+ % <InstName> ResourceStatus false
+ dup //ResourceStatus exec {
+ 3 2 roll pop true % nStatus nSize true
+ } {
+ //IsComposedFont exec { % /CIDFontName /CMapName
+ /CMap resourcestatus { % /CIDFontName nStatusM nSizeM
+ exch pop exch % nSizeM /CIDFontName
+ /CIDFont resourcestatus { % nSizeM nStatusF nSizeF
+ exch pop % nSizeF nSizeM
+ dup 0 ge {
+ exch dup 0 ge {
+ add
+ } {
+ exch pop
+ } ifelse
+ } {
+ pop
+ } ifelse % nSize
+ 2 exch true % nStatus nSize true
+ } {
+ pop pop pop false % work around buggy resource file
+ } ifelse
+ } {
+ pop pop pop false % work around buggy resource file
+ } ifelse
+ } {
+ false
+ } ifelse
+ } ifelse
+} bind def
+
+/ResourceForAll { % <template> <proc> <scratch> ResourceForAll -
+
+ % We suppose that the resourceforall procedure does not
+ % define or install new fonts, CMaps, and/or CIDFonts.
+
+ % First we create 3 temporary dictionaries to store temporary data
+ % about fonts, CMaps and CIDFonts.
+ % These dictionaries must be created dynamically, to allow for a possible
+ % recursive call to resourceforall from the resourceforall procedure.
+
+ currentglobal false setglobal
+ 20 dict 20 dict 20 dict
+ 4 -1 roll setglobal % (templ) proc (scr) <<CIDFont>> <<CMap>> <<Fonts>>
+
+ % Store resource names into local dictionaries :
+
+ 5 index [ 2 index {exch cvn dup put} aload pop ] cvx 5 index //ResourceForAll exec
+ (*) [ 3 index {exch cvn dup put} aload pop ] cvx 5 index /CMap resourceforall
+ (*) [ 4 index {exch cvn dup put} aload pop ] cvx 5 index /CIDFont resourceforall
+
+ %% Make the list of fonts in the form (/Name status) :
+
+ % (templ) proc (scr) <<CIDFont>> <<CMap>> <<Fonts>>
+ dup {
+ //ResourceStatus exec {
+ pop 2 index % (templ) proc (scr) <<CIDFont>> <<CMap>> <<Fonts>> /Name nStatus <<Font>>
+ 3 1 roll put % (templ) proc (scr) <<CIDFont>> <<CMap>> <<Fonts>>
+ } {
+ pop
+ } ifelse
+ } forall % (templ) proc (scr) <<CIDFont>> <<CMap>> <<Fonts>>
+
+ %% Add CIDFont-CMap to it (filtering duplicates) :
+
+ 3 2 roll {
+ 3 index {
+ 3 1 roll % (templ) proc (scr) <<CMap>> <<Font>> /CIDFont /CMap /CIDFont /CMap
+ 6 index //ComposeName exec % (templ) proc (scr) <<CMap>> <<Font>> /CIDFont /CMap (Font)
+ dup 8 index .stringmatch {
+ cvn % (templ) proc (scr) <<CMap>> <<Font>> /CIDFont /CMap /Font
+ dup 4 index exch known {
+ pop pop
+ } {
+ 2 index % (templ) proc (scr) <<CMap>> <<Font>> /CIDFont /CMap /Font /CIDFont
+ 4 2 roll % (templ) proc (scr) <<CMap>> <<Font>> /Font /CIDFont /CIDFont /CMap
+ //IsComposedOK exec {
+ exch 2 index exch 2 put % (templ) proc (scr) <<CMap>> <<Font>> /CIDFont
+ } {
+ exch pop
+ } ifelse
+ } ifelse
+ } {
+ pop pop
+ } ifelse
+ dup % (templ) proc (scr) <<CMap>> <<Font>> /CIDFont /CIDFont
+ } forall
+ pop pop % (templ) proc (scr) <<CMap>> <<Font>>
+ } forall % (templ) proc (scr) <<CMap>> <<Font>>
+ exch pop % (templ) proc (scr) <<Font>>
+
+ % Build the enumeration procedure :
+
+ % Since the resourceforall procedure may leave values on the operand stack,
+ % we cannot simply store the enumerator's local data on the stack.
+ % We also cannot use a static dictionary to store local variables,
+ % because of possible recursion in the resourceforall procedure.
+ % To work around this, we create a copy of the enumeration procedure and
+ % bind it dynamically with a temporary dictionary, which contains
+ % local variables for the currently executing instance of resourceforall.
+
+ currentdict
+ 6 dict begin % the temporary dictionary
+ /Category exch def
+ /Fonts exch def
+ /scr exch def
+ /proc exch def
+ /en_local_dict currentdict def
+ //EnumerateFontNames //Bind exec % (templ) Enumerator
+ /status 0 def % variable for the current status to enumerate - do not Bind with it !
+ end
+ exch pop % Enumerator
+
+ % Do the enumeration :
+
+ exec
+} bind def
+
+
+currentdict end /Font exch /Category defineresource pop
+end
+setglobal .setlanguagelevel