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 
testTightBoundsLines(PathOpsThreadState * data)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 
DEF_TEST(PathOpsTightBoundsLines,reporter)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 
testTightBoundsQuads(PathOpsThreadState * data)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 
DEF_TEST(PathOpsTightBoundsQuads,reporter)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