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