AF.5: cap dash patterns at 64 lengths

A line style's `Patn` was copied twice (filtered, then scaled) whatever its
length, before any budget saw it. Patterns longer than 64 lengths now import
as solid lines, with a warning.

Addresses CodeRabbit's third review on #3548.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
dwetscher
2026-10-22 18:44:39 +07:00
committed by bflatastic
co-authored by Claude Opus 5.5
parent b3ccdf01a7
commit 2d7004f972
2 changed files with 20 additions and 0 deletions
+7
View File
@@ -126,6 +126,9 @@ pub struct Stroke {
/// Gradient stops per gradient.
const MAX_STOPS: usize = 1024;
/// Dash and gap lengths per dash pattern (a pattern has a few; strokes and text runs copy theirs).
const MAX_DASHES: usize = 64;
fn floats(v: &Value) -> Option<Vec<f64>> {
match v {
Value::Floats(f) => Some(f.clone()),
@@ -319,6 +322,10 @@ pub(crate) fn stroke(r: &mut Reader, pen: ObjId, ldsc: ObjId, local: Affine, beh
_ => Align::Center,
};
let dash = match s.field(lsty, b"Patn") {
Some(Value::Array(a)) if a.len() > MAX_DASHES => {
r.warn("dash patterns of more than 64 lengths (imported as solid lines)");
None
}
Some(Value::Array(a)) if data.get(10) == Some(&2) || !a.is_empty() => {
let mut v: Vec<f64> = a.iter().filter_map(|x| if let Value::Float(f) = x { Some(*f) } else { None }).collect();
while v.len() >= 2 && v.iter().rev().take(2).all(|x| *x == 0.0) {