Skip to content

Commit 4ace775

Browse files
committed
fix: new_from_descriptor lose font variations, such as font-weight
use new_from_name instead
1 parent 025dcb3 commit 4ace775

File tree

2 files changed

+71
-5
lines changed

2 files changed

+71
-5
lines changed

core-text/src/font.rs

Lines changed: 58 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@
1212
use font_descriptor;
1313
use font_descriptor::{CTFontDescriptor, CTFontDescriptorRef, CTFontOrientation};
1414
use font_descriptor::{CTFontSymbolicTraits, CTFontTraits, SymbolicTraitAccessors, TraitAccessors};
15-
use font_manager::create_font_descriptor;
15+
use font_manager::{create_font_descriptor, create_font_descriptors, create_font_descriptor_with_data};
1616

1717
use core_foundation::array::{CFArray, CFArrayRef};
18-
use core_foundation::base::{CFIndex, CFOptionFlags, CFType, CFTypeID, CFTypeRef, TCFType};
18+
use core_foundation::base::{CFIndex, CFOptionFlags, CFType, CFTypeID, CFTypeRef, TCFType, TCFTypeRef};
1919
use core_foundation::data::{CFData, CFDataRef};
2020
use core_foundation::dictionary::{CFDictionary, CFDictionaryRef};
2121
use core_foundation::number::CFNumber;
@@ -31,6 +31,7 @@ use foreign_types::ForeignType;
3131
use libc::{self, size_t};
3232
use std::os::raw::c_void;
3333
use std::ptr;
34+
use std::sync::Arc;
3435

3536
type CGContextRef = *mut <CGContext as ForeignType>::CType;
3637
type CGFontRef = *mut <CGFont as ForeignType>::CType;
@@ -127,7 +128,26 @@ pub fn new_from_descriptor(desc: &CTFontDescriptor, pt_size: f64) -> CTFont {
127128

128129
pub fn new_from_buffer(buffer: &[u8]) -> Result<CTFont, ()> {
129130
let ct_font_descriptor = create_font_descriptor(buffer)?;
130-
Ok(new_from_descriptor(&ct_font_descriptor, 16.0))
131+
Ok(new_from_name(&ct_font_descriptor.font_name(), 16.0)?)
132+
}
133+
134+
pub fn new_from_arc_buffer<T: AsRef<[u8]> + Sync + Send>(buffer: Arc<T>) -> Result<CTFont, ()> {
135+
let ct_font_descriptor = create_font_descriptor_with_data(CFData::from_arc(buffer))?;
136+
Ok(new_from_name(&ct_font_descriptor.font_name(), 16.0)?)
137+
}
138+
139+
pub fn new_fonts_from_buffer(buffer: &[u8]) -> Result<Vec<CTFont>, ()> {
140+
let ct_font_descriptors = create_font_descriptors(buffer)?;
141+
142+
let mut ct_fonts = Vec::new();
143+
unsafe {
144+
for descriptor_ptr in ct_font_descriptors.get_all_values().into_iter() {
145+
let descriptor = CTFontDescriptor::wrap_under_get_rule(CTFontDescriptorRef::from_void_ptr(descriptor_ptr));
146+
ct_fonts.push(new_from_name(&descriptor.font_name(), 16.0)?);
147+
}
148+
}
149+
150+
Ok(ct_fonts)
131151
}
132152

133153
pub fn new_from_name(name: &str, pt_size: f64) -> Result<CTFont, ()> {
@@ -646,6 +666,40 @@ extern {
646666
fn CTFontGetTypeID() -> CFTypeID;
647667
}
648668

669+
#[test]
670+
fn test_font_descriptor_and_variation () {
671+
use std::io::Read;
672+
let mut f = std::fs::File::open("/System/Library/Fonts/Helvetica.ttc").unwrap();
673+
let mut font_data = Vec::new();
674+
f.read_to_end(&mut font_data).unwrap();
675+
let descriptors = create_font_descriptors(&font_data).unwrap();
676+
677+
unsafe {
678+
for descriptor_ptr in descriptors.get_all_values().into_iter() {
679+
let descriptor = CTFontDescriptor::wrap_under_get_rule(CTFontDescriptorRef::from_void_ptr(descriptor_ptr));
680+
681+
// when create ttc/otc fonts from descriptor, all font variations are the same
682+
let font = new_from_descriptor(&descriptor, 12.);
683+
println!("font name= {:?}, desc.name= {:?}", font.face_name(), descriptor.font_name());
684+
685+
let sym = font.symbolic_traits();
686+
assert_eq!(false, sym.is_italic());
687+
assert_eq!(false, sym.is_bold());
688+
assert_eq!(false, sym.is_expanded());
689+
assert_eq!(false, sym.is_condensed());
690+
assert_eq!(false, sym.is_monospace());
691+
692+
let all_traits = font.all_traits();
693+
assert_eq!(0., all_traits.normalized_weight());
694+
assert_eq!(0., all_traits.normalized_width());
695+
696+
// we have to create them from font name
697+
let font = new_from_name(&descriptor.font_name(), 12.).unwrap();
698+
debug_font_traits(&font);
699+
}
700+
}
701+
}
702+
649703
#[test]
650704
fn copy_font() {
651705
use std::io::Read;
@@ -741,4 +795,4 @@ fn copy_system_font() {
741795
assert!(matching.attributes().find(CFString::from_static_string("NSFontSizeAttribute")).is_none());
742796

743797
assert_eq!(small.postscript_name(), cgfont.postscript_name());
744-
}
798+
}

core-text/src/font_manager.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use core_foundation::base::TCFType;
1212
use core_foundation::string::CFString;
1313
use core_foundation::url::CFURLRef;
1414
use core_foundation::data::{CFDataRef, CFData};
15-
use crate::font_descriptor::{CTFontDescriptorRef, CTFontDescriptor};
15+
use crate::font_descriptor::{CTFontDescriptor, CTFontDescriptorRef};
1616

1717
pub fn copy_available_font_family_names() -> CFArray<CFString> {
1818
unsafe {
@@ -41,6 +41,17 @@ pub fn create_font_descriptor_with_data(data: CFData) -> Result<CTFontDescriptor
4141
}
4242
}
4343

44+
pub fn create_font_descriptors(buffer: &[u8]) -> Result<CFArray<CTFontDescriptor>, ()> {
45+
let cf_data = CFData::from_buffer(buffer);
46+
unsafe {
47+
let ct_font_descriptors_ref = CTFontManagerCreateFontDescriptorsFromData(cf_data.as_concrete_TypeRef());
48+
if ct_font_descriptors_ref.is_null() {
49+
return Err(());
50+
}
51+
Ok(CFArray::wrap_under_create_rule(ct_font_descriptors_ref))
52+
}
53+
}
54+
4455
extern {
4556
/*
4657
* CTFontManager.h
@@ -55,6 +66,7 @@ extern {
5566
pub fn CTFontManagerCopyAvailablePostScriptNames() -> CFArrayRef;
5667
pub fn CTFontManagerCreateFontDescriptorsFromURL(fileURL: CFURLRef) -> CFArrayRef;
5768
pub fn CTFontManagerCreateFontDescriptorFromData(data: CFDataRef) -> CTFontDescriptorRef;
69+
pub fn CTFontManagerCreateFontDescriptorsFromData(data: CFDataRef) -> CFArrayRef;
5870
//pub fn CTFontManagerCreateFontRequestRunLoopSource
5971
//pub fn CTFontManagerEnableFontDescriptors
6072
//pub fn CTFontManagerGetAutoActivationSetting

0 commit comments

Comments
 (0)