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 pub fn typed(self) -> TypedNode {
75 TypedNode::from_ptr(self.into_ptr())
76 }
77
78 skia_svg_macros::attrs! {
79 SkSVGNode => {
80 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 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}