blob: 6000da059db006adfaaf3f7cc80ea2cda135c21f [file] [log] [blame]
/*
* 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 "SkAAClip.h"
#include "SampleCode.h"
#include "SkView.h"
#include "SkCanvas.h"
#include "SkGradientShader.h"
#include "SkPath.h"
#include "SkRegion.h"
#include "SkShader.h"
#include "SkUtils.h"
#include "SkImageDecoder.h"
#define USE_PATHS 1
#ifdef SK_BUILD_FOR_WIN
// windows doesn't have roundf
inline float roundf(float x) { return (x-floor(x))>0.5 ? ceil(x) : floor(x); }
#endif
static void drawClip(SkCanvas* canvas, const SkAAClip& clip) {
SkMask mask;
SkBitmap bm;
clip.copyToMask(&mask);
SkAutoMaskFreeImage amfi(mask.fImage);
bm.setConfig(SkBitmap::kA8_Config, mask.fBounds.width(),
mask.fBounds.height(), mask.fRowBytes);
bm.setPixels(mask.fImage);
SkPaint paint;
canvas->drawBitmap(bm,
SK_Scalar1 * mask.fBounds.fLeft,
SK_Scalar1 * mask.fBounds.fTop,
&paint);
}
static void paint_rgn(SkCanvas* canvas, const SkAAClip& clip,
const SkPaint& paint) {
SkMask mask;
SkBitmap bm;
clip.copyToMask(&mask);
SkAutoMaskFreeImage amfi(mask.fImage);
bm.setConfig(SkBitmap::kA8_Config, mask.fBounds.width(),
mask.fBounds.height(), mask.fRowBytes);
bm.setPixels(mask.fImage);
canvas->drawBitmap(bm,
SK_Scalar1 * mask.fBounds.fLeft,
SK_Scalar1 * mask.fBounds.fTop,
&paint);
}
class AAClipView2 : public SampleView {
public:
AAClipView2() {
fBase.set(100, 100, 150, 150);
fRect = fBase;
fRect.inset(5, 5);
fRect.offset(25, 25);
this->setBGColor(0xFFDDDDDD);
}
static void setAAClip(SkAAClip* clip, const SkIRect& rect) {
SkRect r;
r.set(rect);
SkPath path;
path.addRoundRect(r, SkIntToScalar(5), SkIntToScalar(5));
clip->setPath(path, NULL, true);
}
void build_rgn(SkAAClip* clip, SkRegion::Op op) {
setAAClip(clip, fBase);
SkAAClip clip2;
setAAClip(&clip2, fRect);
clip->op(clip2, op);
}
protected:
// overrides from SkEventSink
virtual bool onQuery(SkEvent* evt) {
if (SampleCode::TitleQ(*evt)) {
SampleCode::TitleR(evt, "AAClips");
return true;
}
return this->INHERITED::onQuery(evt);
}
void drawOrig(SkCanvas* canvas, bool bg) {
SkRect r;
SkPaint paint;
paint.setStyle(SkPaint::kStroke_Style);
if (bg)
paint.setColor(0xFFBBBBBB);
r.set(fBase);
canvas->drawRect(r, paint);
r.set(fRect);
canvas->drawRect(r, paint);
}
static void outer_frame(SkCanvas* canvas, const SkIRect& rect) {
SkRect r;
r.set(rect);
r.inset(-SK_ScalarHalf, -SK_ScalarHalf);
SkPaint paint;
paint.setColor(SK_ColorGRAY);
paint.setStyle(SkPaint::kStroke_Style);
canvas->drawRect(r, paint);
}
void drawRgnOped(SkCanvas* canvas, SkRegion::Op op, SkColor color) {
SkAAClip clip;
this->build_rgn(&clip, op);
this->drawOrig(canvas, true);
SkPaint paint;
paint.setColor((color & ~(0xFF << 24)) | (0x44 << 24));
paint_rgn(canvas, clip, paint);
paint.setStyle(SkPaint::kStroke_Style);
paint.setColor(color);
paint_rgn(canvas, clip, paint);
SkAAClip clip2(clip);
clip2.translate(0, 80);
outer_frame(canvas, clip2.getBounds());
paint_rgn(canvas, clip2, paint);
}
static void createPath(SkPath *path, const SkIRect& rect) {
SkRect r;
r.set(rect);
path->addRoundRect(r, SkIntToScalar(5), SkIntToScalar(5));
}
void drawPathsOped(SkCanvas* canvas, SkRegion::Op op, SkColor color) {
this->drawOrig(canvas, true);
canvas->save();
// create the clip mask with the supplied boolean op
#if USE_PATHS
// path-based case
SkPath base;
createPath(&base, fBase);
canvas->clipPath(base, SkRegion::kReplace_Op, true);
#else
// rect-based case
SkRect base;
base.set(fBase);
// offset the rects so we get a bit of anti-aliasing
base.offset(SkFloatToScalar(0.5f), SkFloatToScalar(0.5f));
canvas->clipRect(base, SkRegion::kReplace_Op, true);
#endif
#if USE_PATHS
// path-based case
SkPath rect;
createPath(&rect, fRect);
canvas->clipPath(rect, op, true);
#else
// rect-based case
SkRect rect;
rect.set(fRect);
// offset the rects so we get a bit of anti-aliasing
rect.offset(SkFloatToScalar(0.5f), SkFloatToScalar(0.5f));
canvas->clipRect(rect, op, true);
#endif
// draw a rect that will entirely cover the clip mask area
SkPaint paint;
paint.setColor(color);
SkRect r = SkRect::MakeLTRB(SkIntToScalar(90), SkIntToScalar(90),
SkIntToScalar(180), SkIntToScalar(180));
canvas->drawRect(r, paint);
canvas->restore();
}
virtual void onDrawContent(SkCanvas* canvas) {
static const struct {
SkColor fColor;
const char* fName;
SkRegion::Op fOp;
} gOps[] = {
{ SK_ColorBLACK, "Difference", SkRegion::kDifference_Op },
{ SK_ColorRED, "Intersect", SkRegion::kIntersect_Op },
{ 0xFF008800, "Union", SkRegion::kUnion_Op },
{ SK_ColorBLUE, "XOR", SkRegion::kXOR_Op },
{ SK_ColorGREEN, "Rev Diff", SkRegion::kReverseDifference_Op },
{ SK_ColorYELLOW, "Replace", SkRegion::kReplace_Op }
};
SkPaint textPaint;
textPaint.setAntiAlias(true);
textPaint.setTextSize(SK_Scalar1*24);
this->drawOrig(canvas, false);
canvas->translate(0, SkIntToScalar(200));
for (size_t op = 0; op < SK_ARRAY_COUNT(gOps); op++) {
canvas->drawText(gOps[op].fName, strlen(gOps[op].fName),
SkIntToScalar(75), SkIntToScalar(50), textPaint);
this->drawRgnOped(canvas, gOps[op].fOp, gOps[op].fColor);
if (op && !(op % 3)) {
canvas->translate(SkIntToScalar(-600), SkIntToScalar(250));
} else {
canvas->translate(SkIntToScalar(200), 0);
}
}
canvas->translate(SkIntToScalar(int(SK_ARRAY_COUNT(gOps) / 3) * -200),
SkIntToScalar(250));
for (size_t op = 0; op < SK_ARRAY_COUNT(gOps); op++) {
canvas->drawText(gOps[op].fName, strlen(gOps[op].fName),
SkIntToScalar(75), SkIntToScalar(50), textPaint);
this->drawPathsOped(canvas, gOps[op].fOp, gOps[op].fColor);
if (op && !(op % 3)) {
canvas->translate(SkIntToScalar(-600), SkIntToScalar(250));
} else {
canvas->translate(SkIntToScalar(200), 0);
}
}
}
virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {
return fRect.contains(SkScalarRound(x), SkScalarRound(y)) ? new Click(this) : NULL;
}
virtual bool onClick(Click* click) {
fRect.offset(click->fICurr.fX - click->fIPrev.fX,
click->fICurr.fY - click->fIPrev.fY);
this->inval(NULL);
return true;
}
private:
SkIRect fBase, fRect;
typedef SampleView INHERITED;
};
//////////////////////////////////////////////////////////////////////////////
static SkView* MyFactory() { return new AAClipView2; }
static SkViewRegister reg(MyFactory);