@shopify/react-native-skia 1.5.2 → 1.5.4

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 (87) hide show
  1. package/android/CMakeLists.txt +52 -13
  2. package/android/build.gradle +3 -0
  3. package/android/cpp/rnskia-android/RNSkAndroidPlatformContext.h +18 -1
  4. package/android/cpp/rnskia-android/RNSkAndroidVideo.cpp +12 -1
  5. package/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp +13 -0
  6. package/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java +0 -1
  7. package/cpp/api/JsiSkImage.h +15 -2
  8. package/cpp/api/JsiSkSurface.h +18 -3
  9. package/cpp/rnskia/DawnContext.h +241 -0
  10. package/cpp/rnskia/DawnUtils.h +127 -0
  11. package/cpp/rnskia/DawnWindowContext.cpp +19 -0
  12. package/cpp/rnskia/DawnWindowContext.h +77 -0
  13. package/cpp/rnskia/ImageProvider.h +100 -0
  14. package/cpp/rnskia/RNSkView.h +6 -0
  15. package/cpp/skia/include/android/SkAnimatedImage.h +14 -0
  16. package/cpp/skia/include/codec/SkAvifDecoder.h +39 -3
  17. package/cpp/skia/include/codec/SkCodec.h +16 -0
  18. package/cpp/skia/include/config/SkUserConfig.h +3 -2
  19. package/cpp/skia/include/core/SkCanvas.h +55 -10
  20. package/cpp/skia/include/core/SkContourMeasure.h +76 -0
  21. package/cpp/skia/include/core/SkFontScanner.h +48 -0
  22. package/cpp/skia/include/core/SkMilestone.h +1 -1
  23. package/cpp/skia/include/core/SkPath.h +11 -0
  24. package/cpp/skia/include/core/SkPathEffect.h +0 -23
  25. package/cpp/skia/include/core/SkRect.h +2 -0
  26. package/cpp/skia/include/core/SkString.h +4 -0
  27. package/cpp/skia/include/core/SkTypeface.h +5 -0
  28. package/cpp/skia/include/core/SkTypes.h +8 -3
  29. package/cpp/skia/include/docs/SkPDFDocument.h +3 -3
  30. package/cpp/skia/include/effects/SkOverdrawColorFilter.h +1 -0
  31. package/cpp/skia/include/effects/SkRuntimeEffect.h +2 -1
  32. package/cpp/skia/include/encode/SkJpegEncoder.h +4 -0
  33. package/cpp/skia/include/gpu/ganesh/GrContextOptions.h +8 -1
  34. package/cpp/skia/include/gpu/ganesh/GrDirectContext.h +18 -3
  35. package/cpp/skia/include/gpu/ganesh/GrTypes.h +11 -0
  36. package/cpp/skia/include/gpu/ganesh/gl/GrGLFunctions.h +5 -1
  37. package/cpp/skia/include/gpu/ganesh/gl/GrGLInterface.h +0 -1
  38. package/cpp/skia/include/gpu/graphite/GraphiteTypes.h +8 -0
  39. package/cpp/skia/include/gpu/graphite/Recorder.h +0 -2
  40. package/cpp/skia/include/gpu/graphite/precompile/PaintOptions.h +7 -4
  41. package/cpp/skia/include/gpu/graphite/precompile/PrecompileImageFilter.h +2 -0
  42. package/cpp/skia/include/gpu/graphite/precompile/PrecompileMaskFilter.h +2 -0
  43. package/cpp/skia/include/ports/SkFontMgr_android_ndk.h +25 -0
  44. package/cpp/skia/include/ports/SkFontMgr_fontconfig.h +4 -2
  45. package/cpp/skia/include/ports/SkFontScanner_Fontations.h +15 -0
  46. package/cpp/skia/include/ports/SkFontScanner_FreeType.h +15 -0
  47. package/cpp/skia/include/private/SkExif.h +14 -0
  48. package/cpp/skia/include/private/SkPathRef.h +36 -0
  49. package/cpp/skia/include/private/base/SkFeatures.h +4 -0
  50. package/cpp/skia/include/private/base/SkSpan_impl.h +1 -3
  51. package/cpp/skia/modules/skcms/src/skcms_internals.h +3 -0
  52. package/cpp/skia/src/base/SkMathPriv.h +1 -8
  53. package/ios/RNSkia-iOS/RNSkMetalCanvasProvider.h +1 -2
  54. package/ios/RNSkia-iOS/RNSkMetalCanvasProvider.mm +25 -19
  55. package/ios/RNSkia-iOS/RNSkiOSPlatformContext.mm +23 -0
  56. package/ios/RNSkia-iOS/SkiaMetalSurfaceFactory.h +23 -9
  57. package/ios/RNSkia-iOS/SkiaMetalSurfaceFactory.mm +0 -20
  58. package/libs/android/arm64-v8a/libskia.a +0 -0
  59. package/libs/android/arm64-v8a/libskottie.a +0 -0
  60. package/libs/android/armeabi-v7a/libskia.a +0 -0
  61. package/libs/android/armeabi-v7a/libskottie.a +0 -0
  62. package/libs/android/x86/libskia.a +0 -0
  63. package/libs/android/x86/libskottie.a +0 -0
  64. package/libs/android/x86_64/libskia.a +0 -0
  65. package/libs/android/x86_64/libskottie.a +0 -0
  66. package/libs/ios/libskia.xcframework/ios-arm64_arm64e/libskia.a +0 -0
  67. package/libs/ios/libskia.xcframework/ios-arm64_arm64e_x86_64-simulator/libskia.a +0 -0
  68. package/libs/ios/libskottie.xcframework/ios-arm64_arm64e/libskottie.a +0 -0
  69. package/libs/ios/libskottie.xcframework/ios-arm64_arm64e_x86_64-simulator/libskottie.a +0 -0
  70. package/libs/ios/libskparagraph.xcframework/ios-arm64_arm64e/libskparagraph.a +0 -0
  71. package/libs/ios/libskparagraph.xcframework/ios-arm64_arm64e_x86_64-simulator/libskparagraph.a +0 -0
  72. package/libs/ios/libsksg.xcframework/ios-arm64_arm64e/libsksg.a +0 -0
  73. package/libs/ios/libsksg.xcframework/ios-arm64_arm64e_x86_64-simulator/libsksg.a +0 -0
  74. package/libs/ios/libskshaper.xcframework/Info.plist +5 -5
  75. package/libs/ios/libskshaper.xcframework/ios-arm64_arm64e/libskshaper.a +0 -0
  76. package/libs/ios/libskshaper.xcframework/ios-arm64_arm64e_x86_64-simulator/libskshaper.a +0 -0
  77. package/libs/ios/libskunicode_core.xcframework/Info.plist +5 -5
  78. package/libs/ios/libskunicode_core.xcframework/ios-arm64_arm64e/libskunicode_core.a +0 -0
  79. package/libs/ios/libskunicode_core.xcframework/ios-arm64_arm64e_x86_64-simulator/libskunicode_core.a +0 -0
  80. package/libs/ios/libskunicode_libgrapheme.xcframework/Info.plist +5 -5
  81. package/libs/ios/libskunicode_libgrapheme.xcframework/ios-arm64_arm64e/libskunicode_libgrapheme.a +0 -0
  82. package/libs/ios/libskunicode_libgrapheme.xcframework/ios-arm64_arm64e_x86_64-simulator/libskunicode_libgrapheme.a +0 -0
  83. package/libs/ios/libsvg.xcframework/ios-arm64_arm64e/libsvg.a +0 -0
  84. package/libs/ios/libsvg.xcframework/ios-arm64_arm64e_x86_64-simulator/libsvg.a +0 -0
  85. package/package.json +1 -1
  86. package/react-native-skia.podspec +35 -9
  87. package/src/renderer/__tests__/e2e/SVG.spec.tsx +2 -1
