PS1FontProgram.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651
  1. /*
  2. * Copyright (c) 2022, Julian Offenhäuser <offenhaeuser@protonmail.com>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <LibGfx/Font/PathRasterizer.h>
  7. #include <LibPDF/CommonNames.h>
  8. #include <LibPDF/Encoding.h>
  9. #include <LibPDF/Fonts/PS1FontProgram.h>
  10. #include <LibPDF/Reader.h>
  11. #include <ctype.h>
  12. #include <math.h>
  13. namespace PDF {
  14. enum Command {
  15. HStem = 1,
  16. VStem = 3,
  17. VMoveTo,
  18. RLineTo,
  19. HLineTo,
  20. VLineTo,
  21. RRCurveTo,
  22. ClosePath,
  23. CallSubr,
  24. Return,
  25. Extended,
  26. HSbW,
  27. EndChar,
  28. RMoveTo = 21,
  29. HMoveTo,
  30. VHCurveTo = 30,
  31. HVCurveTo
  32. };
  33. enum ExtendedCommand {
  34. DotSection,
  35. VStem3,
  36. HStem3,
  37. Seac = 6,
  38. Div = 12,
  39. CallOtherSubr = 16,
  40. Pop,
  41. SetCurrentPoint = 33,
  42. };
  43. PDFErrorOr<void> PS1FontProgram::create(ReadonlyBytes const& bytes, RefPtr<Encoding> encoding, size_t cleartext_length, size_t encrypted_length)
  44. {
  45. Reader reader(bytes);
  46. if (reader.remaining() == 0)
  47. return error("Empty font program");
  48. reader.move_to(0);
  49. if (reader.remaining() < 2 || !reader.matches("%!"))
  50. return error("Not a font program");
  51. if (!seek_name(reader, CommonNames::Encoding))
  52. return error("Missing encoding array");
  53. if (encoding) {
  54. // 9.6.6.2 Encodings for Type 1 Fonts:
  55. // An Encoding entry may override a Type 1 font’s mapping from character codes to character names.
  56. m_encoding = encoding;
  57. } else {
  58. if (TRY(parse_word(reader)) == "StandardEncoding") {
  59. m_encoding = Encoding::standard_encoding();
  60. } else {
  61. HashMap<u16, CharDescriptor> descriptors;
  62. while (reader.remaining()) {
  63. auto word = TRY(parse_word(reader));
  64. if (word == "readonly") {
  65. break;
  66. } else if (word == "dup") {
  67. u32 char_code = TRY(parse_int(reader));
  68. auto name = TRY(parse_word(reader));
  69. descriptors.set(char_code, { name.starts_with('/') ? name.substring_view(1) : name.view(), char_code });
  70. }
  71. }
  72. m_encoding = TRY(Encoding::create(descriptors));
  73. }
  74. }
  75. bool found_font_matrix = seek_name(reader, "FontMatrix");
  76. if (found_font_matrix) {
  77. auto array = TRY(parse_number_array(reader, 6));
  78. m_font_matrix = { array[0], array[1], array[2], array[3], array[4], array[5] };
  79. } else {
  80. m_font_matrix = { 0.001f, 0.0f, 0.0f, 0.001f, 0.0f, 0.0f };
  81. }
  82. auto decrypted = TRY(decrypt(reader.bytes().slice(cleartext_length, encrypted_length), 55665, 4));
  83. return parse_encrypted_portion(decrypted);
  84. }
  85. RefPtr<Gfx::Bitmap> PS1FontProgram::rasterize_glyph(u32 char_code, float width, Gfx::GlyphSubpixelOffset subpixel_offset)
  86. {
  87. auto path = build_char(char_code, width, subpixel_offset);
  88. auto bounding_box = path.bounding_box().size();
  89. u32 w = (u32)ceilf(bounding_box.width()) + 2;
  90. u32 h = (u32)ceilf(bounding_box.height()) + 2;
  91. Gfx::PathRasterizer rasterizer(Gfx::IntSize(w, h));
  92. rasterizer.draw_path(path);
  93. return rasterizer.accumulate();
  94. }
  95. Gfx::Path PS1FontProgram::build_char(u32 char_code, float width, Gfx::GlyphSubpixelOffset subpixel_offset)
  96. {
  97. auto maybe_glyph = m_glyph_map.get(char_code);
  98. if (!maybe_glyph.has_value())
  99. return {};
  100. auto& glyph = maybe_glyph.value();
  101. auto transform = Gfx::AffineTransform()
  102. .translate(subpixel_offset.to_float_point())
  103. .multiply(glyph_transform_to_device_space(glyph, width));
  104. // Translate such that the top-left point is at [0, 0].
  105. auto bounding_box = glyph.path.bounding_box();
  106. Gfx::FloatPoint translation(-bounding_box.x(), -(bounding_box.y() + bounding_box.height()));
  107. transform.translate(translation);
  108. return glyph.path.copy_transformed(transform);
  109. }
  110. Gfx::FloatPoint PS1FontProgram::glyph_translation(u32 char_code, float width) const
  111. {
  112. auto maybe_glyph = m_glyph_map.get(char_code);
  113. if (!maybe_glyph.has_value())
  114. return {};
  115. auto& glyph = maybe_glyph.value();
  116. auto transform = glyph_transform_to_device_space(glyph, width);
  117. // Undo the translation we applied earlier.
  118. auto bounding_box = glyph.path.bounding_box();
  119. Gfx::FloatPoint translation(bounding_box.x(), bounding_box.y() + bounding_box.height());
  120. return transform.map(translation);
  121. }
  122. Gfx::AffineTransform PS1FontProgram::glyph_transform_to_device_space(Glyph const& glyph, float width) const
  123. {
  124. auto scale = width / (m_font_matrix.a() * glyph.width + m_font_matrix.e());
  125. auto transform = m_font_matrix;
  126. // Convert character space to device space.
  127. transform.scale(scale, -scale);
  128. return transform;
  129. }
  130. PDFErrorOr<PS1FontProgram::Glyph> PS1FontProgram::parse_glyph(ReadonlyBytes const& data, GlyphParserState& state)
  131. {
  132. auto push = [&](float value) -> PDFErrorOr<void> {
  133. if (state.sp >= state.stack.size())
  134. return error("Operand stack overflow");
  135. state.stack[state.sp++] = value;
  136. return {};
  137. };
  138. auto pop = [&]() -> float {
  139. return state.sp ? state.stack[--state.sp] : 0.0f;
  140. };
  141. auto& path = state.glyph.path;
  142. // Parse the stream of parameters and commands that make up a glyph outline.
  143. for (size_t i = 0; i < data.size(); ++i) {
  144. auto require = [&](unsigned num) -> PDFErrorOr<void> {
  145. if (i + num >= data.size())
  146. return error("Malformed glyph outline definition");
  147. return {};
  148. };
  149. int v = data[i];
  150. if (v == 255) {
  151. TRY(require(4));
  152. int a = data[++i];
  153. int b = data[++i];
  154. int c = data[++i];
  155. int d = data[++i];
  156. TRY(push((a << 24) + (b << 16) + (c << 8) + d));
  157. } else if (v >= 251) {
  158. TRY(require(1));
  159. auto w = data[++i];
  160. TRY(push(-((v - 251) * 256) - w - 108));
  161. } else if (v >= 247) {
  162. TRY(require(1));
  163. auto w = data[++i];
  164. TRY(push(((v - 247) * 256) + w + 108));
  165. } else if (v >= 32) {
  166. TRY(push(v - 139));
  167. } else {
  168. // Not a parameter but a command byte.
  169. switch (v) {
  170. case HStem:
  171. case VStem:
  172. state.sp = 0;
  173. break;
  174. case VMoveTo: {
  175. auto dy = pop();
  176. state.point.translate_by(0.0f, dy);
  177. if (state.flex_feature) {
  178. state.flex_sequence[state.flex_index++] = state.point.x();
  179. state.flex_sequence[state.flex_index++] = state.point.y();
  180. } else {
  181. path.move_to(state.point);
  182. }
  183. state.sp = 0;
  184. break;
  185. }
  186. case RLineTo: {
  187. auto dy = pop();
  188. auto dx = pop();
  189. state.point.translate_by(dx, dy);
  190. path.line_to(state.point);
  191. state.sp = 0;
  192. break;
  193. }
  194. case HLineTo: {
  195. auto dx = pop();
  196. state.point.translate_by(dx, 0.0f);
  197. path.line_to(state.point);
  198. state.sp = 0;
  199. break;
  200. }
  201. case VLineTo: {
  202. auto dy = pop();
  203. state.point.translate_by(0.0f, dy);
  204. path.line_to(state.point);
  205. state.sp = 0;
  206. break;
  207. }
  208. case RRCurveTo: {
  209. auto dy3 = pop();
  210. auto dx3 = pop();
  211. auto dy2 = pop();
  212. auto dx2 = pop();
  213. auto dy1 = pop();
  214. auto dx1 = pop();
  215. auto& point = state.point;
  216. path.cubic_bezier_curve_to(
  217. point + Gfx::FloatPoint(dx1, dy1),
  218. point + Gfx::FloatPoint(dx1 + dx2, dy1 + dy2),
  219. point + Gfx::FloatPoint(dx1 + dx2 + dx3, dy1 + dy2 + dy3));
  220. point.translate_by(dx1 + dx2 + dx3, dy1 + dy2 + dy3);
  221. state.sp = 0;
  222. break;
  223. }
  224. case ClosePath:
  225. path.close();
  226. state.sp = 0;
  227. break;
  228. case CallSubr: {
  229. auto subr_number = pop();
  230. if (static_cast<size_t>(subr_number) >= m_subroutines.size())
  231. return error("Subroutine index out of range");
  232. // Subroutines 0-2 handle the flex feature.
  233. if (subr_number == 0) {
  234. if (state.flex_index != 14)
  235. break;
  236. auto& flex = state.flex_sequence;
  237. path.cubic_bezier_curve_to(
  238. { flex[2], flex[3] },
  239. { flex[4], flex[5] },
  240. { flex[6], flex[7] });
  241. path.cubic_bezier_curve_to(
  242. { flex[8], flex[9] },
  243. { flex[10], flex[11] },
  244. { flex[12], flex[13] });
  245. state.flex_feature = false;
  246. state.sp = 0;
  247. } else if (subr_number == 1) {
  248. state.flex_feature = true;
  249. state.flex_index = 0;
  250. state.sp = 0;
  251. } else if (subr_number == 2) {
  252. state.sp = 0;
  253. } else {
  254. auto subr = m_subroutines[subr_number];
  255. if (subr.is_empty())
  256. return error("Empty subroutine");
  257. TRY(parse_glyph(subr, state));
  258. }
  259. break;
  260. }
  261. case Return:
  262. break;
  263. case Extended: {
  264. TRY(require(1));
  265. switch (data[++i]) {
  266. case DotSection:
  267. case VStem3:
  268. case HStem3:
  269. case Seac:
  270. // FIXME: Do something with these?
  271. state.sp = 0;
  272. break;
  273. case Div: {
  274. auto num2 = pop();
  275. auto num1 = pop();
  276. TRY(push(num2 ? num1 / num2 : 0.0f));
  277. break;
  278. }
  279. case CallOtherSubr: {
  280. auto othersubr_number = pop();
  281. auto n = static_cast<int>(pop());
  282. if (othersubr_number == 0) {
  283. state.postscript_stack[state.postscript_sp++] = pop();
  284. state.postscript_stack[state.postscript_sp++] = pop();
  285. pop();
  286. } else if (othersubr_number == 3) {
  287. state.postscript_stack[state.postscript_sp++] = 3;
  288. } else {
  289. for (int i = 0; i < n; ++i)
  290. state.postscript_stack[state.postscript_sp++] = pop();
  291. }
  292. (void)othersubr_number;
  293. break;
  294. }
  295. case Pop:
  296. TRY(push(state.postscript_stack[--state.postscript_sp]));
  297. break;
  298. case SetCurrentPoint: {
  299. auto y = pop();
  300. auto x = pop();
  301. state.point = { x, y };
  302. path.move_to(state.point);
  303. state.sp = 0;
  304. break;
  305. }
  306. default:
  307. return error(DeprecatedString::formatted("Unhandled command: 12 {}", data[i]));
  308. }
  309. break;
  310. }
  311. case HSbW: {
  312. auto wx = pop();
  313. auto sbx = pop();
  314. state.glyph.width = wx;
  315. state.point = { sbx, 0.0f };
  316. state.sp = 0;
  317. break;
  318. }
  319. case EndChar:
  320. break;
  321. case RMoveTo: {
  322. auto dy = pop();
  323. auto dx = pop();
  324. state.point.translate_by(dx, dy);
  325. if (state.flex_feature) {
  326. state.flex_sequence[state.flex_index++] = state.point.x();
  327. state.flex_sequence[state.flex_index++] = state.point.y();
  328. } else {
  329. path.move_to(state.point);
  330. }
  331. state.sp = 0;
  332. break;
  333. }
  334. case HMoveTo: {
  335. auto dx = pop();
  336. state.point.translate_by(dx, 0.0f);
  337. if (state.flex_feature) {
  338. state.flex_sequence[state.flex_index++] = state.point.x();
  339. state.flex_sequence[state.flex_index++] = state.point.y();
  340. } else {
  341. path.move_to(state.point);
  342. }
  343. state.sp = 0;
  344. break;
  345. }
  346. case VHCurveTo: {
  347. auto dx3 = pop();
  348. auto dy2 = pop();
  349. auto dx2 = pop();
  350. auto dy1 = pop();
  351. auto& point = state.point;
  352. path.cubic_bezier_curve_to(
  353. point + Gfx::FloatPoint(0.0f, dy1),
  354. point + Gfx::FloatPoint(dx2, dy1 + dy2),
  355. point + Gfx::FloatPoint(dx2 + dx3, dy1 + dy2));
  356. point.translate_by(dx2 + dx3, dy1 + dy2);
  357. state.sp = 0;
  358. break;
  359. }
  360. case HVCurveTo: {
  361. auto dy3 = pop();
  362. auto dy2 = pop();
  363. auto dx2 = pop();
  364. auto dx1 = pop();
  365. auto& point = state.point;
  366. path.cubic_bezier_curve_to(
  367. point + Gfx::FloatPoint(dx1, 0.0f),
  368. point + Gfx::FloatPoint(dx1 + dx2, dy2),
  369. point + Gfx::FloatPoint(dx1 + dx2, dy2 + dy3));
  370. point.translate_by(dx1 + dx2, dy2 + dy3);
  371. state.sp = 0;
  372. break;
  373. }
  374. default:
  375. return error(DeprecatedString::formatted("Unhandled command: {}", v));
  376. }
  377. }
  378. }
  379. return state.glyph;
  380. }
  381. PDFErrorOr<void> PS1FontProgram::parse_encrypted_portion(ByteBuffer const& buffer)
  382. {
  383. Reader reader(buffer);
  384. if (seek_name(reader, "lenIV"))
  385. m_lenIV = TRY(parse_int(reader));
  386. if (!seek_name(reader, "Subrs"))
  387. return error("Missing subroutine array");
  388. m_subroutines = TRY(parse_subroutines(reader));
  389. if (!seek_name(reader, "CharStrings"))
  390. return error("Missing char strings array");
  391. while (reader.remaining()) {
  392. auto word = TRY(parse_word(reader));
  393. VERIFY(!word.is_empty());
  394. if (word == "end")
  395. break;
  396. if (word[0] == '/') {
  397. auto encrypted_size = TRY(parse_int(reader));
  398. auto rd = TRY(parse_word(reader));
  399. if (rd == "-|" || rd == "RD") {
  400. auto line = TRY(decrypt(reader.bytes().slice(reader.offset(), encrypted_size), m_encryption_key, m_lenIV));
  401. reader.move_by(encrypted_size);
  402. auto name_mapping = m_encoding->name_mapping();
  403. auto char_code = name_mapping.ensure(word.substring_view(1));
  404. GlyphParserState state;
  405. m_glyph_map.set(char_code, TRY(parse_glyph(line, state)));
  406. }
  407. }
  408. }
  409. return {};
  410. }
  411. PDFErrorOr<Vector<ByteBuffer>> PS1FontProgram::parse_subroutines(Reader& reader)
  412. {
  413. if (!reader.matches_number())
  414. return error("Expected array length");
  415. auto length = TRY(parse_int(reader));
  416. VERIFY(length <= 1024);
  417. Vector<ByteBuffer> array;
  418. TRY(array.try_resize(length));
  419. while (reader.remaining()) {
  420. auto word = TRY(parse_word(reader));
  421. if (word.is_empty())
  422. VERIFY(0);
  423. if (word == "dup") {
  424. auto index = TRY(parse_int(reader));
  425. auto entry = TRY(parse_word(reader));
  426. if (entry.is_empty())
  427. return error("Empty array entry");
  428. if (index >= length)
  429. return error("Array index out of bounds");
  430. if (isdigit(entry[0])) {
  431. auto maybe_encrypted_size = entry.to_int();
  432. if (!maybe_encrypted_size.has_value())
  433. return error("Malformed array");
  434. auto rd = TRY(parse_word(reader));
  435. if (rd == "-|" || rd == "RD") {
  436. array[index] = TRY(decrypt(reader.bytes().slice(reader.offset(), maybe_encrypted_size.value()), m_encryption_key, m_lenIV));
  437. reader.move_by(maybe_encrypted_size.value());
  438. }
  439. } else {
  440. array[index] = TRY(ByteBuffer::copy(entry.bytes()));
  441. }
  442. } else if (word == "index") {
  443. break;
  444. }
  445. }
  446. return array;
  447. }
  448. PDFErrorOr<Vector<float>> PS1FontProgram::parse_number_array(Reader& reader, size_t length)
  449. {
  450. Vector<float> array;
  451. TRY(array.try_resize(length));
  452. reader.consume_whitespace();
  453. if (!reader.consume('['))
  454. return error("Expected array to start with '['");
  455. reader.consume_whitespace();
  456. for (size_t i = 0; i < length; ++i)
  457. array.at(i) = TRY(parse_float(reader));
  458. if (!reader.consume(']'))
  459. return error("Expected array to end with ']'");
  460. return array;
  461. }
  462. PDFErrorOr<DeprecatedString> PS1FontProgram::parse_word(Reader& reader)
  463. {
  464. reader.consume_whitespace();
  465. auto start = reader.offset();
  466. reader.move_while([&](char c) {
  467. return !reader.matches_whitespace() && c != '[' && c != ']';
  468. });
  469. auto end = reader.offset();
  470. if (reader.matches_whitespace())
  471. reader.consume();
  472. return StringView(reader.bytes().data() + start, end - start);
  473. }
  474. PDFErrorOr<float> PS1FontProgram::parse_float(Reader& reader)
  475. {
  476. auto word = TRY(parse_word(reader));
  477. return strtof(DeprecatedString(word).characters(), nullptr);
  478. }
  479. PDFErrorOr<int> PS1FontProgram::parse_int(Reader& reader)
  480. {
  481. auto maybe_int = TRY(parse_word(reader)).to_int();
  482. if (!maybe_int.has_value())
  483. return error("Invalid int");
  484. return maybe_int.value();
  485. }
  486. PDFErrorOr<ByteBuffer> PS1FontProgram::decrypt(ReadonlyBytes const& encrypted, u16 key, size_t skip)
  487. {
  488. auto decrypted = TRY(ByteBuffer::create_uninitialized(encrypted.size() - skip));
  489. u16 R = key;
  490. u16 c1 = 52845;
  491. u16 c2 = 22719;
  492. for (size_t i = 0; i < encrypted.size(); ++i) {
  493. u8 C = encrypted[i];
  494. u8 P = C ^ (R >> 8);
  495. R = (C + R) * c1 + c2;
  496. if (i >= skip)
  497. decrypted[i - skip] = P;
  498. }
  499. return decrypted;
  500. }
  501. bool PS1FontProgram::seek_name(Reader& reader, DeprecatedString const& name)
  502. {
  503. auto start = reader.offset();
  504. reader.move_to(0);
  505. while (reader.remaining()) {
  506. if (reader.consume('/') && reader.matches(name.characters())) {
  507. // Skip name
  508. reader.move_while([&](char) {
  509. return reader.matches_regular_character();
  510. });
  511. reader.consume_whitespace();
  512. return true;
  513. }
  514. }
  515. // Jump back to where we started
  516. reader.move_to(start);
  517. return false;
  518. }
  519. Error PS1FontProgram::error(
  520. DeprecatedString const& message
  521. #ifdef PDF_DEBUG
  522. ,
  523. SourceLocation loc
  524. #endif
  525. )
  526. {
  527. #ifdef PDF_DEBUG
  528. dbgln("\033[31m{} Type 1 font error: {}\033[0m", loc, message);
  529. #endif
  530. return Error { Error::Type::MalformedPDF, message };
  531. }
  532. }