ttf_parser/tables/cff/
mod.rs

1pub 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/// A list of errors that can occur during a CFF glyph outlining.
17#[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/// A type-safe wrapper for string ID.
75#[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// Adobe Technical Note #5176, Chapter 16 "Local / Global Subrs INDEXes"
130#[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}