1 /*
2  * Copyright 2013 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.h"
9 #include "SkPerlinNoiseShader.h"
10 
11 class PerlinNoiseGM : public skiagm::GM {
12 public:
PerlinNoiseGM()13     PerlinNoiseGM() {
14         this->setBGColor(0xFF000000);
15         fSize = SkISize::Make(80, 80);
16     }
17 
18 protected:
onShortName()19     virtual SkString onShortName() {
20         return SkString("perlinnoise");
21     }
22 
onISize()23     virtual SkISize onISize() {
24         return SkISize::Make(200, 500);
25     }
26 
drawRect(SkCanvas * canvas,int x,int y,const SkPaint & paint,const SkISize & size)27     void drawRect(SkCanvas* canvas, int x, int y, const SkPaint& paint, const SkISize& size) {
28         canvas->save();
29         canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
30         SkRect r = SkRect::MakeWH(SkIntToScalar(size.width()),
31                                   SkIntToScalar(size.height()));
32         canvas->drawRect(r, paint);
33         canvas->restore();
34     }
35 
test(SkCanvas * canvas,int x,int y,SkPerlinNoiseShader::Type type,float baseFrequencyX,float baseFrequencyY,int numOctaves,float seed,bool stitchTiles)36     void test(SkCanvas* canvas, int x, int y, SkPerlinNoiseShader::Type type,
37               float baseFrequencyX, float baseFrequencyY, int numOctaves, float seed,
38               bool stitchTiles) {
39         SkISize tileSize = SkISize::Make(fSize.width() / 2, fSize.height() / 2);
40         SkShader* shader = (type == SkPerlinNoiseShader::kFractalNoise_Type) ?
41             SkPerlinNoiseShader::CreateFractalNoise(baseFrequencyX, baseFrequencyY, numOctaves,
42                                                    seed, stitchTiles ? &tileSize : NULL) :
43             SkPerlinNoiseShader::CreateTurbulence(baseFrequencyX, baseFrequencyY, numOctaves,
44                                                 seed, stitchTiles ? &tileSize : NULL);
45         SkPaint paint;
46         paint.setShader(shader)->unref();
47         if (stitchTiles) {
48             drawRect(canvas, x, y, paint, tileSize);
49             x += tileSize.width();
50             drawRect(canvas, x, y, paint, tileSize);
51             y += tileSize.width();
52             drawRect(canvas, x, y, paint, tileSize);
53             x -= tileSize.width();
54             drawRect(canvas, x, y, paint, tileSize);
55         } else {
56             drawRect(canvas, x, y, paint, fSize);
57         }
58     }
59 
onDraw(SkCanvas * canvas)60     virtual void onDraw(SkCanvas* canvas) {
61         canvas->clear(SK_ColorBLACK);
62         test(canvas,   0,   0, SkPerlinNoiseShader::kFractalNoise_Type,
63              0.1f, 0.1f, 0, 0, false);
64         test(canvas, 100,   0, SkPerlinNoiseShader::kTurbulence_Type,
65              0.1f, 0.1f, 0, 0, false);
66 
67         test(canvas,   0, 100, SkPerlinNoiseShader::kFractalNoise_Type,
68              0.1f, 0.1f, 2, 0, false);
69         test(canvas, 100, 100, SkPerlinNoiseShader::kFractalNoise_Type,
70              0.05f, 0.1f, 1, 0, true);
71 
72         test(canvas,   0, 200, SkPerlinNoiseShader::kTurbulence_Type,
73              0.1f, 0.1f, 1, 0, true);
74         test(canvas, 100, 200, SkPerlinNoiseShader::kTurbulence_Type,
75              0.2f, 0.4f, 5, 0, false);
76 
77         test(canvas,   0, 300, SkPerlinNoiseShader::kFractalNoise_Type,
78              0.1f, 0.1f, 3, 1, false);
79         test(canvas, 100, 300, SkPerlinNoiseShader::kFractalNoise_Type,
80              0.1f, 0.1f, 3, 4, false);
81 
82         canvas->scale(0.75f, 1.0f);
83 
84         test(canvas,   0, 400, SkPerlinNoiseShader::kFractalNoise_Type,
85              0.1f, 0.1f, 2, 0, false);
86         test(canvas, 100, 400, SkPerlinNoiseShader::kFractalNoise_Type,
87              0.1f, 0.05f, 1, 0, true);
88     }
89 
90 private:
91     typedef GM INHERITED;
92     SkISize fSize;
93 };
94 
95 class PerlinNoiseGM2 : public skiagm::GM {
96 public:
PerlinNoiseGM2()97     PerlinNoiseGM2() {
98         fSize = SkISize::Make(80, 80);
99     }
100 
101 protected:
onShortName()102     virtual SkString onShortName() {
103         return SkString("perlinnoise_localmatrix");
104     }
105 
onISize()106     virtual SkISize onISize() {
107         return SkISize::Make(640, 480);
108     }
109 
install(SkPaint * paint,SkPerlinNoiseShader::Type type,float baseFrequencyX,float baseFrequencyY,int numOctaves,float seed,bool stitchTiles)110     void install(SkPaint* paint, SkPerlinNoiseShader::Type type,
111               float baseFrequencyX, float baseFrequencyY, int numOctaves, float seed,
112               bool stitchTiles) {
113         SkShader* shader = (type == SkPerlinNoiseShader::kFractalNoise_Type) ?
114         SkPerlinNoiseShader::CreateFractalNoise(baseFrequencyX, baseFrequencyY, numOctaves,
115                                                 seed, stitchTiles ? &fSize : NULL) :
116         SkPerlinNoiseShader::CreateTurbulence(baseFrequencyX, baseFrequencyY, numOctaves,
117                                               seed, stitchTiles ? &fSize : NULL);
118         paint->setShader(shader)->unref();
119     }
120 
onDraw(SkCanvas * canvas)121     virtual void onDraw(SkCanvas* canvas) {
122         canvas->translate(10, 10);
123 
124         SkPaint paint;
125         install(&paint, SkPerlinNoiseShader::kFractalNoise_Type, 0.1f, 0.1f, 2, 0, false);
126 
127         const SkScalar w = SkIntToScalar(fSize.width());
128         const SkScalar h = SkIntToScalar(fSize.height());
129 
130         SkRect r = SkRect::MakeWH(w, h);
131         canvas->drawRect(r, paint);
132 
133         canvas->save();
134         canvas->translate(w * 5/4, 0);
135         canvas->drawRect(r, paint);
136         canvas->restore();
137 
138         canvas->save();
139         canvas->translate(0, h + 10);
140         canvas->scale(2, 2);
141         canvas->drawRect(r, paint);
142         canvas->restore();
143 
144         canvas->save();
145         canvas->translate(w + 100, h + 10);
146         canvas->scale(2, 2);
147         canvas->drawRect(r, paint);
148         canvas->restore();
149 
150         // The next row should draw the same as the previous, even though we are using a local
151         // matrix instead of the canvas.
152 
153         canvas->translate(0, h * 2 + 10);
154 
155         SkMatrix lm;
156         lm.setScale(2, 2);
157         paint.setShader(SkShader::CreateLocalMatrixShader(paint.getShader(), lm))->unref();
158         r.fRight += r.width();
159         r.fBottom += r.height();
160 
161         canvas->save();
162         canvas->translate(0, h + 10);
163         canvas->drawRect(r, paint);
164         canvas->restore();
165 
166         canvas->save();
167         canvas->translate(w + 100, h + 10);
168         canvas->drawRect(r, paint);
169         canvas->restore();
170     }
171 
172 private:
173     typedef GM INHERITED;
174     SkISize fSize;
175 };
176 
177 //////////////////////////////////////////////////////////////////////////////
178 
179 DEF_GM( return new PerlinNoiseGM; )
180 DEF_GM( return new PerlinNoiseGM2; )
181