aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/evas/src/lib/engines/common_16/evas_soft16_line.c
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/evas/src/lib/engines/common_16/evas_soft16_line.c')
-rw-r--r--libraries/evas/src/lib/engines/common_16/evas_soft16_line.c444
1 files changed, 444 insertions, 0 deletions
diff --git a/libraries/evas/src/lib/engines/common_16/evas_soft16_line.c b/libraries/evas/src/lib/engines/common_16/evas_soft16_line.c
new file mode 100644
index 0000000..92e14af
--- /dev/null
+++ b/libraries/evas/src/lib/engines/common_16/evas_soft16_line.c
@@ -0,0 +1,444 @@
1#include "evas_common_soft16.h"
2#include "evas_soft16_scanline_fill.c"
3
4/*
5 * All functions except by evas_common_soft16_line_draw() expect x0 <= x1.
6 */
7
8static inline int
9_in_range(int value, int min, int max)
10{
11 return min <= value && value <= max;
12}
13
14static inline int
15_is_xy_inside_clip(int x, int y, const struct RGBA_Draw_Context_clip clip)
16{
17 if (!clip.use)
18 return 1;
19
20 if (!_in_range(x, clip.x, clip.x + clip.w - 1))
21 return 0;
22
23 if (!_in_range(y, clip.y, clip.y + clip.h - 1))
24 return 0;
25
26 return 1;
27}
28
29static inline int
30_is_x_inside_clip(int x, const struct RGBA_Draw_Context_clip clip)
31{
32 if (!clip.use)
33 return 1;
34
35 return _in_range(x, clip.x, clip.x + clip.w - 1);
36}
37
38static inline int
39_is_y_inside_clip(int y, const struct RGBA_Draw_Context_clip clip)
40{
41 if (!clip.use)
42 return 1;
43
44 return _in_range(y, clip.y, clip.y + clip.h - 1);
45}
46
47static inline int
48_is_xy_inside_rect(int x, int y, int w, int h)
49{
50 return _in_range(x, 0, w - 1) && _in_range(y, 0, h - 1);
51}
52
53static inline int
54_is_empty_clip(const struct RGBA_Draw_Context_clip clip)
55{
56 return clip.w < 1 || clip.h < 1;
57}
58
59static void
60_soft16_line_point(Soft16_Image *dst, RGBA_Draw_Context *dc, int x, int y)
61{
62 DATA16 rgb565, *dst_itr;
63 DATA8 alpha;
64
65 if (!_is_xy_inside_rect(x, y, dst->cache_entry.w, dst->cache_entry.h))
66 return;
67
68 if (!_is_xy_inside_clip(x, y, dc->clip))
69 return;
70
71 dst_itr = dst->pixels + (dst->stride * y) + x;
72 alpha = A_VAL(&dc->col.col) >> 3;
73 rgb565 = RGB_565_FROM_COMPONENTS(R_VAL(&dc->col.col),
74 G_VAL(&dc->col.col),
75 B_VAL(&dc->col.col));
76
77 if (alpha == 31)
78 _soft16_pt_fill_solid_solid(dst_itr, rgb565);
79 else if (alpha > 0)
80 {
81 DATA32 rgb565_unpack;
82
83 rgb565_unpack = RGB_565_UNPACK(rgb565);
84 alpha++;
85 _soft16_pt_fill_transp_solid(dst_itr, rgb565_unpack, alpha);
86 }
87}
88
89static void
90_soft16_line_horiz(Soft16_Image *dst, RGBA_Draw_Context *dc, int x0, int x1, int y)
91{
92 DATA16 rgb565, *dst_itr;
93 DATA8 alpha;
94 int w;
95
96 if (!_is_y_inside_clip(y, dc->clip))
97 return;
98
99 if (x0 < dc->clip.x)
100 x0 = dc->clip.x;
101
102 if (x1 >= dc->clip.x + dc->clip.w)
103 x1 = dc->clip.x + dc->clip.w - 1;
104
105 w = x1 - x0;
106 if (w < 1)
107 return;
108
109 dst_itr = dst->pixels + (dst->stride * y) + x0;
110 alpha = A_VAL(&dc->col.col) >> 3;
111 rgb565 = RGB_565_FROM_COMPONENTS(R_VAL(&dc->col.col),
112 G_VAL(&dc->col.col),
113 B_VAL(&dc->col.col));
114
115 if (alpha == 31)
116 _soft16_scanline_fill_solid_solid(dst_itr, w, rgb565);
117 else if (alpha > 0)
118 {
119 DATA32 rgb565_unpack;
120
121 rgb565_unpack = RGB_565_UNPACK(rgb565);
122 alpha++;
123 _soft16_scanline_fill_transp_solid(dst_itr, w, rgb565_unpack, alpha);
124 }
125}
126
127static void
128_soft16_line_vert(Soft16_Image *dst, RGBA_Draw_Context *dc, int x, int y0, int y1)
129{
130 DATA16 rgb565, *dst_itr;
131 DATA8 alpha;
132 int h;
133
134 if (!_is_x_inside_clip(x, dc->clip))
135 return;
136
137 if (y1 < y0)
138 {
139 int t;
140 t = y0;
141 y0 = y1;
142 y1 = t;
143 }
144
145 if (y0 < dc->clip.y)
146 y0 = dc->clip.y;
147
148 if (y1 >= dc->clip.y + dc->clip.h)
149 y1 = dc->clip.y + dc->clip.h - 1;
150
151 h = y1 - y0;
152 if (h < 1)
153 return;
154
155 dst_itr = dst->pixels + (dst->stride * y0) + x;
156 alpha = A_VAL(&dc->col.col) >> 3;
157 rgb565 = RGB_565_FROM_COMPONENTS(R_VAL(&dc->col.col),
158 G_VAL(&dc->col.col),
159 B_VAL(&dc->col.col));
160
161 if (alpha == 31)
162 {
163 for (; h > 0; h--, dst_itr += dst->stride)
164 _soft16_pt_fill_solid_solid(dst_itr, rgb565);
165 }
166 else if (alpha > 0)
167 {
168 DATA32 rgb565_unpack;
169
170 rgb565_unpack = RGB_565_UNPACK(rgb565);
171 alpha++;
172
173 for (; h > 0; h--, dst_itr += dst->stride)
174 _soft16_pt_fill_transp_solid(dst_itr, rgb565_unpack, alpha);
175 }
176}
177
178static inline void
179_soft16_line_45deg_adjust_boundaries(const struct RGBA_Draw_Context_clip clip, int *p_x0, int *p_y0, int *p_x1, int *p_y1)
180{
181 int diff, dy, x0, y0, x1, y1;
182
183 x0 = *p_x0;
184 y0 = *p_y0;
185 x1 = *p_x1;
186 y1 = *p_y1;
187
188 dy = y1 - y0;
189
190 diff = clip.x - x0;
191 if (diff > 0)
192 {
193 x0 = clip.x;
194 y0 += (dy > 0) ? diff : -diff;
195 }
196
197 diff = x1 - (clip.x + clip.w);
198 if (diff > 0)
199 {
200 x1 = clip.x + clip.w;
201 y1 += (dy > 0) ? -diff : diff;
202 }
203
204 if (dy > 0)
205 {
206 diff = clip.y - y0;
207 if (diff > 0)
208 {
209 y0 = clip.y;
210 x0 += diff;
211 }
212
213 diff = y1 - (clip.y + clip.h);
214 if (diff > 0)
215 {
216 y1 = clip.y + clip.h;
217 x1 -= diff;
218 }
219 }
220 else
221 {
222 diff = clip.y - y1;
223 if (diff > 0)
224 {
225 y1 = clip.y;
226 x1 -= diff;
227 }
228
229 diff = y0 - (clip.y + clip.h - 1);
230 if (diff > 0)
231 {
232 y0 = clip.y + clip.h - 1;
233 x0 += diff;
234 }
235 }
236
237 *p_x0 = x0;
238 *p_y0 = y0;
239 *p_x1 = x1;
240 *p_y1 = y1;
241}
242
243static void
244_soft16_line_45deg(Soft16_Image *dst, RGBA_Draw_Context *dc, int x0, int y0, int x1, int y1)
245{
246 int dy, step_dst_itr, len;
247 DATA8 alpha;
248 DATA16 *dst_itr, rgb565;
249
250 alpha = A_VAL(&dc->col.col) >> 3;
251 if (alpha < 1)
252 return;
253
254 rgb565 = RGB_565_FROM_COMPONENTS(R_VAL(&dc->col.col),
255 G_VAL(&dc->col.col),
256 B_VAL(&dc->col.col));
257
258 dy = y1 - y0;
259 step_dst_itr = 1 + ((dy > 0) ? dst->stride : -dst->stride);
260
261 _soft16_line_45deg_adjust_boundaries(dc->clip, &x0, &y0, &x1, &y1);
262
263 len = (dy > 0) ? (y1 - y0) : (y0 - y1);
264 if (len < 1)
265 return;
266
267 dst_itr = dst->pixels + dst->stride * y0 + x0;
268 if (alpha == 31)
269 {
270 for (; len > 0; len--, dst_itr += step_dst_itr)
271 _soft16_pt_fill_solid_solid(dst_itr, rgb565);
272 }
273 else
274 {
275 DATA32 rgb565_unpack;
276
277 rgb565_unpack = RGB_565_UNPACK(rgb565);
278 alpha++;
279 for (; len > 0; len--, dst_itr += step_dst_itr)
280 _soft16_pt_fill_transp_solid(dst_itr, rgb565_unpack, alpha);
281 }
282}
283
284EFL_ALWAYS_INLINE void
285_soft16_line_aliased_pt(DATA16 *dst_itr, DATA16 rgb565, DATA32 rgb565_unpack, DATA8 alpha)
286{
287 if (alpha == 32)
288 _soft16_pt_fill_solid_solid(dst_itr, rgb565);
289 else
290 _soft16_pt_fill_transp_solid(dst_itr, rgb565_unpack, alpha);
291}
292
293static void
294_soft16_line_aliased(Soft16_Image *dst, RGBA_Draw_Context *dc, int x0, int y0, int x1, int y1)
295{
296 int dx, dy, step_y, step_dst_itr;
297 DATA32 rgb565_unpack;
298 DATA16 rgb565;
299 DATA8 alpha;
300
301 alpha = A_VAL(&dc->col.col) >> 3;
302 if (alpha == 0)
303 return;
304 alpha++;
305
306 rgb565 = RGB_565_FROM_COMPONENTS(R_VAL(&dc->col.col),
307 G_VAL(&dc->col.col),
308 B_VAL(&dc->col.col));
309 rgb565_unpack = RGB_565_UNPACK(rgb565);
310
311 dx = x1 - x0;
312 dy = y1 - y0;
313
314 if (dy >= 0)
315 {
316 step_y = 1;
317 step_dst_itr = dst->stride;
318 }
319 else
320 {
321 dy = -dy;
322 step_y = -1;
323 step_dst_itr = -dst->stride;
324 }
325
326 if (dx > dy)
327 {
328 DATA16 *dst_itr;
329 int e, x, y;
330
331 e = - (dx / 2);
332 y = y0;
333 dst_itr = dst->pixels + dst->stride * y0 + x0;
334 for (x=x0; x <= x1; x++, dst_itr++)
335 {
336 if (_is_xy_inside_clip(x, y, dc->clip))
337 _soft16_line_aliased_pt(dst_itr, rgb565, rgb565_unpack, alpha);
338
339 e += dy;
340 if (e >= 0)
341 {
342 dst_itr += step_dst_itr;
343 y += step_y;
344 e -= dx;
345 }
346 }
347 }
348 else
349 {
350 DATA16 *dst_itr;
351 int e, x, y;
352
353 e = - (dy / 2);
354 x = x0;
355 dst_itr = dst->pixels + dst->stride * y0 + x0;
356 for (y=y0; y != y1; y += step_y, dst_itr += step_dst_itr)
357 {
358 if (_is_xy_inside_clip(x, y, dc->clip))
359 _soft16_line_aliased_pt(dst_itr, rgb565, rgb565_unpack, alpha);
360
361 e += dx;
362 if (e >= 0)
363 {
364 dst_itr++;
365 x++;
366 e -= dy;
367 }
368 }
369 }
370}
371
372void
373evas_common_soft16_line_draw(Soft16_Image *dst, RGBA_Draw_Context *dc, int x0, int y0, int x1, int y1)
374{
375 struct RGBA_Draw_Context_clip c_bkp, c_tmp;
376 int dx, dy;
377 int x, y, w, h;
378
379 c_tmp.use = 1;
380 c_tmp.x = 0;
381 c_tmp.y = 0;
382 c_tmp.w = dst->cache_entry.w;
383 c_tmp.h = dst->cache_entry.h;
384
385 /* save out clip info */
386 c_bkp = dc->clip;
387 if (c_bkp.use)
388 {
389 RECTS_CLIP_TO_RECT(c_tmp.x, c_tmp.y, c_tmp.w, c_tmp.h,
390 c_bkp.x, c_bkp.y, c_bkp.w, c_bkp.h);
391 if (_is_empty_clip(c_tmp))
392 return;
393 }
394
395 x = MIN(x0, x1);
396 y = MIN(y0, y1);
397 w = MAX(x0, x1) - x + 1;
398 h = MAX(y0, y1) - y + 1;
399
400 RECTS_CLIP_TO_RECT(c_tmp.x, c_tmp.y, c_tmp.w, c_tmp.h, x, y, w, h);
401 if (_is_empty_clip(c_tmp))
402 return;
403
404 /* Check if the line doesn't cross the clip area */
405 if (x0 < c_tmp.x && x1 < c_tmp.x)
406 return;
407 if (x0 >= c_tmp.x + c_tmp.w && x1 >= c_tmp.x + c_tmp.w)
408 return;
409 if (y0 < c_tmp.y && y1 < c_tmp.y)
410 return;
411 if (y0 >= c_tmp.y + c_tmp.h && y1 >= c_tmp.y + c_tmp.h)
412 return;
413
414 dc->clip = c_tmp;
415 dx = x1 - x0;
416 dy = y1 - y0;
417
418 if (dx < 0)
419 {
420 int t;
421
422 t = x0;
423 x0 = x1;
424 x1 = t;
425
426 t = y0;
427 y0 = y1;
428 y1 = t;
429 }
430
431 if (dx == 0 && dy == 0)
432 _soft16_line_point(dst, dc, x0, y0);
433 else if (dx == 0)
434 _soft16_line_vert(dst, dc, x0, y0, y1);
435 else if (dy == 0)
436 _soft16_line_horiz(dst, dc, x0, x1, y0);
437 else if (dy == dx || dy == -dx)
438 _soft16_line_45deg(dst, dc, x0, y0, x1, y1);
439 else
440 _soft16_line_aliased(dst, dc, x0, y0, x1, y1);
441
442 /* restore clip info */
443 dc->clip = c_bkp;
444}