diff options
-rw-r--r-- | generic/Color.c | 197 |
1 files changed, 102 insertions, 95 deletions
diff --git a/generic/Color.c b/generic/Color.c index 57702c3..c853808 100644 --- a/generic/Color.c +++ b/generic/Color.c @@ -857,58 +857,6 @@ HsvToRgb(ZnReal h, /* *---------------------------------------------------------------------- * - * ZnRealizeGradient -- - * - * This procedure allocate the shades still unallocated in - * a gradient. The milestone colors are always allocated - * during the gradient's creation. - * It's called lazily by ZnGetGradientColor, so that the - * colors aren't allocated until something is actually drawn - * with them. - * - *---------------------------------------------------------------------- - */ -void -ZnRealizeGradient(ZnGradient *grad, - Tk_Window tkwin) -{ - int i, j, num_colors, num_shades; - int red_range, green_range, blue_range; - ZnGradientColor *first, *last; - XColor color; - - if (grad->realized) { - return; - } - - /*printf("realizing gradient with %d(%d) colors\n", - grad->num_colors, BORDER_STEPS);*/ - num_colors = grad->num_colors; - num_shades = grad->num_shades; - for (i = 0; i < grad->num_colors-1; i++) { - first = grad->colors[i]; - last = grad->colors[i+1]; - /*printf("first color : %d %d %d, last color : %d %d %d\n", - first->shades[0]->red, first->shades[0]->green, first->shades[0]->blue, - last->shades[0]->red, last->shades[0]->green, last->shades[0]->blue);*/ - red_range = (int) last->shades[0]->red - (int) first->shades[0]->red; - green_range = (int) last->shades[0]->green - (int) first->shades[0]->green; - blue_range = (int) last->shades[0]->blue - (int) first->shades[0]->blue; - for (j = 1; j < num_shades; j++) { - color.red =(int) first->shades[0]->red + red_range * j/num_shades; - color.green = (int) first->shades[0]->green + green_range * j/num_shades; - color.blue = (int) first->shades[0]->blue + blue_range * j/num_shades; - first->shades[j] = ZnGetColorByValue(tkwin, &color); - } - } - - grad->realized = True; -} - - -/* - *---------------------------------------------------------------------- - * * ZnGetGradientColor -- * *---------------------------------------------------------------------- @@ -916,24 +864,24 @@ ZnRealizeGradient(ZnGradient *grad, XColor * ZnGetGradientColor(Tk_Window tkwin, ZnGradient *grad, - ZnReal position) + ZnReal position, + int *alpha) { int index, min, max; ZnGradientColor *color, *next_color; XColor *shade=NULL; ZnReal tt; - if (!grad->realized) { - ZnRealizeGradient(grad, tkwin); - } - - if (grad->num_colors == 1) { + if ((grad->num_colors == 1) || (position < 0.0)) { + if (alpha) { + *alpha = grad->colors[0]->alpha; + } return grad->colors[0]->shades[0]; } - if (position < 0.0) { - shade = grad->colors[0]->shades[0]; - } - else if (position >= 100.0) { + if (position >= 100.0) { + if (alpha) { + *alpha = grad->colors[grad->num_colors-1]->alpha; + } shade = grad->colors[grad->num_colors-1]->shades[0]; } else { @@ -957,6 +905,10 @@ ZnGetGradientColor(Tk_Window tkwin, index = (int) tt; /*printf("shade index %d %g\n", index, tt);*/ shade = color->shades[index]; + if (alpha) { + *alpha = ((next_color->alpha-color->alpha) * (position - (ZnReal) color->position) / + (ZnReal) (next_color->position - color->position)); + } } return shade; @@ -1080,6 +1032,49 @@ ZnGetReliefGradient(Tcl_Interp *interp, /* + *---------------------------------------------------------------------- + * + * RealizeGradient -- + * + * This procedure allocate the shades still unallocated in + * a gradient. The milestone colors are always allocated + * during the gradient's creation. + * + *---------------------------------------------------------------------- + */ +static void +RealizeGradient(ZnGradient *grad, + Tk_Window tkwin) +{ + int i, j, num_colors, num_shades; + int red_range, green_range, blue_range; + ZnGradientColor *first, *last; + XColor color; + + /*printf("realizing gradient with %d(%d) colors\n", + grad->num_colors, BORDER_STEPS);*/ + num_colors = grad->num_colors; + num_shades = grad->num_shades; + for (i = 0; i < grad->num_colors-1; i++) { + first = grad->colors[i]; + last = grad->colors[i+1]; + /*printf("first color : %d %d %d, last color : %d %d %d\n", + first->shades[0]->red, first->shades[0]->green, first->shades[0]->blue, + last->shades[0]->red, last->shades[0]->green, last->shades[0]->blue);*/ + red_range = (int) last->shades[0]->red - (int) first->shades[0]->red; + green_range = (int) last->shades[0]->green - (int) first->shades[0]->green; + blue_range = (int) last->shades[0]->blue - (int) first->shades[0]->blue; + for (j = 1; j < num_shades; j++) { + color.red =(int) first->shades[0]->red + red_range * j/num_shades; + color.green = (int) first->shades[0]->green + green_range * j/num_shades; + color.blue = (int) first->shades[0]->blue + blue_range * j/num_shades; + first->shades[j] = ZnGetColorByValue(tkwin, &color); + } + } +} + + +/* *-------------------------------------------------------------- * * ZnGetGradient -- @@ -1125,8 +1120,8 @@ ZnGetGradient(Tcl_Interp *interp, int i, j, new, num_colors, num_shades; char type, *scan_ptr; int num_tok, angle; - int x, y; - char color_name[COLOR_NAME_SIZE]; + double x, y; + char *color_ptr, color_name[COLOR_NAME_SIZE]; char buffer[GRADIENT_NAME_SIZE]; if (!initialized) { @@ -1159,17 +1154,22 @@ ZnGetGradient(Tcl_Interp *interp, /* * Try to obtain how many shades sould be drawn. */ - num_shades = DEFAULT_NUM_SHADES; + num_shades = 2; /* Minimum needed to have the start and mid range color */ if ((scan_ptr = strchr(buffer, '%'))) { sscanf(scan_ptr, "%%%d", &num_shades); /*printf("num shades = %d\n", num_shades);*/ *scan_ptr = '\0'; } - /* - * Keep num_shades even. - */ - num_shades /= 2; - num_shades *= 2; + if (num_shades < 2) { + num_shades = 2; + } + else { + /* + * Keep num_shades even. + */ + num_shades /= 2; + num_shades *= 2; + } /* * Then look at the gradient type. */ @@ -1187,7 +1187,7 @@ ZnGetGradient(Tcl_Interp *interp, *scan_ptr = '\0'; } else if ((scan_ptr = strchr(buffer, '('))) { - num_tok = sscanf(scan_ptr, "(%d %d", &x, &y); + num_tok = sscanf(scan_ptr, "(%lf %lf", (double *) &x, (double *) &y); if (num_tok == 2) { type = ZN_RADIAL_GRADIENT; } @@ -1209,11 +1209,7 @@ ZnGetGradient(Tcl_Interp *interp, * Create the gradient structure. */ grad = (ZnGradient *) ZnMalloc(sizeof(ZnGradient) + - sizeof(ZnGradientColor *)*(num_colors-1)); - grad->screen = Tk_Screen(tkwin); - grad->visual = Tk_Visual(tkwin); - grad->depth = Tk_Depth(tkwin); - grad->colormap = key.colormap; + sizeof(ZnGradientColor *)*(num_colors-1)); grad->ref_count = 1; grad->num_shades = num_shades; grad->num_colors = num_colors; @@ -1222,10 +1218,9 @@ ZnGetGradient(Tcl_Interp *interp, grad->g.angle = angle; } else { - grad->g.c.x = x; - grad->g.c.y = y; + grad->g.p.x = x; + grad->g.p.y = y; } - grad->realized = False; grad->hash = hash; Tcl_SetHashValue(hash, grad); @@ -1238,7 +1233,11 @@ ZnGetGradient(Tcl_Interp *interp, else { grad->colors[i] = (ZnGradientColor *) ZnMalloc(sizeof(ZnGradientColor)); } - num_tok = sscanf(scan_ptr, "%s %d %d", color_name, &grad->colors[i]->position, + grad->colors[i]->position = 0; + grad->colors[i]->control = 50; + grad->colors[i]->alpha = 100; + num_tok = sscanf(scan_ptr, "%s %d %d", color_name, + &grad->colors[i]->position, &grad->colors[i]->control); if (num_tok == 0) { Tcl_AppendResult(interp, "incorrect gradient format \"", @@ -1251,11 +1250,21 @@ ZnGetGradient(Tcl_Interp *interp, ZnFree(grad); return NULL; } + color_ptr = strchr(color_name, ':'); + if (color_ptr) { + *color_ptr = 0; + } grad->colors[i]->shades[0] = ZnGetColor(interp, tkwin, Tk_GetUid(color_name)); + if (color_ptr) { + *color_ptr = ':'; + } if (grad->colors[i]->shades[0] == NULL) { Tcl_AppendResult(interp, " in gradient,", NULL); goto grad_err; } + if (color_ptr) { + grad->colors[i]->alpha = atoi(color_ptr+1); + } if (i != num_colors - 1) { for (j = 1; j < num_shades-1; j++) { grad->colors[i]->shades[j] = NULL; @@ -1267,10 +1276,7 @@ ZnGetGradient(Tcl_Interp *interp, else if (i == num_colors - 1) { grad->colors[i]->position = 100; } - else if (num_tok == 1) { - grad->colors[i]->position = 0; - } - if ((num_tok > 1) && (i > 0)) { + if ((num_tok > 2) && (i > 0)) { if ((grad->colors[i]->position > 100) || (grad->colors[i]->position < 0) || (grad->colors[i]->position < grad->colors[i-1]->position)) { @@ -1279,23 +1285,24 @@ ZnGetGradient(Tcl_Interp *interp, goto grad_err; } } - if (num_tok != 3) { - grad->colors[i]->control = 50; + if (grad->colors[i]->control < 0) { + grad->colors[i]->control = 0; } - else if ((grad->colors[i]->control < 0) || - (grad->colors[i]->control > 100)) { - Tcl_AppendResult(interp, "incorrect color control in gradient \"", - name, "\",", NULL); - goto grad_err; + if (grad->colors[i]->control > 100) { + grad->colors[i]->control = 100; + } + if (grad->colors[i]->alpha < 0) { + grad->colors[i]->alpha = 0; + } + if (grad->colors[i]->alpha > 100) { + grad->colors[i]->alpha = 100; } scan_ptr = strtok(NULL, "|"); } } - /* - * Delay the allocation of colors until they are actually - * needed for drawing. - */ + RealizeGradient(grad, tkwin); + return grad; } |