ector: implementation of some common code in Ector.Renderer.Cairo.Base.

This require to make some class mixin instead of interface or abstract. So a lot
of class renaming is also necessary here.
This commit is contained in:
Cedric BAIL 2015-04-03 16:31:44 +02:00
parent bc016aa277
commit e99774946c
19 changed files with 295 additions and 41 deletions

View File

@ -50,6 +50,7 @@ lib_ector_libector_la_SOURCES += \
lib/ector/cairo/ector_renderer_cairo_gradient_linear.c \
lib/ector/cairo/ector_renderer_cairo_gradient_radial.c \
lib/ector/cairo/ector_renderer_cairo_shape.c \
lib/ector/cairo/ector_renderer_cairo_base.c \
lib/ector/cairo/ector_cairo_surface.c
lib_ector_libector_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl \

View File

@ -55,12 +55,13 @@ _ector_cairo_surface_ector_generic_surface_renderer_factory_new(Eo *obj,
Ector_Cairo_Surface_Data *pd EINA_UNUSED,
const Eo_Class *type)
{
if (type == ECTOR_RENDERER_GENERIC_SHAPE_CLASS)
if (type == ECTOR_RENDERER_GENERIC_SHAPE_MIXIN)
return eo_add(ECTOR_RENDERER_CAIRO_SHAPE_CLASS, obj);
else if (type == ECTOR_RENDERER_GENERIC_GRADIENT_LINEAR_CLASS)
else if (type == ECTOR_RENDERER_GENERIC_GRADIENT_LINEAR_MIXIN)
return eo_add(ECTOR_RENDERER_CAIRO_GRADIENT_LINEAR_CLASS, obj);
else if (type == ECTOR_RENDERER_GENERIC_GRADIENT_RADIAL_CLASS)
else if (type == ECTOR_RENDERER_GENERIC_GRADIENT_RADIAL_MIXIN)
return eo_add(ECTOR_RENDERER_CAIRO_GRADIENT_RADIAL_CLASS, obj);
ERR("Couldn't find class for type: %s\n", eo_class_name_get(type));
return NULL;
}
@ -126,4 +127,3 @@ _ector_cairo_surface_eo_base_destructor(Eo *obj EINA_UNUSED,
}
#include "ector_cairo_surface.eo.c"
#include "ector_renderer_cairo_base.eo.c"

View File

@ -0,0 +1,196 @@
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <math.h>
#include <float.h>
#include <Eina.h>
#include <Ector.h>
#include <cairo/Ector_Cairo.h>
#include "ector_private.h"
#include "ector_cairo_private.h"
typedef struct {
double xx; double yx;
double xy; double yy;
double x0; double y0;
} cairo_matrix_t;
typedef enum {
CAIRO_OPERATOR_CLEAR,
CAIRO_OPERATOR_SOURCE,
CAIRO_OPERATOR_OVER,
CAIRO_OPERATOR_IN,
CAIRO_OPERATOR_OUT,
CAIRO_OPERATOR_ATOP,
CAIRO_OPERATOR_DEST,
CAIRO_OPERATOR_DEST_OVER,
CAIRO_OPERATOR_DEST_IN,
CAIRO_OPERATOR_DEST_OUT,
CAIRO_OPERATOR_DEST_ATOP,
CAIRO_OPERATOR_XOR,
CAIRO_OPERATOR_ADD,
CAIRO_OPERATOR_SATURATE,
CAIRO_OPERATOR_MULTIPLY,
CAIRO_OPERATOR_SCREEN,
CAIRO_OPERATOR_OVERLAY,
CAIRO_OPERATOR_DARKEN,
CAIRO_OPERATOR_LIGHTEN,
CAIRO_OPERATOR_COLOR_DODGE,
CAIRO_OPERATOR_COLOR_BURN,
CAIRO_OPERATOR_HARD_LIGHT,
CAIRO_OPERATOR_SOFT_LIGHT,
CAIRO_OPERATOR_DIFFERENCE,
CAIRO_OPERATOR_EXCLUSION,
CAIRO_OPERATOR_HSL_HUE,
CAIRO_OPERATOR_HSL_SATURATION,
CAIRO_OPERATOR_HSL_COLOR,
CAIRO_OPERATOR_HSL_LUMINOSITY
} cairo_operator_t;
static void (*cairo_translate)(cairo_t *cr, double tx, double ty) = NULL;
static void (*cairo_matrix_init)(cairo_matrix_t *matrix,
double xx, double yx,
double xy, double yy,
double x0, double y0) = NULL;
static void (*cairo_transform)(cairo_t *cr, const cairo_matrix_t *matrix) = NULL;
static void (*cairo_set_source_rgba)(cairo_t *cr,
double red, double green, double blue,
double alpha) = NULL;
static void (*cairo_set_operator)(cairo_t *cr, cairo_operator_t op) = NULL;
typedef struct _Ector_Renderer_Cairo_Base_Data Ector_Renderer_Cairo_Base_Data;
struct _Ector_Renderer_Cairo_Base_Data
{
Ector_Cairo_Surface_Data *parent;
Ector_Renderer_Generic_Base_Data *generic;
cairo_matrix_t *m;
};
// Cairo need unpremul color, so force unpremul here
void
_ector_renderer_cairo_base_ector_renderer_generic_base_color_set(Eo *obj EINA_UNUSED,
Ector_Renderer_Cairo_Base_Data *pd,
int r, int g, int b, int a)
{
ector_color_argb_unpremul(a, &r ,&g, &b);
pd->generic->color.r = r;
pd->generic->color.g = g;
pd->generic->color.b = b;
pd->generic->color.a = a;
}
void
_ector_renderer_cairo_base_ector_renderer_generic_base_color_get(Eo *obj EINA_UNUSED,
Ector_Renderer_Cairo_Base_Data *pd,
int *r, int *g, int *b, int *a)
{
if (r) *r = pd->generic->color.r;
if (g) *g = pd->generic->color.g;
if (b) *b = pd->generic->color.b;
if (a) *a = pd->generic->color.a;
ector_color_argb_premul(pd->generic->color.a, r, g, b);
}
static Eina_Bool
_ector_renderer_cairo_base_ector_renderer_generic_base_prepare(Eo *obj, Ector_Renderer_Cairo_Base_Data *pd)
{
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);
}
if (pd->generic->m)
{
USE(obj, cairo_matrix_init, EINA_FALSE);
if (!pd->m) pd->m = malloc(sizeof (cairo_matrix_t));
cairo_matrix_init(pd->m,
pd->generic->m->xx, pd->generic->m->yx,
pd->generic->m->xy, pd->generic->m->yy,
pd->generic->m->xz, pd->generic->m->yz);
}
else
{
free(pd->m);
pd->m = NULL;
}
return EINA_TRUE;
}
static Eina_Bool
_ector_renderer_cairo_base_ector_renderer_generic_base_draw(Eo *obj,
Ector_Renderer_Cairo_Base_Data *pd,
Ector_Rop op,
Eina_Array *clips EINA_UNUSED,
int x, int y,
unsigned int mul_col)
{
double r, g, b, a;
cairo_operator_t cop;
USE(obj, cairo_translate, EINA_FALSE);
USE(obj, cairo_set_source_rgba, EINA_FALSE);
USE(obj, cairo_transform, EINA_FALSE);
USE(obj, cairo_set_operator, EINA_FALSE);
switch (op)
{
case ECTOR_ROP_BLEND:
cop = CAIRO_OPERATOR_OVER;
break;
case ECTOR_ROP_COPY:
default:
cop = CAIRO_OPERATOR_SOURCE;
break;
}
r = ((double)((pd->generic->color.r * R_VAL(&mul_col)) / 255)) / 255;
g = ((double)((pd->generic->color.g * G_VAL(&mul_col)) / 255)) / 255;
b = ((double)((pd->generic->color.b * B_VAL(&mul_col)) / 255)) / 255;
a = ((double)((pd->generic->color.a * A_VAL(&mul_col)) / 255)) / 255;
cairo_set_operator(pd->parent->cairo, cop);
cairo_translate(pd->parent->cairo, pd->generic->origin.x - x, pd->generic->origin.y - y);
cairo_set_source_rgba(pd->parent->cairo, r, g, b, a);
if (pd->m) cairo_transform(pd->parent->cairo, pd->m);
else cairo_transform(pd->parent->cairo, NULL);
return EINA_TRUE;
}
static void
_ector_renderer_cairo_base_eo_base_constructor(Eo *obj, Ector_Renderer_Cairo_Base_Data *pd EINA_UNUSED)
{
eo_do_super(obj, ECTOR_RENDERER_CAIRO_BASE_CLASS, eo_constructor());
pd->generic = eo_data_xref(obj, ECTOR_RENDERER_GENERIC_BASE_CLASS, obj);
}
static void
_ector_renderer_cairo_base_eo_base_destructor(Eo *obj, Ector_Renderer_Cairo_Base_Data *pd)
{
Eo *parent;
free(pd->m);
eo_do(obj, parent = eo_parent_get());
eo_data_xunref(parent, pd->parent, obj);
eo_data_xunref(obj, pd->generic, obj);
eo_do_super(obj, ECTOR_RENDERER_CAIRO_BASE_CLASS, eo_destructor());
}
#include "ector_renderer_cairo_base.eo.c"

