1 #ifndef EVAS_INLINE_H
2 #define EVAS_INLINE_H
3 
4 #include "evas_private.h"
5 
6 /* Paranoid safety checks.
7  * This can avoid lots of SEGV with dangling pointers to deleted objects.
8  * Two variants: valid or alive (extra check on delete_me).
9  */
10 #define EVAS_OBJECT_DATA_VALID(o) ((o) && (o)->layer && (o)->layer->evas)
11 #define EVAS_OBJECT_DATA_ALIVE(o) (EVAS_OBJECT_DATA_VALID(o) && !(o)->delete_me)
12 #define EVAS_OBJECT_DATA_VALID_CHECK(o, ...) do { \
13    if (EINA_UNLIKELY(!EVAS_OBJECT_DATA_VALID(o))) return __VA_ARGS__; } while (0)
14 #define EVAS_OBJECT_DATA_ALIVE_CHECK(o, ...) do { \
15    if (EINA_UNLIKELY(!EVAS_OBJECT_DATA_ALIVE(o))) return __VA_ARGS__; } while (0)
16 #define EVAS_OBJECT_DATA_GET(eo_o) \
17    efl_data_scope_get((eo_o), EFL_CANVAS_OBJECT_CLASS)
18 #define EVAS_OBJECT_DATA_SAFE_GET(eo_o) \
19    efl_data_scope_safe_get((eo_o), EFL_CANVAS_OBJECT_CLASS)
20 
21 static inline Eina_Bool
_evas_render_has_map(Evas_Object_Protected_Data * obj)22 _evas_render_has_map(Evas_Object_Protected_Data *obj)
23 {
24    return (obj->map->cur.map && obj->map->cur.usemap);
25 }
26 
27 static inline Eina_Bool
_evas_render_can_map(Evas_Object_Protected_Data * obj)28 _evas_render_can_map(Evas_Object_Protected_Data *obj)
29 {
30    if (!obj->func->can_map) return EINA_FALSE;
31    return obj->func->can_map(obj->object);
32 }
33 
34 static inline void
_evas_object_gfx_mapping_update(Evas_Object_Protected_Data * obj)35 _evas_object_gfx_mapping_update(Evas_Object_Protected_Data *obj)
36 {
37    if (!obj->gfx_mapping_has) return;
38    _efl_gfx_mapping_update(obj->object);
39 }
40 
41 static inline int
_evas_object_event_new(void)42 _evas_object_event_new(void)
43 {
44    return (++_evas_event_counter);
45 }
46 
47 static inline Eina_Bool
_evas_object_callback_has_by_type(Evas_Object_Protected_Data * obj,Evas_Callback_Type type)48 _evas_object_callback_has_by_type(Evas_Object_Protected_Data *obj, Evas_Callback_Type type)
49 {
50    return (obj->callback_mask & (((uint64_t)1) << type)) != 0;
51 }
52 
53 static inline int
evas_object_was_visible(Evas_Object_Protected_Data * obj)54 evas_object_was_visible(Evas_Object_Protected_Data *obj)
55 {
56    if (EINA_UNLIKELY(!obj->prev)) return 0;
57    if ((obj->prev->visible) && (!obj->no_render) &&
58        ((obj->prev->cache.clip.visible) || obj->is_smart) &&
59        ((obj->prev->cache.clip.a > 0 && obj->prev->render_op == EVAS_RENDER_BLEND)
60        || obj->prev->render_op != EVAS_RENDER_BLEND))
61      {
62         if (obj->func->was_visible)
63           return obj->func->was_visible(obj->object);
64         return 1;
65      }
66    return 0;
67 }
68 
69 static inline void
evas_add_rect(Eina_Array * rects,int x,int y,int w,int h)70 evas_add_rect(Eina_Array *rects, int x, int y, int w, int h)
71 {
72    Eina_Rectangle *r;
73 
74    NEW_RECT(r, x, y, w, h);
75    if (r) eina_array_push(rects, r);
76 }
77 
78 static inline Cutout_Rect*
evas_common_draw_context_cutouts_add(Cutout_Rects * rects,int x,int y,int w,int h)79 evas_common_draw_context_cutouts_add(Cutout_Rects* rects,
80                                      int x, int y, int w, int h)
81 {
82    Cutout_Rect* rect;
83 
84    if (rects->max < (rects->active + 1))
85      {
86         rects->max += 512;
87         rects->rects = (Cutout_Rect *)realloc(rects->rects, sizeof(Cutout_Rect) * rects->max);
88      }
89 
90    rect = rects->rects + rects->active;
91    rect->x = x;
92    rect->y = y;
93    rect->w = w;
94    rect->h = h;
95    rects->active++;
96 
97    return rect;
98 }
99 
100 static inline int
evas_object_is_opaque(Evas_Object_Protected_Data * obj)101 evas_object_is_opaque(Evas_Object_Protected_Data *obj)
102 {
103    if (obj->is_smart || obj->no_render) return 0;
104    if (obj->cur->render_op == EVAS_RENDER_COPY)
105      return 1;
106    /* If clipped: Assume alpha */
107    if (obj->cur->cache.clip.a == 255)
108      {
109         /* If has mask image: Always assume non opaque */
110         if ((obj->cur->clipper && obj->cur->clipper->mask->is_mask) ||
111             (obj->clip.mask))
112           return 0;
113         if (obj->func->is_opaque)
114           return obj->func->is_opaque(obj->object, obj, obj->private_data);
115         return 1;
116      }
117    return 0;
118 }
119 
120 static inline int
evas_object_is_on_plane(Evas_Object_Protected_Data * obj)121 evas_object_is_on_plane(Evas_Object_Protected_Data *obj)
122 {
123    if (obj->func->is_on_plane)
124      return obj->func->is_on_plane(obj->object, obj, obj->private_data);
125    return 0;
126 }
127 
128 static inline int
evas_object_plane_changed(Evas_Object_Protected_Data * obj)129 evas_object_plane_changed(Evas_Object_Protected_Data *obj)
130 {
131    if (obj->func->plane_changed)
132      return obj->func->plane_changed(obj->object, obj, obj->private_data);
133    return 0;
134 }
135 
136 static inline int
evas_event_freezes_through(Evas_Object * eo_obj EINA_UNUSED,Evas_Object_Protected_Data * obj)137 evas_event_freezes_through(Evas_Object *eo_obj EINA_UNUSED, Evas_Object_Protected_Data *obj)
138 {
139    if (obj->freeze_events) return 1;
140    if (obj->parent_cache.freeze_events_valid)
141      return obj->parent_cache.freeze_events;
142    if (!obj->smart.parent) return 0;
143    Evas_Object_Protected_Data *smart_parent_pd = efl_data_scope_get(obj->smart.parent, EFL_CANVAS_OBJECT_CLASS);
144    obj->parent_cache.freeze_events =
145       evas_event_freezes_through(obj->smart.parent, smart_parent_pd);
146    obj->parent_cache.freeze_events_valid = EINA_TRUE;
147    return obj->parent_cache.freeze_events;
148 }
149 
150 static inline int
evas_event_passes_through(Evas_Object * eo_obj EINA_UNUSED,Evas_Object_Protected_Data * obj)151 evas_event_passes_through(Evas_Object *eo_obj EINA_UNUSED, Evas_Object_Protected_Data *obj)
152 {
153    if (obj->pass_events || obj->no_render) return 1;
154    if (obj->parent_cache.pass_events_valid)
155      return obj->parent_cache.pass_events;
156    if (!obj->smart.parent) return 0;
157    Evas_Object_Protected_Data *smart_parent_pd = efl_data_scope_get(obj->smart.parent, EFL_CANVAS_OBJECT_CLASS);
158    obj->parent_cache.pass_events =
159       evas_event_passes_through(obj->smart.parent, smart_parent_pd);
160    obj->parent_cache.pass_events_valid = EINA_TRUE;
161    return obj->parent_cache.pass_events;
162 }
163 
164 static inline int
evas_object_is_source_invisible(Evas_Object * eo_obj EINA_UNUSED,Evas_Object_Protected_Data * obj)165 evas_object_is_source_invisible(Evas_Object *eo_obj EINA_UNUSED, Evas_Object_Protected_Data *obj)
166 {
167    if (obj->parent_cache.src_invisible_valid)
168      return obj->parent_cache.src_invisible;
169    if (obj->proxy->proxies && obj->proxy->src_invisible) return 1;
170    if (!obj->smart.parent) return 0;
171    if (obj->mask->is_mask) return 0;
172    Evas_Object_Protected_Data *smart_parent_pd =
173       efl_data_scope_get(obj->smart.parent, EFL_CANVAS_OBJECT_CLASS);
174    obj->parent_cache.src_invisible =
175       evas_object_is_source_invisible(obj->smart.parent, smart_parent_pd);
176    obj->parent_cache.src_invisible_valid = EINA_TRUE;
177    return obj->parent_cache.src_invisible;
178 }
179 
180 static inline int
evas_object_is_visible(Evas_Object_Protected_Data * obj)181 evas_object_is_visible(Evas_Object_Protected_Data *obj)
182 {
183    if (EINA_UNLIKELY(!obj->cur)) return 0;
184    if ((obj->cur->visible) && (!obj->no_render) &&
185        ((obj->cur->cache.clip.visible) || (obj->is_smart)) &&
186        ((obj->cur->cache.clip.a > 0 && obj->cur->render_op == EVAS_RENDER_BLEND)
187        || obj->cur->render_op != EVAS_RENDER_BLEND))
188      {
189         if (obj->func->is_visible)
190           return obj->func->is_visible(obj->object);
191         return 1;
192      }
193    return 0;
194 }
195 
196 static inline int
evas_object_clippers_is_visible(Evas_Object * eo_obj EINA_UNUSED,Evas_Object_Protected_Data * obj)197 evas_object_clippers_is_visible(Evas_Object *eo_obj EINA_UNUSED, Evas_Object_Protected_Data *obj)
198 {
199    if (obj->cur->visible)
200      {
201         if (obj->cur->clipper)
202           {
203              return evas_object_clippers_is_visible(obj->cur->clipper->object,
204                                                     obj->cur->clipper);
205           }
206         return 1;
207      }
208    return 0;
209 }
210 
211 static inline int
evas_object_is_proxy_visible(Evas_Object_Protected_Data * obj)212 evas_object_is_proxy_visible(Evas_Object_Protected_Data *obj)
213 {
214    if ((obj->cur->visible) &&
215        //FIXME: Check the cached clipper visible properly.
216        (obj->is_smart || !obj->cur->clipper || obj->cur->clipper->cur->visible) &&
217        ((obj->cur->cache.clip.a > 0 && obj->cur->render_op == EVAS_RENDER_BLEND)
218         || obj->cur->render_op != EVAS_RENDER_BLEND))
219      {
220         if (obj->func->is_visible)
221           return obj->func->is_visible(obj->object);
222         return 1;
223      }
224    return 0;
225 }
226 
227 static inline int
evas_object_is_in_output_rect(Evas_Object * eo_obj EINA_UNUSED,Evas_Object_Protected_Data * obj,int x,int y,int w,int h)228 evas_object_is_in_output_rect(Evas_Object *eo_obj EINA_UNUSED, Evas_Object_Protected_Data *obj, int x, int y, int w, int h)
229 {
230    /* assumes coords have been recalced */
231    if ((RECTS_INTERSECT(x, y, w, h,
232                         obj->cur->cache.clip.x,
233                         obj->cur->cache.clip.y,
234                         obj->cur->cache.clip.w,
235                         obj->cur->cache.clip.h)))
236      return 1;
237    return 0;
238 }
239 
240 static inline int
evas_object_is_active(Evas_Object * eo_obj,Evas_Object_Protected_Data * obj)241 evas_object_is_active(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj)
242 {
243    if (evas_object_is_visible(obj) || evas_object_was_visible(obj))
244      {
245         Evas_Public_Data *e = obj->layer->evas;
246         int fx, fy;
247         fx = e->framespace.x;
248         fy = e->framespace.y;
249         if (obj->is_smart && !(obj->map->cur.map && obj->map->cur.usemap))
250           return 1;
251 
252         if (evas_object_is_in_output_rect(eo_obj, obj, -fx, -fy,
253                                           e->output.w, e->output.h) ||
254             evas_object_was_in_output_rect(eo_obj, obj, -fx, -fy,
255                                            e->output.w, e->output.h))
256           return 1;
257      }
258    /* FIXME: forcing object with proxies to stay active,
259       need to be smarter and only do that when really needed. */
260    if (obj->proxy->proxies && obj->changed)
261      return 1;
262    if (obj->mask->is_mask && obj->clip.clipees)
263      return 1;
264    return 0;
265 }
266 
267 static inline void
evas_object_coords_recalc(Evas_Object * eo_obj,Evas_Object_Protected_Data * obj)268 evas_object_coords_recalc(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj)
269 {
270 ////   if (obj->cur->cache.geometry.validity == obj->layer->evas->output_validity)
271 ////     return;
272 ////   obj->cur->cache.geometry.x =
273 ////     evas_coord_world_x_to_screen(obj->layer->evas, obj->cur->geometry.x);
274 ////   obj->cur->cache.geometry.y =
275 ////     evas_coord_world_y_to_screen(obj->layer->evas, obj->cur->geometry.y);
276 ////   obj->cur->cache.geometry.w =
277 ////     evas_coord_world_x_to_screen(obj->layer->evas, obj->cur->geometry.w) -
278 ////     evas_coord_world_x_to_screen(obj->layer->evas, 0);
279 ////   obj->cur->cache.geometry.h =
280 ////     evas_coord_world_y_to_screen(obj->layer->evas, obj->cur->geometry.h) -
281 ////     evas_coord_world_y_to_screen(obj->layer->evas, 0);
282    if (obj->func->coords_recalc) obj->func->coords_recalc(eo_obj, obj, obj->private_data);
283 ////   obj->cur->cache.geometry.validity = obj->layer->evas->output_validity;
284 }
285 
286 static inline void
evas_object_clip_recalc(Evas_Object_Protected_Data * obj)287 evas_object_clip_recalc(Evas_Object_Protected_Data *obj)
288 {
289    Evas_Object_Protected_Data *clipper = NULL;
290 
291    EVAS_OBJECT_DATA_ALIVE_CHECK(obj);
292 
293    clipper = obj->cur->clipper;
294 
295    if (EINA_LIKELY(((!obj->cur->cache.clip.dirty) &&
296                     !(!clipper || clipper->cur->cache.clip.dirty)))) return;
297 
298    if (EINA_UNLIKELY(obj->layer->evas->is_frozen)) return;
299 
300    evas_object_clip_recalc_do(obj, clipper);
301 }
302 
303 static inline void
evas_object_clip_dirty(Evas_Object * eo_obj EINA_UNUSED,Evas_Object_Protected_Data * obj)304 evas_object_clip_dirty(Evas_Object *eo_obj EINA_UNUSED, Evas_Object_Protected_Data *obj)
305 {
306    if (obj->cur->cache.clip.dirty) return;
307    evas_object_clip_dirty_do(obj);
308 }
309 
310 static inline void
evas_object_async_block(Evas_Object_Protected_Data * obj)311 evas_object_async_block(Evas_Object_Protected_Data *obj)
312 {
313    if (EVAS_OBJECT_DATA_VALID(obj))
314      {
315         eina_lock_take(&(obj->layer->evas->lock_objects));
316         eina_lock_release(&(obj->layer->evas->lock_objects));
317      }
318 }
319 
320 static inline void
evas_canvas_async_block(Evas_Public_Data * e)321 evas_canvas_async_block(Evas_Public_Data *e)
322 {
323    if (e)
324      {
325         eina_lock_take(&(e->lock_objects));
326         eina_lock_release(&(e->lock_objects));
327      }
328 }
329 
330 static inline void
evas_common_draw_context_cache_update(RGBA_Draw_Context * dc)331 evas_common_draw_context_cache_update(RGBA_Draw_Context *dc)
332 {
333    dc->cache.used++;
334    if (dc->cache.used >= 4096)
335      {
336         evas_common_draw_context_cutouts_real_free(dc->cache.rects);
337         dc->cache.rects = NULL;
338         dc->cache.used = 0;
339      }
340 }
341 
342 static inline Eina_Bool
_evas_eina_rectangle_inside(const Eina_Rectangle * big,const Eina_Rectangle * small)343 _evas_eina_rectangle_inside(const Eina_Rectangle *big, const Eina_Rectangle *small)
344 {
345    Eina_Rectangle inter = *big;
346 
347    if (!eina_rectangle_intersection(&inter, small))
348      return EINA_FALSE;
349    if ((inter.w == small->w) && (inter.h == small->h))
350      return EINA_TRUE;
351    return EINA_FALSE;
352 }
353 
354 // Temporary until we have multi output support
355 static inline void *
_evas_default_output_get(Evas_Public_Data * e)356 _evas_default_output_get(Evas_Public_Data *e)
357 {
358    Efl_Canvas_Output *output;
359 
360    output = eina_list_data_get(e->outputs);
361    return output ? output->output : NULL;
362 }
363 
364 static inline void *
_evas_engine_context(Evas_Public_Data * e)365 _evas_engine_context(Evas_Public_Data *e)
366 {
367    return e->backend;
368 }
369 
370 static inline void
_evas_wrap_del(Evas_Object ** eo,Evas_Object_Protected_Data * pd)371 _evas_wrap_del(Evas_Object **eo, Evas_Object_Protected_Data *pd)
372 {
373    if (!*eo) return ;
374    if (pd && pd->legacy.ctor) evas_object_del(*eo);
375    else efl_del(*eo);
376 }
377 
378 #define _EVAS_COLOR_CLAMP(x, y) do { \
379    if (x > y) { x = y; bad = 1; } \
380    if (x < 0) { x = 0; bad = 1; } } while (0)
381 
382 #define EVAS_COLOR_SANITIZE(r, g, b, a) \
383    ({ int bad = 0; \
384    _EVAS_COLOR_CLAMP(a, 255); \
385    _EVAS_COLOR_CLAMP(r, a); \
386    _EVAS_COLOR_CLAMP(g, a); \
387    _EVAS_COLOR_CLAMP(b, a); \
388    bad; })
389 
390 #endif
391