Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
nonclosedpaths.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 */
7
8#include "gm/gm.h"
13#include "include/core/SkSize.h"
16
17namespace skiagm {
18
19// This GM tests a grab-bag of non-closed paths. All these paths look like
20// closed rects, but they don't call path.close(). Depending on the stroke
21// settings these slightly different paths give widely different results.
22class NonClosedPathsGM: public GM {
23public:
25
27 TotallyNonClosed, // The last point doesn't coincide with the first one in the contour.
28 // The path looks not closed at all.
29
30 FakeCloseCorner, // The last point coincides with the first one at a corner.
31 // The path looks closed, but final rendering has 2 ends with cap.
32
33 FakeCloseMiddle, // The last point coincides with the first one in the middle of a line.
34 // The path looks closed, and the final rendering looks closed too.
35
37 };
38
39protected:
40 SkString getName() const override { return SkString("nonclosedpaths"); }
41
42 // 12 * 18 + 3 cases, every case is 100 * 100 pixels.
43 SkISize getISize() override { return SkISize::Make(1220, 1920); }
44
45 // Use rect-like geometry for non-closed path, for right angles make it
46 // easier to show the visual difference of lineCap and lineJoin.
48 SkPathBuilder path;
49 if (FakeCloseMiddle == type) {
50 path.moveTo(30, 50);
51 path.lineTo(30, 30);
52 } else {
53 path.moveTo(30, 30);
54 }
55 path.lineTo(70, 30);
56 path.lineTo(70, 70);
57 path.lineTo(30, 70);
58 path.lineTo(30, 50);
59 if (FakeCloseCorner == type) {
60 path.lineTo(30, 30);
61 }
62 return path.detach();
63 }
64
65 // Set the location for the current test on the canvas
66 static void SetLocation(SkCanvas* canvas, int counter, int lineNum) {
67 SkScalar x = SK_Scalar1 * 100 * (counter % lineNum) + 10 + SK_Scalar1 / 4;
68 SkScalar y = SK_Scalar1 * 100 * (counter / lineNum) + 10 + 3 * SK_Scalar1 / 4;
69 canvas->translate(x, y);
70 }
71
72 void onDraw(SkCanvas* canvas) override {
73 // Stroke widths are:
74 // 0(may use hairline rendering), 10(common case for stroke-style)
75 // 40 and 50(>= geometry width/height, make the contour filled in fact)
76 constexpr int kStrokeWidth[] = {0, 10, 40, 50};
77 int numWidths = std::size(kStrokeWidth);
78
79 constexpr SkPaint::Style kStyle[] = {
81 };
82
83 constexpr SkPaint::Cap kCap[] = {
85 };
86
87 constexpr SkPaint::Join kJoin[] = {
89 };
90
91 constexpr ClosureType kType[] = {
93 };
94
95 int counter = 0;
97 paint.setAntiAlias(true);
98
99 // For stroke style painter and fill-and-stroke style painter
100 for (size_t type = 0; type < kClosureTypeCount; ++type) {
101 for (size_t style = 0; style < std::size(kStyle); ++style) {
102 for (size_t cap = 0; cap < std::size(kCap); ++cap) {
103 for (size_t join = 0; join < std::size(kJoin); ++join) {
104 for (int width = 0; width < numWidths; ++width) {
105 canvas->save();
106 SetLocation(canvas, counter, SkPaint::kJoinCount * numWidths);
107
108 SkPath path = MakePath(kType[type]);
109
110 paint.setStyle(kStyle[style]);
111 paint.setStrokeCap(kCap[cap]);
112 paint.setStrokeJoin(kJoin[join]);
113 paint.setStrokeWidth(SkIntToScalar(kStrokeWidth[width]));
114
115 canvas->drawPath(path, paint);
116 canvas->restore();
117 ++counter;
118 }
119 }
120 }
121 }
122 }
123
124 // For fill style painter
125 paint.setStyle(SkPaint::kFill_Style);
126 for (size_t type = 0; type < kClosureTypeCount; ++type) {
127 canvas->save();
128 SetLocation(canvas, counter, SkPaint::kJoinCount * numWidths);
129
130 SkPath path = MakePath(kType[type]);
131
132 canvas->drawPath(path, paint);
133 canvas->restore();
134 ++counter;
135 }
136 }
137
138private:
139 using INHERITED = GM;
140};
141
142//////////////////////////////////////////////////////////////////////////////
143
144DEF_GM(return new NonClosedPathsGM;)
145
146} // namespace skiagm
#define SK_Scalar1
Definition SkScalar.h:18
#define SkIntToScalar(x)
Definition SkScalar.h:57
void restore()
Definition SkCanvas.cpp:465
void translate(SkScalar dx, SkScalar dy)
int save()
Definition SkCanvas.cpp:451
void drawPath(const SkPath &path, const SkPaint &paint)
@ 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
static constexpr int kJoinCount
Definition SkPaint.h:368
@ 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
SkScalar width()
Definition gm.h:159
SkISize getISize() override
SkString getName() const override
static void SetLocation(SkCanvas *canvas, int counter, int lineNum)
static SkPath MakePath(ClosureType type)
void onDraw(SkCanvas *canvas) override
const Paint & paint
float SkScalar
Definition extension.cpp:12
#define DEF_GM(CODE)
Definition gm.h:40
double y
double x
static constexpr float kStrokeWidth
static constexpr SkISize Make(int32_t w, int32_t h)
Definition SkSize.h:20