[canvaskit] Expose Perlin Noise shaders.

Change-Id: I2515efb06dd1a2b02f71922503462572eea0f346
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/327197
Reviewed-by: Nathaniel Nifong <nifong@google.com>
Reviewed-by: Florin Malita <fmalita@chromium.org>
diff --git a/modules/canvaskit/CHANGELOG.md b/modules/canvaskit/CHANGELOG.md
index 7dddc08..440dbc6 100644
--- a/modules/canvaskit/CHANGELOG.md
+++ b/modules/canvaskit/CHANGELOG.md
@@ -6,6 +6,10 @@
 
 ## [Unreleased]
 
+## Added
+ - `MakeFractalNoise`, `MakeImprovedNoise`, and `MakeTurbulence` have been added to
+   `CanvasKit.Shader`.
+
 ### Breaking
  - `CanvasKit.MakePathFromSVGString` was renamed to `CanvasKit.Path.MakeFromSVGString`
  - `CanvasKit.MakePathFromOp` was renamed to `CanvasKit.Path.MakeFromOp`
@@ -14,7 +18,7 @@
  - We now compile CanvasKit with emsdk 2.0.6 when testing and deploying to npm.
  - We no longer compile with rtti on, saving about 1% in code size.
  - `CanvasKit.Shader.Blend`, `...Color`, and `...Lerp` have been renamed to
-   `CanvasKit.Shader.MakeBlend`, `...MakeColor` and `...MakeLerp` to allign with naming conventions.
+   `CanvasKit.Shader.MakeBlend`, `...MakeColor` and `...MakeLerp` to align with naming conventions.
    The old names will be removed in an upcoming release.
 
 ### Removed
diff --git a/modules/canvaskit/canvaskit/types/canvaskit-wasm-tests.ts b/modules/canvaskit/canvaskit/types/canvaskit-wasm-tests.ts
index 03f41ea..76078a1 100644
--- a/modules/canvaskit/canvaskit/types/canvaskit-wasm-tests.ts
+++ b/modules/canvaskit/canvaskit/types/canvaskit-wasm-tests.ts
@@ -740,6 +740,9 @@
         15, 275, // start, end angle in degrees.
         CK.ColorSpace.SRGB,
     );
