1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 03:37:45 +00:00

LibPDF: Implement GoTo action for outline

Outline items can contain either a /Dest key or an /A key.

The /Dest key points to a "Destination" (various ways to reference a
page in the same document).

The /A key points to an "Action" which can have several types.
One type, the /GoTo type, just also points to a Destination.

Implement GoTo actions. This makes clicking "Contents" in the outline of
https://developer.apple.com/library/archive/documentation/mac/pdf/Text.pdf
work. (Almost all other items in this file's outline use /Dest.
"Contents" could too, but it uses /A /GoTo for some reason.)

(Other action types are things like opening a hyperlink, opening a
different file, playing a sound, submitting a form, etc. Actions
are also used for in-page links, not just in outlines. Many of
these action types we'll likely never want to implement.)
This commit is contained in:
Nico Weber 2023-10-17 08:07:59 -04:00 committed by Tim Flynn
parent d9c9510d3c
commit 182639217f
2 changed files with 18 additions and 0 deletions

View file

@ -540,6 +540,22 @@ PDFErrorOr<NonnullRefPtr<OutlineItem>> Document::build_outline_item(NonnullRefPt
if (outline_item_dict->contains(CommonNames::Dest)) {
auto dest_obj = TRY(outline_item_dict->get_object(this, CommonNames::Dest));
outline_item->dest = TRY(create_destination_from_object(dest_obj, page_number_by_index_ref));
} else if (outline_item_dict->contains(CommonNames::A)) {
// PDF 1.7 spec, "8.5 Actions"
auto action_dict = TRY(outline_item_dict->get_dict(this, CommonNames::A));
if (action_dict->contains(CommonNames::S)) {
// PDF 1.7 spec, "TABLE 8.48 Action types"
auto action_type = TRY(action_dict->get_name(this, CommonNames::S))->name();
if (action_type == "GoTo") {
// PDF 1.7 spec, "Go-To Actions"
if (action_dict->contains(CommonNames::D)) {
auto dest_obj = TRY(action_dict->get_object(this, CommonNames::D));
outline_item->dest = TRY(create_destination_from_object(dest_obj, page_number_by_index_ref));
}
} else {
dbgln("Unhandled action type {}", action_type);
}
}
}
if (outline_item_dict->contains(CommonNames::C)) {