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