allsorts_subset_browser/
cff.rs

1//! CFF font handling.
2//!
3//! Refer to [Technical Note #5176](http://wwwimages.adobe.com/content/dam/Adobe/en/devnet/font/pdfs/5176.CFF.pdf)
4//! for more information.
5
6pub mod cff2;
7pub mod charstring;
8#[cfg(feature = "outline")]
9pub mod outline;
10mod subset;
11
12use std::convert::{TryFrom, TryInto};
13use std::io::Write;
14use std::iter;
15use std::marker::PhantomData;
16
17use byteorder::{BigEndian, ByteOrder};
18use itertools::Itertools;
19use lazy_static::lazy_static;
20use num_traits as num;
21use tinyvec::{array_vec, tiny_vec, TinyVec};
22
23use crate::binary::read::{
24    CheckIndex, ReadArray, ReadArrayCow, ReadBinary, ReadBinaryDep, ReadCtxt, ReadFrom, ReadScope,
25    ReadUnchecked,
26};
27use crate::binary::write::{WriteBinary, WriteBinaryDep, WriteBuffer, WriteContext, WriteCounter};
28use crate::binary::{I16Be, I32Be, U16Be, U24Be, U32Be, U8};
29use crate::error::{ParseError, WriteError};
30use crate::tables::variable_fonts::{ItemVariationStore, OwnedTuple};
31use crate::variations::VariationError;
32use cff2::BlendOperand;
33use charstring::{ArgumentsStack, GlyphId, TryNumFrom};
34pub use subset::SubsetCFF;
35
36/// Maximum number of operands in Top DICT, Font DICTs, Private DICTs and CharStrings.
37///
38/// > An operator may be preceded by up to a maximum of 48 operands.
39pub const MAX_OPERANDS: usize = 48;
40const END_OF_FLOAT_FLAG: u8 = 0xf;
41
42const OPERAND_ZERO: [Operand; 1] = [Operand::Integer(0)];
43const OFFSET_ZERO: [Operand; 1] = [Operand::Offset(0)];
44const DEFAULT_UNDERLINE_POSITION: [Operand; 1] = [Operand::Integer(-100)];
45const DEFAULT_UNDERLINE_THICKNESS: [Operand; 1] = [Operand::Integer(50)];
46const DEFAULT_CHARSTRING_TYPE: [Operand; 1] = [Operand::Integer(2)];
47lazy_static! {
48    static ref DEFAULT_FONT_MATRIX: [Operand; 6] = {
49        let real_0_001 = Operand::Real(Real(tiny_vec![0x0a, 0x00, 0x1f])); // 0.001
50        [
51            real_0_001.clone(),
52            Operand::Integer(0),
53            Operand::Integer(0),
54            real_0_001,
55            Operand::Integer(0),
56            Operand::Integer(0),
57        ]
58    };
59}
60const DEFAULT_BBOX: [Operand; 4] = [
61    Operand::Integer(0),
62    Operand::Integer(0),
63    Operand::Integer(0),
64    Operand::Integer(0),
65];
66const DEFAULT_CID_COUNT: [Operand; 1] = [Operand::Integer(8720)];
67const DEFAULT_BLUE_SHIFT: [Operand; 1] = [Operand::Integer(7)];
68const DEFAULT_BLUE_FUZZ: [Operand; 1] = [Operand::Integer(1)];
69lazy_static! {
70    static ref DEFAULT_BLUE_SCALE: [Operand; 1] =
71        [Operand::Real(Real(tiny_vec![0x0a, 0x03, 0x96, 0x25, 0xff]))]; // 0.039625
72    static ref DEFAULT_EXPANSION_FACTOR: [Operand; 1] =
73        [Operand::Real(Real(tiny_vec![0x0a, 0x06, 0xff]))]; // 0.06
74}
75
76const ISO_ADOBE_LAST_SID: u16 = 228;
77const ADOBE: &[u8] = b"Adobe";
78const IDENTITY: &[u8] = b"Identity";
79
80/// Top level representation of a CFF font file, typically read from a CFF OpenType table.
81///
82/// Refer to Technical Note #5176
83#[derive(Clone)]
84pub struct CFF<'a> {
85    pub header: Header,
86    pub name_index: MaybeOwnedIndex<'a>,
87    pub string_index: MaybeOwnedIndex<'a>,
88    pub global_subr_index: MaybeOwnedIndex<'a>,
89    pub fonts: Vec<Font<'a>>,
90}
91
92/// CFF Font Header described in Section 6 of Technical Note #5176
93#[derive(Clone, Debug, PartialEq)]
94pub struct Header {
95    pub major: u8,
96    pub minor: u8,
97    pub hdr_size: u8,
98    pub off_size: u8,
99}
100
101/// Utility type for reading an INDEX with 16-bit offsets
102pub struct IndexU16;
103
104/// Utility type for reading an INDEX with 32-bit offsets
105pub struct IndexU32;
106
107/// A CFF INDEX described in Section 5 of Technical Note #5176
108#[derive(Clone)]
109pub struct Index<'a> {
110    pub count: usize,
111    off_size: u8,
112    offset_array: &'a [u8],
113    data_array: &'a [u8],
114}
115
116/// A single font within a CFF file
117#[derive(Clone)]
118pub struct Font<'a> {
119    pub top_dict: TopDict,
120    pub char_strings_index: MaybeOwnedIndex<'a>,
121    pub charset: Charset<'a>,
122    pub data: CFFVariant<'a>,
123}
124
125/// A borrowed reference to a [cff::Font](Font) or [cff2::Font].
126#[derive(Copy, Clone)]
127pub enum CFFFont<'a, 'data> {
128    CFF(&'a Font<'data>),
129    CFF2(&'a cff2::Font<'data>),
130}
131
132/// A CFF INDEX that can hold borrowed or owned data.
133#[derive(Clone)]
134pub enum MaybeOwnedIndex<'a> {
135    Borrowed(Index<'a>),
136    Owned(owned::Index),
137}
138
139/// Iterator for the entries in a `MaybeOwnedIndex`.
140pub struct MaybeOwnedIndexIterator<'a> {
141    data: &'a MaybeOwnedIndex<'a>,
142    index: usize,
143}
144
145/// A list of errors that can occur when interpreting CFF CharStrings.
146#[derive(Clone, Eq, PartialEq, Debug)]
147pub enum CFFError {
148    ParseError(ParseError),
149    InvalidOperator,
150    // Operand was out of range or otherwise unsuitable for the intended use
151    InvalidOperand,
152    UnsupportedOperator,
153    MissingEndChar,
154    DataAfterEndChar,
155    NestingLimitReached,
156    ArgumentsStackLimitReached,
157    InvalidArgumentsStackLength,
158    BboxOverflow,
159    MissingMoveTo,
160    DuplicateVsIndex,
161    InvalidSubroutineIndex,
162    InvalidFontIndex,
163    NoLocalSubroutines,
164    InvalidSeacCode,
165    VsIndexAfterBlend,
166    MissingVariationStore,
167}
168
169mod owned {
170    use super::{TryFrom, U16Be, U32Be, WriteBinary, WriteContext, WriteError, U8};
171
172    pub(super) struct IndexU16;
173    pub(super) struct IndexU32;
174
175    #[derive(Clone)]
176    pub struct Index {
177        pub(super) data: Vec<Vec<u8>>,
178    }
179
180    impl WriteBinary<&Index> for IndexU16 {
181        type Output = ();
182
183        fn write<C: WriteContext>(ctxt: &mut C, index: &Index) -> Result<(), WriteError> {
184            let count = u16::try_from(index.data.len())?;
185            U16Be::write(ctxt, count)?;
186            write_index_body(ctxt, index)
187        }
188    }
189
190    impl WriteBinary<&Index> for IndexU32 {
191        type Output = ();
192
193        fn write<C: WriteContext>(ctxt: &mut C, index: &Index) -> Result<(), WriteError> {
194            let count = u32::try_from(index.data.len())?;
195            U32Be::write(ctxt, count)?;
196            write_index_body(ctxt, index)
197        }
198    }
199
200    fn write_index_body<C: WriteContext>(ctxt: &mut C, index: &Index) -> Result<(), WriteError> {
201        if index.data.is_empty() {
202            return Ok(());
203        }
204
205        let mut offset = 1; // INDEX offsets start at 1
206        let mut offsets = Vec::with_capacity(index.data.len() + 1);
207        for data in &index.data {
208            offsets.push(offset);
209            offset += data.len();
210        }
211        offsets.push(offset);
212        let (off_size, offset_array) = super::serialise_offset_array(offsets)?;
213        U8::write(ctxt, off_size)?;
214        ctxt.write_bytes(&offset_array)?;
215        for data in &index.data {
216            ctxt.write_bytes(data)?;
217        }
218
219        Ok(())
220    }
221
222    impl Index {
223        pub(super) fn read_object(&self, index: usize) -> Option<&[u8]> {
224            self.data.get(index).map(|data| data.as_slice())
225        }
226    }
227}
228
229#[derive(Clone)]
230pub enum CFFVariant<'a> {
231    CID(CIDData<'a>),
232    Type1(Type1Data<'a>),
233}
234
235#[derive(Clone)]
236pub struct CIDData<'a> {
237    pub font_dict_index: MaybeOwnedIndex<'a>,
238    pub private_dicts: Vec<PrivateDict>,
239    /// An optional local subroutine index per Private DICT.
240    pub local_subr_indices: Vec<Option<MaybeOwnedIndex<'a>>>,
241    pub fd_select: FDSelect<'a>,
242}
243
244pub struct CIDDataOffsets {
245    pub font_dict_index: usize,
246    pub fd_select: usize,
247}
248
249#[derive(Clone)]
250pub struct Type1Data<'a> {
251    pub encoding: Encoding<'a>,
252    pub private_dict: PrivateDict,
253    pub local_subr_index: Option<MaybeOwnedIndex<'a>>,
254}
255
256pub struct Type1DataOffsets {
257    pub custom_encoding: Option<usize>,
258    pub private_dict: usize,
259    pub private_dict_len: usize,
260}
261
262// Encoding data is located via the offset operand to the Encoding operator in the Top DICT. Only
263// one Encoding operator can be specified per font except for CIDFonts which specify no encoding.
264#[derive(Clone)]
265pub enum Encoding<'a> {
266    Standard,
267    Expert,
268    Custom(CustomEncoding<'a>),
269}
270
271#[derive(Clone)]
272pub enum Charset<'a> {
273    ISOAdobe,
274    Expert,
275    ExpertSubset,
276    Custom(CustomCharset<'a>),
277}
278
279#[derive(Clone)]
280pub enum CustomEncoding<'a> {
281    Format0 {
282        codes: ReadArray<'a, U8>,
283    },
284    Format1 {
285        ranges: ReadArray<'a, Range<u8, u8>>,
286    },
287}
288
289// A string id in the font
290type SID = u16;
291
292#[derive(Clone)]
293pub enum CustomCharset<'a> {
294    Format0 {
295        glyphs: ReadArrayCow<'a, U16Be>,
296    },
297    Format1 {
298        ranges: ReadArrayCow<'a, Range<SID, u8>>,
299    },
300    Format2 {
301        ranges: ReadArrayCow<'a, Range<SID, u16>>,
302    },
303}
304
305/// A Range from `first` to `first + n_left`
306#[derive(Copy, Clone, Debug, PartialEq)]
307pub struct Range<F, N> {
308    pub first: F,
309    pub n_left: N,
310}
311
312/// A CFF DICT described in Section 4 of Technical Note #5176
313#[derive(Debug, PartialEq, Clone)]
314pub struct Dict<T>
315where
316    T: DictDefault,
317{
318    dict: Vec<(Operator, Vec<Operand>)>,
319    default: PhantomData<T>,
320}
321
322/// The default values of a DICT
323pub trait DictDefault {
324    /// Returns the default operand(s) if any for the supplied `op`.
325    fn default(op: Operator) -> Option<&'static [Operand]>;
326}
327
328#[derive(Debug, PartialEq, Clone)]
329pub struct TopDictDefault;
330
331#[derive(Debug, PartialEq, Clone)]
332pub struct FontDictDefault;
333
334#[derive(Debug, PartialEq, Clone)]
335pub struct PrivateDictDefault;
336
337pub type TopDict = Dict<TopDictDefault>;
338
339pub type FontDict = Dict<FontDictDefault>;
340
341pub type PrivateDict = Dict<PrivateDictDefault>;
342
343/// A collection of offset changes to a `Dict`
344///
345/// `DictDelta` only accepts Operators with offsets as operands.
346#[derive(Debug, PartialEq, Clone)]
347pub struct DictDelta {
348    // Most entries will have operands of a single offset, so the tiny vec is set to that
349    dict: Vec<(Operator, TinyVec<[Operand; 1]>)>,
350}
351
352/// Font DICT select as described in Section 19 of Technical Note #5176
353#[derive(Clone, Debug)]
354pub enum FDSelect<'a> {
355    Format0 {
356        glyph_font_dict_indices: ReadArrayCow<'a, U8>,
357    },
358    // Formats 1 and 2 are not defined
359    Format3 {
360        ranges: ReadArrayCow<'a, Range<u16, u8>>,
361        sentinel: u16,
362    },
363    // Format 4 is not yet implemented
364}
365
366/// CFF DICT operator
367#[derive(Debug, PartialEq)]
368enum Op {
369    Operator(Operator),
370    Operand(Operand),
371}
372
373/// CFF operand to an operator
374#[derive(Debug, PartialEq, Clone)]
375pub enum Operand {
376    Integer(i32),
377    Offset(i32),
378    Real(Real),
379}
380
381// On a corpus of 23945 CFF fonts real values were encountered as follows:
382//     572 2 bytes
383//     776 3 bytes
384//    1602 4 bytes
385//   14037 5 bytes
386//    3491 6 bytes
387//      36 7 bytes
388// Using 7 bytes for the tiny vec covers all these, fits in a register on 64-bit systems,
389// allows Operand to be 8 bytes on 64-bit systems, and is considerably smaller than the 24 bytes
390// used by Vec (which Real contained in the past).
391
392/// A real number
393///
394/// To parse the value into `f64` use the `TryFrom`/`TryInto` impl.
395#[derive(Debug, PartialEq, Clone)]
396pub struct Real(TinyVec<[u8; 7]>);
397
398#[repr(u16)]
399#[derive(Debug, PartialEq, Copy, Clone)]
400pub enum Operator {
401    Version = 0,
402    Notice = 1,
403    FullName = 2,
404    FamilyName = 3,
405    Weight = 4,
406    FontBBox = 5,
407    BlueValues = 6,
408    OtherBlues = 7,
409    FamilyBlues = 8,
410    FamilyOtherBlues = 9,
411    StdHW = 10,
412    StdVW = 11,
413    UniqueID = 13,
414    XUID = 14,
415    Charset = 15,
416    Encoding = 16,
417    CharStrings = 17,
418    Private = 18,
419    Subrs = 19,
420    DefaultWidthX = 20,
421    NominalWidthX = 21,
422    // CFF2
423    VSIndex = 22,
424    Blend = 23,
425    VStore = 24,
426
427    Copyright = op2(0),
428    IsFixedPitch = op2(1),
429    ItalicAngle = op2(2),
430    UnderlinePosition = op2(3),
431    UnderlineThickness = op2(4),
432    PaintType = op2(5),
433    CharstringType = op2(6),
434    FontMatrix = op2(7),
435    StrokeWidth = op2(8),
436    BlueScale = op2(9),
437    BlueShift = op2(10),
438    BlueFuzz = op2(11),
439    StemSnapH = op2(12),
440    StemSnapV = op2(13),
441    ForceBold = op2(14),
442    LanguageGroup = op2(17),
443    ExpansionFactor = op2(18),
444    InitialRandomSeed = op2(19),
445    SyntheticBase = op2(20),
446    PostScript = op2(21),
447    BaseFontName = op2(22),
448    BaseFontBlend = op2(23),
449    ROS = op2(30),
450    CIDFontVersion = op2(31),
451    CIDFontRevision = op2(32),
452    CIDFontType = op2(33),
453    CIDCount = op2(34),
454    UIDBase = op2(35),
455    FDArray = op2(36),
456    FDSelect = op2(37),
457    FontName = op2(38),
458}
459
460const fn op2(value: u8) -> u16 {
461    (12 << 8) | (value as u16)
462}
463
464impl<'b> ReadBinary for CFF<'b> {
465    type HostType<'a> = CFF<'a>;
466
467    fn read<'a>(ctxt: &mut ReadCtxt<'a>) -> Result<Self::HostType<'a>, ParseError> {
468        // Get a scope that starts at the beginning of the CFF data. This is needed for reading
469        // data that is specified as an offset from the start of the data later.
470        let scope = ctxt.scope();
471
472        let header = ctxt.read::<Header>()?;
473        let name_index = ctxt.read::<IndexU16>()?;
474        let top_dict_index = ctxt.read::<IndexU16>()?;
475        let string_index = ctxt.read::<IndexU16>()?;
476        let global_subr_index = ctxt.read::<IndexU16>().map(MaybeOwnedIndex::Borrowed)?;
477
478        let mut fonts = Vec::with_capacity(name_index.count);
479        for font_index in 0..name_index.count {
480            let top_dict = top_dict_index.read::<TopDict>(font_index, MAX_OPERANDS)?;
481
482            // CharStrings index
483            let offset = top_dict
484                .get_i32(Operator::CharStrings)
485                .unwrap_or(Err(ParseError::MissingValue))?;
486            let char_strings_index = scope.offset(usize::try_from(offset)?).read::<IndexU16>()?;
487
488            // The Top DICT begins with the SyntheticBase and ROS operators
489            // for synthetic and CIDFonts, respectively. Regular Type 1 fonts
490            // begin with some other operator.
491            let data = match top_dict.first_operator() {
492                Some(Operator::ROS) => {
493                    let cid_data = read_cid_data(&scope, &top_dict, char_strings_index.count)?;
494                    CFFVariant::CID(cid_data)
495                }
496                Some(Operator::SyntheticBase) => {
497                    return Err(ParseError::NotImplemented);
498                }
499                Some(_) => {
500                    let (private_dict, private_dict_offset) =
501                        top_dict.read_private_dict::<PrivateDict>(&scope, MAX_OPERANDS)?;
502                    let local_subr_index = read_local_subr_index::<_, IndexU16>(
503                        &scope,
504                        &private_dict,
505                        private_dict_offset,
506                    )?
507                    .map(MaybeOwnedIndex::Borrowed);
508                    let encoding = read_encoding(&scope, &top_dict)?;
509
510                    CFFVariant::Type1(Type1Data {
511                        encoding,
512                        private_dict,
513                        local_subr_index,
514                    })
515                }
516                None => return Err(ParseError::MissingValue),
517            };
518
519            let charset = read_charset(&scope, &top_dict, char_strings_index.count)?;
520
521            fonts.push(Font {
522                top_dict,
523                char_strings_index: MaybeOwnedIndex::Borrowed(char_strings_index),
524                charset,
525                data,
526            });
527        }
528
529        Ok(CFF {
530            header,
531            name_index: MaybeOwnedIndex::Borrowed(name_index),
532            string_index: MaybeOwnedIndex::Borrowed(string_index),
533            global_subr_index,
534            fonts,
535        })
536    }
537}
538
539impl<'a> WriteBinary<&Self> for CFF<'a> {
540    type Output = ();
541
542    fn write<C: WriteContext>(ctxt: &mut C, cff: &CFF<'a>) -> Result<(), WriteError> {
543        Header::write(ctxt, &cff.header)?;
544        MaybeOwnedIndex::write16(ctxt, &cff.name_index)?;
545        let top_dicts = cff.fonts.iter().map(|font| &font.top_dict).collect_vec();
546        let top_dict_index_length =
547            Index::calculate_size::<TopDict, _>(top_dicts.as_slice(), DictDelta::new())?;
548        let top_dict_index_placeholder = ctxt.reserve::<IndexU16, _>(top_dict_index_length)?;
549        MaybeOwnedIndex::write16(ctxt, &cff.string_index)?;
550        MaybeOwnedIndex::write16(ctxt, &cff.global_subr_index)?;
551
552        // Collect Top DICT deltas now that we know the offsets to other items in the DICT
553        let mut top_dict_deltas = vec![DictDelta::new(); cff.fonts.len()];
554        for (font, top_dict_delta) in cff.fonts.iter().zip(top_dict_deltas.iter_mut()) {
555            top_dict_delta.push_offset(Operator::CharStrings, i32::try_from(ctxt.bytes_written())?);
556            MaybeOwnedIndex::write16(ctxt, &font.char_strings_index)?;
557
558            match &font.charset {
559                Charset::ISOAdobe => top_dict_delta.push_offset(Operator::Charset, 0),
560                Charset::Expert => top_dict_delta.push_offset(Operator::Charset, 1),
561                Charset::ExpertSubset => top_dict_delta.push_offset(Operator::Charset, 2),
562                Charset::Custom(custom) => {
563                    top_dict_delta
564                        .push_offset(Operator::Charset, i32::try_from(ctxt.bytes_written())?);
565                    CustomCharset::write(ctxt, custom)?;
566                }
567            }
568            write_cff_variant(ctxt, &font.data, top_dict_delta)?;
569        }
570
571        // Write out the Top DICTs with the updated offsets
572        let mut top_dict_data = WriteBuffer::new();
573        let mut offsets = Vec::with_capacity(cff.fonts.len());
574        for (font, top_dict_delta) in cff.fonts.iter().zip(top_dict_deltas.into_iter()) {
575            offsets.push(top_dict_data.bytes_written() + 1); // +1 because INDEX offsets start at 1
576            TopDict::write_dep(&mut top_dict_data, &font.top_dict, top_dict_delta)?;
577        }
578        offsets.push(top_dict_data.bytes_written() + 1); // Add the extra offset at the end
579        let (off_size, offset_array) = serialise_offset_array(offsets)?;
580
581        // Fill in the Top DICT INDEX placeholder
582        let top_dict_index = Index {
583            count: cff.fonts.len(),
584            off_size,
585            offset_array: &offset_array,
586            data_array: top_dict_data.bytes(),
587        };
588        ctxt.write_placeholder(top_dict_index_placeholder, &top_dict_index)?;
589
590        Ok(())
591    }
592}
593
594impl<'a> CFF<'a> {
595    /// Read a string with the given SID from the String INDEX
596    pub fn read_string(&self, sid: SID) -> Result<&str, ParseError> {
597        read_string_index_string(&self.string_index, sid)
598    }
599}
600
601/// Read a string with the given SID from the String INDEX
602fn read_string_index_string<'idx>(
603    string_index: &'idx MaybeOwnedIndex<'_>,
604    sid: SID,
605) -> Result<&'idx str, ParseError> {
606    let sid = usize::from(sid);
607    // When the client needs to determine the string that corresponds to a particular SID it
608    // performs the following: test if SID is in standard range then fetch from internal table,
609    // otherwise, fetch string from the String INDEX using a value of (SID – nStdStrings) as
610    // the index
611    if let Some(string) = STANDARD_STRINGS.get(sid) {
612        Ok(string)
613    } else {
614        let bytes = string_index
615            .read_object(sid - STANDARD_STRINGS.len())
616            .ok_or(ParseError::BadIndex)?;
617
618        std::str::from_utf8(bytes).map_err(|_utf8_err| ParseError::BadValue)
619    }
620}
621
622impl ReadBinary for Header {
623    type HostType<'b> = Self;
624
625    fn read(ctxt: &mut ReadCtxt<'_>) -> Result<Self, ParseError> {
626        // From section 6 of Technical Note #5176:
627        // Implementations reading font set files must include code to check version numbers so
628        // that if and when the format and therefore the version number changes, older
629        // implementations will reject newer versions gracefully. If the major version number is
630        // understood by an implementation it can safely proceed with reading the font. The minor
631        // version number indicates extensions to the format that are undetectable by
632        // implementations that do not support them although they will be unable to take advantage
633        // of these extensions.
634        let major = ctxt.read_u8()?;
635        ctxt.check(major == 1)?;
636        let minor = ctxt.read_u8()?;
637        let hdr_size = ctxt.read_u8()?;
638        let off_size = ctxt.read_u8()?;
639
640        if hdr_size < 4 {
641            return Err(ParseError::BadValue);
642        }
643
644        if off_size < 1 || off_size > 4 {
645            return Err(ParseError::BadValue);
646        }
647
648        let _unknown = ctxt.read_slice((hdr_size - 4) as usize)?;
649
650        Ok(Header {
651            major,
652            minor,
653            hdr_size,
654            off_size,
655        })
656    }
657}
658
659impl WriteBinary<&Self> for Header {
660    type Output = ();
661
662    fn write<C: WriteContext>(ctxt: &mut C, header: &Header) -> Result<(), WriteError> {
663        U8::write(ctxt, header.major)?;
664        U8::write(ctxt, header.minor)?;
665        // Any data between the header and the Name INDEX will have been discarded.
666        // So the size will always be 4 bytes.
667        U8::write(ctxt, 4)?; // hdr_size
668        U8::write(ctxt, header.off_size)?;
669
670        Ok(())
671    }
672}
673
674impl<'b> ReadBinary for IndexU16 {
675    type HostType<'a> = Index<'a>;
676
677    fn read<'a>(ctxt: &mut ReadCtxt<'a>) -> Result<Self::HostType<'a>, ParseError> {
678        let count = usize::from(ctxt.read_u16be()?);
679        read_index(ctxt, count)
680    }
681}
682
683fn read_index<'a>(ctxt: &mut ReadCtxt<'a>, count: usize) -> Result<Index<'a>, ParseError> {
684    if count > 0 {
685        let off_size = ctxt.read_u8()?;
686        if off_size < 1 || off_size > 4 {
687            return Err(ParseError::BadValue);
688        }
689
690        let offset_array_size = (count + 1) * usize::from(off_size);
691        let offset_array = ctxt.read_slice(offset_array_size)?;
692
693        let last_offset_index = lookup_offset_index(off_size, offset_array, count);
694        if last_offset_index < 1 {
695            return Err(ParseError::BadValue);
696        }
697
698        let data_array_size = last_offset_index - 1;
699        let data_array = ctxt.read_slice(data_array_size)?;
700
701        Ok(Index {
702            count,
703            off_size,
704            offset_array,
705            data_array,
706        })
707    } else {
708        // count == 0
709        Ok(Index {
710            count,
711            off_size: 1,
712            offset_array: &[],
713            data_array: &[],
714        })
715    }
716}
717
718impl<'a> WriteBinary<&Index<'a>> for IndexU16 {
719    type Output = ();
720
721    fn write<C: WriteContext>(ctxt: &mut C, index: &Index<'a>) -> Result<(), WriteError> {
722        U16Be::write(ctxt, u16::try_from(index.count)?)?;
723        write_index_body(ctxt, index)
724    }
725}
726
727fn write_index_body<C: WriteContext>(ctxt: &mut C, index: &Index<'_>) -> Result<(), WriteError> {
728    if index.count == 0 {
729        return Ok(());
730    }
731
732    U8::write(ctxt, index.off_size)?;
733    ctxt.write_bytes(index.offset_array)?;
734    ctxt.write_bytes(index.data_array)?;
735
736    Ok(())
737}
738
739impl<T> ReadBinaryDep for Dict<T>
740where
741    T: DictDefault,
742{
743    type Args<'a> = usize;
744    type HostType<'b> = Self;
745
746    fn read_dep<'a>(
747        ctxt: &mut ReadCtxt<'a>,
748        max_operands: usize,
749    ) -> Result<Self::HostType<'a>, ParseError> {
750        let mut dict = Vec::new();
751        let mut operands = Vec::new();
752
753        while ctxt.bytes_available() {
754            match Op::read(ctxt)? {
755                Op::Operator(operator) => {
756                    integer_to_offset(operator, &mut operands);
757                    dict.push((operator, operands.clone()));
758                    operands.clear();
759                }
760                Op::Operand(operand) => {
761                    operands.push(operand);
762                    if operands.len() > max_operands {
763                        return Err(ParseError::LimitExceeded);
764                    }
765                }
766            }
767        }
768
769        Ok(Dict {
770            dict,
771            default: PhantomData,
772        })
773    }
774}
775
776fn offset_size(value: usize) -> Option<u8> {
777    match value {
778        0..=0xFF => Some(1),
779        0x100..=0xFFFF => Some(2),
780        0x1_0000..=0xFF_FFFF => Some(3),
781        0x100_0000..=0xFFFF_FFFF => Some(4),
782        _ => None,
783    }
784}
785
786// Special case handling for operands that are offsets. This function swaps them from an
787// Integer to an Offset. This is later used when writing operands.
788fn integer_to_offset(operator: Operator, operands: &mut [Operand]) {
789    match (operator, &operands) {
790        // Encodings 0..=1 indicate predefined encodings and are not offsets
791        (Operator::Encoding, [Operand::Integer(offset)]) if *offset > 1 => {
792            operands[0] = Operand::Offset(*offset);
793        }
794        (Operator::Charset, [Operand::Integer(offset)])
795        | (Operator::CharStrings, [Operand::Integer(offset)])
796        | (Operator::Subrs, [Operand::Integer(offset)])
797        | (Operator::FDArray, [Operand::Integer(offset)])
798        | (Operator::FDSelect, [Operand::Integer(offset)])
799        | (Operator::VStore, [Operand::Integer(offset)]) => {
800            operands[0] = Operand::Offset(*offset);
801        }
802        (Operator::Private, [Operand::Integer(length), Operand::Integer(offset)]) => {
803            let offset = *offset; // This is a work around an ownership issue
804            operands[0] = Operand::Offset(*length);
805            operands[1] = Operand::Offset(offset);
806        }
807        _ => {}
808    }
809}
810
811impl<T> WriteBinaryDep<&Self> for Dict<T>
812where
813    T: DictDefault,
814{
815    type Args = DictDelta;
816    type Output = usize; // The length of the written Dict
817
818    fn write_dep<C: WriteContext>(
819        ctxt: &mut C,
820        dict: &Dict<T>,
821        delta: DictDelta,
822    ) -> Result<Self::Output, WriteError> {
823        let offset = ctxt.bytes_written();
824
825        for (operator, operands) in dict.iter() {
826            let mut operands = operands.as_slice();
827
828            // Replace operands with delta operands if present otherwise skip if operands match
829            // default. We never skip operands pulled from the delta DICT as these are offsets and
830            // always need to be written in order to make the size of the DICT predictable.
831            if let Some(delta_operands) = delta.get(*operator) {
832                operands = delta_operands;
833            } else if T::default(*operator)
834                .map(|defaults| defaults == operands)
835                .unwrap_or(false)
836            {
837                continue;
838            }
839
840            for operand in operands {
841                Operand::write(ctxt, operand)?;
842            }
843            Operator::write(ctxt, *operator)?;
844        }
845
846        Ok(ctxt.bytes_written() - offset)
847    }
848}
849
850impl ReadBinary for Op {
851    type HostType<'b> = Self;
852
853    fn read<'a>(ctxt: &mut ReadCtxt<'a>) -> Result<Self, ParseError> {
854        let b0 = ctxt.read_u8()?;
855
856        match b0 {
857            0..=11 | 13..=21 => ok_operator(u16::from(b0).try_into().unwrap()), // NOTE(unwrap): Safe due to pattern
858            // CFF2
859            22..=24 => ok_operator(u16::from(b0).try_into().unwrap()), // NOTE(unwrap): Safe due to pattern
860            12 => ok_operator(op2(ctxt.read_u8()?).try_into()?),
861            28 => {
862                let num = ctxt.read_i16be()?;
863                Ok(Op::Operand(Operand::Integer(i32::from(num))))
864            }
865            29 => ok_int(ctxt.read_i32be()?),
866            30 => ok_real(ctxt.read_until_nibble(END_OF_FLOAT_FLAG)?),
867            32..=246 => ok_int(i32::from(b0) - 139),
868            247..=250 => {
869                let b1 = ctxt.read_u8()?;
870                ok_int((i32::from(b0) - 247) * 256 + i32::from(b1) + 108)
871            }
872            251..=254 => {
873                let b1 = ctxt.read_u8()?;
874                ok_int(-(i32::from(b0) - 251) * 256 - i32::from(b1) - 108)
875            }
876            // reserved
877            25..=27 | 31 | 255 => Err(ParseError::BadValue),
878        }
879    }
880}
881
882impl WriteBinary<Self> for Operator {
883    type Output = ();
884
885    fn write<C: WriteContext>(ctxt: &mut C, op: Operator) -> Result<(), WriteError> {
886        let value = op as u16;
887        if value > 0xFF {
888            U16Be::write(ctxt, value)?;
889        } else {
890            U8::write(ctxt, value as u8)?;
891        }
892
893        Ok(())
894    }
895}
896
897impl WriteBinary<&Self> for Operand {
898    type Output = ();
899
900    // Refer to Table 3 Operand Encoding in section 4 of Technical Note #5176 for details on the
901    // integer encoding scheme.
902    fn write<C: WriteContext>(ctxt: &mut C, op: &Operand) -> Result<(), WriteError> {
903        match op {
904            Operand::Integer(val) => match *val {
905                // NOTE: Casts are safe due to patterns limiting range
906                -107..=107 => {
907                    U8::write(ctxt, (val + 139) as u8)?;
908                }
909                108..=1131 => {
910                    let val = *val - 108;
911                    U8::write(ctxt, ((val >> 8) + 247) as u8)?;
912                    U8::write(ctxt, val as u8)?;
913                }
914                -1131..=-108 => {
915                    let val = -*val - 108;
916                    U8::write(ctxt, ((val >> 8) + 251) as u8)?;
917                    U8::write(ctxt, val as u8)?;
918                }
919                -32768..=32767 => {
920                    U8::write(ctxt, 28)?;
921                    I16Be::write(ctxt, *val as i16)?
922                }
923                _ => {
924                    U8::write(ctxt, 29)?;
925                    I32Be::write(ctxt, *val)?
926                }
927            },
928            Operand::Offset(val) => {
929                U8::write(ctxt, 29)?;
930                // Offsets are always encoded using the i32 representation to make their size
931                // predictable.
932                I32Be::write(ctxt, *val)?;
933            }
934            Operand::Real(Real(val)) => {
935                U8::write(ctxt, 30)?;
936                ctxt.write_bytes(val)?;
937            }
938        }
939
940        Ok(())
941    }
942}
943
944fn ok_operator(op: Operator) -> Result<Op, ParseError> {
945    Ok(Op::Operator(op))
946}
947
948fn ok_int(num: i32) -> Result<Op, ParseError> {
949    Ok(Op::Operand(Operand::Integer(num)))
950}
951
952fn ok_real(slice: &[u8]) -> Result<Op, ParseError> {
953    Ok(Op::Operand(Operand::Real(Real(TinyVec::from(slice)))))
954}
955
956const FLOAT_BUF_LEN: usize = 64;
957
958// Portions of this try_from impl derived from ttf-parser, licenced under Apache-2.0.
959// https://github.com/RazrFalcon/ttf-parser/blob/ba2d9c8b9a207951b7b07e9481bc74688762bd21/src/tables/cff/dict.rs#L188
960impl TryFrom<&Real> for f64 {
961    type Error = ParseError;
962
963    /// Try to parse this `Real` into an `f64`.
964    fn try_from(real: &Real) -> Result<Self, Self::Error> {
965        let mut buf = [0u8; FLOAT_BUF_LEN];
966        let mut used = 0;
967
968        for byte in real.0.iter().copied() {
969            let nibble1 = byte >> 4;
970            let nibble2 = byte & 0xF;
971
972            if nibble1 == END_OF_FLOAT_FLAG {
973                break;
974            }
975            parse_float_nibble(nibble1, &mut used, &mut buf)?;
976            if nibble2 == END_OF_FLOAT_FLAG {
977                break;
978            }
979            parse_float_nibble(nibble2, &mut used, &mut buf)?;
980        }
981
982        // NOTE(unwrap): Safe as we have constructed the string from only ASCII characters in
983        // parse_float_nibble.
984        let s = core::str::from_utf8(&buf[..used]).unwrap();
985        s.parse().map_err(|_| ParseError::BadValue)
986    }
987}
988
989// Adobe Technical Note #5176, Table 5 Nibble Definitions
990fn parse_float_nibble(nibble: u8, idx: &mut usize, data: &mut [u8]) -> Result<(), ParseError> {
991    if *idx == FLOAT_BUF_LEN {
992        return Err(ParseError::LimitExceeded);
993    }
994
995    match nibble {
996        0..=9 => {
997            data[*idx] = b'0' + nibble;
998        }
999        10 => {
1000            data[*idx] = b'.';
1001        }
1002        11 => {
1003            data[*idx] = b'E';
1004        }
1005        12 => {
1006            if *idx + 1 == FLOAT_BUF_LEN {
1007                return Err(ParseError::LimitExceeded);
1008            }
1009
1010            data[*idx] = b'E';
1011            *idx += 1;
1012            data[*idx] = b'-';
1013        }
1014        13 => return Err(ParseError::BadValue),
1015        14 => {
1016            data[*idx] = b'-';
1017        }
1018        _ => return Err(ParseError::BadValue),
1019    }
1020
1021    *idx += 1;
1022    Ok(())
1023}
1024
1025impl ReadFrom for Range<u8, u8> {
1026    type ReadType = (U8, U8);
1027    fn read_from((first, n_left): (u8, u8)) -> Self {
1028        Range { first, n_left }
1029    }
1030}
1031
1032impl WriteBinary for Range<u8, u8> {
1033    type Output = ();
1034
1035    fn write<C: WriteContext>(ctxt: &mut C, range: Self) -> Result<(), WriteError> {
1036        U8::write(ctxt, range.first)?;
1037        U8::write(ctxt, range.n_left)?;
1038
1039        Ok(())
1040    }
1041}
1042
1043impl ReadFrom for Range<SID, u8> {
1044    type ReadType = (U16Be, U8);
1045    fn read_from((first, n_left): (SID, u8)) -> Self {
1046        Range { first, n_left }
1047    }
1048}
1049
1050impl WriteBinary for Range<SID, u8> {
1051    type Output = ();
1052
1053    fn write<C: WriteContext>(ctxt: &mut C, range: Self) -> Result<(), WriteError> {
1054        U16Be::write(ctxt, range.first)?;
1055        U8::write(ctxt, range.n_left)?;
1056
1057        Ok(())
1058    }
1059}
1060
1061impl ReadFrom for Range<SID, u16> {
1062    type ReadType = (U16Be, U16Be);
1063    fn read_from((first, n_left): (SID, u16)) -> Self {
1064        Range { first, n_left }
1065    }
1066}
1067
1068impl WriteBinary for Range<SID, u16> {
1069    type Output = ();
1070
1071    fn write<C: WriteContext>(ctxt: &mut C, range: Self) -> Result<(), WriteError> {
1072        U16Be::write(ctxt, range.first)?;
1073        U16Be::write(ctxt, range.n_left)?;
1074
1075        Ok(())
1076    }
1077}
1078
1079impl<F, N> Range<F, N>
1080where
1081    N: num::Unsigned + Copy,
1082    usize: From<N>,
1083{
1084    pub fn len(&self) -> usize {
1085        usize::from(self.n_left) + 1
1086    }
1087}
1088
1089// TODO: Make these generic. Requires Rust stabilisation of the Step trait or its replacement.
1090// https://doc.rust-lang.org/core/iter/trait.Step.html
1091impl Range<SID, u8> {
1092    pub fn iter(&self) -> impl Iterator<Item = SID> {
1093        let last = self.first + SID::from(self.n_left);
1094        self.first..=last
1095    }
1096}
1097
1098impl Range<SID, u16> {
1099    pub fn iter(&self) -> impl Iterator<Item = SID> {
1100        let last = self.first + self.n_left;
1101        self.first..=last
1102    }
1103}
1104
1105impl<'b> ReadBinary for CustomEncoding<'b> {
1106    type HostType<'a> = CustomEncoding<'a>;
1107
1108    fn read<'a>(ctxt: &mut ReadCtxt<'a>) -> Result<Self::HostType<'a>, ParseError> {
1109        // First byte indicates the format of the encoding data
1110        match ctxt.read::<U8>()? {
1111            0 => {
1112                let ncodes = ctxt.read::<U8>()?;
1113                let codes = ctxt.read_array::<U8>(usize::from(ncodes))?;
1114                Ok(CustomEncoding::Format0 { codes })
1115            }
1116            1 => {
1117                let nranges = ctxt.read::<U8>()?;
1118                let ranges = ctxt.read_array::<Range<u8, u8>>(usize::from(nranges))?;
1119                Ok(CustomEncoding::Format1 { ranges })
1120            }
1121            // The CFF spec notes:
1122            // A few fonts have multiply-encoded glyphs which are not supported directly by any of
1123            // the above formats. This situation is indicated by setting the high-order bit in the
1124            // format byte and supplementing the encoding.
1125            //
1126            // This is not handed as it is not expected that these will be encountered in CFF in
1127            // OTF files.
1128            format if format & 0x80 == 0x80 => Err(ParseError::NotImplemented),
1129            _ => Err(ParseError::BadValue),
1130        }
1131    }
1132}
1133
1134impl<'a> WriteBinary<&Self> for CustomEncoding<'a> {
1135    type Output = ();
1136
1137    fn write<C: WriteContext>(ctxt: &mut C, encoding: &Self) -> Result<(), WriteError> {
1138        match encoding {
1139            CustomEncoding::Format0 { codes } => {
1140                U8::write(ctxt, 0)?; // format
1141                U8::write(ctxt, u8::try_from(codes.len())?)?;
1142                <&ReadArray<'_, _>>::write(ctxt, codes)?;
1143            }
1144            CustomEncoding::Format1 { ranges } => {
1145                U8::write(ctxt, 1)?; // format
1146                U8::write(ctxt, u8::try_from(ranges.len())?)?;
1147                <&ReadArray<'_, _>>::write(ctxt, ranges)?;
1148            }
1149        }
1150
1151        Ok(())
1152    }
1153}
1154
1155impl<'a> Charset<'a> {
1156    /// Returns the id of the SID (Type 1 font) or CID (CID keyed font) of the name of the supplied glyph
1157    pub fn id_for_glyph(&self, glyph_id: u16) -> Option<u16> {
1158        match self {
1159            // In ISOAdobe glyph ID maps to SID
1160            Charset::ISOAdobe => {
1161                if glyph_id <= ISO_ADOBE_LAST_SID {
1162                    Some(glyph_id)
1163                } else {
1164                    None
1165                }
1166            }
1167            Charset::Expert => EXPERT_CHARSET.get(usize::from(glyph_id)).copied(),
1168            Charset::ExpertSubset => EXPERT_SUBSET_CHARSET.get(usize::from(glyph_id)).copied(),
1169            Charset::Custom(custom) => custom.id_for_glyph(glyph_id),
1170        }
1171    }
1172
1173    /// Returns the glyph id of the supplied string id.
1174    pub fn sid_to_gid(&self, sid: SID) -> Option<u16> {
1175        if sid == 0 {
1176            return Some(0);
1177        }
1178
1179        match self {
1180            Charset::ISOAdobe | Charset::Expert | Charset::ExpertSubset => None,
1181            Charset::Custom(custom) => custom.sid_to_gid(sid),
1182        }
1183    }
1184}
1185
1186impl<'b> ReadBinaryDep for CustomCharset<'b> {
1187    type Args<'a> = usize;
1188    type HostType<'a> = CustomCharset<'a>;
1189
1190    fn read_dep<'a>(
1191        ctxt: &mut ReadCtxt<'a>,
1192        n_glyphs: usize,
1193    ) -> Result<Self::HostType<'a>, ParseError> {
1194        // (There is one less element in the charset than nGlyphs because the .notdef glyph name is omitted.)
1195        let n_glyphs = n_glyphs.checked_sub(1).ok_or(ParseError::BadValue)?;
1196        match ctxt.read::<U8>()? {
1197            0 => {
1198                // The number of glyphs (nGlyphs) is the value of the count field in the
1199                // CharStrings INDEX.
1200                let glyphs = ctxt.read_array::<U16Be>(n_glyphs)?;
1201                Ok(CustomCharset::Format0 {
1202                    glyphs: ReadArrayCow::Borrowed(glyphs),
1203                })
1204            }
1205            1 => {
1206                let ranges = read_range_array(ctxt, n_glyphs)?;
1207                Ok(CustomCharset::Format1 {
1208                    ranges: ReadArrayCow::Borrowed(ranges),
1209                })
1210            }
1211            2 => {
1212                let ranges = read_range_array(ctxt, n_glyphs)?;
1213                Ok(CustomCharset::Format2 {
1214                    ranges: ReadArrayCow::Borrowed(ranges),
1215                })
1216            }
1217            _ => Err(ParseError::BadValue),
1218        }
1219    }
1220}
1221
1222impl<'a> WriteBinary<&Self> for CustomCharset<'a> {
1223    type Output = ();
1224
1225    fn write<C: WriteContext>(ctxt: &mut C, charset: &Self) -> Result<(), WriteError> {
1226        match charset {
1227            CustomCharset::Format0 { glyphs } => {
1228                U8::write(ctxt, 0)?; // format
1229                ReadArrayCow::write(ctxt, glyphs)?;
1230            }
1231            CustomCharset::Format1 { ranges } => {
1232                U8::write(ctxt, 1)?; // format
1233                ReadArrayCow::write(ctxt, ranges)?;
1234            }
1235            CustomCharset::Format2 { ranges } => {
1236                U8::write(ctxt, 2)?; // format
1237                ReadArrayCow::write(ctxt, ranges)?;
1238            }
1239        }
1240
1241        Ok(())
1242    }
1243}
1244
1245impl<'a> CustomCharset<'a> {
1246    pub fn iter(&'a self) -> Box<dyn Iterator<Item = u16> + 'a> {
1247        let notdef = iter::once(0);
1248        match &self {
1249            CustomCharset::Format0 { glyphs } => Box::new(notdef.chain(glyphs.iter())),
1250            CustomCharset::Format1 { ranges } => {
1251                Box::new(notdef.chain(ranges.iter().flat_map(|range| range.iter())))
1252            }
1253            CustomCharset::Format2 { ranges } => {
1254                Box::new(notdef.chain(ranges.iter().flat_map(|range| range.iter())))
1255            }
1256        }
1257    }
1258
1259    /// Returns the SID (Type 1 font) or CID (CID keyed font) of the name of the supplied glyph
1260    pub fn id_for_glyph(&self, glyph_id: u16) -> Option<u16> {
1261        // Section 11 of Technical Note #5176:
1262        // By definition the first glyph (GID 0) is ā€œ.notdefā€ and must be present in all fonts.
1263        // Since this is always the case, it is not necessary to represent either the encoding
1264        // (unencoded) or name (.notdef) for GID 0. Consequently, taking advantage of this
1265        // optimization, the encoding and charset arrays always begin with GID 1.
1266        if glyph_id == 0 {
1267            return Some(0);
1268        }
1269
1270        match self {
1271            CustomCharset::Format0 { glyphs } => {
1272                let index = usize::from(glyph_id - 1);
1273                glyphs
1274                    .check_index(index)
1275                    .map(|_| glyphs.get_item(index))
1276                    .ok()
1277            }
1278            CustomCharset::Format1 { ranges } => Self::id_for_glyph_in_ranges(ranges, glyph_id),
1279            CustomCharset::Format2 { ranges } => Self::id_for_glyph_in_ranges(ranges, glyph_id),
1280        }
1281    }
1282
1283    pub fn sid_to_gid(&self, sid: SID) -> Option<u16> {
1284        match self {
1285            CustomCharset::Format0 { glyphs: array } => {
1286                // First glyph is omitted, so we have to add 1.
1287                array
1288                    .into_iter()
1289                    .position(|n| n == sid)
1290                    .and_then(|n| u16::try_from(n + 1).ok())
1291            }
1292            CustomCharset::Format1 { ranges } => Self::glyph_id_for_sid_in_ranges(ranges, sid),
1293            CustomCharset::Format2 { ranges } => Self::glyph_id_for_sid_in_ranges(ranges, sid),
1294        }
1295    }
1296
1297    fn glyph_id_for_sid_in_ranges<F, N>(
1298        ranges: &ReadArrayCow<'a, Range<F, N>>,
1299        sid: SID,
1300    ) -> Option<u16>
1301    where
1302        F: num::Unsigned + Copy,
1303        N: num::Unsigned + Copy,
1304        u32: From<N> + From<F>,
1305        u16: From<N> + From<F>,
1306        Range<F, N>: ReadFrom,
1307    {
1308        let mut glyph_id = 1;
1309        for range in ranges.iter() {
1310            let last = u32::from(range.first) + u32::from(range.n_left);
1311            if u16::from(range.first) <= sid && u32::from(sid) <= last {
1312                glyph_id += sid - u16::from(range.first);
1313                return Some(glyph_id);
1314            }
1315
1316            glyph_id += u16::from(range.n_left) + 1;
1317        }
1318
1319        None
1320    }
1321
1322    fn id_for_glyph_in_ranges<F, N>(
1323        ranges: &ReadArrayCow<'a, Range<F, N>>,
1324        glyph_id: u16,
1325    ) -> Option<u16>
1326    where
1327        F: num::Unsigned + Copy,
1328        N: num::Unsigned + Copy,
1329        usize: From<N> + From<F>,
1330        Range<F, N>: ReadFrom,
1331        <Range<F, N> as ReadUnchecked>::HostType: Copy,
1332    {
1333        let glyph_id = usize::from(glyph_id);
1334
1335        ranges
1336            .iter()
1337            .scan(0usize, |glyphs_covered, range| {
1338                *glyphs_covered += range.len();
1339                Some((*glyphs_covered, range))
1340            })
1341            .find(|(glyphs_covered, _range)| glyph_id <= *glyphs_covered)
1342            .and_then(|(glyphs_covered, range)| {
1343                (usize::from(range.first) + (glyph_id - (glyphs_covered - range.len()) - 1))
1344                    .try_into()
1345                    .ok()
1346            })
1347    }
1348}
1349
1350impl<'b> ReadBinaryDep for FDSelect<'b> {
1351    type Args<'a> = usize;
1352    type HostType<'a> = FDSelect<'a>;
1353
1354    fn read_dep<'a>(
1355        ctxt: &mut ReadCtxt<'a>,
1356        n_glyphs: usize,
1357    ) -> Result<Self::HostType<'a>, ParseError> {
1358        match ctxt.read::<U8>()? {
1359            0 => {
1360                let glyph_font_dict_indices = ctxt.read_array::<U8>(n_glyphs)?;
1361                Ok(FDSelect::Format0 {
1362                    glyph_font_dict_indices: ReadArrayCow::Borrowed(glyph_font_dict_indices),
1363                })
1364            }
1365            3 => {
1366                let nranges = usize::from(ctxt.read::<U16Be>()?);
1367                let ranges = ctxt.read_array(nranges)?;
1368                let sentinel = ctxt.read::<U16Be>()?;
1369                Ok(FDSelect::Format3 {
1370                    ranges: ReadArrayCow::Borrowed(ranges),
1371                    sentinel,
1372                })
1373            }
1374            // Format4 was added in CFF2, it allows GIDs greater than u16::MAX but the
1375            // rest of the OpenType format does not accommodate this yet, so it's not
1376            // implemented.
1377            4 => Err(ParseError::NotImplemented),
1378            _ => Err(ParseError::BadValue),
1379        }
1380    }
1381}
1382
1383impl<'a> WriteBinary<&Self> for FDSelect<'a> {
1384    type Output = ();
1385
1386    fn write<C: WriteContext>(ctxt: &mut C, fd_select: &Self) -> Result<(), WriteError> {
1387        match fd_select {
1388            FDSelect::Format0 {
1389                glyph_font_dict_indices,
1390            } => {
1391                U8::write(ctxt, 0)?; // format
1392                ReadArrayCow::write(ctxt, glyph_font_dict_indices)?;
1393            }
1394            FDSelect::Format3 { ranges, sentinel } => {
1395                U8::write(ctxt, 3)?; // format
1396                U16Be::write(ctxt, u16::try_from(ranges.len())?)?;
1397                ReadArrayCow::write(ctxt, ranges)?;
1398                U16Be::write(ctxt, *sentinel)?;
1399            }
1400        }
1401
1402        Ok(())
1403    }
1404}
1405
1406impl<'a> PartialEq for FDSelect<'a> {
1407    fn eq(&self, other: &Self) -> bool {
1408        match (self, other) {
1409            (
1410                FDSelect::Format0 {
1411                    glyph_font_dict_indices: self_glyph_font_dict_indices,
1412                },
1413                FDSelect::Format0 {
1414                    glyph_font_dict_indices: other_glyph_font_dict_indices,
1415                },
1416            ) => {
1417                self_glyph_font_dict_indices.len() == other_glyph_font_dict_indices.len()
1418                    && self_glyph_font_dict_indices
1419                        .iter()
1420                        .zip(other_glyph_font_dict_indices.iter())
1421                        .all(|(left, right)| left == right)
1422            }
1423            (
1424                FDSelect::Format3 {
1425                    ranges: self_ranges,
1426                    sentinel: self_sentinel,
1427                },
1428                FDSelect::Format3 {
1429                    ranges: other_ranges,
1430                    sentinel: other_sentinel,
1431                },
1432            ) => {
1433                self_ranges.len() == other_ranges.len()
1434                    && self_sentinel == other_sentinel
1435                    && self_ranges
1436                        .iter()
1437                        .zip(other_ranges.iter())
1438                        .all(|(left, right)| left == right)
1439            }
1440            _ => false,
1441        }
1442    }
1443}
1444
1445impl<'a> FDSelect<'a> {
1446    /// Returns the index of the Font DICT for the supplied `glyph_id`
1447    pub fn font_dict_index(&self, glyph_id: u16) -> Option<u8> {
1448        let index = usize::from(glyph_id);
1449        match self {
1450            FDSelect::Format0 {
1451                glyph_font_dict_indices,
1452            } => glyph_font_dict_indices
1453                .check_index(index)
1454                .ok()
1455                .map(|_| glyph_font_dict_indices.get_item(index)),
1456            FDSelect::Format3 { ranges, sentinel } => {
1457                #[rustfmt::skip]
1458                let range_windows = ranges
1459                    .iter()
1460                    .map(|Range { first, n_left }| (first, Some(n_left)))
1461                    .chain(iter::once((*sentinel, None)))
1462                    .tuple_windows();
1463
1464                for ((first, fd_index), (last, _)) in range_windows {
1465                    if glyph_id >= first && glyph_id < last {
1466                        return fd_index;
1467                    }
1468                }
1469
1470                None
1471            }
1472        }
1473    }
1474}
1475
1476impl<'a> Index<'a> {
1477    fn read_object(&self, index: usize) -> Option<&[u8]> {
1478        if index < self.count {
1479            let start_index = lookup_offset_index(self.off_size, self.offset_array, index) - 1;
1480            let end_index = lookup_offset_index(self.off_size, self.offset_array, index + 1) - 1;
1481            Some(&self.data_array[start_index..end_index])
1482        } else {
1483            None
1484        }
1485    }
1486
1487    pub fn read<T: ReadBinaryDep>(
1488        &'a self,
1489        index: usize,
1490        args: T::Args<'a>,
1491    ) -> Result<T::HostType<'a>, ParseError> {
1492        let data = self.read_object(index).ok_or(ParseError::BadIndex)?;
1493        ReadScope::new(data).read_dep::<T>(args)
1494    }
1495
1496    pub fn iter(&self) -> impl Iterator<Item = &[u8]> {
1497        // NOTE(unwrap): Safe since we're iterating over valid indices
1498        (0..self.count).map(move |i| self.read_object(i).unwrap())
1499    }
1500
1501    /// Returns the length required to write `objects`.
1502    pub fn calculate_size<'b, T, HostType>(
1503        objects: &'b [&HostType],
1504        args: T::Args,
1505    ) -> Result<usize, WriteError>
1506    where
1507        T: WriteBinaryDep<&'b HostType>,
1508        T::Args: Clone,
1509    {
1510        let mut counter = WriteCounter::new();
1511
1512        U16Be::write(&mut counter, u16::try_from(objects.len())?)?;
1513        let off_size = if !objects.is_empty() {
1514            let start = counter.bytes_written();
1515            for obj in objects {
1516                T::write_dep(&mut counter, obj, args.clone())?;
1517            }
1518            let last_offset = counter.bytes_written() - start + 1; // +1 because index offsets start at 1
1519            let off_size = offset_size(last_offset).ok_or(WriteError::BadValue)?;
1520            U8::write(&mut counter, off_size)?;
1521            off_size
1522        } else {
1523            0
1524        };
1525
1526        let offset_array_size = usize::from(off_size) * (objects.len() + 1);
1527        Ok(counter.bytes_written() + offset_array_size)
1528    }
1529
1530    /// Returns the size of the data held by this INDEX.
1531    pub fn data_len(&self) -> usize {
1532        self.data_array.len()
1533    }
1534}
1535
1536impl<'a> MaybeOwnedIndex<'a> {
1537    pub fn iter(&'a self) -> MaybeOwnedIndexIterator<'a> {
1538        MaybeOwnedIndexIterator {
1539            data: self,
1540            index: 0,
1541        }
1542    }
1543
1544    pub fn read_object(&self, index: usize) -> Option<&[u8]> {
1545        match self {
1546            MaybeOwnedIndex::Borrowed(idx) => idx.read_object(index),
1547            MaybeOwnedIndex::Owned(idx) => idx.read_object(index),
1548        }
1549    }
1550
1551    /// Returns the number of items in self.
1552    pub fn len(&self) -> usize {
1553        match self {
1554            MaybeOwnedIndex::Borrowed(index) => index.count,
1555            MaybeOwnedIndex::Owned(index) => index.data.len(),
1556        }
1557    }
1558
1559    /// Returns the index of `object` in self if found.
1560    fn index(&self, object: &[u8]) -> Option<usize> {
1561        self.iter().position(|obj| obj == object)
1562    }
1563
1564    /// Push an object onto this `MaybeOwnedIndex`. Returns the index of the object in self.
1565    ///
1566    /// If self is `Borrowed` then it is converted to the `Owned` variant first.
1567    fn push(&mut self, object: Vec<u8>) -> usize {
1568        match self {
1569            MaybeOwnedIndex::Borrowed(_) => {
1570                self.to_owned();
1571                self.push(object);
1572            }
1573            MaybeOwnedIndex::Owned(index) => {
1574                index.data.push(object);
1575            }
1576        }
1577
1578        self.len() - 1
1579    }
1580
1581    /// Replace the object at `idx` with `object`.
1582    ///
1583    /// If self is `Borrowed` then it is converted to the `Owned` variant first.
1584    ///
1585    /// **Panics**
1586    ///
1587    /// Panics if `idx` is out of bounds.
1588    pub fn replace(&mut self, idx: usize, object: Vec<u8>) {
1589        match self {
1590            MaybeOwnedIndex::Borrowed(_) => {
1591                self.to_owned();
1592                self.replace(idx, object);
1593            }
1594            MaybeOwnedIndex::Owned(index) => index.data[idx] = object,
1595        }
1596    }
1597
1598    /// If self is the `Borrowed` variant, convert to the `Owned` variant.
1599    fn to_owned(&mut self) {
1600        match self {
1601            MaybeOwnedIndex::Borrowed(data) => {
1602                let data = data.iter().map(|obj| obj.to_owned()).collect();
1603                *self = MaybeOwnedIndex::Owned(owned::Index { data })
1604            }
1605            MaybeOwnedIndex::Owned(_) => {}
1606        }
1607    }
1608
1609    pub fn data_len(&self) -> usize {
1610        match self {
1611            MaybeOwnedIndex::Borrowed(index) => index.data_len(),
1612            MaybeOwnedIndex::Owned(index) => index.data.iter().map(|data| data.len()).sum(),
1613        }
1614    }
1615
1616    pub(crate) fn write32<C: WriteContext>(
1617        ctxt: &mut C,
1618        index: &MaybeOwnedIndex<'_>,
1619    ) -> Result<(), WriteError> {
1620        match index {
1621            MaybeOwnedIndex::Borrowed(index) => IndexU32::write(ctxt, index),
1622            MaybeOwnedIndex::Owned(index) => owned::IndexU32::write(ctxt, index),
1623        }
1624    }
1625
1626    pub(crate) fn write16<C: WriteContext>(
1627        ctxt: &mut C,
1628        index: &MaybeOwnedIndex<'_>,
1629    ) -> Result<(), WriteError> {
1630        match index {
1631            MaybeOwnedIndex::Borrowed(index) => IndexU16::write(ctxt, index),
1632            MaybeOwnedIndex::Owned(index) => owned::IndexU16::write(ctxt, index),
1633        }
1634    }
1635}
1636
1637impl<'a> Iterator for MaybeOwnedIndexIterator<'a> {
1638    type Item = &'a [u8];
1639
1640    fn next(&mut self) -> Option<Self::Item> {
1641        if self.index < self.data.len() {
1642            let index = self.index;
1643            self.index += 1;
1644            self.data.read_object(index)
1645        } else {
1646            None
1647        }
1648    }
1649
1650    fn size_hint(&self) -> (usize, Option<usize>) {
1651        let len = self.data.len();
1652        (len, Some(len))
1653    }
1654}
1655
1656impl DictDefault for TopDictDefault {
1657    fn default(op: Operator) -> Option<&'static [Operand]> {
1658        match op {
1659            Operator::IsFixedPitch => Some(&OPERAND_ZERO),
1660            Operator::ItalicAngle => Some(&OPERAND_ZERO),
1661            Operator::UnderlinePosition => Some(&DEFAULT_UNDERLINE_POSITION),
1662            Operator::UnderlineThickness => Some(&DEFAULT_UNDERLINE_THICKNESS),
1663            Operator::PaintType => Some(&OPERAND_ZERO),
1664            Operator::CharstringType => Some(&DEFAULT_CHARSTRING_TYPE),
1665            Operator::FontMatrix => Some(DEFAULT_FONT_MATRIX.as_ref()),
1666            Operator::FontBBox => Some(&DEFAULT_BBOX),
1667            Operator::StrokeWidth => Some(&OPERAND_ZERO),
1668            Operator::Charset => Some(&OFFSET_ZERO),
1669            Operator::Encoding => Some(&OFFSET_ZERO),
1670            Operator::CIDFontVersion => Some(&OPERAND_ZERO),
1671            Operator::CIDFontRevision => Some(&OPERAND_ZERO),
1672            Operator::CIDFontType => Some(&OPERAND_ZERO),
1673            Operator::CIDCount => Some(&DEFAULT_CID_COUNT),
1674            _ => None,
1675        }
1676    }
1677}
1678
1679impl DictDefault for FontDictDefault {
1680    fn default(_op: Operator) -> Option<&'static [Operand]> {
1681        None
1682    }
1683}
1684
1685impl DictDefault for PrivateDictDefault {
1686    fn default(op: Operator) -> Option<&'static [Operand]> {
1687        match op {
1688            Operator::BlueScale => Some(DEFAULT_BLUE_SCALE.as_ref()),
1689            Operator::BlueShift => Some(&DEFAULT_BLUE_SHIFT),
1690            Operator::BlueFuzz => Some(&DEFAULT_BLUE_FUZZ),
1691            Operator::ForceBold => Some(&OPERAND_ZERO),
1692            Operator::LanguageGroup => Some(&OPERAND_ZERO),
1693            Operator::ExpansionFactor => Some(DEFAULT_EXPANSION_FACTOR.as_ref()),
1694            Operator::InitialRandomSeed => Some(&OPERAND_ZERO),
1695            Operator::StrokeWidth => Some(&OPERAND_ZERO),
1696            Operator::DefaultWidthX => Some(&OPERAND_ZERO),
1697            Operator::NominalWidthX => Some(&OPERAND_ZERO),
1698            _ => None,
1699        }
1700    }
1701}
1702
1703impl<'a, T> Dict<T>
1704where
1705    T: DictDefault,
1706{
1707    pub fn new() -> Self {
1708        Dict {
1709            dict: Vec::new(),
1710            default: PhantomData,
1711        }
1712    }
1713
1714    pub fn get_with_default(&self, key: Operator) -> Option<&[Operand]> {
1715        self.get(key).or_else(|| T::default(key))
1716    }
1717
1718    pub fn get(&self, key: Operator) -> Option<&[Operand]> {
1719        self.dict.iter().find_map(|(op, args)| {
1720            if *op == key {
1721                Some(args.as_slice())
1722            } else {
1723                None
1724            }
1725        })
1726    }
1727
1728    /// Returns the i32 value of this operator if the operands hold a single Integer.
1729    pub fn get_i32(&self, key: Operator) -> Option<Result<i32, ParseError>> {
1730        self.get_with_default(key).map(|operands| match operands {
1731            [Operand::Integer(number)] => Ok(*number),
1732            [Operand::Offset(number)] => Ok(*number),
1733            _ => Err(ParseError::BadValue),
1734        })
1735    }
1736
1737    pub fn iter(&self) -> impl Iterator<Item = &(Operator, Vec<Operand>)> {
1738        self.dict.iter()
1739    }
1740
1741    /// Returns the first operator of this DICT or `None` if the DICT is empty.
1742    pub fn first_operator(&self) -> Option<Operator> {
1743        self.iter().next().map(|(operator, _)| *operator)
1744    }
1745
1746    /// Read a PrivateDict from this Dict returning it and its offset within `scope` on success.
1747    ///
1748    /// A Private DICT is required, but may be specified as having a length of 0 if there are no
1749    /// non-default values to be stored.
1750    pub fn read_private_dict<D: ReadBinaryDep<Args<'a> = usize>>(
1751        &self,
1752        scope: &ReadScope<'a>,
1753        max_operands: usize,
1754    ) -> Result<(D::HostType<'a>, usize), ParseError> {
1755        let (private_dict_offset, private_dict_length) =
1756            match self.get_with_default(Operator::Private) {
1757                Some([Operand::Offset(length), Operand::Offset(offset)]) => {
1758                    Ok((usize::try_from(*offset)?, usize::try_from(*length)?))
1759                }
1760                Some(_) => Err(ParseError::BadValue),
1761                None => Err(ParseError::MissingValue),
1762            }?;
1763        scope
1764            .offset_length(private_dict_offset, private_dict_length)?
1765            .read_dep::<D>(max_operands)
1766            .map(|dict| (dict, private_dict_offset))
1767    }
1768
1769    pub fn len(&self) -> usize {
1770        self.dict.len()
1771    }
1772
1773    fn inner_mut(&mut self) -> &mut Vec<(Operator, Vec<Operand>)> {
1774        &mut self.dict
1775    }
1776
1777    fn remove(&mut self, operator: Operator) {
1778        if let Some(index) = self.dict.iter().position(|(op, _)| *op == operator) {
1779            self.dict.remove(index);
1780        }
1781    }
1782
1783    /// Replace the entry in the DICT for `operator` with `operands`.
1784    ///
1785    /// If `operator` is not found then append it to the DICT.
1786    fn replace(&mut self, operator: Operator, operands: Vec<Operand>) {
1787        match self.dict.iter().position(|(op, _)| *op == operator) {
1788            Some(index) => self.dict[index] = (operator, operands),
1789            None => self.dict.push((operator, operands)),
1790        }
1791    }
1792
1793    /// Apply variation data to this Dict according to `instance` to produce a new Dict.
1794    ///
1795    /// The new Dict is no longer variable and does not contain any vsindex or blend operators.
1796    fn instance(
1797        &self,
1798        instance: &OwnedTuple,
1799        vstore: &ItemVariationStore<'_>,
1800    ) -> Result<Self, VariationError> {
1801        let mut dict = Vec::new();
1802        let mut vsindex = 0;
1803        let mut stack = ArgumentsStack {
1804            data: &mut [0.0; cff2::MAX_OPERANDS],
1805            len: 0,
1806            max_len: cff2::MAX_OPERANDS,
1807        };
1808
1809        for (op, operands) in self.iter() {
1810            match op {
1811                Operator::VSIndex => match operands.as_slice() {
1812                    [Operand::Integer(variation_index)] => vsindex = *variation_index,
1813                    _ => return Err(ParseError::BadValue.into()),
1814                },
1815                Operator::Blend => {
1816                    // do the blend, generating new operands for the following op to inherit
1817                    operands
1818                        .iter()
1819                        .try_for_each(|operand| stack.push(f32::try_from(operand)?))?;
1820
1821                    let scalars = cff2::scalars(
1822                        u16::try_from(vsindex).map_err(ParseError::from)?,
1823                        vstore,
1824                        instance,
1825                    )?;
1826
1827                    cff2::blend(&scalars, &mut stack)?;
1828                }
1829                _ if !stack.is_empty() => {
1830                    // The operator needs to operate on any blended operands on the stack in
1831                    // addition to any that were supplied to it. All operators except `blend` clear
1832                    // the stack:
1833                    //
1834                    // "In well-formed CFF2 data, the number of operands preceding a DICT key
1835                    // operator must be exactly the number required for that operator; hence, the
1836                    // stack will be empty after the operator is processed."
1837
1838                    // Take all the operands, clearing out the stack at the same time
1839                    let mut new_operands = stack
1840                        .pop_all()
1841                        .iter()
1842                        .copied()
1843                        .map(Operand::from)
1844                        .collect::<Vec<_>>();
1845                    new_operands.extend(operands.iter().cloned());
1846                    dict.push((*op, new_operands));
1847                }
1848                _ => dict.push((*op, operands.clone())),
1849            }
1850        }
1851
1852        Ok(Dict {
1853            dict,
1854            default: PhantomData,
1855        })
1856    }
1857}
1858
1859impl BlendOperand for f32 {
1860    fn try_as_i32(self) -> Option<i32> {
1861        i32::try_num_from(self)
1862    }
1863
1864    fn try_as_u16(self) -> Option<u16> {
1865        if self.fract() == 0.0 {
1866            u16::try_from(self as i32).ok()
1867        } else {
1868            None
1869        }
1870    }
1871
1872    fn try_as_u8(self) -> Option<u8> {
1873        u8::try_num_from(self)
1874    }
1875}
1876
1877impl DictDelta {
1878    pub fn new() -> Self {
1879        DictDelta { dict: Vec::new() }
1880    }
1881
1882    pub fn get(&self, key: Operator) -> Option<&[Operand]> {
1883        self.dict
1884            .iter()
1885            .filter_map(|(op, args)| {
1886                if *op == key {
1887                    Some(args.as_slice())
1888                } else {
1889                    None
1890                }
1891            })
1892            .next()
1893    }
1894
1895    /// Push `operator` on this Dict as an Offset Operand
1896    pub fn push_offset(&mut self, operator: Operator, offset: i32) {
1897        self.dict
1898            .push((operator, tiny_vec!([Operand; 1] => Operand::Offset(offset))))
1899    }
1900
1901    /// Push `operands` onto this Dict
1902    ///
1903    /// Panics if all `operands` are not `Operand::Offsets`
1904    pub fn push(&mut self, operator: Operator, operands: TinyVec<[Operand; 1]>) {
1905        assert!(operands.iter().all(Operand::is_offset));
1906        self.dict.push((operator, operands))
1907    }
1908}
1909
1910impl<'a> CIDData<'a> {
1911    pub fn font_dict(&self, index: usize) -> Result<FontDict, ParseError> {
1912        let data = self
1913            .font_dict_index
1914            .read_object(index)
1915            .ok_or(ParseError::BadIndex)?;
1916        ReadScope::new(data).read_dep::<FontDict>(MAX_OPERANDS)
1917    }
1918}
1919
1920impl TryFrom<u16> for Operator {
1921    type Error = ParseError;
1922
1923    fn try_from(value: u16) -> Result<Self, Self::Error> {
1924        if (value & 0xFF00) == (12 << 8) {
1925            match value as u8 {
1926                0 => Ok(Operator::Copyright),
1927                1 => Ok(Operator::IsFixedPitch),
1928                2 => Ok(Operator::ItalicAngle),
1929                3 => Ok(Operator::UnderlinePosition),
1930                4 => Ok(Operator::UnderlineThickness),
1931                5 => Ok(Operator::PaintType),
1932                6 => Ok(Operator::CharstringType),
1933                7 => Ok(Operator::FontMatrix),
1934                8 => Ok(Operator::StrokeWidth),
1935                9 => Ok(Operator::BlueScale),
1936                10 => Ok(Operator::BlueShift),
1937                11 => Ok(Operator::BlueFuzz),
1938                12 => Ok(Operator::StemSnapH),
1939                13 => Ok(Operator::StemSnapV),
1940                14 => Ok(Operator::ForceBold),
1941                17 => Ok(Operator::LanguageGroup),
1942                18 => Ok(Operator::ExpansionFactor),
1943                19 => Ok(Operator::InitialRandomSeed),
1944                20 => Ok(Operator::SyntheticBase),
1945                21 => Ok(Operator::PostScript),
1946                22 => Ok(Operator::BaseFontName),
1947                23 => Ok(Operator::BaseFontBlend),
1948                30 => Ok(Operator::ROS),
1949                31 => Ok(Operator::CIDFontVersion),
1950                32 => Ok(Operator::CIDFontRevision),
1951                33 => Ok(Operator::CIDFontType),
1952                34 => Ok(Operator::CIDCount),
1953                35 => Ok(Operator::UIDBase),
1954                36 => Ok(Operator::FDArray),
1955                37 => Ok(Operator::FDSelect),
1956                38 => Ok(Operator::FontName),
1957                _ => Err(ParseError::BadValue),
1958            }
1959        } else {
1960            match value {
1961                0 => Ok(Operator::Version),
1962                1 => Ok(Operator::Notice),
1963                2 => Ok(Operator::FullName),
1964                3 => Ok(Operator::FamilyName),
1965                4 => Ok(Operator::Weight),
1966                5 => Ok(Operator::FontBBox),
1967                6 => Ok(Operator::BlueValues),
1968                7 => Ok(Operator::OtherBlues),
1969                8 => Ok(Operator::FamilyBlues),
1970                9 => Ok(Operator::FamilyOtherBlues),
1971                10 => Ok(Operator::StdHW),
1972                11 => Ok(Operator::StdVW),
1973                13 => Ok(Operator::UniqueID),
1974                14 => Ok(Operator::XUID),
1975                15 => Ok(Operator::Charset),
1976                16 => Ok(Operator::Encoding),
1977                17 => Ok(Operator::CharStrings),
1978                18 => Ok(Operator::Private),
1979                19 => Ok(Operator::Subrs),
1980                20 => Ok(Operator::DefaultWidthX),
1981                21 => Ok(Operator::NominalWidthX),
1982                // CFF2
1983                22 => Ok(Operator::VSIndex),
1984                23 => Ok(Operator::Blend),
1985                24 => Ok(Operator::VStore),
1986                _ => Err(ParseError::BadValue),
1987            }
1988        }
1989    }
1990}
1991
1992impl Operand {
1993    pub fn is_offset(&self) -> bool {
1994        matches!(self, Operand::Offset(_))
1995    }
1996
1997    fn bcd_encode(buf: &mut TinyVec<[u8; 32]>, val: f32) -> Operand {
1998        if val == 0.0 {
1999            Operand::Integer(0)
2000        } else if val.fract() == 0.0 {
2001            Operand::Integer(val as i32)
2002        } else {
2003            // encode Real
2004            // https://learn.microsoft.com/en-us/typography/opentype/otspec191alpha/cff2#binary-coded-decimal
2005            buf.clear();
2006            // NOTE(unwrap): write into string won't return an error
2007            write!(buf, "{:E}", val).unwrap();
2008            // The formatter will always include an exponent. Drop it if it's "E0"
2009            if buf.ends_with(b"E0") {
2010                buf.truncate(buf.len() - 2);
2011            }
2012
2013            let mut chars = buf.iter().peekable();
2014            let mut bcd = tiny_vec!([u8; 7]);
2015            let mut pair = array_vec!([u8; 2]);
2016
2017            while let Some(c) = chars.next() {
2018                let nibble = match c {
2019                    b'0'..=b'9' => c - b'0',
2020                    b'.' => 0xA,
2021                    b'E' if chars.peek() == Some(&&b'-') => {
2022                        let _ = chars.next(); // discard '-'
2023                        0xC
2024                    }
2025                    b'E' => 0xB,
2026                    b'-' => 0xE,
2027                    _ => unreachable!(),
2028                };
2029                pair.push(nibble);
2030                if let [high, low] = pair.as_slice() {
2031                    bcd.push((high << 4) | low);
2032                    pair.clear();
2033                }
2034            }
2035
2036            // Add the end of number sentinel
2037            match pair.as_slice() {
2038                // "If the terminating 0xf nibble is the first nibble of a byte, then an additional
2039                // 0xf nibble must be appended (hence, the byte is 0xff) so that the encoded
2040                // representation is always a whole number of bytes."
2041                [] => bcd.push(0xFF),
2042                [high] => bcd.push((high << 4) | 0xF),
2043                _ => unreachable!(),
2044            }
2045            Operand::Real(Real(bcd))
2046        }
2047    }
2048}
2049
2050impl TryFrom<&Operand> for f32 {
2051    type Error = ParseError;
2052
2053    fn try_from(operand: &Operand) -> Result<f32, Self::Error> {
2054        const MAX: i32 = 1 << f32::MANTISSA_DIGITS;
2055        const MIN: i32 = -MAX;
2056
2057        match operand {
2058            Operand::Integer(int) | Operand::Offset(int) => (MIN..=MAX)
2059                .contains(int)
2060                .then_some(*int as f32)
2061                .ok_or(ParseError::LimitExceeded),
2062            Operand::Real(r) => f64::try_from(r).map_err(ParseError::from).and_then(|val| {
2063                (f32::MIN as f64..=f32::MAX as f64)
2064                    .contains(&val)
2065                    .then_some(val as f32)
2066                    .ok_or(ParseError::LimitExceeded)
2067            }),
2068        }
2069    }
2070}
2071
2072impl From<f32> for Operand {
2073    fn from(val: f32) -> Self {
2074        let mut buf = tiny_vec!([u8; 32]);
2075        Operand::bcd_encode(&mut buf, val)
2076    }
2077}
2078
2079// This exists so that Operand can be used in a TinyVec
2080impl Default for Operand {
2081    fn default() -> Self {
2082        Operand::Offset(0)
2083    }
2084}
2085
2086impl<'a> Font<'a> {
2087    pub fn is_cid_keyed(&self) -> bool {
2088        match self.data {
2089            CFFVariant::CID(_) => true,
2090            CFFVariant::Type1(_) => false,
2091        }
2092    }
2093
2094    // seac = standard encoding accented character, makes an accented character from two other
2095    // characters.
2096    pub(crate) fn seac_code_to_glyph_id(&self, code: u8) -> Option<GlyphId> {
2097        let sid = STANDARD_ENCODING[usize::from(code)];
2098
2099        match self.charset {
2100            Charset::ISOAdobe => {
2101                // ISO Adobe charset only defines string ids up to 228 (zcaron)
2102                if code <= 228 {
2103                    Some(u16::from(sid))
2104                } else {
2105                    None
2106                }
2107            }
2108            Charset::Expert | Charset::ExpertSubset => None,
2109            Charset::Custom(_) => self.charset.sid_to_gid(u16::from(sid)),
2110        }
2111    }
2112}
2113
2114fn lookup_offset_index(off_size: u8, offset_array: &[u8], index: usize) -> usize {
2115    let buf = &offset_array[index * usize::from(off_size)..];
2116    match off_size {
2117        1 => buf[0] as usize,
2118        2 => BigEndian::read_u16(buf) as usize,
2119        3 => BigEndian::read_u24(buf) as usize,
2120        4 => BigEndian::read_u32(buf) as usize,
2121        _ => panic!("unexpected off_size"),
2122    }
2123}
2124
2125fn read_range_array<'a, F, N>(
2126    ctxt: &mut ReadCtxt<'a>,
2127    n_glyphs: usize,
2128) -> Result<ReadArray<'a, Range<F, N>>, ParseError>
2129where
2130    Range<F, N>: ReadFrom,
2131    usize: From<N>,
2132    N: num::Unsigned + Copy,
2133{
2134    let mut peek = ctxt.scope().ctxt();
2135    let mut range_count = 0;
2136    let mut glyphs_covered = 0;
2137    while glyphs_covered < n_glyphs {
2138        let range = peek.read::<Range<F, N>>()?;
2139        range_count += 1;
2140        glyphs_covered += range.len();
2141    }
2142
2143    ctxt.read_array::<Range<F, N>>(range_count)
2144}
2145
2146fn write_cff_variant<C: WriteContext>(
2147    ctxt: &mut C,
2148    variant: &CFFVariant<'_>,
2149    top_dict_delta: &mut DictDelta,
2150) -> Result<(), WriteError> {
2151    match variant {
2152        CFFVariant::CID(cid_data) => {
2153            let offsets = CIDData::write(ctxt, cid_data)?;
2154            top_dict_delta.push_offset(Operator::FDArray, i32::try_from(offsets.font_dict_index)?);
2155            top_dict_delta.push_offset(Operator::FDSelect, i32::try_from(offsets.fd_select)?);
2156        }
2157        CFFVariant::Type1(type1_data) => {
2158            let offsets = Type1Data::write(ctxt, type1_data)?;
2159            if let Some(custom_encoding_offset) = offsets.custom_encoding {
2160                top_dict_delta
2161                    .push_offset(Operator::Encoding, i32::try_from(custom_encoding_offset)?);
2162            }
2163            top_dict_delta.push(
2164                Operator::Private,
2165                tiny_vec!([Operand; 1] => 
2166                    Operand::Offset(i32::try_from(offsets.private_dict_len)?),
2167                    Operand::Offset(i32::try_from(offsets.private_dict)?)),
2168            );
2169        }
2170    }
2171
2172    Ok(())
2173}
2174
2175// NOTE: Ideally the following read_* functions would ReadBinary or ReadBinaryDep impls.
2176// However we need to be able to indicate that the borrowed TopDict has a different lifetime
2177// to the other aspects, which is not currently possible.
2178// This post sums up the issue fairly well:
2179// https://lukaskalbertodt.github.io/2018/08/03/solving-the-generalized-streaming-iterator-problem-without-gats.html
2180// Rust tracking issue: https://github.com/rust-lang/rust/issues/44265
2181
2182fn read_cid_data<'a>(
2183    scope: &ReadScope<'a>,
2184    top_dict: &TopDict,
2185    n_glyphs: usize,
2186) -> Result<CIDData<'a>, ParseError> {
2187    // The Top DICT begins with ROS operator
2188    // which specifies the Registry-Ordering-Supplement for the font.
2189    // This will indicate to a CFF parser that special CID processing
2190    // should be applied to this font. Specifically:
2191    //
2192    // • The FDArray operator is expected to be present, with a single
2193    //   argument specifying an offset to the Font DICT INDEX. Each
2194    //   Font DICT in this array specifies information unique to a
2195    //   particular group of glyphs in the font.
2196    let offset = top_dict
2197        .get_i32(Operator::FDArray)
2198        .ok_or(ParseError::MissingValue)??;
2199    let font_dict_index = scope.offset(usize::try_from(offset)?).read::<IndexU16>()?;
2200
2201    let offset = top_dict
2202        .get_i32(Operator::FDSelect)
2203        .ok_or(ParseError::MissingValue)??;
2204    let fd_select = scope
2205        .offset(usize::try_from(offset)?)
2206        .read_dep::<FDSelect<'a>>(n_glyphs)?;
2207
2208    let mut private_dicts = Vec::with_capacity(font_dict_index.count);
2209    let mut local_subr_indices = Vec::with_capacity(font_dict_index.count);
2210    for object in font_dict_index.iter() {
2211        let font_dict = ReadScope::new(object).read_dep::<FontDict>(MAX_OPERANDS)?;
2212        let (private_dict, private_dict_offset) =
2213            font_dict.read_private_dict::<PrivateDict>(scope, MAX_OPERANDS)?;
2214        let local_subr_index =
2215            read_local_subr_index::<_, IndexU16>(scope, &private_dict, private_dict_offset)?
2216                .map(MaybeOwnedIndex::Borrowed);
2217
2218        private_dicts.push(private_dict);
2219        local_subr_indices.push(local_subr_index);
2220    }
2221
2222    Ok(CIDData {
2223        font_dict_index: MaybeOwnedIndex::Borrowed(font_dict_index),
2224        private_dicts,
2225        local_subr_indices,
2226        fd_select,
2227    })
2228}
2229
2230impl<'a> WriteBinary<&Self> for CIDData<'a> {
2231    type Output = CIDDataOffsets;
2232
2233    fn write<C: WriteContext>(ctxt: &mut C, data: &Self) -> Result<Self::Output, WriteError> {
2234        // Private DICTs and Local subroutines
2235        let mut private_dict_offset_lengths = Vec::with_capacity(data.private_dicts.len());
2236        for (private_dict, local_subr_index) in data
2237            .private_dicts
2238            .iter()
2239            .zip(data.local_subr_indices.iter())
2240        {
2241            let offset = ctxt.bytes_written();
2242            let written_length =
2243                write_private_dict_and_local_subr_index(ctxt, private_dict, local_subr_index)?;
2244            private_dict_offset_lengths.push((offset, written_length));
2245        }
2246
2247        // Font DICT INDEX
2248        let mut font_dict_data = WriteBuffer::new();
2249        let mut font_dict_offsets = Vec::with_capacity(data.font_dict_index.len());
2250        for (object, (offset, length)) in data
2251            .font_dict_index
2252            .iter()
2253            .zip(private_dict_offset_lengths.into_iter())
2254        {
2255            let font_dict = ReadScope::new(object)
2256                .read_dep::<FontDict>(MAX_OPERANDS)
2257                .map_err(|_err| WriteError::BadValue)?;
2258            let mut font_dict_delta = DictDelta::new();
2259            font_dict_delta.push(
2260                Operator::Private,
2261                tiny_vec!([Operand; 1] =>
2262                    Operand::Offset(i32::try_from(length)?),
2263                    Operand::Offset(i32::try_from(offset)?)),
2264            );
2265
2266            font_dict_offsets.push(font_dict_data.bytes_written() + 1); // +1 INDEXes start at offset 1
2267            FontDict::write_dep(&mut font_dict_data, &font_dict, font_dict_delta)?;
2268        }
2269        let last_font_dict_offset = font_dict_data.bytes_written() + 1;
2270        font_dict_offsets.push(last_font_dict_offset);
2271
2272        let (off_size, offset_array) = serialise_offset_array(font_dict_offsets)?;
2273        let font_dict_index = Index {
2274            count: data.font_dict_index.len(),
2275            off_size,
2276            offset_array: &offset_array,
2277            data_array: font_dict_data.bytes(),
2278        };
2279        let font_dict_index_offset = ctxt.bytes_written();
2280        IndexU16::write(ctxt, &font_dict_index)?;
2281
2282        let fd_select_offset = ctxt.bytes_written();
2283        FDSelect::write(ctxt, &data.fd_select)?;
2284
2285        Ok(CIDDataOffsets {
2286            font_dict_index: font_dict_index_offset,
2287            fd_select: fd_select_offset,
2288        })
2289    }
2290}
2291
2292impl<'a> WriteBinary<&Self> for Type1Data<'a> {
2293    type Output = Type1DataOffsets;
2294
2295    fn write<C: WriteContext>(ctxt: &mut C, data: &Self) -> Result<Self::Output, WriteError> {
2296        let mut offsets = Type1DataOffsets {
2297            custom_encoding: None,
2298            private_dict: ctxt.bytes_written(),
2299            private_dict_len: 0,
2300        };
2301
2302        offsets.private_dict_len = write_private_dict_and_local_subr_index(
2303            ctxt,
2304            &data.private_dict,
2305            &data.local_subr_index,
2306        )?;
2307
2308        if let Type1Data {
2309            encoding: Encoding::Custom(ref custom_encoding),
2310            ..
2311        } = data
2312        {
2313            offsets.custom_encoding = Some(ctxt.bytes_written());
2314            CustomEncoding::write(ctxt, custom_encoding)?;
2315        }
2316
2317        Ok(offsets)
2318    }
2319}
2320
2321/// Write the Private DICT and local subrs if present, returns the length of the Private DICT
2322fn write_private_dict_and_local_subr_index<C: WriteContext>(
2323    ctxt: &mut C,
2324    private_dict: &PrivateDict,
2325    local_subr_index: &Option<MaybeOwnedIndex<'_>>,
2326) -> Result<usize, WriteError> {
2327    // Determine how big the Private DICT will be
2328    let private_dict_length =
2329        PrivateDict::write_dep(&mut WriteCounter::new(), private_dict, DictDelta::new())?;
2330
2331    // Write Private DICT with updated offset to Local subroutines if present
2332    let mut private_dict_delta = DictDelta::new();
2333    if local_subr_index.is_some() {
2334        // This offset is relative to the start of the Private DICT
2335        private_dict_delta.push_offset(Operator::Subrs, i32::try_from(private_dict_length)?);
2336    }
2337    let written_length = PrivateDict::write_dep(ctxt, private_dict, private_dict_delta)?;
2338    assert_eq!(written_length, private_dict_length);
2339
2340    if let Some(local_subr_index) = local_subr_index {
2341        MaybeOwnedIndex::write16(ctxt, local_subr_index)?;
2342    }
2343
2344    Ok(written_length)
2345}
2346
2347fn read_encoding<'a>(
2348    scope: &ReadScope<'a>,
2349    top_dict: &TopDict,
2350) -> Result<Encoding<'a>, ParseError> {
2351    let offset = top_dict
2352        .get_i32(Operator::Encoding)
2353        .ok_or(ParseError::MissingValue)??;
2354    let encoding = match offset {
2355        0 => Encoding::Standard,
2356        1 => Encoding::Expert,
2357        _ => Encoding::Custom(
2358            scope
2359                .offset(usize::try_from(offset)?)
2360                .read::<CustomEncoding<'_>>()?,
2361        ),
2362    };
2363
2364    Ok(encoding)
2365}
2366
2367fn read_charset<'a>(
2368    scope: &ReadScope<'a>,
2369    top_dict: &TopDict,
2370    char_strings_count: usize,
2371) -> Result<Charset<'a>, ParseError> {
2372    let offset = top_dict
2373        .get_i32(Operator::Charset)
2374        .ok_or(ParseError::MissingValue)??;
2375    let charset = match offset {
2376        0 => Charset::ISOAdobe,
2377        1 => Charset::Expert,
2378        2 => Charset::ExpertSubset,
2379        _ => Charset::Custom(
2380            scope
2381                .offset(usize::try_from(offset)?)
2382                .read_dep::<CustomCharset<'_>>(char_strings_count)?,
2383        ),
2384    };
2385
2386    Ok(charset)
2387}
2388
2389fn read_local_subr_index<'a, T, Idx>(
2390    scope: &ReadScope<'a>,
2391    private_dict: &Dict<T>,
2392    private_dict_offset: usize,
2393) -> Result<Option<Index<'a>>, ParseError>
2394where
2395    T: DictDefault,
2396    Idx: ReadBinary<HostType<'a> = Index<'a>>,
2397{
2398    // Local subrs are stored in an INDEX structure which is located via the offset operand
2399    // of the Subrs operator in the Private DICT. A font without local subrs has no Subrs
2400    // operator in the Private DICT. The local subrs offset is relative to the beginning of
2401    // the Private DICT data.
2402    private_dict
2403        .get_i32(Operator::Subrs)
2404        .transpose()?
2405        .map(|offset| {
2406            let offset = usize::try_from(offset)?;
2407            scope.offset(private_dict_offset + offset).read::<Idx>()
2408        })
2409        .transpose()
2410}
2411
2412/// Serialise the offsets using an optimal `off_size`, returning that and the serialised data.
2413fn serialise_offset_array(offsets: Vec<usize>) -> Result<(u8, Vec<u8>), WriteError> {
2414    if offsets.is_empty() {
2415        return Ok((1, Vec::new()));
2416    }
2417
2418    // NOTE(unwrap): Safe due to is_empty check
2419    let off_size = offset_size(*offsets.last().unwrap()).ok_or(WriteError::BadValue)?;
2420    let mut offset_array = WriteBuffer::new();
2421    match off_size {
2422        1 => offset_array.write_iter::<U8, _>(offsets.into_iter().map(|offset| offset as u8))?,
2423
2424        2 => {
2425            offset_array.write_iter::<U16Be, _>(offsets.into_iter().map(|offset| offset as u16))?
2426        }
2427
2428        3 => {
2429            offset_array.write_iter::<U24Be, _>(offsets.into_iter().map(|offset| offset as u32))?
2430        }
2431
2432        4 => {
2433            offset_array.write_iter::<U32Be, _>(offsets.into_iter().map(|offset| offset as u32))?
2434        }
2435
2436        _ => unreachable!(), // offset_size only returns 1..=4
2437    }
2438
2439    Ok((off_size, offset_array.into_inner()))
2440}
2441
2442impl<'a, 'data> CFFFont<'a, 'data> {
2443    pub fn is_cff(&self) -> bool {
2444        matches!(self, CFFFont::CFF(_))
2445    }
2446
2447    pub fn is_cff2(&self) -> bool {
2448        matches!(self, CFFFont::CFF2(_))
2449    }
2450}
2451
2452const STANDARD_STRINGS: [&str; 391] = [
2453    ".notdef",
2454    "space",
2455    "exclam",
2456    "quotedbl",
2457    "numbersign",
2458    "dollar",
2459    "percent",
2460    "ampersand",
2461    "quoteright",
2462    "parenleft",
2463    "parenright",
2464    "asterisk",
2465    "plus",
2466    "comma",
2467    "hyphen",
2468    "period",
2469    "slash",
2470    "zero",
2471    "one",
2472    "two",
2473    "three",
2474    "four",
2475    "five",
2476    "six",
2477    "seven",
2478    "eight",
2479    "nine",
2480    "colon",
2481    "semicolon",
2482    "less",
2483    "equal",
2484    "greater",
2485    "question",
2486    "at",
2487    "A",
2488    "B",
2489    "C",
2490    "D",
2491    "E",
2492    "F",
2493    "G",
2494    "H",
2495    "I",
2496    "J",
2497    "K",
2498    "L",
2499    "M",
2500    "N",
2501    "O",
2502    "P",
2503    "Q",
2504    "R",
2505    "S",
2506    "T",
2507    "U",
2508    "V",
2509    "W",
2510    "X",
2511    "Y",
2512    "Z",
2513    "bracketleft",
2514    "backslash",
2515    "bracketright",
2516    "asciicircum",
2517    "underscore",
2518    "quoteleft",
2519    "a",
2520    "b",
2521    "c",
2522    "d",
2523    "e",
2524    "f",
2525    "g",
2526    "h",
2527    "i",
2528    "j",
2529    "k",
2530    "l",
2531    "m",
2532    "n",
2533    "o",
2534    "p",
2535    "q",
2536    "r",
2537    "s",
2538    "t",
2539    "u",
2540    "v",
2541    "w",
2542    "x",
2543    "y",
2544    "z",
2545    "braceleft",
2546    "bar",
2547    "braceright",
2548    "asciitilde",
2549    "exclamdown",
2550    "cent",
2551    "sterling",
2552    "fraction",
2553    "yen",
2554    "florin",
2555    "section",
2556    "currency",
2557    "quotesingle",
2558    "quotedblleft",
2559    "guillemotleft",
2560    "guilsinglleft",
2561    "guilsinglright",
2562    "fi",
2563    "fl",
2564    "endash",
2565    "dagger",
2566    "daggerdbl",
2567    "periodcentered",
2568    "paragraph",
2569    "bullet",
2570    "quotesinglbase",
2571    "quotedblbase",
2572    "quotedblright",
2573    "guillemotright",
2574    "ellipsis",
2575    "perthousand",
2576    "questiondown",
2577    "grave",
2578    "acute",
2579    "circumflex",
2580    "tilde",
2581    "macron",
2582    "breve",
2583    "dotaccent",
2584    "dieresis",
2585    "ring",
2586    "cedilla",
2587    "hungarumlaut",
2588    "ogonek",
2589    "caron",
2590    "emdash",
2591    "AE",
2592    "ordfeminine",
2593    "Lslash",
2594    "Oslash",
2595    "OE",
2596    "ordmasculine",
2597    "ae",
2598    "dotlessi",
2599    "lslash",
2600    "oslash",
2601    "oe",
2602    "germandbls",
2603    "onesuperior",
2604    "logicalnot",
2605    "mu",
2606    "trademark",
2607    "Eth",
2608    "onehalf",
2609    "plusminus",
2610    "Thorn",
2611    "onequarter",
2612    "divide",
2613    "brokenbar",
2614    "degree",
2615    "thorn",
2616    "threequarters",
2617    "twosuperior",
2618    "registered",
2619    "minus",
2620    "eth",
2621    "multiply",
2622    "threesuperior",
2623    "copyright",
2624    "Aacute",
2625    "Acircumflex",
2626    "Adieresis",
2627    "Agrave",
2628    "Aring",
2629    "Atilde",
2630    "Ccedilla",
2631    "Eacute",
2632    "Ecircumflex",
2633    "Edieresis",
2634    "Egrave",
2635    "Iacute",
2636    "Icircumflex",
2637    "Idieresis",
2638    "Igrave",
2639    "Ntilde",
2640    "Oacute",
2641    "Ocircumflex",
2642    "Odieresis",
2643    "Ograve",
2644    "Otilde",
2645    "Scaron",
2646    "Uacute",
2647    "Ucircumflex",
2648    "Udieresis",
2649    "Ugrave",
2650    "Yacute",
2651    "Ydieresis",
2652    "Zcaron",
2653    "aacute",
2654    "acircumflex",
2655    "adieresis",
2656    "agrave",
2657    "aring",
2658    "atilde",
2659    "ccedilla",
2660    "eacute",
2661    "ecircumflex",
2662    "edieresis",
2663    "egrave",
2664    "iacute",
2665    "icircumflex",
2666    "idieresis",
2667    "igrave",
2668    "ntilde",
2669    "oacute",
2670    "ocircumflex",
2671    "odieresis",
2672    "ograve",
2673    "otilde",
2674    "scaron",
2675    "uacute",
2676    "ucircumflex",
2677    "udieresis",
2678    "ugrave",
2679    "yacute",
2680    "ydieresis",
2681    "zcaron",
2682    "exclamsmall",
2683    "Hungarumlautsmall",
2684    "dollaroldstyle",
2685    "dollarsuperior",
2686    "ampersandsmall",
2687    "Acutesmall",
2688    "parenleftsuperior",
2689    "parenrightsuperior",
2690    "twodotenleader",
2691    "onedotenleader",
2692    "zerooldstyle",
2693    "oneoldstyle",
2694    "twooldstyle",
2695    "threeoldstyle",
2696    "fouroldstyle",
2697    "fiveoldstyle",
2698    "sixoldstyle",
2699    "sevenoldstyle",
2700    "eightoldstyle",
2701    "nineoldstyle",
2702    "commasuperior",
2703    "threequartersemdash",
2704    "periodsuperior",
2705    "questionsmall",
2706    "asuperior",
2707    "bsuperior",
2708    "centsuperior",
2709    "dsuperior",
2710    "esuperior",
2711    "isuperior",
2712    "lsuperior",
2713    "msuperior",
2714    "nsuperior",
2715    "osuperior",
2716    "rsuperior",
2717    "ssuperior",
2718    "tsuperior",
2719    "ff",
2720    "ffi",
2721    "ffl",
2722    "parenleftinferior",
2723    "parenrightinferior",
2724    "Circumflexsmall",
2725    "hyphensuperior",
2726    "Gravesmall",
2727    "Asmall",
2728    "Bsmall",
2729    "Csmall",
2730    "Dsmall",
2731    "Esmall",
2732    "Fsmall",
2733    "Gsmall",
2734    "Hsmall",
2735    "Ismall",
2736    "Jsmall",
2737    "Ksmall",
2738    "Lsmall",
2739    "Msmall",
2740    "Nsmall",
2741    "Osmall",
2742    "Psmall",
2743    "Qsmall",
2744    "Rsmall",
2745    "Ssmall",
2746    "Tsmall",
2747    "Usmall",
2748    "Vsmall",
2749    "Wsmall",
2750    "Xsmall",
2751    "Ysmall",
2752    "Zsmall",
2753    "colonmonetary",
2754    "onefitted",
2755    "rupiah",
2756    "Tildesmall",
2757    "exclamdownsmall",
2758    "centoldstyle",
2759    "Lslashsmall",
2760    "Scaronsmall",
2761    "Zcaronsmall",
2762    "Dieresissmall",
2763    "Brevesmall",
2764    "Caronsmall",
2765    "Dotaccentsmall",
2766    "Macronsmall",
2767    "figuredash",
2768    "hypheninferior",
2769    "Ogoneksmall",
2770    "Ringsmall",
2771    "Cedillasmall",
2772    "questiondownsmall",
2773    "oneeighth",
2774    "threeeighths",
2775    "fiveeighths",
2776    "seveneighths",
2777    "onethird",
2778    "twothirds",
2779    "zerosuperior",
2780    "foursuperior",
2781    "fivesuperior",
2782    "sixsuperior",
2783    "sevensuperior",
2784    "eightsuperior",
2785    "ninesuperior",
2786    "zeroinferior",
2787    "oneinferior",
2788    "twoinferior",
2789    "threeinferior",
2790    "fourinferior",
2791    "fiveinferior",
2792    "sixinferior",
2793    "seveninferior",
2794    "eightinferior",
2795    "nineinferior",
2796    "centinferior",
2797    "dollarinferior",
2798    "periodinferior",
2799    "commainferior",
2800    "Agravesmall",
2801    "Aacutesmall",
2802    "Acircumflexsmall",
2803    "Atildesmall",
2804    "Adieresissmall",
2805    "Aringsmall",
2806    "AEsmall",
2807    "Ccedillasmall",
2808    "Egravesmall",
2809    "Eacutesmall",
2810    "Ecircumflexsmall",
2811    "Edieresissmall",
2812    "Igravesmall",
2813    "Iacutesmall",
2814    "Icircumflexsmall",
2815    "Idieresissmall",
2816    "Ethsmall",
2817    "Ntildesmall",
2818    "Ogravesmall",
2819    "Oacutesmall",
2820    "Ocircumflexsmall",
2821    "Otildesmall",
2822    "Odieresissmall",
2823    "OEsmall",
2824    "Oslashsmall",
2825    "Ugravesmall",
2826    "Uacutesmall",
2827    "Ucircumflexsmall",
2828    "Udieresissmall",
2829    "Yacutesmall",
2830    "Thornsmall",
2831    "Ydieresissmall",
2832    "001.000",
2833    "001.001",
2834    "001.002",
2835    "001.003",
2836    "Black",
2837    "Bold",
2838    "Book",
2839    "Light",
2840    "Medium",
2841    "Regular",
2842    "Roman",
2843    "Semibold",
2844];
2845
2846#[allow(dead_code)]
2847const STANDARD_ENCODING: [u8; 256] = [
2848    0,   // .notdef
2849    0,   // .notdef
2850    0,   // .notdef
2851    0,   // .notdef
2852    0,   // .notdef
2853    0,   // .notdef
2854    0,   // .notdef
2855    0,   // .notdef
2856    0,   // .notdef
2857    0,   // .notdef
2858    0,   // .notdef
2859    0,   // .notdef
2860    0,   // .notdef
2861    0,   // .notdef
2862    0,   // .notdef
2863    0,   // .notdef
2864    0,   // .notdef
2865    0,   // .notdef
2866    0,   // .notdef
2867    0,   // .notdef
2868    0,   // .notdef
2869    0,   // .notdef
2870    0,   // .notdef
2871    0,   // .notdef
2872    0,   // .notdef
2873    0,   // .notdef
2874    0,   // .notdef
2875    0,   // .notdef
2876    0,   // .notdef
2877    0,   // .notdef
2878    0,   // .notdef
2879    0,   // .notdef
2880    1,   // space
2881    2,   // exclam
2882    3,   // quotedbl
2883    4,   // numbersign
2884    5,   // dollar
2885    6,   // percent
2886    7,   // ampersand
2887    8,   // quoteright
2888    9,   // parenleft
2889    10,  // parenright
2890    11,  // asterisk
2891    12,  // plus
2892    13,  // comma
2893    14,  // hyphen
2894    15,  // period
2895    16,  // slash
2896    17,  // zero
2897    18,  // one
2898    19,  // two
2899    20,  // three
2900    21,  // four
2901    22,  // five
2902    23,  // six
2903    24,  // seven
2904    25,  // eight
2905    26,  // nine
2906    27,  // colon
2907    28,  // semicolon
2908    29,  // less
2909    30,  // equal
2910    31,  // greater
2911    32,  // question
2912    33,  // at
2913    34,  // A
2914    35,  // B
2915    36,  // C
2916    37,  // D
2917    38,  // E
2918    39,  // F
2919    40,  // G
2920    41,  // H
2921    42,  // I
2922    43,  // J
2923    44,  // K
2924    45,  // L
2925    46,  // M
2926    47,  // N
2927    48,  // O
2928    49,  // P
2929    50,  // Q
2930    51,  // R
2931    52,  // S
2932    53,  // T
2933    54,  // U
2934    55,  // V
2935    56,  // W
2936    57,  // X
2937    58,  // Y
2938    59,  // Z
2939    60,  // bracketleft
2940    61,  // backslash
2941    62,  // bracketright
2942    63,  // asciicircum
2943    64,  // underscore
2944    65,  // quoteleft
2945    66,  // a
2946    67,  // b
2947    68,  // c
2948    69,  // d
2949    70,  // e
2950    71,  // f
2951    72,  // g
2952    73,  // h
2953    74,  // i
2954    75,  // j
2955    76,  // k
2956    77,  // l
2957    78,  // m
2958    79,  // n
2959    80,  // o
2960    81,  // p
2961    82,  // q
2962    83,  // r
2963    84,  // s
2964    85,  // t
2965    86,  // u
2966    87,  // v
2967    88,  // w
2968    89,  // x
2969    90,  // y
2970    91,  // z
2971    92,  // braceleft
2972    93,  // bar
2973    94,  // braceright
2974    95,  // asciitilde
2975    0,   // .notdef
2976    0,   // .notdef
2977    0,   // .notdef
2978    0,   // .notdef
2979    0,   // .notdef
2980    0,   // .notdef
2981    0,   // .notdef
2982    0,   // .notdef
2983    0,   // .notdef
2984    0,   // .notdef
2985    0,   // .notdef
2986    0,   // .notdef
2987    0,   // .notdef
2988    0,   // .notdef
2989    0,   // .notdef
2990    0,   // .notdef
2991    0,   // .notdef
2992    0,   // .notdef
2993    0,   // .notdef
2994    0,   // .notdef
2995    0,   // .notdef
2996    0,   // .notdef
2997    0,   // .notdef
2998    0,   // .notdef
2999    0,   // .notdef
3000    0,   // .notdef
3001    0,   // .notdef
3002    0,   // .notdef
3003    0,   // .notdef
3004    0,   // .notdef
3005    0,   // .notdef
3006    0,   // .notdef
3007    0,   // .notdef
3008    0,   // .notdef
3009    96,  // exclamdown
3010    97,  // cent
3011    98,  // sterling
3012    99,  // fraction
3013    100, // yen
3014    101, // florin
3015    102, // section
3016    103, // currency
3017    104, // quotesingle
3018    105, // quotedblleft
3019    106, // guillemotleft
3020    107, // guilsinglleft
3021    108, // guilsinglright
3022    109, // fi
3023    110, // fl
3024    0,   // .notdef
3025    111, // endash
3026    112, // dagger
3027    113, // daggerdbl
3028    114, // periodcentered
3029    0,   // .notdef
3030    115, // paragraph
3031    116, // bullet
3032    117, // quotesinglbase
3033    118, // quotedblbase
3034    119, // quotedblright
3035    120, // guillemotright
3036    121, // ellipsis
3037    122, // perthousand
3038    0,   // .notdef
3039    123, // questiondown
3040    0,   // .notdef
3041    124, // grave
3042    125, // acute
3043    126, // circumflex
3044    127, // tilde
3045    128, // macron
3046    129, // breve
3047    130, // dotaccent
3048    131, // dieresis
3049    0,   // .notdef
3050    132, // ring
3051    133, // cedilla
3052    0,   // .notdef
3053    134, // hungarumlaut
3054    135, // ogonek
3055    136, // caron
3056    137, // emdash
3057    0,   // .notdef
3058    0,   // .notdef
3059    0,   // .notdef
3060    0,   // .notdef
3061    0,   // .notdef
3062    0,   // .notdef
3063    0,   // .notdef
3064    0,   // .notdef
3065    0,   // .notdef
3066    0,   // .notdef
3067    0,   // .notdef
3068    0,   // .notdef
3069    0,   // .notdef
3070    0,   // .notdef
3071    0,   // .notdef
3072    0,   // .notdef
3073    138, // AE
3074    0,   // .notdef
3075    139, // ordfeminine
3076    0,   // .notdef
3077    0,   // .notdef
3078    0,   // .notdef
3079    0,   // .notdef
3080    140, // Lslash
3081    141, // Oslash
3082    142, // OE
3083    143, // ordmasculine
3084    0,   // .notdef
3085    0,   // .notdef
3086    0,   // .notdef
3087    0,   // .notdef
3088    0,   // .notdef
3089    144, // ae
3090    0,   // .notdef
3091    0,   // .notdef
3092    0,   // .notdef
3093    145, // dotlessi
3094    0,   // .notdef
3095    0,   // .notdef
3096    146, // lslash
3097    147, // oslash
3098    148, // oe
3099    149, // germandbls
3100    0,   // .notdef
3101    0,   // .notdef
3102    0,   // .notdef
3103    0,   // .notdef
3104];
3105
3106const EXPERT_CHARSET: [u16; 166] = [
3107    0,   // .notdef
3108    1,   // space
3109    229, // exclamsmall
3110    230, // Hungarumlautsmall
3111    231, // dollaroldstyle
3112    232, // dollarsuperior
3113    233, // ampersandsmall
3114    234, // Acutesmall
3115    235, // parenleftsuperior
3116    236, // parenrightsuperior
3117    237, // twodotenleader
3118    238, // onedotenleader
3119    13,  // comma
3120    14,  // hyphen
3121    15,  // period
3122    99,  // fraction
3123    239, // zerooldstyle
3124    240, // oneoldstyle
3125    241, // twooldstyle
3126    242, // threeoldstyle
3127    243, // fouroldstyle
3128    244, // fiveoldstyle
3129    245, // sixoldstyle
3130    246, // sevenoldstyle
3131    247, // eightoldstyle
3132    248, // nineoldstyle
3133    27,  // colon
3134    28,  // semicolon
3135    249, // commasuperior
3136    250, // threequartersemdash
3137    251, // periodsuperior
3138    252, // questionsmall
3139    253, // asuperior
3140    254, // bsuperior
3141    255, // centsuperior
3142    256, // dsuperior
3143    257, // esuperior
3144    258, // isuperior
3145    259, // lsuperior
3146    260, // msuperior
3147    261, // nsuperior
3148    262, // osuperior
3149    263, // rsuperior
3150    264, // ssuperior
3151    265, // tsuperior
3152    266, // ff
3153    109, // fi
3154    110, // fl
3155    267, // ffi
3156    268, // ffl
3157    269, // parenleftinferior
3158    270, // parenrightinferior
3159    271, // Circumflexsmall
3160    272, // hyphensuperior
3161    273, // Gravesmall
3162    274, // Asmall
3163    275, // Bsmall
3164    276, // Csmall
3165    277, // Dsmall
3166    278, // Esmall
3167    279, // Fsmall
3168    280, // Gsmall
3169    281, // Hsmall
3170    282, // Ismall
3171    283, // Jsmall
3172    284, // Ksmall
3173    285, // Lsmall
3174    286, // Msmall
3175    287, // Nsmall
3176    288, // Osmall
3177    289, // Psmall
3178    290, // Qsmall
3179    291, // Rsmall
3180    292, // Ssmall
3181    293, // Tsmall
3182    294, // Usmall
3183    295, // Vsmall
3184    296, // Wsmall
3185    297, // Xsmall
3186    298, // Ysmall
3187    299, // Zsmall
3188    300, // colonmonetary
3189    301, // onefitted
3190    302, // rupiah
3191    303, // Tildesmall
3192    304, // exclamdownsmall
3193    305, // centoldstyle
3194    306, // Lslashsmall
3195    307, // Scaronsmall
3196    308, // Zcaronsmall
3197    309, // Dieresissmall
3198    310, // Brevesmall
3199    311, // Caronsmall
3200    312, // Dotaccentsmall
3201    313, // Macronsmall
3202    314, // figuredash
3203    315, // hypheninferior
3204    316, // Ogoneksmall
3205    317, // Ringsmall
3206    318, // Cedillasmall
3207    158, // onequarter
3208    155, // onehalf
3209    163, // threequarters
3210    319, // questiondownsmall
3211    320, // oneeighth
3212    321, // threeeighths
3213    322, // fiveeighths
3214    323, // seveneighths
3215    324, // onethird
3216    325, // twothirds
3217    326, // zerosuperior
3218    150, // onesuperior
3219    164, // twosuperior
3220    169, // threesuperior
3221    327, // foursuperior
3222    328, // fivesuperior
3223    329, // sixsuperior
3224    330, // sevensuperior
3225    331, // eightsuperior
3226    332, // ninesuperior
3227    333, // zeroinferior
3228    334, // oneinferior
3229    335, // twoinferior
3230    336, // threeinferior
3231    337, // fourinferior
3232    338, // fiveinferior
3233    339, // sixinferior
3234    340, // seveninferior
3235    341, // eightinferior
3236    342, // nineinferior
3237    343, // centinferior
3238    344, // dollarinferior
3239    345, // periodinferior
3240    346, // commainferior
3241    347, // Agravesmall
3242    348, // Aacutesmall
3243    349, // Acircumflexsmall
3244    350, // Atildesmall
3245    351, // Adieresissmall
3246    352, // Aringsmall
3247    353, // AEsmall
3248    354, // Ccedillasmall
3249    355, // Egravesmall
3250    356, // Eacutesmall
3251    357, // Ecircumflexsmall
3252    358, // Edieresissmall
3253    359, // Igravesmall
3254    360, // Iacutesmall
3255    361, // Icircumflexsmall
3256    362, // Idieresissmall
3257    363, // Ethsmall
3258    364, // Ntildesmall
3259    365, // Ogravesmall
3260    366, // Oacutesmall
3261    367, // Ocircumflexsmall
3262    368, // Otildesmall
3263    369, // Odieresissmall
3264    370, // OEsmall
3265    371, // Oslashsmall
3266    372, // Ugravesmall
3267    373, // Uacutesmall
3268    374, // Ucircumflexsmall
3269    375, // Udieresissmall
3270    376, // Yacutesmall
3271    377, // Thornsmall
3272    378, // Ydieresissmall
3273];
3274
3275const EXPERT_SUBSET_CHARSET: [u16; 87] = [
3276    0,   // .notdef
3277    1,   // space
3278    231, // dollaroldstyle
3279    232, // dollarsuperior
3280    235, // parenleftsuperior
3281    236, // parenrightsuperior
3282    237, // twodotenleader
3283    238, // onedotenleader
3284    13,  // comma
3285    14,  // hyphen
3286    15,  // period
3287    99,  // fraction
3288    239, // zerooldstyle
3289    240, // oneoldstyle
3290    241, // twooldstyle
3291    242, // threeoldstyle
3292    243, // fouroldstyle
3293    244, // fiveoldstyle
3294    245, // sixoldstyle
3295    246, // sevenoldstyle
3296    247, // eightoldstyle
3297    248, // nineoldstyle
3298    27,  // colon
3299    28,  // semicolon
3300    249, // commasuperior
3301    250, // threequartersemdash
3302    251, // periodsuperior
3303    253, // asuperior
3304    254, // bsuperior
3305    255, // centsuperior
3306    256, // dsuperior
3307    257, // esuperior
3308    258, // isuperior
3309    259, // lsuperior
3310    260, // msuperior
3311    261, // nsuperior
3312    262, // osuperior
3313    263, // rsuperior
3314    264, // ssuperior
3315    265, // tsuperior
3316    266, // ff
3317    109, // fi
3318    110, // fl
3319    267, // ffi
3320    268, // ffl
3321    269, // parenleftinferior
3322    270, // parenrightinferior
3323    272, // hyphensuperior
3324    300, // colonmonetary
3325    301, // onefitted
3326    302, // rupiah
3327    305, // centoldstyle
3328    314, // figuredash
3329    315, // hypheninferior
3330    158, // onequarter
3331    155, // onehalf
3332    163, // threequarters
3333    320, // oneeighth
3334    321, // threeeighths
3335    322, // fiveeighths
3336    323, // seveneighths
3337    324, // onethird
3338    325, // twothirds
3339    326, // zerosuperior
3340    150, // onesuperior
3341    164, // twosuperior
3342    169, // threesuperior
3343    327, // foursuperior
3344    328, // fivesuperior
3345    329, // sixsuperior
3346    330, // sevensuperior
3347    331, // eightsuperior
3348    332, // ninesuperior
3349    333, // zeroinferior
3350    334, // oneinferior
3351    335, // twoinferior
3352    336, // threeinferior
3353    337, // fourinferior
3354    338, // fiveinferior
3355    339, // sixinferior
3356    340, // seveninferior
3357    341, // eightinferior
3358    342, // nineinferior
3359    343, // centinferior
3360    344, // dollarinferior
3361    345, // periodinferior
3362    346, // commainferior
3363];
3364
3365#[cfg(test)]
3366mod tests {
3367    use super::*;
3368    use crate::binary::read::ReadScope;
3369
3370    fn assert_close(actual: f64, expected: f64) {
3371        assert!(
3372            (actual - expected).abs() < f64::EPSILON,
3373            "{:?} != {:?} ± {}",
3374            actual,
3375            expected,
3376            f64::EPSILON
3377        );
3378    }
3379
3380    #[test]
3381    fn test_iter_index() {
3382        let offset_array = [1, 2, 3];
3383        let data_array = [4, 5];
3384        let index = Index {
3385            count: 2,
3386            off_size: 1,
3387            offset_array: &offset_array,
3388            data_array: &data_array,
3389        };
3390
3391        assert_eq!(index.iter().collect::<Vec<_>>(), vec![[4], [5]]);
3392    }
3393
3394    #[test]
3395    fn test_read_op1() {
3396        let mut ctxt = ReadScope::new(&[0, 0]).ctxt();
3397        assert_eq!(
3398            Op::read(&mut ctxt).unwrap(),
3399            Op::Operator(Operator::Version)
3400        );
3401    }
3402
3403    #[test]
3404    fn test_fail_op1() {
3405        let mut ctxt = ReadScope::new(&[]).ctxt();
3406        assert!(Op::read(&mut ctxt).is_err());
3407    }
3408
3409    #[test]
3410    fn test_read_op2() {
3411        let mut ctxt = ReadScope::new(&[12, 1]).ctxt();
3412        assert_eq!(
3413            Op::read(&mut ctxt).unwrap(),
3414            Op::Operator(Operator::IsFixedPitch)
3415        );
3416    }
3417
3418    #[test]
3419    fn test_fail_op2() {
3420        let mut ctxt = ReadScope::new(&[12]).ctxt();
3421        assert!(Op::read(&mut ctxt).is_err());
3422    }
3423
3424    #[test]
3425    fn test_read_i8() {
3426        let mut ctxt = ReadScope::new(&[0x8b]).ctxt();
3427        assert_eq!(
3428            Op::read(&mut ctxt).unwrap(),
3429            Op::Operand(Operand::Integer(0))
3430        );
3431    }
3432
3433    #[test]
3434    fn test_read_i16() {
3435        //                             _____-10000______  ______10000_____  100   -100
3436        let mut ctxt = ReadScope::new(&[0x1c, 0xd8, 0xf0, 0x1c, 0x27, 0x10, 0xef, 0x27]).ctxt();
3437        assert_eq!(
3438            Op::read(&mut ctxt).unwrap(),
3439            Op::Operand(Operand::Integer(-10000))
3440        );
3441        assert_eq!(
3442            Op::read(&mut ctxt).unwrap(),
3443            Op::Operand(Operand::Integer(10000))
3444        );
3445        assert_eq!(
3446            Op::read(&mut ctxt).unwrap(),
3447            Op::Operand(Operand::Integer(100))
3448        );
3449        assert_eq!(
3450            Op::read(&mut ctxt).unwrap(),
3451            Op::Operand(Operand::Integer(-100))
3452        );
3453    }
3454
3455    #[test]
3456    fn test_read_i32() {
3457        //                   __________-100000___________  ____________100000__________
3458        let mut ctxt =
3459            ReadScope::new(&[0x1d, 0xff, 0xfe, 0x79, 0x60, 0x1d, 0x00, 0x01, 0x86, 0xa0]).ctxt();
3460        assert_eq!(
3461            Op::read(&mut ctxt).unwrap(),
3462            Op::Operand(Operand::Integer(-100000))
3463        );
3464        assert_eq!(
3465            Op::read(&mut ctxt).unwrap(),
3466            Op::Operand(Operand::Integer(100000))
3467        );
3468    }
3469
3470    #[test]
3471    fn test_read_real() {
3472        // From the spec:
3473        // Thus, the value –2.25 is encoded by the byte sequence (1e e2 a2 5f) and the value
3474        // 0.140541E–3 by the sequence (1e 0a 14 05 41 c3 ff).
3475        let mut ctxt = ReadScope::new(&[
3476            // ______-2.25________  _______________0.140541E–3______________
3477            0x1e, 0xe2, 0xa2, 0x5f, 0x1e, 0x0a, 0x14, 0x05, 0x41, 0xc3, 0xff,
3478        ])
3479        .ctxt();
3480        let op = Op::read(&mut ctxt).unwrap();
3481        assert_eq!(
3482            op,
3483            Op::Operand(Operand::Real(Real(tiny_vec![0xe2, 0xa2, 0x5f])))
3484        );
3485        let Op::Operand(Operand::Real(real)) = op else {
3486            panic!("op didn't match Real")
3487        };
3488        assert_close(f64::try_from(&real).unwrap(), -2.25);
3489        let op = Op::read(&mut ctxt).unwrap();
3490        assert_eq!(
3491            op,
3492            Op::Operand(Operand::Real(Real(tiny_vec![
3493                0x0a, 0x14, 0x05, 0x41, 0xc3, 0xff
3494            ])))
3495        );
3496        let Op::Operand(Operand::Real(real)) = op else {
3497            panic!("op didn't match Real")
3498        };
3499        assert_close(f64::try_from(&real).unwrap(), 0.000140541);
3500    }
3501
3502    #[test]
3503    fn test_read_top_dict() {
3504        let expected = TopDict {
3505            dict: vec![
3506                (Operator::IsFixedPitch, vec![Operand::Integer(1)]),
3507                (Operator::Notice, vec![Operand::Integer(123)]),
3508            ],
3509            default: PhantomData,
3510        };
3511        // IsFixedPitch (12 1) is true (1)
3512        // Notice (1) SID is 123
3513        //                              _1__         __123__
3514        let mut ctxt = ReadScope::new(&[0x8c, 12, 1, 247, 15, 1]).ctxt();
3515        assert_eq!(
3516            TopDict::read_dep(&mut ctxt, MAX_OPERANDS).unwrap(),
3517            expected
3518        );
3519    }
3520
3521    #[test]
3522    fn test_write_top_dict() {
3523        let dict = TopDict {
3524            dict: vec![
3525                (Operator::IsFixedPitch, vec![Operand::Integer(1)]),
3526                (Operator::Notice, vec![Operand::Integer(123)]),
3527                // This one is omitted in the output because it is the default for this operator
3528                (Operator::PaintType, vec![Operand::Integer(0)]),
3529            ],
3530            default: PhantomData,
3531        };
3532        // IsFixedPitch Op2(1) is true (1)
3533        // Notice Op1(1) SID is 123
3534        //              _1__  Op2(1) __123__  Op1(1)
3535        let expected = [0x8c, 12, 1, 247, 15, 1];
3536        let mut ctxt = WriteBuffer::new();
3537        TopDict::write_dep(&mut ctxt, &dict, DictDelta::new()).unwrap();
3538
3539        assert_eq!(ctxt.bytes(), &expected);
3540    }
3541
3542    #[test]
3543    fn test_write_top_dict_delta() {
3544        let dict = TopDict {
3545            dict: vec![(Operator::CharStrings, vec![Operand::Offset(123)])],
3546            default: PhantomData,
3547        };
3548        let mut delta = DictDelta::new();
3549        delta.push(
3550            Operator::CharStrings,
3551            tiny_vec!([Operand; 1] => Operand::Offset(1000)),
3552        );
3553
3554        // CharStrings is operator 17 and takes an offset (number as operand)
3555        // Offsets are always written out using the 5 byte representation
3556        //              _______1000_________
3557        let expected = [29, 0, 0, 0x03, 0xE8, 17];
3558        let mut ctxt = WriteBuffer::new();
3559        TopDict::write_dep(&mut ctxt, &dict, delta).unwrap();
3560
3561        // It's expected that the delta value is used instead of the dict value
3562        assert_eq!(ctxt.bytes(), &expected);
3563    }
3564
3565    #[test]
3566    fn test_write_top_dict_size() {
3567        let dict = TopDict {
3568            dict: vec![
3569                (Operator::IsFixedPitch, vec![Operand::Integer(1)]),
3570                (Operator::Notice, vec![Operand::Integer(123)]),
3571                // This one is omitted in the output because it is the default for this operator
3572                (Operator::PaintType, vec![Operand::Integer(0)]),
3573            ],
3574            default: PhantomData,
3575        };
3576        let mut counter = WriteCounter::new();
3577        TopDict::write_dep(&mut counter, &dict, DictDelta::new()).unwrap();
3578
3579        assert_eq!(counter.bytes_written(), 6);
3580    }
3581
3582    #[test]
3583    fn test_read_top_dict_operand_limit() {
3584        let mut ctxt = ReadScope::new(&[0x8c; 2]).ctxt();
3585        match TopDict::read_dep(&mut ctxt, 1) {
3586            Err(ParseError::LimitExceeded) => {}
3587            _ => panic!("expected Err(ParseError::LimitExceeded) got something else"),
3588        }
3589    }
3590
3591    #[test]
3592    fn test_read_empty_private_dict() {
3593        // A Private DICT is required, but may be specified as having a length of 0 if there are
3594        // no non-default values to be stored.
3595        let dict = ReadScope::new(&[]).read_dep::<PrivateDict>(MAX_OPERANDS);
3596        assert!(dict.is_ok());
3597    }
3598
3599    #[test]
3600    fn test_read_custom_encoding_format0() {
3601        let data_format0 = [0, 3, 4, 5, 6];
3602        let mut ctxt = ReadScope::new(&data_format0).ctxt();
3603        let format0_encoding = ctxt.read::<CustomEncoding<'_>>().unwrap();
3604        match format0_encoding {
3605            CustomEncoding::Format0 { codes } => {
3606                assert_eq!(codes.iter().collect_vec(), vec![4, 5, 6])
3607            }
3608            _ => panic!("expected CustomEncoding::Format0 got something else"),
3609        }
3610    }
3611
3612    #[test]
3613    fn test_read_custom_encoding_format1() {
3614        let data_format1 = [1, 2, 4, 5, 6, 7];
3615        let mut ctxt = ReadScope::new(&data_format1).ctxt();
3616        let format1_encoding = ctxt.read::<CustomEncoding<'_>>().unwrap();
3617        match format1_encoding {
3618            CustomEncoding::Format1 { ranges } => assert_eq!(
3619                ranges.iter().collect_vec(),
3620                vec![
3621                    Range {
3622                        first: 4,
3623                        n_left: 5
3624                    },
3625                    Range {
3626                        first: 6,
3627                        n_left: 7
3628                    }
3629                ]
3630            ),
3631            _ => panic!("expected CustomEncoding::Format1 got something else"),
3632        }
3633    }
3634
3635    #[test]
3636    fn test_read_custom_charset_format0() {
3637        let n_glyphs = 2;
3638        let data_format0 = [0, 0xAA, 0xBB];
3639        let mut ctxt = ReadScope::new(&data_format0).ctxt();
3640        let format0_charset = ctxt.read_dep::<CustomCharset<'_>>(n_glyphs).unwrap();
3641        match format0_charset {
3642            CustomCharset::Format0 { glyphs } => {
3643                assert_eq!(glyphs.iter().collect_vec(), vec![0xAABB])
3644            }
3645            _ => panic!("expected CustomCharset::Format0 got something else"),
3646        }
3647    }
3648
3649    #[test]
3650    fn test_read_custom_charset_format1() {
3651        let n_glyphs = 5;
3652        let data_format1 = [1, 0, 1, 3];
3653        let mut ctxt = ReadScope::new(&data_format1).ctxt();
3654        let format1_charset = ctxt.read_dep::<CustomCharset<'_>>(n_glyphs).unwrap();
3655        match format1_charset {
3656            CustomCharset::Format1 { ranges } => assert_eq!(
3657                ranges.iter().collect_vec(),
3658                vec![Range {
3659                    first: 1,
3660                    n_left: 3
3661                },]
3662            ),
3663            _ => panic!("expected CustomCharset::Format1 got something else"),
3664        }
3665    }
3666
3667    #[test]
3668    fn test_read_custom_charset_format2() {
3669        let n_glyphs = 5;
3670        let data_format2 = [2, 0, 1, 0, 3];
3671        let mut ctxt = ReadScope::new(&data_format2).ctxt();
3672        let format2_charset = ctxt.read_dep::<CustomCharset<'_>>(n_glyphs).unwrap();
3673        match format2_charset {
3674            CustomCharset::Format2 { ranges } => assert_eq!(
3675                ranges.iter().collect_vec(),
3676                vec![Range {
3677                    first: 1,
3678                    n_left: 3
3679                },]
3680            ),
3681            _ => panic!("expected CustomCharset::Format2 got something else"),
3682        }
3683    }
3684
3685    #[test]
3686    fn test_read_write_index() {
3687        let mut count = vec![0, 1];
3688        let off_size = 3;
3689        let mut offset0 = vec![0, 0, 1];
3690        let mut offset1 = vec![0, 0, 2];
3691        let object = 5;
3692
3693        // The data is built up like so it's easier to see what each value represents
3694        let mut data = Vec::new();
3695        data.append(&mut count);
3696        data.push(off_size);
3697        data.append(&mut offset0);
3698        data.append(&mut offset1);
3699        data.push(object);
3700
3701        // Read
3702        let mut ctxt = ReadScope::new(&data).ctxt();
3703        let index = ctxt.read::<IndexU16>().unwrap();
3704
3705        let actual: Vec<_> = index.iter().collect();
3706        assert_eq!(actual, &[&[5]]);
3707
3708        // Write
3709        let mut ctxt = WriteBuffer::new();
3710        IndexU16::write(&mut ctxt, &index).unwrap();
3711
3712        assert_eq!(ctxt.bytes(), &[0, 1, 3, 0, 0, 1, 0, 0, 2, 5]);
3713    }
3714
3715    #[test]
3716    fn test_write_int_operand() {
3717        assert_eq!(write_int_operand(0), &[0x8b]);
3718        assert_eq!(write_int_operand(100), &[0xef]);
3719        assert_eq!(write_int_operand(-100), &[0x27]);
3720        assert_eq!(write_int_operand(1000), &[0xfa, 0x7c]);
3721        assert_eq!(write_int_operand(-1000), &[0xfe, 0x7c]);
3722        assert_eq!(write_int_operand(10000), &[0x1c, 0x27, 0x10]);
3723        assert_eq!(write_int_operand(-10000), &[0x1c, 0xd8, 0xf0]);
3724        assert_eq!(write_int_operand(100000), &[0x1d, 0x00, 0x01, 0x86, 0xa0]);
3725        assert_eq!(write_int_operand(-100000), &[0x1d, 0xff, 0xfe, 0x79, 0x60]);
3726    }
3727
3728    #[test]
3729    fn test_write_int_operand_round_trip() {
3730        int_operand_round_trip(0);
3731        int_operand_round_trip(100);
3732        int_operand_round_trip(540);
3733        int_operand_round_trip(-100);
3734        int_operand_round_trip(-267);
3735        int_operand_round_trip(1000);
3736        int_operand_round_trip(-1000);
3737        int_operand_round_trip(10000);
3738        int_operand_round_trip(-10000);
3739        int_operand_round_trip(100000);
3740        int_operand_round_trip(-100000);
3741    }
3742
3743    fn int_operand_round_trip(val: i32) {
3744        let int = write_int_operand(val);
3745        match ReadScope::new(&int).read::<Op>().unwrap() {
3746            Op::Operand(Operand::Integer(actual)) => assert_eq!(actual, val),
3747            _ => unreachable!(),
3748        }
3749    }
3750
3751    fn write_int_operand(val: i32) -> Vec<u8> {
3752        let mut ctxt = WriteBuffer::new();
3753        Operand::write(&mut ctxt, &Operand::Integer(val)).unwrap();
3754        ctxt.into_inner()
3755    }
3756
3757    #[test]
3758    fn test_fd_select_font_dict_index_format0() {
3759        let glyph_font_dict_indices = ReadArrayCow::Owned(vec![1, 2, 3]);
3760        let fd_select = FDSelect::Format0 {
3761            glyph_font_dict_indices,
3762        };
3763
3764        assert_eq!(fd_select.font_dict_index(2), Some(3));
3765        assert_eq!(fd_select.font_dict_index(3), None);
3766    }
3767
3768    #[test]
3769    fn test_fd_select_font_dict_index_format3() {
3770        // Set up 3 ranges:
3771        //  0..10 -> Font DICT index 2
3772        // 10..17 -> Font DICT index 1
3773        // 17..33 -> Font DICT index 0
3774        let ranges: Vec<Range<u16, u8>> = vec![
3775            Range {
3776                first: 0,
3777                n_left: 2,
3778            },
3779            Range {
3780                first: 10,
3781                n_left: 1,
3782            },
3783            Range {
3784                first: 17,
3785                n_left: 0,
3786            },
3787        ];
3788        let fd_select = FDSelect::Format3 {
3789            ranges: ReadArrayCow::Owned(ranges),
3790            sentinel: 33,
3791        };
3792
3793        assert_eq!(fd_select.font_dict_index(2), Some(2));
3794        assert_eq!(fd_select.font_dict_index(10), Some(1));
3795        assert_eq!(fd_select.font_dict_index(32), Some(0));
3796        assert_eq!(fd_select.font_dict_index(33), None);
3797    }
3798
3799    #[test]
3800    fn test_charset_id_for_glyph_pre_defined_charsets() {
3801        assert_eq!(Charset::ISOAdobe.id_for_glyph(2), Some(2));
3802        assert_eq!(Charset::ISOAdobe.id_for_glyph(300), None);
3803        assert_eq!(Charset::Expert.id_for_glyph(2), Some(229));
3804        assert_eq!(Charset::Expert.id_for_glyph(300), None);
3805        assert_eq!(Charset::ExpertSubset.id_for_glyph(2), Some(231));
3806        assert_eq!(Charset::ExpertSubset.id_for_glyph(300), None);
3807    }
3808
3809    #[test]
3810    fn test_custom_charset_id_for_glyph_format0() {
3811        let glyph_sids = ReadArrayCow::Owned(vec![1, 2, 3]);
3812        let charset = CustomCharset::Format0 { glyphs: glyph_sids };
3813
3814        // glpyh id 0 is .notdef and is implicitly encoded
3815        assert_eq!(charset.id_for_glyph(0), Some(0));
3816        assert_eq!(charset.id_for_glyph(1), Some(1));
3817        assert_eq!(charset.id_for_glyph(4), None);
3818    }
3819
3820    #[test]
3821    fn test_custom_charset_id_for_glyph_format1() {
3822        let ranges = ReadArrayCow::Owned(vec![Range {
3823            first: 34,
3824            n_left: 5,
3825        }]);
3826        let charset = CustomCharset::Format1 { ranges };
3827
3828        // glpyh id 0 is .notdef and is implicitly encoded
3829        assert_eq!(charset.id_for_glyph(0), Some(0));
3830        assert_eq!(charset.id_for_glyph(1), Some(34));
3831        assert_eq!(charset.id_for_glyph(6), Some(39));
3832        assert_eq!(charset.id_for_glyph(7), None);
3833    }
3834
3835    #[test]
3836    fn test_custom_charset_id_for_glyph_format2() {
3837        let ranges = ReadArrayCow::Owned(vec![Range {
3838            first: 34,
3839            n_left: 5,
3840        }]);
3841        let charset = CustomCharset::Format2 { ranges };
3842
3843        // glpyh id 0 is .notdef and is implicitly encoded
3844        assert_eq!(charset.id_for_glyph(0), Some(0));
3845        assert_eq!(charset.id_for_glyph(1), Some(34));
3846        assert_eq!(charset.id_for_glyph(6), Some(39));
3847        assert_eq!(charset.id_for_glyph(7), None);
3848    }
3849
3850    #[test]
3851    fn test_arno_custom_charset_ranges() {
3852        // These ranges are from the ArnoPro-Regular font and are in the same order they are in the
3853        // font.
3854        #[rustfmt::skip]
3855        let ranges = ReadArrayCow::Owned(vec![
3856            Range { first: 1, n_left: 107, },
3857            Range { first: 111, n_left: 38, },
3858            Range { first: 151, n_left: 12, },
3859            Range { first: 165, n_left: 3, },
3860            Range { first: 170, n_left: 58, },
3861            Range { first: 237, n_left: 1, },
3862            Range { first: 391, n_left: 0, },
3863            Range { first: 393, n_left: 0, },
3864            Range { first: 300, n_left: 0, },
3865            Range { first: 392, n_left: 0, },
3866            Range { first: 314, n_left: 0, },
3867            Range { first: 324, n_left: 1, },
3868            Range { first: 320, n_left: 3, },
3869            Range { first: 394, n_left: 2577, },
3870            Range { first: 109, n_left: 1, },
3871            Range { first: 2972, n_left: 28, },
3872            Range { first: 2846, n_left: 768, },
3873        ]);
3874        let charset = CustomCharset::Format2 { ranges };
3875
3876        // glpyh id 0 is .notdef and is implicitly encoded
3877        assert_eq!(charset.id_for_glyph(134), Some(136));
3878        assert_eq!(charset.id_for_glyph(265), Some(422));
3879        assert_eq!(charset.id_for_glyph(279), Some(436));
3880    }
3881
3882    #[test]
3883    fn test_custom_charset_iter() {
3884        // These ranges are from the ArnoPro-Regular font and are in the same order they are in the
3885        // font.
3886        #[rustfmt::skip]
3887            let ranges = ReadArrayCow::Owned(vec![
3888            Range { first: 111, n_left: 4, },
3889            Range { first: 1, n_left: 3, },
3890            Range { first: 2972, n_left: 2, },
3891        ]);
3892        let charset = CustomCharset::Format2 { ranges };
3893        let actual = charset.iter().collect_vec();
3894        let expected = vec![0, 111, 112, 113, 114, 115, 1, 2, 3, 4, 2972, 2973, 2974];
3895
3896        assert_eq!(actual, expected);
3897    }
3898
3899    #[test]
3900    fn test_read_standard_string() {
3901        let data = b"Ferris";
3902        let offsets = [1, (data.len() + 1) as u8];
3903        let string_index = MaybeOwnedIndex::Borrowed(Index {
3904            count: 1,
3905            off_size: 1,
3906            offset_array: &offsets,
3907            data_array: data,
3908        });
3909
3910        assert_eq!(
3911            read_string_index_string(&string_index, 7).unwrap(),
3912            "ampersand"
3913        );
3914        assert_eq!(
3915            read_string_index_string(&string_index, 390).unwrap(),
3916            "Semibold"
3917        );
3918    }
3919
3920    #[test]
3921    fn test_read_custom_string() {
3922        let data = b"Ferris";
3923        let offsets = [1, (data.len() + 1) as u8];
3924        let string_index = MaybeOwnedIndex::Borrowed(Index {
3925            count: 1,
3926            off_size: 1,
3927            offset_array: &offsets,
3928            data_array: data,
3929        });
3930
3931        assert_eq!(
3932            read_string_index_string(&string_index, 391).unwrap(),
3933            "Ferris"
3934        );
3935        assert!(read_string_index_string(&string_index, 392).is_err());
3936    }
3937
3938    #[test]
3939    fn bcd_encode() {
3940        let mut buf = tiny_vec!([u8; 32]);
3941        assert_eq!(Operand::bcd_encode(&mut buf, 0.0), Operand::Integer(0));
3942        assert_eq!(Operand::bcd_encode(&mut buf, 1.0), Operand::Integer(1));
3943        assert_eq!(Operand::bcd_encode(&mut buf, -1.0), Operand::Integer(-1));
3944        assert_eq!(
3945            Operand::bcd_encode(&mut buf, -2.25),
3946            Operand::Real(Real(tiny_vec![0xe2, 0xa2, 0x5f]))
3947        );
3948        assert_eq!(
3949            Operand::bcd_encode(&mut buf, 1.140541E-3),
3950            Operand::Real(Real(tiny_vec![0x1a, 0x14, 0x05, 0x41, 0xc3, 0xff]))
3951        );
3952    }
3953}