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;
}
{
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++;
}
{
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)
{
{
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;
}
-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;
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);
}
}
}
-
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;
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);
}
}
}
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.
}
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);
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;