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