efl/legacy/evas/src/lib/canvas/evas_object_proxy.c

460 lines
11 KiB
C

#include "evas_common.h"
#include "evas_private.h"
#include <stdbool.h>
/* Magic number for Proxy objects */
static const char o_type[] = "proxy";
/* Internal object data */
typedef struct _Evas_Object_Proxy
{
DATA32 magic;
Evas_Object *source;
void *engine_data;
} Evas_Object_Proxy;
/* Helpers */
static void evas_object_proxy_init(Evas_Object *obj);
static Evas_Object_Proxy *evas_object_proxy_new(void);
static void _proxy_unset(Evas_Object *proxy);
static void _proxy_set(Evas_Object *proxy, Evas_Object *src);
static void _proxy_subrender(Evas *e, Evas_Object *source);
/* Engine Functions */
static void _proxy_free(Evas_Object *obj);
static void _proxy_render(Evas_Object *obj, void *output, void *context, void *surface, int x, int y);
static void _proxy_render_pre(Evas_Object *obj);
static void _proxy_render_post(Evas_Object *obj);
static unsigned int _proxy_id_get(Evas_Object *obj);
static unsigned int _proxy_visual_id_get(Evas_Object *obj);
static void *_proxy_engine_data_get(Evas_Object *obj);
static int _proxy_is_opaque(Evas_Object *obj);
static int _proxy_was_opaque(Evas_Object *obj);
static int _proxy_can_map(Evas_Object *obj);
/*
void _proxy_store (Evas_Object *obj);
void _proxy_unstore (Evas_Object *obj);
int _proxy_is_visible (Evas_Object *obj);
int _proxy_was_visible (Evas_Object *obj);
int _proxy_is_inside (Evas_Object *obj, Evas_Coord x, Evas_Coord y);
int _proxy_was_inside (Evas_Object *obj, Evas_Coord x, Evas_Coord y);
void _proxy_coords_recalc (Evas_Object *obj);
void _proxy_scale_update (Evas_Object *obj);
int _proxy_has_opaque_rect (Evas_Object *obj);
int _proxy_get_opaque_rect (Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h);
*/
static const Evas_Object_Func object_func =
{
/* Required */
.free = _proxy_free,
.render = _proxy_render,
.render_pre = _proxy_render_pre,
.render_post = _proxy_render_post,
.type_id_get = _proxy_id_get,
.visual_id_get = _proxy_visual_id_get,
.engine_data_get = _proxy_engine_data_get,
.is_opaque = _proxy_is_opaque,
.was_opaque = _proxy_was_opaque,
/* Optional
.store =
.unstore =
.is_visible =
.was_visible =
.is_inside =
.was_inside =
.coords_recalc =
.scale_update =
.has_opaque_rect =
.get_opaque_rect =
*/
.can_map = _proxy_can_map,
};
EAPI Evas_Object *
evas_object_proxy_add(Evas *e)
{
Evas_Object *obj;
Evas_Object_Proxy *o;
MAGIC_CHECK(e, Evas, MAGIC_EVAS);
return NULL;
MAGIC_CHECK_END();
obj = evas_object_new(e);
evas_object_proxy_init(obj);
evas_object_inject(obj, e);
o = obj->object_data;
/* Do stuff here */
return obj;
}
EAPI Eina_Bool
evas_object_proxy_source_set(Evas_Object *obj, Evas_Object *src)
{
Evas_Object_Proxy *o,*so;
MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
return false;
MAGIC_CHECK_END();
o = obj->object_data;
MAGIC_CHECK(o, Evas_Object_Proxy, MAGIC_OBJ_PROXY);
return false;
MAGIC_CHECK_END();
if (o->source == src) return true;
if (src)
{
MAGIC_CHECK(src, Evas_Object, MAGIC_OBJ);
return false;
MAGIC_CHECK_END();
so = src->object_data;
/* Stop the loop _now_ */
/* FIXME: Should I check for smarts that contain proxies too? */
if (so->magic == MAGIC_OBJ_PROXY)
return false;
}
if (o->source)
{
_proxy_unset(obj);
}
if (src)
{
_proxy_set(obj, src);
}
return true;
}
EAPI Evas_Object *
evas_object_proxy_source_get(Evas_Object *obj)
{
Evas_Object_Proxy *o;
MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
return NULL;
MAGIC_CHECK_END();
o = obj->object_data;
MAGIC_CHECK(o, Evas_Object_Proxy, MAGIC_OBJ_PROXY);
return NULL;
MAGIC_CHECK_END();
return o->source;
}
EAPI Eina_Bool
evas_object_proxy_source_unset(Evas_Object *o)
{
return evas_object_proxy_source_set(o, NULL);
}
/* Internal helpers */
static void
evas_object_proxy_init(Evas_Object *obj)
{
obj->object_data = evas_object_proxy_new();
obj->cur.color.r =obj->cur.color.g =obj->cur.color.b =obj->cur.color.a = 255;
obj->cur.geometry.x = obj->cur.geometry.y = 0;
obj->cur.geometry.w = obj->cur.geometry.h = 0;
obj->cur.layer = 0;
obj->cur.anti_alias = 0;
obj->cur.render_op = EVAS_RENDER_BLEND;
obj->prev = obj->cur;
obj->func = &object_func;
obj->type = o_type;
}
static Evas_Object_Proxy *
evas_object_proxy_new(void)
{
Evas_Object_Proxy *o;
o = calloc(1,sizeof(Evas_Object_Proxy));
o->magic = MAGIC_OBJ_PROXY;
o->source = NULL;
return o;
}
static void
_proxy_unset(Evas_Object *proxy)
{
Evas_Object_Proxy *o;
o = proxy->object_data;
if (!o->source) return;
o->source->proxy.proxies = eina_list_remove(o->source->proxy.proxies, proxy);
o->source = NULL;
}
static void
_proxy_set(Evas_Object *proxy, Evas_Object *src)
{
Evas_Object_Proxy *o;
o = proxy->object_data;
o->source = src;
src->proxy.proxies = eina_list_append(src->proxy.proxies, proxy);
}
static void
_proxy_free(Evas_Object *obj)
{
Evas_Object_Proxy *o;
o = obj->object_data;
MAGIC_CHECK(o, Evas_Object_Proxy, MAGIC_OBJ_PROXY);
return;
MAGIC_CHECK_END();
if (o->source) _proxy_unset(obj);
o->magic = 0;
free(o);
}
static void
_proxy_render(Evas_Object *obj, void *output, void *context,
void *surface, int x, int y)
{
Evas_Object_Proxy *o;
void *pixels;
int w,h;
o = obj->object_data;
printf("proxy render\n");
if (!o->source) return;
/* Images only essentially */
if (o->source->proxy.surface)
{
pixels = o->source->proxy.surface;
}
/* Making this faster would be nice... */
// else if (strcmp(evas_object_type_get(o->source),"image") == 0)
// {
// pixels = o->source->func->engine_data_get(o->source);
//}
else
{
_proxy_subrender(obj->layer->evas, o->source);
pixels = o->source->proxy.surface;
}
if (!pixels)
{
return;
}
w = obj->cur.geometry.w;
h = obj->cur.geometry.h;
/* If we have a map: Use that */
if ((obj->cur.map) && (obj->cur.map->count == 4) && (obj->cur.usemap))
{
const Evas_Map_Point *p, *p_end;
RGBA_Map_Point pts[4], *pt;
p = obj->cur.map->points;
p_end = p + 4;
pt = pts;
pts[0].px = obj->cur.map->persp.px << FP;
pts[0].py = obj->cur.map->persp.py << FP;
pts[0].foc = obj->cur.map->persp.foc << FP;
pts[0].z0 = obj->cur.map->persp.z0 << FP;
// draw geom +x +y
for (; p < p_end; p++, pt++)
{
pt->x = (p->x + x) << FP;
pt->y = (p->y + y) << FP;
pt->z = (p->z) << FP;
pt->x3 = p->px << FP;
pt->y3 = p->py << FP;
pt->u = p->u * FP1;
pt->v = p->v * FP1;
pt->col = ARGB_JOIN(p->a, p->r, p->g, p->b);
}
obj->layer->evas->engine.func->image_map4_draw
(output, context, surface, pixels, pts,
1/* o->cur.smooth_scale | obj->cur.map->smooth */, 0);
}
else
{
obj->layer->evas->engine.func->image_draw(output, context,
surface, pixels,
0, 0,
w, h, /* FIXME:
o->cur.image.w,
o->cur.image.h, */
obj->cur.geometry.x + /*ix +*/ x,
obj->cur.geometry.y + /*iy +*/ y,
w, h,/* was iw,ih */
1);
}
}
/**
* Render the subobject
*/
static void
_proxy_subrender(Evas *e, Evas_Object *source)
{
void *ctx;
Evas_Object *obj2;
int w,h;
if (!source) return;
if (source->proxy.surface)
{
/* FIXME: Don't free every time */
e->engine.func->image_map_surface_free(e->engine.data.output,
source->proxy.surface);
}
w = source->cur.geometry.w;
h = source->cur.geometry.h;
/* FIXME: Hardcoded alpha 'on' */
/* FIXME (cont): Should see if the object has alpha */
source->proxy.surface = e->engine.func->image_map_surface_new(
e->engine.data.output, w, h, 1);
ctx = e->engine.func->context_new(e->engine.data.output);
e->engine.func->context_color_set(e->engine.data.output, ctx, 0, 0, 0, 0);
e->engine.func->context_render_op_set(e->engine.data.output, ctx, EVAS_RENDER_COPY);
e->engine.func->rectangle_draw(e->engine.data.output, ctx,
source->proxy.surface, 0, 0, w, h);
e->engine.func->context_free(e->engine.data.output, ctx);
ctx = e->engine.func->context_new(e->engine.data.output);
if (source->smart.smart)
{
EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(source), obj2){
obj2->func->render(obj2, e->engine.data.output, ctx,
source->proxy.surface,
-source->cur.geometry.x,
-source->cur.geometry.y);
}
}
else
{
source->func->render(source, e->engine.data.output, ctx,
source->proxy.surface,
-source->cur.geometry.x,
-source->cur.geometry.y);
}
e->engine.func->context_free(e->engine.data.output, ctx);
}
static void
_proxy_render_pre(Evas_Object *obj)
{
printf("Proxy render pre\n");
if (obj->pre_render_done) return;
obj->pre_render_done = 1;
}
static void
_proxy_render_post(Evas_Object *obj)
{
printf("proxy render post\n");
}
static unsigned int
_proxy_id_get(Evas_Object *obj)
{
return obj->object_data ? MAGIC_OBJ_PROXY : 0;
}
static unsigned int
_proxy_visual_id_get(Evas_Object *obj)
{
return obj->object_data ? MAGIC_OBJ_PROXY : 0;
}
static void *
_proxy_engine_data_get(Evas_Object *obj)
{
return ((Evas_Object_Proxy *)obj->object_data)->engine_data;
}
static int
_proxy_is_opaque(Evas_Object *obj)
{
Evas_Object_Proxy *o = obj->object_data;
/* No source: Sure, it's opaque */
if (!o->source) return 1;
if (obj->cur.usemap) return 0;
return o->source->func->is_opaque(o->source);
}
static int
_proxy_was_opaque(Evas_Object *obj)
{
Evas_Object_Proxy *o = obj->object_data;
/* No source: Sure, it's opaque */
if (!o->source) return 1;
if (obj->cur.usemap) return 0;
return o->source->func->was_opaque(o->source);
}
static int
_proxy_can_map (Evas_Object *obj)
{
/* Of course it can: that's the bloody point */
return 1;
}
/* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-2f0^-2{2(0W1st0 :*/