From 00e492e8cfb074e8584709986e438e45fc4f9db1 Mon Sep 17 00:00:00 2001 From: Jakub Grzywacz Date: Thu, 25 Jul 2024 10:15:08 +0200 Subject: [PATCH] fix: applying multiple filters on iOS (#2366) # Summary Applying multiple `FeColorFilter` instances can cause unexpected behavior on iOS, likely due to a bug in `CoreImage` where the `CIImage` recipe isn't applied step by step as it should be. This fix ensures that the filter result is rendered after each application by converting the image to `CGImage` and then back to `CIImage`. ## Test Plan With this simple test, we can prove that these changes are working ```tsx ``` | Web | iOS before changes | iOS after changes | | --- | --- | --- | | image | image | image | --- apple/Filters/RNSVGFilter.mm | 7 ++++++- apps/test-examples/App.js | 1 + apps/test-examples/src/Test2366.tsx | 30 +++++++++++++++++++++++++++++ 3 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 apps/test-examples/src/Test2366.tsx diff --git a/apple/Filters/RNSVGFilter.mm b/apple/Filters/RNSVGFilter.mm index c5c7570f..5257e5bd 100644 --- a/apple/Filters/RNSVGFilter.mm +++ b/apple/Filters/RNSVGFilter.mm @@ -1,5 +1,6 @@ #import "RNSVGFilter.h" #import "RNSVGFilterPrimitive.h" +#import "RNSVGRenderUtils.h" #ifdef RCT_NEW_ARCH_ENABLED #import @@ -97,7 +98,11 @@ using namespace facebook::react; for (RNSVGNode *node in self.subviews) { if ([node isKindOfClass:[RNSVGFilterPrimitive class]]) { currentFilter = (RNSVGFilterPrimitive *)node; - result = [currentFilter applyFilter:resultsMap previousFilterResult:result]; + CGImageRef cgResult = [[RNSVGRenderUtils sharedCIContext] createCGImage:[currentFilter applyFilter:resultsMap + previousFilterResult:result] + fromRect:[result extent]]; + result = [CIImage imageWithCGImage:cgResult]; + CGImageRelease(cgResult); if (currentFilter.result) { [resultsMap setObject:result forKey:currentFilter.result]; } diff --git a/apps/test-examples/App.js b/apps/test-examples/App.js index e9211daf..c5a50dc9 100644 --- a/apps/test-examples/App.js +++ b/apps/test-examples/App.js @@ -22,6 +22,7 @@ import Test2248 from './src/Test2248'; import Test2266 from './src/Test2266'; import Test2276 from './src/Test2276'; import Test2327 from './src/Test2327'; +import Test2366 from './src/Test2366'; export default function App() { return ; diff --git a/apps/test-examples/src/Test2366.tsx b/apps/test-examples/src/Test2366.tsx new file mode 100644 index 00000000..a7777746 --- /dev/null +++ b/apps/test-examples/src/Test2366.tsx @@ -0,0 +1,30 @@ +import React from 'react'; +import {View} from 'react-native'; +import {FeColorMatrix, Filter, Rect, Svg} from 'react-native-svg'; + +export default () => { + return ( + + + + + + + + + + ); +};