1mod argstack;
2pub mod cff1;
3#[cfg(feature = "variable-fonts")]
4pub mod cff2;
5mod charset;
6mod charstring;
7mod dict;
8mod encoding;
9mod index;
10#[cfg(feature = "glyph-names")]
11mod std_names;
12
13use core::convert::TryFrom;
14
15use crate::parser::{FromData, TryNumFrom};
16use crate::{BBox, OutlineBuilder};
17
18/// A list of errors that can occur during a CFF glyph outlining.
19#[allow(missing_docs)]
20#[derive(Clone, Copy, PartialEq, Eq, Debug)]
21pub enum CFFError {
22 NoGlyph,
23 ReadOutOfBounds,
24 ZeroBBox,
25 InvalidOperator,
26 UnsupportedOperator,
27 MissingEndChar,
28 DataAfterEndChar,
29 NestingLimitReached,
30 ArgumentsStackLimitReached,
31 InvalidArgumentsStackLength,
32 BboxOverflow,
33 MissingMoveTo,
34 InvalidSubroutineIndex,
35 NoLocalSubroutines,
36 InvalidSeacCode,
37 #[cfg(feature = "variable-fonts")]
38 InvalidItemVariationDataIndex,
39 #[cfg(feature = "variable-fonts")]
40 InvalidNumberOfBlendOperands,
41 #[cfg(feature = "variable-fonts")]
42 BlendRegionsLimitReached,
43}
44
45pub(crate) struct Builder<'a> {
46 builder: &'a mut dyn OutlineBuilder,
47 bbox: BBox,
48}
49
50impl<'a> Builder<'a> {
51 #[inline]
52 fn move_to(&mut self, x: f32, y: f32) {
53 self.bbox.extend_by(x, y);
54 self.builder.move_to(x, y);
55 }
56
57 #[inline]
58 fn line_to(&mut self, x: f32, y: f32) {
59 self.bbox.extend_by(x, y);
60 self.builder.line_to(x, y);
61 }
62
63 #[inline]
64 fn curve_to(&mut self, x1: f32, y1: f32, x2: f32, y2: f32, x: f32, y: f32) {
65 self.bbox.extend_by(x1, y1);
66 self.bbox.extend_by(x2, y2);
67 self.bbox.extend_by(x, y);
68 self.builder.curve_to(x1, y1, x2, y2, x, y);
69 }
70
71 #[inline]
72 fn close(&mut self) {
73 self.builder.close();
74 }
75}
76
77/// A type-safe wrapper for string ID.
78#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Debug)]
79pub struct StringId(u16);
80
81impl FromData for StringId {
82 const SIZE: usize = 2;
83
84 #[inline]
85 fn parse(data: &[u8]) -> Option<Self> {
86 u16::parse(data).map(StringId)
87 }
88}
89
90pub trait IsEven {
91 fn is_even(&self) -> bool;
92 fn is_odd(&self) -> bool;
93}
94
95impl IsEven for usize {
96 #[inline]
97 fn is_even(&self) -> bool {
98 (*self) & 1 == 0
99 }
100
101 #[inline]
102 fn is_odd(&self) -> bool {
103 !self.is_even()
104 }
105}
106
107#[cfg(feature = "std")]
108#[inline]
109pub fn f32_abs(n: f32) -> f32 {
110 n.abs()
111}
112
113#[cfg(not(feature = "std"))]
114#[inline]
115pub fn f32_abs(n: f32) -> f32 {
116 if n.is_sign_negative() {
117 -n
118 } else {
119 n
120 }
121}
122
123#[inline]
124pub fn conv_subroutine_index(index: f32, bias: u16) -> Result<u32, CFFError> {
125 conv_subroutine_index_impl(index, bias).ok_or(err:CFFError::InvalidSubroutineIndex)
126}
127
128#[inline]
129fn conv_subroutine_index_impl(index: f32, bias: u16) -> Option<u32> {
130 let index: i32 = i32::try_num_from(index)?;
131 let bias: i32 = i32::from(bias);
132
133 let index: i32 = index.checked_add(bias)?;
134 u32::try_from(index).ok()
135}
136
137// Adobe Technical Note #5176, Chapter 16 "Local / Global Subrs INDEXes"
138#[inline]
139pub fn calc_subroutine_bias(len: u32) -> u16 {
140 if len < 1240 {
141 107
142 } else if len < 33900 {
143 1131
144 } else {
145 32768
146 }
147}
148