diff --git a/src/OT/Layout/GPOS/SinglePosFormat1.hh b/src/OT/Layout/GPOS/SinglePosFormat1.hh index 5a9dd58a6..01c148f00 100644 --- a/src/OT/Layout/GPOS/SinglePosFormat1.hh +++ b/src/OT/Layout/GPOS/SinglePosFormat1.hh @@ -80,6 +80,17 @@ struct SinglePosFormat1 return_trace (true); } + bool + position_single (hb_ot_apply_context_t *c, + hb_codepoint_t gid, + hb_glyph_position_t &pos) const + { + unsigned int index = (this+coverage).get_coverage (gid); + if (likely (index == NOT_COVERED)) return false; + valueFormat.apply_value (c, this, values, pos); + return true; + } + template diff --git a/src/OT/Layout/GPOS/SinglePosFormat2.hh b/src/OT/Layout/GPOS/SinglePosFormat2.hh index 8a6e8a42a..1f0d72844 100644 --- a/src/OT/Layout/GPOS/SinglePosFormat2.hh +++ b/src/OT/Layout/GPOS/SinglePosFormat2.hh @@ -68,7 +68,7 @@ struct SinglePosFormat2 unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint); if (likely (index == NOT_COVERED)) return_trace (false); - if (likely (index >= valueCount)) return_trace (false); + if (unlikely (index >= valueCount)) return_trace (false); if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) { @@ -92,6 +92,21 @@ struct SinglePosFormat2 return_trace (true); } + bool + position_single (hb_ot_apply_context_t *c, + hb_codepoint_t gid, + hb_glyph_position_t &pos) const + { + unsigned int index = (this+coverage).get_coverage (gid); + if (likely (index == NOT_COVERED)) return false; + if (unlikely (index >= valueCount)) return false; + valueFormat.apply_value (c, this, + &values[index * valueFormat.get_len ()], + pos); + return true; + } + + template diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 44e57987b..2e0b8d5e2 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -1709,6 +1709,63 @@ hb_ot_layout_get_size_params (hb_face_t *face, return false; } + +struct hb_position_single_dispatch_t : + hb_dispatch_context_t +{ + static return_t default_return_value () { return false; } + bool stop_sublookup_iteration (return_t r) const { return r; } + + private: + template auto + _dispatch (const T &obj, hb_priority<1>, Ts&&... ds) HB_AUTO_RETURN + ( obj.position_single (std::forward (ds)...) ) + template auto + _dispatch (const T &obj, hb_priority<0>, Ts&&... ds) HB_AUTO_RETURN + ( default_return_value () ) + public: + template auto + dispatch (const T &obj, Ts&&... ds) HB_AUTO_RETURN + ( _dispatch (obj, hb_prioritize, std::forward (ds)...) ) +}; + +hb_position_t +hb_ot_layout_get_optical_bound (hb_font_t *font, + unsigned lookup_index, + hb_direction_t direction, + hb_codepoint_t glyph) +{ + /* This is ugly... */ + hb_buffer_t buffer; + buffer.props.direction = direction; + OT::hb_ot_apply_context_t c_apply (1, font, &buffer); + const OT::PosLookup &lookup = font->face->table.GPOS->table->get_lookup (lookup_index); + hb_glyph_position_t pos = {0}; + hb_position_single_dispatch_t c; + lookup.dispatch (&c, &c_apply, glyph, pos); + hb_position_t ret = 0; + switch (direction) + { + case HB_DIRECTION_LTR: + ret = pos.x_offset; + break; + case HB_DIRECTION_RTL: + ret = pos.x_advance - pos.x_offset; + break; + case HB_DIRECTION_TTB: + ret = pos.y_offset; + break; + case HB_DIRECTION_BTT: + ret = pos.y_advance - pos.y_offset; + break; + case HB_DIRECTION_INVALID: + default: + break; + } + return ret; +} + + /** * hb_ot_layout_feature_get_name_ids: * @face: #hb_face_t to work upon diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h index 4edddd9e0..288216e25 100644 --- a/src/hb-ot-layout.h +++ b/src/hb-ot-layout.h @@ -403,6 +403,12 @@ hb_ot_layout_get_size_params (hb_face_t *face, unsigned int *range_start, /* OUT. May be NULL */ unsigned int *range_end /* OUT. May be NULL */); +HB_EXTERN hb_position_t +hb_ot_layout_get_optical_bound (hb_font_t *font, + unsigned lookup_index, + hb_direction_t direction, + hb_codepoint_t glyph); + HB_EXTERN hb_bool_t hb_ot_layout_feature_get_name_ids (hb_face_t *face,