1
1
use crate :: { GraphicsContextImpl , SoftBufferError } ;
2
2
use raw_window_handle:: { HasRawWindowHandle , AppKitHandle } ;
3
- use objc:: runtime:: Object ;
4
3
use core_graphics:: base:: { kCGBitmapByteOrder32Little, kCGImageAlphaNoneSkipFirst, kCGRenderingIntentDefault} ;
5
4
use core_graphics:: color_space:: CGColorSpace ;
6
- use core_graphics:: context:: CGContext ;
7
5
use core_graphics:: data_provider:: CGDataProvider ;
8
- use core_graphics:: geometry:: { CGPoint , CGSize , CGRect } ;
9
6
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 ;
11
14
12
15
pub struct CGImpl {
13
- view : * mut Object ,
16
+ layer : CALayer ,
14
17
}
15
18
16
19
impl CGImpl {
17
20
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} )
31
32
}
32
33
}
33
34
34
35
impl GraphicsContextImpl for CGImpl {
35
36
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) ;
40
37
let color_space = CGColorSpace :: create_device_rgb ( ) ;
41
- let slice = std:: slice:: from_raw_parts (
38
+ let data = std:: slice:: from_raw_parts (
42
39
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 ) ) ;
45
42
let image = CGImage :: new (
46
43
width as usize ,
47
44
height as usize ,
@@ -54,11 +51,6 @@ impl GraphicsContextImpl for CGImpl {
54
51
false ,
55
52
kCGRenderingIntentDefault,
56
53
) ;
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 ) ;
63
55
}
64
56
}
0 commit comments