From 895ccc1cde506aa44a38d035e007cb8cb5ef3f98 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Wed, 22 May 2024 03:08:38 +0200 Subject: [PATCH] Use objc2 for macOS font smoothing determination `objc2` / `objc2-foundation` is much more type-safe than `cocoa`, and automatically ensures that memory management-rules are upheld. See also https://github.com/alacritty/copypasta/pull/74. --- Cargo.toml | 8 ++++++-- src/darwin/mod.rs | 44 ++++++++++++++++++++++++++------------------ src/ft/mod.rs | 2 +- 3 files changed, 33 insertions(+), 21 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1dcf65d..906c583 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,13 +25,17 @@ freetype-rs = "0.36.0" pkg-config = "0.3" [target.'cfg(target_os = "macos")'.dependencies] -cocoa = "0.25.0" core-foundation = "0.9.3" core-text = "20.1.0" core-graphics = "0.23.1" core-foundation-sys = "0.8.4" -objc = "0.2.7" once_cell = "1.12" +objc2 = "0.5.1" +objc2-foundation = { version = "0.2.2", features = [ + "NSString", + "NSUserDefaults", + "NSValue", +] } [target.'cfg(windows)'.dependencies] dwrote = { version = "0.11" } diff --git a/src/darwin/mod.rs b/src/darwin/mod.rs index 669b3ab..67ccb86 100644 --- a/src/darwin/mod.rs +++ b/src/darwin/mod.rs @@ -1,15 +1,11 @@ //! Font rendering based on CoreText. use std::collections::HashMap; -use std::ffi::c_char; use std::ffi::CStr; use std::iter; use std::path::PathBuf; use std::ptr; -use cocoa::base::{id, nil}; -use cocoa::foundation::{NSInteger, NSString, NSUserDefaults}; - use core_foundation::array::{CFArray, CFIndex}; use core_foundation::base::{CFType, ItemRef, TCFType}; use core_foundation::number::{CFNumber, CFNumberRef}; @@ -28,10 +24,10 @@ use core_text::font_descriptor::{ self, kCTFontColorGlyphsTrait, kCTFontDefaultOrientation, kCTFontEnabledAttribute, CTFontDescriptor, SymbolicTraitAccessors, }; +use objc2::rc::{autoreleasepool, Retained}; +use objc2_foundation::{ns_string, NSNumber, NSObject, NSObjectProtocol, NSString, NSUserDefaults}; use log::{trace, warn}; -use objc::rc::autoreleasepool; -use objc::{class, msg_send, sel, sel_impl}; use once_cell::sync::Lazy; pub mod byte_order; @@ -274,15 +270,23 @@ fn descriptors_for_family(family: &str) -> Vec { // other integer, or a missing value (the default), or a value of any other type, as leaving it // enabled. static FONT_SMOOTHING_ENABLED: Lazy = Lazy::new(|| { - autoreleasepool(|| unsafe { - let key = NSString::alloc(nil).init_str("AppleFontSmoothing"); - let value: id = msg_send![id::standardUserDefaults(), objectForKey: key]; + autoreleasepool(|_| { + let value = unsafe { + NSUserDefaults::standardUserDefaults().objectForKey(ns_string!("AppleFontSmoothing")) + }; - if msg_send![value, isKindOfClass: class!(NSNumber)] { - let num_type: *const c_char = msg_send![value, objCType]; - if num_type.is_null() { - return true; - } + let value = match value { + Some(value) => value, + None => return true, + }; + + // SAFETY: The values in `NSUserDefaults` are always subclasses of + // `NSObject`. + let value: Retained = unsafe { Retained::cast(value) }; + + if value.is_kind_of::() { + // SAFETY: Just checked that the value is a NSNumber + let value: Retained = unsafe { Retained::cast(value) }; // NSNumber's objCType method returns one of these strings depending on the size: // q = quad (long long), l = long, i = int, s = short. @@ -290,14 +294,18 @@ static FONT_SMOOTHING_ENABLED: Lazy = Lazy::new(|| { // macOS does not treat them the same as an integer 0 or 1 for this setting, // it just ignores it. let int_specifiers: [&[u8]; 4] = [b"q", b"l", b"i", b"s"]; - if !int_specifiers.contains(&CStr::from_ptr(num_type).to_bytes()) { + + let encoding = unsafe { CStr::from_ptr(value.objCType().as_ptr()).to_bytes() }; + if !int_specifiers.contains(&encoding) { return true; } - let smoothing: NSInteger = msg_send![value, integerValue]; + let smoothing = value.integerValue(); smoothing != 0 - } else if msg_send![value, isKindOfClass: class!(NSString)] { - let smoothing: NSInteger = msg_send![value, integerValue]; + } else if value.is_kind_of::() { + // SAFETY: Just checked that the value is a NSString + let value: Retained = unsafe { Retained::cast(value) }; + let smoothing = unsafe { value.integerValue() }; smoothing != 0 } else { true diff --git a/src/ft/mod.rs b/src/ft/mod.rs index 1274e10..de0ccdb 100644 --- a/src/ft/mod.rs +++ b/src/ft/mod.rs @@ -693,7 +693,7 @@ impl FreeTypeLoader { font_key: FontKey, ) -> Result, Error> { if let Some(ft_face_location) = pattern.ft_face_location(0) { - if self.faces.get(&font_key).is_some() { + if self.faces.contains_key(&font_key) { return Ok(Some(font_key)); }