mirror of
https://github.com/harfbuzz/harfbuzz.git
synced 2025-04-14 17:13:40 +00:00
[instancer] support avar table partial instancing
This commit is contained in:
parent
a0bb2d3a9b
commit
13f05ab9b3
3 changed files with 168 additions and 1 deletions
|
@ -72,6 +72,65 @@ struct AxisValueMap
|
|||
return_trace (c->check_struct (this));
|
||||
}
|
||||
|
||||
void set_mapping (float from_coord, float to_coord)
|
||||
{
|
||||
coords[0].set_float (from_coord);
|
||||
coords[1].set_float (to_coord);
|
||||
}
|
||||
|
||||
bool is_outside_axis_range (const Triple& axis_range) const
|
||||
{
|
||||
float from_coord = coords[0].to_float ();
|
||||
return !axis_range.contains (from_coord);
|
||||
}
|
||||
|
||||
bool must_include () const
|
||||
{
|
||||
float from_coord = coords[0].to_float ();
|
||||
float to_coord = coords[1].to_float ();
|
||||
return (from_coord == -1.f && to_coord == -1.f) ||
|
||||
(from_coord == 0.f && to_coord == 0.f) ||
|
||||
(from_coord == 1.f && to_coord == 1.f);
|
||||
}
|
||||
|
||||
void instantiate (const Triple& axis_range,
|
||||
const Triple& unmapped_range,
|
||||
const TripleDistances& triple_distances)
|
||||
{
|
||||
float from_coord = coords[0].to_float ();
|
||||
float to_coord = coords[1].to_float ();
|
||||
|
||||
from_coord = renormalizeValue (from_coord, unmapped_range, triple_distances);
|
||||
to_coord = renormalizeValue (to_coord, axis_range, triple_distances);
|
||||
|
||||
coords[0].set_float (from_coord);
|
||||
coords[1].set_float (to_coord);
|
||||
}
|
||||
|
||||
HB_INTERNAL static int cmp (const void *pa, const void *pb)
|
||||
{
|
||||
const AxisValueMap *a = (const AxisValueMap *) pa;
|
||||
const AxisValueMap *b = (const AxisValueMap *) pb;
|
||||
|
||||
int a_from = a->coords[0].to_int ();
|
||||
int b_from = b->coords[0].to_int ();
|
||||
if (a_from != b_from)
|
||||
return a_from - b_from;
|
||||
|
||||
/* this should never be reached. according to the spec, all of the axis
|
||||
* value map records for a given axis must have different fromCoord values
|
||||
* */
|
||||
int a_to = a->coords[1].to_int ();
|
||||
int b_to = b->coords[1].to_int ();
|
||||
return a_to - b_to;
|
||||
}
|
||||
|
||||
bool serialize (hb_serialize_context_t *c) const
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
return_trace (c->embed (this));
|
||||
}
|
||||
|
||||
public:
|
||||
F2DOT14 coords[2];
|
||||
// F2DOT14 fromCoord; /* A normalized coordinate value obtained using
|
||||
|
@ -122,6 +181,78 @@ struct SegmentMaps : Array16Of<AxisValueMap>
|
|||
|
||||
int unmap (int value) const { return map (value, 1, 0); }
|
||||
|
||||
Triple unmap_axis_range (const Triple& axis_range) const
|
||||
{
|
||||
F2DOT14 val, unmapped_val;
|
||||
|
||||
val.set_float (axis_range.minimum);
|
||||
unmapped_val.set_int (unmap (val.to_int ()));
|
||||
float unmapped_min = unmapped_val.to_float ();
|
||||
|
||||
val.set_float (axis_range.middle);
|
||||
unmapped_val.set_int (unmap (val.to_int ()));
|
||||
float unmapped_middle = unmapped_val.to_float ();
|
||||
|
||||
val.set_float (axis_range.maximum);
|
||||
unmapped_val.set_int (unmap (val.to_int ()));
|
||||
float unmapped_max = unmapped_val.to_float ();
|
||||
|
||||
return Triple{unmapped_min, unmapped_middle, unmapped_max};
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c, hb_tag_t axis_tag) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
/* avar mapped normalized axis range*/
|
||||
Triple *axis_range;
|
||||
if (!c->plan->axes_location.has (axis_tag, &axis_range))
|
||||
return c->serializer->embed (*this);
|
||||
|
||||
TripleDistances *axis_triple_distances;
|
||||
if (!c->plan->axes_triple_distances.has (axis_tag, &axis_triple_distances))
|
||||
return_trace (false);
|
||||
|
||||
auto *out = c->serializer->start_embed (this);
|
||||
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||
|
||||
Triple unmapped_range = unmap_axis_range (*axis_range);
|
||||
|
||||
/* create a vector of retained mappings and sort */
|
||||
hb_vector_t<AxisValueMap> value_mappings;
|
||||
for (const auto& _ : as_array ())
|
||||
{
|
||||
if (_.is_outside_axis_range (unmapped_range))
|
||||
continue;
|
||||
AxisValueMap mapping;
|
||||
mapping = _;
|
||||
mapping.instantiate (*axis_range, unmapped_range, *axis_triple_distances);
|
||||
/* (-1, -1), (0, 0), (1, 1) mappings will be added later, so avoid
|
||||
* duplicates here */
|
||||
if (mapping.must_include ())
|
||||
continue;
|
||||
value_mappings.push (std::move (mapping));
|
||||
}
|
||||
|
||||
AxisValueMap m;
|
||||
m.set_mapping (-1.f, -1.f);
|
||||
value_mappings.push (m);
|
||||
|
||||
m.set_mapping (0.f, 0.f);
|
||||
value_mappings.push (m);
|
||||
|
||||
m.set_mapping (1.f, 1.f);
|
||||
value_mappings.push (m);
|
||||
|
||||
value_mappings.qsort ();
|
||||
|
||||
for (const auto& _ : value_mappings)
|
||||
{
|
||||
if (!_.serialize (c->serializer))
|
||||
return_trace (false);
|
||||
}
|
||||
return_trace (c->serializer->check_assign (out->len, value_mappings.length, HB_SERIALIZE_ERROR_INT_OVERFLOW));
|
||||
}
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (2, *this);
|
||||
};
|
||||
|
@ -225,6 +356,39 @@ struct avar
|
|||
}
|
||||
}
|
||||
|
||||
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/dropped
|
||||
return_trace (false);
|
||||
|
||||
avar *out = c->serializer->allocate_min<avar> ();
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
out->version.major = 1;
|
||||
out->version.minor = 0;
|
||||
if (!c->serializer->check_assign (out->axisCount, retained_axis_count, HB_SERIALIZE_ERROR_INT_OVERFLOW))
|
||||
return_trace (false);
|
||||
|
||||
const hb_map_t& axes_index_map = c->plan->axes_index_map;
|
||||
const SegmentMaps *map = &firstAxisSegmentMaps;
|
||||
unsigned count = axisCount;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
if (axes_index_map.has (i))
|
||||
{
|
||||
hb_tag_t *axis_tag;
|
||||
if (!c->plan->axes_old_index_tag_map.has (i, &axis_tag))
|
||||
return_trace (false);
|
||||
if (!map->subset (c, *axis_tag))
|
||||
return_trace (false);
|
||||
}
|
||||
map = &StructAfter<SegmentMaps> (*map);
|
||||
}
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
protected:
|
||||
FixedVersion<>version; /* Version of the avar table
|
||||
* initially set to 0x00010000u */
|
||||
|
|
|
@ -69,7 +69,6 @@ hb_subset_input_t::hb_subset_input_t ()
|
|||
sets.drop_tables->add_array (default_drop_tables, ARRAY_LENGTH (default_drop_tables));
|
||||
|
||||
hb_tag_t default_no_subset_tables[] = {
|
||||
HB_TAG ('a', 'v', 'a', 'r'),
|
||||
HB_TAG ('g', 'a', 's', 'p'),
|
||||
HB_TAG ('f', 'p', 'g', 'm'),
|
||||
HB_TAG ('p', 'r', 'e', 'p'),
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
#include "hb-ot-name-table.hh"
|
||||
#include "hb-ot-layout-gsub-table.hh"
|
||||
#include "hb-ot-layout-gpos-table.hh"
|
||||
#include "hb-ot-var-avar-table.hh"
|
||||
#include "hb-ot-var-cvar-table.hh"
|
||||
#include "hb-ot-var-fvar-table.hh"
|
||||
#include "hb-ot-var-gvar-table.hh"
|
||||
|
@ -516,6 +517,9 @@ _subset_table (hb_subset_plan_t *plan,
|
|||
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_avar:
|
||||
if (plan->user_axes_location.is_empty ()) return _passthrough (plan, tag);
|
||||
return _subset<const OT::avar> (plan, buf);
|
||||
case HB_OT_TAG_STAT:
|
||||
if (!plan->user_axes_location.is_empty ()) return _subset<const OT::STAT> (plan, buf);
|
||||
else return _passthrough (plan, tag);
|
||||
|
|
Loading…
Add table
Reference in a new issue