@shopify/react-native-skia 0.1.185 → 0.1.186

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (145) hide show
  1. package/android/build.gradle +2 -1
  2. package/android/cpp/jni/JniPlatformContext.cpp +92 -3
  3. package/android/cpp/jni/include/JniPlatformContext.h +4 -0
  4. package/android/cpp/rnskia-android/RNSkAndroidPlatformContext.h +8 -0
  5. package/android/src/main/java/com/shopify/reactnative/skia/PlatformContext.java +17 -1
  6. package/android/src/main/java/com/shopify/reactnative/skia/ViewScreenshotService.java +180 -0
  7. package/cpp/api/JsiSkFont.h +1 -1
  8. package/cpp/api/JsiSkHostObjects.h +1 -1
  9. package/cpp/api/JsiSkImage.h +1 -1
  10. package/cpp/api/JsiSkImageFactory.h +29 -0
  11. package/cpp/api/JsiSkPaint.h +7 -7
  12. package/cpp/api/JsiSkPathFactory.h +1 -1
  13. package/cpp/api/JsiSkPicture.h +2 -2
  14. package/cpp/api/JsiSkRuntimeEffect.h +3 -3
  15. package/cpp/api/JsiSkSVG.h +12 -2
  16. package/cpp/api/JsiSkShader.h +1 -1
  17. package/cpp/api/JsiSkSurface.h +3 -3
  18. package/cpp/api/JsiSkSurfaceFactory.h +1 -1
  19. package/cpp/api/JsiSkTypeface.h +1 -1
  20. package/cpp/rnskia/RNSkAnimation.h +3 -3
  21. package/cpp/rnskia/RNSkDomView.h +9 -9
  22. package/cpp/rnskia/RNSkInfoParameter.h +2 -2
  23. package/cpp/rnskia/RNSkJsView.h +8 -8
  24. package/cpp/rnskia/RNSkJsiViewApi.h +5 -5
  25. package/cpp/rnskia/RNSkPictureView.h +8 -8
  26. package/cpp/rnskia/RNSkPlatformContext.h +32 -3
  27. package/cpp/rnskia/RNSkValueApi.h +5 -5
  28. package/cpp/rnskia/RNSkView.h +6 -6
  29. package/cpp/rnskia/dom/base/ConcatablePaint.h +6 -6
  30. package/cpp/rnskia/dom/base/Declaration.h +1 -1
  31. package/cpp/rnskia/dom/base/DeclarationContext.h +7 -7
  32. package/cpp/rnskia/dom/base/DrawingContext.h +3 -3
  33. package/cpp/rnskia/dom/base/NodePropsContainer.h +1 -1
  34. package/cpp/rnskia/dom/nodes/JsiBlurMaskNode.h +1 -1
  35. package/cpp/rnskia/dom/nodes/JsiColorFilterNodes.h +1 -1
  36. package/cpp/rnskia/dom/nodes/JsiGlyphsNode.h +8 -7
  37. package/cpp/rnskia/dom/nodes/JsiImageFilterNodes.h +1 -1
  38. package/cpp/rnskia/dom/nodes/JsiImageNode.h +5 -2
  39. package/cpp/rnskia/dom/nodes/JsiImageSvgNode.h +9 -9
  40. package/cpp/rnskia/dom/nodes/JsiPathEffectNodes.h +1 -1
  41. package/cpp/rnskia/dom/nodes/JsiPathNode.h +1 -1
  42. package/cpp/rnskia/dom/nodes/JsiPointsNode.h +1 -1
  43. package/cpp/rnskia/dom/nodes/JsiShaderNodes.h +7 -3
  44. package/cpp/rnskia/dom/nodes/JsiTextNode.h +5 -4
  45. package/cpp/rnskia/dom/nodes/JsiTextPathNode.h +3 -1
  46. package/cpp/rnskia/dom/props/BlendModeProp.h +1 -1
  47. package/cpp/rnskia/dom/props/CircleProp.h +1 -1
  48. package/cpp/rnskia/dom/props/ClipProp.h +1 -1
  49. package/cpp/rnskia/dom/props/FontProp.h +15 -10
  50. package/cpp/rnskia/dom/props/ImageProps.h +30 -16
  51. package/cpp/rnskia/dom/props/PaintProps.h +1 -1
  52. package/cpp/rnskia/dom/props/PathProp.h +1 -1
  53. package/cpp/rnskia/dom/props/PointProp.h +1 -1
  54. package/cpp/rnskia/dom/props/PointsProp.h +1 -1
  55. package/cpp/rnskia/dom/props/RRectProp.h +2 -2
  56. package/cpp/rnskia/dom/props/RadiusProp.h +1 -1
  57. package/cpp/rnskia/dom/props/RectProp.h +1 -1
  58. package/cpp/rnskia/dom/props/StrokeProps.h +1 -1
  59. package/cpp/rnskia/dom/props/SvgProp.h +18 -12
  60. package/cpp/rnskia/dom/props/TextBlobProp.h +60 -57
  61. package/cpp/rnskia/dom/props/TileModeProp.h +1 -1
  62. package/cpp/rnskia/dom/props/UniformsProp.h +1 -1
  63. package/cpp/rnskia/dom/props/VertexModeProp.h +1 -1
  64. package/cpp/rnskia/dom/props/VerticesProps.h +1 -1
  65. package/cpp/rnskia/values/RNSkClockValue.h +2 -2
  66. package/cpp/rnskia/values/RNSkComputedValue.h +1 -1
  67. package/cpp/rnskia/values/RNSkReadonlyValue.h +3 -3
  68. package/cpp/rnskia/values/RNSkValue.h +4 -4
  69. package/cpp/utils/RNSkMeasureTime.h +1 -1
  70. package/cpp/utils/RNSkTimingInfo.h +1 -1
  71. package/ios/RNSkia-iOS/RNSkiOSPlatformContext.h +16 -13
  72. package/ios/RNSkia-iOS/RNSkiOSPlatformContext.mm +8 -0
  73. package/ios/RNSkia-iOS/SkiaManager.mm +20 -1
  74. package/ios/RNSkia-iOS/ViewScreenshotService.h +21 -0
  75. package/ios/RNSkia-iOS/ViewScreenshotService.mm +79 -0
  76. package/lib/commonjs/dom/nodes/drawings/ImageNode.js +22 -1
  77. package/lib/commonjs/dom/nodes/drawings/ImageNode.js.map +1 -1
  78. package/lib/commonjs/dom/nodes/drawings/ImageSVG.js +5 -0
  79. package/lib/commonjs/dom/nodes/drawings/ImageSVG.js.map +1 -1
  80. package/lib/commonjs/dom/nodes/drawings/Text.d.ts +2 -2
  81. package/lib/commonjs/dom/nodes/drawings/Text.js +13 -2
  82. package/lib/commonjs/dom/nodes/drawings/Text.js.map +1 -1
  83. package/lib/commonjs/dom/nodes/paint/Shaders.js +5 -0
  84. package/lib/commonjs/dom/nodes/paint/Shaders.js.map +1 -1
  85. package/lib/commonjs/dom/types/Drawings.d.ts +5 -5
  86. package/lib/commonjs/dom/types/Drawings.js.map +1 -1
  87. package/lib/commonjs/dom/types/Shaders.d.ts +1 -1
  88. package/lib/commonjs/dom/types/Shaders.js.map +1 -1
  89. package/lib/commonjs/mock/index.js +2 -1
  90. package/lib/commonjs/mock/index.js.map +1 -1
  91. package/lib/commonjs/skia/core/Image.d.ts +14 -2
  92. package/lib/commonjs/skia/core/Image.js +37 -1
  93. package/lib/commonjs/skia/core/Image.js.map +1 -1
  94. package/lib/commonjs/skia/types/Image/ImageFactory.d.ts +7 -0
  95. package/lib/commonjs/skia/types/Image/ImageFactory.js.map +1 -1
  96. package/lib/commonjs/skia/types/SVG/SVG.d.ts +4 -1
  97. package/lib/commonjs/skia/types/SVG/SVG.js.map +1 -1
  98. package/lib/commonjs/skia/web/JsiSkImageFactory.d.ts +2 -1
  99. package/lib/commonjs/skia/web/JsiSkImageFactory.js +7 -0
  100. package/lib/commonjs/skia/web/JsiSkImageFactory.js.map +1 -1
  101. package/lib/module/dom/nodes/drawings/ImageNode.js +22 -1
  102. package/lib/module/dom/nodes/drawings/ImageNode.js.map +1 -1
  103. package/lib/module/dom/nodes/drawings/ImageSVG.js +5 -0
  104. package/lib/module/dom/nodes/drawings/ImageSVG.js.map +1 -1
  105. package/lib/module/dom/nodes/drawings/Text.d.ts +2 -2
  106. package/lib/module/dom/nodes/drawings/Text.js +13 -2
  107. package/lib/module/dom/nodes/drawings/Text.js.map +1 -1
  108. package/lib/module/dom/nodes/paint/Shaders.js +5 -0
  109. package/lib/module/dom/nodes/paint/Shaders.js.map +1 -1
  110. package/lib/module/dom/types/Drawings.d.ts +5 -5
  111. package/lib/module/dom/types/Drawings.js.map +1 -1
  112. package/lib/module/dom/types/Shaders.d.ts +1 -1
  113. package/lib/module/dom/types/Shaders.js.map +1 -1
  114. package/lib/module/mock/index.js +2 -1
  115. package/lib/module/mock/index.js.map +1 -1
  116. package/lib/module/skia/core/Image.d.ts +14 -2
  117. package/lib/module/skia/core/Image.js +32 -0
  118. package/lib/module/skia/core/Image.js.map +1 -1
  119. package/lib/module/skia/types/Image/ImageFactory.d.ts +7 -0
  120. package/lib/module/skia/types/Image/ImageFactory.js.map +1 -1
  121. package/lib/module/skia/types/SVG/SVG.d.ts +4 -1
  122. package/lib/module/skia/types/SVG/SVG.js.map +1 -1
  123. package/lib/module/skia/web/JsiSkImageFactory.d.ts +2 -1
  124. package/lib/module/skia/web/JsiSkImageFactory.js +7 -0
  125. package/lib/module/skia/web/JsiSkImageFactory.js.map +1 -1
  126. package/lib/typescript/src/dom/nodes/drawings/Text.d.ts +2 -2
  127. package/lib/typescript/src/dom/types/Drawings.d.ts +5 -5
  128. package/lib/typescript/src/dom/types/Shaders.d.ts +1 -1
  129. package/lib/typescript/src/skia/core/Image.d.ts +14 -2
  130. package/lib/typescript/src/skia/types/Image/ImageFactory.d.ts +7 -0
  131. package/lib/typescript/src/skia/types/SVG/SVG.d.ts +4 -1
  132. package/lib/typescript/src/skia/web/JsiSkImageFactory.d.ts +2 -1
  133. package/package.json +2 -2
  134. package/scripts/install-npm.js +3 -2
  135. package/src/dom/nodes/drawings/ImageNode.ts +9 -1
  136. package/src/dom/nodes/drawings/ImageSVG.ts +3 -0
  137. package/src/dom/nodes/drawings/Text.ts +13 -3
  138. package/src/dom/nodes/paint/Shaders.ts +4 -0
  139. package/src/dom/types/Drawings.ts +5 -5
  140. package/src/dom/types/Shaders.ts +1 -1
  141. package/src/mock/index.ts +1 -0
  142. package/src/skia/core/Image.ts +43 -1
  143. package/src/skia/types/Image/ImageFactory.ts +8 -0
  144. package/src/skia/types/SVG/SVG.ts +4 -1
  145. package/src/skia/web/JsiSkImageFactory.ts +8 -1
