diff --git a/Userland/Libraries/LibPDF/Document.cpp b/Userland/Libraries/LibPDF/Document.cpp index ac5f4193b2..f498ff3a3a 100644 --- a/Userland/Libraries/LibPDF/Document.cpp +++ b/Userland/Libraries/LibPDF/Document.cpp @@ -136,6 +136,67 @@ u32 Document::get_page_count() const return m_page_object_indices.size(); } +static ErrorOr collect_referenced_indices(Value const& value, Vector& referenced_indices) +{ + TRY(value.visit( + [&](Empty const&) -> ErrorOr { return {}; }, + [&](nullptr_t const&) -> ErrorOr { return {}; }, + [&](bool const&) -> ErrorOr { return {}; }, + [&](int const&) -> ErrorOr { return {}; }, + [&](float const&) -> ErrorOr { return {}; }, + [&](Reference const& ref) -> ErrorOr { + TRY(referenced_indices.try_append(ref.as_ref_index())); + return {}; + }, + [&](NonnullRefPtr const& object) -> ErrorOr { + if (object->is()) { + for (auto& element : object->cast()->elements()) + TRY(collect_referenced_indices(element, referenced_indices)); + } else if (object->is()) { + for (auto& [key, value] : object->cast()->map()) { + if (key != CommonNames::Parent) + TRY(collect_referenced_indices(value, referenced_indices)); + } + } else if (object->is()) { + for (auto& [key, value] : object->cast()->dict()->map()) { + if (key != CommonNames::Parent) + TRY(collect_referenced_indices(value, referenced_indices)); + } + } + return {}; + })); + return {}; +} + +static PDFErrorOr dump_tree(Document& document, size_t index, HashTable& seen) +{ + if (seen.contains(index)) + return {}; + seen.set(index); + + auto const& value = TRY(document.get_or_load_value(index)); + outln("obj {} 0", index); + outln("{}", value.to_deprecated_string(0)); + outln("endobj"); + + Vector referenced_indices; + TRY(collect_referenced_indices(value, referenced_indices)); + for (auto index : referenced_indices) + TRY(dump_tree(document, index, seen)); + + return {}; +} + +PDFErrorOr Document::dump_page(u32 index) +{ + VERIFY(index < m_page_object_indices.size()); + auto page_object_index = m_page_object_indices[index]; + + HashTable seen; + TRY(dump_tree(*this, page_object_index, seen)); + return {}; +} + PDFErrorOr Document::get_page(u32 index) { VERIFY(index < m_page_object_indices.size()); diff --git a/Userland/Libraries/LibPDF/Document.h b/Userland/Libraries/LibPDF/Document.h index b6a4c70b9b..d302c3832b 100644 --- a/Userland/Libraries/LibPDF/Document.h +++ b/Userland/Libraries/LibPDF/Document.h @@ -118,6 +118,7 @@ public: [[nodiscard]] u32 get_page_count() const; + PDFErrorOr dump_page(u32 index); [[nodiscard]] PDFErrorOr get_page(u32 index); ALWAYS_INLINE Value get_value(u32 index) const