blob: 186b1aea5a30abaf80b5fe11d5d076d68da2af21 [file] [log] [blame]
robertphillipsfac9ceb2015-09-03 08:32:08 -07001/*
2 * Copyright 2015 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 */
7
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "gm/gm.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -04009#include "include/core/SkBitmap.h"
10#include "include/core/SkCanvas.h"
11#include "include/core/SkColor.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050012#include "include/core/SkImage.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040013#include "include/core/SkImageInfo.h"
14#include "include/core/SkMatrix.h"
15#include "include/core/SkPaint.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050016#include "include/core/SkPath.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040017#include "include/core/SkPoint.h"
18#include "include/core/SkRect.h"
19#include "include/core/SkRefCnt.h"
20#include "include/core/SkScalar.h"
21#include "include/core/SkShader.h"
22#include "include/core/SkSize.h"
23#include "include/core/SkString.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050024#include "include/core/SkSurface.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040025#include "include/core/SkTileMode.h"
26#include "include/core/SkTypes.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050027#include "include/effects/SkGradientShader.h"
28#include "tools/ToolUtils.h"
robertphillipsfac9ceb2015-09-03 08:32:08 -070029
reed9ce9d672016-03-17 10:51:11 -070030static sk_sp<SkImage> make_image(SkCanvas* origCanvas, int w, int h) {
robertphillipsfac9ceb2015-09-03 08:32:08 -070031 SkImageInfo info = SkImageInfo::MakeN32Premul(w, h);
Mike Kleinea3f0142019-03-20 11:12:10 -050032 auto surface(ToolUtils::makeSurface(origCanvas, info));
robertphillipsfac9ceb2015-09-03 08:32:08 -070033 SkCanvas* canvas = surface->getCanvas();
34
Mike Kleinea3f0142019-03-20 11:12:10 -050035 ToolUtils::draw_checkerboard(canvas, SK_ColorRED, SK_ColorGREEN, w / 10);
reed9ce9d672016-03-17 10:51:11 -070036 return surface->makeImageSnapshot();
robertphillipsfac9ceb2015-09-03 08:32:08 -070037}
38
robertphillipsfac9ceb2015-09-03 08:32:08 -070039namespace skiagm {
40
41class PerspShadersGM : public GM {
42public:
43 PerspShadersGM(bool doAA) : fDoAA(doAA) { }
44
45protected:
46 SkString onShortName() override {
47 SkString name;
48 name.printf("persp_shaders_%s",
49 fDoAA ? "aa" : "bw");
50 return name;
51 }
52
53 SkISize onISize() override {
54 return SkISize::Make(kCellSize*kNumCols, kCellSize*kNumRows);
55 }
56
57 void onOnceBeforeDraw() override {
Mike Reed8d29ab62021-01-23 18:10:39 -050058 fBitmapImage = ToolUtils::create_checkerboard_image(
Mike Kleinea3f0142019-03-20 11:12:10 -050059 kCellSize, kCellSize, SK_ColorBLUE, SK_ColorYELLOW, kCellSize / 10);
robertphillipsfac9ceb2015-09-03 08:32:08 -070060
robertphillipsfac9ceb2015-09-03 08:32:08 -070061 SkPoint pts1[] = {
62 { 0, 0 },
63 { SkIntToScalar(kCellSize), SkIntToScalar(kCellSize) }
64 };
65 SkPoint pts2[] = {
66 { 0, 0 },
67 { 0, SkIntToScalar(kCellSize) }
68 };
mtkleindbfd7ab2016-09-01 11:24:54 -070069 constexpr SkColor colors[] = {
robertphillipsfac9ceb2015-09-03 08:32:08 -070070 SK_ColorRED, SK_ColorGREEN, SK_ColorRED, SK_ColorGREEN, SK_ColorRED
71 };
mtkleindbfd7ab2016-09-01 11:24:54 -070072 constexpr SkScalar pos[] = { 0, 0.25f, 0.5f, 0.75f, SK_Scalar1 };
robertphillipsfac9ceb2015-09-03 08:32:08 -070073
reed1a9b9642016-03-13 14:13:58 -070074 fLinearGrad1 = SkGradientShader::MakeLinear(pts1, colors, pos, SK_ARRAY_COUNT(colors),
Mike Reedfae8fce2019-04-03 10:27:45 -040075 SkTileMode::kClamp);
reed1a9b9642016-03-13 14:13:58 -070076 fLinearGrad2 = SkGradientShader::MakeLinear(pts2, colors, pos, SK_ARRAY_COUNT(colors),
Mike Reedfae8fce2019-04-03 10:27:45 -040077 SkTileMode::kClamp);
robertphillipsfac9ceb2015-09-03 08:32:08 -070078
79 fPerspMatrix.reset();
80 fPerspMatrix.setPerspY(SK_Scalar1 / 50);
81
82 fPath.moveTo(0, 0);
83 fPath.lineTo(0, SkIntToScalar(kCellSize));
84 fPath.lineTo(kCellSize/2.0f, kCellSize/2.0f);
85 fPath.lineTo(SkIntToScalar(kCellSize), SkIntToScalar(kCellSize));
86 fPath.lineTo(SkIntToScalar(kCellSize), 0);
87 fPath.close();
88 }
89
Mike Reed8d29ab62021-01-23 18:10:39 -050090 void drawRow(SkCanvas* canvas, const SkSamplingOptions& sampling) {
robertphillipsfac9ceb2015-09-03 08:32:08 -070091 SkPaint filterPaint;
robertphillipsfac9ceb2015-09-03 08:32:08 -070092 filterPaint.setAntiAlias(fDoAA);
93
94 SkPaint pathPaint;
Mike Reed8d29ab62021-01-23 18:10:39 -050095 pathPaint.setShader(fBitmapImage->makeShader(sampling));
robertphillipsfac9ceb2015-09-03 08:32:08 -070096 pathPaint.setAntiAlias(fDoAA);
97
98 SkPaint gradPaint1;
99 gradPaint1.setShader(fLinearGrad1);
100 gradPaint1.setAntiAlias(fDoAA);
101 SkPaint gradPaint2;
102 gradPaint2.setShader(fLinearGrad2);
103 gradPaint2.setAntiAlias(fDoAA);
104
105 SkRect r = SkRect::MakeWH(SkIntToScalar(kCellSize), SkIntToScalar(kCellSize));
106
107 canvas->save();
108
109 canvas->save();
110 canvas->concat(fPerspMatrix);
Mike Reed8d29ab62021-01-23 18:10:39 -0500111 canvas->drawImageRect(fBitmapImage, r, sampling, &filterPaint);
robertphillipsfac9ceb2015-09-03 08:32:08 -0700112 canvas->restore();
113
114 canvas->translate(SkIntToScalar(kCellSize), 0);
115 canvas->save();
116 canvas->concat(fPerspMatrix);
Mike Reed8d29ab62021-01-23 18:10:39 -0500117 canvas->drawImage(fImage.get(), 0, 0, sampling, &filterPaint);
robertphillipsfac9ceb2015-09-03 08:32:08 -0700118 canvas->restore();
119
120 canvas->translate(SkIntToScalar(kCellSize), 0);
121 canvas->save();
122 canvas->concat(fPerspMatrix);
123 canvas->drawRect(r, pathPaint);
124 canvas->restore();
125
126 canvas->translate(SkIntToScalar(kCellSize), 0);
127 canvas->save();
128 canvas->concat(fPerspMatrix);
129 canvas->drawPath(fPath, pathPaint);
130 canvas->restore();
131
132 canvas->translate(SkIntToScalar(kCellSize), 0);
133 canvas->save();
134 canvas->concat(fPerspMatrix);
135 canvas->drawRect(r, gradPaint1);
136 canvas->restore();
137
138 canvas->translate(SkIntToScalar(kCellSize), 0);
139 canvas->save();
140 canvas->concat(fPerspMatrix);
141 canvas->drawPath(fPath, gradPaint2);
142 canvas->restore();
143
144 canvas->restore();
145 }
146
147 void onDraw(SkCanvas* canvas) override {
Robert Phillips4a3ebc22020-07-10 11:27:43 -0400148 if (!fImage || !fImage->isValid(canvas->recordingContext())) {
reed9ce9d672016-03-17 10:51:11 -0700149 fImage = make_image(canvas, kCellSize, kCellSize);
robertphillipsfac9ceb2015-09-03 08:32:08 -0700150 }
151
Mike Reed8d29ab62021-01-23 18:10:39 -0500152 this->drawRow(canvas, SkSamplingOptions(SkFilterMode::kNearest));
robertphillipsfac9ceb2015-09-03 08:32:08 -0700153 canvas->translate(0, SkIntToScalar(kCellSize));
Mike Reed8d29ab62021-01-23 18:10:39 -0500154 this->drawRow(canvas, SkSamplingOptions(SkFilterMode::kLinear));
robertphillipsfac9ceb2015-09-03 08:32:08 -0700155 canvas->translate(0, SkIntToScalar(kCellSize));
Mike Reed8d29ab62021-01-23 18:10:39 -0500156 this->drawRow(canvas, SkSamplingOptions(SkFilterMode::kLinear,
157 SkMipmapMode::kNearest));
robertphillipsfac9ceb2015-09-03 08:32:08 -0700158 canvas->translate(0, SkIntToScalar(kCellSize));
Mike Reedf3ac2af2021-02-05 12:55:38 -0500159 this->drawRow(canvas, SkSamplingOptions(SkCubicResampler::Mitchell()));
robertphillipsfac9ceb2015-09-03 08:32:08 -0700160 canvas->translate(0, SkIntToScalar(kCellSize));
161 }
162private:
mtkleindbfd7ab2016-09-01 11:24:54 -0700163 static constexpr int kCellSize = 50;
164 static constexpr int kNumRows = 4;
165 static constexpr int kNumCols = 6;
robertphillipsfac9ceb2015-09-03 08:32:08 -0700166
reed9ce9d672016-03-17 10:51:11 -0700167 bool fDoAA;
168 SkPath fPath;
reed9ce9d672016-03-17 10:51:11 -0700169 sk_sp<SkShader> fLinearGrad1;
170 sk_sp<SkShader> fLinearGrad2;
171 SkMatrix fPerspMatrix;
172 sk_sp<SkImage> fImage;
Mike Reed8d29ab62021-01-23 18:10:39 -0500173 sk_sp<SkImage> fBitmapImage;
robertphillipsfac9ceb2015-09-03 08:32:08 -0700174
John Stiles7571f9e2020-09-02 22:42:33 -0400175 using INHERITED = GM;
robertphillipsfac9ceb2015-09-03 08:32:08 -0700176};
Mike Reedb4068ed2019-12-05 11:55:52 -0500177DEF_GM(return new PerspShadersGM(true);)
178DEF_GM(return new PerspShadersGM(false);)
John Stilesa6841be2020-08-06 14:11:56 -0400179} // namespace skiagm
robertphillipsfac9ceb2015-09-03 08:32:08 -0700180
181//////////////////////////////////////////////////////////////////////////////
182
Mike Reedb4068ed2019-12-05 11:55:52 -0500183#include "tools/Resources.h"
184
185static SkPath make_path() {
186 SkRandom rand;
Mike Reed0483b462019-12-05 17:29:45 -0500187 auto rand_pt = [&rand]() {
188 auto x = rand.nextF();
189 auto y = rand.nextF();
190 return SkPoint{x * 400, y * 400};
191 };
Mike Reedb4068ed2019-12-05 11:55:52 -0500192
193 SkPath path;
194 for (int i = 0; i < 4; ++i) {
Mike Reed0483b462019-12-05 17:29:45 -0500195 SkPoint pts[6];
196 for (auto& p : pts) {
197 p = rand_pt();
198 }
199 path.moveTo(pts[0]).quadTo(pts[1], pts[2]).quadTo(pts[3], pts[4]).lineTo(pts[5]);
Mike Reedb4068ed2019-12-05 11:55:52 -0500200 }
201 return path;
202}
203
204DEF_SIMPLE_GM(perspective_clip, canvas, 800, 800) {
205 SkPath path = make_path();
206 auto shader = GetResourceAsImage("images/mandrill_128.png")
Mike Reedb612b6c2020-12-08 21:58:35 -0500207 ->makeShader(SkSamplingOptions(), SkMatrix::Scale(3, 3));
Mike Reedb4068ed2019-12-05 11:55:52 -0500208
209 SkPaint paint;
210 paint.setColor({0.75, 0.75, 0.75, 1});
211 canvas->drawPath(path, paint);
212
213 // This is a crazy perspective matrix, derived from halfplanes3, to draw a shape where
214 // part of it is "behind" the viewer, hence showing the need for "half-plane" clipping
215 // when in perspective.
216 SkMatrix mx;
217 const SkScalar array[] = {
218 -1.7866f, 1.3357f, 273.0295f,
219 -1.0820f, 1.3186f, 135.5196f,
220 -0.0047f, -0.0015f, 2.1485f,
221 };
222 mx.set9(array);
223
224 paint.setShader(shader);
225 canvas->concat(mx);
226 canvas->drawPath(path, paint);
robertphillipsfac9ceb2015-09-03 08:32:08 -0700227}