1 /* 2 * Copyright 2013 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/SkBitmap.h" 10 #include "include/core/SkCanvas.h" 11 #include "include/core/SkColor.h" 12 #include "include/core/SkPaint.h" 13 #include "include/core/SkPath.h" 14 #include "include/core/SkRect.h" 15 #include "include/core/SkScalar.h" 16 #include "include/core/SkSize.h" 17 #include "include/core/SkString.h" 18 #include "include/pathops/SkPathOps.h" 19 #include "tools/ToolUtils.h" 20 21 namespace skiagm { 22 23 class PathOpsInverseGM : public GM { 24 public: PathOpsInverseGM()25 PathOpsInverseGM() { 26 } 27 28 protected: onOnceBeforeDraw()29 void onOnceBeforeDraw() override { 30 const unsigned oneColor = ToolUtils::color_to_565(0xFF8080FF); 31 const unsigned twoColor = 0x807F1f1f; 32 SkColor blendColor = blend(oneColor, twoColor); 33 makePaint(&fOnePaint, oneColor); 34 makePaint(&fTwoPaint, twoColor); 35 makePaint(&fOpPaint[kDifference_SkPathOp], oneColor); 36 makePaint(&fOpPaint[kIntersect_SkPathOp], blendColor); 37 makePaint(&fOpPaint[kUnion_SkPathOp], ToolUtils::color_to_565(0xFFc0FFc0)); 38 makePaint(&fOpPaint[kReverseDifference_SkPathOp], twoColor); 39 makePaint(&fOpPaint[kXOR_SkPathOp], ToolUtils::color_to_565(0xFFa0FFe0)); 40 makePaint(&fOutlinePaint, 0xFF000000); 41 fOutlinePaint.setStyle(SkPaint::kStroke_Style); 42 } 43 blend(SkColor one,SkColor two)44 SkColor blend(SkColor one, SkColor two) { 45 SkBitmap temp; 46 temp.allocN32Pixels(1, 1); 47 SkCanvas canvas(temp); 48 canvas.drawColor(one); 49 canvas.drawColor(two); 50 void* pixels = temp.getPixels(); 51 return *(SkColor*) pixels; 52 } 53 makePaint(SkPaint * paint,SkColor color)54 void makePaint(SkPaint* paint, SkColor color) { 55 paint->setAntiAlias(true); 56 paint->setStyle(SkPaint::kFill_Style); 57 paint->setColor(color); 58 } 59 getName() const60 SkString getName() const override { return SkString("pathopsinverse"); } 61 getISize()62 SkISize getISize() override { return SkISize::Make(1200, 900); } 63 onDraw(SkCanvas * canvas)64 void onDraw(SkCanvas* canvas) override { 65 SkPath one, two; 66 int yPos = 0; 67 for (int oneFill = 0; oneFill <= 1; ++oneFill) { 68 SkPathFillType oneF = oneFill ? SkPathFillType::kInverseEvenOdd 69 : SkPathFillType::kEvenOdd; 70 for (int twoFill = 0; twoFill <= 1; ++twoFill) { 71 SkPathFillType twoF = twoFill ? SkPathFillType::kInverseEvenOdd 72 : SkPathFillType::kEvenOdd; 73 one.reset(); 74 one.setFillType(oneF); 75 one.addRect(10, 10, 70, 70); 76 two.reset(); 77 two.setFillType(twoF); 78 two.addRect(40, 40, 100, 100); 79 canvas->save(); 80 canvas->translate(0, SkIntToScalar(yPos)); 81 canvas->clipRect(SkRect::MakeWH(110, 110), true); 82 canvas->drawPath(one, fOnePaint); 83 canvas->drawPath(one, fOutlinePaint); 84 canvas->drawPath(two, fTwoPaint); 85 canvas->drawPath(two, fOutlinePaint); 86 canvas->restore(); 87 int xPos = 150; 88 for (int op = kDifference_SkPathOp; op <= kReverseDifference_SkPathOp; ++op) { 89 SkPath result; 90 Op(one, two, (SkPathOp) op, &result); 91 canvas->save(); 92 canvas->translate(SkIntToScalar(xPos), SkIntToScalar(yPos)); 93 canvas->clipRect(SkRect::MakeWH(110, 110), true); 94 canvas->drawPath(result, fOpPaint[op]); 95 canvas->drawPath(result, fOutlinePaint); 96 canvas->restore(); 97 xPos += 150; 98 } 99 yPos += 150; 100 } 101 } 102 } 103 104 private: 105 SkPaint fOnePaint; 106 SkPaint fTwoPaint; 107 SkPaint fOutlinePaint; 108 SkPaint fOpPaint[kReverseDifference_SkPathOp - kDifference_SkPathOp + 1]; 109 using INHERITED = GM; 110 }; 111 112 ////////////////////////////////////////////////////////////////////////////// 113 114 DEF_GM( return new PathOpsInverseGM; ) 115 116 } // namespace skiagm 117 118 #include "include/utils/SkParsePath.h" 119 120 DEF_SIMPLE_GM(pathops_skbug_10155, canvas, 256, 256) { 121 const char* svgStr[] = { 122 "M474.889 27.0952C474.889 27.1002 474.888 27.1018 474.889 27.1004L479.872 27.5019C479.883 27.3656 479.889 27.2299 479.889 27.0952L474.889 27.0952L474.889 27.0952Z", 123 "M474.94 26.9405C474.93 26.9482 474.917 26.9576 474.901 26.9683L477.689 31.1186C477.789 31.0512 477.888 30.9804 477.985 30.9059L474.94 26.9405L474.94 26.9405Z" 124 }; 125 126 SkPath path[2], resultPath; 127 SkOpBuilder builder; 128 129 for (int i = 0; i < 2; i++) 130 { 131 SkParsePath::FromSVGString(svgStr[i], &path[i]); 132 builder.add(path[i], kUnion_SkPathOp); 133 } 134 135 builder.resolve(&resultPath); 136 137 auto r = path[0].getBounds(); 138 canvas->translate(30, 30); 139 canvas->scale(200 / r.width(), 200 / r.width()); 140 canvas->translate(-r.fLeft, -r.fTop); 141 142 SkPaint paint; 143 paint.setColor(SK_ColorRED); 144 paint.setAntiAlias(true); 145 paint.setStyle(SkPaint::kStroke_Style); 146 paint.setStrokeWidth(0); 147 148 canvas->drawPath(path[0], paint); 149 canvas->drawPath(path[1], paint); 150 151 // The blue draw should (nearly) overdraw all of the red (except where the two paths intersect) 152 paint.setColor(SK_ColorBLUE); 153 canvas->drawPath(resultPath, paint); 154 } 155