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 {
42 let font_descriptors = CTFontCollectionCreateMatchingFontDescriptors(self.0);
43 if font_descriptors.is_null() {
44 None
46 } else {
47 Some(CFArray::wrap_under_create_rule(font_descriptors))
48 }
49 }
50 }
51}
52
53pub fn new_from_descriptors(descs: &CFArray<CTFontDescriptor>) -> CTFontCollection {
54 unsafe {
55 let key = CFString::wrap_under_get_rule(kCTFontCollectionRemoveDuplicatesOption);
56 let value = CFNumber::from(1i64);
57 let options = CFDictionary::from_CFType_pairs(&[(key.as_CFType(), value.as_CFType())]);
58 let font_collection_ref = CTFontCollectionCreateWithFontDescriptors(
59 descs.as_concrete_TypeRef(),
60 options.as_concrete_TypeRef(),
61 );
62 CTFontCollection::wrap_under_create_rule(font_collection_ref)
63 }
64}
65
66pub fn create_for_all_families() -> CTFontCollection {
67 unsafe {
68 let key = CFString::wrap_under_get_rule(kCTFontCollectionRemoveDuplicatesOption);
69 let value = CFNumber::from(1i64);
70 let options = CFDictionary::from_CFType_pairs(&[(key.as_CFType(), value.as_CFType())]);
71 let font_collection_ref =
72 CTFontCollectionCreateFromAvailableFonts(options.as_concrete_TypeRef());
73 CTFontCollection::wrap_under_create_rule(font_collection_ref)
74 }
75}
76
77pub fn create_for_family(family: &str) -> Option<CTFontCollection> {
78 use crate::font_descriptor::kCTFontFamilyNameAttribute;
79
80 unsafe {
81 let family_attr = CFString::wrap_under_get_rule(kCTFontFamilyNameAttribute);
82 let family_name: CFString = family.parse().unwrap();
83 let specified_attrs =
84 CFDictionary::from_CFType_pairs(&[(family_attr.clone(), family_name.as_CFType())]);
85
86 let wildcard_desc: CTFontDescriptor =
87 font_descriptor::new_from_attributes(&specified_attrs);
88 let mandatory_attrs = CFSet::from_slice(&[family_attr.as_CFType()]);
89 let matched_descs = CTFontDescriptorCreateMatchingFontDescriptors(
90 wildcard_desc.as_concrete_TypeRef(),
91 mandatory_attrs.as_concrete_TypeRef(),
92 );
93 if matched_descs.is_null() {
94 return None;
95 }
96 let matched_descs = CFArray::wrap_under_create_rule(matched_descs);
97 Some(new_from_descriptors(&matched_descs))
100 }
101}
102
103pub fn get_family_names() -> CFArray<CFString> {
104 unsafe { CFArray::wrap_under_create_rule(CTFontManagerCopyAvailableFontFamilyNames()) }
105}
106
107pub fn get_postscript_names() -> CFArray<CFString> {
108 unsafe { CFArray::wrap_under_create_rule(CTFontManagerCopyAvailablePostScriptNames()) }
109}
110
111extern "C" {
112 static kCTFontCollectionRemoveDuplicatesOption: CFStringRef;
117
118 fn CTFontCollectionCreateFromAvailableFonts(options: CFDictionaryRef) -> CTFontCollectionRef;
122 fn CTFontCollectionCreateMatchingFontDescriptors(collection: CTFontCollectionRef)
126 -> CFArrayRef;
127 fn CTFontCollectionCreateWithFontDescriptors(
128 descriptors: CFArrayRef,
129 options: CFDictionaryRef,
130 ) -> CTFontCollectionRef;
131 fn CTFontCollectionGetTypeID() -> CFTypeID;
133}