use tarrasque::{Extract, ExtractError, ExtractResult, Stream};
use crate::error::{MISMATCH, OPERATOR};
use super::{Entry, Numbers};
#[allow(missing_docs)]
#[derive(Copy, Clone, Debug, PartialEq, Default)]
pub struct Cid {
pub ros: (u16, u16, i32),
pub font_version: f32,
pub font_revision: f32,
pub font_type: i32,
pub count: i32,
pub uid_base: Option<i32>,
pub fd_array: i32,
pub fd_select: i32,
pub font_name: Option<u16>,
}
#[allow(missing_docs)]
#[derive(Copy, Clone, Debug, PartialEq, Default)]
pub struct Top<'s> {
pub version: Option<u16>,
pub notice: Option<u16>,
pub copyright: Option<u16>,
pub full_name: Option<u16>,
pub family_name: Option<u16>,
pub weight: Option<u16>,
pub is_fixed_pitch: bool,
pub italic_angle: i32,
pub underline_position: i32,
pub underline_thickness: i32,
pub paint_type: i32,
pub charstring_type: i32,
pub font_matrix: [f32; 6],
pub unique_id: Option<i32>,
pub font_bounding_box: [i32; 4],
pub stroke_width: i32,
pub xuid: Option<Numbers<'s>>,
pub charset: i32,
pub encoding: i32,
pub charstrings: Option<i32>,
pub private: Option<(i32, i32)>,
pub synthetic_base: Option<i32>,
pub post_script: Option<u16>,
pub base_font_name: Option<u16>,
pub base_font_blend: Option<Numbers<'s>>,
pub cid: Option<Cid>,
}
impl<'s> Extract<'s, ()> for Top<'s> {
#[inline]
fn extract(stream: &mut Stream<'s>, _: ()) -> ExtractResult<'s, Self> {
let mut top = Top::default();
top.is_fixed_pitch = false;
top.italic_angle = 0;
top.underline_position = -100;
top.underline_thickness = 50;
top.paint_type = 0;
top.charstring_type = 2;
top.font_matrix = [0.001, 0.0, 0.0, 0.001, 0.0, 0.0];
top.font_bounding_box = [0, 0, 0, 0];
top.stroke_width = 0;
top.charset = 0;
let mut cid = Cid::default();
cid.font_version = 0.0;
cid.font_revision = 0.0;
cid.font_type = 0;
cid.count = 8720;
while !stream.is_empty() {
let Entry { operator, numbers } = stream.extract(())?;
match operator.0 {
0 => top.version = Some(numbers.first()?.as_string_id()?),
1 => top.notice = Some(numbers.first()?.as_string_id()?),
2 => top.full_name = Some(numbers.first()?.as_string_id()?),
3 => top.family_name = Some(numbers.first()?.as_string_id()?),
4 => top.weight = Some(numbers.first()?.as_string_id()?),
5 => if numbers.len() == 4 {
for (index, number) in numbers.numbers().enumerate() {
top.font_bounding_box[index] = number.into();
}
} else {
return Err(ExtractError::Code(MISMATCH));
},
14 => top.xuid = Some(numbers),
15 => top.charset = numbers.first()?.into(),
16 => top.encoding = numbers.first()?.into(),
17 => top.charstrings = Some(numbers.first()?.into()),
18 => if numbers.len() == 2 {
let mut numbers = numbers.numbers();
let a = numbers.next().unwrap().into();
let b = numbers.next().unwrap().into();
top.private = Some((a, b));
} else {
return Err(ExtractError::Code(MISMATCH));
},
3072 => top.copyright = Some(numbers.first()?.as_string_id()?),
3073 => top.is_fixed_pitch = numbers.first()?.as_boolean()?,
3074 => top.italic_angle = numbers.first()?.into(),
3075 => top.underline_position = numbers.first()?.into(),
3076 => top.underline_thickness = numbers.first()?.into(),
3077 => top.paint_type = numbers.first()?.into(),
3078 => top.charstring_type = numbers.first()?.into(),
3079 => if numbers.len() == 6 {
for (index, number) in numbers.numbers().enumerate() {
top.font_matrix[index] = number.into();
}
} else {
return Err(ExtractError::Code(MISMATCH));
},
3080 => top.stroke_width = numbers.first()?.into(),
3092 => top.synthetic_base = Some(numbers.first()?.into()),
3093 => top.post_script = Some(numbers.first()?.as_string_id()?),
3094 => top.base_font_name = Some(numbers.first()?.as_string_id()?),
3095 => top.base_font_blend = Some(numbers),
3102 => if numbers.len() == 3 {
let mut numbers = numbers.numbers();
let registry = numbers.next().unwrap().as_string_id()?;
let ordering = numbers.next().unwrap().as_string_id()?;
let supplement = numbers.next().unwrap().into();
cid.ros = (registry, ordering, supplement);
} else {
return Err(ExtractError::Code(MISMATCH));
},
3103 => cid.font_version = numbers.first()?.into(),
3104 => cid.font_revision = numbers.first()?.into(),
3105 => cid.font_type = numbers.first()?.into(),
3106 => cid.count = numbers.first()?.into(),
3107 => cid.uid_base = Some(numbers.first()?.into()),
3108 => cid.fd_array = numbers.first()?.into(),
3109 => cid.fd_select = numbers.first()?.into(),
3110 => cid.font_name = Some(numbers.first()?.as_string_id()?),
_ => return Err(ExtractError::Code(OPERATOR)),
}
}
if cid.ros != (0, 0, 0) {
top.cid = Some(cid);
}
Ok(top)
}
}