Home | History | Annotate | Download | only in samplecode
      1 /*
      2  * Copyright 2015 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 
      8 #include "SampleCode.h"
      9 #include "SkAnimTimer.h"
     10 #include "SkDrawable.h"
     11 #include "SkView.h"
     12 #include "SkCanvas.h"
     13 #include "SkDrawable.h"
     14 #include "SkPath.h"
     15 #include "SkRandom.h"
     16 #include "SkRSXform.h"
     17 #include "SkSurface.h"
     18 #include "SkGradientShader.h"
     19 
     20 const struct {
     21     SkXfermode::Mode fMode;
     22     const char*      fName;
     23 } gModes[] = {
     24     { SkXfermode::kSrcOver_Mode, "src-over" },
     25     { SkXfermode::kSrc_Mode,     "src" },
     26     { SkXfermode::kSrcIn_Mode,   "src-in" },
     27     { SkXfermode::kSrcOut_Mode,  "src-out" },
     28     { SkXfermode::kSrcATop_Mode, "src-atop" },
     29     { SkXfermode::kDstOver_Mode, "dst-over" },
     30     { SkXfermode::kDstIn_Mode,   "dst-in" },
     31     { SkXfermode::kDstOut_Mode,  "dst-out" },
     32     { SkXfermode::kDstATop_Mode, "dst-atop" },
     33 };
     34 const int N_Modes = SK_ARRAY_COUNT(gModes);
     35 
     36 class HasEventWig : public SkView {
     37 public:
     38     void postWidgetEvent() {
     39         SkEvent evt;
     40         this->onPrepareWidEvent(&evt);
     41         this->postToListeners(evt, 0);
     42     }
     43 
     44 protected:
     45     virtual void onPrepareWidEvent(SkEvent*) {}
     46 };
     47 
     48 static SkRandom gRand;
     49 
     50 class PushButtonWig : public HasEventWig {
     51     SkString fLabel;
     52     SkColor  fColor;
     53     uint32_t fFast32;
     54 
     55 public:
     56     PushButtonWig(const char label[], uint32_t fast) : fLabel(label) {
     57         fColor = (gRand.nextU() & 0x7F7F7F7F) | SkColorSetARGB(0xFF, 0, 0, 0x80);
     58         fFast32 = fast;
     59     }
     60 
     61 protected:
     62     void onPrepareWidEvent(SkEvent* evt) override {
     63         evt->setType("push-button");
     64         evt->setFast32(fFast32);
     65         evt->setString("label", fLabel.c_str());
     66     }
     67 
     68 //    bool onEvent(const SkEvent&) override;
     69     void onDraw(SkCanvas* canvas) override {
     70         SkRect r;
     71         this->getLocalBounds(&r);
     72         SkPaint paint;
     73         paint.setAntiAlias(true);
     74         paint.setColor(fColor);
     75         canvas->drawRoundRect(r, 8, 8, paint);
     76 
     77         paint.setColor(0xFFFFFFFF);
     78         paint.setTextSize(16);
     79         paint.setTextAlign(SkPaint::kCenter_Align);
     80         paint.setLCDRenderText(true);
     81         canvas->drawText(fLabel.c_str(), fLabel.size(), r.centerX(), r.fTop + 0.68f * r.height(), paint);
     82     }
     83 
     84     Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) override {
     85         return new Click(this);
     86     }
     87 
     88     bool onClick(Click* click) override {
     89         SkRect target = SkRect::MakeXYWH(click->fCurr.x() - 1, click->fCurr.y() - 1, 3, 3);
     90         SkRect r;
     91         this->getLocalBounds(&r);
     92         if (r.intersects(target)) {
     93             fColor = SkColorSetA(fColor, 0x99);
     94         } else {
     95             fColor = SkColorSetA(fColor, 0xFF);
     96         }
     97         this->inval(nullptr);
     98 
     99         if (click->fState == SkView::Click::kUp_State) {
    100             this->postWidgetEvent();
    101         }
    102         return true;
    103     }
    104 
    105 private:
    106     typedef HasEventWig INHERITED;
    107 };
    108 
    109 
    110 class ModeDrawable : public SkDrawable {
    111 public:
    112     ModeDrawable() : fMode(SkXfermode::kSrcOver_Mode), fLoc(SkPoint::Make(0, 0)) {}
    113 
    114     SkXfermode::Mode fMode;
    115     SkPoint          fLoc;
    116 
    117     bool hitTest(SkScalar x, SkScalar y) {
    118         SkRect target = SkRect::MakeXYWH(x - fLoc.x() - 1, y - fLoc.y() - 1, 3, 3);
    119         return this->getBounds().intersects(target);
    120     }
    121 };
    122 
    123 class CircDrawable : public ModeDrawable {
    124     SkPaint fPaint;
    125     SkRect  fBounds;
    126 
    127 public:
    128     CircDrawable(SkScalar size, SkColor c) {
    129         const SkColor colors[] = { 0, c };
    130         SkAutoTUnref<SkShader> shader(SkGradientShader::CreateRadial(SkPoint::Make(size/2, size/2), size/2,
    131                                                                      colors, nullptr, 2,
    132                                                                      SkShader::kClamp_TileMode));
    133         fPaint.setShader(shader);
    134         fBounds = SkRect::MakeWH(size, size);
    135     }
    136 
    137 protected:
    138     SkRect onGetBounds() override {
    139         return fBounds;
    140     }
    141 
    142     void onDraw(SkCanvas* canvas) override {
    143         fPaint.setXfermodeMode(fMode);
    144         canvas->save();
    145         canvas->translate(fLoc.x(), fLoc.y());
    146         canvas->drawOval(fBounds, fPaint);
    147         canvas->restore();
    148     }
    149 };
    150 
    151 class XferDemo : public SampleView {
    152     enum {
    153         N = 4
    154     };
    155 
    156     SkRect        fModeRect[N_Modes];
    157     SkAutoTUnref<CircDrawable> fDrs[N];
    158     CircDrawable* fSelected;
    159 
    160     void addButtons() {
    161         SkScalar x = 10;
    162         SkScalar y = 10;
    163         for (int i = 0; i < N_Modes; ++i) {
    164             SkAutoTUnref<SkView> v(new PushButtonWig(gModes[i].fName, gModes[i].fMode));
    165             v->setSize(70, 25);
    166             v->setLoc(x, y);
    167             v->setVisibleP(true);
    168             v->setEnabledP(true);
    169             v->addListenerID(this->getSinkID());
    170             this->attachChildToFront(v);
    171             fModeRect[i] = SkRect::MakeXYWH(x, y + 28, 70, 2);
    172             x += 80;
    173         }
    174     }
    175 
    176 public:
    177     XferDemo() {
    178         const SkColor colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorBLACK };
    179         for (int i = 0; i < N; ++i) {
    180             fDrs[i].reset(new CircDrawable(200, colors[i]));
    181             fDrs[i]->fLoc.set(100.f + i * 100, 100.f + i * 100);
    182             fDrs[i]->fMode = SkXfermode::kSrcOver_Mode;
    183         }
    184         fSelected = nullptr;
    185 
    186         this->addButtons();
    187     }
    188 
    189 protected:
    190     bool onEvent(const SkEvent& evt) override {
    191         if (evt.isType("push-button")) {
    192             if (fSelected) {
    193                 fSelected->fMode = (SkXfermode::Mode)evt.getFast32();
    194                 this->inval(nullptr);
    195             }
    196             return true;
    197         }
    198         return this->INHERITED::onEvent(evt);
    199     }
    200 
    201     bool onQuery(SkEvent* evt) override {
    202         if (SampleCode::TitleQ(*evt)) {
    203             SampleCode::TitleR(evt, "XferDemo");
    204             return true;
    205         }
    206         return this->INHERITED::onQuery(evt);
    207     }
    208 
    209     void onDrawContent(SkCanvas* canvas) override {
    210         SkPaint paint;
    211         if (fSelected) {
    212             for (int i = 0; i < N_Modes; ++i) {
    213                 if (fSelected->fMode == gModes[i].fMode) {
    214                     canvas->drawRect(fModeRect[i], paint);
    215                     break;
    216                 }
    217             }
    218         }
    219 
    220         canvas->saveLayer(nullptr, nullptr);
    221         for (int i = 0; i < N; ++i) {
    222             fDrs[i]->draw(canvas);
    223         }
    224         canvas->restore();
    225     }
    226 
    227     SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned) override {
    228         fSelected = nullptr;
    229         for (int i = N - 1; i >= 0; --i) {
    230             if (fDrs[i]->hitTest(x, y)) {
    231                 fSelected = fDrs[i];
    232                 break;
    233             }
    234         }
    235         this->inval(nullptr);
    236         return fSelected ? new Click(this) : nullptr;
    237     }
    238 
    239     bool onClick(Click* click) override {
    240         fSelected->fLoc.fX += click->fCurr.fX - click->fPrev.fX;
    241         fSelected->fLoc.fY += click->fCurr.fY - click->fPrev.fY;
    242         this->inval(nullptr);
    243         return true;
    244     }
    245 
    246 private:
    247     typedef SampleView INHERITED;
    248 };
    249 
    250 //////////////////////////////////////////////////////////////////////////////
    251 
    252 DEF_SAMPLE( return new XferDemo; )
    253