mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-11-12 22:02:33 +00:00
Optimize: a removed external action is not replaced by a null in its /Next
When an action to another document was removed and its /Next list started with a null or a reference to something other than an action, that entry became the head of the chain, and the actions after it, such as a web link, were dropped with it. Leading entries that are not action dictionaries are now skipped. The Settings::discard_external_refs doc comment lists every action type the option removes.
This commit is contained in:
1 parent
f3e2701852
commit
8de27ff9ad
3 files changed
+31
-2
No files matched your search
@@ -265,6 +265,9 @@ fn strip_action(doc: &mut Document, a: &Object, owner: ObjRef) -> Result<Option<
|
||||
if walk.removed == 0 && !walk.cut {
|
||||
return Ok(None);
|
||||
}
|
||||
// A null or a reference to something other than an action cannot lead the chain.
|
||||
let head = v.iter().position(|o| doc.resolve(o).as_dict().is_some()).unwrap_or(v.len());
|
||||
v.drain(..head);
|
||||
if v.is_empty() {
|
||||
return Ok(Some(None));
|
||||
}
|
||||
|
||||
@@ -168,8 +168,9 @@ pub struct Settings {
|
||||
pub remove_invalid_links: bool,
|
||||
/// Clean Up: remove named destinations nothing refers to.
|
||||
pub remove_unreferenced_dests: bool,
|
||||
/// Discard User Data: take `GoToR`, `GoToE` and `Launch` actions out of links and bookmarks;
|
||||
/// a link left with nothing to do is removed. Links within the document and web links stay.
|
||||
/// Discard User Data: take `GoToR`, `GoToE`, `Launch` and `ImportData` actions, and `Thread`
|
||||
/// actions with an `/F`, out of links and bookmarks; a link left with nothing to do is
|
||||
/// removed. Links within the document and web links stay.
|
||||
pub discard_external_refs: bool,
|
||||
}
|
||||
|
||||
|
||||
@@ -623,6 +623,31 @@ fn an_action_to_another_document_hands_its_place_to_the_actions_after_it() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn entries_that_are_not_actions_do_not_take_the_place_of_a_removed_action() {
|
||||
let (doc, p, items) = linked_doc(
|
||||
|doc, _| {
|
||||
// A null, then a reference to an empty object, before the web link.
|
||||
let empty = doc.add(Object::Null);
|
||||
let next = Object::Array(vec![Object::Null, Object::Ref(empty), action("URI", None), Object::Null]);
|
||||
vec![link_with(Some(action("GoToR", Some(next))), None)]
|
||||
},
|
||||
&[
|
||||
action("Launch", Some(Object::Array(vec![Object::Null, action("URI", None)]))),
|
||||
action("GoToR", Some(Object::Array(vec![Object::Null, Object::Null]))),
|
||||
],
|
||||
);
|
||||
let mut doc = doc;
|
||||
let report = optimize(&mut doc, &Settings { discard_external_refs: true, ..Settings::default() }).unwrap();
|
||||
assert_eq!((report.external_links, report.external_bookmarks), (1, 2), "{report:?}");
|
||||
let links = annots_of(&doc, p);
|
||||
assert_eq!(links.len(), 1, "the link keeps its web link, so it stays on the page");
|
||||
assert_eq!(chain(&doc, links[0].get(b"A").unwrap()), ["URI"]);
|
||||
let bookmark = |r: ObjRef| doc.get(r).as_dict().unwrap().clone();
|
||||
assert_eq!(chain(&doc, bookmark(items[0]).get(b"A").unwrap()), ["URI"]);
|
||||
assert!(bookmark(items[1]).get(b"A").is_none(), "a chain of nulls alone leaves no action");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_chain_deeper_than_the_limit_loses_its_tail_and_one_without_a_remote_action_stays() {
|
||||
let deep = |n: usize, last: &str| (0..n).fold(action(last, None), |next, _| action("URI", Some(next)));
|
||||
|
||||
Reference in new issue
Block a user