[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:
Qunxin Liu 2020-02-26 13:11:42 -08:00 committed by Garret Rieger
parent 8ba0077ea3
commit 8200e48ffc
8 changed files with 504 additions and 13 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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;
};

View File

@ -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
{

View File

@ -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
/**

View File

@ -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 */

View File

@ -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);

View File

@ -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:
/*