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 #ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
    176     Dot2DPathEffect(SkReadBuffer& buffer) : INHERITED(buffer) {
    177         fRadius = buffer.readScalar();
    178     }
    179 #endif
    180     virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE {
    181         this->INHERITED::flatten(buffer);
    182         buffer.writeScalar(fRadius);
    183     }
    184 
    185 private:
    186     SkScalar fRadius;
    187 
    188     typedef Sk2DPathEffect INHERITED;
    189 };
    190 
    191 static void r7(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) {
    192     SkMatrix    lattice;
    193     lattice.setScale(SK_Scalar1*6, SK_Scalar1*6, 0, 0);
    194     lattice.postSkew(SK_Scalar1/3, 0, 0, 0);
    195     p.setPathEffect(new Dot2DPathEffect(SK_Scalar1*4, lattice))->unref();
    196     rastBuilder->addLayer(p);
    197 }
    198 
    199 static void r8(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) {
    200     rastBuilder->addLayer(p);
    201 
    202     SkMatrix    lattice;
    203     lattice.setScale(SK_Scalar1*6, SK_Scalar1*6, 0, 0);
    204     lattice.postSkew(SK_Scalar1/3, 0, 0, 0);
    205     p.setPathEffect(new Dot2DPathEffect(SK_Scalar1*2, lattice))->unref();
    206     p.setXfermodeMode(SkXfermode::kClear_Mode);
    207     rastBuilder->addLayer(p);
    208 
    209     p.setPathEffect(NULL);
    210     p.setXfermode(NULL);
    211     p.setStyle(SkPaint::kStroke_Style);
    212     p.setStrokeWidth(SK_Scalar1);
    213     rastBuilder->addLayer(p);
    214 }
    215 
    216 static void r9(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) {
    217     rastBuilder->addLayer(p);
    218 
    219     SkMatrix    lattice;
    220     lattice.setScale(SK_Scalar1, SK_Scalar1*6, 0, 0);
    221     lattice.postRotate(SkIntToScalar(30), 0, 0);
    222     p.setPathEffect(SkLine2DPathEffect::Create(SK_Scalar1*2, lattice))->unref();
    223     p.setXfermodeMode(SkXfermode::kClear_Mode);
    224     rastBuilder->addLayer(p);
    225 
    226     p.setPathEffect(NULL);
    227     p.setXfermode(NULL);
    228     p.setStyle(SkPaint::kStroke_Style);
    229     p.setStrokeWidth(SK_Scalar1);
    230     rastBuilder->addLayer(p);
    231 }
    232 
    233 typedef void (*raster_proc)(SkLayerRasterizer::Builder*, SkPaint&);
    234 
    235 static const raster_proc gRastProcs[] = {
    236     r0, r1, r2, r3, r4, r5, r6, r7, r8, r9
    237 };
    238 
    239 static const struct {
    240     SkColor fMul, fAdd;
    241 } gLightingColors[] = {
    242     { 0x808080, 0x800000 }, // general case
    243     { 0x707070, 0x707070 }, // no-pin case
    244     { 0xFFFFFF, 0x800000 }, // just-add case
    245     { 0x808080, 0x000000 }, // just-mul case
    246     { 0xFFFFFF, 0x000000 }  // identity case
    247 };
    248 
    249 static void apply_shader(SkPaint* paint, int index) {
    250     raster_proc proc = gRastProcs[index];
    251     if (proc) {
    252         SkPaint p;
    253         SkLayerRasterizer::Builder rastBuilder;
    254 
    255         p.setAntiAlias(true);
    256         proc(&rastBuilder, p);
    257         paint->setRasterizer(rastBuilder.detachRasterizer())->unref();
    258     }
    259 
    260 #if 1
    261     SkScalar dir[] = { SK_Scalar1, SK_Scalar1, SK_Scalar1 };
    262     paint->setMaskFilter(SkBlurMaskFilter::CreateEmboss(
    263                 SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(3)), dir,
    264                 SK_Scalar1/4, SkIntToScalar(4)))->unref();
    265     paint->setColor(SK_ColorBLUE);
    266 #endif
    267 }
    268 
    269 class DemoView : public SampleView {
    270 public:
    271     DemoView() {}
    272 
    273 protected:
    274     // overrides from SkEventSink
    275     virtual bool onQuery(SkEvent* evt) {
    276         if (SampleCode::TitleQ(*evt)) {
    277             SampleCode::TitleR(evt, "Demo");
    278             return true;
    279         }
    280         return this->INHERITED::onQuery(evt);
    281     }
    282 
    283     virtual bool onClick(Click* click) {
    284         return this->INHERITED::onClick(click);
    285     }
    286 
    287     void makePath(SkPath& path) {
    288         path.addCircle(SkIntToScalar(20), SkIntToScalar(20), SkIntToScalar(20),
    289             SkPath::kCCW_Direction);
    290         for (int index = 0; index < 10; index++) {
    291             SkScalar x = (float) cos(index / 10.0f * 2 * 3.1415925358f);
    292             SkScalar y = (float) sin(index / 10.0f * 2 * 3.1415925358f);
    293             x *= index & 1 ? 7 : 14;
    294             y *= index & 1 ? 7 : 14;
    295             x += SkIntToScalar(20);
    296             y += SkIntToScalar(20);
    297             if (index == 0)
    298                 path.moveTo(x, y);
    299             else
    300                 path.lineTo(x, y);
    301         }
    302         path.close();
    303     }
    304 
    305     virtual void onDrawContent(SkCanvas* canvas) {
    306         canvas->save();
    307         this->drawPicture(canvas, 0);
    308         canvas->restore();
    309 
    310         {
    311             SkPictureRecorder recorder;
    312             {
    313                 SkCanvas* record = recorder.beginRecording(320, 480, NULL, 0);
    314                 this->drawPicture(record, 120);
    315             }
    316             SkAutoTUnref<SkPicture> picture(recorder.endRecording());
    317 
    318             canvas->translate(0, SkIntToScalar(120));
    319 
    320             SkRect clip;
    321             clip.set(0, 0, SkIntToScalar(160), SkIntToScalar(160));
    322             do {
    323                 canvas->save();
    324                 canvas->clipRect(clip);
    325                 picture->playback(canvas);
    326                 canvas->restore();
    327                 if (clip.fRight < SkIntToScalar(320))
    328                     clip.offset(SkIntToScalar(160), 0);
    329                 else if (clip.fBottom < SkIntToScalar(480))
    330                     clip.offset(-SkIntToScalar(320), SkIntToScalar(160));
    331                 else
    332                     break;
    333             } while (true);
    334         }
    335     }
    336 
    337     void drawPicture(SkCanvas* canvas, int spriteOffset) {
    338         SkMatrix matrix; matrix.reset();
    339         SkPaint paint;
    340         SkPath path;
    341         SkPoint start = {0, 0};
    342         SkPoint stop = { SkIntToScalar(40), SkIntToScalar(40) };
    343         SkRect rect = {0, 0, SkIntToScalar(40), SkIntToScalar(40) };
    344         SkRect rect2 = {0, 0, SkIntToScalar(65), SkIntToScalar(20) };
    345         SkScalar left = 0, top = 0, x = 0, y = 0;
    346         int index;
    347 
    348         char ascii[] = "ascii...";
    349         int asciiLength = sizeof(ascii) - 1;
    350         char utf8[] = "utf8" "\xe2\x80\xa6";
    351         short utf16[] = {'u', 't', 'f', '1', '6', 0x2026 };
    352         short utf16simple[] = {'u', 't', 'f', '1', '6', '!' };
    353 
    354         makePath(path);
    355         SkTDArray<SkPoint>(pos);
    356         pos.setCount(asciiLength);
    357         for (index = 0;  index < asciiLength; index++)
    358             pos[index].set(SkIntToScalar((unsigned int)index * 10),
    359                                        SkIntToScalar((unsigned int)index * 2));
    360         SkTDArray<SkPoint>(pos2);
    361         pos2.setCount(asciiLength);
    362         for (index = 0;  index < asciiLength; index++)
    363             pos2[index].set(SkIntToScalar((unsigned int)index * 10),
    364                                         SkIntToScalar(20));
    365 
    366         // shaders
    367         SkPoint linearPoints[] = { { 0, 0, }, { SkIntToScalar(40), SkIntToScalar(40) } };
    368         SkColor linearColors[] = { SK_ColorRED, SK_ColorBLUE };
    369         SkScalar* linearPos = NULL;
    370         int linearCount = 2;
    371         SkShader::TileMode linearMode = SkShader::kMirror_TileMode;
    372         SkShader* linear = SkGradientShader::CreateLinear(linearPoints,
    373             linearColors, linearPos, linearCount, linearMode);
    374 
    375         SkPoint radialCenter = { SkIntToScalar(25), SkIntToScalar(25) };
    376         SkScalar radialRadius = SkIntToScalar(25);
    377         SkColor radialColors[] = { SK_ColorGREEN, SK_ColorGRAY, SK_ColorRED };
    378         SkScalar radialPos[] = { 0, SkIntToScalar(3) / 5, SkIntToScalar(1)};
    379         int radialCount = 3;
    380         SkShader::TileMode radialMode = SkShader::kRepeat_TileMode;
    381         SkShader* radial = SkGradientShader::CreateRadial(radialCenter,
    382             radialRadius, radialColors, radialPos, radialCount,
    383             radialMode);
    384 
    385         SkTransparentShader* transparentShader = new SkTransparentShader();
    386         SkEmbossMaskFilter::Light light;
    387         light.fDirection[0] = SK_Scalar1/2;
    388         light.fDirection[1] = SK_Scalar1/2;
    389         light.fDirection[2] = SK_Scalar1/3;
    390         light.fAmbient        = 0x48;
    391         light.fSpecular        = 0x80;
    392         SkScalar sigma = SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(12)/5);
    393         SkEmbossMaskFilter* embossFilter = SkEmbossMaskFilter::Create(sigma, light);
    394 
    395         SkXfermode* xfermode = SkXfermode::Create(SkXfermode::kXor_Mode);
    396         SkColorFilter* lightingFilter = SkColorFilter::CreateLightingFilter(
    397             0xff89bc45, 0xff112233);
    398 
    399         canvas->save();
    400         canvas->translate(SkIntToScalar(0), SkIntToScalar(5));
    401         paint.setAntiAlias(true);
    402         paint.setFilterLevel(SkPaint::kLow_FilterLevel);
    403         // !!! draw through a clip
    404         paint.setColor(SK_ColorLTGRAY);
    405         paint.setStyle(SkPaint::kFill_Style);
    406         SkRect clip = {0, 0, SkIntToScalar(320), SkIntToScalar(120)};
    407         canvas->clipRect(clip);
    408         paint.setShader(SkShader::CreateBitmapShader(fTx,
    409             SkShader::kMirror_TileMode, SkShader::kRepeat_TileMode))->unref();
    410         canvas->drawPaint(paint);
    411         canvas->save();
    412 
    413         // line (exercises xfermode, colorShader, colorFilter, filterShader)
    414         paint.setColor(SK_ColorGREEN);
    415         paint.setStrokeWidth(SkIntToScalar(10));
    416         paint.setStyle(SkPaint::kStroke_Style);
    417         paint.setXfermode(xfermode)->unref();
    418         paint.setColorFilter(lightingFilter)->unref();
    419         canvas->drawLine(start.fX, start.fY, stop.fX, stop.fY, paint); // should not be green
    420         paint.setXfermode(NULL);
    421         paint.setColorFilter(NULL);
    422 
    423         // rectangle
    424         paint.setStyle(SkPaint::kFill_Style);
    425         canvas->translate(SkIntToScalar(50), 0);
    426         paint.setColor(SK_ColorYELLOW);
    427         paint.setShader(linear)->unref();
    428         paint.setPathEffect(pathEffectTest())->unref();
    429         canvas->drawRect(rect, paint);
    430         paint.setPathEffect(NULL);
    431 
    432         // circle w/ emboss & transparent (exercises 3dshader)
    433         canvas->translate(SkIntToScalar(50), 0);
    434         paint.setMaskFilter(embossFilter)->unref();
    435         canvas->drawOval(rect, paint);
    436         canvas->translate(SkIntToScalar(10), SkIntToScalar(10));
    437         paint.setShader(transparentShader)->unref();
    438         canvas->drawOval(rect, paint);
    439         canvas->translate(0, SkIntToScalar(-10));
    440 
    441         // path
    442         canvas->translate(SkIntToScalar(50), 0);
    443         paint.setColor(SK_ColorRED);
    444         paint.setStyle(SkPaint::kStroke_Style);
    445         paint.setStrokeWidth(SkIntToScalar(5));
    446         paint.setShader(radial)->unref();
    447         paint.setMaskFilter(NULL);
    448         canvas->drawPath(path, paint);
    449 
    450         paint.setShader(NULL);
    451         // bitmap, sprite
    452         canvas->translate(SkIntToScalar(50), 0);
    453         paint.setStyle(SkPaint::kFill_Style);
    454         canvas->drawBitmap(fBug, left, top, &paint);
    455         canvas->translate(SkIntToScalar(30), 0);
    456         canvas->drawSprite(fTb,
    457             SkScalarRoundToInt(canvas->getTotalMatrix().getTranslateX()),
    458             spriteOffset + 10, &paint);
    459 
    460         canvas->translate(-SkIntToScalar(30), SkIntToScalar(30));
    461         paint.setShader(shaderTest())->unref(); // test compose shader
    462         canvas->drawRect(rect2, paint);
    463         paint.setShader(NULL);
    464 
    465         canvas->restore();
    466         // text
    467         canvas->translate(0, SkIntToScalar(60));
    468         canvas->save();
    469         paint.setColor(SK_ColorGRAY);
    470         canvas->drawPosText(ascii, asciiLength, pos.begin(), paint);
    471         canvas->drawPosText(ascii, asciiLength, pos2.begin(), paint);
    472 
    473         canvas->translate(SkIntToScalar(50), 0);
    474         paint.setColor(SK_ColorCYAN);
    475         canvas->drawText(utf8, sizeof(utf8) - 1, x, y, paint);
    476 
    477         canvas->translate(SkIntToScalar(30), 0);
    478         paint.setColor(SK_ColorMAGENTA);
    479         paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
    480         matrix.setTranslate(SkIntToScalar(10), SkIntToScalar(10));
    481         canvas->drawTextOnPath((void*) utf16, sizeof(utf16), path, &matrix, paint);
    482         canvas->translate(0, SkIntToScalar(20));
    483         canvas->drawTextOnPath((void*) utf16simple, sizeof(utf16simple), path, &matrix, paint);
    484         canvas->restore();
    485 
    486         canvas->translate(0, SkIntToScalar(60));
    487         paint.setTextEncoding(SkPaint::kUTF8_TextEncoding);
    488         canvas->restore();
    489     }
    490 
    491     virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) {
    492         fClickPt.set(x, y);
    493         this->inval(NULL);
    494         return this->INHERITED::onFindClickHandler(x, y, modi);
    495     }
    496 
    497     SkPathEffect* pathEffectTest() {
    498         static const int gXY[] = { 1, 0, 0, -1, 2, -1, 3, 0, 2, 1, 0, 1 };
    499         SkScalar gPhase = 0;
    500         SkPath path;
    501         path.moveTo(SkIntToScalar(gXY[0]), SkIntToScalar(gXY[1]));
    502         for (unsigned i = 2; i < SK_ARRAY_COUNT(gXY); i += 2)
    503             path.lineTo(SkIntToScalar(gXY[i]), SkIntToScalar(gXY[i+1]));
    504         path.close();
    505         path.offset(SkIntToScalar(-6), 0);
    506         SkPathEffect* outer = SkPath1DPathEffect::Create(path, SkIntToScalar(12),
    507             gPhase, SkPath1DPathEffect::kRotate_Style);
    508         SkPathEffect* inner = SkDiscretePathEffect::Create(SkIntToScalar(2),
    509             SkIntToScalar(1)/10); // SkCornerPathEffect(SkIntToScalar(2));
    510         SkPathEffect* result = SkComposePathEffect::Create(outer, inner);
    511         outer->unref();
    512         inner->unref();
    513         return result;
    514     }
    515 
    516     SkShader* shaderTest() {
    517         SkPoint pts[] = { { 0, 0, }, { SkIntToScalar(100), 0 } };
    518         SkColor colors[] = { SK_ColorRED, SK_ColorBLUE };
    519         SkShader* shaderA = SkGradientShader::CreateLinear(pts, colors, NULL,
    520             2, SkShader::kClamp_TileMode);
    521         pts[1].set(0, SkIntToScalar(100));
    522         SkColor colors2[] = {SK_ColorBLACK,  SkColorSetARGB(0x80, 0, 0, 0)};
    523         SkShader* shaderB = SkGradientShader::CreateLinear(pts, colors2, NULL,
    524             2, SkShader::kClamp_TileMode);
    525         SkXfermode* mode = SkXfermode::Create(SkXfermode::kDstIn_Mode);
    526         SkShader* result = new SkComposeShader(shaderA, shaderB, mode);
    527         shaderA->unref();
    528         shaderB->unref();
    529         mode->unref();
    530         return result;
    531     }
    532 
    533     virtual void startTest() {
    534         SkImageDecoder::DecodeFile("/Users/caryclark/Desktop/bugcirc.gif", &fBug);
    535         SkImageDecoder::DecodeFile("/Users/caryclark/Desktop/tbcirc.gif", &fTb);
    536         SkImageDecoder::DecodeFile("/Users/caryclark/Desktop/05psp04.gif", &fTx);
    537     }
    538 
    539     void drawRaster(SkCanvas* canvas)  {
    540         for (size_t index = 0; index < SK_ARRAY_COUNT(gRastProcs); index++)
    541             drawOneRaster(canvas);
    542     }
    543 
    544     void drawOneRaster(SkCanvas* canvas) {
    545         canvas->save();
    546 
    547         SkScalar    x = SkIntToScalar(20);
    548         SkScalar    y = SkIntToScalar(40);
    549         SkPaint     paint;
    550 
    551         paint.setAntiAlias(true);
    552         paint.setTextSize(SkIntToScalar(48));
    553         paint.setTypeface(SkTypeface::CreateFromName("sans-serif",
    554                                                      SkTypeface::kBold));
    555 
    556         SkString str("GOOGLE");
    557 
    558         for (size_t i = 0; i < SK_ARRAY_COUNT(gRastProcs); i++) {
    559             apply_shader(&paint, (int)i);
    560 
    561           //  paint.setMaskFilter(NULL);
    562           //  paint.setColor(SK_ColorBLACK);
    563 
    564 #if 01
    565             int index = i % SK_ARRAY_COUNT(gLightingColors);
    566             paint.setColorFilter(SkColorFilter::CreateLightingFilter(
    567                                     gLightingColors[index].fMul,
    568                                     gLightingColors[index].fAdd))->unref();
    569 #endif
    570 
    571             canvas->drawText(str.c_str(), str.size(), x, y, paint);
    572             SkRect  oval = { x, y - SkIntToScalar(40), x + SkIntToScalar(40), y };
    573             paint.setStyle(SkPaint::kStroke_Style);
    574             canvas->drawOval(oval, paint);
    575             paint.setStyle(SkPaint::kFill_Style);
    576 
    577             y += paint.getFontSpacing();
    578         }
    579 
    580         canvas->restore();
    581 
    582         if (1) {
    583             SkAutoTUnref<SkAvoidXfermode> mode(SkAvoidXfermode::Create(SK_ColorWHITE, 0xFF,
    584                                    SkAvoidXfermode::kTargetColor_Mode));
    585             SkPaint paint;
    586             x += SkIntToScalar(20);
    587             SkRect  r = { x, 0, x + SkIntToScalar(360), SkIntToScalar(700) };
    588             paint.setXfermode(mode);
    589             paint.setColor(SK_ColorGREEN);
    590             paint.setAntiAlias(true);
    591             canvas->drawOval(r, paint);
    592         }
    593     }
    594 
    595 private:
    596     SkPoint fClickPt;
    597     SkBitmap fBug, fTb, fTx;
    598     typedef SampleView INHERITED;
    599 };
    600 
    601 //////////////////////////////////////////////////////////////////////////////
    602 
    603 static SkView* MyFactory() { return new DemoView; }
    604 static SkViewRegister reg(MyFactory);
    605