cff 0.5.0

A zero-allocation CFF parser.
// Copyright 2018 Kyle Mayes
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! CFF private `DICT`s.

use tarrasque::{Extract, ExtractError, ExtractResult, Stream};

use crate::error::{OPERATOR};
use super::{Entry, Numbers};

/// A private `DICT` for a font.
#[allow(missing_docs)]
#[derive(Copy, Clone, Debug, PartialEq, Default)]
pub struct Private<'s> {
    pub blues: Option<Numbers<'s>>,
    pub other_blues: Option<Numbers<'s>>,
    pub family_blues: Option<Numbers<'s>>,
    pub family_other_blues: Option<Numbers<'s>>,
    pub blue_scale: f32,
    pub blue_shift: f32,
    pub blue_fuzz: f32,
    pub std_hw: Option<f32>,
    pub std_vw: Option<f32>,
    pub stem_snap_h: Option<Numbers<'s>>,
    pub stem_snap_v: Option<Numbers<'s>>,
    pub force_bold: bool,
    pub language_group: i32,
    pub expansion_factor: f32,
    pub initial_random_seed: i32,
    pub subroutines: Option<i32>,
    pub default_width_x: i32,
    pub nominal_width_x: i32,
}

impl<'s> Extract<'s, ()> for Private<'s> {
    #[inline]
    fn extract(stream: &mut Stream<'s>, _: ()) -> ExtractResult<'s, Self> {
        let mut private = Private::default();
        private.blue_scale = 0.039_625;
        private.blue_shift = 7.0;
        private.blue_fuzz = 1.0;
        private.force_bold = false;
        private.language_group = 0;
        private.expansion_factor = 0.06;
        private.initial_random_seed = 0;
        private.default_width_x = 0;
        private.nominal_width_x = 0;

        while !stream.is_empty() {
            let Entry { operator, numbers } = stream.extract(())?;
            match operator.0 {
                6 => private.blues = Some(numbers),
                7 => private.other_blues = Some(numbers),
                8 => private.family_blues = Some(numbers),
                9 => private.family_other_blues = Some(numbers),
                10 => private.std_hw = Some(numbers.first()?.into()),
                11 => private.std_vw = Some(numbers.first()?.into()),
                19 => private.subroutines = Some(numbers.first()?.into()),
                20 => private.default_width_x = numbers.first()?.into(),
                21 => private.nominal_width_x = numbers.first()?.into(),
                3081 => private.blue_scale = numbers.first()?.into(),
                3082 => private.blue_shift = numbers.first()?.into(),
                3083 => private.blue_fuzz = numbers.first()?.into(),
                3084 => private.stem_snap_h = Some(numbers),
                3085 => private.stem_snap_v = Some(numbers),
                3086 => private.force_bold = numbers.first()?.as_boolean()?,
                3089 => private.language_group = numbers.first()?.into(),
                3090 => private.expansion_factor = numbers.first()?.into(),
                3091 => private.initial_random_seed = numbers.first()?.into(),
                _ => return Err(ExtractError::Code(OPERATOR)),
            }
        }

        Ok(private)
    }
}