1use core::mem::size_of;
2use core::ptr;
3use core::slice;
4
5use read_fonts::types::F2Dot14;
6use read_fonts::types::GlyphId;
7
8use crate::hb::charmap::Charmap;
9use crate::hb::face::FontKind;
10use crate::hb::face::Scale;
11use crate::hb::glyph_metrics::GlyphMetrics;
12
13use super::buffer::{hb_buffer_t, GlyphInfo, GlyphPosition};
14use super::face::{hb_font_t, GlyphExtents};
15
16#[derive(Clone, Copy, Debug)]
18pub struct RawAdvanceWidthBatch {
19 pub len: usize,
21 pub gids: *const u32,
23 pub advances: *mut i32,
28 pub gid_stride: isize,
30 pub advance_stride: isize,
32}
33
34pub struct AdvanceWidthBatch<'a> {
36 infos: &'a [GlyphInfo],
37 positions: &'a mut [GlyphPosition],
38}
39
40impl<'a> AdvanceWidthBatch<'a> {
41 pub(crate) fn new(buffer: &'a mut hb_buffer_t) -> Self {
42 let len = buffer.len;
43 let infos = &buffer.info[..len];
44 let positions = &mut buffer.pos[..len];
45 Self { infos, positions }
46 }
47
48 pub fn len(&self) -> usize {
50 self.infos.len()
51 }
52
53 pub fn is_empty(&self) -> bool {
55 self.infos.is_empty()
56 }
57
58 pub fn into_raw(self) -> RawAdvanceWidthBatch {
60 if self.infos.is_empty() {
61 return RawAdvanceWidthBatch {
62 len: 0,
63 gids: ptr::null(),
64 advances: ptr::null_mut(),
65 gid_stride: size_of::<GlyphInfo>() as isize,
66 advance_stride: size_of::<GlyphPosition>() as isize,
67 };
68 }
69
70 RawAdvanceWidthBatch {
71 len: self.infos.len(),
72 gids: self.infos.as_ptr().cast::<u32>(),
74 advances: self.positions.as_mut_ptr().cast::<i32>(),
76 gid_stride: size_of::<GlyphInfo>() as isize,
77 advance_stride: size_of::<GlyphPosition>() as isize,
78 }
79 }
80}
81
82pub struct AdvanceWidthBatchIter<'a> {
83 infos: slice::Iter<'a, GlyphInfo>,
84 positions: slice::IterMut<'a, GlyphPosition>,
85}
86
87impl<'a> Iterator for AdvanceWidthBatchIter<'a> {
88 type Item = (GlyphId, &'a mut i32);
89
90 fn next(&mut self) -> Option<Self::Item> {
91 let info = self.infos.next()?;
92 let pos = self.positions.next()?;
93 Some((info.as_glyph(), &mut pos.x_advance))
94 }
95}
96
97impl<'a> IntoIterator for AdvanceWidthBatch<'a> {
98 type Item = (GlyphId, &'a mut i32);
99 type IntoIter = AdvanceWidthBatchIter<'a>;
100
101 fn into_iter(self) -> Self::IntoIter {
102 AdvanceWidthBatchIter {
103 infos: self.infos.iter(),
104 positions: self.positions.iter_mut(),
105 }
106 }
107}
108
109pub struct BuiltinFontFuncs<'a> {
111 face: &'a hb_font_t<'a>,
112 glyph_metrics: core::cell::OnceCell<GlyphMetrics<'a>>,
113 charmap: core::cell::OnceCell<Charmap<'a>>,
114}
115
116impl<'a> BuiltinFontFuncs<'a> {
117 pub(crate) fn new(face: &'a hb_font_t<'a>) -> Self {
118 Self {
119 face,
120 glyph_metrics: core::cell::OnceCell::new(),
121 charmap: core::cell::OnceCell::new(),
122 }
123 }
124
125 fn coords(&self) -> &[F2Dot14] {
126 self.face.ot_tables.coords
127 }
128
129 fn charmap(&self) -> &Charmap<'a> {
130 self.charmap.get_or_init(|| match &self.face.font {
131 FontKind::FontRef(font) => font.charmap.clone(),
132 FontKind::FontInstance(instance, _) => Charmap::from_tables(&instance.tables()),
133 })
134 }
135
136 fn glyph_metrics(&self) -> &GlyphMetrics<'a> {
137 self.glyph_metrics.get_or_init(|| match &self.face.font {
138 FontKind::FontRef(font) => font.glyph_metrics.clone(),
139 FontKind::FontInstance(instance, metrics) => {
140 GlyphMetrics::from_tables(&instance.tables(), metrics)
141 }
142 })
143 }
144
145 pub fn nominal_glyph(&self, c: u32) -> Option<GlyphId> {
147 self.charmap().map(c)
148 }
149
150 pub fn variant_glyph(&self, c: u32, vs: u32) -> Option<GlyphId> {
152 self.charmap().map_variant(c, vs)
153 }
154
155 pub fn advance_width(&self, glyph: GlyphId) -> i32 {
157 self.glyph_metrics()
158 .advance_width(glyph, self.coords())
159 .unwrap_or_default()
160 }
161
162 pub fn advance_height(&self, glyph: GlyphId) -> i32 {
164 -self
165 .glyph_metrics()
166 .advance_height(glyph, self.coords())
167 .unwrap_or(self.face.units_per_em as i32)
168 }
169
170 pub fn vertical_origin(&self, glyph: GlyphId) -> (i32, i32) {
172 let v_origin_y = self
173 .glyph_metrics()
174 .v_origin(glyph, self.coords())
175 .unwrap_or_default();
176 (self.advance_width(glyph) / 2, v_origin_y)
177 }
178
179 pub fn extents(&self, glyph: GlyphId) -> Option<GlyphExtents> {
181 self.glyph_metrics().extents(glyph, self.coords())
182 }
183
184 pub fn populate_advance_widths(&self, batch: AdvanceWidthBatch<'_>) {
186 for (glyph, advance) in batch {
187 *advance = self.advance_width(glyph);
188 }
189 }
190}
191
192pub trait FontFuncs {
205 fn nominal_glyph(&mut self, builtin: &BuiltinFontFuncs, c: u32) -> Option<GlyphId> {
207 builtin.nominal_glyph(c)
208 }
209
210 fn variant_glyph(&mut self, builtin: &BuiltinFontFuncs, c: u32, vs: u32) -> Option<GlyphId> {
212 builtin.variant_glyph(c, vs)
213 }
214
215 fn advance_width(&mut self, builtin: &BuiltinFontFuncs, glyph: GlyphId) -> i32 {
220 builtin.advance_width(glyph)
221 }
222
223 fn populate_advance_widths(
228 &mut self,
229 builtin: &BuiltinFontFuncs,
230 batch: AdvanceWidthBatch<'_>,
231 ) {
232 for (glyph, advance) in batch {
233 *advance = self.advance_width(builtin, glyph);
234 }
235 }
236
237 fn advance_height(&mut self, builtin: &BuiltinFontFuncs, glyph: GlyphId) -> i32 {
242 builtin.advance_height(glyph)
243 }
244
245 fn vertical_origin(&mut self, builtin: &BuiltinFontFuncs, glyph: GlyphId) -> (i32, i32) {
252 builtin.vertical_origin(glyph)
253 }
254
255 fn extents(&mut self, builtin: &BuiltinFontFuncs, glyph: GlyphId) -> Option<GlyphExtents> {
260 builtin.extents(glyph)
261 }
262}
263
264pub(crate) struct FontFuncsDispatch<'a, 'u> {
265 builtin: BuiltinFontFuncs<'a>,
266 scale: Scale,
267 funcs: Option<&'u mut (dyn FontFuncs + 'u)>,
268}
269
270impl<'a, 'u> FontFuncsDispatch<'a, 'u> {
271 pub(crate) fn new(
272 face: &'a hb_font_t<'a>,
273 scale: Scale,
274 funcs: Option<&'u mut (dyn FontFuncs + 'u)>,
275 ) -> Self {
276 Self {
277 builtin: BuiltinFontFuncs::new(face),
278 scale,
279 funcs,
280 }
281 }
282
283 #[inline(always)]
284 pub(crate) fn font(&self) -> &'a hb_font_t<'a> {
285 self.builtin.face
286 }
287
288 #[inline(always)]
289 pub(crate) fn scale(&self) -> &Scale {
290 &self.scale
291 }
292
293 #[inline(always)]
294 fn scale_x(&self, value: i32) -> i32 {
295 self.scale.scale_x(value)
296 }
297
298 #[inline(always)]
299 fn scale_y(&self, value: i32) -> i32 {
300 self.scale.scale_y(value)
301 }
302
303 #[inline(always)]
304 fn scale_point(&self, point: (i32, i32)) -> (i32, i32) {
305 (self.scale_x(point.0), self.scale_y(point.1))
306 }
307
308 #[inline(always)]
309 fn scale_extents(&self, extents: GlyphExtents) -> GlyphExtents {
310 self.scale.scale_extents(extents)
311 }
312
313 #[inline(always)]
314 pub(crate) fn nominal_glyph(&mut self, c: u32) -> Option<GlyphId> {
315 if let Some(funcs) = &mut self.funcs {
316 funcs.nominal_glyph(&self.builtin, c)
317 } else if let Some(gid) = self.builtin.face.cmap_cache.get(c) {
318 Some(gid.into())
319 } else if let Some(gid) = self.builtin.nominal_glyph(c) {
320 let cache = self.builtin.face.cmap_cache;
321 cache.set(c, gid.to_u32());
322 Some(gid)
323 } else {
324 None
325 }
326 }
327
328 #[inline(always)]
329 pub(crate) fn has_glyph(&mut self, c: u32) -> bool {
330 self.nominal_glyph(c).is_some()
331 }
332
333 #[inline(always)]
334 pub(crate) fn variant_glyph(&mut self, c: u32, vs: u32) -> Option<GlyphId> {
335 if let Some(funcs) = &mut self.funcs {
336 funcs.variant_glyph(&self.builtin, c, vs)
337 } else {
338 self.builtin.variant_glyph(c, vs)
339 }
340 }
341
342 #[inline(always)]
343 pub(crate) fn advance_width(&mut self, glyph: GlyphId) -> i32 {
344 if let Some(funcs) = &mut self.funcs {
345 funcs.advance_width(&self.builtin, glyph)
346 } else {
347 self.scale_x(self.builtin.advance_width(glyph))
348 }
349 }
350
351 #[inline(always)]
352 pub(crate) fn advance_height(&mut self, glyph: GlyphId) -> i32 {
353 if let Some(funcs) = &mut self.funcs {
354 funcs.advance_height(&self.builtin, glyph)
355 } else {
356 self.scale_y(self.builtin.advance_height(glyph))
357 }
358 }
359
360 #[inline(always)]
361 pub(crate) fn vertical_origin(&mut self, glyph: GlyphId) -> (i32, i32) {
362 if let Some(funcs) = &mut self.funcs {
363 funcs.vertical_origin(&self.builtin, glyph)
364 } else {
365 self.scale_point(self.builtin.vertical_origin(glyph))
366 }
367 }
368
369 #[inline(always)]
370 pub(crate) fn extents(&mut self, glyph: GlyphId) -> Option<GlyphExtents> {
371 if let Some(funcs) = &mut self.funcs {
372 funcs.extents(&self.builtin, glyph)
373 } else {
374 Some(self.scale_extents(self.builtin.extents(glyph)?))
375 }
376 }
377
378 pub(crate) fn populate_advance_widths(&mut self, batch: AdvanceWidthBatch<'_>) {
379 if let Some(funcs) = &mut self.funcs {
380 funcs.populate_advance_widths(&self.builtin, batch);
381 } else {
382 self.builtin.glyph_metrics().populate_advance_widths(
383 batch.infos,
384 batch.positions,
385 self.builtin.coords(),
386 self.scale,
387 );
388 }
389 }
390}