Commit 18d7653d authored by Yury Popov's avatar Yury Popov

SVG load fixes + renderer

parent ef0aea3a
......@@ -23,21 +23,23 @@
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];
}
......
......@@ -12,4 +12,5 @@
+ (instancetype) svgImageWithXML:(NSString*)data;
- (instancetype) initWithXML:(NSString*)data;
@property (nonatomic,readonly) CGRect bounds;
- (CALayer*)makeLayer;
@end
......@@ -37,4 +37,8 @@
{
return self.renderPath.bounds;
}
- (CALayer *)makeLayer
{
return [self.renderPath makeLayer];
}
@end
......@@ -20,4 +20,5 @@
- (void) loadData:(NSData*)data;
- (void) loadString:(NSString*)string;
- (void) loadURL:(NSURL*)url;
@property (nonatomic,readonly) CGRect contentRect;
@end
......@@ -58,6 +58,7 @@
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];
......@@ -87,8 +88,10 @@
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];
}];
......@@ -96,6 +99,14 @@
[[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:)])
......@@ -106,6 +117,16 @@
{
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
......@@ -61,7 +61,7 @@
{
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]];
......@@ -98,9 +98,9 @@
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
......@@ -171,7 +171,7 @@
[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;
......@@ -195,7 +195,6 @@
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);
}
......
......@@ -13,4 +13,5 @@
+ (instancetype) pathWithXML:(pxXMLNode*)xmlNode;
- (instancetype) initWithXML:(pxXMLNode*)xmlNode;
@property (readonly) CGRect bounds;
- (CALayer*)makeLayer;
@end
......@@ -24,7 +24,7 @@
- (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;
......@@ -72,7 +72,7 @@
}
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;
......@@ -94,14 +94,55 @@
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
......@@ -18,6 +18,7 @@
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
self.contentMode = UIViewContentModeScaleAspectFit;
pxSVGLayer *sl = [pxSVGLayer new];
[self.layer addSublayer:sl];
self.svgLayer=sl;
......@@ -33,6 +34,21 @@
- (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];
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment