@shopify/react-native-skia 1.10.2 → 1.11.1

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 (104) 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 +1213 -0
  5. package/cpp/api/recorder/DataTypes.h +232 -0
  6. package/cpp/api/recorder/DrawingCtx.h +187 -0
  7. package/cpp/api/recorder/Drawings.h +950 -0
  8. package/cpp/api/recorder/ImageFilters.h +292 -0
  9. package/cpp/api/recorder/ImageFit.h +108 -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 +637 -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/jestSetup.js +8 -0
  18. package/jestSetup.mjs +8 -0
  19. package/lib/commonjs/renderer/components/image/Image.d.ts +1 -1
  20. package/lib/commonjs/renderer/components/image/Image.js +8 -2
  21. package/lib/commonjs/renderer/components/image/Image.js.map +1 -1
  22. package/lib/commonjs/skia/types/Recorder.d.ts +52 -0
  23. package/lib/commonjs/skia/types/Recorder.js +6 -0
  24. package/lib/commonjs/skia/types/Recorder.js.map +1 -0
  25. package/lib/commonjs/skia/types/Skia.d.ts +2 -0
  26. package/lib/commonjs/skia/types/Skia.js.map +1 -1
  27. package/lib/commonjs/skia/types/index.d.ts +1 -0
  28. package/lib/commonjs/skia/types/index.js +11 -0
  29. package/lib/commonjs/skia/types/index.js.map +1 -1
  30. package/lib/commonjs/skia/web/JsiSkia.js +3 -0
  31. package/lib/commonjs/skia/web/JsiSkia.js.map +1 -1
  32. package/lib/commonjs/sksg/Container.d.ts +6 -1
  33. package/lib/commonjs/sksg/Container.js +59 -2
  34. package/lib/commonjs/sksg/Container.js.map +1 -1
  35. package/lib/commonjs/sksg/Recorder/DrawingContext.js +1 -0
  36. package/lib/commonjs/sksg/Recorder/DrawingContext.js.map +1 -1
  37. package/lib/commonjs/sksg/Recorder/ReanimatedRecorder.d.ts +53 -0
  38. package/lib/commonjs/sksg/Recorder/ReanimatedRecorder.js +189 -0
  39. package/lib/commonjs/sksg/Recorder/ReanimatedRecorder.js.map +1 -0
  40. package/lib/commonjs/sksg/Recorder/Recorder.d.ts +2 -2
  41. package/lib/commonjs/sksg/Recorder/Recorder.js.map +1 -1
  42. package/lib/commonjs/sksg/Recorder/Visitor.d.ts +2 -2
  43. package/lib/commonjs/sksg/Recorder/Visitor.js +2 -2
  44. package/lib/commonjs/sksg/Recorder/Visitor.js.map +1 -1
  45. package/lib/module/renderer/components/image/Image.d.ts +1 -1
  46. package/lib/module/renderer/components/image/Image.js +8 -2
  47. package/lib/module/renderer/components/image/Image.js.map +1 -1
  48. package/lib/module/skia/types/Recorder.d.ts +52 -0
  49. package/lib/module/skia/types/Recorder.js +2 -0
  50. package/lib/module/skia/types/Recorder.js.map +1 -0
  51. package/lib/module/skia/types/Skia.d.ts +2 -0
  52. package/lib/module/skia/types/Skia.js.map +1 -1
  53. package/lib/module/skia/types/index.d.ts +1 -0
  54. package/lib/module/skia/types/index.js +1 -0
  55. package/lib/module/skia/types/index.js.map +1 -1
  56. package/lib/module/skia/web/JsiSkia.js +3 -0
  57. package/lib/module/skia/web/JsiSkia.js.map +1 -1
  58. package/lib/module/sksg/Container.d.ts +6 -1
  59. package/lib/module/sksg/Container.js +59 -2
  60. package/lib/module/sksg/Container.js.map +1 -1
  61. package/lib/module/sksg/Recorder/DrawingContext.js +1 -0
  62. package/lib/module/sksg/Recorder/DrawingContext.js.map +1 -1
  63. package/lib/module/sksg/Recorder/ReanimatedRecorder.d.ts +53 -0
  64. package/lib/module/sksg/Recorder/ReanimatedRecorder.js +182 -0
  65. package/lib/module/sksg/Recorder/ReanimatedRecorder.js.map +1 -0
  66. package/lib/module/sksg/Recorder/Recorder.d.ts +2 -2
  67. package/lib/module/sksg/Recorder/Recorder.js.map +1 -1
  68. package/lib/module/sksg/Recorder/Visitor.d.ts +2 -2
  69. package/lib/module/sksg/Recorder/Visitor.js +2 -2
  70. package/lib/module/sksg/Recorder/Visitor.js.map +1 -1
  71. package/lib/typescript/lib/commonjs/renderer/components/image/Image.d.ts +4 -1
  72. package/lib/typescript/lib/commonjs/skia/types/Recorder.d.ts +1 -0
  73. package/lib/typescript/lib/commonjs/skia/web/JsiSkia.d.ts +1 -0
  74. package/lib/typescript/lib/commonjs/sksg/Container.d.ts +5 -1
  75. package/lib/typescript/lib/commonjs/sksg/Reconciler.d.ts +6 -0
  76. package/lib/typescript/lib/commonjs/sksg/Recorder/ReanimatedRecorder.d.ts +47 -0
  77. package/lib/typescript/lib/module/mock/index.d.ts +4 -1
  78. package/lib/typescript/lib/module/renderer/components/image/Image.d.ts +4 -1
  79. package/lib/typescript/lib/module/skia/Skia.web.d.ts +1 -0
  80. package/lib/typescript/lib/module/skia/types/Recorder.d.ts +1 -0
  81. package/lib/typescript/lib/module/skia/types/index.d.ts +1 -0
  82. package/lib/typescript/lib/module/skia/web/JsiSkia.d.ts +1 -0
  83. package/lib/typescript/lib/module/sksg/Container.d.ts +5 -1
  84. package/lib/typescript/lib/module/sksg/Reconciler.d.ts +6 -0
  85. package/lib/typescript/lib/module/sksg/Recorder/ReanimatedRecorder.d.ts +46 -0
  86. package/lib/typescript/src/renderer/components/image/Image.d.ts +1 -1
  87. package/lib/typescript/src/skia/types/Recorder.d.ts +52 -0
  88. package/lib/typescript/src/skia/types/Skia.d.ts +2 -0
  89. package/lib/typescript/src/skia/types/index.d.ts +1 -0
  90. package/lib/typescript/src/sksg/Container.d.ts +6 -1
  91. package/lib/typescript/src/sksg/Recorder/ReanimatedRecorder.d.ts +53 -0
  92. package/lib/typescript/src/sksg/Recorder/Recorder.d.ts +2 -2
  93. package/lib/typescript/src/sksg/Recorder/Visitor.d.ts +2 -2
  94. package/package.json +3 -2
  95. package/src/renderer/components/image/Image.tsx +2 -2
  96. package/src/skia/types/Recorder.ts +91 -0
  97. package/src/skia/types/Skia.ts +2 -0
  98. package/src/skia/types/index.ts +1 -0
  99. package/src/skia/web/JsiSkia.ts +3 -0
  100. package/src/sksg/Container.ts +63 -4
  101. package/src/sksg/Recorder/DrawingContext.ts +1 -0
  102. package/src/sksg/Recorder/ReanimatedRecorder.ts +271 -0
  103. package/src/sksg/Recorder/Recorder.ts +2 -2
  104. package/src/sksg/Recorder/Visitor.ts +17 -12
@@ -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,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,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