From 63f793c54e199da29ee3fc3c9bdb2ea395689934 Mon Sep 17 00:00:00 2001 From: Horcrux Date: Thu, 21 Jul 2016 19:11:36 +0800 Subject: [PATCH] fix fillOpacity with gradients --- elements/Ellipse.js | 1 + ios/Brushes/RNSVGBaseBrush.m | 9 +++++++++ ios/Brushes/RNSVGBrushConverter.m | 1 + ios/Elements/RNSVGPath.m | 2 +- ios/Elements/RNSVGUse.m | 13 ++----------- ios/RNSVGNode.h | 4 ++++ ios/RNSVGNode.m | 32 ++++++++++++++++++++----------- 7 files changed, 39 insertions(+), 23 deletions(-) diff --git a/elements/Ellipse.js b/elements/Ellipse.js index 42668779..948351b8 100644 --- a/elements/Ellipse.js +++ b/elements/Ellipse.js @@ -28,6 +28,7 @@ class Ellipse extends Shape{ render() { let props = this.props; + return this.root = ele} {...this.extractProps(props)} diff --git a/ios/Brushes/RNSVGBaseBrush.m b/ios/Brushes/RNSVGBaseBrush.m index ae907382..2732fd52 100644 --- a/ios/Brushes/RNSVGBaseBrush.m +++ b/ios/Brushes/RNSVGBaseBrush.m @@ -28,6 +28,11 @@ - (void)paint:(CGContextRef)context opacity:(CGFloat)opacity brushConverter:(RNSVGBrushConverter *)brushConverter { + BOOL transparency = opacity < 1; + if (transparency) { + CGContextSetAlpha(context, opacity); + CGContextBeginTransparencyLayer(context, NULL); + } if (brushConverter.type == kRNSVGLinearGradient) { [brushConverter drawLinearGradient:context]; @@ -36,6 +41,10 @@ } else if (brushConverter.type == kRNSVGPattern) { // todo: } + + if (transparency) { + CGContextEndTransparencyLayer(context); + } } @end diff --git a/ios/Brushes/RNSVGBrushConverter.m b/ios/Brushes/RNSVGBrushConverter.m index f2b164b0..5f349ce4 100644 --- a/ios/Brushes/RNSVGBrushConverter.m +++ b/ios/Brushes/RNSVGBrushConverter.m @@ -58,6 +58,7 @@ CGAffineTransform transform = CGAffineTransformMakeScale(1, ry / rx); CGContextConcatCTM(context, transform); + CGContextDrawRadialGradient(context, gradient, CGPointMake(fx, fy), 0, CGPointMake(cx, cy), rx, extendOptions); CGGradientRelease(gradient); } diff --git a/ios/Elements/RNSVGPath.m b/ios/Elements/RNSVGPath.m index 13393297..3692d18c 100644 --- a/ios/Elements/RNSVGPath.m +++ b/ios/Elements/RNSVGPath.m @@ -59,7 +59,7 @@ CGContextAddPath(context, self.d); CGContextClip(context); RNSVGBrushConverter *brushConverter = [[self getSvgView] getDefinedBrushConverter:[self.fill brushRef]]; - [self.fill paint:context opacity:self.strokeOpacity brushConverter:brushConverter]; + [self.fill paint:context opacity:self.fillOpacity brushConverter:brushConverter]; CGContextRestoreGState(context); if (!self.stroke) { return; diff --git a/ios/Elements/RNSVGUse.m b/ios/Elements/RNSVGUse.m index 13a67d87..9efe19c6 100644 --- a/ios/Elements/RNSVGUse.m +++ b/ios/Elements/RNSVGUse.m @@ -23,21 +23,12 @@ { RNSVGNode* template = [[self getSvgView] getDefinedTemplate:self.href]; if (template) { - CGFloat opacity = self.opacity; - BOOL transparent = opacity < 1; - - if (transparent) { - CGContextBeginTransparencyLayer(context, NULL); - } - + [self beginTransparencyLayer:context]; [self clip:context]; [template mergeProperties:self mergeList:self.mergeList]; [template renderTo:context]; [template resetProperties]; - - if (transparent) { - CGContextEndTransparencyLayer(context); - } + [self endTransparencyLayer:context]; } else if (self.href) { // TODO: calling yellow box here RCTLogWarn(@"`Use` element expected a pre-defined svg template as `href` prop, template named: %@ is not defined.", self.href); diff --git a/ios/RNSVGNode.h b/ios/RNSVGNode.h index 8b89adf2..029262f3 100644 --- a/ios/RNSVGNode.h +++ b/ios/RNSVGNode.h @@ -76,4 +76,8 @@ */ - (void)resetProperties; +- (void)beginTransparencyLayer:(CGContextRef)context; + +- (void)endTransparencyLayer:(CGContextRef)context; + @end diff --git a/ios/RNSVGNode.m b/ios/RNSVGNode.m index 88f06eca..6f901719 100644 --- a/ios/RNSVGNode.m +++ b/ios/RNSVGNode.m @@ -11,6 +11,9 @@ #import "RNSVGClipPath.h" @implementation RNSVGNode +{ + BOOL transparent; +} - (void)insertReactSubview:(UIView *)subview atIndex:(NSInteger)atIndex { @@ -52,8 +55,9 @@ } else if (opacity > 1) { opacity = 1; } - + [self invalidate]; + transparent = opacity < 1; _opacity = opacity; } @@ -63,27 +67,33 @@ super.transform = transform; } +- (void)beginTransparencyLayer:(CGContextRef)context +{ + if (transparent) { + CGContextBeginTransparencyLayer(context, NULL); + } +} + +- (void)endTransparencyLayer:(CGContextRef)context +{ + if (transparent) { + CGContextEndTransparencyLayer(context); + } +} + - (void)renderTo:(CGContextRef)context { float opacity = self.opacity; - BOOL transparent = opacity < 1; - // This needs to be painted on a layer before being composited. CGContextSaveGState(context); CGContextConcatCTM(context, self.transform); CGContextSetAlpha(context, opacity); - if (transparent) { - CGContextBeginTransparencyLayer(context, NULL); - } - + [self beginTransparencyLayer:context]; [self renderClip:context]; [self renderLayerTo:context]; - - if (transparent) { - CGContextEndTransparencyLayer(context); - } + [self endTransparencyLayer:context]; CGContextRestoreGState(context); }