/*
* Copyright 2012 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "gm.h"
#include "SkAAClip.h"
#include "SkCanvas.h"
#include "SkPath.h"
namespace skiagm {
static void paint_rgn(SkCanvas* canvas, const SkAAClip& clip,
const SkPaint& paint) {
SkMask mask;
SkBitmap bm;
clip.copyToMask(&mask);
SkAutoMaskFreeImage amfi(mask.fImage);
bm.installMaskPixels(mask);
// need to copy for deferred drawing test to work
SkBitmap bm2;
bm.deepCopyTo(&bm2);
canvas->drawBitmap(bm2,
SK_Scalar1 * mask.fBounds.fLeft,
SK_Scalar1 * mask.fBounds.fTop,
&paint);
}
//////////////////////////////////////////////////////////////////////////////
/*
* This GM tests anti aliased single operation booleans with SkAAClips,
* SkRect and SkPaths.
*/
class SimpleClipGM : public GM {
public:
enum SkGeomTypes {
kRect_GeomType,
kPath_GeomType,
kAAClip_GeomType
};
SimpleClipGM(SkGeomTypes geomType)
: fGeomType(geomType) {
}
protected:
void onOnceBeforeDraw() override {
// offset the rects a bit so we get anti-aliasing in the rect case
fBase.set(100.65f,
100.65f,
150.65f,
150.65f);
fRect = fBase;
fRect.inset(5, 5);
fRect.offset(25, 25);
fBasePath.addRoundRect(fBase, SkIntToScalar(5), SkIntToScalar(5));
fRectPath.addRoundRect(fRect, SkIntToScalar(5), SkIntToScalar(5));
INHERITED::setBGColor(sk_tool_utils::color_to_565(0xFFDDDDDD));
}
void buildRgn(SkAAClip* clip, SkRegion::Op op) {
clip->setPath(fBasePath, nullptr, true);
SkAAClip clip2;
clip2.setPath(fRectPath, nullptr, true);
clip->op(clip2, op);
}
void drawOrig(SkCanvas* canvas) {
SkPaint paint;
paint.setStyle(SkPaint::kStroke_Style);
paint.setColor(SK_ColorBLACK);
canvas->drawRect(fBase, paint);
canvas->drawRect(fRect, paint);
}
void drawRgnOped(SkCanvas* canvas, SkRegion::Op op, SkColor color) {
SkAAClip clip;
this->buildRgn(&clip, op);
this->drawOrig(canvas);
SkPaint paint;
paint.setColor(color);
paint_rgn(canvas, clip, paint);
}
void drawPathsOped(SkCanvas* canvas, SkRegion::Op op, SkColor color) {
this->drawOrig(canvas);
canvas->save();
// create the clip mask with the supplied boolean op
if (kPath_GeomType == fGeomType) {
// path-based case
canvas->clipPath(fBasePath, SkRegion::kReplace_Op, true);
canvas->clipPath(fRectPath, op, true);
} else {
// rect-based case
canvas->clipRect(fBase, SkRegion::kReplace_Op, true);
canvas->clipRect(fRect, op, true);
}
// 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();
}
SkString onShortName() override {
SkString str;
str.printf("simpleaaclip_%s",
kRect_GeomType == fGeomType ? "rect" :
(kPath_GeomType == fGeomType ? "path" :
"aaclip"));
return str;
}
SkISize onISize() override {
return SkISize::Make(640, 480);
}
void onDraw(SkCanvas* canvas) override {
static const struct {
SkColor fColor;
const char* fName;
SkRegion::Op fOp;
} gOps[] = {
{ SK_ColorBLACK, "Difference", SkRegion::kDifference_Op },
{ SK_ColorRED, "Intersect", SkRegion::kIntersect_Op },
{ sk_tool_utils::color_to_565(0xFF008800), "Union", SkRegion::kUnion_Op },
{ SK_ColorGREEN, "Rev Diff", SkRegion::kReverseDifference_Op },
{ SK_ColorYELLOW, "Replace", SkRegion::kReplace_Op },
{ SK_ColorBLUE, "XOR", SkRegion::kXOR_Op },
};
SkPaint textPaint;
textPaint.setAntiAlias(true);
sk_tool_utils::set_portable_typeface(&textPaint);
textPaint.setTextSize(SK_Scalar1*24);
int xOff = 0;
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);
if (kAAClip_GeomType == fGeomType) {
this->drawRgnOped(canvas, gOps[op].fOp, gOps[op].fColor);
} else {
this->drawPathsOped(canvas, gOps[op].fOp, gOps[op].fColor);
}
if (xOff >= 400) {
canvas->translate(SkIntToScalar(-400), SkIntToScalar(250));
xOff = 0;
} else {
canvas->translate(SkIntToScalar(200), 0);
xOff += 200;
}
}
}
private:
SkGeomTypes fGeomType;
SkRect fBase;
SkRect fRect;
SkPath fBasePath; // fBase as a round rect
SkPath fRectPath; // fRect as a round rect
typedef GM INHERITED;
};
//////////////////////////////////////////////////////////////////////////////
// rects
DEF_GM( return new SimpleClipGM(SimpleClipGM::kRect_GeomType); )
DEF_GM( return new SimpleClipGM(SimpleClipGM::kPath_GeomType); )
DEF_GM( return new SimpleClipGM(SimpleClipGM::kAAClip_GeomType); )
}