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.

252 lines
6.9 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. % Loader for CFF (compressed) fonts, including OpenType CFFs.
  16. % The following are not implemented yet:
  17. % Deleted entries in the Name Index
  18. % Embedded PostScript
  19. % Multiple Master fonts
  20. % Chameleon fonts
  21. % Synthetic fonts
  22. % ---------------- Font loading machinery ---------------- %
  23. % Augment the FONTPATH machinery so it recognizes OpenType CFF font sets.
  24. /.scanfontheaders where {
  25. /.scanfontheaders [
  26. /.scanfontheaders .systemvar aload pop (OTTO*)
  27. ] put
  28. } if
  29. % Load a font file that might be an OpenType CFF font set.
  30. % <file> .init_otto_font_file <file>
  31. /.init_otto_font_file {
  32. /FontSetInit /ProcSet findresource begin
  33. 2 dict begin
  34. /f exch def /cff //null def
  35. card32 pop card16 6 { next pop } repeat dup {
  36. % Stack: numtables tablesleft
  37. dup 0 eq {
  38. pop pop /.loadottofontfile cvx /invalidfont signalerror
  39. } if
  40. f 4 string readstring pop (CFF ) eq { sub exit } if
  41. f 12 string readstring pop pop 1 sub % skip to next table
  42. } loop
  43. % Stack: tablesread
  44. card32 pop card32 card32
  45. % Stack: tablesread start length
  46. exch 3 -1 roll 1 add 16 mul 12 add sub
  47. f exch subfilefilter flushfile % skip to start
  48. f exch subfilefilter end
  49. } .forcebind odef
  50. % <file> .init_otto_font_file <file>
  51. /.init_wOFF_otto_font_file {
  52. /FontSetInit /ProcSet findresource begin
  53. 2 dict begin
  54. /f exch def /cff //null def
  55. 3 {card32 pop} repeat % (wOFF), (OTTO) and file length
  56. card16
  57. 30 { next pop } repeat
  58. dup
  59. {
  60. % Stack: numtables tablesleft
  61. dup 0 eq {
  62. pop pop /.loadottofontfile cvx /invalidfont signalerror
  63. } if
  64. f 4 string readstring pop (CFF ) eq { sub exit } if
  65. f 12 string readstring pop pop 1 sub % skip to next table
  66. } loop
  67. % Stack: tablesread
  68. 4 { card32 } repeat
  69. % Stack: tablesread start complen len checksum
  70. pop
  71. % Stack: tablesread start complen len
  72. 4 -2 roll exch
  73. % Stack: complen len start tablesread
  74. 1 add 20 mul 44 add sub
  75. % Stack: complen len offset
  76. f exch subfilefilter flushfile % skip to start
  77. % Stack: complen len
  78. % the table can legally be uncompressed: complen == len
  79. 1 index 1 index eq
  80. { exch pop f exch subfilefilter}
  81. { pop f exch subfilefilter /FlateDecode filter} ifelse
  82. end
  83. } .internalbind def
  84. % <file> .loadfontfile -
  85. /.loadnonottofontfile /.loadfontfile load def
  86. /.loadfontfile {
  87. dup (12345678) .peekstring pop (wOFFOTTO) eq
  88. {
  89. //.init_wOFF_otto_font_file exec
  90. //true //false
  91. }{//true} ifelse
  92. {
  93. dup 4 string .peekstring pop (OTTO) eq
  94. {
  95. % If this is a font at all, it's an OpenType CFF font set.
  96. .init_otto_font_file //true
  97. }
  98. { //false } ifelse
  99. } if
  100. { % Use a random FontSet resource name. ****** WRONG ******
  101. realtime rand xor =string cvs exch //false //false
  102. ReadData pop
  103. } {
  104. % Not a TrueType font.
  105. .loadnonottofontfile
  106. } ifelse
  107. } .internalbind def
  108. currentdict /.init_wOFF_otto_font_file .forceundef
  109. 20 dict begin
  110. % ------ Utilities ------ %
  111. /subfilefilter { % <file> <length> subfilefilter <filter>
  112. % SubFileDecode interprets a length of 0 as infinite.
  113. dup 0 le { pop pop () 0 } if () /SubFileDecode filter
  114. } .internalbind def
  115. /advance { % <n> advance -
  116. f cff eq { pos add /pos exch store } { pop } ifelse
  117. } .internalbind def
  118. /next { % - next <byte>
  119. f read {
  120. 1 advance
  121. CFFDEBUG { ( ) print dup = } if
  122. } {
  123. 0
  124. CFFDEBUG { ( Out of range access, assuming 0) = } if
  125. /pdfformaterror where {
  126. pop
  127. ( **** Warning: Out of range access to a CFF table, assuming 0.\n)
  128. pdfformaterror
  129. } if
  130. } ifelse
  131. } .internalbind def
  132. /next2 { % - next2 <byte1> <byte2>
  133. f read {
  134. f read {
  135. 2 advance
  136. CFFDEBUG { ( ) print 1 index =only (,) print dup = } if
  137. } {
  138. 1 advance
  139. CFFDEBUG { ( ) print dup = } if
  140. } ifelse
  141. } if
  142. } .internalbind def
  143. /nextstring { % <length> nextstring <string>
  144. dup 0 eq {
  145. pop ()
  146. } {
  147. string f exch readstring pop dup length advance
  148. CFFDEBUG { ( ) print dup //== exec } if
  149. } ifelse
  150. } .internalbind def
  151. /card8 % - card8 <card8>
  152. /next load
  153. def
  154. /card16 { % - card16 <card16>
  155. next2 exch 8 bitshift add
  156. } .internalbind def
  157. /card32 { % - card32 <card32>
  158. card16 16 bitshift card16 add
  159. } .internalbind def
  160. /offsetprocs [
  161. /card8 load
  162. /card16 load
  163. { card8 16 bitshift card16 add } .internalbind
  164. /card32 load
  165. ] readonly def
  166. /offsetproc { % <offsize> offsetproc <proc>
  167. 1 sub //offsetprocs exch get
  168. } .internalbind def
  169. /offset { % <offsize> offset <offset>
  170. offsetproc exec
  171. } .internalbind def
  172. /sid % - <sid> sid
  173. /card16 load
  174. def
  175. % ------ Main program ------ %
  176. % We need to pass the file as a parameter for the sake of the PDF
  177. % interpreter. Also for the sake of PDF, a flag forces the font
  178. % to be defined as <resname> instead of the name embedded in the data.
  179. % This is needed for subsetted fonts; it is valid if the CFF
  180. % contains only a single font.
  181. % Finally, PDF interpreter may request creation of CIDFont out of an
  182. % ordinary CFF font.
  183. /StartData { % <resname> <nbytes> StartData -
  184. currentfile exch subfilefilter //false //false ReadData pop
  185. } .internalbind def
  186. /ReadData { % <resname> <file> <forceresname> <forcecid> ReadData <fontset>
  187. % Initialize.
  188. 30 dict begin
  189. /forcecidfont exch def
  190. /forceresname exch def
  191. /cff exch def
  192. /pos 0 def
  193. /resname exch cvlit def
  194. /DEBUG CFFDEBUG def % bring the binding closer
  195. /StringCache 1 dict def % Private DICT may be reused.
  196. forcecidfont
  197. [ { cff 1024 string readstring not { exit } if } loop ]
  198. .parsecff /fonts exch def
  199. resname
  200. mark fonts {
  201. forceresname { exch pop resname exch } if
  202. dup /CIDFontType known { % This is a CIDFont.
  203. dup /CIDFontName 3 index put
  204. 1 index exch /CIDFont defineresource
  205. } { % This is a font.
  206. dup /FontName 3 index put
  207. dup /FontType 2 put
  208. 1 index exch
  209. definefont
  210. } ifelse
  211. } forall .dicttomark
  212. end % temporary dict
  213. end % FontSetInit ProcSet
  214. /FontSet defineresource
  215. } .internalbind def
  216. % ---------------- Resource category definition ---------------- %
  217. currentdict end readonly
  218. languagelevel exch 2 .setlanguagelevel
  219. /FontSet /Generic /Category findresource dup length dict .copydict
  220. /Category defineresource pop
  221. /FontSetInit exch /ProcSet defineresource pop
  222. .setlanguagelevel