Flutter Engine
The Flutter Engine
EmptyPathTest.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2011 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
12#include "include/core/SkPath.h"
17#include "tests/Test.h"
18
19#include <array>
20#include <cstddef>
21
22#define DIMENSION 32
23
25 const SkPaint& paint, bool shouldDraw) {
26 SkBitmap bm;
28 SkASSERT(DIMENSION*4 == bm.rowBytes()); // ensure no padding on each row
30
31 SkCanvas canvas(bm);
33 p.setColor(SK_ColorWHITE);
34
35 canvas.drawPath(path, p);
36
37 size_t count = DIMENSION * DIMENSION;
38 const SkPMColor* ptr = bm.getAddr32(0, 0);
39
40 SkPMColor andValue = ~0U;
41 SkPMColor orValue = 0;
42 for (size_t i = 0; i < count; ++i) {
43 SkPMColor c = ptr[i];
44 andValue &= c;
45 orValue |= c;
46 }
47
48 // success means we drew everywhere or nowhere (depending on shouldDraw)
49 bool success = shouldDraw ? (~0U == andValue) : (0 == orValue);
50
51 if (!success) {
52 const char* str;
53 if (shouldDraw) {
54 str = "Path expected to draw everywhere, but didn't. ";
55 } else {
56 str = "Path expected to draw nowhere, but did. ";
57 }
58 ERRORF(reporter, "%s style[%d] cap[%d] join[%d] antialias[%d]"
59 " filltype[%d] ptcount[%d]", str, paint.getStyle(),
60 paint.getStrokeCap(), paint.getStrokeJoin(),
61 paint.isAntiAlias(), (int)path.getFillType(), path.countPoints());
62// uncomment this if you want to step in to see the failure
63// canvas.drawPath(path, p);
64 }
65}
66
70};
71
72static void iter_paint(skiatest::Reporter* reporter, const SkPath& path, bool shouldDraw,
73 DrawCaps drawCaps) {
74 static const SkPaint::Cap gCaps[] = {
78 };
79 static const SkPaint::Join gJoins[] = {
83 };
84 static const SkPaint::Style gStyles[] = {
88 };
89 for (size_t cap = 0; cap < std::size(gCaps); ++cap) {
90 for (size_t join = 0; join < std::size(gJoins); ++join) {
91 for (size_t style = 0; style < std::size(gStyles); ++style) {
92 if (drawCaps && SkPaint::kButt_Cap != gCaps[cap]
93 && SkPaint::kFill_Style != gStyles[style]) {
94 continue;
95 }
96
98 paint.setStrokeWidth(SkIntToScalar(10));
99
100 paint.setStrokeCap(gCaps[cap]);
101 paint.setStrokeJoin(gJoins[join]);
102 paint.setStyle(gStyles[style]);
103
104 paint.setAntiAlias(false);
105 drawAndTest(reporter, path, paint, shouldDraw);
106 paint.setAntiAlias(true);
107 drawAndTest(reporter, path, paint, shouldDraw);
108 }
109 }
110 }
111}
112
113#define CX (SkIntToScalar(DIMENSION) / 2)
114#define CY (SkIntToScalar(DIMENSION) / 2)
115
116static void make_empty(SkPath*) {}
117static void make_M(SkPath* path) { path->moveTo(CX, CY); }
118static void make_MM(SkPath* path) { path->moveTo(CX, CY).moveTo(CX, CY); }
119static void make_MZM(SkPath* path) { path->moveTo(CX, CY).close().moveTo(CX, CY); }
120static void make_L(SkPath* path) { path->moveTo(CX, CY).lineTo(CX, CY); }
121static void make_Q(SkPath* path) { path->moveTo(CX, CY).quadTo(CX, CY, CX, CY); }
122static void make_C(SkPath* path) { path->moveTo(CX, CY).cubicTo(CX, CY, CX, CY, CX, CY); }
123
124/* Two invariants are tested: How does an empty/degenerate path draw?
125 * - if the path is drawn inverse, it should draw everywhere
126 * - if the path is drawn non-inverse, it should draw nowhere
127 *
128 * Things to iterate on:
129 * - path (empty, degenerate line/quad/cubic w/ and w/o close
130 * - paint style
131 * - path filltype
132 * - path stroke variants (e.g. caps, joins, width)
133 */
135 static void (*gMakeProc[])(SkPath*) = {
137 };
138 static SkPathFillType gFills[] = {
143 };
144 for (int doClose = 0; doClose < 2; ++doClose) {
145 for (size_t i = 0; i < std::size(gMakeProc); ++i) {
146 SkPath path;
147 gMakeProc[i](&path);
148 if (doClose) {
149 path.close();
150 }
151 /* zero length segments and close following moves draw round and square caps */
152 bool allowCaps = make_L == gMakeProc[i] || make_Q == gMakeProc[i]
153 || make_C == gMakeProc[i] || make_MZM == gMakeProc[i];
154 allowCaps |= SkToBool(doClose);
155 for (size_t fill = 0; fill < std::size(gFills); ++fill) {
156 path.setFillType(gFills[fill]);
157 bool shouldDraw = path.isInverseFillType();
158 iter_paint(reporter, path, shouldDraw, allowCaps ? kDrawCaps : kDontDrawCaps);
159 }
160 }
161 }
162}
163
164DEF_TEST(EmptyPath, reporter) {
166}
#define CX
static void make_C(SkPath *path)
static void make_empty(SkPath *)
DEF_TEST(EmptyPath, reporter)
static void make_Q(SkPath *path)
static void make_L(SkPath *path)
static void iter_paint(skiatest::Reporter *reporter, const SkPath &path, bool shouldDraw, DrawCaps drawCaps)
static void test_emptydrawing(skiatest::Reporter *reporter)
#define DIMENSION
#define CY
DrawCaps
@ kDrawCaps
@ kDontDrawCaps
static void make_M(SkPath *path)
static void make_MM(SkPath *path)
static void make_MZM(SkPath *path)
static void drawAndTest(skiatest::Reporter *reporter, const SkPath &path, const SkPaint &paint, bool shouldDraw)
reporter
Definition: FontMgrTest.cpp:39
int count
Definition: FontMgrTest.cpp:50
#define SkASSERT(cond)
Definition: SkAssert.h:116
constexpr SkColor SK_ColorTRANSPARENT
Definition: SkColor.h:99
uint32_t SkPMColor
Definition: SkColor.h:205
constexpr SkColor SK_ColorWHITE
Definition: SkColor.h:122
SkPathFillType
Definition: SkPathTypes.h:11
#define SkIntToScalar(x)
Definition: SkScalar.h:57
static constexpr bool SkToBool(const T &x)
Definition: SkTo.h:35
#define ERRORF(r,...)
Definition: Test.h:293
size_t rowBytes() const
Definition: SkBitmap.h:238
void allocN32Pixels(int width, int height, bool isOpaque=false)
Definition: SkBitmap.cpp:232
uint32_t * getAddr32(int x, int y) const
Definition: SkBitmap.h:1260
void eraseColor(SkColor4f) const
Definition: SkBitmap.cpp:442
void drawPath(const SkPath &path, const SkPaint &paint)
Definition: SkCanvas.cpp:1747
@ kRound_Cap
adds circle
Definition: SkPaint.h:335
@ kButt_Cap
no stroke extension
Definition: SkPaint.h:334
@ kSquare_Cap
adds square
Definition: SkPaint.h:336
@ kStroke_Style
set to stroke geometry
Definition: SkPaint.h:194
@ kFill_Style
set to fill geometry
Definition: SkPaint.h:193
@ kStrokeAndFill_Style
sets to stroke and fill geometry
Definition: SkPaint.h:195
@ kRound_Join
adds circle
Definition: SkPaint.h:360
@ kMiter_Join
extends to miter limit
Definition: SkPaint.h:359
@ kBevel_Join
connects outside edges
Definition: SkPaint.h:361
Definition: SkPath.h:59
const Paint & paint
Definition: color_source.cc:38
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
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
static SkString join(const CommandLineFlags::StringArray &)
Definition: skpbench.cpp:741
static constexpr SkFontStyle gStyles[]
Definition: typeface.cpp:89