summaryrefslogtreecommitdiff
path: root/src/lib/evas/common/evas_draw_main.c
diff options
context:
space:
mode:
authorVincent Torri <vincent.torri@gmail.com>2012-11-04 11:51:42 +0000
committerVincent Torri <vincent.torri@gmail.com>2012-11-04 11:51:42 +0000
commitc15e9c6575c3b5f39ded167dda5259de3de96151 (patch)
tree5115d7ae3620af24c2bc094cd062575af7adeda9 /src/lib/evas/common/evas_draw_main.c
parenta5ac6a987caec5a7f7596a25d0a065b9cc94c50c (diff)
merge: and now Evas
I've tested make -j 3 install and it works nicely I've tested expedite with software and opengl xlib, and it works. Not tested other engines, so please report any problems (engines or other) on the ML. TODO: examples and tests, I'll add them later ISSUE: Eina_Unicode size check. It indirectly depends on eina_config.h, which is created at the end of the configure script. So its size is always 0. I don't know how that size is used, so I can't do a lot, for now. SVN revision: 78895
Diffstat (limited to 'src/lib/evas/common/evas_draw_main.c')
-rw-r--r--src/lib/evas/common/evas_draw_main.c703
1 files changed, 703 insertions, 0 deletions
diff --git a/src/lib/evas/common/evas_draw_main.c b/src/lib/evas/common/evas_draw_main.c
new file mode 100644
index 0000000000..28b54cd0ae
--- /dev/null
+++ b/src/lib/evas/common/evas_draw_main.c
@@ -0,0 +1,703 @@
1#include "evas_common.h"
2#include "evas_convert_main.h"
3#include "evas_private.h"
4
5EAPI Cutout_Rects*
6evas_common_draw_context_cutouts_new(void)
7{
8 Cutout_Rects *rects;
9
10 rects = calloc(1, sizeof(Cutout_Rects));
11 return rects;
12}
13
14EAPI void
15evas_common_draw_context_cutouts_free(Cutout_Rects* rects)
16{
17 if (!rects) return ;
18 rects->active = 0;
19}
20
21EAPI void
22evas_common_draw_context_cutouts_del(Cutout_Rects* rects, int idx)
23{
24 if ((idx >= 0) && (idx < rects->active))
25 {
26 Cutout_Rect *rect;
27
28 rect = rects->rects + idx;
29 memmove(rect, rect + 1,
30 sizeof(Cutout_Rect) * (rects->active - idx - 1));
31 rects->active--;
32 }
33}
34
35void
36evas_common_init(void)
37{
38 evas_common_cpu_init();
39
40 evas_common_blend_init();
41 evas_common_image_init();
42 evas_common_convert_init();
43 evas_common_scale_init();
44 evas_common_rectangle_init();
45 evas_common_polygon_init();
46 evas_common_line_init();
47 evas_common_font_init();
48 evas_common_draw_init();
49 evas_common_tilebuf_init();
50}
51
52void
53evas_common_shutdown(void)
54{
55 evas_font_dir_cache_free();
56 evas_common_image_cache_free();
57}
58
59EAPI void
60evas_common_draw_init(void)
61{
62}
63
64EAPI RGBA_Draw_Context *
65evas_common_draw_context_new(void)
66{
67 RGBA_Draw_Context *dc;
68
69 dc = calloc(1, sizeof(RGBA_Draw_Context));
70 dc->sli.h = 1;
71 return dc;
72}
73
74EAPI void
75evas_common_draw_context_free(RGBA_Draw_Context *dc)
76{
77 if (!dc) return;
78
79#ifdef HAVE_PIXMAN
80 if (dc->col.pixman_color_image)
81 {
82 pixman_image_unref(dc->col.pixman_color_image);
83 dc->col.pixman_color_image = NULL;
84 }
85#endif
86
87 evas_common_draw_context_apply_clean_cutouts(&dc->cutout);
88 free(dc);
89}
90
91EAPI void
92evas_common_draw_context_clear_cutouts(RGBA_Draw_Context *dc)
93{
94 evas_common_draw_context_cutouts_free(&dc->cutout);
95}
96
97EAPI void
98evas_common_draw_context_font_ext_set(RGBA_Draw_Context *dc,
99 void *data,
100 void *(*gl_new) (void *data, RGBA_Font_Glyph *fg),
101 void (*gl_free) (void *ext_dat),
102 void (*gl_draw) (void *data, void *dest, void *context, RGBA_Font_Glyph *fg, int x, int y))
103{
104 dc->font_ext.data = data;
105 dc->font_ext.func.gl_new = gl_new;
106 dc->font_ext.func.gl_free = gl_free;
107 dc->font_ext.func.gl_draw = gl_draw;
108}
109
110EAPI void
111evas_common_draw_context_clip_clip(RGBA_Draw_Context *dc, int x, int y, int w, int h)
112{
113 if (dc->clip.use)
114 {
115 RECTS_CLIP_TO_RECT(dc->clip.x, dc->clip.y, dc->clip.w, dc->clip.h,
116 x, y, w, h);
117 }
118 else
119 evas_common_draw_context_set_clip(dc, x, y, w, h);
120}
121
122EAPI void
123evas_common_draw_context_set_clip(RGBA_Draw_Context *dc, int x, int y, int w, int h)
124{
125 dc->clip.use = 1;
126 dc->clip.x = x;
127 dc->clip.y = y;
128 dc->clip.w = w;
129 dc->clip.h = h;
130}
131
132EAPI void
133evas_common_draw_context_unset_clip(RGBA_Draw_Context *dc)
134{
135 dc->clip.use = 0;
136}
137
138EAPI void
139evas_common_draw_context_set_color(RGBA_Draw_Context *dc, int r, int g, int b, int a)
140{
141 R_VAL(&(dc->col.col)) = (DATA8)r;
142 G_VAL(&(dc->col.col)) = (DATA8)g;
143 B_VAL(&(dc->col.col)) = (DATA8)b;
144 A_VAL(&(dc->col.col)) = (DATA8)a;
145#ifdef HAVE_PIXMAN
146 if (dc && dc->col.pixman_color_image)
147 pixman_image_unref(dc->col.pixman_color_image);
148
149 pixman_color_t pixman_color;
150
151 pixman_color.alpha = (dc->col.col & 0xff000000) >> 16;
152 pixman_color.red = (dc->col.col & 0x00ff0000) >> 8;
153 pixman_color.green = (dc->col.col & 0x0000ff00);
154 pixman_color.blue = (dc->col.col & 0x000000ff) << 8;
155
156 dc->col.pixman_color_image = pixman_image_create_solid_fill(&pixman_color);
157#endif
158
159}
160
161EAPI void
162evas_common_draw_context_set_multiplier(RGBA_Draw_Context *dc, int r, int g, int b, int a)
163{
164 dc->mul.use = 1;
165 R_VAL(&(dc->mul.col)) = (DATA8)r;
166 G_VAL(&(dc->mul.col)) = (DATA8)g;
167 B_VAL(&(dc->mul.col)) = (DATA8)b;
168 A_VAL(&(dc->mul.col)) = (DATA8)a;
169}
170
171EAPI void
172evas_common_draw_context_unset_multiplier(RGBA_Draw_Context *dc)
173{
174 dc->mul.use = 0;
175}
176
177EAPI void
178evas_common_draw_context_set_mask(RGBA_Draw_Context *dc, RGBA_Image *mask, int x, int y, int w, int h)
179{
180 dc->mask.mask = mask;
181 dc->mask.x = x;
182 dc->mask.y = y;
183 dc->mask.w = w;
184 dc->mask.h = h;
185
186#ifdef HAVE_PIXMAN
187 if (mask->pixman.im)
188 pixman_image_unref(mask->pixman.im);
189
190 if (mask->cache_entry.flags.alpha)
191 {
192 mask->pixman.im = pixman_image_create_bits(PIXMAN_a8r8g8b8, w, h,
193 (uint32_t *)mask->mask.mask,
194 w * 4);
195 }
196 else
197 {
198 mask->pixman.im = pixman_image_create_bits(PIXMAN_x8r8g8b8, w, h,
199 (uint32_t *)mask->mask.mask,
200 w * 4);
201 }
202#endif
203
204}
205
206EAPI void
207evas_common_draw_context_unset_mask(RGBA_Draw_Context *dc)
208{
209 dc->mask.mask = NULL;
210
211#ifdef HAVE_PIXMAN
212 RGBA_Image *mask;
213 mask = (RGBA_Image *)dc->mask.mask;
214
215 if (mask && mask->pixman.im)
216 {
217 pixman_image_unref(mask->pixman.im);
218 mask->pixman.im = NULL;
219 }
220#endif
221}
222
223
224
225
226
227EAPI void
228evas_common_draw_context_add_cutout(RGBA_Draw_Context *dc, int x, int y, int w, int h)
229{
230// if (dc->cutout.rects > 512) return;
231 if (dc->clip.use)
232 {
233#if 1 // this is a bit faster
234 int xa1, xa2, xb1, xb2;
235
236 xa1 = x;
237 xa2 = xa1 + w - 1;
238 xb1 = dc->clip.x;
239 if (xa2 < xb1) return;
240 xb2 = xb1 + dc->clip.w - 1;
241 if (xa1 >= xb2) return;
242 if (xa2 > xb2) xa2 = xb2;
243 if (xb1 > xa1) xa1 = xb1;
244 x = xa1;
245 w = xa2 - xa1 + 1;
246
247 xa1 = y;
248 xa2 = xa1 + h - 1;
249 xb1 = dc->clip.y;
250 if (xa2 < xb1) return;
251 xb2 = xb1 + dc->clip.h - 1;
252 if (xa1 >= xb2) return;
253 if (xa2 > xb2) xa2 = xb2;
254 if (xb1 > xa1) xa1 = xb1;
255 y = xa1;
256 h = xa2 - xa1 + 1;
257#else
258 RECTS_CLIP_TO_RECT(x, y, w, h,
259 dc->clip.x, dc->clip.y, dc->clip.w, dc->clip.h);
260#endif
261 if ((w < 1) || (h < 1)) return;
262 }
263 evas_common_draw_context_cutouts_add(&dc->cutout, x, y, w, h);
264}
265
266int
267evas_common_draw_context_cutout_split(Cutout_Rects* res, int idx, Cutout_Rect *split)
268{
269 /* 1 input rect, multiple out */
270 Cutout_Rect in = res->rects[idx];
271
272 /* this is to save me a LOT of typing */
273#define INX1 (in.x)
274#define INX2 (in.x + in.w)
275#define SPX1 (split->x)
276#define SPX2 (split->x + split->w)
277#define INY1 (in.y)
278#define INY2 (in.y + in.h)
279#define SPY1 (split->y)
280#define SPY2 (split->y + split->h)
281#define X1_IN (in.x < split->x)
282#define X2_IN ((in.x + in.w) > (split->x + split->w))
283#define Y1_IN (in.y < split->y)
284#define Y2_IN ((in.y + in.h) > (split->y + split->h))
285#define R_NEW(_r, _x, _y, _w, _h) { evas_common_draw_context_cutouts_add(_r, _x, _y, _w, _h); }
286 if (!RECTS_INTERSECT(in.x, in.y, in.w, in.h,
287 split->x, split->y, split->w, split->h))
288 {
289 /* No colision => no clipping, don't touch it. */
290 return 1;
291 }
292
293 /* S = split (ie cut out rect) */
294 /* +--+ = in (rect to be cut) */
295
296 /*
297 * +---+
298 * | |
299 * | S |
300 * | |
301 * +---+
302 *
303 */
304 if (X1_IN && X2_IN && Y1_IN && Y2_IN)
305 {
306 R_NEW(res, in.x, in.y, in.w, SPY1 - in.y);
307 R_NEW(res, in.x, SPY1, SPX1 - in.x, SPY2 - SPY1);
308 R_NEW(res, SPX2, SPY1, INX2 - SPX2, SPY2 - SPY1);
309 /* out => (in.x, SPY2, in.w, INY2 - SPY2) */
310 res->rects[idx].h = INY2 - SPY2;
311 res->rects[idx].y = SPY2;
312 return 1;
313 }
314 /* SSSSSSS
315 * S+---+S
316 * S|SSS|S
317 * S|SSS|S
318 * S|SSS|S
319 * S+---+S
320 * SSSSSSS
321 */
322 if (!X1_IN && !X2_IN && !Y1_IN && !Y2_IN)
323 {
324 evas_common_draw_context_cutouts_del(res, idx);
325 return 0;
326 }
327 /* SSS
328 * S+---+
329 * S|S |
330 * S|S |
331 * S|S |
332 * S+---+
333 * SSS
334 */
335 if (!X1_IN && X2_IN && !Y1_IN && !Y2_IN)
336 {
337 /* in => (SPX2, in.y, INX2 - SPX2, in.h) */
338 res->rects[idx].w = INX2 - SPX2;
339 res->rects[idx].x = SPX2;
340 return 1;
341 }
342 /* S
343 * +---+
344 * | S |
345 * | S |
346 * | S |
347 * +---+
348 * S
349 */
350 if (X1_IN && X2_IN && !Y1_IN && !Y2_IN)
351 {
352 R_NEW(res, in.x, in.y, SPX1 - in.x, in.h);
353 /* in => (SPX2, in.y, INX2 - SPX2, in.h) */
354 res->rects[idx].w = INX2 - SPX2;
355 res->rects[idx].x = SPX2;
356 return 1;
357 }
358 /* SSS
359 * +---+S
360 * | S|S
361 * | S|S
362 * | S|S
363 * +---+S
364 * SSS
365 */
366 if (X1_IN && !X2_IN && !Y1_IN && !Y2_IN)
367 {
368 /* in => (in.x, in.y, SPX1 - in.x, in.h) */
369 res->rects[idx].w = SPX1 - in.x;
370 return 1;
371 }
372 /* SSSSSSS
373 * S+---+S
374 * S|SSS|S
375 * | |
376 * | |
377 * +---+
378 *
379 */
380 if (!X1_IN && !X2_IN && !Y1_IN && Y2_IN)
381 {
382 /* in => (in.x, SPY2, in.w, INY2 - SPY2) */
383 res->rects[idx].h = INY2 - SPY2;
384 res->rects[idx].y = SPY2;
385 return 1;
386 }
387 /*
388 * +---+
389 * | |
390 * S|SSS|S
391 * | |
392 * +---+
393 *
394 */
395 if (!X1_IN && !X2_IN && Y1_IN && Y2_IN)
396 {
397 R_NEW(res, in.x, SPY2, in.w, INY2 - SPY2);
398 /* in => (in.x, in.y, in.w, SPY1 - in.y) */
399 res->rects[idx].h = SPY1 - in.y;
400 return 1;
401 }
402 /*
403 * +---+
404 * | |
405 * | |
406 * S|SSS|S
407 * S+---+S
408 * SSSSSSS
409 */
410 if (!X1_IN && !X2_IN && Y1_IN && !Y2_IN)
411 {
412 /* in => (in.x, in.y, in.w, SPY1 - in.y) */
413 res->rects[idx].h = SPY1 - in.y;
414 return 1;
415 }
416 /* SSS
417 * S+---+
418 * S|S |
419 * | |
420 * | |
421 * +---+
422 *
423 */
424 if (!X1_IN && X2_IN && !Y1_IN && Y2_IN)
425 {
426 R_NEW(res, SPX2, in.y, INX2 - SPX2, SPY2 - in.y);
427 /* in => (in.x, SPY2, in.w, INY2 - SPY2) */
428 res->rects[idx].h = INY2 - SPY2;
429 res->rects[idx].y = SPY2;
430 return 1;
431 }
432 /* S
433 * +---+
434 * | S |
435 * | |
436 * | |
437 * +---+
438 *
439 */
440 if (X1_IN && X2_IN && !Y1_IN && Y2_IN)
441 {
442 R_NEW(res, in.x, in.y, SPX1 - in.x, SPY2 - in.y);
443 R_NEW(res, SPX2, in.y, INX2 - SPX2, SPY2 - in.y);
444 /* in => (in.x, SPY2, in.w, INY2 - SPY2) */
445 res->rects[idx].h = INY2 - SPY2;
446 res->rects[idx].y = SPY2;
447 return 1;
448 }
449 /* SSS
450 * +---+S
451 * | S|S
452 * | |
453 * | |
454 * +---+
455 *
456 */
457 if (X1_IN && !X2_IN && !Y1_IN && Y2_IN)
458 {
459 R_NEW(res, in.x, in.y, SPX1 - in.x, SPY2 - in.y);
460 /* in => (in.x, SPY2, in.w, INY2 - SPY2) */
461 res->rects[idx].h = INY2 - SPY2;
462 res->rects[idx].y = SPY2;
463 return 1;
464 }
465 /*
466 * +---+
467 * | |
468 * S|S |
469 * | |
470 * +---+
471 *
472 */
473 if (!X1_IN && X2_IN && Y1_IN && Y2_IN)
474 {
475 R_NEW(res, in.x, SPY2, in.w, INY2 - SPY2);
476 R_NEW(res, SPX2, SPY1, INX2 - SPX2, SPY2 - SPY1);
477 /* in => (in.x, SPY2, in.w, INY2 - SPY2) */
478 res->rects[idx].h = SPY1 - in.y;
479 return 1;
480 }
481 /*
482 * +---+
483 * | |
484 * | S|S
485 * | |
486 * +---+
487 *
488 */
489 if (X1_IN && !X2_IN && Y1_IN && Y2_IN)
490 {
491 R_NEW(res, in.x, SPY2, in.w, INY2 - SPY2);
492 R_NEW(res, in.x, SPY1, SPX1 - in.x, SPY2 - SPY1);
493 /* in => (in.x, in.y, in.w, SPY1 - in.y) */
494 res->rects[idx].h = SPY1 - in.y;
495 return 1;
496 }
497 /*
498 * +---+
499 * | |
500 * | |
501 * S|S |
502 * S+---+
503 * SSS
504 */
505 if (!X1_IN && X2_IN && Y1_IN && !Y2_IN)
506 {
507 R_NEW(res, SPX2, SPY1, INX2 - SPX2, INY2 - SPY1);
508 /* in => (in.x, in.y, in.w, SPY1 - in.y) */
509 res->rects[idx].h = SPY1 - in.y;
510 return 1;
511 }
512 /*
513 * +---+
514 * | |
515 * | |
516 * | S |
517 * +---+
518 * S
519 */
520 if (X1_IN && X2_IN && Y1_IN && !Y2_IN)
521 {
522 R_NEW(res, in.x, SPY1, SPX1 - in.x, INY2 - SPY1);
523 R_NEW(res, SPX2, SPY1, INX2 - SPX2, INY2 - SPY1);
524 /* in => (in.x, in.y, in.w, SPY1 - in.y) */
525 res->rects[idx].h = SPY1 - in.y;
526 return 1;
527 }
528 /*
529 * +---+
530 * | |
531 * | |
532 * | S|S
533 * +---+S
534 * SSS
535 */
536 if (X1_IN && !X2_IN && Y1_IN && !Y2_IN)
537 {
538 R_NEW(res, in.x, SPY1, SPX1 - in.x, INY2 - SPY1);
539 /* in => (in.x, in.y, in.w, SPY1 - in.y) */
540 res->rects[idx].h = SPY1 - in.y;
541 return 1;
542 }
543 evas_common_draw_context_cutouts_del(res, idx);
544 return 0;
545#undef INX1
546#undef INX2
547#undef SPX1
548#undef SPX2
549#undef INY1
550#undef INY2
551#undef SPY1
552#undef SPY2
553#undef X1_IN
554#undef X2_IN
555#undef Y1_IN
556#undef Y2_IN
557#undef R_NEW
558}
559
560EAPI Cutout_Rects*
561evas_common_draw_context_apply_cutouts(RGBA_Draw_Context *dc, Cutout_Rects *reuse)
562{
563 Cutout_Rects* res = NULL;
564 int i;
565 int j;
566
567 if (!dc->clip.use) return NULL;
568 if ((dc->clip.w <= 0) || (dc->clip.h <= 0)) return NULL;
569
570
571 if (!reuse)
572 {
573 res = evas_common_draw_context_cutouts_new();
574 }
575 else
576 {
577 evas_common_draw_context_cutouts_free(reuse);
578 res = reuse;
579 }
580 evas_common_draw_context_cutouts_add(res, dc->clip.x, dc->clip.y, dc->clip.w, dc->clip.h);
581
582 for (i = 0; i < dc->cutout.active; ++i)
583 {
584 /* Don't loop on the element just added to the list as they are already correctly clipped. */
585 int active = res->active;
586
587 for (j = 0; j < active; )
588 {
589 if (evas_common_draw_context_cutout_split(res, j, dc->cutout.rects + i))
590 ++j;
591 else
592 active--;
593 }
594 }
595 /* merge rects */
596#define RI res->rects[i]
597#define RJ res->rects[j]
598 if (res->active > 1)
599 {
600 int found = 1;
601
602 while (found)
603 {
604 found = 0;
605 for (i = 0; i < res->active; i++)
606 {
607 for (j = i + 1; j < res->active; j++)
608 {
609 /* skip empty rects we are removing */
610 if (RJ.w == 0) continue;
611 /* check if its same width, immediately above or below */
612 if ((RJ.w == RI.w) && (RJ.x == RI.x))
613 {
614 if ((RJ.y + RJ.h) == RI.y) /* above */
615 {
616 RI.y = RJ.y;
617 RI.h += RJ.h;
618 RJ.w = 0;
619 found = 1;
620 }
621 else if ((RI.y + RI.h) == RJ.y) /* below */
622 {
623 RI.h += RJ.h;
624 RJ.w = 0;
625 found = 1;
626 }
627 }
628 /* check if its same height, immediately left or right */
629 else if ((RJ.h == RI.h) && (RJ.y == RI.y))
630 {
631 if ((RJ.x + RJ.w) == RI.x) /* left */
632 {
633 RI.x = RJ.x;
634 RI.w += RJ.w;
635 RJ.w = 0;
636 found = 1;
637 }
638 else if ((RI.x + RI.w) == RJ.x) /* right */
639 {
640 RI.w += RJ.w;
641 RJ.w = 0;
642 found = 1;
643 }
644 }
645 }
646 }
647 }
648
649 /* Repack the cutout */
650 j = 0;
651 for (i = 0; i < res->active; i++)
652 {
653 if (RI.w == 0) continue;
654 if (i != j)
655 RJ = RI;
656 j++;
657 }
658 res->active = j;
659 return res;
660 }
661 return res;
662}
663
664EAPI void
665evas_common_draw_context_apply_clear_cutouts(Cutout_Rects* rects)
666{
667 evas_common_draw_context_apply_clean_cutouts(rects);
668 free(rects);
669}
670
671EAPI void
672evas_common_draw_context_apply_clean_cutouts(Cutout_Rects* rects)
673{
674 free(rects->rects);
675 rects->rects = NULL;
676 rects->active = 0;
677 rects->max = 0;
678}
679
680EAPI void
681evas_common_draw_context_set_anti_alias(RGBA_Draw_Context *dc , unsigned char aa)
682{
683 dc->anti_alias = !!aa;
684}
685
686EAPI void
687evas_common_draw_context_set_color_interpolation(RGBA_Draw_Context *dc, int color_space)
688{
689 dc->interpolation.color_space = color_space;
690}
691
692EAPI void
693evas_common_draw_context_set_render_op(RGBA_Draw_Context *dc , int op)
694{
695 dc->render_op = op;
696}
697
698EAPI void
699evas_common_draw_context_set_sli(RGBA_Draw_Context *dc, int y, int h)
700{
701 dc->sli.y = y;
702 dc->sli.h = h;
703}