@@ -8,7 +8,7 @@
8
8
  #pragma clang diagnostic push
9
9
  #pragma clang diagnostic ignored "-Wdocumentation"
10
10
 
11
- #include <SkPaint.h>
11
+ #include "SkPaint.h"
12
12
 
13
13
  #pragma clang diagnostic pop
14
14
 
@@ -17,19 +17,25 @@ public:
17
17
  }
18
18
 
19
19
  void updateDerivedValue() override {
20
- if (_imageSvgProp->value().getType() != PropType::HostObject) {
21
- throw std::runtime_error(
22
- "Expected SkSvgDom object for the svg property.");
20
+ if (_imageSvgProp->isSet()) {
21
+
22
+ if (_imageSvgProp->value().getType() == PropType::HostObject) {
23
+
24
+ auto ptr = std::dynamic_pointer_cast<JsiSkSVG>(
25
+ _imageSvgProp->value().getAsHostObject());
26
+ if (ptr == nullptr) {
27
+ throw std::runtime_error(
28
+ "Expected SkSvgDom object for the svg property.");
29
+ }
30
+ setDerivedValue(ptr->getObject());
31
+ } else {
32
+ throw std::runtime_error(
33
+ "Expected SkSvgDom object or null/undefined for the svg property.");
34
+ }
35
+
36
+ } else {
37
+ setDerivedValue(nullptr);
23
38
  }
24
-
25
- auto ptr = std::dynamic_pointer_cast<JsiSkSVG>(
26
- _imageSvgProp->value().getAsHostObject());
27
- if (ptr == nullptr) {
28
- throw std::runtime_error(
29
- "Expected SkSvgDom object for the svg property.");
30
- }
31
-
32
- setDerivedValue(ptr->getObject());
33
39
  }
34
40
 
35
41
  private:
@@ -46,7 +46,6 @@ public:
46
46
  _pathProp = defineProperty<PathProp>("path");
47
47
  _offsetProp = defineProperty<NodeProp>("initialOffset");
48
48
 
49
- _fontProp->require();
50
49
  _textProp->require();
51
50
  _pathProp->require();
52
51
  _offsetProp->require();
@@ -58,66 +57,70 @@ public:
58
57
  auto path = _pathProp->getDerivedValue();
59
58
  auto offset = _offsetProp->value().getAsNumber();
60
59
 
61
- // Get glyphs
62
- auto numGlyphIds =
63
- font->countText(text.c_str(), text.length(), SkTextEncoding::kUTF8);
64
-
65
- std::vector<SkGlyphID> glyphIds;
66
- glyphIds.reserve(numGlyphIds);
67
- auto ids = font->textToGlyphs(
68
- text.c_str(), text.length(), SkTextEncoding::kUTF8,
69
- static_cast<SkGlyphID *>(glyphIds.data()), numGlyphIds);
70
-
71
- // Get glyph widths
72
- int glyphsSize = static_cast<int>(ids);
73
- std::vector<SkScalar> widthPtrs;
74
- widthPtrs.resize(glyphsSize);
75
- font->getWidthsBounds(glyphIds.data(), numGlyphIds,
76
- static_cast<SkScalar *>(widthPtrs.data()), nullptr,
77
- nullptr); // TODO: Should we use paint somehow here?
78
-
79
- std::vector<SkRSXform> rsx;
80
- SkContourMeasureIter meas(*path, false, 1);
81
-
82
- auto cont = meas.next();
83
- auto dist = offset;
84
-
85
- for (size_t i = 0; i < text.length() && cont != nullptr; ++i) {
86
- auto width = widthPtrs[i];
87
- dist += width / 2;
88
- if (dist > cont->length()) {
89
- // jump to next contour
90
- cont = meas.next();
91
- if (cont == nullptr) {
92
- // We have come to the end of the path - terminate the string
93
- // right here.
94
- text = text.substr(0, i);
95
- break;
60
+ if (font != nullptr) {
61
+ // Get glyphs
62
+ auto numGlyphIds =
63
+ font->countText(text.c_str(), text.length(), SkTextEncoding::kUTF8);
64
+
65
+ std::vector<SkGlyphID> glyphIds;
66
+ glyphIds.reserve(numGlyphIds);
67
+ auto ids = font->textToGlyphs(
68
+ text.c_str(), text.length(), SkTextEncoding::kUTF8,
69
+ static_cast<SkGlyphID *>(glyphIds.data()), numGlyphIds);
70
+
71
+ // Get glyph widths
72
+ int glyphsSize = static_cast<int>(ids);
73
+ std::vector<SkScalar> widthPtrs;
74
+ widthPtrs.resize(glyphsSize);
75
+ font->getWidthsBounds(glyphIds.data(), numGlyphIds,
76
+ static_cast<SkScalar *>(widthPtrs.data()), nullptr,
77
+ nullptr); // TODO: Should we use paint somehow here?
78
+
79
+ std::vector<SkRSXform> rsx;
80
+ SkContourMeasureIter meas(*path, false, 1);
81
+
82
+ auto cont = meas.next();
83
+ auto dist = offset;
84
+
85
+ for (size_t i = 0; i < text.length() && cont != nullptr; ++i) {
86
+ auto width = widthPtrs[i];
87
+ dist += width / 2;
88
+ if (dist > cont->length()) {
89
+ // jump to next contour
90
+ cont = meas.next();
91
+ if (cont == nullptr) {
92
+ // We have come to the end of the path - terminate the string
93
+ // right here.
94
+ text = text.substr(0, i);
95
+ break;
96
+ }
97
+ dist = width / 2;
96
98
  }
97
- dist = width / 2;
98
- }
99
- // Gives us the (x, y) coordinates as well as the cos/sin of the tangent
100
- // line at that position.
101
- SkPoint pos;
102
- SkVector tan;
103
- if (!cont->getPosTan(dist, &pos, &tan)) {
104
- throw std::runtime_error(
105
- "Could not calculate distance when resolving text path");
106
- }
107
- auto px = pos.x();
108
- auto py = pos.y();
109
- auto tx = tan.x();
110
- auto ty = tan.y();
99
+ // Gives us the (x, y) coordinates as well as the cos/sin of the tangent
100
+ // line at that position.
101
+ SkPoint pos;
102
+ SkVector tan;
103
+ if (!cont->getPosTan(dist, &pos, &tan)) {
104
+ throw std::runtime_error(
105
+ "Could not calculate distance when resolving text path");
106
+ }
107
+ auto px = pos.x();
108
+ auto py = pos.y();
109
+ auto tx = tan.x();
110
+ auto ty = tan.y();
111
111
 
112
- auto adjustedX = px - (width / 2) * tx;
113
- auto adjustedY = py - (width / 2) * ty;
112
+ auto adjustedX = px - (width / 2) * tx;
113
+ auto adjustedY = py - (width / 2) * ty;
114
114
 
115
- rsx.push_back(SkRSXform::Make(tx, ty, adjustedX, adjustedY));
116
- dist += width / 2;
117
- }
115
+ rsx.push_back(SkRSXform::Make(tx, ty, adjustedX, adjustedY));
116
+ dist += width / 2;
117
+ }
118
118
 
119
- setDerivedValue(SkTextBlob::MakeFromRSXform(text.c_str(), text.length(),
120
- rsx.data(), *font));
119
+ setDerivedValue(SkTextBlob::MakeFromRSXform(text.c_str(), text.length(),
120
+ rsx.data(), *font));
121
+ } else {
122
+ setDerivedValue(nullptr);
123
+ }
121
124
  }
122
125
 
123
126
  private:
@@ -5,7 +5,7 @@
5
5
  #pragma clang diagnostic push
6
6
  #pragma clang diagnostic ignored "-Wdocumentation"
7
7
 
8
- #include <SkTileMode.h>
8
+ #include "SkTileMode.h"
9
9
 
10
10
  #include <memory>
11
11
  #include <string>
@@ -10,7 +10,7 @@
10
10
  #pragma clang diagnostic push
11
11
  #pragma clang diagnostic ignored "-Wdocumentation"
12
12
 
13
- #include <SkRuntimeEffect.h>
13
+ #include "SkRuntimeEffect.h"
14
14
 
15
15
  #pragma clang diagnostic pop
16
16
 
@@ -8,7 +8,7 @@
8
8
  #pragma clang diagnostic push
9
9
  #pragma clang diagnostic ignored "-Wdocumentation"
10
10
 
11
- #include <SkVertices.h>
11
+ #include "SkVertices.h"
12
12
 
13
13
  #pragma clang diagnostic pop
14
14
 
@@ -13,7 +13,7 @@
13
13
  #pragma clang diagnostic push
14
14
  #pragma clang diagnostic ignored "-Wdocumentation"
15
15
 
16
- #include <SkVertices.h>
16
+ #include "SkVertices.h"
17
17
 
18
18
  #pragma clang diagnostic pop
19
19
 
@@ -1,8 +1,8 @@
1
1
 
2
2
  #pragma once
3
3
 
4
- #include <RNSkPlatformContext.h>
5
- #include <RNSkReadonlyValue.h>
4
+ #include "RNSkPlatformContext.h"
5
+ #include "RNSkReadonlyValue.h"
6
6
  #include <jsi/jsi.h>
7
7
 
8
8
  #include <algorithm>
@@ -1,8 +1,8 @@
1
1
 
2
2
  #pragma once
3
3
 
4
+ #include "RNSkPlatformContext.h"
4
5
  #include "RNSkReadonlyValue.h"
5
- #include <RNSkPlatformContext.h>
6
6
  #include <jsi/jsi.h>
7
7
 
8
8
  #include <algorithm>
@@ -10,9 +10,9 @@
10
10
 
11
11
  #include <jsi/jsi.h>
12
12
 
13
- #include <JsiSkHostObjects.h>
14
- #include <JsiValueWrapper.h>
15
- #include <RNSkPlatformContext.h>
13
+ #include "JsiSkHostObjects.h"
14
+ #include "JsiValueWrapper.h"
15
+ #include "RNSkPlatformContext.h"
16
16
 
17
17
  namespace RNSkia {
18
18
  namespace jsi = facebook::jsi;
@@ -3,10 +3,10 @@
3
3
  #include <functional>
4
4
  #include <memory>
5
5
 
6
- #include <JsiHostObject.h>
7
- #include <RNSkAnimation.h>
8
- #include <RNSkPlatformContext.h>
9
- #include <RNSkReadonlyValue.h>
6
+ #include "JsiHostObject.h"
7
+ #include "RNSkAnimation.h"
8
+ #include "RNSkPlatformContext.h"
9
+ #include "RNSkReadonlyValue.h"
10
10
  #include <jsi/jsi.h>
11
11
 
12
12
  namespace RNSkia {
@@ -7,7 +7,7 @@
7
7
  #include <chrono>
8
8
  #include <string>
9
9
 
10
- #include <RNSkLog.h>
10
+ #include "RNSkLog.h"
11
11
 
12
12
  namespace RNSkia {
13
13
 
@@ -1,6 +1,6 @@
1
1
  #pragma once
2
2
 
3
- #include <RNSkLog.h>
3
+ #include "RNSkLog.h"
4
4
  #include <chrono>
5
5
  #include <string>
6
6
  #include <utility>
@@ -6,16 +6,8 @@
6
6
  #include <memory>
7
7
  #include <string>
8
8
 
9
- #include <DisplayLink.h>
10
- #include <RNSkPlatformContext.h>
11
-
12
- #pragma clang diagnostic push
13
- #pragma clang diagnostic ignored "-Wdocumentation"
14
-
15
- #include "SkStream.h"
16
- #include "SkSurface.h"
17
-
18
- #pragma clang diagnostic pop
9
+ #include "DisplayLink.h"
10
+ #include "RNSkPlatformContext.h"
19
11
 
20
12
  #include <jsi/jsi.h>
21
13
 
@@ -35,10 +27,15 @@ static void handleNotification(CFNotificationCenterRef center, void *observer,
35
27
 
36
28
  class RNSkiOSPlatformContext : public RNSkPlatformContext {
37
29
  public:
38
- RNSkiOSPlatformContext(jsi::Runtime *runtime,
39
- std::shared_ptr<react::CallInvoker> callInvoker)
40
- : RNSkPlatformContext(runtime, callInvoker,
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,
41
37
  [[UIScreen mainScreen] scale]) {
38
+
42
39
  // We need to make sure we invalidate when modules are freed
43
40
  CFNotificationCenterAddObserver(
44
41
  CFNotificationCenterGetLocalCenter(), this, &handleNotification,
@@ -55,6 +52,10 @@ public:
55
52
  void startDrawLoop() override;
56
53
  void stopDrawLoop() override;
57
54
 
55
+ void runOnMainThread(std::function<void()>) override;
56
+
57
+ sk_sp<SkImage> takeScreenshotFromViewTag(size_t tag) override;
58
+
58
59
  virtual void performStreamOperation(
59
60
  const std::string &sourceUri,
60
61
  const std::function<void(std::unique_ptr<SkStreamAsset>)> &op) override;
@@ -69,6 +70,8 @@ public:
69
70
 
70
71
  private:
71
72
  DisplayLink *_displayLink;
73
+ std::function<void(std::function<void()>)> _dispatchMainThread;
74
+ std::function<sk_sp<SkImage>(size_t viewTag)> _takeViewScreenshot;
72
75
  };
73
76
 
74
77
  static void handleNotification(CFNotificationCenterRef center, void *observer,
@@ -62,6 +62,14 @@ sk_sp<SkSurface> RNSkiOSPlatformContext::makeOffscreenSurface(int width,
62
62
  return MakeOffscreenMetalSurface(width, height);
63
63
  }
64
64
 
65
+ void RNSkiOSPlatformContext::runOnMainThread(std::function<void()> func) {
66
+ _dispatchMainThread(func);
67
+ }
68
+
69
+ sk_sp<SkImage> RNSkiOSPlatformContext::takeScreenshotFromViewTag(size_t tag) {
70
+ return _takeViewScreenshot(tag);
71
+ }
72
+
65
73
  void RNSkiOSPlatformContext::startDrawLoop() {
66
74
  if (_displayLink == nullptr) {
67
75
  _displayLink = [[DisplayLink alloc] init];
@@ -4,14 +4,17 @@
4
4
 
5
5
  #import <React/RCTBridge+Private.h>
6
6
  #import <React/RCTBridge.h>
7
+ #import <React/RCTUIManager.h>
7
8
 
8
9
  #import <ReactCommon/RCTTurboModule.h>
9
10
 
10
11
  #import "RNSkiOSPlatformContext.h"
12
+ #import "ViewScreenshotService.h"
11
13
 
12
14
  @implementation SkiaManager {
13
15
  std::shared_ptr<RNSkia::RNSkManager> _skManager;
14
16
  std::shared_ptr<RNSkia::RNSkiOSPlatformContext> _platformContext;
17
+ ViewScreenshotService *_screenshot;
15
18
  __weak RCTBridge *weakBridge;
16
19
  }
17
20
 
@@ -37,9 +40,25 @@
37
40
  facebook::jsi::Runtime *jsRuntime =
38
41
  (facebook::jsi::Runtime *)cxxBridge.runtime;
39
42
 
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
+
40
58
  // Create platform context
41
59
  _platformContext = std::make_shared<RNSkia::RNSkiOSPlatformContext>(
42
- jsRuntime, callInvoker);
60
+ jsRuntime, callInvoker, std::move(dispatchOnMainThread),
61
+ std::move(takeScreenshot));
43
62
 
44
63
  // Create the RNSkiaManager (cross platform)
45
64
  _skManager = std::make_shared<RNSkia::RNSkManager>(jsRuntime, callInvoker,
@@ -0,0 +1,21 @@
1
+ #pragma once
2
+
3
+ #import <CoreFoundation/CoreFoundation.h>
4
+ #import <UIKit/UIKit.h>
5
+
6
+ #import <React/RCTUIManager.h>
7
+
8
+ #pragma clang diagnostic push
9
+ #pragma clang diagnostic ignored "-Wdocumentation"
10
+
11
+ #include "SkImage.h"
12
+
13
+ #pragma clang diagnostic pop
14
+
15
+ @interface ViewScreenshotService : NSObject {
16
+ }
17
+
18
+ - (instancetype)initWithUiManager:(RCTUIManager *)uiManager;
19
+ - (sk_sp<SkImage>)screenshotOfViewWithTag:(NSNumber *)viewTag;
20
+
21
+ @end
@@ -0,0 +1,79 @@
1
+ #import "ViewScreenshotService.h"
2
+ #import <QuartzCore/QuartzCore.h>
3
+
4
+ #pragma clang diagnostic push
5
+ #pragma clang diagnostic ignored "-Wdocumentation"
6
+
7
+ #include "SkData.h"
8
+
9
+ #pragma clang diagnostic pop
10
+
11
+ @implementation ViewScreenshotService {
12
+ RCTUIManager *_uiManager;
13
+ }
14
+
15
+ - (instancetype)initWithUiManager:(RCTUIManager *)uiManager {
16
+ if (self = [super init]) {
17
+ _uiManager = uiManager;
18
+ }
19
+ return self;
20
+ }
21
+
22
+ - (sk_sp<SkImage>)screenshotOfViewWithTag:(NSNumber *)viewTag {
23
+ // Find view corresponding to the tag
24
+ auto view = [_uiManager viewForReactTag:viewTag];
25
+ if (view == NULL) {
26
+ RCTFatal(RCTErrorWithMessage(@"Could not find view with tag"));
27
+ }
28
+
29
+ // Get size
30
+ CGSize size = view.frame.size;
31
+
32
+ // Setup context
33
+ UIGraphicsImageRendererFormat *format =
34
+ [UIGraphicsImageRendererFormat defaultFormat];
35
+ format.opaque = NO;
36
+ UIGraphicsImageRenderer *renderer =
37
+ [[UIGraphicsImageRenderer alloc] initWithSize:size format:format];
38
+
39
+ // Render to context - this is now the only part of this function that shows
40
+ // up in the profiler!
41
+ UIImage *image = [renderer
42
+ imageWithActions:^(UIGraphicsImageRendererContext *_Nonnull context) {
43
+ [view drawViewHierarchyInRect:(CGRect){CGPointZero, size}
44
+ afterScreenUpdates:YES];
45
+ }];
46
+
47
+ // Convert from UIImage -> CGImage -> SkImage
48
+ CGImageRef cgImage = image.CGImage;
49
+
50
+ // Get some info about the image
51
+ auto width = CGImageGetWidth(cgImage);
52
+ auto height = CGImageGetHeight(cgImage);
53
+ auto bytesPerRow = CGImageGetBytesPerRow(cgImage);
54
+
55
+ // Convert from UIImage -> SkImage, start by getting the pixels directly from
56
+ // the CGImage:
57
+ auto dataRef = CGDataProviderCopyData(CGImageGetDataProvider(cgImage));
58
+ auto length = CFDataGetLength(dataRef);
59
+ void *data = CFDataGetMutableBytePtr((CFMutableDataRef)dataRef);
60
+
61
+ // Now we'll capture the data in an SkData object and control releasing it:
62
+ auto skData = SkData::MakeWithProc(
63
+ data, length,
64
+ [](const void *ptr, void *context) {
65
+ CFDataRef dataRef = (CFDataRef)context;
66
+ CFRelease(dataRef);
67
+ },
68
+ (void *)dataRef);
69
+
70
+ // Make SkImageInfo
71
+ SkImageInfo info =
72
+ SkImageInfo::Make(static_cast<int>(width), static_cast<int>(height),
73
+ kRGBA_8888_SkColorType, kPremul_SkAlphaType);
74
+
75
+ // ... and then create the SkImage itself!
76
+ return SkImage::MakeRasterData(info, skData, bytesPerRow);
77
+ }
78
+
79
+ @end
@@ -20,6 +20,24 @@ class ImageNode extends _DrawingNode.JsiDrawingNode {
20
20
  const {
21
21
  image
22
22
  } = this.props;
23
+
24
+ if (!image) {
25
+ return {
26
+ src: {
27
+ x: 0,
28
+ y: 0,
29
+ width: 0,
30
+ height: 0
31
+ },
32
+ dst: {
33
+ x: 0,
34
+ y: 0,
35
+ width: 0,
36
+ height: 0
37
+ }
38
+ };
39
+ }
40
+
23
41
  const fit = this.props.fit ?? "contain";
24
42
  const rect = (0, _datatypes.processRect)(this.Skia, this.props);
25
43
  const {
@@ -54,7 +72,10 @@ class ImageNode extends _DrawingNode.JsiDrawingNode {
54
72
  src,
55
73
  dst
56
74
  } = this.derived;
57
- canvas.drawImageRect(image, src, dst, paint);
75
+
76
+ if (image) {
77
+ canvas.drawImageRect(image, src, dst, paint);
78
+ }
58
79
  }
59
80
 
60
81
  }
@@ -1 +1 @@
1
- {"version":3,"names":["ImageNode","JsiDrawingNode","constructor","ctx","props","NodeType","Image","deriveProps","image","fit","rect","processRect","Skia","src","dst","fitRects","x","y","width","height","draw","canvas","paint","derived","Error","drawImageRect"],"sources":["ImageNode.ts"],"sourcesContent":["import type { SkRect } from \"../../../skia/types\";\nimport type { DrawingContext, ImageProps } from \"../../types\";\nimport { NodeType } from \"../../types\";\nimport { fitRects, processRect } from \"../datatypes\";\nimport { JsiDrawingNode } from \"../DrawingNode\";\nimport type { NodeContext } from \"../Node\";\n\nexport class ImageNode extends JsiDrawingNode<\n ImageProps,\n { src: SkRect; dst: SkRect }\n> {\n constructor(ctx: NodeContext, props: ImageProps) {\n super(ctx, NodeType.Image, props);\n }\n\n deriveProps() {\n const { image } = this.props;\n const fit = this.props.fit ?? \"contain\";\n const rect = processRect(this.Skia, this.props);\n const { src, dst } = fitRects(\n fit,\n {\n x: 0,\n y: 0,\n width: image.width(),\n height: image.height(),\n },\n rect\n );\n return { src, dst };\n }\n\n draw({ canvas, paint }: DrawingContext) {\n const { image } = this.props;\n if (!this.derived) {\n throw new Error(\"ImageNode: src and dst are undefined\");\n }\n const { src, dst } = this.derived;\n canvas.drawImageRect(image, src, dst, paint);\n }\n}\n"],"mappings":";;;;;;;AAEA;;AACA;;AACA;;AAGO,MAAMA,SAAN,SAAwBC,2BAAxB,CAGL;EACAC,WAAW,CAACC,GAAD,EAAmBC,KAAnB,EAAsC;IAC/C,MAAMD,GAAN,EAAWE,eAAA,CAASC,KAApB,EAA2BF,KAA3B;EACD;;EAEDG,WAAW,GAAG;IACZ,MAAM;MAAEC;IAAF,IAAY,KAAKJ,KAAvB;IACA,MAAMK,GAAG,GAAG,KAAKL,KAAL,CAAWK,GAAX,IAAkB,SAA9B;IACA,MAAMC,IAAI,GAAG,IAAAC,sBAAA,EAAY,KAAKC,IAAjB,EAAuB,KAAKR,KAA5B,CAAb;IACA,MAAM;MAAES,GAAF;MAAOC;IAAP,IAAe,IAAAC,mBAAA,EACnBN,GADmB,EAEnB;MACEO,CAAC,EAAE,CADL;MAEEC,CAAC,EAAE,CAFL;MAGEC,KAAK,EAAEV,KAAK,CAACU,KAAN,EAHT;MAIEC,MAAM,EAAEX,KAAK,CAACW,MAAN;IAJV,CAFmB,EAQnBT,IARmB,CAArB;IAUA,OAAO;MAAEG,GAAF;MAAOC;IAAP,CAAP;EACD;;EAEDM,IAAI,OAAoC;IAAA,IAAnC;MAAEC,MAAF;MAAUC;IAAV,CAAmC;IACtC,MAAM;MAAEd;IAAF,IAAY,KAAKJ,KAAvB;;IACA,IAAI,CAAC,KAAKmB,OAAV,EAAmB;MACjB,MAAM,IAAIC,KAAJ,CAAU,sCAAV,CAAN;IACD;;IACD,MAAM;MAAEX,GAAF;MAAOC;IAAP,IAAe,KAAKS,OAA1B;IACAF,MAAM,CAACI,aAAP,CAAqBjB,KAArB,EAA4BK,GAA5B,EAAiCC,GAAjC,EAAsCQ,KAAtC;EACD;;AA7BD"}
1
+ {"version":3,"names":["ImageNode","JsiDrawingNode","constructor","ctx","props","NodeType","Image","deriveProps","image","src","x","y","width","height","dst","fit","rect","processRect","Skia","fitRects","draw","canvas","paint","derived","Error","drawImageRect"],"sources":["ImageNode.ts"],"sourcesContent":["import type { SkRect } from \"../../../skia/types\";\nimport type { DrawingContext, ImageProps } from \"../../types\";\nimport { NodeType } from \"../../types\";\nimport { fitRects, processRect } from \"../datatypes\";\nimport { JsiDrawingNode } from \"../DrawingNode\";\nimport type { NodeContext } from \"../Node\";\n\nexport class ImageNode extends JsiDrawingNode<\n ImageProps,\n { src: SkRect; dst: SkRect }\n> {\n constructor(ctx: NodeContext, props: ImageProps) {\n super(ctx, NodeType.Image, props);\n }\n\n deriveProps() {\n const { image } = this.props;\n if (!image) {\n return {\n src: { x: 0, y: 0, width: 0, height: 0 },\n dst: { x: 0, y: 0, width: 0, height: 0 },\n };\n }\n const fit = this.props.fit ?? \"contain\";\n const rect = processRect(this.Skia, this.props);\n const { src, dst } = fitRects(\n fit,\n {\n x: 0,\n y: 0,\n width: image.width(),\n height: image.height(),\n },\n rect\n );\n return { src, dst };\n }\n\n draw({ canvas, paint }: DrawingContext) {\n const { image } = this.props;\n if (!this.derived) {\n throw new Error(\"ImageNode: src and dst are undefined\");\n }\n const { src, dst } = this.derived;\n if (image) {\n canvas.drawImageRect(image, src, dst, paint);\n }\n }\n}\n"],"mappings":";;;;;;;AAEA;;AACA;;AACA;;AAGO,MAAMA,SAAN,SAAwBC,2BAAxB,CAGL;EACAC,WAAW,CAACC,GAAD,EAAmBC,KAAnB,EAAsC;IAC/C,MAAMD,GAAN,EAAWE,eAAA,CAASC,KAApB,EAA2BF,KAA3B;EACD;;EAEDG,WAAW,GAAG;IACZ,MAAM;MAAEC;IAAF,IAAY,KAAKJ,KAAvB;;IACA,IAAI,CAACI,KAAL,EAAY;MACV,OAAO;QACLC,GAAG,EAAE;UAAEC,CAAC,EAAE,CAAL;UAAQC,CAAC,EAAE,CAAX;UAAcC,KAAK,EAAE,CAArB;UAAwBC,MAAM,EAAE;QAAhC,CADA;QAELC,GAAG,EAAE;UAAEJ,CAAC,EAAE,CAAL;UAAQC,CAAC,EAAE,CAAX;UAAcC,KAAK,EAAE,CAArB;UAAwBC,MAAM,EAAE;QAAhC;MAFA,CAAP;IAID;;IACD,MAAME,GAAG,GAAG,KAAKX,KAAL,CAAWW,GAAX,IAAkB,SAA9B;IACA,MAAMC,IAAI,GAAG,IAAAC,sBAAA,EAAY,KAAKC,IAAjB,EAAuB,KAAKd,KAA5B,CAAb;IACA,MAAM;MAAEK,GAAF;MAAOK;IAAP,IAAe,IAAAK,mBAAA,EACnBJ,GADmB,EAEnB;MACEL,CAAC,EAAE,CADL;MAEEC,CAAC,EAAE,CAFL;MAGEC,KAAK,EAAEJ,KAAK,CAACI,KAAN,EAHT;MAIEC,MAAM,EAAEL,KAAK,CAACK,MAAN;IAJV,CAFmB,EAQnBG,IARmB,CAArB;IAUA,OAAO;MAAEP,GAAF;MAAOK;IAAP,CAAP;EACD;;EAEDM,IAAI,OAAoC;IAAA,IAAnC;MAAEC,MAAF;MAAUC;IAAV,CAAmC;IACtC,MAAM;MAAEd;IAAF,IAAY,KAAKJ,KAAvB;;IACA,IAAI,CAAC,KAAKmB,OAAV,EAAmB;MACjB,MAAM,IAAIC,KAAJ,CAAU,sCAAV,CAAN;IACD;;IACD,MAAM;MAAEf,GAAF;MAAOK;IAAP,IAAe,KAAKS,OAA1B;;IACA,IAAIf,KAAJ,EAAW;MACTa,MAAM,CAACI,aAAP,CAAqBjB,KAArB,EAA4BC,GAA5B,EAAiCK,GAAjC,EAAsCQ,KAAtC;IACD;EACF;;AArCD"}
@@ -27,6 +27,11 @@ class ImageSVGNode extends _DrawingNode.JsiDrawingNode {
27
27
  const {
28
28
  svg
29
29
  } = this.props;
30
+
31
+ if (!svg) {
32
+ return;
33
+ }
34
+
30
35
  const {
31
36
  x,
32
37
  y,
@@ -1 +1 @@
1
- {"version":3,"names":["ImageSVGNode","JsiDrawingNode","constructor","ctx","props","NodeType","ImageSVG","deriveProps","draw","canvas","svg","x","y","width","height","processRect","Skia","save","translate","drawSvg","restore"],"sources":["ImageSVG.ts"],"sourcesContent":["import type { DrawingContext, ImageSVGProps } from \"../../types\";\nimport { NodeType } from \"../../types\";\nimport { processRect } from \"../datatypes\";\nimport { JsiDrawingNode } from \"../DrawingNode\";\nimport type { NodeContext } from \"../Node\";\n\nexport class ImageSVGNode extends JsiDrawingNode<ImageSVGProps, null> {\n constructor(ctx: NodeContext, props: ImageSVGProps) {\n super(ctx, NodeType.ImageSVG, props);\n }\n\n deriveProps() {\n return null;\n }\n\n draw({ canvas }: DrawingContext) {\n const { svg } = this.props;\n const { x, y, width, height } = processRect(this.Skia, this.props);\n canvas.save();\n canvas.translate(x, y);\n canvas.drawSvg(svg, width, height);\n canvas.restore();\n }\n}\n"],"mappings":";;;;;;;AACA;;AACA;;AACA;;AAGO,MAAMA,YAAN,SAA2BC,2BAA3B,CAA+D;EACpEC,WAAW,CAACC,GAAD,EAAmBC,KAAnB,EAAyC;IAClD,MAAMD,GAAN,EAAWE,eAAA,CAASC,QAApB,EAA8BF,KAA9B;EACD;;EAEDG,WAAW,GAAG;IACZ,OAAO,IAAP;EACD;;EAEDC,IAAI,OAA6B;IAAA,IAA5B;MAAEC;IAAF,CAA4B;IAC/B,MAAM;MAAEC;IAAF,IAAU,KAAKN,KAArB;IACA,MAAM;MAAEO,CAAF;MAAKC,CAAL;MAAQC,KAAR;MAAeC;IAAf,IAA0B,IAAAC,sBAAA,EAAY,KAAKC,IAAjB,EAAuB,KAAKZ,KAA5B,CAAhC;IACAK,MAAM,CAACQ,IAAP;IACAR,MAAM,CAACS,SAAP,CAAiBP,CAAjB,EAAoBC,CAApB;IACAH,MAAM,CAACU,OAAP,CAAeT,GAAf,EAAoBG,KAApB,EAA2BC,MAA3B;IACAL,MAAM,CAACW,OAAP;EACD;;AAhBmE"}
1
+ {"version":3,"names":["ImageSVGNode","JsiDrawingNode","constructor","ctx","props","NodeType","ImageSVG","deriveProps","draw","canvas","svg","x","y","width","height","processRect","Skia","save","translate","drawSvg","restore"],"sources":["ImageSVG.ts"],"sourcesContent":["import type { DrawingContext, ImageSVGProps } from \"../../types\";\nimport { NodeType } from \"../../types\";\nimport { processRect } from \"../datatypes\";\nimport { JsiDrawingNode } from \"../DrawingNode\";\nimport type { NodeContext } from \"../Node\";\n\nexport class ImageSVGNode extends JsiDrawingNode<ImageSVGProps, null> {\n constructor(ctx: NodeContext, props: ImageSVGProps) {\n super(ctx, NodeType.ImageSVG, props);\n }\n\n deriveProps() {\n return null;\n }\n\n draw({ canvas }: DrawingContext) {\n const { svg } = this.props;\n if (!svg) {\n return;\n }\n const { x, y, width, height } = processRect(this.Skia, this.props);\n canvas.save();\n canvas.translate(x, y);\n canvas.drawSvg(svg, width, height);\n canvas.restore();\n }\n}\n"],"mappings":";;;;;;;AACA;;AACA;;AACA;;AAGO,MAAMA,YAAN,SAA2BC,2BAA3B,CAA+D;EACpEC,WAAW,CAACC,GAAD,EAAmBC,KAAnB,EAAyC;IAClD,MAAMD,GAAN,EAAWE,eAAA,CAASC,QAApB,EAA8BF,KAA9B;EACD;;EAEDG,WAAW,GAAG;IACZ,OAAO,IAAP;EACD;;EAEDC,IAAI,OAA6B;IAAA,IAA5B;MAAEC;IAAF,CAA4B;IAC/B,MAAM;MAAEC;IAAF,IAAU,KAAKN,KAArB;;IACA,IAAI,CAACM,GAAL,EAAU;MACR;IACD;;IACD,MAAM;MAAEC,CAAF;MAAKC,CAAL;MAAQC,KAAR;MAAeC;IAAf,IAA0B,IAAAC,sBAAA,EAAY,KAAKC,IAAjB,EAAuB,KAAKZ,KAA5B,CAAhC;IACAK,MAAM,CAACQ,IAAP;IACAR,MAAM,CAACS,SAAP,CAAiBP,CAAjB,EAAoBC,CAApB;IACAH,MAAM,CAACU,OAAP,CAAeT,GAAf,EAAoBG,KAApB,EAA2BC,MAA3B;IACAL,MAAM,CAACW,OAAP;EACD;;AAnBmE"}
@@ -8,9 +8,9 @@ export declare class TextNode extends JsiDrawingNode<TextProps, null> {
8
8
  protected deriveProps(): null;
9
9
  draw({ canvas, paint }: DrawingContext): void;
10
10
  }
11
- export declare class TextPathNode extends JsiDrawingNode<TextPathProps, SkTextBlob> {
11
+ export declare class TextPathNode extends JsiDrawingNode<TextPathProps, SkTextBlob | null> {
12
12
  constructor(ctx: NodeContext, props: TextPathProps);
13
- deriveProps(): SkTextBlob;
13
+ deriveProps(): SkTextBlob | null;
14
14
  draw({ canvas, paint }: DrawingContext): void;
15
15
  }
16
16
  export declare class TextBlobNode extends JsiDrawingNode<TextBlobProps, null> {
@@ -31,7 +31,10 @@ class TextNode extends _DrawingNode.JsiDrawingNode {
31
31
  y,
32
32
  font
33
33
  } = this.props;
34
- canvas.drawText(text, x, y, paint, font);
34
+
35
+ if (font) {
36
+ canvas.drawText(text, x, y, paint, font);
37
+ }
35
38
  }
36
39
 
37
40
  }
@@ -49,6 +52,11 @@ class TextPathNode extends _DrawingNode.JsiDrawingNode {
49
52
  font,
50
53
  initialOffset
51
54
  } = this.props;
55
+
56
+ if (!font) {
57
+ return null;
58
+ }
59
+
52
60
  let {
53
61
  text
54
62
  } = this.props;
@@ -171,7 +179,10 @@ class GlyphsNode extends _DrawingNode.JsiDrawingNode {
171
179
  y,
172
180
  font
173
181
  } = this.props;
174
- canvas.drawGlyphs(glyphs, positions, x, y, font, paint);
182
+
183
+ if (font) {
184
+ canvas.drawGlyphs(glyphs, positions, x, y, font, paint);
185
+ }
175
186
  }
176
187
 
177
188
  }