PathOpsCubicReduceOrderTest.cpp revision 0a657bbc2c6fc9daf699942e023050536d5ec95f
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
157839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerstatic bool controls_inside(const SkDCubic& cubic) {
167839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    return between(cubic[0].fX, cubic[1].fX, cubic[3].fX)
177839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            && between(cubic[0].fX, cubic[2].fX, cubic[3].fX)
187839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            && between(cubic[0].fY, cubic[1].fY, cubic[3].fY)
197839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            && between(cubic[0].fY, cubic[2].fY, cubic[3].fY);
207839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
217839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
227839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerstatic bool tiny(const SkDCubic& cubic) {
237839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    int index, minX, maxX, minY, maxY;
247839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    minX = maxX = minY = maxY = 0;
257839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    for (index = 1; index < 4; ++index) {
267839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        if (cubic[minX].fX > cubic[index].fX) {
277839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            minX = index;
287839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        }
297839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        if (cubic[minY].fY > cubic[index].fY) {
307839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            minY = index;
317839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        }
327839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        if (cubic[maxX].fX < cubic[index].fX) {
337839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            maxX = index;
347839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        }
357839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        if (cubic[maxY].fY < cubic[index].fY) {
367839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            maxY = index;
377839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        }
387839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
397839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    return     approximately_equal(cubic[maxX].fX, cubic[minX].fX)
407839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            && approximately_equal(cubic[maxY].fY, cubic[minY].fY);
417839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
427839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
437839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerstatic void find_tight_bounds(const SkDCubic& cubic, SkDRect& bounds) {
447839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    SkDCubicPair cubicPair = cubic.chopAt(0.5);
457839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    if (!tiny(cubicPair.first()) && !controls_inside(cubicPair.first())) {
467839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        find_tight_bounds(cubicPair.first(), bounds);
477839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    } else {
487839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        bounds.add(cubicPair.first()[0]);
497839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        bounds.add(cubicPair.first()[3]);
507839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
517839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    if (!tiny(cubicPair.second()) && !controls_inside(cubicPair.second())) {
527839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        find_tight_bounds(cubicPair.second(), bounds);
537839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    } else {
547839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        bounds.add(cubicPair.second()[0]);
557839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        bounds.add(cubicPair.second()[3]);
567839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
577839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
587839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
597839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerstatic void PathOpsReduceOrderCubicTest(skiatest::Reporter* reporter) {
607839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    size_t index;
617839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    SkReduceOrder reducer;
627839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    int order;
637839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    enum {
647839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        RunAll,
657839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        RunPointDegenerates,
667839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        RunNotPointDegenerates,
677839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        RunLines,
687839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        RunNotLines,
697839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        RunModEpsilonLines,
707839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        RunLessEpsilonLines,
717839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        RunNegEpsilonLines,
727839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        RunQuadraticLines,
737839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        RunQuadraticPoints,
747839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        RunQuadraticModLines,
757839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        RunComputedLines,
767839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        RunNone
777839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    } run = RunAll;
787839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    int firstTestIndex = 0;
797839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#if 0
807839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    run = RunComputedLines;
817839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    firstTestIndex = 18;
827839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#endif
837839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    int firstPointDegeneratesTest = run == RunAll ? 0 : run == RunPointDegenerates
847839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            ? firstTestIndex : SK_MaxS32;
857839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    int firstNotPointDegeneratesTest = run == RunAll ? 0 : run == RunNotPointDegenerates
867839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            ? firstTestIndex : SK_MaxS32;
877839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    int firstLinesTest = run == RunAll ? 0 : run == RunLines ? firstTestIndex : SK_MaxS32;
887839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    int firstNotLinesTest = run == RunAll ? 0 : run == RunNotLines ? firstTestIndex : SK_MaxS32;
897839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    int firstModEpsilonTest = run == RunAll ? 0 : run == RunModEpsilonLines
907839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            ? firstTestIndex : SK_MaxS32;
917839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    int firstLessEpsilonTest = run == RunAll ? 0 : run == RunLessEpsilonLines
927839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            ? firstTestIndex : SK_MaxS32;
937839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    int firstNegEpsilonTest = run == RunAll ? 0 : run == RunNegEpsilonLines
947839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            ? firstTestIndex : SK_MaxS32;
957839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    int firstQuadraticPointTest = run == RunAll ? 0 : run == RunQuadraticPoints
967839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            ? firstTestIndex : SK_MaxS32;
977839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    int firstQuadraticLineTest = run == RunAll ? 0 : run == RunQuadraticLines
987839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            ? firstTestIndex : SK_MaxS32;
997839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    int firstQuadraticModLineTest = run == RunAll ? 0 : run == RunQuadraticModLines
1007839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            ? firstTestIndex : SK_MaxS32;
1017839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    int firstComputedLinesTest = run == RunAll ? 0 : run == RunComputedLines
1027839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            ? firstTestIndex : SK_MaxS32;
1037839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
1047839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    for (index = firstPointDegeneratesTest; index < pointDegenerates_count; ++index) {
1057839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        const SkDCubic& cubic = pointDegenerates[index];
10658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkASSERT(ValidCubic(cubic));
1077839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics, SkReduceOrder::kFill_Style);
1087839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        if (order != 1) {
1097839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            SkDebugf("[%d] pointDegenerates order=%d\n", static_cast<int>(index), order);
1107839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            REPORTER_ASSERT(reporter, 0);
1117839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        }
1127839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
1137839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    for (index = firstNotPointDegeneratesTest; index < notPointDegenerates_count; ++index) {
1147839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        const SkDCubic& cubic = notPointDegenerates[index];
11558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkASSERT(ValidCubic(cubic));
1167839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics, SkReduceOrder::kFill_Style);
1177839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        if (order == 1) {
1187839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            SkDebugf("[%d] notPointDegenerates order=%d\n", static_cast<int>(index), order);
1190a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger            order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics,
1200a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger                    SkReduceOrder::kFill_Style);
1217839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            REPORTER_ASSERT(reporter, 0);
1227839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        }
1237839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
1247839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    for (index = firstLinesTest; index < lines_count; ++index) {
1257839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        const SkDCubic& cubic = lines[index];
12658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkASSERT(ValidCubic(cubic));
1277839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics, SkReduceOrder::kFill_Style);
1287839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        if (order != 2) {
1297839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            SkDebugf("[%d] lines order=%d\n", static_cast<int>(index), order);
1307839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            REPORTER_ASSERT(reporter, 0);
1317839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        }
1327839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
1337839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    for (index = firstNotLinesTest; index < notLines_count; ++index) {
1347839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        const SkDCubic& cubic = notLines[index];
13558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkASSERT(ValidCubic(cubic));
1367839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics, SkReduceOrder::kFill_Style);
1377839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        if (order == 2) {
1387839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            SkDebugf("[%d] notLines order=%d\n", static_cast<int>(index), order);
1397839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            REPORTER_ASSERT(reporter, 0);
1407839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger       }
1417839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
1427839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    for (index = firstModEpsilonTest; index < modEpsilonLines_count; ++index) {
1437839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        const SkDCubic& cubic = modEpsilonLines[index];
14458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkASSERT(ValidCubic(cubic));
1457839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics, SkReduceOrder::kFill_Style);
1467839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        if (order == 2) {
1477839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            SkDebugf("[%d] line mod by epsilon order=%d\n", static_cast<int>(index), order);
1487839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            REPORTER_ASSERT(reporter, 0);
1497839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        }
1507839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
1517839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    for (index = firstLessEpsilonTest; index < lessEpsilonLines_count; ++index) {
1527839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        const SkDCubic& cubic = lessEpsilonLines[index];
15358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkASSERT(ValidCubic(cubic));
1547839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics, SkReduceOrder::kFill_Style);
1557839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        if (order != 2) {
1567839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            SkDebugf("[%d] line less by epsilon/2 order=%d\n", static_cast<int>(index), order);
1570a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger            order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics,
1580a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger                    SkReduceOrder::kFill_Style);
1597839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            REPORTER_ASSERT(reporter, 0);
1607839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        }
1617839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
1627839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    for (index = firstNegEpsilonTest; index < negEpsilonLines_count; ++index) {
1637839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        const SkDCubic& cubic = negEpsilonLines[index];
16458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkASSERT(ValidCubic(cubic));
1657839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics, SkReduceOrder::kFill_Style);
1667839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        if (order != 2) {
1677839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            SkDebugf("[%d] line neg by epsilon/2 order=%d\n", static_cast<int>(index), order);
1687839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            REPORTER_ASSERT(reporter, 0);
1697839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        }
1707839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
1717839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    for (index = firstQuadraticPointTest; index < quadraticPoints_count; ++index) {
1727839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        const SkDQuad& quad = quadraticPoints[index];
17358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkASSERT(ValidQuad(quad));
1747839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        SkDCubic cubic = quad.toCubic();
1757839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics, SkReduceOrder::kFill_Style);
1767839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        if (order != 1) {
1777839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            SkDebugf("[%d] point quad order=%d\n", static_cast<int>(index), order);
1787839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            REPORTER_ASSERT(reporter, 0);
1797839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        }
1807839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
1817839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    for (index = firstQuadraticLineTest; index < quadraticLines_count; ++index) {
1827839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        const SkDQuad& quad = quadraticLines[index];
18358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkASSERT(ValidQuad(quad));
1847839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        SkDCubic cubic = quad.toCubic();
1857839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics, SkReduceOrder::kFill_Style);
1867839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        if (order != 2) {
1877839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            SkDebugf("[%d] line quad order=%d\n", static_cast<int>(index), order);
1887839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            REPORTER_ASSERT(reporter, 0);
1897839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        }
1907839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
1917839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    for (index = firstQuadraticModLineTest; index < quadraticModEpsilonLines_count; ++index) {
1927839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        const SkDQuad& quad = quadraticModEpsilonLines[index];
19358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkASSERT(ValidQuad(quad));
1947839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        SkDCubic cubic = quad.toCubic();
1957839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics, SkReduceOrder::kFill_Style);
1967839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        if (order != 3) {
1977839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            SkDebugf("[%d] line mod quad order=%d\n", static_cast<int>(index), order);
1987839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            REPORTER_ASSERT(reporter, 0);
1997839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        }
2007839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
2017839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
2027839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    // test if computed line end points are valid
2037839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    for (index = firstComputedLinesTest; index < lines_count; ++index) {
2047839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        const SkDCubic& cubic = lines[index];
20558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkASSERT(ValidCubic(cubic));
2067839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        bool controlsInside = controls_inside(cubic);
2077839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics,
2087839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                SkReduceOrder::kStroke_Style);
2097839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        if (order == 2 && reducer.fLine[0] == reducer.fLine[1]) {
2107839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            SkDebugf("[%d] line computed ends match order=%d\n", static_cast<int>(index), order);
2117839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            REPORTER_ASSERT(reporter, 0);
2127839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        }
2137839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        if (controlsInside) {
2147839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            if (       (reducer.fLine[0].fX != cubic[0].fX && reducer.fLine[0].fX != cubic[3].fX)
2157839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                    || (reducer.fLine[0].fY != cubic[0].fY && reducer.fLine[0].fY != cubic[3].fY)
2167839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                    || (reducer.fLine[1].fX != cubic[0].fX && reducer.fLine[1].fX != cubic[3].fX)
2177839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                    || (reducer.fLine[1].fY != cubic[0].fY && reducer.fLine[1].fY != cubic[3].fY)) {
2187839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                SkDebugf("[%d] line computed ends order=%d\n", static_cast<int>(index), order);
2197839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                REPORTER_ASSERT(reporter, 0);
2207839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            }
2217839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        } else {
2227839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            // binary search for extrema, compare against actual results
2237839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                // while a control point is outside of bounding box formed by end points, split
2247839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            SkDRect bounds = {DBL_MAX, DBL_MAX, -DBL_MAX, -DBL_MAX};
2257839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            find_tight_bounds(cubic, bounds);
2267839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            if (      (!AlmostEqualUlps(reducer.fLine[0].fX, bounds.fLeft)
2277839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                    && !AlmostEqualUlps(reducer.fLine[0].fX, bounds.fRight))
2287839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                   || (!AlmostEqualUlps(reducer.fLine[0].fY, bounds.fTop)
2297839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                    && !AlmostEqualUlps(reducer.fLine[0].fY, bounds.fBottom))
2307839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                   || (!AlmostEqualUlps(reducer.fLine[1].fX, bounds.fLeft)
2317839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                    && !AlmostEqualUlps(reducer.fLine[1].fX, bounds.fRight))
2327839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                   || (!AlmostEqualUlps(reducer.fLine[1].fY, bounds.fTop)
2337839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                    && !AlmostEqualUlps(reducer.fLine[1].fY, bounds.fBottom))) {
2347839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                SkDebugf("[%d] line computed tight bounds order=%d\n", static_cast<int>(index), order);
2357839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                REPORTER_ASSERT(reporter, 0);
2367839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            }
2377839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        }
2387839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
2397839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
2407839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
2417839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#include "TestClassDef.h"
2420a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger
2437839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek SollenbergerDEFINE_TESTCLASS_SHORT(PathOpsReduceOrderCubicTest)
244