blob: 938ef3eda9a3ee304978e3782006a58c1224f0bf [file] [log] [blame]
Kevin Lubick217056c2018-09-20 17:39:31 -04001// Adds JS functions to augment the CanvasKit interface.
2// For example, if there is a wrapper around the C++ call or logic to allow
3// chaining, it should go here.
4(function(CanvasKit){
5 // CanvasKit.onRuntimeInitialized is called after the WASM library has loaded.
6 // Anything that modifies an exposed class (e.g. SkPath) should be set
7 // after onRuntimeInitialized, otherwise, it can happen outside of that scope.
8 CanvasKit.onRuntimeInitialized = function() {
9 // All calls to 'this' need to go in externs.js so closure doesn't minify them away.
10 CanvasKit.SkPath.prototype.addPath = function() {
11 // Takes 1, 2, or 10 args, where the first arg is always the path.
12 // The options for the remaining args are:
13 // - an array of 9 parameters
14 // - the 9 parameters of a full Matrix
15 if (arguments.length === 1) {
16 // Add path, unchanged. Use identify matrix
17 this._addPath(arguments[0], 1, 0, 0,
18 0, 1, 0,
19 0, 0, 1);
20 } else if (arguments.length === 2) {
21 // User provided the 9 params of a full matrix as an array.
22 var sm = arguments[1];
23 this._addPath(arguments[0], a[1], a[2], a[3],
24 a[4], a[5], a[6],
25 a[7], a[8], a[9]);
26 } else if (arguments.length === 10) {
27 // User provided the 9 params of a (full) matrix directly.
28 // These are in the same order as what Skia expects.
29 var a = arguments;
30 this._addPath(arguments[0], a[1], a[2], a[3],
31 a[4], a[5], a[6],
32 a[7], a[8], a[9]);
33 } else {
34 console.err('addPath expected to take 1, 2, or 10 args. Got ' + arguments.length);
35 return null;
36 }
37 return this;
38 };
39
40 CanvasKit.SkPath.prototype.arcTo = function(x1, y1, x2, y2, radius) {
41 this._arcTo(x1, y1, x2, y2, radius);
42 return this;
43 };
44
45 CanvasKit.SkPath.prototype.close = function() {
46 this._close();
47 return this;
48 };
49
50 CanvasKit.SkPath.prototype.conicTo = function(x1, y1, x2, y2, w) {
51 this._conicTo(x1, y1, x2, y2, w);
52 return this;
53 };
54
55 CanvasKit.SkPath.prototype.cubicTo = function(cp1x, cp1y, cp2x, cp2y, x, y) {
56 this._cubicTo(cp1x, cp1y, cp2x, cp2y, x, y);
57 return this;
58 };
59
60 CanvasKit.SkPath.prototype.lineTo = function(x, y) {
61 this._lineTo(x, y);
62 return this;
63 };
64
65 CanvasKit.SkPath.prototype.moveTo = function(x, y) {
66 this._moveTo(x, y);
67 return this;
68 };
69
70 CanvasKit.SkPath.prototype.op = function(otherPath, op) {
71 if (this._op(otherPath, op)) {
72 return this;
73 }
74 return null;
75 };
76
77 CanvasKit.SkPath.prototype.quadTo = function(cpx, cpy, x, y) {
78 this._quadTo(cpx, cpy, x, y);
79 return this;
80 };
81
82 CanvasKit.SkPath.prototype.simplify = function() {
83 if (this._simplify()) {
84 return this;
85 }
86 return null;
87 };
88
89 CanvasKit.SkPath.prototype.transform = function() {
90 // Takes 1 or 9 args
91 if (arguments.length === 1) {
92 // argument 1 should be a 9 element array.
93 var a = arguments[0];
94 this._transform(a[0], a[1], a[2],
95 a[3], a[4], a[5],
96 a[6], a[7], a[8]);
97 } else if (arguments.length === 9) {
98 // these arguments are the 9 members of the matrix
99 var a = arguments;
100 this._transform(a[0], a[1], a[2],
101 a[3], a[4], a[5],
102 a[6], a[7], a[8]);
103 } else {
104 console.err('transform expected to take 1 or 9 arguments. Got ' + arguments.length);
105 return null;
106 }
107 return this;
108 };
Kevin Lubick53965c92018-10-11 08:51:55 -0400109
Kevin Lubick3d99b1e2018-10-16 10:15:01 -0400110 if (CanvasKit.gpu) {
111 CanvasKit.getWebGLSurface = function(htmlID) {
112 var canvas = document.getElementById(htmlID);
113 if (!canvas) {
114 throw 'Canvas with id ' + htmlID + ' was not found';
115 }
116 // Maybe better to use clientWidth/height. See:
117 // https://webglfundamentals.org/webgl/lessons/webgl-anti-patterns.html
118 return this._getWebGLSurface(htmlID, canvas.width, canvas.height);
119 };
120
121 CanvasKit.SkSurface.prototype.flush = function() {
122 this._flush();
Kevin Lubick53965c92018-10-11 08:51:55 -0400123 }
Kevin Lubick3d99b1e2018-10-16 10:15:01 -0400124 } else {
125 CanvasKit.getRasterN32PremulSurface = function(htmlID) {
126 var canvas = document.getElementById(htmlID);
127 if (!canvas) {
128 throw 'Canvas with id ' + htmlID + ' was not found';
129 }
130 // Maybe better to use clientWidth/height. See:
131 // https://webglfundamentals.org/webgl/lessons/webgl-anti-patterns.html
132 var surface = this._getRasterN32PremulSurface(canvas.width, canvas.height);
133 if (surface) {
134 surface.canvas = canvas;
135 surface._width = canvas.width;
136 surface._height = canvas.height;
137 surface._pixelLen = surface._width * surface._height * 4; // it's 8888
138 // Allocate the buffer of pixels to be used to draw back and forth.
139 surface._pixelPtr = CanvasKit._malloc(surface._pixelLen);
140 }
141 return surface;
142 };
Kevin Lubick53965c92018-10-11 08:51:55 -0400143
Kevin Lubick3d99b1e2018-10-16 10:15:01 -0400144 CanvasKit.SkSurface.prototype.flush = function() {
145 this._flush();
146 var success = this._readPixels(this._width, this._height, this._pixelPtr);
147 if (!success) {
148 console.err('could not read pixels');
149 return;
150 }
Kevin Lubick53965c92018-10-11 08:51:55 -0400151
Kevin Lubick3d99b1e2018-10-16 10:15:01 -0400152 var pixels = new Uint8ClampedArray(CanvasKit.buffer, this._pixelPtr, this._pixelLen);
153 var imageData = new ImageData(pixels, this._width, this._height);
Kevin Lubick53965c92018-10-11 08:51:55 -0400154
Kevin Lubick3d99b1e2018-10-16 10:15:01 -0400155 this.canvas.getContext('2d').putImageData(imageData, 0, 0);
156 };
Kevin Lubick217056c2018-09-20 17:39:31 -0400157 }
Kevin Lubick3d99b1e2018-10-16 10:15:01 -0400158 } // end CanvasKit.onRuntimeInitialized, that is, anything changing prototypes or dynamic.
Kevin Lubick53965c92018-10-11 08:51:55 -0400159
Kevin Lubick217056c2018-09-20 17:39:31 -0400160 // Likely only used for tests.
161 CanvasKit.LTRBRect = function(l, t, r, b) {
162 return {
163 fLeft: l,
164 fTop: t,
165 fRight: r,
166 fBottom: b,
167 };
168 }
169
170 CanvasKit.MakeSkDashPathEffect = function(intervals, phase) {
171 if (!phase) {
172 phase = 0;
173 }
174 if (!intervals.length || intervals.length % 2 === 1) {
175 throw 'Intervals array must have even length';
176 }
177 if (!(intervals instanceof Float32Array)) {
178 intervals = Float32Array.from(intervals);
179 }
180 var BYTES_PER_ELEMENT = 4; // Float32Array always has 4 bytes per element
181 var ptr = CanvasKit._malloc(intervals.length * BYTES_PER_ELEMENT);
182 CanvasKit.HEAPF32.set(intervals, ptr / BYTES_PER_ELEMENT);
183 return CanvasKit._MakeSkDashPathEffect(ptr, intervals.length, phase);
184 }
185
186}(Module)); // When this file is loaded in, the high level object is "Module";