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