@shopify/react-native-skia 2.5.0 → 2.5.2

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 (41) hide show
  1. package/android/CMakeLists.txt +4 -6
  2. package/android/build.gradle +5 -32
  3. package/android/cpp/rnskia-android/OpenGLContext.h +9 -2
  4. package/android/cpp/rnskia-android/RNSkAndroidPlatformContext.h +6 -3
  5. package/apple/MetalContext.h +10 -2
  6. package/apple/MetalWindowContext.h +1 -0
  7. package/apple/MetalWindowContext.mm +8 -1
  8. package/apple/RNSkApplePlatformContext.h +2 -1
  9. package/apple/RNSkApplePlatformContext.mm +6 -4
  10. package/apple/SkiaPictureView.mm +3 -0
  11. package/cpp/api/JsiSkImage.h +76 -0
  12. package/cpp/api/JsiSkSurfaceFactory.h +12 -1
  13. package/cpp/api/recorder/Drawings.h +1 -1
  14. package/cpp/rnskia/RNDawnContext.h +24 -16
  15. package/cpp/rnskia/RNDawnUtils.h +12 -0
  16. package/cpp/rnskia/RNSkPlatformContext.h +3 -1
  17. package/lib/commonjs/dom/types/Drawings.d.ts +1 -0
  18. package/lib/commonjs/dom/types/Drawings.js.map +1 -1
  19. package/lib/commonjs/skia/types/Surface/SurfaceFactory.d.ts +10 -1
  20. package/lib/commonjs/skia/types/Surface/SurfaceFactory.js +5 -0
  21. package/lib/commonjs/skia/types/Surface/SurfaceFactory.js.map +1 -1
  22. package/lib/commonjs/sksg/Recorder/commands/Drawing.js +2 -2
  23. package/lib/commonjs/sksg/Recorder/commands/Drawing.js.map +1 -1
  24. package/lib/module/dom/types/Drawings.d.ts +1 -0
  25. package/lib/module/dom/types/Drawings.js.map +1 -1
  26. package/lib/module/skia/types/Surface/SurfaceFactory.d.ts +10 -1
  27. package/lib/module/skia/types/Surface/SurfaceFactory.js +4 -1
  28. package/lib/module/skia/types/Surface/SurfaceFactory.js.map +1 -1
  29. package/lib/module/sksg/Recorder/commands/Drawing.js +2 -2
  30. package/lib/module/sksg/Recorder/commands/Drawing.js.map +1 -1
  31. package/lib/typescript/lib/commonjs/skia/types/Surface/SurfaceFactory.d.ts +4 -0
  32. package/lib/typescript/lib/module/mock/index.d.ts +4 -0
  33. package/lib/typescript/lib/module/skia/types/Surface/SurfaceFactory.d.ts +4 -1
  34. package/lib/typescript/src/dom/types/Drawings.d.ts +1 -0
  35. package/lib/typescript/src/skia/types/Surface/SurfaceFactory.d.ts +10 -1
  36. package/package.json +5 -2
  37. package/react-native-skia.podspec +20 -104
  38. package/scripts/install-libs.js +131 -0
  39. package/src/dom/types/Drawings.ts +1 -0
  40. package/src/skia/types/Surface/SurfaceFactory.ts +13 -1
  41. package/src/sksg/Recorder/commands/Drawing.ts +3 -2
@@ -4,7 +4,7 @@ cmake_minimum_required(VERSION 3.4.1)
4
4
  set (CMAKE_VERBOSE_MAKEFILE ON)
5
5
  set (CMAKE_CXX_STANDARD 20)
6
6
 
7
- # SKIA_LIBS_PATH is passed from Gradle (resolved via Node.js package resolution)
7
+ # SKIA_LIBS_PATH is passed from Gradle (pointing to libs/android/, populated by npm postinstall)
8
8
  # Append the ABI to get the full path
9
9
  set (SKIA_LIBS_PATH "${SKIA_LIBS_PATH}/${ANDROID_ABI}")
10
10
 
@@ -17,14 +17,12 @@ if(NOT EXISTS "${SKIA_LIBS_PATH}/libskia.a")
17
17
  message("│ │")
18
18
  message("│ Could not find libskia.a at: ${SKIA_LIBS_PATH} │")
19
19
  message("│ │")
20
- message("│ Make sure react-native-skia-android is installed: │")
21
- message("│ yarn add react-native-skia-android │")
22
- message("│ │")
23
- message("│ See: https://shopify.github.io/react-native-skia/docs/getting-started/installation │")
20
+ message("│ Run the following command to install them: │")
21
+ message("│ npx install-skia │")
24
22
  message("│ │")
25
23
  message("└─────────────────────────────────────────────────────────────────────────────┘")
26
24
  message("")
27
- message(FATAL_ERROR "Skia prebuilt binaries not found at ${SKIA_LIBS_PATH}")
25
+ message(FATAL_ERROR "Skia prebuilt binaries not found. Run `npx install-skia` to fix this.")
28
26
  endif()
29
27
 
30
28
  # Import libskia
@@ -56,41 +56,15 @@ static def findNodeModules(baseDir) {
56
56
  throw new GradleException("React-Native-Skia: Failed to find node_modules/ path!")
57
57
  }
58
58
 
