TestPDF.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. /*
  2. * Copyright (c) 2021, Simon Woertz <simon@woertz.at>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/ByteString.h>
  7. #include <AK/Forward.h>
  8. #include <AK/LexicalPath.h>
  9. #include <LibCore/MappedFile.h>
  10. #include <LibCore/ResourceImplementationFile.h>
  11. #include <LibCore/System.h>
  12. #include <LibGfx/Bitmap.h>
  13. #include <LibPDF/CommonNames.h>
  14. #include <LibPDF/Document.h>
  15. #include <LibPDF/Function.h>
  16. #include <LibPDF/Renderer.h>
  17. #include <LibTest/Macros.h>
  18. #include <LibTest/TestCase.h>
  19. TEST_CASE(parse_value)
  20. {
  21. // document isn't really used for anything, only to check there's no security_handler.
  22. auto file = MUST(Core::MappedFile::map("linearized.pdf"sv));
  23. auto document = MUST(PDF::Document::create(file->bytes()));
  24. auto contents = "<50607><10\n>"sv;
  25. PDF::Parser parser(contents.bytes());
  26. parser.set_document(document->make_weak_ptr());
  27. auto value1 = MUST(parser.parse_value(PDF::Parser::CanBeIndirectValue::No));
  28. auto string1 = value1.get<NonnullRefPtr<PDF::Object>>()->cast<PDF::StringObject>();
  29. EXPECT(string1->is_binary());
  30. EXPECT_EQ(string1->string(), "\x50\x60\x70"sv);
  31. auto value2 = MUST(parser.parse_value(PDF::Parser::CanBeIndirectValue::No));
  32. auto string2 = value2.get<NonnullRefPtr<PDF::Object>>()->cast<PDF::StringObject>();
  33. EXPECT(string2->is_binary());
  34. EXPECT_EQ(string2->string(), "\x10"sv);
  35. }
  36. TEST_CASE(linearized_pdf)
  37. {
  38. auto file = MUST(Core::MappedFile::map("linearized.pdf"sv));
  39. auto document = MUST(PDF::Document::create(file->bytes()));
  40. MUST(document->initialize());
  41. EXPECT_EQ(document->get_page_count(), 1U);
  42. }
  43. TEST_CASE(non_linearized_pdf)
  44. {
  45. auto file = MUST(Core::MappedFile::map("non-linearized.pdf"sv));
  46. auto document = MUST(PDF::Document::create(file->bytes()));
  47. MUST(document->initialize());
  48. EXPECT_EQ(document->get_page_count(), 1U);
  49. }
  50. TEST_CASE(complex_pdf)
  51. {
  52. auto file = MUST(Core::MappedFile::map("complex.pdf"sv));
  53. auto document = MUST(PDF::Document::create(file->bytes()));
  54. MUST(document->initialize());
  55. EXPECT_EQ(document->get_page_count(), 3U);
  56. }
  57. TEST_CASE(empty_file_issue_10702)
  58. {
  59. AK::ReadonlyBytes empty;
  60. auto document = PDF::Document::create(empty);
  61. EXPECT(document.is_error());
  62. }
  63. TEST_CASE(encodig)
  64. {
  65. auto file = MUST(Core::MappedFile::map("encoding.pdf"sv));
  66. auto document = MUST(PDF::Document::create(file->bytes()));
  67. MUST(document->initialize());
  68. EXPECT_EQ(document->get_page_count(), 1U);
  69. auto info_dict = MUST(document->info_dict()).value();
  70. EXPECT_EQ(MUST(info_dict.author()).value(), "Nico Weber");
  71. EXPECT_EQ(MUST(info_dict.producer()).value(), (char const*)u8"Manüally Created");
  72. EXPECT_EQ(MUST(info_dict.title()).value(), (char const*)u8"Êñ©•ding test");
  73. auto outline_dict = document->outline();
  74. EXPECT_EQ(outline_dict->count, 3u);
  75. EXPECT_EQ(outline_dict->children[0]->title, (char const*)u8"Titlè 1");
  76. EXPECT_EQ(outline_dict->children[1]->title, (char const*)u8"Titlè 2");
  77. EXPECT_EQ(outline_dict->children[2]->title, (char const*)u8"Titlè 3");
  78. }
  79. TEST_CASE(truncated_pdf_header_issue_10717)
  80. {
  81. AK::ByteString string { "%PDF-2.11%" };
  82. auto document = PDF::Document::create(string.bytes());
  83. EXPECT(document.is_error());
  84. }
  85. TEST_CASE(encrypted_with_aes)
  86. {
  87. auto file = MUST(Core::MappedFile::map("password-is-sup.pdf"sv));
  88. auto document = MUST(PDF::Document::create(file->bytes()));
  89. EXPECT(document->security_handler()->try_provide_user_password("sup"sv));
  90. MUST(document->initialize());
  91. EXPECT_EQ(document->get_page_count(), 1U);
  92. auto info_dict = MUST(document->info_dict()).value();
  93. EXPECT_EQ(MUST(info_dict.title()).value(), "sup");
  94. EXPECT_EQ(MUST(info_dict.creator()).value(), "TextEdit");
  95. }
  96. TEST_CASE(encrypted_object_stream)
  97. {
  98. auto file = MUST(Core::MappedFile::map("encryption_nocopy.pdf"sv));
  99. auto document = MUST(PDF::Document::create(file->bytes()));
  100. MUST(document->initialize());
  101. EXPECT_EQ(document->get_page_count(), 1U);
  102. auto info_dict = MUST(document->info_dict()).value();
  103. EXPECT_EQ(MUST(info_dict.author()).value(), "van der Knijff");
  104. EXPECT_EQ(MUST(info_dict.creator()).value(), "Acrobat PDFMaker 9.1 voor Word");
  105. }
  106. TEST_CASE(resolve_indirect_reference_during_parsing)
  107. {
  108. auto file = MUST(Core::MappedFile::map("jbig2-globals.pdf"sv));
  109. auto document = MUST(PDF::Document::create(file->bytes()));
  110. MUST(document->initialize());
  111. EXPECT_EQ(document->get_page_count(), 1U);
  112. auto jbig2_stream_value = MUST(document->get_or_load_value(5));
  113. auto jbig2_stream = MUST(document->resolve_to<PDF::StreamObject>(jbig2_stream_value));
  114. EXPECT_EQ(jbig2_stream->bytes().size(), 20'000U);
  115. }
  116. TEST_CASE(malformed_pdf_document)
  117. {
  118. Array test_inputs = {
  119. "oss-fuzz-testcase-62065.pdf"sv
  120. };
  121. for (auto test_input : test_inputs) {
  122. auto file = MUST(Core::MappedFile::map(test_input));
  123. auto document_or_error = PDF::Document::create(file->bytes());
  124. EXPECT(document_or_error.is_error());
  125. }
  126. }
  127. static PDF::Value make_array(Vector<float> floats)
  128. {
  129. Vector<PDF::Value> values;
  130. for (auto f : floats)
  131. values.append(PDF::Value { f });
  132. return PDF::Value { make_object<PDF::ArrayObject>(move(values)) };
  133. }
  134. static PDF::PDFErrorOr<NonnullRefPtr<PDF::Function>> make_function(int type, ReadonlyBytes data, Vector<float> domain, Vector<float> range, Function<void(HashMap<DeprecatedFlyString, PDF::Value>&)> extra_keys = nullptr)
  135. {
  136. HashMap<DeprecatedFlyString, PDF::Value> map;
  137. map.set(PDF::CommonNames::FunctionType, PDF::Value { type });
  138. map.set(PDF::CommonNames::Domain, make_array(move(domain)));
  139. map.set(PDF::CommonNames::Range, make_array(move(range)));
  140. if (extra_keys)
  141. extra_keys(map);
  142. auto dict = make_object<PDF::DictObject>(move(map));
  143. auto stream = make_object<PDF::StreamObject>(dict, MUST(ByteBuffer::copy(data)));
  144. // document isn't used for anything, but UBSan complains about a (harmless) method call on a null object without it.
  145. auto file = MUST(Core::MappedFile::map("linearized.pdf"sv));
  146. auto document = MUST(PDF::Document::create(file->bytes()));
  147. return PDF::Function::create(document, stream);
  148. }
  149. static PDF::PDFErrorOr<NonnullRefPtr<PDF::Function>> make_sampled_function(ReadonlyBytes data, Vector<float> domain, Vector<float> range, Vector<float> sizes)
  150. {
  151. return make_function(0, data, move(domain), move(range), [&sizes](auto& map) {
  152. map.set(PDF::CommonNames::Size, make_array(sizes));
  153. map.set(PDF::CommonNames::BitsPerSample, PDF::Value { 8 });
  154. });
  155. }
  156. TEST_CASE(sampled)
  157. {
  158. auto f1 = MUST(make_sampled_function(Vector<u8> { { 0, 255, 0 } }, { 0.0f, 1.0f }, { 0.0f, 10.0f }, { 3 }));
  159. EXPECT_EQ(MUST(f1->evaluate(Vector<float> { 0.0f })), Vector<float> { 0.0f });
  160. EXPECT_EQ(MUST(f1->evaluate(Vector<float> { 0.25f })), Vector<float> { 5.0f });
  161. EXPECT_EQ(MUST(f1->evaluate(Vector<float> { 0.5f })), Vector<float> { 10.0f });
  162. EXPECT_EQ(MUST(f1->evaluate(Vector<float> { 0.75f })), Vector<float> { 5.0f });
  163. EXPECT_EQ(MUST(f1->evaluate(Vector<float> { 1.0f })), Vector<float> { 0.0f });
  164. auto f2 = MUST(make_sampled_function(Vector<u8> { { 0, 255, 255, 0, 0, 255 } }, { 0.0f, 1.0f }, { 0.0f, 10.0f, 0.0f, 8.0f }, { 3 }));
  165. EXPECT_EQ(MUST(f2->evaluate(Vector<float> { 0.0f })), (Vector<float> { 0.0f, 8.0f }));
  166. EXPECT_EQ(MUST(f2->evaluate(Vector<float> { 0.25f })), (Vector<float> { 5.0f, 4.0f }));
  167. EXPECT_EQ(MUST(f2->evaluate(Vector<float> { 0.5f })), (Vector<float> { 10.0f, 0.0f }));
  168. EXPECT_EQ(MUST(f2->evaluate(Vector<float> { 0.75f })), (Vector<float> { 5.0f, 4.0f }));
  169. EXPECT_EQ(MUST(f2->evaluate(Vector<float> { 1.0f })), (Vector<float> { 0.0f, 8.0f }));
  170. auto f3 = MUST(make_sampled_function(Vector<u8> { { 0, 255, 0, 255, 0, 255 } }, { 0.0f, 1.0f, 0.0f, 1.0f }, { 0.0f, 10.0f }, { 3, 2 }));
  171. EXPECT_EQ(MUST(f3->evaluate(Vector<float> { 0.0f, 0.0f })), Vector<float> { 0.0f });
  172. EXPECT_EQ(MUST(f3->evaluate(Vector<float> { 0.25f, 0.0f })), Vector<float> { 5.0f });
  173. EXPECT_EQ(MUST(f3->evaluate(Vector<float> { 0.5f, 0.0f })), Vector<float> { 10.0f });
  174. EXPECT_EQ(MUST(f3->evaluate(Vector<float> { 0.75f, 0.0f })), Vector<float> { 5.0f });
  175. EXPECT_EQ(MUST(f3->evaluate(Vector<float> { 1.0f, 0.0f })), Vector<float> { 0.0f });
  176. EXPECT_EQ(MUST(f3->evaluate(Vector<float> { 0.0f, 0.5f })), Vector<float> { 5.0f });
  177. EXPECT_EQ(MUST(f3->evaluate(Vector<float> { 0.25f, 0.5f })), Vector<float> { 5.0f });
  178. EXPECT_EQ(MUST(f3->evaluate(Vector<float> { 0.5f, 0.5f })), Vector<float> { 5.0f });
  179. EXPECT_EQ(MUST(f3->evaluate(Vector<float> { 0.75f, 0.5f })), Vector<float> { 5.0f });
  180. EXPECT_EQ(MUST(f3->evaluate(Vector<float> { 1.0f, 0.5f })), Vector<float> { 5.0f });
  181. EXPECT_EQ(MUST(f3->evaluate(Vector<float> { 0.0f, 1.0f })), Vector<float> { 10.0f });
  182. EXPECT_EQ(MUST(f3->evaluate(Vector<float> { 0.25f, 1.0f })), Vector<float> { 5.0f });
  183. EXPECT_EQ(MUST(f3->evaluate(Vector<float> { 0.5f, 1.0f })), Vector<float> { 0.0f });
  184. EXPECT_EQ(MUST(f3->evaluate(Vector<float> { 0.75f, 1.0f })), Vector<float> { 5.0f });
  185. EXPECT_EQ(MUST(f3->evaluate(Vector<float> { 1.0f, 1.0f })), Vector<float> { 10.0f });
  186. auto f4 = MUST(make_sampled_function(Vector<u8> { { 0, 255, 255, 0, 0, 255, 255, 0 } }, { 0.0f, 1.0f, 0.0f, 1.0f }, { 0.0f, 10.0f, 0.0f, 8.0f }, { 2, 2 }));
  187. EXPECT_EQ(MUST(f4->evaluate(Vector<float> { 0.0f, 0.0f })), (Vector<float> { 0.0f, 8.0f }));
  188. EXPECT_EQ(MUST(f4->evaluate(Vector<float> { 0.5f, 0.5f })), (Vector<float> { 5.0f, 4.0f }));
  189. }
  190. static PDF::PDFErrorOr<NonnullRefPtr<PDF::Function>> make_postscript_function(StringView program, Vector<float> domain, Vector<float> range)
  191. {
  192. return make_function(4, program.bytes(), move(domain), move(range));
  193. }
  194. static NonnullRefPtr<PDF::Function> check_postscript_function(StringView program, Vector<float> domain, Vector<float> range)
  195. {
  196. auto function = make_postscript_function(program, move(domain), move(range));
  197. if (function.is_error())
  198. FAIL(function.error().message());
  199. return function.value();
  200. }
  201. static void check_evaluate(StringView program, Vector<float> inputs, Vector<float> outputs)
  202. {
  203. Vector<float> domain;
  204. for (size_t i = 0; i < inputs.size(); ++i) {
  205. domain.append(-100.0f);
  206. domain.append(100.0f);
  207. }
  208. Vector<float> range;
  209. for (size_t i = 0; i < outputs.size(); ++i) {
  210. range.append(-100.0f);
  211. range.append(100.0f);
  212. }
  213. auto function = check_postscript_function(program, domain, range);
  214. auto result = function->evaluate(inputs);
  215. if (result.is_error())
  216. FAIL(result.error().message());
  217. EXPECT_EQ(result.value(), outputs);
  218. }
  219. TEST_CASE(postscript)
  220. {
  221. // Arithmetic operators
  222. check_evaluate("{ abs }"sv, { 0.5f }, { 0.5f });
  223. check_evaluate("{ add }"sv, { 0.25f, 0.5f }, { 0.75f });
  224. check_evaluate("{ atan }"sv, { 1.0f, 0.01f }, { AK::to_degrees(atan2f(0.01f, 1.0f)) });
  225. check_evaluate("{ ceiling }"sv, { 0.5f }, { 1.0f });
  226. check_evaluate("{ cos }"sv, { 1.0f }, { cosf(AK::to_radians(1.0f)) });
  227. check_evaluate("{ cvi }"sv, { 0.5f }, { 0.0f });
  228. check_evaluate("{ cvr }"sv, { 0.5f }, { 0.5f });
  229. check_evaluate("{ div }"sv, { 0.5f, 1.0f }, { 0.5f });
  230. check_evaluate("{ exp }"sv, { 0.0f }, { 1.0f });
  231. check_evaluate("{ floor }"sv, { 0.5f }, { 0.0f });
  232. check_evaluate("{ idiv }"sv, { 0.5f, 1.0f }, { 0.0f });
  233. check_evaluate("{ ln }"sv, { 10.0f }, { logf(10.0f) });
  234. check_evaluate("{ log }"sv, { 10.0f }, { log10f(10.0f) });
  235. check_evaluate("{ mod }"sv, { 0.5f, 0.25f }, { 0.0f });
  236. check_evaluate("{ mul }"sv, { 0.5f, 0.25f }, { 0.125f });
  237. check_evaluate("{ neg }"sv, { 0.5f }, { -0.5f });
  238. check_evaluate("{ round }"sv, { 0.5f }, { 1.0f });
  239. check_evaluate("{ sin }"sv, { 1.0f }, { sinf(AK::to_radians(1.0f)) });
  240. check_evaluate("{ sqrt }"sv, { 0.5f }, { sqrtf(0.5f) });
  241. check_evaluate("{ sub }"sv, { 0.5f, 0.25f }, { 0.25f });
  242. check_evaluate("{ truncate }"sv, { 0.5f }, { 0.0f });
  243. // Relational, boolean, and bitwise operators
  244. check_evaluate("{ and }"sv, { 0.0f, 1.0f }, { 0.0f });
  245. check_evaluate("{ bitshift }"sv, { 1.0f, 3.0f }, { 8.0f });
  246. check_evaluate("{ bitshift }"sv, { 8.0f, -2.0f }, { 2.0f });
  247. check_evaluate("{ eq }"sv, { 0.5f, 0.5f }, { 1.0f });
  248. check_evaluate("{ ge }"sv, { 0.5f, 0.5f }, { 1.0f });
  249. check_evaluate("{ gt }"sv, { 0.5f, 0.5f }, { 0.0f });
  250. check_evaluate("{ le }"sv, { 0.5f, 0.5f }, { 1.0f });
  251. check_evaluate("{ lt }"sv, { 0.5f, 0.5f }, { 0.0f });
  252. check_evaluate("{ ne }"sv, { 0.5f, 0.5f }, { 0.0f });
  253. check_evaluate("{ not }"sv, { 0.5f }, { 0.0f });
  254. check_evaluate("{ or }"sv, { 0.0f, 1.0f }, { 1.0f });
  255. check_evaluate("{ xor }"sv, { 0.0f, 1.0f }, { 1.0f });
  256. // Conditional operators
  257. check_evaluate("{ { 4 } if }"sv, { 1.0f }, { 4.0f });
  258. check_evaluate("{ { 4 } if }"sv, { 0.0f }, {});
  259. check_evaluate("{ { 4 } { 5 } ifelse }"sv, { 1.0f }, { 4.0f });
  260. check_evaluate("{ { 4 } { 5 } ifelse }"sv, { 0.0f }, { 5.0f });
  261. // Stack operators
  262. check_evaluate("{ 2 copy }"sv, { 8.0f, 0.5f, 1.0f }, { 8.0f, 0.5f, 1.0f, 0.5f, 1.0f });
  263. check_evaluate("{ dup }"sv, { 1.0f, 0.5f }, { 1.0f, 0.5f, 0.5f });
  264. check_evaluate("{ exch }"sv, { 8.0f, 1.0f, 0.5f }, { 8.0f, 0.5f, 1.0f });
  265. check_evaluate("{ 1 index }"sv, { 8.0f, 1.0f, 0.5f }, { 8.0f, 1.0f, 0.5f, 1.0f });
  266. check_evaluate("{ pop }"sv, { 8.0f, 1.0f, 0.5f }, { 8.0f, 1.0f });
  267. check_evaluate("{ 3 1 roll }"sv, { 0.5f, 1.0f, 2.0f }, { 2.0f, 0.5f, 1.0f });
  268. check_evaluate("{ 3 -1 roll }"sv, { 0.5f, 1.0f, 2.0f }, { 1.0f, 2.0f, 0.5f });
  269. }
  270. TEST_CASE(render)
  271. {
  272. #if !defined(AK_OS_SERENITY)
  273. // Get from Build/lagom/bin/TestPDF to Build/lagom/Root/res.
  274. auto source_root = LexicalPath(MUST(Core::System::current_executable_path())).parent().parent().string();
  275. Core::ResourceImplementation::install(make<Core::ResourceImplementationFile>(MUST(String::formatted("{}/Root/res", source_root))));
  276. #endif
  277. auto file = MUST(Core::MappedFile::map("colorspaces.pdf"sv));
  278. auto document = MUST(PDF::Document::create(file->bytes()));
  279. MUST(document->initialize());
  280. EXPECT_EQ(document->get_page_count(), 1U);
  281. auto page = MUST(document->get_page(0));
  282. auto page_size = Gfx::IntSize { 310, 370 };
  283. auto bitmap = MUST(Gfx::Bitmap::create(Gfx::BitmapFormat::BGRx8888, page_size));
  284. MUST(PDF::Renderer::render(document, page, bitmap, Color::White, PDF::RenderingPreferences {}));
  285. // DeviceGray
  286. EXPECT_EQ(bitmap->get_pixel(270, 370 - 20), Gfx::Color::NamedColor::Black);
  287. // MyCalRGB
  288. EXPECT_EQ(bitmap->get_pixel(270, 370 - 80), Gfx::Color::NamedColor::Black);
  289. // DeviceRGB
  290. EXPECT_EQ(bitmap->get_pixel(270, 370 - 140), Gfx::Color::NamedColor::Black);
  291. // DeviceCMYK (note: black one box further left)
  292. EXPECT_EQ(bitmap->get_pixel(220, 370 - 200), Gfx::Color::NamedColor::Black);
  293. // MyLab
  294. EXPECT_EQ(bitmap->get_pixel(270, 370 - 260), Gfx::Color::NamedColor::Black);
  295. // MyCalGray
  296. EXPECT_EQ(bitmap->get_pixel(270, 370 - 320), Gfx::Color::NamedColor::Black);
  297. }