mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 09:37:45 +00:00
LibPDF: Load destinations from Catalogue -> Names -> Dests name tree
PDF allows for named destinations to be provided as string. These can be either found in the Dests dictionary in the document catalogue (as already implemented), or in the Name Tree specified by the Dests key in the Names dictionary of the document catalogue (missing). This commit adds this missing case. Once the named destination is found in the name tree, its value is interpreted just like in the first case, so a new utility method encapsulates the common behavior.
This commit is contained in:
parent
5420261347
commit
a5620fd41f
2 changed files with 25 additions and 10 deletions
|
@ -315,6 +315,17 @@ PDFErrorOr<NonnullRefPtr<Object>> Document::get_inheritable_object(FlyString con
|
||||||
return object->get_object(this, name);
|
return object->get_object(this, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PDFErrorOr<Destination> Document::create_destination_from_dictionary_entry(NonnullRefPtr<Object> const& entry, HashMap<u32, u32> const& page_number_by_index_ref)
|
||||||
|
{
|
||||||
|
if (entry->is<ArrayObject>()) {
|
||||||
|
auto entry_array = entry->cast<ArrayObject>();
|
||||||
|
return create_destination_from_parameters(entry_array, page_number_by_index_ref);
|
||||||
|
}
|
||||||
|
auto entry_dictionary = entry->cast<DictObject>();
|
||||||
|
auto d_array = MUST(entry_dictionary->get_array(this, CommonNames::D));
|
||||||
|
return create_destination_from_parameters(d_array, page_number_by_index_ref);
|
||||||
|
}
|
||||||
|
|
||||||
PDFErrorOr<NonnullRefPtr<OutlineItem>> Document::build_outline_item(NonnullRefPtr<DictObject> const& outline_item_dict, HashMap<u32, u32> const& page_number_by_index_ref)
|
PDFErrorOr<NonnullRefPtr<OutlineItem>> Document::build_outline_item(NonnullRefPtr<DictObject> const& outline_item_dict, HashMap<u32, u32> const& page_number_by_index_ref)
|
||||||
{
|
{
|
||||||
auto outline_item = adopt_ref(*new OutlineItem {});
|
auto outline_item = adopt_ref(*new OutlineItem {});
|
||||||
|
@ -340,19 +351,22 @@ PDFErrorOr<NonnullRefPtr<OutlineItem>> Document::build_outline_item(NonnullRefPt
|
||||||
if (dest_obj->is<ArrayObject>()) {
|
if (dest_obj->is<ArrayObject>()) {
|
||||||
auto dest_arr = dest_obj->cast<ArrayObject>();
|
auto dest_arr = dest_obj->cast<ArrayObject>();
|
||||||
outline_item->dest = TRY(create_destination_from_parameters(dest_arr, page_number_by_index_ref));
|
outline_item->dest = TRY(create_destination_from_parameters(dest_arr, page_number_by_index_ref));
|
||||||
} else if (dest_obj->is<NameObject>()) {
|
} else if (dest_obj->is<NameObject>() || dest_obj->is<StringObject>()) {
|
||||||
auto dest_name = dest_obj->cast<NameObject>()->name();
|
FlyString dest_name;
|
||||||
|
if (dest_obj->is<NameObject>())
|
||||||
|
dest_name = dest_obj->cast<NameObject>()->name();
|
||||||
|
else
|
||||||
|
dest_name = dest_obj->cast<StringObject>()->string();
|
||||||
if (auto dests_value = m_catalog->get(CommonNames::Dests); dests_value.has_value()) {
|
if (auto dests_value = m_catalog->get(CommonNames::Dests); dests_value.has_value()) {
|
||||||
auto dests = dests_value.value().get<NonnullRefPtr<Object>>()->cast<DictObject>();
|
auto dests = dests_value.value().get<NonnullRefPtr<Object>>()->cast<DictObject>();
|
||||||
auto entry = MUST(dests->get_object(this, dest_name));
|
auto entry = MUST(dests->get_object(this, dest_name));
|
||||||
if (entry->is<ArrayObject>()) {
|
outline_item->dest = TRY(create_destination_from_dictionary_entry(entry, page_number_by_index_ref));
|
||||||
auto entry_array = entry->cast<ArrayObject>();
|
} else if (auto names_value = m_catalog->get(CommonNames::Names); names_value.has_value()) {
|
||||||
outline_item->dest = TRY(create_destination_from_parameters(entry_array, page_number_by_index_ref));
|
auto names = TRY(resolve(names_value.release_value())).get<NonnullRefPtr<Object>>()->cast<DictObject>();
|
||||||
} else {
|
if (!names->contains(CommonNames::Dests))
|
||||||
auto entry_dictionary = entry->cast<DictObject>();
|
return Error { Error::Type::MalformedPDF, "Missing Dests key in document catalogue's Names dictionary" };
|
||||||
auto d_array = MUST(entry_dictionary->get_array(this, CommonNames::D));
|
auto dest_obj = TRY(find_in_name_tree(TRY(names->get_dict(this, CommonNames::Dests)), dest_name));
|
||||||
outline_item->dest = TRY(create_destination_from_parameters(d_array, page_number_by_index_ref));
|
outline_item->dest = TRY(create_destination_from_dictionary_entry(dest_obj, page_number_by_index_ref));
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
return Error { Error::Type::MalformedPDF, "Malformed outline destination" };
|
return Error { Error::Type::MalformedPDF, "Malformed outline destination" };
|
||||||
}
|
}
|
||||||
|
|
|
@ -136,6 +136,7 @@ private:
|
||||||
PDFErrorOr<NonnullRefPtrVector<OutlineItem>> build_outline_item_chain(Value const& first_ref, HashMap<u32, u32> const&);
|
PDFErrorOr<NonnullRefPtrVector<OutlineItem>> build_outline_item_chain(Value const& first_ref, HashMap<u32, u32> const&);
|
||||||
|
|
||||||
PDFErrorOr<Destination> create_destination_from_parameters(NonnullRefPtr<ArrayObject>, HashMap<u32, u32> const&);
|
PDFErrorOr<Destination> create_destination_from_parameters(NonnullRefPtr<ArrayObject>, HashMap<u32, u32> const&);
|
||||||
|
PDFErrorOr<Destination> create_destination_from_dictionary_entry(NonnullRefPtr<Object> const& entry, HashMap<u32, u32> const& page_number_by_index_ref);
|
||||||
|
|
||||||
PDFErrorOr<NonnullRefPtr<Object>> get_inheritable_object(FlyString const& name, NonnullRefPtr<DictObject>);
|
PDFErrorOr<NonnullRefPtr<Object>> get_inheritable_object(FlyString const& name, NonnullRefPtr<DictObject>);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue