From 4ace7757e303b08d2126eddcf2f97a1d434843fd Mon Sep 17 00:00:00 2001 From: "wangkai.kaiwk" Date: Tue, 15 Dec 2020 11:27:54 +0800 Subject: [PATCH] fix: new_from_descriptor lose font variations, such as font-weight use new_from_name instead --- core-text/src/font.rs | 62 ++++++++++++++++++++++++++++++++--- core-text/src/font_manager.rs | 14 +++++++- 2 files changed, 71 insertions(+), 5 deletions(-) diff --git a/core-text/src/font.rs b/core-text/src/font.rs index ebe6d580f..33c657146 100644 --- a/core-text/src/font.rs +++ b/core-text/src/font.rs @@ -12,10 +12,10 @@ use font_descriptor; use font_descriptor::{CTFontDescriptor, CTFontDescriptorRef, CTFontOrientation}; use font_descriptor::{CTFontSymbolicTraits, CTFontTraits, SymbolicTraitAccessors, TraitAccessors}; -use font_manager::create_font_descriptor; +use font_manager::{create_font_descriptor, create_font_descriptors, create_font_descriptor_with_data}; use core_foundation::array::{CFArray, CFArrayRef}; -use core_foundation::base::{CFIndex, CFOptionFlags, CFType, CFTypeID, CFTypeRef, TCFType}; +use core_foundation::base::{CFIndex, CFOptionFlags, CFType, CFTypeID, CFTypeRef, TCFType, TCFTypeRef}; use core_foundation::data::{CFData, CFDataRef}; use core_foundation::dictionary::{CFDictionary, CFDictionaryRef}; use core_foundation::number::CFNumber; @@ -31,6 +31,7 @@ use foreign_types::ForeignType; use libc::{self, size_t}; use std::os::raw::c_void; use std::ptr; +use std::sync::Arc; type CGContextRef = *mut ::CType; type CGFontRef = *mut ::CType; @@ -127,7 +128,26 @@ pub fn new_from_descriptor(desc: &CTFontDescriptor, pt_size: f64) -> CTFont { pub fn new_from_buffer(buffer: &[u8]) -> Result { let ct_font_descriptor = create_font_descriptor(buffer)?; - Ok(new_from_descriptor(&ct_font_descriptor, 16.0)) + Ok(new_from_name(&ct_font_descriptor.font_name(), 16.0)?) +} + +pub fn new_from_arc_buffer + Sync + Send>(buffer: Arc) -> Result { + let ct_font_descriptor = create_font_descriptor_with_data(CFData::from_arc(buffer))?; + Ok(new_from_name(&ct_font_descriptor.font_name(), 16.0)?) +} + +pub fn new_fonts_from_buffer(buffer: &[u8]) -> Result, ()> { + let ct_font_descriptors = create_font_descriptors(buffer)?; + + let mut ct_fonts = Vec::new(); + unsafe { + for descriptor_ptr in ct_font_descriptors.get_all_values().into_iter() { + let descriptor = CTFontDescriptor::wrap_under_get_rule(CTFontDescriptorRef::from_void_ptr(descriptor_ptr)); + ct_fonts.push(new_from_name(&descriptor.font_name(), 16.0)?); + } + } + + Ok(ct_fonts) } pub fn new_from_name(name: &str, pt_size: f64) -> Result { @@ -646,6 +666,40 @@ extern { fn CTFontGetTypeID() -> CFTypeID; } +#[test] +fn test_font_descriptor_and_variation () { + use std::io::Read; + let mut f = std::fs::File::open("/System/Library/Fonts/Helvetica.ttc").unwrap(); + let mut font_data = Vec::new(); + f.read_to_end(&mut font_data).unwrap(); + let descriptors = create_font_descriptors(&font_data).unwrap(); + + unsafe { + for descriptor_ptr in descriptors.get_all_values().into_iter() { + let descriptor = CTFontDescriptor::wrap_under_get_rule(CTFontDescriptorRef::from_void_ptr(descriptor_ptr)); + + // when create ttc/otc fonts from descriptor, all font variations are the same + let font = new_from_descriptor(&descriptor, 12.); + println!("font name= {:?}, desc.name= {:?}", font.face_name(), descriptor.font_name()); + + let sym = font.symbolic_traits(); + assert_eq!(false, sym.is_italic()); + assert_eq!(false, sym.is_bold()); + assert_eq!(false, sym.is_expanded()); + assert_eq!(false, sym.is_condensed()); + assert_eq!(false, sym.is_monospace()); + + let all_traits = font.all_traits(); + assert_eq!(0., all_traits.normalized_weight()); + assert_eq!(0., all_traits.normalized_width()); + + // we have to create them from font name + let font = new_from_name(&descriptor.font_name(), 12.).unwrap(); + debug_font_traits(&font); + } + } +} + #[test] fn copy_font() { use std::io::Read; @@ -741,4 +795,4 @@ fn copy_system_font() { assert!(matching.attributes().find(CFString::from_static_string("NSFontSizeAttribute")).is_none()); assert_eq!(small.postscript_name(), cgfont.postscript_name()); -} \ No newline at end of file +} diff --git a/core-text/src/font_manager.rs b/core-text/src/font_manager.rs index cdf65ee3b..d2df70ed7 100644 --- a/core-text/src/font_manager.rs +++ b/core-text/src/font_manager.rs @@ -12,7 +12,7 @@ use core_foundation::base::TCFType; use core_foundation::string::CFString; use core_foundation::url::CFURLRef; use core_foundation::data::{CFDataRef, CFData}; -use crate::font_descriptor::{CTFontDescriptorRef, CTFontDescriptor}; +use crate::font_descriptor::{CTFontDescriptor, CTFontDescriptorRef}; pub fn copy_available_font_family_names() -> CFArray { unsafe { @@ -41,6 +41,17 @@ pub fn create_font_descriptor_with_data(data: CFData) -> Result Result, ()> { + let cf_data = CFData::from_buffer(buffer); + unsafe { + let ct_font_descriptors_ref = CTFontManagerCreateFontDescriptorsFromData(cf_data.as_concrete_TypeRef()); + if ct_font_descriptors_ref.is_null() { + return Err(()); + } + Ok(CFArray::wrap_under_create_rule(ct_font_descriptors_ref)) + } +} + extern { /* * CTFontManager.h @@ -55,6 +66,7 @@ extern { pub fn CTFontManagerCopyAvailablePostScriptNames() -> CFArrayRef; pub fn CTFontManagerCreateFontDescriptorsFromURL(fileURL: CFURLRef) -> CFArrayRef; pub fn CTFontManagerCreateFontDescriptorFromData(data: CFDataRef) -> CTFontDescriptorRef; + pub fn CTFontManagerCreateFontDescriptorsFromData(data: CFDataRef) -> CFArrayRef; //pub fn CTFontManagerCreateFontRequestRunLoopSource //pub fn CTFontManagerEnableFontDescriptors //pub fn CTFontManagerGetAutoActivationSetting