1#![allow(
4 unused_imports,
5 unused_variables,
6 clippy::get_first,
7 clippy::clone_on_copy,
8 clippy::identity_op,
9 clippy::manual_is_multiple_of,
10 clippy::field_reassign_with_default,
11 clippy::needless_borrow,
12 clippy::needless_range_loop,
13 clippy::manual_range_contains,
14 clippy::upper_case_acronyms,
15 clippy::expl_impl_clone_on_copy,
16 clippy::unnecessary_cast,
17 clippy::derivable_impls,
18 mismatched_lifetime_syntaxes
19)]
20
21mod argstack;
22mod cff;
23pub mod charset;
24mod charstring;
25mod dict;
26mod encoding;
27mod index;
28mod parser;
29mod std_names;
30
31pub use cff::{string_by_id, Table};
32pub use encoding::{Encoding, EncodingKind, Format1Range, STANDARD_ENCODING};
33use parser::{FromData, Stream, TryNumFrom};
34pub use std_names::STANDARD_NAMES;
35
36#[derive(Clone, Copy, PartialEq, PartialOrd, Debug)]
38pub struct StringId(pub u16);
39
40impl FromData for StringId {
41 const SIZE: usize = 2;
42
43 #[inline]
44 fn parse(data: &[u8]) -> Option<Self> {
45 u16::parse(data).map(StringId)
46 }
47}
48
49trait IsEven {
50 fn is_odd(&self) -> bool;
51}
52impl IsEven for usize {
53 fn is_odd(&self) -> bool {
54 self & 1 == 1
55 }
56}
57
58#[derive(Clone, Copy, PartialEq, Debug)]
60pub enum CFFError {
61 NoGlyph,
62 ReadOutOfBounds,
63 ZeroBBox,
64 InvalidOperator,
65 UnsupportedOperator,
66 MissingEndChar,
67 DataAfterEndChar,
68 NestingLimitReached,
69 ArgumentsStackLimitReached,
70 InvalidArgumentsStackLength,
71 BboxOverflow,
72 MissingMoveTo,
73 InvalidSubroutineIndex,
74 NoLocalSubroutines,
75 InvalidSeacCode,
76}
77
78#[inline]
79pub fn f64_abs(n: f64) -> f64 {
80 n.abs()
81}
82
83#[inline]
84pub fn conv_subroutine_index(index: f64, bias: u16) -> Result<u32, CFFError> {
85 conv_subroutine_index_impl(index, bias).ok_or(CFFError::InvalidSubroutineIndex)
86}
87
88#[inline]
89fn conv_subroutine_index_impl(index: f64, bias: u16) -> Option<u32> {
90 let index = i32::try_num_from(index)?;
91 let bias = i32::from(bias);
92
93 let index = index.checked_add(bias)?;
94 u32::try_from(index).ok()
95}
96
97#[inline]
99pub fn calc_subroutine_bias(len: u32) -> u16 {
100 if len < 1240 {
101 107
102 } else if len < 33900 {
103 1131
104 } else {
105 32768
106 }
107}
108
109pub trait OutlineBuilder {
111 fn move_to(&mut self, x: f32, y: f32);
115
116 fn line_to(&mut self, x: f32, y: f32);
118
119 fn quad_to(&mut self, x1: f32, y1: f32, x: f32, y: f32);
121
122 fn curve_to(&mut self, x1: f32, y1: f32, x2: f32, y2: f32, x: f32, y: f32);
124
125 fn close(&mut self);
129}
130
131struct DummyOutline;
132impl OutlineBuilder for DummyOutline {
133 fn move_to(&mut self, _: f32, _: f32) {}
134 fn line_to(&mut self, _: f32, _: f32) {}
135 fn quad_to(&mut self, _: f32, _: f32, _: f32, _: f32) {}
136 fn curve_to(&mut self, _: f32, _: f32, _: f32, _: f32, _: f32, _: f32) {}
137 fn close(&mut self) {}
138}
139
140pub(crate) struct Builder<'a> {
141 builder: &'a mut dyn OutlineBuilder,
142 bbox: RectF,
143}
144
145impl<'a> Builder<'a> {
146 #[inline]
147 fn move_to(&mut self, x: f64, y: f64) {
148 let x = x as f32;
149 let y = y as f32;
150 self.bbox.extend_by(x, y);
151 self.builder.move_to(x, y);
152 }
153
154 #[inline]
155 fn line_to(&mut self, x: f64, y: f64) {
156 let x = x as f32;
157 let y = y as f32;
158 self.bbox.extend_by(x, y);
159 self.builder.line_to(x, y);
160 }
161
162 #[inline]
163 fn curve_to(&mut self, x1: f64, y1: f64, x2: f64, y2: f64, x: f64, y: f64) {
164 let x1 = x1 as f32;
165 let y1 = y1 as f32;
166 let x2 = x2 as f32;
167 let y2 = y2 as f32;
168 let x = x as f32;
169 let y = y as f32;
170 self.bbox.extend_by(x1, y1);
171 self.bbox.extend_by(x2, y2);
172 self.bbox.extend_by(x, y);
173 self.builder.curve_to(x1, y1, x2, y2, x, y);
174 }
175
176 #[inline]
177 fn close(&mut self) {
178 self.builder.close();
179 }
180}
181#[repr(C)]
185#[allow(missing_docs)]
186#[derive(Clone, Copy, PartialEq, Eq, Debug)]
187pub struct Rect {
188 pub x_min: i16,
189 pub y_min: i16,
190 pub x_max: i16,
191 pub y_max: i16,
192}
193
194impl Rect {
195 #[inline]
196 fn zero() -> Self {
197 Self {
198 x_min: 0,
199 y_min: 0,
200 x_max: 0,
201 y_max: 0,
202 }
203 }
204
205 #[inline]
207 pub fn width(&self) -> i16 {
208 self.x_max - self.x_min
209 }
210
211 #[inline]
213 pub fn height(&self) -> i16 {
214 self.y_max - self.y_min
215 }
216}
217
218#[derive(Clone, Copy, Debug, PartialEq)]
220pub struct RectF {
221 pub x_min: f32,
223 pub y_min: f32,
225 pub x_max: f32,
227 pub y_max: f32,
229}
230
231impl RectF {
232 #[inline]
233 fn new() -> Self {
234 RectF {
235 x_min: f32::MAX,
236 y_min: f32::MAX,
237 x_max: f32::MIN,
238 y_max: f32::MIN,
239 }
240 }
241
242 #[inline]
243 fn is_default(&self) -> bool {
244 self.x_min == f32::MAX
245 && self.y_min == f32::MAX
246 && self.x_max == f32::MIN
247 && self.y_max == f32::MIN
248 }
249
250 #[inline]
251 fn extend_by(&mut self, x: f32, y: f32) {
252 self.x_min = self.x_min.min(x);
253 self.y_min = self.y_min.min(y);
254 self.x_max = self.x_max.max(x);
255 self.y_max = self.y_max.max(y);
256 }
257
258 #[inline]
259 fn to_rect(self) -> Option<Rect> {
260 Some(Rect {
261 x_min: i16::try_num_from(self.x_min)?,
262 y_min: i16::try_num_from(self.y_min)?,
263 x_max: i16::try_num_from(self.x_max)?,
264 y_max: i16::try_num_from(self.y_max)?,
265 })
266 }
267}
268
269#[repr(transparent)]
271#[derive(Clone, Copy, Ord, PartialOrd, Eq, PartialEq, Default, Debug)]
272pub struct GlyphId(pub u16);
273
274impl FromData for GlyphId {
275 const SIZE: usize = 2;
276
277 #[inline]
278 fn parse(data: &[u8]) -> Option<Self> {
279 u16::parse(data).map(GlyphId)
280 }
281}