aboutsummaryrefslogtreecommitdiff
path: root/generic
diff options
context:
space:
mode:
Diffstat (limited to 'generic')
-rw-r--r--generic/Draw.c193
1 files changed, 145 insertions, 48 deletions
diff --git a/generic/Draw.c b/generic/Draw.c
index 7587082..6ddad6a 100644
--- a/generic/Draw.c
+++ b/generic/Draw.c
@@ -1023,7 +1023,7 @@ ZnRenderPolyline(WidgetInfo *wi,
{
int num_clips = ZnListSize(wi->clip_stack);
ZnPoint end_points[LINE_END_POINTS];
- ZnBool need_rcaps, thin, closed;
+ ZnBool need_rcaps, thin, closed, transparent;
int pass, num_passes, i, k, m;
ZnPoint c1, c2;
XColor *color;
@@ -1045,7 +1045,11 @@ ZnRenderPolyline(WidgetInfo *wi,
glColor4us(color->red, color->green, color->blue, alpha);
ZnSetLineStyle(wi, line_style);
glLineWidth(line_width);
- if (thin && (alpha != 65535)) {
+ /*
+ * Do not use joints under this transparency value.
+ */
+ transparent = alpha < (65535 * 0.8);
+ if (thin && transparent) {
/*
* This makes a special case for transparent lines.
* In this case we need to avoid drawing twice a
@@ -1064,16 +1068,16 @@ ZnRenderPolyline(WidgetInfo *wi,
glDisable(GL_LINE_SMOOTH);
}
else {
- glPointSize(line_width);
+ glPointSize(line_width>1?line_width-1:line_width);
}
num_passes = 1;
- if (alpha != 65535) {
+ if (transparent) {
num_passes = 2;
}
for (pass = 0; pass < num_passes; pass++) {
- if (alpha != 65535) {
+ if (transparent) {
if (pass == 0) {
GLX_START_CLIP(num_clips, True);
}
@@ -1363,42 +1367,134 @@ ZnComputeAxialGradient(WidgetInfo *wi,
void
ZnComputeRadialGradient(WidgetInfo *wi,
ZnPoly *shape,
- ZnBBox *bbox,
- ZnPoint *center,
+ ZnBool oval,
+ ZnPoint *focal_pp, /* in percent of bbox */
ZnPoint *grad_geo)
{
- ZnReal dist, new, x, y, fact;
+ ZnReal dist, new, x, y, ff;
+ ZnBBox bbox;
ZnContour *c;
+ ZnPoint offset, focal_point, radius;
ZnPoint *points;
- ZnTransfo *transfo1;
+ ZnTransfo t1;
int i, j;
- ZnTransformPoint(wi->current_transfo, center, &grad_geo[0]);
- transfo1 = ZnTransfoNew();
- ZnTranslate(transfo1, -grad_geo[0].x, -grad_geo[0].y);
- fact = (bbox->corner.x-bbox->orig.x)/(bbox->corner.y-bbox->orig.y);
- ZnScale(transfo1, 1.0, fact);
- dist = 0.0;
+ /*
+ * Compute the shape bbox (which should be in the item space).
+ */
+ ResetBBox(&bbox);
c = shape->contours;
+ dist = 0.0;
for (j = 0; j < shape->num_contours; j++, c++) {
if (c->cw) {
continue;
}
- ZnListAssertSize(wi->work_pts, c->num_points);
- points = ZnListArray(wi->work_pts);
- ZnTransformPoints(transfo1, c->points, points, c->num_points);
- for (i = 0; i < c->num_points; i++, points++) {
- x = points->x;
- y = points->y;
- new = x*x+y*y;
- if (new > dist) {
- dist = new;
+ AddPointsToBBox(&bbox, c->points, c->num_points);
+ }
+
+ /*
+ * Find the gradient focal point in the item space.
+ */
+ offset.x = focal_pp->x * (bbox.corner.x-bbox.orig.x)/100.0;
+ offset.y = focal_pp->y * (bbox.corner.y-bbox.orig.y)/100.0;
+ focal_point.x = (bbox.corner.x+bbox.orig.x)/2 + offset.x;
+ focal_point.y = (bbox.corner.y+bbox.orig.y)/2 + offset.y;
+
+ /*
+ * Find the max distance from the focal point.
+ */
+ if (oval) {
+ /*
+ * radius.x and radius.y are the shape radiuses.
+ * ff is the distance from the bbox center to
+ * the focal point.
+ */
+ radius.x = (bbox.corner.x-bbox.orig.x)/2;
+ radius.y = (bbox.corner.y-bbox.orig.y)/2;
+ ff = sqrt(offset.x*offset.x + offset.y*offset.y);
+ /*
+ * Compute the farthest point from the focal point
+ * on a unit circle, then map it to the oval and
+ * compute the distance between both points.
+ */
+ x = offset.x/ff;
+ y = offset.y/ff;
+ x *= radius.x;
+ y *= radius.y;
+ x = x + offset.x;
+ y = y + offset.y;
+ dist = x*x + y*y;
+ }
+ else {
+ /*
+ * Use the given shape
+ */
+ c = shape->contours;
+ for (j = 0; j < shape->num_contours; j++, c++) {
+ if (c->cw) {
+ continue;
+ }
+ for (i = 0, points = c->points; i < c->num_points; i++, points++) {
+ x = points->x - focal_point.x;
+ y = points->y - focal_point.y;
+ new = x*x+y*y;
+ if (new > dist) {
+ dist = new;
+ }
}
}
}
- grad_geo[1].x = sqrt(dist) + 2; /* Max radius plus a fuzz factor */
- grad_geo[1].y = grad_geo[1].x / fact;
- ZnTransfoFree(transfo1);
+
+ /*
+ * Create a transform to map a unit circle to another one that fill
+ * the item when located at the focal point.
+ */
+ dist = sqrt(dist); /* Max radius plus a fuzz factor */
+ ZnTransfoSetIdentity(&t1);
+ ZnScale(&t1, dist, dist);
+
+ /*
+ * Then, center the oval on the focal point.
+ */
+ ZnTranslate(&t1, focal_point.x, focal_point.y);
+ /*
+ * Last, compose with the current transform.
+ */
+ ZnTransfoCompose((ZnTransfo *) grad_geo, &t1, wi->current_transfo);
+}
+
+void
+ZnComputePathGradient(WidgetInfo *wi,
+ ZnPoly *shape,
+ ZnPoint *focal_pp, /* in percent of the bbox */
+ ZnPoint *grad_geo)
+{
+ ZnBBox bbox;
+ ZnContour *c;
+ ZnPoint focal_point;
+ int j;
+
+ /*
+ * Compute the shape bbox (which should be in the item space).
+ */
+ ResetBBox(&bbox);
+ c = shape->contours;
+ for (j = 0; j < shape->num_contours; j++, c++) {
+ if (c->cw) {
+ continue;
+ }
+ AddPointsToBBox(&bbox, c->points, c->num_points);
+ }
+
+ /*
+ * Find the gradient center in the item space.
+ */
+ focal_point.x = (bbox.corner.x+bbox.orig.x)/2 + focal_pp->x * (bbox.corner.x-bbox.orig.x)/100.0;
+ focal_point.y = (bbox.corner.y+bbox.orig.y)/2 + focal_pp->y * (bbox.corner.y-bbox.orig.y)/100.0;
+ /*
+ * Then convert it to device space.
+ */
+ ZnTransformPoint(wi->current_transfo, &focal_point, &grad_geo[0]);
}
void
@@ -1518,39 +1614,41 @@ ZnRenderGradient(WidgetInfo *wi,
glEnd();
}
else if (type == ZN_RADIAL_GRADIENT) {
- ZnReal x, radiusx, radius2x, radius3x;
- ZnReal y, radiusy, radius2y, radius3y;
+ ZnReal x, position, position2, position3;
+ ZnReal y;
int num_p, alpha2;
- ZnPoint *genarc;
+ ZnPoint *genarc, *tarc, p, focalp;
XColor *color2;
genarc = GetCirclePoints(3, ZN_CIRCLE_FINE, 0, 2*M_PI, &num_p, NULL);
- radiusx = 0;
- radiusy = 0;
+ ZnListAssertSize(wi->work_pts, num_p);
+ tarc = ZnListArray(wi->work_pts);
+ ZnTransformPoints((ZnTransfo *) quad, genarc, tarc, num_p);
+ p.x = p.y = 0;
+ ZnTransformPoint((ZnTransfo *) quad, &p, &focalp);
+
+ position = 0.0;
color = gradient->colors[0].rgb;
alpha = ZnComposeAlpha(gradient->colors[0].alpha, wi->alpha);
control = gradient->colors[0].control;
for (j = 1; j < gradient->num_colors; j++) {
- radius2x = quad[1].x*gradient->colors[j].position/100.0;
- radius2y = quad[1].y*gradient->colors[j].position/100.0;
+ position2 = gradient->colors[j].position/100.0;
if ((control != 50) && (j != gradient->num_colors-1)) {
glBegin(GL_QUAD_STRIP);
color2 = gradient->colors[j-1].mid_rgb;
alpha2 = ZnComposeAlpha(gradient->colors[j-1].mid_alpha, wi->alpha);
- radius3x = radiusx + (radius2x-radiusx)*control/100.0;
- radius3y = radiusy + (radius2y-radiusy)*control/100.0;
+ position3 = position + (position2-position)*control/100.0;
for (i = 0; i < num_p; i++) {
- x = quad[0].x+genarc[i].x*radiusx;
- y = quad[0].y+genarc[i].y*radiusy;
+ x = focalp.x + (tarc[i].x-focalp.x) * position;
+ y = focalp.y + (tarc[i].y-focalp.y) * position;
glColor4us(color->red, color->green, color->blue, alpha);
glVertex2f(x, y);
- x = quad[0].x+genarc[i].x*radius3x;
- y = quad[0].y+genarc[i].y*radius3y;
+ x = focalp.x + (tarc[i].x-focalp.x) * position3;
+ y = focalp.y + (tarc[i].y-focalp.y) * position3;
glColor4us(color2->red, color2->green, color2->blue, alpha);
glVertex2f(x, y);
}
- radiusx = radius3x;
- radiusy = radius3y;
+ position = position3;
color = color2;
alpha = alpha2;
glEnd();
@@ -1559,18 +1657,17 @@ ZnRenderGradient(WidgetInfo *wi,
color2 = gradient->colors[j].rgb;
alpha2 = ZnComposeAlpha(gradient->colors[j].alpha, wi->alpha);
for (i = 0; i < num_p; i++) {
- x = quad[0].x+genarc[i].x*radiusx;
- y = quad[0].y+genarc[i].y*radiusy;
+ x = focalp.x + (tarc[i].x-focalp.x) * position;
+ y = focalp.y + (tarc[i].y-focalp.y) * position;
glColor4us(color->red, color->green, color->blue, alpha);
glVertex2f(x, y);
- x = quad[0].x+genarc[i].x*radius2x;
- y = quad[0].y+genarc[i].y*radius2y;
+ x = focalp.x + (tarc[i].x-focalp.x) * position2;
+ y = focalp.y + (tarc[i].y-focalp.y) * position2;
glColor4us(color2->red, color2->green, color2->blue, alpha2);
glVertex2f(x, y);
}
glEnd();
- radiusx = radius2x;
- radiusy = radius2y;
+ position = position2;
color = color2;
alpha = alpha2;
control = gradient->colors[j].control;