1 #include "evas_common.h"
2 #include "evas_private.h"
6 /* Switch this to not always use the map.
7 * Tested using map, which is a little slower */
10 /* Magic number for Proxy objects */
11 static const char o_type[] = "proxy";
13 /* Internal object data */
14 typedef struct _Evas_Object_Proxy
28 static void evas_object_proxy_init(Evas_Object *obj);
29 static Evas_Object_Proxy *evas_object_proxy_new(void);
30 static void _proxy_unset(Evas_Object *proxy);
31 static void _proxy_set(Evas_Object *proxy, Evas_Object *src);
32 static void _proxy_subrender(Evas *e, Evas_Object *source);
34 /* Engine Functions */
35 static void _proxy_free(Evas_Object *obj);
36 static void _proxy_render(Evas_Object *obj, void *output, void *context, void *surface, int x, int y);
37 static void _proxy_render_pre(Evas_Object *obj);
38 static void _proxy_render_post(Evas_Object *obj);
39 static unsigned int _proxy_id_get(Evas_Object *obj);
40 static unsigned int _proxy_visual_id_get(Evas_Object *obj);
41 static void *_proxy_engine_data_get(Evas_Object *obj);
43 static int _proxy_is_opaque(Evas_Object *obj);
44 static int _proxy_was_opaque(Evas_Object *obj);
45 static int _proxy_can_map(Evas_Object *obj);
48 void _proxy_store (Evas_Object *obj);
49 void _proxy_unstore (Evas_Object *obj);
51 int _proxy_is_visible (Evas_Object *obj);
52 int _proxy_was_visible (Evas_Object *obj);
54 int _proxy_is_inside (Evas_Object *obj, Evas_Coord x, Evas_Coord y);
55 int _proxy_was_inside (Evas_Object *obj, Evas_Coord x, Evas_Coord y);
57 void _proxy_coords_recalc (Evas_Object *obj);
58 void _proxy_scale_update (Evas_Object *obj);
60 int _proxy_has_opaque_rect (Evas_Object *obj);
61 int _proxy_get_opaque_rect (Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h);
66 static const Evas_Object_Func object_func =
70 .render = _proxy_render,
71 .render_pre = _proxy_render_pre,
72 .render_post = _proxy_render_post,
74 .type_id_get = _proxy_id_get,
75 .visual_id_get = _proxy_visual_id_get,
76 .engine_data_get = _proxy_engine_data_get,
78 .is_opaque = _proxy_is_opaque,
79 .was_opaque = _proxy_was_opaque,
97 .can_map = _proxy_can_map,
102 evas_object_proxy_add(Evas *e)
105 Evas_Object_Proxy *o;
107 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
111 obj = evas_object_new(e);
112 evas_object_proxy_init(obj);
113 evas_object_inject(obj, e);
115 o = obj->object_data;
123 evas_object_proxy_source_set(Evas_Object *obj, Evas_Object *src)
125 Evas_Object_Proxy *o,*so;
127 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
130 o = obj->object_data;
131 MAGIC_CHECK(o, Evas_Object_Proxy, MAGIC_OBJ_PROXY);
135 if (o->source == src) return true;
139 MAGIC_CHECK(src, Evas_Object, MAGIC_OBJ);
142 so = src->object_data;
143 /* Stop the loop _now_ */
144 /* FIXME: Should I check for smarts that contain proxies too? */
145 if (so->magic == MAGIC_OBJ_PROXY)
156 _proxy_set(obj, src);
163 evas_object_proxy_source_get(Evas_Object *obj)
165 Evas_Object_Proxy *o;
167 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
170 o = obj->object_data;
171 MAGIC_CHECK(o, Evas_Object_Proxy, MAGIC_OBJ_PROXY);
179 evas_object_proxy_source_unset(Evas_Object *o)
181 return evas_object_proxy_source_set(o, NULL);
187 /* Internal helpers */
189 evas_object_proxy_init(Evas_Object *obj)
191 obj->object_data = evas_object_proxy_new();
192 obj->cur.color.r =obj->cur.color.g =obj->cur.color.b =obj->cur.color.a = 255;
193 obj->cur.geometry.x = obj->cur.geometry.y = 0;
194 obj->cur.geometry.w = obj->cur.geometry.h = 0;
196 obj->cur.anti_alias = 0;
197 obj->cur.render_op = EVAS_RENDER_BLEND;
198 obj->prev = obj->cur;
200 obj->func = &object_func;
204 static Evas_Object_Proxy *
205 evas_object_proxy_new(void)
207 Evas_Object_Proxy *o;
209 o = calloc(1,sizeof(Evas_Object_Proxy));
210 o->magic = MAGIC_OBJ_PROXY;
217 _proxy_unset(Evas_Object *proxy)
219 Evas_Object_Proxy *o;
221 o = proxy->object_data;
222 if (!o->source) return;
224 o->source->proxy.proxies = eina_list_remove(o->source->proxy.proxies, proxy);
231 _proxy_set(Evas_Object *proxy, Evas_Object *src)
233 Evas_Object_Proxy *o;
235 o = proxy->object_data;
239 src->proxy.proxies = eina_list_append(src->proxy.proxies, proxy);
240 src->proxy.redraw = EINA_TRUE;
241 o->mapupdate = EINA_TRUE;
247 _proxy_free(Evas_Object *obj)
249 Evas_Object_Proxy *o;
251 o = obj->object_data;
252 MAGIC_CHECK(o, Evas_Object_Proxy, MAGIC_OBJ_PROXY);
256 if (o->source) _proxy_unset(obj);
257 if (o->defmap) evas_map_free(o->defmap);
263 _proxy_map_update(Evas_Object *obj)
265 Evas_Object_Proxy *o;
270 o = obj->object_data;
272 if (!o->source) return;
273 o->mapupdate = EINA_FALSE;
276 x = obj->cur.geometry.x;
277 y = obj->cur.geometry.y;
278 w = obj->cur.geometry.w;
279 h = obj->cur.geometry.h;
280 sw = o->source->proxy.w;
281 sh = o->source->proxy.h;
284 o->defmap = evas_map_new(4);
287 evas_map_point_coord_set (m, 0, x, y, 0);
288 evas_map_point_image_uv_set(m, 0, 0, 0);
289 evas_map_point_color_set (m, 0, 255, 255, 255, 255);
291 evas_map_point_coord_set (m, 1, x + w, y, 0);
292 evas_map_point_image_uv_set(m, 1, sw, 0);
293 evas_map_point_color_set (m, 1, 255, 255, 255, 255);
295 evas_map_point_coord_set (m, 2, x + w, y + h, 0);
296 evas_map_point_image_uv_set(m, 2, sw, sh);
297 evas_map_point_color_set (m, 2, 255, 255, 255, 255);
299 evas_map_point_coord_set (m, 3, x, y + h, 0);
300 evas_map_point_image_uv_set(m, 3, 0, sh);
301 evas_map_point_color_set (m, 3, 255, 255, 255, 255);
307 _proxy_render(Evas_Object *obj, void *output, void *context,
308 void *surface, int x, int y)
310 Evas_Object_Proxy *o;
314 o = obj->object_data;
316 if (!o->source) return;
318 // ENFN->context_multiplier_unset(output, context);
319 // ENFN->context_render_op_set(output, context, obj->cur.render_op);
321 if (o->source->proxy.surface && o->source->proxy.redraw == EINA_FALSE)
323 pixels = o->source->proxy.surface;
325 /* Making this faster would be nice... */
326 else if (strcmp(evas_object_type_get(o->source),"image") == 0)
328 pixels = o->source->func->engine_data_get(o->source);
329 evas_object_image_size_get(o->source, &o->source->proxy.w,
330 &o->source->proxy.h);
334 _proxy_subrender(obj->layer->evas, o->source);
335 pixels = o->source->proxy.surface;
338 if (o->mapupdate) _proxy_map_update(obj);
345 w = obj->cur.geometry.w;
346 h = obj->cur.geometry.h;
348 /* If we have a map: Use that */
350 ((obj->cur.map) && (obj->cur.map->count == 4) && (obj->cur.usemap)))
352 const Evas_Map_Point *p, *p_end;
353 RGBA_Map_Point pts[4], *pt;
356 if (!obj->cur.usemap || !obj->cur.map)
365 pts[0].px = map->persp.px << FP;
366 pts[0].py = map->persp.py << FP;
367 pts[0].foc = map->persp.foc << FP;
368 pts[0].z0 = map->persp.z0 << FP;
370 pts[0].px = map->persp.px << FP;
371 pts[0].py = map->persp.py << FP;
372 pts[0].foc = map->persp.foc << FP;
373 pts[0].z0 = map->persp.z0 << FP;
375 for (; p < p_end; p++, pt++)
377 pt->x = (p->x + x) << FP;
378 pt->y = (p->y + y) << FP;
379 pt->z = (p->z) << FP;
380 pt->x3 = p->px << FP;
381 pt->y3 = p->py << FP;
384 pt->col = ARGB_JOIN(p->a, p->r, p->g, p->b);
386 obj->layer->evas->engine.func->image_map4_draw
387 (output, context, surface, pixels, pts, map->smooth, 0);
391 obj->layer->evas->engine.func->image_draw(output, context,
395 obj->cur.geometry.x + /*ix +*/ x,
396 obj->cur.geometry.y + /*iy +*/ y,
403 * Render the subobject
406 _proxy_subrender(Evas *e, Evas_Object *source)
414 w = source->cur.geometry.w;
415 h = source->cur.geometry.h;
417 source->proxy.redraw = EINA_FALSE;
419 /* We need to redraw surface then */
420 if (source->proxy.surface && (source->proxy.w != w || source->proxy.h != h))
422 e->engine.func->image_map_surface_free(e->engine.data.output,
423 source->proxy.surface);
424 source->proxy.surface = NULL;
427 /* FIXME: Hardcoded alpha 'on' */
428 /* FIXME (cont): Should see if the object has alpha */
429 if (!source->proxy.surface)
431 source->proxy.surface = e->engine.func->image_map_surface_new(
432 e->engine.data.output, w, h, 1);
437 ctx = e->engine.func->context_new(e->engine.data.output);
438 e->engine.func->context_color_set(e->engine.data.output, ctx, 0, 0, 0, 0);
439 e->engine.func->context_render_op_set(e->engine.data.output, ctx, EVAS_RENDER_COPY);
440 e->engine.func->rectangle_draw(e->engine.data.output, ctx,
441 source->proxy.surface, 0, 0, w, h);
442 e->engine.func->context_free(e->engine.data.output, ctx);
444 ctx = e->engine.func->context_new(e->engine.data.output);
445 if (source->smart.smart)
447 EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(source), obj2){
448 obj2->func->render(obj2, e->engine.data.output, ctx,
449 source->proxy.surface,
450 -source->cur.geometry.x,
451 -source->cur.geometry.y);
456 source->func->render(source, e->engine.data.output, ctx,
457 source->proxy.surface,
458 -source->cur.geometry.x,
459 -source->cur.geometry.y);
461 e->engine.func->context_free(e->engine.data.output, ctx);
466 _proxy_render_pre(Evas_Object *obj)
468 Evas_Object_Proxy *o;
472 if (obj->pre_render_done) return;
473 obj->pre_render_done = 1;
475 e = obj->layer->evas;
476 o = obj->object_data;
478 is_v = evas_object_is_visible(obj);
479 was_v = evas_object_was_visible(obj);
483 evas_object_render_pre_visible_change(&e->clip_changes, obj, is_v, was_v);
485 if (((obj->cur.geometry.x != obj->prev.geometry.x) ||
486 (obj->cur.geometry.y != obj->prev.geometry.y) ||
487 (obj->cur.geometry.w != obj->prev.geometry.w) ||
488 (obj->cur.geometry.h != obj->prev.geometry.h))
491 evas_object_render_pre_prev_cur_add(&e->clip_changes, obj);
492 o->mapupdate = EINA_TRUE;
495 if (o->source && o->source->proxy.redraw)
497 evas_add_rect(&e->clip_changes,
498 obj->cur.geometry.x, obj->cur.geometry.y,
499 obj->cur.geometry.w, obj->cur.geometry.h);
500 o->mapupdate = EINA_TRUE;
503 evas_object_render_pre_effect_updates(&e->clip_changes, obj, is_v, was_v);
506 _proxy_render_post(Evas_Object *obj)
508 Evas_Object_Proxy *o;
510 o = obj->object_data;
512 evas_object_clip_changes_clean(obj);
513 /* move cur to prev safely for object data */
514 obj->prev = obj->cur;
518 _proxy_id_get(Evas_Object *obj)
520 return obj->object_data ? MAGIC_OBJ_PROXY : 0;
523 _proxy_visual_id_get(Evas_Object *obj)
525 return obj->object_data ? MAGIC_OBJ_PROXY : 0;
529 _proxy_engine_data_get(Evas_Object *obj)
531 return ((Evas_Object_Proxy *)obj->object_data)->engine_data;
536 _proxy_is_opaque(Evas_Object *obj)
538 Evas_Object_Proxy *o = obj->object_data;
540 /* No source: Sure, it's opaque */
541 if (!o->source) return 1;
546 _proxy_was_opaque(Evas_Object *obj)
548 Evas_Object_Proxy *o = obj->object_data;
550 /* No source: Sure, it's opaque */
551 if (!o->source) return 1;
556 _proxy_can_map (Evas_Object *obj)
558 /* Of course it can: that's the bloody point */
570 /* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-2f0^-2{2(0W1st0 :*/