59
- // Resolve npm package path using Node.js resolution (handles monorepos, pnpm, etc.)
60
- def resolveSkiaPackage(packageName) {
61
- def cmdResult = providers.exec {
62
- commandLine "node", "-e", "console.log(require.resolve('${packageName}/package.json'))"
63
- ignoreExitValue = true
64
- }
65
-
66
- if (cmdResult.result.get().exitValue == 0) {
67
- def packageJsonPath = cmdResult.standardOutput.asText.get().trim()
68
- return new File(packageJsonPath).parent
69
- }
70
-
71
- // Fallback: walk up directories looking for node_modules
72
- def basePath = projectDir.toPath().normalize()
73
- while (basePath) {
74
- def candidate = Paths.get(basePath.toString(), "node_modules", packageName)
75
- if (candidate.toFile().exists() && new File(candidate.toString(), "package.json").exists()) {
76
- return candidate.toString()
77
- }
78
- basePath = basePath.getParent()
79
- }
80
-
81
- throw new GradleException("React-Native-Skia: Could not find ${packageName}. Make sure you have run 'yarn install' or 'npm install'.")
82
- }
83
-
84
59
  def nodeModules = findNodeModules(projectDir)
85
60
 
86
- // Resolve Skia Android package
87
- def useGraphite = System.getenv("SK_GRAPHITE") == "1" || System.getenv("SK_GRAPHITE") == "true"
88
- def skiaPackageName = useGraphite ? "react-native-skia-graphite-android" : "react-native-skia-android"
89
- def skiaAndroidPackage = resolveSkiaPackage(skiaPackageName)
90
- def skiaLibsPath = "${skiaAndroidPackage}/libs"
61
+ // Skia prebuilt libs are copied into libs/android/ by the npm postinstall script
62
+ // Graphite is detected via marker file created by install-skia-graphite
63
+ def useGraphite = file("${projectDir}/../libs/.graphite").exists()
64
+ def skiaLibsPath = "${projectDir}/../libs/android"
91
65
 
92
66
  logger.warn("react-native-skia: SK_GRAPHITE: ${useGraphite}")
93
- logger.warn("react-native-skia: Skia Android package: ${skiaAndroidPackage}")
67
+ logger.warn("react-native-skia: Skia libs: ${skiaLibsPath}")
94
68
  logger.warn("react-native-skia: node_modules/ found at: ${nodeModules}")
95
69
 
96
70
  def sourceBuild = false
@@ -292,7 +266,6 @@ repositories {
292
266
  }
293
267
  }
294
268
  google()
295
- maven { url 'https://www.jitpack.io' }
296
269
  }
297
270
 
298
271
  dependencies {
@@ -58,7 +58,8 @@ public:
58
58
  return instance;
59
59
  }
60
60
 
