19166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com/*
29166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com * Copyright 2012 Google Inc.
39166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com *
49166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com * Use of this source code is governed by a BSD-style license that can be
59166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com * found in the LICENSE file.
69166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com */
79166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com#include "PathOpsCubicIntersectionTestData.h"
89166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com#include "PathOpsQuadIntersectionTestData.h"
98d0a524a4847bc7e1cc63a93b78922739466c201caryclark@google.com#include "PathOpsTestCommon.h"
109166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com#include "SkIntersections.h"
119166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com#include "SkPathOpsRect.h"
129166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com#include "SkReduceOrder.h"
139166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com#include "Test.h"
149166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com
1502352d14d4d2dc2e35d62f30674bf126eef26c26caryclark@google.com#if 0 // disable test until stroke reduction is supported
169166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.comstatic bool controls_inside(const SkDCubic& cubic) {
179166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com    return between(cubic[0].fX, cubic[1].fX, cubic[3].fX)
189166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com            && between(cubic[0].fX, cubic[2].fX, cubic[3].fX)
199166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com            && between(cubic[0].fY, cubic[1].fY, cubic[3].fY)
209166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com            && between(cubic[0].fY, cubic[2].fY, cubic[3].fY);
219166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com}
229166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com
239166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.comstatic bool tiny(const SkDCubic& cubic) {
249166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com    int index, minX, maxX, minY, maxY;
259166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com    minX = maxX = minY = maxY = 0;
269166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com    for (index = 1; index < 4; ++index) {
279166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com        if (cubic[minX].fX > cubic[index].fX) {
289166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com            minX = index;
299166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com        }
309166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com        if (cubic[minY].fY > cubic[index].fY) {
319166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com            minY = index;
329166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com        }
339166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com        if (cubic[maxX].fX < cubic[index].fX) {
349166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com            maxX = index;
359166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com        }
369166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com        if (cubic[maxY].fY < cubic[index].fY) {
379166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com            maxY = index;
389166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com        }
399166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com    }
409166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com    return     approximately_equal(cubic[maxX].fX, cubic[minX].fX)
419166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com            && approximately_equal(cubic[maxY].fY, cubic[minY].fY);
429166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com}
439166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com
449166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.comstatic void find_tight_bounds(const SkDCubic& cubic, SkDRect& bounds) {
459166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com    SkDCubicPair cubicPair = cubic.chopAt(0.5);
469166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com    if (!tiny(cubicPair.first()) && !controls_inside(cubicPair.first())) {
479166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com        find_tight_bounds(cubicPair.first(), bounds);
489166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com    } else {
499166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com        bounds.add(cubicPair.first()[0]);
509166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com        bounds.add(cubicPair.first()[3]);
519166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com    }
529166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com    if (!tiny(cubicPair.second()) && !controls_inside(cubicPair.second())) {
539166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com        find_tight_bounds(cubicPair.second(), bounds);
549166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com    } else {
559166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com        bounds.add(cubicPair.second()[0]);
569166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com        bounds.add(cubicPair.second()[3]);
579166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com    }
589166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com}
59111417aae90beb459bcd77397270d67ca3731e69caryclark@google.com#endif
609166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com
6178e7b4e1b928fa69f672be3c743df6d6c3ecbcedtfarina@chromium.orgDEF_TEST(PathOpsReduceOrderCubic, reporter) {
629166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com    size_t index;
639166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com    SkReduceOrder reducer;
649166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com    int order;
659166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com    enum {
669166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com        RunAll,
679166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com        RunPointDegenerates,
689166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com        RunNotPointDegenerates,
699166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com        RunLines,
709166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com        RunNotLines,
719166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com        RunModEpsilonLines,
729166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com        RunLessEpsilonLines,
739166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com        RunNegEpsilonLines,
749166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com        RunQuadraticLines,
759166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com        RunQuadraticPoints,
769166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com        RunQuadraticModLines,
779166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com        RunComputedLines,
789166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com        RunNone
799166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com    } run = RunAll;
809166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com    int firstTestIndex = 0;
819166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com#if 0
829166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com    run = RunComputedLines;
839166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com    firstTestIndex = 18;
849166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com#endif
859166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com    int firstPointDegeneratesTest = run == RunAll ? 0 : run == RunPointDegenerates
869166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com            ? firstTestIndex : SK_MaxS32;
879166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com    int firstNotPointDegeneratesTest = run == RunAll ? 0 : run == RunNotPointDegenerates
889166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com            ? firstTestIndex : SK_MaxS32;
899166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com    int firstLinesTest = run == RunAll ? 0 : run == RunLines ? firstTestIndex : SK_MaxS32;
909166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com    int firstNotLinesTest = run == RunAll ? 0 : run == RunNotLines ? firstTestIndex : SK_MaxS32;
919166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com    int firstModEpsilonTest = run == RunAll ? 0 : run == RunModEpsilonLines
929166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com            ? firstTestIndex : SK_MaxS32;
939166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com    int firstLessEpsilonTest = run == RunAll ? 0 : run == RunLessEpsilonLines
949166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com            ? firstTestIndex : SK_MaxS32;
959166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com    int firstNegEpsilonTest = run == RunAll ? 0 : run == RunNegEpsilonLines
969166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com            ? firstTestIndex : SK_MaxS32;
979166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com    int firstQuadraticPointTest = run == RunAll ? 0 : run == RunQuadraticPoints
989166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com            ? firstTestIndex : SK_MaxS32;
999166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com    int firstQuadraticLineTest = run == RunAll ? 0 : run == RunQuadraticLines
1009166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com            ? firstTestIndex : SK_MaxS32;
1019166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com    int firstQuadraticModLineTest = run == RunAll ? 0 : run == RunQuadraticModLines
1029166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com            ? firstTestIndex : SK_MaxS32;
103927b7028d44c46e9cbc18368f16ec2262d59d94dcaryclark@google.com#if 0
1049166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com    int firstComputedLinesTest = run == RunAll ? 0 : run == RunComputedLines
1059166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com            ? firstTestIndex : SK_MaxS32;
106927b7028d44c46e9cbc18368f16ec2262d59d94dcaryclark@google.com#endif
1079166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com    for (index = firstPointDegeneratesTest; index < pointDegenerates_count; ++index) {
108a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark        const CubicPts& c = pointDegenerates[index];
109a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark        SkDCubic cubic;
110a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark        cubic.debugSet(c.fPts);
1118d0a524a4847bc7e1cc63a93b78922739466c201caryclark@google.com        SkASSERT(ValidCubic(cubic));
112927b7028d44c46e9cbc18368f16ec2262d59d94dcaryclark@google.com        order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics);
1139166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com        if (order != 1) {
1149166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com            SkDebugf("[%d] pointDegenerates order=%d\n", static_cast<int>(index), order);
1159166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com            REPORTER_ASSERT(reporter, 0);
1169166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com        }
1179166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com    }
1189166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com    for (index = firstNotPointDegeneratesTest; index < notPointDegenerates_count; ++index) {
119a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark        const CubicPts& c = notPointDegenerates[index];
120a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark        SkDCubic cubic;
121a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark        cubic.debugSet(c.fPts);
1228d0a524a4847bc7e1cc63a93b78922739466c201caryclark@google.com        SkASSERT(ValidCubic(cubic));
123927b7028d44c46e9cbc18368f16ec2262d59d94dcaryclark@google.com        order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics);
1249166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com        if (order == 1) {
1259166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com            SkDebugf("[%d] notPointDegenerates order=%d\n", static_cast<int>(index), order);
126927b7028d44c46e9cbc18368f16ec2262d59d94dcaryclark@google.com            order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics);
1279166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com            REPORTER_ASSERT(reporter, 0);
1289166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com        }
1299166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com    }
1309166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com    for (index = firstLinesTest; index < lines_count; ++index) {
131a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark        const CubicPts& c = lines[index];
132a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark        SkDCubic cubic;
133a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark        cubic.debugSet(c.fPts);
1348d0a524a4847bc7e1cc63a93b78922739466c201caryclark@google.com        SkASSERT(ValidCubic(cubic));
135927b7028d44c46e9cbc18368f16ec2262d59d94dcaryclark@google.com        order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics);
1369166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com        if (order != 2) {
1379166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com            SkDebugf("[%d] lines order=%d\n", static_cast<int>(index), order);
1389166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com            REPORTER_ASSERT(reporter, 0);
1399166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com        }
1409166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com    }
1419166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com    for (index = firstNotLinesTest; index < notLines_count; ++index) {
142a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark        const CubicPts& c = notLines[index];
143a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark        SkDCubic cubic;
144a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark        cubic.debugSet(c.fPts);
1458d0a524a4847bc7e1cc63a93b78922739466c201caryclark@google.com        SkASSERT(ValidCubic(cubic));
146927b7028d44c46e9cbc18368f16ec2262d59d94dcaryclark@google.com        order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics);
1479166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com        if (order == 2) {
1489166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com            SkDebugf("[%d] notLines order=%d\n", static_cast<int>(index), order);
1499166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com            REPORTER_ASSERT(reporter, 0);
1509166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com       }
1519166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com    }
1529166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com    for (index = firstModEpsilonTest; index < modEpsilonLines_count; ++index) {
153a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark        const CubicPts& c = modEpsilonLines[index];
154a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark        SkDCubic cubic;
155a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark        cubic.debugSet(c.fPts);
1568d0a524a4847bc7e1cc63a93b78922739466c201caryclark@google.com        SkASSERT(ValidCubic(cubic));
157927b7028d44c46e9cbc18368f16ec2262d59d94dcaryclark@google.com        order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics);
1589166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com        if (order == 2) {
1599166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com            SkDebugf("[%d] line mod by epsilon order=%d\n", static_cast<int>(index), order);
1609166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com            REPORTER_ASSERT(reporter, 0);
1619166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com        }
1629166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com    }
1639166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com    for (index = firstLessEpsilonTest; index < lessEpsilonLines_count; ++index) {
164a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark        const CubicPts& c = lessEpsilonLines[index];
165a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark        SkDCubic cubic;
166a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark        cubic.debugSet(c.fPts);
1678d0a524a4847bc7e1cc63a93b78922739466c201caryclark@google.com        SkASSERT(ValidCubic(cubic));
168927b7028d44c46e9cbc18368f16ec2262d59d94dcaryclark@google.com        order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics);
1699166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com        if (order != 2) {
1709166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com            SkDebugf("[%d] line less by epsilon/2 order=%d\n", static_cast<int>(index), order);
171927b7028d44c46e9cbc18368f16ec2262d59d94dcaryclark@google.com            order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics);
1729166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com            REPORTER_ASSERT(reporter, 0);
1739166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com        }
1749166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com    }
1759166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com    for (index = firstNegEpsilonTest; index < negEpsilonLines_count; ++index) {
176a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark        const CubicPts& c = negEpsilonLines[index];
177a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark        SkDCubic cubic;
178a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark        cubic.debugSet(c.fPts);
1798d0a524a4847bc7e1cc63a93b78922739466c201caryclark@google.com        SkASSERT(ValidCubic(cubic));
180927b7028d44c46e9cbc18368f16ec2262d59d94dcaryclark@google.com        order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics);
1819166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com        if (order != 2) {
1829166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com            SkDebugf("[%d] line neg by epsilon/2 order=%d\n", static_cast<int>(index), order);
1839166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com            REPORTER_ASSERT(reporter, 0);
1849166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com        }
1859166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com    }
1869166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com    for (index = firstQuadraticPointTest; index < quadraticPoints_count; ++index) {
187a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark        const QuadPts& q = quadraticPoints[index];
188a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark        SkDQuad quad;
189a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark        quad.debugSet(q.fPts);
1908d0a524a4847bc7e1cc63a93b78922739466c201caryclark@google.com        SkASSERT(ValidQuad(quad));
191624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark        SkDCubic cubic = quad.debugToCubic();
192927b7028d44c46e9cbc18368f16ec2262d59d94dcaryclark@google.com        order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics);
1939166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com        if (order != 1) {
1949166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com            SkDebugf("[%d] point quad order=%d\n", static_cast<int>(index), order);
1959166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com            REPORTER_ASSERT(reporter, 0);
1969166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com        }
1979166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com    }
1989166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com    for (index = firstQuadraticLineTest; index < quadraticLines_count; ++index) {
199a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark        const QuadPts& q = quadraticLines[index];
200a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark        SkDQuad quad;
201a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark        quad.debugSet(q.fPts);
2028d0a524a4847bc7e1cc63a93b78922739466c201caryclark@google.com        SkASSERT(ValidQuad(quad));
203624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark        SkDCubic cubic = quad.debugToCubic();
204927b7028d44c46e9cbc18368f16ec2262d59d94dcaryclark@google.com        order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics);
2059166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com        if (order != 2) {
2069166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com            SkDebugf("[%d] line quad order=%d\n", static_cast<int>(index), order);
2079166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com            REPORTER_ASSERT(reporter, 0);
2089166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com        }
2099166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com    }
2109166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com    for (index = firstQuadraticModLineTest; index < quadraticModEpsilonLines_count; ++index) {
211a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark        const QuadPts& q = quadraticModEpsilonLines[index];
212a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark        SkDQuad quad;
213a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark        quad.debugSet(q.fPts);
2148d0a524a4847bc7e1cc63a93b78922739466c201caryclark@google.com        SkASSERT(ValidQuad(quad));
215624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark        SkDCubic cubic = quad.debugToCubic();
216927b7028d44c46e9cbc18368f16ec2262d59d94dcaryclark@google.com        order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics);
2179166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com        if (order != 3) {
2189166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com            SkDebugf("[%d] line mod quad order=%d\n", static_cast<int>(index), order);
2199166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com            REPORTER_ASSERT(reporter, 0);
2209166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com        }
2219166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com    }
2229166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com
223927b7028d44c46e9cbc18368f16ec2262d59d94dcaryclark@google.com#if 0 // disable test until stroke reduction is supported
224927b7028d44c46e9cbc18368f16ec2262d59d94dcaryclark@google.com// test if computed line end points are valid
2259166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com    for (index = firstComputedLinesTest; index < lines_count; ++index) {
2269166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com        const SkDCubic& cubic = lines[index];
2278d0a524a4847bc7e1cc63a93b78922739466c201caryclark@google.com        SkASSERT(ValidCubic(cubic));
2289166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com        bool controlsInside = controls_inside(cubic);
2299166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com        order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics,
2309166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com                SkReduceOrder::kStroke_Style);
2319166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com        if (order == 2 && reducer.fLine[0] == reducer.fLine[1]) {
2329166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com            SkDebugf("[%d] line computed ends match order=%d\n", static_cast<int>(index), order);
2339166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com            REPORTER_ASSERT(reporter, 0);
2349166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com        }
2359166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com        if (controlsInside) {
2369166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com            if (       (reducer.fLine[0].fX != cubic[0].fX && reducer.fLine[0].fX != cubic[3].fX)
2379166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com                    || (reducer.fLine[0].fY != cubic[0].fY && reducer.fLine[0].fY != cubic[3].fY)
2389166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com                    || (reducer.fLine[1].fX != cubic[0].fX && reducer.fLine[1].fX != cubic[3].fX)
2399166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com                    || (reducer.fLine[1].fY != cubic[0].fY && reducer.fLine[1].fY != cubic[3].fY)) {
2409166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com                SkDebugf("[%d] line computed ends order=%d\n", static_cast<int>(index), order);
2419166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com                REPORTER_ASSERT(reporter, 0);
2429166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com            }
2439166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com        } else {
2449166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com            // binary search for extrema, compare against actual results
2459166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com                // while a control point is outside of bounding box formed by end points, split
2469166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com            SkDRect bounds = {DBL_MAX, DBL_MAX, -DBL_MAX, -DBL_MAX};
2479166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com            find_tight_bounds(cubic, bounds);
2489166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com            if (      (!AlmostEqualUlps(reducer.fLine[0].fX, bounds.fLeft)
2499166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com                    && !AlmostEqualUlps(reducer.fLine[0].fX, bounds.fRight))
2509166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com                   || (!AlmostEqualUlps(reducer.fLine[0].fY, bounds.fTop)
2519166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com                    && !AlmostEqualUlps(reducer.fLine[0].fY, bounds.fBottom))
2529166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com                   || (!AlmostEqualUlps(reducer.fLine[1].fX, bounds.fLeft)
2539166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com                    && !AlmostEqualUlps(reducer.fLine[1].fX, bounds.fRight))
2549166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com                   || (!AlmostEqualUlps(reducer.fLine[1].fY, bounds.fTop)
2559166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com                    && !AlmostEqualUlps(reducer.fLine[1].fY, bounds.fBottom))) {
2569166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com                SkDebugf("[%d] line computed tight bounds order=%d\n", static_cast<int>(index), order);
2579166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com                REPORTER_ASSERT(reporter, 0);
2589166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com            }
2599166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com        }
2609166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com    }
261927b7028d44c46e9cbc18368f16ec2262d59d94dcaryclark@google.com#endif
2629166dcb3a0e8784bea83d76ae01aa338c049ae05caryclark@google.com}
263