Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
strokedlines.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2016 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"
16#include "include/core/SkPath.h"
20#include "include/core/SkRect.h"
23#include "include/core/SkSize.h"
31#include "tools/ToolUtils.h"
32
33#include <initializer_list>
34
35using namespace skia_private;
36
37constexpr int kNumColumns = 6;
38constexpr int kNumRows = 8;
39constexpr int kRadius = 40; // radius of the snowflake
40constexpr int kPad = 5; // padding on both sides of the snowflake
41constexpr int kNumSpokes = 6;
42constexpr SkScalar kStrokeWidth = 5.0f;
43
44static void draw_line(SkCanvas* canvas, const SkPoint& p0, const SkPoint& p1,
45 const SkPaint& paint, bool useDrawPath) {
46 if (useDrawPath) {
47 canvas->drawPath(SkPath::Line(p0, p1), paint);
48 } else {
49 canvas->drawLine(p0, p1, paint);
50 }
51}
52
53static void draw_fins(SkCanvas* canvas, const SkPoint& offset, float angle, const SkPaint& paint,
54 bool useDrawPath) {
55 SkScalar cos, sin;
56
57 // first fin
58 sin = SkScalarSin(angle + (SK_ScalarPI/4));
59 cos = SkScalarCos(angle + (SK_ScalarPI/4));
60 sin *= kRadius / 2.0f;
61 cos *= kRadius / 2.0f;
62
63 draw_line(canvas, offset, offset + SkPoint{cos, sin}, paint, useDrawPath);
64
65 // second fin
66 sin = SkScalarSin(angle - (SK_ScalarPI/4));
67 cos = SkScalarCos(angle - (SK_ScalarPI/4));
68 sin *= kRadius / 2.0f;
69 cos *= kRadius / 2.0f;
70
71 draw_line(canvas, offset, offset + SkPoint{cos, sin}, paint, useDrawPath);
72}
73
74// draw a snowflake centered at the origin
75static void draw_snowflake(SkCanvas* canvas, const SkPaint& paint, bool useDrawPath) {
76
78
79 SkScalar sin, cos, angle = 0.0f;
80 for (int i = 0; i < kNumSpokes/2; ++i, angle += SK_ScalarPI/(kNumSpokes/2)) {
81 sin = SkScalarSin(angle);
82 cos = SkScalarCos(angle);
83 sin *= kRadius;
84 cos *= kRadius;
85
86 // main spoke
87 draw_line(canvas, {-cos, -sin}, {cos, sin}, paint, useDrawPath);
88
89 // fins on positive side
90 const SkPoint posOffset = SkPoint::Make(0.5f * cos, 0.5f * sin);
91 draw_fins(canvas, posOffset, angle, paint, useDrawPath);
92
93 // fins on negative side
94 const SkPoint negOffset = SkPoint::Make(-0.5f * cos, -0.5f * sin);
95 draw_fins(canvas, negOffset, angle+SK_ScalarPI, paint, useDrawPath);
96 }
97}
98
99static void draw_row(SkCanvas* canvas, const SkPaint& paint, const SkMatrix& localMatrix,
100 bool useDrawPath) {
101 canvas->translate(kRadius+kPad, 0.0f);
102
104 for (auto isAA : { true, false }) {
105 SkPaint tmp(paint);
108 tmp.setStrokeCap(cap);
109 tmp.setAntiAlias(isAA);
110
111 int saveCount = canvas->save();
112 canvas->concat(localMatrix);
113 draw_snowflake(canvas, tmp, useDrawPath);
114 canvas->restoreToCount(saveCount);
115
116 canvas->translate(2*(kRadius+kPad), 0.0f);
117 }
118 }
119}
120
121namespace skiagm {
122
123// This GM exercises the special case of a stroked lines.
124// Various shaders are applied to ensure the coordinate spaces work out right.
125class StrokedLinesGM : public GM {
126public:
127 StrokedLinesGM(bool useDrawPath) : fUseDrawPath(useDrawPath) {
128 this->setBGColor(ToolUtils::color_to_565(0xFF1A65D7));
129 }
130
131protected:
132 SkString getName() const override {
133 // To preserve history, useDrawPath==true has no suffix.
134 SkString name{"strokedlines"};
135 if (!fUseDrawPath) {
136 name.append("_drawPoints");
137 }
138 return name;
139 }
140
141 SkISize getISize() override {
142 return SkISize::Make(kNumColumns * (2*kRadius+2*kPad), kNumRows * (2*kRadius+2*kPad));
143 }
144
145 void onOnceBeforeDraw() override {
146 // paints
147 {
148 // basic white
149 SkPaint p;
150 p.setColor(SK_ColorWHITE);
151 fPaints.push_back(p);
152 }
153 {
154 // gradient
155 SkColor colors[] = { SK_ColorRED, SK_ColorGREEN };
156 SkPoint pts[] = { {-kRadius-kPad, -kRadius-kPad }, { kRadius+kPad, kRadius+kPad } };
157
158 SkPaint p;
159 p.setShader(SkGradientShader::MakeLinear(pts, colors, nullptr, 2, SkTileMode::kClamp));
160
161 fPaints.push_back(p);
162 }
163 {
164 // dashing
165 SkScalar intervals[] = { kStrokeWidth, kStrokeWidth };
166 int intervalCount = (int) std::size(intervals);
167 SkPaint p;
168 p.setColor(SK_ColorWHITE);
169 p.setPathEffect(SkDashPathEffect::Make(intervals, intervalCount, kStrokeWidth));
170
171 fPaints.push_back(p);
172 }
173 {
174 // Bitmap shader
175 SkBitmap bm;
176 bm.allocN32Pixels(2, 2);
177 *bm.getAddr32(0, 0) = *bm.getAddr32(1, 1) = 0xFFFFFFFF;
178 *bm.getAddr32(1, 0) = *bm.getAddr32(0, 1) = 0x0;
179
180 SkMatrix m;
181 m.setRotate(12.0f);
182 m.preScale(3.0f, 3.0f);
183
184 SkPaint p;
186 SkSamplingOptions(), m));
187 fPaints.push_back(p);
188 }
189 {
190 // blur
191 SkPaint p;
192 p.setColor(SK_ColorWHITE);
193 p.setMaskFilter(SkMaskFilter::MakeBlur(kOuter_SkBlurStyle, 3.0f));
194 fPaints.push_back(p);
195 }
196
197 // matrices
198 {
199 // rotation
200 SkMatrix m;
201 m.setRotate(12.0f);
202
203 fMatrices.push_back(m);
204 }
205 {
206 // skew
207 SkMatrix m;
208 m.setSkew(0.3f, 0.5f);
209
210 fMatrices.push_back(m);
211 }
212 {
213 // perspective
214 SkMatrix m;
215 m.reset();
216 m.setPerspX(-SK_Scalar1 / 300);
217 m.setPerspY(SK_Scalar1 / 300);
218
219 fMatrices.push_back(m);
220 }
221
222 SkASSERT(kNumRows == fPaints.size() + fMatrices.size());
223 }
224
225 void onDraw(SkCanvas* canvas) override {
226 canvas->translate(0, kRadius+kPad);
227
228 for (int i = 0; i < fPaints.size(); ++i) {
229 int saveCount = canvas->save();
230 draw_row(canvas, fPaints[i], SkMatrix::I(), fUseDrawPath);
231 canvas->restoreToCount(saveCount);
232
233 canvas->translate(0, 2*(kRadius+kPad));
234 }
235
236 for (int i = 0; i < fMatrices.size(); ++i) {
237 int saveCount = canvas->save();
238 draw_row(canvas, fPaints[0], fMatrices[i], fUseDrawPath);
239 canvas->restoreToCount(saveCount);
240
241 canvas->translate(0, 2*(kRadius+kPad));
242 }
243 }
244
245private:
246 TArray<SkPaint> fPaints;
247 TArray<SkMatrix> fMatrices;
248
249 const bool fUseDrawPath;
250
251 using INHERITED = GM;
252};
253
254//////////////////////////////////////////////////////////////////////////////
255
256DEF_GM(return new StrokedLinesGM(true);)
257DEF_GM(return new StrokedLinesGM(false);)
258
259//////////////////////////////////////////////////////////////////////////////
260
261static constexpr float kStrokeWidth = 20.f;
262
263static void draw_path(SkCanvas* canvas, const SkPoint& p0, const SkPoint& p1, SkPaint::Cap cap) {
264 // Add a gradient *not* aligned with the line's points to show local coords are tracked properly
266 constexpr SkPoint kPts[] {{kRect.fLeft, kRect.fTop}, {kRect.fRight, kRect.fBottom}};
267 constexpr SkColor kColors[] {SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE};
268 constexpr SkScalar kStops[] {0.f, 0.75f, 1.f};
269 sk_sp<SkShader> shader = SkGradientShader::MakeLinear(kPts, kColors, kStops, 3,
271
273 paint.setAntiAlias(true);
275
276 paint.setShader(std::move(shader));
277 paint.setStrokeWidth(kStrokeWidth);
278 paint.setStrokeCap(cap);
279 canvas->drawLine(p0, p1, paint);
280
281 // Show outline and control points
282 SkPath fillPath;
283 SkPath path = SkPath::Line(p0, p1);
284 skpathutils::FillPathWithPaint(path, paint, &fillPath);
285
287 paint.setStrokeWidth(0);
288 paint.setShader(nullptr);
289 paint.setColor(SK_ColorRED);
290 canvas->drawPath(fillPath, paint);
291
292 paint.setStrokeWidth(3);
293 paint.setStrokeCap(SkPaint::kSquare_Cap);
294 int n = fillPath.countPoints();
296 fillPath.getPoints(points.get(), n);
298}
299
300DEF_SIMPLE_GM(strokedline_caps, canvas, 1400, 740) {
301 canvas->translate(kStrokeWidth*3/2, kStrokeWidth*3/2);
302
303 constexpr SkPaint::Cap kCaps[] = {
305 };
306
307 constexpr float kLengths[] = {
309 };
310
311 for (size_t i = 0; i < std::size(kCaps); ++i) {
312 SkAutoCanvasRestore acr(canvas, true);
313
314 auto drawLine = [&](float x0, float y0, float x1, float y1) {
315 draw_path(canvas, {x0, y0}, {x1, y1}, kCaps[i]);
316 canvas->translate(std::max(x0, x1) + 2 * kStrokeWidth, 0);
317 };
318
319 for (size_t j = 0; j < std::size(kLengths); ++j) {
320 float l = kLengths[j];
321
322 drawLine(0.f, 0.f, l, l);
323 drawLine(l, l, 0.f, 0.f);
324 drawLine(l/2, 0, l/2, l);
325 drawLine(0, l/2, l, l/2);
326 }
327
329
330 acr.restore();
331 canvas->translate(0, kLengths[0] + 2 * kStrokeWidth);
332 }
333}
334
335} // namespace skiagm
static const int points[]
#define SkASSERT(cond)
Definition SkAssert.h:116
@ kOuter_SkBlurStyle
nothing inside, fuzzy outside
Definition SkBlurTypes.h:14
uint32_t SkColor
Definition SkColor.h:37
constexpr SkColor SK_ColorBLUE
Definition SkColor.h:135
constexpr SkColor SK_ColorRED
Definition SkColor.h:126
constexpr SkColor SK_ColorGREEN
Definition SkColor.h:131
constexpr SkColor SK_ColorWHITE
Definition SkColor.h:122
#define SkScalarSin(radians)
Definition SkScalar.h:45
#define SK_Scalar1
Definition SkScalar.h:18
#define SkScalarCos(radians)
Definition SkScalar.h:46
#define SK_ScalarPI
Definition SkScalar.h:21
Type::kYUV Type::kRGBA() int(0.7 *637)
constexpr int kPad
static SkScalar draw_row(SkCanvas *canvas, sk_sp< SkImage > img)
constexpr SkRect kRect
sk_sp< SkShader > makeShader(SkTileMode tmx, SkTileMode tmy, const SkSamplingOptions &, const SkMatrix *localMatrix=nullptr) const
Definition SkBitmap.cpp:669
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 clipRect(const SkRect &rect, SkClipOp op, bool doAntiAlias)
void drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint &paint)
void translate(SkScalar dx, SkScalar dy)
void drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, const SkPaint &paint)
void restoreToCount(int saveCount)
Definition SkCanvas.cpp:482
int save()
Definition SkCanvas.cpp:451
void drawPath(const SkPath &path, const SkPaint &paint)
void concat(const SkMatrix &matrix)
@ kPoints_PointMode
draw each point separately
Definition SkCanvas.h:1241
static sk_sp< SkPathEffect > Make(const SkScalar intervals[], int count, SkScalar phase)
static sk_sp< SkShader > MakeLinear(const SkPoint pts[2], const SkColor colors[], const SkScalar pos[], int count, SkTileMode mode, uint32_t flags=0, const SkMatrix *localMatrix=nullptr)
static sk_sp< SkMaskFilter > MakeBlur(SkBlurStyle style, SkScalar sigma, bool respectCTM=true)
static const SkMatrix & I()
@ 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
void setStyle(Style style)
Definition SkPaint.cpp:105
void setAntiAlias(bool aa)
Definition SkPaint.h:170
void setStrokeCap(Cap cap)
Definition SkPaint.cpp:179
@ kStroke_Style
set to stroke geometry
Definition SkPaint.h:194
void setStrokeWidth(SkScalar width)
Definition SkPaint.cpp:159
int countPoints() const
Definition SkPath.cpp:525
int getPoints(SkPoint points[], int max) const
Definition SkPath.cpp:529
static SkPath Line(const SkPoint a, const SkPoint b)
Definition SkPath.h:106
void append(const char text[])
Definition SkString.h:203
int size() const
Definition SkTArray.h:416
void setBGColor(SkColor)
Definition gm.cpp:159
StrokedLinesGM(bool useDrawPath)
void onDraw(SkCanvas *canvas) override
SkString getName() const override
SkISize getISize() override
void onOnceBeforeDraw() override
const Paint & paint
float SkScalar
Definition extension.cpp:12
const int kNumRows
const int kNumColumns
const char * name
Definition fuchsia.cc:50
#define DEF_GM(CODE)
Definition gm.h:40
#define DEF_SIMPLE_GM(NAME, CANVAS, W, H)
Definition gm.h:50
SkColor color_to_565(SkColor color)
static constexpr SkPoint kPts[kPtsCount]
static constexpr float kStrokeWidth
static void draw_path(SkCanvas *canvas, const SkRect &r, const SkPaint &p)
SK_API bool FillPathWithPaint(const SkPath &src, const SkPaint &paint, SkPath *dst, const SkRect *cullRect, SkScalar resScale=1)
static const SkPaint::Cap kCaps[]
Point offset
constexpr int kPad
static void draw_row(SkCanvas *canvas, const SkPaint &paint, const SkMatrix &localMatrix, bool useDrawPath)
static void draw_fins(SkCanvas *canvas, const SkPoint &offset, float angle, const SkPaint &paint, bool useDrawPath)
static void draw_line(SkCanvas *canvas, const SkPoint &p0, const SkPoint &p1, const SkPaint &paint, bool useDrawPath)
constexpr int kNumColumns
constexpr SkScalar kStrokeWidth
constexpr int kNumRows
constexpr int kNumSpokes
static void draw_snowflake(SkCanvas *canvas, const SkPaint &paint, bool useDrawPath)
constexpr int kRadius
static constexpr SkISize Make(int32_t w, int32_t h)
Definition SkSize.h:20
static constexpr SkPoint Make(float x, float y)
SkScalar fBottom
larger y-axis bounds
Definition extension.cpp:17
SkScalar fLeft
smaller x-axis bounds
Definition extension.cpp:14
SkScalar fRight
larger x-axis bounds
Definition extension.cpp:16
static constexpr SkRect MakeLTRB(float l, float t, float r, float b)
Definition SkRect.h:646
SkScalar fTop
smaller y-axis bounds
Definition extension.cpp:15