@shopify/react-native-skia 2.4.6 → 2.4.14

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 (143) hide show
  1. package/android/cpp/jni/JniPlatformContext.cpp +1 -1
  2. package/android/src/main/java/com/shopify/reactnative/skia/ViewScreenshotService.java +11 -1
  3. package/apple/RNSkApplePlatformContext.h +4 -0
  4. package/apple/RNSkApplePlatformContext.mm +69 -0
  5. package/apple/SkiaCVPixelBufferUtils.mm +8 -4
  6. package/cpp/api/JsiSkFontMgr.h +30 -6
  7. package/cpp/api/JsiSkImageFilterFactory.h +4 -2
  8. package/cpp/api/JsiSkPictureFactory.h +9 -6
  9. package/cpp/api/recorder/RNRecorder.h +33 -55
  10. package/cpp/rnskia/RNSkPictureView.h +7 -5
  11. package/cpp/rnskia/RNSkPlatformContext.h +16 -0
  12. package/cpp/skia/include/codec/SkAndroidCodec.h +3 -2
  13. package/cpp/skia/include/codec/SkAvifDecoder.h +2 -2
  14. package/cpp/skia/include/codec/SkBmpDecoder.h +1 -1
  15. package/cpp/skia/include/codec/SkCodec.h +2 -8
  16. package/cpp/skia/include/codec/SkEncodedOrigin.h +17 -0
  17. package/cpp/skia/include/codec/SkGifDecoder.h +1 -1
  18. package/cpp/skia/include/codec/SkIcoDecoder.h +1 -1
  19. package/cpp/skia/include/codec/SkJpegDecoder.h +8 -1
  20. package/cpp/skia/include/codec/SkJpegxlDecoder.h +1 -1
  21. package/cpp/skia/include/codec/SkPngDecoder.h +8 -1
  22. package/cpp/skia/include/codec/SkRawDecoder.h +1 -1
  23. package/cpp/skia/include/codec/SkWbmpDecoder.h +1 -1
  24. package/cpp/skia/include/codec/SkWebpDecoder.h +8 -1
  25. package/cpp/skia/include/core/SkCPURecorder.h +1 -0
  26. package/cpp/skia/include/core/SkCanvas.h +3 -2
  27. package/cpp/skia/include/core/SkColorTable.h +1 -1
  28. package/cpp/skia/include/core/SkColorType.h +4 -0
  29. package/cpp/skia/include/core/SkDocument.h +1 -1
  30. package/cpp/skia/include/core/SkGraphics.h +7 -2
  31. package/cpp/skia/include/core/SkImage.h +5 -1
  32. package/cpp/skia/include/core/SkImageGenerator.h +5 -3
  33. package/cpp/skia/include/core/SkM44.h +3 -3
  34. package/cpp/skia/include/core/SkMatrix.h +0 -23
  35. package/cpp/skia/include/core/SkMilestone.h +1 -1
  36. package/cpp/skia/include/core/SkOverdrawCanvas.h +1 -1
  37. package/cpp/skia/include/core/SkPath.h +216 -185
  38. package/cpp/skia/include/core/SkPathBuilder.h +97 -47
  39. package/cpp/skia/include/core/SkPathTypes.h +7 -1
  40. package/cpp/skia/include/core/SkPixmap.h +8 -8
  41. package/cpp/skia/include/core/SkRRect.h +24 -3
  42. package/cpp/skia/include/core/SkRecorder.h +3 -1
  43. package/cpp/skia/include/core/SkScalar.h +1 -1
  44. package/cpp/skia/include/core/SkSerialProcs.h +8 -4
  45. package/cpp/skia/include/core/SkStream.h +16 -9
  46. package/cpp/skia/include/core/SkString.h +1 -1
  47. package/cpp/skia/include/core/SkStrokeRec.h +1 -1
  48. package/cpp/skia/include/core/SkYUVAInfo.h +3 -0
  49. package/cpp/skia/include/docs/SkPDFDocument.h +1 -1
  50. package/cpp/skia/include/docs/SkPDFJpegHelpers.h +1 -1
  51. package/cpp/skia/include/docs/SkXPSDocument.h +18 -2
  52. package/cpp/skia/include/effects/SkRuntimeEffect.h +3 -1
  53. package/cpp/skia/include/encode/SkPngRustEncoder.h +18 -0
  54. package/cpp/skia/include/gpu/ganesh/GrBackendSurface.h +1 -1
  55. package/cpp/skia/include/gpu/ganesh/GrExternalTextureGenerator.h +1 -1
  56. package/cpp/skia/include/gpu/ganesh/GrRecordingContext.h +7 -6
  57. package/cpp/skia/include/gpu/ganesh/gl/GrGLBackendSurface.h +6 -0
  58. package/cpp/skia/include/gpu/ganesh/vk/GrBackendDrawableInfo.h +2 -4
  59. package/cpp/skia/include/gpu/graphite/Context.h +15 -1
  60. package/cpp/skia/include/gpu/graphite/ContextOptions.h +52 -11
  61. package/cpp/skia/include/gpu/graphite/GraphiteTypes.h +44 -0
  62. package/cpp/skia/include/gpu/graphite/LogPriority.h +1 -1
  63. package/cpp/skia/include/gpu/graphite/PersistentPipelineStorage.h +45 -0
  64. package/cpp/skia/include/gpu/graphite/PrecompileContext.h +1 -1
  65. package/cpp/skia/include/gpu/graphite/Recorder.h +14 -0
  66. package/cpp/skia/include/gpu/graphite/TextureInfo.h +13 -5
  67. package/cpp/skia/include/gpu/graphite/dawn/DawnGraphiteTypes.h +1 -4
  68. package/cpp/skia/include/gpu/graphite/mtl/MtlGraphiteTypes.h +1 -4
  69. package/cpp/skia/include/gpu/graphite/vk/VulkanGraphiteTypes.h +2 -8
  70. package/cpp/skia/include/gpu/vk/VulkanExtensions.h +1 -1
  71. package/cpp/skia/include/gpu/vk/VulkanTypes.h +124 -9
  72. package/cpp/skia/include/ports/SkFontMgr_fuchsia.h +3 -1
  73. package/cpp/skia/include/ports/SkImageGeneratorCG.h +1 -1
  74. package/cpp/skia/include/ports/SkImageGeneratorNDK.h +1 -1
  75. package/cpp/skia/include/ports/SkImageGeneratorWIC.h +1 -1
  76. package/cpp/skia/include/ports/SkTypeface_fontations.h +1 -1
  77. package/cpp/skia/include/private/SkEncodedInfo.h +38 -29
  78. package/cpp/skia/include/private/SkJpegMetadataDecoder.h +18 -13
  79. package/cpp/skia/include/private/SkPathRef.h +3 -6
  80. package/cpp/skia/include/private/base/SkAlign.h +3 -7
  81. package/cpp/skia/include/private/base/SkContainers.h +1 -1
  82. package/cpp/skia/include/private/base/SkSpan_impl.h +29 -0
  83. package/cpp/skia/include/private/base/SkTArray.h +7 -8
  84. package/cpp/skia/include/private/base/SkTDArray.h +4 -4
  85. package/cpp/skia/include/private/base/SkTemplates.h +5 -5
  86. package/cpp/skia/include/private/chromium/GrDeferredDisplayListRecorder.h +1 -1
  87. package/cpp/skia/include/private/gpu/ganesh/GrContext_Base.h +1 -1
  88. package/cpp/skia/include/private/gpu/ganesh/GrImageContext.h +1 -1
  89. package/cpp/skia/include/private/gpu/ganesh/GrTypesPriv.h +6 -5
  90. package/cpp/skia/include/svg/SkSVGCanvas.h +21 -1
  91. package/cpp/skia/include/utils/SkNoDrawCanvas.h +1 -1
  92. package/cpp/skia/include/utils/SkPaintFilterCanvas.h +1 -1
  93. package/cpp/skia/modules/skcms/src/skcms_public.h +29 -4
  94. package/cpp/skia/modules/skottie/include/Skottie.h +11 -0
  95. package/cpp/skia/modules/skottie/include/SlotManager.h +1 -1
  96. package/cpp/skia/modules/skparagraph/include/Metrics.h +1 -1
  97. package/cpp/skia/modules/skparagraph/include/Paragraph.h +1 -1
  98. package/cpp/skia/modules/sksg/include/SkSGMerge.h +1 -1
  99. package/cpp/skia/modules/sksg/include/SkSGPath.h +1 -1
  100. package/cpp/skia/modules/skshaper/include/SkShaper.h +2 -0
  101. package/cpp/skia/modules/skunicode/include/SkUnicode.h +4 -4
  102. package/cpp/skia/modules/svg/include/SkSVGAttributeParser.h +1 -1
  103. package/cpp/skia/modules/svg/include/SkSVGFeComponentTransfer.h +1 -1
  104. package/cpp/skia/modules/svg/include/SkSVGNode.h +1 -1
  105. package/cpp/skia/modules/svg/include/SkSVGPoly.h +1 -1
  106. package/cpp/skia/modules/svg/include/SkSVGShape.h +1 -1
  107. package/cpp/skia/modules/svg/include/SkSVGTransformableNode.h +1 -1
  108. package/cpp/skia/modules/svg/include/SkSVGValue.h +1 -1
  109. package/lib/commonjs/skia/core/Font.js +7 -1
  110. package/lib/commonjs/skia/core/Font.js.map +1 -1
  111. package/lib/commonjs/skia/web/JsiSkCanvas.d.ts +1 -1
  112. package/lib/commonjs/skia/web/JsiSkCanvas.js +1 -7
  113. package/lib/commonjs/skia/web/JsiSkCanvas.js.map +1 -1
  114. package/lib/commonjs/specs/SkiaPictureViewNativeComponent.web.d.ts +1 -1
  115. package/lib/commonjs/views/SkiaPictureView.web.d.ts +4 -1
  116. package/lib/commonjs/views/SkiaPictureView.web.js +7 -2
  117. package/lib/commonjs/views/SkiaPictureView.web.js.map +1 -1
  118. package/lib/module/skia/core/Font.js +7 -1
  119. package/lib/module/skia/core/Font.js.map +1 -1
  120. package/lib/module/skia/web/JsiSkCanvas.d.ts +1 -1
  121. package/lib/module/skia/web/JsiSkCanvas.js +1 -7
  122. package/lib/module/skia/web/JsiSkCanvas.js.map +1 -1
  123. package/lib/module/specs/SkiaPictureViewNativeComponent.web.d.ts +1 -1
  124. package/lib/module/views/SkiaPictureView.web.d.ts +4 -1
  125. package/lib/module/views/SkiaPictureView.web.js +7 -3
  126. package/lib/module/views/SkiaPictureView.web.js.map +1 -1
  127. package/lib/typescript/lib/commonjs/skia/core/Font.d.ts +1 -1
  128. package/lib/typescript/lib/commonjs/skia/web/JsiSkCanvas.d.ts +1 -1
  129. package/lib/typescript/lib/commonjs/specs/SkiaPictureViewNativeComponent.web.d.ts +1 -11
  130. package/lib/typescript/lib/commonjs/views/SkiaPictureView.web.d.ts +1 -1
  131. package/lib/typescript/lib/module/mock/index.d.ts +1 -1
  132. package/lib/typescript/lib/module/skia/core/Font.d.ts +1 -1
  133. package/lib/typescript/lib/module/skia/web/JsiSkCanvas.d.ts +1 -1
  134. package/lib/typescript/lib/module/specs/SkiaPictureViewNativeComponent.web.d.ts +1 -1
  135. package/lib/typescript/lib/module/views/SkiaPictureView.web.d.ts +1 -1
  136. package/lib/typescript/src/skia/web/JsiSkCanvas.d.ts +1 -1
  137. package/lib/typescript/src/specs/SkiaPictureViewNativeComponent.web.d.ts +1 -1
  138. package/lib/typescript/src/views/SkiaPictureView.web.d.ts +4 -1
  139. package/package.json +8 -8
  140. package/scripts/install-skia.mjs +74 -1
  141. package/src/skia/core/Font.ts +9 -4
  142. package/src/skia/web/JsiSkCanvas.ts +1 -3
  143. package/src/views/SkiaPictureView.web.tsx +8 -7
