Flutter Engine
The Flutter Engine
Functions
DrawPathTest.cpp File Reference
#include "include/core/SkBitmap.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPath.h"
#include "include/core/SkPathEffect.h"
#include "include/core/SkPathTypes.h"
#include "include/core/SkPathUtils.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRRect.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkScalar.h"
#include "include/core/SkStrokeRec.h"
#include "include/core/SkSurface.h"
#include "include/core/SkTypes.h"
#include "include/effects/SkDashPathEffect.h"
#include "tests/Test.h"
#include <cstdint>

Go to the source code of this file.

Functions

static void test_big_aa_rect (skiatest::Reporter *reporter)
 
static void moveToH (SkPath *path, const uint32_t raw[])
 
static void cubicToH (SkPath *path, const uint32_t raw[])
 
static void test_crbug131181 ()
 
static void test_crbug_140803 ()
 
static void test_crbug_1239558 (skiatest::Reporter *reporter)
 
static void test_inversepathwithclip ()
 
static void test_bug533 ()
 
static void test_crbug_140642 ()
 
static void test_crbug_124652 ()
 
static void test_bigcubic ()
 
static void test_halfway ()
 
static void test_giantaa ()
 
static void test_infinite_dash (skiatest::Reporter *reporter)
 
static void test_crbug_165432 (skiatest::Reporter *reporter)
 
static void test_crbug_472147_simple (skiatest::Reporter *reporter)
 
static void test_crbug_472147_actual (skiatest::Reporter *reporter)
 
 DEF_TEST (DrawPath, reporter)
 

Function Documentation

◆ cubicToH()

static void cubicToH ( SkPath path,
const uint32_t  raw[] 
)
static

Definition at line 74 of file DrawPathTest.cpp.

74 {
75 const float* fptr = (const float*)raw;
76 path->cubicTo(fptr[0], fptr[1], fptr[2], fptr[3], fptr[4], fptr[5]);
77}
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_TEST()

DEF_TEST ( DrawPath  ,
reporter   
)

Definition at line 409 of file DrawPathTest.cpp.

409 {
410 test_giantaa();
411 test_bug533();
417 // why?
418 if ((false)) test_crbug131181();
425 test_halfway();
426}
static void test_crbug_165432(skiatest::Reporter *reporter)
static void test_halfway()
static void test_bigcubic()
static void test_crbug_1239558(skiatest::Reporter *reporter)
static void test_giantaa()
static void test_crbug_472147_actual(skiatest::Reporter *reporter)
static void test_crbug_140803()
static void test_crbug_472147_simple(skiatest::Reporter *reporter)
static void test_crbug_140642()
static void test_crbug131181()
static void test_bug533()
static void test_crbug_124652()
static void test_big_aa_rect(skiatest::Reporter *reporter)
static void test_infinite_dash(skiatest::Reporter *reporter)
static void test_inversepathwithclip()
reporter
Definition: FontMgrTest.cpp:39

◆ moveToH()

static void moveToH ( SkPath path,
const uint32_t  raw[] 
)
static

Definition at line 69 of file DrawPathTest.cpp.

69 {
70 const float* fptr = (const float*)raw;
71 path->moveTo(fptr[0], fptr[1]);
72}

◆ test_big_aa_rect()

static void test_big_aa_rect ( skiatest::Reporter reporter)
static

Definition at line 32 of file DrawPathTest.cpp.

