skia_safe/modules/svg/
node.rs

1use super::{
2    fe, pattern::Pattern, svg_::Svg, Circle, ClipPath, ColorSpace, DebugAttributes, Defs, Display,
3    Ellipse, Fill, FillRule, Filter, FontFamily, FontSize, FontStyle, FontWeight, Image, IriFunc,
4    Length, Line, LineCap, LineJoin, LinearGradient, Mask, Paint, Path, Poly, RadialGradient, Rect,
5    Stop, TSpan, Text, TextAnchor, TextLiteral, TextPath, Use, Visibility, G,
6};
7use crate::{prelude::*, scalar, Color};
8use skia_bindings as sb;
9
10pub type NodeTag = sb::SkSVGTag;
11
12pub type Node = RCHandle<sb::SkSVGNode>;
13
14impl NativeRefCountedBase for sb::SkSVGNode {
15    type Base = sb::SkRefCntBase;
16}
17
18impl DebugAttributes for Node {
19    const NAME: &'static str = "Node";
20
21    fn _dbg(&self, builder: &mut std::fmt::DebugStruct) {
22        builder
23            .field("clip_rule", &self.clip_rule())
24            .field("color_interpolation", &self.color_interpolation())
25            .field(
26                "color_interpolation_filters",
27                &self.color_interpolation_filters(),
28            )
29            .field("color", &self.color())
30            .field("fill_rule", &self.fill_rule())
31            .field("fill", &self.fill())
32            .field("fill_opacity", &self.fill_opacity())
33            .field("font_family", &self.font_family())
34            .field("font_size", &self.font_size())
35            .field("font_style", &self.font_style())
36            .field("font_weight", &self.font_weight())
37            .field("stroke", &self.stroke())
38            .field("stroke_line_cap", &self.stroke_line_cap())
39            .field("stroke_line_join", &self.stroke_line_join())
40            .field("stroke_miter_limit", &self.stroke_miter_limit())
41            .field("stroke_opacity", &self.stroke_opacity())
42            .field("stroke_width", &self.stroke_width())
43            .field("text_anchor", &self.text_anchor())
44            .field("visibility", &self.visibility())
45            .field("clip_path", &self.clip_path())
46            .field("display", &self.display())
47            .field("mask", &self.mask())
48            .field("filter", &self.filter())
49            .field("opacity", &self.opacity())
50            .field("stop_color", &self.stop_color())
51            .field("stop_opacity", &self.stop_opacity())
52            .field("flood_color", &self.flood_color())
53            .field("flood_opacity", &self.flood_opacity())
54            .field("lighting_color", &self.lighting_color());
55    }
56}
57
58impl From<TypedNode> for Node {
59    fn from(value: TypedNode) -> Self {
60        value.into_node()
61    }
62}
63
64impl Node {
65    pub fn tag(&self) -> NodeTag {
66        unsafe { sb::C_SkSVGNode_tag(self.native()) }
67    }
68
69    // TODO: wrap appendChild()
70    // TODO: wrap render(), asPaint(), asPath(), objectBoundingBox()
71    // TODO: wrap setAttribute().
72    // TODO: wrap parseAndSetAttribute()
73
74    pub fn typed(self) -> TypedNode {
75        TypedNode::from_ptr(self.into_ptr())
76    }
77
78    skia_svg_macros::attrs! {
79        SkSVGNode => {
80            // inherited
81            clip_rule?: FillRule [get(value) => value.map(|value| &value.fType), set(value) => sb::SkSVGFillRule { fType: value }],
82            color_interpolation?: ColorSpace [get(value) => value, set(value) => value],
83            color_interpolation_filters?: ColorSpace [get(value) => value, set(value) => value],
84            color?: Color [get(value) => value.map(Color::from_native_ref), set(value) => value.into_native()],
85            fill_rule?: FillRule [get(value) => value.map(|value| &value.fType), set(value) => sb::SkSVGFillRule { fType: value }],
86            fill?: Paint [get(value) => value.map(Paint::from_native_ref), set(value) => value.native()],
87            *fill_opacity?: scalar [get(value) => value, set(value) => value],
88            font_family?: FontFamily [get(value) => value.map(FontFamily::from_native_ref), set(value) => value.into_native()],
89            font_size?: FontSize [get(value) => value.map(FontSize::from_native_ref), set(value) => value.into_native()],
90            font_style?: FontStyle [get(value) => value.map(|value| &value.fType), set(value) => sb::SkSVGFontStyle { fType: value }],
91            font_weight?: FontWeight [get(value) => value.map(|value| &value.fType), set(value) => sb::SkSVGFontWeight { fType: value }],
92            stroke?: Paint [get(value) => value.map(Paint::from_native_ref), set(value) => value.native()],
93            stroke_line_cap?: LineCap [get(value) => value, set(value) => value],
94            stroke_line_join?: LineJoin [get(value) => value.map(|value| &value.fType), set(value) => sb::SkSVGLineJoin { fType: value }],
95            *stroke_miter_limit?: scalar [get(value) => value, set(value) => value],
96            *stroke_opacity?: scalar [get(value) => value, set(value) => value],
97            stroke_width?: Length [get(value) => value.map(Length::from_native_ref), set(value) => value.into_native()],
98            text_anchor?: TextAnchor [get(value) => value.map(|value| &value.fType), set(value) => sb::SkSVGTextAnchor { fType: value }],
99            visibility?: Visibility [get(value) => value.map(|value| &value.fType), set(value) => sb::SkSVGVisibility { fType: value }],
100
101            // not inherited
102            clip_path?: IriFunc [get(value) => value.map(IriFunc::from_native_ref), set(value) => value.native()],
103            display?: Display [get(value) => value, set(value) => value],
104            mask?: IriFunc [get(value) => value.map(IriFunc::from_native_ref), set(value) => value.native()],
105            filter?: IriFunc [get(value) => value.map(IriFunc::from_native_ref), set(value) => value.native()],
106            *opacity?: scalar [get(value) => value, set(value) => value],
107            stop_color?: Fill [get(value) => value.map(Fill::from_native_ref), set(value) => value.native()],
108            *stop_opacity?: scalar [get(value) => value, set(value) => value],
109            flood_color?: Fill [get(value) => value.map(Fill::from_native_ref), set(value) => value.native()],
110            *flood_opacity?: scalar [get(value) => value, set(value) => value],
111            lighting_color?: Fill [get(value) => value.map(Fill::from_native_ref), set(value) => value.native()]
112        }
113    }
114}
115
116#[derive(Debug, Clone)]
117pub enum TypedNode {
118    Circle(Circle),
119    ClipPath(ClipPath),
120    Defs(Defs),
121    Ellipse(Ellipse),
122    FeBlend(fe::Blend),
123    FeColorMatrix(fe::ColorMatrix),
124    FeComponentTransfer(fe::ComponentTransfer),
125    FeComposite(fe::Composite),
126    FeDiffuseLighting(fe::DiffuseLighting),
127    FeDisplacementMap(fe::DisplacementMap),
128    FeDistantLight(fe::DistantLight),
129    FeFlood(fe::Flood),
130    FeFuncA(fe::Func),
131    FeFuncR(fe::Func),
132    FeFuncG(fe::Func),
133    FeFuncB(fe::Func),
134    FeGaussianBlur(fe::GaussianBlur),
135    FeImage(fe::Image),
136    FeMerge(fe::Merge),
137    FeMergeNode(fe::MergeNode),
138    FeMorphology(fe::Morphology),
139    FeOffset(fe::Offset),
140    FePointLight(fe::PointLight),
141    FeSpecularLighting(fe::SpecularLighting),
142    FeSpotLight(fe::SpotLight),
143    FeTurbulence(fe::Turbulence),
144    Filter(Filter),
145    G(G),
146    Image(Image),
147    Line(Line),
148    LinearGradient(LinearGradient),
149    Mask(Mask),
150    Path(Path),
151    Pattern(Pattern),
152    Polygon(Poly),
153    Polyline(Poly),
154    RadialGradient(RadialGradient),
155    Rect(Rect),
156    Stop(Stop),
157    Svg(Svg),
158    Text(Text),
159    TextLiteral(TextLiteral),
160    TextPath(TextPath),
161    TSpan(TSpan),
162    Use(Use),
163}
164
165impl From<Node> for TypedNode {
166    fn from(node: Node) -> Self {
167        node.typed()
168    }
169}
170
171impl TypedNode {
172    pub(crate) fn from_ptr(ptr: *mut sb::SkSVGNode) -> Self {
173        Self::from_ptr_opt(ptr).unwrap()
174    }
175
176    pub fn into_node(self) -> Node {
177        let node_ptr = match self {
178            TypedNode::Circle(node) => node.into_ptr() as *mut _,
179            TypedNode::ClipPath(node) => node.into_ptr() as *mut _,
180            TypedNode::Defs(node) => node.into_ptr() as *mut _,
181            TypedNode::Ellipse(node) => node.into_ptr() as *mut _,
182            TypedNode::FeBlend(node) => node.into_ptr() as *mut _,
183            TypedNode::FeColorMatrix(node) => node.into_ptr() as *mut _,
184            TypedNode::FeComponentTransfer(node) => node.into_ptr() as *mut _,
185            TypedNode::FeComposite(node) => node.into_ptr() as *mut _,
186            TypedNode::FeDiffuseLighting(node) => node.into_ptr() as *mut _,
187            TypedNode::FeDisplacementMap(node) => node.into_ptr() as *mut _,
188            TypedNode::FeDistantLight(node) => node.into_ptr() as *mut _,
189            TypedNode::FeFlood(node) => node.into_ptr() as *mut _,
190            TypedNode::FeFuncA(node) => node.into_ptr() as *mut _,
191            TypedNode::FeFuncR(node) => node.into_ptr() as *mut _,
192            TypedNode::FeFuncG(node) => node.into_ptr() as *mut _,
193            TypedNode::FeFuncB(node) => node.into_ptr() as *mut _,
194            TypedNode::FeGaussianBlur(node) => node.into_ptr() as *mut _,
195            TypedNode::FeImage(node) => node.into_ptr() as *mut _,
196            TypedNode::FeMerge(node) => node.into_ptr() as *mut _,
197            TypedNode::FeMergeNode(node) => node.into_ptr() as *mut _,
198            TypedNode::FeMorphology(node) => node.into_ptr() as *mut _,
199            TypedNode::FeOffset(node) => node.into_ptr() as *mut _,
200            TypedNode::FePointLight(node) => node.into_ptr() as *mut _,
201            TypedNode::FeSpecularLighting(node) => node.into_ptr() as *mut _,
202            TypedNode::FeSpotLight(node) => node.into_ptr() as *mut _,
203            TypedNode::FeTurbulence(node) => node.into_ptr() as *mut _,
204            TypedNode::Filter(node) => node.into_ptr() as *mut _,
205            TypedNode::G(node) => node.into_ptr() as *mut _,
206            TypedNode::Image(node) => node.into_ptr() as *mut _,
207            TypedNode::Line(node) => node.into_ptr() as *mut _,
208            TypedNode::LinearGradient(node) => node.into_ptr() as *mut _,
209            TypedNode::Mask(node) => node.into_ptr() as *mut _,
210            TypedNode::Path(node) => node.into_ptr() as *mut _,
211            TypedNode::Pattern(node) => node.into_ptr() as *mut _,
212            TypedNode::Polygon(node) => node.into_ptr() as *mut _,
213            TypedNode::Polyline(node) => node.into_ptr() as *mut _,
214            TypedNode::RadialGradient(node) => node.into_ptr() as *mut _,
215            TypedNode::Rect(node) => node.into_ptr() as *mut _,
216            TypedNode::Stop(node) => node.into_ptr() as *mut _,
217            TypedNode::Svg(node) => node.into_ptr() as *mut _,
218            TypedNode::Text(node) => node.into_ptr() as *mut _,
219            TypedNode::TextLiteral(node) => node.into_ptr() as *mut _,
220            TypedNode::TextPath(node) => node.into_ptr() as *mut _,
221            TypedNode::TSpan(node) => node.into_ptr() as *mut _,
222            TypedNode::Use(node) => node.into_ptr() as *mut _,
223        };
224
225        Node::from_ptr(node_ptr).unwrap()
226    }
227
228    pub(crate) fn from_ptr_opt(ptr: *mut sb::SkSVGNode) -> Option<Self> {
229        let tag = unsafe { sb::C_SkSVGNode_tag(ptr as *const _) };
230
231        Some(match tag {
232            NodeTag::Circle => Self::Circle(Circle::from_ptr(ptr as *mut _)?),
233            NodeTag::ClipPath => Self::ClipPath(ClipPath::from_ptr(ptr as *mut _)?),
234            NodeTag::Defs => Self::Defs(Defs::from_ptr(ptr as *mut _)?),
235            NodeTag::Ellipse => Self::Ellipse(Ellipse::from_ptr(ptr as *mut _)?),
236            NodeTag::FeBlend => Self::FeBlend(fe::Blend::from_ptr(ptr as *mut _)?),
237            NodeTag::FeColorMatrix => {
238                Self::FeColorMatrix(fe::ColorMatrix::from_ptr(ptr as *mut _)?)
239            }
240            NodeTag::FeComponentTransfer => {
241                Self::FeComponentTransfer(fe::ComponentTransfer::from_ptr(ptr as *mut _)?)
242            }
243            NodeTag::FeComposite => Self::FeComposite(fe::Composite::from_ptr(ptr as *mut _)?),
244            NodeTag::FeDiffuseLighting => {
245                Self::FeDiffuseLighting(fe::DiffuseLighting::from_ptr(ptr as *mut _)?)
246            }
247            NodeTag::FeDisplacementMap => {
248                Self::FeDisplacementMap(fe::DisplacementMap::from_ptr(ptr as *mut _)?)
249            }
250            NodeTag::FeDistantLight => {
251                Self::FeDistantLight(fe::DistantLight::from_ptr(ptr as *mut _)?)
252            }
253            NodeTag::FeFlood => Self::FeFlood(fe::Flood::from_ptr(ptr as *mut _)?),
254            NodeTag::FeFuncA => Self::FeFuncA(fe::Func::from_ptr(ptr as *mut _)?),
255            NodeTag::FeFuncR => Self::FeFuncR(fe::Func::from_ptr(ptr as *mut _)?),
256            NodeTag::FeFuncG => Self::FeFuncG(fe::Func::from_ptr(ptr as *mut _)?),
257            NodeTag::FeFuncB => Self::FeFuncB(fe::Func::from_ptr(ptr as *mut _)?),
258            NodeTag::FeGaussianBlur => {
259                Self::FeGaussianBlur(fe::GaussianBlur::from_ptr(ptr as *mut _)?)
260            }
261            NodeTag::FeImage => Self::FeImage(fe::Image::from_ptr(ptr as *mut _)?),
262            NodeTag::FeMerge => Self::FeMerge(fe::Merge::from_ptr(ptr as *mut _)?),
263            NodeTag::FeMergeNode => Self::FeMergeNode(fe::MergeNode::from_ptr(ptr as *mut _)?),
264            NodeTag::FeMorphology => Self::FeMorphology(fe::Morphology::from_ptr(ptr as *mut _)?),
265            NodeTag::FeOffset => Self::FeOffset(fe::Offset::from_ptr(ptr as *mut _)?),
266            NodeTag::FePointLight => Self::FePointLight(fe::PointLight::from_ptr(ptr as *mut _)?),
267            NodeTag::FeSpecularLighting => {
268                Self::FeSpecularLighting(fe::SpecularLighting::from_ptr(ptr as *mut _)?)
269            }
270            NodeTag::FeSpotLight => Self::FeSpotLight(fe::SpotLight::from_ptr(ptr as *mut _)?),
271            NodeTag::FeTurbulence => Self::FeTurbulence(fe::Turbulence::from_ptr(ptr as *mut _)?),
272            NodeTag::Filter => Self::Filter(Filter::from_ptr(ptr as *mut _)?),
273            NodeTag::G => Self::G(G::from_ptr(ptr as *mut _)?),
274            NodeTag::Image => Self::Image(Image::from_ptr(ptr as *mut _)?),
275            NodeTag::Line => Self::Line(Line::from_ptr(ptr as *mut _)?),
276            NodeTag::LinearGradient => {
277                Self::LinearGradient(LinearGradient::from_ptr(ptr as *mut _)?)
278            }
279            NodeTag::Mask => Self::Mask(Mask::from_ptr(ptr as *mut _)?),
280            NodeTag::Path => Self::Path(Path::from_ptr(ptr as *mut _)?),
281            NodeTag::Pattern => Self::Pattern(Pattern::from_ptr(ptr as *mut _)?),
282            NodeTag::Polygon => Self::Polygon(Poly::from_ptr(ptr as *mut _)?),
283            NodeTag::Polyline => Self::Polyline(Poly::from_ptr(ptr as *mut _)?),
284            NodeTag::RadialGradient => {
285                Self::RadialGradient(RadialGradient::from_ptr(ptr as *mut _)?)
286            }
287            NodeTag::Rect => Self::Rect(Rect::from_ptr(ptr as *mut _)?),
288            NodeTag::Stop => Self::Stop(Stop::from_ptr(ptr as *mut _)?),
289            NodeTag::Svg => Self::Svg(Svg::from_ptr(ptr as *mut _)?),
290            NodeTag::Text => Self::Text(Text::from_ptr(ptr as *mut _)?),
291            NodeTag::TextLiteral => Self::TextLiteral(TextLiteral::from_ptr(ptr as *mut _)?),
292            NodeTag::TextPath => Self::TextPath(TextPath::from_ptr(ptr as *mut _)?),
293            NodeTag::TSpan => Self::TSpan(TSpan::from_ptr(ptr as *mut _)?),
294            NodeTag::Use => Self::Use(Use::from_ptr(ptr as *mut _)?),
295        })
296    }
297}