core_graphics/
font.rs

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
10use crate::data_provider::CGDataProvider;
11use crate::geometry::CGRect;
12use core_foundation::array::{CFArray, CFArrayRef};
13use core_foundation::base::{CFRelease, CFRetain, CFType, CFTypeID, TCFType};
14use core_foundation::data::{CFData, CFDataRef};
15use core_foundation::dictionary::{CFDictionary, CFDictionaryRef};
16use core_foundation::number::CFNumber;
17use core_foundation::string::{CFString, CFStringRef};
18use std::ptr::NonNull;
19
20use foreign_types::{foreign_type, ForeignType};
21
22use libc::{c_int, size_t};
23
24pub use core_graphics_types::base::CGGlyph;
25
26foreign_type! {
27    #[doc(hidden)]
28    pub unsafe type CGFont: Send + Sync {
29        type CType = crate::sys::CGFont;
30        fn drop = |p| CFRelease(p as *mut _);
31        fn clone = |p| CFRetain(p as *const _) as *mut _;
32    }
33}
34
35impl CGFont {
36    pub fn type_id() -> CFTypeID {
37        unsafe { CGFontGetTypeID() }
38    }
39
40    pub fn from_data_provider(provider: CGDataProvider) -> Result<CGFont, ()> {
41        unsafe {
42            let font_ref = CGFontCreateWithDataProvider(provider.as_ptr());
43            match NonNull::new(font_ref) {
44                Some(font_ref) => Ok(CGFont(font_ref)),
45                None => Err(()),
46            }
47        }
48    }
49
50    pub fn from_name(name: &CFString) -> Result<CGFont, ()> {
51        unsafe {
52            let font_ref = CGFontCreateWithFontName(name.as_concrete_TypeRef());
53            match NonNull::new(font_ref) {
54                Some(font_ref) => Ok(CGFont(font_ref)),
55                None => Err(()),
56            }
57        }
58    }
59
60    pub fn create_copy_from_variations(
61        &self,
62        vars: &CFDictionary<CFString, CFNumber>,
63    ) -> Result<CGFont, ()> {
64        unsafe {
65            let font_ref =
66                CGFontCreateCopyWithVariations(self.as_ptr(), vars.as_concrete_TypeRef());
67            match NonNull::new(font_ref) {
68                Some(font_ref) => Ok(CGFont(font_ref)),
69                None => Err(()),
70            }
71        }
72    }
73
74    pub fn postscript_name(&self) -> CFString {
75        unsafe {
76            let string_ref = CGFontCopyPostScriptName(self.as_ptr());
77            TCFType::wrap_under_create_rule(string_ref)
78        }
79    }
80
81    pub fn get_glyph_b_boxes(&self, glyphs: &[CGGlyph], bboxes: &mut [CGRect]) -> bool {
82        unsafe {
83            assert!(bboxes.len() >= glyphs.len());
84            CGFontGetGlyphBBoxes(
85                self.as_ptr(),
86                glyphs.as_ptr(),
87                glyphs.len(),
88                bboxes.as_mut_ptr(),
89            )
90        }
91    }
92
93    pub fn get_glyph_advances(&self, glyphs: &[CGGlyph], advances: &mut [c_int]) -> bool {
94        unsafe {
95            assert!(advances.len() >= glyphs.len());
96            CGFontGetGlyphAdvances(
97                self.as_ptr(),
98                glyphs.as_ptr(),
99                glyphs.len(),
100                advances.as_mut_ptr(),
101            )
102        }
103    }
104
105    pub fn ascent(&self) -> c_int {
106        unsafe { CGFontGetAscent(self.as_ptr()) }
107    }
108
109    pub fn descent(&self) -> c_int {
110        unsafe { CGFontGetDescent(self.as_ptr()) }
111    }
112
113    pub fn leading(&self) -> c_int {
114        unsafe { CGFontGetLeading(self.as_ptr()) }
115    }
116
117    pub fn cap_height(&self) -> c_int {
118        unsafe { CGFontGetCapHeight(self.as_ptr()) }
119    }
120
121    pub fn x_height(&self) -> c_int {
122        unsafe { CGFontGetXHeight(self.as_ptr()) }
123    }
124
125    pub fn get_units_per_em(&self) -> c_int {
126        unsafe { CGFontGetUnitsPerEm(self.as_ptr()) }
127    }
128
129    pub fn copy_table_tags(&self) -> CFArray<u32> {
130        unsafe { TCFType::wrap_under_create_rule(CGFontCopyTableTags(self.as_ptr())) }
131    }
132
133    pub fn copy_table_for_tag(&self, tag: u32) -> Option<CFData> {
134        let data_ref = unsafe { CGFontCopyTableForTag(self.as_ptr(), tag) };
135        if !data_ref.is_null() {
136            Some(unsafe { TCFType::wrap_under_create_rule(data_ref) })
137        } else {
138            None
139        }
140    }
141
142    pub fn copy_variations(&self) -> Option<CFDictionary<CFString, CFNumber>> {
143        let variations = unsafe { CGFontCopyVariations(self.as_ptr()) };
144        if !variations.is_null() {
145            Some(unsafe { TCFType::wrap_under_create_rule(variations) })
146        } else {
147            None
148        }
149    }
150
151    pub fn copy_variation_axes(&self) -> Option<CFArray<CFDictionary<CFString, CFType>>> {
152        let axes = unsafe { CGFontCopyVariationAxes(self.as_ptr()) };
153        if !axes.is_null() {
154            Some(unsafe { TCFType::wrap_under_create_rule(axes) })
155        } else {
156            None
157        }
158    }
159}
160
161#[cfg_attr(feature = "link", link(name = "CoreGraphics", kind = "framework"))]
162extern "C" {
163    // TODO: basically nothing has bindings (even commented-out) besides what we use.
164    fn CGFontCreateWithDataProvider(
165        provider: crate::sys::CGDataProviderRef,
166    ) -> crate::sys::CGFontRef;
167    fn CGFontCreateWithFontName(name: CFStringRef) -> crate::sys::CGFontRef;
168    fn CGFontCreateCopyWithVariations(
169        font: crate::sys::CGFontRef,
170        vars: CFDictionaryRef,
171    ) -> crate::sys::CGFontRef;
172    fn CGFontGetTypeID() -> CFTypeID;
173
174    fn CGFontCopyPostScriptName(font: crate::sys::CGFontRef) -> CFStringRef;
175
176    // These do the same thing as CFRetain/CFRelease, except
177    // gracefully handle a NULL argument. We don't use them.
178    //fn CGFontRetain(font: ::sys::CGFontRef);
179    //fn CGFontRelease(font: ::sys::CGFontRef);
180
181    fn CGFontGetGlyphBBoxes(
182        font: crate::sys::CGFontRef,
183        glyphs: *const CGGlyph,
184        count: size_t,
185        bboxes: *mut CGRect,
186    ) -> bool;
187    fn CGFontGetGlyphAdvances(
188        font: crate::sys::CGFontRef,
189        glyphs: *const CGGlyph,
190        count: size_t,
191        advances: *mut c_int,
192    ) -> bool;
193
194    fn CGFontGetAscent(font: crate::sys::CGFontRef) -> c_int;
195    fn CGFontGetDescent(font: crate::sys::CGFontRef) -> c_int;
196    fn CGFontGetLeading(font: crate::sys::CGFontRef) -> c_int;
197    fn CGFontGetCapHeight(font: crate::sys::CGFontRef) -> c_int;
198    fn CGFontGetXHeight(font: crate::sys::CGFontRef) -> c_int;
199    fn CGFontGetUnitsPerEm(font: crate::sys::CGFontRef) -> c_int;
200
201    fn CGFontCopyTableTags(font: crate::sys::CGFontRef) -> CFArrayRef;
202    fn CGFontCopyTableForTag(font: crate::sys::CGFontRef, tag: u32) -> CFDataRef;
203    fn CGFontCopyVariations(font: crate::sys::CGFontRef) -> CFDictionaryRef;
204    fn CGFontCopyVariationAxes(font: crate::sys::CGFontRef) -> CFArrayRef;
205}