blob: 944251ada2b66d44a06d46d64ff58755e1a8e302 [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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "gm/gm.h"
9#include "include/core/SkCanvas.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040010#include "include/core/SkClipOp.h"
11#include "include/core/SkColor.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050012#include "include/core/SkFont.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040013#include "include/core/SkFontTypes.h"
14#include "include/core/SkPaint.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050015#include "include/core/SkPath.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040016#include "include/core/SkRect.h"
17#include "include/core/SkScalar.h"
18#include "include/core/SkSize.h"
19#include "include/core/SkString.h"
20#include "include/core/SkTypeface.h"
21#include "include/core/SkTypes.h"
22#include "src/core/SkClipOpPriv.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050023#include "tools/ToolUtils.h"
bsalomon@google.com807cec42011-03-10 19:20:15 +000024
Ben Wagner7fde8e12019-05-01 17:28:53 -040025#include <string.h>
26
bsalomon@google.com807cec42011-03-10 19:20:15 +000027namespace skiagm {
28
mtkleindbfd7ab2016-09-01 11:24:54 -070029constexpr SkColor gPathColor = SK_ColorBLACK;
30constexpr SkColor gClipAColor = SK_ColorBLUE;
31constexpr SkColor gClipBColor = SK_ColorRED;
reed@google.coma8f60f22011-12-08 16:18:29 +000032
bsalomon@google.com807cec42011-03-10 19:20:15 +000033class ComplexClipGM : public GM {
34public:
bsalomon6ae83cf2014-12-17 14:38:49 -080035 ComplexClipGM(bool aaclip, bool saveLayer, bool invertDraw)
robertphillips@google.com50a69a02012-07-12 13:48:46 +000036 : fDoAAClip(aaclip)
bsalomon6ae83cf2014-12-17 14:38:49 -080037 , fDoSaveLayer(saveLayer)
38 , fInvertDraw(invertDraw) {
caryclarkceb9f3b2015-06-12 10:00:11 -070039 this->setBGColor(0xFFDEDFDE);
bsalomon@google.com807cec42011-03-10 19:20:15 +000040 }
41
42protected:
Mike Reedbc414ed2018-08-16 22:49:55 -040043 SkString onShortName() override {
reed@google.coma8f60f22011-12-08 16:18:29 +000044 SkString str;
bsalomon6ae83cf2014-12-17 14:38:49 -080045 str.printf("complexclip_%s%s%s",
robertphillips@google.com50a69a02012-07-12 13:48:46 +000046 fDoAAClip ? "aa" : "bw",
bsalomon6ae83cf2014-12-17 14:38:49 -080047 fDoSaveLayer ? "_layer" : "",
48 fInvertDraw ? "_invert" : "");
reed@google.coma8f60f22011-12-08 16:18:29 +000049 return str;
bsalomon@google.com807cec42011-03-10 19:20:15 +000050 }
51
Mike Reedbc414ed2018-08-16 22:49:55 -040052 SkISize onISize() override { return SkISize::Make(970, 780); }
bsalomon@google.com807cec42011-03-10 19:20:15 +000053
Mike Reedbc414ed2018-08-16 22:49:55 -040054 void onDraw(SkCanvas* canvas) override {
bsalomon@google.com807cec42011-03-10 19:20:15 +000055 SkPath path;
Mike Reedbc414ed2018-08-16 22:49:55 -040056 path.moveTo(0, 50)
57 .quadTo(0, 0, 50, 0)
58 .lineTo(175, 0)
59 .quadTo(200, 0, 200, 25)
60 .lineTo(200, 150)
61 .quadTo(200, 200, 150, 200)
62 .lineTo(0, 200)
63 .close()
64 .moveTo(50, 50)
65 .lineTo(150, 50)
66 .lineTo(150, 125)
67 .quadTo(150, 150, 125, 150)
68 .lineTo(50, 150)
69 .close();
bsalomon6ae83cf2014-12-17 14:38:49 -080070 if (fInvertDraw) {
Mike Reed7d34dc72019-11-26 12:17:17 -050071 path.setFillType(SkPathFillType::kInverseEvenOdd);
bsalomon6ae83cf2014-12-17 14:38:49 -080072 } else {
Mike Reed7d34dc72019-11-26 12:17:17 -050073 path.setFillType(SkPathFillType::kEvenOdd);
bsalomon6ae83cf2014-12-17 14:38:49 -080074 }
bsalomon@google.com807cec42011-03-10 19:20:15 +000075 SkPaint pathPaint;
76 pathPaint.setAntiAlias(true);
reed@google.coma8f60f22011-12-08 16:18:29 +000077 pathPaint.setColor(gPathColor);
bsalomon@google.com807cec42011-03-10 19:20:15 +000078
79 SkPath clipA;
Mike Reedbc414ed2018-08-16 22:49:55 -040080 clipA.addPoly({{10, 20}, {165, 22}, {70, 105}, {165, 177}, {-5, 180}}, false).close();
bsalomon@google.com807cec42011-03-10 19:20:15 +000081
82 SkPath clipB;
Mike Reedbc414ed2018-08-16 22:49:55 -040083 clipB.addPoly({{40, 10}, {190, 15}, {195, 190}, {40, 185}, {155, 100}}, false).close();
bsalomon@google.com807cec42011-03-10 19:20:15 +000084
Mike Kleinea3f0142019-03-20 11:12:10 -050085 SkFont font(ToolUtils::create_portable_typeface(), 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
Mike Reedbc414ed2018-08-16 22:49:55 -040098 canvas->translate(20, 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
Mike Reedbc414ed2018-08-16 22:49:55 -0400111 bounds.inset(100, 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);
Ben Wagner788a2dc2018-05-09 13:23:38 -0400116 canvas->clipRect(bounds);
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
Mike Reed7d34dc72019-11-26 12:17:17 -0500129 clipA.setFillType(doInvA ? SkPathFillType::kInverseEvenOdd :
130 SkPathFillType::kEvenOdd);
131 clipB.setFillType(doInvB ? SkPathFillType::kInverseEvenOdd :
132 SkPathFillType::kEvenOdd);
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
Mike Reed2e6db182018-12-15 13:45:33 -0500151 SkPaint paint;
Mike Reedbc414ed2018-08-16 22:49:55 -0400152 SkScalar txtX = 45;
reed@google.coma8f60f22011-12-08 16:18:29 +0000153 paint.setColor(gClipAColor);
154 const char* aTxt = doInvA ? "InvA " : "A ";
Ben Wagner51e15a62019-05-07 15:38:46 -0400155 canvas->drawSimpleText(aTxt, strlen(aTxt), SkTextEncoding::kUTF8, txtX, 220, font, paint);
156 txtX += font.measureText(aTxt, strlen(aTxt), SkTextEncoding::kUTF8);
bsalomon@google.com807cec42011-03-10 19:20:15 +0000157 paint.setColor(SK_ColorBLACK);
Ben Wagner51e15a62019-05-07 15:38:46 -0400158 canvas->drawSimpleText(gOps[op].fName, strlen(gOps[op].fName), SkTextEncoding::kUTF8, txtX, 220,
Mike Reed2e6db182018-12-15 13:45:33 -0500159 font, paint);
Ben Wagner51e15a62019-05-07 15:38:46 -0400160 txtX += font.measureText(gOps[op].fName, strlen(gOps[op].fName), SkTextEncoding::kUTF8);
reed@google.coma8f60f22011-12-08 16:18:29 +0000161 paint.setColor(gClipBColor);
162 const char* bTxt = doInvB ? "InvB " : "B ";
Ben Wagner51e15a62019-05-07 15:38:46 -0400163 canvas->drawSimpleText(bTxt, strlen(bTxt), SkTextEncoding::kUTF8, txtX, 220, font, paint);
bsalomon@google.com807cec42011-03-10 19:20:15 +0000164
Mike Reedbc414ed2018-08-16 22:49:55 -0400165 canvas->translate(250,0);
bsalomon@google.com807cec42011-03-10 19:20:15 +0000166 }
reed@google.coma8f60f22011-12-08 16:18:29 +0000167 canvas->restore();
Mike Reedbc414ed2018-08-16 22:49:55 -0400168 canvas->translate(0, 250);
bsalomon@google.com807cec42011-03-10 19:20:15 +0000169 }
robertphillips@google.com50a69a02012-07-12 13:48:46 +0000170
robertphillips@google.com54bb7ab2012-07-13 14:55:25 +0000171 if (fDoSaveLayer) {
robertphillips@google.com50a69a02012-07-12 13:48:46 +0000172 canvas->restore();
173 }
bsalomon@google.com807cec42011-03-10 19:20:15 +0000174 }
175private:
reed@google.coma8f60f22011-12-08 16:18:29 +0000176 void drawHairlines(SkCanvas* canvas, const SkPath& path,
177 const SkPath& clipA, const SkPath& clipB) {
178 SkPaint paint;
179 paint.setAntiAlias(true);
180 paint.setStyle(SkPaint::kStroke_Style);
181 const SkAlpha fade = 0x33;
182
183 // draw path in hairline
184 paint.setColor(gPathColor); paint.setAlpha(fade);
185 canvas->drawPath(path, paint);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000186
reed@google.coma8f60f22011-12-08 16:18:29 +0000187 // draw clips in hair line
188 paint.setColor(gClipAColor); paint.setAlpha(fade);
189 canvas->drawPath(clipA, paint);
190 paint.setColor(gClipBColor); paint.setAlpha(fade);
191 canvas->drawPath(clipB, paint);
192 }
193
bsalomon6ae83cf2014-12-17 14:38:49 -0800194 bool fDoAAClip;
195 bool fDoSaveLayer;
196 bool fInvertDraw;
197
bsalomon@google.com807cec42011-03-10 19:20:15 +0000198 typedef GM INHERITED;
199};
200
201//////////////////////////////////////////////////////////////////////////////
202
halcanary385fe4d2015-08-26 13:07:48 -0700203DEF_GM(return new ComplexClipGM(false, false, false);)
204DEF_GM(return new ComplexClipGM(false, false, true);)
205DEF_GM(return new ComplexClipGM(false, true, false);)
206DEF_GM(return new ComplexClipGM(false, true, true);)
207DEF_GM(return new ComplexClipGM(true, false, false);)
208DEF_GM(return new ComplexClipGM(true, false, true);)
209DEF_GM(return new ComplexClipGM(true, true, false);)
210DEF_GM(return new ComplexClipGM(true, true, true);)
bsalomon@google.com807cec42011-03-10 19:20:15 +0000211}