From b3007c17bd28c47c4564d8a6e3a2110b1ab945f9 Mon Sep 17 00:00:00 2001 From: Rodrigo Tobar Date: Mon, 21 Nov 2022 13:28:41 +0800 Subject: [PATCH] LibPDF: Allow operators to receive optional resources Operators usually assume that the resources its operations will require will be the Page's. This assumption breaks however when XObjects with their own resources come into the picture (and maybe other cases too). In that case, the XObject's resources take precedence, but they should also contain the Page's resources. Because of this, one can safely use the XObject resources alone when given, and default to the Page's if not. This commit adds all operator calls an extra argument with optional resources, which will be fed by XObjects as necessary. --- Userland/Libraries/LibPDF/Renderer.cpp | 25 +++++++++++++------------ Userland/Libraries/LibPDF/Renderer.h | 8 ++++---- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/Userland/Libraries/LibPDF/Renderer.cpp b/Userland/Libraries/LibPDF/Renderer.cpp index 0d0a3d57ff..4a1e9412ed 100644 --- a/Userland/Libraries/LibPDF/Renderer.cpp +++ b/Userland/Libraries/LibPDF/Renderer.cpp @@ -10,7 +10,7 @@ #include #define RENDERER_HANDLER(name) \ - PDFErrorOr Renderer::handle_##name([[maybe_unused]] Vector const& args) + PDFErrorOr Renderer::handle_##name([[maybe_unused]] Vector const& args, [[maybe_unused]] Optional> extra_resources) #define RENDERER_TODO(name) \ RENDERER_HANDLER(name) \ @@ -118,20 +118,20 @@ PDFErrorOr Renderer::render() return {}; } -PDFErrorOr Renderer::handle_operator(Operator const& op) +PDFErrorOr Renderer::handle_operator(Operator const& op, Optional> extra_resources) { switch (op.type()) { -#define V(name, snake_name, symbol) \ - case OperatorType::name: \ - TRY(handle_##snake_name(op.arguments())); \ +#define V(name, snake_name, symbol) \ + case OperatorType::name: \ + MUST(handle_##snake_name(op.arguments(), extra_resources)); \ break; ENUMERATE_OPERATORS(V) #undef V case OperatorType::TextNextLineShowString: - TRY(handle_text_next_line_show_string(op.arguments())); + MUST(handle_text_next_line_show_string(op.arguments())); break; case OperatorType::TextNextLineShowStringSetSpacing: - TRY(handle_text_next_line_show_string_set_spacing(op.arguments())); + MUST(handle_text_next_line_show_string_set_spacing(op.arguments())); break; } @@ -204,9 +204,9 @@ RENDERER_TODO(set_flatness_tolerance) RENDERER_HANDLER(set_graphics_state_from_dict) { - VERIFY(m_page.resources->contains(CommonNames::ExtGState)); + auto resources = extra_resources.value_or(m_page.resources); auto dict_name = MUST(m_document->resolve_to(args[0]))->name(); - auto ext_gstate_dict = MUST(m_page.resources->get_dict(m_document, CommonNames::ExtGState)); + auto ext_gstate_dict = MUST(resources->get_dict(m_document, CommonNames::ExtGState)); auto target_dict = MUST(ext_gstate_dict->get_dict(m_document, dict_name)); TRY(set_graphics_state_from_dict(target_dict)); return {}; @@ -421,8 +421,9 @@ RENDERER_HANDLER(text_set_leading) RENDERER_HANDLER(text_set_font) { + auto resources = extra_resources.value_or(m_page.resources); auto target_font_name = MUST(m_document->resolve_to(args[0]))->name(); - auto fonts_dictionary = MUST(m_page.resources->get_dict(m_document, CommonNames::Font)); + auto fonts_dictionary = MUST(resources->get_dict(m_document, CommonNames::Font)); auto font_dictionary = MUST(fonts_dictionary->get_dict(m_document, target_font_name)); text_state().font_size = args[1].to_float(); @@ -527,14 +528,14 @@ RENDERER_TODO(type3_font_set_glyph_width_and_bbox) RENDERER_HANDLER(set_stroking_space) { - state().stroke_color_space = TRY(get_color_space(args[0], m_page.resources)); + state().stroke_color_space = TRY(get_color_space(args[0], extra_resources.value_or(m_page.resources))); VERIFY(state().stroke_color_space); return {}; } RENDERER_HANDLER(set_painting_space) { - state().paint_color_space = TRY(get_color_space(args[0], m_page.resources)); + state().paint_color_space = TRY(get_color_space(args[0], extra_resources.value_or(m_page.resources))); VERIFY(state().paint_color_space); return {}; } diff --git a/Userland/Libraries/LibPDF/Renderer.h b/Userland/Libraries/LibPDF/Renderer.h index b47af63634..6f9a271a55 100644 --- a/Userland/Libraries/LibPDF/Renderer.h +++ b/Userland/Libraries/LibPDF/Renderer.h @@ -97,13 +97,13 @@ private: PDFErrorOr render(); - PDFErrorOr handle_operator(Operator const&); + PDFErrorOr handle_operator(Operator const&, Optional> = {}); #define V(name, snake_name, symbol) \ - PDFErrorOr handle_##snake_name(Vector const& args); + PDFErrorOr handle_##snake_name(Vector const& args, Optional> = {}); ENUMERATE_OPERATORS(V) #undef V - PDFErrorOr handle_text_next_line_show_string(Vector const& args); - PDFErrorOr handle_text_next_line_show_string_set_spacing(Vector const& args); + PDFErrorOr handle_text_next_line_show_string(Vector const& args, Optional> = {}); + PDFErrorOr handle_text_next_line_show_string_set_spacing(Vector const& args, Optional> = {}); void begin_path_paint(); void end_path_paint();