| 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<'face>| 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<'face>| 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 | |