Coverage Report

Created: 2025-10-28 06:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ttf-parser/src/tables/cff/mod.rs
Line
Count
Source
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::{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)]
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: RectF,
48
    transform: Option<(u16, cff1::Matrix)>,
49
}
50
51
impl<'a> Builder<'a> {
52
    #[inline]
53
2.79M
    fn move_to(&mut self, x: f32, y: f32) {
54
2.79M
        let (x, y) = self.transform(x, y);
55
2.79M
        self.bbox.extend_by(x, y);
56
2.79M
        self.builder.move_to(x, y);
57
2.79M
    }
58
59
    #[inline]
60
653k
    fn line_to(&mut self, x: f32, y: f32) {
61
653k
        let (x, y) = self.transform(x, y);
62
653k
        self.bbox.extend_by(x, y);
63
653k
        self.builder.line_to(x, y);
64
653k
    }
65
66
    #[inline]
67
13.4M
    fn curve_to(&mut self, x1: f32, y1: f32, x2: f32, y2: f32, x: f32, y: f32) {
68
13.4M
        let (x1, y1) = self.transform(x1, y1);
69
13.4M
        let (x2, y2) = self.transform(x2, y2);
70
13.4M
        let (x, y) = self.transform(x, y);
71
13.4M
        self.bbox.extend_by(x1, y1);
72
13.4M
        self.bbox.extend_by(x2, y2);
73
13.4M
        self.bbox.extend_by(x, y);
74
13.4M
        self.builder.curve_to(x1, y1, x2, y2, x, y);
75
13.4M
    }
76
77
    #[inline]
78
2.73M
    fn close(&mut self) {
79
2.73M
        self.builder.close();
80
2.73M
    }
81
82
    #[inline]
83
43.7M
    fn transform(&self, x: f32, y: f32) -> (f32, f32) {
84
43.7M
        let (units_per_em, matrix) = if let Some(transform) = self.transform {
85
949k
            transform
86
        } else {
87
42.7M
            return (x, y);
88
        };
89
949k
        let (mut tx, mut ty) = (x, y);
90
949k
        tx = tx * matrix.sx + ty * matrix.kx + matrix.tx;
91
949k
        ty = tx * matrix.ky + ty * matrix.sy + matrix.ty;
92
949k
        tx *= units_per_em as f32;
93
949k
        ty *= units_per_em as f32;
94
949k
        (tx, ty)
95
43.7M
    }
96
}
97
98
/// A type-safe wrapper for string ID.
99
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Debug)]
100
pub struct StringId(u16);
101
102
impl FromData for StringId {
103
    const SIZE: usize = 2;
104
105
    #[inline]
106
3.18M
    fn parse(data: &[u8]) -> Option<Self> {
107
3.18M
        u16::parse(data).map(StringId)
108
3.18M
    }
109
}
110
111
pub trait IsEven {
112
    fn is_even(&self) -> bool;
113
    fn is_odd(&self) -> bool;
114
}
115
116
impl IsEven for usize {
117
    #[inline]
118
7.58M
    fn is_even(&self) -> bool {
119
7.58M
        (*self) & 1 == 0
120
7.58M
    }
121
122
    #[inline]
123
7.58M
    fn is_odd(&self) -> bool {
124
7.58M
        !self.is_even()
125
7.58M
    }
126
}
127
128
#[cfg(feature = "std")]
129
#[inline]
130
10.7k
pub fn f32_abs(n: f32) -> f32 {
131
10.7k
    n.abs()
132
10.7k
}
133
134
#[cfg(not(feature = "std"))]
135
#[inline]
136
pub fn f32_abs(n: f32) -> f32 {
137
    if n.is_sign_negative() {
138
        -n
139
    } else {
140
        n
141
    }
142
}
143
144
#[inline]
145
3.20M
pub fn conv_subroutine_index(index: f32, bias: u16) -> Result<u32, CFFError> {
146
3.20M
    conv_subroutine_index_impl(index, bias).ok_or(CFFError::InvalidSubroutineIndex)
147
3.20M
}
148
149
#[inline]
150
3.20M
fn conv_subroutine_index_impl(index: f32, bias: u16) -> Option<u32> {
151
3.20M
    let index = i32::try_num_from(index)?;
152
3.20M
    let bias = i32::from(bias);
153
154
3.20M
    let index = index.checked_add(bias)?;
155
3.20M
    u32::try_from(index).ok()
156
3.20M
}
157
158
// Adobe Technical Note #5176, Chapter 16 "Local / Global Subrs INDEXes"
159
#[inline]
160
3.20M
pub fn calc_subroutine_bias(len: u32) -> u16 {
161
3.20M
    if len < 1240 {
162
3.11M
        107
163
93.1k
    } else if len < 33900 {
164
92.9k
        1131
165
    } else {
166
167
        32768
167
    }
168
3.20M
}