fltk_derive/
image.rs

1use crate::utils::get_fl_name;
2use proc_macro::TokenStream;
3use quote::*;
4use syn::*;
5
6pub fn impl_image_trait(ast: &DeriveInput) -> TokenStream {
7    let name = &ast.ident;
8    let name_str = get_fl_name(name.to_string());
9    let ptr_name = Ident::new(name_str.as_str(), name.span());
10
11    let new = Ident::new(format!("{}_{}", name_str, "new").as_str(), name.span());
12    let draw = Ident::new(format!("{}_{}", name_str, "draw").as_str(), name.span());
13    let draw_ext = Ident::new(format!("{}_{}", name_str, "draw_ext").as_str(), name.span());
14    let width = Ident::new(format!("{}_{}", name_str, "width").as_str(), name.span());
15    let height = Ident::new(format!("{}_{}", name_str, "height").as_str(), name.span());
16    let delete = Ident::new(format!("{}_{}", name_str, "delete").as_str(), name.span());
17    let count = Ident::new(format!("{}_{}", name_str, "count").as_str(), name.span());
18    let data = Ident::new(format!("{}_{}", name_str, "data").as_str(), name.span());
19    let copy = Ident::new(format!("{}_{}", name_str, "copy").as_str(), name.span());
20    let scale = Ident::new(format!("{}_{}", name_str, "scale").as_str(), name.span());
21    let data_w = Ident::new(format!("{}_{}", name_str, "data_w").as_str(), name.span());
22    let data_h = Ident::new(format!("{}_{}", name_str, "data_h").as_str(), name.span());
23    let d = Ident::new(format!("{}_{}", name_str, "d").as_str(), name.span());
24    let ld = Ident::new(format!("{}_{}", name_str, "ld").as_str(), name.span());
25    let inactive = Ident::new(format!("{}_{}", name_str, "inactive").as_str(), name.span());
26
27    let gen = quote! {
28        #[cfg(not(feature = "single-threaded"))]
29        unsafe impl Sync for #name {}
30        #[cfg(not(feature = "single-threaded"))]
31        unsafe impl Send for #name {}
32
33        impl PartialEq for #name {
34            fn eq(&self, other: &Self) -> bool {
35                self.inner == other.inner
36            }
37        }
38
39        impl Eq for #name {}
40
41        impl Clone for #name {
42            fn clone(&self) -> Self {
43                assert!(!self.was_deleted());
44                let x = self.refcount.fetch_add(1, Ordering::Relaxed);
45                #name { inner: self.inner, refcount: AtomicUsize::new(x + 1) }
46            }
47        }
48
49        impl Drop for #name {
50            fn drop(&mut self) {
51                if !self.was_deleted() {
52                    self.refcount.fetch_sub(1, Ordering::Relaxed);
53                    if *self.refcount.get_mut() < 1 {
54                        unsafe {
55                            #delete(self.inner);
56                        }
57                    }
58                }
59            }
60        }
61
62        unsafe impl ImageExt for #name {
63            fn copy(&self) -> Self {
64                assert!(!self.was_deleted());
65                unsafe {
66                    let img = #copy(self.inner);
67                    assert!(!img.is_null());
68                    #name {
69                        inner: img,
70                        refcount: AtomicUsize::new(1)
71                    }
72                }
73            }
74
75            fn draw(&mut self, arg2: i32, arg3: i32, arg4: i32, arg5: i32) {
76                assert!(!self.was_deleted());
77                unsafe { #draw(self.inner, arg2, arg3, arg4, arg5) }
78            }
79
80            fn draw_ext(&mut self, arg2: i32, arg3: i32, arg4: i32, arg5: i32, cx: i32, cy: i32) {
81                assert!(!self.was_deleted());
82                unsafe { #draw_ext(self.inner, arg2, arg3, arg4, arg5, cx, cy) }
83            }
84
85            fn width(&self) -> i32 {
86                assert!(!self.was_deleted());
87                unsafe {
88                    #width(self.inner)
89                }
90            }
91
92            fn height(&self) -> i32 {
93                assert!(!self.was_deleted());
94                unsafe {
95                    #height(self.inner)
96                }
97            }
98
99            fn w(&self) -> i32 {
100                assert!(!self.was_deleted());
101                unsafe {
102                    #width(self.inner)
103                }
104            }
105
106            fn h(&self) -> i32 {
107                assert!(!self.was_deleted());
108                unsafe {
109                    #height(self.inner)
110                }
111            }
112
113            unsafe fn as_image_ptr(&self) -> *mut fltk_sys::image::Fl_Image {
114                assert!(!self.was_deleted());
115                self.inner as *mut fltk_sys::image::Fl_Image
116            }
117
118            unsafe fn from_image_ptr(ptr: *mut fltk_sys::image::Fl_Image) -> Self {
119                assert!(!ptr.is_null());
120                #name {
121                    inner: ptr as *mut #ptr_name,
122                    refcount: AtomicUsize::new(1),
123                }
124            }
125
126            fn to_rgb_data(&self) -> Vec<u8> {
127                assert!(!self.was_deleted());
128                unsafe {
129                    let ptr = #data(self.inner);
130                    assert!(!ptr.is_null());
131                    assert!(!(*ptr).is_null());
132                    let cnt = self.data_w() * self.data_h() * self.depth() as i32;
133                    let ret: &[u8] = std::slice::from_raw_parts(*ptr as *const u8, cnt as usize);
134                    ret.to_vec()
135                }
136            }
137
138            fn to_raw_data(&self) -> *const *const u8 {
139                assert!(!self.was_deleted());
140                unsafe {
141                    #data(self.inner) as *const *const u8
142                }
143            }
144
145            fn to_rgb(&self) -> Result<crate::image::RgbImage, FltkError> {
146                assert!(!self.was_deleted());
147                if self.count() != 1 {
148                    Err(FltkError::Internal(FltkErrorKind::ImageFormatError))
149                } else {
150                    let data = self.to_rgb_data();
151                    unsafe { RgbImage::new(&data, self.data_w(), self.data_h(), self.depth()) }
152                }
153            }
154
155            fn scale(&mut self, width: i32, height: i32, proportional: bool, can_expand: bool) {
156                assert!(!self.was_deleted());
157                unsafe {
158                    #scale(self.inner, width, height, proportional as i32, can_expand as i32)
159                }
160            }
161
162            fn count(&self) -> i32 {
163                assert!(!self.was_deleted());
164                unsafe {
165                    #count(self.inner)
166                }
167            }
168
169            fn data_w(&self) -> i32 {
170                assert!(!self.was_deleted());
171                unsafe {
172                    #data_w(self.inner)
173                }
174            }
175
176            fn data_h(&self) -> i32 {
177                assert!(!self.was_deleted());
178                unsafe {
179                    #data_h(self.inner)
180                }
181            }
182
183            fn depth(&self) -> ColorDepth {
184                assert!(!self.was_deleted());
185                unsafe {
186                    mem::transmute(#d(self.inner) as u8)
187                }
188            }
189
190            fn ld(&self) -> i32 {
191                assert!(!self.was_deleted());
192                unsafe {
193                    #ld(self.inner)
194                }
195            }
196
197            fn inactive(&mut self) {
198                assert!(!self.was_deleted());
199                unsafe {
200                    #inactive(self.inner)
201                }
202            }
203
204            unsafe fn delete(mut img: Self) {
205                assert!(!img.inner.is_null());
206                #delete(img.inner);
207                img.inner = std::ptr::null_mut() as *mut #ptr_name;
208            }
209
210            unsafe fn increment_arc(&mut self) {
211                assert!(!self.was_deleted());
212                self.refcount.fetch_add(1, Ordering::Relaxed);
213            }
214
215            unsafe fn decrement_arc(&mut self) {
216                assert!(!self.was_deleted());
217                self.refcount.fetch_sub(1, Ordering::Relaxed);
218                assert!(*self.refcount.get_mut() > 1, "The image should outlive the widget!");
219            }
220
221            fn was_deleted(&self) -> bool {
222                self.inner.is_null()
223            }
224
225            unsafe fn into_image<I: ImageExt>(self) -> I {
226                I::from_image_ptr(self.inner as *mut _)
227            }
228        }
229    };
230    gen.into()
231}