mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-25 15:45:38 +00:00
Squashed 'external/nanosvg/' content from commit 3cdd4a9d
git-subtree-dir: external/nanosvg git-subtree-split: 3cdd4a9d788695699799b37d492e45e2c3625790
This commit is contained in:
commit
1c472d8085
31
.gitignore
vendored
Normal file
31
.gitignore
vendored
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
## Compiled source #
|
||||||
|
*.com
|
||||||
|
*.class
|
||||||
|
*.dll
|
||||||
|
*.exe
|
||||||
|
*.o
|
||||||
|
*.so
|
||||||
|
test
|
||||||
|
|
||||||
|
## Logs and databases #
|
||||||
|
*.log
|
||||||
|
*.sql
|
||||||
|
*.sqlite
|
||||||
|
|
||||||
|
## OS generated files #
|
||||||
|
.DS_Store
|
||||||
|
.DS_Store?
|
||||||
|
._*
|
||||||
|
.Spotlight-V100
|
||||||
|
.Trashes
|
||||||
|
ehthumbs.db
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
## Build dir
|
||||||
|
build/*
|
||||||
|
|
||||||
|
## Stuff in example
|
||||||
|
example/_*
|
||||||
|
|
||||||
|
## xcode specific
|
||||||
|
*xcuserdata*
|
18
LICENSE.txt
Normal file
18
LICENSE.txt
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
Copyright (c) 2013-14 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.
|
||||||
|
|
102
README.md
Normal file
102
README.md
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
*This project is not actively maintained.*
|
||||||
|
|
||||||
|
Nano SVG
|
||||||
|
==========
|
||||||
|
|
||||||
|
## Parser
|
||||||
|
|
||||||
|
![screenshot of some splines rendered with the sample program](/example/screenshot-1.png?raw=true)
|
||||||
|
|
||||||
|
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](/example/screenshot-2.png?raw=true)
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
``` C
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
``` C
|
||||||
|
#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](http://www.w3.org/TR/SVG11/types.html#ColorKeywords), define `NANOSVG_ALL_COLOR_KEYWORDS` before expanding the implementation.
|
||||||
|
|
||||||
|
``` C
|
||||||
|
#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"
|
||||||
|
```
|
||||||
|
|
||||||
|
## 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)
|
730
example/23.svg
Normal file
730
example/23.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 94 KiB |
97
example/drawing.svg
Normal file
97
example/drawing.svg
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="1000"
|
||||||
|
height="1000"
|
||||||
|
id="svg2"
|
||||||
|
version="1.1"
|
||||||
|
inkscape:version="0.48.2 r9819"
|
||||||
|
sodipodi:docname="drawing.svg">
|
||||||
|
<defs
|
||||||
|
id="defs4" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="0.35"
|
||||||
|
inkscape:cx="375"
|
||||||
|
inkscape:cy="520"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:window-width="751"
|
||||||
|
inkscape:window-height="578"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="22"
|
||||||
|
inkscape:window-maximized="0" />
|
||||||
|
<metadata
|
||||||
|
id="metadata7">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"
|
||||||
|
transform="translate(0,-52.362183)">
|
||||||
|
<path
|
||||||
|
style="fill:#ff5555;stroke:#000000;stroke-width:10.62107277px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m 131.73911,422.01626 c 0,146.85769 43.82213,215.39128 201.5818,141.96244 157.75968,-73.42885 188.43518,-107.69564 354.95926,78.32409 166.5241,186.01973 210.34624,244.76282 162.1419,-122.3814 -48.20435,-367.1442 -4.38221,34.26679 -131.46641,-24.47627 C 591.87149,436.70204 732.10231,191.93923 543.66715,187.04398 355.23198,182.14871 574.34264,265.36807 534.90271,368.16845 495.4628,470.96883 355.23198,627.61702 311.40985,475.8641 267.58772,324.11115 193.09009,333.90166 131.73911,422.01626 z"
|
||||||
|
id="path2985"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<rect
|
||||||
|
style="fill:#00ffff;stroke:#000000;stroke-width:10.62107277px;"
|
||||||
|
id="rect2987"
|
||||||
|
width="390.01697"
|
||||||
|
height="200.70551"
|
||||||
|
x="228.14781"
|
||||||
|
y="539.50238" />
|
||||||
|
<path
|
||||||
|
sodipodi:type="arc"
|
||||||
|
style="fill:#00ffff"
|
||||||
|
id="path3008"
|
||||||
|
sodipodi:cx="157.14285"
|
||||||
|
sodipodi:cy="168.57143"
|
||||||
|
sodipodi:rx="57.142857"
|
||||||
|
sodipodi:ry="88.571426"
|
||||||
|
d="m 214.28571,168.57143 a 57.142857,88.571426 0 1 1 -114.285714,0 57.142857,88.571426 0 1 1 114.285714,0 z"
|
||||||
|
transform="translate(188.57143,138.07647)" />
|
||||||
|
<rect
|
||||||
|
style="fill:#00ff00"
|
||||||
|
id="rect3010"
|
||||||
|
width="371.42856"
|
||||||
|
height="145.71428"
|
||||||
|
x="261.66104"
|
||||||
|
y="945.44141"
|
||||||
|
transform="matrix(0.948958,-0.31540248,0.31540248,0.948958,0,0)"
|
||||||
|
ry="51.42857" />
|
||||||
|
<path
|
||||||
|
sodipodi:type="arc"
|
||||||
|
style="fill:#00ff00"
|
||||||
|
id="path3038"
|
||||||
|
sodipodi:cx="200"
|
||||||
|
sodipodi:cy="177.14285"
|
||||||
|
sodipodi:rx="54.285713"
|
||||||
|
sodipodi:ry="54.285713"
|
||||||
|
d="m 254.28571,177.14285 a 54.285713,54.285713 0 1 1 -108.57142,0 54.285713,54.285713 0 1 1 108.57142,0 z"
|
||||||
|
transform="translate(0,52.362183)" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 3.4 KiB |
258
example/example1.c
Normal file
258
example/example1.c
Normal file
|
@ -0,0 +1,258 @@
|
||||||
|
//
|
||||||
|
// 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"
|
||||||
|
|
||||||
|
NSVGimage* g_image = NULL;
|
||||||
|
|
||||||
|
static unsigned char bgColor[4] = {205,202,200,255};
|
||||||
|
static unsigned char lineColor[4] = {0,160,192,255};
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
|
||||||
|
glBegin(GL_POINTS);
|
||||||
|
glVertex2f(pts[0],pts[1]);
|
||||||
|
for (i = 0; i < npts-1; i += 3) {
|
||||||
|
float* p = &pts[i*2];
|
||||||
|
glVertex2f(p[6],p[7]);
|
||||||
|
}
|
||||||
|
glEnd();
|
||||||
|
|
||||||
|
// Points
|
||||||
|
glPointSize(3.0f);
|
||||||
|
|
||||||
|
glBegin(GL_POINTS);
|
||||||
|
glColor4ubv(bgColor);
|
||||||
|
glVertex2f(pts[0],pts[1]);
|
||||||
|
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 view[4], cx, cy, hw, hh, aspect, px;
|
||||||
|
NSVGshape* shape;
|
||||||
|
NSVGpath* path;
|
||||||
|
|
||||||
|
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
|
||||||
|
cx = g_image->width*0.5f;
|
||||||
|
cy = g_image->height*0.5f;
|
||||||
|
hw = g_image->width*0.5f;
|
||||||
|
hh = g_image->height*0.5f;
|
||||||
|
|
||||||
|
if (width/hw < height/hh) {
|
||||||
|
aspect = (float)height / (float)width;
|
||||||
|
view[0] = cx - hw * 1.2f;
|
||||||
|
view[2] = cx + hw * 1.2f;
|
||||||
|
view[1] = cy - hw * 1.2f * aspect;
|
||||||
|
view[3] = cy + hw * 1.2f * aspect;
|
||||||
|
} else {
|
||||||
|
aspect = (float)width / (float)height;
|
||||||
|
view[0] = cx - hh * 1.2f * aspect;
|
||||||
|
view[2] = cx + hh * 1.2f * aspect;
|
||||||
|
view[1] = cy - hh * 1.2f;
|
||||||
|
view[3] = cy + hh * 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);
|
||||||
|
|
||||||
|
// Draw bounds
|
||||||
|
glColor4ub(0,0,0,64);
|
||||||
|
glBegin(GL_LINE_LOOP);
|
||||||
|
glVertex2f(0, 0);
|
||||||
|
glVertex2f(g_image->width, 0);
|
||||||
|
glVertex2f(g_image->width, g_image->height);
|
||||||
|
glVertex2f(0, g_image->height);
|
||||||
|
glEnd();
|
||||||
|
|
||||||
|
for (shape = g_image->shapes; shape != NULL; shape = shape->next) {
|
||||||
|
for (path = shape->paths; path != NULL; path = path->next) {
|
||||||
|
drawPath(path->pts, path->npts, path->closed, px * 1.5f);
|
||||||
|
drawControlPts(path->pts, path->npts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
glfwSwapBuffers(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
void resizecb(GLFWwindow* window, int width, int height)
|
||||||
|
{
|
||||||
|
// Update and render
|
||||||
|
NSVG_NOTUSED(width);
|
||||||
|
NSVG_NOTUSED(height);
|
||||||
|
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_image = nsvgParseFromFile("../example/nano.svg", "px", 96.0f);
|
||||||
|
if (g_image == NULL) {
|
||||||
|
printf("Could not open SVG image.\n");
|
||||||
|
glfwTerminate();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!glfwWindowShouldClose(window))
|
||||||
|
{
|
||||||
|
drawframe(window);
|
||||||
|
glfwPollEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
nsvgDelete(g_image);
|
||||||
|
|
||||||
|
glfwTerminate();
|
||||||
|
return 0;
|
||||||
|
}
|
69
example/example2.c
Normal file
69
example/example2.c
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
//
|
||||||
|
// 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>
|
||||||
|
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||||
|
#include "stb_image_write.h"
|
||||||
|
#define NANOSVG_IMPLEMENTATION
|
||||||
|
#include "nanosvg.h"
|
||||||
|
#define NANOSVGRAST_IMPLEMENTATION
|
||||||
|
#include "nanosvgrast.h"
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
NSVGimage *image = NULL;
|
||||||
|
NSVGrasterizer *rast = NULL;
|
||||||
|
unsigned char* img = NULL;
|
||||||
|
int w, h;
|
||||||
|
const char* filename = "../example/23.svg";
|
||||||
|
|
||||||
|
printf("parsing %s\n", filename);
|
||||||
|
image = nsvgParseFromFile(filename, "px", 96.0f);
|
||||||
|
if (image == NULL) {
|
||||||
|
printf("Could not open SVG image.\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
w = (int)image->width;
|
||||||
|
h = (int)image->height;
|
||||||
|
|
||||||
|
rast = nsvgCreateRasterizer();
|
||||||
|
if (rast == NULL) {
|
||||||
|
printf("Could not init rasterizer.\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
img = malloc(w*h*4);
|
||||||
|
if (img == NULL) {
|
||||||
|
printf("Could not alloc image buffer.\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
error:
|
||||||
|
nsvgDeleteRasterizer(rast);
|
||||||
|
nsvgDelete(image);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
27
example/nano.svg
Normal file
27
example/nano.svg
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 14948) -->
|
||||||
|
<!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="640px" height="480px" viewBox="0 0 640 480" enable-background="new 0 0 640 480" xml:space="preserve">
|
||||||
|
<path d="M282.658,250.271c0,5.31-1.031,10.156-3.087,14.543c-2.059,4.387-4.984,8.152-8.774,11.293
|
||||||
|
c-3.793,3.144-8.477,5.58-14.055,7.312c-5.581,1.731-11.836,2.601-18.767,2.601c-9.968,0-18.605-1.572-25.917-4.713
|
||||||
|
s-13.299-6.986-17.955-11.536l13.812-15.111c4.116,3.684,8.584,6.499,13.405,8.449c4.819,1.95,9.993,2.925,15.518,2.925
|
||||||
|
c5.525,0,9.856-1.219,12.999-3.656c3.141-2.438,4.712-5.769,4.712-9.993c0-2.056-0.3-3.844-0.894-5.361
|
||||||
|
c-0.596-1.517-1.653-2.925-3.168-4.226c-1.518-1.3-3.549-2.519-6.093-3.655c-2.546-1.138-5.768-2.301-9.668-3.494
|
||||||
|
c-6.5-2.056-11.943-4.25-16.33-6.58c-4.387-2.328-7.937-4.9-10.643-7.719c-2.709-2.815-4.659-5.931-5.849-9.343
|
||||||
|
c-1.193-3.412-1.788-7.23-1.788-11.455c0-5.2,1.082-9.831,3.25-13.893c2.166-4.062,5.144-7.5,8.937-10.318
|
||||||
|
c3.791-2.815,8.178-4.956,13.162-6.418c4.981-1.462,10.343-2.193,16.086-2.193c8.449,0,15.842,1.247,22.179,3.737
|
||||||
|
c6.337,2.493,11.997,6.121,16.98,10.887l-12.674,14.624c-7.583-6.281-15.655-9.424-24.21-9.424c-4.875,0-8.721,0.95-11.537,2.844
|
||||||
|
c-2.818,1.896-4.225,4.578-4.225,8.043c0,1.843,0.297,3.412,0.894,4.712c0.594,1.3,1.65,2.519,3.168,3.656
|
||||||
|
c1.516,1.137,3.656,2.249,6.418,3.331c2.763,1.084,6.309,2.33,10.643,3.736c5.306,1.734,10.046,3.631,14.218,5.688
|
||||||
|
c4.169,2.06,7.662,4.524,10.48,7.394c2.815,2.871,4.981,6.174,6.5,9.911C281.898,240.603,282.658,245.071,282.658,250.271z
|
||||||
|
M335.953,260.833l20.637-90.181h27.46l-32.011,112.604h-33.634l-32.173-112.604h28.598l20.311,90.181H335.953z M437.832,286.019
|
||||||
|
c-16.357,0-28.896-5.01-37.615-15.03c-8.722-10.019-13.081-24.779-13.081-44.278c0-9.531,1.407-17.98,4.225-25.348
|
||||||
|
c2.815-7.366,6.688-13.54,11.618-18.524c4.928-4.981,10.668-8.747,17.223-11.293c6.555-2.544,13.568-3.818,21.043-3.818
|
||||||
|
c8.23,0,15.436,1.3,21.611,3.899c6.174,2.6,11.537,5.959,16.086,10.075l-14.137,14.624c-3.467-3.032-6.906-5.281-10.318-6.744
|
||||||
|
s-7.393-2.193-11.941-2.193c-4.01,0-7.693,0.731-11.051,2.193s-6.256,3.793-8.691,6.987c-2.438,3.196-4.334,7.287-5.688,12.268
|
||||||
|
c-1.355,4.984-2.031,10.996-2.031,18.037c0,7.367,0.486,13.567,1.463,18.604c0.975,5.037,2.408,9.1,4.305,12.187
|
||||||
|
c1.895,3.087,4.307,5.309,7.23,6.662c2.926,1.355,6.338,2.031,10.238,2.031c5.631,0,10.613-1.244,14.947-3.737v-25.186h-14.785
|
||||||
|
l-2.6-18.849h43.547v55.57c-5.85,3.793-12.297,6.718-19.336,8.774C453.051,284.987,445.631,286.019,437.832,286.019z M523.5,151.5
|
||||||
|
c0-6.627-5.373-12-12-12h-343c-6.627,0-12,5.373-12,12v150c0,6.627,5.373,12,12,12h343c6.627,0,12-5.373,12-12V151.5z"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.8 KiB |
BIN
example/screenshot-1.png
Normal file
BIN
example/screenshot-1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 59 KiB |
BIN
example/screenshot-2.png
Normal file
BIN
example/screenshot-2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 154 KiB |
511
example/stb_image_write.h
Normal file
511
example/stb_image_write.h
Normal file
|
@ -0,0 +1,511 @@
|
||||||
|
/* stbiw-0.92 - public domain - http://nothings.org/stb/stb_image_write.h
|
||||||
|
writes out PNG/BMP/TGA images to C stdio - Sean Barrett 2010
|
||||||
|
no warranty implied; use at your own risk
|
||||||
|
|
||||||
|
|
||||||
|
Before including,
|
||||||
|
|
||||||
|
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||||
|
|
||||||
|
in the file that you want to have the implementation.
|
||||||
|
|
||||||
|
|
||||||
|
ABOUT:
|
||||||
|
|
||||||
|
This header file is a library for writing images to C stdio. It could be
|
||||||
|
adapted to write to memory or a general streaming interface; let me know.
|
||||||
|
|
||||||
|
The PNG output is not optimal; it is 20-50% larger than the file
|
||||||
|
written by a decent optimizing implementation. This library is designed
|
||||||
|
for source code compactness and simplicitly, not optimal image file size
|
||||||
|
or run-time performance.
|
||||||
|
|
||||||
|
USAGE:
|
||||||
|
|
||||||
|
There are three functions, one for each image file format:
|
||||||
|
|
||||||
|
int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes);
|
||||||
|
int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data);
|
||||||
|
int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data);
|
||||||
|
|
||||||
|
Each function returns 0 on failure and non-0 on success.
|
||||||
|
|
||||||
|
The functions create an image file defined by the parameters. The image
|
||||||
|
is a rectangle of pixels stored from left-to-right, top-to-bottom.
|
||||||
|
Each pixel contains 'comp' channels of data stored interleaved with 8-bits
|
||||||
|
per channel, in the following order: 1=Y, 2=YA, 3=RGB, 4=RGBA. (Y is
|
||||||
|
monochrome color.) The rectangle is 'w' pixels wide and 'h' pixels tall.
|
||||||
|
The *data pointer points to the first byte of the top-left-most pixel.
|
||||||
|
For PNG, "stride_in_bytes" is the distance in bytes from the first byte of
|
||||||
|
a row of pixels to the first byte of the next row of pixels.
|
||||||
|
|
||||||
|
PNG creates output files with the same number of components as the input.
|
||||||
|
The BMP and TGA formats expand Y to RGB in the file format. BMP does not
|
||||||
|
output alpha.
|
||||||
|
|
||||||
|
PNG supports writing rectangles of data even when the bytes storing rows of
|
||||||
|
data are not consecutive in memory (e.g. sub-rectangles of a larger image),
|
||||||
|
by supplying the stride between the beginning of adjacent rows. The other
|
||||||
|
formats do not. (Thus you cannot write a native-format BMP through the BMP
|
||||||
|
writer, both because it is in BGR order and because it may have padding
|
||||||
|
at the end of the line.)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INCLUDE_STB_IMAGE_WRITE_H
|
||||||
|
#define INCLUDE_STB_IMAGE_WRITE_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes);
|
||||||
|
extern int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data);
|
||||||
|
extern int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif//INCLUDE_STB_IMAGE_WRITE_H
|
||||||
|
|
||||||
|
#ifdef STB_IMAGE_WRITE_IMPLEMENTATION
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
typedef unsigned int stbiw_uint32;
|
||||||
|
typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1];
|
||||||
|
|
||||||
|
static void writefv(FILE *f, const char *fmt, va_list v)
|
||||||
|
{
|
||||||
|
while (*fmt) {
|
||||||
|
switch (*fmt++) {
|
||||||
|
case ' ': break;
|
||||||
|
case '1': { unsigned char x = (unsigned char) va_arg(v, int); fputc(x,f); break; }
|
||||||
|
case '2': { int x = va_arg(v,int); unsigned char b[2];
|
||||||
|
b[0] = (unsigned char) x; b[1] = (unsigned char) (x>>8);
|
||||||
|
fwrite(b,2,1,f); break; }
|
||||||
|
case '4': { stbiw_uint32 x = va_arg(v,int); unsigned char b[4];
|
||||||
|
b[0]=(unsigned char)x; b[1]=(unsigned char)(x>>8);
|
||||||
|
b[2]=(unsigned char)(x>>16); b[3]=(unsigned char)(x>>24);
|
||||||
|
fwrite(b,4,1,f); break; }
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write3(FILE *f, unsigned char a, unsigned char b, unsigned char c)
|
||||||
|
{
|
||||||
|
unsigned char arr[3];
|
||||||
|
arr[0] = a, arr[1] = b, arr[2] = c;
|
||||||
|
fwrite(arr, 3, 1, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write_pixels(FILE *f, int rgb_dir, int vdir, int x, int y, int comp, void *data, int write_alpha, int scanline_pad)
|
||||||
|
{
|
||||||
|
unsigned char bg[3] = { 255, 0, 255}, px[3];
|
||||||
|
stbiw_uint32 zero = 0;
|
||||||
|
int i,j,k, j_end;
|
||||||
|
|
||||||
|
if (y <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (vdir < 0)
|
||||||
|
j_end = -1, j = y-1;
|
||||||
|
else
|
||||||
|
j_end = y, j = 0;
|
||||||
|
|
||||||
|
for (; j != j_end; j += vdir) {
|
||||||
|
for (i=0; i < x; ++i) {
|
||||||
|
unsigned char *d = (unsigned char *) data + (j*x+i)*comp;
|
||||||
|
if (write_alpha < 0)
|
||||||
|
fwrite(&d[comp-1], 1, 1, f);
|
||||||
|
switch (comp) {
|
||||||
|
case 1:
|
||||||
|
case 2: write3(f, d[0],d[0],d[0]);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
if (!write_alpha) {
|
||||||
|
// composite against pink background
|
||||||
|
for (k=0; k < 3; ++k)
|
||||||
|
px[k] = bg[k] + ((d[k] - bg[k]) * d[3])/255;
|
||||||
|
write3(f, px[1-rgb_dir],px[1],px[1+rgb_dir]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* FALLTHROUGH */
|
||||||
|
case 3:
|
||||||
|
write3(f, d[1-rgb_dir],d[1],d[1+rgb_dir]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (write_alpha > 0)
|
||||||
|
fwrite(&d[comp-1], 1, 1, f);
|
||||||
|
}
|
||||||
|
fwrite(&zero,scanline_pad,1,f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int outfile(char const *filename, int rgb_dir, int vdir, int x, int y, int comp, void *data, int alpha, int pad, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
FILE *f;
|
||||||
|
if (y < 0 || x < 0) return 0;
|
||||||
|
f = fopen(filename, "wb");
|
||||||
|
if (f) {
|
||||||
|
va_list v;
|
||||||
|
va_start(v, fmt);
|
||||||
|
writefv(f, fmt, v);
|
||||||
|
va_end(v);
|
||||||
|
write_pixels(f,rgb_dir,vdir,x,y,comp,data,alpha,pad);
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
return f != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data)
|
||||||
|
{
|
||||||
|
int pad = (-x*3) & 3;
|
||||||
|
return outfile(filename,-1,-1,x,y,comp,(void *) data,0,pad,
|
||||||
|
"11 4 22 4" "4 44 22 444444",
|
||||||
|
'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header
|
||||||
|
40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header
|
||||||
|
}
|
||||||
|
|
||||||
|
int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data)
|
||||||
|
{
|
||||||
|
int has_alpha = !(comp & 1);
|
||||||
|
return outfile(filename, -1,-1, x, y, comp, (void *) data, has_alpha, 0,
|
||||||
|
"111 221 2222 11", 0,0,2, 0,0,0, 0,0,x,y, 24+8*has_alpha, 8*has_alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
// stretchy buffer; stbi__sbpush() == vector<>::push_back() -- stbi__sbcount() == vector<>::size()
|
||||||
|
#define stbi__sbraw(a) ((int *) (a) - 2)
|
||||||
|
#define stbi__sbm(a) stbi__sbraw(a)[0]
|
||||||
|
#define stbi__sbn(a) stbi__sbraw(a)[1]
|
||||||
|
|
||||||
|
#define stbi__sbneedgrow(a,n) ((a)==0 || stbi__sbn(a)+n >= stbi__sbm(a))
|
||||||
|
#define stbi__sbmaybegrow(a,n) (stbi__sbneedgrow(a,(n)) ? stbi__sbgrow(a,n) : 0)
|
||||||
|
#define stbi__sbgrow(a,n) stbi__sbgrowf((void **) &(a), (n), sizeof(*(a)))
|
||||||
|
|
||||||
|
#define stbi__sbpush(a, v) (stbi__sbmaybegrow(a,1), (a)[stbi__sbn(a)++] = (v))
|
||||||
|
#define stbi__sbcount(a) ((a) ? stbi__sbn(a) : 0)
|
||||||
|
#define stbi__sbfree(a) ((a) ? free(stbi__sbraw(a)),0 : 0)
|
||||||
|
|
||||||
|
static void *stbi__sbgrowf(void **arr, int increment, int itemsize)
|
||||||
|
{
|
||||||
|
int m = *arr ? 2*stbi__sbm(*arr)+increment : increment+1;
|
||||||
|
void *p = realloc(*arr ? stbi__sbraw(*arr) : 0, itemsize * m + sizeof(int)*2);
|
||||||
|
assert(p);
|
||||||
|
if (p) {
|
||||||
|
if (!*arr) ((int *) p)[1] = 0;
|
||||||
|
*arr = (void *) ((int *) p + 2);
|
||||||
|
stbi__sbm(*arr) = m;
|
||||||
|
}
|
||||||
|
return *arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned char *stbi__zlib_flushf(unsigned char *data, unsigned int *bitbuffer, int *bitcount)
|
||||||
|
{
|
||||||
|
while (*bitcount >= 8) {
|
||||||
|
stbi__sbpush(data, (unsigned char) *bitbuffer);
|
||||||
|
*bitbuffer >>= 8;
|
||||||
|
*bitcount -= 8;
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int stbi__zlib_bitrev(int code, int codebits)
|
||||||
|
{
|
||||||
|
int res=0;
|
||||||
|
while (codebits--) {
|
||||||
|
res = (res << 1) | (code & 1);
|
||||||
|
code >>= 1;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int stbi__zlib_countm(unsigned char *a, unsigned char *b, int limit)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i=0; i < limit && i < 258; ++i)
|
||||||
|
if (a[i] != b[i]) break;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int stbi__zhash(unsigned char *data)
|
||||||
|
{
|
||||||
|
stbiw_uint32 hash = data[0] + (data[1] << 8) + (data[2] << 16);
|
||||||
|
hash ^= hash << 3;
|
||||||
|
hash += hash >> 5;
|
||||||
|
hash ^= hash << 4;
|
||||||
|
hash += hash >> 17;
|
||||||
|
hash ^= hash << 25;
|
||||||
|
hash += hash >> 6;
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define stbi__zlib_flush() (out = stbi__zlib_flushf(out, &bitbuf, &bitcount))
|
||||||
|
#define stbi__zlib_add(code,codebits) \
|
||||||
|
(bitbuf |= (code) << bitcount, bitcount += (codebits), stbi__zlib_flush())
|
||||||
|
#define stbi__zlib_huffa(b,c) stbi__zlib_add(stbi__zlib_bitrev(b,c),c)
|
||||||
|
// default huffman tables
|
||||||
|
#define stbi__zlib_huff1(n) stbi__zlib_huffa(0x30 + (n), 8)
|
||||||
|
#define stbi__zlib_huff2(n) stbi__zlib_huffa(0x190 + (n)-144, 9)
|
||||||
|
#define stbi__zlib_huff3(n) stbi__zlib_huffa(0 + (n)-256,7)
|
||||||
|
#define stbi__zlib_huff4(n) stbi__zlib_huffa(0xc0 + (n)-280,8)
|
||||||
|
#define stbi__zlib_huff(n) ((n) <= 143 ? stbi__zlib_huff1(n) : (n) <= 255 ? stbi__zlib_huff2(n) : (n) <= 279 ? stbi__zlib_huff3(n) : stbi__zlib_huff4(n))
|
||||||
|
#define stbi__zlib_huffb(n) ((n) <= 143 ? stbi__zlib_huff1(n) : stbi__zlib_huff2(n))
|
||||||
|
|
||||||
|
#define stbi__ZHASH 16384
|
||||||
|
|
||||||
|
unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality)
|
||||||
|
{
|
||||||
|
static unsigned short lengthc[] = { 3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258, 259 };
|
||||||
|
static unsigned char lengtheb[]= { 0,0,0,0,0,0,0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 };
|
||||||
|
static unsigned short distc[] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577, 32768 };
|
||||||
|
static unsigned char disteb[] = { 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13 };
|
||||||
|
unsigned int bitbuf=0;
|
||||||
|
int i,j, bitcount=0;
|
||||||
|
unsigned char *out = NULL;
|
||||||
|
unsigned char **hash_table[stbi__ZHASH]; // 64KB on the stack!
|
||||||
|
if (quality < 5) quality = 5;
|
||||||
|
|
||||||
|
stbi__sbpush(out, 0x78); // DEFLATE 32K window
|
||||||
|
stbi__sbpush(out, 0x5e); // FLEVEL = 1
|
||||||
|
stbi__zlib_add(1,1); // BFINAL = 1
|
||||||
|
stbi__zlib_add(1,2); // BTYPE = 1 -- fixed huffman
|
||||||
|
|
||||||
|
for (i=0; i < stbi__ZHASH; ++i)
|
||||||
|
hash_table[i] = NULL;
|
||||||
|
|
||||||
|
i=0;
|
||||||
|
while (i < data_len-3) {
|
||||||
|
// hash next 3 bytes of data to be compressed
|
||||||
|
int h = stbi__zhash(data+i)&(stbi__ZHASH-1), best=3;
|
||||||
|
unsigned char *bestloc = 0;
|
||||||
|
unsigned char **hlist = hash_table[h];
|
||||||
|
int n = stbi__sbcount(hlist);
|
||||||
|
for (j=0; j < n; ++j) {
|
||||||
|
if (hlist[j]-data > i-32768) { // if entry lies within window
|
||||||
|
int d = stbi__zlib_countm(hlist[j], data+i, data_len-i);
|
||||||
|
if (d >= best) best=d,bestloc=hlist[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// when hash table entry is too long, delete half the entries
|
||||||
|
if (hash_table[h] && stbi__sbn(hash_table[h]) == 2*quality) {
|
||||||
|
memcpy(hash_table[h], hash_table[h]+quality, sizeof(hash_table[h][0])*quality);
|
||||||
|
stbi__sbn(hash_table[h]) = quality;
|
||||||
|
}
|
||||||
|
stbi__sbpush(hash_table[h],data+i);
|
||||||
|
|
||||||
|
if (bestloc) {
|
||||||
|
// "lazy matching" - check match at *next* byte, and if it's better, do cur byte as literal
|
||||||
|
h = stbi__zhash(data+i+1)&(stbi__ZHASH-1);
|
||||||
|
hlist = hash_table[h];
|
||||||
|
n = stbi__sbcount(hlist);
|
||||||
|
for (j=0; j < n; ++j) {
|
||||||
|
if (hlist[j]-data > i-32767) {
|
||||||
|
int e = stbi__zlib_countm(hlist[j], data+i+1, data_len-i-1);
|
||||||
|
if (e > best) { // if next match is better, bail on current match
|
||||||
|
bestloc = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bestloc) {
|
||||||
|
int d = data+i - bestloc; // distance back
|
||||||
|
assert(d <= 32767 && best <= 258);
|
||||||
|
for (j=0; best > lengthc[j+1]-1; ++j);
|
||||||
|
stbi__zlib_huff(j+257);
|
||||||
|
if (lengtheb[j]) stbi__zlib_add(best - lengthc[j], lengtheb[j]);
|
||||||
|
for (j=0; d > distc[j+1]-1; ++j);
|
||||||
|
stbi__zlib_add(stbi__zlib_bitrev(j,5),5);
|
||||||
|
if (disteb[j]) stbi__zlib_add(d - distc[j], disteb[j]);
|
||||||
|
i += best;
|
||||||
|
} else {
|
||||||
|
stbi__zlib_huffb(data[i]);
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// write out final bytes
|
||||||
|
for (;i < data_len; ++i)
|
||||||
|
stbi__zlib_huffb(data[i]);
|
||||||
|
stbi__zlib_huff(256); // end of block
|
||||||
|
// pad with 0 bits to byte boundary
|
||||||
|
while (bitcount)
|
||||||
|
stbi__zlib_add(0,1);
|
||||||
|
|
||||||
|
for (i=0; i < stbi__ZHASH; ++i)
|
||||||
|
(void) stbi__sbfree(hash_table[i]);
|
||||||
|
|
||||||
|
{
|
||||||
|
// compute adler32 on input
|
||||||
|
unsigned int i=0, s1=1, s2=0, blocklen = data_len % 5552;
|
||||||
|
int j=0;
|
||||||
|
while (j < data_len) {
|
||||||
|
for (i=0; i < blocklen; ++i) s1 += data[j+i], s2 += s1;
|
||||||
|
s1 %= 65521, s2 %= 65521;
|
||||||
|
j += blocklen;
|
||||||
|
blocklen = 5552;
|
||||||
|
}
|
||||||
|
stbi__sbpush(out, (unsigned char) (s2 >> 8));
|
||||||
|
stbi__sbpush(out, (unsigned char) s2);
|
||||||
|
stbi__sbpush(out, (unsigned char) (s1 >> 8));
|
||||||
|
stbi__sbpush(out, (unsigned char) s1);
|
||||||
|
}
|
||||||
|
*out_len = stbi__sbn(out);
|
||||||
|
// make returned pointer freeable
|
||||||
|
memmove(stbi__sbraw(out), out, *out_len);
|
||||||
|
return (unsigned char *) stbi__sbraw(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int stbi__crc32(unsigned char *buffer, int len)
|
||||||
|
{
|
||||||
|
static unsigned int crc_table[256];
|
||||||
|
unsigned int crc = ~0u;
|
||||||
|
int i,j;
|
||||||
|
if (crc_table[1] == 0)
|
||||||
|
for(i=0; i < 256; i++)
|
||||||
|
for (crc_table[i]=i, j=0; j < 8; ++j)
|
||||||
|
crc_table[i] = (crc_table[i] >> 1) ^ (crc_table[i] & 1 ? 0xedb88320 : 0);
|
||||||
|
for (i=0; i < len; ++i)
|
||||||
|
crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)];
|
||||||
|
return ~crc;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define stbi__wpng4(o,a,b,c,d) ((o)[0]=(unsigned char)(a),(o)[1]=(unsigned char)(b),(o)[2]=(unsigned char)(c),(o)[3]=(unsigned char)(d),(o)+=4)
|
||||||
|
#define stbi__wp32(data,v) stbi__wpng4(data, (v)>>24,(v)>>16,(v)>>8,(v));
|
||||||
|
#define stbi__wptag(data,s) stbi__wpng4(data, s[0],s[1],s[2],s[3])
|
||||||
|
|
||||||
|
static void stbi__wpcrc(unsigned char **data, int len)
|
||||||
|
{
|
||||||
|
unsigned int crc = stbi__crc32(*data - len - 4, len+4);
|
||||||
|
stbi__wp32(*data, crc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned char stbi__paeth(int a, int b, int c)
|
||||||
|
{
|
||||||
|
int p = a + b - c, pa = abs(p-a), pb = abs(p-b), pc = abs(p-c);
|
||||||
|
if (pa <= pb && pa <= pc) return (unsigned char) a;
|
||||||
|
if (pb <= pc) return (unsigned char) b;
|
||||||
|
return (unsigned char) c;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len)
|
||||||
|
{
|
||||||
|
int ctype[5] = { -1, 0, 4, 2, 6 };
|
||||||
|
unsigned char sig[8] = { 137,80,78,71,13,10,26,10 };
|
||||||
|
unsigned char *out,*o, *filt, *zlib;
|
||||||
|
signed char *line_buffer;
|
||||||
|
int i,j,k,p,zlen;
|
||||||
|
|
||||||
|
if (stride_bytes == 0)
|
||||||
|
stride_bytes = x * n;
|
||||||
|
|
||||||
|
filt = (unsigned char *) malloc((x*n+1) * y); if (!filt) return 0;
|
||||||
|
line_buffer = (signed char *) malloc(x * n); if (!line_buffer) { free(filt); return 0; }
|
||||||
|
for (j=0; j < y; ++j) {
|
||||||
|
static int mapping[] = { 0,1,2,3,4 };
|
||||||
|
static int firstmap[] = { 0,1,0,5,6 };
|
||||||
|
int *mymap = j ? mapping : firstmap;
|
||||||
|
int best = 0, bestval = 0x7fffffff;
|
||||||
|
for (p=0; p < 2; ++p) {
|
||||||
|
for (k= p?best:0; k < 5; ++k) {
|
||||||
|
int type = mymap[k],est=0;
|
||||||
|
unsigned char *z = pixels + stride_bytes*j;
|
||||||
|
for (i=0; i < n; ++i)
|
||||||
|
switch (type) {
|
||||||
|
case 0: line_buffer[i] = z[i]; break;
|
||||||
|
case 1: line_buffer[i] = z[i]; break;
|
||||||
|
case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break;
|
||||||
|
case 3: line_buffer[i] = z[i] - (z[i-stride_bytes]>>1); break;
|
||||||
|
case 4: line_buffer[i] = (signed char) (z[i] - stbi__paeth(0,z[i-stride_bytes],0)); break;
|
||||||
|
case 5: line_buffer[i] = z[i]; break;
|
||||||
|
case 6: line_buffer[i] = z[i]; break;
|
||||||
|
}
|
||||||
|
for (i=n; i < x*n; ++i) {
|
||||||
|
switch (type) {
|
||||||
|
case 0: line_buffer[i] = z[i]; break;
|
||||||
|
case 1: line_buffer[i] = z[i] - z[i-n]; break;
|
||||||
|
case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break;
|
||||||
|
case 3: line_buffer[i] = z[i] - ((z[i-n] + z[i-stride_bytes])>>1); break;
|
||||||
|
case 4: line_buffer[i] = z[i] - stbi__paeth(z[i-n], z[i-stride_bytes], z[i-stride_bytes-n]); break;
|
||||||
|
case 5: line_buffer[i] = z[i] - (z[i-n]>>1); break;
|
||||||
|
case 6: line_buffer[i] = z[i] - stbi__paeth(z[i-n], 0,0); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (p) break;
|
||||||
|
for (i=0; i < x*n; ++i)
|
||||||
|
est += abs((signed char) line_buffer[i]);
|
||||||
|
if (est < bestval) { bestval = est; best = k; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// when we get here, best contains the filter type, and line_buffer contains the data
|
||||||
|
filt[j*(x*n+1)] = (unsigned char) best;
|
||||||
|
memcpy(filt+j*(x*n+1)+1, line_buffer, x*n);
|
||||||
|
}
|
||||||
|
free(line_buffer);
|
||||||
|
zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, 8); // increase 8 to get smaller but use more memory
|
||||||
|
free(filt);
|
||||||
|
if (!zlib) return 0;
|
||||||
|
|
||||||
|
// each tag requires 12 bytes of overhead
|
||||||
|
out = (unsigned char *) malloc(8 + 12+13 + 12+zlen + 12);
|
||||||
|
if (!out) return 0;
|
||||||
|
*out_len = 8 + 12+13 + 12+zlen + 12;
|
||||||
|
|
||||||
|
o=out;
|
||||||
|
memcpy(o,sig,8); o+= 8;
|
||||||
|
stbi__wp32(o, 13); // header length
|
||||||
|
stbi__wptag(o, "IHDR");
|
||||||
|
stbi__wp32(o, x);
|
||||||
|
stbi__wp32(o, y);
|
||||||
|
*o++ = 8;
|
||||||
|
*o++ = (unsigned char) ctype[n];
|
||||||
|
*o++ = 0;
|
||||||
|
*o++ = 0;
|
||||||
|
*o++ = 0;
|
||||||
|
stbi__wpcrc(&o,13);
|
||||||
|
|
||||||
|
stbi__wp32(o, zlen);
|
||||||
|
stbi__wptag(o, "IDAT");
|
||||||
|
memcpy(o, zlib, zlen); o += zlen; free(zlib);
|
||||||
|
stbi__wpcrc(&o, zlen);
|
||||||
|
|
||||||
|
stbi__wp32(o,0);
|
||||||
|
stbi__wptag(o, "IEND");
|
||||||
|
stbi__wpcrc(&o,0);
|
||||||
|
|
||||||
|
assert(o == out + *out_len);
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
int stbi_write_png(char const *filename, int x, int y, int comp, const void *data, int stride_bytes)
|
||||||
|
{
|
||||||
|
FILE *f;
|
||||||
|
int len;
|
||||||
|
unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len);
|
||||||
|
if (!png) return 0;
|
||||||
|
f = fopen(filename, "wb");
|
||||||
|
if (!f) { free(png); return 0; }
|
||||||
|
fwrite(png, 1, len, f);
|
||||||
|
fclose(f);
|
||||||
|
free(png);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif // STB_IMAGE_WRITE_IMPLEMENTATION
|
||||||
|
|
||||||
|
/* Revision history
|
||||||
|
|
||||||
|
0.92 (2010-08-01)
|
||||||
|
casts to unsigned char to fix warnings
|
||||||
|
0.91 (2010-07-17)
|
||||||
|
first public release
|
||||||
|
0.90 first internal release
|
||||||
|
*/
|
56
premake4.lua
Normal file
56
premake4.lua
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
|
||||||
|
local action = _ACTION or ""
|
||||||
|
|
||||||
|
solution "nanosvg"
|
||||||
|
location ( "build" )
|
||||||
|
configurations { "Debug", "Release" }
|
||||||
|
platforms {"native", "x64", "x32"}
|
||||||
|
|
||||||
|
project "example1"
|
||||||
|
kind "ConsoleApp"
|
||||||
|
language "C++"
|
||||||
|
files { "example/example1.c", "example/*.h", "src/*.h" }
|
||||||
|
includedirs { "example", "src" }
|
||||||
|
targetdir("build")
|
||||||
|
|
||||||
|
configuration { "linux" }
|
||||||
|
links { "X11","Xrandr", "rt", "GL", "GLU", "pthread", "glfw" }
|
||||||
|
|
||||||
|
configuration { "windows" }
|
||||||
|
links { "glu32","opengl32", "gdi32", "winmm", "user32" }
|
||||||
|
|
||||||
|
configuration { "macosx" }
|
||||||
|
links { "glfw3" }
|
||||||
|
linkoptions { "-framework OpenGL", "-framework Cocoa", "-framework IOKit", "-framework CoreVideo" }
|
||||||
|
|
||||||
|
configuration "Debug"
|
||||||
|
defines { "DEBUG" }
|
||||||
|
flags { "Symbols", "ExtraWarnings"}
|
||||||
|
|
||||||
|
configuration "Release"
|
||||||
|
defines { "NDEBUG" }
|
||||||
|
flags { "Optimize", "ExtraWarnings"}
|
||||||
|
|
||||||
|
project "example2"
|
||||||
|
kind "ConsoleApp"
|
||||||
|
language "C++"
|
||||||
|
files { "example/example2.c", "example/*.h", "src/*.h" }
|
||||||
|
includedirs { "example", "src" }
|
||||||
|
targetdir("build")
|
||||||
|
|
||||||
|
configuration { "linux" }
|
||||||
|
links { "X11","Xrandr", "rt", "pthread" }
|
||||||
|
|
||||||
|
configuration { "windows" }
|
||||||
|
links { "winmm", "user32" }
|
||||||
|
|
||||||
|
configuration { "macosx" }
|
||||||
|
linkoptions { "-framework Cocoa", "-framework IOKit" }
|
||||||
|
|
||||||
|
configuration "Debug"
|
||||||
|
defines { "DEBUG" }
|
||||||
|
flags { "Symbols", "ExtraWarnings"}
|
||||||
|
|
||||||
|
configuration "Release"
|
||||||
|
defines { "NDEBUG" }
|
||||||
|
flags { "Optimize", "ExtraWarnings"}
|
3021
src/nanosvg.h
Normal file
3021
src/nanosvg.h
Normal file
File diff suppressed because it is too large
Load diff
1452
src/nanosvgrast.h
Normal file
1452
src/nanosvgrast.h
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue