Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
SVG load fixes + renderer
  • Loading branch information
Yury Popov authored and Yury Popov committed May 13, 2015
1 parent ef0aea3 commit 18d7653
Show file tree
Hide file tree
Showing 10 changed files with 98 additions and 12 deletions.
6 changes: 4 additions & 2 deletions pxSVG-TestApp/ViewController.m
Expand Up @@ -23,21 +23,23 @@ - (instancetype)initWithFrame:(CGRect)frame
sv.svgDelegate = self;
sv.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
[self.contentView addSubview:_svgView=sv];
self.clipsToBounds = YES;
return self;
}

- (void)svgViewDidLoadImage:(pxSVGView *)svgView
{
NSLog(@"%@",self.SVGURL);
NSLog(@"load %@",self.SVGURL);
}

- (void)svgView:(pxSVGView *)svgLayer didFailedLoad:(NSError *)error
{
NSLog(@"%@ %@",self.SVGURL,error);
NSLog(@"err %@ %@",self.SVGURL,error);
}

- (void)setSVGURL:(NSURL *)SVGURL
{
_SVGURL = SVGURL;
[self.svgView loadURL:SVGURL];
}

Expand Down
1 change: 1 addition & 0 deletions pxSVG/pxSVGImage.h
Expand Up @@ -12,4 +12,5 @@
+ (instancetype) svgImageWithXML:(NSString*)data;
- (instancetype) initWithXML:(NSString*)data;
@property (nonatomic,readonly) CGRect bounds;
- (CALayer*)makeLayer;
@end
4 changes: 4 additions & 0 deletions pxSVG/pxSVGImage.m
Expand Up @@ -37,4 +37,8 @@ - (CGRect)bounds
{
return self.renderPath.bounds;
}
- (CALayer *)makeLayer
{
return [self.renderPath makeLayer];
}
@end
1 change: 1 addition & 0 deletions pxSVG/pxSVGLayer.h
Expand Up @@ -20,4 +20,5 @@
- (void) loadData:(NSData*)data;
- (void) loadString:(NSString*)string;
- (void) loadURL:(NSURL*)url;
@property (nonatomic,readonly) CGRect contentRect;
@end
23 changes: 22 additions & 1 deletion pxSVG/pxSVGLayer.m
Expand Up @@ -58,6 +58,7 @@ - (void)loadURL:(NSURL *)url
NSBlockOperation *sync = [NSBlockOperation blockOperationWithBlock:^{
if ([op isCancelled]) return;
if (!weakself) return;
weakself.loadOperation = nil;
NSError *error = err;
if (!error && [resp isKindOfClass:[NSHTTPURLResponse class]] && (((NSHTTPURLResponse*)resp).statusCode != 200))
error = [NSError errorWithDomain:@"pxSVGLoader.httpStatus" code:((NSHTTPURLResponse*)resp).statusCode userInfo:nil];
Expand Down Expand Up @@ -87,15 +88,25 @@ - (void)loadString:(NSString *)string
if ([op isCancelled]) return;
NSBlockOperation *sync = [NSBlockOperation blockOperationWithBlock:^{
if ([op isCancelled]) return;
if (!weakself) return;
weakself.parseOperation = nil;
if (!img) return [weakself loadError:[NSError errorWithDomain:@"pxSVGParser.parseError" code:0 userInfo:nil]];
NSLog(@"%@ %@",img,[NSValue valueWithCGRect:img.bounds]);
[weakself loadImage:img];
}];
[[NSOperationQueue mainQueue] addOperations:@[sync] waitUntilFinished:YES];
}];
op.threadPriority = 0.1f;
[[self.class parseQueue] addOperation:self.parseOperation=op];
}

- (void)loadImage:(pxSVGImage*)image
{
[self clean];
[self addSublayer:[image makeLayer]];
if ([self.svgDelegate respondsToSelector:@selector(svgLayerDidLoadImage:)])
[self.svgDelegate svgLayerDidLoadImage:self];
}

