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