SampleAll.cpp revision ba28d03e94dc221d6a803bf2a84a420b9159255c
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 "SkCanvas.h"
10#include "SkView.h"
11#include "Sk1DPathEffect.h"
12#include "Sk2DPathEffect.h"
13#include "SkAvoidXfermode.h"
14#include "SkBlurMaskFilter.h"
15#include "SkColorFilter.h"
16#include "SkColorPriv.h"
17#include "SkCornerPathEffect.h"
18#include "SkDashPathEffect.h"
19#include "SkDiscretePathEffect.h"
20#include "SkEmbossMaskFilter.h"
21#include "SkGradientShader.h"
22#include "SkImageDecoder.h"
23#include "SkLayerRasterizer.h"
24#include "SkMath.h"
25#include "SkPath.h"
26#include "SkRegion.h"
27#include "SkShader.h"
28#include "SkComposeShader.h"
29#include "SkCornerPathEffect.h"
30#include "SkPathMeasure.h"
31#include "SkPicture.h"
32#include "SkRandom.h"
33#include "SkTransparentShader.h"
34#include "SkTypeface.h"
35#include "SkUnitMappers.h"
36#include "SkUtils.h"
37#include "SkXfermode.h"
38
39#include <math.h>
40
41static 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
51class SkGrayScaleColorFilter : public SkColorFilter {
52public:
53    virtual void filterSpan(const SkPMColor src[], int count, SkPMColor result[]) {
54        for (int i = 0; i < count; i++)
55            result[i] = rgb2gray(src[i]);
56    }
57};
58
59class SkChannelMaskColorFilter : public SkColorFilter {
60public:
61    SkChannelMaskColorFilter(U8CPU redMask, U8CPU greenMask, U8CPU blueMask) {
62        fMask = SkPackARGB32(0xFF, redMask, greenMask, blueMask);
63    }
64
65    virtual void filterSpan(const SkPMColor src[], int count, SkPMColor result[]) {
66        SkPMColor mask = fMask;
67        for (int i = 0; i < count; i++) {
68            result[i] = src[i] & mask;
69        }
70    }
71
72private:
73    SkPMColor   fMask;
74};
75
76///////////////////////////////////////////////////////////
77
78static void r0(SkLayerRasterizer* rast, SkPaint& p) {
79    p.setMaskFilter(SkBlurMaskFilter::Create(SkIntToScalar(3),
80                                             SkBlurMaskFilter::kNormal_BlurStyle))->unref();
81    rast->addLayer(p, SkIntToScalar(3), SkIntToScalar(3));
82
83    p.setMaskFilter(NULL);
84    p.setStyle(SkPaint::kStroke_Style);
85    p.setStrokeWidth(SK_Scalar1);
86    rast->addLayer(p);
87
88    p.setAlpha(0x11);
89    p.setStyle(SkPaint::kFill_Style);
90    p.setXfermodeMode(SkXfermode::kSrc_Mode);
91    rast->addLayer(p);
92}
93
94static void r1(SkLayerRasterizer* rast, SkPaint& p) {
95    rast->addLayer(p);
96
97    p.setAlpha(0x40);
98    p.setXfermodeMode(SkXfermode::kSrc_Mode);
99    p.setStyle(SkPaint::kStroke_Style);
100    p.setStrokeWidth(SK_Scalar1*2);
101    rast->addLayer(p);
102}
103
104static void r2(SkLayerRasterizer* rast, SkPaint& p) {
105    p.setStyle(SkPaint::kStrokeAndFill_Style);
106    p.setStrokeWidth(SK_Scalar1*4);
107    rast->addLayer(p);
108
109    p.setStyle(SkPaint::kStroke_Style);
110    p.setStrokeWidth(SK_Scalar1*3/2);
111    p.setXfermodeMode(SkXfermode::kClear_Mode);
112    rast->addLayer(p);
113}
114
115static void r3(SkLayerRasterizer* rast, SkPaint& p) {
116    p.setStyle(SkPaint::kStroke_Style);
117    p.setStrokeWidth(SK_Scalar1*3);
118    rast->addLayer(p);
119
120    p.setAlpha(0x20);
121    p.setStyle(SkPaint::kFill_Style);
122    p.setXfermodeMode(SkXfermode::kSrc_Mode);
123    rast->addLayer(p);
124}
125
126static void r4(SkLayerRasterizer* rast, SkPaint& p) {
127    p.setAlpha(0x60);
128    rast->addLayer(p, SkIntToScalar(3), SkIntToScalar(3));
129
130    p.setAlpha(0xFF);
131    p.setXfermodeMode(SkXfermode::kClear_Mode);
132    rast->addLayer(p, SK_Scalar1*3/2, SK_Scalar1*3/2);
133
134    p.setXfermode(NULL);
135    rast->addLayer(p);
136}
137
138static void r5(SkLayerRasterizer* rast, SkPaint& p) {
139    rast->addLayer(p);
140
141    p.setPathEffect(new SkDiscretePathEffect(SK_Scalar1*4, SK_Scalar1*3))->unref();
142    p.setXfermodeMode(SkXfermode::kSrcOut_Mode);
143    rast->addLayer(p);
144}
145
146static void r6(SkLayerRasterizer* rast, SkPaint& p) {
147    rast->addLayer(p);
148
149    p.setAntiAlias(false);
150    SkLayerRasterizer* rast2 = new SkLayerRasterizer;
151    r5(rast2, p);
152    p.setRasterizer(rast2)->unref();
153    p.setXfermodeMode(SkXfermode::kClear_Mode);
154    rast->addLayer(p);
155}
156
157class Dot2DPathEffect : public Sk2DPathEffect {
158public:
159    Dot2DPathEffect(SkScalar radius, const SkMatrix& matrix)
160        : Sk2DPathEffect(matrix), fRadius(radius) {}
161
162    virtual void flatten(SkFlattenableWriteBuffer& buffer) {
163        this->INHERITED::flatten(buffer);
164
165        buffer.writeScalar(fRadius);
166    }
167    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Dot2DPathEffect)
168
169protected:
170	virtual void next(const SkPoint& loc, int u, int v, SkPath* dst) {
171        dst->addCircle(loc.fX, loc.fY, fRadius);
172    }
173
174    Dot2DPathEffect(SkFlattenableReadBuffer& buffer) : Sk2DPathEffect(buffer) {
175        fRadius = buffer.readScalar();
176    }
177private:
178    SkScalar fRadius;
179
180    typedef Sk2DPathEffect INHERITED;
181};
182
183static void r7(SkLayerRasterizer* rast, 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    rast->addLayer(p);
189}
190
191static void r8(SkLayerRasterizer* rast, SkPaint& p) {
192    rast->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    rast->addLayer(p);
200
201    p.setPathEffect(NULL);
202    p.setXfermode(NULL);
203    p.setStyle(SkPaint::kStroke_Style);
204    p.setStrokeWidth(SK_Scalar1);
205    rast->addLayer(p);
206}
207
208class Line2DPathEffect : public Sk2DPathEffect {
209public:
210    Line2DPathEffect(SkScalar width, const SkMatrix& matrix)
211        : Sk2DPathEffect(matrix), fWidth(width) {}
212
213	virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width) {
214        if (this->INHERITED::filterPath(dst, src, width)) {
215            *width = fWidth;
216            return true;
217        }
218        return false;
219    }
220
221    virtual void flatten(SkFlattenableWriteBuffer& buffer) {
222        this->INHERITED::flatten(buffer);
223        buffer.writeScalar(fWidth);
224    }
225
226    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Line2DPathEffect)
227
228protected:
229	virtual void nextSpan(int u, int v, int ucount, SkPath* dst) {
230        if (ucount > 1) {
231            SkPoint	src[2], dstP[2];
232
233            src[0].set(SkIntToScalar(u) + SK_ScalarHalf,
234                       SkIntToScalar(v) + SK_ScalarHalf);
235            src[1].set(SkIntToScalar(u+ucount) + SK_ScalarHalf,
236                       SkIntToScalar(v) + SK_ScalarHalf);
237            this->getMatrix().mapPoints(dstP, src, 2);
238
239            dst->moveTo(dstP[0]);
240            dst->lineTo(dstP[1]);
241        }
242    }
243
244    Line2DPathEffect(SkFlattenableReadBuffer& buffer) : Sk2DPathEffect(buffer) {
245        fWidth = buffer.readScalar();
246    }
247
248private:
249    SkScalar fWidth;
250
251    typedef Sk2DPathEffect INHERITED;
252};
253
254static void r9(SkLayerRasterizer* rast, SkPaint& p) {
255    rast->addLayer(p);
256
257    SkMatrix    lattice;
258    lattice.setScale(SK_Scalar1, SK_Scalar1*6, 0, 0);
259    lattice.postRotate(SkIntToScalar(30), 0, 0);
260    p.setPathEffect(new Line2DPathEffect(SK_Scalar1*2, lattice))->unref();
261    p.setXfermodeMode(SkXfermode::kClear_Mode);
262    rast->addLayer(p);
263
264    p.setPathEffect(NULL);
265    p.setXfermode(NULL);
266    p.setStyle(SkPaint::kStroke_Style);
267    p.setStrokeWidth(SK_Scalar1);
268    rast->addLayer(p);
269}
270
271typedef void (*raster_proc)(SkLayerRasterizer*, SkPaint&);
272
273static const raster_proc gRastProcs[] = {
274    r0, r1, r2, r3, r4, r5, r6, r7, r8, r9
275};
276
277static const struct {
278    SkColor fMul, fAdd;
279} gLightingColors[] = {
280    { 0x808080, 0x800000 }, // general case
281    { 0x707070, 0x707070 }, // no-pin case
282    { 0xFFFFFF, 0x800000 }, // just-add case
283    { 0x808080, 0x000000 }, // just-mul case
284    { 0xFFFFFF, 0x000000 }  // identity case
285};
286
287static unsigned color_dist16(uint16_t a, uint16_t b) {
288    unsigned dr = SkAbs32(SkPacked16ToR32(a) - SkPacked16ToR32(b));
289    unsigned dg = SkAbs32(SkPacked16ToG32(a) - SkPacked16ToG32(b));
290    unsigned db = SkAbs32(SkPacked16ToB32(a) - SkPacked16ToB32(b));
291
292    return SkMax32(dr, SkMax32(dg, db));
293}
294
295static unsigned scale_dist(unsigned dist, unsigned scale) {
296    dist >>= 6;
297    dist = (dist << 2) | dist;
298    dist = (dist << 4) | dist;
299    return dist;
300
301//    return SkAlphaMul(dist, scale);
302}
303
304static void apply_shader(SkPaint* paint, int index) {
305    raster_proc proc = gRastProcs[index];
306    if (proc) {
307        SkPaint p;
308        SkLayerRasterizer*  rast = new SkLayerRasterizer;
309
310        p.setAntiAlias(true);
311        proc(rast, p);
312        paint->setRasterizer(rast)->unref();
313    }
314
315#if 1
316    SkScalar dir[] = { SK_Scalar1, SK_Scalar1, SK_Scalar1 };
317    paint->setMaskFilter(SkBlurMaskFilter::CreateEmboss(dir, SK_Scalar1/4, SkIntToScalar(4), SkIntToScalar(3)))->unref();
318    paint->setColor(SK_ColorBLUE);
319#endif
320}
321
322class DemoView : public SampleView {
323public:
324    DemoView() {}
325
326protected:
327    // overrides from SkEventSink
328    virtual bool onQuery(SkEvent* evt) {
329        if (SampleCode::TitleQ(*evt)) {
330            SampleCode::TitleR(evt, "Demo");
331            return true;
332        }
333        return this->INHERITED::onQuery(evt);
334    }
335
336    virtual bool onClick(Click* click) {
337        return this->INHERITED::onClick(click);
338    }
339
340    void makePath(SkPath& path) {
341        path.addCircle(SkIntToScalar(20), SkIntToScalar(20), SkIntToScalar(20),
342            SkPath::kCCW_Direction);
343        for (int index = 0; index < 10; index++) {
344            SkScalar x = SkFloatToScalar(cos(index / 10.0f * 2 * 3.1415925358f));
345            SkScalar y = SkFloatToScalar(sin(index / 10.0f * 2 * 3.1415925358f));
346            x *= index & 1 ? 7 : 14;
347            y *= index & 1 ? 7 : 14;
348            x += SkIntToScalar(20);
349            y += SkIntToScalar(20);
350            if (index == 0)
351                path.moveTo(x, y);
352            else
353                path.lineTo(x, y);
354        }
355        path.close();
356    }
357
358    virtual void onDrawContent(SkCanvas* canvas) {
359        canvas->save();
360        drawPicture(canvas, 0);
361        canvas->restore();
362
363        {
364            SkPicture picture;
365            SkCanvas* record = picture.beginRecording(320, 480);
366            drawPicture(record, 120);
367            canvas->translate(0, SkIntToScalar(120));
368
369            SkRect clip;
370            clip.set(0, 0, SkIntToScalar(160), SkIntToScalar(160));
371            do {
372                canvas->save();
373                canvas->clipRect(clip);
374                picture.draw(canvas);
375                canvas->restore();
376                if (clip.fRight < SkIntToScalar(320))
377                    clip.offset(SkIntToScalar(160), 0);
378                else if (clip.fBottom < SkIntToScalar(480))
379                    clip.offset(-SkIntToScalar(320), SkIntToScalar(160));
380                else
381                    break;
382            } while (true);
383        }
384    }
385
386    void drawPicture(SkCanvas* canvas, int spriteOffset) {
387	    SkMatrix matrix; matrix.reset();
388		SkPaint paint;
389		SkPath path;
390        SkPoint start = {0, 0};
391        SkPoint stop = { SkIntToScalar(40), SkIntToScalar(40) };
392		SkRect rect = {0, 0, SkIntToScalar(40), SkIntToScalar(40) };
393		SkRect rect2 = {0, 0, SkIntToScalar(65), SkIntToScalar(20) };
394		SkScalar left = 0, top = 0, x = 0, y = 0;
395		size_t index;
396
397		char ascii[] = "ascii...";
398		size_t asciiLength = sizeof(ascii) - 1;
399		char utf8[] = "utf8" "\xe2\x80\xa6";
400		short utf16[] = {'u', 't', 'f', '1', '6', 0x2026 };
401		short utf16simple[] = {'u', 't', 'f', '1', '6', '!' };
402
403        makePath(path);
404        SkTDArray<SkPoint>(pos);
405		pos.setCount(asciiLength);
406		for (index = 0;  index < asciiLength; index++)
407			pos[index].set(SkIntToScalar(index * 10), SkIntToScalar(index * 2));
408        SkTDArray<SkPoint>(pos2);
409		pos2.setCount(asciiLength);
410		for (index = 0;  index < asciiLength; index++)
411			pos2[index].set(SkIntToScalar(index * 10), SkIntToScalar(20));
412
413        // shaders
414        SkPoint linearPoints[] = { { 0, 0, }, { SkIntToScalar(40), SkIntToScalar(40) } };
415        SkColor linearColors[] = { SK_ColorRED, SK_ColorBLUE };
416        SkScalar* linearPos = NULL;
417        int linearCount = 2;
418        SkShader::TileMode linearMode = SkShader::kMirror_TileMode;
419        SkUnitMapper* linearMapper = new SkDiscreteMapper(3);
420        SkAutoUnref unmapLinearMapper(linearMapper);
421        SkShader* linear = SkGradientShader::CreateLinear(linearPoints,
422            linearColors, linearPos, linearCount, linearMode, linearMapper);
423
424        SkPoint radialCenter = { SkIntToScalar(25), SkIntToScalar(25) };
425        SkScalar radialRadius = SkIntToScalar(25);
426        SkColor radialColors[] = { SK_ColorGREEN, SK_ColorGRAY, SK_ColorRED };
427        SkScalar radialPos[] = { 0, SkIntToScalar(3) / 5, SkIntToScalar(1)};
428        int radialCount = 3;
429        SkShader::TileMode radialMode = SkShader::kRepeat_TileMode;
430        SkUnitMapper* radialMapper = new SkCosineMapper();
431        SkAutoUnref unmapRadialMapper(radialMapper);
432        SkShader* radial = SkGradientShader::CreateRadial(radialCenter,
433            radialRadius, radialColors, radialPos, radialCount,
434            radialMode, radialMapper);
435
436        SkTransparentShader* transparentShader = new SkTransparentShader();
437        SkEmbossMaskFilter::Light light;
438        light.fDirection[0] = SK_Scalar1/2;
439        light.fDirection[1] = SK_Scalar1/2;
440        light.fDirection[2] = SK_Scalar1/3;
441        light.fAmbient		= 0x48;
442        light.fSpecular		= 0x80;
443        SkScalar radius = SkIntToScalar(12)/5;
444        SkEmbossMaskFilter* embossFilter = new SkEmbossMaskFilter(light,
445            radius);
446
447        SkXfermode* xfermode = SkXfermode::Create(SkXfermode::kXor_Mode);
448        SkColorFilter* lightingFilter = SkColorFilter::CreateLightingFilter(
449            0xff89bc45, 0xff112233);
450
451        canvas->save();
452		canvas->translate(SkIntToScalar(0), SkIntToScalar(5));
453		paint.setFlags(SkPaint::kAntiAlias_Flag | SkPaint::kFilterBitmap_Flag);
454		// !!! draw through a clip
455		paint.setColor(SK_ColorLTGRAY);
456		paint.setStyle(SkPaint::kFill_Style);
457        SkRect clip = {0, 0, SkIntToScalar(320), SkIntToScalar(120)};
458        canvas->clipRect(clip);
459        paint.setShader(SkShader::CreateBitmapShader(fTx,
460            SkShader::kMirror_TileMode, SkShader::kRepeat_TileMode))->unref();
461		canvas->drawPaint(paint);
462		canvas->save();
463
464        // line (exercises xfermode, colorShader, colorFilter, filterShader)
465		paint.setColor(SK_ColorGREEN);
466		paint.setStrokeWidth(SkIntToScalar(10));
467		paint.setStyle(SkPaint::kStroke_Style);
468        paint.setXfermode(xfermode)->unref();
469        paint.setColorFilter(lightingFilter)->unref();
470		canvas->drawLine(start.fX, start.fY, stop.fX, stop.fY, paint); // should not be green
471		paint.setXfermode(NULL);
472        paint.setColorFilter(NULL);
473
474        // rectangle
475		paint.setStyle(SkPaint::kFill_Style);
476		canvas->translate(SkIntToScalar(50), 0);
477		paint.setColor(SK_ColorYELLOW);
478        paint.setShader(linear)->unref();
479        paint.setPathEffect(pathEffectTest())->unref();
480		canvas->drawRect(rect, paint);
481        paint.setPathEffect(NULL);
482
483        // circle w/ emboss & transparent (exercises 3dshader)
484		canvas->translate(SkIntToScalar(50), 0);
485        paint.setMaskFilter(embossFilter)->unref();
486        canvas->drawOval(rect, paint);
487		canvas->translate(SkIntToScalar(10), SkIntToScalar(10));
488        paint.setShader(transparentShader)->unref();
489        canvas->drawOval(rect, paint);
490		canvas->translate(0, SkIntToScalar(-10));
491
492        // path
493		canvas->translate(SkIntToScalar(50), 0);
494		paint.setColor(SK_ColorRED);
495		paint.setStyle(SkPaint::kStroke_Style);
496		paint.setStrokeWidth(SkIntToScalar(5));
497        paint.setShader(radial)->unref();
498        paint.setMaskFilter(NULL);
499		canvas->drawPath(path, paint);
500
501        paint.setShader(NULL);
502        // bitmap, sprite
503		canvas->translate(SkIntToScalar(50), 0);
504		paint.setStyle(SkPaint::kFill_Style);
505		canvas->drawBitmap(fBug, left, top, &paint);
506		canvas->translate(SkIntToScalar(30), 0);
507		canvas->drawSprite(fTb,
508			SkScalarRound(canvas->getTotalMatrix().getTranslateX()),
509            spriteOffset + 10, &paint);
510
511		canvas->translate(-SkIntToScalar(30), SkIntToScalar(30));
512        paint.setShader(shaderTest())->unref(); // test compose shader
513		canvas->drawRect(rect2, paint);
514        paint.setShader(NULL);
515
516        canvas->restore();
517        // text
518		canvas->translate(0, SkIntToScalar(60));
519        canvas->save();
520		paint.setColor(SK_ColorGRAY);
521		canvas->drawPosText(ascii, asciiLength, pos.begin(), paint);
522		canvas->drawPosText(ascii, asciiLength, pos2.begin(), paint);
523
524		canvas->translate(SkIntToScalar(50), 0);
525		paint.setColor(SK_ColorCYAN);
526		canvas->drawText(utf8, sizeof(utf8) - 1, x, y, paint);
527
528		canvas->translate(SkIntToScalar(30), 0);
529		paint.setColor(SK_ColorMAGENTA);
530		paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
531        matrix.setTranslate(SkIntToScalar(10), SkIntToScalar(10));
532		canvas->drawTextOnPath((void*) utf16, sizeof(utf16), path, &matrix, paint);
533		canvas->translate(0, SkIntToScalar(20));
534		canvas->drawTextOnPath((void*) utf16simple, sizeof(utf16simple), path, &matrix, paint);
535        canvas->restore();
536
537        canvas->translate(0, SkIntToScalar(60));
538		paint.setTextEncoding(SkPaint::kUTF8_TextEncoding);
539        canvas->restore();
540    }
541
542    /*
543./SkColorFilter.h:25:class SkColorFilter : public SkFlattenable { -- abstract
544    static SkColorFilter* CreatXfermodeFilter() *** untested ***
545    static SkColorFilter* CreatePorterDuffFilter() *** untested ***
546    static SkColorFilter* CreateLightingFilter() -- tested
547./SkDrawLooper.h:9:class SkDrawLooper : public SkFlattenable { -- virtually abstract
548    ./SkBlurDrawLooper.h:9:class SkBlurDrawLooper : public SkDrawLooper { *** untested ***
549./SkMaskFilter.h:41:class SkMaskFilter : public SkFlattenable { -- abstract chmod +w .h
550    ./SkEmbossMaskFilter.h:27:class SkEmbossMaskFilter : public SkMaskFilter { -- tested
551./SkPathEffect.h:33:class SkPathEffect : public SkFlattenable { -- abstract
552    ./Sk1DPathEffect.h:27:class Sk1DPathEffect : public SkPathEffect { -- abstract
553        ./Sk1DPathEffect.h:48:class SkPath1DPathEffect : public Sk1DPathEffect { -- tested
554    ./Sk2DPathEffect.h:25:class Sk2DPathEffect : public SkPathEffect { *** untested ***
555    ./SkCornerPathEffect.h:28:class SkCornerPathEffect : public SkPathEffect { *** untested ***
556    ./SkDashPathEffect.h:27:class SkDashPathEffect : public SkPathEffect {
557    ./SkDiscretePathEffect.h:27:class SkDiscretePathEffect : public SkPathEffect {
558    ./SkPaint.h:760:class SkStrokePathEffect : public SkPathEffect {
559    ./SkPathEffect.h:58:class SkPairPathEffect : public SkPathEffect {
560        ./SkPathEffect.h:78:class SkComposePathEffect : public SkPairPathEffect {
561        ./SkPathEffect.h:114:class SkSumPathEffect : public SkPairPathEffect {
562./SkRasterizer.h:29:class SkRasterizer : public SkFlattenable {
563    ./SkLayerRasterizer.h:27:class SkLayerRasterizer : public SkRasterizer {
564./SkShader.h:36:class SkShader : public SkFlattenable {
565    ./SkColorFilter.h:59:class SkFilterShader : public SkShader {
566    ./SkColorShader.h:26:class SkColorShader : public SkShader {
567    ./SkShaderExtras.h:31:class SkComposeShader : public SkShader {
568    ./SkTransparentShader.h:23:class SkTransparentShader : public SkShader {
569./SkUnitMapper.h:24:class SkUnitMapper : public SkFlattenable {
570    ./SkUnitMapper.h:33:class SkDiscreteMapper : public SkUnitMapper {
571    ./SkUnitMapper.h:51:class SkFlipCosineMapper : public SkUnitMapper {
572./SkXfermode.h:32:class SkXfermode : public SkFlattenable {
573    ./SkAvoidXfermode.h:28:class SkAvoidXfermode : public SkXfermode { *** not done *** chmod +w .h .cpp
574    ./SkXfermode.h:54:class SkProcXfermode : public SkXfermode {
575    */
576
577    /*
578./SkBlurMaskFilter.h:25:class SkBlurMaskFilter {
579    chmod +w SkBlurMaskFilter.cpp
580./SkGradientShader.h:30:class SkGradientShader {
581    */
582        // save layer, bounder, looper
583        // matrix
584        // clip /path/region
585        // bitmap proc shader ?
586
587/* untested:
588SkCornerPathEffect.h:28:class SkCornerPathEffect : public SkPathEffect {
589*/
590
591    virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {
592        fClickPt.set(x, y);
593        this->inval(NULL);
594        return this->INHERITED::onFindClickHandler(x, y);
595    }
596
597    SkPathEffect* pathEffectTest() {
598        static const int gXY[] = { 1, 0, 0, -1, 2, -1, 3, 0, 2, 1, 0, 1 };
599        SkScalar gPhase = 0;
600        SkPath path;
601        path.moveTo(SkIntToScalar(gXY[0]), SkIntToScalar(gXY[1]));
602        for (unsigned i = 2; i < SK_ARRAY_COUNT(gXY); i += 2)
603            path.lineTo(SkIntToScalar(gXY[i]), SkIntToScalar(gXY[i+1]));
604        path.close();
605        path.offset(SkIntToScalar(-6), 0);
606        SkPathEffect* outer = new SkPath1DPathEffect(path, SkIntToScalar(12),
607            gPhase, SkPath1DPathEffect::kRotate_Style);
608        SkPathEffect* inner = new SkDiscretePathEffect(SkIntToScalar(2),
609            SkIntToScalar(1)/10); // SkCornerPathEffect(SkIntToScalar(2));
610        SkPathEffect* result = new SkComposePathEffect(outer, inner);
611        outer->unref();
612        inner->unref();
613        return result;
614    }
615
616    SkPathEffect* pathEffectTest2() { // unsure this works (has no visible effect)
617        SkPathEffect* outer = new SkStrokePathEffect(SkIntToScalar(4),
618            SkPaint::kStroke_Style, SkPaint::kMiter_Join, SkPaint::kButt_Cap);
619        static const SkScalar intervals[] = {SkIntToScalar(1), SkIntToScalar(2),
620            SkIntToScalar(2), SkIntToScalar(1)};
621        SkPathEffect* inner = new SkDashPathEffect(intervals,
622            sizeof(intervals) / sizeof(intervals[0]), 0);
623        SkPathEffect* result = new SkSumPathEffect(outer, inner);
624        outer->unref();
625        inner->unref();
626        return result;
627    }
628
629    SkShader* shaderTest() {
630        SkPoint pts[] = { { 0, 0, }, { SkIntToScalar(100), 0 } };
631        SkColor colors[] = { SK_ColorRED, SK_ColorBLUE };
632        SkShader* shaderA = SkGradientShader::CreateLinear(pts, colors, NULL,
633            2, SkShader::kClamp_TileMode);
634        pts[1].set(0, SkIntToScalar(100));
635        SkColor colors2[] = {SK_ColorBLACK,  SkColorSetARGB(0x80, 0, 0, 0)};
636        SkShader* shaderB = SkGradientShader::CreateLinear(pts, colors2, NULL,
637            2, SkShader::kClamp_TileMode);
638        SkXfermode* mode = SkXfermode::Create(SkXfermode::kDstIn_Mode);
639        SkShader* result = new SkComposeShader(shaderA, shaderB, mode);
640        shaderA->unref();
641        shaderB->unref();
642        mode->unref();
643        return result;
644    }
645
646    virtual void startTest() {
647		SkImageDecoder::DecodeFile("/Users/caryclark/Desktop/bugcirc.gif", &fBug);
648		SkImageDecoder::DecodeFile("/Users/caryclark/Desktop/tbcirc.gif", &fTb);
649		SkImageDecoder::DecodeFile("/Users/caryclark/Desktop/05psp04.gif", &fTx);
650	}
651
652    void drawRaster(SkCanvas* canvas)  {
653        for (size_t index = 0; index < SK_ARRAY_COUNT(gRastProcs); index++)
654            drawOneRaster(canvas);
655    }
656
657    void drawOneRaster(SkCanvas* canvas) {
658        canvas->save();
659
660        SkScalar    x = SkIntToScalar(20);
661        SkScalar    y = SkIntToScalar(40);
662        SkPaint     paint;
663
664        paint.setAntiAlias(true);
665        paint.setTextSize(SkIntToScalar(48));
666        paint.setTypeface(SkTypeface::CreateFromName("sans-serif",
667                                                     SkTypeface::kBold));
668
669        SkString str("GOOGLE");
670
671        for (size_t i = 0; i < SK_ARRAY_COUNT(gRastProcs); i++) {
672            apply_shader(&paint, i);
673
674          //  paint.setMaskFilter(NULL);
675          //  paint.setColor(SK_ColorBLACK);
676
677#if 01
678            int index = i % SK_ARRAY_COUNT(gLightingColors);
679            paint.setColorFilter(SkColorFilter::CreateLightingFilter(
680                                    gLightingColors[index].fMul,
681                                    gLightingColors[index].fAdd))->unref();
682#endif
683
684            canvas->drawText(str.c_str(), str.size(), x, y, paint);
685            SkRect  oval = { x, y - SkIntToScalar(40), x + SkIntToScalar(40), y };
686            paint.setStyle(SkPaint::kStroke_Style);
687            canvas->drawOval(oval, paint);
688            paint.setStyle(SkPaint::kFill_Style);
689
690            y += paint.getFontSpacing();
691        }
692
693        canvas->restore();
694
695        if (1) {
696            SkAvoidXfermode   mode(SK_ColorWHITE, 0xFF,
697                                   SkAvoidXfermode::kTargetColor_Mode);
698            SkPaint paint;
699            x += SkIntToScalar(20);
700            SkRect  r = { x, 0, x + SkIntToScalar(360), SkIntToScalar(700) };
701            paint.setXfermode(&mode);
702            paint.setColor(SK_ColorGREEN);
703            paint.setAntiAlias(true);
704            canvas->drawOval(r, paint);
705        }
706    }
707
708private:
709    SkPoint fClickPt;
710    SkBitmap fBug, fTb, fTx;
711    typedef SampleView INHERITED;
712};
713
714//////////////////////////////////////////////////////////////////////////////
715
716static SkView* MyFactory() { return new DemoView; }
717static SkViewRegister reg(MyFactory);
718
719