Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
PathOpsTightBoundsTest.cpp
Go to the documentation of this file.
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 */
11#include "include/core/SkPath.h"
12#include "include/core/SkRect.h"
15#include "src/base/SkRandom.h"
18#include "tests/Test.h"
19
20#include <algorithm>
21#include <cstdint>
22
24 SkRandom ran;
25 for (int index = 0; index < 1000; ++index) {
26 SkPath path;
27 int contourCount = ran.nextRangeU(1, 10);
28 for (int cIndex = 0; cIndex < contourCount; ++cIndex) {
29 int lineCount = ran.nextRangeU(1, 10);
30 path.moveTo(ran.nextRangeF(-1000, 1000), ran.nextRangeF(-1000, 1000));
31 for (int lIndex = 0; lIndex < lineCount; ++lIndex) {
32 path.lineTo(ran.nextRangeF(-1000, 1000), ran.nextRangeF(-1000, 1000));
33 }
34 if (ran.nextBool()) {
35 path.close();
36 }
37 }
38 SkRect classicBounds = path.getBounds();
39 SkRect tightBounds;
40 REPORTER_ASSERT(data->fReporter, TightBounds(path, &tightBounds));
41 REPORTER_ASSERT(data->fReporter, classicBounds == tightBounds);
42 }
43}
44
45DEF_TEST(PathOpsTightBoundsLines, reporter) {
46 initializeTests(reporter, "tightBoundsLines");
48 int outerCount = reporter->allowExtendedTest() ? 100 : 1;
49 for (int index = 0; index < outerCount; ++index) {
50 for (int idx2 = 0; idx2 < 10; ++idx2) {
51 *testRunner.fRunnables.append() =
52 new PathOpsThreadedRunnable(&testTightBoundsLines, 0, 0, 0, 0, &testRunner);
53 }
54 }
55 testRunner.render();
56}
57
59 SkRandom ran;
60 const int bitWidth = 32;
61 const int bitHeight = 32;
62 const float pathMin = 1;
63 const float pathMax = (float) (bitHeight - 2);
64 SkBitmap& bits = *data->fBitmap;
65 if (bits.width() == 0) {
66 bits.allocN32Pixels(bitWidth, bitHeight);
67 }
68 SkCanvas canvas(bits);
70 for (int index = 0; index < 100; ++index) {
71 SkPath path;
72 int contourCount = ran.nextRangeU(1, 10);
73 for (int cIndex = 0; cIndex < contourCount; ++cIndex) {
74 int lineCount = ran.nextRangeU(1, 10);
75 path.moveTo(ran.nextRangeF(1, pathMax), ran.nextRangeF(pathMin, pathMax));
76 for (int lIndex = 0; lIndex < lineCount; ++lIndex) {
77 if (ran.nextBool()) {
78 path.lineTo(ran.nextRangeF(pathMin, pathMax), ran.nextRangeF(pathMin, pathMax));
79 } else {
80 path.quadTo(ran.nextRangeF(pathMin, pathMax), ran.nextRangeF(pathMin, pathMax),
81 ran.nextRangeF(pathMin, pathMax), ran.nextRangeF(pathMin, pathMax));
82 }
83 }
84 if (ran.nextBool()) {
85 path.close();
86 }
87 }
88 SkRect classicBounds = path.getBounds();
89 SkRect tightBounds;
90 REPORTER_ASSERT(data->fReporter, TightBounds(path, &tightBounds));
91 REPORTER_ASSERT(data->fReporter, classicBounds.contains(tightBounds));
93 canvas.drawPath(path, paint);
94 SkIRect bitsWritten = {31, 31, 0, 0};
95 for (int y = 0; y < bitHeight; ++y) {
96 uint32_t* addr1 = data->fBitmap->getAddr32(0, y);
97 bool lineWritten = false;
98 for (int x = 0; x < bitWidth; ++x) {
99 if (addr1[x] == (uint32_t) -1) {
100 continue;
101 }
102 lineWritten = true;
103 bitsWritten.fLeft = std::min(bitsWritten.fLeft, x);
104 bitsWritten.fRight = std::max(bitsWritten.fRight, x);
105 }
106 if (!lineWritten) {
107 continue;
108 }
109 bitsWritten.fTop = std::min(bitsWritten.fTop, y);
110 bitsWritten.fBottom = std::max(bitsWritten.fBottom, y);
111 }
112 if (!bitsWritten.isEmpty()) {
113 SkIRect tightOut;
114 tightBounds.roundOut(&tightOut);
115 REPORTER_ASSERT(data->fReporter, tightOut.contains(bitsWritten));
116 }
117 }
118}
119
120DEF_TEST(PathOpsTightBoundsQuads, reporter) {
121 initializeTests(reporter, "tightBoundsQuads");
123 int outerCount = reporter->allowExtendedTest() ? 100 : 1;
124 for (int index = 0; index < outerCount; ++index) {
125 for (int idx2 = 0; idx2 < 10; ++idx2) {
126 *testRunner.fRunnables.append() =
127 new PathOpsThreadedRunnable(&testTightBoundsQuads, 0, 0, 0, 0, &testRunner);
128 }
129 }
130 testRunner.render();
131}
132
133DEF_TEST(PathOpsTightBoundsMove, reporter) {
134 SkPath path;
135 path.moveTo(10, 10);
136 path.close();
137 path.moveTo(20, 20);
138 path.lineTo(20, 20);
139 path.close();
140 path.moveTo(15, 15);
141 path.lineTo(15, 15);
142 path.close();
143 const SkRect& bounds = path.getBounds();
144 SkRect tight;
145 REPORTER_ASSERT(reporter, TightBounds(path, &tight));
146 REPORTER_ASSERT(reporter, bounds == tight);
147}
148
149DEF_TEST(PathOpsTightBoundsMoveOne, reporter) {
150 SkPath path;
151 path.moveTo(20, 20);
152 const SkRect& bounds = path.getBounds();
153 SkRect tight;
154 REPORTER_ASSERT(reporter, TightBounds(path, &tight));
155 REPORTER_ASSERT(reporter, bounds == tight);
156}
157
158DEF_TEST(PathOpsTightBoundsMoveTwo, reporter) {
159 SkPath path;
160 path.moveTo(20, 20);
161 path.moveTo(40, 40);
162 const SkRect& bounds = path.getBounds();
163 SkRect tight;
164 REPORTER_ASSERT(reporter, TightBounds(path, &tight));
165 REPORTER_ASSERT(reporter, bounds == tight);
166}
167
168DEF_TEST(PathOpsTightBoundsTiny, reporter) {
169 SkPath path;
170 path.moveTo(1, 1);
171 path.quadTo(1.000001f, 1, 1, 1);
172 const SkRect& bounds = path.getBounds();
173 SkRect tight;
174 REPORTER_ASSERT(reporter, TightBounds(path, &tight));
175 SkRect moveBounds = {1, 1, 1, 1};
176 REPORTER_ASSERT(reporter, bounds != tight);
177 REPORTER_ASSERT(reporter, moveBounds == tight);
178}
179
180DEF_TEST(PathOpsTightBoundsWellBehaved, reporter) {
181 SkPath path;
182 path.moveTo(1, 1);
183 path.quadTo(2, 3, 4, 5);
184 const SkRect& bounds = path.getBounds();
185 SkRect tight;
186 REPORTER_ASSERT(reporter, TightBounds(path, &tight));
187 REPORTER_ASSERT(reporter, bounds == tight);
188}
189
190DEF_TEST(PathOpsTightBoundsIllBehaved, reporter) {
191 SkPath path;
192 path.moveTo(1, 1);
193 path.quadTo(4, 3, 2, 2);
194 const SkRect& bounds = path.getBounds();
195 SkRect tight;
196 REPORTER_ASSERT(reporter, TightBounds(path, &tight));
197 REPORTER_ASSERT(reporter, bounds != tight);
198}
199
200DEF_TEST(PathOpsTightBoundsIllBehavedScaled, reporter) {
201 SkPath path;
202 path.moveTo(0, 0);
203 path.quadTo(1048578, 1048577, 1048576, 1048576);
204 const SkRect& bounds = path.getBounds();
205 SkRect tight;
206 REPORTER_ASSERT(reporter, TightBounds(path, &tight));
207 REPORTER_ASSERT(reporter, bounds != tight);
208 REPORTER_ASSERT(reporter, tight.right() == 1048576);
209 REPORTER_ASSERT(reporter, tight.bottom() == 1048576);
210}
reporter
void initializeTests(skiatest::Reporter *reporter, const char *test)
static void testTightBoundsQuads(PathOpsThreadState *data)
static void testTightBoundsLines(PathOpsThreadState *data)
constexpr SkColor SK_ColorWHITE
Definition SkColor.h:122
bool SK_API TightBounds(const SkPath &path, SkRect *result)
#define DEF_TEST(name, reporter)
Definition Test.h:312
#define REPORTER_ASSERT(r, cond,...)
Definition Test.h:286
SkTDArray< PathOpsThreadedRunnable * > fRunnables
void drawColor(SkColor color, SkBlendMode mode=SkBlendMode::kSrcOver)
Definition SkCanvas.h:1182
void drawPath(const SkPath &path, const SkPaint &paint)
bool nextBool()
Definition SkRandom.h:117
float nextRangeF(float min, float max)
Definition SkRandom.h:64
uint32_t nextRangeU(uint32_t min, uint32_t max)
Definition SkRandom.h:80
T * append()
Definition SkTDArray.h:191
const Paint & paint
double y
double x
int32_t fBottom
larger y-axis bounds
Definition SkRect.h:36
int32_t fTop
smaller y-axis bounds
Definition SkRect.h:34
bool isEmpty() const
Definition SkRect.h:202
int32_t fLeft
smaller x-axis bounds
Definition SkRect.h:33
bool contains(int32_t x, int32_t y) const
Definition SkRect.h:463
int32_t fRight
larger x-axis bounds
Definition SkRect.h:35
bool contains(SkScalar x, SkScalar y) const
Definition extension.cpp:19
void roundOut(SkIRect *dst) const
Definition SkRect.h:1241
constexpr float right() const
Definition SkRect.h:748
constexpr float bottom() const
Definition SkRect.h:755