From 4c15691768ebd19e613c484f08b604acdb0fbc7c Mon Sep 17 00:00:00 2001 From: Yury Popov Date: Thu, 14 May 2015 20:13:37 +0300 Subject: [PATCH] Clip-paths support --- pxSVG/pxSVGObject.h | 1 + pxSVG/pxSVGObject.m | 5 +++++ pxSVG/pxSVGRenderPath.m | 25 +++++++++++++++++++++++++ 3 files changed, 31 insertions(+) diff --git a/pxSVG/pxSVGObject.h b/pxSVG/pxSVGObject.h index 587e353..fdd36f1 100644 --- a/pxSVG/pxSVGObject.h +++ b/pxSVG/pxSVGObject.h @@ -17,6 +17,7 @@ @property NSArray *animations; @property UIColor *fillColor; @property NSString *fillDef; +@property NSString *clipDef; @property UIColor *strokeColor; @property CGFloat strokeWidth; @property CGFloat opacity; diff --git a/pxSVG/pxSVGObject.m b/pxSVG/pxSVGObject.m index 68f5930..3ce2a14 100644 --- a/pxSVG/pxSVGObject.m +++ b/pxSVG/pxSVGObject.m @@ -108,6 +108,11 @@ - (void)loadAttributes:(NSDictionary *)attributes u = [[u substringWithRange:NSMakeRange(3, u.length-4)] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"\n\r\t ()#"]]; self.fillDef = u; } else self.fillColor = [self.class colorWithSVGColor:[ma objectForKey:@"fill"]]; + if ([ma objectForKey:@"clip-path"]) { + NSString *u = [[ma objectForKey:@"clip-path"] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; + u = [[u substringWithRange:NSMakeRange(3, u.length-4)] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"\n\r\t ()#"]]; + self.clipDef = u; + } self.strokeColor = [self.class colorWithSVGColor:[ma objectForKey:@"stroke"]]; self.strokeWidth = [ma objectForKey:@"stroke-width"]?[[ma objectForKey:@"stroke-width"] doubleValue]:NAN; self.transform = [self.class transformFromString:[ma objectForKey:@"transform"]]; diff --git a/pxSVG/pxSVGRenderPath.m b/pxSVG/pxSVGRenderPath.m index 01338f3..f32f447 100644 --- a/pxSVG/pxSVGRenderPath.m +++ b/pxSVG/pxSVGRenderPath.m @@ -183,6 +183,7 @@ - (pxSVGObject*)reuseObjectWithAttributes:(NSDictionary*)attributes obj.fillOpacity = oobj.fillOpacity; obj.fillColor = oobj.fillColor; obj.fillDef = oobj.fillDef; + obj.clipDef = oobj.clipDef; if ([attributes objectForKey:@"fill"]) { CGFloat a = obj.fillOpacity; if ([[attributes objectForKey:@"fill"] hasPrefix:@"url("]) { @@ -286,6 +287,7 @@ - (pxSVGPattern*)parsePattern:(pxXMLNode*)node p.fillOpacity = op.fillOpacity; p.fillColor = op.fillColor; p.fillDef = op.fillDef; + p.clipDef = op.clipDef; p.strokeColor = op.strokeColor; p.strokeWidth = op.strokeWidth; p.subnodes = op.subnodes; @@ -389,6 +391,7 @@ - (pxSVGObject*)parseObject:(pxXMLNode*)node inheritAttributes:(pxSVGObject*)inh obj.strokeColor = inherit?inherit.strokeColor:nil; if (obj.id) [self.defCache setObject:obj forKey:obj.id]; if (obj.fillDef) [self findDef:obj.fillDef]; + if (obj.clipDef) [self findDef:obj.clipDef]; if (node.childNodes.count) { NSMutableArray *subnodes = [NSMutableArray new]; for (pxXMLNode *n in node.childNodes) { @@ -401,6 +404,19 @@ - (pxSVGObject*)parseObject:(pxXMLNode*)node inheritAttributes:(pxSVGObject*)inh } return obj; } +- (UIBezierPath*)mergePath:(pxSVGObject*)node +{ + UIBezierPath *bp = [UIBezierPath new]; + if ([node respondsToSelector:@selector(d)]) { + [bp appendPath:[(id)node d]]; + } + if ([node respondsToSelector:@selector(subnodes)]) { + for (pxSVGObject *o in [(id)node subnodes]) { + [bp appendPath:[self mergePath:o]]; + } + } + return bp; +} - (CALayer *)makeLayerWithNode:(pxSVGObject*)node rootBounds:(CGRect)bounds; { CALayer *l; @@ -446,6 +462,15 @@ - (CALayer *)makeLayerWithNode:(pxSVGObject*)node rootBounds:(CGRect)bounds; } else { l = [CALayer new]; } + if (node.clipDef) { + id def = [self findDef:node.clipDef]; + if ([def isKindOfClass:[pxSVGObject class]]) { + CAShapeLayer *ml = [CAShapeLayer new]; + ml.frame = (CGRect){CGPointZero,bounds.size}; + ml.path = [self mergePath:def].CGPath; + l.mask = ml; + } + } l.frame = (CGRect){{-bounds.origin.x,-bounds.origin.y},bounds.size}; CATransform3D tr = node.transform; tr = CATransform3DConcat(CATransform3DMakeTranslation( bounds.size.width/2, bounds.size.height/2, 0), tr);