blob: cf1cbabb2543934765c621cf94f2150233c9cab3 [file] [log] [blame]
robertphillips0ee62202016-05-31 06:59:18 -07001/*
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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "gm/gm.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -04009#include "include/core/SkBitmap.h"
10#include "include/core/SkBlurTypes.h"
11#include "include/core/SkCanvas.h"
12#include "include/core/SkColor.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050013#include "include/core/SkMaskFilter.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040014#include "include/core/SkMatrix.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050015#include "include/core/SkPaint.h"
16#include "include/core/SkPath.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040017#include "include/core/SkPathEffect.h"
18#include "include/core/SkPoint.h"
19#include "include/core/SkRect.h"
20#include "include/core/SkScalar.h"
21#include "include/core/SkShader.h"
22#include "include/core/SkSize.h"
23#include "include/core/SkString.h"
24#include "include/core/SkTileMode.h"
25#include "include/core/SkTypes.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050026#include "include/effects/SkDashPathEffect.h"
27#include "include/effects/SkGradientShader.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040028#include "include/private/SkTArray.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050029#include "tools/ToolUtils.h"
robertphillips0ee62202016-05-31 06:59:18 -070030
Ben Wagner7fde8e12019-05-01 17:28:53 -040031#include <initializer_list>
32
mtkleindbfd7ab2016-09-01 11:24:54 -070033constexpr int kNumColumns = 6;
34constexpr int kNumRows = 8;
35constexpr int kRadius = 40; // radius of the snowflake
36constexpr int kPad = 5; // padding on both sides of the snowflake
37constexpr int kNumSpokes = 6;
38constexpr SkScalar kStrokeWidth = 5.0f;
robertphillips0ee62202016-05-31 06:59:18 -070039
40static void draw_fins(SkCanvas* canvas, const SkPoint& offset, float angle, const SkPaint& paint) {
41 SkScalar cos, sin;
42
43 // first fin
Brian Osman4428f2c2019-04-02 10:59:28 -040044 sin = SkScalarSin(angle + (SK_ScalarPI/4));
45 cos = SkScalarCos(angle + (SK_ScalarPI/4));
robertphillips0ee62202016-05-31 06:59:18 -070046 sin *= kRadius / 2.0f;
47 cos *= kRadius / 2.0f;
48
49 SkPath p;
50 p.moveTo(offset.fX, offset.fY);
51 p.lineTo(offset.fX + cos, offset.fY + sin);
52 canvas->drawPath(p, paint);
53
54 // second fin
Brian Osman4428f2c2019-04-02 10:59:28 -040055 sin = SkScalarSin(angle - (SK_ScalarPI/4));
56 cos = SkScalarCos(angle - (SK_ScalarPI/4));
robertphillips0ee62202016-05-31 06:59:18 -070057 sin *= kRadius / 2.0f;
58 cos *= kRadius / 2.0f;
59
60 p.reset();
61 p.moveTo(offset.fX, offset.fY);
62 p.lineTo(offset.fX + cos, offset.fY + sin);
63 canvas->drawPath(p, paint);
64}
65
66// draw a snowflake centered at the origin
67static void draw_snowflake(SkCanvas* canvas, const SkPaint& paint) {
68
69 canvas->clipRect(SkRect::MakeLTRB(-kRadius-kPad, -kRadius-kPad, kRadius+kPad, kRadius+kPad));
70
71 SkScalar sin, cos, angle = 0.0f;
72 for (int i = 0; i < kNumSpokes/2; ++i, angle += SK_ScalarPI/(kNumSpokes/2)) {
Brian Osman4428f2c2019-04-02 10:59:28 -040073 sin = SkScalarSin(angle);
74 cos = SkScalarCos(angle);
robertphillips0ee62202016-05-31 06:59:18 -070075 sin *= kRadius;
76 cos *= kRadius;
77
78 // main spoke
79 SkPath p;
80 p.moveTo(-cos, -sin);
81 p.lineTo(cos, sin);
82 canvas->drawPath(p, paint);
83
84 // fins on positive side
85 const SkPoint posOffset = SkPoint::Make(0.5f * cos, 0.5f * sin);
86 draw_fins(canvas, posOffset, angle, paint);
87
88 // fins on negative side
89 const SkPoint negOffset = SkPoint::Make(-0.5f * cos, -0.5f * sin);
90 draw_fins(canvas, negOffset, angle+SK_ScalarPI, paint);
91 }
92}
93
94static void draw_row(SkCanvas* canvas, const SkPaint& paint, const SkMatrix& localMatrix) {
95 canvas->translate(kRadius+kPad, 0.0f);
96
97 for (auto cap : { SkPaint::kButt_Cap, SkPaint::kRound_Cap, SkPaint::kSquare_Cap }) {
98 for (auto isAA : { true, false }) {
99 SkPaint tmp(paint);
100 tmp.setStrokeWidth(kStrokeWidth);
101 tmp.setStyle(SkPaint::kStroke_Style);
102 tmp.setStrokeCap(cap);
103 tmp.setAntiAlias(isAA);
104
105 int saveCount = canvas->save();
106 canvas->concat(localMatrix);
107 draw_snowflake(canvas, tmp);
108 canvas->restoreToCount(saveCount);
109
110 canvas->translate(2*(kRadius+kPad), 0.0f);
111 }
112 }
113}
114
115namespace skiagm {
116
117// This GM exercises the special case of a stroked lines.
118// Various shaders are applied to ensure the coordinate spaces work out right.
119class StrokedLinesGM : public GM {
120public:
Mike Kleinea3f0142019-03-20 11:12:10 -0500121 StrokedLinesGM() { this->setBGColor(ToolUtils::color_to_565(0xFF1A65D7)); }
robertphillips0ee62202016-05-31 06:59:18 -0700122
123protected:
124 SkString onShortName() override {
125 return SkString("strokedlines");
126 }
127
128 SkISize onISize() override {
129 return SkISize::Make(kNumColumns * (2*kRadius+2*kPad), kNumRows * (2*kRadius+2*kPad));
130 }
131
132 void onOnceBeforeDraw() override {
133 // paints
134 {
135 // basic white
136 SkPaint p;
137 p.setColor(SK_ColorWHITE);
138 fPaints.push_back(p);
139 }
140 {
141 // gradient
142 SkColor colors[] = { SK_ColorRED, SK_ColorGREEN };
143 SkPoint pts[] = { {-kRadius-kPad, -kRadius-kPad }, { kRadius+kPad, kRadius+kPad } };
144
145 SkPaint p;
Mike Reedfae8fce2019-04-03 10:27:45 -0400146 p.setShader(SkGradientShader::MakeLinear(pts, colors, nullptr, 2, SkTileMode::kClamp));
robertphillips0ee62202016-05-31 06:59:18 -0700147
148 fPaints.push_back(p);
149 }
150 {
151 // dashing
152 SkScalar intervals[] = { kStrokeWidth, kStrokeWidth };
153 int intervalCount = (int) SK_ARRAY_COUNT(intervals);
154 SkPaint p;
155 p.setColor(SK_ColorWHITE);
156 p.setPathEffect(SkDashPathEffect::Make(intervals, intervalCount, kStrokeWidth));
157
158 fPaints.push_back(p);
159 }
160 {
161 // Bitmap shader
162 SkBitmap bm;
163 bm.allocN32Pixels(2, 2);
164 *bm.getAddr32(0, 0) = *bm.getAddr32(1, 1) = 0xFFFFFFFF;
165 *bm.getAddr32(1, 0) = *bm.getAddr32(0, 1) = 0x0;
166
167 SkMatrix m;
168 m.setRotate(12.0f);
Brian Salomon23356442018-11-30 15:33:19 -0500169 m.preScale(3.0f, 3.0f);
robertphillips0ee62202016-05-31 06:59:18 -0700170
171 SkPaint p;
Mike Reed50acf8f2019-04-08 13:20:23 -0400172 p.setShader(bm.makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat, &m));
robertphillips0ee62202016-05-31 06:59:18 -0700173 fPaints.push_back(p);
174 }
175 {
176 // blur
177 SkPaint p;
178 p.setColor(SK_ColorWHITE);
Mike Reed1be1f8d2018-03-14 13:01:17 -0400179 p.setMaskFilter(SkMaskFilter::MakeBlur(kOuter_SkBlurStyle, 3.0f));
robertphillips0ee62202016-05-31 06:59:18 -0700180 fPaints.push_back(p);
181 }
182
183 // matrices
184 {
185 // rotation
186 SkMatrix m;
187 m.setRotate(12.0f);
188
189 fMatrices.push_back(m);
190 }
191 {
192 // skew
193 SkMatrix m;
194 m.setSkew(0.3f, 0.5f);
195
196 fMatrices.push_back(m);
197 }
198 {
199 // perspective
200 SkMatrix m;
201 m.reset();
202 m.setPerspX(-SK_Scalar1 / 300);
203 m.setPerspY(SK_Scalar1 / 300);
204
205 fMatrices.push_back(m);
206 }
207
208 SkASSERT(kNumRows == fPaints.count() + fMatrices.count());
209 }
210
211 void onDraw(SkCanvas* canvas) override {
212 canvas->translate(0, kRadius+kPad);
213
214 for (int i = 0; i < fPaints.count(); ++i) {
215 int saveCount = canvas->save();
216 draw_row(canvas, fPaints[i], SkMatrix::I());
217 canvas->restoreToCount(saveCount);
218
219 canvas->translate(0, 2*(kRadius+kPad));
220 }
221
222 for (int i = 0; i < fMatrices.count(); ++i) {
223 int saveCount = canvas->save();
224 draw_row(canvas, fPaints[0], fMatrices[i]);
225 canvas->restoreToCount(saveCount);
226
227 canvas->translate(0, 2*(kRadius+kPad));
228 }
229 }
230
231private:
232 SkTArray<SkPaint> fPaints;
233 SkTArray<SkMatrix> fMatrices;
234
235 typedef GM INHERITED;
236};
237
238//////////////////////////////////////////////////////////////////////////////
239
240DEF_GM(return new StrokedLinesGM;)
241}