1 | use 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)] |
15 | pub struct GlyphId(pub u16); |
16 | |
17 | impl 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)] |
55 | pub 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)] |
71 | pub 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 ] |
85 | pub 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 | |
95 | pub 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)] |
129 | pub 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 | } |
188 | |