61
- sk_sp<SkSurface> MakeOffscreen(int width, int height) {
61
+ sk_sp<SkSurface> MakeOffscreen(int width, int height,
62
+ bool useP3ColorSpace = false) {
62
63
  auto colorType = kRGBA_8888_SkColorType;
63
64
 
64
65
  SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
@@ -89,10 +90,16 @@ public:
89
90
  auto releaseCtx = new ReleaseContext{.directContext = _directContext.get(),
90
91
  .texture = texture};
91
92
 
93
+ sk_sp<SkColorSpace> colorSpace =
94
+ useP3ColorSpace
95
+ ? SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB,
96
+ SkNamedGamut::kDisplayP3)
97
+ : nullptr;
98
+
92
99
  // Create a SkSurface from the GrBackendTexture
93
100
  return SkSurfaces::WrapBackendTexture(
94
101
  _directContext.get(), texture, kTopLeft_GrSurfaceOrigin, 0, colorType,
95
- nullptr, &props,
102
+ colorSpace, &props,
96
103
  [](void *addr) {
97
104
  auto releaseCtx = reinterpret_cast<ReleaseContext *>(addr);
98
105
  releaseCtx->directContext->deleteBackendTexture(releaseCtx->texture);
@@ -50,11 +50,14 @@ public:
50
50
  _jniPlatformContext->raiseError(err);
51
51
  }
52
52
 
53
- sk_sp<SkSurface> makeOffscreenSurface(int width, int height) override {
53
+ sk_sp<SkSurface> makeOffscreenSurface(int width, int height,
54
+ bool useP3ColorSpace = false) override {
54
55
  #if defined(SK_GRAPHITE)
55
- return DawnContext::getInstance().MakeOffscreen(width, height);
56
+ return DawnContext::getInstance().MakeOffscreen(width, height,
57
+ useP3ColorSpace);
56
58
  #else
57
- return OpenGLContext::getInstance().MakeOffscreen(width, height);
59
+ return OpenGLContext::getInstance().MakeOffscreen(width, height,
60
+ useP3ColorSpace);
58
61
  #endif
59
62
  }
60
63
 
@@ -13,6 +13,7 @@
13
13
  #import <include/gpu/ganesh/mtl/GrMtlBackendSurface.h>
14
14
  #import <include/gpu/ganesh/mtl/GrMtlDirectContext.h>
15
15
  #import <include/gpu/ganesh/mtl/SkSurfaceMetal.h>
16
+ #include "include/core/SkColorSpace.h"
16
17
 
17
18
  struct OffscreenRenderContext {
18
19
  id<MTLTexture> texture;
@@ -44,7 +45,8 @@ public:
44
45
  return instance;
45
46
  }
46
47
 
47
- sk_sp<SkSurface> MakeOffscreen(int width, int height) {
48
+ sk_sp<SkSurface> MakeOffscreen(int width, int height,
49
+ bool useP3ColorSpace = false) {
48
50
  auto device = _device;
49
51
  auto ctx = new OffscreenRenderContext(device, _directContext, _commandQueue,
50
52
  width, height);
@@ -55,10 +57,16 @@ public:
55
57
  GrBackendTexture backendTexture =
56
58
  GrBackendTextures::MakeMtl(width, height, skgpu::Mipmapped::kNo, info);
57
59
 
60
+ sk_sp<SkColorSpace> colorSpace =
61
+ useP3ColorSpace
62
+ ? SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB,
63
+ SkNamedGamut::kDisplayP3)
64
+ : nullptr;
65
+
58
66
  // Create a SkSurface from the GrBackendTexture
59
67
  auto surface = SkSurfaces::WrapBackendTexture(
60
68
  _directContext.get(), backendTexture, kTopLeft_GrSurfaceOrigin, 0,
61
- kBGRA_8888_SkColorType, nullptr, nullptr,
69
+ kBGRA_8888_SkColorType, colorSpace, nullptr,
62
70
  [](void *addr) { delete (OffscreenRenderContext *)addr; }, ctx);
63
71
 
64
72
  return surface;
@@ -36,4 +36,5 @@ private:
36
36
  CAMetalLayer *_layer;
37
37
  #pragma clang diagnostic pop
38
38
  id<CAMetalDrawable> _currentDrawable = nil;
39
+ bool _useP3ColorSpace = false;
39
40
  };
@@ -2,6 +2,7 @@
2
2
 
3
3
  #include "MetalContext.h"
4
4
  #include "RNSkLog.h"
5
+ #include "include/core/SkColorSpace.h"
5
6
 
6
7
  MetalWindowContext::MetalWindowContext(GrDirectContext *directContext,
7
8
  id<MTLDevice> device,
@@ -46,6 +47,7 @@ MetalWindowContext::MetalWindowContext(GrDirectContext *directContext,
46
47
  CGColorSpaceCreateWithName(kCGColorSpaceDisplayP3);
47
48
  _layer.colorspace = colorSpace;
48
49
  CGColorSpaceRelease(colorSpace);
50
+ _useP3ColorSpace = true;
49
51
  }
50
52
  }
51
53
 
@@ -69,9 +71,14 @@ sk_sp<SkSurface> MetalWindowContext::getSurface() {
69
71
  GrBackendRenderTarget backendRT = GrBackendRenderTargets::MakeMtl(
70
72
  _layer.drawableSize.width, _layer.drawableSize.height, fbInfo);
71
73
 
74
+ sk_sp<SkColorSpace> skColorSpace =
75
+ _useP3ColorSpace
76
+ ? SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB,
77
+ SkNamedGamut::kDisplayP3)
78
+ : nullptr;
72
79
  _skSurface = SkSurfaces::WrapBackendRenderTarget(
73
80
  _directContext, backendRT, kTopLeft_GrSurfaceOrigin,
74
- kBGRA_8888_SkColorType, nullptr, nullptr);
81
+ kBGRA_8888_SkColorType, skColorSpace, nullptr);
75
82
 
76
83
  return _skSurface;
77
84
  }
@@ -69,7 +69,8 @@ public:
69
69
  const std::function<void(std::unique_ptr<SkStreamAsset>)> &op) override;
70
70
 
71
71
  void raiseError(const std::exception &err) override;
72
- sk_sp<SkSurface> makeOffscreenSurface(int width, int height) override;
72
+ sk_sp<SkSurface> makeOffscreenSurface(int width, int height,
73
+ bool useP3ColorSpace = false) override;
73
74
 
74
75
  sk_sp<SkFontMgr> createFontMgr() override;
75
76
 
@@ -251,12 +251,14 @@ void RNSkApplePlatformContext::raiseError(const std::exception &err) {
251
251
  RCTFatal(RCTErrorWithMessage([NSString stringWithUTF8String:err.what()]));
252
252
  }
253
253
 
254
- sk_sp<SkSurface> RNSkApplePlatformContext::makeOffscreenSurface(int width,
255
- int height) {
254
+ sk_sp<SkSurface> RNSkApplePlatformContext::makeOffscreenSurface(
255
+ int width, int height, bool useP3ColorSpace) {
256
256
  #if defined(SK_GRAPHITE)
257
- return DawnContext::getInstance().MakeOffscreen(width, height);
257
+ return DawnContext::getInstance().MakeOffscreen(width, height,
258
+ useP3ColorSpace);
258
259
  #else
259
- return MetalContext::getInstance().MakeOffscreen(width, height);
260
+ return MetalContext::getInstance().MakeOffscreen(width, height,
261
+ useP3ColorSpace);
260
262
  #endif
261
263
  }
262
264
 
@@ -58,6 +58,9 @@ using namespace facebook::react;
58
58
  if (newProps.colorSpace == "" || newProps.colorSpace == "srgb") {
59
59
  bool useP3 = false;
60
60
  [self setUseP3ColorSpace:useP3];
61
+ } else if (newProps.colorSpace == "p3") {
62
+ bool useP3 = true;
63
+ [self setUseP3ColorSpace:useP3];
61
64
  }
62
65
  }
