aboutsummaryrefslogtreecommitdiff
path: root/generic
diff options
context:
space:
mode:
Diffstat (limited to 'generic')
-rw-r--r--generic/Draw.c1083
1 files changed, 764 insertions, 319 deletions
diff --git a/generic/Draw.c b/generic/Draw.c
index cc5378c..ed8d3ce 100644
--- a/generic/Draw.c
+++ b/generic/Draw.c
@@ -42,15 +42,17 @@
#include "Geo.h"
#include "List.h"
#include "WidgetInfo.h"
+#include "Image.h"
#include <math.h>
#include <stdarg.h>
#define POLYGON_RELIEF_DRAW 0
-#define POLYGON_RELIEF_DIST 1
-#define POLYGON_RELIEF_BBOX 2
-#define POLYGON_RELIEF_IN_BBOX 3
+#define POLYGON_RELIEF_RENDER 1
+#define POLYGON_RELIEF_DIST 2
+#define POLYGON_RELIEF_BBOX 3
+#define POLYGON_RELIEF_IN_BBOX 4
#define TOP_CONTRAST 13
#define BOTTOM_CONTRAST 6
@@ -73,31 +75,52 @@
**********************************************************************************
*/
void
-SetLineStyle(Display *display,
- GC gc,
+SetLineStyle(WidgetInfo *wi,
LineStyle line_style)
{
- XGCValues values;
- static const char dashed[] = { 8 };
- static const char dotted[] = { 2, 5 };
- static const char mixed[] = { 8, 5, 2, 5 };
-
- values.line_style = LineOnOffDash;
- switch (line_style) {
- case LINE_DASHED :
- XSetDashes(display, gc, 0, dashed, 1);
- break;
- case LINE_MIXED :
- XSetDashes(display, gc, 0, mixed, 4);
- break;
- case LINE_DOTTED :
- XSetDashes(display, gc, 0, dotted, 2);
- break;
+ if (wi->render) {
+#ifdef GLX
+ switch (line_style) {
+ case LINE_DASHED :
+ glLineStipple(1, 0xF0F0);
+ glEnable(GL_LINE_STIPPLE);
+ break;
+ case LINE_MIXED :
+ glLineStipple(1, 0x27FF);
+ glEnable(GL_LINE_STIPPLE);
+ break;
+ case LINE_DOTTED :
+ glLineStipple(1, 0x18C3);
+ glEnable(GL_LINE_STIPPLE);
+ break;
+ default:
+ glDisable(GL_LINE_STIPPLE);
+ }
+#endif
+ }
+ else {
+ XGCValues values;
+ static const char dashed[] = { 8 };
+ static const char dotted[] = { 2, 5 };
+ static const char mixed[] = { 8, 5, 2, 5 };
+
+ values.line_style = LineOnOffDash;
+ switch (line_style) {
+ case LINE_DASHED :
+ XSetDashes(wi->dpy, wi->gc, 0, dashed, 1);
+ break;
+ case LINE_MIXED :
+ XSetDashes(wi->dpy, wi->gc, 0, mixed, 4);
+ break;
+ case LINE_DOTTED :
+ XSetDashes(wi->dpy, wi->gc, 0, dotted, 2);
+ break;
default:
values.line_style = LineSolid;
break;
+ }
+ XChangeGC(wi->dpy, wi->gc, GCLineStyle, &values);
}
- XChangeGC(display, gc, GCLineStyle, &values);
}
@@ -290,7 +313,7 @@ DrawLineShape(WidgetInfo *wi,
/*
* Setup GC.
*/
- SetLineStyle(wi->dpy, wi->gc, line_style);
+ SetLineStyle(wi, line_style);
values.foreground = ZnPixel(foreground);
values.line_width = (line_width == 1) ? 0 : line_width;
values.fill_style = FillSolid;
@@ -311,7 +334,7 @@ DrawLineShape(WidgetInfo *wi,
/*
* ReliefIndexOfSegment --
*/
-static long
+static XColor *
ReliefColorOfSegment(ZnReal x1,
ZnReal y1,
ZnReal x2,
@@ -358,7 +381,7 @@ ReliefColorOfSegment(ZnReal x1,
angle,
RadianToDegrees(origin));*/
- return ZnPixel(ZnGetGradientColor(wi->win, gradient, position));
+ return ZnGetGradientColor(wi->win, gradient, position, NULL);
}
@@ -420,8 +443,8 @@ DrawRectangleRelief(WidgetInfo *wi,
bevel[2].x = bevel[1].x - line_width;
bevel[3].x = bevel[0].x + line_width;
XSetForeground(wi->dpy, wi->gc,
- ReliefColorOfSegment(bevel[1].x, bevel[1].y, bevel[0].x, bevel[0].y,
- relief, gradient, wi));
+ ZnPixel(ReliefColorOfSegment(bevel[1].x, bevel[1].y, bevel[0].x, bevel[0].y,
+ relief, gradient, wi)));
XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, bevel, 4, Convex, CoordModeOrigin);
bevel[0] = bevel[1];
@@ -429,8 +452,8 @@ DrawRectangleRelief(WidgetInfo *wi,
bevel[1].y += bbox->height;
bevel[2].y = bevel[1].y - line_width;
XSetForeground(wi->dpy, wi->gc,
- ReliefColorOfSegment(bevel[1].x, bevel[1].y, bevel[0].x, bevel[0].y,
- relief, gradient, wi));
+ ZnPixel(ReliefColorOfSegment(bevel[1].x, bevel[1].y, bevel[0].x, bevel[0].y,
+ relief, gradient, wi)));
XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, bevel, 4, Convex, CoordModeOrigin);
bevel[0] = bevel[1];
@@ -438,8 +461,8 @@ DrawRectangleRelief(WidgetInfo *wi,
bevel[1].x -= bbox->width;
bevel[2].x = bevel[1].x + line_width;
XSetForeground(wi->dpy, wi->gc,
- ReliefColorOfSegment(bevel[1].x, bevel[1].y, bevel[0].x, bevel[0].y,
- relief, gradient, wi));
+ ZnPixel(ReliefColorOfSegment(bevel[1].x, bevel[1].y, bevel[0].x, bevel[0].y,
+ relief, gradient, wi)));
XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, bevel, 4, Convex, CoordModeOrigin);
bevel[0] = bevel[1];
@@ -449,58 +472,26 @@ DrawRectangleRelief(WidgetInfo *wi,
bevel[2].x = bevel[3].x;
bevel[2].y = bbox->y + line_width;
XSetForeground(wi->dpy, wi->gc,
- ReliefColorOfSegment(bevel[1].x, bevel[1].y, bevel[0].x, bevel[0].y,
- relief, gradient, wi));
+ ZnPixel(ReliefColorOfSegment(bevel[1].x, bevel[1].y, bevel[0].x, bevel[0].y,
+ relief, gradient, wi)));
XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, bevel, 4, Convex, CoordModeOrigin);
}
static void
-DoPolygonRelief(ZnPoint *p,
- int num_points,
- int line_width,
- int what_to_do,
- ...)
+DoPolygon(ZnPoint *p,
+ int num_points,
+ int line_width,
+ ZnBool (*cb)(ZnPoint *bevels, int proc_points, void *closure),
+ void *closure)
{
- int i, j, processed_points, *result=NULL;
+ int i, processed_points;
ZnPoint *p1, *p11=NULL, *p2;
ZnPoint pp1, pp2, new_pp1, new_pp2;
ZnPoint perp, c, shift1, shift2;
ZnPoint bevel_points[4];
- XPoint bevel_xpoints[5];
ZnBool folded, closed, colinear;
- WidgetInfo *wi = NULL;
- ReliefStyle relief = 0;
- ZnGradient *gradient = NULL;
- ZnPoint *pp = NULL;
- double *dist = NULL;
- ZnBBox *bbox = NULL;
- va_list var;
-#if 0
- ZnBool toggle=True;
-#endif
ZnReal dx, dy;
-
- va_start(var, what_to_do);
- if (what_to_do == POLYGON_RELIEF_DIST) {
- pp = va_arg(var, ZnPoint *);
- dist = va_arg(var, double *);
- *dist = 1.0e40;
- }
- if (what_to_do == POLYGON_RELIEF_IN_BBOX) {
- bbox = va_arg(var, ZnBBox *);
- result = va_arg(var, int *);
- }
- else if (what_to_do == POLYGON_RELIEF_BBOX) {
- bbox = va_arg(var, ZnBBox *);
- ResetBBox(bbox);
- }
- else if (what_to_do == POLYGON_RELIEF_DRAW) {
- wi = va_arg(var, WidgetInfo *);
- relief = va_arg(var, int);
- gradient = va_arg(var, ZnGradient *);
- }
- va_end(var);
/*
* If the polygon is closed (last point is the same as first) open it by
@@ -644,73 +635,11 @@ DoPolygonRelief(ZnPoint *p,
}
if ((processed_points >= 2) || (!closed && (processed_points == 1))) {
- if (what_to_do == POLYGON_RELIEF_DIST) {
- double new_dist;
-
- new_dist = PolygonToPointDist(bevel_points, 4, pp);
- if (new_dist < 0) {
- new_dist = 0;
- }
- *dist = MIN(*dist, new_dist);
- }
- else if (what_to_do == POLYGON_RELIEF_IN_BBOX) {
- if (processed_points <= 2) {
- *result = PolygonInBBox(bevel_points, 4, bbox, NULL);
- if (*result == 0) {
- return;
- }
- }
- else {
- if (PolygonInBBox(bevel_points, 4, bbox, NULL) != *result) {
- *result = 0;
- return;
- }
- }
- }
- else if (what_to_do == POLYGON_RELIEF_BBOX) {
- int i;
-
- for (i = 0; i < 4; i++) {
- AddPointToBBox(bbox, bevel_points[i].x, bevel_points[i].y);
- }
- }
- else if (what_to_do == POLYGON_RELIEF_DRAW) {
- XGCValues gc_values;
-#if 1
- gc_values.foreground = ReliefColorOfSegment(bevel_points[0].x, bevel_points[0].y,
- bevel_points[3].x, bevel_points[3].y,
- relief, gradient, wi);
-#endif
-#if 0
- gc_values.foreground = toggle ? WhitePixelOfScreen(wi->screen):BlackPixelOfScreen(wi->screen);
-#endif
-#if 0
- gc_values.foreground = colinear ? WhitePixelOfScreen(wi->screen):BlackPixelOfScreen(wi->screen);
-#endif
-#if 0
- toggle = !toggle;
-#endif
- gc_values.fill_style = FillSolid;
- XChangeGC(wi->dpy, wi->gc, GCFillStyle|GCForeground, &gc_values);
-
- for (j = 0; j < 4; j++) {
- bevel_xpoints[j].x = REAL_TO_INT(bevel_points[j].x);
- bevel_xpoints[j].y = REAL_TO_INT(bevel_points[j].y);
- }
-#if 1
- XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, bevel_xpoints, 4,
- Convex, CoordModeOrigin);
-#endif
-#if 0
- bevel_xpoints[4] = bevel_xpoints[0];
- gc_values.line_width = 0;
- XChangeGC(wi->dpy, wi->gc, GCLineWidth, &gc_values);
- XDrawLines(wi->dpy, wi->draw_buffer, wi->gc, bevel_xpoints, 5,
- CoordModeOrigin);
-#endif
+ if ((*cb)(bevel_points, processed_points, closure)) {
+ return;
}
}
-
+
p11 = p1;
p1 = p2;
pp1 = new_pp1;
@@ -727,6 +656,18 @@ DoPolygonRelief(ZnPoint *p,
}
}
+typedef struct {
+ WidgetInfo *wi;
+ ZnPoint *pp;
+ double dist;
+ ZnBBox *bbox;
+ ReliefStyle relief;
+ ZnGradient *gradient;
+ int alpha;
+ ZnBool smooth;
+ int result;
+ ZnBool toggle;
+} PolygonData;
/*
**********************************************************************************
@@ -736,13 +677,28 @@ DoPolygonRelief(ZnPoint *p,
*
**********************************************************************************
*/
+static ZnBool
+PolygonBBoxCB(ZnPoint *bevels,
+ int proc_points,
+ void *closure)
+{
+ ZnBBox *bbox = closure;
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ AddPointToBBox(bbox, bevels[i].x, bevels[i].y);
+ }
+ return 0;
+}
+
void
GetPolygonReliefBBox(ZnPoint *points,
int num_points,
int line_width,
ZnBBox *bbox)
{
- DoPolygonRelief(points, num_points, line_width, POLYGON_RELIEF_BBOX, bbox);
+ ResetBBox(bbox);
+ DoPolygon(points, num_points, line_width, PolygonBBoxCB, bbox);
}
@@ -755,17 +711,40 @@ GetPolygonReliefBBox(ZnPoint *points,
*
**********************************************************************************
*/
+static ZnBool
+PolygonInBBoxCB(ZnPoint *bevels,
+ int proc_points,
+ void *closure)
+{
+ PolygonData *pd = closure;
+
+ if (proc_points <= 2) {
+ pd->result = PolygonInBBox(bevels, 4, pd->bbox, NULL);
+ if (pd->result == 0) {
+ return 1;
+ }
+ }
+ else {
+ if (PolygonInBBox(bevels, 4, pd->bbox, NULL) != pd->result) {
+ pd->result = 0;
+ return 1;
+ }
+ }
+ return 0;
+}
+
int
PolygonReliefInBBox(ZnPoint *points,
int num_points,
int line_width,
ZnBBox *area)
{
- int result;
+ PolygonData pd;
- DoPolygonRelief(points, num_points, line_width, POLYGON_RELIEF_IN_BBOX, area, &result);
+ pd.bbox = area;
+ DoPolygon(points, num_points, line_width, PolygonInBBoxCB, &pd);
- return result;
+ return pd.result;
}
@@ -778,17 +757,37 @@ PolygonReliefInBBox(ZnPoint *points,
*
**********************************************************************************
*/
+static ZnBool
+PolygonDistCB(ZnPoint *bevels,
+ int proc_points,
+ void *closure)
+{
+ PolygonData *pd = closure;
+ double new_dist;
+
+ new_dist = PolygonToPointDist(bevels, 4, pd->pp);
+ if (new_dist < 0.0) {
+ new_dist = 0.0;
+ }
+ if (new_dist < pd->dist) {
+ pd->dist = new_dist;
+ }
+ return 0;
+}
+
double
PolygonReliefToPointDist(ZnPoint *points,
int num_points,
int line_width,
ZnPoint *pp)
{
- double dist;
+ PolygonData pd;
- DoPolygonRelief(points, num_points, line_width, POLYGON_RELIEF_DIST, pp, &dist);
+ pd.dist = 1.0e40;
+ pd.pp = pp;
+ DoPolygon(points, num_points, line_width, PolygonDistCB, &pd);
- return dist;
+ return pd.dist;
}
@@ -800,6 +799,50 @@ PolygonReliefToPointDist(ZnPoint *points,
*
**********************************************************************************
*/
+static ZnBool
+PolygonDrawCB(ZnPoint *bevels,
+ int proc_points,
+ void *closure)
+{
+ PolygonData *pd = closure;
+ WidgetInfo *wi = pd->wi;
+ XPoint bevel_xpoints[5];
+ XGCValues values;
+ int j;
+#if 1
+ values.foreground = ZnPixel(ReliefColorOfSegment(bevels[0].x, bevels[0].y,
+ bevels[3].x, bevels[3].y,
+ pd->relief, pd->gradient, pd->wi));
+#endif
+#if 0
+ values.foreground = toggle ? WhitePixelOfScreen(wi->screen):BlackPixelOfScreen(wi->screen);
+#endif
+#if 0
+ values.foreground = colinear ? WhitePixelOfScreen(wi->screen):BlackPixelOfScreen(wi->screen);
+#endif
+#if 0
+ toggle = !toggle;
+#endif
+ values.fill_style = FillSolid;
+ XChangeGC(wi->dpy, wi->gc, GCFillStyle|GCForeground, &values);
+
+ for (j = 0; j < 4; j++) {
+ bevel_xpoints[j].x = REAL_TO_INT(bevels[j].x);
+ bevel_xpoints[j].y = REAL_TO_INT(bevels[j].y);
+ }
+#if 1
+ XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, bevel_xpoints, 4,
+ Convex, CoordModeOrigin);
+#endif
+#if 0
+ bevel_xpoints[4] = bevel_xpoints[0];
+ values.line_width = 0;
+ XChangeGC(wi->dpy, wi->gc, GCLineWidth, &values);
+ XDrawLines(wi->dpy, wi->draw_buffer, wi->gc, bevel_xpoints, 5, CoordModeOrigin);
+#endif
+ return 0;
+}
+
void
DrawPolygonRelief(WidgetInfo *wi,
ReliefStyle relief,
@@ -808,230 +851,632 @@ DrawPolygonRelief(WidgetInfo *wi,
int num_points,
int line_width)
{
+ PolygonData pd;
+
+ pd.wi = wi;
+ pd.gradient = gradient;
/*
* Grooves and ridges are drawn with two calls. The first
* with the original width, the second with half the width.
*/
if ((relief == RELIEF_RIDGE) || (relief == RELIEF_GROOVE)) {
- DoPolygonRelief(points, num_points, line_width, POLYGON_RELIEF_DRAW, wi,
- (int) (relief==RELIEF_GROOVE)?RELIEF_BEVEL_OUT:RELIEF_BEVEL_IN,
- gradient);
- DoPolygonRelief(points, num_points, line_width/2, POLYGON_RELIEF_DRAW, wi,
- (int) (relief==RELIEF_GROOVE)?RELIEF_BEVEL_IN:RELIEF_BEVEL_OUT,
- gradient);
+ pd.relief = (relief==RELIEF_GROOVE)?RELIEF_BEVEL_OUT:RELIEF_BEVEL_IN;
+ DoPolygon(points, num_points, line_width, PolygonDrawCB, &pd);
+ pd.relief = (relief==RELIEF_GROOVE)?RELIEF_BEVEL_IN:RELIEF_BEVEL_OUT;
+ DoPolygon(points, num_points, line_width/2, PolygonDrawCB, &pd);
}
else {
- DoPolygonRelief(points, num_points, line_width, POLYGON_RELIEF_DRAW, wi,
- (int) relief, gradient);
+ pd.relief = relief;
+ DoPolygon(points, num_points, line_width, PolygonDrawCB, &pd);
}
}
-static void
-DrawRadialGradient(struct _WidgetInfo *wi,
- ZnGradient *grad,
- XRectangle *bbox)
+/*
+ **********************************************************************************
+ *
+ * RenderPolygonRelief --
+ * Draw the bevels around path using alpha enabled rendering.
+ *
+ **********************************************************************************
+ */
+#ifdef GLX
+static ZnBool
+PolygonRenderCB(ZnPoint *bevels,
+ int proc_points,
+ void *closure)
{
+ PolygonData *pd = closure;
+ int i;
+ XColor *color = ReliefColorOfSegment(bevels[0].x, bevels[0].y,
+ bevels[3].x, bevels[3].y,
+ pd->relief, pd->gradient, pd->wi);
+ glColor4us(color->red, color->green, color->blue, pd->alpha*65535/100);
+ glBegin(GL_QUADS);
+ for (i = 0; i < 4; i++) {
+ glVertex2f(bevels[i].x, bevels[i].y);
+ }
+ glEnd();
+
+ return 0;
}
-static void
-DrawAxialGradient(struct _WidgetInfo *wi,
- ZnGradient *grad,
- XRectangle *bbox)
+void
+RenderPolygonRelief(WidgetInfo *wi,
+ ReliefStyle relief,
+ ZnGradient *gradient,
+ int alpha,
+ ZnBool smooth,
+ ZnPoint *points,
+ int num_points,
+ int line_width)
{
-#define NUM_STENCILS 8
- static int s[NUM_STENCILS] = { 0, 1, 3, 5, 7, 9, 11, 13 };
- int angle = grad->g.angle;
- int num_shades = grad->num_shades;
- int num_shades_2 = num_shades /2;
- int num_colors = grad->num_colors;
- int x, y, span, stop, i, j, k, p;
- int *startp, *widthp, width, height;
- int position;
- ZnReal pos, pos_span_bc, pos_span_ac, pos_span;
- ZnReal stencil_step_bc, stencil_step_ac, stencil_step;
- short origin, limit;
- ZnBool dir;
- ZnGradientColor *color, *next_color;
- XColor *shade;
+ PolygonData pd;
+
+ pd.wi = wi;
+ pd.gradient = gradient;
+ pd.alpha = alpha;
+ pd.smooth = smooth;
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
/*
- * We can only handle 0, 90, 180, 270.
+ * Grooves and ridges are drawn with two calls. The first
+ * with the original width, the second with half the width.
*/
- angle = (angle / 90) * 90;
+ if ((relief == RELIEF_RIDGE) || (relief == RELIEF_GROOVE)) {
+ pd.relief = (relief==RELIEF_GROOVE)?RELIEF_BEVEL_OUT:RELIEF_BEVEL_IN;
+ DoPolygon(points, num_points, line_width, PolygonRenderCB, &pd);
+ pd.relief = (relief==RELIEF_GROOVE)?RELIEF_BEVEL_IN:RELIEF_BEVEL_OUT;
+ DoPolygon(points, num_points, line_width/2, PolygonRenderCB, &pd);
+ }
+ else {
+ pd.relief = relief;
+ DoPolygon(points, num_points, line_width, PolygonRenderCB, &pd);
+ }
+}
+
+void
+RenderImage(struct _WidgetInfo *wi,
+ ImageBits *image, /* ImageBits or BitmapBits */
+ XColor *color,
+ int alpha,
+ ZnPoint *origin)
+{
+ ZnReal nx, ny;
+
+ alpha = alpha*65535/100;
+ nx = origin->x + image->width;
+ ny = origin->y + image->height;
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ glEnable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, image->texture);
+ if (color) {
+ glColor4us(color->red, color->green, color->blue, alpha);
+ }
+ else {
+ glColor4us(65535, 65535, 65535, alpha);
+ }
+ glBegin(GL_QUADS);
+ glTexCoord2f(0.0, 0.0);
+ glVertex2f(origin->x, origin->y);
+ glTexCoord2f(0.0, image->t);
+ glVertex2f(origin->x, ny);
+ glTexCoord2f(image->s, image->t);
+ glVertex2f(nx, ny);
+ glTexCoord2f(image->s, 0.0);
+ glVertex2f(nx, origin->y);
+ glEnd();
+ glDisable(GL_TEXTURE_2D);
+}
+
+void
+RenderTile(struct _WidgetInfo *wi,
+ ImageBits *tile,
+ ZnGradient *gradient,
+ void cb(void *),
+ void *closure,
+ ZnPoint *quad) /* Right now it's a ZnBBox */
+{
+ ZnReal x, y, nx, ny, lx, ly, s, t;
+ int alpha, num_clips = ZnListSize(wi->clip_stack);
- x = bbox->x;
- y = bbox->y;
- if ((angle == 0) || (angle == 180)) {
- startp = &x;
- origin = bbox->x;
- limit = bbox->x+bbox->width;
- height = bbox->height;
- widthp = &width;
+ if (gradient) {
+ ZnGetGradientColor(wi->win, gradient, 0.0, &alpha);
+ alpha = alpha*65535/100;
}
else {
- startp = &y;
- origin = bbox->y;
- limit = bbox->y+bbox->height;
- width = bbox->width;
- widthp = &height;
+ alpha = 65535;
}
- dir = True;
- if ((angle == 180) || (angle == 270)) {
- dir = False;
+ if (cb) {
+ /*
+ * Setup the stencil buffer with the shape to be drawn.
+ */
+ if (!num_clips) {
+ glEnable(GL_STENCIL_TEST);
+ }
+ glStencilFunc(GL_EQUAL, num_clips, 0xFF);
+ glStencilOp(GL_KEEP, GL_INCR, GL_INCR);
+ glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+ (*cb)(closure);
+
+ glStencilFunc(GL_EQUAL, num_clips+1, 0xFF);
+ glStencilOp(GL_KEEP, GL_DECR, GL_DECR);
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
}
-
- span = limit - origin;
/*
- * External loop iterates over the gradient colors.
+ * Then texture map the quad through the shape.
+ * The rectangle is drawn using quads, each
+ * quad matching the size of the texture tile.
*/
- XSetTSOrigin(wi->dpy, wi->gc, bbox->x, bbox->y);
- ZnRealizeGradient(grad, wi->win);
- if (dir) {
- *startp = origin;
+ glEnable(GL_TEXTURE_2D);
+ glColor4us(65535, 65535, 65535, alpha);
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ glBindTexture(GL_TEXTURE_2D, tile->texture);
+
+ y = quad[0].y;
+ lx = quad[1].x;
+ ly = quad[1].y;
+ glBegin(GL_QUADS);
+ do {
+ x = quad[0].x;
+ t = 1.0;
+ ny = y + tile->height;
+ if (ny > ly) {
+ ny = ly;
+ t = (ly - y) / (ZnReal) tile->height;
+ }
+ t *= tile->t;
+ do {
+ s = 1.0;
+ nx = x + tile->width;
+ if (nx > lx) {
+ nx = lx;
+ s = (lx - x) / (ZnReal) tile->width;
+ }
+ s *= tile->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;
}
- else {
- stop = limit;
+ while (y != ly);
+ glEnd();
+
+ if (cb) {
+ glStencilFunc(GL_EQUAL, num_clips, 0xFF);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+ if (!num_clips) {
+ glDisable(GL_STENCIL_TEST);
+ }
}
- for (k = 0; k < num_colors-1; k++) {
+ glDisable(GL_TEXTURE_2D);
+}
+
+void
+RenderGradient(struct _WidgetInfo *wi,
+ ZnGradient *gradient,
+ void cb(void *),
+ void *closure,
+ ZnPoint *quad)
+{
+ int alpha, angle, i, j;
+ int type = gradient->type;
+ int num_shades = gradient->num_shades;
+ XColor *color;
+ ZnPoint p;
+ ZnPoint dposa, dposb, dposc, dposd;
+ ZnPoint dcontrol;
+ ZnReal npos, pos, control;
+ int num_clips = ZnListSize(wi->clip_stack);
+ ZnPoint iquad[4];
+
+ if (!cb) { /* Render an axial gradient in the quad */
+ if (type != ZN_AXIAL_GRADIENT) {
+ type = ZN_AXIAL_GRADIENT;
+ angle = 0;
+ }
+ else {
+ angle = gradient->g.angle;
+ }
/*
- * Mid loop iterates over the current color shades.
+ * Adjust the quad for 90 180 and 270 degrees axial
+ * gradients. Other angles not supported.
*/
- color = grad->colors[k];
- next_color = grad->colors[k+1];
- position = color->position;
- pos_span_bc = (next_color->position - position)*color->control/100.0;
- pos_span_ac = (next_color->position - position)-pos_span_bc;
- stencil_step_bc = pos_span_bc/(num_shades_2*NUM_STENCILS);
- stencil_step_ac = pos_span_ac/(num_shades_2*NUM_STENCILS);
- /*printf("span bc %g, span ac %g, stencil bc %g, stencil ac %g\n",
- pos_span_bc, pos_span_ac, stencil_step_bc, stencil_step_ac);*/
- pos_span = pos_span_bc;
- stencil_step = stencil_step_bc;
- pos = position;
- for (j = 0; j < num_shades; j++) {
- p = j+1;
- if (j >= num_shades_2) {
- pos = position + pos_span_bc;
- pos_span = pos_span_ac;
- stencil_step = stencil_step_ac;
- p -= num_shades_2;
- }
- if (dir) {
- stop = origin + span*(pos + (pos_span*p/(num_shades_2)))/100;
- }
- else {
- *startp = limit - span*(pos + (pos_span*p/(num_shades_2)))/100;
- }
- *widthp = stop - *startp;
- XSetFillStyle(wi->dpy, wi->gc, FillSolid);
- shade = color->shades[j];
- XSetForeground(wi->dpy, wi->gc, ZnPixel(shade));
- XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc, x, y, width, height);
-#if 1
- /*
- * Inner loop iterates over the stencils used to
- * smooth the current shade.
- */
- p--;
- if (dir) {
- *startp = origin + span*(pos + (stencil_step*(p*NUM_STENCILS+1)))/100;
- }
- else {
- stop = limit - span*(pos + (stencil_step*(p*NUM_STENCILS+1)))/100;
- }
- XSetFillStyle(wi->dpy, wi->gc, FillStippled);
- if (j < num_shades-1) {
- shade = color->shades[j+1];
- }
- else {
- shade = next_color->shades[0];
+ switch (angle) {
+ case 90:
+ iquad[0] = quad[3];
+ iquad[3] = quad[2];
+ iquad[2] = quad[1];
+ iquad[1] = quad[0];
+ quad = iquad;
+ break;
+ case 180:
+ iquad[0] = quad[2];
+ iquad[3] = quad[1];
+ iquad[2] = quad[0];
+ iquad[1] = quad[3];
+ quad = iquad;
+ break;
+ case 270:
+ iquad[0] = quad[1];
+ iquad[3] = quad[0];
+ iquad[2] = quad[3];
+ iquad[1] = quad[2];
+ quad = iquad;
+ break;
+ }
+ }
+
+ if (cb) {
+ /*
+ * Draw the gradient shape in the stencil using the provided
+ * callback.
+ */
+ if (!num_clips) {
+ glEnable(GL_STENCIL_TEST);
+ }
+ glStencilFunc(GL_EQUAL, num_clips, 0xFF);
+ glStencilOp(GL_KEEP, GL_INCR, GL_INCR);
+ glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+ (*cb)(closure);
+ glStencilFunc(GL_EQUAL, num_clips+1, 0xFF);
+ glStencilOp(GL_KEEP, GL_DECR, GL_DECR);
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ }
+
+ if (type == ZN_AXIAL_GRADIENT) {
+ /*
+ * Then fill the axial gradient using the provided
+ * quad and colors. The stencil will be restored
+ * to its previous state in the process.
+ */
+ glBegin(GL_QUAD_STRIP);
+ for (i = 0; i < gradient->num_colors; i++) {
+ color = gradient->colors[i]->shades[0];
+ alpha = gradient->colors[i]->alpha*65535/100;
+ glColor4us(color->red, color->green, color->blue, alpha);
+
+ pos = gradient->colors[i]->position;
+ control = gradient->colors[i]->control;
+ dposa.x = (quad[1].x - quad[0].x)*pos/100.0;
+ dposa.y = (quad[1].y - quad[0].y)*pos/100.0;
+ p.x = quad[0].x + dposa.x;
+ p.y = quad[0].y + dposa.y;
+ glVertex2f(p.x, p.y);
+
+ dposb.x = (quad[2].x - quad[3].x)*pos/100.0;
+ dposb.y = (quad[2].y - quad[3].y)*pos/100.0;
+ p.x = quad[3].x + dposb.x;
+ p.y = quad[3].y + dposb.y;
+ glVertex2f(p.x, p.y);
+
+ if ((control != 50.0) && (i != gradient->num_colors-1)) {
+ color = gradient->colors[i]->shades[num_shades/2];
+ alpha = gradient->colors[i]->alpha*65535/100;
+ glColor4us(color->red, color->green, color->blue, alpha);
+
+ npos = gradient->colors[i+1]->position;
+ dposc.x = (quad[1].x - quad[0].x)*npos/100.0;
+ dposc.y = (quad[1].y - quad[0].y)*npos/100.0;
+ dcontrol.x = (dposc.x - dposa.x)*control/100.0;
+ dcontrol.y = (dposc.y - dposa.y)*control/100.0;
+ p.x = quad[0].x + dposa.x + dcontrol.x;
+ p.y = quad[0].y + dposa.y + dcontrol.y;
+ glVertex2f(p.x, p.y);
+
+ dposd.x = (quad[2].x - quad[3].x)*npos/100.0;
+ dposd.y = (quad[2].y - quad[3].y)*npos/100.0;
+ dcontrol.x = (dposd.x - dposb.x)*control/100.0;
+ dcontrol.y = (dposd.y - dposb.y)*control/100.0;
+ p.x = quad[3].x + dposb.x + dcontrol.x;
+ p.y = quad[3].y + dposb.y + dcontrol.y;
+ glVertex2f(p.x, p.y);
}
- XSetForeground(wi->dpy, wi->gc, ZnPixel(shade));
- for (i = 1; i < NUM_STENCILS; i++) {
- if (dir) {
- stop = origin + span*(pos + (stencil_step*(p*NUM_STENCILS+i+1)))/100;
- }
- else {
- *startp = limit - span*(pos + (stencil_step*(p*NUM_STENCILS+i+1)))/100;
- }
- *widthp = stop - *startp;
- XSetStipple(wi->dpy, wi->gc, wi->alpha_stipples[s[i]]);
- XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc, x, y, width, height);
- if (dir) {
- *startp = stop;
- }
- else {
- stop = *startp;
+
+ }
+ glEnd();
+ }
+ else if (type == ZN_RADIAL_GRADIENT) {
+ ZnReal x, y, radius, radius2, radius3;
+ int num_p, alpha2;
+ ZnPoint *genarc;
+ XColor *color2;
+
+ genarc = GetCirclePoints(3, ZN_CIRCLE_MEDIUM, 0, 360, &num_p, NULL);
+ radius = 0;
+ color = gradient->colors[0]->shades[0];
+ alpha = gradient->colors[0]->alpha*65535/100;
+ control = gradient->colors[0]->control;
+ for (j = 1; j < gradient->num_colors; j++) {
+ radius2 = quad[1].x*gradient->colors[j]->position/100.0;
+ if ((control != 50) && (j != gradient->num_colors-1)) {
+ glBegin(GL_QUAD_STRIP);
+ color2 = gradient->colors[j-1]->shades[num_shades/2];
+ alpha2 = gradient->colors[j-1]->alpha*65535/100;
+ radius3 = radius + (radius2-radius)*control/100.0;
+ for (i = 0; i < num_p; i++) {
+ x = quad[0].x+genarc[i].x*radius;
+ y = quad[0].y+genarc[i].y*radius;
+ glColor4us(color->red, color->green, color->blue, alpha);
+ glVertex2f(x, y);
+ x = quad[0].x+genarc[i].x*radius3;
+ y = quad[0].y+genarc[i].y*radius3;
+ glColor4us(color2->red, color2->green, color2->blue, alpha);
+ glVertex2f(x, y);
}
+ radius = radius3;
+ color = color2;
+ alpha = alpha2;
+ glEnd();
}
-#else
- if (dir) {
- *startp = stop;
+ glBegin(GL_QUAD_STRIP);
+ color2 = gradient->colors[j]->shades[0];
+ alpha2 = gradient->colors[j]->alpha*65535/100;
+ for (i = 0; i < num_p; i++) {
+ x = quad[0].x+genarc[i].x*radius;
+ y = quad[0].y+genarc[i].y*radius;
+ glColor4us(color->red, color->green, color->blue, alpha);
+ glVertex2f(x, y);
+ x = quad[0].x+genarc[i].x*radius2;
+ y = quad[0].y+genarc[i].y*radius2;
+ glColor4us(color2->red, color2->green, color2->blue, alpha);
+ glVertex2f(x, y);
}
- else {
- stop = *startp;
- }
-#endif
+ glEnd();
+ radius = radius2;
+ color = color2;
+ alpha = alpha2;
+ control = gradient->colors[j]->control;
+ }
+ }
+
+ if (cb) {
+ /*
+ * Restore the previous GL state.
+ */
+ glStencilFunc(GL_EQUAL, num_clips, 0xFF);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+ if (!num_clips) {
+ glDisable(GL_STENCIL_TEST);
}
}
}
+
void
-DrawPolygonGradient(struct _WidgetInfo *wi,
- ZnGradient *gradient,
- ZnPoly *poly,
- ZnBBox *bbox)
+RenderHollowDot(struct _WidgetInfo *wi,
+ ZnPoint *p,
+ ZnReal size)
{
- ZnBBox lbbox;
- XRectangle r;
- int i;
-
- /*
- * The polygon has to be reduced for this to give meaningful
- * results.
- */
- if (!bbox) {
- ResetBBox(&lbbox);
- for (i = 0; i < poly->num_contours; i++) {
- if (!poly->holes[i]) {
- AddPointsToBBox(&lbbox, poly->contours[i].points,
- poly->contours[i].num_points);
+ int num_clips = ZnListSize(wi->clip_stack);
+
+ if (!num_clips) {
+ glEnable(GL_STENCIL_TEST);
+ }
+ glStencilFunc(GL_EQUAL, num_clips, 0xFF);
+ glStencilOp(GL_KEEP, GL_INCR, GL_INCR);
+ glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+ glPointSize(size-2);
+ glBegin(GL_POINTS);
+ glVertex2f(p->x, p->y);
+ glEnd();
+
+ glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ glPointSize(size);
+ glBegin(GL_POINTS);
+ glVertex2f(p->x, p->y);
+ glEnd();
+
+ glStencilFunc(GL_EQUAL, num_clips+1, 0xFF);
+ glStencilOp(GL_KEEP, GL_DECR, GL_DECR);
+ glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+ glPointSize(size-2);
+ glBegin(GL_POINTS);
+ glVertex2f(p->x, p->y);
+ glEnd();
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+
+ if (!num_clips) {
+ glDisable(GL_STENCIL_TEST);
+ }
+}
+#endif
+
+
+#ifdef GLX
+/* Copyright (c) Mark J. Kilgard, 1997. */
+
+/* This program is freely distributable without licensing fees and is
+ provided without guarantee or warrantee expressed or implied. This
+ program is -not- in the public domain. */
+
+#include <GL/glu.h>
+
+static TexGlyphVertexInfo *
+getTCVI(TexFont *txf,
+ int c)
+{
+ TexGlyphVertexInfo *tgvi;
+
+ /* Automatically substitute uppercase letters with lowercase if not
+ uppercase available (and vice versa). */
+ if ((c >= txf->min_glyph) && (c < txf->min_glyph + txf->range)) {
+ tgvi = txf->lut[c - txf->min_glyph];
+ if (tgvi) {
+ return tgvi;
+ }
+ if (islower(c)) {
+ c = toupper(c);
+ if ((c >= txf->min_glyph) && (c < txf->min_glyph + txf->range)) {
+ return txf->lut[c - txf->min_glyph];
+ }
+ }
+ if (isupper(c)) {
+ c = tolower(c);
+ if ((c >= txf->min_glyph) && (c < txf->min_glyph + txf->range)) {
+ return txf->lut[c - txf->min_glyph];
}
}
- bbox = &lbbox;
- }
- BBox2XRect(bbox, &r);
- ITEM_P.PushClip(wi, poly, False, True);
- if (gradient->type == ZN_AXIAL_GRADIENT) {
- DrawAxialGradient(wi, gradient, &r);
}
- else if (gradient->type == ZN_RADIAL_GRADIENT) {
- DrawRadialGradient(wi, gradient, &r);
+ /* ZnWarning("Tried to access unavailable texture font character");*/
+ printf("Tried to access unavailable texture font character '%c'(%d)\n", c, c);
+ return txf->lut[(int)'!' - txf->min_glyph];
+}
+
+
+void
+txfRenderGlyph(TexFont *txf,
+ int c)
+{
+ TexGlyphVertexInfo *tgvi;
+
+ tgvi = getTCVI(txf, c);
+
+ glBegin(GL_QUADS);
+ glTexCoord2fv(tgvi->t0);
+ glVertex2sv(tgvi->v0);
+ glTexCoord2fv(tgvi->t1);
+ glVertex2sv(tgvi->v1);
+ glTexCoord2fv(tgvi->t2);
+ glVertex2sv(tgvi->v2);
+ glTexCoord2fv(tgvi->t3);
+ glVertex2sv(tgvi->v3);
+ glEnd();
+ glTranslatef(tgvi->advance, 0.0, 0.0);
+}
+
+void
+txfRenderString(TexFont *txf,
+ unsigned char *string,
+ int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++) {
+ txfRenderGlyph(txf, string[i]);
}
- ITEM_P.PopClip(wi, True);
}
+enum {
+ MONO, TOP_BOTTOM, LEFT_RIGHT, FOUR
+};
+
void
-DrawRectangleGradient(struct _WidgetInfo *wi,
- ZnGradient *grad,
- XRectangle *bbox)
+txfRenderFancyString(TexFont *txf,
+ unsigned char *string,
+ int len)
{
- if (grad->type == ZN_AXIAL_GRADIENT) {
- DrawAxialGradient(wi, grad, bbox);
+ TexGlyphVertexInfo *tgvi;
+ GLubyte c[4][3];
+ int mode = MONO;
+ int i;
+
+ for (i = 0; i < len; i++) {
+ if (string[i] == 27) {
+ switch (string[i + 1]) {
+ case 'M':
+ mode = MONO;
+ glColor3ubv((GLubyte *) & string[i + 2]);
+ i += 4;
+ break;
+ case 'T':
+ mode = TOP_BOTTOM;
+ memcpy(c, &string[i + 2], 6);
+ i += 7;
+ break;
+ case 'L':
+ mode = LEFT_RIGHT;
+ memcpy(c, &string[i + 2], 6);
+ i += 7;
+ break;
+ case 'F':
+ mode = FOUR;
+ memcpy(c, &string[i + 2], 12);
+ i += 13;
+ break;
+ }
+ } else {
+ switch (mode) {
+ case MONO:
+ txfRenderGlyph(txf, string[i]);
+ break;
+ case TOP_BOTTOM:
+ tgvi = getTCVI(txf, string[i]);
+ glBegin(GL_QUADS);
+ glColor3ubv(c[0]);
+ glTexCoord2fv(tgvi->t0);
+ glVertex2sv(tgvi->v0);
+ glTexCoord2fv(tgvi->t1);
+ glVertex2sv(tgvi->v1);
+ glColor3ubv(c[1]);
+ glTexCoord2fv(tgvi->t2);
+ glVertex2sv(tgvi->v2);
+ glTexCoord2fv(tgvi->t3);
+ glVertex2sv(tgvi->v3);
+ glEnd();
+ glTranslatef(tgvi->advance, 0.0, 0.0);
+ break;
+ case LEFT_RIGHT:
+ tgvi = getTCVI(txf, string[i]);
+ glBegin(GL_QUADS);
+ glColor3ubv(c[0]);
+ glTexCoord2fv(tgvi->t0);
+ glVertex2sv(tgvi->v0);
+ glColor3ubv(c[1]);
+ glTexCoord2fv(tgvi->t1);
+ glVertex2sv(tgvi->v1);
+ glColor3ubv(c[1]);
+ glTexCoord2fv(tgvi->t2);
+ glVertex2sv(tgvi->v2);
+ glColor3ubv(c[0]);
+ glTexCoord2fv(tgvi->t3);
+ glVertex2sv(tgvi->v3);
+ glEnd();
+ glTranslatef(tgvi->advance, 0.0, 0.0);
+ break;
+ case FOUR:
+ tgvi = getTCVI(txf, string[i]);
+ glBegin(GL_QUADS);
+ glColor3ubv(c[0]);
+ glTexCoord2fv(tgvi->t0);
+ glVertex2sv(tgvi->v0);
+ glColor3ubv(c[1]);
+ glTexCoord2fv(tgvi->t1);
+ glVertex2sv(tgvi->v1);
+ glColor3ubv(c[2]);
+ glTexCoord2fv(tgvi->t2);
+ glVertex2sv(tgvi->v2);
+ glColor3ubv(c[3]);
+ glTexCoord2fv(tgvi->t3);
+ glVertex2sv(tgvi->v3);
+ glEnd();
+ glTranslatef(tgvi->advance, 0.0, 0.0);
+ break;
+ }
+ }
}
- else if (grad->type == ZN_RADIAL_GRADIENT) {
- ZnPoly poly;
- ZnPoint points[2];
-
- points[0].x = bbox->x;
- points[0].y = bbox->y;
- points[1].x = bbox->x + bbox->width;
- points[1].y = bbox->x + bbox->height;
- POLY_CONTOUR1(&poly, points, 2);
- ITEM_P.PushClip(wi, &poly, False, True);
- DrawRadialGradient(wi, grad, bbox);
- ITEM_P.PopClip(wi, True);
+}
+
+int
+txfInFont(TexFont * txf, int c)
+{
+ /* NOTE: No uppercase/lowercase substituion. */
+ if ((c >= txf->min_glyph) && (c < txf->min_glyph + txf->range)) {
+ if (txf->lut[c - txf->min_glyph]) {
+ return 1;
+ }
}
+ return 0;
}
+#endif