@@ -0,0 +1,127 @@
1
+ #pragma once
2
+
3
+ #include "webgpu/webgpu_cpp.h"
4
+
5
+ #include "dawn/dawn_proc.h"
6
+ #include "dawn/native/DawnNative.h"
7
+
8
+ #include "include/core/SkColorType.h"
9
+ #include "include/gpu/graphite/dawn/DawnBackendContext.h"
10
+
11
+ namespace DawnUtils {
12
+
13
+ #ifdef __APPLE__
14
+ static const SkColorType PreferedColorType = kBGRA_8888_SkColorType;
15
+ static const wgpu::TextureFormat PreferredTextureFormat =
16
+ wgpu::TextureFormat::BGRA8Unorm;
17
+ #else
18
+ static const SkColorType PreferedColorType = kRGBA_8888_SkColorType;
19
+ static const wgpu::TextureFormat PreferredTextureFormat =
20
+ wgpu::TextureFormat::RGBA8Unorm;
21
+ #endif
22
+
23
+ inline skgpu::graphite::DawnBackendContext
24
+ createDawnBackendContext(dawn::native::Instance *instance) {
25
+
26
+ auto useTintIR = false;
27
+ static constexpr const char *kToggles[] = {
28
+ "allow_unsafe_apis",
29
+ "use_user_defined_labels_in_backend",
30
+ "disable_robustness",
31
+ "use_tint_ir",
32
+ };
33
+ wgpu::DawnTogglesDescriptor togglesDesc;
34
+ togglesDesc.enabledToggleCount = std::size(kToggles) - (useTintIR ? 0 : 1);
35
+ togglesDesc.enabledToggles = kToggles;
36
+
37
+ wgpu::RequestAdapterOptions options;
38
+ #ifdef __APPLE__
39
+ constexpr auto kDefaultBackendType = wgpu::BackendType::Metal;
40
+ #elif __ANDROID__
41
+ constexpr auto kDefaultBackendType = wgpu::BackendType::Vulkan;
42
+ #endif
43
+ options.backendType = kDefaultBackendType;
44
+ options.nextInChain = &togglesDesc;
45
+
46
+ std::vector<dawn::native::Adapter> adapters =
47
+ instance->EnumerateAdapters(&options);
48
+ if (adapters.empty()) {
49
+ throw std::runtime_error("No matching adapter found");
50
+ }
51
+
52
+ wgpu::Adapter adapter = adapters[0].Get();
53
+
54
+ std::vector<wgpu::FeatureName> features;
55
+ if (adapter.HasFeature(wgpu::FeatureName::MSAARenderToSingleSampled)) {
56
+ features.push_back(wgpu::FeatureName::MSAARenderToSingleSampled);
57
+ }
58
+ if (adapter.HasFeature(wgpu::FeatureName::TransientAttachments)) {
59
+ features.push_back(wgpu::FeatureName::TransientAttachments);
60
+ }
61
+ if (adapter.HasFeature(wgpu::FeatureName::Unorm16TextureFormats)) {
62
+ features.push_back(wgpu::FeatureName::Unorm16TextureFormats);
63
+ }
64
+ if (adapter.HasFeature(wgpu::FeatureName::DualSourceBlending)) {
65
+ features.push_back(wgpu::FeatureName::DualSourceBlending);
66
+ }
67
+ if (adapter.HasFeature(wgpu::FeatureName::FramebufferFetch)) {
68
+ features.push_back(wgpu::FeatureName::FramebufferFetch);
69
+ }
70
+ if (adapter.HasFeature(wgpu::FeatureName::BufferMapExtendedUsages)) {
71
+ features.push_back(wgpu::FeatureName::BufferMapExtendedUsages);
72
+ }
73
+ if (adapter.HasFeature(wgpu::FeatureName::TextureCompressionETC2)) {
74
+ features.push_back(wgpu::FeatureName::TextureCompressionETC2);
75
+ }
76
+ if (adapter.HasFeature(wgpu::FeatureName::TextureCompressionBC)) {
77
+ features.push_back(wgpu::FeatureName::TextureCompressionBC);
78
+ }
79
+ if (adapter.HasFeature(wgpu::FeatureName::R8UnormStorage)) {
80
+ features.push_back(wgpu::FeatureName::R8UnormStorage);
81
+ }
82
+ if (adapter.HasFeature(wgpu::FeatureName::DawnLoadResolveTexture)) {
83
+ features.push_back(wgpu::FeatureName::DawnLoadResolveTexture);
84
+ }
85
+ if (adapter.HasFeature(wgpu::FeatureName::DawnPartialLoadResolveTexture)) {
86
+ features.push_back(wgpu::FeatureName::DawnPartialLoadResolveTexture);
87
+ }
88
+ #ifdef __APPLE__
89
+ if (adapter.HasFeature(wgpu::FeatureName::SharedTextureMemoryIOSurface)) {
90
+ features.push_back(wgpu::FeatureName::SharedTextureMemoryIOSurface);
91
+ }
92
+ #else
93
+ if (adapter.HasFeature(
94
+ wgpu::FeatureName::SharedTextureMemoryAHardwareBuffer)) {
95
+ features.push_back(wgpu::FeatureName::SharedTextureMemoryAHardwareBuffer);
96
+ }
97
+ #endif
98
+
99
+ wgpu::DeviceDescriptor desc;
100
+ desc.requiredFeatureCount = features.size();
101
+ desc.requiredFeatures = features.data();
102
+ desc.nextInChain = &togglesDesc;
103
+ desc.SetDeviceLostCallback(
104
+ wgpu::CallbackMode::AllowSpontaneous,
105
+ [](const wgpu::Device &, wgpu::DeviceLostReason reason,
106
+ const char *message) {
107
+ if (reason != wgpu::DeviceLostReason::Destroyed) {
108
+ SK_ABORT("Device lost: %s\n", message);
109
+ }
110
+ });
111
+ desc.SetUncapturedErrorCallback(
112
+ [](const wgpu::Device &, wgpu::ErrorType, const char *message) {
113
+ SkDebugf("Device error: %s\n", message);
114
+ });
115
+
116
+ wgpu::Device device = adapter.CreateDevice(&desc);
117
+ SkASSERT(device);
118
+
119
+ skgpu::graphite::DawnBackendContext backendContext;
120
+ backendContext.fInstance = wgpu::Instance(instance->Get());
121
+ backendContext.fDevice = device;
122
+ backendContext.fQueue = device.GetQueue();
123
+
124
+ return backendContext;
125
+ }
126
+
127
+ } // namespace DawnUtils
@@ -0,0 +1,19 @@
1
+ #include "DawnWindowContext.h"
2
+
3
+ #include "DawnContext.h"
4
+
5
+ namespace RNSkia {
6
+
7
+ void DawnWindowContext::present() {
8
+ auto recording = _recorder->snap();
9
+ if (!recording) {
10
+ throw std::runtime_error("Failed to create graphite recording");
11
+ }
12
+ DawnContext::getInstance().submitRecording(recording.get());
13
+ #ifdef __APPLE__
14
+ dawn::native::metal::WaitForCommandsToBeScheduled(_device.Get());
15
+ #endif
16
+ _surface.Present();
17
+ }
18
+
19
+ } // namespace RNSkia
@@ -0,0 +1,77 @@
1
+ #pragma once
2
+
3
+ #include "DawnUtils.h"
4
+ #include "WindowContext.h"
5
+
6
+ #include "dawn/native/MetalBackend.h"
7
+ #include "webgpu/webgpu_cpp.h"
8
+
9
+ #include "include/core/SkColorSpace.h"
10
+
11
+ #include "include/gpu/graphite/BackendTexture.h"
12
+ #include "include/gpu/graphite/Context.h"
13
+ #include "include/gpu/graphite/ContextOptions.h"
14
+ #include "include/gpu/graphite/GraphiteTypes.h"
15
+ #include "include/gpu/graphite/Recorder.h"
16
+ #include "include/gpu/graphite/Recording.h"
17
+ #include "include/gpu/graphite/Surface.h"
18
+ #include "include/gpu/graphite/dawn/DawnBackendContext.h"
19
+ #include "include/gpu/graphite/dawn/DawnTypes.h"
20
+ #include "include/gpu/graphite/dawn/DawnUtils.h"
21
+
22
+ namespace RNSkia {
23
+
24
+ class DawnWindowContext : public WindowContext {
25
+ public:
26
+ DawnWindowContext(skgpu::graphite::Recorder *recorder, wgpu::Device device,
27
+ wgpu::Surface surface, int width, int height)
28
+ : _recorder(recorder), _device(device), _surface(surface), _width(width),
29
+ _height(height) {
30
+ wgpu::SurfaceConfiguration config;
31
+ config.device = _device;
32
+ config.format = DawnUtils::PreferredTextureFormat;
33
+ config.width = _width;
34
+ config.height = _height;
35
+ #ifdef __APPLE__
36
+ config.alphaMode = wgpu::CompositeAlphaMode::Premultiplied;
37
+ #endif
38
+ _surface.Configure(&config);
39
+ }
40
+
41
+ sk_sp<SkSurface> getSurface() override {
42
+ wgpu::SurfaceTexture surfaceTexture;
43
+ _surface.GetCurrentTexture(&surfaceTexture);
44
+ auto texture = surfaceTexture.texture;
45
+ skgpu::graphite::DawnTextureInfo info(
46
+ /*sampleCount=*/1, skgpu::Mipmapped::kNo,
47
+ DawnUtils::PreferredTextureFormat, texture.GetUsage(),
48
+ wgpu::TextureAspect::All);
49
+ auto backendTex = skgpu::graphite::BackendTextures::MakeDawn(texture.Get());
50
+ sk_sp<SkColorSpace> colorSpace = SkColorSpace::MakeSRGB();
51
+ SkSurfaceProps surfaceProps;
52
+ auto surface = SkSurfaces::WrapBackendTexture(_recorder, backendTex,
53
+ DawnUtils::PreferedColorType,
54
+ colorSpace, &surfaceProps);
55
+ return surface;
56
+ }
57
+
58
+ void present() override;
59
+
60
+ void resize(int width, int height) override {
61
+ throw std::runtime_error("resize not implemented yet");
62
+ }
63
+
64
+ int getWidth() override { return _width; }
65
+
66
+ int getHeight() override { return _height; }
67
+
68
+ private:
69
+ skgpu::graphite::Recorder *_recorder;
70
+ // TODO: keep device in DawnContext? Do we need it for resizing?
71
+ wgpu::Device _device;
72
+ wgpu::Surface _surface;
73
+ int _width;
74
+ int _height;
75
+ };
76
+
77
+ } // namespace RNSkia
@@ -0,0 +1,100 @@
1
+ #pragma once
2
+
3
+ #include "include/core/SkCanvas.h"
4
+ #include "include/core/SkImage.h"
5
+
6
+ #include "include/core/SkTiledImageUtils.h"
7
+ #include "include/gpu/graphite/Image.h"
8
+ #include "include/gpu/graphite/ImageProvider.h"
9
+ #include "include/gpu/graphite/Recorder.h"
10
+ #include "src/core/SkLRUCache.h"
11
+
12
+ namespace RNSkia {
13
+
14
+ // Currently, we give each new Recorder its own ImageProvider. This means we
15
+ // don't have to deal w/ any threading issues.
16
+ // TODO: We should probably have this class generate and report some cache stats
17
+ // TODO: Hook up to listener system?
18
+ // TODO: add testing of a single ImageProvider passed to multiple recorders
19
+ class ImageProvider : public skgpu::graphite::ImageProvider {
20
+ public:
21
+ ImageProvider() : fCache(kDefaultNumCachedImages) {}
22
+ ~ImageProvider() override {}
23
+
24
+ static sk_sp<ImageProvider> Make() { return sk_ref_sp(new ImageProvider); }
25
+
26
+ sk_sp<SkImage>
27
+ findOrCreate(skgpu::graphite::Recorder *recorder, const SkImage *image,
28
+ SkImage::RequiredProperties requiredProps) override {
29
+ if (!requiredProps.fMipmapped) {
30
+ // If no mipmaps are required, check to see if we have a mipmapped version
31
+ // anyway - since it can be used in that case.
32
+ // TODO: we could get fancy and, if ever a mipmapped key eclipsed a
33
+ // non-mipmapped key, we could remove the hidden non-mipmapped key/image
34
+ // from the cache.
35
+ ImageKey mipMappedKey(image, /* mipmapped= */ true);
36
+ auto result = fCache.find(mipMappedKey);
37
+ if (result) {
38
+ return *result;
39
+ }
40
+ }
41
+
42
+ ImageKey key(image, requiredProps.fMipmapped);
43
+
44
+ auto result = fCache.find(key);
45
+ if (result) {
46
+ return *result;
47
+ }
48
+
49
+ sk_sp<SkImage> newImage =
50
+ SkImages::TextureFromImage(recorder, image, requiredProps);
51
+ if (!newImage) {
52
+ return nullptr;
53
+ }
54
+
55
+ result = fCache.insert(key, std::move(newImage));
56
+ SkASSERT(result);
57
+
58
+ return *result;
59
+ }
60
+
61
+ private:
62
+ static constexpr int kDefaultNumCachedImages = 256;
63
+
64
+ class ImageKey {
65
+ public:
66
+ ImageKey(const SkImage *image, bool mipmapped) {
67
+ uint32_t flags = mipmapped ? 0x1 : 0x0;
68
+ SkTiledImageUtils::GetImageKeyValues(image, &fValues[1]);
69
+ fValues[kNumValues - 1] = flags;
70
+ fValues[0] =
71
+ SkChecksum::Hash32(&fValues[1], (kNumValues - 1) * sizeof(uint32_t));
72
+ }
73
+
74
+ uint32_t hash() const { return fValues[0]; }
75
+
76
+ bool operator==(const ImageKey &other) const {
77
+ for (int i = 0; i < kNumValues; ++i) {
78
+ if (fValues[i] != other.fValues[i]) {
79
+ return false;
80
+ }
81
+ }
82
+
83
+ return true;
84
+ }
85
+ bool operator!=(const ImageKey &other) const { return !(*this == other); }
86
+
87
+ private:
88
+ static const int kNumValues = SkTiledImageUtils::kNumImageKeyValues + 2;
89
+
90
+ uint32_t fValues[kNumValues];
91
+ };
92
+
93
+ struct ImageHash {
94
+ size_t operator()(const ImageKey &key) const { return key.hash(); }
95
+ };
96
+
97
+ SkLRUCache<ImageKey, sk_sp<SkImage>, ImageHash> fCache;
98
+ };
99
+
100
+ } // namespace RNSkia
@@ -108,7 +108,13 @@ public:
108
108
  } else {
109
109
  image = _surface->makeImageSnapshot();
110
110
  }
