@shopify/react-native-skia 0.1.187 → 0.1.189

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. package/android/build.gradle +15 -2
  2. package/cpp/api/JsiSkMatrix.h +6 -6
  3. package/cpp/rnskia/dom/base/JsiDependencyManager.h +47 -47
  4. package/cpp/rnskia/dom/base/JsiDomNode.h +6 -7
  5. package/cpp/rnskia/dom/base/NodePropsContainer.h +27 -3
  6. package/cpp/rnskia/dom/props/ColorProp.h +7 -0
  7. package/ios/RNSkia-iOS/RNSkiOSPlatformContext.h +10 -9
  8. package/ios/RNSkia-iOS/RNSkiOSPlatformContext.mm +7 -3
  9. package/ios/RNSkia-iOS/SkiaManager.mm +3 -27
  10. package/ios/RNSkia-iOS/ViewScreenshotService.mm +13 -1
  11. package/lib/commonjs/animation/functions/interpolateColors.d.ts +1 -1
  12. package/lib/commonjs/animation/functions/interpolateColors.js +3 -2
  13. package/lib/commonjs/animation/functions/interpolateColors.js.map +1 -1
  14. package/lib/commonjs/skia/types/Color.d.ts +1 -1
  15. package/lib/commonjs/skia/types/Color.js.map +1 -1
  16. package/lib/commonjs/skia/types/Matrix.d.ts +6 -6
  17. package/lib/commonjs/skia/types/Matrix.js.map +1 -1
  18. package/lib/commonjs/skia/web/JsiSkColor.js +2 -0
  19. package/lib/commonjs/skia/web/JsiSkColor.js.map +1 -1
  20. package/lib/commonjs/skia/web/JsiSkMatrix.d.ts +6 -6
  21. package/lib/commonjs/skia/web/JsiSkMatrix.js +6 -0
  22. package/lib/commonjs/skia/web/JsiSkMatrix.js.map +1 -1
  23. package/lib/module/animation/functions/interpolateColors.d.ts +1 -1
  24. package/lib/module/animation/functions/interpolateColors.js +3 -2
  25. package/lib/module/animation/functions/interpolateColors.js.map +1 -1
  26. package/lib/module/skia/types/Color.d.ts +1 -1
  27. package/lib/module/skia/types/Color.js.map +1 -1
  28. package/lib/module/skia/types/Matrix.d.ts +6 -6
  29. package/lib/module/skia/types/Matrix.js.map +1 -1
  30. package/lib/module/skia/web/JsiSkColor.js +2 -0
  31. package/lib/module/skia/web/JsiSkColor.js.map +1 -1
  32. package/lib/module/skia/web/JsiSkMatrix.d.ts +6 -6
  33. package/lib/module/skia/web/JsiSkMatrix.js +6 -0
  34. package/lib/module/skia/web/JsiSkMatrix.js.map +1 -1
  35. package/lib/typescript/src/animation/functions/interpolateColors.d.ts +1 -1
  36. package/lib/typescript/src/skia/types/Color.d.ts +1 -1
  37. package/lib/typescript/src/skia/types/Matrix.d.ts +6 -6
  38. package/lib/typescript/src/skia/web/JsiSkMatrix.d.ts +6 -6
  39. package/package.json +1 -1
  40. package/src/animation/functions/interpolateColors.ts +2 -1
  41. package/src/skia/types/Color.ts +1 -1
  42. package/src/skia/types/Matrix.ts +6 -6
  43. package/src/skia/web/JsiSkColor.ts +2 -0
  44. package/src/skia/web/JsiSkMatrix.ts +6 -0
