зеркало из https://github.com/mozilla/moz-skia.git
380 строки
9.2 KiB
C++
380 строки
9.2 KiB
C++
|
|
/*
|
|
* Copyright 2011 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 "SkView.h"
|
|
#include "SkCanvas.h"
|
|
#include "SkGraphics.h"
|
|
#include "SkRandom.h"
|
|
|
|
static void test_clearonlayers(SkCanvas* canvas) {
|
|
SkCanvas& c = *canvas;
|
|
|
|
SkPaint paint;
|
|
paint.setColor(SK_ColorBLUE);
|
|
paint.setStyle(SkPaint::kStrokeAndFill_Style);
|
|
SkRect rect = SkRect::MakeXYWH(25, 25, 50, 50);
|
|
c.drawRect(rect, paint);
|
|
|
|
c.clipRect(rect);
|
|
|
|
c.saveLayer(NULL, NULL);
|
|
rect = SkRect::MakeXYWH(50, 10, 40, 80);
|
|
c.clipRect(rect, SkRegion::kUnion_Op);
|
|
|
|
rect = SkRect::MakeXYWH(50, 0, 50, 100);
|
|
// You might draw something here, but it's not necessary.
|
|
// paint.setColor(SK_ColorRED);
|
|
// c.drawRect(rect, paint);
|
|
paint.setXfermodeMode(SkXfermode::kClear_Mode);
|
|
c.drawRect(rect, paint);
|
|
c.restore();
|
|
}
|
|
|
|
static void test_strokerect(SkCanvas* canvas, const SkRect& r) {
|
|
SkPaint p;
|
|
|
|
p.setAntiAlias(true);
|
|
p.setStyle(SkPaint::kStroke_Style);
|
|
p.setStrokeWidth(4);
|
|
|
|
canvas->drawRect(r, p);
|
|
|
|
SkPath path;
|
|
SkRect r2(r);
|
|
r2.offset(18, 0);
|
|
path.addRect(r2);
|
|
|
|
canvas->drawPath(path, p);
|
|
}
|
|
|
|
static void test_strokerect(SkCanvas* canvas) {
|
|
canvas->drawColor(SK_ColorWHITE);
|
|
|
|
SkRect r;
|
|
|
|
r.set(10, 10, 14, 14);
|
|
r.offset(0.25f, 0.3333f);
|
|
test_strokerect(canvas, r);
|
|
canvas->translate(0, 20);
|
|
|
|
r.set(10, 10, 14.5f, 14.5f);
|
|
r.offset(0.25f, 0.3333f);
|
|
test_strokerect(canvas, r);
|
|
canvas->translate(0, 20);
|
|
|
|
r.set(10, 10, 14.5f, 20);
|
|
r.offset(0.25f, 0.3333f);
|
|
test_strokerect(canvas, r);
|
|
canvas->translate(0, 20);
|
|
|
|
r.set(10, 10, 20, 14.5f);
|
|
r.offset(0.25f, 0.3333f);
|
|
test_strokerect(canvas, r);
|
|
canvas->translate(0, 20);
|
|
|
|
r.set(10, 10, 20, 20);
|
|
r.offset(0.25f, 0.3333f);
|
|
test_strokerect(canvas, r);
|
|
canvas->translate(0, 20);
|
|
|
|
}
|
|
|
|
class Draw : public SkRefCnt {
|
|
public:
|
|
Draw() : fFlags(0) {}
|
|
|
|
enum Flags {
|
|
kSelected_Flag = 1 << 0
|
|
};
|
|
int getFlags() const { return fFlags; }
|
|
void setFlags(int flags);
|
|
|
|
bool isSelected() const { return SkToBool(fFlags & kSelected_Flag); }
|
|
void setSelected(bool pred) {
|
|
if (pred) {
|
|
fFlags |= kSelected_Flag;
|
|
} else {
|
|
fFlags &= ~kSelected_Flag;
|
|
}
|
|
}
|
|
|
|
void draw(SkCanvas* canvas) {
|
|
int sc = canvas->save();
|
|
this->onDraw(canvas);
|
|
canvas->restoreToCount(sc);
|
|
|
|
if (this->isSelected()) {
|
|
this->drawSelection(canvas);
|
|
}
|
|
}
|
|
|
|
void drawSelection(SkCanvas* canvas) {
|
|
int sc = canvas->save();
|
|
this->onDrawSelection(canvas);
|
|
canvas->restoreToCount(sc);
|
|
}
|
|
|
|
void getBounds(SkRect* bounds) {
|
|
this->onGetBounds(bounds);
|
|
}
|
|
|
|
bool hitTest(SkScalar x, SkScalar y) {
|
|
return this->onHitTest(x, y);
|
|
}
|
|
|
|
void offset(SkScalar dx, SkScalar dy) {
|
|
if (dx || dy) {
|
|
this->onOffset(dx, dy);
|
|
}
|
|
}
|
|
|
|
protected:
|
|
virtual void onDraw(SkCanvas*) = 0;
|
|
virtual void onGetBounds(SkRect*) = 0;
|
|
virtual void onOffset(SkScalar dx, SkScalar dy) = 0;
|
|
virtual void onDrawSelection(SkCanvas* canvas) {
|
|
SkRect r;
|
|
this->getBounds(&r);
|
|
SkPaint paint;
|
|
SkPoint pts[4];
|
|
r.toQuad(pts);
|
|
paint.setStrokeWidth(SkIntToScalar(10));
|
|
paint.setColor(0x80FF8844);
|
|
paint.setStrokeCap(SkPaint::kRound_Cap);
|
|
canvas->drawPoints(SkCanvas::kPoints_PointMode, 4, pts, paint);
|
|
}
|
|
virtual bool onHitTest(SkScalar x, SkScalar y) {
|
|
SkRect bounds;
|
|
this->getBounds(&bounds);
|
|
return bounds.contains(x, y);
|
|
}
|
|
|
|
private:
|
|
int fFlags;
|
|
};
|
|
|
|
class RDraw : public Draw {
|
|
public:
|
|
enum Style {
|
|
kRect_Style,
|
|
kOval_Style,
|
|
kRRect_Style,
|
|
kFrame_Style
|
|
};
|
|
|
|
RDraw(const SkRect& r, Style s) : fRect(r), fStyle(s) {}
|
|
|
|
void setRect(const SkRect& r) {
|
|
fRect = r;
|
|
}
|
|
|
|
void setPaint(const SkPaint& p) {
|
|
fPaint = p;
|
|
}
|
|
|
|
protected:
|
|
virtual void onDraw(SkCanvas* canvas) {
|
|
switch (fStyle) {
|
|
case kRect_Style:
|
|
canvas->drawRect(fRect, fPaint);
|
|
break;
|
|
case kOval_Style:
|
|
canvas->drawOval(fRect, fPaint);
|
|
break;
|
|
case kRRect_Style: {
|
|
SkScalar rx = fRect.width() / 5;
|
|
SkScalar ry = fRect.height() / 5;
|
|
if (rx < ry) {
|
|
ry = rx;
|
|
} else {
|
|
rx = ry;
|
|
}
|
|
canvas->drawRoundRect(fRect, rx, ry, fPaint);
|
|
break;
|
|
}
|
|
case kFrame_Style: {
|
|
SkPath path;
|
|
path.addOval(fRect, SkPath::kCW_Direction);
|
|
SkRect r = fRect;
|
|
r.inset(fRect.width()/6, 0);
|
|
path.addOval(r, SkPath::kCCW_Direction);
|
|
canvas->drawPath(path, fPaint);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
virtual void onGetBounds(SkRect* bounds) {
|
|
*bounds = fRect;
|
|
}
|
|
|
|
virtual void onOffset(SkScalar dx, SkScalar dy) {
|
|
fRect.offset(dx, dy);
|
|
}
|
|
|
|
private:
|
|
SkRect fRect;
|
|
SkPaint fPaint;
|
|
Style fStyle;
|
|
};
|
|
|
|
class DrawFactory {
|
|
public:
|
|
DrawFactory() {
|
|
fPaint.setAntiAlias(true);
|
|
}
|
|
|
|
const SkPaint& getPaint() const { return fPaint; }
|
|
|
|
void setPaint(const SkPaint& p) {
|
|
fPaint = p;
|
|
}
|
|
|
|
virtual Draw* create(const SkPoint&, const SkPoint&) = 0;
|
|
|
|
private:
|
|
SkPaint fPaint;
|
|
};
|
|
|
|
class RectFactory : public DrawFactory {
|
|
public:
|
|
virtual Draw* create(const SkPoint& p0, const SkPoint& p1) {
|
|
SkRect r;
|
|
r.set(p0.x(), p0.y(), p1.x(), p1.y());
|
|
r.sort();
|
|
|
|
// RDraw* d = new RDraw(r, RDraw::kRRect_Style);
|
|
RDraw* d = new RDraw(r, RDraw::kFrame_Style);
|
|
d->setPaint(this->getPaint());
|
|
return d;
|
|
}
|
|
};
|
|
|
|
class DrawView : public SkView {
|
|
Draw* fDraw;
|
|
DrawFactory* fFactory;
|
|
SkRandom fRand;
|
|
SkTDArray<Draw*> fList;
|
|
|
|
public:
|
|
DrawView() : fDraw(NULL) {
|
|
fFactory = new RectFactory;
|
|
}
|
|
|
|
virtual ~DrawView() {
|
|
fList.unrefAll();
|
|
SkSafeUnref(fDraw);
|
|
delete fFactory;
|
|
}
|
|
|
|
Draw* setDraw(Draw* d) {
|
|
SkRefCnt_SafeAssign(fDraw, d);
|
|
return d;
|
|
}
|
|
|
|
SkColor randColor() {
|
|
return (SkColor)fRand.nextU() | 0xFF000000;
|
|
}
|
|
|
|
Draw* hitTestList(SkScalar x, SkScalar y) const {
|
|
Draw** first = fList.begin();
|
|
for (Draw** iter = fList.end(); iter > first;) {
|
|
--iter;
|
|
if ((*iter)->hitTest(x, y)) {
|
|
return *iter;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
protected:
|
|
// overrides from SkEventSink
|
|
virtual bool onQuery(SkEvent* evt) {
|
|
if (SampleCode::TitleQ(*evt)) {
|
|
SampleCode::TitleR(evt, "Draw");
|
|
return true;
|
|
}
|
|
return this->INHERITED::onQuery(evt);
|
|
}
|
|
|
|
void drawBG(SkCanvas* canvas) {
|
|
canvas->drawColor(0xFFDDDDDD);
|
|
// canvas->drawColor(SK_ColorWHITE);
|
|
}
|
|
|
|
virtual void onDraw(SkCanvas* canvas) {
|
|
this->drawBG(canvas);
|
|
test_clearonlayers(canvas); return;
|
|
// test_strokerect(canvas); return;
|
|
|
|
for (Draw** iter = fList.begin(); iter < fList.end(); iter++) {
|
|
(*iter)->draw(canvas);
|
|
}
|
|
if (fDraw) {
|
|
fDraw->draw(canvas);
|
|
}
|
|
}
|
|
|
|
virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {
|
|
for (Draw** iter = fList.begin(); iter < fList.end(); iter++) {
|
|
(*iter)->setSelected(false);
|
|
}
|
|
|
|
Click* c = new Click(this);
|
|
Draw* d = this->hitTestList(x, y);
|
|
if (d) {
|
|
d->setSelected(true);
|
|
c->setType("dragger");
|
|
} else {
|
|
c->setType("maker");
|
|
}
|
|
return c;
|
|
}
|
|
|
|
virtual bool onClick(Click* click) {
|
|
if (Click::kUp_State == click->fState) {
|
|
if (click->isType("maker")) {
|
|
if (SkPoint::Distance(click->fOrig, click->fCurr) > SkIntToScalar(3)) {
|
|
*fList.append() = fDraw;
|
|
} else {
|
|
fDraw->unref();
|
|
}
|
|
fDraw = NULL;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
if (Click::kDown_State == click->fState) {
|
|
SkPaint p = fFactory->getPaint();
|
|
p.setColor(this->randColor());
|
|
fFactory->setPaint(p);
|
|
}
|
|
|
|
if (click->isType("maker")) {
|
|
this->setDraw(fFactory->create(click->fOrig, click->fCurr))->unref();
|
|
} else if (click->isType("dragger")) {
|
|
for (Draw** iter = fList.begin(); iter < fList.end(); iter++) {
|
|
if ((*iter)->isSelected()) {
|
|
(*iter)->offset(click->fCurr.x() - click->fPrev.x(),
|
|
click->fCurr.y() - click->fPrev.y());
|
|
}
|
|
}
|
|
}
|
|
this->inval(NULL);
|
|
return true;
|
|
}
|
|
|
|
private:
|
|
typedef SkView INHERITED;
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
static SkView* MyFactory() { return new DrawView; }
|
|
static SkViewRegister reg(MyFactory);
|