blob: 5e2d72452b60724e3bda151cbceafef0449d3499 [file] [log] [blame]
Kevin Lubick217056c2018-09-20 17:39:31 -04001/*
2 * This externs file prevents the Closure JS compiler from minifying away
3 * names of objects created by Emscripten.
4 * Basically, by defining empty objects and functions here, Closure will
5 * know not to rename them. This is needed because of our pre-js files,
6 * that is, the JS we hand-write to bundle into the output. That JS will be
7 * hit by the closure compiler and thus needs to know about what functions
8 * have special names and should not be minified.
9 *
10 * Emscripten does not support automatically generating an externs file, so we
11 * do it by hand. The general process is to write some JS code, and then put any
12 * calls to CanvasKit or related things in here. Running ./compile.sh and then
13 * looking at the minified results or running the Release trybot should
14 * verify nothing was missed. Optionally, looking directly at the minified
15 * pathkit.js can be useful when developing locally.
16 *
17 * Docs:
18 * https://github.com/cljsjs/packages/wiki/Creating-Externs
19 * https://github.com/google/closure-compiler/wiki/Types-in-the-Closure-Type-System
20 *
21 * Example externs:
22 * https://github.com/google/closure-compiler/tree/master/externs
23 */
24
25var CanvasKit = {
26 // public API (i.e. things we declare in the pre-js file)
Kevin Lubick006a6f32018-10-19 14:34:34 -040027 Color: function() {},
28 /** @return {CanvasKit.SkRect} */
29 LTRBRect: function() {},
Kevin Lubick61ef7b22018-11-27 13:26:59 -050030 MakeBlurMaskFilter: function() {},
Kevin Lubick006a6f32018-10-19 14:34:34 -040031 MakeCanvas: function() {},
32 MakeCanvasSurface: function() {},
Kevin Lubickb5ae3b52018-11-03 07:51:19 -040033 MakeImageShader: function() {},
Kevin Lubickeb2f6b02018-11-29 15:07:02 -050034 /** @return {LinearCanvasGradient} */
Kevin Lubickb5ae3b52018-11-03 07:51:19 -040035 MakeLinearGradientShader: function() {},
Kevin Lubick134be1d2018-10-30 15:05:04 -040036 MakeNimaActor: function() {},
Kevin Lubick61ef7b22018-11-27 13:26:59 -050037 MakeRadialGradientShader: function() {},
38 MakeSWCanvasSurface: function() {},
Kevin Lubick006a6f32018-10-19 14:34:34 -040039 MakeSkDashPathEffect: function() {},
Kevin Lubickb5ae3b52018-11-03 07:51:19 -040040 MakeSkVertices: function() {},
Kevin Lubick006a6f32018-10-19 14:34:34 -040041 MakeSurface: function() {},
Kevin Lubickeb2f6b02018-11-29 15:07:02 -050042 /** @return {RadialCanvasGradient} */
43 MakeTwoPointConicalGradientShader: function() {},
Kevin Lubick61ef7b22018-11-27 13:26:59 -050044 MakeWebGLCanvasSurface: function() {},
Kevin Lubick217056c2018-09-20 17:39:31 -040045 currentContext: function() {},
Kevin Lubick61ef7b22018-11-27 13:26:59 -050046 getColorComponents: function() {},
Kevin Lubick12c0e502018-11-28 12:51:56 -050047 getSkDataBytes: function() {},
Kevin Lubick006a6f32018-10-19 14:34:34 -040048 initFonts: function() {},
Kevin Lubick12c0e502018-11-28 12:51:56 -050049 multiplyByAlpha: function() {},
Kevin Lubick006a6f32018-10-19 14:34:34 -040050 setCurrentContext: function() {},
Kevin Lubick217056c2018-09-20 17:39:31 -040051
52 // private API (i.e. things declared in the bindings that we use
53 // in the pre-js file)
Kevin Lubickb5ae3b52018-11-03 07:51:19 -040054 _MakeImageShader: function() {},
55 _MakeLinearGradientShader: function() {},
Kevin Lubick134be1d2018-10-30 15:05:04 -040056 _MakeNimaActor: function() {},
Kevin Lubickb5ae3b52018-11-03 07:51:19 -040057 _MakeRadialGradientShader: function() {},
Kevin Lubick006a6f32018-10-19 14:34:34 -040058 _MakeSkDashPathEffect: function() {},
Kevin Lubickb5ae3b52018-11-03 07:51:19 -040059 _MakeSkVertices: function() {},
Kevin Lubickeb2f6b02018-11-29 15:07:02 -050060 _MakeTwoPointConicalGradientShader: function() {},
Kevin Lubickea905ec2018-11-30 14:05:58 -050061 _getRasterDirectSurface: function() {},
Kevin Lubick134be1d2018-10-30 15:05:04 -040062 _getRasterN32PremulSurface: function() {},
63 _getWebGLSurface: function() {},
Kevin Lubick217056c2018-09-20 17:39:31 -040064
Kevin Lubick1a05fce2018-11-20 12:51:16 -050065 // The testing object is meant to expose internal functions
66 // for more fine-grained testing, e.g. parseColor
67 _testing: {},
68
Kevin Lubick217056c2018-09-20 17:39:31 -040069 // Objects and properties on CanvasKit
70
Kevin Lubick134be1d2018-10-30 15:05:04 -040071 NimaActor: {
72 // public API (from C++ bindings)
73 duration: function() {},
74 getAnimationNames: function() {},
75 render: function() {},
76 seek: function() {},
77 setAnimationByIndex: function() {},
78 setAnimationByName: function() {},
79
80 // private API
81 },
82
Kevin Lubick006a6f32018-10-19 14:34:34 -040083 SkCanvas: {
84 // public API (from C++ bindings)
85 clear: function() {},
Kevin Lubickeb2f6b02018-11-29 15:07:02 -050086 clipPath: function() {},
Kevin Lubick006a6f32018-10-19 14:34:34 -040087 drawPaint: function() {},
88 drawPath: function() {},
Kevin Lubick12c0e502018-11-28 12:51:56 -050089 drawRect: function() {},
Kevin Lubick61ef7b22018-11-27 13:26:59 -050090 drawShadow: function() {},
Kevin Lubick12c0e502018-11-28 12:51:56 -050091 drawText: function() {},
92 drawVertices: function() {},
Kevin Lubick006a6f32018-10-19 14:34:34 -040093 flush: function() {},
Kevin Lubickeb2f6b02018-11-29 15:07:02 -050094 restore: function() {},
Kevin Lubick006a6f32018-10-19 14:34:34 -040095 rotate: function() {},
96 save: function() {},
97 scale: function() {},
98 setMatrix: function() {},
99 skew: function() {},
100 translate: function() {},
101
102 // private API
103 delete: function() {},
104 },
105
106 SkImage: {
Alexander Khovansky3e119332018-11-15 02:01:19 +0300107 // private API
108 _encodeToData: function() {},
109 _encodeToDataWithFormat: function() {},
Kevin Lubick006a6f32018-10-19 14:34:34 -0400110 },
111
Kevin Lubick1a05fce2018-11-20 12:51:16 -0500112 SkMatrix: {
Kevin Lubickb9db3902018-11-26 11:47:54 -0500113 identity: function() {},
114 mapPoints: function() {},
115 multiply: function() {},
Kevin Lubick1a05fce2018-11-20 12:51:16 -0500116 rotated: function() {},
Kevin Lubickb9db3902018-11-26 11:47:54 -0500117 scaled: function() {},
118 skewed: function() {},
119 translated: function() {},
120 },
121
122 SkPaint: {
123 // public API (from C++ bindings)
124 /** @return {CanvasKit.SkPaint} */
125 copy: function() {},
Kevin Lubick12c0e502018-11-28 12:51:56 -0500126 getBlendMode: function() {},
Kevin Lubick61ef7b22018-11-27 13:26:59 -0500127 getColor: function() {},
Kevin Lubickb9db3902018-11-26 11:47:54 -0500128 getStrokeCap: function() {},
129 getStrokeJoin: function() {},
130 getStrokeMiter: function() {},
131 getStrokeWidth: function() {},
132 getTextSize: function() {},
133 measureText: function() {},
134 setAntiAlias: function() {},
Kevin Lubick12c0e502018-11-28 12:51:56 -0500135 setBlendMode: function() {},
Kevin Lubickb9db3902018-11-26 11:47:54 -0500136 setColor: function() {},
Kevin Lubick61ef7b22018-11-27 13:26:59 -0500137 setMaskFilter: function() {},
Kevin Lubickb9db3902018-11-26 11:47:54 -0500138 setPathEffect: function() {},
139 setShader: function() {},
140 setStrokeCap: function() {},
141 setStrokeJoin: function() {},
142 setStrokeMiter: function() {},
143 setStrokeWidth: function() {},
144 setStyle: function() {},
145 setTextSize: function() {},
146
147 //private API
148 delete: function() {},
Kevin Lubick1a05fce2018-11-20 12:51:16 -0500149 },
150
Kevin Lubick006a6f32018-10-19 14:34:34 -0400151 SkPath: {
152 // public API (from C++ bindings)
Kevin Lubickb9db3902018-11-26 11:47:54 -0500153 computeTightBounds: function() {},
154 /** @return {CanvasKit.SkPath} */
155 copy: function() {},
156 countPoints: function() {},
157 equals: function() {},
158 getBounds: function() {},
159 getFillType: function() {},
160 getPoint: function() {},
161 setFillType: function() {},
162 toSVGString: function() {},
Kevin Lubick006a6f32018-10-19 14:34:34 -0400163
164 // private API
Kevin Lubick1a05fce2018-11-20 12:51:16 -0500165 _addArc: function() {},
Kevin Lubick006a6f32018-10-19 14:34:34 -0400166 _addPath: function() {},
Kevin Lubick1a05fce2018-11-20 12:51:16 -0500167 _addRect: function() {},
Alexander Khovansky3e119332018-11-15 02:01:19 +0300168 _arc: function() {},
Kevin Lubick006a6f32018-10-19 14:34:34 -0400169 _arcTo: function() {},
170 _close: function() {},
171 _conicTo: function() {},
172 _cubicTo: function() {},
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400173 _dash: function() {},
Kevin Lubick006a6f32018-10-19 14:34:34 -0400174 _lineTo: function() {},
175 _moveTo: function() {},
176 _op: function() {},
177 _quadTo: function() {},
178 _rect: function() {},
179 _simplify: function() {},
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400180 _stroke: function() {},
Kevin Lubick006a6f32018-10-19 14:34:34 -0400181 _transform: function() {},
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400182 _trim: function() {},
Kevin Lubick006a6f32018-10-19 14:34:34 -0400183 delete: function() {},
Kevin Lubickb9db3902018-11-26 11:47:54 -0500184 dump: function() {},
185 dumpHex: function() {},
Kevin Lubick006a6f32018-10-19 14:34:34 -0400186 },
187
188 SkRect: {
189 fLeft: {},
190 fTop: {},
191 fRight: {},
192 fBottom: {},
193 },
194
195 SkSurface: {
196 // public API (from C++ bindings)
197 /** @return {CanvasKit.SkCanvas} */
198 getCanvas: function() {},
199 /** @return {CanvasKit.SkImage} */
200 makeImageSnapshot: function() {},
201
202 // private API
203 _flush: function() {},
204 _getRasterN32PremulSurface: function() {},
205 _readPixels: function() {},
206 delete: function() {},
207 },
208
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400209 SkVertices: {
210 // public API (from C++ bindings)
Kevin Lubick12c0e502018-11-28 12:51:56 -0500211 bounds: function() {},
212 mode: function() {},
213 uniqueID: function() {},
214 vertexCount: function() {},
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400215
216 // private API
217 /** @return {CanvasKit.SkVertices} */
218 _applyBones: function() {},
219 },
220
Kevin Lubick006a6f32018-10-19 14:34:34 -0400221 // Constants and Enums
222 gpu: {},
223 skottie: {},
Kevin Lubick006a6f32018-10-19 14:34:34 -0400224
Kevin Lubick61ef7b22018-11-27 13:26:59 -0500225 TRANSPARENT: {},
226 RED: {},
227 BLUE: {},
228 YELLOW: {},
229 CYAN: {},
230 BLACK: {},
Kevin Lubickea905ec2018-11-30 14:05:58 -0500231 WHITE: {},
232
233 AlphaType: {
234 Opaque: {},
235 Premul: {},
236 Unpremul: {},
237 },
Kevin Lubick61ef7b22018-11-27 13:26:59 -0500238
239 BlendMode: {
240 Clear: {},
241 Src: {},
242 Dst: {},
243 SrcOver: {},
244 DstOver: {},
245 SrcIn: {},
246 DstIn: {},
247 SrcOut: {},
248 DstOut: {},
249 SrcATop: {},
250 DstATop: {},
251 Xor: {},
252 Plus: {},
253 Modulate: {},
254 Screen: {},
255 Overlay: {},
256 Darken: {},
257 Lighten: {},
258 ColorDodge: {},
259 ColorBurn: {},
260 HardLight: {},
261 SoftLight: {},
262 Difference: {},
263 Exclusion: {},
264 Multiply: {},
265 Hue: {},
266 Saturation: {},
267 Color: {},
268 Luminosity: {},
269 },
270
271 BlurStyle: {
272 Normal: {},
273 Solid: {},
274 Outer: {},
275 Inner: {},
276 },
277
Kevin Lubickeb2f6b02018-11-29 15:07:02 -0500278 ClipOp: {
279 Difference: {},
280 Intersect: {},
281 },
282
Kevin Lubickea905ec2018-11-30 14:05:58 -0500283 ColorType: {
284 Alpha_8: {},
285 RGB_565: {},
286 ARGB_4444: {},
287 RGBA_8888: {},
288 RGB_888x: {},
289 BGRA_8888: {},
290 RGBA_1010102: {},
291 RGB_101010x: {},
292 Gray_8: {},
293 RGBA_F16: {},
294 RGBA_F32: {},
295 },
296
Kevin Lubick006a6f32018-10-19 14:34:34 -0400297 FillType: {
Kevin Lubick1a05fce2018-11-20 12:51:16 -0500298 Winding: {},
299 EvenOdd: {},
300 InverseWinding: {},
301 InverseEvenOdd: {},
Kevin Lubick006a6f32018-10-19 14:34:34 -0400302 },
303
Alexander Khovansky3e119332018-11-15 02:01:19 +0300304 ImageFormat: {
305 PNG: {},
306 JPEG: {},
307 },
308
Kevin Lubickb9db3902018-11-26 11:47:54 -0500309 PaintStyle: {
310 Fill: {},
311 Stroke: {},
312 StrokeAndFill: {},
313 },
314
Kevin Lubickeb2f6b02018-11-29 15:07:02 -0500315 PathOp: {
316 Difference: {},
317 Intersect: {},
318 Union: {},
319 XOR: {},
320 ReverseDifference: {},
321 },
322
Kevin Lubickb9db3902018-11-26 11:47:54 -0500323 StrokeCap: {
324 Butt: {},
325 Round: {},
326 Square: {},
327 },
328
329 StrokeJoin: {
330 Miter: {},
331 Round: {},
332 Bevel: {},
333 },
334
Kevin Lubickeb2f6b02018-11-29 15:07:02 -0500335 TileMode: {
336 Clamp: {},
337 Repeat: {},
338 Mirror: {},
339 },
340
341 VertexMode: {
342 Triangles: {},
343 TrianglesStrip: {},
344 TriangleFan: {},
345 },
346
Kevin Lubick006a6f32018-10-19 14:34:34 -0400347 // Things Enscriptem adds for us
348
Kevin Lubick53965c92018-10-11 08:51:55 -0400349 /** Represents the heap of the WASM code
350 * @type {ArrayBuffer}
351 */
352 buffer: {},
353 /**
354 * @type {Float32Array}
355 */
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400356 HEAPF32: {},
Kevin Lubick53965c92018-10-11 08:51:55 -0400357 /**
358 * @type {Uint8Array}
359 */
360 HEAPU8: {},
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400361 /**
362 * @type {Uint16Array}
363 */
364 HEAPU16: {},
365 /**
366 * @type {Int32Array}
367 */
368 HEAP32: {},
Kevin Lubick53965c92018-10-11 08:51:55 -0400369
Kevin Lubick006a6f32018-10-19 14:34:34 -0400370 _malloc: function() {},
371 _free: function() {},
372 onRuntimeInitialized: function() {},
373};
Kevin Lubick217056c2018-09-20 17:39:31 -0400374
Kevin Lubick006a6f32018-10-19 14:34:34 -0400375// Public API things that are newly declared in the JS should go here.
376// It's not enough to declare them above, because closure can still erase them
377// unless they go on the prototype.
Kevin Lubick1a05fce2018-11-20 12:51:16 -0500378CanvasKit.SkPath.prototype.addArc = function() {};
Kevin Lubick217056c2018-09-20 17:39:31 -0400379CanvasKit.SkPath.prototype.addPath = function() {};
Kevin Lubick1a05fce2018-11-20 12:51:16 -0500380CanvasKit.SkPath.prototype.addRect = function() {};
Alexander Khovansky3e119332018-11-15 02:01:19 +0300381CanvasKit.SkPath.prototype.arc = function() {};
Kevin Lubick006a6f32018-10-19 14:34:34 -0400382CanvasKit.SkPath.prototype.arcTo = function() {};
Kevin Lubick217056c2018-09-20 17:39:31 -0400383CanvasKit.SkPath.prototype.close = function() {};
Kevin Lubick006a6f32018-10-19 14:34:34 -0400384CanvasKit.SkPath.prototype.conicTo = function() {};
385CanvasKit.SkPath.prototype.cubicTo = function() {};
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400386CanvasKit.SkPath.prototype.dash = function() {};
Kevin Lubick006a6f32018-10-19 14:34:34 -0400387CanvasKit.SkPath.prototype.lineTo = function() {};
388CanvasKit.SkPath.prototype.moveTo = function() {};
389CanvasKit.SkPath.prototype.op = function() {};
390CanvasKit.SkPath.prototype.quadTo = function() {};
391CanvasKit.SkPath.prototype.rect = function() {};
Kevin Lubick217056c2018-09-20 17:39:31 -0400392CanvasKit.SkPath.prototype.simplify = function() {};
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400393CanvasKit.SkPath.prototype.stroke = function() {};
Kevin Lubick217056c2018-09-20 17:39:31 -0400394CanvasKit.SkPath.prototype.transform = function() {};
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400395CanvasKit.SkPath.prototype.trim = function() {};
Kevin Lubick217056c2018-09-20 17:39:31 -0400396
Kevin Lubick53965c92018-10-11 08:51:55 -0400397CanvasKit.SkSurface.prototype.flush = function() {};
Kevin Lubick5b90b842018-10-17 07:57:18 -0400398CanvasKit.SkSurface.prototype.dispose = function() {};
Kevin Lubick53965c92018-10-11 08:51:55 -0400399
Kevin Lubick12c0e502018-11-28 12:51:56 -0500400/** @return {CanvasKit.SkVertices} */
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400401CanvasKit.SkVertices.prototype.applyBones = function() {};
402
Alexander Khovansky3e119332018-11-15 02:01:19 +0300403CanvasKit.SkImage.prototype.encodeToData = function() {};
404
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400405// Define StrokeOpts object
406var StrokeOpts = {};
407StrokeOpts.prototype.width;
408StrokeOpts.prototype.miter_limit;
409StrokeOpts.prototype.cap;
410StrokeOpts.prototype.join;
411
Kevin Lubickeb2f6b02018-11-29 15:07:02 -0500412// Define everything created in the canvas2d spec here
Kevin Lubickb9db3902018-11-26 11:47:54 -0500413var HTMLCanvas = {};
414HTMLCanvas.prototype.getContext = function() {};
415HTMLCanvas.prototype.toDataURL = function() {};
416HTMLCanvas.prototype.dispose = function() {};
417
418var CanvasRenderingContext2D = {};
419CanvasRenderingContext2D.prototype.addHitRegion = function() {};
420CanvasRenderingContext2D.prototype.arc = function() {};
421CanvasRenderingContext2D.prototype.arcTo = function() {};
422CanvasRenderingContext2D.prototype.beginPath = function() {};
423CanvasRenderingContext2D.prototype.bezierCurveTo = function() {};
424CanvasRenderingContext2D.prototype.clearHitRegions = function() {};
Kevin Lubick12c0e502018-11-28 12:51:56 -0500425CanvasRenderingContext2D.prototype.clearRect = function() {};
Kevin Lubickeb2f6b02018-11-29 15:07:02 -0500426CanvasRenderingContext2D.prototype.clip = function() {};
Kevin Lubickb9db3902018-11-26 11:47:54 -0500427CanvasRenderingContext2D.prototype.closePath = function() {};
Kevin Lubickeb2f6b02018-11-29 15:07:02 -0500428CanvasRenderingContext2D.prototype.createLinearGradient = function() {};
429CanvasRenderingContext2D.prototype.createRadialGradient = function() {};
Kevin Lubickb9db3902018-11-26 11:47:54 -0500430CanvasRenderingContext2D.prototype.drawFocusIfNeeded = function() {};
431CanvasRenderingContext2D.prototype.ellipse = function() {};
Kevin Lubick61ef7b22018-11-27 13:26:59 -0500432CanvasRenderingContext2D.prototype.fill = function() {};
Kevin Lubick12c0e502018-11-28 12:51:56 -0500433CanvasRenderingContext2D.prototype.fillRect = function() {};
Kevin Lubickb9db3902018-11-26 11:47:54 -0500434CanvasRenderingContext2D.prototype.fillText = function() {};
Kevin Lubick12c0e502018-11-28 12:51:56 -0500435CanvasRenderingContext2D.prototype.getLineDash = function() {};
Kevin Lubickb9db3902018-11-26 11:47:54 -0500436CanvasRenderingContext2D.prototype.lineTo = function() {};
437CanvasRenderingContext2D.prototype.measureText = function() {};
438CanvasRenderingContext2D.prototype.moveTo = function() {};
439CanvasRenderingContext2D.prototype.quadraticCurveTo = function() {};
440CanvasRenderingContext2D.prototype.rect = function() {};
441CanvasRenderingContext2D.prototype.removeHitRegion = function() {};
442CanvasRenderingContext2D.prototype.resetTransform = function() {};
Kevin Lubick61ef7b22018-11-27 13:26:59 -0500443CanvasRenderingContext2D.prototype.restore = function() {};
Kevin Lubickb9db3902018-11-26 11:47:54 -0500444CanvasRenderingContext2D.prototype.rotate = function() {};
Kevin Lubick61ef7b22018-11-27 13:26:59 -0500445CanvasRenderingContext2D.prototype.save = function() {};
Kevin Lubickb9db3902018-11-26 11:47:54 -0500446CanvasRenderingContext2D.prototype.scale = function() {};
447CanvasRenderingContext2D.prototype.scrollPathIntoView = function() {};
Kevin Lubick12c0e502018-11-28 12:51:56 -0500448CanvasRenderingContext2D.prototype.setLineDash = function() {};
Kevin Lubickb9db3902018-11-26 11:47:54 -0500449CanvasRenderingContext2D.prototype.setTransform = function() {};
450CanvasRenderingContext2D.prototype.stroke = function() {};
Kevin Lubick12c0e502018-11-28 12:51:56 -0500451CanvasRenderingContext2D.prototype.strokeRect = function() {};
Kevin Lubickb9db3902018-11-26 11:47:54 -0500452CanvasRenderingContext2D.prototype.strokeText = function() {};
453CanvasRenderingContext2D.prototype.transform = function() {};
454CanvasRenderingContext2D.prototype.translate = function() {};
455
Kevin Lubickeb2f6b02018-11-29 15:07:02 -0500456var LinearCanvasGradient = {};
457LinearCanvasGradient.prototype.addColorStop = function() {};
458var RadialCanvasGradient = {};
459RadialCanvasGradient.prototype.addColorStop = function() {};
460
Kevin Lubick217056c2018-09-20 17:39:31 -0400461// Not sure why this is needed - might be a bug in emsdk that this isn't properly declared.
Kevin Lubick6fccc9d2018-11-20 15:55:10 -0500462function loadWebAssemblyModule() {};
Kevin Lubick12c0e502018-11-28 12:51:56 -0500463
464var DOMMatrix = {};