xref: /aosp_15_r20/external/skia/modules/canvaskit/skottie.js (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker// Adds compile-time JS functions to augment the CanvasKit interface.
2*c8dee2aaSAndroid Build Coastguard Worker// Specifically, anything that should only be on the Skottie builds of canvaskit.
3*c8dee2aaSAndroid Build Coastguard Worker
4*c8dee2aaSAndroid Build Coastguard Worker// assets is a dictionary of named blobs: { key: ArrayBuffer, ... }
5*c8dee2aaSAndroid Build Coastguard Worker// The keys should be well-behaved strings - they're turned into null-terminated
6*c8dee2aaSAndroid Build Coastguard Worker// strings for the native side.
7*c8dee2aaSAndroid Build Coastguard Worker
8*c8dee2aaSAndroid Build Coastguard Worker// prop_filter_prefix is an optional string acting as a name filter for selecting
9*c8dee2aaSAndroid Build Coastguard Worker// "interesting" Lottie properties (surfaced in the embedded player controls)
10*c8dee2aaSAndroid Build Coastguard Worker
11*c8dee2aaSAndroid Build Coastguard Worker// soundMap is an optional object that maps string names to AudioPlayers
12*c8dee2aaSAndroid Build Coastguard Worker// AudioPlayers manage a single audio layer with a seek function
13*c8dee2aaSAndroid Build Coastguard Worker
14*c8dee2aaSAndroid Build Coastguard Worker// logger is an optional logging object, expected to provide two functions:
15*c8dee2aaSAndroid Build Coastguard Worker//   - onError(err_str, json_node_str)
16*c8dee2aaSAndroid Build Coastguard Worker//   - onWarning(wrn_str, json_node_str)
17*c8dee2aaSAndroid Build Coastguard WorkerCanvasKit.MakeManagedAnimation = function(json, assets, prop_filter_prefix, soundMap, logger) {
18*c8dee2aaSAndroid Build Coastguard Worker  if (!CanvasKit._MakeManagedAnimation) {
19*c8dee2aaSAndroid Build Coastguard Worker    throw 'Not compiled with MakeManagedAnimation';
20*c8dee2aaSAndroid Build Coastguard Worker  }
21*c8dee2aaSAndroid Build Coastguard Worker  if (!prop_filter_prefix) {
22*c8dee2aaSAndroid Build Coastguard Worker    prop_filter_prefix = '';
23*c8dee2aaSAndroid Build Coastguard Worker  }
24*c8dee2aaSAndroid Build Coastguard Worker  if (!assets) {
25*c8dee2aaSAndroid Build Coastguard Worker    return CanvasKit._MakeManagedAnimation(json, 0, nullptr, nullptr, nullptr, prop_filter_prefix,
26*c8dee2aaSAndroid Build Coastguard Worker                                           soundMap, logger);
27*c8dee2aaSAndroid Build Coastguard Worker  }
28*c8dee2aaSAndroid Build Coastguard Worker  var assetNamePtrs = [];
29*c8dee2aaSAndroid Build Coastguard Worker  var assetDataPtrs = [];
30*c8dee2aaSAndroid Build Coastguard Worker  var assetSizes    = [];
31*c8dee2aaSAndroid Build Coastguard Worker
32*c8dee2aaSAndroid Build Coastguard Worker  var assetKeys = Object.keys(assets || {});
33*c8dee2aaSAndroid Build Coastguard Worker  for (var i = 0; i < assetKeys.length; i++) {
34*c8dee2aaSAndroid Build Coastguard Worker    var key = assetKeys[i];
35*c8dee2aaSAndroid Build Coastguard Worker    var buffer = assets[key];
36*c8dee2aaSAndroid Build Coastguard Worker    var data = new Uint8Array(buffer);
37*c8dee2aaSAndroid Build Coastguard Worker
38*c8dee2aaSAndroid Build Coastguard Worker    var iptr = CanvasKit._malloc(data.byteLength);
39*c8dee2aaSAndroid Build Coastguard Worker    CanvasKit.HEAPU8.set(data, iptr);
40*c8dee2aaSAndroid Build Coastguard Worker    assetDataPtrs.push(iptr);
41*c8dee2aaSAndroid Build Coastguard Worker    assetSizes.push(data.byteLength);
42*c8dee2aaSAndroid Build Coastguard Worker
43*c8dee2aaSAndroid Build Coastguard Worker    // lengthBytesUTF8 and stringToUTF8Array are defined in the emscripten
44*c8dee2aaSAndroid Build Coastguard Worker    // JS.  See https://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html#stringToUTF8
45*c8dee2aaSAndroid Build Coastguard Worker    // Add 1 for null terminator
46*c8dee2aaSAndroid Build Coastguard Worker    var strLen = lengthBytesUTF8(key) + 1;
47*c8dee2aaSAndroid Build Coastguard Worker    var strPtr = CanvasKit._malloc(strLen);
48*c8dee2aaSAndroid Build Coastguard Worker
49*c8dee2aaSAndroid Build Coastguard Worker    stringToUTF8(key, strPtr, strLen);
50*c8dee2aaSAndroid Build Coastguard Worker    assetNamePtrs.push(strPtr);
51*c8dee2aaSAndroid Build Coastguard Worker  }
52*c8dee2aaSAndroid Build Coastguard Worker
53*c8dee2aaSAndroid Build Coastguard Worker  // Not entirely sure if it matters, but the uintptr_t are 32 bits
54*c8dee2aaSAndroid Build Coastguard Worker  // we want to copy our array of uintptr_t into the right size memory.
55*c8dee2aaSAndroid Build Coastguard Worker  var namesPtr      = copy1dArray(assetNamePtrs, "HEAPU32");
56*c8dee2aaSAndroid Build Coastguard Worker  var assetsPtr     = copy1dArray(assetDataPtrs, "HEAPU32");
57*c8dee2aaSAndroid Build Coastguard Worker  var assetSizesPtr = copy1dArray(assetSizes,    "HEAPU32");
58*c8dee2aaSAndroid Build Coastguard Worker
59*c8dee2aaSAndroid Build Coastguard Worker  var anim = CanvasKit._MakeManagedAnimation(json, assetKeys.length, namesPtr,
60*c8dee2aaSAndroid Build Coastguard Worker                                             assetsPtr, assetSizesPtr, prop_filter_prefix,
61*c8dee2aaSAndroid Build Coastguard Worker                                             soundMap, logger);
62*c8dee2aaSAndroid Build Coastguard Worker
63*c8dee2aaSAndroid Build Coastguard Worker  // The C++ code has made copies of the asset and string data, so free our copies.
64*c8dee2aaSAndroid Build Coastguard Worker  CanvasKit._free(namesPtr);
65*c8dee2aaSAndroid Build Coastguard Worker  CanvasKit._free(assetsPtr);
66*c8dee2aaSAndroid Build Coastguard Worker  CanvasKit._free(assetSizesPtr);
67*c8dee2aaSAndroid Build Coastguard Worker
68*c8dee2aaSAndroid Build Coastguard Worker  return anim;
69*c8dee2aaSAndroid Build Coastguard Worker};
70*c8dee2aaSAndroid Build Coastguard Worker
71*c8dee2aaSAndroid Build Coastguard WorkerCanvasKit.SlottableTextProperty = function(t) {
72*c8dee2aaSAndroid Build Coastguard Worker  // Use [''] to tell closure not to minify the names
73*c8dee2aaSAndroid Build Coastguard Worker  t['text'] = t['text'] || "";
74*c8dee2aaSAndroid Build Coastguard Worker  t['textSize'] = t['textSize'] || 0;
75*c8dee2aaSAndroid Build Coastguard Worker  t['minTextSize'] = t['minTextSize'] || 0;
76*c8dee2aaSAndroid Build Coastguard Worker  t['maxTextSize'] = t['maxTextSize'] || Number.MAX_VALUE;
77*c8dee2aaSAndroid Build Coastguard Worker  t['strokeWidth'] = t['strokeWidth'] || 0;
78*c8dee2aaSAndroid Build Coastguard Worker  t['lineHeight'] = t['lineHeight'] || 0;
79*c8dee2aaSAndroid Build Coastguard Worker  t['lineShift'] = t['lineShift'] || 0;
80*c8dee2aaSAndroid Build Coastguard Worker  t['ascent'] = t['ascent'] || 0;
81*c8dee2aaSAndroid Build Coastguard Worker  t['maxLines'] = t['maxLines'] || 0;
82*c8dee2aaSAndroid Build Coastguard Worker  t['horizAlign'] = t['horizAlign'] || CanvasKit.TextAlign.Left;
83*c8dee2aaSAndroid Build Coastguard Worker  t['vertAlign'] = t['vertAlign'] || CanvasKit.VerticalTextAlign.Top;
84*c8dee2aaSAndroid Build Coastguard Worker  t['strokeJoin'] = t['strokeJoin'] || CanvasKit.StrokeJoin.Miter;
85*c8dee2aaSAndroid Build Coastguard Worker  t['direction'] = t['direction'] || CanvasKit.TextDirection.LTR;
86*c8dee2aaSAndroid Build Coastguard Worker  t['linebreak'] = t['linebreak'] || CanvasKit.LineBreakType.HardLineBreak;
87*c8dee2aaSAndroid Build Coastguard Worker  t['resize'] = t['resize'] || CanvasKit.ResizePolicy.None;
88*c8dee2aaSAndroid Build Coastguard Worker
89*c8dee2aaSAndroid Build Coastguard Worker  if (!t['fillColor']) {
90*c8dee2aaSAndroid Build Coastguard Worker    t['fillColor'] = CanvasKit.TRANSPARENT;
91*c8dee2aaSAndroid Build Coastguard Worker  }
92*c8dee2aaSAndroid Build Coastguard Worker  if (!t['strokeColor']) {
93*c8dee2aaSAndroid Build Coastguard Worker    t['strokeColor'] = CanvasKit.TRANSPARENT;
94*c8dee2aaSAndroid Build Coastguard Worker  }
95*c8dee2aaSAndroid Build Coastguard Worker  if (!t['boundingBox']) {
96*c8dee2aaSAndroid Build Coastguard Worker    t['boundingBox'] = [0,0,0,0];
97*c8dee2aaSAndroid Build Coastguard Worker  }
98*c8dee2aaSAndroid Build Coastguard Worker  return t;
99*c8dee2aaSAndroid Build Coastguard Worker};
100*c8dee2aaSAndroid Build Coastguard Worker
101*c8dee2aaSAndroid Build Coastguard Worker(function(CanvasKit){
102*c8dee2aaSAndroid Build Coastguard Worker  CanvasKit._extraInitializations = CanvasKit._extraInitializations || [];
103*c8dee2aaSAndroid Build Coastguard Worker  CanvasKit._extraInitializations.push(function() {
104*c8dee2aaSAndroid Build Coastguard Worker
105*c8dee2aaSAndroid Build Coastguard Worker  CanvasKit.Animation.prototype.render = function(canvas, dstRect) {
106*c8dee2aaSAndroid Build Coastguard Worker    copyRectToWasm(dstRect, _scratchFourFloatsAPtr);
107*c8dee2aaSAndroid Build Coastguard Worker    this._render(canvas, _scratchFourFloatsAPtr);
108*c8dee2aaSAndroid Build Coastguard Worker  };
109*c8dee2aaSAndroid Build Coastguard Worker
110*c8dee2aaSAndroid Build Coastguard Worker  CanvasKit.Animation.prototype.size = function(optSize) {
111*c8dee2aaSAndroid Build Coastguard Worker    // This will copy 2 floats into a space for 4 floats
112*c8dee2aaSAndroid Build Coastguard Worker    this._size(_scratchFourFloatsAPtr);
113*c8dee2aaSAndroid Build Coastguard Worker    var ta = _scratchFourFloatsA['toTypedArray']();
114*c8dee2aaSAndroid Build Coastguard Worker    if (optSize) {
115*c8dee2aaSAndroid Build Coastguard Worker      // We cannot call optSize.set() because it is an error to call .set() with
116*c8dee2aaSAndroid Build Coastguard Worker      // a source bigger than the destination.
117*c8dee2aaSAndroid Build Coastguard Worker      optSize[0] = ta[0];
118*c8dee2aaSAndroid Build Coastguard Worker      optSize[1] = ta[1];
119*c8dee2aaSAndroid Build Coastguard Worker      return optSize;
120*c8dee2aaSAndroid Build Coastguard Worker    }
121*c8dee2aaSAndroid Build Coastguard Worker    // Be sure to return a copy of just the first 2 values.
122*c8dee2aaSAndroid Build Coastguard Worker    return ta.slice(0, 2);
123*c8dee2aaSAndroid Build Coastguard Worker  };
124*c8dee2aaSAndroid Build Coastguard Worker
125*c8dee2aaSAndroid Build Coastguard Worker  if (CanvasKit.ManagedAnimation) {
126*c8dee2aaSAndroid Build Coastguard Worker    CanvasKit.ManagedAnimation.prototype.render = function(canvas, dstRect) {
127*c8dee2aaSAndroid Build Coastguard Worker    copyRectToWasm(dstRect, _scratchFourFloatsAPtr);
128*c8dee2aaSAndroid Build Coastguard Worker    this._render(canvas, _scratchFourFloatsAPtr);
129*c8dee2aaSAndroid Build Coastguard Worker    };
130*c8dee2aaSAndroid Build Coastguard Worker
131*c8dee2aaSAndroid Build Coastguard Worker    CanvasKit.ManagedAnimation.prototype.seek = function(t, optDamageRect) {
132*c8dee2aaSAndroid Build Coastguard Worker      this._seek(t, _scratchFourFloatsAPtr);
133*c8dee2aaSAndroid Build Coastguard Worker      var ta = _scratchFourFloatsA['toTypedArray']();
134*c8dee2aaSAndroid Build Coastguard Worker      if (optDamageRect) {
135*c8dee2aaSAndroid Build Coastguard Worker        optDamageRect.set(ta);
136*c8dee2aaSAndroid Build Coastguard Worker        return optDamageRect;
137*c8dee2aaSAndroid Build Coastguard Worker      }
138*c8dee2aaSAndroid Build Coastguard Worker      return ta.slice();
139*c8dee2aaSAndroid Build Coastguard Worker    };
140*c8dee2aaSAndroid Build Coastguard Worker
141*c8dee2aaSAndroid Build Coastguard Worker    CanvasKit.ManagedAnimation.prototype.seekFrame = function(frame, optDamageRect) {
142*c8dee2aaSAndroid Build Coastguard Worker      this._seekFrame(frame, _scratchFourFloatsAPtr);
143*c8dee2aaSAndroid Build Coastguard Worker      var ta = _scratchFourFloatsA['toTypedArray']();
144*c8dee2aaSAndroid Build Coastguard Worker      if (optDamageRect) {
145*c8dee2aaSAndroid Build Coastguard Worker        optDamageRect.set(ta);
146*c8dee2aaSAndroid Build Coastguard Worker        return optDamageRect;
147*c8dee2aaSAndroid Build Coastguard Worker      }
148*c8dee2aaSAndroid Build Coastguard Worker      return ta.slice();
149*c8dee2aaSAndroid Build Coastguard Worker    };
150*c8dee2aaSAndroid Build Coastguard Worker
151*c8dee2aaSAndroid Build Coastguard Worker    CanvasKit.ManagedAnimation.prototype.setColor = function(key, color) {
152*c8dee2aaSAndroid Build Coastguard Worker      var cPtr = copyColorToWasm(color);
153*c8dee2aaSAndroid Build Coastguard Worker      return this._setColor(key, cPtr);
154*c8dee2aaSAndroid Build Coastguard Worker    };
155*c8dee2aaSAndroid Build Coastguard Worker
156*c8dee2aaSAndroid Build Coastguard Worker    CanvasKit.ManagedAnimation.prototype.setColorSlot = function(key, color) {
157*c8dee2aaSAndroid Build Coastguard Worker      var cPtr = copyColorToWasm(color);
158*c8dee2aaSAndroid Build Coastguard Worker      return this._setColorSlot(key, cPtr);
159*c8dee2aaSAndroid Build Coastguard Worker    };
160*c8dee2aaSAndroid Build Coastguard Worker
161*c8dee2aaSAndroid Build Coastguard Worker    CanvasKit.ManagedAnimation.prototype.getColorSlot = function(key) {
162*c8dee2aaSAndroid Build Coastguard Worker      this._getColorSlot(key, _scratchColorPtr);
163*c8dee2aaSAndroid Build Coastguard Worker      var fourFloats = copyColorFromWasm(_scratchColorPtr);
164*c8dee2aaSAndroid Build Coastguard Worker      if (fourFloats[0] == -1) {
165*c8dee2aaSAndroid Build Coastguard Worker        return null;
166*c8dee2aaSAndroid Build Coastguard Worker      }
167*c8dee2aaSAndroid Build Coastguard Worker      return fourFloats;
168*c8dee2aaSAndroid Build Coastguard Worker    }
169*c8dee2aaSAndroid Build Coastguard Worker
170*c8dee2aaSAndroid Build Coastguard Worker    CanvasKit.ManagedAnimation.prototype.setVec2Slot = function(key, vec) {
171*c8dee2aaSAndroid Build Coastguard Worker      copy1dArray(vec, 'HEAPF32', _scratchThreeFloatsAPtr);
172*c8dee2aaSAndroid Build Coastguard Worker      return this._setVec2Slot(key, _scratchThreeFloatsAPtr);
173*c8dee2aaSAndroid Build Coastguard Worker    };
174*c8dee2aaSAndroid Build Coastguard Worker
175*c8dee2aaSAndroid Build Coastguard Worker    CanvasKit.ManagedAnimation.prototype.getVec2Slot = function(key) {
176*c8dee2aaSAndroid Build Coastguard Worker      this._getVec2Slot(key, _scratchThreeFloatsAPtr);
177*c8dee2aaSAndroid Build Coastguard Worker      var ta = _scratchThreeFloatsA['toTypedArray']();
178*c8dee2aaSAndroid Build Coastguard Worker      if (ta[2] === -1) {
179*c8dee2aaSAndroid Build Coastguard Worker        return null;
180*c8dee2aaSAndroid Build Coastguard Worker      }
181*c8dee2aaSAndroid Build Coastguard Worker      return ta.slice(0, 2);
182*c8dee2aaSAndroid Build Coastguard Worker    }
183*c8dee2aaSAndroid Build Coastguard Worker
184*c8dee2aaSAndroid Build Coastguard Worker    CanvasKit.ManagedAnimation.prototype.setTextSlot = function(key, textValue) {
185*c8dee2aaSAndroid Build Coastguard Worker      var fillPtr = copyColorToWasm(textValue['fillColor'], _scratchColorPtr);
186*c8dee2aaSAndroid Build Coastguard Worker      var strokePtr = copyColorToWasm(textValue['strokeColor'], _scratchFourFloatsAPtr);
187*c8dee2aaSAndroid Build Coastguard Worker      var boxPtr = copyRectToWasm(textValue['boundingBox'], _scratchFourFloatsBPtr);
188*c8dee2aaSAndroid Build Coastguard Worker
189*c8dee2aaSAndroid Build Coastguard Worker      textValue['_fillColorPtr'] = fillPtr;
190*c8dee2aaSAndroid Build Coastguard Worker      textValue['_strokeColorPtr'] = strokePtr;
191*c8dee2aaSAndroid Build Coastguard Worker      textValue['_boundingBoxPtr'] = boxPtr;
192*c8dee2aaSAndroid Build Coastguard Worker
193*c8dee2aaSAndroid Build Coastguard Worker      return this._setTextSlot(key, textValue);
194*c8dee2aaSAndroid Build Coastguard Worker    }
195*c8dee2aaSAndroid Build Coastguard Worker
196*c8dee2aaSAndroid Build Coastguard Worker    CanvasKit.ManagedAnimation.prototype.setTransform = function(key, anchor, position, scale, rotation, skew, skew_axis) {
197*c8dee2aaSAndroid Build Coastguard Worker      let transformData = [anchor[0], anchor[1], position[0], position[1], scale[0], scale[1], rotation, skew, skew_axis];
198*c8dee2aaSAndroid Build Coastguard Worker      const tPtr = copy1dArray(transformData, 'HEAPF32', _scratch3x3MatrixPtr);
199*c8dee2aaSAndroid Build Coastguard Worker      return this._setTransform(key, tPtr);
200*c8dee2aaSAndroid Build Coastguard Worker    };
201*c8dee2aaSAndroid Build Coastguard Worker
202*c8dee2aaSAndroid Build Coastguard Worker    CanvasKit.ManagedAnimation.prototype.size = function(optSize) {
203*c8dee2aaSAndroid Build Coastguard Worker      // This will copy 2 floats into a space for 4 floats
204*c8dee2aaSAndroid Build Coastguard Worker      this._size(_scratchFourFloatsAPtr);
205*c8dee2aaSAndroid Build Coastguard Worker      var ta = _scratchFourFloatsA['toTypedArray']();
206*c8dee2aaSAndroid Build Coastguard Worker      if (optSize) {
207*c8dee2aaSAndroid Build Coastguard Worker        // We cannot call optSize.set() because it is an error to call .set() with
208*c8dee2aaSAndroid Build Coastguard Worker        // a source bigger than the destination.
209*c8dee2aaSAndroid Build Coastguard Worker        optSize[0] = ta[0];
210*c8dee2aaSAndroid Build Coastguard Worker        optSize[1] = ta[1];
211*c8dee2aaSAndroid Build Coastguard Worker        return optSize;
212*c8dee2aaSAndroid Build Coastguard Worker      }
213*c8dee2aaSAndroid Build Coastguard Worker      // Be sure to return a copy of just the first 2 values.
214*c8dee2aaSAndroid Build Coastguard Worker      return ta.slice(0, 2);
215*c8dee2aaSAndroid Build Coastguard Worker    };
216*c8dee2aaSAndroid Build Coastguard Worker  }
217*c8dee2aaSAndroid Build Coastguard Worker
218*c8dee2aaSAndroid Build Coastguard Worker
219*c8dee2aaSAndroid Build Coastguard Worker});
220*c8dee2aaSAndroid Build Coastguard Worker}(Module)); // When this file is loaded in, the high level object is "Module";
221