ab_glyph/glyph.rs
1use crate::{Point, PxScale};
2
3/// Glyph id.
4///
5/// # Example
6/// ```
7/// use ab_glyph::{Font, FontRef, GlyphId};
8/// # fn main() -> Result<(), ab_glyph::InvalidFont> {
9/// let font = FontRef::try_from_slice(include_bytes!("../../dev/fonts/Exo2-Light.otf"))?;
10///
11/// let q_id: GlyphId = font.glyph_id('q');
12/// # Ok(()) }
13/// ```
14#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
15pub struct GlyphId(pub u16);
16
17impl GlyphId {
18 /// Construct a `Glyph` with given scale & position.
19 ///
20 /// # Example
21 /// ```
22 /// # use ab_glyph::*;
23 /// # let font = FontRef::try_from_slice(include_bytes!("../../dev/fonts/Exo2-Light.otf")).unwrap();
24 /// let glyph = font.glyph_id('z').with_scale_and_position(24.0, point(100.0, 0.0));
25 /// ```
26 #[inline]
27 pub fn with_scale_and_position<S: Into<PxScale>, P: Into<Point>>(
28 self,
29 scale: S,
30 position: P,
31 ) -> Glyph {
32 Glyph {
33 id: self,
34 scale: scale.into(),
35 position: position.into(),
36 }
37 }
38
39 /// Construct a `Glyph` with given scale and position `point(0.0, 0.0)`.
40 ///
41 /// # Example
42 /// ```
43 /// # use ab_glyph::*;
44 /// # let font = FontRef::try_from_slice(include_bytes!("../../dev/fonts/Exo2-Light.otf")).unwrap();
45 /// let glyph = font.glyph_id('w').with_scale(48.0);
46 /// ```
47 #[inline]
48 pub fn with_scale<S: Into<PxScale>>(self, scale: S) -> Glyph {
49 self.with_scale_and_position(scale, Point::default())
50 }
51}
52
53/// A glyph with pixel scale & position.
54#[derive(Clone, Debug, PartialEq, PartialOrd)]
55pub struct Glyph {
56 /// Glyph id.
57 pub id: GlyphId,
58 /// Pixel scale of this glyph.
59 pub scale: PxScale,
60 /// Position of this glyph.
61 ///
62 /// This point, relative to the glyph, is to the left before applying
63 /// `h_advance` or `h_side_bearing` & vertically at the "baseline".
64 /// See [glyph layout concepts](trait.Font.html#glyph-layout-concepts).
65 pub position: Point,
66}
67
68/// Old version of [`v2::GlyphImage`].
69#[deprecated(since = "0.2.22", note = "Deprecated in favor of `v2::GlyphImage`")]
70#[derive(Debug, Clone)]
71pub struct GlyphImage<'a> {
72 /// Offset of the image from the normal origin (top at the baseline plus
73 /// ascent), measured in pixels at the image's current scale.
74 pub origin: Point,
75 /// Current scale of the image in pixels per em.
76 pub scale: f32,
77 /// Raw image data, not a bitmap in the case of [`GlyphImageFormat::Png`] format.
78 pub data: &'a [u8],
79 /// Format of the raw data.
80 pub format: GlyphImageFormat,
81}
82
83#[derive(Debug, Clone)]
84#[non_exhaustive]
85pub struct GlyphSvg<'a> {
86 /// Raw image data, it should be rendered or decompressed (in case of SVGZ)
87 /// by the caller.. Note that the data includes records for multiple Glyphs.
88 pub data: &'a [u8],
89 /// The first glyph ID for the range covered by this record.
90 pub start_glyph_id: GlyphId,
91 /// The last glyph ID, *inclusive*, for the range covered by this record.
92 pub end_glyph_id: GlyphId,
93}
94
95pub mod v2 {
96 use crate::{GlyphImageFormat, Point};
97
98 /// A pre-rendered image of a glyph, usually used for emojis or other glyphs
99 /// that can't be represented only using an outline.
100 #[non_exhaustive]
101 #[derive(Debug, Clone)]
102 pub struct GlyphImage<'a> {
103 /// Offset of the image from the normal origin (top at the baseline plus
104 /// ascent), measured in pixels at the image's current scale.
105 pub origin: Point,
106 /// Image width.
107 ///
108 /// It doesn't guarantee that this value is the same as set in the `data` in the case of
109 /// [`GlyphImageFormat::Png`] format.
110 pub width: u16,
111 /// Image height.
112 ///
113 /// It doesn't guarantee that this value is the same as set in the `data` in the case of
114 /// [`GlyphImageFormat::Png`] format.
115 pub height: u16,
116 /// Pixels per em of the selected strike.
117 pub pixels_per_em: u16,
118 /// Raw image data, see [`format`](GlyphImageFormat).
119 pub data: &'a [u8],
120 /// Format of the raw [`data`](Self::data).
121 pub format: GlyphImageFormat,
122 }
123}
124
125/// Valid formats for a [`GlyphImage`].
126// Possible future formats: SVG, JPEG, TIFF
127#[non_exhaustive]
128#[derive(Debug, Clone)]
129pub enum GlyphImageFormat {
130 Png,
131
132 /// A monochrome bitmap.
133 ///
134 /// The most significant bit of the first byte corresponds to the top-left pixel, proceeding
135 /// through succeeding bits moving left to right. The data for each row is padded to a byte
136 /// boundary, so the next row begins with the most significant bit of a new byte. 1 corresponds
137 /// to black, and 0 to white.
138 BitmapMono,
139
140 /// A packed monochrome bitmap.
141 ///
142 /// The most significant bit of the first byte corresponds to the top-left pixel, proceeding
143 /// through succeeding bits moving left to right. Data is tightly packed with no padding. 1
144 /// corresponds to black, and 0 to white.
145 BitmapMonoPacked,
146
147 /// A grayscale bitmap with 2 bits per pixel.
148 ///
149 /// The most significant bits of the first byte corresponds to the top-left pixel, proceeding
150 /// through succeeding bits moving left to right. The data for each row is padded to a byte
151 /// boundary, so the next row begins with the most significant bit of a new byte.
152 BitmapGray2,
153
154 /// A packed grayscale bitmap with 2 bits per pixel.
155 ///
156 /// The most significant bits of the first byte corresponds to the top-left pixel, proceeding
157 /// through succeeding bits moving left to right. Data is tightly packed with no padding.
158 BitmapGray2Packed,
159
160 /// A grayscale bitmap with 4 bits per pixel.
161 ///
162 /// The most significant bits of the first byte corresponds to the top-left pixel, proceeding
163 /// through succeeding bits moving left to right. The data for each row is padded to a byte
164 /// boundary, so the next row begins with the most significant bit of a new byte.
165 BitmapGray4,
166
167 /// A packed grayscale bitmap with 4 bits per pixel.
168 ///
169 /// The most significant bits of the first byte corresponds to the top-left pixel, proceeding
170 /// through succeeding bits moving left to right. Data is tightly packed with no padding.
171 BitmapGray4Packed,
172
173 /// A grayscale bitmap with 8 bits per pixel.
174 ///
175 /// The first byte corresponds to the top-left pixel, proceeding through succeeding bytes
176 /// moving left to right.
177 BitmapGray8,
178
179 /// A color bitmap with 32 bits per pixel.
180 ///
181 /// The first group of four bytes corresponds to the top-left pixel, proceeding through
182 /// succeeding pixels moving left to right. Each byte corresponds to a color channel and the
183 /// channels within a pixel are in blue, green, red, alpha order. Color values are
184 /// pre-multiplied by the alpha. For example, the color "full-green with half translucency"
185 /// is encoded as `\x00\x80\x00\x80`, and not `\x00\xFF\x00\x80`.
186 BitmapPremulBgra32,
187}