summaryrefslogtreecommitdiff
path: root/Userland/Libraries
diff options
context:
space:
mode:
authorJulian Offenhäuser <offenhaeuser@protonmail.com>2023-03-24 22:07:03 +0100
committerAndrew Kaster <andrewdkaster@gmail.com>2023-03-25 16:27:30 -0600
commitfde990ead8bde644a27eeb190b82397753cb3f78 (patch)
tree48e9dd97d190163a5525515697853b21a4004f13 /Userland/Libraries
parent320f5f91ab297dd9e494950a3429f6450d6d31e4 (diff)
downloadserenity-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.cpp52
-rw-r--r--Userland/Libraries/LibPDF/Document.h2
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);