From e9ef999de60cf938a28b89046a830d68f14aaa82 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Mon, 24 Dec 2018 13:52:13 +0900 Subject: [PATCH] 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 --- src/lib/efl/interfaces/efl_gfx_path.c | 96 +++++++++++++++++--------- src/lib/efl/interfaces/efl_gfx_path.eo | 12 ++++ 2 files changed, 77 insertions(+), 31 deletions(-) diff --git a/src/lib/efl/interfaces/efl_gfx_path.c b/src/lib/efl/interfaces/efl_gfx_path.c index cd948ddd3c..7278216647 100644 --- a/src/lib/efl/interfaces/efl_gfx_path.c +++ b/src/lib/efl/interfaces/efl_gfx_path.c @@ -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; diff --git a/src/lib/efl/interfaces/efl_gfx_path.eo b/src/lib/efl/interfaces/efl_gfx_path.eo index 1efb7fc95e..c1ec7aacc4 100644 --- a/src/lib/efl/interfaces/efl_gfx_path.eo +++ b/src/lib/efl/interfaces/efl_gfx_path.eo @@ -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.]]