1use crate::{ffi, BBox, BitmapGlyph, FtResult, Matrix, RenderMode, Stroker, Vector};
2use std::ptr::null_mut;
3
4pub struct Glyph {
8 library_raw: ffi::FT_Library,
9 raw: ffi::FT_Glyph,
10}
11
12impl Glyph {
13 pub unsafe fn from_raw(library_raw: ffi::FT_Library, raw: ffi::FT_Glyph) -> Self {
15 ffi::FT_Reference_Library(library_raw);
16 Glyph { library_raw, raw }
17 }
18
19 pub fn transform(&self, mut matrix: Option<Matrix>, mut delta: Option<Vector>) -> FtResult<()> {
21 let mut p_matrix = null_mut();
22 let mut p_delta = null_mut();
23
24 if let Some(ref mut m) = matrix {
25 p_matrix = m as *mut Matrix;
26 }
27 if let Some(ref mut d) = delta {
28 p_delta = d as *mut Vector;
29 }
30 let err = unsafe { ffi::FT_Glyph_Transform(self.raw, p_matrix, p_delta) };
31 if err == ffi::FT_Err_Ok {
32 Ok(())
33 } else {
34 Err(err.into())
35 }
36 }
37
38 pub fn get_cbox(&self, bbox_mode: ffi::FT_Glyph_BBox_Mode) -> BBox {
47 let mut acbox = ffi::FT_BBox {
48 xMin: 0,
49 yMin: 0,
50 xMax: 0,
51 yMax: 0,
52 };
53 unsafe { ffi::FT_Glyph_Get_CBox(self.raw, bbox_mode, &mut acbox) };
54 acbox
55 }
56
57 pub fn to_bitmap(
59 &self,
60 render_mode: RenderMode,
61 mut origin: Option<Vector>,
62 ) -> FtResult<BitmapGlyph> {
63 let mut the_glyph = self.raw;
64 let mut p_origin = null_mut();
65
66 if let Some(ref mut o) = origin {
67 p_origin = o as *mut Vector;
68 }
69 let err =
70 unsafe { ffi::FT_Glyph_To_Bitmap(&mut the_glyph, render_mode as u32, p_origin, 0) };
71 if err == ffi::FT_Err_Ok {
72 Ok(
73 unsafe {
74 BitmapGlyph::from_raw(self.library_raw, the_glyph as ffi::FT_BitmapGlyph)
75 },
76 )
77 } else {
78 Err(err.into())
79 }
80 }
81
82 pub fn stroke(&self, stroker: &Stroker) -> FtResult<Glyph> {
83 let mut the_glyph = self.raw;
84
85 let err = unsafe {
86 ffi::FT_Glyph_Stroke(&mut the_glyph, stroker.raw_stroker(), false as ffi::FT_Bool)
87 };
88
89 if err == ffi::FT_Err_Ok {
90 Ok(unsafe { Glyph::from_raw(self.library_raw, the_glyph) })
91 } else {
92 Err(err.into())
93 }
94 }
95
96 pub fn stroke_border(&self, stroker: &Stroker, inside: bool) -> FtResult<Glyph> {
97 let mut the_glyph = self.raw;
98
99 let err = unsafe {
100 ffi::FT_Glyph_StrokeBorder(
101 &mut the_glyph,
102 stroker.raw_stroker(),
103 inside as ffi::FT_Bool,
104 false as ffi::FT_Bool,
105 )
106 };
107
108 if err == ffi::FT_Err_Ok {
109 Ok(unsafe { Glyph::from_raw(self.library_raw, the_glyph) })
110 } else {
111 Err(err.into())
112 }
113 }
114
115 pub fn advance_x(&self) -> isize {
116 unsafe { (*self.raw).advance.x as isize }
117 }
118
119 pub fn advance_y(&self) -> isize {
120 unsafe { (*self.raw).advance.y as isize }
121 }
122
123 #[inline(always)]
127 pub fn format(&self) -> ffi::FT_Glyph_Format {
128 unsafe { (*self.raw).format }
129 }
130
131 #[inline(always)]
134 pub fn raw(&self) -> &ffi::FT_GlyphRec {
135 unsafe { &*self.raw }
136 }
137}
138
139impl Clone for Glyph {
140 fn clone(&self) -> Self {
141 let mut target = null_mut();
142
143 let err = unsafe { ffi::FT_Glyph_Copy(self.raw, &mut target) };
144 if err == ffi::FT_Err_Ok {
145 unsafe { Glyph::from_raw(self.library_raw, target) }
146 } else {
147 panic!("Failed to copy glyph")
148 }
149 }
150}
151
152impl Drop for Glyph {
153 fn drop(&mut self) {
154 let err = unsafe {
155 ffi::FT_Done_Glyph(self.raw);
156 ffi::FT_Done_Library(self.library_raw)
157 };
158 if err != ffi::FT_Err_Ok {
159 panic!("Failed to drop library")
160 }
161 }
162}