111
+ #if defined(SK_GRAPHITE)
112
+ DawnContext::getInstance().submitRecording(
113
+ _surface->recorder()->snap().get());
114
+ return DawnContext::getInstance().MakeRasterImage(image);
115
+ #else
111
116
  return image->makeNonTextureImage();
117
+ #endif
112
118
  }
113
119
 
114
120
  /**
@@ -110,6 +110,19 @@ public:
110
110
  */
111
111
  int getFrameCount() const { return fFrameCount; }
112
112
 
113
+ /**
114
+ * Change the filter mode.
115
+ *
116
+ * By default, the image will apply bilinear filtering when drawing in the
117
+ * OnDraw method.
118
+ */
119
+ void setFilterMode(SkFilterMode filterMode);
120
+
121
+ /**
122
+ * Return the filter mode used for sampling when drawing.
123
+ */
124
+ SkFilterMode getFilterMode() const { return fFilterMode; }
125
+
113
126
  protected:
114
127
  SkRect onGetBounds() override;
115
128
  void onDraw(SkCanvas*) override;
@@ -152,6 +165,7 @@ private:
152
165
  Frame fRestoreFrame;
153
166
  int fRepetitionCount;
154
167
  int fRepetitionsCompleted;
168
+ SkFilterMode fFilterMode = SkFilterMode::kLinear;
155
169
 
