Affinity: pressure curves that can't be read count against the document's limit

A curve rejected for having more than 256 segments now counts the most points a curve may have against the document's pressure points, so linking it from many strokes reads it a bounded number of times. Once the points are used up, later strokes import as plain strokes with a warning.
This commit is contained in:
dotCooCoo
2026-11-01 18:09:53 -08:00
parent e441d3ba18
commit 1186d1f712
3 changed files with 14 additions and 2 deletions
+4
View File
@@ -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
+4 -2
View File
@@ -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
}
@@ -462,6 +462,12 @@ mod native {
let flat: Vec<Vec<u8>> = (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<Vec<u8>> = (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]