Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright 2013 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 "PathOpsExtendedTest.h"
      8 #include "PathOpsThreadedCommon.h"
      9 #include "SkCanvas.h"
     10 #include "SkRandom.h"
     11 #include "SkTSort.h"
     12 #include "Test.h"
     13 
     14 static void testTightBoundsLines(PathOpsThreadState* data) {
     15     SkRandom ran;
     16     for (int index = 0; index < 1000; ++index) {
     17         SkPath path;
     18         int contourCount = ran.nextRangeU(1, 10);
     19         for (int cIndex = 0; cIndex < contourCount; ++cIndex) {
     20             int lineCount = ran.nextRangeU(1, 10);
     21             path.moveTo(ran.nextRangeF(-1000, 1000), ran.nextRangeF(-1000, 1000));
     22             for (int lIndex = 0; lIndex < lineCount; ++lIndex) {
     23                 path.lineTo(ran.nextRangeF(-1000, 1000), ran.nextRangeF(-1000, 1000));
     24             }
     25             if (ran.nextBool()) {
     26                 path.close();
     27             }
     28         }
     29         SkRect classicBounds = path.getBounds();
     30         SkRect tightBounds;
     31         REPORTER_ASSERT(data->fReporter, TightBounds(path, &tightBounds));
     32         REPORTER_ASSERT(data->fReporter, classicBounds == tightBounds);
     33     }
     34 }
     35 
     36 DEF_TEST(PathOpsTightBoundsLines, reporter) {
     37     initializeTests(reporter, "tightBoundsLines");
     38     PathOpsThreadedTestRunner testRunner(reporter);
     39     int outerCount = reporter->allowExtendedTest() ? 100 : 1;
     40     for (int index = 0; index < outerCount; ++index) {
     41         for (int idx2 = 0; idx2 < 10; ++idx2) {
     42             *testRunner.fRunnables.append() =
     43                     new PathOpsThreadedRunnable(&testTightBoundsLines, 0, 0, 0, 0, &testRunner);
     44         }
     45     }
     46     testRunner.render();
     47 }
     48 
     49 static void testTightBoundsQuads(PathOpsThreadState* data) {
     50     SkRandom ran;
     51     const int bitWidth = 32;
     52     const int bitHeight = 32;
     53     const float pathMin = 1;
     54     const float pathMax = (float) (bitHeight - 2);
     55     SkBitmap& bits = *data->fBitmap;
     56     if (bits.width() == 0) {
     57         bits.allocN32Pixels(bitWidth, bitHeight);
     58     }
     59     SkCanvas canvas(bits);
     60     SkPaint paint;
     61     for (int index = 0; index < 100; ++index) {
     62         SkPath path;
     63         int contourCount = ran.nextRangeU(1, 10);
     64         for (int cIndex = 0; cIndex < contourCount; ++cIndex) {
     65             int lineCount = ran.nextRangeU(1, 10);
     66             path.moveTo(ran.nextRangeF(1, pathMax), ran.nextRangeF(pathMin, pathMax));
     67             for (int lIndex = 0; lIndex < lineCount; ++lIndex) {
     68                 if (ran.nextBool()) {
     69                     path.lineTo(ran.nextRangeF(pathMin, pathMax), ran.nextRangeF(pathMin, pathMax));
     70                 } else {
     71                     path.quadTo(ran.nextRangeF(pathMin, pathMax), ran.nextRangeF(pathMin, pathMax),
     72                             ran.nextRangeF(pathMin, pathMax), ran.nextRangeF(pathMin, pathMax));
     73                 }
     74             }
     75             if (ran.nextBool()) {
     76                 path.close();
     77             }
     78         }
     79         SkRect classicBounds = path.getBounds();
     80         SkRect tightBounds;
     81         REPORTER_ASSERT(data->fReporter, TightBounds(path, &tightBounds));
     82         REPORTER_ASSERT(data->fReporter, classicBounds.contains(tightBounds));
     83         canvas.drawColor(SK_ColorWHITE);
     84         canvas.drawPath(path, paint);
     85         SkIRect bitsWritten = {31, 31, 0, 0};
     86         for (int y = 0; y < bitHeight; ++y) {
     87             uint32_t* addr1 = data->fBitmap->getAddr32(0, y);
     88             bool lineWritten = false;
     89             for (int x = 0; x < bitWidth; ++x) {
     90                 if (addr1[x] == (uint32_t) -1) {
     91                     continue;
     92                 }
     93                 lineWritten = true;
     94                 bitsWritten.fLeft = SkTMin(bitsWritten.fLeft, x);
     95                 bitsWritten.fRight = SkTMax(bitsWritten.fRight, x);
     96             }
     97             if (!lineWritten) {
     98                 continue;
     99             }
    100             bitsWritten.fTop = SkTMin(bitsWritten.fTop, y);
    101             bitsWritten.fBottom = SkTMax(bitsWritten.fBottom, y);
    102         }
    103         if (!bitsWritten.isEmpty()) {
    104             SkIRect tightOut;
    105             tightBounds.roundOut(&tightOut);
    106             REPORTER_ASSERT(data->fReporter, tightOut.contains(bitsWritten));
    107         }
    108     }
    109 }
    110 
    111 DEF_TEST(PathOpsTightBoundsQuads, reporter) {
    112     initializeTests(reporter, "tightBoundsQuads");
    113     PathOpsThreadedTestRunner testRunner(reporter);
    114     int outerCount = reporter->allowExtendedTest() ? 100 : 1;
    115     for (int index = 0; index < outerCount; ++index) {
    116         for (int idx2 = 0; idx2 < 10; ++idx2) {
    117             *testRunner.fRunnables.append() =
    118                     new PathOpsThreadedRunnable(&testTightBoundsQuads, 0, 0, 0, 0, &testRunner);
    119         }
    120     }
    121     testRunner.render();
    122 }
    123 
    124 DEF_TEST(PathOpsTightBoundsMove, reporter) {
    125     SkPath path;
    126     path.moveTo(10, 10);
    127     path.close();
    128     path.moveTo(20, 20);
    129     path.lineTo(20, 20);
    130     path.close();
    131     path.moveTo(15, 15);
    132     path.lineTo(15, 15);
    133     path.close();
    134     const SkRect& bounds = path.getBounds();
    135     SkRect tight;
    136     REPORTER_ASSERT(reporter, TightBounds(path, &tight));
    137     REPORTER_ASSERT(reporter, bounds == tight);
    138 }
    139 
    140 DEF_TEST(PathOpsTightBoundsMoveOne, reporter) {
    141     SkPath path;
    142     path.moveTo(20, 20);
    143     const SkRect& bounds = path.getBounds();
    144     SkRect tight;
    145     REPORTER_ASSERT(reporter, TightBounds(path, &tight));
    146     REPORTER_ASSERT(reporter, bounds == tight);
    147 }
    148 
    149 DEF_TEST(PathOpsTightBoundsMoveTwo, reporter) {
    150     SkPath path;
    151     path.moveTo(20, 20);
    152     path.moveTo(40, 40);
    153     const SkRect& bounds = path.getBounds();
    154     SkRect tight;
    155     REPORTER_ASSERT(reporter, TightBounds(path, &tight));
    156     REPORTER_ASSERT(reporter, bounds == tight);
    157 }
    158 
    159 DEF_TEST(PathOpsTightBoundsTiny, reporter) {
    160     SkPath path;
    161     path.moveTo(1, 1);
    162     path.quadTo(1.000001f, 1, 1, 1);
    163     const SkRect& bounds = path.getBounds();
    164     SkRect tight;
    165     REPORTER_ASSERT(reporter, TightBounds(path, &tight));
    166     SkRect moveBounds = {1, 1, 1, 1};
    167     REPORTER_ASSERT(reporter, bounds != tight);
    168     REPORTER_ASSERT(reporter, moveBounds == tight);
    169 }
    170 
    171 DEF_TEST(PathOpsTightBoundsWellBehaved, reporter) {
    172     SkPath path;
    173     path.moveTo(1, 1);
    174     path.quadTo(2, 3, 4, 5);
    175     const SkRect& bounds = path.getBounds();
    176     SkRect tight;
    177     REPORTER_ASSERT(reporter, TightBounds(path, &tight));
    178     REPORTER_ASSERT(reporter, bounds == tight);
    179 }
    180 
    181 DEF_TEST(PathOpsTightBoundsIllBehaved, reporter) {
    182     SkPath path;
    183     path.moveTo(1, 1);
    184     path.quadTo(4, 3, 2, 2);
    185     const SkRect& bounds = path.getBounds();
    186     SkRect tight;
    187     REPORTER_ASSERT(reporter, TightBounds(path, &tight));
    188     REPORTER_ASSERT(reporter, bounds != tight);
    189 }
    190 
    191 DEF_TEST(PathOpsTightBoundsIllBehavedScaled, reporter) {
    192     SkPath path;
    193     path.moveTo(0, 0);
    194     path.quadTo(1048578, 1048577, 1048576, 1048576);
    195     const SkRect& bounds = path.getBounds();
    196     SkRect tight;
    197     REPORTER_ASSERT(reporter, TightBounds(path, &tight));
    198     REPORTER_ASSERT(reporter, bounds != tight);
    199     REPORTER_ASSERT(reporter, tight.right() == 1048576);
    200     REPORTER_ASSERT(reporter, tight.bottom() == 1048576);
    201 }
    202