156
170
  SkAnimatedImage(std::unique_ptr<SkAndroidCodec>, const SkImageInfo& requestedInfo,
157
171
  SkIRect cropRect, sk_sp<SkPicture> postProcess);
@@ -18,13 +18,15 @@ class SkStream;
18
18
 
19
19
  namespace SkAvifDecoder {
20
20
 
21
- /** Returns true if this data claims to be a AVIF image. */
21
+ namespace LibAvif {
22
+
23
+ /** Returns true if this data claims to be an AVIF image. */
22
24
  SK_API bool IsAvif(const void*, size_t);
23
25
 
24
26
  /**
25
- * Attempts to decode the given bytes as a AVIF.
27
+ * Attempts to decode the given bytes as an AVIF.
26
28
  *
27
- * If the bytes are not a AVIF, returns nullptr.
29
+ * If the bytes are not an AVIF, returns nullptr.
28
30
  *
29
31
  * DecodeContext is ignored
30
32
  */
@@ -39,6 +41,40 @@ inline constexpr SkCodecs::Decoder Decoder() {
39
41
  return { "avif", IsAvif, Decode };
40
42
  }
41
43
 
44
+ } // namespace LibAvif
45
+
46
+ // This function is in the root SkAvifDecoder namespace. It simply routes
47
+ // everything through the LibAvif namespace and exists for backwards
48
+ // compatibility.
49
+ inline constexpr SkCodecs::Decoder Decoder() {
50
+ return { "avif", LibAvif::IsAvif, LibAvif::Decode };
51
+ }
52
+
53
+ namespace CrabbyAvif {
54
+
55
+ /** Returns true if this data claims to be an AVIF image. */
56
+ SK_API bool IsAvif(const void*, size_t);
57
+
58
+ /**
59
+ * Attempts to decode the given bytes as an AVIF.
60
+ *
61
+ * If the bytes are not an AVIF, returns nullptr.
62
+ *
63
+ * DecodeContext is ignored
64
+ */
65
+ SK_API std::unique_ptr<SkCodec> Decode(std::unique_ptr<SkStream>,
66
+ SkCodec::Result*,
67
+ SkCodecs::DecodeContext = nullptr);
68
+ SK_API std::unique_ptr<SkCodec> Decode(sk_sp<SkData>,
69
+ SkCodec::Result*,
70
+ SkCodecs::DecodeContext = nullptr);
71
+
72
+ inline constexpr SkCodecs::Decoder Decoder() {
73
+ return { "avif", IsAvif, Decode };
74
+ }
75
+
76
+ } // namespace CrabbyAvif
77
+
42
78
  } // namespace SkAvifDecoder
