xref: /aosp_15_r20/external/skia/gm/pathopsinverse.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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