32 {
34 SkPMColor pixel[1];
35 output.installPixels(SkImageInfo::MakeN32Premul(1, 1), pixel, 4);
36
37 auto surf = SkSurfaces::Raster(SkImageInfo::MakeN32Premul(300, 33300));
38 SkCanvas* canvas = surf->getCanvas();
39
40 SkRect r = { 0, 33000, 300, 33300 };
41 int x = SkScalarRoundToInt(r.left());
42 int y = SkScalarRoundToInt(r.top());
43
44 // check that the pixel in question starts as transparent (by the surface)
45 if (surf->readPixels(output, x, y)) {
46 REPORTER_ASSERT(reporter, 0 == pixel[0]);
47 } else {
48 REPORTER_ASSERT(reporter, false, "readPixels failed");
49 }
50
52 paint.setAntiAlias(true);
53 paint.setColor(SK_ColorWHITE);
54
55 canvas->drawRect(r, paint);
56
57 // Now check that it is BLACK
58 if (surf->readPixels(output, x, y)) {
59 // don't know what swizzling PMColor did, but white should always
60 // appear the same.
61 REPORTER_ASSERT(reporter, 0xFFFFFFFF == pixel[0]);
62 } else {
63 REPORTER_ASSERT(reporter, false, "readPixels failed");
64 }
65}
uint32_t SkPMColor
Definition: SkColor.h:205
constexpr SkColor SK_ColorWHITE
Definition: SkColor.h:122
#define SkScalarRoundToInt(x)
Definition: SkScalar.h:37
#define REPORTER_ASSERT(r, cond,...)
Definition: Test.h:286
void drawRect(const SkRect &rect, const SkPaint &paint)
Definition: SkCanvas.cpp:1673
const Paint & paint
Definition: color_source.cc:38
double y
double x
SK_API sk_sp< SkSurface > Raster(const SkImageInfo &imageInfo, size_t rowBytes, const SkSurfaceProps *surfaceProps)
static SkImageInfo MakeN32Premul(int width, int height)
constexpr float left() const
Definition: SkRect.h:734
constexpr float top() const
Definition: SkRect.h:741

◆ test_bigcubic()

static void test_bigcubic ( )
static

Definition at line 268 of file DrawPathTest.cpp.

268 {
269 SkPath path;
270 path.moveTo(64, 3);
271 path.cubicTo(-329936, -100000000, -329936, 100000000, 1153, 330003);
272
274 paint.setAntiAlias(true);
275
277 surface->getCanvas()->drawPath(path, paint);
278}
Definition: SkPath.h:59
VkSurfaceKHR surface
Definition: main.cc:49

◆ test_bug533()

static void test_bug533 ( )
static

Definition at line 221 of file DrawPathTest.cpp.

221 {
222 /*
223 http://code.google.com/p/skia/issues/detail?id=533
224 This particular test/bug only applies to the float case, where the
225 coordinates are very large.
226 */
227 SkPath path;
228 path.moveTo(64, 3);
229 path.quadTo(-329936, -100000000, 1153, 330003);
230
232 paint.setAntiAlias(true);
233
235 surface->getCanvas()->drawPath(path, paint);
236}

◆ test_crbug131181()

static void test_crbug131181 ( )
static

Definition at line 90 of file DrawPathTest.cpp.

90 {
91 /*
92 fX = 18.8943768,
93 fY = 129.121277
94 }, {
95 fX = 18.8937435,
96 fY = 129.121689
97 }, {
98 fX = 18.8950119,
99 fY = 129.120422
100 }, {
101 fX = 18.5030727,
102 fY = 129.13121
103 */
104 uint32_t data[] = {
105 0x419727af, 0x43011f0c, 0x41972663, 0x43011f27,
106 0x419728fc, 0x43011ed4, 0x4194064b, 0x43012197
107 };
108
109 SkPath path;
110 moveToH(&path, &data[0]);
111 cubicToH(&path, &data[2]);
112
114
116 paint.setAntiAlias(true);
117 surface->getCanvas()->drawPath(path, paint);
118}
static void moveToH(SkPath *path, const uint32_t raw[])
static void cubicToH(SkPath *path, const uint32_t raw[])
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63

◆ test_crbug_1239558()

static void test_crbug_1239558 ( skiatest::Reporter reporter)
static

Definition at line 133 of file DrawPathTest.cpp.

