| /* |
| * Copyright 2014 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 "sk_tool_utils.h" |
| #include "SkCanvas.h" |
| #include "SkPath.h" |
| |
| #include <utility> |
| |
| namespace skiagm { |
| |
| constexpr SkColor gPathColor = SK_ColorYELLOW; |
| |
| class ComplexClip3GM : public GM { |
| public: |
| ComplexClip3GM(bool doSimpleClipFirst) |
| : fDoSimpleClipFirst(doSimpleClipFirst) { |
| this->setBGColor(sk_tool_utils::color_to_565(0xFFDDDDDD)); |
| } |
| |
| protected: |
| |
| SkString onShortName() { |
| SkString str; |
| str.printf("complexclip3_%s", fDoSimpleClipFirst ? "simple" : "complex"); |
| return str; |
| } |
| |
| SkISize onISize() { return SkISize::Make(1000, 950); } |
| |
| virtual void onDraw(SkCanvas* canvas) { |
| SkPath clipSimple; |
| clipSimple.addCircle(SkIntToScalar(70), SkIntToScalar(50), SkIntToScalar(20)); |
| |
| SkRect r1 = { 10, 20, 70, 80 }; |
| SkPath clipComplex; |
| clipComplex.moveTo(SkIntToScalar(40), SkIntToScalar(50)); |
| clipComplex.arcTo(r1, SkIntToScalar(30), SkIntToScalar(300), false); |
| clipComplex.close(); |
| |
| SkPath* firstClip = &clipSimple; |
| SkPath* secondClip = &clipComplex; |
| |
| if (!fDoSimpleClipFirst) { |
| using std::swap; |
| swap(firstClip, secondClip); |
| } |
| |
| SkPaint paint; |
| paint.setAntiAlias(true); |
| sk_tool_utils::set_portable_typeface(&paint); |
| paint.setTextSize(SkIntToScalar(20)); |
| |
| constexpr struct { |
| SkClipOp fOp; |
| const char* fName; |
| } gOps[] = { |
| {kIntersect_SkClipOp, "I"}, |
| {kDifference_SkClipOp, "D" }, |
| {kUnion_SkClipOp, "U"}, |
| {kXOR_SkClipOp, "X" }, |
| {kReverseDifference_SkClipOp, "R"} |
| }; |
| |
| canvas->translate(SkIntToScalar(20), SkIntToScalar(20)); |
| canvas->scale(3 * SK_Scalar1 / 4, 3 * SK_Scalar1 / 4); |
| |
| SkPaint pathPaint; |
| pathPaint.setAntiAlias(true); |
| pathPaint.setColor(gPathColor); |
| |
| for (int invA = 0; invA < 2; ++invA) { |
| for (int aaBits = 0; aaBits < 4; ++aaBits) { |
| canvas->save(); |
| for (size_t op = 0; op < SK_ARRAY_COUNT(gOps); ++op) { |
| for (int invB = 0; invB < 2; ++invB) { |
| bool doAAA = SkToBool(aaBits & 1); |
| bool doAAB = SkToBool(aaBits & 2); |
| bool doInvA = SkToBool(invA); |
| bool doInvB = SkToBool(invB); |
| canvas->save(); |
| // set clip |
| firstClip->setFillType(doInvA ? SkPath::kInverseEvenOdd_FillType : |
| SkPath::kEvenOdd_FillType); |
| secondClip->setFillType(doInvB ? SkPath::kInverseEvenOdd_FillType : |
| SkPath::kEvenOdd_FillType); |
| canvas->clipPath(*firstClip, doAAA); |
| canvas->clipPath(*secondClip, gOps[op].fOp, doAAB); |
| |
| // draw rect clipped |
| SkRect r = { 0, 0, 100, 100 }; |
| canvas->drawRect(r, pathPaint); |
| canvas->restore(); |
| |
| |
| SkScalar txtX = SkIntToScalar(10); |
| paint.setColor(SK_ColorBLACK); |
| SkString str; |
| str.printf("%s%s %s %s%s", doAAA ? "A" : "B", |
| doInvA ? "I" : "N", |
| gOps[op].fName, |
| doAAB ? "A" : "B", |
| doInvB ? "I" : "N"); |
| |
| canvas->drawString(str.c_str(), txtX, SkIntToScalar(130), paint); |
| if (doInvB) { |
| canvas->translate(SkIntToScalar(150),0); |
| } else { |
| canvas->translate(SkIntToScalar(120),0); |
| } |
| } |
| } |
| canvas->restore(); |
| canvas->translate(0, SkIntToScalar(150)); |
| } |
| } |
| } |
| |
| private: |
| bool fDoSimpleClipFirst; |
| |
| typedef GM INHERITED; |
| }; |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| |
| // Simple clip first |
| DEF_GM( return new ComplexClip3GM(true); ) |
| // Complex clip first |
| DEF_GM( return new ComplexClip3GM(false); ) |
| } |