@shopify/react-native-skia 2.3.14 → 2.4.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 (71) hide show
  1. package/cpp/api/JsiSkPictureFactory.h +24 -6
  2. package/cpp/api/recorder/Command.h +12 -0
  3. package/cpp/api/recorder/JsiRecorder.h +2 -1
  4. package/cpp/api/recorder/RNRecorder.h +434 -374
  5. package/lib/commonjs/dom/types/Common.d.ts +1 -0
  6. package/lib/commonjs/dom/types/Common.js.map +1 -1
  7. package/lib/commonjs/skia/types/Recorder.d.ts +2 -2
  8. package/lib/commonjs/skia/types/Recorder.js.map +1 -1
  9. package/lib/commonjs/sksg/Recorder/Core.d.ts +2 -1
  10. package/lib/commonjs/sksg/Recorder/Core.js +0 -42
  11. package/lib/commonjs/sksg/Recorder/Core.js.map +1 -1
  12. package/lib/commonjs/sksg/Recorder/Debug.d.ts +2 -0
  13. package/lib/commonjs/sksg/Recorder/Debug.js +86 -0
  14. package/lib/commonjs/sksg/Recorder/Debug.js.map +1 -0
  15. package/lib/commonjs/sksg/Recorder/Player.d.ts +1 -1
  16. package/lib/commonjs/sksg/Recorder/Player.js +51 -7
  17. package/lib/commonjs/sksg/Recorder/Player.js.map +1 -1
  18. package/lib/commonjs/sksg/Recorder/ReanimatedRecorder.d.ts +2 -2
  19. package/lib/commonjs/sksg/Recorder/ReanimatedRecorder.js +7 -2
  20. package/lib/commonjs/sksg/Recorder/ReanimatedRecorder.js.map +1 -1
  21. package/lib/commonjs/sksg/Recorder/Recorder.d.ts +2 -2
  22. package/lib/commonjs/sksg/Recorder/Recorder.js +7 -3
  23. package/lib/commonjs/sksg/Recorder/Recorder.js.map +1 -1
  24. package/lib/commonjs/sksg/Recorder/Visitor.js +14 -6
  25. package/lib/commonjs/sksg/Recorder/Visitor.js.map +1 -1
  26. package/lib/commonjs/views/SkiaPictureView.js.map +1 -1
  27. package/lib/module/dom/types/Common.d.ts +1 -0
  28. package/lib/module/dom/types/Common.js.map +1 -1
  29. package/lib/module/skia/types/Recorder.d.ts +2 -2
  30. package/lib/module/skia/types/Recorder.js.map +1 -1
  31. package/lib/module/sksg/Recorder/Core.d.ts +2 -1
  32. package/lib/module/sksg/Recorder/Core.js +0 -42
  33. package/lib/module/sksg/Recorder/Core.js.map +1 -1
  34. package/lib/module/sksg/Recorder/Debug.d.ts +2 -0
  35. package/lib/module/sksg/Recorder/Debug.js +79 -0
  36. package/lib/module/sksg/Recorder/Debug.js.map +1 -0
  37. package/lib/module/sksg/Recorder/Player.d.ts +1 -1
  38. package/lib/module/sksg/Recorder/Player.js +50 -5
  39. package/lib/module/sksg/Recorder/Player.js.map +1 -1
  40. package/lib/module/sksg/Recorder/ReanimatedRecorder.d.ts +2 -2
  41. package/lib/module/sksg/Recorder/ReanimatedRecorder.js +7 -2
  42. package/lib/module/sksg/Recorder/ReanimatedRecorder.js.map +1 -1
  43. package/lib/module/sksg/Recorder/Recorder.d.ts +2 -2
  44. package/lib/module/sksg/Recorder/Recorder.js +7 -3
  45. package/lib/module/sksg/Recorder/Recorder.js.map +1 -1
  46. package/lib/module/sksg/Recorder/Visitor.js +14 -6
  47. package/lib/module/sksg/Recorder/Visitor.js.map +1 -1
  48. package/lib/module/views/SkiaPictureView.js.map +1 -1
  49. package/lib/typescript/lib/commonjs/sksg/Recorder/Debug.d.ts +2 -0
  50. package/lib/typescript/lib/commonjs/sksg/Recorder/ReanimatedRecorder.d.ts +1 -1
  51. package/lib/typescript/lib/commonjs/sksg/Recorder/Recorder.d.ts +1 -1
  52. package/lib/typescript/lib/module/sksg/Recorder/Debug.d.ts +1 -0
  53. package/lib/typescript/lib/module/sksg/Recorder/ReanimatedRecorder.d.ts +1 -1
  54. package/lib/typescript/lib/module/sksg/Recorder/Recorder.d.ts +1 -1
  55. package/lib/typescript/src/dom/types/Common.d.ts +1 -0
  56. package/lib/typescript/src/skia/types/Recorder.d.ts +2 -2
  57. package/lib/typescript/src/sksg/Recorder/Core.d.ts +2 -1
  58. package/lib/typescript/src/sksg/Recorder/Debug.d.ts +2 -0
  59. package/lib/typescript/src/sksg/Recorder/Player.d.ts +1 -1
  60. package/lib/typescript/src/sksg/Recorder/ReanimatedRecorder.d.ts +2 -2
  61. package/lib/typescript/src/sksg/Recorder/Recorder.d.ts +2 -2
  62. package/package.json +1 -1
  63. package/src/dom/types/Common.ts +3 -1
  64. package/src/skia/types/Recorder.ts +2 -1
  65. package/src/sksg/Recorder/Core.ts +2 -43
  66. package/src/sksg/Recorder/Debug.ts +87 -0
  67. package/src/sksg/Recorder/Player.ts +62 -7
  68. package/src/sksg/Recorder/ReanimatedRecorder.ts +8 -2
  69. package/src/sksg/Recorder/Recorder.ts +7 -2
  70. package/src/sksg/Recorder/Visitor.ts +18 -6
  71. package/src/views/SkiaPictureView.tsx +7 -1
@@ -1,5 +1,7 @@
1
1
  #pragma once
2
2
 
3
+ #include <algorithm>
4
+ #include <cmath>
3
5
  #include <memory>
4
6
  #include <optional>
5
7
  #include <string>
