diff options
-rw-r--r-- | generic/Arc.c | 170 |
1 files changed, 108 insertions, 62 deletions
diff --git a/generic/Arc.c b/generic/Arc.c index ea0f057..de11259 100644 --- a/generic/Arc.c +++ b/generic/Arc.c @@ -27,7 +27,6 @@ */ -#include <alloca.h> #include <malloc.h> #include "Item.h" @@ -51,6 +50,7 @@ static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " #define FIRST_END_OK 1<<3 #define LAST_END_OK 1<<4 +#define USING_POLY_BIT 1<<5 static double Pick(Item item, ZnPoint *p, Item start_item, int aperture, @@ -73,12 +73,13 @@ typedef struct _ArcItemStruct { int angle_extent; Pixmap line_pattern; Pixmap fill_pattern; - ZnColor fill_color; + ZnColorGradient fill_color; + ZnGradientGeom grad_geom; ZnColor line_color; int line_width; LineStyle line_style; - LineEnd first_end; - LineEnd last_end; + ZnLineEnd first_end; + ZnLineEnd last_end; char *tile_name; unsigned char flags; @@ -103,7 +104,7 @@ 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_COLOR, "-fillcolor", NULL, + { ZN_CONFIG_GRADIENT_COLOR, "-fillcolor", NULL, Tk_Offset(ArcItemStruct, fill_color), 0, ZN_DRAW_FLAG, False }, { ZN_CONFIG_BOOL, "-filled", NULL, Tk_Offset(ArcItemStruct, flags), FILLED_BIT, ZN_COORDS_FLAG, False }, @@ -111,6 +112,8 @@ static ZnAttrConfig arc_attrs[] = { Tk_Offset(ArcItemStruct, fill_pattern), 0, ZN_DRAW_FLAG, False }, { ZN_CONFIG_LINE_END, "-firstend", NULL, Tk_Offset(ArcItemStruct, first_end), 0, ZN_COORDS_FLAG, False }, + { ZN_CONFIG_GRADIENT_GEOM, "-gradient", NULL, + Tk_Offset(ArcItemStruct, grad_geom), 0, ZN_COORDS_FLAG, False }, { ZN_CONFIG_LINE_END, "-lastend", NULL, Tk_Offset(ArcItemStruct, last_end), 0, ZN_COORDS_FLAG, False }, { ZN_CONFIG_COLOR, "-linecolor", NULL, @@ -200,6 +203,7 @@ Init(Item item, CLEAR(arc->flags, FILLED_BIT); CLEAR(arc->flags, CLOSED_BIT); CLEAR(arc->flags, PIE_SLICE_BIT); + CLEAR(arc->flags, USING_POLY_BIT); arc->line_pattern = ZnUnspecifiedPattern; arc->fill_pattern = ZnUnspecifiedPattern; arc->line_style = LINE_SIMPLE; @@ -250,8 +254,10 @@ Init(Item item, } #endif - arc->fill_color = ZnGetColorByValue(wi->win, wi->fore_color); + arc->fill_color = ZnGetColorGradient(wi->interp, wi->win, + ZnNameOfColor(wi->fore_color)); arc->line_color = ZnGetColorByValue(wi->win, wi->fore_color); + arc->grad_geom = NULL; return ZN_OK; } @@ -293,10 +299,11 @@ Clone(Item item) Tk_NameOfBitmap(wi->dpy, arc->fill_pattern)); } arc->line_color = ZnGetColorByValue(wi->win, arc->line_color); - arc->fill_color = ZnGetColorByValue(wi->win, arc->fill_color); - if (arc->render_shape) { - arc->render_shape = ZnListDuplicate(arc->render_shape); + arc->fill_color = ZnGetColorGradientByValue(arc->fill_color); + if (arc->grad_geom) { + arc->grad_geom = GradientGeomDuplicate(arc->grad_geom); } + arc->render_shape = NULL; } @@ -335,8 +342,11 @@ Destroy(Item item) if (arc->fill_pattern != ZnUnspecifiedPattern) { Tk_FreeBitmap(wi->dpy, arc->fill_pattern); } - ZnFreeColor(arc->fill_color); + ZnFreeColorGradient(arc->fill_color); ZnFreeColor(arc->line_color); + if (arc->grad_geom) { + GradientGeomDelete(arc->grad_geom); + } } @@ -520,12 +530,14 @@ ComputeCoordinates(Item item, } /* - * Special casing for rotation and/or relief. - * This could eventually be the only code but it has to - * good results and be fast enough. + * Special casing for ellipse rotation and gradient. */ ZnTransfoDecompose(wi->current_transfo, NULL, NULL, &angle, NULL); - if (angle >= PRECISION_LIMIT) { + width_2 = (arc->coords[1].x - arc->coords[0].x)/2.0; + height_2 = (arc->coords[1].y - arc->coords[0].y)/2.0; + if (((angle >= PRECISION_LIMIT) && ((width_2 - height_2) > PRECISION_LIMIT)) || + arc->grad_geom) { + SET(arc->flags, USING_POLY_BIT); if (!arc->render_shape) { arc->render_shape = ZnListNew(4, sizeof(ZnPoint)); } @@ -535,8 +547,6 @@ ComputeCoordinates(Item item, ISCLEAR(arc->flags, PIE_SLICE_BIT) ? 1 : 2), arc->render_shape); p_list = (ZnPoint *) ZnListArray(arc->render_shape); num_p = ZnListSize(arc->render_shape); - width_2 = (arc->coords[1].x - arc->coords[0].x)/2.0; - height_2 = (arc->coords[1].y - arc->coords[0].y)/2.0; ox = (arc->coords[1].x + arc->coords[0].x)/2.0; oy = (arc->coords[1].y + arc->coords[0].y)/2.0; for (i = 0; i < num_p; i++, p_list++) { @@ -555,7 +565,6 @@ ComputeCoordinates(Item item, /* * Add the arrows if any. */ - p_list = (ZnPoint *) ZnListArray(arc->render_shape); if (ISSET(arc->flags, FIRST_END_OK)) { GetLineEnd(p_list, p_list+1, arc->line_width, CapRound, arc->first_end, end_points); @@ -571,13 +580,10 @@ ComputeCoordinates(Item item, /* ******* ******** ********** - * This part is for X drawn arcs: not rotated, without relief. + * This part is for X drawn arcs: not rotated. ******* ******** ********** */ - if (arc->render_shape) { - ZnListFree(arc->render_shape); - arc->render_shape = NULL; - } + CLEAR(arc->flags, USING_POLY_BIT); ZnTransformPoint(wi->current_transfo, &arc->coords[0], &arc->orig); ZnTransformPoint(wi->current_transfo, &arc->coords[1], &arc->corner); @@ -720,7 +726,7 @@ ToArea(Item item, ZnReal rx, ry, angle, tmp; ZnBool inside, new_inside; - if (arc->render_shape && + 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); @@ -775,7 +781,7 @@ ToArea(Item item, /* ******* ******** ********** - * The rest of this code deal with non rotated or relief arcs. * + * The rest of this code deal with non rotated arcs. * * It has been stolen from tkCanvArc.c * ******* ******** ********** */ @@ -998,16 +1004,18 @@ Draw(Item item) XPoint *xp; int num_points, i; - if (arc->render_shape && + 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); - xp = (XPoint *) alloca(num_points*sizeof(XPoint)); + ZnListAssertSize(wi->work_xpts, num_points); + xp = (XPoint *) 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); } else { width = arc->corner.x - arc->orig.x; @@ -1016,39 +1024,45 @@ Draw(Item item) /* Fill if requested */ if (ISSET(arc->flags, FILLED_BIT)) { - values.foreground = ZnPixel(arc->fill_color); - 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 (arc->render_shape) { - XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, - xp, num_points, Convex, CoordModeOrigin); + if (arc->grad_geom) { + DrawPolygonGradient(wi, arc->grad_geom, arc->fill_color, p, num_points, + &item->item_bounding_box); } 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); + values.foreground = ZnPixel(ZnColorGradientMidColor(wi->win, arc->fill_color)); + 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); + } } } @@ -1077,7 +1091,7 @@ Draw(Item item) GCFillStyle|GCStipple|GCLineWidth|GCCapStyle|GCJoinStyle|GCForeground, &values); } - if (arc->render_shape) { + 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)) { @@ -1203,7 +1217,7 @@ Pick(Item item, int width, height; ZnDim lw = arc->line_width; - if (arc->render_shape && + 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); @@ -1472,11 +1486,43 @@ GetClipVertices(Item item, ZnPoint **points, int *num_points) { + WidgetInfo *wi = item->wi; + ArcItem arc = (ArcItem) item; + ZnReal ox, oy, width_2, height_2; + int i, num_p; + ZnPoint *p_list; + /* - * Not yet implemented. + * Il n'est pas possible de faire GetArcPath ici on ne dispose + * pas de la transfo pour recaler ou alors il faut faire + * avec les coins transformés. */ - *num_points = 0; - return True; + if (ISCLEAR(arc->flags, USING_POLY_BIT)) { + 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); + 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); + + *points = (ZnPoint *) ZnListArray(wi->work_pts); + *num_points = ZnListSize(wi->work_pts); + + return False; } |