1#ifndef OT_LAYOUT_GPOS_ANCHORMATRIX_HH
2#define OT_LAYOUT_GPOS_ANCHORMATRIX_HH
3
4namespace OT {
5namespace Layout {
6namespace GPOS_impl {
7
8struct AnchorMatrix
9{
10 HBUINT16 rows; /* Number of rows */
11 UnsizedArrayOf<Offset16To<Anchor>>
12 matrixZ; /* Matrix of offsets to Anchor tables--
13 * from beginning of AnchorMatrix table */
14 public:
15 DEFINE_SIZE_ARRAY (2, matrixZ);
16
17 bool sanitize (hb_sanitize_context_t *c, unsigned int cols) const
18 {
19 TRACE_SANITIZE (this);
20 if (!c->check_struct (this)) return_trace (false);
21 if (unlikely (hb_unsigned_mul_overflows (rows, cols))) return_trace (false);
22 unsigned int count = rows * cols;
23 if (!c->check_array (matrixZ.arrayZ, count)) return_trace (false);
24
25 if (c->lazy_some_gpos)
26 return_trace (true);
27
28 for (unsigned int i = 0; i < count; i++)
29 if (!matrixZ[i].sanitize (c, this)) return_trace (false);
30 return_trace (true);
31 }
32
33 const Anchor& get_anchor (hb_ot_apply_context_t *c,
34 unsigned int row, unsigned int col,
35 unsigned int cols, bool *found) const
36 {
37 *found = false;
38 if (unlikely (row >= rows || col >= cols)) return Null (Anchor);
39 auto &offset = matrixZ[row * cols + col];
40 if (unlikely (!offset.sanitize (&c->sanitizer, this))) return Null (Anchor);
41 *found = !offset.is_null ();
42 return this+offset;
43 }
44
45 template <typename Iterator,
46 hb_requires (hb_is_iterator (Iterator))>
47 void collect_variation_indices (hb_collect_variation_indices_context_t *c,
48 Iterator index_iter) const
49 {
50 for (unsigned i : index_iter)
51 (this+matrixZ[i]).collect_variation_indices (c);
52 }
53
54 template <typename Iterator,
55 hb_requires (hb_is_iterator (Iterator))>
56 bool subset (hb_subset_context_t *c,
57 unsigned num_rows,
58 Iterator index_iter) const
59 {
60 TRACE_SUBSET (this);
61
62 auto *out = c->serializer->start_embed (this);
63
64 if (!index_iter) return_trace (false);
65 if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
66
67 out->rows = num_rows;
68 for (const unsigned i : index_iter)
69 {
70 auto *offset = c->serializer->embed (matrixZ[i]);
71 if (!offset) return_trace (false);
72 offset->serialize_subset (c, matrixZ[i], this);
73 }
74
75 return_trace (true);
76 }
77};
78
79
80}
81}
82}
83
84#endif /* OT_LAYOUT_GPOS_ANCHORMATRIX_HH */
85