View File

@ -1,4 +1,4 @@
interface Ector.Renderer.Cairo.Base
abstract Ector.Renderer.Cairo.Base (Ector.Renderer.Generic.Base)
{
legacy_prefix: null;
methods {
@ -6,4 +6,13 @@ interface Ector.Renderer.Cairo.Base
return: bool;
}
}
implements {
@virtual .fill;
Ector.Renderer.Generic.Base.prepare;
Ector.Renderer.Generic.Base.draw;
Ector.Renderer.Generic.Base.color.set;
Ector.Renderer.Generic.Base.color.get;
Eo.Base.constructor;
Eo.Base.destructor;
}
}

View File

@ -35,10 +35,12 @@ _ector_renderer_cairo_gradient_linear_ector_renderer_generic_base_prepare(Eo *ob
Ector_Renderer_Generic_Gradient_Data *gd;
unsigned int i;
eo_do_super(obj, ECTOR_RENDERER_CAIRO_GRADIENT_LINEAR_CLASS, ector_renderer_prepare());
if (pd->pat) return EINA_FALSE;
gld = eo_data_scope_get(obj, ECTOR_RENDERER_GENERIC_GRADIENT_LINEAR_CLASS);
gd = eo_data_scope_get(obj, ECTOR_RENDERER_GENERIC_GRADIENT_CLASS);
gld = eo_data_scope_get(obj, ECTOR_RENDERER_GENERIC_GRADIENT_LINEAR_MIXIN);
gd = eo_data_scope_get(obj, ECTOR_RENDERER_GENERIC_GRADIENT_MIXIN);
if (!gld || !gd) return EINA_FALSE;
USE(obj, cairo_pattern_create_linear, EINA_FALSE);
@ -71,13 +73,15 @@ _ector_renderer_cairo_gradient_linear_ector_renderer_generic_base_draw(Eo *obj,
Ector_Renderer_Generic_Gradient_Linear_Data *gld;
// FIXME: don't ignore clipping !
gld = eo_data_scope_get(obj, ECTOR_RENDERER_GENERIC_GRADIENT_LINEAR_CLASS);
gld = eo_data_scope_get(obj, ECTOR_RENDERER_GENERIC_GRADIENT_LINEAR_MIXIN);
if (!pd->pat || !gld) return EINA_FALSE;
eo_do_super(obj, ECTOR_RENDERER_CAIRO_GRADIENT_LINEAR_CLASS, ector_renderer_draw(op, clips, x, y, mul_col));
USE(obj, cairo_rectangle, EINA_FALSE);
USE(obj, cairo_fill, EINA_FALSE);
cairo_rectangle(pd->parent->cairo, gld->start.x - x, gld->start.y - y,
cairo_rectangle(pd->parent->cairo, gld->start.x, gld->start.y,
gld->end.x - gld->start.x,
gld->end.y - gld->start.y);
eo_do(obj, ector_renderer_cairo_base_fill());

View File

@ -1,4 +1,4 @@
class Ector.Renderer.Cairo.Gradient_Linear (Ector.Renderer.Generic.Gradient_Linear, Ector.Renderer.Cairo.Base)
class Ector.Renderer.Cairo.Gradient_Linear (Ector.Renderer.Cairo.Base, Ector.Renderer.Generic.Gradient, Ector.Renderer.Generic.Gradient_Linear)
{
eo_prefix: ector_renderer_cairo_gradient_linear;
legacy_prefix: null;

View File

@ -40,10 +40,12 @@ _ector_renderer_cairo_gradient_radial_ector_renderer_generic_base_prepare(Eo *ob
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_CLASS);
gd = eo_data_scope_get(obj, ECTOR_RENDERER_GENERIC_GRADIENT_CLASS);
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);
@ -75,14 +77,16 @@ _ector_renderer_cairo_gradient_radial_ector_renderer_generic_base_draw(Eo *obj,
Ector_Renderer_Generic_Gradient_Radial_Data *gld;
// FIXME: don't ignore clipping !
gld = eo_data_scope_get(obj, ECTOR_RENDERER_GENERIC_GRADIENT_RADIAL_CLASS);
gld = eo_data_scope_get(obj, ECTOR_RENDERER_GENERIC_GRADIENT_RADIAL_MIXIN);
if (!pd->pat || !gld) return EINA_FALSE;
eo_do_super(obj, ECTOR_RENDERER_CAIRO_GRADIENT_RADIAL_CLASS, ector_renderer_draw(op, clips, x, y, mul_col));
USE(obj, cairo_arc, EINA_FALSE);
USE(obj, cairo_fill, EINA_FALSE);
cairo_arc(pd->parent->cairo,
gld->radial.x - x, gld->radial.y - y,
gld->radial.x, gld->radial.y,
gld->radius,
0, 2 * M_PI);
eo_do(obj, ector_renderer_cairo_base_fill());

View File

@ -1,4 +1,4 @@
class Ector.Renderer.Cairo.Gradient_Radial (Ector.Renderer.Generic.Gradient_Radial, Ector.Renderer.Cairo.Base)
class Ector.Renderer.Cairo.Gradient_Radial (Ector.Renderer.Cairo.Base, Ector.Renderer.Generic.Gradient, Ector.Renderer.Generic.Gradient_Radial)
{
eo_prefix: ector_renderer_cairo_gradient_radial;
legacy_prefix: null;

View File

@ -53,6 +53,13 @@ _ector_renderer_cairo_shape_ector_renderer_generic_base_prepare(Eo *obj, Ector_R
eo_do_super(obj, ECTOR_RENDERER_CAIRO_SHAPE_CLASS, ector_renderer_prepare());
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 cairo base object
if (!pd->parent)
{
@ -125,8 +132,7 @@ _ector_renderer_cairo_shape_ector_renderer_generic_base_draw(Eo *obj, Ector_Rend
{
if (pd->path == NULL) return EINA_FALSE;
// FIXME: find a way to offset the drawing and setting multiple clips
// FIXME: find a way to set multiple clips
eo_do_super(obj, ECTOR_RENDERER_CAIRO_SHAPE_CLASS, ector_renderer_draw(op, clips, x, y, mul_col));
USE(obj, cairo_new_path, EINA_FALSE);
@ -167,10 +173,12 @@ _ector_renderer_cairo_shape_ector_renderer_generic_base_draw(Eo *obj, Ector_Rend
}
static Eina_Bool
_ector_renderer_cairo_shape_ector_renderer_cairo_base_fill(Eo *obj, Ector_Renderer_Cairo_Shape_Data *pd)
_ector_renderer_cairo_shape_ector_renderer_cairo_base_fill(Eo *obj EINA_UNUSED,
Ector_Renderer_Cairo_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 cairo.
#warning "fill for a shape object is unhandled at this moment in cairo backend."
ERR("fill with shape not implemented\n");
return EINA_FALSE;
}
@ -192,7 +200,7 @@ void
_ector_renderer_cairo_shape_eo_base_constructor(Eo *obj, Ector_Renderer_Cairo_Shape_Data *pd)
{
eo_do_super(obj, ECTOR_RENDERER_CAIRO_SHAPE_CLASS, eo_constructor());
pd->shape = eo_data_xref(obj, ECTOR_RENDERER_GENERIC_SHAPE_CLASS, obj);
pd->shape = eo_data_xref(obj, ECTOR_RENDERER_GENERIC_SHAPE_MIXIN, obj);
pd->base = eo_data_xref(obj, ECTOR_RENDERER_GENERIC_BASE_CLASS, obj);
}

View File

@ -1,4 +1,4 @@
class Ector.Renderer.Cairo.Shape (Ector.Renderer.Generic.Shape, Ector.Renderer.Cairo.Base)
class Ector.Renderer.Cairo.Shape (Ector.Renderer.Cairo.Base, Ector.Renderer.Generic.Shape)
{
eo_prefix: ector_renderer_cairo_shape;
legacy_prefix: null;

View File

@ -36,6 +36,52 @@ extern int _ector_log_dom_global;
#endif /* ifdef CRI */
#define CRI(...) EINA_LOG_DOM_CRIT(_ector_log_dom_global, __VA_ARGS__)
typedef unsigned char DATA8;
typedef unsigned short DATA16;
#ifndef WORDS_BIGENDIAN
/* x86 */
#define A_VAL(p) (((DATA8 *)(p))[3])
#define R_VAL(p) (((DATA8 *)(p))[2])
#define G_VAL(p) (((DATA8 *)(p))[1])
#define B_VAL(p) (((DATA8 *)(p))[0])
#define AR_VAL(p) ((DATA16 *)(p)[1])
#define GB_VAL(p) ((DATA16 *)(p)[0])
#else
/* ppc */
#define A_VAL(p) (((DATA8 *)(p))[0])
#define R_VAL(p) (((DATA8 *)(p))[1])
#define G_VAL(p) (((DATA8 *)(p))[2])
#define B_VAL(p) (((DATA8 *)(p))[3])
#define AR_VAL(p) ((DATA16 *)(p)[0])
#define GB_VAL(p) ((DATA16 *)(p)[1])
#endif
#define RGB_JOIN(r,g,b) \
(((r) << 16) + ((g) << 8) + (b))
#define ARGB_JOIN(a,r,g,b) \
(((a) << 24) + ((r) << 16) + ((g) << 8) + (b))
static inline void
ector_color_argb_premul(int a, int *r, int *g, int *b)
{
a++;
if (r) { *r = (a * *r) >> 8; }
if (g) { *g = (a * *g) >> 8; }
if (b) { *b = (a * *b) >> 8; }
}
static inline void
ector_color_argb_unpremul(int a, int *r, int *g, int *b)
{
if (!a) return;
if (r) { *r = (255 * *r) / a; }
if (g) { *g = (255 * *g) / a; }
if (b) { *b = (255 * *b) / a; }
}
static inline void
_ector_renderer_replace(Ector_Renderer **d, const Ector_Renderer *s)
{

View File

@ -1,4 +1,4 @@
abstract Ector.Renderer.Generic.Gradient (Ector.Renderer.Generic.Base, Efl.Gfx.Gradient.Base)
mixin Ector.Renderer.Generic.Gradient (Efl.Gfx.Gradient.Base)
{
eo_prefix: ector_renderer_gradient;
legacy_prefix: null;

View File

@ -1,4 +1,4 @@
abstract Ector.Renderer.Generic.Gradient_Linear (Ector.Renderer.Generic.Gradient, Efl.Gfx.Gradient.Linear)
mixin Ector.Renderer.Generic.Gradient_Linear (Efl.Gfx.Gradient.Linear)
{
eo_prefix: ector_renderer_gradient_linear;
legacy_prefix: null;

View File

@ -1,4 +1,4 @@
abstract Ector.Renderer.Generic.Gradient_Radial (Ector.Renderer.Generic.Gradient, Efl.Gfx.Gradient.Radial)
mixin Ector.Renderer.Generic.Gradient_Radial (Efl.Gfx.Gradient.Radial)
{
eo_prefix: ector_renderer_gradient_radial;
legacy_prefix: null;

View File

@ -1,4 +1,4 @@
class Ector.Renderer.Generic.Shape (Ector.Renderer.Generic.Base, Efl.Gfx.Shape)
mixin Ector.Renderer.Generic.Shape (Efl.Gfx.Shape)
{
eo_prefix: ector_renderer_shape;
legacy_prefix: null;
@ -32,7 +32,6 @@ class Ector.Renderer.Generic.Shape (Ector.Renderer.Generic.Base, Efl.Gfx.Shape)
}
}
implements {
Ector.Renderer.Generic.Base.prepare;
Efl.Gfx.Shape.stroke_scale;
Efl.Gfx.Shape.stroke_color;
Efl.Gfx.Shape.stroke_width;

View File

@ -183,17 +183,4 @@ _ector_renderer_generic_shape_efl_gfx_shape_stroke_join_get(Eo *obj EINA_UNUSED,
return pd->stroke.join;
}
static Eina_Bool
_ector_renderer_generic_shape_ector_renderer_generic_base_prepare(Eo *obj,
Ector_Renderer_Generic_Shape_Data *pd)
{
if (pd->fill)
eo_do(pd->fill, ector_renderer_prepare());
if (pd->stroke.fill)
eo_do(pd->stroke.fill, ector_renderer_prepare());
if (pd->stroke.marker)
eo_do(pd->stroke.marker, ector_renderer_prepare());
return EINA_TRUE;
}
#include "ector_renderer_generic_shape.eo.c"

View File

@ -73,7 +73,7 @@ _efl_vg_gradient_linear_render_pre(Eo *obj,
if (!nd->renderer)
{
eo_do(s, nd->renderer = ector_surface_renderer_factory_new(ECTOR_RENDERER_GENERIC_GRADIENT_LINEAR_CLASS));
eo_do(s, nd->renderer = ector_surface_renderer_factory_new(ECTOR_RENDERER_GENERIC_GRADIENT_LINEAR_MIXIN));
}
eo_do(nd->renderer,

View File

@ -89,7 +89,7 @@ _efl_vg_gradient_radial_render_pre(Eo *obj,
if (!nd->renderer)
{
eo_do(s, nd->renderer = ector_surface_renderer_factory_new(ECTOR_RENDERER_GENERIC_GRADIENT_RADIAL_CLASS));
eo_do(s, nd->renderer = ector_surface_renderer_factory_new(ECTOR_RENDERER_GENERIC_GRADIENT_RADIAL_MIXIN));
}
eo_do(nd->renderer,

View File

@ -296,7 +296,7 @@ _efl_vg_shape_render_pre(Eo *obj EINA_UNUSED,
if (!nd->renderer)
{
nd->renderer = eo_do(s, ector_surface_renderer_factory_new(ECTOR_RENDERER_GENERIC_SHAPE_CLASS));
eo_do(s, nd->renderer = ector_surface_renderer_factory_new(ECTOR_RENDERER_GENERIC_SHAPE_MIXIN));
}
eo_do(nd->renderer,