133 {
134 SkBitmap bm;
135 bm.allocN32Pixels(256, 256);
136
137 SkCanvas canvas(bm);
138 canvas.clear(SK_ColorWHITE);
139
140 // This creates a single cubic where the control points form an extremely skinny, vertical
141 // triangle contained within the x=0 column of pixels. Since it is convex (ignoring the leading
142 // moveTo's) it uses the convex aaa optimized edge walking algorithm after clipping the path to
143 // the device bounds. However, due to fixed-point math while walking these edges, the edge
144 // walking evaluates to coords that are very slightly less than 0 (i.e. 0.0012). Both the left
145 // and right edges would be out of bounds, but the edge walking is optimized to only clamp the
146 // left edge to the left bounds, and the right edge to the right bounds. After this clamping,
147 // the left and right edges are no longer sorted. This then led to incorrect behavior in various
148 // forms (described below).
149 SkPath path;
150 path.setFillType(SkPathFillType::kWinding);
151 path.moveTo(7.00649e-45f, 2.f);
152 path.moveTo(0.0160219f, 7.45063e-09f);
153 path.moveTo(192.263f, 8.40779e-44f);
154 path.moveTo(7.34684e-40f, 194.25f);
155 path.moveTo(2.3449e-38f, 6.01858e-36f);
156 path.moveTo(7.34684e-40f, 194.25f);
157 path.cubicTo(5.07266e-39f, 56.0488f,
158 0.0119172f, 0.f,
159 7.34684e-40f, 194.25f);
160
162 paint.setColor(SK_ColorRED);
163 paint.setAntiAlias(true);
164 // On debug builds, the inverted left/right edges led to a negative coverage that triggered an
165 // assert while converting to a uint8 alpha value. On release builds with UBSAN, it would
166 // detect a negative left shift when computing the pixel address and crash. On regular release
167 // builds it would write a saturate coverage value to pixels that wrapped around to the far edge
168 canvas.drawPath(path, paint);
169
170 // UBSAN and debug builds would fail inside the drawPath() call above, but detect the incorrect
171 // memory access on release builds so that the test would fail. Given the path, it should only
172 // touch pixels with x=0 but the incorrect addressing would wrap to the right edge.
173 for (int y = 0; y < 256; ++y) {
174 if (bm.getColor(255, y) != SK_ColorWHITE) {
175 REPORTER_ASSERT(reporter, false, "drawPath modified incorrect pixels");
176 break;
177 }
178 }
179}
constexpr SkColor SK_ColorRED
Definition: SkColor.h:126
SkColor getColor(int x, int y) const
Definition: SkBitmap.h:874
void allocN32Pixels(int width, int height, bool isOpaque=false)
Definition: SkBitmap.cpp:232

◆ test_crbug_124652()

static void test_crbug_124652 ( )
static

Definition at line 258 of file DrawPathTest.cpp.

258 {
259 /*
260 http://code.google.com/p/chromium/issues/detail?id=124652
261 This particular test/bug only applies to the float case, where
262 large values can "swamp" small ones.
263 */
264 SkScalar intervals[2] = {837099584, 33450};
265 auto dontAssert = SkDashPathEffect::Make(intervals, 2, -10);
266}
static sk_sp< SkPathEffect > Make(const SkScalar intervals[], int count, SkScalar phase)
float SkScalar
Definition: extension.cpp:12

◆ test_crbug_140642()

static void test_crbug_140642 ( )
static

Definition at line 238 of file DrawPathTest.cpp.

238 {
239 /*
240 * We used to see this construct, and due to rounding as we accumulated
241 * our length, the loop where we apply the phase would run off the end of
242 * the array, since it relied on just -= each interval value, which did not
243 * behave as "expected". Now the code explicitly checks for walking off the
244 * end of that array.
245
246 * A different (better) fix might be to rewrite dashing to do all of its
247 * length/phase/measure math using double, but this may need to be
248 * coordinated with SkPathMeasure, to be consistent between the two.
249
250 <path stroke="mintcream" stroke-dasharray="27734 35660 2157846850 247"
251 stroke-dashoffset="-248.135982067">
252 */
253
254 const SkScalar vals[] = { 27734, 35660, 2157846850.0f, 247 };
255 auto dontAssert = SkDashPathEffect::Make(vals, 4, -248.135982067f);
256}

◆ test_crbug_140803()

static void test_crbug_140803 ( )
static

Definition at line 123 of file DrawPathTest.cpp.

