• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
8 #include "gm/gm.h"
9 #include "include/core/SkBitmap.h"
10 #include "include/core/SkCanvas.h"
11 #include "include/core/SkColor.h"
12 #include "include/core/SkImage.h"
13 #include "include/core/SkImageInfo.h"
14 #include "include/core/SkMatrix.h"
15 #include "include/core/SkPaint.h"
16 #include "include/core/SkPath.h"
17 #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"
24 #include "include/core/SkSurface.h"
25 #include "include/core/SkTileMode.h"
26 #include "include/core/SkTypes.h"
27 #include "include/effects/SkGradientShader.h"
28 #include "tools/ToolUtils.h"
29 
make_image(SkCanvas * origCanvas,int w,int h)30 static sk_sp<SkImage> make_image(SkCanvas* origCanvas, int w, int h) {
31     SkImageInfo info = SkImageInfo::MakeN32Premul(w, h);
32     auto        surface(ToolUtils::makeSurface(origCanvas, info));
33     SkCanvas* canvas = surface->getCanvas();
34 
35     ToolUtils::draw_checkerboard(canvas, SK_ColorRED, SK_ColorGREEN, w / 10);
36     return surface->makeImageSnapshot();
37 }
38 
39 namespace skiagm {
40 
41 class PerspShadersGM : public GM {
42 public:
PerspShadersGM(bool doAA)43     PerspShadersGM(bool doAA) : fDoAA(doAA) { }
44 
45 protected:
onShortName()46     SkString onShortName() override {
47         SkString name;
48         name.printf("persp_shaders_%s",
49                      fDoAA ? "aa" : "bw");
50         return name;
51     }
52 
onISize()53     SkISize onISize() override {
54         return SkISize::Make(kCellSize*kNumCols, kCellSize*kNumRows);
55     }
56 
onOnceBeforeDraw()57     void onOnceBeforeDraw() override {
58         fBitmapImage = ToolUtils::create_checkerboard_image(
59                 kCellSize, kCellSize, SK_ColorBLUE, SK_ColorYELLOW, kCellSize / 10);
60 
61         SkPoint pts1[] = {
62             { 0, 0 },
63             { SkIntToScalar(kCellSize), SkIntToScalar(kCellSize) }
64         };
65         SkPoint pts2[] = {
66             { 0, 0 },
67             { 0, SkIntToScalar(kCellSize) }
68         };
69         constexpr SkColor colors[] = {
70             SK_ColorRED, SK_ColorGREEN, SK_ColorRED, SK_ColorGREEN, SK_ColorRED
71         };
72         constexpr SkScalar pos[] = { 0, 0.25f, 0.5f, 0.75f, SK_Scalar1 };
73 
74         fLinearGrad1 = SkGradientShader::MakeLinear(pts1, colors, pos, SK_ARRAY_COUNT(colors),
75                                                     SkTileMode::kClamp);
76         fLinearGrad2 = SkGradientShader::MakeLinear(pts2, colors, pos, SK_ARRAY_COUNT(colors),
77                                                     SkTileMode::kClamp);
78 
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 
drawRow(SkCanvas * canvas,const SkSamplingOptions & sampling)90     void drawRow(SkCanvas* canvas, const SkSamplingOptions& sampling) {
91         SkPaint filterPaint;
92         filterPaint.setAntiAlias(fDoAA);
93 
94         SkPaint pathPaint;
95         pathPaint.setShader(fBitmapImage->makeShader(sampling));
96         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);
111         canvas->drawImageRect(fBitmapImage, r, sampling, &filterPaint);
112         canvas->restore();
113 
114         canvas->translate(SkIntToScalar(kCellSize), 0);
115         canvas->save();
116         canvas->concat(fPerspMatrix);
117         canvas->drawImage(fImage.get(), 0, 0, sampling, &filterPaint);
118         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 
onDraw(SkCanvas * canvas)147     void onDraw(SkCanvas* canvas) override {
148         if (!fImage || !fImage->isValid(canvas->recordingContext())) {
149             fImage = make_image(canvas, kCellSize, kCellSize);
150         }
151 
152         this->drawRow(canvas, SkSamplingOptions(SkFilterMode::kNearest));
153         canvas->translate(0, SkIntToScalar(kCellSize));
154         this->drawRow(canvas, SkSamplingOptions(SkFilterMode::kLinear));
155         canvas->translate(0, SkIntToScalar(kCellSize));
156         this->drawRow(canvas, SkSamplingOptions(SkFilterMode::kLinear,
157                                                 SkMipmapMode::kNearest));
158         canvas->translate(0, SkIntToScalar(kCellSize));
159         this->drawRow(canvas, SkSamplingOptions(SkCubicResampler::Mitchell()));
160         canvas->translate(0, SkIntToScalar(kCellSize));
161     }
162 private:
163     inline static constexpr int kCellSize = 50;
164     inline static constexpr int kNumRows = 4;
165     inline static constexpr int kNumCols = 6;
166 
167     bool            fDoAA;
168     SkPath          fPath;
169     sk_sp<SkShader> fLinearGrad1;
170     sk_sp<SkShader> fLinearGrad2;
171     SkMatrix        fPerspMatrix;
172     sk_sp<SkImage>  fImage;
173     sk_sp<SkImage>  fBitmapImage;
174 
175     using INHERITED = GM;
176 };
177 DEF_GM(return new PerspShadersGM(true);)
178 DEF_GM(return new PerspShadersGM(false);)
179 }  // namespace skiagm
180 
181 //////////////////////////////////////////////////////////////////////////////
182 
183 #include "tools/Resources.h"
184 
make_path()185 static SkPath make_path() {
186     SkRandom rand;
187     auto rand_pt = [&rand]() {
188         auto x = rand.nextF();
189         auto y = rand.nextF();
190         return SkPoint{x * 400, y * 400};
191     };
192 
193     SkPath path;
194     for (int i = 0; i < 4; ++i) {
195         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]);
200     }
201     return path;
202 }
203 
204 DEF_SIMPLE_GM(perspective_clip, canvas, 800, 800) {
205     SkPath path = make_path();
206     auto shader = GetResourceAsImage("images/mandrill_128.png")
207                                     ->makeShader(SkSamplingOptions(), SkMatrix::Scale(3, 3));
208 
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);
227 }
228