123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444 |
- % Copyright (C) 2000 artofcode LLC. 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_cidcm.ps,v 1.12 2004/10/25 15:11:37 igor 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 assume 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 8192 string def
- /name_buffer 1024 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.
- RESMPDEBUG { (cidcm GetCIDSystemInfoFromFile beg) = } if
- //.prs_dict begin
- /.prsFile exch def
- /.prsResult //.prs_empty def
- /.prsDictCount countdictstack def
- RESMPDEBUG { (cidcm GetCIDSystemInfoFromFile will PrescanFile.) = } if
- { //PrescanFile } stopped pop
- //.prs_dict /.prsResult get
- end
- RESMPDEBUG { (cidcm GetCIDSystemInfoFromFile end) = } if
- } bind def
- /GetCIDSystemInfo { % <InstName> <CatName> GetCIDSystemInfo <CSI>
-
- % Retrieve CSI, using caches.
- RESMPDEBUG { (cidcm GetCIDSystemInfo beg) = } if
- /Category findresource begin % /InstName
- dup ResourceStatus
- {
- pop 2 lt {
- FindResource /CIDSystemInfo .knownget not {
- //.prs_empty
- } if % CSI
- } { % /InstName
- currentdict /GetCIDSystemInfoFromMap .knownget {
- exec
- } if
- dup type /nametype eq
- {
- RESMPDEBUG { (cidcm GetCIDSystemInfo got a name.) = } if
- //.prs_dict Category get % /InstName CSIs
- dup 2 index known
- //enable_cache and {
- RESMPDEBUG { (cidcm GetCIDSystemInfo from cache.) = } if
- exch get % CSI
- } {
- RESMPDEBUG { (cidcm GetCIDSystemInfo from file.) = } if
- exch % CSIs /InstName
- dup //path_buffer ResourceFileName % CSIs /InstName (path)
- RESMPDEBUG { (cidcm GetCIDSystemInfo from file ) print dup = } if
- currentglobal exch true setglobal % CSIs /InstName g (path)
- mark exch % CSIs /InstName g [ (path)
- { (r) file % CSIs /InstName g [ file
- //GetCIDSystemInfoFromFile exec % CSIs /InstName g [ CSI
- } stopped {
- cleartomark //.prs_empty
- } {
- exch pop
- } ifelse % CSIs /InstName g CSI
- exch setglobal % CSIs /InstName CSI
- dup 4 1 roll % CSI CSIs /InstName CSI
- put % CSI
- RESMPDEBUG {
- (cidcm GetCIDSystemInfo got from file : <<) print
- dup { exch //=string cvs print ( ) print
- //=string cvs print ( ) print
- } forall
- (>>) =
- } if
- } ifelse
- } if
- } ifelse
- } {
- pop //.prs_empty
- } ifelse
- end
- RESMPDEBUG { (cidcm GetCIDSystemInfo end) = } if
- } 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
- /IsWellComposed { % <CIDFontName> <CMapName> IsWellComposed <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 //IsWellComposed 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
- % 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, /IsWellComposed .
- /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 identifiers into local dictionaries
- % A resource instance can have a key that is not a name or a string. In this
- % case, resourceforall passes the key directly to proc instead of copying it
- % into the scratch string. This case can arise only for a resource instance
- % defined in virtual memory by a previous defineresource
- % Discard non-string keys of CIDFont and CMap because <CIDFontName>- -<CMapName>
- % is only defined for names.
- { /.DisableResourceOrdering pop % gs_resmp accesses this through execstack - don't remove !
- 5 index [ 2 index {exch //null put} aload pop ] cvx bind 5 index //ResourceForAll exec
- (*) [ 3 index {exch dup type /stringtype eq { cvn dup put } { pop pop } ifelse } aload pop
- ] cvx bind 5 index /CMap resourceforall
- (*) [ 4 index {exch dup type /stringtype eq { cvn dup put } { pop pop } ifelse } aload pop
- ] cvx bind 5 index /CIDFont resourceforall
- exit
- } loop % This loop is a pattern for execstack_lookup - don't remove !
- %% Make the list of fonts in the form (/Name status) :
- % (templ) proc (scr) <<CIDFont>> <<CMap>> <<Fonts>>
- dup {
- pop 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
- //IsWellComposed 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>>
- 4 3 roll pop % proc (scr) <<Font>>
- % Make the enumerator and apply it :
- /MappedCategoryRedefiner /ProcSet findresource /MakeResourceEnumerator get exec exec
- } bind def
- currentdict end /Font exch /Category defineresource pop
- end
- setglobal .setlanguagelevel
|