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.

441 lines
14 KiB

1 month ago
  1. % Copyright (C) 2001-2023 Artifex Software, Inc.
  2. % All Rights Reserved.
  3. %
  4. % This software is provided AS-IS with no warranty, either express or
  5. % implied.
  6. %
  7. % This software is distributed under license and may not be copied,
  8. % modified or distributed except as expressly authorized under the terms
  9. % of the license contained in the file LICENSE in this distribution.
  10. %
  11. % Refer to licensing information at http://www.artifex.com or contact
  12. % Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
  13. % CA 94129, USA, for further information.
  14. %
  15. % ProcSet for implementing CIDFont and CIDMap resources.
  16. % When this is run, systemdict is still writable.
  17. % ---------------- Defining CIDFont resources ---------------- %
  18. % Define a CIDFont resource. This is the defineresource implementation for
  19. % the CIDFont resource category.
  20. /.checkfonttype { % <cidfont> <fonttype> .checkfonttype <cidfont> <new?>
  21. 1 index /FID known {
  22. 1 index /FontType get ne {
  23. /definefont cvx /invalidfont signalerror
  24. } if //false
  25. } {
  26. 1 index /FontType 3 -1 roll put //true
  27. } ifelse
  28. } .internalbind def
  29. /.cidfonttypes where { pop } { /.cidfonttypes 6 dict def } ifelse
  30. .cidfonttypes
  31. 30 dict begin
  32. /.gcompatstringcopy % <string> <global> .gcompatstringcopy <string>
  33. {
  34. dup 2 index gcheck eq
  35. { pop }
  36. {
  37. currentglobal 3 1 roll setglobal
  38. dup length string copy
  39. exch setglobal
  40. } ifelse
  41. } .internalbind def
  42. % The key in .cidfonttypes is the CIDFontType value;
  43. % the value is a procedure that takes a font name and the CIDFont dictionary
  44. % and replaces the latter with a real font.
  45. % ------ CIDFontType 0 (FontType 9) ------ %
  46. % We add the following entries to the CIDFont dictionary, in addition to
  47. % the ones documented by Adobe:
  48. % SubrCache - dictionary for caching Subr arrays
  49. % For CIDFonts where we read the data from disk incrementally:
  50. % GlyphData is 0 (arbitrary)
  51. % DataSource - a ReusableStreamDecode filter for the data
  52. % We also add a FID entry, and possibly a Subrs entry, to each element of
  53. % FDArray.
  54. dup 0 {
  55. 9 //.checkfonttype exec {
  56. /CIDInit /ProcSet findresource begin
  57. .completefont9
  58. end
  59. } if
  60. 1 index exch .buildfont9
  61. .currentresourcefile dup type /filetype eq { //.filename {1 index gcheck //.gcompatstringcopy exec 1 index exch /ResourcePath exch put} if }{ pop} ifelse
  62. exch pop
  63. } put % Don't bind it here, because gs_fapi.ps redefines .buildfont9
  64. % Add entries to a new CIDFontType 0 font per documentation (FontMatrix)
  65. % or for .buildfont9 (FDArray.Private.Subrs).
  66. /.completefont9 { % <cidfont0> .completefont9 <cidfont0>
  67. currentglobal 3 1 roll dup gcheck setglobal
  68. dup /FontMatrix known {
  69. dup /FDArray get {
  70. dup /FontMatrix get 0 get 1000000 ge {
  71. /FontMatrix matrix put % Bug 688517
  72. } {
  73. pop
  74. } ifelse
  75. } forall
  76. } {
  77. dup /FontMatrix [0.001 0 0 0.001 0 0] put
  78. dup /FDArray get {
  79. currentglobal exch dup gcheck setglobal
  80. dup /FontMatrix get {1000 0 0 1000 0 0} matrix concatmatrix
  81. /FontMatrix exch put
  82. setglobal
  83. } forall
  84. } ifelse
  85. dup /FDArray get {
  86. % Read the Subrs if necessary.
  87. dup /Private get dup /Subrs known not {
  88. dup /SubrCount .knownget {
  89. % Stack: font Private SubrCount
  90. currentglobal 3 1 roll 1 index gcheck setglobal
  91. array 1 index /Subrs 3 -1 roll put
  92. % Stack: font global Private
  93. 2 index begin begin .loadsubrs end end
  94. setglobal
  95. } {
  96. pop
  97. } ifelse readonly pop
  98. } {
  99. pop pop
  100. } ifelse
  101. } forall
  102. 3 -1 roll setglobal
  103. } .internalbind def
  104. % Read some Subrs for the current Type 1 subfont.
  105. % The subfont's Private dict is currentdict; the CIDFont itself is the
  106. % next dictionary on the stack.
  107. /.readsubrs { % <Subrs> <start> .readsubrs <Subrs>
  108. 1 SubrCount 1 sub {
  109. dup SDBytes mul SubrMapOffset add
  110. dup SDBytes .readint exch SDBytes add SDBytes .readint
  111. 1 index sub string ReadString 2 index 3 1 roll put
  112. } for
  113. } .internalbind def
  114. % Ensure that all the Subrs for the current Type 1 subfont are loaded.
  115. % The subfont's Private dict is currentdict; the CIDFont itself is the
  116. % next dictionary on the stack.
  117. /.loadsubrs {
  118. Subrs length 0 ne {
  119. SubrCache SubrMapOffset .knownget {
  120. % We've already loaded some Subrs at this offset.
  121. % Make sure we've got as many as we need.
  122. dup length SubrCount lt {
  123. % We need to load more.
  124. SubrCount array exch 1 index copy length .readsubrs
  125. SubrCache SubrMapOffset 2 index put
  126. } if
  127. } {
  128. % We haven't loaded any Subrs at this offset yet.
  129. SubrCount array 0 .readsubrs
  130. SubrCache SubrMapOffset 2 index put
  131. } ifelse
  132. Subrs copy pop
  133. } if
  134. } .internalbind def
  135. % ------ CIDFontType 1 (FontType 10) ------ %
  136. dup 1 {
  137. 10 //.checkfonttype exec pop
  138. 1 index exch .buildfont10
  139. .currentresourcefile dup type /filetype eq { //.filename {1 index gcheck //.gcompatstringcopy exec 1 index exch /ResourcePath exch put} if }{ pop} ifelse
  140. exch pop
  141. } put % Don't bind it here because gs_fapi.ps redefines .buildfont10
  142. % ------ CIDFontType 2 (FontType 11) ------ %
  143. dup 2 {
  144. 11 //.checkfonttype exec pop
  145. 1 index exch .buildfont11
  146. .currentresourcefile dup type /filetype eq { //.filename {1 index gcheck //.gcompatstringcopy exec 1 index exch /ResourcePath exch put} if }{ pop} ifelse
  147. exch pop
  148. } put % Don't bind it here because gs_fapi.ps redefines .buildfont11
  149. currentdict /.gcompatstringcopy .undef
  150. pop % .cidfonttypes
  151. % ---------------- Reading CIDFontType 0 files ---------------- %
  152. /StartData { % <(Binary)|(Hex)> <datalength> StartData -
  153. % (currentdict is CID font dict)
  154. % If we're loading a resource file and the data format is
  155. % binary, we can just save a pointer to the data and load it
  156. % incrementally.
  157. mark {
  158. % Previous versions of this code made provisions for
  159. % reading hex-encoded data incrementally. Since hex data
  160. % doesn't seem to be used in practice, we no longer bother.
  161. 2 index (Binary) ne { stop } if
  162. currentfile .currentresourcefile ne { stop } if
  163. % Hack: the pdfwrite driver relies on finalization to write
  164. % out fonts. However, the font may be finalized after the
  165. % resource file, in which case the resource file will be
  166. % closed. So if the current output device is pdfwrite,
  167. % don't use incremental loading.
  168. /AllowIncrementalCFF /GetDeviceParam .special_op {
  169. exch pop {stop}if
  170. }if
  171. currentfile fileposition
  172. } //.internalstopped exec {
  173. % File is not positionable, or uses hex data.
  174. % Load the data now.
  175. cleartomark exch
  176. currentfile exch
  177. (Hex) eq { /ASCIIHexDecode filter } if
  178. exch
  179. % Stack: file length
  180. dup 65400 le {
  181. % readstring with a 0-length string causes a rangecheck,
  182. % but a data length of 0 is allowed.
  183. string dup () ne { 1 index exch readstring pop } if
  184. } {
  185. mark 3 1 roll {
  186. % Stack: mark str ... file length
  187. dup 0 eq { pop exit } if
  188. dup 65400 .min dup string 3 index exch readstring pop
  189. % Stack: mark str ... file length newstrlen newstr
  190. 4 1 roll sub
  191. } loop
  192. counttomark 1 add 1 roll ]
  193. } ifelse
  194. /GlyphData exch def
  195. dup currentfile eq { pop } { closefile } ifelse
  196. } {
  197. % File is positionable and binary, just save a pointer.
  198. % Stack: (Binary) length -mark- pos
  199. /GlyphData 0 def
  200. exch pop 3 -1 roll pop exch
  201. % Stack: pos length
  202. /DataSource currentfile 2 index () .subfiledecode //true .reusablestream def
  203. currentfile 3 1 roll add setfileposition
  204. } ifelse
  205. /SubrCache 10 dict def
  206. CIDFontName currentdict /CIDFont defineresource pop
  207. end % CID font dict
  208. end % resource category dict
  209. } .internalbind def
  210. % Some Adobe fonts include the line
  211. % /Setup /cid_Setup load def
  212. % This is apparently included only to prevent proper, conforming PostScript
  213. % interpreters (as opposed to ATM or a special Adobe font loader) from
  214. % loading the font, since Setup is not referenced anywhere else in the file.
  215. /cid_Setup { } def
  216. % ------ Generic ------ %
  217. % Read a string at a given offset in a "file" (binary file or
  218. % GlyphData in RAM).
  219. /ReadString { % <pos> <string> ReadString <string>
  220. GlyphData 0 eq {
  221. % Read from the file.
  222. DataSource 3 -1 roll setfileposition
  223. DataSource exch readstring pop
  224. } {
  225. % Read from a string or an array of strings.
  226. GlyphData .stringsreadstring
  227. } ifelse
  228. } .internalbind def
  229. /.stringsreadstring % <pos> <string> <strings> .stringsreadstring
  230. % <vmstring>
  231. { dup type /stringtype eq
  232. { 3 1 roll length getinterval
  233. }
  234. { { % Stack: pos string glyphdata
  235. dup 0 get length dup 4 index gt { exit } if
  236. 4 -1 roll exch sub 3 1 roll
  237. dup length 1 sub 1 exch getinterval
  238. }
  239. loop
  240. % Stack: pos string glyphdata glyphdata[0]length
  241. % We know no request can span more than 2 strings.
  242. 3 index 3 index length add 1 index le
  243. { % Request fits in a single string: just return a substring.
  244. pop 0 get 3 1 roll length getinterval
  245. }
  246. { % Request spans 2 strings. Copy the first part.
  247. 1 index 0 get 4 index 3 -1 roll 1 index sub getinterval
  248. 2 index copy
  249. % Copy the second part.
  250. % Stack: pos str glyphdata str1
  251. length exch 1 get 0 3 index length
  252. 3 index sub getinterval 2 index 3 1 roll putinterval
  253. exch pop
  254. }
  255. ifelse
  256. }
  257. ifelse
  258. } .internalbind def
  259. % Interpret a byte string as a (big-endian) integer.
  260. /.cvbsi % <bytes> .cvbsi <int>
  261. { 0 exch { exch 8 bitshift add } forall
  262. } .internalbind def
  263. % Read an integer from binary data.
  264. /.readint % <pos> <nbytes> .readint <int>
  265. { string ReadString .cvbsi
  266. } .internalbind def
  267. currentdict end
  268. % ---------------- Rendering ---------------- %
  269. % ------ CIDFontType 0 ------ %
  270. /.readglyphdata {
  271. currentfont exch .type9mapcid
  272. FDArray exch get exch
  273. } .internalbind executeonly def
  274. % BuildGlyph procedure for CIDFontType 0.
  275. % The name %Type9BuildGlyph is known to the interpreter.
  276. /.cid0buildstring 10 string def
  277. (%Type9BuildGlyph) cvn { % <cidfont> <cid> %Type9BuildGlyph -
  278. .currentglobal 3 1 roll 1 index gcheck .setglobal
  279. 1 index begin
  280. dup //.readglyphdata exec dup //null eq {
  281. % Substitute CID 0. **** WRONG ****
  282. pop pop 0 //.readglyphdata exec
  283. } if
  284. % Stack: cidfont cid subfont charstring
  285. dup //null eq { pop pop pop pop } { %**** WRONG ****
  286. 4 -1 roll pop
  287. 3 1 roll exch dup 4 -1 roll 0 0 moveto
  288. 3 index /FontType get 2 eq { .type2execchar } { .type1execchar } ifelse
  289. } ifelse %**** WRONG ****
  290. end
  291. .setglobal
  292. } .internalbind executeonly def
  293. % ------ CIDFontType 2 ------ %
  294. % BuildGlyph procedure for CIDFontType 2.
  295. % The name %Type11BuildGlyph is known to the interpreter.
  296. (%Type11BuildGlyph) cvn { % <cidfont> <cid> %Type11BuildGlyph -
  297. % We must be prepared for out-of-range CIDs.
  298. 2 copy { .type11mapcid } //.internalstopped exec {
  299. pop /CharStrings get /.notdef get
  300. } if
  301. % Stack: cidfont cid glyphindex
  302. 1 index exch .type42execchar
  303. } .internalbind executeonly def
  304. % ---------------- Define resources ---------------- %
  305. languagelevel exch 2 .setlanguagelevel
  306. % Define the CIDInit ProcSet resource.
  307. % The ProcSet dictionary is still on the stack.
  308. % We might have loaded CMap support already. However, Adobe's
  309. % protected font downloader defines a CIDInit ProcSet that will be
  310. % loaded from the filesystem later, so we must check specifically
  311. % for the ProcSet being defined in VM.
  312. /CIDInit /ProcSet 2 copy resourcestatus { pop 0 eq } { //false } ifelse {
  313. pop pop findresource dup length 4 index length add dict .copydict
  314. 4 -1 roll exch .copydict
  315. } {
  316. 3 -1 roll
  317. } ifelse exch defineresource pop
  318. % Define the CIDFont resource category.
  319. % We break out .buildcidfont because it appears that at least for
  320. % Type 32 (CIDFontType 4) fonts, the font can be registered in the Font
  321. % category with only a CIDFontType and no FontType.
  322. /.buildcidfont { % <name> <fontdict> .buildcidfont
  323. % <name> <cidfont>
  324. systemdict /ProvideUnicode .knownget not { //false } if {
  325. /FontEmulationProcs /ProcSet findresource
  326. /ProvideUnicodeDecoding get exec
  327. } if
  328. dup /CIDFontType get //.cidfonttypes exch get exec
  329. } .internalbind executeonly odef
  330. /CIDFont /Generic /Category findresource dup length dict .copydict
  331. dup /InstanceType /dicttype put
  332. dup /DefineResource {
  333. dup /OrigFont known not {
  334. dup dup /OrigFont exch .growput % CPSI does it. Adding just for CET 33_all.PS conformity.
  335. } if
  336. dup /PaintType known not {
  337. dup /PaintType 0 .growput % CPSI does it. Adding just for CET 33_all.PS conformity.
  338. } if
  339. .buildcidfont
  340. /Generic /Category findresource /DefineResource get exec
  341. } put
  342. % CIDFonts may be defined in CFF OpenType files.
  343. % Check for this here.
  344. /.loadcidfontresource {
  345. dup .ResourceFile {
  346. {.loadfont} .execasresource
  347. } {
  348. dup /undefinedresource signalerror
  349. } ifelse
  350. } .internalbind def
  351. dup /.LoadResource {
  352. currentglobal {
  353. //.loadcidfontresource exec
  354. } {
  355. //true setglobal {//.loadcidfontresource exec} stopped //false setglobal {stop} if
  356. } ifelse
  357. } .internalbind put
  358. /Category defineresource pop
  359. % Add the new FontType resources.
  360. 9 1 11 { dup /FontType defineresource pop } for
  361. % Add the new FMapType resource.
  362. 9 dup /FMapType defineresource pop
  363. % Define the CIDMap resource category.
  364. % These aren't documented, but it's clear what they are for:
  365. % to give names to CIDMaps for CIDFontType 2 fonts.
  366. /CIDMap /Generic /Category findresource dup length dict .copydict
  367. dup /.CheckResource {
  368. % Allow a string, an array of strings, or (as of Adobe release 3011)
  369. % a dictionary.
  370. dup type dup dup /stringtype eq exch /dicttype eq or {
  371. pop //true
  372. } {
  373. dup /arraytype eq exch /packedarraytype eq or {
  374. //true exch { type /stringtype eq and } forall
  375. } {
  376. //false
  377. } ifelse
  378. } ifelse
  379. } .internalbind put
  380. /Category defineresource pop
  381. .setlanguagelevel
  382. %% Replace 1 (gs_ciddc.ps)
  383. (gs_ciddc.ps) runlibfile
  384. % Undef these, not needed outside this file
  385. [
  386. /.checkfonttype
  387. /.loadcidfontresource
  388. /.readglyphdata
  389. ] systemdict .undefinternalnames