diff options
Diffstat (limited to 'generic/Draw.c')
-rw-r--r-- | generic/Draw.c | 369 |
1 files changed, 194 insertions, 175 deletions
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 } |