summaryrefslogtreecommitdiff
path: root/thirdparty/harfbuzz/src/hb-ot-layout-gpos-table.hh
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/harfbuzz/src/hb-ot-layout-gpos-table.hh')
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-layout-gpos-table.hh622
1 files changed, 393 insertions, 229 deletions
diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-gpos-table.hh b/thirdparty/harfbuzz/src/hb-ot-layout-gpos-table.hh
index f523e35c00..1e305518f5 100644
--- a/thirdparty/harfbuzz/src/hb-ot-layout-gpos-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-layout-gpos-table.hh
@@ -89,20 +89,22 @@ struct ValueFormat : HBUINT16
HBINT16 yAdvance; /* Vertical adjustment for advance--in
* design units (only used for vertical
* writing) */
- OffsetTo<Device> xPlaDevice; /* Offset to Device table for
+ Offset16To<Device> xPlaDevice; /* Offset to Device table for
* horizontal placement--measured from
* beginning of PosTable (may be NULL) */
- OffsetTo<Device> yPlaDevice; /* Offset to Device table for vertical
+ Offset16To<Device> yPlaDevice; /* Offset to Device table for vertical
* placement--measured from beginning
* of PosTable (may be NULL) */
- OffsetTo<Device> xAdvDevice; /* Offset to Device table for
+ Offset16To<Device> xAdvDevice; /* Offset to Device table for
* horizontal advance--measured from
* beginning of PosTable (may be NULL) */
- OffsetTo<Device> yAdvDevice; /* Offset to Device table for vertical
+ Offset16To<Device> yAdvDevice; /* Offset to Device table for vertical
* advance--measured from beginning of
* PosTable (may be NULL) */
#endif
+ IntType& operator = (uint16_t i) { v = i; return *this; }
+
unsigned int get_len () const { return hb_popcount ((unsigned int) *this); }
unsigned int get_size () const { return get_len () * Value::static_size; }
@@ -160,16 +162,40 @@ struct ValueFormat : HBUINT16
return ret;
}
- void serialize_copy (hb_serialize_context_t *c, const void *base,
- const Value *values, const hb_map_t *layout_variation_idx_map) const
+ unsigned int get_effective_format (const Value *values) const
+ {
+ unsigned int format = *this;
+ for (unsigned flag = xPlacement; flag <= yAdvDevice; flag = flag << 1) {
+ if (format & flag) should_drop (*values++, (Flags) flag, &format);
+ }
+
+ return format;
+ }
+
+ template<typename Iterator,
+ hb_requires (hb_is_iterator (Iterator))>
+ unsigned int get_effective_format (Iterator it) const {
+ unsigned int new_format = 0;
+
+ for (const hb_array_t<const Value>& values : it)
+ new_format = new_format | get_effective_format (&values);
+
+ return new_format;
+ }
+
+ void copy_values (hb_serialize_context_t *c,
+ unsigned int new_format,
+ const void *base,
+ const Value *values,
+ const hb_map_t *layout_variation_idx_map) const
{
unsigned int format = *this;
if (!format) return;
- if (format & xPlacement) c->copy (*values++);
- if (format & yPlacement) c->copy (*values++);
- if (format & xAdvance) c->copy (*values++);
- if (format & yAdvance) c->copy (*values++);
+ if (format & xPlacement) copy_value (c, new_format, xPlacement, *values++);
+ if (format & yPlacement) copy_value (c, new_format, yPlacement, *values++);
+ if (format & xAdvance) copy_value (c, new_format, xAdvance, *values++);
+ if (format & yAdvance) copy_value (c, new_format, yAdvance, *values++);
if (format & xPlaDevice) copy_device (c, base, values++, layout_variation_idx_map);
if (format & yPlaDevice) copy_device (c, base, values++, layout_variation_idx_map);
@@ -177,6 +203,16 @@ struct ValueFormat : HBUINT16
if (format & yAdvDevice) copy_device (c, base, values++, layout_variation_idx_map);
}
+ void copy_value (hb_serialize_context_t *c,
+ unsigned int new_format,
+ Flags flag,
+ Value value) const
+ {
+ // Filter by new format.
+ if (!(new_format & flag)) return;
+ c->copy (value);
+ }
+
void collect_variation_indices (hb_collect_variation_indices_context_t *c,
const void *base,
const hb_array_t<const Value>& values) const
@@ -232,14 +268,14 @@ struct ValueFormat : HBUINT16
return true;
}
- static inline OffsetTo<Device>& get_device (Value* value)
+ static inline Offset16To<Device>& get_device (Value* value)
{
- return *static_cast<OffsetTo<Device> *> (value);
+ return *static_cast<Offset16To<Device> *> (value);
}
- static inline const OffsetTo<Device>& get_device (const Value* value, bool *worked=nullptr)
+ static inline const Offset16To<Device>& get_device (const Value* value, bool *worked=nullptr)
{
if (worked) *worked |= bool (*value);
- return *static_cast<const OffsetTo<Device> *> (value);
+ return *static_cast<const Offset16To<Device> *> (value);
}
bool copy_device (hb_serialize_context_t *c, const void *base,
@@ -317,13 +353,21 @@ struct ValueFormat : HBUINT16
return_trace (true);
}
+
+ private:
+
+ void should_drop (Value value, Flags flag, unsigned int* format) const
+ {
+ if (value) return;
+ *format = *format & ~flag;
+ }
+
};
-template<typename Iterator>
+template<typename Iterator, typename SrcLookup>
static void SinglePos_serialize (hb_serialize_context_t *c,
- const void *src,
+ const SrcLookup *src,
Iterator it,
- ValueFormat valFormat,
const hb_map_t *layout_variation_idx_map);
@@ -346,7 +390,10 @@ struct AnchorFormat1
AnchorFormat1* copy (hb_serialize_context_t *c) const
{
TRACE_SERIALIZE (this);
- return_trace (c->embed<AnchorFormat1> (this));
+ AnchorFormat1* out = c->embed<AnchorFormat1> (this);
+ if (!out) return_trace (out);
+ out->format = 1;
+ return_trace (out);
}
protected:
@@ -447,11 +494,11 @@ struct AnchorFormat3
HBUINT16 format; /* Format identifier--format = 3 */
FWORD xCoordinate; /* Horizontal value--in design units */
FWORD yCoordinate; /* Vertical value--in design units */
- OffsetTo<Device>
+ Offset16To<Device>
xDeviceTable; /* Offset to Device table for X
* coordinate-- from beginning of
* Anchor table (may be NULL) */
- OffsetTo<Device>
+ Offset16To<Device>
yDeviceTable; /* Offset to Device table for Y
* coordinate-- from beginning of
* Anchor table (may be NULL) */
@@ -485,14 +532,22 @@ struct Anchor
}
}
- Anchor* copy (hb_serialize_context_t *c, const hb_map_t *layout_variation_idx_map) const
+ bool subset (hb_subset_context_t *c) const
{
- TRACE_SERIALIZE (this);
+ TRACE_SUBSET (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, layout_variation_idx_map)));
- default:return_trace (nullptr);
+ case 1: return_trace (bool (reinterpret_cast<Anchor *> (u.format1.copy (c->serializer))));
+ case 2:
+ if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
+ {
+ // AnchorFormat 2 just containins extra hinting information, so
+ // if hints are being dropped convert to format 1.
+ return_trace (bool (reinterpret_cast<Anchor *> (u.format1.copy (c->serializer))));
+ }
+ return_trace (bool (reinterpret_cast<Anchor *> (u.format2.copy (c->serializer))));
+ case 3: return_trace (bool (reinterpret_cast<Anchor *> (u.format3.copy (c->serializer,
+ c->plan->layout_variation_idx_map))));
+ default:return_trace (false);
}
}
@@ -541,51 +596,29 @@ struct AnchorMatrix
}
template <typename Iterator,
- hb_requires (hb_is_iterator (Iterator))>
- bool serialize (hb_serialize_context_t *c,
- unsigned num_rows,
- AnchorMatrix const *offset_matrix,
- const hb_map_t *layout_variation_idx_map,
- Iterator index_iter)
+ hb_requires (hb_is_iterator (Iterator))>
+ bool subset (hb_subset_context_t *c,
+ unsigned num_rows,
+ Iterator index_iter) const
{
- TRACE_SERIALIZE (this);
+ TRACE_SUBSET (this);
+
+ auto *out = c->serializer->start_embed (this);
+
if (!index_iter) return_trace (false);
- if (unlikely (!c->extend_min ((*this)))) return_trace (false);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
- this->rows = num_rows;
+ out->rows = num_rows;
for (const unsigned i : index_iter)
{
- auto *offset = c->embed (offset_matrix->matrixZ[i]);
+ auto *offset = c->serializer->embed (matrixZ[i]);
if (!offset) return_trace (false);
- offset->serialize_copy (c, offset_matrix->matrixZ[i],
- offset_matrix, c->to_bias (this),
- hb_serialize_context_t::Head,
- layout_variation_idx_map);
+ offset->serialize_subset (c, matrixZ[i], this);
}
return_trace (true);
}
- bool subset (hb_subset_context_t *c,
- unsigned cols,
- const hb_map_t *klass_mapping) const
- {
- TRACE_SUBSET (this);
- auto *out = c->serializer->start_embed (*this);
-
- auto indexes =
- + hb_range (rows * cols)
- | hb_filter ([=] (unsigned index) { return klass_mapping->has (index % cols); })
- ;
-
- out->serialize (c->serializer,
- (unsigned) rows,
- this,
- c->plan->layout_variation_idx_map,
- indexes);
- return_trace (true);
- }
-
bool sanitize (hb_sanitize_context_t *c, unsigned int cols) const
{
TRACE_SANITIZE (this);
@@ -599,7 +632,7 @@ struct AnchorMatrix
}
HBUINT16 rows; /* Number of rows */
- UnsizedArrayOf<OffsetTo<Anchor>>
+ UnsizedArrayOf<Offset16To<Anchor>>
matrixZ; /* Matrix of offsets to Anchor tables--
* from beginning of AnchorMatrix table */
public:
@@ -618,18 +651,16 @@ struct MarkRecord
return_trace (c->check_struct (this) && markAnchor.sanitize (c, base));
}
- MarkRecord *copy (hb_serialize_context_t *c,
- const void *src_base,
- unsigned dst_bias,
- const hb_map_t *klass_mapping,
- const hb_map_t *layout_variation_idx_map) const
+ MarkRecord *subset (hb_subset_context_t *c,
+ const void *src_base,
+ const hb_map_t *klass_mapping) const
{
- TRACE_SERIALIZE (this);
- auto *out = c->embed (this);
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->embed (this);
if (unlikely (!out)) return_trace (nullptr);
out->klass = klass_mapping->get (klass);
- out->markAnchor.serialize_copy (c, markAnchor, src_base, dst_bias, hb_serialize_context_t::Head, layout_variation_idx_map);
+ out->markAnchor.serialize_subset (c, markAnchor, src_base);
return_trace (out);
}
@@ -641,14 +672,14 @@ struct MarkRecord
protected:
HBUINT16 klass; /* Class defined for this mark */
- OffsetTo<Anchor>
+ Offset16To<Anchor>
markAnchor; /* Offset to Anchor table--from
* beginning of MarkArray table */
public:
DEFINE_SIZE_STATIC (4);
};
-struct MarkArray : ArrayOf<MarkRecord> /* Array of MarkRecords--in Coverage order */
+struct MarkArray : Array16Of<MarkRecord> /* Array of MarkRecords--in Coverage order */
{
bool apply (hb_ot_apply_context_t *c,
unsigned int mark_index, unsigned int glyph_index,
@@ -657,7 +688,7 @@ struct MarkArray : ArrayOf<MarkRecord> /* Array of MarkRecords--in Coverage orde
{
TRACE_APPLY (this);
hb_buffer_t *buffer = c->buffer;
- const MarkRecord &record = ArrayOf<MarkRecord>::operator[](mark_index);
+ const MarkRecord &record = Array16Of<MarkRecord>::operator[](mark_index);
unsigned int mark_class = record.klass;
const Anchor& mark_anchor = this + record.markAnchor;
@@ -684,25 +715,42 @@ struct MarkArray : ArrayOf<MarkRecord> /* Array of MarkRecords--in Coverage orde
return_trace (true);
}
- template<typename Iterator,
- hb_requires (hb_is_source_of (Iterator, MarkRecord))>
- bool serialize (hb_serialize_context_t *c,
- const hb_map_t *klass_mapping,
- const hb_map_t *layout_variation_idx_map,
- const void *base,
- Iterator it)
+ template <typename Iterator,
+ hb_requires (hb_is_iterator (Iterator))>
+ bool subset (hb_subset_context_t *c,
+ Iterator coverage,
+ const hb_map_t *klass_mapping) const
{
- TRACE_SERIALIZE (this);
- if (unlikely (!c->extend_min (*this))) return_trace (false);
- if (unlikely (!c->check_assign (len, it.len ()))) return_trace (false);
- c->copy_all (it, base, c->to_bias (this), klass_mapping, layout_variation_idx_map);
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+
+ auto* out = c->serializer->start_embed (this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+
+ auto mark_iter =
+ + hb_zip (coverage, this->iter ())
+ | hb_filter (glyphset, hb_first)
+ | hb_map (hb_second)
+ ;
+
+ unsigned new_length = 0;
+ for (const auto& mark_record : mark_iter) {
+ if (unlikely (!mark_record.subset (c, this, klass_mapping)))
+ return_trace (false);
+ new_length++;
+ }
+
+ if (unlikely (!c->serializer->check_assign (out->len, new_length,
+ HB_SERIALIZE_ERROR_ARRAY_OVERFLOW)))
+ return_trace (false);
+
return_trace (true);
}
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (ArrayOf<MarkRecord>::sanitize (c, this));
+ return_trace (Array16Of<MarkRecord>::sanitize (c, this));
}
};
@@ -733,6 +781,8 @@ struct SinglePosFormat1
const Coverage &get_coverage () const { return this+coverage; }
+ ValueFormat get_value_format () const { return valueFormat; }
+
bool apply (hb_ot_apply_context_t *c) const
{
TRACE_APPLY (this);
@@ -747,29 +797,33 @@ struct SinglePosFormat1
}
template<typename Iterator,
- hb_requires (hb_is_iterator (Iterator))>
+ typename SrcLookup,
+ hb_requires (hb_is_iterator (Iterator))>
void serialize (hb_serialize_context_t *c,
- const void *src,
+ const SrcLookup *src,
Iterator it,
- ValueFormat valFormat,
+ ValueFormat newFormat,
const hb_map_t *layout_variation_idx_map)
{
- auto out = c->extend_min (*this);
- if (unlikely (!out)) return;
- if (unlikely (!c->check_assign (valueFormat, valFormat))) return;
+ if (unlikely (!c->extend_min (this))) return;
+ if (unlikely (!c->check_assign (valueFormat,
+ newFormat,
+ HB_SERIALIZE_ERROR_INT_OVERFLOW))) return;
- + it
- | hb_map (hb_second)
- | hb_apply ([&] (hb_array_t<const Value> _)
- { valFormat.serialize_copy (c, src, &_, layout_variation_idx_map); })
- ;
+ for (const hb_array_t<const Value>& _ : + it | hb_map (hb_second))
+ {
+ src->get_value_format ().copy_values (c, newFormat, src, &_, layout_variation_idx_map);
+ // Only serialize the first entry in the iterator, the rest are assumed to
+ // be the same.
+ break;
+ }
auto glyphs =
+ it
| hb_map_retains_sorting (hb_first)
;
- coverage.serialize (c, this).serialize (c, glyphs);
+ coverage.serialize_serialize (c, glyphs);
}
bool subset (hb_subset_context_t *c) const
@@ -786,7 +840,7 @@ struct SinglePosFormat1
;
bool ret = bool (it);
- SinglePos_serialize (c->serializer, this, it, valueFormat, c->plan->layout_variation_idx_map);
+ SinglePos_serialize (c->serializer, this, it, c->plan->layout_variation_idx_map);
return_trace (ret);
}
@@ -800,7 +854,7 @@ struct SinglePosFormat1
protected:
HBUINT16 format; /* Format identifier--format = 1 */
- OffsetTo<Coverage>
+ Offset16To<Coverage>
coverage; /* Offset to Coverage table--from
* beginning of subtable */
ValueFormat valueFormat; /* Defines the types of data in the
@@ -843,6 +897,8 @@ struct SinglePosFormat2
const Coverage &get_coverage () const { return this+coverage; }
+ ValueFormat get_value_format () const { return valueFormat; }
+
bool apply (hb_ot_apply_context_t *c) const
{
TRACE_APPLY (this);
@@ -861,22 +917,23 @@ struct SinglePosFormat2
}
template<typename Iterator,
- hb_requires (hb_is_iterator (Iterator))>
+ typename SrcLookup,
+ hb_requires (hb_is_iterator (Iterator))>
void serialize (hb_serialize_context_t *c,
- const void *src,
+ const SrcLookup *src,
Iterator it,
- ValueFormat valFormat,
+ ValueFormat newFormat,
const hb_map_t *layout_variation_idx_map)
{
- auto out = c->extend_min (*this);
+ auto out = c->extend_min (this);
if (unlikely (!out)) return;
- if (unlikely (!c->check_assign (valueFormat, valFormat))) return;
- if (unlikely (!c->check_assign (valueCount, it.len ()))) return;
+ if (unlikely (!c->check_assign (valueFormat, newFormat, HB_SERIALIZE_ERROR_INT_OVERFLOW))) return;
+ if (unlikely (!c->check_assign (valueCount, it.len (), HB_SERIALIZE_ERROR_ARRAY_OVERFLOW))) return;
+ it
| hb_map (hb_second)
| hb_apply ([&] (hb_array_t<const Value> _)
- { valFormat.serialize_copy (c, src, &_, layout_variation_idx_map); })
+ { src->get_value_format ().copy_values (c, newFormat, src, &_, layout_variation_idx_map); })
;
auto glyphs =
@@ -884,7 +941,7 @@ struct SinglePosFormat2
| hb_map_retains_sorting (hb_first)
;
- coverage.serialize (c, this).serialize (c, glyphs);
+ coverage.serialize_serialize (c, glyphs);
}
bool subset (hb_subset_context_t *c) const
@@ -908,7 +965,7 @@ struct SinglePosFormat2
;
bool ret = bool (it);
- SinglePos_serialize (c->serializer, this, it, valueFormat, c->plan->layout_variation_idx_map);
+ SinglePos_serialize (c->serializer, this, it, c->plan->layout_variation_idx_map);
return_trace (ret);
}
@@ -922,7 +979,7 @@ struct SinglePosFormat2
protected:
HBUINT16 format; /* Format identifier--format = 2 */
- OffsetTo<Coverage>
+ Offset16To<Coverage>
coverage; /* Offset to Coverage table--from
* beginning of subtable */
ValueFormat valueFormat; /* Defines the types of data in the
@@ -952,24 +1009,37 @@ struct SinglePos
template<typename Iterator,
- hb_requires (hb_is_iterator (Iterator))>
+ typename SrcLookup,
+ hb_requires (hb_is_iterator (Iterator))>
void serialize (hb_serialize_context_t *c,
- const void *src,
+ const SrcLookup* src,
Iterator glyph_val_iter_pairs,
- ValueFormat valFormat,
const hb_map_t *layout_variation_idx_map)
{
if (unlikely (!c->extend_min (u.format))) return;
unsigned format = 2;
+ ValueFormat new_format = src->get_value_format ();
- if (glyph_val_iter_pairs) format = get_format (glyph_val_iter_pairs);
+ if (glyph_val_iter_pairs)
+ {
+ format = get_format (glyph_val_iter_pairs);
+ new_format = src->get_value_format ().get_effective_format (+ glyph_val_iter_pairs | hb_map (hb_second));
+ }
u.format = format;
switch (u.format) {
- case 1: u.format1.serialize (c, src, glyph_val_iter_pairs, valFormat, layout_variation_idx_map);
- return;
- case 2: u.format2.serialize (c, src, glyph_val_iter_pairs, valFormat, layout_variation_idx_map);
- return;
+ case 1: u.format1.serialize (c,
+ src,
+ glyph_val_iter_pairs,
+ new_format,
+ layout_variation_idx_map);
+ return;
+ case 2: u.format2.serialize (c,
+ src,
+ glyph_val_iter_pairs,
+ new_format,
+ layout_variation_idx_map);
+ return;
default:return;
}
}
@@ -994,14 +1064,13 @@ struct SinglePos
} u;
};
-template<typename Iterator>
+template<typename Iterator, typename SrcLookup>
static void
SinglePos_serialize (hb_serialize_context_t *c,
- const void *src,
+ const SrcLookup *src,
Iterator it,
- ValueFormat valFormat,
const hb_map_t *layout_variation_idx_map)
-{ c->start_embed<SinglePos> ()->serialize (c, src, it, valFormat, layout_variation_idx_map); }
+{ c->start_embed<SinglePos> ()->serialize (c, src, it, layout_variation_idx_map); }
struct PairValueRecord
@@ -1011,26 +1080,35 @@ struct PairValueRecord
int cmp (hb_codepoint_t k) const
{ return secondGlyph.cmp (k); }
- struct serialize_closure_t
+ struct context_t
{
const void *base;
const ValueFormat *valueFormats;
+ const ValueFormat *newFormats;
unsigned len1; /* valueFormats[0].get_len() */
const hb_map_t *glyph_map;
const hb_map_t *layout_variation_idx_map;
};
- bool serialize (hb_serialize_context_t *c,
- serialize_closure_t *closure) const
+ bool subset (hb_subset_context_t *c,
+ context_t *closure) const
{
TRACE_SERIALIZE (this);
- auto *out = c->start_embed (*this);
- if (unlikely (!c->extend_min (out))) return_trace (false);
+ auto *s = c->serializer;
+ auto *out = s->start_embed (*this);
+ if (unlikely (!s->extend_min (out))) return_trace (false);
out->secondGlyph = (*closure->glyph_map)[secondGlyph];
- closure->valueFormats[0].serialize_copy (c, closure->base, &values[0], closure->layout_variation_idx_map);
- closure->valueFormats[1].serialize_copy (c, closure->base, &values[closure->len1], closure->layout_variation_idx_map);
+ closure->valueFormats[0].copy_values (s,
+ closure->newFormats[0],
+ closure->base, &values[0],
+ closure->layout_variation_idx_map);
+ closure->valueFormats[1].copy_values (s,
+ closure->newFormats[1],
+ closure->base,
+ &values[closure->len1],
+ closure->layout_variation_idx_map);
return_trace (true);
}
@@ -1050,6 +1128,21 @@ struct PairValueRecord
valueFormats[1].collect_variation_indices (c, base, values_array.sub_array (record1_len, record2_len));
}
+ bool intersects (const hb_set_t& glyphset) const
+ {
+ return glyphset.has(secondGlyph);
+ }
+
+ const Value* get_values_1 () const
+ {
+ return &values[0];
+ }
+
+ const Value* get_values_2 (ValueFormat format1) const
+ {
+ return &values[format1.get_len ()];
+ }
+
protected:
HBGlyphID secondGlyph; /* GlyphID of second glyph in the
* pair--first glyph is listed in the
@@ -1140,7 +1233,8 @@ struct PairSet
}
bool subset (hb_subset_context_t *c,
- const ValueFormat valueFormats[2]) const
+ const ValueFormat valueFormats[2],
+ const ValueFormat newFormats[2]) const
{
TRACE_SUBSET (this);
auto snap = c->serializer->snapshot ();
@@ -1156,10 +1250,11 @@ struct PairSet
unsigned len2 = valueFormats[1].get_len ();
unsigned record_size = HBUINT16::static_size + Value::static_size * (len1 + len2);
- PairValueRecord::serialize_closure_t closure =
+ PairValueRecord::context_t context =
{
this,
valueFormats,
+ newFormats,
len1,
&glyph_map,
c->plan->layout_variation_idx_map
@@ -1170,7 +1265,7 @@ struct PairSet
for (unsigned i = 0; i < count; i++)
{
if (glyphset.has (record->secondGlyph)
- && record->serialize (c->serializer, &closure)) num++;
+ && record->subset (c, &context)) num++;
record = &StructAtOffset<const PairValueRecord> (record, record_size);
}
@@ -1218,7 +1313,7 @@ struct PairPosFormat1
+ hb_zip (this+coverage, pairSet)
| hb_filter (*glyphs, hb_first)
| hb_map (hb_second)
- | hb_map ([glyphs, this] (const OffsetTo<PairSet> &_)
+ | hb_map ([glyphs, this] (const Offset16To<PairSet> &_)
{ return (this+_).intersects (glyphs, valueFormat); })
| hb_any
;
@@ -1278,17 +1373,23 @@ struct PairPosFormat1
out->format = format;
out->valueFormat[0] = valueFormat[0];
out->valueFormat[1] = valueFormat[1];
+ if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
+ {
+ hb_pair_t<unsigned, unsigned> newFormats = compute_effective_value_formats (glyphset);
+ out->valueFormat[0] = newFormats.first;
+ out->valueFormat[1] = newFormats.second;
+ }
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>& _)
+ | hb_filter ([this, c, out] (const Offset16To<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, valueFormat);
+ bool ret = o->serialize_subset (c, _, this, valueFormat, out->valueFormat);
if (!ret)
{
out->pairSet.pop ();
@@ -1302,12 +1403,41 @@ struct PairPosFormat1
| hb_sink (new_coverage)
;
- out->coverage.serialize (c->serializer, out)
- .serialize (c->serializer, new_coverage.iter ());
+ out->coverage.serialize_serialize (c->serializer, new_coverage.iter ());
return_trace (bool (new_coverage));
}
+
+ hb_pair_t<unsigned, unsigned> compute_effective_value_formats (const hb_set_t& glyphset) const
+ {
+ unsigned len1 = valueFormat[0].get_len ();
+ unsigned len2 = valueFormat[1].get_len ();
+ unsigned record_size = HBUINT16::static_size + Value::static_size * (len1 + len2);
+
+ unsigned format1 = 0;
+ unsigned format2 = 0;
+ for (const Offset16To<PairSet>& _ :
+ + hb_zip (this+coverage, pairSet) | hb_filter (glyphset, hb_first) | hb_map (hb_second))
+ {
+ const PairSet& set = (this + _);
+ const PairValueRecord *record = &set.firstPairValueRecord;
+
+ for (unsigned i = 0; i < set.len; i++)
+ {
+ if (record->intersects (glyphset))
+ {
+ format1 = format1 | valueFormat[0].get_effective_format (record->get_values_1 ());
+ format2 = format2 | valueFormat[1].get_effective_format (record->get_values_2 (valueFormat[0]));
+ }
+ record = &StructAtOffset<const PairValueRecord> (record, record_size);
+ }
+ }
+
+ return hb_pair (format1, format2);
+ }
+
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -1328,7 +1458,7 @@ struct PairPosFormat1
protected:
HBUINT16 format; /* Format identifier--format = 1 */
- OffsetTo<Coverage>
+ Offset16To<Coverage>
coverage; /* Offset to Coverage table--from
* beginning of subtable */
ValueFormat valueFormat[2]; /* [0] Defines the types of data in
@@ -1337,7 +1467,7 @@ struct PairPosFormat1
/* [1] Defines the types of data in
* ValueRecord2--for the second glyph
* in the pair--may be zero (0) */
- OffsetArrayOf<PairSet>
+ Array16OfOffset16To<PairSet>
pairSet; /* Array of PairSet tables
* ordered by Coverage Index */
public:
@@ -1355,18 +1485,35 @@ struct PairPosFormat2
void closure_lookups (hb_closure_lookups_context_t *c) const {}
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
{
+ if (!intersects (c->glyph_set)) return;
if ((!valueFormat1.has_device ()) && (!valueFormat2.has_device ())) return;
+ hb_set_t klass1_glyphs, klass2_glyphs;
+ if (!(this+classDef1).collect_coverage (&klass1_glyphs)) return;
+ if (!(this+classDef2).collect_coverage (&klass2_glyphs)) return;
+
hb_set_t class1_set, class2_set;
- for (const unsigned cp : c->glyph_set->iter ())
+ for (const unsigned cp : + c->glyph_set->iter () | hb_filter (this + coverage))
+ {
+ if (!klass1_glyphs.has (cp)) class1_set.add (0);
+ else
+ {
+ unsigned klass1 = (this+classDef1).get (cp);
+ class1_set.add (klass1);
+ }
+ }
+
+ class2_set.add (0);
+ for (const unsigned cp : + c->glyph_set->iter () | hb_filter (klass2_glyphs))
{
- unsigned klass1 = (this+classDef1).get (cp);
unsigned klass2 = (this+classDef2).get (cp);
- class1_set.add (klass1);
class2_set.add (klass2);
}
- if (class1_set.is_empty () || class2_set.is_empty ()) return;
+ if (class1_set.is_empty ()
+ || class2_set.is_empty ()
+ || (class2_set.get_population() == 1 && class2_set.has(0)))
+ return;
unsigned len1 = valueFormat1.get_len ();
unsigned len2 = valueFormat2.get_len ();
@@ -1431,35 +1578,34 @@ struct PairPosFormat2
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, &klass1_map);
+ out->classDef1.serialize_subset (c, classDef1, this, &klass1_map, true, true, &(this + coverage));
out->class1Count = klass1_map.get_population ();
hb_map_t klass2_map;
- out->classDef2.serialize_subset (c, classDef2, this, &klass2_map);
+ out->classDef2.serialize_subset (c, classDef2, this, &klass2_map, true, false);
out->class2Count = klass2_map.get_population ();
unsigned len1 = valueFormat1.get_len ();
unsigned len2 = 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) * (len1 + len2);
- valueFormat1.serialize_copy (c->serializer, this, &values[idx], c->plan->layout_variation_idx_map);
- valueFormat2.serialize_copy (c->serializer, this, &values[idx + len1], c->plan->layout_variation_idx_map);
- })
- ;
- })
- ;
+ hb_pair_t<unsigned, unsigned> newFormats = hb_pair (valueFormat1, valueFormat2);
+ if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
+ newFormats = compute_effective_value_formats (klass1_map, klass2_map);
+
+ out->valueFormat1 = newFormats.first;
+ out->valueFormat2 = newFormats.second;
+
+ for (unsigned class1_idx : + hb_range ((unsigned) class1Count) | hb_filter (klass1_map))
+ {
+ for (unsigned class2_idx : + hb_range ((unsigned) class2Count) | hb_filter (klass2_map))
+ {
+ unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * (len1 + len2);
+ valueFormat1.copy_values (c->serializer, newFormats.first, this, &values[idx], c->plan->layout_variation_idx_map);
+ valueFormat2.copy_values (c->serializer, newFormats.second, this, &values[idx + len1], c->plan->layout_variation_idx_map);
+ }
+ }
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
const hb_map_t &glyph_map = *c->plan->glyph_map;
@@ -1470,10 +1616,34 @@ struct PairPosFormat2
| hb_map_retains_sorting (glyph_map)
;
- out->coverage.serialize (c->serializer, out).serialize (c->serializer, it);
+ out->coverage.serialize_serialize (c->serializer, it);
return_trace (out->class1Count && out->class2Count && bool (it));
}
+
+ hb_pair_t<unsigned, unsigned> compute_effective_value_formats (const hb_map_t& klass1_map,
+ const hb_map_t& klass2_map) const
+ {
+ unsigned len1 = valueFormat1.get_len ();
+ unsigned len2 = valueFormat2.get_len ();
+
+ unsigned format1 = 0;
+ unsigned format2 = 0;
+
+ for (unsigned class1_idx : + hb_range ((unsigned) class1Count) | hb_filter (klass1_map))
+ {
+ for (unsigned class2_idx : + hb_range ((unsigned) class2Count) | hb_filter (klass2_map))
+ {
+ unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * (len1 + len2);
+ format1 = format1 | valueFormat1.get_effective_format (&values[idx]);
+ format2 = format2 | valueFormat2.get_effective_format (&values[idx + len1]);
+ }
+ }
+
+ return hb_pair (format1, format2);
+ }
+
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -1496,7 +1666,7 @@ struct PairPosFormat2
protected:
HBUINT16 format; /* Format identifier--format = 2 */
- OffsetTo<Coverage>
+ Offset16To<Coverage>
coverage; /* Offset to Coverage table--from
* beginning of subtable */
ValueFormat valueFormat1; /* ValueRecord definition--for the
@@ -1505,11 +1675,11 @@ struct PairPosFormat2
ValueFormat valueFormat2; /* ValueRecord definition--for the
* second glyph of the pair--may be
* zero (0) */
- OffsetTo<ClassDef>
+ Offset16To<ClassDef>
classDef1; /* Offset to ClassDef table--from
* beginning of PairPos subtable--for
* the first glyph of the pair */
- OffsetTo<ClassDef>
+ Offset16To<ClassDef>
classDef2; /* Offset to ClassDef table--from
* beginning of PairPos subtable--for
* the second glyph of the pair */
@@ -1564,26 +1734,24 @@ struct EntryExitRecord
(src_base+exitAnchor).collect_variation_indices (c);
}
- EntryExitRecord* copy (hb_serialize_context_t *c,
- const void *src_base,
- const void *dst_base,
- const hb_map_t *layout_variation_idx_map) const
+ EntryExitRecord* subset (hb_subset_context_t *c,
+ const void *src_base) const
{
TRACE_SERIALIZE (this);
- auto *out = c->embed (this);
+ auto *out = c->serializer->embed (this);
if (unlikely (!out)) return_trace (nullptr);
- out->entryAnchor.serialize_copy (c, entryAnchor, src_base, c->to_bias (dst_base), hb_serialize_context_t::Head, layout_variation_idx_map);
- out->exitAnchor.serialize_copy (c, exitAnchor, src_base, c->to_bias (dst_base), hb_serialize_context_t::Head, layout_variation_idx_map);
+ out->entryAnchor.serialize_subset (c, entryAnchor, src_base);
+ out->exitAnchor.serialize_subset (c, exitAnchor, src_base);
return_trace (out);
}
protected:
- OffsetTo<Anchor>
+ Offset16To<Anchor>
entryAnchor; /* Offset to EntryAnchor table--from
* beginning of CursivePos
* subtable--may be NULL */
- OffsetTo<Anchor>
+ Offset16To<Anchor>
exitAnchor; /* Offset to ExitAnchor table--from
* beginning of CursivePos
* subtable--may be NULL */
@@ -1712,7 +1880,7 @@ struct CursivePosFormat1
else
pos[child].x_offset = x_offset;
- /* If parent was attached to child, break them free.
+ /* If parent was attached to child, separate them.
* https://github.com/harfbuzz/harfbuzz/issues/2469
*/
if (unlikely (pos[parent].attach_chain() == -pos[child].attach_chain()))
@@ -1724,25 +1892,24 @@ struct CursivePosFormat1
template <typename Iterator,
hb_requires (hb_is_iterator (Iterator))>
- void serialize (hb_serialize_context_t *c,
+ void serialize (hb_subset_context_t *c,
Iterator it,
- const void *src_base,
- const hb_map_t *layout_variation_idx_map)
+ const void *src_base)
{
- if (unlikely (!c->extend_min ((*this)))) return;
+ if (unlikely (!c->serializer->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, layout_variation_idx_map);
+ entry_record.subset (c, src_base);
auto glyphs =
+ it
| hb_map_retains_sorting (hb_first)
;
- coverage.serialize (c, this).serialize (c, glyphs);
+ coverage.serialize_serialize (c->serializer, glyphs);
}
bool subset (hb_subset_context_t *c) const
@@ -1762,7 +1929,7 @@ struct CursivePosFormat1
;
bool ret = bool (it);
- out->serialize (c->serializer, it, this, c->plan->layout_variation_idx_map);
+ out->serialize (c, it, this);
return_trace (ret);
}
@@ -1774,10 +1941,10 @@ struct CursivePosFormat1
protected:
HBUINT16 format; /* Format identifier--format = 1 */
- OffsetTo<Coverage>
+ Offset16To<Coverage>
coverage; /* Offset to Coverage table--from
* beginning of subtable */
- ArrayOf<EntryExitRecord>
+ Array16Of<EntryExitRecord>
entryExitRecord; /* Array of EntryExit records--in
* Coverage Index order */
public:
@@ -1949,13 +2116,12 @@ struct MarkBasePosFormat1
| hb_sink (new_coverage)
;
- if (!out->markCoverage.serialize (c->serializer, out)
- .serialize (c->serializer, new_coverage.iter ()))
+ if (!out->markCoverage.serialize_serialize (c->serializer, new_coverage.iter ()))
return_trace (false);
- out->markArray.serialize (c->serializer, out)
- .serialize (c->serializer, &klass_mapping, c->plan->layout_variation_idx_map, &(this+markArray), + mark_iter
- | hb_map (hb_second));
+ out->markArray.serialize_subset (c, markArray, this,
+ (this+markCoverage).iter (),
+ &klass_mapping);
unsigned basecount = (this+baseArray).rows;
auto base_iter =
@@ -1970,8 +2136,7 @@ struct MarkBasePosFormat1
| hb_sink (new_coverage)
;
- if (!out->baseCoverage.serialize (c->serializer, out)
- .serialize (c->serializer, new_coverage.iter ()))
+ if (!out->baseCoverage.serialize_serialize (c->serializer, new_coverage.iter ()))
return_trace (false);
hb_sorted_vector_t<unsigned> base_indexes;
@@ -1984,8 +2149,10 @@ struct MarkBasePosFormat1
| hb_sink (base_indexes)
;
}
- out->baseArray.serialize (c->serializer, out)
- .serialize (c->serializer, base_iter.len (), &(this+baseArray), c->plan->layout_variation_idx_map, base_indexes.iter ());
+
+ out->baseArray.serialize_subset (c, baseArray, this,
+ base_iter.len (),
+ base_indexes.iter ());
return_trace (true);
}
@@ -2002,17 +2169,17 @@ struct MarkBasePosFormat1
protected:
HBUINT16 format; /* Format identifier--format = 1 */
- OffsetTo<Coverage>
+ Offset16To<Coverage>
markCoverage; /* Offset to MarkCoverage table--from
* beginning of MarkBasePos subtable */
- OffsetTo<Coverage>
+ Offset16To<Coverage>
baseCoverage; /* Offset to BaseCoverage table--from
* beginning of MarkBasePos subtable */
HBUINT16 classCount; /* Number of classes defined for marks */
- OffsetTo<MarkArray>
+ Offset16To<MarkArray>
markArray; /* Offset to MarkArray table--from
* beginning of MarkBasePos subtable */
- OffsetTo<BaseArray>
+ Offset16To<BaseArray>
baseArray; /* Offset to BaseArray table--from
* beginning of MarkBasePos subtable */
public:
@@ -2046,12 +2213,12 @@ typedef AnchorMatrix LigatureAttach; /* component-major--
* ordered by class--zero-based. */
/* Array of LigatureAttach tables ordered by LigatureCoverage Index */
-struct LigatureArray : OffsetListOf<LigatureAttach>
+struct LigatureArray : List16OfOffset16To<LigatureAttach>
{
template <typename Iterator,
hb_requires (hb_is_iterator (Iterator))>
bool subset (hb_subset_context_t *c,
- Iterator coverage,
+ Iterator coverage,
unsigned class_count,
const hb_map_t *klass_mapping) const
{
@@ -2067,11 +2234,16 @@ struct LigatureArray : OffsetListOf<LigatureAttach>
auto *matrix = out->serialize_append (c->serializer);
if (unlikely (!matrix)) return_trace (false);
+ const LigatureAttach& src = (this + _.second);
+ auto indexes =
+ + hb_range (src.rows * class_count)
+ | hb_filter ([=] (unsigned index) { return klass_mapping->has (index % class_count); })
+ ;
matrix->serialize_subset (c,
_.second,
this,
- class_count,
- klass_mapping);
+ src.rows,
+ indexes);
}
return_trace (this->len);
}
@@ -2201,17 +2373,12 @@ struct MarkLigPosFormat1
| hb_map_retains_sorting (glyph_map)
;
- if (!out->markCoverage.serialize (c->serializer, out)
- .serialize (c->serializer, new_mark_coverage))
+ if (!out->markCoverage.serialize_serialize (c->serializer, new_mark_coverage))
return_trace (false);
- out->markArray.serialize (c->serializer, out)
- .serialize (c->serializer,
- &klass_mapping,
- c->plan->layout_variation_idx_map,
- &(this+markArray),
- + mark_iter
- | hb_map (hb_second));
+ out->markArray.serialize_subset (c, markArray, this,
+ (this+markCoverage).iter (),
+ &klass_mapping);
auto new_ligature_coverage =
+ hb_iter (this + ligatureCoverage)
@@ -2219,8 +2386,7 @@ struct MarkLigPosFormat1
| hb_map_retains_sorting (glyph_map)
;
- if (!out->ligatureCoverage.serialize (c->serializer, out)
- .serialize (c->serializer, new_ligature_coverage))
+ if (!out->ligatureCoverage.serialize_serialize (c->serializer, new_ligature_coverage))
return_trace (false);
out->ligatureArray.serialize_subset (c, ligatureArray, this,
@@ -2241,18 +2407,18 @@ struct MarkLigPosFormat1
protected:
HBUINT16 format; /* Format identifier--format = 1 */
- OffsetTo<Coverage>
+ Offset16To<Coverage>
markCoverage; /* Offset to Mark Coverage table--from
* beginning of MarkLigPos subtable */
- OffsetTo<Coverage>
+ Offset16To<Coverage>
ligatureCoverage; /* Offset to Ligature Coverage
* table--from beginning of MarkLigPos
* subtable */
HBUINT16 classCount; /* Number of defined mark classes */
- OffsetTo<MarkArray>
+ Offset16To<MarkArray>
markArray; /* Offset to MarkArray table--from
* beginning of MarkLigPos subtable */
- OffsetTo<LigatureArray>
+ Offset16To<LigatureArray>
ligatureArray; /* Offset to LigatureArray table--from
* beginning of MarkLigPos subtable */
public:
@@ -2409,13 +2575,12 @@ struct MarkMarkPosFormat1
| hb_sink (new_coverage)
;
- if (!out->mark1Coverage.serialize (c->serializer, out)
- .serialize (c->serializer, new_coverage.iter ()))
+ if (!out->mark1Coverage.serialize_serialize (c->serializer, new_coverage.iter ()))
return_trace (false);
- out->mark1Array.serialize (c->serializer, out)
- .serialize (c->serializer, &klass_mapping, c->plan->layout_variation_idx_map, &(this+mark1Array), + mark1_iter
- | hb_map (hb_second));
+ out->mark1Array.serialize_subset (c, mark1Array, this,
+ (this+mark1Coverage).iter (),
+ &klass_mapping);
unsigned mark2count = (this+mark2Array).rows;
auto mark2_iter =
@@ -2430,8 +2595,7 @@ struct MarkMarkPosFormat1
| hb_sink (new_coverage)
;
- if (!out->mark2Coverage.serialize (c->serializer, out)
- .serialize (c->serializer, new_coverage.iter ()))
+ if (!out->mark2Coverage.serialize_serialize (c->serializer, new_coverage.iter ()))
return_trace (false);
hb_sorted_vector_t<unsigned> mark2_indexes;
@@ -2444,8 +2608,8 @@ struct MarkMarkPosFormat1
| hb_sink (mark2_indexes)
;
}
- out->mark2Array.serialize (c->serializer, out)
- .serialize (c->serializer, mark2_iter.len (), &(this+mark2Array), c->plan->layout_variation_idx_map, mark2_indexes.iter ());
+
+ out->mark2Array.serialize_subset (c, mark2Array, this, mark2_iter.len (), mark2_indexes.iter ());
return_trace (true);
}
@@ -2462,19 +2626,19 @@ struct MarkMarkPosFormat1
protected:
HBUINT16 format; /* Format identifier--format = 1 */
- OffsetTo<Coverage>
+ Offset16To<Coverage>
mark1Coverage; /* Offset to Combining Mark1 Coverage
* table--from beginning of MarkMarkPos
* subtable */
- OffsetTo<Coverage>
+ Offset16To<Coverage>
mark2Coverage; /* Offset to Combining Mark2 Coverage
* table--from beginning of MarkMarkPos
* subtable */
HBUINT16 classCount; /* Number of defined mark classes */
- OffsetTo<MarkArray>
+ Offset16To<MarkArray>
mark1Array; /* Offset to Mark1Array table--from
* beginning of MarkMarkPos subtable */
- OffsetTo<Mark2Array>
+ Offset16To<Mark2Array>
mark2Array; /* Offset to Mark2Array table--from
* beginning of MarkMarkPos subtable */
public:
@@ -2663,7 +2827,7 @@ struct GPOS : GSUBGPOS
bool subset (hb_subset_context_t *c) const
{
- hb_subset_layout_context_t l (c, tableTag, c->plan->gpos_lookups, c->plan->gpos_features);
+ hb_subset_layout_context_t l (c, tableTag, c->plan->gpos_lookups, c->plan->gpos_langsys, c->plan->gpos_features);
return GSUBGPOS::subset<PosLookup> (&l);
}