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