geometry.rs

 1use cocoa::{
 2    appkit::NSWindow,
 3    base::id,
 4    foundation::{NSPoint, NSRect, NSSize},
 5};
 6use objc::{msg_send, sel, sel_impl};
 7use pathfinder_geometry::{
 8    rect::RectF,
 9    vector::{vec2f, Vector2F},
10};
11
12///! Macos screen have a y axis that goings up from the bottom of the screen and
13///! an origin at the bottom left of the main display.
14
15pub trait Vector2FExt {
16    /// Converts self to an NSPoint with y axis pointing up.
17    fn to_screen_ns_point(&self, native_window: id, window_height: f64) -> NSPoint;
18}
19impl Vector2FExt for Vector2F {
20    fn to_screen_ns_point(&self, native_window: id, window_height: f64) -> NSPoint {
21        unsafe {
22            let point = NSPoint::new(self.x() as f64, window_height - self.y() as f64);
23            msg_send![native_window, convertPointToScreen: point]
24        }
25    }
26}
27
28pub trait RectFExt {
29    /// Converts self to an NSRect with y axis pointing up.
30    /// The resulting NSRect will have an origin at the bottom left of the rectangle.
31    /// Also takes care of converting from window scaled coordinates to screen coordinates
32    fn to_screen_ns_rect(&self, native_window: id) -> NSRect;
33
34    /// Converts self to an NSRect with y axis point up.
35    /// The resulting NSRect will have an origin at the bottom left of the rectangle.
36    /// Unlike to_screen_ns_rect, coordinates are not converted and are assumed to already be in screen scale
37    fn to_ns_rect(&self) -> NSRect;
38}
39impl RectFExt for RectF {
40    fn to_screen_ns_rect(&self, native_window: id) -> NSRect {
41        unsafe { native_window.convertRectToScreen_(self.to_ns_rect()) }
42    }
43
44    fn to_ns_rect(&self) -> NSRect {
45        NSRect::new(
46            NSPoint::new(
47                self.origin_x() as f64,
48                -(self.origin_y() + self.height()) as f64,
49            ),
50            NSSize::new(self.width() as f64, self.height() as f64),
51        )
52    }
53}
54
55pub trait NSRectExt {
56    /// Converts self to a RectF with y axis pointing down.
57    /// The resulting RectF will have an origin at the top left of the rectangle.
58    /// Also takes care of converting from screen scale coordinates to window coordinates
59    fn to_window_rectf(&self, native_window: id) -> RectF;
60
61    /// Converts self to a RectF with y axis pointing down.
62    /// The resulting RectF will have an origin at the top left of the rectangle.
63    /// Unlike to_screen_ns_rect, coordinates are not converted and are assumed to already be in screen scale
64    fn to_rectf(&self) -> RectF;
65
66    fn intersects(&self, other: Self) -> bool;
67}
68impl NSRectExt for NSRect {
69    fn to_window_rectf(&self, native_window: id) -> RectF {
70        unsafe {
71            self.origin.x;
72            let rect: NSRect = native_window.convertRectFromScreen_(*self);
73            rect.to_rectf()
74        }
75    }
76
77    fn to_rectf(&self) -> RectF {
78        RectF::new(
79            vec2f(
80                self.origin.x as f32,
81                -(self.origin.y + self.size.height) as f32,
82            ),
83            vec2f(self.size.width as f32, self.size.height as f32),
84        )
85    }
86
87    fn intersects(&self, other: Self) -> bool {
88        self.size.width > 0.
89            && self.size.height > 0.
90            && other.size.width > 0.
91            && other.size.height > 0.
92            && self.origin.x <= other.origin.x + other.size.width
93            && self.origin.x + self.size.width >= other.origin.x
94            && self.origin.y <= other.origin.y + other.size.height
95            && self.origin.y + self.size.height >= other.origin.y
96    }
97}