1use std::sync::{
2 Arc,
3 Mutex,
4};
5
6use freya_native_core::{
7 attributes::AttributeName,
8 exports::shipyard::Component,
9 node::{
10 NodeType,
11 OwnedAttributeValue,
12 },
13 node_ref::NodeView,
14 prelude::{
15 AttributeMaskBuilder,
16 Dependancy,
17 NodeMaskBuilder,
18 State,
19 },
20 tags::TagName,
21 SendAnyMap,
22};
23use freya_native_core_macro::partial_derive_state;
24
25use crate::{
26 custom_attributes::{
27 AttributesBytes,
28 CustomAttributeValues,
29 },
30 dom::CompositorDirtyNodes,
31 parsing::{
32 Parse,
33 ParseAttribute,
34 ParseError,
35 },
36 values::SvgPaint,
37};
38
39#[derive(Default, Debug, Clone, PartialEq, Component)]
40pub struct SvgState {
41 pub svg_fill: Option<SvgPaint>,
42 pub svg_stroke: Option<SvgPaint>,
43 pub svg_data: Option<AttributesBytes>,
44}
45
46impl ParseAttribute for SvgState {
47 fn parse_attribute(
48 &mut self,
49 attr: freya_native_core::prelude::OwnedAttributeView<CustomAttributeValues>,
50 ) -> Result<(), ParseError> {
51 match attr.attribute {
52 AttributeName::SvgData => {
53 if let OwnedAttributeValue::Custom(CustomAttributeValues::Bytes(bytes)) = attr.value
54 {
55 self.svg_data = Some(bytes.clone());
56 }
57 }
58 AttributeName::Fill => {
59 if let Some(value) = attr.value.as_text() {
60 if value == "none" {
61 return Ok(());
62 }
63 self.svg_fill = Some(SvgPaint::parse(value)?);
64 }
65 }
66 AttributeName::Stroke => {
67 if let Some(value) = attr.value.as_text() {
68 if value == "none" {
69 return Ok(());
70 }
71 self.svg_stroke = Some(SvgPaint::parse(value)?);
72 }
73 }
74 AttributeName::SvgContent => {
75 let text = attr.value.as_text();
76 self.svg_data =
77 text.map(|v| AttributesBytes::Dynamic(v.as_bytes().to_vec().into()));
78 }
79 _ => {}
80 }
81
82 Ok(())
83 }
84}
85
86#[partial_derive_state]
87impl State<CustomAttributeValues> for SvgState {
88 type ParentDependencies = ();
89
90 type ChildDependencies = ();
91
92 type NodeDependencies = ();
93
94 const NODE_MASK: NodeMaskBuilder<'static> =
95 NodeMaskBuilder::new().with_attrs(AttributeMaskBuilder::Some(&[
96 AttributeName::Fill,
97 AttributeName::Stroke,
98 AttributeName::SvgData,
99 AttributeName::SvgContent,
100 ]));
101
102 fn allow_node(node_type: &NodeType<CustomAttributeValues>) -> bool {
103 node_type.tag() == Some(&TagName::Svg)
104 }
105
106 fn update<'a>(
107 &mut self,
108 node_view: NodeView<CustomAttributeValues>,
109 _node: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
110 _parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
111 _children: Vec<<Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>,
112 context: &SendAnyMap,
113 ) -> bool {
114 let mut style = SvgState::default();
115
116 if let Some(attributes) = node_view.attributes() {
117 for attr in attributes {
118 style.parse_safe(attr)
119 }
120 }
121
122 let changed = &style != self;
123 if changed {
124 let compositor_dirty_nodes = context.get::<Arc<Mutex<CompositorDirtyNodes>>>().unwrap();
125 compositor_dirty_nodes
126 .lock()
127 .unwrap()
128 .invalidate(node_view.node_id());
129 }
130
131 *self = style;
132 changed
133 }
134}