Parsing SVG path in objective-c

2019-04-12 20:54发布

i need to parse some paths of an SVG file, they are simple lines. When retrieving the data i end up with this string:

m 0,666.6479 254.28571,0

According to SVG specifications m denotes a new current point then the following 2 numbers are the position and the laters are relative positions to the first one.

So that would create a line from point (0, 666.6479) to (254.28, 666.64)

How can i parse that in Objective-C so i can end up with those 2 CGPoints or more if there were?

i know that if it finds an m, the following 2 comma separated numbers should be my first point and after each space there are 2 comma separated numbers that i should sum to the current point to get the next one.

What i don't know if how to parse this correctly.

Thanks!

3条回答
来,给爷笑一个
2楼-- · 2019-04-12 21:35

Here is a little proto-type I put together for converting an SVG path to Objective-C. This is by no mean anywhere near complete but it maybe helpful to someone:

http://yepher.com/svg2ios.html

查看更多
干净又极端
3楼-- · 2019-04-12 21:44

The "m" command takes only two parameters: the x and y coordinates. But whereas "M" (uppercase) takes absolute coordinates, "m" (lowercase) takes relative coordinates. Thus, if your current coordinates (before the "m" command") were (100,100), the relative move in your example will bring them to (100, 766.6479).

The fact that there is no new command letter after these two coordinates means that the next command is also a relative move, so that brings you to (354.28571, 766.6479).

From the SVG 1.1 spec:

The command letter can be eliminated on subsequent commands if the same command is used multiple times in a row (e.g., you can drop the second "L" in "M 100 200 L 200 100 L -100 -200" and use "M 100 200 L 200 100 -100 -200" instead).

You can use NSScanner to parse decimal numbers:

NSScanner *scanner = [NSScanner scannerWithString:aString];
float num = 0;
BOOL success = [scanner scanFloat:&num];
if (succes) {
// Do something
}
else {
// Throw exception
}

Correctly parsing SVG files is a bit tricky, because the spec is pretty relaxed about how data is formatted. If you want to write a parser that is robust enough to accept input from any source (Illustrator, InkScape...), I would recommend having a close look at the Batik project's microsyntax parsers. (Although you can get something decent working that might cover your needs without anything near Batik's complexity.)

查看更多
乱世女痞
4楼-- · 2019-04-12 21:46

I would use C directly, as:

const char *str = [myString UTF8String];

while(*str)
{
    switch(*str)
    {
        case 'm':
            state = START;
            break;
        case ' ':
            if(state == START) /* we are just after the m */
            {
                state = POINT;
                point = 0;
                break;
            }
            else if(state == POINT)
            {
                if(sscanf(str, "%f,%f", &x, &y) != 2)
                    /* handle error; */
                /* save point somewhere */
                point++;
            }
            break;
    }
    str++;
}

Please note that I just written that in the edit box, just take it as an example.

The other approach is to use NSScanner, but I feel like the above approach is simpler as per your requirements.

查看更多
登录 后发表回答