@shopify/react-native-skia 1.10.2 → 1.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (105) hide show
  1. package/cpp/api/JsiSkApi.h +3 -0
  2. package/cpp/api/recorder/ColorFilters.h +133 -0
  3. package/cpp/api/recorder/Command.h +58 -0
  4. package/cpp/api/recorder/Convertor.h +1212 -0
  5. package/cpp/api/recorder/DataTypes.h +234 -0
  6. package/cpp/api/recorder/DrawingCtx.h +187 -0
  7. package/cpp/api/recorder/Drawings.h +949 -0
  8. package/cpp/api/recorder/Image.h +108 -0
  9. package/cpp/api/recorder/ImageFilters.h +292 -0
  10. package/cpp/api/recorder/JsiRecorder.h +314 -0
  11. package/cpp/api/recorder/Paint.h +191 -0
  12. package/cpp/api/recorder/PathEffects.h +194 -0
  13. package/cpp/api/recorder/RNRecorder.h +635 -0
  14. package/cpp/api/recorder/Shaders.h +406 -0
  15. package/cpp/rnskia/dom/nodes/JsiAtlasNode.h +3 -2
  16. package/cpp/rnskia/dom/nodes/JsiImageNode.h +3 -2
  17. package/ios/RNSkia-iOS/SkiaCVPixelBufferUtils.mm +4 -8
  18. package/jestSetup.js +8 -0
  19. package/jestSetup.mjs +8 -0
  20. package/lib/commonjs/renderer/components/image/Image.d.ts +1 -1
  21. package/lib/commonjs/renderer/components/image/Image.js +8 -2
  22. package/lib/commonjs/renderer/components/image/Image.js.map +1 -1
  23. package/lib/commonjs/skia/types/Recorder.d.ts +52 -0
  24. package/lib/commonjs/skia/types/Recorder.js +6 -0
  25. package/lib/commonjs/skia/types/Recorder.js.map +1 -0
  26. package/lib/commonjs/skia/types/Skia.d.ts +2 -0
  27. package/lib/commonjs/skia/types/Skia.js.map +1 -1
  28. package/lib/commonjs/skia/types/index.d.ts +1 -0
  29. package/lib/commonjs/skia/types/index.js +11 -0
  30. package/lib/commonjs/skia/types/index.js.map +1 -1
  31. package/lib/commonjs/skia/web/JsiSkia.js +3 -0
  32. package/lib/commonjs/skia/web/JsiSkia.js.map +1 -1
  33. package/lib/commonjs/sksg/Container.d.ts +6 -1
  34. package/lib/commonjs/sksg/Container.js +59 -2
  35. package/lib/commonjs/sksg/Container.js.map +1 -1
  36. package/lib/commonjs/sksg/Recorder/DrawingContext.js +1 -0
  37. package/lib/commonjs/sksg/Recorder/DrawingContext.js.map +1 -1
  38. package/lib/commonjs/sksg/Recorder/ReanimatedRecorder.d.ts +53 -0
  39. package/lib/commonjs/sksg/Recorder/ReanimatedRecorder.js +189 -0
  40. package/lib/commonjs/sksg/Recorder/ReanimatedRecorder.js.map +1 -0
  41. package/lib/commonjs/sksg/Recorder/Recorder.d.ts +2 -2
  42. package/lib/commonjs/sksg/Recorder/Recorder.js.map +1 -1
  43. package/lib/commonjs/sksg/Recorder/Visitor.d.ts +2 -2
  44. package/lib/commonjs/sksg/Recorder/Visitor.js +2 -2
  45. package/lib/commonjs/sksg/Recorder/Visitor.js.map +1 -1
  46. package/lib/module/renderer/components/image/Image.d.ts +1 -1
  47. package/lib/module/renderer/components/image/Image.js +8 -2
  48. package/lib/module/renderer/components/image/Image.js.map +1 -1
  49. package/lib/module/skia/types/Recorder.d.ts +52 -0
  50. package/lib/module/skia/types/Recorder.js +2 -0
  51. package/lib/module/skia/types/Recorder.js.map +1 -0
  52. package/lib/module/skia/types/Skia.d.ts +2 -0
  53. package/lib/module/skia/types/Skia.js.map +1 -1
  54. package/lib/module/skia/types/index.d.ts +1 -0
  55. package/lib/module/skia/types/index.js +1 -0
  56. package/lib/module/skia/types/index.js.map +1 -1
  57. package/lib/module/skia/web/JsiSkia.js +3 -0
  58. package/lib/module/skia/web/JsiSkia.js.map +1 -1
  59. package/lib/module/sksg/Container.d.ts +6 -1
  60. package/lib/module/sksg/Container.js +59 -2
  61. package/lib/module/sksg/Container.js.map +1 -1
  62. package/lib/module/sksg/Recorder/DrawingContext.js +1 -0
  63. package/lib/module/sksg/Recorder/DrawingContext.js.map +1 -1
  64. package/lib/module/sksg/Recorder/ReanimatedRecorder.d.ts +53 -0
  65. package/lib/module/sksg/Recorder/ReanimatedRecorder.js +182 -0
  66. package/lib/module/sksg/Recorder/ReanimatedRecorder.js.map +1 -0
  67. package/lib/module/sksg/Recorder/Recorder.d.ts +2 -2
  68. package/lib/module/sksg/Recorder/Recorder.js.map +1 -1
  69. package/lib/module/sksg/Recorder/Visitor.d.ts +2 -2
  70. package/lib/module/sksg/Recorder/Visitor.js +2 -2
  71. package/lib/module/sksg/Recorder/Visitor.js.map +1 -1
  72. package/lib/typescript/lib/commonjs/renderer/components/image/Image.d.ts +4 -1
  73. package/lib/typescript/lib/commonjs/skia/types/Recorder.d.ts +1 -0
  74. package/lib/typescript/lib/commonjs/skia/web/JsiSkia.d.ts +1 -0
  75. package/lib/typescript/lib/commonjs/sksg/Container.d.ts +5 -1
  76. package/lib/typescript/lib/commonjs/sksg/Reconciler.d.ts +6 -0
  77. package/lib/typescript/lib/commonjs/sksg/Recorder/ReanimatedRecorder.d.ts +47 -0
  78. package/lib/typescript/lib/module/mock/index.d.ts +4 -1
  79. package/lib/typescript/lib/module/renderer/components/image/Image.d.ts +4 -1
  80. package/lib/typescript/lib/module/skia/Skia.web.d.ts +1 -0
  81. package/lib/typescript/lib/module/skia/types/Recorder.d.ts +1 -0
  82. package/lib/typescript/lib/module/skia/types/index.d.ts +1 -0
  83. package/lib/typescript/lib/module/skia/web/JsiSkia.d.ts +1 -0
  84. package/lib/typescript/lib/module/sksg/Container.d.ts +5 -1
  85. package/lib/typescript/lib/module/sksg/Reconciler.d.ts +6 -0
  86. package/lib/typescript/lib/module/sksg/Recorder/ReanimatedRecorder.d.ts +46 -0
  87. package/lib/typescript/src/renderer/components/image/Image.d.ts +1 -1
  88. package/lib/typescript/src/skia/types/Recorder.d.ts +52 -0
  89. package/lib/typescript/src/skia/types/Skia.d.ts +2 -0
  90. package/lib/typescript/src/skia/types/index.d.ts +1 -0
  91. package/lib/typescript/src/sksg/Container.d.ts +6 -1
  92. package/lib/typescript/src/sksg/Recorder/ReanimatedRecorder.d.ts +53 -0
  93. package/lib/typescript/src/sksg/Recorder/Recorder.d.ts +2 -2
  94. package/lib/typescript/src/sksg/Recorder/Visitor.d.ts +2 -2
  95. package/package.json +3 -2
  96. package/src/renderer/components/image/Image.tsx +2 -2
  97. package/src/skia/types/Recorder.ts +91 -0
  98. package/src/skia/types/Skia.ts +2 -0
  99. package/src/skia/types/index.ts +1 -0
  100. package/src/skia/web/JsiSkia.ts +3 -0
  101. package/src/sksg/Container.ts +63 -4
  102. package/src/sksg/Recorder/DrawingContext.ts +1 -0
  103. package/src/sksg/Recorder/ReanimatedRecorder.ts +271 -0
  104. package/src/sksg/Recorder/Recorder.ts +2 -2
  105. package/src/sksg/Recorder/Visitor.ts +17 -12
