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