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.format2.copy (c->serializer))));
|
||||
case 3: return_trace (bool (reinterpret_cast<Anchor *> (u.format3.copy (c->serializer,
|
||||
c->plan->layout_variation_idx_map))));
|
||||
case 3: return_trace (u.format3.subset (c));
|
||||
default:return_trace (false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,24 +41,54 @@ struct AnchorFormat3
|
|||
*y += (this+yDeviceTable).get_y_delta (font, c->var_store, c->var_store_cache);
|
||||
}
|
||||
|
||||
AnchorFormat3* copy (hb_serialize_context_t *c,
|
||||
const hb_map_t *layout_variation_idx_map) const
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (!layout_variation_idx_map) return_trace (nullptr);
|
||||
TRACE_SUBSET (this);
|
||||
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);
|
||||
if (unlikely (!out)) return_trace (nullptr);
|
||||
unsigned x_varidx = xDeviceTable ? (this+xDeviceTable).get_variation_index () : HB_OT_LAYOUT_NO_VARIATIONS_INDEX;
|
||||
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);
|
||||
out->yDeviceTable.serialize_copy (c, yDeviceTable, 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;
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
(this+xDeviceTable).collect_variation_indices (c);
|
||||
(this+yDeviceTable).collect_variation_indices (c);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -22,7 +22,8 @@ template<typename Iterator, typename SrcLookup>
|
|||
static void SinglePos_serialize (hb_serialize_context_t *c,
|
||||
const SrcLookup *src,
|
||||
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;
|
||||
}
|
||||
|
||||
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_zip (this+coverage, pairSet)
|
||||
|
|
|
@ -274,13 +274,19 @@ struct PairPosFormat2_4
|
|||
out->valueFormat1 = newFormats.first;
|
||||
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 class2_idx : + hb_range ((unsigned) class2Count) | hb_filter (klass2_map))
|
||||
{
|
||||
unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * (len1 + len2);
|
||||
valueFormat1.copy_values (c->serializer, newFormats.first, this, &values[idx], c->plan->layout_variation_idx_map);
|
||||
valueFormat2.copy_values (c->serializer, newFormats.second, this, &values[idx + len1], c->plan->layout_variation_idx_map);
|
||||
valueFormat1.copy_values (c->serializer, out->valueFormat1, this, &values[idx], c->plan->layout_variation_idx_delta_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,
|
||||
len1,
|
||||
&glyph_map,
|
||||
c->plan->layout_variation_idx_map
|
||||
c->plan->layout_variation_idx_delta_map
|
||||
};
|
||||
|
||||
const PairValueRecord *record = &firstPairValueRecord;
|
||||
|
|
|
@ -34,7 +34,7 @@ struct PairValueRecord
|
|||
const ValueFormat *newFormats;
|
||||
unsigned len1; /* valueFormats[0].get_len() */
|
||||
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,
|
||||
|
@ -50,12 +50,12 @@ struct PairValueRecord
|
|||
closure->valueFormats[0].copy_values (s,
|
||||
closure->newFormats[0],
|
||||
closure->base, &values[0],
|
||||
closure->layout_variation_idx_map);
|
||||
closure->layout_variation_idx_delta_map);
|
||||
closure->valueFormats[1].copy_values (s,
|
||||
closure->newFormats[1],
|
||||
closure->base,
|
||||
&values[closure->len1],
|
||||
closure->layout_variation_idx_map);
|
||||
closure->layout_variation_idx_delta_map);
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
|
|
@ -38,12 +38,16 @@ struct SinglePos
|
|||
void serialize (hb_serialize_context_t *c,
|
||||
const SrcLookup* src,
|
||||
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;
|
||||
unsigned format = 2;
|
||||
ValueFormat new_format = src->get_value_format ();
|
||||
|
||||
if (all_axes_pinned)
|
||||
new_format = new_format.drop_device_table_flags ();
|
||||
|
||||
if (glyph_val_iter_pairs)
|
||||
format = get_format (glyph_val_iter_pairs);
|
||||
|
||||
|
@ -53,13 +57,13 @@ struct SinglePos
|
|||
src,
|
||||
glyph_val_iter_pairs,
|
||||
new_format,
|
||||
layout_variation_idx_map);
|
||||
layout_variation_idx_delta_map);
|
||||
return;
|
||||
case 2: u.format2.serialize (c,
|
||||
src,
|
||||
glyph_val_iter_pairs,
|
||||
new_format,
|
||||
layout_variation_idx_map);
|
||||
layout_variation_idx_delta_map);
|
||||
return;
|
||||
default:return;
|
||||
}
|
||||
|
@ -84,8 +88,9 @@ static void
|
|||
SinglePos_serialize (hb_serialize_context_t *c,
|
||||
const SrcLookup *src,
|
||||
Iterator it,
|
||||
const hb_map_t *layout_variation_idx_map)
|
||||
{ c->start_embed<SinglePos> ()->serialize (c, src, it, layout_variation_idx_map); }
|
||||
const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_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,
|
||||
Iterator it,
|
||||
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->check_assign (valueFormat,
|
||||
|
@ -96,7 +96,7 @@ struct SinglePosFormat1
|
|||
|
||||
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
|
||||
// be the same.
|
||||
break;
|
||||
|
@ -126,7 +126,7 @@ struct SinglePosFormat1
|
|||
;
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -99,7 +99,7 @@ struct SinglePosFormat2
|
|||
const SrcLookup *src,
|
||||
Iterator it,
|
||||
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);
|
||||
if (unlikely (!out)) return;
|
||||
|
@ -109,7 +109,7 @@ struct SinglePosFormat2
|
|||
+ it
|
||||
| hb_map (hb_second)
|
||||
| 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 =
|
||||
|
@ -141,7 +141,7 @@ struct SinglePosFormat2
|
|||
;
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -163,30 +163,50 @@ struct ValueFormat : HBUINT16
|
|||
unsigned int new_format,
|
||||
const void *base,
|
||||
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;
|
||||
if (!format) return;
|
||||
|
||||
if (format & xPlacement) copy_value (c, new_format, xPlacement, *values++);
|
||||
if (format & yPlacement) copy_value (c, new_format, yPlacement, *values++);
|
||||
if (format & xAdvance) copy_value (c, new_format, xAdvance, *values++);
|
||||
if (format & yAdvance) copy_value (c, new_format, yAdvance, *values++);
|
||||
HBINT16 *x_placement = nullptr, *y_placement = nullptr, *x_adv = nullptr, *y_adv = nullptr;
|
||||
if (format & xPlacement) x_placement = copy_value (c, new_format, xPlacement, *values++);
|
||||
if (format & yPlacement) y_placement = copy_value (c, new_format, yPlacement, *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 & yPlaDevice) copy_device (c, base, values++, layout_variation_idx_map);
|
||||
if (format & xAdvDevice) copy_device (c, base, values++, layout_variation_idx_map);
|
||||
if (format & yAdvDevice) copy_device (c, base, values++, layout_variation_idx_map);
|
||||
if (format & xPlaDevice)
|
||||
{
|
||||
add_delta_to_value (x_placement, base, values, layout_variation_idx_delta_map);
|
||||
copy_device (c, base, values++, layout_variation_idx_delta_map, new_format, xPlaDevice);
|
||||
}
|
||||
|
||||
void copy_value (hb_serialize_context_t *c,
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
HBINT16* copy_value (hb_serialize_context_t *c,
|
||||
unsigned int new_format,
|
||||
Flags flag,
|
||||
Value value) const
|
||||
{
|
||||
// Filter by new format.
|
||||
if (!(new_format & flag)) return;
|
||||
c->copy (value);
|
||||
if (!(new_format & flag)) return nullptr;
|
||||
return reinterpret_cast<HBINT16 *> (c->copy (value));
|
||||
}
|
||||
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c,
|
||||
|
@ -201,31 +221,40 @@ struct ValueFormat : HBUINT16
|
|||
if (format & yAdvance) i++;
|
||||
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++;
|
||||
}
|
||||
|
||||
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++;
|
||||
}
|
||||
|
||||
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++;
|
||||
}
|
||||
|
||||
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++;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned drop_device_table_flags () const
|
||||
{
|
||||
unsigned format = *this;
|
||||
for (unsigned flag = xPlaDevice; flag <= yAdvDevice; flag = flag << 1)
|
||||
format = format & ~flag;
|
||||
|
||||
return format;
|
||||
}
|
||||
|
||||
private:
|
||||
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);
|
||||
}
|
||||
|
||||
bool copy_device (hb_serialize_context_t *c, const void *base,
|
||||
const Value *src_value, const hb_map_t *layout_variation_idx_map) const
|
||||
void add_delta_to_value (HBINT16 *value,
|
||||
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);
|
||||
|
||||
if (!dst_value) return false;
|
||||
|
@ -264,7 +311,7 @@ struct ValueFormat : HBUINT16
|
|||
|
||||
*dst_value = 0;
|
||||
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 ());
|
||||
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
|
||||
if (flags & GID_IS_24BIT)
|
||||
p += HBGlyphID24::static_size;
|
||||
|
@ -115,17 +116,54 @@ struct CompositeGlyphRecord
|
|||
#endif
|
||||
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)
|
||||
{
|
||||
HBINT16 *px = reinterpret_cast<HBINT16 *> (p);
|
||||
px[0] += roundf (p_delta.x);
|
||||
px[1] += roundf (p_delta.y);
|
||||
// no overflow, copy and update value with deltas
|
||||
memcpy (out, this, len);
|
||||
|
||||
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
|
||||
{
|
||||
p[0] += roundf (p_delta.x);
|
||||
p[1] += roundf (p_delta.y);
|
||||
int new_x = p[0] + roundf (p_delta.x);
|
||||
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:
|
||||
|
@ -316,32 +354,56 @@ struct CompositeGlyph
|
|||
const contour_point_vector_t &deltas,
|
||||
hb_bytes_t &dest_bytes /* OUT */)
|
||||
{
|
||||
int len = source_bytes.length - GlyphHeader::static_size;
|
||||
if (len <= 0 || header.numberOfContours != -1)
|
||||
if (source_bytes.length <= GlyphHeader::static_size ||
|
||||
header.numberOfContours != -1)
|
||||
{
|
||||
dest_bytes = hb_bytes_t ();
|
||||
return true;
|
||||
}
|
||||
|
||||
char *p = (char *) hb_calloc (len, sizeof (char));
|
||||
if (unlikely (!p)) return false;
|
||||
unsigned source_len = source_bytes.length - GlyphHeader::static_size;
|
||||
|
||||
memcpy (p, source_bytes.arrayZ + GlyphHeader::static_size, len);
|
||||
dest_bytes = hb_bytes_t (p, len);
|
||||
/* try to allocate more memories than source glyph bytes
|
||||
* 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;
|
||||
for (auto &component : it)
|
||||
char *p = o;
|
||||
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*/
|
||||
/* last 4 points in deltas are phantom points and should not be included */
|
||||
if (i >= deltas.length - 4) return false;
|
||||
const_cast<CompositeGlyphRecord &> (component).apply_delta_to_offsets (deltas[i]);
|
||||
|
||||
unsigned comp_len = component.get_size ();
|
||||
if (component.is_anchored ())
|
||||
{
|
||||
memcpy (p, &component, comp_len);
|
||||
p += comp_len;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned new_len = component.compile_with_deltas (deltas[i], p);
|
||||
p += new_len;
|
||||
}
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -101,14 +101,12 @@ struct Glyph
|
|||
const contour_point_vector_t &all_points,
|
||||
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 ();
|
||||
return true;
|
||||
}
|
||||
|
||||
GlyphHeader *glyph_header = (GlyphHeader *) hb_calloc (1, GlyphHeader::static_size);
|
||||
glyph_header = (GlyphHeader *) hb_calloc (1, GlyphHeader::static_size);
|
||||
if (unlikely (!glyph_header)) return false;
|
||||
}
|
||||
|
||||
int xMin, xMax;
|
||||
xMin = xMax = roundf (all_points[0].x);
|
||||
|
@ -128,6 +126,11 @@ struct Glyph
|
|||
|
||||
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->xMin = xMin;
|
||||
glyph_header->yMin = yMin;
|
||||
|
@ -145,7 +148,7 @@ struct Glyph
|
|||
hb_bytes_t &dest_end /* OUT */) const
|
||||
{
|
||||
contour_point_vector_t all_points, deltas;
|
||||
get_points (font, glyf, all_points, &deltas);
|
||||
get_points (font, glyf, all_points, &deltas, false);
|
||||
|
||||
switch (type) {
|
||||
case COMPOSITE:
|
||||
|
@ -161,8 +164,11 @@ struct Glyph
|
|||
return false;
|
||||
break;
|
||||
default:
|
||||
//no need to compile empty glyph (.notdef)
|
||||
return true;
|
||||
/* set empty bytes for empty glyph
|
||||
* 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);
|
||||
|
@ -176,6 +182,7 @@ struct Glyph
|
|||
bool get_points (hb_font_t *font, const accelerator_t &glyf_accelerator,
|
||||
contour_point_vector_t &all_points /* OUT */,
|
||||
contour_point_vector_t *deltas = nullptr, /* OUT */
|
||||
bool use_my_metrics = true,
|
||||
bool phantom_only = false,
|
||||
unsigned int depth = 0) const
|
||||
{
|
||||
|
@ -264,11 +271,11 @@ struct Glyph
|
|||
comp_points.reset ();
|
||||
if (unlikely (!glyf_accelerator.glyph_for_gid (item.get_gid ())
|
||||
.get_points (font, glyf_accelerator, comp_points,
|
||||
deltas, phantom_only, depth + 1)))
|
||||
deltas, use_my_metrics, phantom_only, depth + 1)))
|
||||
return false;
|
||||
|
||||
/* 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++)
|
||||
phantoms[i] = comp_points[comp_points.length - PHANTOM_COUNT + i];
|
||||
|
||||
|
|
|
@ -180,7 +180,7 @@ struct glyf_accelerator_t
|
|||
contour_point_vector_t all_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;
|
||||
|
||||
if (consumer.is_consuming_contour_points ())
|
||||
|
|
|
@ -186,6 +186,7 @@ struct hb_subset_layout_context_t :
|
|||
unsigned lookup_index_count;
|
||||
};
|
||||
|
||||
struct VariationStore;
|
||||
struct 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 (); }
|
||||
|
||||
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_map_t *gpos_lookups;
|
||||
float *store_cache;
|
||||
|
||||
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_map_t *gpos_lookups_) :
|
||||
const hb_map_t *gpos_lookups_,
|
||||
float *store_cache_) :
|
||||
layout_variation_indices (layout_variation_indices_),
|
||||
varidx_delta_map (varidx_delta_map_),
|
||||
font (font_),
|
||||
var_store (var_store_),
|
||||
glyph_set (glyph_set_),
|
||||
gpos_lookups (gpos_lookups_) {}
|
||||
gpos_lookups (gpos_lookups_),
|
||||
store_cache (store_cache_) {}
|
||||
};
|
||||
|
||||
template<typename OutputArray>
|
||||
|
@ -2562,7 +2575,7 @@ struct VariationStore
|
|||
|
||||
bool serialize (hb_serialize_context_t *c,
|
||||
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);
|
||||
#ifdef HB_NO_VAR
|
||||
|
@ -2617,7 +2630,7 @@ struct VariationStore
|
|||
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);
|
||||
#ifdef HB_NO_VAR
|
||||
|
@ -2627,22 +2640,7 @@ struct VariationStore
|
|||
VariationStore *varstore_prime = c->serializer->start_embed<VariationStore> ();
|
||||
if (unlikely (!varstore_prime)) return_trace (false);
|
||||
|
||||
const hb_set_t *variation_indices = c->plan->layout_variation_indices;
|
||||
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 ());
|
||||
varstore_prime->serialize (c->serializer, this, inner_maps);
|
||||
|
||||
return_trace (
|
||||
!c->serializer->in_error()
|
||||
|
@ -3168,28 +3166,36 @@ struct VariationDevice
|
|||
VariationStore::cache_t *store_cache = nullptr) const
|
||||
{ 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);
|
||||
if (!layout_variation_idx_delta_map) return_trace (nullptr);
|
||||
auto snap = c->snapshot ();
|
||||
auto *out = c->embed (this);
|
||||
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. */
|
||||
if (!layout_variation_idx_map->has (varIdx))
|
||||
if (!layout_variation_idx_delta_map->has (varIdx))
|
||||
{
|
||||
c->revert (snap);
|
||||
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;
|
||||
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
|
||||
|
@ -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);
|
||||
switch (u.b.format) {
|
||||
|
@ -3294,14 +3301,14 @@ struct Device
|
|||
#endif
|
||||
#ifndef HB_NO_VAR
|
||||
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
|
||||
default:
|
||||
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) {
|
||||
#ifndef HB_NO_HINTING
|
||||
|
@ -3312,7 +3319,7 @@ struct Device
|
|||
#endif
|
||||
#ifndef HB_NO_VAR
|
||||
case 0x8000:
|
||||
u.variation.record_variation_index (layout_variation_indices);
|
||||
u.variation.collect_variation_index (c);
|
||||
return;
|
||||
#endif
|
||||
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:
|
||||
union {
|
||||
DeviceHeader b;
|
||||
|
|
|
@ -200,15 +200,34 @@ struct CaretValueFormat3
|
|||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (this);
|
||||
auto *out = c->serializer->start_embed (*this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
if (!c->serializer->embed (caretValueFormat)) return_trace (false);
|
||||
if (!c->serializer->embed (coordinate)) return_trace (false);
|
||||
|
||||
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));
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void collect_variation_indices (hb_set_t *layout_variation_indices) const
|
||||
{ (this+deviceTable).collect_variation_indices (layout_variation_indices); }
|
||||
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),
|
||||
hb_serialize_context_t::Head, c->plan->layout_variation_idx_delta_map));
|
||||
}
|
||||
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
|
||||
{ (this+deviceTable).collect_variation_indices (c); }
|
||||
|
||||
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) {
|
||||
case 1:
|
||||
case 2:
|
||||
return;
|
||||
case 3:
|
||||
u.format3.collect_variation_indices (layout_variation_indices);
|
||||
u.format3.collect_variation_indices (c);
|
||||
return;
|
||||
default: return;
|
||||
}
|
||||
|
@ -329,7 +348,7 @@ struct LigGlyph
|
|||
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
|
||||
{
|
||||
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
|
||||
|
@ -586,7 +605,10 @@ struct GDEFVersion1_2
|
|||
bool subset_varstore = false;
|
||||
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)
|
||||
|
@ -846,7 +868,7 @@ struct GDEF
|
|||
{ get_lig_caret_list ().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
|
||||
hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map /* OUT */) const
|
||||
{
|
||||
if (!has_var_store ()) return;
|
||||
if (layout_variation_indices->is_empty ()) return;
|
||||
|
@ -864,7 +886,11 @@ struct GDEF
|
|||
}
|
||||
|
||||
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;
|
||||
last_major = major;
|
||||
}
|
||||
|
|
|
@ -175,10 +175,36 @@ struct OS2
|
|||
int a = (int) floorf (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 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
|
||||
|
|
|
@ -269,11 +269,46 @@ _closure_glyphs_lookups_features (hb_subset_plan_t *plan,
|
|||
|
||||
#ifndef HB_NO_VAR
|
||||
static inline void
|
||||
_collect_layout_variation_indices (hb_subset_plan_t* plan,
|
||||
const hb_set_t *glyphset,
|
||||
const hb_map_t *gpos_lookups,
|
||||
hb_set_t *layout_variation_indices,
|
||||
hb_map_t *layout_variation_idx_map)
|
||||
_generate_varstore_inner_maps (const hb_set_t& varidx_set,
|
||||
unsigned subtable_count,
|
||||
hb_vector_t<hb_inc_bimap_t> &inner_maps /* OUT */)
|
||||
{
|
||||
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<GPOS> gpos = plan->source_table<GPOS> ();
|
||||
|
@ -284,13 +319,40 @@ _collect_layout_variation_indices (hb_subset_plan_t* plan,
|
|||
gpos.destroy ();
|
||||
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);
|
||||
|
||||
if (hb_ot_layout_has_positioning (plan->source))
|
||||
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 ();
|
||||
gpos.destroy ();
|
||||
|
@ -506,11 +568,7 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
|
|||
|
||||
#ifndef HB_NO_VAR
|
||||
if (close_over_gdef)
|
||||
_collect_layout_variation_indices (plan,
|
||||
plan->_glyphset_gsub,
|
||||
plan->gpos_lookups,
|
||||
plan->layout_variation_indices,
|
||||
plan->layout_variation_idx_map);
|
||||
_collect_layout_variation_indices (plan);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -682,8 +740,8 @@ hb_subset_plan_create_or_fail (hb_face_t *face,
|
|||
plan->gpos_features = hb_map_create ();
|
||||
plan->colrv1_layers = hb_map_create ();
|
||||
plan->colr_palettes = hb_map_create ();
|
||||
plan->layout_variation_indices = hb_set_create ();
|
||||
plan->layout_variation_idx_map = hb_map_create ();
|
||||
plan->check_success (plan->layout_variation_idx_delta_map = hb_hashmap_create<unsigned, hb_pair_t<unsigned, int>> ());
|
||||
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->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;
|
||||
}
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
_normalize_axes_location (face, plan);
|
||||
#endif
|
||||
|
||||
_populate_unicodes_to_retain (input->sets.unicodes, input->sets.glyphs, 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);
|
||||
}
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
_normalize_axes_location (face, plan);
|
||||
#endif
|
||||
|
||||
_nameid_closure (face, plan->name_ids, plan->all_axes_pinned, plan->user_axes_location);
|
||||
if (unlikely (plan->in_error ())) {
|
||||
hb_subset_plan_destroy (plan);
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "hb-subset-input.hh"
|
||||
|
||||
#include "hb-map.hh"
|
||||
#include "hb-bimap.hh"
|
||||
#include "hb-set.hh"
|
||||
|
||||
struct hb_subset_plan_t
|
||||
|
@ -66,8 +67,6 @@ struct hb_subset_plan_t
|
|||
hb_map_destroy (gpos_features);
|
||||
hb_map_destroy (colrv1_layers);
|
||||
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 (gpos_langsys);
|
||||
|
@ -75,6 +74,7 @@ struct hb_subset_plan_t
|
|||
hb_hashmap_destroy (sanitized_table_cache);
|
||||
hb_hashmap_destroy (hmtx_map);
|
||||
hb_hashmap_destroy (vmtx_map);
|
||||
hb_hashmap_destroy (layout_variation_idx_delta_map);
|
||||
|
||||
if (user_axes_location)
|
||||
{
|
||||
|
@ -147,10 +147,11 @@ struct hb_subset_plan_t
|
|||
hb_map_t *colrv1_layers;
|
||||
hb_map_t *colr_palettes;
|
||||
|
||||
//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;
|
||||
//Old layout item variation index -> (New varidx, delta) mapping
|
||||
hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_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;
|
||||
//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",
|
||||
"--unicodes=%s" % unicodes,
|
||||
"--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)
|
||||
check_call(args)
|
||||
|
||||
|
@ -66,10 +63,8 @@ def generate_expected_output(input_file, unicodes, profile_flags, instance_flags
|
|||
"--drop-tables+=DSIG",
|
||||
"--drop-tables-=sbix"]
|
||||
args.extend(profile_flags)
|
||||
#TODO: remove the drop later as instancing support is added to GPOS/GDEF.
|
||||
if instance_flags:
|
||||
args.extend(["--drop-tables+=GDEF,GPOS",
|
||||
"--instance=%s" % ','.join(instance_flags)])
|
||||
args.extend(["--instance=%s" % ','.join(instance_flags)])
|
||||
check_call(args)
|
||||
|
||||
with io.StringIO () as fp:
|
||||
|
|
|
@ -53,6 +53,7 @@ tests = [
|
|||
# instacing tests, enable when --instance is not experimental
|
||||
# 'pin_all_at_default',
|
||||
# 'instantiate_glyf',
|
||||
# 'full_instance',
|
||||
]
|
||||
|
||||
repack_tests = [
|
||||
|
|
|
@ -56,8 +56,7 @@ def run_test (test, should_check_ots):
|
|||
"--drop-tables-=sbix"]
|
||||
cli_args.extend (test.get_profile_flags ())
|
||||
if test.get_instance_flags ():
|
||||
cli_args.extend (["--drop-tables+=GPOS,GDEF",
|
||||
"--instance=%s" % ','.join(test.get_instance_flags ())])
|
||||
cli_args.extend (["--instance=%s" % ','.join(test.get_instance_flags ())])
|
||||
ret = subset_cmd (cli_args)
|
||||
|
||||
if ret != "success":
|
||||
|
|
Loading…
Reference in New Issue