rustybuzz/hb/
ot_layout_common.rs1use crate::hb::set_digest::{hb_set_digest_ext, hb_set_digest_t};
2use alloc::vec::Vec;
3use ttf_parser::gpos::PositioningSubtable;
4use ttf_parser::gsub::SubstitutionSubtable;
5use ttf_parser::opentype_layout::{Coverage, Lookup};
6
7#[allow(dead_code)]
8pub mod lookup_flags {
9 pub const RIGHT_TO_LEFT: u16 = 0x0001;
10 pub const IGNORE_BASE_GLYPHS: u16 = 0x0002;
11 pub const IGNORE_LIGATURES: u16 = 0x0004;
12 pub const IGNORE_MARKS: u16 = 0x0008;
13 pub const IGNORE_FLAGS: u16 = 0x000E;
14 pub const USE_MARK_FILTERING_SET: u16 = 0x0010;
15 pub const MARK_ATTACHMENT_TYPE_MASK: u16 = 0xFF00;
16}
17
18#[derive(Clone)]
19pub struct PositioningTable<'a> {
20 pub inner: ttf_parser::opentype_layout::LayoutTable<'a>,
21 pub lookups: Vec<PositioningLookup<'a>>,
22}
23
24impl<'a> PositioningTable<'a> {
25 pub fn new(inner: ttf_parser::opentype_layout::LayoutTable<'a>) -> Self {
26 let lookups = inner
27 .lookups
28 .into_iter()
29 .map(PositioningLookup::parse)
30 .collect();
31
32 Self { inner, lookups }
33 }
34}
35
36pub trait CoverageExt {
37 fn collect(&self, set_digest: &mut hb_set_digest_t);
38}
39
40impl CoverageExt for Coverage<'_> {
41 fn collect(&self, set_digest: &mut hb_set_digest_t) {
43 match *self {
44 Self::Format1 { glyphs } => {
45 set_digest.add_array(glyphs);
46 }
47 Self::Format2 { records } => {
48 for record in records {
49 set_digest.add_range(record.start, record.end);
50 }
51 }
52 }
53 }
54}
55
56#[derive(Clone)]
57pub struct PositioningLookup<'a> {
58 pub subtables: Vec<PositioningSubtable<'a>>,
59 pub set_digest: hb_set_digest_t,
60 pub props: u32,
61}
62
63impl<'a> PositioningLookup<'a> {
64 pub fn parse(lookup: Lookup<'a>) -> Self {
65 let subtables: Vec<_> = lookup
66 .subtables
67 .into_iter::<PositioningSubtable>()
68 .collect();
69
70 let mut set_digest = hb_set_digest_t::new();
71 for subtable in &subtables {
72 subtable.coverage().collect(&mut set_digest);
73 }
74
75 Self {
76 subtables,
77 set_digest,
78 props: lookup_props(lookup),
79 }
80 }
81}
82
83#[derive(Clone)]
84pub struct SubstitutionTable<'a> {
85 pub inner: ttf_parser::opentype_layout::LayoutTable<'a>,
86 pub lookups: Vec<SubstLookup<'a>>,
87}
88
89impl<'a> SubstitutionTable<'a> {
90 pub fn new(inner: ttf_parser::opentype_layout::LayoutTable<'a>) -> Self {
91 let lookups = inner.lookups.into_iter().map(SubstLookup::parse).collect();
92
93 Self { inner, lookups }
94 }
95}
96
97#[derive(Clone)]
98pub struct SubstLookup<'a> {
99 pub subtables: Vec<SubstitutionSubtable<'a>>,
100 pub set_digest: hb_set_digest_t,
101 pub reverse: bool,
102 pub props: u32,
103}
104
105impl<'a> SubstLookup<'a> {
106 pub fn parse(lookup: Lookup<'a>) -> Self {
107 let subtables: Vec<_> = lookup
108 .subtables
109 .into_iter::<SubstitutionSubtable>()
110 .collect();
111
112 let mut set_digest = hb_set_digest_t::new();
113 let mut reverse = !subtables.is_empty();
114
115 for subtable in &subtables {
116 subtable.coverage().collect(&mut set_digest);
117 reverse &= subtable.is_reverse();
118 }
119
120 Self {
121 subtables,
122 set_digest,
123 reverse,
124 props: lookup_props(lookup),
125 }
126 }
127}
128
129fn lookup_props(lookup: Lookup) -> u32 {
133 let mut props = u32::from(lookup.flags.0);
134 if let Some(set) = lookup.mark_filtering_set {
135 props |= u32::from(set) << 16;
136 }
137 props
138}