aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--generic/Color.c139
1 files changed, 91 insertions, 48 deletions
diff --git a/generic/Color.c b/generic/Color.c
index f23dc49..6518aa0 100644
--- a/generic/Color.c
+++ b/generic/Color.c
@@ -1169,14 +1169,16 @@ ZnGetGradient(Tcl_Interp *interp,
Tk_Window tkwin,
Tk_Uid desc)
{
+ #define SEGMENT_SIZE 64
Tcl_HashEntry *hash;
ZnGradient *grad;
- int i, j, new, num_colors;
+ int i, j, nspace, new, num_colors;
+ unsigned int size;
char type;
- char const *scan_ptr;
- int num_tok, angle, position, control;
- double x, y;
- char *color_ptr, color_name[COLOR_NAME_SIZE];
+ char const *scan_ptr, *next_ptr, *str_ptr;
+ int angle, position, control;
+ double x=0, y=0;
+ char *color_ptr, *end, segment[SEGMENT_SIZE];
ZnGradientColor *first, *last;
XColor color;
int red_range, green_range, blue_range;
@@ -1221,7 +1223,7 @@ ZnGetGradient(Tcl_Interp *interp,
* If the first section is the gradient description, start color
* counts up from zero.
*/
- num_colors = (*scan_ptr == '@') ? 0 : 1;
+ num_colors = (*scan_ptr == '=') ? 0 : 1;
while ((scan_ptr = strchr(scan_ptr, '|'))) {
num_colors++;
scan_ptr++;
@@ -1238,44 +1240,53 @@ ZnGetGradient(Tcl_Interp *interp,
* Then look at the gradient type.
*/
scan_ptr = desc;
- if (*scan_ptr == '@') {
+ /*
+ * next_ptr can't be NULL in the following code,
+ * we checked that at least one color was specified
+ * after the gradient description.
+ */
+ next_ptr = strchr(scan_ptr, '|');
+ if (*scan_ptr == '=') {
scan_ptr++;
if ((*scan_ptr == 'a') && (strncmp(scan_ptr, "axial", 5) == 0)) {
scan_ptr += 5;
- num_tok = sscanf(scan_ptr, "%d", &angle);
- if (num_tok != 1) {
- Tcl_AppendResult(interp, "invalid axial gradient parameter \"",
+ angle = strtol(scan_ptr, &end, 10);
+ nspace = strspn(end, " \t");
+ if ((end+nspace) != next_ptr) {
+ grad_err3:
+ Tcl_AppendResult(interp, "invalid gradient parameter \"",
desc, "\",", NULL);
goto grad_err1;
}
}
- else if ((*scan_ptr == 'r') && (strncmp(scan_ptr, "radial", 6) == 0)) {
- scan_ptr += 6;
- num_tok = sscanf(scan_ptr, "%lf %lf", (double *) &x, (double *) &y);
- if (num_tok != 2) {
- Tcl_AppendResult(interp, "invalid radial gradient parameter \"",
- desc, "\",", NULL);
- goto grad_err1;
+ else if (((*scan_ptr == 'r') && (strncmp(scan_ptr, "radial", 6) == 0)) ||
+ ((*scan_ptr == 'p') && (strncmp(scan_ptr, "path", 4) == 0))) {
+ if (*scan_ptr == 'r') {
+ type = ZN_RADIAL_GRADIENT;
+ scan_ptr += 6;
}
- type = ZN_RADIAL_GRADIENT;
- }
- else if ((*scan_ptr == 'p') && (strncmp(scan_ptr, "path", 4) == 0)) {
- scan_ptr += 4;
- num_tok = sscanf(scan_ptr, "%lf %lf", (double *) &x, (double *) &y);
- if (num_tok == 2) {
- Tcl_AppendResult(interp, "invalid path gradient parameter \"",
- desc, "\",", NULL);
- goto grad_err1;
+ else {
+ type = ZN_PATH_GRADIENT;
+ scan_ptr += 4;
+ }
+ x = strtod(scan_ptr, &end);
+ if (end == scan_ptr) {
+ goto grad_err3;
+ }
+ scan_ptr = end;
+ y = strtod(scan_ptr, &end);
+ nspace = strspn(end, " \t");
+ if ((end+nspace) != next_ptr) {
+ goto grad_err3;
}
- type = ZN_PATH_GRADIENT;
}
else {
Tcl_AppendResult(interp, "invalid gradient type \"",
desc, "\",", NULL);
goto grad_err1;
}
- scan_ptr = strchr(scan_ptr, '|');
- scan_ptr++;
+ scan_ptr = next_ptr + 1;
+ next_ptr = strchr(scan_ptr, '|');
}
/*
* Create the gradient structure.
@@ -1296,12 +1307,21 @@ ZnGetGradient(Tcl_Interp *interp,
Tcl_SetHashValue(hash, grad);
for (i = 0; i < num_colors; i++) {
- 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 == 0) {
- Tcl_AppendResult(interp, "incorrect color description in gradient \"",
+ /*
+ * Try to parse the color name.
+ */
+ nspace = strspn(scan_ptr, " \t");
+ scan_ptr += nspace;
+ str_ptr = strpbrk(scan_ptr, " \t|");
+ if (str_ptr) {
+ size = str_ptr - scan_ptr;
+ }
+ else {
+ size = strlen(scan_ptr);
+ }
+ if (size > (SEGMENT_SIZE-1)) {
+ Tcl_AppendResult(interp, "color name too long in gradient \"",
desc, "\",", NULL);
grad_err2:
for (j = 0; j < i; j++) {
@@ -1310,17 +1330,39 @@ ZnGetGradient(Tcl_Interp *interp,
ZnFree(grad);
goto grad_err1;
}
- if (num_tok > 1) {
+ strncpy(segment, scan_ptr, size);
+ segment[size] = 0;
+ scan_ptr += size;
+ /*
+ * Try to parse the color position.
+ */
+ grad->colors[i].position = 0;
+ grad->colors[i].control = 50;
+ position = strtol(scan_ptr, &end, 10);
+ if (end != scan_ptr) {
grad->colors[i].position = position;
+ scan_ptr = end;
+ /*
+ * Try to parse the control point
+ */
+ control = strtol(scan_ptr, &end, 10);
+ if (end != scan_ptr) {
+ grad->colors[i].control = control;
+ scan_ptr = end;
+ }
}
- if (num_tok > 2) {
- grad->colors[i].control = control;
+ nspace = strspn(scan_ptr, " \t");
+ if ((scan_ptr[nspace] != 0) && (scan_ptr+nspace != next_ptr)) {
+ Tcl_AppendResult(interp, "incorrect color description in gradient \"",
+ desc, "\",", NULL);
+ goto grad_err2;
}
- color_ptr = strchr(color_name, ';');
+
+ color_ptr = strchr(segment, ';');
if (color_ptr) {
*color_ptr = 0;
}
- grad->colors[i].rgb = ZnGetColor(interp, tkwin, Tk_GetUid(color_name));
+ grad->colors[i].rgb = ZnGetColor(interp, tkwin, Tk_GetUid(segment));
if (grad->colors[i].rgb == NULL) {
Tcl_AppendResult(interp, "incorrect color value in gradient \"",
desc, "\",", NULL);
@@ -1336,13 +1378,12 @@ ZnGetGradient(Tcl_Interp *interp,
else if (i == num_colors - 1) {
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)) {
- Tcl_AppendResult(interp, "incorrect color position in gradient \"",
- desc, "\",", NULL);
- goto grad_err2;
- }
+ if ((i > 0) &&
+ ((grad->colors[i].position > 100) ||
+ (grad->colors[i].position < grad->colors[i-1].position))) {
+ Tcl_AppendResult(interp, "incorrect color position in gradient \"",
+ desc, "\",", NULL);
+ goto grad_err2;
}
if (grad->colors[i].control > 100) {
grad->colors[i].control = 100;
@@ -1350,8 +1391,10 @@ ZnGetGradient(Tcl_Interp *interp,
if (grad->colors[i].alpha > 100) {
grad->colors[i].alpha = 100;
}
- scan_ptr = strchr(scan_ptr, '|');
- scan_ptr++;
+ if (next_ptr) {
+ scan_ptr = next_ptr + 1;
+ next_ptr = strchr(scan_ptr, '|');
+ }
}
}