63
66
 
@@ -35,6 +35,75 @@
35
35
 
36
36
  #include <jsi/jsi.h>
37
37
 
38
+ #ifdef __APPLE__
39
+ #include <CoreFoundation/CoreFoundation.h>
40
+ #include <CoreGraphics/CoreGraphics.h>
41
+ #include <cstring>
42
+
43
+ // Replaces Skia's generated "Display P3 Gamut with sRGB Transfer" (Google/Skia
44
+ // copyright) ICC profile in a JPEG with Apple's canonical Display P3 ICC bytes
45
+ // from CGColorSpace.displayP3. This is needed because apps like Instagram only
46
+ // recognise the canonical Apple profile, not Skia's mathematically equivalent
47
+ // but non-standard one. Pixel values are untouched — zero quality loss.
48
+ static sk_sp<SkData> replaceJpegICCWithAppleP3(sk_sp<SkData> jpegData) {
49
+ if (!jpegData || jpegData->size() < 4) return jpegData;
50
+
51
+ const uint8_t *src = jpegData->bytes();
52
+ size_t srcLen = jpegData->size();
53
+ if (src[0] != 0xFF || src[1] != 0xD8) return jpegData; // not a JPEG
54
+
55
+ CGColorSpaceRef p3 = CGColorSpaceCreateWithName(kCGColorSpaceDisplayP3);
56
+ if (!p3) return jpegData;
57
+ CFDataRef cfICC = CGColorSpaceCopyICCData(p3);
58
+ CGColorSpaceRelease(p3);
59
+ if (!cfICC) return jpegData;
60
+
61
+ const uint8_t *iccBytes = CFDataGetBytePtr(cfICC);
62
+ size_t iccLen = (size_t)CFDataGetLength(cfICC);
63
+
64
+ // "ICC_PROFILE\0" APP2 marker signature (12 bytes)
65
+ static const uint8_t iccSig[] = {0x49, 0x43, 0x43, 0x5F, 0x50, 0x52,
66
+ 0x4F, 0x46, 0x49, 0x4C, 0x45, 0x00};
67
+
68
+ SkDynamicMemoryWStream out;
69
+
70
+ out.write(src, 2); // SOI
71
+
72
+ // Structure: marker(2) + length(2) + "ICC_PROFILE\0"(12) + chunk[1,1](2) + profile
73
+ size_t iccContentLen = sizeof(iccSig) + 2 + iccLen;
74
+ size_t segLen = iccContentLen + 2; // length field includes itself
75
+ uint8_t app2hdr[4] = {0xFF, 0xE2, (uint8_t)(segLen >> 8),
76
+ (uint8_t)(segLen & 0xFF)};
77
+ uint8_t chunkInfo[2] = {0x01, 0x01}; // chunk 1 of 1
78
+ out.write(app2hdr, 4);
79
+ out.write(iccSig, sizeof(iccSig));
80
+ out.write(chunkInfo, 2);
81
+ out.write(iccBytes, iccLen);
82
+
83
+ // Copy all header segments except any existing ICC APP2
84
+ size_t i = 2;
85
+ while (i + 3 < srcLen) {
86
+ if (src[i] != 0xFF) break;
87
+ uint8_t marker = src[i + 1];
88
+ if (marker == 0xDA || marker == 0xD9) break; // SOS / EOI
89
+ size_t segLenVal = (size_t(src[i + 2]) << 8) | src[i + 3];
90
+ size_t end = i + 2 + segLenVal;
91
+ if (end > srcLen) break;
92
+ bool isICC = marker == 0xE2 && end > i + 4 + sizeof(iccSig) &&
93
+ memcmp(src + i + 4, iccSig, sizeof(iccSig)) == 0;
94
+ if (!isICC) {
95
+ out.write(src + i, end - i);
96
+ }
97
+ i = end;
98
+ }
99
+
100
+ out.write(src + i, srcLen - i);
101
+
102
+ CFRelease(cfICC);
103
+ return out.detachAsData();
104
+ }
105
+ #endif // __APPLE__
106
+
38
107
  namespace RNSkia {
39
108
 
40
109
  namespace jsi = facebook::jsi;
@@ -138,6 +207,13 @@ public:
138
207
  SkJpegEncoder::Options options;
139
208
  options.fQuality = quality;
140
209
  data = SkJpegEncoder::Encode(nullptr, image.get(), options);
210
+ #ifdef __APPLE__
211
+ // Replace Skia's generated ICC with Apple's canonical Display P3 profile
212
+ // so apps like Instagram recognise the wide-gamut colour space.
213
+ if (data && image->colorSpace() && !image->colorSpace()->isSRGB()) {
214
+ data = replaceJpegICCWithAppleP3(data);
215
+ }
216
+ #endif
141
217
  } else if (format == SkEncodedImageFormat::kWEBP) {
142
218
  SkWebpEncoder::Options options;
143
219
  if (quality >= 100) {
@@ -39,8 +39,19 @@ public:
39
39
  JSI_HOST_FUNCTION(MakeOffscreen) {
40
40
  auto width = static_cast<int>(arguments[0].asNumber());
41
41
  auto height = static_cast<int>(arguments[1].asNumber());
42
+ bool useP3ColorSpace = false;
43
+ if (count >= 3 && arguments[2].isObject()) {
44
+ auto opts = arguments[2].asObject(runtime);
45
+ if (opts.hasProperty(runtime, "colorSpace")) {
46
+ auto colorSpaceVal = opts.getProperty(runtime, "colorSpace");
47
+ if (colorSpaceVal.isString()) {
48
+ useP3ColorSpace =
49
+ colorSpaceVal.asString(runtime).utf8(runtime) == "display-p3";
50
+ }
51
+ }
52
+ }
42
53
  auto context = getContext();
43
- auto surface = context->makeOffscreenSurface(width, height);
54
+ auto surface = context->makeOffscreenSurface(width, height, useP3ColorSpace);
44
55
  if (surface == nullptr) {
45
56
  return jsi::Value::null();
46
57
  }
@@ -935,7 +935,7 @@ public:
935
935
  convertProperty(runtime, object, "sprites", props.sprites, variables);
936
936
  convertProperty(runtime, object, "transforms", props.transforms, variables);
937
937
  convertProperty(runtime, object, "colors", props.colors, variables);
938
- convertProperty(runtime, object, "blendMode", props.blendMode, variables);
938
+ convertProperty(runtime, object, "colorBlendMode", props.blendMode, variables);
939
939
  convertProperty(runtime, object, "sampling", props.sampling, variables);
940
940
  }
941
941
 
@@ -7,6 +7,7 @@
7
7
  #include "RNDawnWindowContext.h"
8
8
  #include "RNImageProvider.h"
9
9
 
10
+ #include "include/core/SkColorSpace.h"
10
11
  #include "include/core/SkData.h"
11
12
  #include "include/gpu/graphite/BackendTexture.h"
12
13
  #include "include/gpu/graphite/Context.h"
@@ -162,9 +163,16 @@ public:
162
163
  }
163
164
 
164
165
  // Create offscreen surface
165
- sk_sp<SkSurface> MakeOffscreen(int width, int height) {
166
+ sk_sp<SkSurface> MakeOffscreen(int width, int height,
167
+ bool useP3ColorSpace = false) {
168
+ sk_sp<SkColorSpace> colorSpace =
169
+ useP3ColorSpace
170
+ ? SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB,
171
+ SkNamedGamut::kDisplayP3)
172
+ : nullptr;
166
173
  SkImageInfo info = SkImageInfo::Make(
167
- width, height, DawnUtils::PreferedColorType, kPremul_SkAlphaType);
174
+ width, height, DawnUtils::PreferedColorType, kPremul_SkAlphaType,
175
+ colorSpace);
168
176
  sk_sp<SkSurface> surface = SkSurfaces::RenderTarget(getRecorder(), info);
169
177
 
170
178
  if (!surface) {
@@ -303,6 +311,20 @@ public:
303
311
  getRecorder(), backendContext.fDevice, surface, width, height);
304
312
  }
