1 #include "common.h"
2 
3 #include "blend.h"
4 #include "colormod.h"
5 #include "image.h"
6 #include "rgbadraw.h"
7 #include "span.h"
8 
9 ImlibPoly
__imlib_polygon_new()10 __imlib_polygon_new()
11 {
12    ImlibPoly           poly;
13 
14    poly = malloc(sizeof(_ImlibPoly));
15    if (!poly)
16       return NULL;
17    memset(poly, 0, sizeof(_ImlibPoly));
18    return poly;
19 }
20 
21 void
__imlib_polygon_add_point(ImlibPoly poly,int x,int y)22 __imlib_polygon_add_point(ImlibPoly poly, int x, int y)
23 {
24    if (!poly->points)
25      {
26         poly->points = (ImlibPoint *) malloc(sizeof(ImlibPoint));
27         if (!poly->points)
28            return;
29 
30         poly->pointcount++;
31         poly->lx = poly->rx = x;
32         poly->ty = poly->by = y;
33      }
34    else
35      {
36         poly->pointcount++;
37         poly->points =
38            (ImlibPoint *) realloc(poly->points,
39                                   (poly->pointcount * sizeof(ImlibPoint)));
40 
41         if (!poly->points)
42           {
43              poly->pointcount = 0;
44              return;
45           }
46 
47         if (x < poly->lx)
48            poly->lx = x;
49         if (poly->rx < x)
50            poly->rx = x;
51         if (y < poly->ty)
52            poly->ty = y;
53         if (poly->by < y)
54            poly->by = y;
55      }
56 
57    poly->points[poly->pointcount - 1].x = x;
58    poly->points[poly->pointcount - 1].y = y;
59 }
60 
61 void
__imlib_polygon_free(ImlibPoly poly)62 __imlib_polygon_free(ImlibPoly poly)
63 {
64    if (poly->points)
65       free(poly->points);
66    free(poly);
67 }
68 
69 #define TRUE 1
70 #define FALSE 0
71 
72 /* Check if p lies on segment [ s1, s2 ] given that
73       it lies on the line defined by s1 and s2. */
74 #define __imlib_point_inside_segment(p_x, p_y, s1_x, s1_y, s2_x,s2_y) \
75 (s1_y != s2_y) ? (p_y <= MAX(s1_y, s2_y) && p_y >= MIN(s1_y, s2_y)) : (p_x <= MAX(s1_x, s2_x) && p_x >= MIN(s1_x, s2_x))
76 
77 #define __imlib_point_on_segment(p_x, p_y, s1_x, s1_y, s2_x, s2_y) \
78 __imlib_segments_intersect(p_x, p_y, p_x, p_y, s1_x, s1_y, s2_x, s2_y)
79 
80 void
__imlib_polygon_get_bounds(ImlibPoly poly,int * px1,int * py1,int * px2,int * py2)81 __imlib_polygon_get_bounds(ImlibPoly poly, int *px1, int *py1, int *px2,
82                            int *py2)
83 {
84    if (!poly || !poly->points || (poly->pointcount < 1))
85       return;
86 
87    if (px1)
88       *px1 = poly->lx;
89    if (py1)
90       *py1 = poly->ty;
91    if (px2)
92       *px2 = poly->rx;
93    if (py2)
94       *py2 = poly->by;
95 }
96 
97 static double
__imlib_point_delta_from_line(int p_x,int p_y,int s1_x,int s1_y,int s2_x,int s2_y)98 __imlib_point_delta_from_line(int p_x, int p_y, int s1_x, int s1_y, int s2_x,
99                               int s2_y)
100 {
101    if (s2_x - s1_x == 0.0)
102       return p_x - s1_x;
103    else
104      {
105         double              m = (double)(s2_y - s1_y) / (double)(s2_x - s1_x);
106 
107         return (p_y - s1_y - (double)(p_x - s1_x) * m);
108      }
109 }
110 
111 static unsigned char
__imlib_segments_intersect(int r1_x,int r1_y,int r2_x,int r2_y,int s1_x,int s1_y,int s2_x,int s2_y)112 __imlib_segments_intersect(int r1_x, int r1_y, int r2_x, int r2_y, int s1_x,
113                            int s1_y, int s2_x, int s2_y)
114 {
115    double              testS1R =
116       __imlib_point_delta_from_line(s1_x, s1_y, r1_x, r1_y, r2_x, r2_y);
117    double              testS2R =
118       __imlib_point_delta_from_line(s2_x, s2_y, r1_x, r1_y, r2_x, r2_y);
119    double              testR1S =
120       __imlib_point_delta_from_line(r1_x, r1_y, s1_x, s1_y, s2_x, s2_y);
121    double              testR2S =
122       __imlib_point_delta_from_line(r2_x, r2_y, s1_x, s1_y, s2_x, s2_y);
123 
124    /* check if segments are collinear */
125    if (testS1R == 0.0 && testS2R == 0.0)
126      {
127         if (__imlib_point_inside_segment(s1_x, s1_y, r1_x, r1_y, r2_x, r2_y)
128             || __imlib_point_inside_segment(s2_x, s2_y, r1_x, r1_y, r2_x, r2_y)
129             || __imlib_point_inside_segment(r1_x, r1_y, s1_x, s1_y, s2_x, s2_y)
130             || __imlib_point_inside_segment(r2_x, r2_y, s1_x, s1_y, s2_x, s2_y))
131            return TRUE;
132         else
133            return FALSE;
134      }
135 
136    if (testS1R * testS2R <= 0.0 && testR1S * testR2S <= 0.0)
137       return TRUE;
138    else
139       return FALSE;
140 }
141 
142 unsigned char
__imlib_polygon_contains_point(ImlibPoly poly,int x,int y)143 __imlib_polygon_contains_point(ImlibPoly poly, int x, int y)
144 {
145    int                 count = 0;
146    int                 start = 0;
147    int                 ysave = 0;       /* initial value arbitrary */
148    int                 cx, nx, out_x, out_y, i, n;
149    int                 curr_x, curr_y, next_x, next_y;
150 
151    /* find a vertex of poly that does not lie on the test line */
152    while (start < poly->pointcount && poly->points[start].y == y)
153       start++;
154    /* if one doesn't exist we will use point on segment test
155     * and can start with vertex 0 anyway */
156    cx = start % poly->pointcount;
157 
158    out_x = poly->points[0].x;
159    out_y = y;
160 
161    for (i = 1; i < poly->pointcount; i++)
162      {
163         out_x = MAX(out_x, poly->points[i].x);
164      }
165    out_x++;                     /* out now guaranteed to be outside poly */
166 
167    for (n = 0; n < poly->pointcount; n++)
168      {
169         nx = (cx + 1) % poly->pointcount;
170 
171         curr_x = poly->points[cx].x;
172         curr_y = poly->points[cx].y;
173         next_x = poly->points[nx].x;
174         next_y = poly->points[nx].y;
175 
176         if (__imlib_point_on_segment(x, y, curr_x, curr_y, next_x, next_y))
177            return TRUE;
178 
179         /* ignore horizontal segments from this point on */
180         if (poly->points[cx].y != poly->points[nx].y)
181           {
182              if (__imlib_segments_intersect
183                  (curr_x, curr_y, next_x, next_y, x, y, out_x, out_y))
184                {
185                   count++;
186 
187                   if (__imlib_point_on_segment
188                       (next_x, next_y, x, y, out_x, out_y))
189                     {
190                        /* current seg intersects test seg @ 2nd vtx
191                         * reset ysave */
192                        ysave = curr_y;
193                     }
194                   if (__imlib_point_on_segment
195                       (curr_x, curr_y, x, y, out_x, out_y)
196                       && ((ysave < y) != (next_y < y)))
197                     {
198                        /* current seg xsects test seg @ 1st vtx and
199                         * ysave on opposite side of test line from
200                         * curr seg 2nd vtx;
201                         * decrement hits (2-1) for odd parity */
202                        count--;
203                     }
204                }
205           }
206         cx = nx;
207      }
208    return (count % 2 == 1);
209 }
210 
211 /** Polygon Drawing and Filling **/
212 
213 #define STEEP_EDGE	0
214 #define SHALLOW_EDGE	1
215 #define HORZ_EDGE	2
216 
217 typedef struct _PolyEdge PolyEdge;
218 typedef struct _IndexedValue IndexedValue;
219 
220 struct _PolyEdge {
221    int                 type;
222    int                 xx;
223    int                 dxx, dyy;
224    ImlibPoint         *v0, *v1;
225    int                 index;
226 };
227 
228 struct _IndexedValue {
229    int                 val;
230    int                 index;
231 };
232 
233 static int
poly_value_sorter(const void * a,const void * b)234 poly_value_sorter(const void *a, const void *b)
235 {
236    IndexedValue       *p, *q;
237 
238    p = (IndexedValue *) a;
239    q = (IndexedValue *) b;
240    if (p->val <= q->val)
241       return -1;
242    return 1;
243 }
244 
245 static int
poly_edge_sorter(const void * a,const void * b)246 poly_edge_sorter(const void *a, const void *b)
247 {
248    PolyEdge           *p, *q;
249 
250    p = (PolyEdge *) a;
251    q = (PolyEdge *) b;
252    if (p->xx < q->xx)
253       return -1;
254    if (p->xx > q->xx)
255       return 1;
256    if (p->dxx <= q->dxx)
257       return -1;
258    return 1;
259 }
260 
261 /* general macros */
262 
263 #define DEL_EDGE(j)		\
264 do {									\
265    int m;								\
266    for (m = 0; (m < nactive_edges) && (edge[m].index != (j)); m++);	\
267 									\
268    if (m < nactive_edges)						\
269      {									\
270 	if (edge[m].type == HORZ_EDGE) nactive_horz_edges--;		\
271 	nactive_edges--;						\
272 	memmove(edge + m, edge + m + 1,					\
273               (nactive_edges - m) * sizeof(PolyEdge));			\
274      }									\
275 } while (0)
276 
277 #define DEL_HORZ_EDGES()		\
278 do {									\
279    int m = 0;								\
280 									\
281    while (m < nactive_edges)						\
282      {									\
283 	if (edge[m].type == HORZ_EDGE)					\
284 	  {								\
285 	    nactive_edges--;						\
286 	    memmove(edge + m, edge + m + 1,				\
287               (nactive_edges - m) * sizeof(PolyEdge));			\
288 	    m--;							\
289 	  }								\
290 	m++;								\
291      }									\
292    nactive_horz_edges = 0;						\
293 } while (0)
294 
295 #define ADD_EDGE(i)		\
296 do {									\
297     int m;								\
298 									\
299     for (m = 0; (m < nactive_edges) && (edge[m].index != i); m++);	\
300 									\
301     if ((m == nactive_edges) && (i < nvertices) &&			\
302 	(nactive_edges < nvertices))					\
303       {									\
304 	ImlibPoint *v0, *v1, *w;					\
305 	PolyEdge *ne;							\
306 	int  dx, dy;							\
307 									\
308 	if (i < (nvertices - 1))  m = i + 1;				\
309 	else  m = 0;							\
310 									\
311 	v0 = (poly->points) + i;					\
312 	v1 = (poly->points) + m;					\
313 	if ((v1->y) < (v0->y))						\
314 	  {								\
315 	    w = v0;							\
316 	    v0 = v1;							\
317 	    v1 = w;							\
318 	  }								\
319 									\
320 	dx = (v1->x) - (v0->x);						\
321 	dy = (v1->y) - (v0->y);						\
322 	ne = edge + nactive_edges;					\
323 	ne->index = i;							\
324 	if (dy == 0)							\
325 	  {								\
326 	    ne->type = HORZ_EDGE;					\
327 	    ne->dxx = 0;						\
328             if ((v1->x) < (v0->x))					\
329 	      {								\
330 		w = v0;							\
331 		v0 = v1;						\
332 		v1 = w;							\
333 	      }								\
334 	    ne->xx = (v0->x) << 16;					\
335 	    nactive_horz_edges++;					\
336 	  }								\
337 	else								\
338 	  {								\
339 	    ne->type = STEEP_EDGE;					\
340 	    ne->dxx = ((dx << 16) / dy);				\
341 	    ne->xx = ((ne->dxx) * (y - (v0->y))) + ((v0->x) << 16);	\
342 	    if ((dy < dx) || (dy < (-dx)))				\
343 	      {								\
344 		ne->type = SHALLOW_EDGE;				\
345 		ne->dyy = ((dy << 16) / dx);				\
346 	      }								\
347 	  }								\
348 	ne->v0 = v0;							\
349 	ne->v1 = v1;							\
350 	nactive_edges++;						\
351       }									\
352 } while (0)
353 
354 #define GET_EDGE_RANGE(e, elx, erx)   \
355 do { \
356    switch(e->type)							\
357    {									\
358     case SHALLOW_EDGE:							\
359 	elx = (e->xx - (2 * e->dxx)) >> 16;				\
360 	erx = (e->xx + (2 * e->dxx)) >> 16;				\
361 	if (e->dxx < 0)							\
362 	  { lx = elx; elx = erx; erx = lx; }				\
363 	break;								\
364     default:								\
365     case STEEP_EDGE:							\
366 	lx = (e->xx >> 16);						\
367 	elx = erx = lx;							\
368 	break;								\
369     case HORZ_EDGE:							\
370 	elx = e->v0->x;							\
371 	erx = e->v1->x;							\
372 	break;								\
373    }                                                                    \
374 } while (0)
375 
376 #define CLIP_SPAN(lx, rx, clx, clrx)     \
377 do { \
378    if (lx < (clx)) lx = (clx);           \
379    if (rx > (clrx)) rx = (clrx);         \
380 } while (0)
381 
382 #define BLEND_ALPHA(dst, a, tmp) \
383 do { \
384    if (*dst)                                    \
385      {                                          \
386        tmp = ((a) * (255 - (*(dst)))) + 0x80;   \
387        *(dst) += ((tmp + (tmp >> 8)) >> 8);     \
388      }                                          \
389    else                                         \
390        *(dst) = (a);                            \
391 } while (0)
392 
393 /* initializing macro used in drawing/filling functions */
394 
395 #define INIT_POLY()		\
396 do { \
397    sfunc = __imlib_GetShapedSpanDrawFunction(op, dst_alpha, blend);	\
398    if (!sfunc)  return;							\
399 									\
400    nvertices = poly->pointcount;					\
401    if (nvertices < 1) return;						\
402 									\
403    clrx = clx + clw - 1;						\
404    clby = cly + clh - 1;						\
405 									\
406    CLIP_SPAN(clx, clrx, poly->lx, a_a + poly->rx);			\
407    if (clrx < clx) return;						\
408 									\
409    CLIP_SPAN(cly, clby, poly->ty, poly->by);				\
410    if (clby < cly) return;						\
411 									\
412    clw = clrx - clx + 1;						\
413    clh = clby - cly + 1;						\
414 									\
415    edge = (PolyEdge *)malloc(nvertices * sizeof(PolyEdge));		\
416    if (!edge) return;							\
417 									\
418    ysort = (IndexedValue *)malloc(nvertices * sizeof(IndexedValue));	\
419    if (!ysort) { free(edge); return; }					\
420 									\
421    s0 = (DATA8 *)malloc(clw * sizeof(DATA8));				\
422    if (!s0) { free(edge); free(ysort); return; }			\
423 									\
424    s1 = (DATA8 *)malloc(clw * sizeof(DATA8));				\
425    if (!s1) { free(edge); free(ysort); free(s0); return; }		\
426 									\
427    memset(s0,0,clw);							\
428 									\
429    k = 0;								\
430    while (k < nvertices)						\
431      {									\
432 	ysort[k].val = poly->points[k].y;				\
433 	ysort[k].index = k;						\
434         k++;								\
435      }									\
436 									\
437    qsort(ysort, nvertices, sizeof(IndexedValue), poly_value_sorter);	\
438 									\
439    s0 -= clx;								\
440    s1 -= clx;								\
441 									\
442    x0 = clx;								\
443    x1 = clrx;								\
444 									\
445    nx0 = clrx + 1;							\
446    nx1 = clx - 1;							\
447 									\
448    if (cly > poly->ty)							\
449       ty = cly - 1;							\
450    else									\
451       ty = cly;								\
452    by = clby;								\
453 									\
454    p = dst + (dstw * ty);						\
455    k = 0;								\
456    nactive_edges = 0;							\
457    nactive_horz_edges = 0;						\
458    y = ty;                                                              \
459 } while (0)
460 
461 #define DE_INIT_POLY()  \
462 do { \
463    free(edge);        \
464    free(ysort);       \
465    s0 += clx;         \
466    free(s0);          \
467    s1 += clx;         \
468    free(s1);          \
469 } while (0)
470 
471 /** Polygon Drawing **/
472 
473 /* aliased drawing */
474 /* draws the poly-line defined by the sequence of vertices */
475 
476 static void
__imlib_Polygon_DrawToData(ImlibPoly poly,char close,DATA32 color,DATA32 * dst,int dstw,int clx,int cly,int clw,int clh,ImlibOp op,char dst_alpha,char blend)477 __imlib_Polygon_DrawToData(ImlibPoly poly, char close, DATA32 color,
478                            DATA32 * dst, int dstw,
479                            int clx, int cly, int clw, int clh,
480                            ImlibOp op, char dst_alpha, char blend)
481 {
482    ImlibShapedSpanDrawFunction sfunc;
483    IndexedValue       *ysort;
484    PolyEdge           *edge;
485    int                 k, a_a = 0;
486    int                 nactive_edges, nactive_horz_edges, nvertices;
487    int                 clrx, clby, ty, by, y;
488    int                 x0, x1, nx0, nx1;
489    DATA32             *p;
490    DATA8              *s0, *s1, *ps;
491 
492    INIT_POLY();
493 
494    while (y <= by)
495      {
496         int                 j;
497 
498         while ((k < nvertices) && (poly->points[ysort[k].index].y <= y))
499           {
500              int                 i = ysort[k].index;
501 
502              j = i - 1;
503              if (close && (i == 0))
504                 j = nvertices - 1;
505 
506              if (j >= 0)
507                {
508                   if (poly->points[j].y < y)
509                      DEL_EDGE(j);
510                   else
511                      ADD_EDGE(j);
512                }
513 
514              j = i + 1;
515              if (close && (i == (nvertices - 1)))
516                 j = 0;
517 
518              if (j < nvertices)
519                {
520                   if (poly->points[j].y < y)
521                      DEL_EDGE(i);
522                   else
523                      ADD_EDGE(i);
524                }
525 
526              k++;
527           }
528 
529         /* not really needed, but... */
530         qsort(edge, nactive_edges, sizeof(PolyEdge), poly_edge_sorter);
531 
532         /* clear alpha buffer */
533         if (x0 <= x1)
534            memset(s1 + x0, 0, x1 - x0 + 1);
535 
536         x0 = nx0;
537         x1 = nx1;
538         nx0 = clrx + 1;
539         nx1 = clx - 1;
540 
541         /* draw to alpha buffer */
542         j = 0;
543         while (j < nactive_edges)
544           {
545              int                 lx, rx;
546              int                 e_lx, e_rx;
547              PolyEdge           *e;
548 
549              e = edge + j;
550 
551              GET_EDGE_RANGE(e, e_lx, e_rx);
552              if ((e_lx < e->v0->x) && (e->dxx > 0))
553                 e_lx = e->v0->x;
554              if ((e_rx > e->v0->x) && (e->dxx < 0))
555                 e_rx = e->v0->x;
556 
557              /* draw edge */
558              switch (e->type)
559                {
560                case STEEP_EDGE:
561                   {
562                      lx = e_lx;
563                      lx += (e->xx - (lx << 16)) >> 15;
564                      if (IN_SEGMENT(lx, clx, clw))
565                        {
566                           *(s0 + lx) = 255;
567                           if (lx < x0)
568                              x0 = lx;
569                           if (lx > x1)
570                              x1 = lx;
571                        }
572 
573                      if ((e->v1->y == (y + 1)) && (y < clby))
574                        {
575                           lx = e->v1->x;
576                           if (IN_SEGMENT(lx, clx, clw))
577                             {
578                                *(s1 + lx) = 255;
579                                if (lx < nx0)
580                                   nx0 = lx;
581                                if (lx > nx1)
582                                   nx1 = lx;
583                             }
584                        }
585                      break;
586                   }
587                case SHALLOW_EDGE:
588                   {
589                      int                 x, ey, eyy;
590 
591                      if (e->dyy > 0)
592                         x = e_lx;
593                      else
594                         x = e_rx;
595 
596                      eyy = ((e->v0->y) << 16) + (x - (e->v0->x)) * (e->dyy);
597                      ey = eyy >> 16;
598                      ey += (eyy - (ey << 16)) >> 15;
599 
600                      if (e->dyy > 0)
601                        {
602                           if (x < x0)
603                              x0 = x;
604                           while (ey <= y)
605                             {
606                                if ((ey == y) && IN_SEGMENT(x, clx, clw))
607                                   *(s0 + x) = 255;
608                                eyy += e->dyy;
609                                ey = eyy >> 16;
610                                ey += (eyy - (ey << 16)) >> 15;
611                                x++;
612                             }
613                           if (x > x1)
614                              x1 = x;
615 
616                           if (((y + 1) == e->v1->y) && (y < clby))
617                             {
618                                if (x < nx0)
619                                   nx0 = x;
620                                rx = e->v1->x;
621                                while ((ey == (y + 1)) && (x <= rx))
622                                  {
623                                     if (IN_SEGMENT(x, clx, clw))
624                                        *(s1 + x) = 255;
625                                     eyy += e->dyy;
626                                     ey = eyy >> 16;
627                                     ey += (eyy - (ey << 16)) >> 15;
628                                     x++;
629                                  }
630                                if (x > nx1)
631                                   nx1 = x;
632                             }
633                           break;
634                        }
635 
636                      if (x > x1)
637                         x1 = x;
638                      while (ey <= y)
639                        {
640                           if ((ey == y) && IN_SEGMENT(x, clx, clw))
641                              *(s0 + x) = 255;
642                           eyy -= e->dyy;
643                           ey = eyy >> 16;
644                           ey += (eyy - (ey << 16)) >> 15;
645                           x--;
646                        }
647                      if (x < x0)
648                         x0 = x;
649 
650                      if (((y + 1) == e->v1->y) && (y < clby))
651                        {
652                           if (x > nx1)
653                              nx1 = x;
654                           lx = e->v1->x;
655                           while ((ey == (y + 1)) && (x >= lx))
656                             {
657                                if (IN_SEGMENT(x, clx, clw))
658                                   *(s1 + x) = 255;
659                                eyy -= e->dyy;
660                                ey = eyy >> 16;
661                                ey += (eyy - (ey << 16)) >> 15;
662                                x--;
663                             }
664                           if (x < nx0)
665                              nx0 = x;
666                        }
667                      break;
668                   }
669                case HORZ_EDGE:
670                   {
671                      lx = e_lx;
672                      rx = e_rx;
673                      CLIP_SPAN(lx, rx, clx, clrx);
674                      if (lx <= rx)
675                        {
676                           memset(s0 + lx, 255, rx - lx + 1);
677                           if (lx < x0)
678                              x0 = lx;
679                           if (rx > x1)
680                              x1 = rx;
681                        }
682                      break;
683                   }
684 
685                default:
686                   break;
687                }
688 
689              e->xx += e->dxx;
690              j++;
691           }
692 
693         if (nactive_horz_edges > 0)
694            DEL_HORZ_EDGES();
695 
696         /* draw alpha buffer to dst */
697         CLIP_SPAN(x0, x1, clx, clrx);
698         if ((x0 <= x1) && (y >= cly))
699            sfunc(s0 + x0, color, p + x0, x1 - x0 + 1);
700 
701         /* exchange alpha buffers */
702         ps = s0;
703         s0 = s1;
704         s1 = ps;
705 
706         y++;
707         p += dstw;
708      }
709 
710    DE_INIT_POLY();
711 }
712 
713 /* anti-aliased drawing */
714 
715 static void
__imlib_Polygon_DrawToData_AA(ImlibPoly poly,char close,DATA32 color,DATA32 * dst,int dstw,int clx,int cly,int clw,int clh,ImlibOp op,char dst_alpha,char blend)716 __imlib_Polygon_DrawToData_AA(ImlibPoly poly, char close, DATA32 color,
717                               DATA32 * dst, int dstw,
718                               int clx, int cly, int clw, int clh,
719                               ImlibOp op, char dst_alpha, char blend)
720 {
721    ImlibShapedSpanDrawFunction sfunc;
722    IndexedValue       *ysort;
723    PolyEdge           *edge;
724    int                 k, a_a = 1;
725    int                 nactive_edges, nactive_horz_edges, nvertices;
726    int                 clrx, clby, ty, by, y, yy, prev_y, prev_yy;
727    int                 x0, x1, nx0, nx1;
728    DATA32             *p;
729    DATA8              *s0, *s1, *ps;
730 
731    INIT_POLY();
732 
733    yy = y << 16;
734    prev_y = y - 1;
735    prev_yy = prev_y << 16;
736 
737    while (y <= by)
738      {
739         int                 j;
740 
741         while ((k < nvertices) && (poly->points[ysort[k].index].y <= y))
742           {
743              int                 i = ysort[k].index;
744 
745              j = i - 1;
746              if (close && (i == 0))
747                 j = nvertices - 1;
748 
749              if (j >= 0)
750                {
751                   if (poly->points[j].y < y)
752                      DEL_EDGE(j);
753                   else
754                      ADD_EDGE(j);
755                }
756 
757              j = i + 1;
758              if (close && (i == (nvertices - 1)))
759                 j = 0;
760 
761              if (j < nvertices)
762                {
763                   if (poly->points[j].y <= y)
764                      DEL_EDGE(i);
765                   else
766                      ADD_EDGE(i);
767                }
768 
769              k++;
770           }
771 
772         /* not really needed, but... */
773         qsort(edge, nactive_edges, sizeof(PolyEdge), poly_edge_sorter);
774 
775         /* clear alpha buffer */
776         if (x0 <= x1)
777            memset(s1 + x0, 0, x1 - x0 + 1);
778 
779         x0 = nx0;
780         x1 = nx1;
781         nx0 = clrx + 1;
782         nx1 = clx - 1;
783 
784         /* draw to alpha buffer */
785         j = 0;
786         while (j < nactive_edges)
787           {
788              int                 lx, rx;
789              int                 e_lx, e_rx;
790              PolyEdge           *e;
791 
792              e = edge + j;
793 
794              GET_EDGE_RANGE(e, e_lx, e_rx);
795              if ((e_lx < e->v0->x) && (e->dxx > 0))
796                 e_lx = e->v0->x;
797              if ((e_rx > e->v0->x) && (e->dxx < 0))
798                 e_rx = e->v0->x;
799 
800              /* draw aa edge */
801              switch (e->type)
802                {
803                case STEEP_EDGE:
804                   {
805                      DATA32              tmp;
806                      DATA8               aa;
807 
808                      aa = (e->xx - (e_lx << 16)) >> 8;
809                      rx = e_lx + 1;
810                      if (IN_SEGMENT(rx, clx, clw))
811                        {
812                           ps = s0 + rx;
813                           BLEND_ALPHA(ps, aa, tmp);
814                           if (rx > x1)
815                              x1 = rx;
816                        }
817                      if (IN_SEGMENT(e_lx, clx, clw))
818                        {
819                           aa = 255 - aa;
820                           ps = s0 + e_lx;
821                           BLEND_ALPHA(ps, aa, tmp);
822                           if (e_lx < x0)
823                              x0 = e_lx;
824                        }
825 
826                      if ((e->v1->y == (y + 1)) && (y < clby))
827                        {
828                           lx = (e->xx + e->dxx) >> 16;
829                           aa = ((e->xx + e->dxx - (lx << 16)) >> 8);
830                           rx = lx + 1;
831                           if (IN_SEGMENT(rx, clx, clw))
832                             {
833                                ps = s1 + rx;
834                                BLEND_ALPHA(ps, aa, tmp);
835                                if (rx > nx1)
836                                   nx1 = rx;
837                             }
838                           if (IN_SEGMENT(lx, clx, clw))
839                             {
840                                aa = 255 - aa;
841                                ps = s1 + lx;
842                                BLEND_ALPHA(ps, aa, tmp);
843                                if (lx < nx0)
844                                   nx0 = lx;
845                             }
846                        }
847                      break;
848                   }
849                case SHALLOW_EDGE:
850                   {
851                      int                 x, ey, eyy;
852 
853                      if (e->dyy > 0)
854                         x = e_lx;
855                      else
856                         x = e_rx;
857 
858                      eyy = ((e->v0->y) << 16) + (x - (e->v0->x)) * (e->dyy);
859                      ey = eyy >> 16;
860 
861                      if (e->dyy > 0)
862                        {
863                           if (x < x0)
864                              x0 = x;
865                           while (ey < y)
866                             {
867                                DATA32              tmp;
868                                DATA8               aa;
869 
870                                if ((ey == prev_y) && IN_SEGMENT(x, clx, clw))
871                                  {
872                                     aa = ((eyy - prev_yy) >> 8);
873                                     ps = s0 + x;
874                                     BLEND_ALPHA(ps, aa, tmp);
875                                  }
876                                eyy += e->dyy;
877                                ey = eyy >> 16;
878                                x++;
879                             }
880                           lx = x;
881                           while (ey == y)
882                             {
883                                DATA32              tmp;
884                                DATA8               aa;
885 
886                                if (IN_SEGMENT(x, clx, clw))
887                                  {
888                                     aa = 255 - ((eyy - yy) >> 8);
889                                     ps = s0 + x;
890                                     BLEND_ALPHA(ps, aa, tmp);
891                                  }
892                                eyy += e->dyy;
893                                ey = eyy >> 16;
894                                x++;
895                             }
896                           if (x > x1)
897                              x1 = x;
898 
899                           if (((y + 1) == e->v1->y) && (y < clby))
900                             {
901                                x = lx;
902                                if (x < nx0)
903                                   nx0 = x;
904                                rx = e->v1->x;
905                                eyy =
906                                   ((e->v0->y) << 16) + (x -
907                                                         (e->v0->x)) * (e->dyy);
908                                ey = eyy >> 16;
909                                while ((ey == y) && (x <= rx))
910                                  {
911                                     DATA32              tmp;
912                                     DATA8               aa;
913 
914                                     if (IN_SEGMENT(x, clx, clw))
915                                       {
916                                          aa = ((eyy - yy) >> 8);
917                                          ps = s1 + x;
918                                          BLEND_ALPHA(ps, aa, tmp);
919                                       }
920                                     eyy += e->dyy;
921                                     ey = eyy >> 16;
922                                     x++;
923                                  }
924                                if (x > nx1)
925                                   nx1 = x;
926                             }
927                           break;
928                        }
929 
930                      if (x > x1)
931                         x1 = x;
932                      while (ey < y)
933                        {
934                           DATA32              tmp;
935                           DATA8               aa;
936 
937                           if ((ey == prev_y) && IN_SEGMENT(x, clx, clw))
938                             {
939                                aa = ((eyy - prev_yy) >> 8);
940                                ps = s0 + x;
941                                BLEND_ALPHA(ps, aa, tmp);
942                             }
943                           eyy -= e->dyy;
944                           ey = eyy >> 16;
945                           x--;
946                        }
947                      rx = x;
948                      while (ey == y)
949                        {
950                           DATA32              tmp;
951                           DATA8               aa;
952 
953                           if (IN_SEGMENT(x, clx, clw))
954                             {
955                                aa = 255 - ((eyy - yy) >> 8);
956                                ps = s0 + x;
957                                BLEND_ALPHA(ps, aa, tmp);
958                             }
959                           eyy -= e->dyy;
960                           ey = eyy >> 16;
961                           x--;
962                        }
963                      if (x < x0)
964                         x0 = x;
965 
966                      if (((y + 1) == e->v1->y) && (y < clby))
967                        {
968                           x = rx;
969                           if (x > nx1)
970                              nx1 = x;
971                           lx = e->v1->x;
972                           eyy =
973                              ((e->v0->y) << 16) + (x - (e->v0->x)) * (e->dyy);
974                           ey = eyy >> 16;
975                           while ((ey == y) && (x >= lx))
976                             {
977                                DATA32              tmp;
978                                DATA8               aa;
979 
980                                if (IN_SEGMENT(x, clx, clw))
981                                  {
982                                     aa = ((eyy - yy) >> 8);
983                                     ps = s1 + x;
984                                     BLEND_ALPHA(ps, aa, tmp);
985                                  }
986                                eyy -= e->dyy;
987                                ey = eyy >> 16;
988                                x--;
989                             }
990                           if (x < nx0)
991                              nx0 = x;
992                        }
993                      break;
994                   }
995                case HORZ_EDGE:
996                   {
997                      lx = e_lx;
998                      rx = e_rx;
999                      CLIP_SPAN(lx, rx, clx, clrx);
1000                      if (lx <= rx)
1001                        {
1002                           memset(s0 + lx, 255, rx - lx + 1);
1003                           if (lx < x0)
1004                              x0 = lx;
1005                           if (rx > x1)
1006                              x1 = rx;
1007                        }
1008                      break;
1009                   }
1010 
1011                default:
1012                   break;
1013                }
1014 
1015              e->xx += e->dxx;
1016              j++;
1017           }
1018 
1019         if (nactive_horz_edges > 0)
1020            DEL_HORZ_EDGES();
1021 
1022         /* draw alpha buffer to dst */
1023         CLIP_SPAN(x0, x1, clx, clrx);
1024         if ((x0 <= x1) && (y >= cly))
1025            sfunc(s0 + x0, color, p + x0, x1 - x0 + 1);
1026 
1027         /* exchange alpha buffers */
1028         ps = s0;
1029         s0 = s1;
1030         s1 = ps;
1031 
1032         prev_yy = yy;
1033         prev_y = y;
1034 
1035         y++;
1036         yy = y << 16;
1037 
1038         p += dstw;
1039      }
1040 
1041    DE_INIT_POLY();
1042 }
1043 
1044 void
__imlib_Polygon_DrawToImage(ImlibPoly poly,char close,DATA32 color,ImlibImage * im,int clx,int cly,int clw,int clh,ImlibOp op,char blend,char anti_alias)1045 __imlib_Polygon_DrawToImage(ImlibPoly poly, char close, DATA32 color,
1046                             ImlibImage * im, int clx, int cly, int clw, int clh,
1047                             ImlibOp op, char blend, char anti_alias)
1048 {
1049    if ((!poly) || (!poly->points) || (poly->pointcount < 1) || (clw < 0))
1050       return;
1051    if (blend && (!A_VAL(&color)))
1052       return;
1053    if (poly->pointcount == 1)
1054      {
1055         (void)__imlib_Point_DrawToImage(poly->points[0].x, poly->points[0].y,
1056                                         color, im, clx, cly, clw, clh, op,
1057                                         blend, 0);
1058         return;
1059      }
1060    if (poly->pointcount == 2)
1061      {
1062         (void)__imlib_Line_DrawToImage(poly->points[0].x, poly->points[0].y,
1063                                        poly->points[1].x, poly->points[1].y,
1064                                        color, im, clx, cly, clw, clh, op, blend,
1065                                        anti_alias, 0);
1066         return;
1067      }
1068 
1069    if (clw == 0)
1070      {
1071         clw = im->w;
1072         clx = 0;
1073         clh = im->h;
1074         cly = 0;
1075      }
1076 
1077    CLIP_RECT_TO_RECT(clx, cly, clw, clh, 0, 0, im->w, im->h);
1078    if ((clw < 1) || (clh < 1))
1079       return;
1080 
1081    if (blend && IMAGE_HAS_ALPHA(im))
1082       __imlib_build_pow_lut();
1083 
1084    if (anti_alias)
1085       __imlib_Polygon_DrawToData_AA(poly, close, color,
1086                                     im->data, im->w,
1087                                     clx, cly, clw, clh,
1088                                     op, IMAGE_HAS_ALPHA(im), blend);
1089    else
1090       __imlib_Polygon_DrawToData(poly, close, color,
1091                                  im->data, im->w,
1092                                  clx, cly, clw, clh,
1093                                  op, IMAGE_HAS_ALPHA(im), blend);
1094 }
1095 
1096 /** Polygon Filling **/
1097 
1098 /* aliased filling */
1099 
1100 static void
__imlib_Polygon_FillToData(ImlibPoly poly,DATA32 color,DATA32 * dst,int dstw,int clx,int cly,int clw,int clh,ImlibOp op,char dst_alpha,char blend)1101 __imlib_Polygon_FillToData(ImlibPoly poly, DATA32 color,
1102                            DATA32 * dst, int dstw,
1103                            int clx, int cly, int clw, int clh,
1104                            ImlibOp op, char dst_alpha, char blend)
1105 {
1106    ImlibShapedSpanDrawFunction sfunc;
1107    IndexedValue       *ysort;
1108    PolyEdge           *edge;
1109    int                 k, a_a = 0;
1110    int                 nactive_edges, nactive_horz_edges, nvertices;
1111    int                 clrx, clby, ty, by, y;
1112    int                 x0, x1, nx0, nx1;
1113    DATA32             *p;
1114    DATA8              *s0, *s1, *ps;
1115 
1116    INIT_POLY();
1117 
1118    while (y <= by)
1119      {
1120         int                 j;
1121 
1122         while ((k < nvertices) && (poly->points[ysort[k].index].y <= y))
1123           {
1124              int                 i = ysort[k].index;
1125 
1126              if (i > 0)
1127                 j = i - 1;
1128              else
1129                 j = nvertices - 1;
1130 
1131              if (poly->points[j].y < y)
1132                 DEL_EDGE(j);
1133              else
1134                 ADD_EDGE(j);
1135 
1136              if (i < (nvertices - 1))
1137                 j = i + 1;
1138              else
1139                 j = 0;
1140 
1141              if (poly->points[j].y < y)
1142                 DEL_EDGE(i);
1143              else
1144                 ADD_EDGE(i);
1145 
1146              k++;
1147           }
1148 
1149         qsort(edge, nactive_edges, sizeof(PolyEdge), poly_edge_sorter);
1150 
1151         /* clear alpha buffer */
1152         if (x0 <= x1)
1153            memset(s1 + x0, 0, x1 - x0 + 1);
1154 
1155         x0 = nx0;
1156         x1 = nx1;
1157         nx0 = clrx + 1;
1158         nx1 = clx - 1;
1159 
1160         /* draw to alpha buffer */
1161         j = 0;
1162         while (j < nactive_edges)
1163           {
1164              int                 lx, rx;
1165              int                 le_lx, le_rx;
1166              int                 re_lx, re_rx;
1167              PolyEdge           *le, *re;
1168 
1169              if (j < (nactive_edges - 1))
1170                {
1171                   le = edge + j;
1172                   re = le + 1;
1173                }
1174              else if (j > 0)
1175                {
1176                   le = edge + (j - 1);
1177                   le->xx -= le->dxx;
1178                   re = le + 1;
1179                }
1180              else
1181                {
1182                   re = le = edge;
1183                }
1184 
1185              GET_EDGE_RANGE(le, le_lx, le_rx);
1186              if ((le_lx < le->v0->x) && (le->dxx > 0))
1187                 le_lx = le->v0->x;
1188              GET_EDGE_RANGE(re, re_lx, re_rx);
1189              if ((re_rx > re->v0->x) && (re->dxx < 0))
1190                 re_rx = re->v0->x;
1191 
1192              /* draw left edge */
1193              switch (le->type)
1194                {
1195                case STEEP_EDGE:
1196                   {
1197                      le_rx += (le->xx - (le_rx << 16)) >> 15;
1198                      if (le_rx < x0)
1199                         x0 = le_rx;
1200 
1201                      if ((le->v1->y == (y + 1)) && (y < clby))
1202                        {
1203                           lx = le->v1->x;
1204                           if (IN_SEGMENT(lx, clx, clw))
1205                             {
1206                                *(s1 + lx) = 255;
1207                                if (lx < nx0)
1208                                   nx0 = lx;
1209                             }
1210                        }
1211                      break;
1212                   }
1213                case SHALLOW_EDGE:
1214                   {
1215                      int                 x, ey, eyy;
1216 
1217                      x = le_lx;
1218                      eyy = ((le->v0->y) << 16) + (x - (le->v0->x)) * (le->dyy);
1219                      ey = eyy >> 16;
1220                      ey += (eyy - (ey << 16)) >> 15;
1221 
1222                      if (le->dyy > 0)
1223                        {
1224                           while (ey < y)
1225                             {
1226                                eyy += le->dyy;
1227                                ey = eyy >> 16;
1228                                ey += (eyy - (ey << 16)) >> 15;
1229                                x++;
1230                             }
1231                           le_rx = x;
1232                           if (x < x0)
1233                              x0 = x;
1234 
1235                           if (((y + 1) == le->v1->y) && (y < clby))
1236                             {
1237                                if (x < nx0)
1238                                   nx0 = x;
1239                                rx = le->v1->x;
1240                                while ((ey <= (y + 1)) && (x <= rx))
1241                                  {
1242                                     if ((ey == (y + 1))
1243                                         && IN_SEGMENT(x, clx, clw))
1244                                        *(s1 + x) = 255;
1245                                     eyy += le->dyy;
1246                                     ey = eyy >> 16;
1247                                     ey += (eyy - (ey << 16)) >> 15;
1248                                     x++;
1249                                  }
1250                                if (x > nx1)
1251                                   nx1 = x;
1252                             }
1253                           break;
1254                        }
1255 
1256                      while (ey > y)
1257                        {
1258                           eyy += le->dyy;
1259                           ey = eyy >> 16;
1260                           ey += (eyy - (ey << 16)) >> 15;
1261                           x++;
1262                        }
1263                      le_rx = x;
1264                      if (x < x0)
1265                         x0 = x;
1266                      break;
1267                   }
1268                case HORZ_EDGE:
1269                   {
1270                      lx = le_lx;
1271                      rx = le_rx;
1272                      CLIP_SPAN(lx, rx, clx, clrx);
1273                      if (lx <= rx)
1274                        {
1275                           memset(s0 + lx, 255, rx - lx + 1);
1276                           if (lx < x0)
1277                              x0 = lx;
1278                        }
1279                      le_rx++;
1280                      break;
1281                   }
1282 
1283                default:
1284                   break;
1285                }
1286 
1287              /* draw right edge */
1288              switch (re->type)
1289                {
1290                case STEEP_EDGE:
1291                   {
1292                      re_lx += (re->xx - (re_lx << 16)) >> 15;
1293                      if (re_lx > x1)
1294                         x1 = re_lx;
1295 
1296                      if ((re->v1->y == (y + 1)) && (y < clby))
1297                        {
1298                           rx = re->v1->x;
1299                           if (IN_SEGMENT(rx, clx, clw))
1300                             {
1301                                *(s1 + rx) = 255;
1302                                if (rx > nx1)
1303                                   nx1 = rx;
1304                             }
1305                        }
1306                      break;
1307                   }
1308                case SHALLOW_EDGE:
1309                   {
1310                      int                 x, ey, eyy;
1311 
1312                      x = re_rx;
1313                      eyy = ((re->v0->y) << 16) + (x - (re->v0->x)) * (re->dyy);
1314                      ey = eyy >> 16;
1315                      ey += (eyy - (ey << 16)) >> 15;
1316 
1317                      if (re->dyy > 0)
1318                        {
1319                           while (ey > y)
1320                             {
1321                                eyy -= re->dyy;
1322                                ey = eyy >> 16;
1323                                ey += (eyy - (ey << 16)) >> 15;
1324                                x--;
1325                             }
1326                           re_lx = x;
1327                           if (x > x1)
1328                              x1 = x;
1329                           break;
1330                        }
1331 
1332                      while (ey < y)
1333                        {
1334                           eyy -= re->dyy;
1335                           ey = eyy >> 16;
1336                           ey += (eyy - (ey << 16)) >> 15;
1337                           x--;
1338                        }
1339                      re_lx = x;
1340                      if (x > x1)
1341                         x1 = x;
1342 
1343                      if (((y + 1) == re->v1->y) && (y < clby))
1344                        {
1345                           if (x > nx1)
1346                              nx1 = x;
1347                           lx = re->v1->x;
1348                           while ((ey <= (y + 1)) && (x >= lx))
1349                             {
1350                                if ((ey == (y + 1)) && IN_SEGMENT(x, clx, clw))
1351                                   *(s1 + x) = 255;
1352                                eyy -= re->dyy;
1353                                ey = eyy >> 16;
1354                                ey += (eyy - (ey << 16)) >> 15;
1355                                x--;
1356                             }
1357                           if (x < nx0)
1358                              nx0 = x;
1359                        }
1360                      break;
1361                   }
1362                case HORZ_EDGE:
1363                   {
1364                      lx = re_lx;
1365                      rx = re_rx;
1366                      CLIP_SPAN(lx, rx, clx, clrx);
1367                      if (lx <= rx)
1368                        {
1369                           memset(s0 + lx, 255, rx - lx + 1);
1370                           if (rx > x1)
1371                              x1 = rx;
1372                        }
1373                      re_lx--;
1374                      break;
1375                   }
1376 
1377                default:
1378                   break;
1379                }
1380 
1381              /* draw span between edges */
1382              lx = le_rx;
1383              rx = re_lx;
1384              CLIP_SPAN(lx, rx, clx, clrx);
1385              if ((lx <= rx) && (y >= cly))
1386                 memset(s0 + lx, 255, rx - lx + 1);
1387 
1388              le->xx += le->dxx;
1389              if (le != re)
1390                 re->xx += re->dxx;
1391 
1392              j += 2;
1393           }
1394 
1395         if (nactive_horz_edges > 0)
1396            DEL_HORZ_EDGES();
1397 
1398         /* draw alpha buffer to dst */
1399         CLIP_SPAN(x0, x1, clx, clrx);
1400         if ((x0 <= x1) && (y >= cly))
1401            sfunc(s0 + x0, color, p + x0, x1 - x0 + 1);
1402 
1403         /* exchange alpha buffers */
1404         ps = s0;
1405         s0 = s1;
1406         s1 = ps;
1407 
1408         y++;
1409         p += dstw;
1410      }
1411 
1412    DE_INIT_POLY();
1413 }
1414 
1415 /* anti-aliased filling */
1416 
1417 static void
__imlib_Polygon_FillToData_AA(ImlibPoly poly,DATA32 color,DATA32 * dst,int dstw,int clx,int cly,int clw,int clh,ImlibOp op,char dst_alpha,char blend)1418 __imlib_Polygon_FillToData_AA(ImlibPoly poly, DATA32 color,
1419                               DATA32 * dst, int dstw,
1420                               int clx, int cly, int clw, int clh,
1421                               ImlibOp op, char dst_alpha, char blend)
1422 {
1423    ImlibShapedSpanDrawFunction sfunc;
1424    IndexedValue       *ysort;
1425    PolyEdge           *edge;
1426    int                 k, a_a = 1;
1427    int                 nactive_edges, nactive_horz_edges, nvertices;
1428    int                 clrx, clby, ty, by, y, yy, prev_y, prev_yy;
1429    int                 x0, x1, nx0, nx1;
1430    DATA32             *p;
1431    DATA8              *s0, *s1, *ps;
1432 
1433    INIT_POLY();
1434 
1435    yy = y << 16;
1436    prev_y = y - 1;
1437    prev_yy = prev_y << 16;
1438 
1439    while (y <= by)
1440      {
1441         int                 j;
1442 
1443         while ((k < nvertices) && (poly->points[ysort[k].index].y <= y))
1444           {
1445              int                 i = ysort[k].index;
1446 
1447              if (i > 0)
1448                 j = i - 1;
1449              else
1450                 j = nvertices - 1;
1451 
1452              if (poly->points[j].y < y)
1453                 DEL_EDGE(j);
1454              else
1455                 ADD_EDGE(j);
1456 
1457              if (i < (nvertices - 1))
1458                 j = i + 1;
1459              else
1460                 j = 0;
1461 
1462              if (poly->points[j].y < y)
1463                 DEL_EDGE(i);
1464              else
1465                 ADD_EDGE(i);
1466 
1467              k++;
1468           }
1469 
1470         qsort(edge, nactive_edges, sizeof(PolyEdge), poly_edge_sorter);
1471 
1472         /* clear alpha buffer */
1473         if (x0 <= x1)
1474            memset(s1 + x0, 0, x1 - x0 + 1);
1475 
1476         x0 = nx0;
1477         x1 = nx1;
1478         nx0 = clrx + 1;
1479         nx1 = clx - 1;
1480         /* draw to alpha buffer */
1481         j = 0;
1482         while (j < nactive_edges)
1483           {
1484              int                 lx, rx;
1485              int                 le_lx, le_rx;
1486              int                 re_lx, re_rx;
1487              PolyEdge           *le, *re;
1488 
1489              if (j < (nactive_edges - 1))
1490                {
1491                   le = edge + j;
1492                   re = le + 1;
1493                }
1494              else if (j > 0)
1495                {
1496                   le = edge + (j - 1);
1497                   le->xx -= le->dxx;
1498                   re = le + 1;
1499                }
1500              else
1501                {
1502                   re = le = edge;
1503                }
1504 
1505              GET_EDGE_RANGE(le, le_lx, le_rx);
1506              if ((le_lx < le->v0->x) && (le->dxx > 0))
1507                 le_lx = le->v0->x;
1508              GET_EDGE_RANGE(re, re_lx, re_rx);
1509              if ((re_rx > re->v0->x) && (re->dxx < 0))
1510                 re_rx = re->v0->x;
1511 
1512              /* draw left aa edge */
1513              switch (le->type)
1514                {
1515                case STEEP_EDGE:
1516                   {
1517                      DATA32              tmp;
1518                      DATA8               aa;
1519 
1520                      if (le_lx < x0)
1521                         x0 = le_lx;
1522                      le_rx = le_lx + 1;
1523 
1524                      if (IN_SEGMENT(le_lx, clx, clw))
1525                        {
1526                           aa = 255 - ((le->xx - (le_lx << 16)) >> 8);
1527                           ps = s0 + le_lx;
1528                           BLEND_ALPHA(ps, aa, tmp);
1529                        }
1530 
1531                      if ((le->v1->y == (y + 1)) && (y < clby))
1532                        {
1533                           lx = (le->xx + le->dxx) >> 16;
1534                           if (IN_SEGMENT(lx, clx, clw))
1535                             {
1536                                aa =
1537                                   255 - ((le->xx + le->dxx - (lx << 16)) >> 8);
1538                                ps = s1 + lx;
1539                                BLEND_ALPHA(ps, aa, tmp);
1540                                if (lx < nx0)
1541                                   nx0 = lx;
1542                             }
1543                        }
1544                      break;
1545                   }
1546                case SHALLOW_EDGE:
1547                   {
1548                      int                 x, ey, eyy;
1549 
1550                      if (le_lx < x0)
1551                         x0 = le_lx;
1552                      x = le_lx;
1553                      eyy = ((le->v0->y) << 16) + (x - (le->v0->x)) * (le->dyy);
1554                      ey = eyy >> 16;
1555 
1556                      if (le->dyy > 0)
1557                        {
1558                           while (ey < y)
1559                             {
1560                                DATA32              tmp;
1561                                DATA8               aa;
1562 
1563                                if ((ey == prev_y) && IN_SEGMENT(x, clx, clw))
1564                                  {
1565                                     aa = ((eyy - prev_yy) >> 8);
1566                                     ps = s0 + x;
1567                                     BLEND_ALPHA(ps, aa, tmp);
1568                                  }
1569                                eyy += le->dyy;
1570                                ey = eyy >> 16;
1571                                x++;
1572                             }
1573                           le_rx = x;
1574 
1575                           if (((y + 1) == le->v1->y) && (y < clby))
1576                             {
1577                                if (x < nx0)
1578                                   nx0 = x;
1579                                rx = le->v1->x;
1580                                while ((ey == y) && (x <= rx))
1581                                  {
1582                                     DATA32              tmp;
1583                                     DATA8               aa;
1584 
1585                                     if (IN_SEGMENT(x, clx, clw))
1586                                       {
1587                                          aa = ((eyy - yy) >> 8);
1588                                          ps = s1 + x;
1589                                          BLEND_ALPHA(ps, aa, tmp);
1590                                       }
1591                                     eyy += le->dyy;
1592                                     ey = eyy >> 16;
1593                                     x++;
1594                                  }
1595                             }
1596                           break;
1597                        }
1598 
1599                      while (ey >= y)
1600                        {
1601                           DATA32              tmp;
1602                           DATA8               aa;
1603 
1604                           if ((ey == y) && IN_SEGMENT(x, clx, clw))
1605                             {
1606                                aa = 255 - ((eyy - yy) >> 8);
1607                                ps = s0 + x;
1608                                BLEND_ALPHA(ps, aa, tmp);
1609                             }
1610                           eyy += le->dyy;
1611                           ey = eyy >> 16;
1612                           x++;
1613                        }
1614                      le_rx = x;
1615                      break;
1616                   }
1617                case HORZ_EDGE:
1618                   {
1619                      lx = le_lx;
1620                      rx = le_rx;
1621                      CLIP_SPAN(lx, rx, clx, clrx);
1622                      if (lx <= rx)
1623                        {
1624                           memset(s0 + lx, 255, rx - lx + 1);
1625                           if (lx < x0)
1626                              x0 = lx;
1627                        }
1628                      le_rx++;
1629                      break;
1630                   }
1631 
1632                default:
1633                   break;
1634                }
1635 
1636              /* draw right aa edge */
1637              switch (re->type)
1638                {
1639                case STEEP_EDGE:
1640                   {
1641                      DATA32              tmp;
1642                      DATA8               aa;
1643 
1644                      rx = re_lx + 1;
1645                      if (rx > x1)
1646                         x1 = rx;
1647 
1648                      if (IN_SEGMENT(rx, clx, clw))
1649                        {
1650                           aa = (re->xx - (re_lx << 16)) >> 8;
1651                           ps = s0 + rx;
1652                           BLEND_ALPHA(ps, aa, tmp);
1653                        }
1654 
1655                      if ((re->v1->y == (y + 1)) && (y < clby))
1656                        {
1657                           lx = (re->xx + re->dxx) >> 16;
1658                           rx = lx + 1;
1659                           if (IN_SEGMENT(rx, clx, clw))
1660                             {
1661                                aa = ((re->xx + re->dxx - (lx << 16)) >> 8);
1662                                ps = s1 + rx;
1663                                BLEND_ALPHA(ps, aa, tmp);
1664                                if (rx > nx1)
1665                                   nx1 = rx;
1666                             }
1667                        }
1668                      break;
1669                   }
1670                case SHALLOW_EDGE:
1671                   {
1672                      int                 x, ey, eyy;
1673 
1674                      if (re_rx > x1)
1675                         x1 = re_rx;
1676                      x = re_rx;
1677                      eyy = ((re->v0->y) << 16) + (x - (re->v0->x)) * (re->dyy);
1678                      ey = eyy >> 16;
1679 
1680                      if (re->dyy > 0)
1681                        {
1682                           while (ey >= y)
1683                             {
1684                                DATA32              tmp;
1685                                DATA8               aa;
1686 
1687                                if ((ey == y) && IN_SEGMENT(x, clx, clw))
1688                                  {
1689                                     aa = 255 - ((eyy - yy) >> 8);
1690                                     ps = s0 + x;
1691                                     BLEND_ALPHA(ps, aa, tmp);
1692                                  }
1693                                eyy -= re->dyy;
1694                                ey = eyy >> 16;
1695                                x--;
1696                             }
1697                           re_lx = x;
1698                           break;
1699                        }
1700 
1701                      while (ey < y)
1702                        {
1703                           DATA32              tmp;
1704                           DATA8               aa;
1705 
1706                           if ((ey == prev_y) && IN_SEGMENT(x, clx, clw))
1707                             {
1708                                aa = ((eyy - prev_yy) >> 8);
1709                                ps = s0 + x;
1710                                BLEND_ALPHA(ps, aa, tmp);
1711                             }
1712                           eyy -= re->dyy;
1713                           ey = eyy >> 16;
1714                           x--;
1715                        }
1716                      re_lx = x;
1717 
1718                      if (((y + 1) == re->v1->y) && (y < clby))
1719                        {
1720                           if (x > nx1)
1721                              nx1 = x;
1722                           lx = re->v1->x;
1723                           while ((ey == y) && (x >= lx))
1724                             {
1725                                DATA32              tmp;
1726                                DATA8               aa;
1727 
1728                                if (IN_SEGMENT(x, clx, clw))
1729                                  {
1730                                     aa = ((eyy - yy) >> 8);
1731                                     ps = s1 + x;
1732                                     BLEND_ALPHA(ps, aa, tmp);
1733                                  }
1734                                eyy -= re->dyy;
1735                                ey = eyy >> 16;
1736                                x--;
1737                             }
1738                        }
1739                      break;
1740                   }
1741                case HORZ_EDGE:
1742                   {
1743                      lx = re_lx;
1744                      rx = re_rx;
1745                      CLIP_SPAN(lx, rx, clx, clrx);
1746                      if (lx <= rx)
1747                        {
1748                           memset(s0 + lx, 255, rx - lx + 1);
1749                           if (rx > x1)
1750                              x1 = rx;
1751                        }
1752                      re_lx--;
1753                      break;
1754                   }
1755 
1756                default:
1757                   break;
1758                }
1759 
1760              /* draw span between edges */
1761              lx = le_rx;
1762              rx = re_lx;
1763              CLIP_SPAN(lx, rx, clx, clrx);
1764              if ((lx <= rx) && (y >= cly))
1765                 memset(s0 + lx, 255, rx - lx + 1);
1766 
1767              le->xx += le->dxx;
1768              if (le != re)
1769                 re->xx += re->dxx;
1770 
1771              j += 2;
1772           }
1773 
1774         if (nactive_horz_edges > 0)
1775            DEL_HORZ_EDGES();
1776 
1777         /* draw alpha buffer to dst */
1778         CLIP_SPAN(x0, x1, clx, clrx);
1779         if ((x0 <= x1) && (y >= cly))
1780            sfunc(s0 + x0, color, p + x0, x1 - x0 + 1);
1781 
1782         /* exchange alpha buffers */
1783         ps = s0;
1784         s0 = s1;
1785         s1 = ps;
1786 
1787         prev_yy = yy;
1788         prev_y = y;
1789 
1790         y++;
1791         yy = y << 16;
1792 
1793         p += dstw;
1794      }
1795 
1796    DE_INIT_POLY();
1797 }
1798 
1799 void
__imlib_Polygon_FillToImage(ImlibPoly poly,DATA32 color,ImlibImage * im,int clx,int cly,int clw,int clh,ImlibOp op,char blend,char anti_alias)1800 __imlib_Polygon_FillToImage(ImlibPoly poly, DATA32 color,
1801                             ImlibImage * im, int clx, int cly, int clw, int clh,
1802                             ImlibOp op, char blend, char anti_alias)
1803 {
1804    if ((!poly) || (!poly->points) || (poly->pointcount < 1) || (clw < 0))
1805       return;
1806    if (blend && (!A_VAL(&color)))
1807       return;
1808    if (poly->pointcount == 1)
1809      {
1810         (void)__imlib_Point_DrawToImage(poly->points[0].x, poly->points[0].y,
1811                                         color, im, clx, cly, clw, clh, op,
1812                                         blend, 0);
1813         return;
1814      }
1815    if (poly->pointcount == 2)
1816      {
1817         (void)__imlib_Line_DrawToImage(poly->points[0].x, poly->points[0].y,
1818                                        poly->points[1].x, poly->points[1].y,
1819                                        color, im, clx, cly, clw, clh, op, blend,
1820                                        anti_alias, 0);
1821         return;
1822      }
1823 
1824    if (clw == 0)
1825      {
1826         clw = im->w;
1827         clx = 0;
1828         clh = im->h;
1829         cly = 0;
1830      }
1831 
1832    CLIP_RECT_TO_RECT(clx, cly, clw, clh, 0, 0, im->w, im->h);
1833    if ((clw < 1) || (clh < 1))
1834       return;
1835 
1836    if (blend && IMAGE_HAS_ALPHA(im))
1837       __imlib_build_pow_lut();
1838 
1839    if (anti_alias)
1840       __imlib_Polygon_FillToData_AA(poly, color,
1841                                     im->data, im->w,
1842                                     clx, cly, clw, clh,
1843                                     op, IMAGE_HAS_ALPHA(im), blend);
1844    else
1845       __imlib_Polygon_FillToData(poly, color,
1846                                  im->data, im->w,
1847                                  clx, cly, clw, clh,
1848                                  op, IMAGE_HAS_ALPHA(im), blend);
1849 }
1850