123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372 |
- #include "sys-defines.h"
- #include "extern.h"
- #define VLENGTH(v) sqrt( (v).x * (v).x + (v).y * (v).y )
- void
- _set_ellipse_bbox (plOutbuf *bufp, double x, double y, double rx, double ry, double costheta, double sintheta, double linewidth, double m[6])
- {
- double ux, uy, vx, vy;
- double mixing_angle;
- double semi_axis_1_x, semi_axis_1_y, semi_axis_2_x, semi_axis_2_y;
- double rx_device, ry_device;
- double theta_device, costheta_device, sintheta_device;
- double xdeviation, ydeviation;
-
- rx += 0.5 * linewidth;
- ry += 0.5 * linewidth;
-
- ux = XDV_INTERNAL(rx * costheta, rx * sintheta, m);
- uy = YDV_INTERNAL(rx * costheta, rx * sintheta, m);
- vx = XDV_INTERNAL(-ry * sintheta, ry * costheta, m);
- vy = YDV_INTERNAL(-ry * sintheta, ry * costheta, m);
-
- mixing_angle = 0.5 * _xatan2 (2.0 * (ux * vx + uy * vy),
- ux * ux + uy * uy - vx * vx + vy * vy);
-
-
- semi_axis_1_x = ux * cos(mixing_angle) + vx * sin(mixing_angle);
- semi_axis_1_y = uy * cos(mixing_angle) + vy * sin(mixing_angle);
- semi_axis_2_x = ux * cos(mixing_angle + M_PI_2)
- + vx * sin(mixing_angle + M_PI_2);
- semi_axis_2_y = uy * cos(mixing_angle + M_PI_2)
- + vy * sin(mixing_angle + M_PI_2);
-
- rx_device = sqrt (semi_axis_1_x * semi_axis_1_x
- + semi_axis_1_y * semi_axis_1_y);
- ry_device = sqrt (semi_axis_2_x * semi_axis_2_x
- + semi_axis_2_y * semi_axis_2_y);
-
- theta_device = - _xatan2 (semi_axis_1_y, semi_axis_1_x);
- costheta_device = cos (theta_device);
- sintheta_device = sin (theta_device);
-
- xdeviation = sqrt (rx_device * rx_device * costheta_device * costheta_device
- + ry_device * ry_device * sintheta_device * sintheta_device);
- ydeviation = sqrt (rx_device * rx_device * sintheta_device * sintheta_device
- + ry_device * ry_device * costheta_device * costheta_device);
-
- _update_bbox (bufp,
- XD_INTERNAL(x,y,m) + xdeviation,
- YD_INTERNAL(x,y,m) + ydeviation);
- _update_bbox (bufp,
- XD_INTERNAL(x,y,m) + xdeviation,
- YD_INTERNAL(x,y,m) - ydeviation);
- _update_bbox (bufp,
- XD_INTERNAL(x,y,m) - xdeviation,
- YD_INTERNAL(x,y,m) + ydeviation);
- _update_bbox (bufp,
- XD_INTERNAL(x,y,m) - xdeviation,
- YD_INTERNAL(x,y,m) - ydeviation);
- }
- void
- _set_line_end_bbox (plOutbuf *bufp, double x, double y, double xother, double yother, double linewidth, int capstyle, double m[6])
- {
- plVector v, vrot;
- double xs, ys;
- double halfwidth = 0.5 * linewidth;
- switch (capstyle)
- {
- case PL_CAP_BUTT:
- default:
- vrot.x = yother - y;
- vrot.y = x - xother;
- _vscale (&vrot, halfwidth);
- xs = x + vrot.x;
- ys = y + vrot.y;
- _update_bbox (bufp, XD_INTERNAL(xs,ys,m), YD_INTERNAL(xs,ys,m));
- xs = x - vrot.x;
- ys = y - vrot.y;
- _update_bbox (bufp, XD_INTERNAL(xs,ys,m), YD_INTERNAL(xs,ys,m));
- break;
- case PL_CAP_PROJECT:
- v.x = xother - x;
- v.y = yother - y;
- _vscale (&v, halfwidth);
- vrot.x = yother - y;
- vrot.y = x - xother;
- _vscale (&vrot, halfwidth);
- xs = x - v.x + vrot.x;
- ys = y - v.y + vrot.y;
- _update_bbox (bufp, XD_INTERNAL(xs,ys,m), YD_INTERNAL(xs,ys,m));
- xs = x - v.x - vrot.x;
- ys = y - v.y - vrot.y;
- _update_bbox (bufp, XD_INTERNAL(xs,ys,m), YD_INTERNAL(xs,ys,m));
- break;
- case PL_CAP_ROUND:
- _set_ellipse_bbox (bufp, x, y, halfwidth, halfwidth, 1.0, 0.0, 0.0, m);
- break;
- case PL_CAP_TRIANGULAR:
-
- v.x = xother - x;
- v.y = yother - y;
- _vscale (&v, halfwidth);
- xs = x + v.x;
- ys = y + v.y;
- _update_bbox (bufp, XD_INTERNAL(xs,ys,m), YD_INTERNAL(xs,ys,m));
-
- vrot.x = yother - y;
- vrot.y = x - xother;
- _vscale (&vrot, halfwidth);
- xs = x + vrot.x;
- ys = y + vrot.y;
- _update_bbox (bufp, XD_INTERNAL(xs,ys,m), YD_INTERNAL(xs,ys,m));
- xs = x - vrot.x;
- ys = y - vrot.y;
- _update_bbox (bufp, XD_INTERNAL(xs,ys,m), YD_INTERNAL(xs,ys,m));
- break;
- }
- }
- void
- _set_line_join_bbox (plOutbuf *bufp, double xleft, double yleft, double x, double y, double xright, double yright, double linewidth, int joinstyle, double miterlimit, double m[6])
- {
- plVector v1, v2, vsum;
- double v1len, v2len;
- double halfwidth;
- double mitrelen;
- switch (joinstyle)
- {
- case PL_JOIN_MITER:
- default:
- v1.x = xleft - x;
- v1.y = yleft - y;
- v2.x = xright - x;
- v2.y = yright - y;
- v1len = VLENGTH(v1);
- v2len = VLENGTH(v2);
- if (v1len == 0.0 || v2len == 0.0)
- _update_bbox (bufp, XD_INTERNAL(x,y,m), YD_INTERNAL(x,y,m));
- else
- {
- double cosphi;
-
-
- cosphi = ((v1.x * v2.x + v1.y * v2.y) / v1len) / v2len;
- if (miterlimit <= 1.0
- || (cosphi > (1.0 - 2.0 / (miterlimit * miterlimit))))
-
- {
- _set_line_end_bbox (bufp, x, y, xleft, yleft, linewidth, PL_CAP_BUTT, m);
- _set_line_end_bbox (bufp,x, y, xright, yright, linewidth, PL_CAP_BUTT, m);
- }
- else
- {
- mitrelen = sqrt (1.0 / (2.0 - 2.0 * cosphi)) * linewidth;
- vsum.x = v1.x + v2.x;
- vsum.y = v1.y + v2.y;
- _vscale (&vsum, mitrelen);
- x -= vsum.x;
- y -= vsum.y;
- _update_bbox (bufp, XD_INTERNAL(x,y,m), YD_INTERNAL(x,y,m));
- }
- }
- break;
- case PL_JOIN_TRIANGULAR:
-
- v1.x = xleft - x;
- v1.y = yleft - y;
- v2.x = xright - x;
- v2.y = yright - y;
- vsum.x = v1.x + v2.x;
- vsum.y = v1.y + v2.y;
- _vscale (&vsum, 0.5 * linewidth);
- x -= vsum.x;
- y -= vsum.y;
- _update_bbox (bufp, XD_INTERNAL(x,y,m), YD_INTERNAL(x,y,m));
- x += vsum.x;
- y += vsum.y;
-
- case PL_JOIN_BEVEL:
- _set_line_end_bbox (bufp, x, y, xleft, yleft, linewidth, PL_CAP_BUTT, m);
- _set_line_end_bbox (bufp, x, y, xright, yright, linewidth, PL_CAP_BUTT, m);
- break;
- case PL_JOIN_ROUND:
- halfwidth = 0.5 * linewidth;
- _set_ellipse_bbox (bufp, x, y, halfwidth, halfwidth, 1.0, 0.0, 0.0, m);
- break;
- }
- }
- #define QUAD_COOR(t,x0,x1,x2) (((x0)-2*(x1)+(x2))*t*t + 2*((x1)-(x2))*t + (x2))
- void
- _set_bezier2_bbox (plOutbuf *bufp, double x0, double y0, double x1, double y1, double x2, double y2, double device_line_width, double m[6])
- {
- double a_x, b_x, t_x;
- double a_y, b_y, t_y;
- double x, y, xdevice, ydevice;
- double device_halfwidth = 0.5 * device_line_width;
-
-
- a_x = x0 - 2 * x1 + x2;
- b_x = (x1 - x2);
- a_y = y0 - 2 * y1 + y2;
- b_y = (y1 - y2);
- if (a_x != 0.0)
- {
- t_x = -b_x / a_x;
- if (t_x > 0.0 && t_x < 1.0)
- {
- x = QUAD_COOR(t_x, x0, x1, x2);
- y = QUAD_COOR(t_x, y0, y1, y2);
- xdevice = XD_INTERNAL(x,y,m);
- ydevice = YD_INTERNAL(x,y,m);
- _update_bbox (bufp, xdevice + device_halfwidth, ydevice);
- _update_bbox (bufp, xdevice - device_halfwidth, ydevice);
- }
- }
- if (a_y != 0.0)
- {
- t_y = -b_y / a_y;
- if (t_y > 0.0 && t_y < 1.0)
- {
- x = QUAD_COOR(t_y, x0, x1, x2);
- y = QUAD_COOR(t_y, y0, y1, y2);
- xdevice = XD_INTERNAL(x,y,m);
- ydevice = YD_INTERNAL(x,y,m);
- _update_bbox (bufp, xdevice, ydevice + device_halfwidth);
- _update_bbox (bufp, xdevice, ydevice - device_halfwidth);
- }
- }
- }
- #define CUBIC_COOR(t,x0,x1,x2,x3) (((x0)-3*(x1)+3*(x2)-(x3))*t*t*t + 3*((x1)-2*(x2)+(x3))*t*t + 3*((x2)-(x3))*t + (x3))
- void
- _set_bezier3_bbox (plOutbuf *bufp, double x0, double y0, double x1, double y1, double x2, double y2, double x3, double y3, double device_line_width, double m[6])
- {
- double a_x, b_x, c_x, s_x, t_x;
- double a_y, b_y, c_y, s_y, t_y;
- double x, y, xdevice, ydevice;
- double device_halfwidth = 0.5 * device_line_width;
- double sqrt_disc;
-
-
- a_x = x0 - 3 * x1 + 3 * x2 - x3;
- b_x = 2 * (x1 - 2 * x2 + x3);
- c_x = x2 - x3;
- a_y = y0 - 3 * y1 + 3 * y2 - y3;
- b_y = 2 * (y1 - 2 * y2 + y3);
- c_y = y2 - y3;
- if (a_x != 0.0)
- {
- sqrt_disc = sqrt (b_x * b_x - 4 * a_x * c_x);
- s_x = (- b_x + sqrt_disc) / (2 * a_x);
- t_x = (- b_x - sqrt_disc) / (2 * a_x);
- if (s_x > 0.0 && s_x < 1.0)
- {
- x = CUBIC_COOR(s_x, x0, x1, x2, x3);
- y = CUBIC_COOR(s_x, y0, y1, y2, y3);
- xdevice = XD_INTERNAL(x,y,m);
- ydevice = YD_INTERNAL(x,y,m);
- _update_bbox (bufp, xdevice + device_halfwidth, ydevice);
- _update_bbox (bufp, xdevice - device_halfwidth, ydevice);
- }
- if (t_x > 0.0 && t_x < 1.0)
- {
- x = CUBIC_COOR(t_x, x0, x1, x2, x3);
- y = CUBIC_COOR(t_x, y0, y1, y2, y3);
- xdevice = XD_INTERNAL(x,y,m);
- ydevice = YD_INTERNAL(x,y,m);
- _update_bbox (bufp, xdevice + device_halfwidth, ydevice);
- _update_bbox (bufp, xdevice - device_halfwidth, ydevice);
- }
- }
- if (a_y != 0.0)
- {
- sqrt_disc = sqrt (b_y * b_y - 4 * a_y * c_y);
- s_y = (- b_y + sqrt_disc) / (2 * a_y);
- t_y = (- b_y - sqrt_disc) / (2 * a_y);
- if (s_y > 0.0 && s_y < 1.0)
- {
- x = CUBIC_COOR(s_y, x0, x1, x2, x3);
- y = CUBIC_COOR(s_y, y0, y1, y2, y3);
- xdevice = XD_INTERNAL(x,y,m);
- ydevice = YD_INTERNAL(x,y,m);
- _update_bbox (bufp, xdevice, ydevice + device_halfwidth);
- _update_bbox (bufp, xdevice, ydevice - device_halfwidth);
- }
- if (t_y > 0.0 && t_y < 1.0)
- {
- x = CUBIC_COOR(t_y, x0, x1, x2, x3);
- y = CUBIC_COOR(t_y, y0, y1, y2, y3);
- xdevice = XD_INTERNAL(x,y,m);
- ydevice = YD_INTERNAL(x,y,m);
- _update_bbox (bufp, xdevice, ydevice + device_halfwidth);
- _update_bbox (bufp, xdevice, ydevice - device_halfwidth);
- }
- }
- }
|