diff --git a/Example/ios/Podfile.lock b/Example/ios/Podfile.lock
index 72688179..ff9c8ef9 100644
--- a/Example/ios/Podfile.lock
+++ b/Example/ios/Podfile.lock
@@ -513,7 +513,7 @@ PODS:
- React-RCTText
- ReactCommon/turbomodule/core
- Yoga
- - RNSVG (13.10.0):
+ - RNSVG (13.11.0):
- React-Core
- SocketRocket (0.6.1)
- Yoga (1.14.0)
@@ -741,7 +741,7 @@ SPEC CHECKSUMS:
React-utils: 0a70ea97d4e2749f336b450c082905be1d389435
ReactCommon: e593d19c9e271a6da4d0bd7f13b28cfeae5d164b
RNReanimated: 726395a2fa2f04cea340274ba57a4e659bc0d9c1
- RNSVG: ee7e4ae98adade9ad8a12e7f9276504e71bd3ef7
+ RNSVG: 791907c36f290562750132f8d274730c3aa529f6
SocketRocket: f32cd54efbe0f095c4d7594881e52619cfe80b17
Yoga: 65286bb6a07edce5e4fe8c90774da977ae8fc009
YogaKit: f782866e155069a2cca2517aafea43200b01fd5a
diff --git a/Example/src/App.tsx b/Example/src/App.tsx
index 05695289..45ecb312 100644
--- a/Example/src/App.tsx
+++ b/Example/src/App.tsx
@@ -115,6 +115,7 @@ const names: (keyof typeof examples)[] = [
'Reanimated',
'Transforms',
'Markers',
+ 'Mask',
];
const initialState = {
diff --git a/Example/src/examples.tsx b/Example/src/examples.tsx
index dab7226d..22b7d34c 100644
--- a/Example/src/examples.tsx
+++ b/Example/src/examples.tsx
@@ -18,6 +18,7 @@ import * as PanResponder from './examples/PanResponder';
import * as Reanimated from './examples/Reanimated';
import * as Transforms from './examples/Transforms';
import * as Markers from './examples/Markers';
+import * as Mask from './examples/Mask';
export {
Svg,
@@ -40,4 +41,5 @@ export {
Reanimated,
Transforms,
Markers,
+ Mask,
};
diff --git a/Example/src/examples/Mask.tsx b/Example/src/examples/Mask.tsx
new file mode 100644
index 00000000..a8ca125d
--- /dev/null
+++ b/Example/src/examples/Mask.tsx
@@ -0,0 +1,148 @@
+import React, {Component} from 'react';
+import {StyleSheet, View} from 'react-native';
+import {
+ Svg,
+ Circle,
+ Path,
+ Rect,
+ Mask,
+ Polygon,
+ Defs,
+ LinearGradient,
+ Stop,
+ Text,
+} from 'react-native-svg';
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ height: 100,
+ width: 200,
+ },
+ svg: {
+ flex: 1,
+ alignSelf: 'stretch',
+ },
+});
+
+class SimpleMask extends Component {
+ static title = 'Simple svg with mask';
+ render() {
+ return (
+
+
+
+ );
+ }
+}
+
+class AnotherMask extends Component {
+ static title = 'Another svg with mask';
+ render() {
+ return (
+
+
+
+ );
+ }
+}
+
+class MaskWithText extends Component {
+ static title = 'Svg with with text and a mask with gradient';
+ render() {
+ return (
+
+
+
+ );
+ }
+}
+
+const icon = (
+
+);
+
+const samples = [SimpleMask, AnotherMask, MaskWithText];
+
+export {icon, samples};
diff --git a/FabricExample/ios/Podfile.lock b/FabricExample/ios/Podfile.lock
index 122ad31b..6d63263f 100644
--- a/FabricExample/ios/Podfile.lock
+++ b/FabricExample/ios/Podfile.lock
@@ -1087,7 +1087,7 @@ PODS:
- React-RCTText
- ReactCommon/turbomodule/core
- Yoga
- - RNSVG (13.10.0):
+ - RNSVG (13.11.0):
- hermes-engine
- RCT-Folly (= 2021.07.22.00)
- RCTRequired
@@ -1102,9 +1102,9 @@ PODS:
- React-utils
- ReactCommon/turbomodule/bridging
- ReactCommon/turbomodule/core
- - RNSVG/common (= 13.10.0)
+ - RNSVG/common (= 13.11.0)
- Yoga
- - RNSVG/common (13.10.0):
+ - RNSVG/common (13.11.0):
- hermes-engine
- RCT-Folly (= 2021.07.22.00)
- RCTRequired
@@ -1359,7 +1359,7 @@ SPEC CHECKSUMS:
React-utils: 0a70ea97d4e2749f336b450c082905be1d389435
ReactCommon: e593d19c9e271a6da4d0bd7f13b28cfeae5d164b
RNReanimated: 5008fe999d57038a1c5c1163044854d453f41b98
- RNSVG: b677ab45318fca9f50dc361c1e3fd7c558dd0963
+ RNSVG: e3b83203f24f5d275aa71ed85390222a6eb51a48
SocketRocket: f32cd54efbe0f095c4d7594881e52619cfe80b17
Yoga: 65286bb6a07edce5e4fe8c90774da977ae8fc009
YogaKit: f782866e155069a2cca2517aafea43200b01fd5a
diff --git a/FabricExample/src/App.tsx b/FabricExample/src/App.tsx
index 05695289..45ecb312 100644
--- a/FabricExample/src/App.tsx
+++ b/FabricExample/src/App.tsx
@@ -115,6 +115,7 @@ const names: (keyof typeof examples)[] = [
'Reanimated',
'Transforms',
'Markers',
+ 'Mask',
];
const initialState = {
diff --git a/FabricExample/src/examples.tsx b/FabricExample/src/examples.tsx
index dab7226d..22b7d34c 100644
--- a/FabricExample/src/examples.tsx
+++ b/FabricExample/src/examples.tsx
@@ -18,6 +18,7 @@ import * as PanResponder from './examples/PanResponder';
import * as Reanimated from './examples/Reanimated';
import * as Transforms from './examples/Transforms';
import * as Markers from './examples/Markers';
+import * as Mask from './examples/Mask';
export {
Svg,
@@ -40,4 +41,5 @@ export {
Reanimated,
Transforms,
Markers,
+ Mask,
};
diff --git a/FabricExample/src/examples/Mask.tsx b/FabricExample/src/examples/Mask.tsx
new file mode 100644
index 00000000..a8ca125d
--- /dev/null
+++ b/FabricExample/src/examples/Mask.tsx
@@ -0,0 +1,148 @@
+import React, {Component} from 'react';
+import {StyleSheet, View} from 'react-native';
+import {
+ Svg,
+ Circle,
+ Path,
+ Rect,
+ Mask,
+ Polygon,
+ Defs,
+ LinearGradient,
+ Stop,
+ Text,
+} from 'react-native-svg';
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ height: 100,
+ width: 200,
+ },
+ svg: {
+ flex: 1,
+ alignSelf: 'stretch',
+ },
+});
+
+class SimpleMask extends Component {
+ static title = 'Simple svg with mask';
+ render() {
+ return (
+
+
+
+ );
+ }
+}
+
+class AnotherMask extends Component {
+ static title = 'Another svg with mask';
+ render() {
+ return (
+
+
+
+ );
+ }
+}
+
+class MaskWithText extends Component {
+ static title = 'Svg with with text and a mask with gradient';
+ render() {
+ return (
+
+
+
+ );
+ }
+}
+
+const icon = (
+
+);
+
+const samples = [SimpleMask, AnotherMask, MaskWithText];
+
+export {icon, samples};
diff --git a/RNSVG.podspec b/RNSVG.podspec
index 1f40f05c..88afeb13 100644
--- a/RNSVG.podspec
+++ b/RNSVG.podspec
@@ -28,7 +28,7 @@ Pod::Spec.new do |s|
ss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/common/cpp\"" }
end
else
- s.platforms = { :osx => "10.14", :ios => "9.0", :tvos => "9.2" }
+ s.platforms = { :osx => "10.14", :ios => "10.0", :tvos => "9.2" }
s.exclude_files = 'apple/Utils/RNSVGFabricConversions.h'
s.dependency 'React-Core'
end
diff --git a/apple/Elements/RNSVGSvgView.h b/apple/Elements/RNSVGSvgView.h
index d3c88ffd..e589dad3 100644
--- a/apple/Elements/RNSVGSvgView.h
+++ b/apple/Elements/RNSVGSvgView.h
@@ -63,9 +63,7 @@
- (RNSVGNode *)getDefinedMask:(NSString *)maskName;
-- (NSString *)getDataURL;
-
-- (NSString *)getDataURLwithBounds:(CGRect)bounds;
+- (NSString *)getDataURLWithBounds:(CGRect)bounds;
- (CGRect)getContextBounds;
diff --git a/apple/Elements/RNSVGSvgView.mm b/apple/Elements/RNSVGSvgView.mm
index 51fa1ee9..e5da830c 100644
--- a/apple/Elements/RNSVGSvgView.mm
+++ b/apple/Elements/RNSVGSvgView.mm
@@ -321,29 +321,20 @@ using namespace facebook::react;
return nil;
}
-- (NSString *)getDataURL
+- (NSString *)getDataURLWithBounds:(CGRect)bounds
{
- UIGraphicsBeginImageContextWithOptions(_boundingBox.size, NO, 0);
- [self clearChildCache];
- [self drawRect:_boundingBox];
- [self clearChildCache];
- [self invalidate];
- NSData *imageData = UIImagePNGRepresentation(UIGraphicsGetImageFromCurrentImageContext());
- NSString *base64 = [imageData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
- UIGraphicsEndImageContext();
- return base64;
-}
+ UIGraphicsImageRenderer *renderer = [[UIGraphicsImageRenderer alloc] initWithSize:bounds.size];
-- (NSString *)getDataURLwithBounds:(CGRect)bounds
-{
- UIGraphicsBeginImageContextWithOptions(bounds.size, NO, 1);
- [self clearChildCache];
- [self drawRect:bounds];
- [self clearChildCache];
- [self invalidate];
- NSData *imageData = UIImagePNGRepresentation(UIGraphicsGetImageFromCurrentImageContext());
+ UIImage *image = [renderer imageWithActions:^(UIGraphicsImageRendererContext *_Nonnull rendererContext) {
+ [self clearChildCache];
+ [self drawRect:bounds];
+ [self clearChildCache];
+ [self invalidate];
+ }];
+
+ NSData *imageData = UIImagePNGRepresentation(image);
NSString *base64 = [imageData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
- UIGraphicsEndImageContext();
+
return base64;
}
diff --git a/apple/RNSVGRenderable.mm b/apple/RNSVGRenderable.mm
index d69b9745..20b73787 100644
--- a/apple/RNSVGRenderable.mm
+++ b/apple/RNSVGRenderable.mm
@@ -304,35 +304,30 @@ UInt32 saturate(CGFloat value)
CGContextRelease(bcontext);
free(pixels);
- // Render content of current SVG Renderable to image
- UIGraphicsBeginImageContextWithOptions(boundsSize, NO, 0.0);
- CGContextRef newContext = UIGraphicsGetCurrentContext();
- CGContextTranslateCTM(newContext, 0.0, height);
- CGContextScaleCTM(newContext, 1.0, -1.0);
- [self renderLayerTo:newContext rect:rect];
- CGImageRef contentImage = CGBitmapContextCreateImage(newContext);
- UIGraphicsEndImageContext();
+ UIGraphicsImageRendererFormat *format = [UIGraphicsImageRendererFormat defaultFormat];
+ format.scale = scale;
+ UIGraphicsImageRenderer *renderer = [[UIGraphicsImageRenderer alloc] initWithSize:boundsSize format:format];
+
+ // Get the content image
+ UIImage *contentImage = [renderer imageWithActions:^(UIGraphicsImageRendererContext *_Nonnull rendererContext) {
+ CGContextTranslateCTM(rendererContext.CGContext, 0.0, height);
+ CGContextScaleCTM(rendererContext.CGContext, 1.0, -1.0);
+ [self renderLayerTo:rendererContext.CGContext rect:rect];
+ }];
// Blend current element and mask
- UIGraphicsBeginImageContextWithOptions(boundsSize, NO, 0.0);
- newContext = UIGraphicsGetCurrentContext();
- CGContextTranslateCTM(newContext, 0.0, height);
- CGContextScaleCTM(newContext, 1.0, -1.0);
-
- CGContextSetBlendMode(newContext, kCGBlendModeCopy);
- CGContextDrawImage(newContext, drawBounds, maskImage);
- CGImageRelease(maskImage);
-
- CGContextSetBlendMode(newContext, kCGBlendModeSourceIn);
- CGContextDrawImage(newContext, drawBounds, contentImage);
- CGImageRelease(contentImage);
-
- CGImageRef blendedImage = CGBitmapContextCreateImage(newContext);
- UIGraphicsEndImageContext();
+ UIImage *blendedImage = [renderer imageWithActions:^(UIGraphicsImageRendererContext *_Nonnull rendererContext) {
+ CGContextSetBlendMode(rendererContext.CGContext, kCGBlendModeCopy);
+ CGContextDrawImage(rendererContext.CGContext, drawBounds, maskImage);
+ CGContextSetBlendMode(rendererContext.CGContext, kCGBlendModeSourceIn);
+ CGContextDrawImage(rendererContext.CGContext, drawBounds, contentImage.CGImage);
+ }];
// Render blended result into current render context
- CGContextDrawImage(context, drawBounds, blendedImage);
- CGImageRelease(blendedImage);
+ [blendedImage drawInRect:drawBounds];
+
+ // Render blended result into current render context
+ CGImageRelease(maskImage);
} else {
[self renderLayerTo:context rect:rect];
}
diff --git a/apple/RNSVGSvgViewModule.mm b/apple/RNSVGSvgViewModule.mm
index 231940e7..3d869615 100644
--- a/apple/RNSVGSvgViewModule.mm
+++ b/apple/RNSVGSvgViewModule.mm
@@ -39,7 +39,7 @@ RCT_EXPORT_MODULE()
if ([view isKindOfClass:[RNSVGSvgView class]]) {
RNSVGSvgView *svg = view;
if (options == nil) {
- b64 = [svg getDataURL];
+ b64 = [svg getDataURLWithBounds:svg.boundingBox];
} else {
id width = [options objectForKey:@"width"];
id height = [options objectForKey:@"height"];
@@ -53,7 +53,7 @@ RCT_EXPORT_MODULE()
NSInteger hi = (NSInteger)[h intValue];
CGRect bounds = CGRectMake(0, 0, wi, hi);
- b64 = [svg getDataURLwithBounds:bounds];
+ b64 = [svg getDataURLWithBounds:bounds];
}
} else {
RCTLogError(@"Invalid svg returned from registry, expecting RNSVGSvgView, got: %@", view);