5afd994fc8adea40c236df482425d9ed05f734ef
[framework/uifw/evas.git] / src / lib / canvas / evas_object_image.c
1 #include <sys/types.h>
2 #include <unistd.h>
3 #include <stdlib.h>
4 #include <sys/mman.h>
5
6 #include "evas_common.h"
7 #include "evas_private.h"
8 #include "../engines/common/evas_convert_color.h"
9 #include "../engines/common/evas_convert_colorspace.h"
10 #include "../engines/common/evas_convert_yuv.h"
11
12 #define VERBOSE_PROXY_ERROR 1
13
14 /* private magic number for image objects */
15 static const char o_type[] = "image";
16
17 /* private struct for rectangle object internal data */
18 typedef struct _Evas_Object_Image      Evas_Object_Image;
19
20 struct _Evas_Object_Image
21 {
22    DATA32            magic;
23
24    struct {
25       int                  spread;
26       Evas_Coord_Rectangle fill;
27       struct {
28          short         w, h, stride;
29       } image;
30       struct {
31          short         l, r, t, b;
32          unsigned char fill;
33          double        scale;
34       } border;
35
36       Evas_Object   *source;
37       Evas_Map      *defmap;
38       const char    *file;
39       const char    *key;
40       int            frame;
41       int            cspace;
42
43       unsigned char  smooth_scale : 1;
44       unsigned char  has_alpha :1;
45       unsigned char  opaque :1;
46       unsigned char  opaque_valid :1;
47    } cur, prev;
48
49    int               pixels_checked_out;
50    int               load_error;
51    Eina_List        *pixel_updates;
52
53    struct {
54       unsigned char  scale_down_by;
55       double         dpi;
56       short          w, h;
57       struct {
58          short       x, y, w, h;
59       } region;
60       Eina_Bool  orientation : 1;
61    } load_opts;
62
63    struct {
64       Evas_Object_Image_Pixels_Get_Cb  get_pixels;
65       void                            *get_pixels_data;
66    } func;
67    
68    const char             *tmpf;
69    int                     tmpf_fd;
70
71    Evas_Image_Scale_Hint   scale_hint;
72    Evas_Image_Content_Hint content_hint;
73
74    void             *engine_data;
75
76    unsigned char     changed : 1;
77    unsigned char     dirty_pixels : 1;
78    unsigned char     filled : 1;
79    unsigned char     proxyrendering : 1;
80    unsigned char     preloading : 1;
81 };
82
83 /* private methods for image objects */
84 static void evas_object_image_unload(Evas_Object *obj, Eina_Bool dirty);
85 static void evas_object_image_load(Evas_Object *obj);
86 static Evas_Coord evas_object_image_figure_x_fill(Evas_Object *obj, Evas_Coord start, Evas_Coord size, Evas_Coord *size_ret);
87 static Evas_Coord evas_object_image_figure_y_fill(Evas_Object *obj, Evas_Coord start, Evas_Coord size, Evas_Coord *size_ret);
88
89 static void evas_object_image_init(Evas_Object *obj);
90 static void *evas_object_image_new(void);
91 static void evas_object_image_render(Evas_Object *obj, void *output, void *context, void *surface, int x, int y);
92 static void evas_object_image_free(Evas_Object *obj);
93 static void evas_object_image_render_pre(Evas_Object *obj);
94 static void evas_object_image_render_post(Evas_Object *obj);
95
96 static unsigned int evas_object_image_id_get(Evas_Object *obj);
97 static unsigned int evas_object_image_visual_id_get(Evas_Object *obj);
98 static void *evas_object_image_engine_data_get(Evas_Object *obj);
99
100 static int evas_object_image_is_opaque(Evas_Object *obj);
101 static int evas_object_image_was_opaque(Evas_Object *obj);
102 static int evas_object_image_is_inside(Evas_Object *obj, Evas_Coord x, Evas_Coord y);
103 static int evas_object_image_has_opaque_rect(Evas_Object *obj);
104 static int evas_object_image_get_opaque_rect(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h);
105 static int evas_object_image_can_map(Evas_Object *obj);
106
107 static void *evas_object_image_data_convert_internal(Evas_Object_Image *o, void *data, Evas_Colorspace to_cspace);
108 static void evas_object_image_filled_resize_listener(void *data, Evas *e, Evas_Object *obj, void *einfo);
109
110 static void _proxy_unset(Evas_Object *proxy);
111 static void _proxy_set(Evas_Object *proxy, Evas_Object *src);
112 static void _proxy_error(Evas_Object *proxy, void *context, void *output, void *surface, int x, int y);
113
114 static void _cleanup_tmpf(Evas_Object *obj);
115
116 static const Evas_Object_Func object_func =
117 {
118    /* methods (compulsory) */
119    evas_object_image_free,
120      evas_object_image_render,
121      evas_object_image_render_pre,
122      evas_object_image_render_post,
123      evas_object_image_id_get,
124      evas_object_image_visual_id_get,
125      evas_object_image_engine_data_get,
126      /* these are optional. NULL = nothing */
127      NULL,
128      NULL,
129      NULL,
130      NULL,
131      evas_object_image_is_opaque,
132      evas_object_image_was_opaque,
133      evas_object_image_is_inside,
134      NULL,
135      NULL,
136      NULL,
137      evas_object_image_has_opaque_rect,
138      evas_object_image_get_opaque_rect,
139      evas_object_image_can_map
140 };
141
142 EVAS_MEMPOOL(_mp_obj);
143
144 EAPI Evas_Object *
145 evas_object_image_add(Evas *e)
146 {
147    Evas_Object *obj;
148    Evas_Object_Image *o;
149
150    MAGIC_CHECK(e, Evas, MAGIC_EVAS);
151    return NULL;
152    MAGIC_CHECK_END();
153    obj = evas_object_new(e);
154    evas_object_image_init(obj);
155    evas_object_inject(obj, e);
156    o = (Evas_Object_Image *)(obj->object_data);
157    o->cur.cspace = obj->layer->evas->engine.func->image_colorspace_get(obj->layer->evas->engine.data.output,
158                                                                        o->engine_data);
159    return obj;
160 }
161
162 EAPI Evas_Object *
163 evas_object_image_filled_add(Evas *e)
164 {
165    Evas_Object *obj;
166    obj = evas_object_image_add(e);
167    evas_object_image_filled_set(obj, 1);
168    return obj;
169 }
170
171 static void
172 _cleanup_tmpf(Evas_Object *obj)
173 {
174    Evas_Object_Image *o;
175    
176    o = (Evas_Object_Image *)(obj->object_data);
177    if (!o->tmpf) return;
178 #ifdef __linux__
179 #else
180    unlink(o->tmpf);
181 #endif
182    if (o->tmpf_fd >= 0) close(o->tmpf_fd);
183    eina_stringshare_del(o->tmpf);
184    o->tmpf_fd = -1;
185    o->tmpf = NULL;
186 }
187
188 static void
189 _create_tmpf(Evas_Object *obj, void *data, int size, char *format __UNUSED__)
190 {
191    Evas_Object_Image *o;
192    char buf[4096];
193    void *dst;
194    int fd = -1;
195    
196    o = (Evas_Object_Image *)(obj->object_data);
197 #ifdef __linux__
198    snprintf(buf, sizeof(buf), "/dev/shm/.evas-tmpf-%i-%p-%i-XXXXXX", 
199             (int)getpid(), data, (int)size);
200    fd = mkstemp(buf);
201 #endif   
202    if (fd < 0)
203      {
204         snprintf(buf, sizeof(buf), "/tmp/.evas-tmpf-%i-%p-%i-XXXXXX", 
205                  (int)getpid(), data, (int)size);
206         fd = mkstemp(buf);
207      }
208    if (fd < 0) return;
209    if (ftruncate(fd, size) < 0)
210      {
211         unlink(buf);
212         close(fd);
213         return;
214      }
215    unlink(buf);
216    
217    eina_mmap_safety_enabled_set(EINA_TRUE);
218    
219    dst = mmap(NULL, size, 
220               PROT_READ | PROT_WRITE, 
221               MAP_SHARED, 
222               fd, 0);
223    if (dst == MAP_FAILED)
224      {
225         close(fd);
226         return;
227      }
228    o->tmpf_fd = fd;
229 #ifdef __linux__
230    snprintf(buf, sizeof(buf), "/proc/%li/fd/%i", (long)getpid(), fd);
231 #endif
232    o->tmpf = eina_stringshare_add(buf);
233    memcpy(dst, data, size);
234    munmap(dst, size);
235 }
236
237 EAPI void
238 evas_object_image_memfile_set(Evas_Object *obj, void *data, int size, char *format, char *key)
239 {
240    Evas_Object_Image *o;
241
242    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
243    return;
244    MAGIC_CHECK_END();
245    o = (Evas_Object_Image *)(obj->object_data);
246    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
247    return;
248    MAGIC_CHECK_END();
249    _cleanup_tmpf(obj);
250    evas_object_image_file_set(obj, NULL, NULL);
251    // invalidate the cache effectively
252    evas_object_image_alpha_set(obj, !o->cur.has_alpha);
253    evas_object_image_alpha_set(obj, !o->cur.has_alpha);
254
255    if ((size < 1) || (!data)) return;
256
257    _create_tmpf(obj, data, size, format);
258    evas_object_image_file_set(obj, o->tmpf, key);
259    if (!o->engine_data)
260      {
261         ERR("unable to load '%s' from memory", o->tmpf);
262         _cleanup_tmpf(obj);
263         return;
264      }
265 }
266
267 EAPI void
268 evas_object_image_file_set(Evas_Object *obj, const char *file, const char *key)
269 {
270    Evas_Object_Image *o;
271    Evas_Image_Load_Opts lo;
272
273    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
274    return;
275    MAGIC_CHECK_END();
276    o = (Evas_Object_Image *)(obj->object_data);
277    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
278    return;
279    MAGIC_CHECK_END();
280    if ((o->tmpf) && (file != o->tmpf)) _cleanup_tmpf(obj);
281    if ((o->cur.file) && (file) && (!strcmp(o->cur.file, file)))
282      {
283         if ((!o->cur.key) && (!key))
284           return;
285         if ((o->cur.key) && (key) && (!strcmp(o->cur.key, key)))
286           return;
287      }
288 /*
289  * WTF? why cancel a null image preload? this is just silly (tm)
290    if (!o->engine_data)
291      obj->layer->evas->engine.func->image_data_preload_cancel(obj->layer->evas->engine.data.output,
292                                                               o->engine_data,
293                                                               obj);
294  */
295    if (o->cur.source) _proxy_unset(obj);
296    if (o->cur.file) eina_stringshare_del(o->cur.file);
297    if (o->cur.key) eina_stringshare_del(o->cur.key);
298    if (file) o->cur.file = eina_stringshare_add(file);
299    else o->cur.file = NULL;
300    if (key) o->cur.key = eina_stringshare_add(key);
301    else o->cur.key = NULL;
302    o->prev.file = NULL;
303    o->prev.key = NULL;
304    if (o->engine_data)
305      {
306         if (o->preloading)
307           {
308              o->preloading = 0;
309              obj->layer->evas->engine.func->image_data_preload_cancel(obj->layer->evas->engine.data.output,
310                                                                       o->engine_data,
311                                                                       obj);
312           }
313         obj->layer->evas->engine.func->image_free(obj->layer->evas->engine.data.output,
314                                                   o->engine_data);
315      }
316    o->load_error = EVAS_LOAD_ERROR_NONE;
317    lo.scale_down_by = o->load_opts.scale_down_by;
318    lo.dpi = o->load_opts.dpi;
319    lo.w = o->load_opts.w;
320    lo.h = o->load_opts.h;
321    lo.region.x = o->load_opts.region.x;
322    lo.region.y = o->load_opts.region.y;
323    lo.region.w = o->load_opts.region.w;
324    lo.region.h = o->load_opts.region.h;
325    lo.orientation = o->load_opts.orientation;
326    o->engine_data = obj->layer->evas->engine.func->image_load(obj->layer->evas->engine.data.output,
327                                                               o->cur.file,
328                                                               o->cur.key,
329                                                               &o->load_error,
330                                                               &lo);
331    if (o->engine_data)
332      {
333         int w, h;
334         int stride;
335
336         obj->layer->evas->engine.func->image_size_get(obj->layer->evas->engine.data.output,
337                                                       o->engine_data, &w, &h);
338         if (obj->layer->evas->engine.func->image_stride_get)
339           obj->layer->evas->engine.func->image_stride_get(obj->layer->evas->engine.data.output,
340                                                           o->engine_data, &stride);
341         else
342           stride = w * 4;
343         o->cur.has_alpha = obj->layer->evas->engine.func->image_alpha_get(obj->layer->evas->engine.data.output,
344                                                                           o->engine_data);
345         o->cur.cspace = obj->layer->evas->engine.func->image_colorspace_get(obj->layer->evas->engine.data.output,
346                                                                             o->engine_data);
347         o->cur.image.w = w;
348         o->cur.image.h = h;
349         o->cur.image.stride = stride;
350      }
351    else
352      {
353         if (o->load_error == EVAS_LOAD_ERROR_NONE)
354           o->load_error = EVAS_LOAD_ERROR_GENERIC;
355         o->cur.has_alpha = 1;
356         o->cur.cspace = EVAS_COLORSPACE_ARGB8888;
357         o->cur.image.w = 0;
358         o->cur.image.h = 0;
359         o->cur.image.stride = 0;
360      }
361    o->changed = 1;
362    evas_object_change(obj);
363 }
364
365 EAPI void
366 evas_object_image_file_get(const Evas_Object *obj, const char **file, const char **key)
367 {
368    Evas_Object_Image *o;
369
370    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
371    if (file) *file = NULL;
372    if (key) *key = NULL;
373    return;
374    MAGIC_CHECK_END();
375    o = (Evas_Object_Image *)(obj->object_data);
376    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
377    if (file) *file = NULL;
378    if (key) *key = NULL;
379    return;
380    MAGIC_CHECK_END();
381    if (file) *file = o->cur.file;
382    if (key) *key = o->cur.key;
383 }
384
385 EAPI Eina_Bool
386 evas_object_image_source_set(Evas_Object *obj, Evas_Object *src)
387 {
388    Evas_Object_Image *o;
389
390    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
391    return EINA_FALSE;
392    MAGIC_CHECK_END();
393    o = obj->object_data;
394    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
395    return EINA_FALSE;
396    MAGIC_CHECK_END();
397
398    if (src == obj) return EINA_FALSE;
399    if (o->cur.source == src) return EINA_TRUE;
400
401    if (o->tmpf) _cleanup_tmpf(obj);
402    /* Kill the image if any */
403    if (o->cur.file || o->cur.key)
404       evas_object_image_file_set(obj, NULL, NULL);
405
406    if (o->cur.source)
407      {
408         _proxy_unset(obj);
409      }
410
411    if (src)
412      {
413         _proxy_set(obj, src);
414      }
415
416    return EINA_TRUE;
417 }
418
419
420 EAPI Evas_Object *
421 evas_object_image_source_get(Evas_Object *obj)
422 {
423    Evas_Object_Image *o;
424
425    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
426    return NULL;
427    MAGIC_CHECK_END();
428    o = obj->object_data;
429    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
430    return NULL;
431    MAGIC_CHECK_END();
432
433    return o->cur.source;
434 }
435
436 EAPI Eina_Bool
437 evas_object_image_source_unset(Evas_Object *obj)
438 {
439    return evas_object_image_source_set(obj, NULL);
440 }
441
442 EAPI void
443 evas_object_image_border_set(Evas_Object *obj, int l, int r, int t, int b)
444 {
445    Evas_Object_Image *o;
446
447    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
448    return;
449    MAGIC_CHECK_END();
450    o = (Evas_Object_Image *)(obj->object_data);
451    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
452    return;
453    MAGIC_CHECK_END();
454    if (l < 0) l = 0;
455    if (r < 0) r = 0;
456    if (t < 0) t = 0;
457    if (b < 0) b = 0;
458    if ((o->cur.border.l == l) &&
459        (o->cur.border.r == r) &&
460        (o->cur.border.t == t) &&
461        (o->cur.border.b == b)) return;
462    o->cur.border.l = l;
463    o->cur.border.r = r;
464    o->cur.border.t = t;
465    o->cur.border.b = b;
466    o->cur.opaque_valid = 0;
467    o->changed = 1;
468    evas_object_change(obj);
469 }
470
471 EAPI void
472 evas_object_image_border_get(const Evas_Object *obj, int *l, int *r, int *t, int *b)
473 {
474    Evas_Object_Image *o;
475
476    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
477    if (l) *l = 0;
478    if (r) *r = 0;
479    if (t) *t = 0;
480    if (b) *b = 0;
481    return;
482    MAGIC_CHECK_END();
483    o = (Evas_Object_Image *)(obj->object_data);
484    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
485    if (l) *l = 0;
486    if (r) *r = 0;
487    if (t) *t = 0;
488    if (b) *b = 0;
489    return;
490    MAGIC_CHECK_END();
491    if (l) *l = o->cur.border.l;
492    if (r) *r = o->cur.border.r;
493    if (t) *t = o->cur.border.t;
494    if (b) *b = o->cur.border.b;
495 }
496
497 EAPI void
498 evas_object_image_border_center_fill_set(Evas_Object *obj, Evas_Border_Fill_Mode fill)
499 {
500    Evas_Object_Image *o;
501
502    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
503    return;
504    MAGIC_CHECK_END();
505    o = (Evas_Object_Image *)(obj->object_data);
506    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
507    return;
508    MAGIC_CHECK_END();
509    if (fill == o->cur.border.fill) return;
510    o->cur.border.fill = fill;
511    o->changed = 1;
512    evas_object_change(obj);
513 }
514
515 EAPI Evas_Border_Fill_Mode
516 evas_object_image_border_center_fill_get(const Evas_Object *obj)
517 {
518    Evas_Object_Image *o;
519
520    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
521    return 0;
522    MAGIC_CHECK_END();
523    o = (Evas_Object_Image *)(obj->object_data);
524    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
525    return 0;
526    MAGIC_CHECK_END();
527    return o->cur.border.fill;
528 }
529
530 EAPI void
531 evas_object_image_filled_set(Evas_Object *obj, Eina_Bool setting)
532 {
533    Evas_Object_Image *o;
534
535    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
536    return;
537    MAGIC_CHECK_END();
538    o = (Evas_Object_Image *)(obj->object_data);
539    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
540    return;
541    MAGIC_CHECK_END();
542
543    setting = !!setting;
544    if (o->filled == setting) return;
545
546    o->filled = setting;
547    if (!o->filled)
548      evas_object_event_callback_del(obj, EVAS_CALLBACK_RESIZE, evas_object_image_filled_resize_listener);
549    else
550      {
551         Evas_Coord w, h;
552
553         evas_object_geometry_get(obj, NULL, NULL, &w, &h);
554         evas_object_image_fill_set(obj, 0, 0, w, h);
555
556         evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, evas_object_image_filled_resize_listener, NULL);
557      }
558 }
559
560 EAPI Eina_Bool
561 evas_object_image_filled_get(const Evas_Object *obj)
562 {
563    Evas_Object_Image *o;
564
565    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
566    return 0;
567    MAGIC_CHECK_END();
568    o = (Evas_Object_Image *)(obj->object_data);
569    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
570    return 0;
571    MAGIC_CHECK_END();
572
573    return o->filled;
574 }
575
576 EAPI void
577 evas_object_image_border_scale_set(Evas_Object *obj, double scale)
578 {
579    Evas_Object_Image *o;
580
581    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
582    return;
583    MAGIC_CHECK_END();
584    o = (Evas_Object_Image *)(obj->object_data);
585    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
586    return;
587    MAGIC_CHECK_END();
588    if (scale == o->cur.border.scale) return;
589    o->cur.border.scale = scale;
590    o->changed = 1;
591    evas_object_change(obj);
592 }
593
594 EAPI double
595 evas_object_image_border_scale_get(const Evas_Object *obj)
596 {
597    Evas_Object_Image *o;
598
599    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
600    return 1.0;
601    MAGIC_CHECK_END();
602    o = (Evas_Object_Image *)(obj->object_data);
603    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
604    return 1.0;
605    MAGIC_CHECK_END();
606    return o->cur.border.scale;
607 }
608
609 EAPI void
610 evas_object_image_fill_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
611 {
612    Evas_Object_Image *o;
613
614    if (w < 0) w = -w;
615    if (h < 0) h = -h;
616    if (w == 0) return;
617    if (h == 0) return;
618    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
619    return;
620    MAGIC_CHECK_END();
621    o = (Evas_Object_Image *)(obj->object_data);
622    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
623    return;
624    MAGIC_CHECK_END();
625    if ((o->cur.fill.x == x) &&
626        (o->cur.fill.y == y) &&
627        (o->cur.fill.w == w) &&
628        (o->cur.fill.h == h)) return;
629    o->cur.fill.x = x;
630    o->cur.fill.y = y;
631    o->cur.fill.w = w;
632    o->cur.fill.h = h;
633    o->cur.opaque_valid = 0;   
634    o->changed = 1;
635    evas_object_change(obj);
636 }
637
638 EAPI void
639 evas_object_image_fill_get(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
640 {
641    Evas_Object_Image *o;
642
643    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
644    if (x) *x = 0;
645    if (y) *y = 0;
646    if (w) *w = 0;
647    if (h) *h = 0;
648    return;
649    MAGIC_CHECK_END();
650    o = (Evas_Object_Image *)(obj->object_data);
651    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
652    if (x) *x = 0;
653    if (y) *y = 0;
654    if (w) *w = 0;
655    if (h) *h = 0;
656    return;
657    MAGIC_CHECK_END();
658    if (x) *x = o->cur.fill.x;
659    if (y) *y = o->cur.fill.y;
660    if (w) *w = o->cur.fill.w;
661    if (h) *h = o->cur.fill.h;
662 }
663
664
665 EAPI void
666 evas_object_image_fill_spread_set(Evas_Object *obj, Evas_Fill_Spread spread)
667 {
668    Evas_Object_Image *o;
669
670    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
671    return;
672    MAGIC_CHECK_END();
673    o = (Evas_Object_Image *)(obj->object_data);
674    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
675    return;
676    MAGIC_CHECK_END();
677    if (spread == (Evas_Fill_Spread)o->cur.spread) return;
678    o->cur.spread = spread;
679    o->changed = 1;
680    evas_object_change(obj);
681 }
682
683 EAPI Evas_Fill_Spread
684 evas_object_image_fill_spread_get(const Evas_Object *obj)
685 {
686    Evas_Object_Image *o;
687
688    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
689    return EVAS_TEXTURE_REPEAT;
690    MAGIC_CHECK_END();
691    o = (Evas_Object_Image *)(obj->object_data);
692    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
693    return EVAS_TEXTURE_REPEAT;
694    MAGIC_CHECK_END();
695    return (Evas_Fill_Spread)o->cur.spread;
696 }
697
698 EAPI void
699 evas_object_image_size_set(Evas_Object *obj, int w, int h)
700 {
701    Evas_Object_Image *o;
702    int stride = 0;
703
704    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
705    return;
706    MAGIC_CHECK_END();
707    o = (Evas_Object_Image *)(obj->object_data);
708    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
709    return;
710    MAGIC_CHECK_END();
711    if ((o->preloading) && (o->engine_data))
712      {
713         o->preloading = 0;
714         obj->layer->evas->engine.func->image_data_preload_cancel(obj->layer->evas->engine.data.output,
715                                                                  o->engine_data,
716                                                                  obj);
717      }
718    if (w < 1) w = 1;
719    if (h < 1) h = 1;
720    if (w > 32768) return;
721    if (h > 32768) return;
722    if ((w == o->cur.image.w) &&
723        (h == o->cur.image.h)) return;
724    if (o->tmpf) _cleanup_tmpf(obj);
725    o->cur.image.w = w;
726    o->cur.image.h = h;
727    if (o->engine_data)
728       o->engine_data = obj->layer->evas->engine.func->image_size_set(obj->layer->evas->engine.data.output,
729                                                                      o->engine_data,
730                                                                      w, h);
731    else
732       o->engine_data = obj->layer->evas->engine.func->image_new_from_copied_data
733       (obj->layer->evas->engine.data.output, w, h, NULL, o->cur.has_alpha,
734           o->cur.cspace);
735    
736    if (o->engine_data)
737      {
738         if (obj->layer->evas->engine.func->image_scale_hint_set)
739            obj->layer->evas->engine.func->image_scale_hint_set
740            (obj->layer->evas->engine.data.output,
741                o->engine_data, o->scale_hint);
742         if (obj->layer->evas->engine.func->image_content_hint_set)
743            obj->layer->evas->engine.func->image_content_hint_set
744            (obj->layer->evas->engine.data.output,
745                o->engine_data, o->content_hint);
746         if (obj->layer->evas->engine.func->image_stride_get)
747            obj->layer->evas->engine.func->image_stride_get
748            (obj->layer->evas->engine.data.output,
749                o->engine_data, &stride);
750         else
751            stride = w * 4;
752      }
753    else
754       stride = w * 4;
755    o->cur.image.stride = stride;
756
757 /* FIXME - in engine call above
758    if (o->engine_data)
759      o->engine_data = obj->layer->evas->engine.func->image_alpha_set(obj->layer->evas->engine.data.output,
760                                                                      o->engine_data,
761                                                                      o->cur.has_alpha);
762 */
763    EVAS_OBJECT_IMAGE_FREE_FILE_AND_KEY(o);
764    o->changed = 1;
765    evas_object_change(obj);
766 }
767
768 EAPI void
769 evas_object_image_size_get(const Evas_Object *obj, int *w, int *h)
770 {
771    Evas_Object_Image *o;
772
773    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
774    if (w) *w = 0;
775    if (h) *h = 0;
776    return;
777    MAGIC_CHECK_END();
778    o = (Evas_Object_Image *)(obj->object_data);
779    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
780    if (w) *w = 0;
781    if (h) *h = 0;
782    return;
783    MAGIC_CHECK_END();
784    if (w) *w = o->cur.image.w;
785    if (h) *h = o->cur.image.h;
786 }
787
788 EAPI int
789 evas_object_image_stride_get(const Evas_Object *obj)
790 {
791    Evas_Object_Image *o;
792
793    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
794    return 0;
795    MAGIC_CHECK_END();
796    o = (Evas_Object_Image *)(obj->object_data);
797    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
798    return 0;
799    MAGIC_CHECK_END();
800    return o->cur.image.stride;
801 }
802
803 EAPI Evas_Load_Error
804 evas_object_image_load_error_get(const Evas_Object *obj)
805 {
806    Evas_Object_Image *o;
807
808    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
809    return 0;
810    MAGIC_CHECK_END();
811    o = (Evas_Object_Image *)(obj->object_data);
812    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
813    return 0;
814    MAGIC_CHECK_END();
815    return o->load_error;
816 }
817
818 EAPI void *
819 evas_object_image_data_convert(Evas_Object *obj, Evas_Colorspace to_cspace)
820 {
821    Evas_Object_Image *o;
822    DATA32 *data;
823
824    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
825    return NULL;
826    MAGIC_CHECK_END();
827    o = (Evas_Object_Image *)(obj->object_data);
828    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
829    return NULL;
830    MAGIC_CHECK_END();
831    if ((o->preloading) && (o->engine_data))
832      {
833         o->preloading = 0;
834         obj->layer->evas->engine.func->image_data_preload_cancel(obj->layer->evas->engine.data.output,
835                                                                  o->engine_data,
836                                                                  obj);
837      }
838    if (!o->engine_data) return NULL;
839    if (!o->cur.cspace == to_cspace) return NULL;
840    data = NULL;
841    o->engine_data = obj->layer->evas->engine.func->image_data_get(obj->layer->evas->engine.data.output,
842                                                                   o->engine_data,
843                                                                   0,
844                                                                   &data,
845                                                                   &o->load_error);
846    return evas_object_image_data_convert_internal(o, data, to_cspace);
847 }
848
849 EAPI void
850 evas_object_image_data_set(Evas_Object *obj, void *data)
851 {
852    Evas_Object_Image *o;
853    void *p_data;
854
855    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
856    return;
857    MAGIC_CHECK_END();
858    o = (Evas_Object_Image *)(obj->object_data);
859    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
860    return;
861    MAGIC_CHECK_END();
862    if ((o->preloading) && (o->engine_data))
863      {
864         o->preloading = 0;
865         obj->layer->evas->engine.func->image_data_preload_cancel(obj->layer->evas->engine.data.output,
866                                                                  o->engine_data,
867                                                                  obj);
868      }
869 #ifdef EVAS_FRAME_QUEUING
870    if (o->engine_data)
871      evas_common_pipe_op_image_flush(o->engine_data);
872 #endif
873    p_data = o->engine_data;
874    if (o->tmpf) _cleanup_tmpf(obj);
875    if (data)
876      {
877         if (o->engine_data)
878           o->engine_data = obj->layer->evas->engine.func->image_data_put(obj->layer->evas->engine.data.output,
879                                                                          o->engine_data,
880                                                                          data);
881         else
882           o->engine_data = obj->layer->evas->engine.func->image_new_from_data(obj->layer->evas->engine.data.output,
883                                                                               o->cur.image.w,
884                                                                               o->cur.image.h,
885                                                                               data,
886                                                                               o->cur.has_alpha,
887                                                                               o->cur.cspace);
888         if (o->engine_data)
889           {
890              int stride = 0;
891              
892              if (obj->layer->evas->engine.func->image_scale_hint_set)
893                 obj->layer->evas->engine.func->image_scale_hint_set
894                 (obj->layer->evas->engine.data.output,
895                     o->engine_data, o->scale_hint);
896              if (obj->layer->evas->engine.func->image_content_hint_set)
897                 obj->layer->evas->engine.func->image_content_hint_set
898                 (obj->layer->evas->engine.data.output,
899                     o->engine_data, o->content_hint); 
900              if (obj->layer->evas->engine.func->image_stride_get)
901                 obj->layer->evas->engine.func->image_stride_get
902                 (obj->layer->evas->engine.data.output,
903                     o->engine_data, &stride);
904              else
905                 stride = o->cur.image.w * 4;
906              o->cur.image.stride = stride;
907          }
908      }
909    else
910      {
911         if (o->engine_data)
912           obj->layer->evas->engine.func->image_free(obj->layer->evas->engine.data.output,
913                                                     o->engine_data);
914         o->load_error = EVAS_LOAD_ERROR_NONE;
915         o->cur.image.w = 0;
916         o->cur.image.h = 0;
917         o->cur.image.stride = 0;
918         o->engine_data = NULL;
919      }
920 /* FIXME - in engine call above
921    if (o->engine_data)
922      o->engine_data = obj->layer->evas->engine.func->image_alpha_set(obj->layer->evas->engine.data.output,
923                                                                      o->engine_data,
924                                                                      o->cur.has_alpha);
925 */
926    if (o->pixels_checked_out > 0) o->pixels_checked_out--;
927    if (p_data != o->engine_data)
928      {
929         EVAS_OBJECT_IMAGE_FREE_FILE_AND_KEY(o);
930         o->pixels_checked_out = 0;
931      }
932    o->changed = 1;
933    evas_object_change(obj);
934 }
935
936 EAPI void *
937 evas_object_image_data_get(const Evas_Object *obj, Eina_Bool for_writing)
938 {
939    Evas_Object_Image *o;
940    DATA32 *data;
941
942    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
943    return NULL;
944    MAGIC_CHECK_END();
945    o = (Evas_Object_Image *)(obj->object_data);
946    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
947    return NULL;
948    MAGIC_CHECK_END();
949    if (!o->engine_data) return NULL;
950 #ifdef EVAS_FRAME_QUEUING
951    evas_common_pipe_op_image_flush(o->engine_data);
952 #endif
953
954    data = NULL;
955    if (obj->layer->evas->engine.func->image_scale_hint_set)
956       obj->layer->evas->engine.func->image_scale_hint_set
957       (obj->layer->evas->engine.data.output,
958           o->engine_data, o->scale_hint);
959    if (obj->layer->evas->engine.func->image_content_hint_set)
960       obj->layer->evas->engine.func->image_content_hint_set
961       (obj->layer->evas->engine.data.output,
962           o->engine_data, o->content_hint);
963    o->engine_data = obj->layer->evas->engine.func->image_data_get(obj->layer->evas->engine.data.output,
964                                                                   o->engine_data,
965                                                                   for_writing,
966                                                                   &data,
967                                                                   &o->load_error);
968    if (o->engine_data)
969      {
970         int stride = 0;
971
972         if (obj->layer->evas->engine.func->image_stride_get)
973            obj->layer->evas->engine.func->image_stride_get
974            (obj->layer->evas->engine.data.output,
975                o->engine_data, &stride);
976         else
977            stride = o->cur.image.w * 4;
978         o->cur.image.stride = stride;
979      }
980    o->pixels_checked_out++;
981    if (for_writing)
982      {
983         EVAS_OBJECT_IMAGE_FREE_FILE_AND_KEY(o);
984      }
985
986    return data;
987 }
988
989 EAPI void
990 evas_object_image_preload(Evas_Object *obj, Eina_Bool cancel)
991 {
992    Evas_Object_Image *o;
993
994    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
995    return ;
996    MAGIC_CHECK_END();
997    o = (Evas_Object_Image *)(obj->object_data);
998    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
999    return ;
1000    MAGIC_CHECK_END();
1001    if (!o->engine_data)
1002      {
1003         o->preloading = 1;
1004         evas_object_inform_call_image_preloaded(obj);
1005         return;
1006      }
1007    // FIXME: if already busy preloading, then dont request again until
1008    // preload done
1009    if (cancel)
1010      {
1011         if (o->preloading)
1012           {
1013              o->preloading = 0;
1014              obj->layer->evas->engine.func->image_data_preload_cancel(obj->layer->evas->engine.data.output,
1015                                                                       o->engine_data,
1016                                                                       obj);
1017           }
1018      }
1019    else
1020      {
1021         if (!o->preloading)
1022           {
1023              o->preloading = 1;
1024              obj->layer->evas->engine.func->image_data_preload_request(obj->layer->evas->engine.data.output,
1025                                                                        o->engine_data,
1026                                                                        obj);
1027           }
1028      }
1029 }
1030
1031 EAPI void
1032 evas_object_image_data_copy_set(Evas_Object *obj, void *data)
1033 {
1034    Evas_Object_Image *o;
1035
1036    if (!data) return;
1037    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1038    return;
1039    MAGIC_CHECK_END();
1040    o = (Evas_Object_Image *)(obj->object_data);
1041    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1042    return;
1043    MAGIC_CHECK_END();
1044    if ((o->preloading) && (o->engine_data))
1045      {
1046         o->preloading = 0;
1047         obj->layer->evas->engine.func->image_data_preload_cancel(obj->layer->evas->engine.data.output,
1048                                                                  o->engine_data,
1049                                                                  obj);
1050      }
1051    if ((o->cur.image.w <= 0) ||
1052        (o->cur.image.h <= 0)) return;
1053    if (o->tmpf) _cleanup_tmpf(obj);
1054    if (o->engine_data)
1055      obj->layer->evas->engine.func->image_free(obj->layer->evas->engine.data.output,
1056                                                o->engine_data);
1057    o->engine_data = obj->layer->evas->engine.func->image_new_from_copied_data(obj->layer->evas->engine.data.output,
1058                                                                               o->cur.image.w,
1059                                                                               o->cur.image.h,
1060                                                                               data,
1061                                                                               o->cur.has_alpha,
1062                                                                               o->cur.cspace);
1063    if (o->engine_data)
1064      {
1065         int stride = 0;
1066
1067         o->engine_data = obj->layer->evas->engine.func->image_alpha_set(obj->layer->evas->engine.data.output,
1068                                                                         o->engine_data,
1069                                                                         o->cur.has_alpha);
1070         if (obj->layer->evas->engine.func->image_scale_hint_set)
1071            obj->layer->evas->engine.func->image_scale_hint_set
1072            (obj->layer->evas->engine.data.output,
1073                o->engine_data, o->scale_hint);
1074         if (obj->layer->evas->engine.func->image_content_hint_set)
1075            obj->layer->evas->engine.func->image_content_hint_set
1076            (obj->layer->evas->engine.data.output,
1077                o->engine_data, o->content_hint);
1078         if (obj->layer->evas->engine.func->image_stride_get)
1079            obj->layer->evas->engine.func->image_stride_get
1080            (obj->layer->evas->engine.data.output,
1081                o->engine_data, &stride);
1082         else
1083            stride = o->cur.image.w * 4;
1084         o->cur.image.stride = stride;
1085      }
1086    o->pixels_checked_out = 0;
1087    EVAS_OBJECT_IMAGE_FREE_FILE_AND_KEY(o);
1088 }
1089
1090 EAPI void
1091 evas_object_image_data_update_add(Evas_Object *obj, int x, int y, int w, int h)
1092 {
1093    Evas_Object_Image *o;
1094    Eina_Rectangle *r;
1095
1096    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1097    return;
1098    MAGIC_CHECK_END();
1099    o = (Evas_Object_Image *)(obj->object_data);
1100    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1101    return;
1102    MAGIC_CHECK_END();
1103    RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, o->cur.image.w, o->cur.image.h);
1104    if ((w <= 0)  || (h <= 0)) return;
1105    NEW_RECT(r, x, y, w, h);
1106    if (r) o->pixel_updates = eina_list_append(o->pixel_updates, r);
1107    o->changed = 1;
1108    evas_object_change(obj);
1109 }
1110
1111 EAPI void
1112 evas_object_image_alpha_set(Evas_Object *obj, Eina_Bool has_alpha)
1113 {
1114    Evas_Object_Image *o;
1115
1116    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1117    return;
1118    MAGIC_CHECK_END();
1119    o = (Evas_Object_Image *)(obj->object_data);
1120    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1121    return;
1122    MAGIC_CHECK_END();
1123    if ((o->preloading) && (o->engine_data))
1124      {
1125         o->preloading = 0;
1126         obj->layer->evas->engine.func->image_data_preload_cancel(obj->layer->evas->engine.data.output,
1127                                                                  o->engine_data,
1128                                                                  obj);
1129      }
1130    if (((has_alpha) && (o->cur.has_alpha)) ||
1131        ((!has_alpha) && (!o->cur.has_alpha)))
1132      return;
1133    o->cur.has_alpha = has_alpha;
1134    if (o->engine_data)
1135      {
1136         int stride = 0;
1137
1138 #ifdef EVAS_FRAME_QUEUING
1139         evas_common_pipe_op_image_flush(o->engine_data);
1140 #endif
1141         o->engine_data = obj->layer->evas->engine.func->image_alpha_set(obj->layer->evas->engine.data.output,
1142                                                                      o->engine_data,
1143                                                                      o->cur.has_alpha);
1144         if (obj->layer->evas->engine.func->image_scale_hint_set)
1145            obj->layer->evas->engine.func->image_scale_hint_set
1146            (obj->layer->evas->engine.data.output,
1147                o->engine_data, o->scale_hint);
1148         if (obj->layer->evas->engine.func->image_content_hint_set)
1149            obj->layer->evas->engine.func->image_content_hint_set
1150            (obj->layer->evas->engine.data.output,
1151                o->engine_data, o->content_hint);
1152         if (obj->layer->evas->engine.func->image_stride_get)
1153            obj->layer->evas->engine.func->image_stride_get
1154            (obj->layer->evas->engine.data.output,
1155                o->engine_data, &stride);
1156         else
1157            stride = o->cur.image.w * 4;
1158         o->cur.image.stride = stride;
1159      }
1160    evas_object_image_data_update_add(obj, 0, 0, o->cur.image.w, o->cur.image.h);
1161    EVAS_OBJECT_IMAGE_FREE_FILE_AND_KEY(o);
1162 }
1163
1164
1165 EAPI Eina_Bool
1166 evas_object_image_alpha_get(const Evas_Object *obj)
1167 {
1168    Evas_Object_Image *o;
1169
1170    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1171    return 0;
1172    MAGIC_CHECK_END();
1173    o = (Evas_Object_Image *)(obj->object_data);
1174    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1175    return 0;
1176    MAGIC_CHECK_END();
1177    return o->cur.has_alpha;
1178 }
1179
1180 EAPI void
1181 evas_object_image_smooth_scale_set(Evas_Object *obj, Eina_Bool smooth_scale)
1182 {
1183    Evas_Object_Image *o;
1184
1185    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1186    return;
1187    MAGIC_CHECK_END();
1188    o = (Evas_Object_Image *)(obj->object_data);
1189    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1190    return;
1191    MAGIC_CHECK_END();
1192    if (((smooth_scale) && (o->cur.smooth_scale)) ||
1193        ((!smooth_scale) && (!o->cur.smooth_scale)))
1194      return;
1195    o->cur.smooth_scale = smooth_scale;
1196    o->changed = 1;
1197    evas_object_change(obj);
1198 }
1199
1200 EAPI Eina_Bool
1201 evas_object_image_smooth_scale_get(const Evas_Object *obj)
1202 {
1203    Evas_Object_Image *o;
1204
1205    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1206    return 0;
1207    MAGIC_CHECK_END();
1208    o = (Evas_Object_Image *)(obj->object_data);
1209    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1210    return 0;
1211    MAGIC_CHECK_END();
1212    return o->cur.smooth_scale;
1213 }
1214
1215 EAPI void
1216 evas_object_image_reload(Evas_Object *obj)
1217 {
1218    Evas_Object_Image *o;
1219
1220    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1221    return;
1222    MAGIC_CHECK_END();
1223    o = (Evas_Object_Image *)(obj->object_data);
1224    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1225    return;
1226    MAGIC_CHECK_END();
1227    if ((o->preloading) && (o->engine_data))
1228      {
1229         o->preloading = 0;
1230         obj->layer->evas->engine.func->image_data_preload_cancel(obj->layer->evas->engine.data.output,
1231                                                                  o->engine_data,
1232                                                                  obj);
1233      }
1234    if ((!o->cur.file) ||
1235        (o->pixels_checked_out > 0)) return;
1236    if (o->engine_data)
1237      o->engine_data = obj->layer->evas->engine.func->image_dirty_region(obj->layer->evas->engine.data.output, o->engine_data, 0, 0, o->cur.image.w, o->cur.image.h);
1238    evas_object_image_unload(obj, 1);
1239    evas_object_inform_call_image_unloaded(obj);
1240    evas_object_image_load(obj);
1241    o->prev.file = NULL;
1242    o->prev.key = NULL;
1243    o->changed = 1;
1244    evas_object_change(obj);
1245 }
1246
1247 EAPI Eina_Bool
1248 evas_object_image_save(const Evas_Object *obj, const char *file, const char *key, const char *flags)
1249 {
1250    Evas_Object_Image *o;
1251    DATA32 *data = NULL;
1252    int quality = 80, compress = 9, ok = 0;
1253    RGBA_Image *im;
1254
1255    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1256    return 0;
1257    MAGIC_CHECK_END();
1258    o = (Evas_Object_Image *)(obj->object_data);
1259    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1260    return 0;
1261    MAGIC_CHECK_END();
1262
1263    if (!o->engine_data) return 0;
1264    o->engine_data = obj->layer->evas->engine.func->image_data_get(obj->layer->evas->engine.data.output,
1265                                                                   o->engine_data,
1266                                                                   0,
1267                                                                   &data,
1268                                                                   &o->load_error);
1269    if (flags)
1270      {
1271         char *p, *pp;
1272         char *tflags;
1273
1274         tflags = alloca(strlen(flags) + 1);
1275         strcpy(tflags, flags);
1276         p = tflags;
1277         while (p)
1278           {
1279              pp = strchr(p, ' ');
1280              if (pp) *pp = 0;
1281              sscanf(p, "quality=%i", &quality);
1282              sscanf(p, "compress=%i", &compress);
1283              if (pp) p = pp + 1;
1284              else break;
1285           }
1286      }
1287    im = (RGBA_Image*) evas_cache_image_data(evas_common_image_cache_get(),
1288                                             o->cur.image.w,
1289                                             o->cur.image.h,
1290                                             data,
1291                                             o->cur.has_alpha,
1292                                             EVAS_COLORSPACE_ARGB8888);
1293    if (im)
1294      {
1295         if (o->cur.cspace == EVAS_COLORSPACE_ARGB8888)
1296           im->image.data = data;
1297         else
1298           im->image.data = evas_object_image_data_convert_internal(o,
1299                                                                    data,
1300                                                                    EVAS_COLORSPACE_ARGB8888);
1301         if (im->image.data)
1302           {
1303              ok = evas_common_save_image_to_file(im, file, key, quality, compress);
1304
1305              if (o->cur.cspace != EVAS_COLORSPACE_ARGB8888)
1306                free(im->image.data);
1307           }
1308
1309         evas_cache_image_drop(&im->cache_entry);
1310      }
1311    return ok;
1312 }
1313
1314 EAPI Eina_Bool
1315 evas_object_image_pixels_import(Evas_Object *obj, Evas_Pixel_Import_Source *pixels)
1316 {
1317    Evas_Object_Image *o;
1318
1319    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1320    return 0;
1321    MAGIC_CHECK_END();
1322    o = (Evas_Object_Image *)(obj->object_data);
1323    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1324    return 0;
1325    MAGIC_CHECK_END();
1326
1327    if ((o->preloading) && (o->engine_data))
1328      {
1329         o->preloading = 0;
1330         obj->layer->evas->engine.func->image_data_preload_cancel(obj->layer->evas->engine.data.output,
1331                                                                  o->engine_data,
1332                                                                  obj);
1333      }
1334    if ((pixels->w != o->cur.image.w) || (pixels->h != o->cur.image.h)) return 0;
1335    if (o->tmpf) _cleanup_tmpf(obj);
1336    switch (pixels->format)
1337      {
1338 #if 0
1339       case EVAS_PIXEL_FORMAT_ARGB32:
1340           {
1341              if (o->engine_data)
1342                {
1343                   DATA32 *image_pixels = NULL;
1344
1345                   o->engine_data =
1346                     obj->layer->evas->engine.func->image_data_get(obj->layer->evas->engine.data.output,
1347                                                                   o->engine_data,
1348                                                                   1,
1349                                                                   &image_pixels,
1350                                                                   &o->load_error);
1351 /* FIXME: need to actualyl support this */
1352 /*                memcpy(image_pixels, pixels->rows, o->cur.image.w * o->cur.image.h * 4);*/
1353                   if (o->engine_data)
1354                     o->engine_data =
1355                     obj->layer->evas->engine.func->image_data_put(obj->layer->evas->engine.data.output,
1356                                                                   o->engine_data,
1357                                                                   image_pixels);
1358                   if (o->engine_data)
1359                     o->engine_data =
1360                     obj->layer->evas->engine.func->image_alpha_set(obj->layer->evas->engine.data.output,
1361                                                                    o->engine_data,
1362                                                                    o->cur.has_alpha);
1363                   o->changed = 1;
1364                   evas_object_change(obj);
1365                }
1366           }
1367         break;
1368 #endif
1369 #ifdef BUILD_CONVERT_YUV
1370       case EVAS_PIXEL_FORMAT_YUV420P_601:
1371           {
1372              if (o->engine_data)
1373                {
1374                   DATA32 *image_pixels = NULL;
1375
1376                   o->engine_data =
1377                     obj->layer->evas->engine.func->image_data_get(obj->layer->evas->engine.data.output,
1378                                                                   o->engine_data,
1379                                                                   1,
1380                                                                   &image_pixels,
1381                                                                   &o->load_error);
1382                   if (image_pixels)
1383                     evas_common_convert_yuv_420p_601_rgba((DATA8 **) pixels->rows,
1384                                                           (DATA8 *) image_pixels,
1385                                                           o->cur.image.w,
1386                                                           o->cur.image.h);
1387                   if (o->engine_data)
1388                     o->engine_data =
1389                     obj->layer->evas->engine.func->image_data_put(obj->layer->evas->engine.data.output,
1390                                                                   o->engine_data,
1391                                                                   image_pixels);
1392                   if (o->engine_data)
1393                     o->engine_data =
1394                     obj->layer->evas->engine.func->image_alpha_set(obj->layer->evas->engine.data.output,
1395                                                                    o->engine_data,
1396                                                                    o->cur.has_alpha);
1397                   o->changed = 1;
1398                   evas_object_change(obj);
1399                }
1400           }
1401         break;
1402 #endif
1403       default:
1404         return 0;
1405         break;
1406      }
1407    return 1;
1408 }
1409
1410 EAPI void
1411 evas_object_image_pixels_get_callback_set(Evas_Object *obj, Evas_Object_Image_Pixels_Get_Cb func, void *data)
1412 {
1413    Evas_Object_Image *o;
1414
1415    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1416    return;
1417    MAGIC_CHECK_END();
1418    o = (Evas_Object_Image *)(obj->object_data);
1419    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1420    return;
1421    MAGIC_CHECK_END();
1422    o->func.get_pixels = func;
1423    o->func.get_pixels_data = data;
1424 }
1425
1426 EAPI void
1427 evas_object_image_pixels_dirty_set(Evas_Object *obj, Eina_Bool dirty)
1428 {
1429    Evas_Object_Image *o;
1430
1431    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1432    return;
1433    MAGIC_CHECK_END();
1434    o = (Evas_Object_Image *)(obj->object_data);
1435    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1436    return;
1437    MAGIC_CHECK_END();
1438    if (dirty) o->dirty_pixels = 1;
1439    else o->dirty_pixels = 0;
1440    o->changed = 1;
1441    evas_object_change(obj);
1442 }
1443
1444 EAPI Eina_Bool
1445 evas_object_image_pixels_dirty_get(const Evas_Object *obj)
1446 {
1447    Evas_Object_Image *o;
1448
1449    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1450    return 0;
1451    MAGIC_CHECK_END();
1452    o = (Evas_Object_Image *)(obj->object_data);
1453    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1454    return 0;
1455    MAGIC_CHECK_END();
1456    if (o->dirty_pixels) return 1;
1457    return 0;
1458 }
1459
1460 EAPI void
1461 evas_object_image_load_dpi_set(Evas_Object *obj, double dpi)
1462 {
1463    Evas_Object_Image *o;
1464
1465    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1466    return;
1467    MAGIC_CHECK_END();
1468    o = (Evas_Object_Image *)(obj->object_data);
1469    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1470    return;
1471    MAGIC_CHECK_END();
1472    if (dpi == o->load_opts.dpi) return;
1473    o->load_opts.dpi = dpi;
1474    if (o->cur.file)
1475      {
1476         evas_object_image_unload(obj, 0);
1477         evas_object_inform_call_image_unloaded(obj);
1478         evas_object_image_load(obj);
1479         o->changed = 1;
1480         evas_object_change(obj);
1481      }
1482 }
1483
1484 EAPI double
1485 evas_object_image_load_dpi_get(const Evas_Object *obj)
1486 {
1487    Evas_Object_Image *o;
1488
1489    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1490    return 0.0;
1491    MAGIC_CHECK_END();
1492    o = (Evas_Object_Image *)(obj->object_data);
1493    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1494    return 0.0;
1495    MAGIC_CHECK_END();
1496    return o->load_opts.dpi;
1497 }
1498
1499 EAPI void
1500 evas_object_image_load_size_set(Evas_Object *obj, int w, int h)
1501 {
1502    Evas_Object_Image *o;
1503
1504    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1505    return;
1506    MAGIC_CHECK_END();
1507    o = (Evas_Object_Image *)(obj->object_data);
1508    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1509    return;
1510    MAGIC_CHECK_END();
1511    if ((o->load_opts.w == w) && (o->load_opts.h == h)) return;
1512    o->load_opts.w = w;
1513    o->load_opts.h = h;
1514    if (o->cur.file)
1515      {
1516         evas_object_image_unload(obj, 0);
1517         evas_object_inform_call_image_unloaded(obj);
1518         evas_object_image_load(obj);
1519         o->changed = 1;
1520         evas_object_change(obj);
1521      }
1522 }
1523
1524 EAPI void
1525 evas_object_image_load_size_get(const Evas_Object *obj, int *w, int *h)
1526 {
1527    Evas_Object_Image *o;
1528
1529    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1530    return;
1531    MAGIC_CHECK_END();
1532    o = (Evas_Object_Image *)(obj->object_data);
1533    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1534    return;
1535    MAGIC_CHECK_END();
1536    if (w) *w = o->load_opts.w;
1537    if (h) *h = o->load_opts.h;
1538 }
1539
1540 EAPI void
1541 evas_object_image_load_scale_down_set(Evas_Object *obj, int scale_down)
1542 {
1543    Evas_Object_Image *o;
1544
1545    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1546    return;
1547    MAGIC_CHECK_END();
1548    o = (Evas_Object_Image *)(obj->object_data);
1549    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1550    return;
1551    MAGIC_CHECK_END();
1552    if (o->load_opts.scale_down_by == scale_down) return;
1553    o->load_opts.scale_down_by = scale_down;
1554    if (o->cur.file)
1555      {
1556         evas_object_image_unload(obj, 0);
1557         evas_object_inform_call_image_unloaded(obj);
1558         evas_object_image_load(obj);
1559         o->changed = 1;
1560         evas_object_change(obj);
1561      }
1562 }
1563
1564 EAPI int
1565 evas_object_image_load_scale_down_get(const Evas_Object *obj)
1566 {
1567    Evas_Object_Image *o;
1568
1569    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1570    return 0;
1571    MAGIC_CHECK_END();
1572    o = (Evas_Object_Image *)(obj->object_data);
1573    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1574    return 0;
1575    MAGIC_CHECK_END();
1576    return o->load_opts.scale_down_by;
1577 }
1578
1579 EAPI void
1580 evas_object_image_load_region_set(Evas_Object *obj, int x, int y, int w, int h)
1581 {
1582    Evas_Object_Image *o;
1583
1584    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1585    return;
1586    MAGIC_CHECK_END();
1587    o = (Evas_Object_Image *)(obj->object_data);
1588    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1589    return;
1590    MAGIC_CHECK_END();
1591    if ((o->load_opts.region.x == x) && (o->load_opts.region.y == y) &&
1592        (o->load_opts.region.w == w) && (o->load_opts.region.h == h)) return;
1593    o->load_opts.region.x = x;
1594    o->load_opts.region.y = y;
1595    o->load_opts.region.w = w;
1596    o->load_opts.region.h = h;
1597    if (o->cur.file)
1598      {
1599         evas_object_image_unload(obj, 0);
1600         evas_object_inform_call_image_unloaded(obj);
1601         evas_object_image_load(obj);
1602         o->changed = 1;
1603         evas_object_change(obj);
1604      }
1605 }
1606
1607 EAPI void
1608 evas_object_image_load_region_get(const Evas_Object *obj, int *x, int *y, int *w, int *h)
1609 {
1610    Evas_Object_Image *o;
1611
1612    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1613    return;
1614    MAGIC_CHECK_END();
1615    o = (Evas_Object_Image *)(obj->object_data);
1616    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1617    return;
1618    MAGIC_CHECK_END();
1619    if (x) *x = o->load_opts.region.x;
1620    if (y) *y = o->load_opts.region.y;
1621    if (w) *w = o->load_opts.region.w;
1622    if (h) *h = o->load_opts.region.h;
1623 }
1624
1625 EAPI void
1626 evas_object_image_load_orientation_set(Evas_Object *obj, Eina_Bool enable)
1627 {
1628    Evas_Object_Image *o;
1629
1630    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1631    return;
1632    MAGIC_CHECK_END();
1633    o = (Evas_Object_Image *)(obj->object_data);
1634    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1635    return;
1636    MAGIC_CHECK_END();
1637    o->load_opts.orientation = !!enable;
1638 }
1639
1640 EAPI Eina_Bool
1641 evas_object_image_load_orientation_get(const Evas_Object *obj)
1642 {
1643    Evas_Object_Image *o;
1644
1645    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1646    return EINA_FALSE;
1647    MAGIC_CHECK_END();
1648    o = (Evas_Object_Image *)(obj->object_data);
1649    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1650    return EINA_FALSE;
1651    MAGIC_CHECK_END();
1652    return o->load_opts.orientation;
1653 }
1654
1655 EAPI void
1656 evas_object_image_colorspace_set(Evas_Object *obj, Evas_Colorspace cspace)
1657 {
1658    Evas_Object_Image *o;
1659
1660    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1661    return;
1662    MAGIC_CHECK_END();
1663    o = (Evas_Object_Image *)(obj->object_data);
1664    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1665    return;
1666    MAGIC_CHECK_END();
1667
1668    if ((o->preloading) && (o->engine_data))
1669      {
1670         o->preloading = 0;
1671         obj->layer->evas->engine.func->image_data_preload_cancel(obj->layer->evas->engine.data.output,
1672                                                                  o->engine_data,
1673                                                                  obj);
1674      }
1675    if (o->tmpf) _cleanup_tmpf(obj);
1676 #ifdef EVAS_FRAME_QUEUING
1677    if ((Evas_Colorspace)o->cur.cspace != cspace)
1678      {
1679         if (o->engine_data)
1680           evas_common_pipe_op_image_flush(o->engine_data);
1681      }
1682 #endif
1683
1684    o->cur.cspace = cspace;
1685    if (o->engine_data)
1686      obj->layer->evas->engine.func->image_colorspace_set(obj->layer->evas->engine.data.output,
1687                                                          o->engine_data,
1688                                                          cspace);
1689 }
1690
1691 EAPI Evas_Colorspace
1692 evas_object_image_colorspace_get(const Evas_Object *obj)
1693 {
1694    Evas_Object_Image *o;
1695
1696    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1697    return EVAS_COLORSPACE_ARGB8888;
1698    MAGIC_CHECK_END();
1699    o = (Evas_Object_Image *)(obj->object_data);
1700    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1701    return EVAS_COLORSPACE_ARGB8888;
1702    MAGIC_CHECK_END();
1703    return o->cur.cspace;
1704 }
1705
1706 EAPI void
1707 evas_object_image_native_surface_set(Evas_Object *obj, Evas_Native_Surface *surf)
1708 {
1709    Evas_Object_Image *o;
1710
1711    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1712    return;
1713    MAGIC_CHECK_END();
1714    o = (Evas_Object_Image *)(obj->object_data);
1715    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1716    return;
1717    MAGIC_CHECK_END();
1718    if ((o->preloading) && (o->engine_data))
1719      {
1720         o->preloading = 0;
1721         obj->layer->evas->engine.func->image_data_preload_cancel(obj->layer->evas->engine.data.output,
1722                                                                  o->engine_data,
1723                                                                  obj);
1724      }
1725    if (o->tmpf) _cleanup_tmpf(obj);
1726    if (o->cur.source) _proxy_unset(obj);
1727    if (!obj->layer->evas->engine.func->image_native_set) return;
1728    if ((surf) &&
1729        ((surf->version < 2) ||
1730         (surf->version > EVAS_NATIVE_SURFACE_VERSION))) return;
1731    o->engine_data = 
1732       obj->layer->evas->engine.func->image_native_set(obj->layer->evas->engine.data.output,
1733                                                       o->engine_data,
1734                                                       surf);
1735 }
1736
1737 EAPI Evas_Native_Surface *
1738 evas_object_image_native_surface_get(const Evas_Object *obj)
1739 {
1740    Evas_Object_Image *o;
1741
1742    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1743    return NULL;
1744    MAGIC_CHECK_END();
1745    o = (Evas_Object_Image *)(obj->object_data);
1746    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1747    return NULL;
1748    MAGIC_CHECK_END();
1749    if (!obj->layer->evas->engine.func->image_native_get) return NULL;
1750    return obj->layer->evas->engine.func->image_native_get(obj->layer->evas->engine.data.output,
1751                                                           o->engine_data);
1752 }
1753
1754 EAPI void
1755 evas_object_image_scale_hint_set(Evas_Object *obj, Evas_Image_Scale_Hint hint)
1756 {
1757    Evas_Object_Image *o;
1758
1759    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1760    return;
1761    MAGIC_CHECK_END();
1762    o = (Evas_Object_Image *)(obj->object_data);
1763    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1764    return;
1765    MAGIC_CHECK_END();
1766    if (o->scale_hint == hint) return;
1767 #ifdef EVAS_FRAME_QUEUING
1768    if (o->engine_data)
1769       evas_common_pipe_op_image_flush(o->engine_data);
1770 #endif
1771    o->scale_hint = hint;
1772    if (o->engine_data)
1773      {
1774         int stride = 0;
1775         
1776         if (obj->layer->evas->engine.func->image_scale_hint_set)
1777            obj->layer->evas->engine.func->image_scale_hint_set
1778            (obj->layer->evas->engine.data.output,
1779                o->engine_data, o->scale_hint);
1780         if (obj->layer->evas->engine.func->image_stride_get)
1781            obj->layer->evas->engine.func->image_stride_get
1782            (obj->layer->evas->engine.data.output,
1783                o->engine_data, &stride);
1784         else
1785            stride = o->cur.image.w * 4;
1786         o->cur.image.stride = stride;
1787      }
1788 }
1789
1790 EAPI Evas_Image_Scale_Hint
1791 evas_object_image_scale_hint_get(const Evas_Object *obj)
1792 {
1793    Evas_Object_Image *o;
1794
1795    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1796    return EVAS_IMAGE_SCALE_HINT_NONE;
1797    MAGIC_CHECK_END();
1798    o = (Evas_Object_Image *)(obj->object_data);
1799    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1800    return EVAS_IMAGE_SCALE_HINT_NONE;
1801    MAGIC_CHECK_END();
1802    return o->scale_hint;
1803 }
1804
1805 EAPI void
1806 evas_object_image_content_hint_set(Evas_Object *obj, Evas_Image_Content_Hint hint)
1807 {
1808    Evas_Object_Image *o;
1809
1810    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1811    return;
1812    MAGIC_CHECK_END();
1813    o = (Evas_Object_Image *)(obj->object_data);
1814    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1815    return;
1816    MAGIC_CHECK_END();
1817    if (o->content_hint == hint) return;
1818 #ifdef EVAS_FRAME_QUEUING
1819    if (o->engine_data)
1820       evas_common_pipe_op_image_flush(o->engine_data);
1821 #endif
1822    o->content_hint = hint;
1823    if (o->engine_data)
1824      {
1825         int stride = 0;
1826         
1827         if (obj->layer->evas->engine.func->image_content_hint_set)
1828            obj->layer->evas->engine.func->image_content_hint_set
1829            (obj->layer->evas->engine.data.output,
1830                o->engine_data, o->content_hint);
1831         if (obj->layer->evas->engine.func->image_stride_get)
1832            obj->layer->evas->engine.func->image_stride_get
1833            (obj->layer->evas->engine.data.output,
1834                o->engine_data, &stride);
1835         else
1836            stride = o->cur.image.w * 4;
1837         o->cur.image.stride = stride;
1838      }
1839 }
1840
1841 EAPI void
1842 evas_object_image_alpha_mask_set(Evas_Object *obj, Eina_Bool ismask)
1843 {
1844    Evas_Object_Image *o;
1845
1846    if (!ismask) return;
1847
1848    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1849    return;
1850    MAGIC_CHECK_END();
1851    o = (Evas_Object_Image *)(obj->object_data);
1852    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1853    return;
1854    MAGIC_CHECK_END();
1855
1856    /* Convert to A8 if not already */
1857
1858    /* done */
1859
1860 }
1861
1862 #define FRAME_MAX 1024
1863 EAPI Evas_Image_Content_Hint
1864 evas_object_image_content_hint_get(const Evas_Object *obj)
1865 {
1866    Evas_Object_Image *o;
1867
1868    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1869    return EVAS_IMAGE_CONTENT_HINT_NONE;
1870    MAGIC_CHECK_END();
1871    o = (Evas_Object_Image *)(obj->object_data);
1872    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1873    return EVAS_IMAGE_CONTENT_HINT_NONE;
1874    MAGIC_CHECK_END();
1875    return o->content_hint;
1876 }
1877
1878 /* animated feature */
1879 EAPI Eina_Bool
1880 evas_object_image_animated_get(const Evas_Object *obj)
1881 {
1882    Evas_Object_Image *o;
1883
1884    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1885    return EINA_FALSE;
1886    MAGIC_CHECK_END();
1887    o = (Evas_Object_Image *)(obj->object_data);
1888    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1889    return EINA_FALSE;
1890    MAGIC_CHECK_END();
1891
1892    if (obj->layer->evas->engine.func->image_animated_get)
1893      return obj->layer->evas->engine.func->image_animated_get(obj->layer->evas->engine.data.output, o->engine_data);
1894    return EINA_FALSE;
1895 }
1896
1897 EAPI int
1898 evas_object_image_animated_frame_count_get(const Evas_Object *obj)
1899 {
1900    Evas_Object_Image *o;
1901
1902    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1903    return -1;
1904    MAGIC_CHECK_END();
1905    o = (Evas_Object_Image *)(obj->object_data);
1906    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1907    return -1;
1908    MAGIC_CHECK_END();
1909
1910    if (!evas_object_image_animated_get(obj)) return -1;
1911    if (obj->layer->evas->engine.func->image_animated_frame_count_get)
1912      return obj->layer->evas->engine.func->image_animated_frame_count_get(obj->layer->evas->engine.data.output, o->engine_data);
1913    return -1;
1914 }
1915
1916 EAPI Evas_Image_Animated_Loop_Hint
1917 evas_object_image_animated_loop_type_get(const Evas_Object *obj)
1918 {
1919    Evas_Object_Image *o;
1920
1921    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1922    return EVAS_IMAGE_ANIMATED_HINT_NONE;
1923    MAGIC_CHECK_END();
1924    o = (Evas_Object_Image *)(obj->object_data);
1925    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1926    return EVAS_IMAGE_ANIMATED_HINT_NONE;
1927    MAGIC_CHECK_END();
1928
1929    if (!evas_object_image_animated_get(obj)) return EVAS_IMAGE_ANIMATED_HINT_NONE;
1930
1931    if (obj->layer->evas->engine.func->image_animated_loop_type_get)
1932      return obj->layer->evas->engine.func->image_animated_loop_type_get(obj->layer->evas->engine.data.output, o->engine_data);
1933    return EVAS_IMAGE_ANIMATED_HINT_NONE;
1934 }
1935
1936 EAPI int
1937 evas_object_image_animated_loop_count_get(const Evas_Object *obj)
1938 {
1939    Evas_Object_Image *o;
1940
1941    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1942    return -1;
1943    MAGIC_CHECK_END();
1944    o = (Evas_Object_Image *)(obj->object_data);
1945    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1946    return -1;
1947    MAGIC_CHECK_END();
1948
1949    if (!evas_object_image_animated_get(obj)) return -1;
1950
1951    if (obj->layer->evas->engine.func->image_animated_loop_count_get)
1952      return obj->layer->evas->engine.func->image_animated_loop_count_get(obj->layer->evas->engine.data.output, o->engine_data);
1953    return -1;
1954 }
1955
1956 EAPI double
1957 evas_object_image_animated_frame_duration_get(const Evas_Object *obj, int start_frame, int frame_num)
1958 {
1959    Evas_Object_Image *o;
1960    int frame_count = 0;
1961
1962    if (start_frame < 1) return -1;
1963    if (frame_num < 0) return -1;
1964
1965    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1966    return -1;
1967    MAGIC_CHECK_END();
1968    o = (Evas_Object_Image *)(obj->object_data);
1969    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1970    return -1;
1971    MAGIC_CHECK_END();
1972
1973    if (!evas_object_image_animated_get(obj)) return -1;
1974
1975    if (!obj->layer->evas->engine.func->image_animated_frame_count_get) return -1;
1976
1977    frame_count = obj->layer->evas->engine.func->image_animated_frame_count_get(obj->layer->evas->engine.data.output, o->engine_data);
1978
1979    if ((start_frame + frame_num) > frame_count) return -1;
1980    if (obj->layer->evas->engine.func->image_animated_frame_duration_get)
1981      return obj->layer->evas->engine.func->image_animated_frame_duration_get(obj->layer->evas->engine.data.output, o->engine_data, start_frame, frame_num);
1982    return -1;
1983 }
1984
1985 EAPI void
1986 evas_object_image_animated_frame_set(Evas_Object *obj, int frame_index)
1987 {
1988    Evas_Object_Image *o;
1989    int frame_count = 0;
1990
1991    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1992    return;
1993    MAGIC_CHECK_END();
1994    o = (Evas_Object_Image *)(obj->object_data);
1995    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1996    return;
1997    MAGIC_CHECK_END();
1998
1999    if (!o->cur.file) return;
2000    if (o->cur.frame == frame_index) return;
2001
2002    if (!evas_object_image_animated_get(obj)) return;
2003
2004    frame_count = evas_object_image_animated_frame_count_get(obj);
2005
2006    /* limit the size of frame to FRAME_MAX */
2007    if ((frame_count > FRAME_MAX) || (frame_count < 0) || (frame_index > frame_count))
2008      return;
2009
2010    if (!obj->layer->evas->engine.func->image_animated_frame_set) return;
2011    if (!obj->layer->evas->engine.func->image_animated_frame_set(obj->layer->evas->engine.data.output, o->engine_data, frame_index))
2012      return;
2013
2014    o->prev.frame = o->cur.frame;
2015    o->cur.frame = frame_index;
2016
2017    o->changed = 1;
2018    evas_object_change(obj);
2019
2020 }
2021
2022 EAPI void
2023 evas_image_cache_flush(Evas *e)
2024 {
2025    MAGIC_CHECK(e, Evas, MAGIC_EVAS);
2026    return;
2027    MAGIC_CHECK_END();
2028
2029    e->engine.func->image_cache_flush(e->engine.data.output);
2030 }
2031
2032 EAPI void
2033 evas_image_cache_reload(Evas *e)
2034 {
2035    Evas_Layer *layer;
2036
2037    MAGIC_CHECK(e, Evas, MAGIC_EVAS);
2038    return;
2039    MAGIC_CHECK_END();
2040
2041    evas_image_cache_flush(e);
2042    EINA_INLIST_FOREACH(e->layers, layer)
2043      {
2044         Evas_Object *obj;
2045
2046         EINA_INLIST_FOREACH(layer->objects, obj)
2047           {
2048              Evas_Object_Image *o;
2049
2050              o = (Evas_Object_Image *)(obj->object_data);
2051              if (o->magic == MAGIC_OBJ_IMAGE)
2052                {
2053                   evas_object_image_unload(obj, 1);
2054                   evas_object_inform_call_image_unloaded(obj);
2055                }
2056           }
2057      }
2058    evas_image_cache_flush(e);
2059    EINA_INLIST_FOREACH(e->layers, layer)
2060      {
2061         Evas_Object *obj;
2062
2063         EINA_INLIST_FOREACH(layer->objects, obj)
2064           {
2065              Evas_Object_Image *o;
2066
2067              o = (Evas_Object_Image *)(obj->object_data);
2068              if (o->magic == MAGIC_OBJ_IMAGE)
2069                {
2070                   evas_object_image_load(obj);
2071                   o->changed = 1;
2072                   evas_object_change(obj);
2073                }
2074           }
2075      }
2076    evas_image_cache_flush(e);
2077 }
2078
2079 EAPI void
2080 evas_image_cache_set(Evas *e, int size)
2081 {
2082    MAGIC_CHECK(e, Evas, MAGIC_EVAS);
2083    return;
2084    MAGIC_CHECK_END();
2085
2086    if (size < 0) size = 0;
2087    e->engine.func->image_cache_set(e->engine.data.output, size);
2088 }
2089
2090 EAPI int
2091 evas_image_cache_get(const Evas *e)
2092 {
2093    MAGIC_CHECK(e, Evas, MAGIC_EVAS);
2094    return 0;
2095    MAGIC_CHECK_END();
2096
2097    return e->engine.func->image_cache_get(e->engine.data.output);
2098 }
2099
2100 /* all nice and private */
2101 static void
2102 _proxy_unset(Evas_Object *proxy)
2103 {
2104    Evas_Object_Image *o;
2105
2106    o = proxy->object_data;
2107    if (!o->cur.source) return;
2108
2109    o->cur.source->proxy.proxies = eina_list_remove(o->cur.source->proxy.proxies, proxy);
2110
2111    o->cur.source = NULL;
2112    if (o->cur.defmap)
2113      {
2114         evas_map_free(o->cur.defmap);
2115         o->cur.defmap = NULL;
2116      }
2117 }
2118
2119
2120 static void
2121 _proxy_set(Evas_Object *proxy, Evas_Object *src)
2122 {
2123    Evas_Object_Image *o;
2124
2125    o = proxy->object_data;
2126
2127    evas_object_image_file_set(proxy, NULL, NULL);
2128
2129    o->cur.source = src;
2130
2131    src->proxy.proxies = eina_list_append(src->proxy.proxies, proxy);
2132    src->proxy.redraw = EINA_TRUE;
2133 }
2134
2135 /* Some moron just set a proxy on a proxy.
2136  * Give them some pixels.  A random color
2137  */
2138 static void
2139 _proxy_error(Evas_Object *proxy, void *context, void *output, void *surface,
2140              int x, int y)
2141 {
2142    Evas_Func *func;
2143    int r = rand() % 255;
2144    int g = rand() % 255;
2145    int b = rand() % 255;
2146    
2147    /* XXX: Eina log error or something I'm sure
2148     * If it bugs you, just fix it.  Don't tell me */
2149    if (VERBOSE_PROXY_ERROR) printf("Err: Argh! Recursive proxies.\n");
2150    
2151    func = proxy->layer->evas->engine.func;
2152    func->context_color_set(output, context, r, g, b, 255);
2153    func->context_multiplier_unset(output, context);
2154    func->context_render_op_set(output, context, proxy->cur.render_op);
2155    func->rectangle_draw(output, context, surface, proxy->cur.geometry.x + x,
2156                         proxy->cur.geometry.y + y,
2157                         proxy->cur.geometry.w,
2158                         proxy->cur.geometry.h);
2159    return;
2160 }
2161
2162 /*
2163 static void
2164 _proxy_subrender_recurse(Evas_Object *obj, Evas_Object *clip, void *output, void *surface, void *ctx, int x, int y)
2165 {
2166    Evas_Object *obj2;
2167    Evas *e = obj->layer->evas;
2168    
2169    if (obj->clip.clipees) return;
2170    if (!obj->cur.visible) return;
2171    if ((!clip) || (clip != obj->cur.clipper))
2172      {
2173         if (!obj->cur.cache.clip.visible) return;
2174         if ((obj->cur.cache.clip.a == 0) &&
2175             (obj->cur.render_op == EVAS_RENDER_BLEND)) return;
2176      }
2177    if ((obj->func->is_visible) && (!obj->func->is_visible(obj))) return;
2178    
2179    if (!obj->pre_render_done)
2180       obj->func->render_pre(obj);
2181    ctx = e->engine.func->context_new(output);
2182    if (obj->smart.smart)
2183      {
2184         EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(obj), obj2)
2185           {
2186              _proxy_subrender_recurse(obj2, clip, output, surface, ctx, x, y);
2187           }
2188      }
2189    else
2190      {
2191         obj->func->render(obj, output, ctx, surface, x, y);
2192      }
2193    e->engine.func->context_free(output, ctx);
2194 }
2195 */
2196
2197 /**
2198  * Render the source object when a proxy is set.
2199  *
2200  * Used to force a draw if necessary, else just makes sures it's available.
2201  */
2202 static void
2203 _proxy_subrender(Evas *e, Evas_Object *source)
2204 {
2205    void *ctx;
2206 /*   Evas_Object *obj2, *clip;*/
2207    int w, h;
2208
2209    if (!source) return;
2210
2211    w = source->cur.geometry.w;
2212    h = source->cur.geometry.h;
2213
2214    source->proxy.redraw = EINA_FALSE;
2215
2216    /* We need to redraw surface then */
2217    if ((source->proxy.surface) && 
2218        ((source->proxy.w != w) || (source->proxy.h != h)))
2219      {
2220         e->engine.func->image_map_surface_free(e->engine.data.output,
2221                                                source->proxy.surface);
2222         source->proxy.surface = NULL;
2223      }
2224    
2225    /* FIXME: Hardcoded alpha 'on' */
2226    /* FIXME (cont): Should see if the object has alpha */
2227    if (!source->proxy.surface)
2228      {
2229         source->proxy.surface = e->engine.func->image_map_surface_new
2230            (e->engine.data.output, w, h, 1);
2231         source->proxy.w = w;
2232         source->proxy.h = h;
2233      }
2234
2235    ctx = e->engine.func->context_new(e->engine.data.output);
2236    e->engine.func->context_color_set(e->engine.data.output, ctx, 0, 0, 0, 0);
2237    e->engine.func->context_render_op_set(e->engine.data.output, ctx, EVAS_RENDER_COPY);
2238    e->engine.func->rectangle_draw(e->engine.data.output, ctx,
2239                                   source->proxy.surface, 0, 0, w, h);
2240    e->engine.func->context_free(e->engine.data.output, ctx);
2241    
2242    ctx = e->engine.func->context_new(e->engine.data.output);
2243    evas_render_mapped(e, source, ctx, source->proxy.surface,
2244                       -source->cur.geometry.x,
2245                       -source->cur.geometry.y,
2246                       1, 0, 0, e->output.w, e->output.h);
2247    e->engine.func->context_free(e->engine.data.output, ctx);
2248    source->proxy.surface = e->engine.func->image_dirty_region
2249       (e->engine.data.output, source->proxy.surface, 0, 0, w, h);
2250 /*   
2251    ctx = e->engine.func->context_new(e->engine.data.output);
2252    if (source->smart.smart)
2253      {
2254         clip = evas_object_smart_clipped_clipper_get(source);
2255         EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(source), obj2)
2256           {
2257              _proxy_subrender_recurse(obj2, clip, e->engine.data.output,
2258                                       source->proxy.surface,
2259                                       ctx,
2260                                       -source->cur.geometry.x,
2261                                       -source->cur.geometry.y);
2262           }
2263      }
2264    else
2265      {
2266         if (!source->pre_render_done)
2267            source->func->render_pre(source);
2268         source->func->render(source, e->engine.data.output, ctx,
2269                              source->proxy.surface,
2270                              -source->cur.geometry.x,
2271                              -source->cur.geometry.y);
2272      }
2273    
2274    e->engine.func->context_free(e->engine.data.output, ctx);
2275    source->proxy.surface = e->engine.func->image_dirty_region
2276       (e->engine.data.output, source->proxy.surface, 0, 0, w, h);
2277  */
2278 }
2279
2280 #if 0 // filtering disabled
2281 /*
2282  *
2283  * Note that this is similar to proxy_subrender_recurse.  It should be
2284  * possible to merge I guess
2285  */
2286 static void
2287 image_filter_draw_under_recurse(Evas *e, Evas_Object *obj, Evas_Object *stop,
2288                                 void *output, void *ctx, void *surface,
2289                                 int x, int y)
2290 {
2291    Evas_Object *obj2;
2292    
2293    if (obj->clip.clipees) return;
2294    /* FIXME: Doing bounding box test */
2295    if (!evas_object_is_in_output_rect(obj, stop->cur.geometry.x,
2296                                       stop->cur.geometry.y,
2297                                       stop->cur.geometry.w,
2298                                       stop->cur.geometry.h))
2299       return;
2300    
2301    if (!evas_object_is_visible(obj)) return;
2302    obj->pre_render_done = 1;
2303    ctx = e->engine.func->context_new(output);
2304    
2305    if (obj->smart.smart)
2306      {
2307         EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(obj), obj2)
2308           {
2309              if (obj2 == stop) return;
2310              image_filter_draw_under_recurse(e, obj2, stop, output, surface, 
2311                                              ctx, x, y);
2312           }
2313      }
2314    else
2315       obj->func->render(obj, output, ctx, surface, x ,y);
2316    e->engine.func->context_free(output, ctx);
2317 }
2318
2319 /*
2320  * Draw all visible objects intersecting an object which are _beneath_ it.
2321  */
2322 static void
2323 image_filter_draw_under(Evas *e, Evas_Object *stop, void *output, void *ctx, void *surface, int dx, int dy)
2324 {
2325    Evas_Layer *lay;
2326    int x, y;
2327    
2328    x = stop->cur.geometry.x - dx;
2329    y = stop->cur.geometry.y - dy;
2330    
2331    EINA_INLIST_FOREACH(e->layers, lay)
2332      {
2333         Evas_Object *obj;
2334         EINA_INLIST_FOREACH(lay->objects, obj)
2335           {
2336              if (obj->delete_me) continue;
2337              if (obj == stop) return;
2338              /* FIXME: Do bounding box check */
2339              image_filter_draw_under_recurse(e, obj, stop, output, ctx, 
2340                                              surface, -x, -y);
2341           }
2342      }
2343    e->engine.func->image_dirty_region(output, surface, 0, 0, 300, 300);
2344    e->engine.func->output_flush(output);
2345 }
2346
2347 /*
2348  * Update the filtered object.
2349  *
2350  * Creates a new context, and renders stuff (filtered) onto that.
2351  */
2352 Filtered_Image *
2353 image_filter_update(Evas *e, Evas_Object *obj, void *src, int imagew, int imageh, int *outw, int *outh)
2354 {
2355    int w, h;
2356    void *ctx;
2357    Evas_Filter_Info *info;
2358    void *surface;
2359    Eina_Bool alpha;
2360    
2361    info = obj->filter;
2362    
2363    if (info->mode == EVAS_FILTER_MODE_BELOW)
2364      {
2365         w = obj->cur.geometry.w;
2366         h = obj->cur.geometry.h;
2367         evas_filter_get_size(info, w, h, &imagew, &imageh, EINA_TRUE);
2368         alpha = EINA_FALSE;
2369      }
2370    else
2371      {
2372         evas_filter_get_size(info, imagew, imageh, &w, &h, EINA_FALSE);
2373         alpha = e->engine.func->image_alpha_get(e->engine.data.output, src);
2374      }
2375    
2376    /* Certain filters may make alpha images anyway */
2377    if (alpha == EINA_FALSE) alpha = evas_filter_always_alpha(info);
2378    
2379    surface = e->engine.func->image_map_surface_new(e->engine.data.output, w, h,
2380                                                    alpha);
2381    
2382    if (info->mode == EVAS_FILTER_MODE_BELOW)
2383      {
2384         void *subsurface;
2385         int disw, dish;
2386         int dx, dy;
2387         disw = obj->cur.geometry.w;
2388         dish = obj->cur.geometry.h;
2389         dx = (imagew - w) >> 1;
2390         dy = (imageh - h) >> 1;
2391         subsurface = e->engine.func->image_map_surface_new
2392            (e->engine.data.output, imagew, imageh, 1);
2393         ctx = e->engine.func->context_new(e->engine.data.output);
2394         e->engine.func->context_color_set(e->engine.data.output, ctx, 0, 255, 0, 255);
2395         e->engine.func->context_render_op_set(e->engine.data.output, ctx, EVAS_RENDER_COPY);
2396         e->engine.func->rectangle_draw(e->engine.data.output, ctx,
2397                                        subsurface, 0, 0, imagew, imageh);
2398         
2399         image_filter_draw_under(e, obj, e->engine.data.output, ctx,
2400                                 subsurface, dx, dy);
2401         
2402         e->engine.func->context_free(e->engine.data.output, ctx);
2403         
2404         ctx = e->engine.func->context_new(e->engine.data.output);
2405         
2406         e->engine.func->image_draw_filtered(e->engine.data.output,
2407                                             ctx, surface, subsurface, info);
2408         
2409         e->engine.func->context_free(e->engine.data.output, ctx);
2410         
2411         e->engine.func->image_map_surface_free(e->engine.data.output,
2412                                                subsurface);
2413      }
2414    else
2415      {
2416         ctx = e->engine.func->context_new(e->engine.data.output);
2417         e->engine.func->image_draw_filtered(e->engine.data.output,
2418                                             ctx, surface, src, info);
2419         e->engine.func->context_free(e->engine.data.output, ctx);
2420      }
2421    
2422    e->engine.func->image_dirty_region(e->engine.data.output, surface, 
2423                                       0, 0, w, h);
2424    if (outw) *outw = w;
2425    if (outh) *outh = h;
2426    return e->engine.func->image_filtered_save(src, surface,
2427                                               obj->filter->key,
2428                                               obj->filter->len);
2429 }
2430 #endif
2431
2432 static void
2433 evas_object_image_unload(Evas_Object *obj, Eina_Bool dirty)
2434 {
2435    Evas_Object_Image *o;
2436    
2437    o = (Evas_Object_Image *)(obj->object_data);
2438    
2439    if ((!o->cur.file) ||
2440        (o->pixels_checked_out > 0)) return;
2441    if (dirty)
2442      {
2443         if (o->engine_data)
2444            o->engine_data = obj->layer->evas->engine.func->image_dirty_region
2445            (obj->layer->evas->engine.data.output,
2446                o->engine_data,
2447                0, 0,
2448                o->cur.image.w, o->cur.image.h);
2449      }
2450    if (o->engine_data)
2451      {
2452         if (o->preloading)
2453           {
2454              o->preloading = 0;
2455              obj->layer->evas->engine.func->image_data_preload_cancel(obj->layer->evas->engine.data.output,
2456                                                                       o->engine_data,
2457                                                                       obj);
2458           }
2459         obj->layer->evas->engine.func->image_free(obj->layer->evas->engine.data.output,
2460                                                   o->engine_data);
2461      }
2462    o->engine_data = NULL;
2463    o->load_error = EVAS_LOAD_ERROR_NONE;
2464    o->cur.has_alpha = 1;
2465    o->cur.cspace = EVAS_COLORSPACE_ARGB8888;
2466    o->cur.image.w = 0;
2467    o->cur.image.h = 0;
2468    o->cur.image.stride = 0;
2469 }
2470
2471 static void
2472 evas_object_image_load(Evas_Object *obj)
2473 {
2474    Evas_Object_Image *o;
2475    Evas_Image_Load_Opts lo;
2476
2477    o = (Evas_Object_Image *)(obj->object_data);
2478    if (o->engine_data) return;
2479
2480    lo.scale_down_by = o->load_opts.scale_down_by;
2481    lo.dpi = o->load_opts.dpi;
2482    lo.w = o->load_opts.w;
2483    lo.h = o->load_opts.h;
2484    lo.region.x = o->load_opts.region.x;
2485    lo.region.y = o->load_opts.region.y;
2486    lo.region.w = o->load_opts.region.w;
2487    lo.region.h = o->load_opts.region.h;
2488    lo.orientation = o->load_opts.orientation;
2489    o->engine_data = obj->layer->evas->engine.func->image_load
2490       (obj->layer->evas->engine.data.output,
2491           o->cur.file,
2492           o->cur.key,
2493           &o->load_error,
2494           &lo);
2495    if (o->engine_data)
2496      {
2497         int w, h;
2498         int stride = 0;
2499
2500         obj->layer->evas->engine.func->image_size_get
2501            (obj->layer->evas->engine.data.output,
2502                o->engine_data, &w, &h);
2503         if (obj->layer->evas->engine.func->image_stride_get)
2504           obj->layer->evas->engine.func->image_stride_get
2505            (obj->layer->evas->engine.data.output,
2506                o->engine_data, &stride);
2507         else
2508           stride = w * 4;
2509         o->cur.has_alpha = obj->layer->evas->engine.func->image_alpha_get
2510            (obj->layer->evas->engine.data.output,
2511                o->engine_data);
2512         o->cur.cspace = obj->layer->evas->engine.func->image_colorspace_get
2513            (obj->layer->evas->engine.data.output,
2514                o->engine_data);
2515         o->cur.image.w = w;
2516         o->cur.image.h = h;
2517         o->cur.image.stride = stride;
2518      }
2519    else
2520      {
2521         o->load_error = EVAS_LOAD_ERROR_GENERIC;
2522      }
2523 }
2524
2525 static Evas_Coord
2526 evas_object_image_figure_x_fill(Evas_Object *obj, Evas_Coord start, Evas_Coord size, Evas_Coord *size_ret)
2527 {
2528    Evas_Coord w;
2529
2530    w = ((size * obj->layer->evas->output.w) /
2531         (Evas_Coord)obj->layer->evas->viewport.w);
2532    if (size <= 0) size = 1;
2533    if (start > 0)
2534      {
2535         while (start - size > 0) start -= size;
2536      }
2537    else if (start < 0)
2538      {
2539         while (start < 0) start += size;
2540      }
2541    start = ((start * obj->layer->evas->output.w) /
2542             (Evas_Coord)obj->layer->evas->viewport.w);
2543    *size_ret = w;
2544    return start;
2545 }
2546
2547 static Evas_Coord
2548 evas_object_image_figure_y_fill(Evas_Object *obj, Evas_Coord start, Evas_Coord size, Evas_Coord *size_ret)
2549 {
2550    Evas_Coord h;
2551
2552    h = ((size * obj->layer->evas->output.h) /
2553         (Evas_Coord)obj->layer->evas->viewport.h);
2554    if (size <= 0) size = 1;
2555    if (start > 0)
2556      {
2557         while (start - size > 0) start -= size;
2558      }
2559    else if (start < 0)
2560      {
2561         while (start < 0) start += size;
2562      }
2563    start = ((start * obj->layer->evas->output.h) /
2564             (Evas_Coord)obj->layer->evas->viewport.h);
2565    *size_ret = h;
2566    return start;
2567 }
2568
2569 static void
2570 evas_object_image_init(Evas_Object *obj)
2571 {
2572    /* alloc image ob, setup methods and default values */
2573    obj->object_data = evas_object_image_new();
2574    /* set up default settings for this kind of object */
2575    obj->cur.color.r = 255;
2576    obj->cur.color.g = 255;
2577    obj->cur.color.b = 255;
2578    obj->cur.color.a = 255;
2579    obj->cur.geometry.x = 0;
2580    obj->cur.geometry.y = 0;
2581    obj->cur.geometry.w = 0;
2582    obj->cur.geometry.h = 0;
2583    obj->cur.layer = 0;
2584    obj->cur.anti_alias = 0;
2585    obj->cur.render_op = EVAS_RENDER_BLEND;
2586    /* set up object-specific settings */
2587    obj->prev = obj->cur;
2588    /* set up methods (compulsory) */
2589    obj->func = &object_func;
2590    obj->type = o_type;
2591 }
2592
2593 static void *
2594 evas_object_image_new(void)
2595 {
2596    Evas_Object_Image *o;
2597
2598    /* alloc obj private data */
2599    EVAS_MEMPOOL_INIT(_mp_obj, "evas_object_image", Evas_Object_Image, 256, NULL);
2600    o = EVAS_MEMPOOL_ALLOC(_mp_obj, Evas_Object_Image);
2601    if (!o) return NULL;
2602    EVAS_MEMPOOL_PREP(_mp_obj, o, Evas_Object_Image);
2603    o->magic = MAGIC_OBJ_IMAGE;
2604    o->cur.fill.w = 0;
2605    o->cur.fill.h = 0;
2606    o->cur.smooth_scale = 1;
2607    o->cur.border.fill = 1;
2608    o->cur.border.scale = 1.0;
2609    o->cur.cspace = EVAS_COLORSPACE_ARGB8888;
2610    o->cur.spread = EVAS_TEXTURE_REPEAT;
2611    o->cur.opaque_valid = 0;
2612    o->cur.source = NULL;
2613    o->prev = o->cur;
2614    o->tmpf_fd = -1;
2615    return o;
2616 }
2617
2618 static void
2619 evas_object_image_free(Evas_Object *obj)
2620 {
2621    Evas_Object_Image *o;
2622    Eina_Rectangle *r;
2623
2624    /* frees private object data. very simple here */
2625    o = (Evas_Object_Image *)(obj->object_data);
2626    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
2627    return;
2628    MAGIC_CHECK_END();
2629    /* free obj */
2630    _cleanup_tmpf(obj);
2631    if (o->cur.file) eina_stringshare_del(o->cur.file);
2632    if (o->cur.key) eina_stringshare_del(o->cur.key);
2633    if (o->cur.source) _proxy_unset(obj);
2634    if (o->engine_data)
2635      {
2636         if (o->preloading)
2637           {
2638              o->preloading = 0;
2639              obj->layer->evas->engine.func->image_data_preload_cancel(obj->layer->evas->engine.data.output,
2640                                                                       o->engine_data,
2641                                                                       obj);
2642           }
2643         obj->layer->evas->engine.func->image_free(obj->layer->evas->engine.data.output,
2644                                                   o->engine_data);
2645      }
2646    o->engine_data = NULL;
2647    o->magic = 0;
2648    EINA_LIST_FREE(o->pixel_updates, r)
2649      eina_rectangle_free(r);
2650    EVAS_MEMPOOL_FREE(_mp_obj, o);
2651 }
2652
2653 static void
2654 evas_object_image_render(Evas_Object *obj, void *output, void *context, void *surface, int x, int y)
2655 {
2656    Evas_Object_Image *o;
2657    int imagew, imageh, uvw, uvh;
2658    void *pixels;
2659
2660    /* render object to surface with context, and offset by x,y */
2661    o = (Evas_Object_Image *)(obj->object_data);
2662
2663    if ((o->cur.fill.w < 1) || (o->cur.fill.h < 1))
2664      return; /* no error message, already printed in pre_render */
2665
2666    /* Proxy sanity */
2667    if (o->proxyrendering)
2668      {
2669         _proxy_error(obj, context, output, surface, x, y);
2670         return;
2671      }
2672
2673
2674    obj->layer->evas->engine.func->context_color_set(output,
2675                                                     context,
2676                                                     255, 255, 255, 255);
2677
2678    if ((obj->cur.cache.clip.r == 255) &&
2679        (obj->cur.cache.clip.g == 255) &&
2680        (obj->cur.cache.clip.b == 255) &&
2681        (obj->cur.cache.clip.a == 255))
2682      {
2683         obj->layer->evas->engine.func->context_multiplier_unset(output,
2684                                                                 context);
2685      }
2686    else
2687      obj->layer->evas->engine.func->context_multiplier_set(output,
2688                                                            context,
2689                                                            obj->cur.cache.clip.r,
2690                                                            obj->cur.cache.clip.g,
2691                                                            obj->cur.cache.clip.b,
2692                                                            obj->cur.cache.clip.a);
2693
2694    obj->layer->evas->engine.func->context_render_op_set(output, context,
2695                                                         obj->cur.render_op);
2696
2697    if (!o->cur.source)
2698      {
2699         pixels = o->engine_data;
2700         imagew = o->cur.image.w;
2701         imageh = o->cur.image.h;
2702         uvw = imagew;
2703         uvh = imageh;
2704      }
2705    else if (o->cur.source->proxy.surface && !o->cur.source->proxy.redraw)
2706      {
2707         pixels = o->cur.source->proxy.surface;
2708         imagew = o->cur.source->proxy.w;
2709         imageh = o->cur.source->proxy.h;
2710         uvw = imagew;
2711         uvh = imageh;
2712      }
2713    else if (o->cur.source->type == o_type &&
2714             ((Evas_Object_Image *)o->cur.source->object_data)->engine_data)
2715      {
2716         Evas_Object_Image *oi;
2717         oi = o->cur.source->object_data;
2718         pixels = oi->engine_data;
2719         imagew = oi->cur.image.w;
2720         imageh = oi->cur.image.h;
2721         uvw = o->cur.source->cur.geometry.w;
2722         uvh = o->cur.source->cur.geometry.h;
2723      }
2724    else
2725      {
2726         o->proxyrendering = 1;
2727         _proxy_subrender(obj->layer->evas, o->cur.source);
2728         pixels = o->cur.source->proxy.surface;
2729         imagew = o->cur.source->proxy.w;
2730         imageh = o->cur.source->proxy.h;
2731         uvw = imagew;
2732         uvh = imageh;
2733         o->proxyrendering = 0;
2734      }
2735
2736 #if 0 // filtering disabled
2737    /* Now check/update filter */
2738    if (obj->filter && obj->filter->filter)
2739      {
2740         Filtered_Image *fi = NULL;
2741         //printf("%p has filter: %s\n", obj,obj->filter->dirty?"dirty":"clean");
2742         if (obj->filter->dirty)
2743           {
2744              if (obj->filter->mode != EVAS_FILTER_MODE_BELOW)
2745                {
2746                   uint32_t len;
2747                   uint8_t *key;
2748                   
2749                   if (obj->filter->key) free(obj->filter->key);
2750                   obj->filter->key = NULL;
2751                   obj->filter->len = 0;
2752                   key = evas_filter_key_get(obj->filter, &len);
2753                   if (key)
2754                     {
2755                        obj->filter->key = key;
2756                        obj->filter->len = len;
2757                        fi = obj->layer->evas->engine.func->image_filtered_get
2758                           (o->engine_data, key, len);
2759                        if (obj->filter->cached && fi != obj->filter->cached)
2760                          {
2761                             obj->layer->evas->engine.func->image_filtered_free
2762                                (o->engine_data, obj->filter->cached);
2763                             obj->filter->cached = NULL;
2764                          }
2765                     }
2766                }
2767              else if (obj->filter->cached)
2768                {
2769                   obj->layer->evas->engine.func->image_filtered_free
2770                      (o->engine_data, obj->filter->cached);
2771                }
2772              if (!fi)
2773                 fi = image_filter_update(obj->layer->evas, obj, pixels, 
2774                                          imagew, imageh, &imagew, &imageh);
2775              pixels = fi->image;
2776              obj->filter->dirty = 0;
2777              obj->filter->cached = fi;
2778           }
2779         else
2780           {
2781              fi = obj->filter->cached;
2782              pixels = fi->image;
2783           }
2784      }
2785 #endif
2786    
2787    if (pixels)
2788      {
2789         Evas_Coord idw, idh, idx, idy;
2790         int ix, iy, iw, ih;
2791
2792         if (o->dirty_pixels)
2793           {
2794              if (o->func.get_pixels)
2795                {
2796                   o->func.get_pixels(o->func.get_pixels_data, obj);
2797                   o->engine_data = obj->layer->evas->engine.func->image_dirty_region
2798                      (obj->layer->evas->engine.data.output, o->engine_data,
2799                          0, 0, o->cur.image.w, o->cur.image.h);
2800                }
2801              o->dirty_pixels = 0;
2802           }
2803         if ((obj->cur.map) && (obj->cur.map->count > 3) && (obj->cur.usemap))
2804           {
2805              const Evas_Map_Point *p, *p_end;
2806              RGBA_Map_Point pts[obj->cur.map->count], *pt;
2807
2808              p = obj->cur.map->points;
2809              p_end = p + obj->cur.map->count;
2810              pt = pts;
2811              
2812              pts[0].px = obj->cur.map->persp.px << FP;
2813              pts[0].py = obj->cur.map->persp.py << FP;
2814              pts[0].foc = obj->cur.map->persp.foc << FP;
2815              pts[0].z0 = obj->cur.map->persp.z0 << FP;
2816              // draw geom +x +y
2817              for (; p < p_end; p++, pt++)
2818                {
2819                   pt->x = (p->x + (double)x) * FP1;
2820                   pt->y = (p->y + (double)y) * FP1;
2821                   pt->z = (p->z)             * FP1;
2822                   pt->fx = p->px;
2823                   pt->fy = p->py;
2824                   pt->fz = p->z;
2825                   pt->u = ((p->u * imagew) / uvw) * FP1;
2826                   pt->v = ((p->v * imageh) / uvh) * FP1;
2827                   if      (pt->u < 0) pt->u = 0;
2828                   else if (pt->u > (imagew * FP1)) pt->u = (imagew * FP1);
2829                   if      (pt->v < 0) pt->v = 0;
2830                   else if (pt->v > (imageh * FP1)) pt->v = (imageh * FP1);
2831                   pt->col = ARGB_JOIN(p->a, p->r, p->g, p->b);
2832               }
2833              if (obj->cur.map->count & 0x1)
2834                {
2835                   pts[obj->cur.map->count] = pts[obj->cur.map->count -1];
2836                }
2837
2838              obj->layer->evas->engine.func->image_map_draw
2839                (output, context, surface, pixels, obj->cur.map->count,
2840                 pts, o->cur.smooth_scale | obj->cur.map->smooth, 0);
2841           }
2842         else
2843           {
2844              obj->layer->evas->engine.func->image_scale_hint_set(output,
2845                                                                  pixels,
2846                                                                  o->scale_hint);
2847              /* This is technically a bug here: If the value is recreated
2848               * (which is returned)it may be a new object, however exactly 0
2849               * of all the evas engines do this. */
2850              obj->layer->evas->engine.func->image_border_set(output, pixels,
2851                                                              o->cur.border.l, o->cur.border.r,
2852                                                              o->cur.border.t, o->cur.border.b);
2853              idx = evas_object_image_figure_x_fill(obj, o->cur.fill.x, o->cur.fill.w, &idw);
2854              idy = evas_object_image_figure_y_fill(obj, o->cur.fill.y, o->cur.fill.h, &idh);
2855              if (idw < 1) idw = 1;
2856              if (idh < 1) idh = 1;
2857              if (idx > 0) idx -= idw;
2858              if (idy > 0) idy -= idh;
2859              while ((int)idx < obj->cur.geometry.w)
2860                {
2861                   Evas_Coord ydy;
2862                   int dobreak_w = 0;
2863                   
2864                   ydy = idy;
2865                   ix = idx;
2866                   if ((o->cur.fill.w == obj->cur.geometry.w) &&
2867                       (o->cur.fill.x == 0))
2868                     {
2869                        dobreak_w = 1;
2870                        iw = obj->cur.geometry.w;
2871                     }
2872                   else
2873                     iw = ((int)(idx + idw)) - ix;
2874                   while ((int)idy < obj->cur.geometry.h)
2875                     {
2876                        int dobreak_h = 0;
2877                        
2878                        iy = idy;
2879                        if ((o->cur.fill.h == obj->cur.geometry.h) &&
2880                            (o->cur.fill.y == 0))
2881                          {
2882                             ih = obj->cur.geometry.h;
2883                             dobreak_h = 1;
2884                          }
2885                        else
2886                          ih = ((int)(idy + idh)) - iy;
2887                        if ((o->cur.border.l == 0) &&
2888                            (o->cur.border.r == 0) &&
2889                            (o->cur.border.t == 0) &&
2890                            (o->cur.border.b == 0) &&
2891                            (o->cur.border.fill != 0))
2892                          obj->layer->evas->engine.func->image_draw(output,
2893                                                                    context,
2894                                                                    surface,
2895                                                                    pixels,
2896                                                                    0, 0,
2897                                                                    imagew,
2898                                                                    imageh,
2899                                                                    obj->cur.geometry.x + ix + x,
2900                                                                    obj->cur.geometry.y + iy + y,
2901                                                                    iw, ih,
2902                                                                    o->cur.smooth_scale);
2903                        else
2904                          {
2905                             int inx, iny, inw, inh, outx, outy, outw, outh;
2906                             int bl, br, bt, bb, bsl, bsr, bst, bsb;
2907                             int imw, imh, ox, oy;
2908                             
2909                             ox = obj->cur.geometry.x + ix + x;
2910                             oy = obj->cur.geometry.y + iy + y;
2911                             imw = imagew;
2912                             imh = imageh;
2913                             bl = o->cur.border.l;
2914                             br = o->cur.border.r;
2915                             bt = o->cur.border.t;
2916                             bb = o->cur.border.b;
2917                             if ((bl + br) > iw)
2918                               {
2919                                  bl = iw / 2;
2920                                  br = iw - bl;
2921                               }
2922                             if ((bl + br) > imw)
2923                               {
2924                                  bl = imw / 2;
2925                                  br = imw - bl;
2926                               }
2927                             if ((bt + bb) > ih)
2928                               {
2929                                  bt = ih / 2;
2930                                  bb = ih - bt;
2931                               }
2932                             if ((bt + bb) > imh)
2933                               {
2934                                  bt = imh / 2;
2935                                  bb = imh - bt;
2936                               }
2937                             if (o->cur.border.scale != 1.0)
2938                               {
2939                                  bsl = ((double)bl * o->cur.border.scale);
2940                                  bsr = ((double)br * o->cur.border.scale);
2941                                  bst = ((double)bt * o->cur.border.scale);
2942                                  bsb = ((double)bb * o->cur.border.scale);
2943                               }
2944                             else
2945                               {
2946                                   bsl = bl; bsr = br; bst = bt; bsb = bb;
2947                               }
2948                             // #--
2949                             // |
2950                             inx = 0; iny = 0;
2951                             inw = bl; inh = bt;
2952                             outx = ox; outy = oy;
2953                             outw = bsl; outh = bst;
2954                             obj->layer->evas->engine.func->image_draw(output, context, surface, pixels, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale);
2955                             // .##
2956                             // |
2957                             inx = bl; iny = 0;
2958                             inw = imw - bl - br; inh = bt;
2959                             outx = ox + bsl; outy = oy;
2960                             outw = iw - bsl - bsr; outh = bst;
2961                             obj->layer->evas->engine.func->image_draw(output, context, surface, pixels, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale);
2962                             // --#
2963                             //   |
2964                             inx = imw - br; iny = 0;
2965                             inw = br; inh = bt;
2966                             outx = ox + iw - bsr; outy = oy;
2967                             outw = bsr; outh = bst;
2968                             obj->layer->evas->engine.func->image_draw(output, context, surface, pixels, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale);
2969                             // .--
2970                             // #  
2971                             inx = 0; iny = bt;
2972                             inw = bl; inh = imh - bt - bb;
2973                             outx = ox; outy = oy + bst;
2974                             outw = bsl; outh = ih - bst - bsb;
2975                             obj->layer->evas->engine.func->image_draw(output, context, surface, pixels, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale);
2976                             // .--.
2977                             // |##|
2978                             if (o->cur.border.fill > EVAS_BORDER_FILL_NONE)
2979                               {
2980                                  inx = bl; iny = bt;
2981                                  inw = imw - bl - br; inh = imh - bt - bb;
2982                                  outx = ox + bsl; outy = oy + bst;
2983                                  outw = iw - bsl - bsr; outh = ih - bst - bsb;
2984                                  if ((o->cur.border.fill == EVAS_BORDER_FILL_SOLID) &&
2985                                      (obj->cur.cache.clip.a == 255) &&
2986                                      (obj->cur.render_op == EVAS_RENDER_BLEND))
2987                                    {
2988                                       obj->layer->evas->engine.func->context_render_op_set(output, context,
2989                                                                                            EVAS_RENDER_COPY);
2990                                       obj->layer->evas->engine.func->image_draw(output, context, surface, pixels, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale);
2991                                       obj->layer->evas->engine.func->context_render_op_set(output, context,
2992                                                                                            obj->cur.render_op);
2993                                    }
2994                                  else
2995                                    obj->layer->evas->engine.func->image_draw(output, context, surface, pixels, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale);
2996                               }
2997                             // --.
2998                             //   #
2999                             inx = imw - br; iny = bt;
3000                             inw = br; inh = imh - bt - bb;
3001                             outx = ox + iw - bsr; outy = oy + bst;
3002                             outw = bsr; outh = ih - bst - bsb;
3003                             obj->layer->evas->engine.func->image_draw(output, context, surface, pixels, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale);
3004                             // |
3005                             // #--
3006                             inx = 0; iny = imh - bb;
3007                             inw = bl; inh = bb;
3008                             outx = ox; outy = oy + ih - bsb;
3009                             outw = bsl; outh = bsb;
3010                             obj->layer->evas->engine.func->image_draw(output, context, surface, pixels, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale);
3011                             // |
3012                             // .## 
3013                             inx = bl; iny = imh - bb;
3014                             inw = imw - bl - br; inh = bb;
3015                             outx = ox + bsl; outy = oy + ih - bsb;
3016                             outw = iw - bsl - bsr; outh = bsb;
3017                             obj->layer->evas->engine.func->image_draw(output, context, surface, pixels, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale);
3018                             //   |
3019                             // --#
3020                             inx = imw - br; iny = imh - bb;
3021                             inw = br; inh = bb;
3022                             outx = ox + iw - bsr; outy = oy + ih - bsb;
3023                             outw = bsr; outh = bsb;
3024                             obj->layer->evas->engine.func->image_draw(output, context, surface, pixels, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale);
3025                          }
3026                        idy += idh;
3027                        if (dobreak_h) break;
3028                     }
3029                   idx += idw;
3030                   idy = ydy;
3031                   if (dobreak_w) break;
3032                }
3033           }
3034      }
3035 }
3036
3037 static void
3038 evas_object_image_render_pre(Evas_Object *obj)
3039 {
3040    Evas_Object_Image *o;
3041    int is_v = 0, was_v = 0;
3042    Evas *e;
3043
3044    /* dont pre-render the obj twice! */
3045    if (obj->pre_render_done) return;
3046    obj->pre_render_done = 1;
3047    /* pre-render phase. this does anything an object needs to do just before */
3048    /* rendering. this could mean loading the image data, retrieving it from */
3049    /* elsewhere, decoding video etc. */
3050    /* then when this is done the object needs to figure if it changed and */
3051    /* if so what and where and add the appropriate redraw rectangles */
3052    o = (Evas_Object_Image *)(obj->object_data);
3053    e = obj->layer->evas;
3054
3055    if ((o->cur.fill.w < 1) || (o->cur.fill.h < 1))
3056      {
3057         ERR("%p has invalid fill size: %dx%d. Ignored",
3058             obj, o->cur.fill.w, o->cur.fill.h);
3059         return;
3060      }
3061
3062    /* if someone is clipping this obj - go calculate the clipper */
3063    if (obj->cur.clipper)
3064      {
3065         if (obj->cur.cache.clip.dirty)
3066           evas_object_clip_recalc(obj->cur.clipper);
3067         obj->cur.clipper->func->render_pre(obj->cur.clipper);
3068      }
3069    /* Proxy: Do it early */
3070    if (o->cur.source && 
3071        (o->cur.source->proxy.redraw || o->cur.source->changed))
3072      {
3073         /* XXX: Do I need to sort out the map here? */
3074         evas_object_render_pre_prev_cur_add(&e->clip_changes, obj);
3075         goto done;
3076      }
3077
3078    /* now figure what changed and add draw rects */
3079    /* if it just became visible or invisible */
3080    is_v = evas_object_is_visible(obj);
3081    was_v = evas_object_was_visible(obj);
3082    if (is_v != was_v)
3083      {
3084         evas_object_render_pre_visible_change(&e->clip_changes, obj, is_v, was_v);
3085         if (!o->pixel_updates) goto done;
3086      }
3087    if ((obj->cur.map != obj->prev.map) ||
3088        (obj->cur.usemap != obj->prev.usemap))
3089      {
3090         evas_object_render_pre_prev_cur_add(&e->clip_changes, obj);
3091         goto done;
3092      }
3093    /* it's not visible - we accounted for it appearing or not so just abort */
3094    if (!is_v) goto done;
3095    /* clipper changed this is in addition to anything else for obj */
3096    evas_object_render_pre_clipper_change(&e->clip_changes, obj);
3097    /* if we restacked (layer or just within a layer) and don't clip anyone */
3098    if (obj->restack)
3099      {
3100         evas_object_render_pre_prev_cur_add(&e->clip_changes, obj);
3101         if (!o->pixel_updates) goto done;
3102      }
3103    /* if it changed color */
3104    if ((obj->cur.color.r != obj->prev.color.r) ||
3105        (obj->cur.color.g != obj->prev.color.g) ||
3106        (obj->cur.color.b != obj->prev.color.b) ||
3107        (obj->cur.color.a != obj->prev.color.a))
3108      {
3109         evas_object_render_pre_prev_cur_add(&e->clip_changes, obj);
3110         if (!o->pixel_updates) goto done;
3111      }
3112    /* if it changed render op */
3113    if (obj->cur.render_op != obj->prev.render_op)
3114      {
3115         evas_object_render_pre_prev_cur_add(&e->clip_changes, obj);
3116         if (!o->pixel_updates) goto done;
3117      }
3118    /* if it changed anti_alias */
3119    if (obj->cur.anti_alias != obj->prev.anti_alias)
3120      {
3121         evas_object_render_pre_prev_cur_add(&e->clip_changes, obj);
3122         if (!o->pixel_updates) goto done;
3123      }
3124    if (o->changed)
3125      {
3126         if (((o->cur.file) && (!o->prev.file)) ||
3127             ((!o->cur.file) && (o->prev.file)) ||
3128             ((o->cur.key) && (!o->prev.key)) ||
3129             ((!o->cur.key) && (o->prev.key))
3130             )
3131           {
3132              evas_object_render_pre_prev_cur_add(&e->clip_changes, obj);
3133              if (!o->pixel_updates) goto done;
3134           }
3135         if ((o->cur.image.w != o->prev.image.w) ||
3136             (o->cur.image.h != o->prev.image.h) ||
3137             (o->cur.has_alpha != o->prev.has_alpha) ||
3138             (o->cur.cspace != o->prev.cspace) ||
3139             (o->cur.smooth_scale != o->prev.smooth_scale))
3140           {
3141              evas_object_render_pre_prev_cur_add(&e->clip_changes, obj);
3142              if (!o->pixel_updates) goto done;
3143           }
3144         if ((o->cur.border.l != o->prev.border.l) ||
3145             (o->cur.border.r != o->prev.border.r) ||
3146             (o->cur.border.t != o->prev.border.t) ||
3147             (o->cur.border.b != o->prev.border.b) ||
3148             (o->cur.border.fill != o->prev.border.fill) ||
3149             (o->cur.border.scale != o->prev.border.scale))
3150           {
3151              evas_object_render_pre_prev_cur_add(&e->clip_changes, obj);
3152              if (!o->pixel_updates) goto done;
3153           }
3154         if (o->dirty_pixels)
3155           {
3156              evas_object_render_pre_prev_cur_add(&e->clip_changes, obj);
3157              if (!o->pixel_updates) goto done;
3158           }
3159         if (o->cur.frame != o->prev.frame)
3160           {
3161              evas_object_render_pre_prev_cur_add(&e->clip_changes, obj);
3162              if (!o->pixel_updates) goto done;
3163           }
3164         
3165      }
3166    /* if it changed geometry - and obviously not visibility or color */
3167    /* calculate differences since we have a constant color fill */
3168    /* we really only need to update the differences */
3169 #if 0 // XXX: maybe buggy?
3170    if (((obj->cur.geometry.x != obj->prev.geometry.x) ||
3171         (obj->cur.geometry.y != obj->prev.geometry.y) ||
3172         (obj->cur.geometry.w != obj->prev.geometry.w) ||
3173         (obj->cur.geometry.h != obj->prev.geometry.h)) &&
3174        (o->cur.fill.w == o->prev.fill.w) &&
3175        (o->cur.fill.h == o->prev.fill.h) &&
3176        ((o->cur.fill.x + obj->cur.geometry.x) == (o->prev.fill.x + obj->prev.geometry.x)) &&
3177        ((o->cur.fill.y + obj->cur.geometry.y) == (o->prev.fill.y + obj->prev.geometry.y)) &&
3178        (!o->pixel_updates)
3179        )
3180      {
3181         evas_rects_return_difference_rects(&e->clip_changes,
3182                                            obj->cur.geometry.x,
3183                                            obj->cur.geometry.y,
3184                                            obj->cur.geometry.w,
3185                                            obj->cur.geometry.h,
3186                                            obj->prev.geometry.x,
3187                                            obj->prev.geometry.y,
3188                                            obj->prev.geometry.w,
3189                                            obj->prev.geometry.h);
3190         if (!o->pixel_updates) goto done;
3191      }
3192 #endif   
3193    if (((obj->cur.geometry.x != obj->prev.geometry.x) ||
3194         (obj->cur.geometry.y != obj->prev.geometry.y) ||
3195         (obj->cur.geometry.w != obj->prev.geometry.w) ||
3196         (obj->cur.geometry.h != obj->prev.geometry.h))
3197        )
3198      {
3199         evas_object_render_pre_prev_cur_add(&e->clip_changes, obj);
3200         if (!o->pixel_updates) goto done;
3201      }
3202    if (o->changed)
3203      {
3204         if ((o->cur.fill.x != o->prev.fill.x) ||
3205             (o->cur.fill.y != o->prev.fill.y) ||
3206             (o->cur.fill.w != o->prev.fill.w) ||
3207             (o->cur.fill.h != o->prev.fill.h))
3208           {
3209              evas_object_render_pre_prev_cur_add(&e->clip_changes, obj);
3210              if (!o->pixel_updates) goto done;
3211           }
3212         if (o->pixel_updates)
3213           {
3214              if ((o->cur.border.l == 0) &&
3215                  (o->cur.border.r == 0) &&
3216                  (o->cur.border.t == 0) &&
3217                  (o->cur.border.b == 0) &&
3218                  (o->cur.image.w > 0) &&
3219                  (o->cur.image.h > 0) &&
3220                 (!((obj->cur.map) && (obj->cur.usemap))))
3221                {
3222                   Eina_Rectangle *rr;
3223                   
3224                   EINA_LIST_FREE(o->pixel_updates, rr)
3225                     {
3226                        Evas_Coord idw, idh, idx, idy;
3227                        int x, y, w, h;
3228                        
3229                        e->engine.func->image_dirty_region(e->engine.data.output, o->engine_data, rr->x, rr->y, rr->w, rr->h);
3230                        
3231                        idx = evas_object_image_figure_x_fill(obj, o->cur.fill.x, o->cur.fill.w, &idw);
3232                        idy = evas_object_image_figure_y_fill(obj, o->cur.fill.y, o->cur.fill.h, &idh);
3233                        
3234                        if (idw < 1) idw = 1;
3235                        if (idh < 1) idh = 1;
3236                        if (idx > 0) idx -= idw;
3237                        if (idy > 0) idy -= idh;
3238                        while (idx < obj->cur.geometry.w)
3239                          {
3240                             Evas_Coord ydy;
3241                             
3242                             ydy = idy;
3243                             x = idx;
3244                             w = ((int)(idx + idw)) - x;
3245                             while (idy < obj->cur.geometry.h)
3246                               {
3247                                  Eina_Rectangle r;
3248                                  
3249                                  y = idy;
3250                                  h = ((int)(idy + idh)) - y;
3251                                  
3252                                  r.x = ((rr->x - 1) * w) / o->cur.image.w;
3253                                  r.y = ((rr->y - 1) * h) / o->cur.image.h;
3254                                  r.w = ((rr->w + 2) * w) / o->cur.image.w;
3255                                  r.h = ((rr->h + 2) * h) / o->cur.image.h;
3256                                  r.x += obj->cur.geometry.x + x;
3257                                  r.y += obj->cur.geometry.y + y;
3258                                  evas_add_rect(&e->clip_changes, r.x, r.y, r.w, r.h);
3259                                  idy += h;
3260                               }
3261                             idx += idw;
3262                             idy = ydy;
3263                          }
3264                        eina_rectangle_free(rr);
3265                     }
3266                   goto done;
3267                }
3268              else
3269                {
3270                   Eina_Rectangle *r;
3271                   
3272                   EINA_LIST_FREE(o->pixel_updates, r)
3273                      eina_rectangle_free(r);
3274                   e->engine.func->image_dirty_region(e->engine.data.output, o->engine_data, 0, 0, o->cur.image.w, o->cur.image.h);
3275                   evas_object_render_pre_prev_cur_add(&e->clip_changes, obj);
3276                   goto done;
3277                }
3278           }
3279      }
3280 #if 0 // filtering disabled
3281    if (obj->filter && obj->filter->dirty)
3282      {
3283         evas_object_render_pre_prev_cur_add(&e->clip_changes, obj);
3284      }
3285 #endif   
3286    /* it obviously didn't change - add a NO obscure - this "unupdates"  this */
3287    /* area so if there were updates for it they get wiped. don't do it if we */
3288    /* aren't fully opaque and we are visible */
3289    if (evas_object_is_visible(obj) &&
3290        evas_object_is_opaque(obj))
3291      {
3292          e->engine.func->output_redraws_rect_del(e->engine.data.output,
3293                                                                obj->cur.cache.clip.x,
3294                                                                obj->cur.cache.clip.y,
3295                                                                obj->cur.cache.clip.w,
3296                                                                obj->cur.cache.clip.h);
3297      }
3298    done:
3299    evas_object_render_pre_effect_updates(&e->clip_changes, obj, is_v, was_v);
3300 }
3301
3302 static void
3303 evas_object_image_render_post(Evas_Object *obj)
3304 {
3305    Evas_Object_Image *o;
3306    Eina_Rectangle *r;
3307
3308    /* this moves the current data to the previous state parts of the object */
3309    /* in whatever way is safest for the object. also if we don't need object */
3310    /* data anymore we can free it if the object deems this is a good idea */
3311    o = (Evas_Object_Image *)(obj->object_data);
3312    /* remove those pesky changes */
3313    evas_object_clip_changes_clean(obj);
3314    EINA_LIST_FREE(o->pixel_updates, r)
3315      eina_rectangle_free(r);
3316    /* move cur to prev safely for object data */
3317    obj->prev = obj->cur;
3318    o->prev = o->cur;
3319    o->changed = 0;
3320    /* FIXME: copy strings across */
3321 }
3322
3323 static unsigned int evas_object_image_id_get(Evas_Object *obj)
3324 {
3325    Evas_Object_Image *o;
3326
3327    o = (Evas_Object_Image *)(obj->object_data);
3328    if (!o) return 0;
3329    return MAGIC_OBJ_IMAGE;
3330 }
3331
3332 static unsigned int evas_object_image_visual_id_get(Evas_Object *obj)
3333 {
3334    Evas_Object_Image *o;
3335
3336    o = (Evas_Object_Image *)(obj->object_data);
3337    if (!o) return 0;
3338    return MAGIC_OBJ_IMAGE;
3339 }
3340
3341 static void *evas_object_image_engine_data_get(Evas_Object *obj)
3342 {
3343    Evas_Object_Image *o;
3344
3345    o = (Evas_Object_Image *)(obj->object_data);
3346    if (!o) return NULL;
3347    return o->engine_data;
3348 }
3349
3350 static int
3351 evas_object_image_is_opaque(Evas_Object *obj)
3352 {
3353    Evas_Object_Image *o;
3354
3355    /* this returns 1 if the internal object data implies that the object is */
3356    /* currently fully opaque over the entire rectangle it occupies */
3357    o = (Evas_Object_Image *)(obj->object_data);
3358    if (o->cur.opaque_valid)
3359      {
3360         if (!o->cur.opaque) return 0;
3361      }
3362    else
3363      {
3364         o->cur.opaque = 0;
3365         o->cur.opaque_valid = 1;
3366         if ((o->cur.fill.w < 1) || (o->cur.fill.h < 1))
3367            return 0;
3368         if (((o->cur.border.l != 0) ||
3369              (o->cur.border.r != 0) ||
3370              (o->cur.border.t != 0) ||
3371              (o->cur.border.b != 0)) &&
3372             (!o->cur.border.fill)) return 0;
3373         if (!o->engine_data) return 0;
3374         o->cur.opaque = 1;
3375      }
3376    // FIXME: use proxy
3377    if (o->cur.source) return 0; /* FIXME: Should go poke at the object */
3378    if ((obj->cur.map) && (obj->cur.usemap)) return 0;
3379    if (obj->cur.render_op == EVAS_RENDER_COPY) return 1;
3380    if (o->cur.has_alpha) return 0;
3381    return 1;
3382 }
3383
3384 static int
3385 evas_object_image_was_opaque(Evas_Object *obj)
3386 {
3387    Evas_Object_Image *o;
3388
3389    /* this returns 1 if the internal object data implies that the object was */
3390    /* previously fully opaque over the entire rectangle it occupies */
3391    o = (Evas_Object_Image *)(obj->object_data);
3392    if (o->prev.opaque_valid)
3393      {
3394         if (!o->prev.opaque) return 0;
3395      }
3396    else
3397      {
3398         o->prev.opaque = 0;
3399         o->prev.opaque_valid = 1;
3400         if ((o->prev.fill.w < 1) || (o->prev.fill.h < 1))
3401            return 0;
3402         if (((o->prev.border.l != 0) ||
3403              (o->prev.border.r != 0) ||
3404              (o->prev.border.t != 0) ||
3405              (o->prev.border.b != 0)) &&
3406             (!o->prev.border.fill)) return 0;
3407         if (!o->engine_data) return 0;
3408         o->prev.opaque = 1;
3409      }
3410    // FIXME: use proxy
3411    if (o->prev.source) return 0; /* FIXME: Should go poke at the object */
3412    if (obj->prev.usemap) return 0;
3413    if (obj->prev.render_op == EVAS_RENDER_COPY) return 1;
3414    if (o->prev.has_alpha) return 0;
3415    if (obj->prev.render_op != EVAS_RENDER_BLEND) return 0;
3416    return 1;
3417 }
3418
3419 static int
3420 evas_object_image_is_inside(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
3421 {
3422    Evas_Object_Image *o;
3423    DATA32 *data;
3424    int w, h, stride, iw, ih;
3425    int a;
3426
3427    o = (Evas_Object_Image *)(obj->object_data);
3428
3429    x -= obj->cur.cache.clip.x;
3430    y -= obj->cur.cache.clip.y;
3431    w = obj->cur.cache.clip.w;
3432    h = obj->cur.cache.clip.h;
3433    iw = o->cur.image.w;
3434    ih = o->cur.image.h;
3435
3436    if ((x < 0) || (y < 0) || (x >= w) || (y >= h)) return 0;
3437    if (!o->cur.has_alpha) return 1;
3438
3439    // FIXME: proxy needs to be honored
3440    if (obj->cur.map)
3441      {
3442         x = obj->cur.map->mx;
3443         y = obj->cur.map->my;
3444      }
3445    else
3446      {
3447         int bl, br, bt, bb, bsl, bsr, bst, bsb;
3448         
3449         bl = o->cur.border.l;
3450         br = o->cur.border.r;
3451         bt = o->cur.border.t;
3452         bb = o->cur.border.b;
3453         if ((bl + br) > iw)
3454           {
3455              bl = iw / 2;
3456              br = iw - bl;
3457           }
3458         if ((bl + br) > iw)
3459           {
3460              bl = iw / 2;
3461              br = iw - bl;
3462           }
3463         if ((bt + bb) > ih)
3464           {
3465              bt = ih / 2;
3466              bb = ih - bt;
3467           }
3468         if ((bt + bb) > ih)
3469           {
3470              bt = ih / 2;
3471              bb = ih - bt;
3472           }
3473         if (o->cur.border.scale != 1.0)
3474           {
3475              bsl = ((double)bl * o->cur.border.scale);
3476              bsr = ((double)br * o->cur.border.scale);
3477              bst = ((double)bt * o->cur.border.scale);
3478              bsb = ((double)bb * o->cur.border.scale);
3479           }
3480         else
3481           {
3482              bsl = bl; bsr = br; bst = bt; bsb = bb;
3483           }
3484         
3485         w = o->cur.fill.w;
3486         h = o->cur.fill.h;
3487         x -= o->cur.fill.x;
3488         y -= o->cur.fill.y;
3489         x %= w;
3490         y %= h;
3491         
3492         if (x < 0) x += w;
3493         if (y < 0) y += h;
3494         
3495         if (o->cur.border.fill != EVAS_BORDER_FILL_DEFAULT)
3496           {
3497              if ((x > bsl) && (x < (w - bsr)) &&
3498                  (y > bst) && (y < (h - bsb)))
3499                {
3500                   if (o->cur.border.fill == EVAS_BORDER_FILL_SOLID) return 1;
3501                   return 0;
3502                }
3503           }
3504         
3505         if (x < bsl) x = (x * bl) / bsl;
3506         else if (x > (w - bsr)) x = iw - (((w - x) * br) / bsr);
3507         else if ((bsl + bsr) < w) x = bl + (((x - bsl) * (iw - bl - br)) / (w - bsl - bsr));
3508         else return 1;
3509         
3510         if (y < bst) y = (y * bt) / bst;
3511         else if (y > (h - bsb)) y = ih - (((h - y) * bb) / bsb);
3512         else if ((bst + bsb) < h) y = bt + (((y - bst) * (ih - bt - bb)) / (h - bst - bsb));
3513         else return 1;
3514      }
3515    
3516    if (x < 0) x = 0;
3517    if (y < 0) y = 0;
3518    if (x >= iw) x = iw - 1;
3519    if (y >= ih) y = ih - 1;
3520    
3521    stride = o->cur.image.stride;
3522    
3523    o->engine_data = obj->layer->evas->engine.func->image_data_get
3524       (obj->layer->evas->engine.data.output,
3525           o->engine_data,
3526           0,
3527           &data,
3528           &o->load_error);
3529    if (!data)
3530      return 0;
3531
3532    switch (o->cur.cspace)
3533      {
3534      case EVAS_COLORSPACE_ARGB8888:
3535         data = ((DATA32*)(data) + ((y * (stride >> 2)) + x));
3536         a = (*((DATA32*)(data)) >> 24) & 0xff;
3537         break;
3538      case EVAS_COLORSPACE_RGB565_A5P:
3539         data = (void*) ((DATA16*)(data) + (h * (stride >> 1)));
3540         data = (void*) ((DATA8*)(data) + ((y * (stride >> 1)) + x));
3541         a = (*((DATA8*)(data))) & 0x1f;
3542         break;
3543      default:
3544         return 1;
3545         break;
3546      }
3547
3548    return (a != 0);
3549 }
3550
3551 static int
3552 evas_object_image_has_opaque_rect(Evas_Object *obj)
3553 {
3554    Evas_Object_Image *o;
3555
3556    o = (Evas_Object_Image *)(obj->object_data);
3557    if ((obj->cur.map) && (obj->cur.usemap)) return 0;
3558    if (((o->cur.border.l | o->cur.border.r | o->cur.border.t | o->cur.border.b) != 0) &&
3559        (o->cur.border.fill == EVAS_BORDER_FILL_SOLID) &&
3560        (obj->cur.render_op == EVAS_RENDER_BLEND) &&
3561        (obj->cur.cache.clip.a == 255) &&
3562        (o->cur.fill.x == 0) &&
3563        (o->cur.fill.y == 0) &&
3564        (o->cur.fill.w == obj->cur.geometry.w) &&
3565        (o->cur.fill.h == obj->cur.geometry.h)
3566        ) return 1;
3567    return 0;
3568 }
3569
3570 static int
3571 evas_object_image_get_opaque_rect(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
3572 {
3573    Evas_Object_Image *o;
3574
3575    o = (Evas_Object_Image *)(obj->object_data);
3576    if (o->cur.border.scale == 1.0)
3577      {
3578         *x = obj->cur.geometry.x + o->cur.border.l;
3579         *y = obj->cur.geometry.y + o->cur.border.t;
3580         *w = obj->cur.geometry.w - (o->cur.border.l + o->cur.border.r);
3581         if (*w < 0) *w = 0;
3582         *h = obj->cur.geometry.h - (o->cur.border.t + o->cur.border.b);
3583         if (*h < 0) *h = 0;
3584      }
3585    else
3586      {
3587         *x = obj->cur.geometry.x + (o->cur.border.l * o->cur.border.scale);
3588         *y = obj->cur.geometry.y + (o->cur.border.t * o->cur.border.scale);
3589         *w = obj->cur.geometry.w - ((o->cur.border.l * o->cur.border.scale) + (o->cur.border.r * o->cur.border.scale));
3590         if (*w < 0) *w = 0;
3591         *h = obj->cur.geometry.h - ((o->cur.border.t * o->cur.border.scale) + (o->cur.border.b * o->cur.border.scale));
3592         if (*h < 0) *h = 0;
3593      }
3594    return 1;
3595 }
3596
3597 static int
3598 evas_object_image_can_map(Evas_Object *obj __UNUSED__)
3599 {
3600    return 1;
3601 }
3602
3603 static void *
3604 evas_object_image_data_convert_internal(Evas_Object_Image *o, void *data, Evas_Colorspace to_cspace)
3605 {
3606    void *out = NULL;
3607
3608    if (!data)
3609      return NULL;
3610
3611    switch (o->cur.cspace)
3612      {
3613         case EVAS_COLORSPACE_ARGB8888:
3614           out = evas_common_convert_argb8888_to(data,
3615                                                 o->cur.image.w,
3616                                                 o->cur.image.h,
3617                                                 o->cur.image.stride >> 2,
3618                                                 o->cur.has_alpha,
3619                                                 to_cspace);
3620           break;
3621         case EVAS_COLORSPACE_RGB565_A5P:
3622           out = evas_common_convert_rgb565_a5p_to(data,
3623                                                   o->cur.image.w,
3624                                                   o->cur.image.h,
3625                                                   o->cur.image.stride >> 1,
3626                                                   o->cur.has_alpha,
3627                                                   to_cspace);
3628           break;
3629         default:
3630           break;
3631      }
3632
3633    return out;
3634 }
3635
3636 static void
3637 evas_object_image_filled_resize_listener(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *einfo __UNUSED__)
3638 {
3639    Evas_Coord w, h;
3640    Evas_Object_Image *o;
3641
3642    o = obj->object_data;
3643    evas_object_geometry_get(obj, NULL, NULL, &w, &h);
3644    evas_object_image_fill_set(obj, 0, 0, w, h);
3645 }
3646
3647
3648 Eina_Bool
3649 _evas_object_image_preloading_get(const Evas_Object *obj)
3650 {
3651    Evas_Object_Image *o = (Evas_Object_Image *)(obj->object_data);
3652    if (!o) return EINA_FALSE;
3653    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
3654    return EINA_FALSE;
3655    MAGIC_CHECK_END();
3656    return o->preloading;
3657 }
3658
3659 void
3660 _evas_object_image_preloading_set(Evas_Object *obj, Eina_Bool preloading)
3661 {
3662    Evas_Object_Image *o = (Evas_Object_Image *)(obj->object_data);
3663    o->preloading = preloading;
3664 }
3665
3666 void
3667 _evas_object_image_preloading_check(Evas_Object *obj)
3668 {
3669    Evas_Object_Image *o = (Evas_Object_Image *)(obj->object_data);
3670    if (obj->layer->evas->engine.func->image_load_error_get)
3671       o->load_error = obj->layer->evas->engine.func->image_load_error_get
3672       (obj->layer->evas->engine.data.output, o->engine_data);
3673 }
3674
3675 /* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-2f0^-2{2(0W1st0 :*/