diff options
Diffstat (limited to 'libraries/evas/src/modules/engines/directfb/polygon.c')
-rw-r--r-- | libraries/evas/src/modules/engines/directfb/polygon.c | 269 |
1 files changed, 269 insertions, 0 deletions
diff --git a/libraries/evas/src/modules/engines/directfb/polygon.c b/libraries/evas/src/modules/engines/directfb/polygon.c new file mode 100644 index 0000000..715fd84 --- /dev/null +++ b/libraries/evas/src/modules/engines/directfb/polygon.c | |||
@@ -0,0 +1,269 @@ | |||
1 | #include <math.h> | ||
2 | #include "evas_engine.h" | ||
3 | |||
4 | /* reduce calls to DirectFB (FillSpans), but uses twice as much memory */ | ||
5 | //#define USE_SPAN_RECTS 1 | ||
6 | |||
7 | #define MAX_SPANS 512 | ||
8 | typedef struct _RGBA_Edge RGBA_Edge; | ||
9 | typedef struct _RGBA_Vertex RGBA_Vertex; | ||
10 | |||
11 | struct _RGBA_Edge | ||
12 | { | ||
13 | double x, dx; | ||
14 | int i; | ||
15 | }; | ||
16 | |||
17 | struct _RGBA_Vertex | ||
18 | { | ||
19 | double x, y; | ||
20 | int i; | ||
21 | }; | ||
22 | |||
23 | #define POLY_EDGE_DEL(_i) \ | ||
24 | { \ | ||
25 | int _j; \ | ||
26 | \ | ||
27 | for (_j = 0; (_j < num_active_edges) && (edges[_j].i != _i); _j++); \ | ||
28 | if (_j < num_active_edges) \ | ||
29 | { \ | ||
30 | num_active_edges--; \ | ||
31 | memmove(&(edges[_j]), &(edges[_j + 1]), \ | ||
32 | (num_active_edges - _j) * sizeof(RGBA_Edge)); \ | ||
33 | } \ | ||
34 | } | ||
35 | |||
36 | #define POLY_EDGE_ADD(_i, _y) \ | ||
37 | { \ | ||
38 | int _j; \ | ||
39 | float _dx; \ | ||
40 | RGBA_Vertex *_p, *_q; \ | ||
41 | if (_i < (n - 1)) _j = _i + 1; \ | ||
42 | else _j = 0; \ | ||
43 | if (point[_i].y < point[_j].y) \ | ||
44 | { \ | ||
45 | _p = &(point[_i]); \ | ||
46 | _q = &(point[_j]); \ | ||
47 | } \ | ||
48 | else \ | ||
49 | { \ | ||
50 | _p = &(point[_j]); \ | ||
51 | _q = &(point[_i]); \ | ||
52 | } \ | ||
53 | edges[num_active_edges].dx = _dx = (_q->x - _p->x) / (_q->y - _p->y); \ | ||
54 | edges[num_active_edges].x = (_dx * ((float)_y + 0.5 - _p->y)) + _p->x; \ | ||
55 | edges[num_active_edges].i = _i; \ | ||
56 | num_active_edges++; \ | ||
57 | } | ||
58 | |||
59 | static int | ||
60 | polygon_point_sorter(const void *a, const void *b) | ||
61 | { | ||
62 | RGBA_Vertex *p, *q; | ||
63 | |||
64 | p = (RGBA_Vertex *)a; | ||
65 | q = (RGBA_Vertex *)b; | ||
66 | if (p->y <= q->y) return -1; | ||
67 | return 1; | ||
68 | } | ||
69 | |||
70 | static int | ||
71 | polygon_edge_sorter(const void *a, const void *b) | ||
72 | { | ||
73 | RGBA_Edge *p, *q; | ||
74 | |||
75 | p = (RGBA_Edge *)a; | ||
76 | q = (RGBA_Edge *)b; | ||
77 | if (p->x <= q->x) return -1; | ||
78 | return 1; | ||
79 | } | ||
80 | |||
81 | #ifndef USE_SPAN_RECTS | ||
82 | typedef DFBSpan span_t; | ||
83 | |||
84 | static void | ||
85 | polygon_span_add(span_t *span, int y __UNUSED__, int x, int w) | ||
86 | { | ||
87 | span->x = x; | ||
88 | span->w = w; | ||
89 | } | ||
90 | |||
91 | static void | ||
92 | polygon_spans_fill(IDirectFBSurface *surface, int y, const span_t *spans, int n_spans) | ||
93 | { | ||
94 | /* directfb automatically increments y for each span */ | ||
95 | for (; n_spans > 0; n_spans--, spans++) | ||
96 | surface->FillSpans(surface, y, spans, 1); | ||
97 | } | ||
98 | #else /* USE_SPAN_RECTS */ | ||
99 | typedef DFBRectangle span_t; | ||
100 | |||
101 | static void | ||
102 | polygon_span_add(span_t *span, int y, int x, int w) | ||
103 | { | ||
104 | span->x = x; | ||
105 | span->y = y; | ||
106 | span->w = w; | ||
107 | span->h = 1; | ||
108 | } | ||
109 | |||
110 | static void | ||
111 | polygon_spans_fill(IDirectFBSurface *surface, int y, const span_t *spans, int n_spans) | ||
112 | { | ||
113 | surface->FillRectangles(surface, spans, n_spans); | ||
114 | } | ||
115 | #endif /* USE_SPAN_RECTS */ | ||
116 | |||
117 | |||
118 | void | ||
119 | _dfb_polygon_draw(IDirectFBSurface *surface, RGBA_Draw_Context *dc, Eina_Inlist *points, int px, int py) | ||
120 | { | ||
121 | RGBA_Polygon_Point *pt; | ||
122 | RGBA_Vertex *point; | ||
123 | RGBA_Edge *edges; | ||
124 | int num_active_edges; | ||
125 | int n; | ||
126 | int i, j, k; | ||
127 | int y0, y1, y; | ||
128 | int ext_x, ext_y, ext_w, ext_h; | ||
129 | int *sorted_index; | ||
130 | |||
131 | ext_x = 0; | ||
132 | ext_y = 0; | ||
133 | surface->GetSize(surface, &ext_w, &ext_h); | ||
134 | if (dc->clip.use) | ||
135 | { | ||
136 | if (dc->clip.x > ext_x) | ||
137 | { | ||
138 | ext_w += ext_x - dc->clip.x; | ||
139 | ext_x = dc->clip.x; | ||
140 | } | ||
141 | if ((ext_x + ext_w) > (dc->clip.x + dc->clip.w)) | ||
142 | { | ||
143 | ext_w = (dc->clip.x + dc->clip.w) - ext_x; | ||
144 | } | ||
145 | if (dc->clip.y > ext_y) | ||
146 | { | ||
147 | ext_h += ext_y - dc->clip.y; | ||
148 | ext_y = dc->clip.y; | ||
149 | } | ||
150 | if ((ext_y + ext_h) > (dc->clip.y + dc->clip.h)) | ||
151 | { | ||
152 | ext_h = (dc->clip.y + dc->clip.h) - ext_y; | ||
153 | } | ||
154 | } | ||
155 | if ((ext_w <= 0) || (ext_h <= 0)) return; | ||
156 | |||
157 | evas_common_cpu_end_opt(); | ||
158 | |||
159 | if (!_dfb_surface_set_color_from_context(surface, dc)) | ||
160 | return; | ||
161 | |||
162 | n = 0; EINA_INLIST_FOREACH(points, pt) n++; | ||
163 | if (n < 3) return; | ||
164 | edges = malloc(sizeof(RGBA_Edge) * n); | ||
165 | if (!edges) return; | ||
166 | point = malloc(sizeof(RGBA_Vertex) * n); | ||
167 | if (!point) | ||
168 | { | ||
169 | free(edges); | ||
170 | return; | ||
171 | } | ||
172 | sorted_index = malloc(sizeof(int) * n); | ||
173 | if (!sorted_index) | ||
174 | { | ||
175 | free(edges); | ||
176 | free(point); | ||
177 | return; | ||
178 | } | ||
179 | |||
180 | k = 0; | ||
181 | EINA_INLIST_FOREACH(points, pt) | ||
182 | { | ||
183 | point[k].x = pt->x + px; | ||
184 | point[k].y = pt->y + py; | ||
185 | point[k].i = k; | ||
186 | k++; | ||
187 | } | ||
188 | qsort(point, n, sizeof(RGBA_Vertex), polygon_point_sorter); | ||
189 | for (k = 0; k < n; k++) sorted_index[k] = point[k].i; | ||
190 | k = 0; | ||
191 | EINA_INLIST_FOREACH(points, pt) | ||
192 | { | ||
193 | point[k].x = pt->x + px; | ||
194 | point[k].y = pt->y + py; | ||
195 | point[k].i = k; | ||
196 | k++; | ||
197 | } | ||
198 | |||
199 | y0 = MAX(ext_y, ceil(point[sorted_index[0]].y - 0.5)); | ||
200 | y1 = MIN(ext_y + ext_h - 1, floor(point[sorted_index[n - 1]].y - 0.5)); | ||
201 | |||
202 | k = 0; | ||
203 | num_active_edges = 0; | ||
204 | |||
205 | for (y = y0; y <= y1; y++) | ||
206 | { | ||
207 | span_t spans[MAX_SPANS]; | ||
208 | unsigned int n_spans = 0; | ||
209 | |||
210 | for (; (k < n) && (point[sorted_index[k]].y <= ((double)y + 0.5)); k++) | ||
211 | { | ||
212 | i = sorted_index[k]; | ||
213 | |||
214 | if (i > 0) j = i - 1; | ||
215 | else j = n - 1; | ||
216 | if (point[j].y <= ((double)y - 0.5)) | ||
217 | { | ||
218 | POLY_EDGE_DEL(j) | ||
219 | } | ||
220 | else if (point[j].y > ((double)y + 0.5)) | ||
221 | { | ||
222 | POLY_EDGE_ADD(j, y) | ||
223 | } | ||
224 | if (i < (n - 1)) j = i + 1; | ||
225 | else j = 0; | ||
226 | if (point[j].y <= ((double)y - 0.5)) | ||
227 | { | ||
228 | POLY_EDGE_DEL(i) | ||
229 | } | ||
230 | else if (point[j].y > ((double)y + 0.5)) | ||
231 | { | ||
232 | POLY_EDGE_ADD(i, y) | ||
233 | } | ||
234 | } | ||
235 | |||
236 | qsort(edges, num_active_edges, sizeof(RGBA_Edge), polygon_edge_sorter); | ||
237 | |||
238 | for (j = 0; j < num_active_edges; j += 2) | ||
239 | { | ||
240 | int x0, x1; | ||
241 | |||
242 | x0 = ceil(edges[j].x - 0.5); | ||
243 | if (j < (num_active_edges - 1)) | ||
244 | x1 = floor(edges[j + 1].x - 0.5); | ||
245 | else | ||
246 | x1 = x0; | ||
247 | if ((x1 >= ext_x) && (x0 < (ext_x + ext_w)) && (x0 <= x1)) | ||
248 | { | ||
249 | if (n_spans == MAX_SPANS) | ||
250 | { | ||
251 | polygon_spans_fill(surface, y, spans, n_spans); | ||
252 | n_spans = 0; | ||
253 | } | ||
254 | |||
255 | polygon_span_add(spans + n_spans, y, x0, (x1 - x0) + 1); | ||
256 | n_spans++; | ||
257 | } | ||
258 | edges[j].x += edges[j].dx; | ||
259 | edges[j + 1].x += edges[j + 1].dx; | ||
260 | } | ||
261 | |||
262 | if (n_spans) | ||
263 | polygon_spans_fill(surface, y, spans, n_spans); | ||
264 | } | ||
265 | |||
266 | free(edges); | ||
267 | free(point); | ||
268 | free(sorted_index); | ||
269 | } | ||