[instance] instantiate fvar table
Added an old->new axes_indices mapping in the subset plan
This commit is contained in:
parent
486fc2271a
commit
0a6c16a313
|
@ -47,6 +47,44 @@ struct InstanceRecord
|
|||
hb_array_t<const HBFixed> get_coordinates (unsigned int axis_count) const
|
||||
{ return coordinatesZ.as_array (axis_count); }
|
||||
|
||||
bool subset (hb_subset_context_t *c,
|
||||
unsigned axis_count,
|
||||
bool has_postscript_nameid) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
if (unlikely (!c->serializer->embed (subfamilyNameID))) return_trace (false);
|
||||
if (unlikely (!c->serializer->embed (flags))) return_trace (false);
|
||||
|
||||
const hb_array_t<const HBFixed> coords = get_coordinates (axis_count);
|
||||
const hb_hashmap_t<hb_tag_t, float> *axes_location = c->plan->user_axes_location;
|
||||
for (unsigned i = 0 ; i < axis_count; i++)
|
||||
{
|
||||
unsigned *axis_tag;
|
||||
// only keep instances whose coordinates == pinned axis location
|
||||
if (!c->plan->axes_old_index_tag_map->has (i, &axis_tag)) continue;
|
||||
|
||||
if (axes_location->has (*axis_tag) &&
|
||||
fabsf (axes_location->get (*axis_tag) - coords[i].to_float ()) > 0.001f)
|
||||
return_trace (false);
|
||||
|
||||
if (!c->plan->axes_index_map->has (i))
|
||||
continue;
|
||||
|
||||
if (!c->serializer->embed (coords[i]))
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
if (has_postscript_nameid)
|
||||
{
|
||||
NameID name_id;
|
||||
name_id = StructAfter<NameID> (coords);
|
||||
if (!c->serializer->embed (name_id))
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c, unsigned int axis_count) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
@ -321,6 +359,48 @@ struct fvar
|
|||
}
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
unsigned retained_axis_count = c->plan->axes_index_map->get_population ();
|
||||
if (!retained_axis_count) //all axes are pinned
|
||||
return_trace (false);
|
||||
|
||||
fvar *out = c->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
if (!c->serializer->check_assign (out->axisCount, retained_axis_count, HB_SERIALIZE_ERROR_INT_OVERFLOW))
|
||||
return_trace (false);
|
||||
|
||||
bool has_postscript_nameid = false;
|
||||
if (instanceSize >= axisCount * 4 + 6)
|
||||
has_postscript_nameid = true;
|
||||
|
||||
if (!c->serializer->check_assign (out->instanceSize, retained_axis_count * 4 + (has_postscript_nameid ? 6 : 4),
|
||||
HB_SERIALIZE_ERROR_INT_OVERFLOW))
|
||||
return_trace (false);
|
||||
|
||||
auto axes_records = get_axes ();
|
||||
for (unsigned i = 0 ; i < (unsigned)axisCount; i++)
|
||||
{
|
||||
if (!c->plan->axes_index_map->has (i)) continue;
|
||||
if (unlikely (!c->serializer->embed (axes_records[i])))
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
if (!c->serializer->check_assign (out->firstAxis, get_size (), HB_SERIALIZE_ERROR_INT_OVERFLOW))
|
||||
return_trace (false);
|
||||
|
||||
for (unsigned i = 0 ; i < (unsigned)instanceCount; i++)
|
||||
{
|
||||
const InstanceRecord *instance = get_instance (i);
|
||||
auto snap = c->serializer->snapshot ();
|
||||
if (!instance->subset (c, axisCount, has_postscript_nameid))
|
||||
c->serializer->revert (snap);
|
||||
}
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
public:
|
||||
hb_array_t<const AxisRecord> get_axes () const
|
||||
{ return hb_array (&(this+firstAxis), axisCount); }
|
||||
|
|
|
@ -89,7 +89,6 @@ hb_subset_input_create_or_fail (void)
|
|||
|
||||
hb_tag_t default_no_subset_tables[] = {
|
||||
HB_TAG ('a', 'v', 'a', 'r'),
|
||||
HB_TAG ('f', 'v', 'a', 'r'),
|
||||
HB_TAG ('g', 'a', 's', 'p'),
|
||||
HB_TAG ('c', 'v', 't', ' '),
|
||||
HB_TAG ('f', 'p', 'g', 'm'),
|
||||
|
|
|
@ -663,18 +663,22 @@ _normalize_axes_location (hb_face_t *face, hb_subset_plan_t *plan)
|
|||
seg_maps = face->table.avar->get_segment_maps ();
|
||||
|
||||
bool axis_not_pinned = false;
|
||||
unsigned axis_count = 0;
|
||||
unsigned old_axis_idx = 0, new_axis_idx = 0;
|
||||
for (const auto& axis : axes)
|
||||
{
|
||||
hb_tag_t axis_tag = axis.get_axis_tag ();
|
||||
plan->axes_old_index_tag_map->set (old_axis_idx, axis_tag);
|
||||
|
||||
if (!plan->user_axes_location->has (axis_tag))
|
||||
{
|
||||
axis_not_pinned = true;
|
||||
plan->axes_index_map->set (old_axis_idx, new_axis_idx);
|
||||
new_axis_idx++;
|
||||
}
|
||||
else
|
||||
{
|
||||
int normalized_v = axis.normalize_axis_value (plan->user_axes_location->get (axis_tag));
|
||||
if (has_avar && axis_count < face->table.avar->get_axis_count ())
|
||||
if (has_avar && old_axis_idx < face->table.avar->get_axis_count ())
|
||||
{
|
||||
normalized_v = seg_maps->map (normalized_v);
|
||||
}
|
||||
|
@ -685,7 +689,7 @@ _normalize_axes_location (hb_face_t *face, hb_subset_plan_t *plan)
|
|||
if (has_avar)
|
||||
seg_maps = &StructAfter<OT::SegmentMaps> (*seg_maps);
|
||||
|
||||
axis_count++;
|
||||
old_axis_idx++;
|
||||
}
|
||||
plan->all_axes_pinned = !axis_not_pinned;
|
||||
}
|
||||
|
@ -755,6 +759,8 @@ hb_subset_plan_create_or_fail (hb_face_t *face,
|
|||
plan->check_success (plan->user_axes_location = hb_hashmap_create<hb_tag_t, float> ());
|
||||
if (plan->user_axes_location && input->axes_location)
|
||||
*plan->user_axes_location = *input->axes_location;
|
||||
plan->check_success (plan->axes_index_map = hb_map_create ());
|
||||
plan->check_success (plan->axes_old_index_tag_map = hb_map_create ());
|
||||
plan->all_axes_pinned = false;
|
||||
plan->pinned_at_default = true;
|
||||
|
||||
|
|
|
@ -67,6 +67,8 @@ struct hb_subset_plan_t
|
|||
hb_map_destroy (gpos_features);
|
||||
hb_map_destroy (colrv1_layers);
|
||||
hb_map_destroy (colr_palettes);
|
||||
hb_map_destroy (axes_index_map);
|
||||
hb_map_destroy (axes_old_index_tag_map);
|
||||
|
||||
hb_hashmap_destroy (gsub_langsys);
|
||||
hb_hashmap_destroy (gpos_langsys);
|
||||
|
@ -158,6 +160,10 @@ struct hb_subset_plan_t
|
|||
hb_hashmap_t<hb_tag_t, int> *axes_location;
|
||||
//user specified axes location map
|
||||
hb_hashmap_t<hb_tag_t, float> *user_axes_location;
|
||||
//retained old axis index -> new axis index mapping in fvar axis array
|
||||
hb_map_t *axes_index_map;
|
||||
//axis_index->axis_tag mapping in fvar axis array
|
||||
hb_map_t *axes_old_index_tag_map;
|
||||
bool all_axes_pinned;
|
||||
bool pinned_at_default;
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
#include "hb-ot-color-cbdt-table.hh"
|
||||
#include "hb-ot-layout-gsub-table.hh"
|
||||
#include "hb-ot-layout-gpos-table.hh"
|
||||
#include "hb-ot-var-fvar-table.hh"
|
||||
#include "hb-ot-var-gvar-table.hh"
|
||||
#include "hb-ot-var-hvar-table.hh"
|
||||
#include "hb-ot-math-table.hh"
|
||||
|
@ -475,6 +476,9 @@ _subset_table (hb_subset_plan_t *plan,
|
|||
case HB_OT_TAG_HVAR: return _subset<const OT::HVAR> (plan, buf);
|
||||
case HB_OT_TAG_VVAR: return _subset<const OT::VVAR> (plan, buf);
|
||||
#endif
|
||||
case HB_OT_TAG_fvar:
|
||||
if (plan->user_axes_location->is_empty ()) return _passthrough (plan, tag);
|
||||
return _subset<const OT::fvar> (plan, buf);
|
||||
case HB_OT_TAG_STAT:
|
||||
/*TODO(qxliu): change the condition as we support more complex
|
||||
* instancing operation*/
|
||||
|
|
Loading…
Reference in New Issue