diff options
Diffstat (limited to 'generic')
-rw-r--r-- | generic/Draw.c | 193 |
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; |