Created
November 8, 2023 05:40
-
-
Save stephancasas/7d85cbaf45a469915d1821e590330247 to your computer and use it in GitHub Desktop.
Extensions and utilities for working with CGPoint and CGRect across AppKit and CoreGraphics coordinate spaces.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// CGCoordinateSpaces.swift | |
// | |
// Created by Stephan Casas on 11/7/23. | |
// | |
import Foundation; | |
// MARK: - CGPoint | |
extension CGPoint { | |
/// Assuming this point is relative to the CoreGraphics/Quartz coordinate space, get a copy which represents its AppKit equivalent. | |
func toAppKit() -> CGPoint { CGPointConvertToAppKit(self) } | |
/// Assuming this point is relative to AppKit's coordinate space, get a copy which represents its CoreGraphics/Quartz equivalent. | |
func toCoreGraphics() -> CGPoint { CGPointConvertToCoreGraphics(self) } | |
} | |
// MARK: - CGRect | |
extension CGRect { | |
/// Assuming this rect is relative to the CoreGraphics/Quartz coordinate space, get a copy which represents its AppKit equivalent. | |
func toAppKit() -> CGRect { CGRectConvertToAppKit(self) } | |
/// Assuming this rect is relative to AppKit's coordinate space, get a copy which represents its CoreGraphics/Quartz equivalent. | |
func toCoreGraphics() -> CGRect { CGRectConvertToCoreGraphics(self) } | |
} | |
// MARK: - Constants | |
fileprivate let kClassNameNSCGSWindow: String = "NSCGSWindow"; | |
fileprivate let kNSCGSWindowConvertPointToCGCoordinates: String = "convertPointToCGCoordinates:"; | |
fileprivate let kNSCGSWindowConvertPointFromCGCoordinates: String = "convertPointFromCGCoordinates:"; | |
fileprivate let kNSCGSWindowConvertRectToCGCoordinates: String = "convertRectToCGCoordinates:"; | |
fileprivate let kNSCGSWindowConvertRectFromCGCoordinates: String = "convertRectFromCGCoordinates:"; | |
// MARK: - Utilities | |
/// Convert the given `CGPoint` from its position in a CoreGraphics/Quartz | |
/// coordinate space to its position in AppKit's coordinate space. | |
/// - Parameter point: The point to convert. | |
/// - Returns: The given point — converted to its AppKit coordiate space-equivalent. | |
func CGPointConvertToAppKit(_ point: CGPoint) -> CGPoint { | |
unsafeBitCast(NSCGSWindowGetClassMethodPointer( | |
kNSCGSWindowConvertPointFromCGCoordinates | |
), to: (@convention(c) (CGPoint) -> CGPoint).self)(point) | |
} | |
/// Convert the given `CGPoint` from its position in AppKit's coordinate | |
/// space to its position in a CoreGraphics/Quartz coordinate space. | |
/// - Parameter point: The point to convert. | |
/// - Returns: The given point — converted to its CoreGraphics/Quartz coordiate space-equivalent. | |
func CGPointConvertToCoreGraphics(_ point: CGPoint) -> CGPoint { | |
unsafeBitCast(NSCGSWindowGetClassMethodPointer( | |
kNSCGSWindowConvertPointToCGCoordinates | |
), to: (@convention(c) (CGPoint) -> CGPoint).self)(point) | |
} | |
/// Convert the given `CGRect` from its representation in a CoreGraphics/Quartz | |
/// coordinate space to its representation in AppKit's coordinate space. | |
/// - Parameter rect: The rect to convert. | |
/// - Returns: The given rect — converted to its AppKit representation. | |
func CGRectConvertToAppKit(_ rect: CGRect) -> CGRect { | |
unsafeBitCast(NSCGSWindowGetClassMethodPointer( | |
kNSCGSWindowConvertRectFromCGCoordinates | |
), to: (@convention(c) (CGRect) -> CGRect).self)(rect) | |
} | |
/// Convert the given `CGRect` from its representation in AppKit's coordinate | |
/// space to its representation in a CoreGraphics/Quartz coordinate space. | |
/// - Parameter rect: The rect to convert. | |
/// - Returns: The given rect — converted to its CoreGraphics/Quartz representation. | |
func CGRectConvertToCoreGraphics(_ rect: CGRect) -> CGRect { | |
unsafeBitCast(NSCGSWindowGetClassMethodPointer( | |
kNSCGSWindowConvertRectToCGCoordinates | |
), to: (@convention(c) (CGRect) -> CGRect).self)(rect) | |
} | |
fileprivate func NSCGSWindowGetClassMethodPointer(_ methodName: String) -> IMP { | |
guard | |
let _class = objc_getClass( | |
kClassNameNSCGSWindow) as? AnyClass, | |
let _method = class_getClassMethod( | |
_class, Selector((methodName))) | |
else { fatalError( | |
"Could not load private class method +[\(kClassNameNSCGSWindow) \(methodName)]." | |
) } | |
return method_getImplementation(_method); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment