Skip to content

Instantly share code, notes, and snippets.

@stephancasas
Created November 8, 2023 05:40
Show Gist options
  • Save stephancasas/7d85cbaf45a469915d1821e590330247 to your computer and use it in GitHub Desktop.
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.
//
// 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