1use super::{raw_tag, Array, Bytes, FromBeData, RawTag};
4
5pub const MORX: RawTag = raw_tag(b"morx");
6pub const LTAG: RawTag = raw_tag(b"ltag");
7pub const KERX: RawTag = raw_tag(b"kerx");
8pub const ANKR: RawTag = raw_tag(b"ankr");
9pub const KERN: RawTag = raw_tag(b"kern");
10
11const MAX_CYCLES: u16 = 16;
13
14pub fn lookup<T: FromBeData>(data: &Bytes, offset: usize, id: u16) -> Option<T> {
18 let element_size = T::SIZE;
19 let fmt = data.read::<u16>(offset)?;
20 match fmt {
21 0 => {
22 return data.read::<T>(offset + 2 + id as usize * element_size);
23 }
24 2 => {
25 let reclen = (4 + element_size).max(6);
26 let nrecs = data.read::<u16>(offset + 4)? as usize;
27 let base = offset + 12;
28 let mut l = 0;
29 let mut h = nrecs;
30 while l < h {
31 let i = (l + h) / 2;
32 let rec = base + i * reclen;
33 let last = data.read::<u16>(rec)?;
34 if id > last {
35 l = i + 1;
36 } else if id < data.read::<u16>(rec + 2)? {
37 h = i;
38 } else {
39 return data.read::<T>(rec + 4);
40 }
41 }
42 }
43 4 => {
44 let reclen = 6;
45 let nrecs = data.read::<u16>(offset + 4)? as usize;
46 let base = offset + 12;
47 let mut l = 0;
48 let mut h = nrecs;
49 while l < h {
50 let i = (l + h) / 2;
51 let rec = base + i * reclen;
52 let first = data.read::<u16>(rec + 2)?;
53 let last = data.read::<u16>(rec)?;
54 if id > last {
55 l = i + 1;
56 } else if id < first {
57 h = i;
58 } else {
59 let index = (id - first) as usize;
60 let value_offset =
61 data.read::<u16>(rec + 4)? as usize + offset + index * element_size;
62 return data.read::<T>(value_offset);
63 }
64 }
65 }
66 6 => {
67 let reclen = (2 + element_size).max(4);
68 let nrecs = data.read::<u16>(offset + 4)? as usize;
69 let base = offset + 12;
70 let mut l = 0;
71 let mut h = nrecs;
72 while l < h {
73 use core::cmp::Ordering::*;
74 let i = (l + h) / 2;
75 let rec = base + i * reclen;
76 let glyph = data.read::<u16>(rec)?;
77 match id.cmp(&glyph) {
78 Greater => l = i + 1,
79 Less => h = i,
80 Equal => return data.read::<T>(rec + 2),
81 }
82 }
83 }
84 8 => {
85 let first = data.read::<u16>(offset + 2)?;
86 let count = data.read::<u16>(offset + 4)?;
87 if id < first {
88 return None;
89 }
90 let index = id - first;
91 if index >= count {
92 return None;
93 }
94 return data.read::<T>(offset + 6 + index as usize * element_size);
95 }
96 10 => {
97 let first = data.read::<u16>(offset + 4)?;
98 let count = data.read::<u16>(offset + 6)?;
99 if id < first {
100 return None;
101 }
102 let index = id - first;
103 if index >= count {
104 return None;
105 }
106 return data.read::<T>(offset + 8 + index as usize * element_size);
107 }
108 _ => {}
109 }
110 None
111}
112
113#[derive(Copy, Clone)]
117pub struct ExtendedStateTable<'a> {
118 data: Bytes<'a>,
119 classes: u32,
120 class_table: u32,
121 state_array: u32,
122 entry_table: u32,
123}
124
125impl<'a> ExtendedStateTable<'a> {
126 pub fn new(data: &Bytes<'a>) -> Option<Self> {
128 Some(Self {
129 data: *data,
130 classes: data.read::<u32>(0)?,
131 class_table: data.read::<u32>(4)?,
132 state_array: data.read::<u32>(8)?,
133 entry_table: data.read::<u32>(12)?,
134 })
135 }
136
137 pub fn class(&self, glyph_id: u16) -> u16 {
139 if glyph_id == 0xFFFF {
140 return 2;
141 }
142 lookup::<u16>(&self.data, self.class_table as usize, glyph_id).unwrap_or(1)
143 }
144
145 pub fn entry<T: FromBeData>(&self, state: u16, class: u16) -> Option<Entry<T>> {
147 let mut offset = self.state_array as usize;
148 offset += state as usize * self.classes as usize * 2 + class as usize * 2;
149 let index = self.data.read::<u16>(offset)? as usize;
150 let entry_offset = index * (4 + T::SIZE);
151 self.data
152 .read::<Entry<T>>(self.entry_table as usize + entry_offset)
153 }
154}
155
156#[derive(Copy, Clone)]
157pub struct StateTable<'a> {
158 data: Bytes<'a>,
159 class_count: u16,
160 state_array: u32,
161 states: &'a [u8],
162 entry_table: u32,
163 first_glyph: u16,
164 classes: &'a [u8],
165}
166
167impl<'a> StateTable<'a> {
168 pub fn new(data: &Bytes<'a>) -> Option<Self> {
170 let class_count = data.read_u16(0)?;
171 let class_offset = data.read_u16(2)? as usize;
172 let state_array = data.read_u16(4)? as u32;
173 let entry_table = data.read_u16(6)? as u32;
174 let first_glyph = data.read_u16(class_offset)?;
175 let glyph_count = data.read_u16(class_offset + 2)? as usize;
176 let classes = data.read_bytes(class_offset + 4, glyph_count)?;
177 let states = data.data().get(state_array as usize..)?;
178 Some(Self {
179 data: *data,
180 class_count,
181 state_array,
182 states,
183 entry_table,
184 first_glyph,
185 classes,
186 })
187 }
188
189 pub fn class(&self, glyph_id: u16) -> u16 {
191 if glyph_id == 0xFFFF {
192 return 2;
193 }
194 if let Some(index) = glyph_id.checked_sub(self.first_glyph) {
195 self.classes.get(index as usize).copied().unwrap_or(1) as u16
196 } else {
197 1
198 }
199 }
200
201 pub fn entry<T: FromBeData>(&self, state: u16, class: u16) -> Option<Entry<T>> {
203 let index = state as usize * self.class_count as usize + class as usize;
204 let entry_index = *self.states.get(index)? as usize;
205 let entry_offset = entry_index * (4 + T::SIZE);
206 let mut entry = self
207 .data
208 .read::<Entry<T>>(self.entry_table as usize + entry_offset)?;
209 let new_state =
210 (entry.new_state as u32).checked_sub(self.state_array)? / self.class_count as u32;
211 entry.new_state = new_state as u16;
212 Some(entry)
213 }
214}
215
216#[derive(Copy, Clone)]
218pub struct Entry<T> {
219 pub new_state: u16,
220 pub flags: u16,
221 pub data: T,
222}
223
224impl<T: FromBeData> FromBeData for Entry<T> {
225 const SIZE: usize = 4 + T::SIZE;
226
227 unsafe fn from_be_data_unchecked(buf: &[u8], offset: usize) -> Self {
228 let new_state = u16::from_be_data_unchecked(buf, offset);
229 let flags = u16::from_be_data_unchecked(buf, offset + 2);
230 let data = T::from_be_data_unchecked(buf, offset + 4);
231 Self {
232 new_state,
233 flags,
234 data,
235 }
236 }
237}
238
239pub mod morx {
241 use super::*;
242
243 pub fn chains<'a>(data: &'a [u8], offset: u32) -> Chains<'a> {
246 let data = Bytes::with_offset(data, offset as usize).unwrap_or_else(|| Bytes::new(&[]));
247 let len = data.read_u32(4).unwrap_or(0);
248 Chains {
249 data,
250 offset: 8,
251 len,
252 cur: 0,
253 }
254 }
255
256 #[derive(Copy, Clone)]
258 pub struct Chains<'a> {
259 data: Bytes<'a>,
260 offset: usize,
261 len: u32,
262 cur: u32,
263 }
264
265 impl<'a> Iterator for Chains<'a> {
266 type Item = Chain<'a>;
267
268 fn next(&mut self) -> Option<Self::Item> {
269 if self.cur >= self.len {
270 return None;
271 }
272 self.cur += 1;
273 let offset = self.offset;
274 let len = self.data.read_u32(offset + 4)? as usize;
275 self.offset += len;
276 let default_flags = self.data.read_u32(offset)?;
277 let feature_count = self.data.read_u32(offset + 8)?;
278 let subtable_count = self.data.read_u32(offset + 12)?;
279 Some(Chain {
280 data: self.data,
281 offset,
282 default_flags,
283 feature_count,
284 subtable_count,
285 })
286 }
287 }
288
289 #[derive(Copy, Clone)]
291 pub struct Chain<'a> {
292 data: Bytes<'a>,
293 offset: usize,
294 default_flags: u32,
295 feature_count: u32,
296 subtable_count: u32,
297 }
298
299 impl<'a> Chain<'a> {
300 pub fn default_flags(&self) -> u32 {
302 self.default_flags
303 }
304
305 pub fn features(&self) -> Features<'a> {
307 Features {
308 inner: *self,
309 cur: 0,
310 }
311 }
312
313 pub fn subtables(&self) -> Subtables<'a> {
315 let offset = self.offset + 16 + 12 * self.feature_count as usize;
316 Subtables {
317 inner: *self,
318 offset,
319 len: self.subtable_count,
320 cur: 0,
321 }
322 }
323 }
324
325 #[derive(Copy, Clone)]
327 pub struct Features<'a> {
328 inner: Chain<'a>,
329 cur: u32,
330 }
331
332 impl<'a> Iterator for Features<'a> {
333 type Item = Feature;
334
335 fn next(&mut self) -> Option<Self::Item> {
336 if self.cur >= self.inner.feature_count {
337 return None;
338 }
339 let index = self.cur;
340 self.cur += 1;
341 let offset = self.inner.offset + 16 + index as usize * 12;
342 let b = &self.inner.data;
343 Some(Feature {
344 selector: b.read::<u16>(offset)?,
345 setting_selector: b.read::<u16>(offset + 2)?,
346 enable_flags: b.read::<u32>(offset + 4)?,
347 disable_flags: b.read::<u32>(offset + 8)?,
348 })
349 }
350 }
351
352 #[derive(Copy, Clone)]
354 pub struct Feature {
355 pub selector: u16,
357 pub setting_selector: u16,
359 pub enable_flags: u32,
361 pub disable_flags: u32,
363 }
364
365 #[derive(Copy, Clone)]
367 pub struct Subtables<'a> {
368 inner: Chain<'a>,
369 offset: usize,
370 len: u32,
371 cur: u32,
372 }
373
374 impl<'a> Iterator for Subtables<'a> {
375 type Item = Subtable<'a>;
376
377 fn next(&mut self) -> Option<Self::Item> {
378 if self.cur >= self.len {
379 return None;
380 }
381 self.cur += 1;
382 let offset = self.offset;
383 let b = self.inner.data;
384 self.offset += b.read_u32(offset)? as usize;
385 let coverage = b.read_u32(offset + 4)?;
386 let kind = coverage & 0xFF;
387 let flags = b.read_u32(offset + 8)?;
388 Some(Subtable {
389 data: b,
390 offset,
391 kind,
392 coverage,
393 flags,
394 })
395 }
396 }
397
398 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
400 pub enum Order {
401 Layout,
402 ReverseLayout,
403 Logical,
404 ReverseLogical,
405 }
406
407 #[derive(Copy, Clone)]
409 pub struct Subtable<'a> {
410 data: Bytes<'a>,
411 offset: usize,
412 kind: u32,
413 coverage: u32,
414 flags: u32,
415 }
416
417 impl<'a> Subtable<'a> {
418 pub fn coverage(&self) -> u32 {
420 self.coverage
421 }
422
423 pub fn flags(&self) -> u32 {
425 self.flags
426 }
427
428 pub fn order(&self) -> Order {
430 let order_bits = (self.coverage >> 28) & 0b101;
431 match order_bits {
432 0b000 => Order::Layout,
433 0b100 => Order::ReverseLayout,
434 0b001 => Order::Logical,
435 0b101 => Order::ReverseLogical,
436 _ => Order::Layout,
437 }
438 }
439
440 pub fn should_reverse(&self, is_rtl: bool) -> bool {
444 let order_bits = (self.coverage >> 28) & 0b101;
445 match order_bits {
446 0b000 => is_rtl,
447 0b100 => !is_rtl,
448 0b001 => false,
449 0b101 => true,
450 _ => false,
451 }
452 }
453
454 pub fn kind(&self) -> Option<SubtableKind<'a>> {
456 let data = Bytes::with_offset(self.data.data(), self.offset + 12)?;
457 Some(match self.kind {
458 0 => SubtableKind::Rearrangement(Rearrangement::new(data)?),
459 1 => SubtableKind::Contextual(Contextual::new(data)?),
460 2 => SubtableKind::Ligature(Ligature::new(data)?),
461 4 => SubtableKind::NonContextual(NonContextual::new(data)),
462 5 => SubtableKind::Insertion(Insertion::new(data)?),
463 _ => return None,
464 })
465 }
466 }
467
468 #[derive(Copy, Clone)]
470 pub enum SubtableKind<'a> {
471 Rearrangement(Rearrangement<'a>),
472 Contextual(Contextual<'a>),
473 Ligature(Ligature<'a>),
474 NonContextual(NonContextual<'a>),
475 Insertion(Insertion<'a>),
476 }
477
478 #[derive(Copy, Clone)]
480 pub struct Rearrangement<'a> {
481 state_table: ExtendedStateTable<'a>,
482 }
483
484 impl<'a> Rearrangement<'a> {
485 fn new(data: Bytes<'a>) -> Option<Self> {
486 Some(Self {
487 state_table: ExtendedStateTable::new(&data)?,
488 })
489 }
490
491 pub fn next(
494 &self,
495 state: &mut RearrangementState,
496 index: usize,
497 glyph_id: u16,
498 end_of_text: bool,
499 mut f: impl FnMut(&Rearrange) -> Option<()>,
500 ) -> Option<usize> {
501 const MARK_FIRST: u16 = 0x8000;
502 const DONT_ADVANCE: u16 = 0x4000;
503 const MARK_LAST: u16 = 0x2000;
504 let class = if end_of_text {
505 0
506 } else {
507 self.state_table.class(glyph_id)
508 };
509 let entry = self.state_table.entry::<()>(state.state, class)?;
510 state.state = entry.new_state;
511 if entry.flags & MARK_FIRST != 0 {
512 state.first = index;
513 }
514 if entry.flags & MARK_LAST != 0 {
515 state.last = index;
516 }
517 let verb = entry.flags & 0xF;
518 let start = state.first;
519 let end = state.last;
520 if verb != 0 && start <= end {
521 let m = REARRANGEMENT_MAP[verb as usize & 0xF];
522 let l = 2.min(m >> 4) as usize;
523 let r = 2.min(m & 0x0F) as usize;
524 let reverse_l = 3 == (m >> 4);
525 let reverse_r = 3 == (m & 0x0F);
526 let rearrange = Rearrange {
527 l,
528 r,
529 reverse_l,
530 reverse_r,
531 start,
532 end,
533 };
534 f(&rearrange)?;
535 }
536 let mut advance = entry.flags & DONT_ADVANCE == 0;
537 if advance {
538 state.cycles = 0;
539 } else if state.cycles > MAX_CYCLES {
540 state.cycles = 0;
541 advance = true;
542 } else {
543 state.cycles += 1;
544 }
545 Some(advance as usize)
546 }
547 }
548
549 const REARRANGEMENT_MAP: [u8; 16] = [
550 0x00, 0x10, 0x01, 0x11, 0x20, 0x30, 0x02, 0x03, 0x12, 0x13, 0x21, 0x31, 0x22, 0x32, 0x23, 0x33, ];
567
568 #[derive(Copy, Clone, Default)]
570 pub struct RearrangementState {
571 state: u16,
572 first: usize,
573 last: usize,
574 cycles: u16,
575 }
576
577 impl RearrangementState {
578 pub fn new() -> Self {
580 Self::default()
581 }
582 }
583
584 #[derive(Copy, Clone)]
586 pub struct Rearrange {
587 l: usize,
588 r: usize,
589 reverse_l: bool,
590 reverse_r: bool,
591 start: usize,
592 end: usize,
593 }
594
595 impl Rearrange {
596 pub fn apply<T: Copy + Default>(&self, buffer: &mut [T]) {
598 let l = self.l;
599 let r = self.r;
600 let reverse_l = self.reverse_l;
601 let reverse_r = self.reverse_r;
602 let start = self.start;
603 let end = (self.end + 1).min(buffer.len());
604 let mut tmp = [T::default(); 4];
605 if end - start >= l + r {
606 tmp[..l].copy_from_slice(&buffer[start..(start + l)]);
607 tmp[2..(2 + r)].copy_from_slice(&buffer[(end - r)..end]);
608 if l != r {
609 buffer.copy_within((start + l)..(end - r), start + r);
610 }
611 buffer[start..(r + start)].copy_from_slice(&tmp[2..(r + 2)]);
612 buffer[(end - l)..end].copy_from_slice(&tmp[..l]);
613 if reverse_l {
614 buffer.swap(end - 1, end - 2);
615 }
616 if reverse_r {
617 buffer.swap(start, start + 1);
618 }
619 }
620 }
621 }
622
623 #[derive(Copy, Clone)]
625 pub struct Contextual<'a> {
626 data: Bytes<'a>,
627 state_table: ExtendedStateTable<'a>,
628 table: u32,
629 }
630
631 impl<'a> Contextual<'a> {
632 fn new(data: Bytes<'a>) -> Option<Self> {
633 let table = data.read_u32(16)?;
634 Some(Self {
635 data,
636 state_table: ExtendedStateTable::new(&data)?,
637 table,
638 })
639 }
640
641 pub fn next(
643 &self,
644 state: &mut ContextualState,
645 index: usize,
646 glyph_id: u16,
647 end_of_text: bool,
648 mut f: impl FnMut(usize, u16) -> Option<()>,
649 ) -> Option<()> {
650 const SET_MARK: u16 = 0x8000;
651 const DONT_ADVANCE: u16 = 0x4000;
652 if end_of_text && !state.mark_set {
653 return Some(());
654 }
655 let mut last_glyph_id = glyph_id;
656 let mut current_glyph_id = glyph_id;
657 let mut class = if end_of_text {
658 0
659 } else {
660 self.state_table.class(glyph_id)
661 };
662 if index == 0 && !end_of_text {
663 state.mark_index = 0;
664 state.mark_id = glyph_id;
665 }
666 let mut cycles = 0;
667 loop {
668 let entry = self
669 .state_table
670 .entry::<ContextualData>(state.state, class)?;
671 state.state = entry.new_state;
672 if entry.data.mark_index != 0xFFFF {
673 if let Some(g) = self.lookup(entry.data.mark_index, state.mark_id) {
674 f(state.mark_index, g)?;
675 if state.mark_index == index {
676 last_glyph_id = g;
677 current_glyph_id = g;
678 }
679 }
680 }
681 if entry.data.current_index != 0xFFFF {
682 if let Some(g) = self.lookup(entry.data.current_index, last_glyph_id) {
683 f(index, g)?;
684 current_glyph_id = g;
685 }
686 }
687 if entry.flags & SET_MARK != 0 {
688 state.mark_set = true;
689 state.mark_index = index;
690 state.mark_id = current_glyph_id;
691 }
692 if entry.flags & DONT_ADVANCE == 0 || cycles > MAX_CYCLES {
693 break;
694 }
695 cycles += 1;
696 class = self.state_table.class(current_glyph_id);
697 last_glyph_id = current_glyph_id;
698 }
699 Some(())
700 }
701
702 fn lookup(&self, table_index: u16, glyph_id: u16) -> Option<u16> {
703 let offset = self
704 .data
705 .read_u32(self.table as usize + table_index as usize * 4)?
706 as usize
707 + self.table as usize;
708 lookup(&self.data, offset, glyph_id)
709 }
710 }
711
712 #[derive(Copy, Clone, Default)]
714 pub struct ContextualState {
715 state: u16,
716 mark_set: bool,
717 mark_index: usize,
718 mark_id: u16,
719 }
720
721 impl ContextualState {
722 pub fn new() -> Self {
724 Self::default()
725 }
726 }
727
728 #[derive(Copy, Clone)]
729 struct ContextualData {
730 mark_index: u16,
731 current_index: u16,
732 }
733
734 impl FromBeData for ContextualData {
735 unsafe fn from_be_data_unchecked(buf: &[u8], offset: usize) -> Self {
736 let mark_index = u16::from_be_data_unchecked(buf, offset);
737 let current_index = u16::from_be_data_unchecked(buf, offset + 2);
738 Self {
739 mark_index,
740 current_index,
741 }
742 }
743 }
744
745 #[derive(Copy, Clone)]
747 pub struct Ligature<'a> {
748 data: Bytes<'a>,
749 state_table: ExtendedStateTable<'a>,
750 action: u32,
751 component: u32,
752 ligature: u32,
753 }
754
755 impl<'a> Ligature<'a> {
756 fn new(data: Bytes<'a>) -> Option<Self> {
757 let state_table = ExtendedStateTable::new(&data)?;
758 let action = data.read::<u32>(16)?;
759 let component = data.read::<u32>(20)?;
760 let ligature = data.read::<u32>(24)?;
761 Some(Self {
762 data,
763 state_table,
764 action,
765 component,
766 ligature,
767 })
768 }
769
770 pub fn next(
772 &self,
773 state: &mut LigatureState,
774 index: usize,
775 glyph_id: u16,
776 end_of_text: bool,
777 mut f: impl FnMut(usize, u16, &[usize]) -> Option<()>,
778 ) -> Option<()> {
779 const SET_COMPONENT: u16 = 0x8000;
780 const DONT_ADVANCE: u16 = 0x4000;
781 const PERFORM_ACTION: u16 = 0x2000;
782 const LAST: u32 = 0x80000000;
783 const STORE: u32 = 0x40000000;
784 let class = if end_of_text {
785 0
786 } else {
787 self.state_table.class(glyph_id)
788 };
789 let mut cycles = 0;
790 loop {
791 let entry = self.state_table.entry::<u16>(state.state, class)?;
792 state.state = entry.new_state;
793 if entry.flags & SET_COMPONENT != 0 {
794 state.push(index, glyph_id)?;
795 }
796 if entry.flags & PERFORM_ACTION != 0 {
797 let mut action_index = entry.data;
798 let mut ligature_index = 0;
799 let end_pos = state.pos;
800 let mut pos = end_pos;
801 while pos > 0 {
802 pos -= 1;
803 let glyph_index = state.indices[pos];
804 let action = self.action(action_index)?;
805 action_index += 1;
806 let mut offset = action & 0x3FFFFFFF;
807 if offset & 0x20000000 != 0 {
808 offset |= 0xC0000000;
809 }
810 let offset = offset as i32;
811 let component_index = state.glyphs[pos] as i32 + offset;
812 let component = self.component(component_index as u32)?;
813 ligature_index += component as u32;
814 if action & (LAST | STORE) != 0 {
815 let ligature = self.ligature(ligature_index)?;
816 f(glyph_index, ligature, state.indices.get(pos + 1..end_pos)?)?;
817 state.glyphs[pos] = ligature;
818 pos += 1;
819 }
820 if action & LAST != 0 || cycles > (MAX_CYCLES * 2) {
821 break;
822 }
823 cycles += 1;
824 }
825 state.pos = pos;
826 }
827 if entry.flags & DONT_ADVANCE == 0 || cycles > MAX_CYCLES {
828 break;
829 }
830 cycles += 1;
831 }
832 Some(())
833 }
834
835 fn action(&self, index: u16) -> Option<u32> {
836 self.data
837 .read::<u32>(self.action as usize + index as usize * 4)
838 }
839
840 fn component(&self, index: u32) -> Option<u16> {
841 self.data
842 .read::<u16>(self.component as usize + index as usize * 2)
843 }
844
845 fn ligature(&self, index: u32) -> Option<u16> {
846 self.data
847 .read::<u16>(self.ligature as usize + index as usize * 2)
848 }
849 }
850
851 #[derive(Copy, Clone)]
853 pub struct LigatureState {
854 state: u16,
855 indices: [usize; 32],
856 glyphs: [u16; 32],
857 pos: usize,
858 }
859
860 impl LigatureState {
861 pub fn new() -> Self {
863 Self {
864 state: 0,
865 indices: [0; 32],
866 glyphs: [0; 32],
867 pos: 0,
868 }
869 }
870
871 fn push(&mut self, index: usize, glyph_id: u16) -> Option<()> {
872 *self.indices.get_mut(self.pos)? = index;
873 *self.glyphs.get_mut(self.pos)? = glyph_id;
874 self.pos += 1;
875 Some(())
876 }
877 }
878
879 #[derive(Copy, Clone)]
881 pub struct NonContextual<'a> {
882 data: Bytes<'a>,
883 }
884
885 impl<'a> NonContextual<'a> {
886 fn new(data: Bytes<'a>) -> Self {
887 Self { data }
888 }
889
890 pub fn substitute(&self, glyph_id: u16) -> Option<u16> {
892 lookup(&self.data, 0, glyph_id)
893 }
894 }
895
896 #[derive(Copy, Clone)]
898 pub struct Insertion<'a> {
899 data: Bytes<'a>,
900 state_table: ExtendedStateTable<'a>,
901 action: usize,
902 }
903
904 impl<'a> Insertion<'a> {
905 fn new(data: Bytes<'a>) -> Option<Self> {
906 let state_table = ExtendedStateTable::new(&data)?;
907 let action = data.read_u32(16)? as usize;
908 Some(Self {
909 data,
910 state_table,
911 action,
912 })
913 }
914
915 pub fn next(
918 &self,
919 state: &mut InsertionState,
920 index: usize,
921 glyph_id: u16,
922 end_of_text: bool,
923 mut f: impl FnMut(usize, Array<'a, u16>) -> Option<()>,
924 ) -> Option<usize> {
925 const SET_MARK: u16 = 0x8000;
926 const DONT_ADVANCE: u16 = 0x4000;
927 const _CURRENT_IS_KASHIDA_LIKE: u16 = 0x2000;
928 const _MARKED_IS_KASHIDA_LIKE: u16 = 0x1000;
929 const CURRENT_INSERT_BEFORE: u16 = 0x800;
930 const MARKED_INSERT_BEFORE: u16 = 0x400;
931 let class = if end_of_text {
932 0
933 } else {
934 self.state_table.class(glyph_id)
935 };
936 let entry = self
937 .state_table
938 .entry::<InsertionData>(state.state, class)?;
939 state.state = entry.new_state;
940 let mut working_index = index;
941 let mut mark_inserted = 0;
942 if entry.data.mark_index != 0xFFFF {
943 let before = entry.flags & MARKED_INSERT_BEFORE != 0;
944 let base = if before { state.mark } else { state.mark + 1 };
945 let glyphs = self.marked_glyphs(entry.flags, entry.data.mark_index)?;
946 mark_inserted = glyphs.len();
947 working_index += mark_inserted;
948 f(base, glyphs)?;
949 }
950 if entry.flags & SET_MARK != 0 {
951 state.mark = index;
952 }
953 let mut current_inserted = 0;
954 if entry.data.current_index != 0xFFFF {
955 let before = entry.flags & CURRENT_INSERT_BEFORE != 0;
956 let base = if before {
957 working_index
958 } else {
959 working_index + 1
960 };
961 let glyphs = self.current_glyphs(entry.flags, entry.data.current_index)?;
962 current_inserted = glyphs.len();
963 f(base, glyphs)?;
964 }
965 let mut advance = entry.flags & DONT_ADVANCE == 0;
966 if advance {
967 state.cycles = 0;
968 } else if state.cycles > MAX_CYCLES {
969 state.cycles = 0;
970 advance = true;
971 } else {
972 state.cycles += 1;
973 }
974 if advance {
975 Some(mark_inserted + current_inserted + 1)
976 } else {
977 Some(mark_inserted)
978 }
979 }
980
981 fn marked_glyphs(&self, flags: u16, index: u16) -> Option<Array<'a, u16>> {
982 const MARKED_INSERT_COUNT: u16 = 0x1F;
983 let len = (flags & MARKED_INSERT_COUNT) as usize;
984 let offset = self.action + index as usize * 2;
985 self.data.read_array::<u16>(offset, len)
986 }
987
988 fn current_glyphs(&self, flags: u16, index: u16) -> Option<Array<'a, u16>> {
989 const CURRENT_INSERT_COUNT: u16 = 0x3E0;
990 let len = (flags & CURRENT_INSERT_COUNT) as usize >> 5;
991 let offset = self.action + index as usize * 2;
992 self.data.read_array::<u16>(offset, len)
993 }
994 }
995
996 #[derive(Copy, Clone)]
997 struct InsertionData {
998 current_index: u16,
999 mark_index: u16,
1000 }
1001
1002 impl FromBeData for InsertionData {
1003 unsafe fn from_be_data_unchecked(buf: &[u8], offset: usize) -> Self {
1004 let current_index = u16::from_be_data_unchecked(buf, offset);
1005 let mark_index = u16::from_be_data_unchecked(buf, offset + 2);
1006 Self {
1007 current_index,
1008 mark_index,
1009 }
1010 }
1011 }
1012
1013 #[derive(Copy, Clone, Default)]
1015 pub struct InsertionState {
1016 state: u16,
1017 mark: usize,
1018 cycles: u16,
1019 }
1020
1021 impl InsertionState {
1022 pub fn new() -> Self {
1024 Self::default()
1025 }
1026 }
1027
1028 pub fn language_index(data: &[u8], ltag: u32, language: &str) -> Option<u32> {
1030 let name = language.as_bytes();
1031 let b = Bytes::with_offset(data, ltag as usize)?;
1032 let count = b.read_u32(8)?;
1033 let mut s = b.stream_at(12)?;
1034 for i in 0..count {
1035 let offset = s.read_u16()? as usize;
1036 let len = s.read_u16()? as usize;
1037 let bytes = b.read_bytes(offset, len)?;
1038 if bytes == name {
1039 return Some(i);
1040 }
1041 }
1042 None
1043 }
1044
1045 pub fn feature_from_tag(tag: RawTag) -> Option<(u16, [u16; 2])> {
1048 Some(match AT_TO_AAT.binary_search_by(|e| e.0.cmp(&tag)) {
1049 Ok(index) => {
1050 let (_, feature, on, off) = AT_TO_AAT[index];
1051 (feature as u16, [on as u16, off as u16])
1052 }
1053 _ => return None,
1054 })
1055 }
1056
1057 const AT_TO_AAT: [(u32, u8, u8, u8); 77] = [
1058 (raw_tag(b"afrc"), 11, 1, 0),
1059 (raw_tag(b"c2pc"), 38, 2, 0),
1060 (raw_tag(b"c2sc"), 38, 1, 0),
1061 (raw_tag(b"calt"), 36, 0, 1),
1062 (raw_tag(b"case"), 33, 0, 1),
1063 (raw_tag(b"clig"), 1, 18, 19),
1064 (raw_tag(b"cpsp"), 33, 2, 3),
1065 (raw_tag(b"cswh"), 36, 4, 5),
1066 (raw_tag(b"dlig"), 1, 4, 5),
1067 (raw_tag(b"expt"), 20, 10, 16),
1068 (raw_tag(b"frac"), 11, 2, 0),
1069 (raw_tag(b"fwid"), 22, 1, 7),
1070 (raw_tag(b"halt"), 22, 6, 7),
1071 (raw_tag(b"hist"), 1, 20, 21),
1072 (raw_tag(b"hkna"), 34, 0, 1),
1073 (raw_tag(b"hlig"), 1, 20, 21),
1074 (raw_tag(b"hngl"), 23, 1, 0),
1075 (raw_tag(b"hojo"), 20, 12, 16),
1076 (raw_tag(b"hwid"), 22, 2, 7),
1077 (raw_tag(b"ital"), 32, 2, 3),
1078 (raw_tag(b"jp04"), 20, 11, 16),
1079 (raw_tag(b"jp78"), 20, 2, 16),
1080 (raw_tag(b"jp83"), 20, 3, 16),
1081 (raw_tag(b"jp90"), 20, 4, 16),
1082 (raw_tag(b"liga"), 1, 2, 3),
1083 (raw_tag(b"lnum"), 21, 1, 2),
1084 (raw_tag(b"mgrk"), 15, 10, 11),
1085 (raw_tag(b"nlck"), 20, 13, 16),
1086 (raw_tag(b"onum"), 21, 0, 2),
1087 (raw_tag(b"ordn"), 10, 3, 0),
1088 (raw_tag(b"palt"), 22, 5, 7),
1089 (raw_tag(b"pcap"), 37, 2, 0),
1090 (raw_tag(b"pkna"), 22, 0, 7),
1091 (raw_tag(b"pnum"), 6, 1, 4),
1092 (raw_tag(b"pwid"), 22, 0, 7),
1093 (raw_tag(b"qwid"), 22, 4, 7),
1094 (raw_tag(b"rlig"), 1, 0, 1),
1095 (raw_tag(b"ruby"), 28, 2, 3),
1096 (raw_tag(b"sinf"), 10, 4, 0),
1097 (raw_tag(b"smcp"), 37, 1, 0),
1098 (raw_tag(b"smpl"), 20, 1, 16),
1099 (raw_tag(b"ss01"), 35, 2, 3),
1100 (raw_tag(b"ss02"), 35, 4, 5),
1101 (raw_tag(b"ss03"), 35, 6, 7),
1102 (raw_tag(b"ss04"), 35, 8, 9),
1103 (raw_tag(b"ss05"), 35, 10, 11),
1104 (raw_tag(b"ss06"), 35, 12, 13),
1105 (raw_tag(b"ss07"), 35, 14, 15),
1106 (raw_tag(b"ss08"), 35, 16, 17),
1107 (raw_tag(b"ss09"), 35, 18, 19),
1108 (raw_tag(b"ss10"), 35, 20, 21),
1109 (raw_tag(b"ss11"), 35, 22, 23),
1110 (raw_tag(b"ss12"), 35, 24, 25),
1111 (raw_tag(b"ss13"), 35, 26, 27),
1112 (raw_tag(b"ss14"), 35, 28, 29),
1113 (raw_tag(b"ss15"), 35, 30, 31),
1114 (raw_tag(b"ss16"), 35, 32, 33),
1115 (raw_tag(b"ss17"), 35, 34, 35),
1116 (raw_tag(b"ss18"), 35, 36, 37),
1117 (raw_tag(b"ss19"), 35, 38, 39),
1118 (raw_tag(b"ss20"), 35, 40, 41),
1119 (raw_tag(b"subs"), 10, 2, 0),
1120 (raw_tag(b"sups"), 10, 1, 0),
1121 (raw_tag(b"swsh"), 36, 2, 3),
1122 (raw_tag(b"titl"), 19, 4, 0),
1123 (raw_tag(b"tnam"), 20, 14, 16),
1124 (raw_tag(b"tnum"), 6, 0, 4),
1125 (raw_tag(b"trad"), 20, 0, 16),
1126 (raw_tag(b"twid"), 22, 3, 7),
1127 (raw_tag(b"unic"), 3, 14, 15),
1128 (raw_tag(b"valt"), 22, 5, 7),
1129 (raw_tag(b"vert"), 4, 0, 1),
1130 (raw_tag(b"vhal"), 22, 6, 7),
1131 (raw_tag(b"vkna"), 34, 2, 3),
1132 (raw_tag(b"vpal"), 22, 5, 7),
1133 (raw_tag(b"vrt2"), 4, 0, 1),
1134 (raw_tag(b"zero"), 14, 4, 5),
1135 ];
1136}
1137
1138pub mod kerx {
1140 use super::*;
1141
1142 pub fn subtables<'a>(data: &'a [u8], kerx: u32, ankr: u32) -> Subtables<'a> {
1145 let b = if kerx == 0 {
1146 Bytes::new(&[])
1147 } else {
1148 Bytes::with_offset(data, kerx as usize).unwrap_or_else(|| Bytes::new(&[]))
1149 };
1150 let ankr = if ankr == 0 {
1151 &[]
1152 } else {
1153 data.get(ankr as usize..).unwrap_or(&[])
1154 };
1155 let version = b.read_u16(0).unwrap_or(0);
1156 let len = b.read_u32(4).unwrap_or(0);
1157 Subtables {
1158 data: b,
1159 version,
1160 offset: 8,
1161 len,
1162 cur: 0,
1163 ankr,
1164 }
1165 }
1166
1167 #[derive(Copy, Clone)]
1169 pub struct Subtables<'a> {
1170 data: Bytes<'a>,
1171 version: u16,
1172 offset: usize,
1173 len: u32,
1174 cur: u32,
1175 ankr: &'a [u8],
1176 }
1177
1178 impl<'a> Iterator for Subtables<'a> {
1179 type Item = Subtable<'a>;
1180
1181 fn next(&mut self) -> Option<Self::Item> {
1182 if self.cur >= self.len {
1183 return None;
1184 }
1185 self.cur += 1;
1186 let offset = self.offset;
1187 let subtable = Subtable::new(&self.data, offset, self.version, self.ankr)?;
1188 self.offset = self.offset.checked_add(subtable.size as usize)?;
1189 Some(subtable)
1190 }
1191 }
1192
1193 #[derive(Copy, Clone)]
1195 #[allow(dead_code)]
1196 pub struct Subtable<'a> {
1197 data: Bytes<'a>,
1198 version: u16,
1199 size: u32,
1200 coverage: u32,
1201 tuple_count: u32,
1202 ankr: &'a [u8],
1203 }
1204
1205 impl<'a> Subtable<'a> {
1206 fn new(data: &Bytes<'a>, offset: usize, version: u16, ankr: &'a [u8]) -> Option<Self> {
1207 let data = Bytes::with_offset(data.data(), offset)?;
1208 let size = data.read_u32(0)?;
1209 let coverage = data.read_u32(4)?;
1210 let tuple_count = if version >= 4 { data.read_u32(8)? } else { 0 };
1211 Some(Self {
1212 data,
1213 version,
1214 size,
1215 coverage,
1216 tuple_count,
1217 ankr,
1218 })
1219 }
1220
1221 pub fn is_vertical(&self) -> bool {
1222 self.coverage & 0x80000000 != 0
1223 }
1224
1225 pub fn is_cross_stream(&self) -> bool {
1226 self.coverage & 0x40000000 != 0
1227 }
1228
1229 pub fn has_variations(&self) -> bool {
1230 self.coverage & 0x20000000 != 0
1231 }
1232
1233 pub fn should_reverse(&self, is_rtl: bool) -> bool {
1234 if self.coverage & 0x10000000 != 0 {
1235 !is_rtl
1236 } else {
1237 is_rtl
1238 }
1239 }
1240
1241 pub fn kind(&self) -> Option<SubtableKind<'a>> {
1242 let format = self.coverage & 0xFF;
1243 Some(match format {
1244 0 => SubtableKind::Format0(Format0::new(self.data)?),
1245 1 => SubtableKind::Format1(Format1::new(self.data, self.tuple_count)?),
1246 2 => SubtableKind::Format2(Format2::new(self.data)?),
1247 4 => SubtableKind::Format4(Format4::new(self.data, self.ankr)?),
1248 _ => return None,
1249 })
1250 }
1251 }
1252
1253 #[derive(Copy, Clone)]
1255 pub enum SubtableKind<'a> {
1256 Format0(Format0<'a>),
1257 Format1(Format1<'a>),
1258 Format2(Format2<'a>),
1259 Format4(Format4<'a>),
1260 }
1261
1262 #[derive(Copy, Clone)]
1264 pub struct Format0<'a> {
1265 data: Bytes<'a>,
1266 count: usize,
1267 }
1268
1269 impl<'a> Format0<'a> {
1270 fn new(data: Bytes<'a>) -> Option<Self> {
1271 let count = data.read_u32(12)? as usize;
1272 Some(Self { data, count })
1273 }
1274
1275 pub fn get(&self, left: u16, right: u16) -> Option<i16> {
1277 let key = (left as u32) << 16 | right as u32;
1278 let base = 28;
1279 let reclen = 6;
1280 let b = &self.data;
1281 let mut l = 0;
1282 let mut h = self.count;
1283 while l < h {
1284 use core::cmp::Ordering::*;
1285 let i = (l + h) / 2;
1286 let pair = b.read::<u32>(base + i * reclen)?;
1287 match key.cmp(&pair) {
1288 Greater => l = i + 1,
1289 Less => h = i,
1290 Equal => return b.read_i16(base + i * reclen + 4),
1291 }
1292 }
1293 None
1294 }
1295 }
1296
1297 #[derive(Copy, Clone)]
1299 #[allow(dead_code)]
1300 pub struct Format1<'a> {
1301 data: Bytes<'a>,
1302 state_table: ExtendedStateTable<'a>,
1303 value: usize,
1304 tuple_count: u32,
1305 tuple_size: usize,
1306 }
1307
1308 impl<'a> Format1<'a> {
1309 fn new(data: Bytes<'a>, tuple_count: u32) -> Option<Self> {
1310 let data = Bytes::with_offset(data.data(), 12)?;
1311 let state_table = ExtendedStateTable::new(&data)?;
1312 let value = data.read_u32(16)? as usize;
1313 let tuple_size = if tuple_count == 0 {
1314 2
1315 } else {
1316 tuple_count as usize * 2
1317 };
1318 Some(Self {
1319 data,
1320 state_table,
1321 value,
1322 tuple_count,
1323 tuple_size,
1324 })
1325 }
1326
1327 pub fn next(
1328 &self,
1329 state: &mut ContextualState,
1330 index: usize,
1331 glyph_id: u16,
1332 mut f: impl FnMut(usize, i16) -> Option<()>,
1333 ) -> Option<usize> {
1334 const PUSH: u16 = 0x8000;
1335 const DONT_ADVANCE: u16 = 0x4000;
1336 const RESET: u16 = 0x2000;
1337 let class = self.state_table.class(glyph_id);
1338 let entry = self.state_table.entry::<u16>(state.state, class)?;
1339 state.state = entry.new_state;
1340 if entry.flags & PUSH != 0 {
1341 if state.pos == state.stack.len() {
1342 return None;
1343 }
1344 state.stack[state.pos] = index;
1345 state.pos += 1;
1346 }
1347 if entry.data != 0xFFFF {
1348 let mut offset = self
1349 .value
1350 .checked_add(entry.data as usize)?
1351 .checked_mul(self.tuple_size)?;
1352 while state.pos > 0 {
1353 let value = self.data.read_i16(offset)?;
1354 if value as usize == 0xFFFF {
1355 break;
1356 }
1357 let pos = state.pos - 1;
1358 state.pos = pos;
1359 f(state.stack[pos], value)?;
1360 offset = offset.checked_add(self.tuple_size)?;
1361 }
1362 }
1363 if entry.flags & RESET != 0 {
1364 state.pos = 0;
1365 }
1366 let mut advance = entry.flags & DONT_ADVANCE == 0;
1367 if advance {
1368 state.cycles = 0;
1369 } else if state.cycles > MAX_CYCLES {
1370 state.cycles = 0;
1371 advance = true;
1372 } else {
1373 state.cycles += 1;
1374 }
1375 Some(advance as usize)
1376 }
1377 }
1378
1379 #[derive(Copy, Clone, Default)]
1381 pub struct ContextualState {
1382 state: u16,
1383 stack: [usize; 8],
1384 pos: usize,
1385 cycles: u16,
1386 }
1387
1388 impl ContextualState {
1389 pub fn new() -> Self {
1391 Self::default()
1392 }
1393 }
1394
1395 #[derive(Copy, Clone)]
1397 pub struct Format2<'a> {
1398 data: Bytes<'a>,
1399 l_table: usize,
1400 r_table: usize,
1401 array: usize,
1402 }
1403
1404 impl<'a> Format2<'a> {
1405 fn new(data: Bytes<'a>) -> Option<Self> {
1406 let l_table = data.read_u32(16)? as usize;
1407 let r_table = data.read_u32(20)? as usize;
1408 let array = data.read_u32(24)? as usize;
1409 Some(Self {
1410 data,
1411 l_table,
1412 r_table,
1413 array,
1414 })
1415 }
1416
1417 pub fn get(&self, left: u16, right: u16) -> Option<i16> {
1419 let b = &self.data;
1420 let row = lookup::<u16>(b, self.l_table, left)? as usize;
1421 let column = lookup::<u16>(b, self.r_table, right)? as usize;
1422 b.read_i16(self.array + row + column)
1423 }
1424 }
1425
1426 #[derive(Copy, Clone)]
1428 #[allow(dead_code)]
1429 pub struct Format4<'a> {
1430 data: Bytes<'a>,
1431 state_table: ExtendedStateTable<'a>,
1432 action_type: u32,
1433 control_table: usize,
1434 ankr: &'a [u8],
1435 }
1436
1437 impl<'a> Format4<'a> {
1438 fn new(data: Bytes<'a>, ankr: &'a [u8]) -> Option<Self> {
1439 let data = Bytes::with_offset(data.data(), 12)?;
1440 let state_table = ExtendedStateTable::new(&data)?;
1441 let flags = data.read_u32(16)?;
1442 let action_type = (flags & 0xC0000000) >> 30;
1443 let control_table = (flags & 0x00FFFFFF) as usize;
1444 Some(Self {
1445 data,
1446 state_table,
1447 action_type,
1448 control_table,
1449 ankr,
1450 })
1451 }
1452
1453 pub fn next(
1454 &self,
1455 state: &mut Format4State,
1456 index: usize,
1457 glyph_id: u16,
1458 mut f: impl FnMut(usize, usize, f32, f32) -> Option<()>,
1459 ) -> Option<usize> {
1460 const MARK: u16 = 0x8000;
1461 const DONT_ADVANCE: u16 = 0x4000;
1462 let class = self.state_table.class(glyph_id);
1463 let entry = self.state_table.entry::<u16>(state.state, class)?;
1464 state.state = entry.new_state;
1465 if entry.flags & MARK != 0 {
1466 state.mark = index;
1467 state.mark_id = glyph_id;
1468 }
1469 if entry.data != 0xFFFF {
1470 let offset = self.control_table.checked_add(entry.data as usize * 2)?;
1471 match self.action_type {
1472 0 => {}
1473 1 => {
1474 let mark_index = self.data.read_u16(offset)?;
1475 let cur_index = self.data.read_u16(offset + 2)?;
1476 if let Some((x, y)) =
1477 self.anchor_offset(mark_index, state.mark_id, cur_index, glyph_id)
1478 {
1479 let diff = index - state.mark;
1480 if diff < 255 {
1481 f(index, diff, x, y);
1482 }
1483 }
1484 }
1485 2 => {}
1486 _ => {}
1487 }
1488 }
1489 let mut advance = entry.flags & DONT_ADVANCE == 0;
1490 if advance {
1491 state.cycles = 0;
1492 } else if state.cycles > MAX_CYCLES {
1493 state.cycles = 0;
1494 advance = true;
1495 } else {
1496 state.cycles += 1;
1497 }
1498 Some(advance as usize)
1499 }
1500
1501 fn anchor_offset(
1502 &self,
1503 mark_index: u16,
1504 mark_id: u16,
1505 cur_index: u16,
1506 cur_id: u16,
1507 ) -> Option<(f32, f32)> {
1508 let mark_point = anchor_points(self.ankr, mark_id)?.get(mark_index as u32)?;
1509 let cur_point = anchor_points(self.ankr, cur_id)?.get(cur_index as u32)?;
1510 Some((
1511 mark_point.0 as f32 - cur_point.0 as f32,
1512 mark_point.1 as f32 - cur_point.1 as f32,
1513 ))
1514 }
1515 }
1516
1517 #[derive(Copy, Clone, Default)]
1519 pub struct Format4State {
1520 state: u16,
1521 mark: usize,
1522 mark_id: u16,
1523 cycles: u16,
1524 }
1525
1526 impl Format4State {
1527 pub fn new() -> Self {
1528 Self::default()
1529 }
1530 }
1531
1532 pub fn anchor_points<'a>(data: &'a [u8], glyph_id: u16) -> Option<AnchorPoints<'a>> {
1534 if data.is_empty() {
1535 return None;
1536 }
1537 let b = Bytes::new(data);
1538 let lookup_offset = b.read_u32(4)? as usize;
1539 let base = b.read_u32(8)? as usize;
1540 let offset = lookup::<u16>(&b, lookup_offset, glyph_id)? as usize + base;
1541 Some(AnchorPoints {
1542 data: b,
1543 offset,
1544 len: b.read_u32(offset)?,
1545 })
1546 }
1547
1548 #[derive(Copy, Clone)]
1550 pub struct AnchorPoints<'a> {
1551 data: Bytes<'a>,
1552 offset: usize,
1553 len: u32,
1554 }
1555
1556 impl<'a> AnchorPoints<'a> {
1557 pub fn len(&self) -> u32 {
1559 self.len
1560 }
1561 pub fn get(&self, index: u32) -> Option<(i16, i16)> {
1564 let offset = self.offset + 4 + index as usize * 4;
1565 let x = self.data.read::<i16>(offset)?;
1566 let y = self.data.read::<i16>(offset + 2)?;
1567 Some((x, y))
1568 }
1569 }
1570}
1571
1572pub mod kern {
1574 use super::*;
1575
1576 pub fn subtables<'a>(data: &'a [u8], kern: u32) -> Subtables<'a> {
1577 let b = if kern == 0 {
1578 Bytes::new(&[])
1579 } else {
1580 Bytes::with_offset(data, kern as usize).unwrap_or_else(|| Bytes::new(&[]))
1581 };
1582 let version = b.read_or_default::<u16>(0);
1583 if version == 0 {
1584 let len = b.read_or_default::<u16>(2) as u32;
1585 Subtables {
1586 data: b,
1587 offset: 4,
1588 len,
1589 cur: 0,
1590 is_aat: false,
1591 }
1592 } else {
1593 let len = b.read_or_default::<u32>(4);
1594 Subtables {
1595 data: b,
1596 offset: 8,
1597 len,
1598 cur: 0,
1599 is_aat: true,
1600 }
1601 }
1602 }
1603
1604 #[derive(Copy, Clone)]
1605 pub struct Subtables<'a> {
1606 data: Bytes<'a>,
1607 offset: usize,
1608 len: u32,
1609 cur: u32,
1610 is_aat: bool,
1611 }
1612
1613 impl<'a> Iterator for Subtables<'a> {
1614 type Item = Subtable<'a>;
1615
1616 fn next(&mut self) -> Option<Self::Item> {
1617 if self.cur >= self.len {
1618 return None;
1619 }
1620 self.cur += 1;
1621 let offset = self.offset;
1622 let subtable = Subtable::new(&self.data, offset, self.is_aat)?;
1623 self.offset = self.offset.checked_add(subtable.size as usize)?;
1624 Some(subtable)
1625 }
1626 }
1627
1628 #[derive(Copy, Clone)]
1630 pub struct Subtable<'a> {
1631 data: Bytes<'a>,
1632 offset: usize,
1633 size: u32,
1634 coverage: u16,
1635 is_aat: bool,
1636 is_horizontal: bool,
1637 cross_stream: bool,
1638 format: u8,
1639 }
1640
1641 impl<'a> Subtable<'a> {
1642 fn new(data: &Bytes<'a>, mut offset: usize, is_aat: bool) -> Option<Self> {
1643 let data = Bytes::with_offset(data.data(), offset)?;
1644 let size = if is_aat {
1645 offset = 8;
1646 data.read_u32(0)?
1647 } else {
1648 offset = 6;
1649 data.read_u16(2)? as u32
1650 };
1651 let coverage = data.read_u16(4)?;
1652 let (is_horizontal, cross_stream, format) = if is_aat {
1653 let format = (coverage & 0xFF) as u8;
1654 let is_vertical = coverage & 0x8000 != 0;
1655 let cross_stream = coverage & 0x4000 != 0;
1656 (!is_vertical, cross_stream, format)
1657 } else {
1658 let format = (coverage & 0xFF00) >> 8;
1659 let coverage = coverage & 0xFF;
1660 let is_horizontal = coverage & (1 << 0) != 0;
1661 let cross_stream = coverage & (1 << 2) != 0;
1662 (is_horizontal, cross_stream, format as u8)
1663 };
1664 Some(Self {
1665 data,
1666 offset,
1667 size,
1668 coverage,
1669 is_aat,
1670 is_horizontal,
1671 cross_stream,
1672 format,
1673 })
1674 }
1675
1676 pub fn is_horizontal(&self) -> bool {
1677 self.is_horizontal
1678 }
1679
1680 pub fn cross_stream(&self) -> bool {
1681 self.cross_stream
1682 }
1683
1684 pub fn kind(&self) -> Option<SubtableKind<'a>> {
1685 Some(match self.format {
1686 0 => SubtableKind::Format0(Format0::new(self)?),
1687 1 => SubtableKind::Format1(Format1::new(self)?),
1688 _ => return None,
1689 })
1690 }
1691 }
1692
1693 #[derive(Copy, Clone)]
1694 pub enum SubtableKind<'a> {
1695 Format0(Format0<'a>),
1696 Format1(Format1<'a>),
1697 }
1698
1699 #[derive(Copy, Clone)]
1700 pub struct Format0<'a> {
1701 data: Bytes<'a>,
1702 offset: usize,
1703 count: usize,
1704 }
1705
1706 impl<'a> Format0<'a> {
1707 fn new(subtable: &Subtable<'a>) -> Option<Self> {
1708 let count = subtable.data.read_u16(subtable.offset)? as usize;
1709 Some(Self {
1710 data: subtable.data,
1711 offset: subtable.offset + 8,
1712 count,
1713 })
1714 }
1715
1716 pub fn get(&self, left: u16, right: u16) -> Option<i16> {
1718 let key = (left as u32) << 16 | right as u32;
1719 let base = self.offset;
1720 let reclen = 6;
1721 let b = &self.data;
1722 let mut l = 0;
1723 let mut h = self.count;
1724 while l < h {
1725 use core::cmp::Ordering::*;
1726 let i = (l + h) / 2;
1727 let pair = b.read::<u32>(base + i * reclen)?;
1728 match key.cmp(&pair) {
1729 Greater => l = i + 1,
1730 Less => h = i,
1731 Equal => return b.read_i16(base + i * reclen + 4),
1732 }
1733 }
1734 None
1735 }
1736 }
1737
1738 #[derive(Copy, Clone)]
1740 #[allow(dead_code)]
1741 pub struct Format1<'a> {
1742 data: Bytes<'a>,
1743 state_table: StateTable<'a>,
1744 cross_stream: bool,
1745 }
1746
1747 impl<'a> Format1<'a> {
1748 fn new(subtable: &Subtable<'a>) -> Option<Self> {
1749 let data = Bytes::with_offset(subtable.data.data(), subtable.offset)?;
1750 let state_table = StateTable::new(&data)?;
1751 Some(Self {
1752 data,
1753 state_table,
1754 cross_stream: subtable.cross_stream,
1755 })
1756 }
1757
1758 pub fn next(
1759 &self,
1760 state: &mut Format1State,
1761 index: usize,
1762 glyph_id: u16,
1763 mut f: impl FnMut(usize, i16) -> Option<()>,
1764 ) -> Option<usize> {
1765 const PUSH: u16 = 0x8000;
1766 const DONT_ADVANCE: u16 = 0x4000;
1767 let class = self.state_table.class(glyph_id);
1768 let entry = self.state_table.entry::<()>(state.state, class)?;
1769 state.state = entry.new_state;
1770 if entry.flags & PUSH != 0 {
1771 if state.pos == state.stack.len() {
1772 return None;
1773 }
1774 state.stack[state.pos] = index;
1775 state.pos += 1;
1776 } else if entry.flags == 0 {
1777 state.pos = 0;
1778 }
1779 let mut value_offset = (entry.flags & 0x3FFF) as usize;
1780 if value_offset != 0 {
1781 while state.pos > 0 {
1782 let mut value = self.data.read_i16(value_offset)?;
1783 let mut last = false;
1784 if value & 1 != 0 {
1785 last = true;
1786 value &= !1;
1787 }
1788 let pos = state.pos - 1;
1789 state.pos = pos;
1790 if self.cross_stream && value as u16 == 0x8000 {
1791 } else {
1793 f(state.stack[pos], value)?;
1794 }
1795 if last {
1796 state.pos = 0;
1797 break;
1798 }
1799 value_offset += 2;
1800 }
1801 }
1802 let mut advance = entry.flags & DONT_ADVANCE == 0;
1803 if advance {
1804 state.cycles = 0;
1805 } else if state.cycles > MAX_CYCLES {
1806 state.cycles = 0;
1807 advance = true;
1808 } else {
1809 state.cycles += 1;
1810 }
1811 Some(advance as usize)
1812 }
1813 }
1814
1815 #[derive(Copy, Clone, Default)]
1817 pub struct Format1State {
1818 state: u16,
1819 stack: [usize; 8],
1820 pos: usize,
1821 cycles: u16,
1822 }
1823
1824 impl Format1State {
1825 pub fn new() -> Self {
1827 Self::default()
1828 }
1829 }
1830}