Skip to content

Commit dac3671

Browse files
authored
Merge pull request #3 from lunixbochs/calayer
use CALayer for macOS backend
2 parents 7521606 + 112e777 commit dac3671

File tree

2 files changed

+26
-32
lines changed

2 files changed

+26
-32
lines changed

Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ x11-dl = "2.19.1"
2626
winapi = "0.3.9"
2727

2828
[target.'cfg(target_os = "macos")'.dependencies]
29+
cocoa = "0.24.0"
2930
core-graphics = "0.22.3"
31+
foreign-types = "0.3.0"
3032
objc = "0.2.7"
3133

3234
[target.'cfg(target_arch = "wasm32")'.dependencies]
@@ -49,4 +51,4 @@ features = ["jpeg"]
4951
[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies]
5052
# Turn rayon back on everywhere else; creating the separate entry resets the features to default.
5153
image = "0.23.14"
52-
rayon = "1.5.1"
54+
rayon = "1.5.1"

src/cg.rs

Lines changed: 23 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,44 @@
11
use crate::{GraphicsContextImpl, SoftBufferError};
22
use raw_window_handle::{HasRawWindowHandle, AppKitHandle};
3-
use objc::runtime::Object;
43
use core_graphics::base::{kCGBitmapByteOrder32Little, kCGImageAlphaNoneSkipFirst, kCGRenderingIntentDefault};
54
use core_graphics::color_space::CGColorSpace;
6-
use core_graphics::context::CGContext;
75
use core_graphics::data_provider::CGDataProvider;
8-
use core_graphics::geometry::{CGPoint, CGSize, CGRect};
96
use core_graphics::image::CGImage;
10-
use core_graphics::sys;
7+
8+
use cocoa::base::{id, nil};
9+
use cocoa::appkit::{NSView, NSViewWidthSizable, NSViewHeightSizable};
10+
use cocoa::quartzcore::{CALayer, ContentsGravity};
11+
use foreign_types::ForeignType;
12+
13+
use std::sync::Arc;
1114

1215
pub struct CGImpl {
13-
view: *mut Object,
16+
layer: CALayer,
1417
}
1518

1619
impl CGImpl {
1720
pub unsafe fn new<W: HasRawWindowHandle>(handle: AppKitHandle) -> Result<Self, SoftBufferError<W>> {
18-
let window = handle.ns_window as *mut Object;
19-
let view = handle.ns_view as *mut Object;
20-
let cls = class!(NSGraphicsContext);
21-
let graphics_context: *mut Object = msg_send![cls, graphicsContextWithWindow:window];
22-
if graphics_context.is_null() {
23-
return Err(SoftBufferError::PlatformError(Some("Graphics context is null".into()), None));
24-
}
25-
let _: () = msg_send![cls, setCurrentContext:graphics_context];
26-
Ok(
27-
Self {
28-
view,
29-
}
30-
)
21+
let view = handle.ns_view as id;
22+
let layer = CALayer::new();
23+
let subview: id = NSView::alloc(nil).initWithFrame_(view.frame());
24+
layer.set_contents_gravity(ContentsGravity::TopLeft);
25+
layer.set_needs_display_on_bounds_change(false);
26+
subview.setLayer(layer.id());
27+
subview.setAutoresizingMask_(NSViewWidthSizable | NSViewHeightSizable);
28+
29+
view.addSubview_(subview); // retains subview (+1) = 2
30+
let _: () = msg_send![subview, release]; // releases subview (-1) = 1
31+
Ok(Self{layer})
3132
}
3233
}
3334

3435
impl GraphicsContextImpl for CGImpl {
3536
unsafe fn set_buffer(&mut self, buffer: &[u32], width: u16, height: u16) {
36-
let cls = class!(NSGraphicsContext);
37-
let graphics_context: *mut Object = msg_send![cls, currentContext];
38-
let context_ptr: *mut sys::CGContext = msg_send![graphics_context, CGContext];
39-
let context = CGContext::from_existing_context_ptr(context_ptr);
4037
let color_space = CGColorSpace::create_device_rgb();
41-
let slice = std::slice::from_raw_parts(
38+
let data = std::slice::from_raw_parts(
4239
buffer.as_ptr() as *const u8,
43-
buffer.len() * 4);
44-
let data_provider = CGDataProvider::from_slice(slice);
40+
buffer.len() * 4).to_vec();
41+
let data_provider = CGDataProvider::from_buffer(Arc::new(data));
4542
let image = CGImage::new(
4643
width as usize,
4744
height as usize,
@@ -54,11 +51,6 @@ impl GraphicsContextImpl for CGImpl {
5451
false,
5552
kCGRenderingIntentDefault,
5653
);
57-
let frame: CGRect = msg_send![self.view, frame];
58-
// In Core Graphics, (0, 0) is bottom left, not top left
59-
let origin = CGPoint { x: 0f64, y: frame.size.height };
60-
let size = CGSize { width: width as f64, height: -(height as f64) };
61-
let rect = CGRect { origin, size };
62-
context.draw_image(rect, &image);
54+
self.layer.set_contents(image.as_ptr() as id);
6355
}
6456
}

0 commit comments

Comments
 (0)