From 327848515b57357e6f1b9dadf5c22ff912f082cd Mon Sep 17 00:00:00 2001 From: Zachary Lloyd Date: Wed, 17 Nov 2021 11:52:56 -0500 Subject: [PATCH 1/5] add get_matrix to core text font --- core-text/src/font.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/core-text/src/font.rs b/core-text/src/font.rs index ebe6d580f..64142fac5 100644 --- a/core-text/src/font.rs +++ b/core-text/src/font.rs @@ -395,6 +395,12 @@ impl CTFont { } } + pub fn get_matrix(&self) -> CGAffineTransform { + unsafe { + CTFontGetMatrix(self.as_concrete_TypeRef()) + } + } + pub fn url(&self) -> Option { unsafe { let result = CTFontCopyAttribute(self.0, kCTFontURLAttribute); @@ -556,7 +562,7 @@ extern { fn CTFontCopyFontDescriptor(font: CTFontRef) -> CTFontDescriptorRef; fn CTFontCopyAttribute(font: CTFontRef, attribute: CFStringRef) -> CFTypeRef; fn CTFontGetSize(font: CTFontRef) -> CGFloat; - //fn CTFontGetMatrix + fn CTFontGetMatrix(font: CTFontRef) -> CGAffineTransform; fn CTFontGetSymbolicTraits(font: CTFontRef) -> CTFontSymbolicTraits; fn CTFontCopyTraits(font: CTFontRef) -> CFDictionaryRef; From 6b6191003816fc5f90af1a15e4bfb7b988b03d36 Mon Sep 17 00:00:00 2001 From: Aloke Desai Date: Wed, 19 Jan 2022 17:20:56 -0500 Subject: [PATCH 2/5] add new fn --- core-text/src/run.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/core-text/src/run.rs b/core-text/src/run.rs index b7cb37616..22e532723 100644 --- a/core-text/src/run.rs +++ b/core-text/src/run.rs @@ -15,6 +15,9 @@ use core_foundation::dictionary::{CFDictionary, CFDictionaryRef}; use core_foundation::string::CFString; use core_graphics::font::CGGlyph; use core_graphics::geometry::CGPoint; +use core_graphics::base::{CGFloat}; + +use crate::line::TypographicBounds; #[repr(C)] pub struct __CTRun(c_void); @@ -83,6 +86,16 @@ impl CTRun { } } + pub fn get_typographic_bounds(&self) -> TypographicBounds { + let mut ascent = 0.0; + let mut descent = 0.0; + let mut leading = 0.0; + unsafe { + let width = CTRunGetTypographicBounds(self.as_concrete_TypeRef(), &mut ascent, &mut descent, &mut leading); + TypographicBounds { width, ascent, descent, leading } + } + } + pub fn string_indices(&self) -> Cow<[CFIndex]> { unsafe { // CTRunGetStringIndicesPtr can return null under some not understood circumstances. @@ -149,4 +162,6 @@ extern { fn CTRunGetStringIndices(run: CTRunRef, range: CFRange, buffer: *const CFIndex); fn CTRunGetGlyphsPtr(run: CTRunRef) -> *const CGGlyph; fn CTRunGetGlyphs(run: CTRunRef, range: CFRange, buffer: *const CGGlyph); + + fn CTRunGetTypographicBounds(line: CTRunRef, ascent: *mut CGFloat, descent: *mut CGFloat, leading: *mut CGFloat) -> CGFloat; } From 7e5640bb47ecb4e75a5d7a9d70192e67d9d41c10 Mon Sep 17 00:00:00 2001 From: Aloke Desai Date: Thu, 20 Jan 2022 11:47:11 -0500 Subject: [PATCH 3/5] from pairing with ian --- core-text/src/run.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/core-text/src/run.rs b/core-text/src/run.rs index 22e532723..151005fb2 100644 --- a/core-text/src/run.rs +++ b/core-text/src/run.rs @@ -91,7 +91,11 @@ impl CTRun { let mut descent = 0.0; let mut leading = 0.0; unsafe { - let width = CTRunGetTypographicBounds(self.as_concrete_TypeRef(), &mut ascent, &mut descent, &mut leading); + let range = CFRange { + location: 0, + length: 0, + }; + let width = CTRunGetTypographicBounds(self.as_concrete_TypeRef(), range, &mut ascent, &mut descent, &mut leading); TypographicBounds { width, ascent, descent, leading } } } @@ -163,5 +167,5 @@ extern { fn CTRunGetGlyphsPtr(run: CTRunRef) -> *const CGGlyph; fn CTRunGetGlyphs(run: CTRunRef, range: CFRange, buffer: *const CGGlyph); - fn CTRunGetTypographicBounds(line: CTRunRef, ascent: *mut CGFloat, descent: *mut CGFloat, leading: *mut CGFloat) -> CGFloat; + fn CTRunGetTypographicBounds(line: CTRunRef, range: CFRange, ascent: *mut CGFloat, descent: *mut CGFloat, leading: *mut CGFloat) -> CGFloat; } From ee04992b536b15c9557b27d78f7eb3caf7e7578b Mon Sep 17 00:00:00 2001 From: Aloke Desai Date: Fri, 28 Jan 2022 12:31:42 -0500 Subject: [PATCH 4/5] add comment --- .gitignore | 1 + core-text/src/run.rs | 67 +++++++++++++++++++++++++++++++------------- 2 files changed, 48 insertions(+), 20 deletions(-) diff --git a/.gitignore b/.gitignore index be576c475..0b1dc8775 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ Cargo.lock target/ +.idea diff --git a/core-text/src/run.rs b/core-text/src/run.rs index 151005fb2..c523a4aee 100644 --- a/core-text/src/run.rs +++ b/core-text/src/run.rs @@ -7,15 +7,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::borrow::Cow; -use std::os::raw::c_void; -use std::slice; -use core_foundation::base::{CFIndex, CFTypeID, TCFType, CFType, CFRange}; +use core_foundation::base::{CFIndex, CFRange, CFType, CFTypeID, TCFType}; use core_foundation::dictionary::{CFDictionary, CFDictionaryRef}; use core_foundation::string::CFString; +use core_graphics::base::CGFloat; use core_graphics::font::CGGlyph; use core_graphics::geometry::CGPoint; -use core_graphics::base::{CGFloat}; +use std::borrow::Cow; +use std::os::raw::c_void; +use std::slice; use crate::line::TypographicBounds; @@ -41,9 +41,7 @@ impl CTRun { } } pub fn glyph_count(&self) -> CFIndex { - unsafe { - CTRunGetGlyphCount(self.0) - } + unsafe { CTRunGetGlyphCount(self.0) } } pub fn glyphs(&self) -> Cow<[CGGlyph]> { @@ -91,12 +89,26 @@ impl CTRun { let mut descent = 0.0; let mut leading = 0.0; unsafe { - let range = CFRange { - location: 0, - length: 0, - }; - let width = CTRunGetTypographicBounds(self.as_concrete_TypeRef(), range, &mut ascent, &mut descent, &mut leading); - TypographicBounds { width, ascent, descent, leading } + // The portion of the run to calculate the typographic bounds for. By setting this to 0, + // CoreText will measure the bounds from start to end, see https://developer.apple.com/documentation/coretext/1510569-ctrungettypographicbounds?language=objc. + let range = CFRange { + location: 0, + length: 0, + }; + + let width = CTRunGetTypographicBounds( + self.as_concrete_TypeRef(), + range, + &mut ascent, + &mut descent, + &mut leading, + ); + TypographicBounds { + width, + ascent, + descent, + leading, + } } } @@ -124,21 +136,30 @@ impl CTRun { #[test] fn create_runs() { use core_foundation::attributed_string::CFMutableAttributedString; - use string_attributes::*; - use line::*; use font; + use line::*; + use string_attributes::*; let mut string = CFMutableAttributedString::new(); string.replace_str(&CFString::new("Food"), CFRange::init(0, 0)); let len = string.char_len(); unsafe { - string.set_attribute(CFRange::init(0, len), kCTFontAttributeName, &font::new_from_name("Helvetica", 16.).unwrap()); + string.set_attribute( + CFRange::init(0, len), + kCTFontAttributeName, + &font::new_from_name("Helvetica", 16.).unwrap(), + ); } let line = CTLine::new_with_attributed_string(string.as_concrete_TypeRef()); let runs = line.glyph_runs(); assert_eq!(runs.len(), 1); for run in runs.iter() { assert_eq!(run.glyph_count(), 4); - let font = run.attributes().unwrap().get(CFString::new("NSFont")).downcast::().unwrap(); + let font = run + .attributes() + .unwrap() + .get(CFString::new("NSFont")) + .downcast::() + .unwrap(); assert_eq!(font.pt_size(), 16.); let positions = run.positions(); @@ -156,7 +177,7 @@ fn create_runs() { } #[link(name = "CoreText", kind = "framework")] -extern { +extern "C" { fn CTRunGetTypeID() -> CFTypeID; fn CTRunGetAttributes(run: CTRunRef) -> CFDictionaryRef; fn CTRunGetGlyphCount(run: CTRunRef) -> CFIndex; @@ -167,5 +188,11 @@ extern { fn CTRunGetGlyphsPtr(run: CTRunRef) -> *const CGGlyph; fn CTRunGetGlyphs(run: CTRunRef, range: CFRange, buffer: *const CGGlyph); - fn CTRunGetTypographicBounds(line: CTRunRef, range: CFRange, ascent: *mut CGFloat, descent: *mut CGFloat, leading: *mut CGFloat) -> CGFloat; + fn CTRunGetTypographicBounds( + line: CTRunRef, + range: CFRange, + ascent: *mut CGFloat, + descent: *mut CGFloat, + leading: *mut CGFloat, + ) -> CGFloat; } From 895838e96b581fccdf98f88b514d8192e3b0820f Mon Sep 17 00:00:00 2001 From: alokedesai Date: Thu, 16 Jun 2022 17:22:53 -0400 Subject: [PATCH 5/5] fix ventura crash --- core-text/src/font_descriptor.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/core-text/src/font_descriptor.rs b/core-text/src/font_descriptor.rs index c70495c82..4dd70717a 100644 --- a/core-text/src/font_descriptor.rs +++ b/core-text/src/font_descriptor.rs @@ -20,6 +20,7 @@ use core_graphics::base::CGFloat; use std::os::raw::c_void; use std::path::PathBuf; +use core_foundation::boolean::CFBoolean; /* * CTFontTraits.h @@ -132,7 +133,19 @@ trait TraitAccessorPrivate { impl TraitAccessorPrivate for CTFontTraits { fn extract_number_for_key(&self, key: CFStringRef) -> CFNumber { let cftype = self.get(key); - cftype.downcast::().unwrap() + let number = cftype.downcast::(); + match number { + Some(number) => number, + None => { + // The value was not able to be converted to a CFNumber, this violates the Core + // Foundation's docs (see https://developer.apple.com/documentation/coretext/kctfontsymbolictrait) + // but can occur in practice with certain fonts in MacOS 13 (Ventura). When this + // does occur in Ventura, the value returned is always a CFBoolean, so we attempt to + // convert into a boolean and create a number from there. + let value_as_bool = bool::from(cftype.downcast::().expect("Should be able to convert value into CFBoolean")); + CFNumber::from(value_as_bool as i32) + } + } } }