+ std::vector<Bezier> ClipToRectangle(const Rect& r)
+ {
+ // Find points of intersection with the rectangle.
+ Debug("Clipping Bezier to Rect %s", r.Str().c_str());
+
+ // Convert bezier coefficients -> cubic coefficients
+ Real xd = x0 - r.x;
+ Real xc = Real(3)*(x1 - x0);
+ Real xb = Real(3)*(x2 - x1) - xc;
+ Real xa = x3 - x0 - xc - xb;
+
+ // Find its roots.
+ std::vector<Real> x_intersection = SolveCubic(xa, xb, xc, xd);
+
+ // And for the other side.
+ xd = x0 - r.x - r.w;
+
+ std::vector<Real> x_intersection_pt2 = SolveCubic(xa, xb, xc, xd);
+ x_intersection.insert(x_intersection.end(), x_intersection_pt2.begin(), x_intersection_pt2.end());
+
+ // Similarly for y-coordinates.
+ // Convert bezier coefficients -> cubic coefficients
+ Real yd = y0 - r.y;
+ Real yc = Real(3)*(y1 - y0);
+ Real yb = Real(3)*(y2 - y1) - yc;
+ Real ya = y3 - y0 - yc - yb;
+
+ // Find its roots.
+ std::vector<Real> y_intersection = SolveCubic(ya, yb, yc, yd);
+
+ // And for the other side.
+ yd = y0 - r.y - r.h;
+
+ std::vector<Real> y_intersection_pt2 = SolveCubic(ya, yb, yc, yd);
+ y_intersection.insert(y_intersection.end(), y_intersection_pt2.begin(), y_intersection_pt2.end());
+
+ // Merge and sort.
+ x_intersection.insert(x_intersection.end(), y_intersection.begin(), y_intersection.end());
+ x_intersection.push_back(Real(0));
+ x_intersection.push_back(Real(1));
+ std::sort(x_intersection.begin(), x_intersection.end());
+
+ Debug("Found %d intersections.\n", x_intersection.size());
+
+ std::vector<Bezier> all_beziers;
+ if (x_intersection.empty())
+ {
+ all_beziers.push_back(*this);
+ return all_beziers;
+ }
+ Real t0 = *(x_intersection.begin());
+ for (auto it = x_intersection.begin()+1; it != x_intersection.end(); ++it)
+ {
+ Real t1 = *it;
+ if (t1 == t0) continue;
+ Debug(" -- t0: %f to t1: %f", t0, t1);
+ Real ptx, pty;
+ Evaluate(ptx, pty, ((t1 + t0) / Real(2)));
+ if (r.PointIn(ptx, pty))
+ {
+ all_beziers.push_back(this->ReParametrise(t0, t1));
+ }
+ else
+ {
+ Debug("Segment removed (point at %f, %f)", ptx, pty);
+ }
+ t0 = t1;
+ }
+ return all_beziers;
+ }