1 
2 /*
3  * Copyright 2011 Google Inc.
4  *
5  * Use of this source code is governed by a BSD-style license that can be
6  * found in the LICENSE file.
7  */
8 #include "SampleCode.h"
9 #include "SkBlurMask.h"
10 #include "SkCanvas.h"
11 #include "SkView.h"
12 #include "Sk1DPathEffect.h"
13 #include "Sk2DPathEffect.h"
14 #include "SkBlurMaskFilter.h"
15 #include "SkColorMatrixFilter.h"
16 #include "SkColorPriv.h"
17 #include "SkCornerPathEffect.h"
18 #include "SkDashPathEffect.h"
19 #include "SkDiscretePathEffect.h"
20 #include "SkEmbossMaskFilter.h"
21 #include "SkReadBuffer.h"
22 #include "SkWriteBuffer.h"
23 #include "SkGradientShader.h"
24 #include "SkImageDecoder.h"
25 #include "SkLayerRasterizer.h"
26 #include "SkMath.h"
27 #include "SkPath.h"
28 #include "SkPictureRecorder.h"
29 #include "SkRegion.h"
30 #include "SkShader.h"
31 #include "SkCornerPathEffect.h"
32 #include "SkPathMeasure.h"
33 #include "SkPicture.h"
34 #include "SkRandom.h"
35 #include "SkTypeface.h"
36 #include "SkUtils.h"
37 #include "SkXfermode.h"
38 
39 #include <math.h>
40 
rgb2gray(SkPMColor c)41 static inline SkPMColor rgb2gray(SkPMColor c) {
42     unsigned r = SkGetPackedR32(c);
43     unsigned g = SkGetPackedG32(c);
44     unsigned b = SkGetPackedB32(c);
45 
46     unsigned x = (r * 5 + g * 7 + b * 4) >> 4;
47 
48     return SkPackARGB32(0, x, x, x) | (c & (SK_A32_MASK << SK_A32_SHIFT));
49 }
50 
51 class SkGrayScaleColorFilter : public SkColorFilter {
52 public:
filterSpan(const SkPMColor src[],int count,SkPMColor result[]) const53     virtual void filterSpan(const SkPMColor src[], int count,
54                             SkPMColor result[]) const override {
55         for (int i = 0; i < count; i++)
56             result[i] = rgb2gray(src[i]);
57     }
58 };
59 
60 class SkChannelMaskColorFilter : public SkColorFilter {
61 public:
SkChannelMaskColorFilter(U8CPU redMask,U8CPU greenMask,U8CPU blueMask)62     SkChannelMaskColorFilter(U8CPU redMask, U8CPU greenMask, U8CPU blueMask) {
63         fMask = SkPackARGB32(0xFF, redMask, greenMask, blueMask);
64     }
65 
filterSpan(const SkPMColor src[],int count,SkPMColor result[]) const66     virtual void filterSpan(const SkPMColor src[], int count,
67                             SkPMColor result[]) const override {
68         SkPMColor mask = fMask;
69         for (int i = 0; i < count; i++) {
70             result[i] = src[i] & mask;
71         }
72     }
73 
74 private:
75     SkPMColor   fMask;
76 };
77 
78 ///////////////////////////////////////////////////////////
79 
r0(SkLayerRasterizer::Builder * rastBuilder,SkPaint & p)80 static void r0(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) {
81     p.setMaskFilter(SkBlurMaskFilter::Create(kNormal_SkBlurStyle,
82                                              SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(3)),
83                                              SkBlurMaskFilter::kNone_BlurFlag))->unref();
84     rastBuilder->addLayer(p, SkIntToScalar(3), SkIntToScalar(3));
85 
86     p.setMaskFilter(nullptr);
87     p.setStyle(SkPaint::kStroke_Style);
88     p.setStrokeWidth(SK_Scalar1);
89     rastBuilder->addLayer(p);
90 
91     p.setAlpha(0x11);
92     p.setStyle(SkPaint::kFill_Style);
93     p.setXfermodeMode(SkXfermode::kSrc_Mode);
94     rastBuilder->addLayer(p);
95 }
96 
r1(SkLayerRasterizer::Builder * rastBuilder,SkPaint & p)97 static void r1(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) {
98     rastBuilder->addLayer(p);
99 
100     p.setAlpha(0x40);
101     p.setXfermodeMode(SkXfermode::kSrc_Mode);
102     p.setStyle(SkPaint::kStroke_Style);
103     p.setStrokeWidth(SK_Scalar1*2);
104     rastBuilder->addLayer(p);
105 }
106 
r2(SkLayerRasterizer::Builder * rastBuilder,SkPaint & p)107 static void r2(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) {
108     p.setStyle(SkPaint::kStrokeAndFill_Style);
109     p.setStrokeWidth(SK_Scalar1*4);
110     rastBuilder->addLayer(p);
111 
112     p.setStyle(SkPaint::kStroke_Style);
113     p.setStrokeWidth(SK_Scalar1*3/2);
114     p.setXfermodeMode(SkXfermode::kClear_Mode);
115     rastBuilder->addLayer(p);
116 }
117 
r3(SkLayerRasterizer::Builder * rastBuilder,SkPaint & p)118 static void r3(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) {
119     p.setStyle(SkPaint::kStroke_Style);
120     p.setStrokeWidth(SK_Scalar1*3);
121     rastBuilder->addLayer(p);
122 
123     p.setAlpha(0x20);
124     p.setStyle(SkPaint::kFill_Style);
125     p.setXfermodeMode(SkXfermode::kSrc_Mode);
126     rastBuilder->addLayer(p);
127 }
128 
r4(SkLayerRasterizer::Builder * rastBuilder,SkPaint & p)129 static void r4(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) {
130     p.setAlpha(0x60);
131     rastBuilder->addLayer(p, SkIntToScalar(3), SkIntToScalar(3));
132 
133     p.setAlpha(0xFF);
134     p.setXfermodeMode(SkXfermode::kClear_Mode);
135     rastBuilder->addLayer(p, SK_Scalar1*3/2, SK_Scalar1*3/2);
136 
137     p.setXfermode(nullptr);
138     rastBuilder->addLayer(p);
139 }
140 
r5(SkLayerRasterizer::Builder * rastBuilder,SkPaint & p)141 static void r5(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) {
142     rastBuilder->addLayer(p);
143 
144     p.setPathEffect(SkDiscretePathEffect::Create(SK_Scalar1*4, SK_Scalar1*3))->unref();
145     p.setXfermodeMode(SkXfermode::kSrcOut_Mode);
146     rastBuilder->addLayer(p);
147 }
148 
r6(SkLayerRasterizer::Builder * rastBuilder,SkPaint & p)149 static void r6(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) {
150     rastBuilder->addLayer(p);
151 
152     p.setAntiAlias(false);
153     SkLayerRasterizer::Builder rastBuilder2;
154     r5(&rastBuilder2, p);
155     p.setRasterizer(rastBuilder2.detachRasterizer())->unref();
156     p.setXfermodeMode(SkXfermode::kClear_Mode);
157     rastBuilder->addLayer(p);
158 }
159 
160 class Dot2DPathEffect : public Sk2DPathEffect {
161 public:
Dot2DPathEffect(SkScalar radius,const SkMatrix & matrix)162     Dot2DPathEffect(SkScalar radius, const SkMatrix& matrix)
163         : Sk2DPathEffect(matrix), fRadius(radius) {}
164 
165     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Dot2DPathEffect)
166 
167 protected:
next(const SkPoint & loc,int u,int v,SkPath * dst) const168     void next(const SkPoint& loc, int u, int v, SkPath* dst) const override {
169         dst->addCircle(loc.fX, loc.fY, fRadius);
170     }
171 
flatten(SkWriteBuffer & buffer) const172     void flatten(SkWriteBuffer& buffer) const override {
173         this->INHERITED::flatten(buffer);
174         buffer.writeScalar(fRadius);
175     }
176 
177 private:
178     SkScalar fRadius;
179 
180     typedef Sk2DPathEffect INHERITED;
181 };
182 
r7(SkLayerRasterizer::Builder * rastBuilder,SkPaint & p)183 static void r7(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) {
184     SkMatrix    lattice;
185     lattice.setScale(SK_Scalar1*6, SK_Scalar1*6, 0, 0);
186     lattice.postSkew(SK_Scalar1/3, 0, 0, 0);
187     p.setPathEffect(new Dot2DPathEffect(SK_Scalar1*4, lattice))->unref();
188     rastBuilder->addLayer(p);
189 }
190 
r8(SkLayerRasterizer::Builder * rastBuilder,SkPaint & p)191 static void r8(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) {
192     rastBuilder->addLayer(p);
193 
194     SkMatrix    lattice;
195     lattice.setScale(SK_Scalar1*6, SK_Scalar1*6, 0, 0);
196     lattice.postSkew(SK_Scalar1/3, 0, 0, 0);
197     p.setPathEffect(new Dot2DPathEffect(SK_Scalar1*2, lattice))->unref();
198     p.setXfermodeMode(SkXfermode::kClear_Mode);
199     rastBuilder->addLayer(p);
200 
201     p.setPathEffect(nullptr);
202     p.setXfermode(nullptr);
203     p.setStyle(SkPaint::kStroke_Style);
204     p.setStrokeWidth(SK_Scalar1);
205     rastBuilder->addLayer(p);
206 }
207 
r9(SkLayerRasterizer::Builder * rastBuilder,SkPaint & p)208 static void r9(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) {
209     rastBuilder->addLayer(p);
210 
211     SkMatrix    lattice;
212     lattice.setScale(SK_Scalar1, SK_Scalar1*6, 0, 0);
213     lattice.postRotate(SkIntToScalar(30), 0, 0);
214     p.setPathEffect(SkLine2DPathEffect::Create(SK_Scalar1*2, lattice))->unref();
215     p.setXfermodeMode(SkXfermode::kClear_Mode);
216     rastBuilder->addLayer(p);
217 
218     p.setPathEffect(nullptr);
219     p.setXfermode(nullptr);
220     p.setStyle(SkPaint::kStroke_Style);
221     p.setStrokeWidth(SK_Scalar1);
222     rastBuilder->addLayer(p);
223 }
224 
225 typedef void (*raster_proc)(SkLayerRasterizer::Builder*, SkPaint&);
226 
227 static const raster_proc gRastProcs[] = {
228     r0, r1, r2, r3, r4, r5, r6, r7, r8, r9
229 };
230 
231 static const struct {
232     SkColor fMul, fAdd;
233 } gLightingColors[] = {
234     { 0x808080, 0x800000 }, // general case
235     { 0x707070, 0x707070 }, // no-pin case
236     { 0xFFFFFF, 0x800000 }, // just-add case
237     { 0x808080, 0x000000 }, // just-mul case
238     { 0xFFFFFF, 0x000000 }  // identity case
239 };
240 
apply_shader(SkPaint * paint,int index)241 static void apply_shader(SkPaint* paint, int index) {
242     raster_proc proc = gRastProcs[index];
243     if (proc) {
244         SkPaint p;
245         SkLayerRasterizer::Builder rastBuilder;
246 
247         p.setAntiAlias(true);
248         proc(&rastBuilder, p);
249         paint->setRasterizer(rastBuilder.detachRasterizer())->unref();
250     }
251 
252 #if 1
253     SkScalar dir[] = { SK_Scalar1, SK_Scalar1, SK_Scalar1 };
254     paint->setMaskFilter(SkBlurMaskFilter::CreateEmboss(
255                 SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(3)), dir,
256                 SK_Scalar1/4, SkIntToScalar(4)))->unref();
257     paint->setColor(SK_ColorBLUE);
258 #endif
259 }
260 
261 class DemoView : public SampleView {
262 public:
DemoView()263     DemoView() {}
264 
265 protected:
266     // overrides from SkEventSink
onQuery(SkEvent * evt)267     virtual bool onQuery(SkEvent* evt) {
268         if (SampleCode::TitleQ(*evt)) {
269             SampleCode::TitleR(evt, "Demo");
270             return true;
271         }
272         return this->INHERITED::onQuery(evt);
273     }
274 
onClick(Click * click)275     virtual bool onClick(Click* click) {
276         return this->INHERITED::onClick(click);
277     }
278 
makePath(SkPath & path)279     void makePath(SkPath& path) {
280         path.addCircle(SkIntToScalar(20), SkIntToScalar(20), SkIntToScalar(20),
281             SkPath::kCCW_Direction);
282         for (int index = 0; index < 10; index++) {
283             SkScalar x = (float) cos(index / 10.0f * 2 * 3.1415925358f);
284             SkScalar y = (float) sin(index / 10.0f * 2 * 3.1415925358f);
285             x *= index & 1 ? 7 : 14;
286             y *= index & 1 ? 7 : 14;
287             x += SkIntToScalar(20);
288             y += SkIntToScalar(20);
289             if (index == 0)
290                 path.moveTo(x, y);
291             else
292                 path.lineTo(x, y);
293         }
294         path.close();
295     }
296 
onDrawContent(SkCanvas * canvas)297     virtual void onDrawContent(SkCanvas* canvas) {
298         canvas->save();
299         this->drawPicture(canvas, 0);
300         canvas->restore();
301 
302         {
303             SkPictureRecorder recorder;
304             {
305                 SkCanvas* record = recorder.beginRecording(320, 480, nullptr, 0);
306                 this->drawPicture(record, 120);
307             }
308             SkAutoTUnref<SkPicture> picture(recorder.endRecording());
309 
310             canvas->translate(0, SkIntToScalar(120));
311 
312             SkRect clip;
313             clip.set(0, 0, SkIntToScalar(160), SkIntToScalar(160));
314             do {
315                 canvas->save();
316                 canvas->clipRect(clip);
317                 picture->playback(canvas);
318                 canvas->restore();
319                 if (clip.fRight < SkIntToScalar(320))
320                     clip.offset(SkIntToScalar(160), 0);
321                 else if (clip.fBottom < SkIntToScalar(480))
322                     clip.offset(-SkIntToScalar(320), SkIntToScalar(160));
323                 else
324                     break;
325             } while (true);
326         }
327     }
328 
drawPicture(SkCanvas * canvas,int spriteOffset)329     void drawPicture(SkCanvas* canvas, int spriteOffset) {
330         SkMatrix matrix; matrix.reset();
331         SkPaint paint;
332         SkPath path;
333         SkPoint start = {0, 0};
334         SkPoint stop = { SkIntToScalar(40), SkIntToScalar(40) };
335         SkRect rect = {0, 0, SkIntToScalar(40), SkIntToScalar(40) };
336         SkRect rect2 = {0, 0, SkIntToScalar(65), SkIntToScalar(20) };
337         SkScalar left = 0, top = 0, x = 0, y = 0;
338         int index;
339 
340         char ascii[] = "ascii...";
341         int asciiLength = sizeof(ascii) - 1;
342         char utf8[] = "utf8" "\xe2\x80\xa6";
343         short utf16[] = {'u', 't', 'f', '1', '6', 0x2026 };
344         short utf16simple[] = {'u', 't', 'f', '1', '6', '!' };
345 
346         makePath(path);
347         SkTDArray<SkPoint>(pos);
348         pos.setCount(asciiLength);
349         for (index = 0;  index < asciiLength; index++)
350             pos[index].set(SkIntToScalar((unsigned int)index * 10),
351                                        SkIntToScalar((unsigned int)index * 2));
352         SkTDArray<SkPoint>(pos2);
353         pos2.setCount(asciiLength);
354         for (index = 0;  index < asciiLength; index++)
355             pos2[index].set(SkIntToScalar((unsigned int)index * 10),
356                                         SkIntToScalar(20));
357 
358         // shaders
359         SkPoint linearPoints[] = { { 0, 0, }, { SkIntToScalar(40), SkIntToScalar(40) } };
360         SkColor linearColors[] = { SK_ColorRED, SK_ColorBLUE };
361         SkScalar* linearPos = nullptr;
362         int linearCount = 2;
363         SkShader::TileMode linearMode = SkShader::kMirror_TileMode;
364         SkShader* linear = SkGradientShader::CreateLinear(linearPoints,
365             linearColors, linearPos, linearCount, linearMode);
366 
367         SkPoint radialCenter = { SkIntToScalar(25), SkIntToScalar(25) };
368         SkScalar radialRadius = SkIntToScalar(25);
369         SkColor radialColors[] = { SK_ColorGREEN, SK_ColorGRAY, SK_ColorRED };
370         SkScalar radialPos[] = { 0, SkIntToScalar(3) / 5, SkIntToScalar(1)};
371         int radialCount = 3;
372         SkShader::TileMode radialMode = SkShader::kRepeat_TileMode;
373         SkShader* radial = SkGradientShader::CreateRadial(radialCenter,
374             radialRadius, radialColors, radialPos, radialCount,
375             radialMode);
376 
377         SkEmbossMaskFilter::Light light;
378         light.fDirection[0] = SK_Scalar1/2;
379         light.fDirection[1] = SK_Scalar1/2;
380         light.fDirection[2] = SK_Scalar1/3;
381         light.fAmbient        = 0x48;
382         light.fSpecular        = 0x80;
383         SkScalar sigma = SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(12)/5);
384         SkMaskFilter* embossFilter = SkEmbossMaskFilter::Create(sigma, light);
385 
386         SkXfermode* xfermode = SkXfermode::Create(SkXfermode::kXor_Mode);
387         SkColorFilter* lightingFilter = SkColorMatrixFilter::CreateLightingFilter(
388             0xff89bc45, 0xff112233);
389 
390         canvas->save();
391         canvas->translate(SkIntToScalar(0), SkIntToScalar(5));
392         paint.setAntiAlias(true);
393         paint.setFilterQuality(kLow_SkFilterQuality);
394         // !!! draw through a clip
395         paint.setColor(SK_ColorLTGRAY);
396         paint.setStyle(SkPaint::kFill_Style);
397         SkRect clip = {0, 0, SkIntToScalar(320), SkIntToScalar(120)};
398         canvas->clipRect(clip);
399         paint.setShader(SkShader::CreateBitmapShader(fTx,
400             SkShader::kMirror_TileMode, SkShader::kRepeat_TileMode))->unref();
401         canvas->drawPaint(paint);
402         canvas->save();
403 
404         // line (exercises xfermode, colorShader, colorFilter, filterShader)
405         paint.setColor(SK_ColorGREEN);
406         paint.setStrokeWidth(SkIntToScalar(10));
407         paint.setStyle(SkPaint::kStroke_Style);
408         paint.setXfermode(xfermode)->unref();
409         paint.setColorFilter(lightingFilter)->unref();
410         canvas->drawLine(start.fX, start.fY, stop.fX, stop.fY, paint); // should not be green
411         paint.setXfermode(nullptr);
412         paint.setColorFilter(nullptr);
413 
414         // rectangle
415         paint.setStyle(SkPaint::kFill_Style);
416         canvas->translate(SkIntToScalar(50), 0);
417         paint.setColor(SK_ColorYELLOW);
418         paint.setShader(linear)->unref();
419         paint.setPathEffect(pathEffectTest())->unref();
420         canvas->drawRect(rect, paint);
421         paint.setPathEffect(nullptr);
422 
423         // circle w/ emboss & transparent (exercises 3dshader)
424         canvas->translate(SkIntToScalar(50), 0);
425         paint.setMaskFilter(embossFilter)->unref();
426         canvas->drawOval(rect, paint);
427         canvas->translate(SkIntToScalar(10), SkIntToScalar(10));
428 //        paint.setShader(transparentShader)->unref();
429         canvas->drawOval(rect, paint);
430         canvas->translate(0, SkIntToScalar(-10));
431 
432         // path
433         canvas->translate(SkIntToScalar(50), 0);
434         paint.setColor(SK_ColorRED);
435         paint.setStyle(SkPaint::kStroke_Style);
436         paint.setStrokeWidth(SkIntToScalar(5));
437         paint.setShader(radial)->unref();
438         paint.setMaskFilter(nullptr);
439         canvas->drawPath(path, paint);
440 
441         paint.setShader(nullptr);
442         // bitmap
443         canvas->translate(SkIntToScalar(50), 0);
444         paint.setStyle(SkPaint::kFill_Style);
445         canvas->drawBitmap(fBug, left, top, &paint);
446 
447         canvas->translate(-SkIntToScalar(30), SkIntToScalar(30));
448         paint.setShader(shaderTest())->unref(); // test compose shader
449         canvas->drawRect(rect2, paint);
450         paint.setShader(nullptr);
451 
452         canvas->restore();
453         // text
454         canvas->translate(0, SkIntToScalar(60));
455         canvas->save();
456         paint.setColor(SK_ColorGRAY);
457         canvas->drawPosText(ascii, asciiLength, pos.begin(), paint);
458         canvas->drawPosText(ascii, asciiLength, pos2.begin(), paint);
459 
460         canvas->translate(SkIntToScalar(50), 0);
461         paint.setColor(SK_ColorCYAN);
462         canvas->drawText(utf8, sizeof(utf8) - 1, x, y, paint);
463 
464         canvas->translate(SkIntToScalar(30), 0);
465         paint.setColor(SK_ColorMAGENTA);
466         paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
467         matrix.setTranslate(SkIntToScalar(10), SkIntToScalar(10));
468         canvas->drawTextOnPath((void*) utf16, sizeof(utf16), path, &matrix, paint);
469         canvas->translate(0, SkIntToScalar(20));
470         canvas->drawTextOnPath((void*) utf16simple, sizeof(utf16simple), path, &matrix, paint);
471         canvas->restore();
472 
473         canvas->translate(0, SkIntToScalar(60));
474         paint.setTextEncoding(SkPaint::kUTF8_TextEncoding);
475         canvas->restore();
476     }
477 
onFindClickHandler(SkScalar x,SkScalar y,unsigned modi)478     virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) {
479         fClickPt.set(x, y);
480         this->inval(nullptr);
481         return this->INHERITED::onFindClickHandler(x, y, modi);
482     }
483 
pathEffectTest()484     SkPathEffect* pathEffectTest() {
485         static const int gXY[] = { 1, 0, 0, -1, 2, -1, 3, 0, 2, 1, 0, 1 };
486         SkScalar gPhase = 0;
487         SkPath path;
488         path.moveTo(SkIntToScalar(gXY[0]), SkIntToScalar(gXY[1]));
489         for (unsigned i = 2; i < SK_ARRAY_COUNT(gXY); i += 2)
490             path.lineTo(SkIntToScalar(gXY[i]), SkIntToScalar(gXY[i+1]));
491         path.close();
492         path.offset(SkIntToScalar(-6), 0);
493         SkPathEffect* outer = SkPath1DPathEffect::Create(path, SkIntToScalar(12),
494             gPhase, SkPath1DPathEffect::kRotate_Style);
495         SkPathEffect* inner = SkDiscretePathEffect::Create(SkIntToScalar(2),
496             SkIntToScalar(1)/10); // SkCornerPathEffect(SkIntToScalar(2));
497         SkPathEffect* result = SkComposePathEffect::Create(outer, inner);
498         outer->unref();
499         inner->unref();
500         return result;
501     }
502 
shaderTest()503     SkShader* shaderTest() {
504         SkPoint pts[] = { { 0, 0, }, { SkIntToScalar(100), 0 } };
505         SkColor colors[] = { SK_ColorRED, SK_ColorBLUE };
506         SkShader* shaderA = SkGradientShader::CreateLinear(pts, colors, nullptr,
507             2, SkShader::kClamp_TileMode);
508         pts[1].set(0, SkIntToScalar(100));
509         SkColor colors2[] = {SK_ColorBLACK,  SkColorSetARGB(0x80, 0, 0, 0)};
510         SkShader* shaderB = SkGradientShader::CreateLinear(pts, colors2, nullptr,
511             2, SkShader::kClamp_TileMode);
512         SkXfermode* mode = SkXfermode::Create(SkXfermode::kDstIn_Mode);
513         SkShader* result = SkShader::CreateComposeShader(shaderA, shaderB, mode);
514         shaderA->unref();
515         shaderB->unref();
516         mode->unref();
517         return result;
518     }
519 
startTest()520     virtual void startTest() {
521         SkImageDecoder::DecodeFile("/Users/caryclark/Desktop/bugcirc.gif", &fBug);
522         SkImageDecoder::DecodeFile("/Users/caryclark/Desktop/tbcirc.gif", &fTb);
523         SkImageDecoder::DecodeFile("/Users/caryclark/Desktop/05psp04.gif", &fTx);
524     }
525 
drawRaster(SkCanvas * canvas)526     void drawRaster(SkCanvas* canvas)  {
527         for (size_t index = 0; index < SK_ARRAY_COUNT(gRastProcs); index++)
528             drawOneRaster(canvas);
529     }
530 
drawOneRaster(SkCanvas * canvas)531     void drawOneRaster(SkCanvas* canvas) {
532         canvas->save();
533 
534         SkScalar    x = SkIntToScalar(20);
535         SkScalar    y = SkIntToScalar(40);
536         SkPaint     paint;
537 
538         paint.setAntiAlias(true);
539         paint.setTextSize(SkIntToScalar(48));
540         paint.setTypeface(SkTypeface::CreateFromName("sans-serif",
541                                                      SkTypeface::kBold));
542 
543         SkString str("GOOGLE");
544 
545         for (size_t i = 0; i < SK_ARRAY_COUNT(gRastProcs); i++) {
546             apply_shader(&paint, (int)i);
547 
548           //  paint.setMaskFilter(nullptr);
549           //  paint.setColor(SK_ColorBLACK);
550 
551 #if 01
552             int index = i % SK_ARRAY_COUNT(gLightingColors);
553             paint.setColorFilter(SkColorMatrixFilter::CreateLightingFilter(
554                                     gLightingColors[index].fMul,
555                                     gLightingColors[index].fAdd))->unref();
556 #endif
557 
558             canvas->drawText(str.c_str(), str.size(), x, y, paint);
559             SkRect  oval = { x, y - SkIntToScalar(40), x + SkIntToScalar(40), y };
560             paint.setStyle(SkPaint::kStroke_Style);
561             canvas->drawOval(oval, paint);
562             paint.setStyle(SkPaint::kFill_Style);
563 
564             y += paint.getFontSpacing();
565         }
566 
567         canvas->restore();
568     }
569 
570 private:
571     SkPoint fClickPt;
572     SkBitmap fBug, fTb, fTx;
573     typedef SampleView INHERITED;
574 };
575 
576 //////////////////////////////////////////////////////////////////////////////
577 
MyFactory()578 static SkView* MyFactory() { return new DemoView; }
579 static SkViewRegister reg(MyFactory);
580