Skip to content

Commit

Permalink
pico_svg: Simplify color parsing.
Browse files Browse the repository at this point in the history
The color parsing in `color` is more complete than the older
code in `peniko`, so this can be simplified now.

Also, switch from `peniko::Color` to `AlphaColor<Srgb>` to
continue down the path of using `peniko::Color` less.

Finally, add a couple of tests to show the color parsing
working with a couple of the supported syntaxes.
  • Loading branch information
waywardmonkeys committed Nov 29, 2024
1 parent e82de29 commit 8b7e7e0
Showing 1 changed file with 48 additions and 19 deletions.
67 changes: 48 additions & 19 deletions examples/scenes/src/pico_svg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ use std::str::FromStr;
use roxmltree::{Document, Node};
use vello::{
kurbo::{Affine, BezPath, Point, Size, Vec2},
peniko::color::{self, palette},
peniko::Color,
peniko::color::{self, palette, AlphaColor, DynamicColor, Srgb},
};

pub struct PicoSvg {
Expand All @@ -25,12 +24,12 @@ pub enum Item {

pub struct StrokeItem {
pub width: f64,
pub color: Color,
pub color: AlphaColor<Srgb>,
pub path: BezPath,
}

pub struct FillItem {
pub color: Color,
pub color: AlphaColor<Srgb>,
pub path: BezPath,
}

Expand Down Expand Up @@ -124,7 +123,7 @@ impl PicoSvg {

#[derive(Clone)]
struct RecursiveProperties {
fill: Option<Color>,
fill: Option<AlphaColor<Srgb>>,
}

impl Parser {
Expand Down Expand Up @@ -259,23 +258,18 @@ fn parse_transform(transform: &str) -> Affine {
nt
}

fn parse_color(color: &str) -> Color {
fn parse_color(color: &str) -> AlphaColor<Srgb> {
let color = color.trim();
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::from_rgba8(r, g, b, 255)
} else {
Color::from_rgba8(255, 0, 255, 0x80)
}
color::parse_color(color.trim())
.map(DynamicColor::to_alpha_color)
.unwrap_or(palette::css::FUCHSIA.with_alpha(0.5))
}

fn modify_opacity(color: Color, attr_name: &str, node: Node<'_, '_>) -> Color {
fn modify_opacity(
color: AlphaColor<Srgb>,
attr_name: &str,
node: Node<'_, '_>,
) -> AlphaColor<Srgb> {
if let Some(opacity) = node.attribute(attr_name) {
let alpha: f32 = if let Some(o) = opacity.strip_suffix('%') {
let pctg = o.parse().unwrap_or(100.0);
Expand All @@ -288,3 +282,38 @@ fn modify_opacity(color: Color, attr_name: &str, node: Node<'_, '_>) -> Color {
color
}
}

#[cfg(test)]
mod tests {
use super::parse_color;
use vello::peniko::color::{palette, AlphaColor, Srgb};

fn assert_close_color(c1: AlphaColor<Srgb>, c2: AlphaColor<Srgb>) {
const EPSILON: f32 = 1e-4;
assert_eq!(c1.cs, c2.cs);
for i in 0..4 {
assert!((c1.components[i] - c2.components[i]).abs() < EPSILON);
}
}

#[test]
fn parse_colors() {
let lime = palette::css::LIME;
let lime_a = lime.with_alpha(0.4);

let named = parse_color("lime");
assert_close_color(lime, named);

let hex = parse_color("#00ff00");
assert_close_color(lime, hex);

let rgb = parse_color("rgb(0, 255, 0)");
assert_close_color(lime, rgb);

let modern = parse_color("color(srgb 0 1 0)");
assert_close_color(lime, modern);

let modern_a = parse_color("color(srgb 0 1 0 / 0.4)");
assert_close_color(lime_a, modern_a);
}
}

0 comments on commit 8b7e7e0

Please sign in to comment.