aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/evas/src/lib/engines/common/evas_polygon_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/evas/src/lib/engines/common/evas_polygon_main.c')
-rw-r--r--libraries/evas/src/lib/engines/common/evas_polygon_main.c293
1 files changed, 293 insertions, 0 deletions
diff --git a/libraries/evas/src/lib/engines/common/evas_polygon_main.c b/libraries/evas/src/lib/engines/common/evas_polygon_main.c
new file mode 100644
index 0000000..bca3f83
--- /dev/null
+++ b/libraries/evas/src/lib/engines/common/evas_polygon_main.c
@@ -0,0 +1,293 @@
1#include <math.h>
2
3#include "evas_common.h"
4#include "evas_blend_private.h"
5
6typedef struct _RGBA_Span RGBA_Span;
7typedef struct _RGBA_Edge RGBA_Edge;
8typedef struct _RGBA_Vertex RGBA_Vertex;
9
10struct _RGBA_Span
11{
12 EINA_INLIST;
13 int x, y, w;
14};
15
16struct _RGBA_Edge
17{
18 double x, dx;
19 int i;
20};
21
22struct _RGBA_Vertex
23{
24 double x, y;
25 int i;
26};
27
28#define POLY_EDGE_DEL(_i) \
29{ \
30 int _j; \
31 \
32 for (_j = 0; (_j < num_active_edges) && (edges[_j].i != _i); _j++); \
33 if (_j < num_active_edges) \
34 { \
35 num_active_edges--; \
36 memmove(&(edges[_j]), &(edges[_j + 1]), \
37 (num_active_edges - _j) * sizeof(RGBA_Edge)); \
38 } \
39}
40
41#define POLY_EDGE_ADD(_i, _y) \
42{ \
43 int _j; \
44 float _dx; \
45 RGBA_Vertex *_p, *_q; \
46 if (_i < (n - 1)) _j = _i + 1; \
47 else _j = 0; \
48 if (point[_i].y < point[_j].y) \
49 { \
50 _p = &(point[_i]); \
51 _q = &(point[_j]); \
52 } \
53 else \
54 { \
55 _p = &(point[_j]); \
56 _q = &(point[_i]); \
57 } \
58 edges[num_active_edges].dx = _dx = (_q->x - _p->x) / (_q->y - _p->y); \
59 edges[num_active_edges].x = (_dx * ((float)_y + 0.5 - _p->y)) + _p->x; \
60 edges[num_active_edges].i = _i; \
61 num_active_edges++; \
62}
63
64EAPI void
65evas_common_polygon_init(void)
66{
67}
68
69EAPI RGBA_Polygon_Point *
70evas_common_polygon_point_add(RGBA_Polygon_Point *points, int x, int y)
71{
72 RGBA_Polygon_Point *pt;
73
74 pt = malloc(sizeof(RGBA_Polygon_Point));
75 if (!pt) return points;
76 pt->x = x;
77 pt->y = y;
78 points = (RGBA_Polygon_Point *)eina_inlist_append(EINA_INLIST_GET(points), EINA_INLIST_GET(pt));
79 return points;
80}
81
82EAPI RGBA_Polygon_Point *
83evas_common_polygon_points_clear(RGBA_Polygon_Point *points)
84{
85 if (points)
86 {
87 while (points)
88 {
89 RGBA_Polygon_Point *old_p;
90
91 old_p = points;
92 points = (RGBA_Polygon_Point *)eina_inlist_remove(EINA_INLIST_GET(points), EINA_INLIST_GET(points));
93 free(old_p);
94 }
95 }
96 return NULL;
97}
98
99static int
100polygon_point_sorter(const void *a, const void *b)
101{
102 RGBA_Vertex *p, *q;
103
104 p = (RGBA_Vertex *)a;
105 q = (RGBA_Vertex *)b;
106 if (p->y <= q->y) return -1;
107 return 1;
108}
109
110static int
111polygon_edge_sorter(const void *a, const void *b)
112{
113 RGBA_Edge *p, *q;
114
115 p = (RGBA_Edge *)a;
116 q = (RGBA_Edge *)b;
117 if (p->x <= q->x) return -1;
118 return 1;
119}
120
121EAPI void
122evas_common_polygon_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Polygon_Point *points, int x, int y)
123{
124 RGBA_Gfx_Func func;
125 RGBA_Polygon_Point *pt;
126 RGBA_Vertex *point;
127 RGBA_Edge *edges;
128 Eina_Inlist *spans;
129 int num_active_edges;
130 int n;
131 int i, j, k;
132 int y0, y1, yi;
133 int ext_x, ext_y, ext_w, ext_h;
134 int *sorted_index;
135
136 ext_x = 0;
137 ext_y = 0;
138 ext_w = dst->cache_entry.w;
139 ext_h = dst->cache_entry.h;
140 if (dc->clip.use)
141 {
142 if (dc->clip.x > ext_x)
143 {
144 ext_w += ext_x - dc->clip.x;
145 ext_x = dc->clip.x;
146 }
147 if ((ext_x + ext_w) > (dc->clip.x + dc->clip.w))
148 {
149 ext_w = (dc->clip.x + dc->clip.w) - ext_x;
150 }
151 if (dc->clip.y > ext_y)
152 {
153 ext_h += ext_y - dc->clip.y;
154 ext_y = dc->clip.y;
155 }
156 if ((ext_y + ext_h) > (dc->clip.y + dc->clip.h))
157 {
158 ext_h = (dc->clip.y + dc->clip.h) - ext_y;
159 }
160 }
161 if ((ext_w <= 0) || (ext_h <= 0)) return;
162
163 evas_common_cpu_end_opt();
164
165 n = 0; EINA_INLIST_FOREACH(points, pt) n++;
166 if (n < 3) return;
167 edges = malloc(sizeof(RGBA_Edge) * n);
168 if (!edges) return;
169 point = malloc(sizeof(RGBA_Vertex) * n);
170 if (!point)
171 {
172 free(edges);
173 return;
174 }
175 sorted_index = malloc(sizeof(int) * n);
176 if (!sorted_index)
177 {
178 free(edges);
179 free(point);
180 return;
181 }
182
183 k = 0;
184 EINA_INLIST_FOREACH(points, pt)
185 {
186 point[k].x = pt->x + x;
187 point[k].y = pt->y + y;
188 point[k].i = k;
189 k++;
190 }
191 qsort(point, n, sizeof(RGBA_Vertex), polygon_point_sorter);
192 for (k = 0; k < n; k++) sorted_index[k] = point[k].i;
193 k = 0;
194 EINA_INLIST_FOREACH(points, pt)
195 {
196 point[k].x = pt->x + x;
197 point[k].y = pt->y + y;
198 point[k].i = k;
199 k++;
200 }
201
202 y0 = MAX(ext_y, ceil(point[sorted_index[0]].y - 0.5));
203 y1 = MIN(ext_y + ext_h - 1, floor(point[sorted_index[n - 1]].y - 0.5));
204
205 k = 0;
206 num_active_edges = 0;
207 spans = NULL;
208
209 for (yi = y0; yi <= y1; yi++)
210 {
211 for (; (k < n) && (point[sorted_index[k]].y <= ((double)yi + 0.5)); k++)
212 {
213 i = sorted_index[k];
214
215 if (i > 0) j = i - 1;
216 else j = n - 1;
217 if (point[j].y <= ((double)yi - 0.5))
218 {
219 POLY_EDGE_DEL(j)
220 }
221 else if (point[j].y > ((double)yi + 0.5))
222 {
223 POLY_EDGE_ADD(j, yi)
224 }
225 if (i < (n - 1)) j = i + 1;
226 else j = 0;
227 if (point[j].y <= ((double)yi - 0.5))
228 {
229 POLY_EDGE_DEL(i)
230 }
231 else if (point[j].y > ((double)yi + 0.5))
232 {
233 POLY_EDGE_ADD(i, yi)
234 }
235 }
236
237 qsort(edges, num_active_edges, sizeof(RGBA_Edge), polygon_edge_sorter);
238
239 for (j = 0; j < num_active_edges; j += 2)
240 {
241 int x0, x1;
242
243 x0 = ceil(edges[j].x - 0.5);
244 if (j < (num_active_edges - 1))
245 x1 = floor(edges[j + 1].x - 0.5);
246 else
247 x1 = x0;
248 if ((x1 >= ext_x) && (x0 < (ext_x + ext_w)) && (x0 <= x1))
249 {
250 RGBA_Span *span;
251
252 if (x0 < ext_x) x0 = ext_x;
253 if (x1 >= (ext_x + ext_w)) x1 = ext_x + ext_w - 1;
254 span = malloc(sizeof(RGBA_Span));
255 spans = eina_inlist_append(spans, EINA_INLIST_GET(span));
256 span->y = yi;
257 span->x = x0;
258 span->w = (x1 - x0) + 1;
259 }
260 edges[j].x += edges[j].dx;
261 edges[j + 1].x += edges[j + 1].dx;
262 }
263 }
264
265 free(edges);
266 free(point);
267 free(sorted_index);
268
269 func = evas_common_gfx_func_composite_color_span_get(dc->col.col, dst, 1, dc->render_op);
270 if (spans)
271 {
272 RGBA_Span *span;
273
274 EINA_INLIST_FOREACH(spans, span)
275 {
276 DATA32 *ptr;
277
278#ifdef EVAS_SLI
279 if (((span->y) % dc->sli.h) == dc->sli.y)
280#endif
281 {
282 ptr = dst->image.data + (span->y * (dst->cache_entry.w)) + span->x;
283 func(NULL, NULL, dc->col.col, ptr, span->w);
284 }
285 }
286 while (spans)
287 {
288 span = (RGBA_Span *)spans;
289 spans = eina_inlist_remove(spans, spans);
290 free(span);
291 }
292 }
293}