[subset] GDEF Variation Store: step 1
closure device variation indexes, create old->new variation idx mapping and store them in subset-plan
This commit is contained in:
parent
8ba0077ea3
commit
8200e48ffc
@ -150,6 +150,28 @@ struct hb_subset_layout_context_t :
|
||||
unsigned lookup_index_count;
|
||||
};
|
||||
|
||||
struct hb_collect_variation_indices_context_t :
|
||||
hb_dispatch_context_t<hb_collect_variation_indices_context_t, hb_empty_t, 0>
|
||||
{
|
||||
const char *get_name () { return "CLOSURE_LAYOUT_VARIATION_IDXES"; }
|
||||
template <typename T>
|
||||
return_t dispatch (const T &obj) { obj.collect_variation_indices (this); return hb_empty_t (); }
|
||||
static return_t default_return_value () { return hb_empty_t (); }
|
||||
|
||||
hb_set_t *layout_variation_indices;
|
||||
const hb_set_t *glyph_set;
|
||||
const hb_map_t *gpos_lookups;
|
||||
unsigned int debug_depth;
|
||||
|
||||
hb_collect_variation_indices_context_t (hb_set_t *layout_variation_indices_,
|
||||
const hb_set_t *glyph_set_,
|
||||
const hb_map_t *gpos_lookups_) :
|
||||
layout_variation_indices (layout_variation_indices_),
|
||||
glyph_set (glyph_set_),
|
||||
gpos_lookups (gpos_lookups_),
|
||||
debug_depth (0) {}
|
||||
};
|
||||
|
||||
template<typename OutputArray>
|
||||
struct subset_offset_array_t
|
||||
{
|
||||
@ -2916,6 +2938,12 @@ struct VariationDevice
|
||||
return_trace (c->embed<VariationDevice> (this));
|
||||
}
|
||||
|
||||
void record_variation_index (hb_set_t *layout_variation_indices) const
|
||||
{
|
||||
unsigned var_idx = (outerIndex << 16) + innerIndex;
|
||||
layout_variation_indices->add (var_idx);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
@ -3020,6 +3048,25 @@ struct Device
|
||||
}
|
||||
}
|
||||
|
||||
void collect_variation_indices (hb_set_t *layout_variation_indices) const
|
||||
{
|
||||
switch (u.b.format) {
|
||||
#ifndef HB_NO_HINTING
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
return;
|
||||
#endif
|
||||
#ifndef HB_NO_VAR
|
||||
case 0x8000:
|
||||
u.variation.record_variation_index (layout_variation_indices);
|
||||
return;
|
||||
#endif
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
union {
|
||||
DeviceHeader b;
|
||||
|
@ -175,6 +175,9 @@ struct CaretValueFormat3
|
||||
|
||||
return_trace (out->deviceTable.serialize_copy (c->serializer, deviceTable, this));
|
||||
}
|
||||
|
||||
void collect_variation_indices (hb_set_t *layout_variation_indices) const
|
||||
{ (this+deviceTable).collect_variation_indices (layout_variation_indices); }
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
@ -221,6 +224,19 @@ struct CaretValue
|
||||
}
|
||||
}
|
||||
|
||||
void collect_variation_indices (hb_set_t *layout_variation_indices) const
|
||||
{
|
||||
switch (u.format) {
|
||||
case 1:
|
||||
case 2:
|
||||
return;
|
||||
case 3:
|
||||
u.format3.collect_variation_indices (layout_variation_indices);
|
||||
return;
|
||||
default: return;
|
||||
}
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
@ -277,6 +293,12 @@ struct LigGlyph
|
||||
|
||||
return_trace (bool (out->carets));
|
||||
}
|
||||
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
|
||||
{
|
||||
for (const OffsetTo<CaretValue>& offset : carets.iter ())
|
||||
(this+offset).collect_variation_indices (c->layout_variation_indices);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
@ -336,6 +358,16 @@ struct LigCaretList
|
||||
return_trace (bool (new_coverage));
|
||||
}
|
||||
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
|
||||
{
|
||||
+ hb_zip (this+coverage, ligGlyph)
|
||||
| hb_filter (c->glyph_set, hb_first)
|
||||
| hb_map (hb_second)
|
||||
| hb_map (hb_add (this))
|
||||
| hb_apply ([c] (const LigGlyph& _) { _.collect_variation_indices (c); })
|
||||
;
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
@ -544,6 +576,34 @@ struct GDEF
|
||||
(version.to_int () >= 0x00010003u ? varStore.static_size : 0);
|
||||
}
|
||||
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
|
||||
{ (this+ligCaretList).collect_variation_indices (c); }
|
||||
|
||||
void remap_layout_variation_indices (const hb_set_t *layout_variation_indices,
|
||||
hb_map_t *layout_variation_idx_map /* OUT */) const
|
||||
{
|
||||
if (version.to_int () < 0x00010003u || !varStore) return;
|
||||
if (layout_variation_indices->is_empty ()) return;
|
||||
|
||||
unsigned new_major = 0, new_minor = 0;
|
||||
unsigned last_major = (layout_variation_indices->get_min ()) >> 16;
|
||||
for (unsigned idx : layout_variation_indices->iter ())
|
||||
{
|
||||
uint16_t major = idx >> 16;
|
||||
if (major >= (this+varStore).get_sub_table_count ()) break;
|
||||
if (major != last_major)
|
||||
{
|
||||
new_minor = 0;
|
||||
++new_major;
|
||||
}
|
||||
|
||||
unsigned new_idx = (new_major << 16) + new_minor;
|
||||
layout_variation_idx_map->set (idx, new_idx);
|
||||
++new_minor;
|
||||
last_major = major;
|
||||
}
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
|
@ -176,6 +176,43 @@ struct ValueFormat : HBUINT16
|
||||
if (format & yAdvDevice) copy_device (c, base, values++);
|
||||
}
|
||||
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c,
|
||||
const void *base,
|
||||
const hb_array_t<const Value>& values) const
|
||||
{
|
||||
unsigned format = *this;
|
||||
unsigned i = 0;
|
||||
if (format & xPlacement) i++;
|
||||
if (format & yPlacement) i++;
|
||||
if (format & xAdvance) i++;
|
||||
if (format & yAdvance) i++;
|
||||
if (format & xPlaDevice)
|
||||
{
|
||||
(base + get_device (&(values[i]))).collect_variation_indices (c->layout_variation_indices);
|
||||
i++;
|
||||
}
|
||||
|
||||
if (format & ValueFormat::yPlaDevice)
|
||||
{
|
||||
(base + get_device (&(values[i]))).collect_variation_indices (c->layout_variation_indices);
|
||||
i++;
|
||||
}
|
||||
|
||||
if (format & ValueFormat::xAdvDevice)
|
||||
{
|
||||
|
||||
(base + get_device (&(values[i]))).collect_variation_indices (c->layout_variation_indices);
|
||||
i++;
|
||||
}
|
||||
|
||||
if (format & ValueFormat::yAdvDevice)
|
||||
{
|
||||
|
||||
(base + get_device (&(values[i]))).collect_variation_indices (c->layout_variation_indices);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
bool sanitize_value_devices (hb_sanitize_context_t *c, const void *base, const Value *values) const
|
||||
{
|
||||
@ -194,6 +231,16 @@ struct ValueFormat : HBUINT16
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline OffsetTo<Device>& get_device (Value* value)
|
||||
{
|
||||
return *static_cast<OffsetTo<Device> *> (value);
|
||||
}
|
||||
static inline const OffsetTo<Device>& get_device (const Value* value, bool *worked=nullptr)
|
||||
{
|
||||
if (worked) *worked |= bool (*value);
|
||||
return *static_cast<const OffsetTo<Device> *> (value);
|
||||
}
|
||||
|
||||
bool copy_device (hb_serialize_context_t *c, const void *base, const Value *src_value) const
|
||||
{
|
||||
Value *dst_value = c->copy (*src_value);
|
||||
@ -215,16 +262,6 @@ struct ValueFormat : HBUINT16
|
||||
}
|
||||
}
|
||||
|
||||
static inline OffsetTo<Device>& get_device (Value* value)
|
||||
{
|
||||
return *static_cast<OffsetTo<Device> *> (value);
|
||||
}
|
||||
static inline const OffsetTo<Device>& get_device (const Value* value, bool *worked=nullptr)
|
||||
{
|
||||
if (worked) *worked |= bool (*value);
|
||||
return *static_cast<const OffsetTo<Device> *> (value);
|
||||
}
|
||||
|
||||
static inline const HBINT16& get_short (const Value* value, bool *worked=nullptr)
|
||||
{
|
||||
if (worked) *worked |= bool (*value);
|
||||
@ -394,6 +431,12 @@ struct AnchorFormat3
|
||||
return_trace (out);
|
||||
}
|
||||
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
|
||||
{
|
||||
(this+xDeviceTable).collect_variation_indices (c->layout_variation_indices);
|
||||
(this+yDeviceTable).collect_variation_indices (c->layout_variation_indices);
|
||||
}
|
||||
|
||||
protected:
|
||||
HBUINT16 format; /* Format identifier--format = 3 */
|
||||
FWORD xCoordinate; /* Horizontal value--in design units */
|
||||
@ -447,6 +490,18 @@ struct Anchor
|
||||
}
|
||||
}
|
||||
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
|
||||
{
|
||||
switch (u.format) {
|
||||
case 1: case 2:
|
||||
return;
|
||||
case 3:
|
||||
u.format3.collect_variation_indices (c);
|
||||
return;
|
||||
default: return;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
union {
|
||||
HBUINT16 format; /* Format identifier */
|
||||
@ -470,6 +525,15 @@ struct AnchorMatrix
|
||||
return this+matrixZ[row * cols + col];
|
||||
}
|
||||
|
||||
template <typename Iterator,
|
||||
hb_requires (hb_is_iterator (Iterator))>
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c,
|
||||
Iterator index_iter) const
|
||||
{
|
||||
for (unsigned i : index_iter)
|
||||
(this+matrixZ[i]).collect_variation_indices (c);
|
||||
}
|
||||
|
||||
template <typename Iterator,
|
||||
hb_requires (hb_is_iterator (Iterator))>
|
||||
bool serialize (hb_serialize_context_t *c,
|
||||
@ -536,6 +600,12 @@ struct MarkRecord
|
||||
return_trace (out);
|
||||
}
|
||||
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c,
|
||||
const void *src_base) const
|
||||
{
|
||||
(src_base+markAnchor).collect_variation_indices (c);
|
||||
}
|
||||
|
||||
protected:
|
||||
HBUINT16 klass; /* Class defined for this mark */
|
||||
OffsetTo<Anchor>
|
||||
@ -611,6 +681,18 @@ struct SinglePosFormat1
|
||||
{ return (this+coverage).intersects (glyphs); }
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
|
||||
{
|
||||
if (!valueFormat.has_device ()) return;
|
||||
|
||||
auto it =
|
||||
+ hb_iter (this+coverage)
|
||||
| hb_filter (c->glyph_set)
|
||||
;
|
||||
|
||||
if (!it) return;
|
||||
valueFormat.collect_variation_indices (c, this, values.as_array (valueFormat.get_len ()));
|
||||
}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{ if (unlikely (!(this+coverage).collect_coverage (c->input))) return; }
|
||||
@ -701,6 +783,25 @@ struct SinglePosFormat2
|
||||
{ return (this+coverage).intersects (glyphs); }
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
|
||||
{
|
||||
if (!valueFormat.has_device ()) return;
|
||||
|
||||
auto it =
|
||||
+ hb_zip (this+coverage, hb_range ((unsigned) valueCount))
|
||||
| hb_filter (c->glyph_set, hb_first)
|
||||
;
|
||||
|
||||
if (!it) return;
|
||||
|
||||
unsigned sub_length = valueFormat.get_len ();
|
||||
const hb_array_t<const Value> values_array = values.as_array (valueCount * sub_length);
|
||||
|
||||
for (unsigned i : + it
|
||||
| hb_map (hb_second))
|
||||
valueFormat.collect_variation_indices (c, this, values_array.sub_array (i * sub_length, sub_length));
|
||||
|
||||
}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{ if (unlikely (!(this+coverage).collect_coverage (c->input))) return; }
|
||||
@ -895,6 +996,21 @@ struct PairValueRecord
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c,
|
||||
const ValueFormat *valueFormats,
|
||||
const void *base) const
|
||||
{
|
||||
unsigned record1_len = valueFormats[0].get_len ();
|
||||
unsigned record2_len = valueFormats[1].get_len ();
|
||||
const hb_array_t<const Value> values_array = values.as_array (record1_len + record2_len);
|
||||
|
||||
if (valueFormats[0].has_device ())
|
||||
valueFormats[0].collect_variation_indices (c, base, values_array.sub_array (0, record1_len));
|
||||
|
||||
if (valueFormats[1].has_device ())
|
||||
valueFormats[1].collect_variation_indices (c, base, values_array.sub_array (record1_len, record2_len));
|
||||
}
|
||||
|
||||
protected:
|
||||
HBGlyphID secondGlyph; /* GlyphID of second glyph in the
|
||||
* pair--first glyph is listed in the
|
||||
@ -938,6 +1054,24 @@ struct PairSet
|
||||
c->input->add_array (&record->secondGlyph, len, record_size);
|
||||
}
|
||||
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c,
|
||||
const ValueFormat *valueFormats) const
|
||||
{
|
||||
unsigned len1 = valueFormats[0].get_len ();
|
||||
unsigned len2 = valueFormats[1].get_len ();
|
||||
unsigned record_size = HBUINT16::static_size * (1 + len1 + len2);
|
||||
|
||||
const PairValueRecord *record = &firstPairValueRecord;
|
||||
unsigned count = len;
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
{
|
||||
if (c->glyph_set->has (record->secondGlyph))
|
||||
{ record->collect_variation_indices (c, valueFormats, this); }
|
||||
|
||||
record = &StructAtOffset<const PairValueRecord> (record, record_size);
|
||||
}
|
||||
}
|
||||
|
||||
bool apply (hb_ot_apply_context_t *c,
|
||||
const ValueFormat *valueFormats,
|
||||
unsigned int pos) const
|
||||
@ -1051,6 +1185,22 @@ struct PairPosFormat1
|
||||
}
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
|
||||
{
|
||||
if ((!valueFormat[0].has_device ()) && (!valueFormat[1].has_device ())) return;
|
||||
|
||||
auto it =
|
||||
+ hb_zip (this+coverage, pairSet)
|
||||
| hb_filter (c->glyph_set, hb_first)
|
||||
| hb_map (hb_second)
|
||||
;
|
||||
|
||||
if (!it) return;
|
||||
+ it
|
||||
| hb_map (hb_add (this))
|
||||
| hb_apply ([&] (const PairSet& _) { _.collect_variation_indices (c, valueFormat); })
|
||||
;
|
||||
}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{
|
||||
@ -1163,6 +1313,37 @@ 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 ((!valueFormat1.has_device ()) && (!valueFormat2.has_device ())) return;
|
||||
|
||||
hb_set_t class1_set, class2_set;
|
||||
for (const unsigned cp : c->glyph_set->iter ())
|
||||
{
|
||||
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;
|
||||
|
||||
unsigned len1 = valueFormat1.get_len ();
|
||||
unsigned len2 = valueFormat2.get_len ();
|
||||
const hb_array_t<const Value> values_array = values.as_array ((unsigned)class1Count * (unsigned) class2Count * (len1 + len2));
|
||||
for (const unsigned class1_idx : class1_set.iter ())
|
||||
{
|
||||
for (const unsigned class2_idx : class2_set.iter ())
|
||||
{
|
||||
unsigned start_offset = (class1_idx * (unsigned) class2Count + class2_idx) * (len1 + len2);
|
||||
if (valueFormat1.has_device ())
|
||||
valueFormat1.collect_variation_indices (c, this, values_array.sub_array (start_offset, len1));
|
||||
|
||||
if (valueFormat2.has_device ())
|
||||
valueFormat2.collect_variation_indices (c, this, values_array.sub_array (start_offset+len1, len2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{
|
||||
@ -1336,6 +1517,13 @@ struct EntryExitRecord
|
||||
return_trace (entryAnchor.sanitize (c, base) && exitAnchor.sanitize (c, base));
|
||||
}
|
||||
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c,
|
||||
const void *src_base) const
|
||||
{
|
||||
(src_base+entryAnchor).collect_variation_indices (c);
|
||||
(src_base+exitAnchor).collect_variation_indices (c);
|
||||
}
|
||||
|
||||
EntryExitRecord* copy (hb_serialize_context_t *c, const void *base) const
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
@ -1370,6 +1558,15 @@ struct CursivePosFormat1
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
||||
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
|
||||
{
|
||||
+ hb_zip (this+coverage, entryExitRecord)
|
||||
| hb_filter (c->glyph_set, hb_first)
|
||||
| hb_map (hb_second)
|
||||
| hb_apply ([&] (const EntryExitRecord& record) { record.collect_variation_indices (c, this); })
|
||||
;
|
||||
}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{ if (unlikely (!(this+coverage).collect_coverage (c->input))) return; }
|
||||
|
||||
@ -1592,6 +1789,36 @@ struct MarkBasePosFormat1
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
||||
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
|
||||
{
|
||||
+ hb_zip (this+markCoverage, this+markArray)
|
||||
| hb_filter (c->glyph_set, hb_first)
|
||||
| hb_map (hb_second)
|
||||
| hb_apply ([&] (const MarkRecord& record) { record.collect_variation_indices (c, &(this+markArray)); })
|
||||
;
|
||||
|
||||
hb_map_t klass_mapping;
|
||||
Markclass_closure_and_remap_indexes (this+markCoverage, this+markArray, *c->glyph_set, &klass_mapping);
|
||||
|
||||
unsigned basecount = (this+baseArray).rows;
|
||||
auto base_iter =
|
||||
+ hb_zip (this+baseCoverage, hb_range (basecount))
|
||||
| hb_filter (c->glyph_set, hb_first)
|
||||
| hb_map (hb_second)
|
||||
;
|
||||
|
||||
hb_sorted_vector_t<unsigned> base_indexes;
|
||||
for (const unsigned row : base_iter)
|
||||
{
|
||||
+ hb_range ((unsigned) classCount)
|
||||
| hb_filter (klass_mapping)
|
||||
| hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
|
||||
| hb_sink (base_indexes)
|
||||
;
|
||||
}
|
||||
(this+baseArray).collect_variation_indices (c, base_indexes.iter ());
|
||||
}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{
|
||||
if (unlikely (!(this+markCoverage).collect_coverage (c->input))) return;
|
||||
@ -1777,6 +2004,42 @@ struct MarkLigPosFormat1
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
||||
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
|
||||
{
|
||||
+ hb_zip (this+markCoverage, this+markArray)
|
||||
| hb_filter (c->glyph_set, hb_first)
|
||||
| hb_map (hb_second)
|
||||
| hb_apply ([&] (const MarkRecord& record) { record.collect_variation_indices (c, &(this+markArray)); })
|
||||
;
|
||||
|
||||
hb_map_t klass_mapping;
|
||||
Markclass_closure_and_remap_indexes (this+markCoverage, this+markArray, *c->glyph_set, &klass_mapping);
|
||||
|
||||
unsigned ligcount = (this+ligatureArray).len;
|
||||
auto lig_iter =
|
||||
+ hb_zip (this+ligatureCoverage, hb_range (ligcount))
|
||||
| hb_filter (c->glyph_set, hb_first)
|
||||
| hb_map (hb_second)
|
||||
;
|
||||
|
||||
const LigatureArray& lig_array = this+ligatureArray;
|
||||
for (const unsigned i : lig_iter)
|
||||
{
|
||||
hb_sorted_vector_t<unsigned> lig_indexes;
|
||||
unsigned row_count = lig_array[i].rows;
|
||||
for (unsigned row : + hb_range (row_count))
|
||||
{
|
||||
+ hb_range ((unsigned) classCount)
|
||||
| hb_filter (klass_mapping)
|
||||
| hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
|
||||
| hb_sink (lig_indexes)
|
||||
;
|
||||
}
|
||||
|
||||
lig_array[i].collect_variation_indices (c, lig_indexes.iter ());
|
||||
}
|
||||
}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{
|
||||
if (unlikely (!(this+markCoverage).collect_coverage (c->input))) return;
|
||||
@ -1899,6 +2162,36 @@ struct MarkMarkPosFormat1
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
||||
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
|
||||
{
|
||||
+ hb_zip (this+mark1Coverage, this+mark1Array)
|
||||
| hb_filter (c->glyph_set, hb_first)
|
||||
| hb_map (hb_second)
|
||||
| hb_apply ([&] (const MarkRecord& record) { record.collect_variation_indices (c, &(this+mark1Array)); })
|
||||
;
|
||||
|
||||
hb_map_t klass_mapping;
|
||||
Markclass_closure_and_remap_indexes (this+mark1Coverage, this+mark1Array, *c->glyph_set, &klass_mapping);
|
||||
|
||||
unsigned mark2_count = (this+mark2Array).rows;
|
||||
auto mark2_iter =
|
||||
+ hb_zip (this+mark2Coverage, hb_range (mark2_count))
|
||||
| hb_filter (c->glyph_set, hb_first)
|
||||
| hb_map (hb_second)
|
||||
;
|
||||
|
||||
hb_sorted_vector_t<unsigned> mark2_indexes;
|
||||
for (const unsigned row : mark2_iter)
|
||||
{
|
||||
+ hb_range ((unsigned) classCount)
|
||||
| hb_filter (klass_mapping)
|
||||
| hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
|
||||
| hb_sink (mark2_indexes)
|
||||
;
|
||||
}
|
||||
(this+mark2Array).collect_variation_indices (c, mark2_indexes.iter ());
|
||||
}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{
|
||||
if (unlikely (!(this+mark1Coverage).collect_coverage (c->input))) return;
|
||||
@ -1986,7 +2279,7 @@ struct MarkMarkPosFormat1
|
||||
out->mark1Array.serialize (c->serializer, out)
|
||||
.serialize (c->serializer, &klass_mapping, &(this+mark1Array), + mark1_iter
|
||||
| hb_map (hb_second));
|
||||
//////
|
||||
|
||||
unsigned mark2count = (this+mark2Array).rows;
|
||||
auto mark2_iter =
|
||||
+ hb_zip (this+mark2Coverage, hb_range (mark2count))
|
||||
@ -2243,6 +2536,16 @@ struct GPOS : GSUBGPOS
|
||||
HB_INTERNAL bool is_blacklisted (hb_blob_t *blob,
|
||||
hb_face_t *face) const;
|
||||
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
|
||||
{
|
||||
for (unsigned i = 0; i < GSUBGPOS::get_lookup_count (); i++)
|
||||
{
|
||||
if (!c->gpos_lookups->has (i)) continue;
|
||||
const PosLookup &l = get_lookup (i);
|
||||
l.dispatch (c);
|
||||
}
|
||||
}
|
||||
|
||||
typedef GSUBGPOS::accelerator_t<GPOS> accelerator_t;
|
||||
};
|
||||
|
||||
|
@ -1674,6 +1674,8 @@ struct ContextFormat1
|
||||
;
|
||||
}
|
||||
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const {}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{
|
||||
(this+coverage).collect_coverage (c->input);
|
||||
@ -1814,6 +1816,8 @@ struct ContextFormat2
|
||||
;
|
||||
}
|
||||
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const {}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{
|
||||
(this+coverage).collect_coverage (c->input);
|
||||
@ -1964,6 +1968,8 @@ struct ContextFormat3
|
||||
recurse_lookups (c, lookupCount, lookupRecord);
|
||||
}
|
||||
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const {}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{
|
||||
(this+coverageZ[0]).collect_coverage (c->input);
|
||||
@ -2562,6 +2568,8 @@ struct ChainContextFormat1
|
||||
;
|
||||
}
|
||||
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const {}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{
|
||||
(this+coverage).collect_coverage (c->input);
|
||||
@ -2706,6 +2714,8 @@ struct ChainContextFormat2
|
||||
;
|
||||
}
|
||||
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const {}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{
|
||||
(this+coverage).collect_coverage (c->input);
|
||||
@ -2904,6 +2914,8 @@ struct ChainContextFormat3
|
||||
recurse_lookups (c, lookup.len, lookup.arrayZ);
|
||||
}
|
||||
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const {}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{
|
||||
const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
|
||||
@ -3082,6 +3094,9 @@ struct ExtensionFormat1
|
||||
return_trace (get_subtable<typename T::SubTable> ().dispatch (c, get_type (), hb_forward<Ts> (ds)...));
|
||||
}
|
||||
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
|
||||
{ dispatch (c); }
|
||||
|
||||
/* This is called from may_dispatch() above with hb_sanitize_context_t. */
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
|
@ -318,6 +318,37 @@ hb_ot_layout_get_glyphs_in_class (hb_face_t *face,
|
||||
return face->table.GDEF->table->get_glyphs_in_class (klass, glyphs);
|
||||
}
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
/**
|
||||
* hb_ot_layout_collect_variation_indices:
|
||||
* @face: The #hb_face_t to work on
|
||||
* @layout_variation_indices: (inout): The #hb_set_t set of var indexes in all Device
|
||||
* tables
|
||||
*
|
||||
* Fetch and remap a list of variation indices in all Device tables referenced
|
||||
* in the specified face's GDEF table and GPOS tables that are going to be
|
||||
* retained in the final subset
|
||||
*
|
||||
* Since: REPLACEME
|
||||
**/
|
||||
void
|
||||
hb_ot_layout_collect_variation_indices (hb_face_t *face,
|
||||
const hb_set_t *glyphset,
|
||||
const hb_map_t *gpos_lookups,
|
||||
hb_set_t *layout_variation_indices /* OUT */,
|
||||
hb_map_t *layout_variation_idx_map /* OUT */)
|
||||
{
|
||||
if (!face->table.GDEF->table->has_data ()) return;
|
||||
OT::hb_collect_variation_indices_context_t c (layout_variation_indices, glyphset, gpos_lookups);
|
||||
face->table.GDEF->table->collect_variation_indices (&c);
|
||||
|
||||
if (hb_ot_layout_has_positioning (face))
|
||||
face->table.GPOS->table->collect_variation_indices (&c);
|
||||
|
||||
face->table.GDEF->table->remap_layout_variation_indices (layout_variation_indices, layout_variation_idx_map);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef HB_NO_LAYOUT_UNUSED
|
||||
/**
|
||||
|
@ -121,6 +121,12 @@ hb_ot_layout_get_glyphs_in_class (hb_face_t *face,
|
||||
hb_ot_layout_glyph_class_t klass,
|
||||
hb_set_t *glyphs /* OUT */);
|
||||
|
||||
HB_EXTERN void
|
||||
hb_ot_layout_collect_variation_indices (hb_face_t *face,
|
||||
const hb_set_t *glyphset,
|
||||
const hb_map_t *gpos_lookups,
|
||||
hb_set_t *layout_variation_indices /* INOUT */,
|
||||
hb_map_t *layout_variation_idx_map /* INOUT */);
|
||||
|
||||
/* Not that useful. Provides list of attach points for a glyph that a
|
||||
* client may want to cache */
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "hb-ot-var-fvar-table.hh"
|
||||
#include "hb-ot-stat-table.hh"
|
||||
|
||||
|
||||
#ifndef HB_NO_SUBSET_CFF
|
||||
static inline void
|
||||
_add_cff_seac_components (const OT::cff1::accelerator_t &cff,
|
||||
@ -128,6 +129,18 @@ _gpos_closure_lookups_features (hb_face_t *face,
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
static inline void
|
||||
_collect_layout_variation_indices (hb_face_t *face,
|
||||
const hb_set_t *glyphset,
|
||||
const hb_map_t *gpos_lookups,
|
||||
hb_set_t *layout_variation_indices,
|
||||
hb_map_t *layout_variation_idx_map)
|
||||
{
|
||||
hb_ot_layout_collect_variation_indices (face, glyphset, gpos_lookups, layout_variation_indices, layout_variation_idx_map);
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void
|
||||
_cmap_closure (hb_face_t *face,
|
||||
const hb_set_t *unicodes,
|
||||
@ -156,7 +169,8 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
|
||||
const hb_set_t *unicodes,
|
||||
const hb_set_t *input_glyphs_to_retain,
|
||||
bool close_over_gsub,
|
||||
bool close_over_gpos)
|
||||
bool close_over_gpos,
|
||||
bool close_over_gdef)
|
||||
{
|
||||
OT::cmap::accelerator_t cmap;
|
||||
OT::glyf::accelerator_t glyf;
|
||||
@ -216,6 +230,11 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
|
||||
|
||||
_remove_invalid_gids (plan->_glyphset, plan->source->get_num_glyphs ());
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
if (close_over_gdef)
|
||||
_collect_layout_variation_indices (plan->source, plan->_glyphset, plan->gpos_lookups, plan->layout_variation_indices, plan->layout_variation_idx_map);
|
||||
#endif
|
||||
|
||||
#ifndef HB_NO_SUBSET_CFF
|
||||
cff.fini ();
|
||||
#endif
|
||||
@ -308,12 +327,15 @@ hb_subset_plan_create (hb_face_t *face,
|
||||
plan->gpos_lookups = hb_map_create ();
|
||||
plan->gsub_features = hb_map_create ();
|
||||
plan->gpos_features = hb_map_create ();
|
||||
plan->layout_variation_indices = hb_set_create ();
|
||||
plan->layout_variation_idx_map = hb_map_create ();
|
||||
|
||||
_populate_gids_to_retain (plan,
|
||||
input->unicodes,
|
||||
input->glyphs,
|
||||
!input->drop_tables->has (HB_OT_TAG_GSUB),
|
||||
!input->drop_tables->has (HB_OT_TAG_GPOS));
|
||||
!input->drop_tables->has (HB_OT_TAG_GPOS),
|
||||
!input->drop_tables->has (HB_OT_TAG_GDEF));
|
||||
|
||||
_create_old_gid_to_new_gid_map (face,
|
||||
input->retain_gids,
|
||||
@ -351,6 +373,8 @@ hb_subset_plan_destroy (hb_subset_plan_t *plan)
|
||||
hb_map_destroy (plan->gpos_lookups);
|
||||
hb_map_destroy (plan->gsub_features);
|
||||
hb_map_destroy (plan->gpos_features);
|
||||
hb_set_destroy (plan->layout_variation_indices);
|
||||
hb_map_destroy (plan->layout_variation_idx_map);
|
||||
|
||||
|
||||
free (plan);
|
||||
|
@ -82,6 +82,11 @@ struct hb_subset_plan_t
|
||||
hb_map_t *gsub_features;
|
||||
hb_map_t *gpos_features;
|
||||
|
||||
//The set of layout item variation store delta set indices to be retained
|
||||
hb_set_t *layout_variation_indices;
|
||||
//Old -> New layout item variation store delta set index mapping
|
||||
hb_map_t *layout_variation_idx_map;
|
||||
|
||||
public:
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user