blob: a4f8d52124727ccf853b46b935ce92cb69a5efc9 [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 Lubick82186e92021-06-02 10:29:11 -040053 var cmdPtr = copy1dArray(cmds, 'HEAPF32');
54 var path = CanvasKit.Path._MakeFromCmds(cmdPtr, cmds.length);
55 freeArraysThatAreNotMallocedByUsers(cmdPtr, cmds);
Kevin Lubickd9b9e5e2020-06-23 16:58:10 -040056 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 Lubickf6114042021-08-25 13:13:09 -0400452 CanvasKit.setCurrentContext(this._context);
Kevin Lubick6aa38692020-06-01 11:25:47 -0400453 var cPtr = copyColorToWasm(color4f);
Nathaniel Nifong1bedbeb2020-05-04 16:46:17 -0400454 this._clear(cPtr);
Kevin Lubick9fe83912020-11-03 17:08:34 -0500455 };
Nathaniel Nifong1bedbeb2020-05-04 16:46:17 -0400456
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400457 CanvasKit.Canvas.prototype.clipRRect = function(rrect, op, antialias) {
Kevin Lubickf6114042021-08-25 13:13:09 -0400458 CanvasKit.setCurrentContext(this._context);
Kevin Lubickbe728012020-09-03 11:57:12 +0000459 var rPtr = copyRRectToWasm(rrect);
460 this._clipRRect(rPtr, op, antialias);
Kevin Lubick9fe83912020-11-03 17:08:34 -0500461 };
Kevin Lubickbe728012020-09-03 11:57:12 +0000462
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400463 CanvasKit.Canvas.prototype.clipRect = function(rect, op, antialias) {
Kevin Lubickf6114042021-08-25 13:13:09 -0400464 CanvasKit.setCurrentContext(this._context);
Kevin Lubickf8823b52020-09-03 10:02:10 -0400465 var rPtr = copyRectToWasm(rect);
466 this._clipRect(rPtr, op, antialias);
Kevin Lubick9fe83912020-11-03 17:08:34 -0500467 };
Kevin Lubickf8823b52020-09-03 10:02:10 -0400468
Kevin Lubickc1d08982020-04-06 13:52:15 -0400469 // concat takes a 3x2, a 3x3, or a 4x4 matrix and upscales it (if needed) to 4x4. This is because
470 // under the hood, SkCanvas uses a 4x4 matrix.
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400471 CanvasKit.Canvas.prototype.concat = function(matr) {
Kevin Lubickf6114042021-08-25 13:13:09 -0400472 CanvasKit.setCurrentContext(this._context);
Kevin Lubickc1d08982020-04-06 13:52:15 -0400473 var matrPtr = copy4x4MatrixToWasm(matr);
Kevin Lubick6bffe392020-04-02 15:24:15 -0400474 this._concat(matrPtr);
Kevin Lubick9fe83912020-11-03 17:08:34 -0500475 };
Kevin Lubickd6b32ed2019-05-06 13:04:03 -0400476
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400477 CanvasKit.Canvas.prototype.drawArc = function(oval, startAngle, sweepAngle, useCenter, paint) {
Kevin Lubickf6114042021-08-25 13:13:09 -0400478 CanvasKit.setCurrentContext(this._context);
Kevin Lubickf8823b52020-09-03 10:02:10 -0400479 var oPtr = copyRectToWasm(oval);
480 this._drawArc(oPtr, startAngle, sweepAngle, useCenter, paint);
Kevin Lubick9fe83912020-11-03 17:08:34 -0500481 };
Kevin Lubickf8823b52020-09-03 10:02:10 -0400482
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400483 // atlas is an Image, e.g. from CanvasKit.MakeImageFromEncoded
Kevin Lubick78297af2021-06-02 10:36:06 -0400484 // srcRects, dstXformsshould be arrays of floats of length 4*number of destinations.
485 // The colors param is optional and is used to tint the drawn images using the optional blend
486 // mode. Colors can be a Uint32Array of int colors or a flat Float32Array of float colors.
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400487 CanvasKit.Canvas.prototype.drawAtlas = function(atlas, srcRects, dstXforms, paint,
Mike Reed55144312021-03-25 13:13:23 -0400488 /* optional */ blendMode, /* optional */ colors,
489 /* optional */ sampling) {
Kevin Lubickee91c072019-03-29 10:39:52 -0400490 if (!atlas || !paint || !srcRects || !dstXforms) {
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400491 Debug('Doing nothing since missing a required input');
Kevin Lubickee91c072019-03-29 10:39:52 -0400492 return;
493 }
Nathaniel Nifongcd75b172020-06-05 11:17:43 -0400494
495 // builder arguments report the length as the number of rects, but when passed as arrays
496 // their.length attribute is 4x higher because it's the number of total components of all rects.
497 // colors is always going to report the same length, at least until floats colors are supported
498 // by this function.
499 if (srcRects.length !== dstXforms.length) {
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400500 Debug('Doing nothing since input arrays length mismatches');
Nathaniel Nifonge5d32542020-03-26 09:27:48 -0400501 return;
Kevin Lubickee91c072019-03-29 10:39:52 -0400502 }
Kevin Lubickf6114042021-08-25 13:13:09 -0400503 CanvasKit.setCurrentContext(this._context);
Kevin Lubickee91c072019-03-29 10:39:52 -0400504 if (!blendMode) {
505 blendMode = CanvasKit.BlendMode.SrcOver;
506 }
507
Kevin Lubick78297af2021-06-02 10:36:06 -0400508 var srcRectPtr = copy1dArray(srcRects, 'HEAPF32');
Kevin Lubickee91c072019-03-29 10:39:52 -0400509
Kevin Lubick78297af2021-06-02 10:36:06 -0400510 var dstXformPtr = copy1dArray(dstXforms, 'HEAPF32');
511 var count = dstXforms.length / 4;
Kevin Lubickee91c072019-03-29 10:39:52 -0400512
Kevin Lubick78297af2021-06-02 10:36:06 -0400513 var colorPtr = copy1dArray(assureIntColors(colors), 'HEAPU32');
Kevin Lubickee91c072019-03-29 10:39:52 -0400514
Mike Reed55144312021-03-25 13:13:23 -0400515 // We require one of these:
516 // 1. sampling is null (we default to linear/none)
517 // 2. sampling.B and sampling.C --> CubicResampler
518 // 3. sampling.filter [and sampling.mipmap] --> FilterOptions
519 //
520 // Thus if all fields are available, we will choose cubic (since we search for B,C first)
521
522 if (sampling && ('B' in sampling) && ('C' in sampling)) {
523 this._drawAtlasCubic(atlas, dstXformPtr, srcRectPtr, colorPtr, count, blendMode,
524 sampling['B'], sampling['C'], paint);
525 } else {
526 let filter = CanvasKit.FilterMode.Linear;
527 let mipmap = CanvasKit.MipmapMode.None;
528 if (sampling) {
529 filter = sampling['filter']; // 'filter' is a required field
530 if ('mipmap' in sampling) { // 'mipmap' is optional
531 mipmap = sampling['mipmap'];
532 }
533 }
534 this._drawAtlasOptions(atlas, dstXformPtr, srcRectPtr, colorPtr, count, blendMode,
535 filter, mipmap, paint);
536 }
Kevin Lubickee91c072019-03-29 10:39:52 -0400537
Kevin Lubick78297af2021-06-02 10:36:06 -0400538 freeArraysThatAreNotMallocedByUsers(srcRectPtr, srcRects);
539 freeArraysThatAreNotMallocedByUsers(dstXformPtr, dstXforms);
540 freeArraysThatAreNotMallocedByUsers(colorPtr, colors);
Kevin Lubick9fe83912020-11-03 17:08:34 -0500541 };
Kevin Lubickee91c072019-03-29 10:39:52 -0400542
Kevin Lubickf6114042021-08-25 13:13:09 -0400543 CanvasKit.Canvas.prototype.drawCircle = function(cx, cy, r, paint) {
544 CanvasKit.setCurrentContext(this._context);
545 this._drawCircle(cx, cy, r, paint);
546 }
547
548 CanvasKit.Canvas.prototype.drawColor = function(color4f, mode) {
549 CanvasKit.setCurrentContext(this._context);
Kevin Lubick6aa38692020-06-01 11:25:47 -0400550 var cPtr = copyColorToWasm(color4f);
Nathaniel Nifong1bedbeb2020-05-04 16:46:17 -0400551 if (mode !== undefined) {
552 this._drawColor(cPtr, mode);
553 } else {
554 this._drawColor(cPtr);
555 }
Kevin Lubick9fe83912020-11-03 17:08:34 -0500556 };
Nathaniel Nifong1bedbeb2020-05-04 16:46:17 -0400557
Kevin Lubickf6114042021-08-25 13:13:09 -0400558 CanvasKit.Canvas.prototype.drawColorInt = function(color, mode) {
559 CanvasKit.setCurrentContext(this._context);
560 this._drawColorInt(color, mode || CanvasKit.BlendMode.SrcOver);
561 }
562
563 CanvasKit.Canvas.prototype.drawColorComponents = function(r, g, b, a, mode) {
564 CanvasKit.setCurrentContext(this._context);
Kevin Lubick93f1a382020-06-02 16:15:23 -0400565 var cPtr = copyColorComponentsToWasm(r, g, b, a);
566 if (mode !== undefined) {
567 this._drawColor(cPtr, mode);
568 } else {
569 this._drawColor(cPtr);
570 }
Kevin Lubick9fe83912020-11-03 17:08:34 -0500571 };
Kevin Lubick93f1a382020-06-02 16:15:23 -0400572
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400573 CanvasKit.Canvas.prototype.drawDRRect = function(outer, inner, paint) {
Kevin Lubickf6114042021-08-25 13:13:09 -0400574 CanvasKit.setCurrentContext(this._context);
Kevin Lubickbe728012020-09-03 11:57:12 +0000575 var oPtr = copyRRectToWasm(outer, _scratchRRectPtr);
576 var iPtr = copyRRectToWasm(inner, _scratchRRect2Ptr);
577 this._drawDRRect(oPtr, iPtr, paint);
Kevin Lubick9fe83912020-11-03 17:08:34 -0500578 };
Kevin Lubickbe728012020-09-03 11:57:12 +0000579
Mike Reed9983b1e2021-04-14 14:49:35 -0400580 CanvasKit.Canvas.prototype.drawGlyphs = function(glyphs, positions, x, y, font, paint) {
Mike Reedae339542021-04-27 17:46:41 -0400581 if (!(glyphs.length*2 <= positions.length)) {
582 throw 'Not enough positions for the array of gyphs';
Mike Reed9983b1e2021-04-14 14:49:35 -0400583 }
Kevin Lubickf6114042021-08-25 13:13:09 -0400584 CanvasKit.setCurrentContext(this._context);
Mike Reed9983b1e2021-04-14 14:49:35 -0400585 const glyphs_ptr = copy1dArray(glyphs, 'HEAPU16');
586 const positions_ptr = copy1dArray(positions, 'HEAPF32');
587
588 this._drawGlyphs(glyphs.length, glyphs_ptr, positions_ptr, x, y, font, paint);
589
590 freeArraysThatAreNotMallocedByUsers(positions_ptr, positions);
591 freeArraysThatAreNotMallocedByUsers(glyphs_ptr, glyphs);
592 };
593
Kevin Lubickf6114042021-08-25 13:13:09 -0400594 CanvasKit.Canvas.prototype.drawImage = function(img, x, y, paint) {
595 CanvasKit.setCurrentContext(this._context);
596 this._drawImage(img, x, y, paint || null);
597 };
598
599 CanvasKit.Canvas.prototype.drawImageCubic = function(img, x, y, b, c, paint) {
600 CanvasKit.setCurrentContext(this._context);
601 this._drawImageCubic(img, x, y, b, c, paint || null);
602 };
603
604 CanvasKit.Canvas.prototype.drawImageOptions = function(img, x, y, filter, mipmap, paint) {
605 CanvasKit.setCurrentContext(this._context);
606 this._drawImageOptions(img, x, y, filter, mipmap, paint || null);
607 };
608
Kevin Lubick2d633492020-12-17 09:58:32 -0500609 CanvasKit.Canvas.prototype.drawImageNine = function(img, center, dest, filter, paint) {
Kevin Lubickf6114042021-08-25 13:13:09 -0400610 CanvasKit.setCurrentContext(this._context);
Kevin Lubickf8823b52020-09-03 10:02:10 -0400611 var cPtr = copyIRectToWasm(center);
612 var dPtr = copyRectToWasm(dest);
Kevin Lubick2d633492020-12-17 09:58:32 -0500613 this._drawImageNine(img, cPtr, dPtr, filter, paint || null);
Kevin Lubick9fe83912020-11-03 17:08:34 -0500614 };
Kevin Lubickf8823b52020-09-03 10:02:10 -0400615
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400616 CanvasKit.Canvas.prototype.drawImageRect = function(img, src, dest, paint, fastSample) {
Kevin Lubickf6114042021-08-25 13:13:09 -0400617 CanvasKit.setCurrentContext(this._context);
Kevin Lubicked962642021-02-02 08:18:11 -0500618 copyRectToWasm(src, _scratchFourFloatsAPtr);
619 copyRectToWasm(dest, _scratchFourFloatsBPtr);
620 this._drawImageRect(img, _scratchFourFloatsAPtr, _scratchFourFloatsBPtr, paint, !!fastSample);
Kevin Lubick9fe83912020-11-03 17:08:34 -0500621 };
Kevin Lubickf8823b52020-09-03 10:02:10 -0400622
Kevin Lubick72f40762020-12-16 16:00:55 -0500623 CanvasKit.Canvas.prototype.drawImageRectCubic = function(img, src, dest, B, C, paint) {
Kevin Lubickf6114042021-08-25 13:13:09 -0400624 CanvasKit.setCurrentContext(this._context);
Kevin Lubicked962642021-02-02 08:18:11 -0500625 copyRectToWasm(src, _scratchFourFloatsAPtr);
626 copyRectToWasm(dest, _scratchFourFloatsBPtr);
627 this._drawImageRectCubic(img, _scratchFourFloatsAPtr, _scratchFourFloatsBPtr, B, C,
628 paint || null);
Kevin Lubick72f40762020-12-16 16:00:55 -0500629 };
630
631 CanvasKit.Canvas.prototype.drawImageRectOptions = function(img, src, dest, filter, mipmap, paint) {
Kevin Lubickf6114042021-08-25 13:13:09 -0400632 CanvasKit.setCurrentContext(this._context);
Kevin Lubicked962642021-02-02 08:18:11 -0500633 copyRectToWasm(src, _scratchFourFloatsAPtr);
634 copyRectToWasm(dest, _scratchFourFloatsBPtr);
635 this._drawImageRectOptions(img, _scratchFourFloatsAPtr, _scratchFourFloatsBPtr, filter, mipmap,
636 paint || null);
Kevin Lubick72f40762020-12-16 16:00:55 -0500637 };
638
Kevin Lubickf6114042021-08-25 13:13:09 -0400639 CanvasKit.Canvas.prototype.drawLine = function(x1, y1, x2, y2, paint) {
640 CanvasKit.setCurrentContext(this._context);
641 this._drawLine(x1, y1, x2, y2, paint);
642 }
643
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400644 CanvasKit.Canvas.prototype.drawOval = function(oval, paint) {
Kevin Lubickf6114042021-08-25 13:13:09 -0400645 CanvasKit.setCurrentContext(this._context);
Kevin Lubickf8823b52020-09-03 10:02:10 -0400646 var oPtr = copyRectToWasm(oval);
647 this._drawOval(oPtr, paint);
Kevin Lubick9fe83912020-11-03 17:08:34 -0500648 };
Kevin Lubickf8823b52020-09-03 10:02:10 -0400649
Kevin Lubickf6114042021-08-25 13:13:09 -0400650 CanvasKit.Canvas.prototype.drawPaint = function(paint) {
651 CanvasKit.setCurrentContext(this._context);
652 this._drawPaint(paint);
653 }
654
655 CanvasKit.Canvas.prototype.drawParagraph = function(p, x, y) {
656 CanvasKit.setCurrentContext(this._context);
657 this._drawParagraph(p, x, y);
658 }
659
Mike Reed6e7d2b32021-03-29 16:38:01 -0400660 CanvasKit.Canvas.prototype.drawPatch = function(cubics, colors, texs, mode, paint) {
661 if (cubics.length < 24) {
Mike Reedbe834bf2021-04-14 14:51:59 -0400662 throw 'Need 12 cubic points';
Mike Reed6e7d2b32021-03-29 16:38:01 -0400663 }
664 if (colors && colors.length < 4) {
Mike Reedbe834bf2021-04-14 14:51:59 -0400665 throw 'Need 4 colors';
Mike Reed6e7d2b32021-03-29 16:38:01 -0400666 }
667 if (texs && texs.length < 8) {
Mike Reedbe834bf2021-04-14 14:51:59 -0400668 throw 'Need 4 shader coordinates';
Mike Reed6e7d2b32021-03-29 16:38:01 -0400669 }
Kevin Lubickf6114042021-08-25 13:13:09 -0400670 CanvasKit.setCurrentContext(this._context);
Mike Reed6e7d2b32021-03-29 16:38:01 -0400671
672 const cubics_ptr = copy1dArray(cubics, 'HEAPF32');
673 const colors_ptr = colors ? copy1dArray(assureIntColors(colors), 'HEAPU32') : nullptr;
674 const texs_ptr = texs ? copy1dArray(texs, 'HEAPF32') : nullptr;
675 if (!mode) {
676 mode = CanvasKit.BlendMode.Modulate;
677 }
678
679 this._drawPatch(cubics_ptr, colors_ptr, texs_ptr, mode, paint);
680
681 freeArraysThatAreNotMallocedByUsers(texs_ptr, texs);
682 freeArraysThatAreNotMallocedByUsers(colors_ptr, colors);
683 freeArraysThatAreNotMallocedByUsers(cubics_ptr, cubics);
684 };
685
Kevin Lubickf6114042021-08-25 13:13:09 -0400686 CanvasKit.Canvas.prototype.drawPath = function(path, paint) {
687 CanvasKit.setCurrentContext(this._context);
688 this._drawPath(path, paint);
689 }
690
691 CanvasKit.Canvas.prototype.drawPicture = function(pic) {
692 CanvasKit.setCurrentContext(this._context);
693 this._drawPicture(pic);
694 }
Mike Reed6e7d2b32021-03-29 16:38:01 -0400695
Kevin Lubick658cb712020-12-01 14:55:02 -0500696 // points is a 1d array of length 2n representing n points where the even indices
697 // will be treated as x coordinates and the odd indices will be treated as y coordinates.
698 // Like other APIs, this accepts a malloced type array or malloc obj.
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400699 CanvasKit.Canvas.prototype.drawPoints = function(mode, points, paint) {
Kevin Lubickf6114042021-08-25 13:13:09 -0400700 CanvasKit.setCurrentContext(this._context);
Kevin Lubick658cb712020-12-01 14:55:02 -0500701 var ptr = copy1dArray(points, 'HEAPF32');
702 this._drawPoints(mode, ptr, points.length / 2, paint);
Kevin Lubickcf118922020-05-28 14:43:38 -0400703 freeArraysThatAreNotMallocedByUsers(ptr, points);
Kevin Lubick9fe83912020-11-03 17:08:34 -0500704 };
Kevin Lubick37ab53e2019-11-11 10:06:08 -0500705
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400706 CanvasKit.Canvas.prototype.drawRRect = function(rrect, paint) {
Kevin Lubickf6114042021-08-25 13:13:09 -0400707 CanvasKit.setCurrentContext(this._context);
Kevin Lubickbe728012020-09-03 11:57:12 +0000708 var rPtr = copyRRectToWasm(rrect);
709 this._drawRRect(rPtr, paint);
Kevin Lubick9fe83912020-11-03 17:08:34 -0500710 };
Kevin Lubickbe728012020-09-03 11:57:12 +0000711
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400712 CanvasKit.Canvas.prototype.drawRect = function(rect, paint) {
Kevin Lubickf6114042021-08-25 13:13:09 -0400713 CanvasKit.setCurrentContext(this._context);
Kevin Lubickf8823b52020-09-03 10:02:10 -0400714 var rPtr = copyRectToWasm(rect);
715 this._drawRect(rPtr, paint);
Kevin Lubick9fe83912020-11-03 17:08:34 -0500716 };
Kevin Lubickf8823b52020-09-03 10:02:10 -0400717
Kevin Lubickf6114042021-08-25 13:13:09 -0400718 CanvasKit.Canvas.prototype.drawRect4f = function(l, t, r, b, paint) {
719 CanvasKit.setCurrentContext(this._context);
720 this._drawRect4f(l, t, r, b, paint);
721 }
722
Kevin Lubickcbaea292021-01-13 14:16:58 -0500723 CanvasKit.Canvas.prototype.drawShadow = function(path, zPlaneParams, lightPos, lightRadius,
724 ambientColor, spotColor, flags) {
Kevin Lubickf6114042021-08-25 13:13:09 -0400725 CanvasKit.setCurrentContext(this._context);
Kevin Lubick6aa38692020-06-01 11:25:47 -0400726 var ambiPtr = copyColorToWasmNoScratch(ambientColor);
727 var spotPtr = copyColorToWasmNoScratch(spotColor);
Kevin Lubickf6040ef2021-02-02 08:26:48 -0500728 // We use the return value from copy1dArray in case the passed in arrays are malloc'd.
729 var zPlanePtr = copy1dArray(zPlaneParams, 'HEAPF32', _scratchThreeFloatsAPtr);
730 var lightPosPtr = copy1dArray(lightPos, 'HEAPF32', _scratchThreeFloatsBPtr);
731 this._drawShadow(path, zPlanePtr, lightPosPtr, lightRadius, ambiPtr, spotPtr, flags);
Kevin Lubickcf118922020-05-28 14:43:38 -0400732 freeArraysThatAreNotMallocedByUsers(ambiPtr, ambientColor);
733 freeArraysThatAreNotMallocedByUsers(spotPtr, spotColor);
Kevin Lubick9fe83912020-11-03 17:08:34 -0500734 };
Nathaniel Nifong1bedbeb2020-05-04 16:46:17 -0400735
Kevin Lubickcbaea292021-01-13 14:16:58 -0500736 CanvasKit.getShadowLocalBounds = function(ctm, path, zPlaneParams, lightPos, lightRadius,
737 flags, optOutputRect) {
738 var ctmPtr = copy3x3MatrixToWasm(ctm);
Kevin Lubickf6040ef2021-02-02 08:26:48 -0500739 // We use the return value from copy1dArray in case the passed in arrays are malloc'd.
740 var zPlanePtr = copy1dArray(zPlaneParams, 'HEAPF32', _scratchThreeFloatsAPtr);
741 var lightPosPtr = copy1dArray(lightPos, 'HEAPF32', _scratchThreeFloatsBPtr);
742 var ok = this._getShadowLocalBounds(ctmPtr, path, zPlanePtr, lightPosPtr, lightRadius,
Kevin Lubicked962642021-02-02 08:18:11 -0500743 flags, _scratchFourFloatsAPtr);
Kevin Lubickcbaea292021-01-13 14:16:58 -0500744 if (!ok) {
745 return null;
746 }
Kevin Lubicked962642021-02-02 08:18:11 -0500747 var ta = _scratchFourFloatsA['toTypedArray']();
Kevin Lubickcbaea292021-01-13 14:16:58 -0500748 if (optOutputRect) {
749 optOutputRect.set(ta);
750 return optOutputRect;
751 }
752 return ta.slice();
753 };
754
Kevin Lubickf6114042021-08-25 13:13:09 -0400755 CanvasKit.Canvas.prototype.drawTextBlob = function(blob, x, y, paint) {
756 CanvasKit.setCurrentContext(this._context);
757 this._drawTextBlob(blob, x, y, paint);
758 }
759
760 CanvasKit.Canvas.prototype.drawVertices = function(verts, mode, paint) {
761 CanvasKit.setCurrentContext(this._context);
762 this._drawVertices(verts, mode, paint);
763 }
764
Kevin Lubickc1d08982020-04-06 13:52:15 -0400765 // getLocalToDevice returns a 4x4 matrix.
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400766 CanvasKit.Canvas.prototype.getLocalToDevice = function() {
Kevin Lubickc1d08982020-04-06 13:52:15 -0400767 // _getLocalToDevice will copy the values into the pointer.
Kevin Lubick6aa38692020-06-01 11:25:47 -0400768 this._getLocalToDevice(_scratch4x4MatrixPtr);
769 return copy4x4MatrixFromWasm(_scratch4x4MatrixPtr);
Kevin Lubick9fe83912020-11-03 17:08:34 -0500770 };
Kevin Lubickc1d08982020-04-06 13:52:15 -0400771
Nathaniel Nifong00de91c2020-05-06 16:22:33 -0400772 // findMarkedCTM returns a 4x4 matrix, or null if a matrix was not found at
773 // the provided marker.
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400774 CanvasKit.Canvas.prototype.findMarkedCTM = function(marker) {
Nathaniel Nifong00de91c2020-05-06 16:22:33 -0400775 // _getLocalToDevice will copy the values into the pointer.
Kevin Lubick6aa38692020-06-01 11:25:47 -0400776 var found = this._findMarkedCTM(marker, _scratch4x4MatrixPtr);
Nathaniel Nifong00de91c2020-05-06 16:22:33 -0400777 if (!found) {
778 return null;
779 }
Kevin Lubick6aa38692020-06-01 11:25:47 -0400780 return copy4x4MatrixFromWasm(_scratch4x4MatrixPtr);
Kevin Lubick9fe83912020-11-03 17:08:34 -0500781 };
Nathaniel Nifong00de91c2020-05-06 16:22:33 -0400782
Kevin Lubickc1d08982020-04-06 13:52:15 -0400783 // getTotalMatrix returns the current matrix as a 3x3 matrix.
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400784 CanvasKit.Canvas.prototype.getTotalMatrix = function() {
Kevin Lubick6bffe392020-04-02 15:24:15 -0400785 // _getTotalMatrix will copy the values into the pointer.
Kevin Lubick6aa38692020-06-01 11:25:47 -0400786 this._getTotalMatrix(_scratch3x3MatrixPtr);
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400787 // read them out into an array. TODO(kjlubick): If we change Matrix to be
Kevin Lubick6bffe392020-04-02 15:24:15 -0400788 // typedArrays, then we should return a typed array here too.
789 var rv = new Array(9);
790 for (var i = 0; i < 9; i++) {
Kevin Lubick6aa38692020-06-01 11:25:47 -0400791 rv[i] = CanvasKit.HEAPF32[_scratch3x3MatrixPtr/4 + i]; // divide by 4 to "cast" to float.
Kevin Lubick6bffe392020-04-02 15:24:15 -0400792 }
Kevin Lubick6bffe392020-04-02 15:24:15 -0400793 return rv;
Kevin Lubick9fe83912020-11-03 17:08:34 -0500794 };
Kevin Lubick6bffe392020-04-02 15:24:15 -0400795
Kevin Lubickf6114042021-08-25 13:13:09 -0400796 CanvasKit.Canvas.prototype.makeSurface = function(imageInfo) {
797 var s = this._makeSurface(imageInfo);
798 s._context = this._context;
799 return s;
800 };
801
Kevin Lubickb8123cc2020-11-06 13:05:37 -0500802 CanvasKit.Canvas.prototype.readPixels = function(srcX, srcY, imageInfo, destMallocObj,
803 bytesPerRow) {
Kevin Lubickf6114042021-08-25 13:13:09 -0400804 CanvasKit.setCurrentContext(this._context);
Kevin Lubickb8123cc2020-11-06 13:05:37 -0500805 return readPixels(this, srcX, srcY, imageInfo, destMallocObj, bytesPerRow);
Kevin Lubick9fe83912020-11-03 17:08:34 -0500806 };
Kevin Lubickf5ea37f2019-02-28 10:06:18 -0500807
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400808 CanvasKit.Canvas.prototype.saveLayer = function(paint, boundsRect, backdrop, flags) {
Kevin Lubickf8823b52020-09-03 10:02:10 -0400809 // bPtr will be 0 (nullptr) if boundsRect is undefined/null.
810 var bPtr = copyRectToWasm(boundsRect);
811 // These or clauses help emscripten, which does not deal with undefined well.
812 return this._saveLayer(paint || null, bPtr, backdrop || null, flags || 0);
Kevin Lubick9fe83912020-11-03 17:08:34 -0500813 };
Kevin Lubickf8823b52020-09-03 10:02:10 -0400814
Kevin Lubickcf118922020-05-28 14:43:38 -0400815 // pixels should be a Uint8Array or a plain JS array.
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400816 CanvasKit.Canvas.prototype.writePixels = function(pixels, srcWidth, srcHeight,
Nathaniel Nifongb1ebbb12020-05-26 13:10:20 -0400817 destX, destY, alphaType, colorType, colorSpace) {
Kevin Lubickf5ea37f2019-02-28 10:06:18 -0500818 if (pixels.byteLength % (srcWidth * srcHeight)) {
819 throw 'pixels length must be a multiple of the srcWidth * srcHeight';
820 }
Kevin Lubickf6114042021-08-25 13:13:09 -0400821 CanvasKit.setCurrentContext(this._context);
Kevin Lubickf5ea37f2019-02-28 10:06:18 -0500822 var bytesPerPixel = pixels.byteLength / (srcWidth * srcHeight);
823 // supply defaults (which are compatible with HTMLCanvas's putImageData)
824 alphaType = alphaType || CanvasKit.AlphaType.Unpremul;
825 colorType = colorType || CanvasKit.ColorType.RGBA_8888;
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400826 colorSpace = colorSpace || CanvasKit.ColorSpace.SRGB;
Kevin Lubickf5ea37f2019-02-28 10:06:18 -0500827 var srcRowBytes = bytesPerPixel * srcWidth;
828
Kevin Lubickbe728012020-09-03 11:57:12 +0000829 var pptr = copy1dArray(pixels, 'HEAPU8');
Kevin Lubickf5ea37f2019-02-28 10:06:18 -0500830 var ok = this._writePixels({
831 'width': srcWidth,
832 'height': srcHeight,
833 'colorType': colorType,
834 'alphaType': alphaType,
Nathaniel Nifongb1ebbb12020-05-26 13:10:20 -0400835 'colorSpace': colorSpace,
Kevin Lubickf5ea37f2019-02-28 10:06:18 -0500836 }, pptr, srcRowBytes, destX, destY);
837
Kevin Lubickcf118922020-05-28 14:43:38 -0400838 freeArraysThatAreNotMallocedByUsers(pptr, pixels);
Kevin Lubickf5ea37f2019-02-28 10:06:18 -0500839 return ok;
Kevin Lubick9fe83912020-11-03 17:08:34 -0500840 };
Kevin Lubick52b9f372018-12-04 13:57:36 -0500841
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400842 CanvasKit.ColorFilter.MakeBlend = function(color4f, mode) {
Kevin Lubick6aa38692020-06-01 11:25:47 -0400843 var cPtr = copyColorToWasm(color4f);
Kevin Lubick33645792021-01-29 08:37:41 -0500844 return CanvasKit.ColorFilter._MakeBlend(cPtr, mode);
Kevin Lubick9fe83912020-11-03 17:08:34 -0500845 };
Nathaniel Nifong1bedbeb2020-05-04 16:46:17 -0400846
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400847 // colorMatrix is an ColorMatrix (e.g. Float32Array of length 20)
848 CanvasKit.ColorFilter.MakeMatrix = function(colorMatrix) {
Kevin Lubickd3729342019-09-12 11:11:25 -0400849 if (!colorMatrix || colorMatrix.length !== 20) {
Kevin Lubick6bffe392020-04-02 15:24:15 -0400850 throw 'invalid color matrix';
Kevin Lubickd3729342019-09-12 11:11:25 -0400851 }
Kevin Lubickbe728012020-09-03 11:57:12 +0000852 var fptr = copy1dArray(colorMatrix, 'HEAPF32');
Kevin Lubickd3729342019-09-12 11:11:25 -0400853 // We know skia memcopies the floats, so we can free our memory after the call returns.
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400854 var m = CanvasKit.ColorFilter._makeMatrix(fptr);
Kevin Lubickcf118922020-05-28 14:43:38 -0400855 freeArraysThatAreNotMallocedByUsers(fptr, colorMatrix);
Kevin Lubickd3729342019-09-12 11:11:25 -0400856 return m;
Kevin Lubick9fe83912020-11-03 17:08:34 -0500857 };
Kevin Lubickd3729342019-09-12 11:11:25 -0400858
Kevin Lubicke9e8e5d2021-02-02 10:21:24 -0500859 CanvasKit.ContourMeasure.prototype.getPosTan = function(distance, optionalOutput) {
860 this._getPosTan(distance, _scratchFourFloatsAPtr);
861 var ta = _scratchFourFloatsA['toTypedArray']();
862 if (optionalOutput) {
863 optionalOutput.set(ta);
864 return optionalOutput;
865 }
866 return ta.slice();
867 };
868
Mike Reed5caab8e2021-07-20 09:52:27 -0400869 CanvasKit.ImageFilter.MakeMatrixTransform = function(matrix, sampling, input) {
870 var matrPtr = copy3x3MatrixToWasm(matrix);
871
872 if ('B' in sampling && 'C' in sampling) {
873 return CanvasKit.ImageFilter._MakeMatrixTransformCubic(matrPtr,
874 sampling.B, sampling.C,
875 input);
876 } else {
877 const filter = sampling['filter']; // 'filter' is a required field
878 let mipmap = CanvasKit.MipmapMode.None;
879 if ('mipmap' in sampling) { // 'mipmap' is optional
880 mipmap = sampling['mipmap'];
881 }
882 return CanvasKit.ImageFilter._MakeMatrixTransformOptions(matrPtr,
883 filter, mipmap,
884 input);
885 }
Kevin Lubick9fe83912020-11-03 17:08:34 -0500886 };
Kevin Lubick6bffe392020-04-02 15:24:15 -0400887
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400888 CanvasKit.Paint.prototype.getColor = function() {
Kevin Lubick6aa38692020-06-01 11:25:47 -0400889 this._getColor(_scratchColorPtr);
890 return copyColorFromWasm(_scratchColorPtr);
Kevin Lubick9fe83912020-11-03 17:08:34 -0500891 };
Nathaniel Nifong1bedbeb2020-05-04 16:46:17 -0400892
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400893 CanvasKit.Paint.prototype.setColor = function(color4f, colorSpace) {
Nathaniel Nifongb1ebbb12020-05-26 13:10:20 -0400894 colorSpace = colorSpace || null; // null will be replaced with sRGB in the C++ method.
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400895 // emscripten wouldn't bind undefined to the sk_sp<ColorSpace> expected here.
Kevin Lubick6aa38692020-06-01 11:25:47 -0400896 var cPtr = copyColorToWasm(color4f);
Nathaniel Nifongb1ebbb12020-05-26 13:10:20 -0400897 this._setColor(cPtr, colorSpace);
Kevin Lubick9fe83912020-11-03 17:08:34 -0500898 };
Nathaniel Nifong1bedbeb2020-05-04 16:46:17 -0400899
Kevin Lubick93f1a382020-06-02 16:15:23 -0400900 // The color components here are expected to be floating point values (nominally between
901 // 0.0 and 1.0, but with wider color gamuts, the values could exceed this range). To convert
902 // between standard 8 bit colors and floats, just divide by 255 before passing them in.
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400903 CanvasKit.Paint.prototype.setColorComponents = function(r, g, b, a, colorSpace) {
Kevin Lubick93f1a382020-06-02 16:15:23 -0400904 colorSpace = colorSpace || null; // null will be replaced with sRGB in the C++ method.
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400905 // emscripten wouldn't bind undefined to the sk_sp<ColorSpace> expected here.
Kevin Lubick93f1a382020-06-02 16:15:23 -0400906 var cPtr = copyColorComponentsToWasm(r, g, b, a);
907 this._setColor(cPtr, colorSpace);
Kevin Lubick9fe83912020-11-03 17:08:34 -0500908 };
Kevin Lubick93f1a382020-06-02 16:15:23 -0400909
Kevin Lubicked962642021-02-02 08:18:11 -0500910 CanvasKit.Path.prototype.getPoint = function(idx, optionalOutput) {
911 // This will copy 2 floats into a space for 4 floats
912 this._getPoint(idx, _scratchFourFloatsAPtr);
913 var ta = _scratchFourFloatsA['toTypedArray']();
914 if (optionalOutput) {
915 // We cannot call optionalOutput.set() because it is an error to call .set() with
916 // a source bigger than the destination.
917 optionalOutput[0] = ta[0];
918 optionalOutput[1] = ta[1];
919 return optionalOutput;
920 }
921 // Be sure to return a copy of just the first 2 values.
922 return ta.slice(0, 2);
923 };
924
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400925 CanvasKit.PictureRecorder.prototype.beginRecording = function(bounds) {
Kevin Lubickf8823b52020-09-03 10:02:10 -0400926 var bPtr = copyRectToWasm(bounds);
927 return this._beginRecording(bPtr);
Kevin Lubick9fe83912020-11-03 17:08:34 -0500928 };
Kevin Lubickf8823b52020-09-03 10:02:10 -0400929
Kevin Lubickf6114042021-08-25 13:13:09 -0400930 CanvasKit.Surface.prototype.getCanvas = function() {
931 var c = this._getCanvas();
932 c._context = this._context;
933 return c;
934 };
935
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400936 CanvasKit.Surface.prototype.makeImageSnapshot = function(optionalBoundsRect) {
Kevin Lubickf8823b52020-09-03 10:02:10 -0400937 var bPtr = copyIRectToWasm(optionalBoundsRect);
938 return this._makeImageSnapshot(bPtr);
Kevin Lubick9fe83912020-11-03 17:08:34 -0500939 };
Kevin Lubickf8823b52020-09-03 10:02:10 -0400940
Kevin Lubickf6114042021-08-25 13:13:09 -0400941 CanvasKit.Surface.prototype.makeSurface = function(imageInfo) {
942 var s = this._makeSurface(imageInfo);
943 s._context = this._context;
944 return s;
945 };
946
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400947 CanvasKit.Surface.prototype.requestAnimationFrame = function(callback, dirtyRect) {
Kevin Lubick359a7e32019-03-19 09:34:37 -0400948 if (!this._cached_canvas) {
949 this._cached_canvas = this.getCanvas();
950 }
Elliot Evans1ec3b1a2020-07-23 10:25:58 -0400951 requestAnimationFrame(function() {
Kevin Lubickf6114042021-08-25 13:13:09 -0400952 CanvasKit.setCurrentContext(this._context);
Kevin Lubick359a7e32019-03-19 09:34:37 -0400953
954 callback(this._cached_canvas);
955
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400956 // We do not dispose() of the Surface here, as the client will typically
Bryce Thomas2c5b8562020-01-22 13:49:41 -0800957 // call requestAnimationFrame again from within the supplied callback.
958 // For drawing a single frame, prefer drawOnce().
Bryce Thomas9331ca02020-05-29 16:51:21 -0700959 this.flush(dirtyRect);
Kevin Lubick359a7e32019-03-19 09:34:37 -0400960 }.bind(this));
Kevin Lubick9fe83912020-11-03 17:08:34 -0500961 };
Kevin Lubick359a7e32019-03-19 09:34:37 -0400962
Kevin Lubick52379332020-01-27 10:01:25 -0500963 // drawOnce will dispose of the surface after drawing the frame using the provided
964 // callback.
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400965 CanvasKit.Surface.prototype.drawOnce = function(callback, dirtyRect) {
Bryce Thomas2c5b8562020-01-22 13:49:41 -0800966 if (!this._cached_canvas) {
967 this._cached_canvas = this.getCanvas();
968 }
Elliot Evans1ec3b1a2020-07-23 10:25:58 -0400969 requestAnimationFrame(function() {
Kevin Lubickf6114042021-08-25 13:13:09 -0400970 CanvasKit.setCurrentContext(this._context);
Bryce Thomas2c5b8562020-01-22 13:49:41 -0800971 callback(this._cached_canvas);
972
Bryce Thomas9331ca02020-05-29 16:51:21 -0700973 this.flush(dirtyRect);
Bryce Thomas2c5b8562020-01-22 13:49:41 -0800974 this.dispose();
975 }.bind(this));
Kevin Lubick9fe83912020-11-03 17:08:34 -0500976 };
Bryce Thomas2c5b8562020-01-22 13:49:41 -0800977
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400978 CanvasKit.PathEffect.MakeDash = function(intervals, phase) {
Nathaniel Nifong23b0ed92020-03-04 15:43:50 -0500979 if (!phase) {
980 phase = 0;
981 }
982 if (!intervals.length || intervals.length % 2 === 1) {
983 throw 'Intervals array must have even length';
984 }
Kevin Lubickbe728012020-09-03 11:57:12 +0000985 var ptr = copy1dArray(intervals, 'HEAPF32');
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400986 var dpe = CanvasKit.PathEffect._MakeDash(ptr, intervals.length, phase);
Kevin Lubickcf118922020-05-28 14:43:38 -0400987 freeArraysThatAreNotMallocedByUsers(ptr, intervals);
Nathaniel Nifong23b0ed92020-03-04 15:43:50 -0500988 return dpe;
Kevin Lubick9fe83912020-11-03 17:08:34 -0500989 };
Nathaniel Nifong23b0ed92020-03-04 15:43:50 -0500990
Kevin Lubick421ba882020-10-15 13:07:33 -0400991 CanvasKit.Shader.MakeColor = function(color4f, colorSpace) {
Kevin Lubicked962642021-02-02 08:18:11 -0500992 colorSpace = colorSpace || null;
Kevin Lubick6aa38692020-06-01 11:25:47 -0400993 var cPtr = copyColorToWasm(color4f);
Kevin Lubick421ba882020-10-15 13:07:33 -0400994 return CanvasKit.Shader._MakeColor(cPtr, colorSpace);
Kevin Lubick9fe83912020-11-03 17:08:34 -0500995 };
Nathaniel Nifong1bedbeb2020-05-04 16:46:17 -0400996
Kevin Lubick421ba882020-10-15 13:07:33 -0400997 // TODO(kjlubick) remove deprecated names.
998 CanvasKit.Shader.Blend = CanvasKit.Shader.MakeBlend;
999 CanvasKit.Shader.Color = CanvasKit.Shader.MakeColor;
Kevin Lubick421ba882020-10-15 13:07:33 -04001000
Kevin Lubick54c1b3d2020-10-07 16:09:22 -04001001 CanvasKit.Shader.MakeLinearGradient = function(start, end, colors, pos, mode, localMatrix, flags, colorSpace) {
Kevin Lubickb8123cc2020-11-06 13:05:37 -05001002 colorSpace = colorSpace || null;
Nathaniel Nifongd05fd0c2020-06-11 08:44:20 -04001003 var cPtrInfo = copyFlexibleColorArray(colors);
Kevin Lubick421ba882020-10-15 13:07:33 -04001004 var posPtr = copy1dArray(pos, 'HEAPF32');
Nathaniel Nifong23b0ed92020-03-04 15:43:50 -05001005 flags = flags || 0;
Kevin Lubick6bffe392020-04-02 15:24:15 -04001006 var localMatrixPtr = copy3x3MatrixToWasm(localMatrix);
Nathaniel Nifong23b0ed92020-03-04 15:43:50 -05001007
Kevin Lubicked962642021-02-02 08:18:11 -05001008 // Copy start and end to _scratchFourFloatsAPtr.
1009 var startEndPts = _scratchFourFloatsA['toTypedArray']();
1010 startEndPts.set(start);
1011 startEndPts.set(end, 2);
1012
1013 var lgs = CanvasKit.Shader._MakeLinearGradient(_scratchFourFloatsAPtr, cPtrInfo.colorPtr, cPtrInfo.colorType, posPtr,
Kevin Lubick421ba882020-10-15 13:07:33 -04001014 cPtrInfo.count, mode, flags, localMatrixPtr, colorSpace);
Nathaniel Nifong23b0ed92020-03-04 15:43:50 -05001015
Nathaniel Nifongd05fd0c2020-06-11 08:44:20 -04001016 freeArraysThatAreNotMallocedByUsers(cPtrInfo.colorPtr, colors);
Kevin Lubicke7b329e2020-06-05 15:58:01 -04001017 pos && freeArraysThatAreNotMallocedByUsers(posPtr, pos);
Nathaniel Nifong23b0ed92020-03-04 15:43:50 -05001018 return lgs;
Kevin Lubick9fe83912020-11-03 17:08:34 -05001019 };
Nathaniel Nifong23b0ed92020-03-04 15:43:50 -05001020
Kevin Lubick54c1b3d2020-10-07 16:09:22 -04001021 CanvasKit.Shader.MakeRadialGradient = function(center, radius, colors, pos, mode, localMatrix, flags, colorSpace) {
Kevin Lubicked962642021-02-02 08:18:11 -05001022 colorSpace = colorSpace || null;
Nathaniel Nifongd05fd0c2020-06-11 08:44:20 -04001023 var cPtrInfo = copyFlexibleColorArray(colors);
Kevin Lubick421ba882020-10-15 13:07:33 -04001024 var posPtr = copy1dArray(pos, 'HEAPF32');
Nathaniel Nifong23b0ed92020-03-04 15:43:50 -05001025 flags = flags || 0;
Kevin Lubick6bffe392020-04-02 15:24:15 -04001026 var localMatrixPtr = copy3x3MatrixToWasm(localMatrix);
Nathaniel Nifong23b0ed92020-03-04 15:43:50 -05001027
Kevin Lubicked962642021-02-02 08:18:11 -05001028 var rgs = CanvasKit.Shader._MakeRadialGradient(center[0], center[1], radius, cPtrInfo.colorPtr,
1029 cPtrInfo.colorType, posPtr, cPtrInfo.count, mode,
1030 flags, localMatrixPtr, colorSpace);
Nathaniel Nifong23b0ed92020-03-04 15:43:50 -05001031
Nathaniel Nifongd05fd0c2020-06-11 08:44:20 -04001032 freeArraysThatAreNotMallocedByUsers(cPtrInfo.colorPtr, colors);
Kevin Lubicke7b329e2020-06-05 15:58:01 -04001033 pos && freeArraysThatAreNotMallocedByUsers(posPtr, pos);
Nathaniel Nifong23b0ed92020-03-04 15:43:50 -05001034 return rgs;
Kevin Lubick9fe83912020-11-03 17:08:34 -05001035 };
Nathaniel Nifong23b0ed92020-03-04 15:43:50 -05001036
Kevin Lubick54c1b3d2020-10-07 16:09:22 -04001037 CanvasKit.Shader.MakeSweepGradient = function(cx, cy, colors, pos, mode, localMatrix, flags, startAngle, endAngle, colorSpace) {
Kevin Lubicked962642021-02-02 08:18:11 -05001038 colorSpace = colorSpace || null;
Nathaniel Nifongd05fd0c2020-06-11 08:44:20 -04001039 var cPtrInfo = copyFlexibleColorArray(colors);
Kevin Lubick421ba882020-10-15 13:07:33 -04001040 var posPtr = copy1dArray(pos, 'HEAPF32');
Dan Field3d44f732020-03-16 09:17:30 -07001041 flags = flags || 0;
1042 startAngle = startAngle || 0;
1043 endAngle = endAngle || 360;
Kevin Lubick6bffe392020-04-02 15:24:15 -04001044 var localMatrixPtr = copy3x3MatrixToWasm(localMatrix);
Dan Field3d44f732020-03-16 09:17:30 -07001045
Kevin Lubick421ba882020-10-15 13:07:33 -04001046 var sgs = CanvasKit.Shader._MakeSweepGradient(cx, cy, cPtrInfo.colorPtr, cPtrInfo.colorType, posPtr,
1047 cPtrInfo.count, mode,
1048 startAngle, endAngle, flags,
1049 localMatrixPtr, colorSpace);
Dan Field3d44f732020-03-16 09:17:30 -07001050
Nathaniel Nifongd05fd0c2020-06-11 08:44:20 -04001051 freeArraysThatAreNotMallocedByUsers(cPtrInfo.colorPtr, colors);
Kevin Lubicke7b329e2020-06-05 15:58:01 -04001052 pos && freeArraysThatAreNotMallocedByUsers(posPtr, pos);
Dan Field3d44f732020-03-16 09:17:30 -07001053 return sgs;
Kevin Lubick9fe83912020-11-03 17:08:34 -05001054 };
Dan Field3d44f732020-03-16 09:17:30 -07001055
Kevin Lubick54c1b3d2020-10-07 16:09:22 -04001056 CanvasKit.Shader.MakeTwoPointConicalGradient = function(start, startRadius, end, endRadius,
Kevin Lubick421ba882020-10-15 13:07:33 -04001057 colors, pos, mode, localMatrix, flags, colorSpace) {
Kevin Lubicked962642021-02-02 08:18:11 -05001058 colorSpace = colorSpace || null;
Nathaniel Nifongd05fd0c2020-06-11 08:44:20 -04001059 var cPtrInfo = copyFlexibleColorArray(colors);
Kevin Lubick421ba882020-10-15 13:07:33 -04001060 var posPtr = copy1dArray(pos, 'HEAPF32');
Nathaniel Nifong23b0ed92020-03-04 15:43:50 -05001061 flags = flags || 0;
Kevin Lubick6bffe392020-04-02 15:24:15 -04001062 var localMatrixPtr = copy3x3MatrixToWasm(localMatrix);
Nathaniel Nifong23b0ed92020-03-04 15:43:50 -05001063
Kevin Lubicked962642021-02-02 08:18:11 -05001064 // Copy start and end to _scratchFourFloatsAPtr.
1065 var startEndPts = _scratchFourFloatsA['toTypedArray']();
1066 startEndPts.set(start);
1067 startEndPts.set(end, 2);
1068
1069 var rgs = CanvasKit.Shader._MakeTwoPointConicalGradient(_scratchFourFloatsAPtr,
1070 startRadius, endRadius, cPtrInfo.colorPtr, cPtrInfo.colorType,
Nathaniel Nifongd05fd0c2020-06-11 08:44:20 -04001071 posPtr, cPtrInfo.count, mode, flags, localMatrixPtr, colorSpace);
Nathaniel Nifong23b0ed92020-03-04 15:43:50 -05001072
Nathaniel Nifongd05fd0c2020-06-11 08:44:20 -04001073 freeArraysThatAreNotMallocedByUsers(cPtrInfo.colorPtr, colors);
Kevin Lubicke7b329e2020-06-05 15:58:01 -04001074 pos && freeArraysThatAreNotMallocedByUsers(posPtr, pos);
Nathaniel Nifong23b0ed92020-03-04 15:43:50 -05001075 return rgs;
Kevin Lubick9fe83912020-11-03 17:08:34 -05001076 };
Nathaniel Nifong23b0ed92020-03-04 15:43:50 -05001077
Kevin Lubickf8823b52020-09-03 10:02:10 -04001078 // Clients can pass in a Float32Array with length 4 to this and the results
1079 // will be copied into that array. Otherwise, a new TypedArray will be allocated
1080 // and returned.
Kevin Lubick54c1b3d2020-10-07 16:09:22 -04001081 CanvasKit.Vertices.prototype.bounds = function(optionalOutputArray) {
Kevin Lubicked962642021-02-02 08:18:11 -05001082 this._bounds(_scratchFourFloatsAPtr);
1083 var ta = _scratchFourFloatsA['toTypedArray']();
Kevin Lubickf8823b52020-09-03 10:02:10 -04001084 if (optionalOutputArray) {
1085 optionalOutputArray.set(ta);
1086 return optionalOutputArray;
1087 }
1088 return ta.slice();
Kevin Lubick9fe83912020-11-03 17:08:34 -05001089 };
Kevin Lubickf8823b52020-09-03 10:02:10 -04001090
Kevin Lubickf5ea37f2019-02-28 10:06:18 -05001091 // Run through the JS files that are added at compile time.
1092 if (CanvasKit._extraInitializations) {
1093 CanvasKit._extraInitializations.forEach(function(init) {
1094 init();
1095 });
Kevin Lubickeb2f6b02018-11-29 15:07:02 -05001096 }
Kevin Lubickf5ea37f2019-02-28 10:06:18 -05001097}; // end CanvasKit.onRuntimeInitialized, that is, anything changing prototypes or dynamic.
Kevin Lubickeb2f6b02018-11-29 15:07:02 -05001098
Nathaniel Nifong1bedbeb2020-05-04 16:46:17 -04001099// Accepts an object holding two canvaskit colors.
1100// {
Kevin Lubick3d00e3a2020-10-02 14:59:28 -04001101// ambient: [r, g, b, a],
1102// spot: [r, g, b, a],
Nathaniel Nifong1bedbeb2020-05-04 16:46:17 -04001103// }
Kevin Lubicke7b329e2020-06-05 15:58:01 -04001104// Returns the same format. Note, if malloced colors are passed in, the memory
1105// housing the passed in colors passed in will be overwritten with the computed
1106// tonal colors.
Nathaniel Nifong1bedbeb2020-05-04 16:46:17 -04001107CanvasKit.computeTonalColors = function(tonalColors) {
Kevin Lubicke7b329e2020-06-05 15:58:01 -04001108 // copy the colors into WASM
Kevin Lubick6aa38692020-06-01 11:25:47 -04001109 var cPtrAmbi = copyColorToWasmNoScratch(tonalColors['ambient']);
1110 var cPtrSpot = copyColorToWasmNoScratch(tonalColors['spot']);
Kevin Lubicke7b329e2020-06-05 15:58:01 -04001111 // The output of this function will be the same pointers we passed in.
Nathaniel Nifong1bedbeb2020-05-04 16:46:17 -04001112 this._computeTonalColors(cPtrAmbi, cPtrSpot);
Kevin Lubicke7b329e2020-06-05 15:58:01 -04001113 // Read the results out.
Nathaniel Nifong1bedbeb2020-05-04 16:46:17 -04001114 var result = {
1115 'ambient': copyColorFromWasm(cPtrAmbi),
1116 'spot': copyColorFromWasm(cPtrSpot),
Kevin Lubickd9b9e5e2020-06-23 16:58:10 -04001117 };
Kevin Lubicke7b329e2020-06-05 15:58:01 -04001118 // If the user passed us malloced colors in here, we don't want to clean them up.
1119 freeArraysThatAreNotMallocedByUsers(cPtrAmbi, tonalColors['ambient']);
1120 freeArraysThatAreNotMallocedByUsers(cPtrSpot, tonalColors['spot']);
Nathaniel Nifong1bedbeb2020-05-04 16:46:17 -04001121 return result;
Kevin Lubickd9b9e5e2020-06-23 16:58:10 -04001122};
Nathaniel Nifong1bedbeb2020-05-04 16:46:17 -04001123
Kevin Lubickf5ea37f2019-02-28 10:06:18 -05001124CanvasKit.LTRBRect = function(l, t, r, b) {
Kevin Lubickf8823b52020-09-03 10:02:10 -04001125 return Float32Array.of(l, t, r, b);
Kevin Lubickd9b9e5e2020-06-23 16:58:10 -04001126};
Kevin Lubick1a05fce2018-11-20 12:51:16 -05001127
Kevin Lubickf5ea37f2019-02-28 10:06:18 -05001128CanvasKit.XYWHRect = function(x, y, w, h) {
Kevin Lubickf8823b52020-09-03 10:02:10 -04001129 return Float32Array.of(x, y, x+w, y+h);
1130};
1131
1132CanvasKit.LTRBiRect = function(l, t, r, b) {
1133 return Int32Array.of(l, t, r, b);
1134};
1135
1136CanvasKit.XYWHiRect = function(x, y, w, h) {
1137 return Int32Array.of(x, y, x+w, y+h);
Kevin Lubickd9b9e5e2020-06-23 16:58:10 -04001138};
Kevin Lubick1a05fce2018-11-20 12:51:16 -05001139
Kevin Lubickbe728012020-09-03 11:57:12 +00001140// RRectXY returns a TypedArray representing an RRect with the given rect and a radiusX and
1141// radiusY for all 4 corners.
Kevin Lubick7d644e12019-09-11 14:22:22 -04001142CanvasKit.RRectXY = function(rect, rx, ry) {
Kevin Lubickbe728012020-09-03 11:57:12 +00001143 return Float32Array.of(
Kevin Lubickf8823b52020-09-03 10:02:10 -04001144 rect[0], rect[1], rect[2], rect[3],
Kevin Lubickbe728012020-09-03 11:57:12 +00001145 rx, ry,
1146 rx, ry,
1147 rx, ry,
1148 rx, ry,
1149 );
Kevin Lubickd9b9e5e2020-06-23 16:58:10 -04001150};
Kevin Lubickf5ea37f2019-02-28 10:06:18 -05001151
Kevin Lubickf5ea37f2019-02-28 10:06:18 -05001152// data is a TypedArray or ArrayBuffer e.g. from fetch().then(resp.arrayBuffer())
Kevin Lubick6b921b72019-09-18 16:18:17 -04001153CanvasKit.MakeAnimatedImageFromEncoded = function(data) {
1154 data = new Uint8Array(data);
1155
1156 var iptr = CanvasKit._malloc(data.byteLength);
1157 CanvasKit.HEAPU8.set(data, iptr);
1158 var img = CanvasKit._decodeAnimatedImage(iptr, data.byteLength);
1159 if (!img) {
Kevin Lubick54c1b3d2020-10-07 16:09:22 -04001160 Debug('Could not decode animated image');
Kevin Lubick6b921b72019-09-18 16:18:17 -04001161 return null;
1162 }
1163 return img;
Kevin Lubick9fe83912020-11-03 17:08:34 -05001164};
Kevin Lubick6b921b72019-09-18 16:18:17 -04001165
1166// data is a TypedArray or ArrayBuffer e.g. from fetch().then(resp.arrayBuffer())
Kevin Lubickf5ea37f2019-02-28 10:06:18 -05001167CanvasKit.MakeImageFromEncoded = function(data) {
1168 data = new Uint8Array(data);
1169
1170 var iptr = CanvasKit._malloc(data.byteLength);
1171 CanvasKit.HEAPU8.set(data, iptr);
1172 var img = CanvasKit._decodeImage(iptr, data.byteLength);
1173 if (!img) {
Kevin Lubick54c1b3d2020-10-07 16:09:22 -04001174 Debug('Could not decode image');
Kevin Lubickf5ea37f2019-02-28 10:06:18 -05001175 return null;
1176 }
Kevin Lubickf5ea37f2019-02-28 10:06:18 -05001177 return img;
Kevin Lubick9fe83912020-11-03 17:08:34 -05001178};
Kevin Lubickf5ea37f2019-02-28 10:06:18 -05001179
Elliot Evans28796192020-06-15 12:53:27 -06001180// A variable to hold a canvasElement which can be reused once created the first time.
1181var memoizedCanvas2dElement = null;
1182
1183// Alternative to CanvasKit.MakeImageFromEncoded. Allows for CanvasKit users to take advantage of
1184// browser APIs to decode images instead of using codecs included in the CanvasKit wasm binary.
1185// Expects that the canvasImageSource has already loaded/decoded.
1186// CanvasImageSource reference: https://developer.mozilla.org/en-US/docs/Web/API/CanvasImageSource
1187CanvasKit.MakeImageFromCanvasImageSource = function(canvasImageSource) {
1188 var width = canvasImageSource.width;
1189 var height = canvasImageSource.height;
1190
1191 if (!memoizedCanvas2dElement) {
1192 memoizedCanvas2dElement = document.createElement('canvas');
1193 }
1194 memoizedCanvas2dElement.width = width;
1195 memoizedCanvas2dElement.height = height;
1196
1197 var ctx2d = memoizedCanvas2dElement.getContext('2d');
1198 ctx2d.drawImage(canvasImageSource, 0, 0);
1199
1200 var imageData = ctx2d.getImageData(0, 0, width, height);
1201
Kevin Lubickae0d3ff2020-11-18 11:23:15 -05001202 return CanvasKit.MakeImage({
1203 'width': width,
1204 'height': height,
1205 'alphaType': CanvasKit.AlphaType.Unpremul,
1206 'colorType': CanvasKit.ColorType.RGBA_8888,
1207 'colorSpace': CanvasKit.ColorSpace.SRGB
1208 }, imageData.data, 4 * width);
Kevin Lubick9fe83912020-11-03 17:08:34 -05001209};
Elliot Evans28796192020-06-15 12:53:27 -06001210
Kevin Lubickae0d3ff2020-11-18 11:23:15 -05001211// pixels may be an array but Uint8Array or Uint8ClampedArray is recommended,
1212// with the bytes representing the pixel values.
Kevin Lubickeda0b432019-12-02 08:26:48 -05001213// (e.g. each set of 4 bytes could represent RGBA values for a single pixel).
Kevin Lubickae0d3ff2020-11-18 11:23:15 -05001214CanvasKit.MakeImage = function(info, pixels, bytesPerRow) {
1215 var pptr = CanvasKit._malloc(pixels.length);
1216 CanvasKit.HEAPU8.set(pixels, pptr); // We always want to copy the bytes into the WASM heap.
Kevin Lubickeda0b432019-12-02 08:26:48 -05001217 // No need to _free pptr, Image takes it with SkData::MakeFromMalloc
Kevin Lubickae0d3ff2020-11-18 11:23:15 -05001218 return CanvasKit._MakeImage(info, pptr, pixels.length, bytesPerRow);
Kevin Lubick9fe83912020-11-03 17:08:34 -05001219};
Kevin Lubickf5ea37f2019-02-28 10:06:18 -05001220
Nathaniel Nifongd05fd0c2020-06-11 08:44:20 -04001221// Colors may be a Uint32Array of int colors, a Flat Float32Array of float colors
1222// or a 2d Array of Float32Array(4) (deprecated)
Kevin Lubicke7c1a732020-12-04 09:10:39 -05001223// the underlying Skia function accepts only int colors so it is recommended
Nathaniel Nifongd05fd0c2020-06-11 08:44:20 -04001224// to pass an array of int colors to avoid an extra conversion.
Kevin Lubick54c1b3d2020-10-07 16:09:22 -04001225CanvasKit.MakeVertices = function(mode, positions, textureCoordinates, colors,
1226 indices, isVolatile) {
Kevin Lubicke7c1a732020-12-04 09:10:39 -05001227 // Default isVolatile to true if not set
Kevin Lubickb3574c92019-03-06 08:25:36 -05001228 isVolatile = isVolatile === undefined ? true : isVolatile;
Kevin Lubickd6ba7252019-06-03 14:38:05 -04001229 var idxCount = (indices && indices.length) || 0;
1230
1231 var flags = 0;
1232 // These flags are from SkVertices.h and should be kept in sync with those.
1233 if (textureCoordinates && textureCoordinates.length) {
1234 flags |= (1 << 0);
1235 }
1236 if (colors && colors.length) {
1237 flags |= (1 << 1);
1238 }
Kevin Lubickd6ba7252019-06-03 14:38:05 -04001239 if (!isVolatile) {
Mike Reed5caf9352020-03-02 14:57:09 -05001240 flags |= (1 << 2);
Kevin Lubickd6ba7252019-06-03 14:38:05 -04001241 }
1242
Kevin Lubicke7c1a732020-12-04 09:10:39 -05001243 var builder = new CanvasKit._VerticesBuilder(mode, positions.length / 2, idxCount, flags);
Kevin Lubickd6ba7252019-06-03 14:38:05 -04001244
Kevin Lubicke7c1a732020-12-04 09:10:39 -05001245 copy1dArray(positions, 'HEAPF32', builder.positions());
Kevin Lubickd6ba7252019-06-03 14:38:05 -04001246 if (builder.texCoords()) {
Kevin Lubicke7c1a732020-12-04 09:10:39 -05001247 copy1dArray(textureCoordinates, 'HEAPF32', builder.texCoords());
Kevin Lubickd6ba7252019-06-03 14:38:05 -04001248 }
1249 if (builder.colors()) {
Kevin Lubickbe728012020-09-03 11:57:12 +00001250 copy1dArray(assureIntColors(colors), 'HEAPU32', builder.colors());
Kevin Lubickd6ba7252019-06-03 14:38:05 -04001251 }
Kevin Lubickd6ba7252019-06-03 14:38:05 -04001252 if (builder.indices()) {
Kevin Lubickbe728012020-09-03 11:57:12 +00001253 copy1dArray(indices, 'HEAPU16', builder.indices());
Kevin Lubickd6ba7252019-06-03 14:38:05 -04001254 }
Kevin Lubickb3574c92019-03-06 08:25:36 -05001255
Kevin Lubickd6ba7252019-06-03 14:38:05 -04001256 // Create the vertices, which owns the memory that the builder had allocated.
1257 return builder.detach();
Kevin Lubicka4f218d2020-01-14 08:39:09 -05001258};