aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlecoanet2001-10-12 07:08:48 +0000
committerlecoanet2001-10-12 07:08:48 +0000
commit95c3ef2c408cf8f570582cbd0a79eb5fc0f42887 (patch)
tree221d314cd69524bf6b84db7217a0c6824e7f28f8
parentd17009cc6b1f50b8d55e70a0a7ed7cffe86de5fb (diff)
downloadtkzinc-95c3ef2c408cf8f570582cbd0a79eb5fc0f42887.zip
tkzinc-95c3ef2c408cf8f570582cbd0a79eb5fc0f42887.tar.gz
tkzinc-95c3ef2c408cf8f570582cbd0a79eb5fc0f42887.tar.bz2
tkzinc-95c3ef2c408cf8f570582cbd0a79eb5fc0f42887.tar.xz
Suppression du gradient dans le code X11.
Suppression du code libart. Extension du code de rendu GL.
-rw-r--r--generic/Curve.c456
-rw-r--r--generic/Rectangle.c440
2 files changed, 501 insertions, 395 deletions
diff --git a/generic/Curve.c b/generic/Curve.c
index c8d2a35..3522a87 100644
--- a/generic/Curve.c
+++ b/generic/Curve.c
@@ -37,6 +37,9 @@
#ifdef GPC
#include "gpc/gpc.h"
#endif
+#ifdef GLX
+#include <GL/tube.h>
+#endif
#include <ctype.h>
#include <malloc.h>
@@ -88,20 +91,16 @@ typedef struct _CurveItemStruct {
ZnColor line_color;
ZnColor marker_color;
int line_alpha;
- int fill_alpha;
char *tile_name;
/* Private data */
ZnImage tile;
ZnPoly dev_shape;
ZnGradient *gradient;
-#ifdef LIBART
- ArtSVP *outline_svp;
- ArtSVP *fill_svp;
-#endif
#ifdef GPC
gpc_tristrip tristrip;
#endif
+ ZnPoint *grad_geo;
} CurveItemStruct, *CurveItem;
static ZnAttrConfig cv_attrs[] = {
@@ -116,8 +115,6 @@ static ZnAttrConfig cv_attrs[] = {
{ ZN_CONFIG_BOOL, "-composescale", NULL,
Tk_Offset(CurveItemStruct, header.flags), COMPOSE_SCALE_BIT,
ZN_COORDS_FLAG, False },
- { ZN_CONFIG_UINT, "-fillalpha", NULL,
- Tk_Offset(CurveItemStruct, fill_alpha), 0, ZN_DRAW_FLAG, False },
{ ZN_CONFIG_GRADIENT, "-fillcolor", NULL,
Tk_Offset(CurveItemStruct, fill_color), 0,
ZN_DRAW_FLAG|ZN_BORDER_FLAG, False },
@@ -132,7 +129,7 @@ static ZnAttrConfig cv_attrs[] = {
ZN_COORDS_FLAG, False },
{ ZN_CONFIG_LINE_END, "-lastend", NULL,
Tk_Offset(CurveItemStruct, last_end), 0, ZN_COORDS_FLAG, False },
- { ZN_CONFIG_UINT, "-linealpha", NULL,
+ { ZN_CONFIG_ALPHA, "-linealpha", NULL,
Tk_Offset(CurveItemStruct, line_alpha), 0, ZN_DRAW_FLAG, False },
{ ZN_CONFIG_COLOR, "-linecolor", NULL,
Tk_Offset(CurveItemStruct, line_color), 0,
@@ -215,6 +212,7 @@ Init(Item item,
cv->tristrip.num_strips = 0;
#endif
cv->gradient = NULL;
+ cv->grad_geo = NULL;
/* Init attributes */
SET(item->flags, VISIBLE_BIT);
@@ -278,15 +276,11 @@ Init(Item item,
*/
SET(cv->flags, MARKED_BIT);
cv->marker = ZnUnspecifiedPattern;
- cv->fill_alpha = 255;
cv->fill_color = ZnGetGradient(wi->interp, wi->win,
ZnNameOfColor(wi->fore_color));
- cv->line_alpha = 255;
+ cv->line_alpha = 100;
cv->line_color = ZnGetColorByValue(wi->win, wi->fore_color);
cv->marker_color = ZnGetColorByValue(wi->win, wi->fore_color);
-#ifdef LIBART
- cv->outline_svp = cv->fill_svp = NULL;
-#endif
return ZN_OK;
}
@@ -310,6 +304,7 @@ Clone(Item item)
ZnBool *holes;
POLY_INIT(&cv->dev_shape);
+ cv->grad_geo = NULL;
if (cv->shape.num_contours) {
conts = cv->shape.contours;
@@ -362,9 +357,6 @@ Clone(Item item)
cv->line_color = ZnGetColorByValue(wi->win, cv->line_color);
cv->fill_color = ZnGetGradientByValue(cv->fill_color);
cv->marker_color = ZnGetColorByValue(wi->win, cv->marker_color);
-#ifdef LIBART
- cv->outline_svp = cv->fill_svp = NULL;
-#endif
}
@@ -382,6 +374,9 @@ Destroy(Item item)
CurveItem cv = (CurveItem) item;
POLY_FREE(&cv->shape);
+ if (cv->grad_geo) {
+ ZnFree(cv->grad_geo);
+ }
cv->dev_shape.holes = NULL;
POLY_FREE(&cv->dev_shape);
@@ -418,14 +413,6 @@ Destroy(Item item)
gpc_free_tristrip(&cv->tristrip);
}
#endif
-#ifdef LIBART
- if (cv->outline_svp) {
- art_svp_free(cv->outline_svp);
- }
- if (cv->fill_svp) {
- art_svp_free(cv->fill_svp);
- }
-#endif
}
@@ -494,7 +481,9 @@ Configure(Item item,
}
if ((cv->relief != RELIEF_FLAT) && !cv->gradient) {
cv->gradient = ZnGetReliefGradient(wi->interp, wi->win,
- ZnNameOfColor(ZnGetGradientColor(wi->win, cv->fill_color, 50.0)));
+ ZnNameOfColor(ZnGetGradientColor(wi->win,
+ cv->fill_color,
+ 50.0, NULL)));
if (cv->gradient == NULL) {
status = ZN_ERROR;
}
@@ -718,51 +707,6 @@ ComputeCoordinates(Item item,
lw = cv->line_width;
- /*
- * PLC Rendering works only with one contour, no relief, no markers,
- * round ends, round joins.
- */
- if (wi->render) {
-#ifdef LIBART
- ArtVpath *vpath;
-
- c2 = cv->dev_shape.contours;
- vpath = (ArtVpath *) ZnMalloc((c2->num_points+2) * sizeof(ArtVpath));
- points = c2->points;
- for (i = 0; i < c2->num_points; i++, points++) {
- vpath[i].code = ART_LINETO;
- vpath[i].x = points->x;
- vpath[i].y = points->y;
- }
- if (ISSET(cv->flags, CLOSED_BIT)) {
- vpath[0].code = ART_MOVETO;
- }
- else {
- vpath[0].code = ART_MOVETO_OPEN;
- }
- vpath[i].code = ART_END;
-
- if (cv->fill_svp) {
- art_svp_free(cv->fill_svp);
- cv->fill_svp = NULL;
- }
- if (ISSET(cv->flags, FILLED_BIT)) {
- cv->fill_svp = art_svp_from_vpath(vpath);
- }
- if (cv->outline_svp) {
- art_svp_free(cv->outline_svp);
- cv->outline_svp = NULL;
- }
- if (cv->line_width) {
- cv->outline_svp = art_svp_vpath_stroke(vpath,
- ART_PATH_STROKE_JOIN_ROUND,
- ART_PATH_STROKE_CAP_ROUND,
- lw, 2, 1);
- }
- ZnFree(vpath);
-#endif
- }
-
if (ISSET(cv->flags, RELIEF_OK)) {
holes = cv->shape.holes;
c2 = cv->dev_shape.contours;
@@ -864,6 +808,77 @@ ComputeCoordinates(Item item,
item->item_bounding_box.orig.y -= 1;
item->item_bounding_box.corner.x += 1;
item->item_bounding_box.corner.y += 1;
+
+ if (!ZnGradientFlat(cv->fill_color)) {
+ if (!cv->grad_geo) {
+ cv->grad_geo = ZnMalloc(4*sizeof(ZnPoint));
+ }
+ if (cv->fill_color->type == ZN_AXIAL_GRADIENT) {
+ int angle = cv->fill_color->g.angle;
+ ZnTransfo *transfo1, *transfo2;
+ ZnPoint p[4];
+ ZnBBox bbox;
+
+ transfo1 = ZnTransfoNew();
+ transfo2 = ZnTransfoNew();
+ ZnRotateDeg(transfo1, angle);
+ ZnRotateDeg(transfo2, -angle);
+ holes = cv->shape.holes;
+ c1 = cv->shape.contours;
+ ResetBBox(&bbox);
+ for (j = 0; j < num_contours; j++, c1++, holes++) {
+ if (*holes) {
+ continue;
+ }
+ ZnListAssertSize(wi->work_pts, c1->num_points);
+ points = ZnListArray(wi->work_pts);
+ ZnTransformPoints(transfo1, c1->points, points, c1->num_points);
+ AddPointsToBBox(&bbox, points, c1->num_points);
+ }
+ p[0] = bbox.orig;
+ p[2] = bbox.corner;
+ p[1].x = p[2].x;
+ p[1].y = p[0].y;
+ p[3].x = p[0].x;
+ p[3].y = p[2].y;
+ ZnTransfoSetIdentity(transfo1);
+ ZnTransfoCompose(transfo1, transfo2, wi->current_transfo);
+ ZnTransformPoints(transfo1, p, cv->grad_geo, 4);
+ ZnTransfoFree(transfo1);
+ ZnTransfoFree(transfo2);
+ }
+ else if (cv->fill_color->type == ZN_RADIAL_GRADIENT) {
+ ZnReal dist, new, x0, x, y0, y;
+
+ ZnTransformPoint(wi->current_transfo, &cv->fill_color->g.p, &cv->grad_geo[0]);
+ x0 = cv->grad_geo[0].x;
+ y0 = cv->grad_geo[0].y;
+ dist = 0.0;
+ holes = cv->shape.holes;
+ c1 = cv->dev_shape.contours;
+ for (j = 0; j < num_contours; j++, c1++, holes++) {
+ if (*holes) {
+ continue;
+ }
+ points = c1->points;
+ for (i = 0; i < c1->num_points; i++, points++) {
+ x = points->x;
+ y = points->y;
+ new = (x-x0)*(x-x0) + (y-y0)*(y-y0);
+ if (new > dist) {
+ dist = new;
+ }
+ }
+ }
+ cv->grad_geo[1].x = sqrt(dist) + 2; /* Max radius plus a fuzz factor */
+ }
+ }
+ else {
+ if (cv->grad_geo) {
+ ZnFree(cv->grad_geo);
+ cv->grad_geo = NULL;
+ }
+ }
}
@@ -1044,67 +1059,61 @@ Draw(Item item)
* Fill if requested.
*/
if (ISSET(cv->flags, FILLED_OK)) {
- if (!ZnGradientFlat(cv->fill_color)) {
- DrawPolygonGradient(wi, cv->fill_color, &cv->dev_shape,
- &item->item_bounding_box);
- }
- else {
- values.foreground = ZnPixel(ZnGetGradientColor(wi->win, cv->fill_color, 50.0));
- gc_mask = GCFillStyle;
- if (cv->tile != ZnUnspecifiedImage) { /* Fill tiled */
- Pixmap pmap = GetImagePixmap(wi->win, cv->tile_name, cv->tile, NULL);
- values.fill_style = FillTiled;
- values.tile = pmap;
- values.ts_x_origin = REAL_TO_INT(item->item_bounding_box.orig.x);
- values.ts_y_origin = REAL_TO_INT(item->item_bounding_box.orig.y);
- gc_mask |= GCTileStipXOrigin|GCTileStipYOrigin|GCTile;
- }
- else if (cv->fill_pattern != ZnUnspecifiedPattern) { /* Fill stippled */
- values.fill_style = FillStippled;
- values.stipple = cv->fill_pattern;
- values.ts_x_origin = REAL_TO_INT(item->item_bounding_box.orig.x);
- values.ts_y_origin = REAL_TO_INT(item->item_bounding_box.orig.y);
- gc_mask |= GCTileStipXOrigin|GCTileStipYOrigin|GCStipple|GCForeground;
- }
- else { /* Fill solid */
- values.fill_style = FillSolid;
- gc_mask |= GCForeground;
- }
- XChangeGC(wi->dpy, wi->gc, gc_mask, &values);
-
+ values.foreground = ZnPixel(ZnGetGradientColor(wi->win, cv->fill_color, 0.0, NULL));
+ gc_mask = GCFillStyle;
+ if (cv->tile != ZnUnspecifiedImage) { /* Fill tiled */
+ Pixmap pmap = GetImagePixmap(wi->win, cv->tile_name, cv->tile, NULL);
+ values.fill_style = FillTiled;
+ values.tile = pmap;
+ values.ts_x_origin = REAL_TO_INT(item->item_bounding_box.orig.x);
+ values.ts_y_origin = REAL_TO_INT(item->item_bounding_box.orig.y);
+ gc_mask |= GCTileStipXOrigin|GCTileStipYOrigin|GCTile;
+ }
+ else if (cv->fill_pattern != ZnUnspecifiedPattern) { /* Fill stippled */
+ values.fill_style = FillStippled;
+ values.stipple = cv->fill_pattern;
+ values.ts_x_origin = REAL_TO_INT(item->item_bounding_box.orig.x);
+ values.ts_y_origin = REAL_TO_INT(item->item_bounding_box.orig.y);
+ gc_mask |= GCTileStipXOrigin|GCTileStipYOrigin|GCStipple|GCForeground;
+ }
+ else { /* Fill solid */
+ values.fill_style = FillSolid;
+ gc_mask |= GCForeground;
+ }
+ 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, &cv->tristrip);
- }
- for (i = 0; i < cv->tristrip.num_strips; i++) {
- num_points = cv->tristrip.strip[i].num_vertices;
- points = (ZnPoint *) cv->tristrip.strip[i].vertex;
- 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);
- }
- for (j = 0; j < num_points-2; j++) {
- XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc,
- &xpoints[j], 3, Convex, CoordModeOrigin);
- }
- }
-#else
- num_points = cv->dev_shape.contours[0].num_points;
- points = cv->dev_shape.contours[0].points;
+ if (cv->tristrip.num_strips == 0) {
+ gpc_polygon_to_tristrip((gpc_polygon *) &cv->dev_shape, &cv->tristrip);
+ }
+ for (i = 0; i < cv->tristrip.num_strips; i++) {
+ num_points = cv->tristrip.strip[i].num_vertices;
+ points = (ZnPoint *) cv->tristrip.strip[i].vertex;
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);
+ 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);
}
- XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc,
- xpoints, num_points, Complex, CoordModeOrigin);
-#endif
}
+#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
}
-
+
/*
* Draw the lines between points
*/
@@ -1146,7 +1155,7 @@ Draw(Item item)
}
}
else {
- SetLineStyle(wi->dpy, wi->gc, cv->line_style);
+ SetLineStyle(wi, cv->line_style);
values.foreground = ZnPixel(cv->line_color);
values.line_width = (cv->line_width == 1) ? 0 : cv->line_width;
values.join_style = cv->join_style;
@@ -1254,28 +1263,189 @@ Draw(Item item)
*
**********************************************************************************
*/
+#ifdef GLX
+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, &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.strip[i].num_vertices;
+ points = (ZnPoint *) cv->tristrip.strip[i].vertex;
+ glBegin(GL_TRIANGLE_STRIP);
+ for (j = 0; j < num_points; j++) {
+ glVertex2f(points[j].x, points[j].y);
+ }
+ glEnd();
+ }
+}
+#endif
static void
Render(Item item)
{
-#ifdef LIBART
- WidgetInfo *wi = item->wi;
+#ifdef GLX
+ WidgetInfo *wi = item->wi;
CurveItem cv = (CurveItem) item;
- XColor *color = ZnGetGradientColor(wi->win, cv->fill_color, 50.0);
- ArtPixBuf *pixbuf = NULL;
+ int i, j, num_points;
+ ZnPoint *points;
+ XColor *color;
+ int alpha;
+
+ if ((cv->dev_shape.num_contours == 0) ||
+ (ISCLEAR(cv->flags, FILLED_OK) &&
+ !cv->line_width &&
+ ISCLEAR(cv->flags, MARKER_OK))) {
+ return;
+ }
+
+ /*
+ * Fill if requested.
+ */
+ if (ISSET(cv->flags, FILLED_OK)) {
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ if (!ZnGradientFlat(cv->fill_color)) {
+ RenderGradient(wi, cv->fill_color, CurveRenderCB, cv, cv->grad_geo);
+ }
+ else if (cv->tile != ZnUnspecifiedImage) { /* Fill tiled */
+ RenderTile(wi, GetImageTexture(wi->win, cv->tile_name, cv->tile),
+ cv->fill_color, CurveRenderCB, cv, (ZnPoint *) &item->item_bounding_box);
+ }
+ else {
+ if (cv->fill_pattern != ZnUnspecifiedPattern) { /* Fill stippled */
+ /*
+ * Setup polygon stippling.
+ */
+ glEnable(GL_POLYGON_STIPPLE);
+ glPolygonStipple(GetBitmapMask(wi->dpy, cv->fill_pattern)->pixels);
+ }
+ color = ZnGetGradientColor(wi->win, cv->fill_color, 0.0, &alpha);
+ glColor4us(color->red, color->green, color->blue, alpha*65535/100);
+ 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.
+ */
+ if (ISSET(cv->flags, RELIEF_OK)) {
+ }
+ else {
+ color = cv->line_color;
+ glColor4us(color->red, color->green, color->blue, cv->line_alpha*65535/100);
+ if ((cv->line_width <= wi->max_line_width) &&
+ (cv->line_width <= wi->max_point_width)) {
+ glLineWidth(cv->line_width);
+ SetLineStyle(wi, cv->line_style);
+ 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;
+ if (ISSET(cv->flags, CLOSED_BIT)) {
+ glBegin(GL_LINE_LOOP);
+ }
+ else {
+ glBegin(GL_LINE_STRIP);
+ }
+ for (i = 0; i < num_points; i++) {
+ glVertex2f(points[i].x, points[i].y);
+ }
+ glEnd();
+ }
+ if (cv->line_width > 1) {
+ glPointSize(cv->line_width);
+ 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;
+ glBegin(GL_POINTS);
+ for (i = 0; i < num_points; i++) {
+ glVertex2f(points[i].x, points[i].y);
+ }
+ glEnd();
+ }
+ }
+ }
+ else {
+ double lw_2 = (double) cv->line_width / 2.0;
+ double section[2][2] = { { 0.0, -lw_2 }, { 0.0, lw_2 } };
+ double up[3] = { 1.0, 0.0, 0.0 };
+ double (*gl_pts)[3];
+ int style, num;
+
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ 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;
+ ZnListAssertSize(wi->work_doubles, (num_points+3)*3);
+ gl_pts = (void *) ZnListArray(wi->work_doubles);
+ if (ISSET(cv->flags, CLOSED_BIT)) {
+ gl_pts[0][0] = points[num_points-1].x;
+ gl_pts[0][1] = points[num_points-1].y;
+ gl_pts[0][2] = 0;
+ gl_pts[num_points+1][0] = points[0].x;
+ gl_pts[num_points+1][1] = points[0].y;
+ gl_pts[num_points+1][2] = 0;
+ gl_pts[num_points+2][0] = points[1].x;
+ gl_pts[num_points+2][1] = points[1].y;
+ gl_pts[num_points+2][2] = 0;
+ }
+ else {
+ gl_pts[0][0] = points[0].x;
+ gl_pts[1][1] = points[0].y;
+ gl_pts[2][2] = 0;
+ gl_pts[num_points+1][0] = points[num_points-1].x;
+ gl_pts[num_points+1][1] = points[num_points-1].y;
+ gl_pts[num_points+1][2] = 0;
+ }
+ for (i = 0; i < num_points; i++) {
+ gl_pts[i+1][0] = points[i].x;
+ gl_pts[i+1][1] = points[i].y;
+ gl_pts[i+1][2] = 0;
+ }
+ switch (cv->join_style) {
+ case JoinRound:
+ style = TUBE_JN_ROUND;
+ break;
+ case JoinMiter:
+ style = TUBE_JN_ANGLE;
+ break;
+ case JoinBevel:
+ style = TUBE_JN_CUT;
+ break;
+ }
+ if (cv->cap_style == CapRound) {
+ style |= TUBE_JN_CAP;
+ }
+ style |= TUBE_CONTOUR_CLOSED;
+
+ num = num_points+2;
+ if (ISSET(cv->flags, CLOSED_BIT)) {
+ num++;
+ }
+ gleSetJoinStyle(style);
+ gleExtrusion(2, section, NULL, up, num, gl_pts, NULL);
+ }
+ }
+ }
+ }
- if (cv->fill_svp != NULL) {
- if (strlen(cv->tile_name) != 0) {
- pixbuf = GetImagePixbuf(wi->win, cv->tile_name, cv->tile);
- }
- ITEM_P.RenderSVP(wi, cv->fill_svp, color->red, color->green,
- color->blue, cv->fill_alpha & 0xff,
- item->item_bounding_box.orig.x,
- item->item_bounding_box.orig.y, pixbuf);
- }
- if (cv->outline_svp != NULL) {
- ITEM_P.RenderSVP(wi, cv->outline_svp, cv->line_color->red,
- cv->line_color->green, cv->line_color->blue,
- cv->line_alpha & 0xff, 0, 0, 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)) {
}
#endif
}
diff --git a/generic/Rectangle.c b/generic/Rectangle.c
index fb2fc38..6a5ea69 100644
--- a/generic/Rectangle.c
+++ b/generic/Rectangle.c
@@ -28,6 +28,9 @@
#include <malloc.h>
+#ifdef GLX
+#include <GL/tube.h>
+#endif
#include "Item.h"
#include "Geo.h"
@@ -70,17 +73,13 @@ typedef struct _RectangleItemStruct {
Pixmap line_pattern;
ZnGradient *fill_color;
int line_alpha;
- int fill_alpha;
char *tile_name;
/* Private data */
ZnPoint dev[4];
ZnImage tile;
ZnGradient *gradient;
-#ifdef LIBART
- ArtSVP *outline_svp;
- ArtSVP *fill_svp;
-#endif
+ ZnPoint *grad_geo;
} RectangleItemStruct, *RectangleItem;
@@ -91,8 +90,6 @@ static ZnAttrConfig rect_attrs[] = {
{ ZN_CONFIG_BOOL, "-composescale", NULL,
Tk_Offset(RectangleItemStruct, header.flags), COMPOSE_SCALE_BIT,
ZN_COORDS_FLAG, False },
- { ZN_CONFIG_UINT, "-fillalpha", NULL,
- Tk_Offset(RectangleItemStruct, fill_alpha), 0, ZN_DRAW_FLAG, False },
{ ZN_CONFIG_GRADIENT, "-fillcolor", NULL,
Tk_Offset(RectangleItemStruct, fill_color), 0,
ZN_DRAW_FLAG|ZN_BORDER_FLAG, False },
@@ -100,7 +97,7 @@ static ZnAttrConfig rect_attrs[] = {
Tk_Offset(RectangleItemStruct, flags), FILLED_BIT, ZN_COORDS_FLAG, False },
{ ZN_CONFIG_PATTERN, "-fillpattern", NULL,
Tk_Offset(RectangleItemStruct, fill_pattern), 0, ZN_DRAW_FLAG, False },
- { ZN_CONFIG_UINT, "-linealpha", NULL,
+ { ZN_CONFIG_ALPHA, "-linealpha", NULL,
Tk_Offset(RectangleItemStruct, line_alpha), 0, ZN_DRAW_FLAG, False },
{ ZN_CONFIG_COLOR, "-linecolor", NULL,
Tk_Offset(RectangleItemStruct, line_color), 0,
@@ -173,6 +170,7 @@ Init(Item item,
int num_elems;
rect->gradient = NULL;
+ rect->grad_geo = NULL;
/* Init attributes */
SET(item->flags, VISIBLE_BIT);
@@ -206,13 +204,9 @@ Init(Item item,
rect->tile = ZnUnspecifiedImage;
rect->fill_pattern = ZnUnspecifiedPattern;
rect->line_color = ZnGetColorByValue(wi->win, wi->fore_color);
- rect->line_alpha = 255;
+ rect->line_alpha = 100;
rect->fill_color = ZnGetGradient(wi->interp, wi->win,
ZnNameOfColor(wi->fore_color));
- rect->fill_alpha = 255;
-#ifdef LIBART
- rect->outline_svp = rect->fill_svp = NULL;
-#endif
return ZN_OK;
}
@@ -235,6 +229,7 @@ Clone(Item item)
if (rect->gradient) {
rect->gradient = ZnGetGradientByValue(rect->gradient);
}
+ rect->grad_geo = NULL;
if (strlen(rect->tile_name) != 0) {
text = ZnMalloc((strlen(rect->tile_name) + 1) * sizeof(char));
strcpy(text, rect->tile_name);
@@ -252,9 +247,6 @@ Clone(Item item)
}
rect->line_color = ZnGetColorByValue(wi->win, rect->line_color);
rect->fill_color = ZnGetGradientByValue(rect->fill_color);
-#ifdef LIBART
- rect->outline_svp = rect->fill_svp = NULL;
-#endif
}
@@ -287,16 +279,11 @@ Destroy(Item item)
if (rect->fill_pattern != ZnUnspecifiedPattern) {
Tk_FreeBitmap(wi->dpy, rect->fill_pattern);
}
+ if (rect->grad_geo) {
+ ZnFree(rect->grad_geo);
+ }
ZnFreeGradient(rect->fill_color);
ZnFreeColor(rect->line_color);
-#ifdef LIBART
- if (rect->outline_svp) {
- art_svp_free(rect->outline_svp);
- }
- if (rect->fill_svp) {
- art_svp_free(rect->fill_svp);
- }
-#endif
}
@@ -326,7 +313,10 @@ Configure(Item item,
}
if ((rect->relief != RELIEF_FLAT) && !rect->gradient) {
rect->gradient = ZnGetReliefGradient(wi->interp, wi->win,
- ZnNameOfColor(ZnGetGradientColor(wi->win, rect->fill_color, 50.0)));
+ ZnNameOfColor(ZnGetGradientColor(wi->win,
+ rect->fill_color,
+ 50.0,
+ NULL)));
if (rect->gradient == NULL) {
status = ZN_ERROR;
}
@@ -436,47 +426,73 @@ ComputeCoordinates(Item item,
delta = ABS(delta);
aligned |= delta < X_PRECISION_LIMIT;
ASSIGN(rect->flags, ALIGNED_BIT, aligned);
-
- if (wi->render) {
-#ifdef LIBART
- ArtVpath vpath[6];
-
- if (ISSET(rect->flags, FILLED_BIT) || rect->line_width) {
- vpath[0].code = ART_MOVETO;
- vpath[0].x = rect->dev[0].x;
- vpath[0].y = rect->dev[0].y;
- vpath[1].code = ART_LINETO;
- vpath[1].x = rect->dev[3].x;
- vpath[1].y = rect->dev[3].y;
- vpath[2].code = ART_LINETO;
- vpath[2].x = rect->dev[2].x;
- vpath[2].y = rect->dev[2].y;
- vpath[3].code = ART_LINETO;
- vpath[3].x = rect->dev[1].x;
- vpath[3].y = rect->dev[1].y;
- vpath[4].code = ART_LINETO;
- vpath[4].x = rect->dev[0].x;
- vpath[4].y = rect->dev[0].y;
- vpath[5].code = ART_END;
- }
- if (rect->fill_svp) {
- art_svp_free(rect->fill_svp);
- rect->fill_svp = NULL;
- }
- if (ISSET(rect->flags, FILLED_BIT)) {
- rect->fill_svp = art_svp_from_vpath(vpath);
+
+ /*
+ * If there is an axial gradient with an unaligned axis
+ * compute the bbox in the coordinate system defined
+ * by the gradient axis.
+ */
+ if (!ZnGradientFlat(rect->fill_color)) {
+ if (rect->fill_color->type == ZN_AXIAL_GRADIENT) {
+ int angle = rect->fill_color->g.angle;
+ ZnTransfo *transfo1, *transfo2;
+ ZnPoint p1[4];
+ ZnBBox bbox;
+
+ if ((angle != 0) && (angle != 90) && (angle != 180) && (angle != 270)) {
+ if (!rect->grad_geo) {
+ rect->grad_geo = ZnMalloc(4*sizeof(ZnPoint));
+ }
+ transfo1 = ZnTransfoNew();
+ transfo2 = ZnTransfoNew();
+ ZnRotateDeg(transfo1, angle);
+ ZnRotateDeg(transfo2, -angle);
+ 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, rect->grad_geo, 4);
+ ZnTransfoFree(transfo1);
+ ZnTransfoFree(transfo2);
+ }
+ else {
+ goto free_ggeo;
+ }
}
- if (rect->outline_svp) {
- art_svp_free(rect->outline_svp);
- rect->outline_svp = NULL;
+ else if (rect->fill_color->type == ZN_RADIAL_GRADIENT) {
+ ZnReal dist, new, x0, x, y0, y;
+
+ if (!rect->grad_geo) {
+ rect->grad_geo = ZnMalloc(2*sizeof(ZnPoint));
+ }
+ ZnTransformPoint(wi->current_transfo, &rect->fill_color->g.p, &rect->grad_geo[0]);
+ x0 = rect->grad_geo[0].x;
+ y0 = rect->grad_geo[0].y;
+ dist = 0.0;
+ for (i = 0; i < 4; i++) {
+ x = rect->dev[i].x;
+ y = rect->dev[i].y;
+ new = (x-x0)*(x-x0) + (y-y0)*(y-y0);
+ if (new > dist) {
+ dist = new;
+ }
+ }
+ rect->grad_geo[1].x = sqrt(dist);
}
- if (rect->line_width) {
- rect->outline_svp = art_svp_vpath_stroke(vpath,
- ART_PATH_STROKE_JOIN_MITER,
- ART_PATH_STROKE_CAP_SQUARE,
- rect->line_width, 2, 1);
+ }
+ else {
+ free_ggeo:
+ if (rect->grad_geo) {
+ ZnFree(rect->grad_geo);
+ rect->grad_geo = NULL;
}
-#endif
}
}
@@ -568,63 +584,50 @@ Draw(Item item)
* Fill if requested.
*/
if (ISSET(rect->flags, FILLED_BIT)) {
- if (!ZnGradientFlat(rect->fill_color)) {
+ values.foreground = ZnPixel(ZnGetGradientColor(wi->win, rect->fill_color, 0.0, NULL));
+ if (rect->tile != ZnUnspecifiedImage) { /* Fill tiled */
+ Pixmap pmap = GetImagePixmap(wi->win, rect->tile_name, rect->tile, NULL);
+ values.fill_style = FillTiled;
+ values.tile = pmap;
if (ISSET(rect->flags, ALIGNED_BIT)) {
- DrawRectangleGradient(wi, rect->fill_color, &r);
+ values.ts_x_origin = (int) r.x;
+ values.ts_y_origin = (int) r.y;
}
else {
- ZnPoly poly;
- POLY_CONTOUR1(&poly, rect->dev, 4);
- DrawPolygonGradient(wi, rect->fill_color, &poly,
- &item->item_bounding_box);
+ values.ts_x_origin = (int) item->item_bounding_box.orig.x;
+ values.ts_y_origin = (int) item->item_bounding_box.orig.y;
}
- }
- else {
- values.foreground = ZnPixel(ZnGetGradientColor(wi->win, rect->fill_color, 50.0));
- if (rect->tile != ZnUnspecifiedImage) { /* Fill tiled */
- Pixmap pmap = GetImagePixmap(wi->win, rect->tile_name, rect->tile, NULL);
- values.fill_style = FillTiled;
- values.tile = pmap;
- if (ISSET(rect->flags, ALIGNED_BIT)) {
- values.ts_x_origin = (int) r.x;
- values.ts_y_origin = (int) r.y;
- }
- else {
- 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,
+ XChangeGC(wi->dpy, wi->gc,
GCTileStipXOrigin|GCTileStipYOrigin|GCFillStyle|GCTile, &values);
- }
- else if (rect->fill_pattern != ZnUnspecifiedPattern) { /* Fill stippled */
- values.fill_style = FillStippled;
- values.stipple = rect->fill_pattern;
- if (ISSET(rect->flags, ALIGNED_BIT)) {
- values.ts_x_origin = (int) r.x;
- values.ts_y_origin = (int) r.y;
- }
- else {
- 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,
- &values);
- }
- else { /* Fill solid */
- values.fill_style = FillSolid;
- XChangeGC(wi->dpy, wi->gc, GCForeground | GCFillStyle, &values);
- }
+ }
+ else if (rect->fill_pattern != ZnUnspecifiedPattern) { /* Fill stippled */
+ values.fill_style = FillStippled;
+ values.stipple = rect->fill_pattern;
if (ISSET(rect->flags, ALIGNED_BIT)) {
- XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc, r.x, r.y,
- r.width, r.height);
- }
+ values.ts_x_origin = (int) r.x;
+ values.ts_y_origin = (int) r.y;
+ }
else {
- XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, xp, 4, Convex, CoordModeOrigin);
+ 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,
+ &values);
+ }
+ else { /* Fill solid */
+ values.fill_style = FillSolid;
+ XChangeGC(wi->dpy, wi->gc, GCForeground | GCFillStyle, &values);
+ }
+ if (ISSET(rect->flags, ALIGNED_BIT)) {
+ XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc, r.x, r.y,
+ r.width, r.height);
+ }
+ else {
+ XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, xp, 4, Convex, CoordModeOrigin);
}
}
-
+
/* Draw the outline */
if (rect->line_width) {
if (rect->relief != RELIEF_FLAT) {
@@ -644,7 +647,7 @@ Draw(Item item)
}
}
else {
- SetLineStyle(wi->dpy, wi->gc, rect->line_style);
+ SetLineStyle(wi, rect->line_style);
gc_mask = GCFillStyle|GCLineWidth|GCForeground|GCJoinStyle;
values.foreground = ZnPixel(rect->line_color);
values.line_width = (rect->line_width == 1) ? 0 : rect->line_width;
@@ -682,170 +685,103 @@ Draw(Item item)
*
**********************************************************************************
*/
+#ifdef GLX
+static void
+RectRenderCB(void *closure)
+{
+ RectangleItem rect = (RectangleItem) closure;
+
+ glBegin(GL_TRIANGLE_STRIP);
+ glVertex2f(rect->dev[0].x, rect->dev[0].y);
+ glVertex2f(rect->dev[3].x, rect->dev[3].y);
+ glVertex2f(rect->dev[1].x, rect->dev[1].y);
+ glVertex2f(rect->dev[2].x, rect->dev[2].y);
+ glEnd();
+}
+#endif
+
static void
Render(Item item)
{
+#ifdef GLX
WidgetInfo *wi = item->wi;
RectangleItem rect = (RectangleItem) item;
- XColor *color = ZnGetGradientColor(wi->win, rect->fill_color, 50.0);
-#ifdef LIBART
- ArtPixBuf *pixbuf = NULL;
-
- if (rect->fill_svp != NULL) {
- if (strlen(rect->tile_name) != 0) {
- pixbuf = GetImagePixbuf(wi->win, rect->tile_name, rect->tile);
- }
-
- ITEM_P.RenderSVP(wi, rect->fill_svp, color->red, color->green,
- color->blue, rect->fill_alpha & 0xff,
- item->item_bounding_box.orig.x,
- item->item_bounding_box.orig.y, pixbuf);
- }
- if (rect->outline_svp != NULL) {
- ITEM_P.RenderSVP(wi, rect->outline_svp, rect->line_color->red,
- rect->line_color->green, rect->line_color->blue,
- rect->line_alpha & 0xff, 0, 0, NULL);
- }
-#endif
-#ifdef GLX
- int i;
+ XColor *color;
+ int i, alpha;
if (ISSET(rect->flags, FILLED_BIT)) {
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+
if (!ZnGradientFlat(rect->fill_color)) {
+ ZnBool fast = (rect->fill_color->type == ZN_AXIAL_GRADIENT) && !rect->grad_geo;
+ RenderGradient(wi, rect->fill_color,
+ fast ? NULL : RectRenderCB,
+ rect, fast ? rect->dev : rect->grad_geo);
}
else {
if (rect->tile != ZnUnspecifiedImage) { /* Fill tiled */
- ImageBits *im_bits = GetImageTexture(wi->win, rect->tile_name, rect->tile);
- ZnReal x, y, nx, ny, lx, ly, s, t;
-
- /*
- ZnReal dx, dy, width, height;
-
- if (ISSET(rect->flags, ALIGNED_BIT)) {
- width = rect->dev[1].x - rect->dev[0].x;
- if (width < 0) {
- width = -width;
- }
- height = rect->dev[3].y - rect->dev[0].y;
- if (height < 0) {
- height = -height;
- }
- }
- else {
- dx = rect->dev[1].x - rect->dev[0].x;
- dy = rect->dev[1].y - rect->dev[0].y;
- width = sqrt(dx*dx + dy*dy);
- dx = rect->dev[3].x - rect->dev[0].x;
- dy = rect->dev[3].y - rect->dev[0].y;
- height = sqrt(dx*dx + dy*dy);
- }
- dx = width/im_bits->width * im_bits->s;
- dy = height/im_bits->height * im_bits->t;
- glEnable(GL_TEXTURE_2D);
- glBindTexture(GL_TEXTURE_2D, im_bits->texture);
- glBegin(GL_QUADS);
- glTexCoord2f(0.0, 0.0);
- glVertex2f(rect->dev[0].x, rect->dev[0].y);
- glTexCoord2f(0.0, dy);
- glVertex2f(rect->dev[3].x, rect->dev[3].y);
- glTexCoord2f(dx, dy);
- glVertex2f(rect->dev[2].x, rect->dev[2].y);
- glTexCoord2f(dx, 0.0);
- glVertex2f(rect->dev[1].x, rect->dev[1].y);
- glEnd();
- glDisable(GL_TEXTURE_2D);*/
-
- /*
- * Setup the stencil buffer with the shape to be drawn.
- */
- glClear(GL_STENCIL_BUFFER_BIT);
- glEnable(GL_STENCIL_TEST);
- glStencilFunc(GL_ALWAYS, 1, 1);
- glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
- glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
- glBegin(GL_QUADS);
- glVertex2f(rect->dev[0].x, rect->dev[0].y);
- glVertex2f(rect->dev[3].x, rect->dev[3].y);
- glVertex2f(rect->dev[2].x, rect->dev[2].y);
- glVertex2f(rect->dev[1].x, rect->dev[1].y);
- glEnd();
- /*
- * Then texture map the rectangle through the shape.
- * The rectangle is drawn using quad-strips, each
- * quad matching the size of the texture tile.
- */
- /* glDisable(GL_STENCIL_TEST);*/
- glStencilFunc(GL_EQUAL, 1, 1);
- glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- glEnable(GL_TEXTURE_2D);
- glBindTexture(GL_TEXTURE_2D, im_bits->texture);
- y = item->item_bounding_box.orig.y;
- lx = item->item_bounding_box.corner.x;
- ly = item->item_bounding_box.corner.y;
- glBegin(GL_QUADS);
- do {
- x = item->item_bounding_box.orig.x;
- t = 1.0;
- ny = y + im_bits->height;
- if (ny > ly) {
- ny = ly;
- t = (ly - y) / (ZnReal) im_bits->height;
- }
- t *= im_bits->t;
- do {
- s = 1.0;
- nx = x + im_bits->width;
- if (nx > lx) {
- nx = lx;
- s = (lx - x) / (ZnReal) im_bits->width;
- }
- s *= im_bits->s;
- glTexCoord2f(0.0, 0.0);
- glVertex2f(x, y);
- glTexCoord2f(0.0, t);
- glVertex2f(x, ny);
- glTexCoord2f(s, t);
- glVertex2f(nx, ny);
- glTexCoord2f(s, 0.0);
- glVertex2f(nx, y);
- x = nx;
- }
- while (x != lx);
- y = ny;
- }
- while (y != ly);
- glEnd();
- glDisable(GL_TEXTURE_2D);
- glDisable(GL_STENCIL_TEST);
- }
- else if (rect->fill_pattern != ZnUnspecifiedPattern) { /* Fill stippled */
+ RenderTile(wi, GetImageTexture(wi->win, rect->tile_name, rect->tile),
+ rect->fill_color, RectRenderCB, rect, (ZnPoint *) &item->item_bounding_box);
}
- else { /* Fill solid */
- glColor4us(color->red, color->green, color->blue, rect->fill_alpha*256);
- glBegin(GL_QUADS);
- for (i = 0; i < 4; i++) {
- glVertex2f(rect->dev[i].x, rect->dev[i].y);
+ else {
+ if (rect->fill_pattern != ZnUnspecifiedPattern) { /* Fill stippled */
+ /*
+ * Setup polygon stippling.
+ */
+ glEnable(GL_POLYGON_STIPPLE);
+ glPolygonStipple(GetBitmapMask(wi->dpy, rect->fill_pattern)->pixels);
}
- glEnd();
+ color = ZnGetGradientColor(wi->win, rect->fill_color, 0.0, &alpha);
+ glColor4us(color->red, color->green, color->blue, alpha*65535/100);
+ RectRenderCB(rect);
+ glDisable(GL_POLYGON_STIPPLE);
}
}
}
if (rect->line_width) {
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
if (rect->relief != RELIEF_FLAT) {
+ ZnPoint p[5];
+ for (i = 0; i < 4; i++) {
+ p[4-i].x = rect->dev[i].x;
+ p[4-i].y = rect->dev[i].y;
+ }
+ p[0] = p[4];
+ RenderPolygonRelief(wi, rect->relief, rect->gradient,
+ rect->line_alpha, 0, p, 5, rect->line_width);
}
else {
- glColor4us(rect->line_color->red, rect->line_color->green,
- rect->line_color->blue, rect->line_alpha*256);
- glLineWidth(rect->line_width);
- glBegin(GL_QUADS);
- for (i = 0; i < 4; i++) {
- glVertex2f(rect->dev[i].x, rect->dev[i].y);
+ color = rect->line_color;
+ glColor4us(color->red, color->green, color->blue, rect->line_alpha*65535/100);
+ if (rect->line_width < 3) {
+ SetLineStyle(wi, rect->line_style);
+ glLineWidth(rect->line_width);
+ glBegin(GL_LINE_LOOP);
+ for (i = 0; i < 4; i++) {
+ glVertex2f(rect->dev[i].x, rect->dev[i].y);
+ }
+ glEnd();
+ }
+ else {
+ double lw_2 = (double) rect->line_width / 2.0;
+ double section[2][2] = { { 0.0, -lw_2 }, { 0.0, lw_2 } };
+ double up[3] = { 1.0, 0.0, 0.0 };
+ double vertices[7][3];
+
+ vertices[0][0] = vertices[4][0] = rect->dev[3].x;
+ vertices[0][1] = vertices[4][1] = rect->dev[3].y;
+ vertices[1][0] = vertices[5][0] = rect->dev[0].x;
+ vertices[1][1] = vertices[5][1] = rect->dev[0].y;
+ vertices[2][0] = vertices[6][0] = rect->dev[1].x;
+ vertices[2][1] = vertices[6][1] = rect->dev[1].y;
+ vertices[3][0] = rect->dev[2].x;
+ vertices[3][1] = rect->dev[2].y;
+ vertices[0][2] = vertices[1][2] = vertices[2][2] = vertices[3][2] = 0;
+ vertices[4][2] = vertices[5][2] = vertices[6][2] = 0;
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ gleSetJoinStyle(TUBE_JN_ANGLE | TUBE_CONTOUR_CLOSED);
+ gleExtrusion(2, section, NULL, up, 7, vertices, NULL);
}
- glEnd();
}
}
#endif