blob: c0a64c9b05a719d5ada492713e5960705b7eae0c [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001/*
2 * Copyright 2011 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 */
Mike Reedebfce6d2016-12-12 10:02:12 -05007
bsalomon@google.com807cec42011-03-10 19:20:15 +00008#include "SkCanvas.h"
Mike Reed2e6db182018-12-15 13:45:33 -05009#include "SkFont.h"
bsalomon@google.com807cec42011-03-10 19:20:15 +000010#include "SkPath.h"
Mike Kleinea3f0142019-03-20 11:12:10 -050011#include "ToolUtils.h"
12#include "gm.h"
bsalomon@google.com807cec42011-03-10 19:20:15 +000013
14namespace skiagm {
15
mtkleindbfd7ab2016-09-01 11:24:54 -070016constexpr SkColor gPathColor = SK_ColorBLACK;
17constexpr SkColor gClipAColor = SK_ColorBLUE;
18constexpr SkColor gClipBColor = SK_ColorRED;
reed@google.coma8f60f22011-12-08 16:18:29 +000019
bsalomon@google.com807cec42011-03-10 19:20:15 +000020class ComplexClipGM : public GM {
21public:
bsalomon6ae83cf2014-12-17 14:38:49 -080022 ComplexClipGM(bool aaclip, bool saveLayer, bool invertDraw)
robertphillips@google.com50a69a02012-07-12 13:48:46 +000023 : fDoAAClip(aaclip)
bsalomon6ae83cf2014-12-17 14:38:49 -080024 , fDoSaveLayer(saveLayer)
25 , fInvertDraw(invertDraw) {
caryclarkceb9f3b2015-06-12 10:00:11 -070026 this->setBGColor(0xFFDEDFDE);
bsalomon@google.com807cec42011-03-10 19:20:15 +000027 }
28
29protected:
Mike Reedbc414ed2018-08-16 22:49:55 -040030 SkString onShortName() override {
reed@google.coma8f60f22011-12-08 16:18:29 +000031 SkString str;
bsalomon6ae83cf2014-12-17 14:38:49 -080032 str.printf("complexclip_%s%s%s",
robertphillips@google.com50a69a02012-07-12 13:48:46 +000033 fDoAAClip ? "aa" : "bw",
bsalomon6ae83cf2014-12-17 14:38:49 -080034 fDoSaveLayer ? "_layer" : "",
35 fInvertDraw ? "_invert" : "");
reed@google.coma8f60f22011-12-08 16:18:29 +000036 return str;
bsalomon@google.com807cec42011-03-10 19:20:15 +000037 }
38
Mike Reedbc414ed2018-08-16 22:49:55 -040039 SkISize onISize() override { return SkISize::Make(970, 780); }
bsalomon@google.com807cec42011-03-10 19:20:15 +000040
Mike Reedbc414ed2018-08-16 22:49:55 -040041 void onDraw(SkCanvas* canvas) override {
bsalomon@google.com807cec42011-03-10 19:20:15 +000042 SkPath path;
Mike Reedbc414ed2018-08-16 22:49:55 -040043 path.moveTo(0, 50)
44 .quadTo(0, 0, 50, 0)
45 .lineTo(175, 0)
46 .quadTo(200, 0, 200, 25)
47 .lineTo(200, 150)
48 .quadTo(200, 200, 150, 200)
49 .lineTo(0, 200)
50 .close()
51 .moveTo(50, 50)
52 .lineTo(150, 50)
53 .lineTo(150, 125)
54 .quadTo(150, 150, 125, 150)
55 .lineTo(50, 150)
56 .close();
bsalomon6ae83cf2014-12-17 14:38:49 -080057 if (fInvertDraw) {
58 path.setFillType(SkPath::kInverseEvenOdd_FillType);
59 } else {
60 path.setFillType(SkPath::kEvenOdd_FillType);
61 }
bsalomon@google.com807cec42011-03-10 19:20:15 +000062 SkPaint pathPaint;
63 pathPaint.setAntiAlias(true);
reed@google.coma8f60f22011-12-08 16:18:29 +000064 pathPaint.setColor(gPathColor);
bsalomon@google.com807cec42011-03-10 19:20:15 +000065
66 SkPath clipA;
Mike Reedbc414ed2018-08-16 22:49:55 -040067 clipA.addPoly({{10, 20}, {165, 22}, {70, 105}, {165, 177}, {-5, 180}}, false).close();
bsalomon@google.com807cec42011-03-10 19:20:15 +000068
69 SkPath clipB;
Mike Reedbc414ed2018-08-16 22:49:55 -040070 clipB.addPoly({{40, 10}, {190, 15}, {195, 190}, {40, 185}, {155, 100}}, false).close();
bsalomon@google.com807cec42011-03-10 19:20:15 +000071
Mike Kleinea3f0142019-03-20 11:12:10 -050072 SkFont font(ToolUtils::create_portable_typeface(), 20);
bsalomon@google.com807cec42011-03-10 19:20:15 +000073
mtkleindbfd7ab2016-09-01 11:24:54 -070074 constexpr struct {
Mike Reedc1f77742016-12-09 09:00:50 -050075 SkClipOp fOp;
reed73603f32016-09-20 08:42:38 -070076 const char* fName;
bsalomon@google.com807cec42011-03-10 19:20:15 +000077 } gOps[] = { //extra spaces in names for measureText
Mike Reedc1f77742016-12-09 09:00:50 -050078 {kIntersect_SkClipOp, "Isect "},
79 {kDifference_SkClipOp, "Diff " },
80 {kUnion_SkClipOp, "Union "},
81 {kXOR_SkClipOp, "Xor " },
82 {kReverseDifference_SkClipOp, "RDiff "}
bsalomon@google.com807cec42011-03-10 19:20:15 +000083 };
84
Mike Reedbc414ed2018-08-16 22:49:55 -040085 canvas->translate(20, 20);
bsalomon@google.com807cec42011-03-10 19:20:15 +000086 canvas->scale(3 * SK_Scalar1 / 4, 3 * SK_Scalar1 / 4);
bsalomon@google.com807cec42011-03-10 19:20:15 +000087
robertphillips@google.com54bb7ab2012-07-13 14:55:25 +000088 if (fDoSaveLayer) {
89 // We want the layer to appear symmetric relative to actual
90 // device boundaries so we need to "undo" the effect of the
91 // scale and translate
92 SkRect bounds = SkRect::MakeLTRB(
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +000093 4.0f/3.0f * -20,
94 4.0f/3.0f * -20,
95 4.0f/3.0f * (this->getISize().fWidth - 20),
96 4.0f/3.0f * (this->getISize().fHeight - 20));
robertphillips@google.com54bb7ab2012-07-13 14:55:25 +000097
Mike Reedbc414ed2018-08-16 22:49:55 -040098 bounds.inset(100, 100);
robertphillips@google.com50a69a02012-07-12 13:48:46 +000099 SkPaint boundPaint;
100 boundPaint.setColor(SK_ColorRED);
101 boundPaint.setStyle(SkPaint::kStroke_Style);
102 canvas->drawRect(bounds, boundPaint);
Ben Wagner788a2dc2018-05-09 13:23:38 -0400103 canvas->clipRect(bounds);
halcanary96fcdcc2015-08-27 07:41:13 -0700104 canvas->saveLayer(&bounds, nullptr);
robertphillips@google.com50a69a02012-07-12 13:48:46 +0000105 }
106
reed@google.coma8f60f22011-12-08 16:18:29 +0000107 for (int invBits = 0; invBits < 4; ++invBits) {
108 canvas->save();
bsalomon@google.com807cec42011-03-10 19:20:15 +0000109 for (size_t op = 0; op < SK_ARRAY_COUNT(gOps); ++op) {
reed@google.coma8f60f22011-12-08 16:18:29 +0000110 this->drawHairlines(canvas, path, clipA, clipB);
111
112 bool doInvA = SkToBool(invBits & 1);
113 bool doInvB = SkToBool(invBits & 2);
bsalomon@google.com807cec42011-03-10 19:20:15 +0000114 canvas->save();
115 // set clip
reed@google.coma8f60f22011-12-08 16:18:29 +0000116 clipA.setFillType(doInvA ? SkPath::kInverseEvenOdd_FillType :
117 SkPath::kEvenOdd_FillType);
118 clipB.setFillType(doInvB ? SkPath::kInverseEvenOdd_FillType :
119 SkPath::kEvenOdd_FillType);
reed66998382016-09-21 11:15:07 -0700120 canvas->clipPath(clipA, fDoAAClip);
reed@google.coma8f60f22011-12-08 16:18:29 +0000121 canvas->clipPath(clipB, gOps[op].fOp, fDoAAClip);
bsalomon@google.com807cec42011-03-10 19:20:15 +0000122
bsalomon6ae83cf2014-12-17 14:38:49 -0800123 // In the inverse case we need to prevent the draw from covering the whole
124 // canvas.
125 if (fInvertDraw) {
126 SkRect rectClip = clipA.getBounds();
127 rectClip.join(path.getBounds());
128 rectClip.join(path.getBounds());
129 rectClip.outset(5, 5);
130 canvas->clipRect(rectClip);
131 }
132
bsalomon@google.com807cec42011-03-10 19:20:15 +0000133 // draw path clipped
134 canvas->drawPath(path, pathPaint);
135 canvas->restore();
136
bsalomon@google.com807cec42011-03-10 19:20:15 +0000137
Mike Reed2e6db182018-12-15 13:45:33 -0500138 SkPaint paint;
Mike Reedbc414ed2018-08-16 22:49:55 -0400139 SkScalar txtX = 45;
reed@google.coma8f60f22011-12-08 16:18:29 +0000140 paint.setColor(gClipAColor);
141 const char* aTxt = doInvA ? "InvA " : "A ";
Mike Reed2e6db182018-12-15 13:45:33 -0500142 canvas->drawSimpleText(aTxt, strlen(aTxt), kUTF8_SkTextEncoding, txtX, 220, font, paint);
143 txtX += font.measureText(aTxt, strlen(aTxt), kUTF8_SkTextEncoding);
bsalomon@google.com807cec42011-03-10 19:20:15 +0000144 paint.setColor(SK_ColorBLACK);
Mike Reed2e6db182018-12-15 13:45:33 -0500145 canvas->drawSimpleText(gOps[op].fName, strlen(gOps[op].fName), kUTF8_SkTextEncoding, txtX, 220,
146 font, paint);
147 txtX += font.measureText(gOps[op].fName, strlen(gOps[op].fName), kUTF8_SkTextEncoding);
reed@google.coma8f60f22011-12-08 16:18:29 +0000148 paint.setColor(gClipBColor);
149 const char* bTxt = doInvB ? "InvB " : "B ";
Mike Reed2e6db182018-12-15 13:45:33 -0500150 canvas->drawSimpleText(bTxt, strlen(bTxt), kUTF8_SkTextEncoding, txtX, 220, font, paint);
bsalomon@google.com807cec42011-03-10 19:20:15 +0000151
Mike Reedbc414ed2018-08-16 22:49:55 -0400152 canvas->translate(250,0);
bsalomon@google.com807cec42011-03-10 19:20:15 +0000153 }
reed@google.coma8f60f22011-12-08 16:18:29 +0000154 canvas->restore();
Mike Reedbc414ed2018-08-16 22:49:55 -0400155 canvas->translate(0, 250);
bsalomon@google.com807cec42011-03-10 19:20:15 +0000156 }
robertphillips@google.com50a69a02012-07-12 13:48:46 +0000157
robertphillips@google.com54bb7ab2012-07-13 14:55:25 +0000158 if (fDoSaveLayer) {
robertphillips@google.com50a69a02012-07-12 13:48:46 +0000159 canvas->restore();
160 }
bsalomon@google.com807cec42011-03-10 19:20:15 +0000161 }
162private:
reed@google.coma8f60f22011-12-08 16:18:29 +0000163 void drawHairlines(SkCanvas* canvas, const SkPath& path,
164 const SkPath& clipA, const SkPath& clipB) {
165 SkPaint paint;
166 paint.setAntiAlias(true);
167 paint.setStyle(SkPaint::kStroke_Style);
168 const SkAlpha fade = 0x33;
169
170 // draw path in hairline
171 paint.setColor(gPathColor); paint.setAlpha(fade);
172 canvas->drawPath(path, paint);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000173
reed@google.coma8f60f22011-12-08 16:18:29 +0000174 // draw clips in hair line
175 paint.setColor(gClipAColor); paint.setAlpha(fade);
176 canvas->drawPath(clipA, paint);
177 paint.setColor(gClipBColor); paint.setAlpha(fade);
178 canvas->drawPath(clipB, paint);
179 }
180
bsalomon6ae83cf2014-12-17 14:38:49 -0800181 bool fDoAAClip;
182 bool fDoSaveLayer;
183 bool fInvertDraw;
184
bsalomon@google.com807cec42011-03-10 19:20:15 +0000185 typedef GM INHERITED;
186};
187
188//////////////////////////////////////////////////////////////////////////////
189
halcanary385fe4d2015-08-26 13:07:48 -0700190DEF_GM(return new ComplexClipGM(false, false, false);)
191DEF_GM(return new ComplexClipGM(false, false, true);)
192DEF_GM(return new ComplexClipGM(false, true, false);)
193DEF_GM(return new ComplexClipGM(false, true, true);)
194DEF_GM(return new ComplexClipGM(true, false, false);)
195DEF_GM(return new ComplexClipGM(true, false, true);)
196DEF_GM(return new ComplexClipGM(true, true, false);)
197DEF_GM(return new ComplexClipGM(true, true, true);)
bsalomon@google.com807cec42011-03-10 19:20:15 +0000198}