So I am currently working on a subclass of UIView which uses TBXML to parse a SVG XML files and strip the 'g' path instructions out. Then it passes these sets of instructions to SvgToBezier - a simple parser that takes the path instructions as input and returns a UIBezierPath object. Then it draws them in the drawRect method.
The paths render fine, but the problem is they don't line up with each other the way they're supposed to (they way they show up in google chrome, adobe illustrator, etc)
I know the SVGKit library allows parsing of complex svg files, however I want to write this myself so I can expand my understanding of the concepts involved.
First I'll show you my drawRect method, followed by an example SVG file, it's expected output, and it's actual output drawn on the iPhone in a 300x300 rect.
- (void)drawRect:(CGRect)rect
{
//getting the XML from set property
TBXMLElement *root = self.svgRoot.rootXMLElement;
//getting the rect tag, which is the background
TBXMLElement *rectColor = [TBXML childElementNamed:@"rect" parentElement:root];
//getting the first g tag
TBXMLElement *g1 = [TBXML childElementNamed:@"g" parentElement:root];
//and it's child path tag
TBXMLElement *path1 = [TBXML childElementNamed:@"path" parentElement:g1];
//getting the sibbling g tag
TBXMLElement *g2 = g1->nextSibling;
//and it's child path tag
TBXMLElement *path2 = [TBXML childElementNamed:@"path" parentElement:g2];
//create a context reference
CGContextRef ctx = UIGraphicsGetCurrentContext();
//flip the context so the origin points jive
CGContextTranslateCTM(ctx, 0, rect.size.height);
CGContextScaleCTM(ctx, 1.0, -1.0);
//get fill color for first path
const char *str1 = [[TBXML valueOfAttributeNamed:@"fill" forElement:g1] cStringUsingEncoding:NSASCIIStringEncoding];
long x1 = strtol(str1+1, NULL, 16);
UIColor *rgb1 = UIColorFromRGB(x1);
//get fill color for second path
const char *str2 = [[TBXML valueOfAttributeNamed:@"fill" forElement:g2] cStringUsingEncoding:NSASCIIStringEncoding];
long x2 = strtol(str2+1, NULL, 16);
UIColor *rgb2 = UIColorFromRGB(x2);
//get fill color for rect background
const char *str3 = [[TBXML valueOfAttributeNamed:@"fill" forElement:rectColor] cStringUsingEncoding:NSASCIIStringEncoding];
long x3 = strtol(str3+1, NULL, 16);
UIColor *rgb3 = UIColorFromRGB(x3);
//turn them into CGColors
CGColorRef color1 = rgb1.CGColor;
CGColorRef color2 = rgb2.CGColor;
CGColorRef color3 = rgb3.CGColor;
//draw the rect background and fill it
CGContextSetFillColorWithColor(ctx, color3);
CGContextFillRect(ctx, CGRectMake(0, 0, rect.size.width, rect.size.height));
//make a bezier path from the first path tag using SvgToBezier
SvgToBezier *bezier1 = [[SvgToBezier alloc] initFromSVGPathNodeDAttr:[TBXML valueOfAttributeNamed:@"d" forElement:path1] rect:rect];
//make second bezier path
SvgToBezier *bezier2 = [[SvgToBezier alloc] initFromSVGPathNodeDAttr:[TBXML valueOfAttributeNamed:@"d" forElement:path2] rect:rect];
//set fill color for first bezier
CGContextSetFillColorWithColor(ctx, color1);
//draw it
UIBezierPath *bezierPath1 = bezier1.bezier;
CGContextAddPath(ctx, bezierPath1.CGPath);
CGContextDrawPath(ctx, kCGPathEOFill);
//second bezier
CGContextSetFillColorWithColor(ctx, color2);
UIBezierPath *bezierPath2 = bezier2.bezier;
CGContextAddPath(ctx, bezierPath2.CGPath);
CGContextDrawPath(ctx, kCGPathEOFill);
}
Here's the Raw SVG
Here's the Expected Drawing Result
And here's the Actual iPhone Output (screenshot from iOS Simulator)
I've been experimenting with all kinds of calculations and CGAffineTransforms.. left all that out of the code because it will just confuse things imo.
Thanks for any and all help!
Cheers
EDIT: Including another case, just to illustrate the inconsistency (consistency?) of the problem.