1 | mod argstack; |
2 | pub mod cff1; |
3 | #[cfg (feature = "variable-fonts" )] |
4 | pub mod cff2; |
5 | mod charset; |
6 | mod charstring; |
7 | mod dict; |
8 | mod encoding; |
9 | mod index; |
10 | #[cfg (feature = "glyph-names" )] |
11 | mod std_names; |
12 | |
13 | use core::convert::TryFrom; |
14 | |
15 | use crate::parser::{FromData, TryNumFrom}; |
16 | use 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)] |
21 | pub 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 | |
45 | pub(crate) struct Builder<'a> { |
46 | builder: &'a mut dyn OutlineBuilder, |
47 | bbox: BBox, |
48 | } |
49 | |
50 | impl<'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)] |
79 | pub struct StringId(u16); |
80 | |
81 | impl 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 | |
90 | pub trait IsEven { |
91 | fn is_even(&self) -> bool; |
92 | fn is_odd(&self) -> bool; |
93 | } |
94 | |
95 | impl 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 ] |
109 | pub fn f32_abs(n: f32) -> f32 { |
110 | n.abs() |
111 | } |
112 | |
113 | #[cfg (not(feature = "std" ))] |
114 | #[inline ] |
115 | pub fn f32_abs(n: f32) -> f32 { |
116 | if n.is_sign_negative() { |
117 | -n |
118 | } else { |
119 | n |
120 | } |
121 | } |
122 | |
123 | #[inline ] |
124 | pub 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 ] |
129 | fn 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 ] |
139 | pub 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 | |