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/SkPath.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 "src/core/SkClipOpPriv.h" 22 #include "tools/ToolUtils.h" 23 24 #include <utility> 25 26 namespace skiagm { 27 28 constexpr SkColor gPathColor = SK_ColorYELLOW; 29 30 class ComplexClip3GM : public GM { 31 public: ComplexClip3GM(bool doSimpleClipFirst)32 ComplexClip3GM(bool doSimpleClipFirst) 33 : fDoSimpleClipFirst(doSimpleClipFirst) { 34 this->setBGColor(0xFFDDDDDD); 35 } 36 37 protected: 38 onShortName()39 SkString onShortName() { 40 SkString str; 41 str.printf("complexclip3_%s", fDoSimpleClipFirst ? "simple" : "complex"); 42 return str; 43 } 44 onISize()45 SkISize onISize() { return SkISize::Make(1000, 950); } 46 onDraw(SkCanvas * canvas)47 virtual void onDraw(SkCanvas* canvas) { 48 SkPath clipSimple; 49 clipSimple.addCircle(SkIntToScalar(70), SkIntToScalar(50), SkIntToScalar(20)); 50 51 SkRect r1 = { 10, 20, 70, 80 }; 52 SkPath clipComplex; 53 clipComplex.moveTo(SkIntToScalar(40), SkIntToScalar(50)); 54 clipComplex.arcTo(r1, SkIntToScalar(30), SkIntToScalar(300), false); 55 clipComplex.close(); 56 57 SkPath* firstClip = &clipSimple; 58 SkPath* secondClip = &clipComplex; 59 60 if (!fDoSimpleClipFirst) { 61 using std::swap; 62 swap(firstClip, secondClip); 63 } 64 65 SkPaint paint; 66 paint.setAntiAlias(true); 67 68 SkFont font(ToolUtils::create_portable_typeface(), 20); 69 70 constexpr struct { 71 SkClipOp fOp; 72 const char* fName; 73 } gOps[] = { 74 {kIntersect_SkClipOp, "I"}, 75 {kDifference_SkClipOp, "D" }, 76 {kUnion_SkClipOp, "U"}, 77 {kXOR_SkClipOp, "X" }, 78 {kReverseDifference_SkClipOp, "R"} 79 }; 80 81 canvas->translate(SkIntToScalar(20), SkIntToScalar(20)); 82 canvas->scale(3 * SK_Scalar1 / 4, 3 * SK_Scalar1 / 4); 83 84 SkPaint pathPaint; 85 pathPaint.setAntiAlias(true); 86 pathPaint.setColor(gPathColor); 87 88 for (int invA = 0; invA < 2; ++invA) { 89 for (int aaBits = 0; aaBits < 4; ++aaBits) { 90 canvas->save(); 91 for (size_t op = 0; op < SK_ARRAY_COUNT(gOps); ++op) { 92 for (int invB = 0; invB < 2; ++invB) { 93 bool doAAA = SkToBool(aaBits & 1); 94 bool doAAB = SkToBool(aaBits & 2); 95 bool doInvA = SkToBool(invA); 96 bool doInvB = SkToBool(invB); 97 canvas->save(); 98 // set clip 99 firstClip->setFillType(doInvA ? SkPath::kInverseEvenOdd_FillType : 100 SkPath::kEvenOdd_FillType); 101 secondClip->setFillType(doInvB ? SkPath::kInverseEvenOdd_FillType : 102 SkPath::kEvenOdd_FillType); 103 canvas->clipPath(*firstClip, doAAA); 104 canvas->clipPath(*secondClip, gOps[op].fOp, doAAB); 105 106 // draw rect clipped 107 SkRect r = { 0, 0, 100, 100 }; 108 canvas->drawRect(r, pathPaint); 109 canvas->restore(); 110 111 112 SkScalar txtX = SkIntToScalar(10); 113 paint.setColor(SK_ColorBLACK); 114 SkString str; 115 str.printf("%s%s %s %s%s", doAAA ? "A" : "B", 116 doInvA ? "I" : "N", 117 gOps[op].fName, 118 doAAB ? "A" : "B", 119 doInvB ? "I" : "N"); 120 121 canvas->drawString(str.c_str(), txtX, SkIntToScalar(130), font, paint); 122 if (doInvB) { 123 canvas->translate(SkIntToScalar(150),0); 124 } else { 125 canvas->translate(SkIntToScalar(120),0); 126 } 127 } 128 } 129 canvas->restore(); 130 canvas->translate(0, SkIntToScalar(150)); 131 } 132 } 133 } 134 135 private: 136 bool fDoSimpleClipFirst; 137 138 typedef GM INHERITED; 139 }; 140 141 ////////////////////////////////////////////////////////////////////////////// 142 143 // Simple clip first 144 DEF_GM( return new ComplexClip3GM(true); ) 145 // Complex clip first 146 DEF_GM( return new ComplexClip3GM(false); ) 147 } 148