|
| 1 | +use crate::{GraphicsContextImpl, SoftBufferError}; |
| 2 | +use raw_window_handle::{HasRawWindowHandle, AppKitHandle}; |
| 3 | +use objc::runtime::Object; |
| 4 | +use core_graphics::base::{kCGBitmapByteOrder32Little, kCGImageAlphaNoneSkipFirst, kCGRenderingIntentDefault}; |
| 5 | +use core_graphics::color_space::CGColorSpace; |
| 6 | +use core_graphics::context::CGContext; |
| 7 | +use core_graphics::data_provider::CGDataProvider; |
| 8 | +use core_graphics::geometry::{CGPoint, CGSize, CGRect}; |
| 9 | +use core_graphics::image::CGImage; |
| 10 | +use core_graphics::sys; |
| 11 | + |
| 12 | +pub struct CGImpl; |
| 13 | + |
| 14 | +impl CGImpl { |
| 15 | + pub unsafe fn new<W: HasRawWindowHandle>(handle: AppKitHandle) -> Result<Self, SoftBufferError<W>> { |
| 16 | + let window = handle.ns_window as *mut Object; |
| 17 | + let cls = class!(NSGraphicsContext); |
| 18 | + let graphics_context: *mut Object = msg_send![cls, graphicsContextWithWindow:window]; |
| 19 | + if graphics_context.is_null() { |
| 20 | + return Err(SoftBufferError::PlatformError(Some("Graphics context is null".into()), None)); |
| 21 | + } |
| 22 | + let _: () = msg_send![cls, setCurrentContext:graphics_context]; |
| 23 | + Ok(Self) |
| 24 | + } |
| 25 | +} |
| 26 | + |
| 27 | +impl GraphicsContextImpl for CGImpl { |
| 28 | + unsafe fn set_buffer(&mut self, buffer: &[u32], width: u16, height: u16) { |
| 29 | + let cls = class!(NSGraphicsContext); |
| 30 | + let graphics_context: *mut Object = msg_send![cls, currentContext]; |
| 31 | + let context_ptr: *mut sys::CGContext = msg_send![graphics_context, CGContext]; |
| 32 | + let context = CGContext::from_existing_context_ptr(context_ptr); |
| 33 | + let color_space = CGColorSpace::create_device_rgb(); |
| 34 | + let slice = std::slice::from_raw_parts( |
| 35 | + buffer.as_ptr() as *const u8, |
| 36 | + buffer.len() * 4); |
| 37 | + let data_provider = CGDataProvider::from_slice(slice); |
| 38 | + let image = CGImage::new( |
| 39 | + width as usize, |
| 40 | + height as usize, |
| 41 | + 8, |
| 42 | + 32, |
| 43 | + (width * 4) as usize, |
| 44 | + &color_space, |
| 45 | + kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst, |
| 46 | + &data_provider, |
| 47 | + false, |
| 48 | + kCGRenderingIntentDefault, |
| 49 | + ); |
| 50 | + let origin = CGPoint { x: 0f64, y: 0f64 }; |
| 51 | + let size = CGSize { width: width as f64, height: height as f64 }; |
| 52 | + let rect = CGRect { origin, size }; |
| 53 | + context.draw_image(rect, &image); |
| 54 | + } |
| 55 | +} |
0 commit comments