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
<Svg height="200" width="200">
  <Filter id="filter">
    <FeColorMatrix type="matrix" values="78 -70 -7 0 0 -21 29 -7 0 0 -21 -70 0 0 0 0 0 0 1 0"/>
    <FeColorMatrix type="matrix" values="0.2126, 0.7152, 0.0722, 0, 0, 0.2126, 0.7152, 0.0722, 0, 0, 0.2126, 0.7152, 0, 0, 0, 0, 0, 0, 1, 0"/>
  </Filter>
  <Rect width="200" height="200" fill="red" filter="url(#filter)"/>
</Svg>
```

| Web | iOS before changes | iOS after changes |
| --- | --- | --- |
| <img width="242" alt="image"
src="https://github.com/user-attachments/assets/dc683341-b3ca-4fab-86d8-cf72b15c13d4">
| <img width="237" alt="image"
src="https://github.com/user-attachments/assets/d4a1af5d-ae67-4ed9-9dbd-d03540b2c63c">
| <img width="249" alt="image"
src="https://github.com/user-attachments/assets/83e856a6-5bcc-4534-ad7b-a1f188434e1c">
|
This commit is contained in:
Jakub Grzywacz
2024-07-25 10:15:08 +02:00
committed by GitHub
parent 9a2cd3d855
commit 00e492e8cf
3 changed files with 37 additions and 1 deletions
+6 -1
View File
@@ -1,5 +1,6 @@
#import "RNSVGFilter.h"
#import "RNSVGFilterPrimitive.h"
#import "RNSVGRenderUtils.h"
#ifdef RCT_NEW_ARCH_ENABLED
#import <React/RCTConversions.h>
@@ -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];
}