move around - flatter.
[profile/ivi/evas.git] / src / lib / engines / common_16 / evas_soft16_main.c
1 #include "evas_common_soft16.h"
2
3 static Evas_Cache_Image *eci = NULL;
4 static int               reference = 0;
5
6 static Image_Entry      *_evas_common_soft16_image_new(void);
7 static void              _evas_common_soft16_image_delete(Image_Entry *ie);
8
9 static int               _evas_common_soft16_image_surface_alloc(Image_Entry *ie, int w, int h);
10 static void              _evas_common_soft16_image_surface_delete(Image_Entry *ie);
11 static DATA32           *_evas_common_soft16_image_surface_pixels(Image_Entry *ie);
12
13 static int               _evas_common_load_soft16_image_from_file(Image_Entry *ie);
14 static void              _evas_common_soft16_image_unload(Image_Entry *ie);
15
16 static void              _evas_common_soft16_image_dirty_region(Image_Entry *im, int x, int y, int w, int h);
17 static int               _evas_common_soft16_image_dirty(Image_Entry *ie_dst, const Image_Entry *ie_src);
18
19 static int               _evas_common_soft16_image_ram_usage(Image_Entry *ie);
20
21 static int               _evas_common_soft16_image_size_set(Image_Entry *ie_dst, const Image_Entry *ie_im, int w, int h);
22 static int               _evas_common_soft16_image_from_copied_data(Image_Entry* ie_dst, int w, int h, DATA32 *image_data, int alpha, int cspace);
23 static int               _evas_common_soft16_image_from_data(Image_Entry* ie_dst, int w, int h, DATA32 *image_data, int alpha, int cspace);
24 static int               _evas_common_soft16_image_colorspace_set(Image_Entry* ie_dst, int cspace);
25
26 static int               _evas_common_load_soft16_image_data_from_file(Image_Entry *ie);
27
28 static void
29 _evas_common_soft16_image_debug(const char* context, Image_Entry *eim)
30 {
31    fprintf(stderr, "[16] %p = [%s] {%s,%s} %i [%i|%i]\n", eim, context, eim->file, eim->key, eim->references, eim->w, eim->h);
32 }
33
34 static const Evas_Cache_Image_Func      _evas_common_soft16_image_func =
35 {
36    _evas_common_soft16_image_new,
37    _evas_common_soft16_image_delete,
38    _evas_common_soft16_image_surface_alloc,
39    _evas_common_soft16_image_surface_delete,
40    _evas_common_soft16_image_surface_pixels,
41    _evas_common_load_soft16_image_from_file,
42    _evas_common_soft16_image_unload,
43    _evas_common_soft16_image_dirty_region,
44    _evas_common_soft16_image_dirty,
45    _evas_common_soft16_image_size_set,
46    _evas_common_soft16_image_from_copied_data,
47    _evas_common_soft16_image_from_data,
48    _evas_common_soft16_image_colorspace_set,
49    _evas_common_load_soft16_image_data_from_file,
50    _evas_common_soft16_image_ram_usage,
51 /*    _evas_common_soft16_image_debug */
52    NULL
53 };
54
55 EAPI void
56 evas_common_soft16_image_init(void)
57 {
58    if (!eci)
59      eci = evas_cache_image_init(&_evas_common_soft16_image_func);
60    reference++;
61 }
62
63 EAPI void
64 evas_common_soft16_image_shutdown(void)
65 {
66    if (--reference == 0)
67      {
68 // DISABLE for now - something wrong with cache shutdown freeing things
69 // still in use - rage_thumb segv's now.
70 // 
71 // actually - i think i see it. cache ref goes to 0 (and thus gets freed)
72 // because in eng_setup() when a buffer changes size it is FIRST freed
73 // THEN allocated again - thus brignhjing ref to 0 then back to 1 immediately
74 // where it should stay at 1. - see evas_engine.c in the buffer enigne for
75 // example. eng_output_free() is called BEFORE _output_setup(). although this
76 // is only a SIGNE of the problem. we can patch this up with either freeing
77 // after the setup (so we just pt a ref of 2 then back to 1), or just 
78 // evas_common_image_init() at the start and evas_common_image_shutdown()
79 // after it all. really ref 0 should only be reached when no more canvases
80 // with no more objects exist anywhere.
81 //        evas_cache_image_shutdown(eci);
82 //        eci = NULL;
83      }
84 }
85
86 EAPI Evas_Cache_Image *
87 evas_common_soft16_image_cache_get(void)
88 {
89    return eci;
90 }
91
92 static Image_Entry *
93 _evas_common_soft16_image_new(void)
94 {
95    Soft16_Image *im;
96
97    im = calloc(1, sizeof(Soft16_Image));
98    if (!im) return NULL;
99
100    im->stride = -1;
101
102    return (Image_Entry *) im;
103 }
104
105 static void
106 _evas_common_soft16_image_delete(Image_Entry *ie)
107 {
108    memset(ie, 0xFF, sizeof (Soft16_Image));
109    free(ie);
110 }
111
112 static int
113 _evas_common_soft16_image_surface_alloc(Image_Entry *ie, int w, int h)
114 {
115    Soft16_Image *im = (Soft16_Image *) ie;
116
117    if (im->stride < 0) im->stride = _calc_stride(w);
118
119    im->pixels = realloc(im->pixels, IMG_BYTE_SIZE(im->stride, h, ie->flags.alpha));
120    if (!im->pixels) return -1;
121
122    if (ie->flags.alpha)
123      {
124         im->alpha = (DATA8 *)(im->pixels + (im->stride * h));
125         im->flags.free_alpha = 0;
126      }
127    im->flags.free_pixels = 1;
128
129    return 0;
130 }
131
132 static void
133 _evas_common_soft16_image_surface_delete(Image_Entry *ie)
134 {
135    Soft16_Image *im = (Soft16_Image *) ie;
136
137    if (im->flags.free_pixels)
138      free(im->pixels);
139    im->pixels = NULL;
140    im->flags.free_pixels = 0;
141
142    if (im->flags.free_alpha)
143      free(im->alpha);
144    im->alpha = NULL;
145    im->flags.free_alpha = 0;
146 }
147
148 static DATA32 *
149 _evas_common_soft16_image_surface_pixels(Image_Entry *ie)
150 {
151    abort();
152
153    return NULL;
154 }
155
156 static int
157 _evas_common_load_soft16_image_from_file(Image_Entry *ie)
158 {
159    Soft16_Image *sim = (Soft16_Image *) ie;
160    RGBA_Image   *im;
161    int           error = 0;
162
163    im = (RGBA_Image *) evas_cache_image_request(evas_common_image_cache_get(), sim->cache_entry.file, sim->cache_entry.key, &sim->cache_entry.load_opts, &error);
164    sim->source = im;
165    if (!sim->source) return -1;
166
167    sim->cache_entry.w = sim->source->cache_entry.w;
168    sim->cache_entry.h = sim->source->cache_entry.h;
169    ie->flags.alpha = im->cache_entry.flags.alpha;
170    if (sim->stride < 0) sim->stride = _calc_stride(sim->cache_entry.w);
171
172    return 0;
173 }
174
175 static void
176 _evas_common_soft16_image_unload(Image_Entry *ie)
177 {
178 }
179
180 static void
181 _evas_common_soft16_image_dirty_region(Image_Entry *im, int x, int y, int w, int h)
182 {
183 }
184
185 static int
186 _evas_common_soft16_image_dirty(Image_Entry *ie_dst, const Image_Entry *ie_src)
187 {
188    Soft16_Image *dst = (Soft16_Image *) ie_dst;
189    Soft16_Image *src = (Soft16_Image *) ie_src;
190
191    evas_cache_image_load_data(&src->cache_entry);
192    evas_cache_image_surface_alloc(&dst->cache_entry,
193                                   src->cache_entry.w, src->cache_entry.h);
194
195 /*    evas_common_blit_rectangle(src, dst, 0, 0, src->cache_entry.w, src->cache_entry.h, 0, 0); */
196
197    return 0;
198 }
199
200 static int
201 _evas_common_soft16_image_ram_usage(Image_Entry *ie)
202 {
203    Soft16_Image *im = (Soft16_Image *) ie;
204
205    if (im->pixels && im->flags.free_pixels)
206      return IMG_BYTE_SIZE(im->stride, im->cache_entry.h, ie->flags.alpha);
207    return 0;
208 }
209
210 static int
211 _evas_common_soft16_image_size_set(Image_Entry *ie_dst, const Image_Entry *ie_im, int w, int h)
212 {
213    Soft16_Image *dst = (Soft16_Image *) ie_dst;
214    Soft16_Image *im = (Soft16_Image *) ie_im;
215
216    dst->flags = im->flags;
217
218    return 0;
219 }
220
221 static int
222 _evas_common_soft16_image_from_data(Image_Entry* ie_dst, int w, int h, DATA32 *image_data, int alpha, int cspace)
223 {
224    Soft16_Image *im = (Soft16_Image *) ie_dst;
225
226    /* FIXME: handle colorspace */
227    ie_dst->w = w;
228    ie_dst->h = h;
229    ie_dst->flags.alpha = alpha;
230
231    im->flags.free_pixels = 0;
232    im->flags.free_alpha = 0;
233
234    /* FIXME: That's bad, the application must be aware of the engine internal. */
235    im->pixels = (DATA16 *) image_data;
236    if (ie_dst->flags.alpha)
237      im->alpha = (DATA8 *)(im->pixels + (im->stride * h));
238
239    return 0;
240 }
241
242 static int
243 _evas_common_soft16_image_from_copied_data(Image_Entry* ie_dst, int w, int h, DATA32 *image_data, int alpha, int cspace)
244 {
245    Soft16_Image *im = (Soft16_Image *) ie_dst;
246
247    /* FIXME: handle colorspace */
248    if (image_data)
249      memcpy(im->pixels, image_data, IMG_BYTE_SIZE(im->stride, h, ie_dst->flags.alpha));
250    else
251      memset(im->pixels, 0, IMG_BYTE_SIZE(im->stride, h, ie_dst->flags.alpha));
252
253    return 0;
254 }
255
256 static int
257 _evas_common_soft16_image_colorspace_set(Image_Entry* ie_dst, int cspace)
258 {
259    /* FIXME: handle colorspace */
260    return 0;
261 }
262
263 static int
264 _evas_common_load_soft16_image_data_from_file(Image_Entry *ie)
265 {
266    Soft16_Image *im = (Soft16_Image *) ie;
267
268    if (im->pixels) return 0;
269    if (!im->source) return -1;
270
271    evas_cache_image_load_data(&im->source->cache_entry);
272    if (im->source->image.data)
273      {
274         DATA32 *sp;
275
276         evas_cache_image_surface_alloc(&im->cache_entry,
277                                        im->source->cache_entry.w,
278                                        im->source->cache_entry.h);
279
280         sp = im->source->image.data;
281         if (im->alpha)
282           soft16_image_convert_from_rgba(im, sp);
283         else
284           soft16_image_convert_from_rgb(im, sp);
285      }
286    evas_cache_image_drop(&im->source->cache_entry);
287    im->source = NULL;
288
289    return 0;
290 }
291
292 /* Soft16_Image * */
293 /* soft16_image_new(int w, int h, int stride, int have_alpha, DATA16 *pixels, */
294 /*               int copy) */
295 /* { */
296 /*    Soft16_Image *im; */
297
298 /*    if (stride < 0) stride = _calc_stride(w); */
299
300 /*    im = soft16_image_alloc(w, h, stride, have_alpha, copy); */
301 /*    if (!im) return NULL; */
302
303 /*    if (pixels) */
304 /*      { */
305 /*      if (copy) */
306 /*        memcpy(im->pixels, pixels, IMG_BYTE_SIZE(stride, h, have_alpha)); */
307 /*      else */
308 /*        { */
309 /*           im->pixels = pixels; */
310 /*           if (have_alpha) im->alpha = (DATA8 *)(im->pixels + (stride * h)); */
311 /*        } */
312 /*      } */
313 /*    return im; */
314 /* } */
315
316 static inline void
317 _get_clip(const RGBA_Draw_Context *dc, const Soft16_Image *im,
318           Evas_Rectangle *clip)
319 {
320    if (dc->clip.use)
321      {
322         clip->x = dc->clip.x;
323         clip->y = dc->clip.y;
324         clip->w = dc->clip.w;
325         clip->h = dc->clip.h;
326         if (clip->x < 0)
327           {
328              clip->w += clip->x;
329              clip->x = 0;
330           }
331         if (clip->y < 0)
332           {
333              clip->h += clip->y;
334              clip->y = 0;
335           }
336         if ((clip->x + clip->w) > im->cache_entry.w) clip->w = im->cache_entry.w - clip->x;
337         if ((clip->y + clip->h) > im->cache_entry.h) clip->h = im->cache_entry.h - clip->y;
338      }
339    else
340      {
341         clip->x = 0;
342         clip->y = 0;
343         clip->w = im->cache_entry.w;
344         clip->h = im->cache_entry.h;
345      }
346 }
347
348 static inline int
349 _is_empty_rectangle(const Evas_Rectangle *r)
350 {
351    return (r->w < 1) || (r->h < 1);
352 }
353
354 static inline void
355 _shrink(int *s_pos, int *s_size, int pos, int size)
356 {
357    int d;
358
359    d = (*s_pos) - pos;
360    if (d < 0)
361      {
362         (*s_size) += d;
363         (*s_pos) = pos;
364      }
365
366    d = size + pos - (*s_pos);
367    if ((*s_size) > d)
368      (*s_size) = d;
369 }
370
371 static int
372 _soft16_adjust_areas(Evas_Rectangle *src,
373                      int src_max_x, int src_max_y,
374                      Evas_Rectangle *dst,
375                      int dst_max_x, int dst_max_y,
376                      Evas_Rectangle *dst_clip)
377 {
378    if (_is_empty_rectangle(src) ||
379        _is_empty_rectangle(dst) ||
380        _is_empty_rectangle(dst_clip))
381      return 0;
382
383    /* shrink clip */
384    _shrink(&dst_clip->x, &dst_clip->w, dst->x, dst->w);
385    _shrink(&dst_clip->y, &dst_clip->h, dst->y, dst->h);
386    if (_is_empty_rectangle(dst_clip)) return 0;
387
388    /* sanitise x */
389    if (src->x < 0)
390      {
391         dst->x -= (src->x * dst->w) / src->w;
392         dst->w += (src->x * dst->w) / src->w;
393         src->w += src->x;
394         src->x = 0;
395      }
396    if (src->x >= src_max_x) return 0;
397    if ((src->x + src->w) > src_max_x)
398      {
399         dst->w = (dst->w * (src_max_x - src->x)) / (src->w);
400         src->w = src_max_x - src->x;
401      }
402    if (dst->w <= 0) return 0;
403    if (src->w <= 0) return 0;
404    if (dst_clip->x < 0)
405      {
406         dst_clip->w += dst_clip->x;
407         dst_clip->x = 0;
408      }
409    if (dst_clip->w <= 0) return 0;
410    if (dst_clip->x >= dst_max_x) return 0;
411
412    _shrink(&dst_clip->x, &dst_clip->w, 0, dst_max_x);
413    if (dst_clip->w <= 0) return 0;
414
415    /* sanitise y */
416    if (src->y < 0)
417      {
418         dst->y -= (src->y * dst->h) / src->h;
419         dst->h += (src->y * dst->h) / src->h;
420         src->h += src->y;
421         src->y = 0;
422      }
423    if (src->y >= src_max_y) return 0;
424    if ((src->y + src->h) > src_max_y)
425      {
426         dst->h = (dst->h * (src_max_y - src->y)) / (src->h);
427         src->h = src_max_y - src->y;
428      }
429    if (dst->h <= 0) return 0;
430    if (src->h <= 0) return 0;
431    if (dst_clip->y < 0)
432      {
433         dst_clip->h += dst_clip->y;
434         dst_clip->y = 0;
435      }
436    if (dst_clip->h <= 0) return 0;
437    if (dst_clip->y >= dst_max_y) return 0;
438
439    _shrink(&dst_clip->y, &dst_clip->h, 0, dst_max_y);
440    if (dst_clip->h <= 0) return 0;
441
442    return 1;
443 }
444
445 static void
446 _soft16_image_draw_sampled_int(Soft16_Image *src, Soft16_Image *dst,
447                                RGBA_Draw_Context *dc,
448                                Evas_Rectangle sr, Evas_Rectangle dr)
449 {
450    Evas_Rectangle cr;
451
452    if (!(RECTS_INTERSECT(dr.x, dr.y, dr.w, dr.h, 0, 0, dst->cache_entry.w, dst->cache_entry.h)))
453      return;
454    if (!(RECTS_INTERSECT(sr.x, sr.y, sr.w, sr.h, 0, 0, src->cache_entry.w, src->cache_entry.h)))
455      return;
456
457    _get_clip(dc, dst, &cr);
458    if (!_soft16_adjust_areas(&sr, src->cache_entry.w, src->cache_entry.h, &dr, dst->cache_entry.w, dst->cache_entry.h, &cr))
459      return;
460
461    if ((dr.w == sr.w) && (dr.h == sr.h))
462      soft16_image_draw_unscaled(src, dst, dc, sr, dr, cr);
463    else
464      soft16_image_draw_scaled_sampled(src, dst, dc, sr, dr, cr);
465 }
466
467 EAPI void
468 soft16_image_draw(Soft16_Image *src, Soft16_Image *dst,
469                   RGBA_Draw_Context *dc,
470                   int src_region_x, int src_region_y,
471                   int src_region_w, int src_region_h,
472                   int dst_region_x, int dst_region_y,
473                   int dst_region_w, int dst_region_h,
474                   int smooth)
475 {
476    Evas_Rectangle sr, dr;
477    Cutout_Rects *rects;
478    Cutout_Rect  *r;
479    struct RGBA_Draw_Context_clip clip_bkp;
480    int i;
481
482    /* handle cutouts here! */
483    dr.x = dst_region_x;
484    dr.y = dst_region_y;
485    dr.w = dst_region_w;
486    dr.h = dst_region_h;
487
488    if (_is_empty_rectangle(&dr)) return;
489    if (!(RECTS_INTERSECT(dr.x, dr.y, dr.w, dr.h, 0, 0, dst->cache_entry.w, dst->cache_entry.h)))
490      return;
491
492    sr.x = src_region_x;
493    sr.y = src_region_y;
494    sr.w = src_region_w;
495    sr.h = src_region_h;
496
497    if (_is_empty_rectangle(&sr)) return;
498    if (!(RECTS_INTERSECT(sr.x, sr.y, sr.w, sr.h, 0, 0, src->cache_entry.w, src->cache_entry.h)))
499      return;
500
501    /* no cutouts - cut right to the chase */
502    if (!dc->cutout.rects)
503      {
504         _soft16_image_draw_sampled_int(src, dst, dc, sr, dr);
505         return;
506      }
507
508    /* save out clip info */
509    clip_bkp = dc->clip;
510    evas_common_draw_context_clip_clip(dc, 0, 0, dst->cache_entry.w, dst->cache_entry.h);
511    evas_common_draw_context_clip_clip(dc, dst_region_x, dst_region_y, dst_region_w, dst_region_h);
512    /* our clip is 0 size.. abort */
513    if ((dc->clip.w <= 0) || (dc->clip.h <= 0))
514      {
515         dc->clip = clip_bkp;
516         return;
517      }
518    rects = evas_common_draw_context_apply_cutouts(dc);
519    for (i = 0; i < rects->active; i++)
520      {
521         r = rects->rects + i;
522         evas_common_draw_context_set_clip(dc, r->x, r->y, r->w, r->h);
523         _soft16_image_draw_sampled_int(src, dst, dc, sr, dr);
524      }
525    evas_common_draw_context_apply_clear_cutouts(rects);
526    dc->clip = clip_bkp;
527 }
528
529 EAPI Soft16_Image *
530 soft16_image_alpha_set(Soft16_Image *im, int have_alpha)
531 {
532    Soft16_Image   *new_im;
533
534    if (im->cache_entry.flags.alpha == have_alpha) return im;
535
536    new_im = (Soft16_Image *) evas_cache_image_alone(&im->cache_entry);
537
538    new_im->cache_entry.flags.alpha = have_alpha;
539
540    if (im->cache_entry.w > 0
541        && im->cache_entry.h)
542      new_im = (Soft16_Image *) evas_cache_image_size_set(&new_im->cache_entry, im->cache_entry.w, im->cache_entry.h);
543
544    return new_im;
545 }
546
547 /* Soft16_Image * */
548 /* soft16_image_size_set(Soft16_Image *old_im, int w, int h) */
549 /* { */
550 /*    Soft16_Image *new_im; */
551 /*    DATA16 *dp, *sp; */
552 /*    int i, cw, ch, ew; */
553
554 /*    if ((old_im->cache_entry.w == w) && (old_im->cache_entry.h == h)) return old_im; */
555
556 /*    new_im = soft16_image_new(w, h, -1, old_im->flags.have_alpha, NULL, 1); */
557
558 /*    if (old_im->cache_entry.w < new_im->cache_entry.w) */
559 /*      cw = old_im->cache_entry.w; */
560 /*    else */
561 /*      cw = new_im->cache_entry.w; */
562
563 /*    ew = new_im->cache_entry.w - cw; */
564
565 /*    if (old_im->cache_entry.h < new_im->cache_entry.h) */
566 /*      ch = old_im->cache_entry.h; */
567 /*    else */
568 /*      ch = new_im->cache_entry.h; */
569
570 /*    dp = new_im->pixels; */
571 /*    sp = old_im->pixels; */
572 /*    for (i = 0; i < ch; i++) */
573 /*      { */
574 /*      memcpy(dp, sp, cw * sizeof(DATA16)); */
575 /*      if (ew > 0) memset(dp, 0, ew * sizeof(DATA16)); */
576
577 /*      dp += new_im->stride; */
578 /*      sp += old_im->stride; */
579 /*      } */
580
581 /*    if (old_im->flags.have_alpha) */
582 /*      { */
583 /*      DATA8 *dp, *sp; */
584
585 /*      dp = new_im->alpha; */
586 /*      sp = old_im->alpha; */
587 /*      for (i = 0; i < ch; i++) */
588 /*        { */
589 /*           memcpy(dp, sp, cw * sizeof(DATA8)); */
590 /*           if (ew > 0) memset(dp, 0, ew * sizeof(DATA8)); */
591
592 /*           dp += new_im->stride; */
593 /*           sp += old_im->stride; */
594 /*        } */
595 /*      } */
596
597 /*    evas_cache_image_drop(&old_im->cache_entry); */
598 /*    return new_im; */
599 /* } */