cedric pushed a commit to branch master. http://git.enlightenment.org/core/efl.git/commit/?id=8b075c65348e460166aa964c48f379938cd0bc7d
commit 8b075c65348e460166aa964c48f379938cd0bc7d Author: Subhransu Mohanty <sub.moha...@samsung.com> Date: Mon Aug 17 14:26:40 2015 +0900 ector: refactored shape generation in software backend. Signed-off-by: Cedric BAIL <ced...@osg.samsung.com> --- .../ector/software/ector_renderer_software_shape.c | 284 +++++++++++++-------- 1 file changed, 178 insertions(+), 106 deletions(-) diff --git a/src/lib/ector/software/ector_renderer_software_shape.c b/src/lib/ector/software/ector_renderer_software_shape.c index 1c985d4..2ea12ee 100644 --- a/src/lib/ector/software/ector_renderer_software_shape.c +++ b/src/lib/ector/software/ector_renderer_software_shape.c @@ -30,18 +30,38 @@ typedef struct _Outline int contours_alloc; }Outline; + +static inline void +_grow_outline_contour(Outline *outline, int num) +{ + if ( outline->ft_outline.n_contours + num > outline->contours_alloc) + { + outline->contours_alloc += 5; + outline->ft_outline.contours = (short *) realloc(outline->ft_outline.contours, + outline->contours_alloc * sizeof(short)); + } +} + +static inline void +_grow_outline_points(Outline *outline, int num) +{ + if ( outline->ft_outline.n_points + num > outline->points_alloc) + { + outline->points_alloc += 50; + outline->ft_outline.points = (SW_FT_Vector *) realloc(outline->ft_outline.points, + outline->points_alloc * sizeof(SW_FT_Vector)); + outline->ft_outline.tags = (char *) realloc(outline->ft_outline.tags, + outline->points_alloc * sizeof(char)); + } +} static Outline * _outline_create() { Outline *outline = (Outline *) calloc(1, sizeof(Outline)); - - outline->ft_outline.points = (SW_FT_Vector *) calloc(50, sizeof(SW_FT_Vector)); - outline->ft_outline.tags = (char *) calloc(50, sizeof(char)); - - outline->ft_outline.contours = (short *) calloc(5, sizeof(short)); - - outline->points_alloc = 50; - outline->contours_alloc = 5; + outline->points_alloc = 0; + outline->contours_alloc = 0; + _grow_outline_contour(outline, 1); + _grow_outline_points(outline, 1); return outline; } @@ -63,17 +83,14 @@ _outline_move_to(Outline *outline, double x, double y) { SW_FT_Outline *ft_outline = &outline->ft_outline; - if (ft_outline->n_contours == outline->contours_alloc) - { - outline->contours_alloc += 5; - ft_outline->contours = (short *) realloc(ft_outline->contours, outline->contours_alloc * sizeof(short)); - } + _grow_outline_points(outline, 1); ft_outline->points[ft_outline->n_points].x = x; ft_outline->points[ft_outline->n_points].y = y; ft_outline->tags[ft_outline->n_points] = SW_FT_CURVE_TAG_ON; if (ft_outline->n_points) { + _grow_outline_contour(outline, 1); ft_outline->contours[ft_outline->n_contours] = ft_outline->n_points - 1; ft_outline->n_contours++; } @@ -86,11 +103,7 @@ _outline_end(Outline *outline) { SW_FT_Outline *ft_outline = &outline->ft_outline; - if (ft_outline->n_contours == outline->contours_alloc) - { - outline->contours_alloc += 1; - ft_outline->contours = (short *) realloc(ft_outline->contours, outline->contours_alloc * sizeof(short)); - } + _grow_outline_contour(outline, 1); if (ft_outline->n_points) { @@ -104,12 +117,7 @@ static void _outline_line_to(Outline *outline, double x, double y) { SW_FT_Outline *ft_outline = &outline->ft_outline; - if (ft_outline->n_points == outline->points_alloc) - { - outline->points_alloc += 50; - ft_outline->points = (SW_FT_Vector *) realloc(ft_outline->points, outline->points_alloc * sizeof(SW_FT_Vector)); - ft_outline->tags = (char *) realloc(ft_outline->tags, outline->points_alloc * sizeof(char)); - } + _grow_outline_points(outline, 1); ft_outline->points[ft_outline->n_points].x = x; ft_outline->points[ft_outline->n_points].y = y; ft_outline->tags[ft_outline->n_points] = SW_FT_CURVE_TAG_ON; @@ -141,16 +149,12 @@ _outline_close_path(Outline *outline) } -static void _outline_cubic_to(Outline *outline, double cx1, double cy1, double cx2, double cy2, double x, double y) +static void _outline_cubic_to(Outline *outline, double cx1, double cy1, + double cx2, double cy2, double x, double y) { SW_FT_Outline *ft_outline = &outline->ft_outline; - if (ft_outline->n_points == outline->points_alloc) - { - outline->points_alloc += 50; - ft_outline->points = (SW_FT_Vector *) realloc(ft_outline->points, outline->points_alloc * sizeof(SW_FT_Vector)); - ft_outline->tags = (char *) realloc(ft_outline->tags, outline->points_alloc * sizeof(char)); - } + _grow_outline_points(outline, 3); ft_outline->points[ft_outline->n_points].x = cx1; ft_outline->points[ft_outline->n_points].y = cy1; @@ -171,14 +175,17 @@ static void _outline_cubic_to(Outline *outline, double cx1, double cy1, double static void _outline_transform(Outline *outline, Eina_Matrix3 *m) { int i; + double x, y; SW_FT_Outline *ft_outline = &outline->ft_outline; if (m) { - double x, y; for (i = 0; i < ft_outline->n_points; i++) { - eina_matrix3_point_transform(m, ft_outline->points[i].x, ft_outline->points[i].y, &x, &y); + eina_matrix3_point_transform(m, + ft_outline->points[i].x, + ft_outline->points[i].y, + &x, &y); ft_outline->points[i].x = (int)(x * 64);// to freetype 26.6 coordinate. ft_outline->points[i].y = (int)(y * 64); } @@ -193,98 +200,145 @@ static void _outline_transform(Outline *outline, Eina_Matrix3 *m) } } - static Eina_Bool -_ector_renderer_software_shape_ector_renderer_generic_base_prepare(Eo *obj, Ector_Renderer_Software_Shape_Data *pd) +_generate_outline(const Efl_Gfx_Path_Command *cmds, const double *pts, Outline * outline) { - const Efl_Gfx_Path_Command *cmds = NULL; - const double *pts = NULL; + Eina_Bool close_path = EINA_FALSE; + for (; *cmds != EFL_GFX_PATH_COMMAND_TYPE_END; cmds++) + { + switch (*cmds) + { + case EFL_GFX_PATH_COMMAND_TYPE_MOVE_TO: - // FIXME: shouldn't that be part of the shape generic implementation ? - if (pd->shape->fill) - eo_do(pd->shape->fill, ector_renderer_prepare()); - if (pd->shape->stroke.fill) - eo_do(pd->shape->stroke.fill, ector_renderer_prepare()); - if (pd->shape->stroke.marker) - eo_do(pd->shape->stroke.marker, ector_renderer_prepare()); + _outline_move_to(outline, pts[0], pts[1]); - // shouldn't that be moved to the software base object - if (!pd->surface) - { - Eo *parent; - eo_do(obj, parent = eo_parent_get()); - if (!parent) return EINA_FALSE; - pd->surface = eo_data_xref(parent, ECTOR_SOFTWARE_SURFACE_CLASS, obj); - if (!pd->surface) return EINA_FALSE; - } + pts += 2; + break; + case EFL_GFX_PATH_COMMAND_TYPE_LINE_TO: - eo_do(obj, efl_gfx_shape_path_get(&cmds, &pts)); - if (!pd->shape_data && cmds) - { - Eina_Bool close_path = EINA_FALSE; - Outline * outline = _outline_create(); + _outline_line_to(outline, pts[0], pts[1]); - for (; *cmds != EFL_GFX_PATH_COMMAND_TYPE_END; cmds++) - { - switch (*cmds) - { - case EFL_GFX_PATH_COMMAND_TYPE_MOVE_TO: + pts += 2; + break; + case EFL_GFX_PATH_COMMAND_TYPE_CUBIC_TO: - _outline_move_to(outline, pts[0], pts[1]); + // Be careful, we do have a different order than + // cairo, first is destination point, followed by + // the control point. The opposite of cairo. + _outline_cubic_to(outline, + pts[2], pts[3], pts[4], pts[5], // control points + pts[0], pts[1]); // destination point + pts += 6; + break; - pts += 2; - break; - case EFL_GFX_PATH_COMMAND_TYPE_LINE_TO: + case EFL_GFX_PATH_COMMAND_TYPE_CLOSE: - _outline_line_to(outline, pts[0], pts[1]); + close_path = _outline_close_path(outline); + break; - pts += 2; - break; - case EFL_GFX_PATH_COMMAND_TYPE_CUBIC_TO: + case EFL_GFX_PATH_COMMAND_TYPE_LAST: + case EFL_GFX_PATH_COMMAND_TYPE_END: + break; + } + } + _outline_end(outline); + return close_path; +} - // Be careful, we do have a different order than - // cairo, first is destination point, followed by - // the control point. The opposite of cairo. - _outline_cubic_to(outline, - pts[2], pts[3], pts[4], pts[5], // control points - pts[0], pts[1]); // destination point - pts += 6; - break; +static Eina_Bool +_generate_stroke_data(Ector_Renderer_Software_Shape_Data *pd) +{ + if (pd->outline_data) return EINA_FALSE; - case EFL_GFX_PATH_COMMAND_TYPE_CLOSE: + if (!pd->shape->stroke.fill && + ((pd->shape->stroke.color.a == 0) || + (pd->shape->stroke.width < 0.01))) + return EINA_FALSE; - close_path = _outline_close_path(outline); - break; + return EINA_TRUE; +} - case EFL_GFX_PATH_COMMAND_TYPE_LAST: - case EFL_GFX_PATH_COMMAND_TYPE_END: - break; - } - } +static Eina_Bool +_generate_shape_data(Ector_Renderer_Software_Shape_Data *pd) +{ + if (pd->shape_data) return EINA_FALSE; + + if (!pd->shape->fill && (pd->base->color.a == 0)) return EINA_FALSE; + + return EINA_TRUE; +} + +static void +_update_rle(Eo *obj, Ector_Renderer_Software_Shape_Data *pd) +{ + const Efl_Gfx_Path_Command *cmds = NULL; + const double *pts = NULL; + Eina_Bool close_path; + Outline *outline, *dash_outline; - _outline_end(outline); + eo_do(obj, efl_gfx_shape_path_get(&cmds, &pts)); + if (cmds && (_generate_stroke_data(pd) || _generate_shape_data(pd))) + { + outline = _outline_create(); + close_path = _generate_outline(cmds, pts, outline); _outline_transform(outline, pd->base->m); - // generate the shape data. - pd->shape_data = ector_software_rasterizer_generate_rle_data(pd->surface->software, &outline->ft_outline); - if (!pd->outline_data) + //shape data generation + if (_generate_shape_data(pd)) + pd->shape_data = ector_software_rasterizer_generate_rle_data(pd->surface->software, + &outline->ft_outline); + + //stroke data generation + if ( _generate_stroke_data(pd)) { - ector_software_rasterizer_stroke_set(pd->surface->software, (pd->shape->stroke.width * pd->shape->stroke.scale), pd->shape->stroke.cap, + ector_software_rasterizer_stroke_set(pd->surface->software, + (pd->shape->stroke.width * + pd->shape->stroke.scale), + pd->shape->stroke.cap, pd->shape->stroke.join); - pd->outline_data = ector_software_rasterizer_generate_stroke_rle_data(pd->surface->software, &outline->ft_outline, close_path); + pd->outline_data = ector_software_rasterizer_generate_stroke_rle_data(pd->surface->software, + &outline->ft_outline, + close_path); } - _outline_destroy(outline); } +} + +static Eina_Bool +_ector_renderer_software_shape_ector_renderer_generic_base_prepare(Eo *obj, + Ector_Renderer_Software_Shape_Data *pd) +{ + // FIXME: shouldn't that be part of the shape generic implementation ? + if (pd->shape->fill) + eo_do(pd->shape->fill, ector_renderer_prepare()); + if (pd->shape->stroke.fill) + eo_do(pd->shape->stroke.fill, ector_renderer_prepare()); + if (pd->shape->stroke.marker) + eo_do(pd->shape->stroke.marker, ector_renderer_prepare()); + // shouldn't that be moved to the software base object + if (!pd->surface) + { + Eo *parent; + eo_do(obj, parent = eo_parent_get()); + if (!parent) return EINA_FALSE; + pd->surface = eo_data_xref(parent, ECTOR_SOFTWARE_SURFACE_CLASS, obj); + if (!pd->surface) return EINA_FALSE; + } return EINA_TRUE; } static Eina_Bool -_ector_renderer_software_shape_ector_renderer_generic_base_draw(Eo *obj EINA_UNUSED, Ector_Renderer_Software_Shape_Data *pd, Ector_Rop op, Eina_Array *clips, unsigned int mul_col) +_ector_renderer_software_shape_ector_renderer_generic_base_draw(Eo *obj, + Ector_Renderer_Software_Shape_Data *pd, + Ector_Rop op, Eina_Array *clips, + unsigned int mul_col) { int x, y; + // do lazy creation of rle + _update_rle(obj, pd); + // adjust the offset x = pd->surface->x + (int)pd->base->origin.x; y = pd->surface->y + (int)pd->base->origin.y; @@ -296,30 +350,44 @@ _ector_renderer_software_shape_ector_renderer_generic_base_draw(Eo *obj EINA_UNU if (pd->shape->fill) { eo_do(pd->shape->fill, ector_renderer_software_base_fill()); - ector_software_rasterizer_draw_rle_data(pd->surface->software, x, y, mul_col, op, pd->shape_data); + ector_software_rasterizer_draw_rle_data(pd->surface->software, + x, y, mul_col, op, + pd->shape_data); } else { if (pd->base->color.a > 0) { - ector_software_rasterizer_color_set(pd->surface->software, pd->base->color.r, pd->base->color.g, pd->base->color.b, pd->base->color.a); - ector_software_rasterizer_draw_rle_data(pd->surface->software, x, y, mul_col, op, pd->shape_data); + ector_software_rasterizer_color_set(pd->surface->software, + pd->base->color.r, + pd->base->color.g, + pd->base->color.b, + pd->base->color.a); + ector_software_rasterizer_draw_rle_data(pd->surface->software, + x, y, mul_col, op, + pd->shape_data); } } if (pd->shape->stroke.fill) { eo_do(pd->shape->stroke.fill, ector_renderer_software_base_fill()); - ector_software_rasterizer_draw_rle_data(pd->surface->software, x, y, mul_col, op, pd->outline_data); + ector_software_rasterizer_draw_rle_data(pd->surface->software, + x, y, mul_col, op, + pd->outline_data); } else { if (pd->shape->stroke.color.a > 0) { ector_software_rasterizer_color_set(pd->surface->software, - pd->shape->stroke.color.r, pd->shape->stroke.color.g, - pd->shape->stroke.color.b, pd->shape->stroke.color.a); - ector_software_rasterizer_draw_rle_data(pd->surface->software, x, y, mul_col, op, pd->outline_data); + pd->shape->stroke.color.r, + pd->shape->stroke.color.g, + pd->shape->stroke.color.b, + pd->shape->stroke.color.a); + ector_software_rasterizer_draw_rle_data(pd->surface->software, + x, y, mul_col, op, + pd->outline_data); } } @@ -327,7 +395,8 @@ _ector_renderer_software_shape_ector_renderer_generic_base_draw(Eo *obj EINA_UNU } static Eina_Bool -_ector_renderer_software_shape_ector_renderer_software_base_fill(Eo *obj EINA_UNUSED, Ector_Renderer_Software_Shape_Data *pd EINA_UNUSED) +_ector_renderer_software_shape_ector_renderer_software_base_fill(Eo *obj EINA_UNUSED, + Ector_Renderer_Software_Shape_Data *pd EINA_UNUSED) { // FIXME: let's find out how to fill a shape with a shape later. // I need to read SVG specification and see how to map that with software. @@ -335,8 +404,10 @@ _ector_renderer_software_shape_ector_renderer_software_base_fill(Eo *obj EINA_UN } static void -_ector_renderer_software_shape_efl_gfx_shape_path_set(Eo *obj, Ector_Renderer_Software_Shape_Data *pd, - const Efl_Gfx_Path_Command *op, const double *points) +_ector_renderer_software_shape_efl_gfx_shape_path_set(Eo *obj, + Ector_Renderer_Software_Shape_Data *pd, + const Efl_Gfx_Path_Command *op, + const double *points) { if (pd->shape_data) ector_software_rasterizer_destroy_rle_data(pd->shape_data); if (pd->outline_data) ector_software_rasterizer_destroy_rle_data(pd->outline_data); @@ -348,7 +419,8 @@ _ector_renderer_software_shape_efl_gfx_shape_path_set(Eo *obj, Ector_Renderer_So static Eina_Bool -_ector_renderer_software_shape_path_changed(void *data, Eo *obj EINA_UNUSED, const Eo_Event_Description *desc EINA_UNUSED, +_ector_renderer_software_shape_path_changed(void *data, Eo *obj EINA_UNUSED, + const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED) { Ector_Renderer_Software_Shape_Data *pd = data; --