2018-10-17 11:57:18 +00:00
|
|
|
// Adds compile-time JS functions to augment the CanvasKit interface.
|
2020-05-29 23:51:21 +00:00
|
|
|
// Implementations in this file are considerate of GPU builds, i.e. some
|
|
|
|
// behavior is predicated on whether or not this is being compiled alongside
|
|
|
|
// gpu.js.
|
2018-10-17 11:57:18 +00:00
|
|
|
(function(CanvasKit){
|
|
|
|
CanvasKit._extraInitializations = CanvasKit._extraInitializations || [];
|
|
|
|
CanvasKit._extraInitializations.push(function() {
|
2019-01-03 21:20:04 +00:00
|
|
|
// Takes in an html id or a canvas element
|
|
|
|
CanvasKit.MakeSWCanvasSurface = function(idOrElement) {
|
2020-11-11 21:48:30 +00:00
|
|
|
var canvas = idOrElement;
|
|
|
|
if (canvas.tagName !== 'CANVAS') {
|
|
|
|
// TODO(nifong): unit test
|
|
|
|
canvas = document.getElementById(idOrElement);
|
|
|
|
if (!canvas) {
|
|
|
|
throw 'Canvas with id ' + idOrElement + ' was not found';
|
2019-01-03 21:20:04 +00:00
|
|
|
}
|
2020-11-11 21:48:30 +00:00
|
|
|
}
|
2018-10-17 11:57:18 +00:00
|
|
|
// Maybe better to use clientWidth/height. See:
|
|
|
|
// https://webglfundamentals.org/webgl/lessons/webgl-anti-patterns.html
|
2020-11-12 14:11:47 +00:00
|
|
|
var surface = CanvasKit.MakeSurface(canvas.width, canvas.height);
|
2018-10-17 11:57:18 +00:00
|
|
|
if (surface) {
|
|
|
|
surface._canvas = canvas;
|
|
|
|
}
|
|
|
|
return surface;
|
|
|
|
};
|
|
|
|
|
2018-11-20 19:07:42 +00:00
|
|
|
// Don't over-write the MakeCanvasSurface set by gpu.js if it exists.
|
|
|
|
if (!CanvasKit.MakeCanvasSurface) {
|
|
|
|
CanvasKit.MakeCanvasSurface = CanvasKit.MakeSWCanvasSurface;
|
|
|
|
}
|
|
|
|
|
2020-05-26 17:10:20 +00:00
|
|
|
// Note that color spaces are currently not supported in CPU surfaces. due to the limitation
|
2020-09-29 21:51:57 +00:00
|
|
|
// canvas.getContext('2d').putImageData imposes a limitation of using an RGBA_8888 color type.
|
2020-05-26 17:10:20 +00:00
|
|
|
// TODO(nifong): support WGC color spaces while still using an RGBA_8888 color type when
|
|
|
|
// on a cpu backend.
|
2018-10-17 11:57:18 +00:00
|
|
|
CanvasKit.MakeSurface = function(width, height) {
|
2018-11-30 19:05:58 +00:00
|
|
|
var imageInfo = {
|
|
|
|
'width': width,
|
|
|
|
'height': height,
|
|
|
|
'colorType': CanvasKit.ColorType.RGBA_8888,
|
2020-11-12 14:11:47 +00:00
|
|
|
// Since we are sending these pixels directly into the HTML canvas,
|
|
|
|
// (and those pixels are un-premultiplied, i.e. straight r,g,b,a)
|
|
|
|
'alphaType': CanvasKit.AlphaType.Unpremul,
|
2020-10-07 20:09:22 +00:00
|
|
|
'colorSpace': CanvasKit.ColorSpace.SRGB,
|
2020-11-11 21:48:30 +00:00
|
|
|
};
|
2020-11-12 14:11:47 +00:00
|
|
|
var pixelLen = width * height * 4; // it's 8888, so 4 bytes per pixel
|
|
|
|
// Allocate the buffer of pixels to be drawn into.
|
|
|
|
var pixelPtr = CanvasKit._malloc(pixelLen);
|
|
|
|
|
|
|
|
// Experiments with using RasterDirect vs Raster showed a 10% slowdown
|
|
|
|
// over the traditional Surface::MakeRaster approach. This was exacerbated when
|
|
|
|
// the surface was drawing to Premul and we had to convert to Unpremul each frame
|
|
|
|
// (up to a 10x further slowdown).
|
|
|
|
var surface = CanvasKit.Surface._makeRasterDirect(imageInfo, pixelPtr, width*4);
|
|
|
|
if (surface) {
|
|
|
|
surface._canvas = null;
|
|
|
|
surface._width = width;
|
|
|
|
surface._height = height;
|
|
|
|
surface._pixelLen = pixelLen;
|
|
|
|
|
|
|
|
surface._pixelPtr = pixelPtr;
|
|
|
|
// rasterDirectSurface does not initialize the pixels, so we clear them
|
|
|
|
// to transparent black.
|
|
|
|
surface.getCanvas().clear(CanvasKit.TRANSPARENT);
|
|
|
|
}
|
|
|
|
return surface;
|
2018-10-17 11:57:18 +00:00
|
|
|
};
|
|
|
|
|
2020-11-04 12:23:37 +00:00
|
|
|
CanvasKit.MakeRasterDirectSurface = function(imageInfo, mallocObj, bytesPerRow) {
|
2020-11-11 21:48:30 +00:00
|
|
|
return CanvasKit.Surface._makeRasterDirect(imageInfo, mallocObj['byteOffset'], bytesPerRow);
|
2020-11-04 12:23:37 +00:00
|
|
|
};
|
|
|
|
|
2020-05-29 23:51:21 +00:00
|
|
|
// For GPU builds, simply proxies to native code flush. For CPU builds,
|
|
|
|
// also updates the underlying HTML canvas, optionally with dirtyRect.
|
2020-10-07 20:09:22 +00:00
|
|
|
CanvasKit.Surface.prototype.flush = function(dirtyRect) {
|
2018-10-17 11:57:18 +00:00
|
|
|
this._flush();
|
|
|
|
// Do we have an HTML canvas to write the pixels to?
|
2020-11-11 21:48:30 +00:00
|
|
|
// We will not have a canvas if this a GPU build, for example.
|
2018-10-17 11:57:18 +00:00
|
|
|
if (this._canvas) {
|
2020-01-14 21:46:30 +00:00
|
|
|
var pixels = new Uint8ClampedArray(CanvasKit.HEAPU8.buffer, this._pixelPtr, this._pixelLen);
|
2018-10-17 11:57:18 +00:00
|
|
|
var imageData = new ImageData(pixels, this._width, this._height);
|
|
|
|
|
2020-05-29 23:51:21 +00:00
|
|
|
if (!dirtyRect) {
|
|
|
|
this._canvas.getContext('2d').putImageData(imageData, 0, 0);
|
|
|
|
} else {
|
|
|
|
this._canvas.getContext('2d').putImageData(imageData, 0, 0,
|
2020-09-03 14:02:10 +00:00
|
|
|
dirtyRect[0], dirtyRect[1],
|
|
|
|
dirtyRect[2] - dirtyRect[0],
|
|
|
|
dirtyRect[3] - dirtyRect[1]);
|
2020-05-29 23:51:21 +00:00
|
|
|
}
|
2018-10-17 11:57:18 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-09-29 21:51:57 +00:00
|
|
|
// Call dispose() instead of delete to clean up the underlying memory.
|
|
|
|
// TODO(kjlubick) get rid of this and just wrap around delete().
|
2020-10-07 20:09:22 +00:00
|
|
|
CanvasKit.Surface.prototype.dispose = function() {
|
2018-10-17 11:57:18 +00:00
|
|
|
if (this._pixelPtr) {
|
|
|
|
CanvasKit._free(this._pixelPtr);
|
|
|
|
}
|
|
|
|
this.delete();
|
2020-11-12 14:11:47 +00:00
|
|
|
};
|
2018-10-17 11:57:18 +00:00
|
|
|
|
2018-11-20 19:07:42 +00:00
|
|
|
CanvasKit.currentContext = CanvasKit.currentContext || function() {
|
|
|
|
// no op if this is a cpu-only build.
|
2018-10-17 11:57:18 +00:00
|
|
|
};
|
|
|
|
|
2018-11-20 19:07:42 +00:00
|
|
|
CanvasKit.setCurrentContext = CanvasKit.setCurrentContext || function() {
|
|
|
|
// no op if this is a cpu-only build.
|
2018-10-17 11:57:18 +00:00
|
|
|
};
|
|
|
|
});
|
|
|
|
}(Module)); // When this file is loaded in, the high level object is "Module";
|