mirror of
https://github.com/zoriya/react-native-svg.git
synced 2026-06-03 07:06:04 +00:00
feat: properly implement filter region unit USER_SPACE_ON_USE (#2486)
# Summary After deep dive into the specification, I found out that the default filter subregion is not equal to `0% 0% 100% 100%`, rather the size of the parent filter region. ## Compatibility | OS | Implemented | | ------- | :---------: | | iOS | ✅ | | MacOS | ✅ | | Android | ✅ |
This commit is contained in:
@@ -105,14 +105,16 @@ using namespace facebook::react;
|
||||
CGContext *cropContext = [self openContext:canvasBounds.size];
|
||||
CIImage *mask;
|
||||
|
||||
CGRect filterRegionRect = [self.filterRegion getCropRect:self units:self.filterUnits bounds:renderableBounds];
|
||||
CIImage *result = img;
|
||||
RNSVGFilterPrimitive *currentFilter;
|
||||
for (RNSVGNode *node in self.subviews) {
|
||||
if ([node isKindOfClass:[RNSVGFilterPrimitive class]]) {
|
||||
currentFilter = (RNSVGFilterPrimitive *)node;
|
||||
cropRect = [currentFilter.filterSubregion getCropRect:currentFilter
|
||||
units:self.primitiveUnits
|
||||
bounds:renderableBounds];
|
||||
cropRect = [currentFilter.filterSubregion
|
||||
getCropRect:currentFilter
|
||||
units:self.primitiveUnits
|
||||
bounds:self.primitiveUnits == kRNSVGUnitsUserSpaceOnUse ? filterRegionRect : renderableBounds];
|
||||
mask = [self getMaskFromRect:cropContext rect:cropRect ctm:ctm];
|
||||
[cropFilter setValue:[currentFilter applyFilter:resultsMap previousFilterResult:result ctm:ctm]
|
||||
forKey:@"inputImage"];
|
||||
@@ -131,8 +133,7 @@ using namespace facebook::react;
|
||||
}
|
||||
}
|
||||
|
||||
cropRect = [currentFilter.filterSubregion getCropRect:self units:self.filterUnits bounds:renderableBounds];
|
||||
mask = [self getMaskFromRect:cropContext rect:cropRect ctm:ctm];
|
||||
mask = [self getMaskFromRect:cropContext rect:filterRegionRect ctm:ctm];
|
||||
[cropFilter setValue:result forKey:@"inputImage"];
|
||||
[cropFilter setValue:mask forKey:@"inputMaskImage"];
|
||||
[self endContext:cropContext];
|
||||
|
||||
@@ -38,6 +38,17 @@
|
||||
_height = height;
|
||||
}
|
||||
|
||||
+ (CGFloat)getRelativeOrDefault:(RNSVGNode *)node
|
||||
value:(RNSVGLength *)value
|
||||
relativeOn:(CGFloat)relativeOn
|
||||
defaultValue:(CGFloat)defaultValue
|
||||
{
|
||||
if (value == nil || value.unit == SVG_LENGTHTYPE_UNKNOWN) {
|
||||
return defaultValue;
|
||||
}
|
||||
return [node relativeOn:value relative:relativeOn];
|
||||
}
|
||||
|
||||
- (CGRect)getCropRect:(RNSVGNode *)node units:(RNSVGUnits)units bounds:(CGRect)bounds
|
||||
{
|
||||
CGFloat x, y, width, height;
|
||||
@@ -48,10 +59,22 @@
|
||||
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];
|
||||
width = [node relativeOnWidth:self.width];
|
||||
height = [node relativeOnHeight:self.height];
|
||||
x = [RNSVGFilterRegion getRelativeOrDefault:node
|
||||
value:self.x
|
||||
relativeOn:[node getCanvasWidth]
|
||||
defaultValue:bounds.origin.x];
|
||||
y = [RNSVGFilterRegion getRelativeOrDefault:node
|
||||
value:self.y
|
||||
relativeOn:[node getCanvasHeight]
|
||||
defaultValue:bounds.origin.y];
|
||||
width = [RNSVGFilterRegion getRelativeOrDefault:node
|
||||
value:self.width
|
||||
relativeOn:[node getCanvasWidth]
|
||||
defaultValue:bounds.size.width];
|
||||
height = [RNSVGFilterRegion getRelativeOrDefault:node
|
||||
value:self.height
|
||||
relativeOn:[node getCanvasHeight]
|
||||
defaultValue:bounds.size.height];
|
||||
return CGRectMake(x, y, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user