@@ -272,11 +272,24 @@ task extractJNIFiles {
272
272
  extractJNIFiles.mustRunAfter extractAARHeaders
273
273
 
274
274
  if (ENABLE_PREFAB) {
275
- // Package everything with the original file structure
275
+ // Package all the cpp code in a flattened directory structure
276
276
  task prepareHeaders(type: Copy) {
277
- from('./cpp')
277
+ from("./cpp")
278
278
  into "${project.buildDir}/headers/rnskia/"
279
279
  includeEmptyDirs = false
280
+ include "**/*.h"
281
+ eachFile {
282
+ String path = it.path
283
+
284
+ // Skip flattening third_party dir
285
+ if (path.contains("api/third_party")) {
286
+ path = path.substring("api/".length())
287
+ } else {
288
+ // flatten anything else
289
+ path = path.substring(path.lastIndexOf("/") + 1)
290
+ }
291
+ it.path = path
292
+ }
280
293
  }
281
294
  preBuild.dependsOn(prepareHeaders)
282
295
  }
@@ -47,39 +47,39 @@ public:
47
47
  JSI_HOST_FUNCTION(concat) {
48
48
  auto m3 = JsiSkMatrix::fromValue(runtime, arguments[0]);
49
49
  getObject()->preConcat(*m3);
50
- return jsi::Value::undefined();
50
+ return thisValue.asObject(runtime);
51
51
  }
52
52
 
53
53
  JSI_HOST_FUNCTION(translate) {
54
54
  auto x = arguments[0].asNumber();
55
55
  auto y = arguments[1].asNumber();
56
56
  getObject()->preTranslate(x, y);
57
- return jsi::Value::undefined();
57
+ return thisValue.asObject(runtime);
58
58
  }
59
59
 
60
60
  JSI_HOST_FUNCTION(scale) {
61
61
  auto x = arguments[0].asNumber();
62
62
  auto y = count > 1 ? arguments[1].asNumber() : 1;
63
63
  getObject()->preScale(x, y);
64
- return jsi::Value::undefined();
64
+ return thisValue.asObject(runtime);
65
65
  }
66
66
 
67
67
  JSI_HOST_FUNCTION(skew) {
68
68
  auto x = arguments[0].asNumber();
69
69
  auto y = arguments[1].asNumber();
70
70
  getObject()->preSkew(x, y);
71
- return jsi::Value::undefined();
71
+ return thisValue.asObject(runtime);
72
72
  }
73
73
 
74
74
  JSI_HOST_FUNCTION(rotate) {
75
75
  auto a = arguments[0].asNumber();
76
76
  getObject()->preRotate(SkRadiansToDegrees(a));
77
- return jsi::Value::undefined();
77
+ return thisValue.asObject(runtime);
78
78
  }
79
79
 
80
80
  JSI_HOST_FUNCTION(identity) {
81
81
  getObject()->setIdentity();
82
- return jsi::Value::undefined();
82
+ return thisValue.asObject(runtime);
83
83
  }
84
84
 
85
85
  JSI_HOST_FUNCTION(get) {
@@ -64,53 +64,53 @@ public:
64
64
 
65
65
  // Enumerate registered keys for the given node to only handle known
66
66
  // properties
67
- for (const auto &propMapping :
68
- node->getPropsContainer()->getMappedProperties()) {
69
- auto key = propMapping.first;
70
- auto jsValue = nextProps.getProperty(runtime, key);
71
- JsiValue nativeValue(runtime, jsValue);
72
-
73
- if (isAnimatedValue(nativeValue)) {
74
- // Handle Skia Animation Values
75
- auto animatedValue = getAnimatedValue(nativeValue);
76
- auto unsubscribe = animatedValue->addListener(
77
- [animatedValue, propMapping](jsi::Runtime &runtime) {
78
- // Get value from animation value
79
- auto nextJsValue = animatedValue->getCurrent(runtime);
80
- // Update all props that listens to this animation value
81
- for (auto &prop : propMapping.second) {
82
- prop->updateValue(runtime, nextJsValue);
83
- }
84
- });
85
-
86
- // Save unsubscribe methods
87
- unsubscribers.push_back(std::make_pair(animatedValue, unsubscribe));
88
-
89
- } else if (isSelector(nativeValue)) {
90
- // Handle Skia Animation Value Selectors
91
- auto animatedValue = std::dynamic_pointer_cast<RNSkReadonlyValue>(
92
- nativeValue.getValue(PropNameValue).getAsHostObject());
93
-
94
- auto selector = nativeValue.getValue(PropNameSelector).getAsFunction();
95
- // Add subscription to animated value in selector
96
- auto unsubscribe = animatedValue->addListener(
97
- [nativeValue, propMapping, selector = std::move(selector),
98
- animatedValue](jsi::Runtime &runtime) {
99
- // Get value from animation value
100
- jsi::Value jsValue = animatedValue->getCurrent(runtime);
101
- // Call selector to transform new value
102
- auto selectedJsValue =
103
- selector(runtime, jsi::Value::null(), &jsValue, 1);
104
- // Update all props that listens to this animation value
105
- for (auto &prop : propMapping.second) {
106
- prop->updateValue(runtime, selectedJsValue);
107
- }
108
- });
109
-
110
- // Save unsubscribe methods
111
- unsubscribers.push_back(std::make_pair(animatedValue, unsubscribe));
112
- }
113
- }
67
+ node->getPropsContainer()->enumerateMappedProps(
68
+ [&](const PropId key, const std::vector<NodeProp *> &propMapping) {
69
+ auto jsValue = nextProps.getProperty(runtime, key);
70
+ JsiValue nativeValue(runtime, jsValue);
71
+
72
+ if (isAnimatedValue(nativeValue)) {
73
+ // Handle Skia Animation Values
74
+ auto animatedValue = getAnimatedValue(nativeValue);
75
+ auto unsubscribe = animatedValue->addListener(
76
+ [animatedValue, propMapping](jsi::Runtime &runtime) {
77
+ // Get value from animation value
78
+ auto nextJsValue = animatedValue->getCurrent(runtime);
79
+ // Update all props that listens to this animation value
80
+ for (auto &prop : propMapping) {
81
+ prop->updateValue(runtime, nextJsValue);
82
+ }
83
+ });
84
+
85
+ // Save unsubscribe methods
86
+ unsubscribers.push_back(std::make_pair(animatedValue, unsubscribe));
87
+
88
+ } else if (isSelector(nativeValue)) {
89
+ // Handle Skia Animation Value Selectors
90
+ auto animatedValue = std::dynamic_pointer_cast<RNSkReadonlyValue>(
91
+ nativeValue.getValue(PropNameValue).getAsHostObject());
92
+
93
+ auto selector =
94
+ nativeValue.getValue(PropNameSelector).getAsFunction();
95
+ // Add subscription to animated value in selector
96
+ auto unsubscribe = animatedValue->addListener(
97
+ [nativeValue, propMapping, selector = std::move(selector),
98
+ animatedValue](jsi::Runtime &runtime) {
99
+ // Get value from animation value
100
+ jsi::Value jsValue = animatedValue->getCurrent(runtime);
101
+ // Call selector to transform new value
102
+ auto selectedJsValue =
103
+ selector(runtime, jsi::Value::null(), &jsValue, 1);
104
+ // Update all props that listens to this animation value
105
+ for (auto &prop : propMapping) {
106
+ prop->updateValue(runtime, selectedJsValue);
107
+ }
108
+ });
109
+
110
+ // Save unsubscribe methods
111
+ unsubscribers.push_back(std::make_pair(animatedValue, unsubscribe));
112
+ }
113
+ });
114
114
 
115
115
  // Now let's store the subscription info
116
116
  _subscriptions.emplace(node.get(), unsubscribers);
@@ -98,13 +98,12 @@ public:
98
98
  auto propName = arguments[0].asString(runtime).utf8(runtime);
99
99
  const jsi::Value &propValue = arguments[1];
100
100
 
101
- auto mappedProps = _propsContainer->getMappedProperties();
102
- auto propMapIt = mappedProps.find(JsiPropId::get(propName));
103
- if (propMapIt != mappedProps.end()) {
104
- for (auto &prop : propMapIt->second) {
105
- prop->updateValue(runtime, propValue);
106
- }
107
- }
101
+ // Enumerate all props with this name and update. The
102
+ // enumerateMappedPropsByName function is thread safe and locks props so it
103
+ // can be called from all threads.
104
+ _propsContainer->enumerateMappedPropsByName(propName, [&](NodeProp *prop) {
105
+ prop->updateValue(runtime, propValue);
106
+ });
108
107
 
109
108
  return jsi::Value::undefined();
110
109
  }
@@ -41,10 +41,30 @@ public:
41
41
  }
42
42
 
43
43
  /**
44
- Returns a list of mappings betwen property names and property objects
44
+ Enumerate all mapped properties
45
45
  */
