1use std::os::raw::c_int;
2
3use pixman_sys as ffi;
4use thiserror::Error;
5
6use crate::{
7 repeat::Repeat, Dither, Filter, Fixed, OperationFailed, Region16, Region32, Transform,
8};
9
10mod bits;
11mod conical_gradient;
12mod linear_gradient;
13mod radial_gradient;
14mod solid;
15
16pub use bits::*;
17pub use conical_gradient::ConicalGradient;
18pub use linear_gradient::LinearGradient;
19pub use radial_gradient::RadialGradient;
20pub use solid::Solid;
21
22#[derive(Debug, Error)]
24#[error("Resource creation failed")]
25pub struct CreateFailed;
26
27#[derive(Debug)]
29pub struct ImageRef(*mut ffi::pixman_image_t);
30
31#[cfg(feature = "sync")]
33unsafe impl Send for ImageRef {}
34#[cfg(feature = "sync")]
35unsafe impl Sync for ImageRef {}
36
37impl ImageRef {
38 pub fn set_repeat(&mut self, repeat: Repeat) {
40 unsafe {
41 ffi::pixman_image_set_repeat(self.0, repeat.into());
42 }
43 }
44
45 pub fn set_transform(
47 &mut self,
48 transform: impl Into<Transform>,
49 ) -> Result<(), OperationFailed> {
50 let transform = transform.into();
51 let res = unsafe { ffi::pixman_image_set_transform(self.0, transform.as_ptr()) };
52 if res == 1 {
53 Ok(())
54 } else {
55 Err(OperationFailed)
56 }
57 }
58
59 pub fn clear_transform(&mut self) -> Result<(), OperationFailed> {
61 let res = unsafe { ffi::pixman_image_set_transform(self.0, std::ptr::null()) };
62 if res == 1 {
63 Ok(())
64 } else {
65 Err(OperationFailed)
66 }
67 }
68
69 pub fn set_clip_region(&mut self, region: Option<&Region16>) -> Result<(), OperationFailed> {
71 let region = if let Some(region) = region {
72 region.as_ptr()
73 } else {
74 std::ptr::null()
75 };
76 let res = unsafe { ffi::pixman_image_set_clip_region(self.0, region) };
77 if res == 1 {
78 Ok(())
79 } else {
80 Err(OperationFailed)
81 }
82 }
83
84 pub fn set_clip_region32(&mut self, region: Option<&Region32>) -> Result<(), OperationFailed> {
86 let region = if let Some(region) = region {
87 region.as_ptr()
88 } else {
89 std::ptr::null()
90 };
91 let res = unsafe { ffi::pixman_image_set_clip_region32(self.0, region) };
92 if res == 1 {
93 Ok(())
94 } else {
95 Err(OperationFailed)
96 }
97 }
98
99 pub fn set_dither(&mut self, dither: Dither) {
101 unsafe {
102 ffi::pixman_image_set_dither(self.0, dither.into());
103 }
104 }
105
106 pub fn set_dither_offset(&mut self, offset_x: c_int, offset_y: c_int) {
108 unsafe { ffi::pixman_image_set_dither_offset(self.0, offset_x, offset_y) }
109 }
110
111 pub fn set_filter(
113 &mut self,
114 filter: Filter,
115 filter_params: &[Fixed],
116 ) -> Result<(), OperationFailed> {
117 let res = unsafe {
118 ffi::pixman_image_set_filter(
119 self.0,
120 filter.into(),
121 filter_params.as_ptr() as *const _,
122 filter_params.len() as i32,
123 )
124 };
125 if res == 1 {
126 Ok(())
127 } else {
128 Err(OperationFailed)
129 }
130 }
131
132 pub fn set_has_client_clip(&mut self, client_clip: bool) {
134 let client_clip = if client_clip { 1 } else { 0 };
135 unsafe {
136 ffi::pixman_image_set_has_client_clip(self.0, client_clip);
137 }
138 }
139
140 pub fn set_source_clipping(&mut self, source_clipping: bool) {
145 let source_clipping = if source_clipping { 1 } else { 0 };
146 unsafe {
147 ffi::pixman_image_set_source_clipping(self.0, source_clipping);
148 }
149 }
150
151 pub fn component_alpha(&self) -> bool {
153 unsafe { ffi::pixman_image_get_component_alpha(self.0) == 1 }
154 }
155
156 pub fn set_component_alpha(&mut self, component_alpha: bool) {
158 let component_alpha = if component_alpha { 1 } else { 0 };
159 unsafe { ffi::pixman_image_set_component_alpha(self.0, component_alpha) }
160 }
161}
162
163impl ImageRef {
164 pub unsafe fn from_ptr(ptr: *mut ffi::pixman_image_t) -> Self {
171 assert!(!ptr.is_null());
172 ImageRef(ptr)
173 }
174
175 pub fn as_ptr(&self) -> *mut ffi::pixman_image_t {
177 self.0
178 }
179}
180
181impl Drop for ImageRef {
182 fn drop(&mut self) {
183 #[cfg(feature = "sync")]
184 let _lock = crate::REF_COUNT_LOCK.lock().unwrap();
185 unsafe {
186 ffi::pixman_image_unref(self.0);
187 }
188 }
189}
190
191macro_rules! image_type {
192 ($(#[$attr:meta])* $name:ident) => {
193 $(#[$attr])*
194 pub struct $name<'alpha> {
195 image: $crate::ImageRef,
196 _phantom: std::marker::PhantomData<&'alpha ()>,
197 }
198
199 impl<'a> $name<'a> {
200 pub fn set_alpha_map<'alpha: 'a>(
203 self,
204 alpha_map: &'alpha crate::Image<'_, 'static>,
205 x: i16,
206 y: i16,
207 ) -> $name<'alpha> {
208 #[cfg(feature = "sync")]
209 let _lock = $crate::REF_COUNT_LOCK.lock().unwrap();
210 unsafe {
211 $crate::ffi::pixman_image_set_alpha_map(
212 self.as_ptr(),
213 alpha_map.as_ptr(),
214 x,
215 y,
216 );
217 }
218 $name {
219 image: self.image,
220 _phantom: std::marker::PhantomData,
221 }
222 }
223
224 pub fn clear_alpha_map(self) -> $name<'static> {
226 #[cfg(feature = "sync")]
227 let _lock = $crate::REF_COUNT_LOCK.lock().unwrap();
228 unsafe {
229 $crate::ffi::pixman_image_set_alpha_map(
230 self.as_ptr(),
231 std::ptr::null_mut(),
232 0,
233 0,
234 );
235 }
236 $name {
237 image: self.image,
238 _phantom: std::marker::PhantomData,
239 }
240 }
241 }
242
243 impl<'alpha> $name<'alpha> {
244 pub unsafe fn from_ptr(ptr: *mut ffi::pixman_image_t) -> Self {
251 Self {
252 image: $crate::ImageRef::from_ptr(ptr),
253 _phantom: std::marker::PhantomData,
254 }
255 }
256 }
257
258 impl<'alpha> std::ops::Deref for $name<'alpha> {
259 type Target = $crate::ImageRef;
260
261 fn deref(&self) -> &Self::Target {
262 &self.image
263 }
264 }
265
266 impl<'alpha> std::ops::DerefMut for $name<'alpha> {
267 fn deref_mut(&mut self) -> &mut Self::Target {
268 &mut self.image
269 }
270 }
271 };
272}
273
274pub(crate) use image_type;