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;