static Eina_Bool
_ector_renderer_software_gradient_radial_ector_renderer_generic_base_prepare(Eo *obj, Ector_Renderer_Software_Gradient_Data *pd)
{
   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);
     }

   _update_radial_data(pd);
   return EINA_FALSE;
}
static Eina_Bool
_ector_renderer_cairo_gradient_radial_ector_renderer_generic_base_prepare(Eo *obj, Ector_Renderer_Cairo_Gradient_Radial_Data *pd)
{
   Ector_Renderer_Generic_Gradient_Radial_Data *grd;
   Ector_Renderer_Generic_Gradient_Data *gd;
   unsigned int i;

   eo_do_super(obj, ECTOR_RENDERER_CAIRO_GRADIENT_RADIAL_CLASS, ector_renderer_prepare());

   if (pd->pat) return EINA_FALSE;

   grd = eo_data_scope_get(obj, ECTOR_RENDERER_GENERIC_GRADIENT_RADIAL_MIXIN);
   gd = eo_data_scope_get(obj, ECTOR_RENDERER_GENERIC_GRADIENT_MIXIN);
   if (!grd || !gd) return EINA_FALSE;

   USE(obj, cairo_pattern_create_radial, EINA_FALSE);
   USE(obj, cairo_pattern_add_color_stop_rgba, EINA_FALSE);

   pd->pat = cairo_pattern_create_radial(grd->focal.x, grd->focal.y, 0,
                                         grd->radial.x, grd->radial.y, grd->radius);

   int r,g,b,a;
   for (i = 0; i < gd->colors_count; i++)
     {
       r = gd->colors[i].r;
       g = gd->colors[i].g;
       b = gd->colors[i].b;
       a = gd->colors[i].a;
       ector_color_argb_unpremul(a, &r, &g, &b);
       cairo_pattern_add_color_stop_rgba(pd->pat, gd->colors[i].offset, r/255.0, g/255.0, b/255.0, a/255.0);
     }

   USE(obj, cairo_pattern_set_extend, EINA_FALSE);
   cairo_pattern_set_extend(pd->pat, _ector_cairo_extent_get(gd->s));

   if (!pd->parent)
     {
        Eo *parent;

        eo_do(obj, parent = eo_parent_get());
        if (!parent) return EINA_FALSE;
        pd->parent = eo_data_xref(parent, ECTOR_CAIRO_SURFACE_CLASS, obj);
     }

   return EINA_FALSE;
}
static Eina_Bool
_ector_renderer_software_shape_ector_renderer_generic_base_prepare(Eo *obj, Ector_Renderer_Software_Shape_Data *pd)
{
   const Efl_Gfx_Path_Command *cmds = NULL;
   const double *pts = NULL;

   // 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;
     }

   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();

        for (; *cmds != EFL_GFX_PATH_COMMAND_TYPE_END; cmds++)
          {
             switch (*cmds)
               {
                case EFL_GFX_PATH_COMMAND_TYPE_MOVE_TO:

                   _outline_move_to(outline, pts[0], pts[1]);

                   pts += 2;
                   break;
                case EFL_GFX_PATH_COMMAND_TYPE_LINE_TO:

                   _outline_line_to(outline, pts[0], pts[1]);

                   pts += 2;
                   break;
                case EFL_GFX_PATH_COMMAND_TYPE_CUBIC_TO:

                   // 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;

                case EFL_GFX_PATH_COMMAND_TYPE_CLOSE:

                   close_path = _outline_close_path(outline);
                   break;

                case EFL_GFX_PATH_COMMAND_TYPE_LAST:
                case EFL_GFX_PATH_COMMAND_TYPE_END:
                   break;
               }
          }

        _outline_end(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)
          {
             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);
          }

        _outline_destroy(outline);
     }

   return EINA_TRUE;
}