| #ifndef OT_LAYOUT_GPOS_ANCHORMATRIX_HH | |
| #define OT_LAYOUT_GPOS_ANCHORMATRIX_HH | |
| namespace OT { | |
| namespace Layout { | |
| namespace GPOS_impl { | |
| template <typename Types, typename RowCount=typename Types::HBUINT> | |
| struct AnchorMatrix | |
| { | |
| RowCount rows; /* Number of rows */ | |
| UnsizedArrayOf<typename Types::template OffsetTo<Anchor, AnchorMatrix>> | |
| matrixZ; /* Matrix of offsets to Anchor tables-- | |
| * from beginning of AnchorMatrix table */ | |
| public: | |
| DEFINE_SIZE_ARRAY (sizeof (RowCount), matrixZ); | |
| bool sanitize (hb_sanitize_context_t *c, unsigned int cols) const | |
| { | |
| TRACE_SANITIZE (this); | |
| if (!c->check_struct (this)) return_trace (false); | |
| hb_barrier (); | |
| if (unlikely (hb_unsigned_mul_overflows (rows, cols))) return_trace (false); | |
| unsigned int count = rows * cols; | |
| if (!c->check_array (matrixZ.arrayZ, count)) return_trace (false); | |
| if (c->lazy_some_gpos) | |
| return_trace (true); | |
| hb_barrier (); | |
| for (unsigned int i = 0; i < count; i++) | |
| if (!matrixZ[i].sanitize (c, this)) return_trace (false); | |
| return_trace (true); | |
| } | |
| const Anchor& get_anchor (hb_ot_apply_context_t *c, | |
| unsigned int row, unsigned int col, | |
| unsigned int cols, bool *found) const | |
| { | |
| *found = false; | |
| if (unlikely (row >= rows || col >= cols)) return Null (Anchor); | |
| auto &offset = matrixZ[row * cols + col]; | |
| if (unlikely (!offset.sanitize (&c->sanitizer, this))) return Null (Anchor); | |
| hb_barrier (); | |
| *found = !offset.is_null (); | |
| return this+offset; | |
| } | |
| template <typename Iterator, | |
| hb_requires (hb_is_iterator (Iterator))> | |
| void collect_variation_indices (hb_collect_variation_indices_context_t *c, | |
| Iterator index_iter) const | |
| { | |
| for (unsigned i : index_iter) | |
| (this+matrixZ[i]).collect_variation_indices (c); | |
| } | |
| template <typename Iterator, | |
| hb_requires (hb_is_iterator (Iterator))> | |
| bool subset (hb_subset_context_t *c, | |
| unsigned num_rows, | |
| Iterator index_iter) const | |
| { | |
| TRACE_SUBSET (this); | |
| auto *out = c->serializer->start_embed (this); | |
| if (!index_iter) return_trace (false); | |
| if (unlikely (!c->serializer->extend_min (out))) return_trace (false); | |
| out->rows = num_rows; | |
| for (const unsigned i : index_iter) | |
| { | |
| auto *offset = c->serializer->embed (matrixZ[i]); | |
| if (!offset) return_trace (false); | |
| offset->serialize_subset (c, matrixZ[i], this); | |
| } | |
| return_trace (true); | |
| } | |
| bool offset_is_null (unsigned row, unsigned col, unsigned num_cols) const | |
| { | |
| if (unlikely (row >= rows || col >= num_cols)) return true; | |
| auto &offset = matrixZ[row * num_cols + col]; | |
| return offset.is_null (); | |
| } | |
| }; | |
| } | |
| } | |
| } | |
| #endif /* OT_LAYOUT_GPOS_ANCHORMATRIX_HH */ |