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 = eina_inlist_remove(gr->color.stops, gr->color.stops);
55 gr->color.stops = NULL;
62 while (gr->alpha.stops)
65 gr->alpha.stops = eina_inlist_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 #ifdef EVAS_FRAME_QUEUING
164 LKL(gr->ref_fq_add); LKL(gr->ref_fq_del);
165 if (gr->ref_fq[0] != gr->ref_fq[1])
167 LKU(gr->ref_fq_add); LKU(gr->ref_fq_del);
170 LKU(gr->ref_fq_add); LKU(gr->ref_fq_del);
172 evas_common_gradient_clear(gr);
173 if (gr->type.name) free(gr->type.name);
174 if (gr->type.params) free(gr->type.params);
175 if (gr->type.geometer && gr->type.gdata)
176 gr->type.geometer->geom_free(gr->type.gdata);
177 if (gr->map.data) free(gr->map.data);
182 evas_common_gradient_clear(RGBA_Gradient *gr)
186 _evas_common_gradient_stops_free(gr);
188 if (gr->color.data && !gr->imported_data)
189 free(gr->color.data);
190 gr->color.data = NULL;
192 if (gr->alpha.data && !gr->imported_data)
193 free(gr->alpha.data);
194 gr->alpha.data = NULL;
197 gr->imported_data = 0;
202 evas_common_gradient_color_stop_add(RGBA_Gradient *gr, int r, int g, int b, int a, int dist)
204 RGBA_Gradient_Color_Stop *gc, *gcm, *gc_last;
207 if (gr->imported_data)
209 gr->color.data = NULL;
211 gr->alpha.data = NULL;
213 gr->imported_data = 0;
216 gc = malloc(sizeof(RGBA_Gradient_Color_Stop));
218 if (dist < 1) dist = 1;
219 if (dist > 32768) dist = 32768;
220 if (r < 0) r = 0; if (r > 255) r = 255;
221 if (g < 0) g = 0; if (g > 255) g = 255;
222 if (b < 0) b = 0; if (b > 255) b = 255;
223 if (a < 0) a = 0; if (a > 255) a = 255;
230 if (!gr->color.stops)
232 gr->color.stops = eina_inlist_append(gr->color.stops, EINA_INLIST_GET(gc));
233 gr->color.nstops = 1;
239 gcm = malloc(sizeof(RGBA_Gradient_Color_Stop));
240 if (!gcm) { free(gc); return; }
241 gc_last = (RGBA_Gradient_Color_Stop *)(gr->color.stops->last);
242 if ((dist + gc_last->dist + gr->color.len) > 65535)
243 { free(gc); free(gcm); return; }
244 gcm->r = (gc_last->r + r) / 2;
245 gcm->g = (gc_last->g + g) / 2;
246 gcm->b = (gc_last->b + b) / 2;
247 gcm->a = (gc_last->a + a) / 2;
249 gr->color.stops = eina_inlist_append(gr->color.stops, EINA_INLIST_GET(gcm));
250 gr->color.len += gc_last->dist;
251 gr->color.stops = eina_inlist_append(gr->color.stops, EINA_INLIST_GET(gc));
252 gr->color.len += dist;
253 gr->color.nstops += 2;
259 evas_common_gradient_alpha_stop_add(RGBA_Gradient *gr, int a, int dist)
261 RGBA_Gradient_Alpha_Stop *ga, *gam, *ga_last;
264 if (gr->imported_data)
266 gr->color.data = NULL;
268 gr->alpha.data = NULL;
270 gr->imported_data = 0;
273 ga = malloc(sizeof(RGBA_Gradient_Alpha_Stop));
275 if (dist < 1) dist = 1;
276 if (dist > 32768) dist = 32768;
277 if (a < 0) a = 0; if (a > 255) a = 255;
281 if (!gr->alpha.stops)
283 gr->alpha.stops = eina_inlist_append(gr->alpha.stops, EINA_INLIST_GET(ga));
284 gr->alpha.nstops = 1;
290 gam = malloc(sizeof(RGBA_Gradient_Alpha_Stop));
291 if (!gam) { free(ga); return; }
292 ga_last = (RGBA_Gradient_Alpha_Stop *)(gr->alpha.stops->last);
293 if ((dist + ga_last->dist + gr->alpha.len) > 65535)
294 { free(ga); free(gam); return; }
295 gam->a = (ga_last->a + a) / 2;
297 gr->alpha.stops = eina_inlist_append(gr->alpha.stops, EINA_INLIST_GET(gam));
298 gr->alpha.len += ga_last->dist;
299 gr->alpha.stops = eina_inlist_append(gr->alpha.stops, EINA_INLIST_GET(ga));
300 gr->alpha.len += dist;
301 gr->alpha.nstops += 2;
307 evas_common_gradient_color_data_set(RGBA_Gradient *gr, DATA32 *data, int len, int alpha_flags)
310 if (!gr->imported_data)
311 evas_common_gradient_clear(gr);
312 if (len < 1) data = NULL;
314 gr->color.data = data;
316 gr->has_alpha = !!alpha_flags;
317 gr->imported_data = 1;
321 evas_common_gradient_alpha_data_set(RGBA_Gradient *gr, DATA8 *data, int len)
324 if (!gr->imported_data)
325 evas_common_gradient_clear(gr);
326 if (len < 1) data = NULL;
328 gr->alpha.data = data;
331 gr->imported_data = 1;
335 evas_common_gradient_type_set(RGBA_Gradient *gr, const char *name, char *params)
337 RGBA_Gradient_Type *geometer;
343 geometer = evas_common_gradient_geometer_get(name);
344 if (!geometer) return;
345 if (gr->type.gdata && (geometer != gr->type.geometer))
347 if (gr->type.geometer)
348 gr->type.geometer->geom_free(gr->type.gdata);
349 gr->type.gdata = NULL;
351 gr->type.geometer = geometer;
353 if (gr->type.name) free(gr->type.name);
354 gr->type.name = strdup(name);
356 if (params && !*params)
358 if (gr->type.params) free(gr->type.params);
359 gr->type.params = NULL;
360 if (params) gr->type.params = strdup(params);
362 gr->type.geometer->geom_init(gr);
366 evas_common_gradient_fill_set(RGBA_Gradient *gr, int x, int y, int w, int h)
371 if ((w < 1) && (h < 1))
378 evas_common_gradient_fill_angle_set(RGBA_Gradient *gr, float angle)
381 gr->fill.angle = angle;
385 evas_common_gradient_fill_spread_set(RGBA_Gradient *gr, int spread)
388 gr->fill.spread = spread;
392 evas_common_gradient_map_offset_set(RGBA_Gradient *gr, float offset)
395 gr->map.offset = offset;
399 evas_common_gradient_map_direction_set(RGBA_Gradient *gr, int direction)
402 gr->map.direction = (direction >= 0 ? 1 : -1);
406 evas_common_gradient_map_angle_set(RGBA_Gradient *gr, float angle)
409 gr->map.angle = angle;
412 EAPI RGBA_Gradient_Type *
413 evas_common_gradient_geometer_get(const char *name)
415 RGBA_Gradient_Type *geom = NULL;
419 if (!strcmp(name,"linear") || !strcmp(name,"linear.diag") || !strcmp(name,"linear.codiag"))
420 geom = evas_common_gradient_linear_get();
421 else if (!strcmp(name,"radial"))
422 geom = evas_common_gradient_radial_get();
423 else if (!strcmp(name,"angular"))
424 geom = evas_common_gradient_angular_get();
425 else if (!strcmp(name,"sinusoidal"))
426 geom = evas_common_gradient_sinusoidal_get();
427 else if (!strcmp(name,"rectangular"))
428 geom = evas_common_gradient_rectangular_get();
430 geom = evas_common_gradient_linear_get();
435 evas_common_gradient_draw(RGBA_Image *dst, RGBA_Draw_Context *dc,
436 int x, int y, int w, int h, RGBA_Gradient *gr)
438 Gfx_Func_Gradient_Fill gfunc;
439 RGBA_Gfx_Func bfunc = NULL;
441 int xin, yin, xoff, yoff;
442 int clx, cly, clw, clh;
443 int axx, axy, ayx, ayy;
444 DATA32 *pdst, *dst_end, *buf, *map;
445 RGBA_Image *argb_buf = NULL, *alpha_buf = NULL;
449 int direct_copy = 0, buf_step = 0;
451 if (!dst || !dc || !gr || !dst || !dst->image.data)
453 if (!gr->map.data || !gr->type.geometer)
455 if ((gr->fill.w < 1) || (gr->fill.h < 1))
457 if ((w < 1) || (h < 1))
459 clx = 0; cly = 0; clw = dst->cache_entry.w; clh = dst->cache_entry.h;
460 if ((clw < 1) || (clh < 1)) return;
463 RECTS_CLIP_TO_RECT(clx,cly,clw,clh, dc->clip.x,dc->clip.y,dc->clip.w,dc->clip.h);
464 if ((clw < 1) || (clh < 1)) return;
467 RECTS_CLIP_TO_RECT(x,y,w,h, clx,cly,clw,clh);
468 if ((w < 1) || (h < 1)) return;
470 xoff = (x - xin) - gr->fill.x;
471 yoff = (y - yin) - gr->fill.y;
473 if (!gr->type.geometer->has_mask(gr, dc->render_op))
475 if ((dc->render_op == _EVAS_RENDER_FILL) ||
476 (dc->render_op == _EVAS_RENDER_COPY))
478 direct_copy = 1; buf_step = dst->cache_entry.w;
479 if (gr->type.geometer->has_alpha(gr, dc->render_op))
480 dst->cache_entry.flags.alpha = 1;
482 else if ((dc->render_op == _EVAS_RENDER_BLEND) &&
483 !gr->type.geometer->has_alpha(gr, dc->render_op))
485 direct_copy = 1; buf_step = dst->cache_entry.w;
491 argb_buf = evas_common_image_line_buffer_obtain(w);
494 argb_buf->cache_entry.flags.alpha = gr->type.geometer->has_alpha(gr, dc->render_op) ? 1 : 0;
496 if (gr->type.geometer->has_mask(gr, dc->render_op))
498 alpha_buf = evas_common_image_alpha_line_buffer_obtain(w);
501 evas_common_image_line_buffer_release(argb_buf);
504 bfunc = evas_common_gfx_func_composite_pixel_mask_span_get(argb_buf, dst, w, dc->render_op);
507 bfunc = evas_common_gfx_func_composite_pixel_span_get(argb_buf, dst, w, dc->render_op);
510 gfunc = gr->type.geometer->get_fill_func(gr, dc->render_op, dc->anti_alias);
511 gdata = gr->type.gdata;
516 evas_common_image_line_buffer_release(argb_buf);
518 evas_common_image_alpha_line_buffer_release(alpha_buf);
523 /* I TOLD YOU! this here STOPS the gradeint bugs. it's a missing
524 * emms() before doing floating point operations! the thread pipe code
525 * just brought it out reliably. i swear i had seen this long before i
526 * ever added the thread/pipe code.
528 * now here is why it happens. NO drawing function... EXCEPT
529 * evas_common_polygon_draw() and evas_common_gradient_draw() use floating
530 * point for drawing (the poly stuff should really lose it actually), but
531 * nicely nestled in the poly draw code is a evas_common_cpu_end_opt()
532 * before it does any operations that would use floating point. the fact
533 * is the gradient code was LUCKY before without the thread pipes to almost
534 * all the time have another func do a evas_common_cpu_end_opt() before it
535 * was called. that was no longer the case with the thread renderer and
536 * it suffered. that is why on amd systems it seemed to work as i beileve
537 * on amd cpu's the amms done by evas_common_cpu_end_opt() is not needed
538 * to do floatingpoint ops again.
540 * after a lot of futzing about - this was the culprit (well axx and axy
541 * were garbage values eventually i found after much debugging and i traced
542 * their garbageness back to here).
544 evas_common_cpu_end_opt();
546 angle = (gr->fill.angle * M_PI) / 180.0;
547 axx = (cos(angle) * 65536.0);
549 axy = (sin(angle) * 65536.0);
554 pdst = dst->image.data + (y * dst->cache_entry.w) + x;
555 dst_end = pdst + (h * dst->cache_entry.w);
558 buf = argb_buf->image.data;
560 mask = (DATA8 *)alpha_buf->image.data;
564 while (pdst < dst_end)
567 if (((yoff + y) % dc->sli.h) == dc->sli.y)
570 gfunc(map, len, buf, mask, w, xoff, yoff, axx, axy, ayx, ayy, gdata);
571 evas_common_cpu_end_opt();
573 bfunc(buf, mask, 0, pdst, w);
574 evas_common_cpu_end_opt();
577 pdst += dst->cache_entry.w;
583 evas_common_image_line_buffer_release(argb_buf);
585 evas_common_image_alpha_line_buffer_release(alpha_buf);
590 evas_common_gradient_map_argb(RGBA_Draw_Context *dc, RGBA_Gradient *gr, int len)
605 if ((len != gr->map.len) || (!gr->map.data))
606 gr->map.data = realloc(gr->map.data, len * sizeof(DATA32));
608 { gr->map.len = 0; return; }
610 gr->map.has_alpha = gr->has_alpha;
613 mul_use = dc->mul.use;
614 if (dc->mul.col == 0xffffffff)
617 if ((!gr->imported_data) && (!gr->color.stops) && (!gr->alpha.stops))
619 static DATA32 p = 0xffffffff;
623 gr->imported_data = 1;
630 RGBA_Gradient_Color_Stop *gc, *gc_next;
631 DATA32 *pmap, *map_end;
634 int next_r, next_g, next_b, next_a;
635 int rr, drr, gg, dgg, bb, dbb, aa, daa;
636 int mr = 256, mg = 256, mb = 256, ma = 256;
638 gr->color.data = realloc(gr->color.data, gr->color.len * sizeof(DATA32));
639 if (!gr->color.data) return;
641 gc = (RGBA_Gradient_Color_Stop *)gr->color.stops;
642 r = gc->r; g = gc->g; b = gc->b; a = gc->a;
645 mr = 1 + ((color >> 16) & 0xff); mg = 1 + ((color >> 8) & 0xff);
646 mb = 1 + ((color) & 0xff); ma = 1 + (color >> 24);
648 gr->map.has_alpha = 1;
649 r = (r * mr) >> 8; g = (g * mg) >> 8;
650 b = (b * mb) >> 8; a = (a * ma) >> 8;
652 lc = gr->color.stops->next;
653 pmap = gr->color.data; map_end = pmap + gr->color.len;
655 while (pmap < map_end)
661 gc_next = (RGBA_Gradient_Color_Stop *)lc;
662 next_r = gc_next->r; next_g = gc_next->g;
663 next_b = gc_next->b; next_a = gc_next->a;
666 next_r = (next_r * mr) >> 8; next_g = (next_g * mg) >> 8;
667 next_b = (next_b * mb) >> 8; next_a = (next_a * ma) >> 8;
669 rr = r << 16; drr = ((next_r - r) * dii);
670 gg = g << 16; dgg = ((next_g - g) * dii);
671 bb = b << 16; dbb = ((next_b - b) * dii);
672 aa = a << 16; daa = ((next_a - a) * dii);
675 r = rr >> 16; r += (rr - (r << 16)) >> 15;
676 g = gg >> 16; g += (gg - (g << 16)) >> 15;
677 b = bb >> 16; b += (bb - (b << 16)) >> 15;
678 a = aa >> 16; a += (aa - (a << 16)) >> 15;
679 *pmap++ = ARGB_JOIN(a,r,g,b);
680 rr += drr; gg += dgg; bb += dbb; aa += daa;
683 r = next_r; g = next_g; b = next_b; a = next_a;
687 *pmap++ = ARGB_JOIN(a,r,g,b);
694 RGBA_Gradient_Alpha_Stop *ga, *ga_next;
695 DATA8 *pamap, *amap_end;
700 gr->alpha.data = realloc(gr->alpha.data, gr->alpha.len * sizeof(DATA8));
701 if (!gr->alpha.data) return;
703 ga = (RGBA_Gradient_Alpha_Stop *)gr->alpha.stops;
705 lc = gr->alpha.stops->next;
706 pamap = gr->alpha.data; amap_end = pamap + gr->alpha.len;
708 while (pamap < amap_end)
714 ga_next = (RGBA_Gradient_Alpha_Stop *)lc;
716 aa = a << 16; daa = ((next_a - a) * dii);
719 a = aa >> 16; a += (aa - (a << 16)) >> 15;
732 if (gr->color.data && gr->alpha.data)
734 if (!gr->imported_data)
736 if (gr->color.len == gr->alpha.len)
738 evas_common_scale_rgba_a8_span(gr->color.data, gr->alpha.data, gr->color.len,
739 color, gr->map.data, gr->map.len, gr->map.direction);
742 evas_common_scale_rgba_span(gr->color.data, NULL, gr->color.len,
743 color, gr->map.data, gr->map.len, gr->map.direction);
744 evas_common_scale_clip_a8_span(NULL, gr->alpha.data, gr->alpha.len,
745 0xffffffff, gr->map.data, gr->map.len, gr->map.direction);
751 if (!gr->imported_data)
753 evas_common_scale_rgba_span(gr->color.data, NULL, gr->color.len,
754 color, gr->map.data, gr->map.len, gr->map.direction);
755 gr->map.has_alpha |= (!!(255 - (color >> 24)));
759 evas_common_scale_a8_span(NULL, gr->alpha.data, gr->alpha.len,
760 color, gr->map.data, gr->map.len, gr->map.direction);
764 evas_common_gradient_map_ahsv(RGBA_Draw_Context *dc, RGBA_Gradient *gr, int len)
778 if ((len != gr->map.len) || (!gr->map.data))
779 gr->map.data = realloc(gr->map.data, len * sizeof(DATA32));
781 { gr->map.len = 0; return; }
783 gr->map.has_alpha = gr->has_alpha;
789 if ((!gr->imported_data) && (!gr->color.stops) && (!gr->alpha.stops))
791 static DATA32 p = 0xffffffff;
795 gr->imported_data = 1;
802 RGBA_Gradient_Color_Stop *gc, *gc_next;
803 DATA32 *pmap, *map_end;
806 int next_h, next_s, next_v;
807 int hh, dhh, ss, dss, vv, dvv, aa, daa;
809 int next_r, next_g, next_b, next_a;
811 gr->color.data = realloc(gr->color.data, gr->color.len * sizeof(DATA32));
812 if (!gr->color.data) return;
814 gc = (RGBA_Gradient_Color_Stop *)gr->color.stops;
815 r = gc->r; g = gc->g; b = gc->b; a = gc->a;
816 evas_common_convert_color_rgb_to_hsv_int(r, g, b, &h, &s, &v);
818 lc = gr->color.stops->next;
819 pmap = gr->color.data; map_end = pmap + gr->color.len;
821 while (pmap < map_end)
827 gc_next = (RGBA_Gradient_Color_Stop *)lc;
829 next_r = gc_next->r; next_g = gc_next->g;
830 next_b = gc_next->b; next_a = gc_next->a;
831 evas_common_convert_color_rgb_to_hsv_int(next_r, next_g, next_b,
832 &next_h, &next_s, &next_v);
833 hh = h << 16; dhh = ((next_h - h) * dii);
834 ss = s << 16; dss = ((next_s - s) * dii);
835 vv = v << 16; dvv = ((next_v - v) * dii);
836 aa = a << 16; daa = ((next_a - a) * dii);
839 h = hh >> 16; h += (hh - (h << 16)) >> 15;
840 s = ss >> 16; s += (ss - (s << 16)) >> 15;
841 v = vv >> 16; v += (vv - (v << 16)) >> 15;
842 a = aa >> 16; a += (aa - (a << 16)) >> 15;
843 evas_common_convert_color_hsv_to_rgb_int(h, s, v, &r, &g, &b);
844 *pmap++ = ARGB_JOIN(a,r,g,b);
845 hh += dhh; ss += dss; vv += dvv; aa += daa;
848 h = next_h; s = next_s; v = next_v; a = next_a;
852 *pmap++ = ARGB_JOIN(gc->a,gc->r,gc->g,gc->b);
859 RGBA_Gradient_Alpha_Stop *ga, *ga_next;
860 DATA8 *pamap, *amap_end;
865 gr->alpha.data = realloc(gr->alpha.data, gr->alpha.len * sizeof(DATA8));
866 if (!gr->alpha.data) return;
868 ga = (RGBA_Gradient_Alpha_Stop *)gr->alpha.stops;
870 lc = gr->alpha.stops->next;
871 pamap = gr->alpha.data; amap_end = pamap + gr->alpha.len;
873 while (pamap < amap_end)
879 ga_next = (RGBA_Gradient_Alpha_Stop *)lc;
881 aa = a << 16; daa = ((next_a - a) * dii);
884 a = aa >> 16; a += (aa - (a << 16)) >> 15;
897 if (gr->color.data && gr->alpha.data)
899 if (gr->color.len == gr->alpha.len)
901 evas_common_scale_hsva_a8_span(gr->color.data, gr->alpha.data, gr->color.len,
902 color, gr->map.data, gr->map.len, gr->map.direction);
905 evas_common_scale_hsva_span(gr->color.data, NULL, gr->color.len,
906 color, gr->map.data, gr->map.len, gr->map.direction);
907 evas_common_scale_clip_a8_span(NULL, gr->alpha.data, gr->alpha.len,
908 0xffffffff, gr->map.data, gr->map.len, gr->map.direction);
913 evas_common_scale_hsva_span(gr->color.data, NULL, gr->color.len,
914 color, gr->map.data, gr->map.len, gr->map.direction);
915 gr->map.has_alpha |= (!!(255 - (color >> 24)));
919 evas_common_scale_a8_span(NULL, gr->alpha.data, gr->alpha.len,
920 color, gr->map.data, gr->map.len, gr->map.direction);
924 evas_common_gradient_map(RGBA_Draw_Context *dc, RGBA_Gradient *gr, int len)
926 if (!gr || !dc) return;
927 if (dc->interpolation.color_space == _EVAS_COLOR_SPACE_AHSV)
929 evas_common_gradient_map_ahsv(dc, gr, len);
932 evas_common_gradient_map_argb(dc, gr, len);