aboutsummaryrefslogtreecommitdiff
path: root/generic/Curve.c
diff options
context:
space:
mode:
authorlecoanet2002-12-09 14:30:25 +0000
committerlecoanet2002-12-09 14:30:25 +0000
commit1bd8808d5660cbede81165a25a6cd59e5c5c69b5 (patch)
treed3e655daf93bdc0ff9914dd1c6491bebe67f937d /generic/Curve.c
parent5de4aad21f265022dd3cf9352eca9c6cc40a16ad (diff)
downloadtkzinc-1bd8808d5660cbede81165a25a6cd59e5c5c69b5.zip
tkzinc-1bd8808d5660cbede81165a25a6cd59e5c5c69b5.tar.gz
tkzinc-1bd8808d5660cbede81165a25a6cd59e5c5c69b5.tar.bz2
tkzinc-1bd8808d5660cbede81165a25a6cd59e5c5c69b5.tar.xz
* Remaniement du code des gradients (incompatibilit�s).
* Utilisation des display lists pour am�liorer les perfs en GL. * Adaptation pour g�rer la nouvelle fa�on de traiter les contours. * Nombreuses corrections de bug suite � l'introduction du code sur les contours. * Fin de r�alisation des paths.
Diffstat (limited to 'generic/Curve.c')
-rw-r--r--generic/Curve.c360
1 files changed, 236 insertions, 124 deletions
diff --git a/generic/Curve.c b/generic/Curve.c
index ee50dcd..07e686e 100644
--- a/generic/Curve.c
+++ b/generic/Curve.c
@@ -19,6 +19,7 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
+
*
* You should have received a copy of the GNU Library General Public
* License along with this code; if not, write to the Free
@@ -26,7 +27,6 @@
*
*/
-
#include "Draw.h"
#include "Item.h"
#include "Geo.h"
@@ -38,7 +38,7 @@
#include <ctype.h>
#include <malloc.h>
-
+#include <GL/glu.h>
static const char rcsid[] = "$Id$";
static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $";
@@ -175,10 +175,12 @@ Init(Item item,
CurveItem cv = (CurveItem) item;
int i, num_points, count;
ZnPoint *p, *points;
- char *controls;
+ char *controls, *c;
cv->outlines.num_contours = 0;
+ cv->outlines.contours = NULL;
cv->tristrip.num_strips = 0;
+ cv->tristrip.strips = NULL;
cv->gradient = NULL;
cv->grad_geo = NULL;
@@ -212,30 +214,54 @@ Init(Item item,
if (controls) {
count = 0;
if ((controls[0]) || (controls[num_points-1])) {
- goto control_err;
+ goto contr_err;
}
for (i = 1; i < num_points-1; i++) {
switch (controls[i]) {
case 'c':
count++;
if (count > 2) {
- goto control_err;
+ goto contr_err;
}
break;
case 0:
count = 0;
break;
default:
- control_err:
+ contr_err:
ZnFree(controls);
Tcl_AppendResult(wi->interp, " curve coords expected", NULL);
return ZN_ERROR;
}
}
}
+ /*
+ * Do not allow a hole to be added as the first contour, it breaks
+ * backward compatibility. Instead silently convert it to a plain
+ * contour.
+ */
p = ZnMalloc(num_points * sizeof(ZnPoint));
- memcpy(p, points, num_points * sizeof(ZnPoint));
- POLY_CONTOUR1(&cv->shape, p, num_points);
+ if (! TestCCW(points, num_points)) {
+ if (controls) {
+ c = ZnMalloc(num_points * sizeof(char));
+ for (i = 0; i < num_points; i++) {
+ c[num_points-i-1] = controls[i];
+ }
+ ZnFree(controls);
+ controls = c;
+ }
+ for (i = 0; i < num_points; i++) {
+ p[num_points-i-1] = points[i];
+ }
+ /*printf("revert hole to contour, numpoints: %d %g@%g\n",
+ num_points, points[0].x, points[0].y);*/
+ }
+ else {
+ /*printf("plain contour, numpoints: %d %g@%g\n",
+ num_points, points[0].x, points[0].y);*/
+ memcpy(p, points, num_points * sizeof(ZnPoint));
+ }
+ POLY_CONTOUR1(&cv->shape, p, num_points, False);
cv->shape.contours[0].controls = controls;
}
(*args)++;
@@ -331,7 +357,9 @@ Clone(Item item)
cv->fill_color = ZnGetGradientByValue(cv->fill_color);
cv->marker_color = ZnGetGradientByValue(cv->marker_color);
cv->tristrip.num_strips = 0;
+ cv->tristrip.strips = NULL;
cv->outlines.num_contours = 0;
+ cv->outlines.contours = NULL;
}
@@ -541,13 +569,13 @@ CurveTessVertex(void *vertex_data,
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));
-
+ /*printf("Fin de fragment intermediaire %d, num points: %d\n", cv->tristrip.num_strips-1, size);*/
/* 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;
+ cv->tristrip.strips[cv->tristrip.num_strips-1].fan = False;
}
ZnListAdd(wi->work_pts, &p, ZnListTail);
}
@@ -577,7 +605,7 @@ CurveTessEnd(void *data)
memcpy(cv->tristrip.strips[num-1].points,
ZnListArray(wi->work_pts), size * sizeof(ZnPoint));
}
- /* printf("Fin de fragment %d\n", num);*/
+ /*printf("Fin de fragment %d, num points: %d\n", num, size);*/
}
static void
CurveTessCombine(GLdouble coords[3],
@@ -596,7 +624,7 @@ CurveTessCombine(GLdouble coords[3],
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]);*/
+ cdata->v[0], cdata->v[1]);*/
}
static void
CurveTessError(GLenum errno,
@@ -617,6 +645,7 @@ UpdateTristrip(CurveItem cv,
GLdouble v[3];
int i, j;
+ /*printf("UpdateTristrips sur %d\n", ((Item) cv)->id);*/
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);
@@ -651,6 +680,7 @@ UpdateTristrip(CurveItem cv,
}
wi->tess_combine_list = NULL;
}
+ /*printf("Fin UpdateTristrips sur %d\n", ((Item) cv)->id);*/
}
static void
@@ -662,6 +692,7 @@ UpdateOutlines(CurveItem cv,
GLdouble v[3];
int i, j;
+ /*printf("UpdateOutlines sur %d\n", ((Item) cv)->id);*/
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);
@@ -692,6 +723,7 @@ UpdateOutlines(CurveItem cv,
}
wi->tess_combine_list = NULL;
}
+ /*printf("Fin UpdateOutlines sur %d\n", ((Item) cv)->id);*/
}
@@ -720,7 +752,7 @@ ComputeCoordinates(Item item,
ResetBBox(&item->item_bounding_box);
- /* printf("Curve CC: flags %x\n", cv->flags);*/
+ /*printf("Curve CC: flags %x\n", cv->flags);*/
SetRenderFlags(cv);
num_contours = cv->shape.num_contours;
@@ -759,8 +791,8 @@ ComputeCoordinates(Item item,
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->points[0].x != c1->points[c1->num_points-1].x) ||
+ (c1->points[0].y != c1->points[c1->num_points-1].y)) &&
(c1->num_points > 2)) {
c2->num_points++;
}
@@ -788,7 +820,7 @@ ComputeCoordinates(Item item,
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);
+ &c2->points[j], wi->work_pts, 0.5);
}
else {
/*printf("lineto %g@%g\n", c2->points[j].x, c2->points[j].y);*/
@@ -798,6 +830,17 @@ ComputeCoordinates(Item item,
}
}
/*
+ * Must test if the last point is a control and the contour
+ * is closed (either a mono contour with -closed or
+ * multiple contours).
+ */
+ if (c1->controls[c1->num_points-1]) {
+ GetBezierPoints(&c2->points[segment_start],
+ &c2->points[segment_start+1], &c2->points[c1->num_points-1],
+ &c2->points[0], wi->work_pts, 0.5);
+ }
+
+ /*
* Replce the original path by the expanded, closing it as
* needed (one open contour).
*/
@@ -816,8 +859,8 @@ ComputeCoordinates(Item item,
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;
+ POLY_CONTOUR1(&cv->outlines, dev.contours[0].points, dev.contours[0].num_points,
+ dev.contours[0].cw);
}
else {
UpdateOutlines(cv, &dev);
@@ -913,20 +956,20 @@ ComputeCoordinates(Item item,
item->item_bounding_box.corner.x += 1;
item->item_bounding_box.corner.y += 1;
}
-
+
+#ifdef GLX
if (!ZnGradientFlat(cv->fill_color)) {
if (!cv->grad_geo) {
- cv->grad_geo = ZnMalloc(4*sizeof(ZnPoint));
+ cv->grad_geo = ZnMalloc(6*sizeof(ZnPoint));
}
if (cv->fill_color->type == ZN_AXIAL_GRADIENT) {
ZnComputeAxialGradient(wi, &cv->shape, cv->fill_color->g.angle, cv->grad_geo);
}
else if (cv->fill_color->type == ZN_RADIAL_GRADIENT) {
- ZnComputeRadialGradient(wi, &cv->outlines, &item->item_bounding_box,
- &cv->fill_color->g.p, cv->grad_geo);
+ ZnComputeRadialGradient(wi, &cv->shape, False, &cv->fill_color->g.p, cv->grad_geo);
}
else if (cv->fill_color->type == ZN_PATH_GRADIENT) {
- ZnTransformPoint(wi->current_transfo, &cv->fill_color->g.p, &cv->grad_geo[0]);
+ ZnComputePathGradient(wi, &cv->shape, &cv->fill_color->g.p, cv->grad_geo);
}
}
else {
@@ -935,6 +978,7 @@ ComputeCoordinates(Item item,
cv->grad_geo = NULL;
}
}
+#endif
}
@@ -1141,15 +1185,31 @@ Draw(Item item)
for (i = 0; i < cv->tristrip.num_strips; i++) {
num_points = cv->tristrip.strips[i].num_points;
points = cv->tristrip.strips[i].points;
- ZnListAssertSize(wi->work_xpts, num_points);
- xpoints = (XPoint *) ZnListArray(wi->work_xpts);
- for (j = 0; j < num_points; j++) {
- xpoints[j].x = REAL_TO_INT(points[j].x);
- xpoints[j].y = REAL_TO_INT(points[j].y);
+ if (cv->tristrip.strips[i].fan) {
+ XPoint xpoints[3];
+ xpoints[0].x = REAL_TO_INT(points[0].x);
+ xpoints[0].y = REAL_TO_INT(points[0].y);
+ xpoints[1].x = REAL_TO_INT(points[1].x);
+ xpoints[1].y = REAL_TO_INT(points[1].y);
+ for (j = 2; j < num_points; j++) {
+ xpoints[2].x = REAL_TO_INT(points[j].x);
+ xpoints[2].y = REAL_TO_INT(points[j].y);
+ XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc,
+ xpoints, 3, Convex, CoordModeOrigin);
+ xpoints[1] = xpoints[2];
+ }
}
- for (j = 0; j < num_points-2; j++) {
- XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc,
- &xpoints[j], 3, Convex, CoordModeOrigin);
+ else {
+ ZnListAssertSize(wi->work_xpts, num_points);
+ xpoints = ZnListArray(wi->work_xpts);
+ for (j = 0; j < num_points; j++) {
+ xpoints[j].x = REAL_TO_INT(points[j].x);
+ xpoints[j].y = REAL_TO_INT(points[j].y);
+ }
+ for (j = 0; j < num_points-2; j++) {
+ XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc,
+ &xpoints[j], 3, Convex, CoordModeOrigin);
+ }
}
}
}
@@ -1198,7 +1258,7 @@ Draw(Item item)
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);
+ xpoints = ZnListArray(wi->work_xpts);
for (i = 0; i < num2; i++) {
xpoints[i].x = REAL_TO_INT(points[i].x);
xpoints[i].y = REAL_TO_INT(points[i].y);
@@ -1319,7 +1379,7 @@ Render(Item item)
ZnPoint *points;
XColor *color;
int alpha;
-
+
if ((cv->outlines.num_contours == 0) ||
(ISCLEAR(cv->flags, FILLED_OK) &&
!cv->line_width &&
@@ -1327,99 +1387,108 @@ Render(Item item)
return;
}
- /*
- * Fill if requested.
- */
- if (ISSET(cv->flags, FILLED_OK)) {
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- if (!ZnGradientFlat(cv->fill_color)) {
- ZnRenderGradient(wi, cv->fill_color, CurveRenderCB, cv, cv->grad_geo,
- &cv->outlines);
- }
- else if (cv->tile != ZnUnspecifiedImage) { /* Fill tiled */
- ZnRenderTile(wi, cv->tile, cv->fill_color, CurveRenderCB, cv,
- (ZnPoint *) &item->item_bounding_box);
- }
- else {
- if (cv->fill_pattern != ZnUnspecifiedImage) { /* Fill stippled */
- /*
- * Setup polygon stippling.
- */
- glEnable(GL_POLYGON_STIPPLE);
- glPolygonStipple(ZnImagePattern(cv->fill_pattern, NULL));
+ if (!item->gl_list) {
+ item->gl_list = glGenLists(1);
+ glNewList(item->gl_list, GL_COMPILE);
+
+ /*
+ * Fill if requested.
+ */
+ if (ISSET(cv->flags, FILLED_OK)) {
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ if (!ZnGradientFlat(cv->fill_color)) {
+ ZnRenderGradient(wi, cv->fill_color, CurveRenderCB, cv, cv->grad_geo,
+ &cv->outlines);
+ }
+ else if (cv->tile != ZnUnspecifiedImage) { /* Fill tiled */
+ ZnRenderTile(wi, cv->tile, cv->fill_color, CurveRenderCB, cv,
+ (ZnPoint *) &item->item_bounding_box);
+ }
+ else {
+ if (cv->fill_pattern != ZnUnspecifiedImage) { /* Fill stippled */
+ /*
+ * Setup polygon stippling.
+ */
+ glEnable(GL_POLYGON_STIPPLE);
+ glPolygonStipple(ZnImagePattern(cv->fill_pattern, NULL));
+ }
+ color = ZnGetGradientColor(cv->fill_color, 0.0, &alpha);
+ alpha = ZnComposeAlpha(alpha, wi->alpha);
+ glColor4us(color->red, color->green, color->blue, alpha);
+ CurveRenderCB(cv);
+ glDisable(GL_POLYGON_STIPPLE);
}
- color = ZnGetGradientColor(cv->fill_color, 0.0, &alpha);
- alpha = ZnComposeAlpha(alpha, wi->alpha);
- glColor4us(color->red, color->green, color->blue, alpha);
- CurveRenderCB(cv);
- glDisable(GL_POLYGON_STIPPLE);
}
- }
-
- /*
- * Draw the lines between points
- */
- if (cv->line_width) {
+
/*
- * Drawing with relief disables: ends, line style and line pattern.
+ * Draw the lines between points
*/
- ZnGetGradientColor(cv->line_color, 0, &alpha);
- alpha = ZnComposeAlpha(alpha, wi->alpha);
- if (ISSET(cv->flags, RELIEF_OK)) {
- 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->outlines.contours[j].cw);*/
- ZnRenderPolygonRelief(wi, cv->relief, cv->gradient, ISSET(cv->flags, SMOOTH_RELIEF_BIT),
- points, num_points, cv->line_width);
+ if (cv->line_width) {
+ /*
+ * Drawing with relief disables: ends, line style and line pattern.
+ */
+ ZnGetGradientColor(cv->line_color, 0, &alpha);
+ alpha = ZnComposeAlpha(alpha, wi->alpha);
+ if (ISSET(cv->flags, RELIEF_OK)) {
+ 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->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->outlines.num_contours; j++) {
+ ZnRenderPolyline(wi,
+ 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);
+ }
}
}
- 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;
+
+ /*
+ * Draw the marks at each point. If arrows are specified or
+ * if last point join first point suppress markers at end points.
+ */
+ if (ISSET(cv->flags, MARKER_OK)) {
+ int h_width, h_height;
+ ZnPoint ptmp;
+ 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->outlines.num_contours; j++) {
- ZnRenderPolyline(wi,
- 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);
+ num_points = cv->outlines.contours[j].num_points;
+ points = cv->outlines.contours[j].points;
+ if (ISSET(cv->flags, FIRST_END_OK)) {
+ num_points--;
+ points++;
+ }
+ if (ISSET(cv->flags, LAST_END_OK)) {
+ num_points--;
+ }
+ for (; num_points > 0; num_points--, points++) {
+ ptmp.x = points->x - h_width;
+ ptmp.y = points->y - h_height;
+ ZnRenderIcon(wi, cv->marker, cv->marker_color, &ptmp, True);
+ }
}
}
+
+ glEndList();
}
- /*
- * Draw the marks at each point. If arrows are specified or
- * if last point join first point suppress markers at end points.
- */
- if (ISSET(cv->flags, MARKER_OK)) {
- int h_width, h_height;
- ZnPoint ptmp;
-
- 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->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++;
- }
- if (ISSET(cv->flags, LAST_END_OK)) {
- num_points--;
- }
- for (; num_points > 0; num_points--, points++) {
- ptmp.x = points->x - h_width;
- ptmp.y = points->y - h_height;
- ZnRenderIcon(wi, cv->marker, cv->marker_color, &ptmp, True);
- }
- }
- }
+ glCallList(item->gl_list);
#endif
}
@@ -1668,7 +1737,8 @@ GetContours(Item item,
if (cv->outlines.num_contours == 1) {
POLY_CONTOUR1(poly, cv->outlines.contours[0].points,
- cv->outlines.contours[0].num_points);
+ cv->outlines.contours[0].num_points,
+ cv->outlines.contours[0].cw);
}
else if (cv->outlines.num_contours > 1) {
poly->num_contours = cv->outlines.num_contours;
@@ -1728,7 +1798,7 @@ Coords(Item item,
* is also legal, resulting in the contour being removed.
*/
if ((cv->shape.num_contours == 0) && (*num_pts)) {
- POLY_CONTOUR1(&cv->shape, NULL, 0);
+ POLY_CONTOUR1(&cv->shape, NULL, 0, False);
c = &cv->shape.contours[0];
}
if (*num_pts) {
@@ -1767,6 +1837,7 @@ Coords(Item item,
Tcl_AppendResult(item->wi->interp, " coord index out of range", NULL);
return ZN_ERROR;
}
+ /*printf("--->%g@%g\n", (*pts)[0].x, (*pts)[0].y);*/
c->points[index] = (*pts)[0];
if (!c->controls && *controls && (*controls)[0]) {
c->controls = ZnMalloc(c->num_points*sizeof(char));
@@ -1779,10 +1850,29 @@ Coords(Item item,
else {
if ((*controls)[0]) {
/* Check if the edit is allowable, there should be
- * no more than 2 consecutive control points .
+ * no more than 2 consecutive control points. The first
+ * point must not be a control and the last one can
+ * be one only if the curve is closed.
*/
- for (num_controls = 0, i = index-1; !c->controls[i]; i--, num_controls++);
- for (i = index+1; !c->controls[i]; i++, num_controls++);
+ num_controls = 0;
+ if (!index) {
+ control_first:
+ Tcl_AppendResult(item->wi->interp, " the first point must not be a control", NULL);
+ return ZN_ERROR;
+ }
+ else if (index == c->num_points-1) {
+ if (ISCLEAR(cv->flags, CLOSED_BIT) &&
+ (cv->shape.num_contours == 1)) {
+ control_last:
+ Tcl_AppendResult(item->wi->interp, " the last point must not be a control", NULL);
+ return ZN_ERROR;
+ }
+ }
+ else {
+ for (i = index-1; c->controls[i] && (i >= 0); i--, num_controls++);
+ }
+ for (i = index+1; c->controls[i] && (i < c->num_points); i++, num_controls++);
+ printf("******* num controls(): %d\n", num_controls);
if (num_controls > 1) {
control_err:
Tcl_AppendResult(item->wi->interp, " too many consecutive control points in a curve", NULL);
@@ -1838,7 +1928,7 @@ Coords(Item item,
* created.
*/
if (cv->shape.num_contours == 0) {
- POLY_CONTOUR1(&cv->shape, NULL, 0);
+ POLY_CONTOUR1(&cv->shape, NULL, 0, False);
c = &cv->shape.contours[0];
}
if (cmd == COORDS_ADD_LAST) {
@@ -1852,11 +1942,25 @@ Coords(Item item,
}
if (*controls) {
/* Check if the edit is allowable, there should be
- * no more than 2 consecutive control points .
+ * no more than 2 consecutive control points. The first
+ * point must not be a control and the last one can
+ * be one only if the curve is closed.
*/
+ if ((index == 0) && (*controls)[0]) {
+ goto control_first;
+ }
+ else if ((index == c->num_points-1) && (*controls)[*num_pts-1] &&
+ ISCLEAR(cv->flags, CLOSED_BIT) && (cv->shape.num_contours == 1)) {
+ goto control_last;
+ }
+
+ num_controls = 0;
if (c->controls) {
- for (num_controls = 0, i = index-1; !c->controls[i]; i--, num_controls++);
+ if (index) {
+ for (i = index-1; c->controls[i] && (i >= 0); i--, num_controls++);
+ }
}
+ printf("******* num controls: %d\n", num_controls);
for (i = 0; i < *num_pts; i++) {
if (!(*controls)[i]) {
num_controls = 0;
@@ -1868,16 +1972,24 @@ Coords(Item item,
}
}
}
+ printf("******* num controls(2): %d\n", num_controls);
if (c->controls) {
- for (i = index+1; !c->controls[i]; i++, num_controls++);
+ for (i = index; c->controls[i] && (i < c->num_points); i++, num_controls++);
}
+ printf("******* num controls(3): %d\n", 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));
+ if (c->controls) {
+ c->controls = ZnRealloc(c->controls, (c->num_points+*num_pts)*sizeof(char));
+ }
+ else {
+ c->controls = ZnMalloc((c->num_points+*num_pts)*sizeof(char));
+ memset(c->controls, 0, (c->num_points+*num_pts)*sizeof(char));
+ }
}
/*
* Make a hole if needed.