class ComplexClip2GM : public GM {
public:
- ComplexClip2GM() {
+ ComplexClip2GM(bool doPaths, bool antiAlias)
+ : fDoPaths(doPaths)
+ , fAntiAlias(antiAlias) {
this->setBGColor(SkColorSetRGB(0xDD,0xA0,0xDD));
- SkScalar xA = 0 * SK_Scalar1;
- SkScalar xB = 10 * SK_Scalar1;
- SkScalar xC = 20 * SK_Scalar1;
- SkScalar xD = 30 * SK_Scalar1;
- SkScalar xE = 40 * SK_Scalar1;
- SkScalar xF = 50 * SK_Scalar1;
-
- SkScalar yA = 0 * SK_Scalar1;
- SkScalar yB = 10 * SK_Scalar1;
- SkScalar yC = 20 * SK_Scalar1;
- SkScalar yD = 30 * SK_Scalar1;
- SkScalar yE = 40 * SK_Scalar1;
- SkScalar yF = 50 * SK_Scalar1;
+ // offset the rects a bit so we get antialiasing even in the rect case
+ SkScalar xA = SkFloatToScalar(0.5f);
+ SkScalar xB = SkFloatToScalar(10.5f);
+ SkScalar xC = SkFloatToScalar(20.5f);
+ SkScalar xD = SkFloatToScalar(30.5f);
+ SkScalar xE = SkFloatToScalar(40.5f);
+ SkScalar xF = SkFloatToScalar(50.5f);
+
+ SkScalar yA = SkFloatToScalar(0.5f);
+ SkScalar yB = SkFloatToScalar(10.5f);
+ SkScalar yC = SkFloatToScalar(20.5f);
+ SkScalar yD = SkFloatToScalar(30.5f);
+ SkScalar yE = SkFloatToScalar(40.5f);
+ SkScalar yF = SkFloatToScalar(50.5f);
fWidth = xF - xA;
fHeight = yF - yA;
fRects[0].set(xB, yB, xE, yE);
+ fPaths[0].addRoundRect(fRects[0], SkIntToScalar(5), SkIntToScalar(5));
fRectColors[0] = SK_ColorRED;
fRects[1].set(xA, yA, xD, yD);
+ fPaths[1].addRoundRect(fRects[1], SkIntToScalar(5), SkIntToScalar(5));
fRectColors[1] = SK_ColorGREEN;
fRects[2].set(xC, yA, xF, yD);
+ fPaths[2].addRoundRect(fRects[2], SkIntToScalar(5), SkIntToScalar(5));
fRectColors[2] = SK_ColorBLUE;
fRects[3].set(xA, yC, xD, yF);
+ fPaths[3].addRoundRect(fRects[3], SkIntToScalar(5), SkIntToScalar(5));
fRectColors[3] = SK_ColorYELLOW;
fRects[4].set(xC, yC, xF, yF);
+ fPaths[4].addRoundRect(fRects[4], SkIntToScalar(5), SkIntToScalar(5));
fRectColors[4] = SK_ColorCYAN;
fTotalWidth = kCols * fWidth + SK_Scalar1 * (kCols + 1) * kPadX;
static const int kPadY = 20;
virtual SkString onShortName() {
- return SkString("complexclip2");
+ if (!fDoPaths && !fAntiAlias) {
+ return SkString("complexclip2");
+ }
+
+ SkString str;
+ str.printf("complexclip2_%s_%s",
+ fDoPaths ? "path" : "rect",
+ fAntiAlias ? "aa" : "bw");
+ return str;
}
virtual SkISize onISize() {
for (int i = 0; i < kRows; ++i) {
for (int j = 0; j < kCols; ++j) {
canvas->save();
+
canvas->translate(kPadX * SK_Scalar1 + (fWidth + kPadX * SK_Scalar1)*j,
kPadY * SK_Scalar1 + (fHeight + kPadY * SK_Scalar1)*i);
- canvas->save();
+
+ // draw the original shapes first so we can see the
+ // antialiasing on the clipped draw
for (int k = 0; k < 5; ++k) {
- canvas->clipRect(fRects[k], fOps[j*kRows+i][k]);
+ rectPaint.setColor(fRectColors[k]);
+ if (fDoPaths) {
+ canvas->drawPath(fPaths[k], rectPaint);
+ } else {
+ canvas->drawRect(fRects[k], rectPaint);
+ }
}
- canvas->drawRect(SkRect::MakeWH(fWidth, fHeight), fillPaint);
- canvas->restore();
+
for (int k = 0; k < 5; ++k) {
- rectPaint.setColor(fRectColors[k]);
- canvas->drawRect(fRects[k], rectPaint);
+ if (fDoPaths) {
+ canvas->clipPath(fPaths[k],
+ fOps[j*kRows+i][k],
+ fAntiAlias);
+ } else {
+ canvas->clipRect(fRects[k],
+ fOps[j*kRows+i][k],
+ fAntiAlias);
+ }
}
+ canvas->drawRect(SkRect::MakeWH(fWidth, fHeight), fillPaint);
canvas->restore();
}
}
}
private:
+ bool fDoPaths;
+ bool fAntiAlias;
SkRect fRects[5];
+ SkPath fPaths[5];
SkColor fRectColors[5];
SkRegion::Op fOps[kRows * kCols][5];
SkScalar fWidth;
//////////////////////////////////////////////////////////////////////////////
-static GM* MyFactory(void*) { return new ComplexClip2GM; }
+// bw rects
+static GM* MyFactory(void*) { return new ComplexClip2GM(false, false); }
static GMRegistry reg(MyFactory);
+// bw paths
+static GM* MyFactory2(void*) { return new ComplexClip2GM(true, false); }
+static GMRegistry reg2(MyFactory2);
+
+// aa rects
+static GM* MyFactory3(void*) { return new ComplexClip2GM(false, true); }
+static GMRegistry reg3(MyFactory3);
+
+// aa paths
+static GM* MyFactory4(void*) { return new ComplexClip2GM(true, true); }
+static GMRegistry reg4(MyFactory4);
+
}
#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); }
class AAClipView2 : public SampleView {
public:
- AAClipView2() {
+ AAClipView2() {
fBase.set(100, 100, 150, 150);
fRect = fBase;
fRect.inset(5, 5);
r.set(rect);
SkPath path;
path.addRoundRect(r, SkIntToScalar(5), SkIntToScalar(5));
- clip->setPath(path);
+ clip->setPath(path, NULL, true);
}
void build_rgn(SkAAClip* clip, SkRegion::Op op) {
clip->op(clip2, op);
}
-
protected:
// overrides from SkEventSink
virtual bool onQuery(SkEvent* evt) {
}
void drawRgnOped(SkCanvas* canvas, SkRegion::Op op, SkColor color) {
+
SkAAClip clip;
this->build_rgn(&clip, op);
-
this->drawOrig(canvas, true);
SkPaint 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 {
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_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.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);
+ canvas->drawText(gOps[op].fName, strlen(gOps[op].fName),
+ SkIntToScalar(75), SkIntToScalar(50), textPaint);
this->drawRgnOped(canvas, gOps[op].fOp, gOps[op].fColor);
-
- canvas->translate(SkIntToScalar(200), 0);
+
+ 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;
}