@shopify/react-native-skia 0.1.121 → 0.1.124

Sign up to get free protection for your applications and to get access to all the features.
Files changed (144) hide show
  1. package/android/CMakeLists.txt +3 -1
  2. package/android/cpp/jni/JniSkiaDrawView.cpp +14 -71
  3. package/android/cpp/jni/JniSkiaManager.cpp +1 -1
  4. package/android/cpp/jni/include/JniSkiaDrawView.h +18 -22
  5. package/android/cpp/jni/include/JniSkiaManager.h +4 -4
  6. package/android/cpp/rnskia-android/RNSkDrawViewImpl.cpp +68 -0
  7. package/android/cpp/rnskia-android/RNSkDrawViewImpl.h +48 -0
  8. package/android/cpp/{jni/include/JniPlatformContextWrapper.h → rnskia-android/RNSkPlatformContextImpl.h} +4 -4
  9. package/android/cpp/{jni → rnskia-android}/SkiaOpenGLRenderer.cpp +39 -54
  10. package/android/cpp/{jni/include → rnskia-android}/SkiaOpenGLRenderer.h +2 -31
  11. package/android/src/main/java/com/shopify/reactnative/skia/RNSkiaViewManager.java +1 -1
  12. package/android/src/main/java/com/shopify/reactnative/skia/SkiaDrawView.java +21 -28
  13. package/cpp/api/JsiSkApi.h +2 -0
  14. package/cpp/api/JsiSkColor.h +49 -0
  15. package/cpp/api/JsiSkPath.h +31 -2
  16. package/cpp/api/JsiSkPathFactory.h +96 -1
  17. package/cpp/api/third_party/CSSColorParser.h +324 -0
  18. package/cpp/rnskia/RNSkAnimation.h +3 -8
  19. package/cpp/rnskia/RNSkDrawView.cpp +84 -126
  20. package/cpp/rnskia/RNSkDrawView.h +7 -37
  21. package/cpp/rnskia/RNSkJsiViewApi.h +8 -5
  22. package/cpp/rnskia/RNSkManager.cpp +2 -2
  23. package/cpp/rnskia/RNSkManager.h +2 -2
  24. package/cpp/rnskia/RNSkPlatformContext.h +1 -1
  25. package/cpp/rnskia/RNSkValueApi.h +6 -2
  26. package/cpp/rnskia/values/RNSkClockValue.h +21 -13
  27. package/cpp/rnskia/values/RNSkDerivedValue.h +13 -6
  28. package/cpp/rnskia/values/RNSkReadonlyValue.h +17 -16
  29. package/cpp/rnskia/values/RNSkValue.h +8 -3
  30. package/cpp/utils/RNSkTimingInfo.h +13 -1
  31. package/ios/RNSkia-iOS/RNSkDrawViewImpl.h +8 -10
  32. package/ios/RNSkia-iOS/RNSkDrawViewImpl.mm +25 -10
  33. package/ios/RNSkia-iOS/SkiaDrawView.mm +21 -16
  34. package/lib/commonjs/renderer/Canvas.js +17 -8
  35. package/lib/commonjs/renderer/Canvas.js.map +1 -1
  36. package/lib/commonjs/renderer/components/Paint.js +1 -1
  37. package/lib/commonjs/renderer/components/Paint.js.map +1 -1
  38. package/lib/commonjs/renderer/components/colorFilters/Lerp.js +1 -1
  39. package/lib/commonjs/renderer/components/colorFilters/Lerp.js.map +1 -1
  40. package/lib/commonjs/renderer/components/shaders/Shader.js +2 -2
  41. package/lib/commonjs/renderer/components/shaders/Shader.js.map +1 -1
  42. package/lib/commonjs/renderer/components/shapes/Path.js +10 -2
  43. package/lib/commonjs/renderer/components/shapes/Path.js.map +1 -1
  44. package/lib/commonjs/renderer/nodes/Node.js +3 -3
  45. package/lib/commonjs/renderer/nodes/Node.js.map +1 -1
  46. package/lib/commonjs/renderer/processors/Circles.js +3 -2
  47. package/lib/commonjs/renderer/processors/Circles.js.map +1 -1
  48. package/lib/commonjs/renderer/processors/Font.js +1 -1
  49. package/lib/commonjs/renderer/processors/Font.js.map +1 -1
  50. package/lib/commonjs/renderer/processors/Paint.js +6 -1
  51. package/lib/commonjs/renderer/processors/Paint.js.map +1 -1
  52. package/lib/commonjs/renderer/processors/Rects.js +6 -6
  53. package/lib/commonjs/renderer/processors/Rects.js.map +1 -1
  54. package/lib/commonjs/skia/Color.js +3 -25
  55. package/lib/commonjs/skia/Color.js.map +1 -1
  56. package/lib/commonjs/skia/Image/Image.js.map +1 -1
  57. package/lib/commonjs/skia/ImageFilter/ImageFilterFactory.js.map +1 -1
  58. package/lib/commonjs/skia/Paint/Paint.js +13 -1
  59. package/lib/commonjs/skia/Paint/Paint.js.map +1 -1
  60. package/lib/commonjs/skia/Paint/usePaint.js +2 -4
  61. package/lib/commonjs/skia/Paint/usePaint.js.map +1 -1
  62. package/lib/commonjs/skia/Path/Path.js +13 -1
  63. package/lib/commonjs/skia/Path/Path.js.map +1 -1
  64. package/lib/commonjs/skia/Shader/Shader.js.map +1 -1
  65. package/lib/commonjs/skia/Skia.js +43 -3
  66. package/lib/commonjs/skia/Skia.js.map +1 -1
  67. package/lib/commonjs/values/animation/timing/functions/getResolvedParams.js +3 -3
  68. package/lib/commonjs/values/animation/timing/functions/getResolvedParams.js.map +1 -1
  69. package/lib/module/renderer/Canvas.js +12 -6
  70. package/lib/module/renderer/Canvas.js.map +1 -1
  71. package/lib/module/renderer/components/Paint.js +2 -2
  72. package/lib/module/renderer/components/Paint.js.map +1 -1
  73. package/lib/module/renderer/components/colorFilters/Lerp.js +1 -1
  74. package/lib/module/renderer/components/colorFilters/Lerp.js.map +1 -1
  75. package/lib/module/renderer/components/shaders/Shader.js +3 -2
  76. package/lib/module/renderer/components/shaders/Shader.js.map +1 -1
  77. package/lib/module/renderer/components/shapes/Path.js +10 -3
  78. package/lib/module/renderer/components/shapes/Path.js.map +1 -1
  79. package/lib/module/renderer/nodes/Node.js +3 -3
  80. package/lib/module/renderer/nodes/Node.js.map +1 -1
  81. package/lib/module/renderer/processors/Circles.js +3 -2
  82. package/lib/module/renderer/processors/Circles.js.map +1 -1
  83. package/lib/module/renderer/processors/Font.js +1 -1
  84. package/lib/module/renderer/processors/Font.js.map +1 -1
  85. package/lib/module/renderer/processors/Paint.js +6 -1
  86. package/lib/module/renderer/processors/Paint.js.map +1 -1
  87. package/lib/module/renderer/processors/Rects.js +5 -6
  88. package/lib/module/renderer/processors/Rects.js.map +1 -1
  89. package/lib/module/skia/Color.js +2 -21
  90. package/lib/module/skia/Color.js.map +1 -1
  91. package/lib/module/skia/Image/Image.js.map +1 -1
  92. package/lib/module/skia/ImageFilter/ImageFilterFactory.js.map +1 -1
  93. package/lib/module/skia/Paint/Paint.js +6 -0
  94. package/lib/module/skia/Paint/Paint.js.map +1 -1
  95. package/lib/module/skia/Paint/usePaint.js +2 -3
  96. package/lib/module/skia/Paint/usePaint.js.map +1 -1
  97. package/lib/module/skia/Path/Path.js +11 -0
  98. package/lib/module/skia/Path/Path.js.map +1 -1
  99. package/lib/module/skia/Shader/Shader.js.map +1 -1
  100. package/lib/module/skia/Skia.js +45 -2
  101. package/lib/module/skia/Skia.js.map +1 -1
  102. package/lib/module/values/animation/timing/functions/getResolvedParams.js +3 -3
  103. package/lib/module/values/animation/timing/functions/getResolvedParams.js.map +1 -1
  104. package/lib/typescript/src/renderer/Canvas.d.ts +6 -0
  105. package/lib/typescript/src/renderer/components/shapes/Path.d.ts +3 -1
  106. package/lib/typescript/src/renderer/processors/Paint.d.ts +2 -1
  107. package/lib/typescript/src/skia/Color.d.ts +0 -1
  108. package/lib/typescript/src/skia/Image/Image.d.ts +3 -3
  109. package/lib/typescript/src/skia/ImageFilter/ImageFilterFactory.d.ts +2 -2
  110. package/lib/typescript/src/skia/Paint/Paint.d.ts +3 -2
  111. package/lib/typescript/src/skia/Path/Path.d.ts +13 -0
  112. package/lib/typescript/src/skia/Path/PathFactory.d.ts +7 -1
  113. package/lib/typescript/src/skia/Picture/Picture.d.ts +2 -2
  114. package/lib/typescript/src/skia/RuntimeEffect/RuntimeEffect.d.ts +3 -3
  115. package/lib/typescript/src/skia/Shader/Shader.d.ts +2 -2
  116. package/lib/typescript/src/skia/Shader/ShaderFactory.d.ts +9 -9
  117. package/lib/typescript/src/skia/Skia.d.ts +5 -3
  118. package/lib/typescript/src/values/animation/types.d.ts +5 -5
  119. package/package.json +1 -1
  120. package/scripts/install-npm.js +1 -1
  121. package/src/renderer/Canvas.tsx +13 -6
  122. package/src/renderer/components/Paint.tsx +2 -2
  123. package/src/renderer/components/colorFilters/Lerp.tsx +1 -1
  124. package/src/renderer/components/shaders/Shader.tsx +1 -1
  125. package/src/renderer/components/shapes/Path.tsx +12 -4
  126. package/src/renderer/nodes/Node.ts +3 -3
  127. package/src/renderer/processors/Circles.ts +2 -1
  128. package/src/renderer/processors/Font.ts +1 -1
  129. package/src/renderer/processors/Paint.ts +5 -0
  130. package/src/renderer/processors/Rects.ts +3 -2
  131. package/src/skia/Color.ts +3 -20
  132. package/src/skia/Image/Image.ts +3 -3
  133. package/src/skia/ImageFilter/ImageFilterFactory.ts +2 -2
  134. package/src/skia/Paint/Paint.ts +9 -2
  135. package/src/skia/Paint/usePaint.ts +2 -4
  136. package/src/skia/Path/Path.ts +16 -0
  137. package/src/skia/Path/PathFactory.ts +8 -1
  138. package/src/skia/Picture/Picture.ts +2 -2
  139. package/src/skia/RuntimeEffect/RuntimeEffect.ts +4 -4
  140. package/src/skia/Shader/Shader.ts +2 -2
  141. package/src/skia/Shader/ShaderFactory.ts +9 -9
  142. package/src/skia/Skia.ts +47 -3
  143. package/src/values/animation/timing/functions/getResolvedParams.ts +2 -2
  144. package/src/values/animation/types.ts +5 -5