@@ -207,7 +207,7 @@ void JniPlatformContext::notifyTaskReadyExternal() {
207
207
  jni::ThreadScope ts;
208
208
 
209
209
  static auto method =
210
- javaPart_->getClass()->getMethod<void()>("notifyTaskReady");
210
+ javaPart_->getClass()->getMethod<void()>("notifyTaskReady");
211
211
  method(javaPart_.get());
212
212
  }
213
213
 
@@ -67,6 +67,16 @@ public class ViewScreenshotService {
67
67
  return paint;
68
68
  }
69
69
 
70
+ private static boolean isSvgView(View view) {
71
+ try {
72
+ String className = view.getClass().getName();
73
+ return className != null && className.startsWith("com.horcrux.svg");
74
+ } catch (Throwable t) {
75
+ Log.e("ViewScreenshotService", "Error checking if view is SVG", t);
76
+ return false;
77
+ }
78
+ }
79
+
70
80
  private static void renderViewToCanvas(Canvas canvas, View view, Paint paint, float parentOpacity) {
71
81
  float combinedOpacity = parentOpacity * view.getAlpha();
72
82
  canvas.save();
@@ -83,7 +93,7 @@ public class ViewScreenshotService {
83
93
  canvas.clipRect(clipLeft, clipTop, clipRight, clipBottom);
84
94
  }
85
95
 
86
- if (view instanceof ViewGroup) {
96
+ if (view instanceof ViewGroup && !isSvgView(view)) {
87
97
  ViewGroup group = (ViewGroup) view;
88
98
  drawBackgroundIfPresent(canvas, view, combinedOpacity);
89
99
  drawChildren(canvas, group, paint, combinedOpacity);
@@ -73,6 +73,10 @@ public:
73
73
 
74
74
  sk_sp<SkFontMgr> createFontMgr() override;
75
75
 
76
+ std::vector<std::string> getSystemFontFamilies() override;
77
+
78
+ std::string resolveFontFamily(const std::string &familyName) override;
79
+
76
80
  private:
77
81
  ViewScreenshotService *_screenshotService;
78
82
 
@@ -3,6 +3,7 @@
3
3
  #import <CoreMedia/CMSampleBuffer.h>
4
4
  #include <Metal/Metal.h>
5
5
  #import <React/RCTUtils.h>
6
+ #include <set>
6
7
  #include <thread>
7
8
  #include <utility>
8
9
 
@@ -300,6 +301,74 @@ sk_sp<SkFontMgr> RNSkApplePlatformContext::createFontMgr() {
300
301
  return SkFontMgr_New_CoreText(nullptr);
301
302
  }
302
303
 
304
+ std::vector<std::string> RNSkApplePlatformContext::getSystemFontFamilies() {
305
+ std::vector<std::string> families;
306
+
307
+ // System UI fonts (e.g., .AppleSystemUIFont) are not enumerated by Skia's
308
+ // font manager. We retrieve them via Core Text's CTFontUIFontType constants.
309
+ // This list covers common system font types as of iOS 17 / macOS 14.
310
+ // Apple may add new CTFontUIFontType values in future OS versions,
311
+ // so this list may need to be updated periodically.
312
+ CTFontUIFontType fontTypes[] = {
313
+ kCTFontUIFontUser, kCTFontUIFontUserFixedPitch,
314
+ kCTFontUIFontSystem, kCTFontUIFontEmphasizedSystem,
315
+ kCTFontUIFontSmallSystem, kCTFontUIFontSmallEmphasizedSystem,
316
+ kCTFontUIFontMiniSystem, kCTFontUIFontMiniEmphasizedSystem,
317
+ kCTFontUIFontLabel, kCTFontUIFontMessage,
318
+ kCTFontUIFontToolTip,
319
+ };
320
+
321
+ std::set<std::string> uniqueFamilies;
322
+
323
+ for (CTFontUIFontType fontType : fontTypes) {
324
+ CTFontRef font = CTFontCreateUIFontForLanguage(fontType, 12.0, nullptr);
325
+ if (font) {
326
+ CFStringRef familyName = CTFontCopyFamilyName(font);
327
+ if (familyName) {
328
+ const char *cstr =
329
+ CFStringGetCStringPtr(familyName, kCFStringEncodingUTF8);
330
+ if (cstr) {
331
+ uniqueFamilies.insert(std::string(cstr));
332
+ } else {
333
+ char buffer[256];
334
+ if (CFStringGetCString(familyName, buffer, sizeof(buffer),
335
+ kCFStringEncodingUTF8)) {
336
+ uniqueFamilies.insert(std::string(buffer));
337
+ }
338
+ }
339
+ CFRelease(familyName);
340
+ }
341
+ CFRelease(font);
342
+ }
343
+ }
344
+
345
+ families.assign(uniqueFamilies.begin(), uniqueFamilies.end());
346
+ return families;
347
+ }
348
+
349
+ std::string
350
+ RNSkApplePlatformContext::resolveFontFamily(const std::string &familyName) {
351
+ // Handle special font family names like React Native does
352
+ // See: RCTFont.mm in React Native
353
+ if (familyName == "System" || familyName == "system" ||
354
+ familyName == "sans-serif") {
355
+ return ".AppleSystemUIFont";
356
+ }
357
+ if (familyName == "SystemCondensed" || familyName == "system-condensed") {
358
+ // Return system font - condensed trait is handled via font style
359
+ return ".AppleSystemUIFont";
360
+ }
361
+ // CSS generic font families
362
+ if (familyName == "serif") {
363
+ return "Times New Roman";
364
+ }
365
+ if (familyName == "monospace") {
366
+ return "Courier New";
367
+ }
368
+ // Return as-is if no mapping exists
369
+ return familyName;
370
+ }
371
+
303
372
  void RNSkApplePlatformContext::runOnMainThread(std::function<void()> func) {
304
373
  dispatch_async(dispatch_get_main_queue(), ^{
305
374
  func();
@@ -30,12 +30,16 @@
30
30
  #include <TargetConditionals.h>
31
31
  #if TARGET_RT_BIG_ENDIAN
32
32
  #define FourCC2Str(fourcc) \
33
- (const char[]){*((char *)&fourcc), *(((char *)&fourcc) + 1), \
34
- *(((char *)&fourcc) + 2), *(((char *)&fourcc) + 3), 0}
33
+ (const char[]) { \
34
+ *((char *)&fourcc), *(((char *)&fourcc) + 1), *(((char *)&fourcc) + 2), \
35
+ *(((char *)&fourcc) + 3), 0 \
36
+ }
35
37
  #else
36
38
  #define FourCC2Str(fourcc) \
37
- (const char[]){*(((char *)&fourcc) + 3), *(((char *)&fourcc) + 2), \
38
- *(((char *)&fourcc) + 1), *(((char *)&fourcc) + 0), 0}
39
+ (const char[]) { \
40
+ *(((char *)&fourcc) + 3), *(((char *)&fourcc) + 2), \
41
+ *(((char *)&fourcc) + 1), *(((char *)&fourcc) + 0), 0 \
42
+ }
39
43
  #endif
40
44
 
41
45
  // pragma MARK: TextureHolder
@@ -27,21 +27,42 @@ public:
27
27
 
28
28
  JsiSkFontMgr(std::shared_ptr<RNSkPlatformContext> context,
29
29
  sk_sp<SkFontMgr> fontMgr)
30
- : JsiSkWrappingSkPtrHostObject(std::move(context), fontMgr) {}
30
+ : JsiSkWrappingSkPtrHostObject(context, fontMgr),
31
+ _systemFontFamilies(context->getSystemFontFamilies()) {}
31
32
 
32
- JSI_HOST_FUNCTION(countFamilies) { return getObject()->countFamilies(); }
33
+ JSI_HOST_FUNCTION(countFamilies) {
34
+ return static_cast<int>(getObject()->countFamilies() +
35
+ _systemFontFamilies.size());
36
+ }
33
37
 
34
38
  JSI_HOST_FUNCTION(getFamilyName) {
35
39
  auto i = static_cast<int>(arguments[0].asNumber());
36
- SkString name;
37
- getObject()->getFamilyName(i, &name);
38
- return jsi::String::createFromUtf8(runtime, name.c_str());
40
+ auto baseFamilyCount = getObject()->countFamilies();
41
+ if (i < baseFamilyCount) {
42
+ SkString name;
43
+ getObject()->getFamilyName(i, &name);
44
+ return jsi::String::createFromUtf8(runtime, name.c_str());
45
+ }
46
+ auto systemIndex = i - baseFamilyCount;
47
+ if (systemIndex < static_cast<int>(_systemFontFamilies.size())) {
48
+ return jsi::String::createFromUtf8(runtime,
49
+ _systemFontFamilies[systemIndex]);
50
+ }
51
+ throw jsi::JSError(
52
+ runtime,
53
+ "Font family index out of bounds: " + std::to_string(i) +
54
+ " (total families: " +
55
+ std::to_string(baseFamilyCount + _systemFontFamilies.size()) + ")");
39
56
  }
40
57
 
41
58
  JSI_HOST_FUNCTION(matchFamilyStyle) {
42
59
  auto name = arguments[0].asString(runtime).utf8(runtime);
60
+ // Resolve font family aliases (e.g., "System" -> ".AppleSystemUIFont" on
61
+ // iOS)
62
+ auto resolvedName = getContext()->resolveFontFamily(name);
43
63
  auto fontStyle = JsiSkFontStyle::fromValue(runtime, arguments[1]);
44
- auto typeface = getObject()->matchFamilyStyle(name.c_str(), *fontStyle);
64
+ auto typeface =
65
+ getObject()->matchFamilyStyle(resolvedName.c_str(), *fontStyle);
45
66
  auto hostObjectInstance =
46
67
  std::make_shared<JsiSkTypeface>(getContext(), std::move(typeface));
47
68
  return JSI_CREATE_HOST_OBJECT_WITH_MEMORY_PRESSURE(
@@ -55,6 +76,9 @@ public:
55
76
  JSI_EXPORT_FUNCTIONS(JSI_EXPORT_FUNC(JsiSkFontMgr, countFamilies),
56
77
  JSI_EXPORT_FUNC(JsiSkFontMgr, getFamilyName),
57
78
  JSI_EXPORT_FUNC(JsiSkFontMgr, matchFamilyStyle))
79
+
80
+ private:
81
+ std::vector<std::string> _systemFontFamilies;
58
82
  };
59
83
 
60
84
  } // namespace RNSkia
@@ -245,9 +245,11 @@ public:
245
245
  JSI_HOST_FUNCTION(MakeRuntimeShader) {
246
246
  auto rtb = JsiSkRuntimeShaderBuilder::fromValue(runtime, arguments[0]);
247
247
 
248
- const char *childName = "";
248
+ std::string childNameStr = "";
249
+ const char *childName = childNameStr.c_str();
249
250
  if (hasOptionalArgument(arguments, count, 1)) {
250
- childName = arguments[1].asString(runtime).utf8(runtime).c_str();
251
+ childNameStr = arguments[1].asString(runtime).utf8(runtime);
252
+ childName = childNameStr.c_str();
251
253
  }
252
254
 
253
255
  sk_sp<SkImageFilter> input = nullptr;
@@ -50,12 +50,15 @@ public:
50
50
  }
51
51
  }
52
52
 
53
- // Get ArrayBuffer - try buffer property first (Uint8Array, etc.), then direct ArrayBuffer
54
- jsi::ArrayBuffer buffer = obj.hasProperty(runtime, jsi::PropNameID::forAscii(runtime, "buffer"))
55
- ? obj.getProperty(runtime, jsi::PropNameID::forAscii(runtime, "buffer"))
56
- .asObject(runtime)
57
- .getArrayBuffer(runtime)
58
- : obj.getArrayBuffer(runtime);
53
+ // Get ArrayBuffer - try buffer property first (Uint8Array, etc.), then
54
+ // direct ArrayBuffer
55
+ jsi::ArrayBuffer buffer =
56
+ obj.hasProperty(runtime, jsi::PropNameID::forAscii(runtime, "buffer"))
57
+ ? obj.getProperty(runtime,
58
+ jsi::PropNameID::forAscii(runtime, "buffer"))
59
+ .asObject(runtime)
60
+ .getArrayBuffer(runtime)
61
+ : obj.getArrayBuffer(runtime);
59
62
 
60
63
  sk_sp<SkData> data =
61
64
  SkData::MakeWithCopy(buffer.data(runtime), buffer.size(runtime));
@@ -78,8 +78,8 @@ private:
78
78
  for (const auto &child : group->children) {
79
79
  if (child->type == CommandType::Group) {
80
80
  auto *childGroup = static_cast<GroupCommand *>(child.get());
81
- pending.push_back(
82
- {childGroup, sanitizeZIndex(childGroup), static_cast<int>(pending.size())});
81
+ pending.push_back({childGroup, sanitizeZIndex(childGroup),
82
+ static_cast<int>(pending.size())});
83
83
  } else {
84
84
  flushPendingGroups(ctx, pending);
85
85
  playCommand(ctx, child.get());
@@ -94,9 +94,7 @@ public:
94
94
  std::shared_ptr<RNSkPlatformContext> _context;
95
95
  Variables variables;
96
96
 
97
- Recorder() {
98
- commandStack.push_back(&commands);
99
- }
97
+ Recorder() { commandStack.push_back(&commands); }
100
98
  ~Recorder() {
101
99
  if (!_context || commands.empty()) {
102
100
  return;
@@ -128,14 +126,11 @@ public:
128
126
  pushCommand(
129
127
  std::make_unique<PushImageShaderCmd>(runtime, props, variables));
130
128
  } else if (nodeType == "skColorShader") {
131
- pushCommand(
132
- std::make_unique<ColorShaderCmd>(runtime, props, variables));
129
+ pushCommand(std::make_unique<ColorShaderCmd>(runtime, props, variables));
133
130
  } else if (nodeType == "skTurbulence") {
134
- pushCommand(
135
- std::make_unique<TurbulenceCmd>(runtime, props, variables));
131
+ pushCommand(std::make_unique<TurbulenceCmd>(runtime, props, variables));
136
132
  } else if (nodeType == "skFractalNoise") {
137
- pushCommand(
138
- std::make_unique<FractalNoiseCmd>(runtime, props, variables));
133
+ pushCommand(std::make_unique<FractalNoiseCmd>(runtime, props, variables));
139
134
  } else if (nodeType == "skLinearGradient") {
140
135
  pushCommand(
141
136
  std::make_unique<LinearGradientCmd>(runtime, props, variables));
@@ -146,12 +141,11 @@ public:
146
141
  pushCommand(
147
142
  std::make_unique<SweepGradientCmd>(runtime, props, variables));
148
143
  } else if (nodeType == "skTwoPointConicalGradient") {
149
- pushCommand(std::make_unique<TwoPointConicalGradientCmd>(
150
- runtime, props, variables));
144
+ pushCommand(std::make_unique<TwoPointConicalGradientCmd>(runtime, props,
145
+ variables));
151
146
  // TODO: should receive skBlendShader here
152
147
  } else if (nodeType == "skBlend") {
153
- pushCommand(
154
- std::make_unique<BlendShaderCmd>(runtime, props, variables));
148
+ pushCommand(std::make_unique<BlendShaderCmd>(runtime, props, variables));
155
149
  }
156
150
  }
157
151
 
@@ -216,41 +210,36 @@ public:
216
210
  pushCommand(
217
211
  std::make_unique<BlurImageFilterCmd>(runtime, props, variables));
218
212
  } else if (nodeType == "skDropShadowImageFilter") {
219
- pushCommand(std::make_unique<DropShadowImageFilterCmd>(
220
- runtime, props, variables));
213
+ pushCommand(std::make_unique<DropShadowImageFilterCmd>(runtime, props,
214
+ variables));
221
215
  } else if (nodeType == "skMorphologyImageFilter") {
222
- pushCommand(std::make_unique<MorphologyImageFilterCmd>(
223
- runtime, props, variables));
216
+ pushCommand(std::make_unique<MorphologyImageFilterCmd>(runtime, props,
217
+ variables));
224
218
  } else if (nodeType == "skBlendImageFilter") {
225
219
  pushCommand(
226
220
  std::make_unique<BlendImageFilterCmd>(runtime, props, variables));
227
221
  } else if (nodeType == "skRuntimeShaderImageFilter") {
228
- pushCommand(std::make_unique<RuntimeShaderImageFilterCmd>(
229
- runtime, props, variables));
222
+ pushCommand(std::make_unique<RuntimeShaderImageFilterCmd>(runtime, props,
223
+ variables));
230
224
  } else if (nodeType == "skImageFilter") {
231
- pushCommand(
232
- std::make_unique<ImageFilterCmd>(runtime, props, variables));
225
+ pushCommand(std::make_unique<ImageFilterCmd>(runtime, props, variables));
233
226
  }
234
227
  }
235
228
 
236
229
  void composePathEffect() {
237
- pushCommand(
238
- std::make_unique<Command>(CommandType::ComposePathEffect));
230
+ pushCommand(std::make_unique<Command>(CommandType::ComposePathEffect));
239
231
  }
240
232
 
241
233
  void composeImageFilter() {
242
- pushCommand(
243
- std::make_unique<Command>(CommandType::ComposeImageFilter));
234
+ pushCommand(std::make_unique<Command>(CommandType::ComposeImageFilter));
244
235
  }
245
236
 
246
237
  void composeColorFilter() {
247
- pushCommand(
248
- std::make_unique<Command>(CommandType::ComposeColorFilter));
238
+ pushCommand(std::make_unique<Command>(CommandType::ComposeColorFilter));
249
239
  }
250
240
 
251
241
  void pushBlurMaskFilter(jsi::Runtime &runtime, const jsi::Object &props) {
252
- pushCommand(
253
- std::make_unique<BlurMaskFilterCmd>(runtime, props, variables));
242
+ pushCommand(std::make_unique<BlurMaskFilterCmd>(runtime, props, variables));
254
243
  }
255
244
 
256
245
  void saveCTM(jsi::Runtime &runtime, const jsi::Object &props) {
@@ -278,8 +267,7 @@ public:
278
267
  }
279
268
 
280
269
  void drawTextPath(jsi::Runtime &runtime, const jsi::Object &props) {
281
- pushCommand(
282
- std::make_unique<TextPathCmd>(runtime, props, variables));
270
+ pushCommand(std::make_unique<TextPathCmd>(runtime, props, variables));
283
271
  }
284
272
 
285
273
  void drawText(jsi::Runtime &runtime, const jsi::Object &props) {
@@ -296,8 +284,7 @@ public:
296
284
 
297
285
  void drawBox(jsi::Runtime &runtime, const jsi::Object &props,
298
286
  const jsi::Array &shadows) {
299
- pushCommand(
300
- std::make_unique<BoxCmd>(runtime, props, shadows, variables));
287
+ pushCommand(std::make_unique<BoxCmd>(runtime, props, shadows, variables));
301
288
  }
302
289
 
303
290
  void drawImage(jsi::Runtime &runtime, const jsi::Object &props) {
@@ -322,18 +309,15 @@ public:
322
309
  }
323
310
 
324
311
  void drawVertices(jsi::Runtime &runtime, const jsi::Object &props) {
325
- pushCommand(
326
- std::make_unique<VerticesCmd>(runtime, props, variables));
312
+ pushCommand(std::make_unique<VerticesCmd>(runtime, props, variables));
327
313
  }
328
314
 
329
315
  void drawDiffRect(jsi::Runtime &runtime, const jsi::Object &props) {
330
- pushCommand(
331
- std::make_unique<DiffRectCmd>(runtime, props, variables));
316
+ pushCommand(std::make_unique<DiffRectCmd>(runtime, props, variables));
332
317
  }
333
318
 
334
319
  void drawTextBlob(jsi::Runtime &runtime, const jsi::Object &props) {
335
- pushCommand(
336
- std::make_unique<TextBlobCmd>(runtime, props, variables));
320
+ pushCommand(std::make_unique<TextBlobCmd>(runtime, props, variables));
337
321
  }
338
322
 
339
323
  void drawGlyphs(jsi::Runtime &runtime, const jsi::Object &props) {
@@ -346,13 +330,11 @@ public:
346
330
  }
347
331
 
348
332
  void drawImageSVG(jsi::Runtime &runtime, const jsi::Object &props) {
349
- pushCommand(
350
- std::make_unique<ImageSVGCmd>(runtime, props, variables));
333
+ pushCommand(std::make_unique<ImageSVGCmd>(runtime, props, variables));
351
334
  }
352
335
 
353
336
  void drawParagraph(jsi::Runtime &runtime, const jsi::Object &props) {
354
- pushCommand(
355
- std::make_unique<ParagraphCmd>(runtime, props, variables));
337
+ pushCommand(std::make_unique<ParagraphCmd>(runtime, props, variables));
356
338
  }
357
339
 
358
340
  void drawAtlas(jsi::Runtime &runtime, const jsi::Object &props) {
@@ -365,8 +347,7 @@ public:
365
347
  }
366
348
 
367
349
  void materializePaint() {
368
- pushCommand(
369
- std::make_unique<Command>(CommandType::MaterializePaint));
350
+ pushCommand(std::make_unique<Command>(CommandType::MaterializePaint));
370
351
  }
371
352
 
372
353
  void restorePaintDeclaration() {
@@ -379,11 +360,11 @@ public:
379
360
  }
380
361
 
381
362
  void saveBackdropFilter() {
382
- pushCommand(
383
- std::make_unique<Command>(CommandType::SaveBackdropFilter));
363
+ pushCommand(std::make_unique<Command>(CommandType::SaveBackdropFilter));
384
364
  }
385
365
 
386
- void saveGroup(jsi::Runtime &runtime, const jsi::Value *propsValue = nullptr) {
366
+ void saveGroup(jsi::Runtime &runtime,
367
+ const jsi::Value *propsValue = nullptr) {
387
368
  auto group = std::make_unique<GroupCommand>();
388
369
  if (propsValue != nullptr && propsValue->isObject()) {
389
370
  auto object = propsValue->asObject(runtime);
@@ -400,7 +381,6 @@ public:
400
381
  }
401
382
  }
402
383
 
403
-
404
384
  void play(DrawingCtx *ctx) {
405
385
  for (const auto &cmd : commands) {
406
386
  playCommand(ctx, cmd.get());
@@ -497,8 +477,7 @@ inline void Recorder::playCommand(DrawingCtx *ctx, Command *cmd) {
497
477
  auto *offsetCmd = static_cast<OffsetImageFilterCmd *>(cmd);
498
478
  offsetCmd->pushImageFilter(ctx);
499
479
  } else if (nodeType == "skDisplacementMapImageFilter") {
500
- auto *displacementCmd =
501
- static_cast<DisplacementMapImageFilterCmd *>(cmd);
480
+ auto *displacementCmd = static_cast<DisplacementMapImageFilterCmd *>(cmd);
502
481
  displacementCmd->pushImageFilter(ctx);
503
482
  } else if (nodeType == "skBlurImageFilter") {
504
483
  auto *blurCmd = static_cast<BlurImageFilterCmd *>(cmd);
@@ -513,8 +492,7 @@ inline void Recorder::playCommand(DrawingCtx *ctx, Command *cmd) {
513
492
  auto *blendCmd = static_cast<BlendImageFilterCmd *>(cmd);
514
493
  blendCmd->pushImageFilter(ctx);
515
494
  } else if (nodeType == "skRuntimeShaderImageFilter") {
516
- auto *runtimeShaderCmd =
517
- static_cast<RuntimeShaderImageFilterCmd *>(cmd);
495
+ auto *runtimeShaderCmd = static_cast<RuntimeShaderImageFilterCmd *>(cmd);
518
496
  runtimeShaderCmd->pushImageFilter(ctx);
519
497
  } else if (nodeType == "skImageFilter") {
520
498
  auto *imageFilterCmd = static_cast<ImageFilterCmd *>(cmd);
@@ -60,14 +60,16 @@ public:
60
60
 
61
61
  private:
62
62
  bool performDraw(std::shared_ptr<RNSkCanvasProvider> canvasProvider) {
63
- return canvasProvider->renderToCanvas([=, this](SkCanvas *canvas) {
64
- // Make sure to scale correctly
65
- auto pd = _platformContext->getPixelDensity();
63
+ // Capture picture pointer to ensure thread safety - _picture can be
64
+ // modified from the JS thread while we're drawing on the render thread
65
+ sk_sp<SkPicture> picture = _picture;
66
+ auto pd = _platformContext->getPixelDensity();
67
+ return canvasProvider->renderToCanvas([=](SkCanvas *canvas) {
66
68
  canvas->clear(SK_ColorTRANSPARENT);
67
69
  canvas->save();
68
70
  canvas->scale(pd, pd);
69
- if (_picture != nullptr) {
70
- canvas->drawPicture(_picture);
71
+ if (picture != nullptr) {
72
+ canvas->drawPicture(picture);
71
73
  }
72
74
  canvas->restore();
73
75
  });
@@ -8,6 +8,7 @@
8
8
  #include <thread>
9
9
  #include <unordered_map>
10
10
  #include <utility>
11
+ #include <vector>
11
12
 
12
13
  #include "RNSkVideo.h"
13
14
  #include "RNWindowContext.h"
@@ -145,6 +146,21 @@ public:
145
146
  */
146
147
  virtual sk_sp<SkFontMgr> createFontMgr() = 0;
147
148
 
149
+ /**
150
+ * Return platform-specific system font family names that aren't
151
+ * enumerated by the standard font manager (e.g., .AppleSystemUIFont on iOS)
152
+ */
153
+ virtual std::vector<std::string> getSystemFontFamilies() { return {}; }
154
+
155
+ /**
156
+ * Resolve font family aliases to actual font family names.
157
+ * For example, "System" on iOS resolves to ".AppleSystemUIFont".
158
+ * Returns the input unchanged if no mapping exists.
159
+ */
160
+ virtual std::string resolveFontFamily(const std::string &familyName) {
161
+ return familyName;
162
+ }
163
+
148
164
  /**
149
165
  * Creates an skImage containing the screenshot of a native view and its
150
166
  * children.
@@ -76,7 +76,8 @@ public:
76
76
  * The SkPngChunkReader handles unknown chunks in PNGs.
77
77
  * See SkCodec.h for more details.
78
78
  */
79
- static std::unique_ptr<SkAndroidCodec> MakeFromData(sk_sp<SkData>, SkPngChunkReader* = nullptr);
79
+ static std::unique_ptr<SkAndroidCodec> MakeFromData(sk_sp<const SkData>,
80
+ SkPngChunkReader* = nullptr);
80
81
 
81
82
  virtual ~SkAndroidCodec();
82
83
 
@@ -285,7 +286,7 @@ public:
285
286
  std::unique_ptr<SkStream>* outGainmapImageStream);
286
287
 
287
288
  protected:
288
- SkAndroidCodec(SkCodec*);
289
+ explicit SkAndroidCodec(SkCodec*);
289
290
 
290
291
  virtual SkISize onGetSampledDimensions(int sampleSize) const = 0;
291
292
 
@@ -33,7 +33,7 @@ SK_API bool IsAvif(const void*, size_t);
33
33
  SK_API std::unique_ptr<SkCodec> Decode(std::unique_ptr<SkStream>,
34
34
  SkCodec::Result*,
35
35
  SkCodecs::DecodeContext = nullptr);
36
- SK_API std::unique_ptr<SkCodec> Decode(sk_sp<SkData>,
36
+ SK_API std::unique_ptr<SkCodec> Decode(sk_sp<const SkData>,
37
37
  SkCodec::Result*,
38
38
  SkCodecs::DecodeContext = nullptr);
39
39
 
@@ -65,7 +65,7 @@ SK_API bool IsAvif(const void*, size_t);
65
65
  SK_API std::unique_ptr<SkCodec> Decode(std::unique_ptr<SkStream>,
66
66
  SkCodec::Result*,
67
67
  SkCodecs::DecodeContext = nullptr);
68
- SK_API std::unique_ptr<SkCodec> Decode(sk_sp<SkData>,
68
+ SK_API std::unique_ptr<SkCodec> Decode(sk_sp<const SkData>,
69
69
  SkCodec::Result*,
70
70
  SkCodecs::DecodeContext = nullptr);
71
71
 
@@ -31,7 +31,7 @@ SK_API bool IsBmp(const void*, size_t);
31
31
  SK_API std::unique_ptr<SkCodec> Decode(std::unique_ptr<SkStream>,
32
32
  SkCodec::Result*,
33
33
  SkCodecs::DecodeContext = nullptr);
34
- SK_API std::unique_ptr<SkCodec> Decode(sk_sp<SkData>,
34
+ SK_API std::unique_ptr<SkCodec> Decode(sk_sp<const SkData>,
35
35
  SkCodec::Result*,
36
36
  SkCodecs::DecodeContext = nullptr);
37
37
 
@@ -212,11 +212,11 @@ public:
212
212
  * If the PNG does not contain unknown chunks, the SkPngChunkReader
213
213
  * will not be used or modified.
214
214
  */
215
- static std::unique_ptr<SkCodec> MakeFromData(sk_sp<SkData>,
215
+ static std::unique_ptr<SkCodec> MakeFromData(sk_sp<const SkData>,
216
216
  SkSpan<const SkCodecs::Decoder> decoders,
217
217
  SkPngChunkReader* = nullptr);
218
218
  // deprecated
219
- static std::unique_ptr<SkCodec> MakeFromData(sk_sp<SkData>, SkPngChunkReader* = nullptr);
219
+ static std::unique_ptr<SkCodec> MakeFromData(sk_sp<const SkData>, SkPngChunkReader* = nullptr);
220
220
 
221
221
  virtual ~SkCodec();
222
222
 
@@ -849,12 +849,6 @@ protected:
849
849
  std::unique_ptr<SkStream>,
850
850
  SkEncodedOrigin = kTopLeft_SkEncodedOrigin);
851
851
 
852
- void setSrcXformFormat(XformFormat pixelFormat);
853
-
854
- XformFormat getSrcXformFormat() const {
855
- return fSrcXformFormat;
856
- }
857
-
858
852
  virtual bool onGetGainmapCodec(SkGainmapInfo*, std::unique_ptr<SkCodec>*) { return false; }
859
853
  virtual bool onGetGainmapInfo(SkGainmapInfo*) { return false; }
860
854
 
@@ -43,6 +43,23 @@ static inline SkMatrix SkEncodedOriginToMatrix(SkEncodedOrigin origin, int w, in
43
43
  SK_ABORT("Unexpected origin");
44
44
  }
45
45
 
46
+ /**
47
+ * Return a matrix equal to SkEncodedOriginToMatrix(origin, w, h).invert().
48
+ */
49
+ static inline SkMatrix SkEncodedOriginToMatrixInverse(SkEncodedOrigin origin, int w, int h) {
50
+ switch (origin) {
51
+ case kTopLeft_SkEncodedOrigin: return SkMatrix::I();
52
+ case kTopRight_SkEncodedOrigin: return SkMatrix::MakeAll(-1, 0, w, 0, 1, 0, 0, 0, 1);
53
+ case kBottomRight_SkEncodedOrigin: return SkMatrix::MakeAll(-1, 0, w, 0, -1, h, 0, 0, 1);
54
+ case kBottomLeft_SkEncodedOrigin: return SkMatrix::MakeAll( 1, 0, 0, 0, -1, h, 0, 0, 1);
55
+ case kLeftTop_SkEncodedOrigin: return SkMatrix::MakeAll( 0, 1, 0, 1, 0, 0, 0, 0, 1);
56
+ case kRightTop_SkEncodedOrigin: return SkMatrix::MakeAll( 0, 1, 0, -1, 0, w, 0, 0, 1);
57
+ case kRightBottom_SkEncodedOrigin: return SkMatrix::MakeAll( 0, -1, h, -1, 0, w, 0, 0, 1);
58
+ case kLeftBottom_SkEncodedOrigin: return SkMatrix::MakeAll( 0, -1, h, 1, 0, 0, 0, 0, 1);
59
+ }
60
+ SK_ABORT("Unexpected origin");
61
+ }
62
+
46
63
  /**
47
64
  * Return true if the encoded origin includes a 90 degree rotation, in which case the width
48
65
  * and height of the source data are swapped relative to a correctly oriented destination.
@@ -31,7 +31,7 @@ SK_API bool IsGif(const void*, size_t);
31
31
  SK_API std::unique_ptr<SkCodec> Decode(std::unique_ptr<SkStream>,
32
32
  SkCodec::Result*,
33
33
  SkCodecs::DecodeContext = nullptr);
34
- SK_API std::unique_ptr<SkCodec> Decode(sk_sp<SkData>,
34
+ SK_API std::unique_ptr<SkCodec> Decode(sk_sp<const SkData>,
35
35
  SkCodec::Result*,
36
36
  SkCodecs::DecodeContext = nullptr);
37
37
 
@@ -31,7 +31,7 @@ SK_API bool IsIco(const void*, size_t);
31
31
  SK_API std::unique_ptr<SkCodec> Decode(std::unique_ptr<SkStream>,
32
32
  SkCodec::Result*,
33
33
  SkCodecs::DecodeContext = nullptr);
34
- SK_API std::unique_ptr<SkCodec> Decode(sk_sp<SkData>,
34
+ SK_API std::unique_ptr<SkCodec> Decode(sk_sp<const SkData>,
35
35
  SkCodec::Result*,
36
36
  SkCodecs::DecodeContext = nullptr);
37
37
 
@@ -31,10 +31,17 @@ SK_API bool IsJpeg(const void*, size_t);
31
31
  SK_API std::unique_ptr<SkCodec> Decode(std::unique_ptr<SkStream>,
32
32
  SkCodec::Result*,
33
33
  SkCodecs::DecodeContext = nullptr);
34
- SK_API std::unique_ptr<SkCodec> Decode(sk_sp<SkData>,
34
+ SK_API std::unique_ptr<SkCodec> Decode(sk_sp<const SkData>,
35
35
  SkCodec::Result*,
36
36
  SkCodecs::DecodeContext = nullptr);
37
37
 
38
+ // TODO: remove after client migration
39
+ inline std::unique_ptr<SkCodec> Decode(sk_sp<SkData> data,
40
+ SkCodec::Result* result,
41
+ SkCodecs::DecodeContext ctx = nullptr) {
42
+ return Decode(sk_sp<const SkData>(static_cast<const SkData*>(data.release())), result, ctx);
43
+ }
44
+
38
45
  inline constexpr SkCodecs::Decoder Decoder() {
39
46
  return { "jpeg", IsJpeg, Decode };
40
47
  }