read_fonts/tables/postscript/
fd_select.rs1use types::GlyphId;
4
5use super::FdSelect;
6
7impl FdSelect<'_> {
8 pub fn font_index(&self, glyph_id: GlyphId) -> Option<u16> {
10 match self {
11 Self::Format0(fds) => fds
13 .fds()
14 .get(glyph_id.to_u32() as usize)
15 .map(|fd| *fd as u16),
16 Self::Format3(fds) => {
18 let ranges = fds.ranges();
19 let gid = glyph_id.to_u32();
20 let ix = match ranges.binary_search_by(|range| (range.first() as u32).cmp(&gid)) {
21 Ok(ix) => ix,
22 Err(ix) => ix.saturating_sub(1),
23 };
24 Some(ranges.get(ix)?.fd() as u16)
25 }
26 Self::Format4(fds) => {
28 let ranges = fds.ranges();
29 let gid = glyph_id.to_u32();
30 let ix = match ranges.binary_search_by(|range| range.first().cmp(&gid)) {
31 Ok(ix) => ix,
32 Err(ix) => ix.saturating_sub(1),
33 };
34 Some(ranges.get(ix)?.fd())
35 }
36 }
37 }
38}
39
40#[cfg(test)]
41mod tests {
42 use font_test_data::bebuffer::BeBuffer;
43
44 use super::{FdSelect, GlyphId};
45 use crate::FontRead;
46 use std::ops::Range;
47
48 #[test]
49 fn select_font_index() {
50 let map = &[
51 (0..10, 0),
52 (10..32, 4),
53 (32..34, 1),
54 (34..128, 12),
55 (128..1024, 2),
56 ];
57 for data in make_fd_selects(map) {
58 let fd_select = FdSelect::read(data.data().into()).unwrap();
59 for (range, font_index) in map {
60 for gid in range.clone() {
61 assert_eq!(
62 fd_select.font_index(GlyphId::from(gid)).unwrap() as u8,
63 *font_index
64 )
65 }
66 }
67 }
68 }
69
70 fn make_fd_selects(map: &[(Range<u16>, u8)]) -> [BeBuffer; 3] {
73 let glyph_count = map.last().unwrap().0.end;
74 let format0 = {
75 let mut buf = BeBuffer::new();
76 buf = buf.push(0u8);
77 let mut fds = vec![0u8; glyph_count as usize];
78 for (range, font_index) in map {
79 for gid in range.clone() {
80 fds[gid as usize] = *font_index;
81 }
82 }
83 buf = buf.extend(fds);
84 buf
85 };
86 let format3 = {
87 let mut buf = BeBuffer::new();
88 buf = buf.push(3u8);
89 buf = buf.push(map.len() as u16);
90 for (range, font_index) in map {
91 buf = buf.push(range.start);
92 buf = buf.push(*font_index);
93 }
94 buf = buf.push(glyph_count);
95 buf
96 };
97 let format4 = {
98 let mut buf = BeBuffer::new();
99 buf = buf.push(4u8);
100 buf = buf.push(map.len() as u32);
101 for (range, font_index) in map {
102 buf = buf.push(range.start as u32);
103 buf = buf.push(*font_index as u16);
104 }
105 buf = buf.push(glyph_count as u32);
106 buf
107 };
108 [format0, format3, format4]
109 }
110}