[glyf] Optimize retrieval of hmtx/vmtx/gvar

This should make glyf/gvar faster as makes it to invoke less table wrapper atomic operations and things.

$ meson build -Dexperimental_api=true --buildtype=release && ninja -Cbuild && build/perf/perf "--benchmark_filter=glyf.*- ot -"

Before:
extents/glyf - ot - SourceSerifVariable         46091 ns      46036 ns      16173
extents/glyf/vf - ot - SourceSerifVariable    4160142 ns    4154913 ns        174
extents/glyf - ot - Comfortaa                   25754 ns      25726 ns      27030
extents/glyf/vf - ot - Comfortaa              2627804 ns    2624596 ns        265
extents/glyf - ot - Roboto                      33556 ns      33540 ns      18513
draw/glyf - ot - SourceSerifVariable          2716848 ns    2715438 ns        256
draw/glyf/vf - ot - SourceSerifVariable       4602379 ns    4598907 ns        151
draw/glyf - ot - Comfortaa                    1659364 ns    1658142 ns        417
draw/glyf/vf - ot - Comfortaa                 2845100 ns    2842549 ns        246
draw/glyf - ot - Roboto                       1571509 ns    1570060 ns        442

After:
extents/glyf - ot - SourceSerifVariable         34738 ns      34713 ns      21332
extents/glyf/vf - ot - SourceSerifVariable    3700510 ns    3698104 ns        187
extents/glyf - ot - Comfortaa                   21604 ns      21595 ns      31907
extents/glyf/vf - ot - Comfortaa              2324787 ns    2323440 ns        296
extents/glyf - ot - Roboto                      31259 ns      31246 ns      21814
draw/glyf - ot - SourceSerifVariable          2689230 ns    2687589 ns        260
draw/glyf/vf - ot - SourceSerifVariable       4625135 ns    4622036 ns        131
draw/glyf - ot - Comfortaa                    1690336 ns    1689454 ns        402
draw/glyf/vf - ot - Comfortaa                 2898748 ns    2897074 ns        241
draw/glyf - ot - Roboto                       1570911 ns    1570138 ns        440
This commit is contained in:
Ebrahim Byagowi 2020-08-07 01:21:19 +04:30 committed by GitHub
parent 0907c10214
commit 1f519c2567
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 43 additions and 27 deletions

View File

