diff options
author | reed <reed@google.com> | 2015-09-02 19:05:10 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-09-02 19:05:10 -0700 |
commit | 1a9cafff044e5a352c60065e44d64e9d0eb8f92a (patch) | |
tree | c1b6c564c0120a69990f392ad77443cf6c778cb2 /samplecode/SampleXfer.cpp | |
parent | 1dec47a054bb455a3e9dead3518747f9d8164497 (diff) |
add interactive xfer sample
BUG=skia:
TBR=
Review URL: https://codereview.chromium.org/1323223004
Diffstat (limited to 'samplecode/SampleXfer.cpp')
-rw-r--r-- | samplecode/SampleXfer.cpp | 252 |
1 files changed, 252 insertions, 0 deletions
diff --git a/samplecode/SampleXfer.cpp b/samplecode/SampleXfer.cpp new file mode 100644 index 0000000000..221ba5815e --- /dev/null +++ b/samplecode/SampleXfer.cpp @@ -0,0 +1,252 @@ +/* + * Copyright 2015 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SampleCode.h" +#include "SkAnimTimer.h" +#include "SkDrawable.h" +#include "SkView.h" +#include "SkCanvas.h" +#include "SkDrawable.h" +#include "SkPath.h" +#include "SkRandom.h" +#include "SkRSXform.h" +#include "SkSurface.h" +#include "SkGradientShader.h" + +const struct { + SkXfermode::Mode fMode; + const char* fName; +} gModes[] = { + { SkXfermode::kSrcOver_Mode, "src-over" }, + { SkXfermode::kSrc_Mode, "src" }, + { SkXfermode::kSrcIn_Mode, "src-in" }, + { SkXfermode::kSrcOut_Mode, "src-out" }, + { SkXfermode::kSrcATop_Mode, "src-atop" }, + { SkXfermode::kDstOver_Mode, "dst-over" }, + { SkXfermode::kDstIn_Mode, "dst-in" }, + { SkXfermode::kDstOut_Mode, "dst-out" }, + { SkXfermode::kDstATop_Mode, "dst-atop" }, +}; +const int N_Modes = SK_ARRAY_COUNT(gModes); + +class HasEventWig : public SkView { +public: + void postWidgetEvent() { + SkEvent evt; + this->onPrepareWidEvent(&evt); + this->postToListeners(evt, 0); + } + +protected: + virtual void onPrepareWidEvent(SkEvent*) {} +}; + +static SkRandom gRand; + +class PushButtonWig : public HasEventWig { + SkString fLabel; + SkColor fColor; + uint32_t fFast32; + +public: + PushButtonWig(const char label[], uint32_t fast) : fLabel(label) { + fColor = (gRand.nextU() & 0x7F7F7F7F) | SkColorSetARGB(0xFF, 0, 0, 0x80); + fFast32 = fast; + } + +protected: + void onPrepareWidEvent(SkEvent* evt) override { + evt->setType("push-button"); + evt->setFast32(fFast32); + evt->setString("label", fLabel.c_str()); + } + +// bool onEvent(const SkEvent&) override; + void onDraw(SkCanvas* canvas) override { + SkRect r; + this->getLocalBounds(&r); + SkPaint paint; + paint.setAntiAlias(true); + paint.setColor(fColor); + canvas->drawRoundRect(r, 8, 8, paint); + + paint.setColor(0xFFFFFFFF); + paint.setTextSize(16); + paint.setTextAlign(SkPaint::kCenter_Align); + paint.setLCDRenderText(true); + canvas->drawText(fLabel.c_str(), fLabel.size(), r.centerX(), r.fTop + 0.68f * r.height(), paint); + } + + Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) override { + return new Click(this); + } + + bool onClick(Click* click) override { + SkRect target = SkRect::MakeXYWH(click->fCurr.x() - 1, click->fCurr.y() - 1, 3, 3); + SkRect r; + this->getLocalBounds(&r); + if (r.intersects(target)) { + fColor = SkColorSetA(fColor, 0x99); + } else { + fColor = SkColorSetA(fColor, 0xFF); + } + this->inval(nullptr); + + if (click->fState == SkView::Click::kUp_State) { + this->postWidgetEvent(); + } + return true; + } + +private: + typedef HasEventWig INHERITED; +}; + + +class ModeDrawable : public SkDrawable { +public: + ModeDrawable() : fMode(SkXfermode::kSrcOver_Mode), fLoc(SkPoint::Make(0, 0)) {} + + SkXfermode::Mode fMode; + SkPoint fLoc; + + bool hitTest(SkScalar x, SkScalar y) { + SkRect target = SkRect::MakeXYWH(x - fLoc.x() - 1, y - fLoc.y() - 1, 3, 3); + return this->getBounds().intersects(target); + } +}; + +class CircDrawable : public ModeDrawable { + SkPaint fPaint; + SkRect fBounds; + +public: + CircDrawable(SkScalar size, SkColor c) { + const SkColor colors[] = { 0, c }; + SkAutoTUnref<SkShader> shader(SkGradientShader::CreateRadial(SkPoint::Make(size/2, size/2), size/2, + colors, nullptr, 2, + SkShader::kClamp_TileMode)); + fPaint.setShader(shader); + fBounds = SkRect::MakeWH(size, size); + } + +protected: + SkRect onGetBounds() override { + return fBounds; + } + + void onDraw(SkCanvas* canvas) override { + fPaint.setXfermodeMode(fMode); + canvas->save(); + canvas->translate(fLoc.x(), fLoc.y()); + canvas->drawOval(fBounds, fPaint); + canvas->restore(); + } +}; + +class XferDemo : public SampleView { + enum { + N = 4 + }; + + SkRect fModeRect[N_Modes]; + SkAutoTUnref<CircDrawable> fDrs[N]; + CircDrawable* fSelected; + + void addButtons() { + SkScalar x = 10; + SkScalar y = 10; + for (int i = 0; i < N_Modes; ++i) { + SkAutoTUnref<SkView> v(new PushButtonWig(gModes[i].fName, gModes[i].fMode)); + v->setSize(70, 25); + v->setLoc(x, y); + v->setVisibleP(true); + v->setEnabledP(true); + v->addListenerID(this->getSinkID()); + this->attachChildToFront(v); + fModeRect[i] = SkRect::MakeXYWH(x, y + 28, 70, 2); + x += 80; + } + } + +public: + XferDemo() { + const SkColor colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorBLACK }; + for (int i = 0; i < N; ++i) { + fDrs[i].reset(new CircDrawable(200, colors[i])); + fDrs[i]->fLoc.set(100.f + i * 100, 100.f + i * 100); + fDrs[i]->fMode = SkXfermode::kSrcOver_Mode; + } + fSelected = nullptr; + + this->addButtons(); + } + +protected: + bool onEvent(const SkEvent& evt) override { + if (evt.isType("push-button")) { + if (fSelected) { + fSelected->fMode = (SkXfermode::Mode)evt.getFast32(); + this->inval(nullptr); + } + return true; + } + return this->INHERITED::onEvent(evt); + } + + bool onQuery(SkEvent* evt) override { + if (SampleCode::TitleQ(*evt)) { + SampleCode::TitleR(evt, "XferDemo"); + return true; + } + return this->INHERITED::onQuery(evt); + } + + void onDrawContent(SkCanvas* canvas) override { + SkPaint paint; + if (fSelected) { + for (int i = 0; i < N_Modes; ++i) { + if (fSelected->fMode == gModes[i].fMode) { + canvas->drawRect(fModeRect[i], paint); + break; + } + } + } + + canvas->saveLayer(nullptr, nullptr); + for (int i = 0; i < N; ++i) { + fDrs[i]->draw(canvas); + } + canvas->restore(); + } + + SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned) override { + fSelected = nullptr; + for (int i = N - 1; i >= 0; --i) { + if (fDrs[i]->hitTest(x, y)) { + fSelected = fDrs[i]; + break; + } + } + this->inval(nullptr); + return fSelected ? new Click(this) : nullptr; + } + + bool onClick(Click* click) override { + fSelected->fLoc.fX += click->fCurr.fX - click->fPrev.fX; + fSelected->fLoc.fY += click->fCurr.fY - click->fPrev.fY; + this->inval(nullptr); + return true; + } + +private: + typedef SampleView INHERITED; +}; + +////////////////////////////////////////////////////////////////////////////// + +DEF_SAMPLE( return new XferDemo; ) |