aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlecoanet2001-06-25 11:20:03 +0000
committerlecoanet2001-06-25 11:20:03 +0000
commita3adeee4ca08764b8e78282c4b1cd57a0d830c0d (patch)
tree45ce35e7184460623d82f84842f63326466e3374
parente3c6410aaa3aa3257d40a506b496c4cba137ae0c (diff)
downloadtkzinc-a3adeee4ca08764b8e78282c4b1cd57a0d830c0d.zip
tkzinc-a3adeee4ca08764b8e78282c4b1cd57a0d830c0d.tar.gz
tkzinc-a3adeee4ca08764b8e78282c4b1cd57a0d830c0d.tar.bz2
tkzinc-a3adeee4ca08764b8e78282c4b1cd57a0d830c0d.tar.xz
Modification des gradients
-rw-r--r--Bezier.c38
-rw-r--r--generic/Arc.c33
-rw-r--r--generic/Attrs.c112
-rw-r--r--generic/Attrs.h21
-rw-r--r--generic/Color.c683
-rw-r--r--generic/Color.h57
-rw-r--r--generic/Curve.c40
-rw-r--r--generic/Draw.c369
-rw-r--r--generic/Draw.h12
-rw-r--r--generic/Item.c70
-rw-r--r--generic/Rectangle.c44
-rw-r--r--generic/Types.h16
12 files changed, 632 insertions, 863 deletions
diff --git a/Bezier.c b/Bezier.c
index 9f55f53..d239c4b 100644
--- a/Bezier.c
+++ b/Bezier.c
@@ -75,8 +75,7 @@ typedef struct _BezierItemStruct {
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;
char *tile_name;
@@ -84,7 +83,7 @@ typedef struct _BezierItemStruct {
/* Private data */
ZnImage tile;
ZnList dev_points;
- ZnColorGradient gradient;
+ ZnGradient *gradient;
} BezierItemStruct, *BezierItem;
@@ -98,7 +97,7 @@ static ZnAttrConfig bz_attrs[] = {
{ ZN_CONFIG_BOOL, "-composescale", NULL,
Tk_Offset(BezierItemStruct, header.flags), COMPOSE_SCALE_BIT,
ZN_COORDS_FLAG, False },
- { ZN_CONFIG_GRADIENT_COLOR, "-fillcolor", NULL,
+ { ZN_CONFIG_GRADIENT, "-fillcolor", NULL,
Tk_Offset(BezierItemStruct, fill_color), 0,
ZN_DRAW_FLAG|ZN_BORDER_FLAG, False },
{ ZN_CONFIG_PATTERN, "-fillpattern", NULL,
@@ -107,8 +106,6 @@ static ZnAttrConfig bz_attrs[] = {
Tk_Offset(BezierItemStruct, flags), FILLED_BIT, ZN_COORDS_FLAG, False },
{ ZN_CONFIG_LINE_END, "-firstend", NULL,
Tk_Offset(BezierItemStruct, first_end), 0, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_GRADIENT_GEOM, "-gradient", NULL,
- Tk_Offset(BezierItemStruct, grad_geom), 0, ZN_DRAW_FLAG, False },
{ ZN_CONFIG_LINE_END, "-lastend", NULL,
Tk_Offset(BezierItemStruct, last_end), 0, ZN_COORDS_FLAG, False },
{ ZN_CONFIG_COLOR, "-linecolor", NULL,
@@ -231,10 +228,9 @@ Init(Item item,
bz->line_pattern = ZnUnspecifiedPattern;
bz->cap_style = CapRound;
- bz->fill_color = ZnGetColorGradient(wi->interp, wi->win,
- ZnNameOfColor(wi->fore_color));
+ bz->fill_color = ZnGetGradient(wi->interp, wi->win,
+ ZnNameOfColor(wi->fore_color));
bz->line_color = ZnGetColorByValue(wi->win, wi->fore_color);
- bz->grad_geom = NULL;
return ZN_OK;
}
@@ -257,7 +253,7 @@ Clone(Item item)
bz->dev_points = NULL;
if (bz->gradient) {
- bz->gradient = ZnGetColorGradientByValue(bz->gradient);
+ bz->gradient = ZnGetGradientByValue(bz->gradient);
}
if (bz->points) {
bz->points = ZnListDuplicate(bz->points);
@@ -284,10 +280,7 @@ Clone(Item item)
Tk_NameOfBitmap(wi->dpy, bz->fill_pattern));
}
bz->line_color = ZnGetColorByValue(wi->win, bz->line_color);
- bz->fill_color = ZnGetColorGradientByValue(bz->fill_color);
- if (bz->grad_geom) {
- bz->grad_geom = GradientGeomDuplicate(bz->grad_geom);
- }
+ bz->fill_color = ZnGetGradientByValue(bz->fill_color);
}
@@ -317,7 +310,7 @@ Destroy(Item item)
LineEndDelete(bz->last_end);
}
if (bz->gradient) {
- ZnFreeColorGradient(bz->gradient);
+ ZnFreeGradient(bz->gradient);
}
if (bz->tile != ZnUnspecifiedImage) {
Tk_FreeImage(bz->tile);
@@ -332,11 +325,8 @@ Destroy(Item item)
if (bz->fill_pattern != ZnUnspecifiedPattern) {
Tk_FreeBitmap(wi->dpy, bz->fill_pattern);
}
- ZnFreeColorGradient(bz->fill_color);
+ ZnFreeGradient(bz->fill_color);
ZnFreeColor(bz->line_color);
- if (bz->grad_geom) {
- GradientGeomDelete(bz->grad_geom);
- }
}
@@ -391,12 +381,12 @@ Configure(Item item,
if (bz->gradient &&
(ISSET(*flags, ZN_BORDER_FLAG) || (bz->relief == RELIEF_FLAT))) {
- ZnFreeColorGradient(bz->gradient);
+ ZnFreeGradient(bz->gradient);
bz->gradient = NULL;
}
if ((bz->relief != RELIEF_FLAT) && !bz->gradient) {
bz->gradient = ZnGetReliefGradient(wi->interp, wi->win,
- ZnNameOfColor(ZnColorGradientMidColor(wi->win, bz->fill_color)));
+ ZnNameOfColor(ZnGetGradientColor(wi->win, bz->fill_color, 50.0)));
}
if (ISSET(*flags, ZN_TILE_FLAG)) {
Tk_Image tile;
@@ -697,14 +687,14 @@ Draw(Item item)
* Fill if requested.
*/
if (ISSET(bz->flags, FILLED_OK)) {
- if (bz->grad_geom) {
+ if (!ZnGradientFlat(bz->fill_color)) {
ZnPoly poly;
POLY_CONTOUR1(&poly, points, num_points);
- DrawPolygonGradient(wi, bz->grad_geom, bz->fill_color, &poly,
+ DrawPolygonGradient(wi, bz->fill_color, &poly,
&item->item_bounding_box);
}
else {
- values.foreground = ZnPixel(ZnColorGradientMidColor(wi->win, bz->fill_color));
+ values.foreground = ZnPixel(ZnGetGradientColor(wi->win, bz->fill_color, 50.0));
gc_mask = GCFillStyle;
if (bz->tile != ZnUnspecifiedImage) { /* Fill tiled */
Pixmap pmap = GetImagePixmap(wi->win, bz->tile_name, bz->tile, NULL);
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 <malloc.h>
+#include <string.h>
#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.