1fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/*
2fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Copyright 2012 Google Inc.
3fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *
4fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Use of this source code is governed by a BSD-style license that can be
5fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * found in the LICENSE file.
6fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */
7fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "PathOpsCubicIntersectionTestData.h"
8fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "PathOpsQuadIntersectionTestData.h"
9fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "PathOpsTestCommon.h"
10fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkIntersections.h"
11fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPathOpsRect.h"
12fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkReduceOrder.h"
13fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "Test.h"
14fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
15fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if 0 // disable test until stroke reduction is supported
16fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic bool controls_inside(const SkDCubic& cubic) {
17fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return between(cubic[0].fX, cubic[1].fX, cubic[3].fX)
18fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            && between(cubic[0].fX, cubic[2].fX, cubic[3].fX)
19fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            && between(cubic[0].fY, cubic[1].fY, cubic[3].fY)
20fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            && between(cubic[0].fY, cubic[2].fY, cubic[3].fY);
21fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
22fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
23fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic bool tiny(const SkDCubic& cubic) {
24fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int index, minX, maxX, minY, maxY;
25fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    minX = maxX = minY = maxY = 0;
26fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    for (index = 1; index < 4; ++index) {
27fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (cubic[minX].fX > cubic[index].fX) {
28fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            minX = index;
29fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
30fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (cubic[minY].fY > cubic[index].fY) {
31fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            minY = index;
32fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
33fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (cubic[maxX].fX < cubic[index].fX) {
34fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            maxX = index;
35fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
36fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (cubic[maxY].fY < cubic[index].fY) {
37fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            maxY = index;
38fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
39fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
40fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return     approximately_equal(cubic[maxX].fX, cubic[minX].fX)
41fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            && approximately_equal(cubic[maxY].fY, cubic[minY].fY);
42fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
43fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
44fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void find_tight_bounds(const SkDCubic& cubic, SkDRect& bounds) {
45fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDCubicPair cubicPair = cubic.chopAt(0.5);
46fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!tiny(cubicPair.first()) && !controls_inside(cubicPair.first())) {
47fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        find_tight_bounds(cubicPair.first(), bounds);
48fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    } else {
49fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        bounds.add(cubicPair.first()[0]);
50fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        bounds.add(cubicPair.first()[3]);
51fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
52fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!tiny(cubicPair.second()) && !controls_inside(cubicPair.second())) {
53fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        find_tight_bounds(cubicPair.second(), bounds);
54fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    } else {
55fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        bounds.add(cubicPair.second()[0]);
56fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        bounds.add(cubicPair.second()[3]);
57fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
58fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
59fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
60fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
61fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_TEST(PathOpsReduceOrderCubic, reporter) {
62fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    size_t index;
63fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkReduceOrder reducer;
64fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int order;
65fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    enum {
66fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        RunAll,
67fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        RunPointDegenerates,
68fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        RunNotPointDegenerates,
69fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        RunLines,
70fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        RunNotLines,
71fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        RunModEpsilonLines,
72fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        RunLessEpsilonLines,
73fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        RunNegEpsilonLines,
74fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        RunQuadraticLines,
75fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        RunQuadraticPoints,
76fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        RunQuadraticModLines,
77fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        RunComputedLines,
78fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        RunNone
79fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    } run = RunAll;
80fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int firstTestIndex = 0;
81fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if 0
82fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    run = RunComputedLines;
83fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    firstTestIndex = 18;
84fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
85fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int firstPointDegeneratesTest = run == RunAll ? 0 : run == RunPointDegenerates
86fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            ? firstTestIndex : SK_MaxS32;
87fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int firstNotPointDegeneratesTest = run == RunAll ? 0 : run == RunNotPointDegenerates
88fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            ? firstTestIndex : SK_MaxS32;
89fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int firstLinesTest = run == RunAll ? 0 : run == RunLines ? firstTestIndex : SK_MaxS32;
90fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int firstNotLinesTest = run == RunAll ? 0 : run == RunNotLines ? firstTestIndex : SK_MaxS32;
91fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int firstModEpsilonTest = run == RunAll ? 0 : run == RunModEpsilonLines
92fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            ? firstTestIndex : SK_MaxS32;
93fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int firstLessEpsilonTest = run == RunAll ? 0 : run == RunLessEpsilonLines
94fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            ? firstTestIndex : SK_MaxS32;
95fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int firstNegEpsilonTest = run == RunAll ? 0 : run == RunNegEpsilonLines
96fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            ? firstTestIndex : SK_MaxS32;
97fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int firstQuadraticPointTest = run == RunAll ? 0 : run == RunQuadraticPoints
98fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            ? firstTestIndex : SK_MaxS32;
99fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int firstQuadraticLineTest = run == RunAll ? 0 : run == RunQuadraticLines
100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            ? firstTestIndex : SK_MaxS32;
101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int firstQuadraticModLineTest = run == RunAll ? 0 : run == RunQuadraticModLines
102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            ? firstTestIndex : SK_MaxS32;
103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if 0
104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int firstComputedLinesTest = run == RunAll ? 0 : run == RunComputedLines
105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            ? firstTestIndex : SK_MaxS32;
106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    for (index = firstPointDegeneratesTest; index < pointDegenerates_count; ++index) {
108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const CubicPts& c = pointDegenerates[index];
109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDCubic cubic;
110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        cubic.debugSet(c.fPts);
111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(ValidCubic(cubic));
112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics);
113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (order != 1) {
114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkDebugf("[%d] pointDegenerates order=%d\n", static_cast<int>(index), order);
115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            REPORTER_ASSERT(reporter, 0);
116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    for (index = firstNotPointDegeneratesTest; index < notPointDegenerates_count; ++index) {
119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const CubicPts& c = notPointDegenerates[index];
120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDCubic cubic;
121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        cubic.debugSet(c.fPts);
122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(ValidCubic(cubic));
123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics);
124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (order == 1) {
125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkDebugf("[%d] notPointDegenerates order=%d\n", static_cast<int>(index), order);
126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics);
127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            REPORTER_ASSERT(reporter, 0);
128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    for (index = firstLinesTest; index < lines_count; ++index) {
131fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const CubicPts& c = lines[index];
132fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDCubic cubic;
133fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        cubic.debugSet(c.fPts);
134fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(ValidCubic(cubic));
135fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics);
136fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (order != 2) {
137fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkDebugf("[%d] lines order=%d\n", static_cast<int>(index), order);
138fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            REPORTER_ASSERT(reporter, 0);
139fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
140fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
141fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    for (index = firstNotLinesTest; index < notLines_count; ++index) {
142fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const CubicPts& c = notLines[index];
143fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDCubic cubic;
144fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        cubic.debugSet(c.fPts);
145fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(ValidCubic(cubic));
146fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics);
147fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (order == 2) {
148fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkDebugf("[%d] notLines order=%d\n", static_cast<int>(index), order);
149fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            REPORTER_ASSERT(reporter, 0);
150fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot       }
151fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
152fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    for (index = firstModEpsilonTest; index < modEpsilonLines_count; ++index) {
153fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const CubicPts& c = modEpsilonLines[index];
154fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDCubic cubic;
155fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        cubic.debugSet(c.fPts);
156fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(ValidCubic(cubic));
157fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics);
158fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (order == 2) {
159fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkDebugf("[%d] line mod by epsilon order=%d\n", static_cast<int>(index), order);
160fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            REPORTER_ASSERT(reporter, 0);
161fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
162fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
163fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    for (index = firstLessEpsilonTest; index < lessEpsilonLines_count; ++index) {
164fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const CubicPts& c = lessEpsilonLines[index];
165fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDCubic cubic;
166fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        cubic.debugSet(c.fPts);
167fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(ValidCubic(cubic));
168fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics);
169fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (order != 2) {
170fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkDebugf("[%d] line less by epsilon/2 order=%d\n", static_cast<int>(index), order);
171fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics);
172fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            REPORTER_ASSERT(reporter, 0);
173fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
174fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
175fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    for (index = firstNegEpsilonTest; index < negEpsilonLines_count; ++index) {
176fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const CubicPts& c = negEpsilonLines[index];
177fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDCubic cubic;
178fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        cubic.debugSet(c.fPts);
179fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(ValidCubic(cubic));
180fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics);
181fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (order != 2) {
182fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkDebugf("[%d] line neg by epsilon/2 order=%d\n", static_cast<int>(index), order);
183fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            REPORTER_ASSERT(reporter, 0);
184fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
185fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
186fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    for (index = firstQuadraticPointTest; index < quadraticPoints_count; ++index) {
187fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const QuadPts& q = quadraticPoints[index];
188fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDQuad quad;
189fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        quad.debugSet(q.fPts);
190fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(ValidQuad(quad));
191fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDCubic cubic = quad.debugToCubic();
192fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics);
193fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (order != 1) {
194fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkDebugf("[%d] point quad order=%d\n", static_cast<int>(index), order);
195fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            REPORTER_ASSERT(reporter, 0);
196fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
197fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
198fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    for (index = firstQuadraticLineTest; index < quadraticLines_count; ++index) {
199fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const QuadPts& q = quadraticLines[index];
200fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDQuad quad;
201fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        quad.debugSet(q.fPts);
202fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(ValidQuad(quad));
203fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDCubic cubic = quad.debugToCubic();
204fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics);
205fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (order != 2) {
206fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkDebugf("[%d] line quad order=%d\n", static_cast<int>(index), order);
207fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            REPORTER_ASSERT(reporter, 0);
208fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
209fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
210fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    for (index = firstQuadraticModLineTest; index < quadraticModEpsilonLines_count; ++index) {
211fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const QuadPts& q = quadraticModEpsilonLines[index];
212fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDQuad quad;
213fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        quad.debugSet(q.fPts);
214fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(ValidQuad(quad));
215fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDCubic cubic = quad.debugToCubic();
216fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics);
217fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (order != 3) {
218fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkDebugf("[%d] line mod quad order=%d\n", static_cast<int>(index), order);
219fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            REPORTER_ASSERT(reporter, 0);
220fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
221fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
222fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
223fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if 0 // disable test until stroke reduction is supported
224fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// test if computed line end points are valid
225fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    for (index = firstComputedLinesTest; index < lines_count; ++index) {
226fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const SkDCubic& cubic = lines[index];
227fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(ValidCubic(cubic));
228fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        bool controlsInside = controls_inside(cubic);
229fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics,
230fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkReduceOrder::kStroke_Style);
231fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (order == 2 && reducer.fLine[0] == reducer.fLine[1]) {
232fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkDebugf("[%d] line computed ends match order=%d\n", static_cast<int>(index), order);
233fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            REPORTER_ASSERT(reporter, 0);
234fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
235fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (controlsInside) {
236fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (       (reducer.fLine[0].fX != cubic[0].fX && reducer.fLine[0].fX != cubic[3].fX)
237fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    || (reducer.fLine[0].fY != cubic[0].fY && reducer.fLine[0].fY != cubic[3].fY)
238fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    || (reducer.fLine[1].fX != cubic[0].fX && reducer.fLine[1].fX != cubic[3].fX)
239fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    || (reducer.fLine[1].fY != cubic[0].fY && reducer.fLine[1].fY != cubic[3].fY)) {
240fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkDebugf("[%d] line computed ends order=%d\n", static_cast<int>(index), order);
241fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                REPORTER_ASSERT(reporter, 0);
242fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
243fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        } else {
244fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            // binary search for extrema, compare against actual results
245fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                // while a control point is outside of bounding box formed by end points, split
246fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkDRect bounds = {DBL_MAX, DBL_MAX, -DBL_MAX, -DBL_MAX};
247fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            find_tight_bounds(cubic, bounds);
248fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (      (!AlmostEqualUlps(reducer.fLine[0].fX, bounds.fLeft)
249fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    && !AlmostEqualUlps(reducer.fLine[0].fX, bounds.fRight))
250fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                   || (!AlmostEqualUlps(reducer.fLine[0].fY, bounds.fTop)
251fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    && !AlmostEqualUlps(reducer.fLine[0].fY, bounds.fBottom))
252fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                   || (!AlmostEqualUlps(reducer.fLine[1].fX, bounds.fLeft)
253fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    && !AlmostEqualUlps(reducer.fLine[1].fX, bounds.fRight))
254fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                   || (!AlmostEqualUlps(reducer.fLine[1].fY, bounds.fTop)
255fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    && !AlmostEqualUlps(reducer.fLine[1].fY, bounds.fBottom))) {
256fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkDebugf("[%d] line computed tight bounds order=%d\n", static_cast<int>(index), order);
257fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                REPORTER_ASSERT(reporter, 0);
258fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
259fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
260fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
261fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
262fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
263