107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com/*
207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com * Copyright 2012 Google Inc.
307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *
407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com * Use of this source code is governed by a BSD-style license that can be
507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com * found in the LICENSE file.
607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com */
707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#include "SkIntersections.h"
807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#include "SkPathOpsCubic.h"
907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#include "SkPathOpsLine.h"
1007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
1107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com/*
1207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comFind the interection of a line and cubic by solving for valid t values.
1307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
1407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comAnalogous to line-quadratic intersection, solve line-cubic intersection by
1507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comrepresenting the cubic as:
1607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com  x = a(1-t)^3 + 2b(1-t)^2t + c(1-t)t^2 + dt^3
1707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com  y = e(1-t)^3 + 2f(1-t)^2t + g(1-t)t^2 + ht^3
1807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comand the line as:
1907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com  y = i*x + j  (if the line is more horizontal)
2007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comor:
2107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com  x = i*y + j  (if the line is more vertical)
2207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
2307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comThen using Mathematica, solve for the values of t where the cubic intersects the
2407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comline:
2507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
2607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com  (in) Resultant[
2707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        a*(1 - t)^3 + 3*b*(1 - t)^2*t + 3*c*(1 - t)*t^2 + d*t^3 - x,
2807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        e*(1 - t)^3 + 3*f*(1 - t)^2*t + 3*g*(1 - t)*t^2 + h*t^3 - i*x - j, x]
2907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com  (out) -e     +   j     +
3007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com       3 e t   - 3 f t   -
3107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com       3 e t^2 + 6 f t^2 - 3 g t^2 +
3207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com         e t^3 - 3 f t^3 + 3 g t^3 - h t^3 +
3307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com     i ( a     -
3407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com       3 a t + 3 b t +
3507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com       3 a t^2 - 6 b t^2 + 3 c t^2 -
3607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com         a t^3 + 3 b t^3 - 3 c t^3 + d t^3 )
3707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
3807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comif i goes to infinity, we can rewrite the line in terms of x. Mathematica:
3907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
4007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com  (in) Resultant[
4107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        a*(1 - t)^3 + 3*b*(1 - t)^2*t + 3*c*(1 - t)*t^2 + d*t^3 - i*y - j,
4207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        e*(1 - t)^3 + 3*f*(1 - t)^2*t + 3*g*(1 - t)*t^2 + h*t^3 - y,       y]
4307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com  (out)  a     -   j     -
4407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com       3 a t   + 3 b t   +
4507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com       3 a t^2 - 6 b t^2 + 3 c t^2 -
4607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com         a t^3 + 3 b t^3 - 3 c t^3 + d t^3 -
4707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com     i ( e     -
4807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com       3 e t   + 3 f t   +
4907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com       3 e t^2 - 6 f t^2 + 3 g t^2 -
5007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com         e t^3 + 3 f t^3 - 3 g t^3 + h t^3 )
5107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
5207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comSolving this with Mathematica produces an expression with hundreds of terms;
5307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.cominstead, use Numeric Solutions recipe to solve the cubic.
5407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
5507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comThe near-horizontal case, in terms of:  Ax^3 + Bx^2 + Cx + D == 0
5607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    A =   (-(-e + 3*f - 3*g + h) + i*(-a + 3*b - 3*c + d)     )
5707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    B = 3*(-( e - 2*f +   g    ) + i*( a - 2*b +   c    )     )
5807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    C = 3*(-(-e +   f          ) + i*(-a +   b          )     )
5907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    D =   (-( e                ) + i*( a                ) + j )
6007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
6107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comThe near-vertical case, in terms of:  Ax^3 + Bx^2 + Cx + D == 0
6207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    A =   ( (-a + 3*b - 3*c + d) - i*(-e + 3*f - 3*g + h)     )
6307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    B = 3*( ( a - 2*b +   c    ) - i*( e - 2*f +   g    )     )
6407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    C = 3*( (-a +   b          ) - i*(-e +   f          )     )
6507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    D =   ( ( a                ) - i*( e                ) - j )
6607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
6707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comFor horizontal lines:
6807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com(in) Resultant[
6907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com      a*(1 - t)^3 + 3*b*(1 - t)^2*t + 3*c*(1 - t)*t^2 + d*t^3 - j,
7007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com      e*(1 - t)^3 + 3*f*(1 - t)^2*t + 3*g*(1 - t)*t^2 + h*t^3 - y, y]
7107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com(out)  e     -   j     -
7207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com     3 e t   + 3 f t   +
7307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com     3 e t^2 - 6 f t^2 + 3 g t^2 -
7407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com       e t^3 + 3 f t^3 - 3 g t^3 + h t^3
7507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com */
7607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
7707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comclass LineCubicIntersections {
7807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.compublic:
794fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com    enum PinTPoint {
804fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        kPointUninitialized,
814fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        kPointInitialized
824fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com    };
834fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com
844fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com    LineCubicIntersections(const SkDCubic& c, const SkDLine& l, SkIntersections* i)
854fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        : fCubic(c)
864fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        , fLine(l)
874fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        , fIntersections(i)
884fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        , fAllowNear(true) {
897eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com        i->setMax(3);
904fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com    }
9107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
924fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com    void allowNear(bool allow) {
934fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        fAllowNear = allow;
9407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
9507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
964fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com    // see parallel routine in line quadratic intersections
974fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com    int intersectRay(double roots[3]) {
984fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        double adj = fLine[1].fX - fLine[0].fX;
994fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        double opp = fLine[1].fY - fLine[0].fY;
1002db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org        SkDCubic c;
1014fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        for (int n = 0; n < 4; ++n) {
1022db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org            c[n].fX = (fCubic[n].fY - fLine[0].fY) * adj - (fCubic[n].fX - fLine[0].fX) * opp;
10307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
1044fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        double A, B, C, D;
1052db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org        SkDCubic::Coefficients(&c[0].fX, &A, &B, &C, &D);
1062db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org        int count = SkDCubic::RootsValidT(A, B, C, D, roots);
1072db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org        for (int index = 0; index < count; ++index) {
1082db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org            SkDPoint calcPt = c.ptAtT(roots[index]);
1092db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org            if (!approximately_zero(calcPt.fX)) {
1102db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org                for (int n = 0; n < 4; ++n) {
1112db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org                    c[n].fY = (fCubic[n].fY - fLine[0].fY) * opp
1122db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org                            + (fCubic[n].fX - fLine[0].fX) * adj;
1132db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org                }
1142db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org                double extremeTs[6];
1152db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org                int extrema = SkDCubic::FindExtrema(c[0].fX, c[1].fX, c[2].fX, c[3].fX, extremeTs);
1162db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org                count = c.searchRoots(extremeTs, extrema, 0, SkDCubic::kXAxis, roots);
1172db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org                break;
1182db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org            }
1192db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org        }
1202db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org        return count;
12107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
12207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
1234fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com    int intersect() {
1244fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        addExactEndPoints();
125570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        if (fAllowNear) {
126570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com            addNearEndPoints();
127570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        }
1284fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        double rootVals[3];
1294fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        int roots = intersectRay(rootVals);
1304fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        for (int index = 0; index < roots; ++index) {
1314fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com            double cubicT = rootVals[index];
1324fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com            double lineT = findLineT(cubicT);
1334fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com            SkDPoint pt;
1344fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com            if (pinTs(&cubicT, &lineT, &pt, kPointUninitialized)) {
1354fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com    #if ONE_OFF_DEBUG
1364fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com                SkDPoint cPt = fCubic.ptAtT(cubicT);
1374fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com                SkDebugf("%s pt=(%1.9g,%1.9g) cPt=(%1.9g,%1.9g)\n", __FUNCTION__, pt.fX, pt.fY,
1384fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com                        cPt.fX, cPt.fY);
1394fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com    #endif
1407eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com                for (int inner = 0; inner < fIntersections->used(); ++inner) {
1417eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com                    if (fIntersections->pt(inner) != pt) {
1427eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com                        continue;
1437eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com                    }
1447eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com                    double existingCubicT = (*fIntersections)[0][inner];
1457eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com                    if (cubicT == existingCubicT) {
1467eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com                        goto skipInsert;
1477eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com                    }
1487eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com                    // check if midway on cubic is also same point. If so, discard this
1497eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com                    double cubicMidT = (existingCubicT + cubicT) / 2;
1507eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com                    SkDPoint cubicMidPt = fCubic.ptAtT(cubicMidT);
1517eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com                    if (cubicMidPt.approximatelyEqual(pt)) {
1527eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com                        goto skipInsert;
1537eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com                    }
1547eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com                }
1554fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com                fIntersections->insert(cubicT, lineT, pt);
1567eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com        skipInsert:
1577eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com                ;
1584fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com            }
15907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
1604fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        return fIntersections->used();
16107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
16207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
1632db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org    static int HorizontalIntersect(const SkDCubic& c, double axisIntercept, double roots[3]) {
1644fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        double A, B, C, D;
1652db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org        SkDCubic::Coefficients(&c[0].fY, &A, &B, &C, &D);
1664fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        D -= axisIntercept;
1672db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org        int count = SkDCubic::RootsValidT(A, B, C, D, roots);
1682db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org        for (int index = 0; index < count; ++index) {
1692db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org            SkDPoint calcPt = c.ptAtT(roots[index]);
1702db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org            if (!approximately_equal(calcPt.fY, axisIntercept)) {
1712db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org                double extremeTs[6];
1722db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org                int extrema = SkDCubic::FindExtrema(c[0].fY, c[1].fY, c[2].fY, c[3].fY, extremeTs);
1732db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org                count = c.searchRoots(extremeTs, extrema, axisIntercept, SkDCubic::kYAxis, roots);
1742db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org                break;
1752db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org            }
1762db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org        }
1772db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org        return count;
1784fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com    }
17907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
1804fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com    int horizontalIntersect(double axisIntercept, double left, double right, bool flipped) {
1814fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        addExactHorizontalEndPoints(left, right, axisIntercept);
182570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        if (fAllowNear) {
183570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com            addNearHorizontalEndPoints(left, right, axisIntercept);
184570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        }
1852db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org        double roots[3];
1862db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org        int count = HorizontalIntersect(fCubic, axisIntercept, roots);
1872db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org        for (int index = 0; index < count; ++index) {
1882db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org            double cubicT = roots[index];
1892db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org            SkDPoint pt;
1902db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org            pt.fX = fCubic.ptAtT(cubicT).fX;
1912db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org            pt.fY = axisIntercept;
1924fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com            double lineT = (pt.fX - left) / (right - left);
1934fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com            if (pinTs(&cubicT, &lineT, &pt, kPointInitialized)) {
1944fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com                fIntersections->insert(cubicT, lineT, pt);
1954fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com            }
1964fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        }
1974fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        if (flipped) {
1984fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com            fIntersections->flip();
1994fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        }
2004fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        return fIntersections->used();
20107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
2024fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com
2032db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org    static int VerticalIntersect(const SkDCubic& c, double axisIntercept, double roots[3]) {
2044fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        double A, B, C, D;
2052db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org        SkDCubic::Coefficients(&c[0].fX, &A, &B, &C, &D);
2064fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        D -= axisIntercept;
2072db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org        int count = SkDCubic::RootsValidT(A, B, C, D, roots);
2082db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org        for (int index = 0; index < count; ++index) {
2092db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org            SkDPoint calcPt = c.ptAtT(roots[index]);
2102db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org            if (!approximately_equal(calcPt.fX, axisIntercept)) {
2112db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org                double extremeTs[6];
2122db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org                int extrema = SkDCubic::FindExtrema(c[0].fX, c[1].fX, c[2].fX, c[3].fX, extremeTs);
2132db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org                count = c.searchRoots(extremeTs, extrema, axisIntercept, SkDCubic::kXAxis, roots);
2142db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org                break;
2152db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org            }
2162db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org        }
2172db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org        return count;
218fa2aeee27af27f2934ee52a9732148f66481fb03caryclark@google.com    }
2194fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com
2204fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com    int verticalIntersect(double axisIntercept, double top, double bottom, bool flipped) {
2214fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        addExactVerticalEndPoints(top, bottom, axisIntercept);
222570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        if (fAllowNear) {
223570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com            addNearVerticalEndPoints(top, bottom, axisIntercept);
224570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        }
2252db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org        double roots[3];
2262db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org        int count = VerticalIntersect(fCubic, axisIntercept, roots);
2272db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org        for (int index = 0; index < count; ++index) {
2282db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org            double cubicT = roots[index];
2292db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org            SkDPoint pt;
2302db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org            pt.fX = axisIntercept;
2312db7fe7d3b7ee875e1099a22f0af17520696f5d7commit-bot@chromium.org            pt.fY = fCubic.ptAtT(cubicT).fY;
2324fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com            double lineT = (pt.fY - top) / (bottom - top);
2334fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com            if (pinTs(&cubicT, &lineT, &pt, kPointInitialized)) {
2344fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com                fIntersections->insert(cubicT, lineT, pt);
2354fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com            }
2364fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        }
2374fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        if (flipped) {
2384fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com            fIntersections->flip();
2394fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        }
2404fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        return fIntersections->used();
24107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
24207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
2434fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com    protected:
24407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
2454fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com    void addExactEndPoints() {
2464fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        for (int cIndex = 0; cIndex < 4; cIndex += 3) {
2474fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com            double lineT = fLine.exactPoint(fCubic[cIndex]);
2484fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com            if (lineT < 0) {
2494fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com                continue;
2504fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com            }
2514fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com            double cubicT = (double) (cIndex >> 1);
2524fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com            fIntersections->insert(cubicT, lineT, fCubic[cIndex]);
25307e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com        }
254fa2aeee27af27f2934ee52a9732148f66481fb03caryclark@google.com    }
255fa2aeee27af27f2934ee52a9732148f66481fb03caryclark@google.com
256a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com    /* Note that this does not look for endpoints of the line that are near the cubic.
257a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com       These points are found later when check ends looks for missing points */
2584fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com    void addNearEndPoints() {
2594fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        for (int cIndex = 0; cIndex < 4; cIndex += 3) {
2604fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com            double cubicT = (double) (cIndex >> 1);
2614fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com            if (fIntersections->hasT(cubicT)) {
2624fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com                continue;
2634fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com            }
264dac1d17027dcaa5596885a9f333979418b35001ccaryclark            double lineT = fLine.nearPoint(fCubic[cIndex], NULL);
2654fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com            if (lineT < 0) {
2664fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com                continue;
2674fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com            }
2684fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com            fIntersections->insert(cubicT, lineT, fCubic[cIndex]);
26907e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com        }
27007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
27107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
2724fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com    void addExactHorizontalEndPoints(double left, double right, double y) {
2734fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        for (int cIndex = 0; cIndex < 4; cIndex += 3) {
2744fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com            double lineT = SkDLine::ExactPointH(fCubic[cIndex], left, right, y);
2754fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com            if (lineT < 0) {
2764fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com                continue;
2774fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com            }
2784fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com            double cubicT = (double) (cIndex >> 1);
2794fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com            fIntersections->insert(cubicT, lineT, fCubic[cIndex]);
28007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
281fa2aeee27af27f2934ee52a9732148f66481fb03caryclark@google.com    }
282fa2aeee27af27f2934ee52a9732148f66481fb03caryclark@google.com
2834fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com    void addNearHorizontalEndPoints(double left, double right, double y) {
2844fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        for (int cIndex = 0; cIndex < 4; cIndex += 3) {
2854fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com            double cubicT = (double) (cIndex >> 1);
2864fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com            if (fIntersections->hasT(cubicT)) {
2874fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com                continue;
2884fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com            }
2894fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com            double lineT = SkDLine::NearPointH(fCubic[cIndex], left, right, y);
2904fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com            if (lineT < 0) {
2914fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com                continue;
2924fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com            }
2934fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com            fIntersections->insert(cubicT, lineT, fCubic[cIndex]);
29407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
2954fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        // FIXME: see if line end is nearly on cubic
29607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
29707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
2984fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com    void addExactVerticalEndPoints(double top, double bottom, double x) {
2994fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        for (int cIndex = 0; cIndex < 4; cIndex += 3) {
3004fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com            double lineT = SkDLine::ExactPointV(fCubic[cIndex], top, bottom, x);
3014fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com            if (lineT < 0) {
3024fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com                continue;
3034fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com            }
3044fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com            double cubicT = (double) (cIndex >> 1);
3054fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com            fIntersections->insert(cubicT, lineT, fCubic[cIndex]);
30607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
307fa2aeee27af27f2934ee52a9732148f66481fb03caryclark@google.com    }
308fa2aeee27af27f2934ee52a9732148f66481fb03caryclark@google.com
3094fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com    void addNearVerticalEndPoints(double top, double bottom, double x) {
3104fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        for (int cIndex = 0; cIndex < 4; cIndex += 3) {
3114fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com            double cubicT = (double) (cIndex >> 1);
3124fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com            if (fIntersections->hasT(cubicT)) {
3134fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com                continue;
3144fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com            }
3154fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com            double lineT = SkDLine::NearPointV(fCubic[cIndex], top, bottom, x);
3164fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com            if (lineT < 0) {
3174fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com                continue;
3184fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com            }
3194fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com            fIntersections->insert(cubicT, lineT, fCubic[cIndex]);
32007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
3214fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        // FIXME: see if line end is nearly on cubic
32207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
32307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
3244fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com    double findLineT(double t) {
3254fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        SkDPoint xy = fCubic.ptAtT(t);
3264fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        double dx = fLine[1].fX - fLine[0].fX;
3274fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        double dy = fLine[1].fY - fLine[0].fY;
3284fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        if (fabs(dx) > fabs(dy)) {
3294fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com            return (xy.fX - fLine[0].fX) / dx;
3304fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        }
3314fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        return (xy.fY - fLine[0].fY) / dy;
33207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
33307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
3344fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com    bool pinTs(double* cubicT, double* lineT, SkDPoint* pt, PinTPoint ptSet) {
3354fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        if (!approximately_one_or_less(*lineT)) {
3364fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com            return false;
3374fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        }
3384fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        if (!approximately_zero_or_more(*lineT)) {
3394fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com            return false;
3404fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        }
3414fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        double cT = *cubicT = SkPinT(*cubicT);
3424fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        double lT = *lineT = SkPinT(*lineT);
34391fc81c972c5ac4090f106d3b3fd9b26a3235ce1commit-bot@chromium.org        SkDPoint lPt = fLine.ptAtT(lT);
34491fc81c972c5ac4090f106d3b3fd9b26a3235ce1commit-bot@chromium.org        SkDPoint cPt = fCubic.ptAtT(cT);
34591fc81c972c5ac4090f106d3b3fd9b26a3235ce1commit-bot@chromium.org        if (!lPt.moreRoughlyEqual(cPt)) {
34691fc81c972c5ac4090f106d3b3fd9b26a3235ce1commit-bot@chromium.org            return false;
34791fc81c972c5ac4090f106d3b3fd9b26a3235ce1commit-bot@chromium.org        }
34824f6e29fc133f1082c73e2a96f30bee92e3123aaskia.committer@gmail.com        // FIXME: if points are roughly equal but not approximately equal, need to do
34991fc81c972c5ac4090f106d3b3fd9b26a3235ce1commit-bot@chromium.org        // a binary search like quad/quad intersection to find more precise t values
3504fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        if (lT == 0 || lT == 1 || (ptSet == kPointUninitialized && cT != 0 && cT != 1)) {
35191fc81c972c5ac4090f106d3b3fd9b26a3235ce1commit-bot@chromium.org            *pt = lPt;
3524fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        } else if (ptSet == kPointUninitialized) {
35391fc81c972c5ac4090f106d3b3fd9b26a3235ce1commit-bot@chromium.org            *pt = cPt;
3544fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        }
355570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        SkPoint gridPt = pt->asSkPoint();
356570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        if (gridPt == fLine[0].asSkPoint()) {
357570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com            *lineT = 0;
358570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        } else if (gridPt == fLine[1].asSkPoint()) {
359570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com            *lineT = 1;
360570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        }
361570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        if (gridPt == fCubic[0].asSkPoint() && approximately_equal(*cubicT, 0)) {
362570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com            *cubicT = 0;
363570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        } else if (gridPt == fCubic[3].asSkPoint() && approximately_equal(*cubicT, 1)) {
364570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com            *cubicT = 1;
365570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        }
3664fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        return true;
36707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
36807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
36907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comprivate:
3704fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com    const SkDCubic& fCubic;
3714fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com    const SkDLine& fLine;
3724fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com    SkIntersections* fIntersections;
3734fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com    bool fAllowNear;
37407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com};
37507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
37607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comint SkIntersections::horizontal(const SkDCubic& cubic, double left, double right, double y,
37707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        bool flipped) {
3784fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com    SkDLine line = {{{ left, y }, { right, y }}};
3794fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com    LineCubicIntersections c(cubic, line, this);
38007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    return c.horizontalIntersect(y, left, right, flipped);
38107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
38207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
38307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comint SkIntersections::vertical(const SkDCubic& cubic, double top, double bottom, double x,
38407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        bool flipped) {
3854fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com    SkDLine line = {{{ x, top }, { x, bottom }}};
3864fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com    LineCubicIntersections c(cubic, line, this);
38707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    return c.verticalIntersect(x, top, bottom, flipped);
38807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
38907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
39007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comint SkIntersections::intersect(const SkDCubic& cubic, const SkDLine& line) {
3914fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com    LineCubicIntersections c(cubic, line, this);
392fa2aeee27af27f2934ee52a9732148f66481fb03caryclark@google.com    c.allowNear(fAllowNear);
39307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    return c.intersect();
39407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
39507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
39607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comint SkIntersections::intersectRay(const SkDCubic& cubic, const SkDLine& line) {
3974fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com    LineCubicIntersections c(cubic, line, this);
398a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com    fUsed = c.intersectRay(fT[0]);
399a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com    for (int index = 0; index < fUsed; ++index) {
4004fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        fPt[index] = cubic.ptAtT(fT[0][index]);
401a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com    }
402a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com    return fUsed;
40307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
404