PS1FontProgram.cpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  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. PDFErrorOr<NonnullRefPtr<Type1FontProgram>> PS1FontProgram::create(ReadonlyBytes const& bytes, RefPtr<Encoding> encoding, size_t cleartext_length, size_t encrypted_length)
  15. {
  16. Reader reader(bytes);
  17. if (reader.remaining() == 0)
  18. return error("Empty font program");
  19. reader.move_to(0);
  20. if (reader.remaining() < 2 || !reader.matches("%!"))
  21. return error("Not a font program");
  22. if (!seek_name(reader, CommonNames::Encoding))
  23. return error("Missing encoding array");
  24. auto font_program = adopt_ref(*new PS1FontProgram());
  25. if (encoding) {
  26. // 9.6.6.2 Encodings for Type 1 Fonts:
  27. // An Encoding entry may override a Type 1 font’s mapping from character codes to character names.
  28. font_program->set_encoding(move(encoding));
  29. } else {
  30. if (TRY(parse_word(reader)) == "StandardEncoding") {
  31. font_program->set_encoding(Encoding::standard_encoding());
  32. } else {
  33. auto encoding = Encoding::create();
  34. while (reader.remaining()) {
  35. auto word = TRY(parse_word(reader));
  36. if (word == "readonly") {
  37. break;
  38. } else if (word == "dup") {
  39. u8 char_code = TRY(parse_int(reader));
  40. auto name = TRY(parse_word(reader));
  41. encoding->set(char_code, name.starts_with('/') ? name.substring_view(1) : name.view());
  42. }
  43. }
  44. font_program->set_encoding(move(encoding));
  45. }
  46. }
  47. bool found_font_matrix = seek_name(reader, "FontMatrix");
  48. if (found_font_matrix) {
  49. auto array = TRY(parse_number_array(reader, 6));
  50. font_program->set_font_matrix({ array[0], array[1], array[2], array[3], array[4], array[5] });
  51. } else {
  52. font_program->set_font_matrix({ 0.001f, 0.0f, 0.0f, 0.001f, 0.0f, 0.0f });
  53. }
  54. auto decrypted = TRY(decrypt(reader.bytes().slice(cleartext_length, encrypted_length), 55665, 4));
  55. TRY(font_program->parse_encrypted_portion(decrypted));
  56. return font_program;
  57. }
  58. PDFErrorOr<void> PS1FontProgram::parse_encrypted_portion(ByteBuffer const& buffer)
  59. {
  60. Reader reader(buffer);
  61. if (seek_name(reader, "lenIV"))
  62. m_lenIV = TRY(parse_int(reader));
  63. if (!seek_name(reader, "Subrs"))
  64. return error("Missing subroutine array");
  65. auto subroutines = TRY(parse_subroutines(reader));
  66. if (!seek_name(reader, "CharStrings"))
  67. return error("Missing char strings array");
  68. while (reader.remaining()) {
  69. auto word = TRY(parse_word(reader));
  70. VERIFY(!word.is_empty());
  71. if (word == "end")
  72. break;
  73. if (word[0] == '/') {
  74. auto encrypted_size = TRY(parse_int(reader));
  75. auto rd = TRY(parse_word(reader));
  76. if (rd == "-|" || rd == "RD") {
  77. auto line = TRY(decrypt(reader.bytes().slice(reader.offset(), encrypted_size), m_encryption_key, m_lenIV));
  78. reader.move_by(encrypted_size);
  79. auto glyph_name = word.substring_view(1);
  80. GlyphParserState state;
  81. TRY(add_glyph(glyph_name, TRY(parse_glyph(line, subroutines, state, false))));
  82. }
  83. }
  84. }
  85. consolidate_glyphs();
  86. return {};
  87. }
  88. PDFErrorOr<Vector<ByteBuffer>> PS1FontProgram::parse_subroutines(Reader& reader) const
  89. {
  90. if (!reader.matches_number())
  91. return error("Expected array length");
  92. auto length = TRY(parse_int(reader));
  93. VERIFY(length <= 1024);
  94. Vector<ByteBuffer> array;
  95. TRY(array.try_resize(length));
  96. while (reader.remaining()) {
  97. auto word = TRY(parse_word(reader));
  98. if (word.is_empty())
  99. VERIFY(0);
  100. if (word == "dup") {
  101. auto index = TRY(parse_int(reader));
  102. auto entry = TRY(parse_word(reader));
  103. if (entry.is_empty())
  104. return error("Empty array entry");
  105. if (index >= length)
  106. return error("Array index out of bounds");
  107. if (isdigit(entry[0])) {
  108. auto maybe_encrypted_size = entry.to_int();
  109. if (!maybe_encrypted_size.has_value())
  110. return error("Malformed array");
  111. auto rd = TRY(parse_word(reader));
  112. if (rd == "-|" || rd == "RD") {
  113. array[index] = TRY(decrypt(reader.bytes().slice(reader.offset(), maybe_encrypted_size.value()), m_encryption_key, m_lenIV));
  114. reader.move_by(maybe_encrypted_size.value());
  115. }
  116. } else {
  117. array[index] = TRY(ByteBuffer::copy(entry.bytes()));
  118. }
  119. } else if (word == "index" || word == "def" || word == "ND") {
  120. break;
  121. }
  122. }
  123. return array;
  124. }
  125. PDFErrorOr<Vector<float>> PS1FontProgram::parse_number_array(Reader& reader, size_t length)
  126. {
  127. Vector<float> array;
  128. TRY(array.try_resize(length));
  129. reader.consume_whitespace();
  130. if (!reader.consume('['))
  131. return error("Expected array to start with '['");
  132. reader.consume_whitespace();
  133. for (size_t i = 0; i < length; ++i)
  134. array.at(i) = TRY(parse_float(reader));
  135. if (!reader.consume(']'))
  136. return error("Expected array to end with ']'");
  137. return array;
  138. }
  139. PDFErrorOr<DeprecatedString> PS1FontProgram::parse_word(Reader& reader)
  140. {
  141. reader.consume_whitespace();
  142. auto start = reader.offset();
  143. reader.move_while([&](char c) {
  144. return !reader.matches_whitespace() && c != '[' && c != ']';
  145. });
  146. auto end = reader.offset();
  147. if (reader.matches_whitespace())
  148. reader.consume();
  149. return StringView(reader.bytes().data() + start, end - start);
  150. }
  151. PDFErrorOr<float> PS1FontProgram::parse_float(Reader& reader)
  152. {
  153. auto word = TRY(parse_word(reader));
  154. return strtof(DeprecatedString(word).characters(), nullptr);
  155. }
  156. PDFErrorOr<int> PS1FontProgram::parse_int(Reader& reader)
  157. {
  158. auto maybe_int = TRY(parse_word(reader)).to_int();
  159. if (!maybe_int.has_value())
  160. return error("Invalid int");
  161. return maybe_int.value();
  162. }
  163. PDFErrorOr<ByteBuffer> PS1FontProgram::decrypt(ReadonlyBytes const& encrypted, u16 key, size_t skip)
  164. {
  165. auto decrypted = TRY(ByteBuffer::create_uninitialized(encrypted.size() - skip));
  166. u16 R = key;
  167. u16 c1 = 52845;
  168. u16 c2 = 22719;
  169. for (size_t i = 0; i < encrypted.size(); ++i) {
  170. u8 C = encrypted[i];
  171. u8 P = C ^ (R >> 8);
  172. R = (C + R) * c1 + c2;
  173. if (i >= skip)
  174. decrypted[i - skip] = P;
  175. }
  176. return decrypted;
  177. }
  178. bool PS1FontProgram::seek_name(Reader& reader, DeprecatedString const& name)
  179. {
  180. auto start = reader.offset();
  181. reader.move_to(0);
  182. while (reader.remaining()) {
  183. if (reader.consume('/') && reader.matches(name.characters())) {
  184. // Skip name
  185. reader.move_while([&](char) {
  186. return reader.matches_regular_character();
  187. });
  188. reader.consume_whitespace();
  189. return true;
  190. }
  191. }
  192. // Jump back to where we started
  193. reader.move_to(start);
  194. return false;
  195. }
  196. }