Поэтому в настоящее время я работаю над подклассом UIView, который использует TBXML для анализа файлов SVG XML и удаления 'g' инструкции пути. Затем он передает эти наборы инструкций в SvgToBezier — простой синтаксический анализатор, который принимает инструкции пути в качестве входных данных и возвращает объект UIBezierPath. Затем он рисует их в методе drawRect.
Пути отображаются нормально, но проблема в том, что они не совпадают друг с другом так, как должны (они отображаются в google chrome, adobe illustrator и т. д.)
Я знаю, что библиотека SVGKit позволяет анализировать сложные файлы svg, однако я хочу написать это самостоятельно, чтобы расширить свое понимание задействованных концепций.
Сначала я покажу вам свой метод drawRect, затем пример SVG-файла, его ожидаемый результат и фактический результат, нарисованный на iPhone в прямоугольнике 300x300.
- (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);
}
Вот ожидаемый результат рисования
А вот фактический вывод iPhone (скриншот из симулятора iOS)
Я экспериментировал со всеми видами вычислений и CGAffineTransforms.. оставил все это вне кода, потому что это просто запутает вещи imo.
Спасибо за любую помощь!
Ваше здоровье
РЕДАКТИРОВАТЬ: Включая еще один случай, просто чтобы проиллюстрировать непоследовательность (непротиворечивость?) проблемы.