[glyf] do a phantom only iteration when possible
This commit is contained in:
parent
11f3fca01d
commit
5c03fbe7e0
|
@ -633,8 +633,7 @@ struct glyf
|
||||||
void drop_hints_bytes (hb_bytes_t &dest_start) const
|
void drop_hints_bytes (hb_bytes_t &dest_start) const
|
||||||
{ dest_start = bytes.sub_array (0, bytes.length - instructions_length (bytes)); }
|
{ dest_start = bytes.sub_array (0, bytes.length - instructions_length (bytes)); }
|
||||||
|
|
||||||
bool get_contour_points (contour_point_vector_t &points_ /* OUT */,
|
bool get_contour_points (contour_point_vector_t &points_ /* OUT */) const
|
||||||
bool phantom_only = false) const
|
|
||||||
{
|
{
|
||||||
/* add one pseudo point for each component in composite glyph */
|
/* add one pseudo point for each component in composite glyph */
|
||||||
unsigned int num_points = hb_len (get_iterator ());
|
unsigned int num_points = hb_len (get_iterator ());
|
||||||
|
@ -696,7 +695,7 @@ struct glyf
|
||||||
bool get_contour_points (contour_point_vector_t &points_ /* OUT */, bool phantom_only = false) const
|
bool get_contour_points (contour_point_vector_t &points_ /* OUT */, bool phantom_only = false) const
|
||||||
{
|
{
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case COMPOSITE: return CompositeGlyph (*header, bytes).get_contour_points (points_, phantom_only);
|
case COMPOSITE: return CompositeGlyph (*header, bytes).get_contour_points (points_);
|
||||||
case SIMPLE: return SimpleGlyph (*header, bytes).get_contour_points (points_, phantom_only);
|
case SIMPLE: return SimpleGlyph (*header, bytes).get_contour_points (points_, phantom_only);
|
||||||
default:
|
default:
|
||||||
/* empty glyph */
|
/* empty glyph */
|
||||||
|
@ -825,14 +824,16 @@ struct glyf
|
||||||
bool _get_points (hb_codepoint_t gid,
|
bool _get_points (hb_codepoint_t gid,
|
||||||
const int *coords, unsigned int coord_count,
|
const int *coords, unsigned int coord_count,
|
||||||
contour_point_vector_t &all_points /* OUT */,
|
contour_point_vector_t &all_points /* OUT */,
|
||||||
|
bool phantom_only = false,
|
||||||
unsigned int depth = 0) const
|
unsigned int depth = 0) const
|
||||||
{
|
{
|
||||||
if (unlikely (depth++ > HB_MAX_NESTING_LEVEL)) return false;
|
if (unlikely (depth++ > HB_MAX_NESTING_LEVEL)) return false;
|
||||||
contour_point_vector_t points;
|
contour_point_vector_t points;
|
||||||
const Glyph &glyph = glyph_for_gid (gid);
|
const Glyph &glyph = glyph_for_gid (gid);
|
||||||
if (unlikely (!glyph.get_contour_points (points))) return false;
|
if (unlikely (!glyph.get_contour_points (points, phantom_only))) return false;
|
||||||
hb_array_t<contour_point_t> phantoms = points.sub_array (points.length - PHANTOM_COUNT, PHANTOM_COUNT);
|
hb_array_t<contour_point_t> phantoms = points.sub_array (points.length - PHANTOM_COUNT, PHANTOM_COUNT);
|
||||||
init_phantom_points (gid, phantoms);
|
init_phantom_points (gid, phantoms);
|
||||||
|
|
||||||
#ifndef HB_NO_VAR
|
#ifndef HB_NO_VAR
|
||||||
if (unlikely (!face->table.gvar->apply_deltas_to_points (gid, coords, coord_count, points.as_array ()))) return false;
|
if (unlikely (!face->table.gvar->apply_deltas_to_points (gid, coords, coord_count, points.as_array ()))) return false;
|
||||||
#endif
|
#endif
|
||||||
|
@ -846,7 +847,7 @@ struct glyf
|
||||||
{
|
{
|
||||||
contour_point_vector_t comp_points;
|
contour_point_vector_t comp_points;
|
||||||
if (unlikely (!_get_points (item.glyphIndex, coords, coord_count,
|
if (unlikely (!_get_points (item.glyphIndex, coords, coord_count,
|
||||||
comp_points, depth))
|
comp_points, phantom_only, depth))
|
||||||
|| comp_points.length < PHANTOM_COUNT)
|
|| comp_points.length < PHANTOM_COUNT)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -890,9 +891,16 @@ struct glyf
|
||||||
template<typename T>
|
template<typename T>
|
||||||
bool get_points (hb_font_t *font, hb_codepoint_t gid, T consumer) const
|
bool get_points (hb_font_t *font, hb_codepoint_t gid, T consumer) const
|
||||||
{
|
{
|
||||||
|
/* Making this alloc free is not that easy
|
||||||
|
https://github.com/harfbuzz/harfbuzz/issues/2095
|
||||||
|
mostly because of gvar handling in VF fonts,
|
||||||
|
perhaps a separate path for non-VF fonts can be considered */
|
||||||
contour_point_vector_t all_points;
|
contour_point_vector_t all_points;
|
||||||
if (unlikely (!_get_points (gid, font->coords, font->num_coords, all_points) ||
|
|
||||||
all_points.length < PHANTOM_COUNT)) return false;
|
bool phantom_only = !consumer.is_consuming_contour_points ();
|
||||||
|
if (unlikely (!_get_points (gid, font->coords, font->num_coords, all_points, phantom_only) ||
|
||||||
|
all_points.length < PHANTOM_COUNT))
|
||||||
|
return false;
|
||||||
|
|
||||||
/* Undocumented rasterizer behavior:
|
/* Undocumented rasterizer behavior:
|
||||||
* Shift points horizontally by the updated left side bearing
|
* Shift points horizontally by the updated left side bearing
|
||||||
|
@ -901,9 +909,12 @@ struct glyf
|
||||||
delta.init (-all_points[all_points.length - PHANTOM_COUNT + PHANTOM_LEFT].x, 0.f);
|
delta.init (-all_points[all_points.length - PHANTOM_COUNT + PHANTOM_LEFT].x, 0.f);
|
||||||
if (delta.x) all_points.translate (delta);
|
if (delta.x) all_points.translate (delta);
|
||||||
|
|
||||||
for (unsigned point_index = 0; point_index + 4 < all_points.length; ++point_index)
|
if (consumer.is_consuming_contour_points ())
|
||||||
consumer.consume_point (all_points[point_index]);
|
{
|
||||||
consumer.points_end ();
|
for (unsigned point_index = 0; point_index + 4 < all_points.length; ++point_index)
|
||||||
|
consumer.consume_point (all_points[point_index]);
|
||||||
|
consumer.points_end ();
|
||||||
|
}
|
||||||
|
|
||||||
for (unsigned i = 0; i < PHANTOM_COUNT; ++i)
|
for (unsigned i = 0; i < PHANTOM_COUNT; ++i)
|
||||||
consumer.consume_phantom (all_points[all_points.length - PHANTOM_COUNT + i], i);
|
consumer.consume_phantom (all_points[all_points.length - PHANTOM_COUNT + i], i);
|
||||||
|
@ -912,14 +923,14 @@ struct glyf
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef HB_NO_VAR
|
#ifndef HB_NO_VAR
|
||||||
struct extents_bounds_aggregator_t
|
struct points_aggregator_t
|
||||||
{
|
{
|
||||||
hb_font_t *font;
|
hb_font_t *font;
|
||||||
hb_glyph_extents_t *extents;
|
hb_glyph_extents_t *extents;
|
||||||
contour_point_vector_t *phantoms;
|
contour_point_vector_t *phantoms;
|
||||||
contour_bounds_t bounds;
|
contour_bounds_t bounds;
|
||||||
|
|
||||||
extents_bounds_aggregator_t (hb_font_t *font_, hb_glyph_extents_t *extents_, contour_point_vector_t *phantoms_)
|
points_aggregator_t (hb_font_t *font_, hb_glyph_extents_t *extents_, contour_point_vector_t *phantoms_)
|
||||||
{
|
{
|
||||||
font = font_;
|
font = font_;
|
||||||
extents = extents_;
|
extents = extents_;
|
||||||
|
@ -927,11 +938,13 @@ struct glyf
|
||||||
if (extents) bounds = contour_bounds_t ();
|
if (extents) bounds = contour_bounds_t ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void consume_point (const contour_point_t &point) { if (extents) bounds.add (point); }
|
void consume_point (const contour_point_t &point) { bounds.add (point); }
|
||||||
void points_end () { if (extents) bounds.get_extents (font, extents); }
|
void points_end () { bounds.get_extents (font, extents); }
|
||||||
|
|
||||||
void consume_phantom (const contour_point_t &point, unsigned i)
|
void consume_phantom (const contour_point_t &point, unsigned i)
|
||||||
{ if (phantoms) (*phantoms)[i] = point; }
|
{ if (phantoms) (*phantoms)[i] = point; }
|
||||||
|
|
||||||
|
bool is_consuming_contour_points () { return extents; }
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -945,7 +958,7 @@ struct glyf
|
||||||
phantoms.resize (PHANTOM_COUNT);
|
phantoms.resize (PHANTOM_COUNT);
|
||||||
|
|
||||||
if (likely (font->num_coords == face->table.gvar->get_axis_count ()))
|
if (likely (font->num_coords == face->table.gvar->get_axis_count ()))
|
||||||
success = get_points (font, gid, extents_bounds_aggregator_t (font, nullptr, &phantoms));
|
success = get_points (font, gid, points_aggregator_t (font, nullptr, &phantoms));
|
||||||
|
|
||||||
if (unlikely (!success))
|
if (unlikely (!success))
|
||||||
return is_vertical ? face->table.vmtx->get_advance (gid) : face->table.hmtx->get_advance (gid);
|
return is_vertical ? face->table.vmtx->get_advance (gid) : face->table.hmtx->get_advance (gid);
|
||||||
|
@ -962,7 +975,7 @@ struct glyf
|
||||||
contour_point_vector_t phantoms;
|
contour_point_vector_t phantoms;
|
||||||
phantoms.resize (PHANTOM_COUNT);
|
phantoms.resize (PHANTOM_COUNT);
|
||||||
|
|
||||||
if (unlikely (!get_points (font, gid, extents_bounds_aggregator_t (font, &extents, &phantoms))))
|
if (unlikely (!get_points (font, gid, points_aggregator_t (font, &extents, &phantoms))))
|
||||||
return is_vertical ? face->table.vmtx->get_side_bearing (gid) : face->table.hmtx->get_side_bearing (gid);
|
return is_vertical ? face->table.vmtx->get_side_bearing (gid) : face->table.hmtx->get_side_bearing (gid);
|
||||||
|
|
||||||
return is_vertical ? ceil (phantoms[PHANTOM_TOP].y) - extents.y_bearing : floor (phantoms[PHANTOM_LEFT].x);
|
return is_vertical ? ceil (phantoms[PHANTOM_TOP].y) - extents.y_bearing : floor (phantoms[PHANTOM_LEFT].x);
|
||||||
|
@ -975,7 +988,7 @@ struct glyf
|
||||||
unsigned int coord_count;
|
unsigned int coord_count;
|
||||||
const int *coords = hb_font_get_var_coords_normalized (font, &coord_count);
|
const int *coords = hb_font_get_var_coords_normalized (font, &coord_count);
|
||||||
if (coords && coord_count > 0 && coord_count == face->table.gvar->get_axis_count ())
|
if (coords && coord_count > 0 && coord_count == face->table.gvar->get_axis_count ())
|
||||||
return get_points (font, gid, extents_bounds_aggregator_t (font, extents, nullptr));
|
return get_points (font, gid, points_aggregator_t (font, extents, nullptr));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (unlikely (gid >= num_glyphs)) return false;
|
if (unlikely (gid >= num_glyphs)) return false;
|
||||||
|
@ -1193,8 +1206,9 @@ struct glyf
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void points_end () {}
|
void points_end () {}
|
||||||
|
|
||||||
void consume_phantom (const contour_point_t &point HB_UNUSED, unsigned i HB_UNUSED) {}
|
void consume_phantom (const contour_point_t &point HB_UNUSED, unsigned i HB_UNUSED) {}
|
||||||
|
|
||||||
|
bool is_consuming_contour_points () { return true; }
|
||||||
};
|
};
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
Loading…
Reference in New Issue