46
- const std::map<PropId, std::vector<NodeProp *>> &getMappedProperties() {
47
- return _mappedProperties;
46
+ void enumerateMappedProps(
47
+ const std::function<void(const PropId name,
48
+ const std::vector<NodeProp *>)> &callback) {
49
+ std::lock_guard<std::mutex> lock(_mappedPropsLock);
50
+ for (auto &props : _mappedProperties) {
51
+ callback(props.first, props.second);
52
+ }
53
+ }
54
+
55
+ /**
56
+ Enumerates a named property instances from the mapped properties list
57
+ */
58
+ void
59
+ enumerateMappedPropsByName(const std::string &name,
60
+ const std::function<void(NodeProp *)> &callback) {
61
+ std::lock_guard<std::mutex> lock(_mappedPropsLock);
62
+ auto propMapIt = _mappedProperties.find(JsiPropId::get(name));
63
+ if (propMapIt != _mappedProperties.end()) {
64
+ for (auto &prop : propMapIt->second) {
65
+ callback(prop);
66
+ }
67
+ }
48
68
  }
49
69
 
50
70
  /**
@@ -75,6 +95,7 @@ public:
75
95
  Clears all props and data from the container
76
96
  */
77
97
  void dispose() {
98
+ std::lock_guard<std::mutex> lock(_mappedPropsLock);
78
99
  _properties.clear();
79
100
  _mappedProperties.clear();
80
101
  }
@@ -83,6 +104,8 @@ public:
83
104
  Called when the React / JS side sets properties on a node
84
105
  */
85
106
  void setProps(jsi::Runtime &runtime, const jsi::Value &maybePropsObject) {
107
+ std::lock_guard<std::mutex> lock(_mappedPropsLock);
108
+
86
109
  // Clear property mapping
87
110
  _mappedProperties.clear();
88
111
 
@@ -129,6 +152,7 @@ private:
129
152
  std::vector<std::shared_ptr<BaseNodeProp>> _properties;
130
153
  std::map<PropId, std::vector<NodeProp *>> _mappedProperties;
131
154
  PropId _type;
155
+ std::mutex _mappedPropsLock;
132
156
  };
133
157
 
134
158
  } // namespace RNSkia
@@ -42,6 +42,13 @@ public:
42
42
  return SkColorSetARGB(a.getAsNumber() * 255.0f, r.getAsNumber() * 255.0f,
43
43
  g.getAsNumber() * 255.0f, b.getAsNumber() * 255.0f);
44
44
 
