Giter Site home page Giter Site logo

nanosvg's Introduction

This project is not actively maintained.

Nano SVG

Parser

screenshot of some splines rendered with the sample program

NanoSVG is a simple stupid single-header-file SVG parse. The output of the parser is a list of cubic bezier shapes.

The library suits well for anything from rendering scalable icons in your editor application to prototyping a game.

NanoSVG supports a wide range of SVG features, but something may be missing, feel free to create a pull request!

The shapes in the SVG images are transformed by the viewBox and converted to specified units. That is, you should get the same looking data as your designed in your favorite app.

NanoSVG can return the paths in few different units. For example if you want to render an image, you may choose to get the paths in pixels, or if you are feeding the data into a CNC-cutter, you may want to use millimeters.

The units passed to NanoSVG should be one of: 'px', 'pt', 'pc' 'mm', 'cm', or 'in'. DPI (dots-per-inch) controls how the unit conversion is done.

If you don't know or care about the units stuff, "px" and 96 should get you going.

Rasterizer

screenshot of tiger.svg rendered with NanoSVG rasterizer

The parser library is accompanied with really simpler SVG rasterizer. Currently it only renders flat filled shapes.

The intended usage for the rasterizer is to for example bake icons of different size into a texture. The rasterizer is not particular fast or accurate, but it's small and packed in one header file.

Example Usage

// Load
struct NSVGimage* image;
image = nsvgParseFromFile("test.svg", "px", 96);
printf("size: %f x %f\n", image->width, image->height);
// Use...
for (shape = image->shapes; shape != NULL; shape = shape->next) {
	for (path = shape->paths; path != NULL; path = path->next) {
		for (i = 0; i < path->npts-1; i += 3) {
			float* p = &path->pts[i*2];
			drawCubicBez(p[0],p[1], p[2],p[3], p[4],p[5], p[6],p[7]);
		}
	}
}
// Delete
nsvgDelete(image);

Using NanoSVG in your project

In order to use NanoSVG in your own project, just copy nanosvg.h to your project. In one C/C++ define NANOSVG_IMPLEMENTATION before including the library to expand the NanoSVG implementation in that file. NanoSVG depends on stdio.h ,string.h and math.h, they should be included where the implementation is expanded before including NanoSVG.

#include <stdio.h>
#include <string.h>
#include <math.h>
#define NANOSVG_IMPLEMENTATION	// Expands implementation
#include "nanosvg.h"

By default, NanoSVG parses only the most common colors. In order to get support for full list of SVG color keywords, define NANOSVG_ALL_COLOR_KEYWORDS before expanding the implementation.

#include <stdio.h>
#include <string.h>
#include <math.h>
#define NANOSVG_ALL_COLOR_KEYWORDS	// Include full list of color keywords.
#define NANOSVG_IMPLEMENTATION		// Expands implementation
#include "nanosvg.h"

Alternatively, you can install the library using CMake and import it into your project using the standard CMake find_package command.

add_executable(myexe main.c)

find_package(NanoSVG REQUIRED)

target_link_libraries(myexe NanoSVG::nanosvg NanoSVG::nanosvgrast)

Compiling Example Project

In order to compile the demo project, your will need to install GLFW to compile.

NanoSVG demo project uses premake4 to build platform specific projects, now is good time to install it if you don't have it already. To build the example, navigate into the root folder in your favorite terminal, then:

  • OS X: premake4 xcode4
  • Windows: premake4 vs2010
  • Linux: premake4 gmake

See premake4 documentation for full list of supported build file types. The projects will be created in build folder. An example of building and running the example on OS X:

$ premake4 gmake
$ cd build/
$ make
$ ./example

License

The library is licensed under zlib license

nanosvg's People

Contributors

authorityfx avatar bryanmcconkey avatar chrismile avatar chrstphrchvz avatar daniel-starke avatar darealshinji avatar deanm avatar djack1010 avatar erco77 avatar fvogelnew1 avatar galibert avatar janrysavy avatar jzrake avatar klapeto avatar lieff avatar luzpaz avatar martinlindhe avatar memononen avatar nigels-com avatar nightlark avatar oehhar avatar sancheung avatar sezero avatar shlyakpavel avatar smilyorg avatar tamasmeszaros avatar tido64 avatar tope99 avatar wcout avatar x-ryl669 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

nanosvg's Issues

<use xlink:href> not working

I am trying to render a very simple file with <use> elements, but it's not rendering correctly. Does nanosvg supports <use>? Here are the contents of my file:

<svg viewBox="0 0 400 100">
    <rect id="original-rect"
        x="100" y="20"
        width="50" height="50"
        fill="#29e" />

    <use xlink:href="#original-rect" x="150" y="10" />
</svg>

Compound path support missing

Hello Mikko,

Thanks for your work, I know you from my work on Kynapse but did not know you were at the origin of nanosvg.

I always wanted to write you about some modifications I made but never find time sorry about that. Now you updated quite some things, so I will upgrade a add compound support back if you are interesting.

Tell me if you need more info.

Thanks again for your work !

Julien.

Unnecessary extra points are added via moveto command

This is due to the pass through from the 'm' + 'M' cases to 'l' and 'L'.

According to the spec - "If a moveto is followed by multiple pairs of coordinates, the subsequent pairs are treated as implicit lineto command", perhaps more correct handling would be:

from line 142

