move around - flatter.
[profile/ivi/evas.git] / src / lib / engines / common_16 / evas_soft16_line.c
1 #include "evas_common_soft16.h"
2 #include "evas_soft16_scanline_fill.c"
3
4 /*
5  * All functions except by soft16_line_draw() expect x0 <= x1.
6  */
7
8 static inline int
9 _in_range(int value, int min, int max)
10 {
11    return min <= value && value <= max;
12 }
13
14 static inline int
15 _is_xy_inside_clip(int x, int y, const struct RGBA_Draw_Context_clip clip)
16 {
17    if (!clip.use)
18      return 1;
19
20    if (!_in_range(x, clip.x, clip.x + clip.w - 1))
21      return 0;
22
23    if (!_in_range(y, clip.y, clip.y + clip.h - 1))
24      return 0;
25
26    return 1;
27 }
28
29 static inline int
30 _is_x_inside_clip(int x, const struct RGBA_Draw_Context_clip clip)
31 {
32    if (!clip.use)
33      return 1;
34
35    return _in_range(x, clip.x, clip.x + clip.w - 1);
36 }
37
38 static inline int
39 _is_y_inside_clip(int y, const struct RGBA_Draw_Context_clip clip)
40 {
41    if (!clip.use)
42      return 1;
43
44    return _in_range(y, clip.y, clip.y + clip.h - 1);
45 }
46
47 static inline int
48 _is_xy_inside_rect(int x, int y, int w, int h)
49 {
50    return _in_range(x, 0, w - 1) && _in_range(y, 0, h - 1);
51 }
52
53 static inline int
54 _is_empty_clip(const struct RGBA_Draw_Context_clip clip)
55 {
56    return clip.w < 1 || clip.h < 1;
57 }
58
59 static void
60 _soft16_line_point(Soft16_Image *dst, RGBA_Draw_Context *dc, int x, int y)
61 {
62    DATA16 rgb565, *dst_itr;
63    DATA8 alpha;
64
65    if (!_is_xy_inside_rect(x, y, dst->cache_entry.w, dst->cache_entry.h))
66      return;
67
68    if (!_is_xy_inside_clip(x, y, dc->clip))
69      return;
70
71    dst_itr = dst->pixels + (dst->stride * y) + x;
72    alpha = A_VAL(&dc->col.col) >> 3;
73    rgb565 = RGB_565_FROM_COMPONENTS(R_VAL(&dc->col.col),
74                                     G_VAL(&dc->col.col),
75                                     B_VAL(&dc->col.col));
76
77    if (alpha == 31)
78      _soft16_pt_fill_solid_solid(dst_itr, rgb565);
79    else if (alpha > 0)
80      {
81         DATA32 rgb565_unpack;
82
83         rgb565_unpack = RGB_565_UNPACK(rgb565);
84         alpha++;
85         _soft16_pt_fill_transp_solid(dst_itr, rgb565_unpack, alpha);
86      }
87 }
88
89 static void
90 _soft16_line_horiz(Soft16_Image *dst, RGBA_Draw_Context *dc, int x0, int x1, int y)
91 {
92    DATA16 rgb565, *dst_itr;
93    DATA8 alpha;
94    int w;
95
96    if (!_is_y_inside_clip(y, dc->clip))
97      return;
98
99    if (x0 < dc->clip.x)
100      x0 = dc->clip.x;
101
102    if (x1 >= dc->clip.x + dc->clip.w)
103      x1 = dc->clip.x + dc->clip.w - 1;
104
105    w = x1 - x0;
106    if (w < 1)
107      return;
108
109    dst_itr = dst->pixels + (dst->stride * y) + x0;
110    alpha = A_VAL(&dc->col.col) >> 3;
111    rgb565 = RGB_565_FROM_COMPONENTS(R_VAL(&dc->col.col),
112                                     G_VAL(&dc->col.col),
113                                     B_VAL(&dc->col.col));
114
115    if (alpha == 31)
116      _soft16_scanline_fill_solid_solid(dst_itr, w, rgb565);
117    else if (alpha > 0)
118      {
119         DATA32 rgb565_unpack;
120
121         rgb565_unpack = RGB_565_UNPACK(rgb565);
122         alpha++;
123         _soft16_scanline_fill_transp_solid(dst_itr, w, rgb565_unpack, alpha);
124      }
125 }
126
127 static void
128 _soft16_line_vert(Soft16_Image *dst, RGBA_Draw_Context *dc, int x, int y0, int y1)
129 {
130    DATA16 rgb565, *dst_itr;
131    DATA8 alpha;
132    int h;
133
134    if (!_is_x_inside_clip(x, dc->clip))
135      return;
136
137    if (y1 < y0)
138      {
139         int t;
140         t = y0;
141         y0 = y1;
142         y1 = t;
143      }
144
145    if (y0 < dc->clip.y)
146      y0 = dc->clip.y;
147
148    if (y1 >= dc->clip.y + dc->clip.h)
149      y1 = dc->clip.y + dc->clip.h - 1;
150
151    h = y1 - y0;
152    if (h < 1)
153      return;
154
155    dst_itr = dst->pixels + (dst->stride * y0) + x;
156    alpha = A_VAL(&dc->col.col) >> 3;
157    rgb565 = RGB_565_FROM_COMPONENTS(R_VAL(&dc->col.col),
158                                     G_VAL(&dc->col.col),
159                                     B_VAL(&dc->col.col));
160
161    if (alpha == 31)
162      {
163         for (; h > 0; h--, dst_itr += dst->stride)
164           _soft16_pt_fill_solid_solid(dst_itr, rgb565);
165      }
166    else if (alpha > 0)
167      {
168         DATA32 rgb565_unpack;
169
170         rgb565_unpack = RGB_565_UNPACK(rgb565);
171         alpha++;
172
173         for (; h > 0; h--, dst_itr += dst->stride)
174           _soft16_pt_fill_transp_solid(dst_itr, rgb565_unpack, alpha);
175      }
176 }
177
178 static inline void
179 _soft16_line_45deg_adjust_boundaries(const struct RGBA_Draw_Context_clip clip, int *p_x0, int *p_y0, int *p_x1, int *p_y1)
180 {
181    int diff, dy, x0, y0, x1, y1;
182
183    x0 = *p_x0;
184    y0 = *p_y0;
185    x1 = *p_x1;
186    y1 = *p_y1;
187
188    dy = y1 - y0;
189
190    diff = clip.x - x0;
191    if (diff > 0)
192      {
193         x0 = clip.x;
194         y0 += (dy > 0) ? diff : -diff;
195      }
196
197    diff = x1 - (clip.x + clip.w);
198    if (diff > 0)
199      {
200         x1 = clip.x + clip.w;
201         y1 += (dy > 0) ? -diff : diff;
202      }
203
204    if (dy > 0)
205      {
206         diff = clip.y - y0;
207         if (diff > 0)
208           {
209              y0 = clip.y;
210              x0 += diff;
211           }
212
213         diff = y1 - (clip.y + clip.h);
214         if (diff > 0)
215           {
216              y1 = clip.y + clip.h;
217              x1 -= diff;
218           }
219      }
220    else
221      {
222         diff = clip.y - y1;
223         if (diff > 0)
224           {
225              y1 = clip.y;
226              x1 -= diff;
227           }
228
229         diff = y0 - (clip.y + clip.h - 1);
230         if (diff > 0)
231           {
232              y0 = clip.y + clip.h - 1;
233              x0 += diff;
234           }
235      }
236
237    *p_x0 = x0;
238    *p_y0 = y0;
239    *p_x1 = x1;
240    *p_y1 = y1;
241 }
242
243 static void
244 _soft16_line_45deg(Soft16_Image *dst, RGBA_Draw_Context *dc, int x0, int y0, int x1, int y1)
245 {
246    int dy, step_dst_itr, len;
247    DATA8 alpha;
248    DATA16 *dst_itr, rgb565;
249
250    alpha = A_VAL(&dc->col.col) >> 3;
251    if (alpha < 1)
252      return;
253
254    rgb565 = RGB_565_FROM_COMPONENTS(R_VAL(&dc->col.col),
255                                     G_VAL(&dc->col.col),
256                                     B_VAL(&dc->col.col));
257
258    dy = y1 - y0;
259    step_dst_itr = 1 + ((dy > 0) ? dst->stride : -dst->stride);
260
261    _soft16_line_45deg_adjust_boundaries(dc->clip, &x0, &y0, &x1, &y1);
262
263    len = (dy > 0) ? (y1 - y0) : (y0 - y1);
264    if (len < 1)
265      return;
266
267    dst_itr = dst->pixels + dst->stride * y0 + x0;
268    if (alpha == 31)
269      {
270         for (; len > 0; len--, dst_itr += step_dst_itr)
271           _soft16_pt_fill_solid_solid(dst_itr, rgb565);
272      }
273    else
274      {
275         DATA32 rgb565_unpack;
276
277         rgb565_unpack = RGB_565_UNPACK(rgb565);
278         alpha++;
279         for (; len > 0; len--, dst_itr += step_dst_itr)
280           _soft16_pt_fill_transp_solid(dst_itr, rgb565_unpack, alpha);
281      }
282 }
283
284 static always_inline void
285 _soft16_line_aliased_pt(DATA16 *dst_itr, DATA16 rgb565, DATA32 rgb565_unpack, DATA8 alpha)
286 {
287    if (alpha == 32)
288      _soft16_pt_fill_solid_solid(dst_itr, rgb565);
289    else
290      _soft16_pt_fill_transp_solid(dst_itr, rgb565_unpack, alpha);
291 }
292
293 static void
294 _soft16_line_aliased(Soft16_Image *dst, RGBA_Draw_Context *dc, int x0, int y0, int x1, int y1)
295 {
296    int dx, dy, step_y, step_dst_itr;
297    DATA32 rgb565_unpack;
298    DATA16 rgb565;
299    DATA8 alpha;
300
301    alpha = A_VAL(&dc->col.col) >> 3;
302    if (alpha == 0)
303      return;
304    alpha++;
305
306    rgb565 = RGB_565_FROM_COMPONENTS(R_VAL(&dc->col.col),
307                                     G_VAL(&dc->col.col),
308                                     B_VAL(&dc->col.col));
309    rgb565_unpack = RGB_565_UNPACK(rgb565);
310
311    dx = x1 - x0;
312    dy = y1 - y0;
313
314    if (dy >= 0)
315      {
316         step_y = 1;
317         step_dst_itr = dst->stride;
318      }
319    else
320      {
321         dy = -dy;
322         step_y = -1;
323         step_dst_itr = -dst->stride;
324      }
325
326    if (dx > dy)
327      {
328         DATA16 *dst_itr;
329         int e, x, y;
330
331         e = - (dx / 2);
332         y = y0;
333         dst_itr = dst->pixels + dst->stride * y0 + x0;
334         for (x=x0; x <= x1; x++, dst_itr++)
335           {
336              if (_is_xy_inside_clip(x, y, dc->clip))
337                _soft16_line_aliased_pt(dst_itr, rgb565, rgb565_unpack, alpha);
338
339              e += dy;
340              if (e >= 0)
341                {
342                   dst_itr += step_dst_itr;
343                   y += step_y;
344                   e -= dx;
345                }
346           }
347      }
348    else
349      {
350         DATA16 *dst_itr;
351         int e, x, y;
352
353         e = - (dy / 2);
354         x = x0;
355         dst_itr = dst->pixels + dst->stride * y0 + x0;
356         for (y=y0; y != y1; y += step_y, dst_itr += step_dst_itr)
357           {
358              if (_is_xy_inside_clip(x, y, dc->clip))
359                _soft16_line_aliased_pt(dst_itr, rgb565, rgb565_unpack, alpha);
360
361              e += dx;
362              if (e >= 0)
363                {
364                   dst_itr++;
365                   x++;
366                   e -= dy;
367                }
368           }
369      }
370 }
371
372 void
373 soft16_line_draw(Soft16_Image *dst, RGBA_Draw_Context *dc, int x0, int y0, int x1, int y1)
374 {
375    struct RGBA_Draw_Context_clip c_bkp, c_tmp;
376    int dx, dy;
377    int  x, y, w, h;
378
379    c_tmp.use = 1;
380    c_tmp.x = 0;
381    c_tmp.y = 0;
382    c_tmp.w = dst->cache_entry.w;
383    c_tmp.h = dst->cache_entry.h;
384
385    /* save out clip info */
386    c_bkp = dc->clip;
387    if (c_bkp.use)
388      {
389         RECTS_CLIP_TO_RECT(c_tmp.x, c_tmp.y, c_tmp.w, c_tmp.h,
390                            c_bkp.x, c_bkp.y, c_bkp.w, c_bkp.h);
391         if (_is_empty_clip(c_tmp))
392           return;
393      }
394
395    x = MIN(x0, x1);
396    y = MIN(y0, y1);
397    w = MAX(x0, x1) - x + 1;
398    h = MAX(y0, y1) - y + 1;
399
400    RECTS_CLIP_TO_RECT(c_tmp.x, c_tmp.y, c_tmp.w, c_tmp.h, x, y, w, h);
401    if (_is_empty_clip(c_tmp))
402      return;
403
404    /* Check if the line doesn't cross the clip area */
405    if (x0 < c_tmp.x && x1 < c_tmp.x)
406      return;
407    if (x0 >= c_tmp.x + c_tmp.w && x1 >= c_tmp.x + c_tmp.w)
408      return;
409    if (y0 < c_tmp.y && y1 < c_tmp.y)
410      return;
411    if (y0 >= c_tmp.y + c_tmp.h && y1 >= c_tmp.y + c_tmp.h)
412      return;
413
414    dc->clip = c_tmp;
415    dx = x1 - x0;
416    dy = y1 - y0;
417
418    if (dx < 0)
419      {
420         int t;
421
422         t = x0;
423         x0 = x1;
424         x1 = t;
425
426         t = y0;
427         y0 = y1;
428         y1 = t;
429      }
430
431    if (dx == 0 && dy == 0)
432      _soft16_line_point(dst, dc, x0, y0);
433    else if (dx == 0)
434      _soft16_line_vert(dst, dc, x0, y0, y1);
435    else if (dy == 0)
436      _soft16_line_horiz(dst, dc, x0, x1, y0);
437    else if (dy == dx || dy == -dx)
438      _soft16_line_45deg(dst, dc, x0, y0, x1, y1);
439    else
440      _soft16_line_aliased(dst, dc, x0, y0, x1, y1);
441
442    /* restore clip info */
443    dc->clip = c_bkp;
444 }