map code... works.. with bugs... but works. visually...

SVN revision: 43163
This commit is contained in:
Carsten Haitzler 2009-10-20 16:03:57 +00:00
parent 64d7bf0c71
commit 8bf3f50b2c
7 changed files with 610 additions and 258 deletions

View File

@ -104,6 +104,7 @@ typedef enum _Evas_Object_Table_Homogeneous_Mode
typedef struct _Evas_Transform Evas_Transform; /**< An Evas projective or affine transform */
typedef struct _Evas_Coord_Rectangle Evas_Coord_Rectangle; /**< A generic rectangle handle */
typedef struct _Evas_Smart_Class Evas_Smart_Class; /**< A smart object base class */
typedef struct _Evas_Map_Point Evas_Map_Point; /**< A point with attributes for x, y, z texture u & v etc. */
typedef struct _Evas Evas; /**< An Evas canvas handle */
typedef struct _Evas_Object Evas_Object; /**< An Evas Object handle */
@ -846,7 +847,18 @@ extern "C" {
EAPI Eina_List *evas_objects_at_xy_get (const Evas *e, Evas_Coord x, Evas_Coord y, Eina_Bool include_pass_events_objects, Eina_Bool include_hidden_objects) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;
EAPI Eina_List *evas_objects_in_rectangle_get (const Evas *e, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h, Eina_Bool include_pass_events_objects, Eina_Bool include_hidden_objects) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;
EAPI void evas_object_map_enable_set (Evas_Object *obj, Eina_Bool enabled);
EAPI Eina_Bool evas_object_map_enable_get (const Evas_Object *obj);
EAPI void evas_object_map_set (Evas_Object *obj, const Evas_Map_Point *points);
EAPI void evas_object_map_get (const Evas_Object *obj, Evas_Map_Point *points);
EAPI Evas_Map_Point *evas_map_new (int num);
EAPI void evas_map_free (Evas_Map_Point *mp);
EAPI void evas_map_point_coord_set (Evas_Map_Point *mp, int n, Evas_Coord x, Evas_Coord y, Evas_Coord z);
EAPI void evas_map_point_coord_get (const Evas_Map_Point *mp, int n, Evas_Coord *x, Evas_Coord *y, Evas_Coord *z);
EAPI void evas_map_point_image_uv_set (Evas_Map_Point *mp, int n, double u, double v);
EAPI void evas_map_point_image_uv_get (const Evas_Map_Point *mp, int n, double *u, double *v);
/* smart objects */
EINA_DEPRECATED EAPI Evas_Smart *evas_smart_new (const char *name, void (*func_add) (Evas_Object *obj), void (*func_del) (Evas_Object *obj), void (*func_layer_set) (Evas_Object *obj, int l), void (*func_raise) (Evas_Object *obj), void (*func_lower) (Evas_Object *obj), void (*func_stack_above) (Evas_Object *obj, Evas_Object *above), void (*func_stack_below) (Evas_Object *obj, Evas_Object *below), void (*func_move) (Evas_Object *obj, Evas_Coord x, Evas_Coord y), void (*func_resize) (Evas_Object *obj, Evas_Coord w, Evas_Coord h), void (*func_show) (Evas_Object *obj), void (*func_hide) (Evas_Object *obj), void (*func_color_set) (Evas_Object *obj, int r, int g, int b, int a), void (*func_clip_set) (Evas_Object *obj, Evas_Object *clip), void (*func_clip_unset) (Evas_Object *obj), const void *data) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_MALLOC;
EAPI void evas_smart_free (Evas_Smart *s) EINA_ARG_NONNULL(1);

View File

@ -2327,165 +2327,190 @@ evas_object_image_render(Evas_Object *obj, void *output, void *context, void *su
}
o->dirty_pixels = 0;
}
obj->layer->evas->engine.func->image_scale_hint_set(output,
if ((obj->cur.mappoints) && (obj->cur.usemap))
{
RGBA_Map_Point pts[4];
int i;
// draw geom +x +y
for (i = 0; i < 4; i++)
{
pts[i].x = (obj->cur.mappoints[i].x + x) << FP;
pts[i].y = (obj->cur.mappoints[i].y + y) << FP;
pts[i].z = (obj->cur.mappoints[i].z) << FP;
pts[i].u = obj->cur.mappoints[i].u * FP1;
pts[i].v = obj->cur.mappoints[i].v * FP1;
}
obj->layer->evas->engine.func->image_map4_draw(output,
context,
surface,
o->engine_data,
o->scale_hint);
o->engine_data = obj->layer->evas->engine.func->image_border_set(output, o->engine_data,
o->cur.border.l, o->cur.border.r,
o->cur.border.t, o->cur.border.b);
idx = evas_object_image_figure_x_fill(obj, o->cur.fill.x, o->cur.fill.w, &idw);
idy = evas_object_image_figure_y_fill(obj, o->cur.fill.y, o->cur.fill.h, &idh);
if (idw < 1) idw = 1;
if (idh < 1) idh = 1;
if (idx > 0) idx -= idw;
if (idy > 0) idy -= idh;
while ((int)idx < obj->cur.geometry.w)
{
Evas_Coord ydy;
int dobreak_w = 0;
ydy = idy;
ix = idx;
if ((o->cur.fill.w == obj->cur.geometry.w) &&
(o->cur.fill.x == 0))
{
dobreak_w = 1;
iw = obj->cur.geometry.w;
}
else
iw = ((int)(idx + idw)) - ix;
while ((int)idy < obj->cur.geometry.h)
{
int dobreak_h = 0;
iy = idy;
if ((o->cur.fill.h == obj->cur.geometry.h) &&
(o->cur.fill.y == 0))
{
ih = obj->cur.geometry.h;
dobreak_h = 1;
}
else
ih = ((int)(idy + idh)) - iy;
if ((o->cur.border.l == 0) &&
(o->cur.border.r == 0) &&
(o->cur.border.t == 0) &&
(o->cur.border.b == 0) &&
(o->cur.border.fill != 0))
obj->layer->evas->engine.func->image_draw(output,
context,
surface,
o->engine_data,
0, 0,
o->cur.image.w,
o->cur.image.h,
obj->cur.geometry.x + ix + x,
obj->cur.geometry.y + iy + y,
iw, ih,
o->cur.smooth_scale);
else
{
int inx, iny, inw, inh, outx, outy, outw, outh;
int bl, br, bt, bb;
int imw, imh, ox, oy;
ox = obj->cur.geometry.x + ix + x;
oy = obj->cur.geometry.y + iy + y;
imw = o->cur.image.w;
imh = o->cur.image.h;
bl = o->cur.border.l;
br = o->cur.border.r;
bt = o->cur.border.t;
bb = o->cur.border.b;
if ((bl + br) > iw)
{
bl = iw / 2;
br = iw - bl;
}
if ((bl + br) > imw)
{
bl = imw / 2;
br = imw - bl;
}
if ((bt + bb) > ih)
{
bt = ih / 2;
bb = ih - bt;
}
if ((bt + bb) > imh)
{
bt = imh / 2;
bb = imh - bt;
}
inx = 0; iny = 0;
inw = bl; inh = bt;
outx = ox; outy = oy;
outw = bl; outh = bt;
obj->layer->evas->engine.func->image_draw(output, context, surface, o->engine_data, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale);
inx = bl; iny = 0;
inw = imw - bl - br; inh = bt;
outx = ox + bl; outy = oy;
outw = iw - bl - br; outh = bt;
obj->layer->evas->engine.func->image_draw(output, context, surface, o->engine_data, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale);
inx = imw - br; iny = 0;
inw = br; inh = bt;
outx = ox + iw - br; outy = oy;
outw = br; outh = bt;
obj->layer->evas->engine.func->image_draw(output, context, surface, o->engine_data, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale);
inx = 0; iny = bt;
inw = bl; inh = imh - bt - bb;
outx = ox; outy = oy + bt;
outw = bl; outh = ih - bt - bb;
obj->layer->evas->engine.func->image_draw(output, context, surface, o->engine_data, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale);
if (o->cur.border.fill > EVAS_BORDER_FILL_NONE)
{
inx = bl; iny = bt;
inw = imw - bl - br; inh = imh - bt - bb;
outx = ox + bl; outy = oy + bt;
outw = iw - bl - br; outh = ih - bt - bb;
if ((o->cur.border.fill == EVAS_BORDER_FILL_SOLID) &&
(obj->cur.cache.clip.a == 255) &&
(obj->cur.render_op == EVAS_RENDER_BLEND))
pts,
o->cur.smooth_scale,
0);
}
else
{
obj->layer->evas->engine.func->image_scale_hint_set(output,
o->engine_data,
o->scale_hint);
o->engine_data = obj->layer->evas->engine.func->image_border_set(output, o->engine_data,
o->cur.border.l, o->cur.border.r,
o->cur.border.t, o->cur.border.b);
idx = evas_object_image_figure_x_fill(obj, o->cur.fill.x, o->cur.fill.w, &idw);
idy = evas_object_image_figure_y_fill(obj, o->cur.fill.y, o->cur.fill.h, &idh);
if (idw < 1) idw = 1;
if (idh < 1) idh = 1;
if (idx > 0) idx -= idw;
if (idy > 0) idy -= idh;
while ((int)idx < obj->cur.geometry.w)
{
Evas_Coord ydy;
int dobreak_w = 0;
ydy = idy;
ix = idx;
if ((o->cur.fill.w == obj->cur.geometry.w) &&
(o->cur.fill.x == 0))
{
dobreak_w = 1;
iw = obj->cur.geometry.w;
}
else
iw = ((int)(idx + idw)) - ix;
while ((int)idy < obj->cur.geometry.h)
{
int dobreak_h = 0;
iy = idy;
if ((o->cur.fill.h == obj->cur.geometry.h) &&
(o->cur.fill.y == 0))
{
ih = obj->cur.geometry.h;
dobreak_h = 1;
}
else
ih = ((int)(idy + idh)) - iy;
if ((o->cur.border.l == 0) &&
(o->cur.border.r == 0) &&
(o->cur.border.t == 0) &&
(o->cur.border.b == 0) &&
(o->cur.border.fill != 0))
obj->layer->evas->engine.func->image_draw(output,
context,
surface,
o->engine_data,
0, 0,
o->cur.image.w,
o->cur.image.h,
obj->cur.geometry.x + ix + x,
obj->cur.geometry.y + iy + y,
iw, ih,
o->cur.smooth_scale);
else
{
int inx, iny, inw, inh, outx, outy, outw, outh;
int bl, br, bt, bb;
int imw, imh, ox, oy;
ox = obj->cur.geometry.x + ix + x;
oy = obj->cur.geometry.y + iy + y;
imw = o->cur.image.w;
imh = o->cur.image.h;
bl = o->cur.border.l;
br = o->cur.border.r;
bt = o->cur.border.t;
bb = o->cur.border.b;
if ((bl + br) > iw)
{
obj->layer->evas->engine.func->context_render_op_set(output, context,
EVAS_RENDER_COPY);
obj->layer->evas->engine.func->image_draw(output, context, surface, o->engine_data, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale);
obj->layer->evas->engine.func->context_render_op_set(output, context,
obj->cur.render_op);
bl = iw / 2;
br = iw - bl;
}
else
obj->layer->evas->engine.func->image_draw(output, context, surface, o->engine_data, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale);
}
inx = imw - br; iny = bt;
inw = br; inh = imh - bt - bb;
outx = ox + iw - br; outy = oy + bt;
outw = br; outh = ih - bt - bb;
obj->layer->evas->engine.func->image_draw(output, context, surface, o->engine_data, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale);
inx = 0; iny = imh - bb;
inw = bl; inh = bb;
outx = ox; outy = oy + ih - bb;
outw = bl; outh = bb;
obj->layer->evas->engine.func->image_draw(output, context, surface, o->engine_data, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale);
inx = bl; iny = imh - bb;
inw = imw - bl - br; inh = bb;
outx = ox + bl; outy = oy + ih - bb;
outw = iw - bl - br; outh = bb;
obj->layer->evas->engine.func->image_draw(output, context, surface, o->engine_data, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale);
inx = imw - br; iny = imh - bb;
inw = br; inh = bb;
outx = ox + iw - br; outy = oy + ih - bb;
outw = br; outh = bb;
obj->layer->evas->engine.func->image_draw(output, context, surface, o->engine_data, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale);
}
idy += idh;
if (dobreak_h) break;
}
idx += idw;
idy = ydy;
if (dobreak_w) break;
if ((bl + br) > imw)
{
bl = imw / 2;
br = imw - bl;
}
if ((bt + bb) > ih)
{
bt = ih / 2;
bb = ih - bt;
}
if ((bt + bb) > imh)
{
bt = imh / 2;
bb = imh - bt;
}
inx = 0; iny = 0;
inw = bl; inh = bt;
outx = ox; outy = oy;
outw = bl; outh = bt;
obj->layer->evas->engine.func->image_draw(output, context, surface, o->engine_data, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale);
inx = bl; iny = 0;
inw = imw - bl - br; inh = bt;
outx = ox + bl; outy = oy;
outw = iw - bl - br; outh = bt;
obj->layer->evas->engine.func->image_draw(output, context, surface, o->engine_data, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale);
inx = imw - br; iny = 0;
inw = br; inh = bt;
outx = ox + iw - br; outy = oy;
outw = br; outh = bt;
obj->layer->evas->engine.func->image_draw(output, context, surface, o->engine_data, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale);
inx = 0; iny = bt;
inw = bl; inh = imh - bt - bb;
outx = ox; outy = oy + bt;
outw = bl; outh = ih - bt - bb;
obj->layer->evas->engine.func->image_draw(output, context, surface, o->engine_data, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale);
if (o->cur.border.fill > EVAS_BORDER_FILL_NONE)
{
inx = bl; iny = bt;
inw = imw - bl - br; inh = imh - bt - bb;
outx = ox + bl; outy = oy + bt;
outw = iw - bl - br; outh = ih - bt - bb;
if ((o->cur.border.fill == EVAS_BORDER_FILL_SOLID) &&
(obj->cur.cache.clip.a == 255) &&
(obj->cur.render_op == EVAS_RENDER_BLEND))
{
obj->layer->evas->engine.func->context_render_op_set(output, context,
EVAS_RENDER_COPY);
obj->layer->evas->engine.func->image_draw(output, context, surface, o->engine_data, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale);
obj->layer->evas->engine.func->context_render_op_set(output, context,
obj->cur.render_op);
}
else
obj->layer->evas->engine.func->image_draw(output, context, surface, o->engine_data, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale);
}
inx = imw - br; iny = bt;
inw = br; inh = imh - bt - bb;
outx = ox + iw - br; outy = oy + bt;
outw = br; outh = ih - bt - bb;
obj->layer->evas->engine.func->image_draw(output, context, surface, o->engine_data, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale);
inx = 0; iny = imh - bb;
inw = bl; inh = bb;
outx = ox; outy = oy + ih - bb;
outw = bl; outh = bb;
obj->layer->evas->engine.func->image_draw(output, context, surface, o->engine_data, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale);
inx = bl; iny = imh - bb;
inw = imw - bl - br; inh = bb;
outx = ox + bl; outy = oy + ih - bb;
outw = iw - bl - br; outh = bb;
obj->layer->evas->engine.func->image_draw(output, context, surface, o->engine_data, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale);
inx = imw - br; iny = imh - bb;
inw = br; inh = bb;
outx = ox + iw - br; outy = oy + ih - bb;
outw = br; outh = bb;
obj->layer->evas->engine.func->image_draw(output, context, surface, o->engine_data, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale);
}
idy += idh;
if (dobreak_h) break;
}
idx += idw;
idy = ydy;
if (dobreak_w) break;
}
}
}
}
@ -2774,17 +2799,6 @@ evas_object_image_is_opaque(Evas_Object *obj)
/* this returns 1 if the internal object data implies that the object is */
/* currently fully opaque over the entire rectangle it occupies */
o = (Evas_Object_Image *)(obj->object_data);
if (o->cur.has_alpha) return 0;
v = (!!!o->cur.fill.w) + (!!!o->cur.fill.h);
if (v) return 0;
if (!o->engine_data) return 0;
v = o->cur.border.l + o->cur.border.r + o->cur.border.t + o->cur.border.b;
v += !o->cur.border.fill;
if (v > 0) return 0;
if (obj->cur.render_op == EVAS_RENDER_COPY) return 1;
if (obj->cur.render_op != EVAS_RENDER_BLEND) return 0;
return 1;
/*
if ((o->cur.fill.w < 1) || (o->cur.fill.h < 1))
return 0;
if (((o->cur.border.l != 0) ||
@ -2793,10 +2807,10 @@ evas_object_image_is_opaque(Evas_Object *obj)
(o->cur.border.b != 0)) &&
(!o->cur.border.fill)) return 0;
if (!o->engine_data) return 0;
if ((obj->cur.mappoints) && (obj->cur.usemap)) return 0;
if (obj->cur.render_op == EVAS_RENDER_COPY) return 1;
if (o->cur.has_alpha) return 0;
return 1;
*/
}
static int
@ -2815,11 +2829,10 @@ evas_object_image_was_opaque(Evas_Object *obj)
(o->prev.border.b != 0)) &&
(!o->prev.border.fill)) return 0;
if (!o->engine_data) return 0;
if (obj->prev.render_op == EVAS_RENDER_COPY)
return 1;
if ((obj->prev.mappoints) && (obj->prev.usemap)) return 0;
if (obj->prev.render_op == EVAS_RENDER_COPY) return 1;
if (o->prev.has_alpha) return 0;
if (obj->prev.render_op != EVAS_RENDER_BLEND)
return 0;
if (obj->prev.render_op != EVAS_RENDER_BLEND) return 0;
return 1;
}
@ -2960,6 +2973,7 @@ evas_object_image_has_opaque_rect(Evas_Object *obj)
Evas_Object_Image *o;
o = (Evas_Object_Image *)(obj->object_data);
if ((obj->cur.mappoints) && (obj->cur.usemap)) return 0;
if (((o->cur.border.l | o->cur.border.r | o->cur.border.t | o->cur.border.b) != 0) &&
(o->cur.border.fill == EVAS_BORDER_FILL_SOLID) &&
(obj->cur.render_op == EVAS_RENDER_BLEND) &&

View File

@ -1658,6 +1658,171 @@ evas_object_precise_is_inside_get(const Evas_Object *obj)
return obj->precise_is_inside;
}
static void
_calc_map_geometry(Evas_Object *obj)
{
int i;
int is, was = 0, pass = 0;
Evas_Coord x1, x2, y1, y2;
if (!obj->cur.mappoints) return;
x1 = obj->cur.mappoints[0].x;
x2 = obj->cur.mappoints[0].x;
y1 = obj->cur.mappoints[0].y;
y2 = obj->cur.mappoints[0].y;
for (i = 1; i < 4; i++)
{
if (obj->cur.mappoints[i].x < x1) x1 = obj->cur.mappoints[i].x;
if (obj->cur.mappoints[i].x > x2) x2 = obj->cur.mappoints[i].x;
if (obj->cur.mappoints[i].y < y1) y1 = obj->cur.mappoints[i].y;
if (obj->cur.mappoints[i].y > y2) y2 = obj->cur.mappoints[i].y;
}
obj->cur.geometry.x = x1;
obj->cur.geometry.y = y1;
obj->cur.geometry.w = (x2 - x1) + 1;
obj->cur.geometry.h = (y2 - y1) + 1;
evas_object_change(obj);
evas_object_clip_dirty(obj);
if (obj->layer->evas->events_frozen <= 0)
{
evas_object_recalc_clippees(obj);
if (!pass)
{
if (!obj->smart.smart)
{
is = evas_object_is_in_output_rect(obj,
obj->layer->evas->pointer.x,
obj->layer->evas->pointer.y, 1, 1);
if ((is ^ was) && obj->cur.visible)
evas_event_feed_mouse_move(obj->layer->evas,
obj->layer->evas->pointer.x,
obj->layer->evas->pointer.y,
obj->layer->evas->last_timestamp,
NULL);
}
}
}
evas_object_inform_call_move(obj);
evas_object_inform_call_resize(obj);
}
EAPI void
evas_object_map_enable_set(Evas_Object *obj, Eina_Bool enabled)
{
MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
return;
MAGIC_CHECK_END();
if (obj->cur.usemap == !!enabled) return;
obj->cur.usemap = enabled;
if (obj->cur.usemap) _calc_map_geometry(obj);
}
EAPI Eina_Bool
evas_object_map_enable_get(const Evas_Object *obj)
{
MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
return 0;
MAGIC_CHECK_END();
return obj->cur.usemap;
}
EAPI void
evas_object_map_set(Evas_Object *obj, const Evas_Map_Point *points)
{
MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
return;
MAGIC_CHECK_END();
if (!points)
{
if (obj->cur.mappoints)
{
if (!obj->prev.mappoints)
{
free(obj->cur.mappoints);
obj->cur.mappoints = NULL;
return;
}
obj->cur.mappoints = NULL;
}
return;
}
if (!obj->cur.mappoints)
{
obj->cur.mappoints = malloc(4 * sizeof(Evas_Map_Point));
if (obj->cur.mappoints)
{
memcpy(obj->cur.mappoints, points, 4 * sizeof(Evas_Map_Point));
}
obj->prev.mappoints = NULL;
}
else
{
memcpy(obj->cur.mappoints, points, 4 * sizeof(Evas_Map_Point));
obj->prev.mappoints = NULL;
}
if (obj->cur.usemap) _calc_map_geometry(obj);
}
EAPI void
evas_object_map_get(const Evas_Object *obj, Evas_Map_Point *points)
{
MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
return;
MAGIC_CHECK_END();
if (obj->cur.mappoints)
{
memcpy(points, obj->cur.mappoints, 4 * sizeof(Evas_Map_Point));
}
}
EAPI Evas_Map_Point *
evas_map_new(int num)
{
return calloc(num, sizeof(Evas_Map_Point));
}
EAPI void
evas_map_free(Evas_Map_Point *mp)
{
if (!mp) return;
free(mp);
}
EAPI void
evas_map_point_coord_set(Evas_Map_Point *mp, int n, Evas_Coord x, Evas_Coord y, Evas_Coord z)
{
if (!mp) return;
mp[n].x = x;
mp[n].y = y;
mp[n].z = z;
}
EAPI void
evas_map_point_coord_get(const Evas_Map_Point *mp, int n, Evas_Coord *x, Evas_Coord *y, Evas_Coord *z)
{
if (!mp) return;
if (x) *x = mp[n].x;
if (y) *y = mp[n].y;
if (z) *z = mp[n].z;
}
EAPI void
evas_map_point_image_uv_set(Evas_Map_Point *mp, int n, double u, double v)
{
if (!mp) return;
mp[n].u = u;
mp[n].v = v;
}
EAPI void
evas_map_point_image_uv_get(const Evas_Map_Point *mp, int n, double *u, double *v)
{
if (!mp) return;
if (u) *u = mp[n].u;
if (v) *v = mp[n].v;
}
/**
* @}
*/

