From a3adeee4ca08764b8e78282c4b1cd57a0d830c0d Mon Sep 17 00:00:00 2001 From: lecoanet Date: Mon, 25 Jun 2001 11:20:03 +0000 Subject: Modification des gradients --- generic/Arc.c | 33 +-- generic/Attrs.c | 112 --------- generic/Attrs.h | 21 -- generic/Color.c | 683 +++++++++++++++++++++++----------------------------- generic/Color.h | 57 ++++- generic/Curve.c | 40 ++- generic/Draw.c | 369 ++++++++++++++-------------- generic/Draw.h | 12 +- generic/Item.c | 70 ++---- generic/Rectangle.c | 44 ++-- generic/Types.h | 16 +- 11 files changed, 618 insertions(+), 839 deletions(-) (limited to 'generic') diff --git a/generic/Arc.c b/generic/Arc.c index f3699c8..43aeb5c 100644 --- a/generic/Arc.c +++ b/generic/Arc.c @@ -73,8 +73,7 @@ typedef struct _ArcItemStruct { int angle_extent; Pixmap line_pattern; Pixmap fill_pattern; - ZnColorGradient fill_color; - ZnGradientGeom grad_geom; + ZnGradient *fill_color; ZnColor line_color; int line_width; LineStyle line_style; @@ -112,7 +111,7 @@ static ZnAttrConfig arc_attrs[] = { Tk_Offset(ArcItemStruct, angle_extent), 0, ZN_COORDS_FLAG, False }, { ZN_CONFIG_UINT, "-fillalpha", NULL, Tk_Offset(ArcItemStruct, fill_alpha), 0, ZN_DRAW_FLAG, False }, - { ZN_CONFIG_GRADIENT_COLOR, "-fillcolor", NULL, + { ZN_CONFIG_GRADIENT, "-fillcolor", NULL, Tk_Offset(ArcItemStruct, fill_color), 0, ZN_DRAW_FLAG, False }, { ZN_CONFIG_BOOL, "-filled", NULL, Tk_Offset(ArcItemStruct, flags), FILLED_BIT, ZN_COORDS_FLAG, False }, @@ -120,8 +119,6 @@ static ZnAttrConfig arc_attrs[] = { Tk_Offset(ArcItemStruct, fill_pattern), 0, ZN_DRAW_FLAG, False }, { ZN_CONFIG_LINE_END, "-firstend", NULL, Tk_Offset(ArcItemStruct, first_end), 0, ZN_COORDS_FLAG, False }, - { ZN_CONFIG_GRADIENT_GEOM, "-gradient", NULL, - Tk_Offset(ArcItemStruct, grad_geom), 0, ZN_COORDS_FLAG, False }, { ZN_CONFIG_LINE_END, "-lastend", NULL, Tk_Offset(ArcItemStruct, last_end), 0, ZN_COORDS_FLAG, False }, { ZN_CONFIG_UINT, "-linealpha", NULL, @@ -237,11 +234,10 @@ Init(Item item, (*argc)--; arc->fill_alpha = 255; - arc->fill_color = ZnGetColorGradient(wi->interp, wi->win, - ZnNameOfColor(wi->fore_color)); + arc->fill_color = ZnGetGradient(wi->interp, wi->win, + ZnNameOfColor(wi->fore_color)); arc->line_alpha = 255; arc->line_color = ZnGetColorByValue(wi->win, wi->fore_color); - arc->grad_geom = NULL; #ifdef LIBART arc->outline_svp = arc->fill_svp = NULL; #endif @@ -286,10 +282,7 @@ Clone(Item item) Tk_NameOfBitmap(wi->dpy, arc->fill_pattern)); } arc->line_color = ZnGetColorByValue(wi->win, arc->line_color); - arc->fill_color = ZnGetColorGradientByValue(arc->fill_color); - if (arc->grad_geom) { - arc->grad_geom = GradientGeomDuplicate(arc->grad_geom); - } + arc->fill_color = ZnGetGradientByValue(arc->fill_color); #ifdef LIBART arc->outline_svp = arc->fill_svp = NULL; #endif @@ -340,11 +333,8 @@ Destroy(Item item) if (arc->fill_pattern != ZnUnspecifiedPattern) { Tk_FreeBitmap(wi->dpy, arc->fill_pattern); } - ZnFreeColorGradient(arc->fill_color); + ZnFreeGradient(arc->fill_color); ZnFreeColor(arc->line_color); - if (arc->grad_geom) { - GradientGeomDelete(arc->grad_geom); - } } @@ -534,7 +524,7 @@ ComputeCoordinates(Item item, width_2 = (arc->coords[1].x - arc->coords[0].x)/2.0; height_2 = (arc->coords[1].y - arc->coords[0].y)/2.0; if (((angle >= PRECISION_LIMIT) && ((width_2 - height_2) > PRECISION_LIMIT)) || - arc->grad_geom || wi->render) { + !ZnGradientFlat(arc->fill_color) || wi->render) { SET(arc->flags, USING_POLY_BIT); if (!arc->render_shape) { arc->render_shape = ZnListNew(4, sizeof(ZnPoint)); @@ -1067,14 +1057,15 @@ Draw(Item item) /* Fill if requested */ if (ISSET(arc->flags, FILLED_BIT)) { - if (arc->grad_geom) { + if (!ZnGradientFlat(arc->fill_color)) { ZnPoly poly; POLY_CONTOUR1(&poly, p, num_points); - DrawPolygonGradient(wi, arc->grad_geom, arc->fill_color, &poly, + DrawPolygonGradient(wi, arc->fill_color, &poly, &item->item_bounding_box); } else { - values.foreground = ZnPixel(ZnColorGradientMidColor(wi->win, arc->fill_color)); + values.foreground = ZnPixel(ZnGetGradientColor(wi->win, + arc->fill_color, 50.0)); values.arc_mode = ISSET(arc->flags, PIE_SLICE_BIT) ? ArcPieSlice : ArcChord; if (arc->tile != ZnUnspecifiedImage) { /* Fill Tiled */ Pixmap pmap = GetImagePixmap(wi->win, arc->tile_name, arc->tile, NULL); @@ -1232,7 +1223,7 @@ Render(Item item) #ifdef LIBART WidgetInfo *wi = item->wi; ArcItem arc = (ArcItem) item; - XColor *color = ZnColorGradientMidColor(wi->win, arc->fill_color); + XColor *color = ZnGetGradientColor(wi->win, arc->fill_color, 50.0); ArtPixBuf *pixbuf = NULL; if (arc->fill_svp != NULL) { diff --git a/generic/Attrs.c b/generic/Attrs.c index bfd155c..45d7dc8 100644 --- a/generic/Attrs.c +++ b/generic/Attrs.c @@ -502,115 +502,3 @@ LineEndDuplicate(ZnLineEnd le) le->ref_count++; return le; } - - -/* - **************************************************************** - * - * Code for gradient geometry. - * - **************************************************************** - */ -static Tcl_HashTable gradient_geom_cache; -static ZnBool gradient_inited = False; - -ZnGradientGeom -GradientGeomCreate(Tcl_Interp *interp, - char *grad_geom_str) -{ - Tcl_HashEntry *entry; - ZnGradientGeom gg; - int new; - char *next_ptr, *ptr; - int d1, d2, angle; - - if (!gradient_inited) { - Tcl_InitHashTable(&gradient_geom_cache, TCL_STRING_KEYS); - gradient_inited = True; - } - - entry = Tcl_CreateHashEntry(&gradient_geom_cache, grad_geom_str, &new); - if (!new) { - gg = (ZnGradientGeom) Tcl_GetHashValue(entry); - gg->ref_count++; - return gg; - } - - d1 = d2 = 50; - angle = 0; - ptr = grad_geom_str; - if (!*ptr) { - error_gg: - Tcl_AppendResult(interp, "incorrect gradient geometry spec: \"", - grad_geom_str, - "\", should be: [threshold1][-threshold2][/angle]", NULL); - return NULL; - } - if (*ptr != '/') { - d1 = strtol(ptr, &next_ptr, 10); - if (next_ptr == ptr) { - goto error_gg; - } - ptr = next_ptr; - if (*next_ptr == '-') { - ptr++; - d2 = strtol(ptr, &next_ptr, 10); - if (next_ptr == ptr) { - goto error_gg; - } - ptr = next_ptr; - } - } - if (*ptr == '/') { - ptr++; - angle = strtol(ptr, &next_ptr, 10); - if (*next_ptr != 0) { - goto error_gg; - } - ptr = next_ptr; - while (angle < 0) { - angle += 360; - } - while (angle >= 360) { - angle -= 360; - } - } - else if (*next_ptr != 0) { - goto error_gg; - } - gg = (ZnGradientGeom) ZnMalloc(sizeof(ZnGradientGeomStruct)); - gg->d1 = d1; - gg->d2 = d2; - gg->angle = angle; - gg->entry = entry; - gg->ref_count = 1; - Tcl_SetHashValue(entry, (ClientData) gg); - - return gg; -} - - -char * -GradientGeomGetString(ZnGradientGeom gg) -{ - return Tcl_GetHashKey(&gradient_geom_cache, gg->entry); -} - - -void -GradientGeomDelete(ZnGradientGeom gg) -{ - gg->ref_count--; - if (gg->ref_count == 0) { - Tcl_DeleteHashEntry(gg->entry); - ZnFree(gg); - } -} - - -ZnGradientGeom -GradientGeomDuplicate(ZnGradientGeom gg) -{ - gg->ref_count++; - return gg; -} diff --git a/generic/Attrs.h b/generic/Attrs.h index cac2244..85583fd 100644 --- a/generic/Attrs.h +++ b/generic/Attrs.h @@ -126,27 +126,6 @@ LineEndDelete(ZnLineEnd le); char * LineEndGetString(ZnLineEnd le); -/* - * Gradient Geometry. - */ -typedef struct { - int d1; - int d2; - int angle; - Tcl_HashEntry *entry; - int ref_count; -} ZnGradientGeomStruct, *ZnGradientGeom; - -ZnGradientGeom -GradientGeomCreate(Tcl_Interp *interp, - char *grad_geom_str); -ZnGradientGeom -GradientGeomDuplicate(ZnGradientGeom gg); -void -GradientGeomDelete(ZnGradientGeom gg); -char * -GradientGeomGetString(ZnGradientGeom gg); - #ifdef __CPLUSPLUS__ } diff --git a/generic/Color.c b/generic/Color.c index 443a3e6..64707b5 100644 --- a/generic/Color.c +++ b/generic/Color.c @@ -37,6 +37,7 @@ #include +#include #include "Types.h" #include "Image.h" @@ -139,37 +140,19 @@ typedef struct { } ValueKey; -typedef struct _ColorGradient { - Screen *screen; /* Screen on which the gradient will be used. */ - Visual *visual; /* Visual for all windows and pixmaps using - * the gradient. */ - int depth; /* Number of bits per pixel of drawables where - * the gradient will be used. */ - Colormap colormap; /* Colormap out of which pixels are - * allocated. */ - int ref_count; - Tcl_HashEntry *hash; - ZnBool realized; - ZnBool relief; - int num_colors; /* Number of steps in the gradient. */ - XColor *colors[1]; /* Colors of the gradient. */ -} ColorGradient; - - /* * Maximum size of a color name including the \0. */ #define COLOR_NAME_SIZE 128 - /* - * Maximum intensity for a color. + * Maximum size of a gradient name including the \0. */ -#define MAX_INTENSITY 65535 +#define GRADIENT_NAME_SIZE 512 /* - * Number of steps in a border gradient (should be odd). + * Maximum intensity for a color. */ -#define BORDER_STEPS (RELIEF_STEPS*2+1) +#define MAX_INTENSITY 65535 /* * Hash table to map from a gradient's values (color, etc.) to a @@ -779,6 +762,7 @@ ZnFreeColor(XColor *color) /* Color to be released. Must have been * *---------------------------------------------------------------------- */ +#if 0 static void RgbToHsv(int r, int g, @@ -868,29 +852,30 @@ HsvToRgb(ZnReal h, break; } } - +#endif /* *---------------------------------------------------------------------- * - * RealizeColorGradient -- + * ZnRealizeGradient -- * - * This procedure allocate the colors still unallocated in - * a gradient. The first and last colors are always allocated - * during the gradient's creation. For 3D gradients the center - * color is also allocated. - * It's called lazily by ZnColorGradientColor, so that the + * 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. * *---------------------------------------------------------------------- */ -static void -RealizeColorGradient(ColorGradient *grad, - Tk_Window tkwin) +void +ZnRealizeGradient(ZnGradient *grad, + Tk_Window tkwin) { - int i, num_colors, num_colors_2; - XColor *base, *first, *last, color; + int i, j, num_colors, num_shades; + int red_range, green_range, blue_range; + ZnGradientColor *first, *last; + XColor color; if (grad->realized) { return; @@ -899,177 +884,97 @@ RealizeColorGradient(ColorGradient *grad, /*printf("realizing gradient with %d(%d) colors\n", grad->num_colors, BORDER_STEPS);*/ num_colors = grad->num_colors; - num_colors_2 = num_colors/2; - first = grad->colors[0]; - last = grad->colors[num_colors-1]; - - /* - * Fill the in between colors. For a border gradient, this - * is done in two steps, first compute the colors between the - * base and the lightest, then the colors between base and the - * darkest. This ensure that the gradient will go through base. - * For others gradients proceed from lightest to darkest. - */ - if (grad->relief) { -#if 1 - { - int red_range, green_range, blue_range; - - base = grad->colors[BORDER_STEPS/2]; - red_range = (int) base->red - (int) first->red; - green_range = (int) base->green - (int) first->green; - blue_range = (int) base->blue - (int) first->blue; - for (i = BORDER_STEPS/2-1; i > 0; i--) { - color.red = (int) first->red + red_range * i / num_colors_2; - color.green = (int) first->green + green_range * i / num_colors_2; - color.blue = (int) first->blue + blue_range * i / num_colors_2; - grad->colors[i] = ZnGetColorByValue(tkwin, &color); - /*printf("getting color %x %x %x\n", color.red, color.green, color.blue);*/ - } - red_range = (int) last->red - (int) base->red; - green_range = (int) last->green - (int) base->green; - blue_range = (int) last->blue - (int) base->blue; - for (i = BORDER_STEPS/2-1; i > 0; i--) { - color.red = (int) base->red + red_range * i / num_colors_2; - color.green = (int) base->green + green_range * i / num_colors_2; - color.blue = (int) base->blue + blue_range * i / num_colors_2; - /*printf("getting color %x %x %x\n", color.red, color.green, color.blue);*/ - grad->colors[BORDER_STEPS/2+i] = ZnGetColorByValue(tkwin, &color); - } - /*printf("base %x %x %x\n", grad->colors[BORDER_STEPS/2]->red, - grad->colors[BORDER_STEPS/2]->green, grad->colors[BORDER_STEPS/2]->blue); - printf("relief pixels: "); - for (i = 0; i < BORDER_STEPS; i++) { - printf("%d ", ZnPixel(grad->colors[i])); - } - printf("\n");*/ - } -#else - { - ZnReal h1, h2, h3; - ZnReal v1, v2, v3; - ZnReal s1, s2, s3; - ZnReal ds, dv; - - base = grad->colors[BORDER_STEPS/2]; - RgbToHsv(first->red, first->green, first->blue, &h1, &s1, &v1); - RgbToHsv(base->red, base->green, base->blue, &h2, &s2, &v2); - RgbToHsv(last->red, last->green, last->blue, &h3, &s3, &v3); - dv = v2 - v1; - for (i = BORDER_STEPS/2-1; i > 0; i--) { - HsvToRgb(h2, - s2, - v1 + (dv * i / num_colors_2), - &color.red, &color.green, &color.blue); - grad->colors[i] = ZnGetColorByValue(tkwin, &color); - } - ds = s3 - s2; - for (i = BORDER_STEPS/2-1; i > 0; i--) { - HsvToRgb(h2, - s1 - (ds * i / num_colors_2), - v2, - &color.red, &color.green, &color.blue); - grad->colors[BORDER_STEPS/2+i] = ZnGetColorByValue(tkwin, &color); - } - } -#endif - } -#if 1 - else { - int red_range, green_range, blue_range; + 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->red, first->green, first->blue, - last->red, last->green, last->blue);*/ - red_range = (int) last->red - (int) first->red; - green_range = (int) last->green - (int) first->green; - blue_range = (int) last->blue - (int) first->blue; - for (i = 1; i < num_colors-1; i++) { - color.red =(int) first->red + red_range * i / (num_colors-1); - color.green = (int) first->green + green_range * i / (num_colors-1); - color.blue = (int) first->blue + blue_range * i / (num_colors-1); - grad->colors[i] = ZnGetColorByValue(tkwin, &color); - } - } -#else - else { - ZnReal h1, h2, v1, v2, s1, s2, dh, ds, dv; - - RgbToHsv(first->red, first->green, first->blue, &h1, &s1, &v1); - RgbToHsv(last->red, last->green, last->blue, &h2, &s2, &v2); - dh = h2 - h1; - ds = s2 - s1; - dv = v2 - v1; - for (i = 1; i < num_colors-1; i++) { - HsvToRgb(h1 + (dh * i / (num_colors-1)), - s1 + (ds * i / (num_colors-1)), - v1 + (dv * i / (num_colors-1)), - &color.red, &color.green, &color.blue); - grad->colors[i] = ZnGetColorByValue(tkwin, &color); + 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); } } -#endif - grad->realized = True; -} - -/* - *---------------------------------------------------------------------- - * - * ZnColorGradientSpan -- - * - *---------------------------------------------------------------------- - */ -int -ZnColorGradientSpan(ZnColorGradient gradient) -{ - return ((ColorGradient *) gradient)->num_colors; + grad->realized = True; } /* *---------------------------------------------------------------------- * - * ZnColorGradientColor -- + * ZnGetGradientColor -- * *---------------------------------------------------------------------- */ XColor * -ZnColorGradientColor(Tk_Window tkwin, - ZnColorGradient gradient, - int color_index) +ZnGetGradientColor(Tk_Window tkwin, + ZnGradient *grad, + ZnReal position) { - ColorGradient *grad = (ColorGradient *) gradient; + int index, min, max; + ZnGradientColor *color, *next_color; + XColor *shade; + ZnReal tt; + + if (!grad->realized) { + ZnRealizeGradient(grad, tkwin); + } - if (color_index < 0) { - color_index += grad->num_colors; + if (grad->num_colors == 1) { + return grad->colors[0]->shades[0]; } - if (color_index >= grad->num_colors) { - color_index = grad->num_colors-1; + if (position < 0.0) { + shade = grad->colors[0]->shades[0]; } - if (!grad->realized) { - RealizeColorGradient(grad, tkwin); + else if (position >= 100.0) { + shade = grad->colors[grad->num_colors-1]->shades[0]; } - return grad->colors[color_index]; + else { + min = 0; + max = grad->num_colors-1; + index = (max + min) / 2; + while (max - min != 1) { + if (grad->colors[index]->position < position) { + min = index; + } + else { + max = index; + } + index = (max + min) / 2; + } + color = grad->colors[index]; + next_color = grad->colors[index+1]; + tt = ((position - (ZnReal) color->position) / + (ZnReal) ((next_color->position - color->position) / grad->num_shades)); + index = REAL_TO_INT(tt); + shade = color->shades[index]; + } + + return shade; } /* - *---------------------------------------------------------------------- + *-------------------------------------------------------------- * - * ZnColorGradientMidColor -- + * ZnGradientFlat -- * - *---------------------------------------------------------------------- + * Returns true if the gradient is defined by a single + * color. + * + *-------------------------------------------------------------- */ -XColor * -ZnColorGradientMidColor(Tk_Window tkwin, - ZnColorGradient gradient) +ZnBool +ZnGradientFlat(ZnGradient *grad) { - ColorGradient *grad = (ColorGradient *) gradient; - - if (!grad->realized) { - RealizeColorGradient(grad, tkwin); - } - return grad->colors[grad->num_colors/2]; + return (grad->num_colors == 1); } @@ -1090,7 +995,7 @@ ZnColorGradientMidColor(Tk_Window tkwin, * 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 - * ZnColorGradientColor asserts that all the colors + * ZnGetGradientColor asserts that all the colors * get allocated when needed. * If an error prevented the gradient from being created * then NULL is returned and an error message will be @@ -1099,177 +1004,94 @@ ZnColorGradientMidColor(Tk_Window tkwin, * Side effects: * Data structures, etc. are allocated. * It is the caller's responsibility to eventually call - * ZnFreeColorGradient to release the resources. + * ZnFreeGradient to release the resources. * *-------------------------------------------------------------- */ -ZnColorGradient +ZnGradient * ZnGetReliefGradient(Tcl_Interp *interp, Tk_Window tkwin, Tk_Uid name) { - GradientKey key; - Tcl_HashEntry *hash; - ColorGradient *grad; - int i, new; - XColor *base, color; - - if (!initialized) { - ColorInit(); - } + XColor *base, light_color, dark_color; + char color_name[COLOR_NAME_SIZE]; + int tmp1, tmp2; + base = ZnGetColor(interp, tkwin, name); /* - * First, check to see if there's already a gradient that will work - * for this request. + * Compute the border gradient. + * + * Always consider that we are dealing with a color display with + * enough colors available. If the colormap is full (stressed) + * then just pray, the susbstitution algorithm may return something + * adequate ;-). + * + * The extremum colors get computed using whichever formula results + * in the greatest change in color: + * 1. Lighter color is half-way to white, darker color is half + * way to dark. + * 2. Lighter color is 40% brighter than base, darker color + * is 40% darker than base. + * The first approach works better for unsaturated colors, the + * second for saturated ones. + * + * NOTE: Colors are computed with integers not color shorts which + * may lead to overflow errors. */ - name = Tk_GetUid(name); - key.name = name; - key.colormap = Tk_Colormap(tkwin); - key.screen = Tk_Screen(tkwin); + tmp1 = (30 * (int) base->red)/100; + tmp2 = ((int) base->red)/2; + light_color.red = MIN(tmp1, tmp2); + tmp1 = (30 * (int) base->green)/100; + tmp2 = ((int) base->green)/2; + light_color.green = MIN(tmp1, tmp2); + tmp1 = (30 * (int) base->blue)/100; + tmp2 = ((int) base->blue)/2; + light_color.blue = MIN(tmp1, tmp2); - hash = Tcl_CreateHashEntry(&gradient_table, (char *) &key, &new); - if (!new) { - /* printf("GetReliefGradient: Reusing color gradient for %s\n", name);*/ - grad = (ColorGradient *) Tcl_GetHashValue(hash); - grad->ref_count++; + tmp1 = MAX_INTENSITY;/*(170 * (int) base->red)/10;*/ + if (tmp1 > MAX_INTENSITY) { + tmp1 = MAX_INTENSITY; } - else { - /*printf("GetReliefGradient: Creating color gradient for %s\n", name);*/ - /* - * No satisfactory gradient exists yet. Initialize a new one. - */ - base = ZnGetColor(interp, tkwin, name); - if (base == NULL) { - Tcl_AppendResult(interp, " in border gradient", NULL); - Tcl_DeleteHashEntry(hash); - return NULL; - } + tmp2 = (MAX_INTENSITY + (int) base->red)/2; + dark_color.red = MAX(tmp1, tmp2); + tmp1 = MAX_INTENSITY;/*(170 * (int) base->green)/10;*/ + if (tmp1 > MAX_INTENSITY) { + tmp1 = MAX_INTENSITY; + } + tmp2 = (MAX_INTENSITY + (int) base->green)/2; + dark_color.green = MAX(tmp1, tmp2); + tmp1 = MAX_INTENSITY;/*(170 * (int) base->blue)/10;*/ + if (tmp1 > MAX_INTENSITY) { + tmp1 = MAX_INTENSITY; + } + tmp2 = (MAX_INTENSITY + (int) base->blue)/2; + dark_color.blue = MAX(tmp1, tmp2); - grad = (ColorGradient *) ZnMalloc(sizeof(ColorGradient) + - sizeof(XColor *)*(BORDER_STEPS-1)); - grad->screen = Tk_Screen(tkwin); - grad->visual = Tk_Visual(tkwin); - grad->depth = Tk_Depth(tkwin); - grad->colormap = key.colormap; - grad->ref_count = 1; - grad->realized = False; - grad->relief = True; - grad->hash = hash; - grad->num_colors = BORDER_STEPS; - /* - * BORDER_STEPS should be odd, the base color - * takes the center position (assuming that the number - * of colors is odd). - */ - grad->colors[BORDER_STEPS/2] = base; + sprintf(color_name, "#%2d%2d%2d|#%2d%2d%2d|#%2d%2d%2d%%%d", + light_color.red, light_color.green, light_color.blue, + base->red, base->green, base->blue, + dark_color.red, dark_color.green, dark_color.blue, + RELIEF_STEPS); - /* - * Compute the border gradient. - * - * Always consider that we are dealing with a color display with - * enough colors available. If the colormap is full (stressed) - * then just pray, the susbstitution algorithm may return something - * adequate ;-). - * - * The extremum colors get computed using whichever formula results - * in the greatest change in color: - * 1. Lighter color is half-way to white, darker color is half - * way to dark. - * 2. Lighter color is 40% brighter than base, darker color - * is 40% darker than base. - * The first approach works better for unsaturated colors, the - * second for saturated ones. - * - * NOTE: Colors are computed with integers not color shorts which - * may lead to overflow errors. - */ -#if 1 - { - int tmp1, tmp2; - - tmp1 = (30 * (int) base->red)/100; - tmp2 = ((int) base->red)/2; - color.red = MIN(tmp1, tmp2); - tmp1 = (30 * (int) base->green)/100; - tmp2 = ((int) base->green)/2; - color.green = MIN(tmp1, tmp2); - tmp1 = (30 * (int) base->blue)/100; - tmp2 = ((int) base->blue)/2; - color.blue = MIN(tmp1, tmp2); - grad->colors[0] = ZnGetColorByValue(tkwin, &color); - - tmp1 = MAX_INTENSITY;/*(170 * (int) base->red)/10;*/ - if (tmp1 > MAX_INTENSITY) { - tmp1 = MAX_INTENSITY; - } - tmp2 = (MAX_INTENSITY + (int) base->red)/2; - color.red = MAX(tmp1, tmp2); - tmp1 = MAX_INTENSITY;/*(170 * (int) base->green)/10;*/ - if (tmp1 > MAX_INTENSITY) { - tmp1 = MAX_INTENSITY; - } - tmp2 = (MAX_INTENSITY + (int) base->green)/2; - color.green = MAX(tmp1, tmp2); - tmp1 = MAX_INTENSITY;/*(170 * (int) base->blue)/10;*/ - if (tmp1 > MAX_INTENSITY) { - tmp1 = MAX_INTENSITY; - } - tmp2 = (MAX_INTENSITY + (int) base->blue)/2; - color.blue = MAX(tmp1, tmp2); - grad->colors[BORDER_STEPS-1] = ZnGetColorByValue(tkwin, &color); - } -#else - { - ZnReal h, s, v, vmin, smin; - - RgbToHsv(base->red, base->green, base->blue, &h, &s, &v); - vmin = v * 0.3; - smin = s * 0.3; - HsvToRgb(h, s, vmin, &color.red, &color.green, &color.blue); - grad->colors[0] = ZnGetColorByValue(tkwin, &color); - HsvToRgb(h, smin, v, &color.red, &color.green, &color.blue); - grad->colors[BORDER_STEPS-1] = ZnGetColorByValue(tkwin, &color); - } -#endif - - /* - * Now init the in between colors to let RealizeColorGradient know - * what it has to do. - */ - for (i = BORDER_STEPS/2-1; i > 0; i--) { - grad->colors[i] = NULL; - } - for (i = BORDER_STEPS/2+1; i < BORDER_STEPS-1; i++) { - grad->colors[i] = NULL; - } - Tcl_SetHashValue(hash, grad); - } - - /* - * Delay the allocation of colors until they are actually - * needed for drawing. - */ - return (ZnColorGradient) grad; + return ZnGetGradient(interp, tkwin, color_name); } /* *-------------------------------------------------------------- * - * ZnGetColorGradient -- + * ZnGetGradient -- * * Create a data structure containing a range of colors - * used to display a gradient. Name contains the gradient - * description in the form: - * color1[ color2 steps] + * used to display a gradient. * * 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 two end colors in an attempt to use only + * the milestone colors in an attempt to use only * actually needed resources. The function - * ZnColorGradientColor asserts that all the colors + * ZnGetGradientColor asserts that all the colors * get allocated when needed. * If an error prevented the gradient from being created * then NULL is returned and an error message will be @@ -1278,32 +1100,32 @@ ZnGetReliefGradient(Tcl_Interp *interp, * Side effects: * Data structures, etc. are allocated. * It is the caller's responsibility to eventually call - * ZnFreeColorGradient to release the resources. + * ZnFreeGradient to release the resources. * *-------------------------------------------------------------- */ -ZnColorGradient -ZnGetColorGradientByValue(ZnColorGradient gradient) +ZnGradient * +ZnGetGradientByValue(ZnGradient *grad) { - ColorGradient *grad; - - grad = (ColorGradient *) gradient; grad->ref_count++; - return gradient; + return grad; } -ZnColorGradient -ZnGetColorGradient(Tcl_Interp *interp, - Tk_Window tkwin, - Tk_Uid name) +ZnGradient * +ZnGetGradient(Tcl_Interp *interp, + Tk_Window tkwin, + Tk_Uid name) { GradientKey key; Tcl_HashEntry *hash; - ColorGradient *grad; - int i, new, steps, num_tok; - XColor *first, *last; - char name_first[COLOR_NAME_SIZE], name_last[COLOR_NAME_SIZE]; + ZnGradient *grad; + 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]; + char buffer[GRADIENT_NAME_SIZE]; if (!initialized) { ColorInit(); @@ -1320,70 +1142,159 @@ ZnGetColorGradient(Tcl_Interp *interp, hash = Tcl_CreateHashEntry(&gradient_table, (char *) &key, &new); if (!new) { - grad = (ColorGradient *) Tcl_GetHashValue(hash); + grad = (ZnGradient *) Tcl_GetHashValue(hash); grad->ref_count++; } else { /* * No satisfactory gradient exists yet. Initialize a new one. */ - num_tok = sscanf(name, "%s %s %d", name_first, name_last, &steps); - if ((num_tok != 1) && ((num_tok != 3) || (steps < 2))) { - Tcl_AppendResult(interp, "incorrect gradient format \"", - name, "\"", NULL); - grad_err: - Tcl_DeleteHashEntry(hash); - return NULL; + if ((name[0] == '%') || (name[0] == '/') || (name[0] == '(')) { + goto grad_err2; } - first = ZnGetColor(interp, tkwin, Tk_GetUid(name_first)); - if (first == NULL) { - grad_err2: - Tcl_AppendResult(interp, " in gradient", NULL); - goto grad_err; + + strcpy(buffer, name); + /* + * Try to obtain how many shades sould be drawn. + */ + num_shades = DEFAULT_NUM_SHADES; + if ((scan_ptr = strchr(buffer, '%'))) { + sscanf(scan_ptr, "%%%d", &num_shades); + /*printf("num shades = %d\n", num_shades);*/ + *scan_ptr = '\0'; } - if (num_tok != 1) { - last = ZnGetColor(interp, tkwin, Tk_GetUid(name_last)); - if (last == NULL) { - ZnFreeColor(first); - goto grad_err2; + /* + * Keep num_shades even. + */ + num_shades /= 2; + num_shades *= 2; + /* + * Then look at the gradient type. + */ + type = ZN_AXIAL_GRADIENT; + angle = 0; + if ((scan_ptr = strchr(buffer, '/'))) { + num_tok = sscanf(scan_ptr, "/%d", &angle); + if (num_tok != 1) { + grad_err2: + Tcl_DeleteHashEntry(hash); + Tcl_AppendResult(interp, "incorrect gradient format \"", + name, "\",", NULL); + return NULL; } + *scan_ptr = '\0'; } - else { - last = ZnGetColor(interp, tkwin, Tk_GetUid(name_first)); - steps = 2; + else if ((scan_ptr = strchr(buffer, '('))) { + num_tok = sscanf(scan_ptr, "(%d %d", &x, &y); + if (num_tok == 2) { + type = ZN_RADIAL_GRADIENT; + } + else { + goto grad_err2; + } + *scan_ptr = '\0'; } - /* - * Gradients span an odd number of colors. + * Next count the colors. */ - if (steps % 2 == 0) { - steps++; + scan_ptr = buffer; + num_colors = 1; + while ((scan_ptr = strchr(scan_ptr, '|'))) { + num_colors++; + scan_ptr++; } - - grad = (ColorGradient *) ZnMalloc(sizeof(ColorGradient) + - sizeof(XColor *)*(steps-1)); + /* + * 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; grad->ref_count = 1; - grad->colors[0] = first; - grad->colors[steps-1] = last; - for (i = 1; i < steps-1; i++) { - grad->colors[i] = NULL; + grad->num_shades = num_shades; + grad->num_colors = num_colors; + grad->type = type; + if (type == ZN_AXIAL_GRADIENT) { + grad->g.angle = angle; + } + else { + grad->g.c.x = x; + grad->g.c.y = y; } - grad->num_colors = steps; grad->realized = False; - grad->relief = False; grad->hash = hash; Tcl_SetHashValue(hash, grad); + + 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)); + } + 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 \"", + name, "\",", NULL); + grad_err: + Tcl_DeleteHashEntry(hash); + for (j = i; j >= 0; j--) { + ZnFree(grad->colors[j]); + } + ZnFree(grad); + return NULL; + } + grad->colors[i]->shades[0] = ZnGetColor(interp, tkwin, Tk_GetUid(color_name)); + if (grad->colors[i]->shades[0] == NULL) { + Tcl_AppendResult(interp, " in gradient,", NULL); + goto grad_err; + } + if (i != num_colors - 1) { + for (j = 1; j < num_shades-1; j++) { + grad->colors[i]->shades[j] = NULL; + } + } + if (i == 0) { + grad->colors[i]->position = 0; + } + 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 ((grad->colors[i]->position > 100) || + (grad->colors[i]->position < 0) || + (grad->colors[i]->position < grad->colors[i-1]->position)) { + Tcl_AppendResult(interp, "incorrect color position in gradient \"", + name, "\",", NULL); + goto grad_err; + } + } + if (num_tok != 3) { + grad->colors[i]->control = 50; + } + 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; + } + scan_ptr = strtok(NULL, "|"); + } } /* * Delay the allocation of colors until they are actually * needed for drawing. */ - return (ZnColorGradient) grad; + return grad; } @@ -1393,9 +1304,7 @@ ZnGetColorGradient(Tcl_Interp *interp, * ZnNameOfColorGradient -- * * Given a gradient, return a textual string identifying - * the gradient. This can be either a single color (for - * gradients allocated by ZnGetReliefGradient) or a - * full gradient spec: color1:color2:steps. + * the gradient. * * Results: * The return value is the string that was used to create @@ -1407,10 +1316,8 @@ ZnGetColorGradient(Tcl_Interp *interp, *-------------------------------------------------------------- */ char * -ZnNameOfColorGradient(ZnColorGradient gradient) +ZnNameOfGradient(ZnGradient *grad) { - ColorGradient *grad = (ColorGradient *) gradient; - return ((GradientKey *) grad->hash->key.words)->name; } @@ -1418,7 +1325,7 @@ ZnNameOfColorGradient(ZnColorGradient gradient) /* *-------------------------------------------------------------- * - * ZnFreeColorGradient -- + * ZnFreeGradient -- * * This procedure is called when a gradient is no longer * needed. It frees the resources associated with the @@ -1434,19 +1341,23 @@ ZnNameOfColorGradient(ZnColorGradient gradient) *-------------------------------------------------------------- */ void -ZnFreeColorGradient(ZnColorGradient gradient) +ZnFreeGradient(ZnGradient *grad) { - ColorGradient *grad = (ColorGradient *) gradient; - int i; + int i, j; grad->ref_count--; if (grad->ref_count == 0) { - for (i = 0; i < grad->num_colors; i++) { - if (grad->colors[i] != NULL) { - ZnFreeColor(grad->colors[i]); + 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]); + } } + ZnFree(grad->colors[i]); } - Tcl_DeleteHashEntry(grad->hash); + ZnFreeColor(grad->colors[grad->num_colors-1]->shades[0]); + ZnFree(grad->colors[grad->num_colors-1]); ZnFree(grad); } } diff --git a/generic/Color.h b/generic/Color.h index 140c2ea..c7ac91e 100644 --- a/generic/Color.h +++ b/generic/Color.h @@ -34,24 +34,57 @@ #include "Types.h" -typedef struct _ColorGradient *ZnColorGradient; +typedef struct _GradientColor { + int position; /* Color starting position along the gradient axis. + * This is in percent of the gradient total size. */ + int control; /* Middle-shade position in percent of this color + * size along the gradient axis. */ + XColor *shades[1]; /* The real shades used to draw this color segment. + * The number of shades is constant for all the colors + * of a given gradient and is setup in num_shades. */ +} ZnGradientColor; + +typedef struct _Gradient { + Screen *screen; /* Screen on which the gradient will be used. */ + Visual *visual; /* Visual for all windows and pixmaps using + * the gradient. */ + int depth; /* Number of bits per pixel of drawables where + * the gradient will be used. */ + Colormap colormap; /* Colormap out of which pixels are allocated. */ + int ref_count; + Tcl_HashEntry *hash; + ZnBool realized; + char type; /* Either ZN_AXIAL_GRADIENT (lines) or + * ZN_RADIAL_GRADIENT (circles). */ + union { + int angle; /* Angle spec for an axial gradient (Degrees). */ + struct { + int x; /* Center for a radial gradiant (percent of */ + int y; /* area size). */ + } c; + } g; + int num_shades; /* Number of shades used for each color */ + int num_colors; /* Number of colors in gradient spec. */ + ZnGradientColor *colors[1]; +} ZnGradient; + XColor *ZnGetColor(Tcl_Interp *interp, Tk_Window tkwin, Tk_Uid name); XColor *ZnGetColorByValue(Tk_Window tkwin, XColor *color); char *ZnNameOfColor(XColor *color); void ZnFreeColor(XColor *color); -ZnColorGradient ZnGetColorGradient(Tcl_Interp *interp, Tk_Window tkwin, - Tk_Uid name); -ZnColorGradient ZnGetColorGradientByValue(ZnColorGradient gradient); -ZnColorGradient ZnGetReliefGradient(Tcl_Interp *interp, Tk_Window tkwin, - Tk_Uid name); -int ZnColorGradientSpan(ZnColorGradient); -XColor *ZnColorGradientColor(Tk_Window tkwin, ZnColorGradient gradient, - int color_index); -XColor *ZnColorGradientMidColor(Tk_Window tkwin, ZnColorGradient gradient); -char *ZnNameOfColorGradient(ZnColorGradient gradient); -void ZnFreeColorGradient(ZnColorGradient gradient); +ZnGradient *ZnGetGradient(Tcl_Interp *interp, Tk_Window tkwin, + Tk_Uid name); +ZnGradient *ZnGetGradientByValue(ZnGradient *gradient); +ZnGradient *ZnGetReliefGradient(Tcl_Interp *interp, Tk_Window tkwin, + Tk_Uid name); +ZnBool ZnGradientFlat(ZnGradient *grad); +XColor *ZnGetGradientColor(Tk_Window tkwin, ZnGradient *gradient, + ZnReal position); +char *ZnNameOfGradient(ZnGradient *gradient); +void ZnFreeGradient(ZnGradient *gradient); +void ZnRealizeGradient(ZnGradient *grad, Tk_Window tkwin); #endif /* _Color_h */ diff --git a/generic/Curve.c b/generic/Curve.c index 8bda064..48b64ba 100644 --- a/generic/Curve.c +++ b/generic/Curve.c @@ -83,8 +83,7 @@ typedef struct _CurveItemStruct { ReliefStyle relief; int line_width; /* If 0 the path is not drawn, if <2 relief is flat */ Pixmap fill_pattern; - ZnColorGradient fill_color; - ZnGradientGeom grad_geom; + ZnGradient *fill_color; Pixmap line_pattern; ZnColor line_color; ZnColor marker_color; @@ -95,7 +94,7 @@ typedef struct _CurveItemStruct { /* Private data */ ZnImage tile; ZnPoly dev_shape; - ZnColorGradient gradient; + ZnGradient *gradient; #ifdef LIBART ArtSVP *outline_svp; ArtSVP *fill_svp; @@ -119,7 +118,7 @@ static ZnAttrConfig cv_attrs[] = { ZN_COORDS_FLAG, False }, { ZN_CONFIG_UINT, "-fillalpha", NULL, Tk_Offset(CurveItemStruct, fill_alpha), 0, ZN_DRAW_FLAG, False }, - { ZN_CONFIG_GRADIENT_COLOR, "-fillcolor", NULL, + { ZN_CONFIG_GRADIENT, "-fillcolor", NULL, Tk_Offset(CurveItemStruct, fill_color), 0, ZN_DRAW_FLAG|ZN_BORDER_FLAG, False }, { ZN_CONFIG_PATTERN, "-fillpattern", NULL, @@ -128,8 +127,6 @@ static ZnAttrConfig cv_attrs[] = { Tk_Offset(CurveItemStruct, flags), FILLED_BIT, ZN_COORDS_FLAG, False }, { ZN_CONFIG_LINE_END, "-firstend", NULL, Tk_Offset(CurveItemStruct, first_end), 0, ZN_COORDS_FLAG, False }, - { ZN_CONFIG_GRADIENT_GEOM, "-gradient", NULL, - Tk_Offset(CurveItemStruct, grad_geom), 0, ZN_DRAW_FLAG, False }, { ZN_CONFIG_JOIN_STYLE, "-joinstyle", NULL, Tk_Offset(CurveItemStruct, join_style), 0, ZN_COORDS_FLAG, False }, @@ -282,12 +279,11 @@ Init(Item item, SET(cv->flags, MARKED_BIT); cv->marker = ZnUnspecifiedPattern; cv->fill_alpha = 255; - cv->fill_color = ZnGetColorGradient(wi->interp, wi->win, - ZnNameOfColor(wi->fore_color)); + cv->fill_color = ZnGetGradient(wi->interp, wi->win, + ZnNameOfColor(wi->fore_color)); cv->line_alpha = 255; cv->line_color = ZnGetColorByValue(wi->win, wi->fore_color); cv->marker_color = ZnGetColorByValue(wi->win, wi->fore_color); - cv->grad_geom = NULL; #ifdef LIBART cv->outline_svp = cv->fill_svp = NULL; #endif @@ -336,7 +332,7 @@ Clone(Item item) } if (cv->gradient) { - cv->gradient = ZnGetColorGradientByValue(cv->gradient); + cv->gradient = ZnGetGradientByValue(cv->gradient); } if (cv->line_pattern != ZnUnspecifiedPattern) { cv->line_pattern = Tk_GetBitmap(wi->interp, wi->win, @@ -364,11 +360,8 @@ Clone(Item item) Tk_NameOfBitmap(wi->dpy, cv->marker)); } cv->line_color = ZnGetColorByValue(wi->win, cv->line_color); - cv->fill_color = ZnGetColorGradientByValue(cv->fill_color); + cv->fill_color = ZnGetGradientByValue(cv->fill_color); cv->marker_color = ZnGetColorByValue(wi->win, cv->marker_color); - if (cv->grad_geom) { - cv->grad_geom = GradientGeomDuplicate(cv->grad_geom); - } #ifdef LIBART cv->outline_svp = cv->fill_svp = NULL; #endif @@ -399,7 +392,7 @@ Destroy(Item item) LineEndDelete(cv->last_end); } if (cv->gradient) { - ZnFreeColorGradient(cv->gradient); + ZnFreeGradient(cv->gradient); } if (cv->tile != ZnUnspecifiedImage) { Tk_FreeImage(cv->tile); @@ -417,12 +410,9 @@ Destroy(Item item) if (cv->marker != ZnUnspecifiedPattern) { Tk_FreeBitmap(wi->dpy, cv->marker); } - ZnFreeColorGradient(cv->fill_color); + ZnFreeGradient(cv->fill_color); ZnFreeColor(cv->line_color); ZnFreeColor(cv->marker_color); - if (cv->grad_geom) { - GradientGeomDelete(cv->grad_geom); - } #ifdef GPC if (cv->tristrip.num_strips) { gpc_free_tristrip(&cv->tristrip); @@ -499,12 +489,12 @@ Configure(Item item, if (cv->gradient && (ISSET(*flags, ZN_BORDER_FLAG) || (cv->relief == RELIEF_FLAT))) { - ZnFreeColorGradient(cv->gradient); + ZnFreeGradient(cv->gradient); cv->gradient = NULL; } if ((cv->relief != RELIEF_FLAT) && !cv->gradient) { cv->gradient = ZnGetReliefGradient(wi->interp, wi->win, - ZnNameOfColor(ZnColorGradientMidColor(wi->win, cv->fill_color))); + ZnNameOfColor(ZnGetGradientColor(wi->win, cv->fill_color, 50.0))); } if (ISSET(*flags, ZN_TILE_FLAG)) { Tk_Image tile; @@ -1051,12 +1041,12 @@ Draw(Item item) * Fill if requested. */ if (ISSET(cv->flags, FILLED_OK)) { - if (cv->grad_geom) { - DrawPolygonGradient(wi, cv->grad_geom, cv->fill_color, &cv->dev_shape, + if (!ZnGradientFlat(cv->fill_color)) { + DrawPolygonGradient(wi, cv->fill_color, &cv->dev_shape, &item->item_bounding_box); } else { - values.foreground = ZnPixel(ZnColorGradientMidColor(wi->win, cv->fill_color)); + values.foreground = ZnPixel(ZnGetGradientColor(wi->win, cv->fill_color, 50.0)); gc_mask = GCFillStyle; if (cv->tile != ZnUnspecifiedImage) { /* Fill tiled */ Pixmap pmap = GetImagePixmap(wi->win, cv->tile_name, cv->tile, NULL); @@ -1267,7 +1257,7 @@ Render(Item item) #ifdef LIBART WidgetInfo *wi = item->wi; CurveItem cv = (CurveItem) item; - XColor *color = ZnColorGradientMidColor(wi->win, cv->fill_color); + XColor *color = ZnGetGradientColor(wi->win, cv->fill_color, 50.0); ArtPixBuf *pixbuf = NULL; if (cv->fill_svp != NULL) { diff --git a/generic/Draw.c b/generic/Draw.c index c77d59e..ce48b3d 100644 --- a/generic/Draw.c +++ b/generic/Draw.c @@ -317,14 +317,14 @@ ReliefColorOfSegment(ZnReal x1, ZnReal x2, ZnReal y2, ReliefStyle relief, - ZnColorGradient gradient, + ZnGradient *gradient, WidgetInfo *wi) { - ZnReal angle, angle_step, origin; - int color_index, num_colors; + ZnReal angle, angle_step, origin, position; + int num_colors; - num_colors = ZnColorGradientSpan(gradient); - angle_step = M_PI / (num_colors-1); + num_colors = RELIEF_STEPS*2+1; + angle_step = 2*M_PI / num_colors; origin = -(DegreesToRadian(wi->light_angle))-(angle_step/2.0); if (relief == RELIEF_BEVEL_IN) { origin += M_PI; @@ -337,25 +337,13 @@ ReliefColorOfSegment(ZnReal x1, while (angle > 2*M_PI) { angle -= 2*M_PI; } - color_index = (int) (angle/angle_step); - if (color_index > num_colors-1) { - color_index = 2*(num_colors-1)-color_index; - } - if ((color_index < 0) || (color_index >= num_colors)) { - printf("Color index out of gradient (should not happen).\n"); - if (color_index < 0) { - color_index = 0; - } - if (color_index >= num_colors) { - color_index = num_colors-1; - } - } - /*printf("color index %d(), angle %g(), origin %g\n", - color_index, + position = (angle/angle_step)*(100/num_colors); + /*printf("position %g, angle %g, origin %g\n", + position, RadianToDegrees(angle), RadianToDegrees(origin));*/ - return ZnPixel(ZnColorGradientColor(wi->win, gradient, color_index)); + return ZnPixel(ZnGetGradientColor(wi->win, gradient, position)); } @@ -370,7 +358,7 @@ ReliefColorOfSegment(ZnReal x1, void DrawRectangleRelief(WidgetInfo *wi, ReliefStyle relief, - ZnColorGradient gradient, + ZnGradient *gradient, XRectangle *bbox, unsigned int line_width) { @@ -468,7 +456,7 @@ DoPolygonRelief(ZnPoint *p, ZnBool folded, closed, colinear; WidgetInfo *wi = NULL; ReliefStyle relief = 0; - ZnColorGradient gradient = NULL; + ZnGradient *gradient = NULL; ZnPoint *pp = NULL; double *dist = NULL; ZnBBox *bbox = NULL; @@ -495,7 +483,7 @@ DoPolygonRelief(ZnPoint *p, else if (what_to_do == POLYGON_RELIEF_DRAW) { wi = va_arg(var, WidgetInfo *); relief = va_arg(var, int); - gradient = va_arg(var, ZnColorGradient); + gradient = va_arg(var, ZnGradient *); } va_end(var); @@ -798,12 +786,12 @@ PolygonReliefToPointDist(ZnPoint *points, ********************************************************************************** */ void -DrawPolygonRelief(WidgetInfo *wi, - ReliefStyle relief, - ZnColorGradient gradient, - ZnPoint *points, - int num_points, - int line_width) +DrawPolygonRelief(WidgetInfo *wi, + ReliefStyle relief, + ZnGradient *gradient, + ZnPoint *points, + int num_points, + int line_width) { /* * Grooves and ridges are drawn with two calls. The first @@ -823,10 +811,161 @@ DrawPolygonRelief(WidgetInfo *wi, } } +static void +DrawRadialGradient(struct _WidgetInfo *wi, + ZnGradient *grad, + XRectangle *bbox) +{ +} + +static void +DrawAxialGradient(struct _WidgetInfo *wi, + ZnGradient *grad, + XRectangle *bbox) +{ +#define NUM_STENCILS 8 + static int s[NUM_STENCILS] = { 0, 1, 3, 5, 7, 9, 11, 13 }; + int angle = grad->g.angle; + int num_shades = grad->num_shades; + int num_shades_2 = num_shades /2; + int num_colors = grad->num_colors; + int x, y, span, stop, i, j, k, p; + int *startp, *widthp, width, height; + int position; + ZnReal pos, pos_span_bc, pos_span_ac, pos_span; + ZnReal stencil_step_bc, stencil_step_ac, stencil_step; + short origin, limit; + ZnBool dir; + ZnGradientColor *color, *next_color; + XColor *shade; + + /* + * We can only handle 0, 90, 180, 270. + */ + angle = (angle / 90) * 90; + + x = bbox->x; + y = bbox->y; + if ((angle == 0) || (angle == 180)) { + startp = &x; + origin = bbox->x; + limit = bbox->x+bbox->width; + height = bbox->height; + widthp = &width; + } + else { + startp = &y; + origin = bbox->y; + limit = bbox->y+bbox->height; + width = bbox->width; + widthp = &height; + } + + dir = True; + if ((angle == 180) || (angle == 270)) { + dir = False; + } + + span = limit - origin; + + /* + * External loop iterates over the gradient colors. + */ + XSetTSOrigin(wi->dpy, wi->gc, bbox->x, bbox->y); + ZnRealizeGradient(grad, wi->win); + if (dir) { + *startp = origin; + } + else { + stop = limit; + } + for (k = 0; k < num_colors-1; k++) { + /* + * Mid loop iterates over the current color shades. + */ + color = grad->colors[k]; + next_color = grad->colors[k+1]; + position = color->position; + pos_span_bc = (next_color->position - position)*color->control/100.0; + pos_span_ac = (next_color->position - position)-pos_span_bc; + stencil_step_bc = pos_span_bc/(num_shades_2*NUM_STENCILS); + stencil_step_ac = pos_span_ac/(num_shades_2*NUM_STENCILS); + /*printf("span bc %g, span ac %g, stencil bc %g, stencil ac %g\n", + pos_span_bc, pos_span_ac, stencil_step_bc, stencil_step_ac);*/ + pos_span = pos_span_bc; + stencil_step = stencil_step_bc; + pos = position; + for (j = 0; j < num_shades; j++) { + p = j+1; + if (j >= num_shades_2) { + pos = position + pos_span_bc; + pos_span = pos_span_ac; + stencil_step = stencil_step_ac; + p -= num_shades_2; + } + if (dir) { + stop = origin + span*(pos + (pos_span*p/(num_shades_2)))/100; + } + else { + *startp = limit - span*(pos + (pos_span*p/(num_shades_2)))/100; + } + *widthp = stop - *startp; + XSetFillStyle(wi->dpy, wi->gc, FillSolid); + shade = color->shades[j]; + XSetForeground(wi->dpy, wi->gc, ZnPixel(shade)); + XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc, x, y, width, height); +#if 1 + /* + * Inner loop iterates over the stencils used to + * smooth the current shade. + */ + p--; + if (dir) { + *startp = origin + span*(pos + (stencil_step*(p*NUM_STENCILS+1)))/100; + } + else { + stop = limit - span*(pos + (stencil_step*(p*NUM_STENCILS+1)))/100; + } + XSetFillStyle(wi->dpy, wi->gc, FillStippled); + if (j < num_shades-1) { + shade = color->shades[j+1]; + } + else { + shade = next_color->shades[0]; + } + XSetForeground(wi->dpy, wi->gc, ZnPixel(shade)); + for (i = 1; i < NUM_STENCILS; i++) { + if (dir) { + stop = origin + span*(pos + (stencil_step*(p*NUM_STENCILS+i+1)))/100; + } + else { + *startp = limit - span*(pos + (stencil_step*(p*NUM_STENCILS+i+1)))/100; + } + *widthp = stop - *startp; + XSetStipple(wi->dpy, wi->gc, wi->alpha_stipples[s[i]]); + XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc, x, y, width, height); + if (dir) { + *startp = stop; + } + else { + stop = *startp; + } + } +#else + if (dir) { + *startp = stop; + } + else { + stop = *startp; + } +#endif + } + } +} + void DrawPolygonGradient(struct _WidgetInfo *wi, - ZnGradientGeom grad_geom, - ZnColorGradient grad_color, + ZnGradient *gradient, ZnPoly *poly, ZnBBox *bbox) { @@ -842,162 +981,42 @@ DrawPolygonGradient(struct _WidgetInfo *wi, ResetBBox(&lbbox); for (i = 0; i < poly->num_contours; i++) { if (!poly->holes[i]) { - AddPointsToBBox(&lbbox, poly->contours[i].points, poly->contours[i].num_points); + AddPointsToBBox(&lbbox, poly->contours[i].points, + poly->contours[i].num_points); } } bbox = &lbbox; } BBox2XRect(bbox, &r); ITEM_P.PushClip(wi, poly, False, True); - DrawRectangleGradient(wi, grad_geom, grad_color, &r); + if (gradient->type == ZN_AXIAL_GRADIENT) { + DrawAxialGradient(wi, gradient, &r); + } + else if (gradient->type == ZN_RADIAL_GRADIENT) { + DrawRadialGradient(wi, gradient, &r); + } ITEM_P.PopClip(wi, True); } void DrawRectangleGradient(struct _WidgetInfo *wi, - ZnGradientGeom grad_geom, - ZnColorGradient grad_color, + ZnGradient *grad, XRectangle *bbox) { - static int s[] = { 0, 13, 11, 9, 7, 5, 3, 1 }; - int steps = ZnColorGradientSpan(grad_color); - ZnReal d1, d2; - int angle = grad_geom->angle; - int x, y, c, y_d2, w, h, i, j; - int *optr, *hptr; - short yorig, ycorner; - ZnBool dir; - XColor *col; - - /* - * We can only hangle 0, 90, 180, 270. - */ - angle = (angle / 90) * 90; - - x = bbox->x; - y = bbox->y; - if ((angle == 90) || (angle == 270)) { - optr = &x; - yorig = bbox->x; - ycorner = bbox->x+bbox->width; - h = bbox->height; - hptr = &w; - d1 = grad_geom->d1*bbox->width/100; - d2 = grad_geom->d2*bbox->width/100; - } - else { - optr = &y; - yorig = bbox->y; - ycorner = bbox->y+bbox->height; - w = bbox->width; - hptr = &h; - d1 = grad_geom->d1*bbox->height/100.0; - d2 = bbox->height*(1.0-grad_geom->d2/100.0); - } - d1 = REAL_TO_INT(d1); - d2 = REAL_TO_INT(d2); - - dir = True; - if ((angle == 180) || (angle == 270)) { - dir = False; + if (grad->type == ZN_AXIAL_GRADIENT) { + DrawAxialGradient(wi, grad, bbox); } -#if 0 - XSetFillStyle(wi->dpy, wi->gc, FillSolid); - c = ycorner; - for (i = 2, j = steps-1; i < steps; i += 2, j--) { - *optr = REAL_TO_INT(ycorner - (i * d2 / steps)); - *hptr = c - *optr; - XSetForeground(wi->dpy, wi->gc, - ZnPixel(ZnColorGradientColor(wi->win, grad_color, - dir?j:steps-1-j))); - XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc, x, y, w, h); - c = *optr; - } - y_d2 = *optr; - - *optr = yorig; - for (i = 2, j = 0; i < steps; i += 2, j++) { - c = REAL_TO_INT(yorig + (i * d1 / steps)); - *hptr = c - *optr; - XSetForeground(wi->dpy, wi->gc, - ZnPixel(ZnColorGradientColor(wi->win, grad_color, dir?j:steps-1-j))); - XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc, x, y, w, h); - *optr = c; + else if (grad->type == ZN_RADIAL_GRADIENT) { + ZnPoly poly; + ZnPoint points[2]; + + points[0].x = bbox->x; + points[0].y = bbox->y; + points[1].x = bbox->x + bbox->width; + points[1].y = bbox->x + bbox->height; + POLY_CONTOUR1(&poly, points, 2); + ITEM_P.PushClip(wi, &poly, False, True); + DrawRadialGradient(wi, grad, bbox); + ITEM_P.PopClip(wi, True); } - - XSetForeground(wi->dpy, wi->gc, - ZnPixel(ZnColorGradientMidColor(wi->win, grad_color))); - *hptr = y_d2 - *optr; - XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc, x, y, w, h); -#endif - /* - * Draw over with a 50% gray pattern to smooth the color - * waves. - */ -#if 1 - /* - * First draw the from the gradient end. - */ - XSetTSOrigin(wi->dpy, wi->gc, bbox->x, bbox->y); - c = ycorner; - for (i = 0, j = steps-1; i < ((steps-1) * 4); i++) { - *optr = REAL_TO_INT(ycorner - ((i + 1) * d2 / (steps * 4))); - *hptr = c - *optr; - XSetFillStyle(wi->dpy, wi->gc, FillSolid); - col = ZnColorGradientColor(wi->win, grad_color, dir?j:steps-1-j); - XSetForeground(wi->dpy, wi->gc, ZnPixel(col)); - XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc, x, y, w, h); - if (i % 8) { - XSetFillStyle(wi->dpy, wi->gc, FillStippled); - XSetStipple(wi->dpy, wi->gc, wi->alpha_stipples[s[i%8]]); - XSetForeground(wi->dpy, wi->gc, - ZnPixel(ZnColorGradientColor(wi->win, grad_color, - dir?j+1:steps-j))); - XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc, x, y, w, h); - } - else { - /*printf("remplissage en %d %d %d (%d)\n", - col->red, col->green, col->blue, dir?j:steps-1-j);*/ - j--; - } - c = *optr; - } - y_d2 = *optr; - /* - * Then draw from the gradient start. - */ -#if 1 - *optr = yorig; - for (i = 0, j = 0; i < ((steps-1) * 4); i++) { - c = REAL_TO_INT(yorig + ((i + 1) * d1 / (steps * 4))); - *hptr = c - *optr; - XSetFillStyle(wi->dpy, wi->gc, FillSolid); - col = ZnColorGradientColor(wi->win, grad_color, dir?j:steps-1-j); - XSetForeground(wi->dpy, wi->gc, ZnPixel(col)); - XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc, x, y, w, h); - if (i % 8) { - XSetFillStyle(wi->dpy, wi->gc, FillStippled); - XSetStipple(wi->dpy, wi->gc, wi->alpha_stipples[s[i%8]]); - XSetForeground(wi->dpy, wi->gc, - ZnPixel(ZnColorGradientColor(wi->win, grad_color, - dir?j-1:steps-2-j))); - XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc, x, y, w, h); - } - else { - /*printf("remplissage en %d %d %d (%d)\n", - col->red, col->green, col->blue, dir?j:steps-1-j);*/ - j++; - } - *optr = c; - } -#endif - /* - * Last draw the central part. - */ - *hptr = y_d2 - *optr; - XSetFillStyle(wi->dpy, wi->gc, FillSolid); - XSetForeground(wi->dpy, wi->gc, - ZnPixel(ZnColorGradientMidColor(wi->win, grad_color))); - XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc, x, y, w, h); -#endif } diff --git a/generic/Draw.h b/generic/Draw.h index 81ddc95..99e1b48 100644 --- a/generic/Draw.h +++ b/generic/Draw.h @@ -61,15 +61,15 @@ void GetPolygonReliefBBox(ZnPoint *points, int num_points, int line_width, double PolygonReliefToPointDist(ZnPoint *points, int num_points, int line_width, ZnPoint *pp); void DrawRectangleRelief(struct _WidgetInfo *wi, - ReliefStyle relief, ZnColorGradient gradient, + ReliefStyle relief, ZnGradient *gradient, XRectangle *bbox, unsigned int line_width); void DrawPolygonRelief(struct _WidgetInfo *wi, ReliefStyle relief, - ZnColorGradient gradient, ZnPoint *points, + ZnGradient *gradient, ZnPoint *points, int num_points, int line_width); -void DrawRectangleGradient(struct _WidgetInfo *wi, ZnGradientGeom grad_geom, - ZnColorGradient grad_color, XRectangle *bbox); -void DrawPolygonGradient(struct _WidgetInfo *wi, ZnGradientGeom grad_geom, - ZnColorGradient grad_color, ZnPoly *poly, ZnBBox *bbox); +void DrawRectangleGradient(struct _WidgetInfo *wi, ZnGradient *gradient, + XRectangle *bbox); +void DrawPolygonGradient(struct _WidgetInfo *wi, ZnGradient *gradient, + ZnPoly *poly, ZnBBox *bbox); #endif /* _Draw_h */ diff --git a/generic/Item.c b/generic/Item.c index 2e8050a..752e330 100644 --- a/generic/Item.c +++ b/generic/Item.c @@ -87,7 +87,7 @@ typedef struct _FieldStruct { /* Private data */ ZnImage image; ZnImage tile; - ZnColorGradient gradient; + ZnGradient *gradient; short orig_x; short orig_y; short corner_x; @@ -178,8 +178,7 @@ static char *attribute_type_strings[] = { "leaderanchors", "joinstyle", "capstyle", - "gradientgeometry", - "gradientcolor", + "gradient", "window" }; @@ -394,26 +393,26 @@ ConfigureAttributes(char *record, } break; } - case ZN_CONFIG_GRADIENT_COLOR: + case ZN_CONFIG_GRADIENT: { - ZnColorGradient cg; + ZnGradient *g; Tk_Uid new_name = Tk_GetUid(Tcl_GetString(args[i+1])); char *name = NULL; - if (*((ZnColorGradient *) valp)) { - name = ZnNameOfColorGradient(*((ZnColorGradient *) valp)); + if (*((ZnGradient **) valp)) { + name = ZnNameOfGradient(*((ZnGradient **) valp)); } if (name != new_name) { - cg = ZnGetColorGradient(wi->interp, wi->win, new_name); - if (!cg) { + g = ZnGetGradient(wi->interp, wi->win, new_name); + if (!g) { Tcl_AppendResult(wi->interp, - " color gradient expected for attribute \"", + " gradient expected for attribute \"", Tcl_GetString(args[i]), "\"", NULL); return ZN_ERROR; } - if (*((ZnColorGradient *) valp)) { - ZnFreeColorGradient(*((ZnColorGradient *) valp)); + if (*((ZnGradient **) valp)) { + ZnFreeGradient(*((ZnGradient **) valp)); } - *((ZnColorGradient *) valp) = cg; + *((ZnGradient **) valp) = g; *flags |= desc->flags; } break; @@ -716,29 +715,6 @@ ConfigureAttributes(char *record, } break; } - case ZN_CONFIG_GRADIENT_GEOM: - { - ZnGradientGeom gg = NULL; - str = Tcl_GetString(args[i+1]); - if (strlen(str) != 0) { - gg = GradientGeomCreate(wi->interp, str); - if (gg == NULL) { - return ZN_ERROR; - } - } - if (*((ZnGradientGeom *) valp) != NULL) { - GradientGeomDelete(*((ZnGradientGeom *) valp)); - *((ZnGradientGeom *) valp) = gg; - *flags |= desc->flags; - } - else { - if (gg != NULL) { - *((ZnGradientGeom *) valp) = gg; - *flags |= desc->flags; - } - } - break; - } case ZN_CONFIG_RELIEF: { int relief; @@ -1210,6 +1186,12 @@ AttributeToObj(WidgetInfo *wi, Tcl_SetStringObj(result, str, strlen(str)); } break; + case ZN_CONFIG_GRADIENT: + if (*((ZnGradient **) valp)) { + str = ZnNameOfGradient(*((ZnGradient **) valp)); + Tcl_SetStringObj(result, str, strlen(str)); + } + break; case ZN_CONFIG_BOOL: Tcl_SetBooleanObj(result, ISSET(*((char *) valp), desc->bool_bit)?1:0); break; @@ -1375,16 +1357,6 @@ AttributeToObj(WidgetInfo *wi, } break; } - case ZN_CONFIG_GRADIENT_GEOM: - { - ZnGradientGeom gg = *((ZnGradientGeom *) valp); - - if (gg) { - str = GradientGeomGetString(gg); - Tcl_SetStringObj(result, str, strlen(str)); - } - break; - } case ZN_CONFIG_RELIEF: str = Tk_NameOfRelief(*((ReliefStyle *) valp)); Tcl_SetStringObj(result, str, strlen(str)); @@ -3716,7 +3688,7 @@ CloneFields(FieldSet field_set) for (i = 0; i < num_fields; i++) { field = &fields_ret[i]; if (field->gradient) { - field->gradient = ZnGetColorGradientByValue(field->gradient); + field->gradient = ZnGetGradientByValue(field->gradient); } if (strlen(field->image_name) != 0) { @@ -3789,7 +3761,7 @@ ConfigureField(FieldSet field_set, if (field_ptr->gradient && (ISSET(*flags, ZN_BORDER_FLAG) || (field_ptr->relief == RELIEF_FLAT))) { - ZnFreeColorGradient(field_ptr->gradient); + ZnFreeGradient(field_ptr->gradient); field_ptr->gradient = NULL; } if ((field_ptr->relief != RELIEF_FLAT) && !field_ptr->gradient) { @@ -3912,7 +3884,7 @@ FreeFields(FieldSet field_set) ZnFree(field->text); } if (field->gradient) { - ZnFreeColorGradient(field->gradient); + ZnFreeGradient(field->gradient); } if (field->image != ZnUnspecifiedImage) { Tk_FreeImage(field->image); diff --git a/generic/Rectangle.c b/generic/Rectangle.c index 2779e80..a9989a2 100644 --- a/generic/Rectangle.c +++ b/generic/Rectangle.c @@ -68,8 +68,7 @@ typedef struct _RectangleItemStruct { ZnColor line_color; Pixmap fill_pattern; Pixmap line_pattern; - ZnColorGradient fill_color; - ZnGradientGeom grad_geom; + ZnGradient *fill_color; int line_alpha; int fill_alpha; char *tile_name; @@ -77,7 +76,7 @@ typedef struct _RectangleItemStruct { /* Private data */ ZnPoint dev[4]; ZnImage tile; - ZnColorGradient gradient; + ZnGradient *gradient; #ifdef LIBART ArtSVP *outline_svp; ArtSVP *fill_svp; @@ -94,15 +93,13 @@ static ZnAttrConfig rect_attrs[] = { ZN_COORDS_FLAG, False }, { ZN_CONFIG_UINT, "-fillalpha", NULL, Tk_Offset(RectangleItemStruct, fill_alpha), 0, ZN_DRAW_FLAG, False }, - { ZN_CONFIG_GRADIENT_COLOR, "-fillcolor", NULL, + { ZN_CONFIG_GRADIENT, "-fillcolor", NULL, Tk_Offset(RectangleItemStruct, fill_color), 0, ZN_DRAW_FLAG|ZN_BORDER_FLAG, False }, { ZN_CONFIG_BOOL, "-filled", NULL, Tk_Offset(RectangleItemStruct, flags), FILLED_BIT, ZN_COORDS_FLAG, False }, { ZN_CONFIG_PATTERN, "-fillpattern", NULL, Tk_Offset(RectangleItemStruct, fill_pattern), 0, ZN_DRAW_FLAG, False }, - { ZN_CONFIG_GRADIENT_GEOM, "-gradient", NULL, - Tk_Offset(RectangleItemStruct, grad_geom), 0, ZN_DRAW_FLAG, False }, { ZN_CONFIG_UINT, "-linealpha", NULL, Tk_Offset(RectangleItemStruct, line_alpha), 0, ZN_DRAW_FLAG, False }, { ZN_CONFIG_COLOR, "-linecolor", NULL, @@ -210,10 +207,9 @@ Init(Item item, rect->fill_pattern = ZnUnspecifiedPattern; rect->line_color = ZnGetColorByValue(wi->win, wi->fore_color); rect->line_alpha = 255; - rect->fill_color = ZnGetColorGradient(wi->interp, wi->win, - ZnNameOfColor(wi->fore_color)); + rect->fill_color = ZnGetGradient(wi->interp, wi->win, + ZnNameOfColor(wi->fore_color)); rect->fill_alpha = 255; - rect->grad_geom = NULL; #ifdef LIBART rect->outline_svp = rect->fill_svp = NULL; #endif @@ -237,7 +233,7 @@ Clone(Item item) char *text; if (rect->gradient) { - rect->gradient = ZnGetColorGradientByValue(rect->gradient); + rect->gradient = ZnGetGradientByValue(rect->gradient); } if (strlen(rect->tile_name) != 0) { text = ZnMalloc((strlen(rect->tile_name) + 1) * sizeof(char)); @@ -255,10 +251,7 @@ Clone(Item item) Tk_NameOfBitmap(wi->dpy, rect->fill_pattern)); } rect->line_color = ZnGetColorByValue(wi->win, rect->line_color); - rect->fill_color = ZnGetColorGradientByValue(rect->fill_color); - if (rect->grad_geom) { - rect->grad_geom = GradientGeomDuplicate(rect->grad_geom); - } + rect->fill_color = ZnGetGradientByValue(rect->fill_color); #ifdef LIBART rect->outline_svp = rect->fill_svp = NULL; #endif @@ -286,7 +279,7 @@ Destroy(Item item) ZnFree(rect->tile_name); } if (rect->gradient) { - ZnFreeColorGradient(rect->gradient); + ZnFreeGradient(rect->gradient); } if (rect->line_pattern != ZnUnspecifiedPattern) { Tk_FreeBitmap(wi->dpy, rect->line_pattern); @@ -294,11 +287,8 @@ Destroy(Item item) if (rect->fill_pattern != ZnUnspecifiedPattern) { Tk_FreeBitmap(wi->dpy, rect->fill_pattern); } - ZnFreeColorGradient(rect->fill_color); + ZnFreeGradient(rect->fill_color); ZnFreeColor(rect->line_color); - if (rect->grad_geom) { - GradientGeomDelete(rect->grad_geom); - } #ifdef LIBART if (rect->outline_svp) { art_svp_free(rect->outline_svp); @@ -331,12 +321,12 @@ Configure(Item item, if (rect->gradient && (ISSET(*flags, ZN_BORDER_FLAG) || (rect->relief == RELIEF_FLAT))) { - ZnFreeColorGradient(rect->gradient); + ZnFreeGradient(rect->gradient); rect->gradient = NULL; } if ((rect->relief != RELIEF_FLAT) && !rect->gradient) { rect->gradient = ZnGetReliefGradient(wi->interp, wi->win, - ZnNameOfColor(ZnColorGradientMidColor(wi->win, rect->fill_color))); + ZnNameOfColor(ZnGetGradientColor(wi->win, rect->fill_color, 50.0))); } if (ISSET(*flags, ZN_TILE_FLAG)) { Tk_Image tile; @@ -575,19 +565,19 @@ Draw(Item item) * Fill if requested. */ if (ISSET(rect->flags, FILLED_BIT)) { - if (rect->grad_geom) { + if (!ZnGradientFlat(rect->fill_color)) { if (ISSET(rect->flags, ALIGNED_BIT)) { - DrawRectangleGradient(wi, rect->grad_geom, rect->fill_color, &r); + DrawRectangleGradient(wi, rect->fill_color, &r); } else { ZnPoly poly; POLY_CONTOUR1(&poly, rect->dev, 4); - DrawPolygonGradient(wi, rect->grad_geom, rect->fill_color, &poly, + DrawPolygonGradient(wi, rect->fill_color, &poly, &item->item_bounding_box); } } else { - values.foreground = ZnPixel(ZnColorGradientMidColor(wi->win, rect->fill_color)); + values.foreground = ZnPixel(ZnGetGradientColor(wi->win, rect->fill_color, 50.0)); if (rect->tile != ZnUnspecifiedImage) { /* Fill tiled */ Pixmap pmap = GetImagePixmap(wi->win, rect->tile_name, rect->tile, NULL); values.fill_style = FillTiled; @@ -694,7 +684,7 @@ Render(Item item) { WidgetInfo *wi = item->wi; RectangleItem rect = (RectangleItem) item; - XColor *color = ZnColorGradientMidColor(wi->win, rect->fill_color); + XColor *color = ZnGetGradientColor(wi->win, rect->fill_color, 50.0); #ifdef LIBART ArtPixBuf *pixbuf = NULL; @@ -719,7 +709,7 @@ Render(Item item) if (ISSET(rect->flags, FILLED_BIT)) { glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - if (rect->grad_geom) { + if (!ZnGradientFlat(rect->fill_color)) { } else { if (rect->tile != ZnUnspecifiedImage) { /* Fill tiled */ diff --git a/generic/Types.h b/generic/Types.h index 52f9397..73bfd4a 100644 --- a/generic/Types.h +++ b/generic/Types.h @@ -158,9 +158,8 @@ typedef struct { #define ZN_CONFIG_LEADER_ANCHORS 28 #define ZN_CONFIG_JOIN_STYLE 29 #define ZN_CONFIG_CAP_STYLE 30 -#define ZN_CONFIG_GRADIENT_GEOM 31 -#define ZN_CONFIG_GRADIENT_COLOR 32 -#define ZN_CONFIG_WINDOW 33 +#define ZN_CONFIG_GRADIENT 31 +#define ZN_CONFIG_WINDOW 32 #define ZN_DRAW_FLAG 1 << 0 #define ZN_COORDS_FLAG 1 << 1 @@ -268,9 +267,16 @@ typedef int ReliefStyle; /* Keep it an int to keep Tk happy */ #define RELIEF_RIDGE TK_RELIEF_RIDGE /* * Number of steps for relief drawing. This translate in - * RELIEF_STEPS*2+1 color steps in the color gradient. + * RELIEF_STEPS*2+1 color shades in the color gradient. */ -#define RELIEF_STEPS 6 +#define RELIEF_STEPS 6 +#define DEFAULT_NUM_SHADES 6 + +/* + * Types of gradients. + */ +#define ZN_AXIAL_GRADIENT 0 +#define ZN_RADIAL_GRADIENT 1 /* * Type and constant values for automatic alignments. -- cgit v1.1