diff --git a/pxSVG/pxSVGObject.h b/pxSVG/pxSVGObject.h index 89cf6b6..8301eb0 100644 --- a/pxSVG/pxSVGObject.h +++ b/pxSVG/pxSVGObject.h @@ -9,6 +9,8 @@ #import @interface pxSVGObject : NSObject ++ (CATransform3D) transformFromString:(NSString*)string; ++ (UIColor*) colorWithSVGColor:(NSString*)string; - (void) loadAttributes:(NSDictionary*)attributes; - (void) setSubnodes:(NSArray*)subnodes; @property NSString *id; diff --git a/pxSVG/pxSVGObject.m b/pxSVG/pxSVGObject.m index e1ff1d8..1dd55b6 100644 --- a/pxSVG/pxSVGObject.m +++ b/pxSVG/pxSVGObject.m @@ -54,7 +54,7 @@ + (CATransform3D) transformFromString:(NSString*)string } return tr; } -- (UIColor*) colorWithSVGColor:(NSString*)string ++ (UIColor*) colorWithSVGColor:(NSString*)string { if (!string) return nil; string = [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; @@ -103,8 +103,8 @@ - (void)loadAttributes:(NSDictionary *)attributes } } self.id = [ma objectForKey:@"id"]; - self.fillColor = [self colorWithSVGColor:[ma objectForKey:@"fill"]]; - self.strokeColor = [self colorWithSVGColor:[ma objectForKey:@"stroke"]]; + self.fillColor = [self.class colorWithSVGColor:[ma objectForKey:@"fill"]]; + 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"]]; self.opacity = [ma objectForKey:@"opacity"]?[[ma objectForKey:@"opacity"] doubleValue]:1; diff --git a/pxSVG/pxSVGRenderPath.m b/pxSVG/pxSVGRenderPath.m index 383cf32..b34da00 100644 --- a/pxSVG/pxSVGRenderPath.m +++ b/pxSVG/pxSVGRenderPath.m @@ -11,7 +11,7 @@ #import "pxSVGPath.h" @interface pxSVGRenderPath () -@property NSDictionary *defs; +@property NSMutableDictionary *defs; @property pxSVGObject *root; @property CGRect bounds; @end @@ -24,6 +24,7 @@ + (instancetype)pathWithXML:(pxXMLNode *)xmlNode - (instancetype)initWithXML:(pxXMLNode *)xmlNode { self = [super init]; + self.defs = [NSMutableDictionary new]; self.root = [self parseObject:xmlNode inheritAttributes:nil]; if ([xmlNode.attributes objectForKey:@"viewBox"]) { NSArray *vb = [[xmlNode.attributes objectForKey:@"viewBox"] componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; @@ -76,11 +77,48 @@ - (pxSVGObject*)parseObject:(pxXMLNode*)node inheritAttributes:(pxSVGObject*)inh { if ([node.tagName rangeOfString:@":"].location != NSNotFound) return nil; if ([node.tagName isEqualToString:@"metadata"]) return nil; + if ([node.tagName isEqualToString:@"marker"]) return nil; + if ([node.tagName isEqualToString:@"filter"]) return nil; + if ([node.tagName isEqualToString:@"a"]) return nil; + if ([node.tagName isEqualToString:@"use"]) { + NSString *href = [node.attributes objectForKey:@"xlink:href"]; + if (!href) href = [node.attributes objectForKey:@"href"]; + if (!href) return nil; + href = [href substringFromIndex:1]; + pxSVGObject *oobj = [self.defs objectForKey:href], *obj; + if (!oobj) return nil; + obj = [oobj.class new]; + obj.fillColor = oobj.fillColor; + obj.strokeColor = oobj.strokeColor; + obj.strokeWidth = oobj.strokeWidth; + obj.opacity = oobj.opacity; + if ([oobj respondsToSelector:@selector(d)]) + [(id)obj setD:[(id)oobj d]]; + if ([oobj respondsToSelector:@selector(subnodes)]) + [(id)obj setSubnodes:[(id)oobj subnodes]]; + CATransform3D tr = oobj.transform; + if ([node.attributes objectForKey:@"x"]) tr = CATransform3DTranslate(tr, [[node.attributes objectForKey:@"x"] doubleValue], 0, 0); + if ([node.attributes objectForKey:@"y"]) tr = CATransform3DTranslate(tr, 0, [[node.attributes objectForKey:@"y"] doubleValue], 0); + if ([node.attributes objectForKey:@"width"]) { + CGFloat ow = [self objBounds:oobj].size.width, w = [[node.attributes objectForKey:@"width"] doubleValue]; + tr = CATransform3DScale(tr, ow/w, 1, 1); + } + if ([node.attributes objectForKey:@"height"]) { + CGFloat oh = [self objBounds:oobj].size.width, h = [[node.attributes objectForKey:@"height"] doubleValue]; + tr = CATransform3DScale(tr, 1, oh/h, 1); + } + if ([node.attributes objectForKey:@"transform"]) tr = CATransform3DConcat(tr, [pxSVGObject transformFromString:[node.attributes objectForKey:@"transform"]]); + obj.transform = tr; + obj.animations = oobj.animations; + return obj; + } Class objClass = pxSVGObject.class; if ([node.tagName isEqualToString:@"g"]) objClass = pxSVGGroup.class; else if ([node.tagName isEqualToString:@"svg"]) objClass = pxSVGGroup.class; + else if ([node.tagName isEqualToString:@"defs"]) + objClass = pxSVGGroup.class; else if ([node.tagName isEqualToString:@"path"]) objClass = pxSVGPath.class; else if ([node.tagName isEqualToString:@"polygon"]) @@ -100,11 +138,12 @@ - (pxSVGObject*)parseObject:(pxXMLNode*)node inheritAttributes:(pxSVGObject*)inh obj.strokeWidth = inherit.strokeWidth; if (!obj.strokeColor) obj.strokeColor = inherit.strokeColor; + if (obj.id) [self.defs setObject:obj forKey:obj.id]; if (node.childNodes.count) { NSMutableArray *subnodes = [NSMutableArray new]; for (pxXMLNode *n in node.childNodes) { pxSVGObject *o = [self parseObject:n inheritAttributes:obj]; - if (o) { + if (o && ![n.tagName isEqualToString:@"defs"]) { [subnodes addObject:o]; } }