summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorwlemb <wlemb>2003-07-10 20:37:49 +0000
committerwlemb <wlemb>2003-07-10 20:37:49 +0000
commit319f698f7fbe9f51a5ab6224634beaa639ee6e19 (patch)
treec5a9b5721f826dd2e9196f282bfd9f365630bed4 /src
parent9cdff6794ff6c344bcfad7de2e2f0017e94ee012 (diff)
downloadgroff-319f698f7fbe9f51a5ab6224634beaa639ee6e19.tar.gz
* src/libs/libgroff/geometry.cpp (check_output_arc_limits):
Rewritten.
Diffstat (limited to 'src')
-rw-r--r--src/libs/libgroff/geometry.cpp215
1 files changed, 54 insertions, 161 deletions
diff --git a/src/libs/libgroff/geometry.cpp b/src/libs/libgroff/geometry.cpp
index 256d266a..2bb89e41 100644
--- a/src/libs/libgroff/geometry.cpp
+++ b/src/libs/libgroff/geometry.cpp
@@ -113,10 +113,6 @@ int printer::adjust_arc_center(const int *p, double *c)
* Works out in which quadrant the arc starts and
* stops, and from this it determines the x, y
* max/min limits. The arc is drawn clockwise.
- *
- * [I'm sure there is a better way to do this, but
- * I don't know how. Please can someone let me
- * know or "improve" this function.]
*/
void check_output_arc_limits(int x1, int y1,
@@ -126,161 +122,58 @@ void check_output_arc_limits(int x1, int y1,
int *minx, int *maxx,
int *miny, int *maxy)
{
- int radius = (int)sqrt(c0*c0 + c1*c1);
- int x2 = x1 + xv1 + xv2; // end of arc is (x2, y2)
- int y2 = y1 + yv1 + yv2;
-
- // firstly lets use the `circle' limitation
- *minx = x1 + xv1 - radius;
- *maxx = x1 + xv1 + radius;
- *miny = y1 + yv1 - radius;
- *maxy = y1 + yv1 + radius;
-
- /* now to see which min/max can be reduced and increased for the limits of
- * the arc
- *
- * Q2 | Q1
- * -----+-----
- * Q3 | Q4
- *
- *
- * NB. (x1+xv1, y1+yv1) is at the origin
- *
- * below we ask a nested question
- * (i) from which quadrant does the first vector start?
- * (ii) into which quadrant does the second vector go?
- * from the 16 possible answers we determine the limits of the arc
- */
- if (xv1 > 0 && yv1 > 0) {
- // first vector in Q3
- if (xv2 >= 0 && yv2 >= 0 ) {
- // second in Q1
- *maxx = x2;
- *miny = y1;
- }
- else if (xv2 < 0 && yv2 >= 0) {
- // second in Q2
- *maxx = x2;
- *miny = y1;
- }
- else if (xv2 >= 0 && yv2 < 0) {
- // second in Q4
- *miny = MIN(y1, y2);
- }
- else if (xv2 < 0 && yv2 < 0) {
- // second in Q3
- if (x1 >= x2) {
- *minx = x2;
- *maxx = x1;
- *miny = MIN(y1, y2);
- *maxy = MAX(y1, y2);
- }
- else {
- // xv2, yv2 could all be zero?
- }
- }
- }
- else if (xv1 > 0 && yv1 < 0) {
- // first vector in Q2
- if (xv2 >= 0 && yv2 >= 0) {
- // second in Q1
- *maxx = MAX(x1, x2);
- *minx = MIN(x1, x2);
- *miny = y1;
- }
- else if (xv2 < 0 && yv2 >= 0) {
- // second in Q2
- if (x1 < x2) {
- *maxx = x2;
- *minx = x1;
- *miny = MIN(y1, y2);
- *maxy = MAX(y1, y2);
- }
- else {
- // otherwise almost full circle anyway
- }
- }
- else if (xv2 >= 0 && yv2 < 0) {
- // second in Q4
- *miny = y2;
- *minx = x1;
- }
- else if (xv2 < 0 && yv2 < 0) {
- // second in Q3
- *minx = MIN(x1, x2);
- }
- }
- else if (xv1 <= 0 && yv1 <= 0) {
- // first vector in Q1
- if (xv2 >= 0 && yv2 >= 0) {
- // second in Q1
- if (x1 < x2) {
- *minx = x1;
- *maxx = x2;
- *miny = MIN(y1, y2);
- *maxy = MAX(y1, y2);
- }
- else {
- // nearly full circle
- }
- }
- else if (xv2 < 0 && yv2 >= 0) {
- // second in Q2
- *maxy = MAX(y1, y2);
- }
- else if (xv2 >= 0 && yv2 < 0) {
- // second in Q4
- *miny = MIN(y1, y2);
- *maxy = MAX(y1, y2);
- *minx = MIN(x1, x2);
- }
- else if (xv2 < 0 && yv2 < 0) {
- // second in Q3
- *minx = x2;
- *maxy = y1;
- }
- }
- else if (xv1 <= 0 && yv1 > 0) {
- // first vector in Q4
- if (xv2 >= 0 && yv2 >= 0) {
- // second in Q1
- *maxx = MAX(x1, x2);
- }
- else if (xv2 < 0 && yv2 >= 0) {
- // second in Q2
- *maxy = MAX(y1, y2);
- *maxx = MAX(x1, x2);
- }
- else if (xv2 >= 0 && yv2 < 0) {
- // second in Q4
- if (x1 >= x2) {
- *miny = MIN(y1, y2);
- *maxy = MAX(y1, y2);
- *minx = MIN(x1, x2);
- *maxx = MAX(x2, x2);
- }
- else {
- // nearly full circle
- }
- }
- else if (xv2 < 0 && yv2 < 0) {
- // second in Q3
- *maxy = MAX(y1, y2);
- *minx = MIN(x1, x2);
- *maxx = MAX(x1, x2);
- }
- }
-
- // this should *never* happen but if it does it means a case above is wrong
- // this code is only present for safety sake
- if (*maxx < *minx) {
- fprintf(stderr, "assert failed *minx > *maxx\n");
- fflush(stderr);
- *maxx = *minx;
- }
- if (*maxy < *miny) {
- fprintf(stderr, "assert failed *miny > *maxy\n");
- fflush(stderr);
- *maxy = *miny;
- }
+ int radius = (int)sqrt(c0 * c0 + c1 * c1);
+ // clockwise direction
+ int xcenter = x1 + xv1;
+ int ycenter = y1 + yv1;
+ int xend = xcenter + xv2;
+ int yend = ycenter + yv2;
+ // for convenience, transform to counterclockwise direction,
+ // centered at the origin
+ int xs = xend - xcenter;
+ int ys = yend - ycenter;
+ int xe = x1 - xcenter;
+ int ye = y1 - ycenter;
+ *minx = *maxx = xs;
+ *miny = *maxy = ys;
+ if (xe > *maxx)
+ *maxx = xe;
+ else if (xe < *minx)
+ *minx = xe;
+ if (ye > *maxy)
+ *maxy = ye;
+ else if (ye < *miny)
+ *miny = ye;
+ int qs, qe; // quadrants 0..3
+ if (xs >= 0)
+ qs = (ys >= 0) ? 0 : 3;
+ else
+ qs = (ys >= 0) ? 1 : 2;
+ if (xe >= 0)
+ qe = (ye >= 0) ? 0 : 3;
+ else
+ qe = (ye >= 0) ? 1 : 2;
+ // make qs always smaller than qe
+ if ((qs > qe)
+ || ((qs == qe) && (double(xs) * ye < double(xe) * ys)))
+ qe += 4;
+ for (int i = qs; i < qe; i++)
+ switch (i % 4) {
+ case 0:
+ *maxy = radius;
+ break;
+ case 1:
+ *minx = -radius;
+ break;
+ case 2:
+ *miny = -radius;
+ break;
+ case 3:
+ *maxx = radius;
+ break;
+ }
+ *minx += xcenter;
+ *maxx += xcenter;
+ *miny += ycenter;
+ *maxy += ycenter;
}