Skip to content

Commit a120e4a

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

File tree

2 files changed

+66
-4
lines changed

2 files changed

+66
-4
lines changed

core-text/src/font.rs

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use font_descriptor::{CTFontSymbolicTraits, CTFontTraits, SymbolicTraitAccessors
1515
use font_manager::create_font_descriptor;
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;
@@ -32,6 +32,8 @@ use libc::{self, size_t};
3232
use std::os::raw::c_void;
3333
use std::ptr;
3434

35+
use crate::font_manager::create_font_descriptors;
36+
3537
type CGContextRef = *mut <CGContext as ForeignType>::CType;
3638
type CGFontRef = *mut <CGFont as ForeignType>::CType;
3739
type CGPathRef = *mut <CGPath as ForeignType>::CType;
@@ -127,7 +129,21 @@ pub fn new_from_descriptor(desc: &CTFontDescriptor, pt_size: f64) -> CTFont {
127129

128130
pub fn new_from_buffer(buffer: &[u8]) -> Result<CTFont, ()> {
129131
let ct_font_descriptor = create_font_descriptor(buffer)?;
130-
Ok(new_from_descriptor(&ct_font_descriptor, 16.0))
132+
Ok(new_from_name(&ct_font_descriptor.postscript_name(), 16.0)?)
133+
}
134+
135+
pub fn new_fonts_from_buffer(buffer: &[u8]) -> Result<Vec<CTFont>, ()> {
136+
let ct_font_descriptors = create_font_descriptors(buffer)?;
137+
138+
let mut ct_fonts = Vec::new();
139+
unsafe {
140+
for descriptor_ptr in ct_font_descriptors.get_all_values().into_iter() {
141+
let descriptor = CTFontDescriptor::wrap_under_get_rule(CTFontDescriptorRef::from_void_ptr(descriptor_ptr));
142+
ct_fonts.push(new_from_name(&descriptor.font_name(), 16.0)?);
143+
}
144+
}
145+
146+
Ok(ct_fonts)
131147
}
132148

133149
pub fn new_from_name(name: &str, pt_size: f64) -> Result<CTFont, ()> {
@@ -646,6 +662,40 @@ extern {
646662
fn CTFontGetTypeID() -> CFTypeID;
647663
}
648664

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

743793
assert_eq!(small.postscript_name(), cgfont.postscript_name());
744-
}
794+
}

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)