Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright 2012 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 #include "PathOpsCubicIntersectionTestData.h"
      8 #include "PathOpsQuadIntersectionTestData.h"
      9 #include "PathOpsTestCommon.h"
     10 #include "SkGeometry.h"
     11 #include "SkIntersections.h"
     12 #include "SkPathOpsRect.h"
     13 #include "SkReduceOrder.h"
     14 #include "Test.h"
     15 
     16 static void test(skiatest::Reporter* reporter, const SkDCubic* cubics, const char* name,
     17                  int firstTest, size_t testCount) {
     18     for (size_t index = firstTest; index < testCount; ++index) {
     19         const SkDCubic& cubic = cubics[index];
     20         SkASSERT(ValidCubic(cubic));
     21         double precision = cubic.calcPrecision();
     22         SkTArray<SkDQuad, true> quads;
     23         CubicToQuads(cubic, precision, quads);
     24         if (quads.count() != 1 && quads.count() != 2) {
     25             SkDebugf("%s [%d] cubic to quadratics failed count=%d\n", name, static_cast<int>(index),
     26                     quads.count());
     27         }
     28         REPORTER_ASSERT(reporter, quads.count() == 1);
     29     }
     30 }
     31 
     32 static void test(skiatest::Reporter* reporter, const SkDQuad* quadTests, const char* name,
     33                  int firstTest, size_t testCount) {
     34     for (size_t index = firstTest; index < testCount; ++index) {
     35         const SkDQuad& quad = quadTests[index];
     36         SkASSERT(ValidQuad(quad));
     37         SkDCubic cubic = quad.toCubic();
     38         double precision = cubic.calcPrecision();
     39         SkTArray<SkDQuad, true> quads;
     40         CubicToQuads(cubic, precision, quads);
     41         if (quads.count() != 1 && quads.count() != 2) {
     42             SkDebugf("%s [%d] cubic to quadratics failed count=%d\n", name, static_cast<int>(index),
     43                     quads.count());
     44         }
     45         REPORTER_ASSERT(reporter, quads.count() <= 2);
     46     }
     47 }
     48 
     49 static void testC(skiatest::Reporter* reporter, const SkDCubic* cubics, const char* name,
     50                   int firstTest, size_t testCount) {
     51     // test if computed line end points are valid
     52     for (size_t index = firstTest; index < testCount; ++index) {
     53         const SkDCubic& cubic = cubics[index];
     54         SkASSERT(ValidCubic(cubic));
     55         double precision = cubic.calcPrecision();
     56         SkTArray<SkDQuad, true> quads;
     57         CubicToQuads(cubic, precision, quads);
     58         if (!AlmostEqualUlps(cubic[0].fX, quads[0][0].fX)
     59                 || !AlmostEqualUlps(cubic[0].fY, quads[0][0].fY)) {
     60             SkDebugf("[%d] unmatched start\n", static_cast<int>(index));
     61             REPORTER_ASSERT(reporter, 0);
     62         }
     63         int last = quads.count() - 1;
     64         if (!AlmostEqualUlps(cubic[3].fX, quads[last][2].fX)
     65                 || !AlmostEqualUlps(cubic[3].fY, quads[last][2].fY)) {
     66             SkDebugf("[%d] unmatched end\n", static_cast<int>(index));
     67             REPORTER_ASSERT(reporter, 0);
     68         }
     69     }
     70 }
     71 
     72 static void testC(skiatest::Reporter* reporter, const SkDCubic(* cubics)[2], const char* name,
     73                   int firstTest, size_t testCount) {
     74     for (size_t index = firstTest; index < testCount; ++index) {
     75         for (int idx2 = 0; idx2 < 2; ++idx2) {
     76             const SkDCubic& cubic = cubics[index][idx2];
     77             SkASSERT(ValidCubic(cubic));
     78             double precision = cubic.calcPrecision();
     79             SkTArray<SkDQuad, true> quads;
     80             CubicToQuads(cubic, precision, quads);
     81             if (!AlmostEqualUlps(cubic[0].fX, quads[0][0].fX)
     82                     || !AlmostEqualUlps(cubic[0].fY, quads[0][0].fY)) {
     83                 SkDebugf("[%d][%d] unmatched start\n", static_cast<int>(index), idx2);
     84                 REPORTER_ASSERT(reporter, 0);
     85             }
     86             int last = quads.count() - 1;
     87             if (!AlmostEqualUlps(cubic[3].fX, quads[last][2].fX)
     88                     || !AlmostEqualUlps(cubic[3].fY, quads[last][2].fY)) {
     89                 SkDebugf("[%d][%d] unmatched end\n", static_cast<int>(index), idx2);
     90                 REPORTER_ASSERT(reporter, 0);
     91             }
     92         }
     93     }
     94 }
     95 
     96 DEF_TEST(CubicToQuads, reporter) {
     97     enum {
     98         RunAll,
     99         RunPointDegenerates,
    100         RunNotPointDegenerates,
    101         RunLines,
    102         RunNotLines,
    103         RunModEpsilonLines,
    104         RunLessEpsilonLines,
    105         RunNegEpsilonLines,
    106         RunQuadraticLines,
    107         RunQuadraticModLines,
    108         RunComputedLines,
    109         RunComputedTests,
    110         RunNone
    111     } run = RunAll;
    112     int firstTestIndex = 0;
    113 #if 0
    114     run = RunComputedLines;
    115     firstTestIndex = 18;
    116 #endif
    117     int firstPointDegeneratesTest = run == RunAll ? 0 : run == RunPointDegenerates
    118             ? firstTestIndex : SK_MaxS32;
    119     int firstNotPointDegeneratesTest = run == RunAll ? 0 : run == RunNotPointDegenerates
    120             ? firstTestIndex : SK_MaxS32;
    121     int firstLinesTest = run == RunAll ? 0 : run == RunLines ? firstTestIndex : SK_MaxS32;
    122     int firstNotLinesTest = run == RunAll ? 0 : run == RunNotLines ? firstTestIndex : SK_MaxS32;
    123     int firstModEpsilonTest = run == RunAll ? 0 : run == RunModEpsilonLines
    124             ? firstTestIndex : SK_MaxS32;
    125     int firstLessEpsilonTest = run == RunAll ? 0 : run == RunLessEpsilonLines
    126             ? firstTestIndex : SK_MaxS32;
    127     int firstNegEpsilonTest = run == RunAll ? 0 : run == RunNegEpsilonLines
    128             ? firstTestIndex : SK_MaxS32;
    129     int firstQuadraticLineTest = run == RunAll ? 0 : run == RunQuadraticLines
    130             ? firstTestIndex : SK_MaxS32;
    131     int firstQuadraticModLineTest = run == RunAll ? 0 : run == RunQuadraticModLines
    132             ? firstTestIndex : SK_MaxS32;
    133     int firstComputedLinesTest = run == RunAll ? 0 : run == RunComputedLines
    134             ? firstTestIndex : SK_MaxS32;
    135     int firstComputedCubicsTest = run == RunAll ? 0 : run == RunComputedTests
    136             ? firstTestIndex : SK_MaxS32;
    137 
    138     test(reporter, pointDegenerates, "pointDegenerates", firstPointDegeneratesTest,
    139             pointDegenerates_count);
    140     testC(reporter, notPointDegenerates, "notPointDegenerates", firstNotPointDegeneratesTest,
    141             notPointDegenerates_count);
    142     test(reporter, lines, "lines", firstLinesTest, lines_count);
    143     testC(reporter, notLines, "notLines", firstNotLinesTest, notLines_count);
    144     testC(reporter, modEpsilonLines, "modEpsilonLines", firstModEpsilonTest, modEpsilonLines_count);
    145     test(reporter, lessEpsilonLines, "lessEpsilonLines", firstLessEpsilonTest,
    146             lessEpsilonLines_count);
    147     test(reporter, negEpsilonLines, "negEpsilonLines", firstNegEpsilonTest, negEpsilonLines_count);
    148     test(reporter, quadraticLines, "quadraticLines", firstQuadraticLineTest, quadraticLines_count);
    149     test(reporter, quadraticModEpsilonLines, "quadraticModEpsilonLines", firstQuadraticModLineTest,
    150             quadraticModEpsilonLines_count);
    151     testC(reporter, lines, "computed lines", firstComputedLinesTest, lines_count);
    152     testC(reporter, tests, "computed tests", firstComputedCubicsTest, tests_count);
    153 }
    154 
    155 static SkDCubic locals[] = {
    156     {{{0, 1}, {1.9274705288631189e-19, 1.0000000000000002},
    157             {0.0017190297609673323, 0.99828097023903239},
    158             {0.0053709083094631276, 0.99505672974365911}}},
    159     {{{14.5975863, 41.632436}, {16.3518929, 26.2639684}, {18.5165519, 7.68775139},
    160             {8.03767257, 89.1628526}}},
    161     {{{69.7292014, 38.6877352}, {24.7648688, 23.1501713}, {84.9283191, 90.2588441},
    162             {80.392774, 61.3533852}}},
    163     {{{60.776536520932126, 71.249307306133829}, {87.107894191103014, 22.377669868235323},
    164             {1.4974754310666936, 68.069569937917208}, {45.261946574441133, 17.536076632112298}}},
    165 };
    166 
    167 static size_t localsCount = SK_ARRAY_COUNT(locals);
    168 
    169 #define DEBUG_CRASH 0
    170 #define TEST_AVERAGE_END_POINTS 0  // must take const off to test
    171 extern const bool AVERAGE_END_POINTS;
    172 
    173 static void oneOff(skiatest::Reporter* reporter, size_t x) {
    174     const SkDCubic& cubic = locals[x];
    175     SkASSERT(ValidCubic(cubic));
    176     const SkPoint skcubic[4] = {
    177             {static_cast<float>(cubic[0].fX), static_cast<float>(cubic[0].fY)},
    178             {static_cast<float>(cubic[1].fX), static_cast<float>(cubic[1].fY)},
    179             {static_cast<float>(cubic[2].fX), static_cast<float>(cubic[2].fY)},
    180             {static_cast<float>(cubic[3].fX), static_cast<float>(cubic[3].fY)}};
    181     SkScalar skinflect[2];
    182     int skin = SkFindCubicInflections(skcubic, skinflect);
    183     if (false) SkDebugf("%s %d %1.9g\n", __FUNCTION__, skin, skinflect[0]);
    184     SkTArray<SkDQuad, true> quads;
    185     double precision = cubic.calcPrecision();
    186     CubicToQuads(cubic, precision, quads);
    187     if (false) SkDebugf("%s quads=%d\n", __FUNCTION__, quads.count());
    188 }
    189 
    190 DEF_TEST(CubicsToQuadratics_OneOff_Loop, reporter) {
    191     for (size_t x = 0; x < localsCount; ++x) {
    192         oneOff(reporter, x);
    193     }
    194 }
    195 
    196 DEF_TEST(CubicsToQuadratics_OneOff_Single, reporter) {
    197     oneOff(reporter, 0);
    198 }
    199