diff options
Diffstat (limited to 'src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh')
-rw-r--r-- | src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh | 253 |
1 files changed, 132 insertions, 121 deletions
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh index 568b5f63a9..952fd60fec 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh @@ -36,8 +36,17 @@ namespace OT { /* buffer **position** var allocations */ -#define attach_lookback() var.u16[0] /* number of glyphs to go back to attach this glyph to its base */ -#define cursive_chain() var.i16[1] /* character to which this connects, may be positive or negative */ +#define attach_chain() var.i16[0] /* glyph to which this attaches to, relative to current glyphs; negative for going back, positive for forward. */ +#define attach_type() var.u8[2] /* attachment type */ +/* Note! if attach_chain() is zero, the value of attach_type() is irrelevant. */ + +enum attach_type_t { + ATTACH_TYPE_NONE = 0X00, + + /* Each attachment should be either a mark or a cursive; can't be both. */ + ATTACH_TYPE_MARK = 0X01, + ATTACH_TYPE_CURSIVE = 0X02, +}; /* Shared Tables: ValueRecord, Anchor Table, and MarkArray */ @@ -94,18 +103,17 @@ struct ValueFormat : USHORT inline unsigned int get_size (void) const { return get_len () * Value::static_size; } - void apply_value (hb_font_t *font, - hb_direction_t direction, + void apply_value (hb_apply_context_t *c, const void *base, const Value *values, hb_glyph_position_t &glyph_pos) const { - unsigned int x_ppem, y_ppem; unsigned int format = *this; - hb_bool_t horizontal = HB_DIRECTION_IS_HORIZONTAL (direction); - if (!format) return; + hb_font_t *font = c->font; + hb_bool_t horizontal = HB_DIRECTION_IS_HORIZONTAL (c->direction); + if (format & xPlacement) glyph_pos.x_offset += font->em_scale_x (get_short (values++)); if (format & yPlacement) glyph_pos.y_offset += font->em_scale_y (get_short (values++)); if (format & xAdvance) { @@ -120,27 +128,29 @@ struct ValueFormat : USHORT if (!has_device ()) return; - x_ppem = font->x_ppem; - y_ppem = font->y_ppem; + bool use_x_device = font->x_ppem || font->num_coords; + bool use_y_device = font->y_ppem || font->num_coords; + + if (!use_x_device && !use_y_device) return; - if (!x_ppem && !y_ppem) return; + const VariationStore &store = c->var_store; /* pixel -> fractional pixel */ if (format & xPlaDevice) { - if (x_ppem) glyph_pos.x_offset += (base + get_device (values)).get_x_delta (font); + if (use_x_device) glyph_pos.x_offset += (base + get_device (values)).get_x_delta (font, store); values++; } if (format & yPlaDevice) { - if (y_ppem) glyph_pos.y_offset += (base + get_device (values)).get_y_delta (font); + if (use_y_device) glyph_pos.y_offset += (base + get_device (values)).get_y_delta (font, store); values++; } if (format & xAdvDevice) { - if (horizontal && x_ppem) glyph_pos.x_advance += (base + get_device (values)).get_x_delta (font); + if (horizontal && use_x_device) glyph_pos.x_advance += (base + get_device (values)).get_x_delta (font, store); values++; } if (format & yAdvDevice) { /* y_advance values grow downward but font-space grows upward, hence negation */ - if (!horizontal && y_ppem) glyph_pos.y_advance -= (base + get_device (values)).get_y_delta (font); + if (!horizontal && use_y_device) glyph_pos.y_advance -= (base + get_device (values)).get_y_delta (font, store); values++; } } @@ -222,11 +232,12 @@ struct ValueFormat : USHORT struct AnchorFormat1 { - inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id HB_UNUSED, + inline void get_anchor (hb_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED, hb_position_t *x, hb_position_t *y) const { - *x = font->em_scale_x (xCoordinate); - *y = font->em_scale_y (yCoordinate); + hb_font_t *font = c->font; + *x = font->em_scale_x (xCoordinate); + *y = font->em_scale_y (yCoordinate); } inline bool sanitize (hb_sanitize_context_t *c) const @@ -245,18 +256,19 @@ struct AnchorFormat1 struct AnchorFormat2 { - inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id, + inline void get_anchor (hb_apply_context_t *c, hb_codepoint_t glyph_id, hb_position_t *x, hb_position_t *y) const { - unsigned int x_ppem = font->x_ppem; - unsigned int y_ppem = font->y_ppem; - hb_position_t cx, cy; - hb_bool_t ret; + hb_font_t *font = c->font; + unsigned int x_ppem = font->x_ppem; + unsigned int y_ppem = font->y_ppem; + hb_position_t cx, cy; + hb_bool_t ret; - ret = (x_ppem || y_ppem) && - font->get_glyph_contour_point_for_origin (glyph_id, anchorPoint, HB_DIRECTION_LTR, &cx, &cy); - *x = ret && x_ppem ? cx : font->em_scale_x (xCoordinate); - *y = ret && y_ppem ? cy : font->em_scale_y (yCoordinate); + ret = (x_ppem || y_ppem) && + font->get_glyph_contour_point_for_origin (glyph_id, anchorPoint, HB_DIRECTION_LTR, &cx, &cy); + *x = ret && x_ppem ? cx : font->em_scale_x (xCoordinate); + *y = ret && y_ppem ? cy : font->em_scale_y (yCoordinate); } inline bool sanitize (hb_sanitize_context_t *c) const @@ -276,16 +288,17 @@ struct AnchorFormat2 struct AnchorFormat3 { - inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id HB_UNUSED, + inline void get_anchor (hb_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED, hb_position_t *x, hb_position_t *y) const { - *x = font->em_scale_x (xCoordinate); - *y = font->em_scale_y (yCoordinate); + hb_font_t *font = c->font; + *x = font->em_scale_x (xCoordinate); + *y = font->em_scale_y (yCoordinate); - if (font->x_ppem) - *x += (this+xDeviceTable).get_x_delta (font); - if (font->y_ppem) - *y += (this+yDeviceTable).get_x_delta (font); + if (font->x_ppem || font->num_coords) + *x += (this+xDeviceTable).get_x_delta (font, c->var_store); + if (font->y_ppem || font->num_coords) + *y += (this+yDeviceTable).get_y_delta (font, c->var_store); } inline bool sanitize (hb_sanitize_context_t *c) const @@ -312,14 +325,14 @@ struct AnchorFormat3 struct Anchor { - inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id, + inline void get_anchor (hb_apply_context_t *c, hb_codepoint_t glyph_id, hb_position_t *x, hb_position_t *y) const { *x = *y = 0; switch (u.format) { - case 1: u.format1.get_anchor (font, glyph_id, x, y); return; - case 2: u.format2.get_anchor (font, glyph_id, x, y); return; - case 3: u.format3.get_anchor (font, glyph_id, x, y); return; + case 1: u.format1.get_anchor (c, glyph_id, x, y); return; + case 2: u.format2.get_anchor (c, glyph_id, x, y); return; + case 3: u.format3.get_anchor (c, glyph_id, x, y); return; default: return; } } @@ -361,7 +374,7 @@ struct AnchorMatrix { TRACE_SANITIZE (this); if (!c->check_struct (this)) return_trace (false); - if (unlikely (rows > 0 && cols >= ((unsigned int) -1) / rows)) return_trace (false); + if (unlikely (_hb_unsigned_int_mul_overflows (rows, cols))) return_trace (false); unsigned int count = rows * cols; if (!c->check_array (matrixZ, matrixZ[0].static_size, count)) return_trace (false); for (unsigned int i = 0; i < count; i++) @@ -419,13 +432,15 @@ struct MarkArray : ArrayOf<MarkRecord> /* Array of MarkRecords--in Coverage orde hb_position_t mark_x, mark_y, base_x, base_y; - mark_anchor.get_anchor (c->font, buffer->cur().codepoint, &mark_x, &mark_y); - glyph_anchor.get_anchor (c->font, buffer->info[glyph_pos].codepoint, &base_x, &base_y); + 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 = base_x - mark_x; o.y_offset = base_y - mark_y; - o.attach_lookback() = buffer->idx - glyph_pos; + 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); @@ -461,8 +476,7 @@ struct SinglePosFormat1 unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint); if (likely (index == NOT_COVERED)) return_trace (false); - valueFormat.apply_value (c->font, c->direction, this, - values, buffer->cur_pos()); + valueFormat.apply_value (c, this, values, buffer->cur_pos()); buffer->idx++; return_trace (true); @@ -512,7 +526,7 @@ struct SinglePosFormat2 if (likely (index >= valueCount)) return_trace (false); - valueFormat.apply_value (c->font, c->direction, this, + valueFormat.apply_value (c, this, &values[index * valueFormat.get_len ()], buffer->cur_pos()); @@ -629,10 +643,8 @@ struct PairSet min = mid + 1; else { - valueFormats[0].apply_value (c->font, c->direction, this, - &record->values[0], buffer->cur_pos()); - valueFormats[1].apply_value (c->font, c->direction, this, - &record->values[len1], buffer->pos[pos]); + valueFormats[0].apply_value (c, this, &record->values[0], buffer->cur_pos()); + valueFormats[1].apply_value (c, this, &record->values[len1], buffer->pos[pos]); if (len2) pos++; buffer->idx = pos; @@ -678,7 +690,7 @@ struct PairPosFormat1 (this+coverage).add_coverage (c->input); unsigned int count = pairSet.len; for (unsigned int i = 0; i < count; i++) - (this+pairSet[i]).collect_glyphs (c, &valueFormat1); + (this+pairSet[i]).collect_glyphs (c, valueFormat); } inline const Coverage &get_coverage (void) const @@ -697,7 +709,7 @@ struct PairPosFormat1 skippy_iter.reset (buffer->idx, 1); if (!skippy_iter.next ()) return_trace (false); - return_trace ((this+pairSet[index]).apply (c, &valueFormat1, skippy_iter.idx)); + return_trace ((this+pairSet[index]).apply (c, valueFormat, skippy_iter.idx)); } inline bool sanitize (hb_sanitize_context_t *c) const @@ -706,11 +718,11 @@ struct PairPosFormat1 if (!c->check_struct (this)) return_trace (false); - unsigned int len1 = valueFormat1.get_len (); - unsigned int len2 = valueFormat2.get_len (); + unsigned int len1 = valueFormat[0].get_len (); + unsigned int len2 = valueFormat[1].get_len (); PairSet::sanitize_closure_t closure = { this, - &valueFormat1, + valueFormat, len1, 1 + len1 + len2 }; @@ -723,10 +735,10 @@ struct PairPosFormat1 OffsetTo<Coverage> coverage; /* Offset to Coverage table--from * beginning of subtable */ - ValueFormat valueFormat1; /* Defines the types of data in + ValueFormat valueFormat[2]; /* [0] Defines the types of data in * ValueRecord1--for the first glyph * in the pair--may be zero (0) */ - ValueFormat valueFormat2; /* Defines the types of data in + /* [1] Defines the types of data in * ValueRecord2--for the second glyph * in the pair--may be zero (0) */ OffsetArrayOf<PairSet> @@ -741,7 +753,7 @@ struct PairPosFormat2 inline void collect_glyphs (hb_collect_glyphs_context_t *c) const { TRACE_COLLECT_GLYPHS (this); - /* (this+coverage).add_coverage (c->input); // Don't need this. */ + (this+coverage).add_coverage (c->input); unsigned int count1 = class1Count; const ClassDef &klass1 = this+classDef1; @@ -779,10 +791,8 @@ struct PairPosFormat2 if (unlikely (klass1 >= class1Count || klass2 >= class2Count)) return_trace (false); const Value *v = &values[record_len * (klass1 * class2Count + klass2)]; - valueFormat1.apply_value (c->font, c->direction, this, - v, buffer->cur_pos()); - valueFormat2.apply_value (c->font, c->direction, this, - v + len1, buffer->pos[skippy_iter.idx]); + valueFormat1.apply_value (c, this, v, buffer->cur_pos()); + valueFormat2.apply_value (c, this, v + len1, buffer->pos[skippy_iter.idx]); buffer->idx = skippy_iter.idx; if (len2) @@ -906,9 +916,6 @@ struct CursivePosFormat1 TRACE_APPLY (this); hb_buffer_t *buffer = c->buffer; - /* We don't handle mark glyphs here. */ - if (unlikely (_hb_glyph_info_is_mark (&buffer->cur()))) return_trace (false); - const EntryExitRecord &this_record = entryExitRecord[(this+coverage).get_coverage (buffer->cur().codepoint)]; if (!this_record.exitAnchor) return_trace (false); @@ -923,8 +930,8 @@ struct CursivePosFormat1 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, buffer->info[i].codepoint, &exit_x, &exit_y); - (this+next_record.entryAnchor).get_anchor (c->font, buffer->info[j].codepoint, &entry_x, &entry_y); + (this+this_record.exitAnchor).get_anchor (c, buffer->info[i].codepoint, &exit_x, &exit_y); + (this+next_record.entryAnchor).get_anchor (c, buffer->info[j].codepoint, &entry_x, &entry_y); hb_glyph_position_t *pos = buffer->pos; @@ -992,7 +999,9 @@ struct CursivePosFormat1 */ reverse_cursive_minor_offset (pos, child, c->direction, parent); - pos[child].cursive_chain() = parent - child; + pos[child].attach_type() = ATTACH_TYPE_CURSIVE; + pos[child].attach_chain() = (int) parent - (int) child; + buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT; if (likely (HB_DIRECTION_IS_HORIZONTAL (c->direction))) pos[child].y_offset = y_offset; else @@ -1067,7 +1076,7 @@ struct MarkBasePosFormat1 unsigned int mark_index = (this+markCoverage).get_coverage (buffer->cur().codepoint); if (likely (mark_index == NOT_COVERED)) return_trace (false); - /* now we search backwards for a non-mark glyph */ + /* Now we search backwards for a non-mark glyph */ hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; skippy_iter.reset (buffer->idx, 1); skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks); @@ -1079,7 +1088,7 @@ struct MarkBasePosFormat1 } while (1); /* Checking that matched glyph is actually a base glyph by GDEF is too strong; disabled */ - if (!_hb_glyph_info_is_base_glyph (&buffer->info[skippy_iter.idx])) { /*return_trace (false);*/ } + //if (!_hb_glyph_info_is_base_glyph (&buffer->info[skippy_iter.idx])) { return_trace (false); } unsigned int base_index = (this+baseCoverage).get_coverage (buffer->info[skippy_iter.idx].codepoint); if (base_index == NOT_COVERED) return_trace (false); @@ -1168,14 +1177,14 @@ struct MarkLigPosFormat1 unsigned int mark_index = (this+markCoverage).get_coverage (buffer->cur().codepoint); if (likely (mark_index == NOT_COVERED)) return_trace (false); - /* now we search backwards for a non-mark glyph */ + /* Now we search backwards for a non-mark glyph */ hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; skippy_iter.reset (buffer->idx, 1); skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks); if (!skippy_iter.prev ()) return_trace (false); /* Checking that matched glyph is actually a ligature by GDEF is too strong; disabled */ - if (!_hb_glyph_info_is_ligature (&buffer->info[skippy_iter.idx])) { /*return_trace (false);*/ } + //if (!_hb_glyph_info_is_ligature (&buffer->info[skippy_iter.idx])) { return_trace (false); } unsigned int j = skippy_iter.idx; unsigned int lig_index = (this+ligatureCoverage).get_coverage (buffer->info[j].codepoint); @@ -1499,7 +1508,8 @@ struct GPOS : GSUBGPOS { return CastR<PosLookup> (GSUBGPOS::get_lookup (i)); } static inline void position_start (hb_font_t *font, hb_buffer_t *buffer); - static inline void position_finish (hb_font_t *font, hb_buffer_t *buffer); + static inline void position_finish_advances (hb_font_t *font, hb_buffer_t *buffer); + static inline void position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer); inline bool sanitize (hb_sanitize_context_t *c) const { @@ -1508,21 +1518,19 @@ struct GPOS : GSUBGPOS const OffsetTo<PosLookupList> &list = CastR<OffsetTo<PosLookupList> > (lookupList); return_trace (list.sanitize (c, this)); } - public: - DEFINE_SIZE_STATIC (10); }; static void reverse_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction, unsigned int new_parent) { - unsigned int j = pos[i].cursive_chain(); - if (likely (!j)) + int chain = pos[i].attach_chain(), type = pos[i].attach_type(); + if (likely (!chain || 0 == (type & ATTACH_TYPE_CURSIVE))) return; - j += i; + pos[i].attach_chain() = 0; - pos[i].cursive_chain() = 0; + unsigned int j = (int) i + chain; /* Stop if we see new parent in the chain. */ if (j == new_parent) @@ -1535,62 +1543,68 @@ reverse_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direc else pos[j].x_offset = -pos[i].x_offset; - pos[j].cursive_chain() = i - j; + pos[j].attach_chain() = -chain; + pos[j].attach_type() = type; } static void -fix_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction) +propagate_attachment_offsets (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction) { - unsigned int j = pos[i].cursive_chain(); - if (likely (!j)) + /* Adjusts offsets of attached glyphs (both cursive and mark) to accumulate + * offset of glyph they are attached to. */ + int chain = pos[i].attach_chain(), type = pos[i].attach_type(); + if (likely (!chain)) return; - j += i; - - pos[i].cursive_chain() = 0; + unsigned int j = (int) i + chain; - fix_cursive_minor_offset (pos, j, direction); + pos[i].attach_chain() = 0; - if (HB_DIRECTION_IS_HORIZONTAL (direction)) - pos[i].y_offset += pos[j].y_offset; - else - pos[i].x_offset += pos[j].x_offset; -} + propagate_attachment_offsets (pos, j, direction); -static void -fix_mark_attachment (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction) -{ - if (likely (!(pos[i].attach_lookback()))) - return; + assert (!!(type & ATTACH_TYPE_MARK) ^ !!(type & ATTACH_TYPE_CURSIVE)); - unsigned int j = i - pos[i].attach_lookback(); - - pos[i].x_offset += pos[j].x_offset; - pos[i].y_offset += pos[j].y_offset; + if (type & ATTACH_TYPE_CURSIVE) + { + if (HB_DIRECTION_IS_HORIZONTAL (direction)) + pos[i].y_offset += pos[j].y_offset; + else + pos[i].x_offset += pos[j].x_offset; + } + else /*if (type & ATTACH_TYPE_MARK)*/ + { + pos[i].x_offset += pos[j].x_offset; + pos[i].y_offset += pos[j].y_offset; - if (HB_DIRECTION_IS_FORWARD (direction)) - for (unsigned int k = j; k < i; k++) { - pos[i].x_offset -= pos[k].x_advance; - pos[i].y_offset -= pos[k].y_advance; - } - else - for (unsigned int k = j + 1; k < i + 1; k++) { - pos[i].x_offset += pos[k].x_advance; - pos[i].y_offset += pos[k].y_advance; - } + assert (j < i); + if (HB_DIRECTION_IS_FORWARD (direction)) + for (unsigned int k = j; k < i; k++) { + pos[i].x_offset -= pos[k].x_advance; + pos[i].y_offset -= pos[k].y_advance; + } + else + for (unsigned int k = j + 1; k < i + 1; k++) { + pos[i].x_offset += pos[k].x_advance; + pos[i].y_offset += pos[k].y_advance; + } + } } void GPOS::position_start (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer) { - buffer->clear_positions (); - unsigned int count = buffer->len; for (unsigned int i = 0; i < count; i++) - buffer->pos[i].attach_lookback() = buffer->pos[i].cursive_chain() = 0; + buffer->pos[i].attach_chain() = buffer->pos[i].attach_type() = 0; } void -GPOS::position_finish (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer) +GPOS::position_finish_advances (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer) +{ + //_hb_buffer_assert_gsubgpos_vars (buffer); +} + +void +GPOS::position_finish_offsets (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer) { _hb_buffer_assert_gsubgpos_vars (buffer); @@ -1598,13 +1612,10 @@ GPOS::position_finish (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer) hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer, &len); hb_direction_t direction = buffer->props.direction; - /* Handle cursive connections */ - for (unsigned int i = 0; i < len; i++) - fix_cursive_minor_offset (pos, i, direction); - /* Handle attachments */ - for (unsigned int i = 0; i < len; i++) - fix_mark_attachment (pos, i, direction); + if (buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT) + for (unsigned int i = 0; i < len; i++) + propagate_attachment_offsets (pos, i, direction); } @@ -1633,8 +1644,8 @@ template <typename context_t> } -#undef attach_lookback -#undef cursive_chain +#undef attach_chain +#undef attach_type } /* namespace OT */ |