mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-10-24 10:08:00 -06:00
Optimizer: Audit space usage counts images PrintCraft added as images (#3)
Content added with Edit ▸ Add content records its image in the content stream's dictionary (/PCAdded /Image). The audit claimed a page's content streams before its resources and followed that reference, so an added image's bytes were reported as Content Streams and Images showed 0 % (a 1.9 MB picture read as 99.9 % content). Resources are now claimed first, so whatever a content stream's dictionary points at keeps its own category. Co-authored-by: storybored379 <storybored379@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
storybored379
Claude Opus 5.5
parent
8f1f4e7ffb
commit
3908a03aa6
@@ -188,11 +188,13 @@ pub fn audit_space(doc: &Document, file_len: u64) -> Vec<SpaceUse> {
|
||||
a.claim(&x, if widget { SpaceCategory::Forms } else { SpaceCategory::Comments });
|
||||
}
|
||||
}
|
||||
// Resources before the content: a content stream's dictionary may point at what it
|
||||
// draws (PrintCraft's /PCAdded records an added image), which stays an image or font.
|
||||
let res = a.resolve_dict(p.dict.get(b"Resources"));
|
||||
a.resources(&res);
|
||||
if let Some(c) = p.dict.get(b"Contents") {
|
||||
a.claim(c, SpaceCategory::ContentStreams);
|
||||
}
|
||||
let res = a.resolve_dict(p.dict.get(b"Resources"));
|
||||
a.resources(&res);
|
||||
if let Some(t) = p.dict.get(b"Thumb") {
|
||||
a.claim(t, SpaceCategory::Thumbnails);
|
||||
}
|
||||
|
||||
@@ -193,6 +193,25 @@ fn space_audit_shares_the_file_out_by_kind() {
|
||||
assert!((audit.iter().map(|u| u.percent).sum::<f64>() - 100.0).abs() < 1e-6);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn space_audit_counts_images_a_content_stream_dictionary_points_at_as_images() {
|
||||
// Content added with Edit ▸ Add content records its image in the content stream's
|
||||
// dictionary (/PCAdded); the image is still an image, not part of the content stream.
|
||||
let mut doc = Document::new_empty();
|
||||
let img = image(&mut doc, 300, 300, 3, false, None);
|
||||
let p = page(&mut doc, &[("Im0", img)], "q 300 0 0 300 0 0 cm /Im0 Do Q");
|
||||
let c = doc.get(p).as_dict().and_then(|d| d.reference(b"Contents")).unwrap();
|
||||
let mut added = Dict::new();
|
||||
added.set(b"Kind".to_vec(), Object::name("Image"));
|
||||
added.set(b"Image".to_vec(), Object::Ref(img));
|
||||
doc.update_dict(c, |d| d.set(b"PCAdded".to_vec(), Object::Dict(added))).unwrap();
|
||||
let bytes = write_full(&doc, &SaveOptions { object_streams: false, ..SaveOptions::default() }).unwrap();
|
||||
let doc = Document::open(Arc::new(bytes.clone())).unwrap();
|
||||
let audit = audit_space(&doc, bytes.len() as u64);
|
||||
let images = audit.iter().find(|u| u.category == SpaceCategory::Images).unwrap();
|
||||
assert!(images.percent > 80.0, "{audit:?}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_links_and_unreferenced_destinations_go() {
|
||||
let mut doc = Document::new_empty();
|
||||
|
||||
Reference in New Issue
Block a user