skia_safe/modules/svg/
node_hierarchy.rs1use crate::prelude::*;
2use std::{
3 fmt::{Debug, DebugStruct, Formatter, Result},
4 ops::{Deref, DerefMut},
5};
6
7use super::{Node, TypedNode};
8
9pub trait NodeSubtype {
10 type Base: NativeRefCounted;
11}
12
13impl<T: NodeSubtype> NativeRefCountedBase for T {
16 type Base = skia_bindings::SkRefCntBase;
17}
18
19impl<T: NativeRefCounted + NodeSubtype> RCHandle<T> {
20 pub fn as_base(&self) -> &RCHandle<T::Base> {
21 unsafe { transmute_ref(self) }
22 }
23
24 pub fn as_base_mut(&mut self) -> &mut RCHandle<T::Base> {
25 unsafe { transmute_ref_mut(self) }
26 }
27
28 pub fn into_node(self) -> Node {
30 unsafe { std::mem::transmute(self) }
31 }
32
33 pub fn typed(self) -> TypedNode {
35 self.into_node().typed()
36 }
37}
38
39impl<T: NativeRefCounted + NodeSubtype> Deref for RCHandle<T> {
40 type Target = RCHandle<T::Base>;
41
42 fn deref(&self) -> &Self::Target {
43 self.as_base()
44 }
45}
46
47impl<T: NativeRefCounted + NodeSubtype> DerefMut for RCHandle<T> {
51 fn deref_mut(&mut self) -> &mut Self::Target {
52 self.as_base_mut()
53 }
54}
55
56impl<N: NativeRefCounted> Debug for RCHandle<N>
57where
58 Self: DebugAttributes,
59{
60 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
61 let mut builder = f.debug_struct(Self::NAME);
62
63 self._dbg(&mut builder);
64
65 builder.finish()
66 }
67}
68
69pub trait DebugAttributes {
70 const NAME: &'static str;
71
72 fn _dbg(&self, builder: &mut DebugStruct);
73}
74
75#[cfg(test)]
76mod tests {
77 use crate::svg::{Circle, Shape, TypedNode};
78
79 #[test]
80 fn subtype_can_access_supertype_attributes() {
81 let circle = Circle::default();
82 _ = circle.opacity();
83 }
84
85 #[test]
86 fn subtype_can_set_supertype_attributes() {
87 let mut circle = Circle::default();
88 circle.set_opacity(0.1);
89 }
90
91 #[test]
92 fn supertype_can_be_retrieved_and_contains_the_same_attributes() {
93 let mut circle = Circle::default();
94 circle.set_opacity(0.1);
95 let base: &Shape = circle.as_base();
96 assert_eq!(base.opacity(), Some(0.1));
97 }
98
99 #[test]
100 fn supertype_can_be_modified_and_affects_subtype() {
101 let mut circle = Circle::default();
102 let base: &mut Shape = circle.as_base_mut();
103 base.set_opacity(0.1);
104 assert_eq!(circle.opacity(), Some(0.1));
105 }
106
107 #[test]
108 fn concrete_node_can_be_converted_to_a_node() {
109 Circle::default().into_node();
110 }
111
112 #[test]
113 fn concrete_node_can_be_typed() {
114 let circle = Circle::default().typed();
115 assert!(matches!(circle, TypedNode::Circle(_)));
116 }
117}