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