@@ -0,0 +1,108 @@
1
+ #pragma once
2
+
3
+ #include <string>
4
+
5
+ #include <include/core/SkMatrix.h>
6
+ #include <include/core/SkRect.h>
7
+
8
+ // TODO: to rename once the old reconciler is removed
9
+ namespace RNSkiaImage {
10
+
11
+ struct FitSizes {
12
+ SkSize src;
13
+ SkSize dst;
14
+ };
15
+
16
+ struct FitRects {
17
+ SkRect src;
18
+ SkRect dst;
19
+ };
20
+
21
+ SkRect inscribe(SkSize size, SkRect rect) {
22
+ auto halfWidthDelta = (rect.width() - size.width()) / 2.0;
23
+ auto halfHeightDelta = (rect.height() - size.height()) / 2.0;
24
+ return SkRect::MakeXYWH(rect.x() + halfWidthDelta, rect.y() + halfHeightDelta,
25
+ size.width(), size.height());
26
+ }
27
+
28
+ SkMatrix rect2rect(SkRect src, SkRect dst) {
29
+ auto sx = dst.width() / src.width();
30
+ auto sy = dst.height() / src.height();
31
+ auto tx = dst.x() - src.x() * sx;
32
+ auto ty = dst.y() - src.y() * sy;
33
+ SkMatrix m3;
34
+ m3.preTranslate(tx, ty);
35
+ m3.preScale(sx, sy);
36
+ return m3;
37
+ }
38
+
39
+ SkSize size(double width, double height) { return SkSize::Make(width, height); }
40
+
41
+ FitSizes applyBoxFit(const std::string fit, SkSize input, SkSize output) {
42
+ SkSize src = size(0, 0);
43
+ SkSize dst = size(0, 0);
44
+
45
+ if (input.height() <= 0.0 || input.width() <= 0.0 || output.height() <= 0.0 ||
46
+ output.width() <= 0.0) {
47
+ return {.src = src, .dst = dst};
48
+ }
49
+
50
+ if (fit == "fill") {
51
+ src = input;
52
+ dst = output;
53
+ } else if (fit == "contain") {
54
+ src = input;
55
+ if (output.width() / output.height() > src.width() / src.height()) {
56
+ dst =
57
+ size((src.width() * output.height()) / src.height(), output.height());
58
+ } else {
59
+ dst = size(output.width(), (src.height() * output.width()) / src.width());
60
+ }
61
+ } else if (fit == "cover") {
62
+ if (output.width() / output.height() > input.width() / input.height()) {
63
+ src = size(input.width(),
64
+ (input.width() * output.height()) / output.width());
65
+ } else {
66
+ src = size((input.height() * output.width()) / output.height(),
67
+ input.height());
68
+ }
69
+ dst = output;
70
+ } else if (fit == "fitWidth") {
71
+ src =
72
+ size(input.width(), (input.width() * output.height()) / output.width());
73
+ dst = size(output.width(), (src.height() * output.width()) / src.width());
74
+ } else if (fit == "fitHeight") {
75
+ src = size((input.height() * output.width()) / output.height(),
76
+ input.height());
77
+ dst = size((src.width() * output.height()) / src.height(), output.height());
78
+ } else if (fit == "none") {
79
+ src = size(std::min(input.width(), output.width()),
80
+ std::min(input.height(), output.height()));
81
+ dst = src;
82
+ } else if (fit == "scaleDown") {
83
+ src = input;
84
+ dst = input;
85
+ auto aspectRatio = input.width() / input.height();
86
+ if (dst.height() > output.height()) {
87
+ dst = size(output.height() * aspectRatio, output.height());
88
+ }
89
+ if (dst.width() > output.width()) {
90
+ dst = size(output.width(), output.width() / aspectRatio);
91
+ }
92
+ } else {
93
+ throw std::runtime_error("The value \"" + fit +
94
+ "\" is not a valid fit value.");
95
+ }
96
+ return {.src = src, .dst = dst};
97
+ }
98
+
99
+ FitRects fitRects(const std::string &fit, SkRect rect, SkRect rect2) {
100
+ auto sizes = applyBoxFit(fit, size(rect.width(), rect.height()),
101
+ size(rect2.width(), rect2.height()));
102
+
103
+ auto src = inscribe(sizes.src, rect);
104
+ auto dst = inscribe(sizes.dst, rect2);
105
+
106
+ return {.src = src, .dst = dst};
107
+ }
108
+ } // namespace RNSkiaImage
@@ -0,0 +1,292 @@
1
+ #pragma once
2
+
3
+ #include <optional>
4
+ #include <string>
5
+ #include <variant>
6
+
7
+ #include "Command.h"
8
+ #include "Convertor.h"
9
+ #include "DrawingCtx.h"
10
+
11
+ namespace RNSkia {
12
+
13
+ struct BlurMaskFilterCmdProps {
14
+ float blur;
15
+ SkBlurStyle style;
16
+ bool respectCTM;
17
+ };
18
+
19
+ class BlurMaskFilterCmd : public Command {
20
+ private:
21
+ BlurMaskFilterCmdProps props;
22
+
23
+ public:
24
+ BlurMaskFilterCmd(jsi::Runtime &runtime, const jsi::Object &object,
25
+ Variables &variables)
26
+ : Command(CommandType::PushBlurMaskFilter, "skBlurMaskFilter") {
27
+ convertProperty(runtime, object, "blur", props.blur, variables);
28
+ convertProperty(runtime, object, "style", props.style, variables);
29
+ convertProperty(runtime, object, "respectCTM", props.respectCTM, variables);
30
+ }
31
+
32
+ void pushMaskFilter(DrawingCtx *ctx) {
33
+ auto [blur, style, respectCTM] = props;
34
+ auto maskFilter = SkMaskFilter::MakeBlur(style, blur, respectCTM);
35
+ ctx->getPaint().setMaskFilter(maskFilter);
36
+ }
37
+ };
38
+
39
+ struct BlurImageFilterProps {
40
+ Radius blur;
41
+ SkTileMode mode;
42
+ };
43
+
44
+ class BlurImageFilterCmd : public Command {
45
+ private:
46
+ BlurImageFilterProps props;
47
+
48
+ public:
49
+ BlurImageFilterCmd(jsi::Runtime &runtime, const jsi::Object &object,
50
+ Variables &variables)
51
+ : Command(CommandType::PushImageFilter, "skBlurImageFilter") {
52
+ convertProperty(runtime, object, "blur", props.blur, variables);
53
+ convertProperty(runtime, object, "mode", props.mode, variables);
54
+ }
55
+
56
+ void pushImageFilter(DrawingCtx *ctx) {
57
+ auto imgf =
58
+ SkImageFilters::Blur(props.blur.rX, props.blur.rY, props.mode, nullptr);
59
+ ctx->imageFilters.push_back(imgf);
60
+ }
61
+ };
62
+
63
+ struct OffsetImageFilterProps {
64
+ float x;
65
+ float y;
66
+ };
67
+
68
+ class OffsetImageFilterCmd : public Command {
69
+ private:
70
+ OffsetImageFilterProps props;
71
+
72
+ public:
73
+ OffsetImageFilterCmd(jsi::Runtime &runtime, const jsi::Object &object,
74
+ Variables &variables)
75
+ : Command(CommandType::PushImageFilter, "skOffsetImageFilter") {
76
+ convertProperty(runtime, object, "x", props.x, variables);
77
+ convertProperty(runtime, object, "y", props.y, variables);
78
+ }
79
+
80
+ void pushImageFilter(DrawingCtx *ctx) {
81
+ auto imgf = SkImageFilters::Offset(props.x, props.y, nullptr);
82
+ ctx->imageFilters.push_back(imgf);
83
+ }
84
+ };
85
+
86
+ struct DisplacementMapImageFilterProps {
87
+ SkColorChannel channelX;
88
+ SkColorChannel channelY;
89
+ float scale;
90
+ };
91
+
92
+ class DisplacementMapImageFilterCmd : public Command {
93
+ private:
94
+ DisplacementMapImageFilterProps props;
95
+
96
+ public:
97
+ DisplacementMapImageFilterCmd(jsi::Runtime &runtime,
98
+ const jsi::Object &object, Variables &variables)
99
+ : Command(CommandType::PushImageFilter, "skDisplacementMapImageFilter") {
100
+ convertProperty(runtime, object, "channelX", props.channelX, variables);
101
+ convertProperty(runtime, object, "channelY", props.channelY, variables);
102
+ convertProperty(runtime, object, "scale", props.scale, variables);
103
+ }
104
+
105
+ void pushImageFilter(DrawingCtx *ctx) {
106
+ auto shader = ctx->shaders.back();
107
+ ctx->shaders.pop_back();
108
+ auto map = SkImageFilters::Shader(shader, nullptr);
109
+ auto imgf = SkImageFilters::DisplacementMap(props.channelX, props.channelY,
110
+ props.scale, map, nullptr);
111
+ ctx->imageFilters.push_back(imgf);
112
+ }
113
+ };
114
+
115
+ struct DropShadowImageFilterProps {
116
+ float dx;
117
+ float dy;
118
+ float blur;
119
+ SkColor color;
120
+ std::optional<bool> inner;
121
+ std::optional<bool> shadowOnly;
122
+ };
123
+
124
+ class DropShadowImageFilterCmd : public Command {
125
+ private:
126
+ DropShadowImageFilterProps props;
127
+
128
+ sk_sp<SkImageFilter> MakeInnerShadow(bool shadowOnly, float dx, float dy,
129
+ float sigmaX, float sigmaY,
130
+ SkColor color,
131
+ sk_sp<SkImageFilter> input) {
132
+ auto sourceGraphic = SkImageFilters::ColorFilter(
133
+ SkColorFilters::Blend(SK_ColorBLACK, SkBlendMode::kDst), nullptr);
134
+
135
+ auto sourceAlpha = SkImageFilters::ColorFilter(
136
+ SkColorFilters::Blend(SK_ColorBLACK, SkBlendMode::kSrcIn), nullptr);
137
+
138
+ auto f1 = SkImageFilters::ColorFilter(
139
+ SkColorFilters::Blend(color, SkBlendMode::kSrcOut), nullptr);
140
+
141
+ auto f2 = SkImageFilters::Offset(dx, dy, f1);
142
+ auto f3 = SkImageFilters::Blur(sigmaX, sigmaY, SkTileMode::kDecal, f2);
143
+ auto f4 = SkImageFilters::Blend(SkBlendMode::kSrcIn, sourceAlpha, f3);
144
+
145
+ if (shadowOnly) {
146
+ return f4;
147
+ }
148
+
149
+ return SkImageFilters::Compose(
150
+ input, SkImageFilters::Blend(SkBlendMode::kSrcOver, sourceGraphic, f4));
151
+ }
152
+
153
+ public:
154
+ DropShadowImageFilterCmd(jsi::Runtime &runtime, const jsi::Object &object,
155
+ Variables &variables)
156
+ : Command(CommandType::PushImageFilter, "skDropShadowImageFilter") {
157
+ convertProperty(runtime, object, "dx", props.dx, variables);
158
+ convertProperty(runtime, object, "dy", props.dy, variables);
159
+ convertProperty(runtime, object, "blur", props.blur, variables);
160
+ convertProperty(runtime, object, "color", props.color, variables);
161
+ convertProperty(runtime, object, "inner", props.inner, variables);
162
+ convertProperty(runtime, object, "shadowOnly", props.shadowOnly, variables);
163
+ }
164
+
165
+ void pushImageFilter(DrawingCtx *ctx) {
166
+ auto shadowOnly = props.shadowOnly.value_or(false);
167
+ auto inner = props.inner.value_or(false);
168
+
169
+ sk_sp<SkImageFilter> imgf;
170
+ if (inner) {
171
+ imgf = MakeInnerShadow(shadowOnly, props.dx, props.dy, props.blur,
172
+ props.blur, props.color, nullptr);
173
+ } else {
174
+ if (shadowOnly) {
175
+ imgf = SkImageFilters::DropShadowOnly(props.dx, props.dy, props.blur,
176
+ props.blur, props.color, nullptr);
177
+ } else {
178
+ imgf = SkImageFilters::DropShadow(props.dx, props.dy, props.blur,
179
+ props.blur, props.color, nullptr);
180
+ }
181
+ }
182
+ ctx->imageFilters.push_back(imgf);
183
+ }
184
+ };
185
+
186
+ struct MorphologyImageFilterProps {
187
+ std::string op; // "erode" or "dilate"
188
+ Radius radius;
189
+ };
190
+
191
+ class MorphologyImageFilterCmd : public Command {
192
+ private:
193
+ MorphologyImageFilterProps props;
194
+
195
+ public:
196
+ MorphologyImageFilterCmd(jsi::Runtime &runtime, const jsi::Object &object,
197
+ Variables &variables)
198
+ : Command(CommandType::PushImageFilter, "skMorphologyImageFilter") {
199
+ convertProperty(runtime, object, "operator", props.op, variables);
200
+ convertProperty(runtime, object, "radius", props.radius, variables);
201
+ }
202
+
203
+ void pushImageFilter(DrawingCtx *ctx) {
204
+ if (props.op == "erode") {
205
+ auto imgf =
206
+ SkImageFilters::Erode(props.radius.rX, props.radius.rY, nullptr);
207
+ ctx->imageFilters.push_back(imgf);
208
+ } else {
209
+ auto imgf =
210
+ SkImageFilters::Dilate(props.radius.rX, props.radius.rY, nullptr);
211
+ ctx->imageFilters.push_back(imgf);
212
+ }
213
+ }
214
+ };
215
+
216
+ struct BlendImageFilterProps {
217
+ SkBlendMode mode;
218
+ };
219
+
220
+ class BlendImageFilterCmd : public Command {
221
+ private:
222
+ BlendImageFilterProps props;
223
+
224
+ public:
225
+ BlendImageFilterCmd(jsi::Runtime &runtime, const jsi::Object &object,
226
+ Variables &variables)
227
+ : Command(CommandType::PushImageFilter, "skBlendImageFilter") {
228
+ convertProperty(runtime, object, "mode", props.mode, variables);
229
+ }
230
+
231
+ void pushImageFilter(DrawingCtx *ctx) {
232
+ // Get all filters
233
+ auto filters = std::move(ctx->imageFilters);
234
+ ctx->imageFilters.clear();
235
+
236
+ // Create composer function
237
+ auto composer = [this](sk_sp<SkImageFilter> outer,
238
+ sk_sp<SkImageFilter> inner) {
239
+ return SkImageFilters::Blend(props.mode, outer, inner);
240
+ };
241
+
242
+ // Compose filters
243
+ auto composedFilter = composeEffects<SkImageFilter>(filters, composer);
244
+
245
+ if (composedFilter) {
246
+ ctx->imageFilters.push_back(composedFilter);
247
+ }
248
+ }
249
+ };
250
+
251
+ struct RuntimeShaderImageFilterProps {
252
+ sk_sp<SkRuntimeEffect> source;
253
+ std::optional<Uniforms> uniforms;
254
+ };
255
+
256
+ class RuntimeShaderImageFilterCmd : public Command {
257
+ private:
258
+ RuntimeShaderImageFilterProps props;
259
+
260
+ public:
261
+ RuntimeShaderImageFilterCmd(jsi::Runtime &runtime, const jsi::Object &object,
262
+ Variables &variables)
263
+ : Command(CommandType::PushImageFilter, "skRuntimeShaderImageFilter") {
264
+ convertProperty(runtime, object, "source", props.source, variables);
265
+ convertProperty(runtime, object, "uniforms", props.uniforms, variables);
266
+ }
267
+
268
+ void pushImageFilter(DrawingCtx *ctx) {
269
+ if (props.source) {
270
+ // Create the runtime shader builder
271
+ SkRuntimeShaderBuilder builder(props.source);
272
+
273
+ // Process uniforms if present
274
+ if (props.uniforms.has_value()) {
275
+ processUniforms(builder, props.source, props.uniforms.value());
276
+ }
277
+
278
+ // Get the input filter (if any)
279
+ sk_sp<SkImageFilter> input = nullptr;
280
+ if (!ctx->imageFilters.empty()) {
281
+ input = ctx->imageFilters.back();
282
+ ctx->imageFilters.pop_back();
283
+ }
284
+
285
+ // Create and push the runtime shader image filter
286
+ auto imgf = SkImageFilters::RuntimeShader(builder, "", input);
287
+ ctx->imageFilters.push_back(imgf);
288
+ }
289
+ }
290
+ };
291
+
292
+ } // namespace RNSkia
@@ -0,0 +1,314 @@
1
+ #pragma once
2
+
3
+ #include <memory>
4
+ #include <numeric>
5
+ #include <utility>
6
+ #include <vector>
7
+
8
+ #include "JsiSkCanvas.h"
9
+ #include "JsiSkHostObjects.h"
10
+
11
+ #include "DrawingCtx.h"
12
+ #include "RNRecorder.h"
13
+ #include "RNSkLog.h"
14
+
15
+ #include <jsi/jsi.h>
16
+
17
+ namespace RNSkia {
18
+
19
+ namespace jsi = facebook::jsi;
20
+
21
+ class JsiRecorder : public JsiSkWrappingSharedPtrHostObject<Recorder> {
22
+ public:
23
+ JsiRecorder(std::shared_ptr<RNSkPlatformContext> context)
24
+ : JsiSkWrappingSharedPtrHostObject(std::move(context),
25
+ std::make_shared<Recorder>()) {}
26
+
27
+ JSI_HOST_FUNCTION(savePaint) {
28
+ getObject()->savePaint(runtime, arguments[0].asObject(runtime));
29
+ return jsi::Value::undefined();
30
+ }
31
+
32
+ JSI_HOST_FUNCTION(materializePaint) {
33
+ getObject()->materializePaint();
34
+ return jsi::Value::undefined();
35
+ }
36
+
37
+ JSI_HOST_FUNCTION(drawCircle) {
38
+ getObject()->drawCircle(runtime, arguments[0].asObject(runtime));
39
+ return jsi::Value::undefined();
40
+ }
41
+
42
+ JSI_HOST_FUNCTION(restorePaint) {
43
+ getObject()->restorePaint();
44
+ return jsi::Value::undefined();
45
+ }
46
+
47
+ JSI_HOST_FUNCTION(drawPaint) {
48
+ getObject()->drawPaint();
49
+ return jsi::Value::undefined();
50
+ }
51
+
52
+ JSI_HOST_FUNCTION(play) {
53
+ auto jsiCanvas =
54
+ arguments[0].asObject(runtime).asHostObject<JsiSkCanvas>(runtime);
55
+ DrawingCtx ctx(jsiCanvas->getCanvas());
56
+ getObject()->play(&ctx);
57
+ return jsi::Value::undefined();
58
+ }
59
+
60
+ JSI_HOST_FUNCTION(applyUpdates) {
61
+ auto values = arguments[0].asObject(runtime).asArray(runtime);
62
+ auto size = values.size(runtime);
63
+ auto recorder = getObject();
64
+ for (int i = 0; i < size; i++) {
65
+ auto sharedValue = values.getValueAtIndex(runtime, i).asObject(runtime);
66
+ auto name = "variable" + std::to_string(i);
67
+ // Look up the conversion functions for this name
68
+ auto it = recorder->variables.find(name);
69
+ if (it != recorder->variables.end()) {
70
+ // Execute each conversion function in the vector
71
+ const auto &conversionFunctions = it->second;
72
+ for (const auto &conversionFunc : conversionFunctions) {
73
+ conversionFunc(runtime, sharedValue);
74
+ }
75
+ }
76
+ }
77
+ return jsi::Value::undefined();
78
+ }
79
+
80
+ JSI_HOST_FUNCTION(saveGroup) {
81
+ getObject()->saveGroup();
82
+ return jsi::Value::undefined();
83
+ }
84
+
85
+ JSI_HOST_FUNCTION(restoreGroup) {
86
+ getObject()->restoreGroup();
87
+ return jsi::Value::undefined();
88
+ }
89
+
90
+ JSI_HOST_FUNCTION(restorePaintDeclaration) {
91
+ getObject()->restorePaintDeclaration();
92
+ return jsi::Value::undefined();
93
+ }
94
+
95
+ JSI_HOST_FUNCTION(pushPathEffect) {
96
+ getObject()->pushPathEffect(runtime,
97
+ arguments[0].asString(runtime).utf8(runtime),
98
+ arguments[1].asObject(runtime));
99
+ return jsi::Value::undefined();
100
+ }
101
+
102
+ JSI_HOST_FUNCTION(pushImageFilter) {
103
+ getObject()->pushImageFilter(runtime,
104
+ arguments[0].asString(runtime).utf8(runtime),
105
+ arguments[1].asObject(runtime));
106
+ return jsi::Value::undefined();
107
+ }
108
+
109
+ JSI_HOST_FUNCTION(pushColorFilter) {
110
+ getObject()->pushColorFilter(runtime,
111
+ arguments[0].asString(runtime).utf8(runtime),
112
+ arguments[1].asObject(runtime));
113
+ return jsi::Value::undefined();
114
+ }
115
+
116
+ JSI_HOST_FUNCTION(pushShader) {
117
+ getObject()->pushShader(runtime,
118
+ arguments[0].asString(runtime).utf8(runtime),
119
+ arguments[1].asObject(runtime));
120
+ return jsi::Value::undefined();
121
+ }
122
+
123
+ JSI_HOST_FUNCTION(pushBlurMaskFilter) {
124
+ getObject()->pushBlurMaskFilter(runtime, arguments[0].asObject(runtime));
125
+ return jsi::Value::undefined();
126
+ }
127
+
128
+ JSI_HOST_FUNCTION(composePathEffect) {
129
+ getObject()->composePathEffect();
130
+ return jsi::Value::undefined();
131
+ }
132
+
133
+ JSI_HOST_FUNCTION(composeColorFilter) {
134
+ getObject()->composeColorFilter();
135
+ return jsi::Value::undefined();
136
+ }
137
+
138
+ JSI_HOST_FUNCTION(composeImageFilter) {
139
+ getObject()->composeImageFilter();
140
+ return jsi::Value::undefined();
141
+ }
142
+
143
+ JSI_HOST_FUNCTION(saveCTM) {
144
+ getObject()->saveCTM(runtime, arguments[0].asObject(runtime));
145
+ return jsi::Value::undefined();
146
+ }
147
+
148
+ JSI_HOST_FUNCTION(restoreCTM) {
149
+ getObject()->restoreCTM();
150
+ return jsi::Value::undefined();
151
+ }
152
+
153
+ JSI_HOST_FUNCTION(saveLayer) {
154
+ getObject()->saveLayer();
155
+ return jsi::Value::undefined();
156
+ }
157
+
158
+ JSI_HOST_FUNCTION(saveBackdropFilter) {
159
+ getObject()->saveBackdropFilter();
160
+ return jsi::Value::undefined();
161
+ }
162
+
163
+ JSI_HOST_FUNCTION(drawBox) {
164
+ auto boxProps = arguments[0].asObject(runtime);
165
+ auto shadowsArray = arguments[1].asObject(runtime).asArray(runtime);
166
+ getObject()->drawBox(runtime, boxProps, shadowsArray);
167
+ return jsi::Value::undefined();
168
+ }
169
+
170
+ JSI_HOST_FUNCTION(drawImage) {
171
+ getObject()->drawImage(runtime, arguments[0].asObject(runtime));
172
+ return jsi::Value::undefined();
173
+ }
174
+
175
+ JSI_HOST_FUNCTION(drawPoints) {
176
+ getObject()->drawPoints(runtime, arguments[0].asObject(runtime));
177
+ return jsi::Value::undefined();
178
+ }
179
+
180
+ JSI_HOST_FUNCTION(drawPath) {
181
+ getObject()->drawPath(runtime, arguments[0].asObject(runtime));
182
+ return jsi::Value::undefined();
183
+ }
184
+
185
+ JSI_HOST_FUNCTION(drawRect) {
186
+ getObject()->drawRect(runtime, arguments[0].asObject(runtime));
187
+ return jsi::Value::undefined();
188
+ }
189
+
190
+ JSI_HOST_FUNCTION(drawRRect) {
191
+ getObject()->drawRRect(runtime, arguments[0].asObject(runtime));
192
+ return jsi::Value::undefined();
193
+ }
194
+
195
+ JSI_HOST_FUNCTION(drawOval) {
196
+ getObject()->drawOval(runtime, arguments[0].asObject(runtime));
197
+ return jsi::Value::undefined();
198
+ }
199
+
200
+ JSI_HOST_FUNCTION(drawLine) {
201
+ getObject()->drawLine(runtime, arguments[0].asObject(runtime));
202
+ return jsi::Value::undefined();
203
+ }
204
+
205
+ JSI_HOST_FUNCTION(drawPatch) {
206
+ getObject()->drawPatch(runtime, arguments[0].asObject(runtime));
207
+ return jsi::Value::undefined();
208
+ }
209
+
210
+ JSI_HOST_FUNCTION(drawVertices) {
211
+ getObject()->drawVertices(runtime, arguments[0].asObject(runtime));
212
+ return jsi::Value::undefined();
213
+ }
214
+
215
+ JSI_HOST_FUNCTION(drawDiffRect) {
216
+ getObject()->drawDiffRect(runtime, arguments[0].asObject(runtime));
217
+ return jsi::Value::undefined();
218
+ }
219
+
220
+ JSI_HOST_FUNCTION(drawText) {
221
+ getObject()->drawText(runtime, arguments[0].asObject(runtime));
222
+ return jsi::Value::undefined();
223
+ }
224
+
225
+ JSI_HOST_FUNCTION(drawTextPath) {
226
+ getObject()->drawTextPath(runtime, arguments[0].asObject(runtime));
227
+ return jsi::Value::undefined();
228
+ }
229
+
230
+ JSI_HOST_FUNCTION(drawTextBlob) {
231
+ getObject()->drawTextBlob(runtime, arguments[0].asObject(runtime));
232
+ return jsi::Value::undefined();
233
+ }
234
+
235
+ JSI_HOST_FUNCTION(drawGlyphs) {
236
+ getObject()->drawGlyphs(runtime, arguments[0].asObject(runtime));
237
+ return jsi::Value::undefined();
238
+ }
239
+
240
+ JSI_HOST_FUNCTION(drawPicture) {
241
+ getObject()->drawPicture(runtime, arguments[0].asObject(runtime));
242
+ return jsi::Value::undefined();
243
+ }
244
+
245
+ JSI_HOST_FUNCTION(drawImageSVG) {
246
+ getObject()->drawImageSVG(runtime, arguments[0].asObject(runtime));
247
+ return jsi::Value::undefined();
248
+ }
249
+
250
+ JSI_HOST_FUNCTION(drawParagraph) {
251
+ getObject()->drawParagraph(runtime, arguments[0].asObject(runtime));
252
+ return jsi::Value::undefined();
253
+ }
254
+
255
+ JSI_HOST_FUNCTION(drawAtlas) {
256
+ getObject()->drawAtlas(runtime, arguments[0].asObject(runtime));
257
+ return jsi::Value::undefined();
258
+ }
259
+
260
+ EXPORT_JSI_API_TYPENAME(JsiRecorder, Recorder)
261
+
262
+ JSI_EXPORT_FUNCTIONS(JSI_EXPORT_FUNC(JsiRecorder, saveGroup),
263
+ JSI_EXPORT_FUNC(JsiRecorder, restoreGroup),
264
+ JSI_EXPORT_FUNC(JsiRecorder, savePaint),
265
+ JSI_EXPORT_FUNC(JsiRecorder, restorePaint),
266
+ JSI_EXPORT_FUNC(JsiRecorder, restorePaintDeclaration),
267
+ JSI_EXPORT_FUNC(JsiRecorder, materializePaint),
268
+ JSI_EXPORT_FUNC(JsiRecorder, pushPathEffect),
269
+ JSI_EXPORT_FUNC(JsiRecorder, pushImageFilter),
270
+ JSI_EXPORT_FUNC(JsiRecorder, pushColorFilter),
271
+ JSI_EXPORT_FUNC(JsiRecorder, pushShader),
272
+ JSI_EXPORT_FUNC(JsiRecorder, pushBlurMaskFilter),
273
+ JSI_EXPORT_FUNC(JsiRecorder, composePathEffect),
274
+ JSI_EXPORT_FUNC(JsiRecorder, composeColorFilter),
275
+ JSI_EXPORT_FUNC(JsiRecorder, composeImageFilter),
276
+ JSI_EXPORT_FUNC(JsiRecorder, saveCTM),
277
+ JSI_EXPORT_FUNC(JsiRecorder, restoreCTM),
278
+ JSI_EXPORT_FUNC(JsiRecorder, drawPaint),
279
+ JSI_EXPORT_FUNC(JsiRecorder, saveLayer),
280
+ JSI_EXPORT_FUNC(JsiRecorder, saveBackdropFilter),
281
+ JSI_EXPORT_FUNC(JsiRecorder, drawBox),
282
+ JSI_EXPORT_FUNC(JsiRecorder, drawImage),
283
+ JSI_EXPORT_FUNC(JsiRecorder, drawCircle),
284
+ JSI_EXPORT_FUNC(JsiRecorder, drawPoints),
285
+ JSI_EXPORT_FUNC(JsiRecorder, drawPath),
286
+ JSI_EXPORT_FUNC(JsiRecorder, drawRect),
287
+ JSI_EXPORT_FUNC(JsiRecorder, drawRRect),
288
+ JSI_EXPORT_FUNC(JsiRecorder, drawOval),
289
+ JSI_EXPORT_FUNC(JsiRecorder, drawLine),
290
+ JSI_EXPORT_FUNC(JsiRecorder, drawPatch),
291
+ JSI_EXPORT_FUNC(JsiRecorder, drawVertices),
292
+ JSI_EXPORT_FUNC(JsiRecorder, drawDiffRect),
293
+ JSI_EXPORT_FUNC(JsiRecorder, drawText),
294
+ JSI_EXPORT_FUNC(JsiRecorder, drawTextPath),
295
+ JSI_EXPORT_FUNC(JsiRecorder, drawTextBlob),
296
+ JSI_EXPORT_FUNC(JsiRecorder, drawGlyphs),
297
+ JSI_EXPORT_FUNC(JsiRecorder, drawPicture),
298
+ JSI_EXPORT_FUNC(JsiRecorder, drawImageSVG),
299
+ JSI_EXPORT_FUNC(JsiRecorder, drawParagraph),
300
+ JSI_EXPORT_FUNC(JsiRecorder, drawAtlas),
301
+ JSI_EXPORT_FUNC(JsiRecorder, play),
302
+ JSI_EXPORT_FUNC(JsiRecorder, applyUpdates))
303
+
304
+ static const jsi::HostFunctionType
305
+ createCtor(std::shared_ptr<RNSkPlatformContext> context) {
306
+ return JSI_HOST_FUNCTION_LAMBDA {
307
+ // Return the newly constructed object
308
+ return jsi::Object::createFromHostObject(
309
+ runtime, std::make_shared<JsiRecorder>(std::move(context)));
310
+ };
311
+ }
312
+ };
313
+
314
+ } // namespace RNSkia