#ifndef OT_LAYOUT_GPOS_MARKARRAY_HH #define OT_LAYOUT_GPOS_MARKARRAY_HH #include "AnchorMatrix.hh" #include "MarkRecord.hh" namespace OT { namespace Layout { namespace GPOS_impl { struct MarkArray : Array16Of /* Array of MarkRecords--in Coverage order */ { bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (Array16Of::sanitize (c, this)); } bool apply (hb_ot_apply_context_t *c, unsigned int mark_index, unsigned int glyph_index, const AnchorMatrix &anchors, unsigned int class_count, unsigned int glyph_pos) const { TRACE_APPLY (this); hb_buffer_t *buffer = c->buffer; const MarkRecord &record = Array16Of::operator[](mark_index); unsigned int mark_class = record.klass; const Anchor& mark_anchor = this + record.markAnchor; bool found; const Anchor& glyph_anchor = anchors.get_anchor (glyph_index, mark_class, class_count, &found); /* If this subtable doesn't have an anchor for this base and this class, * return false such that the subsequent subtables have a chance at it. */ if (unlikely (!found)) return_trace (false); float mark_x, mark_y, base_x, base_y; buffer->unsafe_to_break (glyph_pos, buffer->idx + 1); mark_anchor.get_anchor (c, buffer->cur().codepoint, &mark_x, &mark_y); glyph_anchor.get_anchor (c, buffer->info[glyph_pos].codepoint, &base_x, &base_y); hb_glyph_position_t &o = buffer->cur_pos(); o.x_offset = roundf (base_x - mark_x); o.y_offset = roundf (base_y - mark_y); o.attach_type() = ATTACH_TYPE_MARK; o.attach_chain() = (int) glyph_pos - (int) buffer->idx; buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT; buffer->idx++; return_trace (true); } template bool subset (hb_subset_context_t *c, Iterator coverage, const hb_map_t *klass_mapping) const { TRACE_SUBSET (this); const hb_set_t &glyphset = *c->plan->glyphset_gsub (); auto* out = c->serializer->start_embed (this); if (unlikely (!c->serializer->extend_min (out))) return_trace (false); auto mark_iter = + hb_zip (coverage, this->iter ()) | hb_filter (glyphset, hb_first) | hb_map (hb_second) ; unsigned new_length = 0; for (const auto& mark_record : mark_iter) { if (unlikely (!mark_record.subset (c, this, klass_mapping))) return_trace (false); new_length++; } if (unlikely (!c->serializer->check_assign (out->len, new_length, HB_SERIALIZE_ERROR_ARRAY_OVERFLOW))) return_trace (false); return_trace (true); } }; static void Markclass_closure_and_remap_indexes (const Coverage &mark_coverage, const MarkArray &mark_array, const hb_set_t &glyphset, hb_map_t* klass_mapping /* INOUT */) { hb_set_t orig_classes; + hb_zip (mark_coverage, mark_array) | hb_filter (glyphset, hb_first) | hb_map (hb_second) | hb_map (&MarkRecord::get_class) | hb_sink (orig_classes) ; unsigned idx = 0; for (auto klass : orig_classes.iter ()) { if (klass_mapping->has (klass)) continue; klass_mapping->set (klass, idx); idx++; } } } } } #endif /* OT_LAYOUT_GPOS_MARKARRAY_HH */