星火微课系统客户端
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_cmap.ps 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549
  1. % Copyright (C) 1995, 2000 Aladdin Enterprises. 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_cmap.ps 8954 2008-08-08 04:22:38Z ray $
  16. % ProcSet for implementing CMap resources.
  17. % When this is run, systemdict is still writable.
  18. % NOTE: Rearranged fonts are not implemented yet.
  19. [
  20. /CMERGE_DEBUG
  21. /USE_CIDCHAR_AS_RANGE
  22. ] {dup where {pop pop} { currentdict exch //false def pop } ifelse} forall
  23. % ---------------- Public operators ---------------- %
  24. /.rewriteTempMapsNotDef {
  25. %
  26. % Before building .CodeMapData from .TempMaps,
  27. % we need to replace dst type codes in the notdef map with the value 3,
  28. % which corresponds to CODE_VALUE_NOTDEF, see gxfcmap.h .
  29. %
  30. CMAPDEBUG { (rewriting TempMapsNotDef\n) print flush } if
  31. .TempMaps 2 get
  32. dup length 0 gt {
  33. 0 get
  34. CMAPDEBUG { (...original...\n) print flush } if
  35. 1 5 2 index length 1 sub {
  36. { 1 index exch get 2 3 put } stopped
  37. { CMAPDEBUG { (cannot rewrite\n) print flush } if }
  38. { CMAPDEBUG { (rewrite\n) print flush } if } ifelse
  39. } for
  40. } if
  41. pop
  42. CMAPDEBUG { (...FINISHED...\n) print } if
  43. } bind def
  44. /.composefontdict { % <name> <cmap|cmapname> <fonts> composefont <name> <font_dict>
  45. 10 dict begin
  46. /CMap 2 index dup type /dicttype ne { /CMap findresource } if def
  47. /FDepVector 1 index cvlit def % temporarily
  48. /Encoding [ 0 1 FDepVector length 1 sub { } for ] def
  49. /FontInfo 1 dict def % for .processToUnicode in pdf_font.ps .
  50. /FDepVector [ 0 1 FDepVector length 1 sub {
  51. % Stack: name cmap[name] fonts /FDepVector [ fonts... i
  52. FDepVector 1 index get
  53. dup type /dicttype ne {
  54. dup /CIDFont resourcestatus {
  55. pop pop /CIDFont
  56. } {
  57. /Font
  58. } ifelse findresource
  59. } if
  60. exch CMap /FontMatrices get dup length 2 index gt {
  61. exch get dup //null eq { pop } { makefont } ifelse
  62. } {
  63. pop pop
  64. } ifelse
  65. } for ] readonly def
  66. /FMapType 9 def
  67. /FontMatrix matrix def
  68. /FontName 3 index def
  69. CMap /WMode .knownget { /WMode exch def } if
  70. /FontType 0 def
  71. pop pop currentdict end
  72. } bind odef
  73. % composefont doesn't appear in CMap files -- it's documented in
  74. % the "PostScript Language Reference Manual Supplement".
  75. /composefont { % <name> <cmap|cmapname> <fonts> composefont <font>
  76. .composefontdict /Font defineresource
  77. } bind def
  78. % ---------------- CMap operators ---------------- %
  79. 40 dict begin
  80. % Our internal .CodeMapData structure closely mirrors the structures
  81. % defined in gxfcmap.h (q.v.). () indicate a string, [] indicate an array,
  82. % ? indicates a Boolean, # indicates an integer, {} for grouping.
  83. % [[[(first) (last) ...]+] % code space ranges
  84. % [[(prefix) (key_size,?is_range,value_type,value_size) (keys...)
  85. % {(values...) | [value ...]} #font_index ]+] % code mappings
  86. % ...]
  87. % <<same>> % notdef mappings
  88. % ]
  89. % FontMatrices is the array of matrices defined by begin/endusematrix.
  90. % All of the arrays and strings are read-only after they have been built.
  91. %
  92. % Note that the code in zfcmap.c that constructs the C structures from
  93. % the PostScript structures has intimate knowledge of the above format.
  94. % ****** NOTE: The code currently only handles "well-behaved" CMaps:
  95. % - CID values only (no bfchars), 16-bit
  96. % - Entries (both code space and map) must be sorted
  97. % - Only the last byte must vary in each map range, except for
  98. % the identity mapping
  99. % ------ Font-level operators ------ %
  100. /begincmap { % - begincmap -
  101. /.CodeMapData [[[]] [[]] [[]]] def
  102. /FontMatrices [] def
  103. /.FontIndex 0 def
  104. /.TempMaps [20 dict 50 dict 50 dict] def
  105. /CodeMap //null def % for .buildcmap
  106. } bind def
  107. /endcmap { % - endcmap -
  108. .rewriteTempMapsNotDef
  109. CMAPDEBUG {
  110. 2 (*** undefined charmap ***)
  111. 1 (*** defined charmap ***)
  112. 0 (*** code space ranges ***)
  113. 3 { =
  114. .TempMaps exch get
  115. 0 1 2 index length 1 sub {
  116. dup == (\t) print
  117. 1 index exch get ==
  118. } for
  119. pop
  120. } repeat
  121. } if
  122. /.CodeMapData dup load [ exch
  123. .TempMaps aload pop begin begin begin
  124. {
  125. [ exch aload pop
  126. 0 1 currentdict length 1 sub {
  127. currentdict exch get
  128. } for
  129. ]
  130. end
  131. } forall
  132. ] .endmap def
  133. CMAPDEBUG {
  134. (*** Content of .CodeMapData ***) =
  135. 0 .CodeMapData { exch dup == 1 add exch (\t) print == } forall
  136. pop
  137. } if
  138. currentdict /.TempMaps undef
  139. /FontMatrices FontMatrices .endmap def
  140. } bind def
  141. /.endmap { % <map> .endmap <map>
  142. dup type /arraytype eq {
  143. % This might be a shared read-only array inherited via usecmap.
  144. % Don't try to update its elements if this is the case.
  145. dup wcheck {
  146. 0 1 2 index length 1 sub {
  147. 2 copy 2 copy get .endmap put pop
  148. } for readonly
  149. } if
  150. } {
  151. dup type /stringtype eq { readonly } if
  152. } ifelse
  153. } bind def
  154. /.appendmap { % -mark- <elt> ... <array#> .appendmap -
  155. .TempMaps exch get counttomark 1 add 1 roll
  156. ] 1 index length exch put
  157. } bind def
  158. /begincodespacerange { % <count> begincodespacerange -
  159. pop mark
  160. } bind def
  161. /endcodespacerange { % <code_lo> <code_hi> ... endcodespacerange -
  162. 0 .appendmap
  163. } bind def
  164. /usecmap { % <CMap_name> usecmap -
  165. /CMap findresource dup
  166. % Copy the top level of .CodeMapData
  167. /.CodeMapData exch /.CodeMapData get copyarray def
  168. /FontMatrices exch /FontMatrices get copyarray def
  169. } bind def
  170. /usefont { % <fontID> usefont -
  171. /.FontIndex exch def
  172. } bind def
  173. /beginusematrix { % <fontID> beginusematrix -
  174. FontMatrices wcheck not FontMatrices length 2 index le or {
  175. FontMatrices length 1 index 1 add .max array
  176. dup 0 FontMatrices putinterval
  177. /FontMatrices exch def
  178. } if
  179. } bind def
  180. /endusematrix { % <matrix> endusematrix -
  181. FontMatrices 3 1 roll put
  182. } bind def
  183. % ------ Rearranged font operators ------ %
  184. /beginrearrangedfont { % <font_name> <font*> beginrearrangedfont -
  185. 10 dict begin
  186. /.FontNames exch def
  187. /.FontName exch def
  188. begincmap
  189. } bind def
  190. /endrearrangedfont { % - endrearrangedfont -
  191. (REARRANGED FONTS NOT IMPLEMENTED YET.) = flush
  192. FontName .FontNames 0 get findfont end definefont pop
  193. } bind def
  194. % ------ Character name/code selector operators ------ %
  195. /beginbfchar { % <count> beginbfchar -
  196. pop mark
  197. } bind def
  198. /endbfchar { % <code> <to_code|charname> ... endbfchar
  199. counttomark 2 idiv {
  200. counttomark -2 roll % process in correct order
  201. .addbfchar
  202. } repeat 1 .appendmap
  203. } bind def
  204. /beginbfrange { % <count> beginbfrange -
  205. pop mark
  206. } bind def
  207. /endbfrange { % <code_lo> <code_hi> <to_code|(charname*)> ...
  208. % endbfrange -
  209. counttomark 3 idiv {
  210. counttomark -3 roll % process in correct order
  211. dup type dup /arraytype eq exch /packedarraytype eq or {
  212. % Array value, split up.
  213. exch pop {
  214. % Stack: code to_code|charname
  215. 1 index exch .addbfchar
  216. % Increment the code. As noted above, we require
  217. % that only the last byte vary, but we still must
  218. % mask it after incrementing, in case the last
  219. % value was 0xff.
  220. % Stack: code prefix params key value fontindex
  221. 6 -1 roll dup length string copy
  222. dup dup length 1 sub 2 copy get 1 add 255 and put
  223. } forall pop
  224. } {
  225. % Single value, handle directly.
  226. .addbfrange
  227. } ifelse
  228. } repeat 1 .appendmap
  229. } bind def
  230. /.addbfchar { % <code> <to_code|charname> .addbfchar
  231. % <prefix> <params> <key> <value> <font_index>
  232. 1 index exch .addbfrange
  233. } bind def
  234. /.addbfrange { % <code_lo> <code_hi> <to_code|charname>
  235. % .addbfrange <<same as .addbfchar>>
  236. 4 string dup 3
  237. 3 index type /nametype eq {
  238. 2 index 2 1 put % dst = CODE_VALUE_GLYPH, see gxfcmap.h .
  239. 4 -1 roll 1 array astore 4 1 roll 4
  240. } {
  241. 2 index 2 2 put % dst = CODE_VALUE_CHARS, see gxfcmap.h .
  242. 3 index length
  243. } ifelse put
  244. % Stack: code_lo code_hi value params
  245. 3 index 3 index eq {
  246. % Single value.
  247. 3 -1 roll pop exch () exch
  248. } {
  249. % Range.
  250. dup 0 1 put dup 1 1 put
  251. 4 2 roll
  252. dup dup length 1 sub 0 exch getinterval 5 1 roll % prefix
  253. % Stack: prefix value params code_lo code_hi
  254. 2 { exch dup length 1 sub 1 getinterval } repeat concatstrings
  255. 3 -1 roll
  256. } ifelse
  257. .FontIndex
  258. } bind def
  259. % ------ CID selector operators ------ %
  260. /begincidchar { % <count> begincidchar -
  261. pop mark
  262. } bind def
  263. /endcidchar { % <code> <cid> ... endcidchar -
  264. 1 .endmapchars
  265. } bind def
  266. /begincidrange { % <count> begincidrange -
  267. pop mark
  268. } bind def
  269. /endcidrange { % <code_lo> <code_hi> <cid_base> ... endcidrange -
  270. 1 .endmapranges
  271. } bind def
  272. /.endmapchars { % -mark- <code> <cid> ... <map#> .endmapchars -
  273. counttomark 1 add 1 roll
  274. counttomark 2 idiv {
  275. counttomark -2 roll % process in correct order
  276. exch % <cid> <code>
  277. % Construct prefix, params, key, value, font_index
  278. dup length 1 eq { % 1-byte
  279. <00 00 00 02> () % <prefix> <param> <null_key>
  280. } { % N-byte
  281. dup 0 1 getinterval exch % make 1-byte prefix
  282. 4 string dup 0
  283. USE_CIDCHAR_AS_RANGE {
  284. <00 01 00 02> % skelton for param
  285. } {
  286. <00 00 00 02> % skelton for param
  287. } ifelse
  288. putinterval
  289. exch % <prefix> <param> <code>
  290. dup length % <prefix> <param> <code> N
  291. 1 sub % <prefix> <param> <code> N-1
  292. dup % <prefix> <param> <code> N-1 N-1
  293. 3 index % <prefix> <param> <code> N-1 N-1 <param>
  294. exch % <prefix> <param> <code> N-1 <param> N-1
  295. 0 exch % <prefix> <param> <code> N-1 <param> 0 N-1
  296. put % <prefix> <param'> <code> N-1
  297. 1 exch % <prefix> <param'> <code> 1 N-1
  298. getinterval % <prefix> <param'> <key>
  299. USE_CIDCHAR_AS_RANGE {
  300. dup length 2 mul string % <key> <dkey>
  301. dup % <key> <dkey> <dkey>
  302. 2 index % <key> <dkey> <dkey> <key>
  303. 0 exch putinterval % <key> <dkey'>
  304. dup % <key> <dkey'> <dkey'>
  305. 3 -1 roll % <dkey'> <dkey'> <key>
  306. dup length % <dkey'> <dkey'> <key> N-1
  307. exch putinterval % <dkey''>
  308. } if
  309. } ifelse
  310. 4 -1 roll % <prefix> <param'> <key> <cid>
  311. .endmapvalue % <prefix> <param'> <key> <hex_cid> <font_idx>
  312. % prefix params keys value fontindex
  313. counttomark 5 gt { % 2 (or more) ranges (1 range = 5 item)
  314. 4 index 10 index eq % compare prefix
  315. 4 index 10 index eq and % compare params
  316. 1 index 7 index eq and % compare fontindex
  317. {
  318. CMAPDEBUG { (merge! char\n) print } if
  319. pop 4 2 roll pop pop
  320. % prefix params keys value fontindex keys2 value2
  321. 5 -1 roll 3 -1 roll concatstrings
  322. % prefix params value fontindex value2 keys'
  323. 4 -1 roll 3 -1 roll concatstrings
  324. % prefix params fontindex keys' values'
  325. 3 -1 roll
  326. } if
  327. } if % end of 2 (or more) ranges
  328. CMERGE_DEBUG {
  329. ( prefix:) print 4 index =only
  330. ( param:) print 3 index =only
  331. ( key:) print 2 index =only
  332. ( hex_cid:) print 1 index =only
  333. ( font_idx:) print 0 index == flush
  334. } if
  335. } repeat
  336. counttomark 2 add -1 roll .appendmap
  337. } bind def
  338. /.endmapranges { % -mark- <code_lo> <code_hi> <cid_base> ... <map#>
  339. % .endmapranges -
  340. counttomark 1 add 1 roll
  341. counttomark 3 idiv {
  342. counttomark -3 roll % process in correct order
  343. % Construct prefix, params, key_lo, key_hi, value, font_index
  344. 3 1 roll % <cid_base> <code_lo> <code_hi>
  345. % prefix key
  346. % 1-byte code: () .
  347. % 1-byte range: () .
  348. % N-byte code: . (*)
  349. % N-byte range: (*) (*)
  350. dup 2 index eq { % <code_lo> == <code_hi>
  351. % 0: prefix_len for 1-byte code
  352. % 1: prefix_len for N-byte code
  353. dup length 1 eq { 0 } { 1 } ifelse
  354. } { % <code_lo> != <code_hi>
  355. % calculate prefix_len for *-byte range
  356. dup length 1 sub % <cid_base> <code_lo> <code_hi> <code_len-1>
  357. 0 % initial value for N
  358. { % <cid_base> <code_lo> <code_hi> (code_len-1) N
  359. dup 2 index ge { exit } if % if (N >= len - 1) exit
  360. 3 index 1 index get % N-th byte of code_lo
  361. 3 index 2 index get % N-th byte of code_hi
  362. eq { 1 add } { exit } ifelse
  363. } loop
  364. exch pop % discard <code_len-1>
  365. } ifelse
  366. % cid_base code_lo code_hi prefix_len
  367. % Althogh Adobe CPSI with native CID/CMap support accept
  368. % multi-dimensional range specification in notdef & cidrange
  369. % (and CID is calculated as relative position in multi-dimensional
  370. % range), but older CPSI & ATM cannot handle it.
  371. %
  372. % GS accepts such specification, but it's recommended to keep
  373. % from using this feature for notdef & cidrange.
  374. % Following is a disabler of this feature.
  375. % -------------------------------------------------------------
  376. % counttomark 1 add index % get map#
  377. % 0 ne { % if not codespacerange
  378. % 1 index length % get code length
  379. % 1 index % get prefix length
  380. % sub % calculate key length
  381. % 1 gt { % if (key_len > 1),
  382. % (.endmapranges error) = flush
  383. % (multi-dimensional range specification is used out of codespacerange)
  384. % = flush
  385. % (/) =only
  386. % CMapName CMapName length string cvs =only
  387. % (: <) =only
  388. % 2 index (%stdout) (w) file exch writehexstring
  389. % (> <) =only
  390. % 1 index (%stdout) (w) file exch writehexstring
  391. % (>\n) =only flush
  392. % quit
  393. % } if
  394. % } if
  395. % -------------------------------------------------------------
  396. 1 index exch 0 exch getinterval
  397. % cid_base code_lo code_hi prefix
  398. dup length 3 index length exch sub
  399. % cid_base code_lo code_hi prefix range_len
  400. dup 255 gt {
  401. (too long coderange specification for current GS\n) print
  402. /.endmapranges cvx /rangecheck signalerror
  403. } if
  404. <00 01 00 02> 4 string copy % create initialized param
  405. dup 0 4 -1 roll put % put range_len into param
  406. % get key_hi
  407. 3 -1 roll dup length 3 index length dup 3 1 roll sub getinterval
  408. % get key_lo
  409. 4 -1 roll dup length 4 index length dup 3 1 roll sub getinterval
  410. % make "keys" (concatenated key_lo + key_hi)
  411. exch concatstrings
  412. %
  413. 4 -1 roll
  414. .endmapvalue
  415. % See if we can merge with the previous value.
  416. % The prefix, params, and font index must match.
  417. % prefix params keys value fontindex
  418. counttomark 5 gt { % 2 (or more) ranges (1 range = 5 item)
  419. 4 index 10 index eq % compare prefix
  420. 4 index 10 index eq and % compare params
  421. 1 index 7 index eq and % compare fontindex
  422. {
  423. CMAPDEBUG { (merge!\n) print } if
  424. pop 4 2 roll pop pop
  425. % prefix params keys value fontindex keys2 value2
  426. 5 -1 roll 3 -1 roll concatstrings
  427. % prefix params value fontindex value2 keys'
  428. 4 -1 roll 3 -1 roll concatstrings
  429. % prefix params fontindex keys' values'
  430. 3 -1 roll
  431. } if
  432. } if % end of 2 (or more) ranges
  433. } repeat
  434. counttomark 2 add -1 roll .appendmap
  435. } bind def
  436. /.endmapvalue { % <cid> .endmapvalue (hi,lo) .FontIndex
  437. 2 string dup 0 3 index -8 bitshift put % value
  438. dup 1 4 -1 roll 255 and put
  439. .FontIndex % font_index
  440. } bind def
  441. % ------ notdef operators ------ %
  442. /beginnotdefchar { % <count> beginnotdefchar -
  443. pop mark
  444. } bind def
  445. /endnotdefchar { % <code> <cid> ... endnotdefchar -
  446. 2 .endmapchars
  447. } bind def
  448. /beginnotdefrange { % <count> beginnotdefrange -
  449. pop mark
  450. } bind def
  451. /endnotdefrange { % <code_lo> <code_hi> <cid> ... endnotdefrange -
  452. 2 .endmapranges
  453. } bind def
  454. % ---------------- Resource category definition ---------------- %
  455. currentdict end
  456. languagelevel exch 2 .setlanguagelevel
  457. /CMap /Generic /Category findresource dup length dict .copydict
  458. dup /InstanceType /dicttype put
  459. dup /DefineResource {
  460. % The AdobePS5 Windows driver emits code that attempts to
  461. % create CMaps without the required CMapName entry.
  462. % Work around this here.
  463. dup /CMapName known not {
  464. dup wcheck not {
  465. .currentglobal exch dup wcheck .setglobal
  466. dup length dict .copydict exch .setglobal
  467. } if
  468. dup gcheck 2 index gcheck not and {
  469. exch .currentglobal exch //true .setglobal
  470. dup length string copy exch .setglobal exch
  471. } if dup /CMapName 3 index put
  472. } if
  473. % Adobe PS CET 23-25 and others define an almost empty CMap. Tolerate this.
  474. % With the above, we can actually tolerate: /name << >> defineresource
  475. dup /CIDSystemInfo known not {
  476. dup wcheck not {
  477. .currentglobal exch dup wcheck .setglobal
  478. dup length dict .copydict exch .setglobal
  479. } if
  480. dup /CIDSystemInfo [ //null ] put
  481. } if
  482. dup /CodeMap .knownget { //null eq { .buildcmap } if } if
  483. /Generic /Category findresource /DefineResource get exec
  484. } bind put
  485. /Category defineresource pop
  486. % We might have loaded CID font support already.
  487. /CIDInit /ProcSet 2 copy { findresource } .internalstopped
  488. % An interior `stopped' might have reset VM allocation to local.
  489. //true .setglobal
  490. { pop pop 3 -1 roll }
  491. { dup length 4 index length add dict .copydict 4 -1 roll exch .copydict }
  492. ifelse exch defineresource pop
  493. .setlanguagelevel