move around - flatter.
[profile/ivi/evas.git] / src / lib / engines / common / evas_scale_smooth_scaler.c
1 void
2 SCALE_FUNC(RGBA_Image *src, RGBA_Image *dst,
3            RGBA_Draw_Context *dc,
4            int src_region_x, int src_region_y,
5            int src_region_w, int src_region_h,
6            int dst_region_x, int dst_region_y,
7            int dst_region_w, int dst_region_h)
8 {
9    DATA32  *dst_ptr;
10    int      dst_jump;
11    int      dst_clip_x, dst_clip_y, dst_clip_w, dst_clip_h;
12    int      src_w, src_h, dst_w, dst_h;
13
14    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)))
15      return;
16    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)))
17      return;
18
19    src_w = src->cache_entry.w;
20    src_h = src->cache_entry.h;
21    dst_w = dst->cache_entry.w;
22    dst_h = dst->cache_entry.h;
23
24    if (dc->clip.use)
25      {
26         dst_clip_x = dc->clip.x;
27         dst_clip_y = dc->clip.y;
28         dst_clip_w = dc->clip.w;
29         dst_clip_h = dc->clip.h;
30         if (dst_clip_x < 0)
31           {
32              dst_clip_w += dst_clip_x;
33              dst_clip_x = 0;
34           }
35         if (dst_clip_y < 0)
36           {
37              dst_clip_h += dst_clip_y;
38              dst_clip_y = 0;
39           }
40         if ((dst_clip_w <= 0) || (dst_clip_h <= 0)) return;
41         if ((dst_clip_x + dst_clip_w) > dst_w) dst_clip_w = dst_w - dst_clip_x;
42         if ((dst_clip_y + dst_clip_h) > dst_h) dst_clip_h = dst_h - dst_clip_y;
43      }
44    else
45      {
46         dst_clip_x = 0;
47         dst_clip_y = 0;
48         dst_clip_w = dst_w;
49         dst_clip_h = dst_h;
50      }
51
52    if (dst_clip_x < dst_region_x)
53      {
54         dst_clip_w += dst_clip_x - dst_region_x;
55         dst_clip_x = dst_region_x;
56      }
57    if ((dst_clip_x + dst_clip_w) > (dst_region_x + dst_region_w))
58      dst_clip_w = dst_region_x + dst_region_w - dst_clip_x;
59    if (dst_clip_y < dst_region_y)
60      {
61         dst_clip_h += dst_clip_y - dst_region_y;
62         dst_clip_y = dst_region_y;
63      }
64    if ((dst_clip_y + dst_clip_h) > (dst_region_y + dst_region_h))
65      dst_clip_h = dst_region_y + dst_region_h - dst_clip_y;
66
67    if ((src_region_w <= 0) || (src_region_h <= 0) ||
68        (dst_region_w <= 0) || (dst_region_h <= 0) ||
69        (dst_clip_w <= 0) || (dst_clip_h <= 0))
70      return;
71
72    /* sanitise x */
73    if (src_region_x < 0)
74      {
75         dst_region_x -= (src_region_x * dst_region_w) / src_region_w;
76         dst_region_w += (src_region_x * dst_region_w) / src_region_w;
77         src_region_w += src_region_x;
78         src_region_x = 0;
79      }
80    if (src_region_x >= src_w) return;
81    if ((src_region_x + src_region_w) > src_w)
82      {
83         dst_region_w = (dst_region_w * (src_w - src_region_x)) / (src_region_w);
84         src_region_w = src_w - src_region_x;
85      }
86    if (dst_region_w <= 0) return;
87    if (src_region_w <= 0) return;
88    if (dst_clip_x < 0)
89      {
90         dst_clip_w += dst_clip_x;
91         dst_clip_x = 0;
92      }
93    if (dst_clip_w <= 0) return;
94    if (dst_clip_x >= dst_w) return;
95    if (dst_clip_x < dst_region_x)
96      {
97         dst_clip_w += (dst_clip_x - dst_region_x);
98         dst_clip_x = dst_region_x;
99      }
100    if ((dst_clip_x + dst_clip_w) > dst_w)
101      {
102         dst_clip_w = dst_w - dst_clip_x;
103      }
104    if (dst_clip_w <= 0) return;
105
106    /* sanitise y */
107    if (src_region_y < 0)
108      {
109         dst_region_y -= (src_region_y * dst_region_h) / src_region_h;
110         dst_region_h += (src_region_y * dst_region_h) / src_region_h;
111         src_region_h += src_region_y;
112         src_region_y = 0;
113      }
114    if (src_region_y >= src_h) return;
115    if ((src_region_y + src_region_h) > src_h)
116      {
117         dst_region_h = (dst_region_h * (src_h - src_region_y)) / (src_region_h);
118         src_region_h = src_h - src_region_y;
119      }
120    if (dst_region_h <= 0) return;
121    if (src_region_h <= 0) return;
122    if (dst_clip_y < 0)
123      {
124         dst_clip_h += dst_clip_y;
125         dst_clip_y = 0;
126      }
127    if (dst_clip_h <= 0) return;
128    if (dst_clip_y >= dst_h) return;
129    if (dst_clip_y < dst_region_y)
130      {
131         dst_clip_h += (dst_clip_y - dst_region_y);
132         dst_clip_y = dst_region_y;
133      }
134    if ((dst_clip_y + dst_clip_h) > dst_h)
135      {
136         dst_clip_h = dst_h - dst_clip_y;
137      }
138    if (dst_clip_h <= 0) return;
139
140    /* figure out dst jump */
141    dst_jump = dst_w - dst_clip_w;
142
143    /* figure out dest start ptr */
144    dst_ptr = dst->image.data + dst_clip_x + (dst_clip_y * dst_w);
145
146 /* FIXME:
147  *
148  * things to do later for speedups:
149  *
150  * break upscale into 3 cases (as listed below - up:up, 1:up, up:1)
151  *
152  * break downscale into more cases (as listed below)
153  *
154  * roll func (blend/copy/cultiply/cmod) code into inner loop of scaler.
155  * (578 fps vs 550 in mmx upscale in evas demo - this means probably
156  *  a good 10-15% speedup over the func call, but means massively larger
157  *  code)
158  *
159  * anything involving downscaling has no mmx equivalent code and maybe the
160  * C could do with a little work.
161  *
162  * ---------------------------------------------------------------------------
163  *
164  * (1 = no scaling (1:1 ratio), + = scale up, - = scale down)
165  * (* == fully optimised mmx, # = fully optimised C)
166  *
167  * h:v mmx C
168  *
169  * 1:1 *   #
170  *
171  * +:+ *   #
172  * 1:+ *   #
173  * +:1 *   #
174  *
175  * 1:-
176  * -:1
177  * +:-
178  * -:+
179  * -:-
180  *
181  */
182
183    /* if 1:1 scale */
184    if ((dst_region_w == src_region_w) &&
185        (dst_region_h == src_region_h))
186      {
187 #include "evas_scale_smooth_scaler_noscale.c"
188      }
189    else
190      {
191         /* scaling up only - dont need anything except original */
192 //      if ((!dc->anti_alias) || ((dst_region_w >= src_region_w) && (dst_region_h >= src_region_h)))
193         if (((dst_region_w >= src_region_w) && (dst_region_h >= src_region_h)))
194           {
195 #include "evas_scale_smooth_scaler_up.c"
196              return;
197           }
198         else
199           /* scaling down... funkiness */
200           {
201 #include "evas_scale_smooth_scaler_down.c"
202              return;
203           }
204      }
205 }