瀏覽代碼

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.
Rodrigo Tobar 2 年之前
父節點
當前提交
cb3e05f476
共有 1 個文件被更改,包括 32 次插入1 次删除
  1. 32 1
      Userland/Libraries/LibPDF/Renderer.cpp

+ 32 - 1
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<NonnullRefPtr<Object>>()->cast<NameObject>()->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<Value> 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<NonnullRefPtr<DictObject>> 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)
 {