1// Adds JS functions to augment the CanvasKit interface. 2// For example, if there is a wrapper around the C++ call or logic to allow 3// chaining, it should go here. 4 5// CanvasKit.onRuntimeInitialized is called after the WASM library has loaded. 6// Anything that modifies an exposed class (e.g. Path) should be set 7// after onRuntimeInitialized, otherwise, it can happen outside of that scope. 8CanvasKit.onRuntimeInitialized = function() { 9 // All calls to 'this' need to go in externs.js so closure doesn't minify them away. 10 11 _scratchColor = CanvasKit.Malloc(Float32Array, 4); // 4 color scalars. 12 _scratchColorPtr = _scratchColor['byteOffset']; 13 14 _scratch4x4Matrix = CanvasKit.Malloc(Float32Array, 16); // 16 matrix scalars. 15 _scratch4x4MatrixPtr = _scratch4x4Matrix['byteOffset']; 16 17 _scratch3x3Matrix = CanvasKit.Malloc(Float32Array, 9); // 9 matrix scalars. 18 _scratch3x3MatrixPtr = _scratch3x3Matrix['byteOffset']; 19 20 _scratchRRect = CanvasKit.Malloc(Float32Array, 12); // 4 scalars for rrect, 8 for radii. 21 _scratchRRectPtr = _scratchRRect['byteOffset']; 22 23 _scratchRRect2 = CanvasKit.Malloc(Float32Array, 12); // 4 scalars for rrect, 8 for radii. 24 _scratchRRect2Ptr = _scratchRRect2['byteOffset']; 25 26 _scratchFourFloatsA = CanvasKit.Malloc(Float32Array, 4); 27 _scratchFourFloatsAPtr = _scratchFourFloatsA['byteOffset']; 28 29 _scratchFourFloatsB = CanvasKit.Malloc(Float32Array, 4); 30 _scratchFourFloatsBPtr = _scratchFourFloatsB['byteOffset']; 31 32 _scratchThreeFloatsA = CanvasKit.Malloc(Float32Array, 3); // 3 floats to represent SkVector3 33 _scratchThreeFloatsAPtr = _scratchThreeFloatsA['byteOffset']; 34 35 _scratchThreeFloatsB = CanvasKit.Malloc(Float32Array, 3); // 3 floats to represent SkVector3 36 _scratchThreeFloatsBPtr = _scratchThreeFloatsB['byteOffset']; 37 38 _scratchIRect = CanvasKit.Malloc(Int32Array, 4); 39 _scratchIRectPtr = _scratchIRect['byteOffset']; 40 41 // Create single copies of all three supported color spaces 42 // These are sk_sp<ColorSpace> 43 CanvasKit.ColorSpace.SRGB = CanvasKit.ColorSpace._MakeSRGB(); 44 CanvasKit.ColorSpace.DISPLAY_P3 = CanvasKit.ColorSpace._MakeDisplayP3(); 45 CanvasKit.ColorSpace.ADOBE_RGB = CanvasKit.ColorSpace._MakeAdobeRGB(); 46 47 // Use quotes to tell closure compiler not to minify the names 48 CanvasKit['GlyphRunFlags'] = { 49 'IsWhiteSpace': CanvasKit['_GlyphRunFlags_isWhiteSpace'], 50 }; 51 52 CanvasKit.Path.MakeFromCmds = function(cmds) { 53 var cmdPtr = copy1dArray(cmds, 'HEAPF32'); 54 var path = CanvasKit.Path._MakeFromCmds(cmdPtr, cmds.length); 55 freeArraysThatAreNotMallocedByUsers(cmdPtr, cmds); 56 return path; 57 }; 58 59 // The weights array is optional (only used for conics). 60 CanvasKit.Path.MakeFromVerbsPointsWeights = function(verbs, pts, weights) { 61 var verbsPtr = copy1dArray(verbs, 'HEAPU8'); 62 var pointsPtr = copy1dArray(pts, 'HEAPF32'); 63 var weightsPtr = copy1dArray(weights, 'HEAPF32'); 64 var numWeights = (weights && weights.length) || 0; 65 var path = CanvasKit.Path._MakeFromVerbsPointsWeights( 66 verbsPtr, verbs.length, pointsPtr, pts.length, weightsPtr, numWeights); 67 freeArraysThatAreNotMallocedByUsers(verbsPtr, verbs); 68 freeArraysThatAreNotMallocedByUsers(pointsPtr, pts); 69 freeArraysThatAreNotMallocedByUsers(weightsPtr, weights); 70 return path; 71 }; 72 73 CanvasKit.Path.prototype.addArc = function(oval, startAngle, sweepAngle) { 74 // see arc() for the HTMLCanvas version 75 // note input angles are degrees. 76 var oPtr = copyRectToWasm(oval); 77 this._addArc(oPtr, startAngle, sweepAngle); 78 return this; 79 }; 80 81 CanvasKit.Path.prototype.addOval = function(oval, isCCW, startIndex) { 82 if (startIndex === undefined) { 83 startIndex = 1; 84 } 85 var oPtr = copyRectToWasm(oval); 86 this._addOval(oPtr, !!isCCW, startIndex); 87 return this; 88 }; 89 90 // TODO(kjlubick) clean up this API - split it apart if necessary 91 CanvasKit.Path.prototype.addPath = function() { 92 // Takes 1, 2, 7, or 10 required args, where the first arg is always the path. 93 // The last arg is optional and chooses between add or extend mode. 94 // The options for the remaining args are: 95 // - an array of 6 or 9 parameters (perspective is optional) 96 // - the 9 parameters of a full matrix or 97 // the 6 non-perspective params of a matrix. 98 var args = Array.prototype.slice.call(arguments); 99 var path = args[0]; 100 var extend = false; 101 if (typeof args[args.length-1] === 'boolean') { 102 extend = args.pop(); 103 } 104 if (args.length === 1) { 105 // Add path, unchanged. Use identity matrix 106 this._addPath(path, 1, 0, 0, 107 0, 1, 0, 108 0, 0, 1, 109 extend); 110 } else if (args.length === 2) { 111 // User provided the 9 params of a full matrix as an array. 112 var a = args[1]; 113 this._addPath(path, a[0], a[1], a[2], 114 a[3], a[4], a[5], 115 a[6] || 0, a[7] || 0, a[8] || 1, 116 extend); 117 } else if (args.length === 7 || args.length === 10) { 118 // User provided the 9 params of a (full) matrix directly. 119 // (or just the 6 non perspective ones) 120 // These are in the same order as what Skia expects. 121 var a = args; 122 this._addPath(path, a[1], a[2], a[3], 123 a[4], a[5], a[6], 124 a[7] || 0, a[8] || 0, a[9] || 1, 125 extend); 126 } else { 127 Debug('addPath expected to take 1, 2, 7, or 10 required args. Got ' + args.length); 128 return null; 129 } 130 return this; 131 }; 132 133 // points is a 1d array of length 2n representing n points where the even indices 134 // will be treated as x coordinates and the odd indices will be treated as y coordinates. 135 // Like other APIs, this accepts a malloced type array or malloc obj. 136 CanvasKit.Path.prototype.addPoly = function(points, close) { 137 var ptr = copy1dArray(points, 'HEAPF32'); 138 this._addPoly(ptr, points.length / 2, close); 139 freeArraysThatAreNotMallocedByUsers(ptr, points); 140 return this; 141 }; 142 143 CanvasKit.Path.prototype.addRect = function(rect, isCCW) { 144 var rPtr = copyRectToWasm(rect); 145 this._addRect(rPtr, !!isCCW); 146 return this; 147 }; 148 149 CanvasKit.Path.prototype.addRRect = function(rrect, isCCW) { 150 var rPtr = copyRRectToWasm(rrect); 151 this._addRRect(rPtr, !!isCCW); 152 return this; 153 }; 154 155 // The weights array is optional (only used for conics). 156 CanvasKit.Path.prototype.addVerbsPointsWeights = function(verbs, points, weights) { 157 var verbsPtr = copy1dArray(verbs, 'HEAPU8'); 158 var pointsPtr = copy1dArray(points, 'HEAPF32'); 159 var weightsPtr = copy1dArray(weights, 'HEAPF32'); 160 var numWeights = (weights && weights.length) || 0; 161 this._addVerbsPointsWeights(verbsPtr, verbs.length, pointsPtr, points.length, 162 weightsPtr, numWeights); 163 freeArraysThatAreNotMallocedByUsers(verbsPtr, verbs); 164 freeArraysThatAreNotMallocedByUsers(pointsPtr, points); 165 freeArraysThatAreNotMallocedByUsers(weightsPtr, weights); 166 }; 167 168 CanvasKit.Path.prototype.arc = function(x, y, radius, startAngle, endAngle, ccw) { 169 // emulates the HTMLCanvas behavior. See addArc() for the Path version. 170 // Note input angles are radians. 171 var bounds = CanvasKit.LTRBRect(x-radius, y-radius, x+radius, y+radius); 172 var sweep = radiansToDegrees(endAngle - startAngle) - (360 * !!ccw); 173 var temp = new CanvasKit.Path(); 174 temp.addArc(bounds, radiansToDegrees(startAngle), sweep); 175 this.addPath(temp, true); 176 temp.delete(); 177 return this; 178 }; 179 180 // Appends arc to Path. Arc added is part of ellipse 181 // bounded by oval, from startAngle through sweepAngle. Both startAngle and 182 // sweepAngle are measured in degrees, where zero degrees is aligned with the 183 // positive x-axis, and positive sweeps extends arc clockwise. 184 CanvasKit.Path.prototype.arcToOval = function(oval, startAngle, sweepAngle, forceMoveTo) { 185 var oPtr = copyRectToWasm(oval); 186 this._arcToOval(oPtr, startAngle, sweepAngle, forceMoveTo); 187 return this; 188 }; 189 190 // Appends arc to Path. Arc is implemented by one or more conics weighted to 191 // describe part of oval with radii (rx, ry) rotated by xAxisRotate degrees. Arc 192 // curves from last point to (x, y), choosing one of four possible routes: 193 // clockwise or counterclockwise, and smaller or larger. 194 195 // Arc sweep is always less than 360 degrees. arcTo() appends line to (x, y) if 196 // either radii are zero, or if last point equals (x, y). arcTo() scales radii 197 // (rx, ry) to fit last point and (x, y) if both are greater than zero but 198 // too small. 199 200 // arcToRotated() appends up to four conic curves. 201 // arcToRotated() implements the functionality of SVG arc, although SVG sweep-flag value 202 // is opposite the integer value of sweep; SVG sweep-flag uses 1 for clockwise, 203 // while kCW_Direction cast to int is zero. 204 CanvasKit.Path.prototype.arcToRotated = function(rx, ry, xAxisRotate, useSmallArc, isCCW, x, y) { 205 this._arcToRotated(rx, ry, xAxisRotate, !!useSmallArc, !!isCCW, x, y); 206 return this; 207 }; 208 209 // Appends arc to Path, after appending line if needed. Arc is implemented by conic 210 // weighted to describe part of circle. Arc is contained by tangent from 211 // last Path point to (x1, y1), and tangent from (x1, y1) to (x2, y2). Arc 212 // is part of circle sized to radius, positioned so it touches both tangent lines. 213 214 // If last Path Point does not start Arc, arcTo appends connecting Line to Path. 215 // The length of Vector from (x1, y1) to (x2, y2) does not affect Arc. 216 217 // Arc sweep is always less than 180 degrees. If radius is zero, or if 218 // tangents are nearly parallel, arcTo appends Line from last Path Point to (x1, y1). 219 220 // arcToTangent appends at most one Line and one conic. 221 // arcToTangent implements the functionality of PostScript arct and HTML Canvas arcTo. 222 CanvasKit.Path.prototype.arcToTangent = function(x1, y1, x2, y2, radius) { 223 this._arcToTangent(x1, y1, x2, y2, radius); 224 return this; 225 }; 226 227 CanvasKit.Path.prototype.close = function() { 228 this._close(); 229 return this; 230 }; 231 232 CanvasKit.Path.prototype.conicTo = function(x1, y1, x2, y2, w) { 233 this._conicTo(x1, y1, x2, y2, w); 234 return this; 235 }; 236 237 // Clients can pass in a Float32Array with length 4 to this and the results 238 // will be copied into that array. Otherwise, a new TypedArray will be allocated 239 // and returned. 240 CanvasKit.Path.prototype.computeTightBounds = function(optionalOutputArray) { 241 this._computeTightBounds(_scratchFourFloatsAPtr); 242 var ta = _scratchFourFloatsA['toTypedArray'](); 243 if (optionalOutputArray) { 244 optionalOutputArray.set(ta); 245 return optionalOutputArray; 246 } 247 return ta.slice(); 248 }; 249 250 CanvasKit.Path.prototype.cubicTo = function(cp1x, cp1y, cp2x, cp2y, x, y) { 251 this._cubicTo(cp1x, cp1y, cp2x, cp2y, x, y); 252 return this; 253 }; 254 255 CanvasKit.Path.prototype.dash = function(on, off, phase) { 256 if (this._dash(on, off, phase)) { 257 return this; 258 } 259 return null; 260 }; 261 262 // Clients can pass in a Float32Array with length 4 to this and the results 263 // will be copied into that array. Otherwise, a new TypedArray will be allocated 264 // and returned. 265 CanvasKit.Path.prototype.getBounds = function(optionalOutputArray) { 266 this._getBounds(_scratchFourFloatsAPtr); 267 var ta = _scratchFourFloatsA['toTypedArray'](); 268 if (optionalOutputArray) { 269 optionalOutputArray.set(ta); 270 return optionalOutputArray; 271 } 272 return ta.slice(); 273 }; 274 275 CanvasKit.Path.prototype.lineTo = function(x, y) { 276 this._lineTo(x, y); 277 return this; 278 }; 279 280 CanvasKit.Path.prototype.moveTo = function(x, y) { 281 this._moveTo(x, y); 282 return this; 283 }; 284 285 CanvasKit.Path.prototype.offset = function(dx, dy) { 286 this._transform(1, 0, dx, 287 0, 1, dy, 288 0, 0, 1); 289 return this; 290 }; 291 292 CanvasKit.Path.prototype.quadTo = function(cpx, cpy, x, y) { 293 this._quadTo(cpx, cpy, x, y); 294 return this; 295 }; 296 297 CanvasKit.Path.prototype.rArcTo = function(rx, ry, xAxisRotate, useSmallArc, isCCW, dx, dy) { 298 this._rArcTo(rx, ry, xAxisRotate, useSmallArc, isCCW, dx, dy); 299 return this; 300 }; 301 302 CanvasKit.Path.prototype.rConicTo = function(dx1, dy1, dx2, dy2, w) { 303 this._rConicTo(dx1, dy1, dx2, dy2, w); 304 return this; 305 }; 306 307 // These params are all relative 308 CanvasKit.Path.prototype.rCubicTo = function(cp1x, cp1y, cp2x, cp2y, x, y) { 309 this._rCubicTo(cp1x, cp1y, cp2x, cp2y, x, y); 310 return this; 311 }; 312 313 CanvasKit.Path.prototype.rLineTo = function(dx, dy) { 314 this._rLineTo(dx, dy); 315 return this; 316 }; 317 318 CanvasKit.Path.prototype.rMoveTo = function(dx, dy) { 319 this._rMoveTo(dx, dy); 320 return this; 321 }; 322 323 // These params are all relative 324 CanvasKit.Path.prototype.rQuadTo = function(cpx, cpy, x, y) { 325 this._rQuadTo(cpx, cpy, x, y); 326 return this; 327 }; 328 329 CanvasKit.Path.prototype.stroke = function(opts) { 330 // Fill out any missing values with the default values. 331 opts = opts || {}; 332 opts['width'] = opts['width'] || 1; 333 opts['miter_limit'] = opts['miter_limit'] || 4; 334 opts['cap'] = opts['cap'] || CanvasKit.StrokeCap.Butt; 335 opts['join'] = opts['join'] || CanvasKit.StrokeJoin.Miter; 336 opts['precision'] = opts['precision'] || 1; 337 if (this._stroke(opts)) { 338 return this; 339 } 340 return null; 341 }; 342 343 // TODO(kjlubick) Change this to take a 3x3 or 4x4 matrix (optionally malloc'd) 344 CanvasKit.Path.prototype.transform = function() { 345 // Takes 1 or 9 args 346 if (arguments.length === 1) { 347 // argument 1 should be a 6 or 9 element array. 348 var a = arguments[0]; 349 this._transform(a[0], a[1], a[2], 350 a[3], a[4], a[5], 351 a[6] || 0, a[7] || 0, a[8] || 1); 352 } else if (arguments.length === 6 || arguments.length === 9) { 353 // these arguments are the 6 or 9 members of the matrix 354 var a = arguments; 355 this._transform(a[0], a[1], a[2], 356 a[3], a[4], a[5], 357 a[6] || 0, a[7] || 0, a[8] || 1); 358 } else { 359 throw 'transform expected to take 1 or 9 arguments. Got ' + arguments.length; 360 } 361 return this; 362 }; 363 // isComplement is optional, defaults to false 364 CanvasKit.Path.prototype.trim = function(startT, stopT, isComplement) { 365 if (this._trim(startT, stopT, !!isComplement)) { 366 return this; 367 } 368 return null; 369 }; 370 371 // makeShaderCubic returns a shader for a given image, allowing it to be used on 372 // a paint as well as other purposes. This shader will be higher quality than 373 // other shader functions. See CubicResampler in SkSamplingOptions.h for more information 374 // on the cubicResampler params. 375 CanvasKit.Image.prototype.makeShaderCubic = function(xTileMode, yTileMode, 376 cubicResamplerB, cubicResamplerC, 377 localMatrix) { 378 var localMatrixPtr = copy3x3MatrixToWasm(localMatrix); 379 return this._makeShaderCubic(xTileMode, yTileMode, cubicResamplerB, 380 cubicResamplerC, localMatrixPtr); 381 }; 382 383 // makeShaderCubic returns a shader for a given image, allowing it to be used on 384 // a paint as well as other purposes. This shader will draw more quickly than 385 // other shader functions, but at a lower quality. 386 CanvasKit.Image.prototype.makeShaderOptions = function(xTileMode, yTileMode, 387 filterMode, mipmapMode, 388 localMatrix) { 389 var localMatrixPtr = copy3x3MatrixToWasm(localMatrix); 390 return this._makeShaderOptions(xTileMode, yTileMode, filterMode, mipmapMode, localMatrixPtr); 391 }; 392 393 function readPixels(source, srcX, srcY, imageInfo, destMallocObj, bytesPerRow) { 394 if (!bytesPerRow) { 395 bytesPerRow = 4 * imageInfo['width']; 396 if (imageInfo['colorType'] === CanvasKit.ColorType.RGBA_F16) { 397 bytesPerRow *= 2; 398 } 399 else if (imageInfo['colorType'] === CanvasKit.ColorType.RGBA_F32) { 400 bytesPerRow *= 4; 401 } 402 } 403 var pBytes = bytesPerRow * imageInfo.height; 404 var pPtr; 405 if (destMallocObj) { 406 pPtr = destMallocObj['byteOffset']; 407 } else { 408 pPtr = CanvasKit._malloc(pBytes); 409 } 410 411 if (!source._readPixels(imageInfo, pPtr, bytesPerRow, srcX, srcY)) { 412 Debug('Could not read pixels with the given inputs'); 413 if (!destMallocObj) { 414 CanvasKit._free(pPtr); 415 } 416 return null; 417 } 418 419 // If the user provided us a buffer to copy into, we don't need to allocate a new TypedArray. 420 if (destMallocObj) { 421 return destMallocObj['toTypedArray'](); // Return the typed array wrapper w/o allocating. 422 } 423 424 // Put those pixels into a typed array of the right format and then 425 // make a copy with slice() that we can return. 426 var retVal = null; 427 switch (imageInfo['colorType']) { 428 case CanvasKit.ColorType.RGBA_8888: 429 case CanvasKit.ColorType.RGBA_F16: // there is no half-float JS type, so we return raw bytes. 430 retVal = new Uint8Array(CanvasKit.HEAPU8.buffer, pPtr, pBytes).slice(); 431 break; 432 case CanvasKit.ColorType.RGBA_F32: 433 retVal = new Float32Array(CanvasKit.HEAPU8.buffer, pPtr, pBytes).slice(); 434 break; 435 default: 436 Debug('ColorType not yet supported'); 437 return null; 438 } 439 440 // Free the allocated pixels in the WASM memory 441 CanvasKit._free(pPtr); 442 return retVal; 443 } 444 445 CanvasKit.Image.prototype.readPixels = function(srcX, srcY, imageInfo, destMallocObj, 446 bytesPerRow) { 447 return readPixels(this, srcX, srcY, imageInfo, destMallocObj, bytesPerRow); 448 }; 449 450 // Accepts an array of four numbers in the range of 0-1 representing a 4f color 451 CanvasKit.Canvas.prototype.clear = function(color4f) { 452 CanvasKit.setCurrentContext(this._context); 453 var cPtr = copyColorToWasm(color4f); 454 this._clear(cPtr); 455 }; 456 457 CanvasKit.Canvas.prototype.clipRRect = function(rrect, op, antialias) { 458 CanvasKit.setCurrentContext(this._context); 459 var rPtr = copyRRectToWasm(rrect); 460 this._clipRRect(rPtr, op, antialias); 461 }; 462 463 CanvasKit.Canvas.prototype.clipRect = function(rect, op, antialias) { 464 CanvasKit.setCurrentContext(this._context); 465 var rPtr = copyRectToWasm(rect); 466 this._clipRect(rPtr, op, antialias); 467 }; 468 469 // concat takes a 3x2, a 3x3, or a 4x4 matrix and upscales it (if needed) to 4x4. This is because 470 // under the hood, SkCanvas uses a 4x4 matrix. 471 CanvasKit.Canvas.prototype.concat = function(matr) { 472 CanvasKit.setCurrentContext(this._context); 473 var matrPtr = copy4x4MatrixToWasm(matr); 474 this._concat(matrPtr); 475 }; 476 477 CanvasKit.Canvas.prototype.drawArc = function(oval, startAngle, sweepAngle, useCenter, paint) { 478 CanvasKit.setCurrentContext(this._context); 479 var oPtr = copyRectToWasm(oval); 480 this._drawArc(oPtr, startAngle, sweepAngle, useCenter, paint); 481 }; 482 483 // atlas is an Image, e.g. from CanvasKit.MakeImageFromEncoded 484 // srcRects, dstXformsshould be arrays of floats of length 4*number of destinations. 485 // The colors param is optional and is used to tint the drawn images using the optional blend 486 // mode. Colors can be a Uint32Array of int colors or a flat Float32Array of float colors. 487 CanvasKit.Canvas.prototype.drawAtlas = function(atlas, srcRects, dstXforms, paint, 488 /* optional */ blendMode, /* optional */ colors, 489 /* optional */ sampling) { 490 if (!atlas || !paint || !srcRects || !dstXforms) { 491 Debug('Doing nothing since missing a required input'); 492 return; 493 } 494 495 // builder arguments report the length as the number of rects, but when passed as arrays 496 // their.length attribute is 4x higher because it's the number of total components of all rects. 497 // colors is always going to report the same length, at least until floats colors are supported 498 // by this function. 499 if (srcRects.length !== dstXforms.length) { 500 Debug('Doing nothing since input arrays length mismatches'); 501 return; 502 } 503 CanvasKit.setCurrentContext(this._context); 504 if (!blendMode) { 505 blendMode = CanvasKit.BlendMode.SrcOver; 506 } 507 508 var srcRectPtr = copy1dArray(srcRects, 'HEAPF32'); 509 510 var dstXformPtr = copy1dArray(dstXforms, 'HEAPF32'); 511 var count = dstXforms.length / 4; 512 513 var colorPtr = copy1dArray(assureIntColors(colors), 'HEAPU32'); 514 515 // We require one of these: 516 // 1. sampling is null (we default to linear/none) 517 // 2. sampling.B and sampling.C --> CubicResampler 518 // 3. sampling.filter [and sampling.mipmap] --> FilterOptions 519 // 520 // Thus if all fields are available, we will choose cubic (since we search for B,C first) 521 522 if (sampling && ('B' in sampling) && ('C' in sampling)) { 523 this._drawAtlasCubic(atlas, dstXformPtr, srcRectPtr, colorPtr, count, blendMode, 524 sampling['B'], sampling['C'], paint); 525 } else { 526 let filter = CanvasKit.FilterMode.Linear; 527 let mipmap = CanvasKit.MipmapMode.None; 528 if (sampling) { 529 filter = sampling['filter']; // 'filter' is a required field 530 if ('mipmap' in sampling) { // 'mipmap' is optional 531 mipmap = sampling['mipmap']; 532 } 533 } 534 this._drawAtlasOptions(atlas, dstXformPtr, srcRectPtr, colorPtr, count, blendMode, 535 filter, mipmap, paint); 536 } 537 538 freeArraysThatAreNotMallocedByUsers(srcRectPtr, srcRects); 539 freeArraysThatAreNotMallocedByUsers(dstXformPtr, dstXforms); 540 freeArraysThatAreNotMallocedByUsers(colorPtr, colors); 541 }; 542 543 CanvasKit.Canvas.prototype.drawCircle = function(cx, cy, r, paint) { 544 CanvasKit.setCurrentContext(this._context); 545 this._drawCircle(cx, cy, r, paint); 546 } 547 548 CanvasKit.Canvas.prototype.drawColor = function(color4f, mode) { 549 CanvasKit.setCurrentContext(this._context); 550 var cPtr = copyColorToWasm(color4f); 551 if (mode !== undefined) { 552 this._drawColor(cPtr, mode); 553 } else { 554 this._drawColor(cPtr); 555 } 556 }; 557 558 CanvasKit.Canvas.prototype.drawColorInt = function(color, mode) { 559 CanvasKit.setCurrentContext(this._context); 560 this._drawColorInt(color, mode || CanvasKit.BlendMode.SrcOver); 561 } 562 563 CanvasKit.Canvas.prototype.drawColorComponents = function(r, g, b, a, mode) { 564 CanvasKit.setCurrentContext(this._context); 565 var cPtr = copyColorComponentsToWasm(r, g, b, a); 566 if (mode !== undefined) { 567 this._drawColor(cPtr, mode); 568 } else { 569 this._drawColor(cPtr); 570 } 571 }; 572 573 CanvasKit.Canvas.prototype.drawDRRect = function(outer, inner, paint) { 574 CanvasKit.setCurrentContext(this._context); 575 var oPtr = copyRRectToWasm(outer, _scratchRRectPtr); 576 var iPtr = copyRRectToWasm(inner, _scratchRRect2Ptr); 577 this._drawDRRect(oPtr, iPtr, paint); 578 }; 579 580 CanvasKit.Canvas.prototype.drawGlyphs = function(glyphs, positions, x, y, font, paint) { 581 if (!(glyphs.length*2 <= positions.length)) { 582 throw 'Not enough positions for the array of gyphs'; 583 } 584 CanvasKit.setCurrentContext(this._context); 585 const glyphs_ptr = copy1dArray(glyphs, 'HEAPU16'); 586 const positions_ptr = copy1dArray(positions, 'HEAPF32'); 587 588 this._drawGlyphs(glyphs.length, glyphs_ptr, positions_ptr, x, y, font, paint); 589 590 freeArraysThatAreNotMallocedByUsers(positions_ptr, positions); 591 freeArraysThatAreNotMallocedByUsers(glyphs_ptr, glyphs); 592 }; 593 594 CanvasKit.Canvas.prototype.drawImage = function(img, x, y, paint) { 595 CanvasKit.setCurrentContext(this._context); 596 this._drawImage(img, x, y, paint || null); 597 }; 598 599 CanvasKit.Canvas.prototype.drawImageCubic = function(img, x, y, b, c, paint) { 600 CanvasKit.setCurrentContext(this._context); 601 this._drawImageCubic(img, x, y, b, c, paint || null); 602 }; 603 604 CanvasKit.Canvas.prototype.drawImageOptions = function(img, x, y, filter, mipmap, paint) { 605 CanvasKit.setCurrentContext(this._context); 606 this._drawImageOptions(img, x, y, filter, mipmap, paint || null); 607 }; 608 609 CanvasKit.Canvas.prototype.drawImageNine = function(img, center, dest, filter, paint) { 610 CanvasKit.setCurrentContext(this._context); 611 var cPtr = copyIRectToWasm(center); 612 var dPtr = copyRectToWasm(dest); 613 this._drawImageNine(img, cPtr, dPtr, filter, paint || null); 614 }; 615 616 CanvasKit.Canvas.prototype.drawImageRect = function(img, src, dest, paint, fastSample) { 617 CanvasKit.setCurrentContext(this._context); 618 copyRectToWasm(src, _scratchFourFloatsAPtr); 619 copyRectToWasm(dest, _scratchFourFloatsBPtr); 620 this._drawImageRect(img, _scratchFourFloatsAPtr, _scratchFourFloatsBPtr, paint, !!fastSample); 621 }; 622 623 CanvasKit.Canvas.prototype.drawImageRectCubic = function(img, src, dest, B, C, paint) { 624 CanvasKit.setCurrentContext(this._context); 625 copyRectToWasm(src, _scratchFourFloatsAPtr); 626 copyRectToWasm(dest, _scratchFourFloatsBPtr); 627 this._drawImageRectCubic(img, _scratchFourFloatsAPtr, _scratchFourFloatsBPtr, B, C, 628 paint || null); 629 }; 630 631 CanvasKit.Canvas.prototype.drawImageRectOptions = function(img, src, dest, filter, mipmap, paint) { 632 CanvasKit.setCurrentContext(this._context); 633 copyRectToWasm(src, _scratchFourFloatsAPtr); 634 copyRectToWasm(dest, _scratchFourFloatsBPtr); 635 this._drawImageRectOptions(img, _scratchFourFloatsAPtr, _scratchFourFloatsBPtr, filter, mipmap, 636 paint || null); 637 }; 638 639 CanvasKit.Canvas.prototype.drawLine = function(x1, y1, x2, y2, paint) { 640 CanvasKit.setCurrentContext(this._context); 641 this._drawLine(x1, y1, x2, y2, paint); 642 } 643 644 CanvasKit.Canvas.prototype.drawOval = function(oval, paint) { 645 CanvasKit.setCurrentContext(this._context); 646 var oPtr = copyRectToWasm(oval); 647 this._drawOval(oPtr, paint); 648 }; 649 650 CanvasKit.Canvas.prototype.drawPaint = function(paint) { 651 CanvasKit.setCurrentContext(this._context); 652 this._drawPaint(paint); 653 } 654 655 CanvasKit.Canvas.prototype.drawParagraph = function(p, x, y) { 656 CanvasKit.setCurrentContext(this._context); 657 this._drawParagraph(p, x, y); 658 } 659 660 CanvasKit.Canvas.prototype.drawPatch = function(cubics, colors, texs, mode, paint) { 661 if (cubics.length < 24) { 662 throw 'Need 12 cubic points'; 663 } 664 if (colors && colors.length < 4) { 665 throw 'Need 4 colors'; 666 } 667 if (texs && texs.length < 8) { 668 throw 'Need 4 shader coordinates'; 669 } 670 CanvasKit.setCurrentContext(this._context); 671 672 const cubics_ptr = copy1dArray(cubics, 'HEAPF32'); 673 const colors_ptr = colors ? copy1dArray(assureIntColors(colors), 'HEAPU32') : nullptr; 674 const texs_ptr = texs ? copy1dArray(texs, 'HEAPF32') : nullptr; 675 if (!mode) { 676 mode = CanvasKit.BlendMode.Modulate; 677 } 678 679 this._drawPatch(cubics_ptr, colors_ptr, texs_ptr, mode, paint); 680 681 freeArraysThatAreNotMallocedByUsers(texs_ptr, texs); 682 freeArraysThatAreNotMallocedByUsers(colors_ptr, colors); 683 freeArraysThatAreNotMallocedByUsers(cubics_ptr, cubics); 684 }; 685 686 CanvasKit.Canvas.prototype.drawPath = function(path, paint) { 687 CanvasKit.setCurrentContext(this._context); 688 this._drawPath(path, paint); 689 } 690 691 CanvasKit.Canvas.prototype.drawPicture = function(pic) { 692 CanvasKit.setCurrentContext(this._context); 693 this._drawPicture(pic); 694 } 695 696 // points is a 1d array of length 2n representing n points where the even indices 697 // will be treated as x coordinates and the odd indices will be treated as y coordinates. 698 // Like other APIs, this accepts a malloced type array or malloc obj. 699 CanvasKit.Canvas.prototype.drawPoints = function(mode, points, paint) { 700 CanvasKit.setCurrentContext(this._context); 701 var ptr = copy1dArray(points, 'HEAPF32'); 702 this._drawPoints(mode, ptr, points.length / 2, paint); 703 freeArraysThatAreNotMallocedByUsers(ptr, points); 704 }; 705 706 CanvasKit.Canvas.prototype.drawRRect = function(rrect, paint) { 707 CanvasKit.setCurrentContext(this._context); 708 var rPtr = copyRRectToWasm(rrect); 709 this._drawRRect(rPtr, paint); 710 }; 711 712 CanvasKit.Canvas.prototype.drawRect = function(rect, paint) { 713 CanvasKit.setCurrentContext(this._context); 714 var rPtr = copyRectToWasm(rect); 715 this._drawRect(rPtr, paint); 716 }; 717 718 CanvasKit.Canvas.prototype.drawRect4f = function(l, t, r, b, paint) { 719 CanvasKit.setCurrentContext(this._context); 720 this._drawRect4f(l, t, r, b, paint); 721 } 722 723 CanvasKit.Canvas.prototype.drawShadow = function(path, zPlaneParams, lightPos, lightRadius, 724 ambientColor, spotColor, flags) { 725 CanvasKit.setCurrentContext(this._context); 726 var ambiPtr = copyColorToWasmNoScratch(ambientColor); 727 var spotPtr = copyColorToWasmNoScratch(spotColor); 728 // We use the return value from copy1dArray in case the passed in arrays are malloc'd. 729 var zPlanePtr = copy1dArray(zPlaneParams, 'HEAPF32', _scratchThreeFloatsAPtr); 730 var lightPosPtr = copy1dArray(lightPos, 'HEAPF32', _scratchThreeFloatsBPtr); 731 this._drawShadow(path, zPlanePtr, lightPosPtr, lightRadius, ambiPtr, spotPtr, flags); 732 freeArraysThatAreNotMallocedByUsers(ambiPtr, ambientColor); 733 freeArraysThatAreNotMallocedByUsers(spotPtr, spotColor); 734 }; 735 736 CanvasKit.getShadowLocalBounds = function(ctm, path, zPlaneParams, lightPos, lightRadius, 737 flags, optOutputRect) { 738 var ctmPtr = copy3x3MatrixToWasm(ctm); 739 // We use the return value from copy1dArray in case the passed in arrays are malloc'd. 740 var zPlanePtr = copy1dArray(zPlaneParams, 'HEAPF32', _scratchThreeFloatsAPtr); 741 var lightPosPtr = copy1dArray(lightPos, 'HEAPF32', _scratchThreeFloatsBPtr); 742 var ok = this._getShadowLocalBounds(ctmPtr, path, zPlanePtr, lightPosPtr, lightRadius, 743 flags, _scratchFourFloatsAPtr); 744 if (!ok) { 745 return null; 746 } 747 var ta = _scratchFourFloatsA['toTypedArray'](); 748 if (optOutputRect) { 749 optOutputRect.set(ta); 750 return optOutputRect; 751 } 752 return ta.slice(); 753 }; 754 755 CanvasKit.Canvas.prototype.drawTextBlob = function(blob, x, y, paint) { 756 CanvasKit.setCurrentContext(this._context); 757 this._drawTextBlob(blob, x, y, paint); 758 } 759 760 CanvasKit.Canvas.prototype.drawVertices = function(verts, mode, paint) { 761 CanvasKit.setCurrentContext(this._context); 762 this._drawVertices(verts, mode, paint); 763 } 764 765 // getLocalToDevice returns a 4x4 matrix. 766 CanvasKit.Canvas.prototype.getLocalToDevice = function() { 767 // _getLocalToDevice will copy the values into the pointer. 768 this._getLocalToDevice(_scratch4x4MatrixPtr); 769 return copy4x4MatrixFromWasm(_scratch4x4MatrixPtr); 770 }; 771 772 // findMarkedCTM returns a 4x4 matrix, or null if a matrix was not found at 773 // the provided marker. 774 CanvasKit.Canvas.prototype.findMarkedCTM = function(marker) { 775 // _getLocalToDevice will copy the values into the pointer. 776 var found = this._findMarkedCTM(marker, _scratch4x4MatrixPtr); 777 if (!found) { 778 return null; 779 } 780 return copy4x4MatrixFromWasm(_scratch4x4MatrixPtr); 781 }; 782 783 // getTotalMatrix returns the current matrix as a 3x3 matrix. 784 CanvasKit.Canvas.prototype.getTotalMatrix = function() { 785 // _getTotalMatrix will copy the values into the pointer. 786 this._getTotalMatrix(_scratch3x3MatrixPtr); 787 // read them out into an array. TODO(kjlubick): If we change Matrix to be 788 // typedArrays, then we should return a typed array here too. 789 var rv = new Array(9); 790 for (var i = 0; i < 9; i++) { 791 rv[i] = CanvasKit.HEAPF32[_scratch3x3MatrixPtr/4 + i]; // divide by 4 to "cast" to float. 792 } 793 return rv; 794 }; 795 796 CanvasKit.Canvas.prototype.makeSurface = function(imageInfo) { 797 var s = this._makeSurface(imageInfo); 798 s._context = this._context; 799 return s; 800 }; 801 802 CanvasKit.Canvas.prototype.readPixels = function(srcX, srcY, imageInfo, destMallocObj, 803 bytesPerRow) { 804 CanvasKit.setCurrentContext(this._context); 805 return readPixels(this, srcX, srcY, imageInfo, destMallocObj, bytesPerRow); 806 }; 807 808 CanvasKit.Canvas.prototype.saveLayer = function(paint, boundsRect, backdrop, flags) { 809 // bPtr will be 0 (nullptr) if boundsRect is undefined/null. 810 var bPtr = copyRectToWasm(boundsRect); 811 // These or clauses help emscripten, which does not deal with undefined well. 812 return this._saveLayer(paint || null, bPtr, backdrop || null, flags || 0); 813 }; 814 815 // pixels should be a Uint8Array or a plain JS array. 816 CanvasKit.Canvas.prototype.writePixels = function(pixels, srcWidth, srcHeight, 817 destX, destY, alphaType, colorType, colorSpace) { 818 if (pixels.byteLength % (srcWidth * srcHeight)) { 819 throw 'pixels length must be a multiple of the srcWidth * srcHeight'; 820 } 821 CanvasKit.setCurrentContext(this._context); 822 var bytesPerPixel = pixels.byteLength / (srcWidth * srcHeight); 823 // supply defaults (which are compatible with HTMLCanvas's putImageData) 824 alphaType = alphaType || CanvasKit.AlphaType.Unpremul; 825 colorType = colorType || CanvasKit.ColorType.RGBA_8888; 826 colorSpace = colorSpace || CanvasKit.ColorSpace.SRGB; 827 var srcRowBytes = bytesPerPixel * srcWidth; 828 829 var pptr = copy1dArray(pixels, 'HEAPU8'); 830 var ok = this._writePixels({ 831 'width': srcWidth, 832 'height': srcHeight, 833 'colorType': colorType, 834 'alphaType': alphaType, 835 'colorSpace': colorSpace, 836 }, pptr, srcRowBytes, destX, destY); 837 838 freeArraysThatAreNotMallocedByUsers(pptr, pixels); 839 return ok; 840 }; 841 842 CanvasKit.ColorFilter.MakeBlend = function(color4f, mode) { 843 var cPtr = copyColorToWasm(color4f); 844 return CanvasKit.ColorFilter._MakeBlend(cPtr, mode); 845 }; 846 847 // colorMatrix is an ColorMatrix (e.g. Float32Array of length 20) 848 CanvasKit.ColorFilter.MakeMatrix = function(colorMatrix) { 849 if (!colorMatrix || colorMatrix.length !== 20) { 850 throw 'invalid color matrix'; 851 } 852 var fptr = copy1dArray(colorMatrix, 'HEAPF32'); 853 // We know skia memcopies the floats, so we can free our memory after the call returns. 854 var m = CanvasKit.ColorFilter._makeMatrix(fptr); 855 freeArraysThatAreNotMallocedByUsers(fptr, colorMatrix); 856 return m; 857 }; 858 859 CanvasKit.ContourMeasure.prototype.getPosTan = function(distance, optionalOutput) { 860 this._getPosTan(distance, _scratchFourFloatsAPtr); 861 var ta = _scratchFourFloatsA['toTypedArray'](); 862 if (optionalOutput) { 863 optionalOutput.set(ta); 864 return optionalOutput; 865 } 866 return ta.slice(); 867 }; 868 869 CanvasKit.ImageFilter.MakeMatrixTransform = function(matrix, sampling, input) { 870 var matrPtr = copy3x3MatrixToWasm(matrix); 871 872 if ('B' in sampling && 'C' in sampling) { 873 return CanvasKit.ImageFilter._MakeMatrixTransformCubic(matrPtr, 874 sampling.B, sampling.C, 875 input); 876 } else { 877 const filter = sampling['filter']; // 'filter' is a required field 878 let mipmap = CanvasKit.MipmapMode.None; 879 if ('mipmap' in sampling) { // 'mipmap' is optional 880 mipmap = sampling['mipmap']; 881 } 882 return CanvasKit.ImageFilter._MakeMatrixTransformOptions(matrPtr, 883 filter, mipmap, 884 input); 885 } 886 }; 887 888 CanvasKit.Paint.prototype.getColor = function() { 889 this._getColor(_scratchColorPtr); 890 return copyColorFromWasm(_scratchColorPtr); 891 }; 892 893 CanvasKit.Paint.prototype.setColor = function(color4f, colorSpace) { 894 colorSpace = colorSpace || null; // null will be replaced with sRGB in the C++ method. 895 // emscripten wouldn't bind undefined to the sk_sp<ColorSpace> expected here. 896 var cPtr = copyColorToWasm(color4f); 897 this._setColor(cPtr, colorSpace); 898 }; 899 900 // The color components here are expected to be floating point values (nominally between 901 // 0.0 and 1.0, but with wider color gamuts, the values could exceed this range). To convert 902 // between standard 8 bit colors and floats, just divide by 255 before passing them in. 903 CanvasKit.Paint.prototype.setColorComponents = function(r, g, b, a, colorSpace) { 904 colorSpace = colorSpace || null; // null will be replaced with sRGB in the C++ method. 905 // emscripten wouldn't bind undefined to the sk_sp<ColorSpace> expected here. 906 var cPtr = copyColorComponentsToWasm(r, g, b, a); 907 this._setColor(cPtr, colorSpace); 908 }; 909 910 CanvasKit.Path.prototype.getPoint = function(idx, optionalOutput) { 911 // This will copy 2 floats into a space for 4 floats 912 this._getPoint(idx, _scratchFourFloatsAPtr); 913 var ta = _scratchFourFloatsA['toTypedArray'](); 914 if (optionalOutput) { 915 // We cannot call optionalOutput.set() because it is an error to call .set() with 916 // a source bigger than the destination. 917 optionalOutput[0] = ta[0]; 918 optionalOutput[1] = ta[1]; 919 return optionalOutput; 920 } 921 // Be sure to return a copy of just the first 2 values. 922 return ta.slice(0, 2); 923 }; 924 925 CanvasKit.PictureRecorder.prototype.beginRecording = function(bounds) { 926 var bPtr = copyRectToWasm(bounds); 927 return this._beginRecording(bPtr); 928 }; 929 930 CanvasKit.Surface.prototype.getCanvas = function() { 931 var c = this._getCanvas(); 932 c._context = this._context; 933 return c; 934 }; 935 936 CanvasKit.Surface.prototype.makeImageSnapshot = function(optionalBoundsRect) { 937 CanvasKit.setCurrentContext(this._context); 938 var bPtr = copyIRectToWasm(optionalBoundsRect); 939 return this._makeImageSnapshot(bPtr); 940 }; 941 942 CanvasKit.Surface.prototype.makeSurface = function(imageInfo) { 943 CanvasKit.setCurrentContext(this._context); 944 var s = this._makeSurface(imageInfo); 945 s._context = this._context; 946 return s; 947 }; 948 949 CanvasKit.Surface.prototype.requestAnimationFrame = function(callback, dirtyRect) { 950 if (!this._cached_canvas) { 951 this._cached_canvas = this.getCanvas(); 952 } 953 requestAnimationFrame(function() { 954 CanvasKit.setCurrentContext(this._context); 955 956 callback(this._cached_canvas); 957 958 // We do not dispose() of the Surface here, as the client will typically 959 // call requestAnimationFrame again from within the supplied callback. 960 // For drawing a single frame, prefer drawOnce(). 961 this.flush(dirtyRect); 962 }.bind(this)); 963 }; 964 965 // drawOnce will dispose of the surface after drawing the frame using the provided 966 // callback. 967 CanvasKit.Surface.prototype.drawOnce = function(callback, dirtyRect) { 968 if (!this._cached_canvas) { 969 this._cached_canvas = this.getCanvas(); 970 } 971 requestAnimationFrame(function() { 972 CanvasKit.setCurrentContext(this._context); 973 callback(this._cached_canvas); 974 975 this.flush(dirtyRect); 976 this.dispose(); 977 }.bind(this)); 978 }; 979 980 CanvasKit.PathEffect.MakeDash = function(intervals, phase) { 981 if (!phase) { 982 phase = 0; 983 } 984 if (!intervals.length || intervals.length % 2 === 1) { 985 throw 'Intervals array must have even length'; 986 } 987 var ptr = copy1dArray(intervals, 'HEAPF32'); 988 var dpe = CanvasKit.PathEffect._MakeDash(ptr, intervals.length, phase); 989 freeArraysThatAreNotMallocedByUsers(ptr, intervals); 990 return dpe; 991 }; 992 993 CanvasKit.Shader.MakeColor = function(color4f, colorSpace) { 994 colorSpace = colorSpace || null; 995 var cPtr = copyColorToWasm(color4f); 996 return CanvasKit.Shader._MakeColor(cPtr, colorSpace); 997 }; 998 999 // TODO(kjlubick) remove deprecated names. 1000 CanvasKit.Shader.Blend = CanvasKit.Shader.MakeBlend; 1001 CanvasKit.Shader.Color = CanvasKit.Shader.MakeColor; 1002 1003 CanvasKit.Shader.MakeLinearGradient = function(start, end, colors, pos, mode, localMatrix, flags, colorSpace) { 1004 colorSpace = colorSpace || null; 1005 var cPtrInfo = copyFlexibleColorArray(colors); 1006 var posPtr = copy1dArray(pos, 'HEAPF32'); 1007 flags = flags || 0; 1008 var localMatrixPtr = copy3x3MatrixToWasm(localMatrix); 1009 1010 // Copy start and end to _scratchFourFloatsAPtr. 1011 var startEndPts = _scratchFourFloatsA['toTypedArray'](); 1012 startEndPts.set(start); 1013 startEndPts.set(end, 2); 1014 1015 var lgs = CanvasKit.Shader._MakeLinearGradient(_scratchFourFloatsAPtr, cPtrInfo.colorPtr, cPtrInfo.colorType, posPtr, 1016 cPtrInfo.count, mode, flags, localMatrixPtr, colorSpace); 1017 1018 freeArraysThatAreNotMallocedByUsers(cPtrInfo.colorPtr, colors); 1019 pos && freeArraysThatAreNotMallocedByUsers(posPtr, pos); 1020 return lgs; 1021 }; 1022 1023 CanvasKit.Shader.MakeRadialGradient = function(center, radius, colors, pos, mode, localMatrix, flags, colorSpace) { 1024 colorSpace = colorSpace || null; 1025 var cPtrInfo = copyFlexibleColorArray(colors); 1026 var posPtr = copy1dArray(pos, 'HEAPF32'); 1027 flags = flags || 0; 1028 var localMatrixPtr = copy3x3MatrixToWasm(localMatrix); 1029 1030 var rgs = CanvasKit.Shader._MakeRadialGradient(center[0], center[1], radius, cPtrInfo.colorPtr, 1031 cPtrInfo.colorType, posPtr, cPtrInfo.count, mode, 1032 flags, localMatrixPtr, colorSpace); 1033 1034 freeArraysThatAreNotMallocedByUsers(cPtrInfo.colorPtr, colors); 1035 pos && freeArraysThatAreNotMallocedByUsers(posPtr, pos); 1036 return rgs; 1037 }; 1038 1039 CanvasKit.Shader.MakeSweepGradient = function(cx, cy, colors, pos, mode, localMatrix, flags, startAngle, endAngle, colorSpace) { 1040 colorSpace = colorSpace || null; 1041 var cPtrInfo = copyFlexibleColorArray(colors); 1042 var posPtr = copy1dArray(pos, 'HEAPF32'); 1043 flags = flags || 0; 1044 startAngle = startAngle || 0; 1045 endAngle = endAngle || 360; 1046 var localMatrixPtr = copy3x3MatrixToWasm(localMatrix); 1047 1048 var sgs = CanvasKit.Shader._MakeSweepGradient(cx, cy, cPtrInfo.colorPtr, cPtrInfo.colorType, posPtr, 1049 cPtrInfo.count, mode, 1050 startAngle, endAngle, flags, 1051 localMatrixPtr, colorSpace); 1052 1053 freeArraysThatAreNotMallocedByUsers(cPtrInfo.colorPtr, colors); 1054 pos && freeArraysThatAreNotMallocedByUsers(posPtr, pos); 1055 return sgs; 1056 }; 1057 1058 CanvasKit.Shader.MakeTwoPointConicalGradient = function(start, startRadius, end, endRadius, 1059 colors, pos, mode, localMatrix, flags, colorSpace) { 1060 colorSpace = colorSpace || null; 1061 var cPtrInfo = copyFlexibleColorArray(colors); 1062 var posPtr = copy1dArray(pos, 'HEAPF32'); 1063 flags = flags || 0; 1064 var localMatrixPtr = copy3x3MatrixToWasm(localMatrix); 1065 1066 // Copy start and end to _scratchFourFloatsAPtr. 1067 var startEndPts = _scratchFourFloatsA['toTypedArray'](); 1068 startEndPts.set(start); 1069 startEndPts.set(end, 2); 1070 1071 var rgs = CanvasKit.Shader._MakeTwoPointConicalGradient(_scratchFourFloatsAPtr, 1072 startRadius, endRadius, cPtrInfo.colorPtr, cPtrInfo.colorType, 1073 posPtr, cPtrInfo.count, mode, flags, localMatrixPtr, colorSpace); 1074 1075 freeArraysThatAreNotMallocedByUsers(cPtrInfo.colorPtr, colors); 1076 pos && freeArraysThatAreNotMallocedByUsers(posPtr, pos); 1077 return rgs; 1078 }; 1079 1080 // Clients can pass in a Float32Array with length 4 to this and the results 1081 // will be copied into that array. Otherwise, a new TypedArray will be allocated 1082 // and returned. 1083 CanvasKit.Vertices.prototype.bounds = function(optionalOutputArray) { 1084 this._bounds(_scratchFourFloatsAPtr); 1085 var ta = _scratchFourFloatsA['toTypedArray'](); 1086 if (optionalOutputArray) { 1087 optionalOutputArray.set(ta); 1088 return optionalOutputArray; 1089 } 1090 return ta.slice(); 1091 }; 1092 1093 // Run through the JS files that are added at compile time. 1094 if (CanvasKit._extraInitializations) { 1095 CanvasKit._extraInitializations.forEach(function(init) { 1096 init(); 1097 }); 1098 } 1099}; // end CanvasKit.onRuntimeInitialized, that is, anything changing prototypes or dynamic. 1100 1101// Accepts an object holding two canvaskit colors. 1102// { 1103// ambient: [r, g, b, a], 1104// spot: [r, g, b, a], 1105// } 1106// Returns the same format. Note, if malloced colors are passed in, the memory 1107// housing the passed in colors passed in will be overwritten with the computed 1108// tonal colors. 1109CanvasKit.computeTonalColors = function(tonalColors) { 1110 // copy the colors into WASM 1111 var cPtrAmbi = copyColorToWasmNoScratch(tonalColors['ambient']); 1112 var cPtrSpot = copyColorToWasmNoScratch(tonalColors['spot']); 1113 // The output of this function will be the same pointers we passed in. 1114 this._computeTonalColors(cPtrAmbi, cPtrSpot); 1115 // Read the results out. 1116 var result = { 1117 'ambient': copyColorFromWasm(cPtrAmbi), 1118 'spot': copyColorFromWasm(cPtrSpot), 1119 }; 1120 // If the user passed us malloced colors in here, we don't want to clean them up. 1121 freeArraysThatAreNotMallocedByUsers(cPtrAmbi, tonalColors['ambient']); 1122 freeArraysThatAreNotMallocedByUsers(cPtrSpot, tonalColors['spot']); 1123 return result; 1124}; 1125 1126CanvasKit.LTRBRect = function(l, t, r, b) { 1127 return Float32Array.of(l, t, r, b); 1128}; 1129 1130CanvasKit.XYWHRect = function(x, y, w, h) { 1131 return Float32Array.of(x, y, x+w, y+h); 1132}; 1133 1134CanvasKit.LTRBiRect = function(l, t, r, b) { 1135 return Int32Array.of(l, t, r, b); 1136}; 1137 1138CanvasKit.XYWHiRect = function(x, y, w, h) { 1139 return Int32Array.of(x, y, x+w, y+h); 1140}; 1141 1142// RRectXY returns a TypedArray representing an RRect with the given rect and a radiusX and 1143// radiusY for all 4 corners. 1144CanvasKit.RRectXY = function(rect, rx, ry) { 1145 return Float32Array.of( 1146 rect[0], rect[1], rect[2], rect[3], 1147 rx, ry, 1148 rx, ry, 1149 rx, ry, 1150 rx, ry, 1151 ); 1152}; 1153 1154// data is a TypedArray or ArrayBuffer e.g. from fetch().then(resp.arrayBuffer()) 1155CanvasKit.MakeAnimatedImageFromEncoded = function(data) { 1156 data = new Uint8Array(data); 1157 1158 var iptr = CanvasKit._malloc(data.byteLength); 1159 CanvasKit.HEAPU8.set(data, iptr); 1160 var img = CanvasKit._decodeAnimatedImage(iptr, data.byteLength); 1161 if (!img) { 1162 Debug('Could not decode animated image'); 1163 return null; 1164 } 1165 return img; 1166}; 1167 1168// data is a TypedArray or ArrayBuffer e.g. from fetch().then(resp.arrayBuffer()) 1169CanvasKit.MakeImageFromEncoded = function(data) { 1170 data = new Uint8Array(data); 1171 1172 var iptr = CanvasKit._malloc(data.byteLength); 1173 CanvasKit.HEAPU8.set(data, iptr); 1174 var img = CanvasKit._decodeImage(iptr, data.byteLength); 1175 if (!img) { 1176 Debug('Could not decode image'); 1177 return null; 1178 } 1179 return img; 1180}; 1181 1182// A variable to hold a canvasElement which can be reused once created the first time. 1183var memoizedCanvas2dElement = null; 1184 1185// Alternative to CanvasKit.MakeImageFromEncoded. Allows for CanvasKit users to take advantage of 1186// browser APIs to decode images instead of using codecs included in the CanvasKit wasm binary. 1187// Expects that the canvasImageSource has already loaded/decoded. 1188// CanvasImageSource reference: https://developer.mozilla.org/en-US/docs/Web/API/CanvasImageSource 1189CanvasKit.MakeImageFromCanvasImageSource = function(canvasImageSource) { 1190 var width = canvasImageSource.width; 1191 var height = canvasImageSource.height; 1192 1193 if (!memoizedCanvas2dElement) { 1194 memoizedCanvas2dElement = document.createElement('canvas'); 1195 } 1196 memoizedCanvas2dElement.width = width; 1197 memoizedCanvas2dElement.height = height; 1198 1199 var ctx2d = memoizedCanvas2dElement.getContext('2d'); 1200 ctx2d.drawImage(canvasImageSource, 0, 0); 1201 1202 var imageData = ctx2d.getImageData(0, 0, width, height); 1203 1204 return CanvasKit.MakeImage({ 1205 'width': width, 1206 'height': height, 1207 'alphaType': CanvasKit.AlphaType.Unpremul, 1208 'colorType': CanvasKit.ColorType.RGBA_8888, 1209 'colorSpace': CanvasKit.ColorSpace.SRGB 1210 }, imageData.data, 4 * width); 1211}; 1212 1213// pixels may be an array but Uint8Array or Uint8ClampedArray is recommended, 1214// with the bytes representing the pixel values. 1215// (e.g. each set of 4 bytes could represent RGBA values for a single pixel). 1216CanvasKit.MakeImage = function(info, pixels, bytesPerRow) { 1217 var pptr = CanvasKit._malloc(pixels.length); 1218 CanvasKit.HEAPU8.set(pixels, pptr); // We always want to copy the bytes into the WASM heap. 1219 // No need to _free pptr, Image takes it with SkData::MakeFromMalloc 1220 return CanvasKit._MakeImage(info, pptr, pixels.length, bytesPerRow); 1221}; 1222 1223// Colors may be a Uint32Array of int colors, a Flat Float32Array of float colors 1224// or a 2d Array of Float32Array(4) (deprecated) 1225// the underlying Skia function accepts only int colors so it is recommended 1226// to pass an array of int colors to avoid an extra conversion. 1227CanvasKit.MakeVertices = function(mode, positions, textureCoordinates, colors, 1228 indices, isVolatile) { 1229 // Default isVolatile to true if not set 1230 isVolatile = isVolatile === undefined ? true : isVolatile; 1231 var idxCount = (indices && indices.length) || 0; 1232 1233 var flags = 0; 1234 // These flags are from SkVertices.h and should be kept in sync with those. 1235 if (textureCoordinates && textureCoordinates.length) { 1236 flags |= (1 << 0); 1237 } 1238 if (colors && colors.length) { 1239 flags |= (1 << 1); 1240 } 1241 if (!isVolatile) { 1242 flags |= (1 << 2); 1243 } 1244 1245 var builder = new CanvasKit._VerticesBuilder(mode, positions.length / 2, idxCount, flags); 1246 1247 copy1dArray(positions, 'HEAPF32', builder.positions()); 1248 if (builder.texCoords()) { 1249 copy1dArray(textureCoordinates, 'HEAPF32', builder.texCoords()); 1250 } 1251 if (builder.colors()) { 1252 copy1dArray(assureIntColors(colors), 'HEAPU32', builder.colors()); 1253 } 1254 if (builder.indices()) { 1255 copy1dArray(indices, 'HEAPU16', builder.indices()); 1256 } 1257 1258 // Create the vertices, which owns the memory that the builder had allocated. 1259 return builder.detach(); 1260}; 1261