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