// 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. use super::{with_cff}; use cff::{Cff}; use cff::dict::{Number}; use cff::glyphs::{Range, Select}; use cff::glyphs::charset::{Charset, Range2}; use cff::glyphs::encodings::{Encodings}; #[test] fn test_parse_cff() { with_cff("tests/resources/NotoSansCJKjp-Regular.otf", |bytes| { let cff = Cff::parse(bytes).unwrap(); assert_eq!(cff.header.major_version, 1); assert_eq!(cff.header.minor_version, 0); assert_eq!(cff.header.header_size, 4); assert_eq!(cff.header.offset_size.0, 3); assert_eq!(cff.tops.len(), 1); let top = cff.tops.parse_object(0).unwrap().unwrap(); assert_eq!(top.version, None); assert_eq!(cff.strings.find_string(top.notice.unwrap() as usize), Some(Ok("Copyright 2014, 2015 Adobe Systems Incorporated (http://www.adobe.com/). Noto is a trademark of Google Inc."))); assert_eq!(top.copyright, None); assert_eq!(cff.strings.find_string(top.full_name.unwrap() as usize), Some(Ok("Noto Sans CJK JP Regular"))); assert_eq!(cff.strings.find_string(top.family_name.unwrap() as usize), Some(Ok("Noto Sans CJK JP"))); assert_eq!(cff.strings.find_string(top.weight.unwrap() as usize), Some(Ok("Regular"))); assert_eq!(top.is_fixed_pitch, false); assert_eq!(top.italic_angle, 0); assert_eq!(top.underline_position, -66); assert_eq!(top.underline_thickness, 50); assert_eq!(top.paint_type, 0); assert_eq!(top.charstring_type, 2); assert_eq!(top.font_matrix, [0.001, 0.0, 0.0, 0.001, 0.0, 0.0]); assert_eq!(top.unique_id, None); assert_eq!(top.font_bounding_box, [-750, -704, 2928, 1808]); assert_eq!(top.stroke_width, 0); let xuid = top.xuid.unwrap().numbers().collect::>(); assert_eq!(xuid, vec![Number::Integer(1), Number::Integer(11), Number::Integer(9274312)]); assert_eq!(top.charset, 15542); assert_eq!(top.encoding, 0); assert_eq!(top.charstrings, Some(15891)); assert_eq!(top.private, None); assert_eq!(top.synthetic_base, None); assert_eq!(top.post_script, None); assert_eq!(top.base_font_name, None); assert_eq!(top.base_font_blend, None); let cid = top.cid.unwrap(); assert_eq!(cid.ros, (391, 392, 0)); assert_eq!(cid.font_version, 1.004); assert_eq!(cid.font_revision, 0.0); assert_eq!(cid.font_type, 0); assert_eq!(cid.count, 65535); assert_eq!(cid.uid_base, None); assert_eq!(cid.fd_array, 14430827); assert_eq!(cid.fd_select, 15547); assert_eq!(cid.font_name, None); assert_eq!(cff.strings.len(), 415); assert_eq!(cff.strings.find_string(0), Some(Ok(".notdef"))); assert_eq!(cff.strings.find_string(414), Some(Ok("NotoSansCJKjp-Regular-VKana"))); assert_eq!(cff.subroutines.len(), 1613); assert_eq!(cff.subroutines.get(0).map(|s| &s[..5]), Some(&[215, 22, 229, 115, 29][..])); assert_eq!(cff.subroutines.get(1612), Some(&[250, 20, 7, 11][..])); let glyphs = cff.parse_glyphs(0).unwrap().unwrap(); assert_eq!(glyphs.private.blues, None); assert_eq!(glyphs.private.other_blues, None); assert_eq!(glyphs.private.family_blues, None); assert_eq!(glyphs.private.family_other_blues, None); assert_eq!(glyphs.private.blue_scale, 0.039_625); assert_eq!(glyphs.private.blue_shift, 7.0); assert_eq!(glyphs.private.blue_fuzz, 1.0); assert_eq!(glyphs.private.std_hw, None); assert_eq!(glyphs.private.std_vw, None); assert_eq!(glyphs.private.stem_snap_h, None); assert_eq!(glyphs.private.stem_snap_v, None); assert_eq!(glyphs.private.force_bold, false); assert_eq!(glyphs.private.language_group, 0); assert_eq!(glyphs.private.expansion_factor, 0.06); assert_eq!(glyphs.private.initial_random_seed, 0); assert_eq!(glyphs.private.subroutines, None); assert_eq!(glyphs.private.language_group, 0); assert_eq!(glyphs.private.default_width_x, 0); assert_eq!(glyphs.private.nominal_width_x, 0); assert_eq!(glyphs.subroutines.1, None); match glyphs.encodings { Encodings::Standard => { }, _ => unreachable!(), } assert_eq!(glyphs.encodings.find_id('m' as u32), 78); assert_eq!(cff.strings.find_string(78), Some(Ok("m"))); match glyphs.charset { Charset::Format2(charset) => { let ranges = charset.ranges.iter().collect::>(); assert_eq!(ranges.len(), 1); assert_eq!(ranges[0], Range2 { first: 1, num_glyphs: 65533 }); }, _ => unreachable!(), } assert_eq!(glyphs.charset.find_id(32768), 32768); assert_eq!(glyphs.charstrings.len(), 65535); assert_eq!(glyphs.charstrings.get(0).map(|s| &s[..5]), Some(&[251, 12, 189, 250, 24][..])); assert_eq!(glyphs.charstrings.get(65534), Some(&[32, 14][..])); let (select, groups) = glyphs.groups.unwrap(); assert_eq!(select.find_index(0), Some(5)); assert_eq!(select.find_index(1), Some(15)); match select { Select::Format3(select) => { let ranges = select.ranges.iter().collect::>(); assert_eq!(ranges.len(), 113); assert_eq!(ranges[0], Range { first: 0, index: 5 }); assert_eq!(ranges[112], Range { first: 65506, index: 5 }); }, _ => unreachable!(), } let groups = groups.objects().collect::>(); assert_eq!(groups.len(), 19); for i in 0..1024 { match glyphs.parse_charstring(i).unwrap() { Ok((charstring, _)) => { for (j, operation) in charstring.operations().enumerate() { if let Err(error) = operation { panic!("{}: {}: {:?}", i, j, error); } } }, Err(error) => panic!("{}: {:?}", i, error), } } }); }