CFF.cpp 39 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147
  1. /*
  2. * Copyright (c) 2023, Rodrigo Tobar <rtobarc@gmail.com>.
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. // CFF spec: https://adobe-type-tools.github.io/font-tech-notes/pdfs/5176.CFF.pdf
  7. #include <AK/Debug.h>
  8. #include <AK/Endian.h>
  9. #include <AK/String.h>
  10. #include <LibGfx/Forward.h>
  11. #include <LibPDF/Encoding.h>
  12. #include <LibPDF/Error.h>
  13. #include <LibPDF/Fonts/CFF.h>
  14. namespace PDF {
  15. // The built-in encodings map codes to SIDs.
  16. // CFF spec, "Appendix B Predefined Encodings, Standard Encoding"
  17. // clang-format off
  18. static constexpr Array s_predefined_encoding_standard = to_array<CFF::SID>({
  19. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  20. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
  21. 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
  22. 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
  23. 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
  24. 90, 91, 92, 93, 94, 95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  25. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 0, 111, 112,
  26. 113, 114, 0, 115, 116, 117, 118, 119, 120, 121, 122, 0, 123, 0, 124, 125, 126, 127, 128, 129, 130, 131, 0, 132, 133, 0, 134, 135, 136,
  27. 137, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138, 0, 139, 0, 0, 0, 0, 140, 141, 142, 143, 0,
  28. 0, 0, 0, 0, 144, 0, 0,
  29. 0, 145, 0, 0, 146, 147, 148,
  30. 149, 0, 0, 0, 0,
  31. });
  32. static_assert(s_predefined_encoding_standard.size() == 256);
  33. // clang-format on
  34. // CFF spec, "Appendix B Predefined Encodings, Expert Encoding"
  35. // clang-format off
  36. static constexpr Array s_predefined_encoding_expert = to_array<CFF::SID>({
  37. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  38. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 229, 230, 0,
  39. 231, 232, 233, 234, 235, 236, 237, 238, 13, 14, 15, 99, 239, 240, 241, 242, 243, 244,
  40. 245, 246, 247, 248, 27, 28, 249, 250, 251, 252, 0, 253, 254, 255, 256, 257, 0, 0, 0, 258, 0, 0, 259, 260, 261, 262, 0, 0, 263,
  41. 264, 265, 0, 266, 109, 110, 267, 268, 269, 0, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288,
  42. 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  43. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 304, 305, 306, 0, 0, 307, 308, 309, 310,
  44. 311, 0, 312, 0, 0, 313, 0, 0, 314, 315, 0, 0, 316, 317, 318, 0, 0, 0, 158, 155, 163, 319, 320, 321, 322, 323, 324, 325, 0,
  45. 0, 326, 150, 164, 169, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350,
  46. 351, 352, 353, 354, 355, 356, 357, 358, 359, 360,
  47. 361, 362, 363, 364, 365, 366, 367, 368, 369, 370,
  48. 371, 372, 373, 374, 375, 376, 377, 378,
  49. });
  50. static_assert(s_predefined_encoding_expert.size() == 256);
  51. // clang-format on
  52. // Charsets map GIDs to SIDs.
  53. // CFF spec, "Appendix C Predefined Charsets, Expert"
  54. // clang-format off
  55. static constexpr auto s_predefined_charset_expert = to_array<CFF::SID>({
  56. 1, 229, 230, 231, 232,
  57. 233, 234, 235, 236, 237,
  58. 238, 13, 14, 15, 99,
  59. 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 27, 28, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 109, 110,
  60. 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298,
  61. 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 158, 155, 163, 319, 320, 321, 322, 323, 324, 325, 326, 150,
  62. 164, 169, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342,
  63. 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360,
  64. 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378,
  65. });
  66. // clang-format on
  67. // CFF spec, "Appendix C Predefined Charsets, Expert Subset"
  68. // clang-format off
  69. static constexpr auto s_predefined_charset_expert_subset = to_array<CFF::SID>({
  70. 1, 231, 232, 235, 236, 237, 238, 13, 14, 15, 99,
  71. 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 27,
  72. 28, 249, 250, 251, 253, 254, 255, 256, 257, 258, 259,
  73. 260, 261, 262, 263, 264, 265, 266, 109, 110, 267, 268, 269, 270, 272, 300, 301, 302, 305,
  74. 314, 315, 158, 155, 163, 320, 321, 322, 323, 324, 325, 326, 150, 164, 169, 327, 328, 329,
  75. 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346,
  76. });
  77. // clang-format on
  78. PDFErrorOr<NonnullRefPtr<CFF>> CFF::create(ReadonlyBytes const& cff_bytes, RefPtr<Encoding> encoding)
  79. {
  80. FixedMemoryStream reader(cff_bytes);
  81. // CFF spec, "6 Header"
  82. // skip major, minor version
  83. TRY(reader.discard(2));
  84. auto header_size = TRY(reader.read_value<Card8>());
  85. // skip offset size
  86. TRY(reader.discard(1));
  87. TRY(reader.seek(header_size));
  88. // CFF spec, "7 Name INDEX"
  89. Vector<String> font_names;
  90. TRY(parse_index(reader, [&](ReadonlyBytes const& data) -> PDFErrorOr<void> {
  91. auto font_name = TRY(String::from_utf8(data));
  92. dbgln_if(CFF_DEBUG, "CFF font name '{}'", font_name);
  93. return TRY(font_names.try_append(font_name));
  94. }));
  95. if (font_names.size() != 1)
  96. return error("CFFs with more than one font not yet implemented");
  97. auto cff = adopt_ref(*new CFF());
  98. cff->set_font_matrix({ 0.001f, 0.0f, 0.0f, 0.001f, 0.0f, 0.0f });
  99. auto top_dicts = TRY(parse_top_dicts(reader, cff_bytes));
  100. if (top_dicts.size() != 1)
  101. return error("CFFs with more than one font not yet implemented");
  102. auto const& top_dict = top_dicts[0];
  103. if (top_dict.is_cid_keyed) {
  104. // CFF spec, "18 CID-keyed Fonts"
  105. // "* The FDArray operator is expected to be present"
  106. if (top_dict.fdarray_offset == 0)
  107. return error("CID-keyed CFFs must have an FDArray");
  108. // "* The charset data, although in the same format as non-CIDFonts, will represent CIDs rather than SIDs"
  109. // (Done below.)
  110. // "* The Top DICT will include an FDSelect operator"
  111. if (top_dict.fdselect_offset == 0)
  112. return error("CID-keyed CFFs must have FDSelect");
  113. // "* no Encoding operator will be present and the default StandardEncoding should not be applied"
  114. if (top_dict.encoding_offset != 0)
  115. return error("CID-keyed CFFs must not have Encoding");
  116. cff->set_kind(CFF::Kind::CIDKeyed);
  117. }
  118. auto strings = TRY(parse_strings(reader));
  119. // CFF spec "16 Local/Global Subrs INDEXes"
  120. // "Global subrs are stored in an INDEX structure which follows the String INDEX."
  121. Vector<ByteBuffer> global_subroutines;
  122. TRY(parse_index(reader, [&](ReadonlyBytes const& subroutine_bytes) -> PDFErrorOr<void> {
  123. return TRY(global_subroutines.try_append(TRY(ByteBuffer::copy(subroutine_bytes))));
  124. }));
  125. dbgln_if(CFF_DEBUG, "CFF has {} gsubr entries", global_subroutines.size());
  126. // Create glyphs (now that we have the subroutines) and associate missing information to store them and their encoding
  127. auto glyphs = TRY(parse_charstrings(FixedMemoryStream(cff_bytes.slice(top_dict.charstrings_offset)), top_dict.local_subroutines, global_subroutines));
  128. // CFF spec, "Table 16 Encoding ID"
  129. // FIXME: Only read this if the built-in encoding is actually needed? (ie. `if (!encoding)`)
  130. Vector<u8> encoding_codes; // Maps GID to its codepoint.
  131. HashMap<Card8, SID> encoding_supplemental; // Maps codepoint to SID.
  132. if (!top_dict.is_cid_keyed) {
  133. switch (top_dict.encoding_offset) {
  134. case 0:
  135. dbgln_if(CFF_DEBUG, "CFF predefined encoding Standard");
  136. for (size_t i = 1; i < s_predefined_encoding_standard.size(); ++i)
  137. TRY(encoding_supplemental.try_set(i, s_predefined_encoding_standard[i]));
  138. break;
  139. case 1:
  140. dbgln_if(CFF_DEBUG, "CFF predefined encoding Expert");
  141. for (size_t i = 1; i < s_predefined_encoding_expert.size(); ++i)
  142. TRY(encoding_supplemental.try_set(i, s_predefined_encoding_expert[i]));
  143. break;
  144. default:
  145. encoding_codes = TRY(parse_encoding(FixedMemoryStream(cff_bytes.slice(top_dict.encoding_offset)), encoding_supplemental));
  146. break;
  147. }
  148. }
  149. // CFF spec, "Table 22 Charset ID"
  150. Vector<SID> charset; // Maps GID to CIDs for CID-keyed, to SIDs otherwise.
  151. Vector<DeprecatedFlyString> charset_names; // Only valid for non-CID-keyed fonts.
  152. if (top_dict.is_cid_keyed) {
  153. charset = TRY(parse_charset(FixedMemoryStream { cff_bytes.slice(top_dict.charset_offset) }, glyphs.size()));
  154. } else {
  155. switch (top_dict.charset_offset) {
  156. case 0:
  157. dbgln_if(CFF_DEBUG, "CFF predefined charset ISOAdobe");
  158. // CFF spec, "Appendix C Predefined Charsets, ISOAdobe"
  159. for (SID sid = 1; sid <= 228; sid++)
  160. TRY(charset_names.try_append(resolve_sid(sid, strings)));
  161. break;
  162. case 1:
  163. dbgln_if(CFF_DEBUG, "CFF predefined charset Expert");
  164. for (SID sid : s_predefined_charset_expert)
  165. TRY(charset_names.try_append(resolve_sid(sid, strings)));
  166. break;
  167. case 2:
  168. dbgln_if(CFF_DEBUG, "CFF predefined charset Expert Subset");
  169. for (SID sid : s_predefined_charset_expert_subset)
  170. TRY(charset_names.try_append(resolve_sid(sid, strings)));
  171. break;
  172. default: {
  173. charset = TRY(parse_charset(FixedMemoryStream { cff_bytes.slice(top_dict.charset_offset) }, glyphs.size()));
  174. for (SID sid : charset)
  175. TRY(charset_names.try_append(resolve_sid(sid, strings)));
  176. break;
  177. }
  178. }
  179. }
  180. // CFF spec, "18 CID-keyed Fonts"
  181. Vector<TopDict> font_dicts;
  182. if (top_dict.fdarray_offset != 0) {
  183. FixedMemoryStream fdarray_reader { cff_bytes.slice(top_dict.fdarray_offset) };
  184. font_dicts = TRY(parse_top_dicts(fdarray_reader, cff_bytes));
  185. dbgln_if(CFF_DEBUG, "CFF has {} FDArray entries", font_dicts.size());
  186. }
  187. // CFF spec, "19 FDSelect"
  188. Vector<u8> fdselect;
  189. if (top_dict.fdselect_offset != 0) {
  190. fdselect = TRY(parse_fdselect(FixedMemoryStream { cff_bytes.slice(top_dict.fdselect_offset) }, glyphs.size()));
  191. dbgln_if(CFF_DEBUG, "CFF has {} FDSelect entries", fdselect.size());
  192. }
  193. // Adjust glyphs' widths as they are deltas from nominalWidthX
  194. for (size_t glyph_id = 0; glyph_id < glyphs.size(); glyph_id++) {
  195. auto& glyph = glyphs[glyph_id];
  196. if (!glyph.has_width()) {
  197. auto default_width = top_dict.defaultWidthX.value_or(0.0f);
  198. if (top_dict.is_cid_keyed)
  199. default_width = font_dicts[fdselect[glyph_id]].defaultWidthX.value_or(default_width);
  200. glyph.set_width(default_width);
  201. } else {
  202. auto nominal_width = top_dict.nominalWidthX.value_or(0.0f);
  203. if (top_dict.is_cid_keyed)
  204. nominal_width = font_dicts[fdselect[glyph_id]].nominalWidthX.value_or(nominal_width);
  205. glyph.set_width(glyph.width() + nominal_width);
  206. }
  207. }
  208. for (size_t i = 0; i < glyphs.size(); i++) {
  209. if (i == 0) {
  210. if (top_dict.is_cid_keyed) {
  211. // FIXME: Do better than printing the cid to a string.
  212. auto cid = 0;
  213. TRY(cff->add_glyph(ByteString::formatted("{}", cid), move(glyphs[0])));
  214. } else {
  215. TRY(cff->add_glyph(".notdef", move(glyphs[0])));
  216. }
  217. continue;
  218. }
  219. if (top_dict.is_cid_keyed) {
  220. // FIXME: Do better than printing the cid to a string.
  221. auto cid = charset[i - 1];
  222. TRY(cff->add_glyph(ByteString::formatted("{}", cid), move(glyphs[i])));
  223. } else {
  224. auto const& name = charset_names[i - 1];
  225. TRY(cff->add_glyph(name, move(glyphs[i])));
  226. }
  227. }
  228. cff->consolidate_glyphs();
  229. // Encoding given or read
  230. if (encoding) {
  231. dbgln_if(CFF_DEBUG, "CFF using external encoding");
  232. cff->set_encoding(move(encoding));
  233. } else if (!top_dict.is_cid_keyed) {
  234. dbgln_if(CFF_DEBUG, "CFF using embedded encoding");
  235. auto encoding = Encoding::create();
  236. for (size_t i = 0; i < glyphs.size(); i++) {
  237. if (i == 0) {
  238. encoding->set(0, ".notdef");
  239. continue;
  240. }
  241. if (i - 1 >= encoding_codes.size() || i - 1 >= charset_names.size()) {
  242. dbgln("CFF: No encoding for glyph {} onwards, encoding_codes size {} charset_names size {}", i, encoding_codes.size(), charset_names.size());
  243. break;
  244. }
  245. auto code = encoding_codes[i - 1];
  246. auto char_name = charset_names[i - 1];
  247. encoding->set(code, char_name);
  248. }
  249. for (auto const& entry : encoding_supplemental)
  250. encoding->set(entry.key, resolve_sid(entry.value, strings));
  251. cff->set_encoding(move(encoding));
  252. }
  253. return cff;
  254. }
  255. PDFErrorOr<Vector<CFF::TopDict>> CFF::parse_top_dicts(FixedMemoryStream& reader, ReadonlyBytes const& cff_bytes)
  256. {
  257. Vector<TopDict> top_dicts;
  258. TRY(parse_index(reader, [&](ReadonlyBytes const& element_data) -> PDFErrorOr<void> {
  259. TopDict top_dict;
  260. FixedMemoryStream element_reader { element_data };
  261. TRY(parse_dict<TopDictOperator>(element_reader, [&](TopDictOperator op, Vector<DictOperand> const& operands) -> PDFErrorOr<void> {
  262. switch (op) {
  263. case TopDictOperator::Version:
  264. case TopDictOperator::Notice:
  265. case TopDictOperator::FullName:
  266. case TopDictOperator::FamilyName:
  267. case TopDictOperator::Weight:
  268. case TopDictOperator::FontBBox:
  269. case TopDictOperator::UniqueID:
  270. case TopDictOperator::XUID:
  271. case TopDictOperator::Copyright:
  272. case TopDictOperator::IsFixedPitch:
  273. case TopDictOperator::ItalicAngle:
  274. case TopDictOperator::UnderlinePosition:
  275. case TopDictOperator::UnderlineThickness:
  276. case TopDictOperator::PaintType:
  277. case TopDictOperator::FontMatrix:
  278. case TopDictOperator::StrokeWidth:
  279. case TopDictOperator::PostScript:
  280. case TopDictOperator::BaseFontName:
  281. case TopDictOperator::BaseFontBlend:
  282. break;
  283. case TopDictOperator::CharstringType: {
  284. int charstring_type = 2;
  285. if (!operands.is_empty())
  286. charstring_type = operands[0].get<int>();
  287. if (charstring_type != 2)
  288. dbgln("CFF: has unimplemented CharstringType, might not look right");
  289. break;
  290. }
  291. case TopDictOperator::SyntheticBase:
  292. dbgln("CFF: has unimplemented SyntheticBase, might not look right");
  293. break;
  294. case TopDictOperator::Encoding: {
  295. if (!operands.is_empty())
  296. top_dict.encoding_offset = operands[0].get<int>();
  297. break;
  298. }
  299. case TopDictOperator::Charset: {
  300. if (!operands.is_empty())
  301. top_dict.charset_offset = operands[0].get<int>();
  302. break;
  303. }
  304. case TopDictOperator::CharStrings: {
  305. if (!operands.is_empty())
  306. top_dict.charstrings_offset = operands[0].get<int>();
  307. break;
  308. }
  309. case TopDictOperator::Private: {
  310. auto private_dict_size = operands[0].get<int>();
  311. auto private_dict_offset = operands[1].get<int>();
  312. FixedMemoryStream priv_dict_reader { cff_bytes.slice(private_dict_offset, private_dict_size) };
  313. TRY(parse_dict<PrivDictOperator>(priv_dict_reader, [&](PrivDictOperator op, Vector<DictOperand> const& operands) -> PDFErrorOr<void> {
  314. switch (op) {
  315. case PrivDictOperator::BlueValues:
  316. case PrivDictOperator::OtherBlues:
  317. case PrivDictOperator::FamilyBlues:
  318. case PrivDictOperator::FamilyOtherBlues:
  319. case PrivDictOperator::BlueScale:
  320. case PrivDictOperator::BlueShift:
  321. case PrivDictOperator::BlueFuzz:
  322. case PrivDictOperator::StemSnapH:
  323. case PrivDictOperator::StemSnapV:
  324. case PrivDictOperator::ForceBold:
  325. case PrivDictOperator::LanguageGroup:
  326. case PrivDictOperator::ExpansionFactor:
  327. case PrivDictOperator::InitialRandomSeed:
  328. // Ignore hinting-related operators for now.
  329. break;
  330. case PrivDictOperator::StdHW:
  331. case PrivDictOperator::StdVW:
  332. // FIXME: What do these do?
  333. break;
  334. case PrivDictOperator::Subrs: {
  335. // CFF spec, "16 Local/Global Subrs INDEXes"
  336. // "Local subrs are stored in an INDEX structure which is located via the offset operand of the Subrs operator in the Private DICT."
  337. auto subrs_offset = operands[0].get<int>();
  338. FixedMemoryStream subrs_reader { cff_bytes.slice(private_dict_offset + subrs_offset) };
  339. TRY(parse_index(subrs_reader, [&](ReadonlyBytes const& subroutine_bytes) -> PDFErrorOr<void> {
  340. return TRY(top_dict.local_subroutines.try_append(TRY(ByteBuffer::copy(subroutine_bytes))));
  341. }));
  342. dbgln_if(CFF_DEBUG, "CFF has {} subr entries", top_dict.local_subroutines.size());
  343. break;
  344. }
  345. case PrivDictOperator::DefaultWidthX:
  346. if (!operands.is_empty())
  347. top_dict.defaultWidthX = to_number(operands[0]);
  348. break;
  349. case PrivDictOperator::NominalWidthX:
  350. if (!operands.is_empty())
  351. top_dict.nominalWidthX = to_number(operands[0]);
  352. break;
  353. default:
  354. dbgln("CFF: Unhandled private dict entry {}", static_cast<int>(op));
  355. }
  356. return {};
  357. }));
  358. break;
  359. }
  360. case TopDictOperator::RegistryOrderingSupplement:
  361. // CFF Spec, "18 CID-keyed Fonts"
  362. // "The Top DICT begins with ROS operator which specifies the Registry-Ordering-Supplement for the font.
  363. // This will indicate to a CFF parser that special CID processing should be applied to this font."
  364. top_dict.is_cid_keyed = true;
  365. break;
  366. case TopDictOperator::FDSelect:
  367. if (!operands.is_empty())
  368. top_dict.fdselect_offset = operands[0].get<int>();
  369. break;
  370. case TopDictOperator::FDArray:
  371. if (!operands.is_empty())
  372. top_dict.fdarray_offset = operands[0].get<int>();
  373. break;
  374. case TopDictOperator::CIDFontVersion:
  375. case TopDictOperator::CIDFontRevision:
  376. case TopDictOperator::CIDFontType:
  377. case TopDictOperator::CIDCount:
  378. case TopDictOperator::UIDBase:
  379. case TopDictOperator::FontName:
  380. // Keys for CID-keyed fonts that we don't need, at least at the moment.
  381. break;
  382. default:
  383. dbgln("CFF: Unhandled top dict entry {}", static_cast<int>(op));
  384. }
  385. return {};
  386. }));
  387. top_dicts.append((move(top_dict)));
  388. return {};
  389. }));
  390. return top_dicts;
  391. }
  392. /// Appendix A: Standard Strings
  393. static constexpr Array s_cff_builtin_names {
  394. ".notdef"sv,
  395. "space"sv,
  396. "exclam"sv,
  397. "quotedbl"sv,
  398. "numbersign"sv,
  399. "dollar"sv,
  400. "percent"sv,
  401. "ampersand"sv,
  402. "quoteright"sv,
  403. "parenleft"sv,
  404. "parenright"sv,
  405. "asterisk"sv,
  406. "plus"sv,
  407. "comma"sv,
  408. "hyphen"sv,
  409. "period"sv,
  410. "slash"sv,
  411. "zero"sv,
  412. "one"sv,
  413. "two"sv,
  414. "three"sv,
  415. "four"sv,
  416. "five"sv,
  417. "six"sv,
  418. "seven"sv,
  419. "eight"sv,
  420. "nine"sv,
  421. "colon"sv,
  422. "semicolon"sv,
  423. "less"sv,
  424. "equal"sv,
  425. "greater"sv,
  426. "question"sv,
  427. "at"sv,
  428. "A"sv,
  429. "B"sv,
  430. "C"sv,
  431. "D"sv,
  432. "E"sv,
  433. "F"sv,
  434. "G"sv,
  435. "H"sv,
  436. "I"sv,
  437. "J"sv,
  438. "K"sv,
  439. "L"sv,
  440. "M"sv,
  441. "N"sv,
  442. "O"sv,
  443. "P"sv,
  444. "Q"sv,
  445. "R"sv,
  446. "S"sv,
  447. "T"sv,
  448. "U"sv,
  449. "V"sv,
  450. "W"sv,
  451. "X"sv,
  452. "Y"sv,
  453. "Z"sv,
  454. "bracketleft"sv,
  455. "backslash"sv,
  456. "bracketright"sv,
  457. "asciicircum"sv,
  458. "underscore"sv,
  459. "quoteleft"sv,
  460. "a"sv,
  461. "b"sv,
  462. "c"sv,
  463. "d"sv,
  464. "e"sv,
  465. "f"sv,
  466. "g"sv,
  467. "h"sv,
  468. "i"sv,
  469. "j"sv,
  470. "k"sv,
  471. "l"sv,
  472. "m"sv,
  473. "n"sv,
  474. "o"sv,
  475. "p"sv,
  476. "q"sv,
  477. "r"sv,
  478. "s"sv,
  479. "t"sv,
  480. "u"sv,
  481. "v"sv,
  482. "w"sv,
  483. "x"sv,
  484. "y"sv,
  485. "z"sv,
  486. "braceleft"sv,
  487. "bar"sv,
  488. "braceright"sv,
  489. "asciitilde"sv,
  490. "exclamdown"sv,
  491. "cent"sv,
  492. "sterling"sv,
  493. "fraction"sv,
  494. "yen"sv,
  495. "florin"sv,
  496. "section"sv,
  497. "currency"sv,
  498. "quotesingle"sv,
  499. "quotedblleft"sv,
  500. "guillemotleft"sv,
  501. "guilsinglleft"sv,
  502. "guilsinglright"sv,
  503. "fi"sv,
  504. "fl"sv,
  505. "endash"sv,
  506. "dagger"sv,
  507. "daggerdbl"sv,
  508. "periodcentered"sv,
  509. "paragraph"sv,
  510. "bullet"sv,
  511. "quotesinglbase"sv,
  512. "quotedblbase"sv,
  513. "quotedblright"sv,
  514. "guillemotright"sv,
  515. "ellipsis"sv,
  516. "perthousand"sv,
  517. "questiondown"sv,
  518. "grave"sv,
  519. "acute"sv,
  520. "circumflex"sv,
  521. "tilde"sv,
  522. "macron"sv,
  523. "breve"sv,
  524. "dotaccent"sv,
  525. "dieresis"sv,
  526. "ring"sv,
  527. "cedilla"sv,
  528. "hungarumlaut"sv,
  529. "ogonek"sv,
  530. "caron"sv,
  531. "emdash"sv,
  532. "AE"sv,
  533. "ordfeminine"sv,
  534. "Lslash"sv,
  535. "Oslash"sv,
  536. "OE"sv,
  537. "ordmasculine"sv,
  538. "ae"sv,
  539. "dotlessi"sv,
  540. "lslash"sv,
  541. "oslash"sv,
  542. "oe"sv,
  543. "germandbls"sv,
  544. "onesuperior"sv,
  545. "logicalnot"sv,
  546. "mu"sv,
  547. "trademark"sv,
  548. "Eth"sv,
  549. "onehalf"sv,
  550. "plusminus"sv,
  551. "Thorn"sv,
  552. "onequarter"sv,
  553. "divide"sv,
  554. "brokenbar"sv,
  555. "degree"sv,
  556. "thorn"sv,
  557. "threequarters"sv,
  558. "twosuperior"sv,
  559. "registered"sv,
  560. "minus"sv,
  561. "eth"sv,
  562. "multiply"sv,
  563. "threesuperior"sv,
  564. "copyright"sv,
  565. "Aacute"sv,
  566. "Acircumflex"sv,
  567. "Adieresis"sv,
  568. "Agrave"sv,
  569. "Aring"sv,
  570. "Atilde"sv,
  571. "Ccedilla"sv,
  572. "Eacute"sv,
  573. "Ecircumflex"sv,
  574. "Edieresis"sv,
  575. "Egrave"sv,
  576. "Iacute"sv,
  577. "Icircumflex"sv,
  578. "Idieresis"sv,
  579. "Igrave"sv,
  580. "Ntilde"sv,
  581. "Oacute"sv,
  582. "Ocircumflex"sv,
  583. "Odieresis"sv,
  584. "Ograve"sv,
  585. "Otilde"sv,
  586. "Scaron"sv,
  587. "Uacute"sv,
  588. "Ucircumflex"sv,
  589. "Udieresis"sv,
  590. "Ugrave"sv,
  591. "Yacute"sv,
  592. "Ydieresis"sv,
  593. "Zcaron"sv,
  594. "aacute"sv,
  595. "acircumflex"sv,
  596. "adieresis"sv,
  597. "agrave"sv,
  598. "aring"sv,
  599. "atilde"sv,
  600. "ccedilla"sv,
  601. "eacute"sv,
  602. "ecircumflex"sv,
  603. "edieresis"sv,
  604. "egrave"sv,
  605. "iacute"sv,
  606. "icircumflex"sv,
  607. "idieresis"sv,
  608. "igrave"sv,
  609. "ntilde"sv,
  610. "oacute"sv,
  611. "ocircumflex"sv,
  612. "odieresis"sv,
  613. "ograve"sv,
  614. "otilde"sv,
  615. "scaron"sv,
  616. "uacute"sv,
  617. "ucircumflex"sv,
  618. "udieresis"sv,
  619. "ugrave"sv,
  620. "yacute"sv,
  621. "ydieresis"sv,
  622. "zcaron"sv,
  623. "exclamsmall"sv,
  624. "Hungarumlautsmall"sv,
  625. "dollaroldstyle"sv,
  626. "dollarsuperior"sv,
  627. "ampersandsmall"sv,
  628. "Acutesmall"sv,
  629. "parenleftsuperior"sv,
  630. "parenrightsuperior"sv,
  631. "twodotenleader"sv,
  632. "onedotenleader"sv,
  633. "zerooldstyle"sv,
  634. "oneoldstyle"sv,
  635. "twooldstyle"sv,
  636. "threeoldstyle"sv,
  637. "fouroldstyle"sv,
  638. "fiveoldstyle"sv,
  639. "sixoldstyle"sv,
  640. "sevenoldstyle"sv,
  641. "eightoldstyle"sv,
  642. "nineoldstyle"sv,
  643. "commasuperior"sv,
  644. "threequartersemdash"sv,
  645. "periodsuperior"sv,
  646. "questionsmall"sv,
  647. "asuperior"sv,
  648. "bsuperior"sv,
  649. "centsuperior"sv,
  650. "dsuperior"sv,
  651. "esuperior"sv,
  652. "isuperior"sv,
  653. "lsuperior"sv,
  654. "msuperior"sv,
  655. "nsuperior"sv,
  656. "osuperior"sv,
  657. "rsuperior"sv,
  658. "ssuperior"sv,
  659. "tsuperior"sv,
  660. "ff"sv,
  661. "ffi"sv,
  662. "ffl"sv,
  663. "parenleftinferior"sv,
  664. "parenrightinferior"sv,
  665. "Circumflexsmall"sv,
  666. "hyphensuperior"sv,
  667. "Gravesmall"sv,
  668. "Asmall"sv,
  669. "Bsmall"sv,
  670. "Csmall"sv,
  671. "Dsmall"sv,
  672. "Esmall"sv,
  673. "Fsmall"sv,
  674. "Gsmall"sv,
  675. "Hsmall"sv,
  676. "Ismall"sv,
  677. "Jsmall"sv,
  678. "Ksmall"sv,
  679. "Lsmall"sv,
  680. "Msmall"sv,
  681. "Nsmall"sv,
  682. "Osmall"sv,
  683. "Psmall"sv,
  684. "Qsmall"sv,
  685. "Rsmall"sv,
  686. "Ssmall"sv,
  687. "Tsmall"sv,
  688. "Usmall"sv,
  689. "Vsmall"sv,
  690. "Wsmall"sv,
  691. "Xsmall"sv,
  692. "Ysmall"sv,
  693. "Zsmall"sv,
  694. "colonmonetary"sv,
  695. "onefitted"sv,
  696. "rupiah"sv,
  697. "Tildesmall"sv,
  698. "exclamdownsmall"sv,
  699. "centoldstyle"sv,
  700. "Lslashsmall"sv,
  701. "Scaronsmall"sv,
  702. "Zcaronsmall"sv,
  703. "Dieresissmall"sv,
  704. "Brevesmall"sv,
  705. "Caronsmall"sv,
  706. "Dotaccentsmall"sv,
  707. "Macronsmall"sv,
  708. "figuredash"sv,
  709. "hypheninferior"sv,
  710. "Ogoneksmall"sv,
  711. "Ringsmall"sv,
  712. "Cedillasmall"sv,
  713. "questiondownsmall"sv,
  714. "oneeighth"sv,
  715. "threeeighths"sv,
  716. "fiveeighths"sv,
  717. "seveneighths"sv,
  718. "onethird"sv,
  719. "twothirds"sv,
  720. "zerosuperior"sv,
  721. "foursuperior"sv,
  722. "fivesuperior"sv,
  723. "sixsuperior"sv,
  724. "sevensuperior"sv,
  725. "eightsuperior"sv,
  726. "ninesuperior"sv,
  727. "zeroinferior"sv,
  728. "oneinferior"sv,
  729. "twoinferior"sv,
  730. "threeinferior"sv,
  731. "fourinferior"sv,
  732. "fiveinferior"sv,
  733. "sixinferior"sv,
  734. "seveninferior"sv,
  735. "eightinferior"sv,
  736. "nineinferior"sv,
  737. "centinferior"sv,
  738. "dollarinferior"sv,
  739. "periodinferior"sv,
  740. "commainferior"sv,
  741. "Agravesmall"sv,
  742. "Aacutesmall"sv,
  743. "Acircumflexsmall"sv,
  744. "Atildesmall"sv,
  745. "Adieresissmall"sv,
  746. "Aringsmall"sv,
  747. "AEsmall"sv,
  748. "Ccedillasmall"sv,
  749. "Egravesmall"sv,
  750. "Eacutesmall"sv,
  751. "Ecircumflexsmall"sv,
  752. "Edieresissmall"sv,
  753. "Igravesmall"sv,
  754. "Iacutesmall"sv,
  755. "Icircumflexsmall"sv,
  756. "Idieresissmall"sv,
  757. "Ethsmall"sv,
  758. "Ntildesmall"sv,
  759. "Ogravesmall"sv,
  760. "Oacutesmall"sv,
  761. "Ocircumflexsmall"sv,
  762. "Otildesmall"sv,
  763. "Odieresissmall"sv,
  764. "OEsmall"sv,
  765. "Oslashsmall"sv,
  766. "Ugravesmall"sv,
  767. "Uacutesmall"sv,
  768. "Ucircumflexsmall"sv,
  769. "Udieresissmall"sv,
  770. "Yacutesmall"sv,
  771. "Thornsmall"sv,
  772. "Ydieresissmall"sv,
  773. "001.000"sv,
  774. "001.001"sv,
  775. "001.002"sv,
  776. "001.003"sv,
  777. "Black"sv,
  778. "Bold"sv,
  779. "Book"sv,
  780. "Light"sv,
  781. "Medium"sv,
  782. "Regular"sv,
  783. "Roman"sv,
  784. "Semibold"sv,
  785. };
  786. PDFErrorOr<Vector<StringView>> CFF::parse_strings(FixedMemoryStream& reader)
  787. {
  788. // CFF spec "10 String Index"
  789. Vector<StringView> strings;
  790. TRY(parse_index(reader, [&](ReadonlyBytes const& string) -> PDFErrorOr<void> {
  791. return TRY(strings.try_append(string));
  792. }));
  793. dbgln_if(CFF_DEBUG, "CFF has {} additional strings in string table", strings.size());
  794. return strings;
  795. }
  796. DeprecatedFlyString CFF::resolve_sid(SID sid, Vector<StringView> const& strings)
  797. {
  798. if (sid < s_cff_builtin_names.size())
  799. return DeprecatedFlyString(s_cff_builtin_names[sid]);
  800. if (sid - s_cff_builtin_names.size() < strings.size())
  801. return DeprecatedFlyString(strings[sid - s_cff_builtin_names.size()]);
  802. dbgln("Couldn't find string for SID {}, going with space", sid);
  803. return DeprecatedFlyString("space");
  804. }
  805. PDFErrorOr<Vector<CFF::SID>> CFF::parse_charset(Stream&& reader, size_t glyph_count)
  806. {
  807. // CFF spec, "13 Charsets"
  808. // Maps `GID - 1` to a SID (or CID, for CID-keyed fonts). The name of GID 0 is implicitly ".notdef".
  809. Vector<SID> names;
  810. auto format = TRY(reader.read_value<Card8>());
  811. if (format == 0) {
  812. // CFF spec, "Table 17 Format 0"
  813. dbgln_if(CFF_DEBUG, "CFF charset format 0");
  814. for (size_t i = 0; i < glyph_count - 1; i++) {
  815. SID sid = TRY(reader.read_value<BigEndian<SID>>());
  816. TRY(names.try_append(sid));
  817. }
  818. } else if (format == 1) {
  819. // CFF spec, "Table 18 Format 1"
  820. dbgln_if(CFF_DEBUG, "CFF charset format 1");
  821. while (names.size() < glyph_count - 1) {
  822. // CFF spec, "Table 19 Range1 Format (Charset)"
  823. auto first_sid = TRY(reader.read_value<BigEndian<SID>>());
  824. int left = TRY(reader.read_value<Card8>());
  825. for (SID sid = first_sid; left >= 0; left--, sid++)
  826. TRY(names.try_append(sid));
  827. }
  828. } else if (format == 2) {
  829. // CFF spec, "Table 20 Format 2"
  830. // "Format 2 differs from format 1 only in the size of the Left field in each range."
  831. dbgln_if(CFF_DEBUG, "CFF charset format 2");
  832. while (names.size() < glyph_count - 1) {
  833. // CFF spec, "Table 21 Range2 Format"
  834. auto first_sid = TRY(reader.read_value<BigEndian<SID>>());
  835. int left = TRY(reader.read_value<BigEndian<Card16>>());
  836. for (SID sid = first_sid; left >= 0; left--, sid++)
  837. TRY(names.try_append(sid));
  838. }
  839. } else {
  840. dbgln("CFF: Unknown charset format {}", format);
  841. }
  842. return names;
  843. }
  844. PDFErrorOr<Vector<u8>> CFF::parse_fdselect(Stream&& reader, size_t glyph_count)
  845. {
  846. Vector<u8> fd_selector_array; // Maps GIDs to their FD index.
  847. // CFF spec, "19 FDSelect"
  848. auto format = TRY(reader.read_value<Card8>());
  849. if (format == 0) {
  850. // CFF spec, "Table 27 Format 0"
  851. // "(This format is identical to charset format 0 except that the notdef glyph is included in this case.)"
  852. dbgln_if(CFF_DEBUG, "CFF fdselect format 0");
  853. fd_selector_array.ensure_capacity(glyph_count);
  854. for (size_t i = 0; i < glyph_count; i++)
  855. fd_selector_array.append(TRY(reader.read_value<Card8>()));
  856. } else if (format == 3) {
  857. // CFF spec, "Table 28 Format 3"
  858. dbgln_if(CFF_DEBUG, "CFF fdselect format 3");
  859. // The spec presents this as n "Card16 first; Card8 fd;" struct entries followed by a Char16 sentinel value.
  860. // But the code is shorter if we treat it as a Char16 start value followed by n "Card8 fd; Card16 end;" struct entries.
  861. Card16 n_ranges = TRY(reader.read_value<BigEndian<Card16>>());
  862. Card16 begin = TRY(reader.read_value<BigEndian<Card16>>());
  863. // "The first range must have a 'first' GID of 0."
  864. if (begin != 0)
  865. return error("CFF fdselect format 3 first range must have a 'first' GID of 0");
  866. for (Card16 i = 0; i < n_ranges; i++) {
  867. auto fd = TRY(reader.read_value<Card8>());
  868. auto end = TRY(reader.read_value<BigEndian<Card16>>());
  869. for (Card16 j = begin; j < end; j++)
  870. fd_selector_array.append(fd);
  871. begin = end;
  872. }
  873. // "The sentinel GID is set equal to the number of glyphs in the font."
  874. if (begin != glyph_count)
  875. return error("CFF fdselect format 3 last range must end at the number of glyphs in the font");
  876. } else {
  877. dbgln("CFF: Unknown fdselect format {}", format);
  878. }
  879. return fd_selector_array;
  880. }
  881. PDFErrorOr<Vector<CFF::Glyph>> CFF::parse_charstrings(FixedMemoryStream&& reader, Vector<ByteBuffer> const& local_subroutines, Vector<ByteBuffer> const& global_subroutines)
  882. {
  883. // CFF spec, "14 CharStrings INDEX"
  884. Vector<Glyph> glyphs;
  885. TRY(parse_index(reader, [&](ReadonlyBytes const& charstring_data) -> PDFErrorOr<void> {
  886. GlyphParserState state;
  887. auto glyph = TRY(parse_glyph(charstring_data, local_subroutines, global_subroutines, state, true));
  888. return TRY(glyphs.try_append(glyph));
  889. }));
  890. dbgln_if(CFF_DEBUG, "CFF has {} glyphs", glyphs.size());
  891. return glyphs;
  892. }
  893. PDFErrorOr<Vector<u8>> CFF::parse_encoding(Stream&& reader, HashMap<Card8, SID>& supplemental)
  894. {
  895. // CFF spec, "12 Encodings"
  896. Vector<u8> encoding_codes;
  897. auto format_raw = TRY(reader.read_value<Card8>());
  898. auto format = format_raw & 0x7f;
  899. if (format == 0) {
  900. // CFF spec, "Table 11 Format 0"
  901. auto n_codes = TRY(reader.read_value<Card8>());
  902. dbgln_if(CFF_DEBUG, "CFF encoding format 0, {} codes", n_codes);
  903. for (u8 i = 0; i < n_codes; i++) {
  904. TRY(encoding_codes.try_append(TRY(reader.read_value<Card8>())));
  905. }
  906. } else if (format == 1) {
  907. // CFF spec, "Table 12 Format 1"
  908. auto n_ranges = TRY(reader.read_value<Card8>());
  909. dbgln_if(CFF_DEBUG, "CFF encoding format 1, {} ranges", n_ranges);
  910. for (u8 i = 0; i < n_ranges; i++) {
  911. // CFF spec, "Table 13 Range1 Format (Encoding)"
  912. auto first_code = TRY(reader.read_value<Card8>());
  913. int left = TRY(reader.read_value<Card8>());
  914. for (u8 code = first_code; left >= 0; left--, code++)
  915. TRY(encoding_codes.try_append(code));
  916. }
  917. } else
  918. return error(ByteString::formatted("Invalid encoding format: {}", format));
  919. if (format_raw & 0x80) {
  920. // CFF spec, "Table 14 Supplemental Encoding Data"
  921. auto n_sups = TRY(reader.read_value<Card8>());
  922. dbgln_if(CFF_DEBUG, "CFF encoding, {} supplemental entries", n_sups);
  923. for (u8 i = 0; i < n_sups; i++) {
  924. // CFF spec, "Table 15 Supplement Format"
  925. auto code = TRY(reader.read_value<Card8>());
  926. SID name = TRY(reader.read_value<SID>());
  927. TRY(supplemental.try_set(code, name));
  928. }
  929. }
  930. return encoding_codes;
  931. }
  932. template<typename OperatorT>
  933. PDFErrorOr<void> CFF::parse_dict(Stream& reader, DictEntryHandler<OperatorT>&& handler)
  934. {
  935. // CFF spec, "4 DICT data"
  936. Vector<DictOperand> operands;
  937. while (!reader.is_eof()) {
  938. auto b0 = TRY(reader.read_value<u8>());
  939. // "Operators and operands may be distinguished by inspection of their first byte: 0-21 specify operators"
  940. if (b0 <= 21) {
  941. auto op = TRY(parse_dict_operator<OperatorT>(b0, reader));
  942. TRY(handler(op, operands));
  943. operands.clear();
  944. continue;
  945. }
  946. // An operand
  947. TRY(operands.try_append(TRY(load_dict_operand(b0, reader))));
  948. }
  949. return {};
  950. }
  951. template PDFErrorOr<void> CFF::parse_dict<CFF::TopDictOperator>(Stream&, DictEntryHandler<TopDictOperator>&&);
  952. template PDFErrorOr<void> CFF::parse_dict<CFF::PrivDictOperator>(Stream&, DictEntryHandler<PrivDictOperator>&&);
  953. template<typename OperatorT>
  954. PDFErrorOr<OperatorT> CFF::parse_dict_operator(u8 b0, Stream& reader)
  955. {
  956. // CFF spec, "4 DICT data"
  957. VERIFY(b0 <= 21);
  958. // "Two-byte operators have an initial escape byte of 12."
  959. if (b0 != 12)
  960. return OperatorT { (int)b0 };
  961. auto b1 = TRY(reader.read_value<u8>());
  962. return OperatorT { b0 << 8 | b1 };
  963. }
  964. template PDFErrorOr<CFF::TopDictOperator> CFF::parse_dict_operator(u8, Stream&);
  965. PDFErrorOr<void> CFF::parse_index(FixedMemoryStream& reader, IndexDataHandler&& data_handler)
  966. {
  967. // CFF spec, "5 INDEX Data"
  968. Card16 count = TRY(reader.read_value<BigEndian<Card16>>());
  969. if (count == 0)
  970. return {};
  971. auto offset_size = TRY(reader.read_value<OffSize>());
  972. if (offset_size > 4)
  973. return error("CFF INDEX Data offset_size > 4 not supported");
  974. return parse_index_data(offset_size, count, reader, data_handler);
  975. }
  976. PDFErrorOr<void> CFF::parse_index_data(OffSize offset_size, Card16 count, FixedMemoryStream& reader, IndexDataHandler& handler)
  977. {
  978. // CFF spec, "5 INDEX Data"
  979. u32 last_data_end = 1;
  980. auto read_offset = [&]() -> PDFErrorOr<u32> {
  981. u32 offset = 0;
  982. for (OffSize i = 0; i < offset_size; ++i)
  983. offset = (offset << 8) | TRY(reader.read_value<u8>());
  984. return offset;
  985. };
  986. auto offset_refpoint = reader.offset() + offset_size * (count + 1) - 1;
  987. for (u16 i = 0; i < count; i++) {
  988. auto saved_offset = TRY(reader.tell());
  989. TRY(reader.seek(offset_size * i, SeekMode::FromCurrentPosition));
  990. u32 data_start = TRY(read_offset());
  991. last_data_end = TRY(read_offset());
  992. auto data_size = last_data_end - data_start;
  993. TRY(reader.seek(offset_refpoint + data_start));
  994. TRY(handler(TRY(reader.read_in_place<u8 const>(data_size))));
  995. TRY(reader.seek(saved_offset));
  996. }
  997. TRY(reader.seek(offset_refpoint + last_data_end));
  998. return {};
  999. }
  1000. ErrorOr<int> CFF::load_int_dict_operand(u8 b0, Stream& reader)
  1001. {
  1002. // CFF spec, "Table 3 Operand Encoding"
  1003. if (b0 >= 32 && b0 <= 246) {
  1004. return b0 - 139;
  1005. }
  1006. if (b0 >= 247 && b0 <= 250) {
  1007. auto b1 = TRY(reader.read_value<u8>());
  1008. return (b0 - 247) * 256 + b1 + 108;
  1009. }
  1010. if (b0 >= 251 && b0 <= 254) {
  1011. auto b1 = TRY(reader.read_value<u8>());
  1012. return -(b0 - 251) * 256 - b1 - 108;
  1013. }
  1014. if (b0 == 28) {
  1015. auto b1 = TRY(reader.read_value<u8>());
  1016. auto b2 = TRY(reader.read_value<u8>());
  1017. return b1 << 8 | b2;
  1018. }
  1019. if (b0 == 29) {
  1020. auto b1 = TRY(reader.read_value<u8>());
  1021. auto b2 = TRY(reader.read_value<u8>());
  1022. auto b3 = TRY(reader.read_value<u8>());
  1023. auto b4 = TRY(reader.read_value<u8>());
  1024. return b1 << 24 | b2 << 16 | b3 << 8 | b4;
  1025. }
  1026. VERIFY_NOT_REACHED();
  1027. }
  1028. ErrorOr<float> CFF::load_float_dict_operand(Stream& reader)
  1029. {
  1030. // CFF spec, "Table 5 Nibble Definitions"
  1031. StringBuilder sb;
  1032. auto add_nibble = [&](char nibble) {
  1033. if (nibble < 0xa)
  1034. sb.append('0' + nibble);
  1035. else if (nibble == 0xa)
  1036. sb.append('.');
  1037. else if (nibble == 0xb)
  1038. sb.append('E');
  1039. else if (nibble == 0xc)
  1040. sb.append("E-"sv);
  1041. else if (nibble == 0xe)
  1042. sb.append('-');
  1043. };
  1044. while (true) {
  1045. auto byte = TRY(reader.read_value<u8>());
  1046. char nibble1 = (byte & 0xf0) >> 4;
  1047. char nibble2 = byte & 0x0f;
  1048. if (nibble1 == 0xf)
  1049. break;
  1050. add_nibble(nibble1);
  1051. if (nibble2 == 0xf)
  1052. break;
  1053. add_nibble(nibble2);
  1054. }
  1055. auto result = AK::StringUtils::convert_to_floating_point<float>(sb.string_view());
  1056. return result.release_value();
  1057. }
  1058. PDFErrorOr<CFF::DictOperand> CFF::load_dict_operand(u8 b0, Stream& reader)
  1059. {
  1060. // CFF spec, "4 DICT data"
  1061. if (b0 == 30)
  1062. return DictOperand { TRY(load_float_dict_operand(reader)) };
  1063. if (b0 >= 28)
  1064. return DictOperand { TRY(load_int_dict_operand(b0, reader)) };
  1065. return Error { Error::Type::MalformedPDF, ByteString::formatted("Unknown CFF dict element prefix: {}", b0) };
  1066. }
  1067. }