blob: a098eb6c16d12bdebf9dac29299f09175542413e [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001/*
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 */
reed@android.com8a1c16f2008-12-17 15:59:43 +00007#include "SampleCode.h"
robertphillips@google.comb7061172013-09-06 14:16:12 +00008#include "SkBlurMask.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +00009#include "SkCanvas.h"
10#include "SkView.h"
11#include "Sk1DPathEffect.h"
12#include "Sk2DPathEffect.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000013#include "SkBlurMaskFilter.h"
reed0daf5dd2016-01-11 12:34:04 -080014#include "SkColorMatrixFilter.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000015#include "SkColorPriv.h"
16#include "SkCornerPathEffect.h"
17#include "SkDashPathEffect.h"
18#include "SkDiscretePathEffect.h"
19#include "SkEmbossMaskFilter.h"
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000020#include "SkReadBuffer.h"
21#include "SkWriteBuffer.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000022#include "SkGradientShader.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000023#include "SkLayerRasterizer.h"
24#include "SkMath.h"
25#include "SkPath.h"
robertphillips@google.com770963f2014-04-18 18:04:41 +000026#include "SkPictureRecorder.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000027#include "SkRegion.h"
28#include "SkShader.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000029#include "SkCornerPathEffect.h"
30#include "SkPathMeasure.h"
31#include "SkPicture.h"
32#include "SkRandom.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000033#include "SkTypeface.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000034#include "SkUtils.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000035
36#include <math.h>
msarettd15750c2016-03-18 15:48:49 -070037#include "DecodeFile.h"
rmistry@google.comae933ce2012-08-23 18:19:56 +000038
mike@reedtribe.org5fd92432011-05-05 01:59:48 +000039static inline SkPMColor rgb2gray(SkPMColor c) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000040 unsigned r = SkGetPackedR32(c);
41 unsigned g = SkGetPackedG32(c);
42 unsigned b = SkGetPackedB32(c);
rmistry@google.comae933ce2012-08-23 18:19:56 +000043
reed@android.comf2b98d62010-12-20 18:26:13 +000044 unsigned x = (r * 5 + g * 7 + b * 4) >> 4;
rmistry@google.comae933ce2012-08-23 18:19:56 +000045
reed@android.com8a1c16f2008-12-17 15:59:43 +000046 return SkPackARGB32(0, x, x, x) | (c & (SK_A32_MASK << SK_A32_SHIFT));
47}
48
49class SkGrayScaleColorFilter : public SkColorFilter {
50public:
mike@reedtribe.org61490fa2012-12-24 14:38:46 +000051 virtual void filterSpan(const SkPMColor src[], int count,
mtklein36352bf2015-03-25 18:17:31 -070052 SkPMColor result[]) const override {
reed@android.com8a1c16f2008-12-17 15:59:43 +000053 for (int i = 0; i < count; i++)
54 result[i] = rgb2gray(src[i]);
55 }
56};
57
58class SkChannelMaskColorFilter : public SkColorFilter {
59public:
mike@reedtribe.org5fd92432011-05-05 01:59:48 +000060 SkChannelMaskColorFilter(U8CPU redMask, U8CPU greenMask, U8CPU blueMask) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000061 fMask = SkPackARGB32(0xFF, redMask, greenMask, blueMask);
62 }
63
mike@reedtribe.org61490fa2012-12-24 14:38:46 +000064 virtual void filterSpan(const SkPMColor src[], int count,
mtklein36352bf2015-03-25 18:17:31 -070065 SkPMColor result[]) const override {
reed@android.com8a1c16f2008-12-17 15:59:43 +000066 SkPMColor mask = fMask;
mike@reedtribe.org5fd92432011-05-05 01:59:48 +000067 for (int i = 0; i < count; i++) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000068 result[i] = src[i] & mask;
mike@reedtribe.org5fd92432011-05-05 01:59:48 +000069 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000070 }
rmistry@google.comae933ce2012-08-23 18:19:56 +000071
reed@android.com8a1c16f2008-12-17 15:59:43 +000072private:
73 SkPMColor fMask;
74};
75
76///////////////////////////////////////////////////////////
77
commit-bot@chromium.orgf792a1b2014-02-26 13:27:37 +000078static void r0(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) {
reedefdfd512016-04-04 10:02:58 -070079 p.setMaskFilter(SkBlurMaskFilter::Make(kNormal_SkBlurStyle,
80 SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(3)),
81 SkBlurMaskFilter::kNone_BlurFlag));
commit-bot@chromium.orgf792a1b2014-02-26 13:27:37 +000082 rastBuilder->addLayer(p, SkIntToScalar(3), SkIntToScalar(3));
reed@android.com8a1c16f2008-12-17 15:59:43 +000083
halcanary96fcdcc2015-08-27 07:41:13 -070084 p.setMaskFilter(nullptr);
reed@android.com8a1c16f2008-12-17 15:59:43 +000085 p.setStyle(SkPaint::kStroke_Style);
86 p.setStrokeWidth(SK_Scalar1);
commit-bot@chromium.orgf792a1b2014-02-26 13:27:37 +000087 rastBuilder->addLayer(p);
reed@android.com8a1c16f2008-12-17 15:59:43 +000088
89 p.setAlpha(0x11);
90 p.setStyle(SkPaint::kFill_Style);
reed374772b2016-10-05 17:33:02 -070091 p.setBlendMode(SkBlendMode::kSrc);
commit-bot@chromium.orgf792a1b2014-02-26 13:27:37 +000092 rastBuilder->addLayer(p);
reed@android.com8a1c16f2008-12-17 15:59:43 +000093}
94
commit-bot@chromium.orgf792a1b2014-02-26 13:27:37 +000095static void r1(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) {
96 rastBuilder->addLayer(p);
reed@android.com8a1c16f2008-12-17 15:59:43 +000097
98 p.setAlpha(0x40);
reed374772b2016-10-05 17:33:02 -070099 p.setBlendMode(SkBlendMode::kSrc);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000100 p.setStyle(SkPaint::kStroke_Style);
101 p.setStrokeWidth(SK_Scalar1*2);
commit-bot@chromium.orgf792a1b2014-02-26 13:27:37 +0000102 rastBuilder->addLayer(p);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000103}
rmistry@google.comae933ce2012-08-23 18:19:56 +0000104
commit-bot@chromium.orgf792a1b2014-02-26 13:27:37 +0000105static void r2(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000106 p.setStyle(SkPaint::kStrokeAndFill_Style);
107 p.setStrokeWidth(SK_Scalar1*4);
commit-bot@chromium.orgf792a1b2014-02-26 13:27:37 +0000108 rastBuilder->addLayer(p);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000109
110 p.setStyle(SkPaint::kStroke_Style);
111 p.setStrokeWidth(SK_Scalar1*3/2);
reed374772b2016-10-05 17:33:02 -0700112 p.setBlendMode(SkBlendMode::kClear);
commit-bot@chromium.orgf792a1b2014-02-26 13:27:37 +0000113 rastBuilder->addLayer(p);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000114}
115
commit-bot@chromium.orgf792a1b2014-02-26 13:27:37 +0000116static void r3(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000117 p.setStyle(SkPaint::kStroke_Style);
118 p.setStrokeWidth(SK_Scalar1*3);
commit-bot@chromium.orgf792a1b2014-02-26 13:27:37 +0000119 rastBuilder->addLayer(p);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000120
121 p.setAlpha(0x20);
122 p.setStyle(SkPaint::kFill_Style);
reed374772b2016-10-05 17:33:02 -0700123 p.setBlendMode(SkBlendMode::kSrc);
commit-bot@chromium.orgf792a1b2014-02-26 13:27:37 +0000124 rastBuilder->addLayer(p);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000125}
126
commit-bot@chromium.orgf792a1b2014-02-26 13:27:37 +0000127static void r4(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000128 p.setAlpha(0x60);
commit-bot@chromium.orgf792a1b2014-02-26 13:27:37 +0000129 rastBuilder->addLayer(p, SkIntToScalar(3), SkIntToScalar(3));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000130
131 p.setAlpha(0xFF);
reed374772b2016-10-05 17:33:02 -0700132 p.setBlendMode(SkBlendMode::kClear);
commit-bot@chromium.orgf792a1b2014-02-26 13:27:37 +0000133 rastBuilder->addLayer(p, SK_Scalar1*3/2, SK_Scalar1*3/2);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000134
reed374772b2016-10-05 17:33:02 -0700135 p.setBlendMode(SkBlendMode::kSrcOver);
commit-bot@chromium.orgf792a1b2014-02-26 13:27:37 +0000136 rastBuilder->addLayer(p);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000137}
138
commit-bot@chromium.orgf792a1b2014-02-26 13:27:37 +0000139static void r5(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) {
140 rastBuilder->addLayer(p);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000141
reeda4393342016-03-18 11:22:57 -0700142 p.setPathEffect(SkDiscretePathEffect::Make(SK_Scalar1*4, SK_Scalar1*3));
reed374772b2016-10-05 17:33:02 -0700143 p.setBlendMode(SkBlendMode::kSrcOut);
commit-bot@chromium.orgf792a1b2014-02-26 13:27:37 +0000144 rastBuilder->addLayer(p);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000145}
146
commit-bot@chromium.orgf792a1b2014-02-26 13:27:37 +0000147static void r6(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) {
148 rastBuilder->addLayer(p);
rmistry@google.comae933ce2012-08-23 18:19:56 +0000149
reed@android.com8a1c16f2008-12-17 15:59:43 +0000150 p.setAntiAlias(false);
commit-bot@chromium.orgf792a1b2014-02-26 13:27:37 +0000151 SkLayerRasterizer::Builder rastBuilder2;
152 r5(&rastBuilder2, p);
reed7b380d02016-03-21 13:25:16 -0700153 p.setRasterizer(rastBuilder2.detach());
reed374772b2016-10-05 17:33:02 -0700154 p.setBlendMode(SkBlendMode::kClear);
commit-bot@chromium.orgf792a1b2014-02-26 13:27:37 +0000155 rastBuilder->addLayer(p);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000156}
157
158class Dot2DPathEffect : public Sk2DPathEffect {
159public:
160 Dot2DPathEffect(SkScalar radius, const SkMatrix& matrix)
161 : Sk2DPathEffect(matrix), fRadius(radius) {}
162
djsollen@google.comba28d032012-03-26 17:57:35 +0000163 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Dot2DPathEffect)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000164
165protected:
mtklein36352bf2015-03-25 18:17:31 -0700166 void next(const SkPoint& loc, int u, int v, SkPath* dst) const override {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000167 dst->addCircle(loc.fX, loc.fY, fRadius);
168 }
rmistry@google.comae933ce2012-08-23 18:19:56 +0000169
mtklein36352bf2015-03-25 18:17:31 -0700170 void flatten(SkWriteBuffer& buffer) const override {
djsollen@google.com54924242012-03-29 15:18:04 +0000171 this->INHERITED::flatten(buffer);
172 buffer.writeScalar(fRadius);
173 }
174
reed@android.com8a1c16f2008-12-17 15:59:43 +0000175private:
176 SkScalar fRadius;
177
reed@android.com8a1c16f2008-12-17 15:59:43 +0000178 typedef Sk2DPathEffect INHERITED;
179};
180
commit-bot@chromium.orgf792a1b2014-02-26 13:27:37 +0000181static void r7(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000182 SkMatrix lattice;
183 lattice.setScale(SK_Scalar1*6, SK_Scalar1*6, 0, 0);
184 lattice.postSkew(SK_Scalar1/3, 0, 0, 0);
reeda4393342016-03-18 11:22:57 -0700185 p.setPathEffect(sk_make_sp<Dot2DPathEffect>(SK_Scalar1*4, lattice));
commit-bot@chromium.orgf792a1b2014-02-26 13:27:37 +0000186 rastBuilder->addLayer(p);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000187}
188
commit-bot@chromium.orgf792a1b2014-02-26 13:27:37 +0000189static void r8(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) {
190 rastBuilder->addLayer(p);
rmistry@google.comae933ce2012-08-23 18:19:56 +0000191
reed@android.com8a1c16f2008-12-17 15:59:43 +0000192 SkMatrix lattice;
193 lattice.setScale(SK_Scalar1*6, SK_Scalar1*6, 0, 0);
194 lattice.postSkew(SK_Scalar1/3, 0, 0, 0);
reeda4393342016-03-18 11:22:57 -0700195 p.setPathEffect(sk_make_sp<Dot2DPathEffect>(SK_Scalar1*2, lattice));
reed374772b2016-10-05 17:33:02 -0700196 p.setBlendMode(SkBlendMode::kClear);
commit-bot@chromium.orgf792a1b2014-02-26 13:27:37 +0000197 rastBuilder->addLayer(p);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000198
halcanary96fcdcc2015-08-27 07:41:13 -0700199 p.setPathEffect(nullptr);
reed374772b2016-10-05 17:33:02 -0700200 p.setBlendMode(SkBlendMode::kSrcOver);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000201 p.setStyle(SkPaint::kStroke_Style);
202 p.setStrokeWidth(SK_Scalar1);
commit-bot@chromium.orgf792a1b2014-02-26 13:27:37 +0000203 rastBuilder->addLayer(p);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000204}
205
commit-bot@chromium.orgf792a1b2014-02-26 13:27:37 +0000206static void r9(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) {
207 rastBuilder->addLayer(p);
rmistry@google.comae933ce2012-08-23 18:19:56 +0000208
reed@android.com8a1c16f2008-12-17 15:59:43 +0000209 SkMatrix lattice;
210 lattice.setScale(SK_Scalar1, SK_Scalar1*6, 0, 0);
211 lattice.postRotate(SkIntToScalar(30), 0, 0);
reeda4393342016-03-18 11:22:57 -0700212 p.setPathEffect(SkLine2DPathEffect::Make(SK_Scalar1*2, lattice));
reed374772b2016-10-05 17:33:02 -0700213 p.setBlendMode(SkBlendMode::kClear);
commit-bot@chromium.orgf792a1b2014-02-26 13:27:37 +0000214 rastBuilder->addLayer(p);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000215
halcanary96fcdcc2015-08-27 07:41:13 -0700216 p.setPathEffect(nullptr);
reed374772b2016-10-05 17:33:02 -0700217 p.setBlendMode(SkBlendMode::kSrcOver);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000218 p.setStyle(SkPaint::kStroke_Style);
219 p.setStrokeWidth(SK_Scalar1);
commit-bot@chromium.orgf792a1b2014-02-26 13:27:37 +0000220 rastBuilder->addLayer(p);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000221}
222
commit-bot@chromium.orgf792a1b2014-02-26 13:27:37 +0000223typedef void (*raster_proc)(SkLayerRasterizer::Builder*, SkPaint&);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000224
225static const raster_proc gRastProcs[] = {
226 r0, r1, r2, r3, r4, r5, r6, r7, r8, r9
227};
228
229static const struct {
230 SkColor fMul, fAdd;
231} gLightingColors[] = {
232 { 0x808080, 0x800000 }, // general case
233 { 0x707070, 0x707070 }, // no-pin case
234 { 0xFFFFFF, 0x800000 }, // just-add case
235 { 0x808080, 0x000000 }, // just-mul case
236 { 0xFFFFFF, 0x000000 } // identity case
237};
238
rmistry@google.comae933ce2012-08-23 18:19:56 +0000239static void apply_shader(SkPaint* paint, int index) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000240 raster_proc proc = gRastProcs[index];
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000241 if (proc) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000242 SkPaint p;
commit-bot@chromium.orgf792a1b2014-02-26 13:27:37 +0000243 SkLayerRasterizer::Builder rastBuilder;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000244
245 p.setAntiAlias(true);
commit-bot@chromium.orgf792a1b2014-02-26 13:27:37 +0000246 proc(&rastBuilder, p);
reed7b380d02016-03-21 13:25:16 -0700247 paint->setRasterizer(rastBuilder.detach());
reed@android.com8a1c16f2008-12-17 15:59:43 +0000248 }
249
Mike Reedfd87be82016-12-07 13:41:57 -0500250#ifdef SK_SUPPORT_LEGACY_EMBOSSMASKFILTER
reed@android.com8a1c16f2008-12-17 15:59:43 +0000251 SkScalar dir[] = { SK_Scalar1, SK_Scalar1, SK_Scalar1 };
reedefdfd512016-04-04 10:02:58 -0700252 paint->setMaskFilter(SkBlurMaskFilter::MakeEmboss(
robertphillips@google.comb7061172013-09-06 14:16:12 +0000253 SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(3)), dir,
reedefdfd512016-04-04 10:02:58 -0700254 SK_Scalar1/4, SkIntToScalar(4)));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000255 paint->setColor(SK_ColorBLUE);
256#endif
257}
258
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000259class DemoView : public SampleView {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000260public:
reed@google.com2f3dc9d2011-05-02 17:33:45 +0000261 DemoView() {}
rmistry@google.comae933ce2012-08-23 18:19:56 +0000262
reed@android.com8a1c16f2008-12-17 15:59:43 +0000263protected:
264 // overrides from SkEventSink
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000265 virtual bool onQuery(SkEvent* evt) {
266 if (SampleCode::TitleQ(*evt)) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000267 SampleCode::TitleR(evt, "Demo");
268 return true;
269 }
270 return this->INHERITED::onQuery(evt);
271 }
rmistry@google.comae933ce2012-08-23 18:19:56 +0000272
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000273 virtual bool onClick(Click* click) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000274 return this->INHERITED::onClick(click);
275 }
rmistry@google.comae933ce2012-08-23 18:19:56 +0000276
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000277 void makePath(SkPath& path) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000278 path.addCircle(SkIntToScalar(20), SkIntToScalar(20), SkIntToScalar(20),
279 SkPath::kCCW_Direction);
280 for (int index = 0; index < 10; index++) {
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000281 SkScalar x = (float) cos(index / 10.0f * 2 * 3.1415925358f);
282 SkScalar y = (float) sin(index / 10.0f * 2 * 3.1415925358f);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000283 x *= index & 1 ? 7 : 14;
284 y *= index & 1 ? 7 : 14;
285 x += SkIntToScalar(20);
286 y += SkIntToScalar(20);
287 if (index == 0)
288 path.moveTo(x, y);
289 else
290 path.lineTo(x, y);
291 }
292 path.close();
293 }
rmistry@google.comae933ce2012-08-23 18:19:56 +0000294
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000295 virtual void onDrawContent(SkCanvas* canvas) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000296 canvas->save();
robertphillips@google.com84b18c72014-04-13 19:09:42 +0000297 this->drawPicture(canvas, 0);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000298 canvas->restore();
299
300 {
robertphillips@google.com84b18c72014-04-13 19:09:42 +0000301 SkPictureRecorder recorder;
302 {
halcanary96fcdcc2015-08-27 07:41:13 -0700303 SkCanvas* record = recorder.beginRecording(320, 480, nullptr, 0);
robertphillips@google.com84b18c72014-04-13 19:09:42 +0000304 this->drawPicture(record, 120);
305 }
reedca2622b2016-03-18 07:25:55 -0700306 sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture());
robertphillips@google.com84b18c72014-04-13 19:09:42 +0000307
reed@android.com8a1c16f2008-12-17 15:59:43 +0000308 canvas->translate(0, SkIntToScalar(120));
309
310 SkRect clip;
311 clip.set(0, 0, SkIntToScalar(160), SkIntToScalar(160));
312 do {
313 canvas->save();
314 canvas->clipRect(clip);
robertphillipsc5ba71d2014-09-04 08:42:50 -0700315 picture->playback(canvas);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000316 canvas->restore();
317 if (clip.fRight < SkIntToScalar(320))
318 clip.offset(SkIntToScalar(160), 0);
319 else if (clip.fBottom < SkIntToScalar(480))
320 clip.offset(-SkIntToScalar(320), SkIntToScalar(160));
321 else
322 break;
323 } while (true);
324 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000325 }
rmistry@google.comae933ce2012-08-23 18:19:56 +0000326
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000327 void drawPicture(SkCanvas* canvas, int spriteOffset) {
rmistry@google.comae933ce2012-08-23 18:19:56 +0000328 SkMatrix matrix; matrix.reset();
329 SkPaint paint;
330 SkPath path;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000331 SkPoint start = {0, 0};
332 SkPoint stop = { SkIntToScalar(40), SkIntToScalar(40) };
rmistry@google.comae933ce2012-08-23 18:19:56 +0000333 SkRect rect = {0, 0, SkIntToScalar(40), SkIntToScalar(40) };
334 SkRect rect2 = {0, 0, SkIntToScalar(65), SkIntToScalar(20) };
335 SkScalar left = 0, top = 0, x = 0, y = 0;
reed@google.com7fa2a652014-01-27 13:42:58 +0000336 int index;
rmistry@google.comae933ce2012-08-23 18:19:56 +0000337
338 char ascii[] = "ascii...";
reed@google.com7fa2a652014-01-27 13:42:58 +0000339 int asciiLength = sizeof(ascii) - 1;
rmistry@google.comae933ce2012-08-23 18:19:56 +0000340 char utf8[] = "utf8" "\xe2\x80\xa6";
341 short utf16[] = {'u', 't', 'f', '1', '6', 0x2026 };
342 short utf16simple[] = {'u', 't', 'f', '1', '6', '!' };
343
reed@android.com8a1c16f2008-12-17 15:59:43 +0000344 makePath(path);
345 SkTDArray<SkPoint>(pos);
rmistry@google.comae933ce2012-08-23 18:19:56 +0000346 pos.setCount(asciiLength);
347 for (index = 0; index < asciiLength; index++)
348 pos[index].set(SkIntToScalar((unsigned int)index * 10),
tomhudson@google.comffe39bd2012-05-17 15:38:00 +0000349 SkIntToScalar((unsigned int)index * 2));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000350 SkTDArray<SkPoint>(pos2);
rmistry@google.comae933ce2012-08-23 18:19:56 +0000351 pos2.setCount(asciiLength);
352 for (index = 0; index < asciiLength; index++)
353 pos2[index].set(SkIntToScalar((unsigned int)index * 10),
tomhudson@google.comffe39bd2012-05-17 15:38:00 +0000354 SkIntToScalar(20));
rmistry@google.comae933ce2012-08-23 18:19:56 +0000355
reed@android.com8a1c16f2008-12-17 15:59:43 +0000356 // shaders
senorblanco@chromium.org64cc5792011-05-19 19:58:58 +0000357 SkPoint linearPoints[] = { { 0, 0, }, { SkIntToScalar(40), SkIntToScalar(40) } };
reed@android.com8a1c16f2008-12-17 15:59:43 +0000358 SkColor linearColors[] = { SK_ColorRED, SK_ColorBLUE };
halcanary96fcdcc2015-08-27 07:41:13 -0700359 SkScalar* linearPos = nullptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000360 int linearCount = 2;
361 SkShader::TileMode linearMode = SkShader::kMirror_TileMode;
reed8a21c9f2016-03-08 18:50:00 -0800362 auto linear = SkGradientShader::MakeLinear(linearPoints,
commit-bot@chromium.org83f23d82014-05-22 12:27:41 +0000363 linearColors, linearPos, linearCount, linearMode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000364
365 SkPoint radialCenter = { SkIntToScalar(25), SkIntToScalar(25) };
366 SkScalar radialRadius = SkIntToScalar(25);
367 SkColor radialColors[] = { SK_ColorGREEN, SK_ColorGRAY, SK_ColorRED };
368 SkScalar radialPos[] = { 0, SkIntToScalar(3) / 5, SkIntToScalar(1)};
369 int radialCount = 3;
370 SkShader::TileMode radialMode = SkShader::kRepeat_TileMode;
reed8a21c9f2016-03-08 18:50:00 -0800371 auto radial = SkGradientShader::MakeRadial(radialCenter,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000372 radialRadius, radialColors, radialPos, radialCount,
commit-bot@chromium.org83f23d82014-05-22 12:27:41 +0000373 radialMode);
rmistry@google.comae933ce2012-08-23 18:19:56 +0000374
reed@android.com8a1c16f2008-12-17 15:59:43 +0000375 SkEmbossMaskFilter::Light light;
376 light.fDirection[0] = SK_Scalar1/2;
377 light.fDirection[1] = SK_Scalar1/2;
378 light.fDirection[2] = SK_Scalar1/3;
rmistry@google.comae933ce2012-08-23 18:19:56 +0000379 light.fAmbient = 0x48;
380 light.fSpecular = 0x80;
rmistry@google.comae933ce2012-08-23 18:19:56 +0000381
reedd053ce92016-03-22 10:17:23 -0700382 auto lightingFilter = SkColorMatrixFilter::MakeLightingFilter(
reed@android.com8a1c16f2008-12-17 15:59:43 +0000383 0xff89bc45, 0xff112233);
rmistry@google.comae933ce2012-08-23 18:19:56 +0000384
reed@android.com8a1c16f2008-12-17 15:59:43 +0000385 canvas->save();
rmistry@google.comae933ce2012-08-23 18:19:56 +0000386 canvas->translate(SkIntToScalar(0), SkIntToScalar(5));
reed@google.com9cfc83c2013-07-22 17:18:18 +0000387 paint.setAntiAlias(true);
reed93a12152015-03-16 10:08:34 -0700388 paint.setFilterQuality(kLow_SkFilterQuality);
rmistry@google.comae933ce2012-08-23 18:19:56 +0000389 // !!! draw through a clip
390 paint.setColor(SK_ColorLTGRAY);
391 paint.setStyle(SkPaint::kFill_Style);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000392 SkRect clip = {0, 0, SkIntToScalar(320), SkIntToScalar(120)};
393 canvas->clipRect(clip);
reed8a21c9f2016-03-08 18:50:00 -0800394 paint.setShader(SkShader::MakeBitmapShader(fTx,
395 SkShader::kMirror_TileMode, SkShader::kRepeat_TileMode));
rmistry@google.comae933ce2012-08-23 18:19:56 +0000396 canvas->drawPaint(paint);
397 canvas->save();
398
reed@android.com8a1c16f2008-12-17 15:59:43 +0000399 // line (exercises xfermode, colorShader, colorFilter, filterShader)
rmistry@google.comae933ce2012-08-23 18:19:56 +0000400 paint.setColor(SK_ColorGREEN);
401 paint.setStrokeWidth(SkIntToScalar(10));
402 paint.setStyle(SkPaint::kStroke_Style);
reed374772b2016-10-05 17:33:02 -0700403 paint.setBlendMode(SkBlendMode::kXor);
reedd053ce92016-03-22 10:17:23 -0700404 paint.setColorFilter(lightingFilter);
rmistry@google.comae933ce2012-08-23 18:19:56 +0000405 canvas->drawLine(start.fX, start.fY, stop.fX, stop.fY, paint); // should not be green
reed374772b2016-10-05 17:33:02 -0700406 paint.setBlendMode(SkBlendMode::kSrcOver);
halcanary96fcdcc2015-08-27 07:41:13 -0700407 paint.setColorFilter(nullptr);
rmistry@google.comae933ce2012-08-23 18:19:56 +0000408
reed@android.com8a1c16f2008-12-17 15:59:43 +0000409 // rectangle
rmistry@google.comae933ce2012-08-23 18:19:56 +0000410 paint.setStyle(SkPaint::kFill_Style);
411 canvas->translate(SkIntToScalar(50), 0);
412 paint.setColor(SK_ColorYELLOW);
reed8a21c9f2016-03-08 18:50:00 -0800413 paint.setShader(linear);
reeda4393342016-03-18 11:22:57 -0700414 paint.setPathEffect(pathEffectTest());
rmistry@google.comae933ce2012-08-23 18:19:56 +0000415 canvas->drawRect(rect, paint);
halcanary96fcdcc2015-08-27 07:41:13 -0700416 paint.setPathEffect(nullptr);
rmistry@google.comae933ce2012-08-23 18:19:56 +0000417
reed@android.com8a1c16f2008-12-17 15:59:43 +0000418 // circle w/ emboss & transparent (exercises 3dshader)
rmistry@google.comae933ce2012-08-23 18:19:56 +0000419 canvas->translate(SkIntToScalar(50), 0);
reedefdfd512016-04-04 10:02:58 -0700420 paint.setMaskFilter(SkEmbossMaskFilter::Make(
421 SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(12)/5), light));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000422 canvas->drawOval(rect, paint);
rmistry@google.comae933ce2012-08-23 18:19:56 +0000423 canvas->translate(SkIntToScalar(10), SkIntToScalar(10));
reed56263c72015-06-05 11:31:26 -0700424// paint.setShader(transparentShader)->unref();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000425 canvas->drawOval(rect, paint);
rmistry@google.comae933ce2012-08-23 18:19:56 +0000426 canvas->translate(0, SkIntToScalar(-10));
427
reed@android.com8a1c16f2008-12-17 15:59:43 +0000428 // path
rmistry@google.comae933ce2012-08-23 18:19:56 +0000429 canvas->translate(SkIntToScalar(50), 0);
430 paint.setColor(SK_ColorRED);
431 paint.setStyle(SkPaint::kStroke_Style);
432 paint.setStrokeWidth(SkIntToScalar(5));
reed8a21c9f2016-03-08 18:50:00 -0800433 paint.setShader(radial);
halcanary96fcdcc2015-08-27 07:41:13 -0700434 paint.setMaskFilter(nullptr);
rmistry@google.comae933ce2012-08-23 18:19:56 +0000435 canvas->drawPath(path, paint);
436
halcanary96fcdcc2015-08-27 07:41:13 -0700437 paint.setShader(nullptr);
reed6f45c172015-11-04 08:34:07 -0800438 // bitmap
rmistry@google.comae933ce2012-08-23 18:19:56 +0000439 canvas->translate(SkIntToScalar(50), 0);
440 paint.setStyle(SkPaint::kFill_Style);
441 canvas->drawBitmap(fBug, left, top, &paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000442
rmistry@google.comae933ce2012-08-23 18:19:56 +0000443 canvas->translate(-SkIntToScalar(30), SkIntToScalar(30));
reed8a21c9f2016-03-08 18:50:00 -0800444 paint.setShader(shaderTest()); // test compose shader
rmistry@google.comae933ce2012-08-23 18:19:56 +0000445 canvas->drawRect(rect2, paint);
halcanary96fcdcc2015-08-27 07:41:13 -0700446 paint.setShader(nullptr);
rmistry@google.comae933ce2012-08-23 18:19:56 +0000447
reed@android.com8a1c16f2008-12-17 15:59:43 +0000448 canvas->restore();
449 // text
reed@android.com8a1c16f2008-12-17 15:59:43 +0000450 canvas->translate(0, SkIntToScalar(60));
rmistry@google.comae933ce2012-08-23 18:19:56 +0000451 canvas->save();
452 paint.setColor(SK_ColorGRAY);
453 canvas->drawPosText(ascii, asciiLength, pos.begin(), paint);
454 canvas->drawPosText(ascii, asciiLength, pos2.begin(), paint);
455
456 canvas->translate(SkIntToScalar(50), 0);
457 paint.setColor(SK_ColorCYAN);
458 canvas->drawText(utf8, sizeof(utf8) - 1, x, y, paint);
459
460 canvas->translate(SkIntToScalar(30), 0);
461 paint.setColor(SK_ColorMAGENTA);
462 paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
463 matrix.setTranslate(SkIntToScalar(10), SkIntToScalar(10));
464 canvas->drawTextOnPath((void*) utf16, sizeof(utf16), path, &matrix, paint);
465 canvas->translate(0, SkIntToScalar(20));
466 canvas->drawTextOnPath((void*) utf16simple, sizeof(utf16simple), path, &matrix, paint);
467 canvas->restore();
468
469 canvas->translate(0, SkIntToScalar(60));
470 paint.setTextEncoding(SkPaint::kUTF8_TextEncoding);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000471 canvas->restore();
472 }
rmistry@google.comae933ce2012-08-23 18:19:56 +0000473
reed@google.com4d5c26d2013-01-08 16:17:50 +0000474 virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000475 fClickPt.set(x, y);
halcanary96fcdcc2015-08-27 07:41:13 -0700476 this->inval(nullptr);
reed@google.com4d5c26d2013-01-08 16:17:50 +0000477 return this->INHERITED::onFindClickHandler(x, y, modi);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000478 }
rmistry@google.comae933ce2012-08-23 18:19:56 +0000479
reeda4393342016-03-18 11:22:57 -0700480 sk_sp<SkPathEffect> pathEffectTest() {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000481 static const int gXY[] = { 1, 0, 0, -1, 2, -1, 3, 0, 2, 1, 0, 1 };
482 SkScalar gPhase = 0;
483 SkPath path;
484 path.moveTo(SkIntToScalar(gXY[0]), SkIntToScalar(gXY[1]));
485 for (unsigned i = 2; i < SK_ARRAY_COUNT(gXY); i += 2)
486 path.lineTo(SkIntToScalar(gXY[i]), SkIntToScalar(gXY[i+1]));
487 path.close();
488 path.offset(SkIntToScalar(-6), 0);
reeda4393342016-03-18 11:22:57 -0700489 auto outer = SkPath1DPathEffect::Make(path, SkIntToScalar(12),
reed@android.com8a1c16f2008-12-17 15:59:43 +0000490 gPhase, SkPath1DPathEffect::kRotate_Style);
reeda4393342016-03-18 11:22:57 -0700491 auto inner = SkDiscretePathEffect::Make(SkIntToScalar(2),
reed@android.com8a1c16f2008-12-17 15:59:43 +0000492 SkIntToScalar(1)/10); // SkCornerPathEffect(SkIntToScalar(2));
reeda4393342016-03-18 11:22:57 -0700493 return SkComposePathEffect::Make(outer, inner);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000494 }
reed@google.com963a8fa2012-05-10 13:04:59 +0000495
reed8a21c9f2016-03-08 18:50:00 -0800496 sk_sp<SkShader> shaderTest() {
senorblanco@chromium.org64cc5792011-05-19 19:58:58 +0000497 SkPoint pts[] = { { 0, 0, }, { SkIntToScalar(100), 0 } };
reed@android.com8a1c16f2008-12-17 15:59:43 +0000498 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE };
reed8a21c9f2016-03-08 18:50:00 -0800499 auto shaderA = SkGradientShader::MakeLinear(pts, colors, nullptr,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000500 2, SkShader::kClamp_TileMode);
501 pts[1].set(0, SkIntToScalar(100));
502 SkColor colors2[] = {SK_ColorBLACK, SkColorSetARGB(0x80, 0, 0, 0)};
reed8a21c9f2016-03-08 18:50:00 -0800503 auto shaderB = SkGradientShader::MakeLinear(pts, colors2, nullptr,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000504 2, SkShader::kClamp_TileMode);
reedcfb6bdf2016-03-29 11:32:50 -0700505 return SkShader::MakeComposeShader(std::move(shaderA), std::move(shaderB),
Mike Reed7d954ad2016-10-28 15:42:34 -0400506 SkBlendMode::kDstIn);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000507 }
508
509 virtual void startTest() {
msarettd15750c2016-03-18 15:48:49 -0700510 decode_file("/Users/caryclark/Desktop/bugcirc.gif", &fBug);
511 decode_file("/Users/caryclark/Desktop/tbcirc.gif", &fTb);
512 decode_file("/Users/caryclark/Desktop/05psp04.gif", &fTx);
rmistry@google.comae933ce2012-08-23 18:19:56 +0000513 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000514
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000515 void drawRaster(SkCanvas* canvas) {
senorblanco@chromium.org64cc5792011-05-19 19:58:58 +0000516 for (size_t index = 0; index < SK_ARRAY_COUNT(gRastProcs); index++)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000517 drawOneRaster(canvas);
518 }
rmistry@google.comae933ce2012-08-23 18:19:56 +0000519
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000520 void drawOneRaster(SkCanvas* canvas) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000521 canvas->save();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000522
523 SkScalar x = SkIntToScalar(20);
524 SkScalar y = SkIntToScalar(40);
525 SkPaint paint;
rmistry@google.comae933ce2012-08-23 18:19:56 +0000526
reed@android.com8a1c16f2008-12-17 15:59:43 +0000527 paint.setAntiAlias(true);
528 paint.setTextSize(SkIntToScalar(48));
mbocee6a9912016-05-31 11:42:36 -0700529 paint.setTypeface(SkTypeface::MakeFromName("sans-serif",
530 SkFontStyle::FromOldStyle(SkTypeface::kBold)));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000531
532 SkString str("GOOGLE");
533
senorblanco@chromium.org64cc5792011-05-19 19:58:58 +0000534 for (size_t i = 0; i < SK_ARRAY_COUNT(gRastProcs); i++) {
reed@google.com7fa2a652014-01-27 13:42:58 +0000535 apply_shader(&paint, (int)i);
rmistry@google.comae933ce2012-08-23 18:19:56 +0000536
halcanary96fcdcc2015-08-27 07:41:13 -0700537 // paint.setMaskFilter(nullptr);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000538 // paint.setColor(SK_ColorBLACK);
539
540#if 01
541 int index = i % SK_ARRAY_COUNT(gLightingColors);
reedd053ce92016-03-22 10:17:23 -0700542 paint.setColorFilter(SkColorMatrixFilter::MakeLightingFilter(
reed@android.com8a1c16f2008-12-17 15:59:43 +0000543 gLightingColors[index].fMul,
reedd053ce92016-03-22 10:17:23 -0700544 gLightingColors[index].fAdd));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000545#endif
rmistry@google.comae933ce2012-08-23 18:19:56 +0000546
reed@android.com8a1c16f2008-12-17 15:59:43 +0000547 canvas->drawText(str.c_str(), str.size(), x, y, paint);
548 SkRect oval = { x, y - SkIntToScalar(40), x + SkIntToScalar(40), y };
549 paint.setStyle(SkPaint::kStroke_Style);
550 canvas->drawOval(oval, paint);
551 paint.setStyle(SkPaint::kFill_Style);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000552
553 y += paint.getFontSpacing();
554 }
555
556 canvas->restore();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000557 }
558
559private:
560 SkPoint fClickPt;
561 SkBitmap fBug, fTb, fTx;
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000562 typedef SampleView INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000563};
564
565//////////////////////////////////////////////////////////////////////////////
566
567static SkView* MyFactory() { return new DemoView; }
568static SkViewRegister reg(MyFactory);