diff options
author | wlemb <wlemb> | 2003-07-10 20:37:49 +0000 |
---|---|---|
committer | wlemb <wlemb> | 2003-07-10 20:37:49 +0000 |
commit | 319f698f7fbe9f51a5ab6224634beaa639ee6e19 (patch) | |
tree | c5a9b5721f826dd2e9196f282bfd9f365630bed4 /src | |
parent | 9cdff6794ff6c344bcfad7de2e2f0017e94ee012 (diff) | |
download | groff-319f698f7fbe9f51a5ab6224634beaa639ee6e19.tar.gz |
* src/libs/libgroff/geometry.cpp (check_output_arc_limits):
Rewritten.
Diffstat (limited to 'src')
-rw-r--r-- | src/libs/libgroff/geometry.cpp | 215 |
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; } |