1 /* 2 * Copyright 2014 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "gm/gm.h" 9 #include "include/core/SkCanvas.h" 10 #include "include/core/SkClipOp.h" 11 #include "include/core/SkColor.h" 12 #include "include/core/SkFont.h" 13 #include "include/core/SkPaint.h" 14 #include "include/core/SkPathBuilder.h" 15 #include "include/core/SkRect.h" 16 #include "include/core/SkScalar.h" 17 #include "include/core/SkSize.h" 18 #include "include/core/SkString.h" 19 #include "include/core/SkTypeface.h" 20 #include "include/core/SkTypes.h" 21 #include "tools/ToolUtils.h" 22 23 #include <utility> 24 25 namespace skiagm { 26 27 constexpr SkColor gPathColor = SK_ColorYELLOW; 28 29 class ComplexClip3GM : public GM { 30 public: ComplexClip3GM(bool doSimpleClipFirst)31 ComplexClip3GM(bool doSimpleClipFirst) 32 : fDoSimpleClipFirst(doSimpleClipFirst) { 33 this->setBGColor(0xFFDDDDDD); 34 } 35 36 protected: 37 onShortName()38 SkString onShortName() override { 39 SkString str; 40 str.printf("complexclip3_%s", fDoSimpleClipFirst ? "simple" : "complex"); 41 return str; 42 } 43 onISize()44 SkISize onISize() override { return SkISize::Make(400, 950); } 45 onDraw(SkCanvas * canvas)46 void onDraw(SkCanvas* canvas) override { 47 SkPath clipSimple = SkPath::Circle(70, 50, 20); 48 49 SkRect r1 = { 10, 20, 70, 80 }; 50 SkPath clipComplex = SkPathBuilder().moveTo(40, 50) 51 .arcTo(r1, 30, 300, false) 52 .close() 53 .detach(); 54 55 SkPath* firstClip = &clipSimple; 56 SkPath* secondClip = &clipComplex; 57 if (!fDoSimpleClipFirst) { 58 std::swap(firstClip, secondClip); 59 } 60 61 SkPaint paint; 62 paint.setAntiAlias(true); 63 64 SkFont font(ToolUtils::create_portable_typeface(), 20); 65 66 constexpr struct { 67 SkClipOp fOp; 68 const char* fName; 69 } gOps[] = { 70 {SkClipOp::kIntersect, "I"}, 71 {SkClipOp::kDifference, "D" }, 72 }; 73 74 canvas->translate(SkIntToScalar(20), SkIntToScalar(20)); 75 canvas->scale(3 * SK_Scalar1 / 4, 3 * SK_Scalar1 / 4); 76 77 SkPaint pathPaint; 78 pathPaint.setAntiAlias(true); 79 pathPaint.setColor(gPathColor); 80 81 for (int invA = 0; invA < 2; ++invA) { 82 for (int aaBits = 0; aaBits < 4; ++aaBits) { 83 canvas->save(); 84 for (size_t op = 0; op < SK_ARRAY_COUNT(gOps); ++op) { 85 for (int invB = 0; invB < 2; ++invB) { 86 bool doAAA = SkToBool(aaBits & 1); 87 bool doAAB = SkToBool(aaBits & 2); 88 bool doInvA = SkToBool(invA); 89 bool doInvB = SkToBool(invB); 90 canvas->save(); 91 // set clip 92 firstClip->setFillType(doInvA ? SkPathFillType::kInverseEvenOdd : 93 SkPathFillType::kEvenOdd); 94 secondClip->setFillType(doInvB ? SkPathFillType::kInverseEvenOdd : 95 SkPathFillType::kEvenOdd); 96 canvas->clipPath(*firstClip, doAAA); 97 canvas->clipPath(*secondClip, gOps[op].fOp, doAAB); 98 99 // draw rect clipped 100 SkRect r = { 0, 0, 100, 100 }; 101 canvas->drawRect(r, pathPaint); 102 canvas->restore(); 103 104 105 SkScalar txtX = SkIntToScalar(10); 106 paint.setColor(SK_ColorBLACK); 107 SkString str; 108 str.printf("%s%s %s %s%s", doAAA ? "A" : "B", 109 doInvA ? "I" : "N", 110 gOps[op].fName, 111 doAAB ? "A" : "B", 112 doInvB ? "I" : "N"); 113 114 canvas->drawString(str.c_str(), txtX, SkIntToScalar(130), font, paint); 115 if (doInvB) { 116 canvas->translate(SkIntToScalar(150),0); 117 } else { 118 canvas->translate(SkIntToScalar(120),0); 119 } 120 } 121 } 122 canvas->restore(); 123 canvas->translate(0, SkIntToScalar(150)); 124 } 125 } 126 } 127 128 private: 129 bool fDoSimpleClipFirst; 130 131 using INHERITED = GM; 132 }; 133 134 ////////////////////////////////////////////////////////////////////////////// 135 136 // Simple clip first 137 DEF_GM( return new ComplexClip3GM(true); ) 138 // Complex clip first 139 DEF_GM( return new ComplexClip3GM(false); ) 140 } // namespace skiagm 141