From 8516442be4b957b4b3b03da857a6a1ea16263236 Mon Sep 17 00:00:00 2001 From: lecoanet Date: Fri, 16 May 2003 14:10:06 +0000 Subject: Modification of gradient syntax to support vector style specification --- generic/Color.c | 93 ++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 73 insertions(+), 20 deletions(-) (limited to 'generic/Color.c') diff --git a/generic/Color.c b/generic/Color.c index d0c3a81..c83631d 100644 --- a/generic/Color.c +++ b/generic/Color.c @@ -375,9 +375,30 @@ ZnDeleteGradientName(char *name) * * graddesc := =type args * where type := axial | radial | path - * args := angle if type = axial; angle in (0..360) - * args := x y if type = (radial| path); x and - * y being real valued. + * + * If type = axial + * args := angle (0..360) | xs ys xe ye (reals) + * + * The first form define the axial gradiant by its slope. + * With this syntax the gradient fits the whole shape. + * This is a backward compatible syntax. + * The second form specifies a vector which will be used + * to draw the gradient. The vector defines both the angle + * and the gradient area. Parts of the shape that lie before + * the vector origin are filled with the first color and + * parts that lie after the vector end are filled with the + * last color. + * + * If type = radial or path + * args := xs ys [xe ye] (reals) + * + * The vector specified by the 4 coordinates defines the + * gradient area. Parts of the shape that lie before + * the vector origin are filled with the first color and + * parts that lie after the vector end are filled with the + * last color. The vector end may be omitted, in such case + * the gradient fits exactly the whole shape to be filled, + * this is backward compatible with older gradients. * * color := colorvalue | colorvalue position | * colorvalue control position @@ -388,7 +409,7 @@ ZnDeleteGradientName(char *name) * * Results: * The return value is a token for a data structure - * describing a gradient. This token may be passed + * describing a gradient. This token may be passed * to the drawing routines. * If an error prevented the gradient from being created * then NULL is returned and an error message will be @@ -409,6 +430,30 @@ ZnGetGradientByValue(ZnGradient *grad) } +static int +ParseRealList(const char *str, + const char *stop, + ZnReal *list, + int max) +{ + int num; + char *end; + + num = 0; + while ((num < max) && (str != stop)) { + list[num] = strtod(str, &end); + if (end == str) { + /* A syntax error occured, return a 0 count + * as a hint for the caller. + */ + return 0; + } + num++; + str = end+strspn(end, " \t"); + } + return num; +} + ZnGradient * ZnGetGradient(Tcl_Interp *interp, Tk_Window tkwin, @@ -418,11 +463,11 @@ ZnGetGradient(Tcl_Interp *interp, Tcl_HashEntry *hash; ZnGradient *grad; unsigned int i, j, nspace, num_colors; - unsigned int size; + unsigned int size, num_coords; char type; char const *scan_ptr, *next_ptr, *str_ptr; int angle, position, control; - double x=0, y=0; + ZnReal coords[4]; char *color_ptr, *end, segment[SEGMENT_SIZE]; ZnGradientColor *first, *last; XColor color; @@ -495,14 +540,13 @@ ZnGetGradient(Tcl_Interp *interp, scan_ptr++; if ((*scan_ptr == 'a') && (strncmp(scan_ptr, "axial", 5) == 0)) { scan_ptr += 5; - angle = strtol(scan_ptr, &end, 10); - nspace = strspn(end, " \t"); - if ((end+nspace) != next_ptr) { + if (ParseRealList(scan_ptr, next_ptr, coords, 1) != 1) { grad_err3: Tcl_AppendResult(interp, "invalid gradient parameter \"", desc, "\",", NULL); goto grad_err1; } + angle = (int) coords[0]; } else if (((*scan_ptr == 'r') && (strncmp(scan_ptr, "radial", 6) == 0)) || ((*scan_ptr == 'p') && (strncmp(scan_ptr, "path", 4) == 0))) { @@ -514,14 +558,8 @@ ZnGetGradient(Tcl_Interp *interp, 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) { + num_coords = ParseRealList(scan_ptr, next_ptr, coords, 4); + if ((num_coords != 2) && (num_coords != 4)) { goto grad_err3; } } @@ -539,14 +577,29 @@ ZnGetGradient(Tcl_Interp *interp, grad = (ZnGradient *) ZnMalloc(sizeof(ZnGradient) + sizeof(ZnGradientColor)*(num_colors-1)); grad->ref_count = 1; + grad->simple = True; grad->num_colors = num_colors; grad->type = type; if (type == ZN_AXIAL_GRADIENT) { - grad->g.angle = angle; + if (num_coords == 4) { + grad->simple = False; + grad->g.p.x = coords[0]; + grad->g.p.y = coords[1]; + grad->e.x = coords[2]; + grad->e.y = coords[3]; + } + else { + grad->g.angle = angle; + } } else { - grad->g.p.x = x; - grad->g.p.y = y; + grad->g.p.x = coords[0]; + grad->g.p.y = coords[1]; + if (num_coords == 4) { + grad->simple = False; + grad->e.x = coords[2]; + grad->e.y = coords[3]; + } } grad->hash = hash; Tcl_SetHashValue(hash, grad); -- cgit v1.1