xref: /third_party/skia/gm/pathopsinverse.cpp (revision cb93a386)
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
21namespace skiagm {
22
23class PathOpsInverseGM : public GM {
24public:
25    PathOpsInverseGM() {
26    }
27
28protected:
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
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
54    void makePaint(SkPaint* paint, SkColor color) {
55        paint->setAntiAlias(true);
56        paint->setStyle(SkPaint::kFill_Style);
57        paint->setColor(color);
58    }
59
60    SkString onShortName() override {
61        return SkString("pathopsinverse");
62    }
63
64    SkISize onISize() override {
65        return SkISize::Make(1200, 900);
66    }
67
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
108private:
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
118DEF_GM( return new PathOpsInverseGM; )
119
120}  // namespace skiagm
121
122#include "include/pathops/SkPathOps.h"
123#include "include/utils/SkParsePath.h"
124
125DEF_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