123 {
124 SkBitmap bm;
125 bm.allocN32Pixels(2700, 30*1024);
126 SkCanvas canvas(bm);
127
129 paint.setAntiAlias(true);
130 canvas.drawPath(SkPath().moveTo(2762, 20).quadTo(11, 21702, 10, 21706), paint);
131}

◆ test_crbug_165432()

static void test_crbug_165432 ( skiatest::Reporter reporter)
static

Definition at line 358 of file DrawPathTest.cpp.

358 {
359 SkPath path;
360 path.moveTo(0, 0);
361 path.lineTo(10000000, 0);
362
363 SkScalar intervals[] = { 0.5f, 0.5f };
364 sk_sp<SkPathEffect> dash(SkDashPathEffect::Make(intervals, 2, 0));
365
368 paint.setPathEffect(dash);
369
370 SkPath filteredPath;
371 SkStrokeRec rec(paint);
372 REPORTER_ASSERT(reporter, !dash->filterPath(&filteredPath, path, &rec, nullptr));
373 REPORTER_ASSERT(reporter, filteredPath.isEmpty());
374}
@ kStroke_Style
set to stroke geometry
Definition: SkPaint.h:194
bool isEmpty() const
Definition: SkPath.cpp:416

◆ test_crbug_472147_actual()

static void test_crbug_472147_actual ( skiatest::Reporter reporter)
static

Definition at line 393 of file DrawPathTest.cpp.

393 {
395 SkCanvas* canvas = surface->getCanvas();
396 SkPaint p;
397 SkRect r = SkRect::MakeLTRB(-246.0f, 33.0f, 848.0f, 33554464.0f);
398 SkVector radii[4] = {
399 { 13.0f, 8.0f }, { 170.0f, 2.0 }, { 256.0f, 33554430.0f }, { 120.0f, 5.0f }
400 };
401 SkRRect rr;
402 rr.setRectRadii(r, radii);
403 canvas->clipRRect(rr);
404
405 SkRect r2 = SkRect::MakeLTRB(0, 33, 1102, 33554464);
406 canvas->drawRect(r2, p);
407}
void clipRRect(const SkRRect &rrect, SkClipOp op, bool doAntiAlias)
Definition: SkCanvas.cpp:1439
void setRectRadii(const SkRect &rect, const SkVector radii[4])
Definition: SkRRect.cpp:189
static constexpr SkRect MakeLTRB(float l, float t, float r, float b)
Definition: SkRect.h:646

◆ test_crbug_472147_simple()

static void test_crbug_472147_simple ( skiatest::Reporter reporter)
static

Definition at line 378 of file DrawPathTest.cpp.

378 {
380 SkCanvas* canvas = surface->getCanvas();
381 SkPaint p;
382 SkRect r = SkRect::MakeLTRB(-246.0f, 33.0f, 848.0f, 33554464.0f);
383 SkVector radii[4] = {
384 { 13.0f, 8.0f }, { 170.0f, 2.0 }, { 256.0f, 33554430.0f }, { 120.0f, 5.0f }
385 };
386 SkRRect rr;
387 rr.setRectRadii(r, radii);
388 canvas->drawRRect(rr, p);
389}
void drawRRect(const SkRRect &rrect, const SkPaint &paint)
Definition: SkCanvas.cpp:1705

◆ test_giantaa()

static void test_giantaa ( )
static

Definition at line 322 of file DrawPathTest.cpp.

322 {
323 const int W = 400;
324 const int H = 400;
326
328 paint.setAntiAlias(true);
329 SkPath path;
330 path.addOval(SkRect::MakeXYWH(-10, -10, 20 + W, 20 + H));
331 surface->getCanvas()->drawPath(path, paint);
332}
#define W
Definition: aaa.cpp:17
Definition: SkMD5.cpp:130
static constexpr SkRect MakeXYWH(float x, float y, float w, float h)
Definition: SkRect.h:659

◆ test_halfway()

static void test_halfway ( )
static

Definition at line 281 of file DrawPathTest.cpp.

