ndless_freetype/
glyph.rs

1use crate::{ffi, BBox, BitmapGlyph, FtResult, Matrix, RenderMode, Stroker, Vector};
2use std::ptr::null_mut;
3
4/// Represents a retrieved glyph from the library
5///
6/// Note that when this glyph is dropped, so is the library
7pub struct Glyph {
8	library_raw: ffi::FT_Library,
9	raw: ffi::FT_Glyph,
10}
11
12impl Glyph {
13	/// Create a freetype-rs glyph object from c constituent parts
14	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	/// Transform a glyph image if its format is scalable.
20	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	/// Return a glyph's ‘control box’. The control box encloses all the outline's points,
39	/// including Bézier control points. Though it coincides with the exact bounding box for most
40	/// glyphs, it can be slightly larger in some situations (like when rotating an outline that
41	/// contains Bézier outside arcs).
42	///
43	/// Computing the control box is very fast, while getting the bounding box can take much more
44	/// time as it needs to walk over all segments and arcs in the outline. To get the latter, you
45	/// can use the ‘ftbbox’ component, which is dedicated to this single task.
46	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	/// Convert a given glyph object to a bitmap glyph object.
58	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	/// An enumeration type used to describe the format of a given glyph image. Note that this
124	/// version of FreeType only supports two image formats, even though future font drivers will
125	/// be able to register their own format.
126	#[inline(always)]
127	pub fn format(&self) -> ffi::FT_Glyph_Format {
128		unsafe { (*self.raw).format }
129	}
130
131	/// Get the underlying c glyph struct (The system actually calls this a GlyphRec because it can
132	/// be a different struct in different circumstances)
133	#[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}