Flutter Engine
The Flutter Engine
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
path_stroke_with_zero_length.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
8#include "gm/gm.h"
15#include "include/core/SkPath.h"
16#include "include/core/SkRect.h"
25
26// GM to test combinations of stroking zero length paths with different caps and other settings
27// Variables:
28// * Antialiasing: On, Off
29// * Caps: Butt, Round, Square
30// * Stroke width: 0, 0.9, 1, 1.1, 15, 25
31// * Path form: M, ML, MLZ, MZ
32// * Path contours: 1 or 2
33// * Path verbs: Line, Quad, Cubic, Conic
34//
35// Each test is drawn to a 50x20 offscreen surface, and expected to produce some number (0 - 2) of
36// visible pieces of cap geometry. These are counted by scanning horizontally for peaks (blobs).
37
38static void draw_path_cell(SkCanvas* canvas,
40 int expectedCaps) {
41 static const SkColor kFailureRed = 0x7F7F0000;
42 static const SkColor kFailureYellow = 0x7F7F7F00;
43 static const SkColor kSuccessGreen = 0x7F007f00;
44
45 int w = surface->width(), h = surface->height();
46
47 // Read the pixels back
50 pmap.alloc(info);
51 if (!surface->readPixels(pmap, 0, 0)) {
52 return;
53 }
54
55 // To account for rasterization differences, we scan the middle two rows [y, y+1] of the image
56 SkASSERT(h % 2 == 0);
57 int y = (h - 1) / 2;
58
59 bool inBlob = false;
60 int numBlobs = 0;
61 for (int x = 0; x < w; ++x) {
62 // We drew white-on-black. We can look for any non-zero value. Just check red.
63 // And we care if either row is non-zero, so just add them to simplify everything.
64 uint32_t v = SkGetPackedR32(*pmap.addr32(x, y)) + SkGetPackedR32(*pmap.addr32(x, y + 1));
65
66 if (!inBlob && v) {
67 ++numBlobs;
68 }
69 inBlob = SkToBool(v);
70 }
71
73
74 if (numBlobs == expectedCaps) {
75 result.setColor(kSuccessGreen); // Green
76 } else if (numBlobs > expectedCaps) {
77 result.setColor(kFailureYellow); // Yellow -- more geometry than expected
78 } else {
79 result.setColor(kFailureRed); // Red -- missing some geometry
80 }
81
82 auto img = surface->makeImageSnapshot();
83 canvas->drawImage(img, 0, 0);
84 canvas->drawRect(SkRect::MakeWH(w, h), result);
85}
86
87static const SkPaint::Cap kCaps[] = {
91};
92
93static const SkScalar kWidths[] = { 0.0f, 0.9f, 1.0f, 1.1f, 15.0f, 25.0f };
94
95// Full set of path structures for single contour case (each primitive with and without a close)
96static const char* kAllVerbs[] = {
97 nullptr,
98 "z ",
99 "l 0 0 ",
100 "l 0 0 z ",
101 "q 0 0 0 0 ",
102 "q 0 0 0 0 z ",
103 "c 0 0 0 0 0 0 ",
104 "c 0 0 0 0 0 0 z ",
105 "a 0 0 0 0 0 0 0 ",
106 "a 0 0 0 0 0 0 0 z "
107};
108
109// Reduced set of path structures for double contour case, to keep total number of cases down
110static const char* kSomeVerbs[] = {
111 nullptr,
112 "z ",
113 "l 0 0 ",
114 "l 0 0 z ",
115 "q 0 0 0 0 ",
116 "q 0 0 0 0 z ",
117};
118
119static const int kCellWidth = 50;
120static const int kCellHeight = 20;
121static const int kCellPad = 2;
122
123static const int kNumRows = std::size(kCaps) * std::size(kWidths);
124static const int kNumColumns = std::size(kAllVerbs);
127
130
132 SkString* errorMsg) {
133 canvas->translate(kCellPad, kCellPad);
134
136 auto surface = canvas->makeSurface(info);
137 if (!surface) {
139 }
140
142 paint.setColor(SK_ColorWHITE);
143 paint.setAntiAlias(aa);
145
146 for (auto cap : kCaps) {
147 for (auto width : kWidths) {
148 paint.setStrokeCap(cap);
149 paint.setStrokeWidth(width);
150 canvas->save();
151
152 for (auto verb : kAllVerbs) {
153 SkString pathStr;
154 pathStr.appendf("M %f %f ", (kCellWidth - 1) * 0.5f, (kCellHeight - 1) * 0.5f);
155 if (verb) {
156 pathStr.append(verb);
157 }
158
159 SkPath path;
161
162 surface->getCanvas()->clear(SK_ColorTRANSPARENT);
163 surface->getCanvas()->drawPath(path, paint);
164
165 // All cases should draw one cap, except for butt capped, and dangling moves
166 // (without a verb or close), which shouldn't draw anything.
167 int expectedCaps = ((SkPaint::kButt_Cap == cap) || !verb) ? 0 : 1;
168
169 draw_path_cell(canvas, surface.get(), expectedCaps);
170 canvas->translate(kCellWidth + kCellPad, 0);
171 }
172 canvas->restore();
173 canvas->translate(0, kCellHeight + kCellPad);
174 }
175 }
176
178}
179
180DEF_SIMPLE_GM_BG_CAN_FAIL(zero_length_paths_aa, canvas, errorMsg,
182 return draw_zero_length_capped_paths(canvas, true, errorMsg);
183}
184
185DEF_SIMPLE_GM_BG_CAN_FAIL(zero_length_paths_bw, canvas, errorMsg,
187 return draw_zero_length_capped_paths(canvas, false, errorMsg);
188}
189
191 SkString* errorMsg) {
192 auto rContext = canvas->recordingContext();
193 auto dContext = GrAsDirectContext(rContext);
194
195 if (!dContext && rContext) {
196 *errorMsg = "Not supported in DDL mode";
198 }
199 canvas->translate(kCellPad, kCellPad);
200
202 auto surface = canvas->makeSurface(info);
203 if (!surface) {
205 }
206
208 paint.setColor(SK_ColorWHITE);
209 paint.setAntiAlias(aa);
211
212 for (auto cap : kCaps) {
213 for (auto width : kWidths) {
214 paint.setStrokeCap(cap);
215 paint.setStrokeWidth(width);
216 canvas->save();
217
218 for (auto firstVerb : kSomeVerbs) {
219 for (auto secondVerb : kSomeVerbs) {
220 int expectedCaps = 0;
221
222 SkString pathStr;
223 pathStr.append("M 9.5 9.5 ");
224 if (firstVerb) {
225 pathStr.append(firstVerb);
226 ++expectedCaps;
227 }
228 pathStr.append("M 40.5 9.5 ");
229 if (secondVerb) {
230 pathStr.append(secondVerb);
231 ++expectedCaps;
232 }
233
234 SkPath path;
236
237 surface->getCanvas()->clear(SK_ColorTRANSPARENT);
238 surface->getCanvas()->drawPath(path, paint);
239
240 if (SkPaint::kButt_Cap == cap) {
241 expectedCaps = 0;
242 }
243
244 draw_path_cell(canvas, surface.get(), expectedCaps);
245 canvas->translate(kCellWidth + kCellPad, 0);
246 }
247 }
248 canvas->restore();
249 canvas->translate(0, kCellHeight + kCellPad);
250 }
251 }
252
254}
255
256DEF_SIMPLE_GM_BG_CAN_FAIL(zero_length_paths_dbl_aa, canvas, errorMsg,
258 return draw_zero_length_capped_paths_dbl_contour(canvas, true, errorMsg);
259}
260
261DEF_SIMPLE_GM_BG_CAN_FAIL(zero_length_paths_dbl_bw, canvas, errorMsg,
263 return draw_zero_length_capped_paths_dbl_contour(canvas, false, errorMsg);
264}
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
static GrDirectContext * GrAsDirectContext(GrContext_Base *base)
#define SkASSERT(cond)
Definition: SkAssert.h:116
#define SkGetPackedR32(packed)
Definition: SkColorPriv.h:93
uint32_t SkColor
Definition: SkColor.h:37
constexpr SkColor SK_ColorTRANSPARENT
Definition: SkColor.h:99
constexpr SkColor SK_ColorBLACK
Definition: SkColor.h:103
constexpr SkColor SK_ColorWHITE
Definition: SkColor.h:122
static constexpr bool SkToBool(const T &x)
Definition: SkTo.h:35
void alloc(const SkImageInfo &)
void drawRect(const SkRect &rect, const SkPaint &paint)
Definition: SkCanvas.cpp:1673
void restore()
Definition: SkCanvas.cpp:461
void translate(SkScalar dx, SkScalar dy)
Definition: SkCanvas.cpp:1278
sk_sp< SkSurface > makeSurface(const SkImageInfo &info, const SkSurfaceProps *props=nullptr)
Definition: SkCanvas.cpp:1195
virtual GrRecordingContext * recordingContext() const
Definition: SkCanvas.cpp:1637
int save()
Definition: SkCanvas.cpp:447
SkImageInfo imageInfo() const
Definition: SkCanvas.cpp:1206
void drawImage(const SkImage *image, SkScalar left, SkScalar top)
Definition: SkCanvas.h:1528
@ 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
static bool FromSVGString(const char str[], SkPath *)
Definition: SkPath.h:59
const uint32_t * addr32() const
Definition: SkPixmap.h:352
void append(const char text[])
Definition: SkString.h:203
const char * c_str() const
Definition: SkString.h:133
void void void appendf(const char format[],...) SK_PRINTF_LIKE(2
Definition: SkString.cpp:550
const Paint & paint
Definition: color_source.cc:38
VkSurfaceKHR surface
Definition: main.cc:49
float SkScalar
Definition: extension.cpp:12
GAsyncResult * result
double y
double x
SK_API sk_sp< SkSurface > Raster(const SkImageInfo &imageInfo, size_t rowBytes, const SkSurfaceProps *surfaceProps)
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
DrawResult
Definition: gm.h:104
static skiagm::DrawResult draw_zero_length_capped_paths_dbl_contour(SkCanvas *canvas, bool aa, SkString *errorMsg)
static skiagm::DrawResult draw_zero_length_capped_paths(SkCanvas *canvas, bool aa, SkString *errorMsg)
static const int kNumRows
static const int kTotalWidth
static const SkPaint::Cap kCaps[]
static const int kNumColumns
static const int kDblContourTotalWidth
static const char * kAllVerbs[]
static const int kTotalHeight
static const int kDblContourNumColums
static const int kCellWidth
static const SkScalar kWidths[]
static const char * kSomeVerbs[]
static const int kCellHeight
DEF_SIMPLE_GM_BG_CAN_FAIL(zero_length_paths_aa, canvas, errorMsg, kTotalWidth, kTotalHeight, SK_ColorBLACK)
static void draw_path_cell(SkCanvas *canvas, SkSurface *surface, int expectedCaps)
static const int kCellPad
SkScalar w
SkScalar h
int32_t width
SkImageInfo makeWH(int newWidth, int newHeight) const
Definition: SkImageInfo.h:444
static SkImageInfo MakeN32Premul(int width, int height)
static constexpr SkRect MakeWH(float w, float h)
Definition: SkRect.h:609