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