43
79
 
44
80
  #endif // SkAvifDecoder_DEFINED
@@ -239,6 +239,16 @@ public:
239
239
  return this->getEncodedInfo().profile();
240
240
  }
241
241
 
242
+ /**
243
+ * Whether the encoded input uses 16 or more bits per component.
244
+ */
245
+ bool hasHighBitDepthEncodedData() const {
246
+ // API design note: We don't return `bitsPerComponent` because it may be
247
+ // misleading in some cases - see https://crbug.com/359350061#comment4
248
+ // for more details.
249
+ return this->getEncodedInfo().bitsPerComponent() >= 16;
250
+ }
251
+
242
252
  /**
243
253
  * Returns the image orientation stored in the EXIF data.
244
254
  * If there is no EXIF data, or if we cannot read the EXIF data, returns kTopLeft.
@@ -637,6 +647,12 @@ public:
637
647
  * Return the number of frames in the image.
638
648
  *
639
649
  * May require reading through the stream.
650
+ *
651
+ * Note that some codecs may be unable to gather `FrameInfo` for all frames
652
+ * in case of `kIncompleteInput`. For such codecs `getFrameCount` may
653
+ * initially report a low frame count. After the underlying `SkStream`
654
+ * provides additional data, then calling `getFrameCount` again may return
655
+ * an updated, increased frame count.
640
656
  */
