ttf_parser/tables/cff/
mod.rs

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::{OutlineBuilder, RectF};
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: RectF,
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(CFFError::InvalidSubroutineIndex)
126}
127
128#[inline]
129fn conv_subroutine_index_impl(index: f32, bias: u16) -> Option<u32> {
130    let index = i32::try_num_from(index)?;
131    let bias = i32::from(bias);
132
133    let index = 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}