[canvaskit] Replace RRect objects with TypedArrays.
This is about 2.5x faster. Will try to do the same for Rects in a followup CL. Change-Id: Ia1ba1381435f4eee2fcf4f0cc2738e3306edd5f9 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/312304 Reviewed-by: Nathaniel Nifong <nifong@google.com>
This commit is contained in:
parent
2ff9706328
commit
c9498efc8e
@ -6,6 +6,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Breaking
|
||||
- SkRRect (Rectangles with rounded corners) are no longer returned from `CanvasKit.RRectXY`
|
||||
nor accepted as JS objects. Instead, the format is 12 floats in either an array, a
|
||||
Float32Array or a piece of memory returned by CanvasKit.Malloc. The first 4 floats
|
||||
are the left, top, right, bottom numbers of the rectangle and then 4 sets of points
|
||||
starting in the upper left corner and going clockwise. This change allows for faster
|
||||
transfer between JS and WASM code.
|
||||
|
||||
### Changed
|
||||
- We now compile CanvasKit with emsdk 2.0.0 when testing and deploying to npm.
|
||||
- WebGL interface creation is a little leaner in terms of code size and speed.
|
||||
|
@ -106,6 +106,19 @@ SkColor4f ptrToSkColor4f(uintptr_t /* float* */ cPtr) {
|
||||
return color;
|
||||
}
|
||||
|
||||
SkRRect ptrToSkRRect(uintptr_t /* float* */ fPtr) {
|
||||
// In order, these floats should be 4 floats for the rectangle
|
||||
// (left, top, right, bottom) and then 8 floats for the radii
|
||||
// (upper left, upper right, lower right, lower left).
|
||||
const SkScalar* twelveFloats = reinterpret_cast<const SkScalar*>(fPtr);
|
||||
const SkRect rect = reinterpret_cast<const SkRect*>(twelveFloats)[0];
|
||||
const SkVector* radiiValues = reinterpret_cast<const SkVector*>(twelveFloats + 4);
|
||||
|
||||
SkRRect rr;
|
||||
rr.setRectRadii(rect, radiiValues);
|
||||
return rr;
|
||||
}
|
||||
|
||||
// Surface creation structs and helpers
|
||||
struct SimpleImageInfo {
|
||||
int width;
|
||||
@ -689,28 +702,6 @@ struct PosTan {
|
||||
SkScalar px, py, tx, ty;
|
||||
};
|
||||
|
||||
// SimpleRRect is simpler than passing a (complex) SkRRect over the wire to JS.
|
||||
struct SimpleRRect {
|
||||
SkRect rect;
|
||||
|
||||
SkScalar rx1;
|
||||
SkScalar ry1;
|
||||
SkScalar rx2;
|
||||
SkScalar ry2;
|
||||
SkScalar rx3;
|
||||
SkScalar ry3;
|
||||
SkScalar rx4;
|
||||
SkScalar ry4;
|
||||
};
|
||||
|
||||
SkRRect toRRect(const SimpleRRect& r) {
|
||||
SkVector fRadii[4] = {{r.rx1, r.ry1}, {r.rx2, r.ry2},
|
||||
{r.rx3, r.ry3}, {r.rx4, r.ry4}};
|
||||
SkRRect rr;
|
||||
rr.setRectRadii(r.rect, fRadii);
|
||||
return rr;
|
||||
}
|
||||
|
||||
// This function is private, we call it in interface.js
|
||||
void computeTonalColors(uintptr_t cPtrAmbi /* float * */, uintptr_t cPtrSpot /* float * */) {
|
||||
// private methods accepting colors take pointers to floats already copied into wasm memory.
|
||||
@ -1003,8 +994,8 @@ EMSCRIPTEN_BINDINGS(Skia) {
|
||||
self.clear(ptrToSkColor4f(cPtr));
|
||||
}))
|
||||
.function("clipPath", select_overload<void (const SkPath&, SkClipOp, bool)>(&SkCanvas::clipPath))
|
||||
.function("clipRRect", optional_override([](SkCanvas& self, const SimpleRRect& r, SkClipOp op, bool doAntiAlias) {
|
||||
self.clipRRect(toRRect(r), op, doAntiAlias);
|
||||
.function("_clipRRect", optional_override([](SkCanvas& self, uintptr_t /* float* */ fPtr, SkClipOp op, bool doAntiAlias) {
|
||||
self.clipRRect(ptrToSkRRect(fPtr), op, doAntiAlias);
|
||||
}))
|
||||
.function("clipRect", select_overload<void (const SkRect&, SkClipOp, bool)>(&SkCanvas::clipRect))
|
||||
.function("_concat", optional_override([](SkCanvas& self, uintptr_t /* SkScalar* */ mPtr) {
|
||||
@ -1042,8 +1033,9 @@ EMSCRIPTEN_BINDINGS(Skia) {
|
||||
.function("drawColorInt", optional_override([](SkCanvas& self, SkColor color, SkBlendMode mode) {
|
||||
self.drawColor(color, mode);
|
||||
}))
|
||||
.function("drawDRRect",optional_override([](SkCanvas& self, const SimpleRRect& o, const SimpleRRect& i, const SkPaint& paint) {
|
||||
self.drawDRRect(toRRect(o), toRRect(i), paint);
|
||||
.function("_drawDRRect",optional_override([](SkCanvas& self, uintptr_t /* float* */ outerPtr,
|
||||
uintptr_t /* float* */ innerPtr, const SkPaint& paint) {
|
||||
self.drawDRRect(ptrToSkRRect(outerPtr), ptrToSkRRect(innerPtr), paint);
|
||||
}))
|
||||
.function("drawAnimatedImage", optional_override([](SkCanvas& self, sk_sp<SkAnimatedImage>& aImg,
|
||||
SkScalar x, SkScalar y)->void {
|
||||
@ -1082,8 +1074,8 @@ EMSCRIPTEN_BINDINGS(Skia) {
|
||||
const SkPoint* pts = reinterpret_cast<const SkPoint*>(pptr);
|
||||
self.drawPoints(mode, count, pts, paint);
|
||||
}))
|
||||
.function("drawRRect",optional_override([](SkCanvas& self, const SimpleRRect& r, const SkPaint& paint) {
|
||||
self.drawRRect(toRRect(r), paint);
|
||||
.function("_drawRRect",optional_override([](SkCanvas& self, uintptr_t /* float* */ fPtr, const SkPaint& paint) {
|
||||
self.drawRRect(ptrToSkRRect(fPtr), paint);
|
||||
}))
|
||||
.function("drawRect", &SkCanvas::drawRect)
|
||||
.function("drawRoundRect", &SkCanvas::drawRoundRect)
|
||||
@ -1858,17 +1850,6 @@ EMSCRIPTEN_BINDINGS(Skia) {
|
||||
.field("fRight", &SkRect::fRight)
|
||||
.field("fBottom", &SkRect::fBottom);
|
||||
|
||||
value_object<SimpleRRect>("SkRRect")
|
||||
.field("rect", &SimpleRRect::rect)
|
||||
.field("rx1", &SimpleRRect::rx1)
|
||||
.field("ry1", &SimpleRRect::ry1)
|
||||
.field("rx2", &SimpleRRect::rx2)
|
||||
.field("ry2", &SimpleRRect::ry2)
|
||||
.field("rx3", &SimpleRRect::rx3)
|
||||
.field("ry3", &SimpleRRect::ry3)
|
||||
.field("rx4", &SimpleRRect::rx4)
|
||||
.field("ry4", &SimpleRRect::ry4);
|
||||
|
||||
value_object<SkIRect>("SkIRect")
|
||||
.field("fLeft", &SkIRect::fLeft)
|
||||
.field("fTop", &SkIRect::fTop)
|
||||
|
@ -185,13 +185,11 @@ var CanvasKit = {
|
||||
SkCanvas: {
|
||||
// public API (from C++ bindings)
|
||||
clipPath: function() {},
|
||||
clipRRect: function() {},
|
||||
clipRect: function() {},
|
||||
drawAnimatedImage: function() {},
|
||||
drawArc: function() {},
|
||||
drawCircle: function() {},
|
||||
drawColorInt: function() {},
|
||||
drawDRRect: function() {},
|
||||
drawImage: function() {},
|
||||
drawImageNine: function() {},
|
||||
drawImageRect: function() {},
|
||||
@ -201,7 +199,6 @@ var CanvasKit = {
|
||||
drawParagraph: function() {},
|
||||
drawPath: function() {},
|
||||
drawPicture: function() {},
|
||||
drawRRect: function() {},
|
||||
drawRect: function() {},
|
||||
drawRoundRect: function() {},
|
||||
drawText: function() {},
|
||||
@ -223,24 +220,38 @@ var CanvasKit = {
|
||||
|
||||
prototype: {
|
||||
clear: function() {},
|
||||
clipRRect: function() {},
|
||||
concat44: function() {}, // deprecated
|
||||
concat: function() {},
|
||||
drawAtlas: function() {},
|
||||
drawColor: function() {},
|
||||
drawColorComponents: function() {},
|
||||
drawDRRect: function() {},
|
||||
drawPoints: function() {},
|
||||
drawRRect: function() {},
|
||||
drawShadow: function() {},
|
||||
drawText: function() {},
|
||||
findMarkedCTM: function() {},
|
||||
getLocalToDevice: function() {},
|
||||
getTotalMatrix: function() {},
|
||||
readPixels: function() {},
|
||||
writePixels : function() {},
|
||||
},
|
||||
|
||||
// private API
|
||||
_clear: function() {},
|
||||
_clipRRect: function() {},
|
||||
_concat: function() {},
|
||||
_drawAtlas: function() {},
|
||||
_drawColor: function() {},
|
||||
_drawDRRect: function() {},
|
||||
_drawPoints: function() {},
|
||||
_drawRRect: function() {},
|
||||
_drawShadow: function() {},
|
||||
_drawSimpleText: function() {},
|
||||
_getLocalToCamera: function() {},
|
||||
_getLocalToDevice: function() {},
|
||||
_getLocalToWorld: function() {},
|
||||
_getTotalMatrix: function() {},
|
||||
_findMarkedCTM: function() {},
|
||||
_getLocalToDevice: function() {},
|
||||
_getTotalMatrix: function() {},
|
||||
_readPixels: function() {},
|
||||
_writePixels: function() {},
|
||||
delete: function() {},
|
||||
@ -932,19 +943,6 @@ CanvasKit.SkSurface.prototype.captureFrameAsSkPicture = function() {};
|
||||
CanvasKit.SkImage.prototype.encodeToData = function() {};
|
||||
CanvasKit.SkImage.prototype.makeShader = function() {};
|
||||
|
||||
CanvasKit.SkCanvas.prototype.concat = function() {};
|
||||
CanvasKit.SkCanvas.prototype.concat44 = function() {}; // deprecated
|
||||
CanvasKit.SkCanvas.prototype.drawAtlas = function() {};
|
||||
CanvasKit.SkCanvas.prototype.drawPoints = function() {};
|
||||
CanvasKit.SkCanvas.prototype.drawText = function() {};
|
||||
CanvasKit.SkCanvas.prototype.getLocalToCamera = function() {};
|
||||
CanvasKit.SkCanvas.prototype.getLocalToDevice = function() {};
|
||||
CanvasKit.SkCanvas.prototype.getLocalToWorld = function() {};
|
||||
CanvasKit.SkCanvas.prototype.getTotalMatrix = function() {};
|
||||
/** @return {Uint8Array} */
|
||||
CanvasKit.SkCanvas.prototype.readPixels = function() {};
|
||||
CanvasKit.SkCanvas.prototype.writePixels = function() {};
|
||||
|
||||
CanvasKit.SkFontMgr.prototype.MakeTypefaceFromData = function() {};
|
||||
|
||||
CanvasKit.SkFont.prototype.getWidths = function() {};
|
||||
|
@ -465,6 +465,18 @@ function copyColorFromWasm(colorPtr) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// These will be initialized after loading.
|
||||
var _scratchRRect;
|
||||
var _scratchRRectPtr = nullptr;
|
||||
|
||||
var _scratchRRect2;
|
||||
var _scratchRRect2Ptr = nullptr;
|
||||
|
||||
|
||||
function copyRRectToWasm(twelveFloats, ptr) {
|
||||
return copy1dArray(twelveFloats, "HEAPF32", ptr || _scratchRRectPtr);
|
||||
}
|
||||
|
||||
// Caching the Float32Arrays can save having to reallocate them
|
||||
// over and over again.
|
||||
var Float32ArrayCache = {};
|
||||
|
@ -16,6 +16,13 @@ CanvasKit.onRuntimeInitialized = function() {
|
||||
|
||||
_scratch3x3Matrix = CanvasKit.Malloc(Float32Array, 9); // 9 matrix scalars.
|
||||
_scratch3x3MatrixPtr = _scratch3x3Matrix['byteOffset'];
|
||||
|
||||
_scratchRRect = CanvasKit.Malloc(Float32Array, 12); // 4 scalars for rrect, 8 for radii.
|
||||
_scratchRRectPtr = _scratchRRect['byteOffset'];
|
||||
|
||||
_scratchRRect2 = CanvasKit.Malloc(Float32Array, 12); // 4 scalars for rrect, 8 for radii.
|
||||
_scratchRRect2Ptr = _scratchRRect2['byteOffset'];
|
||||
|
||||
// Create single copies of all three supported color spaces
|
||||
// These are sk_sp<SkColorSpace>
|
||||
CanvasKit.SkColorSpace.SRGB = CanvasKit.SkColorSpace._MakeSRGB();
|
||||
@ -312,7 +319,7 @@ CanvasKit.onRuntimeInitialized = function() {
|
||||
// angle is in radians.
|
||||
CanvasKit.SkM44.perspective = function(near, far, angle) {
|
||||
if (skIsDebug && (far <= near)) {
|
||||
throw "far must be greater than near when constructing SkM44 using perspective.";
|
||||
throw 'far must be greater than near when constructing SkM44 using perspective.';
|
||||
}
|
||||
var dInv = 1 / (far - near);
|
||||
var halfAngle = angle / 2;
|
||||
@ -438,7 +445,7 @@ CanvasKit.onRuntimeInitialized = function() {
|
||||
CanvasKit.SkM44.mustInvert = function(m) {
|
||||
var m2 = CanvasKit.SkM44.invert(m);
|
||||
if (m2 === null) {
|
||||
throw "Matrix not invertible";
|
||||
throw 'Matrix not invertible';
|
||||
}
|
||||
return m2;
|
||||
}
|
||||
@ -568,9 +575,9 @@ CanvasKit.onRuntimeInitialized = function() {
|
||||
|
||||
// The weights array is optional (only used for conics).
|
||||
CanvasKit.SkPath.MakeFromVerbsPointsWeights = function(verbs, pts, weights) {
|
||||
var verbsPtr = copy1dArray(verbs, "HEAPU8");
|
||||
var pointsPtr = copy1dArray(pts, "HEAPF32");
|
||||
var weightsPtr = copy1dArray(weights, "HEAPF32");
|
||||
var verbsPtr = copy1dArray(verbs, 'HEAPU8');
|
||||
var pointsPtr = copy1dArray(pts, 'HEAPF32');
|
||||
var weightsPtr = copy1dArray(weights, 'HEAPF32');
|
||||
var numWeights = (weights && weights.length) || 0;
|
||||
var path = CanvasKit.SkPath._MakeFromVerbsPointsWeights(
|
||||
verbsPtr, verbs.length, pointsPtr, pts.length, weightsPtr, numWeights);
|
||||
@ -605,7 +612,7 @@ CanvasKit.onRuntimeInitialized = function() {
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
var path = args[0];
|
||||
var extend = false;
|
||||
if (typeof args[args.length-1] === "boolean") {
|
||||
if (typeof args[args.length-1] === 'boolean') {
|
||||
extend = args.pop();
|
||||
}
|
||||
if (args.length === 1) {
|
||||
@ -649,7 +656,7 @@ CanvasKit.onRuntimeInitialized = function() {
|
||||
ptr = points.byteOffset;
|
||||
n = points.length/2;
|
||||
} else {
|
||||
ptr = copy2dArray(points, "HEAPF32");
|
||||
ptr = copy2dArray(points, 'HEAPF32');
|
||||
n = points.length;
|
||||
}
|
||||
this._addPoly(ptr, n, close);
|
||||
@ -699,7 +706,7 @@ CanvasKit.onRuntimeInitialized = function() {
|
||||
SkDebug('addRoundRect needs 8 radii provided. Got ' + radii.length);
|
||||
return null;
|
||||
}
|
||||
var rptr = copy1dArray(radii, "HEAPF32");
|
||||
var rptr = copy1dArray(radii, 'HEAPF32');
|
||||
if (args.length === 3 || args.length === 4) {
|
||||
var r = args[0];
|
||||
var ccw = args[args.length - 1];
|
||||
@ -714,9 +721,9 @@ CanvasKit.onRuntimeInitialized = function() {
|
||||
|
||||
// The weights array is optional (only used for conics).
|
||||
CanvasKit.SkPath.prototype.addVerbsPointsWeights = function(verbs, points, weights) {
|
||||
var verbsPtr = copy1dArray(verbs, "HEAPU8");
|
||||
var pointsPtr = copy1dArray(points, "HEAPF32");
|
||||
var weightsPtr = copy1dArray(weights, "HEAPF32");
|
||||
var verbsPtr = copy1dArray(verbs, 'HEAPU8');
|
||||
var pointsPtr = copy1dArray(points, 'HEAPF32');
|
||||
var weightsPtr = copy1dArray(weights, 'HEAPF32');
|
||||
var numWeights = (weights && weights.length) || 0;
|
||||
this._addVerbsPointsWeights(verbsPtr, verbs.length, pointsPtr, points.length,
|
||||
weightsPtr, numWeights);
|
||||
@ -940,9 +947,9 @@ CanvasKit.onRuntimeInitialized = function() {
|
||||
|
||||
CanvasKit.SkImage.prototype.readPixels = function(imageInfo, srcX, srcY) {
|
||||
var rowBytes;
|
||||
// Important to use ["string"] notation here, otherwise the closure compiler will
|
||||
// Important to use ['string'] notation here, otherwise the closure compiler will
|
||||
// minify away the colorType.
|
||||
switch (imageInfo["colorType"]) {
|
||||
switch (imageInfo['colorType']) {
|
||||
case CanvasKit.ColorType.RGBA_8888:
|
||||
rowBytes = imageInfo.width * 4; // 1 byte per channel == 4 bytes per pixel in 8888
|
||||
break;
|
||||
@ -950,21 +957,21 @@ CanvasKit.onRuntimeInitialized = function() {
|
||||
rowBytes = imageInfo.width * 16; // 4 bytes per channel == 16 bytes per pixel in F32
|
||||
break;
|
||||
default:
|
||||
SkDebug("Colortype not yet supported");
|
||||
SkDebug('Colortype not yet supported');
|
||||
return;
|
||||
}
|
||||
var pBytes = rowBytes * imageInfo.height;
|
||||
var pPtr = CanvasKit._malloc(pBytes);
|
||||
|
||||
if (!this._readPixels(imageInfo, pPtr, rowBytes, srcX, srcY)) {
|
||||
SkDebug("Could not read pixels with the given inputs");
|
||||
SkDebug('Could not read pixels with the given inputs');
|
||||
return null;
|
||||
}
|
||||
|
||||
// Put those pixels into a typed array of the right format and then
|
||||
// make a copy with slice() that we can return.
|
||||
var retVal = null;
|
||||
switch (imageInfo["colorType"]) {
|
||||
switch (imageInfo['colorType']) {
|
||||
case CanvasKit.ColorType.RGBA_8888:
|
||||
retVal = new Uint8Array(CanvasKit.HEAPU8.buffer, pPtr, pBytes).slice();
|
||||
break;
|
||||
@ -979,11 +986,16 @@ CanvasKit.onRuntimeInitialized = function() {
|
||||
}
|
||||
|
||||
// Accepts an array of four numbers in the range of 0-1 representing a 4f color
|
||||
CanvasKit.SkCanvas.prototype.clear = function (color4f) {
|
||||
CanvasKit.SkCanvas.prototype.clear = function(color4f) {
|
||||
var cPtr = copyColorToWasm(color4f);
|
||||
this._clear(cPtr);
|
||||
}
|
||||
|
||||
CanvasKit.SkCanvas.prototype.clipRRect = function(rrect, op, antialias) {
|
||||
var rPtr = copyRRectToWasm(rrect);
|
||||
this._clipRRect(rPtr, op, antialias);
|
||||
}
|
||||
|
||||
// concat takes a 3x2, a 3x3, or a 4x4 matrix and upscales it (if needed) to 4x4. This is because
|
||||
// under the hood, SkCanvas uses a 4x4 matrix.
|
||||
CanvasKit.SkCanvas.prototype.concat = function(matr) {
|
||||
@ -1024,7 +1036,7 @@ CanvasKit.onRuntimeInitialized = function() {
|
||||
if (srcRects.build) {
|
||||
srcRectPtr = srcRects.build();
|
||||
} else {
|
||||
srcRectPtr = copy1dArray(srcRects, "HEAPF32");
|
||||
srcRectPtr = copy1dArray(srcRects, 'HEAPF32');
|
||||
}
|
||||
|
||||
var count = 1;
|
||||
@ -1033,7 +1045,7 @@ CanvasKit.onRuntimeInitialized = function() {
|
||||
dstXformPtr = dstXforms.build();
|
||||
count = dstXforms.length;
|
||||
} else {
|
||||
dstXformPtr = copy1dArray(dstXforms, "HEAPF32");
|
||||
dstXformPtr = copy1dArray(dstXforms, 'HEAPF32');
|
||||
count = dstXforms.length / 4;
|
||||
}
|
||||
|
||||
@ -1042,7 +1054,7 @@ CanvasKit.onRuntimeInitialized = function() {
|
||||
if (colors.build) {
|
||||
colorPtr = colors.build();
|
||||
} else {
|
||||
colorPtr = copy1dArray(assureIntColors(colors), "HEAPU32");
|
||||
colorPtr = copy1dArray(assureIntColors(colors), 'HEAPU32');
|
||||
}
|
||||
}
|
||||
|
||||
@ -1077,6 +1089,12 @@ CanvasKit.onRuntimeInitialized = function() {
|
||||
}
|
||||
}
|
||||
|
||||
CanvasKit.SkCanvas.prototype.drawDRRect = function(outer, inner, paint) {
|
||||
var oPtr = copyRRectToWasm(outer, _scratchRRectPtr);
|
||||
var iPtr = copyRRectToWasm(inner, _scratchRRect2Ptr);
|
||||
this._drawDRRect(oPtr, iPtr, paint);
|
||||
}
|
||||
|
||||
// points is either an array of [x, y] where x and y are numbers or
|
||||
// a typed array from Malloc where the even indices will be treated
|
||||
// as x coordinates and the odd indices will be treated as y coordinates.
|
||||
@ -1089,13 +1107,18 @@ CanvasKit.onRuntimeInitialized = function() {
|
||||
ptr = points.byteOffset;
|
||||
n = points.length/2;
|
||||
} else {
|
||||
ptr = copy2dArray(points, "HEAPF32");
|
||||
ptr = copy2dArray(points, 'HEAPF32');
|
||||
n = points.length;
|
||||
}
|
||||
this._drawPoints(mode, ptr, n, paint);
|
||||
freeArraysThatAreNotMallocedByUsers(ptr, points);
|
||||
}
|
||||
|
||||
CanvasKit.SkCanvas.prototype.drawRRect = function(rrect, paint) {
|
||||
var rPtr = copyRRectToWasm(rrect);
|
||||
this._drawRRect(rPtr, paint);
|
||||
}
|
||||
|
||||
CanvasKit.SkCanvas.prototype.drawShadow = function(path, zPlaneParams, lightPos, lightRadius, ambientColor, spotColor, flags) {
|
||||
var ambiPtr = copyColorToWasmNoScratch(ambientColor);
|
||||
var spotPtr = copyColorToWasmNoScratch(spotColor);
|
||||
@ -1182,7 +1205,7 @@ CanvasKit.onRuntimeInitialized = function() {
|
||||
colorSpace = colorSpace || CanvasKit.SkColorSpace.SRGB;
|
||||
var srcRowBytes = bytesPerPixel * srcWidth;
|
||||
|
||||
var pptr = copy1dArray(pixels, "HEAPU8");
|
||||
var pptr = copy1dArray(pixels, 'HEAPU8');
|
||||
var ok = this._writePixels({
|
||||
'width': srcWidth,
|
||||
'height': srcHeight,
|
||||
@ -1206,7 +1229,7 @@ CanvasKit.onRuntimeInitialized = function() {
|
||||
if (!colorMatrix || colorMatrix.length !== 20) {
|
||||
throw 'invalid color matrix';
|
||||
}
|
||||
var fptr = copy1dArray(colorMatrix, "HEAPF32");
|
||||
var fptr = copy1dArray(colorMatrix, 'HEAPF32');
|
||||
// We know skia memcopies the floats, so we can free our memory after the call returns.
|
||||
var m = CanvasKit.SkColorFilter._makeMatrix(fptr);
|
||||
freeArraysThatAreNotMallocedByUsers(fptr, colorMatrix);
|
||||
@ -1295,7 +1318,7 @@ CanvasKit.onRuntimeInitialized = function() {
|
||||
if (!intervals.length || intervals.length % 2 === 1) {
|
||||
throw 'Intervals array must have even length';
|
||||
}
|
||||
var ptr = copy1dArray(intervals, "HEAPF32");
|
||||
var ptr = copy1dArray(intervals, 'HEAPF32');
|
||||
var dpe = CanvasKit.SkPathEffect._MakeDash(ptr, intervals.length, phase);
|
||||
freeArraysThatAreNotMallocedByUsers(ptr, intervals);
|
||||
return dpe;
|
||||
@ -1311,7 +1334,7 @@ CanvasKit.onRuntimeInitialized = function() {
|
||||
CanvasKit.SkShader.MakeLinearGradient = function(start, end, colors, pos, mode, localMatrix, flags, colorSpace) {
|
||||
colorSpace = colorSpace || null
|
||||
var cPtrInfo = copyFlexibleColorArray(colors);
|
||||
var posPtr = copy1dArray(pos, "HEAPF32");
|
||||
var posPtr = copy1dArray(pos, 'HEAPF32');
|
||||
flags = flags || 0;
|
||||
var localMatrixPtr = copy3x3MatrixToWasm(localMatrix);
|
||||
|
||||
@ -1326,7 +1349,7 @@ CanvasKit.onRuntimeInitialized = function() {
|
||||
CanvasKit.SkShader.MakeRadialGradient = function(center, radius, colors, pos, mode, localMatrix, flags, colorSpace) {
|
||||
colorSpace = colorSpace || null
|
||||
var cPtrInfo = copyFlexibleColorArray(colors);
|
||||
var posPtr = copy1dArray(pos, "HEAPF32");
|
||||
var posPtr = copy1dArray(pos, 'HEAPF32');
|
||||
flags = flags || 0;
|
||||
var localMatrixPtr = copy3x3MatrixToWasm(localMatrix);
|
||||
|
||||
@ -1341,7 +1364,7 @@ CanvasKit.onRuntimeInitialized = function() {
|
||||
CanvasKit.SkShader.MakeSweepGradient = function(cx, cy, colors, pos, mode, localMatrix, flags, startAngle, endAngle, colorSpace) {
|
||||
colorSpace = colorSpace || null
|
||||
var cPtrInfo = copyFlexibleColorArray(colors);
|
||||
var posPtr = copy1dArray(pos, "HEAPF32");
|
||||
var posPtr = copy1dArray(pos, 'HEAPF32');
|
||||
flags = flags || 0;
|
||||
startAngle = startAngle || 0;
|
||||
endAngle = endAngle || 360;
|
||||
@ -1361,7 +1384,7 @@ CanvasKit.onRuntimeInitialized = function() {
|
||||
colors, pos, mode, localMatrix, flags, colorSpace) {
|
||||
colorSpace = colorSpace || null
|
||||
var cPtrInfo = copyFlexibleColorArray(colors);
|
||||
var posPtr = copy1dArray(pos, "HEAPF32");
|
||||
var posPtr = copy1dArray(pos, 'HEAPF32');
|
||||
flags = flags || 0;
|
||||
var localMatrixPtr = copy3x3MatrixToWasm(localMatrix);
|
||||
|
||||
@ -1431,20 +1454,16 @@ CanvasKit.XYWHRect = function(x, y, w, h) {
|
||||
};
|
||||
};
|
||||
|
||||
// RRectXY returns an RRect with the given rect and a radiusX and radiusY for
|
||||
// all 4 corners.
|
||||
// RRectXY returns a TypedArray representing an RRect with the given rect and a radiusX and
|
||||
// radiusY for all 4 corners.
|
||||
CanvasKit.RRectXY = function(rect, rx, ry) {
|
||||
return {
|
||||
rect: rect,
|
||||
rx1: rx,
|
||||
ry1: ry,
|
||||
rx2: rx,
|
||||
ry2: ry,
|
||||
rx3: rx,
|
||||
ry3: ry,
|
||||
rx4: rx,
|
||||
ry4: ry,
|
||||
};
|
||||
return Float32Array.of(
|
||||
rect['fLeft'], rect['fTop'], rect['fRight'], rect['fBottom'],
|
||||
rx, ry,
|
||||
rx, ry,
|
||||
rx, ry,
|
||||
rx, ry,
|
||||
);
|
||||
};
|
||||
|
||||
// data is a TypedArray or ArrayBuffer e.g. from fetch().then(resp.arrayBuffer())
|
||||
@ -1519,7 +1538,7 @@ CanvasKit.MakeImage = function(pixels, width, height, alphaType, colorType, colo
|
||||
'colorType': colorType,
|
||||
'colorSpace': colorSpace,
|
||||
};
|
||||
var pptr = copy1dArray(pixels, "HEAPU8");
|
||||
var pptr = copy1dArray(pixels, 'HEAPU8');
|
||||
// No need to _free pptr, Image takes it with SkData::MakeFromMalloc
|
||||
|
||||
return CanvasKit._MakeImage(info, pptr, pixels.length, width * bytesPerPixel);
|
||||
@ -1550,19 +1569,19 @@ CanvasKit.MakeSkVertices = function(mode, positions, textureCoordinates, colors,
|
||||
|
||||
var builder = new CanvasKit._SkVerticesBuilder(mode, positions.length, idxCount, flags);
|
||||
|
||||
copy2dArray(positions, "HEAPF32", builder.positions());
|
||||
copy2dArray(positions, 'HEAPF32', builder.positions());
|
||||
if (builder.texCoords()) {
|
||||
copy2dArray(textureCoordinates, "HEAPF32", builder.texCoords());
|
||||
copy2dArray(textureCoordinates, 'HEAPF32', builder.texCoords());
|
||||
}
|
||||
if (builder.colors()) {
|
||||
if (colors.build) {
|
||||
throw('Color builder not accepted by MakeSkVertices, use array of ints');
|
||||
} else {
|
||||
copy1dArray(assureIntColors(colors), "HEAPU32", builder.colors());
|
||||
copy1dArray(assureIntColors(colors), 'HEAPU32', builder.colors());
|
||||
}
|
||||
}
|
||||
if (builder.indices()) {
|
||||
copy1dArray(indices, "HEAPU16", builder.indices());
|
||||
copy1dArray(indices, 'HEAPU16', builder.indices());
|
||||
}
|
||||
|
||||
// Create the vertices, which owns the memory that the builder had allocated.
|
||||
|
@ -177,22 +177,47 @@ describe('Canvas Behavior', () => {
|
||||
|
||||
canvas.clear(CanvasKit.WHITE);
|
||||
|
||||
canvas.drawRRect({
|
||||
rect: CanvasKit.LTRBRect(10, 10, 210, 210),
|
||||
rx1: 10, // top left corner, going clockwise
|
||||
ry1: 30,
|
||||
rx2: 30,
|
||||
ry2: 10,
|
||||
rx3: 50,
|
||||
ry3: 75,
|
||||
rx4: 120,
|
||||
ry4: 120,
|
||||
}, paint);
|
||||
canvas.drawRRect([10, 10, 210, 210,
|
||||
// top left corner, going clockwise
|
||||
10, 30,
|
||||
30, 10,
|
||||
50, 75,
|
||||
120, 120,
|
||||
], paint);
|
||||
|
||||
path.delete();
|
||||
paint.delete();
|
||||
});
|
||||
|
||||
// As above, except with the array passed in via malloc'd memory.
|
||||
gm('rrect_8corners_malloc_canvas', (canvas) => {
|
||||
const path = starPath(CanvasKit);
|
||||
|
||||
const paint = new CanvasKit.SkPaint();
|
||||
|
||||
paint.setStyle(CanvasKit.PaintStyle.Stroke);
|
||||
paint.setStrokeWidth(3.0);
|
||||
paint.setAntiAlias(true);
|
||||
paint.setColor(CanvasKit.BLACK);
|
||||
|
||||
canvas.clear(CanvasKit.WHITE);
|
||||
|
||||
const rrect = CanvasKit.Malloc(Float32Array, 12);
|
||||
rrect.toTypedArray().set([10, 10, 210, 210,
|
||||
// top left corner, going clockwise
|
||||
10, 30,
|
||||
30, 10,
|
||||
50, 75,
|
||||
120, 120,
|
||||
]);
|
||||
|
||||
canvas.drawRRect(rrect, paint);
|
||||
|
||||
CanvasKit.Free(rrect);
|
||||
path.delete();
|
||||
paint.delete();
|
||||
});
|
||||
|
||||
gm('drawDRRect_canvas', (canvas) => {
|
||||
const path = starPath(CanvasKit);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user