1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2016 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker
8*c8dee2aaSAndroid Build Coastguard Worker #include "gm/gm.h"
9*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkBitmap.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkBlurTypes.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColor.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkMaskFilter.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkMatrix.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPaint.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPath.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPathEffect.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPathUtils.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPoint.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRect.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkScalar.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkShader.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSize.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkString.h"
25*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTileMode.h"
26*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h"
27*c8dee2aaSAndroid Build Coastguard Worker #include "include/effects/SkDashPathEffect.h"
28*c8dee2aaSAndroid Build Coastguard Worker #include "include/effects/SkGradientShader.h"
29*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTArray.h"
30*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTemplates.h"
31*c8dee2aaSAndroid Build Coastguard Worker #include "tools/ToolUtils.h"
32*c8dee2aaSAndroid Build Coastguard Worker
33*c8dee2aaSAndroid Build Coastguard Worker #include <initializer_list>
34*c8dee2aaSAndroid Build Coastguard Worker
35*c8dee2aaSAndroid Build Coastguard Worker using namespace skia_private;
36*c8dee2aaSAndroid Build Coastguard Worker
37*c8dee2aaSAndroid Build Coastguard Worker constexpr int kNumColumns = 6;
38*c8dee2aaSAndroid Build Coastguard Worker constexpr int kNumRows = 8;
39*c8dee2aaSAndroid Build Coastguard Worker constexpr int kRadius = 40; // radius of the snowflake
40*c8dee2aaSAndroid Build Coastguard Worker constexpr int kPad = 5; // padding on both sides of the snowflake
41*c8dee2aaSAndroid Build Coastguard Worker constexpr int kNumSpokes = 6;
42*c8dee2aaSAndroid Build Coastguard Worker constexpr SkScalar kStrokeWidth = 5.0f;
43*c8dee2aaSAndroid Build Coastguard Worker
draw_line(SkCanvas * canvas,const SkPoint & p0,const SkPoint & p1,const SkPaint & paint,bool useDrawPath)44*c8dee2aaSAndroid Build Coastguard Worker static void draw_line(SkCanvas* canvas, const SkPoint& p0, const SkPoint& p1,
45*c8dee2aaSAndroid Build Coastguard Worker const SkPaint& paint, bool useDrawPath) {
46*c8dee2aaSAndroid Build Coastguard Worker if (useDrawPath) {
47*c8dee2aaSAndroid Build Coastguard Worker canvas->drawPath(SkPath::Line(p0, p1), paint);
48*c8dee2aaSAndroid Build Coastguard Worker } else {
49*c8dee2aaSAndroid Build Coastguard Worker canvas->drawLine(p0, p1, paint);
50*c8dee2aaSAndroid Build Coastguard Worker }
51*c8dee2aaSAndroid Build Coastguard Worker }
52*c8dee2aaSAndroid Build Coastguard Worker
draw_fins(SkCanvas * canvas,const SkPoint & offset,float angle,const SkPaint & paint,bool useDrawPath)53*c8dee2aaSAndroid Build Coastguard Worker static void draw_fins(SkCanvas* canvas, const SkPoint& offset, float angle, const SkPaint& paint,
54*c8dee2aaSAndroid Build Coastguard Worker bool useDrawPath) {
55*c8dee2aaSAndroid Build Coastguard Worker SkScalar cos, sin;
56*c8dee2aaSAndroid Build Coastguard Worker
57*c8dee2aaSAndroid Build Coastguard Worker // first fin
58*c8dee2aaSAndroid Build Coastguard Worker sin = SkScalarSin(angle + (SK_ScalarPI/4));
59*c8dee2aaSAndroid Build Coastguard Worker cos = SkScalarCos(angle + (SK_ScalarPI/4));
60*c8dee2aaSAndroid Build Coastguard Worker sin *= kRadius / 2.0f;
61*c8dee2aaSAndroid Build Coastguard Worker cos *= kRadius / 2.0f;
62*c8dee2aaSAndroid Build Coastguard Worker
63*c8dee2aaSAndroid Build Coastguard Worker draw_line(canvas, offset, offset + SkPoint{cos, sin}, paint, useDrawPath);
64*c8dee2aaSAndroid Build Coastguard Worker
65*c8dee2aaSAndroid Build Coastguard Worker // second fin
66*c8dee2aaSAndroid Build Coastguard Worker sin = SkScalarSin(angle - (SK_ScalarPI/4));
67*c8dee2aaSAndroid Build Coastguard Worker cos = SkScalarCos(angle - (SK_ScalarPI/4));
68*c8dee2aaSAndroid Build Coastguard Worker sin *= kRadius / 2.0f;
69*c8dee2aaSAndroid Build Coastguard Worker cos *= kRadius / 2.0f;
70*c8dee2aaSAndroid Build Coastguard Worker
71*c8dee2aaSAndroid Build Coastguard Worker draw_line(canvas, offset, offset + SkPoint{cos, sin}, paint, useDrawPath);
72*c8dee2aaSAndroid Build Coastguard Worker }
73*c8dee2aaSAndroid Build Coastguard Worker
74*c8dee2aaSAndroid Build Coastguard Worker // draw a snowflake centered at the origin
draw_snowflake(SkCanvas * canvas,const SkPaint & paint,bool useDrawPath)75*c8dee2aaSAndroid Build Coastguard Worker static void draw_snowflake(SkCanvas* canvas, const SkPaint& paint, bool useDrawPath) {
76*c8dee2aaSAndroid Build Coastguard Worker
77*c8dee2aaSAndroid Build Coastguard Worker canvas->clipRect(SkRect::MakeLTRB(-kRadius-kPad, -kRadius-kPad, kRadius+kPad, kRadius+kPad));
78*c8dee2aaSAndroid Build Coastguard Worker
79*c8dee2aaSAndroid Build Coastguard Worker SkScalar sin, cos, angle = 0.0f;
80*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < kNumSpokes/2; ++i, angle += SK_ScalarPI/(kNumSpokes/2)) {
81*c8dee2aaSAndroid Build Coastguard Worker sin = SkScalarSin(angle);
82*c8dee2aaSAndroid Build Coastguard Worker cos = SkScalarCos(angle);
83*c8dee2aaSAndroid Build Coastguard Worker sin *= kRadius;
84*c8dee2aaSAndroid Build Coastguard Worker cos *= kRadius;
85*c8dee2aaSAndroid Build Coastguard Worker
86*c8dee2aaSAndroid Build Coastguard Worker // main spoke
87*c8dee2aaSAndroid Build Coastguard Worker draw_line(canvas, {-cos, -sin}, {cos, sin}, paint, useDrawPath);
88*c8dee2aaSAndroid Build Coastguard Worker
89*c8dee2aaSAndroid Build Coastguard Worker // fins on positive side
90*c8dee2aaSAndroid Build Coastguard Worker const SkPoint posOffset = SkPoint::Make(0.5f * cos, 0.5f * sin);
91*c8dee2aaSAndroid Build Coastguard Worker draw_fins(canvas, posOffset, angle, paint, useDrawPath);
92*c8dee2aaSAndroid Build Coastguard Worker
93*c8dee2aaSAndroid Build Coastguard Worker // fins on negative side
94*c8dee2aaSAndroid Build Coastguard Worker const SkPoint negOffset = SkPoint::Make(-0.5f * cos, -0.5f * sin);
95*c8dee2aaSAndroid Build Coastguard Worker draw_fins(canvas, negOffset, angle+SK_ScalarPI, paint, useDrawPath);
96*c8dee2aaSAndroid Build Coastguard Worker }
97*c8dee2aaSAndroid Build Coastguard Worker }
98*c8dee2aaSAndroid Build Coastguard Worker
draw_row(SkCanvas * canvas,const SkPaint & paint,const SkMatrix & localMatrix,bool useDrawPath)99*c8dee2aaSAndroid Build Coastguard Worker static void draw_row(SkCanvas* canvas, const SkPaint& paint, const SkMatrix& localMatrix,
100*c8dee2aaSAndroid Build Coastguard Worker bool useDrawPath) {
101*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(kRadius+kPad, 0.0f);
102*c8dee2aaSAndroid Build Coastguard Worker
103*c8dee2aaSAndroid Build Coastguard Worker for (auto cap : { SkPaint::kButt_Cap, SkPaint::kRound_Cap, SkPaint::kSquare_Cap }) {
104*c8dee2aaSAndroid Build Coastguard Worker for (auto isAA : { true, false }) {
105*c8dee2aaSAndroid Build Coastguard Worker SkPaint tmp(paint);
106*c8dee2aaSAndroid Build Coastguard Worker tmp.setStrokeWidth(kStrokeWidth);
107*c8dee2aaSAndroid Build Coastguard Worker tmp.setStyle(SkPaint::kStroke_Style);
108*c8dee2aaSAndroid Build Coastguard Worker tmp.setStrokeCap(cap);
109*c8dee2aaSAndroid Build Coastguard Worker tmp.setAntiAlias(isAA);
110*c8dee2aaSAndroid Build Coastguard Worker
111*c8dee2aaSAndroid Build Coastguard Worker int saveCount = canvas->save();
112*c8dee2aaSAndroid Build Coastguard Worker canvas->concat(localMatrix);
113*c8dee2aaSAndroid Build Coastguard Worker draw_snowflake(canvas, tmp, useDrawPath);
114*c8dee2aaSAndroid Build Coastguard Worker canvas->restoreToCount(saveCount);
115*c8dee2aaSAndroid Build Coastguard Worker
116*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(2*(kRadius+kPad), 0.0f);
117*c8dee2aaSAndroid Build Coastguard Worker }
118*c8dee2aaSAndroid Build Coastguard Worker }
119*c8dee2aaSAndroid Build Coastguard Worker }
120*c8dee2aaSAndroid Build Coastguard Worker
121*c8dee2aaSAndroid Build Coastguard Worker namespace skiagm {
122*c8dee2aaSAndroid Build Coastguard Worker
123*c8dee2aaSAndroid Build Coastguard Worker // This GM exercises the special case of a stroked lines.
124*c8dee2aaSAndroid Build Coastguard Worker // Various shaders are applied to ensure the coordinate spaces work out right.
125*c8dee2aaSAndroid Build Coastguard Worker class StrokedLinesGM : public GM {
126*c8dee2aaSAndroid Build Coastguard Worker public:
StrokedLinesGM(bool useDrawPath)127*c8dee2aaSAndroid Build Coastguard Worker StrokedLinesGM(bool useDrawPath) : fUseDrawPath(useDrawPath) {
128*c8dee2aaSAndroid Build Coastguard Worker this->setBGColor(ToolUtils::color_to_565(0xFF1A65D7));
129*c8dee2aaSAndroid Build Coastguard Worker }
130*c8dee2aaSAndroid Build Coastguard Worker
131*c8dee2aaSAndroid Build Coastguard Worker protected:
getName() const132*c8dee2aaSAndroid Build Coastguard Worker SkString getName() const override {
133*c8dee2aaSAndroid Build Coastguard Worker // To preserve history, useDrawPath==true has no suffix.
134*c8dee2aaSAndroid Build Coastguard Worker SkString name{"strokedlines"};
135*c8dee2aaSAndroid Build Coastguard Worker if (!fUseDrawPath) {
136*c8dee2aaSAndroid Build Coastguard Worker name.append("_drawPoints");
137*c8dee2aaSAndroid Build Coastguard Worker }
138*c8dee2aaSAndroid Build Coastguard Worker return name;
139*c8dee2aaSAndroid Build Coastguard Worker }
140*c8dee2aaSAndroid Build Coastguard Worker
getISize()141*c8dee2aaSAndroid Build Coastguard Worker SkISize getISize() override {
142*c8dee2aaSAndroid Build Coastguard Worker return SkISize::Make(kNumColumns * (2*kRadius+2*kPad), kNumRows * (2*kRadius+2*kPad));
143*c8dee2aaSAndroid Build Coastguard Worker }
144*c8dee2aaSAndroid Build Coastguard Worker
onOnceBeforeDraw()145*c8dee2aaSAndroid Build Coastguard Worker void onOnceBeforeDraw() override {
146*c8dee2aaSAndroid Build Coastguard Worker // paints
147*c8dee2aaSAndroid Build Coastguard Worker {
148*c8dee2aaSAndroid Build Coastguard Worker // basic white
149*c8dee2aaSAndroid Build Coastguard Worker SkPaint p;
150*c8dee2aaSAndroid Build Coastguard Worker p.setColor(SK_ColorWHITE);
151*c8dee2aaSAndroid Build Coastguard Worker fPaints.push_back(p);
152*c8dee2aaSAndroid Build Coastguard Worker }
153*c8dee2aaSAndroid Build Coastguard Worker {
154*c8dee2aaSAndroid Build Coastguard Worker // gradient
155*c8dee2aaSAndroid Build Coastguard Worker SkColor colors[] = { SK_ColorRED, SK_ColorGREEN };
156*c8dee2aaSAndroid Build Coastguard Worker SkPoint pts[] = { {-kRadius-kPad, -kRadius-kPad }, { kRadius+kPad, kRadius+kPad } };
157*c8dee2aaSAndroid Build Coastguard Worker
158*c8dee2aaSAndroid Build Coastguard Worker SkPaint p;
159*c8dee2aaSAndroid Build Coastguard Worker p.setShader(SkGradientShader::MakeLinear(pts, colors, nullptr, 2, SkTileMode::kClamp));
160*c8dee2aaSAndroid Build Coastguard Worker
161*c8dee2aaSAndroid Build Coastguard Worker fPaints.push_back(p);
162*c8dee2aaSAndroid Build Coastguard Worker }
163*c8dee2aaSAndroid Build Coastguard Worker {
164*c8dee2aaSAndroid Build Coastguard Worker // dashing
165*c8dee2aaSAndroid Build Coastguard Worker SkScalar intervals[] = { kStrokeWidth, kStrokeWidth };
166*c8dee2aaSAndroid Build Coastguard Worker int intervalCount = (int) std::size(intervals);
167*c8dee2aaSAndroid Build Coastguard Worker SkPaint p;
168*c8dee2aaSAndroid Build Coastguard Worker p.setColor(SK_ColorWHITE);
169*c8dee2aaSAndroid Build Coastguard Worker p.setPathEffect(SkDashPathEffect::Make(intervals, intervalCount, kStrokeWidth));
170*c8dee2aaSAndroid Build Coastguard Worker
171*c8dee2aaSAndroid Build Coastguard Worker fPaints.push_back(p);
172*c8dee2aaSAndroid Build Coastguard Worker }
173*c8dee2aaSAndroid Build Coastguard Worker {
174*c8dee2aaSAndroid Build Coastguard Worker // Bitmap shader
175*c8dee2aaSAndroid Build Coastguard Worker SkBitmap bm;
176*c8dee2aaSAndroid Build Coastguard Worker bm.allocN32Pixels(2, 2);
177*c8dee2aaSAndroid Build Coastguard Worker *bm.getAddr32(0, 0) = *bm.getAddr32(1, 1) = 0xFFFFFFFF;
178*c8dee2aaSAndroid Build Coastguard Worker *bm.getAddr32(1, 0) = *bm.getAddr32(0, 1) = 0x0;
179*c8dee2aaSAndroid Build Coastguard Worker
180*c8dee2aaSAndroid Build Coastguard Worker SkMatrix m;
181*c8dee2aaSAndroid Build Coastguard Worker m.setRotate(12.0f);
182*c8dee2aaSAndroid Build Coastguard Worker m.preScale(3.0f, 3.0f);
183*c8dee2aaSAndroid Build Coastguard Worker
184*c8dee2aaSAndroid Build Coastguard Worker SkPaint p;
185*c8dee2aaSAndroid Build Coastguard Worker p.setShader(bm.makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat,
186*c8dee2aaSAndroid Build Coastguard Worker SkSamplingOptions(), m));
187*c8dee2aaSAndroid Build Coastguard Worker fPaints.push_back(p);
188*c8dee2aaSAndroid Build Coastguard Worker }
189*c8dee2aaSAndroid Build Coastguard Worker {
190*c8dee2aaSAndroid Build Coastguard Worker // blur
191*c8dee2aaSAndroid Build Coastguard Worker SkPaint p;
192*c8dee2aaSAndroid Build Coastguard Worker p.setColor(SK_ColorWHITE);
193*c8dee2aaSAndroid Build Coastguard Worker p.setMaskFilter(SkMaskFilter::MakeBlur(kOuter_SkBlurStyle, 3.0f));
194*c8dee2aaSAndroid Build Coastguard Worker fPaints.push_back(p);
195*c8dee2aaSAndroid Build Coastguard Worker }
196*c8dee2aaSAndroid Build Coastguard Worker
197*c8dee2aaSAndroid Build Coastguard Worker // matrices
198*c8dee2aaSAndroid Build Coastguard Worker {
199*c8dee2aaSAndroid Build Coastguard Worker // rotation
200*c8dee2aaSAndroid Build Coastguard Worker SkMatrix m;
201*c8dee2aaSAndroid Build Coastguard Worker m.setRotate(12.0f);
202*c8dee2aaSAndroid Build Coastguard Worker
203*c8dee2aaSAndroid Build Coastguard Worker fMatrices.push_back(m);
204*c8dee2aaSAndroid Build Coastguard Worker }
205*c8dee2aaSAndroid Build Coastguard Worker {
206*c8dee2aaSAndroid Build Coastguard Worker // skew
207*c8dee2aaSAndroid Build Coastguard Worker SkMatrix m;
208*c8dee2aaSAndroid Build Coastguard Worker m.setSkew(0.3f, 0.5f);
209*c8dee2aaSAndroid Build Coastguard Worker
210*c8dee2aaSAndroid Build Coastguard Worker fMatrices.push_back(m);
211*c8dee2aaSAndroid Build Coastguard Worker }
212*c8dee2aaSAndroid Build Coastguard Worker {
213*c8dee2aaSAndroid Build Coastguard Worker // perspective
214*c8dee2aaSAndroid Build Coastguard Worker SkMatrix m;
215*c8dee2aaSAndroid Build Coastguard Worker m.reset();
216*c8dee2aaSAndroid Build Coastguard Worker m.setPerspX(-SK_Scalar1 / 300);
217*c8dee2aaSAndroid Build Coastguard Worker m.setPerspY(SK_Scalar1 / 300);
218*c8dee2aaSAndroid Build Coastguard Worker
219*c8dee2aaSAndroid Build Coastguard Worker fMatrices.push_back(m);
220*c8dee2aaSAndroid Build Coastguard Worker }
221*c8dee2aaSAndroid Build Coastguard Worker
222*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(kNumRows == fPaints.size() + fMatrices.size());
223*c8dee2aaSAndroid Build Coastguard Worker }
224*c8dee2aaSAndroid Build Coastguard Worker
onDraw(SkCanvas * canvas)225*c8dee2aaSAndroid Build Coastguard Worker void onDraw(SkCanvas* canvas) override {
226*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(0, kRadius+kPad);
227*c8dee2aaSAndroid Build Coastguard Worker
228*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < fPaints.size(); ++i) {
229*c8dee2aaSAndroid Build Coastguard Worker int saveCount = canvas->save();
230*c8dee2aaSAndroid Build Coastguard Worker draw_row(canvas, fPaints[i], SkMatrix::I(), fUseDrawPath);
231*c8dee2aaSAndroid Build Coastguard Worker canvas->restoreToCount(saveCount);
232*c8dee2aaSAndroid Build Coastguard Worker
233*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(0, 2*(kRadius+kPad));
234*c8dee2aaSAndroid Build Coastguard Worker }
235*c8dee2aaSAndroid Build Coastguard Worker
236*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < fMatrices.size(); ++i) {
237*c8dee2aaSAndroid Build Coastguard Worker int saveCount = canvas->save();
238*c8dee2aaSAndroid Build Coastguard Worker draw_row(canvas, fPaints[0], fMatrices[i], fUseDrawPath);
239*c8dee2aaSAndroid Build Coastguard Worker canvas->restoreToCount(saveCount);
240*c8dee2aaSAndroid Build Coastguard Worker
241*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(0, 2*(kRadius+kPad));
242*c8dee2aaSAndroid Build Coastguard Worker }
243*c8dee2aaSAndroid Build Coastguard Worker }
244*c8dee2aaSAndroid Build Coastguard Worker
245*c8dee2aaSAndroid Build Coastguard Worker private:
246*c8dee2aaSAndroid Build Coastguard Worker TArray<SkPaint> fPaints;
247*c8dee2aaSAndroid Build Coastguard Worker TArray<SkMatrix> fMatrices;
248*c8dee2aaSAndroid Build Coastguard Worker
249*c8dee2aaSAndroid Build Coastguard Worker const bool fUseDrawPath;
250*c8dee2aaSAndroid Build Coastguard Worker
251*c8dee2aaSAndroid Build Coastguard Worker using INHERITED = GM;
252*c8dee2aaSAndroid Build Coastguard Worker };
253*c8dee2aaSAndroid Build Coastguard Worker
254*c8dee2aaSAndroid Build Coastguard Worker //////////////////////////////////////////////////////////////////////////////
255*c8dee2aaSAndroid Build Coastguard Worker
256*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new StrokedLinesGM(true);)
257*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new StrokedLinesGM(false);)
258*c8dee2aaSAndroid Build Coastguard Worker
259*c8dee2aaSAndroid Build Coastguard Worker //////////////////////////////////////////////////////////////////////////////
260*c8dee2aaSAndroid Build Coastguard Worker
261*c8dee2aaSAndroid Build Coastguard Worker static constexpr float kStrokeWidth = 20.f;
262*c8dee2aaSAndroid Build Coastguard Worker
draw_path(SkCanvas * canvas,const SkPoint & p0,const SkPoint & p1,SkPaint::Cap cap)263*c8dee2aaSAndroid Build Coastguard Worker static void draw_path(SkCanvas* canvas, const SkPoint& p0, const SkPoint& p1, SkPaint::Cap cap) {
264*c8dee2aaSAndroid Build Coastguard Worker // Add a gradient *not* aligned with the line's points to show local coords are tracked properly
265*c8dee2aaSAndroid Build Coastguard Worker constexpr SkRect kRect {-kStrokeWidth, -kStrokeWidth, 2*kStrokeWidth, 4*kStrokeWidth};
266*c8dee2aaSAndroid Build Coastguard Worker constexpr SkPoint kPts[] {{kRect.fLeft, kRect.fTop}, {kRect.fRight, kRect.fBottom}};
267*c8dee2aaSAndroid Build Coastguard Worker constexpr SkColor kColors[] {SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE};
268*c8dee2aaSAndroid Build Coastguard Worker constexpr SkScalar kStops[] {0.f, 0.75f, 1.f};
269*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkShader> shader = SkGradientShader::MakeLinear(kPts, kColors, kStops, 3,
270*c8dee2aaSAndroid Build Coastguard Worker SkTileMode::kClamp);
271*c8dee2aaSAndroid Build Coastguard Worker
272*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
273*c8dee2aaSAndroid Build Coastguard Worker paint.setAntiAlias(true);
274*c8dee2aaSAndroid Build Coastguard Worker paint.setStyle(SkPaint::kStroke_Style);
275*c8dee2aaSAndroid Build Coastguard Worker
276*c8dee2aaSAndroid Build Coastguard Worker paint.setShader(std::move(shader));
277*c8dee2aaSAndroid Build Coastguard Worker paint.setStrokeWidth(kStrokeWidth);
278*c8dee2aaSAndroid Build Coastguard Worker paint.setStrokeCap(cap);
279*c8dee2aaSAndroid Build Coastguard Worker canvas->drawLine(p0, p1, paint);
280*c8dee2aaSAndroid Build Coastguard Worker
281*c8dee2aaSAndroid Build Coastguard Worker // Show outline and control points
282*c8dee2aaSAndroid Build Coastguard Worker SkPath fillPath;
283*c8dee2aaSAndroid Build Coastguard Worker SkPath path = SkPath::Line(p0, p1);
284*c8dee2aaSAndroid Build Coastguard Worker skpathutils::FillPathWithPaint(path, paint, &fillPath);
285*c8dee2aaSAndroid Build Coastguard Worker
286*c8dee2aaSAndroid Build Coastguard Worker paint.setStyle(SkPaint::kStroke_Style);
287*c8dee2aaSAndroid Build Coastguard Worker paint.setStrokeWidth(0);
288*c8dee2aaSAndroid Build Coastguard Worker paint.setShader(nullptr);
289*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(SK_ColorRED);
290*c8dee2aaSAndroid Build Coastguard Worker canvas->drawPath(fillPath, paint);
291*c8dee2aaSAndroid Build Coastguard Worker
292*c8dee2aaSAndroid Build Coastguard Worker paint.setStrokeWidth(3);
293*c8dee2aaSAndroid Build Coastguard Worker paint.setStrokeCap(SkPaint::kSquare_Cap);
294*c8dee2aaSAndroid Build Coastguard Worker int n = fillPath.countPoints();
295*c8dee2aaSAndroid Build Coastguard Worker AutoTArray<SkPoint> points(n);
296*c8dee2aaSAndroid Build Coastguard Worker fillPath.getPoints(points.get(), n);
297*c8dee2aaSAndroid Build Coastguard Worker canvas->drawPoints(SkCanvas::kPoints_PointMode, n, points.get(), paint);
298*c8dee2aaSAndroid Build Coastguard Worker }
299*c8dee2aaSAndroid Build Coastguard Worker
300*c8dee2aaSAndroid Build Coastguard Worker DEF_SIMPLE_GM(strokedline_caps, canvas, 1400, 740) {
301*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(kStrokeWidth*3/2, kStrokeWidth*3/2);
302*c8dee2aaSAndroid Build Coastguard Worker
303*c8dee2aaSAndroid Build Coastguard Worker constexpr SkPaint::Cap kCaps[] = {
304*c8dee2aaSAndroid Build Coastguard Worker SkPaint::kSquare_Cap, SkPaint::kButt_Cap, SkPaint::kRound_Cap
305*c8dee2aaSAndroid Build Coastguard Worker };
306*c8dee2aaSAndroid Build Coastguard Worker
307*c8dee2aaSAndroid Build Coastguard Worker constexpr float kLengths[] = {
308*c8dee2aaSAndroid Build Coastguard Worker 4*kStrokeWidth, kStrokeWidth, kStrokeWidth/2, kStrokeWidth/4
309*c8dee2aaSAndroid Build Coastguard Worker };
310*c8dee2aaSAndroid Build Coastguard Worker
311*c8dee2aaSAndroid Build Coastguard Worker for (size_t i = 0; i < std::size(kCaps); ++i) {
312*c8dee2aaSAndroid Build Coastguard Worker SkAutoCanvasRestore acr(canvas, true);
313*c8dee2aaSAndroid Build Coastguard Worker
__anonddfeee690102(float x0, float y0, float x1, float y1) 314*c8dee2aaSAndroid Build Coastguard Worker auto drawLine = [&](float x0, float y0, float x1, float y1) {
315*c8dee2aaSAndroid Build Coastguard Worker draw_path(canvas, {x0, y0}, {x1, y1}, kCaps[i]);
316*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(std::max(x0, x1) + 2 * kStrokeWidth, 0);
317*c8dee2aaSAndroid Build Coastguard Worker };
318*c8dee2aaSAndroid Build Coastguard Worker
319*c8dee2aaSAndroid Build Coastguard Worker for (size_t j = 0; j < std::size(kLengths); ++j) {
320*c8dee2aaSAndroid Build Coastguard Worker float l = kLengths[j];
321*c8dee2aaSAndroid Build Coastguard Worker
322*c8dee2aaSAndroid Build Coastguard Worker drawLine(0.f, 0.f, l, l);
323*c8dee2aaSAndroid Build Coastguard Worker drawLine(l, l, 0.f, 0.f);
324*c8dee2aaSAndroid Build Coastguard Worker drawLine(l/2, 0, l/2, l);
325*c8dee2aaSAndroid Build Coastguard Worker drawLine(0, l/2, l, l/2);
326*c8dee2aaSAndroid Build Coastguard Worker }
327*c8dee2aaSAndroid Build Coastguard Worker
328*c8dee2aaSAndroid Build Coastguard Worker drawLine(kStrokeWidth/2, kStrokeWidth/2, kStrokeWidth/2, kStrokeWidth/2);
329*c8dee2aaSAndroid Build Coastguard Worker
330*c8dee2aaSAndroid Build Coastguard Worker acr.restore();
331*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(0, kLengths[0] + 2 * kStrokeWidth);
332*c8dee2aaSAndroid Build Coastguard Worker }
333*c8dee2aaSAndroid Build Coastguard Worker }
334*c8dee2aaSAndroid Build Coastguard Worker
335*c8dee2aaSAndroid Build Coastguard Worker } // namespace skiagm
336