1macro_rules! wand_common {
17 ( $wand:ident,
18 $new_wand:ident, $clear_wand:ident, $is_wand:ident, $clone:ident, $destroy:ident,
19 $clear_exc:ident, $get_exc_type:ident, $get_exc:ident
20 ) => {
21 #[doc = concat!(
22 "A safe wrapper around an ImageMagick `", stringify!($wand), "`.\n\n",
23 "The wand owns the underlying ImageMagick handle and destroys it when dropped."
24 )]
25 pub struct $wand {
26 wand: *mut crate::bindings::$wand,
27 }
28
29 impl Default for $wand {
30 fn default() -> Self {
31 Self::new()
32 }
33 }
34
35 impl $wand {
36 #[doc = concat!("Creates a new, empty `", stringify!($wand), "`.")]
37 pub fn new() -> Self {
38 $wand {
39 wand: unsafe { crate::bindings::$new_wand() },
40 }
41 }
42
43 pub(crate) fn from_ptr(ptr: *mut crate::bindings::$wand) -> Self {
44 $wand { wand: ptr }
45 }
46
47 pub(crate) fn as_ptr(&self) -> *mut crate::bindings::$wand {
48 self.wand
49 }
50
51 fn clear(&mut self) {
52 unsafe { crate::bindings::$clear_wand(self.wand) }
53 }
54
55 pub fn clear_exception(&mut self) -> Result<()> {
57 match unsafe { crate::bindings::$clear_exc(self.wand) } {
58 crate::bindings::MagickBooleanType::MagickTrue => Ok(()),
59 _ => Err(MagickError(
60 concat!("failed to clear", stringify!($wand), "exception").to_string(),
61 )),
62 }
63 }
64
65 pub fn get_exception_type(&self) -> crate::bindings::ExceptionType {
67 unsafe { crate::bindings::$get_exc_type(self.wand) }
68 }
69
70 pub fn get_exception(&self) -> Result<(String, crate::bindings::ExceptionType)> {
73 let mut severity: crate::bindings::ExceptionType =
74 crate::bindings::ExceptionType::UndefinedException;
75
76 let ptr = unsafe { crate::bindings::$get_exc(self.wand, &mut severity as *mut _) };
77 if ptr.is_null() {
78 Err(MagickError(
79 concat!("null ptr returned by", stringify!($wand), "get_exception")
80 .to_string(),
81 ))
82 } else {
83 let c_str = unsafe { CStr::from_ptr(ptr) };
84 let exception = c_str.to_string_lossy().into_owned();
85 unsafe { crate::bindings::RelinquishMagickMemory(ptr as *mut ::libc::c_void) };
86 Ok((exception, severity))
87 }
88 }
89
90 pub fn is_wand(&self) -> Result<()> {
92 match unsafe { crate::bindings::$is_wand(self.wand) } {
93 crate::bindings::MagickBooleanType::MagickTrue => Ok(()),
94 _ => Err(MagickError(
95 concat!(stringify!($wand), " not a wand").to_string(),
96 )),
97 }
98 }
99 }
100
101 impl Clone for $wand {
102 fn clone(&self) -> Self {
103 $wand {
104 wand: unsafe { crate::bindings::$clone(self.wand) },
105 }
106 }
107 }
108
109 impl Drop for $wand {
110 fn drop(&mut self) {
111 unsafe {
112 crate::bindings::$clear_exc(self.wand);
113 crate::bindings::$destroy(self.wand);
114 }
115 }
116 }
117
118 unsafe impl Send for $wand {}
120
121 };
125}
126
127macro_rules! get {
128 ($($get:ident, $c_get:ident, $typ:ty )*) => {
129 $(
130 #[doc = concat!("Wraps ImageMagick's `", stringify!($c_get), "` function.")]
131 pub fn $get(&self) -> $typ {
132 unsafe { crate::bindings::$c_get(self.wand).into() }
133 }
134 )*
135 }
136}
137
138macro_rules! set_get {
139 ($($get:ident, $set:ident, $c_get:ident, $c_set:ident, $typ:ty )*) => {
140 $(
141 #[doc = concat!("Wraps ImageMagick's `", stringify!($c_get), "` function.")]
142 pub fn $get(&self) -> $typ {
143 unsafe { crate::bindings::$c_get(self.wand).into() }
144 }
145 #[doc = concat!("Wraps ImageMagick's `", stringify!($c_set), "` function.")]
146 pub fn $set(&mut self, v: $typ) -> Result<()> {
147 match unsafe { crate::bindings::$c_set(self.wand, v.into()) } {
148 crate::bindings::MagickBooleanType::MagickTrue => Ok(()),
149 _ => Err(MagickError(concat!(stringify!($set), " returned false").to_string()))
150 }
151 }
152 )*
153 pub fn fmt_checked_settings(&self, f: &mut ::std::fmt::Formatter, prefix: &str) -> ::std::fmt::Result {
154 $( writeln!(f, "{}{:<50}: {:?}", prefix, stringify!($c_get), self.$get())?; )*
155 Ok(())
156 }
157 }
158}
159
160macro_rules! set_get_unchecked {
161 ($($get:ident, $set:ident, $c_get:ident, $c_set:ident, $typ:ty )*) => {
162 $(
163 #[doc = concat!("Wraps ImageMagick's `", stringify!($c_get), "` function.")]
164 pub fn $get(&self) -> $typ {
165 unsafe { crate::bindings::$c_get(self.wand).into() }
166 }
167 #[doc = concat!("Wraps ImageMagick's `", stringify!($c_set), "` function.")]
168 pub fn $set(&mut self, v: $typ) {
169 unsafe { crate::bindings::$c_set(self.wand, v.into()) }
170 }
171 )*
172 pub fn fmt_unchecked_settings(&self, f: &mut ::std::fmt::Formatter, prefix: &str) -> ::std::fmt::Result {
173 $( writeln!(f, "{}{:<50}: {:?}", prefix, stringify!($c_get), self.$get())?; )*
174 Ok(())
175 }
176 }
177}
178
179macro_rules! string_get {
180 ($get:ident, $c_get:ident) => {
181 #[doc = concat!("Wraps ImageMagick's `", stringify!($c_get), "` function.")]
182 pub fn $get(&self) -> Result<String> {
183 let ptr = unsafe { crate::bindings::$c_get(self.wand) };
184 if ptr.is_null() {
185 Err(MagickError(
186 concat!("null ptr returned by ", stringify!($get)).to_string(),
187 ))
188 } else {
189 let c_str = unsafe { ::std::ffi::CStr::from_ptr(ptr) };
190 let result: String = c_str.to_string_lossy().into_owned();
191 unsafe { crate::bindings::free(ptr as *mut ::libc::c_void) };
192 Ok(result)
193 }
194 }
195 };
196}
197
198macro_rules! string_set_get {
199 ($($get:ident, $set:ident, $c_get:ident, $c_set:ident)*) => {
200 $(
201 string_get!($get, $c_get);
202 #[doc = concat!("Wraps ImageMagick's `", stringify!($c_set), "` function.")]
203 pub fn $set(&mut self, s: &str) -> Result<()> {
204 let c_string = std::ffi::CString::new(s).map_err(|_| "could not convert to cstring")?;
205 match unsafe { crate::bindings::$c_set(self.wand, c_string.as_ptr()) } {
206 crate::bindings::MagickBooleanType::MagickTrue => Ok(()),
207 _ => Err(MagickError(concat!(stringify!($set), " returned false").to_string()))
208 }
209 }
210 )*
211 pub fn fmt_string_settings(&self, f: &mut ::std::fmt::Formatter, prefix: &str) -> ::std::fmt::Result {
212 $( writeln!(f, "{}{:<50}: {:?}", prefix, stringify!($c_get), self.$get())?; )*
213 Ok(())
214 }
215 }
216}
217
218macro_rules! string_set_get_unchecked {
219 ($($get:ident, $set:ident, $c_get:ident, $c_set:ident )*) => {
220 $(
221 string_get!($get, $c_get);
222 #[doc = concat!("Wraps ImageMagick's `", stringify!($c_set), "` function.")]
223 pub fn $set(&mut self, s: &str) -> Result<()> {
224 let c_string = ::std::ffi::CString::new(s).map_err(|_| "could not convert to cstring")?;
225 unsafe { crate::bindings::$c_set(self.wand, c_string.as_ptr()) };
226 Ok(())
227 }
228 )*
229 pub fn fmt_string_unchecked_settings(&self, f: &mut ::std::fmt::Formatter, prefix: &str) -> ::std::fmt::Result {
230 $( writeln!(f, "{}{:<50}: {:?}", prefix, stringify!($c_get), self.$get())?; )*
231 Ok(())
232 }
233 }
234}
235
236macro_rules! pixel_set_get {
237 ($($get:ident, $set:ident, $c_get:ident, $c_set:ident )*) => {
238 $(
239 #[doc = concat!("Wraps ImageMagick's `", stringify!($c_get), "` function.")]
240 pub fn $get(&self) -> crate::PixelWand {
241 let pw = crate::PixelWand::new();
242 unsafe { crate::bindings::$c_get(self.wand, pw.as_ptr()) };
243 pw
244 }
245 #[doc = concat!("Wraps ImageMagick's `", stringify!($c_set), "` function.")]
246 pub fn $set(&mut self, pw: &crate::PixelWand) {
247 unsafe { crate::bindings::$c_set(self.wand, pw.as_ptr()) }
248 }
249 )*
250 pub fn fmt_pixel_settings(&self, f: &mut ::std::fmt::Formatter, prefix: &str) -> ::std::fmt::Result {
251 $(
252 writeln!(f, "{}{:<50}: ", prefix, stringify!($c_get))?;
253 self.$get().fmt_w_prefix(f, &format!("{}{:<53}", prefix, " ") )?;
254 )*
255 Ok(())
256 }
257 }
258}
259
260macro_rules! color_set_get {
261 ($(
262 $get:ident, $get_quantum:ident, $set:ident, $set_quantum:ident,
263 $c_get:ident, $c_get_quantum:ident, $c_set:ident, $c_set_quantum:ident
264 )*) => {
265 $(
266 #[doc = concat!("Wraps ImageMagick's `", stringify!($c_get), "` function.")]
267 pub fn $get(&self) -> f64 {
268 unsafe { crate::bindings::$c_get(self.wand) }
269 }
270 #[doc = concat!("Wraps ImageMagick's `", stringify!($c_get_quantum), "` function.")]
271 pub fn $get_quantum(&self) -> bindings::Quantum {
272 unsafe { crate::bindings::$c_get_quantum(self.wand) }
273 }
274 #[doc = concat!("Wraps ImageMagick's `", stringify!($c_set), "` function.")]
275 pub fn $set(&mut self, v: f64) {
276 unsafe { crate::bindings::$c_set(self.wand, v) }
277 }
278 #[doc = concat!("Wraps ImageMagick's `", stringify!($c_set_quantum), "` function.")]
279 pub fn $set_quantum(&mut self, v: bindings::Quantum) {
280 unsafe { crate::bindings::$c_set_quantum(self.wand, v) }
281 }
282 )*
283 pub fn fmt_color_settings(&self, f: &mut ::std::fmt::Formatter, prefix: &str) -> ::std::fmt::Result {
284 writeln!(f, "{}Color: {:?}, normalized: {:?}\n{}hsl: {:?}",
285 prefix,
286 self.get_color_as_string(),
287 self.get_color_as_normalized_string(),
288 prefix,
289 self.get_hsl()
290 )?;
291 $( writeln!(f, "{}{:<10}: {:>} quantum: {}", prefix, stringify!($c_get).split_at(8).1, self.$get(), self.$get_quantum())?; )*
292 Ok(())
293 }
294 }
295}
296
297macro_rules! mutations {
298 ($($(#[$attr:meta])* $c_fun:ident => $fun:ident($($arg:ident: $ty:ty),*))*) => {
299 $(
300 $(#[$attr])*
301 pub fn $fun(&self $(, $arg: $ty)*) -> Result<()> {
302 match unsafe { bindings::$c_fun(self.wand $(, $arg.into())*) } {
303 bindings::MagickBooleanType::MagickTrue => Ok(()),
304 _ => Err(MagickError(concat!(stringify!($c_fun), " invocation failed").to_string()))
305 }
306 }
307 )*
308 }
309}