blob: d704450a1f035555e2e034a177077f8423129c2a [file] [log] [blame]
caryclark@google.com7dfbb072013-04-22 14:37:05 +00001/*
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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "gm/gm.h"
9#include "include/core/SkBitmap.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040010#include "include/core/SkCanvas.h"
11#include "include/core/SkColor.h"
12#include "include/core/SkPaint.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050013#include "include/core/SkPath.h"
14#include "include/core/SkRect.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040015#include "include/core/SkScalar.h"
16#include "include/core/SkSize.h"
17#include "include/core/SkString.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050018#include "include/pathops/SkPathOps.h"
19#include "tools/ToolUtils.h"
caryclark@google.com7dfbb072013-04-22 14:37:05 +000020
21namespace skiagm {
22
23class PathOpsInverseGM : public GM {
24public:
25 PathOpsInverseGM() {
caryclark@google.com7dfbb072013-04-22 14:37:05 +000026 }
27
28protected:
mtklein36352bf2015-03-25 18:17:31 -070029 void onOnceBeforeDraw() override {
Mike Kleinea3f0142019-03-20 11:12:10 -050030 const unsigned oneColor = ToolUtils::color_to_565(0xFF8080FF);
caryclark@google.com7dfbb072013-04-22 14:37:05 +000031 const unsigned twoColor = 0x807F1f1f;
32 SkColor blendColor = blend(oneColor, twoColor);
caryclark@google.com4eedae62013-04-22 20:12:47 +000033 makePaint(&fOnePaint, oneColor);
34 makePaint(&fTwoPaint, twoColor);
caryclark54359292015-03-26 07:52:43 -070035 makePaint(&fOpPaint[kDifference_SkPathOp], oneColor);
36 makePaint(&fOpPaint[kIntersect_SkPathOp], blendColor);
Mike Kleinea3f0142019-03-20 11:12:10 -050037 makePaint(&fOpPaint[kUnion_SkPathOp], ToolUtils::color_to_565(0xFFc0FFc0));
caryclark54359292015-03-26 07:52:43 -070038 makePaint(&fOpPaint[kReverseDifference_SkPathOp], twoColor);
Mike Kleinea3f0142019-03-20 11:12:10 -050039 makePaint(&fOpPaint[kXOR_SkPathOp], ToolUtils::color_to_565(0xFFa0FFe0));
caryclark@google.com4eedae62013-04-22 20:12:47 +000040 makePaint(&fOutlinePaint, 0xFF000000);
41 fOutlinePaint.setStyle(SkPaint::kStroke_Style);
caryclark@google.com7dfbb072013-04-22 14:37:05 +000042 }
43
44 SkColor blend(SkColor one, SkColor two) {
45 SkBitmap temp;
reed@google.comeb9a46c2014-01-25 16:46:20 +000046 temp.allocN32Pixels(1, 1);
caryclark@google.com7dfbb072013-04-22 14:37:05 +000047 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
Leandro Lovisolo24fa2112023-08-15 19:05:17 +000060 SkString getName() const override { return SkString("pathopsinverse"); }
caryclark@google.com7dfbb072013-04-22 14:37:05 +000061
Leandro Lovisolo8f023882023-08-15 21:13:52 +000062 SkISize getISize() override { return SkISize::Make(1200, 900); }
caryclark@google.com7dfbb072013-04-22 14:37:05 +000063
mtklein36352bf2015-03-25 18:17:31 -070064 void onDraw(SkCanvas* canvas) override {
caryclark@google.com7dfbb072013-04-22 14:37:05 +000065 SkPath one, two;
66 int yPos = 0;
67 for (int oneFill = 0; oneFill <= 1; ++oneFill) {
Mike Reed7d34dc72019-11-26 12:17:17 -050068 SkPathFillType oneF = oneFill ? SkPathFillType::kInverseEvenOdd
69 : SkPathFillType::kEvenOdd;
caryclark@google.com7dfbb072013-04-22 14:37:05 +000070 for (int twoFill = 0; twoFill <= 1; ++twoFill) {
Mike Reed7d34dc72019-11-26 12:17:17 -050071 SkPathFillType twoF = twoFill ? SkPathFillType::kInverseEvenOdd
72 : SkPathFillType::kEvenOdd;
caryclark@google.com7dfbb072013-04-22 14:37:05 +000073 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));
reed66998382016-09-21 11:15:07 -070081 canvas->clipRect(SkRect::MakeWH(110, 110), true);
caryclark@google.com4eedae62013-04-22 20:12:47 +000082 canvas->drawPath(one, fOnePaint);
83 canvas->drawPath(one, fOutlinePaint);
84 canvas->drawPath(two, fTwoPaint);
85 canvas->drawPath(two, fOutlinePaint);
caryclark@google.com7dfbb072013-04-22 14:37:05 +000086 canvas->restore();
87 int xPos = 150;
caryclark54359292015-03-26 07:52:43 -070088 for (int op = kDifference_SkPathOp; op <= kReverseDifference_SkPathOp; ++op) {
caryclark@google.com7dfbb072013-04-22 14:37:05 +000089 SkPath result;
90 Op(one, two, (SkPathOp) op, &result);
91 canvas->save();
92 canvas->translate(SkIntToScalar(xPos), SkIntToScalar(yPos));
reed66998382016-09-21 11:15:07 -070093 canvas->clipRect(SkRect::MakeWH(110, 110), true);
caryclark@google.com4eedae62013-04-22 20:12:47 +000094 canvas->drawPath(result, fOpPaint[op]);
95 canvas->drawPath(result, fOutlinePaint);
caryclark@google.com7dfbb072013-04-22 14:37:05 +000096 canvas->restore();
97 xPos += 150;
98 }
99 yPos += 150;
100 }
101 }
102 }
103
104private:
caryclark@google.com4eedae62013-04-22 20:12:47 +0000105 SkPaint fOnePaint;
106 SkPaint fTwoPaint;
107 SkPaint fOutlinePaint;
caryclark54359292015-03-26 07:52:43 -0700108 SkPaint fOpPaint[kReverseDifference_SkPathOp - kDifference_SkPathOp + 1];
John Stiles7571f9e2020-09-02 22:42:33 -0400109 using INHERITED = GM;
caryclark@google.com7dfbb072013-04-22 14:37:05 +0000110};
111
112//////////////////////////////////////////////////////////////////////////////
113
Hal Canarye964c182019-01-23 10:22:01 -0500114DEF_GM( return new PathOpsInverseGM; )
caryclark@google.com7dfbb072013-04-22 14:37:05 +0000115
John Stilesa6841be2020-08-06 14:11:56 -0400116} // namespace skiagm
Mike Reed1174cf82020-04-20 14:01:17 -0400117
118#include "include/pathops/SkPathOps.h"
119#include "include/utils/SkParsePath.h"
120
121DEF_SIMPLE_GM(pathops_skbug_10155, canvas, 256, 256) {
122 const char* svgStr[] = {
123 "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",
124 "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"
125 };
126
127 SkPath path[2], resultPath;
128 SkOpBuilder builder;
129
130 for (int i = 0; i < 2; i++)
131 {
132 SkParsePath::FromSVGString(svgStr[i], &path[i]);
133 builder.add(path[i], kUnion_SkPathOp);
134 }
135
136 builder.resolve(&resultPath);
137
138 auto r = path[0].getBounds();
139 canvas->translate(30, 30);
140 canvas->scale(200 / r.width(), 200 / r.width());
141 canvas->translate(-r.fLeft, -r.fTop);
142
143 SkPaint paint;
144 paint.setColor(SK_ColorRED);
145 paint.setAntiAlias(true);
146 paint.setStyle(SkPaint::kStroke_Style);
147 paint.setStrokeWidth(0);
148
149 canvas->drawPath(path[0], paint);
150 canvas->drawPath(path[1], paint);
151
152 // The blue draw should (nearly) overdraw all of the red (except where the two paths intersect)
153 paint.setColor(SK_ColorBLUE);
154 canvas->drawPath(resultPath, paint);
155}