Fix memory issue with ClipPath

Fix memory issue with ClipPath.
This commit is contained in:
Horcrux
2016-11-11 13:25:16 +08:00
parent aae482236d
commit 0434cddc8b
15 changed files with 77 additions and 80 deletions

View File

@@ -17,7 +17,7 @@
- (void)saveDefinition - (void)saveDefinition
{ {
[[self getSvgView] defineClipPath:self clipPathRef:self.name]; [[self getSvgView] defineClipPath:self clipPathName:self.name];
} }

View File

@@ -46,7 +46,7 @@
- (CGPathRef)getPath:(CGContextRef)context - (CGPathRef)getPath:(CGContextRef)context
{ {
CGMutablePathRef path = CGPathCreateMutable(); CGMutablePathRef __block path = CGPathCreateMutable();
[self traverseSubviews:^(RNSVGNode *node) { [self traverseSubviews:^(RNSVGNode *node) {
CGAffineTransform transform = node.matrix; CGAffineTransform transform = node.matrix;
CGPathAddPath(path, &transform, [node getPath:context]); CGPathAddPath(path, &transform, [node getPath:context]);
@@ -60,6 +60,11 @@
{ {
CGAffineTransform matrix = CGAffineTransformConcat(self.matrix, transform); CGAffineTransform matrix = CGAffineTransformConcat(self.matrix, transform);
CGPathRef clip = [self getComputedClipPath];
if (clip && !CGPathContainsPoint(clip, nil, point, NO)) {
return nil;
}
for (RNSVGNode *node in [self.subviews reverseObjectEnumerator]) { for (RNSVGNode *node in [self.subviews reverseObjectEnumerator]) {
if ([node isKindOfClass:[RNSVGNode class]]) { if ([node isKindOfClass:[RNSVGNode class]]) {
if (event) { if (event) {
@@ -87,7 +92,7 @@
{ {
if (self.name) { if (self.name) {
RNSVGSvgView* svg = [self getSvgView]; RNSVGSvgView* svg = [self getSvgView];
[svg defineTemplate:self templateRef:self.name]; [svg defineTemplate:self templateName:self.name];
} }
[self traverseSubviews:^(RNSVGNode *node) { [self traverseSubviews:^(RNSVGNode *node) {

View File

@@ -94,7 +94,7 @@
{ {
CGRect rect = [self getRect:context]; CGRect rect = [self getRect:context];
// add hit area // add hit area
self.hitArea = CFAutorelease(CGPathCreateWithRect(rect, nil)); self.hitArea = CGPathCreateWithRect(rect, nil);
[self clip:context]; [self clip:context];
CGContextSaveGState(context); CGContextSaveGState(context);
@@ -152,7 +152,7 @@
- (CGPathRef)getPath:(CGContextRef)context - (CGPathRef)getPath:(CGContextRef)context
{ {
return CGPathCreateWithRect([self getRect:context], nil); return (CGPathRef)CFAutorelease(CGPathCreateWithRect([self getRect:context], nil));
} }
@end @end

View File

@@ -32,7 +32,7 @@
converter.colors = self.gradient; converter.colors = self.gradient;
converter.points = @[self.x1, self.y1, self.x2, self.y2]; converter.points = @[self.x1, self.y1, self.x2, self.y2];
converter.type = kRNSVGLinearGradient; converter.type = kRNSVGLinearGradient;
[[self getSvgView] defineBrushConverter:converter brushConverterRef:self.name]; [[self getSvgView] defineBrushConverter:converter brushConverterName:self.name];
} }
@end @end

View File

@@ -40,17 +40,17 @@
if ([self getSvgView].responsible) { if ([self getSvgView].responsible) {
// Add path to hitArea // Add path to hitArea
CGMutablePathRef hitArea = CGPathCreateMutableCopy(path); CGMutablePathRef hitAreaPath = CGPathCreateMutableCopy(path);
if (self.stroke) { if (self.stroke) {
// Add stroke to hitArea // Add stroke to hitArea
CGPathRef strokePath = CGPathCreateCopyByStrokingPath(hitArea, nil, self.strokeWidth, self.strokeLinecap, self.strokeLinejoin, self.strokeMiterlimit); CGPathRef strokePath = CGPathCreateCopyByStrokingPath(hitAreaPath, nil, self.strokeWidth, self.strokeLinecap, self.strokeLinejoin, self.strokeMiterlimit);
CGPathAddPath(hitArea, nil, strokePath); CGPathAddPath(hitAreaPath, nil, strokePath);
CGPathRelease(strokePath); CGPathRelease(strokePath);
} }
CGAffineTransform transform = self.matrix; CGAffineTransform transform = self.matrix;
self.hitArea = CFAutorelease(CGPathCreateCopyByTransformingPath(hitArea, &transform)); self.hitArea = CGPathCreateCopyByTransformingPath(hitAreaPath, &transform);
CGPathRelease(hitArea); CGPathRelease(hitAreaPath);
} }
if (self.opacity == 0) { if (self.opacity == 0) {

View File

@@ -30,7 +30,7 @@
converter.colors = self.gradient; converter.colors = self.gradient;
converter.points = @[self.fx, self.fy, self.rx, self.ry, self.cx, self.cy]; converter.points = @[self.fx, self.fy, self.rx, self.ry, self.cx, self.cy];
converter.type = kRNSVGRadialGradient; converter.type = kRNSVGRadialGradient;
[[self getSvgView] defineBrushConverter:converter brushConverterRef:self.name]; [[self getSvgView] defineBrushConverter:converter brushConverterName:self.name];
} }
@end @end

View File

@@ -19,12 +19,12 @@
/** /**
* define <ClipPath></ClipPath> content as clipPath template. * define <ClipPath></ClipPath> content as clipPath template.
*/ */
- (void)defineClipPath:(__kindof RNSVGNode *)clipPath clipPathRef:(NSString *)clipPathRef; - (void)defineClipPath:(__kindof RNSVGNode *)clipPath clipPathName:(NSString *)clipPathName;
- (RNSVGNode *)getDefinedClipPath:(NSString *)clipPathRef; - (RNSVGNode *)getDefinedClipPath:(NSString *)clipPathName;
- (void)defineTemplate:(__kindof RNSVGNode *)template templateRef:(NSString *)templateRef; - (void)defineTemplate:(__kindof RNSVGNode *)template templateName:(NSString *)templateName;
- (RNSVGNode *)getDefinedTemplate:(NSString *)tempalteRef; - (RNSVGNode *)getDefinedTemplate:(NSString *)templateName;
- (void)defineBrushConverter:(RNSVGBrushConverter *)brushConverter brushConverterRef:(NSString *)brushConverterRef; - (void)defineBrushConverter:(RNSVGBrushConverter *)brushConverter brushConverterName:(NSString *)brushConverterName;
- (RNSVGBrushConverter *)getDefinedBrushConverter:(NSString *)brushConverterRef; - (RNSVGBrushConverter *)getDefinedBrushConverter:(NSString *)brushConverterName;
- (NSString *)getDataURL; - (NSString *)getDataURL;
@end @end

View File

@@ -83,44 +83,44 @@
self.backgroundColor = inheritedBackgroundColor; self.backgroundColor = inheritedBackgroundColor;
} }
- (void)defineClipPath:(__kindof RNSVGNode *)clipPath clipPathRef:(NSString *)clipPathRef - (void)defineClipPath:(__kindof RNSVGNode *)clipPath clipPathName:(NSString *)clipPathName
{ {
if (!clipPaths) { if (!clipPaths) {
clipPaths = [[NSMutableDictionary alloc] init]; clipPaths = [[NSMutableDictionary alloc] init];
} }
[clipPaths setObject:clipPath forKey:clipPathRef]; [clipPaths setObject:clipPath forKey:clipPathName];
} }
- (RNSVGNode *)getDefinedClipPath:(NSString *)clipPathRef - (RNSVGNode *)getDefinedClipPath:(NSString *)clipPathName
{ {
return clipPaths ? [clipPaths objectForKey:clipPathRef] : nil; return clipPaths ? [clipPaths objectForKey:clipPathName] : nil;
} }
- (void)defineTemplate:(RNSVGNode *)template templateRef:(NSString *)templateRef - (void)defineTemplate:(RNSVGNode *)template templateName:(NSString *)templateName
{ {
if (!templates) { if (!templates) {
templates = [[NSMutableDictionary alloc] init]; templates = [[NSMutableDictionary alloc] init];
} }
[templates setObject:template forKey:templateRef]; [templates setObject:template forKey:templateName];
} }
- (RNSVGNode *)getDefinedTemplate:(NSString *)tempalteRef - (RNSVGNode *)getDefinedTemplate:(NSString *)templateName
{ {
return templates ? [templates objectForKey:tempalteRef] : nil; return templates ? [templates objectForKey:templateName] : nil;
} }
- (void)defineBrushConverter:(RNSVGBrushConverter *)brushConverter brushConverterRef:(NSString *)brushConverterRef - (void)defineBrushConverter:(RNSVGBrushConverter *)brushConverter brushConverterName:(NSString *)brushConverterName
{ {
if (!brushConverters) { if (!brushConverters) {
brushConverters = [[NSMutableDictionary alloc] init]; brushConverters = [[NSMutableDictionary alloc] init];
} }
[brushConverters setObject:brushConverter forKey:brushConverterRef]; [brushConverters setObject:brushConverter forKey:brushConverterName];
} }
- (RNSVGBrushConverter *)getDefinedBrushConverter:(NSString *)brushConverterRef - (RNSVGBrushConverter *)getDefinedBrushConverter:(NSString *)brushConverterName
{ {
return brushConverters ? [brushConverters objectForKey:brushConverterRef] : nil; return brushConverters ? [brushConverters objectForKey:brushConverterName] : nil;
} }
@end @end

View File

@@ -20,8 +20,7 @@
@property (nonatomic, strong) NSString *name; @property (nonatomic, strong) NSString *name;
@property (nonatomic, assign) CGFloat opacity; @property (nonatomic, assign) CGFloat opacity;
@property (nonatomic, assign) RNSVGCGFCRule clipRule; @property (nonatomic, assign) RNSVGCGFCRule clipRule;
@property (nonatomic, assign) CGPathRef clipPath; // convert clipPath="M0,0 L0,10 L10,10z" into path @property (nonatomic, assign) NSString *clipPath;
@property (nonatomic, strong) NSString *clipPathRef; // use clipPath="url(#clip)" as ClipPath
@property (nonatomic, assign) BOOL responsible; @property (nonatomic, assign) BOOL responsible;
@property (nonatomic, assign) CGAffineTransform matrix; @property (nonatomic, assign) CGAffineTransform matrix;
@property (nonatomic, assign) BOOL active; @property (nonatomic, assign) BOOL active;
@@ -37,10 +36,8 @@
*/ */
- (void)renderLayerTo:(CGContextRef)context; - (void)renderLayerTo:(CGContextRef)context;
- (void)renderClip:(CGContextRef)context;
/** /**
* clip node by clipPath or clipPathRef. * clip node by clipPath
*/ */
- (void)clip:(CGContextRef)context; - (void)clip:(CGContextRef)context;
@@ -49,6 +46,10 @@
*/ */
- (CGPathRef)getPath:(CGContextRef) context; - (CGPathRef)getPath:(CGContextRef) context;
/**
* getComputedClipPath will return the CGPathRef computed with clipPath
*/
- (CGPathRef)getComputedClipPath;
/** /**
* run hitTest * run hitTest

View File

@@ -13,6 +13,7 @@
@implementation RNSVGNode @implementation RNSVGNode
{ {
BOOL _transparent; BOOL _transparent;
CGPathRef _computedClipPath;
} }
- (instancetype)init - (instancetype)init
@@ -78,24 +79,14 @@
_matrix = matrix; _matrix = matrix;
} }
- (void)setClipPath:(CGPathRef)clipPath - (void)setClipPath:(NSString *)clipPath
{ {
if (_clipPath == clipPath) { if (_clipPath == clipPath) {
return; return;
} }
[self invalidate]; [self invalidate];
CGPathRelease(_clipPath); _clipPath = clipPath;
_clipPath = CGPathRetain(clipPath);
}
- (void)setClipPathRef:(NSString *)clipPathRef
{
if (_clipPathRef == clipPathRef) {
return;
}
[self invalidate];
self.clipPath = nil;
_clipPathRef = clipPathRef;
} }
- (void)beginTransparencyLayer:(CGContextRef)context - (void)beginTransparencyLayer:(CGContextRef)context
@@ -117,27 +108,38 @@
// abstract // abstract
} }
- (void)renderClip:(CGContextRef)context
{
if (self.clipPathRef) {
self.clipPath = [[[self getSvgView] getDefinedClipPath:self.clipPathRef] getPath:context];
}
}
- (void)clip:(CGContextRef)context - (void)clip:(CGContextRef)context
{ {
CGPathRef clipPath = self.clipPath; if (self.clipPath) {
CGPathRef clip = [[[self getSvgView] getDefinedClipPath:self.clipPath] getPath:context];
if (clipPath) { if (!clip) {
CGContextAddPath(context, clipPath); // TODO: WARNING ABOUT THIS
return;
}
CGContextAddPath(context, clip);
if (self.clipRule == kRNSVGCGFCRuleEvenodd) { if (self.clipRule == kRNSVGCGFCRuleEvenodd) {
CGContextEOClip(context); CGContextEOClip(context);
} else { } else {
CGContextClip(context); CGContextClip(context);
} }
CGAffineTransform matrix = self.matrix;
[self computeClipPath:CGPathCreateCopyByTransformingPath(clip, &matrix)];
} }
} }
- (CGPathRef)getComputedClipPath{
return _computedClipPath;
}
- (void)computeClipPath:(CGPathRef)computedClipPath
{
CGPathRelease(_computedClipPath);
_computedClipPath = computedClipPath;
}
- (CGPathRef)getPath: (CGContextRef) context - (CGPathRef)getPath: (CGContextRef) context
{ {
// abstract // abstract
@@ -149,10 +151,8 @@
// abstract // abstract
} }
// hitTest delagate
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{ {
// abstract // abstract
return nil; return nil;
} }
@@ -177,7 +177,7 @@
{ {
if (self.name) { if (self.name) {
RNSVGSvgView* svg = [self getSvgView]; RNSVGSvgView* svg = [self getSvgView];
[svg defineTemplate:self templateRef:self.name]; [svg defineTemplate:self templateName:self.name];
} }
} }
@@ -198,7 +198,7 @@
- (void)dealloc - (void)dealloc
{ {
CGPathRelease(_clipPath); CGPathRelease(_computedClipPath);
} }
@end @end

View File

@@ -137,9 +137,8 @@
return; return;
} }
[self invalidate];
CGPathRelease(_hitArea); CGPathRelease(_hitArea);
_hitArea = CGPathRetain(hitArea); _hitArea = CGPathRetain(CFAutorelease(hitArea));
} }
- (void)setPropList:(NSArray<NSString *> *)propList - (void)setPropList:(NSArray<NSString *> *)propList
@@ -168,7 +167,6 @@
CGContextSetAlpha(context, self.opacity); CGContextSetAlpha(context, self.opacity);
[self beginTransparencyLayer:context]; [self beginTransparencyLayer:context];
[self renderClip:context];
[self renderLayerTo:context]; [self renderLayerTo:context];
[self endTransparencyLayer:context]; [self endTransparencyLayer:context];
@@ -191,14 +189,14 @@
} }
CGPathRef hitArea = CGPathCreateCopyByTransformingPath(self.hitArea, &transfrom); CGPathRef hitArea = CGPathCreateCopyByTransformingPath(self.hitArea, &transfrom);
CGPathRef clipPath = self.clipPath;
BOOL contains = CGPathContainsPoint(hitArea, nil, point, NO); BOOL contains = CGPathContainsPoint(hitArea, nil, point, NO);
CGPathRelease(hitArea); CGPathRelease(hitArea);
if (contains) { if (contains) {
if (!clipPath) { CGPathRef clipPath = [self getComputedClipPath];
return self; if (clipPath) {
} else {
return CGPathContainsPoint(clipPath, nil, point, NO) ? self : nil; return CGPathContainsPoint(clipPath, nil, point, NO) ? self : nil;
} else {
return self;
} }
} else { } else {
return nil; return nil;

View File

@@ -35,7 +35,6 @@
CGMutablePathRef shape = [self getTextGroupPath:context]; CGMutablePathRef shape = [self getTextGroupPath:context];
CGAffineTransform translation = CGAffineTransformMakeTranslation([self getShift:context path:shape], 0); CGAffineTransform translation = CGAffineTransformMakeTranslation([self getShift:context path:shape], 0);
CGMutablePathRef path = CGPathCreateCopyByTransformingPath(shape, &translation); CGMutablePathRef path = CGPathCreateCopyByTransformingPath(shape, &translation);
CGPathRelease(shape);
return (CGPathRef)CFAutorelease(path); return (CGPathRef)CFAutorelease(path);
} }

View File

@@ -32,8 +32,7 @@ RCT_EXPORT_MODULE()
RCT_EXPORT_VIEW_PROPERTY(name, NSString) RCT_EXPORT_VIEW_PROPERTY(name, NSString)
RCT_EXPORT_VIEW_PROPERTY(opacity, CGFloat) RCT_EXPORT_VIEW_PROPERTY(opacity, CGFloat)
RCT_EXPORT_VIEW_PROPERTY(matrix, CGAffineTransform) RCT_EXPORT_VIEW_PROPERTY(matrix, CGAffineTransform)
RCT_EXPORT_VIEW_PROPERTY(clipPathRef, NSString) RCT_EXPORT_VIEW_PROPERTY(clipPath, NSString)
RCT_EXPORT_VIEW_PROPERTY(clipPath, CGPath)
RCT_EXPORT_VIEW_PROPERTY(clipRule, RNSVGCGFCRule) RCT_EXPORT_VIEW_PROPERTY(clipRule, RNSVGCGFCRule)
RCT_EXPORT_VIEW_PROPERTY(responsible, BOOL) RCT_EXPORT_VIEW_PROPERTY(responsible, BOOL)

View File

@@ -46,10 +46,7 @@ const NodeAttributes = {
}, },
opacity: true, opacity: true,
clipRule: true, clipRule: true,
clipPathRef: true, clipPath: true,
clipPath: {
diff: arrayDiffer
},
propList: { propList: {
diff: arrayDiffer diff: arrayDiffer
}, },

View File

@@ -16,9 +16,7 @@ export default function (props) {
let matched = clipPath.match(clipReg); let matched = clipPath.match(clipReg);
if (matched) { if (matched) {
clippingProps.clipPathRef = matched[1]; clippingProps.clipPath = matched[1];
} else {
clippingProps.clipPath = new SerializablePath(clipPath).toJSON();
} }
} }