move around - flatter.
[profile/ivi/evas.git] / src / lib / engines / common / evas_scale_sample.c
1 /*
2  * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
3  */
4
5 #include "evas_common.h"
6 #include "evas_blend_private.h"
7
8 void scale_rgba_in_to_out_clip_sample_internal(RGBA_Image *src, RGBA_Image *dst, RGBA_Draw_Context *dc, int src_region_x, int src_region_y, int src_region_w, int src_region_h, int dst_region_x, int dst_region_y, int dst_region_w, int dst_region_h);
9
10 #ifndef BUILD_SCALE_SMOOTH
11 #ifdef BUILD_SCALE_SAMPLE
12 EAPI void
13 evas_common_scale_rgba_in_to_out_clip_smooth(RGBA_Image *src, RGBA_Image *dst,
14                                  RGBA_Draw_Context *dc,
15                                  int src_region_x, int src_region_y,
16                                  int src_region_w, int src_region_h,
17                                  int dst_region_x, int dst_region_y,
18                                  int dst_region_w, int dst_region_h)
19 {
20    evas_common_scale_rgba_in_to_out_clip_sample(src, dst, dc,
21                                     src_region_x, src_region_y,
22                                     src_region_w, src_region_h,
23                                     dst_region_x, dst_region_y,
24                                     dst_region_w, dst_region_h);
25 }
26 #endif
27 #endif
28
29 #ifdef BUILD_SCALE_SAMPLE
30 EAPI void
31 evas_common_scale_rgba_in_to_out_clip_sample(RGBA_Image *src, RGBA_Image *dst,
32                                  RGBA_Draw_Context *dc,
33                                  int src_region_x, int src_region_y,
34                                  int src_region_w, int src_region_h,
35                                  int dst_region_x, int dst_region_y,
36                                  int dst_region_w, int dst_region_h)
37 {
38    Cutout_Rects *rects;
39    Cutout_Rect  *r;
40    int          c, cx, cy, cw, ch;
41    int          i;
42    /* handle cutouts here! */
43
44    if ((dst_region_w <= 0) || (dst_region_h <= 0)) return;
45    if (!(RECTS_INTERSECT(dst_region_x, dst_region_y, dst_region_w, dst_region_h, 0, 0, dst->cache_entry.w, dst->cache_entry.h)))
46      return;
47    /* no cutouts - cut right to the chase */
48    if (!dc->cutout.rects)
49      {
50         scale_rgba_in_to_out_clip_sample_internal(src, dst, dc,
51                                                   src_region_x, src_region_y,
52                                                   src_region_w, src_region_h,
53                                                   dst_region_x, dst_region_y,
54                                                   dst_region_w, dst_region_h);
55         return;
56      }
57    /* save out clip info */
58    c = dc->clip.use; cx = dc->clip.x; cy = dc->clip.y; cw = dc->clip.w; ch = dc->clip.h;
59    evas_common_draw_context_clip_clip(dc, 0, 0, dst->cache_entry.w, dst->cache_entry.h);
60    evas_common_draw_context_clip_clip(dc, dst_region_x, dst_region_y, dst_region_w, dst_region_h);
61    /* our clip is 0 size.. abort */
62    if ((dc->clip.w <= 0) || (dc->clip.h <= 0))
63      {
64         dc->clip.use = c; dc->clip.x = cx; dc->clip.y = cy; dc->clip.w = cw; dc->clip.h = ch;
65         return;
66      }
67    rects = evas_common_draw_context_apply_cutouts(dc);
68    for (i = 0; i < rects->active; ++i)
69      {
70         r = rects->rects + i;
71         evas_common_draw_context_set_clip(dc, r->x, r->y, r->w, r->h);
72         scale_rgba_in_to_out_clip_sample_internal(src, dst, dc,
73                                                   src_region_x, src_region_y,
74                                                   src_region_w, src_region_h,
75                                                   dst_region_x, dst_region_y,
76                                                   dst_region_w, dst_region_h);
77
78      }
79    evas_common_draw_context_apply_clear_cutouts(rects);
80    /* restore clip info */
81    dc->clip.use = c; dc->clip.x = cx; dc->clip.y = cy; dc->clip.w = cw; dc->clip.h = ch;
82 }
83
84 void
85 scale_rgba_in_to_out_clip_sample_internal(RGBA_Image *src, RGBA_Image *dst,
86                                           RGBA_Draw_Context *dc,
87                                           int src_region_x, int src_region_y,
88                                           int src_region_w, int src_region_h,
89                                           int dst_region_x, int dst_region_y,
90                                           int dst_region_w, int dst_region_h)
91 {
92    int      x, y;
93    int     *lin_ptr;
94    DATA32  *buf, *dptr;
95    DATA32 **row_ptr;
96    DATA32  *ptr, *dst_ptr, *src_data, *dst_data;
97    int      dst_jump;
98    int      dst_clip_x, dst_clip_y, dst_clip_w, dst_clip_h;
99    int      src_w, src_h, dst_w, dst_h;
100    RGBA_Gfx_Func func;
101
102    if (!(RECTS_INTERSECT(dst_region_x, dst_region_y, dst_region_w, dst_region_h, 0, 0, dst->cache_entry.w, dst->cache_entry.h)))
103      return;
104    if (!(RECTS_INTERSECT(src_region_x, src_region_y, src_region_w, src_region_h, 0, 0, src->cache_entry.w, src->cache_entry.h)))
105      return;
106
107    src_w = src->cache_entry.w;
108    src_h = src->cache_entry.h;
109    dst_w = dst->cache_entry.w;
110    dst_h = dst->cache_entry.h;
111
112    src_data = src->image.data;
113    dst_data = dst->image.data;
114
115    if (dc->clip.use)
116      {
117         dst_clip_x = dc->clip.x;
118         dst_clip_y = dc->clip.y;
119         dst_clip_w = dc->clip.w;
120         dst_clip_h = dc->clip.h;
121         if (dst_clip_x < 0)
122           {
123              dst_clip_w += dst_clip_x;
124              dst_clip_x = 0;
125           }
126         if (dst_clip_y < 0)
127           {
128              dst_clip_h += dst_clip_y;
129              dst_clip_y = 0;
130           }
131         if ((dst_clip_x + dst_clip_w) > dst_w)
132           dst_clip_w = dst_w - dst_clip_x;
133         if ((dst_clip_y + dst_clip_h) > dst_h)
134           dst_clip_h = dst_h - dst_clip_y;
135      }
136    else
137      {
138         dst_clip_x = 0;
139         dst_clip_y = 0;
140         dst_clip_w = dst_w;
141         dst_clip_h = dst_h;
142      }
143
144    if (dst_clip_x < dst_region_x)
145      {
146         dst_clip_w += dst_clip_x - dst_region_x;
147         dst_clip_x = dst_region_x;
148      }
149    if ((dst_clip_x + dst_clip_w) > (dst_region_x + dst_region_w))
150      dst_clip_w = dst_region_x + dst_region_w - dst_clip_x;
151    if (dst_clip_y < dst_region_y)
152      {
153         dst_clip_h += dst_clip_y - dst_region_y;
154         dst_clip_y = dst_region_y;
155      }
156    if ((dst_clip_y + dst_clip_h) > (dst_region_y + dst_region_h))
157      dst_clip_h = dst_region_y + dst_region_h - dst_clip_y;
158
159    if ((src_region_w <= 0) || (src_region_h <= 0) ||
160        (dst_region_w <= 0) || (dst_region_h <= 0) ||
161        (dst_clip_w <= 0) || (dst_clip_h <= 0))
162      return;
163
164    /* sanitise x */
165    if (src_region_x < 0)
166      {
167         dst_region_x -= (src_region_x * dst_region_w) / src_region_w;
168         dst_region_w += (src_region_x * dst_region_w) / src_region_w;
169         src_region_w += src_region_x;
170         src_region_x = 0;
171      }
172    if (src_region_x >= src_w) return;
173    if ((src_region_x + src_region_w) > src_w)
174      {
175         dst_region_w = (dst_region_w * (src_w - src_region_x)) / (src_region_w);
176         src_region_w = src_w - src_region_x;
177      }
178    if (dst_region_w <= 0) return;
179    if (src_region_w <= 0) return;
180    if (dst_clip_x < 0)
181      {
182         dst_clip_w += dst_clip_x;
183         dst_clip_x = 0;
184      }
185    if (dst_clip_w <= 0) return;
186    if (dst_clip_x >= dst_w) return;
187    if (dst_clip_x < dst_region_x)
188      {
189         dst_clip_w += (dst_clip_x - dst_region_x);
190         dst_clip_x = dst_region_x;
191      }
192    if ((dst_clip_x + dst_clip_w) > dst_w)
193      {
194         dst_clip_w = dst_w - dst_clip_x;
195      }
196    if (dst_clip_w <= 0) return;
197
198    /* sanitise y */
199    if (src_region_y < 0)
200      {
201         dst_region_y -= (src_region_y * dst_region_h) / src_region_h;
202         dst_region_h += (src_region_y * dst_region_h) / src_region_h;
203         src_region_h += src_region_y;
204         src_region_y = 0;
205      }
206    if (src_region_y >= src_h) return;
207    if ((src_region_y + src_region_h) > src_h)
208      {
209         dst_region_h = (dst_region_h * (src_h - src_region_y)) / (src_region_h);
210         src_region_h = src_h - src_region_y;
211      }
212    if (dst_region_h <= 0) return;
213    if (src_region_h <= 0) return;
214    if (dst_clip_y < 0)
215      {
216         dst_clip_h += dst_clip_y;
217         dst_clip_y = 0;
218      }
219    if (dst_clip_h <= 0) return;
220    if (dst_clip_y >= dst_h) return;
221    if (dst_clip_y < dst_region_y)
222      {
223         dst_clip_h += (dst_clip_y - dst_region_y);
224         dst_clip_y = dst_region_y;
225      }
226    if ((dst_clip_y + dst_clip_h) > dst_h)
227      {
228         dst_clip_h = dst_h - dst_clip_y;
229      }
230    if (dst_clip_h <= 0) return;
231
232    /* allocate scale lookup tables */
233    lin_ptr = alloca(dst_clip_w * sizeof(int));
234    row_ptr = alloca(dst_clip_h * sizeof(DATA32 *));
235
236    /* figure out dst jump */
237    dst_jump = dst_w - dst_clip_w;
238
239    /* figure out dest start ptr */
240    dst_ptr = dst_data + dst_clip_x + (dst_clip_y * dst_w);
241
242    if (dc->mul.use)
243      func = evas_common_gfx_func_composite_pixel_color_span_get(src, dc->mul.col, dst, dst_clip_w, dc->render_op);
244    else
245      func = evas_common_gfx_func_composite_pixel_span_get(src, dst, dst_clip_w, dc->render_op);
246
247    if ((dst_region_w == src_region_w) && (dst_region_h == src_region_h))
248      {
249         ptr = src_data + ((dst_clip_y - dst_region_y + src_region_y) * src_w) + (dst_clip_x - dst_region_x) + src_region_x;
250         for (y = 0; y < dst_clip_h; y++)
251           {
252             /* * blend here [clip_w *] ptr -> dst_ptr * */
253 #ifdef EVAS_SLI
254              if (((y + dst_clip_y) % dc->sli.h) == dc->sli.y)
255 #endif
256                {
257                   func(ptr, NULL, dc->mul.col, dst_ptr, dst_clip_w);
258                }
259             ptr += src_w;
260             dst_ptr += dst_w;
261           }
262      }
263    else
264      {
265        /* fill scale tables */
266         for (x = 0; x < dst_clip_w; x++)
267             lin_ptr[x] = (((x + dst_clip_x - dst_region_x) * src_region_w) / dst_region_w) + src_region_x;
268         for (y = 0; y < dst_clip_h; y++)
269             row_ptr[y] = src_data + (((((y + dst_clip_y - dst_region_y) * src_region_h) / dst_region_h)
270                         + src_region_y) * src_w);
271         /* scale to dst */
272         dptr = dst_ptr;
273 #ifdef DIRECT_SCALE
274         if ((!src->cache_entry.flags.alpha) &&
275              (!dst->cache_entry.flags.alpha) &&
276              (!dc->mul.use))
277           {
278              for (y = 0; y < dst_clip_h; y++)
279                {
280 #ifdef EVAS_SLI
281                  if (((y + dst_clip_y) % dc->sli.h) == dc->sli.y)
282 #endif
283                    {
284                       dst_ptr = dptr;
285                       for (x = 0; x < dst_clip_w; x++)
286                         {
287                            ptr = row_ptr[y] + lin_ptr[x];
288                            *dst_ptr = *ptr;
289                            dst_ptr++;
290                         }
291                    }
292                  dptr += dst_w;
293               }
294           }
295         else
296 #endif
297           {
298             /* a scanline buffer */
299             buf = alloca(dst_clip_w * sizeof(DATA32));
300             for (y = 0; y < dst_clip_h; y++)
301               {
302 #ifdef EVAS_SLI
303                  if (((y + dst_clip_y) % dc->sli.h) == dc->sli.y)
304 #endif
305                    {
306                       dst_ptr = buf;
307                       for (x = 0; x < dst_clip_w; x++)
308                         {
309                            ptr = row_ptr[y] + lin_ptr[x];
310                            *dst_ptr = *ptr;
311                            dst_ptr++;
312                         }
313                       /* * blend here [clip_w *] buf -> dptr * */
314                       func(buf, NULL, dc->mul.col, dptr, dst_clip_w);
315                    }
316                 dptr += dst_w;
317               }
318           }
319      }
320 }
321 #else
322 #ifdef BUILD_SCALE_SMOOTH
323 EAPI void
324 evas_common_scale_rgba_in_to_out_clip_sample(RGBA_Image *src, RGBA_Image *dst,
325                                  RGBA_Draw_Context *dc,
326                                  int src_region_x, int src_region_y,
327                                  int src_region_w, int src_region_h,
328                                  int dst_region_x, int dst_region_y,
329                                  int dst_region_w, int dst_region_h)
330 {
331    evas_common_scale_rgba_in_to_out_clip_smooth(src, dst, dc,
332                                     src_region_x, src_region_y,
333                                     src_region_w, src_region_h,
334                                     dst_region_x, dst_region_y,
335                                     dst_region_w, dst_region_h);
336 }
337 #endif
338 #endif