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 "SkString.h"
     18 #include "SkSurface.h"
     19 #include "SkGradientShader.h"
     20 
     21 const SkBlendMode gModes[] = {
     22     SkBlendMode::kSrcOver,
     23     SkBlendMode::kSrc,
     24     SkBlendMode::kSrcIn,
     25     SkBlendMode::kSrcOut,
     26     SkBlendMode::kSrcATop,
     27     SkBlendMode::kDstOver,
     28     SkBlendMode::kDstIn,
     29     SkBlendMode::kDstOut,
     30     SkBlendMode::kDstATop,
     31 };
     32 const int N_Modes = SK_ARRAY_COUNT(gModes);
     33 
     34 static SkRandom gRand;
     35 
     36 struct ModeButton {
     37     SkString fLabel;
     38     SkColor  fColor;
     39     SkRect   fRect;
     40 
     41 public:
     42     void init(const char label[], const SkRect& rect) {
     43         fLabel = label;
     44         fRect = rect;
     45         fColor = (gRand.nextU() & 0x7F7F7F7F) | SkColorSetARGB(0xFF, 0, 0, 0x80);
     46     }
     47 
     48     void draw(SkCanvas* canvas) {
     49         SkPaint paint;
     50         paint.setAntiAlias(true);
     51         paint.setColor(fColor);
     52         canvas->drawRoundRect(fRect, 8, 8, paint);
     53 
     54         paint.setColor(0xFFFFFFFF);
     55         paint.setTextSize(16);
     56         paint.setTextAlign(SkPaint::kCenter_Align);
     57         paint.setLCDRenderText(true);
     58         canvas->drawString(fLabel, fRect.centerX(), fRect.fTop + 0.68f * fRect.height(), paint);
     59     }
     60 
     61     bool hitTest(SkScalar x, SkScalar y) {
     62         return fRect.intersects(x - 1, y - 1, x + 1, y + 1);
     63     }
     64 };
     65 
     66 class ModeDrawable : public SkDrawable {
     67 public:
     68     ModeDrawable() : fMode(SkBlendMode::kSrcOver), fLoc(SkPoint::Make(0, 0)) {}
     69 
     70     SkBlendMode fMode;
     71     SkPoint     fLoc;
     72 
     73     bool hitTest(SkScalar x, SkScalar y) {
     74         SkRect target = SkRect::MakeXYWH(x - fLoc.x() - 1, y - fLoc.y() - 1, 3, 3);
     75         return this->getBounds().intersects(target);
     76     }
     77 };
     78 
     79 class CircDrawable : public ModeDrawable {
     80     SkPaint fPaint;
     81     SkRect  fBounds;
     82 
     83 public:
     84     CircDrawable(SkScalar size, SkColor c) {
     85         const SkColor colors[] = { 0, c };
     86         fPaint.setShader(SkGradientShader::MakeRadial(SkPoint::Make(size/2, size/2), size/2,
     87                                                                      colors, nullptr, 2,
     88                                                                      SkShader::kClamp_TileMode));
     89         fBounds = SkRect::MakeWH(size, size);
     90     }
     91 
     92 protected:
     93     SkRect onGetBounds() override {
     94         return fBounds;
     95     }
     96 
     97     void onDraw(SkCanvas* canvas) override {
     98         fPaint.setBlendMode(fMode);
     99         canvas->save();
    100         canvas->translate(fLoc.x(), fLoc.y());
    101         canvas->drawOval(fBounds, fPaint);
    102         canvas->restore();
    103     }
    104 };
    105 
    106 class XferDemo : public SampleView {
    107     enum {
    108         N = 4
    109     };
    110 
    111     SkRect        fModeRect[N_Modes];
    112     ModeButton    fModeButtons[N_Modes];
    113     sk_sp<CircDrawable> fDrs[N];
    114     CircDrawable* fSelected;
    115 
    116     void addButtons() {
    117         SkScalar x = 10;
    118         SkScalar y = 10;
    119         for (int i = 0; i < N_Modes; ++i) {
    120             fModeButtons[i].init(SkBlendMode_Name(gModes[i]), SkRect::MakeXYWH(x, y, 70, 25));
    121             fModeRect[i] = SkRect::MakeXYWH(x, y + 28, 70, 2);
    122             x += 80;
    123         }
    124     }
    125 
    126 public:
    127     XferDemo() {
    128         const SkColor colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorBLACK };
    129         for (int i = 0; i < N; ++i) {
    130             fDrs[i].reset(new CircDrawable(200, colors[i]));
    131             fDrs[i]->fLoc.set(100.f + i * 100, 100.f + i * 100);
    132             fDrs[i]->fMode = SkBlendMode::kSrcOver;
    133         }
    134         fSelected = nullptr;
    135 
    136         this->addButtons();
    137     }
    138 
    139 protected:
    140     bool onQuery(SkEvent* evt) override {
    141         if (SampleCode::TitleQ(*evt)) {
    142             SampleCode::TitleR(evt, "XferDemo");
    143             return true;
    144         }
    145         return this->INHERITED::onQuery(evt);
    146     }
    147 
    148     void onDrawContent(SkCanvas* canvas) override {
    149         for (int i = 0; i < N_Modes; ++i) {
    150             fModeButtons[i].draw(canvas);
    151         }
    152 
    153         SkPaint paint;
    154         if (fSelected) {
    155             for (int i = 0; i < N_Modes; ++i) {
    156                 if (fSelected->fMode == gModes[i]) {
    157                     canvas->drawRect(fModeRect[i], paint);
    158                     break;
    159                 }
    160             }
    161         }
    162 
    163         canvas->saveLayer(nullptr, nullptr);
    164         for (int i = 0; i < N; ++i) {
    165             fDrs[i]->draw(canvas);
    166         }
    167         canvas->restore();
    168     }
    169 
    170     SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned) override {
    171         // Check mode buttons first
    172         for (int i = 0; i < N_Modes; ++i) {
    173             if (fModeButtons[i].hitTest(x, y)) {
    174                 Click* click = new Click(this);
    175                 click->fMeta.setS32("mode", i);
    176                 return click;
    177             }
    178         }
    179         fSelected = nullptr;
    180         for (int i = N - 1; i >= 0; --i) {
    181             if (fDrs[i]->hitTest(x, y)) {
    182                 fSelected = fDrs[i].get();
    183                 break;
    184             }
    185         }
    186         return fSelected ? new Click(this) : nullptr;
    187     }
    188 
    189     bool onClick(Click* click) override {
    190         int32_t mode;
    191         if (click->fMeta.findS32("mode", &mode)) {
    192             if (fSelected && Click::kUp_State == click->fState) {
    193                 fSelected->fMode = gModes[mode];
    194             }
    195         } else {
    196             fSelected->fLoc.fX += click->fCurr.fX - click->fPrev.fX;
    197             fSelected->fLoc.fY += click->fCurr.fY - click->fPrev.fY;
    198         }
    199         return true;
    200     }
    201 
    202 private:
    203     typedef SampleView INHERITED;
    204 };
    205 
    206 //////////////////////////////////////////////////////////////////////////////
    207 
    208 DEF_SAMPLE( return new XferDemo; )
    209