aboutsummaryrefslogtreecommitdiff
path: root/generic/Draw.c
diff options
context:
space:
mode:
Diffstat (limited to 'generic/Draw.c')
-rw-r--r--generic/Draw.c369
1 files changed, 194 insertions, 175 deletions
diff --git a/generic/Draw.c b/generic/Draw.c
index c77d59e..ce48b3d 100644
--- a/generic/Draw.c
+++ b/generic/Draw.c
@@ -317,14 +317,14 @@ ReliefColorOfSegment(ZnReal x1,
ZnReal x2,
ZnReal y2,
ReliefStyle relief,
- ZnColorGradient gradient,
+ ZnGradient *gradient,
WidgetInfo *wi)
{
- ZnReal angle, angle_step, origin;
- int color_index, num_colors;
+ ZnReal angle, angle_step, origin, position;
+ int num_colors;
- num_colors = ZnColorGradientSpan(gradient);
- angle_step = M_PI / (num_colors-1);
+ num_colors = RELIEF_STEPS*2+1;
+ angle_step = 2*M_PI / num_colors;
origin = -(DegreesToRadian(wi->light_angle))-(angle_step/2.0);
if (relief == RELIEF_BEVEL_IN) {
origin += M_PI;
@@ -337,25 +337,13 @@ ReliefColorOfSegment(ZnReal x1,
while (angle > 2*M_PI) {
angle -= 2*M_PI;
}
- color_index = (int) (angle/angle_step);
- if (color_index > num_colors-1) {
- color_index = 2*(num_colors-1)-color_index;
- }
- if ((color_index < 0) || (color_index >= num_colors)) {
- printf("Color index out of gradient (should not happen).\n");
- if (color_index < 0) {
- color_index = 0;
- }
- if (color_index >= num_colors) {
- color_index = num_colors-1;
- }
- }
- /*printf("color index %d(), angle %g(), origin %g\n",
- color_index,
+ position = (angle/angle_step)*(100/num_colors);
+ /*printf("position %g, angle %g, origin %g\n",
+ position,
RadianToDegrees(angle),
RadianToDegrees(origin));*/
- return ZnPixel(ZnColorGradientColor(wi->win, gradient, color_index));
+ return ZnPixel(ZnGetGradientColor(wi->win, gradient, position));
}
@@ -370,7 +358,7 @@ ReliefColorOfSegment(ZnReal x1,
void
DrawRectangleRelief(WidgetInfo *wi,
ReliefStyle relief,
- ZnColorGradient gradient,
+ ZnGradient *gradient,
XRectangle *bbox,
unsigned int line_width)
{
@@ -468,7 +456,7 @@ DoPolygonRelief(ZnPoint *p,
ZnBool folded, closed, colinear;
WidgetInfo *wi = NULL;
ReliefStyle relief = 0;
- ZnColorGradient gradient = NULL;
+ ZnGradient *gradient = NULL;
ZnPoint *pp = NULL;
double *dist = NULL;
ZnBBox *bbox = NULL;
@@ -495,7 +483,7 @@ DoPolygonRelief(ZnPoint *p,
else if (what_to_do == POLYGON_RELIEF_DRAW) {
wi = va_arg(var, WidgetInfo *);
relief = va_arg(var, int);
- gradient = va_arg(var, ZnColorGradient);
+ gradient = va_arg(var, ZnGradient *);
}
va_end(var);
@@ -798,12 +786,12 @@ PolygonReliefToPointDist(ZnPoint *points,
**********************************************************************************
*/
void
-DrawPolygonRelief(WidgetInfo *wi,
- ReliefStyle relief,
- ZnColorGradient gradient,
- ZnPoint *points,
- int num_points,
- int line_width)
+DrawPolygonRelief(WidgetInfo *wi,
+ ReliefStyle relief,
+ ZnGradient *gradient,
+ ZnPoint *points,
+ int num_points,
+ int line_width)
{
/*
* Grooves and ridges are drawn with two calls. The first
@@ -823,10 +811,161 @@ DrawPolygonRelief(WidgetInfo *wi,
}
}
+static void
+DrawRadialGradient(struct _WidgetInfo *wi,
+ ZnGradient *grad,
+ XRectangle *bbox)
+{
+}
+
+static void
+DrawAxialGradient(struct _WidgetInfo *wi,
+ ZnGradient *grad,
+ XRectangle *bbox)
+{
+#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;
+
+ /*
+ * We can only handle 0, 90, 180, 270.
+ */
+ angle = (angle / 90) * 90;
+
+ 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;
+ }
+ else {
+ startp = &y;
+ origin = bbox->y;
+ limit = bbox->y+bbox->height;
+ width = bbox->width;
+ widthp = &height;
+ }
+
+ dir = True;
+ if ((angle == 180) || (angle == 270)) {
+ dir = False;
+ }
+
+ span = limit - origin;
+
+ /*
+ * External loop iterates over the gradient colors.
+ */
+ XSetTSOrigin(wi->dpy, wi->gc, bbox->x, bbox->y);
+ ZnRealizeGradient(grad, wi->win);
+ if (dir) {
+ *startp = origin;
+ }
+ else {
+ stop = limit;
+ }
+ for (k = 0; k < num_colors-1; k++) {
+ /*
+ * Mid loop iterates over the current color shades.
+ */
+ 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];
+ }
+ 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;
+ }
+ }
+#else
+ if (dir) {
+ *startp = stop;
+ }
+ else {
+ stop = *startp;
+ }
+#endif
+ }
+ }
+}
+
void
DrawPolygonGradient(struct _WidgetInfo *wi,
- ZnGradientGeom grad_geom,
- ZnColorGradient grad_color,
+ ZnGradient *gradient,
ZnPoly *poly,
ZnBBox *bbox)
{
@@ -842,162 +981,42 @@ DrawPolygonGradient(struct _WidgetInfo *wi,
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);
+ AddPointsToBBox(&lbbox, poly->contours[i].points,
+ poly->contours[i].num_points);
}
}
bbox = &lbbox;
}
BBox2XRect(bbox, &r);
ITEM_P.PushClip(wi, poly, False, True);
- DrawRectangleGradient(wi, grad_geom, grad_color, &r);
+ if (gradient->type == ZN_AXIAL_GRADIENT) {
+ DrawAxialGradient(wi, gradient, &r);
+ }
+ else if (gradient->type == ZN_RADIAL_GRADIENT) {
+ DrawRadialGradient(wi, gradient, &r);
+ }
ITEM_P.PopClip(wi, True);
}
void
DrawRectangleGradient(struct _WidgetInfo *wi,
- ZnGradientGeom grad_geom,
- ZnColorGradient grad_color,
+ ZnGradient *grad,
XRectangle *bbox)
{
- static int s[] = { 0, 13, 11, 9, 7, 5, 3, 1 };
- int steps = ZnColorGradientSpan(grad_color);
- ZnReal d1, d2;
- int angle = grad_geom->angle;
- int x, y, c, y_d2, w, h, i, j;
- int *optr, *hptr;
- short yorig, ycorner;
- ZnBool dir;
- XColor *col;
-
- /*
- * We can only hangle 0, 90, 180, 270.
- */
- angle = (angle / 90) * 90;
-
- x = bbox->x;
- y = bbox->y;
- if ((angle == 90) || (angle == 270)) {
- optr = &x;
- yorig = bbox->x;
- ycorner = bbox->x+bbox->width;
- h = bbox->height;
- hptr = &w;
- d1 = grad_geom->d1*bbox->width/100;
- d2 = grad_geom->d2*bbox->width/100;
- }
- else {
- optr = &y;
- yorig = bbox->y;
- ycorner = bbox->y+bbox->height;
- w = bbox->width;
- hptr = &h;
- d1 = grad_geom->d1*bbox->height/100.0;
- d2 = bbox->height*(1.0-grad_geom->d2/100.0);
- }
- d1 = REAL_TO_INT(d1);
- d2 = REAL_TO_INT(d2);
-
- dir = True;
- if ((angle == 180) || (angle == 270)) {
- dir = False;
+ if (grad->type == ZN_AXIAL_GRADIENT) {
+ DrawAxialGradient(wi, grad, bbox);
}
-#if 0
- XSetFillStyle(wi->dpy, wi->gc, FillSolid);
- c = ycorner;
- for (i = 2, j = steps-1; i < steps; i += 2, j--) {
- *optr = REAL_TO_INT(ycorner - (i * d2 / steps));
- *hptr = c - *optr;
- XSetForeground(wi->dpy, wi->gc,
- ZnPixel(ZnColorGradientColor(wi->win, grad_color,
- dir?j:steps-1-j)));
- XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc, x, y, w, h);
- c = *optr;
- }
- y_d2 = *optr;
-
- *optr = yorig;
- for (i = 2, j = 0; i < steps; i += 2, j++) {
- c = REAL_TO_INT(yorig + (i * d1 / steps));
- *hptr = c - *optr;
- XSetForeground(wi->dpy, wi->gc,
- ZnPixel(ZnColorGradientColor(wi->win, grad_color, dir?j:steps-1-j)));
- XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc, x, y, w, h);
- *optr = c;
+ 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);
}
-
- XSetForeground(wi->dpy, wi->gc,
- ZnPixel(ZnColorGradientMidColor(wi->win, grad_color)));
- *hptr = y_d2 - *optr;
- XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc, x, y, w, h);
-#endif
- /*
- * Draw over with a 50% gray pattern to smooth the color
- * waves.
- */
-#if 1
- /*
- * First draw the from the gradient end.
- */
- XSetTSOrigin(wi->dpy, wi->gc, bbox->x, bbox->y);
- c = ycorner;
- for (i = 0, j = steps-1; i < ((steps-1) * 4); i++) {
- *optr = REAL_TO_INT(ycorner - ((i + 1) * d2 / (steps * 4)));
- *hptr = c - *optr;
- XSetFillStyle(wi->dpy, wi->gc, FillSolid);
- col = ZnColorGradientColor(wi->win, grad_color, dir?j:steps-1-j);
- XSetForeground(wi->dpy, wi->gc, ZnPixel(col));
- XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc, x, y, w, h);
- if (i % 8) {
- XSetFillStyle(wi->dpy, wi->gc, FillStippled);
- XSetStipple(wi->dpy, wi->gc, wi->alpha_stipples[s[i%8]]);
- XSetForeground(wi->dpy, wi->gc,
- ZnPixel(ZnColorGradientColor(wi->win, grad_color,
- dir?j+1:steps-j)));
- XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc, x, y, w, h);
- }
- else {
- /*printf("remplissage en %d %d %d (%d)\n",
- col->red, col->green, col->blue, dir?j:steps-1-j);*/
- j--;
- }
- c = *optr;
- }
- y_d2 = *optr;
- /*
- * Then draw from the gradient start.
- */
-#if 1
- *optr = yorig;
- for (i = 0, j = 0; i < ((steps-1) * 4); i++) {
- c = REAL_TO_INT(yorig + ((i + 1) * d1 / (steps * 4)));
- *hptr = c - *optr;
- XSetFillStyle(wi->dpy, wi->gc, FillSolid);
- col = ZnColorGradientColor(wi->win, grad_color, dir?j:steps-1-j);
- XSetForeground(wi->dpy, wi->gc, ZnPixel(col));
- XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc, x, y, w, h);
- if (i % 8) {
- XSetFillStyle(wi->dpy, wi->gc, FillStippled);
- XSetStipple(wi->dpy, wi->gc, wi->alpha_stipples[s[i%8]]);
- XSetForeground(wi->dpy, wi->gc,
- ZnPixel(ZnColorGradientColor(wi->win, grad_color,
- dir?j-1:steps-2-j)));
- XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc, x, y, w, h);
- }
- else {
- /*printf("remplissage en %d %d %d (%d)\n",
- col->red, col->green, col->blue, dir?j:steps-1-j);*/
- j++;
- }
- *optr = c;
- }
-#endif
- /*
- * Last draw the central part.
- */
- *hptr = y_d2 - *optr;
- XSetFillStyle(wi->dpy, wi->gc, FillSolid);
- XSetForeground(wi->dpy, wi->gc,
- ZnPixel(ZnColorGradientMidColor(wi->win, grad_color)));
- XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc, x, y, w, h);
-#endif
}