Gradients: Expand to a gradient mesh keeps a Perceptual gradient's colour curve

Review follow-up (CodeRabbit): a linear gradient expands to a mesh with a
column at each stop, and the mesh mixes linearly between columns, so a
Perceptual blue -> yellow came out as the grey RGB mix in the middle.
`breaks` now also takes a column at each stop the Perceptual expansion adds
(Gradient::expanded), so the mesh follows the OKLab curve; Classic is
unchanged. the_mesh_option_makes_a_mesh_that_paints_the_gradient gains a
Perceptual case; without the change 1812 pixels differ from the gradient.
This commit is contained in:
Taha-Mahmoodi
2026-10-23 01:53:30 +07:00
committed by bflatastic
parent 6fd1f566e1
commit 8924b24e94
2 changed files with 7 additions and 0 deletions
+5
View File
@@ -747,6 +747,11 @@ pub(crate) fn gradient_sampler(g: &GradientPaint, bounds: Rect, doc_model: Model
fn breaks(g: &Gradient, t0: f64, t1: f64, max_gap: f64) -> Vec<(f64, (Color, f32))> {
let at = |t: f64| (t, g.sample_keep_model(t as f32));
let mut v = vec![at(t0)];
// A Perceptual gradient curves between its stops: the mesh takes a column at each of the stops
// its expansion adds, so the linear mix between columns follows that curve.
if !g.method.is_classic() {
v.extend(g.expanded().map(|(o, ..)| f64::from(o)).filter(|o| *o > t0 && *o < t1).map(at));
}
for (i, s) in g.stops.iter().enumerate() {
let o = s.offset as f64;
if o > t0 && o < t1 {
+2
View File
@@ -197,6 +197,8 @@ fn the_mesh_option_makes_a_mesh_that_paints_the_gradient() {
for gradient in [
json!({"kind": "linear", "angle": 30, "stops": [{"offset": 0, "color": "#ff0000"}, {"offset": 0.4, "color": "#00ff00", "midpoint": 0.3}, {"offset": 1, "color": "#0000ff"}]}),
json!({"kind": "radial", "stops": [{"offset": 0, "color": "#ffff00"}, {"offset": 0.5, "color": "#ff00ff"}, {"offset": 1, "color": "#004080"}]}),
// Perceptual: the mesh follows the OKLab curve between the stops, not a straight RGB mix.
json!({"kind": "linear", "method": "perceptual", "stops": [{"offset": 0, "color": "#2050f0"}, {"offset": 1, "color": "#f5d020"}]}),
] {
let mut s = session();
gradient_rect(&mut s, Rect::new(30.0, 40.0, 170.0, 160.0), gradient.clone(), false);