cff_parser/
lib.rs

1mod parser;
2mod index;
3pub mod charset;
4mod charstring;
5mod dict;
6mod argstack;
7mod std_names;
8mod encoding;
9mod cff;
10
11pub use cff::{Table, string_by_id};
12use parser::{FromData, Stream, TryNumFrom};
13pub use encoding::{Encoding, EncodingKind, Format1Range, STANDARD_ENCODING};
14
15/// A type-safe wrapper for string ID.
16#[derive(Clone, Copy, PartialEq, PartialOrd, Debug)]
17pub struct StringId(u16);
18
19impl FromData for StringId {
20    const SIZE: usize = 2;
21
22    #[inline]
23    fn parse(data: &[u8]) -> Option<Self> {
24        u16::parse(data).map(StringId)
25    }
26}
27
28trait IsEven {
29    fn is_odd(&self) -> bool;
30}
31impl IsEven for usize {
32    fn is_odd(&self) -> bool {
33        self & 1 == 1
34    }
35}
36
37/// A list of errors that can occur during a CFF table parsing.
38#[derive(Clone, Copy, PartialEq, Debug)]
39pub enum CFFError {
40    NoGlyph,
41    ReadOutOfBounds,
42    ZeroBBox,
43    InvalidOperator,
44    UnsupportedOperator,
45    MissingEndChar,
46    DataAfterEndChar,
47    NestingLimitReached,
48    ArgumentsStackLimitReached,
49    InvalidArgumentsStackLength,
50    BboxOverflow,
51    MissingMoveTo,
52    InvalidSubroutineIndex,
53    NoLocalSubroutines,
54    InvalidSeacCode,
55}
56
57
58#[inline]
59pub fn f32_abs(n: f32) -> f32 {
60    n.abs()
61}
62
63
64#[inline]
65pub fn conv_subroutine_index(index: f32, bias: u16) -> Result<u32, CFFError> {
66    conv_subroutine_index_impl(index, bias).ok_or(CFFError::InvalidSubroutineIndex)
67}
68
69#[inline]
70fn conv_subroutine_index_impl(index: f32, bias: u16) -> Option<u32> {
71    let index = i32::try_num_from(index)?;
72    let bias = i32::from(bias);
73
74    let index = index.checked_add(bias)?;
75    u32::try_from(index).ok()
76}
77
78// Adobe Technical Note #5176, Chapter 16 "Local / Global Subrs INDEXes"
79#[inline]
80pub fn calc_subroutine_bias(len: u32) -> u16 {
81    if len < 1240 {
82        107
83    } else if len < 33900 {
84        1131
85    } else {
86        32768
87    }
88}
89
90/// A trait for glyph outline construction.
91pub trait OutlineBuilder {
92    /// Appends a MoveTo segment.
93    ///
94    /// Start of a contour.
95    fn move_to(&mut self, x: f32, y: f32);
96
97    /// Appends a LineTo segment.
98    fn line_to(&mut self, x: f32, y: f32);
99
100    /// Appends a QuadTo segment.
101    fn quad_to(&mut self, x1: f32, y1: f32, x: f32, y: f32);
102
103    /// Appends a CurveTo segment.
104    fn curve_to(&mut self, x1: f32, y1: f32, x2: f32, y2: f32, x: f32, y: f32);
105
106    /// Appends a ClosePath segment.
107    ///
108    /// End of a contour.
109    fn close(&mut self);
110}
111
112
113struct DummyOutline;
114impl OutlineBuilder for DummyOutline {
115    fn move_to(&mut self, _: f32, _: f32) {}
116    fn line_to(&mut self, _: f32, _: f32) {}
117    fn quad_to(&mut self, _: f32, _: f32, _: f32, _: f32) {}
118    fn curve_to(&mut self, _: f32, _: f32, _: f32, _: f32, _: f32, _: f32) {}
119    fn close(&mut self) {}
120}
121
122
123pub(crate) struct Builder<'a> {
124    builder: &'a mut dyn OutlineBuilder,
125    bbox: RectF,
126}
127
128impl<'a> Builder<'a> {
129    #[inline]
130    fn move_to(&mut self, x: f32, y: f32) {
131        self.bbox.extend_by(x, y);
132        self.builder.move_to(x, y);
133    }
134
135    #[inline]
136    fn line_to(&mut self, x: f32, y: f32) {
137        self.bbox.extend_by(x, y);
138        self.builder.line_to(x, y);
139    }
140
141    #[inline]
142    fn curve_to(&mut self, x1: f32, y1: f32, x2: f32, y2: f32, x: f32, y: f32) {
143        self.bbox.extend_by(x1, y1);
144        self.bbox.extend_by(x2, y2);
145        self.bbox.extend_by(x, y);
146        self.builder.curve_to(x1, y1, x2, y2, x, y);
147    }
148
149    #[inline]
150    fn close(&mut self) {
151        self.builder.close();
152    }
153}
154/// A rectangle.
155///
156/// Doesn't guarantee that `x_min` <= `x_max` and/or `y_min` <= `y_max`.
157#[repr(C)]
158#[allow(missing_docs)]
159#[derive(Clone, Copy, PartialEq, Eq, Debug)]
160pub struct Rect {
161    pub x_min: i16,
162    pub y_min: i16,
163    pub x_max: i16,
164    pub y_max: i16,
165}
166
167impl Rect {
168    #[inline]
169    fn zero() -> Self {
170        Self {
171            x_min: 0,
172            y_min: 0,
173            x_max: 0,
174            y_max: 0,
175        }
176    }
177
178    /// Returns rect's width.
179    #[inline]
180    pub fn width(&self) -> i16 {
181        self.x_max - self.x_min
182    }
183
184    /// Returns rect's height.
185    #[inline]
186    pub fn height(&self) -> i16 {
187        self.y_max - self.y_min
188    }
189}
190
191/// A rectangle described by the left-lower and upper-right points.
192#[derive(Clone, Copy, Debug, PartialEq)]
193pub struct RectF {
194    /// The horizontal minimum of the rect.
195    pub x_min: f32,
196    /// The vertical minimum of the rect.
197    pub y_min: f32,
198    /// The horizontal maximum of the rect.
199    pub x_max: f32,
200    /// The vertical maximum of the rect.
201    pub y_max: f32,
202}
203
204impl RectF {
205    #[inline]
206    fn new() -> Self {
207        RectF {
208            x_min: f32::MAX,
209            y_min: f32::MAX,
210            x_max: f32::MIN,
211            y_max: f32::MIN,
212        }
213    }
214
215    #[inline]
216    fn is_default(&self) -> bool {
217        self.x_min == f32::MAX
218            && self.y_min == f32::MAX
219            && self.x_max == f32::MIN
220            && self.y_max == f32::MIN
221    }
222
223    #[inline]
224    fn extend_by(&mut self, x: f32, y: f32) {
225        self.x_min = self.x_min.min(x);
226        self.y_min = self.y_min.min(y);
227        self.x_max = self.x_max.max(x);
228        self.y_max = self.y_max.max(y);
229    }
230
231    #[inline]
232    fn to_rect(self) -> Option<Rect> {
233        Some(Rect {
234            x_min: i16::try_num_from(self.x_min)?,
235            y_min: i16::try_num_from(self.y_min)?,
236            x_max: i16::try_num_from(self.x_max)?,
237            y_max: i16::try_num_from(self.y_max)?,
238        })
239    }
240}
241
242
243
244/// A type-safe wrapper for glyph ID.
245#[repr(transparent)]
246#[derive(Clone, Copy, Ord, PartialOrd, Eq, PartialEq, Default, Debug)]
247pub struct GlyphId(pub u16);
248
249impl FromData for GlyphId {
250    const SIZE: usize = 2;
251
252    #[inline]
253    fn parse(data: &[u8]) -> Option<Self> {
254        u16::parse(data).map(GlyphId)
255    }
256}
257
258