blob: 2f8fa3d32582ccb3fc2770fa4cc224241ff5503e [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 */
bsalomon@google.com807cec42011-03-10 19:20:15 +00007#include "gm.h"
8#include "SkCanvas.h"
9//#include "SkParsePath.h"
10#include "SkPath.h"
11//#include "SkRandom.h"
12
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:
commit-bot@chromium.orga90c6802014-04-30 13:20:45 +000029
bsalomon@google.com807cec42011-03-10 19:20:15 +000030
31 SkString onShortName() {
reed@google.coma8f60f22011-12-08 16:18:29 +000032 SkString str;
bsalomon6ae83cf2014-12-17 14:38:49 -080033 str.printf("complexclip_%s%s%s",
robertphillips@google.com50a69a02012-07-12 13:48:46 +000034 fDoAAClip ? "aa" : "bw",
bsalomon6ae83cf2014-12-17 14:38:49 -080035 fDoSaveLayer ? "_layer" : "",
36 fInvertDraw ? "_invert" : "");
reed@google.coma8f60f22011-12-08 16:18:29 +000037 return str;
bsalomon@google.com807cec42011-03-10 19:20:15 +000038 }
39
tfarinaf5393182014-06-09 23:59:03 -070040 SkISize onISize() { return SkISize::Make(970, 780); }
bsalomon@google.com807cec42011-03-10 19:20:15 +000041
bsalomon@google.com807cec42011-03-10 19:20:15 +000042 virtual void onDraw(SkCanvas* canvas) {
43 SkPath path;
44 path.moveTo(SkIntToScalar(0), SkIntToScalar(50));
45 path.quadTo(SkIntToScalar(0), SkIntToScalar(0), SkIntToScalar(50), SkIntToScalar(0));
46 path.lineTo(SkIntToScalar(175), SkIntToScalar(0));
47 path.quadTo(SkIntToScalar(200), SkIntToScalar(0), SkIntToScalar(200), SkIntToScalar(25));
48 path.lineTo(SkIntToScalar(200), SkIntToScalar(150));
49 path.quadTo(SkIntToScalar(200), SkIntToScalar(200), SkIntToScalar(150), SkIntToScalar(200));
50 path.lineTo(SkIntToScalar(0), SkIntToScalar(200));
51 path.close();
52 path.moveTo(SkIntToScalar(50), SkIntToScalar(50));
53 path.lineTo(SkIntToScalar(150), SkIntToScalar(50));
54 path.lineTo(SkIntToScalar(150), SkIntToScalar(125));
55 path.quadTo(SkIntToScalar(150), SkIntToScalar(150), SkIntToScalar(125), SkIntToScalar(150));
56 path.lineTo(SkIntToScalar(50), SkIntToScalar(150));
57 path.close();
bsalomon6ae83cf2014-12-17 14:38:49 -080058 if (fInvertDraw) {
59 path.setFillType(SkPath::kInverseEvenOdd_FillType);
60 } else {
61 path.setFillType(SkPath::kEvenOdd_FillType);
62 }
bsalomon@google.com807cec42011-03-10 19:20:15 +000063 SkPaint pathPaint;
64 pathPaint.setAntiAlias(true);
reed@google.coma8f60f22011-12-08 16:18:29 +000065 pathPaint.setColor(gPathColor);
bsalomon@google.com807cec42011-03-10 19:20:15 +000066
67 SkPath clipA;
68 clipA.moveTo(SkIntToScalar(10), SkIntToScalar(20));
69 clipA.lineTo(SkIntToScalar(165), SkIntToScalar(22));
70 clipA.lineTo(SkIntToScalar(70), SkIntToScalar(105));
71 clipA.lineTo(SkIntToScalar(165), SkIntToScalar(177));
72 clipA.lineTo(SkIntToScalar(-5), SkIntToScalar(180));
73 clipA.close();
bsalomon@google.com807cec42011-03-10 19:20:15 +000074
75 SkPath clipB;
76 clipB.moveTo(SkIntToScalar(40), SkIntToScalar(10));
77 clipB.lineTo(SkIntToScalar(190), SkIntToScalar(15));
78 clipB.lineTo(SkIntToScalar(195), SkIntToScalar(190));
79 clipB.lineTo(SkIntToScalar(40), SkIntToScalar(185));
80 clipB.lineTo(SkIntToScalar(155), SkIntToScalar(100));
81 clipB.close();
bsalomon@google.com807cec42011-03-10 19:20:15 +000082
bsalomon@google.com807cec42011-03-10 19:20:15 +000083 SkPaint paint;
84 paint.setAntiAlias(true);
caryclark1818acb2015-07-24 12:09:25 -070085 sk_tool_utils::set_portable_typeface(&paint);
reed@google.coma8f60f22011-12-08 16:18:29 +000086 paint.setTextSize(SkIntToScalar(20));
bsalomon@google.com807cec42011-03-10 19:20:15 +000087
mtkleindbfd7ab2016-09-01 11:24:54 -070088 constexpr struct {
reed73603f32016-09-20 08:42:38 -070089 SkCanvas::ClipOp fOp;
90 const char* fName;
bsalomon@google.com807cec42011-03-10 19:20:15 +000091 } gOps[] = { //extra spaces in names for measureText
reed73603f32016-09-20 08:42:38 -070092 {SkCanvas::kIntersect_Op, "Isect "},
93 {SkCanvas::kDifference_Op, "Diff " },
94 {SkCanvas::kUnion_Op, "Union "},
95 {SkCanvas::kXOR_Op, "Xor " },
96 {SkCanvas::kReverseDifference_Op, "RDiff "}
bsalomon@google.com807cec42011-03-10 19:20:15 +000097 };
98
reed@google.coma8f60f22011-12-08 16:18:29 +000099 canvas->translate(SkIntToScalar(20), SkIntToScalar(20));
bsalomon@google.com807cec42011-03-10 19:20:15 +0000100 canvas->scale(3 * SK_Scalar1 / 4, 3 * SK_Scalar1 / 4);
bsalomon@google.com807cec42011-03-10 19:20:15 +0000101
robertphillips@google.com54bb7ab2012-07-13 14:55:25 +0000102 if (fDoSaveLayer) {
103 // We want the layer to appear symmetric relative to actual
104 // device boundaries so we need to "undo" the effect of the
105 // scale and translate
106 SkRect bounds = SkRect::MakeLTRB(
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000107 4.0f/3.0f * -20,
108 4.0f/3.0f * -20,
109 4.0f/3.0f * (this->getISize().fWidth - 20),
110 4.0f/3.0f * (this->getISize().fHeight - 20));
robertphillips@google.com54bb7ab2012-07-13 14:55:25 +0000111
112 bounds.inset(SkIntToScalar(100), SkIntToScalar(100));
robertphillips@google.com50a69a02012-07-12 13:48:46 +0000113 SkPaint boundPaint;
114 boundPaint.setColor(SK_ColorRED);
115 boundPaint.setStyle(SkPaint::kStroke_Style);
116 canvas->drawRect(bounds, boundPaint);
halcanary96fcdcc2015-08-27 07:41:13 -0700117 canvas->saveLayer(&bounds, nullptr);
robertphillips@google.com50a69a02012-07-12 13:48:46 +0000118 }
119
reed@google.coma8f60f22011-12-08 16:18:29 +0000120 for (int invBits = 0; invBits < 4; ++invBits) {
121 canvas->save();
bsalomon@google.com807cec42011-03-10 19:20:15 +0000122 for (size_t op = 0; op < SK_ARRAY_COUNT(gOps); ++op) {
reed@google.coma8f60f22011-12-08 16:18:29 +0000123 this->drawHairlines(canvas, path, clipA, clipB);
124
125 bool doInvA = SkToBool(invBits & 1);
126 bool doInvB = SkToBool(invBits & 2);
bsalomon@google.com807cec42011-03-10 19:20:15 +0000127 canvas->save();
128 // set clip
reed@google.coma8f60f22011-12-08 16:18:29 +0000129 clipA.setFillType(doInvA ? SkPath::kInverseEvenOdd_FillType :
130 SkPath::kEvenOdd_FillType);
131 clipB.setFillType(doInvB ? SkPath::kInverseEvenOdd_FillType :
132 SkPath::kEvenOdd_FillType);
reed66998382016-09-21 11:15:07 -0700133 canvas->clipPath(clipA, fDoAAClip);
reed@google.coma8f60f22011-12-08 16:18:29 +0000134 canvas->clipPath(clipB, gOps[op].fOp, fDoAAClip);
bsalomon@google.com807cec42011-03-10 19:20:15 +0000135
bsalomon6ae83cf2014-12-17 14:38:49 -0800136 // In the inverse case we need to prevent the draw from covering the whole
137 // canvas.
138 if (fInvertDraw) {
139 SkRect rectClip = clipA.getBounds();
140 rectClip.join(path.getBounds());
141 rectClip.join(path.getBounds());
142 rectClip.outset(5, 5);
143 canvas->clipRect(rectClip);
144 }
145
bsalomon@google.com807cec42011-03-10 19:20:15 +0000146 // draw path clipped
147 canvas->drawPath(path, pathPaint);
148 canvas->restore();
149
bsalomon@google.com807cec42011-03-10 19:20:15 +0000150
reed@google.coma8f60f22011-12-08 16:18:29 +0000151 SkScalar txtX = SkIntToScalar(45);
152 paint.setColor(gClipAColor);
153 const char* aTxt = doInvA ? "InvA " : "A ";
bsalomon@google.com807cec42011-03-10 19:20:15 +0000154 canvas->drawText(aTxt, strlen(aTxt), txtX, SkIntToScalar(220), paint);
155 txtX += paint.measureText(aTxt, strlen(aTxt));
156 paint.setColor(SK_ColorBLACK);
157 canvas->drawText(gOps[op].fName, strlen(gOps[op].fName),
158 txtX, SkIntToScalar(220), paint);
159 txtX += paint.measureText(gOps[op].fName, strlen(gOps[op].fName));
reed@google.coma8f60f22011-12-08 16:18:29 +0000160 paint.setColor(gClipBColor);
161 const char* bTxt = doInvB ? "InvB " : "B ";
162 canvas->drawText(bTxt, strlen(bTxt), txtX, SkIntToScalar(220), paint);
bsalomon@google.com807cec42011-03-10 19:20:15 +0000163
164 canvas->translate(SkIntToScalar(250),0);
165 }
reed@google.coma8f60f22011-12-08 16:18:29 +0000166 canvas->restore();
167 canvas->translate(0, SkIntToScalar(250));
bsalomon@google.com807cec42011-03-10 19:20:15 +0000168 }
robertphillips@google.com50a69a02012-07-12 13:48:46 +0000169
robertphillips@google.com54bb7ab2012-07-13 14:55:25 +0000170 if (fDoSaveLayer) {
robertphillips@google.com50a69a02012-07-12 13:48:46 +0000171 canvas->restore();
172 }
bsalomon@google.com807cec42011-03-10 19:20:15 +0000173 }
174private:
reed@google.coma8f60f22011-12-08 16:18:29 +0000175 void drawHairlines(SkCanvas* canvas, const SkPath& path,
176 const SkPath& clipA, const SkPath& clipB) {
177 SkPaint paint;
178 paint.setAntiAlias(true);
179 paint.setStyle(SkPaint::kStroke_Style);
180 const SkAlpha fade = 0x33;
181
182 // draw path in hairline
183 paint.setColor(gPathColor); paint.setAlpha(fade);
184 canvas->drawPath(path, paint);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000185
reed@google.coma8f60f22011-12-08 16:18:29 +0000186 // draw clips in hair line
187 paint.setColor(gClipAColor); paint.setAlpha(fade);
188 canvas->drawPath(clipA, paint);
189 paint.setColor(gClipBColor); paint.setAlpha(fade);
190 canvas->drawPath(clipB, paint);
191 }
192
bsalomon6ae83cf2014-12-17 14:38:49 -0800193 bool fDoAAClip;
194 bool fDoSaveLayer;
195 bool fInvertDraw;
196
bsalomon@google.com807cec42011-03-10 19:20:15 +0000197 typedef GM INHERITED;
198};
199
200//////////////////////////////////////////////////////////////////////////////
201
halcanary385fe4d2015-08-26 13:07:48 -0700202DEF_GM(return new ComplexClipGM(false, false, false);)
203DEF_GM(return new ComplexClipGM(false, false, true);)
204DEF_GM(return new ComplexClipGM(false, true, false);)
205DEF_GM(return new ComplexClipGM(false, true, true);)
206DEF_GM(return new ComplexClipGM(true, false, false);)
207DEF_GM(return new ComplexClipGM(true, false, true);)
208DEF_GM(return new ComplexClipGM(true, true, false);)
209DEF_GM(return new ComplexClipGM(true, true, true);)
bsalomon@google.com807cec42011-03-10 19:20:15 +0000210}