1use 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 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 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}