
@ -0,0 +1,18 @@ |
|||
Copyright (c) 2013 Mikko Mononen memon@inside.org |
|||
|
|||
This software is provided 'as-is', without any express or implied |
|||
warranty. In no event will the authors be held liable for any damages |
|||
arising from the use of this software. |
|||
|
|||
Permission is granted to anyone to use this software for any purpose, |
|||
including commercial applications, and to alter it and redistribute it |
|||
freely, subject to the following restrictions: |
|||
|
|||
1. The origin of this software must not be misrepresented; you must not |
|||
claim that you wrote the original software. If you use this software |
|||
in a product, an acknowledgment in the product documentation would be |
|||
appreciated but is not required. |
|||
2. Altered source versions must be plainly marked as such, and must not be |
|||
misrepresented as being the original software. |
|||
3. This notice may not be removed or altered from any source distribution. |
|||
|
@ -0,0 +1,71 @@ |
|||
Nano SVG |
|||
========== |
|||
|
|||
 |
|||
|
|||
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, if somehing is missing, feel free to create a pull request! |
|||
|
|||
|
|||
## Example Usage |
|||
|
|||
``` C |
|||
// Load |
|||
struct SNVGPath* plist; |
|||
plist = nsvgParseFromFile("test.svg."); |
|||
|
|||
// Use |
|||
for (NSVGPath* it = plist; it; it = it->next) { |
|||
for (i = 0; i < npts-1; i += 3) { |
|||
float* p = &pts[i*2]; |
|||
drawCubicBez(p[0],p[1], p[2],p[3], p[4],p[5], p[6],p[7]); |
|||
} |
|||
} |
|||
|
|||
// Delete |
|||
nsvgDelete(plist); |
|||
``` |
|||
|
|||
## 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. |
|||
|
|||
``` C |
|||
#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](http://www.w3.org/TR/SVG11/types.html#ColorKeywords), define `NANOSVG_ALL_COLOR_KEYWORDS` before expanding the implementation. |
|||
|
|||
``` C |
|||
#define NANOSVG_ALL_COLOR_KEYWORDS // Include full list of color keywords. |
|||
#define NANOSVG_IMPLEMENTATION // Expands implementation |
|||
#include "nanosvg.h" |
|||
``` |
|||
|
|||
## Compiling Example Project |
|||
|
|||
In order to compile the demo project, your will need to install [GLFW](http://www.glfw.org/) to compile. |
|||
|
|||
NanoSVG demo project uses [premake4](http://industriousone.com/premake) 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: |
|||
|
|||
```bash |
|||
$ premake4 gmake |
|||
$ cd build/ |
|||
$ make |
|||
$ ./example |
|||
``` |
|||
|
|||
# License |
|||
|
|||
The library is licensed under [zlib license](LICENSE.txt) |
After Width: | Height: | Size: 94 KiB |
After Width: | Height: | Size: 3.3 KiB |
@ -0,0 +1,267 @@ |
|||
//
|
|||
// Copyright (c) 2013 Mikko Mononen memon@inside.org
|
|||
//
|
|||
// This software is provided 'as-is', without any express or implied
|
|||
// warranty. In no event will the authors be held liable for any damages
|
|||
// arising from the use of this software.
|
|||
// Permission is granted to anyone to use this software for any purpose,
|
|||
// including commercial applications, and to alter it and redistribute it
|
|||
// freely, subject to the following restrictions:
|
|||
// 1. The origin of this software must not be misrepresented; you must not
|
|||
// claim that you wrote the original software. If you use this software
|
|||
// in a product, an acknowledgment in the product documentation would be
|
|||
// appreciated but is not required.
|
|||
// 2. Altered source versions must be plainly marked as such, and must not be
|
|||
// misrepresented as being the original software.
|
|||
// 3. This notice may not be removed or altered from any source distribution.
|
|||
//
|
|||
|
|||
#include <stdio.h> |
|||
#include <string.h> |
|||
#include <float.h> |
|||
#include <GLFW/glfw3.h> |
|||
|
|||
#define NANOSVG_IMPLEMENTATION |
|||
#include "nanosvg.h" |
|||
|
|||
struct NSVGPath* g_plist = NULL; |
|||
|
|||
static unsigned char bgColor[4] = {205,202,200,255}; |
|||
static unsigned char lineColor[4] = {0,160,192,255}; |
|||
|
|||
static float minf(float a, float b) { return a < b ? a : b; } |
|||
static float maxf(float a, float b) { return a > b ? a : b; } |
|||
|
|||
static float distPtSeg(float x, float y, float px, float py, float qx, float qy) |
|||
{ |
|||
float pqx, pqy, dx, dy, d, t; |
|||
pqx = qx-px; |
|||
pqy = qy-py; |
|||
dx = x-px; |
|||
dy = y-py; |
|||
d = pqx*pqx + pqy*pqy; |
|||
t = pqx*dx + pqy*dy; |
|||
if (d > 0) t /= d; |
|||
if (t < 0) t = 0; |
|||
else if (t > 1) t = 1; |
|||
dx = px + t*pqx - x; |
|||
dy = py + t*pqy - y; |
|||
return dx*dx + dy*dy; |
|||
} |
|||
|
|||
static void cubicBez(float x1, float y1, float x2, float y2, |
|||
float x3, float y3, float x4, float y4, |
|||
float tol, int level) |
|||
{ |
|||
float x12,y12,x23,y23,x34,y34,x123,y123,x234,y234,x1234,y1234; |
|||
float d; |
|||
|
|||
if (level > 12) return; |
|||
|
|||
x12 = (x1+x2)*0.5f; |
|||
y12 = (y1+y2)*0.5f; |
|||
x23 = (x2+x3)*0.5f; |
|||
y23 = (y2+y3)*0.5f; |
|||
x34 = (x3+x4)*0.5f; |
|||
y34 = (y3+y4)*0.5f; |
|||
x123 = (x12+x23)*0.5f; |
|||
y123 = (y12+y23)*0.5f; |
|||
x234 = (x23+x34)*0.5f; |
|||
y234 = (y23+y34)*0.5f; |
|||
x1234 = (x123+x234)*0.5f; |
|||
y1234 = (y123+y234)*0.5f; |
|||
|
|||
d = distPtSeg(x1234, y1234, x1,y1, x4,y4); |
|||
if (d > tol*tol) { |
|||
cubicBez(x1,y1, x12,y12, x123,y123, x1234,y1234, tol, level+1); |
|||
cubicBez(x1234,y1234, x234,y234, x34,y34, x4,y4, tol, level+1); |
|||
} else { |
|||
glVertex2f(x4, y4); |
|||
} |
|||
} |
|||
|
|||
static void calcBounds(struct NSVGPath* plist, float* bounds) |
|||
{ |
|||
struct NSVGPath* it; |
|||
int i; |
|||
bounds[0] = FLT_MAX; |
|||
bounds[1] = FLT_MAX; |
|||
bounds[2] = -FLT_MAX; |
|||
bounds[3] = -FLT_MAX; |
|||
for (it = plist; it; it = it->next) { |
|||
for (i = 0; i < it->npts; i++) { |
|||
float* p = &it->pts[i*2]; |
|||
bounds[0] = minf(bounds[0], p[0]); |
|||
bounds[1] = minf(bounds[1], p[1]); |
|||
bounds[2] = maxf(bounds[2], p[0]); |
|||
bounds[3] = maxf(bounds[3], p[1]); |
|||
} |
|||
} |
|||
} |
|||
|
|||
void drawPath(float* pts, int npts, char closed, float tol) |
|||
{ |
|||
int i; |
|||
glBegin(GL_LINE_STRIP); |
|||
glColor4ubv(lineColor); |
|||
glVertex2f(pts[0], pts[1]); |
|||
for (i = 0; i < npts-1; i += 3) { |
|||
float* p = &pts[i*2]; |
|||
cubicBez(p[0],p[1], p[2],p[3], p[4],p[5], p[6],p[7], tol, 0); |
|||
} |
|||
if (closed) { |
|||
glVertex2f(pts[0], pts[1]); |
|||
} |
|||
glEnd(); |
|||
} |
|||
|
|||
void drawControlPts(float* pts, int npts, char closed) |
|||
{ |
|||
int i; |
|||
|
|||
// Control lines
|
|||
glColor4ubv(lineColor); |
|||
glBegin(GL_LINES); |
|||
for (i = 0; i < npts-1; i += 3) { |
|||
float* p = &pts[i*2]; |
|||
glVertex2f(p[0],p[1]); |
|||
glVertex2f(p[2],p[3]); |
|||
glVertex2f(p[4],p[5]); |
|||
glVertex2f(p[6],p[7]); |
|||
} |
|||
glEnd(); |
|||
|
|||
// Points
|
|||
glPointSize(6.0f); |
|||
glColor4ubv(lineColor); |
|||
|
|||
glVertex2f(pts[0],pts[1]); |
|||
glBegin(GL_POINTS); |
|||
for (i = 0; i < npts-1; i += 3) { |
|||
float* p = &pts[i*2]; |
|||
glVertex2f(p[6],p[7]); |
|||
} |
|||
glEnd(); |
|||
|
|||
// Points
|
|||
glPointSize(3.0f); |
|||
|
|||
glColor4ubv(bgColor); |
|||
glVertex2f(pts[0],pts[1]); |
|||
glBegin(GL_POINTS); |
|||
for (i = 0; i < npts-1; i += 3) { |
|||
float* p = &pts[i*2]; |
|||
glColor4ubv(lineColor); |
|||
glVertex2f(p[2],p[3]); |
|||
glVertex2f(p[4],p[5]); |
|||
glColor4ubv(bgColor); |
|||
glVertex2f(p[6],p[7]); |
|||
} |
|||
glEnd(); |
|||
} |
|||
|
|||
void drawframe(GLFWwindow* window) |
|||
{ |
|||
int width = 0, height = 0; |
|||
float bounds[4], view[4], cx, cy, w, h, aspect, px; |
|||
struct NSVGPath* it; |
|||
|
|||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); |
|||
glfwGetFramebufferSize(window, &width, &height); |
|||
|
|||
glViewport(0, 0, width, height); |
|||
glClearColor(220.0f/255.0f, 220.0f/255.0f, 220.0f/255.0f, 1.0f); |
|||
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); |
|||
glEnable(GL_BLEND); |
|||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); |
|||
glDisable(GL_TEXTURE_2D); |
|||
glMatrixMode(GL_PROJECTION); |
|||
glLoadIdentity(); |
|||
|
|||
// Fit view to bounds
|
|||
calcBounds(g_plist, bounds); |
|||
cx = (bounds[0]+bounds[2])/2; |
|||
cy = (bounds[3]+bounds[1])/2; |
|||
w = (bounds[2]-bounds[0])/2; |
|||
h = (bounds[3]-bounds[1])/2; |
|||
|
|||
if (width/w < height/h) { |
|||
aspect = (float)height / (float)width; |
|||
view[0] = cx - w * 1.2f; |
|||
view[2] = cx + w * 1.2f; |
|||
view[1] = cy - w * 1.2f * aspect; |
|||
view[3] = cy + w * 1.2f * aspect; |
|||
} else { |
|||
aspect = (float)width / (float)height; |
|||
view[0] = cx - h * 1.2f * aspect; |
|||
view[2] = cx + h * 1.2f * aspect; |
|||
view[1] = cy - h * 1.2f; |
|||
view[3] = cy + h * 1.2f; |
|||
} |
|||
// Size of one pixel.
|
|||
px = (view[2] - view[1]) / (float)width; |
|||
|
|||
glOrtho(view[0], view[2], view[3], view[1], -1, 1); |
|||
|
|||
glMatrixMode(GL_MODELVIEW); |
|||
glLoadIdentity(); |
|||
glDisable(GL_DEPTH_TEST); |
|||
glColor4ub(255,255,255,255); |
|||
glEnable(GL_BLEND); |
|||
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); |
|||
|
|||
for (it = g_plist; it; it = it->next) { |
|||
drawPath(it->pts, it->npts, it->closed, px * 1.5f); |
|||
drawControlPts(it->pts, it->npts, it->closed); |
|||
} |
|||
|
|||
glfwSwapBuffers(window); |
|||
} |
|||
|
|||
void resizecb(GLFWwindow* window, int width, int height) |
|||
{ |
|||
// Update and render
|
|||
drawframe(window); |
|||
} |
|||
|
|||
int main() |
|||
{ |
|||
GLFWwindow* window; |
|||
const GLFWvidmode* mode; |
|||
|
|||
if (!glfwInit()) |
|||
return -1; |
|||
|
|||
mode = glfwGetVideoMode(glfwGetPrimaryMonitor()); |
|||
window = glfwCreateWindow(mode->width - 40, mode->height - 80, "Nano SVG", NULL, NULL); |
|||
if (!window) |
|||
{ |
|||
printf("Could not open window\n"); |
|||
glfwTerminate(); |
|||
return -1; |
|||
} |
|||
|
|||
glfwSetFramebufferSizeCallback(window, resizecb); |
|||
glfwMakeContextCurrent(window); |
|||
glEnable(GL_POINT_SMOOTH); |
|||
glEnable(GL_LINE_SMOOTH); |
|||
|
|||
|
|||
g_plist = nsvgParseFromFile("../example/nano.svg"); |
|||
if (g_plist == NULL) { |
|||
printf("Could not open test.svg\n"); |
|||
glfwTerminate(); |
|||
return -1; |
|||
} |
|||
|
|||
while (!glfwWindowShouldClose(window)) |
|||
{ |
|||
drawframe(window); |
|||
glfwPollEvents(); |
|||
} |
|||
|
|||
nsvgDelete(g_plist); |
|||
|
|||
glfwTerminate(); |
|||
return 0; |
|||
} |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 59 KiB |
After Width: | Height: | Size: 813 B |
After Width: | Height: | Size: 505 B |
After Width: | Height: | Size: 855 B |
After Width: | Height: | Size: 199 B |
@ -0,0 +1,32 @@ |
|||
|
|||
local action = _ACTION or "" |
|||
|
|||
solution "nanosvg" |
|||
location ( "build" ) |
|||
configurations { "Debug", "Release" } |
|||
platforms {"native", "x64", "x32"} |
|||
|
|||
project "example" |
|||
kind "ConsoleApp" |
|||
language "C++" |
|||
files { "example/*.c", "example/*.h", "src/*.h" } |
|||
includedirs { "example", "src" } |
|||
targetdir("build") |
|||
|
|||
configuration { "linux" } |
|||
links { "X11","Xrandr", "rt", "GL", "GLU", "pthread" } |
|||
|
|||
configuration { "windows" } |
|||
links { "glu32","opengl32", "gdi32", "winmm", "user32" } |
|||
|
|||
configuration { "macosx" } |
|||
links { "glfw3" } |
|||
linkoptions { "-framework OpenGL", "-framework Cocoa", "-framework IOKit" } |
|||
|
|||
configuration "Debug" |
|||
defines { "DEBUG" } |
|||
flags { "Symbols", "ExtraWarnings"} |
|||
|
|||
configuration "Release" |
|||
defines { "NDEBUG" } |
|||
flags { "Optimize", "ExtraWarnings"} |