Thursday, June 25, 2009

NanoSVG


I like prototyping. Over the years I have gathered small pieces of code I seem to rewrite every time I land to a work environment. This is my first attempt at storing these interesting bits for other people to use too (and to save myself the trouble of finding the previous version from some half broken hard drive).

NanoSVG is simple and stupid SVG parser that does not need ay external libraries. Just blob the header and a source file into your project and your ready to enjoy vector paths! It is just enough that you can do all your level editing in Inkscape or Illustrator, hit save and play your new level.

I usually use colors to encode different things. For example red squares could be enemy spawn locations and green square the starting point of the player. If you need modifiers, just add outlines, so that red box with blue outline means a grunt with a SMG.

As you might have guessed my prototypes often look like geometry wars. I tend to use OpenGL to draw antialiased lines, points and some text. The point is to build something just enough to get validation or better insight to your ideas.

This version of the SVG parser is based on the Antigrain Geometry SVG example, and I wrote similar parser with Kimmo when I was working with Mountain Sheep.

2 comments:

  1. Hi,

    I've looking for a while a simple yet powerful SVG parser, and gest what... you saved my a...

    I was writing my own parser for for an iPhone app, my parser works for rectangles and polygons (I know, the easiest ones), but as every shape can be converted into paths, I beter use yours and modifi it to parse rects and polys too, plus some XML meta data that I need for Box2D

    Thanks for your work ;-)

    ReplyDelete
  2. Hi, first of all, thank you for the library.
    I just been found a bug in the curve parser:

    cpx2 and cpy2 are uninitializated and shows invalid values (you can test it with tiger.svg)

    In the file nanosvg.c, line 985, It should be like this:
    // --------------------------------------
    case 'C':
    case 'c':
    cpx2 = cpx;
    cpy2 = cpy;
    pathCubicBezTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 'c' ? 1 : 0);
    break;
    case 'S':
    case 's':
    cpx2 = cpx;
    cpy2 = cpy;
    pathCubicBezShortTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 's' ? 1 : 0);
    break;
    case 'Q':
    case 'q':
    cpx2 = cpx;
    cpy2 = cpy;
    pathQuadBezTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 'q' ? 1 : 0);
    break;
    case 'T':
    case 't':
    cpx2 = cpx;
    cpy2 = cpy;
    pathQuadBezShortTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 's' ? 1 : 0);
    break;
    //--------------------------------------

    Regards ^^

    ReplyDelete