From cb3e05f47638a4432f13cfe3103952c0afba3910 Mon Sep 17 00:00:00 2001 From: Rodrigo Tobar Date: Mon, 21 Nov 2022 13:32:09 +0800 Subject: [PATCH] LibPDF: Add initial implementation of XObject rendering This implementation currently handles Form XObjects only, skipping image XObjects. When rendering an XObject, its resources are passed to the underlying operations so they use those instead of the Page's. --- Userland/Libraries/LibPDF/Renderer.cpp | 33 +++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/Userland/Libraries/LibPDF/Renderer.cpp b/Userland/Libraries/LibPDF/Renderer.cpp index 4a1e9412ed..8eb8edab1f 100644 --- a/Userland/Libraries/LibPDF/Renderer.cpp +++ b/Userland/Libraries/LibPDF/Renderer.cpp @@ -620,7 +620,38 @@ RENDERER_TODO(shade) RENDERER_TODO(inline_image_begin) RENDERER_TODO(inline_image_begin_data) RENDERER_TODO(inline_image_end) -RENDERER_TODO(paint_xobject) +RENDERER_HANDLER(paint_xobject) +{ + VERIFY(args.size() > 0); + auto resources = extra_resources.value_or(m_page.resources); + auto xobject_name = args[0].get>()->cast()->name(); + auto xobjects_dict = MUST(resources->get_dict(m_document, CommonNames::XObject)); + auto xobject = MUST(xobjects_dict->get_stream(m_document, xobject_name)); + + auto subtype = MUST(xobject->dict()->get_name(m_document, CommonNames::Subtype))->name(); + if (subtype == CommonNames::Image) { + dbgln("Skipping image"); + return {}; + } + + MUST(handle_save_state({})); + Vector matrix; + if (xobject->dict()->contains(CommonNames::Matrix)) { + matrix = xobject->dict()->get_array(m_document, CommonNames::Matrix).value()->elements(); + } else { + matrix = Vector { Value { 1 }, Value { 0 }, Value { 0 }, Value { 1 }, Value { 0 }, Value { 0 } }; + } + MUST(handle_concatenate_matrix(matrix)); + Optional> xobject_resources {}; + if (xobject->dict()->contains(CommonNames::Resources)) { + xobject_resources = xobject->dict()->get_dict(m_document, CommonNames::Resources).value(); + } + auto operators = TRY(Parser::parse_operators(m_document, xobject->bytes())); + for (auto& op : operators) + TRY(handle_operator(op, xobject_resources)); + MUST(handle_restore_state({})); + return {}; +} RENDERER_HANDLER(marked_content_point) {