- (void)loadError:(NSError *)error
{
if ([self.svgDelegate respondsToSelector:@selector(svgLayer:didFailedLoad:)])
Expand All @@ -106,6 +117,16 @@ - (void)clean
{
if (self.loadOperation) [self.loadOperation cancel];
if (self.parseOperation) [self.parseOperation cancel];
while (self.sublayers.count) [self.sublayers.firstObject removeFromSuperlayer];
}

- (CGRect)contentRect
{
CGRect f = CGRectNull;
for (CALayer *l in self.sublayers) {
f = CGRectUnion(f, l.frame);
}
return f;
}

@end
6 changes: 3 additions & 3 deletions pxSVG/pxSVGObject.m
Expand Up @@ -61,7 +61,7 @@ - (UIColor*) colorWithSVGColor:(NSString*)string
{
if (!string) return nil;
string = [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
if ([string isEqualToString:@"none"]) return nil;
if ([string isEqualToString:@"none"]) return [UIColor clearColor];
if ([string isEqualToString:@"black"]) return [UIColor blackColor];
if ([string isEqualToString:@"white"]) return [UIColor whiteColor];
NSScanner *sc = [NSScanner scannerWithString:[string lowercaseString]];
Expand Down Expand Up @@ -98,9 +98,9 @@ - (void)loadAttributes:(NSDictionary *)attributes
self.id = [attributes objectForKey:@"id"];
self.fillColor = [self colorWithSVGColor:[attributes objectForKey:@"fill"]];
self.strokeColor = [self colorWithSVGColor:[attributes objectForKey:@"stroke"]];
self.strokeWidth = [[attributes objectForKey:@"stroke-width"] doubleValue];
self.strokeWidth = [attributes objectForKey:@"stroke-width"]?[[attributes objectForKey:@"stroke-width"] doubleValue]:NAN;
self.transform = [self.class transformFromString:[attributes objectForKey:@"transform"]];
self.opacity = [[attributes objectForKey:@"opacity"] doubleValue];
self.opacity = [attributes objectForKey:@"opacity"]?[[attributes objectForKey:@"opacity"] doubleValue]:1;
}
- (void)setSubnodes:(NSArray *)subnodes { }
@end
3 changes: 1 addition & 2 deletions pxSVG/pxSVGPath.m
Expand Up @@ -171,7 +171,7 @@ - (void)loadAttributes:(NSDictionary *)attributes
[attributes objectForKey:@"ry"]) {
CGRect r;
r.size.width = [[attributes objectForKey:@"rx"] doubleValue];
r.size.height = [[attributes objectForKey:@"rx"] doubleValue];
r.size.height = [[attributes objectForKey:@"ry"] doubleValue];
r.origin.x = [[attributes objectForKey:@"cx"] doubleValue] - r.size.width;
r.origin.y = [[attributes objectForKey:@"cy"] doubleValue] - r.size.height;
r.size.width *= 2; r.size.height *= 2;
Expand All @@ -195,7 +195,6 @@ - (void)loadAttributes:(NSDictionary *)attributes
r.size.height = [[attributes objectForKey:@"height"] doubleValue];
r.origin.x = [[attributes objectForKey:@"x"] doubleValue];
r.origin.y = [[attributes objectForKey:@"y"] doubleValue];
r.size.width *= 2; r.size.height *= 2;
self.d = [UIBezierPath bezierPathWithRect:r];
} else NSLog(@"%@",attributes);
}
Expand Down
1 change: 1 addition & 0 deletions pxSVG/pxSVGRenderPath.h
Expand Up @@ -13,4 +13,5 @@
+ (instancetype) pathWithXML:(pxXMLNode*)xmlNode;
- (instancetype) initWithXML:(pxXMLNode*)xmlNode;
@property (readonly) CGRect bounds;
- (CALayer*)makeLayer;
@end
49 changes: 45 additions & 4 deletions pxSVG/pxSVGRenderPath.m
Expand Up @@ -24,7 +24,7 @@ + (instancetype)pathWithXML:(pxXMLNode *)xmlNode
- (instancetype)initWithXML:(pxXMLNode *)xmlNode
{
self = [super init];
self.root = [self parseObject:xmlNode];
self.root = [self parseObject:xmlNode inheritAttributes:nil];
if ([xmlNode.attributes objectForKey:@"width"] &&
[xmlNode.attributes objectForKey:@"height"]) {
CGPoint o = CGPointZero;
Expand Down Expand Up @@ -72,7 +72,7 @@ - (CGRect) objBounds:(pxSVGObject*)obj
}
return CGRectNull;
}
- (pxSVGObject*)parseObject:(pxXMLNode*)node
- (pxSVGObject*)parseObject:(pxXMLNode*)node inheritAttributes:(pxSVGObject*)inherit
{
if ([node.tagName rangeOfString:@":"].location != NSNotFound) return nil;
if ([node.tagName isEqualToString:@"metadata"]) return nil;
Expand All @@ -94,14 +94,55 @@ - (pxSVGObject*)parseObject:(pxXMLNode*)node
else NSLog(@"Unknown tag: %@",node.tagName);
pxSVGObject *obj = [objClass new];
[obj loadAttributes:node.attributes];
if (!obj.fillColor)
obj.fillColor = inherit.fillColor;
if (obj.strokeWidth == NAN)
obj.strokeWidth = inherit.strokeWidth;
if (!obj.strokeColor)
obj.strokeColor = inherit.strokeColor;
if (node.childNodes.count) {
NSMutableArray *subnodes = [NSMutableArray new];
for (pxXMLNode *n in node.childNodes) {
pxSVGObject *o = [self parseObject:n];
if (o) [subnodes addObject:o];
pxSVGObject *o = [self parseObject:n inheritAttributes:obj];
if (o) {
[subnodes addObject:o];
}
}
[obj setSubnodes:[NSArray arrayWithArray:subnodes]];
}
return obj;
}
- (CALayer *)makeLayerWithNode:(pxSVGObject*)node withOffset:(CGPoint)off
{
CGRect f = [self objBounds:node];
if (CGRectIsNull(f)) return nil;
CALayer *l;
if ([node respondsToSelector:@selector(d)]) {
CAShapeLayer *sl = [CAShapeLayer new];
CGAffineTransform t = CGAffineTransformMakeTranslation(-f.origin.x, -f.origin.y);
CGPathRef p = CGPathCreateCopyByTransformingPath([(id)node d].CGPath, &t);
sl.path = p;
CGPathRelease(p);
sl.fillColor = (node.fillColor?:[UIColor blackColor]).CGColor;
sl.strokeColor = node.strokeColor.CGColor;
sl.lineWidth = node.strokeWidth==NAN?0:node.strokeWidth;
l = sl;
} else {
l = [CALayer new];
}
l.frame = CGRectOffset(f, -off.x, -off.y);
l.transform = node.transform;
l.opacity = node.opacity;
if ([node respondsToSelector:@selector(subnodes)]) {
for (pxSVGObject *n in [(id)node subnodes]) {
CALayer *sl = [self makeLayerWithNode:n withOffset:(CGPoint){f.origin.x+off.x,f.origin.y+off.y}];
if (sl) [l addSublayer:sl];
}
}
return l;
}
- (CALayer *)makeLayer
{
return [self makeLayerWithNode:self.root withOffset:CGPointZero];
}
@end
16 changes: 16 additions & 0 deletions pxSVG/pxSVGView.m
Expand Up @@ -18,6 +18,7 @@ @implementation pxSVGView
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
self.contentMode = UIViewContentModeScaleAspectFit;
pxSVGLayer *sl = [pxSVGLayer new];
[self.layer addSublayer:sl];
self.svgLayer=sl;
Expand All @@ -33,6 +34,21 @@ - (void)layoutSublayersOfLayer:(CALayer *)layer

- (void)svgLayerDidLoadImage:(pxSVGLayer *)svgLayer
{
CATransform3D tr = CATransform3DIdentity;
CGRect c = svgLayer.contentRect;
switch (self.contentMode) {
case UIViewContentModeScaleAspectFit: {
CGFloat
scx = c.size.width/self.bounds.size.width,
scy = c.size.height/self.bounds.size.height,
sc = MAX(scx,scy);
tr = CATransform3DMakeScale(1/sc, 1/sc, 1);
tr = CATransform3DTranslate(tr, -c.origin.x/sc, -c.origin.y/sc, 0);
break;
}
default: break;
}
[svgLayer setTransform:tr];
if ([self.svgDelegate respondsToSelector:@selector(svgViewDidLoadImage:)])
[self.svgDelegate svgViewDidLoadImage:self];
}
Expand Down

0 comments on commit 18d7653

Please sign in to comment.