281 {
283 SkPath path;
284 path.moveTo(16365.5f, 1394);
285 path.lineTo(16365.5f, 1387.5f);
286 path.quadTo(16365.5f, 1385.43f, 16367, 1383.96f);
287 path.quadTo(16368.4f, 1382.5f, 16370.5f, 1382.5f);
288 path.lineTo(16465.5f, 1382.5f);
289 path.quadTo(16467.6f, 1382.5f, 16469, 1383.96f);
290 path.quadTo(16470.5f, 1385.43f, 16470.5f, 1387.5f);
291 path.lineTo(16470.5f, 1394);
292 path.quadTo(16470.5f, 1396.07f, 16469, 1397.54f);
293 path.quadTo(16467.6f, 1399, 16465.5f, 1399);
294 path.lineTo(16370.5f, 1399);
295 path.quadTo(16368.4f, 1399, 16367, 1397.54f);
296 path.quadTo(16365.5f, 1396.07f, 16365.5f, 1394);
297 path.close();
298 SkPath p2;
299 SkMatrix m;
300 m.reset();
301 m.postTranslate(0.001f, 0.001f);
302 path.transform(m, &p2);
303
305 SkCanvas* canvas = surface->getCanvas();
306 canvas->translate(-16366, -1383);
307 canvas->drawPath(p2, paint);
308
309 m.reset();
310 m.postTranslate(-0.001f, -0.001f);
311 path.transform(m, &p2);
312 canvas->drawPath(p2, paint);
313
314 m.reset();
315 path.transform(m, &p2);
316 canvas->drawPath(p2, paint);
317}
void translate(SkScalar dx, SkScalar dy)
Definition: SkCanvas.cpp:1278
void drawPath(const SkPath &path, const SkPaint &paint)
Definition: SkCanvas.cpp:1747

◆ test_infinite_dash()

static void test_infinite_dash ( skiatest::Reporter reporter)
static

Definition at line 338 of file DrawPathTest.cpp.

338 {
339 SkPath path;
340 path.moveTo(0, 0);
341 path.lineTo(5000000, 0);
342
343 SkScalar intervals[] = { 0.2f, 0.2f };
344 sk_sp<SkPathEffect> dash(SkDashPathEffect::Make(intervals, 2, 0));
345
346 SkPath filteredPath;
349 paint.setPathEffect(dash);
350
352 // If we reach this, we passed.
354}
SK_API bool FillPathWithPaint(const SkPath &src, const SkPaint &paint, SkPath *dst, const SkRect *cullRect, SkScalar resScale=1)
Definition: SkPathUtils.cpp:23

◆ test_inversepathwithclip()

static void test_inversepathwithclip ( )
static

Definition at line 186 of file DrawPathTest.cpp.

186 {
187 SkPath path;
188
189 path.moveTo(0, 20);
190 path.quadTo(10, 10, 20, 20);
191 path.toggleInverseFillType();
192
194
196 SkCanvas* canvas = surface->getCanvas();
197 canvas->save();
198 canvas->clipRect(SkRect::MakeWH(19, 11));
199
200 paint.setAntiAlias(false);
201 canvas->drawPath(path, paint);
202 paint.setAntiAlias(true);
203 canvas->drawPath(path, paint);
204
205 canvas->restore();
206
207 // Now do the test again, with the path flipped, so we only draw in the
208 // top half of our bounds, and have the clip intersect our bounds at the
209 // bottom.
210 path.reset(); // preserves our filltype
211 path.moveTo(0, 10);
212 path.quadTo(10, 20, 20, 10);
213 canvas->clipRect(SkRect::MakeXYWH(0, 19, 19, 11));
214
215 paint.setAntiAlias(false);
216 canvas->drawPath(path, paint);
217 paint.setAntiAlias(true);
218 canvas->drawPath(path, paint);
219}
void clipRect(const SkRect &rect, SkClipOp op, bool doAntiAlias)
Definition: SkCanvas.cpp:1361
void restore()
Definition: SkCanvas.cpp:461
int save()
Definition: SkCanvas.cpp:447
static constexpr SkRect MakeWH(float w, float h)
Definition: SkRect.h:609