core_text/
font_collection.rs1use crate::font_descriptor;
11use crate::font_descriptor::{CTFontDescriptor, CTFontDescriptorCreateMatchingFontDescriptors};
12use crate::font_manager::{
13 CTFontManagerCopyAvailableFontFamilyNames, CTFontManagerCopyAvailablePostScriptNames,
14};
15
16use core_foundation::array::{CFArray, CFArrayRef};
17use core_foundation::base::{CFTypeID, TCFType};
18use core_foundation::dictionary::{CFDictionary, CFDictionaryRef};
19use core_foundation::number::CFNumber;
20use core_foundation::set::CFSet;
21use core_foundation::string::{CFString, CFStringRef};
22use core_foundation::{declare_TCFType, impl_CFTypeDescription, impl_TCFType};
23
24#[repr(C)]
25pub struct __CTFontCollection(core::ffi::c_void);
26
27pub type CTFontCollectionRef = *const __CTFontCollection;
28
29declare_TCFType! {
30 CTFontCollection, CTFontCollectionRef
31}
32impl_TCFType!(
33 CTFontCollection,
34 CTFontCollectionRef,
35 CTFontCollectionGetTypeID
36);
37impl_CFTypeDescription!(CTFontCollection);
38
39impl CTFontCollection {
40 pub fn get_descriptors(&self) -> Option<CFArray<CTFontDescriptor>> {
41 unsafe {
44 let font_descriptors = CTFontCollectionCreateMatchingFontDescriptors(self.0);
45 if font_descriptors.is_null() {
46 None
48 } else {
49 Some(CFArray::wrap_under_get_rule(font_descriptors))
50 }
51 }
52 }
53}
54
55pub fn new_from_descriptors(descs: &CFArray<CTFontDescriptor>) -> CTFontCollection {
56 unsafe {
57 let key = CFString::wrap_under_get_rule(kCTFontCollectionRemoveDuplicatesOption);
58 let value = CFNumber::from(1i64);
59 let options = CFDictionary::from_CFType_pairs(&[(key.as_CFType(), value.as_CFType())]);
60 let font_collection_ref = CTFontCollectionCreateWithFontDescriptors(
61 descs.as_concrete_TypeRef(),
62 options.as_concrete_TypeRef(),
63 );
64 CTFontCollection::wrap_under_create_rule(font_collection_ref)
65 }
66}
67
68pub fn create_for_all_families() -> CTFontCollection {
69 unsafe {
70 let key = CFString::wrap_under_get_rule(kCTFontCollectionRemoveDuplicatesOption);
71 let value = CFNumber::from(1i64);
72 let options = CFDictionary::from_CFType_pairs(&[(key.as_CFType(), value.as_CFType())]);
73 let font_collection_ref =
74 CTFontCollectionCreateFromAvailableFonts(options.as_concrete_TypeRef());
75 CTFontCollection::wrap_under_create_rule(font_collection_ref)
76 }
77}
78
79pub fn create_for_family(family: &str) -> Option<CTFontCollection> {
80 use crate::font_descriptor::kCTFontFamilyNameAttribute;
81
82 unsafe {
83 let family_attr = CFString::wrap_under_get_rule(kCTFontFamilyNameAttribute);
84 let family_name: CFString = family.parse().unwrap();
85 let specified_attrs =
86 CFDictionary::from_CFType_pairs(&[(family_attr.clone(), family_name.as_CFType())]);
87
88 let wildcard_desc: CTFontDescriptor =
89 font_descriptor::new_from_attributes(&specified_attrs);
90 let mandatory_attrs = CFSet::from_slice(&[family_attr.as_CFType()]);
91 let matched_descs = CTFontDescriptorCreateMatchingFontDescriptors(
92 wildcard_desc.as_concrete_TypeRef(),
93 mandatory_attrs.as_concrete_TypeRef(),
94 );
95 if matched_descs.is_null() {
96 return None;
97 }
98 let matched_descs = CFArray::wrap_under_create_rule(matched_descs);
99 Some(new_from_descriptors(&matched_descs))
102 }
103}
104
105pub fn get_family_names() -> CFArray<CFString> {
106 unsafe { CFArray::wrap_under_create_rule(CTFontManagerCopyAvailableFontFamilyNames()) }
107}
108
109pub fn get_postscript_names() -> CFArray<CFString> {
110 unsafe { CFArray::wrap_under_create_rule(CTFontManagerCopyAvailablePostScriptNames()) }
111}
112
113extern "C" {
114 static kCTFontCollectionRemoveDuplicatesOption: CFStringRef;
119
120 fn CTFontCollectionCreateFromAvailableFonts(options: CFDictionaryRef) -> CTFontCollectionRef;
124 fn CTFontCollectionCreateMatchingFontDescriptors(collection: CTFontCollectionRef)
128 -> CFArrayRef;
129 fn CTFontCollectionCreateWithFontDescriptors(
130 descriptors: CFArrayRef,
131 options: CFDictionaryRef,
132 ) -> CTFontCollectionRef;
133 fn CTFontCollectionGetTypeID() -> CFTypeID;
135}