diff --git a/src/hb-ot-layout-gpos-table.hh b/src/hb-ot-layout-gpos-table.hh index d24a06138..412850ba3 100644 --- a/src/hb-ot-layout-gpos-table.hh +++ b/src/hb-ot-layout-gpos-table.hh @@ -629,23 +629,18 @@ struct PairPosFormat1 inline bool apply (hb_apply_context_t *c) const { TRACE_APPLY (); - unsigned int j = c->buffer->idx; - unsigned int end = MIN (c->buffer->len, j + c->context_length); - if (unlikely (j >= end)) + hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, 1); + if (skippy_iter.has_no_chance ()) return false; - unsigned int index = (this+coverage) (c->buffer->info[j].codepoint); + unsigned int index = (this+coverage) (c->buffer->info[c->buffer->idx].codepoint); if (likely (index == NOT_COVERED)) return false; - do - { - j++; - if (unlikely (j == end)) - return false; - } while (_hb_ot_layout_skip_mark (c->face, &c->buffer->info[j], c->lookup_props, NULL)); + if (!skippy_iter.next ()) + return false; - return (this+pairSet[index]).apply (c, &valueFormat1, j); + return (this+pairSet[index]).apply (c, &valueFormat1, skippy_iter.idx); } inline bool sanitize (hb_sanitize_context_t *c) { @@ -691,28 +686,23 @@ struct PairPosFormat2 inline bool apply (hb_apply_context_t *c) const { TRACE_APPLY (); - unsigned int j = c->buffer->idx; - unsigned int end = MIN (c->buffer->len, j + c->context_length); - if (unlikely (j >= end)) + hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, 1); + if (skippy_iter.has_no_chance ()) return false; - unsigned int index = (this+coverage) (c->buffer->info[j].codepoint); + unsigned int index = (this+coverage) (c->buffer->info[c->buffer->idx].codepoint); if (likely (index == NOT_COVERED)) return false; - do - { - j++; - if (unlikely (j == end)) - return false; - } while (_hb_ot_layout_skip_mark (c->face, &c->buffer->info[j], c->lookup_props, NULL)); + if (!skippy_iter.next ()) + return false; unsigned int len1 = valueFormat1.get_len (); unsigned int len2 = valueFormat2.get_len (); unsigned int record_len = len1 + len2; unsigned int klass1 = (this+classDef1) (c->buffer->info[c->buffer->idx].codepoint); - unsigned int klass2 = (this+classDef2) (c->buffer->info[j].codepoint); + unsigned int klass2 = (this+classDef2) (c->buffer->info[skippy_iter.idx].codepoint); if (unlikely (klass1 >= class1Count || klass2 >= class2Count)) return false; @@ -720,11 +710,11 @@ struct PairPosFormat2 valueFormat1.apply_value (c->font, c->direction, this, v, c->buffer->pos[c->buffer->idx]); valueFormat2.apply_value (c->font, c->direction, this, - v + len1, c->buffer->pos[j]); + v + len1, c->buffer->pos[skippy_iter.idx]); + c->buffer->idx = skippy_iter.idx; if (len2) - j++; - c->buffer->idx = j; + c->buffer->idx++; return true; } @@ -846,27 +836,23 @@ struct CursivePosFormat1 if (c->property & HB_OT_LAYOUT_GLYPH_CLASS_MARK) return false; - unsigned int j = c->buffer->idx; - unsigned int end = MIN (c->buffer->len, j + c->context_length); - if (unlikely (j >= end)) + hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, 1); + if (skippy_iter.has_no_chance ()) return false; - const EntryExitRecord &this_record = entryExitRecord[(this+coverage) (c->buffer->info[j].codepoint)]; + const EntryExitRecord &this_record = entryExitRecord[(this+coverage) (c->buffer->info[c->buffer->idx].codepoint)]; if (!this_record.exitAnchor) return false; - do - { - j++; - if (unlikely (j == end)) - return false; - } while (_hb_ot_layout_skip_mark (c->face, &c->buffer->info[j], c->lookup_props, NULL)); + if (!skippy_iter.next ()) + return false; - const EntryExitRecord &next_record = entryExitRecord[(this+coverage) (c->buffer->info[j].codepoint)]; + const EntryExitRecord &next_record = entryExitRecord[(this+coverage) (c->buffer->info[skippy_iter.idx].codepoint)]; if (!next_record.entryAnchor) return false; unsigned int i = c->buffer->idx; + unsigned int j = skippy_iter.idx; hb_position_t entry_x, entry_y, exit_x, exit_y; (this+this_record.exitAnchor).get_anchor (c->font, c->buffer->info[i].codepoint, &exit_x, &exit_y); @@ -997,23 +983,19 @@ struct MarkBasePosFormat1 /* now we search backwards for a non-mark glyph */ unsigned int property; - unsigned int j = c->buffer->idx; - do - { - if (unlikely (!j)) - return false; - j--; - } while (_hb_ot_layout_skip_mark (c->face, &c->buffer->info[j], LookupFlag::IgnoreMarks, &property)); + hb_apply_context_t::mark_skipping_backward_iterator_t skippy_iter (c, c->buffer->idx, 1); + if (!skippy_iter.prev (&property, LookupFlag::IgnoreMarks)) + return false; /* The following assertion is too strong, so we've disabled it. */ if (!(property & HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH)) {/*return false;*/} - unsigned int base_index = (this+baseCoverage) (c->buffer->info[j].codepoint); + unsigned int base_index = (this+baseCoverage) (c->buffer->info[skippy_iter.idx].codepoint); if (base_index == NOT_COVERED) return false; - return (this+markArray).apply (c, mark_index, base_index, this+baseArray, classCount, j); + return (this+markArray).apply (c, mark_index, base_index, this+baseArray, classCount, skippy_iter.idx); } inline bool sanitize (hb_sanitize_context_t *c) { @@ -1099,18 +1081,15 @@ struct MarkLigPosFormat1 /* now we search backwards for a non-mark glyph */ unsigned int property; - unsigned int j = c->buffer->idx; - do - { - if (unlikely (!j)) - return false; - j--; - } while (_hb_ot_layout_skip_mark (c->face, &c->buffer->info[j], LookupFlag::IgnoreMarks, &property)); + hb_apply_context_t::mark_skipping_backward_iterator_t skippy_iter (c, c->buffer->idx, 1); + if (!skippy_iter.prev (&property, LookupFlag::IgnoreMarks)) + return false; /* The following assertion is too strong, so we've disabled it. */ if (!(property & HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE)) {/*return false;*/} + unsigned int j = skippy_iter.idx; unsigned int lig_index = (this+ligatureCoverage) (c->buffer->info[j].codepoint); if (lig_index == NOT_COVERED) return false; @@ -1218,17 +1197,15 @@ struct MarkMarkPosFormat1 /* now we search backwards for a suitable mark glyph until a non-mark glyph */ unsigned int property; - unsigned int j = c->buffer->idx; - do - { - if (unlikely (!j)) - return false; - j--; - } while (_hb_ot_layout_skip_mark (c->face, &c->buffer->info[j], c->lookup_props, &property)); + hb_apply_context_t::mark_skipping_backward_iterator_t skippy_iter (c, c->buffer->idx, 1); + if (!skippy_iter.prev (&property)) + return false; if (!(property & HB_OT_LAYOUT_GLYPH_CLASS_MARK)) return false; + unsigned int j = skippy_iter.idx; + /* Two marks match only if they belong to the same base, or same component * of the same ligature. That is, the component numbers must match, and * if those are non-zero, the ligid number should also match. */ diff --git a/src/hb-ot-layout-gsub-table.hh b/src/hb-ot-layout-gsub-table.hh index 0a17a7a72..77f440013 100644 --- a/src/hb-ot-layout-gsub-table.hh +++ b/src/hb-ot-layout-gsub-table.hh @@ -343,10 +343,12 @@ struct Ligature inline bool apply (hb_apply_context_t *c) const { TRACE_APPLY (); - unsigned int j = c->buffer->idx; unsigned int count = component.len; - unsigned int end = MIN (c->buffer->len, j + c->context_length); - if (unlikely (count < 2 || j >= end)) + if (unlikely (count < 2)) + return false; + + hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, count - 1); + if (skippy_iter.has_no_chance ()) return false; bool first_was_mark = (c->property & HB_OT_LAYOUT_GLYPH_CLASS_MARK); @@ -355,16 +357,13 @@ struct Ligature for (unsigned int i = 1; i < count; i++) { unsigned int property; - do - { - j++; - if (unlikely (j == end)) - return false; - } while (_hb_ot_layout_skip_mark (c->face, &c->buffer->info[j], c->lookup_props, &property)); + + if (!skippy_iter.next (&property)) + return false; found_non_mark |= !(property & HB_OT_LAYOUT_GLYPH_CLASS_MARK); - if (likely (c->buffer->info[j].codepoint != component[i])) + if (likely (c->buffer->info[skippy_iter.idx].codepoint != component[i])) return false; } @@ -376,7 +375,7 @@ struct Ligature c->buffer->info[c->buffer->idx].lig_comp() = 0; c->buffer->info[c->buffer->idx].lig_id() = lig_id; - if (j < c->buffer->idx + count) /* No input glyphs skipped */ + if (skippy_iter.idx < c->buffer->idx + count) /* No input glyphs skipped */ { c->replace_glyphs_be16 (count, 1, (const uint16_t *) &ligGlyph); } diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh index 24bc315b8..f22306f05 100644 --- a/src/hb-ot-layout-gsubgpos-private.hh +++ b/src/hb-ot-layout-gsubgpos-private.hh @@ -68,6 +68,85 @@ struct hb_apply_context_t unsigned int property; /* propety of first glyph */ + struct mark_skipping_forward_iterator_t + { + inline mark_skipping_forward_iterator_t (hb_apply_context_t *c_, + unsigned int start_index_, + unsigned int num_items_) + { + c = c_; + idx = start_index_; + num_items = num_items_; + end = MIN (c->buffer->len, c->buffer->idx + c->context_length); + } + inline bool has_no_chance (void) const + { + return unlikely (num_items && idx + num_items >= end); + } + inline bool next (unsigned int *property_out, + unsigned int lookup_props) + { + do + { + idx++; + if (has_no_chance ()) + return false; + } while (_hb_ot_layout_skip_mark (c->face, &c->buffer->info[idx], lookup_props, property_out)); + num_items--; + return true; + } + inline bool next (unsigned int *property_out = NULL) + { + return next (property_out, c->lookup_props); + } + + unsigned int idx; + private: + hb_apply_context_t *c; + unsigned int num_items; + unsigned int end; + }; + + struct mark_skipping_backward_iterator_t + { + inline mark_skipping_backward_iterator_t (hb_apply_context_t *c_, + unsigned int start_index_, + unsigned int num_items_) + { + c = c_; + idx = start_index_; + num_items = num_items_; + } + inline bool has_no_chance (void) const + { + return unlikely (num_items && num_items >= idx); + } + inline bool prev (unsigned int *property_out, + unsigned int lookup_props) + { + do + { + if (has_no_chance ()) + return false; + idx--; + } while (_hb_ot_layout_skip_mark (c->face, &c->buffer->out_info[idx], lookup_props, property_out)); + num_items--; + return true; + } + inline bool prev (unsigned int *property_out = NULL) + { + return prev (property_out, c->lookup_props); + } + + unsigned int idx; + private: + hb_apply_context_t *c; + unsigned int num_items; + }; + + + + inline void replace_glyph (hb_codepoint_t glyph_index) const { clear_property (); @@ -132,25 +211,20 @@ static inline bool match_input (hb_apply_context_t *c, const void *match_data, unsigned int *context_length_out) { - unsigned int j = c->buffer->idx; - unsigned int end = MIN (c->buffer->len, j + c->context_length); - if (unlikely (j + count > end)) + hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, count - 1); + if (skippy_iter.has_no_chance ()) return false; for (unsigned int i = 1; i < count; i++) { - do - { - j++; - if (unlikely (j >= end)) - return false; - } while (_hb_ot_layout_skip_mark (c->face, &c->buffer->info[j], c->lookup_props, NULL)); + if (!skippy_iter.next ()) + return false; - if (likely (!match_func (c->buffer->info[j].codepoint, input[i - 1], match_data))) + if (likely (!match_func (c->buffer->info[skippy_iter.idx].codepoint, input[i - 1], match_data))) return false; } - *context_length_out = j - c->buffer->idx + 1; + *context_length_out = skippy_iter.idx - c->buffer->idx + 1; return true; } @@ -161,18 +235,16 @@ static inline bool match_backtrack (hb_apply_context_t *c, match_func_t match_func, const void *match_data) { - unsigned int j = c->buffer->backtrack_len (); + hb_apply_context_t::mark_skipping_backward_iterator_t skippy_iter (c, c->buffer->backtrack_len (), count); + if (skippy_iter.has_no_chance ()) + return false; for (unsigned int i = 0; i < count; i++) { - do - { - if (unlikely (!j)) - return false; - j--; - } while (_hb_ot_layout_skip_mark (c->face, &c->buffer->out_info[j], c->lookup_props, NULL)); + if (!skippy_iter.prev ()) + return false; - if (likely (!match_func (c->buffer->out_info[j].codepoint, backtrack[i], match_data))) + if (likely (!match_func (c->buffer->out_info[skippy_iter.idx].codepoint, backtrack[i], match_data))) return false; } @@ -186,19 +258,16 @@ static inline bool match_lookahead (hb_apply_context_t *c, const void *match_data, unsigned int offset) { - unsigned int j = c->buffer->idx + offset - 1; - unsigned int end = MIN (c->buffer->len, c->buffer->idx + c->context_length); + hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buffer->idx + offset - 1, count); + if (skippy_iter.has_no_chance ()) + return false; for (unsigned int i = 0; i < count; i++) { - do - { - j++; - if (unlikely (j >= end)) - return false; - } while (_hb_ot_layout_skip_mark (c->face, &c->buffer->info[j], c->lookup_props, NULL)); + if (!skippy_iter.next ()) + return false; - if (likely (!match_func (c->buffer->info[j].codepoint, lookahead[i], match_data))) + if (likely (!match_func (c->buffer->info[skippy_iter.idx].codepoint, lookahead[i], match_data))) return false; }