@@ -18,10 +18,11 @@ public class SkiaDrawView extends TextureView implements TextureView.SurfaceText
18
18
  @DoNotStrip
19
19
  private HybridData mHybridData;
20
20
 
21
- private Surface mSurface;
21
+ @DoNotStrip
22
+ private boolean mViewRemoved;
22
23
 
23
24
  @DoNotStrip
24
- private boolean mIsRemoved = false;
25
+ private Surface mSurface;
25
26
 
26
27
  public SkiaDrawView(Context ctx) {
27
28
  super(ctx);
@@ -36,26 +37,25 @@ public class SkiaDrawView extends TextureView implements TextureView.SurfaceText
36
37
  // Texture view does not support setting the background color.
37
38
  }
38
39
 
39
- @Override
40
- protected void finalize() throws Throwable {
41
- mHybridData.resetNative();
42
- super.finalize();
40
+ public void releaseSurface() {
41
+ if(mSurface != null) {
42
+ mSurface.release();
43
+ mSurface = null;
44
+ }
45
+ // We can only reset the native side when the view was removed from screen.
46
+ // releasing the surface can also be done when the view is hidden and then
47
+ // we should only release the surface - and keep the native part around.
48
+ if(mViewRemoved) {
49
+ mHybridData.resetNative();
50
+ }
43
51
  }
44
52
 
45
-
46
- public void onRemoved() {
47
- // We'll mark the view removed since we reset the native part.
48
- // This means that none of the native methods should be called after
49
- // this point.
50
- mIsRemoved = true;
51
- mHybridData.resetNative();
53
+ void onViewRemoved() {
54
+ mViewRemoved = true;
52
55
  }
53
56
 
54
57
  @Override
55
58
  public boolean onTouchEvent(MotionEvent ev) {
56
- if(mIsRemoved) {
57
- return false;
58
- }
59
59
  int action = ev.getAction();
60
60
  int count = ev.getPointerCount();
61
61
  MotionEvent.PointerCoords r = new MotionEvent.PointerCoords();
@@ -88,30 +88,23 @@ public class SkiaDrawView extends TextureView implements TextureView.SurfaceText
88
88
 
89
89
  @Override
90
90
  public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
91
- if(mIsRemoved) {
92
- return;
93
- }
94
91
  mSurface = new Surface(surface);
95
92
  surfaceAvailable(mSurface, width, height);
96
93
  }
97
94
 
98
95
  @Override
99
96
  public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
100
- if(mIsRemoved) {
101
- return;
102
- }
103
97
  surfaceSizeChanged(width, height);
104
98
  }
105
99
 
106
100
  @Override
107
101
  public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
108
- if(mIsRemoved) {
109
- return true;
110
- }
111
102
  surfaceDestroyed();
112
- mSurface.release();
113
- mSurface = null;
114
- return true;
103
+ // https://developer.android.com/reference/android/view/TextureView.SurfaceTextureListener#onSurfaceTextureDestroyed(android.graphics.SurfaceTexture)
104
+ // Invoked when the specified SurfaceTexture is about to be destroyed. If returns true,
105
+ // no rendering should happen inside the surface texture after this method is invoked.
106
+ // If returns false, the client needs to call SurfaceTexture#release().
107
+ return false;
115
108
  }
