[canvaskit] Add test and extern for MakeImage

This was originally exposed for use with specs/web-img-decode and has
seen some actual use.

Change-Id: I6cc4fdf431b45cbbc21b91881c688c5545ca44a3
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/257317
Reviewed-by: Kevin Lubick <kjlubick@google.com>
diff --git a/modules/canvaskit/CHANGELOG.md b/modules/canvaskit/CHANGELOG.md
index 3474800..0a47ec5 100644
--- a/modules/canvaskit/CHANGELOG.md
+++ b/modules/canvaskit/CHANGELOG.md
@@ -15,6 +15,9 @@
  - The returned values from `SkParagraph.getRectsForRange` now have direction with value
    `CanvasKit.TextDirection`.
 
+### Fixed
+ - `MakeImage` properly in the externs file and can work with `CanvasKit.Malloc`.
+
 ## [0.9.0] - 2019-11-18
 ### Added
  - Experimental `CanvasKit.Malloc`, which can be used to create a
diff --git a/modules/canvaskit/externs.js b/modules/canvaskit/externs.js
index c071df1..2ad2cb3 100644
--- a/modules/canvaskit/externs.js
+++ b/modules/canvaskit/externs.js
@@ -42,6 +42,8 @@
 	/** @return {CanvasKit.SkAnimatedImage} */
 	MakeAnimatedImageFromEncoded: function() {},
 	/** @return {CanvasKit.SkImage} */
+	MakeImage: function() {},
+	/** @return {CanvasKit.SkImage} */
 	MakeImageFromEncoded: function() {},
 	/** @return {LinearCanvasGradient} */
 	MakeLinearGradientShader: function() {},
diff --git a/modules/canvaskit/interface.js b/modules/canvaskit/interface.js
index a859cbd..294e5db 100644
--- a/modules/canvaskit/interface.js
+++ b/modules/canvaskit/interface.js
@@ -1065,20 +1065,20 @@
   return img;
 }
 
-// pixels is a Uint8Array
+// pixels must be a Uint8Array with bytes representing the pixel values
+// (e.g. each set of 4 bytes could represent RGBA values for a single pixel).
 CanvasKit.MakeImage = function(pixels, width, height, alphaType, colorType) {
-  var bytesPerPixel = pixels.byteLength / (width * height);
+  var bytesPerPixel = pixels.length / (width * height);
   var info = {
     'width': width,
     'height': height,
     'alphaType': alphaType,
     'colorType': colorType,
   };
-  var pptr = CanvasKit._malloc(pixels.byteLength);
-  CanvasKit.HEAPU8.set(pixels, pptr);
-  // No need to _free iptr, Image takes it with SkData::MakeFromMalloc
+  var pptr = copy1dArray(pixels, CanvasKit.HEAPU8);
+  // No need to _free pptr, Image takes it with SkData::MakeFromMalloc
 
-  return CanvasKit._MakeImage(info, pptr, pixels.byteLength, width * bytesPerPixel);
+  return CanvasKit._MakeImage(info, pptr, pixels.length, width * bytesPerPixel);
 }
 
 CanvasKit.MakeLinearGradientShader = function(start, end, colors, pos, mode, localMatrix, flags) {
diff --git a/modules/canvaskit/tests/core.spec.js b/modules/canvaskit/tests/core.spec.js
index 481c4bb..2f90062 100644
--- a/modules/canvaskit/tests/core.spec.js
+++ b/modules/canvaskit/tests/core.spec.js
@@ -76,7 +76,7 @@
                 let img = CanvasKit.MakeImageFromEncoded(pngData);
                 expect(img).toBeTruthy();
                 const surface = CanvasKit.MakeCanvasSurface('test');
-                expect(surface).toBeTruthy('Could not make surface')
+                expect(surface).toBeTruthy('Could not make surface');
                 if (!surface) {
                     done();
                     return;
@@ -103,7 +103,7 @@
                 let img = CanvasKit.MakeImageFromEncoded(jpgData);
                 expect(img).toBeTruthy();
                 const surface = CanvasKit.MakeCanvasSurface('test');
-                expect(surface).toBeTruthy('Could not make surface')
+                expect(surface).toBeTruthy('Could not make surface');
                 if (!surface) {
                     done();
                     return;
@@ -130,7 +130,7 @@
                 let img = CanvasKit.MakeImageFromEncoded(gifData);
                 expect(img).toBeTruthy();
                 const surface = CanvasKit.MakeCanvasSurface('test');
-                expect(surface).toBeTruthy('Could not make surface')
+                expect(surface).toBeTruthy('Could not make surface');
                 if (!surface) {
                     done();
                     return;
@@ -162,7 +162,7 @@
                 expect(aImg.getFrameCount()).toEqual(60);
 
                 const surface = CanvasKit.MakeCanvasSurface('test');
-                expect(surface).toBeTruthy('Could not make surface')
+                expect(surface).toBeTruthy('Could not make surface');
                 if (!surface) {
                     done();
                     return;
@@ -182,7 +182,7 @@
                     c = aImg.decodeNextFrame();
                     expect(c).not.toEqual(-1);
                 }
-                 canvas.drawAnimatedImage(aImg, 300, 300);
+                canvas.drawAnimatedImage(aImg, 300, 300);
 
                 aImg.delete();
 
@@ -191,10 +191,37 @@
         });
     });
 
+    it('can create an image "from scratch" by specifying pixels/colorInfo manually', function(done) {
+        LoadCanvasKit.then(catchException(done, () => {
+            const surface = CanvasKit.MakeCanvasSurface('test');
+            expect(surface).toBeTruthy('Could not make surface');
+            if (!surface) {
+                done();
+                return;
+            }
+            const canvas = surface.getCanvas();
+            canvas.clear(CanvasKit.WHITE);
+            const paint = new CanvasKit.SkPaint();
+
+            // This creates and draws an SkImage that is 1 pixel wide, 4 pixels tall with
+            // the colors listed below.
+            const pixels = Uint8Array.from([
+                255,   0,   0, 255, // opaque red
+                  0, 255,   0, 255, // opaque green
+                  0,   0, 255, 255, // opaque blue
+                255,   0, 255, 100, // transparent purple
+            ]);
+            const img = CanvasKit.MakeImage(pixels, 1, 4, CanvasKit.AlphaType.Unpremul, CanvasKit.ColorType.RGBA_8888);
+            canvas.drawImage(img, 1, 1, paint);
+
+            reportSurface(surface, '1x4_from_scratch', done);
+        }));
+    });
+
     it('can blur using ImageFilter or MaskFilter', function(done) {
         LoadCanvasKit.then(catchException(done, () => {
             const surface = CanvasKit.MakeCanvasSurface('test');
-            expect(surface).toBeTruthy('Could not make surface')
+            expect(surface).toBeTruthy('Could not make surface');
             if (!surface) {
                 done();
                 return;
@@ -241,7 +268,7 @@
                 let img = CanvasKit.MakeImageFromEncoded(pngData);
                 expect(img).toBeTruthy();
                 const surface = CanvasKit.MakeCanvasSurface('test');
-                expect(surface).toBeTruthy('Could not make surface')
+                expect(surface).toBeTruthy('Could not make surface');
                 if (!surface) {
                     done();
                     return;