diff --git a/Cargo.lock b/Cargo.lock index a3ec299c5..936d44795 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -432,6 +432,14 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "color" +version = "0.1.0" +source = "git+https://github.com/linebender/color.git?rev=bccd4050607eba830cfba3b2f39616a27500288a#bccd4050607eba830cfba3b2f39616a27500288a" +dependencies = [ + "serde", +] + [[package]] name = "colorchoice" version = "1.0.3" @@ -1631,9 +1639,9 @@ checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "peniko" version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a648c93f502a0bef0a9cb47fa1335994958a2744667d3f82defe513f276741a" +source = "git+https://github.com/linebender/peniko.git?rev=cb75a00#cb75a00f1915b46e65a47cbef69f693934b27629" dependencies = [ + "color", "kurbo", "smallvec", ] @@ -2042,18 +2050,18 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.214" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5" +checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.214" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" +checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index 50f1f07aa..646eb36e3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -101,7 +101,8 @@ bytemuck = { version = "1.18.0", features = ["derive"] } skrifa = "0.22.3" # The version of kurbo used below should be kept in sync # with the version of kurbo used by peniko. -peniko = "0.2.0" +# peniko = "0.2.0" +peniko = { version = "0.2.0", git = "https://github.com/linebender/peniko.git", rev = "cb75a00" } # FIXME: This can be removed once peniko supports the schemars feature. kurbo = "0.11.1" futures-intrusive = "0.5.0" diff --git a/examples/scenes/src/lib.rs b/examples/scenes/src/lib.rs index 3248a1bc8..b6870fe2a 100644 --- a/examples/scenes/src/lib.rs +++ b/examples/scenes/src/lib.rs @@ -32,7 +32,6 @@ mod simple_text; mod svg; pub mod test_scenes; -use anyhow::{anyhow, Result}; use clap::Args; pub use images::ImageCache; pub use simple_text::SimpleText; @@ -41,7 +40,7 @@ pub use svg::{default_scene, scene_from_files}; use test_scenes::test_scenes; use vello::kurbo::Vec2; -use vello::peniko::Color; +use vello::peniko::{color, Color}; use vello::Scene; pub struct SceneParams<'a> { @@ -93,7 +92,7 @@ pub struct Arguments { /// The svg files paths to render svgs: Option>, #[arg(help_heading = "Render Parameters")] - #[arg(long, global(false), value_parser = parse_color)] + #[arg(long, global(false), value_parser = parse_color_arg)] /// The base color applied as the blend background to the rasterizer. /// Format is CSS style hexadecimal (#RGB, #RGBA, #RRGGBB, #RRGGBBAA) or /// an SVG color name such as "aliceblue" @@ -101,7 +100,7 @@ pub struct Arguments { } impl Arguments { - pub fn select_scene_set(&self) -> Result> { + pub fn select_scene_set(&self) -> anyhow::Result> { // There is no file access on WASM, and on Android we haven't set up the assets // directory. // TODO: Upload the assets directory on Android @@ -120,6 +119,6 @@ impl Arguments { } } -fn parse_color(s: &str) -> Result { - Color::parse(s).ok_or(anyhow!("'{s}' is not a valid color")) +fn parse_color_arg(s: &str) -> Result { + color::parse_color(s).map(|c| c.to_alpha_color()) } diff --git a/examples/scenes/src/mmark.rs b/examples/scenes/src/mmark.rs index bd901155e..45b419ac3 100644 --- a/examples/scenes/src/mmark.rs +++ b/examples/scenes/src/mmark.rs @@ -118,13 +118,13 @@ impl TestScene for MMark { } const COLORS: &[Color] = &[ - Color::rgb8(0x10, 0x10, 0x10), - Color::rgb8(0x80, 0x80, 0x80), - Color::rgb8(0xc0, 0xc0, 0xc0), - Color::rgb8(0x10, 0x10, 0x10), - Color::rgb8(0x80, 0x80, 0x80), - Color::rgb8(0xc0, 0xc0, 0xc0), - Color::rgb8(0xe0, 0x10, 0x40), + Color::from_rgba8(0x10, 0x10, 0x10, 0xff), + Color::from_rgba8(0x80, 0x80, 0x80, 0xff), + Color::from_rgba8(0xc0, 0xc0, 0xc0, 0xff), + Color::from_rgba8(0x10, 0x10, 0x10, 0xff), + Color::from_rgba8(0x80, 0x80, 0x80, 0xff), + Color::from_rgba8(0xc0, 0xc0, 0xc0, 0xff), + Color::from_rgba8(0xe0, 0x10, 0x40, 0xff), ]; impl Element { diff --git a/examples/scenes/src/pico_svg.rs b/examples/scenes/src/pico_svg.rs index bf8a2707f..5c776bcbd 100644 --- a/examples/scenes/src/pico_svg.rs +++ b/examples/scenes/src/pico_svg.rs @@ -8,7 +8,7 @@ use std::str::FromStr; use roxmltree::{Document, Node}; use vello::{ kurbo::{Affine, BezPath, Point, Size, Vec2}, - peniko::Color, + peniko::{color, Color}, }; pub struct PicoSvg { @@ -260,30 +260,29 @@ fn parse_transform(transform: &str) -> Affine { fn parse_color(color: &str) -> Color { let color = color.trim(); - if let Some(c) = Color::parse(color) { - c + if let Ok(c) = color::parse_color(color) { + c.to_alpha_color() } else if let Some(s) = color.strip_prefix("rgb(").and_then(|s| s.strip_suffix(')')) { let mut iter = s.split([',', ' ']).map(str::trim).map(u8::from_str); let r = iter.next().unwrap().unwrap(); let g = iter.next().unwrap().unwrap(); let b = iter.next().unwrap().unwrap(); - Color::rgb8(r, g, b) + Color::from_rgba8(r, g, b, 255) } else { - Color::rgba8(255, 0, 255, 0x80) + Color::from_rgba8(255, 0, 255, 0x80) } } -fn modify_opacity(mut color: Color, attr_name: &str, node: Node<'_, '_>) -> Color { +fn modify_opacity(color: Color, attr_name: &str, node: Node<'_, '_>) -> Color { if let Some(opacity) = node.attribute(attr_name) { - let alpha: f64 = if let Some(o) = opacity.strip_suffix('%') { + let alpha: f32 = if let Some(o) = opacity.strip_suffix('%') { let pctg = o.parse().unwrap_or(100.0); pctg * 0.01 } else { opacity.parse().unwrap_or(1.0) }; - color.a = (alpha.clamp(0.0, 1.0) * 255.0).round() as u8; - color + color.with_alpha(alpha.clamp(0., 1.)) } else { color } diff --git a/examples/scenes/src/svg.rs b/examples/scenes/src/svg.rs index 06027b545..370596845 100644 --- a/examples/scenes/src/svg.rs +++ b/examples/scenes/src/svg.rs @@ -12,7 +12,7 @@ use web_time::Instant; use anyhow::Result; use vello::{ kurbo::{Affine, Rect, Stroke, Vec2}, - peniko::{Color, Fill}, + peniko::{color::palette, Fill}, Scene, }; @@ -124,7 +124,7 @@ pub fn svg_function_of>( error_scene.fill( Fill::NonZero, Affine::IDENTITY, - Color::FUCHSIA, + palette::css::FUCHSIA, None, &Rect::new(0.0, 0.0, 1.0, 1.0), ); diff --git a/examples/scenes/src/test_scenes.rs b/examples/scenes/src/test_scenes.rs index a2a02491a..e0c1affe7 100644 --- a/examples/scenes/src/test_scenes.rs +++ b/examples/scenes/src/test_scenes.rs @@ -96,6 +96,7 @@ mod impls { use vello::kurbo::{ Affine, BezPath, Cap, Circle, Ellipse, Join, PathEl, Point, Rect, Shape, Stroke, Vec2, }; + use vello::peniko::color::{palette, AlphaColor, Lch}; use vello::peniko::*; use vello::*; @@ -137,28 +138,28 @@ mod impls { scene.fill( Fill::NonZero, Affine::translate((100.0, 100.0)), - Color::rgb8(0, 0, 255), + Color::from_rgba8(0, 0, 255, 255), None, &missing_movetos, ); scene.fill( Fill::NonZero, Affine::IDENTITY, - Color::rgb8(0, 0, 255), + Color::from_rgba8(0, 0, 255, 255), None, &empty, ); scene.fill( Fill::NonZero, Affine::IDENTITY, - Color::rgb8(0, 0, 255), + Color::from_rgba8(0, 0, 255, 255), None, &only_movetos, ); scene.stroke( &Stroke::new(8.0), Affine::translate((100.0, 100.0)), - Color::rgb8(0, 255, 255), + Color::from_rgba8(0, 255, 255, 255), None, &missing_movetos, ); @@ -168,10 +169,10 @@ mod impls { use PathEl::*; move |scene, params| { let colors = [ - Color::rgb8(140, 181, 236), - Color::rgb8(246, 236, 202), - Color::rgb8(201, 147, 206), - Color::rgb8(150, 195, 160), + Color::from_rgba8(140, 181, 236, 255), + Color::from_rgba8(246, 236, 202, 255), + Color::from_rgba8(201, 147, 206, 255), + Color::from_rgba8(150, 195, 160, 255), ]; let simple_stroke = [MoveTo((0., 0.).into()), LineTo((100., 0.).into())]; let join_stroke = [ @@ -345,10 +346,10 @@ mod impls { pub(super) fn tricky_strokes(scene: &mut Scene, params: &mut SceneParams) { use PathEl::*; let colors = [ - Color::rgb8(140, 181, 236), - Color::rgb8(246, 236, 202), - Color::rgb8(201, 147, 206), - Color::rgb8(150, 195, 160), + Color::from_rgba8(140, 181, 236, 255), + Color::from_rgba8(246, 236, 202, 255), + Color::from_rgba8(201, 147, 206, 255), + Color::from_rgba8(150, 195, 160, 255), ]; const CELL_SIZE: f64 = 200.; @@ -563,14 +564,14 @@ mod impls { scene.fill( Fill::NonZero, t, - &Brush::Solid(Color::rgb8(128, 128, 128)), + &Brush::Solid(Color::from_rgba8(128, 128, 128, 255)), None, &rect, ); scene.fill( rule.0, Affine::translate((0., 10.)) * t, - Color::YELLOW, + palette::css::YELLOW, None, &rule.2, ); @@ -585,28 +586,28 @@ mod impls { scene.fill( Fill::NonZero, t, - &Brush::Solid(Color::rgb8(128, 128, 128)), + &Brush::Solid(Color::from_rgba8(128, 128, 128, 255)), None, &rect, ); scene.fill( rule.0, Affine::translate((0., 10.)) * t, - Color::YELLOW, + palette::css::YELLOW, None, &rule.2, ); scene.fill( rule.0, Affine::translate((0., 10.)) * t * Affine::rotate(0.06), - Color::rgba(0., 1., 0.7, 0.6), + Color::new([0., 1., 0.7, 0.6]), None, &rule.2, ); scene.fill( rule.0, Affine::translate((0., 10.)) * t * Affine::rotate(-0.06), - Color::rgba(0.9, 0.7, 0.5, 0.6), + Color::new([0.9, 0.7, 0.5, 0.6]), None, &rule.2, ); @@ -657,7 +658,7 @@ mod impls { .with_join(Join::Bevel) .with_dashes(0.0, [1.0, 1.0]), Affine::translate((50.0, 50.0)), - Color::YELLOW, + palette::css::YELLOW, None, &path, ); @@ -685,7 +686,7 @@ mod impls { scene.fill( Fill::NonZero, Affine::IDENTITY, - &Brush::Solid(Color::rgb8(128, 128, 128)), + &Brush::Solid(Color::from_rgba8(128, 128, 128, 255)), None, &rect, ); @@ -703,7 +704,7 @@ mod impls { scene, None, text_size, - Color::WHITE, + palette::css::WHITE, Affine::translate((110.0, 700.0)), // Add a skew to simulate an oblique font. Some(Affine::skew(20f64.to_radians().tan(), 0.0)), @@ -718,7 +719,7 @@ mod impls { None, 72.0, &[("wght", weight), ("wdth", width)], - Color::WHITE, + palette::css::WHITE, Affine::translate((110.0, 800.0)), // Add a skew to simulate an oblique font. None, @@ -733,14 +734,14 @@ mod impls { scene.stroke( &Stroke::new(5.0), Affine::IDENTITY, - &Brush::Solid(Color::rgb8(128, 0, 0)), + &Brush::Solid(Color::from_rgba8(128, 0, 0, 255)), None, &[MoveTo(center), LineTo(p1)], ); scene.fill( Fill::NonZero, Affine::translate((150.0, 150.0)) * Affine::scale(0.2), - Color::RED, + palette::css::RED, None, &rect, ); @@ -749,14 +750,14 @@ mod impls { scene.fill( Fill::NonZero, Affine::translate((100.0, 100.0)) * Affine::scale(0.2), - Color::BLUE, + palette::css::BLUE, None, &rect, ); scene.fill( Fill::NonZero, Affine::translate((200.0, 200.0)) * Affine::scale(0.2), - Color::GREEN, + palette::css::GREEN, None, &rect, ); @@ -764,14 +765,14 @@ mod impls { scene.fill( Fill::NonZero, Affine::translate((400.0, 100.0)), - Color::PURPLE, + palette::css::PURPLE, None, &star, ); scene.fill( Fill::EvenOdd, Affine::translate((500.0, 100.0)), - Color::PURPLE, + palette::css::PURPLE, None, &star, ); @@ -784,17 +785,17 @@ mod impls { pub(super) fn brush_transform(scene: &mut Scene, params: &mut SceneParams) { let th = params.time; let linear = Gradient::new_linear((0.0, 0.0), (0.0, 200.0)).with_stops([ - Color::RED, - Color::GREEN, - Color::BLUE, + palette::css::RED, + palette::css::GREEN, + palette::css::BLUE, ]); scene.fill( Fill::NonZero, Affine::rotate(25f64.to_radians()) * Affine::scale_non_uniform(2.0, 1.0), &Gradient::new_radial((200.0, 200.0), 80.0).with_stops([ - Color::RED, - Color::GREEN, - Color::BLUE, + palette::css::RED, + palette::css::GREEN, + palette::css::BLUE, ]), None, &Rect::from_origin_size((100.0, 100.0), (200.0, 200.0)), @@ -822,7 +823,11 @@ mod impls { Sweep, } pub(super) fn square(scene: &mut Scene, kind: Kind, transform: Affine, extend: Extend) { - let colors = [Color::RED, Color::rgb8(0, 255, 0), Color::BLUE]; + let colors = [ + palette::css::RED, + Color::from_rgba8(0, 255, 0, 255), + palette::css::BLUE, + ]; let width = 300f64; let height = 300f64; let gradient: Brush = match kind { @@ -874,7 +879,7 @@ mod impls { scene, None, 32.0, - Some(&Color::WHITE.into()), + Some(&palette::css::WHITE.into()), Affine::translate((x, 70.0)), label, ); @@ -894,11 +899,15 @@ mod impls { transform: Affine, extend: Extend, ) { - let colors = [Color::RED, Color::YELLOW, Color::rgb8(6, 85, 186)]; + let colors = [ + palette::css::RED, + palette::css::YELLOW, + Color::from_rgba8(6, 85, 186, 255), + ]; let width = 400f64; let height = 200f64; let rect = Rect::new(0.0, 0.0, width, height); - scene.fill(Fill::NonZero, transform, Color::WHITE, None, &rect); + scene.fill(Fill::NonZero, transform, palette::css::WHITE, None, &rect); scene.fill( Fill::NonZero, transform, @@ -914,14 +923,14 @@ mod impls { scene.stroke( &Stroke::new(stroke_width), transform, - Color::BLACK, + palette::css::BLACK, None, &Ellipse::new((x0, y0), (r0, r0), 0.0), ); scene.stroke( &Stroke::new(stroke_width), transform, - Color::BLACK, + palette::css::BLACK, None, &Ellipse::new((x1, y1), (r1, r1), 0.0), ); @@ -1080,19 +1089,19 @@ mod impls { scene.fill( Fill::EvenOdd, Affine::IDENTITY, - Color::RED, + palette::css::RED, None, &main_rect, ); let options = [ - (800., Color::AQUA), - (700., Color::RED), - (600., Color::ALICE_BLUE), - (500., Color::YELLOW), - (400., Color::GREEN), - (300., Color::BLUE), - (200., Color::ORANGE), - (100., Color::WHITE), + (800., palette::css::AQUA), + (700., palette::css::RED), + (600., palette::css::ALICE_BLUE), + (500., palette::css::YELLOW), + (400., palette::css::GREEN), + (300., palette::css::BLUE), + (200., palette::css::ORANGE), + (100., palette::css::WHITE), ]; let mut depth = 0; for (width, colour) in &options[..params.complexity.min(options.len() - 1)] { @@ -1127,7 +1136,7 @@ mod impls { scene.push_layer(Mix::Clip, 1.0, translate * rot, &base_tri); } let rot = Affine::rotate(rng.gen_range(0.0..PI)); - let color = Color::rgb(rng.r#gen(), rng.r#gen(), rng.r#gen()); + let color = Color::new([rng.r#gen(), rng.r#gen(), rng.r#gen(), 1.]); scene.fill(Fill::NonZero, translate * rot, color, None, &base_tri); for _ in 0..CLIPS_PER_FILL { scene.pop_layer(); @@ -1159,7 +1168,7 @@ mod impls { scene.stroke( &Stroke::new(2.0), Affine::IDENTITY, - Color::rgb8(0, 0, 255), + Color::from_rgba8(0, 0, 255, 255), None, &path, ); @@ -1190,7 +1199,7 @@ mod impls { scene.fill( Fill::NonZero, Affine::IDENTITY, - &Brush::Solid(Color::rgb8(0, 255, 0)), + &Brush::Solid(Color::from_rgba8(0, 255, 0, 255)), None, &rect, ); @@ -1204,14 +1213,14 @@ mod impls { scene.fill( Fill::NonZero, Affine::IDENTITY, - Color::rgb8(255, 0, 0), + Color::from_rgba8(255, 0, 0, 255), None, &make_diamond(1024.0, 100.0), ); scene.fill( Fill::NonZero, Affine::IDENTITY, - Color::rgba8(0, 255, 0, 0x80), + Color::from_rgba8(0, 255, 0, 0x80), None, &make_diamond(1024.0, 125.0), ); @@ -1224,7 +1233,7 @@ mod impls { scene.fill( Fill::NonZero, Affine::IDENTITY, - Color::rgba8(0, 0, 255, 0x80), + Color::from_rgba8(0, 0, 255, 0x80), None, &make_diamond(1024.0, 175.0), ); @@ -1234,29 +1243,28 @@ mod impls { pub(super) fn render_blend_square(scene: &mut Scene, blend: BlendMode, transform: Affine) { // Inspired by https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode let rect = Rect::from_origin_size(Point::new(0., 0.), (200., 200.)); - let linear = - Gradient::new_linear((0.0, 0.0), (200.0, 0.0)).with_stops([Color::BLACK, Color::WHITE]); + let linear = Gradient::new_linear((0.0, 0.0), (200.0, 0.0)) + .with_stops([palette::css::BLACK, palette::css::WHITE]); scene.fill(Fill::NonZero, transform, &linear, None, &rect); const GRADIENTS: &[(f64, f64, Color)] = &[ - (150., 0., Color::rgb8(255, 240, 64)), - (175., 100., Color::rgb8(255, 96, 240)), - (125., 200., Color::rgb8(64, 192, 255)), + (150., 0., Color::from_rgba8(255, 240, 64, 255)), + (175., 100., Color::from_rgba8(255, 96, 240, 255)), + (125., 200., Color::from_rgba8(64, 192, 255, 255)), ]; for (x, y, c) in GRADIENTS { - let mut color2 = *c; - color2.a = 0; + let color2 = c.with_alpha(0.); let radial = Gradient::new_radial((*x, *y), 100.0).with_stops([*c, color2]); scene.fill(Fill::NonZero, transform, &radial, None, &rect); } const COLORS: &[Color] = &[ - Color::rgb8(255, 0, 0), - Color::rgb8(0, 255, 0), - Color::rgb8(0, 0, 255), + Color::from_rgba8(255, 0, 0, 255), + Color::from_rgba8(0, 255, 0, 255), + Color::from_rgba8(0, 0, 255, 255), ]; scene.push_layer(Mix::Normal, 1.0, transform, &rect); for (i, c) in COLORS.iter().enumerate() { - let linear = - Gradient::new_linear((0.0, 0.0), (0.0, 200.0)).with_stops([Color::WHITE, *c]); + let linear = Gradient::new_linear((0.0, 0.0), (0.0, 200.0)) + .with_stops([palette::css::WHITE, *c]); scene.push_layer(blend, 1.0, transform, &rect); // squash the ellipse let a = transform @@ -1291,8 +1299,8 @@ mod impls { let x = N + 0.5; // Fractional pixel offset reveals the problem on axis-aligned edges. let mut y = N; - let bg_color = Color::rgb8(255, 194, 19); - let fg_color = Color::rgb8(12, 165, 255); + let bg_color = Color::from_rgba8(255, 194, 19, 255); + let fg_color = Color::from_rgba8(12, 165, 255, 255); // Two adjacent triangles touching at diagonal edge with opposing winding numbers scene.fill( @@ -1442,7 +1450,7 @@ mod impls { scene.fill( Fill::NonZero, Affine::translate((20.5, 20.5)) * Affine::scale(80.0), - Color::rgba8(0x70, 0x80, 0x80, 0xff), + Color::from_rgba8(0x70, 0x80, 0x80, 0xff), None, &path, ); @@ -1495,11 +1503,17 @@ mod impls { path.line_to((256.0, 24.5)); path.line_to((241.0, 24.5)); path.close_path(); - scene.fill(Fill::NonZero, Affine::IDENTITY, Color::YELLOW, None, &path); + scene.fill( + Fill::NonZero, + Affine::IDENTITY, + palette::css::YELLOW, + None, + &path, + ); scene.fill( Fill::EvenOdd, Affine::translate((300.0, 0.0)), - Color::LIME, + palette::css::LIME, None, &path, ); @@ -1512,14 +1526,14 @@ mod impls { scene.fill( Fill::NonZero, Affine::translate((0.0, 100.0)), - Color::YELLOW, + palette::css::YELLOW, None, &path, ); scene.fill( Fill::EvenOdd, Affine::translate((300.0, 100.0)), - Color::LIME, + palette::css::LIME, None, &path, ); @@ -1527,14 +1541,14 @@ mod impls { pub(super) fn base_color_test(scene: &mut Scene, params: &mut SceneParams) { // Cycle through the hue value every 5 seconds (t % 5) * 360/5 - let color = Color::hlc((params.time % 5.0) * 72.0, 80.0, 80.0); - params.base_color = Some(color); + let color = AlphaColor::::new([80., 80., (params.time % 5.) as f32 * 72., 1.]); + params.base_color = Some(color.convert()); // Blend a white square over it. scene.fill( Fill::NonZero, Affine::IDENTITY, - Color::rgba8(255, 255, 255, 128), + Color::from_rgba8(255, 255, 255, 128), None, &Rect::new(50.0, 50.0, 500.0, 500.0), ); @@ -1594,7 +1608,7 @@ mod impls { scene.fill( Fill::NonZero, Affine::new([scale, 0.0, 0.0, scale, 27.07470703125, 176.40660533027858]), - Color::rgb8(0, 0, 255), + Color::from_rgba8(0, 0, 255, 255), None, &large_background_rect, ); @@ -1608,7 +1622,7 @@ mod impls { 29.027636718750003, 182.9755506427786, ]), - Color::rgb8(0, 255, 0), + Color::from_rgba8(0, 255, 0, 255), None, &inside_clip_rect, ); @@ -1622,7 +1636,7 @@ mod impls { 29.027636718750003, scale * 559.3583631427786, ]), - Color::rgb8(255, 0, 0), + Color::from_rgba8(255, 0, 0, 255), None, &outside_clip_rect, ); @@ -1656,7 +1670,13 @@ mod impls { for i in 0..N_WIDE { let x = (i as f64 + 0.5) * (SCENE_WIDTH / N_WIDE as f64); let c = Circle::new((x, y), 3.0); - scene.fill(Fill::NonZero, Affine::IDENTITY, Color::YELLOW, None, &c); + scene.fill( + Fill::NonZero, + Affine::IDENTITY, + palette::css::YELLOW, + None, + &c, + ); } } } @@ -1701,14 +1721,14 @@ mod impls { pub(super) fn blurred_rounded_rect(scene: &mut Scene, params: &mut SceneParams) { params.resolution = Some(Vec2::new(1200., 1200.)); - params.base_color = Some(Color::WHITE); + params.base_color = Some(palette::css::WHITE); let rect = Rect::from_center_size((0.0, 0.0), (300.0, 240.0)); let radius = 50.0; scene.draw_blurred_rounded_rect( Affine::translate((300.0, 300.0)), rect, - Color::BLUE, + palette::css::BLUE, radius, params.time.sin() * 50.0 + 50.0, ); @@ -1717,7 +1737,7 @@ mod impls { scene.draw_blurred_rounded_rect( Affine::translate((900.0, 300.0)) * Affine::skew(20f64.to_radians().tan(), 0.0), rect, - Color::BLACK, + palette::css::BLACK, radius, params.time.sin() * 50.0 + 50.0, ); @@ -1726,7 +1746,7 @@ mod impls { scene.draw_blurred_rounded_rect( Affine::IDENTITY, Rect::new(100.0, 800.0, 400.0, 1100.0), - Color::BLACK, + palette::css::BLACK, 150.0, params.time.sin() * 50.0 + 50.0, ); @@ -1735,7 +1755,7 @@ mod impls { scene.draw_blurred_rounded_rect( Affine::IDENTITY, Rect::new(600.0, 800.0, 900.0, 900.0), - Color::BLACK, + palette::css::BLACK, 150.0, params.time.sin() * 50.0 + 50.0, ); @@ -1758,7 +1778,7 @@ mod impls { &shape, Affine::translate((600.0, 600.0)) * Affine::scale_non_uniform(2.2, 0.9), rect, - Color::BLACK, + palette::css::BLACK, radius, std_dev, ); @@ -1766,17 +1786,23 @@ mod impls { pub(super) fn image_sampling(scene: &mut Scene, params: &mut SceneParams) { params.resolution = Some(Vec2::new(1100., 1100.)); - params.base_color = Some(Color::WHITE); + params.base_color = Some(palette::css::WHITE); let mut blob: Vec = Vec::new(); - [Color::RED, Color::BLUE, Color::CYAN, Color::MAGENTA] - .iter() - .for_each(|c| { - let b = c.to_premul_u32().to_ne_bytes(); - blob.push(b[3]); - blob.push(b[2]); - blob.push(b[1]); - blob.push(b[0]); - }); + [ + palette::css::RED, + palette::css::BLUE, + palette::css::CYAN, + palette::css::MAGENTA, + ] + .iter() + .for_each(|c| { + // FIXME(color): Get rid of the to_u32 and just use the PremulRgba8 + let b = c.premultiply().to_rgba8().to_u32().to_ne_bytes(); + blob.push(b[3]); + blob.push(b[2]); + blob.push(b[1]); + blob.push(b[0]); + }); let data = Blob::new(Arc::new(blob)); let image = Image::new(data, Format::Rgba8, 2, 2); @@ -1808,17 +1834,23 @@ mod impls { pub(super) fn image_extend_modes(scene: &mut Scene, params: &mut SceneParams) { params.resolution = Some(Vec2::new(1500., 1500.)); - params.base_color = Some(Color::WHITE); + params.base_color = Some(palette::css::WHITE); let mut blob: Vec = Vec::new(); - [Color::RED, Color::BLUE, Color::CYAN, Color::MAGENTA] - .iter() - .for_each(|c| { - let b = c.to_premul_u32().to_ne_bytes(); - blob.push(b[3]); - blob.push(b[2]); - blob.push(b[1]); - blob.push(b[0]); - }); + [ + palette::css::RED, + palette::css::BLUE, + palette::css::CYAN, + palette::css::MAGENTA, + ] + .iter() + .for_each(|c| { + // FIXME(color): Get rid of the to_u32 and just use the PremulRgba8 + let b = c.premultiply().to_rgba8().to_u32().to_ne_bytes(); + blob.push(b[3]); + blob.push(b[2]); + blob.push(b[1]); + blob.push(b[0]); + }); let data = Blob::new(Arc::new(blob)); let image = Image::new(data, Format::Rgba8, 2, 2); let image = image.with_extend(Extend::Pad); diff --git a/examples/simple/src/main.rs b/examples/simple/src/main.rs index 044ea12a8..1b0cede14 100644 --- a/examples/simple/src/main.rs +++ b/examples/simple/src/main.rs @@ -210,12 +210,12 @@ fn add_shapes_to_scene(scene: &mut Scene) { // Draw an outlined rectangle let stroke = Stroke::new(6.0); let rect = RoundedRect::new(10.0, 10.0, 240.0, 240.0, 20.0); - let rect_stroke_color = Color::rgb(0.9804, 0.702, 0.5294); + let rect_stroke_color = Color::new([0.9804, 0.702, 0.5294, 1.]); scene.stroke(&stroke, Affine::IDENTITY, rect_stroke_color, None, &rect); // Draw a filled circle let circle = Circle::new((420.0, 200.0), 120.0); - let circle_fill_color = Color::rgb(0.9529, 0.5451, 0.6588); + let circle_fill_color = Color::new([0.9529, 0.5451, 0.6588, 1.]); scene.fill( vello::peniko::Fill::NonZero, Affine::IDENTITY, @@ -226,7 +226,7 @@ fn add_shapes_to_scene(scene: &mut Scene) { // Draw a filled ellipse let ellipse = Ellipse::new((250.0, 420.0), (100.0, 160.0), -90.0); - let ellipse_fill_color = Color::rgb(0.7961, 0.651, 0.9686); + let ellipse_fill_color = Color::new([0.7961, 0.651, 0.9686, 1.]); scene.fill( vello::peniko::Fill::NonZero, Affine::IDENTITY, @@ -237,6 +237,6 @@ fn add_shapes_to_scene(scene: &mut Scene) { // Draw a straight line let line = Line::new((260.0, 20.0), (620.0, 100.0)); - let line_stroke_color = Color::rgb(0.5373, 0.7059, 0.9804); + let line_stroke_color = Color::new([0.5373, 0.7059, 0.9804, 1.]); scene.stroke(&stroke, Affine::IDENTITY, line_stroke_color, None, &line); } diff --git a/examples/simple_sdl2/src/main.rs b/examples/simple_sdl2/src/main.rs index 52ecd7fc3..29a71b60d 100644 --- a/examples/simple_sdl2/src/main.rs +++ b/examples/simple_sdl2/src/main.rs @@ -120,12 +120,12 @@ fn add_shapes_to_scene(scene: &mut Scene) { // Draw an outlined rectangle let stroke = Stroke::new(6.0); let rect = RoundedRect::new(10.0, 10.0, 240.0, 240.0, 20.0); - let rect_stroke_color = Color::rgb(0.9804, 0.702, 0.5294); + let rect_stroke_color = Color::new([0.9804, 0.702, 0.5294, 1.]); scene.stroke(&stroke, Affine::IDENTITY, rect_stroke_color, None, &rect); // Draw a filled circle let circle = Circle::new((420.0, 200.0), 120.0); - let circle_fill_color = Color::rgb(0.9529, 0.5451, 0.6588); + let circle_fill_color = Color::new([0.9529, 0.5451, 0.6588, 1.]); scene.fill( vello::peniko::Fill::NonZero, Affine::IDENTITY, @@ -136,7 +136,7 @@ fn add_shapes_to_scene(scene: &mut Scene) { // Draw a filled ellipse let ellipse = Ellipse::new((250.0, 420.0), (100.0, 160.0), -90.0); - let ellipse_fill_color = Color::rgb(0.7961, 0.651, 0.9686); + let ellipse_fill_color = Color::new([0.7961, 0.651, 0.9686, 1.]); scene.fill( vello::peniko::Fill::NonZero, Affine::IDENTITY, @@ -147,6 +147,6 @@ fn add_shapes_to_scene(scene: &mut Scene) { // Draw a straight line let line = Line::new((260.0, 20.0), (620.0, 100.0)); - let line_stroke_color = Color::rgb(0.5373, 0.7059, 0.9804); + let line_stroke_color = Color::new([0.5373, 0.7059, 0.9804, 1.]); scene.stroke(&stroke, Affine::IDENTITY, line_stroke_color, None, &line); } diff --git a/examples/with_winit/src/stats.rs b/examples/with_winit/src/stats.rs index e9f9c6b4f..14ed0eb7a 100644 --- a/examples/with_winit/src/stats.rs +++ b/examples/with_winit/src/stats.rs @@ -6,7 +6,7 @@ use std::collections::VecDeque; #[cfg(feature = "wgpu-profiler")] use vello::kurbo::Line; use vello::kurbo::{Affine, PathEl, Rect, Stroke}; -use vello::peniko::{Brush, Color, Fill}; +use vello::peniko::{color::palette, Brush, Color, Fill}; use vello::{low_level::BumpAllocators, AaConfig, Scene}; #[cfg(all(feature = "wgpu-profiler", not(target_arch = "wasm32")))] @@ -48,7 +48,7 @@ impl Snapshot { scene.fill( Fill::NonZero, offset, - &Brush::Solid(Color::rgba8(0, 0, 0, 200)), + &Brush::Solid(Color::from_rgba8(0, 0, 0, 200)), None, &Rect::new(0., 0., width, height), ); @@ -88,7 +88,7 @@ impl Snapshot { scene, None, text_size, - Some(&Brush::Solid(Color::WHITE)), + Some(&Brush::Solid(palette::css::WHITE)), offset * Affine::translate((left_margin, (i + 1) as f64 * text_height)), label, ); @@ -97,7 +97,7 @@ impl Snapshot { scene, None, text_size, - Some(&Brush::Solid(Color::WHITE)), + Some(&Brush::Solid(palette::css::WHITE)), offset * Affine::translate((width * 0.67, text_height)), &format!("FPS: {:.2}", self.fps), ); @@ -135,9 +135,9 @@ impl Snapshot { let s = Affine::scale_non_uniform(1., -h); #[allow(clippy::match_overlapping_arm)] let color = match *sample { - ..=16_667 => Color::rgb8(100, 143, 255), - ..=33_334 => Color::rgb8(255, 176, 0), - _ => Color::rgb8(220, 38, 127), + ..=16_667 => Color::from_rgba8(100, 143, 255, 255), + ..=33_334 => Color::from_rgba8(255, 176, 0, 255), + _ => Color::from_rgba8(220, 38, 127, 255), }; scene.fill( Fill::NonZero, @@ -164,7 +164,7 @@ impl Snapshot { scene, None, thres_text_height as f32, - Some(&Brush::Solid(Color::WHITE)), + Some(&Brush::Solid(palette::css::WHITE)), offset * Affine::translate(( left_margin, @@ -175,7 +175,7 @@ impl Snapshot { scene.stroke( &Stroke::new(graph_max_height * 0.01), offset * Affine::translate((left_margin_padding, (1. - y) * graph_max_height)), - Color::WHITE, + palette::css::WHITE, None, &marker, ); @@ -289,14 +289,14 @@ pub fn draw_gpu_profiling( profiles: &[GpuTimerQueryResult], ) { const COLORS: &[Color] = &[ - Color::AQUA, - Color::RED, - Color::ALICE_BLUE, - Color::YELLOW, - Color::GREEN, - Color::BLUE, - Color::ORANGE, - Color::WHITE, + palette::css::AQUA, + palette::css::RED, + palette::css::ALICE_BLUE, + palette::css::YELLOW, + palette::css::GREEN, + palette::css::BLUE, + palette::css::ORANGE, + palette::css::WHITE, ]; if profiles_are_empty(profiles) { return; @@ -310,7 +310,7 @@ pub fn draw_gpu_profiling( scene.fill( Fill::NonZero, offset, - &Brush::Solid(Color::rgba8(0, 0, 0, 200)), + &Brush::Solid(Color::from_rgba8(0, 0, 0, 200)), None, &Rect::new(0., 0., width, height), ); @@ -351,7 +351,7 @@ pub fn draw_gpu_profiling( scene, None, text_size, - Some(&Brush::Solid(Color::WHITE)), + Some(&Brush::Solid(palette::css::WHITE)), offset * Affine::translate((left_margin, (i + 1) as f64 * text_height)), label, ); @@ -363,7 +363,7 @@ pub fn draw_gpu_profiling( scene, None, text_size, - Some(&Brush::Solid(Color::WHITE)), + Some(&Brush::Solid(palette::css::WHITE)), offset * Affine::translate((left_margin, (i + 1) as f64 * text_height)), label, ); @@ -415,9 +415,9 @@ pub fn draw_gpu_profiling( // Ensure that all remaining items can fit .min(timeline_range_end - (count - cur_index) as f64 * text_height); let (text_height, text_color) = if slow { - (text_height, Color::WHITE) + (text_height, palette::css::WHITE) } else { - (text_height * 0.6, Color::LIGHT_GRAY) + (text_height * 0.6, palette::css::LIGHT_GRAY) }; let text_size = (text_height * 0.9) as f32; // Text is specified by the baseline, but the y positions all refer to the top of the text diff --git a/vello/src/debug/renderer.rs b/vello/src/debug/renderer.rs index 6de15991b..f9d028a4b 100644 --- a/vello/src/debug/renderer.rs +++ b/vello/src/debug/renderer.rs @@ -18,7 +18,7 @@ use crate::{ use { bytemuck::{offset_of, Pod, Zeroable}, - peniko::Color, + peniko::{color::palette, Color}, vello_encoding::{BumpAllocators, LineSoup, PathBbox}, }; pub(crate) struct DebugRenderer { @@ -255,8 +255,8 @@ impl DebugRenderer { ); let linepoints_uniforms = [ - LinepointsUniforms::new(Color::DARK_CYAN, 10.), - LinepointsUniforms::new(Color::RED, 80.), + LinepointsUniforms::new(palette::css::DARK_CYAN, 10.), + LinepointsUniforms::new(palette::css::RED, 80.), ]; let linepoints_uniforms_buf = recording.upload_uniform( "vello.debug.linepoints_uniforms", @@ -358,12 +358,9 @@ struct LinepointsUniforms { impl LinepointsUniforms { fn new(color: Color, point_size: f32) -> Self { + let point_color = color.discard_alpha().components; Self { - point_color: [ - color.r as f32 / 255., - color.g as f32 / 255., - color.b as f32 / 255., - ], + point_color, point_size, _pad0: [0; 30], _pad1: [0; 30], diff --git a/vello/src/scene.rs b/vello/src/scene.rs index 51c32f095..04f06280d 100644 --- a/vello/src/scene.rs +++ b/vello/src/scene.rs @@ -6,6 +6,7 @@ mod bitmap; use std::sync::Arc; use peniko::{ + color::{DynamicColor, Srgb}, kurbo::{Affine, BezPath, Point, Rect, Shape, Stroke, Vec2}, BlendMode, Blob, Brush, BrushRef, Color, ColorStop, ColorStops, ColorStopsSource, Compose, Extend, Fill, Font, Gradient, Image, Mix, StyleRef, @@ -987,7 +988,7 @@ fn color_index(cpal: &'_ Cpal<'_>, palette_index: u16) -> Option { let actual_colors = cpal.color_records_array().unwrap().unwrap(); // TODO: Error reporting in the `None` case let color = actual_colors.get(usize::from(palette_index))?; - Some(Color::rgba8( + Some(Color::from_rgba8( color.red, color.green, color.blue, @@ -1027,14 +1028,14 @@ impl ColorStopsSource for ColorStopsConverter<'_> { BrushRef::Gradient(grad) => grad .stops .first() - .map(|it| it.color) + .map(|it| it.color.to_alpha_color::()) .unwrap_or(Color::TRANSPARENT), BrushRef::Image(_) => Color::BLACK, }, }; let color = color.multiply_alpha(item.alpha); vec.push(ColorStop { - color, + color: DynamicColor::from_alpha_color(color), offset: item.offset, }); } diff --git a/vello_encoding/src/config.rs b/vello_encoding/src/config.rs index 8f155498f..b2515c387 100644 --- a/vello_encoding/src/config.rs +++ b/vello_encoding/src/config.rs @@ -180,7 +180,7 @@ impl RenderConfig { height_in_tiles, target_width: width, target_height: height, - base_color: base_color.to_premul_u32(), + base_color: base_color.premultiply().to_rgba8().to_u32(), lines_size: buffer_sizes.lines.len(), binning_size: buffer_sizes.bin_data.len() - layout.bin_data_start, tiles_size: buffer_sizes.tiles.len(), diff --git a/vello_encoding/src/draw.rs b/vello_encoding/src/draw.rs index 162384263..9bc403d95 100644 --- a/vello_encoding/src/draw.rs +++ b/vello_encoding/src/draw.rs @@ -74,7 +74,7 @@ impl DrawColor { /// Creates new solid color draw data. pub fn new(color: Color) -> Self { Self { - rgba: color.to_premul_u32(), + rgba: color.premultiply().to_rgba8().to_u32(), } } } diff --git a/vello_encoding/src/encoding.rs b/vello_encoding/src/encoding.rs index f3fa4b125..eae856718 100644 --- a/vello_encoding/src/encoding.rs +++ b/vello_encoding/src/encoding.rs @@ -12,6 +12,7 @@ use { DrawImage, DrawLinearGradient, DrawRadialGradient, DrawSweepGradient, Glyph, GlyphRun, Patch, }, + peniko::color::{DynamicColor, Srgb}, peniko::{ColorStop, Extend, GradientKind, Image}, skrifa::instance::NormalizedCoord, }; @@ -355,7 +356,9 @@ impl Encoding { ) { match self.add_ramp(color_stops, alpha, extend) { RampStops::Empty => self.encode_color(DrawColor::new(Color::TRANSPARENT)), - RampStops::One(color) => self.encode_color(DrawColor::new(color)), + RampStops::One(color) => { + self.encode_color(DrawColor::new(color.to_alpha_color::())); + } _ => { self.draw_tags.push(DrawTag::LINEAR_GRADIENT); self.draw_data @@ -381,7 +384,9 @@ impl Encoding { } match self.add_ramp(color_stops, alpha, extend) { RampStops::Empty => self.encode_color(DrawColor::new(Color::TRANSPARENT)), - RampStops::One(color) => self.encode_color(DrawColor::new(color)), + RampStops::One(color) => { + self.encode_color(DrawColor::new(color.to_alpha_color::())); + } _ => { self.draw_tags.push(DrawTag::RADIAL_GRADIENT); self.draw_data @@ -406,7 +411,9 @@ impl Encoding { } match self.add_ramp(color_stops, alpha, extend) { RampStops::Empty => self.encode_color(DrawColor::new(Color::TRANSPARENT)), - RampStops::One(color) => self.encode_color(DrawColor::new(color)), + RampStops::One(color) => { + self.encode_color(DrawColor::new(color.to_alpha_color::())); + } _ => { self.draw_tags.push(DrawTag::SWEEP_GRADIENT); self.draw_data @@ -418,7 +425,7 @@ impl Encoding { /// Encodes an image brush. #[cfg(feature = "full")] pub fn encode_image(&mut self, image: &Image, alpha: f32) { - let _alpha = alpha * f32::from(image.alpha); + let _alpha = alpha * image.alpha; // TODO: feed the alpha multiplier through the full pipeline for consistency // with other brushes? // Tracked in https://github.com/linebender/vello/issues/692 @@ -527,7 +534,7 @@ enum RampStops { /// Color stop sequence was empty. Empty, /// Contained a single color stop. - One(Color), + One(DynamicColor), /// More than one color stop. Many, } diff --git a/vello_encoding/src/ramp_cache.rs b/vello_encoding/src/ramp_cache.rs index ceee7bb6c..84ad5677d 100644 --- a/vello_encoding/src/ramp_cache.rs +++ b/vello_encoding/src/ramp_cache.rs @@ -3,6 +3,7 @@ use std::collections::HashMap; +use peniko::color::Srgb; use peniko::{Color, ColorStop, ColorStops}; const N_SAMPLES: usize = 512; @@ -81,7 +82,7 @@ impl RampCache { fn make_ramp(stops: &[ColorStop]) -> impl Iterator + '_ { let mut last_u = 0.0; - let mut last_c = ColorF64::from_color(stops[0].color); + let mut last_c = ColorF64::from_color(stops[0].color.to_alpha_color::()); let mut this_u = last_u; let mut this_c = last_c; let mut j = 0; @@ -92,7 +93,7 @@ fn make_ramp(stops: &[ColorStop]) -> impl Iterator + '_ { last_c = this_c; if let Some(s) = stops.get(j + 1) { this_u = s.offset as f64; - this_c = ColorF64::from_color(s.color); + this_c = ColorF64::from_color(s.color.to_alpha_color::()); j += 1; } else { break; @@ -113,12 +114,8 @@ struct ColorF64([f64; 4]); impl ColorF64 { fn from_color(color: Color) -> Self { - Self([ - color.r as f64 / 255.0, - color.g as f64 / 255.0, - color.b as f64 / 255.0, - color.a as f64 / 255.0, - ]) + let [r, g, b, a] = color.components; + Self([r as f64, g as f64, b as f64, a as f64]) } fn lerp(&self, other: &Self, a: f64) -> Self { diff --git a/vello_tests/snapshots/many_clips.png b/vello_tests/snapshots/many_clips.png index cf95a1cef..0b7ac99b1 100644 --- a/vello_tests/snapshots/many_clips.png +++ b/vello_tests/snapshots/many_clips.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3794d764eaab03964653644cb80e5ea6fcfb59a2b3496e95ed3ee7c90758644c -size 25610 +oid sha256:08ae2b90cea2d9f055d0b45cef370e980225f996ca81dceba171e0992dcb5596 +size 25513 diff --git a/vello_tests/tests/known_issues.rs b/vello_tests/tests/known_issues.rs index 5e9576cee..cedb49d29 100644 --- a/vello_tests/tests/known_issues.rs +++ b/vello_tests/tests/known_issues.rs @@ -14,7 +14,7 @@ use vello::{ kurbo::{Affine, Rect}, - peniko::{Color, Format}, + peniko::{color::palette, Format}, Scene, }; use vello_tests::TestParams; @@ -25,7 +25,7 @@ fn many_bins(use_cpu: bool) { scene.fill( vello::peniko::Fill::NonZero, Affine::IDENTITY, - Color::RED, + palette::css::RED, None, &Rect::new(-5., -5., 256. * 20., 256. * 20.), ); diff --git a/vello_tests/tests/property.rs b/vello_tests/tests/property.rs index e70c7a06e..5a1dae73c 100644 --- a/vello_tests/tests/property.rs +++ b/vello_tests/tests/property.rs @@ -10,7 +10,7 @@ )] use vello::kurbo::{Affine, Rect}; -use vello::peniko::{Brush, Color, Format}; +use vello::peniko::{color::palette, Brush, Color, Format}; use vello::Scene; use vello_tests::TestParams; @@ -19,7 +19,7 @@ fn simple_square(use_cpu: bool) { scene.fill( vello::peniko::Fill::NonZero, Affine::IDENTITY, - &Brush::Solid(Color::RED), + &Brush::Solid(palette::css::RED), None, &Rect::from_center_size((100., 100.), (50., 50.)), ); @@ -55,7 +55,7 @@ fn empty_scene(use_cpu: bool) { // Adding an alpha factor here changes the resulting colour *slightly*, // presumably due to pre-multiplied alpha. // We just assume that alpha scenarios work fine - let color = Color::PLUM; + let color = palette::css::PLUM; let params = TestParams { use_cpu, base_colour: Some(color), @@ -65,9 +65,9 @@ fn empty_scene(use_cpu: bool) { assert_eq!(image.format, Format::Rgba8); for pixel in image.data.data().chunks_exact(4) { let &[r, g, b, a] = pixel else { unreachable!() }; - let image_color = Color::rgba8(r, g, b, a); - if image_color != color { - panic!("Got {image_color:?}, expected clear colour {color:?}"); + let image_color = Color::from_rgba8(r, g, b, a); + if image_color.premultiply().difference(color.premultiply()) > 1e-4 { + panic!("Got {image_color:?}, expected clear color {color:?}"); } } } diff --git a/vello_tests/tests/smoke_snapshots.rs b/vello_tests/tests/smoke_snapshots.rs index b27d445e7..9e22fcc39 100644 --- a/vello_tests/tests/smoke_snapshots.rs +++ b/vello_tests/tests/smoke_snapshots.rs @@ -6,7 +6,7 @@ use scenes::SimpleText; use vello::{ kurbo::{Affine, Circle, Rect}, - peniko::{Brush, Color, Fill}, + peniko::{color::palette, Brush, Fill}, Scene, }; use vello_tests::{smoke_snapshot_test_sync, TestParams}; @@ -16,7 +16,7 @@ fn filled_square(use_cpu: bool) { scene.fill( Fill::NonZero, Affine::IDENTITY, - &Brush::Solid(Color::BLUE), + &Brush::Solid(palette::css::BLUE), None, &Rect::from_center_size((10., 10.), (6., 6.)), ); @@ -34,7 +34,7 @@ fn filled_circle(use_cpu: bool) { scene.fill( Fill::NonZero, Affine::IDENTITY, - &Brush::Solid(Color::BLUE), + &Brush::Solid(palette::css::BLUE), None, &Circle::new((10., 10.), 7.), );