Merge pull request #5971 from slafebre/fix/5964-gradient-dash-corner

Part of #5964: stroke gradients cover an arrowhead to the end of its reach
This commit is contained in:
BFlat
2026-11-07 09:09:47 +08:00
committed by GitHub
3 changed files with 37 additions and 4 deletions
+14 -3
View File
@@ -174,10 +174,21 @@ fn strips(bp: &BezPath, rule: FillRule, st: &StrokeLayer, tol: f64, margin: f64,
}
let steps = if max_dt < 1.0 { (1.0 / max_dt).ceil() as usize } else { 1 };
let profile = st.profile.iter().flat_map(|p| p.points.iter().map(|q| q.0));
let at: Vec<f64> =
marks.iter().copied().chain(profile).chain((1..steps).map(|i| i as f64 / steps as f64)).map(|t| t * total).collect();
let heads = if closed { (0.0, 0.0) } else { heads };
// Where an arrowhead's reach ends gets a rib of its own, so the ribs that reach
// across a head run all the way there instead of narrowing towards the next corner
// from the head's tip, which leaves the corners of its base outside (#5964).
let head_ends = [heads.0, total - heads.1].into_iter().filter(|&s| s > 0.0 && s < total);
let at: Vec<f64> = marks
.iter()
.copied()
.chain(profile)
.chain((1..steps).map(|i| i as f64 / steps as f64))
.map(|t| t * total)
.chain(head_ends)
.collect();
let (pts, _) = split_at(&pts, &corner, closed, &at);
strip(&lay, &pts, closed, total, side, if closed { (0.0, 0.0) } else { heads })
strip(&lay, &pts, closed, total, side, heads)
}
};
out.push(ribs);
@@ -216,3 +216,24 @@ fn meshes_colour_the_stroke_as_the_slices_do() {
}
}
}
/// #5964: with ribs only at the path's corners (an Along gradient), an arrowhead whose tip sits on
/// the end of a long straight leg is covered all the way to where it can reach: the ribs that
/// reach across it run to the end of its reach, rather than narrowing from its tip towards the
/// next corner and leaving the corners of its base outside.
#[test]
fn slices_cover_an_arrowhead_on_a_long_straight_leg() {
let zig = poly(&[(0.0, 0.0), (60.0, 40.0), (0.0, 80.0), (70.0, 90.0), (75.0, 20.0)], false);
for profile in [None, WidthProfile::preset("lens"), WidthProfile::preset("taperStart")] {
for align in [ArrowAlign::Tip, ArrowAlign::Extend] {
for mode in [StrokeGradientMode::Along, StrokeGradientMode::Across] {
let mut st = stroke(12.0, mode);
st.start_arrow = Some(Arrowhead::Triangle);
st.end_arrow = Some(Arrowhead::Triangle);
st.arrow_align = align;
st.profile = profile.clone();
assert_covered(&zig, &st);
}
}
}
}
+2 -1
View File
@@ -1,6 +1,6 @@
# Parity with Adobe Illustrator
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-11-06 · **Change:** minor (Width profiles: smooth widths between width points, #5714; Drop Shadow and glow dialogs: spinner arrows, #5367, #5368; Stroke Weight Up and Down shortcuts, #5797; Hindi catalog and contributor loanword preferences; full wording review in progress; Properties in Edit Artboards: a Transform section with the reference point above the Artboards section, #5219; the Control bar's Stroke: and Opacity: links scrub their fields, #4088; an image zoomed in on is separated, colorized or proofed only where it shows (#4155); a document's first frame renders on the render worker, so opening a heavy file no longer freezes the window, #4155; Control bar Paragraph section with type selected, #5372; translating unchanged type reuses its glyph and character-stroke outlines; scores and estimates unchanged) · **Target:** Adobe Illustrator 2026 (30.x; public release notes through 30.7, August 2026)
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-11-06 · **Change:** minor (Stroke gradients: an arrowhead aligned to the tip is painted to the corners of its base, #5964; Drop Shadow and glow dialogs: spinner arrows, #5367, #5368; Stroke Weight Up and Down shortcuts, #5797; Hindi catalog and contributor loanword preferences; full wording review in progress; Properties in Edit Artboards: a Transform section with the reference point above the Artboards section, #5219; the Control bar's Stroke: and Opacity: links scrub their fields, #4088; an image zoomed in on is separated, colorized or proofed only where it shows (#4155); a document's first frame renders on the render worker, so opening a heavy file no longer freezes the window, #4155; Control bar Paragraph section with type selected, #5372; translating unchanged type reuses its glyph and character-stroke outlines; scores and estimates unchanged) · **Target:** Adobe Illustrator 2026 (30.x; public release notes through 30.7, August 2026)
## Feature submission evidence
@@ -31,6 +31,7 @@ Artboard Options forwards the active Artboard tool's Scale Artwork with Artboard
| Date | Change | Summary |
|---|---|---|
| 2026-11-06 | minor | Stroke gradients: an arrowhead whose tip sits on the end of a long straight leg is painted by the gradient to the corners of its base. The slices that reach across a head now run to the end of its reach instead of narrowing towards the next corner (#5964). Test: `stroke::tests_gradient::slices_cover_an_arrowhead_on_a_long_straight_leg`. Scores and estimates unchanged. |
| 2026-11-06 | minor | Width profiles: the width between two width points follows a smooth curve instead of a straight line, so a stroke no longer kinks at each width point (#5714). Each side is a monotone cubic through its points: flat at a widest or narrowest point, never past either point of a span; stacked points still step. Straight runs are sampled between width points to the drawing tolerance. Scores and estimates unchanged. |
| 2026-11-05 | minor | A nearby hit on a plain long stroke or outline avoids assembling its whole path. A hit near the middle of a 200,000-anchor path took about 11–13 ms before and 1.0–1.4 ms after in paired runs on a busy Windows machine; a miss inside the path's box fell from 18.7 ms to 1.6 ms, while a distant miss was unchanged. Other stroke styles and fill hits keep their existing checks. Scores and estimates unchanged; idle performance budgets remain unverified. |
| 2026-11-05 | minor | Translating a type object without changing its text or formatting reuses glyph geometry and expanded character-stroke outlines between frames. The text appears at its new position with unchanged pixels. Scaling the type, editing its content or formatting, or changing installed fonts rebuilds the geometry; scores and estimates unchanged. |