parent
c8b31773a6
commit
cabe22fc69
|
@ -513,9 +513,9 @@ struct glyf
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct bounds_t
|
struct contour_bounds_t
|
||||||
{
|
{
|
||||||
bounds_t () { min.x = min.y = FLT_MAX; max.x = max.y = FLT_MIN; }
|
contour_bounds_t () { min.x = min.y = FLT_MAX; max.x = max.y = FLT_MIN; }
|
||||||
|
|
||||||
void add (const contour_point_t &p)
|
void add (const contour_point_t &p)
|
||||||
{
|
{
|
||||||
|
@ -525,8 +525,14 @@ struct glyf
|
||||||
max.y = MAX (max.y, p.y);
|
max.y = MAX (max.y, p.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _union (const bounds_t &b)
|
void merge (const contour_bounds_t &b)
|
||||||
{ add (b.min); add (b.max); }
|
{
|
||||||
|
if (empty ()) { *this = b; return; }
|
||||||
|
add (b.min);
|
||||||
|
add (b.max);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool empty () const { return (min.x >= max.x) || (min.y >= max.y); }
|
||||||
|
|
||||||
contour_point_t min;
|
contour_point_t min;
|
||||||
contour_point_t max;
|
contour_point_t max;
|
||||||
|
@ -535,7 +541,7 @@ struct glyf
|
||||||
/* Note: Recursively calls itself. Who's checking recursively nested composite glyph BTW? */
|
/* Note: Recursively calls itself. Who's checking recursively nested composite glyph BTW? */
|
||||||
bool get_bounds_var (hb_codepoint_t glyph,
|
bool get_bounds_var (hb_codepoint_t glyph,
|
||||||
const int *coords, unsigned int coord_count,
|
const int *coords, unsigned int coord_count,
|
||||||
bounds_t &bounds) const
|
contour_bounds_t &bounds) const
|
||||||
{
|
{
|
||||||
hb_vector_t<contour_point_t> points;
|
hb_vector_t<contour_point_t> points;
|
||||||
hb_vector_t<unsigned int> end_points;
|
hb_vector_t<unsigned int> end_points;
|
||||||
|
@ -555,12 +561,12 @@ struct glyf
|
||||||
/* composite glyph */
|
/* composite glyph */
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
bounds_t comp_bounds;
|
contour_bounds_t comp_bounds;
|
||||||
if (unlikely (!get_bounds_var (composite.current->glyphIndex, coords, coord_count, comp_bounds))) return false;
|
if (unlikely (!get_bounds_var (composite.current->glyphIndex, coords, coord_count, comp_bounds))) return false;
|
||||||
|
|
||||||
composite.current->transform_point (comp_bounds.min.x, comp_bounds.min.y);
|
composite.current->transform_point (comp_bounds.min.x, comp_bounds.min.y);
|
||||||
composite.current->transform_point (comp_bounds.max.x, comp_bounds.max.y);
|
composite.current->transform_point (comp_bounds.max.x, comp_bounds.max.y);
|
||||||
bounds._union (comp_bounds);
|
bounds.merge (comp_bounds);
|
||||||
} while (composite.move_to_next());
|
} while (composite.move_to_next());
|
||||||
|
|
||||||
/* Shift bounds by the updated left side bearing (vertically too?) */
|
/* Shift bounds by the updated left side bearing (vertically too?) */
|
||||||
|
@ -577,7 +583,7 @@ struct glyf
|
||||||
const int *coords, unsigned int coord_count,
|
const int *coords, unsigned int coord_count,
|
||||||
hb_glyph_extents_t *extents) const
|
hb_glyph_extents_t *extents) const
|
||||||
{
|
{
|
||||||
bounds_t bounds;
|
contour_bounds_t bounds;
|
||||||
if (unlikely (!get_bounds_var (glyph, coords, coord_count, bounds))) return false;
|
if (unlikely (!get_bounds_var (glyph, coords, coord_count, bounds))) return false;
|
||||||
|
|
||||||
if (bounds.min.x >= bounds.max.x)
|
if (bounds.min.x >= bounds.max.x)
|
||||||
|
|
|
@ -511,6 +511,34 @@ struct gvar
|
||||||
gvar_table.destroy ();
|
gvar_table.destroy ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct x_getter { static float get (const contour_point_t &p) { return p.x; } };
|
||||||
|
struct y_getter { static float get (const contour_point_t &p) { return p.y; } };
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static float infer_delta (const hb_array_t<contour_point_t> points,
|
||||||
|
const hb_array_t<contour_point_t> deltas,
|
||||||
|
unsigned int target, unsigned int prev, unsigned int next)
|
||||||
|
{
|
||||||
|
float target_val = T::get (points[target]);
|
||||||
|
float prev_val = T::get (points[prev]);
|
||||||
|
float next_val = T::get (points[next]);
|
||||||
|
float prev_delta = T::get (deltas[prev]);
|
||||||
|
float next_delta = T::get (deltas[next]);
|
||||||
|
|
||||||
|
if (prev_val == next_val)
|
||||||
|
return (prev_delta == next_delta)? prev_delta: 0.f;
|
||||||
|
else if (target_val <= MIN (prev_val, next_val))
|
||||||
|
return (prev_val < next_val) ? prev_delta: next_delta;
|
||||||
|
else if (target_val >= MAX (prev_val, next_val))
|
||||||
|
return (prev_val > next_val)? prev_delta: next_delta;
|
||||||
|
|
||||||
|
/* linear interpolation */
|
||||||
|
float r = (target_val - prev_val) / (next_val - prev_val);
|
||||||
|
return (1.f - r) * prev_delta + r * next_delta;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
bool apply_deltas_to_points (hb_codepoint_t glyph,
|
bool apply_deltas_to_points (hb_codepoint_t glyph,
|
||||||
const int *coords, unsigned int coord_count,
|
const int *coords, unsigned int coord_count,
|
||||||
const hb_array_t<contour_point_t> points,
|
const hb_array_t<contour_point_t> points,
|
||||||
|
@ -570,6 +598,11 @@ struct gvar
|
||||||
} while (iterator.move_to_next ());
|
} while (iterator.move_to_next ());
|
||||||
|
|
||||||
/* infer deltas for unreferenced points */
|
/* infer deltas for unreferenced points */
|
||||||
|
hb_vector_t<contour_point_t> orig_points;
|
||||||
|
orig_points.resize (points.length);
|
||||||
|
for (unsigned int i = 0; i < orig_points.length; i++)
|
||||||
|
orig_points[i] = points[i];
|
||||||
|
|
||||||
unsigned int start_point = 0;
|
unsigned int start_point = 0;
|
||||||
for (unsigned int c = 0; c < end_points.length; c++)
|
for (unsigned int c = 0; c < end_points.length; c++)
|
||||||
{
|
{
|
||||||
|
@ -592,8 +625,8 @@ struct gvar
|
||||||
if (next == i || deltas[next].flag) break;
|
if (next == i || deltas[next].flag) break;
|
||||||
}
|
}
|
||||||
assert (next != i);
|
assert (next != i);
|
||||||
deltas[i].x = infer_delta (points[i].x, points[prev].x, points[next].x, deltas[prev].x, deltas[next].x);
|
deltas[i].x = infer_delta<x_getter> (orig_points.as_array (), deltas.as_array (), i, prev, next);
|
||||||
deltas[i].y = infer_delta (points[i].y, points[prev].y, points[next].y, deltas[prev].y, deltas[next].y);
|
deltas[i].y = infer_delta<y_getter> (orig_points.as_array (), deltas.as_array (), i, prev, next);
|
||||||
}
|
}
|
||||||
start_point = end_point + 1;
|
start_point = end_point + 1;
|
||||||
}
|
}
|
||||||
|
@ -611,21 +644,6 @@ struct gvar
|
||||||
unsigned int get_axis_count () const { return gvar_table->axisCount; }
|
unsigned int get_axis_count () const { return gvar_table->axisCount; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static float infer_delta (float target_val, float prev_val, float next_val,
|
|
||||||
float prev_delta, float next_delta)
|
|
||||||
{
|
|
||||||
if (prev_val == next_val)
|
|
||||||
return (prev_delta == next_delta)? prev_delta: 0.f;
|
|
||||||
else if (target_val <= MIN (prev_val, next_val))
|
|
||||||
return (prev_val < next_val) ? prev_delta: next_delta;
|
|
||||||
else if (target_val >= MAX (prev_val, next_val))
|
|
||||||
return (prev_val > next_val)? prev_delta: next_delta;
|
|
||||||
|
|
||||||
/* linear interpolation */
|
|
||||||
float r = (target_val - prev_val) / (next_val - prev_val);
|
|
||||||
return (1.f - r) * prev_delta + r * next_delta;
|
|
||||||
}
|
|
||||||
|
|
||||||
const GlyphVarData *get_glyph_var_data (hb_codepoint_t glyph) const
|
const GlyphVarData *get_glyph_var_data (hb_codepoint_t glyph) const
|
||||||
{ return gvar_table->get_glyph_var_data (glyph); }
|
{ return gvar_table->get_glyph_var_data (glyph); }
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue