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 // getTotalMatrix returns the current matrix as a 3x3 matrix. 773 CanvasKit.Canvas.prototype.getTotalMatrix = function() { 774 // _getTotalMatrix will copy the values into the pointer. 775 this._getTotalMatrix(_scratch3x3MatrixPtr); 776 // read them out into an array. TODO(kjlubick): If we change Matrix to be 777 // typedArrays, then we should return a typed array here too. 778 var rv = new Array(9); 779 for (var i = 0; i < 9; i++) { 780 rv[i] = CanvasKit.HEAPF32[_scratch3x3MatrixPtr/4 + i]; // divide by 4 to "cast" to float. 781 } 782 return rv; 783 }; 784 785 CanvasKit.Canvas.prototype.makeSurface = function(imageInfo) { 786 var s = this._makeSurface(imageInfo); 787 s._context = this._context; 788 return s; 789 }; 790 791 CanvasKit.Canvas.prototype.readPixels = function(srcX, srcY, imageInfo, destMallocObj, 792 bytesPerRow) { 793 CanvasKit.setCurrentContext(this._context); 794 return readPixels(this, srcX, srcY, imageInfo, destMallocObj, bytesPerRow); 795 }; 796 797 CanvasKit.Canvas.prototype.saveLayer = function(paint, boundsRect, backdrop, flags) { 798 // bPtr will be 0 (nullptr) if boundsRect is undefined/null. 799 var bPtr = copyRectToWasm(boundsRect); 800 // These or clauses help emscripten, which does not deal with undefined well. 801 return this._saveLayer(paint || null, bPtr, backdrop || null, flags || 0); 802 }; 803 804 // pixels should be a Uint8Array or a plain JS array. 805 CanvasKit.Canvas.prototype.writePixels = function(pixels, srcWidth, srcHeight, 806 destX, destY, alphaType, colorType, colorSpace) { 807 if (pixels.byteLength % (srcWidth * srcHeight)) { 808 throw 'pixels length must be a multiple of the srcWidth * srcHeight'; 809 } 810 CanvasKit.setCurrentContext(this._context); 811 var bytesPerPixel = pixels.byteLength / (srcWidth * srcHeight); 812 // supply defaults (which are compatible with HTMLCanvas's putImageData) 813 alphaType = alphaType || CanvasKit.AlphaType.Unpremul; 814 colorType = colorType || CanvasKit.ColorType.RGBA_8888; 815 colorSpace = colorSpace || CanvasKit.ColorSpace.SRGB; 816 var srcRowBytes = bytesPerPixel * srcWidth; 817 818 var pptr = copy1dArray(pixels, 'HEAPU8'); 819 var ok = this._writePixels({ 820 'width': srcWidth, 821 'height': srcHeight, 822 'colorType': colorType, 823 'alphaType': alphaType, 824 'colorSpace': colorSpace, 825 }, pptr, srcRowBytes, destX, destY); 826 827 freeArraysThatAreNotMallocedByUsers(pptr, pixels); 828 return ok; 829 }; 830 831 CanvasKit.ColorFilter.MakeBlend = function(color4f, mode) { 832 var cPtr = copyColorToWasm(color4f); 833 return CanvasKit.ColorFilter._MakeBlend(cPtr, mode); 834 }; 835 836 // colorMatrix is an ColorMatrix (e.g. Float32Array of length 20) 837 CanvasKit.ColorFilter.MakeMatrix = function(colorMatrix) { 838 if (!colorMatrix || colorMatrix.length !== 20) { 839 throw 'invalid color matrix'; 840 } 841 var fptr = copy1dArray(colorMatrix, 'HEAPF32'); 842 // We know skia memcopies the floats, so we can free our memory after the call returns. 843 var m = CanvasKit.ColorFilter._makeMatrix(fptr); 844 freeArraysThatAreNotMallocedByUsers(fptr, colorMatrix); 845 return m; 846 }; 847 848 CanvasKit.ContourMeasure.prototype.getPosTan = function(distance, optionalOutput) { 849 this._getPosTan(distance, _scratchFourFloatsAPtr); 850 var ta = _scratchFourFloatsA['toTypedArray'](); 851 if (optionalOutput) { 852 optionalOutput.set(ta); 853 return optionalOutput; 854 } 855 return ta.slice(); 856 }; 857 858 CanvasKit.ImageFilter.MakeMatrixTransform = function(matrix, sampling, input) { 859 var matrPtr = copy3x3MatrixToWasm(matrix); 860 861 if ('B' in sampling && 'C' in sampling) { 862 return CanvasKit.ImageFilter._MakeMatrixTransformCubic(matrPtr, 863 sampling.B, sampling.C, 864 input); 865 } else { 866 const filter = sampling['filter']; // 'filter' is a required field 867 let mipmap = CanvasKit.MipmapMode.None; 868 if ('mipmap' in sampling) { // 'mipmap' is optional 869 mipmap = sampling['mipmap']; 870 } 871 return CanvasKit.ImageFilter._MakeMatrixTransformOptions(matrPtr, 872 filter, mipmap, 873 input); 874 } 875 }; 876 877 CanvasKit.Paint.prototype.getColor = function() { 878 this._getColor(_scratchColorPtr); 879 return copyColorFromWasm(_scratchColorPtr); 880 }; 881 882 CanvasKit.Paint.prototype.setColor = function(color4f, colorSpace) { 883 colorSpace = colorSpace || null; // null will be replaced with sRGB in the C++ method. 884 // emscripten wouldn't bind undefined to the sk_sp<ColorSpace> expected here. 885 var cPtr = copyColorToWasm(color4f); 886 this._setColor(cPtr, colorSpace); 887 }; 888 889 // The color components here are expected to be floating point values (nominally between 890 // 0.0 and 1.0, but with wider color gamuts, the values could exceed this range). To convert 891 // between standard 8 bit colors and floats, just divide by 255 before passing them in. 892 CanvasKit.Paint.prototype.setColorComponents = function(r, g, b, a, colorSpace) { 893 colorSpace = colorSpace || null; // null will be replaced with sRGB in the C++ method. 894 // emscripten wouldn't bind undefined to the sk_sp<ColorSpace> expected here. 895 var cPtr = copyColorComponentsToWasm(r, g, b, a); 896 this._setColor(cPtr, colorSpace); 897 }; 898 899 CanvasKit.Path.prototype.getPoint = function(idx, optionalOutput) { 900 // This will copy 2 floats into a space for 4 floats 901 this._getPoint(idx, _scratchFourFloatsAPtr); 902 var ta = _scratchFourFloatsA['toTypedArray'](); 903 if (optionalOutput) { 904 // We cannot call optionalOutput.set() because it is an error to call .set() with 905 // a source bigger than the destination. 906 optionalOutput[0] = ta[0]; 907 optionalOutput[1] = ta[1]; 908 return optionalOutput; 909 } 910 // Be sure to return a copy of just the first 2 values. 911 return ta.slice(0, 2); 912 }; 913 914 CanvasKit.Picture.prototype.makeShader = function(tmx, tmy, mode, matr, rect) { 915 var mPtr = copy3x3MatrixToWasm(matr); 916 var rPtr = copyRectToWasm(rect); 917 return this._makeShader(tmx, tmy, mode, mPtr, rPtr); 918 }; 919 920 CanvasKit.PictureRecorder.prototype.beginRecording = function(bounds) { 921 var bPtr = copyRectToWasm(bounds); 922 return this._beginRecording(bPtr); 923 }; 924 925 CanvasKit.Surface.prototype.getCanvas = function() { 926 var c = this._getCanvas(); 927 c._context = this._context; 928 return c; 929 }; 930 931 CanvasKit.Surface.prototype.makeImageSnapshot = function(optionalBoundsRect) { 932 CanvasKit.setCurrentContext(this._context); 933 var bPtr = copyIRectToWasm(optionalBoundsRect); 934 return this._makeImageSnapshot(bPtr); 935 }; 936 937 CanvasKit.Surface.prototype.makeSurface = function(imageInfo) { 938 CanvasKit.setCurrentContext(this._context); 939 var s = this._makeSurface(imageInfo); 940 s._context = this._context; 941 return s; 942 }; 943 944 CanvasKit.Surface.prototype.requestAnimationFrame = function(callback, dirtyRect) { 945 if (!this._cached_canvas) { 946 this._cached_canvas = this.getCanvas(); 947 } 948 requestAnimationFrame(function() { 949 CanvasKit.setCurrentContext(this._context); 950 951 callback(this._cached_canvas); 952 953 // We do not dispose() of the Surface here, as the client will typically 954 // call requestAnimationFrame again from within the supplied callback. 955 // For drawing a single frame, prefer drawOnce(). 956 this.flush(dirtyRect); 957 }.bind(this)); 958 }; 959 960 // drawOnce will dispose of the surface after drawing the frame using the provided 961 // callback. 962 CanvasKit.Surface.prototype.drawOnce = function(callback, dirtyRect) { 963 if (!this._cached_canvas) { 964 this._cached_canvas = this.getCanvas(); 965 } 966 requestAnimationFrame(function() { 967 CanvasKit.setCurrentContext(this._context); 968 callback(this._cached_canvas); 969 970 this.flush(dirtyRect); 971 this.dispose(); 972 }.bind(this)); 973 }; 974 975 CanvasKit.PathEffect.MakeDash = function(intervals, phase) { 976 if (!phase) { 977 phase = 0; 978 } 979 if (!intervals.length || intervals.length % 2 === 1) { 980 throw 'Intervals array must have even length'; 981 } 982 var ptr = copy1dArray(intervals, 'HEAPF32'); 983 var dpe = CanvasKit.PathEffect._MakeDash(ptr, intervals.length, phase); 984 freeArraysThatAreNotMallocedByUsers(ptr, intervals); 985 return dpe; 986 }; 987 988 CanvasKit.PathEffect.MakeLine2D = function(width, matrix) { 989 var matrixPtr = copy3x3MatrixToWasm(matrix); 990 return CanvasKit.PathEffect._MakeLine2D(width, matrixPtr); 991 }; 992 993 CanvasKit.PathEffect.MakePath2D = function(matrix, path) { 994 var matrixPtr = copy3x3MatrixToWasm(matrix); 995 return CanvasKit.PathEffect._MakePath2D(matrixPtr, path); 996 }; 997 998 CanvasKit.Shader.MakeColor = function(color4f, colorSpace) { 999 colorSpace = colorSpace || null; 1000 var cPtr = copyColorToWasm(color4f); 1001 return CanvasKit.Shader._MakeColor(cPtr, colorSpace); 1002 }; 1003 1004 // TODO(kjlubick) remove deprecated names. 1005 CanvasKit.Shader.Blend = CanvasKit.Shader.MakeBlend; 1006 CanvasKit.Shader.Color = CanvasKit.Shader.MakeColor; 1007 1008 CanvasKit.Shader.MakeLinearGradient = function(start, end, colors, pos, mode, localMatrix, flags, colorSpace) { 1009 colorSpace = colorSpace || null; 1010 var cPtrInfo = copyFlexibleColorArray(colors); 1011 var posPtr = copy1dArray(pos, 'HEAPF32'); 1012 flags = flags || 0; 1013 var localMatrixPtr = copy3x3MatrixToWasm(localMatrix); 1014 1015 // Copy start and end to _scratchFourFloatsAPtr. 1016 var startEndPts = _scratchFourFloatsA['toTypedArray'](); 1017 startEndPts.set(start); 1018 startEndPts.set(end, 2); 1019 1020 var lgs = CanvasKit.Shader._MakeLinearGradient(_scratchFourFloatsAPtr, cPtrInfo.colorPtr, cPtrInfo.colorType, posPtr, 1021 cPtrInfo.count, mode, flags, localMatrixPtr, colorSpace); 1022 1023 freeArraysThatAreNotMallocedByUsers(cPtrInfo.colorPtr, colors); 1024 pos && freeArraysThatAreNotMallocedByUsers(posPtr, pos); 1025 return lgs; 1026 }; 1027 1028 CanvasKit.Shader.MakeRadialGradient = function(center, radius, colors, pos, mode, localMatrix, flags, colorSpace) { 1029 colorSpace = colorSpace || null; 1030 var cPtrInfo = copyFlexibleColorArray(colors); 1031 var posPtr = copy1dArray(pos, 'HEAPF32'); 1032 flags = flags || 0; 1033 var localMatrixPtr = copy3x3MatrixToWasm(localMatrix); 1034 1035 var rgs = CanvasKit.Shader._MakeRadialGradient(center[0], center[1], radius, cPtrInfo.colorPtr, 1036 cPtrInfo.colorType, posPtr, cPtrInfo.count, mode, 1037 flags, localMatrixPtr, colorSpace); 1038 1039 freeArraysThatAreNotMallocedByUsers(cPtrInfo.colorPtr, colors); 1040 pos && freeArraysThatAreNotMallocedByUsers(posPtr, pos); 1041 return rgs; 1042 }; 1043 1044 CanvasKit.Shader.MakeSweepGradient = function(cx, cy, colors, pos, mode, localMatrix, flags, startAngle, endAngle, colorSpace) { 1045 colorSpace = colorSpace || null; 1046 var cPtrInfo = copyFlexibleColorArray(colors); 1047 var posPtr = copy1dArray(pos, 'HEAPF32'); 1048 flags = flags || 0; 1049 startAngle = startAngle || 0; 1050 endAngle = endAngle || 360; 1051 var localMatrixPtr = copy3x3MatrixToWasm(localMatrix); 1052 1053 var sgs = CanvasKit.Shader._MakeSweepGradient(cx, cy, cPtrInfo.colorPtr, cPtrInfo.colorType, posPtr, 1054 cPtrInfo.count, mode, 1055 startAngle, endAngle, flags, 1056 localMatrixPtr, colorSpace); 1057 1058 freeArraysThatAreNotMallocedByUsers(cPtrInfo.colorPtr, colors); 1059 pos && freeArraysThatAreNotMallocedByUsers(posPtr, pos); 1060 return sgs; 1061 }; 1062 1063 CanvasKit.Shader.MakeTwoPointConicalGradient = function(start, startRadius, end, endRadius, 1064 colors, pos, mode, localMatrix, flags, colorSpace) { 1065 colorSpace = colorSpace || null; 1066 var cPtrInfo = copyFlexibleColorArray(colors); 1067 var posPtr = copy1dArray(pos, 'HEAPF32'); 1068 flags = flags || 0; 1069 var localMatrixPtr = copy3x3MatrixToWasm(localMatrix); 1070 1071 // Copy start and end to _scratchFourFloatsAPtr. 1072 var startEndPts = _scratchFourFloatsA['toTypedArray'](); 1073 startEndPts.set(start); 1074 startEndPts.set(end, 2); 1075 1076 var rgs = CanvasKit.Shader._MakeTwoPointConicalGradient(_scratchFourFloatsAPtr, 1077 startRadius, endRadius, cPtrInfo.colorPtr, cPtrInfo.colorType, 1078 posPtr, cPtrInfo.count, mode, flags, localMatrixPtr, colorSpace); 1079 1080 freeArraysThatAreNotMallocedByUsers(cPtrInfo.colorPtr, colors); 1081 pos && freeArraysThatAreNotMallocedByUsers(posPtr, pos); 1082 return rgs; 1083 }; 1084 1085 // Clients can pass in a Float32Array with length 4 to this and the results 1086 // will be copied into that array. Otherwise, a new TypedArray will be allocated 1087 // and returned. 1088 CanvasKit.Vertices.prototype.bounds = function(optionalOutputArray) { 1089 this._bounds(_scratchFourFloatsAPtr); 1090 var ta = _scratchFourFloatsA['toTypedArray'](); 1091 if (optionalOutputArray) { 1092 optionalOutputArray.set(ta); 1093 return optionalOutputArray; 1094 } 1095 return ta.slice(); 1096 }; 1097 1098 // Run through the JS files that are added at compile time. 1099 if (CanvasKit._extraInitializations) { 1100 CanvasKit._extraInitializations.forEach(function(init) { 1101 init(); 1102 }); 1103 } 1104}; // end CanvasKit.onRuntimeInitialized, that is, anything changing prototypes or dynamic. 1105 1106// Accepts an object holding two canvaskit colors. 1107// { 1108// ambient: [r, g, b, a], 1109// spot: [r, g, b, a], 1110// } 1111// Returns the same format. Note, if malloced colors are passed in, the memory 1112// housing the passed in colors passed in will be overwritten with the computed 1113// tonal colors. 1114CanvasKit.computeTonalColors = function(tonalColors) { 1115 // copy the colors into WASM 1116 var cPtrAmbi = copyColorToWasmNoScratch(tonalColors['ambient']); 1117 var cPtrSpot = copyColorToWasmNoScratch(tonalColors['spot']); 1118 // The output of this function will be the same pointers we passed in. 1119 this._computeTonalColors(cPtrAmbi, cPtrSpot); 1120 // Read the results out. 1121 var result = { 1122 'ambient': copyColorFromWasm(cPtrAmbi), 1123 'spot': copyColorFromWasm(cPtrSpot), 1124 }; 1125 // If the user passed us malloced colors in here, we don't want to clean them up. 1126 freeArraysThatAreNotMallocedByUsers(cPtrAmbi, tonalColors['ambient']); 1127 freeArraysThatAreNotMallocedByUsers(cPtrSpot, tonalColors['spot']); 1128 return result; 1129}; 1130 1131CanvasKit.LTRBRect = function(l, t, r, b) { 1132 return Float32Array.of(l, t, r, b); 1133}; 1134 1135CanvasKit.XYWHRect = function(x, y, w, h) { 1136 return Float32Array.of(x, y, x+w, y+h); 1137}; 1138 1139CanvasKit.LTRBiRect = function(l, t, r, b) { 1140 return Int32Array.of(l, t, r, b); 1141}; 1142 1143CanvasKit.XYWHiRect = function(x, y, w, h) { 1144 return Int32Array.of(x, y, x+w, y+h); 1145}; 1146 1147// RRectXY returns a TypedArray representing an RRect with the given rect and a radiusX and 1148// radiusY for all 4 corners. 1149CanvasKit.RRectXY = function(rect, rx, ry) { 1150 return Float32Array.of( 1151 rect[0], rect[1], rect[2], rect[3], 1152 rx, ry, 1153 rx, ry, 1154 rx, ry, 1155 rx, ry, 1156 ); 1157}; 1158 1159// data is a TypedArray or ArrayBuffer e.g. from fetch().then(resp.arrayBuffer()) 1160CanvasKit.MakeAnimatedImageFromEncoded = function(data) { 1161 data = new Uint8Array(data); 1162 1163 var iptr = CanvasKit._malloc(data.byteLength); 1164 CanvasKit.HEAPU8.set(data, iptr); 1165 var img = CanvasKit._decodeAnimatedImage(iptr, data.byteLength); 1166 if (!img) { 1167 Debug('Could not decode animated image'); 1168 return null; 1169 } 1170 return img; 1171}; 1172 1173// data is a TypedArray or ArrayBuffer e.g. from fetch().then(resp.arrayBuffer()) 1174CanvasKit.MakeImageFromEncoded = function(data) { 1175 data = new Uint8Array(data); 1176 1177 var iptr = CanvasKit._malloc(data.byteLength); 1178 CanvasKit.HEAPU8.set(data, iptr); 1179 var img = CanvasKit._decodeImage(iptr, data.byteLength); 1180 if (!img) { 1181 Debug('Could not decode image'); 1182 return null; 1183 } 1184 return img; 1185}; 1186 1187// A variable to hold a canvasElement which can be reused once created the first time. 1188var memoizedCanvas2dElement = null; 1189 1190// Alternative to CanvasKit.MakeImageFromEncoded. Allows for CanvasKit users to take advantage of 1191// browser APIs to decode images instead of using codecs included in the CanvasKit wasm binary. 1192// Expects that the canvasImageSource has already loaded/decoded. 1193// CanvasImageSource reference: https://developer.mozilla.org/en-US/docs/Web/API/CanvasImageSource 1194CanvasKit.MakeImageFromCanvasImageSource = function(canvasImageSource) { 1195 var width = canvasImageSource.width; 1196 var height = canvasImageSource.height; 1197 1198 if (!memoizedCanvas2dElement) { 1199 memoizedCanvas2dElement = document.createElement('canvas'); 1200 } 1201 memoizedCanvas2dElement.width = width; 1202 memoizedCanvas2dElement.height = height; 1203 1204 var ctx2d = memoizedCanvas2dElement.getContext('2d', {willReadFrequently: true}); 1205 ctx2d.drawImage(canvasImageSource, 0, 0); 1206 1207 var imageData = ctx2d.getImageData(0, 0, width, height); 1208 1209 return CanvasKit.MakeImage({ 1210 'width': width, 1211 'height': height, 1212 'alphaType': CanvasKit.AlphaType.Unpremul, 1213 'colorType': CanvasKit.ColorType.RGBA_8888, 1214 'colorSpace': CanvasKit.ColorSpace.SRGB 1215 }, imageData.data, 4 * width); 1216}; 1217 1218// pixels may be an array but Uint8Array or Uint8ClampedArray is recommended, 1219// with the bytes representing the pixel values. 1220// (e.g. each set of 4 bytes could represent RGBA values for a single pixel). 1221CanvasKit.MakeImage = function(info, pixels, bytesPerRow) { 1222 var pptr = CanvasKit._malloc(pixels.length); 1223 CanvasKit.HEAPU8.set(pixels, pptr); // We always want to copy the bytes into the WASM heap. 1224 // No need to _free pptr, Image takes it with SkData::MakeFromMalloc 1225 return CanvasKit._MakeImage(info, pptr, pixels.length, bytesPerRow); 1226}; 1227 1228// Colors may be a Uint32Array of int colors, a Flat Float32Array of float colors 1229// or a 2d Array of Float32Array(4) (deprecated) 1230// the underlying Skia function accepts only int colors so it is recommended 1231// to pass an array of int colors to avoid an extra conversion. 1232CanvasKit.MakeVertices = function(mode, positions, textureCoordinates, colors, 1233 indices, isVolatile) { 1234 // Default isVolatile to true if not set 1235 isVolatile = isVolatile === undefined ? true : isVolatile; 1236 var idxCount = (indices && indices.length) || 0; 1237 1238 var flags = 0; 1239 // These flags are from SkVertices.h and should be kept in sync with those. 1240 if (textureCoordinates && textureCoordinates.length) { 1241 flags |= (1 << 0); 1242 } 1243 if (colors && colors.length) { 1244 flags |= (1 << 1); 1245 } 1246 if (!isVolatile) { 1247 flags |= (1 << 2); 1248 } 1249 1250 var builder = new CanvasKit._VerticesBuilder(mode, positions.length / 2, idxCount, flags); 1251 1252 copy1dArray(positions, 'HEAPF32', builder.positions()); 1253 if (builder.texCoords()) { 1254 copy1dArray(textureCoordinates, 'HEAPF32', builder.texCoords()); 1255 } 1256 if (builder.colors()) { 1257 copy1dArray(assureIntColors(colors), 'HEAPU32', builder.colors()); 1258 } 1259 if (builder.indices()) { 1260 copy1dArray(indices, 'HEAPU16', builder.indices()); 1261 } 1262 1263 // Create the vertices, which owns the memory that the builder had allocated. 1264 return builder.detach(); 1265}; 1266