From 084a8182fb5c79cb8ebb41e015992fc4e4daea4a Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Fri, 10 Jan 2020 22:14:46 +0330 Subject: [PATCH] [ot-glyphs] Move CFF glyph decompose logic to their tables Thus making path decompose zero alloc on CFF/CFF2 --- docs/harfbuzz-sections.txt | 14 +++---- src/hb-ot-cff1-table.cc | 85 ++++++++++++++++++++++---------------- src/hb-ot-cff1-table.hh | 3 +- src/hb-ot-cff2-table.cc | 62 ++++++++++++++------------- src/hb-ot-cff2-table.hh | 6 +-- src/hb-ot-glyph.cc | 41 ++---------------- 6 files changed, 93 insertions(+), 118 deletions(-) diff --git a/docs/harfbuzz-sections.txt b/docs/harfbuzz-sections.txt index 5c9edbfab..834ef9165 100644 --- a/docs/harfbuzz-sections.txt +++ b/docs/harfbuzz-sections.txt @@ -522,14 +522,12 @@ hb_ot_font_set_funcs
hb-ot-glyph -hb_ot_glyph_path_t -hb_ot_glyph_path_create -hb_ot_glyph_path_create_from_font -hb_ot_glyph_path_destroy -hb_ot_glyph_path_empty -hb_ot_glyph_path_get_commands -hb_ot_glyph_path_get_coords -hb_ot_glyph_path_reference +hb_ot_glyph_decompose_funcs_t +hb_ot_glyph_decompose_move_to_func_t +hb_ot_glyph_decompose_line_to_func_t +hb_ot_glyph_decompose_conic_to_func_t +hb_ot_glyph_decompose_cubic_to_func_t +hb_ot_glyph_decompose
diff --git a/src/hb-ot-cff1-table.cc b/src/hb-ot-cff1-table.cc index e5136e68a..6dfc76456 100644 --- a/src/hb-ot-cff1-table.cc +++ b/src/hb-ot-cff1-table.cc @@ -344,33 +344,57 @@ bool OT::cff1::accelerator_t::get_extents (hb_font_t *font, hb_codepoint_t glyph struct cff1_path_param_t { - void init (const OT::cff1::accelerator_t *cff_, hb_font_t *font_, hb_vector_t *points_, hb_vector_t *commands_, point_t *delta_) + void init (const OT::cff1::accelerator_t *cff_, hb_font_t *font_, + hb_ot_glyph_decompose_funcs_t *funcs_, void *user_data_, + point_t *delta_) { path_open = false; cff = cff_; font = font_; - points = points_; - commands = commands_; + funcs = funcs_; + user_data = user_data_; delta = delta_; } void start_path () { path_open = true; } - void end_path () { if (path_open) push_command ('Z'); path_open = false; } + void end_path () { /* funcs->end_path (); */ path_open = false; } bool is_path_open () const { return path_open; } - void push_point (const point_t &p) + void move_to (const point_t &p) { point_t point = p; if (delta) point.move (*delta); - points->push (font->em_scalef_x (point.x.to_real ())); - points->push (font->em_scalef_y (point.y.to_real ())); + funcs->move_to (font->em_scalef_x (point.x.to_real ()), font->em_scalef_y (point.y.to_real ()), + user_data); + } + + void line_to (const point_t &p) + { + point_t point = p; + if (delta) point.move (*delta); + funcs->line_to (font->em_scalef_x (point.x.to_real ()), font->em_scalef_y (point.y.to_real ()), + user_data); + } + + void cubic_to (const point_t &p1, const point_t &p2, const point_t &p3) + { + point_t point1 = p1, point2 = p2, point3 = p3; + if (delta) + { + point1.move (*delta); + point2.move (*delta); + point3.move (*delta); + } + funcs->cubic_to (font->em_scalef_x (point1.x.to_real ()), font->em_scalef_y (point1.y.to_real ()), + font->em_scalef_x (point2.x.to_real ()), font->em_scalef_y (point2.y.to_real ()), + font->em_scalef_x (point3.x.to_real ()), font->em_scalef_y (point3.y.to_real ()), + user_data); } - void push_command (uint8_t c) { commands->push (c); } bool path_open; hb_font_t *font; - hb_vector_t *points; - hb_vector_t *commands; + hb_ot_glyph_decompose_funcs_t *funcs; + void *user_data; point_t *delta; const OT::cff1::accelerator_t *cff; @@ -381,39 +405,28 @@ struct cff1_path_procs_path_t : path_procs_t *points, hb_vector_t *commands, bool in_seac=false, point_t *delta = nullptr); +static bool _get_path (const OT::cff1::accelerator_t *cff, hb_font_t *font, hb_codepoint_t glyph, + hb_ot_glyph_decompose_funcs_t *funcs, void *user_data, + bool in_seac = false, point_t *delta = nullptr); struct cff1_cs_opset_path_t : cff1_cs_opset_t { @@ -427,13 +440,14 @@ struct cff1_cs_opset_path_t : cff1_cs_opset_tstd_code_to_glyph (env.argStack[n-1].to_int ()); if (unlikely (!(!env.in_seac && base && accent - && _get_path (param.cff, param.font, base, param.points, param.commands, true) - && _get_path (param.cff, param.font, accent, param.points, param.commands, true, &delta)))) + && _get_path (param.cff, param.font, base, param.funcs, param.user_data, true) + && _get_path (param.cff, param.font, accent, param.funcs, param.user_data, true, &delta)))) env.set_error (); } }; -bool _get_path (const OT::cff1::accelerator_t *cff, hb_font_t *font, hb_codepoint_t glyph, hb_vector_t *points, hb_vector_t *commands, bool in_seac, point_t *delta) +bool _get_path (const OT::cff1::accelerator_t *cff, hb_font_t *font, hb_codepoint_t glyph, + hb_ot_glyph_decompose_funcs_t *funcs, void *user_data, bool in_seac, point_t *delta) { if (unlikely (!cff->is_valid () || (glyph >= cff->num_glyphs))) return false; @@ -443,19 +457,20 @@ bool _get_path (const OT::cff1::accelerator_t *cff, hb_font_t *font, hb_codepoin interp.env.init (str, *cff, fd); interp.env.set_in_seac (in_seac); cff1_path_param_t param; - param.init (cff, font, points, commands, delta); + param.init (cff, font, funcs, user_data, delta); if (unlikely (!interp.interpret (param))) return false; return true; } -bool OT::cff1::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, hb_vector_t *points, hb_vector_t *commands) const +bool OT::cff1::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, + hb_ot_glyph_decompose_funcs_t *funcs, void *user_data) const { #ifdef HB_NO_OT_FONT_CFF /* XXX Remove check when this code moves to .hh file. */ return true; #endif - return _get_path (this, font, glyph, points, commands); + return _get_path (this, font, glyph, funcs, user_data); } struct get_seac_param_t diff --git a/src/hb-ot-cff1-table.hh b/src/hb-ot-cff1-table.hh index 1ecd66748..ae5519499 100644 --- a/src/hb-ot-cff1-table.hh +++ b/src/hb-ot-cff1-table.hh @@ -1347,7 +1347,8 @@ struct cff1 HB_INTERNAL bool get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const; HB_INTERNAL bool get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const; - HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, hb_vector_t *points, hb_vector_t *commands) const; + HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, + hb_ot_glyph_decompose_funcs_t *funcs, void *user_data) const; private: struct gname_t diff --git a/src/hb-ot-cff2-table.cc b/src/hb-ot-cff2-table.cc index da1e719cb..01ee17b8d 100644 --- a/src/hb-ot-cff2-table.cc +++ b/src/hb-ot-cff2-table.cc @@ -144,29 +144,42 @@ bool OT::cff2::accelerator_t::get_extents (hb_font_t *font, struct cff2_path_param_t { - void init (hb_font_t *font_, hb_vector_t *points_, hb_vector_t *commands_) + void init (hb_font_t *font_, hb_ot_glyph_decompose_funcs_t *funcs_, void *user_data_) { path_open = false; font = font_; - points = points_; - commands = commands_; + funcs = funcs_; + user_data = user_data_; } void start_path () { path_open = true; } void end_path () { path_open = false; } bool is_path_open () const { return path_open; } - void push_point (const point_t &p) + void move_to (const point_t &p) { - points->push (font->em_scalef_x (p.x.to_real ())); - points->push (font->em_scalef_y (p.y.to_real ())); + funcs->move_to (font->em_scalef_x (p.x.to_real ()), font->em_scalef_y (p.y.to_real ()), + user_data); + } + + void line_to (const point_t &p) + { + funcs->line_to (font->em_scalef_x (p.x.to_real ()), font->em_scalef_y (p.y.to_real ()), + user_data); + } + + void cubic_to (const point_t &p1, const point_t &p2, const point_t &p3) + { + funcs->cubic_to (font->em_scalef_x (p1.x.to_real ()), font->em_scalef_y (p1.y.to_real ()), + font->em_scalef_x (p2.x.to_real ()), font->em_scalef_y (p2.y.to_real ()), + font->em_scalef_x (p3.x.to_real ()), font->em_scalef_y (p3.y.to_real ()), + user_data); } - void push_command (uint8_t c) { commands->push (c); } bool path_open; hb_font_t *font; - hb_vector_t *points; - hb_vector_t *commands; + hb_ot_glyph_decompose_funcs_t *funcs; + void *user_data; }; struct cff2_path_procs_path_t : path_procs_t @@ -174,44 +187,29 @@ struct cff2_path_procs_path_t : path_procs_t {}; -bool OT::cff2::accelerator_t::get_path (hb_font_t *font, - hb_codepoint_t glyph, - hb_vector_t *points, - hb_vector_t *commands) const +bool OT::cff2::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, + hb_ot_glyph_decompose_funcs_t *funcs, void *user_data) const { #ifdef HB_NO_OT_FONT_CFF /* XXX Remove check when this code moves to .hh file. */ @@ -225,7 +223,7 @@ bool OT::cff2::accelerator_t::get_path (hb_font_t *font, const byte_str_t str = (*charStrings)[glyph]; interp.env.init (str, *this, fd, font->coords, font->num_coords); cff2_path_param_t param; - param.init (font, points, commands); + param.init (font, funcs, user_data); if (unlikely (!interp.interpret (param))) return false; return true; } diff --git a/src/hb-ot-cff2-table.hh b/src/hb-ot-cff2-table.hh index bbaa15301..50620ecfc 100644 --- a/src/hb-ot-cff2-table.hh +++ b/src/hb-ot-cff2-table.hh @@ -533,10 +533,8 @@ struct cff2 HB_INTERNAL bool get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const; - HB_INTERNAL bool get_path (hb_font_t *font, - hb_codepoint_t glyph, - hb_vector_t *points, - hb_vector_t *commands) const; + HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, + hb_ot_glyph_decompose_funcs_t *funcs, void *user_data) const; }; typedef accelerator_templ_t accelerator_subset_t; diff --git a/src/hb-ot-glyph.cc b/src/hb-ot-glyph.cc index a58650b10..065a2c4ca 100644 --- a/src/hb-ot-glyph.cc +++ b/src/hb-ot-glyph.cc @@ -39,44 +39,9 @@ hb_ot_glyph_decompose (hb_font_t *font, hb_codepoint_t glyph, if (unlikely (!funcs || glyph >= font->face->get_num_glyphs ())) return false; if (font->face->table.glyf->get_path (font, glyph, funcs, user_data)) return true; - -#ifndef HB_NO_OT_FONT_CFF - hb_vector_t coords; - hb_vector_t commands; - - bool ret = false; - if (!ret) ret = font->face->table.cff1->get_path (font, glyph, &coords, &commands); - if (!ret) ret = font->face->table.cff2->get_path (font, glyph, &coords, &commands); - - if (unlikely (!ret || coords.length % 2 != 0)) return false; - - /* FIXME: We should do all these memory O(1) without hb_vector_t - by moving the logic to the tables */ - unsigned int coords_idx = 0; - for (unsigned int i = 0; i < commands.length; ++i) - switch (commands[i]) - { - case 'Z': break; - case 'M': - if (unlikely (coords.length < coords_idx + 2)) return false; - funcs->move_to (coords[coords_idx + 0], coords[coords_idx + 1], user_data); - coords_idx += 2; - break; - case 'L': - if (unlikely (coords.length < coords_idx + 2)) return false; - funcs->line_to (coords[coords_idx + 0], coords[coords_idx + 1], user_data); - coords_idx += 2; - break; - case 'C': - if (unlikely (coords.length >= coords_idx + 6)) return false; - funcs->cubic_to (coords[coords_idx + 0], coords[coords_idx + 1], - coords[coords_idx + 2], coords[coords_idx + 3], - coords[coords_idx + 4], coords[coords_idx + 5], user_data); - coords_idx += 6; - break; - } - - return true; +#ifndef HB_NO_CFF + if (font->face->table.cff1->get_path (font, glyph, funcs, user_data)) return true; + if (font->face->table.cff2->get_path (font, glyph, funcs, user_data)) return true; #endif return false;