blob: 1d3359fbbe000f7c3f2bdc8d9792aab71e2841d7 [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 "gm.h"
Mike Klein33d20552017-03-22 13:47:51 -04009#include "sk_tool_utils.h"
bsalomon@google.com807cec42011-03-10 19:20:15 +000010#include "SkCanvas.h"
bsalomon@google.com807cec42011-03-10 19:20:15 +000011#include "SkPath.h"
bsalomon@google.com807cec42011-03-10 19:20:15 +000012
13namespace skiagm {
14
mtkleindbfd7ab2016-09-01 11:24:54 -070015constexpr SkColor gPathColor = SK_ColorBLACK;
16constexpr SkColor gClipAColor = SK_ColorBLUE;
17constexpr SkColor gClipBColor = SK_ColorRED;
reed@google.coma8f60f22011-12-08 16:18:29 +000018
bsalomon@google.com807cec42011-03-10 19:20:15 +000019class ComplexClipGM : public GM {
20public:
bsalomon6ae83cf2014-12-17 14:38:49 -080021 ComplexClipGM(bool aaclip, bool saveLayer, bool invertDraw)
robertphillips@google.com50a69a02012-07-12 13:48:46 +000022 : fDoAAClip(aaclip)
bsalomon6ae83cf2014-12-17 14:38:49 -080023 , fDoSaveLayer(saveLayer)
24 , fInvertDraw(invertDraw) {
caryclarkceb9f3b2015-06-12 10:00:11 -070025 this->setBGColor(0xFFDEDFDE);
bsalomon@google.com807cec42011-03-10 19:20:15 +000026 }
27
28protected:
Mike Reedbc414ed2018-08-16 22:49:55 -040029 SkString onShortName() override {
reed@google.coma8f60f22011-12-08 16:18:29 +000030 SkString str;
bsalomon6ae83cf2014-12-17 14:38:49 -080031 str.printf("complexclip_%s%s%s",
robertphillips@google.com50a69a02012-07-12 13:48:46 +000032 fDoAAClip ? "aa" : "bw",
bsalomon6ae83cf2014-12-17 14:38:49 -080033 fDoSaveLayer ? "_layer" : "",
34 fInvertDraw ? "_invert" : "");
reed@google.coma8f60f22011-12-08 16:18:29 +000035 return str;
bsalomon@google.com807cec42011-03-10 19:20:15 +000036 }
37
Mike Reedbc414ed2018-08-16 22:49:55 -040038 SkISize onISize() override { return SkISize::Make(970, 780); }
bsalomon@google.com807cec42011-03-10 19:20:15 +000039
Mike Reedbc414ed2018-08-16 22:49:55 -040040 void onDraw(SkCanvas* canvas) override {
bsalomon@google.com807cec42011-03-10 19:20:15 +000041 SkPath path;
Mike Reedbc414ed2018-08-16 22:49:55 -040042 path.moveTo(0, 50)
43 .quadTo(0, 0, 50, 0)
44 .lineTo(175, 0)
45 .quadTo(200, 0, 200, 25)
46 .lineTo(200, 150)
47 .quadTo(200, 200, 150, 200)
48 .lineTo(0, 200)
49 .close()
50 .moveTo(50, 50)
51 .lineTo(150, 50)
52 .lineTo(150, 125)
53 .quadTo(150, 150, 125, 150)
54 .lineTo(50, 150)
55 .close();
bsalomon6ae83cf2014-12-17 14:38:49 -080056 if (fInvertDraw) {
57 path.setFillType(SkPath::kInverseEvenOdd_FillType);
58 } else {
59 path.setFillType(SkPath::kEvenOdd_FillType);
60 }
bsalomon@google.com807cec42011-03-10 19:20:15 +000061 SkPaint pathPaint;
62 pathPaint.setAntiAlias(true);
reed@google.coma8f60f22011-12-08 16:18:29 +000063 pathPaint.setColor(gPathColor);
bsalomon@google.com807cec42011-03-10 19:20:15 +000064
65 SkPath clipA;
Mike Reedbc414ed2018-08-16 22:49:55 -040066 clipA.addPoly({{10, 20}, {165, 22}, {70, 105}, {165, 177}, {-5, 180}}, false).close();
bsalomon@google.com807cec42011-03-10 19:20:15 +000067
68 SkPath clipB;
Mike Reedbc414ed2018-08-16 22:49:55 -040069 clipB.addPoly({{40, 10}, {190, 15}, {195, 190}, {40, 185}, {155, 100}}, false).close();
bsalomon@google.com807cec42011-03-10 19:20:15 +000070
bsalomon@google.com807cec42011-03-10 19:20:15 +000071 SkPaint paint;
72 paint.setAntiAlias(true);
caryclark1818acb2015-07-24 12:09:25 -070073 sk_tool_utils::set_portable_typeface(&paint);
Mike Reedbc414ed2018-08-16 22:49:55 -040074 paint.setTextSize(20);
bsalomon@google.com807cec42011-03-10 19:20:15 +000075
mtkleindbfd7ab2016-09-01 11:24:54 -070076 constexpr struct {
Mike Reedc1f77742016-12-09 09:00:50 -050077 SkClipOp fOp;
reed73603f32016-09-20 08:42:38 -070078 const char* fName;
bsalomon@google.com807cec42011-03-10 19:20:15 +000079 } gOps[] = { //extra spaces in names for measureText
Mike Reedc1f77742016-12-09 09:00:50 -050080 {kIntersect_SkClipOp, "Isect "},
81 {kDifference_SkClipOp, "Diff " },
82 {kUnion_SkClipOp, "Union "},
83 {kXOR_SkClipOp, "Xor " },
84 {kReverseDifference_SkClipOp, "RDiff "}
bsalomon@google.com807cec42011-03-10 19:20:15 +000085 };
86
Mike Reedbc414ed2018-08-16 22:49:55 -040087 canvas->translate(20, 20);
bsalomon@google.com807cec42011-03-10 19:20:15 +000088 canvas->scale(3 * SK_Scalar1 / 4, 3 * SK_Scalar1 / 4);
bsalomon@google.com807cec42011-03-10 19:20:15 +000089
robertphillips@google.com54bb7ab2012-07-13 14:55:25 +000090 if (fDoSaveLayer) {
91 // We want the layer to appear symmetric relative to actual
92 // device boundaries so we need to "undo" the effect of the
93 // scale and translate
94 SkRect bounds = SkRect::MakeLTRB(
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +000095 4.0f/3.0f * -20,
96 4.0f/3.0f * -20,
97 4.0f/3.0f * (this->getISize().fWidth - 20),
98 4.0f/3.0f * (this->getISize().fHeight - 20));
robertphillips@google.com54bb7ab2012-07-13 14:55:25 +000099
Mike Reedbc414ed2018-08-16 22:49:55 -0400100 bounds.inset(100, 100);
robertphillips@google.com50a69a02012-07-12 13:48:46 +0000101 SkPaint boundPaint;
102 boundPaint.setColor(SK_ColorRED);
103 boundPaint.setStyle(SkPaint::kStroke_Style);
104 canvas->drawRect(bounds, boundPaint);
Ben Wagner788a2dc2018-05-09 13:23:38 -0400105 canvas->clipRect(bounds);
halcanary96fcdcc2015-08-27 07:41:13 -0700106 canvas->saveLayer(&bounds, nullptr);
robertphillips@google.com50a69a02012-07-12 13:48:46 +0000107 }
108
reed@google.coma8f60f22011-12-08 16:18:29 +0000109 for (int invBits = 0; invBits < 4; ++invBits) {
110 canvas->save();
bsalomon@google.com807cec42011-03-10 19:20:15 +0000111 for (size_t op = 0; op < SK_ARRAY_COUNT(gOps); ++op) {
reed@google.coma8f60f22011-12-08 16:18:29 +0000112 this->drawHairlines(canvas, path, clipA, clipB);
113
114 bool doInvA = SkToBool(invBits & 1);
115 bool doInvB = SkToBool(invBits & 2);
bsalomon@google.com807cec42011-03-10 19:20:15 +0000116 canvas->save();
117 // set clip
reed@google.coma8f60f22011-12-08 16:18:29 +0000118 clipA.setFillType(doInvA ? SkPath::kInverseEvenOdd_FillType :
119 SkPath::kEvenOdd_FillType);
120 clipB.setFillType(doInvB ? SkPath::kInverseEvenOdd_FillType :
121 SkPath::kEvenOdd_FillType);
reed66998382016-09-21 11:15:07 -0700122 canvas->clipPath(clipA, fDoAAClip);
reed@google.coma8f60f22011-12-08 16:18:29 +0000123 canvas->clipPath(clipB, gOps[op].fOp, fDoAAClip);
bsalomon@google.com807cec42011-03-10 19:20:15 +0000124
bsalomon6ae83cf2014-12-17 14:38:49 -0800125 // In the inverse case we need to prevent the draw from covering the whole
126 // canvas.
127 if (fInvertDraw) {
128 SkRect rectClip = clipA.getBounds();
129 rectClip.join(path.getBounds());
130 rectClip.join(path.getBounds());
131 rectClip.outset(5, 5);
132 canvas->clipRect(rectClip);
133 }
134
bsalomon@google.com807cec42011-03-10 19:20:15 +0000135 // draw path clipped
136 canvas->drawPath(path, pathPaint);
137 canvas->restore();
138
bsalomon@google.com807cec42011-03-10 19:20:15 +0000139
Mike Reedbc414ed2018-08-16 22:49:55 -0400140 SkScalar txtX = 45;
reed@google.coma8f60f22011-12-08 16:18:29 +0000141 paint.setColor(gClipAColor);
142 const char* aTxt = doInvA ? "InvA " : "A ";
Mike Reedbc414ed2018-08-16 22:49:55 -0400143 canvas->drawString(aTxt, txtX, 220, paint);
bsalomon@google.com807cec42011-03-10 19:20:15 +0000144 txtX += paint.measureText(aTxt, strlen(aTxt));
145 paint.setColor(SK_ColorBLACK);
Mike Reedbc414ed2018-08-16 22:49:55 -0400146 canvas->drawString(gOps[op].fName, txtX, 220, paint);
bsalomon@google.com807cec42011-03-10 19:20:15 +0000147 txtX += paint.measureText(gOps[op].fName, strlen(gOps[op].fName));
reed@google.coma8f60f22011-12-08 16:18:29 +0000148 paint.setColor(gClipBColor);
149 const char* bTxt = doInvB ? "InvB " : "B ";
Mike Reedbc414ed2018-08-16 22:49:55 -0400150 canvas->drawString(bTxt, txtX, 220, 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}