Sample that exercises complex clipping variations.
git-svn-id: http://skia.googlecode.com/svn/trunk@875 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/samplecode/SampleComplexClip.cpp b/samplecode/SampleComplexClip.cpp
new file mode 100644
index 0000000..c01a9a3
--- /dev/null
+++ b/samplecode/SampleComplexClip.cpp
@@ -0,0 +1,181 @@
+#include "SampleCode.h"
+#include "SkCanvas.h"
+#include "SkParsePath.h"
+#include "SkPath.h"
+#include "SkRandom.h"
+#include "SkView.h"
+
+static void scale_to_width(SkPath* path, SkScalar dstWidth) {
+ const SkRect& bounds = path->getBounds();
+ SkScalar scale = dstWidth / bounds.width();
+ SkMatrix matrix;
+
+ matrix.setScale(scale, scale);
+ path->transform(matrix);
+}
+
+static const struct {
+ SkPaint::Style fStyle;
+ SkPaint::Join fJoin;
+ int fStrokeWidth;
+} gRec[] = {
+ { SkPaint::kFill_Style, SkPaint::kMiter_Join, 0 },
+ { SkPaint::kStroke_Style, SkPaint::kMiter_Join, 0 },
+ { SkPaint::kStroke_Style, SkPaint::kMiter_Join, 10 },
+ { SkPaint::kStrokeAndFill_Style, SkPaint::kMiter_Join, 10 },
+};
+
+#define TEST_INVERSE 0
+
+class ComplexClipView : public SkView {
+ SkScalar fWidth;
+public:
+ ComplexClipView() {
+ }
+
+protected:
+ // overrides from SkEventSink
+ virtual bool onQuery(SkEvent* evt) {
+ if (SampleCode::TitleQ(*evt)) {
+ SampleCode::TitleR(evt, "ComplexClip");
+ return true;
+ }
+ return this->INHERITED::onQuery(evt);
+ }
+
+ void drawBG(SkCanvas* canvas) {
+ canvas->drawColor(SkColorSetRGB(0xA0,0xDD,0xA0));
+ }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ SkPath path;
+ path.moveTo(SkIntToScalar(0), SkIntToScalar(50));
+ path.quadTo(SkIntToScalar(0), SkIntToScalar(0), SkIntToScalar(50), SkIntToScalar(0));
+ path.lineTo(SkIntToScalar(175), SkIntToScalar(0));
+ path.quadTo(SkIntToScalar(200), SkIntToScalar(0), SkIntToScalar(200), SkIntToScalar(25));
+ path.lineTo(SkIntToScalar(200), SkIntToScalar(150));
+ path.quadTo(SkIntToScalar(200), SkIntToScalar(200), SkIntToScalar(150), SkIntToScalar(200));
+ path.lineTo(SkIntToScalar(0), SkIntToScalar(200));
+ path.close();
+ path.moveTo(SkIntToScalar(50), SkIntToScalar(50));
+ path.lineTo(SkIntToScalar(150), SkIntToScalar(50));
+ path.lineTo(SkIntToScalar(150), SkIntToScalar(125));
+ path.quadTo(SkIntToScalar(150), SkIntToScalar(150), SkIntToScalar(125), SkIntToScalar(150));
+ path.lineTo(SkIntToScalar(50), SkIntToScalar(150));
+ path.close();
+ path.setFillType(SkPath::kEvenOdd_FillType);
+ SkColor pathColor = SK_ColorBLACK;
+ SkPaint pathPaint;
+ pathPaint.setAntiAlias(true);
+ pathPaint.setColor(pathColor);
+
+ SkPath clipA;
+ clipA.moveTo(SkIntToScalar(10), SkIntToScalar(20));
+ clipA.lineTo(SkIntToScalar(165), SkIntToScalar(22));
+ clipA.lineTo(SkIntToScalar(70), SkIntToScalar(105));
+ clipA.lineTo(SkIntToScalar(165), SkIntToScalar(177));
+ clipA.lineTo(SkIntToScalar(-5), SkIntToScalar(180));
+ clipA.close();
+ SkColor colorA = SK_ColorCYAN;
+
+ SkPath clipB;
+ clipB.moveTo(SkIntToScalar(40), SkIntToScalar(10));
+ clipB.lineTo(SkIntToScalar(190), SkIntToScalar(15));
+ clipB.lineTo(SkIntToScalar(195), SkIntToScalar(190));
+ clipB.lineTo(SkIntToScalar(40), SkIntToScalar(185));
+ clipB.lineTo(SkIntToScalar(155), SkIntToScalar(100));
+ clipB.close();
+ SkColor colorB = SK_ColorRED;
+
+ drawBG(canvas);
+ SkPaint paint;
+ paint.setAntiAlias(true);
+
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStrokeWidth(0);
+
+ canvas->translate(SkIntToScalar(10),SkIntToScalar(10));
+ canvas->drawPath(path, pathPaint);
+ paint.setColor(colorA);
+ canvas->drawPath(clipA, paint);
+ paint.setColor(colorB);
+ canvas->drawPath(clipB, paint);
+
+ static const struct {
+ SkRegion::Op fOp;
+ const char* fName;
+ } gOps[] = { //extra spaces in names for measureText
+ {SkRegion::kIntersect_Op, "Isect "},
+ {SkRegion::kDifference_Op, "Diff " },
+ {SkRegion::kUnion_Op, "Union "},
+ {SkRegion::kXOR_Op, "Xor " },
+ {SkRegion::kReverseDifference_Op, "RDiff "}
+ };
+
+ canvas->translate(0, SkIntToScalar(40));
+ canvas->scale(3 * SK_Scalar1 / 4, 3 * SK_Scalar1 / 4);
+ canvas->save();
+
+ int invALimit = TEST_INVERSE ? 1 : 2;
+ for (int invA = 0; invALimit < 2; ++invA) {
+ for (int op = 0; op < SK_ARRAY_COUNT(gOps); ++op) {
+ int idx = invA * SK_ARRAY_COUNT(gOps) + op;
+ if (!(idx % 3)) {
+ canvas->restore();
+ canvas->translate(0, SkIntToScalar(250));
+ canvas->save();
+ }
+ canvas->save();
+ // set clip
+ clipA.setFillType(invA ? SkPath::kInverseEvenOdd_FillType :
+ SkPath::kEvenOdd_FillType);
+ canvas->clipPath(clipA);
+ canvas->clipPath(clipB, gOps[op].fOp);
+
+ // draw path clipped
+ canvas->drawPath(path, pathPaint);
+ canvas->restore();
+
+ // draw path in hairline
+ paint.setColor(pathColor);
+ canvas->drawPath(path, paint);
+
+ // draw clips in hair line
+ paint.setColor(colorA);
+ canvas->drawPath(clipA, paint);
+ paint.setColor(colorB);
+ canvas->drawPath(clipB, paint);
+
+ paint.setTextSize(SkIntToScalar(20));
+
+ SkScalar txtX = SkIntToScalar(55);
+ paint.setColor(colorA);
+ const char* aTxt = invA ? "InverseA " : "A ";
+ canvas->drawText(aTxt, strlen(aTxt), txtX, SkIntToScalar(220), paint);
+ txtX += paint.measureText(aTxt, strlen(aTxt));
+ paint.setColor(SK_ColorBLACK);
+ canvas->drawText(gOps[op].fName, strlen(gOps[op].fName),
+ txtX, SkIntToScalar(220), paint);
+ txtX += paint.measureText(gOps[op].fName, strlen(gOps[op].fName));
+ paint.setColor(colorB);
+ canvas->drawText("B", 1, txtX, SkIntToScalar(220), paint);
+
+ canvas->translate(SkIntToScalar(250),0);
+ }
+ }
+ canvas->restore();
+ }
+
+ virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {
+ this->inval(NULL);
+ return this->INHERITED::onFindClickHandler(x, y);
+ }
+private:
+ typedef SkView INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static SkView* MyFactory() { return new ComplexClipView; }
+static SkViewRegister reg(MyFactory);
+