641
657
  int getFrameCount() {
642
658
  return this->onGetFrameCount();
@@ -90,9 +90,10 @@
90
90
  integrate with their histogram collection backend.
91
91
  */
92
92
  //#define SK_HISTOGRAM_BOOLEAN(name, sample)
93
- //#define SK_HISTOGRAM_ENUMERATION(name, sample, enum_size)
94
- //#define SK_HISTOGRAM_EXACT_LINEAR(name, sample, value_max)
93
+ //#define SK_HISTOGRAM_ENUMERATION(name, sampleEnum, enumSize)
94
+ //#define SK_HISTOGRAM_EXACT_LINEAR(name, sample, valueMax)
95
95
  //#define SK_HISTOGRAM_MEMORY_KB(name, sample)
96
+ //#define SK_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES(name, sampleUSec, minUSec, maxUSec, bucketCount)
96
97
 
97
98
  // To use smaller but slower mipmap builder
98
99
  //#define SK_USE_DRAWING_MIPMAP_DOWNSAMPLER
@@ -28,6 +28,7 @@
28
28
  #include "include/core/SkSpan.h"
29
29
  #include "include/core/SkString.h"
30
30
  #include "include/core/SkSurfaceProps.h"
31
+ #include "include/core/SkTileMode.h"
31
32
  #include "include/core/SkTypes.h"
32
33
  #include "include/private/base/SkCPUTypes.h"
33
34
  #include "include/private/base/SkDeque.h"
@@ -700,7 +701,8 @@ public:
700
701
  @return SaveLayerRec with empty fBackdrop
701
702
  */
702
703
  SaveLayerRec(const SkRect* bounds, const SkPaint* paint, SaveLayerFlags saveLayerFlags = 0)
703
- : SaveLayerRec(bounds, paint, nullptr, nullptr, 1.f, saveLayerFlags, /*filters=*/{}) {}
704
+ : SaveLayerRec(bounds, paint, nullptr, nullptr, 1.f, SkTileMode::kClamp,
705
+ saveLayerFlags, /*filters=*/{}) {}
704
706
 
705
707
  /** Sets fBounds, fPaint, fBackdrop, and fSaveLayerFlags.
706
708
 
@@ -716,9 +718,10 @@ public:
716
718
  */
717
719
  SaveLayerRec(const SkRect* bounds, const SkPaint* paint, const SkImageFilter* backdrop,
718
720
  SaveLayerFlags saveLayerFlags)
719
- : SaveLayerRec(bounds, paint, backdrop, nullptr, 1.f, saveLayerFlags, /*filters=*/{}) {}
721
+ : SaveLayerRec(bounds, paint, backdrop, nullptr, 1.f, SkTileMode::kClamp,
722
+ saveLayerFlags, /*filters=*/{}) {}
720
723
 
721
- /** Sets fBounds, fColorSpace, and fSaveLayerFlags.
724
+ /** Sets fBounds, fBackdrop, fColorSpace, and fSaveLayerFlags.
722
725
 
723
726
  @param bounds layer dimensions; may be nullptr
724
727
  @param paint applied to layer when overlaying prior layer;
@@ -738,15 +741,44 @@ public:
738
741
  */
739
742
  SaveLayerRec(const SkRect* bounds, const SkPaint* paint, const SkImageFilter* backdrop,
740
743
  const SkColorSpace* colorSpace, SaveLayerFlags saveLayerFlags)
741
- : SaveLayerRec(bounds, paint, backdrop, colorSpace, 1.f, saveLayerFlags, /*filters=*/{}) {}
744
+ : SaveLayerRec(bounds, paint, backdrop, colorSpace, 1.f, SkTileMode::kClamp,
745
+ saveLayerFlags, /*filters=*/{}) {}
746
+
747
+
748
+ /** Sets fBounds, fBackdrop, fBackdropTileMode, fColorSpace, and fSaveLayerFlags.
749
+
750
+ @param bounds layer dimensions; may be nullptr
751
+ @param paint applied to layer when overlaying prior layer;
752
+ may be nullptr
753
+ @param backdrop If not null, this causes the current layer to be filtered by
754
+ backdrop, and then drawn into the new layer
755
+ (respecting the current clip).
756
+ If null, the new layer is initialized with transparent-black.
757
+ @param backdropTileMode If the 'backdrop' is not null, or 'saveLayerFlags' has
758
+ kInitWithPrevious set, this tile mode is used when the new layer
759
+ would read outside the backdrop image's available content.
760
+ @param colorSpace If not null, when the layer is restored, a color space
761
+ conversion will be applied from this color space to the parent's
762
+ color space. The restore paint and backdrop filters will be
763
+ applied in this color space.
764
+ If null, the new layer will inherit the color space from its
765
+ parent.
766
+ @param saveLayerFlags SaveLayerRec options to modify layer
767
+ @return SaveLayerRec fully specified
768
+ */
769
+ SaveLayerRec(const SkRect* bounds, const SkPaint* paint, const SkImageFilter* backdrop,
770
+ SkTileMode backdropTileMode, const SkColorSpace* colorSpace,
771
+ SaveLayerFlags saveLayerFlags)
772
+ : SaveLayerRec(bounds, paint, backdrop, colorSpace, 1.f, backdropTileMode,
773
+ saveLayerFlags, /*filters=*/{}) {}
742
774
 
743
775
  /** hints at layer size limit */
744
- const SkRect* fBounds = nullptr;
776
+ const SkRect* fBounds = nullptr;
745
777
 
746
778
  /** modifies overlay */
747
- const SkPaint* fPaint = nullptr;
779
+ const SkPaint* fPaint = nullptr;
748
780
 
749
- FilterSpan fFilters = {};
781
+ FilterSpan fFilters = {};
750
782
 
751
783
  /**
752
784
  * If not null, this triggers the same initialization behavior as setting
@@ -754,17 +786,24 @@ public:
754
786
  * the new layer, rather than initializing the new layer with transparent-black.
755
787
  * This is then filtered by fBackdrop (respecting the current clip).
756
788
  */
757
- const SkImageFilter* fBackdrop = nullptr;
789
+ const SkImageFilter* fBackdrop = nullptr;
790
+
791
+ /**
792
+ * If the layer is initialized with prior content (and/or with a backdrop filter) and this
793
+ * would require sampling outside of the available backdrop, this is the tilemode applied
794
+ * to the boundary of the prior layer's image.
795
+ */
796
+ SkTileMode fBackdropTileMode = SkTileMode::kClamp;
758
797
 
759
798
  /**
760
799
  * If not null, this triggers a color space conversion when the layer is restored. It
761
800
  * will be as if the layer's contents are drawn in this color space. Filters from
762
801
  * fBackdrop and fPaint will be applied in this color space.
763
802
  */
764
- const SkColorSpace* fColorSpace = nullptr;
803
+ const SkColorSpace* fColorSpace = nullptr;
765
804
 
766
805
  /** preserves LCD text, creates with prior layer contents */
767
- SaveLayerFlags fSaveLayerFlags = 0;
806
+ SaveLayerFlags fSaveLayerFlags = 0;
768
807
 
769
808
  private:
770
809
  friend class SkCanvas;
@@ -775,12 +814,14 @@ public:
775
814
  const SkImageFilter* backdrop,
776
815
  const SkColorSpace* colorSpace,
777
816
  SkScalar backdropScale,
817
+ SkTileMode backdropTileMode,
778
818
  SaveLayerFlags saveLayerFlags,
779
819
  FilterSpan filters)
