core_graphics2/
bitmap_context.rs1use std::{mem, ptr::null_mut, slice};
2
3use core_foundation::base::TCFType;
4use libc::{c_void, size_t};
5
6use crate::{
7 color_space::{CGColorSpace, CGColorSpaceRef},
8 context::{CGContext, CGContextRef},
9 image::{CGBitmapInfo, CGImage, CGImageAlphaInfo, CGImageRef},
10};
11
12pub type CGBitmapContextReleaseDataCallback = extern "C" fn(*mut c_void, *mut c_void);
13
14extern "C" {
15 pub fn CGBitmapContextCreateWithData(
16 data: *mut c_void,
17 width: size_t,
18 height: size_t,
19 bitsPerComponent: size_t,
20 bytesPerRow: size_t,
21 space: CGColorSpaceRef,
22 bitmapInfo: u32,
23 releaseCallback: CGBitmapContextReleaseDataCallback,
24 releaseInfo: *mut c_void,
25 ) -> CGContextRef;
26 pub fn CGBitmapContextCreate(
27 data: *mut c_void,
28 width: size_t,
29 height: size_t,
30 bitsPerComponent: size_t,
31 bytesPerRow: size_t,
32 space: CGColorSpaceRef,
33 bitmapInfo: u32,
34 ) -> CGContextRef;
35 pub fn CGBitmapContextGetData(context: CGContextRef) -> *mut c_void;
36 pub fn CGBitmapContextGetWidth(context: CGContextRef) -> size_t;
37 pub fn CGBitmapContextGetHeight(context: CGContextRef) -> size_t;
38 pub fn CGBitmapContextGetBitsPerComponent(context: CGContextRef) -> size_t;
39 pub fn CGBitmapContextGetBitsPerPixel(context: CGContextRef) -> size_t;
40 pub fn CGBitmapContextGetBytesPerRow(context: CGContextRef) -> size_t;
41 pub fn CGBitmapContextGetColorSpace(context: CGContextRef) -> CGColorSpaceRef;
42 pub fn CGBitmapContextGetAlphaInfo(context: CGContextRef) -> CGImageAlphaInfo;
43 pub fn CGBitmapContextGetBitmapInfo(context: CGContextRef) -> CGBitmapInfo;
44 pub fn CGBitmapContextCreateImage(context: CGContextRef) -> CGImageRef;
45}
46
47pub trait BitmapData {
48 unsafe fn ptr(&self) -> *const u8;
49 unsafe fn mut_ptr(&self) -> *mut u8;
50 fn width(&self) -> usize;
51 fn height(&self) -> usize;
52 fn bytes_per_row(&self) -> usize;
53}
54
55impl CGContext {
56 pub fn new_bitmap_context(
57 width: size_t,
58 height: size_t,
59 bits_per_component: size_t,
60 bytes_per_row: size_t,
61 space: Option<&CGColorSpace>,
62 bitmap_info: u32,
63 ) -> Option<Self> {
64 unsafe {
65 let context = CGBitmapContextCreate(
66 null_mut(),
67 width,
68 height,
69 bits_per_component,
70 bytes_per_row,
71 space.map_or(null_mut(), |s| s.as_concrete_TypeRef()),
72 bitmap_info,
73 );
74 if context.is_null() {
75 None
76 } else {
77 Some(TCFType::wrap_under_create_rule(context))
78 }
79 }
80 }
81
82 pub unsafe fn new_bitmap_context_with_data(
83 data: &mut [u8],
84 width: size_t,
85 height: size_t,
86 bits_per_component: size_t,
87 bytes_per_row: size_t,
88 space: Option<&CGColorSpace>,
89 bitmap_info: u32,
90 ) -> Option<Self> {
91 if data.len() < height * bytes_per_row {
92 return None;
93 }
94 unsafe {
95 let context = CGBitmapContextCreate(
96 data.as_mut_ptr() as *mut c_void,
97 width,
98 height,
99 bits_per_component,
100 bytes_per_row,
101 space.map_or(null_mut(), |s| s.as_concrete_TypeRef()),
102 bitmap_info,
103 );
104 if context.is_null() {
105 None
106 } else {
107 Some(TCFType::wrap_under_create_rule(context))
108 }
109 }
110 }
111
112 pub fn new_bitmap_context_with_bitmap_data(
113 bitmap_data: Box<Box<dyn BitmapData>>,
114 bits_per_component: size_t,
115 space: Option<&CGColorSpace>,
116 bitmap_info: u32,
117 ) -> Option<Self> {
118 let (width, height, bytes_per_row) = (bitmap_data.width() as size_t, bitmap_data.height() as size_t, bitmap_data.bytes_per_row() as size_t);
119 unsafe {
120 let ptr = bitmap_data.mut_ptr() as *mut c_void;
121 let info = mem::transmute::<Box<Box<dyn BitmapData>>, &mut c_void>(bitmap_data);
122 let context = CGBitmapContextCreateWithData(
123 ptr,
124 width,
125 height,
126 bits_per_component,
127 bytes_per_row,
128 space.map_or(null_mut(), |s| s.as_concrete_TypeRef()),
129 bitmap_info,
130 release,
131 info,
132 );
133 if context.is_null() {
134 drop(mem::transmute::<*mut c_void, Box<Box<dyn BitmapData>>>(info));
135 return None;
136 } else {
137 return Some(TCFType::wrap_under_create_rule(context));
138 }
139 }
140
141 extern "C" fn release(release_info: *mut c_void, _: *mut c_void) {
142 unsafe { drop(mem::transmute::<*mut c_void, Box<Box<dyn BitmapData>>>(release_info)) }
143 }
144 }
145
146 pub fn new_image(&self) -> Option<CGImage> {
147 unsafe {
148 let image = CGBitmapContextCreateImage(self.as_concrete_TypeRef());
149 if image.is_null() {
150 None
151 } else {
152 Some(TCFType::wrap_under_create_rule(image))
153 }
154 }
155 }
156
157 pub fn data(&mut self) -> &mut [u8] {
158 unsafe { slice::from_raw_parts_mut(CGBitmapContextGetData(self.as_concrete_TypeRef()) as *mut u8, self.height() * self.bytes_per_row()) }
159 }
160
161 pub fn width(&self) -> usize {
162 unsafe { CGBitmapContextGetWidth(self.as_concrete_TypeRef()) }
163 }
164
165 pub fn height(&self) -> usize {
166 unsafe { CGBitmapContextGetHeight(self.as_concrete_TypeRef()) }
167 }
168
169 pub fn bits_per_component(&self) -> usize {
170 unsafe { CGBitmapContextGetBitsPerComponent(self.as_concrete_TypeRef()) }
171 }
172
173 pub fn bits_per_pixel(&self) -> usize {
174 unsafe { CGBitmapContextGetBitsPerPixel(self.as_concrete_TypeRef()) }
175 }
176
177 pub fn bytes_per_row(&self) -> usize {
178 unsafe { CGBitmapContextGetBytesPerRow(self.as_concrete_TypeRef()) }
179 }
180
181 pub fn color_space(&self) -> CGColorSpace {
182 unsafe { TCFType::wrap_under_get_rule(CGBitmapContextGetColorSpace(self.as_concrete_TypeRef())) }
183 }
184
185 pub fn alpha_info(&self) -> CGImageAlphaInfo {
186 unsafe { CGBitmapContextGetAlphaInfo(self.as_concrete_TypeRef()) }
187 }
188
189 pub fn bitmap_info(&self) -> CGBitmapInfo {
190 unsafe { CGBitmapContextGetBitmapInfo(self.as_concrete_TypeRef()) }
191 }
192}