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