+    const s12 = CK.Shader.MakeFractalNoise(0.1, 0.05, 2, 0, 80, 80); // $ExpectType Shader
+    const s13 = CK.Shader.MakeTurbulence(0.1, 0.05, 2, 0, 80, 80); // $ExpectType Shader
+    const s14 = CK.Shader.MakeImprovedNoise(0.1, 0.05, 2, 0); // $ExpectType Shader
 }
 
 function shapedTextTests(CK: CanvasKit, textFont?: Font) {
diff --git a/modules/canvaskit/canvaskit/types/index.d.ts b/modules/canvaskit/canvaskit/types/index.d.ts
index 0fa6c6c..0d0ea6f 100644
--- a/modules/canvaskit/canvaskit/types/index.d.ts
+++ b/modules/canvaskit/canvaskit/types/index.d.ts
@@ -2942,6 +2942,31 @@
     MakeColor(color: InputColor, space: ColorSpace): Shader;
 
     /**
+     * Returns a shader with Perlin Fractal Noise.
+     * See SkPerlinNoiseShader.h for more details
+     * @param baseFreqX - base frequency in the X direction; range [0.0, 1.0]
+     * @param baseFreqY - base frequency in the Y direction; range [0.0, 1.0]
+     * @param octaves
+     * @param seed
+     * @param tileW - if this and tileH are non-zero, the frequencies will be modified so that the
+     *                noise will be tileable for the given size.
+     * @param tileH - if this and tileW are non-zero, the frequencies will be modified so that the
+     *                noise will be tileable for the given size.
+     */
+    MakeFractalNoise(baseFreqX: number, baseFreqY: number, octaves: number, seed: number,
+                     tileW: number, tileH: number): Shader;
+
+    /**
+     * Returns a shader with Improved Perlin Noise.
+     * See SkPerlinNoiseShader.h for more details
+     * @param baseFreqX - base frequency in the X direction; range [0.0, 1.0]
+     * @param baseFreqY - base frequency in the Y direction; range [0.0, 1.0]
+     * @param octaves
+     * @param z - like seed, but minor variations to z will only slightly change the noise.
+     */
+    MakeImprovedNoise(baseFreqX: number, baseFreqY: number, octaves: number, z: number): Shader;
+
+    /**
      * Returns a shader is a linear interpolation combines the given shaders with a BlendMode.
      * @param t - range of [0.0, 1.0], indicating how far we should be between one and two.
      * @param one
@@ -3007,6 +3032,21 @@
                       colorSpace?: ColorSpace): Shader;
 
     /**
+     * Returns a shader with Perlin Turbulence.
+     * See SkPerlinNoiseShader.h for more details
+     * @param baseFreqX - base frequency in the X direction; range [0.0, 1.0]
+     * @param baseFreqY - base frequency in the Y direction; range [0.0, 1.0]
+     * @param octaves
+     * @param seed
+     * @param tileW - if this and tileH are non-zero, the frequencies will be modified so that the
+     *                noise will be tileable for the given size.
+     * @param tileH - if this and tileW are non-zero, the frequencies will be modified so that the
+     *                noise will be tileable for the given size.
+     */
+    MakeTurbulence(baseFreqX: number, baseFreqY: number, octaves: number, seed: number,
+                   tileW: number, tileH: number): Shader;
+
+    /**
      * Returns a shader that generates a conical gradient given two circles.
      * See SkGradientShader.h for more.
      * @param start
diff --git a/modules/canvaskit/canvaskit_bindings.cpp b/modules/canvaskit/canvaskit_bindings.cpp
index a51e930..538a3c8 100644
--- a/modules/canvaskit/canvaskit_bindings.cpp
+++ b/modules/canvaskit/canvaskit_bindings.cpp
@@ -44,6 +44,7 @@
 #include "include/effects/SkDiscretePathEffect.h"
 #include "include/effects/SkGradientShader.h"
 #include "include/effects/SkImageFilters.h"
+#include "include/effects/SkPerlinNoiseShader.h"
 #include "include/effects/SkRuntimeEffect.h"
 #include "include/effects/SkTrimPathEffect.h"
 #include "include/utils/SkParsePath.h"
@@ -1490,6 +1491,16 @@
             })
         )
         .class_function("MakeLerp", select_overload<sk_sp<SkShader>(float, sk_sp<SkShader>, sk_sp<SkShader>)>(&SkShaders::Lerp))
+        .class_function("MakeFractalNoise", optional_override([](
+                                                SkScalar baseFreqX, SkScalar baseFreqY,
+                                                int numOctaves, SkScalar seed,
+                                                int tileW, int tileH)->sk_sp<SkShader> {
+            // if tileSize is empty (e.g. tileW <= 0 or tileH <= 0, it will be ignored.
+            SkISize tileSize = SkISize::Make(tileW, tileH);
+            return SkPerlinNoiseShader::MakeFractalNoise(baseFreqX, baseFreqY,
+                                                         numOctaves, seed, &tileSize);
+        }))
+        .class_function("MakeImprovedNoise", &SkPerlinNoiseShader::MakeImprovedNoise)
          // Here and in other gradient functions, cPtr is a pointer to an array of data
          // representing colors. whether this is an array of SkColor or SkColor4f is indicated
          // by the colorType argument. Only RGBA_8888 and RGBA_F32 are accepted.
@@ -1559,6 +1570,15 @@
             SkDebugf("%d is not an accepted colorType\n", colorType);
             return nullptr;
         }), allow_raw_pointers())
+        .class_function("MakeTurbulence", optional_override([](
+                                                SkScalar baseFreqX, SkScalar baseFreqY,
+                                                int numOctaves, SkScalar seed,
+                                                int tileW, int tileH)->sk_sp<SkShader> {
+            // if tileSize is empty (e.g. tileW <= 0 or tileH <= 0, it will be ignored.
+            SkISize tileSize = SkISize::Make(tileW, tileH);
+            return SkPerlinNoiseShader::MakeTurbulence(baseFreqX, baseFreqY,
+                                                       numOctaves, seed, &tileSize);
+        }))
         .class_function("_MakeTwoPointConicalGradient", optional_override([](
                                          SkPoint start, SkScalar startRadius,
                                          SkPoint end, SkScalar endRadius,
diff --git a/modules/canvaskit/externs.js b/modules/canvaskit/externs.js
index 47913b6..9c8d1f3 100644
--- a/modules/canvaskit/externs.js
+++ b/modules/canvaskit/externs.js
@@ -604,14 +604,17 @@
     Blend: function() {},
     Color: function() {},
     Lerp: function() {},
-    // public API (from JS)
+    // public API (from JS / C++ bindings)
     MakeBlend: function() {},
     MakeColor: function() {},
+    MakeFractalNoise: function() {},
+    MakeImprovedNoise: function() {},
     MakeLerp: function() {},
     MakeLinearGradient: function() {},
     MakeRadialGradient: function() {},
-    MakeTwoPointConicalGradient: function() {},
     MakeSweepGradient: function() {},
+    MakeTurbulence: function() {},
+    MakeTwoPointConicalGradient: function() {},
 
     // private API (from C++ bindings)
     _MakeColor: function() {},
diff --git a/modules/canvaskit/tests/core.spec.js b/modules/canvaskit/tests/core.spec.js
index f359b99..82ce600 100644
--- a/modules/canvaskit/tests/core.spec.js
+++ b/modules/canvaskit/tests/core.spec.js
@@ -827,6 +827,56 @@
                               CanvasKit.BLACK, CanvasKit.MAGENTA, flags);
     })
 
+    gm('fractal_noise_shader', (canvas) => {
+        const shader = CanvasKit.Shader.MakeFractalNoise(0.1, 0.05, 2, 0, 0, 0);
+        const paint = new CanvasKit.Paint();
+        paint.setColor(CanvasKit.BLACK);
+        paint.setShader(shader);
+        canvas.drawPaint(paint);
+        paint.delete();
+        shader.delete();
+    });
+
+    gm('turbulance_shader', (canvas) => {
+        const shader = CanvasKit.Shader.MakeTurbulence(0.1, 0.05, 2, 117, 0, 0);
+        const paint = new CanvasKit.Paint();
+        paint.setColor(CanvasKit.BLACK);
+        paint.setShader(shader);
+        canvas.drawPaint(paint);
+        paint.delete();
+        shader.delete();
+    });
+
+    gm('fractal_noise_tiled_shader', (canvas) => {
+        const shader = CanvasKit.Shader.MakeFractalNoise(0.1, 0.05, 2, 0, 80, 80);
+        const paint = new CanvasKit.Paint();
+        paint.setColor(CanvasKit.BLACK);
+        paint.setShader(shader);
+        canvas.drawPaint(paint);
+        paint.delete();
+        shader.delete();
+    });
+
+    gm('turbulance_tiled_shader', (canvas) => {
+        const shader = CanvasKit.Shader.MakeTurbulence(0.1, 0.05, 2, 117, 80, 80);
+        const paint = new CanvasKit.Paint();
+        paint.setColor(CanvasKit.BLACK);
+        paint.setShader(shader);
+        canvas.drawPaint(paint);
+        paint.delete();
+        shader.delete();
+    });
+
+    gm('improved_noise_shader', (canvas) => {
+        const shader = CanvasKit.Shader.MakeImprovedNoise(0.1, 0.05, 2, 10);
+        const paint = new CanvasKit.Paint();
+        paint.setColor(CanvasKit.BLACK);
+        paint.setShader(shader);
+        canvas.drawPaint(paint);
+        paint.delete();
+        shader.delete();
+    });
+
     describe('ColorSpace Support', () => {
         it('Can create an SRGB 8888 surface', () => {
             const colorSpace = CanvasKit.ColorSpace.SRGB;