我有一个从下面的代码生成的NSBezierPath,我想把这个路径变成一个svg文件(参见下面的svg代码(,我可以导入到Adobe Illustrator中。任何想法如何做到这一点?
贝塞尔路径描述
NSColor* color0 = [NSColor colorWithCalibratedRed: 0 green: 0 blue: 0 alpha: 1];
{
//// Bezier Drawing
NSBezierPath* bezierPath = [NSBezierPath bezierPath];
[bezierPath moveToPoint: NSMakePoint(2, 30.41)];
[bezierPath curveToPoint: NSMakePoint(8.41, 1.91) controlPoint1: NSMakePoint(5.73, 41.21) controlPoint2: NSMakePoint(17.37, 63.33)];
[bezierPath curveToPoint: NSMakePoint(49.79, 1.53) controlPoint1: NSMakePoint(45.32, 94.95) controlPoint2: NSMakePoint(41.89, 1.26)];
[bezierPath setMiterLimit: 4];
[bezierPath setLineCapStyle: NSRoundLineCapStyle];
[bezierPath setLineJoinStyle: NSRoundLineJoinStyle];
[color0 setStroke];
[bezierPath setLineWidth: 3];
[bezierPath stroke];
}
SVG 说明
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="200px" height="200px" viewBox="0 0 200 200" enable-background="new 0 0 200 200" xml:space="preserve">
<g id="n1">
<path fill="none" stroke="#000000" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" d="M2,169.585
c3.73-10.794,15.369-32.913,6.406,28.508c36.91-93.04,33.489,0.644,41.384,0.381"/>
</g>
</svg>
一些意见
BezierPath 使用 [NSBezierPath bezierPath] 来指示路径数据的开始,而 svg 使用 d = "路径数据"。
BezierPath 使用 moveToPoint,而 svg 使用 M。
BezierPath 使用 curveToPoint,而 svg 使用 c。
SVG 不使用空格,而是使用非常紧凑的形式。
BezierPath 使用绝对坐标,而 svg 使用相对坐标。
对于曲线,BezierPath 使用顺序 "point, controlPoint1,controlPoint2",而 svg 使用顺序 "controlPoint1, controlPoint2, point"。
观察我们在 svg 中将路径嵌入到一个 width="200px" height="200px" 的框中。
使用这些观察结果,我们可以将BezierPath描述转换为svg描述,如下所示:
- moveToPoint: NSMakePoint(2, 30.41(]
转换为 M2,169.59 (M=MoveToPoint, 2=2, 200-30.41=169.59(
- curveToPoint: NSMakePoint(8.41, 1.91( controlPoint1: NSMakePoint(
- 5.73, 41.21( controlPoint2: NSMakePoint(17.37, 63.33(]
被翻译成
C3.73-10.794,15.369-32.913,6.406,28.508
(c=曲线点, 3.73=5.73-2, -10.8=30.41-41.21,15.37=17.37-2, 32.89=63.3-30.41, 6.41=8.41-2, 28.5=30.41-1.91((
等等
我想我可以使用这些观察来制作自己的翻译,但如果已经有我可以使用的书面代码,那会更好、更通用。
这是一个解决我问题的解决方案。但它只适用于贝塞尔路径。请注意,我只是在填写路径数据。这之前必须有一些类型的静态文本。如果有人有更通用或更好的解决方案,我想听听。
<?xml version="1.0" encoding="utf-8"?>
...
stroke-linejoin="round
另请注意,我使用的是 200x200 的画布(因此翻转 y 坐标时为 200(。
-(NSString *)svgFromBezierPath:(NSBezierPath *)path {
int numElements = (int) [path elementCount];
if (numElements == 0) {
return nil;
}
NSString *result = @"d="";
NSPoint points[3];
NSString *xStr;
NSString *yStr;
NSString *xCp1;
NSString *yCp1;
NSString *xCp2;
NSString *yCp2;
NSString *temp;
double yValue;
for (int i=0; i < numElements; i++)
{
switch ([path elementAtIndex:i associatedPoints:points])
{
case NSMoveToBezierPathElement:
xStr = [NSString stringWithFormat:@"%0.2f", points[0].x];
yValue = 200 - points[0].y;
yStr = [NSString stringWithFormat:@"%0.2f", yValue];
temp = [NSString stringWithFormat:@"M%@,%@,",xStr, yStr];
result = [result stringByAppendingString:temp];
break;
case NSLineToBezierPathElement:
xStr = [NSString stringWithFormat:@"%0.2f", points[0].x];
yValue = 200 - points[0].y;
yStr = [NSString stringWithFormat:@"%0.2f", yValue];
temp = [NSString stringWithFormat:@"L%@,%@,",xStr, yStr];
result = [result stringByAppendingString:temp];
break;
case NSCurveToBezierPathElement:
xStr = [NSString stringWithFormat:@"%0.2f", points[0].x];
yValue = 200 - points[0].y;
yStr = [NSString stringWithFormat:@"%0.2f", yValue];
xCp1 = [NSString stringWithFormat:@"%0.2f", points[1].x];
yValue = 200 - points[1].y;
yCp1= [NSString stringWithFormat:@"%0.2f", yValue];
xCp2 = [NSString stringWithFormat:@"%0.2f", points[2].x];
yValue = 200 - points[2].y;
yCp2= [NSString stringWithFormat:@"%0.2f", yValue];
temp = [NSString stringWithFormat:@"C%@,%@,%@,%@,%@,%@,", xStr, yStr, xCp1, yCp1,xCp2, yCp2];
result = [result stringByAppendingString:temp];
break;
case NSClosePathBezierPathElement:
result = [result stringByAppendingString:@"z,"];
break;
}
}
result = [result substringToIndex:result.length-1]; // delete the trailing comma
result = [result stringByAppendingString:@""/></svg>"];
return result;
}