allsorts_subset_browser/cff/charstring/
argstack.rs

1// This file is derived from ttf-parser, licenced under Apache-2.0.
2// https://github.com/RazrFalcon/ttf-parser/blob/439aaaebd50eb8aed66302e3c1b51fae047f85b2/src/tables/cff/argstack.rs
3
4use std::fmt::Debug;
5
6use crate::cff::CFFError;
7
8/// Storage for the CFF operand stack with processing CharStrings.
9pub struct ArgumentsStack<'a, T>
10where
11    T: Debug,
12{
13    pub data: &'a mut [T],
14    pub len: usize,
15    pub max_len: usize,
16}
17
18impl<'a, T> ArgumentsStack<'a, T>
19where
20    T: Copy + Debug,
21{
22    pub fn len(&self) -> usize {
23        self.len
24    }
25
26    pub fn is_empty(&self) -> bool {
27        self.len == 0
28    }
29
30    pub fn push(&mut self, n: T) -> Result<(), CFFError> {
31        if self.len == self.max_len {
32            Err(CFFError::ArgumentsStackLimitReached)
33        } else {
34            self.data[self.len] = n;
35            self.len += 1;
36            Ok(())
37        }
38    }
39
40    #[cfg(feature = "outline")]
41    pub fn at(&self, index: usize) -> T {
42        self.data[index]
43    }
44
45    pub fn pop(&mut self) -> T {
46        debug_assert!(!self.is_empty());
47        self.len -= 1;
48        self.data[self.len]
49    }
50
51    /// pop n values from the stack
52    pub fn pop_n(&mut self, n: usize) -> &[T] {
53        debug_assert!(n <= self.len);
54        self.len -= n;
55        &self.data[self.len..]
56    }
57
58    pub fn pop_all(&mut self) -> &[T] {
59        let len = self.len;
60        self.len = 0;
61        &self.data[..len]
62    }
63
64    pub fn all(&self) -> &[T] {
65        &self.data[..self.len]
66    }
67
68    pub fn offset<E>(
69        &mut self,
70        offset: usize,
71        mut func: impl FnMut(&ArgumentsStack<'_, T>) -> Result<(), E>,
72    ) -> Result<(), E> {
73        debug_assert!(offset <= self.len);
74        let temporary_stack = ArgumentsStack {
75            data: &mut self.data[offset..],
76            len: self.len - offset,
77            max_len: self.max_len - offset,
78        };
79        func(&temporary_stack)
80    }
81
82    #[cfg(feature = "outline")]
83    pub fn reverse(&mut self) {
84        if self.is_empty() {
85            return;
86        }
87
88        // Reverse only the actual data and not the whole stack.
89        let (first, _) = self.data.split_at_mut(self.len);
90        first.reverse();
91    }
92
93    pub fn clear(&mut self) {
94        self.len = 0;
95    }
96
97    #[cfg(feature = "outline")]
98    pub(crate) fn clone_into(&self, data: &'a mut [T]) -> Self {
99        data[..self.len].clone_from_slice(&self.data[..self.len]);
100        ArgumentsStack {
101            data,
102            len: self.len,
103            max_len: self.max_len,
104        }
105    }
106}
107
108impl<T: Debug> Debug for ArgumentsStack<'_, T> {
109    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
110        f.debug_list().entries(&self.data[..self.len]).finish()
111    }
112}