Skip to content

Commit

Permalink
feat: support for current_color in the svg attributes fill and `s…
Browse files Browse the repository at this point in the history
…troke`. (#1110)

* add support for current_color and updated example

* rename variable for clarity reasons

* sync mocked

* swap svg_fill & svg_stroke in svg element

* fixes

---------

Co-authored-by: marc2332 <mespinsanz@gmail.com>
  • Loading branch information
Aiving and marc2332 authored Feb 22, 2025
1 parent 1f63f9c commit 0827e48
Show file tree
Hide file tree
Showing 9 changed files with 89 additions and 20 deletions.
8 changes: 4 additions & 4 deletions crates/core/src/elements/svg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@ impl ElementUtils for SvgElement {
root.set_width(svg::Length::new(100.0, svg::LengthUnit::Percentage));
root.set_height(svg::Length::new(100.0, svg::LengthUnit::Percentage));
root.set_color(font_style.color);
if let Some(color) = svg_state.svg_stroke.as_ref() {
root.set_fill(svg::Paint::from_color(*color));
if let Some(paint) = svg_state.svg_fill.as_ref() {
root.set_fill((*paint).into());
}
if let Some(color) = svg_state.svg_fill.as_ref() {
root.set_stroke(svg::Paint::from_color(*color));
if let Some(paint) = svg_state.svg_stroke.as_ref() {
root.set_stroke((*paint).into());
}
svg_dom.render(canvas);
canvas.restore();
Expand Down
15 changes: 12 additions & 3 deletions crates/core/src/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ use crate::{
CornerRadius,
Fill,
Shadow,
SvgPaint,
TextOverflow,
},
};
Expand Down Expand Up @@ -159,12 +160,20 @@ impl NodeState {
("offset_y", AttributeType::Measure(self.size.offset_y.get())),
("content", AttributeType::Content(&self.size.content)),
(
"fill",
AttributeType::OptionalColor(self.svg.svg_fill.map(|color| color.into())),
"svg_fill",
AttributeType::OptionalColor(self.svg.svg_fill.and_then(|fill| match fill {
SvgPaint::None => None,
SvgPaint::CurrentColor => Some(Fill::Color(self.font_style.color)),
SvgPaint::Color(color) => Some(Fill::Color(color)),
})),
),
(
"svg_stroke",
AttributeType::OptionalColor(self.svg.svg_stroke.map(|color| color.into())),
AttributeType::OptionalColor(self.svg.svg_stroke.and_then(|stroke| match stroke {
SvgPaint::None => None,
SvgPaint::CurrentColor => Some(Fill::Color(self.font_style.color)),
SvgPaint::Color(color) => Some(Fill::Color(color)),
})),
),
];

Expand Down
11 changes: 5 additions & 6 deletions crates/core/src/states/svg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use std::sync::{
Mutex,
};

use freya_engine::prelude::Color;
use freya_native_core::{
attributes::AttributeName,
exports::shipyard::Component,
Expand Down Expand Up @@ -34,12 +33,13 @@ use crate::{
ParseAttribute,
ParseError,
},
values::SvgPaint,
};

#[derive(Default, Debug, Clone, PartialEq, Component)]
pub struct SvgState {
pub svg_fill: Option<Color>,
pub svg_stroke: Option<Color>,
pub svg_fill: Option<SvgPaint>,
pub svg_stroke: Option<SvgPaint>,
pub svg_data: Option<AttributesBytes>,
}

Expand All @@ -55,21 +55,20 @@ impl ParseAttribute for SvgState {
self.svg_data = Some(bytes.clone());
}
}

AttributeName::Fill => {
if let Some(value) = attr.value.as_text() {
if value == "none" {
return Ok(());
}
self.svg_fill = Some(Color::parse(value)?);
self.svg_fill = Some(SvgPaint::parse(value)?);
}
}
AttributeName::Stroke => {
if let Some(value) = attr.value.as_text() {
if value == "none" {
return Ok(());
}
self.svg_stroke = Some(Color::parse(value)?);
self.svg_stroke = Some(SvgPaint::parse(value)?);
}
}
AttributeName::SvgContent => {
Expand Down
2 changes: 2 additions & 0 deletions crates/core/src/values/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ mod gradient;
mod highlight;
mod image_cover;
mod overflow;
mod paint;
mod position;
mod sampling;
mod shadow;
Expand All @@ -35,6 +36,7 @@ pub use gradient::*;
pub use highlight::*;
pub use image_cover::*;
pub use overflow::*;
pub use paint::*;
pub use sampling::*;
pub use shadow::*;
pub use size::*;
Expand Down
34 changes: 34 additions & 0 deletions crates/core/src/values/paint.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
use freya_engine::prelude::*;

use crate::parsing::{
Parse,
ParseError,
};

#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
pub enum SvgPaint {
#[default]
None,
CurrentColor,
Color(Color),
}

impl Parse for SvgPaint {
fn parse(value: &str) -> Result<Self, ParseError> {
match value {
"current_color" => Ok(SvgPaint::CurrentColor),
"none" => Ok(SvgPaint::None),
value => Ok(SvgPaint::Color(Color::parse(value)?)),
}
}
}

impl From<SvgPaint> for svg::Paint {
fn from(value: SvgPaint) -> Self {
match value {
SvgPaint::None => svg::Paint::none(),
SvgPaint::CurrentColor => svg::Paint::current_color(),
SvgPaint::Color(color) => svg::Paint::from_color(color),
}
}
}
6 changes: 6 additions & 0 deletions crates/elements/src/_docs/color_syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,9 @@
//! - With HSL: `hsl(28deg, 80%, 50%)`
//! - With HSL and alpha: `hsl(28deg, 80%, 50%, 25%)`
//! - With Hex: `#E93323`
//!
//! #### SVG
//!
//! For the `svg` element you can also use:
//!
//! - `current_color`: Use the inherited color from the `color` attribute.
4 changes: 2 additions & 2 deletions crates/elements/src/attributes/svg_attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::def_attribute;
def_attribute!(
svg_data,
svg_content,
/// The `fill` attributes allows you to specify the fill or stroke color for the `svg`.
/// The `fill` attributes allows you to specify the fill color for the `svg`.
///
/// You can learn about the syntax of this attribute in [`Color Syntax`](crate::_docs::color_syntax).
///
Expand All @@ -26,7 +26,7 @@ def_attribute!(
/// ```
fill,

/// The `stroke` attributes allows you to specify the fill or stroke color for the `svg`.
/// The `stroke` attributes allows you to specify stroke color for the `svg`.
///
/// You can learn about the syntax of this attribute in [`Color Syntax`](crate::_docs::color_syntax).
///
Expand Down
8 changes: 8 additions & 0 deletions crates/engine/src/mocked.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1640,6 +1640,14 @@ pub mod svg {
pub struct Paint;

impl Paint {
pub fn none() -> Self {
unimplemented!("This is mocked")
}

pub fn current_color() -> Self {
unimplemented!("This is mocked")
}

pub fn from_color(_color: Color) -> Self {
unimplemented!("This is mocked")
}
Expand Down
21 changes: 16 additions & 5 deletions examples/svg_fill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,21 @@ static SETTINGS: &[u8] = include_bytes!("./settings.svg");
fn app() -> Element {
let svg_data = static_bytes(SETTINGS);

rsx!(svg {
fill: "red",
width: "100%",
height: "100%",
svg_data,
rsx!(rect {
spacing: "8",
svg {
fill: "red",
width: "100%",
height: "50%",
svg_data: svg_data.clone(),
}
// You can achieve same effect using `fill: "current_color"` and `color` attribute.
svg {
color: "red",
fill: "current_color",
width: "100%",
height: "50%",
svg_data,
}
})
}

0 comments on commit 0827e48

Please sign in to comment.