1 /*
2 * Copyright 2011 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 #include "SampleCode.h"
8 #include "SkBlurMask.h"
9 #include "SkCanvas.h"
10 #include "SkView.h"
11 #include "Sk1DPathEffect.h"
12 #include "Sk2DPathEffect.h"
13 #include "SkBlurMaskFilter.h"
14 #include "SkColorMatrixFilter.h"
15 #include "SkColorPriv.h"
16 #include "SkCornerPathEffect.h"
17 #include "SkDashPathEffect.h"
18 #include "SkDiscretePathEffect.h"
19 #include "SkEmbossMaskFilter.h"
20 #include "SkReadBuffer.h"
21 #include "SkWriteBuffer.h"
22 #include "SkGradientShader.h"
23 #include "SkMath.h"
24 #include "SkPath.h"
25 #include "SkPictureRecorder.h"
26 #include "SkRegion.h"
27 #include "SkShader.h"
28 #include "SkCornerPathEffect.h"
29 #include "SkPathMeasure.h"
30 #include "SkPicture.h"
31 #include "SkRandom.h"
32 #include "SkTypeface.h"
33 #include "SkUtils.h"
34
35 #include <math.h>
36 #include "DecodeFile.h"
37
38 class Dot2DPathEffect : public Sk2DPathEffect {
39 public:
Dot2DPathEffect(SkScalar radius,const SkMatrix & matrix)40 Dot2DPathEffect(SkScalar radius, const SkMatrix& matrix)
41 : Sk2DPathEffect(matrix), fRadius(radius) {}
42
43 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Dot2DPathEffect)
44
45 protected:
next(const SkPoint & loc,int u,int v,SkPath * dst) const46 void next(const SkPoint& loc, int u, int v, SkPath* dst) const override {
47 dst->addCircle(loc.fX, loc.fY, fRadius);
48 }
49
flatten(SkWriteBuffer & buffer) const50 void flatten(SkWriteBuffer& buffer) const override {
51 this->INHERITED::flatten(buffer);
52 buffer.writeScalar(fRadius);
53 }
54
55 private:
56 SkScalar fRadius;
57
58 typedef Sk2DPathEffect INHERITED;
59 };
60
61 class DemoView : public SampleView {
62 public:
DemoView()63 DemoView() {}
64
65 protected:
66 // overrides from SkEventSink
onQuery(SkEvent * evt)67 virtual bool onQuery(SkEvent* evt) {
68 if (SampleCode::TitleQ(*evt)) {
69 SampleCode::TitleR(evt, "Demo");
70 return true;
71 }
72 return this->INHERITED::onQuery(evt);
73 }
74
onClick(Click * click)75 virtual bool onClick(Click* click) {
76 return this->INHERITED::onClick(click);
77 }
78
makePath(SkPath & path)79 void makePath(SkPath& path) {
80 path.addCircle(SkIntToScalar(20), SkIntToScalar(20), SkIntToScalar(20),
81 SkPath::kCCW_Direction);
82 for (int index = 0; index < 10; index++) {
83 SkScalar x = (float) cos(index / 10.0f * 2 * 3.1415925358f);
84 SkScalar y = (float) sin(index / 10.0f * 2 * 3.1415925358f);
85 x *= index & 1 ? 7 : 14;
86 y *= index & 1 ? 7 : 14;
87 x += SkIntToScalar(20);
88 y += SkIntToScalar(20);
89 if (index == 0)
90 path.moveTo(x, y);
91 else
92 path.lineTo(x, y);
93 }
94 path.close();
95 }
96
onDrawContent(SkCanvas * canvas)97 virtual void onDrawContent(SkCanvas* canvas) {
98 canvas->save();
99 this->drawPicture(canvas, 0);
100 canvas->restore();
101
102 {
103 SkPictureRecorder recorder;
104 {
105 SkCanvas* record = recorder.beginRecording(320, 480, nullptr, 0);
106 this->drawPicture(record, 120);
107 }
108 sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture());
109
110 canvas->translate(0, SkIntToScalar(120));
111
112 SkRect clip;
113 clip.set(0, 0, SkIntToScalar(160), SkIntToScalar(160));
114 do {
115 canvas->save();
116 canvas->clipRect(clip);
117 picture->playback(canvas);
118 canvas->restore();
119 if (clip.fRight < SkIntToScalar(320))
120 clip.offset(SkIntToScalar(160), 0);
121 else if (clip.fBottom < SkIntToScalar(480))
122 clip.offset(-SkIntToScalar(320), SkIntToScalar(160));
123 else
124 break;
125 } while (true);
126 }
127 }
128
drawPicture(SkCanvas * canvas,int spriteOffset)129 void drawPicture(SkCanvas* canvas, int spriteOffset) {
130 SkMatrix matrix; matrix.reset();
131 SkPaint paint;
132 SkPath path;
133 SkPoint start = {0, 0};
134 SkPoint stop = { SkIntToScalar(40), SkIntToScalar(40) };
135 SkRect rect = {0, 0, SkIntToScalar(40), SkIntToScalar(40) };
136 SkRect rect2 = {0, 0, SkIntToScalar(65), SkIntToScalar(20) };
137 SkScalar left = 0, top = 0, x = 0, y = 0;
138 int index;
139
140 char ascii[] = "ascii...";
141 int asciiLength = sizeof(ascii) - 1;
142 char utf8[] = "utf8" "\xe2\x80\xa6";
143 short utf16[] = {'u', 't', 'f', '1', '6', 0x2026 };
144 short utf16simple[] = {'u', 't', 'f', '1', '6', '!' };
145
146 makePath(path);
147 SkTDArray<SkPoint> pos;
148 pos.setCount(asciiLength);
149 for (index = 0; index < asciiLength; index++)
150 pos[index].set(SkIntToScalar((unsigned int)index * 10),
151 SkIntToScalar((unsigned int)index * 2));
152 SkTDArray<SkPoint> pos2;
153 pos2.setCount(asciiLength);
154 for (index = 0; index < asciiLength; index++)
155 pos2[index].set(SkIntToScalar((unsigned int)index * 10),
156 SkIntToScalar(20));
157
158 // shaders
159 SkPoint linearPoints[] = { { 0, 0, }, { SkIntToScalar(40), SkIntToScalar(40) } };
160 SkColor linearColors[] = { SK_ColorRED, SK_ColorBLUE };
161 SkScalar* linearPos = nullptr;
162 int linearCount = 2;
163 SkShader::TileMode linearMode = SkShader::kMirror_TileMode;
164 auto linear = SkGradientShader::MakeLinear(linearPoints,
165 linearColors, linearPos, linearCount, linearMode);
166
167 SkPoint radialCenter = { SkIntToScalar(25), SkIntToScalar(25) };
168 SkScalar radialRadius = SkIntToScalar(25);
169 SkColor radialColors[] = { SK_ColorGREEN, SK_ColorGRAY, SK_ColorRED };
170 SkScalar radialPos[] = { 0, SkIntToScalar(3) / 5, SkIntToScalar(1)};
171 int radialCount = 3;
172 SkShader::TileMode radialMode = SkShader::kRepeat_TileMode;
173 auto radial = SkGradientShader::MakeRadial(radialCenter,
174 radialRadius, radialColors, radialPos, radialCount,
175 radialMode);
176
177 SkEmbossMaskFilter::Light light;
178 light.fDirection[0] = SK_Scalar1/2;
179 light.fDirection[1] = SK_Scalar1/2;
180 light.fDirection[2] = SK_Scalar1/3;
181 light.fAmbient = 0x48;
182 light.fSpecular = 0x80;
183
184 auto lightingFilter = SkColorMatrixFilter::MakeLightingFilter(
185 0xff89bc45, 0xff112233);
186
187 canvas->save();
188 canvas->translate(SkIntToScalar(0), SkIntToScalar(5));
189 paint.setAntiAlias(true);
190 paint.setFilterQuality(kLow_SkFilterQuality);
191 // !!! draw through a clip
192 paint.setColor(SK_ColorLTGRAY);
193 paint.setStyle(SkPaint::kFill_Style);
194 SkRect clip = {0, 0, SkIntToScalar(320), SkIntToScalar(120)};
195 canvas->clipRect(clip);
196 paint.setShader(SkShader::MakeBitmapShader(fTx,
197 SkShader::kMirror_TileMode, SkShader::kRepeat_TileMode));
198 canvas->drawPaint(paint);
199 canvas->save();
200
201 // line (exercises xfermode, colorShader, colorFilter, filterShader)
202 paint.setColor(SK_ColorGREEN);
203 paint.setStrokeWidth(SkIntToScalar(10));
204 paint.setStyle(SkPaint::kStroke_Style);
205 paint.setBlendMode(SkBlendMode::kXor);
206 paint.setColorFilter(lightingFilter);
207 canvas->drawLine(start, stop, paint); // should not be green
208 paint.setBlendMode(SkBlendMode::kSrcOver);
209 paint.setColorFilter(nullptr);
210
211 // rectangle
212 paint.setStyle(SkPaint::kFill_Style);
213 canvas->translate(SkIntToScalar(50), 0);
214 paint.setColor(SK_ColorYELLOW);
215 paint.setShader(linear);
216 paint.setPathEffect(pathEffectTest());
217 canvas->drawRect(rect, paint);
218 paint.setPathEffect(nullptr);
219
220 // circle w/ emboss & transparent (exercises 3dshader)
221 canvas->translate(SkIntToScalar(50), 0);
222 paint.setMaskFilter(SkEmbossMaskFilter::Make(
223 SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(12)/5), light));
224 canvas->drawOval(rect, paint);
225 canvas->translate(SkIntToScalar(10), SkIntToScalar(10));
226 // paint.setShader(transparentShader)->unref();
227 canvas->drawOval(rect, paint);
228 canvas->translate(0, SkIntToScalar(-10));
229
230 // path
231 canvas->translate(SkIntToScalar(50), 0);
232 paint.setColor(SK_ColorRED);
233 paint.setStyle(SkPaint::kStroke_Style);
234 paint.setStrokeWidth(SkIntToScalar(5));
235 paint.setShader(radial);
236 paint.setMaskFilter(nullptr);
237 canvas->drawPath(path, paint);
238
239 paint.setShader(nullptr);
240 // bitmap
241 canvas->translate(SkIntToScalar(50), 0);
242 paint.setStyle(SkPaint::kFill_Style);
243 canvas->drawBitmap(fBug, left, top, &paint);
244
245 canvas->translate(-SkIntToScalar(30), SkIntToScalar(30));
246 paint.setShader(shaderTest()); // test compose shader
247 canvas->drawRect(rect2, paint);
248 paint.setShader(nullptr);
249
250 canvas->restore();
251 // text
252 canvas->translate(0, SkIntToScalar(60));
253 canvas->save();
254 paint.setColor(SK_ColorGRAY);
255 canvas->drawPosText(ascii, asciiLength, pos.begin(), paint);
256 canvas->drawPosText(ascii, asciiLength, pos2.begin(), paint);
257
258 canvas->translate(SkIntToScalar(50), 0);
259 paint.setColor(SK_ColorCYAN);
260 canvas->drawText(utf8, sizeof(utf8) - 1, x, y, paint);
261
262 canvas->translate(SkIntToScalar(30), 0);
263 paint.setColor(SK_ColorMAGENTA);
264 paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
265 matrix.setTranslate(SkIntToScalar(10), SkIntToScalar(10));
266 canvas->drawTextOnPath((void*) utf16, sizeof(utf16), path, &matrix, paint);
267 canvas->translate(0, SkIntToScalar(20));
268 canvas->drawTextOnPath((void*) utf16simple, sizeof(utf16simple), path, &matrix, paint);
269 canvas->restore();
270
271 canvas->translate(0, SkIntToScalar(60));
272 paint.setTextEncoding(SkPaint::kUTF8_TextEncoding);
273 canvas->restore();
274 }
275
onFindClickHandler(SkScalar x,SkScalar y,unsigned modi)276 virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) {
277 fClickPt.set(x, y);
278 return this->INHERITED::onFindClickHandler(x, y, modi);
279 }
280
pathEffectTest()281 sk_sp<SkPathEffect> pathEffectTest() {
282 static const int gXY[] = { 1, 0, 0, -1, 2, -1, 3, 0, 2, 1, 0, 1 };
283 SkScalar gPhase = 0;
284 SkPath path;
285 path.moveTo(SkIntToScalar(gXY[0]), SkIntToScalar(gXY[1]));
286 for (unsigned i = 2; i < SK_ARRAY_COUNT(gXY); i += 2)
287 path.lineTo(SkIntToScalar(gXY[i]), SkIntToScalar(gXY[i+1]));
288 path.close();
289 path.offset(SkIntToScalar(-6), 0);
290 auto outer = SkPath1DPathEffect::Make(path, SkIntToScalar(12),
291 gPhase, SkPath1DPathEffect::kRotate_Style);
292 auto inner = SkDiscretePathEffect::Make(SkIntToScalar(2),
293 SkIntToScalar(1)/10); // SkCornerPathEffect(SkIntToScalar(2));
294 return SkPathEffect::MakeCompose(outer, inner);
295 }
296
shaderTest()297 sk_sp<SkShader> shaderTest() {
298 SkPoint pts[] = { { 0, 0, }, { SkIntToScalar(100), 0 } };
299 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE };
300 auto shaderA = SkGradientShader::MakeLinear(pts, colors, nullptr,
301 2, SkShader::kClamp_TileMode);
302 pts[1].set(0, SkIntToScalar(100));
303 SkColor colors2[] = {SK_ColorBLACK, SkColorSetARGB(0x80, 0, 0, 0)};
304 auto shaderB = SkGradientShader::MakeLinear(pts, colors2, nullptr,
305 2, SkShader::kClamp_TileMode);
306 return SkShader::MakeComposeShader(std::move(shaderA), std::move(shaderB),
307 SkBlendMode::kDstIn);
308 }
309
startTest()310 virtual void startTest() {
311 decode_file("/Users/caryclark/Desktop/bugcirc.gif", &fBug);
312 decode_file("/Users/caryclark/Desktop/tbcirc.gif", &fTb);
313 decode_file("/Users/caryclark/Desktop/05psp04.gif", &fTx);
314 }
315
316 private:
317 SkPoint fClickPt;
318 SkBitmap fBug, fTb, fTx;
319 typedef SampleView INHERITED;
320 };
321
322 //////////////////////////////////////////////////////////////////////////////
323
MyFactory()324 static SkView* MyFactory() { return new DemoView; }
325 static SkViewRegister reg(MyFactory);
326