PS1FontProgram.cpp 17 KB

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