mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-11-09 16:36:34 +00:00
M2: a page's own /MediaBox wins and a nearest box without area gives Letter, tested in the renderer and model (view.render-pages)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Pq7HyCHD1R3rywQBPCHXZA
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
d65d40a5bf
commit
49ec643a78
@@ -303,6 +303,35 @@ mod tests {
|
||||
assert_ne!(p.view_matrix(&d), view_matrix_for(0, [0.0, 0.0, 300.0, 400.0]), "the origin is kept");
|
||||
}
|
||||
|
||||
/// The nearest ancestor's `/MediaBox` wins over the root's, origin and all: the crop and the view matrix come from
|
||||
/// the intermediate `/Pages` node's box.
|
||||
#[test]
|
||||
fn a_page_takes_its_nearest_ancestors_media_box_and_origin() {
|
||||
let d = doc_from(&[
|
||||
"<< /Type /Catalog /Pages 2 0 R >>".to_string(),
|
||||
"<< /Type /Pages /Kids [3 0 R] /Count 1 /MediaBox [0 0 612 792] >>".to_string(),
|
||||
"<< /Type /Pages /Parent 2 0 R /Kids [4 0 R] /Count 1 /MediaBox [100 200 400 600] >>".to_string(),
|
||||
"<< /Type /Page /Parent 3 0 R >>".to_string(),
|
||||
]);
|
||||
let p = &pages(&d)[0];
|
||||
assert_eq!(p.crop(&d), [100.0, 200.0, 400.0, 600.0]);
|
||||
assert_eq!(p.view_matrix(&d), view_matrix_for(0, [100.0, 200.0, 400.0, 600.0]));
|
||||
}
|
||||
|
||||
/// An intermediate `/Pages` node's `/MediaBox` without area is the inherited one, so the page is US Letter, not
|
||||
/// its grandparent's box.
|
||||
#[test]
|
||||
fn a_nearest_media_box_without_area_gives_letter_not_a_further_ancestors() {
|
||||
let d = doc_from(&[
|
||||
"<< /Type /Catalog /Pages 2 0 R >>".to_string(),
|
||||
"<< /Type /Pages /Kids [3 0 R] /Count 1 /MediaBox [0 0 300 400] >>".to_string(),
|
||||
"<< /Type /Pages /Parent 2 0 R /Kids [4 0 R] /Count 1 /MediaBox [0 0 0 0] >>".to_string(),
|
||||
"<< /Type /Page /Parent 3 0 R >>".to_string(),
|
||||
]);
|
||||
let p = &pages(&d)[0];
|
||||
assert_eq!(p.crop(&d), [0.0, 0.0, 612.0, 792.0]);
|
||||
}
|
||||
|
||||
/// A `/MediaBox` without area (`[0 0 0 0]`) is US Letter too, as the renderer draws it.
|
||||
#[test]
|
||||
fn a_page_whose_media_box_has_no_area_is_letter() {
|
||||
|
||||
@@ -5602,6 +5602,49 @@ trailer << /Root 1 0 R >>
|
||||
assert_eq!((info.pages[0].width, info.pages[0].height), (300.0, 400.0), "inspected size");
|
||||
}
|
||||
|
||||
/// A page's own `/MediaBox` wins over its parent's: rendered and inspected at the page's 200 × 100, the content placed by
|
||||
/// the page box's origin.
|
||||
#[test]
|
||||
fn a_pages_own_media_box_wins_over_its_parents() {
|
||||
let pdf = b"%PDF-1.4
|
||||
1 0 obj << /Type /Catalog /Pages 2 0 R >> endobj
|
||||
2 0 obj << /Type /Pages /Kids [3 0 R] /Count 1 /MediaBox [0 0 300 400] >> endobj
|
||||
3 0 obj << /Type /Page /Parent 2 0 R /MediaBox [50 50 250 150] /Contents 4 0 R >> endobj
|
||||
4 0 obj << /Length 25 >> stream
|
||||
0 0 1 rg 60 60 50 50 re f
|
||||
endstream endobj
|
||||
trailer << /Root 1 0 R >>
|
||||
%%EOF"
|
||||
.to_vec();
|
||||
let page = render_first_page(pdf.clone());
|
||||
assert_eq!((page.width, page.height), (200, 100), "the page's box, not its parent's");
|
||||
// The square sits 10 pt in from the page box's lower-left corner, at (50, 50).
|
||||
assert_eq!(rgb_at(&page.rgba, page.width as usize, 30, 100 - 30), [0, 0, 255], "placed by the page box's origin");
|
||||
let info = crate::inspect(Arc::new(pdf), None).expect("inspect");
|
||||
assert_eq!((info.pages[0].width, info.pages[0].height), (200.0, 100.0), "inspected size");
|
||||
}
|
||||
|
||||
/// The nearest ancestor's `/MediaBox` is the inherited one even when it has no area: an intermediate `/Pages` node's
|
||||
/// `[0 0 0 0]` gives US Letter, not the grandparent's 300 × 400 (ISO 32000-2 §7.7.3.4).
|
||||
#[test]
|
||||
fn a_nearest_media_box_without_area_gives_letter_not_a_further_ancestors() {
|
||||
let pdf = b"%PDF-1.4
|
||||
1 0 obj << /Type /Catalog /Pages 2 0 R >> endobj
|
||||
2 0 obj << /Type /Pages /Kids [5 0 R] /Count 1 /MediaBox [0 0 300 400] >> endobj
|
||||
5 0 obj << /Type /Pages /Parent 2 0 R /Kids [3 0 R] /Count 1 /MediaBox [0 0 0 0] >> endobj
|
||||
3 0 obj << /Type /Page /Parent 5 0 R /Contents 4 0 R >> endobj
|
||||
4 0 obj << /Length 25 >> stream
|
||||
0 0 1 rg 10 10 50 50 re f
|
||||
endstream endobj
|
||||
trailer << /Root 1 0 R >>
|
||||
%%EOF"
|
||||
.to_vec();
|
||||
let page = render_first_page(pdf.clone());
|
||||
assert_eq!((page.width, page.height), (612, 792), "rendered size");
|
||||
let info = crate::inspect(Arc::new(pdf), None).expect("inspect");
|
||||
assert_eq!((info.pages[0].width, info.pages[0].height), (612.0, 792.0), "inspected size");
|
||||
}
|
||||
|
||||
/// A page whose content expands far beyond its compressed stream stops at the expansion budget,
|
||||
/// which is 64 times the compressed size and at least `MAX_DECODED_STREAM`, and the page says so.
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user