blob: 1fecd9487af10a2ea1f7dd8991b2ec3e55cd63f6 [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"
9#include "SkCanvas.h"
bsalomon@google.com807cec42011-03-10 19:20:15 +000010#include "SkPath.h"
bsalomon@google.com807cec42011-03-10 19:20:15 +000011
12namespace skiagm {
13
mtkleindbfd7ab2016-09-01 11:24:54 -070014constexpr SkColor gPathColor = SK_ColorBLACK;
15constexpr SkColor gClipAColor = SK_ColorBLUE;
16constexpr SkColor gClipBColor = SK_ColorRED;
reed@google.coma8f60f22011-12-08 16:18:29 +000017
bsalomon@google.com807cec42011-03-10 19:20:15 +000018class ComplexClipGM : public GM {
19public:
bsalomon6ae83cf2014-12-17 14:38:49 -080020 ComplexClipGM(bool aaclip, bool saveLayer, bool invertDraw)
robertphillips@google.com50a69a02012-07-12 13:48:46 +000021 : fDoAAClip(aaclip)
bsalomon6ae83cf2014-12-17 14:38:49 -080022 , fDoSaveLayer(saveLayer)
23 , fInvertDraw(invertDraw) {
caryclarkceb9f3b2015-06-12 10:00:11 -070024 this->setBGColor(0xFFDEDFDE);
bsalomon@google.com807cec42011-03-10 19:20:15 +000025 }
26
27protected:
commit-bot@chromium.orga90c6802014-04-30 13:20:45 +000028
bsalomon@google.com807cec42011-03-10 19:20:15 +000029
30 SkString onShortName() {
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
tfarinaf5393182014-06-09 23:59:03 -070039 SkISize onISize() { return SkISize::Make(970, 780); }
bsalomon@google.com807cec42011-03-10 19:20:15 +000040
bsalomon@google.com807cec42011-03-10 19:20:15 +000041 virtual void onDraw(SkCanvas* canvas) {
42 SkPath path;
43 path.moveTo(SkIntToScalar(0), SkIntToScalar(50));
44 path.quadTo(SkIntToScalar(0), SkIntToScalar(0), SkIntToScalar(50), SkIntToScalar(0));
45 path.lineTo(SkIntToScalar(175), SkIntToScalar(0));
46 path.quadTo(SkIntToScalar(200), SkIntToScalar(0), SkIntToScalar(200), SkIntToScalar(25));
47 path.lineTo(SkIntToScalar(200), SkIntToScalar(150));
48 path.quadTo(SkIntToScalar(200), SkIntToScalar(200), SkIntToScalar(150), SkIntToScalar(200));
49 path.lineTo(SkIntToScalar(0), SkIntToScalar(200));
50 path.close();
51 path.moveTo(SkIntToScalar(50), SkIntToScalar(50));
52 path.lineTo(SkIntToScalar(150), SkIntToScalar(50));
53 path.lineTo(SkIntToScalar(150), SkIntToScalar(125));
54 path.quadTo(SkIntToScalar(150), SkIntToScalar(150), SkIntToScalar(125), SkIntToScalar(150));
55 path.lineTo(SkIntToScalar(50), SkIntToScalar(150));
56 path.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;
67 clipA.moveTo(SkIntToScalar(10), SkIntToScalar(20));
68 clipA.lineTo(SkIntToScalar(165), SkIntToScalar(22));
69 clipA.lineTo(SkIntToScalar(70), SkIntToScalar(105));
70 clipA.lineTo(SkIntToScalar(165), SkIntToScalar(177));
71 clipA.lineTo(SkIntToScalar(-5), SkIntToScalar(180));
72 clipA.close();
bsalomon@google.com807cec42011-03-10 19:20:15 +000073
74 SkPath clipB;
75 clipB.moveTo(SkIntToScalar(40), SkIntToScalar(10));
76 clipB.lineTo(SkIntToScalar(190), SkIntToScalar(15));
77 clipB.lineTo(SkIntToScalar(195), SkIntToScalar(190));
78 clipB.lineTo(SkIntToScalar(40), SkIntToScalar(185));
79 clipB.lineTo(SkIntToScalar(155), SkIntToScalar(100));
80 clipB.close();
bsalomon@google.com807cec42011-03-10 19:20:15 +000081
bsalomon@google.com807cec42011-03-10 19:20:15 +000082 SkPaint paint;
83 paint.setAntiAlias(true);
caryclark1818acb2015-07-24 12:09:25 -070084 sk_tool_utils::set_portable_typeface(&paint);
reed@google.coma8f60f22011-12-08 16:18:29 +000085 paint.setTextSize(SkIntToScalar(20));
bsalomon@google.com807cec42011-03-10 19:20:15 +000086
mtkleindbfd7ab2016-09-01 11:24:54 -070087 constexpr struct {
Mike Reedc1f77742016-12-09 09:00:50 -050088 SkClipOp fOp;
reed73603f32016-09-20 08:42:38 -070089 const char* fName;
bsalomon@google.com807cec42011-03-10 19:20:15 +000090 } gOps[] = { //extra spaces in names for measureText
Mike Reedc1f77742016-12-09 09:00:50 -050091 {kIntersect_SkClipOp, "Isect "},
92 {kDifference_SkClipOp, "Diff " },
93 {kUnion_SkClipOp, "Union "},
94 {kXOR_SkClipOp, "Xor " },
95 {kReverseDifference_SkClipOp, "RDiff "}
bsalomon@google.com807cec42011-03-10 19:20:15 +000096 };
97
reed@google.coma8f60f22011-12-08 16:18:29 +000098 canvas->translate(SkIntToScalar(20), SkIntToScalar(20));
bsalomon@google.com807cec42011-03-10 19:20:15 +000099 canvas->scale(3 * SK_Scalar1 / 4, 3 * SK_Scalar1 / 4);
bsalomon@google.com807cec42011-03-10 19:20:15 +0000100
robertphillips@google.com54bb7ab2012-07-13 14:55:25 +0000101 if (fDoSaveLayer) {
102 // We want the layer to appear symmetric relative to actual
103 // device boundaries so we need to "undo" the effect of the
104 // scale and translate
105 SkRect bounds = SkRect::MakeLTRB(
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000106 4.0f/3.0f * -20,
107 4.0f/3.0f * -20,
108 4.0f/3.0f * (this->getISize().fWidth - 20),
109 4.0f/3.0f * (this->getISize().fHeight - 20));
robertphillips@google.com54bb7ab2012-07-13 14:55:25 +0000110
111 bounds.inset(SkIntToScalar(100), SkIntToScalar(100));
robertphillips@google.com50a69a02012-07-12 13:48:46 +0000112 SkPaint boundPaint;
113 boundPaint.setColor(SK_ColorRED);
114 boundPaint.setStyle(SkPaint::kStroke_Style);
115 canvas->drawRect(bounds, boundPaint);
halcanary96fcdcc2015-08-27 07:41:13 -0700116 canvas->saveLayer(&bounds, nullptr);
robertphillips@google.com50a69a02012-07-12 13:48:46 +0000117 }
118
reed@google.coma8f60f22011-12-08 16:18:29 +0000119 for (int invBits = 0; invBits < 4; ++invBits) {
120 canvas->save();
bsalomon@google.com807cec42011-03-10 19:20:15 +0000121 for (size_t op = 0; op < SK_ARRAY_COUNT(gOps); ++op) {
reed@google.coma8f60f22011-12-08 16:18:29 +0000122 this->drawHairlines(canvas, path, clipA, clipB);
123
124 bool doInvA = SkToBool(invBits & 1);
125 bool doInvB = SkToBool(invBits & 2);
bsalomon@google.com807cec42011-03-10 19:20:15 +0000126 canvas->save();
127 // set clip
reed@google.coma8f60f22011-12-08 16:18:29 +0000128 clipA.setFillType(doInvA ? SkPath::kInverseEvenOdd_FillType :
129 SkPath::kEvenOdd_FillType);
130 clipB.setFillType(doInvB ? SkPath::kInverseEvenOdd_FillType :
131 SkPath::kEvenOdd_FillType);
reed66998382016-09-21 11:15:07 -0700132 canvas->clipPath(clipA, fDoAAClip);
reed@google.coma8f60f22011-12-08 16:18:29 +0000133 canvas->clipPath(clipB, gOps[op].fOp, fDoAAClip);
bsalomon@google.com807cec42011-03-10 19:20:15 +0000134
bsalomon6ae83cf2014-12-17 14:38:49 -0800135 // In the inverse case we need to prevent the draw from covering the whole
136 // canvas.
137 if (fInvertDraw) {
138 SkRect rectClip = clipA.getBounds();
139 rectClip.join(path.getBounds());
140 rectClip.join(path.getBounds());
141 rectClip.outset(5, 5);
142 canvas->clipRect(rectClip);
143 }
144
bsalomon@google.com807cec42011-03-10 19:20:15 +0000145 // draw path clipped
146 canvas->drawPath(path, pathPaint);
147 canvas->restore();
148
bsalomon@google.com807cec42011-03-10 19:20:15 +0000149
reed@google.coma8f60f22011-12-08 16:18:29 +0000150 SkScalar txtX = SkIntToScalar(45);
151 paint.setColor(gClipAColor);
152 const char* aTxt = doInvA ? "InvA " : "A ";
bsalomon@google.com807cec42011-03-10 19:20:15 +0000153 canvas->drawText(aTxt, strlen(aTxt), txtX, SkIntToScalar(220), paint);
154 txtX += paint.measureText(aTxt, strlen(aTxt));
155 paint.setColor(SK_ColorBLACK);
156 canvas->drawText(gOps[op].fName, strlen(gOps[op].fName),
157 txtX, SkIntToScalar(220), paint);
158 txtX += paint.measureText(gOps[op].fName, strlen(gOps[op].fName));
reed@google.coma8f60f22011-12-08 16:18:29 +0000159 paint.setColor(gClipBColor);
160 const char* bTxt = doInvB ? "InvB " : "B ";
161 canvas->drawText(bTxt, strlen(bTxt), txtX, SkIntToScalar(220), paint);
bsalomon@google.com807cec42011-03-10 19:20:15 +0000162
163 canvas->translate(SkIntToScalar(250),0);
164 }
reed@google.coma8f60f22011-12-08 16:18:29 +0000165 canvas->restore();
166 canvas->translate(0, SkIntToScalar(250));
bsalomon@google.com807cec42011-03-10 19:20:15 +0000167 }
robertphillips@google.com50a69a02012-07-12 13:48:46 +0000168
robertphillips@google.com54bb7ab2012-07-13 14:55:25 +0000169 if (fDoSaveLayer) {
robertphillips@google.com50a69a02012-07-12 13:48:46 +0000170 canvas->restore();
171 }
bsalomon@google.com807cec42011-03-10 19:20:15 +0000172 }
173private:
reed@google.coma8f60f22011-12-08 16:18:29 +0000174 void drawHairlines(SkCanvas* canvas, const SkPath& path,
175 const SkPath& clipA, const SkPath& clipB) {
176 SkPaint paint;
177 paint.setAntiAlias(true);
178 paint.setStyle(SkPaint::kStroke_Style);
179 const SkAlpha fade = 0x33;
180
181 // draw path in hairline
182 paint.setColor(gPathColor); paint.setAlpha(fade);
183 canvas->drawPath(path, paint);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000184
reed@google.coma8f60f22011-12-08 16:18:29 +0000185 // draw clips in hair line
186 paint.setColor(gClipAColor); paint.setAlpha(fade);
187 canvas->drawPath(clipA, paint);
188 paint.setColor(gClipBColor); paint.setAlpha(fade);
189 canvas->drawPath(clipB, paint);
190 }
191
bsalomon6ae83cf2014-12-17 14:38:49 -0800192 bool fDoAAClip;
193 bool fDoSaveLayer;
194 bool fInvertDraw;
195
bsalomon@google.com807cec42011-03-10 19:20:15 +0000196 typedef GM INHERITED;
197};
198
199//////////////////////////////////////////////////////////////////////////////
200
halcanary385fe4d2015-08-26 13:07:48 -0700201DEF_GM(return new ComplexClipGM(false, false, false);)
202DEF_GM(return new ComplexClipGM(false, false, true);)
203DEF_GM(return new ComplexClipGM(false, true, false);)
204DEF_GM(return new ComplexClipGM(false, true, true);)
205DEF_GM(return new ComplexClipGM(true, false, false);)
206DEF_GM(return new ComplexClipGM(true, false, true);)
207DEF_GM(return new ComplexClipGM(true, true, false);)
208DEF_GM(return new ComplexClipGM(true, true, true);)
bsalomon@google.com807cec42011-03-10 19:20:15 +0000209}