summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibPDF
diff options
context:
space:
mode:
authorMatthew Olsson <matthewcolsson@gmail.com>2022-03-05 18:25:33 -0700
committerAndreas Kling <kling@serenityos.org>2022-03-07 10:53:57 +0100
commite9342183f05f173ad9f35eb2d35f4d3393c5ed62 (patch)
treeeb7e619c8e86d2703c25eae239128c73c06c0c9d /Userland/Libraries/LibPDF
parentb240d23a8749da290d26c2990fa27fc9b68af376 (diff)
downloadserenity-e9342183f05f173ad9f35eb2d35f4d3393c5ed62.zip
LibPDF: Support all Dest types
Diffstat (limited to 'Userland/Libraries/LibPDF')
-rw-r--r--Userland/Libraries/LibPDF/CommonNames.h3
-rw-r--r--Userland/Libraries/LibPDF/Document.cpp84
-rw-r--r--Userland/Libraries/LibPDF/Document.h2
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;