mirror of
https://github.com/zoriya/react-native-svg.git
synced 2026-06-04 07:25:53 +00:00
feat: implement filter region lengths directly on RNSVGFilterRegion (#2485)
# Summary [apple] Use filter region directly instead of creating new one on every rerender. [android] rename some variables and add temporary fix for null lengths
This commit is contained in:
@@ -3,12 +3,9 @@
|
||||
|
||||
@interface RNSVGFilter : RNSVGNode
|
||||
|
||||
@property (nonatomic, strong) RNSVGLength *x;
|
||||
@property (nonatomic, strong) RNSVGLength *y;
|
||||
@property (nonatomic, strong) RNSVGLength *width;
|
||||
@property (nonatomic, strong) RNSVGLength *height;
|
||||
@property (nonatomic, assign) RNSVGUnits filterUnits;
|
||||
@property (nonatomic, assign) RNSVGUnits primitiveUnits;
|
||||
@property (nonatomic, strong) RNSVGFilterRegion *filterRegion;
|
||||
|
||||
- (CIImage *)applyFilter:(CIImage *)img
|
||||
backgroundImg:(CIImage *)backgroundImg
|
||||
@@ -18,5 +15,9 @@
|
||||
- (CGContext *)openContext:(CGSize)size;
|
||||
- (void)endContext:(CGContext *)context;
|
||||
- (CIImage *)getMaskFromRect:(CGContext *)context rect:(CGRect)rect ctm:(CGAffineTransform)ctm;
|
||||
- (void)setX:(RNSVGLength *)x;
|
||||
- (void)setY:(RNSVGLength *)y;
|
||||
- (void)setWidth:(RNSVGLength *)width;
|
||||
- (void)setHeight:(RNSVGLength *)height;
|
||||
|
||||
@end
|
||||
|
||||
@@ -70,12 +70,9 @@ using namespace facebook::react;
|
||||
- (void)prepareForRecycle
|
||||
{
|
||||
[super prepareForRecycle];
|
||||
_x = nil;
|
||||
_y = nil;
|
||||
_width = nil;
|
||||
_height = nil;
|
||||
_filterUnits = kRNSVGUnitsObjectBoundingBox;
|
||||
_primitiveUnits = kRNSVGUnitsUserSpaceOnUse;
|
||||
_filterRegion = nil;
|
||||
}
|
||||
#endif // RCT_NEW_ARCH_ENABLED
|
||||
|
||||
@@ -83,6 +80,7 @@ using namespace facebook::react;
|
||||
{
|
||||
if (self = [super init]) {
|
||||
resultsMap = [NSMutableDictionary dictionary];
|
||||
_filterRegion = [[RNSVGFilterRegion alloc] init];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@@ -112,12 +110,9 @@ using namespace facebook::react;
|
||||
for (RNSVGNode *node in self.subviews) {
|
||||
if ([node isKindOfClass:[RNSVGFilterPrimitive class]]) {
|
||||
currentFilter = (RNSVGFilterPrimitive *)node;
|
||||
cropRect = [[RNSVGFilterRegion regionWithX:currentFilter.x
|
||||
y:currentFilter.y
|
||||
width:currentFilter.width
|
||||
height:currentFilter.height] getCropRect:currentFilter
|
||||
units:self.primitiveUnits
|
||||
renderableBounds:renderableBounds];
|
||||
cropRect = [currentFilter.filterSubregion getCropRect:currentFilter
|
||||
units:self.primitiveUnits
|
||||
bounds:renderableBounds];
|
||||
mask = [self getMaskFromRect:cropContext rect:cropRect ctm:ctm];
|
||||
[cropFilter setValue:[currentFilter applyFilter:resultsMap previousFilterResult:result ctm:ctm]
|
||||
forKey:@"inputImage"];
|
||||
@@ -136,10 +131,7 @@ using namespace facebook::react;
|
||||
}
|
||||
}
|
||||
|
||||
cropRect = [[RNSVGFilterRegion regionWithX:self.x y:self.y width:self.width
|
||||
height:self.height] getCropRect:self
|
||||
units:self.filterUnits
|
||||
renderableBounds:renderableBounds];
|
||||
cropRect = [currentFilter.filterSubregion getCropRect:self units:self.filterUnits bounds:renderableBounds];
|
||||
mask = [self getMaskFromRect:cropContext rect:cropRect ctm:ctm];
|
||||
[cropFilter setValue:result forKey:@"inputImage"];
|
||||
[cropFilter setValue:mask forKey:@"inputMaskImage"];
|
||||
@@ -212,41 +204,41 @@ static CIImage *applySourceAlphaFilter(CIImage *inputImage)
|
||||
|
||||
- (void)setX:(RNSVGLength *)x
|
||||
{
|
||||
if ([x isEqualTo:_x]) {
|
||||
if ([x isEqualTo:_filterRegion.x]) {
|
||||
return;
|
||||
}
|
||||
|
||||
_x = x;
|
||||
[_filterRegion setX:x];
|
||||
[self invalidate];
|
||||
}
|
||||
|
||||
- (void)setY:(RNSVGLength *)y
|
||||
{
|
||||
if ([y isEqualTo:_y]) {
|
||||
if ([y isEqualTo:_filterRegion.y]) {
|
||||
return;
|
||||
}
|
||||
|
||||
_y = y;
|
||||
[_filterRegion setY:y];
|
||||
[self invalidate];
|
||||
}
|
||||
|
||||
- (void)setWidth:(RNSVGLength *)width
|
||||
{
|
||||
if ([width isEqualTo:_width]) {
|
||||
if ([width isEqualTo:_filterRegion.width]) {
|
||||
return;
|
||||
}
|
||||
|
||||
_width = width;
|
||||
[_filterRegion setWidth:width];
|
||||
[self invalidate];
|
||||
}
|
||||
|
||||
- (void)setHeight:(RNSVGLength *)height
|
||||
{
|
||||
if ([height isEqualTo:_height]) {
|
||||
if ([height isEqualTo:_filterRegion.height]) {
|
||||
return;
|
||||
}
|
||||
|
||||
_height = height;
|
||||
[_filterRegion setHeight:height];
|
||||
[self invalidate];
|
||||
}
|
||||
|
||||
|
||||
@@ -3,15 +3,16 @@
|
||||
|
||||
@interface RNSVGFilterPrimitive : RNSVGNode
|
||||
|
||||
@property (nonatomic, strong) RNSVGLength *x;
|
||||
@property (nonatomic, strong) RNSVGLength *y;
|
||||
@property (nonatomic, strong) RNSVGLength *width;
|
||||
@property (nonatomic, strong) RNSVGLength *height;
|
||||
@property (nonatomic, strong) NSString *result;
|
||||
@property (nonatomic, strong) RNSVGFilterRegion *filterSubregion;
|
||||
|
||||
- (CIImage *)applyFilter:(NSMutableDictionary<NSString *, CIImage *> *)results previousFilterResult:(CIImage *)previous;
|
||||
- (CIImage *)applyFilter:(NSMutableDictionary<NSString *, CIImage *> *)results
|
||||
previousFilterResult:(CIImage *)previous
|
||||
ctm:(CGAffineTransform)ctm;
|
||||
- (void)setX:(RNSVGLength *)x;
|
||||
- (void)setY:(RNSVGLength *)y;
|
||||
- (void)setWidth:(RNSVGLength *)width;
|
||||
- (void)setHeight:(RNSVGLength *)height;
|
||||
|
||||
@end
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#import <RNSVGFilterPrimitive.h>
|
||||
#import <RNSVGNode.h>
|
||||
#import "RNSVGFilter.h"
|
||||
|
||||
#ifdef RCT_NEW_ARCH_ENABLED
|
||||
#import <React/RCTConversions.h>
|
||||
@@ -15,14 +16,20 @@
|
||||
- (void)prepareForRecycle
|
||||
{
|
||||
[super prepareForRecycle];
|
||||
_x = nil;
|
||||
_y = nil;
|
||||
_width = nil;
|
||||
_height = nil;
|
||||
_filterSubregion = nil;
|
||||
_result = nil;
|
||||
}
|
||||
#endif // RCT_NEW_ARCH_ENABLED
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_filterSubregion = [[RNSVGFilterRegion alloc] init];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (RNSVGPlatformView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
|
||||
{
|
||||
return nil;
|
||||
@@ -40,41 +47,41 @@
|
||||
|
||||
- (void)setX:(RNSVGLength *)x
|
||||
{
|
||||
if ([x isEqualTo:_x]) {
|
||||
if ([x isEqualTo:_filterSubregion.x]) {
|
||||
return;
|
||||
}
|
||||
|
||||
_x = x;
|
||||
[_filterSubregion setX:x];
|
||||
[self invalidate];
|
||||
}
|
||||
|
||||
- (void)setY:(RNSVGLength *)y
|
||||
{
|
||||
if ([y isEqualTo:_y]) {
|
||||
if ([y isEqualTo:_filterSubregion.y]) {
|
||||
return;
|
||||
}
|
||||
|
||||
_y = y;
|
||||
[_filterSubregion setY:y];
|
||||
[self invalidate];
|
||||
}
|
||||
|
||||
- (void)setWidth:(RNSVGLength *)width
|
||||
{
|
||||
if ([width isEqualTo:_width]) {
|
||||
if ([width isEqualTo:_filterSubregion.width]) {
|
||||
return;
|
||||
}
|
||||
|
||||
_width = width;
|
||||
[_filterSubregion setWidth:width];
|
||||
[self invalidate];
|
||||
}
|
||||
|
||||
- (void)setHeight:(RNSVGLength *)height
|
||||
{
|
||||
if ([height isEqualTo:_height]) {
|
||||
if ([height isEqualTo:_filterSubregion.height]) {
|
||||
return;
|
||||
}
|
||||
|
||||
_height = height;
|
||||
[_filterSubregion setHeight:height];
|
||||
[self invalidate];
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
@property (nonatomic, strong) RNSVGLength *height;
|
||||
|
||||
+ (instancetype)regionWithX:(RNSVGLength *)x y:(RNSVGLength *)y width:(RNSVGLength *)width height:(RNSVGLength *)height;
|
||||
- (CGRect)getCropRect:(RNSVGNode *)node units:(RNSVGUnits)units renderableBounds:(CGRect)renderableBounds;
|
||||
- (CGRect)getCropRect:(RNSVGNode *)node units:(RNSVGUnits)units bounds:(CGRect)bounds;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@@ -5,12 +5,6 @@
|
||||
- (instancetype)init
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_x = [RNSVGLength lengthWithNumber:0];
|
||||
_y = [RNSVGLength lengthWithNumber:0];
|
||||
_width = [RNSVGLength lengthWithNumber:0];
|
||||
_height = [RNSVGLength lengthWithNumber:0];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -44,15 +38,15 @@
|
||||
_height = height;
|
||||
}
|
||||
|
||||
- (CGRect)getCropRect:(RNSVGNode *)node units:(RNSVGUnits)units renderableBounds:(CGRect)renderableBounds
|
||||
- (CGRect)getCropRect:(RNSVGNode *)node units:(RNSVGUnits)units bounds:(CGRect)bounds
|
||||
{
|
||||
CGFloat x, y, width, height;
|
||||
if (units == kRNSVGUnitsObjectBoundingBox) {
|
||||
x = [node relativeOnFraction:self.x relative:renderableBounds.size.width];
|
||||
y = [node relativeOnFraction:self.y relative:renderableBounds.size.height];
|
||||
width = [node relativeOnFraction:self.width relative:renderableBounds.size.width];
|
||||
height = [node relativeOnFraction:self.height relative:renderableBounds.size.height];
|
||||
return CGRectMake(renderableBounds.origin.x + x, renderableBounds.origin.y + y, width, height);
|
||||
x = [node relativeOnFraction:self.x relative:bounds.size.width];
|
||||
y = [node relativeOnFraction:self.y relative:bounds.size.height];
|
||||
width = [node relativeOnFraction:self.width relative:bounds.size.width];
|
||||
height = [node relativeOnFraction:self.height relative:bounds.size.height];
|
||||
return CGRectMake(bounds.origin.x + x, bounds.origin.y + y, width, height);
|
||||
} else { // kRNSVGUnitsUserSpaceOnUse
|
||||
x = [node relativeOnWidth:self.x];
|
||||
y = [node relativeOnHeight:self.y];
|
||||
|
||||
@@ -141,4 +141,11 @@ extern CGFloat const RNSVG_DEFAULT_FONT_SIZE;
|
||||
|
||||
- (void)clearPath;
|
||||
|
||||
/**
|
||||
* get canvas dimensions
|
||||
*/
|
||||
- (CGFloat)getCanvasWidth;
|
||||
|
||||
- (CGFloat)getCanvasHeight;
|
||||
|
||||
@end
|
||||
|
||||
Reference in New Issue
Block a user