Skip to main content

gsk4/
render_node.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use glib::translate::*;
4
5use crate::{ParseLocation, RenderNode, RenderNodeType, ffi, prelude::*};
6
7impl RenderNode {
8    #[inline]
9    pub fn is<T: IsRenderNode>(&self) -> bool {
10        T::NODE_TYPE == self.node_type()
11    }
12
13    #[inline]
14    pub fn type_(&self) -> glib::Type {
15        unsafe {
16            let ptr = self.as_ptr();
17            from_glib((*(*(ptr as *mut glib::gobject_ffi::GTypeInstance)).g_class).g_type)
18        }
19    }
20
21    /// Loads data previously created via [`serialize()`][Self::serialize()].
22    ///
23    /// For a discussion of the supported format, see that function.
24    /// ## `bytes`
25    /// the bytes containing the data
26    /// ## `error_func`
27    /// callback on parsing errors
28    ///
29    /// # Returns
30    ///
31    /// a new render node
32    #[doc(alias = "gsk_render_node_deserialize")]
33    pub fn deserialize(bytes: &glib::Bytes) -> Option<Self> {
34        assert_initialized_main_thread!();
35        unsafe {
36            from_glib_full(ffi::gsk_render_node_deserialize(
37                bytes.to_glib_none().0,
38                None,
39                std::ptr::null_mut(),
40            ))
41        }
42    }
43
44    #[doc(alias = "gsk_render_node_deserialize")]
45    pub fn deserialize_with_error_func<P: FnMut(&ParseLocation, &ParseLocation, &glib::Error)>(
46        bytes: &glib::Bytes,
47        error_func: P,
48    ) -> Option<Self> {
49        assert_initialized_main_thread!();
50        let mut error_func_data: P = error_func;
51        unsafe extern "C" fn error_func_func<
52            P: FnMut(&ParseLocation, &ParseLocation, &glib::Error),
53        >(
54            start: *const ffi::GskParseLocation,
55            end: *const ffi::GskParseLocation,
56            error: *const glib::ffi::GError,
57            user_data: glib::ffi::gpointer,
58        ) {
59            unsafe {
60                let start = from_glib_borrow(start);
61                let end = from_glib_borrow(end);
62                let error = from_glib_borrow(error);
63                let callback = user_data as *mut P;
64                (*callback)(&start, &end, &error);
65            }
66        }
67        let error_func = Some(error_func_func::<P> as _);
68        let super_callback0: &mut P = &mut error_func_data;
69        unsafe {
70            from_glib_full(ffi::gsk_render_node_deserialize(
71                bytes.to_glib_none().0,
72                error_func,
73                super_callback0 as *mut _ as *mut _,
74            ))
75        }
76    }
77
78    #[inline]
79    pub fn downcast<T: IsRenderNode>(self) -> Result<T, Self> {
80        unsafe {
81            if self.is::<T>() {
82                Ok(from_glib_full(self.into_glib_ptr()))
83            } else {
84                Err(self)
85            }
86        }
87    }
88
89    #[inline]
90    pub fn downcast_ref<T: IsRenderNode>(&self) -> Option<&T> {
91        unsafe {
92            if self.is::<T>() {
93                Some(&*(self as *const RenderNode as *const T))
94            } else {
95                None
96            }
97        }
98    }
99}
100
101impl std::fmt::Debug for RenderNode {
102    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
103        f.debug_struct("RenderNode")
104            .field("bounds", &self.bounds())
105            .field("node_type", &self.node_type())
106            .finish()
107    }
108}
109
110// rustdoc-stripper-ignore-next
111/// A common trait implemented by the various [`RenderNode`](crate::RenderNode)
112/// types.
113///
114/// # Safety
115///
116/// The user is not supposed to implement this trait.
117pub unsafe trait IsRenderNode:
118    StaticType
119    + FromGlibPtrFull<*mut ffi::GskRenderNode>
120    + std::convert::AsRef<crate::RenderNode>
121    + 'static
122{
123    const NODE_TYPE: RenderNodeType;
124    fn upcast(self) -> RenderNode;
125    fn upcast_ref(&self) -> &RenderNode;
126}
127
128macro_rules! define_render_node {
129    ($rust_type:ident, $ffi_type:path, $node_type:path) => {
130        impl std::ops::Deref for $rust_type {
131            type Target = crate::RenderNode;
132
133            #[inline]
134            fn deref(&self) -> &Self::Target {
135                unsafe { &*(self as *const $rust_type as *const crate::RenderNode) }
136            }
137        }
138
139        unsafe impl crate::render_node::IsRenderNode for $rust_type {
140            const NODE_TYPE: RenderNodeType = $node_type;
141
142            #[inline]
143            fn upcast(self) -> crate::RenderNode {
144                unsafe {
145                    glib::translate::from_glib_full(
146                        glib::translate::IntoGlibPtr::<*mut $ffi_type>::into_glib_ptr(self)
147                            as *mut crate::ffi::GskRenderNode,
148                    )
149                }
150            }
151
152            #[inline]
153            fn upcast_ref(&self) -> &crate::RenderNode {
154                self
155            }
156        }
157
158        #[doc(hidden)]
159        impl glib::translate::FromGlibPtrFull<*mut crate::ffi::GskRenderNode> for $rust_type {
160            #[inline]
161            unsafe fn from_glib_full(ptr: *mut crate::ffi::GskRenderNode) -> Self {
162                unsafe { glib::translate::from_glib_full(ptr as *mut $ffi_type) }
163            }
164        }
165
166        define_render_node!($rust_type, $ffi_type);
167    };
168    ($rust_type:ident, $ffi_type:path) => {
169        impl std::convert::AsRef<crate::RenderNode> for $rust_type {
170            #[inline]
171            fn as_ref(&self) -> &crate::RenderNode {
172                self
173            }
174        }
175
176        #[cfg(feature = "v4_6")]
177        #[cfg_attr(docsrs, doc(cfg(feature = "v4_6")))]
178        impl glib::value::ValueType for $rust_type {
179            type Type = Self;
180        }
181
182        #[cfg(feature = "v4_6")]
183        #[cfg_attr(docsrs, doc(cfg(feature = "v4_6")))]
184        unsafe impl<'a> glib::value::FromValue<'a> for $rust_type {
185            type Checker = glib::value::GenericValueTypeOrNoneChecker<Self>;
186
187            #[inline]
188            unsafe fn from_value(value: &'a glib::Value) -> Self {
189                unsafe {
190                    skip_assert_initialized!();
191                    glib::translate::from_glib_full(crate::ffi::gsk_value_dup_render_node(
192                        glib::translate::ToGlibPtr::to_glib_none(value).0,
193                    ))
194                }
195            }
196        }
197
198        #[cfg(feature = "v4_6")]
199        #[cfg_attr(docsrs, doc(cfg(feature = "v4_6")))]
200        impl glib::value::ToValue for $rust_type {
201            #[inline]
202            fn to_value(&self) -> glib::Value {
203                let mut value = glib::Value::for_value_type::<Self>();
204                unsafe {
205                    crate::ffi::gsk_value_set_render_node(
206                        glib::translate::ToGlibPtrMut::to_glib_none_mut(&mut value).0,
207                        self.as_ptr() as *mut _,
208                    )
209                }
210                value
211            }
212
213            #[inline]
214            fn value_type(&self) -> glib::Type {
215                use glib::prelude::StaticType;
216                Self::static_type()
217            }
218        }
219
220        #[cfg(feature = "v4_6")]
221        #[cfg_attr(docsrs, doc(cfg(feature = "v4_6")))]
222        impl glib::value::ToValueOptional for $rust_type {
223            #[inline]
224            fn to_value_optional(s: Option<&Self>) -> glib::Value {
225                skip_assert_initialized!();
226                let mut value = glib::Value::for_value_type::<Self>();
227                unsafe {
228                    crate::ffi::gsk_value_set_render_node(
229                        glib::translate::ToGlibPtrMut::to_glib_none_mut(&mut value).0,
230                        s.map(|s| s.as_ptr()).unwrap_or(std::ptr::null_mut()) as *mut _,
231                    )
232                }
233                value
234            }
235        }
236    };
237}
238
239define_render_node!(RenderNode, crate::ffi::GskRenderNode);