MarkArray.hh (4044B)
1 #ifndef OT_LAYOUT_GPOS_MARKARRAY_HH 2 #define OT_LAYOUT_GPOS_MARKARRAY_HH 3 4 #include "AnchorMatrix.hh" 5 #include "MarkRecord.hh" 6 7 namespace OT { 8 namespace Layout { 9 namespace GPOS_impl { 10 11 struct MarkArray : Array16Of<MarkRecord> /* Array of MarkRecords--in Coverage order */ 12 { 13 bool sanitize (hb_sanitize_context_t *c) const 14 { 15 TRACE_SANITIZE (this); 16 return_trace (Array16Of<MarkRecord>::sanitize (c, this)); 17 } 18 19 bool apply (hb_ot_apply_context_t *c, 20 unsigned int mark_index, unsigned int glyph_index, 21 const AnchorMatrix &anchors, unsigned int class_count, 22 unsigned int glyph_pos) const 23 { 24 TRACE_APPLY (this); 25 hb_buffer_t *buffer = c->buffer; 26 const MarkRecord &record = Array16Of<MarkRecord>::operator[](mark_index); 27 unsigned int mark_class = record.klass; 28 29 const Anchor& mark_anchor = this + record.markAnchor; 30 bool found; 31 const Anchor& glyph_anchor = anchors.get_anchor (c, glyph_index, mark_class, class_count, &found); 32 /* If this subtable doesn't have an anchor for this base and this class, 33 * return false such that the subsequent subtables have a chance at it. */ 34 if (unlikely (!found)) return_trace (false); 35 36 float mark_x, mark_y, base_x, base_y; 37 38 buffer->unsafe_to_break (glyph_pos, buffer->idx + 1); 39 mark_anchor.get_anchor (c, buffer->cur().codepoint, &mark_x, &mark_y); 40 glyph_anchor.get_anchor (c, buffer->info[glyph_pos].codepoint, &base_x, &base_y); 41 42 if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) 43 { 44 c->buffer->message (c->font, 45 "attaching mark glyph at %u to glyph at %u", 46 c->buffer->idx, glyph_pos); 47 } 48 49 hb_glyph_position_t &o = buffer->cur_pos(); 50 o.attach_chain() = (int) glyph_pos - (int) buffer->idx; 51 if (o.attach_chain() != (int) glyph_pos - (int) buffer->idx) 52 { 53 o.attach_chain() = 0; 54 goto overflow; 55 } 56 o.attach_type() = ATTACH_TYPE_MARK; 57 o.x_offset = roundf (base_x - mark_x); 58 o.y_offset = roundf (base_y - mark_y); 59 buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT; 60 61 if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) 62 { 63 c->buffer->message (c->font, 64 "attached mark glyph at %u to glyph at %u", 65 c->buffer->idx, glyph_pos); 66 } 67 68 overflow: 69 buffer->idx++; 70 return_trace (true); 71 } 72 73 template <typename Iterator, 74 hb_requires (hb_is_iterator (Iterator))> 75 bool subset (hb_subset_context_t *c, 76 Iterator coverage, 77 const hb_map_t *klass_mapping) const 78 { 79 TRACE_SUBSET (this); 80 const hb_set_t &glyphset = *c->plan->glyphset_gsub (); 81 82 auto* out = c->serializer->start_embed (this); 83 if (unlikely (!c->serializer->extend_min (out))) return_trace (false); 84 85 auto mark_iter = 86 + hb_zip (coverage, this->iter ()) 87 | hb_filter (glyphset, hb_first) 88 | hb_map (hb_second) 89 ; 90 91 bool ret = false; 92 unsigned new_length = 0; 93 for (const auto& mark_record : mark_iter) { 94 ret |= mark_record.subset (c, this, klass_mapping); 95 new_length++; 96 } 97 98 if (unlikely (!c->serializer->check_assign (out->len, new_length, 99 HB_SERIALIZE_ERROR_ARRAY_OVERFLOW))) 100 return_trace (false); 101 102 return_trace (ret); 103 } 104 }; 105 106 HB_INTERNAL inline 107 void Markclass_closure_and_remap_indexes (const Coverage &mark_coverage, 108 const MarkArray &mark_array, 109 const hb_set_t &glyphset, 110 hb_map_t* klass_mapping /* INOUT */) 111 { 112 hb_set_t orig_classes; 113 114 + hb_zip (mark_coverage, mark_array) 115 | hb_filter (glyphset, hb_first) 116 | hb_map (hb_second) 117 | hb_map (&MarkRecord::get_class) 118 | hb_sink (orig_classes) 119 ; 120 121 unsigned idx = 0; 122 for (auto klass : orig_classes.iter ()) 123 { 124 if (klass_mapping->has (klass)) continue; 125 klass_mapping->set (klass, idx); 126 idx++; 127 } 128 } 129 130 } 131 } 132 } 133 134 #endif /* OT_LAYOUT_GPOS_MARKARRAY_HH */