1 // Copyright 2013 The Servo Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution.
3 //
4 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
5 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
7 // option. This file may not be copied, modified, or distributed
8 // except according to those terms.
9 
10 #![allow(non_upper_case_globals)]
11 
12 use core_foundation::array::CFArrayRef;
13 use core_foundation::base::{CFType, CFTypeID, CFTypeRef, TCFType};
14 use core_foundation::dictionary::{CFDictionary, CFDictionaryRef};
15 use core_foundation::number::{CFNumber, CFNumberRef};
16 use core_foundation::set::CFSetRef;
17 use core_foundation::string::{CFString, CFStringRef};
18 use core_foundation::url::{CFURL, CFURLRef};
19 use core_graphics::base::CGFloat;
20 
21 use std::os::raw::c_void;
22 use std::path::PathBuf;
23 
24 /*
25 * CTFontTraits.h
26 */
27 // actually, these are extern enums
28 pub type CTFontFormat = u32;
29 pub const kCTFontFormatUnrecognized: CTFontFormat = 0;
30 pub const kCTFontFormatOpenTypePostScript: CTFontFormat = 1;
31 pub const kCTFontFormatOpenTypeTrueType: CTFontFormat = 2;
32 pub const kCTFontFormatTrueType: CTFontFormat = 3;
33 pub const kCTFontFormatPostScript: CTFontFormat = 4;
34 pub const kCTFontFormatBitmap: CTFontFormat = 5;
35 
36 pub const kCTFontClassMaskShift: u32 = 28;
37 
38 pub type CTFontSymbolicTraits = u32;
39 pub const kCTFontItalicTrait: CTFontSymbolicTraits = (1 << 0);
40 pub const kCTFontBoldTrait: CTFontSymbolicTraits = (1 << 1);
41 pub const kCTFontExpandedTrait: CTFontSymbolicTraits = (1 << 5);
42 pub const kCTFontCondensedTrait: CTFontSymbolicTraits = (1 << 6);
43 pub const kCTFontMonoSpaceTrait: CTFontSymbolicTraits = (1 << 10);
44 pub const kCTFontVerticalTrait: CTFontSymbolicTraits = (1 << 11);
45 pub const kCTFontUIOptimizedTrait: CTFontSymbolicTraits = (1 << 12);
46 pub const kCTFontColorGlyphsTrait: CTFontSymbolicTraits = (1 << 13);
47 pub const kCTFontClassMaskTrait: CTFontSymbolicTraits = (15 << kCTFontClassMaskShift );
48 
49 pub trait SymbolicTraitAccessors {
is_italic(&self) -> bool50     fn is_italic(&self) -> bool;
is_bold(&self) -> bool51     fn is_bold(&self) -> bool;
is_expanded(&self) -> bool52     fn is_expanded(&self) -> bool;
is_condensed(&self) -> bool53     fn is_condensed(&self) -> bool;
is_monospace(&self) -> bool54     fn is_monospace(&self) -> bool;
is_vertical(&self) -> bool55     fn is_vertical(&self) -> bool;
56 }
57 
58 impl SymbolicTraitAccessors for CTFontSymbolicTraits {
is_italic(&self) -> bool59     fn is_italic(&self) -> bool { (*self & kCTFontItalicTrait) != 0 }
is_bold(&self) -> bool60     fn is_bold(&self) -> bool { (*self & kCTFontBoldTrait) != 0 }
is_expanded(&self) -> bool61     fn is_expanded(&self) -> bool { (*self & kCTFontExpandedTrait) != 0 }
is_condensed(&self) -> bool62     fn is_condensed(&self) -> bool { (*self & kCTFontCondensedTrait) != 0 }
is_monospace(&self) -> bool63     fn is_monospace(&self) -> bool { (*self & kCTFontMonoSpaceTrait) != 0 }
is_vertical(&self) -> bool64     fn is_vertical(&self) -> bool { (*self & kCTFontVerticalTrait) != 0 }
65 }
66 
67 pub type CTFontStylisticClass = u32;
68 pub const kCTFontUnknownClass: CTFontStylisticClass = (0 << kCTFontClassMaskShift );
69 pub const kCTFontOldStyleSerifsClass: CTFontStylisticClass = (1 << kCTFontClassMaskShift );
70 pub const kCTFontTransitionalSerifsClass: CTFontStylisticClass = (2 << kCTFontClassMaskShift );
71 pub const kCTFontModernSerifsClass: CTFontStylisticClass = (3 << kCTFontClassMaskShift );
72 pub const kCTFontClarendonSerifsClass: CTFontStylisticClass = (4 << kCTFontClassMaskShift );
73 pub const kCTFontSlabSerifsClass: CTFontStylisticClass = (5 << kCTFontClassMaskShift );
74 pub const kCTFontFreeformSerifsClass: CTFontStylisticClass = (7 << kCTFontClassMaskShift );
75 pub const kCTFontSansSerifClass: CTFontStylisticClass = (8 << kCTFontClassMaskShift );
76 pub const kCTFontOrnamentalsClass: CTFontStylisticClass = (9 << kCTFontClassMaskShift );
77 pub const kCTFontScriptsClass: CTFontStylisticClass = (10 << kCTFontClassMaskShift );
78 pub const kCTFontSymbolicClass: CTFontStylisticClass = (12 << kCTFontClassMaskShift );
79 
80 pub trait StylisticClassAccessors {
is_serif(&self) -> bool81     fn is_serif(&self) -> bool;
is_sans_serif(&self) -> bool82     fn is_sans_serif(&self) -> bool;
is_script(&self) -> bool83     fn is_script(&self) -> bool;
is_fantasy(&self) -> bool84     fn is_fantasy(&self) -> bool;
is_symbols(&self) -> bool85     fn is_symbols(&self) -> bool;
86 }
87 
88 impl StylisticClassAccessors for CTFontStylisticClass {
is_serif(&self) -> bool89     fn is_serif(&self) -> bool {
90         let any_serif_class = kCTFontOldStyleSerifsClass
91             | kCTFontTransitionalSerifsClass
92             | kCTFontModernSerifsClass
93             | kCTFontClarendonSerifsClass
94             | kCTFontSlabSerifsClass
95             | kCTFontFreeformSerifsClass;
96 
97         (*self & any_serif_class) != 0
98     }
99 
is_sans_serif(&self) -> bool100     fn is_sans_serif(&self) -> bool {
101         (*self & kCTFontSansSerifClass) != 0
102     }
103 
is_script(&self) -> bool104     fn is_script(&self) -> bool {
105         (*self & kCTFontScriptsClass) != 0
106     }
107 
is_fantasy(&self) -> bool108     fn is_fantasy(&self) -> bool {
109         (*self & kCTFontOrnamentalsClass) != 0
110     }
111 
is_symbols(&self) -> bool112     fn is_symbols(&self) -> bool {
113         (*self & kCTFontSymbolicClass) != 0
114     }
115 }
116 
117 pub type CTFontAttributes = CFDictionary;
118 
119 pub type CTFontTraits = CFDictionary<CFString, CFType>;
120 
121 pub trait TraitAccessors {
symbolic_traits(&self) -> CTFontSymbolicTraits122     fn symbolic_traits(&self) -> CTFontSymbolicTraits;
normalized_weight(&self) -> f64123     fn normalized_weight(&self) -> f64;
normalized_width(&self) -> f64124     fn normalized_width(&self) -> f64;
normalized_slant(&self) -> f64125     fn normalized_slant(&self) -> f64;
126 }
127 
128 trait TraitAccessorPrivate {
extract_number_for_key(&self, key: CFStringRef) -> CFNumber129     fn extract_number_for_key(&self, key: CFStringRef) -> CFNumber;
130 }
131 
132 impl TraitAccessorPrivate for CTFontTraits {
extract_number_for_key(&self, key: CFStringRef) -> CFNumber133     fn extract_number_for_key(&self, key: CFStringRef) -> CFNumber {
134         let cftype = self.get(key);
135         cftype.downcast::<CFNumber>().unwrap()
136     }
137 
138 }
139 
140 impl TraitAccessors for CTFontTraits {
symbolic_traits(&self) -> CTFontSymbolicTraits141     fn symbolic_traits(&self) -> CTFontSymbolicTraits {
142         unsafe {
143             let number = self.extract_number_for_key(kCTFontSymbolicTrait);
144             number.to_i64().unwrap() as u32
145         }
146     }
147 
normalized_weight(&self) -> f64148     fn normalized_weight(&self) -> f64 {
149         unsafe {
150             let number = self.extract_number_for_key(kCTFontWeightTrait);
151             number.to_f64().unwrap()
152         }
153     }
154 
normalized_width(&self) -> f64155     fn normalized_width(&self) -> f64 {
156         unsafe {
157             let number = self.extract_number_for_key(kCTFontWidthTrait);
158             number.to_f64().unwrap()
159         }
160     }
161 
normalized_slant(&self) -> f64162     fn normalized_slant(&self) -> f64 {
163         unsafe {
164             let number = self.extract_number_for_key(kCTFontSlantTrait);
165             number.to_f64().unwrap()
166         }
167     }
168 }
169 
170 /*
171 * CTFontDescriptor.h
172 */
173 pub type CTFontOrientation = u32;
174 pub const kCTFontDefaultOrientation: CTFontOrientation = 0;
175 pub const kCTFontHorizontalOrientation: CTFontOrientation = 1;
176 pub const kCTFontVerticalOrientation: CTFontOrientation = 2;
177 
178 pub type CTFontPriority = u32;
179 pub const kCTFontPrioritySystem: CTFontPriority = 10000;
180 pub const kCTFontPriorityNetwork: CTFontPriority = 20000;
181 pub const kCTFontPriorityComputer: CTFontPriority = 30000;
182 pub const kCTFontPriorityUser: CTFontPriority = 40000;
183 pub const kCTFontPriorityDynamic: CTFontPriority = 50000;
184 pub const kCTFontPriorityProcess: CTFontPriority = 60000;
185 
186 #[repr(C)]
187 pub struct __CTFontDescriptor(c_void);
188 
189 pub type CTFontDescriptorRef = *const __CTFontDescriptor;
190 
191 declare_TCFType! {
192     CTFontDescriptor, CTFontDescriptorRef
193 }
194 impl_TCFType!(CTFontDescriptor, CTFontDescriptorRef, CTFontDescriptorGetTypeID);
195 impl_CFTypeDescription!(CTFontDescriptor);
196 
197 
198 impl CTFontDescriptor {
get_string_attribute(&self, attribute: CFStringRef) -> Option<String>199     fn get_string_attribute(&self, attribute: CFStringRef) -> Option<String> {
200         unsafe {
201             let value = CTFontDescriptorCopyAttribute(self.0, attribute);
202             if value.is_null() {
203                 return None
204             }
205 
206             let value = CFType::wrap_under_create_rule(value);
207             assert!(value.instance_of::<CFString>());
208             let s = CFString::wrap_under_get_rule(value.as_CFTypeRef() as CFStringRef);
209             Some(s.to_string())
210         }
211     }
212 
213 }
214 
215 impl CTFontDescriptor {
family_name(&self) -> String216     pub fn family_name(&self) -> String {
217         unsafe {
218             let value = self.get_string_attribute(kCTFontFamilyNameAttribute);
219             value.expect("A font must have a non-null family name.")
220         }
221     }
222 
font_name(&self) -> String223     pub fn font_name(&self) -> String {
224         unsafe {
225             let value = self.get_string_attribute(kCTFontNameAttribute);
226             value.expect("A font must have a non-null name.")
227         }
228     }
229 
style_name(&self) -> String230     pub fn style_name(&self) -> String {
231         unsafe {
232             let value = self.get_string_attribute(kCTFontStyleNameAttribute);
233             value.expect("A font must have a non-null style name.")
234         }
235     }
236 
display_name(&self) -> String237     pub fn display_name(&self) -> String {
238         unsafe {
239             let value = self.get_string_attribute(kCTFontDisplayNameAttribute);
240             value.expect("A font must have a non-null display name.")
241         }
242     }
243 
font_format(&self) -> Option<CTFontFormat>244     pub fn font_format(&self) -> Option<CTFontFormat> {
245         unsafe {
246             let value = CTFontDescriptorCopyAttribute(self.0, kCTFontFormatAttribute);
247             if value.is_null() {
248                 return None;
249             }
250 
251             let value = CFType::wrap_under_create_rule(value);
252             assert!(value.instance_of::<CFNumber>());
253             let format = CFNumber::wrap_under_get_rule(value.as_CFTypeRef() as CFNumberRef);
254             format.to_i32().map(|x| x as CTFontFormat)
255         }
256     }
257 
font_path(&self) -> Option<PathBuf>258     pub fn font_path(&self) -> Option<PathBuf> {
259         unsafe {
260             let value = CTFontDescriptorCopyAttribute(self.0, kCTFontURLAttribute);
261             if value.is_null() {
262                 return None;
263             }
264 
265             let value = CFType::wrap_under_create_rule(value);
266             assert!(value.instance_of::<CFURL>());
267             let url = CFURL::wrap_under_get_rule(value.as_CFTypeRef() as CFURLRef);
268             url.to_path()
269         }
270     }
271 
traits(&self) -> CTFontTraits272     pub fn traits(&self) -> CTFontTraits {
273         unsafe {
274             let value = CTFontDescriptorCopyAttribute(self.0, kCTFontTraitsAttribute);
275             assert!(!value.is_null());
276             let value = CFType::wrap_under_create_rule(value);
277             assert!(value.instance_of::<CFDictionary>());
278             CFDictionary::wrap_under_get_rule(value.as_CFTypeRef() as CFDictionaryRef)
279         }
280     }
281 }
282 
new_from_attributes(attributes: &CFDictionary<CFString, CFType>) -> CTFontDescriptor283 pub fn new_from_attributes(attributes: &CFDictionary<CFString, CFType>) -> CTFontDescriptor {
284     unsafe {
285         let result: CTFontDescriptorRef =
286             CTFontDescriptorCreateWithAttributes(attributes.as_concrete_TypeRef());
287         CTFontDescriptor::wrap_under_create_rule(result)
288     }
289 }
290 
new_from_variations(variations: &CFDictionary<CFString, CFNumber>) -> CTFontDescriptor291 pub fn new_from_variations(variations: &CFDictionary<CFString, CFNumber>) -> CTFontDescriptor {
292     unsafe {
293         let var_key = CFString::wrap_under_get_rule(kCTFontVariationAttribute);
294         let var_val = CFType::wrap_under_get_rule(variations.as_CFTypeRef());
295         let attributes = CFDictionary::from_CFType_pairs(&[(var_key, var_val)]);
296         new_from_attributes(&attributes)
297     }
298 }
299 
new_from_postscript_name(name: &CFString) -> CTFontDescriptor300 pub fn new_from_postscript_name(name: &CFString) -> CTFontDescriptor {
301     unsafe {
302         let result: CTFontDescriptorRef =
303             CTFontDescriptorCreateWithNameAndSize(name.as_concrete_TypeRef(), 0.0);
304         CTFontDescriptor::wrap_under_create_rule(result)
305     }
306 }
307 
debug_descriptor(desc: &CTFontDescriptor)308 pub fn debug_descriptor(desc: &CTFontDescriptor) {
309     println!("family: {}", desc.family_name());
310     println!("name: {}", desc.font_name());
311     println!("style: {}", desc.style_name());
312     println!("display: {}", desc.display_name());
313     println!("path: {:?}", desc.font_path());
314     desc.show();
315 }
316 
317 extern {
318     /*
319      * CTFontTraits.h
320      */
321 
322     // font trait constants
323     pub static kCTFontSymbolicTrait: CFStringRef;
324     pub static kCTFontWeightTrait: CFStringRef;
325     pub static kCTFontWidthTrait: CFStringRef;
326     pub static kCTFontSlantTrait: CFStringRef;
327 
328     /*
329      * CTFontDescriptor.h
330      */
331 
332     // font attribute constants. Note that the name-related attributes
333     // here are somewhat flaky. Servo creates CTFont instances and
334     // then uses CTFontCopyName to get more fine-grained names.
335     pub static kCTFontURLAttribute:                  CFStringRef; // value: CFURLRef
336     pub static kCTFontNameAttribute:                 CFStringRef; // value: CFStringRef
337     pub static kCTFontDisplayNameAttribute:          CFStringRef; // value: CFStringRef
338     pub static kCTFontFamilyNameAttribute:           CFStringRef; // value: CFStringRef
339     pub static kCTFontStyleNameAttribute:            CFStringRef; // value: CFStringRef
340     pub static kCTFontTraitsAttribute:               CFStringRef;
341     pub static kCTFontVariationAttribute:            CFStringRef;
342     pub static kCTFontSizeAttribute:                 CFStringRef;
343     pub static kCTFontMatrixAttribute:               CFStringRef;
344     pub static kCTFontCascadeListAttribute:          CFStringRef;
345     pub static kCTFontCharacterSetAttribute:         CFStringRef;
346     pub static kCTFontLanguagesAttribute:            CFStringRef;
347     pub static kCTFontBaselineAdjustAttribute:       CFStringRef;
348     pub static kCTFontMacintoshEncodingsAttribute:   CFStringRef;
349     pub static kCTFontFeaturesAttribute:             CFStringRef;
350     pub static kCTFontFeatureSettingsAttribute:      CFStringRef;
351     pub static kCTFontFixedAdvanceAttribute:         CFStringRef;
352     pub static kCTFontOrientationAttribute:          CFStringRef;
353     pub static kCTFontFormatAttribute:               CFStringRef;
354     pub static kCTFontRegistrationScopeAttribute:    CFStringRef;
355     pub static kCTFontPriorityAttribute:             CFStringRef;
356     pub static kCTFontEnabledAttribute:              CFStringRef;
357 
CTFontDescriptorCopyAttribute(descriptor: CTFontDescriptorRef, attribute: CFStringRef) -> CFTypeRef358     pub fn CTFontDescriptorCopyAttribute(descriptor: CTFontDescriptorRef,
359                                          attribute: CFStringRef) -> CFTypeRef;
CTFontDescriptorCopyAttributes(descriptor: CTFontDescriptorRef) -> CFDictionaryRef360     pub fn CTFontDescriptorCopyAttributes(descriptor: CTFontDescriptorRef) -> CFDictionaryRef;
CTFontDescriptorCopyLocalizedAttribute(descriptor: CTFontDescriptorRef, attribute: CFStringRef, language: *mut CFStringRef) -> CFTypeRef361     pub fn CTFontDescriptorCopyLocalizedAttribute(descriptor: CTFontDescriptorRef,
362                                                   attribute: CFStringRef,
363                                                   language: *mut CFStringRef) -> CFTypeRef;
CTFontDescriptorCreateCopyWithAttributes(original: CTFontDescriptorRef, attributes: CFDictionaryRef) -> CTFontDescriptorRef364     pub fn CTFontDescriptorCreateCopyWithAttributes(original: CTFontDescriptorRef,
365                                                     attributes: CFDictionaryRef) -> CTFontDescriptorRef;
CTFontDescriptorCreateCopyWithFeature(original: CTFontDescriptorRef, featureTypeIdentifier: CFNumberRef, featureSelectorIdentifier: CFNumberRef) -> CTFontDescriptorRef366     pub fn CTFontDescriptorCreateCopyWithFeature(original: CTFontDescriptorRef,
367                                                  featureTypeIdentifier: CFNumberRef,
368                                                  featureSelectorIdentifier: CFNumberRef) -> CTFontDescriptorRef;
CTFontDescriptorCreateCopyWithVariation(original: CTFontDescriptorRef, variationIdentifier: CFNumberRef, variationValue: CGFloat) -> CTFontDescriptorRef369     pub fn CTFontDescriptorCreateCopyWithVariation(original: CTFontDescriptorRef,
370                                                    variationIdentifier: CFNumberRef,
371                                                    variationValue: CGFloat) -> CTFontDescriptorRef;
CTFontDescriptorCreateMatchingFontDescriptor(descriptor: CTFontDescriptorRef, mandatoryAttributes: CFSetRef) -> CTFontDescriptorRef372     pub fn CTFontDescriptorCreateMatchingFontDescriptor(descriptor: CTFontDescriptorRef,
373                                                         mandatoryAttributes: CFSetRef) -> CTFontDescriptorRef;
CTFontDescriptorCreateWithAttributes(attributes: CFDictionaryRef) -> CTFontDescriptorRef374     pub fn CTFontDescriptorCreateWithAttributes(attributes: CFDictionaryRef) -> CTFontDescriptorRef;
CTFontDescriptorCreateWithNameAndSize(name: CFStringRef, size: CGFloat) -> CTFontDescriptorRef375     pub fn CTFontDescriptorCreateWithNameAndSize(name: CFStringRef, size: CGFloat) -> CTFontDescriptorRef;
CTFontDescriptorGetTypeID() -> CFTypeID376     pub fn CTFontDescriptorGetTypeID() -> CFTypeID;
377 }
378 
379 extern {
CTFontDescriptorCreateMatchingFontDescriptors(descriptor: CTFontDescriptorRef, mandatoryAttributes: CFSetRef) -> CFArrayRef380     pub fn CTFontDescriptorCreateMatchingFontDescriptors(descriptor: CTFontDescriptorRef,
381                                                          mandatoryAttributes: CFSetRef) -> CFArrayRef;
382 }
383