Превратите BezierPath в файл SVG - PullRequest
0 голосов
/ 14 сентября 2018

У меня есть NSBezierPath, созданный из кода ниже, и я хочу превратить этот путь в файл SVG (см. Код SVG ниже), который я могу импортировать в Adobe Illustrator. Есть идеи как это сделать?

Описание BezierPath

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 использует порядок «точка, controlPoint1, controlPoint2», в то время как svg использует порядок «controlPoint1, controlPoint2, точка».

Заметьте, что мы встраиваем путь в блок ширины = "200px" height = "200px" в svg.

Используя эти наблюдения, мы могли бы перевести описание BezierPath в описание svg следующим образом:

  1. moveToPoint: NSMakePoint (2, 30,41)]

переведено в M2 169,59 (M = MoveToPoint, 2 = 2, 200-30,41 = 169,59)

  1. 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 = CurveToPoint, 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))

и т. Д.

Полагаю, я мог бы использовать эти наблюдения, чтобы сделать свои собственные переводы, но было бы лучше и более общее, если бы уже был написанный код, который я мог бы использовать.

1 Ответ

0 голосов
/ 15 сентября 2018

Вот одно решение, которое решает мою проблему.Но это работает только для путей Безье.Заметьте, что я только заполняю данные пути.Этому должен предшествовать некоторый статический текст типа ниже.Если у кого-то есть более общее или более хорошее решение, я бы хотел услышать его.

<?xml version="1.0" encoding="utf-8"?>
 ...
stroke-linejoin="round

Заметьте также, что я использую холст размером 200x200 (следовательно, 200 при переключении координат y).

-(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;
}
...