diff options
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.c | 293 |
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 | |||
6 | typedef struct _RGBA_Span RGBA_Span; | ||
7 | typedef struct _RGBA_Edge RGBA_Edge; | ||
8 | typedef struct _RGBA_Vertex RGBA_Vertex; | ||
9 | |||
10 | struct _RGBA_Span | ||
11 | { | ||
12 | EINA_INLIST; | ||
13 | int x, y, w; | ||
14 | }; | ||
15 | |||
16 | struct _RGBA_Edge | ||
17 | { | ||
18 | double x, dx; | ||
19 | int i; | ||
20 | }; | ||
21 | |||
22 | struct _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 | |||
64 | EAPI void | ||
65 | evas_common_polygon_init(void) | ||
66 | { | ||
67 | } | ||
68 | |||
69 | EAPI RGBA_Polygon_Point * | ||
70 | evas_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 | |||
82 | EAPI RGBA_Polygon_Point * | ||
83 | evas_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 | |||
99 | static int | ||
100 | polygon_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 | |||
110 | static int | ||
111 | polygon_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 | |||
121 | EAPI void | ||
122 | evas_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 | } | ||