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