aboutsummaryrefslogtreecommitdiff
path: root/generic/Arc.c
diff options
context:
space:
mode:
Diffstat (limited to 'generic/Arc.c')
-rw-r--r--generic/Arc.c764
1 files changed, 109 insertions, 655 deletions
diff --git a/generic/Arc.c b/generic/Arc.c
index 4bca94d..2fab777 100644
--- a/generic/Arc.c
+++ b/generic/Arc.c
@@ -348,66 +348,6 @@ Query(ZnItem item,
/*
- * Tangent --
- * Compute a point describing the arc tangent at the first/last
- * end of the arc. The point is on the tangent segment next to
- * the arc (ie: it is suitable for drawing arrows).
- */
-static void
-Tangent(ArcItem arc,
- ZnBool first,
- ZnPoint *p)
-{
- double a2, b2, w_2, h_2;
- double angle;
- ZnPoint p1, center;
-
- if (first) {
- angle = ZnDegRad(arc->start_angle);
- }
- else {
- angle = ZnDegRad(arc->start_angle + arc->angle_extent);
- }
- p1.x = cos(angle);
- p1.y = sin(angle);
- w_2 = (arc->corner.x - arc->orig.x) / 2.0;
- h_2 = (arc->corner.y - arc->orig.y) / 2.0;
- center.x = (arc->orig.x + arc->corner.x) / 2.0;
- center.y = (arc->orig.y + arc->corner.y) / 2.0;
-
- /*
- * Slope of the initial segment.
- *
- * a1 = (center->y - p1.y) / (center->x - p1.x);
- * a2 = -1/a1;
- */
- a2 = - p1.x / p1.y;
- b2 = p1.y - a2*p1.x;
-
- if (p1.y == 0.0) {
- p->x = p1.x;
- if (!first) {
- p->y = p1.y - 10.0;
- }
- else {
- p->y = p1.y + 10.0;
- }
- }
- else {
- if ((!first && (p1.y < 0.0)) || (first && (p1.y > 0.0))) {
- p->x = p1.x - 10.0;
- }
- else {
- p->x = p1.x + 10.0;
- }
- p->y = a2*p->x + b2;
- }
- p->x = center.x + ZnNearestInt(p->x*w_2);
- p->y = center.y + ZnNearestInt(p->y*h_2);
-}
-
-
-/*
**********************************************************************************
*
* ComputeCoordinates --
@@ -439,7 +379,7 @@ UpdateRenderShape(ArcItem arc)
arc->render_shape);
/*
- * Adapt the number of arc circles to the radius of the arc.
+ * Adapt the number of arc points to the radius of the arc.
*/
p.x = o.x + p_list->x*d;
p.y = o.y + p_list->y*d;
@@ -455,6 +395,7 @@ UpdateRenderShape(ArcItem arc)
else if (d > 9.0) {
quality = ZN_CIRCLE_MEDIUM;
}
+
if (quality != ZN_CIRCLE_COARSE) {
p_list = ZnGetCirclePoints(ISCLEAR(arc->flags, PIE_SLICE_BIT) ? 1 : 2,
quality,
@@ -477,10 +418,9 @@ ComputeCoordinates(ZnItem item,
{
ZnWInfo *wi = item->wi;
ArcItem arc = (ArcItem) item;
- ZnReal angle, sin1, cos1, sin2, cos2;
- ZnReal tmp, w_2, h_2, center_x, center_y;
+ ZnReal angle, tmp;
unsigned int num_p;
- ZnPoint *p_list, p;
+ ZnPoint *p_list;
ZnPoint end_points[ZN_LINE_END_POINTS];
ZnResetBBox(&item->item_bounding_box);
@@ -497,9 +437,9 @@ ComputeCoordinates(ZnItem item,
if (!wi->render) {
ZnTransfoDecompose(wi->current_transfo, NULL, NULL, &angle, NULL);
}
- if (wi->render || (angle >= PRECISION_LIMIT)) {
+ if (wi->render || (angle >= PRECISION_LIMIT) || (ABS(arc->angle_extent) != 360) ||
+ ISSET(arc->flags, FIRST_END_OK) || ISSET(arc->flags, LAST_END_OK)) {
SET(arc->flags, USING_POLY_BIT);
-
UpdateRenderShape(arc);
p_list = ZnListArray(arc->render_shape);
num_p = ZnListSize(arc->render_shape);
@@ -559,122 +499,21 @@ ComputeCoordinates(ZnItem item,
/*
******* ******** **********
- * This part is for X drawn arcs: not rotated.
+ * This part is for X drawn arcs: full extent, not rotated.
******* ******** **********
*/
CLEAR(arc->flags, USING_POLY_BIT);
ZnTransformPoint(wi->current_transfo, &arc->coords[0], &arc->orig);
ZnTransformPoint(wi->current_transfo, &arc->coords[1], &arc->corner);
- if (arc->orig.x > arc->corner.x) {
- tmp = arc->orig.x;
- arc->orig.x = arc->corner.x;
- arc->corner.x = tmp;
- }
- if (arc->orig.y > arc->corner.y) {
- tmp = arc->orig.y;
- arc->orig.y = arc->corner.y;
- arc->corner.y = tmp;
- }
+ ZnAddPointToBBox(&item->item_bounding_box, arc->orig.x, arc->orig.y);
+ ZnAddPointToBBox(&item->item_bounding_box, arc->corner.x, arc->corner.y);
- /*
- * now compute the two points at the centers of the ends of the arc.
- * We first compute the position for a unit circle and then scale
- * to fit the shape.
- * Angles are running clockwise and y coordinates are inverted.
- */
- angle = ZnDegRad(arc->start_angle);
- sin1 = sin(angle);
- cos1 = cos(angle);
- angle += ZnDegRad(arc->angle_extent);
- sin2 = sin(angle);
- cos2 = cos(angle);
-
- w_2 = (arc->corner.x - arc->orig.x) / 2;
- h_2 = (arc->corner.y - arc->orig.y) / 2;
- center_x = (arc->corner.x + arc->orig.x) / 2;
- center_y = (arc->corner.y + arc->orig.y) / 2;
-
- arc->center1.x = center_x + ZnNearestInt(cos1*w_2);
- arc->center1.y = center_y + ZnNearestInt(sin1*h_2);
- arc->center2.x = center_x + ZnNearestInt(cos2*w_2);
- arc->center2.y = center_y + ZnNearestInt(sin2*h_2);
-
- /*
- * Add the ends centers to the bbox.
- */
- ZnAddPointToBBox(&item->item_bounding_box, arc->center1.x, arc->center1.y);
- ZnAddPointToBBox(&item->item_bounding_box, arc->center2.x, arc->center2.y);
-
- /*
- * If the arc is filled or if the outline is closed in pie slice,
- * add the center of the arc.
- */
- if ((ISSET(arc->flags, FILLED_BIT) || ISSET(arc->flags, CLOSED_BIT)) &&
- ISSET(arc->flags, PIE_SLICE_BIT)) {
- ZnAddPointToBBox(&item->item_bounding_box, center_x, center_y);
- }
-
- /*
- * Then add the 3-o'clock, 6-o'clock, 9-o'clock, 12-o'clock position
- * as required.
- */
- tmp = -arc->start_angle;
- if (tmp < 0) {
- tmp += 360;
- }
- if ((tmp < arc->angle_extent) || ((tmp - 360) > arc->angle_extent)) {
- ZnAddPointToBBox(&item->item_bounding_box, arc->corner.x, center_y);
- }
-
- tmp = 180 - arc->start_angle;
- if (tmp < 0) {
- tmp += 360;
- }
- if ((tmp < arc->angle_extent) || ((tmp - 360) > arc->angle_extent)) {
- ZnAddPointToBBox(&item->item_bounding_box, arc->orig.x, center_y);
- }
-
- tmp = 90 - arc->start_angle;
- if (tmp < 0) {
- tmp += 360;
- }
- if ((tmp < arc->angle_extent) || ((tmp - 360) > arc->angle_extent)) {
- ZnAddPointToBBox(&item->item_bounding_box, center_x, arc->corner.y);
- }
-
- tmp = 270 - arc->start_angle;
- if (tmp < 0) {
- tmp += 360;
- }
- if ((tmp < arc->angle_extent) || ((tmp - 360) > arc->angle_extent)) {
- ZnAddPointToBBox(&item->item_bounding_box, center_x, arc->orig.y);
- }
-
- /*
- * Now take care of the arc outline width plus one pixel of margin.
- */
tmp = (arc->line_width + 1.0) / 2.0 + 1.0;
item->item_bounding_box.orig.x -= tmp;
item->item_bounding_box.orig.y -= tmp;
item->item_bounding_box.corner.x += tmp;
item->item_bounding_box.corner.y += tmp;
-
- /*
- * Then add the arrows if any.
- */
- if (ISSET(arc->flags, FIRST_END_OK)) {
- Tangent(arc, True, &p);
- ZnGetLineEnd(&arc->center1, &p, arc->line_width, CapRound,
- arc->first_end, end_points);
- ZnAddPointsToBBox(&item->item_bounding_box, end_points, ZN_LINE_END_POINTS);
- }
- if (ISSET(arc->flags, LAST_END_OK)) {
- Tangent(arc, False, &p);
- ZnGetLineEnd(&arc->center2, &p, arc->line_width, CapRound,
- arc->last_end, end_points);
- ZnAddPointsToBBox(&item->item_bounding_box, end_points, ZN_LINE_END_POINTS);
- }
}
@@ -694,71 +533,73 @@ ToArea(ZnItem item,
ArcItem arc = (ArcItem) item;
ZnPoint *points;
ZnPoint pts[20]; /* Should be at least ZN_LINE_END_POINTS large */
- ZnPoint center, tang;
- ZnBBox t_area, *area = ta->area;
+ ZnPoint center;
+ ZnBBox *area = ta->area;
unsigned int num_points;
int result=-1, result2;
ZnReal lw = arc->line_width;
- ZnReal rx, ry, angle, tmp;
- ZnBool inside, new_inside;
- ZnPickStruct ps;
-
- if (ISSET(arc->flags, USING_POLY_BIT) &&
- (ISSET(arc->flags, FILLED_BIT) || (arc->line_width))) {
- points = ZnListArray(arc->render_shape);
- num_points = ZnListSize(arc->render_shape);
+ ZnReal width, height;
- if (ISSET(arc->flags, FILLED_BIT)) {
- result = ZnPolygonInBBox(points, num_points, area, NULL);
- if (result == 0) {
- return 0;
- }
- }
- if (arc->line_width > 0) {
- result2 = ZnPolylineInBBox(points, num_points, arc->line_width,
- CapRound, JoinRound, area);
- if (ISCLEAR(arc->flags, FILLED_BIT)) {
- if (result2 == 0) {
+ if (ISSET(arc->flags, USING_POLY_BIT)) {
+ if (ISSET(arc->flags, FILLED_BIT) || (arc->line_width)) {
+ points = ZnListArray(arc->render_shape);
+ num_points = ZnListSize(arc->render_shape);
+
+ if (ISSET(arc->flags, FILLED_BIT)) {
+ result = ZnPolygonInBBox(points, num_points, area, NULL);
+ if (result == 0) {
return 0;
}
- result = result2;
- }
- else if (result2 != result) {
- return 0;
}
- if (ISSET(arc->flags, CLOSED_BIT) && ISSET(arc->flags, PIE_SLICE_BIT)) {
- pts[0] = points[num_points-1];
- pts[1] = points[0];
- if (ZnPolylineInBBox(pts, 2, arc->line_width,
- CapRound, JoinRound, area) != result) {
- return 0;
+ if (arc->line_width > 0) {
+ result2 = ZnPolylineInBBox(points, num_points, arc->line_width,
+ CapRound, JoinRound, area);
+ if (ISCLEAR(arc->flags, FILLED_BIT)) {
+ if (result2 == 0) {
+ return 0;
+ }
+ result = result2;
}
- }
- /*
- * Check line ends.
- */
- if (ISSET(arc->flags, FIRST_END_OK)) {
- ZnGetLineEnd(&points[0], &points[1], arc->line_width, CapRound,
- arc->first_end, pts);
- if (ZnPolygonInBBox(pts, ZN_LINE_END_POINTS, area, NULL) != result) {
+ else if (result2 != result) {
return 0;
}
- }
- if (ISSET(arc->flags, LAST_END_OK)) {
- ZnGetLineEnd(&points[num_points-1], &points[num_points-2], arc->line_width,
- CapRound, arc->last_end, pts);
- if (ZnPolygonInBBox(pts, ZN_LINE_END_POINTS, area, NULL) != result) {
- return 0;
+ if (ISSET(arc->flags, CLOSED_BIT) && ISSET(arc->flags, PIE_SLICE_BIT)) {
+ pts[0] = points[num_points-1];
+ pts[1] = points[0];
+ if (ZnPolylineInBBox(pts, 2, arc->line_width,
+ CapRound, JoinRound, area) != result) {
+ return 0;
+ }
+ }
+ /*
+ * Check line ends.
+ */
+ if (ISSET(arc->flags, FIRST_END_OK)) {
+ ZnGetLineEnd(&points[0], &points[1], arc->line_width, CapRound,
+ arc->first_end, pts);
+ if (ZnPolygonInBBox(pts, ZN_LINE_END_POINTS, area, NULL) != result) {
+ return 0;
+ }
+ }
+ if (ISSET(arc->flags, LAST_END_OK)) {
+ ZnGetLineEnd(&points[num_points-1], &points[num_points-2], arc->line_width,
+ CapRound, arc->last_end, pts);
+ if (ZnPolygonInBBox(pts, ZN_LINE_END_POINTS, area, NULL) != result) {
+ return 0;
+ }
}
}
+ return result;
+ }
+ else {
+ return -1;
}
- return result;
}
/*
******* ******** **********
- * The rest of this code deal with non rotated arcs. *
- * It has been stolen from tkCanvArc.c *
+ * The rest of this code deal with non rotated, full extent *
+ * arcs. It has been stolen from tkRectOval.c *
******* ******** **********
*/
/*
@@ -767,199 +608,37 @@ ToArea(ZnItem item,
*/
center.x = (arc->orig.x + arc->corner.x)/2.0;
center.y = (arc->orig.y + arc->corner.y)/2.0;
- t_area.orig.x = area->orig.x - center.x;
- t_area.orig.y = area->orig.y - center.y;
- t_area.corner.x = area->corner.x - center.x;
- t_area.corner.y = area->corner.y - center.y;
- rx = arc->corner.x - center.x + lw/2.0;
- ry = arc->corner.y - center.y + lw/2.0;
-
- /*
- * Find the extreme points of the arc and see whether these are all
- * inside the rectangle (in which case we're done), partly in and
- * partly out (in which case we're done), or all outside (in which
- * case we have more work to do). The extreme points include the
- * following, which are checked in order:
- *
- * 1. The outside points of the arc, corresponding to start and
- * extent.
- * 2. The center of the arc (but only in pie-slice mode).
- * 3. The 12, 3, 6, and 9-o'clock positions (but only if the arc
- * includes those angles).
- */
- points = pts;
- angle = ZnDegRad(arc->start_angle);
- points->x = rx*cos(angle);
- points->y = ry*sin(angle);
- angle += ZnDegRad(arc->angle_extent);
- points[1].x = rx*cos(angle);
- points[1].y = ry*sin(angle);
- num_points = 2;
- points += 2;
-
- if (ISSET(arc->flags, PIE_SLICE_BIT) && (arc->angle_extent < 180.0)) {
- points->x = 0.0;
- points->y = 0.0;
- num_points++;
- points++;
- }
-
- tmp = -arc->start_angle;
- if (tmp < 0) {
- tmp += 360.0;
- }
- if ((tmp < arc->angle_extent) || ((tmp-360) > arc->angle_extent)) {
- points->x = rx;
- points->y = 0.0;
- num_points++;
- points++;
- }
- tmp = 180.0 - arc->start_angle;
- if (tmp < 0) {
- tmp += 360.0;
- }
- if ((tmp < arc->angle_extent) || ((tmp-360) > arc->angle_extent)) {
- points->x = 0.0;
- points->y = ry;
- num_points++;
- points++;
- }
- tmp = 90.0 - arc->start_angle;
- if (tmp < 0) {
- tmp += 360.0;
- }
- if ((tmp < arc->angle_extent) || ((tmp-360) > arc->angle_extent)) {
- points->x = -rx;
- points->y = 0.0;
- num_points++;
- points++;
- }
- tmp = 270.0 - arc->start_angle;
- if (tmp < 0) {
- tmp += 360.0;
- }
- if ((tmp < arc->angle_extent) || ((tmp-360) > arc->angle_extent)) {
- points->x = 0.0;
- points->y = -ry;
- num_points++;
- }
-
- /*
- * Now that we've located the extreme points, loop through them all
- * to see which are inside the rectangle.
- */
- inside = ZnPointInBBox(&t_area, pts->x, pts->y);
- for (points = pts+1; num_points > 1; points++, num_points--) {
- new_inside = ZnPointInBBox(&t_area, points->x, points->y);
- if (new_inside != inside) {
- return 0;
- }
- }
- result = inside ? 1 : -1;
-
- /*
- * So far, oval appears to be outside rectangle, but can't yet tell
- * for sure. Next, test each of the four sides of the rectangle
- * against the bounding region for the arc. If any intersections
- * are found, then return "overlapping". First, test against the
- * polygon(s) forming the sides of a chord or pie-slice.
- */
- if ((lw >= 1.0) && (ISSET(arc->flags, CLOSED_BIT))) {
- if (ISSET(arc->flags, PIE_SLICE_BIT)) {
- pts[0] = arc->center1;
- pts[1] = center;
- pts[2] = arc->center2;
- num_points = 3;
- }
- else {
- pts[0] = arc->center1;
- pts[1] = arc->center2;
- num_points = 2;
- }
- if (ZnPolylineInBBox(pts, num_points, lw, CapRound, JoinRound, area) != result) {
- return 0;
- }
- }
- else if (ISSET(arc->flags, FILLED_BIT)) {
- if (ISSET(arc->flags, PIE_SLICE_BIT)) {
- if ((ZnLineInBBox(&center, &arc->center1, area) != result) ||
- (ZnLineInBBox(&center, &arc->center2, area) != result)) {
- return 0;
- }
- }
- else {
- if (ZnLineInBBox(&arc->center1, &arc->center2, area) != result) {
- return 0;
- }
- }
- }
-
- /*
- * Check line ends.
- */
- if (ISSET(arc->flags, FIRST_END_OK)) {
- Tangent(arc, True, &tang);
- ZnGetLineEnd(&arc->center1, &tang, arc->line_width, CapRound,
- arc->first_end, pts);
- if (ZnPolygonInBBox(pts, ZN_LINE_END_POINTS, area, NULL) != result) {
- return 0;
- }
- }
- if (ISSET(arc->flags, LAST_END_OK)) {
- Tangent(arc, False, &tang);
- ZnGetLineEnd(&arc->center2, &tang, arc->line_width, CapRound,
- arc->last_end, pts);
- if (ZnPolygonInBBox(pts, ZN_LINE_END_POINTS, area, NULL) != result) {
- return 0;
- }
- }
- if (result == 1) {
- return result;
- }
-
- /*
- * Next check for overlap between each of the four sides and the
- * outer perimiter of the arc. If the arc isn't filled, then also
- * check the inner perimeter of the arc.
- */
- if (ZnHorizLineToArc(t_area.orig.x, t_area.corner.x, t_area.orig.y,
- rx, ry, arc->start_angle, arc->angle_extent) ||
- ZnHorizLineToArc(t_area.orig.x, t_area.corner.x, t_area.corner.y,
- rx, ry, arc->start_angle, arc->angle_extent) ||
- ZnVertLineToArc(t_area.orig.x, t_area.orig.y, t_area.corner.y,
- rx, ry, arc->start_angle, arc->angle_extent) ||
- ZnVertLineToArc(t_area.corner.x, t_area.orig.y, t_area.corner.y,
- rx, ry, arc->start_angle, arc->angle_extent)) {
- return 0;
- }
- if ((lw > 1.0) && ISCLEAR(arc->flags, FILLED_BIT)) {
- rx -= lw;
- ry -= lw;
- if (ZnHorizLineToArc(t_area.orig.x, t_area.corner.x, t_area.orig.y,
- rx, ry, arc->start_angle, arc->angle_extent) ||
- ZnHorizLineToArc(t_area.orig.x, t_area.corner.x, t_area.corner.y,
- rx, ry, arc->start_angle, arc->angle_extent) ||
- ZnVertLineToArc(t_area.orig.x, t_area.orig.y, t_area.corner.y,
- rx, ry, arc->start_angle, arc->angle_extent) ||
- ZnVertLineToArc(t_area.corner.x, t_area.orig.y, t_area.corner.y,
- rx, ry, arc->start_angle, arc->angle_extent)) {
- return 0;
+ width = (arc->corner.x - arc->orig.x) + lw;
+ height = (arc->corner.y - arc->orig.y) + lw;
+
+ result = ZnOvalInBBox(&center, width, height, area);
+
+ /*
+ * If the area appears to overlap the oval and the oval
+ * isn't filled, do one more check to see if perhaps all four
+ * of the area's corners are totally inside the oval's
+ * unfilled center, in which case we should return "outside".
+ */
+ if ((result == 0) && lw && ISCLEAR(arc->flags, FILLED_BIT)) {
+ ZnReal x_delta1, x_delta2, y_delta1, y_delta2;
+
+ width /= 2.0;
+ height /= 2.0;
+ x_delta1 = (area->orig.x - center.x) / width;
+ x_delta1 *= x_delta1;
+ y_delta1 = (area->orig.y - center.y) / height;
+ y_delta1 *= y_delta1;
+ x_delta2 = (area->corner.x - center.x) / width;
+ x_delta2 *= x_delta2;
+ y_delta2 = (area->corner.y - center.y) / height;
+ y_delta2 *= y_delta2;
+ if (((x_delta1 + y_delta1) < 1.0) && ((x_delta1 + y_delta2) < 1.0) &&
+ ((x_delta2 + y_delta1) < 1.0) && ((x_delta2 + y_delta2) < 1.0)) {
+ return -1;
}
}
-
- /*
- * The arc still appears to be totally disjoint from the rectangle,
- * but it's also possible that the rectangle is totally inside the arc.
- * Do one last check, which is to check one point of the rectangle
- * to see if it's inside the arc. If it is, we've got overlap. If
- * it isn't, the arc's really outside the rectangle.
- */
- ps.point = &area->orig;
- if (Pick(item, &ps) == 0.0) {
- return 0;
- }
- return -1;
+ return result;
}
@@ -980,9 +659,11 @@ Draw(ZnItem item)
ZnPoint *p=NULL;
XPoint *xp=NULL;
unsigned int num_points=0, i;
-
- if (ISSET(arc->flags, USING_POLY_BIT) &&
- (ISSET(arc->flags, FILLED_BIT) || (arc->line_width))) {
+
+ if (ISCLEAR(arc->flags, FILLED_BIT) && !arc->line_width) {
+ return;
+ }
+ if (ISSET(arc->flags, USING_POLY_BIT)) {
p = ZnListArray(arc->render_shape);
num_points = ZnListSize(arc->render_shape);
ZnListAssertSize(ZnWorkXPoints, num_points);
@@ -1026,6 +707,7 @@ Draw(ZnItem item)
values.fill_style = FillSolid;
XChangeGC(wi->dpy, wi->gc, GCForeground|GCFillStyle|GCArcMode, &values);
}
+
if (ISSET(arc->flags, USING_POLY_BIT)) {
XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc,
xp, (int) num_points, Nonconvex, CoordModeOrigin);
@@ -1046,7 +728,6 @@ Draw(ZnItem item)
if (arc->line_width) {
ZnPoint end_points[ZN_LINE_END_POINTS];
XPoint xap[ZN_LINE_END_POINTS];
- ZnPoint tang;
ZnSetLineStyle(wi, arc->line_style);
values.foreground = ZnGetGradientPixel(arc->line_color, 0.0);
@@ -1105,52 +786,6 @@ Draw(ZnItem item)
(unsigned int) width,
(unsigned int) height,
-arc->start_angle*64, -arc->angle_extent*64);
- /*
- * If the outline is closed, draw the closure.
- */
- if (ISSET(arc->flags, CLOSED_BIT)) {
- if (ISSET(arc->flags, PIE_SLICE_BIT)) {
- XPoint points[3];
-
- points[0].x = (short) arc->center1.x;
- points[0].y = (short) arc->center1.y;
- points[1].x = (short) ((arc->corner.x + arc->orig.x) / 2);
- points[1].y = (short) ((arc->corner.y + arc->orig.y) / 2);
- points[2].x = (short) arc->center2.x;
- points[2].y = (short) arc->center2.y;
- XDrawLines(wi->dpy, wi->draw_buffer, wi->gc, points, 3,
- CoordModeOrigin);
- }
- else {
- XDrawLine(wi->dpy, wi->draw_buffer, wi->gc,
- (int) arc->center1.x,
- (int) arc->center1.y,
- (int) arc->center2.x,
- (int) arc->center2.y);
- }
- }
- if (ISSET(arc->flags, FIRST_END_OK)) {
- Tangent(arc, True, &tang);
- ZnGetLineEnd(&arc->center1, &tang, arc->line_width, CapRound,
- arc->first_end, end_points);
- for (i = 0; i < ZN_LINE_END_POINTS; i++) {
- xap[i].x = (short) end_points[i].x;
- xap[i].y = (short) end_points[i].y;
- }
- XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, xap, ZN_LINE_END_POINTS,
- Nonconvex, CoordModeOrigin);
- }
- if (ISSET(arc->flags, LAST_END_OK)) {
- Tangent(arc, False, &tang);
- ZnGetLineEnd(&arc->center2, &tang, arc->line_width, CapRound,
- arc->last_end, end_points);
- for (i = 0; i < ZN_LINE_END_POINTS; i++) {
- xap[i].x = (short) end_points[i].x;
- xap[i].y = (short) end_points[i].y;
- }
- XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, xap, ZN_LINE_END_POINTS,
- Nonconvex, CoordModeOrigin);
- }
}
}
}
@@ -1295,17 +930,16 @@ Pick(ZnItem item,
{
ArcItem arc = (ArcItem) item;
double dist = 1e40, new_dist;
- ZnBool point_in_angle, filled, closed;
- ZnBool in_triangle, acute_angle;
- ZnPoint p1, center, tang;
+ ZnPoint center;
ZnPoint *points, *p = ps->point;
ZnPoint end_points[ZN_LINE_END_POINTS];
unsigned int num_points;
- ZnDim width, height;
ZnDim lw = arc->line_width;
- if (ISSET(arc->flags, USING_POLY_BIT) &&
- (ISSET(arc->flags, FILLED_BIT) || (arc->line_width))) {
+ if (ISCLEAR(arc->flags, FILLED_BIT) && ! arc->line_width) {
+ return dist;
+ }
+ if (ISSET(arc->flags, USING_POLY_BIT)) {
points = ZnListArray(arc->render_shape);
num_points = ZnListSize(arc->render_shape);
@@ -1361,205 +995,25 @@ Pick(ZnItem item,
}
/*
- ******* ******** **********
- * The rest of this code deal with non rotated or relief arcs. *
- ******* ******** **********
- */
- center.x = (arc->corner.x + arc->orig.x) / 2;
- center.y = (arc->corner.y + arc->orig.y) / 2;
- width = arc->corner.x - arc->orig.x;
- height = arc->corner.y - arc->orig.y;
-
- /*
- * Let see if the point is in the angular range. First
- * transform the coordinates so that the oval is circular.
- */
- p1.y = (p->y - center.y) / height;
- p1.x = (p->x - center.x) / width;
- point_in_angle = ZnPointInAngle(arc->start_angle, arc->angle_extent, &p1);
-
- /*
- * Now try to compute the distance dealing with the
- * many possible configurations.
- */
- filled = !ISCLEAR(arc->flags, FILLED_BIT);
- closed = !ISCLEAR(arc->flags, CLOSED_BIT);
-
- /*
- * First the case of an arc not filled, not closed. We suppose
- * here that the outline is drawn since we cannot get here without
- * filling or outlining.
- */
- if (!filled && !closed) {
- if (point_in_angle) {
- dist = ZnOvalToPointDist(&center, width, height, lw, p);
- if (dist < 0.0) {
- dist = -dist;
- }
- }
- else {
- dist = hypot((p->x - arc->center1.x), (p->y - arc->center1.y));
- }
- new_dist = hypot((p->x - arc->center2.x), (p->y - arc->center2.y));
- if (new_dist < dist) {
- dist = new_dist;
- }
- /* Take into account CapRounded path. */
- if (lw > 1) {
- dist -= lw/2;
- if (dist < 0.0) {
- dist = 0.0;
- }
- }
- if (dist == 0.0) {
- return 0.0;
- }
-
- /*
- * Check line ends.
- */
- if (ISSET(arc->flags, FIRST_END_OK)) {
- Tangent(arc, True, &tang);
- ZnGetLineEnd(&arc->center1, &tang, arc->line_width, CapRound,
- arc->first_end, end_points);
- new_dist = ZnPolygonToPointDist(end_points, ZN_LINE_END_POINTS, p);
- if (new_dist < dist) {
- dist = new_dist;
- }
- if (dist <= 0.0) {
- return 0.0;
- }
- }
- if (ISSET(arc->flags, LAST_END_OK)) {
- Tangent(arc, False, &tang);
- ZnGetLineEnd(&arc->center2, &tang, arc->line_width,
- CapRound, arc->last_end, end_points);
- new_dist = ZnPolygonToPointDist(end_points, ZN_LINE_END_POINTS, p);
- if (new_dist < dist) {
- dist = new_dist;
- }
- if (dist <= 0.0) {
- return 0.0;
- }
- }
- return dist;
- }
-
- /*
- * Try to deal with filled and/or outline-closed arcs (not having full
- * angular extent).
+ ******* ******** **********
+ * The rest of this code deal with non rotated full extent arcs. *
+ ******* ******** **********
*/
- if (ISSET(arc->flags, PIE_SLICE_BIT)) {
- dist = ZnLineToPointDist(&center, &arc->center1, p, NULL);
- new_dist = ZnLineToPointDist(&center, &arc->center2, p, NULL);
- if (new_dist < dist) {
- dist = new_dist;
- }
- if (arc->line_width > 1) {
- if (closed) {
- dist -= arc->line_width/2;
- }
- /*
- * The arc outline is CapRounded so if it is not
- * full extent, includes the caps.
- */
- else {
- new_dist = hypot(p->x - arc->center1.x, p->y - arc->center1.y) - lw/2;
- if (new_dist < dist) {
- dist = new_dist;
- }
- new_dist = hypot(p->x - arc->center2.x, p->y - arc->center2.y) - lw/2;
- if (new_dist < dist) {
- dist = new_dist;
- }
- }
- }
- if (dist <= 0.0) {
- return 0.0;
- }
- if (point_in_angle) {
- new_dist = ZnOvalToPointDist(&center, width, height, lw, p);
- if (new_dist < dist) {
- dist = new_dist;
- }
- if (dist < 0.0) {
- dist = filled ? 0.0 : -dist;
- }
- }
- return dist;
- }
-
- /*
- * This is a chord closed oval.
- */
- dist = ZnLineToPointDist(&arc->center1, &arc->center2, p, NULL);
- if (arc->line_width > 1) {
- if (closed) {
- dist -= arc->line_width/2;
+ center.x = (arc->orig.x + arc->corner.x) / 2.0;
+ center.y = (arc->orig.y + arc->corner.y) / 2.0;
+ dist = ZnOvalToPointDist(&center, arc->corner.x - arc->orig.x,
+ arc->corner.y - arc->orig.y, lw, p);
+ if (dist < 0.0) {
+ if (ISSET(arc->flags, FILLED_BIT)) {
+ dist = 0.0;
}
- /*
- * The arc outline is CapRounded so if it is not
- * full extent, includes the caps.
- */
else {
- new_dist = hypot(p->x - arc->center1.x, p->y - arc->center1.y) - lw/2;
- if (new_dist < dist) {
- dist = new_dist;
- }
- new_dist = hypot(p->x - arc->center2.x, p->y - arc->center2.y) - lw/2;
- if (new_dist < dist) {
- dist = new_dist;
- }
+ dist = -dist;
}
}
- if (dist <= 0.0) {
- return 0.0;
- }
-
- /*
- * Need to check the point against the triangle formed
- * by the difference between Chord mode and PieSlice mode.
- * This triangle needs to be included if extend is more than
- * 180 degrees and excluded otherwise. We try to see if
- * the center of the arc and the point are both on the same
- * side of the chord. If they are, the point is in the triangle
- */
- if (arc->center1.x == arc->center2.x) {
- in_triangle = ((center.x <= arc->center1.x) && (p->x <= arc->center1.x)) ||
- ((center.x > arc->center1.x) && (p->x > arc->center1.x));
- }
- else {
- double a, b;
-
- a = ((double) (arc->center2.y - arc->center1.y)) /
- ((double) (arc->center2.x - arc->center1.x));
- b = arc->center1.y - a*arc->center1.x;
- in_triangle = (((a*center.x + b - center.y) >= 0.0) ==
- ((a*p->x + b - p->y) >= 0.0));
- }
-
- acute_angle = ((arc->angle_extent > -180) && (arc->angle_extent < 180));
- if (!point_in_angle && !acute_angle && filled && in_triangle) {
- return 0.0;
- }
-
- if (point_in_angle && (!acute_angle || !in_triangle)) {
- new_dist = ZnOvalToPointDist(&center, width, height, lw, p);
- if (new_dist < dist) {
- dist = new_dist;
- }
- if (dist < 0.0) {
- dist = filled ? 0.0 : -dist;
- }
- if (dist == 0.0) {
- return 0.0;
- }
- }
-
return dist;
}
-
/*
**********************************************************************************
*