1 #include "evas_image_private.h"
2 #include "efl_canvas_image.eo.h"
3 
4 #define MY_CLASS EFL_CANVAS_IMAGE_CLASS
5 #define MY_CLASS_NAME efl_class_name_get(MY_CLASS)
6 
7 void
_evas_image_file_unload(Eo * eo_obj)8 _evas_image_file_unload(Eo *eo_obj)
9 {
10    Evas_Object_Protected_Data *obj;
11    Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS);
12 
13    if (!o->cur->f) return;
14 
15    obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
16    evas_object_async_block(obj);
17    _evas_image_init_set(NULL, NULL, eo_obj, obj, o, NULL);
18    o->buffer_data_set = EINA_FALSE;
19    _evas_image_done_set(eo_obj, obj, o);
20    o->load_error = EFL_GFX_IMAGE_LOAD_ERROR_NONE;
21 }
22 
23 void
_evas_image_preload_update(Eo * eo_obj,Eina_File * f)24 _evas_image_preload_update(Eo *eo_obj, Eina_File *f)
25 {
26    Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS);
27    if (o->cur->f) return;
28    EINA_COW_IMAGE_STATE_WRITE_BEGIN(o, cur)
29    {
30       cur->f = eina_file_dup(f);
31    }
32    EINA_COW_IMAGE_STATE_WRITE_END(o, cur)
33 }
34 
35 Eina_Bool
_evas_image_file_load(Eo * eo_obj,Evas_Image_Data * o)36 _evas_image_file_load(Eo *eo_obj, Evas_Image_Data *o)
37 {
38    Evas_Object_Protected_Data *obj;
39    Evas_Image_Load_Opts lo;
40    const Eina_File *f = efl_file_mmap_get(eo_obj);
41    const char *key = efl_file_key_get(eo_obj);
42    int load_error;
43    int frame_index;
44 
45    if (!o->skip_head)
46      EINA_SAFETY_ON_NULL_RETURN_VAL(f, EINA_FALSE);
47 
48    if (f && (o->cur->f == f))
49      {
50         if ((!o->cur->key) && (!key))
51           return EINA_TRUE;
52         if ((o->cur->key) && (key) && (!strcmp(o->cur->key, key)))
53           return EINA_TRUE;
54      }
55 
56    obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
57    evas_object_async_block(obj);
58    _evas_image_init_set(f, key, eo_obj, obj, o, &lo);
59    if (f)
60      o->engine_data = ENFN->image_mmap(ENC, o->cur->f, o->cur->key, &load_error, &lo);
61    else
62      o->engine_data = ENFN->image_load(ENC, efl_file_get(eo_obj), o->cur->key, &load_error, &lo);
63 
64    if (_evas_image_animated_get(eo_obj))
65      {
66         frame_index = ENFN->image_animated_frame_get(ENC, o->engine_data);
67         _evas_image_animated_frame_set(eo_obj, frame_index);
68      }
69 
70    o->load_error = _evas_load_error_to_efl_gfx_image_load_error(load_error);
71    o->buffer_data_set = EINA_FALSE;
72    _evas_image_done_set(eo_obj, obj, o);
73    o->file_size.w = o->cur->image.w;
74    o->file_size.h = o->cur->image.h;
75 
76    return EINA_TRUE;
77 }
78 
79 EOLIAN static Eina_Bool
_efl_canvas_image_efl_file_loaded_get(const Eo * eo_obj,void * _pd EINA_UNUSED)80 _efl_canvas_image_efl_file_loaded_get(const Eo *eo_obj, void *_pd EINA_UNUSED)
81 {
82    Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS);
83    if (!o->skip_head)
84      return efl_file_loaded_get(efl_super(eo_obj, MY_CLASS));
85    return !!o->cur->f;
86 }
87 
88 EOLIAN static const Eina_File *
_efl_canvas_image_efl_file_mmap_get(const Eo * eo_obj,void * _pd EINA_UNUSED)89 _efl_canvas_image_efl_file_mmap_get(const Eo *eo_obj, void *_pd EINA_UNUSED)
90 {
91    Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS);
92    if (!o->skip_head)
93      return efl_file_mmap_get(efl_super(eo_obj, MY_CLASS));
94    return o->cur->f;
95 }
96 
97 EOLIAN static Eina_Error
_efl_canvas_image_efl_file_load(Eo * eo_obj,void * _pd EINA_UNUSED)98 _efl_canvas_image_efl_file_load(Eo *eo_obj, void *_pd EINA_UNUSED)
99 {
100    if (efl_file_loaded_get(eo_obj)) return 0;
101    Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS);
102    Eina_Error err = 0;
103 
104    if (!o->skip_head)
105      err = efl_file_load(efl_super(eo_obj, MY_CLASS));
106    if (err) return err;
107    if (_evas_image_file_load(eo_obj, o))
108      return 0;
109    return EFL_GFX_IMAGE_LOAD_ERROR_DOES_NOT_EXIST;
110 }
111 
112 EOLIAN static void
_efl_canvas_image_efl_file_unload(Eo * eo_obj,void * _pd EINA_UNUSED)113 _efl_canvas_image_efl_file_unload(Eo *eo_obj, void *_pd EINA_UNUSED)
114 {
115    efl_file_unload(efl_super(eo_obj, MY_CLASS));
116    _evas_image_file_unload(eo_obj);
117 }
118 
119 const Eina_File *
_evas_image_mmap_get(const Eo * eo_obj)120 _evas_image_mmap_get(const Eo *eo_obj)
121 {
122    Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS);
123 
124    return o->cur->f;
125 }
126 
127 const char *
_evas_image_key_get(const Eo * eo_obj)128 _evas_image_key_get(const Eo *eo_obj)
129 {
130    Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS);
131 
132    return o->cur->key;
133 }
134 
135 void
_efl_canvas_image_load_error_set(Eo * eo_obj EINA_UNUSED,Eina_Error err)136 _efl_canvas_image_load_error_set(Eo *eo_obj EINA_UNUSED, Eina_Error err)
137 {
138    Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS);
139    o->load_error = err;
140 }
141 
142 static void
_image_preload_internal(Eo * eo_obj,Evas_Image_Data * o,Eina_Bool cancel)143 _image_preload_internal(Eo *eo_obj, Evas_Image_Data *o, Eina_Bool cancel)
144 {
145    if (!o->engine_data)
146      {
147         o->preload = EVAS_IMAGE_PRELOADING;
148         evas_object_inform_call_image_preloaded(eo_obj);
149         return;
150      }
151    // FIXME: if already busy preloading, then dont request again until
152    // preload done
153    Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
154    if (cancel)
155      {
156         if (o->preload & EVAS_IMAGE_PRELOADING)
157           {
158              o->preload |= EVAS_IMAGE_PRELOAD_CANCEL;
159              ENFN->image_data_preload_cancel(ENC, o->engine_data, eo_obj, EINA_TRUE);
160           }
161      }
162    else
163      {
164         if (o->preload != EVAS_IMAGE_PRELOADING)
165           {
166              o->preload = EVAS_IMAGE_PRELOADING;
167              ENFN->image_data_preload_request(ENC, o->engine_data, eo_obj);
168           }
169      }
170 }
171 
172 void
_evas_image_load_async_start(Eo * eo_obj)173 _evas_image_load_async_start(Eo *eo_obj)
174 {
175    Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
176    Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS);
177 
178    evas_object_async_block(obj);
179    _image_preload_internal(eo_obj, o, EINA_FALSE);
180 }
181 
182 EOLIAN static void
_efl_canvas_image_efl_gfx_image_load_controller_load_async_start(Eo * eo_obj,void * _pd EINA_UNUSED)183 _efl_canvas_image_efl_gfx_image_load_controller_load_async_start(Eo *eo_obj, void *_pd EINA_UNUSED)
184 {
185    _evas_image_load_async_start(eo_obj);
186 }
187 
188 void
_evas_image_load_async_cancel(Eo * eo_obj)189 _evas_image_load_async_cancel(Eo *eo_obj)
190 {
191    Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
192    Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS);
193 
194    evas_object_async_block(obj);
195    _image_preload_internal(eo_obj, o, EINA_TRUE);
196 }
197 
198 EOLIAN static void
_efl_canvas_image_efl_gfx_image_load_controller_load_async_cancel(Eo * eo_obj,void * _pd EINA_UNUSED)199 _efl_canvas_image_efl_gfx_image_load_controller_load_async_cancel(Eo *eo_obj, void *_pd EINA_UNUSED)
200 {
201    _evas_image_load_async_cancel(eo_obj);
202 }
203 
204 void
_evas_image_load_dpi_set(Eo * eo_obj,double dpi)205 _evas_image_load_dpi_set(Eo *eo_obj, double dpi)
206 {
207    Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
208    Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS);
209 
210    if (EINA_DBL_EQ(dpi, o->load_opts->dpi)) return;
211    evas_object_async_block(obj);
212    EINA_COW_LOAD_OPTS_WRITE_BEGIN(o, low)
213      low->dpi = dpi;
214    EINA_COW_LOAD_OPTS_WRITE_END(o, low);
215 
216    if (o->cur->f)
217      {
218         _evas_image_unload(eo_obj, obj, 0);
219         evas_object_inform_call_image_unloaded(eo_obj);
220         _evas_image_load(eo_obj, obj, o);
221         o->changed = EINA_TRUE;
222         evas_object_change(eo_obj, obj);
223      }
224 }
225 
226 EOLIAN static void
_efl_canvas_image_efl_gfx_image_load_controller_load_dpi_set(Eo * eo_obj,void * _pd EINA_UNUSED,double dpi)227 _efl_canvas_image_efl_gfx_image_load_controller_load_dpi_set(Eo *eo_obj, void *_pd EINA_UNUSED, double dpi)
228 {
229    _evas_image_load_dpi_set(eo_obj, dpi);
230 }
231 
232 double
_evas_image_load_dpi_get(const Eo * eo_obj)233 _evas_image_load_dpi_get(const Eo *eo_obj)
234 {
235    Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS);
236 
237    return o->load_opts->dpi;
238 }
239 
240 EOLIAN static double
_efl_canvas_image_efl_gfx_image_load_controller_load_dpi_get(const Eo * eo_obj,void * _pd EINA_UNUSED)241 _efl_canvas_image_efl_gfx_image_load_controller_load_dpi_get(const Eo *eo_obj, void *_pd EINA_UNUSED)
242 {
243    return _evas_image_load_dpi_get(eo_obj);
244 }
245 
246 void
_evas_image_load_size_set(Eo * eo_obj,int w,int h)247 _evas_image_load_size_set(Eo *eo_obj, int w, int h)
248 {
249    Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
250    Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS);
251 
252    if ((o->load_opts->w == w) && (o->load_opts->h == h)) return;
253    evas_object_async_block(obj);
254    EINA_COW_LOAD_OPTS_WRITE_BEGIN(o, low)
255    {
256       low->w = w;
257       low->h = h;
258    }
259    EINA_COW_LOAD_OPTS_WRITE_END(o, low);
260 
261    if (o->cur->f)
262      {
263         _evas_image_unload(eo_obj, obj, 0);
264         evas_object_inform_call_image_unloaded(eo_obj);
265         _evas_image_load(eo_obj, obj, o);
266         o->changed = EINA_TRUE;
267         evas_object_change(eo_obj, obj);
268      }
269    o->proxyerror = 0;
270 }
271 
272 EOLIAN static void
_efl_canvas_image_efl_gfx_image_load_controller_load_size_set(Eo * eo_obj,void * _pd EINA_UNUSED,Eina_Size2D sz)273 _efl_canvas_image_efl_gfx_image_load_controller_load_size_set(Eo *eo_obj, void *_pd EINA_UNUSED, Eina_Size2D sz)
274 {
275    _evas_image_load_size_set(eo_obj, sz.w, sz.h);
276 }
277 
278 void
_evas_image_load_size_get(const Eo * eo_obj,int * w,int * h)279 _evas_image_load_size_get(const Eo *eo_obj, int *w, int *h)
280 {
281    Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS);
282 
283    if (w) *w = o->load_opts->w;
284    if (h) *h = o->load_opts->h;
285 }
286 
287 EOLIAN static Eina_Size2D
_efl_canvas_image_efl_gfx_image_load_controller_load_size_get(const Eo * eo_obj,void * _pd EINA_UNUSED)288 _efl_canvas_image_efl_gfx_image_load_controller_load_size_get(const Eo *eo_obj, void *_pd EINA_UNUSED)
289 {
290    Eina_Size2D sz;
291    _evas_image_load_size_get(eo_obj, &sz.w, &sz.h);
292    return sz;
293 }
294 
295 void
_evas_image_load_scale_down_set(Eo * eo_obj,int scale_down)296 _evas_image_load_scale_down_set(Eo *eo_obj, int scale_down)
297 {
298    Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
299    Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS);
300 
301    if (o->load_opts->scale_down_by == scale_down) return;
302    evas_object_async_block(obj);
303    EINA_COW_LOAD_OPTS_WRITE_BEGIN(o, low)
304      low->scale_down_by = scale_down;
305    EINA_COW_LOAD_OPTS_WRITE_END(o, low);
306 
307    if (o->cur->f)
308      {
309         _evas_image_unload(eo_obj, obj, 0);
310         evas_object_inform_call_image_unloaded(eo_obj);
311         _evas_image_load(eo_obj, obj, o);
312         o->changed = EINA_TRUE;
313         evas_object_change(eo_obj, obj);
314      }
315 }
316 
317 EOLIAN static void
_efl_canvas_image_efl_gfx_image_load_controller_load_scale_down_set(Eo * eo_obj,void * _pd EINA_UNUSED,int scale_down)318 _efl_canvas_image_efl_gfx_image_load_controller_load_scale_down_set(Eo *eo_obj, void *_pd EINA_UNUSED, int scale_down)
319 {
320    _evas_image_load_scale_down_set(eo_obj, scale_down);
321 }
322 
323 int
_evas_image_load_scale_down_get(const Eo * eo_obj)324 _evas_image_load_scale_down_get(const Eo *eo_obj)
325 {
326    Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS);
327 
328    return o->load_opts->scale_down_by;
329 }
330 
331 EOLIAN static int
_efl_canvas_image_efl_gfx_image_load_controller_load_scale_down_get(const Eo * eo_obj,void * _pd EINA_UNUSED)332 _efl_canvas_image_efl_gfx_image_load_controller_load_scale_down_get(const Eo *eo_obj, void *_pd EINA_UNUSED)
333 {
334    return _evas_image_load_scale_down_get(eo_obj);
335 }
336 
337 void
_evas_image_load_head_skip_set(const Eo * eo_obj,Eina_Bool skip)338 _evas_image_load_head_skip_set(const Eo *eo_obj, Eina_Bool skip)
339 {
340    Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS);
341    o->skip_head = skip;
342 }
343 
344 EOLIAN static void
_efl_canvas_image_efl_gfx_image_load_controller_load_skip_header_set(Eo * eo_obj,void * _pd EINA_UNUSED,Eina_Bool skip)345 _efl_canvas_image_efl_gfx_image_load_controller_load_skip_header_set(Eo *eo_obj, void *_pd EINA_UNUSED, Eina_Bool skip)
346 {
347    _evas_image_load_head_skip_set(eo_obj, skip);
348 }
349 
350 Eina_Bool
_evas_image_load_head_skip_get(const Eo * eo_obj)351 _evas_image_load_head_skip_get(const Eo *eo_obj)
352 {
353    Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS);
354    return o->skip_head;
355 }
356 
357 EOLIAN static Eina_Bool
_efl_canvas_image_efl_gfx_image_load_controller_load_skip_header_get(const Eo * eo_obj,void * _pd EINA_UNUSED)358 _efl_canvas_image_efl_gfx_image_load_controller_load_skip_header_get(const Eo *eo_obj, void *_pd EINA_UNUSED)
359 {
360    return _evas_image_load_head_skip_get(eo_obj);
361 }
362 
363 void
_evas_image_load_region_set(Eo * eo_obj,int x,int y,int w,int h)364 _evas_image_load_region_set(Eo *eo_obj, int x, int y, int w, int h)
365 {
366    Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
367    Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS);
368 
369    if ((o->load_opts->region.x == x) && (o->load_opts->region.y == y) &&
370        (o->load_opts->region.w == w) && (o->load_opts->region.h == h)) return;
371    evas_object_async_block(obj);
372    EINA_COW_LOAD_OPTS_WRITE_BEGIN(o, low)
373    {
374       low->region.x = x;
375       low->region.y = y;
376       low->region.w = w;
377       low->region.h = h;
378    }
379    EINA_COW_LOAD_OPTS_WRITE_END(o, low);
380 
381    if (o->cur->f)
382      {
383         _evas_image_unload(eo_obj, obj, 0);
384         evas_object_inform_call_image_unloaded(eo_obj);
385         _evas_image_load(eo_obj, obj, o);
386         o->changed = EINA_TRUE;
387         evas_object_change(eo_obj, obj);
388      }
389 }
390 
391 EOLIAN static void
_efl_canvas_image_efl_gfx_image_load_controller_load_region_set(Eo * eo_obj,void * _pd EINA_UNUSED,Eina_Rect region)392 _efl_canvas_image_efl_gfx_image_load_controller_load_region_set(Eo *eo_obj, void *_pd EINA_UNUSED, Eina_Rect region)
393 {
394    _evas_image_load_region_set(eo_obj, region.x, region.y, region.w, region.h);
395 }
396 
397 void
_evas_image_load_region_get(const Eo * eo_obj,int * x,int * y,int * w,int * h)398 _evas_image_load_region_get(const Eo *eo_obj, int *x, int *y, int *w, int *h)
399 {
400    Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS);
401 
402    if (x) *x = o->load_opts->region.x;
403    if (y) *y = o->load_opts->region.y;
404    if (w) *w = o->load_opts->region.w;
405    if (h) *h = o->load_opts->region.h;
406 }
407 
408 EOLIAN static Eina_Rect
_efl_canvas_image_efl_gfx_image_load_controller_load_region_get(const Eo * eo_obj,void * _pd EINA_UNUSED)409 _efl_canvas_image_efl_gfx_image_load_controller_load_region_get(const Eo *eo_obj, void *_pd EINA_UNUSED)
410 {
411    Eina_Rect r;
412    _evas_image_load_region_get(eo_obj, &r.x, &r.y, &r.w, &r.h);
413    return r;
414 }
415 
416 void
_evas_image_load_orientation_set(Eo * eo_obj,Eina_Bool enable)417 _evas_image_load_orientation_set(Eo *eo_obj, Eina_Bool enable)
418 {
419    Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
420    Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS);
421 
422    if (o->load_opts->orientation == !!enable) return;
423    evas_object_async_block(obj);
424 
425    EINA_COW_LOAD_OPTS_WRITE_BEGIN(o, low)
426          low->orientation = !!enable;
427    EINA_COW_LOAD_OPTS_WRITE_END(o, low);
428 }
429 
430 EOLIAN static void
_efl_canvas_image_efl_gfx_image_load_controller_load_orientation_set(Eo * eo_obj,void * _pd EINA_UNUSED,Eina_Bool enable)431 _efl_canvas_image_efl_gfx_image_load_controller_load_orientation_set(Eo *eo_obj, void *_pd EINA_UNUSED, Eina_Bool enable)
432 {
433    _evas_image_load_orientation_set(eo_obj, enable);
434 }
435 
436 Eina_Bool
_evas_image_load_orientation_get(const Eo * eo_obj)437 _evas_image_load_orientation_get(const Eo *eo_obj)
438 {
439    Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS);
440 
441    return o->load_opts->orientation;
442 }
443 
444 EOLIAN static Eina_Bool
_efl_canvas_image_efl_gfx_image_load_controller_load_orientation_get(const Eo * eo_obj,void * _pd EINA_UNUSED)445 _efl_canvas_image_efl_gfx_image_load_controller_load_orientation_get(const Eo *eo_obj, void *_pd EINA_UNUSED)
446 {
447    return _evas_image_load_orientation_get(eo_obj);
448 }
449 
450 Eina_Bool
_evas_image_load_region_support_get(const Eo * eo_obj)451 _evas_image_load_region_support_get(const Eo *eo_obj)
452 {
453    Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
454    Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS);
455 
456    return ENFN->image_can_region_get(ENC, o->engine_data);
457 }
458 
459 EOLIAN static Eina_Bool
_efl_canvas_image_efl_gfx_image_load_controller_load_region_support_get(const Eo * eo_obj,void * _pd EINA_UNUSED)460 _efl_canvas_image_efl_gfx_image_load_controller_load_region_support_get(const Eo *eo_obj, void *_pd EINA_UNUSED)
461 {
462    return _evas_image_load_region_support_get(eo_obj);
463 }
464 
465 /* animated feature */
466 Eina_Bool
_evas_image_animated_get(const Eo * eo_obj)467 _evas_image_animated_get(const Eo *eo_obj)
468 {
469    Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
470    Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS);
471 
472    if (!ENFN->image_animated_get)
473      return EINA_FALSE;
474 
475    return ENFN->image_animated_get(ENC, o->engine_data);
476 }
477 
478 EOLIAN static Eina_Bool
_efl_canvas_image_efl_gfx_frame_controller_animated_get(const Eo * eo_obj,void * _pd EINA_UNUSED)479 _efl_canvas_image_efl_gfx_frame_controller_animated_get(const Eo *eo_obj, void *_pd EINA_UNUSED)
480 {
481    return _evas_image_animated_get(eo_obj);
482 }
483 
484 int
_evas_image_animated_frame_count_get(const Eo * eo_obj)485 _evas_image_animated_frame_count_get(const Eo *eo_obj)
486 {
487    Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
488    Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS);
489 
490    if (!ENFN->image_animated_frame_count_get ||
491        !evas_object_image_animated_get(eo_obj))
492      return -1;
493 
494    obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
495    return ENFN->image_animated_frame_count_get(ENC, o->engine_data);
496 }
497 
498 EOLIAN static int
_efl_canvas_image_efl_gfx_frame_controller_frame_count_get(const Eo * eo_obj,void * _pd EINA_UNUSED)499 _efl_canvas_image_efl_gfx_frame_controller_frame_count_get(const Eo *eo_obj, void *_pd EINA_UNUSED)
500 {
501    return _evas_image_animated_frame_count_get(eo_obj);
502 }
503 
504 Efl_Gfx_Frame_Controller_Loop_Hint
_evas_image_animated_loop_type_get(const Eo * eo_obj)505 _evas_image_animated_loop_type_get(const Eo *eo_obj)
506 {
507    Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
508    Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS);
509 
510    if (!ENFN->image_animated_loop_type_get ||
511        !evas_object_image_animated_get(eo_obj))
512      return EFL_GFX_FRAME_CONTROLLER_LOOP_HINT_NONE;
513 
514    return (Efl_Gfx_Frame_Controller_Loop_Hint) ENFN->image_animated_loop_type_get(ENC, o->engine_data);
515 }
516 
517 EOLIAN static Efl_Gfx_Frame_Controller_Loop_Hint
_efl_canvas_image_efl_gfx_frame_controller_loop_type_get(const Eo * eo_obj,void * _pd EINA_UNUSED)518 _efl_canvas_image_efl_gfx_frame_controller_loop_type_get(const Eo *eo_obj, void *_pd EINA_UNUSED)
519 {
520    return _evas_image_animated_loop_type_get(eo_obj);
521 }
522 
523 int
_evas_image_animated_loop_count_get(const Eo * eo_obj)524 _evas_image_animated_loop_count_get(const Eo *eo_obj)
525 {
526    Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
527    Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS);
528 
529    if (!ENFN->image_animated_loop_count_get ||
530        !evas_object_image_animated_get(eo_obj))
531      return -1;
532 
533    return ENFN->image_animated_loop_count_get(ENC, o->engine_data);
534 }
535 
536 EOLIAN static int
_efl_canvas_image_efl_gfx_frame_controller_loop_count_get(const Eo * eo_obj,void * _pd EINA_UNUSED)537 _efl_canvas_image_efl_gfx_frame_controller_loop_count_get(const Eo *eo_obj, void *_pd EINA_UNUSED)
538 {
539    return _evas_image_animated_loop_count_get(eo_obj);
540 }
541 
542 double
_evas_image_animated_frame_duration_get(const Eo * eo_obj,int start_frame,int frame_num)543 _evas_image_animated_frame_duration_get(const Eo *eo_obj, int start_frame, int frame_num)
544 {
545    Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
546    Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS);
547    int frame_count = 0;
548 
549    if (!ENFN->image_animated_frame_count_get ||
550        !ENFN->image_animated_frame_duration_get)
551      return -1.0;
552 
553    frame_count = ENFN->image_animated_frame_count_get(ENC, o->engine_data);
554    if ((start_frame + frame_num) > frame_count)
555      return -1.0;
556 
557    return ENFN->image_animated_frame_duration_get(ENC, o->engine_data, start_frame, frame_num);
558 }
559 
560 EOLIAN static double
_efl_canvas_image_efl_gfx_frame_controller_frame_duration_get(const Eo * eo_obj,void * _pd EINA_UNUSED,int start_frame,int frame_num)561 _efl_canvas_image_efl_gfx_frame_controller_frame_duration_get(const Eo *eo_obj, void *_pd EINA_UNUSED, int start_frame, int frame_num)
562 {
563    return _evas_image_animated_frame_duration_get(eo_obj, start_frame, frame_num);
564 }
565 
_efl_canvas_image_efl_gfx_frame_controller_sector_set(Eo * obj EINA_UNUSED,void * _pd EINA_UNUSED,const char * name EINA_UNUSED,int startframe EINA_UNUSED,int endframe EINA_UNUSED)566 Eina_Bool _efl_canvas_image_efl_gfx_frame_controller_sector_set(Eo *obj EINA_UNUSED,
567                                                                     void *_pd EINA_UNUSED,
568                                                                     const char *name EINA_UNUSED,
569                                                                     int startframe EINA_UNUSED,
570                                                                     int endframe EINA_UNUSED)
571 {
572    // TODO: We need to implement the feature to section playback of image animation.
573    ERR("efl_gfx_frame_controller_sector_set not implemented for efl_canvas_image yet.");
574    return EINA_FALSE;
575 }
576 
_efl_canvas_image_efl_gfx_frame_controller_sector_get(const Eo * obj EINA_UNUSED,void * _pd EINA_UNUSED,const char * name EINA_UNUSED,int * startframe EINA_UNUSED,int * endframe EINA_UNUSED)577 Eina_Bool _efl_canvas_image_efl_gfx_frame_controller_sector_get(const Eo *obj EINA_UNUSED,
578                                                                       void *_pd EINA_UNUSED,
579                                                                       const char *name EINA_UNUSED,
580                                                                       int *startframe EINA_UNUSED,
581                                                                       int *endframe EINA_UNUSED)
582 {
583    // TODO: We need to implement the feature to section playback of image animation.
584    ERR("efl_gfx_frame_controller_sector_get not implemented for efl_canvas_image yet.");
585    return EINA_FALSE;
586 }
587 
588 Eina_Bool
_evas_image_animated_frame_set(Eo * eo_obj,int frame_index)589 _evas_image_animated_frame_set(Eo *eo_obj, int frame_index)
590 {
591    Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
592    Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS);
593    int frame_count = 0;
594 
595    if (!o->cur->f) return EINA_FALSE;
596    if (o->cur->frame == frame_index) return EINA_TRUE;
597 
598    if (!evas_object_image_animated_get(eo_obj)) return EINA_FALSE;
599    evas_object_async_block(obj);
600    frame_count = evas_object_image_animated_frame_count_get(eo_obj);
601 
602    /* limit the size of frame to FRAME_MAX */
603    if ((frame_count > FRAME_MAX) || (frame_count < 0) || (frame_index > frame_count))
604      return EINA_FALSE;
605 
606    if (!ENFN->image_animated_frame_set) return EINA_FALSE;
607    ENFN->image_animated_frame_set(ENC, o->engine_data, frame_index);
608    //   if (!ENFN->image_animated_frame_set(ENC, o->engine_data, frame_index)) return;
609 
610    EINA_COW_WRITE_BEGIN(evas_object_image_state_cow, o->prev, Evas_Object_Image_State, prev_write)
611      prev_write->frame = o->cur->frame;
612    EINA_COW_WRITE_END(evas_object_image_state_cow, o->prev, prev_write);
613 
614    EINA_COW_IMAGE_STATE_WRITE_BEGIN(o, state_write)
615      state_write->frame = frame_index;
616    EINA_COW_IMAGE_STATE_WRITE_END(o, state_write);
617 
618    o->changed = EINA_TRUE;
619    evas_object_change(eo_obj, obj);
620 
621    return EINA_TRUE;
622 }
623 
624 EOLIAN static Eina_Bool
_efl_canvas_image_efl_gfx_frame_controller_frame_set(Eo * eo_obj,void * _pd EINA_UNUSED,int frame_index)625 _efl_canvas_image_efl_gfx_frame_controller_frame_set(Eo *eo_obj, void *_pd EINA_UNUSED, int frame_index)
626 {
627    return _evas_image_animated_frame_set(eo_obj, frame_index);
628 }
629 
630 int
_evas_image_animated_frame_get(const Eo * eo_obj)631 _evas_image_animated_frame_get(const Eo *eo_obj)
632 {
633    Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS);
634 
635    if (!o->cur->f) return EINA_FALSE;
636    if (!evas_object_image_animated_get(eo_obj)) return EINA_FALSE;
637    return o->cur->frame;
638 }
639 
640 EOLIAN static int
_efl_canvas_image_efl_gfx_frame_controller_frame_get(const Eo * eo_obj,void * _pd EINA_UNUSED)641 _efl_canvas_image_efl_gfx_frame_controller_frame_get(const Eo *eo_obj, void *_pd EINA_UNUSED)
642 {
643    return _evas_image_animated_frame_get(eo_obj);
644 }
645 
646 EOLIAN static Eina_Size2D
_efl_canvas_image_efl_gfx_buffer_buffer_size_get(const Eo * eo_obj,void * _pd EINA_UNUSED)647 _efl_canvas_image_efl_gfx_buffer_buffer_size_get(const Eo *eo_obj, void *_pd EINA_UNUSED)
648 {
649    Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS);
650 
651    return EINA_SIZE2D(o->cur->image.w, o->cur->image.h);
652 }
653 
654 static Eina_Bool
_image_pixels_set(Evas_Object_Protected_Data * obj,Evas_Image_Data * o,const Eina_Slice * slice,int w,int h,int stride,Efl_Gfx_Colorspace cspace,int plane,Eina_Bool copy)655 _image_pixels_set(Evas_Object_Protected_Data *obj,
656                   Evas_Image_Data *o, const Eina_Slice *slice,
657                   int w, int h, int stride, Efl_Gfx_Colorspace cspace, int plane,
658                   Eina_Bool copy)
659 {
660    Eina_Bool resized = EINA_FALSE, ret = EINA_FALSE;
661    int int_stride = 0;
662 
663    // FIXME: buffer border support is not implemented
664 
665    if (ENFN->image_data_maps_get)
666      {
667         if (ENFN->image_data_maps_get(ENC, o->engine_data, NULL) > 0)
668           {
669              ERR("can not set pixels when there are open memory maps");
670              return EINA_FALSE;
671           }
672      }
673 
674    if (o->pixels_checked_out)
675      {
676         // is there anything to do?
677         ERR("Calling efl_gfx_buffer_%s_set after evas_object_image_data_get is "
678             "not valid.", copy ? "copy" : "managed");
679         return EINA_FALSE;
680      }
681 
682    if (o->engine_data)
683      {
684         Evas_Colorspace ics;
685         int iw = 0, ih = 0;
686         Eina_Bool alpha;
687 
688         ENFN->image_size_get(ENC, o->engine_data, &iw, &ih);
689         ics = ENFN->image_colorspace_get(ENC, o->engine_data);
690         alpha = ENFN->image_alpha_get(ENC, o->engine_data);
691         if ((w != iw) || (h != ih) || (ics != (Evas_Colorspace)cspace) || (alpha != o->cur->has_alpha))
692           {
693              ENFN->image_free(ENC, o->engine_data);
694              o->engine_data = NULL;
695           }
696      }
697 
698    if (!slice || !slice->mem)
699      {
700         // note: we release all planes at once
701         if (o->engine_data)
702           ENFN->image_free(ENC, o->engine_data);
703         o->engine_data = ENFN->image_new_from_copied_data(ENC, w, h, NULL, o->cur->has_alpha, (Evas_Colorspace)cspace);
704      }
705    else
706      {
707         o->buffer_data_set = EINA_TRUE;
708         o->engine_data = ENFN->image_data_slice_add(ENC, o->engine_data,
709                                                     slice, copy, w, h, stride,
710                                                     (Evas_Colorspace)cspace, plane, o->cur->has_alpha);
711      }
712 
713    if (!o->engine_data)
714      {
715         ERR("Failed to create internal image");
716         goto end;
717      }
718 
719    if ((o->cur->image.w != w) || (o->cur->image.h != h))
720      resized = EINA_TRUE;
721 
722    if (ENFN->image_scale_hint_set)
723      ENFN->image_scale_hint_set(ENC, o->engine_data, o->scale_hint);
724 
725    if (ENFN->image_content_hint_set)
726      ENFN->image_content_hint_set(ENC, o->engine_data, o->content_hint);
727 
728    if (ENFN->image_stride_get)
729      ENFN->image_stride_get(ENC, o->engine_data, &int_stride);
730 
731    if (resized || o->cur->f || o->cur->key ||
732        (o->cur->image.stride != int_stride) || (cspace != (Efl_Gfx_Colorspace)o->cur->cspace))
733      {
734         EINA_COW_IMAGE_STATE_WRITE_BEGIN(o, cur)
735         {
736            cur->f = NULL;
737            cur->key = NULL;
738            cur->cspace = (Evas_Colorspace)cspace;
739            cur->image.w = w;
740            cur->image.h = h;
741            cur->image.stride = int_stride;
742         }
743         EINA_COW_IMAGE_STATE_WRITE_END(o, cur)
744      }
745 
746    ret = EINA_TRUE;
747 
748 end:
749    o->written = EINA_TRUE;
750    if (resized)
751      evas_object_inform_call_image_resize(obj->object);
752 
753    efl_gfx_buffer_update_add(obj->object, NULL);
754    return ret;
755 }
756 
757 EOLIAN static Eina_Bool
_efl_canvas_image_efl_gfx_buffer_buffer_managed_set(Eo * eo_obj,void * _pd EINA_UNUSED,const Eina_Slice * slice,Eina_Size2D size,int stride,Efl_Gfx_Colorspace cspace,int plane)758 _efl_canvas_image_efl_gfx_buffer_buffer_managed_set(Eo *eo_obj, void *_pd EINA_UNUSED,
759                                                     const Eina_Slice *slice,
760                                                     Eina_Size2D size, int stride,
761                                                     Efl_Gfx_Colorspace cspace,
762                                                     int plane)
763 {
764    Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
765    Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS);
766 
767    return _image_pixels_set(obj, o, slice, size.w, size.h, stride, cspace, plane, EINA_FALSE);
768 }
769 
770 EOLIAN static Eina_Bool
_efl_canvas_image_efl_gfx_buffer_buffer_copy_set(Eo * eo_obj,void * _pd EINA_UNUSED,const Eina_Slice * slice,Eina_Size2D size,int stride,Efl_Gfx_Colorspace cspace,int plane)771 _efl_canvas_image_efl_gfx_buffer_buffer_copy_set(Eo *eo_obj, void *_pd EINA_UNUSED,
772                                                  const Eina_Slice *slice, Eina_Size2D size, int stride,
773                                                  Efl_Gfx_Colorspace cspace, int plane)
774 {
775    Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
776    Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS);
777 
778    return _image_pixels_set(obj, o, slice, size.w, size.h, stride, cspace, plane, EINA_TRUE);
779 }
780 
781 EOLIAN static Eina_Slice
_efl_canvas_image_efl_gfx_buffer_buffer_managed_get(Eo * eo_obj,void * _pd EINA_UNUSED,int plane)782 _efl_canvas_image_efl_gfx_buffer_buffer_managed_get(Eo *eo_obj, void *_pd EINA_UNUSED,
783                                                     int plane)
784 {
785    Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
786    Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS);
787    Evas_Colorspace cspace = EVAS_COLORSPACE_ARGB8888;
788    Eina_Slice slice = {};
789 
790    if (!o->buffer_data_set || !o->engine_data || !ENFN->image_data_direct_get)
791      return slice;
792 
793    ENFN->image_data_direct_get(ENC, o->engine_data, plane, &slice, &cspace, EINA_FALSE, NULL);
794 
795    return slice;
796 }
797 
798 EOLIAN static Eina_Rw_Slice
_efl_canvas_image_efl_gfx_buffer_buffer_map(Eo * eo_obj,void * _pd EINA_UNUSED,Efl_Gfx_Buffer_Access_Mode mode,const Eina_Rect * region,Efl_Gfx_Colorspace cspace,int plane,int * stride)799 _efl_canvas_image_efl_gfx_buffer_buffer_map(Eo *eo_obj, void *_pd EINA_UNUSED,
800                                             Efl_Gfx_Buffer_Access_Mode mode,
801                                             const Eina_Rect *region,
802                                             Efl_Gfx_Colorspace cspace,
803                                             int plane, int *stride)
804 {
805    Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
806    Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS);
807    int s = 0, width = 0, height = 0;
808    Eina_Rw_Slice slice = {};
809    int x, y, w, h;
810 
811    if (!ENFN->image_data_map)
812      goto end; // not implemented
813 
814    if (o->engine_data)
815      ENFN->image_size_get(ENC, o->engine_data, &width, &height);
816 
817    if (!o->engine_data || !width || !height)
818      {
819         // TODO: Create a map_surface and draw there. Maybe. This could
820         // depend on the flags (eg. add a "force render" flag).
821         WRN("This image image has no data available");
822         goto end;
823      }
824 
825    if (region)
826      {
827         x = region->x;
828         y = region->y;
829         w = region->w;
830         h = region->h;
831      }
832    else
833      {
834         x = y = 0;
835         w = width;
836         h = height;
837      }
838 
839    if ((x < 0) || (y < 0) || (w <= 0) || (h <= 0) || ((x + w) > width) || ((y + h) > height))
840      {
841         ERR("Invalid map dimensions: %dx%d +%d,%d. Image is %dx%d.",
842             w, h, x, y, width, height);
843         goto end;
844      }
845 
846    if (ENFN->image_data_map(ENC, &o->engine_data, &slice, &s, x, y, w, h, (Evas_Colorspace)cspace, mode, plane))
847      {
848         DBG("map(%p, %d,%d %dx%d plane:%d) -> " EINA_SLICE_FMT,
849             eo_obj, x, y, w, h, plane, EINA_SLICE_PRINT(slice));
850      }
851    else DBG("map(%p, %d,%d %dx%d plane:%d) -> (null)", eo_obj, x, y, w, h, plane);
852 
853 end:
854    if (stride) *stride = s;
855    return slice;
856 }
857 
858 EOLIAN static Eina_Bool
_efl_canvas_image_efl_gfx_buffer_buffer_unmap(Eo * eo_obj,void * _pd EINA_UNUSED,Eina_Rw_Slice slice)859 _efl_canvas_image_efl_gfx_buffer_buffer_unmap(Eo *eo_obj, void *_pd EINA_UNUSED,
860                                               Eina_Rw_Slice slice)
861 {
862    Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
863    Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS);
864 
865    if (!slice.mem || !ENFN->image_data_unmap || !o->engine_data)
866      return EINA_FALSE;
867 
868    if (!ENFN->image_data_unmap(ENC, o->engine_data, &slice))
869      return EINA_FALSE;
870 
871    return EINA_TRUE;
872 }
873 
874 EOLIAN static void
_efl_canvas_image_efl_object_dbg_info_get(Eo * obj,void * pd EINA_UNUSED,Efl_Dbg_Info * root)875 _efl_canvas_image_efl_object_dbg_info_get(Eo *obj, void *pd EINA_UNUSED, Efl_Dbg_Info *root)
876 {
877    efl_dbg_info_get(efl_super(obj, MY_CLASS), root);
878 
879    if ((efl_gfx_image_load_error_get(obj) != EFL_GFX_IMAGE_LOAD_ERROR_NONE) &&
880        (root))
881      {
882         Efl_Dbg_Info *group = EFL_DBG_INFO_LIST_APPEND(root, MY_CLASS_NAME);
883         Eina_Error error = EFL_GFX_IMAGE_LOAD_ERROR_GENERIC;
884 
885         error = efl_gfx_image_load_error_get(obj);
886         EFL_DBG_INFO_APPEND(group, "Load Error", EINA_VALUE_TYPE_STRING,
887                             eina_error_msg_get(error));
888      }
889 }
890 
891 #define EFL_CANVAS_IMAGE_EXTRA_OPS \
892    EFL_OBJECT_OP_FUNC(efl_dbg_info_get, _efl_canvas_image_efl_object_dbg_info_get)
893 
894 #include "efl_canvas_image.eo.c"
895