core_text/
font_descriptor.rs1#![allow(non_upper_case_globals)]
11
12use core_foundation::array::CFArrayRef;
13use core_foundation::base::{CFType, CFTypeID, CFTypeRef, TCFType};
14use core_foundation::dictionary::{CFDictionary, CFDictionaryRef};
15use core_foundation::number::{CFNumber, CFNumberRef};
16use core_foundation::set::CFSetRef;
17use core_foundation::string::{CFString, CFStringRef};
18use core_foundation::url::{CFURLRef, CFURL};
19use core_foundation::{declare_TCFType, impl_CFTypeDescription, impl_TCFType};
20use core_graphics::base::CGFloat;
21
22use core_foundation::boolean::CFBoolean;
23use std::path::PathBuf;
24
25pub type CTFontFormat = u32;
30pub const kCTFontFormatUnrecognized: CTFontFormat = 0;
31pub const kCTFontFormatOpenTypePostScript: CTFontFormat = 1;
32pub const kCTFontFormatOpenTypeTrueType: CTFontFormat = 2;
33pub const kCTFontFormatTrueType: CTFontFormat = 3;
34pub const kCTFontFormatPostScript: CTFontFormat = 4;
35pub const kCTFontFormatBitmap: CTFontFormat = 5;
36
37pub const kCTFontClassMaskShift: u32 = 28;
38
39pub type CTFontSymbolicTraits = u32;
40pub const kCTFontItalicTrait: CTFontSymbolicTraits = 1 << 0;
41pub const kCTFontBoldTrait: CTFontSymbolicTraits = 1 << 1;
42pub const kCTFontExpandedTrait: CTFontSymbolicTraits = 1 << 5;
43pub const kCTFontCondensedTrait: CTFontSymbolicTraits = 1 << 6;
44pub const kCTFontMonoSpaceTrait: CTFontSymbolicTraits = 1 << 10;
45pub const kCTFontVerticalTrait: CTFontSymbolicTraits = 1 << 11;
46pub const kCTFontUIOptimizedTrait: CTFontSymbolicTraits = 1 << 12;
47pub const kCTFontColorGlyphsTrait: CTFontSymbolicTraits = 1 << 13;
48pub const kCTFontClassMaskTrait: CTFontSymbolicTraits = 15 << kCTFontClassMaskShift;
49
50pub trait SymbolicTraitAccessors {
51 fn is_italic(&self) -> bool;
52 fn is_bold(&self) -> bool;
53 fn is_expanded(&self) -> bool;
54 fn is_condensed(&self) -> bool;
55 fn is_monospace(&self) -> bool;
56 fn is_vertical(&self) -> bool;
57}
58
59impl SymbolicTraitAccessors for CTFontSymbolicTraits {
60 fn is_italic(&self) -> bool {
61 (*self & kCTFontItalicTrait) != 0
62 }
63 fn is_bold(&self) -> bool {
64 (*self & kCTFontBoldTrait) != 0
65 }
66 fn is_expanded(&self) -> bool {
67 (*self & kCTFontExpandedTrait) != 0
68 }
69 fn is_condensed(&self) -> bool {
70 (*self & kCTFontCondensedTrait) != 0
71 }
72 fn is_monospace(&self) -> bool {
73 (*self & kCTFontMonoSpaceTrait) != 0
74 }
75 fn is_vertical(&self) -> bool {
76 (*self & kCTFontVerticalTrait) != 0
77 }
78}
79
80pub type CTFontStylisticClass = u32;
81pub const kCTFontUnknownClass: CTFontStylisticClass = 0 << kCTFontClassMaskShift;
82pub const kCTFontOldStyleSerifsClass: CTFontStylisticClass = 1 << kCTFontClassMaskShift;
83pub const kCTFontTransitionalSerifsClass: CTFontStylisticClass = 2 << kCTFontClassMaskShift;
84pub const kCTFontModernSerifsClass: CTFontStylisticClass = 3 << kCTFontClassMaskShift;
85pub const kCTFontClarendonSerifsClass: CTFontStylisticClass = 4 << kCTFontClassMaskShift;
86pub const kCTFontSlabSerifsClass: CTFontStylisticClass = 5 << kCTFontClassMaskShift;
87pub const kCTFontFreeformSerifsClass: CTFontStylisticClass = 7 << kCTFontClassMaskShift;
88pub const kCTFontSansSerifClass: CTFontStylisticClass = 8 << kCTFontClassMaskShift;
89pub const kCTFontOrnamentalsClass: CTFontStylisticClass = 9 << kCTFontClassMaskShift;
90pub const kCTFontScriptsClass: CTFontStylisticClass = 10 << kCTFontClassMaskShift;
91pub const kCTFontSymbolicClass: CTFontStylisticClass = 12 << kCTFontClassMaskShift;
92
93pub trait StylisticClassAccessors {
94 fn is_serif(&self) -> bool;
95 fn is_sans_serif(&self) -> bool;
96 fn is_script(&self) -> bool;
97 fn is_fantasy(&self) -> bool;
98 fn is_symbols(&self) -> bool;
99}
100
101impl StylisticClassAccessors for CTFontStylisticClass {
102 fn is_serif(&self) -> bool {
103 let any_serif_class = kCTFontOldStyleSerifsClass
104 | kCTFontTransitionalSerifsClass
105 | kCTFontModernSerifsClass
106 | kCTFontClarendonSerifsClass
107 | kCTFontSlabSerifsClass
108 | kCTFontFreeformSerifsClass;
109
110 (*self & any_serif_class) != 0
111 }
112
113 fn is_sans_serif(&self) -> bool {
114 (*self & kCTFontSansSerifClass) != 0
115 }
116
117 fn is_script(&self) -> bool {
118 (*self & kCTFontScriptsClass) != 0
119 }
120
121 fn is_fantasy(&self) -> bool {
122 (*self & kCTFontOrnamentalsClass) != 0
123 }
124
125 fn is_symbols(&self) -> bool {
126 (*self & kCTFontSymbolicClass) != 0
127 }
128}
129
130pub type CTFontAttributes = CFDictionary;
131
132pub type CTFontTraits = CFDictionary<CFString, CFType>;
133
134pub trait TraitAccessors {
135 fn symbolic_traits(&self) -> CTFontSymbolicTraits;
136 fn normalized_weight(&self) -> f64;
137 fn normalized_width(&self) -> f64;
138 fn normalized_slant(&self) -> f64;
139}
140
141trait TraitAccessorPrivate {
142 fn extract_number_for_key(&self, key: CFStringRef) -> CFNumber;
143}
144
145impl TraitAccessorPrivate for CTFontTraits {
146 fn extract_number_for_key(&self, key: CFStringRef) -> CFNumber {
147 let cftype = self.get(key);
148 let number = cftype.downcast::<CFNumber>();
149 match number {
150 Some(number) => number,
151 None => {
152 let value_as_bool = bool::from(
158 cftype
159 .downcast::<CFBoolean>()
160 .expect("Should be able to convert value into CFBoolean"),
161 );
162 CFNumber::from(value_as_bool as i32)
163 }
164 }
165 }
166}
167
168impl TraitAccessors for CTFontTraits {
169 fn symbolic_traits(&self) -> CTFontSymbolicTraits {
170 unsafe {
171 let number = self.extract_number_for_key(kCTFontSymbolicTrait);
172 number.to_i64().unwrap() as u32
173 }
174 }
175
176 fn normalized_weight(&self) -> f64 {
177 unsafe {
178 let number = self.extract_number_for_key(kCTFontWeightTrait);
179 number.to_f64().unwrap()
180 }
181 }
182
183 fn normalized_width(&self) -> f64 {
184 unsafe {
185 let number = self.extract_number_for_key(kCTFontWidthTrait);
186 number.to_f64().unwrap()
187 }
188 }
189
190 fn normalized_slant(&self) -> f64 {
191 unsafe {
192 let number = self.extract_number_for_key(kCTFontSlantTrait);
193 number.to_f64().unwrap()
194 }
195 }
196}
197
198pub type CTFontOrientation = u32;
202pub const kCTFontDefaultOrientation: CTFontOrientation = 0; pub const kCTFontOrientationDefault: CTFontOrientation = 0; pub const kCTFontHorizontalOrientation: CTFontOrientation = 1; pub const kCTFontOrientationHorizontal: CTFontOrientation = 1; pub const kCTFontVerticalOrientation: CTFontOrientation = 2; pub const kCTFontOrientationVertical: CTFontOrientation = 2; pub type CTFontPriority = u32;
210pub const kCTFontPrioritySystem: CTFontPriority = 10000;
211pub const kCTFontPriorityNetwork: CTFontPriority = 20000;
212pub const kCTFontPriorityComputer: CTFontPriority = 30000;
213pub const kCTFontPriorityUser: CTFontPriority = 40000;
214pub const kCTFontPriorityDynamic: CTFontPriority = 50000;
215pub const kCTFontPriorityProcess: CTFontPriority = 60000;
216
217#[repr(C)]
218pub struct __CTFontDescriptor(core::ffi::c_void);
219
220pub type CTFontDescriptorRef = *const __CTFontDescriptor;
221
222declare_TCFType! {
223 CTFontDescriptor, CTFontDescriptorRef
224}
225impl_TCFType!(
226 CTFontDescriptor,
227 CTFontDescriptorRef,
228 CTFontDescriptorGetTypeID
229);
230impl_CFTypeDescription!(CTFontDescriptor);
231
232unsafe impl Send for CTFontDescriptor {}
235unsafe impl Sync for CTFontDescriptor {}
236
237impl CTFontDescriptor {
238 fn get_string_attribute(&self, attribute: CFStringRef) -> Option<String> {
239 unsafe {
240 let value = CTFontDescriptorCopyAttribute(self.0, attribute);
241 if value.is_null() {
242 return None;
243 }
244
245 let value = CFType::wrap_under_create_rule(value);
246 assert!(value.instance_of::<CFString>());
247 let s = CFString::wrap_under_get_rule(value.as_CFTypeRef() as CFStringRef);
248 Some(s.to_string())
249 }
250 }
251}
252
253impl CTFontDescriptor {
254 pub fn family_name(&self) -> String {
255 unsafe {
256 let value = self.get_string_attribute(kCTFontFamilyNameAttribute);
257 value.expect("A font must have a non-null family name.")
258 }
259 }
260
261 pub fn font_name(&self) -> String {
262 unsafe {
263 let value = self.get_string_attribute(kCTFontNameAttribute);
264 value.expect("A font must have a non-null name.")
265 }
266 }
267
268 pub fn style_name(&self) -> String {
269 unsafe {
270 let value = self.get_string_attribute(kCTFontStyleNameAttribute);
271 value.expect("A font must have a non-null style name.")
272 }
273 }
274
275 pub fn display_name(&self) -> String {
276 unsafe {
277 let value = self.get_string_attribute(kCTFontDisplayNameAttribute);
278 value.expect("A font must have a non-null display name.")
279 }
280 }
281
282 pub fn font_format(&self) -> Option<CTFontFormat> {
283 unsafe {
284 let value = CTFontDescriptorCopyAttribute(self.0, kCTFontFormatAttribute);
285 if value.is_null() {
286 return None;
287 }
288
289 let value = CFType::wrap_under_create_rule(value);
290 assert!(value.instance_of::<CFNumber>());
291 let format = CFNumber::wrap_under_get_rule(value.as_CFTypeRef() as CFNumberRef);
292 format.to_i32().map(|x| x as CTFontFormat)
293 }
294 }
295
296 pub fn font_path(&self) -> Option<PathBuf> {
297 unsafe {
298 let value = CTFontDescriptorCopyAttribute(self.0, kCTFontURLAttribute);
299 if value.is_null() {
300 return None;
301 }
302
303 let value = CFType::wrap_under_create_rule(value);
304 assert!(value.instance_of::<CFURL>());
305 let url = CFURL::wrap_under_get_rule(value.as_CFTypeRef() as CFURLRef);
306 url.to_path()
307 }
308 }
309
310 pub fn traits(&self) -> CTFontTraits {
311 unsafe {
312 let value = CTFontDescriptorCopyAttribute(self.0, kCTFontTraitsAttribute);
313 assert!(!value.is_null());
314 let value = CFType::wrap_under_create_rule(value);
315 assert!(value.instance_of::<CFDictionary>());
316 CFDictionary::wrap_under_get_rule(value.as_CFTypeRef() as CFDictionaryRef)
317 }
318 }
319
320 pub fn create_copy_with_attributes(&self, attr: CFDictionary) -> Result<CTFontDescriptor, ()> {
321 unsafe {
322 let desc = CTFontDescriptorCreateCopyWithAttributes(
323 self.as_concrete_TypeRef(),
324 attr.as_concrete_TypeRef(),
325 );
326 if desc.is_null() {
327 return Err(());
328 }
329 Ok(CTFontDescriptor::wrap_under_create_rule(desc))
330 }
331 }
332
333 pub fn attributes(&self) -> CFDictionary<CFString, CFType> {
334 unsafe {
335 let attrs = CTFontDescriptorCopyAttributes(self.as_concrete_TypeRef());
336 CFDictionary::wrap_under_create_rule(attrs)
337 }
338 }
339}
340
341pub fn new_from_attributes(attributes: &CFDictionary<CFString, CFType>) -> CTFontDescriptor {
342 unsafe {
343 let result: CTFontDescriptorRef =
344 CTFontDescriptorCreateWithAttributes(attributes.as_concrete_TypeRef());
345 CTFontDescriptor::wrap_under_create_rule(result)
346 }
347}
348
349pub fn new_from_variations(variations: &CFDictionary<CFString, CFNumber>) -> CTFontDescriptor {
350 unsafe {
351 let var_key = CFString::wrap_under_get_rule(kCTFontVariationAttribute);
352 let var_val = CFType::wrap_under_get_rule(variations.as_CFTypeRef());
353 let attributes = CFDictionary::from_CFType_pairs(&[(var_key, var_val)]);
354 new_from_attributes(&attributes)
355 }
356}
357
358pub fn new_from_postscript_name(name: &CFString) -> CTFontDescriptor {
359 unsafe {
360 let result: CTFontDescriptorRef =
361 CTFontDescriptorCreateWithNameAndSize(name.as_concrete_TypeRef(), 0.0);
362 CTFontDescriptor::wrap_under_create_rule(result)
363 }
364}
365
366pub fn debug_descriptor(desc: &CTFontDescriptor) {
367 println!("family: {}", desc.family_name());
368 println!("name: {}", desc.font_name());
369 println!("style: {}", desc.style_name());
370 println!("display: {}", desc.display_name());
371 println!("path: {:?}", desc.font_path());
372 desc.show();
373}
374
375extern "C" {
376 pub static kCTFontSymbolicTrait: CFStringRef;
382 pub static kCTFontWeightTrait: CFStringRef;
383 pub static kCTFontWidthTrait: CFStringRef;
384 pub static kCTFontSlantTrait: CFStringRef;
385
386 pub static kCTFontURLAttribute: CFStringRef; pub static kCTFontNameAttribute: CFStringRef; pub static kCTFontDisplayNameAttribute: CFStringRef; pub static kCTFontFamilyNameAttribute: CFStringRef; pub static kCTFontStyleNameAttribute: CFStringRef; pub static kCTFontTraitsAttribute: CFStringRef;
399 pub static kCTFontVariationAttribute: CFStringRef;
400 pub static kCTFontSizeAttribute: CFStringRef;
401 pub static kCTFontMatrixAttribute: CFStringRef;
402 pub static kCTFontCascadeListAttribute: CFStringRef;
403 pub static kCTFontCharacterSetAttribute: CFStringRef;
404 pub static kCTFontLanguagesAttribute: CFStringRef;
405 pub static kCTFontBaselineAdjustAttribute: CFStringRef;
406 pub static kCTFontMacintoshEncodingsAttribute: CFStringRef;
407 pub static kCTFontFeaturesAttribute: CFStringRef;
408 pub static kCTFontFeatureSettingsAttribute: CFStringRef;
409 pub static kCTFontFixedAdvanceAttribute: CFStringRef;
410 pub static kCTFontOrientationAttribute: CFStringRef;
411 pub static kCTFontFormatAttribute: CFStringRef;
412 pub static kCTFontRegistrationScopeAttribute: CFStringRef;
413 pub static kCTFontPriorityAttribute: CFStringRef;
414 pub static kCTFontEnabledAttribute: CFStringRef;
415
416 pub fn CTFontDescriptorCopyAttribute(
417 descriptor: CTFontDescriptorRef,
418 attribute: CFStringRef,
419 ) -> CFTypeRef;
420 pub fn CTFontDescriptorCopyAttributes(descriptor: CTFontDescriptorRef) -> CFDictionaryRef;
421 pub fn CTFontDescriptorCopyLocalizedAttribute(
422 descriptor: CTFontDescriptorRef,
423 attribute: CFStringRef,
424 language: *mut CFStringRef,
425 ) -> CFTypeRef;
426 pub fn CTFontDescriptorCreateCopyWithAttributes(
427 original: CTFontDescriptorRef,
428 attributes: CFDictionaryRef,
429 ) -> CTFontDescriptorRef;
430 pub fn CTFontDescriptorCreateCopyWithFeature(
431 original: CTFontDescriptorRef,
432 featureTypeIdentifier: CFNumberRef,
433 featureSelectorIdentifier: CFNumberRef,
434 ) -> CTFontDescriptorRef;
435 pub fn CTFontDescriptorCreateCopyWithVariation(
436 original: CTFontDescriptorRef,
437 variationIdentifier: CFNumberRef,
438 variationValue: CGFloat,
439 ) -> CTFontDescriptorRef;
440 pub fn CTFontDescriptorCreateMatchingFontDescriptor(
441 descriptor: CTFontDescriptorRef,
442 mandatoryAttributes: CFSetRef,
443 ) -> CTFontDescriptorRef;
444 pub fn CTFontDescriptorCreateWithAttributes(attributes: CFDictionaryRef)
445 -> CTFontDescriptorRef;
446 pub fn CTFontDescriptorCreateWithNameAndSize(
447 name: CFStringRef,
448 size: CGFloat,
449 ) -> CTFontDescriptorRef;
450 pub fn CTFontDescriptorGetTypeID() -> CFTypeID;
451}
452
453extern "C" {
454 pub fn CTFontDescriptorCreateMatchingFontDescriptors(
455 descriptor: CTFontDescriptorRef,
456 mandatoryAttributes: CFSetRef,
457 ) -> CFArrayRef;
458}