diff options
author | Matthew Olsson <matthewcolsson@gmail.com> | 2022-03-05 18:25:33 -0700 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2022-03-07 10:53:57 +0100 |
commit | e9342183f05f173ad9f35eb2d35f4d3393c5ed62 (patch) | |
tree | eb7e619c8e86d2703c25eae239128c73c06c0c9d /Userland/Libraries/LibPDF | |
parent | b240d23a8749da290d26c2990fa27fc9b68af376 (diff) | |
download | serenity-e9342183f05f173ad9f35eb2d35f4d3393c5ed62.zip |
LibPDF: Support all Dest types
Diffstat (limited to 'Userland/Libraries/LibPDF')
-rw-r--r-- | Userland/Libraries/LibPDF/CommonNames.h | 3 | ||||
-rw-r--r-- | Userland/Libraries/LibPDF/Document.cpp | 84 | ||||
-rw-r--r-- | Userland/Libraries/LibPDF/Document.h | 2 |
3 files changed, 58 insertions, 31 deletions
diff --git a/Userland/Libraries/LibPDF/CommonNames.h b/Userland/Libraries/LibPDF/CommonNames.h index d17999f206..0c76674273 100644 --- a/Userland/Libraries/LibPDF/CommonNames.h +++ b/Userland/Libraries/LibPDF/CommonNames.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Matthew Olsson <mattco@serenityos.org> + * Copyright (c) 2021-2022, Matthew Olsson <mattco@serenityos.org> * * SPDX-License-Identifier: BSD-2-Clause */ @@ -29,6 +29,7 @@ V(D) \ V(DCTDecode) \ V(Dest) \ + V(Dests) \ V(DeviceCMYK) \ V(DeviceGray) \ V(DeviceRGB) \ diff --git a/Userland/Libraries/LibPDF/Document.cpp b/Userland/Libraries/LibPDF/Document.cpp index aa41dc6492..51a60afa6c 100644 --- a/Userland/Libraries/LibPDF/Document.cpp +++ b/Userland/Libraries/LibPDF/Document.cpp @@ -209,6 +209,39 @@ PDFErrorOr<void> Document::build_outline() return {}; } +PDFErrorOr<Destination> Document::create_destination_from_parameters(NonnullRefPtr<ArrayObject> array) +{ + auto page_ref = array->at(0); + auto type_name = TRY(array->get_name_at(this, 1))->name(); + + Vector<float> parameters; + for (size_t i = 2; i < array->size(); i++) + parameters.append(array->at(i).to_float()); + + Destination::Type type; + if (type_name == CommonNames::XYZ) { + type = Destination::Type::XYZ; + } else if (type_name == CommonNames::Fit) { + type = Destination::Type::Fit; + } else if (type_name == CommonNames::FitH) { + type = Destination::Type::FitH; + } else if (type_name == CommonNames::FitV) { + type = Destination::Type::FitV; + } else if (type_name == CommonNames::FitR) { + type = Destination::Type::FitR; + } else if (type_name == CommonNames::FitB) { + type = Destination::Type::FitB; + } else if (type_name == CommonNames::FitBH) { + type = Destination::Type::FitBH; + } else if (type_name == CommonNames::FitBV) { + type = Destination::Type::FitBV; + } else { + VERIFY_NOT_REACHED(); + } + + return Destination { type, page_ref, parameters }; +} + PDFErrorOr<NonnullRefPtr<OutlineItem>> Document::build_outline_item(NonnullRefPtr<DictObject> const& outline_item_dict) { auto outline_item = adopt_ref(*new OutlineItem {}); @@ -228,37 +261,28 @@ PDFErrorOr<NonnullRefPtr<OutlineItem>> Document::build_outline_item(NonnullRefPt outline_item->count = outline_item_dict->get_value(CommonNames::Count).get<int>(); if (outline_item_dict->contains(CommonNames::Dest)) { - auto dest_arr = TRY(outline_item_dict->get_array(this, CommonNames::Dest)); - dbgln("IS ARRAY = {}", dest_arr->is_array()); - auto page_ref = dest_arr->at(0); - auto type_name = TRY(dest_arr->get_name_at(this, 1))->name(); - - Vector<float> parameters; - for (size_t i = 2; i < dest_arr->size(); i++) - parameters.append(dest_arr->at(i).to_float()); - - Destination::Type type; - if (type_name == CommonNames::XYZ) { - type = Destination::Type::XYZ; - } else if (type_name == CommonNames::Fit) { - type = Destination::Type::Fit; - } else if (type_name == CommonNames::FitH) { - type = Destination::Type::FitH; - } else if (type_name == CommonNames::FitV) { - type = Destination::Type::FitV; - } else if (type_name == CommonNames::FitR) { - type = Destination::Type::FitR; - } else if (type_name == CommonNames::FitB) { - type = Destination::Type::FitB; - } else if (type_name == CommonNames::FitBH) { - type = Destination::Type::FitBH; - } else if (type_name == CommonNames::FitBV) { - type = Destination::Type::FitBV; - } else { - VERIFY_NOT_REACHED(); + auto dest_obj = TRY(outline_item_dict->get_object(this, CommonNames::Dest)); + + if (dest_obj->is<ArrayObject>()) { + auto dest_arr = dest_obj->cast<ArrayObject>(); + outline_item->dest = TRY(create_destination_from_parameters(dest_arr)); + } else if (dest_obj->is<NameObject>()) { + auto dest_name = dest_obj->cast<NameObject>()->name(); + if (auto dests_value = m_catalog->get(CommonNames::Dests); dests_value.has_value()) { + auto dests = dests_value.value().get<NonnullRefPtr<Object>>()->cast<DictObject>(); + auto entry = MUST(dests->get_object(this, dest_name)); + if (entry->is<ArrayObject>()) { + auto entry_array = entry->cast<ArrayObject>(); + outline_item->dest = TRY(create_destination_from_parameters(entry_array)); + } else { + auto entry_dictionary = entry->cast<DictObject>(); + auto d_array = MUST(entry_dictionary->get_array(this, CommonNames::D)); + outline_item->dest = TRY(create_destination_from_parameters(d_array)); + } + } else { + return Error { Error::Type::MalformedPDF, "Malformed outline destination" }; + } } - - outline_item->dest = Destination { type, page_ref, parameters }; } if (outline_item_dict->contains(CommonNames::C)) { diff --git a/Userland/Libraries/LibPDF/Document.h b/Userland/Libraries/LibPDF/Document.h index 142eca1722..bebde8aa4e 100644 --- a/Userland/Libraries/LibPDF/Document.h +++ b/Userland/Libraries/LibPDF/Document.h @@ -135,6 +135,8 @@ private: PDFErrorOr<NonnullRefPtr<OutlineItem>> build_outline_item(NonnullRefPtr<DictObject> const& outline_item_dict); PDFErrorOr<NonnullRefPtrVector<OutlineItem>> build_outline_item_chain(Value const& first_ref, Value const& last_ref); + PDFErrorOr<Destination> create_destination_from_parameters(NonnullRefPtr<ArrayObject>); + NonnullRefPtr<Parser> m_parser; RefPtr<DictObject> m_catalog; Vector<u32> m_page_object_indices; |