@ -409,6 +409,8 @@ struct glyf
PHANTOM_COUNT = 4
};
struct accelerator_t;
struct Glyph
{
enum simple_glyph_flag_t
@ -428,11 +430,12 @@ struct glyf
{
bool has_data () const { return numberOfContours; }
bool get_extents (hb_font_t *font, hb_codepoint_t gid, hb_glyph_extents_t *extents) const
bool get_extents (hb_font_t *font, const accelerator_t &glyf_accelerator,
hb_codepoint_t gid, hb_glyph_extents_t *extents) const
{
/* Undocumented rasterizer behavior: shift glyph to the left by (lsb - xMin), i.e., xMin = lsb */
/* extents->x_bearing = hb_min (glyph_header.xMin, glyph_header.xMax); */
extents->x_bearing = font->em_scale_x (font->face->table.hmtx->get_side_bearing (gid));
extents->x_bearing = font->em_scale_x (glyf_accelerator.hmtx->get_side_bearing (gid));
extents->y_bearing = font->em_scale_y (hb_max (yMin, yMax));
extents->width = font->em_scale_x (hb_max (xMin, xMax) - hb_min (xMin, xMax));
extents->height = font->em_scale_y (hb_min (yMin, yMax) - hb_max (yMin, yMax));
@ -694,7 +697,7 @@ struct glyf
* all_points includes phantom points
*/
template<typename T>
bool get_points (T glyph_for_gid, hb_font_t *font,
bool get_points (T glyph_for_gid, hb_font_t *font, const accelerator_t &glyf_accelerator,
contour_point_vector_t &all_points /* OUT */,
bool phantom_only = false,
unsigned int depth = 0) const
@ -718,17 +721,15 @@ struct glyf
break;
}
hb_face_t *face = font->face;
/* Init phantom points */
if (unlikely (!points.resize (points.length + PHANTOM_COUNT))) return false;
hb_array_t<contour_point_t> phantoms = points.sub_array (points.length - PHANTOM_COUNT, PHANTOM_COUNT);
{
for (unsigned i = 0; i < PHANTOM_COUNT; ++i) phantoms[i].init ();
int h_delta = (int) header->xMin - face->table.hmtx->get_side_bearing (gid);
int v_orig = (int) header->yMax + face->table.vmtx->get_side_bearing (gid);
unsigned h_adv = face->table.hmtx->get_advance (gid);
unsigned v_adv = face->table.vmtx->get_advance (gid);
int h_delta = (int) header->xMin - glyf_accelerator.hmtx->get_side_bearing (gid);
int v_orig = (int) header->yMax + glyf_accelerator.vmtx->get_side_bearing (gid);
unsigned h_adv = glyf_accelerator.hmtx->get_advance (gid);
unsigned v_adv = glyf_accelerator.vmtx->get_advance (gid);
phantoms[PHANTOM_LEFT].x = h_delta;
phantoms[PHANTOM_RIGHT].x = h_adv + h_delta;
phantoms[PHANTOM_TOP].y = v_orig;
@ -736,7 +737,7 @@ struct glyf
}
#ifndef HB_NO_VAR
if (unlikely (!face->table.gvar->apply_deltas_to_points (gid, font, points.as_array ())))
if (unlikely (!glyf_accelerator.gvar->apply_deltas_to_points (gid, font, points.as_array ())))
return false;
#endif
@ -750,7 +751,7 @@ struct glyf
for (auto &item : get_composite_iterator ())
{
contour_point_vector_t comp_points;
if (unlikely (!glyph_for_gid (item.glyphIndex).get_points (glyph_for_gid, font, comp_points, phantom_only, depth + 1))
if (unlikely (!glyph_for_gid (item.glyphIndex).get_points (glyph_for_gid, font, glyf_accelerator, comp_points, phantom_only, depth + 1))
|| comp_points.length < PHANTOM_COUNT)
return false;
@ -803,10 +804,11 @@ struct glyf
return true;
}
bool get_extents (hb_font_t *font, hb_glyph_extents_t *extents) const
bool get_extents (hb_font_t *font, const accelerator_t &glyf_accelerator,
hb_glyph_extents_t *extents) const
{
if (type == EMPTY) return true; /* Empty glyph; zero extents. */
return header->get_extents (font, gid, extents);
return header->get_extents (font, glyf_accelerator, gid, extents);
}
hb_bytes_t get_bytes () const { return bytes; }
@ -836,6 +838,11 @@ struct glyf
num_glyphs = 0;
loca_table = nullptr;
glyf_table = nullptr;
#ifndef HB_NO_VAR
gvar = &Null (gvar_accelerator_t);
#endif
hmtx = &Null (hmtx_accelerator_t);
vmtx = &Null (vmtx_accelerator_t);
face = face_;
const OT::head &head = *face->table.head;
if (head.indexToLocFormat > 1 || head.glyphDataFormat > 0)
@ -845,6 +852,11 @@ struct glyf
loca_table = hb_sanitize_context_t ().reference_table<loca> (face);
glyf_table = hb_sanitize_context_t ().reference_table<glyf> (face);
#ifndef HB_NO_VAR
gvar = face->table.gvar;
#endif
hmtx = face->table.hmtx;
vmtx = face->table.vmtx;
num_glyphs = hb_max (1u, loca_table.get_length () / (short_offset ? 2 : 4)) - 1;
num_glyphs = hb_min (num_glyphs, face->get_num_glyphs ());
@ -870,7 +882,7 @@ struct glyf
bool phantom_only = !consumer.is_consuming_contour_points ();
if (unlikely (!glyph_for_gid (gid).get_points ([this] (hb_codepoint_t gid) -> const Glyph { return this->glyph_for_gid (gid); },
font, all_points, phantom_only)))
font, *this, all_points, phantom_only)))
return false;
if (consumer.is_consuming_contour_points ())
@ -896,6 +908,7 @@ struct glyf
hb_font_t *font;
hb_glyph_extents_t *extents;
contour_point_t *phantoms;
const accelerator_t *accelerator;
struct contour_bounds_t
{
@ -931,9 +944,10 @@ struct glyf
float min_x, min_y, max_x, max_y;
} bounds;
points_aggregator_t (hb_font_t *font_, hb_glyph_extents_t *extents_, contour_point_t *phantoms_)
points_aggregator_t (hb_font_t *font_, const accelerator_t *accelerator_, hb_glyph_extents_t *extents_, contour_point_t *phantoms_)
{
font = font_;
accelerator = accelerator_;
extents = extents_;
phantoms = phantoms_;
if (extents) bounds = contour_bounds_t ();
@ -952,13 +966,11 @@ struct glyf
bool success = false;
contour_point_t phantoms[PHANTOM_COUNT];
if (likely (font->num_coords == face->table.gvar->get_axis_count ()))
success = get_points (font, gid, points_aggregator_t (font, nullptr, phantoms));
if (likely (font->num_coords == gvar->get_axis_count ()))
success = get_points (font, gid, points_aggregator_t (font, this, nullptr, phantoms));
if (unlikely (!success))
return is_vertical
? face->table.vmtx->get_advance (gid)
: face->table.hmtx->get_advance (gid);
return is_vertical ? vmtx->get_advance (gid) : hmtx->get_advance (gid);
float result = is_vertical
? phantoms[PHANTOM_TOP].y - phantoms[PHANTOM_BOTTOM].y
@ -971,10 +983,8 @@ struct glyf
hb_glyph_extents_t extents;
contour_point_t phantoms[PHANTOM_COUNT];
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);
if (unlikely (!get_points (font, gid, points_aggregator_t (font, this, &extents, phantoms))))
return is_vertical ? vmtx->get_side_bearing (gid) : hmtx->get_side_bearing (gid);
return is_vertical
? ceilf (phantoms[PHANTOM_TOP].y) - extents.y_bearing
@ -986,10 +996,10 @@ struct glyf
{
if (unlikely (gid >= num_glyphs)) return false;
#ifndef HB_NO_VAR
if (font->num_coords && font->num_coords == face->table.gvar->get_axis_count ())
return get_points (font, gid, points_aggregator_t (font, extents, nullptr));
if (font->num_coords && font->num_coords == gvar->get_axis_count ())
return get_points (font, gid, points_aggregator_t (font, this, extents, nullptr));
#endif
return glyph_for_gid (gid).get_extents (font, extents);
return glyph_for_gid (gid).get_extents (font, *this, extents);
}
const Glyph
@ -1154,6 +1164,12 @@ struct glyf
{ return get_points (font, gid, path_builder_t (font, draw_helper)); }
#endif
#ifndef HB_NO_VAR
const gvar_accelerator_t *gvar;
#endif
const hmtx_accelerator_t *hmtx;
const vmtx_accelerator_t *vmtx;
private:
bool short_offset;
unsigned int num_glyphs;