mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-31 13:17:19 -06:00
Fix #3232: a CMYK gradient mesh keeps its K when lightened
Create Gradient Mesh's To Center / To Edge highlight lightened every point towards RGB white, so a CMYK (or grey) point became display RGB. A patch with any non-CMYK corner then mixes in RGB, and the PDF writer separated those colours back to CMYK with K = 0, moving ink off the K plate. Points now lighten towards white in their own colour model (no ink for CMYK), so the mesh stays CMYK and K shrinks with the other inks. Flat meshes (highlight 0) already kept their inks.
This commit is contained in:
@@ -221,6 +221,25 @@ mod tests {
|
||||
assert!(matches!(m.color_at(0, 0, 0.5, 0.5).0, Color::Rgb { .. }));
|
||||
}
|
||||
|
||||
/// #3232: the Appearance highlight lightens each point towards white in its own model, so a
|
||||
/// CMYK mesh stays CMYK (K shrinks with the other inks) and a grey one stays grey.
|
||||
#[test]
|
||||
fn mesh_highlight_keeps_each_points_model() {
|
||||
let square = shapes::rectangle(Rect::new(0.0, 0.0, 100.0, 100.0));
|
||||
let ink = Color::Cmyk { c: 0.0, m: 0.4, y: 0.6, k: 0.1 };
|
||||
let m = GradientMesh::for_path(&square, 2, 2, ink, MeshAppearance::ToCenter, 50.0).unwrap();
|
||||
assert_eq!(m.points[0].color, ink, "corners stay");
|
||||
let centre = m.points[m.idx(1, 1)].color;
|
||||
let Color::Cmyk { c, m: mg, y, k } = centre else { panic!("{centre:?}") };
|
||||
assert!(c.abs() < 1e-6 && (mg - 0.2).abs() < 1e-6 && (y - 0.3).abs() < 1e-6 && (k - 0.05).abs() < 1e-6, "{c} {mg} {y} {k}");
|
||||
assert!(matches!(m.color_at(0, 0, 0.5, 0.5).0, Color::Cmyk { .. }), "patches mix in CMYK");
|
||||
let m = GradientMesh::for_path(&square, 2, 2, Color::gray(0.8), MeshAppearance::ToEdge, 100.0).unwrap();
|
||||
assert_eq!((m.points[0].color, m.points[m.idx(1, 1)].color), (Color::gray(0.0), Color::gray(0.8)));
|
||||
// RGB lightens in RGB as before.
|
||||
let m = GradientMesh::for_path(&square, 2, 2, Color::rgb(1.0, 0.0, 0.0), MeshAppearance::ToCenter, 100.0).unwrap();
|
||||
assert_eq!(m.points[m.idx(1, 1)].color.to_hex(), "#ffffff");
|
||||
}
|
||||
|
||||
/// Alt-clicking a point of a mesh from a file with fewer points than its rows and columns need
|
||||
/// deletes nothing (it indexed past the points, a panic).
|
||||
#[test]
|
||||
|
||||
@@ -267,7 +267,8 @@ impl GradientMesh {
|
||||
}
|
||||
|
||||
/// Create Gradient Mesh → Appearance: lighten the points towards white, to the centre or to
|
||||
/// the edges, by at most `highlight` %.
|
||||
/// the edges, by at most `highlight` %. Each point lightens towards white in its own colour
|
||||
/// model (paper white, no ink, for CMYK), so a CMYK or grey mesh keeps its inks (#3232).
|
||||
pub fn highlight(&mut self, appearance: MeshAppearance, highlight: f64) {
|
||||
let h = (highlight / 100.0).clamp(0.0, 1.0) as f32;
|
||||
let (rows, cols) = (self.rows as usize, self.cols as usize);
|
||||
@@ -282,7 +283,8 @@ impl GradientMesh {
|
||||
};
|
||||
if w > 0.0 {
|
||||
let i = self.idx(r, c);
|
||||
self.points[i].color = lerp_color(&self.points[i].color, &Color::WHITE, w);
|
||||
let color = self.points[i].color;
|
||||
self.points[i].color = lerp_color(&color, &Color::WHITE.in_model(color.model()), w);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user