aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/evas/src/lib/engines/common_8/evas_soft8_polygon.c
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/evas/src/lib/engines/common_8/evas_soft8_polygon.c')
-rw-r--r--libraries/evas/src/lib/engines/common_8/evas_soft8_polygon.c230
1 files changed, 230 insertions, 0 deletions
diff --git a/libraries/evas/src/lib/engines/common_8/evas_soft8_polygon.c b/libraries/evas/src/lib/engines/common_8/evas_soft8_polygon.c
new file mode 100644
index 0000000..fb7027e
--- /dev/null
+++ b/libraries/evas/src/lib/engines/common_8/evas_soft8_polygon.c
@@ -0,0 +1,230 @@
1#include <evas_common_soft8.h>
2#include "evas_soft8_scanline_fill.c"
3#include <math.h>
4
5typedef struct _RGBA_Edge RGBA_Edge;
6typedef struct _RGBA_Vertex RGBA_Vertex;
7
8struct _RGBA_Edge {
9 float x, dx;
10 int i;
11};
12
13struct _RGBA_Vertex {
14 float x, y;
15 int i;
16};
17
18#define POLY_EDGE_DEL(_i) \
19{ \
20 int _j; \
21 \
22 for (_j = 0; (_j < num_active_edges) && (edges[_j].i != _i); _j++); \
23 if (_j < num_active_edges) \
24 { \
25 num_active_edges--; \
26 memmove(&(edges[_j]), &(edges[_j + 1]), \
27 (num_active_edges - _j) * sizeof(RGBA_Edge)); \
28 } \
29}
30
31#define POLY_EDGE_ADD(_i, _y) \
32{ \
33 int _j; \
34 float _dx; \
35 RGBA_Vertex *_p, *_q; \
36 if (_i < (n - 1)) _j = _i + 1; \
37 else _j = 0; \
38 if (point[_i].y < point[_j].y) \
39 { \
40 _p = &(point[_i]); \
41 _q = &(point[_j]); \
42 } \
43 else \
44 { \
45 _p = &(point[_j]); \
46 _q = &(point[_i]); \
47 } \
48 edges[num_active_edges].dx = _dx = (_q->x - _p->x) / (_q->y - _p->y); \
49 edges[num_active_edges].x = (_dx * ((float)_y + 0.5 - _p->y)) + _p->x; \
50 edges[num_active_edges].i = _i; \
51 num_active_edges++; \
52}
53
54static int
55polygon_point_sorter(const void *a, const void *b)
56{
57 RGBA_Vertex *p, *q;
58
59 p = (RGBA_Vertex *) a;
60 q = (RGBA_Vertex *) b;
61 if (p->y <= q->y)
62 return -1;
63 return 1;
64}
65
66static int
67polygon_edge_sorter(const void *a, const void *b)
68{
69 RGBA_Edge *p, *q;
70
71 p = (RGBA_Edge *) a;
72 q = (RGBA_Edge *) b;
73 if (p->x <= q->x)
74 return -1;
75 return 1;
76}
77
78void
79evas_common_soft8_polygon_draw(Soft8_Image * dst, RGBA_Draw_Context * dc,
80 RGBA_Polygon_Point * points, int x, int y)
81{
82 RGBA_Polygon_Point *pt;
83 RGBA_Vertex *point;
84 RGBA_Edge *edges;
85 int num_active_edges;
86 int n;
87 int i, j, k;
88 int y0, y1, yi;
89 int ext_x, ext_y, ext_w, ext_h;
90 int *sorted_index;
91 DATA8 alpha;
92 DATA8 gry8;
93
94 alpha = A_VAL(&dc->col.col);
95 if (alpha == 0)
96 return;
97 alpha++;
98
99 gry8 = GRY_8_FROM_RGB(&dc->col.col);
100
101 ext_x = 0;
102 ext_y = 0;
103 ext_w = dst->cache_entry.w;
104 ext_h = dst->cache_entry.h;
105 if (dc->clip.use)
106 RECTS_CLIP_TO_RECT(ext_x, ext_y, ext_w, ext_h,
107 dc->clip.x, dc->clip.y, dc->clip.w, dc->clip.h);
108
109 if ((ext_w <= 0) || (ext_h <= 0))
110 return;
111
112 n = 0;
113 EINA_INLIST_FOREACH(points, pt) n++;
114
115 if (n < 3)
116 return;
117
118 edges = malloc(sizeof(RGBA_Edge) * n);
119 if (!edges)
120 return;
121
122 point = malloc(sizeof(RGBA_Vertex) * n);
123 if (!point)
124 {
125 free(edges);
126 return;
127 }
128
129 sorted_index = malloc(sizeof(int) * n);
130 if (!sorted_index)
131 {
132 free(edges);
133 free(point);
134 return;
135 }
136
137 k = 0;
138 EINA_INLIST_FOREACH(points, pt)
139 {
140 point[k].x = pt->x + x;
141 point[k].y = pt->y + y;
142 point[k].i = k;
143 k++;
144 }
145 qsort(point, n, sizeof(RGBA_Vertex), polygon_point_sorter);
146
147 for (k = 0; k < n; k++)
148 sorted_index[k] = point[k].i;
149
150 k = 0;
151 EINA_INLIST_FOREACH(points, pt)
152 {
153 point[k].x = pt->x + x;
154 point[k].y = pt->y + y;
155 point[k].i = k;
156 k++;
157 }
158
159 y0 = MAX(ext_y, ceil(point[sorted_index[0]].y - 0.5));
160 y1 = MIN(ext_y + ext_h - 1, floor(point[sorted_index[n - 1]].y - 0.5));
161
162 k = 0;
163 num_active_edges = 0;
164
165 for (yi = y0; yi <= y1; yi++)
166 {
167 for (; (k < n) && (point[sorted_index[k]].y <= ((float)yi + 0.5)); k++)
168 {
169 i = sorted_index[k];
170
171 if (i > 0)
172 j = i - 1;
173 else
174 j = n - 1;
175 if (point[j].y <= ((float)yi - 0.5))
176 {
177 POLY_EDGE_DEL(j)}
178 else if (point[j].y > ((float)yi + 0.5))
179 {
180 POLY_EDGE_ADD(j, yi)}
181 if (i < (n - 1))
182 j = i + 1;
183 else
184 j = 0;
185 if (point[j].y <= ((float)yi - 0.5))
186 {
187 POLY_EDGE_DEL(i)}
188 else if (point[j].y > ((float)yi + 0.5))
189 {
190 POLY_EDGE_ADD(i, yi)}
191 }
192
193 qsort(edges, num_active_edges, sizeof(RGBA_Edge), polygon_edge_sorter);
194
195 for (j = 0; j < num_active_edges; j += 2)
196 {
197 int x0, x1;
198
199 x0 = ceil(edges[j].x - 0.5);
200 if (j < (num_active_edges - 1))
201 x1 = floor(edges[j + 1].x - 0.5);
202 else
203 x1 = x0;
204 if ((x1 >= ext_x) && (x0 < (ext_x + ext_w)) && (x0 <= x1))
205 {
206 DATA8 *dst_itr;
207 int w;
208
209 if (x0 < ext_x)
210 x0 = ext_x;
211 if (x1 >= (ext_x + ext_w))
212 x1 = ext_x + ext_w - 1;
213
214 w = (x1 - x0) + 1;
215 dst_itr = dst->pixels + (yi * dst->stride) + x0;
216
217 if (alpha == 0xff)
218 _soft8_scanline_fill_solid_solid(dst_itr, w, gry8);
219 else
220 _soft8_scanline_fill_transp_solid(dst_itr, w, gry8, alpha);
221 }
222 edges[j].x += edges[j].dx;
223 edges[j + 1].x += edges[j + 1].dx;
224 }
225 }
226
227 free(edges);
228 free(point);
229 free(sorted_index);
230}