305
313
 
314
+ skgpu::graphite::Recorder *getRecorder() {
315
+ static thread_local skgpu::graphite::RecorderOptions recorderOptions;
316
+ if (!recorderOptions.fImageProvider) {
317
+ auto imageProvider = ImageProvider::Make();
318
+ recorderOptions.fImageProvider = imageProvider;
319
+ }
320
+ static thread_local auto recorder =
321
+ fGraphiteContext->makeRecorder(recorderOptions);
322
+ if (!recorder) {
323
+ throw std::runtime_error("Failed to create graphite context");
324
+ }
325
+ return recorder.get();
326
+ }
327
+
306
328
  private:
307
329
  std::unique_ptr<dawn::native::Instance> instance;
308
330
  std::unique_ptr<skgpu::graphite::Context> fGraphiteContext;
@@ -346,20 +368,6 @@ private:
346
368
  backendContext.fTick(backendContext.fInstance);
347
369
  }
348
370
  }
349
-
350
- skgpu::graphite::Recorder *getRecorder() {
351
- static thread_local skgpu::graphite::RecorderOptions recorderOptions;
352
- if (!recorderOptions.fImageProvider) {
353
- auto imageProvider = ImageProvider::Make();
354
- recorderOptions.fImageProvider = imageProvider;
355
- }
356
- static thread_local auto recorder =
357
- fGraphiteContext->makeRecorder(recorderOptions);
358
- if (!recorder) {
359
- throw std::runtime_error("Failed to create graphite context");
360
- }
361
- return recorder.get();
362
- }
363
371
  };
364
372
 
365
373
  } // namespace RNSkia