116
109
 
117
110
  @Override
@@ -39,6 +39,7 @@
39
39
  #include "JsiSkContourMeasureIter.h"
40
40
  #include "JsiSkPictureRecorder.h"
41
41
  #include "JsiSkPictureFactory.h"
42
+ #include "JsiSkColor.h"
42
43
 
43
44
  namespace RNSkia
44
45
  {
@@ -67,6 +68,7 @@ namespace RNSkia
67
68
  installFunction("ContourMeasureIter", JsiSkContourMeasureIter::createCtor(context));
68
69
  installFunction("MakeVertices", JsiSkVertices::createCtor(context));
69
70
  installFunction("PictureRecorder", JsiSkPictureRecorder::createCtor(context));
71
+ installFunction("parseColorString", JsiSkColor::createCtor());
70
72
 
71
73
  // Static members
72
74
  installReadonlyProperty("FontMgr",
@@ -0,0 +1,49 @@
1
+ #pragma once
2
+
3
+ #include <memory>
4
+ #include <utility>
5
+
6
+ #include <jsi/jsi.h>
7
+
8
+ #include "JsiSkHostObjects.h"
9
+ #include "third_party/CSSColorParser.h"
10
+
11
+ #pragma clang diagnostic push
12
+ #pragma clang diagnostic ignored "-Wdocumentation"
13
+
14
+ #include <SkColor.h>
15
+
16
+ #pragma clang diagnostic pop
17
+
18
+ namespace RNSkia {
19
+
20
+ using namespace facebook;
21
+
22
+ class JsiSkColor : public JsiHostObject {
23
+ public:
24
+
25
+ JsiSkColor(): JsiHostObject() {}
26
+
27
+ ~JsiSkColor() {}
28
+
29
+ /**
30
+ * Creates the function for construction a new instance of the SkColor
31
+ * wrapper
32
+ * @return A function for creating a new host object wrapper for the SkColor
33
+ * class
34
+ */
35
+ static const jsi::HostFunctionType
36
+ createCtor() {
37
+ return JSI_HOST_FUNCTION_LAMBDA {
38
+ auto text = arguments[0].asString(runtime).utf8(runtime);
39
+ auto color = CSSColorParser::parse(text);
40
+ if (color.a == -1.0f) {
41
+ return jsi::Value::undefined();
42
+ }
43
+ int a = round(color.a * 255);
44
+ // Because JS numbers are unsigned we need to do this conversion
45
+ return jsi::Value(static_cast<double>(SkColorSetARGB(a, color.r, color.g, color.b) >> 0));
46
+ };
47
+ }
48
+ };
49
+ } // namespace RNSkia
@@ -29,9 +29,9 @@ namespace RNSkia {
29
29
 
30
30
  using namespace facebook;
31
31
 
32
+
32
33
  class JsiSkPath : public JsiSkWrappingSharedPtrHostObject<SkPath> {
33
34
  public:
34
-
35
35
  // TODO: declare in JsiSkWrappingSkPtrHostObject via extra template parameter?
36
36
  JSI_PROPERTY_GET(__typename__) {
37
37
  return jsi::String::createFromUtf8(runtime, "Path");
@@ -484,6 +484,33 @@ public:
484
484
  runtime, std::make_shared<JsiSkPath>(getContext(), std::move(result)));
485
485
  }
486
486
 
487
+ JSI_HOST_FUNCTION(toCmds) {
488
+ auto path = *getObject();
489
+ auto cmds = jsi::Array(runtime, path.countVerbs());
490
+ auto it = SkPath::Iter(path, false);
491
+ // { "Move", "Line", "Quad", "Conic", "Cubic", "Close", "Done" };
492
+ const int pointCount[] = { 1 , 2 , 3 , 3 , 4 , 1 , 0 };
493
+ const int cmdCount[] = { 3 , 5 , 7 , 8 , 9 , 3 , 0 };
494
+ SkPoint points[4];
495
+ SkPath::Verb verb;
496
+ auto k = 0;
497
+ while (SkPath::kDone_Verb != (verb = it.next(points))) {
498
+ auto verbVal = static_cast<int>(verb);
499
+ auto cmd = jsi::Array(runtime, cmdCount[verbVal]);
500
+ auto j = 0;
501
+ cmd.setValueAtIndex(runtime, j++, jsi::Value(verbVal));
502
+ for (int i = 0; i < pointCount[verbVal]; ++i) {
503
+ cmd.setValueAtIndex(runtime, j++, jsi::Value(static_cast<double>(points[i].fX)));
504
+ cmd.setValueAtIndex(runtime, j++, jsi::Value(static_cast<double>(points[i].fY)));
505
+ }
506
+ if (SkPath::kConic_Verb == verb) {
507
+ cmd.setValueAtIndex(runtime, j, jsi::Value(static_cast<double>(it.conicWeight())));
508
+ }
509
+ cmds.setValueAtIndex(runtime, k++, cmd);
510
+ }
511
+ return cmds;
512
+ }
513
+
487
514
  JSI_EXPORT_PROPERTY_GETTERS(JSI_EXPORT_PROP_GET(JsiSkPath, __typename__))
488
515
 
489
516
  JSI_EXPORT_FUNCTIONS(
@@ -518,7 +545,9 @@ public:
518
545
  JSI_EXPORT_FUNC(JsiSkPath, simplify),
519
546
  JSI_EXPORT_FUNC(JsiSkPath, countPoints), JSI_EXPORT_FUNC(JsiSkPath, copy),
520
547
  JSI_EXPORT_FUNC(JsiSkPath, fromText), JSI_EXPORT_FUNC(JsiSkPath, op),
521
- JSI_EXPORT_FUNC(JsiSkPath, isInterpolatable), JSI_EXPORT_FUNC(JsiSkPath, interpolate)
548
+ JSI_EXPORT_FUNC(JsiSkPath, isInterpolatable),
549
+ JSI_EXPORT_FUNC(JsiSkPath, interpolate),
550
+ JSI_EXPORT_FUNC(JsiSkPath, toCmds),
522
551
  )
523
552
 
524
553
  JsiSkPath(std::shared_ptr<RNSkPlatformContext> context, SkPath path)
@@ -13,6 +13,7 @@
13
13
 
14
14
  #include <SkPath.h>
15
15
  #include <SkPathOps.h>
16
+ #include <RNSkLog.h>
16
17
 
17
18
  #pragma clang diagnostic pop
18
19
 
@@ -21,6 +22,14 @@ namespace RNSkia {
21
22
  using namespace facebook;
22
23
 
23
24
  class JsiSkPathFactory : public JsiSkHostObject {
25
+
26
+ static const int MOVE = 0;
27
+ static const int LINE = 1;
28
+ static const int QUAD = 2;
29
+ static const int CONIC = 3;
30
+ static const int CUBIC = 4;
31
+ static const int CLOSE = 5;
32
+
24
33
  public:
25
34
  JSI_HOST_FUNCTION(Make) {
26
35
  return jsi::Object::createFromHostObject(
@@ -53,9 +62,95 @@ public:
53
62
  runtime, std::make_shared<JsiSkPath>(getContext(), std::move(result)));
54
63
  }
55
64
 
65
+ JSI_HOST_FUNCTION(MakeFromCmds) {
66
+ SkPath path;
67
+ auto cmds = arguments[0].asObject(runtime).asArray(runtime);
68
+ auto cmdCount = cmds.size(runtime);
69
+ for (int i = 0; i < cmdCount; i++) {
70
+ auto cmd = cmds.getValueAtIndex(runtime, i).asObject(runtime).asArray(runtime);
71
+ if (cmd.size(runtime) < 1) {
72
+ RNSkLogger::logToConsole("Invalid command found (got an empty array)");
73
+ return jsi::Value::null();
74
+ }
75
+ auto verb = static_cast<int>(cmd.getValueAtIndex(runtime, 0).asNumber());
76
+ switch (verb) {
77
+ case MOVE: {
78
+ if (cmd.size(runtime) < 3) {
79
+ RNSkLogger::logToConsole( "Invalid move command found");
80
+ return jsi::Value::null();
81
+ }
82
+ auto x = cmd.getValueAtIndex(runtime, 1).asNumber();
83
+ auto y = cmd.getValueAtIndex(runtime, 2).asNumber();
84
+ path.moveTo(x, y);
85
+ break;
86
+ }
87
+ case LINE: {
88
+ if (cmd.size(runtime) < 3) {
89
+ RNSkLogger::logToConsole("Invalid line command found");
90
+ return jsi::Value::null();
91
+ }
92
+ auto x = cmd.getValueAtIndex(runtime, 1).asNumber();
93
+ auto y = cmd.getValueAtIndex(runtime, 2).asNumber();
94
+ path.lineTo(x, y);
95
+ break;
96
+ }
97
+ case QUAD: {
98
+ if (cmd.size(runtime) < 5) {
99
+ RNSkLogger::logToConsole("Invalid line command found");
100
+ return jsi::Value::null();
101
+ }
102
+ auto x1 = cmd.getValueAtIndex(runtime, 1).asNumber();
103
+ auto y1 = cmd.getValueAtIndex(runtime, 2).asNumber();
104
+ auto x2 = cmd.getValueAtIndex(runtime, 3).asNumber();
105
+ auto y2 = cmd.getValueAtIndex(runtime, 4).asNumber();
106
+ path.quadTo(x1, y1, x2, y2);
107
+ break;
108
+ }
109
+ case CONIC: {
110
+ if (cmd.size(runtime) < 6) {
111
+ RNSkLogger::logToConsole("Invalid line command found");
112
+ return jsi::Value::null();
113
+ }
114
+ auto x1 = cmd.getValueAtIndex(runtime, 1).asNumber();
115
+ auto y1 = cmd.getValueAtIndex(runtime, 2).asNumber();
116
+ auto x2 = cmd.getValueAtIndex(runtime, 3).asNumber();
117
+ auto y2 = cmd.getValueAtIndex(runtime, 4).asNumber();
118
+ auto w = cmd.getValueAtIndex(runtime, 5).asNumber();
119
+ path.conicTo(x1, y1, x2, y2, w);
120
+ break;
121
+ }
122
+ case CUBIC: {
123
+ if (cmd.size(runtime) < 7) {
124
+ RNSkLogger::logToConsole("Invalid line command found");
125
+ return jsi::Value::null();
126
+ }
127
+ auto x1 = cmd.getValueAtIndex(runtime, 1).asNumber();
128
+ auto y1 = cmd.getValueAtIndex(runtime, 2).asNumber();
129
+ auto x2 = cmd.getValueAtIndex(runtime, 3).asNumber();
130
+ auto y2 = cmd.getValueAtIndex(runtime, 4).asNumber();
131
+ auto x3 = cmd.getValueAtIndex(runtime, 5).asNumber();
132
+ auto y3 = cmd.getValueAtIndex(runtime, 6).asNumber();
133
+ path.cubicTo(x1, y1, x2, y2, x3, y3);
134
+ break;
135
+ }
136
+ case CLOSE: {
137
+ path.close();
138
+ break;
139
+ }
140
+ default: {
141
+ RNSkLogger::logToConsole("Found an unknown command");
142
+ return jsi::Value::null();
143
+ }
144
+ }
145
+ }
146
+ return jsi::Object::createFromHostObject(
147
+ runtime, std::make_shared<JsiSkPath>(getContext(), std::move(path)));
148
+ }
149
+
56
150
  JSI_EXPORT_FUNCTIONS(JSI_EXPORT_FUNC(JsiSkPathFactory, Make),
57
151
  JSI_EXPORT_FUNC(JsiSkPathFactory, MakeFromSVGString),
58
- JSI_EXPORT_FUNC(JsiSkPathFactory, MakeFromOp))
152
+ JSI_EXPORT_FUNC(JsiSkPathFactory, MakeFromOp),
153
+ JSI_EXPORT_FUNC(JsiSkPathFactory, MakeFromCmds))
59
154
 
60
155
  JsiSkPathFactory(std::shared_ptr<RNSkPlatformContext> context)
61
156
  : JsiSkHostObject(std::move(context)) {}
@@ -0,0 +1,324 @@
1
+ // (c) Dean McNamee <dean@gmail.com>, 2012.
2
+ // C++ port by Mapbox, Konstantin Käfer <mail@kkaefer.com>, 2014-2017.
3
+ //
4
+ // https://github.com/deanm/css-color-parser-js
5
+ // https://github.com/kkaefer/css-color-parser-cpp
6
+ //
7
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ // of this software and associated documentation files (the "Software"), to
9
+ // deal in the Software without restriction, including without limitation the
10
+ // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
11
+ // sell copies of the Software, and to permit persons to whom the Software is
12
+ // furnished to do so, subject to the following conditions:
13
+ //
14
+ // The above copyright notice and this permission notice shall be included in
15
+ // all copies or substantial portions of the Software.
16
+ //
17
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
+ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
23
+ // IN THE SOFTWARE.
24
+
25
+ #pragma once
26
+
27
+ #include <cstdint>
28
+ #include <vector>
29
+ #include <sstream>
30
+ #include <algorithm>
31
+ #include <string>
32
+ #include <cmath>
33
+
34
+ namespace CSSColorParser {
35
+
36
+ struct Color {
37
+ inline Color() {
38
+ }
39
+ inline Color(unsigned char r_, unsigned char g_, unsigned char b_, float a_)
40
+ : r(r_), g(g_), b(b_), a(a_ > 1 ? 1 : a_ < 0 ? 0 : a_) {
41
+ }
42
+ unsigned char r = 0, g = 0, b = 0;
43
+ float a = -1.0f;
44
+ };
45
+
46
+ struct NamedColor { const char *const name; const Color color; };
47
+
48
+ const NamedColor namedColors[] = {
49
+ { "transparent", { 0, 0, 0, 0 } }, { "aliceblue", { 240, 248, 255, 1 } },
50
+ { "antiquewhite", { 250, 235, 215, 1 } }, { "aqua", { 0, 255, 255, 1 } },
51
+ { "aquamarine", { 127, 255, 212, 1 } }, { "azure", { 240, 255, 255, 1 } },
52
+ { "beige", { 245, 245, 220, 1 } }, { "bisque", { 255, 228, 196, 1 } },
53
+ { "black", { 0, 0, 0, 1 } }, { "blanchedalmond", { 255, 235, 205, 1 } },
54
+ { "blue", { 0, 0, 255, 1 } }, { "blueviolet", { 138, 43, 226, 1 } },
55
+ { "brown", { 165, 42, 42, 1 } }, { "burlywood", { 222, 184, 135, 1 } },
56
+ { "cadetblue", { 95, 158, 160, 1 } }, { "chartreuse", { 127, 255, 0, 1 } },
57
+ { "chocolate", { 210, 105, 30, 1 } }, { "coral", { 255, 127, 80, 1 } },
58
+ { "cornflowerblue", { 100, 149, 237, 1 } }, { "cornsilk", { 255, 248, 220, 1 } },
59
+ { "crimson", { 220, 20, 60, 1 } }, { "cyan", { 0, 255, 255, 1 } },
60
+ { "darkblue", { 0, 0, 139, 1 } }, { "darkcyan", { 0, 139, 139, 1 } },
61
+ { "darkgoldenrod", { 184, 134, 11, 1 } }, { "darkgray", { 169, 169, 169, 1 } },
62
+ { "darkgreen", { 0, 100, 0, 1 } }, { "darkgrey", { 169, 169, 169, 1 } },
63
+ { "darkkhaki", { 189, 183, 107, 1 } }, { "darkmagenta", { 139, 0, 139, 1 } },
64
+ { "darkolivegreen", { 85, 107, 47, 1 } }, { "darkorange", { 255, 140, 0, 1 } },
65
+ { "darkorchid", { 153, 50, 204, 1 } }, { "darkred", { 139, 0, 0, 1 } },
66
+ { "darksalmon", { 233, 150, 122, 1 } }, { "darkseagreen", { 143, 188, 143, 1 } },
67
+ { "darkslateblue", { 72, 61, 139, 1 } }, { "darkslategray", { 47, 79, 79, 1 } },
68
+ { "darkslategrey", { 47, 79, 79, 1 } }, { "darkturquoise", { 0, 206, 209, 1 } },
69
+ { "darkviolet", { 148, 0, 211, 1 } }, { "deeppink", { 255, 20, 147, 1 } },
70
+ { "deepskyblue", { 0, 191, 255, 1 } }, { "dimgray", { 105, 105, 105, 1 } },
71
+ { "dimgrey", { 105, 105, 105, 1 } }, { "dodgerblue", { 30, 144, 255, 1 } },
72
+ { "firebrick", { 178, 34, 34, 1 } }, { "floralwhite", { 255, 250, 240, 1 } },
73
+ { "forestgreen", { 34, 139, 34, 1 } }, { "fuchsia", { 255, 0, 255, 1 } },
74
+ { "gainsboro", { 220, 220, 220, 1 } }, { "ghostwhite", { 248, 248, 255, 1 } },
75
+ { "gold", { 255, 215, 0, 1 } }, { "goldenrod", { 218, 165, 32, 1 } },
76
+ { "gray", { 128, 128, 128, 1 } }, { "green", { 0, 128, 0, 1 } },
77
+ { "greenyellow", { 173, 255, 47, 1 } }, { "grey", { 128, 128, 128, 1 } },
78
+ { "honeydew", { 240, 255, 240, 1 } }, { "hotpink", { 255, 105, 180, 1 } },
79
+ { "indianred", { 205, 92, 92, 1 } }, { "indigo", { 75, 0, 130, 1 } },
80
+ { "ivory", { 255, 255, 240, 1 } }, { "khaki", { 240, 230, 140, 1 } },
81
+ { "lavender", { 230, 230, 250, 1 } }, { "lavenderblush", { 255, 240, 245, 1 } },
82
+ { "lawngreen", { 124, 252, 0, 1 } }, { "lemonchiffon", { 255, 250, 205, 1 } },
83
+ { "lightblue", { 173, 216, 230, 1 } }, { "lightcoral", { 240, 128, 128, 1 } },
84
+ { "lightcyan", { 224, 255, 255, 1 } }, { "lightgoldenrodyellow", { 250, 250, 210, 1 } },
85
+ { "lightgray", { 211, 211, 211, 1 } }, { "lightgreen", { 144, 238, 144, 1 } },
86
+ { "lightgrey", { 211, 211, 211, 1 } }, { "lightpink", { 255, 182, 193, 1 } },
87
+ { "lightsalmon", { 255, 160, 122, 1 } }, { "lightseagreen", { 32, 178, 170, 1 } },
88
+ { "lightskyblue", { 135, 206, 250, 1 } }, { "lightslategray", { 119, 136, 153, 1 } },
89
+ { "lightslategrey", { 119, 136, 153, 1 } }, { "lightsteelblue", { 176, 196, 222, 1 } },
90
+ { "lightyellow", { 255, 255, 224, 1 } }, { "lime", { 0, 255, 0, 1 } },
91
+ { "limegreen", { 50, 205, 50, 1 } }, { "linen", { 250, 240, 230, 1 } },
92
+ { "magenta", { 255, 0, 255, 1 } }, { "maroon", { 128, 0, 0, 1 } },
93
+ { "mediumaquamarine", { 102, 205, 170, 1 } }, { "mediumblue", { 0, 0, 205, 1 } },
94
+ { "mediumorchid", { 186, 85, 211, 1 } }, { "mediumpurple", { 147, 112, 219, 1 } },
95
+ { "mediumseagreen", { 60, 179, 113, 1 } }, { "mediumslateblue", { 123, 104, 238, 1 } },
96
+ { "mediumspringgreen", { 0, 250, 154, 1 } }, { "mediumturquoise", { 72, 209, 204, 1 } },
97
+ { "mediumvioletred", { 199, 21, 133, 1 } }, { "midnightblue", { 25, 25, 112, 1 } },
98
+ { "mintcream", { 245, 255, 250, 1 } }, { "mistyrose", { 255, 228, 225, 1 } },
99
+ { "moccasin", { 255, 228, 181, 1 } }, { "navajowhite", { 255, 222, 173, 1 } },
100
+ { "navy", { 0, 0, 128, 1 } }, { "oldlace", { 253, 245, 230, 1 } },
101
+ { "olive", { 128, 128, 0, 1 } }, { "olivedrab", { 107, 142, 35, 1 } },
102
+ { "orange", { 255, 165, 0, 1 } }, { "orangered", { 255, 69, 0, 1 } },
103
+ { "orchid", { 218, 112, 214, 1 } }, { "palegoldenrod", { 238, 232, 170, 1 } },
104
+ { "palegreen", { 152, 251, 152, 1 } }, { "paleturquoise", { 175, 238, 238, 1 } },
105
+ { "palevioletred", { 219, 112, 147, 1 } }, { "papayawhip", { 255, 239, 213, 1 } },
106
+ { "peachpuff", { 255, 218, 185, 1 } }, { "peru", { 205, 133, 63, 1 } },
107
+ { "pink", { 255, 192, 203, 1 } }, { "plum", { 221, 160, 221, 1 } },
108
+ { "powderblue", { 176, 224, 230, 1 } }, { "purple", { 128, 0, 128, 1 } },
109
+ { "red", { 255, 0, 0, 1 } }, { "rosybrown", { 188, 143, 143, 1 } },
110
+ { "royalblue", { 65, 105, 225, 1 } }, { "saddlebrown", { 139, 69, 19, 1 } },
111
+ { "salmon", { 250, 128, 114, 1 } }, { "sandybrown", { 244, 164, 96, 1 } },
112
+ { "seagreen", { 46, 139, 87, 1 } }, { "seashell", { 255, 245, 238, 1 } },
113
+ { "sienna", { 160, 82, 45, 1 } }, { "silver", { 192, 192, 192, 1 } },
114
+ { "skyblue", { 135, 206, 235, 1 } }, { "slateblue", { 106, 90, 205, 1 } },
115
+ { "slategray", { 112, 128, 144, 1 } }, { "slategrey", { 112, 128, 144, 1 } },
116
+ { "snow", { 255, 250, 250, 1 } }, { "springgreen", { 0, 255, 127, 1 } },
117
+ { "steelblue", { 70, 130, 180, 1 } }, { "tan", { 210, 180, 140, 1 } },
118
+ { "teal", { 0, 128, 128, 1 } }, { "thistle", { 216, 191, 216, 1 } },
119
+ { "tomato", { 255, 99, 71, 1 } }, { "turquoise", { 64, 224, 208, 1 } },
120
+ { "violet", { 238, 130, 238, 1 } }, { "wheat", { 245, 222, 179, 1 } },
121
+ { "white", { 255, 255, 255, 1 } }, { "whitesmoke", { 245, 245, 245, 1 } },
122
+ { "yellow", { 255, 255, 0, 1 } }, { "yellowgreen", { 154, 205, 50, 1 } }
123
+ };
124
+
125
+ template <typename T>
126
+ uint8_t clamp_css_byte(T i) { // Clamp to integer 0 .. 255.
127
+ i = ::round(i); // Seems to be what Chrome does (vs truncation).
128
+ return i < 0 ? 0 : i > 255 ? 255 : uint8_t(i);
129
+ }
130
+
131
+ template <typename T>
132
+ float clamp_css_float(T f) { // Clamp to float 0.0 .. 1.0.
133
+ return f < 0 ? 0 : f > 1 ? 1 : float(f);
134
+ }
135
+
136
+ float parseFloat(const std::string& str) {
137
+ return strtof(str.c_str(), nullptr);
138
+ }
139
+
140
+ int64_t parseInt(const std::string& str, uint8_t base = 10) {
141
+ return strtoll(str.c_str(), nullptr, base);
142
+ }
143
+
144
+ uint8_t parse_css_int(const std::string& str) { // int or percentage.
145
+ if (str.length() && str.back() == '%') {
146
+ return clamp_css_byte(parseFloat(str) / 100.0f * 255.0f);
147
+ } else {
148
+ return clamp_css_byte(parseInt(str));
149
+ }
150
+ }
151
+
152
+ float parse_css_float(const std::string& str) { // float or percentage.
153
+ if (str.length() && str.back() == '%') {
154
+ return clamp_css_float(parseFloat(str) / 100.0f);
155
+ } else {
156
+ return clamp_css_float(parseFloat(str));
157
+ }
158
+ }
159
+
160
+ float css_hue_to_rgb(float m1, float m2, float h) {
161
+ if (h < 0.0f) {
162
+ h += 1.0f;
163
+ } else if (h > 1.0f) {
164
+ h -= 1.0f;
165
+ }
166
+
167
+ if (h * 6.0f < 1.0f) {
168
+ return m1 + (m2 - m1) * h * 6.0f;
169
+ }
170
+ if (h * 2.0f < 1.0f) {
171
+ return m2;
172
+ }
173
+ if (h * 3.0f < 2.0f) {
174
+ return m1 + (m2 - m1) * (2.0f / 3.0f - h) * 6.0f;
175
+ }
176
+ return m1;
177
+ }
178
+
179
+ std::vector<std::string> split(const std::string& s, char delim) {
180
+ std::vector<std::string> elems;
181
+ std::stringstream ss(s);
182
+ std::string item;
183
+ while (std::getline(ss, item, delim)) {
184
+ elems.push_back(item);
185
+ }
186
+ return elems;
187
+ }
188
+
189
+
190
+ inline bool operator==(const Color& lhs, const Color& rhs) {
191
+ return lhs.r == rhs.r && lhs.g == rhs.g && lhs.b == rhs.b && ::fabs(lhs.a - rhs.a) < 0.0001f;
192
+ }
193
+
194
+ inline bool operator!=(const Color& lhs, const Color& rhs) {
195
+ return !(lhs == rhs);
196
+ }
197
+
198
+ Color parse(const std::string& css_str) {
199
+ std::string str = css_str;
200
+
201
+ // Remove all whitespace, not compliant, but should just be more accepting.
202
+ str.erase(std::remove(str.begin(), str.end(), ' '), str.end());
203
+
204
+ // Convert to lowercase.
205
+ std::transform(str.begin(), str.end(), str.begin(), ::tolower);
206
+
207
+ for (const auto& namedColor : namedColors) {
208
+ if (str == namedColor.name) {
209
+ return { namedColor.color };
210
+ }
211
+ }
212
+
213
+ // #abc and #abc123 syntax.
214
+ if (str.length() && str.front() == '#') {
215
+ auto iv = parseInt(str.substr(1), 16); // TODO(deanm): Stricter parsing.
216
+ if (str.length() == 4) {
217
+ if (!(iv >= 0 && iv <= 0xfff)) {
218
+ return {};
219
+ } else {
220
+ return {
221
+ static_cast<uint8_t>(((iv & 0xf00) >> 4) | ((iv & 0xf00) >> 8)),
222
+ static_cast<uint8_t>((iv & 0xf0) | ((iv & 0xf0) >> 4)),
223
+ static_cast<uint8_t>((iv & 0xf) | ((iv & 0xf) << 4)),
224
+ 1
225
+ };
226
+ }
227
+ } else if (str.length() == 7) {
228
+ if (!(iv >= 0 && iv <= 0xffffff)) {
229
+ return {}; // Covers NaN.
230
+ } else {
231
+ return {
232
+ static_cast<uint8_t>((iv & 0xff0000) >> 16),
233
+ static_cast<uint8_t>((iv & 0xff00) >> 8),
234
+ static_cast<uint8_t>(iv & 0xff),
235
+ 1
236
+ };
237
+ }
238
+ }else if (str.length() == 5) {
239
+ // #rgba
240
+ if (!(iv >= 0 && iv <= 0xffff)) return {}; // Covers NaN.
241
+ return {
242
+ static_cast<uint8_t>(((iv & 0xf000) >> 8) | ((iv & 0xf000) >> 12)),
243
+ static_cast<uint8_t>(((iv & 0x0f00) >> 4) | ((iv & 0x0f00) >> 8)),
244
+ static_cast<uint8_t>((iv & 0x00f0) | ((iv & 0x00f0) >> 4)),
245
+ static_cast<uint8_t>(((iv & 0x000f) << 4 | (iv & 0x000f))) / 255.0f
246
+ };
247
+ } else if (str.length() == 9) {
248
+ // #rrggbbaa
249
+ if (!(iv >= 0 && iv <= 0xffffffff)) return {}; // Covers NaN.
250
+ return {
251
+ static_cast<uint8_t>(((iv & 0xff000000) >> 24) & 0xff),
252
+ static_cast<uint8_t>((iv & 0x00ff0000) >> 16),
253
+ static_cast<uint8_t>((iv & 0x0000ff00) >> 8),
254
+ static_cast<uint8_t>((iv & 0x000000ff)) / 255.0f
255
+ };
256
+ }
257
+
258
+ return {};
259
+ }
260
+
261
+ size_t op = str.find_first_of('('), ep = str.find_first_of(')');
262
+ if (op != std::string::npos && ep + 1 == str.length()) {
263
+ const std::string fname = str.substr(0, op);
264
+ const std::vector<std::string> params = split(str.substr(op + 1, ep - (op + 1)), ',');
265
+
266
+ float alpha = 1.0f;
267
+
268
+ if (fname == "rgba" || fname == "rgb") {
269
+ if (fname == "rgba") {
270
+ if (params.size() != 4) {
271
+ return { };
272
+ }
273
+ alpha = parse_css_float(params.back());
274
+ } else {
275
+ if (params.size() != 3) {
276
+ return { };
277
+ }
278
+ }
279
+
280
+ return {
281
+ parse_css_int(params[0]),
282
+ parse_css_int(params[1]),
283
+ parse_css_int(params[2]),
284
+ alpha
285
+ };
286
+
287
+ } else if (fname == "hsla" || fname == "hsl") {
288
+ if (fname == "hsla") {
289
+ if (params.size() != 4) {
290
+ return { };
291
+ }
292
+ alpha = parse_css_float(params.back());
293
+ } else {
294
+ if (params.size() != 3) {
295
+ return { };
296
+ }
297
+ }
298
+
299
+ float h = parseFloat(params[0]) / 360.0f;
300
+ float i;
301
+ // Normalize the hue to [0..1[
302
+ h = std::modf(h, &i);
303
+
304
+ // NOTE(deanm): According to the CSS spec s/l should only be
305
+ // percentages, but we don't bother and let float or percentage.
306
+ float s = parse_css_float(params[1]);
307
+ float l = parse_css_float(params[2]);
308
+
309
+ float m2 = l <= 0.5f ? l * (s + 1.0f) : l + s - l * s;
310
+ float m1 = l * 2.0f - m2;
311
+
312
+ return {
313
+ clamp_css_byte(css_hue_to_rgb(m1, m2, h + 1.0f / 3.0f) * 255.0f),
314
+ clamp_css_byte(css_hue_to_rgb(m1, m2, h) * 255.0f),
315
+ clamp_css_byte(css_hue_to_rgb(m1, m2, h - 1.0f / 3.0f) * 255.0f),
316
+ alpha
317
+ };
318
+ }
319
+ }
320
+
321
+ return { };
322
+ }
323
+
324
+ } // namespace CSSColorParser