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 onShortName()60 SkString onShortName() override { 61 return SkString("pathopsinverse"); 62 } 63 onISize()64 SkISize onISize() override { 65 return SkISize::Make(1200, 900); 66 } 67 onDraw(SkCanvas * canvas)68 void onDraw(SkCanvas* canvas) override { 69 SkPath one, two; 70 int yPos = 0; 71 for (int oneFill = 0; oneFill <= 1; ++oneFill) { 72 SkPathFillType oneF = oneFill ? SkPathFillType::kInverseEvenOdd 73 : SkPathFillType::kEvenOdd; 74 for (int twoFill = 0; twoFill <= 1; ++twoFill) { 75 SkPathFillType twoF = twoFill ? SkPathFillType::kInverseEvenOdd 76 : SkPathFillType::kEvenOdd; 77 one.reset(); 78 one.setFillType(oneF); 79 one.addRect(10, 10, 70, 70); 80 two.reset(); 81 two.setFillType(twoF); 82 two.addRect(40, 40, 100, 100); 83 canvas->save(); 84 canvas->translate(0, SkIntToScalar(yPos)); 85 canvas->clipRect(SkRect::MakeWH(110, 110), true); 86 canvas->drawPath(one, fOnePaint); 87 canvas->drawPath(one, fOutlinePaint); 88 canvas->drawPath(two, fTwoPaint); 89 canvas->drawPath(two, fOutlinePaint); 90 canvas->restore(); 91 int xPos = 150; 92 for (int op = kDifference_SkPathOp; op <= kReverseDifference_SkPathOp; ++op) { 93 SkPath result; 94 Op(one, two, (SkPathOp) op, &result); 95 canvas->save(); 96 canvas->translate(SkIntToScalar(xPos), SkIntToScalar(yPos)); 97 canvas->clipRect(SkRect::MakeWH(110, 110), true); 98 canvas->drawPath(result, fOpPaint[op]); 99 canvas->drawPath(result, fOutlinePaint); 100 canvas->restore(); 101 xPos += 150; 102 } 103 yPos += 150; 104 } 105 } 106 } 107 108 private: 109 SkPaint fOnePaint; 110 SkPaint fTwoPaint; 111 SkPaint fOutlinePaint; 112 SkPaint fOpPaint[kReverseDifference_SkPathOp - kDifference_SkPathOp + 1]; 113 using INHERITED = GM; 114 }; 115 116 ////////////////////////////////////////////////////////////////////////////// 117 118 DEF_GM( return new PathOpsInverseGM; ) 119 120 } // namespace skiagm 121 122 #include "include/pathops/SkPathOps.h" 123 #include "include/utils/SkParsePath.h" 124 125 DEF_SIMPLE_GM(pathops_skbug_10155, canvas, 256, 256) { 126 const char* svgStr[] = { 127 "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", 128 "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" 129 }; 130 131 SkPath path[2], resultPath; 132 SkOpBuilder builder; 133 134 for (int i = 0; i < 2; i++) 135 { 136 SkParsePath::FromSVGString(svgStr[i], &path[i]); 137 builder.add(path[i], kUnion_SkPathOp); 138 } 139 140 builder.resolve(&resultPath); 141 142 auto r = path[0].getBounds(); 143 canvas->translate(30, 30); 144 canvas->scale(200 / r.width(), 200 / r.width()); 145 canvas->translate(-r.fLeft, -r.fTop); 146 147 SkPaint paint; 148 paint.setColor(SK_ColorRED); 149 paint.setAntiAlias(true); 150 paint.setStyle(SkPaint::kStroke_Style); 151 paint.setStrokeWidth(0); 152 153 canvas->drawPath(path[0], paint); 154 canvas->drawPath(path[1], paint); 155 156 // The blue draw should (nearly) overdraw all of the red (except where the two paths intersect) 157 paint.setColor(SK_ColorBLUE); 158 canvas->drawPath(resultPath, paint); 159 } 160