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 CanvasKit.Image.prototype.encodeToBytes = function(fmt, quality) { 378 var grCtx = CanvasKit.getCurrentGrDirectContext(); 379 fmt = fmt || CanvasKit.ImageFormat.PNG; 380 quality = quality || 100; 381 if (grCtx) { 382 return this._encodeToBytes(fmt, quality, grCtx); 383 } else { 384 return this._encodeToBytes(fmt, quality); 385 } 386 }; 387 388 // makeShaderCubic returns a shader for a given image, allowing it to be used on 389 // a paint as well as other purposes. This shader will be higher quality than 390 // other shader functions. See CubicResampler in SkSamplingOptions.h for more information 391 // on the cubicResampler params. 392 CanvasKit.Image.prototype.makeShaderCubic = function(xTileMode, yTileMode, 393 cubicResamplerB, cubicResamplerC, 394 localMatrix) { 395 var localMatrixPtr = copy3x3MatrixToWasm(localMatrix); 396 return this._makeShaderCubic(xTileMode, yTileMode, cubicResamplerB, 397 cubicResamplerC, localMatrixPtr); 398 }; 399 400 // makeShaderCubic returns a shader for a given image, allowing it to be used on 401 // a paint as well as other purposes. This shader will draw more quickly than 402 // other shader functions, but at a lower quality. 403 CanvasKit.Image.prototype.makeShaderOptions = function(xTileMode, yTileMode, 404 filterMode, mipmapMode, 405 localMatrix) { 406 var localMatrixPtr = copy3x3MatrixToWasm(localMatrix); 407 return this._makeShaderOptions(xTileMode, yTileMode, filterMode, mipmapMode, localMatrixPtr); 408 }; 409 410 function readPixels(source, srcX, srcY, imageInfo, destMallocObj, bytesPerRow, grCtx) { 411 if (!bytesPerRow) { 412 bytesPerRow = 4 * imageInfo['width']; 413 if (imageInfo['colorType'] === CanvasKit.ColorType.RGBA_F16) { 414 bytesPerRow *= 2; 415 } 416 else if (imageInfo['colorType'] === CanvasKit.ColorType.RGBA_F32) { 417 bytesPerRow *= 4; 418 } 419 } 420 var pBytes = bytesPerRow * imageInfo.height; 421 var pPtr; 422 if (destMallocObj) { 423 pPtr = destMallocObj['byteOffset']; 424 } else { 425 pPtr = CanvasKit._malloc(pBytes); 426 } 427 428 var rv; 429 if (grCtx) { 430 rv = source._readPixels(imageInfo, pPtr, bytesPerRow, srcX, srcY, grCtx); 431 } else { 432 rv = source._readPixels(imageInfo, pPtr, bytesPerRow, srcX, srcY); 433 } 434 if (!rv) { 435 Debug('Could not read pixels with the given inputs'); 436 if (!destMallocObj) { 437 CanvasKit._free(pPtr); 438 } 439 return null; 440 } 441 442 // If the user provided us a buffer to copy into, we don't need to allocate a new TypedArray. 443 if (destMallocObj) { 444 return destMallocObj['toTypedArray'](); // Return the typed array wrapper w/o allocating. 445 } 446 447 // Put those pixels into a typed array of the right format and then 448 // make a copy with slice() that we can return. 449 var retVal = null; 450 switch (imageInfo['colorType']) { 451 case CanvasKit.ColorType.RGBA_8888: 452 case CanvasKit.ColorType.RGBA_F16: // there is no half-float JS type, so we return raw bytes. 453 retVal = new Uint8Array(CanvasKit.HEAPU8.buffer, pPtr, pBytes).slice(); 454 break; 455 case CanvasKit.ColorType.RGBA_F32: 456 retVal = new Float32Array(CanvasKit.HEAPU8.buffer, pPtr, pBytes).slice(); 457 break; 458 default: 459 Debug('ColorType not yet supported'); 460 return null; 461 } 462 463 // Free the allocated pixels in the WASM memory 464 CanvasKit._free(pPtr); 465 return retVal; 466 } 467 468 CanvasKit.Image.prototype.readPixels = function(srcX, srcY, imageInfo, destMallocObj, 469 bytesPerRow) { 470 var grCtx = CanvasKit.getCurrentGrDirectContext(); 471 return readPixels(this, srcX, srcY, imageInfo, destMallocObj, bytesPerRow, grCtx); 472 }; 473 474 // Accepts an array of four numbers in the range of 0-1 representing a 4f color 475 CanvasKit.Canvas.prototype.clear = function(color4f) { 476 CanvasKit.setCurrentContext(this._context); 477 var cPtr = copyColorToWasm(color4f); 478 this._clear(cPtr); 479 }; 480 481 CanvasKit.Canvas.prototype.clipRRect = function(rrect, op, antialias) { 482 CanvasKit.setCurrentContext(this._context); 483 var rPtr = copyRRectToWasm(rrect); 484 this._clipRRect(rPtr, op, antialias); 485 }; 486 487 CanvasKit.Canvas.prototype.clipRect = function(rect, op, antialias) { 488 CanvasKit.setCurrentContext(this._context); 489 var rPtr = copyRectToWasm(rect); 490 this._clipRect(rPtr, op, antialias); 491 }; 492 493 // concat takes a 3x2, a 3x3, or a 4x4 matrix and upscales it (if needed) to 4x4. This is because 494 // under the hood, SkCanvas uses a 4x4 matrix. 495 CanvasKit.Canvas.prototype.concat = function(matr) { 496 CanvasKit.setCurrentContext(this._context); 497 var matrPtr = copy4x4MatrixToWasm(matr); 498 this._concat(matrPtr); 499 }; 500 501 CanvasKit.Canvas.prototype.drawArc = function(oval, startAngle, sweepAngle, useCenter, paint) { 502 CanvasKit.setCurrentContext(this._context); 503 var oPtr = copyRectToWasm(oval); 504 this._drawArc(oPtr, startAngle, sweepAngle, useCenter, paint); 505 }; 506 507 // atlas is an Image, e.g. from CanvasKit.MakeImageFromEncoded 508 // srcRects, dstXformsshould be arrays of floats of length 4*number of destinations. 509 // The colors param is optional and is used to tint the drawn images using the optional blend 510 // mode. Colors can be a Uint32Array of int colors or a flat Float32Array of float colors. 511 CanvasKit.Canvas.prototype.drawAtlas = function(atlas, srcRects, dstXforms, paint, 512 /* optional */ blendMode, /* optional */ colors, 513 /* optional */ sampling) { 514 if (!atlas || !paint || !srcRects || !dstXforms) { 515 Debug('Doing nothing since missing a required input'); 516 return; 517 } 518 519 // builder arguments report the length as the number of rects, but when passed as arrays 520 // their.length attribute is 4x higher because it's the number of total components of all rects. 521 // colors is always going to report the same length, at least until floats colors are supported 522 // by this function. 523 if (srcRects.length !== dstXforms.length) { 524 Debug('Doing nothing since input arrays length mismatches'); 525 return; 526 } 527 CanvasKit.setCurrentContext(this._context); 528 if (!blendMode) { 529 blendMode = CanvasKit.BlendMode.SrcOver; 530 } 531 532 var srcRectPtr = copy1dArray(srcRects, 'HEAPF32'); 533 534 var dstXformPtr = copy1dArray(dstXforms, 'HEAPF32'); 535 var count = dstXforms.length / 4; 536 537 var colorPtr = copy1dArray(assureIntColors(colors), 'HEAPU32'); 538 539 // We require one of these: 540 // 1. sampling is null (we default to linear/none) 541 // 2. sampling.B and sampling.C --> CubicResampler 542 // 3. sampling.filter [and sampling.mipmap] --> FilterOptions 543 // 544 // Thus if all fields are available, we will choose cubic (since we search for B,C first) 545 546 if (sampling && ('B' in sampling) && ('C' in sampling)) { 547 this._drawAtlasCubic(atlas, dstXformPtr, srcRectPtr, colorPtr, count, blendMode, 548 sampling['B'], sampling['C'], paint); 549 } else { 550 let filter = CanvasKit.FilterMode.Linear; 551 let mipmap = CanvasKit.MipmapMode.None; 552 if (sampling) { 553 filter = sampling['filter']; // 'filter' is a required field 554 if ('mipmap' in sampling) { // 'mipmap' is optional 555 mipmap = sampling['mipmap']; 556 } 557 } 558 this._drawAtlasOptions(atlas, dstXformPtr, srcRectPtr, colorPtr, count, blendMode, 559 filter, mipmap, paint); 560 } 561 562 freeArraysThatAreNotMallocedByUsers(srcRectPtr, srcRects); 563 freeArraysThatAreNotMallocedByUsers(dstXformPtr, dstXforms); 564 freeArraysThatAreNotMallocedByUsers(colorPtr, colors); 565 }; 566 567 CanvasKit.Canvas.prototype.drawCircle = function(cx, cy, r, paint) { 568 CanvasKit.setCurrentContext(this._context); 569 this._drawCircle(cx, cy, r, paint); 570 } 571 572 CanvasKit.Canvas.prototype.drawColor = function(color4f, mode) { 573 CanvasKit.setCurrentContext(this._context); 574 var cPtr = copyColorToWasm(color4f); 575 if (mode !== undefined) { 576 this._drawColor(cPtr, mode); 577 } else { 578 this._drawColor(cPtr); 579 } 580 }; 581 582 CanvasKit.Canvas.prototype.drawColorInt = function(color, mode) { 583 CanvasKit.setCurrentContext(this._context); 584 this._drawColorInt(color, mode || CanvasKit.BlendMode.SrcOver); 585 } 586 587 CanvasKit.Canvas.prototype.drawColorComponents = function(r, g, b, a, mode) { 588 CanvasKit.setCurrentContext(this._context); 589 var cPtr = copyColorComponentsToWasm(r, g, b, a); 590 if (mode !== undefined) { 591 this._drawColor(cPtr, mode); 592 } else { 593 this._drawColor(cPtr); 594 } 595 }; 596 597 CanvasKit.Canvas.prototype.drawDRRect = function(outer, inner, paint) { 598 CanvasKit.setCurrentContext(this._context); 599 var oPtr = copyRRectToWasm(outer, _scratchRRectPtr); 600 var iPtr = copyRRectToWasm(inner, _scratchRRect2Ptr); 601 this._drawDRRect(oPtr, iPtr, paint); 602 }; 603 604 CanvasKit.Canvas.prototype.drawImage = function(img, x, y, paint) { 605 CanvasKit.setCurrentContext(this._context); 606 this._drawImage(img, x, y, paint || null); 607 }; 608 609 CanvasKit.Canvas.prototype.drawImageCubic = function(img, x, y, b, c, paint) { 610 CanvasKit.setCurrentContext(this._context); 611 this._drawImageCubic(img, x, y, b, c, paint || null); 612 }; 613 614 CanvasKit.Canvas.prototype.drawImageOptions = function(img, x, y, filter, mipmap, paint) { 615 CanvasKit.setCurrentContext(this._context); 616 this._drawImageOptions(img, x, y, filter, mipmap, paint || null); 617 }; 618 619 CanvasKit.Canvas.prototype.drawImageNine = function(img, center, dest, filter, paint) { 620 CanvasKit.setCurrentContext(this._context); 621 var cPtr = copyIRectToWasm(center); 622 var dPtr = copyRectToWasm(dest); 623 this._drawImageNine(img, cPtr, dPtr, filter, paint || null); 624 }; 625 626 CanvasKit.Canvas.prototype.drawImageRect = function(img, src, dest, paint, fastSample) { 627 CanvasKit.setCurrentContext(this._context); 628 copyRectToWasm(src, _scratchFourFloatsAPtr); 629 copyRectToWasm(dest, _scratchFourFloatsBPtr); 630 this._drawImageRect(img, _scratchFourFloatsAPtr, _scratchFourFloatsBPtr, paint, !!fastSample); 631 }; 632 633 CanvasKit.Canvas.prototype.drawImageRectCubic = function(img, src, dest, B, C, paint) { 634 CanvasKit.setCurrentContext(this._context); 635 copyRectToWasm(src, _scratchFourFloatsAPtr); 636 copyRectToWasm(dest, _scratchFourFloatsBPtr); 637 this._drawImageRectCubic(img, _scratchFourFloatsAPtr, _scratchFourFloatsBPtr, B, C, 638 paint || null); 639 }; 640 641 CanvasKit.Canvas.prototype.drawImageRectOptions = function(img, src, dest, filter, mipmap, paint) { 642 CanvasKit.setCurrentContext(this._context); 643 copyRectToWasm(src, _scratchFourFloatsAPtr); 644 copyRectToWasm(dest, _scratchFourFloatsBPtr); 645 this._drawImageRectOptions(img, _scratchFourFloatsAPtr, _scratchFourFloatsBPtr, filter, mipmap, 646 paint || null); 647 }; 648 649 CanvasKit.Canvas.prototype.drawLine = function(x1, y1, x2, y2, paint) { 650 CanvasKit.setCurrentContext(this._context); 651 this._drawLine(x1, y1, x2, y2, paint); 652 } 653 654 CanvasKit.Canvas.prototype.drawOval = function(oval, paint) { 655 CanvasKit.setCurrentContext(this._context); 656 var oPtr = copyRectToWasm(oval); 657 this._drawOval(oPtr, paint); 658 }; 659 660 CanvasKit.Canvas.prototype.drawPaint = function(paint) { 661 CanvasKit.setCurrentContext(this._context); 662 this._drawPaint(paint); 663 } 664 665 CanvasKit.Canvas.prototype.drawParagraph = function(p, x, y) { 666 CanvasKit.setCurrentContext(this._context); 667 this._drawParagraph(p, x, y); 668 } 669 670 CanvasKit.Canvas.prototype.drawPatch = function(cubics, colors, texs, mode, paint) { 671 if (cubics.length < 24) { 672 throw 'Need 12 cubic points'; 673 } 674 if (colors && colors.length < 4) { 675 throw 'Need 4 colors'; 676 } 677 if (texs && texs.length < 8) { 678 throw 'Need 4 shader coordinates'; 679 } 680 CanvasKit.setCurrentContext(this._context); 681 682 const cubics_ptr = copy1dArray(cubics, 'HEAPF32'); 683 const colors_ptr = colors ? copy1dArray(assureIntColors(colors), 'HEAPU32') : nullptr; 684 const texs_ptr = texs ? copy1dArray(texs, 'HEAPF32') : nullptr; 685 if (!mode) { 686 mode = CanvasKit.BlendMode.Modulate; 687 } 688 689 this._drawPatch(cubics_ptr, colors_ptr, texs_ptr, mode, paint); 690 691 freeArraysThatAreNotMallocedByUsers(texs_ptr, texs); 692 freeArraysThatAreNotMallocedByUsers(colors_ptr, colors); 693 freeArraysThatAreNotMallocedByUsers(cubics_ptr, cubics); 694 }; 695 696 CanvasKit.Canvas.prototype.drawPath = function(path, paint) { 697 CanvasKit.setCurrentContext(this._context); 698 this._drawPath(path, paint); 699 } 700 701 CanvasKit.Canvas.prototype.drawPicture = function(pic) { 702 CanvasKit.setCurrentContext(this._context); 703 this._drawPicture(pic); 704 } 705 706 // points is a 1d array of length 2n representing n points where the even indices 707 // will be treated as x coordinates and the odd indices will be treated as y coordinates. 708 // Like other APIs, this accepts a malloced type array or malloc obj. 709 CanvasKit.Canvas.prototype.drawPoints = function(mode, points, paint) { 710 CanvasKit.setCurrentContext(this._context); 711 var ptr = copy1dArray(points, 'HEAPF32'); 712 this._drawPoints(mode, ptr, points.length / 2, paint); 713 freeArraysThatAreNotMallocedByUsers(ptr, points); 714 }; 715 716 CanvasKit.Canvas.prototype.drawRRect = function(rrect, paint) { 717 CanvasKit.setCurrentContext(this._context); 718 var rPtr = copyRRectToWasm(rrect); 719 this._drawRRect(rPtr, paint); 720 }; 721 722 CanvasKit.Canvas.prototype.drawRect = function(rect, paint) { 723 CanvasKit.setCurrentContext(this._context); 724 var rPtr = copyRectToWasm(rect); 725 this._drawRect(rPtr, paint); 726 }; 727 728 CanvasKit.Canvas.prototype.drawRect4f = function(l, t, r, b, paint) { 729 CanvasKit.setCurrentContext(this._context); 730 this._drawRect4f(l, t, r, b, paint); 731 } 732 733 CanvasKit.Canvas.prototype.drawShadow = function(path, zPlaneParams, lightPos, lightRadius, 734 ambientColor, spotColor, flags) { 735 CanvasKit.setCurrentContext(this._context); 736 var ambiPtr = copyColorToWasmNoScratch(ambientColor); 737 var spotPtr = copyColorToWasmNoScratch(spotColor); 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 this._drawShadow(path, zPlanePtr, lightPosPtr, lightRadius, ambiPtr, spotPtr, flags); 742 freeArraysThatAreNotMallocedByUsers(ambiPtr, ambientColor); 743 freeArraysThatAreNotMallocedByUsers(spotPtr, spotColor); 744 }; 745 746 CanvasKit.getShadowLocalBounds = function(ctm, path, zPlaneParams, lightPos, lightRadius, 747 flags, optOutputRect) { 748 var ctmPtr = copy3x3MatrixToWasm(ctm); 749 // We use the return value from copy1dArray in case the passed in arrays are malloc'd. 750 var zPlanePtr = copy1dArray(zPlaneParams, 'HEAPF32', _scratchThreeFloatsAPtr); 751 var lightPosPtr = copy1dArray(lightPos, 'HEAPF32', _scratchThreeFloatsBPtr); 752 var ok = this._getShadowLocalBounds(ctmPtr, path, zPlanePtr, lightPosPtr, lightRadius, 753 flags, _scratchFourFloatsAPtr); 754 if (!ok) { 755 return null; 756 } 757 var ta = _scratchFourFloatsA['toTypedArray'](); 758 if (optOutputRect) { 759 optOutputRect.set(ta); 760 return optOutputRect; 761 } 762 return ta.slice(); 763 }; 764 765 CanvasKit.Canvas.prototype.drawTextBlob = function(blob, x, y, paint) { 766 CanvasKit.setCurrentContext(this._context); 767 this._drawTextBlob(blob, x, y, paint); 768 } 769 770 CanvasKit.Canvas.prototype.drawVertices = function(verts, mode, paint) { 771 CanvasKit.setCurrentContext(this._context); 772 this._drawVertices(verts, mode, paint); 773 } 774 775 // getDeviceClipBounds returns an SkIRect 776 CanvasKit.Canvas.prototype.getDeviceClipBounds = function(outputRect) { 777 // _getDeviceClipBounds will copy the values into the pointer. 778 this._getDeviceClipBounds(_scratchIRectPtr); 779 return copyIRectFromWasm(_scratchIRect, outputRect); 780 }; 781 782 CanvasKit.Canvas.prototype.quickReject = function(rect) { 783 var rPtr = copyRectToWasm(rect); 784 return this._quickReject(rPtr); 785 }; 786 787 // getLocalToDevice returns a 4x4 matrix. 788 CanvasKit.Canvas.prototype.getLocalToDevice = function() { 789 // _getLocalToDevice will copy the values into the pointer. 790 this._getLocalToDevice(_scratch4x4MatrixPtr); 791 return copy4x4MatrixFromWasm(_scratch4x4MatrixPtr); 792 }; 793 794 // getTotalMatrix returns the current matrix as a 3x3 matrix. 795 CanvasKit.Canvas.prototype.getTotalMatrix = function() { 796 // _getTotalMatrix will copy the values into the pointer. 797 this._getTotalMatrix(_scratch3x3MatrixPtr); 798 // read them out into an array. TODO(kjlubick): If we change Matrix to be 799 // typedArrays, then we should return a typed array here too. 800 var rv = new Array(9); 801 for (var i = 0; i < 9; i++) { 802 rv[i] = CanvasKit.HEAPF32[_scratch3x3MatrixPtr/4 + i]; // divide by 4 to "cast" to float. 803 } 804 return rv; 805 }; 806 807 CanvasKit.Canvas.prototype.makeSurface = function(imageInfo) { 808 var s = this._makeSurface(imageInfo); 809 s._context = this._context; 810 return s; 811 }; 812 813 CanvasKit.Canvas.prototype.readPixels = function(srcX, srcY, imageInfo, destMallocObj, 814 bytesPerRow) { 815 CanvasKit.setCurrentContext(this._context); 816 return readPixels(this, srcX, srcY, imageInfo, destMallocObj, bytesPerRow); 817 }; 818 819 CanvasKit.Canvas.prototype.saveLayer = function (paint, boundsRect, backdrop, flags, backdropTileMode) { 820 // bPtr will be 0 (nullptr) if boundsRect is undefined/null. 821 var bPtr = copyRectToWasm(boundsRect); 822 // These or clauses help emscripten, which does not deal with undefined well. 823 return this._saveLayer(paint || null, bPtr, backdrop || null, flags || 0, backdropTileMode || CanvasKit.TileMode.Clamp); 824 }; 825 826 // pixels should be a Uint8Array or a plain JS array. 827 CanvasKit.Canvas.prototype.writePixels = function(pixels, srcWidth, srcHeight, 828 destX, destY, alphaType, colorType, colorSpace) { 829 if (pixels.byteLength % (srcWidth * srcHeight)) { 830 throw 'pixels length must be a multiple of the srcWidth * srcHeight'; 831 } 832 CanvasKit.setCurrentContext(this._context); 833 var bytesPerPixel = pixels.byteLength / (srcWidth * srcHeight); 834 // supply defaults (which are compatible with HTMLCanvas's putImageData) 835 alphaType = alphaType || CanvasKit.AlphaType.Unpremul; 836 colorType = colorType || CanvasKit.ColorType.RGBA_8888; 837 colorSpace = colorSpace || CanvasKit.ColorSpace.SRGB; 838 var srcRowBytes = bytesPerPixel * srcWidth; 839 840 var pptr = copy1dArray(pixels, 'HEAPU8'); 841 var ok = this._writePixels({ 842 'width': srcWidth, 843 'height': srcHeight, 844 'colorType': colorType, 845 'alphaType': alphaType, 846 'colorSpace': colorSpace, 847 }, pptr, srcRowBytes, destX, destY); 848 849 freeArraysThatAreNotMallocedByUsers(pptr, pixels); 850 return ok; 851 }; 852 853 CanvasKit.ColorFilter.MakeBlend = function(color4f, mode, colorSpace) { 854 var cPtr = copyColorToWasm(color4f); 855 colorSpace = colorSpace || CanvasKit.ColorSpace.SRGB; 856 return CanvasKit.ColorFilter._MakeBlend(cPtr, mode, colorSpace); 857 }; 858 859 // colorMatrix is an ColorMatrix (e.g. Float32Array of length 20) 860 CanvasKit.ColorFilter.MakeMatrix = function(colorMatrix) { 861 if (!colorMatrix || colorMatrix.length !== 20) { 862 throw 'invalid color matrix'; 863 } 864 var fptr = copy1dArray(colorMatrix, 'HEAPF32'); 865 // We know skia memcopies the floats, so we can free our memory after the call returns. 866 var m = CanvasKit.ColorFilter._makeMatrix(fptr); 867 freeArraysThatAreNotMallocedByUsers(fptr, colorMatrix); 868 return m; 869 }; 870 871 CanvasKit.ContourMeasure.prototype.getPosTan = function(distance, optionalOutput) { 872 this._getPosTan(distance, _scratchFourFloatsAPtr); 873 var ta = _scratchFourFloatsA['toTypedArray'](); 874 if (optionalOutput) { 875 optionalOutput.set(ta); 876 return optionalOutput; 877 } 878 return ta.slice(); 879 }; 880 881 CanvasKit.ImageFilter.prototype.getOutputBounds = function (drawBounds, ctm, optionalOutputArray) { 882 var bPtr = copyRectToWasm(drawBounds, _scratchFourFloatsAPtr); 883 var mPtr = copy3x3MatrixToWasm(ctm); 884 this._getOutputBounds(bPtr, mPtr, _scratchIRectPtr); 885 var ta = _scratchIRect['toTypedArray'](); 886 if (optionalOutputArray) { 887 optionalOutputArray.set(ta); 888 return optionalOutputArray; 889 } 890 return ta.slice(); 891 }; 892 893 CanvasKit.ImageFilter.MakeDropShadow = function(dx, dy, sx, sy, color, input) { 894 var cPtr = copyColorToWasm(color, _scratchColorPtr); 895 return CanvasKit.ImageFilter._MakeDropShadow(dx, dy, sx, sy, cPtr, input); 896 }; 897 898 CanvasKit.ImageFilter.MakeDropShadowOnly = function(dx, dy, sx, sy, color, input) { 899 var cPtr = copyColorToWasm(color, _scratchColorPtr); 900 return CanvasKit.ImageFilter._MakeDropShadowOnly(dx, dy, sx, sy, cPtr, input); 901 }; 902 903 CanvasKit.ImageFilter.MakeImage = function(img, sampling, srcRect, dstRect) { 904 var srcPtr = copyRectToWasm(srcRect, _scratchFourFloatsAPtr); 905 var dstPtr = copyRectToWasm(dstRect, _scratchFourFloatsBPtr); 906 907 if ('B' in sampling && 'C' in sampling) { 908 return CanvasKit.ImageFilter._MakeImageCubic(img, sampling['B'], sampling['C'], srcPtr, dstPtr); 909 } else { 910 const filter = sampling['filter']; // 'filter' is a required field 911 let mipmap = CanvasKit.MipmapMode.None; 912 if ('mipmap' in sampling) { // 'mipmap' is optional 913 mipmap = sampling['mipmap']; 914 } 915 return CanvasKit.ImageFilter._MakeImageOptions(img, filter, mipmap, srcPtr, dstPtr); 916 } 917 }; 918 919 CanvasKit.ImageFilter.MakeMatrixTransform = function(matrix, sampling, input) { 920 var matrPtr = copy3x3MatrixToWasm(matrix); 921 922 if ('B' in sampling && 'C' in sampling) { 923 return CanvasKit.ImageFilter._MakeMatrixTransformCubic(matrPtr, 924 sampling['B'], sampling['C'], 925 input); 926 } else { 927 const filter = sampling['filter']; // 'filter' is a required field 928 let mipmap = CanvasKit.MipmapMode.None; 929 if ('mipmap' in sampling) { // 'mipmap' is optional 930 mipmap = sampling['mipmap']; 931 } 932 return CanvasKit.ImageFilter._MakeMatrixTransformOptions(matrPtr, 933 filter, mipmap, 934 input); 935 } 936 }; 937 938 CanvasKit.Paint.prototype.getColor = function() { 939 this._getColor(_scratchColorPtr); 940 return copyColorFromWasm(_scratchColorPtr); 941 }; 942 943 CanvasKit.Paint.prototype.setColor = function(color4f, colorSpace) { 944 colorSpace = colorSpace || null; // null will be replaced with sRGB in the C++ method. 945 // emscripten wouldn't bind undefined to the sk_sp<ColorSpace> expected here. 946 var cPtr = copyColorToWasm(color4f); 947 this._setColor(cPtr, colorSpace); 948 }; 949 950 // The color components here are expected to be floating point values (nominally between 951 // 0.0 and 1.0, but with wider color gamuts, the values could exceed this range). To convert 952 // between standard 8 bit colors and floats, just divide by 255 before passing them in. 953 CanvasKit.Paint.prototype.setColorComponents = function(r, g, b, a, colorSpace) { 954 colorSpace = colorSpace || null; // null will be replaced with sRGB in the C++ method. 955 // emscripten wouldn't bind undefined to the sk_sp<ColorSpace> expected here. 956 var cPtr = copyColorComponentsToWasm(r, g, b, a); 957 this._setColor(cPtr, colorSpace); 958 }; 959 960 CanvasKit.Path.prototype.getPoint = function(idx, optionalOutput) { 961 // This will copy 2 floats into a space for 4 floats 962 this._getPoint(idx, _scratchFourFloatsAPtr); 963 var ta = _scratchFourFloatsA['toTypedArray'](); 964 if (optionalOutput) { 965 // We cannot call optionalOutput.set() because it is an error to call .set() with 966 // a source bigger than the destination. 967 optionalOutput[0] = ta[0]; 968 optionalOutput[1] = ta[1]; 969 return optionalOutput; 970 } 971 // Be sure to return a copy of just the first 2 values. 972 return ta.slice(0, 2); 973 }; 974 975 CanvasKit.Picture.prototype.makeShader = function(tmx, tmy, mode, matr, rect) { 976 var mPtr = copy3x3MatrixToWasm(matr); 977 var rPtr = copyRectToWasm(rect); 978 return this._makeShader(tmx, tmy, mode, mPtr, rPtr); 979 }; 980 981 // Clients can pass in a Float32Array with length 4 to this and the results 982 // will be copied into that array. Otherwise, a new TypedArray will be allocated 983 // and returned. 984 CanvasKit.Picture.prototype.cullRect = function (optionalOutputArray) { 985 this._cullRect(_scratchFourFloatsAPtr); 986 var ta = _scratchFourFloatsA['toTypedArray'](); 987 if (optionalOutputArray) { 988 optionalOutputArray.set(ta); 989 return optionalOutputArray; 990 } 991 return ta.slice(); 992 }; 993 994 // `bounds` is a required argument and is the initial cullRect for the picture. 995 // `computeBounds` is an optional boolean argument (default false) which, if 996 // true, will cause the recorded picture to compute a more accurate cullRect 997 // when it is created. 998 CanvasKit.PictureRecorder.prototype.beginRecording = function (bounds, computeBounds) { 999 var bPtr = copyRectToWasm(bounds); 1000 return this._beginRecording(bPtr, !!computeBounds); 1001 }; 1002 1003 CanvasKit.Surface.prototype.getCanvas = function() { 1004 var c = this._getCanvas(); 1005 c._context = this._context; 1006 return c; 1007 }; 1008 1009 CanvasKit.Surface.prototype.makeImageSnapshot = function(optionalBoundsRect) { 1010 CanvasKit.setCurrentContext(this._context); 1011 var bPtr = copyIRectToWasm(optionalBoundsRect); 1012 return this._makeImageSnapshot(bPtr); 1013 }; 1014 1015 CanvasKit.Surface.prototype.makeSurface = function(imageInfo) { 1016 CanvasKit.setCurrentContext(this._context); 1017 var s = this._makeSurface(imageInfo); 1018 s._context = this._context; 1019 return s; 1020 }; 1021 1022 CanvasKit.Surface.prototype._requestAnimationFrameInternal = function(callback, dirtyRect) { 1023 if (!this._cached_canvas) { 1024 this._cached_canvas = this.getCanvas(); 1025 } 1026 return requestAnimationFrame(function() { 1027 CanvasKit.setCurrentContext(this._context); 1028 1029 callback(this._cached_canvas); 1030 1031 // We do not dispose() of the Surface here, as the client will typically 1032 // call requestAnimationFrame again from within the supplied callback. 1033 // For drawing a single frame, prefer drawOnce(). 1034 this.flush(dirtyRect); 1035 }.bind(this)); 1036 }; 1037 if (!CanvasKit.Surface.prototype.requestAnimationFrame) { 1038 CanvasKit.Surface.prototype.requestAnimationFrame = 1039 CanvasKit.Surface.prototype._requestAnimationFrameInternal; 1040 } 1041 1042 // drawOnce will dispose of the surface after drawing the frame using the provided 1043 // callback. 1044 CanvasKit.Surface.prototype._drawOnceInternal = function(callback, dirtyRect) { 1045 if (!this._cached_canvas) { 1046 this._cached_canvas = this.getCanvas(); 1047 } 1048 requestAnimationFrame(function() { 1049 CanvasKit.setCurrentContext(this._context); 1050 callback(this._cached_canvas); 1051 1052 this.flush(dirtyRect); 1053 this.dispose(); 1054 }.bind(this)); 1055 }; 1056 if (!CanvasKit.Surface.prototype.drawOnce) { 1057 CanvasKit.Surface.prototype.drawOnce = CanvasKit.Surface.prototype._drawOnceInternal; 1058 } 1059 1060 CanvasKit.PathEffect.MakeDash = function(intervals, phase) { 1061 if (!phase) { 1062 phase = 0; 1063 } 1064 if (!intervals.length || intervals.length % 2 === 1) { 1065 throw 'Intervals array must have even length'; 1066 } 1067 var ptr = copy1dArray(intervals, 'HEAPF32'); 1068 var dpe = CanvasKit.PathEffect._MakeDash(ptr, intervals.length, phase); 1069 freeArraysThatAreNotMallocedByUsers(ptr, intervals); 1070 return dpe; 1071 }; 1072 1073 CanvasKit.PathEffect.MakeLine2D = function(width, matrix) { 1074 var matrixPtr = copy3x3MatrixToWasm(matrix); 1075 return CanvasKit.PathEffect._MakeLine2D(width, matrixPtr); 1076 }; 1077 1078 CanvasKit.PathEffect.MakePath2D = function(matrix, path) { 1079 var matrixPtr = copy3x3MatrixToWasm(matrix); 1080 return CanvasKit.PathEffect._MakePath2D(matrixPtr, path); 1081 }; 1082 1083 CanvasKit.Shader.MakeColor = function(color4f, colorSpace) { 1084 colorSpace = colorSpace || null; 1085 var cPtr = copyColorToWasm(color4f); 1086 return CanvasKit.Shader._MakeColor(cPtr, colorSpace); 1087 }; 1088 1089 // TODO(kjlubick) remove deprecated names. 1090 CanvasKit.Shader.Blend = CanvasKit.Shader.MakeBlend; 1091 CanvasKit.Shader.Color = CanvasKit.Shader.MakeColor; 1092 1093 CanvasKit.Shader.MakeLinearGradient = function(start, end, colors, pos, mode, localMatrix, flags, colorSpace) { 1094 colorSpace = colorSpace || null; 1095 var cPtrInfo = copyFlexibleColorArray(colors); 1096 var posPtr = copy1dArray(pos, 'HEAPF32'); 1097 flags = flags || 0; 1098 var localMatrixPtr = copy3x3MatrixToWasm(localMatrix); 1099 1100 // Copy start and end to _scratchFourFloatsAPtr. 1101 var startEndPts = _scratchFourFloatsA['toTypedArray'](); 1102 startEndPts.set(start); 1103 startEndPts.set(end, 2); 1104 1105 var lgs = CanvasKit.Shader._MakeLinearGradient(_scratchFourFloatsAPtr, cPtrInfo.colorPtr, cPtrInfo.colorType, posPtr, 1106 cPtrInfo.count, mode, flags, localMatrixPtr, colorSpace); 1107 1108 freeArraysThatAreNotMallocedByUsers(cPtrInfo.colorPtr, colors); 1109 pos && freeArraysThatAreNotMallocedByUsers(posPtr, pos); 1110 return lgs; 1111 }; 1112 1113 CanvasKit.Shader.MakeRadialGradient = function(center, radius, colors, pos, mode, localMatrix, flags, colorSpace) { 1114 colorSpace = colorSpace || null; 1115 var cPtrInfo = copyFlexibleColorArray(colors); 1116 var posPtr = copy1dArray(pos, 'HEAPF32'); 1117 flags = flags || 0; 1118 var localMatrixPtr = copy3x3MatrixToWasm(localMatrix); 1119 1120 var rgs = CanvasKit.Shader._MakeRadialGradient(center[0], center[1], radius, cPtrInfo.colorPtr, 1121 cPtrInfo.colorType, posPtr, cPtrInfo.count, mode, 1122 flags, localMatrixPtr, colorSpace); 1123 1124 freeArraysThatAreNotMallocedByUsers(cPtrInfo.colorPtr, colors); 1125 pos && freeArraysThatAreNotMallocedByUsers(posPtr, pos); 1126 return rgs; 1127 }; 1128 1129 CanvasKit.Shader.MakeSweepGradient = function(cx, cy, colors, pos, mode, localMatrix, flags, startAngle, endAngle, colorSpace) { 1130 colorSpace = colorSpace || null; 1131 var cPtrInfo = copyFlexibleColorArray(colors); 1132 var posPtr = copy1dArray(pos, 'HEAPF32'); 1133 flags = flags || 0; 1134 startAngle = startAngle || 0; 1135 endAngle = endAngle || 360; 1136 var localMatrixPtr = copy3x3MatrixToWasm(localMatrix); 1137 1138 var sgs = CanvasKit.Shader._MakeSweepGradient(cx, cy, cPtrInfo.colorPtr, cPtrInfo.colorType, posPtr, 1139 cPtrInfo.count, mode, 1140 startAngle, endAngle, flags, 1141 localMatrixPtr, colorSpace); 1142 1143 freeArraysThatAreNotMallocedByUsers(cPtrInfo.colorPtr, colors); 1144 pos && freeArraysThatAreNotMallocedByUsers(posPtr, pos); 1145 return sgs; 1146 }; 1147 1148 CanvasKit.Shader.MakeTwoPointConicalGradient = function(start, startRadius, end, endRadius, 1149 colors, pos, mode, localMatrix, flags, colorSpace) { 1150 colorSpace = colorSpace || null; 1151 var cPtrInfo = copyFlexibleColorArray(colors); 1152 var posPtr = copy1dArray(pos, 'HEAPF32'); 1153 flags = flags || 0; 1154 var localMatrixPtr = copy3x3MatrixToWasm(localMatrix); 1155 1156 // Copy start and end to _scratchFourFloatsAPtr. 1157 var startEndPts = _scratchFourFloatsA['toTypedArray'](); 1158 startEndPts.set(start); 1159 startEndPts.set(end, 2); 1160 1161 var rgs = CanvasKit.Shader._MakeTwoPointConicalGradient(_scratchFourFloatsAPtr, 1162 startRadius, endRadius, cPtrInfo.colorPtr, cPtrInfo.colorType, 1163 posPtr, cPtrInfo.count, mode, flags, localMatrixPtr, colorSpace); 1164 1165 freeArraysThatAreNotMallocedByUsers(cPtrInfo.colorPtr, colors); 1166 pos && freeArraysThatAreNotMallocedByUsers(posPtr, pos); 1167 return rgs; 1168 }; 1169 1170 // Clients can pass in a Float32Array with length 4 to this and the results 1171 // will be copied into that array. Otherwise, a new TypedArray will be allocated 1172 // and returned. 1173 CanvasKit.Vertices.prototype.bounds = function(optionalOutputArray) { 1174 this._bounds(_scratchFourFloatsAPtr); 1175 var ta = _scratchFourFloatsA['toTypedArray'](); 1176 if (optionalOutputArray) { 1177 optionalOutputArray.set(ta); 1178 return optionalOutputArray; 1179 } 1180 return ta.slice(); 1181 }; 1182 1183 // Run through the JS files that are added at compile time. 1184 if (CanvasKit._extraInitializations) { 1185 CanvasKit._extraInitializations.forEach(function(init) { 1186 init(); 1187 }); 1188 } 1189}; // end CanvasKit.onRuntimeInitialized, that is, anything changing prototypes or dynamic. 1190 1191// Accepts an object holding two canvaskit colors. 1192// { 1193// ambient: [r, g, b, a], 1194// spot: [r, g, b, a], 1195// } 1196// Returns the same format. Note, if malloced colors are passed in, the memory 1197// housing the passed in colors passed in will be overwritten with the computed 1198// tonal colors. 1199CanvasKit.computeTonalColors = function(tonalColors) { 1200 // copy the colors into WASM 1201 var cPtrAmbi = copyColorToWasmNoScratch(tonalColors['ambient']); 1202 var cPtrSpot = copyColorToWasmNoScratch(tonalColors['spot']); 1203 // The output of this function will be the same pointers we passed in. 1204 this._computeTonalColors(cPtrAmbi, cPtrSpot); 1205 // Read the results out. 1206 var result = { 1207 'ambient': copyColorFromWasm(cPtrAmbi), 1208 'spot': copyColorFromWasm(cPtrSpot), 1209 }; 1210 // If the user passed us malloced colors in here, we don't want to clean them up. 1211 freeArraysThatAreNotMallocedByUsers(cPtrAmbi, tonalColors['ambient']); 1212 freeArraysThatAreNotMallocedByUsers(cPtrSpot, tonalColors['spot']); 1213 return result; 1214}; 1215 1216CanvasKit.LTRBRect = function(l, t, r, b) { 1217 return Float32Array.of(l, t, r, b); 1218}; 1219 1220CanvasKit.XYWHRect = function(x, y, w, h) { 1221 return Float32Array.of(x, y, x+w, y+h); 1222}; 1223 1224CanvasKit.LTRBiRect = function(l, t, r, b) { 1225 return Int32Array.of(l, t, r, b); 1226}; 1227 1228CanvasKit.XYWHiRect = function(x, y, w, h) { 1229 return Int32Array.of(x, y, x+w, y+h); 1230}; 1231 1232// RRectXY returns a TypedArray representing an RRect with the given rect and a radiusX and 1233// radiusY for all 4 corners. 1234CanvasKit.RRectXY = function(rect, rx, ry) { 1235 return Float32Array.of( 1236 rect[0], rect[1], rect[2], rect[3], 1237 rx, ry, 1238 rx, ry, 1239 rx, ry, 1240 rx, ry, 1241 ); 1242}; 1243 1244// data is a TypedArray or ArrayBuffer e.g. from fetch().then(resp.arrayBuffer()) 1245CanvasKit.MakeAnimatedImageFromEncoded = function(data) { 1246 data = new Uint8Array(data); 1247 1248 var iptr = CanvasKit._malloc(data.byteLength); 1249 CanvasKit.HEAPU8.set(data, iptr); 1250 var img = CanvasKit._decodeAnimatedImage(iptr, data.byteLength); 1251 if (!img) { 1252 Debug('Could not decode animated image'); 1253 return null; 1254 } 1255 return img; 1256}; 1257 1258// data is a TypedArray or ArrayBuffer e.g. from fetch().then(resp.arrayBuffer()) 1259CanvasKit.MakeImageFromEncoded = function(data) { 1260 data = new Uint8Array(data); 1261 1262 var iptr = CanvasKit._malloc(data.byteLength); 1263 CanvasKit.HEAPU8.set(data, iptr); 1264 var img = CanvasKit._decodeImage(iptr, data.byteLength); 1265 if (!img) { 1266 Debug('Could not decode image'); 1267 return null; 1268 } 1269 return img; 1270}; 1271 1272// A variable to hold a canvasElement which can be reused once created the first time. 1273var memoizedCanvas2dElement = null; 1274 1275// Alternative to CanvasKit.MakeImageFromEncoded. Allows for CanvasKit users to take advantage of 1276// browser APIs to decode images instead of using codecs included in the CanvasKit wasm binary. 1277// Expects that the canvasImageSource has already loaded/decoded. 1278// CanvasImageSource reference: https://developer.mozilla.org/en-US/docs/Web/API/CanvasImageSource 1279CanvasKit.MakeImageFromCanvasImageSource = function(canvasImageSource) { 1280 var width = canvasImageSource.width; 1281 var height = canvasImageSource.height; 1282 1283 if (!memoizedCanvas2dElement) { 1284 memoizedCanvas2dElement = document.createElement('canvas'); 1285 } 1286 memoizedCanvas2dElement.width = width; 1287 memoizedCanvas2dElement.height = height; 1288 1289 var ctx2d = memoizedCanvas2dElement.getContext('2d', {willReadFrequently: true}); 1290 ctx2d.drawImage(canvasImageSource, 0, 0); 1291 1292 var imageData = ctx2d.getImageData(0, 0, width, height); 1293 1294 return CanvasKit.MakeImage({ 1295 'width': width, 1296 'height': height, 1297 'alphaType': CanvasKit.AlphaType.Unpremul, 1298 'colorType': CanvasKit.ColorType.RGBA_8888, 1299 'colorSpace': CanvasKit.ColorSpace.SRGB 1300 }, imageData.data, 4 * width); 1301}; 1302 1303// pixels may be an array but Uint8Array or Uint8ClampedArray is recommended, 1304// with the bytes representing the pixel values. 1305// (e.g. each set of 4 bytes could represent RGBA values for a single pixel). 1306CanvasKit.MakeImage = function(info, pixels, bytesPerRow) { 1307 var pptr = CanvasKit._malloc(pixels.length); 1308 CanvasKit.HEAPU8.set(pixels, pptr); // We always want to copy the bytes into the WASM heap. 1309 // No need to _free pptr, Image takes it with SkData::MakeFromMalloc 1310 return CanvasKit._MakeImage(info, pptr, pixels.length, bytesPerRow); 1311}; 1312 1313// Colors may be a Uint32Array of int colors, a Flat Float32Array of float colors 1314// or a 2d Array of Float32Array(4) (deprecated) 1315// the underlying Skia function accepts only int colors so it is recommended 1316// to pass an array of int colors to avoid an extra conversion. 1317CanvasKit.MakeVertices = function(mode, positions, textureCoordinates, colors, 1318 indices, isVolatile) { 1319 // Default isVolatile to true if not set 1320 isVolatile = isVolatile === undefined ? true : isVolatile; 1321 var idxCount = (indices && indices.length) || 0; 1322 1323 var flags = 0; 1324 // These flags are from SkVertices.h and should be kept in sync with those. 1325 if (textureCoordinates && textureCoordinates.length) { 1326 flags |= (1 << 0); 1327 } 1328 if (colors && colors.length) { 1329 flags |= (1 << 1); 1330 } 1331 if (!isVolatile) { 1332 flags |= (1 << 2); 1333 } 1334 1335 var builder = new CanvasKit._VerticesBuilder(mode, positions.length / 2, idxCount, flags); 1336 1337 copy1dArray(positions, 'HEAPF32', builder.positions()); 1338 if (builder.texCoords()) { 1339 copy1dArray(textureCoordinates, 'HEAPF32', builder.texCoords()); 1340 } 1341 if (builder.colors()) { 1342 copy1dArray(assureIntColors(colors), 'HEAPU32', builder.colors()); 1343 } 1344 if (builder.indices()) { 1345 copy1dArray(indices, 'HEAPU16', builder.indices()); 1346 } 1347 1348 // Create the vertices, which owns the memory that the builder had allocated. 1349 return builder.detach(); 1350}; 1351