From 320e8e0b54d6218191abc5835b4d8cc397a24920 Mon Sep 17 00:00:00 2001 From: lecoanet Date: Thu, 9 Mar 2000 13:39:37 +0000 Subject: * Suppression de DrawRectangleRelief. * Am�lioration de la stabilit� de g�n�ration des faces dans DrawPolygonRelief (il reste des cas pathologiques - plein meme). * Traitement de la lumi�re par DrawPolygonRelief. --- generic/Draw.c | 221 +++++++++++++++++++++++++++++---------------------------- 1 file changed, 111 insertions(+), 110 deletions(-) (limited to 'generic/Draw.c') diff --git a/generic/Draw.c b/generic/Draw.c index 26d952f..037e745 100644 --- a/generic/Draw.c +++ b/generic/Draw.c @@ -311,87 +311,53 @@ DrawLineShape(Display *display, /* - ********************************************************************************** - * - * DrawRectangleRelief -- - * Draw the bevels inside bbox. - * - ********************************************************************************** + * ReliefIndexOfSegment -- */ -void -DrawRectangleRelief(WidgetInfo *wi, - ReliefStyle relief, - ZnColorGradient gradient, - XRectangle *bbox, - unsigned int line_width) +static long +ReliefColorOfSegment(ZnReal x1, + ZnReal y1, + ZnReal x2, + ZnReal y2, + ReliefStyle relief, + ZnColorGradient gradient, + WidgetInfo *wi) { - XGCValues gc_values; - XPoint top_points[7]; + ZnReal angle, angle_step, origin; + int color_index, num_colors; - /* - * If we haven't enough space to draw, exit. - */ - if ((bbox->width < 2*line_width) || (bbox->height < 2*line_width)) { - return; - } - - /* - * Grooves and ridges are drawn with two recursives calls with - * half the width of the original one. - */ - if ((relief == RELIEF_RIDGE) || (relief == RELIEF_GROOVE)) { - unsigned int new_line_width; - int offset; - XRectangle internal_bbox; - - new_line_width = line_width/2; - offset = line_width - new_line_width; - DrawRectangleRelief(wi, - (relief==RELIEF_GROOVE)?RELIEF_BEVEL_IN:RELIEF_BEVEL_OUT, - gradient, bbox, new_line_width); - internal_bbox = *bbox; - internal_bbox.x +=offset; - internal_bbox.y += offset; - internal_bbox.width -= offset*2; - internal_bbox.height -= offset*2; - DrawRectangleRelief(wi, - (relief==RELIEF_GROOVE)?RELIEF_BEVEL_OUT:RELIEF_BEVEL_IN, - gradient, &internal_bbox, new_line_width); - return; - } - - gc_values.fill_style = FillSolid; + num_colors = ZnColorGradientSpan(gradient); + angle_step = M_PI / (num_colors-1); + origin = -(DegreesToRadian(wi->light_angle))-(angle_step/2.0); if (relief == RELIEF_BEVEL_IN) { - gc_values.foreground = ZnColorGradientPixel(gradient, wi->win, -1); + origin += M_PI; } - else { - gc_values.foreground = ZnColorGradientPixel(gradient, wi->win, 0); - } - XChangeGC(wi->dpy, wi->gc, GCFillStyle|GCForeground, &gc_values); - XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc, - bbox->x, bbox->y + bbox->height - line_width, - bbox->width, line_width); - XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc, - bbox->x + bbox->width - line_width, bbox->y, - line_width, bbox->height); - if (relief == RELIEF_BEVEL_IN) { - gc_values.foreground = ZnColorGradientPixel(gradient, wi->win, 0); + angle = (ProjectionToAngle(y1 - y2, x2 - x1) + M_PI - origin); + while (angle < 0.0) { + angle += 2*M_PI; } - else { - gc_values.foreground = ZnColorGradientPixel(gradient, wi->win, -1); + 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; + } } - XChangeGC(wi->dpy, wi->gc, GCFillStyle|GCForeground, &gc_values); - top_points[0].x = top_points[1].x = top_points[6].x = bbox->x; - top_points[0].y = top_points[6].y = bbox->y + bbox->height; - top_points[1].y = top_points[2].y = bbox->y; - top_points[2].x = bbox->x + bbox->width; - top_points[3].x = bbox->x + bbox->width - line_width; - top_points[3].y = top_points[4].y = bbox->y + line_width; - top_points[4].x = top_points[5].x = bbox->x + line_width; - top_points[5].y = bbox->y + bbox->height - line_width; - XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, top_points, 7, - Nonconvex, CoordModeOrigin); + /*printf("color index %d(), angle %g(), origin %g\n", + color_index, + RadianToDegrees(angle), + RadianToDegrees(origin));*/ + + return ZnColorGradientPixel(gradient, wi->win, color_index); } @@ -407,8 +373,8 @@ DoPolygonRelief(ZnPoint *p, ZnPoint pp1, pp2, new_pp1, new_pp2; ZnPoint perp, c, shift1, shift2; ZnPoint bevel_points[4]; - XPoint bevel_xpoints[4]; - ZnBool parallel, closed; + XPoint bevel_xpoints[5]; + ZnBool folded, closed, colinear; WidgetInfo *wi = NULL; ReliefStyle relief = 0; ZnColorGradient gradient = NULL; @@ -416,7 +382,11 @@ DoPolygonRelief(ZnPoint *p, double *dist = NULL; ZnBBox *bbox = NULL; va_list var; - +#if 0 + ZnBool toggle=True; +#endif + ZnReal dx, dy; + va_start(var, what_to_do); if (what_to_do == POLYGON_RELIEF_DIST) { pp = va_arg(var, ZnPoint *); @@ -449,7 +419,8 @@ DoPolygonRelief(ZnPoint *p, closed = True; num_points--; } - + /*printf("num_points=%d(%s)\n\n", num_points, closed?"closed":"");*/ + /* * We loop on all vertices of the polygon. * At each step we try to compute the corresponding border @@ -480,7 +451,7 @@ DoPolygonRelief(ZnPoint *p, * process two points). This is why we start at the point before the last * and then wrap to the first point. * The algorithm discards any duplicate contiguous points. - * It makes a special case if two consecutives edges are parallel: + * It makes a special case if two consecutives edges are folded: * * bevel[1] pp1 pp2 a bevel[2] * *-----------*--------------*----------* @@ -494,8 +465,8 @@ DoPolygonRelief(ZnPoint *p, * ----------*-----------*-------------* * new_pp1 new_pp2 c * - * In such a case we need to compute a, b, corner from pp1, pp2, new_pp1 - * and new_pp2. We compute the perpendicular to p&,p2 through p1, intersect + * In such a case we need to compute a, c, corner from pp1, pp2, new_pp1 + * and new_pp2. We compute the perpendicular to p1,p2 through p1, intersect * it with pp1,pp2 to obtain a, intersect it with new_pp1, new_pp2 to * obtain c, shift a,c and intersect it with p1,p2 to obtain corner. * @@ -510,7 +481,7 @@ DoPolygonRelief(ZnPoint *p, i = -2; p1 = &p[num_points-2]; } - for (p2 = p1+1; i < num_points; i++, p1 = p2, p2++) { + for (p2 = p1+1; i < num_points; i++, p2++) { /* * When it is time to wrap, do it */ @@ -519,15 +490,18 @@ DoPolygonRelief(ZnPoint *p, } /* - * Skip over duplicate vertices. + * Skip over close vertices. */ - if ((p2->x == p1->x) && (p2->y == p1->y)) { + dx = p2->x - p1->x; + dy = p2->y - p1->y; + if ((ABS(dx) < 1.0) && (ABS(dy) < 1.0)) { continue; } ShiftLine(p1, p2, line_width, &new_pp1, &new_pp2); bevel_points[3] = *p1; - parallel = False; + folded = False; + colinear = False; /* * The first two cases are for `open' polygons. We compute * a bevel closure that is perpendicular to the path. @@ -543,14 +517,36 @@ DoPolygonRelief(ZnPoint *p, IntersectLines(p1, &perp, &pp1, &pp2, &bevel_points[2]); } else if (processed_points >= 1) { - parallel = !IntersectLines(&new_pp1, &new_pp2, &pp1, &pp2, &bevel_points[2]); - if (parallel) { + ZnReal dotp, dist, odx, ody; + + /* + * The dot product of the two faces tell if the are + * folded or colinear. The + */ + odx = (p1-1)->x - p1->x; + ody = (p1-1)->y - p1->y; + dotp = odx*dx + ody*dy; + dist = LineToPointDist(p1-1, p2, p1); + if ((dist < 4.0) && (dotp <= 0)) { perp.x = p1->x + (p2->y - p1->y); perp.y = p1->y - (p2->x - p1->x); - IntersectLines(p1, &perp, &pp1, &pp2, &bevel_points[2]); - IntersectLines(p1, &perp, &new_pp1, &new_pp2, &c); - ShiftLine(p1, &perp, line_width, &shift1, &shift2); - IntersectLines(p1, p2, &shift1, &shift2, &bevel_points[3]); + IntersectLines(p1, &perp, &new_pp1, &new_pp2, &bevel_points[2]); + colinear = True; + } + else { + folded = !IntersectLines(&new_pp1, &new_pp2, &pp1, &pp2, &bevel_points[2]); + folded = folded && (dotp < 0); + if (folded) { + /*printf("DoPolygonRelief: folded edges detected, %g@%g, %g@%g, %g@%g, %g@%g\n", + pp1.x, pp1.y, pp2.x, pp2.y, new_pp1.x, new_pp1.y, + new_pp2.x, new_pp2.y);*/ + perp.x = p1->x + (p2->y - p1->y); + perp.y = p1->y - (p2->x - p1->x); + IntersectLines(p1, &perp, &pp1, &pp2, &bevel_points[2]); + IntersectLines(p1, &perp, &new_pp1, &new_pp2, &c); + ShiftLine(p1, &perp, line_width, &shift1, &shift2); + IntersectLines(p1, p2, &shift1, &shift2, &bevel_points[3]); + } } } @@ -586,41 +582,46 @@ DoPolygonRelief(ZnPoint *p, } } else if (what_to_do == POLYGON_RELIEF_DRAW) { - ZnReal dx, dy; - ZnBool light_on_left; XGCValues gc_values; - - dx = bevel_points[3].x - bevel_points[0].x; - dy = bevel_points[3].y - bevel_points[0].y; - if (dx > 0.0) { - light_on_left = (dy <= dx); - } - else { - light_on_left = (dy < dx); - } - +#if 1 + gc_values.foreground = ReliefColorOfSegment(bevel_points[0].x, bevel_points[0].y, + bevel_points[3].x, bevel_points[3].y, + relief, gradient, wi); +#endif +#if 0 + gc_values.foreground = toggle ? WhitePixelOfScreen(wi->screen):BlackPixelOfScreen(wi->screen); +#endif +#if 0 + gc_values.foreground = colinear ? WhitePixelOfScreen(wi->screen):BlackPixelOfScreen(wi->screen); +#endif +#if 0 + toggle = !toggle; +#endif gc_values.fill_style = FillSolid; - if (light_on_left ^ (relief == RELIEF_BEVEL_OUT)) { - gc_values.foreground = ZnColorGradientPixel(gradient, wi->win, -1); - } - else { - gc_values.foreground = ZnColorGradientPixel(gradient, wi->win, 0); - } - XChangeGC(wi->dpy, wi->gc, GCFillStyle|GCForeground, &gc_values); + gc_values.line_width = 0; + XChangeGC(wi->dpy, wi->gc, GCLineWidth|GCFillStyle|GCForeground, &gc_values); for (j = 0; j < 4; j++) { bevel_xpoints[j].x = REAL_TO_INT(bevel_points[j].x); bevel_xpoints[j].y = REAL_TO_INT(bevel_points[j].y); } +#if 1 XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, bevel_xpoints, 4, Convex, CoordModeOrigin); +#endif +#if 0 + bevel_xpoints[4] = bevel_xpoints[0]; + XDrawLines(wi->dpy, wi->draw_buffer, wi->gc, bevel_xpoints, 5, + CoordModeOrigin); +#endif } } + p1 = p2; pp1 = new_pp1; pp2 = new_pp2; bevel_points[0] = bevel_points[3]; - if (parallel) { + if (folded) { bevel_points[1] = c; } else if ((processed_points >= 1) || !closed) { -- cgit v1.1