17839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger/*
27839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger * Copyright 2012 Google Inc.
37839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger *
47839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger * Use of this source code is governed by a BSD-style license that can be
57839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger * found in the LICENSE file.
67839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger */
77839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#include "PathOpsCubicIntersectionTestData.h"
87839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#include "PathOpsQuadIntersectionTestData.h"
958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger#include "PathOpsTestCommon.h"
107839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#include "SkIntersections.h"
117839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#include "SkPathOpsRect.h"
127839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#include "SkReduceOrder.h"
137839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#include "Test.h"
147839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
15910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger#if 0 // disable test until stroke reduction is supported
167839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerstatic bool controls_inside(const SkDCubic& cubic) {
177839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    return between(cubic[0].fX, cubic[1].fX, cubic[3].fX)
187839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            && between(cubic[0].fX, cubic[2].fX, cubic[3].fX)
197839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            && between(cubic[0].fY, cubic[1].fY, cubic[3].fY)
207839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            && between(cubic[0].fY, cubic[2].fY, cubic[3].fY);
217839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
227839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
237839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerstatic bool tiny(const SkDCubic& cubic) {
247839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    int index, minX, maxX, minY, maxY;
257839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    minX = maxX = minY = maxY = 0;
267839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    for (index = 1; index < 4; ++index) {
277839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        if (cubic[minX].fX > cubic[index].fX) {
287839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            minX = index;
297839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        }
307839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        if (cubic[minY].fY > cubic[index].fY) {
317839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            minY = index;
327839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        }
337839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        if (cubic[maxX].fX < cubic[index].fX) {
347839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            maxX = index;
357839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        }
367839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        if (cubic[maxY].fY < cubic[index].fY) {
377839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            maxY = index;
387839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        }
397839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
407839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    return     approximately_equal(cubic[maxX].fX, cubic[minX].fX)
417839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            && approximately_equal(cubic[maxY].fY, cubic[minY].fY);
427839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
437839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
447839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerstatic void find_tight_bounds(const SkDCubic& cubic, SkDRect& bounds) {
457839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    SkDCubicPair cubicPair = cubic.chopAt(0.5);
467839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    if (!tiny(cubicPair.first()) && !controls_inside(cubicPair.first())) {
477839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        find_tight_bounds(cubicPair.first(), bounds);
487839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    } else {
497839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        bounds.add(cubicPair.first()[0]);
507839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        bounds.add(cubicPair.first()[3]);
517839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
527839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    if (!tiny(cubicPair.second()) && !controls_inside(cubicPair.second())) {
537839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        find_tight_bounds(cubicPair.second(), bounds);
547839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    } else {
557839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        bounds.add(cubicPair.second()[0]);
567839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        bounds.add(cubicPair.second()[3]);
577839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
587839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
59910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger#endif
607839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
617839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerstatic void PathOpsReduceOrderCubicTest(skiatest::Reporter* reporter) {
627839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    size_t index;
637839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    SkReduceOrder reducer;
647839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    int order;
657839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    enum {
667839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        RunAll,
677839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        RunPointDegenerates,
687839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        RunNotPointDegenerates,
697839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        RunLines,
707839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        RunNotLines,
717839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        RunModEpsilonLines,
727839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        RunLessEpsilonLines,
737839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        RunNegEpsilonLines,
747839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        RunQuadraticLines,
757839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        RunQuadraticPoints,
767839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        RunQuadraticModLines,
777839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        RunComputedLines,
787839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        RunNone
797839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    } run = RunAll;
807839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    int firstTestIndex = 0;
817839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#if 0
827839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    run = RunComputedLines;
837839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    firstTestIndex = 18;
847839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#endif
857839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    int firstPointDegeneratesTest = run == RunAll ? 0 : run == RunPointDegenerates
867839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            ? firstTestIndex : SK_MaxS32;
877839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    int firstNotPointDegeneratesTest = run == RunAll ? 0 : run == RunNotPointDegenerates
887839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            ? firstTestIndex : SK_MaxS32;
897839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    int firstLinesTest = run == RunAll ? 0 : run == RunLines ? firstTestIndex : SK_MaxS32;
907839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    int firstNotLinesTest = run == RunAll ? 0 : run == RunNotLines ? firstTestIndex : SK_MaxS32;
917839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    int firstModEpsilonTest = run == RunAll ? 0 : run == RunModEpsilonLines
927839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            ? firstTestIndex : SK_MaxS32;
937839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    int firstLessEpsilonTest = run == RunAll ? 0 : run == RunLessEpsilonLines
947839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            ? firstTestIndex : SK_MaxS32;
957839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    int firstNegEpsilonTest = run == RunAll ? 0 : run == RunNegEpsilonLines
967839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            ? firstTestIndex : SK_MaxS32;
977839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    int firstQuadraticPointTest = run == RunAll ? 0 : run == RunQuadraticPoints
987839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            ? firstTestIndex : SK_MaxS32;
997839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    int firstQuadraticLineTest = run == RunAll ? 0 : run == RunQuadraticLines
1007839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            ? firstTestIndex : SK_MaxS32;
1017839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    int firstQuadraticModLineTest = run == RunAll ? 0 : run == RunQuadraticModLines
1027839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            ? firstTestIndex : SK_MaxS32;
103910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger#if 0
1047839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    int firstComputedLinesTest = run == RunAll ? 0 : run == RunComputedLines
1057839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            ? firstTestIndex : SK_MaxS32;
106910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger#endif
1077839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    for (index = firstPointDegeneratesTest; index < pointDegenerates_count; ++index) {
1087839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        const SkDCubic& cubic = pointDegenerates[index];
10958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkASSERT(ValidCubic(cubic));
110910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics);
1117839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        if (order != 1) {
1127839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            SkDebugf("[%d] pointDegenerates order=%d\n", static_cast<int>(index), order);
1137839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            REPORTER_ASSERT(reporter, 0);
1147839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        }
1157839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
1167839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    for (index = firstNotPointDegeneratesTest; index < notPointDegenerates_count; ++index) {
1177839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        const SkDCubic& cubic = notPointDegenerates[index];
11858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkASSERT(ValidCubic(cubic));
119910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics);
1207839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        if (order == 1) {
1217839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            SkDebugf("[%d] notPointDegenerates order=%d\n", static_cast<int>(index), order);
122910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics);
1237839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            REPORTER_ASSERT(reporter, 0);
1247839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        }
1257839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
1267839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    for (index = firstLinesTest; index < lines_count; ++index) {
1277839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        const SkDCubic& cubic = lines[index];
12858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkASSERT(ValidCubic(cubic));
129910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics);
1307839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        if (order != 2) {
1317839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            SkDebugf("[%d] lines order=%d\n", static_cast<int>(index), order);
1327839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            REPORTER_ASSERT(reporter, 0);
1337839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        }
1347839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
1357839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    for (index = firstNotLinesTest; index < notLines_count; ++index) {
1367839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        const SkDCubic& cubic = notLines[index];
13758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkASSERT(ValidCubic(cubic));
138910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics);
1397839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        if (order == 2) {
1407839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            SkDebugf("[%d] notLines order=%d\n", static_cast<int>(index), order);
1417839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            REPORTER_ASSERT(reporter, 0);
1427839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger       }
1437839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
1447839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    for (index = firstModEpsilonTest; index < modEpsilonLines_count; ++index) {
1457839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        const SkDCubic& cubic = modEpsilonLines[index];
14658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkASSERT(ValidCubic(cubic));
147910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics);
1487839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        if (order == 2) {
1497839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            SkDebugf("[%d] line mod by epsilon order=%d\n", static_cast<int>(index), order);
1507839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            REPORTER_ASSERT(reporter, 0);
1517839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        }
1527839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
1537839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    for (index = firstLessEpsilonTest; index < lessEpsilonLines_count; ++index) {
1547839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        const SkDCubic& cubic = lessEpsilonLines[index];
15558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkASSERT(ValidCubic(cubic));
156910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics);
1577839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        if (order != 2) {
1587839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            SkDebugf("[%d] line less by epsilon/2 order=%d\n", static_cast<int>(index), order);
159910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics);
1607839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            REPORTER_ASSERT(reporter, 0);
1617839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        }
1627839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
1637839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    for (index = firstNegEpsilonTest; index < negEpsilonLines_count; ++index) {
1647839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        const SkDCubic& cubic = negEpsilonLines[index];
16558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkASSERT(ValidCubic(cubic));
166910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics);
1677839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        if (order != 2) {
1687839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            SkDebugf("[%d] line neg by epsilon/2 order=%d\n", static_cast<int>(index), order);
1697839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            REPORTER_ASSERT(reporter, 0);
1707839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        }
1717839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
1727839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    for (index = firstQuadraticPointTest; index < quadraticPoints_count; ++index) {
1737839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        const SkDQuad& quad = quadraticPoints[index];
17458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkASSERT(ValidQuad(quad));
1757839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        SkDCubic cubic = quad.toCubic();
176910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics);
1777839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        if (order != 1) {
1787839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            SkDebugf("[%d] point quad order=%d\n", static_cast<int>(index), order);
1797839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            REPORTER_ASSERT(reporter, 0);
1807839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        }
1817839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
1827839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    for (index = firstQuadraticLineTest; index < quadraticLines_count; ++index) {
1837839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        const SkDQuad& quad = quadraticLines[index];
18458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkASSERT(ValidQuad(quad));
1857839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        SkDCubic cubic = quad.toCubic();
186910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics);
1877839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        if (order != 2) {
1887839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            SkDebugf("[%d] line quad order=%d\n", static_cast<int>(index), order);
1897839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            REPORTER_ASSERT(reporter, 0);
1907839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        }
1917839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
1927839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    for (index = firstQuadraticModLineTest; index < quadraticModEpsilonLines_count; ++index) {
1937839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        const SkDQuad& quad = quadraticModEpsilonLines[index];
19458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkASSERT(ValidQuad(quad));
1957839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        SkDCubic cubic = quad.toCubic();
196910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics);
1977839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        if (order != 3) {
1987839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            SkDebugf("[%d] line mod quad order=%d\n", static_cast<int>(index), order);
1997839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            REPORTER_ASSERT(reporter, 0);
2007839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        }
2017839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
2027839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
203910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger#if 0 // disable test until stroke reduction is supported
204910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger// test if computed line end points are valid
2057839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    for (index = firstComputedLinesTest; index < lines_count; ++index) {
2067839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        const SkDCubic& cubic = lines[index];
20758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkASSERT(ValidCubic(cubic));
2087839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        bool controlsInside = controls_inside(cubic);
2097839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics,
2107839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                SkReduceOrder::kStroke_Style);
2117839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        if (order == 2 && reducer.fLine[0] == reducer.fLine[1]) {
2127839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            SkDebugf("[%d] line computed ends match order=%d\n", static_cast<int>(index), order);
2137839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            REPORTER_ASSERT(reporter, 0);
2147839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        }
2157839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        if (controlsInside) {
2167839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            if (       (reducer.fLine[0].fX != cubic[0].fX && reducer.fLine[0].fX != cubic[3].fX)
2177839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                    || (reducer.fLine[0].fY != cubic[0].fY && reducer.fLine[0].fY != cubic[3].fY)
2187839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                    || (reducer.fLine[1].fX != cubic[0].fX && reducer.fLine[1].fX != cubic[3].fX)
2197839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                    || (reducer.fLine[1].fY != cubic[0].fY && reducer.fLine[1].fY != cubic[3].fY)) {
2207839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                SkDebugf("[%d] line computed ends order=%d\n", static_cast<int>(index), order);
2217839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                REPORTER_ASSERT(reporter, 0);
2227839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            }
2237839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        } else {
2247839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            // binary search for extrema, compare against actual results
2257839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                // while a control point is outside of bounding box formed by end points, split
2267839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            SkDRect bounds = {DBL_MAX, DBL_MAX, -DBL_MAX, -DBL_MAX};
2277839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            find_tight_bounds(cubic, bounds);
2287839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            if (      (!AlmostEqualUlps(reducer.fLine[0].fX, bounds.fLeft)
2297839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                    && !AlmostEqualUlps(reducer.fLine[0].fX, bounds.fRight))
2307839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                   || (!AlmostEqualUlps(reducer.fLine[0].fY, bounds.fTop)
2317839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                    && !AlmostEqualUlps(reducer.fLine[0].fY, bounds.fBottom))
2327839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                   || (!AlmostEqualUlps(reducer.fLine[1].fX, bounds.fLeft)
2337839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                    && !AlmostEqualUlps(reducer.fLine[1].fX, bounds.fRight))
2347839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                   || (!AlmostEqualUlps(reducer.fLine[1].fY, bounds.fTop)
2357839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                    && !AlmostEqualUlps(reducer.fLine[1].fY, bounds.fBottom))) {
2367839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                SkDebugf("[%d] line computed tight bounds order=%d\n", static_cast<int>(index), order);
2377839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                REPORTER_ASSERT(reporter, 0);
2387839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            }
2397839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        }
2407839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
241910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger#endif
2427839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
2437839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
2447839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#include "TestClassDef.h"
2450a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger
2467839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek SollenbergerDEFINE_TESTCLASS_SHORT(PathOpsReduceOrderCubicTest)
247