123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368 |
- #include "sys-defines.h"
- #include "extern.h"
- enum { ACCEPTED = 0x1, CLIPPED_FIRST = 0x2, CLIPPED_SECOND = 0x4 };
- enum { TOP = 0x1, BOTTOM = 0x2, RIGHT = 0x4, LEFT = 0x8 };
- static int clip_line (double *x0_p, double *y0_p, double *x1_p, double *y1_p, double x_min_clip, double x_max_clip, double y_min_clip, double y_max_clip, bool spec_min_x, bool spec_min_y, bool spec_max_x, bool spec_max_y);
- static int compute_relevant_points (double xx, double yy, double oldxx, double oldyy, int clip_mode, double user_min_x, double user_min_y, double user_max_x, double user_max_y, bool spec_min_x, bool spec_min_y, bool spec_max_x, bool spec_max_y, double xxr[2], double yyr[2]);
- static int compute_outcode (double x, double y, double x_min_clip, double x_max_clip, double y_min_clip, double y_max_clip, bool spec_min_x, bool spec_min_y, bool spec_max_x, bool spec_max_y);
- void
- swapd(double * a, double * b)
- {
- double tmp = *a;
- *a = *b;
- *b = tmp;
- }
- void
- array_bounds (const Point *p, int length,
- bool transpose_axes, int clip_mode,
- double *min_x, double *min_y, double *max_x, double *max_y,
- const bool spec_min_x, const bool spec_min_y,
- const bool spec_max_x, const bool spec_max_y)
- {
-
- double user_min_x = 0.0, user_min_y = 0.0;
- double user_max_x = 0.0, user_max_y = 0.0;
- double local_min_x = 0.0, local_min_y = 0.0;
- double local_max_x = 0.0, local_max_y = 0.0;
- double xx, yy, oldxx, oldyy;
- bool point_seen = false;
- int i;
- if (length == 0)
-
- {
- if (!spec_min_x)
- *min_x = 0.0;
- if (!spec_min_y)
- *min_y = 0.0;
- if (!spec_max_x)
- *max_x = *min_x;
- if (!spec_max_y)
- *max_y = *min_y;
- return;
- }
- if (spec_min_x)
- user_min_x = *min_x;
- else
- local_min_x = DBL_MAX;
- if (spec_max_x)
- user_max_x = *max_x;
- else
- local_max_x = -(DBL_MAX);
-
- if (spec_min_x && spec_max_x && user_min_x > user_max_x)
- swapd (&user_min_x, &user_max_x);
- if (spec_min_y)
- user_min_y = *min_y;
- else
- local_min_y = DBL_MAX;
- if (spec_max_y)
- user_max_y = *max_y;
- else
- local_max_y = -(DBL_MAX);
-
- if (spec_min_y && spec_max_y && user_min_y > user_max_y)
- swapd (&user_min_y, &user_max_y);
-
- oldxx = oldyy = 0.0;
- for (i = 0; i < length; i++)
- {
- double xxr[2], yyr[2];
- int n, j;
- int effective_clip_mode;
-
- xx = (transpose_axes ? p[i].y : p[i].x);
- yy = (transpose_axes ? p[i].x : p[i].y);
-
- if (i == 0 || p[i].pendown == false
- || (p[i].linemode <= 0 && p[i].fill_fraction < 0.0))
-
- effective_clip_mode = 0;
- else if (p[i].fill_fraction >= 0.0)
- effective_clip_mode = 2;
- else
- effective_clip_mode = clip_mode;
- n = compute_relevant_points (xx, yy, oldxx, oldyy,
- effective_clip_mode,
- user_min_x, user_min_y,
- user_max_x, user_max_y,
- spec_min_x, spec_min_y,
- spec_max_x, spec_max_y,
- xxr, yyr);
-
- for (j = 0; j < n; j++)
- {
- point_seen = true;
- if (!spec_min_x)
- local_min_x = DMIN(local_min_x, xxr[j]);
- if (!spec_min_y)
- local_min_y = DMIN(local_min_y, yyr[j]);
- if (!spec_max_x)
- local_max_x = DMAX(local_max_x, xxr[j]);
- if (!spec_max_y)
- local_max_y = DMAX(local_max_y, yyr[j]);
- }
- oldxx = xx;
- oldyy = yy;
- }
- if (!point_seen)
-
- local_min_x = local_min_y = local_max_x = local_max_y = 0.0;
-
- if (!spec_min_x)
- *min_x = local_min_x;
- if (!spec_min_y)
- *min_y = local_min_y;
- if (!spec_max_x)
- *max_x = local_max_x;
- if (!spec_max_y)
- *max_y = local_max_y;
- return;
- }
- static int
- compute_relevant_points (double xx, double yy,
- double oldxx, double oldyy,
- int clip_mode,
- double user_min_x, double user_min_y,
- double user_max_x, double user_max_y,
- bool spec_min_x, bool spec_min_y,
- bool spec_max_x, bool spec_max_y,
- double xxr[2], double yyr[2])
- {
- int clipval;
- switch (clip_mode)
- {
- case 0:
- if ((!spec_min_x || xx >= user_min_x)
- && (!spec_max_x || xx <= user_max_x)
- && (!spec_min_y || yy >= user_min_y)
- && (!spec_max_y || yy <= user_max_y))
- {
- xxr[0] = xx;
- yyr[0] = yy;
- return 1;
- }
- else
- return 0;
- break;
- case 1:
- default:
- clipval = clip_line (&oldxx, &oldyy, &xx, &yy, user_min_x, user_max_x, user_min_y, user_max_y, spec_min_x, spec_min_y, spec_max_x, spec_max_y);
- if ((clipval & ACCEPTED)
- && !((clipval & CLIPPED_FIRST) && (clipval & CLIPPED_SECOND)))
- {
- xxr[0] = oldxx;
- yyr[0] = oldyy;
- xxr[1] = xx;
- yyr[1] = yy;
- return 2;
- }
- else
- return 0;
- break;
- case 2:
- clipval = clip_line (&oldxx, &oldyy, &xx, &yy, user_min_x, user_max_x, user_min_y, user_max_y, spec_min_x, spec_min_y, spec_max_x, spec_max_y);
- if (clipval & ACCEPTED)
- {
- xxr[0] = oldxx;
- yyr[0] = oldyy;
- xxr[1] = xx;
- yyr[1] = yy;
- return 2;
- }
- else
- return 0;
- break;
- }
- }
- static int
- clip_line (double *x0_p, double *y0_p, double *x1_p, double *y1_p, double x_min_clip, double x_max_clip, double y_min_clip, double y_max_clip, bool spec_min_x, bool spec_min_y, bool spec_max_x, bool spec_max_y)
- {
- double x0 = *x0_p;
- double y0 = *y0_p;
- double x1 = *x1_p;
- double y1 = *y1_p;
- int outcode0, outcode1;
- bool accepted;
- int clipval = 0;
- outcode0 = compute_outcode (x0, y0, x_min_clip, x_max_clip, y_min_clip, y_max_clip, spec_min_x, spec_min_y, spec_max_x, spec_max_y);
- outcode1 = compute_outcode (x1, y1, x_min_clip, x_max_clip, y_min_clip, y_max_clip, spec_min_x, spec_min_y, spec_max_x, spec_max_y);
- for ( ; ; )
- {
- if (!(outcode0 | outcode1))
- {
- accepted = true;
- break;
- }
- else if (outcode0 & outcode1)
- {
- accepted = false;
- break;
- }
- else
- {
-
- int outcode_out = (outcode0 ? outcode0 : outcode1);
- double x, y;
- if (outcode_out & RIGHT)
- {
- x = x_max_clip;
- y = isinf (x0) ? y1 : y0 + (y1 - y0) * (x - x0) / (x1 - x0);
- }
- else if (outcode_out & LEFT)
- {
- x = x_min_clip;
- y = isinf (x0) ? y1 : y0 + (y1 - y0) * (x - x0) / (x1 - x0);
- }
- else if (outcode_out & TOP)
- {
- y = y_max_clip;
- x = isinf (y0) ? x1 : x0 + (x1 - x0) * (y - y0) / (y1 - y0);
- }
- else
- {
- y = y_min_clip;
- x = isinf (y0) ? x1 : x0 + (x1 - x0) * (y - y0) / (y1 - y0);
- }
- if (outcode_out == outcode0)
- {
- x0 = x;
- y0 = y;
- outcode0 = compute_outcode (x0, y0, x_min_clip, x_max_clip, y_min_clip, y_max_clip, spec_min_x, spec_min_y, spec_max_x, spec_max_y);
- }
- else
- {
- x1 = x;
- y1 = y;
- outcode1 = compute_outcode (x1, y1, x_min_clip, x_max_clip, y_min_clip, y_max_clip, spec_min_x, spec_min_y, spec_max_x, spec_max_y);
- }
- }
- }
- if (accepted)
- {
- clipval |= ACCEPTED;
- if ((x0 != *x0_p) || (y0 != *y0_p))
- clipval |= CLIPPED_FIRST;
- if ((x1 != *x1_p) || (y1 != *y1_p))
- clipval |= CLIPPED_SECOND;
- *x0_p = x0;
- *y0_p = y0;
- *x1_p = x1;
- *y1_p = y1;
- }
- return clipval;
- }
- static int
- compute_outcode (double x, double y, double x_min_clip, double x_max_clip, double y_min_clip, double y_max_clip, bool spec_min_x, bool spec_min_y, bool spec_max_x, bool spec_max_y)
- {
- return RIGHT * (spec_max_x && x > x_max_clip)
- + LEFT * (spec_min_x && x < x_min_clip)
- + TOP * (spec_max_y && y > y_max_clip)
- + BOTTOM * (spec_min_y && y < y_min_clip);
- }
|