9d524f22bf
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1842753002 Review URL: https://codereview.chromium.org/1842753002
252 lines
6.9 KiB
C++
252 lines
6.9 KiB
C++
/*
|
|
* 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 };
|
|
fPaint.setShader(SkGradientShader::MakeRadial(SkPoint::Make(size/2, size/2), size/2,
|
|
colors, nullptr, 2,
|
|
SkShader::kClamp_TileMode));
|
|
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; )
|