// 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::charset::{Charset, Range1}; use cff::glyphs::encodings::{Encodings}; #[test] fn test_parse_cff() { with_cff("tests/resources/SourceSansPro-It.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, 2); assert_eq!(cff.names.len(), 1); assert_eq!(cff.names.parse_object(0), Some(Ok("SourceSansPro-It"))); assert_eq!(cff.tops.len(), 1); let top = cff.tops.parse_object(0).unwrap().unwrap(); assert_eq!(cff.strings.find_string(top.version.unwrap() as usize), Some(Ok("2.0"))); assert_eq!(cff.strings.find_string(top.notice.unwrap() as usize), Some(Ok("Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries."))); assert_eq!(top.full_name, None); assert_eq!(cff.strings.find_string(top.copyright.unwrap() as usize), Some(Ok("Copyright 2010, 2012, 2014 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name \'Source\'."))); assert_eq!(cff.strings.find_string(top.family_name.unwrap() as usize), Some(Ok("Source Sans Pro"))); assert_eq!(top.weight, None); assert_eq!(top.is_fixed_pitch, false); assert_eq!(top.italic_angle, -11); assert_eq!(top.underline_position, -100); 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, [-5, 68, 1106, 969]); assert_eq!(top.stroke_width, 0); assert_eq!(top.xuid, None); assert_eq!(top.charset, 11163); assert_eq!(top.encoding, 0); assert_eq!(top.charstrings, Some(11779)); assert_eq!(top.private, Some((66, 43525))); 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); assert_eq!(top.cid, None); assert_eq!(cff.strings.len(), 1020); assert_eq!(cff.strings.find_string(0), Some(Ok(".notdef"))); assert_eq!(cff.strings.find_string(1019), Some(Ok("Source Sans Pro"))); assert_eq!(cff.subroutines.len(), 195); assert_eq!(cff.subroutines.get(0).map(|s| &s[..5]), Some(&[176, 247, 83, 21, 251][..])); assert_eq!(cff.subroutines.get(194), Some(&[247, 20, 247, 46, 11][..])); let glyphs = cff.parse_glyphs(0).unwrap().unwrap(); 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, Some(66)); assert_eq!(glyphs.private.language_group, 0); assert_eq!(glyphs.private.default_width_x, 0); assert_eq!(glyphs.private.nominal_width_x, 536); let blues = glyphs.private.blues.unwrap().numbers().collect::>(); assert_eq!(blues.len(), 14); assert_eq!(blues[0], Number::Integer(-12)); assert_eq!(blues[13], Number::Integer(12)); let other_blues = glyphs.private.other_blues.unwrap().numbers().collect::>(); assert_eq!(other_blues.len(), 2); assert_eq!(other_blues[0], Number::Integer(1)); assert_eq!(other_blues[1], Number::Integer(12)); let family_blues = glyphs.private.family_blues.unwrap().numbers().collect::>(); assert_eq!(family_blues.len(), 14); assert_eq!(family_blues[0], Number::Integer(-12)); assert_eq!(family_blues[13], Number::Integer(12)); let family_other_blues = glyphs.private.family_other_blues.unwrap().numbers().collect::>(); assert_eq!(family_other_blues.len(), 2); assert_eq!(family_other_blues[0], Number::Integer(1)); assert_eq!(family_other_blues[1], Number::Integer(12)); assert_eq!(glyphs.private.blue_scale, 0.0625); assert_eq!(glyphs.private.blue_shift, 7.0); assert_eq!(glyphs.private.blue_fuzz, 0.0); assert_eq!(glyphs.private.std_hw, Some(67.0)); assert_eq!(glyphs.private.std_vw, Some(84.0)); let stem_snap_h = glyphs.private.stem_snap_h.unwrap().numbers().collect::>(); assert_eq!(stem_snap_h.len(), 2); assert_eq!(stem_snap_h[0], Number::Integer(67)); assert_eq!(stem_snap_h[1], Number::Integer(11)); let stem_snap_v = glyphs.private.stem_snap_v.unwrap().numbers().collect::>(); assert_eq!(stem_snap_v.len(), 2); assert_eq!(stem_snap_v[0], Number::Integer(84)); assert_eq!(stem_snap_v[1], Number::Integer(11)); let subroutines = glyphs.subroutines.1.unwrap(); assert_eq!(subroutines.len(), 195); assert_eq!(subroutines.get(0).map(|s| &s[..5]), Some(&[120, 78, 5, 135, 6][..])); assert_eq!(subroutines.get(194), Some(&[5, 81, 6, 14][..])); 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::Format1(charset) => { let ranges = charset.ranges.iter().collect::>(); assert_eq!(ranges.len(), 205); assert_eq!(ranges[0], Range1 { first: 1, num_glyphs: 0 }); assert_eq!(ranges[204], Range1 { first: 109, num_glyphs: 1 }); }, _ => unreachable!(), } assert_eq!(glyphs.charset.find_id(41), 79); assert_eq!(cff.strings.find_string(79), Some(Ok("n"))); assert_eq!(glyphs.charstrings.len(), 857); assert_eq!(glyphs.charstrings.get(0).map(|s| &s[..5]), Some(&[231, 139, 195, 248, 184][..])); assert_eq!(glyphs.charstrings.get(856).map(|s| &s[..5]), Some(&[133, 127, 203, 96, 118][..])); assert_eq!(glyphs.groups, None); for i in 0..glyphs.charstrings.len() { 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), } } }); }