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}