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