45
+ } else if (color.getType() == PropType::Array) {
46
+ auto r = color.getAsArray().at(0);
47
+ auto g = color.getAsArray().at(1);
48
+ auto b = color.getAsArray().at(2);
49
+ auto a = color.getAsArray().at(3);
50
+ return SkColorSetARGB(a.getAsNumber() * 255.0f, r.getAsNumber() * 255.0f,
51
+ g.getAsNumber() * 255.0f, b.getAsNumber() * 255.0f);
45
52
  } else if (color.getType() == PropType::Number) {
46
53
  return static_cast<SkColor>(color.getAsNumber());
47
54
  } else {
@@ -1,6 +1,8 @@
1
1
  #pragma once
2
2
 
3
+ #import <React/RCTBridge+Private.h>
3
4
  #import <React/RCTBridge.h>
5
+ #import <ReactCommon/RCTTurboModule.h>
4
6
 
5
7
  #include <functional>
6
8
  #include <memory>
@@ -8,6 +10,7 @@
8
10
 
9
11
  #include "DisplayLink.h"
10
12
  #include "RNSkPlatformContext.h"
13
+ #include "ViewScreenshotService.h"
11
14
 
12
15
  #include <jsi/jsi.h>
13
16
 
@@ -27,13 +30,8 @@ static void handleNotification(CFNotificationCenterRef center, void *observer,
27
30
 
28
31
  class RNSkiOSPlatformContext : public RNSkPlatformContext {
29
32
  public:
30
- RNSkiOSPlatformContext(
31
- jsi::Runtime *runtime, std::shared_ptr<react::CallInvoker> callInvoker,
32
- std::function<void(std::function<void()>)> dispatchMainThread,
33
- std::function<sk_sp<SkImage>(size_t viewTag)> takeViewScreenshot)
34
- : _dispatchMainThread(dispatchMainThread),
35
- _takeViewScreenshot(takeViewScreenshot),
36
- RNSkPlatformContext(runtime, callInvoker,
33
+ RNSkiOSPlatformContext(jsi::Runtime *runtime, RCTBridge *bridge)
34
+ : RNSkPlatformContext(runtime, bridge.jsCallInvoker,
37
35
  [[UIScreen mainScreen] scale]) {
38
36
 
39
37
  // We need to make sure we invalidate when modules are freed
@@ -41,6 +39,10 @@ public:
41
39
  CFNotificationCenterGetLocalCenter(), this, &handleNotification,
42
40
  (__bridge CFStringRef)RCTBridgeWillInvalidateModulesNotification, NULL,
43
41
  CFNotificationSuspensionBehaviorDeliverImmediately);
42
+
43
+ // Create screenshot manager
44
+ _screenshotService =
45
+ [[ViewScreenshotService alloc] initWithUiManager:bridge.uiManager];
44
46
  }
45
47
 
46
48
  ~RNSkiOSPlatformContext() {
@@ -70,8 +72,7 @@ public:
70
72
 
71
73
  private:
72
74
  DisplayLink *_displayLink;
73
- std::function<void(std::function<void()>)> _dispatchMainThread;
74
- std::function<sk_sp<SkImage>(size_t viewTag)> _takeViewScreenshot;
75
+ ViewScreenshotService *_screenshotService;
75
76
  };
76
77
 
77
78
  static void handleNotification(CFNotificationCenterRef center, void *observer,
@@ -63,11 +63,15 @@ sk_sp<SkSurface> RNSkiOSPlatformContext::makeOffscreenSurface(int width,
63
63
  }
64
64
 
65
65
  void RNSkiOSPlatformContext::runOnMainThread(std::function<void()> func) {
66
- _dispatchMainThread(func);
66
+ dispatch_async(dispatch_get_main_queue(), ^{
67
+ func();
68
+ });
67
69
  }
68
70
 
69
- sk_sp<SkImage> RNSkiOSPlatformContext::takeScreenshotFromViewTag(size_t tag) {
70
- return _takeViewScreenshot(tag);
71
+ sk_sp<SkImage>
72
+ RNSkiOSPlatformContext::takeScreenshotFromViewTag(size_t viewTag) {
73
+ return [_screenshotService
74
+ screenshotOfViewWithTag:[NSNumber numberWithLong:viewTag]];
71
75
  }
72
76
 
73
77
  void RNSkiOSPlatformContext::startDrawLoop() {
@@ -9,12 +9,9 @@
9
9
  #import <ReactCommon/RCTTurboModule.h>
10
10
 
11
11
  #import "RNSkiOSPlatformContext.h"
12
- #import "ViewScreenshotService.h"
13
12
 
14
13
  @implementation SkiaManager {
15
14
  std::shared_ptr<RNSkia::RNSkManager> _skManager;
16
- std::shared_ptr<RNSkia::RNSkiOSPlatformContext> _platformContext;
17
- ViewScreenshotService *_screenshot;
18
15
  __weak RCTBridge *weakBridge;
19
16
  }
20
17
 
@@ -27,7 +24,6 @@
27
24
  _skManager->invalidate();
28
25
  }
29
26
  _skManager = nullptr;
30
- _platformContext = nullptr;
31
27
  }
32
28
 
33
29
  - (instancetype)initWithBridge:(RCTBridge *)bridge {
@@ -36,33 +32,13 @@
36
32
  RCTCxxBridge *cxxBridge = (RCTCxxBridge *)bridge;
37
33
  if (cxxBridge.runtime) {
38
34
 
39
- auto callInvoker = bridge.jsCallInvoker;
40
35
  facebook::jsi::Runtime *jsRuntime =
41
36
  (facebook::jsi::Runtime *)cxxBridge.runtime;
42
37
 
43
- // Create screenshot manager
44
- _screenshot =
45
- [[ViewScreenshotService alloc] initWithUiManager:bridge.uiManager];
46
-
47
- auto takeScreenshot = [self](size_t viewTag) {
48
- return [_screenshot
49
- screenshotOfViewWithTag:[NSNumber numberWithLong:viewTag]];
50
- };
51
-
52
- auto dispatchOnMainThread = [self](std::function<void()> fp) {
53
- dispatch_async(dispatch_get_main_queue(), ^{
54
- fp();
55
- });
56
- };
57
-
58
- // Create platform context
59
- _platformContext = std::make_shared<RNSkia::RNSkiOSPlatformContext>(
60
- jsRuntime, callInvoker, std::move(dispatchOnMainThread),
61
- std::move(takeScreenshot));
62
-
63
38
  // Create the RNSkiaManager (cross platform)
64
- _skManager = std::make_shared<RNSkia::RNSkManager>(jsRuntime, callInvoker,
65
- _platformContext);
39
+ _skManager = std::make_shared<RNSkia::RNSkManager>(
40
+ jsRuntime, bridge.jsCallInvoker,
41
+ std::make_shared<RNSkia::RNSkiOSPlatformContext>(jsRuntime, bridge));
66
42
  }
67
43
  }
68
44
  return self;
@@ -33,6 +33,15 @@
33
33
  UIGraphicsImageRendererFormat *format =
34
34
  [UIGraphicsImageRendererFormat defaultFormat];
35
35
  format.opaque = NO;
36
+
37
+ // Explicitly ask for the standard format to get ARGB 32bits and not 64bits.
38
+ if (@available(iOS 12.0, *)) {
39
+ format.preferredRange = UIGraphicsImageRendererFormatRangeStandard;
40
+ } else {
41
+ // Fallback on earlier versions
42
+ format.prefersExtendedRange = false;
43
+ }
44
+
36
45
  UIGraphicsImageRenderer *renderer =
37
46
  [[UIGraphicsImageRenderer alloc] initWithSize:size format:format];
38
47
 
@@ -68,9 +77,12 @@
68
77
  (void *)dataRef);
69
78
 
70
79
  // Make SkImageInfo
80
+ // We're using kBGRA_8888_SkColorType since this is what we get when the
81
+ // UIGraphicsImageRenderer uses the standard format (the extended is using
82
+ // 64bits so it is not suitable for us).
71
83
  SkImageInfo info =
72
84
  SkImageInfo::Make(static_cast<int>(width), static_cast<int>(height),
73
- kRGBA_8888_SkColorType, kPremul_SkAlphaType);
85
+ kBGRA_8888_SkColorType, kPremul_SkAlphaType);
74
86
 
75
87
  // ... and then create the SkImage itself!
76
88
  return SkImage::MakeRasterData(info, skData, bytesPerRow);
@@ -1,3 +1,3 @@
1
1
  import type { Color } from "../../skia";
2
- export declare const interpolateColors: (value: number, inputRange: number[], _outputRange: Color[]) => Float32Array;
2
+ export declare const interpolateColors: (value: number, inputRange: number[], _outputRange: Color[]) => number[];
3
3
  export declare const mixColors: (value: number, x: Color, y: Color) => Float32Array;
@@ -17,8 +17,9 @@ const interpolateColorsRGB = (value, inputRange, outputRange) => {
17
17
  const r = (0, _interpolate.interpolate)(value, inputRange, outputRange.map(c => c[0]), "clamp");
18
18
  const g = (0, _interpolate.interpolate)(value, inputRange, outputRange.map(c => c[1]), "clamp");
19
19
  const b = (0, _interpolate.interpolate)(value, inputRange, outputRange.map(c => c[2]), "clamp");
20
- const a = (0, _interpolate.interpolate)(value, inputRange, outputRange.map(c => c[3]), "clamp");
21
- return new Float32Array([r, g, b, a]);
20
+ const a = (0, _interpolate.interpolate)(value, inputRange, outputRange.map(c => c[3]), "clamp"); // TODO: once Float32Array are supported in the reanimated integration we can switch there
21
+
22
+ return [r, g, b, a];
22
23
  };
23
24
 
24
25
  const interpolateColors = (value, inputRange, _outputRange) => {
@@ -1 +1 @@
1
- {"version":3,"names":["interpolateColorsRGB","value","inputRange","outputRange","r","interpolate","map","c","g","b","a","Float32Array","interpolateColors","_outputRange","cl","Skia","Color","mixColors","x","y","c1","c2","mix"],"sources":["interpolateColors.ts"],"sourcesContent":["import { mix } from \"../../renderer/processors/math\";\nimport type { Color, SkColor } from \"../../skia\";\nimport { Skia } from \"../../skia\";\n\nimport { interpolate } from \"./interpolate\";\n\nconst interpolateColorsRGB = (\n value: number,\n inputRange: number[],\n outputRange: SkColor[]\n) => {\n \"worklet\";\n const r = interpolate(\n value,\n inputRange,\n outputRange.map((c) => c[0]),\n \"clamp\"\n );\n const g = interpolate(\n value,\n inputRange,\n outputRange.map((c) => c[1]),\n \"clamp\"\n );\n const b = interpolate(\n value,\n inputRange,\n outputRange.map((c) => c[2]),\n \"clamp\"\n );\n const a = interpolate(\n value,\n inputRange,\n outputRange.map((c) => c[3]),\n \"clamp\"\n );\n return new Float32Array([r, g, b, a]);\n};\n\nexport const interpolateColors = (\n value: number,\n inputRange: number[],\n _outputRange: Color[]\n) => {\n \"worklet\";\n const outputRange = _outputRange.map((cl) => Skia.Color(cl));\n return interpolateColorsRGB(value, inputRange, outputRange);\n};\n\nexport const mixColors = (value: number, x: Color, y: Color) => {\n \"worklet\";\n const c1 = Skia.Color(x);\n const c2 = Skia.Color(y);\n return new Float32Array([\n mix(value, c1[0], c2[0]),\n mix(value, c1[1], c2[1]),\n mix(value, c1[2], c2[2]),\n mix(value, c1[3], c2[3]),\n ]);\n};\n"],"mappings":";;;;;;;AAAA;;AAEA;;AAEA;;AAEA,MAAMA,oBAAoB,GAAG,CAC3BC,KAD2B,EAE3BC,UAF2B,EAG3BC,WAH2B,KAIxB;EACH;;EACA,MAAMC,CAAC,GAAG,IAAAC,wBAAA,EACRJ,KADQ,EAERC,UAFQ,EAGRC,WAAW,CAACG,GAAZ,CAAiBC,CAAD,IAAOA,CAAC,CAAC,CAAD,CAAxB,CAHQ,EAIR,OAJQ,CAAV;EAMA,MAAMC,CAAC,GAAG,IAAAH,wBAAA,EACRJ,KADQ,EAERC,UAFQ,EAGRC,WAAW,CAACG,GAAZ,CAAiBC,CAAD,IAAOA,CAAC,CAAC,CAAD,CAAxB,CAHQ,EAIR,OAJQ,CAAV;EAMA,MAAME,CAAC,GAAG,IAAAJ,wBAAA,EACRJ,KADQ,EAERC,UAFQ,EAGRC,WAAW,CAACG,GAAZ,CAAiBC,CAAD,IAAOA,CAAC,CAAC,CAAD,CAAxB,CAHQ,EAIR,OAJQ,CAAV;EAMA,MAAMG,CAAC,GAAG,IAAAL,wBAAA,EACRJ,KADQ,EAERC,UAFQ,EAGRC,WAAW,CAACG,GAAZ,CAAiBC,CAAD,IAAOA,CAAC,CAAC,CAAD,CAAxB,CAHQ,EAIR,OAJQ,CAAV;EAMA,OAAO,IAAII,YAAJ,CAAiB,CAACP,CAAD,EAAII,CAAJ,EAAOC,CAAP,EAAUC,CAAV,CAAjB,CAAP;AACD,CA/BD;;AAiCO,MAAME,iBAAiB,GAAG,CAC/BX,KAD+B,EAE/BC,UAF+B,EAG/BW,YAH+B,KAI5B;EACH;;EACA,MAAMV,WAAW,GAAGU,YAAY,CAACP,GAAb,CAAkBQ,EAAD,IAAQC,UAAA,CAAKC,KAAL,CAAWF,EAAX,CAAzB,CAApB;;EACA,OAAOd,oBAAoB,CAACC,KAAD,EAAQC,UAAR,EAAoBC,WAApB,CAA3B;AACD,CARM;;;;AAUA,MAAMc,SAAS,GAAG,CAAChB,KAAD,EAAgBiB,CAAhB,EAA0BC,CAA1B,KAAuC;EAC9D;;EACA,MAAMC,EAAE,GAAGL,UAAA,CAAKC,KAAL,CAAWE,CAAX,CAAX;;EACA,MAAMG,EAAE,GAAGN,UAAA,CAAKC,KAAL,CAAWG,CAAX,CAAX;;EACA,OAAO,IAAIR,YAAJ,CAAiB,CACtB,IAAAW,SAAA,EAAIrB,KAAJ,EAAWmB,EAAE,CAAC,CAAD,CAAb,EAAkBC,EAAE,CAAC,CAAD,CAApB,CADsB,EAEtB,IAAAC,SAAA,EAAIrB,KAAJ,EAAWmB,EAAE,CAAC,CAAD,CAAb,EAAkBC,EAAE,CAAC,CAAD,CAApB,CAFsB,EAGtB,IAAAC,SAAA,EAAIrB,KAAJ,EAAWmB,EAAE,CAAC,CAAD,CAAb,EAAkBC,EAAE,CAAC,CAAD,CAApB,CAHsB,EAItB,IAAAC,SAAA,EAAIrB,KAAJ,EAAWmB,EAAE,CAAC,CAAD,CAAb,EAAkBC,EAAE,CAAC,CAAD,CAApB,CAJsB,CAAjB,CAAP;AAMD,CAVM"}
1
+ {"version":3,"names":["interpolateColorsRGB","value","inputRange","outputRange","r","interpolate","map","c","g","b","a","interpolateColors","_outputRange","cl","Skia","Color","mixColors","x","y","c1","c2","Float32Array","mix"],"sources":["interpolateColors.ts"],"sourcesContent":["import { mix } from \"../../renderer/processors/math\";\nimport type { Color, SkColor } from \"../../skia\";\nimport { Skia } from \"../../skia\";\n\nimport { interpolate } from \"./interpolate\";\n\nconst interpolateColorsRGB = (\n value: number,\n inputRange: number[],\n outputRange: SkColor[]\n) => {\n \"worklet\";\n const r = interpolate(\n value,\n inputRange,\n outputRange.map((c) => c[0]),\n \"clamp\"\n );\n const g = interpolate(\n value,\n inputRange,\n outputRange.map((c) => c[1]),\n \"clamp\"\n );\n const b = interpolate(\n value,\n inputRange,\n outputRange.map((c) => c[2]),\n \"clamp\"\n );\n const a = interpolate(\n value,\n inputRange,\n outputRange.map((c) => c[3]),\n \"clamp\"\n );\n // TODO: once Float32Array are supported in the reanimated integration we can switch there\n return [r, g, b, a];\n};\n\nexport const interpolateColors = (\n value: number,\n inputRange: number[],\n _outputRange: Color[]\n) => {\n \"worklet\";\n const outputRange = _outputRange.map((cl) => Skia.Color(cl));\n return interpolateColorsRGB(value, inputRange, outputRange);\n};\n\nexport const mixColors = (value: number, x: Color, y: Color) => {\n \"worklet\";\n const c1 = Skia.Color(x);\n const c2 = Skia.Color(y);\n return new Float32Array([\n mix(value, c1[0], c2[0]),\n mix(value, c1[1], c2[1]),\n mix(value, c1[2], c2[2]),\n mix(value, c1[3], c2[3]),\n ]);\n};\n"],"mappings":";;;;;;;AAAA;;AAEA;;AAEA;;AAEA,MAAMA,oBAAoB,GAAG,CAC3BC,KAD2B,EAE3BC,UAF2B,EAG3BC,WAH2B,KAIxB;EACH;;EACA,MAAMC,CAAC,GAAG,IAAAC,wBAAA,EACRJ,KADQ,EAERC,UAFQ,EAGRC,WAAW,CAACG,GAAZ,CAAiBC,CAAD,IAAOA,CAAC,CAAC,CAAD,CAAxB,CAHQ,EAIR,OAJQ,CAAV;EAMA,MAAMC,CAAC,GAAG,IAAAH,wBAAA,EACRJ,KADQ,EAERC,UAFQ,EAGRC,WAAW,CAACG,GAAZ,CAAiBC,CAAD,IAAOA,CAAC,CAAC,CAAD,CAAxB,CAHQ,EAIR,OAJQ,CAAV;EAMA,MAAME,CAAC,GAAG,IAAAJ,wBAAA,EACRJ,KADQ,EAERC,UAFQ,EAGRC,WAAW,CAACG,GAAZ,CAAiBC,CAAD,IAAOA,CAAC,CAAC,CAAD,CAAxB,CAHQ,EAIR,OAJQ,CAAV;EAMA,MAAMG,CAAC,GAAG,IAAAL,wBAAA,EACRJ,KADQ,EAERC,UAFQ,EAGRC,WAAW,CAACG,GAAZ,CAAiBC,CAAD,IAAOA,CAAC,CAAC,CAAD,CAAxB,CAHQ,EAIR,OAJQ,CAAV,CApBG,CA0BH;;EACA,OAAO,CAACH,CAAD,EAAII,CAAJ,EAAOC,CAAP,EAAUC,CAAV,CAAP;AACD,CAhCD;;AAkCO,MAAMC,iBAAiB,GAAG,CAC/BV,KAD+B,EAE/BC,UAF+B,EAG/BU,YAH+B,KAI5B;EACH;;EACA,MAAMT,WAAW,GAAGS,YAAY,CAACN,GAAb,CAAkBO,EAAD,IAAQC,UAAA,CAAKC,KAAL,CAAWF,EAAX,CAAzB,CAApB;;EACA,OAAOb,oBAAoB,CAACC,KAAD,EAAQC,UAAR,EAAoBC,WAApB,CAA3B;AACD,CARM;;;;AAUA,MAAMa,SAAS,GAAG,CAACf,KAAD,EAAgBgB,CAAhB,EAA0BC,CAA1B,KAAuC;EAC9D;;EACA,MAAMC,EAAE,GAAGL,UAAA,CAAKC,KAAL,CAAWE,CAAX,CAAX;;EACA,MAAMG,EAAE,GAAGN,UAAA,CAAKC,KAAL,CAAWG,CAAX,CAAX;;EACA,OAAO,IAAIG,YAAJ,CAAiB,CACtB,IAAAC,SAAA,EAAIrB,KAAJ,EAAWkB,EAAE,CAAC,CAAD,CAAb,EAAkBC,EAAE,CAAC,CAAD,CAApB,CADsB,EAEtB,IAAAE,SAAA,EAAIrB,KAAJ,EAAWkB,EAAE,CAAC,CAAD,CAAb,EAAkBC,EAAE,CAAC,CAAD,CAApB,CAFsB,EAGtB,IAAAE,SAAA,EAAIrB,KAAJ,EAAWkB,EAAE,CAAC,CAAD,CAAb,EAAkBC,EAAE,CAAC,CAAD,CAApB,CAHsB,EAItB,IAAAE,SAAA,EAAIrB,KAAJ,EAAWkB,EAAE,CAAC,CAAD,CAAb,EAAkBC,EAAE,CAAC,CAAD,CAApB,CAJsB,CAAjB,CAAP;AAMD,CAVM"}
@@ -1,2 +1,2 @@
1
1
  export declare type SkColor = Float32Array;
2
- export declare type Color = string | Float32Array | number;
2
+ export declare type Color = string | Float32Array | number | number[];
@@ -1 +1 @@
1
- {"version":3,"names":[],"sources":["Color.ts"],"sourcesContent":["// This is the JSI color\nexport type SkColor = Float32Array;\n// Input colors can be string, number or Float32Array\nexport type Color = string | Float32Array | number;\n"],"mappings":""}
1
+ {"version":3,"names":[],"sources":["Color.ts"],"sourcesContent":["// This is the JSI color\nexport type SkColor = Float32Array;\n// Input colors can be string, number or Float32Array\nexport type Color = string | Float32Array | number | number[];\n"],"mappings":""}
@@ -13,12 +13,12 @@ export declare enum MatrixIndex {
13
13
  }
14
14
  export declare const isMatrix: (obj: unknown) => obj is SkMatrix;
15
15
  export interface SkMatrix extends SkJSIInstance<"Matrix"> {
16
- concat: (matrix: SkMatrix) => void;
17
- translate: (x: number, y: number) => void;
18
- scale: (x: number, y?: number) => void;
19
- skew: (x: number, y: number) => void;
20
- rotate: (theta: number) => void;
21
- identity: () => void;
16
+ concat: (matrix: SkMatrix) => SkMatrix;
17
+ translate: (x: number, y: number) => SkMatrix;
18
+ scale: (x: number, y?: number) => SkMatrix;
19
+ skew: (x: number, y: number) => SkMatrix;
20
+ rotate: (theta: number) => SkMatrix;
21
+ identity: () => SkMatrix;
22
22
  get: () => number[];
23
23
  }
24
24
  declare type Transform2dName = "translateX" | "translateY" | "scale" | "skewX" | "skewY" | "scaleX" | "scaleY" | "rotateZ" | "rotate";
@@ -1 +1 @@
1
- {"version":3,"names":["MatrixIndex","isMatrix","obj","__typename__","processTransform","m","transforms","transform","key","Object","keys","value","translate","scale","skew","rotate","toDegrees","exhaustiveCheck","a","Error","rad","Math","PI"],"sources":["Matrix.ts"],"sourcesContent":["import type { SkJSIInstance } from \"./JsiInstance\";\nimport type { SkCanvas } from \"./Canvas\";\nexport enum MatrixIndex {\n ScaleX = 0,\n SkewX = 1,\n TransX = 2,\n SkewY = 3,\n ScaleY = 4,\n TransY = 5,\n Persp0 = 6,\n Persp1 = 7,\n Persp2 = 8,\n}\n\nexport const isMatrix = (obj: unknown): obj is SkMatrix =>\n obj !== null && (obj as SkJSIInstance<string>).__typename__ === \"Matrix\";\n\nexport interface SkMatrix extends SkJSIInstance<\"Matrix\"> {\n concat: (matrix: SkMatrix) => void;\n translate: (x: number, y: number) => void;\n scale: (x: number, y?: number) => void;\n skew: (x: number, y: number) => void;\n rotate: (theta: number) => void;\n identity: () => void;\n get: () => number[];\n}\n\ntype Transform2dName =\n | \"translateX\"\n | \"translateY\"\n | \"scale\"\n | \"skewX\"\n | \"skewY\"\n | \"scaleX\"\n | \"scaleY\"\n | \"rotateZ\"\n | \"rotate\";\n\ntype Transformations = {\n readonly [Name in Transform2dName]: number;\n};\n\nexport type Transforms2d = readonly (\n | Pick<Transformations, \"translateX\">\n | Pick<Transformations, \"translateY\">\n | Pick<Transformations, \"scale\">\n | Pick<Transformations, \"scaleX\">\n | Pick<Transformations, \"scaleY\">\n | Pick<Transformations, \"skewX\">\n | Pick<Transformations, \"skewY\">\n | Pick<Transformations, \"rotate\">\n)[];\n\nexport interface TransformProp {\n transform?: Transforms2d;\n}\n\nexport const processTransform = <T extends SkMatrix | SkCanvas>(\n m: T,\n transforms: Transforms2d\n) => {\n for (const transform of transforms) {\n const key = Object.keys(transform)[0] as Transform2dName;\n const value = (transform as Pick<Transformations, typeof key>)[key];\n if (key === \"translateX\") {\n m.translate(value, 0);\n continue;\n }\n if (key === \"translateY\") {\n m.translate(0, value);\n continue;\n }\n if (key === \"scale\") {\n m.scale(value, value);\n continue;\n }\n if (key === \"scaleX\") {\n m.scale(value, 1);\n continue;\n }\n if (key === \"scaleY\") {\n m.scale(1, value);\n continue;\n }\n if (key === \"skewX\") {\n m.skew(value, 0);\n continue;\n }\n if (key === \"skewY\") {\n m.skew(0, value);\n continue;\n }\n if (key === \"rotate\" || key === \"rotateZ\") {\n if (isMatrix(m)) {\n m.rotate(value);\n } else {\n m.rotate(toDegrees(value), 0, 0);\n }\n continue;\n }\n exhaustiveCheck(key);\n }\n return m;\n};\n\nconst exhaustiveCheck = (a: never): never => {\n throw new Error(`Unknown transformation: ${a}`);\n};\n\nexport const toDegrees = (rad: number) => {\n return (rad * 180) / Math.PI;\n};\n"],"mappings":";;;;;;IAEYA,W;;;WAAAA,W;EAAAA,W,CAAAA,W;EAAAA,W,CAAAA,W;EAAAA,W,CAAAA,W;EAAAA,W,CAAAA,W;EAAAA,W,CAAAA,W;EAAAA,W,CAAAA,W;EAAAA,W,CAAAA,W;EAAAA,W,CAAAA,W;EAAAA,W,CAAAA,W;GAAAA,W,2BAAAA,W;;AAYL,MAAMC,QAAQ,GAAIC,GAAD,IACtBA,GAAG,KAAK,IAAR,IAAiBA,GAAD,CAA+BC,YAA/B,KAAgD,QAD3D;;;;AA2CA,MAAMC,gBAAgB,GAAG,CAC9BC,CAD8B,EAE9BC,UAF8B,KAG3B;EACH,KAAK,MAAMC,SAAX,IAAwBD,UAAxB,EAAoC;IAClC,MAAME,GAAG,GAAGC,MAAM,CAACC,IAAP,CAAYH,SAAZ,EAAuB,CAAvB,CAAZ;IACA,MAAMI,KAAK,GAAIJ,SAAD,CAAiDC,GAAjD,CAAd;;IACA,IAAIA,GAAG,KAAK,YAAZ,EAA0B;MACxBH,CAAC,CAACO,SAAF,CAAYD,KAAZ,EAAmB,CAAnB;MACA;IACD;;IACD,IAAIH,GAAG,KAAK,YAAZ,EAA0B;MACxBH,CAAC,CAACO,SAAF,CAAY,CAAZ,EAAeD,KAAf;MACA;IACD;;IACD,IAAIH,GAAG,KAAK,OAAZ,EAAqB;MACnBH,CAAC,CAACQ,KAAF,CAAQF,KAAR,EAAeA,KAAf;MACA;IACD;;IACD,IAAIH,GAAG,KAAK,QAAZ,EAAsB;MACpBH,CAAC,CAACQ,KAAF,CAAQF,KAAR,EAAe,CAAf;MACA;IACD;;IACD,IAAIH,GAAG,KAAK,QAAZ,EAAsB;MACpBH,CAAC,CAACQ,KAAF,CAAQ,CAAR,EAAWF,KAAX;MACA;IACD;;IACD,IAAIH,GAAG,KAAK,OAAZ,EAAqB;MACnBH,CAAC,CAACS,IAAF,CAAOH,KAAP,EAAc,CAAd;MACA;IACD;;IACD,IAAIH,GAAG,KAAK,OAAZ,EAAqB;MACnBH,CAAC,CAACS,IAAF,CAAO,CAAP,EAAUH,KAAV;MACA;IACD;;IACD,IAAIH,GAAG,KAAK,QAAR,IAAoBA,GAAG,KAAK,SAAhC,EAA2C;MACzC,IAAIP,QAAQ,CAACI,CAAD,CAAZ,EAAiB;QACfA,CAAC,CAACU,MAAF,CAASJ,KAAT;MACD,CAFD,MAEO;QACLN,CAAC,CAACU,MAAF,CAASC,SAAS,CAACL,KAAD,CAAlB,EAA2B,CAA3B,EAA8B,CAA9B;MACD;;MACD;IACD;;IACDM,eAAe,CAACT,GAAD,CAAf;EACD;;EACD,OAAOH,CAAP;AACD,CA9CM;;;;AAgDP,MAAMY,eAAe,GAAIC,CAAD,IAAqB;EAC3C,MAAM,IAAIC,KAAJ,CAAW,2BAA0BD,CAAE,EAAvC,CAAN;AACD,CAFD;;AAIO,MAAMF,SAAS,GAAII,GAAD,IAAiB;EACxC,OAAQA,GAAG,GAAG,GAAP,GAAcC,IAAI,CAACC,EAA1B;AACD,CAFM"}
1
+ {"version":3,"names":["MatrixIndex","isMatrix","obj","__typename__","processTransform","m","transforms","transform","key","Object","keys","value","translate","scale","skew","rotate","toDegrees","exhaustiveCheck","a","Error","rad","Math","PI"],"sources":["Matrix.ts"],"sourcesContent":["import type { SkJSIInstance } from \"./JsiInstance\";\nimport type { SkCanvas } from \"./Canvas\";\nexport enum MatrixIndex {\n ScaleX = 0,\n SkewX = 1,\n TransX = 2,\n SkewY = 3,\n ScaleY = 4,\n TransY = 5,\n Persp0 = 6,\n Persp1 = 7,\n Persp2 = 8,\n}\n\nexport const isMatrix = (obj: unknown): obj is SkMatrix =>\n obj !== null && (obj as SkJSIInstance<string>).__typename__ === \"Matrix\";\n\nexport interface SkMatrix extends SkJSIInstance<\"Matrix\"> {\n concat: (matrix: SkMatrix) => SkMatrix;\n translate: (x: number, y: number) => SkMatrix;\n scale: (x: number, y?: number) => SkMatrix;\n skew: (x: number, y: number) => SkMatrix;\n rotate: (theta: number) => SkMatrix;\n identity: () => SkMatrix;\n get: () => number[];\n}\n\ntype Transform2dName =\n | \"translateX\"\n | \"translateY\"\n | \"scale\"\n | \"skewX\"\n | \"skewY\"\n | \"scaleX\"\n | \"scaleY\"\n | \"rotateZ\"\n | \"rotate\";\n\ntype Transformations = {\n readonly [Name in Transform2dName]: number;\n};\n\nexport type Transforms2d = readonly (\n | Pick<Transformations, \"translateX\">\n | Pick<Transformations, \"translateY\">\n | Pick<Transformations, \"scale\">\n | Pick<Transformations, \"scaleX\">\n | Pick<Transformations, \"scaleY\">\n | Pick<Transformations, \"skewX\">\n | Pick<Transformations, \"skewY\">\n | Pick<Transformations, \"rotate\">\n)[];\n\nexport interface TransformProp {\n transform?: Transforms2d;\n}\n\nexport const processTransform = <T extends SkMatrix | SkCanvas>(\n m: T,\n transforms: Transforms2d\n) => {\n for (const transform of transforms) {\n const key = Object.keys(transform)[0] as Transform2dName;\n const value = (transform as Pick<Transformations, typeof key>)[key];\n if (key === \"translateX\") {\n m.translate(value, 0);\n continue;\n }\n if (key === \"translateY\") {\n m.translate(0, value);\n continue;\n }\n if (key === \"scale\") {\n m.scale(value, value);\n continue;\n }\n if (key === \"scaleX\") {\n m.scale(value, 1);\n continue;\n }\n if (key === \"scaleY\") {\n m.scale(1, value);\n continue;\n }\n if (key === \"skewX\") {\n m.skew(value, 0);\n continue;\n }\n if (key === \"skewY\") {\n m.skew(0, value);\n continue;\n }\n if (key === \"rotate\" || key === \"rotateZ\") {\n if (isMatrix(m)) {\n m.rotate(value);\n } else {\n m.rotate(toDegrees(value), 0, 0);\n }\n continue;\n }\n exhaustiveCheck(key);\n }\n return m;\n};\n\nconst exhaustiveCheck = (a: never): never => {\n throw new Error(`Unknown transformation: ${a}`);\n};\n\nexport const toDegrees = (rad: number) => {\n return (rad * 180) / Math.PI;\n};\n"],"mappings":";;;;;;IAEYA,W;;;WAAAA,W;EAAAA,W,CAAAA,W;EAAAA,W,CAAAA,W;EAAAA,W,CAAAA,W;EAAAA,W,CAAAA,W;EAAAA,W,CAAAA,W;EAAAA,W,CAAAA,W;EAAAA,W,CAAAA,W;EAAAA,W,CAAAA,W;EAAAA,W,CAAAA,W;GAAAA,W,2BAAAA,W;;AAYL,MAAMC,QAAQ,GAAIC,GAAD,IACtBA,GAAG,KAAK,IAAR,IAAiBA,GAAD,CAA+BC,YAA/B,KAAgD,QAD3D;;;;AA2CA,MAAMC,gBAAgB,GAAG,CAC9BC,CAD8B,EAE9BC,UAF8B,KAG3B;EACH,KAAK,MAAMC,SAAX,IAAwBD,UAAxB,EAAoC;IAClC,MAAME,GAAG,GAAGC,MAAM,CAACC,IAAP,CAAYH,SAAZ,EAAuB,CAAvB,CAAZ;IACA,MAAMI,KAAK,GAAIJ,SAAD,CAAiDC,GAAjD,CAAd;;IACA,IAAIA,GAAG,KAAK,YAAZ,EAA0B;MACxBH,CAAC,CAACO,SAAF,CAAYD,KAAZ,EAAmB,CAAnB;MACA;IACD;;IACD,IAAIH,GAAG,KAAK,YAAZ,EAA0B;MACxBH,CAAC,CAACO,SAAF,CAAY,CAAZ,EAAeD,KAAf;MACA;IACD;;IACD,IAAIH,GAAG,KAAK,OAAZ,EAAqB;MACnBH,CAAC,CAACQ,KAAF,CAAQF,KAAR,EAAeA,KAAf;MACA;IACD;;IACD,IAAIH,GAAG,KAAK,QAAZ,EAAsB;MACpBH,CAAC,CAACQ,KAAF,CAAQF,KAAR,EAAe,CAAf;MACA;IACD;;IACD,IAAIH,GAAG,KAAK,QAAZ,EAAsB;MACpBH,CAAC,CAACQ,KAAF,CAAQ,CAAR,EAAWF,KAAX;MACA;IACD;;IACD,IAAIH,GAAG,KAAK,OAAZ,EAAqB;MACnBH,CAAC,CAACS,IAAF,CAAOH,KAAP,EAAc,CAAd;MACA;IACD;;IACD,IAAIH,GAAG,KAAK,OAAZ,EAAqB;MACnBH,CAAC,CAACS,IAAF,CAAO,CAAP,EAAUH,KAAV;MACA;IACD;;IACD,IAAIH,GAAG,KAAK,QAAR,IAAoBA,GAAG,KAAK,SAAhC,EAA2C;MACzC,IAAIP,QAAQ,CAACI,CAAD,CAAZ,EAAiB;QACfA,CAAC,CAACU,MAAF,CAASJ,KAAT;MACD,CAFD,MAEO;QACLN,CAAC,CAACU,MAAF,CAASC,SAAS,CAACL,KAAD,CAAlB,EAA2B,CAA3B,EAA8B,CAA9B;MACD;;MACD;IACD;;IACDM,eAAe,CAACT,GAAD,CAAf;EACD;;EACD,OAAOH,CAAP;AACD,CA9CM;;;;AAgDP,MAAMY,eAAe,GAAIC,CAAD,IAAqB;EAC3C,MAAM,IAAIC,KAAJ,CAAW,2BAA0BD,CAAE,EAAvC,CAAN;AACD,CAFD;;AAIO,MAAMF,SAAS,GAAII,GAAD,IAAiB;EACxC,OAAQA,GAAG,GAAG,GAAP,GAAcC,IAAI,CAACC,EAA1B;AACD,CAFM"}
@@ -334,6 +334,8 @@ const parseCSSColor = cssStr => {
334
334
  const Color = color => {
335
335
  if (color instanceof Float32Array) {
336
336
  return color;
337
+ } else if (Array.isArray(color)) {
338
+ return new Float32Array(color);
337
339
  } else if (typeof color === "string") {
338
340
  const r = parseCSSColor(color);
339
341
  const rgba = r === null ? CSSColorTable.black : r;