Merge pull request #3795 from googlefonts/instance_GDEF_GPOS
[instancing] update GDEF/GPOS tables and a few fixes for glyf instancing
This commit is contained in:
commit
fd107bddb0
|
@ -58,8 +58,7 @@ struct Anchor
|
||||||
return_trace (bool (reinterpret_cast<Anchor *> (u.format1.copy (c->serializer))));
|
return_trace (bool (reinterpret_cast<Anchor *> (u.format1.copy (c->serializer))));
|
||||||
}
|
}
|
||||||
return_trace (bool (reinterpret_cast<Anchor *> (u.format2.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,
|
case 3: return_trace (u.format3.subset (c));
|
||||||
c->plan->layout_variation_idx_map))));
|
|
||||||
default:return_trace (false);
|
default:return_trace (false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,24 +41,54 @@ struct AnchorFormat3
|
||||||
*y += (this+yDeviceTable).get_y_delta (font, c->var_store, c->var_store_cache);
|
*y += (this+yDeviceTable).get_y_delta (font, c->var_store, c->var_store_cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
AnchorFormat3* copy (hb_serialize_context_t *c,
|
bool subset (hb_subset_context_t *c) const
|
||||||
const hb_map_t *layout_variation_idx_map) const
|
|
||||||
{
|
{
|
||||||
TRACE_SERIALIZE (this);
|
TRACE_SUBSET (this);
|
||||||
if (!layout_variation_idx_map) return_trace (nullptr);
|
auto *out = c->serializer->start_embed (*this);
|
||||||
|
if (unlikely (!out)) return_trace (false);
|
||||||
|
if (unlikely (!c->serializer->embed (format))) return_trace (false);
|
||||||
|
if (unlikely (!c->serializer->embed (xCoordinate))) return_trace (false);
|
||||||
|
if (unlikely (!c->serializer->embed (yCoordinate))) return_trace (false);
|
||||||
|
|
||||||
auto *out = c->embed<AnchorFormat3> (this);
|
unsigned x_varidx = xDeviceTable ? (this+xDeviceTable).get_variation_index () : HB_OT_LAYOUT_NO_VARIATIONS_INDEX;
|
||||||
if (unlikely (!out)) return_trace (nullptr);
|
if (c->plan->layout_variation_idx_delta_map->has (x_varidx))
|
||||||
|
{
|
||||||
|
int delta = hb_second (c->plan->layout_variation_idx_delta_map->get (x_varidx));
|
||||||
|
if (delta != 0)
|
||||||
|
{
|
||||||
|
if (!c->serializer->check_assign (out->xCoordinate, xCoordinate + delta,
|
||||||
|
HB_SERIALIZE_ERROR_INT_OVERFLOW))
|
||||||
|
return_trace (false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
out->xDeviceTable.serialize_copy (c, xDeviceTable, this, 0, hb_serialize_context_t::Head, layout_variation_idx_map);
|
unsigned y_varidx = yDeviceTable ? (this+yDeviceTable).get_variation_index () : HB_OT_LAYOUT_NO_VARIATIONS_INDEX;
|
||||||
out->yDeviceTable.serialize_copy (c, yDeviceTable, this, 0, hb_serialize_context_t::Head, layout_variation_idx_map);
|
if (c->plan->layout_variation_idx_delta_map->has (y_varidx))
|
||||||
|
{
|
||||||
|
int delta = hb_second (c->plan->layout_variation_idx_delta_map->get (y_varidx));
|
||||||
|
if (delta != 0)
|
||||||
|
{
|
||||||
|
if (!c->serializer->check_assign (out->yCoordinate, yCoordinate + delta,
|
||||||
|
HB_SERIALIZE_ERROR_INT_OVERFLOW))
|
||||||
|
return_trace (false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c->plan->all_axes_pinned)
|
||||||
|
return_trace (c->serializer->check_assign (out->format, 1, HB_SERIALIZE_ERROR_INT_OVERFLOW));
|
||||||
|
|
||||||
|
if (!c->serializer->embed (xDeviceTable)) return_trace (false);
|
||||||
|
if (!c->serializer->embed (yDeviceTable)) return_trace (false);
|
||||||
|
|
||||||
|
out->xDeviceTable.serialize_copy (c->serializer, xDeviceTable, this, 0, hb_serialize_context_t::Head, c->plan->layout_variation_idx_delta_map);
|
||||||
|
out->yDeviceTable.serialize_copy (c->serializer, yDeviceTable, this, 0, hb_serialize_context_t::Head, c->plan->layout_variation_idx_delta_map);
|
||||||
return_trace (out);
|
return_trace (out);
|
||||||
}
|
}
|
||||||
|
|
||||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
|
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
|
||||||
{
|
{
|
||||||
(this+xDeviceTable).collect_variation_indices (c->layout_variation_indices);
|
(this+xDeviceTable).collect_variation_indices (c);
|
||||||
(this+yDeviceTable).collect_variation_indices (c->layout_variation_indices);
|
(this+yDeviceTable).collect_variation_indices (c);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,8 @@ template<typename Iterator, typename SrcLookup>
|
||||||
static void SinglePos_serialize (hb_serialize_context_t *c,
|
static void SinglePos_serialize (hb_serialize_context_t *c,
|
||||||
const SrcLookup *src,
|
const SrcLookup *src,
|
||||||
Iterator it,
|
Iterator it,
|
||||||
const hb_map_t *layout_variation_idx_map);
|
const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map,
|
||||||
|
bool all_axes_pinned);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,6 +127,12 @@ struct PairPosFormat1_3
|
||||||
out->valueFormat[1] = newFormats.second;
|
out->valueFormat[1] = newFormats.second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (c->plan->all_axes_pinned)
|
||||||
|
{
|
||||||
|
out->valueFormat[0] = out->valueFormat[0].drop_device_table_flags ();
|
||||||
|
out->valueFormat[1] = out->valueFormat[1].drop_device_table_flags ();
|
||||||
|
}
|
||||||
|
|
||||||
hb_sorted_vector_t<hb_codepoint_t> new_coverage;
|
hb_sorted_vector_t<hb_codepoint_t> new_coverage;
|
||||||
|
|
||||||
+ hb_zip (this+coverage, pairSet)
|
+ hb_zip (this+coverage, pairSet)
|
||||||
|
|
|
@ -274,13 +274,19 @@ struct PairPosFormat2_4
|
||||||
out->valueFormat1 = newFormats.first;
|
out->valueFormat1 = newFormats.first;
|
||||||
out->valueFormat2 = newFormats.second;
|
out->valueFormat2 = newFormats.second;
|
||||||
|
|
||||||
|
if (c->plan->all_axes_pinned)
|
||||||
|
{
|
||||||
|
out->valueFormat1 = out->valueFormat1.drop_device_table_flags ();
|
||||||
|
out->valueFormat2 = out->valueFormat2.drop_device_table_flags ();
|
||||||
|
}
|
||||||
|
|
||||||
for (unsigned class1_idx : + hb_range ((unsigned) class1Count) | hb_filter (klass1_map))
|
for (unsigned class1_idx : + hb_range ((unsigned) class1Count) | hb_filter (klass1_map))
|
||||||
{
|
{
|
||||||
for (unsigned class2_idx : + hb_range ((unsigned) class2Count) | hb_filter (klass2_map))
|
for (unsigned class2_idx : + hb_range ((unsigned) class2Count) | hb_filter (klass2_map))
|
||||||
{
|
{
|
||||||
unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * (len1 + len2);
|
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);
|
valueFormat1.copy_values (c->serializer, out->valueFormat1, this, &values[idx], c->plan->layout_variation_idx_delta_map);
|
||||||
valueFormat2.copy_values (c->serializer, newFormats.second, this, &values[idx + len1], c->plan->layout_variation_idx_map);
|
valueFormat2.copy_values (c->serializer, out->valueFormat2, this, &values[idx + len1], c->plan->layout_variation_idx_delta_map);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -163,7 +163,7 @@ struct PairSet
|
||||||
newFormats,
|
newFormats,
|
||||||
len1,
|
len1,
|
||||||
&glyph_map,
|
&glyph_map,
|
||||||
c->plan->layout_variation_idx_map
|
c->plan->layout_variation_idx_delta_map
|
||||||
};
|
};
|
||||||
|
|
||||||
const PairValueRecord *record = &firstPairValueRecord;
|
const PairValueRecord *record = &firstPairValueRecord;
|
||||||
|
|
|
@ -34,7 +34,7 @@ struct PairValueRecord
|
||||||
const ValueFormat *newFormats;
|
const ValueFormat *newFormats;
|
||||||
unsigned len1; /* valueFormats[0].get_len() */
|
unsigned len1; /* valueFormats[0].get_len() */
|
||||||
const hb_map_t *glyph_map;
|
const hb_map_t *glyph_map;
|
||||||
const hb_map_t *layout_variation_idx_map;
|
const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool subset (hb_subset_context_t *c,
|
bool subset (hb_subset_context_t *c,
|
||||||
|
@ -50,12 +50,12 @@ struct PairValueRecord
|
||||||
closure->valueFormats[0].copy_values (s,
|
closure->valueFormats[0].copy_values (s,
|
||||||
closure->newFormats[0],
|
closure->newFormats[0],
|
||||||
closure->base, &values[0],
|
closure->base, &values[0],
|
||||||
closure->layout_variation_idx_map);
|
closure->layout_variation_idx_delta_map);
|
||||||
closure->valueFormats[1].copy_values (s,
|
closure->valueFormats[1].copy_values (s,
|
||||||
closure->newFormats[1],
|
closure->newFormats[1],
|
||||||
closure->base,
|
closure->base,
|
||||||
&values[closure->len1],
|
&values[closure->len1],
|
||||||
closure->layout_variation_idx_map);
|
closure->layout_variation_idx_delta_map);
|
||||||
|
|
||||||
return_trace (true);
|
return_trace (true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,12 +38,16 @@ struct SinglePos
|
||||||
void serialize (hb_serialize_context_t *c,
|
void serialize (hb_serialize_context_t *c,
|
||||||
const SrcLookup* src,
|
const SrcLookup* src,
|
||||||
Iterator glyph_val_iter_pairs,
|
Iterator glyph_val_iter_pairs,
|
||||||
const hb_map_t *layout_variation_idx_map)
|
const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map,
|
||||||
|
bool all_axes_pinned)
|
||||||
{
|
{
|
||||||
if (unlikely (!c->extend_min (u.format))) return;
|
if (unlikely (!c->extend_min (u.format))) return;
|
||||||
unsigned format = 2;
|
unsigned format = 2;
|
||||||
ValueFormat new_format = src->get_value_format ();
|
ValueFormat new_format = src->get_value_format ();
|
||||||
|
|
||||||
|
if (all_axes_pinned)
|
||||||
|
new_format = new_format.drop_device_table_flags ();
|
||||||
|
|
||||||
if (glyph_val_iter_pairs)
|
if (glyph_val_iter_pairs)
|
||||||
format = get_format (glyph_val_iter_pairs);
|
format = get_format (glyph_val_iter_pairs);
|
||||||
|
|
||||||
|
@ -53,13 +57,13 @@ struct SinglePos
|
||||||
src,
|
src,
|
||||||
glyph_val_iter_pairs,
|
glyph_val_iter_pairs,
|
||||||
new_format,
|
new_format,
|
||||||
layout_variation_idx_map);
|
layout_variation_idx_delta_map);
|
||||||
return;
|
return;
|
||||||
case 2: u.format2.serialize (c,
|
case 2: u.format2.serialize (c,
|
||||||
src,
|
src,
|
||||||
glyph_val_iter_pairs,
|
glyph_val_iter_pairs,
|
||||||
new_format,
|
new_format,
|
||||||
layout_variation_idx_map);
|
layout_variation_idx_delta_map);
|
||||||
return;
|
return;
|
||||||
default:return;
|
default:return;
|
||||||
}
|
}
|
||||||
|
@ -84,8 +88,9 @@ static void
|
||||||
SinglePos_serialize (hb_serialize_context_t *c,
|
SinglePos_serialize (hb_serialize_context_t *c,
|
||||||
const SrcLookup *src,
|
const SrcLookup *src,
|
||||||
Iterator it,
|
Iterator it,
|
||||||
const hb_map_t *layout_variation_idx_map)
|
const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map,
|
||||||
{ c->start_embed<SinglePos> ()->serialize (c, src, it, layout_variation_idx_map); }
|
bool all_axes_pinned)
|
||||||
|
{ c->start_embed<SinglePos> ()->serialize (c, src, it, layout_variation_idx_delta_map, all_axes_pinned); }
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,7 +87,7 @@ struct SinglePosFormat1
|
||||||
const SrcLookup *src,
|
const SrcLookup *src,
|
||||||
Iterator it,
|
Iterator it,
|
||||||
ValueFormat newFormat,
|
ValueFormat newFormat,
|
||||||
const hb_map_t *layout_variation_idx_map)
|
const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map)
|
||||||
{
|
{
|
||||||
if (unlikely (!c->extend_min (this))) return;
|
if (unlikely (!c->extend_min (this))) return;
|
||||||
if (unlikely (!c->check_assign (valueFormat,
|
if (unlikely (!c->check_assign (valueFormat,
|
||||||
|
@ -96,7 +96,7 @@ struct SinglePosFormat1
|
||||||
|
|
||||||
for (const hb_array_t<const Value>& _ : + it | hb_map (hb_second))
|
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);
|
src->get_value_format ().copy_values (c, newFormat, src, &_, layout_variation_idx_delta_map);
|
||||||
// Only serialize the first entry in the iterator, the rest are assumed to
|
// Only serialize the first entry in the iterator, the rest are assumed to
|
||||||
// be the same.
|
// be the same.
|
||||||
break;
|
break;
|
||||||
|
@ -126,7 +126,7 @@ struct SinglePosFormat1
|
||||||
;
|
;
|
||||||
|
|
||||||
bool ret = bool (it);
|
bool ret = bool (it);
|
||||||
SinglePos_serialize (c->serializer, this, it, c->plan->layout_variation_idx_map);
|
SinglePos_serialize (c->serializer, this, it, c->plan->layout_variation_idx_delta_map, c->plan->all_axes_pinned);
|
||||||
return_trace (ret);
|
return_trace (ret);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -99,7 +99,7 @@ struct SinglePosFormat2
|
||||||
const SrcLookup *src,
|
const SrcLookup *src,
|
||||||
Iterator it,
|
Iterator it,
|
||||||
ValueFormat newFormat,
|
ValueFormat newFormat,
|
||||||
const hb_map_t *layout_variation_idx_map)
|
const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map)
|
||||||
{
|
{
|
||||||
auto out = c->extend_min (this);
|
auto out = c->extend_min (this);
|
||||||
if (unlikely (!out)) return;
|
if (unlikely (!out)) return;
|
||||||
|
@ -109,7 +109,7 @@ struct SinglePosFormat2
|
||||||
+ it
|
+ it
|
||||||
| hb_map (hb_second)
|
| hb_map (hb_second)
|
||||||
| hb_apply ([&] (hb_array_t<const Value> _)
|
| hb_apply ([&] (hb_array_t<const Value> _)
|
||||||
{ src->get_value_format ().copy_values (c, newFormat, src, &_, layout_variation_idx_map); })
|
{ src->get_value_format ().copy_values (c, newFormat, src, &_, layout_variation_idx_delta_map); })
|
||||||
;
|
;
|
||||||
|
|
||||||
auto glyphs =
|
auto glyphs =
|
||||||
|
@ -141,7 +141,7 @@ struct SinglePosFormat2
|
||||||
;
|
;
|
||||||
|
|
||||||
bool ret = bool (it);
|
bool ret = bool (it);
|
||||||
SinglePos_serialize (c->serializer, this, it, c->plan->layout_variation_idx_map);
|
SinglePos_serialize (c->serializer, this, it, c->plan->layout_variation_idx_delta_map, c->plan->all_axes_pinned);
|
||||||
return_trace (ret);
|
return_trace (ret);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -163,30 +163,50 @@ struct ValueFormat : HBUINT16
|
||||||
unsigned int new_format,
|
unsigned int new_format,
|
||||||
const void *base,
|
const void *base,
|
||||||
const Value *values,
|
const Value *values,
|
||||||
const hb_map_t *layout_variation_idx_map) const
|
const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map) const
|
||||||
{
|
{
|
||||||
unsigned int format = *this;
|
unsigned int format = *this;
|
||||||
if (!format) return;
|
if (!format) return;
|
||||||
|
|
||||||
if (format & xPlacement) copy_value (c, new_format, xPlacement, *values++);
|
HBINT16 *x_placement = nullptr, *y_placement = nullptr, *x_adv = nullptr, *y_adv = nullptr;
|
||||||
if (format & yPlacement) copy_value (c, new_format, yPlacement, *values++);
|
if (format & xPlacement) x_placement = copy_value (c, new_format, xPlacement, *values++);
|
||||||
if (format & xAdvance) copy_value (c, new_format, xAdvance, *values++);
|
if (format & yPlacement) y_placement = copy_value (c, new_format, yPlacement, *values++);
|
||||||
if (format & yAdvance) copy_value (c, new_format, yAdvance, *values++);
|
if (format & xAdvance) x_adv = copy_value (c, new_format, xAdvance, *values++);
|
||||||
|
if (format & yAdvance) y_adv = copy_value (c, new_format, yAdvance, *values++);
|
||||||
|
|
||||||
if (format & xPlaDevice) copy_device (c, base, values++, layout_variation_idx_map);
|
if (format & xPlaDevice)
|
||||||
if (format & yPlaDevice) copy_device (c, base, values++, layout_variation_idx_map);
|
{
|
||||||
if (format & xAdvDevice) copy_device (c, base, values++, layout_variation_idx_map);
|
add_delta_to_value (x_placement, base, values, layout_variation_idx_delta_map);
|
||||||
if (format & yAdvDevice) copy_device (c, base, values++, layout_variation_idx_map);
|
copy_device (c, base, values++, layout_variation_idx_delta_map, new_format, xPlaDevice);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (format & yPlaDevice)
|
||||||
|
{
|
||||||
|
add_delta_to_value (y_placement, base, values, layout_variation_idx_delta_map);
|
||||||
|
copy_device (c, base, values++, layout_variation_idx_delta_map, new_format, yPlaDevice);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (format & xAdvDevice)
|
||||||
|
{
|
||||||
|
add_delta_to_value (x_adv, base, values, layout_variation_idx_delta_map);
|
||||||
|
copy_device (c, base, values++, layout_variation_idx_delta_map, new_format, xAdvDevice);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (format & yAdvDevice)
|
||||||
|
{
|
||||||
|
add_delta_to_value (y_adv, base, values, layout_variation_idx_delta_map);
|
||||||
|
copy_device (c, base, values++, layout_variation_idx_delta_map, new_format, yAdvDevice);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void copy_value (hb_serialize_context_t *c,
|
HBINT16* copy_value (hb_serialize_context_t *c,
|
||||||
unsigned int new_format,
|
unsigned int new_format,
|
||||||
Flags flag,
|
Flags flag,
|
||||||
Value value) const
|
Value value) const
|
||||||
{
|
{
|
||||||
// Filter by new format.
|
// Filter by new format.
|
||||||
if (!(new_format & flag)) return;
|
if (!(new_format & flag)) return nullptr;
|
||||||
c->copy (value);
|
return reinterpret_cast<HBINT16 *> (c->copy (value));
|
||||||
}
|
}
|
||||||
|
|
||||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c,
|
void collect_variation_indices (hb_collect_variation_indices_context_t *c,
|
||||||
|
@ -201,31 +221,40 @@ struct ValueFormat : HBUINT16
|
||||||
if (format & yAdvance) i++;
|
if (format & yAdvance) i++;
|
||||||
if (format & xPlaDevice)
|
if (format & xPlaDevice)
|
||||||
{
|
{
|
||||||
(base + get_device (&(values[i]))).collect_variation_indices (c->layout_variation_indices);
|
(base + get_device (&(values[i]))).collect_variation_indices (c);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (format & ValueFormat::yPlaDevice)
|
if (format & ValueFormat::yPlaDevice)
|
||||||
{
|
{
|
||||||
(base + get_device (&(values[i]))).collect_variation_indices (c->layout_variation_indices);
|
(base + get_device (&(values[i]))).collect_variation_indices (c);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (format & ValueFormat::xAdvDevice)
|
if (format & ValueFormat::xAdvDevice)
|
||||||
{
|
{
|
||||||
|
|
||||||
(base + get_device (&(values[i]))).collect_variation_indices (c->layout_variation_indices);
|
(base + get_device (&(values[i]))).collect_variation_indices (c);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (format & ValueFormat::yAdvDevice)
|
if (format & ValueFormat::yAdvDevice)
|
||||||
{
|
{
|
||||||
|
|
||||||
(base + get_device (&(values[i]))).collect_variation_indices (c->layout_variation_indices);
|
(base + get_device (&(values[i]))).collect_variation_indices (c);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned drop_device_table_flags () const
|
||||||
|
{
|
||||||
|
unsigned format = *this;
|
||||||
|
for (unsigned flag = xPlaDevice; flag <= yAdvDevice; flag = flag << 1)
|
||||||
|
format = format & ~flag;
|
||||||
|
|
||||||
|
return format;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool sanitize_value_devices (hb_sanitize_context_t *c, const void *base, const Value *values) const
|
bool sanitize_value_devices (hb_sanitize_context_t *c, const void *base, const Value *values) const
|
||||||
{
|
{
|
||||||
|
@ -254,9 +283,27 @@ struct ValueFormat : HBUINT16
|
||||||
return *static_cast<const Offset16To<Device> *> (value);
|
return *static_cast<const Offset16To<Device> *> (value);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool copy_device (hb_serialize_context_t *c, const void *base,
|
void add_delta_to_value (HBINT16 *value,
|
||||||
const Value *src_value, const hb_map_t *layout_variation_idx_map) const
|
const void *base,
|
||||||
|
const Value *src_value,
|
||||||
|
const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map) const
|
||||||
{
|
{
|
||||||
|
if (!value) return;
|
||||||
|
unsigned varidx = (base + get_device (src_value)).get_variation_index ();
|
||||||
|
hb_pair_t<unsigned, int> *varidx_delta;
|
||||||
|
if (!layout_variation_idx_delta_map->has (varidx, &varidx_delta)) return;
|
||||||
|
|
||||||
|
*value += hb_second (*varidx_delta);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool copy_device (hb_serialize_context_t *c, const void *base,
|
||||||
|
const Value *src_value,
|
||||||
|
const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map,
|
||||||
|
unsigned int new_format, Flags flag) const
|
||||||
|
{
|
||||||
|
// Filter by new format.
|
||||||
|
if (!(new_format & flag)) return true;
|
||||||
|
|
||||||
Value *dst_value = c->copy (*src_value);
|
Value *dst_value = c->copy (*src_value);
|
||||||
|
|
||||||
if (!dst_value) return false;
|
if (!dst_value) return false;
|
||||||
|
@ -264,7 +311,7 @@ struct ValueFormat : HBUINT16
|
||||||
|
|
||||||
*dst_value = 0;
|
*dst_value = 0;
|
||||||
c->push ();
|
c->push ();
|
||||||
if ((base + get_device (src_value)).copy (c, layout_variation_idx_map))
|
if ((base + get_device (src_value)).copy (c, layout_variation_idx_delta_map))
|
||||||
{
|
{
|
||||||
c->add_link (*dst_value, c->pop_pack ());
|
c->add_link (*dst_value, c->pop_pack ());
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -105,9 +105,10 @@ struct CompositeGlyphRecord
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void apply_delta_to_offsets (const contour_point_t &p_delta)
|
unsigned compile_with_deltas (const contour_point_t &p_delta,
|
||||||
|
char *out) const
|
||||||
{
|
{
|
||||||
HBINT8 *p = &StructAfter<HBINT8> (flags);
|
const HBINT8 *p = &StructAfter<const HBINT8> (flags);
|
||||||
#ifndef HB_NO_BEYOND_64K
|
#ifndef HB_NO_BEYOND_64K
|
||||||
if (flags & GID_IS_24BIT)
|
if (flags & GID_IS_24BIT)
|
||||||
p += HBGlyphID24::static_size;
|
p += HBGlyphID24::static_size;
|
||||||
|
@ -115,17 +116,54 @@ struct CompositeGlyphRecord
|
||||||
#endif
|
#endif
|
||||||
p += HBGlyphID16::static_size;
|
p += HBGlyphID16::static_size;
|
||||||
|
|
||||||
|
unsigned len = get_size ();
|
||||||
|
unsigned len_before_val = (const char *)p - (const char *)this;
|
||||||
if (flags & ARG_1_AND_2_ARE_WORDS)
|
if (flags & ARG_1_AND_2_ARE_WORDS)
|
||||||
{
|
{
|
||||||
HBINT16 *px = reinterpret_cast<HBINT16 *> (p);
|
// no overflow, copy and update value with deltas
|
||||||
px[0] += roundf (p_delta.x);
|
memcpy (out, this, len);
|
||||||
px[1] += roundf (p_delta.y);
|
|
||||||
|
const HBINT16 *px = reinterpret_cast<const HBINT16 *> (p);
|
||||||
|
HBINT16 *o = reinterpret_cast<HBINT16 *> (out + len_before_val);
|
||||||
|
o[0] = px[0] + roundf (p_delta.x);
|
||||||
|
o[1] = px[1] + roundf (p_delta.y);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
p[0] += roundf (p_delta.x);
|
int new_x = p[0] + roundf (p_delta.x);
|
||||||
p[1] += roundf (p_delta.y);
|
int new_y = p[1] + roundf (p_delta.y);
|
||||||
|
if (new_x <= 127 && new_x >= -128 &&
|
||||||
|
new_y <= 127 && new_y >= -128)
|
||||||
|
{
|
||||||
|
memcpy (out, this, len);
|
||||||
|
HBINT8 *o = reinterpret_cast<HBINT8 *> (out + len_before_val);
|
||||||
|
o[0] = new_x;
|
||||||
|
o[1] = new_y;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// int8 overflows after deltas applied
|
||||||
|
memcpy (out, this, len_before_val);
|
||||||
|
|
||||||
|
//update flags
|
||||||
|
CompositeGlyphRecord *o = reinterpret_cast<CompositeGlyphRecord *> (out);
|
||||||
|
o->flags = flags | ARG_1_AND_2_ARE_WORDS;
|
||||||
|
out += len_before_val;
|
||||||
|
|
||||||
|
HBINT16 new_value;
|
||||||
|
new_value = new_x;
|
||||||
|
memcpy (out, &new_value, HBINT16::static_size);
|
||||||
|
out += HBINT16::static_size;
|
||||||
|
|
||||||
|
new_value = new_y;
|
||||||
|
memcpy (out, &new_value, HBINT16::static_size);
|
||||||
|
out += HBINT16::static_size;
|
||||||
|
|
||||||
|
memcpy (out, p+2, len - len_before_val - 2);
|
||||||
|
len += 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -316,32 +354,56 @@ struct CompositeGlyph
|
||||||
const contour_point_vector_t &deltas,
|
const contour_point_vector_t &deltas,
|
||||||
hb_bytes_t &dest_bytes /* OUT */)
|
hb_bytes_t &dest_bytes /* OUT */)
|
||||||
{
|
{
|
||||||
int len = source_bytes.length - GlyphHeader::static_size;
|
if (source_bytes.length <= GlyphHeader::static_size ||
|
||||||
if (len <= 0 || header.numberOfContours != -1)
|
header.numberOfContours != -1)
|
||||||
{
|
{
|
||||||
dest_bytes = hb_bytes_t ();
|
dest_bytes = hb_bytes_t ();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *p = (char *) hb_calloc (len, sizeof (char));
|
unsigned source_len = source_bytes.length - GlyphHeader::static_size;
|
||||||
if (unlikely (!p)) return false;
|
|
||||||
|
|
||||||
memcpy (p, source_bytes.arrayZ + GlyphHeader::static_size, len);
|
/* try to allocate more memories than source glyph bytes
|
||||||
dest_bytes = hb_bytes_t (p, len);
|
* in case that there might be an overflow for int8 value
|
||||||
|
* and we would need to use int16 instead */
|
||||||
|
char *o = (char *) hb_calloc (source_len + source_len/2, sizeof (char));
|
||||||
|
if (unlikely (!o)) return false;
|
||||||
|
|
||||||
auto it = composite_iter_t (dest_bytes, (CompositeGlyphRecord *)p);
|
const CompositeGlyphRecord *c = reinterpret_cast<const CompositeGlyphRecord *> (source_bytes.arrayZ + GlyphHeader::static_size);
|
||||||
|
auto it = composite_iter_t (hb_bytes_t ((const char *)c, source_len), c);
|
||||||
|
|
||||||
unsigned i = 0;
|
char *p = o;
|
||||||
for (auto &component : it)
|
unsigned i = 0, source_comp_len = 0;
|
||||||
|
for (const auto &component : it)
|
||||||
{
|
{
|
||||||
if (!component.is_anchored ())
|
/* last 4 points in deltas are phantom points and should not be included */
|
||||||
|
if (i >= deltas.length - 4) return false;
|
||||||
|
|
||||||
|
unsigned comp_len = component.get_size ();
|
||||||
|
if (component.is_anchored ())
|
||||||
{
|
{
|
||||||
/* last 4 points in deltas are phantom points and should not be included*/
|
memcpy (p, &component, comp_len);
|
||||||
if (i >= deltas.length - 4) return false;
|
p += comp_len;
|
||||||
const_cast<CompositeGlyphRecord &> (component).apply_delta_to_offsets (deltas[i]);
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsigned new_len = component.compile_with_deltas (deltas[i], p);
|
||||||
|
p += new_len;
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
|
source_comp_len += comp_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//copy instructions if any
|
||||||
|
if (source_len > source_comp_len)
|
||||||
|
{
|
||||||
|
unsigned instr_len = source_len - source_comp_len;
|
||||||
|
memcpy (p, (const char *)c + source_comp_len, instr_len);
|
||||||
|
p += instr_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned len = p - o;
|
||||||
|
dest_bytes = hb_bytes_t (o, len);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -101,15 +101,13 @@ struct Glyph
|
||||||
const contour_point_vector_t &all_points,
|
const contour_point_vector_t &all_points,
|
||||||
hb_bytes_t &dest_bytes /* OUT */) const
|
hb_bytes_t &dest_bytes /* OUT */) const
|
||||||
{
|
{
|
||||||
if (all_points.length == 4) //Empty glyph
|
GlyphHeader *glyph_header = nullptr;
|
||||||
|
if (all_points.length > 4)
|
||||||
{
|
{
|
||||||
dest_bytes = hb_bytes_t ();
|
glyph_header = (GlyphHeader *) hb_calloc (1, GlyphHeader::static_size);
|
||||||
return true;
|
if (unlikely (!glyph_header)) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
GlyphHeader *glyph_header = (GlyphHeader *) hb_calloc (1, GlyphHeader::static_size);
|
|
||||||
if (unlikely (!glyph_header)) return false;
|
|
||||||
|
|
||||||
int xMin, xMax;
|
int xMin, xMax;
|
||||||
xMin = xMax = roundf (all_points[0].x);
|
xMin = xMax = roundf (all_points[0].x);
|
||||||
|
|
||||||
|
@ -128,6 +126,11 @@ struct Glyph
|
||||||
|
|
||||||
update_mtx (plan, xMin, yMax, all_points);
|
update_mtx (plan, xMin, yMax, all_points);
|
||||||
|
|
||||||
|
/*for empty glyphs: all_points only include phantom points.
|
||||||
|
*just update metrics and then return */
|
||||||
|
if (all_points.length == 4)
|
||||||
|
return true;
|
||||||
|
|
||||||
glyph_header->numberOfContours = header->numberOfContours;
|
glyph_header->numberOfContours = header->numberOfContours;
|
||||||
glyph_header->xMin = xMin;
|
glyph_header->xMin = xMin;
|
||||||
glyph_header->yMin = yMin;
|
glyph_header->yMin = yMin;
|
||||||
|
@ -145,7 +148,7 @@ struct Glyph
|
||||||
hb_bytes_t &dest_end /* OUT */) const
|
hb_bytes_t &dest_end /* OUT */) const
|
||||||
{
|
{
|
||||||
contour_point_vector_t all_points, deltas;
|
contour_point_vector_t all_points, deltas;
|
||||||
get_points (font, glyf, all_points, &deltas);
|
get_points (font, glyf, all_points, &deltas, false);
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case COMPOSITE:
|
case COMPOSITE:
|
||||||
|
@ -161,8 +164,11 @@ struct Glyph
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
//no need to compile empty glyph (.notdef)
|
/* set empty bytes for empty glyph
|
||||||
return true;
|
* do not use source glyph's pointers */
|
||||||
|
dest_start = hb_bytes_t ();
|
||||||
|
dest_end = hb_bytes_t ();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return compile_header_bytes (plan, all_points, dest_start);
|
return compile_header_bytes (plan, all_points, dest_start);
|
||||||
|
@ -176,6 +182,7 @@ struct Glyph
|
||||||
bool get_points (hb_font_t *font, const accelerator_t &glyf_accelerator,
|
bool get_points (hb_font_t *font, const accelerator_t &glyf_accelerator,
|
||||||
contour_point_vector_t &all_points /* OUT */,
|
contour_point_vector_t &all_points /* OUT */,
|
||||||
contour_point_vector_t *deltas = nullptr, /* OUT */
|
contour_point_vector_t *deltas = nullptr, /* OUT */
|
||||||
|
bool use_my_metrics = true,
|
||||||
bool phantom_only = false,
|
bool phantom_only = false,
|
||||||
unsigned int depth = 0) const
|
unsigned int depth = 0) const
|
||||||
{
|
{
|
||||||
|
@ -264,11 +271,11 @@ struct Glyph
|
||||||
comp_points.reset ();
|
comp_points.reset ();
|
||||||
if (unlikely (!glyf_accelerator.glyph_for_gid (item.get_gid ())
|
if (unlikely (!glyf_accelerator.glyph_for_gid (item.get_gid ())
|
||||||
.get_points (font, glyf_accelerator, comp_points,
|
.get_points (font, glyf_accelerator, comp_points,
|
||||||
deltas, phantom_only, depth + 1)))
|
deltas, use_my_metrics, phantom_only, depth + 1)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* Copy phantom points from component if USE_MY_METRICS flag set */
|
/* Copy phantom points from component if USE_MY_METRICS flag set */
|
||||||
if (item.is_use_my_metrics ())
|
if (use_my_metrics && item.is_use_my_metrics ())
|
||||||
for (unsigned int i = 0; i < PHANTOM_COUNT; i++)
|
for (unsigned int i = 0; i < PHANTOM_COUNT; i++)
|
||||||
phantoms[i] = comp_points[comp_points.length - PHANTOM_COUNT + i];
|
phantoms[i] = comp_points[comp_points.length - PHANTOM_COUNT + i];
|
||||||
|
|
||||||
|
|
|
@ -180,7 +180,7 @@ struct glyf_accelerator_t
|
||||||
contour_point_vector_t all_points;
|
contour_point_vector_t all_points;
|
||||||
|
|
||||||
bool phantom_only = !consumer.is_consuming_contour_points ();
|
bool phantom_only = !consumer.is_consuming_contour_points ();
|
||||||
if (unlikely (!glyph_for_gid (gid).get_points (font, *this, all_points, nullptr, phantom_only)))
|
if (unlikely (!glyph_for_gid (gid).get_points (font, *this, all_points, nullptr, true, phantom_only)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (consumer.is_consuming_contour_points ())
|
if (consumer.is_consuming_contour_points ())
|
||||||
|
|
|
@ -186,6 +186,7 @@ struct hb_subset_layout_context_t :
|
||||||
unsigned lookup_index_count;
|
unsigned lookup_index_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct VariationStore;
|
||||||
struct hb_collect_variation_indices_context_t :
|
struct hb_collect_variation_indices_context_t :
|
||||||
hb_dispatch_context_t<hb_collect_variation_indices_context_t>
|
hb_dispatch_context_t<hb_collect_variation_indices_context_t>
|
||||||
{
|
{
|
||||||
|
@ -194,15 +195,27 @@ struct hb_collect_variation_indices_context_t :
|
||||||
static return_t default_return_value () { return hb_empty_t (); }
|
static return_t default_return_value () { return hb_empty_t (); }
|
||||||
|
|
||||||
hb_set_t *layout_variation_indices;
|
hb_set_t *layout_variation_indices;
|
||||||
|
hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *varidx_delta_map;
|
||||||
|
hb_font_t *font;
|
||||||
|
const VariationStore *var_store;
|
||||||
const hb_set_t *glyph_set;
|
const hb_set_t *glyph_set;
|
||||||
const hb_map_t *gpos_lookups;
|
const hb_map_t *gpos_lookups;
|
||||||
|
float *store_cache;
|
||||||
|
|
||||||
hb_collect_variation_indices_context_t (hb_set_t *layout_variation_indices_,
|
hb_collect_variation_indices_context_t (hb_set_t *layout_variation_indices_,
|
||||||
|
hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *varidx_delta_map_,
|
||||||
|
hb_font_t *font_,
|
||||||
|
const VariationStore *var_store_,
|
||||||
const hb_set_t *glyph_set_,
|
const hb_set_t *glyph_set_,
|
||||||
const hb_map_t *gpos_lookups_) :
|
const hb_map_t *gpos_lookups_,
|
||||||
|
float *store_cache_) :
|
||||||
layout_variation_indices (layout_variation_indices_),
|
layout_variation_indices (layout_variation_indices_),
|
||||||
|
varidx_delta_map (varidx_delta_map_),
|
||||||
|
font (font_),
|
||||||
|
var_store (var_store_),
|
||||||
glyph_set (glyph_set_),
|
glyph_set (glyph_set_),
|
||||||
gpos_lookups (gpos_lookups_) {}
|
gpos_lookups (gpos_lookups_),
|
||||||
|
store_cache (store_cache_) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename OutputArray>
|
template<typename OutputArray>
|
||||||
|
@ -2562,7 +2575,7 @@ struct VariationStore
|
||||||
|
|
||||||
bool serialize (hb_serialize_context_t *c,
|
bool serialize (hb_serialize_context_t *c,
|
||||||
const VariationStore *src,
|
const VariationStore *src,
|
||||||
const hb_array_t <hb_inc_bimap_t> &inner_maps)
|
const hb_array_t <const hb_inc_bimap_t> &inner_maps)
|
||||||
{
|
{
|
||||||
TRACE_SERIALIZE (this);
|
TRACE_SERIALIZE (this);
|
||||||
#ifdef HB_NO_VAR
|
#ifdef HB_NO_VAR
|
||||||
|
@ -2617,7 +2630,7 @@ struct VariationStore
|
||||||
return_trace (true);
|
return_trace (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool subset (hb_subset_context_t *c) const
|
bool subset (hb_subset_context_t *c, const hb_array_t<const hb_inc_bimap_t> &inner_maps) const
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
#ifdef HB_NO_VAR
|
#ifdef HB_NO_VAR
|
||||||
|
@ -2627,22 +2640,7 @@ struct VariationStore
|
||||||
VariationStore *varstore_prime = c->serializer->start_embed<VariationStore> ();
|
VariationStore *varstore_prime = c->serializer->start_embed<VariationStore> ();
|
||||||
if (unlikely (!varstore_prime)) return_trace (false);
|
if (unlikely (!varstore_prime)) return_trace (false);
|
||||||
|
|
||||||
const hb_set_t *variation_indices = c->plan->layout_variation_indices;
|
varstore_prime->serialize (c->serializer, this, inner_maps);
|
||||||
if (variation_indices->is_empty ()) return_trace (false);
|
|
||||||
|
|
||||||
hb_vector_t<hb_inc_bimap_t> inner_maps;
|
|
||||||
inner_maps.resize ((unsigned) dataSets.len);
|
|
||||||
|
|
||||||
for (unsigned idx : c->plan->layout_variation_indices->iter ())
|
|
||||||
{
|
|
||||||
uint16_t major = idx >> 16;
|
|
||||||
uint16_t minor = idx & 0xFFFF;
|
|
||||||
|
|
||||||
if (major >= inner_maps.length)
|
|
||||||
return_trace (false);
|
|
||||||
inner_maps[major].add (minor);
|
|
||||||
}
|
|
||||||
varstore_prime->serialize (c->serializer, this, inner_maps.as_array ());
|
|
||||||
|
|
||||||
return_trace (
|
return_trace (
|
||||||
!c->serializer->in_error()
|
!c->serializer->in_error()
|
||||||
|
@ -3168,28 +3166,36 @@ struct VariationDevice
|
||||||
VariationStore::cache_t *store_cache = nullptr) const
|
VariationStore::cache_t *store_cache = nullptr) const
|
||||||
{ return font->em_scalef_y (get_delta (font, store, store_cache)); }
|
{ return font->em_scalef_y (get_delta (font, store, store_cache)); }
|
||||||
|
|
||||||
VariationDevice* copy (hb_serialize_context_t *c, const hb_map_t *layout_variation_idx_map) const
|
VariationDevice* copy (hb_serialize_context_t *c,
|
||||||
|
const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map) const
|
||||||
{
|
{
|
||||||
TRACE_SERIALIZE (this);
|
TRACE_SERIALIZE (this);
|
||||||
|
if (!layout_variation_idx_delta_map) return_trace (nullptr);
|
||||||
auto snap = c->snapshot ();
|
auto snap = c->snapshot ();
|
||||||
auto *out = c->embed (this);
|
auto *out = c->embed (this);
|
||||||
if (unlikely (!out)) return_trace (nullptr);
|
if (unlikely (!out)) return_trace (nullptr);
|
||||||
if (!layout_variation_idx_map || layout_variation_idx_map->is_empty ()) return_trace (out);
|
|
||||||
|
|
||||||
/* TODO Just get() and bail if NO_VARIATION. Needs to setup the map to return that. */
|
/* TODO Just get() and bail if NO_VARIATION. Needs to setup the map to return that. */
|
||||||
if (!layout_variation_idx_map->has (varIdx))
|
if (!layout_variation_idx_delta_map->has (varIdx))
|
||||||
{
|
{
|
||||||
c->revert (snap);
|
c->revert (snap);
|
||||||
return_trace (nullptr);
|
return_trace (nullptr);
|
||||||
}
|
}
|
||||||
unsigned new_idx = layout_variation_idx_map->get (varIdx);
|
unsigned new_idx = hb_first (layout_variation_idx_delta_map->get (varIdx));
|
||||||
out->varIdx = new_idx;
|
out->varIdx = new_idx;
|
||||||
return_trace (out);
|
return_trace (out);
|
||||||
}
|
}
|
||||||
|
|
||||||
void record_variation_index (hb_set_t *layout_variation_indices) const
|
void collect_variation_index (hb_collect_variation_indices_context_t *c) const
|
||||||
{
|
{
|
||||||
layout_variation_indices->add (varIdx);
|
c->layout_variation_indices->add (varIdx);
|
||||||
|
int delta = 0;
|
||||||
|
if (c->font && c->var_store)
|
||||||
|
delta = roundf (get_delta (c->font, *c->var_store, c->store_cache));
|
||||||
|
|
||||||
|
/* set new varidx to HB_OT_LAYOUT_NO_VARIATIONS_INDEX here, will remap
|
||||||
|
* varidx later*/
|
||||||
|
c->varidx_delta_map->set (varIdx, hb_pair_t<unsigned, int> (HB_OT_LAYOUT_NO_VARIATIONS_INDEX, delta));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sanitize (hb_sanitize_context_t *c) const
|
bool sanitize (hb_sanitize_context_t *c) const
|
||||||
|
@ -3282,7 +3288,8 @@ struct Device
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Device* copy (hb_serialize_context_t *c, const hb_map_t *layout_variation_idx_map=nullptr) const
|
Device* copy (hb_serialize_context_t *c,
|
||||||
|
const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map=nullptr) const
|
||||||
{
|
{
|
||||||
TRACE_SERIALIZE (this);
|
TRACE_SERIALIZE (this);
|
||||||
switch (u.b.format) {
|
switch (u.b.format) {
|
||||||
|
@ -3294,14 +3301,14 @@ struct Device
|
||||||
#endif
|
#endif
|
||||||
#ifndef HB_NO_VAR
|
#ifndef HB_NO_VAR
|
||||||
case 0x8000:
|
case 0x8000:
|
||||||
return_trace (reinterpret_cast<Device *> (u.variation.copy (c, layout_variation_idx_map)));
|
return_trace (reinterpret_cast<Device *> (u.variation.copy (c, layout_variation_idx_delta_map)));
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
return_trace (nullptr);
|
return_trace (nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void collect_variation_indices (hb_set_t *layout_variation_indices) const
|
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
|
||||||
{
|
{
|
||||||
switch (u.b.format) {
|
switch (u.b.format) {
|
||||||
#ifndef HB_NO_HINTING
|
#ifndef HB_NO_HINTING
|
||||||
|
@ -3312,7 +3319,7 @@ struct Device
|
||||||
#endif
|
#endif
|
||||||
#ifndef HB_NO_VAR
|
#ifndef HB_NO_VAR
|
||||||
case 0x8000:
|
case 0x8000:
|
||||||
u.variation.record_variation_index (layout_variation_indices);
|
u.variation.collect_variation_index (c);
|
||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
|
@ -3320,6 +3327,18 @@ struct Device
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned get_variation_index () const
|
||||||
|
{
|
||||||
|
switch (u.b.format) {
|
||||||
|
#ifndef HB_NO_VAR
|
||||||
|
case 0x8000:
|
||||||
|
return u.variation.varIdx;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
return HB_OT_LAYOUT_NO_VARIATIONS_INDEX;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
union {
|
union {
|
||||||
DeviceHeader b;
|
DeviceHeader b;
|
||||||
|
|
|
@ -200,15 +200,34 @@ struct CaretValueFormat3
|
||||||
bool subset (hb_subset_context_t *c) const
|
bool subset (hb_subset_context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
auto *out = c->serializer->embed (this);
|
auto *out = c->serializer->start_embed (*this);
|
||||||
if (unlikely (!out)) return_trace (false);
|
if (unlikely (!out)) return_trace (false);
|
||||||
|
if (!c->serializer->embed (caretValueFormat)) return_trace (false);
|
||||||
|
if (!c->serializer->embed (coordinate)) return_trace (false);
|
||||||
|
|
||||||
|
unsigned varidx = (this+deviceTable).get_variation_index ();
|
||||||
|
if (c->plan->layout_variation_idx_delta_map->has (varidx))
|
||||||
|
{
|
||||||
|
int delta = hb_second (c->plan->layout_variation_idx_delta_map->get (varidx));
|
||||||
|
if (delta != 0)
|
||||||
|
{
|
||||||
|
if (!c->serializer->check_assign (out->coordinate, coordinate + delta, HB_SERIALIZE_ERROR_INT_OVERFLOW))
|
||||||
|
return_trace (false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c->plan->all_axes_pinned)
|
||||||
|
return_trace (c->serializer->check_assign (out->caretValueFormat, 1, HB_SERIALIZE_ERROR_INT_OVERFLOW));
|
||||||
|
|
||||||
|
if (!c->serializer->embed (deviceTable))
|
||||||
|
return_trace (false);
|
||||||
|
|
||||||
return_trace (out->deviceTable.serialize_copy (c->serializer, deviceTable, this, c->serializer->to_bias (out),
|
return_trace (out->deviceTable.serialize_copy (c->serializer, deviceTable, this, c->serializer->to_bias (out),
|
||||||
hb_serialize_context_t::Head, c->plan->layout_variation_idx_map));
|
hb_serialize_context_t::Head, c->plan->layout_variation_idx_delta_map));
|
||||||
}
|
}
|
||||||
|
|
||||||
void collect_variation_indices (hb_set_t *layout_variation_indices) const
|
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
|
||||||
{ (this+deviceTable).collect_variation_indices (layout_variation_indices); }
|
{ (this+deviceTable).collect_variation_indices (c); }
|
||||||
|
|
||||||
bool sanitize (hb_sanitize_context_t *c) const
|
bool sanitize (hb_sanitize_context_t *c) const
|
||||||
{
|
{
|
||||||
|
@ -255,14 +274,14 @@ struct CaretValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void collect_variation_indices (hb_set_t *layout_variation_indices) const
|
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
|
||||||
{
|
{
|
||||||
switch (u.format) {
|
switch (u.format) {
|
||||||
case 1:
|
case 1:
|
||||||
case 2:
|
case 2:
|
||||||
return;
|
return;
|
||||||
case 3:
|
case 3:
|
||||||
u.format3.collect_variation_indices (layout_variation_indices);
|
u.format3.collect_variation_indices (c);
|
||||||
return;
|
return;
|
||||||
default: return;
|
default: return;
|
||||||
}
|
}
|
||||||
|
@ -329,7 +348,7 @@ struct LigGlyph
|
||||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
|
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
|
||||||
{
|
{
|
||||||
for (const Offset16To<CaretValue>& offset : carets.iter ())
|
for (const Offset16To<CaretValue>& offset : carets.iter ())
|
||||||
(this+offset).collect_variation_indices (c->layout_variation_indices);
|
(this+offset).collect_variation_indices (c);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sanitize (hb_sanitize_context_t *c) const
|
bool sanitize (hb_sanitize_context_t *c) const
|
||||||
|
@ -586,7 +605,10 @@ struct GDEFVersion1_2
|
||||||
bool subset_varstore = false;
|
bool subset_varstore = false;
|
||||||
if (version.to_int () >= 0x00010003u)
|
if (version.to_int () >= 0x00010003u)
|
||||||
{
|
{
|
||||||
subset_varstore = out->varStore.serialize_subset (c, varStore, this);
|
if (c->plan->all_axes_pinned)
|
||||||
|
out->varStore = 0;
|
||||||
|
else
|
||||||
|
subset_varstore = out->varStore.serialize_subset (c, varStore, this, c->plan->gdef_varstore_inner_maps.as_array ());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (subset_varstore)
|
if (subset_varstore)
|
||||||
|
@ -846,7 +868,7 @@ struct GDEF
|
||||||
{ get_lig_caret_list ().collect_variation_indices (c); }
|
{ get_lig_caret_list ().collect_variation_indices (c); }
|
||||||
|
|
||||||
void remap_layout_variation_indices (const hb_set_t *layout_variation_indices,
|
void remap_layout_variation_indices (const hb_set_t *layout_variation_indices,
|
||||||
hb_map_t *layout_variation_idx_map /* OUT */) const
|
hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map /* OUT */) const
|
||||||
{
|
{
|
||||||
if (!has_var_store ()) return;
|
if (!has_var_store ()) return;
|
||||||
if (layout_variation_indices->is_empty ()) return;
|
if (layout_variation_indices->is_empty ()) return;
|
||||||
|
@ -864,7 +886,11 @@ struct GDEF
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned new_idx = (new_major << 16) + new_minor;
|
unsigned new_idx = (new_major << 16) + new_minor;
|
||||||
layout_variation_idx_map->set (idx, new_idx);
|
if (!layout_variation_idx_delta_map->has (idx))
|
||||||
|
continue;
|
||||||
|
int delta = hb_second (layout_variation_idx_delta_map->get (idx));
|
||||||
|
|
||||||
|
layout_variation_idx_delta_map->set (idx, hb_pair_t<unsigned, int> (new_idx, delta));
|
||||||
++new_minor;
|
++new_minor;
|
||||||
last_major = major;
|
last_major = major;
|
||||||
}
|
}
|
||||||
|
|
|
@ -175,10 +175,36 @@ struct OS2
|
||||||
int a = (int) floorf (ratio);
|
int a = (int) floorf (ratio);
|
||||||
int b = (int) ceilf (ratio);
|
int b = (int) ceilf (ratio);
|
||||||
|
|
||||||
|
/* follow this maping:
|
||||||
|
* https://docs.microsoft.com/en-us/typography/opentype/spec/os2#uswidthclass
|
||||||
|
*/
|
||||||
|
if (b <= 6) // 50-125
|
||||||
|
{
|
||||||
|
if (a == b) return a + 1.0f;
|
||||||
|
}
|
||||||
|
else if (b == 7) // no mapping for 137.5
|
||||||
|
{
|
||||||
|
a = 6;
|
||||||
|
b = 8;
|
||||||
|
}
|
||||||
|
else if (b == 8)
|
||||||
|
{
|
||||||
|
if (a == b) return 8.0f; // 150
|
||||||
|
a = 6;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (a == b && a == 12) return 9.0f; //200
|
||||||
|
b = 12;
|
||||||
|
a = 8;
|
||||||
|
}
|
||||||
|
|
||||||
float va = 50 + a * 12.5f;
|
float va = 50 + a * 12.5f;
|
||||||
float vb = 50 + b * 12.5f;
|
float vb = 50 + b * 12.5f;
|
||||||
|
|
||||||
return a + 1.0f + (float) (b - a) * (width - va) / (vb - va);
|
float ret = a + (width - va) / (vb - va);
|
||||||
|
if (a <= 6) ret += 1.0f;
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool subset (hb_subset_context_t *c) const
|
bool subset (hb_subset_context_t *c) const
|
||||||
|
|
|
@ -269,11 +269,46 @@ _closure_glyphs_lookups_features (hb_subset_plan_t *plan,
|
||||||
|
|
||||||
#ifndef HB_NO_VAR
|
#ifndef HB_NO_VAR
|
||||||
static inline void
|
static inline void
|
||||||
_collect_layout_variation_indices (hb_subset_plan_t* plan,
|
_generate_varstore_inner_maps (const hb_set_t& varidx_set,
|
||||||
const hb_set_t *glyphset,
|
unsigned subtable_count,
|
||||||
const hb_map_t *gpos_lookups,
|
hb_vector_t<hb_inc_bimap_t> &inner_maps /* OUT */)
|
||||||
hb_set_t *layout_variation_indices,
|
{
|
||||||
hb_map_t *layout_variation_idx_map)
|
if (varidx_set.is_empty () || subtable_count == 0) return;
|
||||||
|
|
||||||
|
inner_maps.resize (subtable_count);
|
||||||
|
for (unsigned idx : varidx_set)
|
||||||
|
{
|
||||||
|
uint16_t major = idx >> 16;
|
||||||
|
uint16_t minor = idx & 0xFFFF;
|
||||||
|
|
||||||
|
if (major >= subtable_count)
|
||||||
|
continue;
|
||||||
|
inner_maps[major].add (minor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline hb_font_t*
|
||||||
|
_get_hb_font_with_variations (const hb_subset_plan_t *plan)
|
||||||
|
{
|
||||||
|
hb_font_t *font = hb_font_create (plan->source);
|
||||||
|
|
||||||
|
hb_vector_t<hb_variation_t> vars;
|
||||||
|
vars.alloc (plan->user_axes_location->get_population ());
|
||||||
|
|
||||||
|
for (auto _ : *plan->user_axes_location)
|
||||||
|
{
|
||||||
|
hb_variation_t var;
|
||||||
|
var.tag = _.first;
|
||||||
|
var.value = _.second;
|
||||||
|
vars.push (var);
|
||||||
|
}
|
||||||
|
|
||||||
|
hb_font_set_variations (font, vars.arrayZ, plan->user_axes_location->get_population ());
|
||||||
|
return font;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
_collect_layout_variation_indices (hb_subset_plan_t* plan)
|
||||||
{
|
{
|
||||||
hb_blob_ptr_t<OT::GDEF> gdef = plan->source_table<OT::GDEF> ();
|
hb_blob_ptr_t<OT::GDEF> gdef = plan->source_table<OT::GDEF> ();
|
||||||
hb_blob_ptr_t<GPOS> gpos = plan->source_table<GPOS> ();
|
hb_blob_ptr_t<GPOS> gpos = plan->source_table<GPOS> ();
|
||||||
|
@ -284,13 +319,40 @@ _collect_layout_variation_indices (hb_subset_plan_t* plan,
|
||||||
gpos.destroy ();
|
gpos.destroy ();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
OT::hb_collect_variation_indices_context_t c (layout_variation_indices, glyphset, gpos_lookups);
|
|
||||||
|
const OT::VariationStore *var_store = nullptr;
|
||||||
|
hb_set_t varidx_set;
|
||||||
|
hb_font_t *font = nullptr;
|
||||||
|
float *store_cache = nullptr;
|
||||||
|
bool collect_delta = plan->pinned_at_default ? false : true;
|
||||||
|
if (collect_delta)
|
||||||
|
{
|
||||||
|
font = _get_hb_font_with_variations (plan);
|
||||||
|
if (gdef->has_var_store ())
|
||||||
|
{
|
||||||
|
var_store = &(gdef->get_var_store ());
|
||||||
|
store_cache = var_store->create_cache ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OT::hb_collect_variation_indices_context_t c (&varidx_set,
|
||||||
|
plan->layout_variation_idx_delta_map,
|
||||||
|
font, var_store,
|
||||||
|
plan->_glyphset_gsub,
|
||||||
|
plan->gpos_lookups,
|
||||||
|
store_cache);
|
||||||
gdef->collect_variation_indices (&c);
|
gdef->collect_variation_indices (&c);
|
||||||
|
|
||||||
if (hb_ot_layout_has_positioning (plan->source))
|
if (hb_ot_layout_has_positioning (plan->source))
|
||||||
gpos->collect_variation_indices (&c);
|
gpos->collect_variation_indices (&c);
|
||||||
|
|
||||||
gdef->remap_layout_variation_indices (layout_variation_indices, layout_variation_idx_map);
|
hb_font_destroy (font);
|
||||||
|
var_store->destroy_cache (store_cache);
|
||||||
|
|
||||||
|
gdef->remap_layout_variation_indices (&varidx_set, plan->layout_variation_idx_delta_map);
|
||||||
|
|
||||||
|
unsigned subtable_count = gdef->has_var_store () ? gdef->get_var_store ().get_sub_table_count () : 0;
|
||||||
|
_generate_varstore_inner_maps (varidx_set, subtable_count, plan->gdef_varstore_inner_maps);
|
||||||
|
|
||||||
gdef.destroy ();
|
gdef.destroy ();
|
||||||
gpos.destroy ();
|
gpos.destroy ();
|
||||||
|
@ -506,11 +568,7 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
|
||||||
|
|
||||||
#ifndef HB_NO_VAR
|
#ifndef HB_NO_VAR
|
||||||
if (close_over_gdef)
|
if (close_over_gdef)
|
||||||
_collect_layout_variation_indices (plan,
|
_collect_layout_variation_indices (plan);
|
||||||
plan->_glyphset_gsub,
|
|
||||||
plan->gpos_lookups,
|
|
||||||
plan->layout_variation_indices,
|
|
||||||
plan->layout_variation_idx_map);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -682,8 +740,8 @@ hb_subset_plan_create_or_fail (hb_face_t *face,
|
||||||
plan->gpos_features = hb_map_create ();
|
plan->gpos_features = hb_map_create ();
|
||||||
plan->colrv1_layers = hb_map_create ();
|
plan->colrv1_layers = hb_map_create ();
|
||||||
plan->colr_palettes = hb_map_create ();
|
plan->colr_palettes = hb_map_create ();
|
||||||
plan->layout_variation_indices = hb_set_create ();
|
plan->check_success (plan->layout_variation_idx_delta_map = hb_hashmap_create<unsigned, hb_pair_t<unsigned, int>> ());
|
||||||
plan->layout_variation_idx_map = hb_map_create ();
|
plan->gdef_varstore_inner_maps.init ();
|
||||||
|
|
||||||
plan->check_success (plan->sanitized_table_cache = hb_hashmap_create<hb_tag_t, hb::unique_ptr<hb_blob_t>> ());
|
plan->check_success (plan->sanitized_table_cache = hb_hashmap_create<hb_tag_t, hb::unique_ptr<hb_blob_t>> ());
|
||||||
plan->check_success (plan->axes_location = hb_hashmap_create<hb_tag_t, int> ());
|
plan->check_success (plan->axes_location = hb_hashmap_create<hb_tag_t, int> ());
|
||||||
|
@ -701,6 +759,10 @@ hb_subset_plan_create_or_fail (hb_face_t *face,
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef HB_NO_VAR
|
||||||
|
_normalize_axes_location (face, plan);
|
||||||
|
#endif
|
||||||
|
|
||||||
_populate_unicodes_to_retain (input->sets.unicodes, input->sets.glyphs, plan);
|
_populate_unicodes_to_retain (input->sets.unicodes, input->sets.glyphs, plan);
|
||||||
|
|
||||||
_populate_gids_to_retain (plan,
|
_populate_gids_to_retain (plan,
|
||||||
|
@ -728,10 +790,6 @@ hb_subset_plan_create_or_fail (hb_face_t *face,
|
||||||
plan->glyph_map->get(plan->unicode_to_new_gid_list.arrayZ[i].second);
|
plan->glyph_map->get(plan->unicode_to_new_gid_list.arrayZ[i].second);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef HB_NO_VAR
|
|
||||||
_normalize_axes_location (face, plan);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
_nameid_closure (face, plan->name_ids, plan->all_axes_pinned, plan->user_axes_location);
|
_nameid_closure (face, plan->name_ids, plan->all_axes_pinned, plan->user_axes_location);
|
||||||
if (unlikely (plan->in_error ())) {
|
if (unlikely (plan->in_error ())) {
|
||||||
hb_subset_plan_destroy (plan);
|
hb_subset_plan_destroy (plan);
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include "hb-subset-input.hh"
|
#include "hb-subset-input.hh"
|
||||||
|
|
||||||
#include "hb-map.hh"
|
#include "hb-map.hh"
|
||||||
|
#include "hb-bimap.hh"
|
||||||
#include "hb-set.hh"
|
#include "hb-set.hh"
|
||||||
|
|
||||||
struct hb_subset_plan_t
|
struct hb_subset_plan_t
|
||||||
|
@ -66,8 +67,6 @@ struct hb_subset_plan_t
|
||||||
hb_map_destroy (gpos_features);
|
hb_map_destroy (gpos_features);
|
||||||
hb_map_destroy (colrv1_layers);
|
hb_map_destroy (colrv1_layers);
|
||||||
hb_map_destroy (colr_palettes);
|
hb_map_destroy (colr_palettes);
|
||||||
hb_set_destroy (layout_variation_indices);
|
|
||||||
hb_map_destroy (layout_variation_idx_map);
|
|
||||||
|
|
||||||
hb_hashmap_destroy (gsub_langsys);
|
hb_hashmap_destroy (gsub_langsys);
|
||||||
hb_hashmap_destroy (gpos_langsys);
|
hb_hashmap_destroy (gpos_langsys);
|
||||||
|
@ -75,6 +74,7 @@ struct hb_subset_plan_t
|
||||||
hb_hashmap_destroy (sanitized_table_cache);
|
hb_hashmap_destroy (sanitized_table_cache);
|
||||||
hb_hashmap_destroy (hmtx_map);
|
hb_hashmap_destroy (hmtx_map);
|
||||||
hb_hashmap_destroy (vmtx_map);
|
hb_hashmap_destroy (vmtx_map);
|
||||||
|
hb_hashmap_destroy (layout_variation_idx_delta_map);
|
||||||
|
|
||||||
if (user_axes_location)
|
if (user_axes_location)
|
||||||
{
|
{
|
||||||
|
@ -147,10 +147,11 @@ struct hb_subset_plan_t
|
||||||
hb_map_t *colrv1_layers;
|
hb_map_t *colrv1_layers;
|
||||||
hb_map_t *colr_palettes;
|
hb_map_t *colr_palettes;
|
||||||
|
|
||||||
//The set of layout item variation store delta set indices to be retained
|
//Old layout item variation index -> (New varidx, delta) mapping
|
||||||
hb_set_t *layout_variation_indices;
|
hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map;
|
||||||
//Old -> New layout item variation store delta set index mapping
|
|
||||||
hb_map_t *layout_variation_idx_map;
|
//gdef varstore retained varidx mapping
|
||||||
|
hb_vector_t<hb_inc_bimap_t> gdef_varstore_inner_maps;
|
||||||
|
|
||||||
hb_hashmap_t<hb_tag_t, hb::unique_ptr<hb_blob_t>>* sanitized_table_cache;
|
hb_hashmap_t<hb_tag_t, hb::unique_ptr<hb_blob_t>>* sanitized_table_cache;
|
||||||
//normalized axes location map
|
//normalized axes location map
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,12 @@
|
||||||
|
FONTS:
|
||||||
|
Roboto-Variable.ttf
|
||||||
|
|
||||||
|
PROFILES:
|
||||||
|
default.txt
|
||||||
|
|
||||||
|
SUBSETS:
|
||||||
|
*
|
||||||
|
|
||||||
|
INSTANCES:
|
||||||
|
wght=150,wdth=80
|
||||||
|
wght=300,wdth=90
|
|
@ -34,9 +34,6 @@ def generate_expected_output(input_file, unicodes, profile_flags, instance_flags
|
||||||
"--drop-tables-=sbix",
|
"--drop-tables-=sbix",
|
||||||
"--unicodes=%s" % unicodes,
|
"--unicodes=%s" % unicodes,
|
||||||
"--output-file=%s" % fonttools_path])
|
"--output-file=%s" % fonttools_path])
|
||||||
#TODO: remove the drop later as instancing support is added to GPOS/GDEF.
|
|
||||||
if instance_flags:
|
|
||||||
args.extend(["--drop-tables+=GPOS,GDEF"])
|
|
||||||
args.extend(profile_flags)
|
args.extend(profile_flags)
|
||||||
check_call(args)
|
check_call(args)
|
||||||
|
|
||||||
|
@ -66,10 +63,8 @@ def generate_expected_output(input_file, unicodes, profile_flags, instance_flags
|
||||||
"--drop-tables+=DSIG",
|
"--drop-tables+=DSIG",
|
||||||
"--drop-tables-=sbix"]
|
"--drop-tables-=sbix"]
|
||||||
args.extend(profile_flags)
|
args.extend(profile_flags)
|
||||||
#TODO: remove the drop later as instancing support is added to GPOS/GDEF.
|
|
||||||
if instance_flags:
|
if instance_flags:
|
||||||
args.extend(["--drop-tables+=GDEF,GPOS",
|
args.extend(["--instance=%s" % ','.join(instance_flags)])
|
||||||
"--instance=%s" % ','.join(instance_flags)])
|
|
||||||
check_call(args)
|
check_call(args)
|
||||||
|
|
||||||
with io.StringIO () as fp:
|
with io.StringIO () as fp:
|
||||||
|
|
|
@ -53,6 +53,7 @@ tests = [
|
||||||
# instacing tests, enable when --instance is not experimental
|
# instacing tests, enable when --instance is not experimental
|
||||||
# 'pin_all_at_default',
|
# 'pin_all_at_default',
|
||||||
# 'instantiate_glyf',
|
# 'instantiate_glyf',
|
||||||
|
# 'full_instance',
|
||||||
]
|
]
|
||||||
|
|
||||||
repack_tests = [
|
repack_tests = [
|
||||||
|
|
|
@ -56,8 +56,7 @@ def run_test (test, should_check_ots):
|
||||||
"--drop-tables-=sbix"]
|
"--drop-tables-=sbix"]
|
||||||
cli_args.extend (test.get_profile_flags ())
|
cli_args.extend (test.get_profile_flags ())
|
||||||
if test.get_instance_flags ():
|
if test.get_instance_flags ():
|
||||||
cli_args.extend (["--drop-tables+=GPOS,GDEF",
|
cli_args.extend (["--instance=%s" % ','.join(test.get_instance_flags ())])
|
||||||
"--instance=%s" % ','.join(test.get_instance_flags ())])
|
|
||||||
ret = subset_cmd (cli_args)
|
ret = subset_cmd (cli_args)
|
||||||
|
|
||||||
if ret != "success":
|
if ret != "success":
|
||||||
|
|
Loading…
Reference in New Issue