aboutsummaryrefslogtreecommitdiff
path: root/generic/Arc.c
diff options
context:
space:
mode:
authorlecoanet2000-03-23 14:21:02 +0000
committerlecoanet2000-03-23 14:21:02 +0000
commit9c8d2c38d3356f61838ac0f2ed83a1a835f11c37 (patch)
tree827978dba66d52c0d62a53477509adcc71a7e4f3 /generic/Arc.c
parent70459a89b33623d482a122baceed7d8def7b849a (diff)
downloadtkzinc-9c8d2c38d3356f61838ac0f2ed83a1a835f11c37.zip
tkzinc-9c8d2c38d3356f61838ac0f2ed83a1a835f11c37.tar.gz
tkzinc-9c8d2c38d3356f61838ac0f2ed83a1a835f11c37.tar.bz2
tkzinc-9c8d2c38d3356f61838ac0f2ed83a1a835f11c37.tar.xz
R�alisation des d�grad�s et du clipping par un arc.
Diffstat (limited to 'generic/Arc.c')
-rw-r--r--generic/Arc.c170
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;
}