780
820
  : fBounds(bounds)
781
821
  , fPaint(paint)
782
822
  , fFilters(filters)
783
823
  , fBackdrop(backdrop)
824
+ , fBackdropTileMode(backdropTileMode)
784
825
  , fColorSpace(colorSpace)
785
826
  , fSaveLayerFlags(saveLayerFlags)
786
827
  , fExperimentalBackdropScale(backdropScale) {
@@ -2591,12 +2632,16 @@ private:
2591
2632
  * before any filtering, or as part of the copy, and is then drawn with 1/scaleFactor to 'dst'.
2592
2633
  * Must be 1.0 if 'compat' is kYes (i.e. any scale factor has already been baked into the
2593
2634
  * relative transforms between the devices).
2635
+ *
2636
+ * 'srcTileMode' is the tile mode to apply to the boundary of the 'src' image when insufficient
2637
+ * content is available. It defaults to kDecal for the regular saveLayer() case.
2594
2638
  */
2595
2639
  void internalDrawDeviceWithFilter(SkDevice* src, SkDevice* dst,
2596
2640
  FilterSpan filters, const SkPaint& paint,
2597
2641
  DeviceCompatibleWithFilter compat,
2598
2642
  const SkColorInfo& filterColorInfo,
2599
2643
  SkScalar scaleFactor = 1.f,
2644
+ SkTileMode srcTileMode = SkTileMode::kDecal,
2600
2645
  bool srcIsCoverageLayer = false);
2601
2646
 
2602
2647
  /*