efl gfx_path: introduce efl_gfx_path_reserve()

Summary:
This method reserves path commands buffer in advance.
If user know the count of path commands coming,
they can reserve commands buffer in advance to avoid buffer growing job.

This reserved buffer would grow up by double size, if the buffer is full.

@feature

Reviewers: #committers, cedric

Reviewed By: #committers, cedric

Subscribers: cedric, #reviewers, #committers

Tags: #efl

Differential Revision: https://phab.enlightenment.org/D7456
This commit is contained in:
Hermet Park 2018-12-24 13:52:13 +09:00
parent 47728f0c89
commit e9ef999de6
2 changed files with 77 additions and 31 deletions

View File

@ -22,10 +22,17 @@ struct _Efl_Gfx_Path_Data
unsigned int commands_count;
unsigned int points_count;
unsigned int reserved_pts_cnt; //Reserved Points Count
unsigned int reserved_cmd_cnt; //Reserved Commands Count
char *path_data;
Eina_Bool convex;
};
static void _path_interpolation(Eo *obj, Efl_Gfx_Path_Data *pd, char *from, char *to, double pos);
static void _efl_gfx_path_reset(Eo *obj, Efl_Gfx_Path_Data *pd);
static inline unsigned int
_efl_gfx_path_command_length(Efl_Gfx_Path_Command command)
{
@ -65,8 +72,6 @@ efl_gfx_path_grow(Efl_Gfx_Path_Command command,
Efl_Gfx_Path_Data *pd,
double **offset_point)
{
Efl_Gfx_Path_Command *cmd_tmp;
double *pts_tmp;
unsigned int cmd_length = 0, pts_length = 0;
cmd_length = pd->commands_count ? pd->commands_count : 1;
@ -75,27 +80,38 @@ efl_gfx_path_grow(Efl_Gfx_Path_Command command,
if (_efl_gfx_path_command_length(command))
{
pts_length += _efl_gfx_path_command_length(command);
pts_tmp = realloc(pd->points, pts_length * sizeof (double));
if (!pts_tmp) return EINA_FALSE;
pd->points = pts_tmp;
//grow up twice
if (pts_length > pd->reserved_pts_cnt)
{
double *pts_tmp = realloc(pd->points, sizeof(double) * (pts_length * 2));
if (!pts_tmp) return EINA_FALSE;
pd->reserved_pts_cnt = pts_length * 2;
pd->points = pts_tmp;
}
*offset_point =
pd->points + pts_length - _efl_gfx_path_command_length(command);
}
cmd_tmp = realloc(pd->commands,
(cmd_length + 1) * sizeof (Efl_Gfx_Path_Command));
if (!cmd_tmp) return EINA_FALSE;
pd->commands = cmd_tmp;
//grow up twice
if ((cmd_length + 1) > pd->reserved_cmd_cnt)
{
Efl_Gfx_Path_Command *cmd_tmp =
realloc(pd->commands, (cmd_length * 2) * sizeof (Efl_Gfx_Path_Command));
if (!cmd_tmp) return EINA_FALSE;
pd->reserved_cmd_cnt = (cmd_length * 2);
pd->commands = cmd_tmp;
}
pd->commands_count = cmd_length + 1;
pd->points_count = pts_length;
// Append the command
cmd_tmp[cmd_length - 1] = command;
pd->commands[cmd_length - 1] = command;
// NULL terminate the stream
cmd_tmp[cmd_length] = EFL_GFX_PATH_COMMAND_TYPE_END;
pd->commands[cmd_length] = EFL_GFX_PATH_COMMAND_TYPE_END;
pd->convex = EINA_FALSE;
return EINA_TRUE;
@ -148,25 +164,20 @@ _efl_gfx_path_current_search(const Efl_Gfx_Path_Command *cmd,
EOLIAN static void
_efl_gfx_path_path_set(Eo *obj, Efl_Gfx_Path_Data *pd,
const Efl_Gfx_Path_Command *commands,
const double *points)
const Efl_Gfx_Path_Command *commands,
const double *points)
{
if (!commands)
{
_efl_gfx_path_reset(obj, pd);
return;
}
Efl_Gfx_Path_Change_Event ev = { EFL_GFX_CHANGE_FLAG_PATH };
Efl_Gfx_Path_Command *cmds;
double *pts;
unsigned int cmds_length = 0, pts_length = 0;
if (!commands)
{
free(pd->commands);
pd->commands = NULL;
free(pd->points);
pd->points = NULL;
pd->current.x = pd->current.y = 0;
pd->current_ctrl.x = pd->current_ctrl.y = 0;
goto end;
}
_efl_gfx_path_length(commands, &cmds_length, &pts_length);
cmds = realloc(pd->commands, sizeof (Efl_Gfx_Path_Command) * cmds_length);
@ -181,14 +192,17 @@ _efl_gfx_path_path_set(Eo *obj, Efl_Gfx_Path_Data *pd,
pd->commands_count = cmds_length;
pd->points_count = pts_length;
memcpy(pd->commands, commands, sizeof (Efl_Gfx_Path_Command) * cmds_length);
memcpy(pd->points, points, sizeof (double) * pts_length);
//full reserved memory
pd->reserved_cmd_cnt = cmds_length;
pd->reserved_pts_cnt = pts_length;
memcpy(pd->commands, commands, sizeof(Efl_Gfx_Path_Command) * cmds_length);
memcpy(pd->points, points, sizeof(double) * pts_length);
_efl_gfx_path_current_search(pd->commands, pd->points,
&pd->current.x, &pd->current.y,
&pd->current_ctrl.x, &pd->current_ctrl.y);
end:
efl_event_callback_call(obj, EFL_GFX_PATH_EVENT_CHANGED, &ev);
}
@ -275,9 +289,6 @@ interpolate(double from, double to, double pos_map)
return (from * (1.0 - pos_map)) + (to * pos_map);
}
static void _path_interpolation(Eo *obj, Efl_Gfx_Path_Data *pd, char *from, char *to, double pos);
static void _efl_gfx_path_reset(Eo *obj, Efl_Gfx_Path_Data *pd);
EOLIAN static Eina_Bool
_efl_gfx_path_interpolate(Eo *obj, Efl_Gfx_Path_Data *pd,
const Eo *from, const Eo *to, double pos_map)
@ -344,6 +355,8 @@ _efl_gfx_path_interpolate(Eo *obj, Efl_Gfx_Path_Data *pd,
pd->points_count = from_pd->points_count;
pd->commands_count = from_pd->commands_count;
pd->reserved_cmd_cnt = from_pd->commands_count;
pd->reserved_pts_cnt = from_pd->points_count;
interv = interpolate(from_pd->current.x, to_pd->current.x, pos_map);
pd->current.x = interv;
@ -379,18 +392,39 @@ _efl_gfx_path_equal_commands(Eo *obj EINA_UNUSED,
return _efl_gfx_path_equal_commands_internal(with_pd, pd);
}
EOLIAN static void
_efl_gfx_path_reserve(Eo *obj EINA_UNUSED, Efl_Gfx_Path_Data *pd,
unsigned int cmd_count, unsigned int pts_count)
{
if (pd->reserved_cmd_cnt < cmd_count)
{
//+1 for path close.
pd->reserved_cmd_cnt = cmd_count + 1;
pd->commands = realloc(pd->commands, sizeof(Efl_Gfx_Path_Command) * pd->reserved_cmd_cnt);
}
if (pd->reserved_pts_cnt < pts_count)
{
pd->reserved_pts_cnt = pts_count;
pd->points = realloc(pd->points, sizeof(double) * pts_count);
}
}
EOLIAN static void
_efl_gfx_path_reset(Eo *obj, Efl_Gfx_Path_Data *pd)
{
Efl_Gfx_Path_Change_Event ev = { EFL_GFX_CHANGE_FLAG_PATH };
free(pd->commands);
pd->reserved_cmd_cnt = 0;
pd->commands = NULL;
pd->commands_count = 0;
free(pd->points);
pd->reserved_pts_cnt = 0;
pd->points = NULL;
pd->points_count = 0;
free(pd->path_data);
pd->path_data = NULL;

View File

@ -280,6 +280,18 @@ mixin Efl.Gfx.Path
@in with: const(Efl.Object); [[Object]]
}
}
reserve {
[[Reserve path commands buffer in advance. If you know the count of
path commands coming, you can reserve commands buffer in advance
to avoid buffer growing job.
@since 1.22
]]
params {
@in cmd_count: uint; [[Commands count to reserve]]
@in pts_count: uint; [[Pointers count to reserve]]
}
}
}
events {
changed: Efl.Gfx.Path_Change_Event; [[Graphics path was changed.]]