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