aboutsummaryrefslogtreecommitdiff
path: root/generic/Curve.c
diff options
context:
space:
mode:
authorlecoanet2002-11-05 10:04:55 +0000
committerlecoanet2002-11-05 10:04:55 +0000
commitb9d2768e801e670ad2816b5d0fb9fe7393c49fcb (patch)
treeecf95344d89dfd45820a9e6a1805ada13b26d3f1 /generic/Curve.c
parent9961760cd467172ca3e4f5e876900392d3e78afd (diff)
downloadtkzinc-b9d2768e801e670ad2816b5d0fb9fe7393c49fcb.zip
tkzinc-b9d2768e801e670ad2816b5d0fb9fe7393c49fcb.tar.gz
tkzinc-b9d2768e801e670ad2816b5d0fb9fe7393c49fcb.tar.bz2
tkzinc-b9d2768e801e670ad2816b5d0fb9fe7393c49fcb.tar.xz
* (Coords): Correction de warnings sans objet.
Suppression de GPC et remplacement par le tesselateur GLU. Support des paths et de la nouvelle gestion des contours.
Diffstat (limited to 'generic/Curve.c')
-rw-r--r--generic/Curve.c1014
1 files changed, 633 insertions, 381 deletions
diff --git a/generic/Curve.c b/generic/Curve.c
index a31210f..ee50dcd 100644
--- a/generic/Curve.c
+++ b/generic/Curve.c
@@ -34,9 +34,7 @@
#include "WidgetInfo.h"
#include "Image.h"
#include "Color.h"
-#ifdef GPC
-#include "gpc/gpc.h"
-#endif
+#include "tkZinc.h"
#include <ctype.h>
#include <malloc.h>
@@ -53,8 +51,7 @@ static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ "
#define MARKED_BIT 1<<1 /* If the vertices are marked by a symbol */
#define CLOSED_BIT 1<<2 /* If the outline should be closed automatically */
#define SMOOTH_RELIEF_BIT 1<<3 /* If the relief should be continuous (arc) or discrete (angle) */
-#define REDUCED_BIT 1<<5 /* Tell if the contours are in the most reduced
- * form. */
+
#define FIRST_END_OK 1<<6
#define LAST_END_OK 1<<7
#define FILLED_OK 1<<8
@@ -91,7 +88,7 @@ typedef struct _CurveItemStruct {
ZnImage tile;
/* Private data */
- ZnPoly dev_shape;
+ ZnPoly outlines;
ZnGradient *gradient;
ZnTriStrip tristrip;
ZnPoint *grad_geo;
@@ -176,12 +173,11 @@ Init(Item item,
{
WidgetInfo *wi = item->wi;
CurveItem cv = (CurveItem) item;
- Tcl_Obj **elems;
- int i, num_elems;
+ int i, num_points, count;
ZnPoint *p, *points;
- double dbl;
+ char *controls;
- POLY_INIT(&cv->dev_shape);
+ cv->outlines.num_contours = 0;
cv->tristrip.num_strips = 0;
cv->gradient = NULL;
cv->grad_geo = NULL;
@@ -194,7 +190,6 @@ Init(Item item,
SET(item->flags, COMPOSE_SCALE_BIT);
CLEAR(cv->flags, CLOSED_BIT);
CLEAR(cv->flags, SMOOTH_RELIEF_BIT);
- SET(cv->flags, REDUCED_BIT);
item->priority = DEFAULT_CURVE_PRIORITY;
@@ -202,31 +197,46 @@ Init(Item item,
Tcl_AppendResult(wi->interp, " curve coords expected", NULL);
return ZN_ERROR;
}
- if ((Tcl_ListObjGetElements(wi->interp, (*args)[0], &num_elems, &elems) == ZN_ERROR) ||
- ((num_elems % 2) != 0)) {
- cv_error:
- Tcl_AppendResult(wi->interp, " malformed curve coords", NULL);
+ if (ZnParseCoordList(wi, (*args)[0], &points, &controls, &num_points) == ZN_ERROR) {
return ZN_ERROR;
}
- if (num_elems == 0) {
+ if (num_points == 0) {
POLY_INIT(&cv->shape);
}
else {
- p = points = (ZnPoint *) ZnMalloc(num_elems/2 * sizeof(ZnPoint));
- POLY_CONTOUR1(&cv->shape, points, num_elems/2);
- for (i = 0; i < num_elems; i += 2, p++) {
- if (Tcl_GetDoubleFromObj(wi->interp, elems[i], &dbl) == ZN_ERROR) {
- cv_error2:
- POLY_FREE(&cv->shape);
- goto cv_error;
+ /*
+ * Scan the control array (if any) to detect malformed
+ * curves (more than 2 consecutive control points).
+ */
+ if (controls) {
+ count = 0;
+ if ((controls[0]) || (controls[num_points-1])) {
+ goto control_err;
}
- p->x = dbl;
- if (Tcl_GetDoubleFromObj(wi->interp, elems[i+1], &dbl) == ZN_ERROR) {
- goto cv_error2;
+ for (i = 1; i < num_points-1; i++) {
+ switch (controls[i]) {
+ case 'c':
+ count++;
+ if (count > 2) {
+ goto control_err;
+ }
+ break;
+ case 0:
+ count = 0;
+ break;
+ default:
+ control_err:
+ ZnFree(controls);
+ Tcl_AppendResult(wi->interp, " curve coords expected", NULL);
+ return ZN_ERROR;
+ }
}
- p->y = dbl;
}
+ p = ZnMalloc(num_points * sizeof(ZnPoint));
+ memcpy(p, points, num_points * sizeof(ZnPoint));
+ POLY_CONTOUR1(&cv->shape, p, num_points);
+ cv->shape.contours[0].controls = controls;
}
(*args)++;
(*argc)--;
@@ -270,9 +280,6 @@ Clone(Item item)
CurveItem cv = (CurveItem) item;
int i;
ZnContour *conts;
- ZnBool *holes;
-
- POLY_INIT(&cv->dev_shape);
if (cv->grad_geo) {
ZnPoint *grad_geo = ZnMalloc(4*sizeof(ZnPoint));
@@ -282,21 +289,20 @@ Clone(Item item)
if (cv->shape.num_contours) {
conts = cv->shape.contours;
- holes = cv->shape.holes;
if (cv->shape.contours != &cv->shape.contour1) {
cv->shape.contours = (ZnContour *) ZnMalloc(cv->shape.num_contours*sizeof(ZnContour));
- if (cv->shape.holes) {
- cv->shape.holes = (ZnBool *) ZnMalloc(cv->shape.num_contours*sizeof(ZnBool));
- }
}
for (i = 0; i < cv->shape.num_contours; i++) {
- if (cv->shape.holes) {
- cv->shape.holes[i] = holes[i];
- }
cv->shape.contours[i].num_points = conts[i].num_points;
- cv->shape.contours[i].points = (ZnPoint *) ZnMalloc(conts[i].num_points*sizeof(ZnPoint));
+ cv->shape.contours[i].points = ZnMalloc(conts[i].num_points*sizeof(ZnPoint));
memcpy(cv->shape.contours[i].points, conts[i].points,
conts[i].num_points*sizeof(ZnPoint));
+ cv->shape.contours[i].controls = NULL;
+ if (conts[i].controls) {
+ cv->shape.contours[i].controls = ZnMalloc(conts[i].num_points*sizeof(char));
+ memcpy(cv->shape.contours[i].controls, conts[i].controls,
+ conts[i].num_points*sizeof(char));
+ }
}
}
@@ -325,6 +331,7 @@ Clone(Item item)
cv->fill_color = ZnGetGradientByValue(cv->fill_color);
cv->marker_color = ZnGetGradientByValue(cv->marker_color);
cv->tristrip.num_strips = 0;
+ cv->outlines.num_contours = 0;
}
@@ -339,14 +346,22 @@ static void
Destroy(Item item)
{
CurveItem cv = (CurveItem) item;
+ int i;
+ /*
+ * Need to free the control array here, it is only known
+ * by the Curve code.
+ */
+ for (i = 0; i < cv->shape.num_contours; i++) {
+ if (cv->shape.contours[i].controls) {
+ ZnFree(cv->shape.contours[i].controls);
+ }
+ }
POLY_FREE(&cv->shape);
+
if (cv->grad_geo) {
ZnFree(cv->grad_geo);
}
- cv->dev_shape.holes = NULL;
- POLY_FREE(&cv->dev_shape);
-
if (cv->first_end) {
LineEndDelete(cv->first_end);
}
@@ -379,6 +394,9 @@ Destroy(Item item)
if (cv->tristrip.num_strips) {
TRI_FREE(&cv->tristrip);
}
+ if (cv->outlines.num_contours) {
+ POLY_FREE(&cv->outlines);
+ }
}
@@ -479,72 +497,202 @@ Query(Item item,
}
-static ZnBool
-TestCCW(ZnPoint *points,
- int num_points)
+static void
+CurveTessBegin(GLenum type,
+ void *data)
{
- ZnPoint *p, *p_p, *p_n, min;
- ZnReal xprod;
- int i, min_index;
-
- if (num_points < 3) {
- return True;
+ CurveItem cv = data;
+ WidgetInfo *wi = ((Item) data)->wi;
+
+ ZnListEmpty(wi->work_pts);
+ wi->tess_type = type;
+ if (type == GL_LINE_LOOP) {
+ cv->outlines.num_contours++;
+ cv->outlines.contours = ZnRealloc(cv->outlines.contours,
+ cv->outlines.num_contours * sizeof(ZnContour));
}
+ else {
+ cv->tristrip.num_strips++;
+ cv->tristrip.strips = ZnRealloc(cv->tristrip.strips,
+ cv->tristrip.num_strips * sizeof(ZnStrip));
+ cv->tristrip.strips[cv->tristrip.num_strips-1].fan = (type==GL_TRIANGLE_FAN);
+ }
+ /*printf("Début de fragment de type: %s\n",
+ (type == GL_TRIANGLE_FAN) ? "FAN" :
+ (type == GL_TRIANGLE_STRIP) ? "STRIP" :
+ (type == GL_TRIANGLES) ? "TRIANGLES" :
+ (type == GL_LINE_LOOP) ? "LINE LOOP" : "");*/
+}
+static void
+CurveTessVertex(void *vertex_data,
+ void *data)
+{
+ CurveItem cv = data;
+ WidgetInfo *wi = ((Item) data)->wi;
+ ZnPoint p;
+ int size;
+
+ p.x = ((GLdouble *) vertex_data)[0];
+ p.y = ((GLdouble *) vertex_data)[1];
+ /*printf("Sommet en %g %g\n", p.x, p.y);*/
+ size = ZnListSize(wi->work_pts);
+ if ((wi->tess_type == GL_TRIANGLES) && (size == 3)) {
+ cv->tristrip.strips[cv->tristrip.num_strips-1].num_points = size;
+ cv->tristrip.strips[cv->tristrip.num_strips-1].points = ZnMalloc(size * sizeof(ZnPoint));
+ memcpy(cv->tristrip.strips[cv->tristrip.num_strips-1].points,
+ ZnListArray(wi->work_pts), size * sizeof(ZnPoint));
+
+ /* Allocate a new fragment */
+ ZnListEmpty(wi->work_pts);
+ cv->tristrip.num_strips++;
+ cv->tristrip.strips = ZnRealloc(cv->tristrip.strips,
+ cv->tristrip.num_strips * sizeof(ZnStrip));
+ cv->tristrip.strips[cv->tristrip.num_strips-1].fan = GL_TRIANGLES;
+ }
+ ZnListAdd(wi->work_pts, &p, ZnListTail);
+}
+static void
+CurveTessEnd(void *data)
+{
+ CurveItem cv = data;
+ WidgetInfo *wi = ((Item) data)->wi;
+ int size = ZnListSize(wi->work_pts);
+ int num;
+
+ if (wi->tess_type == GL_LINE_LOOP) {
+ /* Add the last point to close the outline */
+ size++;
+ num = cv->outlines.num_contours;
+ cv->outlines.contours[num-1].num_points = size;
+ cv->outlines.contours[num-1].points = ZnMalloc(size * sizeof(ZnPoint));
+ memcpy(cv->outlines.contours[num-1].points,
+ ZnListArray(wi->work_pts), size * sizeof(ZnPoint));
+ cv->outlines.contours[num-1].points[size-1] = cv->outlines.contours[num-1].points[0];
+ cv->outlines.contours[num-1].cw = !TestCCW(cv->outlines.contours[num-1].points, size);
+ }
+ else {
+ num = cv->tristrip.num_strips;
+ cv->tristrip.strips[num-1].num_points = size;
+ cv->tristrip.strips[num-1].points = ZnMalloc(size * sizeof(ZnPoint));
+ memcpy(cv->tristrip.strips[num-1].points,
+ ZnListArray(wi->work_pts), size * sizeof(ZnPoint));
+ }
+ /* printf("Fin de fragment %d\n", num);*/
+}
+static void
+CurveTessCombine(GLdouble coords[3],
+ void *vertex_data[4],
+ GLfloat weight[4],
+ void **out_data,
+ void *data)
+{
+ WidgetInfo *wi = ((Item) data)->wi;
+ ZnCombineData *cdata;
+
+ cdata = ZnMalloc(sizeof(ZnCombineData));
+ cdata->v[0] = coords[0];
+ cdata->v[1] = coords[1];
+ cdata->next = wi->tess_combine_list;
+ wi->tess_combine_list = cdata;
+ *out_data = &cdata->v;
+ /*printf("Création d'un nouveau sommet en %g %g\n",
+ cdata->v[0], cdata->v[1]);*/
+}
+static void
+CurveTessError(GLenum errno,
+ void *data)
+{
+ const GLubyte *msg;
- /*
- * First find the lowest rightmost vertex. In X11 this is the
- * topmost one.
- */
- p = points;
- min = *p;
- min_index = 0;
- for (i = 1, p++; i < num_points; i++, p++) {
- if ((p->y < min.y) ||
- ((p->y == min.y) && (p->x > min.x))) {
- min_index = i;
- min = *p;
+ msg = gluErrorString(errno);
+ fprintf(stderr, "Tesselation error in curve item: %s\n", msg);
+}
+
+static void
+UpdateTristrip(CurveItem cv,
+ ZnPoly *poly)
+{
+ WidgetInfo *wi = ((Item) cv)->wi;
+ ZnCombineData *cdata, *cnext;
+ GLdouble v[3];
+ int i, j;
+
+ gluTessCallback(wi->tess, GLU_TESS_BEGIN_DATA, (void (*)()) CurveTessBegin);
+ gluTessCallback(wi->tess, GLU_TESS_VERTEX_DATA, (void (*)()) CurveTessVertex);
+ gluTessCallback(wi->tess, GLU_TESS_END_DATA, (void (*)()) CurveTessEnd);
+ gluTessCallback(wi->tess, GLU_TESS_COMBINE_DATA, (void (*)()) CurveTessCombine);
+ gluTessCallback(wi->tess, GLU_TESS_ERROR_DATA, (void (*)()) CurveTessError);
+ gluTessProperty(wi->tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_POSITIVE);
+ gluTessNormal(wi->tess, 0, 0, -1);
+
+ if (cv->tristrip.num_strips == 0) {
+ gluTessProperty(wi->tess, GLU_TESS_BOUNDARY_ONLY, GL_FALSE);
+ gluTessBeginPolygon(wi->tess, cv);
+ for (j = 0; j < poly->num_contours; j++){
+ gluTessBeginContour(wi->tess);
+ /*printf("Début contour %d num_points %d %d\n",
+ j, poly->contours[j].num_points, poly->contours[j].cw);*/
+ for (i = 0; i < poly->contours[j].num_points; i++) {
+ /*printf("%g@%g ", poly->contours[j].points[i].x, poly->contours[j].points[i].y);*/
+ v[0] = poly->contours[j].points[i].x;
+ v[1] = poly->contours[j].points[i].y;
+ v[2] = 0;
+ gluTessVertex(wi->tess, v, &poly->contours[j].points[i]);
+ }
+ /*printf("\n");*/
+ gluTessEndContour(wi->tess);
+ }
+ gluTessEndPolygon(wi->tess);
+ cdata = wi->tess_combine_list;
+ while (cdata) {
+ cnext = cdata->next;
+ ZnFree(cdata);
+ cdata = cnext;
}
+ wi->tess_combine_list = NULL;
}
- /*
- * Then find the indices of the previous and next
- * vertices.
- */
- p = &points[min_index];
- /*printf("min index %d, prev %d, next %d\n", min_index,
- (min_index+(num_points-1))%num_points, (min_index+1)%num_points);*/
- p_p = &points[(min_index+(num_points-1))%num_points]; /* min_index-1 */
- p_n = &points[(min_index+1)%num_points];
- xprod = ((p_p->x*p->y - p_p->y*p->x) +
- (p_p->y*p_n->x - p_p->x*p_n->y) +
- (p->x*p_n->y - p->y*p_n->x));
- return (xprod <= 0.0); /* Should be >= 0 but X11 has Y axis reverted. */
}
-
-/*
- * Create a reduced polygon from an unknown one by
- * adding/clipping all the shapes/holes in turn.
- */
-#ifdef GPC
static void
-ReduceContours(ZnPoly *poly_in,
- ZnPoly *poly_out)
+UpdateOutlines(CurveItem cv,
+ ZnPoly *poly)
{
- int i;
- ZnContour *c;
- ZnBool *hole;
- ZnPoly cpoly, rpoly;
-
- POLY_INIT(poly_out);
- for (i = 0, hole = poly_in->holes, c = poly_in->contours;
- i < poly_in->num_contours; i++, c++, hole++) {
- POLY_CONTOUR1(&cpoly, c->points, c->num_points);
- gpc_polygon_clip(*hole?GPC_DIFF:GPC_UNION, (gpc_polygon *) &poly_out,
- (gpc_polygon *) &cpoly, (gpc_polygon *) &rpoly);
- POLY_SET(poly_out, &rpoly);
+ WidgetInfo *wi = ((Item) cv)->wi;
+ ZnCombineData *cdata, *cnext;
+ GLdouble v[3];
+ int i, j;
+
+ gluTessCallback(wi->tess, GLU_TESS_BEGIN_DATA, (void (*)()) CurveTessBegin);
+ gluTessCallback(wi->tess, GLU_TESS_VERTEX_DATA, (void (*)()) CurveTessVertex);
+ gluTessCallback(wi->tess, GLU_TESS_END_DATA, (void (*)()) CurveTessEnd);
+ gluTessCallback(wi->tess, GLU_TESS_COMBINE_DATA, (void (*)()) CurveTessCombine);
+ gluTessCallback(wi->tess, GLU_TESS_ERROR_DATA, (void (*)()) CurveTessError);
+ gluTessProperty(wi->tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_POSITIVE);
+ gluTessNormal(wi->tess, 0, 0, -1);
+
+ if (cv->outlines.num_contours == 0) {
+ gluTessProperty(wi->tess, GLU_TESS_BOUNDARY_ONLY, GL_TRUE);
+ gluTessBeginPolygon(wi->tess, cv);
+ for (j = 0; j < poly->num_contours; j++){
+ gluTessBeginContour(wi->tess);
+ for (i = 0; i < poly->contours[j].num_points; i++) {
+ v[0] = poly->contours[j].points[i].x;
+ v[1] = poly->contours[j].points[i].y;
+ v[2] = 0;
+ gluTessVertex(wi->tess, v, &poly->contours[j].points[i]);
+ }
+ gluTessEndContour(wi->tess);
+ }
+ gluTessEndPolygon(wi->tess);
+ cdata = wi->tess_combine_list;
+ while (cdata) {
+ cnext = cdata->next;
+ ZnFree(cdata);
+ cdata = cnext;
+ }
+ wi->tess_combine_list = NULL;
}
}
-#endif
/*
@@ -563,33 +711,18 @@ ComputeCoordinates(Item item,
int i, j;
ZnPoint end_points[LINE_END_POINTS];
ZnPoint *points;
- int num_points, num_contours;
+ int num_points, num_contours, segment_start;
ZnBBox bbox;
int lw;
ZnContour *c1, *c2;
- ZnBool *holes, *cw;
-
+ ZnPoly dev;
+
+
ResetBBox(&item->item_bounding_box);
- /*printf("flags %x\n", cv->flags);*/
+ /* printf("Curve CC: flags %x\n", cv->flags);*/
SetRenderFlags(cv);
- /*
- * Try to reduce the contours if needed. This can be
- * switched off and replaced by an explicit reduction.
- */
- if (cv->shape.num_contours == 1) {
- SET(cv->flags, REDUCED_BIT);
- }
- else if (ISCLEAR(cv->flags, REDUCED_BIT)) {
-#ifdef GPC
- ZnPoly poly;
- ReduceContours(&cv->shape, &poly);
- POLY_SET(&cv->shape, &poly);
-#endif
- SET(cv->flags, REDUCED_BIT);
- }
-
num_contours = cv->shape.num_contours;
if (num_contours == 0) {
return;
@@ -598,85 +731,115 @@ ComputeCoordinates(Item item,
if (cv->tristrip.num_strips) {
TRI_FREE(&cv->tristrip);
}
-
- /*
- * Allocate space for devices coordinates, the holes array is _NOT_
- * duplicated.
- */
- cv->dev_shape.holes = NULL;
- POLY_FREE(&cv->dev_shape);
- if (cv->shape.contours != &cv->shape.contour1) {
- cv->dev_shape.contours = (ZnContour *) ZnMalloc(num_contours*sizeof(ZnContour));
+ if (cv->outlines.num_contours) {
+ POLY_FREE(&cv->outlines);
+ };
+
+ POLY_INIT(&dev);
+ if (num_contours != 1) {
+ dev.contours = ZnMalloc(num_contours * sizeof(ZnContour));
+ dev.num_contours = num_contours;
}
else {
- cv->dev_shape.contours = &cv->dev_shape.contour1;
- cv->dev_shape.cw = &cv->dev_shape.cw1;
- }
- cv->dev_shape.holes = cv->shape.holes;
- cv->dev_shape.num_contours = num_contours;
- c1 = cv->shape.contours;
- c2 = cv->dev_shape.contours;
- for (i = 0; i < cv->shape.num_contours; i++, c1++, c2++) {
+ dev.contours = &dev.contour1;
+ dev.num_contours = 1;
+ }
+
+ for (c1 = cv->shape.contours, c2 = dev.contours, i = 0;
+ i < cv->shape.num_contours; i++, c1++, c2++) {
+ c2->cw = c1->cw;
c2->num_points = c1->num_points;
/*
* Add a point at the end of the contour to close it
- * if needed.
+ * if needed. Works only if a single contour is given, in
+ * this case it can be used as a path. In the case of
+ * multiple contours, the outline is automatically
+ * closed by the tesselator.
*/
- if (ISSET(cv->flags, CLOSED_BIT) &&
+ if ((num_contours == 1) &&
+ (c1->num_points > 2) &&
+ ISSET(cv->flags, CLOSED_BIT) &&
((c1->points[0].x != c1->points[c2->num_points-1].x) ||
(c1->points[0].y != c1->points[c2->num_points-1].y)) &&
- (c1->num_points != 1)) {
+ (c1->num_points > 2)) {
c2->num_points++;
}
- c2->points = (ZnPoint *) ZnMalloc((c2->num_points)*sizeof(ZnPoint));
+ c2->points = ZnMalloc((c2->num_points)*sizeof(ZnPoint));
/*printf("CC: \"%d\" num_points %d\n", item->id, c1->num_points);*/
- }
-
- /*
- * Process all points, transforming coordinates.
- */
- c1 = cv->shape.contours;
- c2 = cv->dev_shape.contours;
- for (j = 0; j < num_contours; j++, c1++, c2++) {
- ZnTransformPoints(wi->current_transfo, c1->points, c2->points, c1->num_points);
- /*
- * Close the curve if needed.
- */
+ ZnTransformPoints(wi->current_transfo, c1->points, c2->points, c1->num_points);
if (c1->num_points != c2->num_points) {
c2->points[c2->num_points-1] = c2->points[0];
}
+ /*
+ * Now expand the bezier segments into polylines.
+ */
+ if (c1->controls) {
+ segment_start = 0;
+ ZnListEmpty(wi->work_pts);
+ ZnListAdd(wi->work_pts, &c2->points[0], ZnListTail);
+ /*printf("moveto %g@%g\n", c2->points[0].x, c2->points[0].y);*/
+ for (j = 1; j < c1->num_points; j++) {
+ if (!c1->controls[j]) {
+ if (segment_start != j-1) {
+ /* traitement bezier */
+ /* printf("arcto %g@%g %g@%g %g@%g\n",
+ c2->points[segment_start+1].x, c2->points[segment_start+1].y,
+ c2->points[j-1].x, c2->points[j-1].y,
+ c2->points[j].x, c2->points[j].y);*/
+ GetBezierPoints(&c2->points[segment_start],
+ &c2->points[segment_start+1], &c2->points[j-1],
+ &c2->points[j], wi->work_pts, 2.0);
+ }
+ else {
+ /*printf("lineto %g@%g\n", c2->points[j].x, c2->points[j].y);*/
+ ZnListAdd(wi->work_pts, &c2->points[j], ZnListTail);
+ }
+ segment_start = j;
+ }
+ }
+ /*
+ * Replce the original path by the expanded, closing it as
+ * needed (one open contour).
+ */
+ num_points =ZnListSize(wi->work_pts);
+ if (c2->num_points != c1->num_points) {
+ num_points++;
+ }
+ c2->points = ZnRealloc(c2->points, num_points*sizeof(ZnPoint));
+ memcpy(c2->points, ZnListArray(wi->work_pts), num_points*sizeof(ZnPoint));
+ if (c2->num_points != c1->num_points) {
+ c2->points[num_points-1] = c2->points[0];
+ }
+ c2->num_points = num_points;
+ }
+ }
+
+ UpdateTristrip(cv, &dev);
+ if (num_contours == 1) {
+ POLY_CONTOUR1(&cv->outlines, dev.contours[0].points, dev.contours[0].num_points);
+ cv->outlines.contours[0].cw = dev.contours[0].cw;
+ }
+ else {
+ UpdateOutlines(cv, &dev);
+ POLY_FREE(&dev);
}
lw = cv->line_width;
-
+ num_contours = cv->outlines.num_contours;
if (ISSET(cv->flags, RELIEF_OK)) {
- holes = cv->shape.holes;
- c2 = cv->dev_shape.contours;
- if (!cv->dev_shape.cw) {
- cv->dev_shape.cw = (ZnBool *) ZnMalloc(num_contours*sizeof(ZnBool));
- }
- cw = cv->dev_shape.cw;
- for (j = 0; j < num_contours; j++, c2++, holes++, cw++) {
- num_points = c2->num_points;
- points = c2->points;
- *cw = !TestCCW(points, num_points);
- if (*holes) {
- continue;
- }
+ c2 = cv->outlines.contours;
+ for (i = 0; i < num_contours; i++, c2++) {
/*
* Add to bounding box.
*/
- ZnGetPolygonReliefBBox(points, num_points, (*cw ^ *holes)?-lw:lw, &bbox);
+ ZnGetPolygonReliefBBox(c2->points, c2->num_points, lw, &bbox);
AddBBoxToBBox(&item->item_bounding_box, &bbox);
}
}
else {
- holes = cv->shape.holes;
- c2 = cv->dev_shape.contours;
- for (j = 0; j < num_contours; j++, c2++, holes++) {
- if (!*holes) {
- AddPointsToBBox(&item->item_bounding_box, c2->points, c2->num_points);
- }
+ c2 = cv->outlines.contours;
+ for (i = 0; i < num_contours; i++, c2++) {
+ AddPointsToBBox(&item->item_bounding_box, c2->points, c2->num_points);
}
/*
@@ -692,10 +855,9 @@ ComputeCoordinates(Item item,
/*
* Take care of miters, markers and arrows.
*/
- holes = cv->shape.holes;
- c2 = cv->dev_shape.contours;
- for (j = 0; j < num_contours; j++, c2++, holes++) {
- if (*holes) {
+ c2 = cv->outlines.contours;
+ for (j = 0; j < num_contours; j++, c2++) {
+ if (c2->cw) {
continue;
}
if (cv->join_style == JoinMiter) {
@@ -760,7 +922,7 @@ ComputeCoordinates(Item item,
ZnComputeAxialGradient(wi, &cv->shape, cv->fill_color->g.angle, cv->grad_geo);
}
else if (cv->fill_color->type == ZN_RADIAL_GRADIENT) {
- ZnComputeRadialGradient(wi, &cv->dev_shape, &item->item_bounding_box,
+ ZnComputeRadialGradient(wi, &cv->outlines, &item->item_bounding_box,
&cv->fill_color->g.p, cv->grad_geo);
}
else if (cv->fill_color->type == ZN_PATH_GRADIENT) {
@@ -793,49 +955,56 @@ ToArea(Item item,
CurveItem cv = (CurveItem) item;
ZnBBox bbox, *area = ta->area;
ZnPoint *points;
+ ZnPoint triangle[3];
ZnPoint end_points[LINE_END_POINTS];
- int i, num_points, result=-1, result2;
+ int i, j, num_points, result=-1, result2;
int width, height;
ZnBool first_done = False;
- if (cv->dev_shape.num_contours == 0) {
+ if (cv->outlines.num_contours == 0) {
return -1;
}
/*printf("============== poly %d ==============\n", item->id);*/
if (ISSET(cv->flags, FILLED_OK)) {
- for (i = 0; i < cv->dev_shape.num_contours; i++) {
- ZnBool area_enclosed;
-
- num_points = cv->dev_shape.contours[i].num_points;
- points = cv->dev_shape.contours[i].points;
- if (!first_done) {
- first_done = True;
- result = PolygonInBBox(points, num_points, area, &area_enclosed);
- /*printf("contour %d, result %d, area_enclosed %d\n",
- i, result, area_enclosed);*/
- if (cv->shape.holes[i] && area_enclosed) {
- return -1;
- }
+ /*printf("testing surfaces\n");*/
+ for (i = 0; i < cv->tristrip.num_strips; i++) {
+ num_points = cv->tristrip.strips[i].num_points;
+ points = cv->tristrip.strips[i].points;
+ j = 0;
+ if (cv->tristrip.strips[i].fan) {
+ triangle[0] = points[0];
+ j++;
}
- else {
- result2 = PolygonInBBox(points, num_points, area, &area_enclosed);
- /*printf("contour %d, result %d, area_enclosed %d\n",
- i, result2, area_enclosed);*/
- if (cv->shape.holes[i] && area_enclosed) {
- return -1;
+ for (; j < num_points-2; j++, points++) {
+ if (cv->tristrip.strips[i].fan) {
+ triangle[1] = points[0];
+ triangle[2] = points[1];
}
- if (result2 != result) {
- return 0;
+ else {
+ triangle[0] = points[0];
+ triangle[1] = points[1];
+ triangle[2] = points[2];
+ }
+ if (!first_done) {
+ first_done = True;
+ result = PolygonInBBox(triangle, 3, area, NULL);
+ }
+ else {
+ result2 = PolygonInBBox(triangle, 3, area, NULL);
+ if (result2 != result) {
+ return 0;
+ }
}
}
}
}
if (cv->line_width > 0) {
- for (i = 0; i < cv->dev_shape.num_contours; i++) {
- num_points = cv->dev_shape.contours[i].num_points;
- points = cv->dev_shape.contours[i].points;
+ /*printf("testing lines\n");*/
+ for (i = 0; i < cv->outlines.num_contours; i++) {
+ num_points = cv->outlines.contours[i].num_points;
+ points = cv->outlines.contours[i].points;
if (!first_done) {
first_done = True;
if (ISCLEAR(cv->flags, RELIEF_OK)) {
@@ -843,9 +1012,7 @@ ToArea(Item item,
cv->line_width, cv->cap_style, cv->join_style, area);
}
else {
- result = ZnPolygonReliefInBBox(points, num_points,
- (cv->dev_shape.cw[0]^cv->shape.holes[0])?-cv->line_width:cv->line_width,
- area);
+ result = ZnPolygonReliefInBBox(points, num_points, cv->line_width, area);
}
if (result == 0) {
return 0;
@@ -857,9 +1024,7 @@ ToArea(Item item,
cv->line_width, cv->cap_style, cv->join_style, area);
}
else {
- result2 = ZnPolygonReliefInBBox(points, num_points,
- (cv->dev_shape.cw[0]^cv->shape.holes[0])?-cv->line_width:cv->line_width,
- area);
+ result2 = ZnPolygonReliefInBBox(points, num_points, cv->line_width, area);
}
if (result2 != result) {
return 0;
@@ -870,8 +1035,8 @@ ToArea(Item item,
/*
* Check line ends (only on first contour).
*/
- points = cv->dev_shape.contours[0].points;
- num_points = cv->dev_shape.contours[0].num_points;
+ points = cv->outlines.contours[0].points;
+ num_points = cv->outlines.contours[0].num_points;
if (ISSET(cv->flags, FIRST_END_OK)) {
GetLineEnd(&points[0], &points[1], cv->line_width, cv->cap_style,
cv->first_end, end_points);
@@ -892,9 +1057,9 @@ ToArea(Item item,
* Last, check markers
*/
if (ISSET(cv->flags, MARKER_OK)) {
- for (i = 0; i < cv->dev_shape.num_contours; i++) {
- points = cv->dev_shape.contours[i].points;
- num_points = cv->dev_shape.contours[i].num_points;
+ for (i = 0; i < cv->outlines.num_contours; i++) {
+ points = cv->outlines.contours[i].points;
+ num_points = cv->outlines.contours[i].num_points;
if (ISSET(cv->flags, FIRST_END_OK)) {
num_points--;
@@ -939,7 +1104,7 @@ Draw(Item item)
ZnPoint *points=NULL;
XPoint *xpoints=NULL;
- if ((cv->dev_shape.num_contours == 0) ||
+ if ((cv->outlines.num_contours == 0) ||
(ISCLEAR(cv->flags, FILLED_OK) &&
!cv->line_width &&
ISCLEAR(cv->flags, MARKER_OK))) {
@@ -972,11 +1137,7 @@ Draw(Item item)
}
XChangeGC(wi->dpy, wi->gc, gc_mask, &values);
-#ifdef GPC
- if (cv->tristrip.num_strips == 0) {
- gpc_polygon_to_tristrip((gpc_polygon *) &cv->dev_shape,
- (gpc_tristrip *) &cv->tristrip);
- }
+
for (i = 0; i < cv->tristrip.num_strips; i++) {
num_points = cv->tristrip.strips[i].num_points;
points = cv->tristrip.strips[i].points;
@@ -991,18 +1152,6 @@ Draw(Item item)
&xpoints[j], 3, Convex, CoordModeOrigin);
}
}
-#else
- num_points = cv->dev_shape.contours[0].num_points;
- points = cv->dev_shape.contours[0].points;
- ZnListAssertSize(wi->work_xpts, num_points);
- xpoints = (XPoint *) ZnListArray(wi->work_xpts);
- for (i = 0; i < num_points; i++) {
- xpoints[i].x = REAL_TO_INT(points[i].x);
- xpoints[i].y = REAL_TO_INT(points[i].y);
- }
- XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc,
- xpoints, num_points, Complex, CoordModeOrigin);
-#endif
}
/*
@@ -1011,35 +1160,20 @@ Draw(Item item)
if (cv->line_width) {
ZnPoint end_points[LINE_END_POINTS];
XPoint xp[LINE_END_POINTS];
- ReliefStyle relief;
- int lw, relief_dir;
/*
* Drawing with relief disables: ends, line style and line pattern.
*/
if (ISSET(cv->flags, RELIEF_OK)) {
- for (j = 0; j < cv->dev_shape.num_contours; j++) {
- num_points = cv->dev_shape.contours[j].num_points;
- points = cv->dev_shape.contours[j].points;
- /*printf("Draw: item %d, num_points %d %g@%g %g@%g, holes %d cw %d i/o %d\n",
+ for (j = 0; j < cv->outlines.num_contours; j++) {
+ num_points = cv->outlines.contours[j].num_points;
+ points = cv->outlines.contours[j].points;
+ /*printf("Draw: item %d, num_points %d %g@%g %g@%g, cw %d i/o %d\n",
item->id,
num_points, points[0].x, points[0].y,
- points[num_points-1].x, points[num_points-1].y,cv->shape.holes[j],
- cv->dev_shape.cw[j], cv->dev_shape.cw[j]^cv->shape.holes[j]);*/
- lw = cv->line_width;
- relief = cv->relief;
- relief_dir = relief & RELIEF_MASK;
- if (cv->dev_shape.cw[j]^cv->shape.holes[j]) {
- lw = -lw;
- if (relief_dir == RELIEF_SUNKEN) {
- relief_dir = RELIEF_RAISED;
- }
- else {
- relief_dir = RELIEF_SUNKEN;
- }
- relief = (relief & ~RELIEF_MASK) | relief_dir;
- }
- ZnDrawPolygonRelief(wi, relief, cv->gradient, points, num_points, lw);
+ points[num_points-1].x, points[num_points-1].y,
+ cv->outlines.contours[j].cw);*/
+ ZnDrawPolygonRelief(wi, cv->relief, cv->gradient, points, num_points, cv->line_width);
}
}
else {
@@ -1060,9 +1194,9 @@ Draw(Item item)
GCFillStyle|GCStipple|GCLineWidth|GCJoinStyle|GCCapStyle|GCForeground,
&values);
}
- for (j = 0; j < cv->dev_shape.num_contours; j++) {
- num2 = num_points = cv->dev_shape.contours[j].num_points;
- points = cv->dev_shape.contours[j].points;
+ for (j = 0; j < cv->outlines.num_contours; j++) {
+ num2 = num_points = cv->outlines.contours[j].num_points;
+ points = cv->outlines.contours[j].points;
ZnListAssertSize(wi->work_xpts, num_points);
xpoints = (XPoint *) ZnListArray(wi->work_xpts);
for (i = 0; i < num2; i++) {
@@ -1113,9 +1247,9 @@ Draw(Item item)
values.stipple = ZnImagePixmap(cv->marker, NULL);
values.foreground = ZnPixel(ZnGetGradientColor(cv->marker_color, 0, NULL));
XChangeGC(wi->dpy, wi->gc, GCFillStyle|GCStipple|GCForeground, &values);
- for (j = 0; j < cv->dev_shape.num_contours; j++) {
- num_points = cv->dev_shape.contours[j].num_points;
- points = cv->dev_shape.contours[j].points;
+ for (j = 0; j < cv->outlines.num_contours; j++) {
+ num_points = cv->outlines.contours[j].num_points;
+ points = cv->outlines.contours[j].points;
ZnListAssertSize(wi->work_xpts, num_points);
xpoints = (XPoint *) ZnListArray(wi->work_xpts);
for (i = 0; i < num_points; i++) {
@@ -1152,25 +1286,22 @@ Draw(Item item)
**********************************************************************************
*/
#ifdef GLX
-void
+static void
CurveRenderCB(void *closure)
{
CurveItem cv = (CurveItem) closure;
int i, j, num_points;
ZnPoint *points;
-
-#ifdef GPC
- if (cv->tristrip.num_strips == 0) {
- gpc_polygon_to_tristrip((gpc_polygon *) &cv->dev_shape,
- (gpc_tristrip *) &cv->tristrip);
- }
-#else
-#error "GPC needed to render filled curves with GLX"
-#endif
+
for (i = 0; i < cv->tristrip.num_strips; i++) {
num_points = cv->tristrip.strips[i].num_points;
points = cv->tristrip.strips[i].points;
- glBegin(GL_TRIANGLE_STRIP);
+ if (cv->tristrip.strips[i].fan) {
+ glBegin(GL_TRIANGLE_FAN);
+ }
+ else {
+ glBegin(GL_TRIANGLE_STRIP);
+ }
for (j = 0; j < num_points; j++, points++) {
glVertex2f(points->x, points->y);
}
@@ -1189,7 +1320,7 @@ Render(Item item)
XColor *color;
int alpha;
- if ((cv->dev_shape.num_contours == 0) ||
+ if ((cv->outlines.num_contours == 0) ||
(ISCLEAR(cv->flags, FILLED_OK) &&
!cv->line_width &&
ISCLEAR(cv->flags, MARKER_OK))) {
@@ -1203,7 +1334,7 @@ Render(Item item)
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
if (!ZnGradientFlat(cv->fill_color)) {
ZnRenderGradient(wi, cv->fill_color, CurveRenderCB, cv, cv->grad_geo,
- &cv->dev_shape);
+ &cv->outlines);
}
else if (cv->tile != ZnUnspecifiedImage) { /* Fill tiled */
ZnRenderTile(wi, cv->tile, cv->fill_color, CurveRenderCB, cv,
@@ -1235,43 +1366,26 @@ Render(Item item)
ZnGetGradientColor(cv->line_color, 0, &alpha);
alpha = ZnComposeAlpha(alpha, wi->alpha);
if (ISSET(cv->flags, RELIEF_OK)) {
- ReliefStyle relief;
- ZnDim line_width;
- int relief_dir;
-
- for (j = 0; j < cv->dev_shape.num_contours; j++) {
- num_points = cv->dev_shape.contours[j].num_points;
- points = cv->dev_shape.contours[j].points;
- /*printf("Render: item %d, num_points %d %g@%g %g@%g, holes %d cw %d i/o %d\n",
+ for (j = 0; j < cv->outlines.num_contours; j++) {
+ num_points = cv->outlines.contours[j].num_points;
+ points = cv->outlines.contours[j].points;
+ /*printf("Render: item %d, num_points %d %g@%g %g@%g, cw %d i/o %d\n",
item->id,
num_points, points[0].x, points[0].y,
- points[num_points-1].x, points[num_points-1].y,cv->shape.holes[j],
- cv->dev_shape.cw[j], cv->dev_shape.cw[j]^cv->shape.holes[j]);*/
- relief = cv->relief;
- line_width = cv->line_width;
- relief_dir = relief & RELIEF_MASK;
- if (cv->dev_shape.cw[j]^cv->shape.holes[j]) {
- line_width = -line_width;
- if (relief_dir == RELIEF_SUNKEN) {
- relief_dir = RELIEF_RAISED;
- }
- else {
- relief_dir = RELIEF_SUNKEN;
- }
- relief = (relief & ~RELIEF_MASK) | relief_dir;
- }
- ZnRenderPolygonRelief(wi, relief, cv->gradient, ISSET(cv->flags, SMOOTH_RELIEF_BIT),
- points, num_points, line_width);
+ points[num_points-1].x, points[num_points-1].y,
+ cv->outlines.contours[j].cw);*/
+ ZnRenderPolygonRelief(wi, cv->relief, cv->gradient, ISSET(cv->flags, SMOOTH_RELIEF_BIT),
+ points, num_points, cv->line_width);
}
}
else {
ZnLineEnd first = ISSET(cv->flags, FIRST_END_OK) ? cv->first_end : NULL;
ZnLineEnd last = ISSET(cv->flags, LAST_END_OK) ? cv->last_end : NULL;
- for (j = 0; j < cv->dev_shape.num_contours; j++) {
+ for (j = 0; j < cv->outlines.num_contours; j++) {
ZnRenderPolyline(wi,
- cv->dev_shape.contours[j].points,
- cv->dev_shape.contours[j].num_points,
+ cv->outlines.contours[j].points,
+ cv->outlines.contours[j].num_points,
cv->line_width, cv->line_style, cv->cap_style, cv->join_style,
first, last, cv->line_color);
}
@@ -1289,9 +1403,9 @@ Render(Item item)
ZnSizeOfImage(cv->marker, &h_width, & h_height);
h_width = (h_width+1.0)/2.0;
h_height = (h_height+1.0)/2.0;
- for (j = 0; j < cv->dev_shape.num_contours; j++) {
- num_points = cv->dev_shape.contours[j].num_points;
- points = cv->dev_shape.contours[j].points;
+ for (j = 0; j < cv->outlines.num_contours; j++) {
+ num_points = cv->outlines.contours[j].num_points;
+ points = cv->outlines.contours[j].points;
if (ISSET(cv->flags, FIRST_END_OK)) {
num_points--;
points++;
@@ -1346,7 +1460,7 @@ Pick(Item item,
int width, height;
int i;
- if (cv->dev_shape.num_contours == 0) {
+ if (cv->outlines.num_contours == 0) {
return dist;
}
@@ -1357,23 +1471,24 @@ Pick(Item item,
* Check all contours. Compute distance to holes
* in the same pass.
*/
- for (i = 0; i < cv->dev_shape.num_contours; i++) {
- if (cv->shape.holes[i]) {
- new_hole_dist = PolygonToPointDist(cv->dev_shape.contours[i].points,
- cv->dev_shape.contours[i].num_points, p);
+ for (i = 0; i < cv->outlines.num_contours; i++) {
+ if (cv->outlines.contours[i].cw) {
+ new_hole_dist = PolygonToPointDist(cv->outlines.contours[i].points,
+ cv->outlines.contours[i].num_points, p);
if (new_hole_dist < hole_dist) {
hole_dist = new_hole_dist;
}
}
else {
- new_dist = PolygonToPointDist(cv->dev_shape.contours[i].points,
- cv->dev_shape.contours[i].num_points, p);
+ new_dist = PolygonToPointDist(cv->outlines.contours[i].points,
+ cv->outlines.contours[i].num_points, p);
if (new_dist < dist) {
dist = new_dist;
}
}
}
if ((dist <= 0.0) && (hole_dist >= 0.0)) {
+ /*printf("dist %g hole dist: %g\n", dist, hole_dist);*/
return 0.0;
}
if (hole_dist < 0.0) {
@@ -1391,9 +1506,9 @@ Pick(Item item,
/*
* Check all contours.
*/
- for (i = 0; i < cv->dev_shape.num_contours; i++) {
- points = cv->dev_shape.contours[i].points;
- num_points = cv->dev_shape.contours[i].num_points;
+ for (i = 0; i < cv->outlines.num_contours; i++) {
+ points = cv->outlines.contours[i].points;
+ num_points = cv->outlines.contours[i].num_points;
if (ISCLEAR(cv->flags, RELIEF_OK)) {
new_dist = PolylineToPointDist(points, num_points,
cv->line_width, cv->cap_style, cv->join_style, p);
@@ -1401,17 +1516,17 @@ Pick(Item item,
dist = new_dist;
}
if (dist <= 0.0) {
+ /*printf("dist %g\n", dist);*/
return 0.0;
}
}
else {
- new_dist = ZnPolygonReliefToPointDist(points, num_points,
- (cv->dev_shape.cw[0]^cv->shape.holes[0])?-cv->line_width:cv->line_width,
- p);
+ new_dist = ZnPolygonReliefToPointDist(points, num_points, cv->line_width, p);
if (new_dist < dist) {
dist = new_dist;
}
if (dist <= 0.0) {
+ /*printf("dist %g\n", dist);*/
return 0.0;
}
}
@@ -1421,8 +1536,8 @@ Pick(Item item,
/*
* Line ends are checked only on the first contour.
*/
- points = cv->dev_shape.contours[0].points;
- num_points = cv->dev_shape.contours[0].num_points;
+ points = cv->outlines.contours[0].points;
+ num_points = cv->outlines.contours[0].num_points;
/*
* Check line ends.
*/
@@ -1434,6 +1549,7 @@ Pick(Item item,
dist = new_dist;
}
if (dist <= 0.0) {
+ /*printf("dist %g\n", dist);*/
return 0.0;
}
}
@@ -1445,6 +1561,7 @@ Pick(Item item,
dist = new_dist;
}
if (dist <= 0.0) {
+ /*printf("dist %g\n", dist);*/
return 0.0;
}
}
@@ -1453,9 +1570,9 @@ Pick(Item item,
* Last, check markers on all contours.
*/
if (ISSET(cv->flags, MARKER_OK)) {
- for (i = 0; i < cv->dev_shape.num_contours; i++) {
- points = cv->dev_shape.contours[i].points;
- num_points = cv->dev_shape.contours[i].num_points;
+ for (i = 0; i < cv->outlines.num_contours; i++) {
+ points = cv->outlines.contours[i].points;
+ num_points = cv->outlines.contours[i].num_points;
if (ISSET(cv->flags, FIRST_END_OK)) {
num_points--;
@@ -1476,12 +1593,14 @@ Pick(Item item,
dist = new_dist;
}
if (dist <= 0.0) {
+ /*printf("dist %g\n", dist);*/
return 0.0;
}
}
}
}
+ /*printf("dist %g\n", dist);*/
return dist;
}
@@ -1514,40 +1633,21 @@ GetClipVertices(Item item,
ZnTriStrip *tristrip)
{
CurveItem cv = (CurveItem) item;
-#ifndef GPC
- ZnPoint *points;
-#endif
-#ifdef GPC
tristrip->num_strips = 0;
- if (cv->tristrip.num_strips == 0) {
- gpc_polygon_to_tristrip((gpc_polygon *) &cv->dev_shape,
- (gpc_tristrip *) &cv->tristrip);
- }
-
if (cv->tristrip.num_strips == 1) {
TRI_STRIP1(tristrip,
cv->tristrip.strips[0].points,
- cv->tristrip.strips[0].num_points);
+ cv->tristrip.strips[0].num_points,
+ cv->tristrip.strips[0].fan);
}
else if (cv->tristrip.num_strips > 1) {
tristrip->num_strips = cv->tristrip.num_strips;
tristrip->strips = cv->tristrip.strips;
}
- tristrip->fan = False;
-
return False;
-#else
- ZnListAssertSize(item->wi->work_pts, 2);
- points = (ZnPoint *) ZnListArray(item->wi->work_pts);
- TRI_STRIP1(tristrip, points, 2);
- points[0] = item->item_bounding_box.orig;
- points[1] = item->item_bounding_box.corner;
-
- return True;
-#endif
}
@@ -1566,13 +1666,13 @@ GetContours(Item item,
{
CurveItem cv = (CurveItem) item;
- if (cv->dev_shape.num_contours == 1) {
- POLY_CONTOUR1(poly, cv->dev_shape.contours[0].points,
- cv->dev_shape.contours[0].num_points);
+ if (cv->outlines.num_contours == 1) {
+ POLY_CONTOUR1(poly, cv->outlines.contours[0].points,
+ cv->outlines.contours[0].num_points);
}
- else if (cv->dev_shape.num_contours > 1) {
- poly->num_contours = cv->dev_shape.num_contours;
- poly->contours = cv->dev_shape.contours;
+ else if (cv->outlines.num_contours > 1) {
+ poly->num_contours = cv->outlines.num_contours;
+ poly->contours = cv->outlines.contours;
}
return False;
@@ -1593,11 +1693,12 @@ Coords(Item item,
int index,
int cmd,
ZnPoint **pts,
+ char **controls,
int *num_pts)
{
CurveItem cv = (CurveItem) item;
- int i;
- ZnContour *c;
+ int i, num_controls;
+ ZnContour *c=NULL;
/*printf("contour %d, num_pts %d, index %d, cmd %d\n",
contour, *num_pts, index, cmd);*/
@@ -1632,11 +1733,15 @@ Coords(Item item,
}
if (*num_pts) {
if (c->points) {
- ZnFree(c->points);
+ ZnFree(c->points);
}
c->points = (ZnPoint *) ZnMalloc(*num_pts*sizeof(ZnPoint));
c->num_points = *num_pts;
memcpy(c->points, *pts, *num_pts*sizeof(ZnPoint));
+ if (*controls) {
+ c->controls = ZnRealloc(c->controls, *num_pts*sizeof(char));
+ memcpy(c->controls, *controls, *num_pts*sizeof(char));
+ }
}
else {
goto cont_remove;
@@ -1663,8 +1768,31 @@ Coords(Item item,
return ZN_ERROR;
}
c->points[index] = (*pts)[0];
+ if (!c->controls && *controls && (*controls)[0]) {
+ c->controls = ZnMalloc(c->num_points*sizeof(char));
+ memset(c->controls, 0, c->num_points*sizeof(char));
+ }
+ if (c->controls) {
+ if (!*controls) {
+ c->controls[index] = 0;
+ }
+ else {
+ if ((*controls)[0]) {
+ /* Check if the edit is allowable, there should be
+ * no more than 2 consecutive control points .
+ */
+ for (num_controls = 0, i = index-1; !c->controls[i]; i--, num_controls++);
+ for (i = index+1; !c->controls[i]; i++, num_controls++);
+ if (num_controls > 1) {
+ control_err:
+ Tcl_AppendResult(item->wi->interp, " too many consecutive control points in a curve", NULL);
+ return ZN_ERROR;
+ }
+ }
+ c->controls[index] = (*controls)[0];
+ }
+ }
}
- CLEAR(cv->flags, REDUCED_BIT);
ITEM.Invalidate(item, ZN_COORDS_FLAG);
}
@@ -1680,6 +1808,9 @@ Coords(Item item,
if (cmd == COORDS_READ_ALL) {
*num_pts = c->num_points;
*pts = c->points;
+ if (c->controls) {
+ *controls = c->controls;
+ }
}
else {
if (index < 0) {
@@ -1690,6 +1821,9 @@ Coords(Item item,
}
*num_pts = 1;
*pts = &c->points[index];
+ if (c->controls) {
+ *controls = &c->controls[index];
+ }
}
}
@@ -1716,19 +1850,51 @@ Coords(Item item,
if ((index < 0) || (index > c->num_points)) {
goto range_err;
}
- c->points = (ZnPoint *) ZnRealloc(c->points,
- (c->num_points+*num_pts)*sizeof(ZnPoint));
+ if (*controls) {
+ /* Check if the edit is allowable, there should be
+ * no more than 2 consecutive control points .
+ */
+ if (c->controls) {
+ for (num_controls = 0, i = index-1; !c->controls[i]; i--, num_controls++);
+ }
+ for (i = 0; i < *num_pts; i++) {
+ if (!(*controls)[i]) {
+ num_controls = 0;
+ }
+ else {
+ num_controls++;
+ if (num_controls > 2) {
+ goto control_err;
+ }
+ }
+ }
+ if (c->controls) {
+ for (i = index+1; !c->controls[i]; i++, num_controls++);
+ }
+ if (num_controls > 2) {
+ goto control_err;
+ }
+ }
+ c->points = ZnRealloc(c->points, (c->num_points+*num_pts)*sizeof(ZnPoint));
+ if (*controls || c->controls) {
+ c->controls = ZnRealloc(c->controls, (c->num_points+*num_pts)*sizeof(char));
+ }
/*
* Make a hole if needed.
*/
for (i = c->num_points-1; i >= index; i--) {
c->points[i+*num_pts] = c->points[i];
+ if (c->controls) {
+ c->controls[i+*num_pts] = c->controls[i];
+ }
}
for (i = 0; i < *num_pts; i++, index++) {
c->points[index] = (*pts)[i];
+ if (c->controls) {
+ c->controls[index] = (*controls)?(*controls)[i]:0;
+ }
}
c->num_points += *num_pts;
- CLEAR(cv->flags, REDUCED_BIT);
ITEM.Invalidate(item, ZN_COORDS_FLAG);
}
@@ -1747,17 +1913,32 @@ Coords(Item item,
if ((index < 0) || (index >= c->num_points)) {
goto range_err;
}
+
+ if (c->controls) {
+ /* Check if the edit is allowable, there should be
+ * no more than 2 consecutive control points .
+ */
+ for (num_controls = 0, i = index-1; !c->controls[i]; i--, num_controls++);
+ for (i = index+1; !c->controls[i]; i++, num_controls++);
+ if (num_controls > 2) {
+ goto control_err;
+ }
+ }
+
c->num_points--;
if (c->num_points == 0) {
/*
* Contour is removed.
*/
cont_remove:
+ if (c->controls) {
+ ZnFree(c->controls);
+ }
+ ZnFree(c->points);
if (cv->shape.num_contours == 1) {
POLY_FREE(&cv->shape);
}
else {
- ZnFree(c->points);
for (i = contour; i < cv->shape.num_contours; i++) {
cv->shape.contours[i] = cv->shape.contours[i+1];
}
@@ -1766,9 +1947,11 @@ Coords(Item item,
else if (index != c->num_points) {
for (i = index; i < c->num_points; i++) {
c->points[i] = c->points[i+1];
+ if (c->controls) {
+ c->controls[i] = c->controls[i+1];
+ }
}
}
- CLEAR(cv->flags, REDUCED_BIT);
ITEM.Invalidate(item, ZN_COORDS_FLAG);
}
@@ -1784,32 +1967,96 @@ Coords(Item item,
*
**********************************************************************************
*/
-#ifdef GPC
static int
Contour(Item item,
int cmd,
+ int index,
ZnPoly *poly)
{
CurveItem cv = (CurveItem) item;
- ZnPoly rpoly;
+ int i, num_contours;
switch (cmd) {
- case GPC_DIFF:
- case GPC_INT:
- case GPC_UNION:
- case GPC_XOR:
- POLY_INIT(&rpoly);
- gpc_polygon_clip(cmd, (gpc_polygon *) &cv->shape, (gpc_polygon *) poly,
- (gpc_polygon *) &rpoly);
-
- POLY_SET(&cv->shape, &rpoly);
-
+ case ZN_CONTOUR_ADD:
+ if (index < 0) {
+ index += cv->shape.num_contours;
+ }
+ if (index > cv->shape.num_contours) {
+ index = cv->shape.num_contours;
+ }
+ if (index < 0) {
+ contour_err:
+ Tcl_AppendResult(item->wi->interp, " contour index out of range", NULL);
+ return ZN_ERROR;
+ }
+ num_contours = cv->shape.num_contours + poly->num_contours;
+ if (cv->shape.contours == &cv->shape.contour1) {
+ cv->shape.contours = ZnMalloc(num_contours*sizeof(ZnContour));
+ cv->shape.contours[0].num_points = cv->shape.contour1.num_points;
+ cv->shape.contours[0].cw = cv->shape.contour1.cw;
+ cv->shape.contours[0].points = cv->shape.contour1.points;
+ cv->shape.contours[0].controls = cv->shape.contour1.controls;
+ }
+ else {
+ cv->shape.contours = ZnRealloc(cv->shape.contours, num_contours*sizeof(ZnContour));
+ /*printf("Reallocating shape contours (%d) 0x%X\n", num_contours, cv->shape.contours);*/
+ }
+ /*
+ * Make a hole if needed.
+ */
+ /*printf("index : %d, i : %d\n", index, cv->shape.num_contours-1);*/
+ for (i = cv->shape.num_contours-1; i >= index; i--) {
+ cv->shape.contours[i+poly->num_contours] = cv->shape.contours[i];
+ }
+ for (i = 0; i < poly->num_contours; i++, index++) {
+ cv->shape.contours[index].num_points = poly->contours[i].num_points;
+ cv->shape.contours[index].cw = poly->contours[i].cw;
+ cv->shape.contours[index].points = ZnMalloc(poly->contours[i].num_points * sizeof(ZnPoint));
+ memcpy(cv->shape.contours[index].points, poly->contours[i].points,
+ poly->contours[i].num_points * sizeof(ZnPoint));
+ cv->shape.contours[index].controls = NULL;
+ if (poly->contours[i].controls) {
+ /*
+ * The controls array in poly is shared, duplicate it
+ * to keep a locally owned copy.
+ */
+ cv->shape.contours[index].controls = ZnMalloc(poly->contours[i].num_points * sizeof(char));
+ memcpy(cv->shape.contours[index].controls, poly->contours[i].controls,
+ poly->contours[i].num_points * sizeof(char));
+ }
+ }
+ cv->shape.num_contours = num_contours;
ITEM.Invalidate(item, ZN_COORDS_FLAG);
+ break;
+ case ZN_CONTOUR_REMOVE:
+ if (index < 0) {
+ index += cv->shape.num_contours;
+ }
+ if (index >= cv->shape.num_contours) {
+ index = cv->shape.num_contours - 1;
+ }
+ if (index < 0) {
+ goto contour_err;
+ }
+ cv->shape.num_contours--;
+ if (cv->shape.num_contours == 0) {
+ POLY_FREE(&cv->shape);
+ }
+ else {
+ ZnFree(cv->shape.contours[index].points);
+ if (cv->shape.contours[index].controls) {
+ ZnFree(cv->shape.contours[index].controls);
+ }
+ for (i = index; i < cv->shape.num_contours; i++) {
+ cv->shape.contours[i] = cv->shape.contours[i+1];
+ }
+ }
+ ITEM.Invalidate(item, ZN_COORDS_FLAG);
+ break;
}
return cv->shape.num_contours;
}
-#endif
/*
@@ -1831,22 +2078,31 @@ PickVertex(Item item,
{
CurveItem cv = (CurveItem) item;
int i, j, k, num_points;
- ZnPoint *points;
+ ZnPoint *points, po;
ZnReal dist=1.0e40, new_dist, dist2;
-
+ ZnTransfo t, inv;
+
*contour = *vertex = *o_vertex = -1;
if ((cv->line_width > 0) ||
ISSET(cv->flags, FILLED_OK) ||
ISSET(cv->flags, MARKER_OK)) {
+
+ /*
+ * Get the point in the item coordinate space.
+ */
+ ITEM.GetItemTransform(item, &t);
+ ZnTransfoInvert(&t, &inv);
+ ZnTransformPoint(&inv, p, &po);
+
/*
* Check all contours.
*/
- for (i = 0; i < cv->dev_shape.num_contours; i++) {
- points = cv->dev_shape.contours[i].points;
- num_points = cv->dev_shape.contours[i].num_points;
+ for (i = 0; i < cv->shape.num_contours; i++) {
+ points = cv->shape.contours[i].points;
+ num_points = cv->shape.contours[i].num_points;
for (j = 0; j < num_points; j++) {
- new_dist = hypot(points[j].x - p->x, points[j].y - p->y);
+ new_dist = hypot(points[j].x - po.x, points[j].y - po.y);
if (new_dist < dist) {
dist = new_dist;
*contour = i;
@@ -1859,9 +2115,9 @@ PickVertex(Item item,
*/
if (i == *contour) {
j = (*vertex+1) % num_points;
- new_dist = LineToPointDist(&points[*vertex], &points[j], p);
+ new_dist = LineToPointDist(&points[*vertex], &points[j], &po);
k = ((unsigned)(*vertex-1)) % num_points;
- dist2 = LineToPointDist(&points[*vertex], &points[k], p);
+ dist2 = LineToPointDist(&points[*vertex], &points[k], &po);
if (dist2 < new_dist) {
*o_vertex = k;
}
@@ -1903,11 +2159,7 @@ static ItemClassStruct CURVE_ITEM_CLASS = {
NULL, /* Index */
NULL, /* Part */
NULL, /* Selection */
-#ifdef GPC
Contour,
-#else
- NULL,
-#endif
ComputeCoordinates,
ToArea,
Draw,