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