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