diff options
Diffstat (limited to 'generic')
-rw-r--r-- | generic/Arc.c | 372 |
1 files changed, 213 insertions, 159 deletions
diff --git a/generic/Arc.c b/generic/Arc.c index 43aeb5c..2df6e7d 100644 --- a/generic/Arc.c +++ b/generic/Arc.c @@ -80,7 +80,6 @@ typedef struct _ArcItemStruct { ZnLineEnd first_end; ZnLineEnd last_end; int line_alpha; - int fill_alpha; char *tile_name; unsigned char flags; @@ -91,10 +90,7 @@ typedef struct _ArcItemStruct { ZnPoint center2; ZnImage tile; ZnList render_shape; -#ifdef LIBART - ArtSVP *outline_svp; - ArtSVP *fill_svp; -#endif + ZnPoint *grad_geo; } ArcItemStruct, *ArcItem; @@ -109,8 +105,6 @@ static ZnAttrConfig arc_attrs[] = { ZN_COORDS_FLAG, False }, { ZN_CONFIG_ANGLE, "-extent", NULL, Tk_Offset(ArcItemStruct, angle_extent), 0, ZN_COORDS_FLAG, False }, - { ZN_CONFIG_UINT, "-fillalpha", NULL, - Tk_Offset(ArcItemStruct, fill_alpha), 0, ZN_DRAW_FLAG, False }, { ZN_CONFIG_GRADIENT, "-fillcolor", NULL, Tk_Offset(ArcItemStruct, fill_color), 0, ZN_DRAW_FLAG, False }, { ZN_CONFIG_BOOL, "-filled", NULL, @@ -121,7 +115,7 @@ static ZnAttrConfig arc_attrs[] = { Tk_Offset(ArcItemStruct, first_end), 0, ZN_COORDS_FLAG, False }, { ZN_CONFIG_LINE_END, "-lastend", NULL, Tk_Offset(ArcItemStruct, last_end), 0, ZN_COORDS_FLAG, False }, - { ZN_CONFIG_UINT, "-linealpha", NULL, + { ZN_CONFIG_ALPHA, "-linealpha", NULL, Tk_Offset(ArcItemStruct, line_alpha), 0, ZN_DRAW_FLAG, False }, { ZN_CONFIG_COLOR, "-linecolor", NULL, Tk_Offset(ArcItemStruct, line_color), 0, @@ -216,6 +210,7 @@ Init(Item item, arc->tile_name = ""; arc->tile = ZnUnspecifiedImage; arc->render_shape = NULL; + arc->grad_geo = NULL; if (*argc < 1) { Tcl_AppendResult(wi->interp, " arc coords expected", NULL); @@ -233,14 +228,10 @@ Init(Item item, (*args)++; (*argc)--; - arc->fill_alpha = 255; arc->fill_color = ZnGetGradient(wi->interp, wi->win, ZnNameOfColor(wi->fore_color)); - arc->line_alpha = 255; + arc->line_alpha = 100; arc->line_color = ZnGetColorByValue(wi->win, wi->fore_color); -#ifdef LIBART - arc->outline_svp = arc->fill_svp = NULL; -#endif return ZN_OK; } @@ -260,6 +251,7 @@ Clone(Item item) WidgetInfo *wi = item->wi; char *text; + arc->grad_geo = NULL; if (strlen(arc->tile_name) != 0) { text = ZnMalloc((strlen(arc->tile_name) + 1) * sizeof(char)); strcpy(text, arc->tile_name); @@ -283,9 +275,6 @@ Clone(Item item) } arc->line_color = ZnGetColorByValue(wi->win, arc->line_color); arc->fill_color = ZnGetGradientByValue(arc->fill_color); -#ifdef LIBART - arc->outline_svp = arc->fill_svp = NULL; -#endif arc->render_shape = NULL; } @@ -306,14 +295,6 @@ Destroy(Item item) if (arc->render_shape) { ZnListFree(arc->render_shape); } -#ifdef LIBART - if (arc->outline_svp) { - art_svp_free(arc->outline_svp); - } - if (arc->fill_svp) { - art_svp_free(arc->fill_svp); - } -#endif if (arc->first_end) { LineEndDelete(arc->first_end); } @@ -333,6 +314,9 @@ Destroy(Item item) if (arc->fill_pattern != ZnUnspecifiedPattern) { Tk_FreeBitmap(wi->dpy, arc->fill_pattern); } + if (arc->grad_geo) { + ZnFree(arc->grad_geo); + } ZnFreeGradient(arc->fill_color); ZnFreeColor(arc->line_color); } @@ -527,19 +511,19 @@ ComputeCoordinates(Item item, !ZnGradientFlat(arc->fill_color) || wi->render) { SET(arc->flags, USING_POLY_BIT); if (!arc->render_shape) { - arc->render_shape = ZnListNew(4, sizeof(ZnPoint)); + arc->render_shape = ZnListNew(20, sizeof(ZnPoint)); } - GetArcPath(DegreesToRadian(arc->start_angle), - DegreesToRadian(arc->start_angle+arc->angle_extent), - (ISCLEAR(arc->flags, CLOSED_BIT) ? 0 : - ISCLEAR(arc->flags, PIE_SLICE_BIT) ? 1 : 2), arc->render_shape); + p_list = GetCirclePoints((ISCLEAR(arc->flags, CLOSED_BIT) ? 0 : + ISCLEAR(arc->flags, PIE_SLICE_BIT) ? 1 : 2), + ZN_CIRCLE_FINEST, + DegreesToRadian(arc->start_angle), + DegreesToRadian(arc->start_angle+arc->angle_extent), + &num_p, + arc->render_shape); ox = (arc->coords[1].x + arc->coords[0].x)/2.0; oy = (arc->coords[1].y + arc->coords[0].y)/2.0; - p_list = (ZnPoint *) ZnListArray(arc->render_shape); - num_p = ZnListSize(arc->render_shape); - for (i = 0; i < num_p; i++, p_list++) { p.x = ox + p_list->x*width_2; p.y = oy + p_list->y*height_2; @@ -567,47 +551,68 @@ ComputeCoordinates(Item item, AddPointsToBBox(&item->item_bounding_box, end_points, LINE_END_POINTS); } - if (wi->render) { -#ifdef LIBART - ArtVpath *vpath; - - GetBezierPath(arc->render_shape, wi->work_pts); - p_list = (ZnPoint *) ZnListArray(wi->work_pts); - num_p = ZnListSize(wi->work_pts); - p_list = &p_list[num_p-1]; - vpath = (ArtVpath *) ZnMalloc((num_p+2) * sizeof(ArtVpath)); - for (i = 0; i < num_p; i++, p_list--) { - vpath[i].code = ART_LINETO; - vpath[i].x = p_list->x; - vpath[i].y = p_list->y; - } - vpath[0].code = ART_MOVETO; - vpath[i].code = ART_LINETO; - vpath[i].x = vpath[0].x; - vpath[i].y = vpath[0].y; - i++; - vpath[i].code = ART_END; - - if (arc->fill_svp) { - art_svp_free(arc->fill_svp); - arc->fill_svp = NULL; + if (!ZnGradientFlat(arc->fill_color)) { + if (!arc->grad_geo) { + arc->grad_geo = ZnMalloc(4*sizeof(ZnPoint)); } - if (ISSET(arc->flags, FILLED_BIT)) { - arc->fill_svp = art_svp_from_vpath(vpath); + if (arc->fill_color->type == ZN_AXIAL_GRADIENT) { + int angle = arc->fill_color->g.angle; + ZnTransfo *transfo1, *transfo2; + ZnPoint p[4], p1[4]; + ZnBBox bbox; + + transfo1 = ZnTransfoNew(); + transfo2 = ZnTransfoNew(); + ZnRotateDeg(transfo1, angle); + ZnRotateDeg(transfo2, -angle); + p[0] = arc->coords[0]; + p[2] = arc->coords[1]; + p[1].x = p[2].x; + p[1].y = p[0].y; + p[3].x = p[0].x; + p[3].y = p[2].y; + ZnTransformPoints(transfo1, p, p1, 4); + ResetBBox(&bbox); + AddPointsToBBox(&bbox, p1, 4); + p1[0] = bbox.orig; + p1[2] = bbox.corner; + p1[1].x = p1[2].x; + p1[1].y = p1[0].y; + p1[3].x = p1[0].x; + p1[3].y = p1[2].y; + ZnTransfoSetIdentity(transfo1); + ZnTransfoCompose(transfo1, transfo2, wi->current_transfo); + ZnTransformPoints(transfo1, p1, arc->grad_geo, 4); + ZnTransfoFree(transfo1); + ZnTransfoFree(transfo2); } - if (arc->outline_svp) { - art_svp_free(arc->outline_svp); - arc->outline_svp = NULL; + else if (arc->fill_color->type == ZN_RADIAL_GRADIENT) { + ZnReal dist, new, x0, x, y0, y; + + ZnTransformPoint(wi->current_transfo, &arc->fill_color->g.p, &arc->grad_geo[0]); + x0 = arc->grad_geo[0].x; + y0 = arc->grad_geo[0].y; + dist = 0.0; + p_list = ZnListArray(arc->render_shape); + num_p = ZnListSize(arc->render_shape); + for (i = 0; i < num_p; i++, p_list++) { + x = p_list->x; + y = p_list->y; + new = (x-x0)*(x-x0) + (y-y0)*(y-y0); + if (new > dist) { + dist = new; + } + } + arc->grad_geo[1].x = sqrt(dist) + 2; /* Max radius plus a fuzz factor */ } - if (arc->line_width) { - arc->outline_svp = art_svp_vpath_stroke(vpath, - ART_PATH_STROKE_JOIN_ROUND, - ART_PATH_STROKE_CAP_ROUND, - arc->line_width, 2, 1); + } + else { + if (arc->grad_geo) { + ZnFree(arc->grad_geo); + arc->grad_geo = NULL; } - ZnFree(vpath); -#endif } + return; } @@ -749,7 +754,6 @@ ToArea(Item item, ZnBool report) { ArcItem arc = (ArcItem) item; - WidgetInfo *wi = item->wi; ZnPoint *points; ZnPoint pts[20]; /* Should be at least LINE_END_POINTS large */ ZnPoint center, tang; @@ -761,9 +765,8 @@ ToArea(Item item, if (ISSET(arc->flags, USING_POLY_BIT) && (ISSET(arc->flags, FILLED_BIT) || (arc->line_width))) { - GetBezierPath(arc->render_shape, wi->work_pts); - points = (ZnPoint *) ZnListArray(wi->work_pts); - num_points = ZnListSize(wi->work_pts); + points = ZnListArray(arc->render_shape); + num_points = ZnListSize(arc->render_shape); if (ISSET(arc->flags, FILLED_BIT)) { result = PolygonInBBox(points, num_points, area, NULL); @@ -1039,16 +1042,15 @@ Draw(Item item) if (ISSET(arc->flags, USING_POLY_BIT) && (ISSET(arc->flags, FILLED_BIT) || (arc->line_width))) { - GetBezierPath(arc->render_shape, wi->work_pts); - p = (ZnPoint *) ZnListArray(wi->work_pts); - num_points = ZnListSize(wi->work_pts); + p = ZnListArray(arc->render_shape); + num_points = ZnListSize(arc->render_shape); ZnListAssertSize(wi->work_xpts, num_points); - xp = (XPoint *) ZnListArray(wi->work_xpts); + xp = ZnListArray(wi->work_xpts); for (i = 0; i < num_points; i++, p++) { xp[i].x = (short) p->x; xp[i].y = (short) p->y; } - p = (ZnPoint *) ZnListArray(wi->work_pts); + p = ZnListArray(arc->render_shape); } else { width = arc->corner.x - arc->orig.x; @@ -1057,48 +1059,41 @@ Draw(Item item) /* Fill if requested */ if (ISSET(arc->flags, FILLED_BIT)) { - if (!ZnGradientFlat(arc->fill_color)) { - ZnPoly poly; - POLY_CONTOUR1(&poly, p, num_points); - DrawPolygonGradient(wi, arc->fill_color, &poly, - &item->item_bounding_box); + values.foreground = ZnPixel(ZnGetGradientColor(wi->win, + arc->fill_color, + 0.0, NULL)); + values.arc_mode = ISSET(arc->flags, PIE_SLICE_BIT) ? ArcPieSlice : ArcChord; + if (arc->tile != ZnUnspecifiedImage) { /* Fill Tiled */ + Pixmap pmap = GetImagePixmap(wi->win, arc->tile_name, arc->tile, NULL); + values.fill_style = FillTiled; + values.tile = pmap; + values.ts_x_origin = (int) item->item_bounding_box.orig.x; + values.ts_y_origin = (int) item->item_bounding_box.orig.y; + XChangeGC(wi->dpy, wi->gc, + GCTileStipXOrigin|GCTileStipYOrigin|GCFillStyle|GCTile|GCArcMode, + &values); + } + else if (arc->fill_pattern != ZnUnspecifiedPattern) { /* Fill stippled */ + values.fill_style = FillStippled; + values.stipple = arc->fill_pattern; + values.ts_x_origin = (int) item->item_bounding_box.orig.x; + values.ts_y_origin = (int) item->item_bounding_box.orig.y; + XChangeGC(wi->dpy, wi->gc, + GCTileStipXOrigin|GCTileStipYOrigin|GCFillStyle|GCStipple|GCForeground|GCArcMode, + &values); + } + else { /* Fill solid */ + values.fill_style = FillSolid; + XChangeGC(wi->dpy, wi->gc, GCForeground|GCFillStyle|GCArcMode, &values); + } + if (ISSET(arc->flags, USING_POLY_BIT)) { + XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, + xp, num_points, Nonconvex, CoordModeOrigin); } else { - values.foreground = ZnPixel(ZnGetGradientColor(wi->win, - arc->fill_color, 50.0)); - values.arc_mode = ISSET(arc->flags, PIE_SLICE_BIT) ? ArcPieSlice : ArcChord; - if (arc->tile != ZnUnspecifiedImage) { /* Fill Tiled */ - Pixmap pmap = GetImagePixmap(wi->win, arc->tile_name, arc->tile, NULL); - values.fill_style = FillTiled; - values.tile = pmap; - values.ts_x_origin = (int) item->item_bounding_box.orig.x; - values.ts_y_origin = (int) item->item_bounding_box.orig.y; - XChangeGC(wi->dpy, wi->gc, - GCTileStipXOrigin|GCTileStipYOrigin|GCFillStyle|GCTile|GCArcMode, - &values); - } - else if (arc->fill_pattern != ZnUnspecifiedPattern) { /* Fill stippled */ - values.fill_style = FillStippled; - values.stipple = arc->fill_pattern; - values.ts_x_origin = (int) item->item_bounding_box.orig.x; - values.ts_y_origin = (int) item->item_bounding_box.orig.y; - XChangeGC(wi->dpy, wi->gc, - GCTileStipXOrigin|GCTileStipYOrigin|GCFillStyle|GCStipple|GCForeground|GCArcMode, - &values); - } - else { /* Fill solid */ - values.fill_style = FillSolid; - XChangeGC(wi->dpy, wi->gc, GCForeground|GCFillStyle|GCArcMode, &values); - } - if (ISSET(arc->flags, USING_POLY_BIT)) { - XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, - xp, num_points, Convex, CoordModeOrigin); - } - else { - XFillArc(wi->dpy, wi->draw_buffer, wi->gc, - arc->orig.x, arc->orig.y, width, height, - -arc->start_angle*64, -arc->angle_extent*64); - } + XFillArc(wi->dpy, wi->draw_buffer, wi->gc, + arc->orig.x, arc->orig.y, width, height, + -arc->start_angle*64, -arc->angle_extent*64); } } @@ -1110,7 +1105,7 @@ Draw(Item item) XPoint xap[LINE_END_POINTS]; ZnPoint tang; - SetLineStyle(wi->dpy, wi->gc, arc->line_style); + SetLineStyle(wi, arc->line_style); values.foreground = ZnPixel(arc->line_color); values.line_width = (arc->line_width == 1) ? 0 : arc->line_width; values.cap_style = CapRound; @@ -1130,11 +1125,6 @@ Draw(Item item) if (ISSET(arc->flags, USING_POLY_BIT)) { XDrawLines(wi->dpy, wi->draw_buffer, wi->gc, xp, num_points, CoordModeOrigin); - if (ISSET(arc->flags, CLOSED_BIT) && ISSET(arc->flags, PIE_SLICE_BIT)) { - XDrawLine(wi->dpy, wi->draw_buffer, wi->gc, - xp[num_points-1].x, xp[num_points-1].y, - xp[0].x, xp[0].y); - } if (ISSET(arc->flags, FIRST_END_OK)) { p = (ZnPoint *) ZnListArray(arc->render_shape); GetLineEnd(p, p+1, arc->line_width, CapRound, @@ -1217,29 +1207,104 @@ Draw(Item item) * ********************************************************************************** */ +#ifdef GLX +static void +ArcRenderCB(void *closure) +{ + Item item = (Item) closure; + ArcItem arc = (ArcItem) item; + int num_points=0, i; + ZnPoint *p=NULL; + ZnPoint center; + + center.x = (item->item_bounding_box.corner.x + item->item_bounding_box.orig.x) / 2.0; + center.y = (item->item_bounding_box.corner.y + item->item_bounding_box.orig.y) / 2.0; + p = ZnListArray(arc->render_shape); + num_points = ZnListSize(arc->render_shape); + glBegin(GL_TRIANGLE_FAN); + glVertex2f(center.x, center.y); + for (i = 0; i < num_points; i++) { + glVertex2f(p[i].x, p[i].y); + } + glEnd(); +} +#endif static void Render(Item item) { -#ifdef LIBART +#ifdef GLX WidgetInfo *wi = item->wi; ArcItem arc = (ArcItem) item; - XColor *color = ZnGetGradientColor(wi->win, arc->fill_color, 50.0); - ArtPixBuf *pixbuf = NULL; + int num_points=0, i; + ZnPoint *p=NULL; + XColor *color; + int alpha; - if (arc->fill_svp != NULL) { - if (strlen(arc->tile_name) != 0) { - pixbuf = GetImagePixbuf(wi->win, arc->tile_name, arc->tile); - } + if (ISCLEAR(arc->flags, FILLED_BIT) && !arc->line_width) { + return; + } + + /* Fill if requested */ + if (ISSET(arc->flags, FILLED_BIT)) { + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - ITEM_P.RenderSVP(wi, arc->fill_svp, color->red, color->green, - color->blue, arc->fill_alpha & 0xff, - item->item_bounding_box.orig.x, - item->item_bounding_box.orig.y, pixbuf); + if (!ZnGradientFlat(arc->fill_color)) { + RenderGradient(wi, arc->fill_color, ArcRenderCB, arc, arc->grad_geo); + } + else if (arc->tile != ZnUnspecifiedImage) { /* Fill tiled */ + RenderTile(wi, GetImageTexture(wi->win, arc->tile_name, arc->tile), + arc->fill_color, ArcRenderCB, arc, (ZnPoint *) &item->item_bounding_box); + } + else { + if (arc->fill_pattern != ZnUnspecifiedPattern) { /* Fill stippled */ + /* + * Setup polygon stippling. + */ + glEnable(GL_POLYGON_STIPPLE); + glPolygonStipple(GetBitmapMask(wi->dpy, arc->fill_pattern)->pixels); + } + color = ZnGetGradientColor(wi->win, arc->fill_color, 0.0, &alpha); + glColor4us(color->red, color->green, color->blue, alpha*65535/100); + ArcRenderCB(arc); + glDisable(GL_POLYGON_STIPPLE); + } } - if (arc->outline_svp != NULL) { - ITEM_P.RenderSVP(wi, arc->outline_svp, arc->line_color->red, - arc->line_color->green, arc->line_color->blue, - arc->line_alpha & 0xff, 0, 0, NULL); + + /* + * Draw the arc. + */ + if (arc->line_width) { + p = ZnListArray(arc->render_shape); + num_points = ZnListSize(arc->render_shape); + glColor4us(arc->line_color->red, arc->line_color->green, + arc->line_color->blue, arc->line_alpha*65535/100); + if ((arc->line_width <= wi->max_line_width) && + (arc->line_width <= wi->max_point_width)) { + glLineWidth(arc->line_width); + SetLineStyle(wi, arc->line_style); + + if (ISSET(arc->flags, CLOSED_BIT)) { + glBegin(GL_LINE_LOOP); + } + else { + glBegin(GL_LINE_STRIP); + } + for (i = 0; i < num_points; i++) { + glVertex2f(p[i].x, p[i].y); + } + glEnd(); + } + else { + double (*gl_pts)[3]; + + ZnListAssertSize(wi->work_doubles, (num_points+3)*3); + gl_pts = ZnListArray(wi->work_doubles); + for (i = 1; i <= num_points; i++, p++) { + gl_pts[i][0] = p->x; + gl_pts[i][1] = p->y; + gl_pts[i][1] = 0; + } + } } #endif } @@ -1276,7 +1341,6 @@ Pick(Item item, Item *a_item, int *a_part) { - WidgetInfo *wi = item->wi; ArcItem arc = (ArcItem) item; double dist = 1e40, new_dist; ZnBool point_in_angle, filled, closed; @@ -1290,9 +1354,8 @@ Pick(Item item, if (ISSET(arc->flags, USING_POLY_BIT) && (ISSET(arc->flags, FILLED_BIT) || (arc->line_width))) { - GetBezierPath(arc->render_shape, wi->work_pts); - points = (ZnPoint *) ZnListArray(wi->work_pts); - num_points = ZnListSize(wi->work_pts); + points = ZnListArray(arc->render_shape); + num_points = ZnListSize(arc->render_shape); if (ISSET(arc->flags, FILLED_BIT)) { dist = PolygonToPointDist(points, num_points, p); @@ -1306,12 +1369,6 @@ Pick(Item item, if (new_dist < dist) { dist = new_dist; } - if (ISSET(arc->flags, CLOSED_BIT) && ISSET(arc->flags, PIE_SLICE_BIT)) { - new_dist = LineToPointDist(&points[num_points-1], &points[0], p); - if (new_dist < dist) { - dist = new_dist; - } - } if (dist <= 0.0) { return 0.0; } @@ -1556,7 +1613,6 @@ static ZnBool GetClipVertices(Item item, ZnPoly *poly) { - WidgetInfo *wi = item->wi; ArcItem arc = (ArcItem) item; ZnReal ox, oy, width_2, height_2; int i, num_p; @@ -1566,26 +1622,24 @@ GetClipVertices(Item item, if (!arc->render_shape) { arc->render_shape = ZnListNew(4, sizeof(ZnPoint)); } - GetArcPath(DegreesToRadian(arc->start_angle), - DegreesToRadian(arc->start_angle+arc->angle_extent), - (ISCLEAR(arc->flags, CLOSED_BIT) ? 0 : - ISCLEAR(arc->flags, PIE_SLICE_BIT) ? 1 : 2), arc->render_shape); + p_list = GetCirclePoints((ISCLEAR(arc->flags, CLOSED_BIT) ? 0 : + ISCLEAR(arc->flags, PIE_SLICE_BIT) ? 1 : 2), + ZN_CIRCLE_FINEST, + DegreesToRadian(arc->start_angle), + DegreesToRadian(arc->start_angle+arc->angle_extent), + &num_p, arc->render_shape); ox = (arc->corner.x + arc->orig.x) / 2.0; oy = (arc->corner.y + arc->orig.y) / 2.0; width_2 = (arc->corner.x - arc->orig.x) / 2.0; height_2 = (arc->corner.y - arc->orig.y) / 2.0; - num_p = ZnListSize(arc->render_shape); - p_list = (ZnPoint *) ZnListArray(arc->render_shape); for (i = 0; i < num_p; i++, p_list++) { p_list->x = ox + p_list->x*width_2; p_list->y = oy + p_list->y*height_2; } SET(arc->flags, USING_POLY_BIT); } - GetBezierPath(arc->render_shape, wi->work_pts); - - POLY_CONTOUR1(poly, (ZnPoint *) ZnListArray(wi->work_pts), - ZnListSize(wi->work_pts)); + POLY_CONTOUR1(poly, ZnListArray(arc->render_shape), + ZnListSize(arc->render_shape)); return False; } |