Flutter Engine
The Flutter Engine
RRectInPathTest.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2015 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
13#include "include/core/SkRect.h"
21#include "src/core/SkPathPriv.h"
22#include "tests/Test.h"
23
24#include <cstdint>
25#include <initializer_list>
26
28 SkPathDirection* dir, unsigned* start) {
31 SkPath recreatedPath;
32 recreatedPath.addRRect(out, *dir, *start);
33 REPORTER_ASSERT(reporter, path == recreatedPath);
34 // Test that rotations/mirrors of the rrect path are still rrect paths and the returned
35 // parameters for the transformed paths are correct.
36 static const SkMatrix kMatrices[] = {
37 SkMatrix::Scale( 1, 1),
38 SkMatrix::Scale(-1, 1),
39 SkMatrix::Scale( 1, -1),
40 SkMatrix::Scale(-1, -1),
41 };
42 for (auto& m : kMatrices) {
43 SkPath xformed;
44 path.transform(m, &xformed);
47 unsigned xs = ~0U;
48 REPORTER_ASSERT(reporter, SkPathPriv::IsRRect(xformed, &xrr, &xd, &xs));
49 recreatedPath.reset();
50 recreatedPath.addRRect(xrr, xd, xs);
51 REPORTER_ASSERT(reporter, recreatedPath == xformed);
52 }
53 return out;
54}
55
57 SkPathDirection dir, unsigned start) {
58 switch (in.getType()) {
62 return in;
63 default:
64 break;
65 }
67 path.addRRect(in, dir, start);
68 SkPathDirection outDir;
69 unsigned outStart;
70 SkRRect rrect = path_contains_rrect(reporter, path, &outDir, &outStart);
71 REPORTER_ASSERT(reporter, outDir == dir && outStart == start);
72 return rrect;
73}
74
76 SkPathDirection dir, unsigned start) {
78 if (in != out) {
79 SkDebugf("%s", "");
80 }
82}
83
85 SkPathDirection dir, unsigned start) {
87 if (in == out) {
88 SkDebugf("%s", "");
89 }
90}
91
93 SkVector v[4], SkPathDirection dir, unsigned start) {
95 rrect.setRectRadii(r, v);
97}
98
100public:
102 path->fPathRef->setIsRRect(dir == SkPathDirection::kCCW, start);
103 }
104};
105
107 SkPathDirection dir, unsigned start) {
108 ForceIsRRect_Private force_rrect(&path, dir, start);
109 SkPathDirection outDir;
110 unsigned outStart;
111 path_contains_rrect(reporter, path, &outDir, &outStart);
112 REPORTER_ASSERT(reporter, outDir == dir && outStart == start);
113}
114
116 // We first get the exact conic weight used by SkPath for a circular arc. This
117 // allows our local, hand-crafted, artisanal round rect paths below to exactly match the
118 // factory made corporate paths produced by SkPath.
119 SkPath exactPath;
120 exactPath.addCircle(0, 0, 10);
123 const SkScalar weight = SkPathPriv::ConicWeightData(exactPath)[0];
124
125 SkPath path;
126 path.moveTo(0, 62.5f);
127 path.lineTo(0, 3.5f);
128 path.conicTo(0, 0, 3.5f, 0, weight);
129 path.lineTo(196.5f, 0);
130 path.conicTo(200, 0, 200, 3.5f, weight);
131 path.lineTo(200, 62.5f);
132 path.conicTo(200, 66, 196.5f, 66, weight);
133 path.lineTo(3.5f, 66);
134 path.conicTo(0, 66, 0, 62.5, weight);
135 path.close();
137
138 path.reset();
139 path.moveTo(0, 81.5f);
140 path.lineTo(0, 3.5f);
141 path.conicTo(0, 0, 3.5f, 0, weight);
142 path.lineTo(149.5, 0);
143 path.conicTo(153, 0, 153, 3.5f, weight);
144 path.lineTo(153, 81.5f);
145 path.conicTo(153, 85, 149.5f, 85, weight);
146 path.lineTo(3.5f, 85);
147 path.conicTo(0, 85, 0, 81.5f, weight);
148 path.close();
150
151 path.reset();
152 path.moveTo(14, 1189);
153 path.lineTo(14, 21);
154 path.conicTo(14, 14, 21, 14, weight);
155 path.lineTo(1363, 14);
156 path.conicTo(1370, 14, 1370, 21, weight);
157 path.lineTo(1370, 1189);
158 path.conicTo(1370, 1196, 1363, 1196, weight);
159 path.lineTo(21, 1196);
160 path.conicTo(14, 1196, 14, 1189, weight);
161 path.close();
163
164 path.reset();
165 path.moveTo(14, 1743);
166 path.lineTo(14, 21);
167 path.conicTo(14, 14, 21, 14, weight);
168 path.lineTo(1363, 14);
169 path.conicTo(1370, 14, 1370, 21, weight);
170 path.lineTo(1370, 1743);
171 path.conicTo(1370, 1750, 1363, 1750, weight);
172 path.lineTo(21, 1750);
173 path.conicTo(14, 1750, 14, 1743, weight);
174 path.close();
176}
177
178static const SkScalar kWidth = 100.0f;
179static const SkScalar kHeight = 100.0f;
180
183 for (int start = 0; start < 8; ++start) {
184 {
185 // crbug.com/458522
186 SkRRect rr;
187 const SkRect bounds = { 3709, 3709, 3709 + 7402, 3709 + 29825 };
188 const SkScalar rad = 12814;
189 const SkVector vec[] = { { rad, rad }, { 0, rad }, { rad, rad }, { 0, rad } };
190 rr.setRectRadii(bounds, vec);
192 }
193
194 {
195 // crbug.com//463920
196 SkRect r = SkRect::MakeLTRB(0, 0, 1009, 33554432.0);
197 SkVector radii[4] = {
198 { 13.0f, 8.0f }, { 170.0f, 2.0 }, { 256.0f, 33554432.0 }, { 110.0f, 5.0f }
199 };
200 SkRRect rr;
201 rr.setRectRadii(r, radii);
203 }
204 }
205 }
206}
207
210 for (int start = 0; start < 8; ++start) {
211 SkRRect rr;
212 const SkRect bounds = { 3709, 3709, 3709 + 7402, 3709 + 29825 };
213 const SkScalar rad = 40;
214 rr.setRectXY(bounds, rad, rad);
216
217 SkRRect other;
219 matrix.setScale(0, 1);
220 rr.transform(matrix, &other);
222 }
223 }
224}
225
228 for (int start = 0; start < 8; ++start) {
229 SkRRect rr, rr2;
230 SkRect r = { 0, 0, 100, 100 };
231
232 rr.setRect(r);
233 rr.inset(-20, -20, &rr2);
235
236 rr.inset(20, 20, &rr2);
238
239 rr.inset(r.width()/2, r.height()/2, &rr2);
241
242 rr.setRectXY(r, 20, 20);
243 rr.inset(19, 19, &rr2);
245 rr.inset(20, 20, &rr2);
247 }
248 }
249}
250
251
253 const SkRect& rect,
255 bool checkRadii) {
257 for (int start = 0; start < 8; ++start) {
258 SkRRect rr;
259 rr.setNinePatch(rect, l, t, r, b);
260 if (checkRadii) {
262 } else {
264 }
265
266 SkRRect rr2; // construct the same RR using the most general set function
267 SkVector radii[4] = { { l, t }, { r, t }, { r, b }, { l, b } };
268 rr2.setRectRadii(rect, radii);
269 if (checkRadii) {
271 } else {
273 }
274 }
275 }
276}
277
278// Test out the basic API entry points
281 for (int start = 0; start < 8; ++start) {
282 //----
284
285 SkRRect rr1;
286 rr1.setRect(rect);
288
289 SkRRect rr1_2; // construct the same RR using the most general set function
290 SkVector rr1_2_radii[4] = { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } };
291 rr1_2.setRectRadii(rect, rr1_2_radii);
293 SkRRect rr1_3; // construct the same RR using the nine patch set function
294 rr1_3.setNinePatch(rect, 0, 0, 0, 0);
296
297 //----
299 SkRRect rr2;
300 rr2.setOval(rect);
302
303 SkRRect rr2_2; // construct the same RR using the most general set function
304 SkVector rr2_2_radii[4] = { { halfPoint.fX, halfPoint.fY },
305 { halfPoint.fX, halfPoint.fY },
306 { halfPoint.fX, halfPoint.fY },
307 { halfPoint.fX, halfPoint.fY } };
308 rr2_2.setRectRadii(rect, rr2_2_radii);
310 SkRRect rr2_3; // construct the same RR using the nine patch set function
311 rr2_3.setNinePatch(rect, halfPoint.fX, halfPoint.fY, halfPoint.fX, halfPoint.fY);
313
314 //----
315 SkPoint p = { 5, 5 };
316 SkRRect rr3;
317 rr3.setRectXY(rect, p.fX, p.fY);
319
320 SkRRect rr3_2; // construct the same RR using the most general set function
321 SkVector rr3_2_radii[4] = { { 5, 5 }, { 5, 5 }, { 5, 5 }, { 5, 5 } };
322 rr3_2.setRectRadii(rect, rr3_2_radii);
324 SkRRect rr3_3; // construct the same RR using the nine patch set function
325 rr3_3.setNinePatch(rect, 5, 5, 5, 5);
327
328 //----
329 test_9patch_rrect(reporter, rect, 10, 9, 8, 7, true);
330
331 {
332 // Test out the rrect from skia:3466
333 SkRect rect2 = SkRect::MakeLTRB(0.358211994f, 0.755430222f, 0.872866154f,
334 0.806214333f);
335
337 rect2,
338 0.926942348f, 0.642850280f, 0.529063463f, 0.587844372f,
339 false);
340 }
341
342 //----
343 SkPoint radii2[4] = { { 0, 0 }, { 0, 0 }, { 50, 50 }, { 20, 50 } };
344
345 SkRRect rr5;
346 rr5.setRectRadii(rect, radii2);
348 }
349 }
350}
351
352// Test out the cases when the RR degenerates to a rect
355 for (int start = 0; start < 8; ++start) {
356 //----
358 SkRRect rr1;
359 rr1.setRectXY(rect, 0, 0);
360
362
363 //----
364 SkPoint radii[4] = { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } };
365
366 SkRRect rr2;
367 rr2.setRectRadii(rect, radii);
368
370
371 //----
372 SkPoint radii2[4] = { { 0, 0 }, { 20, 20 }, { 50, 50 }, { 20, 50 } };
373
374 SkRRect rr3;
375 rr3.setRectRadii(rect, radii2);
377 }
378 }
379}
380
381// Test out the cases when the RR degenerates to an oval
384 for (int start = 0; start < 8; ++start) {
385 //----
387 SkRRect rr1;
389
391 }
392 }
393}
394
395// Test out the non-degenerate RR cases
398 for (int start = 0; start < 8; ++start) {
399 //----
401 SkRRect rr1;
402 rr1.setRectXY(rect, 20, 20);
403
405
406 //----
407 SkPoint radii[4] = { { 0, 0 }, { 20, 20 }, { 50, 50 }, { 20, 50 } };
408
409 SkRRect rr2;
410 rr2.setRectRadii(rect, radii);
411
413 }
414 }
415}
416
419 for (int start = 0; start < 8; ++start) {
421 SkPoint radii[4] = { { 50, 100 }, { 100, 50 }, { 50, 100 }, { 100, 50 } };
422 SkRRect rr1;
423 rr1.setRectRadii(rect, radii);
425 }
426 }
427}
428
429static void set_radii(SkVector radii[4], int index, float rad) {
430 sk_bzero(radii, sizeof(SkVector) * 4);
431 radii[index].set(rad, rad);
432}
433
435 const float min = SkBits2Float(0xcb7f16c8); /* -16717512.000000 */
436 const float max = SkBits2Float(0x4b7f1c1d); /* 16718877.000000 */
437 const float big = SkBits2Float(0x4b7f1bd7); /* 16718807.000000 */
438
439 const float rad = 33436320;
440
441 const SkRect rectx = SkRect::MakeLTRB(min, min, max, big);
442 const SkRect recty = SkRect::MakeLTRB(min, min, big, max);
443
445 for (int start = 0; start < 8; ++start) {
446 SkVector radii[4];
447 for (int i = 0; i < 4; ++i) {
448 set_radii(radii, i, rad);
451 }
452 }
453 }
454}
455
458 for (int start = 0; start < 8; ++start) {
459 // Test out mixed degenerate and non-degenerate geometry with Conics
460 const SkVector radii[4] = { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 100, 100 } };
461 SkRect r = SkRect::MakeWH(100, 100);
462 SkRRect rr;
463 rr.setRectRadii(r, radii);
465 }
466 }
467}
468
469DEF_TEST(RoundRectInPath, reporter) {
481}
482
483DEF_TEST(RRect_fragile, reporter) {
484 SkRect rect = {
485 SkBits2Float(0x1f800000), // 0x003F0000 was the starter value that also fails
486 SkBits2Float(0x1400001C),
487 SkBits2Float(0x3F000004),
488 SkBits2Float(0x3F000004),
489 };
490
491 SkPoint radii[] = {
492 { SkBits2Float(0x00000001), SkBits2Float(0x00000001) },
493 { SkBits2Float(0x00000020), SkBits2Float(0x00000001) },
494 { SkBits2Float(0x00000000), SkBits2Float(0x00000000) },
495 { SkBits2Float(0x3F000004), SkBits2Float(0x3F000004) },
496 };
497
498 SkRRect rr;
499 // please don't assert
500 if ((false)) { // disable until we fix this
501 SkDebugf("%g 0x%08X\n", rect.fLeft, SkFloat2Bits(rect.fLeft));
502 rr.setRectRadii(rect, radii);
503 }
504}
505
sk_bzero(glyphs, sizeof(glyphs))
reporter
Definition: FontMgrTest.cpp:39
static void path_contains_rrect_check(skiatest::Reporter *reporter, const SkRRect &in, SkPathDirection dir, unsigned start)
static void test_round_rect_rects(skiatest::Reporter *reporter)
static const SkScalar kHeight
static void test_round_rect_ovals(skiatest::Reporter *reporter)
static void test_undetected_paths(skiatest::Reporter *reporter)
static void test_9patch_rrect(skiatest::Reporter *reporter, const SkRect &rect, SkScalar l, SkScalar t, SkScalar r, SkScalar b, bool checkRadii)
static void force_path_contains_rrect(skiatest::Reporter *reporter, SkPath &path, SkPathDirection dir, unsigned start)
static void test_tricky_radii(skiatest::Reporter *reporter)
static void path_contains_rrect_nocheck(skiatest::Reporter *reporter, const SkRRect &in, SkPathDirection dir, unsigned start)
static void test_inset(skiatest::Reporter *reporter)
static void test_round_rect_basic(skiatest::Reporter *reporter)
static const SkScalar kWidth
static void test_mix(skiatest::Reporter *reporter)
static void test_round_rect_iffy_parameters(skiatest::Reporter *reporter)
static SkRRect inner_path_contains_rrect(skiatest::Reporter *reporter, const SkRRect &in, SkPathDirection dir, unsigned start)
static void test_empty_crbug_458524(skiatest::Reporter *reporter)
static void test_skbug_3239(skiatest::Reporter *reporter)
static void set_radii(SkVector radii[4], int index, float rad)
DEF_TEST(RoundRectInPath, reporter)
static SkRRect path_contains_rrect(skiatest::Reporter *reporter, const SkPath &path, SkPathDirection *dir, unsigned *start)
static void test_round_rect_general(skiatest::Reporter *reporter)
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
static float SkBits2Float(uint32_t bits)
Definition: SkFloatBits.h:48
static uint32_t SkFloat2Bits(float value)
Definition: SkFloatBits.h:41
SkPathDirection
Definition: SkPathTypes.h:34
#define SkScalarHalf(a)
Definition: SkScalar.h:75
#define REPORTER_ASSERT(r, cond,...)
Definition: Test.h:286
ForceIsRRect_Private(SkPath *path, SkPathDirection dir, unsigned start)
static SkMatrix Scale(SkScalar sx, SkScalar sy)
Definition: SkMatrix.h:75
static bool IsRRect(const SkPath &path, SkRRect *rrect, SkPathDirection *dir, unsigned *start)
Definition: SkPathPriv.h:272
static const uint8_t * VerbData(const SkPath &path)
Definition: SkPathPriv.h:198
static const SkScalar * ConicWeightData(const SkPath &path)
Definition: SkPathPriv.h:213
Definition: SkPath.h:59
SkPath & addCircle(SkScalar x, SkScalar y, SkScalar radius, SkPathDirection dir=SkPathDirection::kCW)
Definition: SkPath.cpp:1213
SkPath & addRRect(const SkRRect &rrect, SkPathDirection dir=SkPathDirection::kCW)
Definition: SkPath.cpp:1000
SkPath & reset()
Definition: SkPath.cpp:370
@ kMove_Verb
Definition: SkPath.h:1466
@ kConic_Verb
Definition: SkPath.h:1469
Type getType() const
Definition: SkRRect.h:76
@ kOval_Type
non-zero width and height filled with radii
Definition: SkRRect.h:69
@ kEmpty_Type
zero width or height
Definition: SkRRect.h:67
@ kRect_Type
non-zero width and height, and zeroed radii
Definition: SkRRect.h:68
void inset(SkScalar dx, SkScalar dy, SkRRect *dst) const
Definition: SkRRect.cpp:562
bool transform(const SkMatrix &matrix, SkRRect *dst) const
Definition: SkRRect.cpp:436
static SkRRect MakeRect(const SkRect &r)
Definition: SkRRect.h:149
void setOval(const SkRect &oval)
Definition: SkRRect.cpp:30
void setRectRadii(const SkRect &rect, const SkVector radii[4])
Definition: SkRRect.cpp:189
void setRectXY(const SkRect &rect, SkScalar xRad, SkScalar yRad)
Definition: SkRRect.cpp:52
void setNinePatch(const SkRect &rect, SkScalar leftRad, SkScalar topRad, SkScalar rightRad, SkScalar bottomRad)
Definition: SkRRect.cpp:115
void setRect(const SkRect &rect)
Definition: SkRRect.h:126
float SkScalar
Definition: extension.cpp:12
static bool b
static float max(float r, float g, float b)
Definition: hsl.cpp:49
static float min(float r, float g, float b)
Definition: hsl.cpp:48
unsigned useCenter Optional< SkMatrix > matrix
Definition: SkRecords.h:258
Optional< SkRect > bounds
Definition: SkRecords.h:189
SkRRect rrect
Definition: SkRecords.h:232
sk_sp< SkBlender > blender SkRect rect
Definition: SkRecords.h:350
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition: switches.h:57
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace Enable an endless trace buffer The default is a ring buffer This is useful when very old events need to viewed For during application launch Memory usage will continue to grow indefinitely however Start app with an specific route defined on the framework flutter assets dir
Definition: switches.h:145
float fX
x-axis value
Definition: SkPoint_impl.h:164
void set(float x, float y)
Definition: SkPoint_impl.h:200
float fY
y-axis value
Definition: SkPoint_impl.h:165
static constexpr SkRect MakeEmpty()
Definition: SkRect.h:595
constexpr float height() const
Definition: SkRect.h:769
constexpr float width() const
Definition: SkRect.h:762
static constexpr SkRect MakeWH(float w, float h)
Definition: SkRect.h:609
static constexpr SkRect MakeLTRB(float l, float t, float r, float b)
Definition: SkRect.h:646