[ot-glyphs] Move CFF glyph decompose logic to their tables
Thus making path decompose zero alloc on CFF/CFF2
This commit is contained in:
parent
6118523502
commit
084a8182fb
@ -522,14 +522,12 @@ hb_ot_font_set_funcs
|
||||
|
||||
<SECTION>
|
||||
<FILE>hb-ot-glyph</FILE>
|
||||
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
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
|
@ -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<hb_position_t> *points_, hb_vector_t<uint8_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<hb_position_t> *points;
|
||||
hb_vector_t<uint8_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<cff1_path_procs_path_t, cff1_cs_int
|
||||
static void moveto (cff1_cs_interp_env_t &env, cff1_path_param_t& param, const point_t &pt)
|
||||
{
|
||||
param.end_path ();
|
||||
param.move_to (pt);
|
||||
env.moveto (pt);
|
||||
param.push_command ('M');
|
||||
}
|
||||
|
||||
static void line (cff1_cs_interp_env_t &env, cff1_path_param_t& param, const point_t &pt1)
|
||||
{
|
||||
if (!param.is_path_open ())
|
||||
{
|
||||
param.start_path ();
|
||||
param.push_point (env.get_pt ());
|
||||
}
|
||||
if (!param.is_path_open ()) param.start_path ();
|
||||
param.line_to (pt1);
|
||||
env.moveto (pt1);
|
||||
param.push_point (env.get_pt ());
|
||||
param.push_command ('L');
|
||||
}
|
||||
|
||||
static void curve (cff1_cs_interp_env_t &env, cff1_path_param_t& param, const point_t &pt1, const point_t &pt2, const point_t &pt3)
|
||||
{
|
||||
if (!param.is_path_open ())
|
||||
{
|
||||
param.start_path ();
|
||||
param.push_point (env.get_pt ());
|
||||
}
|
||||
/* include control points */
|
||||
param.push_point (pt1);
|
||||
param.push_point (pt2);
|
||||
if (!param.is_path_open ()) param.start_path ();
|
||||
param.cubic_to (pt1, pt2, pt3);
|
||||
env.moveto (pt3);
|
||||
param.push_point (env.get_pt ());
|
||||
param.push_command ('C');
|
||||
}
|
||||
};
|
||||
|
||||
static bool _get_path (const OT::cff1::accelerator_t *cff, hb_font_t *font, hb_codepoint_t glyph, hb_vector_t<hb_position_t> *points, hb_vector_t<uint8_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<cff1_cs_opset_path_t, cff1_path_param_t, cff1_path_procs_path_t>
|
||||
{
|
||||
@ -427,13 +440,14 @@ struct cff1_cs_opset_path_t : cff1_cs_opset_t<cff1_cs_opset_path_t, cff1_path_pa
|
||||
hb_codepoint_t accent = param.cff->std_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<hb_position_t> *points, hb_vector_t<uint8_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<hb_position_t> *points, hb_vector_t<uint8_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
|
||||
|
@ -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<hb_position_t> *points, hb_vector_t<uint8_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
|
||||
|
@ -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<hb_position_t> *points_, hb_vector_t<uint8_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<hb_position_t> *points;
|
||||
hb_vector_t<uint8_t> *commands;
|
||||
hb_ot_glyph_decompose_funcs_t *funcs;
|
||||
void *user_data;
|
||||
};
|
||||
|
||||
struct cff2_path_procs_path_t : path_procs_t<cff2_path_procs_path_t, cff2_cs_interp_env_t, cff2_path_param_t>
|
||||
@ -174,44 +187,29 @@ struct cff2_path_procs_path_t : path_procs_t<cff2_path_procs_path_t, cff2_cs_int
|
||||
static void moveto (cff2_cs_interp_env_t &env, cff2_path_param_t& param, const point_t &pt)
|
||||
{
|
||||
param.end_path ();
|
||||
param.move_to (pt);
|
||||
env.moveto (pt);
|
||||
param.push_command ('M');
|
||||
}
|
||||
|
||||
static void line (cff2_cs_interp_env_t &env, cff2_path_param_t& param, const point_t &pt1)
|
||||
{
|
||||
if (!param.is_path_open ())
|
||||
{
|
||||
param.start_path ();
|
||||
param.push_point (env.get_pt ());
|
||||
}
|
||||
if (!param.is_path_open ()) param.start_path ();
|
||||
param.line_to (pt1);
|
||||
env.moveto (pt1);
|
||||
param.push_point (env.get_pt ());
|
||||
param.push_command ('L');
|
||||
}
|
||||
|
||||
static void curve (cff2_cs_interp_env_t &env, cff2_path_param_t& param, const point_t &pt1, const point_t &pt2, const point_t &pt3)
|
||||
{
|
||||
if (!param.is_path_open ())
|
||||
{
|
||||
param.start_path ();
|
||||
param.push_point (env.get_pt ());
|
||||
}
|
||||
/* include control points */
|
||||
param.push_point (pt1);
|
||||
param.push_point (pt2);
|
||||
if (!param.is_path_open ()) param.start_path ();
|
||||
param.cubic_to (pt1, pt2, pt3);
|
||||
env.moveto (pt3);
|
||||
param.push_point (env.get_pt ());
|
||||
param.push_command ('C');
|
||||
}
|
||||
};
|
||||
|
||||
struct cff2_cs_opset_path_t : cff2_cs_opset_t<cff2_cs_opset_path_t, cff2_path_param_t, cff2_path_procs_path_t> {};
|
||||
|
||||
bool OT::cff2::accelerator_t::get_path (hb_font_t *font,
|
||||
hb_codepoint_t glyph,
|
||||
hb_vector_t<hb_position_t> *points,
|
||||
hb_vector_t<uint8_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;
|
||||
}
|
||||
|
@ -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<hb_position_t> *points,
|
||||
hb_vector_t<uint8_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<cff2_private_dict_opset_subset_t, cff2_private_dict_values_subset_t> accelerator_subset_t;
|
||||
|
@ -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<hb_position_t> coords;
|
||||
hb_vector_t<uint8_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;
|
||||
|
Loading…
Reference in New Issue
Block a user