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