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