summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh
diff options
context:
space:
mode:
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.hh1098
1 files changed, 769 insertions, 329 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 b344d793c7..024312d610 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
@@ -29,7 +29,7 @@
#ifndef HB_OT_LAYOUT_GPOS_TABLE_HH
#define HB_OT_LAYOUT_GPOS_TABLE_HH
-#include "hb-ot-layout-gsubgpos-private.hh"
+#include "hb-ot-layout-gsubgpos.hh"
namespace OT {
@@ -51,11 +51,11 @@ enum attach_type_t {
/* Shared Tables: ValueRecord, Anchor Table, and MarkArray */
-typedef UINT16 Value;
+typedef HBUINT16 Value;
-typedef Value ValueRecord[VAR];
+typedef UnsizedArrayOf<Value> ValueRecord;
-struct ValueFormat : UINT16
+struct ValueFormat : HBUINT16
{
enum Flags {
xPlacement = 0x0001u, /* Includes horizontal adjustment for placement */
@@ -74,89 +74,89 @@ struct ValueFormat : UINT16
/* All fields are options. Only those available advance the value pointer. */
#if 0
- INT16 xPlacement; /* Horizontal adjustment for
+ HBINT16 xPlacement; /* Horizontal adjustment for
* placement--in design units */
- INT16 yPlacement; /* Vertical adjustment for
+ HBINT16 yPlacement; /* Vertical adjustment for
* placement--in design units */
- INT16 xAdvance; /* Horizontal adjustment for
+ HBINT16 xAdvance; /* Horizontal adjustment for
* advance--in design units (only used
* for horizontal writing) */
- INT16 yAdvance; /* Vertical adjustment for advance--in
+ HBINT16 yAdvance; /* Vertical adjustment for advance--in
* design units (only used for vertical
* writing) */
- Offset xPlaDevice; /* Offset to Device table for
+ OffsetTo<Device> xPlaDevice; /* Offset to Device table for
* horizontal placement--measured from
* beginning of PosTable (may be NULL) */
- Offset yPlaDevice; /* Offset to Device table for vertical
+ OffsetTo<Device> yPlaDevice; /* Offset to Device table for vertical
* placement--measured from beginning
* of PosTable (may be NULL) */
- Offset xAdvDevice; /* Offset to Device table for
+ OffsetTo<Device> xAdvDevice; /* Offset to Device table for
* horizontal advance--measured from
* beginning of PosTable (may be NULL) */
- Offset yAdvDevice; /* Offset to Device table for vertical
+ OffsetTo<Device> yAdvDevice; /* Offset to Device table for vertical
* advance--measured from beginning of
* PosTable (may be NULL) */
#endif
- inline unsigned int get_len (void) const
- { return _hb_popcount32 ((unsigned int) *this); }
- inline unsigned int get_size (void) const
- { return get_len () * Value::static_size; }
+ unsigned int get_len () const { return hb_popcount ((unsigned int) *this); }
+ unsigned int get_size () const { return get_len () * Value::static_size; }
- void apply_value (hb_apply_context_t *c,
- const void *base,
- const Value *values,
- hb_glyph_position_t &glyph_pos) const
+ bool apply_value (hb_ot_apply_context_t *c,
+ const void *base,
+ const Value *values,
+ hb_glyph_position_t &glyph_pos) const
{
+ bool ret = false;
unsigned int format = *this;
- if (!format) return;
+ if (!format) return ret;
hb_font_t *font = c->font;
- hb_bool_t horizontal = HB_DIRECTION_IS_HORIZONTAL (c->direction);
+ bool 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 & xPlacement) glyph_pos.x_offset += font->em_scale_x (get_short (values++, &ret));
+ if (format & yPlacement) glyph_pos.y_offset += font->em_scale_y (get_short (values++, &ret));
if (format & xAdvance) {
- if (likely (horizontal)) glyph_pos.x_advance += font->em_scale_x (get_short (values));
+ if (likely (horizontal)) glyph_pos.x_advance += font->em_scale_x (get_short (values, &ret));
values++;
}
/* y_advance values grow downward but font-space grows upward, hence negation */
if (format & yAdvance) {
- if (unlikely (!horizontal)) glyph_pos.y_advance -= font->em_scale_y (get_short (values));
+ if (unlikely (!horizontal)) glyph_pos.y_advance -= font->em_scale_y (get_short (values, &ret));
values++;
}
- if (!has_device ()) return;
+ if (!has_device ()) return ret;
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 (!use_x_device && !use_y_device) return ret;
const VariationStore &store = c->var_store;
/* pixel -> fractional pixel */
if (format & xPlaDevice) {
- if (use_x_device) glyph_pos.x_offset += (base + get_device (values)).get_x_delta (font, store);
+ if (use_x_device) glyph_pos.x_offset += (base + get_device (values, &ret)).get_x_delta (font, store);
values++;
}
if (format & yPlaDevice) {
- if (use_y_device) glyph_pos.y_offset += (base + get_device (values)).get_y_delta (font, store);
+ if (use_y_device) glyph_pos.y_offset += (base + get_device (values, &ret)).get_y_delta (font, store);
values++;
}
if (format & xAdvDevice) {
- if (horizontal && use_x_device) glyph_pos.x_advance += (base + get_device (values)).get_x_delta (font, store);
+ if (horizontal && use_x_device) glyph_pos.x_advance += (base + get_device (values, &ret)).get_x_delta (font, store);
values++;
}
if (format & yAdvDevice) {
/* y_advance values grow downward but font-space grows upward, hence negation */
- if (!horizontal && use_y_device) glyph_pos.y_advance -= (base + get_device (values)).get_y_delta (font, store);
+ if (!horizontal && use_y_device) glyph_pos.y_advance -= (base + get_device (values, &ret)).get_y_delta (font, store);
values++;
}
+ return ret;
}
private:
- inline bool sanitize_value_devices (hb_sanitize_context_t *c, const void *base, const Value *values) const
+ bool sanitize_value_devices (hb_sanitize_context_t *c, const void *base, const Value *values) const
{
unsigned int format = *this;
@@ -173,39 +173,46 @@ struct ValueFormat : UINT16
return true;
}
- static inline OffsetTo<Device>& get_device (Value* value)
- { return *CastP<OffsetTo<Device> > (value); }
- static inline const OffsetTo<Device>& get_device (const Value* value)
- { return *CastP<OffsetTo<Device> > (value); }
+ HB_INTERNAL static OffsetTo<Device>& get_device (Value* value)
+ { return *CastP<OffsetTo<Device>> (value); }
+ HB_INTERNAL static const OffsetTo<Device>& get_device (const Value* value, bool *worked=nullptr)
+ {
+ if (worked) *worked |= bool (*value);
+ return *CastP<OffsetTo<Device>> (value);
+ }
- static inline const INT16& get_short (const Value* value)
- { return *CastP<INT16> (value); }
+ HB_INTERNAL static const HBINT16& get_short (const Value* value, bool *worked=nullptr)
+ {
+ if (worked) *worked |= bool (*value);
+ return *CastP<HBINT16> (value);
+ }
public:
- inline bool has_device (void) const {
+ bool has_device () const
+ {
unsigned int format = *this;
return (format & devices) != 0;
}
- inline bool sanitize_value (hb_sanitize_context_t *c, const void *base, const Value *values) const
+ bool sanitize_value (hb_sanitize_context_t *c, const void *base, const Value *values) const
{
TRACE_SANITIZE (this);
return_trace (c->check_range (values, get_size ()) && (!has_device () || sanitize_value_devices (c, base, values)));
}
- inline bool sanitize_values (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count) const
+ bool sanitize_values (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count) const
{
TRACE_SANITIZE (this);
unsigned int len = get_len ();
- if (!c->check_array (values, get_size (), count)) return_trace (false);
+ if (!c->check_range (values, count, get_size ())) return_trace (false);
if (!has_device ()) return_trace (true);
for (unsigned int i = 0; i < count; i++) {
if (!sanitize_value_devices (c, base, values))
- return_trace (false);
+ return_trace (false);
values += len;
}
@@ -213,7 +220,7 @@ struct ValueFormat : UINT16
}
/* Just sanitize referenced Device tables. Doesn't check the values themselves. */
- inline bool sanitize_values_stride_unsafe (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count, unsigned int stride) const
+ bool sanitize_values_stride_unsafe (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count, unsigned int stride) const
{
TRACE_SANITIZE (this);
@@ -221,7 +228,7 @@ struct ValueFormat : UINT16
for (unsigned int i = 0; i < count; i++) {
if (!sanitize_value_devices (c, base, values))
- return_trace (false);
+ return_trace (false);
values += stride;
}
@@ -229,71 +236,95 @@ struct ValueFormat : UINT16
}
};
+template<typename Iterator>
+static inline void SinglePos_serialize (hb_serialize_context_t *c,
+ Iterator it,
+ ValueFormat valFormat);
+
struct AnchorFormat1
{
- 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
+ void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
+ float *x, float *y) const
{
hb_font_t *font = c->font;
- *x = font->em_scale_x (xCoordinate);
- *y = font->em_scale_y (yCoordinate);
+ *x = font->em_fscale_x (xCoordinate);
+ *y = font->em_fscale_y (yCoordinate);
}
- inline bool sanitize (hb_sanitize_context_t *c) const
+ bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this));
}
+ AnchorFormat1* copy (hb_serialize_context_t *c) const
+ {
+ TRACE_SERIALIZE (this);
+ return_trace (c->embed<AnchorFormat1> (this));
+ }
+
protected:
- UINT16 format; /* Format identifier--format = 1 */
- INT16 xCoordinate; /* Horizontal value--in design units */
- INT16 yCoordinate; /* Vertical value--in design units */
+ HBUINT16 format; /* Format identifier--format = 1 */
+ FWORD xCoordinate; /* Horizontal value--in design units */
+ FWORD yCoordinate; /* Vertical value--in design units */
public:
DEFINE_SIZE_STATIC (6);
};
struct AnchorFormat2
{
- inline void get_anchor (hb_apply_context_t *c, hb_codepoint_t glyph_id,
- hb_position_t *x, hb_position_t *y) const
+ void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id,
+ float *x, float *y) const
{
hb_font_t *font = c->font;
+
+#ifdef HB_NO_HINTING
+ *x = font->em_fscale_x (xCoordinate);
+ *y = font->em_fscale_y (yCoordinate);
+ return;
+#endif
+
unsigned int x_ppem = font->x_ppem;
unsigned int y_ppem = font->y_ppem;
- hb_position_t cx, cy;
- hb_bool_t ret;
+ hb_position_t cx = 0, cy = 0;
+ bool 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);
+ font->get_glyph_contour_point_for_origin (glyph_id, anchorPoint, HB_DIRECTION_LTR, &cx, &cy);
+ *x = ret && x_ppem ? cx : font->em_fscale_x (xCoordinate);
+ *y = ret && y_ppem ? cy : font->em_fscale_y (yCoordinate);
}
- inline bool sanitize (hb_sanitize_context_t *c) const
+ bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this));
}
+ AnchorFormat2* copy (hb_serialize_context_t *c) const
+ {
+ TRACE_SERIALIZE (this);
+ return_trace (c->embed<AnchorFormat2> (this));
+ }
+
protected:
- UINT16 format; /* Format identifier--format = 2 */
- INT16 xCoordinate; /* Horizontal value--in design units */
- INT16 yCoordinate; /* Vertical value--in design units */
- UINT16 anchorPoint; /* Index to glyph contour point */
+ HBUINT16 format; /* Format identifier--format = 2 */
+ FWORD xCoordinate; /* Horizontal value--in design units */
+ FWORD yCoordinate; /* Vertical value--in design units */
+ HBUINT16 anchorPoint; /* Index to glyph contour point */
public:
DEFINE_SIZE_STATIC (8);
};
struct AnchorFormat3
{
- 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
+ void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
+ float *x, float *y) const
{
hb_font_t *font = c->font;
- *x = font->em_scale_x (xCoordinate);
- *y = font->em_scale_y (yCoordinate);
+ *x = font->em_fscale_x (xCoordinate);
+ *y = font->em_fscale_y (yCoordinate);
if (font->x_ppem || font->num_coords)
*x += (this+xDeviceTable).get_x_delta (font, c->var_store);
@@ -301,16 +332,27 @@ struct AnchorFormat3
*y += (this+yDeviceTable).get_y_delta (font, c->var_store);
}
- inline bool sanitize (hb_sanitize_context_t *c) const
+ bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) && xDeviceTable.sanitize (c, this) && yDeviceTable.sanitize (c, this));
}
+ AnchorFormat3* copy (hb_serialize_context_t *c) const
+ {
+ TRACE_SERIALIZE (this);
+ auto *out = c->embed<AnchorFormat3> (this);
+ if (unlikely (!out)) return_trace (nullptr);
+
+ out->xDeviceTable.serialize_copy (c, xDeviceTable, this, out);
+ out->yDeviceTable.serialize_copy (c, yDeviceTable, this, out);
+ return_trace (out);
+ }
+
protected:
- UINT16 format; /* Format identifier--format = 3 */
- INT16 xCoordinate; /* Horizontal value--in design units */
- INT16 yCoordinate; /* Vertical value--in design units */
+ HBUINT16 format; /* Format identifier--format = 3 */
+ FWORD xCoordinate; /* Horizontal value--in design units */
+ FWORD yCoordinate; /* Vertical value--in design units */
OffsetTo<Device>
xDeviceTable; /* Offset to Device table for X
* coordinate-- from beginning of
@@ -325,19 +367,19 @@ struct AnchorFormat3
struct Anchor
{
- inline void get_anchor (hb_apply_context_t *c, hb_codepoint_t glyph_id,
- hb_position_t *x, hb_position_t *y) const
+ void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id,
+ float *x, float *y) const
{
*x = *y = 0;
switch (u.format) {
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;
+ default: return;
}
}
- inline bool sanitize (hb_sanitize_context_t *c) const
+ bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
if (!u.format.sanitize (c)) return_trace (false);
@@ -349,9 +391,20 @@ struct Anchor
}
}
+ Anchor* copy (hb_serialize_context_t *c) const
+ {
+ TRACE_SERIALIZE (this);
+ switch (u.format) {
+ case 1: return_trace (reinterpret_cast<Anchor *> (u.format1.copy (c)));
+ case 2: return_trace (reinterpret_cast<Anchor *> (u.format2.copy (c)));
+ case 3: return_trace (reinterpret_cast<Anchor *> (u.format3.copy (c)));
+ default:return_trace (nullptr);
+ }
+ }
+
protected:
union {
- UINT16 format; /* Format identifier */
+ HBUINT16 format; /* Format identifier */
AnchorFormat1 format1;
AnchorFormat2 format2;
AnchorFormat3 format3;
@@ -363,29 +416,31 @@ struct Anchor
struct AnchorMatrix
{
- inline const Anchor& get_anchor (unsigned int row, unsigned int col, unsigned int cols, bool *found) const {
+ const Anchor& get_anchor (unsigned int row, unsigned int col,
+ unsigned int cols, bool *found) const
+ {
*found = false;
if (unlikely (row >= rows || col >= cols)) return Null(Anchor);
*found = !matrixZ[row * cols + col].is_null ();
return this+matrixZ[row * cols + col];
}
- inline bool sanitize (hb_sanitize_context_t *c, unsigned int cols) const
+ bool sanitize (hb_sanitize_context_t *c, unsigned int cols) const
{
TRACE_SANITIZE (this);
if (!c->check_struct (this)) return_trace (false);
- if (unlikely (_hb_unsigned_int_mul_overflows (rows, cols))) return_trace (false);
+ if (unlikely (hb_unsigned_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);
+ if (!c->check_array (matrixZ.arrayZ, count)) return_trace (false);
for (unsigned int i = 0; i < count; i++)
if (!matrixZ[i].sanitize (c, this)) return_trace (false);
return_trace (true);
}
- UINT16 rows; /* Number of rows */
+ HBUINT16 rows; /* Number of rows */
protected:
- OffsetTo<Anchor>
- matrixZ[VAR]; /* Matrix of offsets to Anchor tables--
+ UnsizedArrayOf<OffsetTo<Anchor>>
+ matrixZ; /* Matrix of offsets to Anchor tables--
* from beginning of AnchorMatrix table */
public:
DEFINE_SIZE_ARRAY (2, matrixZ);
@@ -396,14 +451,14 @@ struct MarkRecord
{
friend struct MarkArray;
- inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+ bool sanitize (hb_sanitize_context_t *c, const void *base) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) && markAnchor.sanitize (c, base));
}
protected:
- UINT16 klass; /* Class defined for this mark */
+ HBUINT16 klass; /* Class defined for this mark */
OffsetTo<Anchor>
markAnchor; /* Offset to Anchor table--from
* beginning of MarkArray table */
@@ -413,10 +468,10 @@ struct MarkRecord
struct MarkArray : ArrayOf<MarkRecord> /* Array of MarkRecords--in Coverage order */
{
- inline bool apply (hb_apply_context_t *c,
- unsigned int mark_index, unsigned int glyph_index,
- const AnchorMatrix &anchors, unsigned int class_count,
- unsigned int glyph_pos) const
+ 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;
@@ -430,15 +485,15 @@ struct MarkArray : ArrayOf<MarkRecord> /* Array of MarkRecords--in Coverage orde
* return false such that the subsequent subtables have a chance at it. */
if (unlikely (!found)) return_trace (false);
- hb_position_t mark_x, mark_y, base_x, base_y;
+ float mark_x, mark_y, base_x, base_y;
buffer->unsafe_to_break (glyph_pos, buffer->idx);
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.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;
@@ -447,7 +502,7 @@ struct MarkArray : ArrayOf<MarkRecord> /* Array of MarkRecords--in Coverage orde
return_trace (true);
}
- inline bool sanitize (hb_sanitize_context_t *c) const
+ bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (ArrayOf<MarkRecord>::sanitize (c, this));
@@ -459,18 +514,15 @@ struct MarkArray : ArrayOf<MarkRecord> /* Array of MarkRecords--in Coverage orde
struct SinglePosFormat1
{
- inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
- {
- TRACE_COLLECT_GLYPHS (this);
- if (unlikely (!(this+coverage).add_coverage (c->input))) return;
- }
+ bool intersects (const hb_set_t *glyphs) const
+ { return (this+coverage).intersects (glyphs); }
- inline const Coverage &get_coverage (void) const
- {
- return this+coverage;
- }
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ { if (unlikely (!(this+coverage).add_coverage (c->input))) return; }
+
+ const Coverage &get_coverage () const { return this+coverage; }
- inline bool apply (hb_apply_context_t *c) const
+ bool apply (hb_ot_apply_context_t *c) const
{
TRACE_APPLY (this);
hb_buffer_t *buffer = c->buffer;
@@ -483,7 +535,45 @@ struct SinglePosFormat1
return_trace (true);
}
- inline bool sanitize (hb_sanitize_context_t *c) const
+ template<typename Iterator,
+ hb_requires (hb_is_iterator (Iterator))>
+ void serialize (hb_serialize_context_t *c,
+ Iterator it,
+ ValueFormat valFormat)
+ {
+ if (unlikely (!c->extend_min (*this))) return;
+ if (unlikely (!c->check_assign (valueFormat, valFormat))) return;
+
+ for (const auto &_ : hb_second (*it))
+ c->copy (_);
+
+ auto glyphs =
+ + it
+ | hb_map_retains_sorting (hb_first)
+ ;
+
+ coverage.serialize (c, this).serialize (c, glyphs);
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ auto it =
+ + hb_iter (this+coverage)
+ | hb_filter (glyphset)
+ | hb_map_retains_sorting (glyph_map)
+ | hb_zip (hb_repeat (values.as_array (valueFormat.get_len ())))
+ ;
+
+ bool ret = bool (it);
+ SinglePos_serialize (c->serializer, it, valueFormat);
+ return_trace (ret);
+ }
+
+ bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) &&
@@ -492,7 +582,7 @@ struct SinglePosFormat1
}
protected:
- UINT16 format; /* Format identifier--format = 1 */
+ HBUINT16 format; /* Format identifier--format = 1 */
OffsetTo<Coverage>
coverage; /* Offset to Coverage table--from
* beginning of subtable */
@@ -507,18 +597,15 @@ struct SinglePosFormat1
struct SinglePosFormat2
{
- inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
- {
- TRACE_COLLECT_GLYPHS (this);
- if (unlikely (!(this+coverage).add_coverage (c->input))) return;
- }
+ bool intersects (const hb_set_t *glyphs) const
+ { return (this+coverage).intersects (glyphs); }
- inline const Coverage &get_coverage (void) const
- {
- return this+coverage;
- }
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ { if (unlikely (!(this+coverage).add_coverage (c->input))) return; }
+
+ const Coverage &get_coverage () const { return this+coverage; }
- inline bool apply (hb_apply_context_t *c) const
+ bool apply (hb_ot_apply_context_t *c) const
{
TRACE_APPLY (this);
hb_buffer_t *buffer = c->buffer;
@@ -535,7 +622,54 @@ struct SinglePosFormat2
return_trace (true);
}
- inline bool sanitize (hb_sanitize_context_t *c) const
+ template<typename Iterator,
+ hb_requires (hb_is_iterator (Iterator))>
+ void serialize (hb_serialize_context_t *c,
+ Iterator it,
+ ValueFormat valFormat)
+ {
+ if (unlikely (!c->extend_min (*this))) return;
+ if (unlikely (!c->check_assign (valueFormat, valFormat))) return;
+ if (unlikely (!c->check_assign (valueCount, it.len ()))) return;
+
+ for (const auto iter : it)
+ for (const auto &_ : iter.second)
+ c->copy (_);
+
+ auto glyphs =
+ + it
+ | hb_map_retains_sorting (hb_first)
+ ;
+
+ coverage.serialize (c, this).serialize (c, glyphs);
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ unsigned sub_length = valueFormat.get_len ();
+ auto values_array = values.as_array (valueCount * sub_length);
+
+ auto it =
+ + hb_zip (this+coverage, hb_range ((unsigned) valueCount))
+ | hb_filter (glyphset, hb_first)
+ | hb_map_retains_sorting ([&] (const hb_pair_t<hb_codepoint_t, unsigned>& _)
+ {
+ return hb_pair (glyph_map[_.first],
+ values_array.sub_array (_.second * sub_length,
+ sub_length));
+ })
+ ;
+
+ bool ret = bool (it);
+ SinglePos_serialize (c->serializer, it, valueFormat);
+ return_trace (ret);
+ }
+
+ bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) &&
@@ -544,13 +678,13 @@ struct SinglePosFormat2
}
protected:
- UINT16 format; /* Format identifier--format = 2 */
+ HBUINT16 format; /* Format identifier--format = 2 */
OffsetTo<Coverage>
coverage; /* Offset to Coverage table--from
* beginning of subtable */
ValueFormat valueFormat; /* Defines the types of data in the
* ValueRecord */
- UINT16 valueCount; /* Number of ValueRecords */
+ HBUINT16 valueCount; /* Number of ValueRecords */
ValueRecord values; /* Array of ValueRecords--positioning
* values applied to glyphs */
public:
@@ -559,33 +693,88 @@ struct SinglePosFormat2
struct SinglePos
{
- template <typename context_t>
- inline typename context_t::return_t dispatch (context_t *c) const
+ template<typename Iterator,
+ hb_requires (hb_is_iterator (Iterator))>
+ unsigned get_format (Iterator glyph_val_iter_pairs)
+ {
+ hb_array_t<const Value> first_val_iter = hb_second (*glyph_val_iter_pairs);
+
+ for (const auto iter : glyph_val_iter_pairs)
+ for (const auto _ : hb_zip (iter.second, first_val_iter))
+ if (_.first != _.second)
+ return 2;
+
+ return 1;
+ }
+
+
+ template<typename Iterator,
+ hb_requires (hb_is_iterator (Iterator))>
+ void serialize (hb_serialize_context_t *c,
+ Iterator glyph_val_iter_pairs,
+ ValueFormat valFormat)
+ {
+ if (unlikely (!c->extend_min (u.format))) return;
+ unsigned format = 2;
+
+ if (glyph_val_iter_pairs) format = get_format (glyph_val_iter_pairs);
+
+ u.format = format;
+ switch (u.format) {
+ case 1: u.format1.serialize (c, glyph_val_iter_pairs, valFormat);
+ return;
+ case 2: u.format2.serialize (c, glyph_val_iter_pairs, valFormat);
+ return;
+ default:return;
+ }
+ }
+
+ template <typename context_t, typename ...Ts>
+ typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
{
TRACE_DISPATCH (this, u.format);
if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
switch (u.format) {
- case 1: return_trace (c->dispatch (u.format1));
- case 2: return_trace (c->dispatch (u.format2));
+ case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
+ case 2: return_trace (c->dispatch (u.format2, hb_forward<Ts> (ds)...));
default:return_trace (c->default_return_value ());
}
}
protected:
union {
- UINT16 format; /* Format identifier */
+ HBUINT16 format; /* Format identifier */
SinglePosFormat1 format1;
SinglePosFormat2 format2;
} u;
};
+template<typename Iterator>
+static inline void
+SinglePos_serialize (hb_serialize_context_t *c,
+ Iterator it,
+ ValueFormat valFormat)
+{ c->start_embed<SinglePos> ()->serialize (c, it, valFormat); }
+
struct PairValueRecord
{
friend struct PairSet;
+ bool serialize (hb_serialize_context_t *c,
+ unsigned length,
+ const hb_map_t &glyph_map) const
+ {
+ TRACE_SERIALIZE (this);
+ auto *out = c->start_embed (*this);
+ if (unlikely (!c->extend_min (out))) return_trace (false);
+
+ out->secondGlyph = glyph_map[secondGlyph];
+ return_trace (c->copy (values, length));
+ }
+
protected:
- GlyphID secondGlyph; /* GlyphID of second glyph in the
+ HBGlyphID secondGlyph; /* GlyphID of second glyph in the
* pair--first glyph is listed in the
* Coverage table */
ValueRecord values; /* Positioning data for the first glyph
@@ -598,19 +787,36 @@ struct PairSet
{
friend struct PairPosFormat1;
- inline void collect_glyphs (hb_collect_glyphs_context_t *c,
+ bool intersects (const hb_set_t *glyphs,
+ const ValueFormat *valueFormats) const
+ {
+ unsigned int len1 = valueFormats[0].get_len ();
+ unsigned int len2 = valueFormats[1].get_len ();
+ unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2);
+
+ const PairValueRecord *record = &firstPairValueRecord;
+ unsigned int count = len;
+ for (unsigned int i = 0; i < count; i++)
+ {
+ if (glyphs->has (record->secondGlyph))
+ return true;
+ record = &StructAtOffset<const PairValueRecord> (record, record_size);
+ }
+ return false;
+ }
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c,
const ValueFormat *valueFormats) const
{
- TRACE_COLLECT_GLYPHS (this);
unsigned int len1 = valueFormats[0].get_len ();
unsigned int len2 = valueFormats[1].get_len ();
- unsigned int record_size = UINT16::static_size * (1 + len1 + len2);
+ unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2);
- const PairValueRecord *record = CastP<PairValueRecord> (arrayZ);
+ const PairValueRecord *record = &firstPairValueRecord;
c->input->add_array (&record->secondGlyph, len, record_size);
}
- inline bool apply (hb_apply_context_t *c,
+ bool apply (hb_ot_apply_context_t *c,
const ValueFormat *valueFormats,
unsigned int pos) const
{
@@ -618,9 +824,8 @@ struct PairSet
hb_buffer_t *buffer = c->buffer;
unsigned int len1 = valueFormats[0].get_len ();
unsigned int len2 = valueFormats[1].get_len ();
- unsigned int record_size = UINT16::static_size * (1 + len1 + len2);
+ unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2);
- const PairValueRecord *record_array = CastP<PairValueRecord> (arrayZ);
unsigned int count = len;
/* Hand-coded bsearch. */
@@ -630,18 +835,19 @@ struct PairSet
int min = 0, max = (int) count - 1;
while (min <= max)
{
- int mid = (min + max) / 2;
- const PairValueRecord *record = &StructAtOffset<PairValueRecord> (record_array, record_size * mid);
+ int mid = ((unsigned int) min + (unsigned int) max) / 2;
+ const PairValueRecord *record = &StructAtOffset<PairValueRecord> (&firstPairValueRecord, record_size * mid);
hb_codepoint_t mid_x = record->secondGlyph;
if (x < mid_x)
- max = mid - 1;
+ max = mid - 1;
else if (x > mid_x)
- min = mid + 1;
+ min = mid + 1;
else
{
- buffer->unsafe_to_break (buffer->idx, pos + 1);
- valueFormats[0].apply_value (c, this, &record->values[0], buffer->cur_pos());
- valueFormats[1].apply_value (c, this, &record->values[len1], buffer->pos[pos]);
+ /* Note the intentional use of "|" instead of short-circuit "||". */
+ if (valueFormats[0].apply_value (c, this, &record->values[0], buffer->cur_pos()) |
+ valueFormats[1].apply_value (c, this, &record->values[len1], buffer->pos[pos]))
+ buffer->unsafe_to_break (buffer->idx, pos + 1);
if (len2)
pos++;
buffer->idx = pos;
@@ -652,64 +858,150 @@ struct PairSet
return_trace (false);
}
- struct sanitize_closure_t {
+ bool subset (hb_subset_context_t *c,
+ const ValueFormat valueFormats[2]) const
+ {
+ TRACE_SUBSET (this);
+ auto snap = c->serializer->snapshot ();
+
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+ out->len = 0;
+
+ const hb_set_t &glyphset = *c->plan->glyphset ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ unsigned len1 = valueFormats[0].get_len ();
+ unsigned len2 = valueFormats[1].get_len ();
+ unsigned record_size = HBUINT16::static_size + Value::static_size * (len1 + len2);
+
+ const PairValueRecord *record = &firstPairValueRecord;
+ unsigned count = len, num = 0;
+ for (unsigned i = 0; i < count; i++)
+ {
+ if (!glyphset.has (record->secondGlyph)) continue;
+ if (record->serialize (c->serializer, len1 + len2, glyph_map)) num++;
+ record = &StructAtOffset<const PairValueRecord> (record, record_size);
+ }
+
+ out->len = num;
+ if (!num) c->serializer->revert (snap);
+ return_trace (num);
+ }
+
+ struct sanitize_closure_t
+ {
const void *base;
const ValueFormat *valueFormats;
unsigned int len1; /* valueFormats[0].get_len() */
unsigned int stride; /* 1 + len1 + len2 */
};
- inline bool sanitize (hb_sanitize_context_t *c, const sanitize_closure_t *closure) const
+ bool sanitize (hb_sanitize_context_t *c, const sanitize_closure_t *closure) const
{
TRACE_SANITIZE (this);
if (!(c->check_struct (this)
- && c->check_array (arrayZ, UINT16::static_size * closure->stride, len))) return_trace (false);
+ && c->check_range (&firstPairValueRecord,
+ len,
+ HBUINT16::static_size,
+ closure->stride))) return_trace (false);
unsigned int count = len;
- const PairValueRecord *record = CastP<PairValueRecord> (arrayZ);
+ const PairValueRecord *record = &firstPairValueRecord;
return_trace (closure->valueFormats[0].sanitize_values_stride_unsafe (c, closure->base, &record->values[0], count, closure->stride) &&
closure->valueFormats[1].sanitize_values_stride_unsafe (c, closure->base, &record->values[closure->len1], count, closure->stride));
}
protected:
- UINT16 len; /* Number of PairValueRecords */
- UINT16 arrayZ[VAR]; /* Array of PairValueRecords--ordered
- * by GlyphID of the second glyph */
+ HBUINT16 len; /* Number of PairValueRecords */
+ PairValueRecord firstPairValueRecord;
+ /* Array of PairValueRecords--ordered
+ * by GlyphID of the second glyph */
public:
- DEFINE_SIZE_ARRAY (2, arrayZ);
+ DEFINE_SIZE_MIN (2);
};
struct PairPosFormat1
{
- inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ bool intersects (const hb_set_t *glyphs) const
+ {
+ return
+ + hb_zip (this+coverage, pairSet)
+ | hb_filter (*glyphs, hb_first)
+ | hb_map (hb_second)
+ | hb_map ([glyphs, this] (const OffsetTo<PairSet> &_)
+ { return (this+_).intersects (glyphs, valueFormat); })
+ | hb_any
+ ;
+ }
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
{
- TRACE_COLLECT_GLYPHS (this);
if (unlikely (!(this+coverage).add_coverage (c->input))) return;
unsigned int count = pairSet.len;
for (unsigned int i = 0; i < count; i++)
(this+pairSet[i]).collect_glyphs (c, valueFormat);
}
- inline const Coverage &get_coverage (void) const
- {
- return this+coverage;
- }
+ const Coverage &get_coverage () const { return this+coverage; }
- inline bool apply (hb_apply_context_t *c) const
+ bool apply (hb_ot_apply_context_t *c) const
{
TRACE_APPLY (this);
hb_buffer_t *buffer = c->buffer;
unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
if (likely (index == NOT_COVERED)) return_trace (false);
- hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
+ hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
skippy_iter.reset (buffer->idx, 1);
if (!skippy_iter.next ()) return_trace (false);
return_trace ((this+pairSet[index]).apply (c, valueFormat, skippy_iter.idx));
}
- inline bool sanitize (hb_sanitize_context_t *c) const
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+
+ const hb_set_t &glyphset = *c->plan->glyphset ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+ out->format = format;
+ out->valueFormat[0] = valueFormat[0];
+ out->valueFormat[1] = valueFormat[1];
+
+ hb_sorted_vector_t<hb_codepoint_t> new_coverage;
+
+ + hb_zip (this+coverage, pairSet)
+ | hb_filter (glyphset, hb_first)
+ | hb_filter ([this, c, out] (const OffsetTo<PairSet>& _)
+ {
+ auto *o = out->pairSet.serialize_append (c->serializer);
+ if (unlikely (!o)) return false;
+ auto snap = c->serializer->snapshot ();
+ bool ret = o->serialize_subset (c, _, this, out, valueFormat);
+ if (!ret)
+ {
+ out->pairSet.pop ();
+ c->serializer->revert (snap);
+ }
+ return ret;
+ },
+ hb_second)
+ | hb_map (hb_first)
+ | hb_map (glyph_map)
+ | hb_sink (new_coverage)
+ ;
+
+ out->coverage.serialize (c->serializer, out)
+ .serialize (c->serializer, new_coverage.iter ());
+
+ return_trace (bool (new_coverage));
+ }
+
+ bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -717,7 +1009,8 @@ struct PairPosFormat1
unsigned int len1 = valueFormat[0].get_len ();
unsigned int len2 = valueFormat[1].get_len ();
- PairSet::sanitize_closure_t closure = {
+ PairSet::sanitize_closure_t closure =
+ {
this,
valueFormat,
len1,
@@ -728,7 +1021,7 @@ struct PairPosFormat1
}
protected:
- UINT16 format; /* Format identifier--format = 1 */
+ HBUINT16 format; /* Format identifier--format = 1 */
OffsetTo<Coverage>
coverage; /* Offset to Coverage table--from
* beginning of subtable */
@@ -747,26 +1040,28 @@ struct PairPosFormat1
struct PairPosFormat2
{
- inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ bool intersects (const hb_set_t *glyphs) const
{
- TRACE_COLLECT_GLYPHS (this);
- if (unlikely (!(this+coverage).add_coverage (c->input))) return;
- if (unlikely (!(this+classDef2).add_coverage (c->input))) return;
+ return (this+coverage).intersects (glyphs) &&
+ (this+classDef2).intersects (glyphs);
}
- inline const Coverage &get_coverage (void) const
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
{
- return this+coverage;
+ if (unlikely (!(this+coverage).add_coverage (c->input))) return;
+ if (unlikely (!(this+classDef2).add_coverage (c->input))) return;
}
- inline bool apply (hb_apply_context_t *c) const
+ const Coverage &get_coverage () const { return this+coverage; }
+
+ bool apply (hb_ot_apply_context_t *c) const
{
TRACE_APPLY (this);
hb_buffer_t *buffer = c->buffer;
unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
if (likely (index == NOT_COVERED)) return_trace (false);
- hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
+ hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
skippy_iter.reset (buffer->idx, 1);
if (!skippy_iter.next ()) return_trace (false);
@@ -778,10 +1073,11 @@ struct PairPosFormat2
unsigned int klass2 = (this+classDef2).get_class (buffer->info[skippy_iter.idx].codepoint);
if (unlikely (klass1 >= class1Count || klass2 >= class2Count)) return_trace (false);
- buffer->unsafe_to_break (buffer->idx, skippy_iter.idx + 1);
const Value *v = &values[record_len * (klass1 * class2Count + klass2)];
- valueFormat1.apply_value (c, this, v, buffer->cur_pos());
- valueFormat2.apply_value (c, this, v + len1, buffer->pos[skippy_iter.idx]);
+ /* Note the intentional use of "|" instead of short-circuit "||". */
+ if (valueFormat1.apply_value (c, this, v, buffer->cur_pos()) |
+ valueFormat2.apply_value (c, this, v + len1, buffer->pos[skippy_iter.idx]))
+ buffer->unsafe_to_break (buffer->idx, skippy_iter.idx + 1);
buffer->idx = skippy_iter.idx;
if (len2)
@@ -790,7 +1086,55 @@ struct PairPosFormat2
return_trace (true);
}
- inline bool sanitize (hb_sanitize_context_t *c) const
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+ out->format = format;
+ out->valueFormat1 = valueFormat1;
+ out->valueFormat2 = valueFormat2;
+
+ hb_map_t klass1_map;
+ out->classDef1.serialize_subset (c, classDef1, this, out, &klass1_map);
+ out->class1Count = klass1_map.get_population ();
+
+ hb_map_t klass2_map;
+ out->classDef2.serialize_subset (c, classDef2, this, out, &klass2_map);
+ out->class2Count = klass2_map.get_population ();
+
+ unsigned record_len = valueFormat1.get_len () + valueFormat2.get_len ();
+
+ + hb_range ((unsigned) class1Count)
+ | hb_filter (klass1_map)
+ | hb_apply ([&] (const unsigned class1_idx)
+ {
+ + hb_range ((unsigned) class2Count)
+ | hb_filter (klass2_map)
+ | hb_apply ([&] (const unsigned class2_idx)
+ {
+ unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * record_len;
+ for (unsigned i = 0; i < record_len; i++)
+ c->serializer->copy (values[idx+i]);
+ })
+ ;
+ })
+ ;
+
+ const hb_set_t &glyphset = *c->plan->glyphset ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ auto it =
+ + hb_iter (this+coverage)
+ | hb_filter (glyphset)
+ | hb_map_retains_sorting (glyph_map)
+ ;
+
+ out->coverage.serialize (c->serializer, out).serialize (c->serializer, it);
+ return_trace (out->class1Count && out->class2Count && bool (it));
+ }
+
+ bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
if (!(c->check_struct (this)
@@ -803,13 +1147,15 @@ struct PairPosFormat2
unsigned int stride = len1 + len2;
unsigned int record_size = valueFormat1.get_size () + valueFormat2.get_size ();
unsigned int count = (unsigned int) class1Count * (unsigned int) class2Count;
- return_trace (c->check_array (values, record_size, count) &&
+ return_trace (c->check_range ((const void *) values,
+ count,
+ record_size) &&
valueFormat1.sanitize_values_stride_unsafe (c, this, &values[0], count, stride) &&
valueFormat2.sanitize_values_stride_unsafe (c, this, &values[len1], count, stride));
}
protected:
- UINT16 format; /* Format identifier--format = 2 */
+ HBUINT16 format; /* Format identifier--format = 2 */
OffsetTo<Coverage>
coverage; /* Offset to Coverage table--from
* beginning of subtable */
@@ -827,9 +1173,9 @@ struct PairPosFormat2
classDef2; /* Offset to ClassDef table--from
* beginning of PairPos subtable--for
* the second glyph of the pair */
- UINT16 class1Count; /* Number of classes in ClassDef1
+ HBUINT16 class1Count; /* Number of classes in ClassDef1
* table--includes Class0 */
- UINT16 class2Count; /* Number of classes in ClassDef2
+ HBUINT16 class2Count; /* Number of classes in ClassDef2
* table--includes Class0 */
ValueRecord values; /* Matrix of value pairs:
* class1-major, class2-minor,
@@ -840,21 +1186,21 @@ struct PairPosFormat2
struct PairPos
{
- template <typename context_t>
- inline typename context_t::return_t dispatch (context_t *c) const
+ template <typename context_t, typename ...Ts>
+ typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
{
TRACE_DISPATCH (this, u.format);
if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
switch (u.format) {
- case 1: return_trace (c->dispatch (u.format1));
- case 2: return_trace (c->dispatch (u.format2));
+ case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
+ case 2: return_trace (c->dispatch (u.format2, hb_forward<Ts> (ds)...));
default:return_trace (c->default_return_value ());
}
}
protected:
union {
- UINT16 format; /* Format identifier */
+ HBUINT16 format; /* Format identifier */
PairPosFormat1 format1;
PairPosFormat2 format2;
} u;
@@ -865,12 +1211,25 @@ struct EntryExitRecord
{
friend struct CursivePosFormat1;
- inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+ bool sanitize (hb_sanitize_context_t *c, const void *base) const
{
TRACE_SANITIZE (this);
return_trace (entryAnchor.sanitize (c, base) && exitAnchor.sanitize (c, base));
}
+ EntryExitRecord* copy (hb_serialize_context_t *c,
+ const void *src_base,
+ const void *dst_base) const
+ {
+ TRACE_SERIALIZE (this);
+ auto *out = c->embed (this);
+ if (unlikely (!out)) return_trace (nullptr);
+
+ out->entryAnchor.serialize_copy (c, entryAnchor, src_base, dst_base);
+ out->exitAnchor.serialize_copy (c, exitAnchor, src_base, dst_base);
+ return_trace (out);
+ }
+
protected:
OffsetTo<Anchor>
entryAnchor; /* Offset to EntryAnchor table--from
@@ -889,39 +1248,36 @@ reverse_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direc
struct CursivePosFormat1
{
- inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
- {
- TRACE_COLLECT_GLYPHS (this);
- if (unlikely (!(this+coverage).add_coverage (c->input))) return;
- }
+ bool intersects (const hb_set_t *glyphs) const
+ { return (this+coverage).intersects (glyphs); }
- inline const Coverage &get_coverage (void) const
- {
- return this+coverage;
- }
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ { if (unlikely (!(this+coverage).add_coverage (c->input))) return; }
+
+ const Coverage &get_coverage () const { return this+coverage; }
- inline bool apply (hb_apply_context_t *c) const
+ bool apply (hb_ot_apply_context_t *c) const
{
TRACE_APPLY (this);
hb_buffer_t *buffer = c->buffer;
const EntryExitRecord &this_record = entryExitRecord[(this+coverage).get_coverage (buffer->cur().codepoint)];
- if (!this_record.exitAnchor) return_trace (false);
+ if (!this_record.entryAnchor) return_trace (false);
- hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
+ hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
skippy_iter.reset (buffer->idx, 1);
- if (!skippy_iter.next ()) return_trace (false);
+ if (!skippy_iter.prev ()) return_trace (false);
- const EntryExitRecord &next_record = entryExitRecord[(this+coverage).get_coverage (buffer->info[skippy_iter.idx].codepoint)];
- if (!next_record.entryAnchor) return_trace (false);
+ const EntryExitRecord &prev_record = entryExitRecord[(this+coverage).get_coverage (buffer->info[skippy_iter.idx].codepoint)];
+ if (!prev_record.exitAnchor) return_trace (false);
- unsigned int i = buffer->idx;
- unsigned int j = skippy_iter.idx;
+ unsigned int i = skippy_iter.idx;
+ unsigned int j = buffer->idx;
buffer->unsafe_to_break (i, j);
- hb_position_t entry_x, entry_y, exit_x, exit_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);
+ float entry_x, entry_y, exit_x, exit_y;
+ (this+prev_record.exitAnchor).get_anchor (c, buffer->info[i].codepoint, &exit_x, &exit_y);
+ (this+this_record.entryAnchor).get_anchor (c, buffer->info[j].codepoint, &entry_x, &entry_y);
hb_glyph_position_t *pos = buffer->pos;
@@ -929,32 +1285,32 @@ struct CursivePosFormat1
/* Main-direction adjustment */
switch (c->direction) {
case HB_DIRECTION_LTR:
- pos[i].x_advance = exit_x + pos[i].x_offset;
+ pos[i].x_advance = roundf (exit_x) + pos[i].x_offset;
- d = entry_x + pos[j].x_offset;
+ d = roundf (entry_x) + pos[j].x_offset;
pos[j].x_advance -= d;
pos[j].x_offset -= d;
break;
case HB_DIRECTION_RTL:
- d = exit_x + pos[i].x_offset;
+ d = roundf (exit_x) + pos[i].x_offset;
pos[i].x_advance -= d;
pos[i].x_offset -= d;
- pos[j].x_advance = entry_x + pos[j].x_offset;
+ pos[j].x_advance = roundf (entry_x) + pos[j].x_offset;
break;
case HB_DIRECTION_TTB:
- pos[i].y_advance = exit_y + pos[i].y_offset;
+ pos[i].y_advance = roundf (exit_y) + pos[i].y_offset;
- d = entry_y + pos[j].y_offset;
+ d = roundf (entry_y) + pos[j].y_offset;
pos[j].y_advance -= d;
pos[j].y_offset -= d;
break;
case HB_DIRECTION_BTT:
- d = exit_y + pos[i].y_offset;
+ d = roundf (exit_y) + pos[i].y_offset;
pos[i].y_advance -= d;
pos[i].y_offset -= d;
- pos[j].y_advance = entry_y;
+ pos[j].y_advance = roundf (entry_y);
break;
case HB_DIRECTION_INVALID:
default:
@@ -968,7 +1324,7 @@ struct CursivePosFormat1
* parent.
*
* Optimize things for the case of RightToLeft, as that's most common in
- * Arabinc. */
+ * Arabic. */
unsigned int child = i;
unsigned int parent = j;
hb_position_t x_offset = entry_x - exit_x;
@@ -997,18 +1353,61 @@ struct CursivePosFormat1
else
pos[child].x_offset = x_offset;
- buffer->idx = j;
+ buffer->idx++;
return_trace (true);
}
- inline bool sanitize (hb_sanitize_context_t *c) const
+ template <typename Iterator,
+ hb_requires (hb_is_iterator (Iterator))>
+ void serialize (hb_serialize_context_t *c,
+ Iterator it,
+ const void *src_base)
+ {
+ if (unlikely (!c->extend_min ((*this)))) return;
+ this->format = 1;
+ this->entryExitRecord.len = it.len ();
+
+ for (const EntryExitRecord& entry_record : + it
+ | hb_map (hb_second))
+ c->copy (entry_record, src_base, this);
+
+ auto glyphs =
+ + it
+ | hb_map_retains_sorting (hb_first)
+ ;
+
+ coverage.serialize (c, this).serialize (c, glyphs);
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!out)) return_trace (false);
+
+ auto it =
+ + hb_zip (this+coverage, entryExitRecord)
+ | hb_filter (glyphset, hb_first)
+ | hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const EntryExitRecord&> p) -> hb_pair_t<hb_codepoint_t, const EntryExitRecord&>
+ { return hb_pair (glyph_map[p.first], p.second);})
+ ;
+
+ bool ret = bool (it);
+ out->serialize (c->serializer, it, this);
+ return_trace (ret);
+ }
+
+ bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (coverage.sanitize (c, this) && entryExitRecord.sanitize (c, this));
}
protected:
- UINT16 format; /* Format identifier--format = 1 */
+ HBUINT16 format; /* Format identifier--format = 1 */
OffsetTo<Coverage>
coverage; /* Offset to Coverage table--from
* beginning of subtable */
@@ -1021,20 +1420,20 @@ struct CursivePosFormat1
struct CursivePos
{
- template <typename context_t>
- inline typename context_t::return_t dispatch (context_t *c) const
+ template <typename context_t, typename ...Ts>
+ typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
{
TRACE_DISPATCH (this, u.format);
if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
switch (u.format) {
- case 1: return_trace (c->dispatch (u.format1));
+ case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
default:return_trace (c->default_return_value ());
}
}
protected:
union {
- UINT16 format; /* Format identifier */
+ HBUINT16 format; /* Format identifier */
CursivePosFormat1 format1;
} u;
};
@@ -1047,19 +1446,19 @@ typedef AnchorMatrix BaseArray; /* base-major--
struct MarkBasePosFormat1
{
- inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ bool intersects (const hb_set_t *glyphs) const
+ { return (this+markCoverage).intersects (glyphs) &&
+ (this+baseCoverage).intersects (glyphs); }
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
{
- TRACE_COLLECT_GLYPHS (this);
if (unlikely (!(this+markCoverage).add_coverage (c->input))) return;
if (unlikely (!(this+baseCoverage).add_coverage (c->input))) return;
}
- inline const Coverage &get_coverage (void) const
- {
- return this+markCoverage;
- }
+ const Coverage &get_coverage () const { return this+markCoverage; }
- inline bool apply (hb_apply_context_t *c) const
+ bool apply (hb_ot_apply_context_t *c) const
{
TRACE_APPLY (this);
hb_buffer_t *buffer = c->buffer;
@@ -1067,17 +1466,28 @@ struct MarkBasePosFormat1
if (likely (mark_index == NOT_COVERED)) return_trace (false);
/* Now we search backwards for a non-mark glyph */
- hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
+ hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
skippy_iter.reset (buffer->idx, 1);
skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks);
do {
if (!skippy_iter.prev ()) return_trace (false);
- /* We only want to attach to the first of a MultipleSubst sequence. Reject others. */
+ /* We only want to attach to the first of a MultipleSubst sequence.
+ * https://github.com/harfbuzz/harfbuzz/issues/740
+ * Reject others...
+ * ...but stop if we find a mark in the MultipleSubst sequence:
+ * https://github.com/harfbuzz/harfbuzz/issues/1020 */
if (!_hb_glyph_info_multiplied (&buffer->info[skippy_iter.idx]) ||
- 0 == _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]))
+ 0 == _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]) ||
+ (skippy_iter.idx == 0 ||
+ _hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx - 1]) ||
+ _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx]) !=
+ _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx - 1]) ||
+ _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]) !=
+ _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx - 1]) + 1
+ ))
break;
skippy_iter.reject ();
- } while (1);
+ } while (true);
/* 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); }
@@ -1088,7 +1498,14 @@ struct MarkBasePosFormat1
return_trace ((this+markArray).apply (c, mark_index, base_index, this+baseArray, classCount, skippy_iter.idx));
}
- inline bool sanitize (hb_sanitize_context_t *c) const
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ // TODO(subset)
+ return_trace (false);
+ }
+
+ bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) &&
@@ -1099,14 +1516,14 @@ struct MarkBasePosFormat1
}
protected:
- UINT16 format; /* Format identifier--format = 1 */
+ HBUINT16 format; /* Format identifier--format = 1 */
OffsetTo<Coverage>
markCoverage; /* Offset to MarkCoverage table--from
* beginning of MarkBasePos subtable */
OffsetTo<Coverage>
baseCoverage; /* Offset to BaseCoverage table--from
* beginning of MarkBasePos subtable */
- UINT16 classCount; /* Number of classes defined for marks */
+ HBUINT16 classCount; /* Number of classes defined for marks */
OffsetTo<MarkArray>
markArray; /* Offset to MarkArray table--from
* beginning of MarkBasePos subtable */
@@ -1119,20 +1536,20 @@ struct MarkBasePosFormat1
struct MarkBasePos
{
- template <typename context_t>
- inline typename context_t::return_t dispatch (context_t *c) const
+ template <typename context_t, typename ...Ts>
+ typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
{
TRACE_DISPATCH (this, u.format);
if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
switch (u.format) {
- case 1: return_trace (c->dispatch (u.format1));
+ case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
default:return_trace (c->default_return_value ());
}
}
protected:
union {
- UINT16 format; /* Format identifier */
+ HBUINT16 format; /* Format identifier */
MarkBasePosFormat1 format1;
} u;
};
@@ -1150,19 +1567,19 @@ typedef OffsetListOf<LigatureAttach> LigatureArray;
struct MarkLigPosFormat1
{
- inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ bool intersects (const hb_set_t *glyphs) const
+ { return (this+markCoverage).intersects (glyphs) &&
+ (this+ligatureCoverage).intersects (glyphs); }
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
{
- TRACE_COLLECT_GLYPHS (this);
if (unlikely (!(this+markCoverage).add_coverage (c->input))) return;
if (unlikely (!(this+ligatureCoverage).add_coverage (c->input))) return;
}
- inline const Coverage &get_coverage (void) const
- {
- return this+markCoverage;
- }
+ const Coverage &get_coverage () const { return this+markCoverage; }
- inline bool apply (hb_apply_context_t *c) const
+ bool apply (hb_ot_apply_context_t *c) const
{
TRACE_APPLY (this);
hb_buffer_t *buffer = c->buffer;
@@ -1170,7 +1587,7 @@ struct MarkLigPosFormat1
if (likely (mark_index == NOT_COVERED)) return_trace (false);
/* Now we search backwards for a non-mark glyph */
- hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
+ hb_ot_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);
@@ -1198,14 +1615,21 @@ struct MarkLigPosFormat1
unsigned int mark_id = _hb_glyph_info_get_lig_id (&buffer->cur());
unsigned int mark_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
if (lig_id && lig_id == mark_id && mark_comp > 0)
- comp_index = MIN (comp_count, _hb_glyph_info_get_lig_comp (&buffer->cur())) - 1;
+ comp_index = hb_min (comp_count, _hb_glyph_info_get_lig_comp (&buffer->cur())) - 1;
else
comp_index = comp_count - 1;
return_trace ((this+markArray).apply (c, mark_index, comp_index, lig_attach, classCount, j));
}
- inline bool sanitize (hb_sanitize_context_t *c) const
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ // TODO(subset)
+ return_trace (false);
+ }
+
+ bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) &&
@@ -1216,7 +1640,7 @@ struct MarkLigPosFormat1
}
protected:
- UINT16 format; /* Format identifier--format = 1 */
+ HBUINT16 format; /* Format identifier--format = 1 */
OffsetTo<Coverage>
markCoverage; /* Offset to Mark Coverage table--from
* beginning of MarkLigPos subtable */
@@ -1224,7 +1648,7 @@ struct MarkLigPosFormat1
ligatureCoverage; /* Offset to Ligature Coverage
* table--from beginning of MarkLigPos
* subtable */
- UINT16 classCount; /* Number of defined mark classes */
+ HBUINT16 classCount; /* Number of defined mark classes */
OffsetTo<MarkArray>
markArray; /* Offset to MarkArray table--from
* beginning of MarkLigPos subtable */
@@ -1237,20 +1661,20 @@ struct MarkLigPosFormat1
struct MarkLigPos
{
- template <typename context_t>
- inline typename context_t::return_t dispatch (context_t *c) const
+ template <typename context_t, typename ...Ts>
+ typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
{
TRACE_DISPATCH (this, u.format);
if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
switch (u.format) {
- case 1: return_trace (c->dispatch (u.format1));
+ case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
default:return_trace (c->default_return_value ());
}
}
protected:
union {
- UINT16 format; /* Format identifier */
+ HBUINT16 format; /* Format identifier */
MarkLigPosFormat1 format1;
} u;
};
@@ -1263,19 +1687,19 @@ typedef AnchorMatrix Mark2Array; /* mark2-major--
struct MarkMarkPosFormat1
{
- inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ bool intersects (const hb_set_t *glyphs) const
+ { return (this+mark1Coverage).intersects (glyphs) &&
+ (this+mark2Coverage).intersects (glyphs); }
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
{
- TRACE_COLLECT_GLYPHS (this);
if (unlikely (!(this+mark1Coverage).add_coverage (c->input))) return;
if (unlikely (!(this+mark2Coverage).add_coverage (c->input))) return;
}
- inline const Coverage &get_coverage (void) const
- {
- return this+mark1Coverage;
- }
+ const Coverage &get_coverage () const { return this+mark1Coverage; }
- inline bool apply (hb_apply_context_t *c) const
+ bool apply (hb_ot_apply_context_t *c) const
{
TRACE_APPLY (this);
hb_buffer_t *buffer = c->buffer;
@@ -1283,7 +1707,7 @@ struct MarkMarkPosFormat1
if (likely (mark1_index == NOT_COVERED)) return_trace (false);
/* now we search backwards for a suitable mark glyph until a non-mark glyph */
- hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
+ hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
skippy_iter.reset (buffer->idx, 1);
skippy_iter.set_lookup_props (c->lookup_props & ~LookupFlag::IgnoreFlags);
if (!skippy_iter.prev ()) return_trace (false);
@@ -1301,7 +1725,7 @@ struct MarkMarkPosFormat1
if (id1 == 0) /* Marks belonging to the same base. */
goto good;
else if (comp1 == comp2) /* Marks belonging to the same ligature component. */
- goto good;
+ goto good;
} else {
/* If ligature ids don't match, it may be the case that one of the marks
* itself is a ligature. In which case match. */
@@ -1319,7 +1743,14 @@ struct MarkMarkPosFormat1
return_trace ((this+mark1Array).apply (c, mark1_index, mark2_index, this+mark2Array, classCount, j));
}
- inline bool sanitize (hb_sanitize_context_t *c) const
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ // TODO(subset)
+ return_trace (false);
+ }
+
+ bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) &&
@@ -1330,7 +1761,7 @@ struct MarkMarkPosFormat1
}
protected:
- UINT16 format; /* Format identifier--format = 1 */
+ HBUINT16 format; /* Format identifier--format = 1 */
OffsetTo<Coverage>
mark1Coverage; /* Offset to Combining Mark1 Coverage
* table--from beginning of MarkMarkPos
@@ -1339,7 +1770,7 @@ struct MarkMarkPosFormat1
mark2Coverage; /* Offset to Combining Mark2 Coverage
* table--from beginning of MarkMarkPos
* subtable */
- UINT16 classCount; /* Number of defined mark classes */
+ HBUINT16 classCount; /* Number of defined mark classes */
OffsetTo<MarkArray>
mark1Array; /* Offset to Mark1Array table--from
* beginning of MarkMarkPos subtable */
@@ -1352,20 +1783,20 @@ struct MarkMarkPosFormat1
struct MarkMarkPos
{
- template <typename context_t>
- inline typename context_t::return_t dispatch (context_t *c) const
+ template <typename context_t, typename ...Ts>
+ typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
{
TRACE_DISPATCH (this, u.format);
if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
switch (u.format) {
- case 1: return_trace (c->dispatch (u.format1));
+ case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
default:return_trace (c->default_return_value ());
}
}
protected:
union {
- UINT16 format; /* Format identifier */
+ HBUINT16 format; /* Format identifier */
MarkMarkPosFormat1 format1;
} u;
};
@@ -1377,7 +1808,7 @@ struct ChainContextPos : ChainContext {};
struct ExtensionPos : Extension<ExtensionPos>
{
- typedef struct PosLookupSubTable LookupSubTable;
+ typedef struct PosLookupSubTable SubTable;
};
@@ -1389,6 +1820,7 @@ struct ExtensionPos : Extension<ExtensionPos>
struct PosLookupSubTable
{
+ friend struct Lookup;
friend struct PosLookup;
enum Type {
@@ -1403,28 +1835,26 @@ struct PosLookupSubTable
Extension = 9
};
- template <typename context_t>
- inline typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type) const
+ template <typename context_t, typename ...Ts>
+ typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type, Ts&&... ds) const
{
TRACE_DISPATCH (this, lookup_type);
- if (unlikely (!c->may_dispatch (this, &u.sub_format))) return_trace (c->no_dispatch_return_value ());
switch (lookup_type) {
- case Single: return_trace (u.single.dispatch (c));
- case Pair: return_trace (u.pair.dispatch (c));
- case Cursive: return_trace (u.cursive.dispatch (c));
- case MarkBase: return_trace (u.markBase.dispatch (c));
- case MarkLig: return_trace (u.markLig.dispatch (c));
- case MarkMark: return_trace (u.markMark.dispatch (c));
- case Context: return_trace (u.context.dispatch (c));
- case ChainContext: return_trace (u.chainContext.dispatch (c));
- case Extension: return_trace (u.extension.dispatch (c));
+ case Single: return_trace (u.single.dispatch (c, hb_forward<Ts> (ds)...));
+ case Pair: return_trace (u.pair.dispatch (c, hb_forward<Ts> (ds)...));
+ case Cursive: return_trace (u.cursive.dispatch (c, hb_forward<Ts> (ds)...));
+ case MarkBase: return_trace (u.markBase.dispatch (c, hb_forward<Ts> (ds)...));
+ case MarkLig: return_trace (u.markLig.dispatch (c, hb_forward<Ts> (ds)...));
+ case MarkMark: return_trace (u.markMark.dispatch (c, hb_forward<Ts> (ds)...));
+ case Context: return_trace (u.context.dispatch (c, hb_forward<Ts> (ds)...));
+ case ChainContext: return_trace (u.chainContext.dispatch (c, hb_forward<Ts> (ds)...));
+ case Extension: return_trace (u.extension.dispatch (c, hb_forward<Ts> (ds)...));
default: return_trace (c->default_return_value ());
}
}
protected:
union {
- UINT16 sub_format;
SinglePos single;
PairPos pair;
CursivePos cursive;
@@ -1436,80 +1866,86 @@ struct PosLookupSubTable
ExtensionPos extension;
} u;
public:
- DEFINE_SIZE_UNION (2, sub_format);
+ DEFINE_SIZE_MIN (0);
};
struct PosLookup : Lookup
{
- inline const PosLookupSubTable& get_subtable (unsigned int i) const
- { return Lookup::get_subtable<PosLookupSubTable> (i); }
+ typedef struct PosLookupSubTable SubTable;
- inline bool is_reverse (void) const
+ const SubTable& get_subtable (unsigned int i) const
+ { return Lookup::get_subtable<SubTable> (i); }
+
+ bool is_reverse () const
{
return false;
}
- inline bool apply (hb_apply_context_t *c) const
+ bool apply (hb_ot_apply_context_t *c) const
{
TRACE_APPLY (this);
return_trace (dispatch (c));
}
- inline hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const
+ bool intersects (const hb_set_t *glyphs) const
{
- TRACE_COLLECT_GLYPHS (this);
- return_trace (dispatch (c));
+ hb_intersects_context_t c (glyphs);
+ return dispatch (&c);
}
+ hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const
+ { return dispatch (c); }
+
template <typename set_t>
- inline void add_coverage (set_t *glyphs) const
+ void add_coverage (set_t *glyphs) const
{
hb_add_coverage_context_t<set_t> c (glyphs);
dispatch (&c);
}
- static bool apply_recurse_func (hb_apply_context_t *c, unsigned int lookup_index);
+ HB_INTERNAL static bool apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index);
template <typename context_t>
- static inline typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index);
+ static typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index);
- template <typename context_t>
- inline typename context_t::return_t dispatch (context_t *c) const
- { return Lookup::dispatch<PosLookupSubTable> (c); }
+ template <typename context_t, typename ...Ts>
+ typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
+ { return Lookup::dispatch<SubTable> (c, hb_forward<Ts> (ds)...); }
- inline bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- if (unlikely (!Lookup::sanitize (c))) return_trace (false);
- return_trace (dispatch (c));
- }
-};
+ bool subset (hb_subset_context_t *c) const
+ { return Lookup::subset<SubTable> (c); }
-typedef OffsetListOf<PosLookup> PosLookupList;
+ bool sanitize (hb_sanitize_context_t *c) const
+ { return Lookup::sanitize<SubTable> (c); }
+};
/*
- * GPOS -- The Glyph Positioning Table
+ * GPOS -- Glyph Positioning
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/gpos
*/
struct GPOS : GSUBGPOS
{
- static const hb_tag_t tableTag = HB_OT_TAG_GPOS;
+ static constexpr hb_tag_t tableTag = HB_OT_TAG_GPOS;
- inline const PosLookup& get_lookup (unsigned int i) const
+ const PosLookup& get_lookup (unsigned int i) const
{ 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_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
- {
- TRACE_SANITIZE (this);
- if (unlikely (!GSUBGPOS::sanitize (c))) return_trace (false);
- const OffsetTo<PosLookupList> &list = CastR<OffsetTo<PosLookupList> > (lookupList);
- return_trace (list.sanitize (c, this));
- }
+ bool subset (hb_subset_context_t *c) const
+ { return GSUBGPOS::subset<PosLookup> (c); }
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ { return GSUBGPOS::sanitize<PosLookup> (c); }
+
+ HB_INTERNAL bool is_blacklisted (hb_blob_t *blob,
+ hb_face_t *face) const;
+
+ typedef GSUBGPOS::accelerator_t<GPOS> accelerator_t;
};
@@ -1539,7 +1975,10 @@ reverse_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direc
pos[j].attach_type() = type;
}
static void
-propagate_attachment_offsets (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction)
+propagate_attachment_offsets (hb_glyph_position_t *pos,
+ unsigned int len,
+ unsigned int i,
+ hb_direction_t direction)
{
/* Adjusts offsets of attached glyphs (both cursive and mark) to accumulate
* offset of glyph they are attached to. */
@@ -1547,11 +1986,14 @@ propagate_attachment_offsets (hb_glyph_position_t *pos, unsigned int i, hb_direc
if (likely (!chain))
return;
+ pos[i].attach_chain() = 0;
+
unsigned int j = (int) i + chain;
- pos[i].attach_chain() = 0;
+ if (unlikely (j >= len))
+ return;
- propagate_attachment_offsets (pos, j, direction);
+ propagate_attachment_offsets (pos, len, j, direction);
assert (!!(type & ATTACH_TYPE_MARK) ^ !!(type & ATTACH_TYPE_CURSIVE));
@@ -1590,7 +2032,7 @@ GPOS::position_start (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer)
}
void
-GPOS::position_finish_advances (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_UNUSED)
{
//_hb_buffer_assert_gsubgpos_vars (buffer);
}
@@ -1607,24 +2049,25 @@ GPOS::position_finish_offsets (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer)
/* Handle attachments */
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);
+ propagate_attachment_offsets (pos, len, i, direction);
}
+struct GPOS_accelerator_t : GPOS::accelerator_t {};
+
+
/* Out-of-class implementation for methods recursing */
+#ifndef HB_NO_OT_LAYOUT
template <typename context_t>
/*static*/ inline typename context_t::return_t PosLookup::dispatch_recurse_func (context_t *c, unsigned int lookup_index)
{
- const GPOS &gpos = *(hb_ot_layout_from_face (c->face)->gpos);
- const PosLookup &l = gpos.get_lookup (lookup_index);
+ const PosLookup &l = c->face->table.GPOS.get_relaxed ()->table->get_lookup (lookup_index);
return l.dispatch (c);
}
-
-/*static*/ inline bool PosLookup::apply_recurse_func (hb_apply_context_t *c, unsigned int lookup_index)
+/*static*/ inline bool PosLookup::apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index)
{
- const GPOS &gpos = *(hb_ot_layout_from_face (c->face)->gpos);
- const PosLookup &l = gpos.get_lookup (lookup_index);
+ const PosLookup &l = c->face->table.GPOS.get_relaxed ()->table->get_lookup (lookup_index);
unsigned int saved_lookup_props = c->lookup_props;
unsigned int saved_lookup_index = c->lookup_index;
c->set_lookup_index (lookup_index);
@@ -1634,10 +2077,7 @@ template <typename context_t>
c->set_lookup_props (saved_lookup_props);
return ret;
}
-
-
-#undef attach_chain
-#undef attach_type
+#endif
} /* namespace OT */