summaryrefslogtreecommitdiff
path: root/src/lib/evas/common/evas_polygon_main.c
diff options
context:
space:
mode:
authorVincent Torri <vincent.torri@gmail.com>2012-11-04 11:51:42 +0000
committerVincent Torri <vincent.torri@gmail.com>2012-11-04 11:51:42 +0000
commitc15e9c6575c3b5f39ded167dda5259de3de96151 (patch)
tree5115d7ae3620af24c2bc094cd062575af7adeda9 /src/lib/evas/common/evas_polygon_main.c
parenta5ac6a987caec5a7f7596a25d0a065b9cc94c50c (diff)
merge: and now Evas
I've tested make -j 3 install and it works nicely I've tested expedite with software and opengl xlib, and it works. Not tested other engines, so please report any problems (engines or other) on the ML. TODO: examples and tests, I'll add them later ISSUE: Eina_Unicode size check. It indirectly depends on eina_config.h, which is created at the end of the configure script. So its size is always 0. I don't know how that size is used, so I can't do a lot, for now. SVN revision: 78895
Diffstat (limited to 'src/lib/evas/common/evas_polygon_main.c')
-rw-r--r--src/lib/evas/common/evas_polygon_main.c320
1 files changed, 320 insertions, 0 deletions
diff --git a/src/lib/evas/common/evas_polygon_main.c b/src/lib/evas/common/evas_polygon_main.c
new file mode 100644
index 0000000000..f6c79c837a
--- /dev/null
+++ b/src/lib/evas/common/evas_polygon_main.c
@@ -0,0 +1,320 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#include <math.h>
6
7#include "evas_common.h"
8#include "evas_blend_private.h"
9
10typedef struct _RGBA_Span RGBA_Span;
11typedef struct _RGBA_Edge RGBA_Edge;
12typedef struct _RGBA_Vertex RGBA_Vertex;
13
14struct _RGBA_Span
15{
16 EINA_INLIST;
17 int x, y, w;
18};
19
20struct _RGBA_Edge
21{
22 double x, dx;
23 int i;
24};
25
26struct _RGBA_Vertex
27{
28 double x, y;
29 int i;
30};
31
32#define POLY_EDGE_DEL(_i) \
33{ \
34 int _j; \
35 \
36 for (_j = 0; (_j < num_active_edges) && (edges[_j].i != _i); _j++); \
37 if (_j < num_active_edges) \
38 { \
39 num_active_edges--; \
40 memmove(&(edges[_j]), &(edges[_j + 1]), \
41 (num_active_edges - _j) * sizeof(RGBA_Edge)); \
42 } \
43}
44
45#define POLY_EDGE_ADD(_i, _y) \
46{ \
47 int _j; \
48 float _dx; \
49 RGBA_Vertex *_p, *_q; \
50 if (_i < (n - 1)) _j = _i + 1; \
51 else _j = 0; \
52 if (point[_i].y < point[_j].y) \
53 { \
54 _p = &(point[_i]); \
55 _q = &(point[_j]); \
56 } \
57 else \
58 { \
59 _p = &(point[_j]); \
60 _q = &(point[_i]); \
61 } \
62 edges[num_active_edges].dx = _dx = (_q->x - _p->x) / (_q->y - _p->y); \
63 edges[num_active_edges].x = (_dx * ((float)_y + 0.5 - _p->y)) + _p->x; \
64 edges[num_active_edges].i = _i; \
65 num_active_edges++; \
66}
67
68EAPI void
69evas_common_polygon_init(void)
70{
71}
72
73EAPI RGBA_Polygon_Point *
74evas_common_polygon_point_add(RGBA_Polygon_Point *points, int x, int y)
75{
76 RGBA_Polygon_Point *pt;
77
78 pt = malloc(sizeof(RGBA_Polygon_Point));
79 if (!pt) return points;
80 pt->x = x;
81 pt->y = y;
82 points = (RGBA_Polygon_Point *)eina_inlist_append(EINA_INLIST_GET(points), EINA_INLIST_GET(pt));
83 return points;
84}
85
86EAPI RGBA_Polygon_Point *
87evas_common_polygon_points_clear(RGBA_Polygon_Point *points)
88{
89 if (points)
90 {
91 while (points)
92 {
93 RGBA_Polygon_Point *old_p;
94
95 old_p = points;
96 points = (RGBA_Polygon_Point *)eina_inlist_remove(EINA_INLIST_GET(points), EINA_INLIST_GET(points));
97 free(old_p);
98 }
99 }
100 return NULL;
101}
102
103static int
104polygon_point_sorter(const void *a, const void *b)
105{
106 RGBA_Vertex *p, *q;
107
108 p = (RGBA_Vertex *)a;
109 q = (RGBA_Vertex *)b;
110 if (p->y <= q->y) return -1;
111 return 1;
112}
113
114static int
115polygon_edge_sorter(const void *a, const void *b)
116{
117 RGBA_Edge *p, *q;
118
119 p = (RGBA_Edge *)a;
120 q = (RGBA_Edge *)b;
121 if (p->x <= q->x) return -1;
122 return 1;
123}
124
125EAPI void
126evas_common_polygon_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Polygon_Point *points, int x, int y)
127{
128 RGBA_Gfx_Func func;
129 RGBA_Polygon_Point *pt;
130 RGBA_Vertex *point;
131 RGBA_Edge *edges;
132 Eina_Inlist *spans;
133 int num_active_edges;
134 int n;
135 int i, j, k;
136 int yy0, yy1, yi;
137 int ext_x, ext_y, ext_w, ext_h;
138 int *sorted_index;
139
140#ifdef HAVE_PIXMAN
141# ifdef PIXMAN_POLY
142 pixman_op_t op = PIXMAN_OP_SRC; // _EVAS_RENDER_COPY
143 if (dc->render_op == _EVAS_RENDER_BLEND)
144 op = PIXMAN_OP_OVER;
145# endif
146#endif
147
148 ext_x = 0;
149 ext_y = 0;
150 ext_w = dst->cache_entry.w;
151 ext_h = dst->cache_entry.h;
152 if (dc->clip.use)
153 {
154 if (dc->clip.x > ext_x)
155 {
156 ext_w += ext_x - dc->clip.x;
157 ext_x = dc->clip.x;
158 }
159 if ((ext_x + ext_w) > (dc->clip.x + dc->clip.w))
160 {
161 ext_w = (dc->clip.x + dc->clip.w) - ext_x;
162 }
163 if (dc->clip.y > ext_y)
164 {
165 ext_h += ext_y - dc->clip.y;
166 ext_y = dc->clip.y;
167 }
168 if ((ext_y + ext_h) > (dc->clip.y + dc->clip.h))
169 {
170 ext_h = (dc->clip.y + dc->clip.h) - ext_y;
171 }
172 }
173 if ((ext_w <= 0) || (ext_h <= 0)) return;
174
175 evas_common_cpu_end_opt();
176
177 n = 0; EINA_INLIST_FOREACH(points, pt) n++;
178 if (n < 3) return;
179 edges = malloc(sizeof(RGBA_Edge) * n);
180 if (!edges) return;
181 point = malloc(sizeof(RGBA_Vertex) * n);
182 if (!point)
183 {
184 free(edges);
185 return;
186 }
187 sorted_index = malloc(sizeof(int) * n);
188 if (!sorted_index)
189 {
190 free(edges);
191 free(point);
192 return;
193 }
194
195 k = 0;
196 EINA_INLIST_FOREACH(points, pt)
197 {
198 point[k].x = pt->x + x;
199 point[k].y = pt->y + y;
200 point[k].i = k;
201 k++;
202 }
203 qsort(point, n, sizeof(RGBA_Vertex), polygon_point_sorter);
204 for (k = 0; k < n; k++) sorted_index[k] = point[k].i;
205 k = 0;
206 EINA_INLIST_FOREACH(points, pt)
207 {
208 point[k].x = pt->x + x;
209 point[k].y = pt->y + y;
210 point[k].i = k;
211 k++;
212 }
213
214 yy0 = MAX(ext_y, ceil(point[sorted_index[0]].y - 0.5));
215 yy1 = MIN(ext_y + ext_h - 1, floor(point[sorted_index[n - 1]].y - 0.5));
216
217 k = 0;
218 num_active_edges = 0;
219 spans = NULL;
220
221 for (yi = yy0; yi <= yy1; yi++)
222 {
223 for (; (k < n) && (point[sorted_index[k]].y <= ((double)yi + 0.5)); k++)
224 {
225 i = sorted_index[k];
226
227 if (i > 0) j = i - 1;
228 else j = n - 1;
229 if (point[j].y <= ((double)yi - 0.5))
230 {
231 POLY_EDGE_DEL(j)
232 }
233 else if (point[j].y > ((double)yi + 0.5))
234 {
235 POLY_EDGE_ADD(j, yi)
236 }
237 if (i < (n - 1)) j = i + 1;
238 else j = 0;
239 if (point[j].y <= ((double)yi - 0.5))
240 {
241 POLY_EDGE_DEL(i)
242 }
243 else if (point[j].y > ((double)yi + 0.5))
244 {
245 POLY_EDGE_ADD(i, yi)
246 }
247 }
248
249 qsort(edges, num_active_edges, sizeof(RGBA_Edge), polygon_edge_sorter);
250
251 for (j = 0; j < num_active_edges; j += 2)
252 {
253 int x0, x1;
254
255 x0 = ceil(edges[j].x - 0.5);
256 if (j < (num_active_edges - 1))
257 x1 = floor(edges[j + 1].x - 0.5);
258 else
259 x1 = x0;
260 if ((x1 >= ext_x) && (x0 < (ext_x + ext_w)) && (x0 <= x1))
261 {
262 RGBA_Span *span;
263
264 if (x0 < ext_x) x0 = ext_x;
265 if (x1 >= (ext_x + ext_w)) x1 = ext_x + ext_w - 1;
266 span = malloc(sizeof(RGBA_Span));
267 spans = eina_inlist_append(spans, EINA_INLIST_GET(span));
268 span->y = yi;
269 span->x = x0;
270 span->w = (x1 - x0) + 1;
271 }
272 edges[j].x += edges[j].dx;
273 edges[j + 1].x += edges[j + 1].dx;
274 }
275 }
276
277 free(edges);
278 free(point);
279 free(sorted_index);
280
281 func = evas_common_gfx_func_composite_color_span_get(dc->col.col, dst, 1, dc->render_op);
282 if (spans)
283 {
284 RGBA_Span *span;
285
286 EINA_INLIST_FOREACH(spans, span)
287 {
288 DATA32 *ptr;
289
290#ifdef HAVE_PIXMAN
291# ifdef PIXMAN_POLY
292 if ((dst->pixman.im) && (dc->col.pixman_color_image) &&
293 (!dc->mask.mask))
294 pixman_image_composite(op, dc->col.pixman_color_image,
295 NULL, dst->pixman.im,
296 span->x, span->y, 0, 0,
297 span->x, span->y, span->w, 1);
298 else if ((dst->pixman.im) && (dc->col.pixman_color_image) &&
299 (dc->mask.mask))
300 pixman_image_composite(op, dc->col.pixman_color_image,
301 dc->mask.mask->pixman.im,
302 dst->pixman.im,
303 span->x, span->y, 0, 0,
304 span->x, span->y, span->w, 1);
305 else
306# endif
307#endif
308 {
309 ptr = dst->image.data + (span->y * (dst->cache_entry.w)) + span->x;
310 func(NULL, NULL, dc->col.col, ptr, span->w);
311 }
312 }
313 while (spans)
314 {
315 span = (RGBA_Span *)spans;
316 spans = eina_inlist_remove(spans, spans);
317 free(span);
318 }
319 }
320}