1 | //! Logic to avoid re-parsing subtables in ttf_parser::Face methods |
2 | use crate::{AsFaceRef, FaceMut, OwnedFace}; |
3 | #[cfg (not(feature = "std" ))] |
4 | use alloc::vec::Vec; |
5 | use core::fmt; |
6 | use ttf_parser::{cmap, kern, Face, GlyphId}; |
7 | |
8 | /// A `Face` with cmap & kern subtables parsed once on initialization. |
9 | /// |
10 | /// Provides much faster [`PreParsedSubtables::glyph_index`] & |
11 | /// [`PreParsedSubtables::glyphs_hor_kerning`] methods compared to the |
12 | /// `.as_face_ref()` equivalents that must parse their subtables on each call. |
13 | /// |
14 | /// # Example |
15 | /// ``` |
16 | /// use owned_ttf_parser::{AsFaceRef, GlyphId, OwnedFace, PreParsedSubtables}; |
17 | /// |
18 | /// # let owned_font_data = include_bytes!("../fonts/font.ttf" ).to_vec(); |
19 | /// let owned_face = OwnedFace::from_vec(owned_font_data, 0).unwrap(); |
20 | /// let faster_face = PreParsedSubtables::from(owned_face); |
21 | /// |
22 | /// // Lookup a GlyphId using the pre-parsed cmap subtables |
23 | /// // this is much faster than doing: .as_face_ref().glyph_index('x') |
24 | /// assert_eq!(faster_face.glyph_index('x' ), Some(GlyphId(91))); |
25 | /// |
26 | /// // The rest of the methods are still available as normal |
27 | /// assert_eq!(faster_face.as_face_ref().ascender(), 2254); |
28 | /// ``` |
29 | #[derive (Clone)] |
30 | pub struct PreParsedSubtables<'face, F> { |
31 | /// Underlying face. |
32 | pub face: F, |
33 | // note must not be public as could be self-referencing |
34 | pub(crate) subtables: FaceSubtables<'face>, |
35 | } |
36 | |
37 | impl<'face> From<Face<'face>> for PreParsedSubtables<'face, Face<'face>> { |
38 | fn from(face: Face<'face>) -> Self { |
39 | let subtables: FaceSubtables<'_> = FaceSubtables::from(&face); |
40 | Self { face, subtables } |
41 | } |
42 | } |
43 | |
44 | impl From<OwnedFace> for PreParsedSubtables<'static, OwnedFace> { |
45 | fn from(face: OwnedFace) -> Self { |
46 | face.pre_parse_subtables() |
47 | } |
48 | } |
49 | |
50 | impl<F> fmt::Debug for PreParsedSubtables<'_, F> { |
51 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
52 | write!(f, "PreParsedSubtables" ) |
53 | } |
54 | } |
55 | |
56 | #[derive (Clone)] |
57 | pub(crate) struct FaceSubtables<'face> { |
58 | /// Unicode cmap subtables. |
59 | cmap: Vec<cmap::Subtable<'face>>, |
60 | /// Horizontal kern subtables. |
61 | h_kern: Vec<kern::Subtable<'face>>, |
62 | } |
63 | |
64 | impl<'face> From<&Face<'face>> for FaceSubtables<'face> { |
65 | fn from(face: &Face<'face>) -> Self { |
66 | let cmap: Vec> = faceimpl Iterator- >
|
67 | .tables() |
68 | .cmap |
69 | .iter() |
70 | .flat_map(|cmap: &Table<'_>| cmap.subtables) |
71 | .filter(|st: &Subtable<'_>| st.is_unicode()) |
72 | .collect(); |
73 | let h_kern: Vec> = faceimpl Iterator- >
|
74 | .tables() |
75 | .kern |
76 | .iter() |
77 | .flat_map(|c: &Table<'_>| c.subtables) |
78 | .filter(|st: &Subtable<'_>| st.horizontal && !st.variable) |
79 | .collect(); |
80 | Self { cmap, h_kern } |
81 | } |
82 | } |
83 | |
84 | impl<F> PreParsedSubtables<'_, F> { |
85 | /// Maps a character to a `GlyphId` using pre-parsed unicode cmap subtables. |
86 | #[inline ] |
87 | pub fn glyph_index(&self, c: char) -> Option<GlyphId> { |
88 | self.subtables |
89 | .cmap |
90 | .iter() |
91 | .find_map(|t| t.glyph_index(c.into())) |
92 | } |
93 | |
94 | /// Maps a variation of a character to a `GlyphId` using pre-parsed unicode cmap subtables. |
95 | #[inline ] |
96 | pub fn glyph_variation_index(&self, c: char, v: char) -> Option<GlyphId> { |
97 | self.subtables |
98 | .cmap |
99 | .iter() |
100 | .find_map(|t| t.glyph_variation_index(c.into(), v.into())) |
101 | .and_then(|r| match r { |
102 | cmap::GlyphVariationResult::Found(v) => Some(v), |
103 | cmap::GlyphVariationResult::UseDefault => self.glyph_index(c), |
104 | }) |
105 | } |
106 | |
107 | /// Returns horizontal kerning for a pair of glyphs using pre-parsed kern subtables. |
108 | #[inline ] |
109 | pub fn glyphs_hor_kerning(&self, first: GlyphId, second: GlyphId) -> Option<i16> { |
110 | self.subtables |
111 | .h_kern |
112 | .iter() |
113 | .find_map(|st| st.glyphs_kerning(first, second)) |
114 | } |
115 | } |
116 | |
117 | impl<F> AsFaceRef for PreParsedSubtables<'_, F> |
118 | where |
119 | F: AsFaceRef, |
120 | { |
121 | #[inline ] |
122 | fn as_face_ref(&self) -> &ttf_parser::Face<'_> { |
123 | self.face.as_face_ref() |
124 | } |
125 | } |
126 | impl<F> AsFaceRef for &PreParsedSubtables<'_, F> |
127 | where |
128 | F: AsFaceRef, |
129 | { |
130 | #[inline ] |
131 | fn as_face_ref(&self) -> &ttf_parser::Face<'_> { |
132 | (*self).as_face_ref() |
133 | } |
134 | } |
135 | |
136 | impl<F> FaceMut for PreParsedSubtables<'_, F> |
137 | where |
138 | F: FaceMut, |
139 | { |
140 | #[inline ] |
141 | fn set_variation(&mut self, axis: ttf_parser::Tag, value: f32) -> Option<()> { |
142 | self.face.set_variation(axis, value) |
143 | } |
144 | } |
145 | impl<F> FaceMut for &mut PreParsedSubtables<'_, F> |
146 | where |
147 | F: FaceMut, |
148 | { |
149 | #[inline ] |
150 | fn set_variation(&mut self, axis: ttf_parser::Tag, value: f32) -> Option<()> { |
151 | (*self).set_variation(axis, value) |
152 | } |
153 | } |
154 | |