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