View File

@ -19,6 +19,18 @@ struct _Line
Span span[2];
};
static FPc
_interp(int x1, int x2, int p, FPc u1, FPc u2)
{
FPc u;
x2 -= x1;
x1 = 0;
u = u2 - u1;
u = (u * p) / (x2 + 1);
return u + u1;
}
EAPI void
evas_common_map4_rgba(RGBA_Image *src, RGBA_Image *dst,
RGBA_Draw_Context *dc,
@ -26,10 +38,16 @@ evas_common_map4_rgba(RGBA_Image *src, RGBA_Image *dst,
int smooth, int level)
{
int i;
int ytop, ybottom, ystart, yend, y;
int ytop, ybottom, ystart, yend, y, yp;
int py[4];
Line *spans = NULL;
DATA32 *buf;
RGBA_Gfx_Func func;
if (src->cache_entry.space == EVAS_COLORSPACE_ARGB8888)
evas_cache_image_load_data(&src->cache_entry);
evas_common_image_colorspace_normalize(src);
ytop = p[0].y;
for (i = 1; i < 4; i++)
{
@ -46,8 +64,8 @@ evas_common_map4_rgba(RGBA_Image *src, RGBA_Image *dst,
if ((ytop >= dst->cache_entry.h) || (ybottom < 0)) return;
if (ystart < 0) ystart = 0;
else ystart = ytop;
if (ytop < 0) ystart = 0;
else ystart = ytop;
if (ybottom >= dst->cache_entry.h) yend = dst->cache_entry.h - 1;
else yend = ybottom;
@ -82,62 +100,12 @@ evas_common_map4_rgba(RGBA_Image *src, RGBA_Image *dst,
}
else
{
// convex case
// |------------|
// |------------|
// |------------|
// |------------|
// |------------|
// |------------|
// |----------|
// |--------|
// |------|
// |----|
// |--------|
// |--------|
// |--------|
// |-----|
// |--|
// |--|
// |-----|
// |--------|
// |--------|
// |--------|
// |--|
// |-----|
// |--------|
// |-----|
// |--|
// |--|
// |------|
// |----------|
// |------|
// |--|
// concave case
// |--|
// |------|
// |----||----|
// |--| |--|
// |--| |--|
// |----||----|
// |------|
// |--|
for (y = ystart; y <= yend; y++)
{
int edge[4][3], edge_num, x, t, h, swapped, order[4];
FPc uv[4][2], u, v;
int edge[4][3], edge_num, swapped, order[4];
FPc uv[4][2], u, v, x, h, t;
yp = y - ystart;
edge_num = 0;
//--------------------
if ((PY(0) <= y) && (PY(1) > y)) // 0 above, 1, below
@ -196,17 +164,25 @@ evas_common_map4_rgba(RGBA_Image *src, RGBA_Image *dst,
{
int e1 = edge[i][0], e2 = edge[i][1];
h = p[e2].y - p[e1].y; // height of span
t = (((y + 1) << FP) + (FP1 - 1)) - p[e1].y;
h = (p[e2].y - p[e1].y) >> FP; // height of edge
t = (((y << FP) + (FP1 - 1)) - p[e1].y) >> FP;
x = p[e2].x - p[e1].x;
// printf(" x = %i, p1 = %i, p2 = %i\n", x, p[e1].x, p[e2].x);
// printf(" + %i\n", ((x * t) / h));
x = p[e1].x + ((x * t) / h);
u = p[e2].u - p[e1].u;
u = p[e1].u + ((u * t) / h);
v = p[e2].v - p[e1].v;
v = p[e1].v + ((v * t) / h);
uv[i][1] = v;
uv[i][0] = u;
edge[i][2] = x >> FP;
// printf("%i | %3i: %3i - %i / %i [%i->%i]\n",
// y, i, x >> FP,
// t, h >> FP,
// p[e1].x >> FP, p[e2].x >> FP);
// also fill in order
order[i] = i;
}
@ -214,13 +190,13 @@ evas_common_map4_rgba(RGBA_Image *src, RGBA_Image *dst,
do
{
swapped = 0;
for (i = 0; i < edge_num; i++)
for (i = 0; i < (edge_num - 1); i++)
{
if (edge[order[i]][2] > edge[order[i + 1]][2])
{
t = order[i];
order[i] = order[i + 1];
order[i] = t;
order[i + 1] = t;
swapped = 1;
}
}
@ -228,38 +204,200 @@ evas_common_map4_rgba(RGBA_Image *src, RGBA_Image *dst,
while (swapped);
if (edge_num == 2)
{
spans[y].span[0].x1 = edge[order[0]][2];
spans[y].span[0].u[0] = uv[order[0]][0];
spans[y].span[0].v[0] = uv[order[0]][1];
spans[y].span[0].x2 = edge[order[1]][2];
spans[y].span[0].u[0] = uv[order[1]][0];
spans[y].span[0].v[0] = uv[order[1]][1];
spans[y].span[1].x1 = -1;
i = 0;
spans[yp].span[i].x1 = edge[order[0]][2];
spans[yp].span[i].u[0] = uv[order[0]][0];
spans[yp].span[i].v[0] = uv[order[0]][1];
spans[yp].span[i].x2 = edge[order[1]][2];
spans[yp].span[i].u[1] = uv[order[1]][0];
spans[yp].span[i].v[1] = uv[order[1]][1];
if ((spans[yp].span[i].x1 >= dst->cache_entry.w) ||
(spans[yp].span[i].x2 < 0))
{
spans[yp].span[i].x1 = -1;
}
else
{
if (spans[yp].span[i].x1 < 0)
{
spans[yp].span[i].u[0] =
_interp(spans[yp].span[i].x1,
spans[yp].span[i].x2, 0,
spans[yp].span[i].u[0],
spans[yp].span[i].u[1]);
spans[yp].span[i].v[0] =
_interp(spans[yp].span[i].x1,
spans[yp].span[i].x2, 0,
spans[yp].span[i].v[0],
spans[yp].span[i].v[1]);
spans[yp].span[i].x1 = 0;
}
if (spans[yp].span[i].x2 >= dst->cache_entry.w)
{
spans[yp].span[i].u[1] =
_interp(spans[yp].span[i].x1,
spans[yp].span[i].x2, dst->cache_entry.w,
spans[yp].span[i].u[0],
spans[yp].span[i].u[1]);
spans[yp].span[i].v[1] =
_interp(spans[yp].span[i].x1,
spans[yp].span[i].x2, dst->cache_entry.w,
spans[yp].span[i].v[0],
spans[yp].span[i].v[1]);
spans[yp].span[i].x2 = dst->cache_entry.w - 1;
}
i++;
spans[yp].span[i].x1 = -1;
}
}
else if (edge_num == 4)
{
spans[y].span[0].x1 = edge[order[0]][2];
spans[y].span[0].u[0] = uv[order[0]][0];
spans[y].span[0].v[0] = uv[order[0]][1];
spans[y].span[0].x2 = edge[order[1]][2];
spans[y].span[0].u[0] = uv[order[1]][0];
spans[y].span[0].v[0] = uv[order[1]][1];
spans[y].span[1].x1 = edge[order[2]][2];
spans[y].span[1].u[0] = uv[order[2]][0];
spans[y].span[1].v[0] = uv[order[2]][1];
spans[y].span[1].x2 = edge[order[3]][2];
spans[y].span[1].u[0] = uv[order[3]][0];
spans[y].span[1].v[0] = uv[order[3]][1];
i = 0;
spans[yp].span[i].x1 = edge[order[0]][2];
spans[yp].span[i].u[0] = uv[order[0]][0];
spans[yp].span[i].v[0] = uv[order[0]][1];
spans[yp].span[i].x2 = edge[order[1]][2];
spans[yp].span[i].u[1] = uv[order[1]][0];
spans[yp].span[i].v[1] = uv[order[1]][1];
if ((spans[yp].span[i].x1 >= dst->cache_entry.w) ||
(spans[yp].span[i].x2 < 0))
{
spans[yp].span[i].x1 = -1;
}
else
{
if (spans[yp].span[i].x1 < 0)
{
spans[yp].span[i].u[0] =
_interp(spans[yp].span[i].x1,
spans[yp].span[i].x2, 0,
spans[yp].span[i].u[0],
spans[yp].span[i].u[1]);
spans[yp].span[i].v[0] =
_interp(spans[yp].span[i].x1,
spans[yp].span[i].x2, 0,
spans[yp].span[i].v[0],
spans[yp].span[i].v[1]);
spans[yp].span[i].x1 = 0;
}
if (spans[yp].span[i].x2 >= dst->cache_entry.w)
{
spans[yp].span[i].u[1] =
_interp(spans[yp].span[i].x1,
spans[yp].span[i].x2, dst->cache_entry.w,
spans[yp].span[i].u[0],
spans[yp].span[i].u[1]);
spans[yp].span[i].v[1] =
_interp(spans[yp].span[i].x1,
spans[yp].span[i].x2, dst->cache_entry.w,
spans[yp].span[i].v[0],
spans[yp].span[i].v[1]);
spans[yp].span[i].x2 = dst->cache_entry.w - 1;
}
i++;
}
spans[yp].span[i].x1 = edge[order[2]][2];
spans[yp].span[i].u[0] = uv[order[2]][0];
spans[yp].span[i].v[0] = uv[order[2]][1];
spans[yp].span[i].x2 = edge[order[3]][2];
spans[yp].span[i].u[1] = uv[order[3]][0];
spans[yp].span[i].v[1] = uv[order[3]][1];
if ((spans[yp].span[i].x1 >= dst->cache_entry.w) ||
(spans[yp].span[i].x2 < 0))
{
spans[yp].span[i].x1 = -1;
}
else
{
if (spans[yp].span[i].x1 < 0)
{
spans[yp].span[i].u[0] =
_interp(spans[yp].span[i].x1,
spans[yp].span[i].x2, 0,
spans[yp].span[i].u[0],
spans[yp].span[i].u[1]);
spans[yp].span[i].v[0] =
_interp(spans[yp].span[i].x1,
spans[yp].span[i].x2, 0,
spans[yp].span[i].v[0],
spans[yp].span[i].v[1]);
spans[yp].span[i].x1 = 0;
}
if (spans[yp].span[i].x2 >= dst->cache_entry.w)
{
spans[yp].span[i].u[1] =
_interp(spans[yp].span[i].x1,
spans[yp].span[i].x2, dst->cache_entry.w,
spans[yp].span[i].u[0],
spans[yp].span[i].u[1]);
spans[yp].span[i].v[1] =
_interp(spans[yp].span[i].x1,
spans[yp].span[i].x2, dst->cache_entry.w,
spans[yp].span[i].v[0],
spans[yp].span[i].v[1]);
spans[yp].span[i].x2 = dst->cache_entry.w - 1;
}
}
}
else
{
printf("duck for y %i, edge_num is %i\n", y, edge_num);
spans[yp].span[0].x1 = -1;
// printf("duck for y %i, edge_num is %i\n", y, edge_num);
}
}
}
if (dc->mul.use)
func = evas_common_gfx_func_composite_pixel_color_span_get(src, dc->mul.col, dst, dst->cache_entry.w, dc->render_op);
else
func = evas_common_gfx_func_composite_pixel_span_get(src, dst, dst->cache_entry.w, dc->render_op);
buf = alloca(dst->cache_entry.w * sizeof(DATA32));
// walk spans and fill
// printf("---------- %i -> %i / %i [%i]\n",
// ystart, yend, dst->cache_entry.h, dst->cache_entry.w);
for (y = ystart; y <= yend; y++)
{
yp = y - ystart;
// printf("y: %3i[%3i] :", y, yp);
for (i = 0; i < 2; i++)
{
if (spans[yp].span[i].x1 >= 0)
{
int x, w, ww, sw, shp, swp;
FPc u, v, ud, vd;
DATA32 *d, *dptr, *sp, *s;
x = spans[yp].span[i].x1;
w = (spans[yp].span[i].x2 - x) + 1;
ww = w;
d = buf;
u = spans[yp].span[i].u[0];
v = spans[yp].span[i].v[0];
ud = (spans[yp].span[i].u[1] - u) / w;
vd = (spans[yp].span[i].v[1] - v) / w;
sp = src->image.data;
sw = src->cache_entry.w;
swp = sw << FP;
shp = src->cache_entry.h << FP ;
// printf(" %3i[%3i,%3i] - %3i[%3i,%3i] |",
// x, u >> FP, v >> FP,
// x + w - 1, spans[yp].span[i].u[1] >> FP, spans[yp].span[i].v[1] >> FP);
while (ww > 0)
{
s = sp + ((v >> FP) * sw) + (u >> FP);
*d++ = *s;
u += ud;
if (u >= swp) u = swp - 1;
v += vd;
if (v >= shp) v = shp - 1;
ww--;
}
dptr = ((DATA32 *)dst->image.data) +
(y * dst->cache_entry.w) + x;
func(buf, NULL, dc->mul.col, dptr, w);
}
}
// printf("\n");
}
}

View File

@ -13,9 +13,9 @@ typedef int FPc;
// fp # of bits of float accuracy
#define FP 12
// fp half (half of an fp unit)
#define FPH (1 << (FP - 1 - 1))
#define FPH (1 << (FP - 1))
// one fp unit
#define FP1 (1 << (FP - 1))
#define FP1 (1 << (FP))
struct _RGBA_Map_Point
{

View File

@ -357,6 +357,13 @@ struct _Evas_Size_Hints
Evas_Border padding;
};
struct _Evas_Map_Point
{
Evas_Coord x, y, z;
double u, v;
// FIXME: add color?
};
struct _Evas_Object
{
EINA_INLIST;
@ -382,12 +389,14 @@ struct _Evas_Object
} clip;
} cache;
double scale;
Evas_Map_Point *mappoints;
Evas_Coord_Rectangle geometry;
struct {
unsigned char r, g, b, a;
} color;
Evas_Object *clipper;
short layer;
Eina_Bool usemap : 1;
Eina_Bool visible : 1;
Eina_Bool have_clipees : 1;
Eina_Bool anti_alias : 1;
@ -672,6 +681,8 @@ struct _Evas_Func
void (*image_scale_hint_set) (void *data, void *image, int hint);
int (*image_scale_hint_get) (void *data, void *image);
int (*font_last_up_to_pos) (void *data, void *font, const char *text, int x, int y);
void (*image_map4_draw) (void *data, void *context, void *surface, void *image, RGBA_Map_Point *p, int smooth, int level);
};
struct _Evas_Image_Load_Func

View File

@ -777,6 +777,17 @@ eng_image_draw(void *data __UNUSED__, void *context, void *surface, void *image,
}
}
static void
eng_image_map4_draw(void *data __UNUSED__, void *context, void *surface, void *image, RGBA_Map_Point *p, int smooth, int level)
{
RGBA_Image *im;
if (!image) return;
im = image;
evas_common_map4_rgba(im, surface, context, p, smooth, level);
evas_common_cpu_end_opt();
}
static void
eng_image_scale_hint_set(void *data __UNUSED__, void *image, int hint)
{
@ -1123,9 +1134,10 @@ static Evas_Func func =
eng_image_scale_hint_set,
eng_image_scale_hint_get,
/* more font draw functions */
eng_font_last_up_to_pos
eng_font_last_up_to_pos,
/* FUTURE software generic calls go here (done) */
eng_image_map4_draw
/* FUTURE software generic calls go here */
};
/*