blob: 05321591e54e2efd9fd63b8c494a091a009e286a [file] [log] [blame]
Kevin Lubick217056c2018-09-20 17:39:31 -04001// 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.
Kevin Lubick1a05fce2018-11-20 12:51:16 -05004
Kevin Lubickf5ea37f2019-02-28 10:06:18 -05005// CanvasKit.onRuntimeInitialized is called after the WASM library has loaded.
Kevin Lubick54c1b3d2020-10-07 16:09:22 -04006// Anything that modifies an exposed class (e.g. Path) should be set
Kevin Lubickf5ea37f2019-02-28 10:06:18 -05007// 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.
Kevin Lubick1a05fce2018-11-20 12:51:16 -050010
Kevin Lubick93f1a382020-06-02 16:15:23 -040011 _scratchColor = CanvasKit.Malloc(Float32Array, 4); // 4 color scalars.
Kevin Lubickb42660f2020-06-03 09:58:27 -040012 _scratchColorPtr = _scratchColor['byteOffset'];
Kevin Lubick6aa38692020-06-01 11:25:47 -040013
14 _scratch4x4Matrix = CanvasKit.Malloc(Float32Array, 16); // 16 matrix scalars.
Kevin Lubickb42660f2020-06-03 09:58:27 -040015 _scratch4x4MatrixPtr = _scratch4x4Matrix['byteOffset'];
Kevin Lubick6aa38692020-06-01 11:25:47 -040016
17 _scratch3x3Matrix = CanvasKit.Malloc(Float32Array, 9); // 9 matrix scalars.
Kevin Lubickb42660f2020-06-03 09:58:27 -040018 _scratch3x3MatrixPtr = _scratch3x3Matrix['byteOffset'];
Kevin Lubickbe728012020-09-03 11:57:12 +000019
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
Kevin Lubicked962642021-02-02 08:18:11 -050026 _scratchFourFloatsA = CanvasKit.Malloc(Float32Array, 4);
27 _scratchFourFloatsAPtr = _scratchFourFloatsA['byteOffset'];
Kevin Lubickf8823b52020-09-03 10:02:10 -040028
Kevin Lubicked962642021-02-02 08:18:11 -050029 _scratchFourFloatsB = CanvasKit.Malloc(Float32Array, 4);
30 _scratchFourFloatsBPtr = _scratchFourFloatsB['byteOffset'];
Kevin Lubickf8823b52020-09-03 10:02:10 -040031
Kevin Lubickf6040ef2021-02-02 08:26:48 -050032 _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
Kevin Lubickf8823b52020-09-03 10:02:10 -040038 _scratchIRect = CanvasKit.Malloc(Int32Array, 4);
39 _scratchIRectPtr = _scratchIRect['byteOffset'];
40
Nathaniel Nifongb1ebbb12020-05-26 13:10:20 -040041 // Create single copies of all three supported color spaces
Kevin Lubick54c1b3d2020-10-07 16:09:22 -040042 // 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();
Nathaniel Nifongb1ebbb12020-05-26 13:10:20 -040046
Kevin Lubick995f2e62021-04-30 11:12:01 -040047 // Use quotes to tell closure compiler not to minify the names
48 CanvasKit['GlyphRunFlags'] = {
49 'IsWhiteSpace': CanvasKit['_GlyphRunFlags_isWhiteSpace'],
50 };
51
Kevin Lubick54c1b3d2020-10-07 16:09:22 -040052 CanvasKit.Path.MakeFromCmds = function(cmds) {
Kevin Lubickd9b9e5e2020-06-23 16:58:10 -040053 var ptrLen = loadCmdsTypedArray(cmds);
Kevin Lubick54c1b3d2020-10-07 16:09:22 -040054 var path = CanvasKit.Path._MakeFromCmds(ptrLen[0], ptrLen[1]);
Kevin Lubickd9b9e5e2020-06-23 16:58:10 -040055 CanvasKit._free(ptrLen[0]);
56 return path;
57 };
58
Kevin Lubickd9b9e5e2020-06-23 16:58:10 -040059 // The weights array is optional (only used for conics).
Kevin Lubick54c1b3d2020-10-07 16:09:22 -040060 CanvasKit.Path.MakeFromVerbsPointsWeights = function(verbs, pts, weights) {
Kevin Lubickbe728012020-09-03 11:57:12 +000061 var verbsPtr = copy1dArray(verbs, 'HEAPU8');
62 var pointsPtr = copy1dArray(pts, 'HEAPF32');
63 var weightsPtr = copy1dArray(weights, 'HEAPF32');
Kevin Lubickd9b9e5e2020-06-23 16:58:10 -040064 var numWeights = (weights && weights.length) || 0;
Kevin Lubick54c1b3d2020-10-07 16:09:22 -040065 var path = CanvasKit.Path._MakeFromVerbsPointsWeights(
Kevin Lubickd9b9e5e2020-06-23 16:58:10 -040066 verbsPtr, verbs.length, pointsPtr, pts.length, weightsPtr, numWeights);
67 freeArraysThatAreNotMallocedByUsers(verbsPtr, verbs);
68 freeArraysThatAreNotMallocedByUsers(pointsPtr, pts);
69 freeArraysThatAreNotMallocedByUsers(weightsPtr, weights);
70 return path;
71 };
Kevin Lubickd3729342019-09-12 11:11:25 -040072
Kevin Lubick54c1b3d2020-10-07 16:09:22 -040073 CanvasKit.Path.prototype.addArc = function(oval, startAngle, sweepAngle) {
Kevin Lubickf5ea37f2019-02-28 10:06:18 -050074 // see arc() for the HTMLCanvas version
75 // note input angles are degrees.
Kevin Lubickf8823b52020-09-03 10:02:10 -040076 var oPtr = copyRectToWasm(oval);
77 this._addArc(oPtr, startAngle, sweepAngle);
Kevin Lubickf5ea37f2019-02-28 10:06:18 -050078 return this;
79 };
Kevin Lubick217056c2018-09-20 17:39:31 -040080
Kevin Lubick54c1b3d2020-10-07 16:09:22 -040081 CanvasKit.Path.prototype.addOval = function(oval, isCCW, startIndex) {
Kevin Lubicke384df42019-08-26 15:48:09 -040082 if (startIndex === undefined) {
83 startIndex = 1;
84 }
Kevin Lubickf8823b52020-09-03 10:02:10 -040085 var oPtr = copyRectToWasm(oval);
86 this._addOval(oPtr, !!isCCW, startIndex);
Kevin Lubicke384df42019-08-26 15:48:09 -040087 return this;
88 };
89
Kevin Lubicka2535af2020-10-02 08:01:57 -040090 // TODO(kjlubick) clean up this API - split it apart if necessary
Kevin Lubick54c1b3d2020-10-07 16:09:22 -040091 CanvasKit.Path.prototype.addPath = function() {
Kevin Lubickf5ea37f2019-02-28 10:06:18 -050092 // Takes 1, 2, 7, or 10 required args, where the first arg is always the path.
93 // The last arg is optional and chooses between add or extend mode.
94 // The options for the remaining args are:
95 // - an array of 6 or 9 parameters (perspective is optional)
96 // - the 9 parameters of a full matrix or
97 // the 6 non-perspective params of a matrix.
98 var args = Array.prototype.slice.call(arguments);
99 var path = args[0];
100 var extend = false;
Kevin Lubickbe728012020-09-03 11:57:12 +0000101 if (typeof args[args.length-1] === 'boolean') {
Kevin Lubickf5ea37f2019-02-28 10:06:18 -0500102 extend = args.pop();
103 }
104 if (args.length === 1) {
105 // Add path, unchanged. Use identity matrix
106 this._addPath(path, 1, 0, 0,
107 0, 1, 0,
108 0, 0, 1,
109 extend);
110 } else if (args.length === 2) {
111 // User provided the 9 params of a full matrix as an array.
112 var a = args[1];
113 this._addPath(path, a[0], a[1], a[2],
114 a[3], a[4], a[5],
115 a[6] || 0, a[7] || 0, a[8] || 1,
116 extend);
117 } else if (args.length === 7 || args.length === 10) {
118 // User provided the 9 params of a (full) matrix directly.
119 // (or just the 6 non perspective ones)
120 // These are in the same order as what Skia expects.
121 var a = args;
122 this._addPath(path, a[1], a[2], a[3],
123 a[4], a[5], a[6],
124 a[7] || 0, a[8] || 0, a[9] || 1,
125 extend);
126 } else {
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400127 Debug('addPath expected to take 1, 2, 7, or 10 required args. Got ' + args.length);
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400128 return null;
Kevin Lubickf5ea37f2019-02-28 10:06:18 -0500129 }
130 return this;
131 };
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400132
Kevin Lubicke7c1a732020-12-04 09:10:39 -0500133 // points is a 1d array of length 2n representing n points where the even indices
134 // will be treated as x coordinates and the odd indices will be treated as y coordinates.
135 // Like other APIs, this accepts a malloced type array or malloc obj.
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400136 CanvasKit.Path.prototype.addPoly = function(points, close) {
Kevin Lubicke7c1a732020-12-04 09:10:39 -0500137 var ptr = copy1dArray(points, 'HEAPF32');
138 this._addPoly(ptr, points.length / 2, close);
Kevin Lubickcf118922020-05-28 14:43:38 -0400139 freeArraysThatAreNotMallocedByUsers(ptr, points);
Kevin Lubick37ab53e2019-11-11 10:06:08 -0500140 return this;
141 };
142
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400143 CanvasKit.Path.prototype.addRect = function(rect, isCCW) {
Kevin Lubickf8823b52020-09-03 10:02:10 -0400144 var rPtr = copyRectToWasm(rect);
145 this._addRect(rPtr, !!isCCW);
Kevin Lubickf5ea37f2019-02-28 10:06:18 -0500146 return this;
147 };
Kevin Lubick217056c2018-09-20 17:39:31 -0400148
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400149 CanvasKit.Path.prototype.addRRect = function(rrect, isCCW) {
Kevin Lubickf8823b52020-09-03 10:02:10 -0400150 var rPtr = copyRRectToWasm(rrect);
151 this._addRRect(rPtr, !!isCCW);
Kevin Lubickf5ea37f2019-02-28 10:06:18 -0500152 return this;
153 };
154
Kevin Lubickd9b9e5e2020-06-23 16:58:10 -0400155 // The weights array is optional (only used for conics).
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400156 CanvasKit.Path.prototype.addVerbsPointsWeights = function(verbs, points, weights) {
Kevin Lubickbe728012020-09-03 11:57:12 +0000157 var verbsPtr = copy1dArray(verbs, 'HEAPU8');
158 var pointsPtr = copy1dArray(points, 'HEAPF32');
159 var weightsPtr = copy1dArray(weights, 'HEAPF32');
Kevin Lubickd9b9e5e2020-06-23 16:58:10 -0400160 var numWeights = (weights && weights.length) || 0;
161 this._addVerbsPointsWeights(verbsPtr, verbs.length, pointsPtr, points.length,
162 weightsPtr, numWeights);
163 freeArraysThatAreNotMallocedByUsers(verbsPtr, verbs);
164 freeArraysThatAreNotMallocedByUsers(pointsPtr, points);
165 freeArraysThatAreNotMallocedByUsers(weightsPtr, weights);
166 };
167
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400168 CanvasKit.Path.prototype.arc = function(x, y, radius, startAngle, endAngle, ccw) {
169 // emulates the HTMLCanvas behavior. See addArc() for the Path version.
Kevin Lubickf5ea37f2019-02-28 10:06:18 -0500170 // Note input angles are radians.
171 var bounds = CanvasKit.LTRBRect(x-radius, y-radius, x+radius, y+radius);
172 var sweep = radiansToDegrees(endAngle - startAngle) - (360 * !!ccw);
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400173 var temp = new CanvasKit.Path();
Kevin Lubickf5ea37f2019-02-28 10:06:18 -0500174 temp.addArc(bounds, radiansToDegrees(startAngle), sweep);
175 this.addPath(temp, true);
176 temp.delete();
177 return this;
178 };
179
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400180 // Appends arc to Path. Arc added is part of ellipse
Nathaniel Nifongd0c9d0c2020-07-15 16:46:17 -0400181 // bounded by oval, from startAngle through sweepAngle. Both startAngle and
182 // sweepAngle are measured in degrees, where zero degrees is aligned with the
183 // positive x-axis, and positive sweeps extends arc clockwise.
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400184 CanvasKit.Path.prototype.arcToOval = function(oval, startAngle, sweepAngle, forceMoveTo) {
Kevin Lubickf8823b52020-09-03 10:02:10 -0400185 var oPtr = copyRectToWasm(oval);
186 this._arcToOval(oPtr, startAngle, sweepAngle, forceMoveTo);
Nathaniel Nifongd0c9d0c2020-07-15 16:46:17 -0400187 return this;
188 };
189
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400190 // Appends arc to Path. Arc is implemented by one or more conics weighted to
Nathaniel Nifongd0c9d0c2020-07-15 16:46:17 -0400191 // describe part of oval with radii (rx, ry) rotated by xAxisRotate degrees. Arc
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400192 // curves from last point to (x, y), choosing one of four possible routes:
Nathaniel Nifongd0c9d0c2020-07-15 16:46:17 -0400193 // clockwise or counterclockwise, and smaller or larger.
194
195 // Arc sweep is always less than 360 degrees. arcTo() appends line to (x, y) if
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400196 // either radii are zero, or if last point equals (x, y). arcTo() scales radii
197 // (rx, ry) to fit last point and (x, y) if both are greater than zero but
Nathaniel Nifongd0c9d0c2020-07-15 16:46:17 -0400198 // too small.
199
200 // arcToRotated() appends up to four conic curves.
201 // arcToRotated() implements the functionality of SVG arc, although SVG sweep-flag value
202 // is opposite the integer value of sweep; SVG sweep-flag uses 1 for clockwise,
203 // while kCW_Direction cast to int is zero.
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400204 CanvasKit.Path.prototype.arcToRotated = function(rx, ry, xAxisRotate, useSmallArc, isCCW, x, y) {
Nathaniel Nifongd0c9d0c2020-07-15 16:46:17 -0400205 this._arcToRotated(rx, ry, xAxisRotate, !!useSmallArc, !!isCCW, x, y);
206 return this;
207 };
208
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400209 // Appends arc to Path, after appending line if needed. Arc is implemented by conic
Nathaniel Nifongd0c9d0c2020-07-15 16:46:17 -0400210 // weighted to describe part of circle. Arc is contained by tangent from
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400211 // last Path point to (x1, y1), and tangent from (x1, y1) to (x2, y2). Arc
Nathaniel Nifongd0c9d0c2020-07-15 16:46:17 -0400212 // is part of circle sized to radius, positioned so it touches both tangent lines.
213
214 // If last Path Point does not start Arc, arcTo appends connecting Line to Path.
215 // The length of Vector from (x1, y1) to (x2, y2) does not affect Arc.
216
217 // Arc sweep is always less than 180 degrees. If radius is zero, or if
218 // tangents are nearly parallel, arcTo appends Line from last Path Point to (x1, y1).
219
220 // arcToTangent appends at most one Line and one conic.
221 // arcToTangent implements the functionality of PostScript arct and HTML Canvas arcTo.
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400222 CanvasKit.Path.prototype.arcToTangent = function(x1, y1, x2, y2, radius) {
Nathaniel Nifongd0c9d0c2020-07-15 16:46:17 -0400223 this._arcToTangent(x1, y1, x2, y2, radius);
224 return this;
225 };
226
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400227 CanvasKit.Path.prototype.close = function() {
Kevin Lubickf5ea37f2019-02-28 10:06:18 -0500228 this._close();
229 return this;
230 };
231
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400232 CanvasKit.Path.prototype.conicTo = function(x1, y1, x2, y2, w) {
Kevin Lubickf5ea37f2019-02-28 10:06:18 -0500233 this._conicTo(x1, y1, x2, y2, w);
234 return this;
235 };
236
Kevin Lubick7d96c5c2020-10-01 10:55:16 -0400237 // Clients can pass in a Float32Array with length 4 to this and the results
238 // will be copied into that array. Otherwise, a new TypedArray will be allocated
239 // and returned.
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400240 CanvasKit.Path.prototype.computeTightBounds = function(optionalOutputArray) {
Kevin Lubicked962642021-02-02 08:18:11 -0500241 this._computeTightBounds(_scratchFourFloatsAPtr);
242 var ta = _scratchFourFloatsA['toTypedArray']();
Kevin Lubick7d96c5c2020-10-01 10:55:16 -0400243 if (optionalOutputArray) {
244 optionalOutputArray.set(ta);
245 return optionalOutputArray;
246 }
247 return ta.slice();
248 };
249
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400250 CanvasKit.Path.prototype.cubicTo = function(cp1x, cp1y, cp2x, cp2y, x, y) {
Kevin Lubickf5ea37f2019-02-28 10:06:18 -0500251 this._cubicTo(cp1x, cp1y, cp2x, cp2y, x, y);
252 return this;
253 };
254
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400255 CanvasKit.Path.prototype.dash = function(on, off, phase) {
Kevin Lubickf5ea37f2019-02-28 10:06:18 -0500256 if (this._dash(on, off, phase)) {
Kevin Lubick217056c2018-09-20 17:39:31 -0400257 return this;
Kevin Lubickf5ea37f2019-02-28 10:06:18 -0500258 }
259 return null;
260 };
Kevin Lubick217056c2018-09-20 17:39:31 -0400261
Kevin Lubickf8823b52020-09-03 10:02:10 -0400262 // Clients can pass in a Float32Array with length 4 to this and the results
263 // will be copied into that array. Otherwise, a new TypedArray will be allocated
264 // and returned.
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400265 CanvasKit.Path.prototype.getBounds = function(optionalOutputArray) {
Kevin Lubicked962642021-02-02 08:18:11 -0500266 this._getBounds(_scratchFourFloatsAPtr);
267 var ta = _scratchFourFloatsA['toTypedArray']();
Kevin Lubickf8823b52020-09-03 10:02:10 -0400268 if (optionalOutputArray) {
269 optionalOutputArray.set(ta);
270 return optionalOutputArray;
271 }
272 return ta.slice();
273 };
274
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400275 CanvasKit.Path.prototype.lineTo = function(x, y) {
Kevin Lubickf5ea37f2019-02-28 10:06:18 -0500276 this._lineTo(x, y);
277 return this;
278 };
Kevin Lubick217056c2018-09-20 17:39:31 -0400279
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400280 CanvasKit.Path.prototype.moveTo = function(x, y) {
Kevin Lubickf5ea37f2019-02-28 10:06:18 -0500281 this._moveTo(x, y);
282 return this;
283 };
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400284
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400285 CanvasKit.Path.prototype.offset = function(dx, dy) {
Kevin Lubicke384df42019-08-26 15:48:09 -0400286 this._transform(1, 0, dx,
287 0, 1, dy,
288 0, 0, 1);
289 return this;
290 };
291
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400292 CanvasKit.Path.prototype.quadTo = function(cpx, cpy, x, y) {
Kevin Lubickf5ea37f2019-02-28 10:06:18 -0500293 this._quadTo(cpx, cpy, x, y);
294 return this;
295 };
296
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400297 CanvasKit.Path.prototype.rArcTo = function(rx, ry, xAxisRotate, useSmallArc, isCCW, dx, dy) {
Kevin Lubick79b71342019-11-01 14:36:52 -0400298 this._rArcTo(rx, ry, xAxisRotate, useSmallArc, isCCW, dx, dy);
299 return this;
300 };
301
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400302 CanvasKit.Path.prototype.rConicTo = function(dx1, dy1, dx2, dy2, w) {
Kevin Lubick79b71342019-11-01 14:36:52 -0400303 this._rConicTo(dx1, dy1, dx2, dy2, w);
304 return this;
305 };
306
307 // These params are all relative
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400308 CanvasKit.Path.prototype.rCubicTo = function(cp1x, cp1y, cp2x, cp2y, x, y) {
Kevin Lubick79b71342019-11-01 14:36:52 -0400309 this._rCubicTo(cp1x, cp1y, cp2x, cp2y, x, y);
310 return this;
311 };
312
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400313 CanvasKit.Path.prototype.rLineTo = function(dx, dy) {
Kevin Lubick79b71342019-11-01 14:36:52 -0400314 this._rLineTo(dx, dy);
315 return this;
316 };
317
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400318 CanvasKit.Path.prototype.rMoveTo = function(dx, dy) {
Kevin Lubick79b71342019-11-01 14:36:52 -0400319 this._rMoveTo(dx, dy);
320 return this;
321 };
322
323 // These params are all relative
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400324 CanvasKit.Path.prototype.rQuadTo = function(cpx, cpy, x, y) {
Kevin Lubick79b71342019-11-01 14:36:52 -0400325 this._rQuadTo(cpx, cpy, x, y);
326 return this;
327 };
328
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400329 CanvasKit.Path.prototype.stroke = function(opts) {
Kevin Lubickf5ea37f2019-02-28 10:06:18 -0500330 // Fill out any missing values with the default values.
Kevin Lubickf5ea37f2019-02-28 10:06:18 -0500331 opts = opts || {};
Kevin Lubick6aa38692020-06-01 11:25:47 -0400332 opts['width'] = opts['width'] || 1;
333 opts['miter_limit'] = opts['miter_limit'] || 4;
334 opts['cap'] = opts['cap'] || CanvasKit.StrokeCap.Butt;
335 opts['join'] = opts['join'] || CanvasKit.StrokeJoin.Miter;
336 opts['precision'] = opts['precision'] || 1;
Kevin Lubickf5ea37f2019-02-28 10:06:18 -0500337 if (this._stroke(opts)) {
338 return this;
339 }
340 return null;
341 };
342
Kevin Lubicka2535af2020-10-02 08:01:57 -0400343 // TODO(kjlubick) Change this to take a 3x3 or 4x4 matrix (optionally malloc'd)
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400344 CanvasKit.Path.prototype.transform = function() {
Kevin Lubickf5ea37f2019-02-28 10:06:18 -0500345 // Takes 1 or 9 args
346 if (arguments.length === 1) {
347 // argument 1 should be a 6 or 9 element array.
348 var a = arguments[0];
349 this._transform(a[0], a[1], a[2],
350 a[3], a[4], a[5],
351 a[6] || 0, a[7] || 0, a[8] || 1);
352 } else if (arguments.length === 6 || arguments.length === 9) {
353 // these arguments are the 6 or 9 members of the matrix
354 var a = arguments;
355 this._transform(a[0], a[1], a[2],
356 a[3], a[4], a[5],
357 a[6] || 0, a[7] || 0, a[8] || 1);
358 } else {
359 throw 'transform expected to take 1 or 9 arguments. Got ' + arguments.length;
360 }
361 return this;
362 };
363 // isComplement is optional, defaults to false
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400364 CanvasKit.Path.prototype.trim = function(startT, stopT, isComplement) {
Kevin Lubickf5ea37f2019-02-28 10:06:18 -0500365 if (this._trim(startT, stopT, !!isComplement)) {
366 return this;
367 }
368 return null;
369 };
370
Kevin Lubick652d7902020-12-11 14:51:36 -0500371 // makeShaderCubic returns a shader for a given image, allowing it to be used on
372 // a paint as well as other purposes. This shader will be higher quality than
373 // other shader functions. See CubicResampler in SkSamplingOptions.h for more information
374 // on the cubicResampler params.
375 CanvasKit.Image.prototype.makeShaderCubic = function(xTileMode, yTileMode,
376 cubicResamplerB, cubicResamplerC,
377 localMatrix) {
Kevin Lubick6bffe392020-04-02 15:24:15 -0400378 var localMatrixPtr = copy3x3MatrixToWasm(localMatrix);
Kevin Lubick652d7902020-12-11 14:51:36 -0500379 return this._makeShaderCubic(xTileMode, yTileMode, cubicResamplerB,
380 cubicResamplerC, localMatrixPtr);
381 };
382
383 // makeShaderCubic returns a shader for a given image, allowing it to be used on
384 // a paint as well as other purposes. This shader will draw more quickly than
385 // other shader functions, but at a lower quality.
386 CanvasKit.Image.prototype.makeShaderOptions = function(xTileMode, yTileMode,
387 filterMode, mipmapMode,
388 localMatrix) {
389 var localMatrixPtr = copy3x3MatrixToWasm(localMatrix);
390 return this._makeShaderOptions(xTileMode, yTileMode, filterMode, mipmapMode, localMatrixPtr);
Kevin Lubick9fe83912020-11-03 17:08:34 -0500391 };
Kevin Lubicka064c282019-04-04 09:28:53 -0400392
Kevin Lubickb8123cc2020-11-06 13:05:37 -0500393 function readPixels(source, srcX, srcY, imageInfo, destMallocObj, bytesPerRow) {
394 if (!bytesPerRow) {
395 bytesPerRow = 4 * imageInfo['width'];
396 if (imageInfo['colorType'] === CanvasKit.ColorType.RGBA_F16) {
397 bytesPerRow *= 2;
398 }
399 else if (imageInfo['colorType'] === CanvasKit.ColorType.RGBA_F32) {
400 bytesPerRow *= 4;
401 }
Kevin Lubickd6b32ed2019-05-06 13:04:03 -0400402 }
Kevin Lubickb8123cc2020-11-06 13:05:37 -0500403 var pBytes = bytesPerRow * imageInfo.height;
Kevin Lubickc4ab0872020-11-03 17:13:09 -0500404 var pPtr;
405 if (destMallocObj) {
406 pPtr = destMallocObj['byteOffset'];
407 } else {
408 pPtr = CanvasKit._malloc(pBytes);
409 }
Kevin Lubickd6b32ed2019-05-06 13:04:03 -0400410
Kevin Lubickb8123cc2020-11-06 13:05:37 -0500411 if (!source._readPixels(imageInfo, pPtr, bytesPerRow, srcX, srcY)) {
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400412 Debug('Could not read pixels with the given inputs');
Kevin Lubickc4ab0872020-11-03 17:13:09 -0500413 if (!destMallocObj) {
414 CanvasKit._free(pPtr);
415 }
Kevin Lubickd6b32ed2019-05-06 13:04:03 -0400416 return null;
417 }
418
Kevin Lubickc4ab0872020-11-03 17:13:09 -0500419 // If the user provided us a buffer to copy into, we don't need to allocate a new TypedArray.
420 if (destMallocObj) {
421 return destMallocObj['toTypedArray'](); // Return the typed array wrapper w/o allocating.
422 }
423
Kevin Lubickd6b32ed2019-05-06 13:04:03 -0400424 // Put those pixels into a typed array of the right format and then
425 // make a copy with slice() that we can return.
426 var retVal = null;
Kevin Lubickbe728012020-09-03 11:57:12 +0000427 switch (imageInfo['colorType']) {
Kevin Lubickd6b32ed2019-05-06 13:04:03 -0400428 case CanvasKit.ColorType.RGBA_8888:
Kevin Lubickb8123cc2020-11-06 13:05:37 -0500429 case CanvasKit.ColorType.RGBA_F16: // there is no half-float JS type, so we return raw bytes.
Bryce Thomas1fa54042020-01-14 13:46:30 -0800430 retVal = new Uint8Array(CanvasKit.HEAPU8.buffer, pPtr, pBytes).slice();
Kevin Lubickd6b32ed2019-05-06 13:04:03 -0400431 break;
432 case CanvasKit.ColorType.RGBA_F32:
Bryce Thomas1fa54042020-01-14 13:46:30 -0800433 retVal = new Float32Array(CanvasKit.HEAPU8.buffer, pPtr, pBytes).slice();
Kevin Lubickd6b32ed2019-05-06 13:04:03 -0400434 break;
Kevin Lubickb8123cc2020-11-06 13:05:37 -0500435 default:
436 Debug('ColorType not yet supported');
437 return null;
Kevin Lubickd6b32ed2019-05-06 13:04:03 -0400438 }
439
440 // Free the allocated pixels in the WASM memory
441 CanvasKit._free(pPtr);
442 return retVal;
Kevin Lubickb8123cc2020-11-06 13:05:37 -0500443 }
444
445 CanvasKit.Image.prototype.readPixels = function(srcX, srcY, imageInfo, destMallocObj,
446 bytesPerRow) {
447 return readPixels(this, srcX, srcY, imageInfo, destMallocObj, bytesPerRow);
Kevin Lubick9fe83912020-11-03 17:08:34 -0500448 };
Kevin Lubickd6b32ed2019-05-06 13:04:03 -0400449
Nathaniel Nifong1bedbeb2020-05-04 16:46:17 -0400450 // Accepts an array of four numbers in the range of 0-1 representing a 4f color
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400451 CanvasKit.Canvas.prototype.clear = function(color4f) {
Kevin Lubick6aa38692020-06-01 11:25:47 -0400452 var cPtr = copyColorToWasm(color4f);
Nathaniel Nifong1bedbeb2020-05-04 16:46:17 -0400453 this._clear(cPtr);
Kevin Lubick9fe83912020-11-03 17:08:34 -0500454 };
Nathaniel Nifong1bedbeb2020-05-04 16:46:17 -0400455
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400456 CanvasKit.Canvas.prototype.clipRRect = function(rrect, op, antialias) {
Kevin Lubickbe728012020-09-03 11:57:12 +0000457 var rPtr = copyRRectToWasm(rrect);
458 this._clipRRect(rPtr, op, antialias);
Kevin Lubick9fe83912020-11-03 17:08:34 -0500459 };
Kevin Lubickbe728012020-09-03 11:57:12 +0000460
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400461 CanvasKit.Canvas.prototype.clipRect = function(rect, op, antialias) {
Kevin Lubickf8823b52020-09-03 10:02:10 -0400462 var rPtr = copyRectToWasm(rect);
463 this._clipRect(rPtr, op, antialias);
Kevin Lubick9fe83912020-11-03 17:08:34 -0500464 };
Kevin Lubickf8823b52020-09-03 10:02:10 -0400465
Kevin Lubickc1d08982020-04-06 13:52:15 -0400466 // concat takes a 3x2, a 3x3, or a 4x4 matrix and upscales it (if needed) to 4x4. This is because
467 // under the hood, SkCanvas uses a 4x4 matrix.
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400468 CanvasKit.Canvas.prototype.concat = function(matr) {
Kevin Lubickc1d08982020-04-06 13:52:15 -0400469 var matrPtr = copy4x4MatrixToWasm(matr);
Kevin Lubick6bffe392020-04-02 15:24:15 -0400470 this._concat(matrPtr);
Kevin Lubick9fe83912020-11-03 17:08:34 -0500471 };
Kevin Lubickd6b32ed2019-05-06 13:04:03 -0400472
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400473 CanvasKit.Canvas.prototype.drawArc = function(oval, startAngle, sweepAngle, useCenter, paint) {
Kevin Lubickf8823b52020-09-03 10:02:10 -0400474 var oPtr = copyRectToWasm(oval);
475 this._drawArc(oPtr, startAngle, sweepAngle, useCenter, paint);
Kevin Lubick9fe83912020-11-03 17:08:34 -0500476 };
Kevin Lubickf8823b52020-09-03 10:02:10 -0400477
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400478 // atlas is an Image, e.g. from CanvasKit.MakeImageFromEncoded
479 // srcRects, dstXforms, and colors should be CanvasKit.RectBuilder, CanvasKit.RSXFormBuilder,
480 // and CanvasKit.ColorBuilder (fastest)
Nathaniel Nifongcd75b172020-06-05 11:17:43 -0400481 // Or they can be an array of floats of length 4*number of destinations.
482 // colors are optional and used to tint the drawn images using the optional blend mode
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400483 // Colors may be an ColorBuilder, a Uint32Array of int colors,
Nathaniel Nifongd05fd0c2020-06-11 08:44:20 -0400484 // a Flat Float32Array of float colors or a 2d Array of Float32Array(4) (deprecated)
Kevin Lubick97440de2020-09-29 17:58:21 -0400485 // TODO(kjlubick) remove Builders - no longer needed now that Malloc is a thing.
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400486 CanvasKit.Canvas.prototype.drawAtlas = function(atlas, srcRects, dstXforms, paint,
Mike Reed55144312021-03-25 13:13:23 -0400487 /* optional */ blendMode, /* optional */ colors,
488 /* optional */ sampling) {
Kevin Lubickee91c072019-03-29 10:39:52 -0400489 if (!atlas || !paint || !srcRects || !dstXforms) {
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400490 Debug('Doing nothing since missing a required input');
Kevin Lubickee91c072019-03-29 10:39:52 -0400491 return;
492 }
Nathaniel Nifongcd75b172020-06-05 11:17:43 -0400493
494 // builder arguments report the length as the number of rects, but when passed as arrays
495 // their.length attribute is 4x higher because it's the number of total components of all rects.
496 // colors is always going to report the same length, at least until floats colors are supported
497 // by this function.
498 if (srcRects.length !== dstXforms.length) {
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400499 Debug('Doing nothing since input arrays length mismatches');
Nathaniel Nifonge5d32542020-03-26 09:27:48 -0400500 return;
Kevin Lubickee91c072019-03-29 10:39:52 -0400501 }
502 if (!blendMode) {
503 blendMode = CanvasKit.BlendMode.SrcOver;
504 }
505
506 var srcRectPtr;
507 if (srcRects.build) {
508 srcRectPtr = srcRects.build();
509 } else {
Kevin Lubickbe728012020-09-03 11:57:12 +0000510 srcRectPtr = copy1dArray(srcRects, 'HEAPF32');
Kevin Lubickee91c072019-03-29 10:39:52 -0400511 }
512
Nathaniel Nifongcd75b172020-06-05 11:17:43 -0400513 var count = 1;
Kevin Lubickee91c072019-03-29 10:39:52 -0400514 var dstXformPtr;
515 if (dstXforms.build) {
516 dstXformPtr = dstXforms.build();
Nathaniel Nifongcd75b172020-06-05 11:17:43 -0400517 count = dstXforms.length;
Kevin Lubickee91c072019-03-29 10:39:52 -0400518 } else {
Kevin Lubickbe728012020-09-03 11:57:12 +0000519 dstXformPtr = copy1dArray(dstXforms, 'HEAPF32');
Nathaniel Nifongcd75b172020-06-05 11:17:43 -0400520 count = dstXforms.length / 4;
Kevin Lubickee91c072019-03-29 10:39:52 -0400521 }
522
Kevin Lubick6bffe392020-04-02 15:24:15 -0400523 var colorPtr = nullptr;
Kevin Lubickee91c072019-03-29 10:39:52 -0400524 if (colors) {
525 if (colors.build) {
526 colorPtr = colors.build();
527 } else {
Kevin Lubickbe728012020-09-03 11:57:12 +0000528 colorPtr = copy1dArray(assureIntColors(colors), 'HEAPU32');
Kevin Lubickee91c072019-03-29 10:39:52 -0400529 }
530 }
531
Mike Reed55144312021-03-25 13:13:23 -0400532 // We require one of these:
533 // 1. sampling is null (we default to linear/none)
534 // 2. sampling.B and sampling.C --> CubicResampler
535 // 3. sampling.filter [and sampling.mipmap] --> FilterOptions
536 //
537 // Thus if all fields are available, we will choose cubic (since we search for B,C first)
538
539 if (sampling && ('B' in sampling) && ('C' in sampling)) {
540 this._drawAtlasCubic(atlas, dstXformPtr, srcRectPtr, colorPtr, count, blendMode,
541 sampling['B'], sampling['C'], paint);
542 } else {
543 let filter = CanvasKit.FilterMode.Linear;
544 let mipmap = CanvasKit.MipmapMode.None;
545 if (sampling) {
546 filter = sampling['filter']; // 'filter' is a required field
547 if ('mipmap' in sampling) { // 'mipmap' is optional
548 mipmap = sampling['mipmap'];
549 }
550 }
551 this._drawAtlasOptions(atlas, dstXformPtr, srcRectPtr, colorPtr, count, blendMode,
552 filter, mipmap, paint);
553 }
Kevin Lubickee91c072019-03-29 10:39:52 -0400554
555 if (srcRectPtr && !srcRects.build) {
Kevin Lubickcf118922020-05-28 14:43:38 -0400556 freeArraysThatAreNotMallocedByUsers(srcRectPtr, srcRects);
Kevin Lubickee91c072019-03-29 10:39:52 -0400557 }
558 if (dstXformPtr && !dstXforms.build) {
Kevin Lubickcf118922020-05-28 14:43:38 -0400559 freeArraysThatAreNotMallocedByUsers(dstXformPtr, dstXforms);
Kevin Lubickee91c072019-03-29 10:39:52 -0400560 }
561 if (colorPtr && !colors.build) {
Kevin Lubickcf118922020-05-28 14:43:38 -0400562 freeArraysThatAreNotMallocedByUsers(colorPtr, colors);
Kevin Lubickee91c072019-03-29 10:39:52 -0400563 }
Kevin Lubick9fe83912020-11-03 17:08:34 -0500564 };
Kevin Lubickee91c072019-03-29 10:39:52 -0400565
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400566 CanvasKit.Canvas.prototype.drawColor = function (color4f, mode) {
Kevin Lubick6aa38692020-06-01 11:25:47 -0400567 var cPtr = copyColorToWasm(color4f);
Nathaniel Nifong1bedbeb2020-05-04 16:46:17 -0400568 if (mode !== undefined) {
569 this._drawColor(cPtr, mode);
570 } else {
571 this._drawColor(cPtr);
572 }
Kevin Lubick9fe83912020-11-03 17:08:34 -0500573 };
Nathaniel Nifong1bedbeb2020-05-04 16:46:17 -0400574
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400575 CanvasKit.Canvas.prototype.drawColorComponents = function (r, g, b, a, mode) {
Kevin Lubick93f1a382020-06-02 16:15:23 -0400576 var cPtr = copyColorComponentsToWasm(r, g, b, a);
577 if (mode !== undefined) {
578 this._drawColor(cPtr, mode);
579 } else {
580 this._drawColor(cPtr);
581 }
Kevin Lubick9fe83912020-11-03 17:08:34 -0500582 };
Kevin Lubick93f1a382020-06-02 16:15:23 -0400583
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400584 CanvasKit.Canvas.prototype.drawDRRect = function(outer, inner, paint) {
Kevin Lubickbe728012020-09-03 11:57:12 +0000585 var oPtr = copyRRectToWasm(outer, _scratchRRectPtr);
586 var iPtr = copyRRectToWasm(inner, _scratchRRect2Ptr);
587 this._drawDRRect(oPtr, iPtr, paint);
Kevin Lubick9fe83912020-11-03 17:08:34 -0500588 };
Kevin Lubickbe728012020-09-03 11:57:12 +0000589
Mike Reed9983b1e2021-04-14 14:49:35 -0400590 CanvasKit.Canvas.prototype.drawGlyphs = function(glyphs, positions, x, y, font, paint) {
Mike Reedae339542021-04-27 17:46:41 -0400591 if (!(glyphs.length*2 <= positions.length)) {
592 throw 'Not enough positions for the array of gyphs';
Mike Reed9983b1e2021-04-14 14:49:35 -0400593 }
594
595 const glyphs_ptr = copy1dArray(glyphs, 'HEAPU16');
596 const positions_ptr = copy1dArray(positions, 'HEAPF32');
597
598 this._drawGlyphs(glyphs.length, glyphs_ptr, positions_ptr, x, y, font, paint);
599
600 freeArraysThatAreNotMallocedByUsers(positions_ptr, positions);
601 freeArraysThatAreNotMallocedByUsers(glyphs_ptr, glyphs);
602 };
603
Kevin Lubick2d633492020-12-17 09:58:32 -0500604 CanvasKit.Canvas.prototype.drawImageNine = function(img, center, dest, filter, paint) {
Kevin Lubickf8823b52020-09-03 10:02:10 -0400605 var cPtr = copyIRectToWasm(center);
606 var dPtr = copyRectToWasm(dest);
Kevin Lubick2d633492020-12-17 09:58:32 -0500607 this._drawImageNine(img, cPtr, dPtr, filter, paint || null);
Kevin Lubick9fe83912020-11-03 17:08:34 -0500608 };
Kevin Lubickf8823b52020-09-03 10:02:10 -0400609
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400610 CanvasKit.Canvas.prototype.drawImageRect = function(img, src, dest, paint, fastSample) {
Kevin Lubicked962642021-02-02 08:18:11 -0500611 copyRectToWasm(src, _scratchFourFloatsAPtr);
612 copyRectToWasm(dest, _scratchFourFloatsBPtr);
613 this._drawImageRect(img, _scratchFourFloatsAPtr, _scratchFourFloatsBPtr, paint, !!fastSample);
Kevin Lubick9fe83912020-11-03 17:08:34 -0500614 };
Kevin Lubickf8823b52020-09-03 10:02:10 -0400615
Kevin Lubick72f40762020-12-16 16:00:55 -0500616 CanvasKit.Canvas.prototype.drawImageRectCubic = function(img, src, dest, B, C, paint) {
Kevin Lubicked962642021-02-02 08:18:11 -0500617 copyRectToWasm(src, _scratchFourFloatsAPtr);
618 copyRectToWasm(dest, _scratchFourFloatsBPtr);
619 this._drawImageRectCubic(img, _scratchFourFloatsAPtr, _scratchFourFloatsBPtr, B, C,
620 paint || null);
Kevin Lubick72f40762020-12-16 16:00:55 -0500621 };
622
623 CanvasKit.Canvas.prototype.drawImageRectOptions = function(img, src, dest, filter, mipmap, paint) {
Kevin Lubicked962642021-02-02 08:18:11 -0500624 copyRectToWasm(src, _scratchFourFloatsAPtr);
625 copyRectToWasm(dest, _scratchFourFloatsBPtr);
626 this._drawImageRectOptions(img, _scratchFourFloatsAPtr, _scratchFourFloatsBPtr, filter, mipmap,
627 paint || null);
Kevin Lubick72f40762020-12-16 16:00:55 -0500628 };
629
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400630 CanvasKit.Canvas.prototype.drawOval = function(oval, paint) {
Kevin Lubickf8823b52020-09-03 10:02:10 -0400631 var oPtr = copyRectToWasm(oval);
632 this._drawOval(oPtr, paint);
Kevin Lubick9fe83912020-11-03 17:08:34 -0500633 };
Kevin Lubickf8823b52020-09-03 10:02:10 -0400634
Mike Reed6e7d2b32021-03-29 16:38:01 -0400635 CanvasKit.Canvas.prototype.drawPatch = function(cubics, colors, texs, mode, paint) {
636 if (cubics.length < 24) {
Mike Reedbe834bf2021-04-14 14:51:59 -0400637 throw 'Need 12 cubic points';
Mike Reed6e7d2b32021-03-29 16:38:01 -0400638 }
639 if (colors && colors.length < 4) {
Mike Reedbe834bf2021-04-14 14:51:59 -0400640 throw 'Need 4 colors';
Mike Reed6e7d2b32021-03-29 16:38:01 -0400641 }
642 if (texs && texs.length < 8) {
Mike Reedbe834bf2021-04-14 14:51:59 -0400643 throw 'Need 4 shader coordinates';
Mike Reed6e7d2b32021-03-29 16:38:01 -0400644 }
645
646 const cubics_ptr = copy1dArray(cubics, 'HEAPF32');
647 const colors_ptr = colors ? copy1dArray(assureIntColors(colors), 'HEAPU32') : nullptr;
648 const texs_ptr = texs ? copy1dArray(texs, 'HEAPF32') : nullptr;
649 if (!mode) {
650 mode = CanvasKit.BlendMode.Modulate;
651 }
652
653 this._drawPatch(cubics_ptr, colors_ptr, texs_ptr, mode, paint);
654
655 freeArraysThatAreNotMallocedByUsers(texs_ptr, texs);
656 freeArraysThatAreNotMallocedByUsers(colors_ptr, colors);
657 freeArraysThatAreNotMallocedByUsers(cubics_ptr, cubics);
658 };
659
660
Kevin Lubick658cb712020-12-01 14:55:02 -0500661 // points is a 1d array of length 2n representing n points where the even indices
662 // will be treated as x coordinates and the odd indices will be treated as y coordinates.
663 // Like other APIs, this accepts a malloced type array or malloc obj.
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400664 CanvasKit.Canvas.prototype.drawPoints = function(mode, points, paint) {
Kevin Lubick658cb712020-12-01 14:55:02 -0500665 var ptr = copy1dArray(points, 'HEAPF32');
666 this._drawPoints(mode, ptr, points.length / 2, paint);
Kevin Lubickcf118922020-05-28 14:43:38 -0400667 freeArraysThatAreNotMallocedByUsers(ptr, points);
Kevin Lubick9fe83912020-11-03 17:08:34 -0500668 };
Kevin Lubick37ab53e2019-11-11 10:06:08 -0500669
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400670 CanvasKit.Canvas.prototype.drawRRect = function(rrect, paint) {
Kevin Lubickbe728012020-09-03 11:57:12 +0000671 var rPtr = copyRRectToWasm(rrect);
672 this._drawRRect(rPtr, paint);
Kevin Lubick9fe83912020-11-03 17:08:34 -0500673 };
Kevin Lubickbe728012020-09-03 11:57:12 +0000674
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400675 CanvasKit.Canvas.prototype.drawRect = function(rect, paint) {
Kevin Lubickf8823b52020-09-03 10:02:10 -0400676 var rPtr = copyRectToWasm(rect);
677 this._drawRect(rPtr, paint);
Kevin Lubick9fe83912020-11-03 17:08:34 -0500678 };
Kevin Lubickf8823b52020-09-03 10:02:10 -0400679
Kevin Lubickcbaea292021-01-13 14:16:58 -0500680 CanvasKit.Canvas.prototype.drawShadow = function(path, zPlaneParams, lightPos, lightRadius,
681 ambientColor, spotColor, flags) {
Kevin Lubick6aa38692020-06-01 11:25:47 -0400682 var ambiPtr = copyColorToWasmNoScratch(ambientColor);
683 var spotPtr = copyColorToWasmNoScratch(spotColor);
Kevin Lubickf6040ef2021-02-02 08:26:48 -0500684 // We use the return value from copy1dArray in case the passed in arrays are malloc'd.
685 var zPlanePtr = copy1dArray(zPlaneParams, 'HEAPF32', _scratchThreeFloatsAPtr);
686 var lightPosPtr = copy1dArray(lightPos, 'HEAPF32', _scratchThreeFloatsBPtr);
687 this._drawShadow(path, zPlanePtr, lightPosPtr, lightRadius, ambiPtr, spotPtr, flags);
Kevin Lubickcf118922020-05-28 14:43:38 -0400688 freeArraysThatAreNotMallocedByUsers(ambiPtr, ambientColor);
689 freeArraysThatAreNotMallocedByUsers(spotPtr, spotColor);
Kevin Lubick9fe83912020-11-03 17:08:34 -0500690 };
Nathaniel Nifong1bedbeb2020-05-04 16:46:17 -0400691
Kevin Lubickcbaea292021-01-13 14:16:58 -0500692 CanvasKit.getShadowLocalBounds = function(ctm, path, zPlaneParams, lightPos, lightRadius,
693 flags, optOutputRect) {
694 var ctmPtr = copy3x3MatrixToWasm(ctm);
Kevin Lubickf6040ef2021-02-02 08:26:48 -0500695 // We use the return value from copy1dArray in case the passed in arrays are malloc'd.
696 var zPlanePtr = copy1dArray(zPlaneParams, 'HEAPF32', _scratchThreeFloatsAPtr);
697 var lightPosPtr = copy1dArray(lightPos, 'HEAPF32', _scratchThreeFloatsBPtr);
698 var ok = this._getShadowLocalBounds(ctmPtr, path, zPlanePtr, lightPosPtr, lightRadius,
Kevin Lubicked962642021-02-02 08:18:11 -0500699 flags, _scratchFourFloatsAPtr);
Kevin Lubickcbaea292021-01-13 14:16:58 -0500700 if (!ok) {
701 return null;
702 }
Kevin Lubicked962642021-02-02 08:18:11 -0500703 var ta = _scratchFourFloatsA['toTypedArray']();
Kevin Lubickcbaea292021-01-13 14:16:58 -0500704 if (optOutputRect) {
705 optOutputRect.set(ta);
706 return optOutputRect;
707 }
708 return ta.slice();
709 };
710
Kevin Lubickc1d08982020-04-06 13:52:15 -0400711 // getLocalToDevice returns a 4x4 matrix.
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400712 CanvasKit.Canvas.prototype.getLocalToDevice = function() {
Kevin Lubickc1d08982020-04-06 13:52:15 -0400713 // _getLocalToDevice will copy the values into the pointer.
Kevin Lubick6aa38692020-06-01 11:25:47 -0400714 this._getLocalToDevice(_scratch4x4MatrixPtr);
715 return copy4x4MatrixFromWasm(_scratch4x4MatrixPtr);
Kevin Lubick9fe83912020-11-03 17:08:34 -0500716 };
Kevin Lubickc1d08982020-04-06 13:52:15 -0400717
Nathaniel Nifong00de91c2020-05-06 16:22:33 -0400718 // findMarkedCTM returns a 4x4 matrix, or null if a matrix was not found at
719 // the provided marker.
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400720 CanvasKit.Canvas.prototype.findMarkedCTM = function(marker) {
Nathaniel Nifong00de91c2020-05-06 16:22:33 -0400721 // _getLocalToDevice will copy the values into the pointer.
Kevin Lubick6aa38692020-06-01 11:25:47 -0400722 var found = this._findMarkedCTM(marker, _scratch4x4MatrixPtr);
Nathaniel Nifong00de91c2020-05-06 16:22:33 -0400723 if (!found) {
724 return null;
725 }
Kevin Lubick6aa38692020-06-01 11:25:47 -0400726 return copy4x4MatrixFromWasm(_scratch4x4MatrixPtr);
Kevin Lubick9fe83912020-11-03 17:08:34 -0500727 };
Nathaniel Nifong00de91c2020-05-06 16:22:33 -0400728
Kevin Lubickc1d08982020-04-06 13:52:15 -0400729 // getTotalMatrix returns the current matrix as a 3x3 matrix.
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400730 CanvasKit.Canvas.prototype.getTotalMatrix = function() {
Kevin Lubick6bffe392020-04-02 15:24:15 -0400731 // _getTotalMatrix will copy the values into the pointer.
Kevin Lubick6aa38692020-06-01 11:25:47 -0400732 this._getTotalMatrix(_scratch3x3MatrixPtr);
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400733 // read them out into an array. TODO(kjlubick): If we change Matrix to be
Kevin Lubick6bffe392020-04-02 15:24:15 -0400734 // typedArrays, then we should return a typed array here too.
735 var rv = new Array(9);
736 for (var i = 0; i < 9; i++) {
Kevin Lubick6aa38692020-06-01 11:25:47 -0400737 rv[i] = CanvasKit.HEAPF32[_scratch3x3MatrixPtr/4 + i]; // divide by 4 to "cast" to float.
Kevin Lubick6bffe392020-04-02 15:24:15 -0400738 }
Kevin Lubick6bffe392020-04-02 15:24:15 -0400739 return rv;
Kevin Lubick9fe83912020-11-03 17:08:34 -0500740 };
Kevin Lubick6bffe392020-04-02 15:24:15 -0400741
Kevin Lubickb8123cc2020-11-06 13:05:37 -0500742 CanvasKit.Canvas.prototype.readPixels = function(srcX, srcY, imageInfo, destMallocObj,
743 bytesPerRow) {
744 return readPixels(this, srcX, srcY, imageInfo, destMallocObj, bytesPerRow);
Kevin Lubick9fe83912020-11-03 17:08:34 -0500745 };
Kevin Lubickf5ea37f2019-02-28 10:06:18 -0500746
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400747 CanvasKit.Canvas.prototype.saveLayer = function(paint, boundsRect, backdrop, flags) {
Kevin Lubickf8823b52020-09-03 10:02:10 -0400748 // bPtr will be 0 (nullptr) if boundsRect is undefined/null.
749 var bPtr = copyRectToWasm(boundsRect);
750 // These or clauses help emscripten, which does not deal with undefined well.
751 return this._saveLayer(paint || null, bPtr, backdrop || null, flags || 0);
Kevin Lubick9fe83912020-11-03 17:08:34 -0500752 };
Kevin Lubickf8823b52020-09-03 10:02:10 -0400753
Kevin Lubickcf118922020-05-28 14:43:38 -0400754 // pixels should be a Uint8Array or a plain JS array.
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400755 CanvasKit.Canvas.prototype.writePixels = function(pixels, srcWidth, srcHeight,
Nathaniel Nifongb1ebbb12020-05-26 13:10:20 -0400756 destX, destY, alphaType, colorType, colorSpace) {
Kevin Lubickf5ea37f2019-02-28 10:06:18 -0500757 if (pixels.byteLength % (srcWidth * srcHeight)) {
758 throw 'pixels length must be a multiple of the srcWidth * srcHeight';
759 }
760 var bytesPerPixel = pixels.byteLength / (srcWidth * srcHeight);
761 // supply defaults (which are compatible with HTMLCanvas's putImageData)
762 alphaType = alphaType || CanvasKit.AlphaType.Unpremul;
763 colorType = colorType || CanvasKit.ColorType.RGBA_8888;
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400764 colorSpace = colorSpace || CanvasKit.ColorSpace.SRGB;
Kevin Lubickf5ea37f2019-02-28 10:06:18 -0500765 var srcRowBytes = bytesPerPixel * srcWidth;
766
Kevin Lubickbe728012020-09-03 11:57:12 +0000767 var pptr = copy1dArray(pixels, 'HEAPU8');
Kevin Lubickf5ea37f2019-02-28 10:06:18 -0500768 var ok = this._writePixels({
769 'width': srcWidth,
770 'height': srcHeight,
771 'colorType': colorType,
772 'alphaType': alphaType,
Nathaniel Nifongb1ebbb12020-05-26 13:10:20 -0400773 'colorSpace': colorSpace,
Kevin Lubickf5ea37f2019-02-28 10:06:18 -0500774 }, pptr, srcRowBytes, destX, destY);
775
Kevin Lubickcf118922020-05-28 14:43:38 -0400776 freeArraysThatAreNotMallocedByUsers(pptr, pixels);
Kevin Lubickf5ea37f2019-02-28 10:06:18 -0500777 return ok;
Kevin Lubick9fe83912020-11-03 17:08:34 -0500778 };
Kevin Lubick52b9f372018-12-04 13:57:36 -0500779
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400780 CanvasKit.ColorFilter.MakeBlend = function(color4f, mode) {
Kevin Lubick6aa38692020-06-01 11:25:47 -0400781 var cPtr = copyColorToWasm(color4f);
Kevin Lubick33645792021-01-29 08:37:41 -0500782 return CanvasKit.ColorFilter._MakeBlend(cPtr, mode);
Kevin Lubick9fe83912020-11-03 17:08:34 -0500783 };
Nathaniel Nifong1bedbeb2020-05-04 16:46:17 -0400784
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400785 // colorMatrix is an ColorMatrix (e.g. Float32Array of length 20)
786 CanvasKit.ColorFilter.MakeMatrix = function(colorMatrix) {
Kevin Lubickd3729342019-09-12 11:11:25 -0400787 if (!colorMatrix || colorMatrix.length !== 20) {
Kevin Lubick6bffe392020-04-02 15:24:15 -0400788 throw 'invalid color matrix';
Kevin Lubickd3729342019-09-12 11:11:25 -0400789 }
Kevin Lubickbe728012020-09-03 11:57:12 +0000790 var fptr = copy1dArray(colorMatrix, 'HEAPF32');
Kevin Lubickd3729342019-09-12 11:11:25 -0400791 // We know skia memcopies the floats, so we can free our memory after the call returns.
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400792 var m = CanvasKit.ColorFilter._makeMatrix(fptr);
Kevin Lubickcf118922020-05-28 14:43:38 -0400793 freeArraysThatAreNotMallocedByUsers(fptr, colorMatrix);
Kevin Lubickd3729342019-09-12 11:11:25 -0400794 return m;
Kevin Lubick9fe83912020-11-03 17:08:34 -0500795 };
Kevin Lubickd3729342019-09-12 11:11:25 -0400796
Kevin Lubicke9e8e5d2021-02-02 10:21:24 -0500797 CanvasKit.ContourMeasure.prototype.getPosTan = function(distance, optionalOutput) {
798 this._getPosTan(distance, _scratchFourFloatsAPtr);
799 var ta = _scratchFourFloatsA['toTypedArray']();
800 if (optionalOutput) {
801 optionalOutput.set(ta);
802 return optionalOutput;
803 }
804 return ta.slice();
805 };
806
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400807 CanvasKit.ImageFilter.MakeMatrixTransform = function(matr, filterQuality, input) {
Kevin Lubick6bffe392020-04-02 15:24:15 -0400808 var matrPtr = copy3x3MatrixToWasm(matr);
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400809 return CanvasKit.ImageFilter._MakeMatrixTransform(matrPtr, filterQuality, input);
Kevin Lubick9fe83912020-11-03 17:08:34 -0500810 };
Kevin Lubick6bffe392020-04-02 15:24:15 -0400811
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400812 CanvasKit.Paint.prototype.getColor = function() {
Kevin Lubick6aa38692020-06-01 11:25:47 -0400813 this._getColor(_scratchColorPtr);
814 return copyColorFromWasm(_scratchColorPtr);
Kevin Lubick9fe83912020-11-03 17:08:34 -0500815 };
Nathaniel Nifong1bedbeb2020-05-04 16:46:17 -0400816
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400817 CanvasKit.Paint.prototype.setColor = function(color4f, colorSpace) {
Nathaniel Nifongb1ebbb12020-05-26 13:10:20 -0400818 colorSpace = colorSpace || null; // null will be replaced with sRGB in the C++ method.
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400819 // emscripten wouldn't bind undefined to the sk_sp<ColorSpace> expected here.
Kevin Lubick6aa38692020-06-01 11:25:47 -0400820 var cPtr = copyColorToWasm(color4f);
Nathaniel Nifongb1ebbb12020-05-26 13:10:20 -0400821 this._setColor(cPtr, colorSpace);
Kevin Lubick9fe83912020-11-03 17:08:34 -0500822 };
Nathaniel Nifong1bedbeb2020-05-04 16:46:17 -0400823
Kevin Lubick93f1a382020-06-02 16:15:23 -0400824 // The color components here are expected to be floating point values (nominally between
825 // 0.0 and 1.0, but with wider color gamuts, the values could exceed this range). To convert
826 // between standard 8 bit colors and floats, just divide by 255 before passing them in.
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400827 CanvasKit.Paint.prototype.setColorComponents = function(r, g, b, a, colorSpace) {
Kevin Lubick93f1a382020-06-02 16:15:23 -0400828 colorSpace = colorSpace || null; // null will be replaced with sRGB in the C++ method.
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400829 // emscripten wouldn't bind undefined to the sk_sp<ColorSpace> expected here.
Kevin Lubick93f1a382020-06-02 16:15:23 -0400830 var cPtr = copyColorComponentsToWasm(r, g, b, a);
831 this._setColor(cPtr, colorSpace);
Kevin Lubick9fe83912020-11-03 17:08:34 -0500832 };
Kevin Lubick93f1a382020-06-02 16:15:23 -0400833
Kevin Lubicked962642021-02-02 08:18:11 -0500834 CanvasKit.Path.prototype.getPoint = function(idx, optionalOutput) {
835 // This will copy 2 floats into a space for 4 floats
836 this._getPoint(idx, _scratchFourFloatsAPtr);
837 var ta = _scratchFourFloatsA['toTypedArray']();
838 if (optionalOutput) {
839 // We cannot call optionalOutput.set() because it is an error to call .set() with
840 // a source bigger than the destination.
841 optionalOutput[0] = ta[0];
842 optionalOutput[1] = ta[1];
843 return optionalOutput;
844 }
845 // Be sure to return a copy of just the first 2 values.
846 return ta.slice(0, 2);
847 };
848
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400849 CanvasKit.PictureRecorder.prototype.beginRecording = function(bounds) {
Kevin Lubickf8823b52020-09-03 10:02:10 -0400850 var bPtr = copyRectToWasm(bounds);
851 return this._beginRecording(bPtr);
Kevin Lubick9fe83912020-11-03 17:08:34 -0500852 };
Kevin Lubickf8823b52020-09-03 10:02:10 -0400853
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400854 CanvasKit.Surface.prototype.makeImageSnapshot = function(optionalBoundsRect) {
Kevin Lubickf8823b52020-09-03 10:02:10 -0400855 var bPtr = copyIRectToWasm(optionalBoundsRect);
856 return this._makeImageSnapshot(bPtr);
Kevin Lubick9fe83912020-11-03 17:08:34 -0500857 };
Kevin Lubickf8823b52020-09-03 10:02:10 -0400858
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400859 CanvasKit.Surface.prototype.requestAnimationFrame = function(callback, dirtyRect) {
Kevin Lubick359a7e32019-03-19 09:34:37 -0400860 if (!this._cached_canvas) {
861 this._cached_canvas = this.getCanvas();
862 }
Elliot Evans1ec3b1a2020-07-23 10:25:58 -0400863 requestAnimationFrame(function() {
Kevin Lubick39026282019-03-28 12:46:40 -0400864 if (this._context !== undefined) {
865 CanvasKit.setCurrentContext(this._context);
866 }
Kevin Lubick359a7e32019-03-19 09:34:37 -0400867
868 callback(this._cached_canvas);
869
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400870 // We do not dispose() of the Surface here, as the client will typically
Bryce Thomas2c5b8562020-01-22 13:49:41 -0800871 // call requestAnimationFrame again from within the supplied callback.
872 // For drawing a single frame, prefer drawOnce().
Bryce Thomas9331ca02020-05-29 16:51:21 -0700873 this.flush(dirtyRect);
Kevin Lubick359a7e32019-03-19 09:34:37 -0400874 }.bind(this));
Kevin Lubick9fe83912020-11-03 17:08:34 -0500875 };
Kevin Lubick359a7e32019-03-19 09:34:37 -0400876
Kevin Lubick52379332020-01-27 10:01:25 -0500877 // drawOnce will dispose of the surface after drawing the frame using the provided
878 // callback.
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400879 CanvasKit.Surface.prototype.drawOnce = function(callback, dirtyRect) {
Bryce Thomas2c5b8562020-01-22 13:49:41 -0800880 if (!this._cached_canvas) {
881 this._cached_canvas = this.getCanvas();
882 }
Elliot Evans1ec3b1a2020-07-23 10:25:58 -0400883 requestAnimationFrame(function() {
Bryce Thomas2c5b8562020-01-22 13:49:41 -0800884 if (this._context !== undefined) {
885 CanvasKit.setCurrentContext(this._context);
886 }
887 callback(this._cached_canvas);
888
Bryce Thomas9331ca02020-05-29 16:51:21 -0700889 this.flush(dirtyRect);
Bryce Thomas2c5b8562020-01-22 13:49:41 -0800890 this.dispose();
891 }.bind(this));
Kevin Lubick9fe83912020-11-03 17:08:34 -0500892 };
Bryce Thomas2c5b8562020-01-22 13:49:41 -0800893
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400894 CanvasKit.PathEffect.MakeDash = function(intervals, phase) {
Nathaniel Nifong23b0ed92020-03-04 15:43:50 -0500895 if (!phase) {
896 phase = 0;
897 }
898 if (!intervals.length || intervals.length % 2 === 1) {
899 throw 'Intervals array must have even length';
900 }
Kevin Lubickbe728012020-09-03 11:57:12 +0000901 var ptr = copy1dArray(intervals, 'HEAPF32');
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400902 var dpe = CanvasKit.PathEffect._MakeDash(ptr, intervals.length, phase);
Kevin Lubickcf118922020-05-28 14:43:38 -0400903 freeArraysThatAreNotMallocedByUsers(ptr, intervals);
Nathaniel Nifong23b0ed92020-03-04 15:43:50 -0500904 return dpe;
Kevin Lubick9fe83912020-11-03 17:08:34 -0500905 };
Nathaniel Nifong23b0ed92020-03-04 15:43:50 -0500906
Kevin Lubick421ba882020-10-15 13:07:33 -0400907 CanvasKit.Shader.MakeColor = function(color4f, colorSpace) {
Kevin Lubicked962642021-02-02 08:18:11 -0500908 colorSpace = colorSpace || null;
Kevin Lubick6aa38692020-06-01 11:25:47 -0400909 var cPtr = copyColorToWasm(color4f);
Kevin Lubick421ba882020-10-15 13:07:33 -0400910 return CanvasKit.Shader._MakeColor(cPtr, colorSpace);
Kevin Lubick9fe83912020-11-03 17:08:34 -0500911 };
Nathaniel Nifong1bedbeb2020-05-04 16:46:17 -0400912
Kevin Lubick421ba882020-10-15 13:07:33 -0400913 // TODO(kjlubick) remove deprecated names.
914 CanvasKit.Shader.Blend = CanvasKit.Shader.MakeBlend;
915 CanvasKit.Shader.Color = CanvasKit.Shader.MakeColor;
916 CanvasKit.Shader.Lerp = CanvasKit.Shader.MakeLerp;
917
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400918 CanvasKit.Shader.MakeLinearGradient = function(start, end, colors, pos, mode, localMatrix, flags, colorSpace) {
Kevin Lubickb8123cc2020-11-06 13:05:37 -0500919 colorSpace = colorSpace || null;
Nathaniel Nifongd05fd0c2020-06-11 08:44:20 -0400920 var cPtrInfo = copyFlexibleColorArray(colors);
Kevin Lubick421ba882020-10-15 13:07:33 -0400921 var posPtr = copy1dArray(pos, 'HEAPF32');
Nathaniel Nifong23b0ed92020-03-04 15:43:50 -0500922 flags = flags || 0;
Kevin Lubick6bffe392020-04-02 15:24:15 -0400923 var localMatrixPtr = copy3x3MatrixToWasm(localMatrix);
Nathaniel Nifong23b0ed92020-03-04 15:43:50 -0500924
Kevin Lubicked962642021-02-02 08:18:11 -0500925 // Copy start and end to _scratchFourFloatsAPtr.
926 var startEndPts = _scratchFourFloatsA['toTypedArray']();
927 startEndPts.set(start);
928 startEndPts.set(end, 2);
929
930 var lgs = CanvasKit.Shader._MakeLinearGradient(_scratchFourFloatsAPtr, cPtrInfo.colorPtr, cPtrInfo.colorType, posPtr,
Kevin Lubick421ba882020-10-15 13:07:33 -0400931 cPtrInfo.count, mode, flags, localMatrixPtr, colorSpace);
Nathaniel Nifong23b0ed92020-03-04 15:43:50 -0500932
Nathaniel Nifongd05fd0c2020-06-11 08:44:20 -0400933 freeArraysThatAreNotMallocedByUsers(cPtrInfo.colorPtr, colors);
Kevin Lubicke7b329e2020-06-05 15:58:01 -0400934 pos && freeArraysThatAreNotMallocedByUsers(posPtr, pos);
Nathaniel Nifong23b0ed92020-03-04 15:43:50 -0500935 return lgs;
Kevin Lubick9fe83912020-11-03 17:08:34 -0500936 };
Nathaniel Nifong23b0ed92020-03-04 15:43:50 -0500937
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400938 CanvasKit.Shader.MakeRadialGradient = function(center, radius, colors, pos, mode, localMatrix, flags, colorSpace) {
Kevin Lubicked962642021-02-02 08:18:11 -0500939 colorSpace = colorSpace || null;
Nathaniel Nifongd05fd0c2020-06-11 08:44:20 -0400940 var cPtrInfo = copyFlexibleColorArray(colors);
Kevin Lubick421ba882020-10-15 13:07:33 -0400941 var posPtr = copy1dArray(pos, 'HEAPF32');
Nathaniel Nifong23b0ed92020-03-04 15:43:50 -0500942 flags = flags || 0;
Kevin Lubick6bffe392020-04-02 15:24:15 -0400943 var localMatrixPtr = copy3x3MatrixToWasm(localMatrix);
Nathaniel Nifong23b0ed92020-03-04 15:43:50 -0500944
Kevin Lubicked962642021-02-02 08:18:11 -0500945 var rgs = CanvasKit.Shader._MakeRadialGradient(center[0], center[1], radius, cPtrInfo.colorPtr,
946 cPtrInfo.colorType, posPtr, cPtrInfo.count, mode,
947 flags, localMatrixPtr, colorSpace);
Nathaniel Nifong23b0ed92020-03-04 15:43:50 -0500948
Nathaniel Nifongd05fd0c2020-06-11 08:44:20 -0400949 freeArraysThatAreNotMallocedByUsers(cPtrInfo.colorPtr, colors);
Kevin Lubicke7b329e2020-06-05 15:58:01 -0400950 pos && freeArraysThatAreNotMallocedByUsers(posPtr, pos);
Nathaniel Nifong23b0ed92020-03-04 15:43:50 -0500951 return rgs;
Kevin Lubick9fe83912020-11-03 17:08:34 -0500952 };
Nathaniel Nifong23b0ed92020-03-04 15:43:50 -0500953
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400954 CanvasKit.Shader.MakeSweepGradient = function(cx, cy, colors, pos, mode, localMatrix, flags, startAngle, endAngle, colorSpace) {
Kevin Lubicked962642021-02-02 08:18:11 -0500955 colorSpace = colorSpace || null;
Nathaniel Nifongd05fd0c2020-06-11 08:44:20 -0400956 var cPtrInfo = copyFlexibleColorArray(colors);
Kevin Lubick421ba882020-10-15 13:07:33 -0400957 var posPtr = copy1dArray(pos, 'HEAPF32');
Dan Field3d44f732020-03-16 09:17:30 -0700958 flags = flags || 0;
959 startAngle = startAngle || 0;
960 endAngle = endAngle || 360;
Kevin Lubick6bffe392020-04-02 15:24:15 -0400961 var localMatrixPtr = copy3x3MatrixToWasm(localMatrix);
Dan Field3d44f732020-03-16 09:17:30 -0700962
Kevin Lubick421ba882020-10-15 13:07:33 -0400963 var sgs = CanvasKit.Shader._MakeSweepGradient(cx, cy, cPtrInfo.colorPtr, cPtrInfo.colorType, posPtr,
964 cPtrInfo.count, mode,
965 startAngle, endAngle, flags,
966 localMatrixPtr, colorSpace);
Dan Field3d44f732020-03-16 09:17:30 -0700967
Nathaniel Nifongd05fd0c2020-06-11 08:44:20 -0400968 freeArraysThatAreNotMallocedByUsers(cPtrInfo.colorPtr, colors);
Kevin Lubicke7b329e2020-06-05 15:58:01 -0400969 pos && freeArraysThatAreNotMallocedByUsers(posPtr, pos);
Dan Field3d44f732020-03-16 09:17:30 -0700970 return sgs;
Kevin Lubick9fe83912020-11-03 17:08:34 -0500971 };
Dan Field3d44f732020-03-16 09:17:30 -0700972
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400973 CanvasKit.Shader.MakeTwoPointConicalGradient = function(start, startRadius, end, endRadius,
Kevin Lubick421ba882020-10-15 13:07:33 -0400974 colors, pos, mode, localMatrix, flags, colorSpace) {
Kevin Lubicked962642021-02-02 08:18:11 -0500975 colorSpace = colorSpace || null;
Nathaniel Nifongd05fd0c2020-06-11 08:44:20 -0400976 var cPtrInfo = copyFlexibleColorArray(colors);
Kevin Lubick421ba882020-10-15 13:07:33 -0400977 var posPtr = copy1dArray(pos, 'HEAPF32');
Nathaniel Nifong23b0ed92020-03-04 15:43:50 -0500978 flags = flags || 0;
Kevin Lubick6bffe392020-04-02 15:24:15 -0400979 var localMatrixPtr = copy3x3MatrixToWasm(localMatrix);
Nathaniel Nifong23b0ed92020-03-04 15:43:50 -0500980
Kevin Lubicked962642021-02-02 08:18:11 -0500981 // Copy start and end to _scratchFourFloatsAPtr.
982 var startEndPts = _scratchFourFloatsA['toTypedArray']();
983 startEndPts.set(start);
984 startEndPts.set(end, 2);
985
986 var rgs = CanvasKit.Shader._MakeTwoPointConicalGradient(_scratchFourFloatsAPtr,
987 startRadius, endRadius, cPtrInfo.colorPtr, cPtrInfo.colorType,
Nathaniel Nifongd05fd0c2020-06-11 08:44:20 -0400988 posPtr, cPtrInfo.count, mode, flags, localMatrixPtr, colorSpace);
Nathaniel Nifong23b0ed92020-03-04 15:43:50 -0500989
Nathaniel Nifongd05fd0c2020-06-11 08:44:20 -0400990 freeArraysThatAreNotMallocedByUsers(cPtrInfo.colorPtr, colors);
Kevin Lubicke7b329e2020-06-05 15:58:01 -0400991 pos && freeArraysThatAreNotMallocedByUsers(posPtr, pos);
Nathaniel Nifong23b0ed92020-03-04 15:43:50 -0500992 return rgs;
Kevin Lubick9fe83912020-11-03 17:08:34 -0500993 };
Nathaniel Nifong23b0ed92020-03-04 15:43:50 -0500994
Kevin Lubickf8823b52020-09-03 10:02:10 -0400995 // Clients can pass in a Float32Array with length 4 to this and the results
996 // will be copied into that array. Otherwise, a new TypedArray will be allocated
997 // and returned.
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400998 CanvasKit.Vertices.prototype.bounds = function(optionalOutputArray) {
Kevin Lubicked962642021-02-02 08:18:11 -0500999 this._bounds(_scratchFourFloatsAPtr);
1000 var ta = _scratchFourFloatsA['toTypedArray']();
Kevin Lubickf8823b52020-09-03 10:02:10 -04001001 if (optionalOutputArray) {
1002 optionalOutputArray.set(ta);
1003 return optionalOutputArray;
1004 }
1005 return ta.slice();
Kevin Lubick9fe83912020-11-03 17:08:34 -05001006 };
Kevin Lubickf8823b52020-09-03 10:02:10 -04001007
Kevin Lubickf5ea37f2019-02-28 10:06:18 -05001008 // Run through the JS files that are added at compile time.
1009 if (CanvasKit._extraInitializations) {
1010 CanvasKit._extraInitializations.forEach(function(init) {
1011 init();
1012 });
Kevin Lubickeb2f6b02018-11-29 15:07:02 -05001013 }
Kevin Lubickf5ea37f2019-02-28 10:06:18 -05001014}; // end CanvasKit.onRuntimeInitialized, that is, anything changing prototypes or dynamic.
Kevin Lubickeb2f6b02018-11-29 15:07:02 -05001015
Nathaniel Nifong1bedbeb2020-05-04 16:46:17 -04001016// Accepts an object holding two canvaskit colors.
1017// {
Kevin Lubick3d00e3a2020-10-02 14:59:28 -04001018// ambient: [r, g, b, a],
1019// spot: [r, g, b, a],
Nathaniel Nifong1bedbeb2020-05-04 16:46:17 -04001020// }
Kevin Lubicke7b329e2020-06-05 15:58:01 -04001021// Returns the same format. Note, if malloced colors are passed in, the memory
1022// housing the passed in colors passed in will be overwritten with the computed
1023// tonal colors.
Nathaniel Nifong1bedbeb2020-05-04 16:46:17 -04001024CanvasKit.computeTonalColors = function(tonalColors) {
Kevin Lubicke7b329e2020-06-05 15:58:01 -04001025 // copy the colors into WASM
Kevin Lubick6aa38692020-06-01 11:25:47 -04001026 var cPtrAmbi = copyColorToWasmNoScratch(tonalColors['ambient']);
1027 var cPtrSpot = copyColorToWasmNoScratch(tonalColors['spot']);
Kevin Lubicke7b329e2020-06-05 15:58:01 -04001028 // The output of this function will be the same pointers we passed in.
Nathaniel Nifong1bedbeb2020-05-04 16:46:17 -04001029 this._computeTonalColors(cPtrAmbi, cPtrSpot);
Kevin Lubicke7b329e2020-06-05 15:58:01 -04001030 // Read the results out.
Nathaniel Nifong1bedbeb2020-05-04 16:46:17 -04001031 var result = {
1032 'ambient': copyColorFromWasm(cPtrAmbi),
1033 'spot': copyColorFromWasm(cPtrSpot),
Kevin Lubickd9b9e5e2020-06-23 16:58:10 -04001034 };
Kevin Lubicke7b329e2020-06-05 15:58:01 -04001035 // If the user passed us malloced colors in here, we don't want to clean them up.
1036 freeArraysThatAreNotMallocedByUsers(cPtrAmbi, tonalColors['ambient']);
1037 freeArraysThatAreNotMallocedByUsers(cPtrSpot, tonalColors['spot']);
Nathaniel Nifong1bedbeb2020-05-04 16:46:17 -04001038 return result;
Kevin Lubickd9b9e5e2020-06-23 16:58:10 -04001039};
Nathaniel Nifong1bedbeb2020-05-04 16:46:17 -04001040
Kevin Lubickf5ea37f2019-02-28 10:06:18 -05001041CanvasKit.LTRBRect = function(l, t, r, b) {
Kevin Lubickf8823b52020-09-03 10:02:10 -04001042 return Float32Array.of(l, t, r, b);
Kevin Lubickd9b9e5e2020-06-23 16:58:10 -04001043};
Kevin Lubick1a05fce2018-11-20 12:51:16 -05001044
Kevin Lubickf5ea37f2019-02-28 10:06:18 -05001045CanvasKit.XYWHRect = function(x, y, w, h) {
Kevin Lubickf8823b52020-09-03 10:02:10 -04001046 return Float32Array.of(x, y, x+w, y+h);
1047};
1048
1049CanvasKit.LTRBiRect = function(l, t, r, b) {
1050 return Int32Array.of(l, t, r, b);
1051};
1052
1053CanvasKit.XYWHiRect = function(x, y, w, h) {
1054 return Int32Array.of(x, y, x+w, y+h);
Kevin Lubickd9b9e5e2020-06-23 16:58:10 -04001055};
Kevin Lubick1a05fce2018-11-20 12:51:16 -05001056
Kevin Lubickbe728012020-09-03 11:57:12 +00001057// RRectXY returns a TypedArray representing an RRect with the given rect and a radiusX and
1058// radiusY for all 4 corners.
Kevin Lubick7d644e12019-09-11 14:22:22 -04001059CanvasKit.RRectXY = function(rect, rx, ry) {
Kevin Lubickbe728012020-09-03 11:57:12 +00001060 return Float32Array.of(
Kevin Lubickf8823b52020-09-03 10:02:10 -04001061 rect[0], rect[1], rect[2], rect[3],
Kevin Lubickbe728012020-09-03 11:57:12 +00001062 rx, ry,
1063 rx, ry,
1064 rx, ry,
1065 rx, ry,
1066 );
Kevin Lubickd9b9e5e2020-06-23 16:58:10 -04001067};
Kevin Lubickf5ea37f2019-02-28 10:06:18 -05001068
Kevin Lubickf5ea37f2019-02-28 10:06:18 -05001069// data is a TypedArray or ArrayBuffer e.g. from fetch().then(resp.arrayBuffer())
Kevin Lubick6b921b72019-09-18 16:18:17 -04001070CanvasKit.MakeAnimatedImageFromEncoded = function(data) {
1071 data = new Uint8Array(data);
1072
1073 var iptr = CanvasKit._malloc(data.byteLength);
1074 CanvasKit.HEAPU8.set(data, iptr);
1075 var img = CanvasKit._decodeAnimatedImage(iptr, data.byteLength);
1076 if (!img) {
Kevin Lubick54c1b3d2020-10-07 16:09:22 -04001077 Debug('Could not decode animated image');
Kevin Lubick6b921b72019-09-18 16:18:17 -04001078 return null;
1079 }
1080 return img;
Kevin Lubick9fe83912020-11-03 17:08:34 -05001081};
Kevin Lubick6b921b72019-09-18 16:18:17 -04001082
1083// data is a TypedArray or ArrayBuffer e.g. from fetch().then(resp.arrayBuffer())
Kevin Lubickf5ea37f2019-02-28 10:06:18 -05001084CanvasKit.MakeImageFromEncoded = function(data) {
1085 data = new Uint8Array(data);
1086
1087 var iptr = CanvasKit._malloc(data.byteLength);
1088 CanvasKit.HEAPU8.set(data, iptr);
1089 var img = CanvasKit._decodeImage(iptr, data.byteLength);
1090 if (!img) {
Kevin Lubick54c1b3d2020-10-07 16:09:22 -04001091 Debug('Could not decode image');
Kevin Lubickf5ea37f2019-02-28 10:06:18 -05001092 return null;
1093 }
Kevin Lubickf5ea37f2019-02-28 10:06:18 -05001094 return img;
Kevin Lubick9fe83912020-11-03 17:08:34 -05001095};
Kevin Lubickf5ea37f2019-02-28 10:06:18 -05001096
Elliot Evans28796192020-06-15 12:53:27 -06001097// A variable to hold a canvasElement which can be reused once created the first time.
1098var memoizedCanvas2dElement = null;
1099
1100// Alternative to CanvasKit.MakeImageFromEncoded. Allows for CanvasKit users to take advantage of
1101// browser APIs to decode images instead of using codecs included in the CanvasKit wasm binary.
1102// Expects that the canvasImageSource has already loaded/decoded.
1103// CanvasImageSource reference: https://developer.mozilla.org/en-US/docs/Web/API/CanvasImageSource
1104CanvasKit.MakeImageFromCanvasImageSource = function(canvasImageSource) {
1105 var width = canvasImageSource.width;
1106 var height = canvasImageSource.height;
1107
1108 if (!memoizedCanvas2dElement) {
1109 memoizedCanvas2dElement = document.createElement('canvas');
1110 }
1111 memoizedCanvas2dElement.width = width;
1112 memoizedCanvas2dElement.height = height;
1113
1114 var ctx2d = memoizedCanvas2dElement.getContext('2d');
1115 ctx2d.drawImage(canvasImageSource, 0, 0);
1116
1117 var imageData = ctx2d.getImageData(0, 0, width, height);
1118
Kevin Lubickae0d3ff2020-11-18 11:23:15 -05001119 return CanvasKit.MakeImage({
1120 'width': width,
1121 'height': height,
1122 'alphaType': CanvasKit.AlphaType.Unpremul,
1123 'colorType': CanvasKit.ColorType.RGBA_8888,
1124 'colorSpace': CanvasKit.ColorSpace.SRGB
1125 }, imageData.data, 4 * width);
Kevin Lubick9fe83912020-11-03 17:08:34 -05001126};
Elliot Evans28796192020-06-15 12:53:27 -06001127
Kevin Lubickae0d3ff2020-11-18 11:23:15 -05001128// pixels may be an array but Uint8Array or Uint8ClampedArray is recommended,
1129// with the bytes representing the pixel values.
Kevin Lubickeda0b432019-12-02 08:26:48 -05001130// (e.g. each set of 4 bytes could represent RGBA values for a single pixel).
Kevin Lubickae0d3ff2020-11-18 11:23:15 -05001131CanvasKit.MakeImage = function(info, pixels, bytesPerRow) {
1132 var pptr = CanvasKit._malloc(pixels.length);
1133 CanvasKit.HEAPU8.set(pixels, pptr); // We always want to copy the bytes into the WASM heap.
Kevin Lubickeda0b432019-12-02 08:26:48 -05001134 // No need to _free pptr, Image takes it with SkData::MakeFromMalloc
Kevin Lubickae0d3ff2020-11-18 11:23:15 -05001135 return CanvasKit._MakeImage(info, pptr, pixels.length, bytesPerRow);
Kevin Lubick9fe83912020-11-03 17:08:34 -05001136};
Kevin Lubickf5ea37f2019-02-28 10:06:18 -05001137
Nathaniel Nifongd05fd0c2020-06-11 08:44:20 -04001138// Colors may be a Uint32Array of int colors, a Flat Float32Array of float colors
1139// or a 2d Array of Float32Array(4) (deprecated)
Kevin Lubicke7c1a732020-12-04 09:10:39 -05001140// the underlying Skia function accepts only int colors so it is recommended
Nathaniel Nifongd05fd0c2020-06-11 08:44:20 -04001141// to pass an array of int colors to avoid an extra conversion.
Kevin Lubick54c1b3d2020-10-07 16:09:22 -04001142// ColorBuilder is not accepted.
1143CanvasKit.MakeVertices = function(mode, positions, textureCoordinates, colors,
1144 indices, isVolatile) {
Kevin Lubicke7c1a732020-12-04 09:10:39 -05001145 // Default isVolatile to true if not set
Kevin Lubickb3574c92019-03-06 08:25:36 -05001146 isVolatile = isVolatile === undefined ? true : isVolatile;
Kevin Lubickd6ba7252019-06-03 14:38:05 -04001147 var idxCount = (indices && indices.length) || 0;
1148
1149 var flags = 0;
1150 // These flags are from SkVertices.h and should be kept in sync with those.
1151 if (textureCoordinates && textureCoordinates.length) {
1152 flags |= (1 << 0);
1153 }
1154 if (colors && colors.length) {
1155 flags |= (1 << 1);
1156 }
Kevin Lubickd6ba7252019-06-03 14:38:05 -04001157 if (!isVolatile) {
Mike Reed5caf9352020-03-02 14:57:09 -05001158 flags |= (1 << 2);
Kevin Lubickd6ba7252019-06-03 14:38:05 -04001159 }
1160
Kevin Lubicke7c1a732020-12-04 09:10:39 -05001161 var builder = new CanvasKit._VerticesBuilder(mode, positions.length / 2, idxCount, flags);
Kevin Lubickd6ba7252019-06-03 14:38:05 -04001162
Kevin Lubicke7c1a732020-12-04 09:10:39 -05001163 copy1dArray(positions, 'HEAPF32', builder.positions());
Kevin Lubickd6ba7252019-06-03 14:38:05 -04001164 if (builder.texCoords()) {
Kevin Lubicke7c1a732020-12-04 09:10:39 -05001165 copy1dArray(textureCoordinates, 'HEAPF32', builder.texCoords());
Kevin Lubickd6ba7252019-06-03 14:38:05 -04001166 }
1167 if (builder.colors()) {
Nathaniel Nifongd05fd0c2020-06-11 08:44:20 -04001168 if (colors.build) {
Kevin Lubick54c1b3d2020-10-07 16:09:22 -04001169 throw('Color builder not accepted by MakeVertices, use array of ints');
Nathaniel Nifongd05fd0c2020-06-11 08:44:20 -04001170 } else {
Kevin Lubickbe728012020-09-03 11:57:12 +00001171 copy1dArray(assureIntColors(colors), 'HEAPU32', builder.colors());
Nathaniel Nifongd05fd0c2020-06-11 08:44:20 -04001172 }
Kevin Lubickd6ba7252019-06-03 14:38:05 -04001173 }
Kevin Lubickd6ba7252019-06-03 14:38:05 -04001174 if (builder.indices()) {
Kevin Lubickbe728012020-09-03 11:57:12 +00001175 copy1dArray(indices, 'HEAPU16', builder.indices());
Kevin Lubickd6ba7252019-06-03 14:38:05 -04001176 }
Kevin Lubickb3574c92019-03-06 08:25:36 -05001177
Kevin Lubickd6ba7252019-06-03 14:38:05 -04001178 // Create the vertices, which owns the memory that the builder had allocated.
1179 return builder.detach();
Kevin Lubicka4f218d2020-01-14 08:39:09 -05001180};