use std::num::NonZeroU16; use ttf_parser::GlyphId; use ttf_parser::apple_layout::Lookup; use crate::{convert, Unit::*}; mod format0 { use super::*; #[test] fn single() { let data = convert(&[ UInt16(0), // format UInt16(10), // value ]); let table = Lookup::parse(NonZeroU16::new(1).unwrap(), &data).unwrap(); assert_eq!(table.value(GlyphId(0)).unwrap(), 10); assert!(table.value(GlyphId(1)).is_none()); } #[test] fn not_enough_glyphs() { let data = convert(&[ UInt16(0), // format UInt16(10), // value ]); assert!(Lookup::parse(NonZeroU16::new(2).unwrap(), &data).is_none()); } #[test] fn too_many_glyphs() { let data = convert(&[ UInt16(0), // format UInt16(10), // value UInt16(11), // value <-- will be ignored ]); let table = Lookup::parse(NonZeroU16::new(1).unwrap(), &data).unwrap(); assert_eq!(table.value(GlyphId(0)).unwrap(), 10); assert!(table.value(GlyphId(1)).is_none()); } } mod format2 { use super::*; #[test] fn single() { let data = convert(&[ UInt16(2), // format // Binary Search Table UInt16(6), // segment size UInt16(1), // number of segments UInt16(0), // search range: we don't use it UInt16(0), // entry selector: we don't use it UInt16(0), // range shift: we don't use it // Segment [0] UInt16(118), // last glyph UInt16(118), // first glyph UInt16(10), // value ]); let table = Lookup::parse(NonZeroU16::new(1).unwrap(), &data).unwrap(); assert_eq!(table.value(GlyphId(118)).unwrap(), 10); assert!(table.value(GlyphId(1)).is_none()); } #[test] fn range() { let data = convert(&[ UInt16(2), // format // Binary Search Table UInt16(6), // segment size UInt16(1), // number of segments UInt16(0), // search range: we don't use it UInt16(0), // entry selector: we don't use it UInt16(0), // range shift: we don't use it // Segment [0] UInt16(7), // last glyph UInt16(5), // first glyph UInt16(18), // offset ]); let table = Lookup::parse(NonZeroU16::new(1).unwrap(), &data).unwrap(); assert!(table.value(GlyphId(4)).is_none()); assert_eq!(table.value(GlyphId(5)).unwrap(), 18); assert_eq!(table.value(GlyphId(6)).unwrap(), 18); assert_eq!(table.value(GlyphId(7)).unwrap(), 18); assert!(table.value(GlyphId(8)).is_none()); } } mod format4 { use super::*; #[test] fn single() { let data = convert(&[ UInt16(4), // format // Binary Search Table UInt16(6), // segment size UInt16(1), // number of segments UInt16(0), // search range: we don't use it UInt16(0), // entry selector: we don't use it UInt16(0), // range shift: we don't use it // Segment [0] UInt16(118), // last glyph UInt16(118), // first glyph UInt16(18), // offset // Values [0] UInt16(10), // value [0] ]); let table = Lookup::parse(NonZeroU16::new(1).unwrap(), &data).unwrap(); assert_eq!(table.value(GlyphId(118)).unwrap(), 10); assert!(table.value(GlyphId(1)).is_none()); } #[test] fn range() { let data = convert(&[ UInt16(4), // format // Binary Search Table UInt16(6), // segment size UInt16(1), // number of segments UInt16(0), // search range: we don't use it UInt16(0), // entry selector: we don't use it UInt16(0), // range shift: we don't use it // Segment [0] UInt16(7), // last glyph UInt16(5), // first glyph UInt16(18), // offset // Values [0] UInt16(10), // value [0] UInt16(11), // value [1] UInt16(12), // value [2] ]); let table = Lookup::parse(NonZeroU16::new(1).unwrap(), &data).unwrap(); assert!(table.value(GlyphId(4)).is_none()); assert_eq!(table.value(GlyphId(5)).unwrap(), 10); assert_eq!(table.value(GlyphId(6)).unwrap(), 11); assert_eq!(table.value(GlyphId(7)).unwrap(), 12); assert!(table.value(GlyphId(8)).is_none()); } } mod format6 { use super::*; #[test] fn single() { let data = convert(&[ UInt16(6), // format // Binary Search Table UInt16(4), // segment size UInt16(1), // number of segments UInt16(0), // search range: we don't use it UInt16(0), // entry selector: we don't use it UInt16(0), // range shift: we don't use it // Segment [0] UInt16(0), // glyph UInt16(10), // value ]); let table = Lookup::parse(NonZeroU16::new(1).unwrap(), &data).unwrap(); assert_eq!(table.value(GlyphId(0)).unwrap(), 10); assert!(table.value(GlyphId(1)).is_none()); } #[test] fn multiple() { let data = convert(&[ UInt16(6), // format // Binary Search Table UInt16(4), // segment size UInt16(3), // number of segments UInt16(0), // search range: we don't use it UInt16(0), // entry selector: we don't use it UInt16(0), // range shift: we don't use it // Segment [0] UInt16(0), // glyph UInt16(10), // value // Segment [1] UInt16(5), // glyph UInt16(20), // value // Segment [2] UInt16(10), // glyph UInt16(30), // value ]); let table = Lookup::parse(NonZeroU16::new(1).unwrap(), &data).unwrap(); assert_eq!(table.value(GlyphId(0)).unwrap(), 10); assert_eq!(table.value(GlyphId(5)).unwrap(), 20); assert_eq!(table.value(GlyphId(10)).unwrap(), 30); assert!(table.value(GlyphId(1)).is_none()); } // Tests below are indirectly testing BinarySearchTable. #[test] fn no_segments() { let data = convert(&[ UInt16(6), // format // Binary Search Table UInt16(4), // segment size UInt16(0), // number of segments UInt16(0), // search range: we don't use it UInt16(0), // entry selector: we don't use it UInt16(0), // range shift: we don't use it ]); assert!(Lookup::parse(NonZeroU16::new(1).unwrap(), &data).is_none()); } #[test] fn ignore_termination() { let data = convert(&[ UInt16(6), // format // Binary Search Table UInt16(4), // segment size UInt16(2), // number of segments UInt16(0), // search range: we don't use it UInt16(0), // entry selector: we don't use it UInt16(0), // range shift: we don't use it // Segment [0] UInt16(0), // glyph UInt16(10), // value // Segment [1] UInt16(0xFFFF), // glyph UInt16(0xFFFF), // value ]); let table = Lookup::parse(NonZeroU16::new(1).unwrap(), &data).unwrap(); assert!(table.value(GlyphId(0xFFFF)).is_none()); } #[test] fn only_termination() { let data = convert(&[ UInt16(6), // format // Binary Search Table UInt16(4), // segment size UInt16(1), // number of segments UInt16(0), // search range: we don't use it UInt16(0), // entry selector: we don't use it UInt16(0), // range shift: we don't use it // Segment [0] UInt16(0xFFFF), // glyph UInt16(0xFFFF), // value ]); assert!(Lookup::parse(NonZeroU16::new(1).unwrap(), &data).is_none()); } #[test] fn invalid_segment_size() { let data = convert(&[ UInt16(6), // format // Binary Search Table UInt16(8), // segment size <-- must be 4 UInt16(1), // number of segments UInt16(0), // search range: we don't use it UInt16(0), // entry selector: we don't use it UInt16(0), // range shift: we don't use it // Segment [0] UInt16(0), // glyph UInt16(10), // value ]); assert!(Lookup::parse(NonZeroU16::new(1).unwrap(), &data).is_none()); } } mod format8 { use super::*; #[test] fn single() { let data = convert(&[ UInt16(8), // format UInt16(0), // first glyph UInt16(1), // glyphs count UInt16(2), // value [0] ]); let table = Lookup::parse(NonZeroU16::new(1).unwrap(), &data).unwrap(); assert_eq!(table.value(GlyphId(0)).unwrap(), 2); assert!(table.value(GlyphId(1)).is_none()); } #[test] fn non_zero_first() { let data = convert(&[ UInt16(8), // format UInt16(5), // first glyph UInt16(1), // glyphs count UInt16(2), // value [0] ]); let table = Lookup::parse(NonZeroU16::new(1).unwrap(), &data).unwrap(); assert_eq!(table.value(GlyphId(5)).unwrap(), 2); assert!(table.value(GlyphId(1)).is_none()); assert!(table.value(GlyphId(6)).is_none()); } } mod format10 { use super::*; #[test] fn single() { let data = convert(&[ UInt16(10), // format UInt16(1), // value size: u8 UInt16(0), // first glyph UInt16(1), // glyphs count UInt8(2), // value [0] ]); let table = Lookup::parse(NonZeroU16::new(1).unwrap(), &data).unwrap(); assert_eq!(table.value(GlyphId(0)).unwrap(), 2); assert!(table.value(GlyphId(1)).is_none()); } #[test] fn invalid_value_size() { let data = convert(&[ UInt16(10), // format UInt16(50), // value size <-- invalid UInt16(0), // first glyph UInt16(1), // glyphs count UInt8(2), // value [0] ]); let table = Lookup::parse(NonZeroU16::new(1).unwrap(), &data).unwrap(); assert!(table.value(GlyphId(0)).is_none()); } #[test] fn unsupported_value_size() { let data = convert(&[ UInt16(10), // format UInt16(8), // value size <-- we do not support u64 UInt16(0), // first glyph UInt16(1), // glyphs count Raw(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02]), // value [0] ]); let table = Lookup::parse(NonZeroU16::new(1).unwrap(), &data).unwrap(); assert!(table.value(GlyphId(0)).is_none()); } #[test] fn u32_value_size() { let data = convert(&[ UInt16(10), // format UInt16(4), // value size UInt16(0), // first glyph UInt16(1), // glyphs count UInt32(0xFFFF + 10), // value [0] <-- will be truncated ]); let table = Lookup::parse(NonZeroU16::new(1).unwrap(), &data).unwrap(); assert_eq!(table.value(GlyphId(0)).unwrap(), 9); } }