Skip to content

Commit

Permalink
Merge pull request #1 from sanxiyn/core-graphics
Browse files Browse the repository at this point in the history
Add macOS support using Core Graphics
  • Loading branch information
john01dav committed Jan 19, 2022
2 parents a23b7f9 + f5b18e8 commit 55f5c79
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 0 deletions.
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ x11-dl = "2.19.1"
[target.'cfg(target_os = "windows")'.dependencies]
winapi = "0.3.9"

[target.'cfg(target_os = "macos")'.dependencies]
core-graphics = "0.22.3"
objc = "0.2.7"

[dev-dependencies]
winit = "0.26.1"
image = "0.23.14"
64 changes: 64 additions & 0 deletions src/cg.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
use crate::{GraphicsContextImpl, SoftBufferError};
use raw_window_handle::{HasRawWindowHandle, AppKitHandle};
use objc::runtime::Object;
use core_graphics::base::{kCGBitmapByteOrder32Little, kCGImageAlphaNoneSkipFirst, kCGRenderingIntentDefault};
use core_graphics::color_space::CGColorSpace;
use core_graphics::context::CGContext;
use core_graphics::data_provider::CGDataProvider;
use core_graphics::geometry::{CGPoint, CGSize, CGRect};
use core_graphics::image::CGImage;
use core_graphics::sys;

pub struct CGImpl {
view: *mut Object,
}

impl CGImpl {
pub unsafe fn new<W: HasRawWindowHandle>(handle: AppKitHandle) -> Result<Self, SoftBufferError<W>> {
let window = handle.ns_window as *mut Object;
let view = handle.ns_view as *mut Object;
let cls = class!(NSGraphicsContext);
let graphics_context: *mut Object = msg_send![cls, graphicsContextWithWindow:window];
if graphics_context.is_null() {
return Err(SoftBufferError::PlatformError(Some("Graphics context is null".into()), None));
}
let _: () = msg_send![cls, setCurrentContext:graphics_context];
Ok(
Self {
view,
}
)
}
}

impl GraphicsContextImpl for CGImpl {
unsafe fn set_buffer(&mut self, buffer: &[u32], width: u16, height: u16) {
let cls = class!(NSGraphicsContext);
let graphics_context: *mut Object = msg_send![cls, currentContext];
let context_ptr: *mut sys::CGContext = msg_send![graphics_context, CGContext];
let context = CGContext::from_existing_context_ptr(context_ptr);
let color_space = CGColorSpace::create_device_rgb();
let slice = std::slice::from_raw_parts(
buffer.as_ptr() as *const u8,
buffer.len() * 4);
let data_provider = CGDataProvider::from_slice(slice);
let image = CGImage::new(
width as usize,
height as usize,
8,
32,
(width * 4) as usize,
&color_space,
kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst,
&data_provider,
false,
kCGRenderingIntentDefault,
);
let frame: CGRect = msg_send![self.view, frame];
// In Core Graphics, (0, 0) is bottom left, not top left
let origin = CGPoint { x: 0f64, y: frame.size.height };
let size = CGSize { width: width as f64, height: -(height as f64) };
let rect = CGRect { origin, size };
context.draw_image(rect, &image);
}
}
8 changes: 8 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
#![doc = include_str!("../README.md")]

#[cfg(target_os = "macos")]
#[macro_use]
extern crate objc;

#[cfg(target_os = "windows")]
mod win32;
#[cfg(target_os = "macos")]
mod cg;
#[cfg(target_os = "linux")]
mod x11;

Expand Down Expand Up @@ -32,6 +38,8 @@ impl<W: HasRawWindowHandle> GraphicsContext<W> {
RawWindowHandle::Xlib(xlib_handle) => Box::new(x11::X11Impl::new(xlib_handle)?),
#[cfg(target_os = "windows")]
RawWindowHandle::Win32(win32_handle) => Box::new(win32::Win32Impl::new(&win32_handle)?),
#[cfg(target_os = "macos")]
RawWindowHandle::AppKit(appkit_handle) => Box::new(cg::CGImpl::new(appkit_handle)?),
unimplemented_handle_type => return Err(SoftBufferError::UnsupportedPlatform {
window,
human_readable_platform_name: window_handle_type_name(&unimplemented_handle_type),
Expand Down

0 comments on commit 55f5c79

Please sign in to comment.