move around - flatter.
[profile/ivi/evas.git] / src / lib / engines / common / evas_line_main.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
9 static void
10 _evas_draw_point(RGBA_Image *dst, RGBA_Draw_Context *dc, int x, int y);
11
12 static void
13 _evas_draw_simple_line(RGBA_Image *dst, RGBA_Draw_Context *dc, int x0, int y0, int x1, int y1);
14
15 static void
16 _evas_draw_line(RGBA_Image *dst, RGBA_Draw_Context *dc, int x0, int y0, int x1, int y1);
17
18 static void
19 _evas_draw_line_aa(RGBA_Image *dst, RGBA_Draw_Context *dc, int x0, int y0, int x1, int y1);
20
21
22 #define IN_RANGE(x, y, w, h) \
23 ( ((unsigned)(x) < (w)) && ((unsigned)(y) < (h)) )
24
25 #define IN_RECT(x, y, rx, ry, rw, rh) \
26 ( ((unsigned)((x) - (rx)) < (rw)) && ((unsigned)((y) - (ry)) < (rh)) )
27
28 #define EXCHANGE_POINTS(x0, y0, x1, y1) \
29 { \
30         int _tmp = y0; \
31   \
32         y0 = y1;   \
33         y1 = _tmp; \
34   \
35         _tmp = x0; \
36         x0 = x1;   \
37         x1 = _tmp; \
38 }
39
40
41 EAPI void
42 evas_common_line_init(void)
43 {
44 }
45
46 EAPI void
47 evas_common_line_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, int x0, int y0, int x1, int y1)
48 {
49    int  x, y, w, h;
50    int  clx, cly, clw, clh;
51    int  cuse, cx, cy, cw, ch;
52
53    if ((x0 == x1) && (y0 == y1))
54      {
55         _evas_draw_point(dst, dc, x0, y0);
56         return;
57      }
58
59    clx = cly = 0;
60    clw = dst->cache_entry.w;
61    clh = dst->cache_entry.h;
62
63    /* save out clip info */
64    cuse = dc->clip.use;
65    cx = dc->clip.x;
66    cy = dc->clip.y;
67    cw = dc->clip.w;
68    ch = dc->clip.h;
69
70    if (cuse)
71      {
72         RECTS_CLIP_TO_RECT(clx, cly, clw, clh, cx, cy, cw, ch);
73         if ((clw < 1) || (clh < 1))
74            return;
75      }
76
77    x = MIN(x0, x1);
78    y = MIN(y0, y1);
79    w = MAX(x0, x1) - x + 1;
80    h = MAX(y0, y1) - y + 1;
81
82    RECTS_CLIP_TO_RECT(clx, cly, clw, clh, x, y, w, h);
83    if ((clw < 1) || (clh < 1))
84         return;
85
86    dc->clip.use = 1;
87    dc->clip.x = clx;
88    dc->clip.y = cly;
89    dc->clip.w = clw;
90    dc->clip.h = clh;
91
92    if (dc->anti_alias)
93         _evas_draw_line_aa(dst, dc, x0, y0, x1, y1);
94    else
95         _evas_draw_line(dst, dc, x0, y0, x1, y1);
96
97    /* restore clip info */
98    dc->clip.use = cuse;
99    dc->clip.x = cx;
100    dc->clip.y = cy;
101    dc->clip.w = cw;
102    dc->clip.h = ch;
103 }
104
105
106 static void
107 _evas_draw_point(RGBA_Image *dst, RGBA_Draw_Context *dc, int x, int y)
108 {
109    RGBA_Gfx_Pt_Func pfunc;
110
111    if (!IN_RANGE(x, y, dst->cache_entry.w, dst->cache_entry.h))
112         return;
113    if ((dc->clip.use) && (!IN_RECT(x, y, dc->clip.x, dc->clip.y, dc->clip.w, dc->clip.h)))
114         return;
115    pfunc = evas_common_gfx_func_composite_color_pt_get(dc->col.col, dst, dc->render_op);
116    if (pfunc)
117         pfunc(0, 255, dc->col.col, dst->image.data + (dst->cache_entry.w * y) + x);
118 }
119
120 /*
121    these functions use the dc->clip data as bounding
122    data. they assume that such data has already been cut
123    back to lie in the dst image rect and the object's
124    (line) bounding rect.
125 */
126 static void
127 _evas_draw_simple_line(RGBA_Image *dst, RGBA_Draw_Context *dc, int x0, int y0, int x1, int y1)
128 {
129    int     dx, dy, len, lx, ty, rx, by;
130    int     clx, cly, clw, clh;
131    int     dstw;
132    DATA32  *p, color;
133    RGBA_Gfx_Pt_Func pfunc;
134    RGBA_Gfx_Func    sfunc;
135
136    dstw = dst->cache_entry.w;
137    color = dc->col.col;
138
139    if (y0 > y1)
140       EXCHANGE_POINTS(x0, y0, x1, y1)
141    if (x0 > x1)
142       EXCHANGE_POINTS(x0, y0, x1, y1)
143
144    dx = x1 - x0;
145    dy = y1 - y0;
146
147    clx = dc->clip.x;
148    cly = dc->clip.y;
149    clw = dc->clip.w;
150    clh = dc->clip.h;
151
152    lx = clx;
153    rx = clx + clw - 1;
154    ty = cly;
155    by = cly + clh - 1;
156
157    if (dy == 0)
158      {
159 #ifdef EVAS_SLI
160         if (((y0) % dc->sli.h) == dc->sli.y)
161 #endif
162           {
163              if ((y0 >= ty) && (y0 <= by))
164                {
165                   if (dx < 0)
166                     {
167                        int  tmp = x1;
168
169                        x1 = x0;
170                        x0 = tmp;
171                     }
172
173                   if (x0 < lx) x0 = lx;
174                   if (x1 > rx) x1 = rx;
175
176                   len = x1 - x0 + 1;
177                   p = dst->image.data + (dstw * y0) + x0;
178                   sfunc = evas_common_gfx_func_composite_color_span_get(color, dst, len, dc->render_op);
179                   if (sfunc)
180                     sfunc(NULL, NULL, color, p, len);
181                }
182           }
183         return;
184      }
185
186    pfunc = evas_common_gfx_func_composite_color_pt_get(color, dst, dc->render_op);
187    if (!pfunc) return;
188
189    if (dx == 0)
190      {
191         if ((x0 >= lx) && (x0 <= rx))
192           {
193              if (y0 < ty) y0 = ty;
194              if (y1 > by) y1 = by;
195
196              len = y1 - y0 + 1;
197              p = dst->image.data + (dstw * y0) + x0;
198              while (len--)
199                {
200 #ifdef EVAS_SLI
201                   if (((y1 + 1 - len) % dc->sli.h) == dc->sli.y)
202 #endif
203                     {
204                        pfunc(0, 255, color, p);
205                     }
206                   p += dstw;
207                }
208           }
209         return;
210      }
211
212    if ((dy == dx) || (dy == -dx))
213      {
214         int   p0_in, p1_in;
215
216         p0_in = (IN_RECT(x0, y0, clx, cly, clw, clh) ? 1 : 0);
217         p1_in = (IN_RECT(x1, y1, clx, cly, clw, clh) ? 1 : 0);
218
219         if (dx > 0)
220           {
221             if (!p0_in)
222               {
223                 x0 = x0 + (ty - y0);
224                 y0 = ty;
225                 if (x0 > rx) return;
226                 if (x0 < lx)
227                   {
228                     y0 = y0 + (lx - x0);
229                     x0 = lx;
230                     if ((y0 < ty) || (y0 > by)) return;
231                   }
232               }
233             if (!p1_in)
234               {
235                 x1 = x0 + (by - y0);
236                 y1 = by;
237                 if (x1 < lx) return;
238                 if (x1 > rx)
239                   {
240                     y1 = y0 + (rx - x0);
241                     x1 = rx;
242                     if ((y1 < ty) || (y1 > by)) return;
243                   }
244               }
245           }
246         else
247           {
248             if (!p0_in)
249               {
250                 x0 = x0 - (ty - y0);
251                 y0 = ty;
252                 if (x0 < lx) return;
253                 if (x0 > rx)
254                   {
255                     y0 = y0 - (rx - x0);
256                     x0 = rx;
257                     if ((y0 < ty) || (y0 > by)) return;
258                   }
259               }
260             if (!p1_in)
261               {
262                 x1 = x0 - (by - y0);
263                 y1 = by;
264                 if (x1 > rx) return;
265                 if (x1 < lx)
266                   {
267                     y1 = y0 - (lx - x0);
268                     x1 = lx;
269                     if ((y1 < ty) || (y1 > by)) return;
270                   }
271               }
272           }
273         if (y1 > y0)
274           {
275              p = dst->image.data + (dstw * y0) + x0;
276              len = y1 - y0 + 1;
277              if (dx > 0)  dstw++;
278              else  dstw--;
279           }
280         else
281           {
282              len = y0 - y1 + 1;
283              p = dst->image.data + (dstw * y1) + x1;
284              if (dx > 0)  dstw--;
285              else  dstw++;
286           }
287
288         while (len--)
289           {
290 #ifdef EVAS_SLI
291              if (((y1 + 1 - len) % dc->sli.h) == dc->sli.y)
292 #endif
293                {
294                   pfunc(0, 255, color, p);
295                }
296             p += dstw;
297           }
298      }
299 }
300
301
302 #define SETUP_LINE_SHALLOW              \
303         if (x0 > x1)                                                    \
304           {                                                                     \
305            EXCHANGE_POINTS(x0, y0, x1, y1)                              \
306            dx = -dx;                                                    \
307            dy = -dy;                                                    \
308           }                                                                     \
309                                                                                 \
310         px = x0;                                                                \
311         py = y0;                                                                \
312                                                                                 \
313         p0_in = (IN_RANGE(x0 , y0 , clw, clh) ? 1 : 0);         \
314         p1_in = (IN_RANGE(x1 , y1 , clw, clh) ? 1 : 0);         \
315                                                                                 \
316         dely = 1;                                                               \
317         dh = dstw;                                                              \
318         if (dy < 0)                                                             \
319           {                                                                     \
320            dely = -1;                                                   \
321            dh = -dstw;                                                  \
322           }                                                                     \
323                                                                                 \
324         dyy = ((dy) << 16) / (dx);                                              \
325                                                                                 \
326         if (!p0_in)                                                             \
327           {                                                                     \
328            dxx = ((dx) << 16) / (dy);                                   \
329            if (px < 0)                                                  \
330              {                                                          \
331                 x = -px;  px = 0;                                               \
332                 yy = x * dyy;                                           \
333                 y = yy >> 16;                                           \
334                 if (!a_a)                                                       \
335                    y += (yy - (y << 16)) >> 15;                 \
336                 py += y;                                                        \
337                 if ((dely > 0) && (py >= clh))                  \
338                    return;                                                      \
339                 else if ((dely < 0) && (py < -1))                       \
340                    return;                                                      \
341              }                                                          \
342                                                                                 \
343            y = 0;                                                               \
344            if ((dely > 0) && (py < -1))                         \
345                 y = (-1 - py);                                          \
346            else if ((dely < 0) && (py >= clh))                  \
347                 y = (clh - 1 - py);                                     \
348                                                                                 \
349            xx = y * dxx;                                                        \
350            x = xx >> 16;                                                        \
351            if (!a_a)                                                    \
352               x += (xx - (x << 16)) >> 15;                      \
353            px += x;                                                             \
354            if (px >= clw) return;                                       \
355                                                                                 \
356            yy = x * dyy;                                                        \
357            y = yy >> 16;                                                        \
358            if (!a_a)                                                    \
359               y += (yy - (y << 16)) >> 15;                      \
360            py += y;                                                             \
361            if ((dely > 0) && (py >= clh))                               \
362                  return;                                                        \
363            else if ((dely < 0) && (py < -1))                    \
364                  return;                                                        \
365           }                                                                     \
366                                                                                 \
367         p = data + (dstw * py) + px;                                    \
368                                                                                 \
369         x = px - x0;                                                    \
370         yy = x * dyy;                                                   \
371         prev_y = (yy >> 16);                                            \
372                                                                                 \
373         rx = MIN(x1 + 1, clw);                                          \
374         by = clh - 1;
375
376
377 #define SETUP_LINE_STEEP                \
378    if (y0 > y1)                                                         \
379      {                                                                  \
380         EXCHANGE_POINTS(x0, y0, x1, y1)                         \
381         dx = -dx;                                                               \
382         dy = -dy;                                                               \
383      }                                                                  \
384                                                                                 \
385    px = x0;                                                                     \
386    py = y0;                                                                     \
387                                                                                 \
388    p0_in = (IN_RANGE(x0 , y0 , clw, clh) ? 1 : 0);              \
389    p1_in = (IN_RANGE(x1 , y1 , clw, clh) ? 1 : 0);              \
390                                                                                 \
391    delx = 1;                                                            \
392    if (dx < 0)                                                          \
393         delx = -1;                                                              \
394                                                                                 \
395    dxx = ((dx) << 16) / (dy);                                           \
396                                                                                 \
397    if (!p0_in)                                                          \
398      {                                                                  \
399         dyy = ((dy) << 16) / (dx);                                              \
400                                                                                 \
401         if (py < 0)                                                             \
402           {                                                                     \
403            y = -py;  py = 0;                                            \
404            xx = y * dxx;                                                        \
405            x = xx >> 16;                                                        \
406            if (!a_a)                                                    \
407               x += (xx - (x << 16)) >> 15;                      \
408            px += x;                                                             \
409            if ((delx > 0) && (px >= clw))                               \
410                 return;                                                 \
411            else if ((delx < 0) && (px < -1))                    \
412                 return;                                                 \
413           }                                                                     \
414                                                                                 \
415         x = 0;                                                          \
416         if ((delx > 0) && (px < -1))                                    \
417            x = (-1 - px);                                                       \
418         else if ((delx < 0) && (px >= clw))                             \
419            x = (clw - 1 - px);                                          \
420                                                                                 \
421         yy = x * dyy;                                                   \
422         y = yy >> 16;                                                   \
423         if (!a_a)                                                               \
424            y += (yy - (y << 16)) >> 15;                         \
425         py += y;                                                                \
426         if (py >= clh) return;                                          \
427                                                                                 \
428         xx = y * dxx;                                                   \
429         x = xx >> 16;                                                   \
430         if (!a_a)                                                               \
431            x += (xx - (x << 16)) >> 15;                         \
432         px += x;                                                                \
433         if ((delx > 0) && (px >= clw))                          \
434            return;                                                              \
435         else if ((delx < 0) && (px < -1))                               \
436            return;                                                              \
437      }                                                                  \
438                                                                                 \
439    p = data + (dstw * py) + px;                                 \
440                                                                                 \
441    y = py - y0;                                                         \
442    xx = y * dxx;                                                                \
443    prev_x = (xx >> 16);                                                 \
444                                                                                 \
445    by = MIN(y1 + 1, clh);                                               \
446    rx = clw - 1;
447
448
449
450 static void
451 _evas_draw_line(RGBA_Image *dst, RGBA_Draw_Context *dc, int x0, int y0, int x1, int y1)
452 {
453    int     px, py, x, y, prev_x, prev_y;
454    int     dx, dy, rx, by, p0_in, p1_in, dh, a_a = 0;
455    int     delx, dely, xx, yy, dxx, dyy;
456    int     clx, cly, clw, clh;
457    int     dstw;
458    DATA32  *p, *data, color;
459    RGBA_Gfx_Pt_Func pfunc;
460
461    dx = x1 - x0;
462    dy = y1 - y0;
463
464    if ( (dx == 0) || (dy == 0) || (dx == dy) || (dx == -dy) )
465      {
466         _evas_draw_simple_line(dst, dc, x0, y0, x1, y1);
467         return;
468      }
469
470    color = dc->col.col;
471    pfunc = evas_common_gfx_func_composite_color_pt_get(color, dst, dc->render_op);
472    if (!pfunc) return;
473
474    clx = dc->clip.x;
475    cly = dc->clip.y;
476    clw = dc->clip.w;
477    clh = dc->clip.h;
478
479    data = dst->image.data;
480    dstw = dst->cache_entry.w;
481
482    data += (dstw * cly) + clx;
483    x0 -= clx;
484    y0 -= cly;
485    x1 -= clx;
486    y1 -= cly;
487
488    /* shallow: x-parametric */
489    if ((dy < dx) || (dy < -dx))
490      {
491         SETUP_LINE_SHALLOW
492
493         while (px < rx)
494           {
495             y = (yy >> 16);
496             y += ((yy - (y << 16)) >> 15);
497             if (prev_y != y)
498               {
499                 prev_y = y;
500                 p += dh;
501                 py += dely;
502               }
503             if (!p1_in)
504               {
505                 if ((py < 0) && (dely < 0)) return;
506                 if ((py > by) && (dely > 0)) return;
507               }
508 #ifdef EVAS_SLI
509              if (((py) % dc->sli.h) == dc->sli.y)
510 #endif
511                {
512                   if (IN_RANGE(px, py, clw, clh))
513                     pfunc(0, 255, color, p);
514                }
515             yy += dyy;
516             px++;
517             p++;
518           }
519         return;
520      }
521
522    /* steep: y-parametric */
523
524    SETUP_LINE_STEEP
525
526    while (py < by)
527      {
528         x = (xx >> 16);
529         x += ((xx - (x << 16)) >> 15);
530         if (prev_x != x)
531           {
532             prev_x = x;
533             px += delx;
534             p += delx;
535           }
536         if (!p1_in)
537           {
538             if ((px < 0) && (delx < 0)) return;
539             if ((px > rx) && (delx > 0)) return;
540           }
541 #ifdef EVAS_SLI
542         if (((py) % dc->sli.h) == dc->sli.y)
543 #endif
544           {
545              if (IN_RANGE(px, py, clw, clh))
546                pfunc(0, 255, color, p);
547           }
548         xx += dxx;
549         py++;
550         p += dstw;
551      }
552 }
553
554
555 static void
556 _evas_draw_line_aa(RGBA_Image *dst, RGBA_Draw_Context *dc, int x0, int y0, int x1, int y1)
557 {
558    int     px, py, x, y, prev_x, prev_y;
559    int     dx, dy, rx, by, p0_in, p1_in, dh, a_a = 1;
560    int     delx, dely, xx, yy, dxx, dyy;
561    int     clx, cly, clw, clh;
562    int     dstw;
563    DATA32  *p, *data, color;
564    RGBA_Gfx_Pt_Func pfunc;
565
566    if (y0 > y1)
567       EXCHANGE_POINTS(x0, y0, x1, y1)
568    dx = x1 - x0;
569    dy = y1 - y0;
570
571    if ( (dx == 0) || (dy == 0) || (dx == dy) || (dx == -dy) )
572      {
573         _evas_draw_simple_line(dst, dc, x0, y0, x1, y1);
574         return;
575      }
576
577    color = dc->col.col;
578    pfunc = evas_common_gfx_func_composite_mask_color_pt_get(color, dst, dc->render_op);
579    if (!pfunc) return;
580
581    clx = dc->clip.x;
582    cly = dc->clip.y;
583    clw = dc->clip.w;
584    clh = dc->clip.h;
585
586    data = dst->image.data;
587    dstw = dst->cache_entry.w;
588
589    data += (dstw * cly) + clx;
590    x0 -= clx;
591    y0 -= cly;
592    x1 -= clx;
593    y1 -= cly;
594
595    /* shallow: x-parametric */
596    if ((dy < dx) || (dy < -dx))
597      {
598         SETUP_LINE_SHALLOW
599
600         while (px < rx)
601           {
602             DATA8   aa;
603
604             y = (yy >> 16);
605             if (prev_y != y)
606               {
607                 prev_y = y;
608                 p += dh;
609                 py += dely;
610               }
611             if (!p1_in)
612               {
613                 if ((py < -1) && (dely < 0)) return;
614                 if ((py > by) && (dely > 0)) return;
615               }
616             if ((unsigned)(px) < clw)
617               {
618                 aa = ((yy - (y << 16)) >> 8);
619                 if ((unsigned)(py) < clh)
620                    pfunc(0, 255 - aa, color, p);
621                 if ((unsigned)(py + 1) < clh)
622                    pfunc(0, aa, color, p + dstw);
623               }
624             yy += dyy;
625             px++;
626             p++;
627           }
628         return;
629      }
630
631    /* steep: y-parametric */
632
633    SETUP_LINE_STEEP
634
635    while (py < by)
636      {
637         DATA8   aa;
638
639         x = (xx >> 16);
640         if (prev_x != x)
641           {
642             prev_x = x;
643             px += delx;
644             p += delx;
645           }
646         if (!p1_in)
647           {
648             if ((px < -1) && (delx < 0)) return;
649             if ((px > rx) && (delx > 0)) return;
650           }
651         if ((unsigned)(py) < clh)
652           {
653             aa = ((xx - (x << 16)) >> 8);
654             if ((unsigned)(px) < clw)
655                 pfunc(0, 255 - aa, color, p);
656             if ((unsigned)(px + 1) < clw)
657                 pfunc(0, aa, color, p + 1);
658           }
659         xx += dxx;
660         py++;
661         p += dstw;
662      }
663 }