@shopify/react-native-skia 0.1.184 → 0.1.186
Sign up to get free protection for your applications and to get access to all the features.
- package/android/build.gradle +2 -1
- package/android/cpp/jni/JniPlatformContext.cpp +92 -3
- package/android/cpp/jni/include/JniPlatformContext.h +4 -0
- package/android/cpp/rnskia-android/RNSkAndroidPlatformContext.h +8 -0
- package/android/src/main/java/com/shopify/reactnative/skia/PlatformContext.java +17 -1
- package/android/src/main/java/com/shopify/reactnative/skia/ViewScreenshotService.java +180 -0
- package/cpp/api/JsiSkFont.h +1 -1
- package/cpp/api/JsiSkHostObjects.h +1 -1
- package/cpp/api/JsiSkImage.h +8 -1
- package/cpp/api/JsiSkImageFactory.h +29 -0
- package/cpp/api/JsiSkPaint.h +7 -7
- package/cpp/api/JsiSkPathFactory.h +1 -1
- package/cpp/api/JsiSkPicture.h +2 -2
- package/cpp/api/JsiSkRuntimeEffect.h +3 -3
- package/cpp/api/JsiSkSVG.h +12 -2
- package/cpp/api/JsiSkShader.h +1 -1
- package/cpp/api/JsiSkSurface.h +3 -3
- package/cpp/api/JsiSkSurfaceFactory.h +1 -1
- package/cpp/api/JsiSkTypeface.h +1 -1
- package/cpp/rnskia/RNSkAnimation.h +3 -3
- package/cpp/rnskia/RNSkDomView.h +9 -9
- package/cpp/rnskia/RNSkInfoParameter.h +2 -2
- package/cpp/rnskia/RNSkJsView.h +8 -8
- package/cpp/rnskia/RNSkJsiViewApi.h +5 -5
- package/cpp/rnskia/RNSkPictureView.h +8 -8
- package/cpp/rnskia/RNSkPlatformContext.h +32 -3
- package/cpp/rnskia/RNSkValueApi.h +5 -5
- package/cpp/rnskia/RNSkView.h +10 -8
- package/cpp/rnskia/dom/base/ConcatablePaint.h +6 -6
- package/cpp/rnskia/dom/base/Declaration.h +1 -1
- package/cpp/rnskia/dom/base/DeclarationContext.h +7 -7
- package/cpp/rnskia/dom/base/DrawingContext.h +3 -3
- package/cpp/rnskia/dom/base/NodePropsContainer.h +1 -1
- package/cpp/rnskia/dom/nodes/JsiBlurMaskNode.h +1 -1
- package/cpp/rnskia/dom/nodes/JsiColorFilterNodes.h +1 -1
- package/cpp/rnskia/dom/nodes/JsiGlyphsNode.h +8 -7
- package/cpp/rnskia/dom/nodes/JsiImageFilterNodes.h +9 -6
- package/cpp/rnskia/dom/nodes/JsiImageNode.h +5 -2
- package/cpp/rnskia/dom/nodes/JsiImageSvgNode.h +9 -9
- package/cpp/rnskia/dom/nodes/JsiPathEffectNodes.h +1 -1
- package/cpp/rnskia/dom/nodes/JsiPathNode.h +1 -1
- package/cpp/rnskia/dom/nodes/JsiPointsNode.h +1 -1
- package/cpp/rnskia/dom/nodes/JsiShaderNodes.h +7 -3
- package/cpp/rnskia/dom/nodes/JsiTextNode.h +5 -4
- package/cpp/rnskia/dom/nodes/JsiTextPathNode.h +3 -1
- package/cpp/rnskia/dom/props/BlendModeProp.h +1 -1
- package/cpp/rnskia/dom/props/CircleProp.h +1 -1
- package/cpp/rnskia/dom/props/ClipProp.h +1 -1
- package/cpp/rnskia/dom/props/FontProp.h +15 -10
- package/cpp/rnskia/dom/props/ImageProps.h +30 -16
- package/cpp/rnskia/dom/props/PaintProps.h +1 -1
- package/cpp/rnskia/dom/props/PathProp.h +1 -1
- package/cpp/rnskia/dom/props/PointProp.h +1 -1
- package/cpp/rnskia/dom/props/PointsProp.h +1 -1
- package/cpp/rnskia/dom/props/RRectProp.h +2 -2
- package/cpp/rnskia/dom/props/RadiusProp.h +1 -1
- package/cpp/rnskia/dom/props/RectProp.h +1 -1
- package/cpp/rnskia/dom/props/StrokeProps.h +1 -1
- package/cpp/rnskia/dom/props/SvgProp.h +18 -12
- package/cpp/rnskia/dom/props/TextBlobProp.h +60 -57
- package/cpp/rnskia/dom/props/TileModeProp.h +1 -1
- package/cpp/rnskia/dom/props/UniformsProp.h +1 -1
- package/cpp/rnskia/dom/props/VertexModeProp.h +1 -1
- package/cpp/rnskia/dom/props/VerticesProps.h +1 -1
- package/cpp/rnskia/values/RNSkClockValue.h +2 -2
- package/cpp/rnskia/values/RNSkComputedValue.h +1 -1
- package/cpp/rnskia/values/RNSkReadonlyValue.h +3 -3
- package/cpp/rnskia/values/RNSkValue.h +4 -4
- package/cpp/utils/RNSkMeasureTime.h +1 -1
- package/cpp/utils/RNSkTimingInfo.h +1 -1
- package/ios/RNSkia-iOS/RNSkiOSPlatformContext.h +16 -13
- package/ios/RNSkia-iOS/RNSkiOSPlatformContext.mm +8 -0
- package/ios/RNSkia-iOS/SkiaManager.mm +20 -1
- package/ios/RNSkia-iOS/ViewScreenshotService.h +21 -0
- package/ios/RNSkia-iOS/ViewScreenshotService.mm +79 -0
- package/lib/commonjs/dom/nodes/drawings/ImageNode.js +22 -1
- package/lib/commonjs/dom/nodes/drawings/ImageNode.js.map +1 -1
- package/lib/commonjs/dom/nodes/drawings/ImageSVG.js +5 -0
- package/lib/commonjs/dom/nodes/drawings/ImageSVG.js.map +1 -1
- package/lib/commonjs/dom/nodes/drawings/Text.d.ts +2 -2
- package/lib/commonjs/dom/nodes/drawings/Text.js +13 -2
- package/lib/commonjs/dom/nodes/drawings/Text.js.map +1 -1
- package/lib/commonjs/dom/nodes/paint/Shaders.js +5 -0
- package/lib/commonjs/dom/nodes/paint/Shaders.js.map +1 -1
- package/lib/commonjs/dom/types/Drawings.d.ts +5 -5
- package/lib/commonjs/dom/types/Drawings.js.map +1 -1
- package/lib/commonjs/dom/types/Shaders.d.ts +1 -1
- package/lib/commonjs/dom/types/Shaders.js.map +1 -1
- package/lib/commonjs/mock/index.js +2 -1
- package/lib/commonjs/mock/index.js.map +1 -1
- package/lib/commonjs/skia/core/Image.d.ts +14 -2
- package/lib/commonjs/skia/core/Image.js +37 -1
- package/lib/commonjs/skia/core/Image.js.map +1 -1
- package/lib/commonjs/skia/types/Image/Image.d.ts +6 -0
- package/lib/commonjs/skia/types/Image/Image.js.map +1 -1
- package/lib/commonjs/skia/types/Image/ImageFactory.d.ts +7 -0
- package/lib/commonjs/skia/types/Image/ImageFactory.js.map +1 -1
- package/lib/commonjs/skia/types/SVG/SVG.d.ts +4 -1
- package/lib/commonjs/skia/types/SVG/SVG.js.map +1 -1
- package/lib/commonjs/skia/web/JsiSkImage.d.ts +1 -0
- package/lib/commonjs/skia/web/JsiSkImage.js +4 -0
- package/lib/commonjs/skia/web/JsiSkImage.js.map +1 -1
- package/lib/commonjs/skia/web/JsiSkImageFactory.d.ts +2 -1
- package/lib/commonjs/skia/web/JsiSkImageFactory.js +7 -0
- package/lib/commonjs/skia/web/JsiSkImageFactory.js.map +1 -1
- package/lib/module/dom/nodes/drawings/ImageNode.js +22 -1
- package/lib/module/dom/nodes/drawings/ImageNode.js.map +1 -1
- package/lib/module/dom/nodes/drawings/ImageSVG.js +5 -0
- package/lib/module/dom/nodes/drawings/ImageSVG.js.map +1 -1
- package/lib/module/dom/nodes/drawings/Text.d.ts +2 -2
- package/lib/module/dom/nodes/drawings/Text.js +13 -2
- package/lib/module/dom/nodes/drawings/Text.js.map +1 -1
- package/lib/module/dom/nodes/paint/Shaders.js +5 -0
- package/lib/module/dom/nodes/paint/Shaders.js.map +1 -1
- package/lib/module/dom/types/Drawings.d.ts +5 -5
- package/lib/module/dom/types/Drawings.js.map +1 -1
- package/lib/module/dom/types/Shaders.d.ts +1 -1
- package/lib/module/dom/types/Shaders.js.map +1 -1
- package/lib/module/mock/index.js +2 -1
- package/lib/module/mock/index.js.map +1 -1
- package/lib/module/skia/core/Image.d.ts +14 -2
- package/lib/module/skia/core/Image.js +32 -0
- package/lib/module/skia/core/Image.js.map +1 -1
- package/lib/module/skia/types/Image/Image.d.ts +6 -0
- package/lib/module/skia/types/Image/Image.js.map +1 -1
- package/lib/module/skia/types/Image/ImageFactory.d.ts +7 -0
- package/lib/module/skia/types/Image/ImageFactory.js.map +1 -1
- package/lib/module/skia/types/SVG/SVG.d.ts +4 -1
- package/lib/module/skia/types/SVG/SVG.js.map +1 -1
- package/lib/module/skia/web/JsiSkImage.d.ts +1 -0
- package/lib/module/skia/web/JsiSkImage.js +4 -0
- package/lib/module/skia/web/JsiSkImage.js.map +1 -1
- package/lib/module/skia/web/JsiSkImageFactory.d.ts +2 -1
- package/lib/module/skia/web/JsiSkImageFactory.js +7 -0
- package/lib/module/skia/web/JsiSkImageFactory.js.map +1 -1
- package/lib/typescript/src/dom/nodes/drawings/Text.d.ts +2 -2
- package/lib/typescript/src/dom/types/Drawings.d.ts +5 -5
- package/lib/typescript/src/dom/types/Shaders.d.ts +1 -1
- package/lib/typescript/src/skia/core/Image.d.ts +14 -2
- package/lib/typescript/src/skia/types/Image/Image.d.ts +6 -0
- package/lib/typescript/src/skia/types/Image/ImageFactory.d.ts +7 -0
- package/lib/typescript/src/skia/types/SVG/SVG.d.ts +4 -1
- package/lib/typescript/src/skia/web/JsiSkImage.d.ts +1 -0
- package/lib/typescript/src/skia/web/JsiSkImageFactory.d.ts +2 -1
- package/package.json +2 -2
- package/scripts/install-npm.js +3 -2
- package/src/dom/nodes/drawings/ImageNode.ts +9 -1
- package/src/dom/nodes/drawings/ImageSVG.ts +3 -0
- package/src/dom/nodes/drawings/Text.ts +13 -3
- package/src/dom/nodes/paint/Shaders.ts +4 -0
- package/src/dom/types/Drawings.ts +5 -5
- package/src/dom/types/Shaders.ts +1 -1
- package/src/mock/index.ts +1 -0
- package/src/skia/core/Image.ts +43 -1
- package/src/skia/types/Image/Image.ts +7 -0
- package/src/skia/types/Image/ImageFactory.ts +8 -0
- package/src/skia/types/SVG/SVG.ts +4 -1
- package/src/skia/web/JsiSkImage.ts +7 -0
- package/src/skia/web/JsiSkImageFactory.ts +8 -1
@@ -17,19 +17,25 @@ public:
|
|
17
17
|
}
|
18
18
|
|
19
19
|
void updateDerivedValue() override {
|
20
|
-
if (_imageSvgProp->
|
21
|
-
|
22
|
-
|
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
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
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
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
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
|
-
|
113
|
-
|
112
|
+
auto adjustedX = px - (width / 2) * tx;
|
113
|
+
auto adjustedY = py - (width / 2) * ty;
|
114
114
|
|
115
|
-
|
116
|
-
|
117
|
-
|
115
|
+
rsx.push_back(SkRSXform::Make(tx, ty, adjustedX, adjustedY));
|
116
|
+
dist += width / 2;
|
117
|
+
}
|
118
118
|
|
119
|
-
|
120
|
-
|
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:
|
@@ -10,9 +10,9 @@
|
|
10
10
|
|
11
11
|
#include <jsi/jsi.h>
|
12
12
|
|
13
|
-
#include
|
14
|
-
#include
|
15
|
-
#include
|
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
|
7
|
-
#include
|
8
|
-
#include
|
9
|
-
#include
|
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 {
|
@@ -6,16 +6,8 @@
|
|
6
6
|
#include <memory>
|
7
7
|
#include <string>
|
8
8
|
|
9
|
-
#include
|
10
|
-
#include
|
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(
|
39
|
-
|
40
|
-
|
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
|
-
|
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","
|
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"}
|
@@ -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
|
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"}
|