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::{CFURLCopyFileSystemPath, kCFURLPOSIXPathStyle, CFURL};
19 use core_graphics::base::CGFloat;
20 
21 use libc::c_void;
22 use std::mem;
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;
55 }
56 
57 impl SymbolicTraitAccessors for CTFontSymbolicTraits {
is_italic(&self) -> bool58     fn is_italic(&self) -> bool { (*self & kCTFontItalicTrait) != 0 }
is_bold(&self) -> bool59     fn is_bold(&self) -> bool { (*self & kCTFontBoldTrait) != 0 }
is_expanded(&self) -> bool60     fn is_expanded(&self) -> bool { (*self & kCTFontExpandedTrait) != 0 }
is_condensed(&self) -> bool61     fn is_condensed(&self) -> bool { (*self & kCTFontCondensedTrait) != 0 }
is_monospace(&self) -> bool62     fn is_monospace(&self) -> bool { (*self & kCTFontMonoSpaceTrait) != 0 }
63 }
64 
65 pub type CTFontStylisticClass = u32;
66 pub const kCTFontUnknownClass: CTFontStylisticClass = (0 << kCTFontClassMaskShift );
67 pub const kCTFontOldStyleSerifsClass: CTFontStylisticClass = (1 << kCTFontClassMaskShift );
68 pub const kCTFontTransitionalSerifsClass: CTFontStylisticClass = (2 << kCTFontClassMaskShift );
69 pub const kCTFontModernSerifsClass: CTFontStylisticClass = (3 << kCTFontClassMaskShift );
70 pub const kCTFontClarendonSerifsClass: CTFontStylisticClass = (4 << kCTFontClassMaskShift );
71 pub const kCTFontSlabSerifsClass: CTFontStylisticClass = (5 << kCTFontClassMaskShift );
72 pub const kCTFontFreeformSerifsClass: CTFontStylisticClass = (7 << kCTFontClassMaskShift );
73 pub const kCTFontSansSerifClass: CTFontStylisticClass = (8 << kCTFontClassMaskShift );
74 pub const kCTFontOrnamentalsClass: CTFontStylisticClass = (9 << kCTFontClassMaskShift );
75 pub const kCTFontScriptsClass: CTFontStylisticClass = (10 << kCTFontClassMaskShift );
76 pub const kCTFontSymbolicClass: CTFontStylisticClass = (12 << kCTFontClassMaskShift );
77 
78 pub trait StylisticClassAccessors {
is_serif(&self) -> bool79     fn is_serif(&self) -> bool;
is_sans_serif(&self) -> bool80     fn is_sans_serif(&self) -> bool;
is_script(&self) -> bool81     fn is_script(&self) -> bool;
is_fantasy(&self) -> bool82     fn is_fantasy(&self) -> bool;
is_symbols(&self) -> bool83     fn is_symbols(&self) -> bool;
84 }
85 
86 impl StylisticClassAccessors for CTFontStylisticClass {
is_serif(&self) -> bool87     fn is_serif(&self) -> bool {
88         let any_serif_class = kCTFontOldStyleSerifsClass
89             | kCTFontTransitionalSerifsClass
90             | kCTFontModernSerifsClass
91             | kCTFontClarendonSerifsClass
92             | kCTFontSlabSerifsClass
93             | kCTFontFreeformSerifsClass;
94 
95         return (*self & any_serif_class) != 0;
96     }
97 
is_sans_serif(&self) -> bool98     fn is_sans_serif(&self) -> bool {
99         return (*self & kCTFontSansSerifClass) != 0;
100     }
101 
is_script(&self) -> bool102     fn is_script(&self) -> bool {
103         return (*self & kCTFontScriptsClass) != 0;
104     }
105 
is_fantasy(&self) -> bool106     fn is_fantasy(&self) -> bool {
107         return (*self & kCTFontOrnamentalsClass) != 0;
108     }
109 
is_symbols(&self) -> bool110     fn is_symbols(&self) -> bool {
111         return (*self & kCTFontSymbolicClass) != 0;
112     }
113 }
114 
115 pub type CTFontAttributes = CFDictionary;
116 
117 pub type CTFontTraits = CFDictionary;
118 
119 pub trait TraitAccessors {
symbolic_traits(&self) -> CTFontSymbolicTraits120     fn symbolic_traits(&self) -> CTFontSymbolicTraits;
normalized_weight(&self) -> f64121     fn normalized_weight(&self) -> f64;
normalized_width(&self) -> f64122     fn normalized_width(&self) -> f64;
normalized_slant(&self) -> f64123     fn normalized_slant(&self) -> f64;
124 }
125 
126 trait TraitAccessorPrivate {
extract_number_for_key(&self, key: CFStringRef) -> CFNumber127     unsafe fn extract_number_for_key(&self, key: CFStringRef) -> CFNumber;
128 }
129 
130 impl TraitAccessorPrivate for CTFontTraits {
extract_number_for_key(&self, key: CFStringRef) -> CFNumber131     unsafe fn extract_number_for_key(&self, key: CFStringRef) -> CFNumber {
132         let cftype = self.get_CFType(mem::transmute(key));
133         assert!(cftype.instance_of::<CFNumber>());
134         CFNumber::wrap_under_get_rule(mem::transmute(cftype.as_CFTypeRef()))
135     }
136 
137 }
138 
139 impl TraitAccessors for CTFontTraits {
symbolic_traits(&self) -> CTFontSymbolicTraits140     fn symbolic_traits(&self) -> CTFontSymbolicTraits {
141         unsafe {
142             let number = self.extract_number_for_key(kCTFontSymbolicTrait);
143             number.to_i64().unwrap() as u32
144         }
145     }
146 
normalized_weight(&self) -> f64147     fn normalized_weight(&self) -> f64 {
148         unsafe {
149             let number = self.extract_number_for_key(kCTFontWeightTrait);
150             number.to_f64().unwrap()
151         }
152     }
153 
normalized_width(&self) -> f64154     fn normalized_width(&self) -> f64 {
155         unsafe {
156             let number = self.extract_number_for_key(kCTFontWidthTrait);
157             number.to_f64().unwrap()
158         }
159     }
160 
normalized_slant(&self) -> f64161     fn normalized_slant(&self) -> f64 {
162         unsafe {
163             let number = self.extract_number_for_key(kCTFontSlantTrait);
164             number.to_f64().unwrap()
165         }
166     }
167 }
168 
169 /*
170 * CTFontDescriptor.h
171 */
172 pub type CTFontOrientation = u32;
173 pub const kCTFontDefaultOrientation: CTFontOrientation = 0;
174 pub const kCTFontHorizontalOrientation: CTFontOrientation = 1;
175 pub const kCTFontVerticalOrientation: CTFontOrientation = 2;
176 
177 pub type CTFontPriority = u32;
178 pub const kCTFontPrioritySystem: CTFontPriority = 10000;
179 pub const kCTFontPriorityNetwork: CTFontPriority = 20000;
180 pub const kCTFontPriorityComputer: CTFontPriority = 30000;
181 pub const kCTFontPriorityUser: CTFontPriority = 40000;
182 pub const kCTFontPriorityDynamic: CTFontPriority = 50000;
183 pub const kCTFontPriorityProcess: CTFontPriority = 60000;
184 
185 #[repr(C)]
186 pub struct __CTFontDescriptor(c_void);
187 
188 pub type CTFontDescriptorRef = *const __CTFontDescriptor;
189 
190 declare_TCFType! {
191     CTFontDescriptor, CTFontDescriptorRef
192 }
193 impl_TCFType!(CTFontDescriptor, CTFontDescriptorRef, CTFontDescriptorGetTypeID);
194 impl_CFTypeDescription!(CTFontDescriptor);
195 
196 
197 impl CTFontDescriptor {
get_string_attribute(&self, attribute: CFStringRef) -> Option<String>198     fn get_string_attribute(&self, attribute: CFStringRef) -> Option<String> {
199         unsafe {
200             let value = CTFontDescriptorCopyAttribute(self.0, attribute);
201             if value.is_null() {
202                 return None
203             }
204 
205             let value = CFType::wrap_under_create_rule(value);
206             assert!(value.instance_of::<CFString>());
207             let s = CFString::wrap_under_get_rule(mem::transmute(value.as_CFTypeRef()));
208             Some(s.to_string())
209         }
210     }
211 
212 }
213 
214 impl CTFontDescriptor {
family_name(&self) -> String215     pub fn family_name(&self) -> String {
216         unsafe {
217             let value = self.get_string_attribute(kCTFontFamilyNameAttribute);
218             value.expect("A font must have a non-null family name.")
219         }
220     }
221 
font_name(&self) -> String222     pub fn font_name(&self) -> String {
223         unsafe {
224             let value = self.get_string_attribute(kCTFontNameAttribute);
225             value.expect("A font must have a non-null name.")
226         }
227     }
228 
style_name(&self) -> String229     pub fn style_name(&self) -> String {
230         unsafe {
231             let value = self.get_string_attribute(kCTFontStyleNameAttribute);
232             value.expect("A font must have a non-null style name.")
233         }
234     }
235 
display_name(&self) -> String236     pub fn display_name(&self) -> String {
237         unsafe {
238             let value = self.get_string_attribute(kCTFontDisplayNameAttribute);
239             value.expect("A font must have a non-null display name.")
240         }
241     }
242 
font_path(&self) -> Option<String>243     pub fn font_path(&self) -> Option<String> {
244         unsafe {
245             let value = CTFontDescriptorCopyAttribute(self.0, kCTFontURLAttribute);
246             if value.is_null() {
247                 return None;
248             }
249 
250             let value = CFType::wrap_under_create_rule(value);
251             assert!(value.instance_of::<CFURL>());
252             let url = CFURL::wrap_under_get_rule(mem::transmute(value.as_CFTypeRef()));
253             let path = CFString::wrap_under_create_rule(CFURLCopyFileSystemPath(
254                 url.as_concrete_TypeRef(),
255                 kCFURLPOSIXPathStyle,
256             )).to_string();
257             Some(path)
258         }
259     }
260 
traits(&self) -> CTFontTraits261     pub fn traits(&self) -> CTFontTraits {
262         unsafe {
263             let value = CTFontDescriptorCopyAttribute(self.0, kCTFontTraitsAttribute);
264             assert!(!value.is_null());
265             let value = CFType::wrap_under_create_rule(value);
266             assert!(value.instance_of::<CFDictionary>());
267             CFDictionary::wrap_under_get_rule(mem::transmute(value.as_CFTypeRef()))
268         }
269     }
270 }
271 
new_from_attributes(attributes: &CFDictionary) -> CTFontDescriptor272 pub fn new_from_attributes(attributes: &CFDictionary) -> CTFontDescriptor {
273     unsafe {
274         let result: CTFontDescriptorRef =
275             CTFontDescriptorCreateWithAttributes(attributes.as_concrete_TypeRef());
276         CTFontDescriptor::wrap_under_create_rule(result)
277     }
278 }
279 
new_from_variations(variations: &CFDictionary) -> CTFontDescriptor280 pub fn new_from_variations(variations: &CFDictionary) -> CTFontDescriptor {
281     unsafe {
282         let var_key = CFType::wrap_under_get_rule(mem::transmute(kCTFontVariationAttribute));
283         let var_val = CFType::wrap_under_get_rule(variations.as_CFTypeRef());
284         let attributes = CFDictionary::from_CFType_pairs(&[(var_key, var_val)]);
285         new_from_attributes(&attributes)
286     }
287 }
288 
debug_descriptor(desc: &CTFontDescriptor)289 pub fn debug_descriptor(desc: &CTFontDescriptor) {
290     println!("family: {}", desc.family_name());
291     println!("name: {}", desc.font_name());
292     println!("style: {}", desc.style_name());
293     println!("display: {}", desc.display_name());
294     println!("path: {:?}", desc.font_path());
295     desc.show();
296 }
297 
298 extern {
299     /*
300      * CTFontTraits.h
301      */
302 
303     // font trait constants
304     pub static kCTFontSymbolicTrait: CFStringRef;
305     pub static kCTFontWeightTrait: CFStringRef;
306     pub static kCTFontWidthTrait: CFStringRef;
307     pub static kCTFontSlantTrait: CFStringRef;
308 
309     /*
310      * CTFontDescriptor.h
311      */
312 
313     // font attribute constants. Note that the name-related attributes
314     // here are somewhat flaky. Servo creates CTFont instances and
315     // then uses CTFontCopyName to get more fine-grained names.
316     pub static kCTFontURLAttribute:                  CFStringRef; // value: CFURLRef
317     pub static kCTFontNameAttribute:                 CFStringRef; // value: CFStringRef
318     pub static kCTFontDisplayNameAttribute:          CFStringRef; // value: CFStringRef
319     pub static kCTFontFamilyNameAttribute:           CFStringRef; // value: CFStringRef
320     pub static kCTFontStyleNameAttribute:            CFStringRef; // value: CFStringRef
321     pub static kCTFontTraitsAttribute:               CFStringRef;
322     pub static kCTFontVariationAttribute:            CFStringRef;
323     pub static kCTFontSizeAttribute:                 CFStringRef;
324     pub static kCTFontMatrixAttribute:               CFStringRef;
325     pub static kCTFontCascadeListAttribute:          CFStringRef;
326     pub static kCTFontCharacterSetAttribute:         CFStringRef;
327     pub static kCTFontLanguagesAttribute:            CFStringRef;
328     pub static kCTFontBaselineAdjustAttribute:       CFStringRef;
329     pub static kCTFontMacintoshEncodingsAttribute:   CFStringRef;
330     pub static kCTFontFeaturesAttribute:             CFStringRef;
331     pub static kCTFontFeatureSettingsAttribute:      CFStringRef;
332     pub static kCTFontFixedAdvanceAttribute:         CFStringRef;
333     pub static kCTFontOrientationAttribute:          CFStringRef;
334     pub static kCTFontFormatAttribute:               CFStringRef;
335     pub static kCTFontRegistrationScopeAttribute:    CFStringRef;
336     pub static kCTFontPriorityAttribute:             CFStringRef;
337     pub static kCTFontEnabledAttribute:              CFStringRef;
338 
CTFontDescriptorCopyAttribute(descriptor: CTFontDescriptorRef, attribute: CFStringRef) -> CFTypeRef339     pub fn CTFontDescriptorCopyAttribute(descriptor: CTFontDescriptorRef,
340                                          attribute: CFStringRef) -> CFTypeRef;
CTFontDescriptorCopyAttributes(descriptor: CTFontDescriptorRef) -> CFDictionaryRef341     pub fn CTFontDescriptorCopyAttributes(descriptor: CTFontDescriptorRef) -> CFDictionaryRef;
CTFontDescriptorCopyLocalizedAttribute(descriptor: CTFontDescriptorRef, attribute: CFStringRef, language: *mut CFStringRef) -> CFTypeRef342     pub fn CTFontDescriptorCopyLocalizedAttribute(descriptor: CTFontDescriptorRef,
343                                                   attribute: CFStringRef,
344                                                   language: *mut CFStringRef) -> CFTypeRef;
CTFontDescriptorCreateCopyWithAttributes(original: CTFontDescriptorRef, attributes: CFDictionaryRef) -> CTFontDescriptorRef345     pub fn CTFontDescriptorCreateCopyWithAttributes(original: CTFontDescriptorRef,
346                                                     attributes: CFDictionaryRef) -> CTFontDescriptorRef;
CTFontDescriptorCreateCopyWithFeature(original: CTFontDescriptorRef, featureTypeIdentifier: CFNumberRef, featureSelectorIdentifier: CFNumberRef) -> CTFontDescriptorRef347     pub fn CTFontDescriptorCreateCopyWithFeature(original: CTFontDescriptorRef,
348                                                  featureTypeIdentifier: CFNumberRef,
349                                                  featureSelectorIdentifier: CFNumberRef) -> CTFontDescriptorRef;
CTFontDescriptorCreateCopyWithVariation(original: CTFontDescriptorRef, variationIdentifier: CFNumberRef, variationValue: CGFloat) -> CTFontDescriptorRef350     pub fn CTFontDescriptorCreateCopyWithVariation(original: CTFontDescriptorRef,
351                                                    variationIdentifier: CFNumberRef,
352                                                    variationValue: CGFloat) -> CTFontDescriptorRef;
CTFontDescriptorCreateMatchingFontDescriptor(descriptor: CTFontDescriptorRef, mandatoryAttributes: CFSetRef) -> CTFontDescriptorRef353     pub fn CTFontDescriptorCreateMatchingFontDescriptor(descriptor: CTFontDescriptorRef,
354                                                         mandatoryAttributes: CFSetRef) -> CTFontDescriptorRef;
CTFontDescriptorCreateWithAttributes(attributes: CFDictionaryRef) -> CTFontDescriptorRef355     pub fn CTFontDescriptorCreateWithAttributes(attributes: CFDictionaryRef) -> CTFontDescriptorRef;
CTFontDescriptorCreateWithNameAndSize(name: CFStringRef, size: CGFloat) -> CTFontDescriptorRef356     pub fn CTFontDescriptorCreateWithNameAndSize(name: CFStringRef, size: CGFloat) -> CTFontDescriptorRef;
CTFontDescriptorGetTypeID() -> CFTypeID357     pub fn CTFontDescriptorGetTypeID() -> CFTypeID;
358 }
359 
360 extern {
CTFontDescriptorCreateMatchingFontDescriptors(descriptor: CTFontDescriptorRef, mandatoryAttributes: CFSetRef) -> CFArrayRef361     pub fn CTFontDescriptorCreateMatchingFontDescriptors(descriptor: CTFontDescriptorRef,
362                                                          mandatoryAttributes: CFSetRef) -> CFArrayRef;
363 }
364