@@ -177,6 +177,18 @@ createDawnBackendContext(dawn::native::Instance *instance) {
177
177
  if (adapter.HasFeature(wgpu::FeatureName::SharedTextureMemoryIOSurface)) {
178
178
  features.push_back(wgpu::FeatureName::SharedTextureMemoryIOSurface);
179
179
  }
180
+ if (adapter.HasFeature(wgpu::FeatureName::DawnMultiPlanarFormats)) {
181
+ features.push_back(wgpu::FeatureName::DawnMultiPlanarFormats);
182
+ }
183
+ if (adapter.HasFeature(wgpu::FeatureName::MultiPlanarFormatP010)) {
184
+ features.push_back(wgpu::FeatureName::MultiPlanarFormatP010);
185
+ }
186
+ if (adapter.HasFeature(wgpu::FeatureName::MultiPlanarFormatP210)) {
187
+ features.push_back(wgpu::FeatureName::MultiPlanarFormatP210);
188
+ }
189
+ if (adapter.HasFeature(wgpu::FeatureName::MultiPlanarFormatExtendedUsages)) {
190
+ features.push_back(wgpu::FeatureName::MultiPlanarFormatExtendedUsages);
191
+ }
180
192
  #else
181
193
  if (adapter.HasFeature(
182
194
  wgpu::FeatureName::SharedTextureMemoryAHardwareBuffer)) {
@@ -90,9 +90,11 @@ public:
90
90
  * Creates an offscreen surface
91
91
  * @param width Width of the offscreen surface
92
92
  * @param height Height of the offscreen surface
93
+ * @param useP3ColorSpace If true, surface will use Display P3 color space
93
94
  * @return sk_sp<SkSurface>
94
95
  */
95
- virtual sk_sp<SkSurface> makeOffscreenSurface(int width, int height) = 0;
96
+ virtual sk_sp<SkSurface> makeOffscreenSurface(int width, int height,
97
+ bool useP3ColorSpace = false) = 0;
96
98
 
97
99
  virtual std::shared_ptr<WindowContext>
98
100
  makeContextFromNativeSurface(void *surface, int width, int height) = 0;
@@ -28,6 +28,7 @@ export interface AtlasProps extends DrawingNodeProps {
28
28
  sprites: SkRect[];
29
29
  transforms: SkRSXform[];
30
30
  colors?: SkColor[];
31
+ colorBlendMode?: SkEnum<typeof BlendMode>;
31
32
  sampling?: SamplingOptions;
32
33
  }
33
34
  export interface CubicBezierHandle {
@@ -1 +1 @@
1
- {"version":3,"names":[],"sources":["Drawings.ts"],"sourcesContent":["import type {\n FillType,\n SkImage,\n StrokeOpts,\n Vector,\n Color,\n SkPoint,\n BlendMode,\n PointMode,\n VertexMode,\n SkFont,\n SkRRect,\n SkTextBlob,\n SkPicture,\n SkSVG,\n SkPaint,\n SkRect,\n SkRSXform,\n SkColor,\n SamplingOptions,\n SkSkottieAnimation,\n SkImageFilter,\n} from \"../../skia/types\";\n\nimport type {\n CircleDef,\n Fit,\n GroupProps,\n PathDef,\n RectDef,\n RRectDef,\n SkEnum,\n} from \"./Common\";\n\nexport interface DrawingNodeProps extends GroupProps {\n paint?: SkPaint;\n}\n\nexport type ImageProps = DrawingNodeProps &\n RectDef & {\n fit?: Fit;\n image: SkImage | null;\n sampling?: SamplingOptions;\n };\n\nexport type CircleProps = CircleDef & DrawingNodeProps;\n\nexport interface PathProps extends DrawingNodeProps {\n path: PathDef;\n start: number;\n end: number;\n stroke?: StrokeOpts;\n fillType?: SkEnum<typeof FillType>;\n}\n\nexport interface LineProps extends DrawingNodeProps {\n p1: Vector;\n p2: Vector;\n}\n\nexport type OvalProps = RectDef & DrawingNodeProps;\n\nexport type RectProps = RectDef & DrawingNodeProps;\n\nexport type RoundedRectProps = RRectDef & DrawingNodeProps;\n\nexport interface AtlasProps extends DrawingNodeProps {\n image: SkImage | null;\n sprites: SkRect[];\n transforms: SkRSXform[];\n colors?: SkColor[];\n sampling?: SamplingOptions;\n}\n\nexport interface CubicBezierHandle {\n pos: Vector;\n c1: Vector;\n c2: Vector;\n}\n\nexport interface PatchProps extends DrawingNodeProps {\n colors?: Color[];\n patch: [\n CubicBezierHandle,\n CubicBezierHandle,\n CubicBezierHandle,\n CubicBezierHandle,\n ];\n texture?: readonly [SkPoint, SkPoint, SkPoint, SkPoint];\n blendMode?: SkEnum<typeof BlendMode>;\n}\n\nexport interface VerticesProps extends DrawingNodeProps {\n colors?: string[];\n vertices: SkPoint[];\n textures?: SkPoint[];\n mode: SkEnum<typeof VertexMode>;\n blendMode?: SkEnum<typeof BlendMode>;\n indices?: number[];\n}\n\nexport interface ImageSVGProps extends DrawingNodeProps {\n svg: SkSVG | null;\n x?: number;\n y?: number;\n width?: number;\n height?: number;\n rect?: SkRect;\n}\n\nexport interface SkottieProps extends DrawingNodeProps {\n animation: SkSkottieAnimation;\n frame: number;\n}\n\nexport interface PictureProps extends DrawingNodeProps {\n picture: SkPicture;\n}\n\nexport interface PointsProps extends DrawingNodeProps {\n points: SkPoint[];\n mode: SkEnum<typeof PointMode>;\n}\n\nexport interface DiffRectProps extends DrawingNodeProps {\n inner: SkRRect;\n outer: SkRRect;\n}\n\nexport interface TextProps extends DrawingNodeProps {\n font: SkFont | null;\n text: string;\n x: number;\n y: number;\n}\n\nexport interface TextPathProps extends DrawingNodeProps {\n font: SkFont | null;\n text: string;\n path: PathDef;\n initialOffset: number;\n}\n\nexport interface TextBlobProps extends DrawingNodeProps {\n blob: SkTextBlob;\n x: number;\n y: number;\n}\n\nexport interface Glyph {\n id: number;\n pos: SkPoint;\n}\n\nexport interface GlyphsProps extends DrawingNodeProps {\n font: SkFont | null;\n x: number;\n y: number;\n glyphs: Glyph[];\n}\n\nexport interface BoxProps extends DrawingNodeProps {\n box: SkRRect | SkRect;\n}\n\nexport interface BoxShadowProps {\n dx?: number;\n dy?: number;\n spread?: number;\n blur: number;\n color?: Color;\n inner?: boolean;\n}\n\nexport interface ImageFilterProps extends GroupProps {\n filter: SkImageFilter;\n}\n"],"mappings":"","ignoreList":[]}
1
+ {"version":3,"names":[],"sources":["Drawings.ts"],"sourcesContent":["import type {\n FillType,\n SkImage,\n StrokeOpts,\n Vector,\n Color,\n SkPoint,\n BlendMode,\n PointMode,\n VertexMode,\n SkFont,\n SkRRect,\n SkTextBlob,\n SkPicture,\n SkSVG,\n SkPaint,\n SkRect,\n SkRSXform,\n SkColor,\n SamplingOptions,\n SkSkottieAnimation,\n SkImageFilter,\n} from \"../../skia/types\";\n\nimport type {\n CircleDef,\n Fit,\n GroupProps,\n PathDef,\n RectDef,\n RRectDef,\n SkEnum,\n} from \"./Common\";\n\nexport interface DrawingNodeProps extends GroupProps {\n paint?: SkPaint;\n}\n\nexport type ImageProps = DrawingNodeProps &\n RectDef & {\n fit?: Fit;\n image: SkImage | null;\n sampling?: SamplingOptions;\n };\n\nexport type CircleProps = CircleDef & DrawingNodeProps;\n\nexport interface PathProps extends DrawingNodeProps {\n path: PathDef;\n start: number;\n end: number;\n stroke?: StrokeOpts;\n fillType?: SkEnum<typeof FillType>;\n}\n\nexport interface LineProps extends DrawingNodeProps {\n p1: Vector;\n p2: Vector;\n}\n\nexport type OvalProps = RectDef & DrawingNodeProps;\n\nexport type RectProps = RectDef & DrawingNodeProps;\n\nexport type RoundedRectProps = RRectDef & DrawingNodeProps;\n\nexport interface AtlasProps extends DrawingNodeProps {\n image: SkImage | null;\n sprites: SkRect[];\n transforms: SkRSXform[];\n colors?: SkColor[];\n colorBlendMode?: SkEnum<typeof BlendMode>;\n sampling?: SamplingOptions;\n}\n\nexport interface CubicBezierHandle {\n pos: Vector;\n c1: Vector;\n c2: Vector;\n}\n\nexport interface PatchProps extends DrawingNodeProps {\n colors?: Color[];\n patch: [\n CubicBezierHandle,\n CubicBezierHandle,\n CubicBezierHandle,\n CubicBezierHandle,\n ];\n texture?: readonly [SkPoint, SkPoint, SkPoint, SkPoint];\n blendMode?: SkEnum<typeof BlendMode>;\n}\n\nexport interface VerticesProps extends DrawingNodeProps {\n colors?: string[];\n vertices: SkPoint[];\n textures?: SkPoint[];\n mode: SkEnum<typeof VertexMode>;\n blendMode?: SkEnum<typeof BlendMode>;\n indices?: number[];\n}\n\nexport interface ImageSVGProps extends DrawingNodeProps {\n svg: SkSVG | null;\n x?: number;\n y?: number;\n width?: number;\n height?: number;\n rect?: SkRect;\n}\n\nexport interface SkottieProps extends DrawingNodeProps {\n animation: SkSkottieAnimation;\n frame: number;\n}\n\nexport interface PictureProps extends DrawingNodeProps {\n picture: SkPicture;\n}\n\nexport interface PointsProps extends DrawingNodeProps {\n points: SkPoint[];\n mode: SkEnum<typeof PointMode>;\n}\n\nexport interface DiffRectProps extends DrawingNodeProps {\n inner: SkRRect;\n outer: SkRRect;\n}\n\nexport interface TextProps extends DrawingNodeProps {\n font: SkFont | null;\n text: string;\n x: number;\n y: number;\n}\n\nexport interface TextPathProps extends DrawingNodeProps {\n font: SkFont | null;\n text: string;\n path: PathDef;\n initialOffset: number;\n}\n\nexport interface TextBlobProps extends DrawingNodeProps {\n blob: SkTextBlob;\n x: number;\n y: number;\n}\n\nexport interface Glyph {\n id: number;\n pos: SkPoint;\n}\n\nexport interface GlyphsProps extends DrawingNodeProps {\n font: SkFont | null;\n x: number;\n y: number;\n glyphs: Glyph[];\n}\n\nexport interface BoxProps extends DrawingNodeProps {\n box: SkRRect | SkRect;\n}\n\nexport interface BoxShadowProps {\n dx?: number;\n dy?: number;\n spread?: number;\n blur: number;\n color?: Color;\n inner?: boolean;\n}\n\nexport interface ImageFilterProps extends GroupProps {\n filter: SkImageFilter;\n}\n"],"mappings":"","ignoreList":[]}
@@ -1,4 +1,12 @@
1
1
  import type { SkSurface } from "./Surface";
2
+ export declare const ColorSpace: {
3
+ readonly SRGB: "srgb";
4
+ readonly DisplayP3: "display-p3";
5
+ };
6
+ export type ColorSpaceValue = (typeof ColorSpace)[keyof typeof ColorSpace];
7
+ export interface SurfaceOptions {
8
+ colorSpace: ColorSpaceValue;
9
+ }
2
10
  export interface SurfaceFactory {
3
11
  /**
4
12
  * Returns a CPU backed surface with the given dimensions, an SRGB colorspace, Unpremul
@@ -12,6 +20,7 @@ export interface SurfaceFactory {
12
20
  * Creates a GPU backed surface.
13
21
  * @param width - number of pixels of the width of the drawable area.
14
22
  * @param height - number of pixels of the height of the drawable area.
23
+ * @param opts - optional surface options (e.g. colorSpace: "display-p3" | "srgb").
15
24
  */
16
- MakeOffscreen: (width: number, height: number) => SkSurface | null;
25
+ MakeOffscreen: (width: number, height: number, opts?: SurfaceOptions) => SkSurface | null;
17
26
  }
@@ -3,4 +3,9 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
+ exports.ColorSpace = void 0;
7
+ const ColorSpace = exports.ColorSpace = {
8
+ SRGB: "srgb",
9
+ DisplayP3: "display-p3"
10
+ };
6
11
  //# sourceMappingURL=SurfaceFactory.js.map
@@ -1 +1 @@
1
- {"version":3,"names":[],"sources":["SurfaceFactory.ts"],"sourcesContent":["import type { SkSurface } from \"./Surface\";\n\nexport interface SurfaceFactory {\n /**\n * Returns a CPU backed surface with the given dimensions, an SRGB colorspace, Unpremul\n * alphaType and 8888 color type. The pixels belonging to this surface will be in memory and\n * not visible.\n * @param width - number of pixels of the width of the drawable area.\n * @param height - number of pixels of the height of the drawable area.\n */\n Make: (width: number, height: number) => SkSurface | null;\n\n /**\n * Creates a GPU backed surface.\n * @param width - number of pixels of the width of the drawable area.\n * @param height - number of pixels of the height of the drawable area.\n */\n MakeOffscreen: (width: number, height: number) => SkSurface | null;\n}\n"],"mappings":"","ignoreList":[]}
1
+ {"version":3,"names":["ColorSpace","exports","SRGB","DisplayP3"],"sources":["SurfaceFactory.ts"],"sourcesContent":["import type { SkSurface } from \"./Surface\";\n\nexport const ColorSpace = {\n SRGB: \"srgb\",\n DisplayP3: \"display-p3\",\n} as const;\n\nexport type ColorSpaceValue = (typeof ColorSpace)[keyof typeof ColorSpace];\n\nexport interface SurfaceOptions {\n colorSpace: ColorSpaceValue;\n}\n\nexport interface SurfaceFactory {\n /**\n * Returns a CPU backed surface with the given dimensions, an SRGB colorspace, Unpremul\n * alphaType and 8888 color type. The pixels belonging to this surface will be in memory and\n * not visible.\n * @param width - number of pixels of the width of the drawable area.\n * @param height - number of pixels of the height of the drawable area.\n */\n Make: (width: number, height: number) => SkSurface | null;\n\n /**\n * Creates a GPU backed surface.\n * @param width - number of pixels of the width of the drawable area.\n * @param height - number of pixels of the height of the drawable area.\n * @param opts - optional surface options (e.g. colorSpace: \"display-p3\" | \"srgb\").\n */\n MakeOffscreen: (width: number, height: number, opts?: SurfaceOptions) => SkSurface | null;\n}\n"],"mappings":";;;;;;AAEO,MAAMA,UAAU,GAAAC,OAAA,CAAAD,UAAA,GAAG;EACxBE,IAAI,EAAE,MAAM;EACZC,SAAS,EAAE;AACb,CAAU","ignoreList":[]}
@@ -318,10 +318,10 @@ const drawAtlas = (ctx, props) => {
318
318
  sprites,
319
319
  transforms,
320
320
  colors,
321
- blendMode,
321
+ colorBlendMode,
322
322
  sampling
323
323
  } = props;
324
- const blend = blendMode ? _types.BlendMode[(0, _nodes.enumKey)(blendMode)] : undefined;
324
+ const blend = colorBlendMode ? _types.BlendMode[(0, _nodes.enumKey)(colorBlendMode)] : undefined;
325
325
  if (image) {
326
326
  ctx.canvas.drawAtlas(image, sprites, transforms, ctx.paint, blend, colors, sampling);
327
327
  }