if (nargs >= rargs) {
                        switch (cmd) {
                            case 'm':
                            case 'M':
                                nsvg__pathMoveTo(p, &cpx, &cpy, args, cmd == 'm' ? 1 : 0);
                                cmd = (cmd =='m') ? 'l' : 'L';
                                rargs = nsvg__getArgsPerElement(cmd);
                                break;
                            case 'l':
                            case 'L':

RGB byte order?

Hi, I've noticed that nanosvg encodes RGB values into an integer in reverse order (so it's actually BGR), which was pretty unexpected for me. Is this intentional?

Around line 161:

#define NSVG_RGB(r, g, b) (((unsigned int)r) | ((unsigned int)g << 8) | ((unsigned int)b << 16))

I would expect that line to be this (as is the standard most everywhere else):

#define NSVG_RGB(r, g, b) (((unsigned int)r << 16) | ((unsigned int)g << 8) | ((unsigned int)b))

How to nanovg to render SVG with the data parse from nanosvg?

This is not an issue, but I don't know the way to contact with you.
Hi, I'm look to use nanovg to render SVG with the data parse from nanosvg.
Could you help me correct this code to support full feature
(just like open the svg file with a svg viewer)?
I have search the google, but find nothing about this.
Could you append it into readme.md. Thank you.

NSVGimage* g_image = = nsvgParseFromFile("drawing.svg", "px", 96.0f);
NSVGshape * shape;
NSVGpath * path;
int i;
nvgStrokeColor(vg, nvgRGBA(0,0,0,255));
for (shape = g_image->shapes; shape != NULL; shape = shape->next) {

    nvgStrokeWidth(vg, shape->strokeWidth);

   for (path = shape->paths; path != NULL; path = path->next) {
        for (i = 0; i < path->npts-1; i += 3) {
            float* p = &path->pts[i*2];

            nvgBeginPath(vg);
            nvgMoveTo(vg, p[0], p[1]);
            nvgBezierTo(vg, p[2], p[3], p[4], p[5], p[6], p[7]);
            nvgStroke(vg);
        }
    }
}

Circle from two arcs not rendering properly

The path below should render as a circle, but NSVG returns only the lower half (twice). Probably a numerical error somewhere in arc calculations.

The path is a part of an actual file made with Inkscape, Qt, Firefox, etc. render it properly. The whole file validates with the w3c validator.

<path
     sodipodi:type="arc"
     style="fill:#000000;fill-opacity:0;stroke:#000000;stroke-width:10.70246888;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
     id="path4687-1"
     sodipodi:cx="330.72961"
     sodipodi:cy="426.55115"
     sodipodi:rx="33.07296"
     sodipodi:ry="34.451"
     d="m 363.80257,426.55115 a 33.07296,34.451 0 1 1 -66.14592,0 33.07296,34.451 0 1 1 66.14592,0 z"
     transform="matrix(2.892314,0,0,2.7166215,-388.8214,-747.3853)" />

I'm going through the nsvg__pathArcTo right now, will provide a patch if I find anything. Here is the list of points I get from NSVG: http://pastebin.com/UdgnMnqU (split in groups of for as in the example from README).

undefined references to glfw

I have glfw installed but make gives me these errors:
Linking example1
obj/Debug/example1/example1.o: In function drawframe': /run/media/user/MISC DATA/nanosvg/build/../example/example1.c:148: undefined reference toglfwSetInputMode'
/run/media/user/MISC DATA/nanosvg/build/../example/example1.c:149: undefined reference to glfwGetFramebufferSize' /run/media/user/MISC DATA/nanosvg/build/../example/example1.c:207: undefined reference toglfwSwapBuffers'
obj/Debug/example1/example1.o: In function main': /run/media/user/MISC DATA/nanosvg/build/../example/example1.c:223: undefined reference toglfwInit'
/run/media/user/MISC DATA/nanosvg/build/../example/example1.c:226: undefined reference to glfwGetPrimaryMonitor' /run/media/user/MISC DATA/nanosvg/build/../example/example1.c:226: undefined reference toglfwGetVideoMode'
/run/media/user/MISC DATA/nanosvg/build/../example/example1.c:227: undefined reference to glfwCreateWindow' /run/media/user/MISC DATA/nanosvg/build/../example/example1.c:231: undefined reference toglfwTerminate'
/run/media/user/MISC DATA/nanosvg/build/../example/example1.c:235: undefined reference to glfwSetFramebufferSizeCallback' /run/media/user/MISC DATA/nanosvg/build/../example/example1.c:236: undefined reference toglfwMakeContextCurrent'
/run/media/user/MISC DATA/nanosvg/build/../example/example1.c:244: undefined reference to glfwTerminate' /run/media/user/MISC DATA/nanosvg/build/../example/example1.c:251: undefined reference toglfwPollEvents'
/run/media/user/MISC DATA/nanosvg/build/../example/example1.c:248: undefined reference to glfwWindowShouldClose' /run/media/user/MISC DATA/nanosvg/build/../example/example1.c:256: undefined reference toglfwTerminate'
collect2: Fehler: ld gab 1 als Ende-Status zurück
example1.make:173: die Regel für Ziel „example1“ scheiterte
make[1]: *** [example1] Fehler 1
Makefile:16: die Regel für Ziel „example1“ scheiterte
make: *** [example1] Fehler 2

VS2015 warnings

I'm getting following warnings when compiling Nano SVG with VS 2015 RC. I will prepare PR with fixes, unfortunately I'm not able to test Xcode, only VC2015 and GCC. Note: I used premake5.exe vs2015 to make projects, it works fine.

1>------ Rebuild All started: Project: example2, Configuration: Debug Win32 ------
1>  example2.c
1>e:\source\nanosvg\example\stb_image_write.h(156): warning C4996: 'fopen': This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
1>  c:\program files (x86)\windows kits\10\include\10.0.10056.0\ucrt\stdio.h(205): note: see declaration of 'fopen'
1>e:\source\nanosvg\example\stb_image_write.h(348): warning C4456: declaration of 'i' hides previous local declaration
1>  e:\source\nanosvg\example\stb_image_write.h(271): note: see declaration of 'i'
1>e:\source\nanosvg\example\stb_image_write.h(349): warning C4456: declaration of 'j' hides previous local declaration
1>  e:\source\nanosvg\example\stb_image_write.h(271): note: see declaration of 'j'
1>e:\source\nanosvg\example\stb_image_write.h(495): warning C4996: 'fopen': This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
1>  c:\program files (x86)\windows kits\10\include\10.0.10056.0\ucrt\stdio.h(205): note: see declaration of 'fopen'
1>e:\source\nanosvg\src\nanosvg.h(120): warning C4201: nonstandard extension used: nameless struct/union
1>e:\source\nanosvg\src\nanosvg.h(359): warning C4201: nonstandard extension used: nameless struct/union
1>e:\source\nanosvg\src\nanosvg.h(730): warning C4127: conditional expression is constant
1>e:\source\nanosvg\src\nanosvg.h(2487): warning C4127: conditional expression is constant
1>e:\source\nanosvg\src\nanosvg.h(2488): warning C4127: conditional expression is constant
1>e:\source\nanosvg\src\nanosvgrast.h(251): warning C4244: '=': conversion from 'int' to 'unsigned char', possible loss of data
1>e:\source\nanosvg\src\nanosvgrast.h(632): warning C4456: declaration of 's' hides previous local declaration
1>  e:\source\nanosvg\src\nanosvgrast.h(577): note: see declaration of 's'
1>e:\source\nanosvg\src\nanosvgrast.h(753): warning C4244: '=': conversion from 'float' to 'int', possible loss of data
1>e:\source\nanosvg\src\nanosvgrast.h(755): warning C4244: '=': conversion from 'float' to 'int', possible loss of data
1>e:\source\nanosvg\src\nanosvgrast.h(756): warning C4244: '=': conversion from 'float' to 'int', possible loss of data
1>e:\source\nanosvg\src\nanosvgrast.h(849): warning C4244: 'function': conversion from 'int' to 'unsigned char', possible loss of data
1>e:\source\nanosvg\src\nanosvgrast.h(844): warning C4244: 'initializing': conversion from 'float' to 'int', possible loss of data
1>e:\source\nanosvg\src\nanosvgrast.h(859): warning C4244: 'function': conversion from 'int' to 'unsigned char', possible loss of data
1>e:\source\nanosvg\src\nanosvgrast.h(854): warning C4244: 'initializing': conversion from 'float' to 'int', possible loss of data
1>e:\source\nanosvg\src\nanosvgrast.h(1093): warning C4244: '=': conversion from 'int' to 'unsigned char', possible loss of data
1>e:\source\nanosvg\src\nanosvgrast.h(1094): warning C4244: '=': conversion from 'int' to 'unsigned char', possible loss of data
1>e:\source\nanosvg\src\nanosvgrast.h(1095): warning C4244: '=': conversion from 'int' to 'unsigned char', possible loss of data
1>e:\source\nanosvg\src\nanosvgrast.h(1132): warning C4244: '=': conversion from 'int' to 'unsigned char', possible loss of data
1>e:\source\nanosvg\src\nanosvgrast.h(1133): warning C4244: '=': conversion from 'int' to 'unsigned char', possible loss of data
1>e:\source\nanosvg\src\nanosvgrast.h(1134): warning C4244: '=': conversion from 'int' to 'unsigned char', possible loss of data
1>e:\source\nanosvg\src\nanosvgrast.h(1174): warning C4244: '=': conversion from 'float' to 'int', possible loss of data
1>e:\source\nanosvg\src\nanosvgrast.h(1175): warning C4244: '=': conversion from 'float' to 'int', possible loss of data
1>e:\source\nanosvg\src\nanosvgrast.h(1185): warning C4244: '=': conversion from 'float' to 'int', possible loss of data
1>e:\source\nanosvg\src\nanosvgrast.h(1186): warning C4244: '=': conversion from 'float' to 'int', possible loss of data
1>e:\source\nanosvg\example\example2.c(43): warning C4244: '=': conversion from 'float' to 'int', possible loss of data
1>e:\source\nanosvg\example\example2.c(44): warning C4244: '=': conversion from 'float' to 'int', possible loss of data
1>e:\source\nanosvg\src\nanosvgrast.h(1198): warning C4701: potentially uninitialized local variable 'cb' used
1>e:\source\nanosvg\src\nanosvgrast.h(708): warning C4701: potentially uninitialized local variable 'right' used
1>e:\source\nanosvg\src\nanosvgrast.h(707): warning C4701: potentially uninitialized local variable 'left' used
1>e:\source\nanosvg\src\nanosvgrast.h(707): warning C4701: potentially uninitialized local variable 'firstLeft' used
1>e:\source\nanosvg\src\nanosvgrast.h(708): warning C4701: potentially uninitialized local variable 'firstRight' used
1>e:\source\nanosvg\src\nanosvgrast.h(435): warning C4701: potentially uninitialized local variable 'prevy' used
1>e:\source\nanosvg\src\nanosvgrast.h(435): warning C4701: potentially uninitialized local variable 'prevx' used
1>e:\source\nanosvg\src\nanosvgrast.h(448): warning C4701: potentially uninitialized local variable 'lx' used
1>e:\source\nanosvg\src\nanosvgrast.h(448): warning C4701: potentially uninitialized local variable 'ly' used
1>e:\source\nanosvg\src\nanosvgrast.h(449): warning C4701: potentially uninitialized local variable 'rx' used
1>e:\source\nanosvg\src\nanosvgrast.h(449): warning C4701: potentially uninitialized local variable 'ry' used
1>  example2.vcxproj -> E:\Source\nanosvg\build\.\example2.exe
========== Rebuild All: 1 succeeded, 0 failed, 0 skipped ==========

Rasterizer SSE2 optimization

I tried SSE2 version of nsvg__scanlineSolid() with NSVG_PAINT_COLOR code path converted. Benchmark on my i5 661 @ 3.5GHz, Windows 7 x64, Visual Studio 2015 RC, x86 release target. Rendering Ghostscript_Tiger.svg, measuring nsvgRasterize() time.

Upstream NanoSVG
900x900px: 68ms
9000x9000px: 4256ms

SSE2 NanoSVG
900x900px: 60ms
9000x9000px: 3125ms

Broken nsvg__scanlineSolid NanoSVG
900x900px: 44ms
9000x9000px: 1895ms
Note: this version does nothing in nsvg__scanlineSolid(), just return. Output is just an empty rectangle.

Some improvement, but nothing stellar. I didn't use SSE before so maybe someone experienced could do better. Anyone interested in my quick&dirty patch? Output PNG is binary same for both upstream and SSE2 versions.

Streaming SIMD Extensions (/arch:SSE) option was enabled for whole application. There is another boost with Streaming SIMD Extensions 2 (/arch:SSE2) enabled, but there are still (AMD) CPUs not supporting SSE2 in old computers.

crush on single quoted params

Program crashes when the parameters are in single quotation marks. Some adobe products use single quotes when saving. I added a check for single quotes in line 257 and 262.

while (*s && *s != '"' && *s != ''') s++;

nanosvg and OpenCV

Hello @memononen ,

I discovered this little neat library and I think that is perfect for my svg manipulation goals. However, I am having some problems with the rasterization step.
What I am currently doing is:

  • read an svg image
  • rasterize it into a memory buffer
  • read this buffer from OpenCV and create a cv::Mat from the buffer
  • display the cv::Mat

The source code is available here: https://github.com/ScazLab/snap_circuits/blob/master/snap_circuits_visualization/visualizer.cpp

This is the result (left: original, right: processed by nanosvg and OpenCV):
img1

As you can see, there are some issues:

  • The background of the rasterized image is black. Would it be possible to change it to white? I tried on my own but I was not able to.
  • The edges are not antialiased as it is clear from the top right part of the rasterized image;
  • The colorspace is wrong between the two libraries. Now, in this regard there are many way one can proceed in order to solve this issue. Unfortunately, OpenCV works with BGRA color space (instead of RGBA). I could either create my own conversion method, search for something suitable in the openCV library, or patch your library. I think that the best way would be the latter: I was thinking to a flag to add to nsvgRasterize in order to choose the color space. I already did a very dirty modification of your library in order to achieve this, and this is the result:

img2

What do you think? My modifications to the library are available here https://github.com/ScazLab/snap_circuits/blob/master/lib/include/nanosvg/nanosvgrast.h , but I think you can have better ideas to do that :)

Style Sheets

https://www.w3.org/TR/SVG/single-page.html#styling-StylingWithCSS

nanosvg already parses style attributes, but there are some programs (for example Adobe Illustrator) that produce SVGs with inline stylesheets.

There are lots of example in the SVG test suite, just search for "text/css", ex:

https://www.w3.org/Graphics/SVG/Test/20110816/svg/styling-class-01-f.svg

In general this means supporting parsing the style sheet, and also the "class" attribute and matching that back to the style sheet. I realize that in general is a pretty big task and basically requires a lot of the CSS infrastructure, but perhaps it would be good to have something basic working.

In my case I will have to at least implement simple class based rules to handle the SVGs from Illustrator.

gcc compiler warning: array subscript is above array bounds

...
.../nanosvg-0.0-dc755086/include/nanosvg.h: In function ‘void nsvg__addShape(NSVGparser*)’:
.../nanosvg-0.0-dc755086/include/nanosvg.h:938:54: warning: array subscript is above array bounds [-Warray-bounds]
  shape->strokeDashArray[i] = attr->strokeDashArray[i] * scale;
.../nanosvg-0.0-dc755086/include/nanosvg.h:938:27: warning: array subscript is above array bounds [-Warray-bounds]
   shape->strokeDashArray[i] = attr->strokeDashArray[i] * scale;
...

Question/tutorial

Hello Mikko, @alecive again. I am really excited about this library, but I am struggling with trying to understand what it can and it cannot do (and how to eventually extend it).

So, beginning with the basics:

  • how can I rotate and translate a NSVGshape ? Can I use something like nsvg__parseRotate and nsvg__parseTranslate ? If so, how can I use them?
  • If I have two NSVGimages, what would be the best way to combine them in one single NSVGimage with the NSVGshapes from both?

Thank you!

Example of use with NANOVG

It would be helpful to provide a self contained example of loading svg files using this library with nanovg for rendering rather than raw opengl.

Pixel format

Hi!

First, thanks for sharing!

I'd like to use nanosvg for a hobby OS, and tried it on a linux framebuffer, which happens to use a BGRA format. Could you add, if not a runtime option, at least a compile time option? Or should i make a pull request?

I also noticed some svg being misrendered in a framebuffer but rendered fine a png, does that makes sense to you?

Thanks!

Proper gradient support

If I rasterize an object with a (linear) gradient that has a non-identity transform, it is rendered incorrectly (similar to the transform not being set at all).
Here is an example:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<linearGradient inkscape:collect="always" id="linearGradient4416-4" x1="457.85709" y1="640.57642" x2="458.39285" y2="625.93359" gradientUnits="userSpaceOnUse" gradientTransform="matrix(1,0,0,0.95454547,86.600955,30.474306)">
    <stop style="stop-color:#494949;stop-opacity:0" offset="0" id="stop4412"/>
    <stop style="stop-color:#464646;stop-opacity:1" offset="1" id="stop4414"/>
</linearGradient>
</defs>
<g id="layer1">
<path transform="matrix(2.2560027,0,0,2.2560027,-422.41146,-1104.3522)" style="fill:url(#linearGradient4416-4);fill-opacity:1" id="path4408-7" d="M 542.851,635.456 m -18.2143,0 a 18.2143,10.0893 0 1 0 36.4286,0 a 18.2143,10.0893 0 1 0 -36.4286,0"/>
</g>
</svg>

NanoSVG rasterizer (my program is applying a blur to the image):
lantern01_blur2

Qt & Inkscape rasterizer (with same blurring code):
lantern01_blur2

Note: The object is not in the center. So when viewing the file in Inkscape, you have to zoom out a bit.

Are you still interested in working on gradients/NanoSVG?
A lot of people would be really grateful if you'd fix these bugs, as NanoSVG is the best lightweight SVG rasterizer out there. There are also libraries like Qt and Cairo, but getting them to work on Android devices could be really hard.

Buggy gradients seem to be a problem for some months now:
#26 (look especially on the linear gradient on the left of the picture)
#27

I can also reproduce this bug: #21
NanoSVG isn't able to dereference "xlink:href" properly, as it doesn't remove the hash in front of the id.

rasterization broken

it seems rasterization is broken on my builds.
any idea?

here is the relevant code:

// Load SVG, parse and rasterize
char *str = new char[ size + 1 ];
memcpy( str, ptr, size );
str[size] = '\0';

NSVGimage *image = nsvgParse( str, "px" /*units*/, 96.f /* dpi */ );
if( image ) {
    // Create rasterizer (can be used to render multiple images).
    static struct install {
        NSVGrasterizer *rasterizer;
         install() { rasterizer = nsvgCreateRasterizer(); }
        ~install() { if( rasterizer ) nsvgDeleteRasterizer( rasterizer ); rasterizer = 0; }
    } local;
    // Allocate memory for image
    int w = image->width;
    int h = image->height;

    double scale = 1.0;
    imageWidth = image->width * scale;
    imageHeight = image->height * scale;
    imageBpp = 4;

    imageuc = (stbi_uc *)malloc(w*h*4);
    deleter = FREE_DELETER;
    if( imageuc ) {
        // Rasterizes SVG image, returns RGBA image (non-premultiplied alpha)
        //   r - pointer to rasterizer context
        //   image - pointer to image to rasterize
        //   tx,ty - image offset (applied after scaling)
        //   scale - image scale
        //   dst - pointer to destination image data, 4 bytes per pixel (RGBA)
        //   w - width of the image to render
        //   h - height of the image to render
        //   stride - number of bytes per scaleline in the destination buffer
        nsvgRasterize( local.rasterizer, image, 0,0,scale, imageuc, w, h, w*scale*4 );
    }
    nsvgDelete(image);
}

delete [] str;

image

ps: thanks for the lib btw! 😁

Question About NanoSVG

Great work! I was thinking about using the project in an application to display some SVG output from d3js.org. I pulled a few random selections from the d3 project and tried them out. I noticed a few things upon rasterization (forgive me up front for not knowing the SVG format or terminology yet) : no text appears, no lines appear, and no gradient colors appear - basically all that shows are some of the solid shapes (like the description stated). I was wondering all 3 of these issues is expected at this point and how difficult it would be to implement? I do not want to look into contributing to a feature that might already be implemented and just nor working for me.

How to implement new renderer?

Where would i have to "hook in" if i wanted to write a new renderer, e.g. using GDI+? Somehow i expected to find methods to draw primitives in the renderer that i could easily replace with GDI+ calls. But i guess that was a little too optimistic :)

Thanks.

Gradients not rendered

i found that nsvg__findGradientData is often called with something like "#linearGradient2802" as id, while the stored gradient has an id of "linearGradient2802", so it doesn't get found and therefore not rendered.

I pasted the SVG here: http://pastebin.com/MTA9XNBX

Path is not rendered correctly

I'm not sure if this is a bug, but following path is not rendered correctly:

<?xml version="1.0" encoding="utf-8"?>
<!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="Report" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
     width="492px" height="485px" viewBox="0 0 492 485" enable-background="new 0 0 492 485" xml:space="preserve">
<path fill-rule="evenodd" clip-rule="evenodd" fill="#ABABAB" d="M188.603,167.706c80.044,0,144.958,64.914,144.958,144.959
    c0,80.044-64.914,144.958-144.958,144.958c-80.046,0-144.958-64.914-144.958-144.958
    C43.646,232.619,108.558,167.706,188.603,167.706L188.603,167.706z M185.009,172.391c75.474,0,136.679,61.207,136.679,136.683
    c0,75.466-61.205,136.673-136.679,136.673c-75.472,0-136.679-61.207-136.679-136.673C48.33,233.598,109.537,172.391,185.009,172.391
    L185.009,172.391z"/>
</svg>

There should be transparent center part of image that is filled when rendered with Nano SVG.

Trying to load properly data from SVG

I use my own reading file method and it looks like it load some strange data from it. I load your file width a tiger called 23.svg with this code:

svgImage = nsvgParse( imgData, "px", 96.0f );
if (svgImage == NULL) printf("Could not open SVG image.\n");
w = (int)svgImage->width;
h = (int)svgImage->height;
std::cout << "size = " << w << "x" << h << std::endl;
for ( auto shape = svgImage->shapes; shape != NULL; shape = shape->next )
    for ( auto path = shape->paths; path != NULL; path = path->next ) {
        std::cout << "pts(" << path->npts << "): ";
        for ( auto i = 0; i < path->npts; i++ ) std::cout << path->pts[ i ] << ", ";
        std::cout << std::endl;
    }
std::cout << "---------------------------------" << std::endl;

And I get this output: http://pastebin.com/KfAkZvQ8
Please take a look at this. I get properly width and height but those points... I opened 23.svg and I can't see such points. Why do I get such strange points? Or maybe I don't understand what do I actually need to get? I see that there are no such points in 23.svg...
My reading method is fails or does it look like correct data?

Feature request: svg2png converter command-line app

I think that providing a "nsvg" command-line tool would be useful for batch conversions and could aid development and testing. Is there a reason there isn't one bundled already?

  1. We would need to rename and patch example2.c (see quick and dirty patch below)
  2. We would need to add "make install" equivalent in the premake buildfile (or make a Makefile for the cli app?)
modified   example/example2.c
@@ -26,13 +26,13 @@
 #define NANOSVGRAST_IMPLEMENTATION
 #include "nanosvgrast.h"

-int main()
+int main(int argc, char **argv)
 {
    NSVGimage *image = NULL;
    NSVGrasterizer *rast = NULL;
    unsigned char* img = NULL;
    int w, h;
-   const char* filename = "../example/23.svg";
+   const char* filename = argv[1];

    printf("parsing %s\n", filename);
    image = nsvgParseFromFile(filename, "px", 96.0f);
@@ -58,8 +58,10 @@ int main()
    printf("rasterizing image %d x %d\n", w, h);
    nsvgRasterize(rast, image, 0,0,1, img, w, h, w*4);

-   printf("writing svg.png\n");
-   stbi_write_png("svg.png", w, h, 4, img, w*4);
+   char outfile[4096];
+   snprintf(outfile, 4096, "%s.png", filename);
+   printf("writing \"%s\"\n", outfile);
+   stbi_write_png(outfile, w, h, 4, img, w*4);

 error:
    nsvgDeleteRasterizer(rast);

A tool like this lets us, for example, do easy benchmarking. NanoSVG is, for example, a lot faster than Inkscape (though probably because inkscape takes a long time to bootstrap itself and all its dependencies):

$ time inkscape ruby.svg -e ruby.svg.inkscape.png 
Area 0:0:100:100 exported to 100 x 100 pixels (90 dpi)
real    0m0.362s
$ time nsvg ruby.svg
rasterizing image 100 x 100
writing "ruby.svg.png"
real    0m0.025s

Something worth considering?

<!-- --> comments not correctly handled

Testcase: paths-data-02-t.svg from SVG test suite.

  <!-- comment out this watermark once the test is approved -->
  <!--<g id="draft-watermark">
    <rect x="1" y="1" width="478" height="20" fill="red" stroke="black" stroke-width="1"/>
    <text font-family="SVGFreeSansASCII,sans-serif" font-weight="bold" font-size="20" x="240"
      text-anchor="middle" y="18" stroke-width="0.5" stroke="black" fill="white">DRAFT</text>
  </g>-->

The elements inside of the last comment are still parsed.

Incorrect colors

Library doesn't render proper colors. For example pure white #FFFFFF is rendered as #FCFCFC, you can check whites on tiger from library description. #000000 is rendered as #010101. Gradients seems to be affected to. Do you have any idea what could be source of this problem?

Edit: Maybe this? (an other >> 8 operations)
int a = ((int)cover[0] * ca) >> 8;
vs
int a = ((int)cover[0] * ca) / 255;

bug nsvg__pathArcTo()

Hi,

Try the following path and you will get a parse error due to a division by 0 in nsvg__pathArcTo()

<?xml version="1.0" encoding="utf-8"?><svg version="1.1" id="Layer_1" width="10000mm" height="10000mm"><path d="M40.7595, -20.5388 A38.200000000000074,38.200000000000074,0,0,1,32.0609, -22.2933"/></svg>

The included patch fixes the bug and does not seem to create regression, as observed by the folowing screen shots
4cornerbig

4cornersmall

patch:

Index: trunk/src/nanosvg.h
===================================================================
--- trunk/src/nanosvg.h (revision 50)
+++ trunk/src/nanosvg.h (working copy)
@@ -1887,7 +1887,7 @@
    t[4] = cx; t[5] = cy;

    // Split arc into max 90 degree segments.
-   ndivs = (int)(fabsf(da) / (NSVG_PI*0.5f) + 0.5f);
+   ndivs = (int)(fabsf(da) / (NSVG_PI*0.5f) + 1.0f);
    hda = (da / (float)ndivs) / 2.0f;
    kappa = fabsf(4.0f / 3.0f * (1.0f - cosf(hda)) / sinf(hda));
    if (da < 0.0f)

Gradients

Although you say "it only renders flat filled shapes", i noticed a lot of gradient related code, but i never saw any gradients rendered. After some debugging, i found that nsvg__findGradientData is often called with something like "#linearGradient2802" as id, while the stored gradient has an id of "linearGradient2802", so it doesn't get found. After changing that, gradients started appearing and it's getting closer to what it's supposed to look like ;) I haven't found yet why the linear gradient doesn't look right.

nanosvg:
gradients_nanosvg

ImageMagick
gradients_imagemagick

I have some problems with implementing gradients for my own renderer though. The structure i have access to through the "chain of structures" is NSVGgradient:

typedef struct NSVGgradient {
float xform[6];
char spread;
float fx, fy;
int nstops;
NSVGgradientStop stops[1];
} NSVGgradient;

But i think i need the information stored in NSVGgradientData, which gives me these:
typedef struct NSVGlinearData {
float x1, y1, x2, y2;
} NSVGlinearData;

typedef struct NSVGradialData {
float cx, cy, r, fx, fy;
} NSVGradialData;

I think i am missing something.

Incorrect handling of relative path coordinates

Current pen coordinates (cpx+cpy) are reset to zero on start of each moveto command ('m'/'M') - See line 1453 of nanosvg.h - these variable should only be reset on start of parsing the "d" attribute.

How to control output size?

Hi, first of all thanks for the nice library. I spent half a day looking at SVG renderers and yours is the first one that looks easy to use.

My question: When using NSVGrasterizer, how do i control the output size? It seems that whatever parameters i pass as "unit" and "dpi", i always get the size that's given in the SVG, e.g. 900x900 pixels for the famous Ghostscript_Tiger.svg

Library extension

Hey @memononen ,

I really like this library, so thank you for your efforts in it! I am trying to extend it a bit in order to suit my needs. I would like to give you back my contributions disguised as pull requests and whatnot. Specifically, I am in the process of doing:

  • nsvgCopyGradient
  • nsvgCopyPaint
  • nsvgCopyPath
  • nsvgCopyShape
  • nsvgAppendShape (it concatenates two shapes in order to have a single picture)
  • nsvgTransformPath
  • nsvgTransformShape
  • ...

Would you be interested in including them in the library? I think that they can be useful also for other users (but if you are not interested I will keep them on my private copy).

arc seg

Hi!
Thanks for this!

http://www.w3.org/TR/SVG/images/painting/fillrule-evenodd.svg

This sample brings up the question of 'holes', which in this uses the "evenodd" fill-rule. Maybe there are other ways to have a hole; we haven't had a lot of luck finding any definitive spec on that as such.
Should we check on multiple paths within a path? <Path .. c ... z M c...z >

We appreciate your effort and any answer you might provide!
Regards,
-brian

Independent X and Y scaling

I submitted a pull request #68 that (passably?) uses a scalex and scaley to scale and stretch/compress images to a different aspect ration. I am trying to add an option to replace cairo/rsvg in jwm with nanosvg (requires independent x-y scaling) as well as demonstrate xcb with a basic image viewer

I think this will be useful for other purposes, but I wasn't sure if nanosvgrast had declared a stable API, so I reimplemented all the functions with a single scale parameter to call the new *Full versions.

nsvg__parseRotate Bug

In nanosvg.h line 1314 you have
nsvg__xformPremultiply(0, t);

Which will cause dereferences on 0, as well as memcpy with 0 as the destination. I suspect this should be 'm' instead.

Also I was curious why in the following functions you do not just use the xform pointer directly, and instead create a float[6] and then memcpy into xform to return?
nsvg__parseRotate
nsvg__parseSkewY
nsvg__parseSkewX
nsvg__parseScale
nsvg__parseTranslate
nsvg__parseMatrix

Use NanoVG to draw point arrays

Hi,

Can NanoVG be used to draw point arrays?

I'm currently attempting to port old code to NanoVG from OpenGL 1.x. There are several usages of rendering a vertex array of type GL_POINTS that I would like to convert but I do not see a way to do it with NanoVG.

Any help would be appreciated. Thanks!

nanosvg is too slow but easy to make it faster

I am reading 8MB svg and it takes 30 seconds to parse. When profiling with VerySleepy I found it's because of svg__addShape adds new shape to the tail of the list. Tail is not cached so this operation is very slow. When I changed it to add it to the list's head (no iteration) parsing time went down to 1s! The speedup is too big to ignore so I think the code should be changed. If you still want to have list of shapes in correct order you can reverse the list at the end of parsing.

nanosvg run against w3.org test suite

What an amazing accomplishment, @memononen! I'm looking forward to experiment with embedded SVG-files in my prototype games instead of PNGs.

I made your example2.c into something that can be used from the command-line (see this issue), and I ran it across all the svg sample files from w2.org like this:

$ gcc -lm example2.c -o nsvg -I ../src
$ find -name "*.svg" | while read F ; do ./nsvg "$F" ; done

I was really surprised how accurate NanoSvg really was! Among the 204 examples, I found just a couple of problems:

  • Text won't render but we knew that (and I fear a proper implementation of this would make NanoSVG not be so nano anymore?)
  • ubuntu.svg is completely blank:
    ubuntu svg
  • yinyang.svg is missing a dot and has a strange curve:
    yinyang svg
  • tiger.svg is 800px tall, but it looks like it should be 510px

Apart from those, they all render beautifully!

I don't have time to investigate, but I though I'd mention these minor problems just in case. Keep up the good work!

Problem with groups

This is an excellent lib, simple and useful without all the bloat that comes with most other SVG parsers/renderers. The recent support for strokes is greatly appreciated too, as previously it was quite painful having to convert all strokes to paths before they could be used.

I am still having problems with group objects though. If you take any SVG from http://www.game-icons.net they fail to render at all using NanoSVG unless I first go in to Inkscape and ungroup all objects. Any chance of a fix for this?

Bug in nsvg__scaleToViewbox()

When no viewWidth/viewHeight is specified, it is determined from content's bounds max element instead of bound's max - min.

the following patch works for me on this test file (DO NOT expect it to render, meant to be used with a debugguer). I'm not sure the patch does the right thing when multiple paths are involved (one would use the extrema of path`s bounds)

<?xml version="1.0" encoding="utf-8"?><svg version="1.1" id="Layer_1"><path d="M-24.5, 0L0, -24.5L8.80764, -26.0009L41.0517, -12.645"/></svg>
Index: trunk/src/nanosvg.h
===================================================================
--- trunk/src/nanosvg.h (revision 50)
+++ trunk/src/nanosvg.h (working copy)
@@ -2497,13 +2497,13 @@
        if (p->image->width > 0)
            p->viewWidth = p->image->width;
        else
-           p->viewWidth = bounds[2];
+           p->viewWidth = bounds[2] - bounds[0];
    }
    if (p->viewHeight == 0) {
        if (p->image->height > 0)
            p->viewHeight = p->image->height;
        else
-           p->viewHeight = bounds[3];
+           p->viewHeight = bounds[3] - bounds[1];
    }
    if (p->image->width == 0)
        p->image->width = p->viewWidth;

[Edited: removed non pertinent part of the patch]

Compilation Errors

I tried to compile examples. Example2 runs fine but I am getting these errors in example1. Can anyone through some light?

/nanosvg-master/build$ make
==== Building example1 (debug) ====
example1.c
../example/example1.c:141:16: error: unknown type name ‘GLFWwindow’
void drawframe(GLFWwindow* window)
^
../example/example1.c:210:15: error: unknown type name ‘GLFWwindow’
void resizecb(GLFWwindow* window, int width, int height)
^
../example/example1.c: In function ‘main’:
../example/example1.c:220:2: error: unknown type name ‘GLFWwindow’
GLFWwindow* window;
^
../example/example1.c:226:2: warning: implicit declaration of function ‘glfwGetVideoMode’ [-Wimplicit-function-declaration]
mode = glfwGetVideoMode(glfwGetPrimaryMonitor());
^
../example/example1.c:226:2: warning: implicit declaration of function ‘glfwGetPrimaryMonitor’ [-Wimplicit-function-declaration]
../example/example1.c:226:7: warning: assignment makes pointer from integer without a cast [enabled by default]
mode = glfwGetVideoMode(glfwGetPrimaryMonitor());
^
../example/example1.c:227:5: warning: implicit declaration of function ‘glfwCreateWindow’ [-Wimplicit-function-declaration]
window = glfwCreateWindow(mode->width - 40, mode->height - 80, "Nano SVG", NULL, NULL);
^
../example/example1.c:227:35: error: ‘GLFWvidmode’ has no member named ‘width’
window = glfwCreateWindow(mode->width - 40, mode->height - 80, "Nano SVG", NULL, NULL);
^
../example/example1.c:227:53: error: ‘GLFWvidmode’ has no member named ‘height’
window = glfwCreateWindow(mode->width - 40, mode->height - 80, "Nano SVG", NULL, NULL);
^
../example/example1.c:235:2: warning: implicit declaration of function ‘glfwSetFramebufferSizeCallback’ [-Wimplicit-function-declaration]
glfwSetFramebufferSizeCallback(window, resizecb);
^
../example/example1.c:235:41: error: ‘resizecb’ undeclared (first use in this function)
glfwSetFramebufferSizeCallback(window, resizecb);
^
../example/example1.c:235:41: note: each undeclared identifier is reported only once for each function it appears in
../example/example1.c:236:2: warning: implicit declaration of function ‘glfwMakeContextCurrent’ [-Wimplicit-function-declaration]
glfwMakeContextCurrent(window);
^
../example/example1.c:248:2: warning: implicit declaration of function ‘glfwWindowShouldClose’ [-Wimplicit-function-declaration]
while (!glfwWindowShouldClose(window))
^
../example/example1.c:250:3: warning: implicit declaration of function ‘drawframe’ [-Wimplicit-function-declaration]
drawframe(window);
^
make[1]: *** [obj/Debug/example1/example1.o] Error 1
make: *** [example1] Error 2

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.