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.

463 lines
15 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. % Redefine Font and CIDFont categories with FAPI-handeled fonts.
  16. systemdict /.FAPIavailable known { //null .FAPIavailable } { //false } ifelse not {
  17. (%END FAPI) .skipeof
  18. } if
  19. languagelevel 2 .setlanguagelevel
  20. %====================================================================
  21. % Redefine Font category with FAPIfontmap and CIDFont with FAPIfontmap :
  22. 15 dict begin % a temporary dictionary for local binding.
  23. /EmbedFontObjectsQuery mark
  24. /.EmbedFontObjects 0
  25. .dicttomark def
  26. /is_device_compatible_to_FAPI % - is_device_compatible_to_FAPI <bool>
  27. {
  28. //true % removed a bogus check against EmbedFontObjectsQuery
  29. %
  30. % Temporary switch to allow override of FAPI and fallback to GS font rendering
  31. % to be removed at some date after FT integration is completed and released.
  32. %
  33. /DisableFAPI where {
  34. /DisableFAPI get not and
  35. }if
  36. % The code above assumes that only the requested parameter is rendered.
  37. % The commented-out code below may be useful for general case.
  38. % Keeping it for a while.
  39. % counttomark 2 idiv {
  40. % exch /.EmbedFontObjects eq {
  41. % counttomark 1 add 1 roll cleartomark
  42. % 0 eq exit
  43. % } if
  44. % } repeat
  45. % dup mark eq {
  46. % pop //true
  47. % } if
  48. } .internalbind def
  49. %----------------------------- Process FAPIconfig -----------------------
  50. % The HookDiskFonts and HookEmbeddedFonts take a simple array setting normally.
  51. % but if two or more FAPI plugins are built in, they can take a dictionary,
  52. % whose contents are the FAPI subtype string of a given plugin as the key,
  53. % and an array containing the (sub)set of font types the plugin should handle.
  54. % Any repetition of font types is ill advised since the resulting bevhaviour
  55. % will depend on the order entries are stored in the dictionary, which is
  56. % indeterminate. An attempt to use request a font scaler/renderer which cannot
  57. % deal with a given font type will result in the FAPI resorting to it's default
  58. % search for a viable plugin.
  59. %
  60. % As an example, you might want UFST to handle Truetype/Type 42 fonts, and
  61. % Freetype to handle others, thus:
  62. % /HookDiskFonts << /UFST [11 42] /FreeType [1 2 9] >>
  63. % /HookEmbeddedFonts << /UFST [11 42] /FreeType [1 2 9] >>
  64. /Config
  65. <<
  66. % If we've got a FAPIConfig, run it now.
  67. systemdict /FAPIconfig known
  68. {
  69. /FAPIconfig .systemvar .runlibfile
  70. } if
  71. % Now setup defaults for any entries not set above - these defaults are correct
  72. % for FAPI/Freeetype
  73. currentdict /FontPath known not { /FontPath (/Fonts)} if % A default directory for FAPI-handled font files
  74. % path in FAPIfontmap.
  75. currentdict /CIDFontPath known not { /CIDFontPath (/CIDFonts)} if % A default directory for FAPI-handled CIDfont % files path in FAPIcidfmap.
  76. currentdict /HookDiskFonts known not { /HookDiskFonts [1 2 9 11 42] } if % FontType values for disk PS fonts to be
  77. % redirected to FAPI.
  78. currentdict /HookEmbeddedFonts known not { /HookEmbeddedFonts [1 2 9 11 42] } if % FontType values for embedded PS fonts to be
  79. % redirected to FAPI.
  80. /ServerOptions 2 dict
  81. >> def
  82. systemdict /.FAPIconfig //Config put
  83. /UFST .FAPIavailable
  84. {
  85. systemdict /UFST_SSdir known
  86. {
  87. /UFSTFONTDIR UFST_SSdir def
  88. systemdict /UFST_SSdir undef
  89. }
  90. {
  91. /UFSTROMFONTDIR (%rom%fontdata/) def
  92. UFSTROMFONTDIR (mtfonts/pcl45/mt3/plug__xi.fco)
  93. concatstrings status
  94. {
  95. pop pop pop pop
  96. /UFSTFONTDIR UFSTROMFONTDIR def
  97. }
  98. {
  99. /UFSTFONTDIR () def
  100. } ifelse
  101. } ifelse
  102. systemdict /UFST_PlugIn known not
  103. {
  104. systemdict /UFST_PlugIn UFSTFONTDIR (mtfonts/pcl45/mt3/plug__xi.fco) concatstrings put
  105. } if
  106. systemdict /FCOfontfile known not
  107. {
  108. systemdict /FCOfontfile UFSTFONTDIR (mtfonts/pclps2/mt3/pclp2_xj.fco) concatstrings put
  109. } if
  110. systemdict /FCOfontfile2 known not
  111. {
  112. systemdict /FCOfontfile2 UFSTFONTDIR (mtfonts/pcl45/mt3/wd____xh.fco) concatstrings put
  113. } if
  114. systemdict /FAPIfontmap known not
  115. {
  116. systemdict /FAPIfontmap (FCOfontmap-PCLPS2) put
  117. } if
  118. } if
  119. ()
  120. systemdict /UFST_SSdir .knownget {
  121. (UFST_SSdir=) exch concatstrings concatstrings
  122. } if
  123. systemdict /UFST_PlugIn .knownget {
  124. 1 index length 0 ne {
  125. exch .filenamelistseparator concatstrings exch
  126. } if
  127. (UFST_PlugIn=) exch concatstrings concatstrings
  128. } if
  129. dup length 0 ne {
  130. //Config /ServerOptions get exch /UFST exch put
  131. } {
  132. pop
  133. } ifelse
  134. %------------------Copy the FontEmulationProcs here : -------------------
  135. /FontEmulationProcs /ProcSet findresource {
  136. def
  137. } forall
  138. currentdict /super.complete_instance currentdict /complete_instance get put
  139. %-----------FAPI-specific methods for category redefinition : -----------
  140. /RefinePath % <FontDict> /key RefinePath <FontDict>
  141. { exch begin
  142. //Config exch get
  143. /Path exch
  144. Path //false .file_name_combine not {
  145. exch
  146. (Can't combine paths ) print print ( and ) print =
  147. /RefinePath cvx /configurationerror signalerror
  148. } if
  149. def
  150. currentdict end
  151. } .internalbind def
  152. /complete_instance % <font_name> <FontDict> <Options> complete_FAPI_Font <font_name> <FontDict>
  153. { //super.complete_instance exec
  154. dup /CIDFontName known { /CIDFontPath } { /FontPath } ifelse //RefinePath exec
  155. } .internalbind def
  156. /IsMyRecord % <raw_record> -> <raw_record> bool
  157. { dup type /dicttype eq { dup /FAPI known } { //false } ifelse
  158. } .internalbind def
  159. /IsActive % <record> IsActive <bool>
  160. { pop //is_device_compatible_to_FAPI exec
  161. } .internalbind def
  162. /FontRecordVirtualMethods //RecordVirtualMethodsStub dup length 2 add dict copy begin
  163. /IsActive //IsActive def
  164. /MakeInstance % <Name> <record> MakeInstance <Name> <Instance> <size>
  165. { currentglobal 3 1 roll //true setglobal
  166. //FontOptions //complete_instance exec
  167. 2 copy //GetSize exec
  168. 4 3 roll setglobal
  169. } .internalbind def
  170. currentdict end def
  171. /CIDFontRecordVirtualMethods //RecordVirtualMethodsStub dup length 3 add dict copy begin
  172. /GetCSI //TranslateCSI def
  173. /IsActive //IsActive def
  174. /MakeInstance % <Name> <record> MakeInstance <Name> <Instance> <size>
  175. { currentglobal 3 1 roll //true setglobal
  176. //CIDFontOptions //complete_instance exec
  177. 2 copy //GetSize exec
  178. 4 3 roll setglobal
  179. } .internalbind def
  180. currentdict end def
  181. /ReadFCOfontmap: % <path> ReadFCOfontmap: name dict ...
  182. {
  183. /fontfile exch def
  184. {
  185. currentfile =string readline not {
  186. pop exit
  187. } if
  188. dup length 0 ne {
  189. 0 () /SubFileDecode filter
  190. dup token not {
  191. % A comment line
  192. closefile
  193. } {
  194. dup /EndFCOfontmap cvx eq {
  195. pop closefile exit
  196. } if
  197. exch dup token not {
  198. /ReadFCOfontmap: cvx /rangecheck signalerror
  199. } if
  200. exch dup token not {
  201. /StandardEncoding
  202. } {
  203. dup type /nametype ne {
  204. /ReadFCOfontmap: cvx /rangecheck signalerror
  205. } if
  206. } ifelse
  207. findencoding
  208. exch dup token not {
  209. //null
  210. } {
  211. dup type /nametype ne {
  212. /ReadFCOfontmap: cvx /rangecheck signalerror
  213. } if
  214. /Decoding findresource
  215. } ifelse
  216. exch closefile % index name enc dec|null
  217. 4 3 roll % name enc dec|null index
  218. << /Path fontfile
  219. /FontType 1
  220. /FAPI /UFST
  221. /SubfontId counttomark 2 add -1 roll
  222. /Decoding counttomark 2 add -1 roll
  223. dup //null eq {
  224. pop pop
  225. } if
  226. /Encoding counttomark 2 add -1 roll
  227. /FontInfo
  228. <<
  229. /UnderlineThickness 50
  230. /Weight (Regular)
  231. /version (0.00)
  232. /ItalicAngle 0
  233. /UnderlinePosition -100
  234. /FamilyName ()
  235. /Notice ()
  236. /FullName ()
  237. >>
  238. % although we pretend this is a Type 1, the FAPI interface currently
  239. % needs an identity FontMatrix
  240. /FontMatrix [0.001 0.0 0.0 0.001 0.0 0.0]
  241. % we need a fake CharStrings dictionary to placate certain jobs
  242. % which try to look inside it
  243. /CharStrings
  244. <<
  245. /.notdef ( )
  246. StandardEncoding { ( ) } forall
  247. >>
  248. % FontBBox will get replaced with valid numbers pulled from the rendering engine
  249. /FontBBox [-128 -128 1024 1024] cvx
  250. >> % dup { exch == = } forall
  251. } ifelse
  252. } {
  253. pop
  254. } ifelse
  255. } loop
  256. currentdict /fontfile undef
  257. } .internalbind def
  258. %----------------------------------The Redefintion---------------------
  259. /MappedCategoryRedefiner /ProcSet findresource /Redefine get /Redefine exch def
  260. % Redefine the /Font category :
  261. 4 dict begin
  262. /CategoryName /Font def
  263. /MapFileName systemdict /FAPIfontmap known {/FAPIfontmap .systemvar} {(FAPIfontmap)} ifelse def
  264. /VerifyMap { pop } .internalbind def
  265. /PreprocessRecord % <map> <Name> <raw_record> PreprocessRecord <map> <Name> <record> <bool>
  266. { //IsMyRecord exec dup {
  267. pop dup /RecordVirtualMethods //FontRecordVirtualMethods put
  268. //true
  269. } if
  270. } .internalbind def
  271. currentdict end Redefine
  272. % Redefine the /CIDFont category :
  273. 4 dict begin
  274. /CategoryName /CIDFont def
  275. /MapFileName systemdict /FAPIcidfmap known {/FAPIcidfmap .systemvar} {(FAPIcidfmap)} ifelse def
  276. /VerifyMap { pop } .internalbind def
  277. /PreprocessRecord % <map> <Name> <raw_record> PreprocessRecord <map> <Name> <record> <bool>
  278. { //IsMyRecord exec dup {
  279. pop dup /RecordVirtualMethods //CIDFontRecordVirtualMethods put
  280. //true
  281. } if
  282. } .internalbind def
  283. currentdict end Redefine
  284. %==================== A hook for buildfont* operators ====================
  285. % The procedure .FAPIhook redirects PS fonts to FAPI on necessity.
  286. % This depends on the following conditions :
  287. %
  288. % 1. If font dictionary has /FAPI entry, it is a font listed in FAPIconfig.FontPath,
  289. % and must be build with .FAPIrebuildfont, or a copy of a font, which was
  290. % built with .FAPIrebuildfont .
  291. %
  292. % 2. If the font dictionary has /PathLoad entry, and has no /FAPI entry,
  293. % it is an installed PS font, which is described in lib/fontmap or
  294. % in GS_FONTPATH. .loadfont inserts /PathLoad entry for this case
  295. % (see gs_fonts.ps).
  296. %
  297. % Installed fonts are being loaded with GS font loader,
  298. % the they are passed to FAPI is same way as embedded fonts are.
  299. % We do so because UFST cannot read fonts, which don't
  300. % follow Type 1/42 file format strongly.
  301. %
  302. % 3. Executing .loadfont, we place /FAPI_hook_disable in the 0th
  303. % element of some procedure on the execution stack - see gs_fonts.ps .
  304. % If FAPI_hook finds /FAPI_hook_disable in there,
  305. % it knows that it is called for a disk font during
  306. % its internal definefont.
  307. %
  308. % 4. If font dictionary has no /FAPI entry, and has no /Path entry,
  309. % and if we are not in .loadfont context, it is an embedded font.
  310. %
  311. % 5. Two entries to be defined in lib/FAPIconfig to control the hooking of PS fonts :
  312. % HookDiskFonts and HookEmbeddedFonts .
  313. % They specify arrays of font types (integers) to be redirected with FAPI.
  314. % HookDiskFonts controls disk PS fonts (which fall into (2) and (3) ).
  315. % HookEmbeddedFonts controls fonts being embedded into documents.
  316. %
  317. % 7. We apply the operator .passtoFAPI for checking whether FAPI can handle a font.
  318. % If so, we insert /FAPI entry into the font dictionary and convert it
  319. % with .FAPIrebuildfont . Otherwise the font is handled with the native GS font renderer.
  320. /FAPI_hook_debug % <proc> FAPI_hook_debug -
  321. FAPIDEBUG { {exec} } { {pop} } ifelse
  322. bind def
  323. /FAPI_hook_warn % <proc> FAPI_hook_debug -
  324. QUIET { {pop} } { {exec} } ifelse
  325. bind def
  326. /FAPI_is_hook_disabled % - FAPI_is_hook_disabled <bool>
  327. { % checks whether execution stack contains packedarray started with /FAPI_hook_disable .
  328. /FAPI_hook_disable /MappedCategoryRedefiner /ProcSet findresource /execstack_lookup get exec
  329. //null ne
  330. } .internalbind def
  331. /FAPIhook_aux % <string|name> <font_dict> .FAPIhook <string|name> <font>
  332. { % name <<font>>
  333. { (\nFAPIhook ) print 1 index = flush } //FAPI_hook_debug exec
  334. dup /FAPI known {
  335. { //PrintFontRef exec ( is mapped to FAPI=) print dup /FAPI get = flush } //FAPI_hook_debug exec
  336. //true .FAPIrebuildfont //ChooseDecoding exec
  337. } {
  338. dup /PathLoad known dup {
  339. { (PathLoad known for the font ) print //PrintFontRef exec (.\n) print flush} //FAPI_hook_debug exec
  340. } {
  341. pop //FAPI_is_hook_disabled exec dup
  342. { pop
  343. { (FAPIhook is in .loadfont context for the font ) print //PrintFontRef exec (.\n) print flush } //FAPI_hook_debug exec
  344. //true
  345. } if
  346. } ifelse
  347. { /HookDiskFonts } { /HookEmbeddedFonts } ifelse
  348. //Config exch get % name <<font>> [types]
  349. dup type /dicttype eq
  350. {
  351. //false exch
  352. {
  353. 3 index //GetFontType exec //FindInArray exec
  354. {
  355. 2 index exch /FAPIPlugInReq exch put
  356. pop //true exit
  357. }
  358. { pop } ifelse
  359. } forall
  360. }
  361. {
  362. 1 index //GetFontType exec //FindInArray exec % name <<font>> bHook
  363. } ifelse
  364. { { (Trying to render the font ) print //PrintFontRef exec ( with FAPI...\n) print flush } //FAPI_hook_debug exec
  365. .FAPIpassfont {
  366. { //PrintFontRef exec ( is being rendered with FAPI=) print dup /FAPI get = flush } //FAPI_hook_debug exec
  367. //false .FAPIrebuildfont //ChooseDecoding exec
  368. } {
  369. { (Can't render ) print //PrintFontRef exec ( with FAPI, will do with native GS renderer.\n) print flush } //FAPI_hook_warn exec
  370. } ifelse
  371. } {
  372. { (The font ) print //PrintFontRef exec ( doesn't need to render with FAPI.\n) print flush } //FAPI_hook_debug exec
  373. } ifelse
  374. % Remove the plugin request from the font dictionary
  375. dup /FAPIPlugInReq undef
  376. } ifelse
  377. } .internalbind def
  378. /FAPIhook % <string|name> <font_dict> .FAPIhook <string|name> <font>
  379. { //is_device_compatible_to_FAPI exec
  380. { //FAPIhook_aux exec
  381. } {
  382. { (FAPIhook is disabled for the current device.\n) print flush } //FAPI_hook_debug exec
  383. } ifelse
  384. } .internalbind def
  385. % ------------------ Redefine .buildfont* with FAPI : -----------------------
  386. /.buildfont1
  387. { //.buildfont1 exec //FAPIhook exec
  388. } .internalbind % 'odef' is below.
  389. /.buildfont2
  390. { //.buildfont2 exec //FAPIhook exec
  391. } .internalbind % 'odef' is below.
  392. /.buildfont42
  393. { //.buildfont42 exec //FAPIhook exec
  394. } .internalbind % 'odef' is below.
  395. /.buildfont9
  396. { //.buildfont9 exec //FAPIhook exec
  397. } .internalbind % 'odef' is below.
  398. /.buildfont10
  399. { //.buildfont10 exec //FAPIhook exec
  400. } .internalbind % 'odef' is below.
  401. /.buildfont11
  402. { //.buildfont11 exec //FAPIhook exec
  403. } .internalbind % 'odef' is below.
  404. end % the temporary dictionary for local binding.
  405. odef odef odef odef odef odef
  406. % Undef these, not needed outside this file
  407. [ /.FAPIavailable /.FAPIpassfont /.FAPIrebuildfont ] systemdict .undefinternalnames
  408. .setlanguagelevel
  409. %END FAPI