summaryrefslogtreecommitdiff
path: root/src/lib/evas/common/evas_map_image_aa.c
diff options
context:
space:
mode:
authorChunEon Park <hermet@hermet.pe.kr>2014-11-26 15:12:25 +0900
committerChunEon Park <hermet@hermet.pe.kr>2014-11-26 15:12:25 +0900
commita3b3e1ecad73f2da2e95d86670c336a474cff77f (patch)
tree2460f9ce0a6ceaf0ac1218628d02c753f9d53b17 /src/lib/evas/common/evas_map_image_aa.c
parent215b52ecc108b2b13814534d75565152e8c0973a (diff)
evas/map: support aa in basic c computation.
Diffstat (limited to 'src/lib/evas/common/evas_map_image_aa.c')
-rw-r--r--src/lib/evas/common/evas_map_image_aa.c297
1 files changed, 297 insertions, 0 deletions
diff --git a/src/lib/evas/common/evas_map_image_aa.c b/src/lib/evas/common/evas_map_image_aa.c
new file mode 100644
index 0000000000..671e067900
--- /dev/null
+++ b/src/lib/evas/common/evas_map_image_aa.c
@@ -0,0 +1,297 @@
1/*
2 * evas_map_image_aa.c
3 *
4 * Created on: Nov 21, 2014
5 * Author: hermet
6 */
7
8#define READY_TX() \
9{ \
10 if (eidx == 0) \
11 { \
12 tx[0] = edge2.x; \
13 tx[1] = spans[y].span[0].x[0]; \
14 } \
15 else \
16 { \
17 tx[0] = spans[y].span[0].x[1]; \
18 tx[1] = edge2.x; \
19 } \
20}
21
22#define READY_TX2() \
23{ \
24 if (eidx == 0) \
25 { \
26 tx2[0] = edge2.x; \
27 tx2[1] = edge1.x; \
28 } \
29 else \
30 { \
31 tx2[0] = edge1.x; \
32 tx2[1] = edge2.x; \
33 } \
34}
35
36#define PUSH_EDGES(xx) \
37{ \
38 if (!leftover) \
39 { \
40 edge1.x = edge2.x; \
41 edge1.y = edge2.y; \
42 edge2.x = (xx); \
43 edge2.y = y; \
44 } \
45 else \
46 { \
47 edge1.y = edge2.y; \
48 edge2.y = y; \
49 } \
50 reset_tx2 = EINA_TRUE; \
51}
52
53//Vertical Inside Direction
54#define VERT_INSIDE(rewind, y_advance) \
55{ \
56 int cov_range = edge2.y - edge1.y; \
57 int coverage = (256 / (cov_range + 1)); \
58 int ry; \
59 int val; \
60 for (ry = 1; ry < ((rewind) + 1); ry++) \
61 { \
62 int ridx = (y - ry) + (y_advance); \
63 if (spans[ridx].aa_len[eidx] > 1) continue; \
64 if (eidx == 1) \
65 val = (256 - (coverage * (ry + (cov_range - (rewind))))); \
66 else \
67 val = (coverage * (ry + (cov_range - (rewind)))); \
68 if ((spans[ridx].aa_len[eidx] == 0) || \
69 (val < spans[ridx].aa_cov[eidx])) \
70 spans[ridx].aa_cov[eidx] = val; \
71 spans[ridx].aa_len[eidx] = 1; \
72 } \
73 prev_aa = 4; \
74}
75
76//Vertical Outside Direction
77#define VERT_OUTSIDE(rewind, y_advance, cov_range) \
78{ \
79 int coverage = (256 / ((cov_range) + 1)); \
80 int ry = 1; \
81 for (; ry < ((rewind) + 1); ry++) \
82 { \
83 int ridx = (y - ry) + (y_advance); \
84 if (spans[ridx].aa_len[(eidx)] > 1) continue; \
85 spans[ridx].aa_len[(eidx)] = 1; \
86 if (eidx == 1) \
87 { \
88 spans[ridx].aa_cov[(eidx)] = \
89 (coverage * (ry + (cov_range - (rewind)))); \
90 } \
91 else \
92 { \
93 spans[ridx].aa_cov[(eidx)] = \
94 (256 - (coverage * (ry + ((cov_range) - (rewind))))); \
95 } \
96 } \
97 prev_aa = 2; \
98}
99
100//Horizontal Inside Direction
101#define HORIZ_INSIDE(yy, xx, xx2) \
102{ \
103 if (((xx) - (xx2)) > spans[(yy)].aa_len[(eidx)]) \
104 { \
105 spans[(yy)].aa_len[(eidx)] = ((xx) - (xx2)); \
106 spans[(yy)].aa_cov[(eidx)] = (256 / (spans[(yy)].aa_len[(eidx)] + 1)); \
107 } \
108}
109
110//Horizontal Outside Direction
111#define HORIZ_OUTSIDE(yy, xx, xx2) \
112{ \
113 if (((xx) - (xx2)) > spans[(yy)].aa_len[(eidx)]) \
114 { \
115 spans[(yy)].aa_len[(eidx)] = ((xx) - (xx2)); \
116 spans[(yy)].aa_cov[(eidx)] = (256 / (spans[(yy)].aa_len[(eidx)] + 1)); \
117 } \
118}
119
120static inline DATA32
121_aa_coverage_apply(Line *line, int ww, int w, DATA32 val)
122{
123 //Left Edge Anti Anliasing
124 if ((w - line->aa_len[0]) < ww)
125 {
126 return MUL_256((line->aa_cov[0] * (w - ww + 1)), val);
127 }
128 //Right Edge Anti Aliasing
129 if (line->aa_len[1] >= ww)
130 {
131 return MUL_256(256 - (line->aa_cov[1] * (line->aa_len[1] - ww + 1)),
132 val);
133 }
134 return val;
135}
136
137void
138_calc_aa_edges_internal(Line *spans, int eidx, int ystart, int yend)
139{
140 int y;
141 Evas_Coord_Point edge1 = { -1, -1 }; //prev-previous edge pixel
142 Evas_Coord_Point edge2 = { -1, -1 }; //previous edge pixel
143
144 /* store larger to tx[0] between prev and current edge's x positions. */
145 int tx[2] = {0, 0};
146
147 /* store lager to tx2[0] between edge1 and edge2's x positions. */
148 int tx2[2] = {0, 0};
149
150 /* previous edge anti-aliased type.
151 2: vertical outside
152 4: vertical inside */
153 int prev_aa = 0;
154
155 Eina_Bool reset_tx2 = EINA_TRUE;
156
157 yend -= ystart;
158
159 //Find Start Edge
160 for (y = 0; y < yend; y++)
161 {
162 if (spans[y].span[0].x[0] == -1) continue;
163 edge1.x = edge2.x = spans[y].span[0].x[eidx];
164 edge1.y = edge2.y = y;
165 break;
166 }
167
168 //Calculates AA Edges
169 for (y++; y <= yend; y++)
170 {
171 Eina_Bool leftover = EINA_FALSE;
172
173 if (spans[y].span[0].x[eidx] == -1) leftover = EINA_TRUE;
174
175 if (!leftover) READY_TX()
176
177 //Case1. Outside Incremental
178 if (tx[0] > tx[1])
179 {
180 //Horizontal Edge
181 if ((y - edge2.y) == 1)
182 {
183 HORIZ_OUTSIDE(y, tx[0], tx[1])
184 }
185 //Vertical Edge
186 else if (tx[0] > tx[1])
187 {
188 VERT_OUTSIDE((y - edge2.y), 0, (y - edge2.y))
189
190 //Just in case: 1 pixel alias next to vertical edge?
191 if (abs(spans[(y + 1)].span[0].x[eidx] -
192 spans[y].span[0].x[eidx]) >= 1)
193 {
194 HORIZ_OUTSIDE(y, tx[0], tx[1])
195 }
196 }
197 PUSH_EDGES(spans[y].span[0].x[eidx])
198 }
199 //Case2. Inside Incremental
200 else if (tx[1] > tx[0])
201 {
202 //Just in case: direction is reversed at the outside vertical edge?
203 if (prev_aa == 2)
204 {
205 VERT_OUTSIDE((y - edge2.y), 0, (y - edge2.y))
206 edge1.x = spans[y - 1].span[0].x[eidx];
207 edge1.y = y - 1;
208 edge2.x = spans[y].span[0].x[eidx];
209 edge2.y = y;
210 }
211 else
212 PUSH_EDGES(spans[y].span[0].x[eidx])
213
214 /* Find next edge. We go forward 2 more index since this logic
215 computes aa edges by looking back in advance 2 spans. */
216 for (y++; y <= (yend + 2); y++)
217 {
218 leftover = EINA_FALSE;
219
220 if ((spans[y].span[0].x[eidx] == -1) || (y > yend))
221 leftover = EINA_TRUE;
222
223 if (!leftover) READY_TX()
224 if (reset_tx2) READY_TX2()
225
226 //Case 1. Inside Direction
227 if (tx[1] > tx[0])
228 {
229 //Horizontal Edge
230 if ((edge2.y - edge1.y) == 1)
231 {
232 HORIZ_INSIDE(edge1.y, tx2[0], tx2[1]);
233 }
234 //Vertical Edge
235 else if ((tx2[0] - tx2[1]) == 1)
236 {
237 VERT_INSIDE((edge2.y - edge1.y), -(y - edge2.y))
238 }
239 //Just in case: Right Side Square Edge...?
240 else if (prev_aa == 4)
241 {
242 VERT_INSIDE((edge2.y - edge1.y), -(y - edge2.y))
243 if ((y - edge2.y) == 1)
244 {
245 HORIZ_INSIDE((edge2.y - 1), edge2.x,
246 spans[y].span[0].x[eidx]);
247 }
248 }
249 PUSH_EDGES(spans[y].span[0].x[eidx])
250 }
251 //Case 2. Reversed. Outside Direction
252 else if (tx[1] < tx[0])
253 {
254 //Horizontal Edge
255 if ((edge2.y - edge1.y) == 1)
256 HORIZ_INSIDE(edge1.y, tx2[0], tx2[1])
257 //Vertical Edge
258 else
259 VERT_INSIDE((edge2.y - edge1.y), -(y - edge2.y))
260
261 PUSH_EDGES(spans[y].span[0].x[eidx])
262 break;
263 }
264 }
265 }
266 }
267
268 y = yend;
269
270 //Leftovers for verticals.
271 if (prev_aa == 2)
272 {
273 if (((eidx == 0) && (edge1.x > edge2.x)) ||
274 ((eidx == 1) && (edge1.x < edge2.x)))
275 VERT_OUTSIDE((y - edge2.y + 1), 1, (edge2.y - edge1.y));
276 }
277 else if (prev_aa == 4)
278 {
279 if (((eidx == 0) && (edge1.x < edge2.x)) ||
280 ((eidx == 1) && (edge1.x > edge2.x)))
281 {
282 VERT_INSIDE((edge2.y - edge1.y), -(y - edge2.y))
283 VERT_INSIDE((y - edge2.y) + 1, 1);
284 }
285 }
286}
287
288static void
289_calc_aa_edges(Line *spans, int ystart, int yend)
290{
291 //FIXME: support 2 span case.
292
293 //left side
294 _calc_aa_edges_internal(spans, 0, ystart, yend);
295 //right side
296 _calc_aa_edges_internal(spans, 1, ystart, yend);
297}