-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
# Summary As mentioned in #2362 Introduce new filters: * `FeMerge` * `FeMergeNode` ## Example usage ```tsx <Svg width="200" height="200"> <Filter id="mergeWithOffset" width="180" height="180"> <FeOffset dx="50" dy="50" result="test" /> <FeOffset dx="100" dy="100" in="SourceGraphic" /> <FeMerge> <FeMergeNode in="SourceGraphic" /> <FeMergeNode in="test" /> <FeMergeNode /> </FeMerge> </Filter> <Rect x="0" y="0" width="100" height="100" stroke="black" fill="red" filter="url(#mergeWithOffset)" /> </Svg> ``` <img width="207" alt="image" src="https://github.com/user-attachments/assets/9cb3ded6-f939-4b2b-8ece-df54e64fe898"> ## Test Plan `Example` app -> `Filters` -> `FeMerge` ## Compatibility | OS | Implemented | | ------- | :---------: | | iOS | ✅ | | Android | ✅ | ## Checklist - [x] I have tested this on a device and a simulator - [x] I added documentation in `README.md` - [x] I updated the typed files (typescript)
- Loading branch information
Showing
25 changed files
with
508 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
package com.horcrux.svg; | ||
|
||
import android.annotation.SuppressLint; | ||
import android.graphics.Bitmap; | ||
import android.graphics.Canvas; | ||
import android.graphics.Paint; | ||
import com.facebook.react.bridge.ReactContext; | ||
import com.facebook.react.bridge.ReadableArray; | ||
import com.facebook.react.bridge.ReadableType; | ||
import java.util.HashMap; | ||
|
||
@SuppressLint("ViewConstructor") | ||
class FeMergeView extends FilterPrimitiveView { | ||
private ReadableArray mNodes; | ||
|
||
public FeMergeView(ReactContext reactContext) { | ||
super(reactContext); | ||
} | ||
|
||
public void setNodes(ReadableArray nodes) { | ||
this.mNodes = nodes; | ||
invalidate(); | ||
} | ||
|
||
@Override | ||
public Bitmap applyFilter(HashMap<String, Bitmap> resultsMap, Bitmap prevResult) { | ||
Bitmap result = | ||
Bitmap.createBitmap(prevResult.getWidth(), prevResult.getHeight(), Bitmap.Config.ARGB_8888); | ||
Canvas canvas = new Canvas(result); | ||
int nodesSize = this.mNodes.size(); | ||
for (int i = 0; i < nodesSize; i++) { | ||
Bitmap sourceFromResults = | ||
this.mNodes.getType(i) == ReadableType.String | ||
? resultsMap.get(this.mNodes.getString(i)) | ||
: prevResult; | ||
if (sourceFromResults != null) { | ||
canvas.drawBitmap(sourceFromResults, 0, 0, new Paint()); | ||
} | ||
} | ||
|
||
return result; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
48 changes: 48 additions & 0 deletions
48
android/src/paper/java/com/facebook/react/viewmanagers/RNSVGFeMergeManagerDelegate.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
/** | ||
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). | ||
* | ||
* Do not edit this file as changes may cause incorrect behavior and will be lost | ||
* once the code is regenerated. | ||
* | ||
* @generated by codegen project: GeneratePropsJavaDelegate.js | ||
*/ | ||
|
||
package com.facebook.react.viewmanagers; | ||
|
||
import android.view.View; | ||
import androidx.annotation.Nullable; | ||
import com.facebook.react.bridge.DynamicFromObject; | ||
import com.facebook.react.bridge.ReadableArray; | ||
import com.facebook.react.uimanager.BaseViewManagerDelegate; | ||
import com.facebook.react.uimanager.BaseViewManagerInterface; | ||
|
||
public class RNSVGFeMergeManagerDelegate<T extends View, U extends BaseViewManagerInterface<T> & RNSVGFeMergeManagerInterface<T>> extends BaseViewManagerDelegate<T, U> { | ||
public RNSVGFeMergeManagerDelegate(U viewManager) { | ||
super(viewManager); | ||
} | ||
@Override | ||
public void setProperty(T view, String propName, @Nullable Object value) { | ||
switch (propName) { | ||
case "x": | ||
mViewManager.setX(view, new DynamicFromObject(value)); | ||
break; | ||
case "y": | ||
mViewManager.setY(view, new DynamicFromObject(value)); | ||
break; | ||
case "width": | ||
mViewManager.setWidth(view, new DynamicFromObject(value)); | ||
break; | ||
case "height": | ||
mViewManager.setHeight(view, new DynamicFromObject(value)); | ||
break; | ||
case "result": | ||
mViewManager.setResult(view, value == null ? null : (String) value); | ||
break; | ||
case "nodes": | ||
mViewManager.setNodes(view, (ReadableArray) value); | ||
break; | ||
default: | ||
super.setProperty(view, propName, value); | ||
} | ||
} | ||
} |
24 changes: 24 additions & 0 deletions
24
android/src/paper/java/com/facebook/react/viewmanagers/RNSVGFeMergeManagerInterface.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
/** | ||
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). | ||
* | ||
* Do not edit this file as changes may cause incorrect behavior and will be lost | ||
* once the code is regenerated. | ||
* | ||
* @generated by codegen project: GeneratePropsJavaInterface.js | ||
*/ | ||
|
||
package com.facebook.react.viewmanagers; | ||
|
||
import android.view.View; | ||
import androidx.annotation.Nullable; | ||
import com.facebook.react.bridge.Dynamic; | ||
import com.facebook.react.bridge.ReadableArray; | ||
|
||
public interface RNSVGFeMergeManagerInterface<T extends View> { | ||
void setX(T view, Dynamic value); | ||
void setY(T view, Dynamic value); | ||
void setWidth(T view, Dynamic value); | ||
void setHeight(T view, Dynamic value); | ||
void setResult(T view, @Nullable String value); | ||
void setNodes(T view, @Nullable ReadableArray value); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
#import "RNSVGFilterPrimitive.h" | ||
|
||
@interface RNSVGFeMerge : RNSVGFilterPrimitive | ||
|
||
@property (nonatomic, copy) NSArray<NSString *> *nodes; | ||
|
||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
#import "RNSVGFeMerge.h" | ||
|
||
#ifdef RCT_NEW_ARCH_ENABLED | ||
#import <React/RCTConversions.h> | ||
#import <React/RCTFabricComponentsPlugins.h> | ||
#import <react/renderer/components/rnsvg/ComponentDescriptors.h> | ||
#import <react/renderer/components/view/conversions.h> | ||
#import "RNSVGFabricConversions.h" | ||
#endif // RCT_NEW_ARCH_ENABLED | ||
|
||
@implementation RNSVGFeMerge | ||
|
||
#ifdef RCT_NEW_ARCH_ENABLED | ||
using namespace facebook::react; | ||
|
||
- (instancetype)initWithFrame:(CGRect)frame | ||
{ | ||
if (self = [super initWithFrame:frame]) { | ||
static const auto defaultProps = std::make_shared<const RNSVGFeMergeProps>(); | ||
_props = defaultProps; | ||
} | ||
return self; | ||
} | ||
|
||
#pragma mark - RCTComponentViewProtocol | ||
|
||
+ (ComponentDescriptorProvider)componentDescriptorProvider | ||
{ | ||
return concreteComponentDescriptorProvider<RNSVGFeMergeComponentDescriptor>(); | ||
} | ||
|
||
- (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps | ||
{ | ||
const auto &newProps = static_cast<const RNSVGFeMergeProps &>(*props); | ||
|
||
if (newProps.nodes.size() > 0) { | ||
NSMutableArray *nodesArray = [NSMutableArray new]; | ||
for (auto node : newProps.nodes) { | ||
id json = RNSVGConvertFollyDynamicToId(node); | ||
if ([json isKindOfClass:[NSString class]]) { | ||
[nodesArray addObject:[json stringValue]]; | ||
} else { | ||
[nodesArray addObject:[NSNull null]]; | ||
} | ||
} | ||
self.nodes = nodesArray; | ||
} | ||
|
||
setCommonFilterProps(newProps, self); | ||
_props = std::static_pointer_cast<RNSVGFeMergeProps const>(props); | ||
} | ||
|
||
- (void)prepareForRecycle | ||
{ | ||
[super prepareForRecycle]; | ||
_nodes = nil; | ||
} | ||
#endif // RCT_NEW_ARCH_ENABLED | ||
|
||
- (void)setNodes:(NSArray<NSString *> *)nodes | ||
{ | ||
if (nodes == _nodes) { | ||
return; | ||
} | ||
|
||
_nodes = nodes; | ||
[self invalidate]; | ||
} | ||
|
||
- (CIImage *)applyFilter:(NSMutableDictionary<NSString *, CIImage *> *)results | ||
previousFilterResult:(CIImage *)previous | ||
ctm:(CGAffineTransform)ctm | ||
{ | ||
CIFilter *filter = [CIFilter filterWithName:@"CISourceOverCompositing"]; | ||
[filter setDefaults]; | ||
|
||
CIImage *result; | ||
|
||
for (int i = 0; i < [self.nodes count]; i++) { | ||
NSString *nodeKey = [self.nodes objectAtIndex:i]; | ||
CIImage *inputImage = | ||
[nodeKey isEqual:[NSNull null]] ? previous : [results objectForKey:[self.nodes objectAtIndex:i]]; | ||
if (inputImage == nil) { | ||
continue; | ||
} | ||
if (result == nil) { | ||
result = inputImage; | ||
continue; | ||
} | ||
[filter setValue:result forKey:@"inputBackgroundImage"]; | ||
[filter setValue:inputImage forKey:@"inputImage"]; | ||
|
||
result = [filter valueForKey:@"outputImage"]; | ||
} | ||
return result; | ||
} | ||
|
||
#ifdef RCT_NEW_ARCH_ENABLED | ||
Class<RCTComponentViewProtocol> RNSVGFeMergeCls(void) | ||
{ | ||
return RNSVGFeMerge.class; | ||
} | ||
#endif // RCT_NEW_ARCH_ENABLED | ||
|
||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
#import "RNSVGFilterPrimitiveManager.h" | ||
|
||
@interface RNSVGFeMergeManager : RNSVGFilterPrimitiveManager | ||
|
||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
#import "RNSVGFeMergeManager.h" | ||
#import "RNSVGFeMerge.h" | ||
|
||
@implementation RNSVGFeMergeManager | ||
|
||
RCT_EXPORT_MODULE() | ||
|
||
- (RNSVGFeMerge *)node | ||
{ | ||
return [RNSVGFeMerge new]; | ||
} | ||
|
||
RCT_EXPORT_VIEW_PROPERTY(nodes, NSArray<NSString *>) | ||
|
||
@end |
Oops, something went wrong.