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: postWidgetEvent()35 void postWidgetEvent() { 36 SkEvent evt; 37 this->onPrepareWidEvent(&evt); 38 this->postToListeners(evt, 0); 39 } 40 41 protected: onPrepareWidEvent(SkEvent *)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: PushButtonWig(const char label[],uint32_t fast)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: onPrepareWidEvent(SkEvent * evt)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; onDraw(SkCanvas * canvas)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->drawString(fLabel, r.centerX(), r.fTop + 0.68f * r.height(), paint); 79 } 80 onFindClickHandler(SkScalar x,SkScalar y,unsigned modi)81 Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) override { 82 return new Click(this); 83 } 84 onClick(Click * click)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: ModeDrawable()109 ModeDrawable() : fMode(SkBlendMode::kSrcOver), fLoc(SkPoint::Make(0, 0)) {} 110 111 SkBlendMode fMode; 112 SkPoint fLoc; 113 hitTest(SkScalar x,SkScalar y)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: CircDrawable(SkScalar size,SkColor c)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: onGetBounds()134 SkRect onGetBounds() override { 135 return fBounds; 136 } 137 onDraw(SkCanvas * canvas)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 addButtons()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: XferDemo()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: onEvent(const SkEvent & evt)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 onQuery(SkEvent * evt)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 onDrawContent(SkCanvas * canvas)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 onFindClickHandler(SkScalar x,SkScalar y,unsigned)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 onClick(Click * click)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