星火微课系统客户端
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

gs_cidcm.ps 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452
  1. % Copyright (C) 2000 Artifex Software, Inc. All rights reserved.
  2. %
  3. % This software is provided AS-IS with no warranty, either express or
  4. % implied.
  5. %
  6. % This software is distributed under license and may not be copied,
  7. % modified or distributed except as expressly authorized under the terms
  8. % of the license contained in the file LICENSE in this distribution.
  9. %
  10. % For more information about licensing, please refer to
  11. % http://www.ghostscript.com/licensing/. For information on
  12. % commercial licensing, go to http://www.artifex.com/licensing/ or
  13. % contact Artifex Software, Inc., 101 Lucas Valley Road #110,
  14. % San Rafael, CA 94903, U.S.A., +1(415)492-9861.
  15. % $Id: gs_cidcm.ps 9164 2008-10-17 13:44:34Z alexcher $
  16. % Extending Font resource category with CIDFont-CMap fonts.
  17. languagelevel 2 .setlanguagelevel currentglobal true setglobal
  18. % In the comments below, 'CSI' is an abbreviation/acronym for CIDSystemInfo.
  19. % We pre-scan resource files to retrieve the CSI from them.
  20. % First we define a hidden procset .prs_dict containing
  21. % necessary variables and procedures.
  22. % Then we redefine the old /Font category using this procset.
  23. % We maintain internal caches for the CSI values retrieved from
  24. % resource files. This supposes that document doesn't uninstall
  25. % resource files. To disable caching, set enable_cache to false.
  26. % We assume that names starting with '.prs' do not appear in resource files.
  27. % If this causes any problem, this prefix should be systematically changed
  28. % in this file. ('prs' is an abbreviation for 'prescan'.)
  29. 25 dict begin
  30. % Define local variables :
  31. /.prs_dict currentdict def % self-reference (constant)
  32. /.prs_empty 0 dict readonly def
  33. /path_buffer 8192 string def
  34. /name_buffer 1024 string def
  35. /minus (-) 0 get def % character code constant for '-'
  36. /period (.) 0 get def % character code constant for '.'
  37. /CMap 10 dict def % CSI cache for CMaps
  38. /CIDFont 10 dict def % CSI cache for CIDFonts
  39. /enable_cache true def % set false to disable cache
  40. % The folloving variables are just placeholders for ones to be set
  41. % dynamically :
  42. /.prsFile 0 def % file to prescan
  43. /.prsResult 0 def % result of prescan
  44. /.prsDictCount 0 def % save the dictionary stack depth
  45. % Define a dummy CIDInit procset to use while pre-scanning :
  46. /DummyCIDInit 15 dict
  47. begin
  48. /begincmap {} def
  49. /usecmap {pop} bind def
  50. {stop} bind
  51. [ /begincodespacerange /endcodespacerange /beginnotdefchar /endnotdefchar
  52. /beginnotdefrange /endnotdefrange /begincidchar /endcidchar /begincidrange
  53. /endcidrange /endcmap /usefont /StartData
  54. ] {
  55. 1 index def
  56. } bind forall
  57. pop
  58. currentdict end def
  59. % Define a local 'findresource' for pre-scanning :
  60. % (it returns the dummy CIDInit instead of the regular CIDInit ProcSet)
  61. /findresource { % <InstName> <CatName> findresource <inst>
  62. 2 copy /ProcSet eq exch % /InstName /CatName bool /InstName
  63. /CIDInit eq and {
  64. pop pop //DummyCIDInit
  65. } {
  66. //findresource exec
  67. } ifelse
  68. } bind def
  69. % Define procedures for pre-scanning :
  70. /StopIfCSIDefined { % - StopIfCSIDefined -
  71. % Check if the dictionary stack contains a dictionary containing /CIDSystemInfo.
  72. % The search is limited to the top .prsDictCount dictionaries in the stack.
  73. % If so, retrieve the CSI, and execute stop to terminate the pre-scanning of the file.
  74. % Otherwise, do nothing, so the pre-scanning continues.
  75. countdictstack //.prs_dict /.prsDictCount get sub dup {
  76. currentdict /CIDSystemInfo .knownget {
  77. //.prs_dict exch /.prsResult exch put
  78. stop
  79. } if
  80. currentdict exch end
  81. } repeat {
  82. begin
  83. } repeat
  84. } bind def
  85. /PrescanFile { % - PrescanFile -
  86. { //.prs_dict /.prsFile get token {
  87. dup type % token type
  88. dup /nametype eq exch /operatortype eq or {
  89. dup xcheck {
  90. exec
  91. //StopIfCSIDefined exec
  92. } if
  93. } if
  94. } {
  95. stop
  96. } ifelse
  97. } loop
  98. } bind odef
  99. /GetCIDSystemInfoFromFile { % <file> GetCIDSystemInfoFromFile <CSI>
  100. % This procedure reads resource files with 'token',
  101. % executing the tokens untill /CIDSystemInfo appears to be defined.
  102. % Normally the resource file creates a new dictionary on
  103. % dictionary stack and defines /CIDSystemInfo in it.
  104. %
  105. % Returns an empty dictionary if no CIDSystemInfo is found.
  106. RESMPDEBUG { (cidcm GetCIDSystemInfoFromFile beg) = } if
  107. //.prs_dict begin
  108. /.prsFile exch def
  109. /.prsResult //.prs_empty def
  110. /.prsDictCount countdictstack def
  111. RESMPDEBUG { (cidcm GetCIDSystemInfoFromFile will PrescanFile.) = } if
  112. { //PrescanFile } stopped pop
  113. //.prs_dict /.prsResult get
  114. end
  115. RESMPDEBUG { (cidcm GetCIDSystemInfoFromFile end) = } if
  116. } bind def
  117. /GetCIDSystemInfo { % <InstName> <CatName> GetCIDSystemInfo <CSI>
  118. % Retrieve CSI, using caches.
  119. RESMPDEBUG { (cidcm GetCIDSystemInfo beg) = } if
  120. /Category findresource begin % /InstName
  121. dup ResourceStatus
  122. {
  123. pop 2 lt {
  124. FindResource /CIDSystemInfo .knownget not {
  125. //.prs_empty
  126. } if % CSI
  127. } { % /InstName
  128. currentdict /GetCIDSystemInfoFromMap .knownget {
  129. exec
  130. } if
  131. dup type /nametype eq
  132. {
  133. RESMPDEBUG { (cidcm GetCIDSystemInfo got a name.) = } if
  134. //.prs_dict Category get % /InstName CSIs
  135. dup 2 index known
  136. //enable_cache and {
  137. RESMPDEBUG { (cidcm GetCIDSystemInfo from cache.) = } if
  138. exch get % CSI
  139. } {
  140. RESMPDEBUG { (cidcm GetCIDSystemInfo from file.) = } if
  141. exch % CSIs /InstName
  142. dup //path_buffer ResourceFileName % CSIs /InstName (path)
  143. RESMPDEBUG { (cidcm GetCIDSystemInfo from file ) print dup = } if
  144. currentglobal exch true setglobal % CSIs /InstName g (path)
  145. mark exch % CSIs /InstName g [ (path)
  146. { (r) file } stopped {
  147. cleartomark //.prs_empty
  148. } {
  149. exch 1 index % CSIs /InstName g file [ file
  150. //GetCIDSystemInfoFromFile stopped {
  151. cleartomark closefile //.prs_empty
  152. } {
  153. exch pop exch closefile
  154. } ifelse
  155. } ifelse % CSIs /InstName g CSI
  156. exch setglobal % CSIs /InstName CSI
  157. dup 4 1 roll % CSI CSIs /InstName CSI
  158. put % CSI
  159. RESMPDEBUG {
  160. (cidcm GetCIDSystemInfo got from file : <<) print
  161. dup { exch //=string cvs print ( ) print
  162. //=string cvs print ( ) print
  163. } forall
  164. (>>) =
  165. } if
  166. } ifelse
  167. } if
  168. } ifelse
  169. } {
  170. pop //.prs_empty
  171. } ifelse
  172. end
  173. RESMPDEBUG { (cidcm GetCIDSystemInfo end) = } if
  174. } bind def
  175. /IsCompatibleCSI { % <CSI-M> <CSI-F> IsCompatibleCSI <bool>
  176. % The CSI in a CIDFont may be an array, a dict, or null.
  177. % If it is an array, it must be of 1 element, which is a dict.
  178. % In this case the dict is used for testing the compatibility.
  179. % Two dicts are compatible iff they contain same /Ordering and /Registry.
  180. % Identity CMap is compatible with any CIDFont.
  181. exch % CSI-F CSI-M
  182. { dup type /arraytype eq {
  183. dup length 1 ne {
  184. pop pop //false exit
  185. } if
  186. 0 get
  187. } if % CSI-F CSI-M
  188. dup type /dicttype ne {
  189. pop pop //false exit
  190. } if % CSI-F <<CSI-M>>
  191. exch % <<CSI-M>> CSI-F
  192. dup type /dicttype ne {
  193. pop pop //false exit
  194. } if % <<CSI-M>> <<CSI-F>>
  195. dup /Ordering .knownget {
  196. /Identity eq {
  197. pop pop //true exit
  198. } if
  199. } if
  200. //true % <<CSI-M>> <<CSI-F>> bEQ
  201. [/Registry /Ordering] {
  202. 2 index 1 index .knownget not {
  203. 1234567
  204. } if % <<CSI-M>> <<CSI-F>> bEQ /key vF
  205. exch % <<CSI-M>> <<CSI-F>> bEQ vF /key
  206. 4 index exch .knownget not {
  207. 7654321
  208. } if % <<CSI-M>> <<CSI-F>> bEQ vF vM
  209. eq and % <<CSI-M>> <<CSI-F>> bEQ
  210. } forall
  211. exch pop exch pop % bEQ
  212. exit
  213. } loop
  214. } bind def
  215. /IsWellComposed { % <CIDFontName> <CMapName> IsWellComposed <bool>
  216. % Check if the given CIDFont and CMap have compatible CSIs.
  217. exch % /CMapName /CIDFontName
  218. /CIDFont //GetCIDSystemInfo exec % /CMapName CSI-F
  219. dup type /dicttype eq {
  220. dup length 0 ne {
  221. exch % CSI-F /CMapName
  222. /CMap //GetCIDSystemInfo exec % CSI-F CSI-M
  223. //IsCompatibleCSI exec % bool
  224. } {
  225. pop pop false
  226. } ifelse
  227. } {
  228. pop pop false
  229. } ifelse
  230. } bind def
  231. /IsComposedFont { % <FontName> IsComposedFont <CIDFontName> <CMapName> true
  232. % <FontName> IsComposedFont false
  233. % Check if the given font name may be decomposed into CIDFont.CMap, CIDFont-CMap
  234. % or into CIDFont--CMap, such that CIDFont and CMap have compatible CSIs.
  235. % FontName
  236. dup type /stringtype ne {
  237. //name_buffer cvs
  238. } if % (FontName)
  239. { dup length 2 sub -1 1 {
  240. % (FontName) i
  241. 2 copy get dup //minus eq exch //period eq or {
  242. 2 copy 2 copy % (FontName) i (FontName) i (FontName) i
  243. 2 copy get //minus eq {
  244. 2 copy 1 sub get //minus eq {
  245. 1 sub
  246. } if
  247. } if % (FontName) i (FontName) i (FontName) i0
  248. 0 exch getinterval cvn % (FontName) i (FontName) i /CIDFontName
  249. 3 1 roll % (FontName) i /CIDFontName (FontName) i
  250. 1 add dup % (FontName) i /CIDFontName (FontName) i1 i1
  251. 5 index length % (FontName) i /CIDFontName (FontName) i1 i1 l
  252. exch sub getinterval cvn % (FontName) i /CIDFontName /CMapName
  253. 2 copy //IsWellComposed exec { % (FontName) i /CIDFontName /CMapName
  254. 4 2 roll pop pop % /CIDFontName /CMapName
  255. stop
  256. } if
  257. pop pop pop
  258. } {
  259. pop
  260. } ifelse % (FontName)
  261. } for
  262. pop
  263. } stopped
  264. } bind def
  265. /ComposeName { % <CIDFont> <CMap> <scr> ComposeName <CIDFont-CMap>
  266. dup dup 5 2 roll % (scr) (scr) /CIDFont /CMap (scr)
  267. 3 2 roll exch cvs length dup % (scr) (scr) /CMap l0 l0
  268. 4 -1 roll exch //minus put % (scr) /CMap l0
  269. 1 add dup % (scr) /CMap l1 l1
  270. 3 index dup length % (scr) /CMap l1 l1 (scr) L
  271. 2 index sub % (scr) /CMap l1 l1 (scr) LT
  272. 3 2 roll % (scr) /CMap l1 (scr) LT l1
  273. exch getinterval % (scr) /CMap l1 (scrT)
  274. 3 2 roll exch cvs length % (scr) l1 l2
  275. add 0 exch getinterval % (CIDFont-CMap)
  276. } bind def
  277. % Redefine the /Font category with CIDFont-CMap construction :
  278. % The following code supposes that the following names are not
  279. % defined in the old /Font category dictionary :
  280. % /IsComposedFont, /IsWellComposed .
  281. /Font /Category findresource dup length dict copy begin
  282. /FindResource { % <InstName> FindResource <inst>
  283. dup //ResourceStatus exec {
  284. pop pop //FindResource exec
  285. } {
  286. dup //IsComposedFont exec { % /FontName /CIDFontName /CMapName
  287. exch [ exch ] composefont % inst
  288. } {
  289. //FindResource exec
  290. } ifelse
  291. } ifelse
  292. } bind def
  293. /ResourceStatus { % <InstName> ResourceStatus <nStatus> <nSize> true
  294. % <InstName> ResourceStatus false
  295. dup //ResourceStatus exec {
  296. 3 2 roll pop true % nStatus nSize true
  297. } {
  298. //IsComposedFont exec { % /CIDFontName /CMapName
  299. /CMap resourcestatus { % /CIDFontName nStatusM nSizeM
  300. exch pop exch % nSizeM /CIDFontName
  301. /CIDFont resourcestatus { % nSizeM nStatusF nSizeF
  302. exch pop % nSizeF nSizeM
  303. dup 0 ge {
  304. exch dup 0 ge {
  305. add
  306. } {
  307. exch pop
  308. } ifelse
  309. } {
  310. pop
  311. } ifelse % nSize
  312. 2 exch true % nStatus nSize true
  313. } {
  314. pop pop pop false % work around buggy resource file
  315. } ifelse
  316. } {
  317. pop pop pop false % work around buggy resource file
  318. } ifelse
  319. } {
  320. false
  321. } ifelse
  322. } ifelse
  323. } bind def
  324. /ResourceForAll { % <template> <proc> <scratch> ResourceForAll -
  325. % We suppose that the resourceforall procedure does not
  326. % define or install new fonts, CMaps, and/or CIDFonts.
  327. % First we create 3 temporary dictionaries to store temporary data
  328. % about fonts, CMaps and CIDFonts.
  329. % These dictionaries must be created dynamically, to allow for a possible
  330. % recursive call to resourceforall from the resourceforall procedure.
  331. currentglobal false setglobal
  332. 20 dict 20 dict 20 dict % (templ) proc (scr) g <<CIDFont>> <<CMap>> <<Fonts>>
  333. % Store resource identifiers into local dictionaries
  334. % A resource instance can have a key that is not a name or a string. In this
  335. % case, resourceforall passes the key directly to proc instead of copying it
  336. % into the scratch string. This case can arise only for a resource instance
  337. % defined in virtual memory by a previous defineresource
  338. % Discard non-string keys of CIDFont and CMap because <CIDFontName>-<CMapName>
  339. % is only defined for names.
  340. { /.DisableResourceOrdering pop % gs_resmp accesses this through execstack - don't remove !
  341. 6 index [ 2 index {exch //null put} aload pop ] cvx bind 6 index //ResourceForAll exec
  342. (*) [ 3 index {exch dup type /stringtype eq { cvn dup put } { pop pop } ifelse } aload pop
  343. ] cvx bind 6 index /CMap resourceforall
  344. (*) [ 4 index {exch dup type /stringtype eq { cvn dup put } { pop pop } ifelse } aload pop
  345. ] cvx bind 6 index /CIDFont resourceforall
  346. exit
  347. } loop % This loop is a pattern for execstack_lookup - don't remove !
  348. 4 -1 roll setglobal % (templ) proc (scr) <<CIDFont>> <<CMap>> <<Fonts>>
  349. %% Make the list of fonts in the form (/Name status) :
  350. % (templ) proc (scr) <<CIDFont>> <<CMap>> <<Fonts>>
  351. dup {
  352. pop dup
  353. //ResourceStatus exec {
  354. pop 2 index % (templ) proc (scr) <<CIDFont>> <<CMap>> <<Fonts>> /Name nStatus <<Font>>
  355. 3 1 roll put % (templ) proc (scr) <<CIDFont>> <<CMap>> <<Fonts>>
  356. } {
  357. pop
  358. } ifelse
  359. } forall % (templ) proc (scr) <<CIDFont>> <<CMap>> <<Fonts>>
  360. %% Add CIDFont-CMap to it (filtering duplicates) :
  361. 3 2 roll {
  362. 3 index {
  363. 3 1 roll % (templ) proc (scr) <<CMap>> <<Font>> /CIDFont /CMap /CIDFont /CMap
  364. 6 index //ComposeName exec % (templ) proc (scr) <<CMap>> <<Font>> /CIDFont /CMap (Font)
  365. dup 8 index .stringmatch {
  366. cvn % (templ) proc (scr) <<CMap>> <<Font>> /CIDFont /CMap /Font
  367. dup 4 index exch known {
  368. pop pop
  369. } {
  370. 2 index % (templ) proc (scr) <<CMap>> <<Font>> /CIDFont /CMap /Font /CIDFont
  371. 4 2 roll % (templ) proc (scr) <<CMap>> <<Font>> /Font /CIDFont /CIDFont /CMap
  372. //IsWellComposed exec {
  373. exch 2 index exch 2 put % (templ) proc (scr) <<CMap>> <<Font>> /CIDFont
  374. } {
  375. exch pop
  376. } ifelse
  377. } ifelse
  378. } {
  379. pop pop
  380. } ifelse
  381. dup % (templ) proc (scr) <<CMap>> <<Font>> /CIDFont /CIDFont
  382. } forall
  383. pop pop % (templ) proc (scr) <<CMap>> <<Font>>
  384. } forall % (templ) proc (scr) <<CMap>> <<Font>>
  385. exch pop % (templ) proc (scr) <<Font>>
  386. 4 3 roll pop % proc (scr) <<Font>>
  387. % Make the enumerator and apply it :
  388. /MappedCategoryRedefiner /ProcSet findresource /MakeResourceEnumerator get exec exec
  389. } bind def
  390. currentdict end /Font exch /Category defineresource pop
  391. end
  392. setglobal .setlanguagelevel