From 6b36f92065f054abd810d956169a87180677d4f7 Mon Sep 17 00:00:00 2001 From: lecoanet Date: Mon, 18 Feb 2002 16:03:54 +0000 Subject: Passage des couleurs en gradients pour uniformiser --- generic/Color.c | 266 +++++++++++++++++++++++++------------------------------- 1 file changed, 119 insertions(+), 147 deletions(-) (limited to 'generic/Color.c') diff --git a/generic/Color.c b/generic/Color.c index 33708c7..f60722a 100644 --- a/generic/Color.c +++ b/generic/Color.c @@ -143,11 +143,11 @@ typedef struct { /* * Maximum size of a color name including the \0. */ -#define COLOR_NAME_SIZE 128 +#define COLOR_NAME_SIZE 32 /* * Maximum size of a gradient name including the \0. */ -#define GRADIENT_NAME_SIZE 512 +#define GRADIENT_NAME_SIZE 1024 /* * Maximum intensity for a color. @@ -854,34 +854,32 @@ HsvToRgb(ZnReal h, *---------------------------------------------------------------------- */ XColor * -ZnGetGradientColor(Tk_Window tkwin, - ZnGradient *grad, +ZnGetGradientColor(ZnGradient *grad, ZnReal position, int *alpha) { int index, min, max; - ZnGradientColor *color, *next_color; XColor *shade=NULL; - ZnReal tt; - if ((grad->num_colors == 1) || (position < 0.0)) { + if ((grad->num_colors == 1) || (position <= 0.0)) { if (alpha) { - *alpha = grad->colors[0]->alpha; + *alpha = grad->colors[0].alpha; } - return grad->colors[0]->shades[0]; + return grad->colors[0].rgb; } if (position >= 100.0) { if (alpha) { - *alpha = grad->colors[grad->num_colors-1]->alpha; + *alpha = grad->colors[grad->num_colors-1].alpha; } - shade = grad->colors[grad->num_colors-1]->shades[0]; + shade = grad->colors[grad->num_colors-1].rgb; } else { min = 0; max = grad->num_colors-1; index = (max + min) / 2; while (max - min != 1) { - if (grad->colors[index]->position < position) { + /*printf("color index %d, min: %d, max: %d\n", index, min, max);*/ + if (grad->colors[index].position < position) { min = index; } else { @@ -889,17 +887,9 @@ ZnGetGradientColor(Tk_Window tkwin, } index = (max + min) / 2; } - /*printf("color index %d ", index);*/ - color = grad->colors[index]; - next_color = grad->colors[index+1]; - tt = (grad->num_shades * (position - (ZnReal) color->position) / - (ZnReal) (next_color->position - color->position)); - index = (int) tt; - /*printf("shade index %d %g\n", index, tt);*/ - shade = color->shades[index]; + shade = grad->colors[index].rgb; if (alpha) { - *alpha = ((next_color->alpha-color->alpha) * (position - (ZnReal) color->position) / - (ZnReal) (next_color->position - color->position)); + *alpha = grad->colors[index].alpha; } } @@ -938,11 +928,7 @@ ZnGradientFlat(ZnGradient *grad) * Results: * The return value is a token for a data structure * describing a gradient. This token may be passed - * to the drawing routines. This function allocate - * the base color and the two end colors in an attempt - * to use only actually needed resources. The function - * ZnGetGradientColor asserts that all the colors - * get allocated when needed. + * to the drawing routines. * If an error prevented the gradient from being created * then NULL is returned and an error message will be * left in interp. @@ -959,9 +945,11 @@ ZnGetReliefGradient(Tcl_Interp *interp, Tk_Window tkwin, Tk_Uid name) { - XColor *base, light_color, dark_color; + XColor *base, light_color, dark_color, color; char color_name[COLOR_NAME_SIZE]; - int tmp1, tmp2; + char buffer[GRADIENT_NAME_SIZE]; + int j, tmp1, tmp2; + int red_range, green_range, blue_range; base = ZnGetColor(interp, tkwin, name); /* @@ -1013,59 +1001,45 @@ ZnGetReliefGradient(Tcl_Interp *interp, tmp2 = (MAX_INTENSITY + (int) base->blue)/2; light_color.blue = MAX(tmp1, tmp2); - sprintf(color_name, "#%02x%02x%02x|#%02x%02x%02x 50|#%02x%02x%02x%%%d", - dark_color.red/256, dark_color.green/256, dark_color.blue/256, - base->red/256, base->green/256, base->blue/256, - light_color.red/256, light_color.green/256, light_color.blue/256, - RELIEF_STEPS); + buffer[0] = 0; + sprintf(color_name, "#%02x%02x%02x|", + dark_color.red/256, dark_color.green/256, dark_color.blue/256); + red_range = (int) base->red - (int) dark_color.red; + green_range = (int) base->green - (int) dark_color.green; + blue_range = (int) base->blue - (int) dark_color.blue; + strcat(buffer, color_name); + for (j = 1; j < RELIEF_STEPS; j++) { + color.red =(int) dark_color.red + red_range * j/RELIEF_STEPS; + color.green = (int) dark_color.green + green_range * j/RELIEF_STEPS; + color.blue = (int) dark_color.blue + blue_range * j/RELIEF_STEPS; + sprintf(color_name, "#%02x%02x%02x %d|", + color.red/256, color.green/256, color.blue/256, 50/RELIEF_STEPS*j); + strcat(buffer, color_name); + } + sprintf(color_name, "#%02x%02x%02x 50|", + base->red/256, base->green/256, base->blue/256); + strcat(buffer, color_name); + red_range = (int) light_color.red - (int) base->red; + green_range = (int) light_color.green - (int) base->green; + blue_range = (int) light_color.blue - (int) base->blue; + for (j = 1; j < RELIEF_STEPS; j++) { + color.red =(int) base->red + red_range * j/RELIEF_STEPS; + color.green = (int) base->green + green_range * j/RELIEF_STEPS; + color.blue = (int) base->blue + blue_range * j/RELIEF_STEPS; + sprintf(color_name, "#%02x%02x%02x %d|", + color.red/256, color.green/256, color.blue/256, 50+50/RELIEF_STEPS*j); + strcat(buffer, color_name); + } + sprintf(color_name, "#%02x%02x%02x", + light_color.red/256, light_color.green/256, light_color.blue/256); + strcat(buffer, color_name); - return ZnGetGradient(interp, tkwin, color_name); + /*printf("gradient relief: %s \n", buffer);*/ + return ZnGetGradient(interp, tkwin, buffer); } /* - *---------------------------------------------------------------------- - * - * 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); - } - } -} - -/* *-------------------------------------------------------------- * * ZnNameGradient @@ -1130,11 +1104,7 @@ ZnDeleteGradientName(char *name) * Results: * The return value is a token for a data structure * describing a gradient. This token may be passed - * to the drawing routines. This function allocate - * the milestone colors in an attempt to use only - * actually needed resources. The function - * ZnGetGradientColor asserts that all the colors - * get allocated when needed. + * to the drawing routines. * If an error prevented the gradient from being created * then NULL is returned and an error message will be * left in interp. @@ -1161,12 +1131,15 @@ ZnGetGradient(Tcl_Interp *interp, { Tcl_HashEntry *hash; ZnGradient *grad; - int i, j, new, num_colors, num_shades; + int i, j, new, num_colors; char type, *scan_ptr; int num_tok, angle, position, control; double x, y; char *color_ptr, color_name[COLOR_NAME_SIZE]; char buffer[GRADIENT_NAME_SIZE]; + ZnGradientColor *first, *last; + XColor color; + int red_range, green_range, blue_range; if (!name || !*name) { return NULL; @@ -1190,31 +1163,12 @@ ZnGetGradient(Tcl_Interp *interp, /* * No satisfactory gradient exists yet. Initialize a new one. */ - if ((name[0] == '%') || (name[0] == '/') || (name[0] == '(')) { + if ((name[0] == '/') || (name[0] == '(') || (name[0] == '[')) { goto grad_err2; } strcpy(buffer, name); /* - * Try to obtain how many shades sould be drawn. - */ - 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'; - } - if (num_shades < 2) { - num_shades = 2; - } - else { - /* - * Keep num_shades even. - */ - num_shades /= 2; - num_shades *= 2; - } - /* * Then look at the gradient type. */ type = ZN_AXIAL_GRADIENT; @@ -1263,9 +1217,8 @@ ZnGetGradient(Tcl_Interp *interp, * Create the gradient structure. */ grad = (ZnGradient *) ZnMalloc(sizeof(ZnGradient) + - sizeof(ZnGradientColor *)*(num_colors-1)); + sizeof(ZnGradientColor)*(num_colors-1)); grad->ref_count = 1; - grad->num_shades = num_shades; grad->num_colors = num_colors; grad->type = type; if (type == ZN_AXIAL_GRADIENT) { @@ -1280,30 +1233,23 @@ ZnGetGradient(Tcl_Interp *interp, scan_ptr = strtok(buffer, "|"); for (i = 0; i < num_colors; i++) { - if (i != num_colors - 1) { - grad->colors[i] = (ZnGradientColor *) ZnMalloc(sizeof(ZnGradientColor) + - sizeof(XColor *)*(num_shades-1)); - } - else { - grad->colors[i] = (ZnGradientColor *) ZnMalloc(sizeof(ZnGradientColor)); - } - grad->colors[i]->position = 0; - grad->colors[i]->control = 50; - grad->colors[i]->alpha = 100; + 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, &position, &control); if (num_tok > 1) { - grad->colors[i]->position = position; + grad->colors[i].position = position; } if (num_tok > 2) { - grad->colors[i]->control = control; + grad->colors[i].control = control; } if (num_tok == 0) { Tcl_AppendResult(interp, "incorrect gradient format \"", name, "\",", NULL); grad_err: Tcl_DeleteHashEntry(hash); - for (j = i; j >= 0; j--) { - ZnFree(grad->colors[j]); + for (j = 0; j < i; j++) { + ZnFreeColor(grad->colors[j].rgb); } ZnFree(grad); return NULL; @@ -1312,47 +1258,59 @@ ZnGetGradient(Tcl_Interp *interp, if (color_ptr) { *color_ptr = 0; } - grad->colors[i]->shades[0] = ZnGetColor(interp, tkwin, Tk_GetUid(color_name)); + grad->colors[i].rgb = ZnGetColor(interp, tkwin, Tk_GetUid(color_name)); if (color_ptr) { *color_ptr = ':'; } - if (grad->colors[i]->shades[0] == NULL) { + if (grad->colors[i].rgb == 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; - } + grad->colors[i].alpha = atoi(color_ptr+1); } if (i == 0) { - grad->colors[i]->position = 0; + grad->colors[i].position = 0; } else if (i == num_colors - 1) { - grad->colors[i]->position = 100; + grad->colors[i].position = 100; } if ((num_tok > 2) && (i > 0)) { - if ((grad->colors[i]->position > 100) || - (grad->colors[i]->position < grad->colors[i-1]->position)) { + if ((grad->colors[i].position > 100) || + (grad->colors[i].position < grad->colors[i-1].position)) { Tcl_AppendResult(interp, "incorrect color position in gradient \"", name, "\",", NULL); goto grad_err; } } - if (grad->colors[i]->control > 100) { - grad->colors[i]->control = 100; + if (grad->colors[i].control > 100) { + grad->colors[i].control = 100; } - if (grad->colors[i]->alpha > 100) { - grad->colors[i]->alpha = 100; + if (grad->colors[i].alpha > 100) { + grad->colors[i].alpha = 100; } scan_ptr = strtok(NULL, "|"); } } - - RealizeGradient(grad, tkwin); + + /* + * Compute the mid alpha and mid color values. These will be + * used by the gradient rendering primitives when a control + * is not at mid range. The last color has no mid_* values. + */ + for (i = 0; i < grad->num_colors-1; i++) { + first = &grad->colors[i]; + last = &grad->colors[i+1]; + red_range = (int) last->rgb->red - (int) first->rgb->red; + green_range = (int) last->rgb->green - (int) first->rgb->green; + blue_range = (int) last->rgb->blue - (int) first->rgb->blue; + color.red =(int) first->rgb->red + red_range*first->control/100; + color.green = (int) first->rgb->green + green_range*first->control/100; + color.blue = (int) first->rgb->blue + blue_range*first->control/100; + first->mid_rgb = ZnGetColorByValue(tkwin, &color); + first->mid_alpha = first->alpha + (last->alpha-first->alpha)*first->control/100; + } + grad->colors[grad->num_colors-1].mid_rgb = NULL; return grad; } @@ -1361,7 +1319,7 @@ ZnGetGradient(Tcl_Interp *interp, /* *-------------------------------------------------------------- * - * ZnNameOfColorGradient -- + * ZnNameOfGradient -- * * Given a gradient, return a textual string identifying * the gradient. @@ -1403,21 +1361,35 @@ ZnNameOfGradient(ZnGradient *grad) void ZnFreeGradient(ZnGradient *grad) { - int i, j; + int i; grad->ref_count--; if (grad->ref_count == 0) { Tcl_DeleteHashEntry(grad->hash); - for (i = 0; i < grad->num_colors-1; i++) { - for (j = 0; j < grad->num_shades; j++) { - if (grad->colors[i]->shades[j] != NULL) { - ZnFreeColor(grad->colors[i]->shades[j]); - } + for (i = 0; i < grad->num_colors; i++) { + ZnFreeColor(grad->colors[i].rgb); + if (grad->colors[i].mid_rgb) { + ZnFreeColor(grad->colors[i].mid_rgb); } - ZnFree(grad->colors[i]); } - ZnFreeColor(grad->colors[grad->num_colors-1]->shades[0]); - ZnFree(grad->colors[grad->num_colors-1]); ZnFree(grad); } } + + +/* + *-------------------------------------------------------------- + * + * ZnComposeAlpha -- + * + * This procedure takes two alpha values in percent and + * returns the composite value between 0 and 65535. + * + *-------------------------------------------------------------- + */ +int +ZnComposeAlpha(int alpha1, + int alpha2) +{ + return (alpha1*alpha2/100)*65535/100; +} -- cgit v1.1