diff --git a/crates/affinity/src/geometry.rs b/crates/affinity/src/geometry.rs index 945c3040f..bb1c45746 100644 --- a/crates/affinity/src/geometry.rs +++ b/crates/affinity/src/geometry.rs @@ -178,6 +178,10 @@ const MAX_PRESSURE_SEGMENTS: usize = 256; /// points; the document's limit counts all of them. const PRESSURE_POINTS: usize = 512; +/// Most points one pressure curve can have (see [`PRESSURE_POINTS`]). A curve that can't be read +/// counts this many against the document's limit. +pub(crate) const MAX_PRESSURE_CURVE_POINTS: usize = 1 + 4 * MAX_PRESSURE_SEGMENTS; + /// A stroke's pressure curve (`LDsc.LDeP`, a `CrvD` whose positional `Data` holds an array of /// 18-byte records as in [`curves`]): x is the position along the path (0 to 1) and y the width as /// a fraction of the stroke's weight. Each segment is sampled at 2 to 8 points, at most diff --git a/crates/affinity/src/paint.rs b/crates/affinity/src/paint.rs index cfc95b8dd..12102581e 100644 --- a/crates/affinity/src/paint.rs +++ b/crates/affinity/src/paint.rs @@ -357,8 +357,9 @@ pub(crate) fn stroke(r: &mut Reader, pen: ObjId, ldsc: ObjId, local: Affine, beh r.warn("brush strokes (imported as plain strokes)"); } // The pressure curve sets the width along the path; one at full width all along is a plain - // stroke. Every curve read, full width or not, counts against the document's points, and once - // they are used up the rest are not read. + // stroke. Every curve read counts against the document's points: one at full width counts its + // points, and one that can't be read counts the most a curve may have. Once the points are + // used up the rest are not read. const BEYOND: &str = "pressure strokes beyond the pressure points one document may hold (imported as plain strokes)"; let ldep = s.obj(ldsc, b"LDeP"); if ldep.is_some() && r.budget.pressure == 0 { @@ -377,6 +378,7 @@ pub(crate) fn stroke(r: &mut Reader, pen: ObjId, ldsc: ObjId, local: Affine, beh } }, Some(None) => { + r.budget.pressure = r.budget.pressure.saturating_sub(crate::geometry::MAX_PRESSURE_CURVE_POINTS); r.warn("pressure strokes whose pressure curve can't be read (imported as plain strokes)"); None } diff --git a/crates/engine/src/cmd/fileio/tests_affinity.rs b/crates/engine/src/cmd/fileio/tests_affinity.rs index a57da79fc..70b9b992a 100644 --- a/crates/engine/src/cmd/fileio/tests_affinity.rs +++ b/crates/engine/src/cmd/fileio/tests_affinity.rs @@ -462,6 +462,12 @@ mod native { let flat: Vec> = (0..=768).map(|i| node(f64::from(i) / 768.0, 1.0, if i % 3 == 0 { 4 } else { 0 }, (i % 3) as u8)).collect(); let r = load("flat-many.af", &pressure_documents(flat, 2100)).unwrap(); assert!(r.warnings.iter().any(|w| w.contains("pressure points one document may hold")), "{:?}", r.warnings); + + // So do curves that can't be read: 768 segments, more than a curve may have. + let long: Vec> = (0..=768).map(|i| node(f64::from(i) / 768.0, f64::from(i % 2), 4, 0)).collect(); + let r = load("long-many.af", &pressure_documents(long, 2100)).unwrap(); + assert!(r.warnings.iter().any(|w| w.contains("pressure curve can't be read")), "{:?}", r.warnings); + assert!(r.warnings.iter().any(|w| w.contains("pressure points one document may hold")), "{:?}", r.warnings); } #[test]