2 * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
7 #include "evas_common.h"
8 #include "evas_blend_private.h"
9 #include "evas_gradient_private.h"
12 static void _get_word(char *in, char *key);
13 static void evas_common_gradient_map_argb(RGBA_Draw_Context *dc, RGBA_Gradient *gr, int len);
14 static void evas_common_gradient_map_ahsv(RGBA_Draw_Context *dc, RGBA_Gradient *gr, int len);
16 static int grad_initialised = 0;
19 _get_word(char *in, char *key)
26 if (!in || !*in) return;
29 while (*p && isspace(*p))
33 while (*pp && !isspace(*pp))
38 strncpy(key, p, l + 1);
42 _evas_common_gradient_stops_free(RGBA_Gradient *gr)
49 while (gr->color.stops)
52 gr->color.stops = evas_object_list_remove(gr->color.stops, gr->color.stops);
55 gr->color.stops = NULL;
62 while (gr->alpha.stops)
65 gr->alpha.stops = evas_object_list_remove(gr->alpha.stops, gr->alpha.stops);
68 gr->alpha.stops = NULL;
75 evas_common_gradient_get_key_fval(char *in, char *key, float *val)
77 char *p, *pp, sval[256];
79 if (!key || !val) return NULL;
81 if (!in || !*in) return NULL;
83 if (!p || !*p) return NULL;
87 if (!pp || !*pp) return NULL;
89 if (!*key) return NULL;
92 if (!sval[0]) return NULL;
98 evas_common_gradient_init(void)
100 RGBA_Gradient_Type *geom;
102 if (grad_initialised)
104 geom = evas_common_gradient_geometer_get("linear");
107 geom = evas_common_gradient_geometer_get("radial");
110 geom = evas_common_gradient_geometer_get("rectangular");
113 geom = evas_common_gradient_geometer_get("angular");
116 geom = evas_common_gradient_geometer_get("sinusoidal");
119 grad_initialised = 1;
123 evas_common_gradient_shutdown(void)
125 RGBA_Gradient_Type *geom;
127 if (!grad_initialised)
129 geom = evas_common_gradient_geometer_get("linear");
132 geom = evas_common_gradient_geometer_get("radial");
135 geom = evas_common_gradient_geometer_get("rectangular");
138 geom = evas_common_gradient_geometer_get("angular");
141 geom = evas_common_gradient_geometer_get("sinusoidal");
144 grad_initialised = 0;
148 evas_common_gradient_new(void)
152 gr = calloc(1, sizeof(RGBA_Gradient));
158 evas_common_gradient_free(RGBA_Gradient *gr)
162 if (gr->references > 0) return;
163 evas_common_gradient_clear(gr);
164 if (gr->type.name) free(gr->type.name);
165 if (gr->type.params) free(gr->type.params);
166 if (gr->type.geometer && gr->type.gdata)
167 gr->type.geometer->geom_free(gr->type.gdata);
168 if (gr->map.data) free(gr->map.data);
173 evas_common_gradient_clear(RGBA_Gradient *gr)
177 _evas_common_gradient_stops_free(gr);
179 if (gr->color.data && !gr->imported_data)
180 free(gr->color.data);
181 gr->color.data = NULL;
183 if (gr->alpha.data && !gr->imported_data)
184 free(gr->alpha.data);
185 gr->alpha.data = NULL;
188 gr->imported_data = 0;
193 evas_common_gradient_color_stop_add(RGBA_Gradient *gr, int r, int g, int b, int a, int dist)
195 RGBA_Gradient_Color_Stop *gc, *gcm, *gc_last;
198 if (gr->imported_data)
200 gr->color.data = NULL;
202 gr->alpha.data = NULL;
204 gr->imported_data = 0;
207 gc = malloc(sizeof(RGBA_Gradient_Color_Stop));
209 if (dist < 1) dist = 1;
210 if (dist > 32768) dist = 32768;
211 if (r < 0) r = 0; if (r > 255) r = 255;
212 if (g < 0) g = 0; if (g > 255) g = 255;
213 if (b < 0) b = 0; if (b > 255) b = 255;
214 if (a < 0) a = 0; if (a > 255) a = 255;
221 if (!gr->color.stops)
223 gr->color.stops = evas_object_list_append(gr->color.stops, gc);
224 gr->color.nstops = 1;
230 gcm = malloc(sizeof(RGBA_Gradient_Color_Stop));
231 if (!gcm) { free(gc); return; }
232 gc_last = (RGBA_Gradient_Color_Stop *)(gr->color.stops->last);
233 if ((dist + gc_last->dist + gr->color.len) > 65535)
234 { free(gc); free(gcm); return; }
235 gcm->r = (gc_last->r + r) / 2;
236 gcm->g = (gc_last->g + g) / 2;
237 gcm->b = (gc_last->b + b) / 2;
238 gcm->a = (gc_last->a + a) / 2;
240 gr->color.stops = evas_object_list_append(gr->color.stops, gcm);
241 gr->color.len += gc_last->dist;
242 gr->color.stops = evas_object_list_append(gr->color.stops, gc);
243 gr->color.len += dist;
244 gr->color.nstops += 2;
250 evas_common_gradient_alpha_stop_add(RGBA_Gradient *gr, int a, int dist)
252 RGBA_Gradient_Alpha_Stop *ga, *gam, *ga_last;
255 if (gr->imported_data)
257 gr->color.data = NULL;
259 gr->alpha.data = NULL;
261 gr->imported_data = 0;
264 ga = malloc(sizeof(RGBA_Gradient_Alpha_Stop));
266 if (dist < 1) dist = 1;
267 if (dist > 32768) dist = 32768;
268 if (a < 0) a = 0; if (a > 255) a = 255;
272 if (!gr->alpha.stops)
274 gr->alpha.stops = evas_object_list_append(gr->alpha.stops, ga);
275 gr->alpha.nstops = 1;
281 gam = malloc(sizeof(RGBA_Gradient_Alpha_Stop));
282 if (!gam) { free(ga); return; }
283 ga_last = (RGBA_Gradient_Alpha_Stop *)(gr->alpha.stops->last);
284 if ((dist + ga_last->dist + gr->alpha.len) > 65535)
285 { free(ga); free(gam); return; }
286 gam->a = (ga_last->a + a) / 2;
288 gr->alpha.stops = evas_object_list_append(gr->alpha.stops, gam);
289 gr->alpha.len += ga_last->dist;
290 gr->alpha.stops = evas_object_list_append(gr->alpha.stops, ga);
291 gr->alpha.len += dist;
292 gr->alpha.nstops += 2;
298 evas_common_gradient_color_data_set(RGBA_Gradient *gr, DATA32 *data, int len, int alpha_flags)
301 if (!gr->imported_data)
302 evas_common_gradient_clear(gr);
303 if (len < 1) data = NULL;
305 gr->color.data = data;
307 gr->has_alpha = !!alpha_flags;
308 gr->imported_data = 1;
312 evas_common_gradient_alpha_data_set(RGBA_Gradient *gr, DATA8 *data, int len)
315 if (!gr->imported_data)
316 evas_common_gradient_clear(gr);
317 if (len < 1) data = NULL;
319 gr->alpha.data = data;
322 gr->imported_data = 1;
326 evas_common_gradient_type_set(RGBA_Gradient *gr, const char *name, char *params)
328 RGBA_Gradient_Type *geometer;
334 geometer = evas_common_gradient_geometer_get(name);
335 if (!geometer) return;
336 if (gr->type.gdata && (geometer != gr->type.geometer))
338 if (gr->type.geometer)
339 gr->type.geometer->geom_free(gr->type.gdata);
340 gr->type.gdata = NULL;
342 gr->type.geometer = geometer;
344 if (gr->type.name) free(gr->type.name);
345 gr->type.name = strdup(name);
347 if (params && !*params)
349 if (gr->type.params) free(gr->type.params);
350 gr->type.params = NULL;
351 if (params) gr->type.params = strdup(params);
353 gr->type.geometer->geom_init(gr);
357 evas_common_gradient_fill_set(RGBA_Gradient *gr, int x, int y, int w, int h)
362 if ((w < 1) && (h < 1))
369 evas_common_gradient_fill_angle_set(RGBA_Gradient *gr, float angle)
372 gr->fill.angle = angle;
376 evas_common_gradient_fill_spread_set(RGBA_Gradient *gr, int spread)
379 gr->fill.spread = spread;
383 evas_common_gradient_map_offset_set(RGBA_Gradient *gr, float offset)
386 gr->map.offset = offset;
390 evas_common_gradient_map_direction_set(RGBA_Gradient *gr, int direction)
393 gr->map.direction = (direction >= 0 ? 1 : -1);
397 evas_common_gradient_map_angle_set(RGBA_Gradient *gr, float angle)
400 gr->map.angle = angle;
403 EAPI RGBA_Gradient_Type *
404 evas_common_gradient_geometer_get(const char *name)
406 RGBA_Gradient_Type *geom = NULL;
410 if (!strcmp(name,"linear") || !strcmp(name,"linear.diag") || !strcmp(name,"linear.codiag"))
411 geom = evas_common_gradient_linear_get();
412 else if (!strcmp(name,"radial"))
413 geom = evas_common_gradient_radial_get();
414 else if (!strcmp(name,"angular"))
415 geom = evas_common_gradient_angular_get();
416 else if (!strcmp(name,"sinusoidal"))
417 geom = evas_common_gradient_sinusoidal_get();
418 else if (!strcmp(name,"rectangular"))
419 geom = evas_common_gradient_rectangular_get();
421 geom = evas_common_gradient_linear_get();
426 evas_common_gradient_draw(RGBA_Image *dst, RGBA_Draw_Context *dc,
427 int x, int y, int w, int h, RGBA_Gradient *gr)
429 Gfx_Func_Gradient_Fill gfunc;
432 int xin, yin, xoff, yoff;
433 int clx, cly, clw, clh;
434 int axx, axy, ayx, ayy;
435 DATA32 *pdst, *dst_end, *buf, *map;
436 RGBA_Image *argb_buf = NULL, *alpha_buf = NULL;
440 int direct_copy = 0, buf_step = 0;
442 if (!dst || !dc || !gr || !dst || !dst->image.data)
444 if (!gr->map.data || !gr->type.geometer)
446 if ((gr->fill.w < 1) || (gr->fill.h < 1))
448 if ((w < 1) || (h < 1))
450 clx = 0; cly = 0; clw = dst->cache_entry.w; clh = dst->cache_entry.h;
451 if ((clw < 1) || (clh < 1)) return;
454 RECTS_CLIP_TO_RECT(clx,cly,clw,clh, dc->clip.x,dc->clip.y,dc->clip.w,dc->clip.h);
455 if ((clw < 1) || (clh < 1)) return;
458 RECTS_CLIP_TO_RECT(x,y,w,h, clx,cly,clw,clh);
459 if ((w < 1) || (h < 1)) return;
461 xoff = (x - xin) - gr->fill.x;
462 yoff = (y - yin) - gr->fill.y;
464 if (!gr->type.geometer->has_mask(gr, dc->render_op))
466 if ((dc->render_op == _EVAS_RENDER_FILL) ||
467 (dc->render_op == _EVAS_RENDER_COPY))
469 direct_copy = 1; buf_step = dst->cache_entry.w;
470 if (gr->type.geometer->has_alpha(gr, dc->render_op))
471 dst->cache_entry.flags.alpha = 1;
473 else if ((dc->render_op == _EVAS_RENDER_BLEND) &&
474 !gr->type.geometer->has_alpha(gr, dc->render_op))
476 direct_copy = 1; buf_step = dst->cache_entry.w;
482 argb_buf = evas_common_image_line_buffer_obtain(w);
485 argb_buf->cache_entry.flags.alpha = gr->type.geometer->has_alpha(gr, dc->render_op) ? 1 : 0;
487 if (gr->type.geometer->has_mask(gr, dc->render_op))
489 alpha_buf = evas_common_image_alpha_line_buffer_obtain(w);
492 evas_common_image_line_buffer_release(argb_buf);
495 bfunc = evas_common_gfx_func_composite_pixel_mask_span_get(argb_buf, dst, w, dc->render_op);
498 bfunc = evas_common_gfx_func_composite_pixel_span_get(argb_buf, dst, w, dc->render_op);
501 gfunc = gr->type.geometer->get_fill_func(gr, dc->render_op, dc->anti_alias);
502 gdata = gr->type.gdata;
507 evas_common_image_line_buffer_release(argb_buf);
509 evas_common_image_alpha_line_buffer_release(alpha_buf);
514 /* I TOLD YOU! this here STOPS the gradeint bugs. it's a missing
515 * emms() before doing floating point operations! the thread pipe code
516 * just brought it out reliably. i swear i had seen this long before i
517 * ever added the thread/pipe code.
519 * now here is why it happens. NO drawing function... EXCEPT
520 * evas_common_polygon_draw() and evas_common_gradient_draw() use floating
521 * point for drawing (the poly stuff should really lose it actually), but
522 * nicely nestled in the poly draw code is a evas_common_cpu_end_opt()
523 * before it does any operations that would use floating point. the fact
524 * is the gradient code was LUCKY before without the thread pipes to almost
525 * all the time have another func do a evas_common_cpu_end_opt() before it
526 * was called. that was no longer the case with the thread renderer and
527 * it suffered. that is why on amd systems it seemed to work as i beileve
528 * on amd cpu's the amms done by evas_common_cpu_end_opt() is not needed
529 * to do floatingpoint ops again.
531 * after a lot of futzing about - this was the culprit (well axx and axy
532 * were garbage values eventually i found after much debugging and i traced
533 * their garbageness back to here).
535 evas_common_cpu_end_opt();
537 angle = (gr->fill.angle * M_PI) / 180.0;
538 axx = (cos(angle) * 65536.0);
540 axy = (sin(angle) * 65536.0);
545 pdst = dst->image.data + (y * dst->cache_entry.w) + x;
546 dst_end = pdst + (h * dst->cache_entry.w);
549 buf = argb_buf->image.data;
551 mask = (DATA8 *)alpha_buf->image.data;
555 while (pdst < dst_end)
558 if (((yoff + y) % dc->sli.h) == dc->sli.y)
561 gfunc(map, len, buf, mask, w, xoff, yoff, axx, axy, ayx, ayy, gdata);
562 evas_common_cpu_end_opt();
564 bfunc(buf, mask, 0, pdst, w);
565 evas_common_cpu_end_opt();
568 pdst += dst->cache_entry.w;
574 evas_common_image_line_buffer_release(argb_buf);
576 evas_common_image_alpha_line_buffer_release(alpha_buf);
581 evas_common_gradient_map_argb(RGBA_Draw_Context *dc, RGBA_Gradient *gr, int len)
596 if ((len != gr->map.len) || (!gr->map.data))
597 gr->map.data = realloc(gr->map.data, len * sizeof(DATA32));
599 { gr->map.len = 0; return; }
601 gr->map.has_alpha = gr->has_alpha;
604 mul_use = dc->mul.use;
605 if (dc->mul.col == 0xffffffff)
608 if ((!gr->imported_data) && (!gr->color.stops) && (!gr->alpha.stops))
610 static DATA32 p = 0xffffffff;
614 gr->imported_data = 1;
620 Evas_Object_List *lc;
621 RGBA_Gradient_Color_Stop *gc, *gc_next;
622 DATA32 *pmap, *map_end;
625 int next_r, next_g, next_b, next_a;
626 int rr, drr, gg, dgg, bb, dbb, aa, daa;
627 int mr = 256, mg = 256, mb = 256, ma = 256;
629 gr->color.data = realloc(gr->color.data, gr->color.len * sizeof(DATA32));
630 if (!gr->color.data) return;
632 gc = (RGBA_Gradient_Color_Stop *)gr->color.stops;
633 r = gc->r; g = gc->g; b = gc->b; a = gc->a;
636 mr = 1 + ((color >> 16) & 0xff); mg = 1 + ((color >> 8) & 0xff);
637 mb = 1 + ((color) & 0xff); ma = 1 + (color >> 24);
639 gr->map.has_alpha = 1;
640 r = (r * mr) >> 8; g = (g * mg) >> 8;
641 b = (b * mb) >> 8; a = (a * ma) >> 8;
643 lc = gr->color.stops->next;
644 pmap = gr->color.data; map_end = pmap + gr->color.len;
646 while (pmap < map_end)
652 gc_next = (RGBA_Gradient_Color_Stop *)lc;
653 next_r = gc_next->r; next_g = gc_next->g;
654 next_b = gc_next->b; next_a = gc_next->a;
657 next_r = (next_r * mr) >> 8; next_g = (next_g * mg) >> 8;
658 next_b = (next_b * mb) >> 8; next_a = (next_a * ma) >> 8;
660 rr = r << 16; drr = ((next_r - r) * dii);
661 gg = g << 16; dgg = ((next_g - g) * dii);
662 bb = b << 16; dbb = ((next_b - b) * dii);
663 aa = a << 16; daa = ((next_a - a) * dii);
666 r = rr >> 16; r += (rr - (r << 16)) >> 15;
667 g = gg >> 16; g += (gg - (g << 16)) >> 15;
668 b = bb >> 16; b += (bb - (b << 16)) >> 15;
669 a = aa >> 16; a += (aa - (a << 16)) >> 15;
670 *pmap++ = ARGB_JOIN(a,r,g,b);
671 rr += drr; gg += dgg; bb += dbb; aa += daa;
674 r = next_r; g = next_g; b = next_b; a = next_a;
678 *pmap++ = ARGB_JOIN(a,r,g,b);
684 Evas_Object_List *lc;
685 RGBA_Gradient_Alpha_Stop *ga, *ga_next;
686 DATA8 *pamap, *amap_end;
691 gr->alpha.data = realloc(gr->alpha.data, gr->alpha.len * sizeof(DATA8));
692 if (!gr->alpha.data) return;
694 ga = (RGBA_Gradient_Alpha_Stop *)gr->alpha.stops;
696 lc = gr->alpha.stops->next;
697 pamap = gr->alpha.data; amap_end = pamap + gr->alpha.len;
699 while (pamap < amap_end)
705 ga_next = (RGBA_Gradient_Alpha_Stop *)lc;
707 aa = a << 16; daa = ((next_a - a) * dii);
710 a = aa >> 16; a += (aa - (a << 16)) >> 15;
723 if (gr->color.data && gr->alpha.data)
725 if (!gr->imported_data)
727 if (gr->color.len == gr->alpha.len)
729 evas_common_scale_rgba_a8_span(gr->color.data, gr->alpha.data, gr->color.len,
730 color, gr->map.data, gr->map.len, gr->map.direction);
733 evas_common_scale_rgba_span(gr->color.data, NULL, gr->color.len,
734 color, gr->map.data, gr->map.len, gr->map.direction);
735 evas_common_scale_clip_a8_span(NULL, gr->alpha.data, gr->alpha.len,
736 0xffffffff, gr->map.data, gr->map.len, gr->map.direction);
742 if (!gr->imported_data)
744 evas_common_scale_rgba_span(gr->color.data, NULL, gr->color.len,
745 color, gr->map.data, gr->map.len, gr->map.direction);
746 gr->map.has_alpha |= (!!(255 - (color >> 24)));
750 evas_common_scale_a8_span(NULL, gr->alpha.data, gr->alpha.len,
751 color, gr->map.data, gr->map.len, gr->map.direction);
755 evas_common_gradient_map_ahsv(RGBA_Draw_Context *dc, RGBA_Gradient *gr, int len)
769 if ((len != gr->map.len) || (!gr->map.data))
770 gr->map.data = realloc(gr->map.data, len * sizeof(DATA32));
772 { gr->map.len = 0; return; }
774 gr->map.has_alpha = gr->has_alpha;
780 if ((!gr->imported_data) && (!gr->color.stops) && (!gr->alpha.stops))
782 static DATA32 p = 0xffffffff;
786 gr->imported_data = 1;
792 Evas_Object_List *lc;
793 RGBA_Gradient_Color_Stop *gc, *gc_next;
794 DATA32 *pmap, *map_end;
797 int next_h, next_s, next_v;
798 int hh, dhh, ss, dss, vv, dvv, aa, daa;
800 int next_r, next_g, next_b, next_a;
802 gr->color.data = realloc(gr->color.data, gr->color.len * sizeof(DATA32));
803 if (!gr->color.data) return;
805 gc = (RGBA_Gradient_Color_Stop *)gr->color.stops;
806 r = gc->r; g = gc->g; b = gc->b; a = gc->a;
807 evas_common_convert_color_rgb_to_hsv_int(r, g, b, &h, &s, &v);
809 lc = gr->color.stops->next;
810 pmap = gr->color.data; map_end = pmap + gr->color.len;
812 while (pmap < map_end)
818 gc_next = (RGBA_Gradient_Color_Stop *)lc;
820 next_r = gc_next->r; next_g = gc_next->g;
821 next_b = gc_next->b; next_a = gc_next->a;
822 evas_common_convert_color_rgb_to_hsv_int(next_r, next_g, next_b,
823 &next_h, &next_s, &next_v);
824 hh = h << 16; dhh = ((next_h - h) * dii);
825 ss = s << 16; dss = ((next_s - s) * dii);
826 vv = v << 16; dvv = ((next_v - v) * dii);
827 aa = a << 16; daa = ((next_a - a) * dii);
830 h = hh >> 16; h += (hh - (h << 16)) >> 15;
831 s = ss >> 16; s += (ss - (s << 16)) >> 15;
832 v = vv >> 16; v += (vv - (v << 16)) >> 15;
833 a = aa >> 16; a += (aa - (a << 16)) >> 15;
834 evas_common_convert_color_hsv_to_rgb_int(h, s, v, &r, &g, &b);
835 *pmap++ = ARGB_JOIN(a,r,g,b);
836 hh += dhh; ss += dss; vv += dvv; aa += daa;
839 h = next_h; s = next_s; v = next_v; a = next_a;
843 *pmap++ = ARGB_JOIN(gc->a,gc->r,gc->g,gc->b);
849 Evas_Object_List *lc;
850 RGBA_Gradient_Alpha_Stop *ga, *ga_next;
851 DATA8 *pamap, *amap_end;
856 gr->alpha.data = realloc(gr->alpha.data, gr->alpha.len * sizeof(DATA8));
857 if (!gr->alpha.data) return;
859 ga = (RGBA_Gradient_Alpha_Stop *)gr->alpha.stops;
861 lc = gr->alpha.stops->next;
862 pamap = gr->alpha.data; amap_end = pamap + gr->alpha.len;
864 while (pamap < amap_end)
870 ga_next = (RGBA_Gradient_Alpha_Stop *)lc;
872 aa = a << 16; daa = ((next_a - a) * dii);
875 a = aa >> 16; a += (aa - (a << 16)) >> 15;
888 if (gr->color.data && gr->alpha.data)
890 if (gr->color.len == gr->alpha.len)
892 evas_common_scale_hsva_a8_span(gr->color.data, gr->alpha.data, gr->color.len,
893 color, gr->map.data, gr->map.len, gr->map.direction);
896 evas_common_scale_hsva_span(gr->color.data, NULL, gr->color.len,
897 color, gr->map.data, gr->map.len, gr->map.direction);
898 evas_common_scale_clip_a8_span(NULL, gr->alpha.data, gr->alpha.len,
899 0xffffffff, gr->map.data, gr->map.len, gr->map.direction);
904 evas_common_scale_hsva_span(gr->color.data, NULL, gr->color.len,
905 color, gr->map.data, gr->map.len, gr->map.direction);
906 gr->map.has_alpha |= (!!(255 - (color >> 24)));
910 evas_common_scale_a8_span(NULL, gr->alpha.data, gr->alpha.len,
911 color, gr->map.data, gr->map.len, gr->map.direction);
915 evas_common_gradient_map(RGBA_Draw_Context *dc, RGBA_Gradient *gr, int len)
917 if (!gr || !dc) return;
918 if (dc->interpolation.color_space == _EVAS_COLOR_SPACE_AHSV)
920 evas_common_gradient_map_ahsv(dc, gr, len);
923 evas_common_gradient_map_argb(dc, gr, len);