mirror of
https://github.com/zoriya/react-native-svg.git
synced 2026-06-05 16:04:38 +00:00
feat: FeBlend (#2489)
# Summary Continuation of #2362 implementing `FeBlend` filter https://www.w3.org/TR/SVG11/filters.html#feBlendElement ## Test Plan Example app → Filters → `FeBlend` ## Compatibility | OS | Implemented | | ------- | :---------: | | iOS | ✅ | | macOS | ✅ _*_ | | Android | ✅ | | Web | ✅ |
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
typedef CF_ENUM(int32_t, RNSVGBlendMode) {
|
||||
SVG_FEBLEND_MODE_UNKNOWN,
|
||||
SVG_FEBLEND_MODE_NORMAL,
|
||||
SVG_FEBLEND_MODE_MULTIPLY,
|
||||
SVG_FEBLEND_MODE_SCREEN,
|
||||
SVG_FEBLEND_MODE_DARKEN,
|
||||
SVG_FEBLEND_MODE_LIGHTEN,
|
||||
};
|
||||
@@ -0,0 +1,10 @@
|
||||
#import "RNSVGBlendMode.h"
|
||||
#import "RNSVGFilterPrimitive.h"
|
||||
|
||||
@interface RNSVGFeBlend : RNSVGFilterPrimitive
|
||||
|
||||
@property (nonatomic, strong) NSString *in1;
|
||||
@property (nonatomic, strong) NSString *in2;
|
||||
@property (nonatomic, assign) RNSVGBlendMode mode;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,132 @@
|
||||
#import "RNSVGFeBlend.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 "RNSVGConvert.h"
|
||||
#import "RNSVGFabricConversions.h"
|
||||
#endif // RCT_NEW_ARCH_ENABLED
|
||||
|
||||
@implementation RNSVGFeBlend
|
||||
|
||||
#ifdef RCT_NEW_ARCH_ENABLED
|
||||
using namespace facebook::react;
|
||||
|
||||
// Needed because of this: https://github.com/facebook/react-native/pull/37274
|
||||
+ (void)load
|
||||
{
|
||||
[super load];
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
{
|
||||
if (self = [super initWithFrame:frame]) {
|
||||
static const auto defaultProps = std::make_shared<const RNSVGFeBlendProps>();
|
||||
_props = defaultProps;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - RCTComponentViewProtocol
|
||||
|
||||
+ (ComponentDescriptorProvider)componentDescriptorProvider
|
||||
{
|
||||
return concreteComponentDescriptorProvider<RNSVGFeBlendComponentDescriptor>();
|
||||
}
|
||||
|
||||
- (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps
|
||||
{
|
||||
const auto &newProps = static_cast<const RNSVGFeBlendProps &>(*props);
|
||||
|
||||
self.in1 = RCTNSStringFromStringNilIfEmpty(newProps.in1);
|
||||
self.in2 = RCTNSStringFromStringNilIfEmpty(newProps.in2);
|
||||
self.mode = [RNSVGConvert RNSVGBlendModeFromCppEquivalent:newProps.mode];
|
||||
|
||||
setCommonFilterProps(newProps, self);
|
||||
_props = std::static_pointer_cast<RNSVGFeBlendProps const>(props);
|
||||
}
|
||||
|
||||
- (void)prepareForRecycle
|
||||
{
|
||||
[super prepareForRecycle];
|
||||
_in1 = nil;
|
||||
_in2 = nil;
|
||||
_mode = RNSVGBlendMode::SVG_FEBLEND_MODE_NORMAL;
|
||||
}
|
||||
#endif // RCT_NEW_ARCH_ENABLED
|
||||
|
||||
- (void)setIn1:(NSString *)in1
|
||||
{
|
||||
if ([in1 isEqualToString:_in1]) {
|
||||
return;
|
||||
}
|
||||
|
||||
_in1 = in1;
|
||||
[self invalidate];
|
||||
}
|
||||
|
||||
- (void)setIn2:(NSString *)in2
|
||||
{
|
||||
if ([in2 isEqualToString:_in2]) {
|
||||
return;
|
||||
}
|
||||
|
||||
_in2 = in2;
|
||||
[self invalidate];
|
||||
}
|
||||
|
||||
- (void)setMode:(RNSVGBlendMode)mode
|
||||
{
|
||||
if (mode == _mode) {
|
||||
return;
|
||||
}
|
||||
_mode = mode;
|
||||
[self invalidate];
|
||||
}
|
||||
|
||||
- (CIImage *)applyFilter:(NSMutableDictionary<NSString *, CIImage *> *)results previousFilterResult:(CIImage *)previous
|
||||
{
|
||||
CIImage *inResults1 = self.in1 ? [results objectForKey:self.in1] : nil;
|
||||
CIImage *inResults2 = self.in2 ? [results objectForKey:self.in2] : nil;
|
||||
CIImage *inputImage1 = inResults1 ? inResults1 : previous;
|
||||
CIImage *inputImage2 = inResults2 ? inResults2 : previous;
|
||||
|
||||
CIFilter *filter = nil;
|
||||
|
||||
switch (self.mode) {
|
||||
case SVG_FEBLEND_MODE_NORMAL:
|
||||
filter = [CIFilter filterWithName:@"CISourceOverCompositing"];
|
||||
break;
|
||||
case SVG_FEBLEND_MODE_MULTIPLY:
|
||||
filter = [CIFilter filterWithName:@"CIMultiplyBlendMode"];
|
||||
break;
|
||||
case SVG_FEBLEND_MODE_SCREEN:
|
||||
filter = [CIFilter filterWithName:@"CIScreenBlendMode"];
|
||||
break;
|
||||
case SVG_FEBLEND_MODE_DARKEN:
|
||||
filter = [CIFilter filterWithName:@"CIDarkenBlendMode"];
|
||||
break;
|
||||
case SVG_FEBLEND_MODE_LIGHTEN:
|
||||
filter = [CIFilter filterWithName:@"CILightenBlendMode"];
|
||||
break;
|
||||
default:
|
||||
return nil;
|
||||
}
|
||||
|
||||
[filter setDefaults];
|
||||
[filter setValue:inputImage1 forKey:@"inputImage"];
|
||||
[filter setValue:inputImage2 forKey:@"inputBackgroundImage"];
|
||||
|
||||
return [filter valueForKey:@"outputImage"];
|
||||
}
|
||||
|
||||
#ifdef RCT_NEW_ARCH_ENABLED
|
||||
Class<RCTComponentViewProtocol> RNSVGFeBlendCls(void)
|
||||
{
|
||||
return RNSVGFeBlend.class;
|
||||
}
|
||||
#endif // RCT_NEW_ARCH_ENABLED
|
||||
|
||||
@end
|
||||
@@ -10,6 +10,7 @@
|
||||
#import <QuartzCore/QuartzCore.h>
|
||||
#import <React/RCTConvert.h>
|
||||
#import "RCTConvert+RNSVG.h"
|
||||
#import "RNSVGBlendMode.h"
|
||||
#import "RNSVGCGFCRule.h"
|
||||
#import "RNSVGColorMatrixType.h"
|
||||
#import "RNSVGEdgeMode.h"
|
||||
|
||||
@@ -72,6 +72,19 @@ RCT_ENUM_CONVERTER(
|
||||
SVG_FECOLORMATRIX_TYPE_UNKNOWN,
|
||||
intValue)
|
||||
|
||||
RCT_ENUM_CONVERTER(
|
||||
RNSVGBlendMode,
|
||||
(@{
|
||||
@"unknown" : @(SVG_FEBLEND_MODE_UNKNOWN),
|
||||
@"normal" : @(SVG_FEBLEND_MODE_NORMAL),
|
||||
@"multiply" : @(SVG_FEBLEND_MODE_MULTIPLY),
|
||||
@"screen" : @(SVG_FEBLEND_MODE_SCREEN),
|
||||
@"darken" : @(SVG_FEBLEND_MODE_DARKEN),
|
||||
@"lighten" : @(SVG_FEBLEND_MODE_LIGHTEN),
|
||||
}),
|
||||
SVG_FEBLEND_MODE_UNKNOWN,
|
||||
intValue)
|
||||
|
||||
+ (RNSVGBrush *)RNSVGBrush:(id)json
|
||||
{
|
||||
if ([json isKindOfClass:[NSNumber class]]) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#ifdef RCT_NEW_ARCH_ENABLED
|
||||
#import <react/renderer/components/rnsvg/Props.h>
|
||||
#import "RNSVGBlendMode.h"
|
||||
#import "RNSVGColorMatrixType.h"
|
||||
#import "RNSVGEdgeMode.h"
|
||||
#import "RNSVGUnits.h"
|
||||
@@ -10,6 +11,7 @@ namespace react = facebook::react;
|
||||
|
||||
+ (RNSVGUnits)RNSVGUnitsFromFilterUnitsCppEquivalent:(react::RNSVGFilterFilterUnits)svgUnits;
|
||||
+ (RNSVGUnits)RNSVGUnitsFromPrimitiveUnitsCppEquivalent:(react::RNSVGFilterPrimitiveUnits)svgUnits;
|
||||
+ (RNSVGBlendMode)RNSVGBlendModeFromCppEquivalent:(react::RNSVGFeBlendMode)mode;
|
||||
+ (RNSVGColorMatrixType)RNSVGColorMatrixTypeFromCppEquivalent:(react::RNSVGFeColorMatrixType)type;
|
||||
+ (RNSVGEdgeMode)RNSVGEdgeModeFromCppEquivalent:(react::RNSVGFeGaussianBlurEdgeMode)edgeMode;
|
||||
|
||||
|
||||
@@ -23,6 +23,24 @@
|
||||
}
|
||||
}
|
||||
|
||||
+ (RNSVGBlendMode)RNSVGBlendModeFromCppEquivalent:(react::RNSVGFeBlendMode)mode
|
||||
{
|
||||
switch (mode) {
|
||||
case react::RNSVGFeBlendMode::Unknown:
|
||||
return SVG_FEBLEND_MODE_UNKNOWN;
|
||||
case react::RNSVGFeBlendMode::Normal:
|
||||
return SVG_FEBLEND_MODE_NORMAL;
|
||||
case react::RNSVGFeBlendMode::Multiply:
|
||||
return SVG_FEBLEND_MODE_MULTIPLY;
|
||||
case react::RNSVGFeBlendMode::Screen:
|
||||
return SVG_FEBLEND_MODE_SCREEN;
|
||||
case react::RNSVGFeBlendMode::Darken:
|
||||
return SVG_FEBLEND_MODE_DARKEN;
|
||||
case react::RNSVGFeBlendMode::Lighten:
|
||||
return SVG_FEBLEND_MODE_LIGHTEN;
|
||||
}
|
||||
}
|
||||
|
||||
+ (RNSVGColorMatrixType)RNSVGColorMatrixTypeFromCppEquivalent:(react::RNSVGFeColorMatrixType)type
|
||||
{
|
||||
switch (type) {
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
#import "RNSVGFilterPrimitiveManager.h"
|
||||
|
||||
@interface RNSVGFeBlendManager : RNSVGFilterPrimitiveManager
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,18 @@
|
||||
#import "RNSVGFeBlendManager.h"
|
||||
#import "RNSVGBlendMode.h"
|
||||
#import "RNSVGFeBlend.h"
|
||||
|
||||
@implementation RNSVGFeBlendManager
|
||||
|
||||
RCT_EXPORT_MODULE()
|
||||
|
||||
- (RNSVGFeBlend *)node
|
||||
{
|
||||
return [RNSVGFeBlend new];
|
||||
}
|
||||
|
||||
RCT_EXPORT_VIEW_PROPERTY(in1, NSString)
|
||||
RCT_EXPORT_VIEW_PROPERTY(in2, NSString)
|
||||
RCT_EXPORT_VIEW_PROPERTY(mode, RNSVGBlendMode)
|
||||
|
||||
@end
|
||||
Reference in New Issue
Block a user