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 use std::ptr;
11 use core_foundation::base::{CFRelease, CFRetain, CFTypeID, TCFType};
12 use core_foundation::array::{CFArray, CFArrayRef};
13 use core_foundation::data::{CFData, CFDataRef};
14 use core_foundation::number::CFNumber;
15 use core_foundation::string::{CFString, CFStringRef};
16 use core_foundation::dictionary::{CFDictionary, CFDictionaryRef};
17 use data_provider::CGDataProvider;
18 use geometry::CGRect;
19 
20 use foreign_types::ForeignType;
21 
22 use libc::{self, c_int, size_t};
23 
24 pub type CGGlyph = libc::c_ushort;
25 
26 foreign_type! {
27     #[doc(hidden)]
28     type CType = ::sys::CGFont;
29     fn drop = |p| CFRelease(p as *mut _);
30     fn clone = |p| CFRetain(p as *const _) as *mut _;
31     pub struct CGFont;
32     pub struct CGFontRef;
33 }
34 
35 unsafe impl Send for CGFont {}
36 unsafe impl Sync for CGFont {}
37 
38 impl CGFont {
type_id() -> CFTypeID39     pub fn type_id() -> CFTypeID {
40         unsafe {
41             CGFontGetTypeID()
42         }
43     }
44 
from_data_provider(provider: CGDataProvider) -> Result<CGFont, ()>45     pub fn from_data_provider(provider: CGDataProvider) -> Result<CGFont, ()> {
46         unsafe {
47             let font_ref = CGFontCreateWithDataProvider(provider.as_ptr());
48             if !font_ref.is_null() {
49                 Ok(CGFont::from_ptr(font_ref))
50             } else {
51                 Err(())
52             }
53         }
54     }
55 
from_name(name: &CFString) -> Result<CGFont, ()>56     pub fn from_name(name: &CFString) -> Result<CGFont, ()> {
57         unsafe {
58             let font_ref = CGFontCreateWithFontName(name.as_concrete_TypeRef());
59             if !font_ref.is_null() {
60                 Ok(CGFont::from_ptr(font_ref))
61             } else {
62                 Err(())
63             }
64         }
65     }
66 
create_copy_from_variations(&self, vars: &CFDictionary<CFString, CFNumber>) -> Result<CGFont, ()>67     pub fn create_copy_from_variations(&self, vars: &CFDictionary<CFString, CFNumber>) -> Result<CGFont, ()> {
68         unsafe {
69             let font_ref = CGFontCreateCopyWithVariations(self.as_ptr(),
70                                                           vars.as_concrete_TypeRef());
71             if !font_ref.is_null() {
72                 Ok(CGFont::from_ptr(font_ref))
73             } else {
74                 Err(())
75             }
76         }
77     }
78 
postscript_name(&self) -> CFString79     pub fn postscript_name(&self) -> CFString {
80         unsafe {
81             let string_ref = CGFontCopyPostScriptName(self.as_ptr());
82             TCFType::wrap_under_create_rule(string_ref)
83         }
84     }
85 
get_glyph_b_boxes(&self, glyphs: &[CGGlyph], bboxes: &mut [CGRect]) -> bool86     pub fn get_glyph_b_boxes(&self, glyphs: &[CGGlyph], bboxes: &mut [CGRect]) -> bool {
87         unsafe {
88             assert!(bboxes.len() >= glyphs.len());
89             CGFontGetGlyphBBoxes(self.as_ptr(),
90                                  glyphs.as_ptr(),
91                                  glyphs.len(),
92                                  bboxes.as_mut_ptr())
93         }
94     }
95 
get_glyph_advances(&self, glyphs: &[CGGlyph], advances: &mut [c_int]) -> bool96     pub fn get_glyph_advances(&self, glyphs: &[CGGlyph], advances: &mut [c_int]) -> bool {
97         unsafe {
98             assert!(advances.len() >= glyphs.len());
99             CGFontGetGlyphAdvances(self.as_ptr(),
100                                    glyphs.as_ptr(),
101                                    glyphs.len(),
102                                    advances.as_mut_ptr())
103         }
104     }
105 
get_units_per_em(&self) -> c_int106     pub fn get_units_per_em(&self) -> c_int {
107         unsafe {
108             CGFontGetUnitsPerEm(self.as_ptr())
109         }
110     }
111 
copy_table_tags(&self) -> CFArray<u32>112     pub fn copy_table_tags(&self) -> CFArray<u32> {
113         unsafe {
114             TCFType::wrap_under_create_rule(CGFontCopyTableTags(self.as_ptr()))
115         }
116     }
117 
copy_table_for_tag(&self, tag: u32) -> Option<CFData>118     pub fn copy_table_for_tag(&self, tag: u32) -> Option<CFData> {
119         let data_ref = unsafe { CGFontCopyTableForTag(self.as_ptr(), tag) };
120         if data_ref != ptr::null() {
121             Some(unsafe { TCFType::wrap_under_create_rule(data_ref) })
122         } else {
123             None
124         }
125     }
126 }
127 
128 #[link(name = "CoreGraphics", kind = "framework")]
129 extern {
130     // TODO: basically nothing has bindings (even commented-out) besides what we use.
CGFontCreateWithDataProvider(provider: ::sys::CGDataProviderRef) -> ::sys::CGFontRef131     fn CGFontCreateWithDataProvider(provider: ::sys::CGDataProviderRef) -> ::sys::CGFontRef;
CGFontCreateWithFontName(name: CFStringRef) -> ::sys::CGFontRef132     fn CGFontCreateWithFontName(name: CFStringRef) -> ::sys::CGFontRef;
CGFontCreateCopyWithVariations(font: ::sys::CGFontRef, vars: CFDictionaryRef) -> ::sys::CGFontRef133     fn CGFontCreateCopyWithVariations(font: ::sys::CGFontRef, vars: CFDictionaryRef) -> ::sys::CGFontRef;
CGFontGetTypeID() -> CFTypeID134     fn CGFontGetTypeID() -> CFTypeID;
135 
CGFontCopyPostScriptName(font: ::sys::CGFontRef) -> CFStringRef136     fn CGFontCopyPostScriptName(font: ::sys::CGFontRef) -> CFStringRef;
137 
138     // These do the same thing as CFRetain/CFRelease, except
139     // gracefully handle a NULL argument. We don't use them.
140     //fn CGFontRetain(font: ::sys::CGFontRef);
141     //fn CGFontRelease(font: ::sys::CGFontRef);
142 
CGFontGetGlyphBBoxes(font: ::sys::CGFontRef, glyphs: *const CGGlyph, count: size_t, bboxes: *mut CGRect) -> bool143     fn CGFontGetGlyphBBoxes(font: ::sys::CGFontRef,
144                             glyphs: *const CGGlyph,
145                             count: size_t,
146                             bboxes: *mut CGRect)
147                             -> bool;
CGFontGetGlyphAdvances(font: ::sys::CGFontRef, glyphs: *const CGGlyph, count: size_t, advances: *mut c_int) -> bool148     fn CGFontGetGlyphAdvances(font: ::sys::CGFontRef,
149                               glyphs: *const CGGlyph,
150                               count: size_t,
151                               advances: *mut c_int)
152                               -> bool;
CGFontGetUnitsPerEm(font: ::sys::CGFontRef) -> c_int153     fn CGFontGetUnitsPerEm(font: ::sys::CGFontRef) -> c_int;
154 
CGFontCopyTableTags(font: ::sys::CGFontRef) -> CFArrayRef155     fn CGFontCopyTableTags(font: ::sys::CGFontRef) -> CFArrayRef;
CGFontCopyTableForTag(font: ::sys::CGFontRef, tag: u32) -> CFDataRef156     fn CGFontCopyTableForTag(font: ::sys::CGFontRef, tag: u32) -> CFDataRef;
157 }
158