mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-11-10 13:35:21 +00:00
address review: charge the pairwise boundary check only for areas
This commit is contained in:
@@ -520,11 +520,12 @@ pub fn list(doc: &Document) -> Listing {
|
||||
Some(b"PolygonDimension") => Kind::Area,
|
||||
_ => continue,
|
||||
};
|
||||
// The boundary check compares every pair of edges: charge it before reading the
|
||||
// vertices, so a listing stops at its work bound rather than at a stall.
|
||||
// An area's boundary check compares every pair of edges: charge it before reading the
|
||||
// vertices, so a listing stops at its work bound rather than at a stall. Other kinds
|
||||
// read their vertices once.
|
||||
let vertices = d.get(if kind == Kind::Distance { b"L".as_slice() } else { b"Vertices" }).map(|v| doc.resolve(v));
|
||||
let n = vertices.as_deref().and_then(Object::as_array).map_or(0, |a| a.len() / 2).min(MAX_POINTS);
|
||||
work = work.saturating_add(n.saturating_mul(n));
|
||||
work = work.saturating_add(if kind == Kind::Area { n.saturating_mul(n) } else { n.max(1) });
|
||||
if work > MAX_LISTED_WORK {
|
||||
out.truncated = true;
|
||||
return out;
|
||||
|
||||
@@ -511,3 +511,27 @@ fn listing_reads_a_shared_scale_once_and_bounds_boundary_checks() {
|
||||
assert!((5..areas).contains(&l.measurements.len()), "{} listed", l.measurements.len());
|
||||
assert!(l.unsupported.is_empty(), "{:?}", l.unsupported);
|
||||
}
|
||||
|
||||
/// Perimeters and distances read their vertices once: only areas pay for the pairwise boundary
|
||||
/// check, so many maximal perimeters list in full.
|
||||
#[test]
|
||||
fn perimeters_are_charged_linear_work() {
|
||||
let measure = "<< /Type /Measure /Subtype /RL /R (1 pt = 1 pt) /X [<< /Type /NumberFormat /U (pt) /C 1 /D 100 >>] /D [<< /Type /NumberFormat /U (pt) /C 1 /D 100 >>] /A [<< /Type /NumberFormat /U (pt) /C 1 /D 100 >>] >>";
|
||||
let verts: Vec<String> = (0..MAX_POINTS).map(|i| format!("{} {}", 10 + i % 500, 10 + i / 500 * 3 + (i % 2))).collect();
|
||||
let verts = verts.join(" ");
|
||||
let lines = 40;
|
||||
let annots: Vec<String> = (0..lines).map(|i| format!("{} 0 R", 6 + i)).collect();
|
||||
let mut pdf = Pdf::new()
|
||||
.obj("<< /Type /Catalog /Pages 2 0 R >>")
|
||||
.obj("<< /Type /Pages /Kids [3 0 R] /Count 1 /MediaBox [0 0 612 792] >>")
|
||||
.obj(format!("<< /Type /Page /Parent 2 0 R /Contents 4 0 R /Annots [{}] >>", annots.join(" ")))
|
||||
.stream("", "")
|
||||
.obj(measure);
|
||||
for _ in 0..lines {
|
||||
pdf = pdf.obj(format!("<< /Type /Annot /Subtype /PolyLine /IT /PolyLineDimension /Rect [0 0 612 792] /Vertices [{verts}] /Measure 5 0 R >>"));
|
||||
}
|
||||
let d = Document::open(Arc::new(pdf.build())).unwrap();
|
||||
let l = list(&d);
|
||||
assert!(!l.truncated, "{} listed", l.measurements.len());
|
||||
assert_eq!(l.measurements.len() + l.unsupported.len(), lines, "{:?}", l.unsupported.first());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user