@@ -22,20 +24,85 @@ namespace RNSkia {
22
24
 
23
25
  class Recorder {
24
26
  private:
25
- std::vector<std::unique_ptr<Command>> commands;
27
+ using CommandList = std::vector<std::unique_ptr<Command>>;
28
+
29
+ struct PendingGroup {
30
+ GroupCommand *group;
31
+ float zIndex;
32
+ int order;
33
+ };
34
+
35
+ CommandList commands;
36
+ std::vector<CommandList *> commandStack;
37
+
38
+ CommandList &currentCommands() { return *commandStack.back(); }
39
+
40
+ void pushCommand(std::unique_ptr<Command> command) {
41
+ currentCommands().push_back(std::move(command));
42
+ }
43
+
44
+ static float sanitizeZIndex(const GroupCommand *group) {
45
+ if (!group || !group->zIndex.has_value()) {
46
+ return 0.0f;
47
+ }
48
+ const auto value = group->zIndex.value();
49
+ if (!std::isfinite(value)) {
50
+ return 0.0f;
51
+ }
52
+ return value;
53
+ }
54
+
55
+ void flushPendingGroups(DrawingCtx *ctx,
56
+ std::vector<PendingGroup> &pendingGroups) {
57
+ if (pendingGroups.empty()) {
58
+ return;
59
+ }
60
+ std::sort(pendingGroups.begin(), pendingGroups.end(),
61
+ [](const PendingGroup &a, const PendingGroup &b) {
62
+ if (a.zIndex == b.zIndex) {
63
+ return a.order < b.order;
64
+ }
65
+ return a.zIndex < b.zIndex;
66
+ });
67
+ for (const auto &pending : pendingGroups) {
68
+ playGroup(ctx, pending.group);
69
+ }
70
+ pendingGroups.clear();
71
+ }
72
+
73
+ void playGroup(DrawingCtx *ctx, GroupCommand *group) {
74
+ if (group == nullptr) {
75
+ return;
76
+ }
77
+ std::vector<PendingGroup> pending;
78
+ for (const auto &child : group->children) {
79
+ if (child->type == CommandType::Group) {
80
+ auto *childGroup = static_cast<GroupCommand *>(child.get());
81
+ pending.push_back(
82
+ {childGroup, sanitizeZIndex(childGroup), static_cast<int>(pending.size())});
83
+ } else {
84
+ flushPendingGroups(ctx, pending);
85
+ playCommand(ctx, child.get());
86
+ }
87
+ }
88
+ flushPendingGroups(ctx, pending);
89
+ }
90
+
91
+ void playCommand(DrawingCtx *ctx, Command *cmd);
26
92
 
27
93
  public:
28
94
  std::shared_ptr<RNSkPlatformContext> _context;
29
95
  Variables variables;
30
96
 
31
- Recorder() = default;
97
+ Recorder() {
98
+ commandStack.push_back(&commands);
99
+ }
32
100
  ~Recorder() {
33
101
  if (!_context || commands.empty()) {
34
102
  return;
35
103
  }
36
104
 
37
105
  auto context = _context;
38
- using CommandList = std::vector<std::unique_ptr<Command>>;
39
106
  auto pendingCommands = std::make_shared<CommandList>(std::move(commands));
40
107
 
41
108
  context->runOnMainThread(
@@ -48,42 +115,42 @@ public:
48
115
 
49
116
  void savePaint(jsi::Runtime &runtime, const jsi::Object &props,
50
117
  bool standalone) {
51
- commands.push_back(
118
+ pushCommand(
52
119
  std::make_unique<SavePaintCmd>(runtime, props, variables, standalone));
53
120
  }
54
121
 
55
122
  void pushShader(jsi::Runtime &runtime, const std::string &nodeType,
56
123
  const jsi::Object &props, int children) {
57
124
  if (nodeType == "skShader") {
58
- commands.push_back(
125
+ pushCommand(
59
126
  std::make_unique<PushShaderCmd>(runtime, props, variables, children));
60
127
  } else if (nodeType == "skImageShader") {
61
- commands.push_back(
128
+ pushCommand(
62
129
  std::make_unique<PushImageShaderCmd>(runtime, props, variables));
63
130
  } else if (nodeType == "skColorShader") {
64
- commands.push_back(
131
+ pushCommand(
65
132
  std::make_unique<ColorShaderCmd>(runtime, props, variables));
66
133
  } else if (nodeType == "skTurbulence") {
67
- commands.push_back(
134
+ pushCommand(
68
135
  std::make_unique<TurbulenceCmd>(runtime, props, variables));
69
136
  } else if (nodeType == "skFractalNoise") {
70
- commands.push_back(
137
+ pushCommand(
71
138
  std::make_unique<FractalNoiseCmd>(runtime, props, variables));
72
139
  } else if (nodeType == "skLinearGradient") {
73
- commands.push_back(
140
+ pushCommand(
74
141
  std::make_unique<LinearGradientCmd>(runtime, props, variables));
75
142
  } else if (nodeType == "skRadialGradient") {
76
- commands.push_back(
143
+ pushCommand(
77
144
  std::make_unique<RadialGradientCmd>(runtime, props, variables));
78
145
  } else if (nodeType == "skSweepGradient") {
79
- commands.push_back(
146
+ pushCommand(
80
147
  std::make_unique<SweepGradientCmd>(runtime, props, variables));
81
148
  } else if (nodeType == "skTwoPointConicalGradient") {
82
- commands.push_back(std::make_unique<TwoPointConicalGradientCmd>(
149
+ pushCommand(std::make_unique<TwoPointConicalGradientCmd>(
83
150
  runtime, props, variables));
84
151
  // TODO: should receive skBlendShader here
85
152
  } else if (nodeType == "skBlend") {
86
- commands.push_back(
153
+ pushCommand(
87
154
  std::make_unique<BlendShaderCmd>(runtime, props, variables));
88
155
  }
89
156
  }
@@ -91,25 +158,25 @@ public:
91
158
  void pushPathEffect(jsi::Runtime &runtime, const std::string &nodeType,
92
159
  const jsi::Object &props) {
93
160
  if (nodeType == "skDiscretePathEffect") {
94
- commands.push_back(
161
+ pushCommand(
95
162
  std::make_unique<DiscretePathEffectCmd>(runtime, props, variables));
96
163
  } else if (nodeType == "skDashPathEffect") {
97
- commands.push_back(
164
+ pushCommand(
98
165
  std::make_unique<DashPathEffectCmd>(runtime, props, variables));
99
166
  } else if (nodeType == "skPath1DPathEffect") {
100
- commands.push_back(
167
+ pushCommand(
101
168
  std::make_unique<Path1DPathEffectCmd>(runtime, props, variables));
102
169
  } else if (nodeType == "skPath2DPathEffect") {
103
- commands.push_back(
170
+ pushCommand(
104
171
  std::make_unique<Path2DPathEffectCmd>(runtime, props, variables));
105
172
  } else if (nodeType == "skCornerPathEffect") {
106
- commands.push_back(
173
+ pushCommand(
107
174
  std::make_unique<CornerPathEffectCmd>(runtime, props, variables));
108
175
  } else if (nodeType == "skSumPathEffect") {
109
- commands.push_back(
176
+ pushCommand(
110
177
  std::make_unique<SumPathEffectCmd>(runtime, props, variables));
111
178
  } else if (nodeType == "skLine2DPathEffect") {
112
- commands.push_back(
179
+ pushCommand(
113
180
  std::make_unique<Line2DPathEffectCmd>(runtime, props, variables));
114
181
  }
115
182
  }
@@ -117,22 +184,22 @@ public:
117
184
  void pushColorFilter(jsi::Runtime &runtime, const std::string &nodeType,
118
185
  const jsi::Object &props) {
119
186
  if (nodeType == "skMatrixColorFilter") {
120
- commands.push_back(
187
+ pushCommand(
121
188
  std::make_unique<MatrixColorFilterCmd>(runtime, props, variables));
122
189
  } else if (nodeType == "skBlendColorFilter") {
123
- commands.push_back(
190
+ pushCommand(
124
191
  std::make_unique<BlendColorFilterCmd>(runtime, props, variables));
125
192
  } else if (nodeType == "skLinearToSRGBGammaColorFilter") {
126
- commands.push_back(std::make_unique<LinearToSRGBGammaColorFilterCmd>(
193
+ pushCommand(std::make_unique<LinearToSRGBGammaColorFilterCmd>(
127
194
  runtime, props, variables));
128
195
  } else if (nodeType == "skSRGBToLinearGammaColorFilter") {
129
- commands.push_back(std::make_unique<SRGBToLinearGammaColorFilterCmd>(
196
+ pushCommand(std::make_unique<SRGBToLinearGammaColorFilterCmd>(
130
197
  runtime, props, variables));
131
198
  } else if (nodeType == "skLumaColorFilter") {
132
- commands.push_back(
199
+ pushCommand(
133
200
  std::make_unique<LumaColorFilterCmd>(runtime, props, variables));
134
201
  } else if (nodeType == "skLerpColorFilter") {
135
- commands.push_back(
202
+ pushCommand(
136
203
  std::make_unique<LerpColorFilterCmd>(runtime, props, variables));
137
204
  }
138
205
  }
@@ -140,531 +207,524 @@ public:
140
207
  void pushImageFilter(jsi::Runtime &runtime, const std::string &nodeType,
141
208
  const jsi::Object &props) {
142
209
  if (nodeType == "skOffsetImageFilter") {
143
- commands.push_back(
210
+ pushCommand(
144
211
  std::make_unique<OffsetImageFilterCmd>(runtime, props, variables));
145
212
  } else if (nodeType == "skDisplacementMapImageFilter") {
146
- commands.push_back(std::make_unique<DisplacementMapImageFilterCmd>(
213
+ pushCommand(std::make_unique<DisplacementMapImageFilterCmd>(
147
214
  runtime, props, variables));
148
215
  } else if (nodeType == "skBlurImageFilter") {
149
- commands.push_back(
216
+ pushCommand(
150
217
  std::make_unique<BlurImageFilterCmd>(runtime, props, variables));
151
218
  } else if (nodeType == "skDropShadowImageFilter") {
152
- commands.push_back(std::make_unique<DropShadowImageFilterCmd>(
219
+ pushCommand(std::make_unique<DropShadowImageFilterCmd>(
153
220
  runtime, props, variables));
154
221
  } else if (nodeType == "skMorphologyImageFilter") {
155
- commands.push_back(std::make_unique<MorphologyImageFilterCmd>(
222
+ pushCommand(std::make_unique<MorphologyImageFilterCmd>(
156
223
  runtime, props, variables));
157
224
  } else if (nodeType == "skBlendImageFilter") {
158
- commands.push_back(
225
+ pushCommand(
159
226
  std::make_unique<BlendImageFilterCmd>(runtime, props, variables));
160
227
  } else if (nodeType == "skRuntimeShaderImageFilter") {
161
- commands.push_back(std::make_unique<RuntimeShaderImageFilterCmd>(
228
+ pushCommand(std::make_unique<RuntimeShaderImageFilterCmd>(
162
229
  runtime, props, variables));
163
230
  } else if (nodeType == "skImageFilter") {
164
- commands.push_back(
231
+ pushCommand(
165
232
  std::make_unique<ImageFilterCmd>(runtime, props, variables));
166
233
  }
167
234
  }
168
235
 
169
236
  void composePathEffect() {
170
- commands.push_back(
237
+ pushCommand(
171
238
  std::make_unique<Command>(CommandType::ComposePathEffect));
172
239
  }
173
240
 
174
241
  void composeImageFilter() {
175
- commands.push_back(
242
+ pushCommand(
176
243
  std::make_unique<Command>(CommandType::ComposeImageFilter));
177
244
  }
178
245
 
179
246
  void composeColorFilter() {
180
- commands.push_back(
247
+ pushCommand(
181
248
  std::make_unique<Command>(CommandType::ComposeColorFilter));
182
249
  }
183
250
 
184
251
  void pushBlurMaskFilter(jsi::Runtime &runtime, const jsi::Object &props) {
185
- commands.push_back(
252
+ pushCommand(
186
253
  std::make_unique<BlurMaskFilterCmd>(runtime, props, variables));
187
254
  }
188
255
 
189
256
  void saveCTM(jsi::Runtime &runtime, const jsi::Object &props) {
190
- commands.push_back(std::make_unique<SaveCTMCmd>(runtime, props, variables));
257
+ pushCommand(std::make_unique<SaveCTMCmd>(runtime, props, variables));
191
258
  }
192
259
 
193
260
  void restoreCTM() {
194
- commands.push_back(std::make_unique<Command>(CommandType::RestoreCTM));
261
+ pushCommand(std::make_unique<Command>(CommandType::RestoreCTM));
195
262
  }
196
263
 
197
264
  void restorePaint() {
198
- commands.push_back(std::make_unique<Command>(CommandType::RestorePaint));
265
+ pushCommand(std::make_unique<Command>(CommandType::RestorePaint));
199
266
  }
200
267
 
201
268
  void drawRect(jsi::Runtime &runtime, const jsi::Object &props) {
202
- commands.push_back(std::make_unique<RectCmd>(runtime, props, variables));
269
+ pushCommand(std::make_unique<RectCmd>(runtime, props, variables));
203
270
  }
204
271
 
205
272
  void drawCircle(jsi::Runtime &runtime, const jsi::Object &props) {
206
- commands.push_back(std::make_unique<CircleCmd>(runtime, props, variables));
273
+ pushCommand(std::make_unique<CircleCmd>(runtime, props, variables));
207
274
  }
208
275
 
209
276
  void drawLine(jsi::Runtime &runtime, const jsi::Object &props) {
210
- commands.push_back(std::make_unique<LineCmd>(runtime, props, variables));
277
+ pushCommand(std::make_unique<LineCmd>(runtime, props, variables));
211
278
  }
212
279
 
213
280
  void drawTextPath(jsi::Runtime &runtime, const jsi::Object &props) {
214
- commands.push_back(
281
+ pushCommand(
215
282
  std::make_unique<TextPathCmd>(runtime, props, variables));
216
283
  }
217
284
 
218
285
  void drawText(jsi::Runtime &runtime, const jsi::Object &props) {
219
- commands.push_back(std::make_unique<TextCmd>(runtime, props, variables));
286
+ pushCommand(std::make_unique<TextCmd>(runtime, props, variables));
220
287
  }
221
288
 
222
289
  void drawPath(jsi::Runtime &runtime, const jsi::Object &props) {
223
- commands.push_back(std::make_unique<PathCmd>(runtime, props, variables));
290
+ pushCommand(std::make_unique<PathCmd>(runtime, props, variables));
224
291
  }
225
292
 
226
293
  void drawPaint() {
227
- commands.push_back(std::make_unique<Command>(CommandType::DrawPaint));
294
+ pushCommand(std::make_unique<Command>(CommandType::DrawPaint));
228
295
  }
229
296
 
230
297
  void drawBox(jsi::Runtime &runtime, const jsi::Object &props,
231
298
  const jsi::Array &shadows) {
232
- commands.push_back(
299
+ pushCommand(
233
300
  std::make_unique<BoxCmd>(runtime, props, shadows, variables));
234
301
  }
235
302
 
236
303
  void drawImage(jsi::Runtime &runtime, const jsi::Object &props) {
237
- commands.push_back(
304
+ pushCommand(
238
305
  std::make_unique<ImageCmd>(_context, runtime, props, variables));
239
306
  }
240
307
 
241
308
  void drawPoints(jsi::Runtime &runtime, const jsi::Object &props) {
242
- commands.push_back(std::make_unique<PointsCmd>(runtime, props, variables));
309
+ pushCommand(std::make_unique<PointsCmd>(runtime, props, variables));
243
310
  }
244
311
 
245
312
  void drawRRect(jsi::Runtime &runtime, const jsi::Object &props) {
246
- commands.push_back(std::make_unique<RRectCmd>(runtime, props, variables));
313
+ pushCommand(std::make_unique<RRectCmd>(runtime, props, variables));
247
314
  }
248
315
 
249
316
  void drawOval(jsi::Runtime &runtime, const jsi::Object &props) {
250
- commands.push_back(std::make_unique<OvalCmd>(runtime, props, variables));
317
+ pushCommand(std::make_unique<OvalCmd>(runtime, props, variables));
251
318
  }
252
319
 
253
320
  void drawPatch(jsi::Runtime &runtime, const jsi::Object &props) {
254
- commands.push_back(std::make_unique<PatchCmd>(runtime, props, variables));
321
+ pushCommand(std::make_unique<PatchCmd>(runtime, props, variables));
255
322
  }
256
323
 
257
324
  void drawVertices(jsi::Runtime &runtime, const jsi::Object &props) {
258
- commands.push_back(
325
+ pushCommand(
259
326
  std::make_unique<VerticesCmd>(runtime, props, variables));
260
327
  }
261
328
 
262
329
  void drawDiffRect(jsi::Runtime &runtime, const jsi::Object &props) {
263
- commands.push_back(
330
+ pushCommand(
264
331
  std::make_unique<DiffRectCmd>(runtime, props, variables));
265
332
  }
266
333
 
267
334
  void drawTextBlob(jsi::Runtime &runtime, const jsi::Object &props) {
268
- commands.push_back(
335
+ pushCommand(
269
336
  std::make_unique<TextBlobCmd>(runtime, props, variables));
270
337
  }
271
338
 
272
339
  void drawGlyphs(jsi::Runtime &runtime, const jsi::Object &props) {
273
- commands.push_back(std::make_unique<GlyphsCmd>(runtime, props, variables));
340
+ pushCommand(std::make_unique<GlyphsCmd>(runtime, props, variables));
274
341
  }
275
342
 
276
343
  void drawPicture(jsi::Runtime &runtime, const jsi::Object &props) {
277
- commands.push_back(
344
+ pushCommand(
278
345
  std::make_unique<PictureCmd>(_context, runtime, props, variables));
279
346
  }
280
347
 
281
348
  void drawImageSVG(jsi::Runtime &runtime, const jsi::Object &props) {
282
- commands.push_back(
349
+ pushCommand(
283
350
  std::make_unique<ImageSVGCmd>(runtime, props, variables));
284
351
  }
285
352
 
286
353
  void drawParagraph(jsi::Runtime &runtime, const jsi::Object &props) {
287
- commands.push_back(
354
+ pushCommand(
288
355
  std::make_unique<ParagraphCmd>(runtime, props, variables));
289
356
  }
290
357
 
291
358
  void drawAtlas(jsi::Runtime &runtime, const jsi::Object &props) {
292
- commands.push_back(
359
+ pushCommand(
293
360
  std::make_unique<AtlasCmd>(_context, runtime, props, variables));
294
361
  }
295
362
 
296
363
  void drawSkottie(jsi::Runtime &runtime, const jsi::Object &props) {
297
- commands.push_back(std::make_unique<SkottieCmd>(runtime, props, variables));
364
+ pushCommand(std::make_unique<SkottieCmd>(runtime, props, variables));
298
365
  }
299
366
 
300
367
  void materializePaint() {
301
- commands.push_back(
368
+ pushCommand(
302
369
  std::make_unique<Command>(CommandType::MaterializePaint));
303
370
  }
304
371
 
305
372
  void restorePaintDeclaration() {
306
- commands.push_back(
373
+ pushCommand(
307
374
  std::make_unique<Command>(CommandType::RestorePaintDeclaration));
308
375
  }
309
376
 
310
377
  void saveLayer() {
311
- commands.push_back(std::make_unique<Command>(CommandType::SaveLayer));
378
+ pushCommand(std::make_unique<Command>(CommandType::SaveLayer));
312
379
  }
313
380
 
314
381
  void saveBackdropFilter() {
315
- commands.push_back(
382
+ pushCommand(
316
383
  std::make_unique<Command>(CommandType::SaveBackdropFilter));
317
384
  }
318
385
 
319
- void saveGroup() {}
386
+ void saveGroup(jsi::Runtime &runtime, const jsi::Value *propsValue = nullptr) {
387
+ auto group = std::make_unique<GroupCommand>();
388
+ if (propsValue != nullptr && propsValue->isObject()) {
389
+ auto object = propsValue->asObject(runtime);
390
+ convertProperty(runtime, object, "zIndex", group->zIndex, variables);
391
+ }
392
+ auto *children = &group->children;
393
+ pushCommand(std::move(group));
394
+ commandStack.push_back(children);
395
+ }
396
+
397
+ void restoreGroup() {
398
+ if (commandStack.size() > 1) {
399
+ commandStack.pop_back();
400
+ }
401
+ }
320
402
 
321
- void restoreGroup() {}
322
403
 
323
404
  void play(DrawingCtx *ctx) {
324
405
  for (const auto &cmd : commands) {
325
- switch (cmd->type) {
406
+ playCommand(ctx, cmd.get());
407
+ }
408
+ }
409
+ };
326
410
 
327
- case Group: {
328
- // Do nothing here for now
411
+ inline void Recorder::playCommand(DrawingCtx *ctx, Command *cmd) {
412
+ switch (cmd->type) {
413
+ case CommandType::Group: {
414
+ auto *group = static_cast<GroupCommand *>(cmd);
415
+ playGroup(ctx, group);
416
+ break;
417
+ }
418
+ case CommandType::ComposeColorFilter: {
419
+ ctx->composeColorFilter();
420
+ break;
421
+ }
422
+ case CommandType::ComposeImageFilter: {
423
+ ctx->composeImageFilter();
424
+ break;
425
+ }
426
+ case CommandType::ComposePathEffect: {
427
+ ctx->composePathEffect();
428
+ break;
429
+ }
430
+ case CommandType::RestorePaintDeclaration: {
431
+ ctx->materializePaint();
432
+ auto paint = ctx->restorePaint();
433
+ ctx->paintDeclarations.push_back(paint);
434
+ break;
435
+ }
436
+ case CommandType::SaveBackdropFilter: {
437
+ ctx->saveBackdropFilter();
438
+ break;
439
+ }
440
+ case CommandType::SaveLayer: {
441
+ ctx->materializePaint();
442
+ auto paint = ctx->paintDeclarations.back();
443
+ ctx->paintDeclarations.pop_back();
444
+ ctx->canvas->saveLayer(SkCanvas::SaveLayerRec(nullptr, &paint, nullptr, 0));
445
+ break;
446
+ }
447
+ case CommandType::MaterializePaint: {
448
+ ctx->materializePaint();
449
+ break;
450
+ }
451
+ case CommandType::SavePaint: {
452
+ auto *savePaintCmd = static_cast<SavePaintCmd *>(cmd);
453
+ savePaintCmd->savePaint(ctx);
454
+ break;
455
+ }
456
+ case CommandType::PushShader: {
457
+ auto nodeType = cmd->nodeType;
458
+ if (nodeType == "skShader") {
459
+ auto *pushShaderCmd = static_cast<PushShaderCmd *>(cmd);
460
+ pushShaderCmd->pushShader(ctx);
461
+ } else if (nodeType == "skImageShader") {
462
+ auto *pushImageShaderCmd = static_cast<PushImageShaderCmd *>(cmd);
463
+ pushImageShaderCmd->pushShader(ctx);
464
+ } else if (nodeType == "skColorShader") {
465
+ auto *colorShaderCmd = static_cast<ColorShaderCmd *>(cmd);
466
+ colorShaderCmd->pushShader(ctx);
467
+ } else if (nodeType == "skTurbulence") {
468
+ auto *turbulenceCmd = static_cast<TurbulenceCmd *>(cmd);
469
+ turbulenceCmd->pushShader(ctx);
470
+ } else if (nodeType == "skFractalNoise") {
471
+ auto *fractalNoiseCmd = static_cast<FractalNoiseCmd *>(cmd);
472
+ fractalNoiseCmd->pushShader(ctx);
473
+ } else if (nodeType == "skLinearGradient") {
474
+ auto *linearGradientCmd = static_cast<LinearGradientCmd *>(cmd);
475
+ linearGradientCmd->pushShader(ctx);
476
+ } else if (nodeType == "skRadialGradient") {
477
+ auto *radialGradientCmd = static_cast<RadialGradientCmd *>(cmd);
478
+ radialGradientCmd->pushShader(ctx);
479
+ } else if (nodeType == "skSweepGradient") {
480
+ auto *sweepGradientCmd = static_cast<SweepGradientCmd *>(cmd);
481
+ sweepGradientCmd->pushShader(ctx);
482
+ } else if (nodeType == "skTwoPointConicalGradient") {
483
+ auto *twoPointConicalGradientCmd =
484
+ static_cast<TwoPointConicalGradientCmd *>(cmd);
485
+ twoPointConicalGradientCmd->pushShader(ctx);
486
+ } else if (nodeType == "skBlendShader") {
487
+ auto *blendShaderCmd = static_cast<BlendShaderCmd *>(cmd);
488
+ blendShaderCmd->pushShader(ctx);
489
+ } else {
490
+ throw std::runtime_error("Invalid shader type: " + nodeType);
491
+ }
492
+ break;
493
+ }
494
+ case CommandType::PushImageFilter: {
495
+ auto nodeType = cmd->nodeType;
496
+ if (nodeType == "skOffsetImageFilter") {
497
+ auto *offsetCmd = static_cast<OffsetImageFilterCmd *>(cmd);
498
+ offsetCmd->pushImageFilter(ctx);
499
+ } else if (nodeType == "skDisplacementMapImageFilter") {
500
+ auto *displacementCmd =
501
+ static_cast<DisplacementMapImageFilterCmd *>(cmd);
502
+ displacementCmd->pushImageFilter(ctx);
503
+ } else if (nodeType == "skBlurImageFilter") {
504
+ auto *blurCmd = static_cast<BlurImageFilterCmd *>(cmd);
505
+ blurCmd->pushImageFilter(ctx);
506
+ } else if (nodeType == "skDropShadowImageFilter") {
507
+ auto *dropShadowCmd = static_cast<DropShadowImageFilterCmd *>(cmd);
508
+ dropShadowCmd->pushImageFilter(ctx);
509
+ } else if (nodeType == "skMorphologyImageFilter") {
510
+ auto *morphologyCmd = static_cast<MorphologyImageFilterCmd *>(cmd);
511
+ morphologyCmd->pushImageFilter(ctx);
512
+ } else if (nodeType == "skBlendImageFilter") {
513
+ auto *blendCmd = static_cast<BlendImageFilterCmd *>(cmd);
514
+ blendCmd->pushImageFilter(ctx);
515
+ } else if (nodeType == "skRuntimeShaderImageFilter") {
516
+ auto *runtimeShaderCmd =
517
+ static_cast<RuntimeShaderImageFilterCmd *>(cmd);
518
+ runtimeShaderCmd->pushImageFilter(ctx);
519
+ } else if (nodeType == "skImageFilter") {
520
+ auto *imageFilterCmd = static_cast<ImageFilterCmd *>(cmd);
521
+ imageFilterCmd->pushImageFilter(ctx);
522
+ } else {
523
+ throw std::runtime_error("Invalid image filter type: " + nodeType);
524
+ }
525
+ break;
526
+ }
527
+ case CommandType::PushPathEffect: {
528
+ auto nodeType = cmd->nodeType;
529
+ if (nodeType == "skDiscretePathEffect") {
530
+ auto *discreteCmd = static_cast<DiscretePathEffectCmd *>(cmd);
531
+ discreteCmd->pushPathEffect(ctx);
532
+ } else if (nodeType == "skDashPathEffect") {
533
+ auto *dashCmd = static_cast<DashPathEffectCmd *>(cmd);
534
+ dashCmd->pushPathEffect(ctx);
535
+ } else if (nodeType == "skPath1DPathEffect") {
536
+ auto *path1DCmd = static_cast<Path1DPathEffectCmd *>(cmd);
537
+ path1DCmd->pushPathEffect(ctx);
538
+ } else if (nodeType == "skPath2DPathEffect") {
539
+ auto *path2DCmd = static_cast<Path2DPathEffectCmd *>(cmd);
540
+ path2DCmd->pushPathEffect(ctx);
541
+ } else if (nodeType == "skCornerPathEffect") {
542
+ auto *cornerCmd = static_cast<CornerPathEffectCmd *>(cmd);
543
+ cornerCmd->pushPathEffect(ctx);
544
+ } else if (nodeType == "skSumPathEffect") {
545
+ auto *sumCmd = static_cast<SumPathEffectCmd *>(cmd);
546
+ sumCmd->pushPathEffect(ctx);
547
+ } else if (nodeType == "skLine2DPathEffect") {
548
+ auto *line2DCmd = static_cast<Line2DPathEffectCmd *>(cmd);
549
+ line2DCmd->pushPathEffect(ctx);
550
+ } else {
551
+ throw std::runtime_error("Invalid path effect type: " + nodeType);
552
+ }
553
+ break;
554
+ }
555
+ case CommandType::PushColorFilter: {
556
+ auto nodeType = cmd->nodeType;
557
+ if (nodeType == "skMatrixColorFilter") {
558
+ auto *matrixCmd = static_cast<MatrixColorFilterCmd *>(cmd);
559
+ matrixCmd->pushColorFilter(ctx);
560
+ } else if (nodeType == "skBlendColorFilter") {
561
+ auto *blendCmd = static_cast<BlendColorFilterCmd *>(cmd);
562
+ blendCmd->pushColorFilter(ctx);
563
+ } else if (nodeType == "skLinearToSRGBGammaColorFilter") {
564
+ auto *linearToSRGBCmd =
565
+ static_cast<LinearToSRGBGammaColorFilterCmd *>(cmd);
566
+ linearToSRGBCmd->pushColorFilter(ctx);
567
+ } else if (nodeType == "skSRGBToLinearGammaColorFilter") {
568
+ auto *srgbToLinearCmd =
569
+ static_cast<SRGBToLinearGammaColorFilterCmd *>(cmd);
570
+ srgbToLinearCmd->pushColorFilter(ctx);
571
+ } else if (nodeType == "skLumaColorFilter") {
572
+ auto *lumaCmd = static_cast<LumaColorFilterCmd *>(cmd);
573
+ lumaCmd->pushColorFilter(ctx);
574
+ } else if (nodeType == "skLerpColorFilter") {
575
+ auto *lerpCmd = static_cast<LerpColorFilterCmd *>(cmd);
576
+ lerpCmd->pushColorFilter(ctx);
577
+ } else {
578
+ throw std::runtime_error("Invalid color filter type: " + nodeType);
579
+ }
580
+ break;
581
+ }
582
+ case CommandType::PushBlurMaskFilter: {
583
+ auto *blurMaskFilterCmd = static_cast<BlurMaskFilterCmd *>(cmd);
584
+ blurMaskFilterCmd->pushMaskFilter(ctx);
585
+ break;
586
+ }
587
+ case CommandType::RestorePaint: {
588
+ ctx->restorePaint();
589
+ break;
590
+ }
591
+ case CommandType::SaveCTM: {
592
+ auto *saveCTMCmd = static_cast<SaveCTMCmd *>(cmd);
593
+ saveCTMCmd->saveCTM(ctx);
594
+ break;
595
+ }
596
+ case CommandType::RestoreCTM: {
597
+ ctx->canvas->restore();
598
+ break;
599
+ }
600
+ default: {
601
+ auto currentPaints = ctx->paintDeclarations;
602
+ SkPaint paint(ctx->getPaint());
603
+ paint.setAlphaf(paint.getAlphaf() * ctx->getOpacity());
604
+ currentPaints.push_back(paint);
605
+ ctx->paintDeclarations.clear();
606
+
607
+ for (auto &layerPaint : currentPaints) {
608
+ ctx->pushPaint(layerPaint);
609
+
610
+ switch (cmd->type) {
611
+ case CommandType::DrawPaint:
612
+ ctx->canvas->drawPaint(layerPaint);
613
+ break;
614
+ case CommandType::DrawCircle: {
615
+ auto *circleCmd = static_cast<CircleCmd *>(cmd);
616
+ circleCmd->draw(ctx);
329
617
  break;
330
618
  }
331
-
332
- case CommandType::ComposeColorFilter: {
333
- ctx->composeColorFilter();
619
+ case CommandType::DrawPath: {
620
+ auto *pathCmd = static_cast<PathCmd *>(cmd);
621
+ pathCmd->draw(ctx);
334
622
  break;
335
623
  }
336
-
337
- case CommandType::ComposeImageFilter: {
338
- ctx->composeImageFilter();
624
+ case CommandType::DrawRect: {
625
+ auto *rectCmd = static_cast<RectCmd *>(cmd);
626
+ rectCmd->draw(ctx);
339
627
  break;
340
628
  }
341
-
342
- case CommandType::ComposePathEffect: {
343
- ctx->composePathEffect();
629
+ case CommandType::DrawLine: {
630
+ auto *lineCmd = static_cast<LineCmd *>(cmd);
631
+ lineCmd->draw(ctx);
344
632
  break;
345
633
  }
346
-
347
- case CommandType::RestorePaintDeclaration: {
348
- ctx->materializePaint();
349
- auto paint = ctx->restorePaint();
350
- ctx->paintDeclarations.push_back(paint);
634
+ case CommandType::DrawTextPath: {
635
+ auto *textPathCmd = static_cast<TextPathCmd *>(cmd);
636
+ textPathCmd->draw(ctx);
351
637
  break;
352
638
  }
353
-
354
- case CommandType::SaveBackdropFilter: {
355
- ctx->saveBackdropFilter();
639
+ case CommandType::DrawText: {
640
+ auto *textCmd = static_cast<TextCmd *>(cmd);
641
+ textCmd->draw(ctx);
356
642
  break;
357
643
  }
358
-
359
- case CommandType::SaveLayer: {
360
- ctx->materializePaint();
361
- auto paint = ctx->paintDeclarations.back();
362
- ctx->paintDeclarations.pop_back();
363
- ctx->canvas->saveLayer(
364
- SkCanvas::SaveLayerRec(nullptr, &paint, nullptr, 0));
644
+ case CommandType::DrawBox: {
645
+ auto *boxCmd = static_cast<BoxCmd *>(cmd);
646
+ boxCmd->draw(ctx);
365
647
  break;
366
648
  }
367
-
368
- case CommandType::MaterializePaint: {
369
- ctx->materializePaint();
649
+ case CommandType::DrawImage: {
650
+ auto *imageCmd = static_cast<ImageCmd *>(cmd);
651
+ imageCmd->draw(ctx);
370
652
  break;
371
653
  }
372
-
373
- case CommandType::SavePaint: {
374
- auto *savePaintCmd = static_cast<SavePaintCmd *>(cmd.get());
375
- savePaintCmd->savePaint(ctx);
654
+ case CommandType::DrawPoints: {
655
+ auto *pointsCmd = static_cast<PointsCmd *>(cmd);
656
+ pointsCmd->draw(ctx);
376
657
  break;
377
658
  }
378
-
379
- case CommandType::PushShader: {
380
- auto nodeType = cmd->nodeType;
381
- if (nodeType == "skShader") {
382
- auto *pushShaderCmd = static_cast<PushShaderCmd *>(cmd.get());
383
- pushShaderCmd->pushShader(ctx);
384
- } else if (nodeType == "skImageShader") {
385
- auto *pushImageShaderCmd =
386
- static_cast<PushImageShaderCmd *>(cmd.get());
387
- pushImageShaderCmd->pushShader(ctx);
388
- } else if (nodeType == "skColorShader") {
389
- auto *colorShaderCmd = static_cast<ColorShaderCmd *>(cmd.get());
390
- colorShaderCmd->pushShader(ctx);
391
- } else if (nodeType == "skTurbulence") {
392
- auto *turbulenceCmd = static_cast<TurbulenceCmd *>(cmd.get());
393
- turbulenceCmd->pushShader(ctx);
394
- } else if (nodeType == "skFractalNoise") {
395
- auto *fractalNoiseCmd = static_cast<FractalNoiseCmd *>(cmd.get());
396
- fractalNoiseCmd->pushShader(ctx);
397
- } else if (nodeType == "skLinearGradient") {
398
- auto *linearGradientCmd = static_cast<LinearGradientCmd *>(cmd.get());
399
- linearGradientCmd->pushShader(ctx);
400
- } else if (nodeType == "skRadialGradient") {
401
- auto *radialGradientCmd = static_cast<RadialGradientCmd *>(cmd.get());
402
- radialGradientCmd->pushShader(ctx);
403
- } else if (nodeType == "skSweepGradient") {
404
- auto *sweepGradientCmd = static_cast<SweepGradientCmd *>(cmd.get());
405
- sweepGradientCmd->pushShader(ctx);
406
- } else if (nodeType == "skTwoPointConicalGradient") {
407
- auto *twoPointConicalGradientCmd =
408
- static_cast<TwoPointConicalGradientCmd *>(cmd.get());
409
- twoPointConicalGradientCmd->pushShader(ctx);
410
- } else if (nodeType == "skBlendShader") {
411
- auto *blendShaderCmd = static_cast<BlendShaderCmd *>(cmd.get());
412
- blendShaderCmd->pushShader(ctx);
413
- } else {
414
- throw std::runtime_error("Invalid shader type: " + nodeType);
415
- }
659
+ case CommandType::DrawRRect: {
660
+ auto *rRectCmd = static_cast<RRectCmd *>(cmd);
661
+ rRectCmd->draw(ctx);
416
662
  break;
417
663
  }
418
-
419
- case CommandType::PushImageFilter: {
420
- auto nodeType = cmd->nodeType;
421
- if (nodeType == "skOffsetImageFilter") {
422
- auto *offsetCmd = static_cast<OffsetImageFilterCmd *>(cmd.get());
423
- offsetCmd->pushImageFilter(ctx);
424
- } else if (nodeType == "skDisplacementMapImageFilter") {
425
- auto *displacementCmd =
426
- static_cast<DisplacementMapImageFilterCmd *>(cmd.get());
427
- displacementCmd->pushImageFilter(ctx);
428
- } else if (nodeType == "skBlurImageFilter") {
429
- auto *blurCmd = static_cast<BlurImageFilterCmd *>(cmd.get());
430
- blurCmd->pushImageFilter(ctx);
431
- } else if (nodeType == "skDropShadowImageFilter") {
432
- auto *dropShadowCmd =
433
- static_cast<DropShadowImageFilterCmd *>(cmd.get());
434
- dropShadowCmd->pushImageFilter(ctx);
435
- } else if (nodeType == "skMorphologyImageFilter") {
436
- auto *morphologyCmd =
437
- static_cast<MorphologyImageFilterCmd *>(cmd.get());
438
- morphologyCmd->pushImageFilter(ctx);
439
- } else if (nodeType == "skBlendImageFilter") {
440
- auto *blendCmd = static_cast<BlendImageFilterCmd *>(cmd.get());
441
- blendCmd->pushImageFilter(ctx);
442
- } else if (nodeType == "skRuntimeShaderImageFilter") {
443
- auto *runtimeShaderCmd =
444
- static_cast<RuntimeShaderImageFilterCmd *>(cmd.get());
445
- runtimeShaderCmd->pushImageFilter(ctx);
446
- } else if (nodeType == "skImageFilter") {
447
- auto *imageFilterCmd = static_cast<ImageFilterCmd *>(cmd.get());
448
- imageFilterCmd->pushImageFilter(ctx);
449
- } else {
450
- throw std::runtime_error("Invalid image filter type: " + nodeType);
451
- }
664
+ case CommandType::DrawOval: {
665
+ auto *ovalCmd = static_cast<OvalCmd *>(cmd);
666
+ ovalCmd->draw(ctx);
452
667
  break;
453
668
  }
454
-
455
- case CommandType::PushPathEffect: {
456
- auto nodeType = cmd->nodeType;
457
- if (nodeType == "skDiscretePathEffect") {
458
- auto *discreteCmd = static_cast<DiscretePathEffectCmd *>(cmd.get());
459
- discreteCmd->pushPathEffect(ctx);
460
- } else if (nodeType == "skDashPathEffect") {
461
- auto *dashCmd = static_cast<DashPathEffectCmd *>(cmd.get());
462
- dashCmd->pushPathEffect(ctx);
463
- } else if (nodeType == "skPath1DPathEffect") {
464
- auto *path1DCmd = static_cast<Path1DPathEffectCmd *>(cmd.get());
465
- path1DCmd->pushPathEffect(ctx);
466
- } else if (nodeType == "skPath2DPathEffect") {
467
- auto *path2DCmd = static_cast<Path2DPathEffectCmd *>(cmd.get());
468
- path2DCmd->pushPathEffect(ctx);
469
- } else if (nodeType == "skCornerPathEffect") {
470
- auto *cornerCmd = static_cast<CornerPathEffectCmd *>(cmd.get());
471
- cornerCmd->pushPathEffect(ctx);
472
- } else if (nodeType == "skSumPathEffect") {
473
- auto *sumCmd = static_cast<SumPathEffectCmd *>(cmd.get());
474
- sumCmd->pushPathEffect(ctx);
475
- } else if (nodeType == "skLine2DPathEffect") {
476
- auto *line2DCmd = static_cast<Line2DPathEffectCmd *>(cmd.get());
477
- line2DCmd->pushPathEffect(ctx);
478
- } else {
479
- throw std::runtime_error("Invalid path effect type: " + nodeType);
480
- }
669
+ case CommandType::DrawPatch: {
670
+ auto *patchCmd = static_cast<PatchCmd *>(cmd);
671
+ patchCmd->draw(ctx);
481
672
  break;
482
673
  }
483
-
484
- case CommandType::PushColorFilter: {
485
- auto nodeType = cmd->nodeType;
486
- if (nodeType == "skMatrixColorFilter") {
487
- auto *matrixCmd = static_cast<MatrixColorFilterCmd *>(cmd.get());
488
- matrixCmd->pushColorFilter(ctx);
489
- } else if (nodeType == "skBlendColorFilter") {
490
- auto *blendCmd = static_cast<BlendColorFilterCmd *>(cmd.get());
491
- blendCmd->pushColorFilter(ctx);
492
- } else if (nodeType == "skLinearToSRGBGammaColorFilter") {
493
- auto *linearToSRGBCmd =
494
- static_cast<LinearToSRGBGammaColorFilterCmd *>(cmd.get());
495
- linearToSRGBCmd->pushColorFilter(ctx);
496
- } else if (nodeType == "skSRGBToLinearGammaColorFilter") {
497
- auto *srgbToLinearCmd =
498
- static_cast<SRGBToLinearGammaColorFilterCmd *>(cmd.get());
499
- srgbToLinearCmd->pushColorFilter(ctx);
500
- } else if (nodeType == "skLumaColorFilter") {
501
- auto *lumaCmd = static_cast<LumaColorFilterCmd *>(cmd.get());
502
- lumaCmd->pushColorFilter(ctx);
503
- } else if (nodeType == "skLerpColorFilter") {
504
- auto *lerpCmd = static_cast<LerpColorFilterCmd *>(cmd.get());
505
- lerpCmd->pushColorFilter(ctx);
506
- } else {
507
- throw std::runtime_error("Invalid color filter type: " + nodeType);
508
- }
674
+ case CommandType::DrawVertices: {
675
+ auto *verticesCmd = static_cast<VerticesCmd *>(cmd);
676
+ verticesCmd->draw(ctx);
509
677
  break;
510
678
  }
511
-
512
- case CommandType::PushBlurMaskFilter: {
513
- auto *blurMaskFilterCmd = static_cast<BlurMaskFilterCmd *>(cmd.get());
514
- blurMaskFilterCmd->pushMaskFilter(ctx);
679
+ case CommandType::DrawDiffRect: {
680
+ auto *diffRectCmd = static_cast<DiffRectCmd *>(cmd);
681
+ diffRectCmd->draw(ctx);
515
682
  break;
516
683
  }
517
-
518
- case CommandType::RestorePaint: {
519
- ctx->restorePaint();
684
+ case CommandType::DrawTextBlob: {
685
+ auto *textBlobCmd = static_cast<TextBlobCmd *>(cmd);
686
+ textBlobCmd->draw(ctx);
520
687
  break;
521
688
  }
522
-
523
- case CommandType::SaveCTM: {
524
- auto *saveCTMCmd = static_cast<SaveCTMCmd *>(cmd.get());
525
- saveCTMCmd->saveCTM(ctx);
689
+ case CommandType::DrawGlyphs: {
690
+ auto *glyphsCmd = static_cast<GlyphsCmd *>(cmd);
691
+ glyphsCmd->draw(ctx);
526
692
  break;
527
693
  }
528
-
529
- case CommandType::RestoreCTM: {
530
- ctx->canvas->restore();
694
+ case CommandType::DrawPicture: {
695
+ auto *pictureCmd = static_cast<PictureCmd *>(cmd);
696
+ pictureCmd->draw(ctx);
697
+ break;
698
+ }
699
+ case CommandType::DrawImageSVG: {
700
+ auto *imageSVGCmd = static_cast<ImageSVGCmd *>(cmd);
701
+ imageSVGCmd->draw(ctx);
702
+ break;
703
+ }
704
+ case CommandType::DrawParagraph: {
705
+ auto *paragraphCmd = static_cast<ParagraphCmd *>(cmd);
706
+ paragraphCmd->draw(ctx);
531
707
  break;
532
708
  }
533
- default: {
534
- // Handle all drawing commands
535
- auto currentPaints = ctx->paintDeclarations;
536
- // apply alpha to the current paint.
537
- SkPaint paint(ctx->getPaint());
538
- paint.setAlphaf(paint.getAlphaf() * ctx->getOpacity());
539
- currentPaints.push_back(paint);
540
- ctx->paintDeclarations.clear();
541
-
542
- for (auto &paint : currentPaints) {
543
- ctx->pushPaint(paint);
544
-
545
- switch (cmd->type) {
546
- case CommandType::DrawPaint: {
547
- ctx->canvas->drawPaint(paint);
548
- break;
549
- }
550
- case CommandType::DrawCircle: {
551
- auto *circleCmd = static_cast<CircleCmd *>(cmd.get());
552
- circleCmd->draw(ctx);
553
- break;
554
- }
555
- case CommandType::DrawPath: {
556
- auto *pathCmd = static_cast<PathCmd *>(cmd.get());
557
- pathCmd->draw(ctx);
558
- break;
559
- }
560
- case CommandType::DrawRect: {
561
- auto *rectCmd = static_cast<RectCmd *>(cmd.get());
562
- rectCmd->draw(ctx);
563
- break;
564
- }
565
- case CommandType::DrawLine: {
566
- auto *lineCmd = static_cast<LineCmd *>(cmd.get());
567
- lineCmd->draw(ctx);
568
- break;
569
- }
570
- case CommandType::DrawTextPath: {
571
- auto *textPathCmd = static_cast<TextPathCmd *>(cmd.get());
572
- textPathCmd->draw(ctx);
573
- break;
574
- }
575
- case CommandType::DrawText: {
576
- auto *textCmd = static_cast<TextCmd *>(cmd.get());
577
- textCmd->draw(ctx);
578
- break;
579
- }
580
- case CommandType::DrawBox: {
581
- auto *boxCmd = static_cast<BoxCmd *>(cmd.get());
582
- boxCmd->draw(ctx);
583
- break;
584
- }
585
- case CommandType::DrawImage: {
586
- auto *imageCmd = static_cast<ImageCmd *>(cmd.get());
587
- imageCmd->draw(ctx);
588
- break;
589
- }
590
- case CommandType::DrawPoints: {
591
- auto *pointsCmd = static_cast<PointsCmd *>(cmd.get());
592
- pointsCmd->draw(ctx);
593
- break;
594
- }
595
- case CommandType::DrawRRect: {
596
- auto *rRectCmd = static_cast<RRectCmd *>(cmd.get());
597
- rRectCmd->draw(ctx);
598
- break;
599
- }
600
- case CommandType::DrawOval: {
601
- auto *ovalCmd = static_cast<OvalCmd *>(cmd.get());
602
- ovalCmd->draw(ctx);
603
- break;
604
- }
605
- case CommandType::DrawPatch: {
606
- auto *patchCmd = static_cast<PatchCmd *>(cmd.get());
607
- patchCmd->draw(ctx);
608
- break;
609
- }
610
- case CommandType::DrawVertices: {
611
- auto *verticesCmd = static_cast<VerticesCmd *>(cmd.get());
612
- verticesCmd->draw(ctx);
613
- break;
614
- }
615
- case CommandType::DrawDiffRect: {
616
- auto *diffRectCmd = static_cast<DiffRectCmd *>(cmd.get());
617
- diffRectCmd->draw(ctx);
618
- break;
619
- }
620
- case CommandType::DrawTextBlob: {
621
- auto *textBlobCmd = static_cast<TextBlobCmd *>(cmd.get());
622
- textBlobCmd->draw(ctx);
623
- break;
624
- }
625
- case CommandType::DrawGlyphs: {
626
- auto *glyphsCmd = static_cast<GlyphsCmd *>(cmd.get());
627
- glyphsCmd->draw(ctx);
628
- break;
629
- }
630
- case CommandType::DrawPicture: {
631
- auto *pictureCmd = static_cast<PictureCmd *>(cmd.get());
632
- pictureCmd->draw(ctx);
633
- break;
634
- }
635
- case CommandType::DrawImageSVG: {
636
- auto *imageSVGCmd = static_cast<ImageSVGCmd *>(cmd.get());
637
- imageSVGCmd->draw(ctx);
638
- break;
639
- }
640
- case CommandType::DrawParagraph: {
641
- auto *paragraphCmd = static_cast<ParagraphCmd *>(cmd.get());
642
- paragraphCmd->draw(ctx);
643
- break;
644
- }
645
- case CommandType::DrawAtlas: {
646
- auto *atlasCmd = static_cast<AtlasCmd *>(cmd.get());
647
- atlasCmd->draw(ctx);
648
- break;
649
- }
650
- case CommandType::DrawSkottie: {
651
- auto *skottieCmd = static_cast<SkottieCmd *>(cmd.get());
652
- skottieCmd->draw(ctx);
653
- break;
654
- }
655
- default:
656
- // Context commands (Group, SavePaint, RestorePaint, etc.) are not
657
- // handled here
658
- break;
659
- }
660
-
661
- ctx->restorePaint();
662
- }
709
+ case CommandType::DrawAtlas: {
710
+ auto *atlasCmd = static_cast<AtlasCmd *>(cmd);
711
+ atlasCmd->draw(ctx);
663
712
  break;
664
713
  }
714
+ case CommandType::DrawSkottie: {
715
+ auto *skottieCmd = static_cast<SkottieCmd *>(cmd);
716
+ skottieCmd->draw(ctx);
717
+ break;
718
+ }
719
+ default:
720
+ break;
665
721
  }
722
+
723
+ ctx->restorePaint();
666
724
  }
725
+ break;
667
726
  }
668
- };
727
+ }
728
+ }
669
729
 
670
730
  } // namespace RNSkia