diff options
author | Julian Offenhäuser <offenhaeuser@protonmail.com> | 2023-03-24 22:07:03 +0100 |
---|---|---|
committer | Andrew Kaster <andrewdkaster@gmail.com> | 2023-03-25 16:27:30 -0600 |
commit | fde990ead8bde644a27eeb190b82397753cb3f78 (patch) | |
tree | 48e9dd97d190163a5525515697853b21a4004f13 /Userland/Libraries | |
parent | 320f5f91ab297dd9e494950a3429f6450d6d31e4 (diff) | |
download | serenity-fde990ead8bde644a27eeb190b82397753cb3f78.zip |
LibPDF: Allow optional inheritable page attributes
Previously, get_inheritable_object would always try to find the object
and throw an error if it couldn't. The spec tells us that some page
attributes, like CropBox, are optional but also inheritable. Others,
like the media box and resources, are technically required by the spec,
but omitted by some documents.
In both cases, we are now able to search for inheritable objects and
find a suitable replacement if there wasn't one.
Diffstat (limited to 'Userland/Libraries')
-rw-r--r-- | Userland/Libraries/LibPDF/Document.cpp | 52 | ||||
-rw-r--r-- | Userland/Libraries/LibPDF/Document.h | 2 |
2 files changed, 38 insertions, 16 deletions
diff --git a/Userland/Libraries/LibPDF/Document.cpp b/Userland/Libraries/LibPDF/Document.cpp index 99d70127ca..de1a373a95 100644 --- a/Userland/Libraries/LibPDF/Document.cpp +++ b/Userland/Libraries/LibPDF/Document.cpp @@ -109,26 +109,46 @@ PDFErrorOr<Page> Document::get_page(u32 index) auto page_object = TRY(get_or_load_value(page_object_index)); auto raw_page_object = TRY(resolve_to<DictObject>(page_object)); - auto resources = TRY(get_inheritable_object(CommonNames::Resources, raw_page_object))->cast<DictObject>(); + RefPtr<DictObject> resources; + auto maybe_resources_object = TRY(get_inheritable_object(CommonNames::Resources, raw_page_object)); + if (maybe_resources_object.has_value()) + resources = maybe_resources_object.value()->cast<DictObject>(); + else + resources = adopt_ref(*new DictObject({})); + auto contents = TRY(raw_page_object->get_object(this, CommonNames::Contents)); - auto media_box_array = TRY(get_inheritable_object(CommonNames::MediaBox, raw_page_object))->cast<ArrayObject>(); - auto media_box = Rectangle { - media_box_array->at(0).to_float(), - media_box_array->at(1).to_float(), - media_box_array->at(2).to_float(), - media_box_array->at(3).to_float(), - }; - - auto crop_box = media_box; - if (raw_page_object->contains(CommonNames::CropBox)) { - auto crop_box_array = TRY(raw_page_object->get_array(this, CommonNames::CropBox)); + Rectangle media_box; + auto maybe_media_box_object = TRY(get_inheritable_object(CommonNames::MediaBox, raw_page_object)); + if (maybe_media_box_object.has_value()) { + auto media_box_array = maybe_media_box_object.value()->cast<ArrayObject>(); + media_box = Rectangle { + media_box_array->at(0).to_float(), + media_box_array->at(1).to_float(), + media_box_array->at(2).to_float(), + media_box_array->at(3).to_float(), + }; + } else { + // As most other libraries seem to do, we default to the standard + // US letter size of 8.5" x 11" (612 x 792 Postscript units). + media_box = Rectangle { + 0, 0, + 612, 792 + }; + } + + Rectangle crop_box; + auto maybe_crop_box_object = TRY(get_inheritable_object(CommonNames::CropBox, raw_page_object)); + if (maybe_crop_box_object.has_value()) { + auto crop_box_array = maybe_crop_box_object.value()->cast<ArrayObject>(); crop_box = Rectangle { crop_box_array->at(0).to_float(), crop_box_array->at(1).to_float(), crop_box_array->at(2).to_float(), crop_box_array->at(3).to_float(), }; + } else { + crop_box = media_box; } float user_unit = 1.0f; @@ -141,7 +161,7 @@ PDFErrorOr<Page> Document::get_page(u32 index) VERIFY(rotate % 90 == 0); } - Page page { move(resources), move(contents), media_box, crop_box, user_unit, rotate }; + Page page { resources.release_nonnull(), move(contents), media_box, crop_box, user_unit, rotate }; m_pages.set(index, page); return page; } @@ -306,13 +326,15 @@ PDFErrorOr<Destination> Document::create_destination_from_parameters(NonnullRefP return Destination { type, page_number_by_index_ref.get(page_ref.as_ref_index()), parameters }; } -PDFErrorOr<NonnullRefPtr<Object>> Document::get_inheritable_object(DeprecatedFlyString const& name, NonnullRefPtr<DictObject> object) +PDFErrorOr<Optional<NonnullRefPtr<Object>>> Document::get_inheritable_object(DeprecatedFlyString const& name, NonnullRefPtr<DictObject> object) { if (!object->contains(name)) { + if (!object->contains(CommonNames::Parent)) + return { OptionalNone() }; auto parent = TRY(object->get_dict(this, CommonNames::Parent)); return get_inheritable_object(name, parent); } - return object->get_object(this, name); + return TRY(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) diff --git a/Userland/Libraries/LibPDF/Document.h b/Userland/Libraries/LibPDF/Document.h index 7805a20017..8880c653a2 100644 --- a/Userland/Libraries/LibPDF/Document.h +++ b/Userland/Libraries/LibPDF/Document.h @@ -143,7 +143,7 @@ private: 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(DeprecatedFlyString const& name, NonnullRefPtr<DictObject>); + PDFErrorOr<Optional<NonnullRefPtr<Object>>> get_inheritable_object(DeprecatedFlyString const& name, NonnullRefPtr<DictObject>); PDFErrorOr<NonnullRefPtr<Object>> find_in_name_tree(NonnullRefPtr<DictObject> root, DeprecatedFlyString name); PDFErrorOr<NonnullRefPtr<Object>> find_in_name_tree_nodes(NonnullRefPtr<ArrayObject> siblings, DeprecatedFlyString name); |