This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <float.h> | |
#include <inttypes.h> | |
#include "nanosvg.h" | |
#define NANOSVGRAST_IMPLEMENTATION | |
#include "nanosvgrast.h" | |
#define STB_IMAGE_WRITE_IMPLEMENTATION | |
#include "stb_image_write.h" | |
#include "out.h" | |
#ifndef NANOSVG_IMPLEMENTATION | |
void nsvgDelete(NSVGimage* image) | |
{ | |
NSVGshape *snext, *shape; | |
if (image == NULL) return; | |
shape = image->shapes; | |
while (shape != NULL) { | |
snext = shape->next; | |
//nsvg__deletePaths(shape->paths); | |
while (shape->paths) { | |
NSVGpath *next = shape->paths->next; | |
if (shape->paths->pts != NULL) { | |
free(shape->paths->pts); | |
} | |
free(shape->paths); | |
shape->paths = next; | |
} | |
//nsvg__deletePaint(&shape->fill); | |
if (shape->fill.type == NSVG_PAINT_LINEAR_GRADIENT || shape->fill.type == NSVG_PAINT_RADIAL_GRADIENT) { | |
free(shape->fill.gradient); | |
} | |
//nsvg__deletePaint(&shape->stroke); | |
if (shape->stroke.type == NSVG_PAINT_LINEAR_GRADIENT || shape->stroke.type == NSVG_PAINT_RADIAL_GRADIENT) { | |
free(shape->stroke.gradient); | |
} | |
free(shape); | |
shape = snext; | |
} | |
free(image); | |
} | |
#endif | |
inline static float get_float(const unsigned char *p) | |
{ | |
float f; | |
memcpy(&f, p, 4); | |
return f; | |
} | |
#define GET_FLOAT(x) x = get_float(p); p+=4; | |
inline static unsigned get_uint(const unsigned char *p) | |
{ | |
unsigned int i; | |
memcpy(&i, p, 4); | |
return i; | |
} | |
#define GET_UINT(x) x = get_uint(p); p+=4; | |
inline static int get_int(const unsigned char *p) | |
{ | |
int i; | |
memcpy(&i, p, 4); | |
return i; | |
} | |
#define GET_INT(x) x = get_int(p); p+=4; | |
#define GET_CHAR(x) x = *p; ++p; | |
int main() | |
{ | |
NSVGrasterizer *rast = NULL; | |
unsigned char* img = NULL; | |
int w, h; | |
NSVGimage *image; | |
NSVGshape *shape, *shapesTail; | |
NSVGpath *path, *pathsTail = NULL; | |
const unsigned char *p = data; | |
float fw, fh; | |
unsigned char has_shape, has_path; | |
GET_FLOAT(fw); | |
GET_FLOAT(fh); | |
GET_CHAR(has_shape); | |
if (has_shape != 0x01) { | |
printf("error: no shapes found!\n"); | |
return 1; | |
} | |
image = (NSVGimage *)calloc(sizeof(NSVGimage), 1); | |
image->width = fw; | |
image->height = fh; | |
image->shapes = NULL; | |
shapesTail = image->shapes; | |
while (has_shape != 0) { | |
shape = (NSVGshape *)calloc(sizeof(NSVGshape), 1); | |
//memcpy(shape->id, p, 64); | |
//p += 64; | |
strcpy(shape->id, (const char *)p); | |
p += strlen(shape->id) + 1; | |
GET_CHAR( shape->fill.type ); | |
GET_UINT( shape->fill.color ); | |
if (shape->fill.color == NSVG_PAINT_LINEAR_GRADIENT || shape->fill.color == NSVG_PAINT_RADIAL_GRADIENT) { | |
shape->fill.gradient = (NSVGgradient *)calloc(sizeof(NSVGgradient), 1); | |
for (int i=0; i < 6; ++i) { | |
GET_FLOAT( shape->fill.gradient->xform[i] ); | |
} | |
GET_CHAR( shape->fill.gradient->spread ); | |
GET_FLOAT( shape->fill.gradient->fx ); | |
GET_FLOAT( shape->fill.gradient->fy ); | |
GET_INT( shape->fill.gradient->nstops ); | |
GET_UINT( shape->fill.gradient->stops[0].color ); | |
GET_FLOAT( shape->fill.gradient->stops[0].offset ); | |
} | |
GET_CHAR( shape->stroke.type ); | |
GET_UINT( shape->stroke.color ); | |
if (shape->stroke.color == NSVG_PAINT_LINEAR_GRADIENT || shape->stroke.color == NSVG_PAINT_RADIAL_GRADIENT) { | |
shape->stroke.gradient = (NSVGgradient *)calloc(sizeof(NSVGgradient), 1); | |
for (int i=0; i < 6; ++i) { | |
GET_FLOAT( shape->stroke.gradient->xform[i] ); | |
} | |
GET_CHAR( shape->stroke.gradient->spread ); | |
GET_FLOAT( shape->stroke.gradient->fx ); | |
GET_FLOAT( shape->stroke.gradient->fy ); | |
GET_INT( shape->stroke.gradient->nstops ); | |
GET_UINT( shape->stroke.gradient->stops[0].color ); | |
GET_FLOAT( shape->stroke.gradient->stops[0].offset ); | |
} | |
GET_FLOAT( shape->opacity ); | |
GET_FLOAT( shape->strokeWidth ); | |
GET_FLOAT( shape->strokeDashOffset ); | |
for (int i=0; i < 8; ++i) { | |
GET_FLOAT( shape->strokeDashArray[i] ); | |
} | |
GET_CHAR( shape->strokeDashCount ); | |
GET_CHAR( shape->strokeLineJoin ); | |
GET_CHAR( shape->strokeLineCap ); | |
GET_FLOAT( shape->miterLimit ); | |
GET_CHAR( shape->fillRule ); | |
GET_CHAR( shape->flags ); | |
for (int i=0; i < 4; ++i) { | |
GET_FLOAT( shape->bounds[i] ); | |
} | |
if (image->shapes == NULL) { | |
image->shapes = shape; | |
} else { | |
shapesTail->next = shape; | |
} | |
shapesTail = shape; | |
GET_CHAR( has_path ); | |
while (has_path != 0) { | |
path = (NSVGpath *)calloc(sizeof(NSVGpath), 1); | |
path->npts = get_int(p); | |
p += 4; | |
path->pts = (float *)malloc(path->npts * 4); | |
for (int i=0; i < path->npts; ++i) { | |
GET_FLOAT( path->pts[i] ); | |
} | |
GET_CHAR( path->closed ); | |
for (int i=0; i < 4; ++i) { | |
GET_FLOAT( path->bounds[i] ); | |
} | |
if (shapesTail->paths == NULL) { | |
shapesTail->paths = path; | |
} else { | |
if (pathsTail == NULL) { | |
pathsTail = path; | |
} else { | |
pathsTail->next = path; | |
} | |
} | |
pathsTail = path; | |
GET_CHAR( has_path ); | |
} | |
GET_CHAR( has_shape ); | |
} | |
printf("parsing from data succeeded\n"); | |
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; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <string.h> | |
#define NANOSVG_IMPLEMENTATION | |
#include "nanosvg.h" | |
void f2hex(float f) | |
{ | |
unsigned char b[4]; | |
memcpy(b, &f, 4); | |
printf("0x%x,0x%x,0x%x,0x%x,", b[0], b[1], b[2], b[3]); | |
} | |
void uint2hex(unsigned int i) | |
{ | |
unsigned char b[4]; | |
memcpy(b, &i, 4); | |
printf("0x%x,0x%x,0x%x,0x%x,", b[0], b[1], b[2], b[3]); | |
} | |
void int2hex(int i) | |
{ | |
unsigned char b[4]; | |
memcpy(b, &i, 4); | |
printf("0x%x,0x%x,0x%x,0x%x,", b[0], b[1], b[2], b[3]); | |
} | |
void print_paint(NSVGpaint p) | |
{ | |
NSVGgradient *g; | |
printf("0x%x,", p.type); | |
uint2hex(p.color); | |
if (p.color == NSVG_PAINT_LINEAR_GRADIENT || p.color == NSVG_PAINT_RADIAL_GRADIENT) { | |
g = p.gradient; | |
for (int i=0; i < 6; ++i) { | |
f2hex(g->xform[i]); | |
} | |
printf("0x%x,", g->spread); | |
f2hex(g->fx); | |
f2hex(g->fy); | |
int2hex(g->nstops); | |
uint2hex(g->stops[0].color); | |
f2hex(g->stops[0].offset); | |
} | |
} | |
int main() | |
{ | |
NSVGimage *image = NULL; | |
NSVGshape *shape = NULL; | |
NSVGpath *path = NULL; | |
const char *filename = "nano.svg"; | |
int i; | |
image = nsvgParseFromFile(filename, "px", 96.0f); | |
if (image == NULL) { | |
printf("Could not open SVG image.\n"); | |
goto error; | |
} | |
printf("unsigned char data[] = {\n"); | |
f2hex(image->width); | |
printf(" // width\n"); | |
f2hex(image->height); | |
printf(" // height\n"); | |
for (shape = image->shapes; shape != NULL; shape = shape->next) { | |
printf("\n\n0x01, // shape\n"); | |
for (i = 0; i < 64; ++i) { | |
if (shape->id[i] == 0 || i == 63) { | |
printf("0x0, // id\n"); | |
break; | |
} | |
printf("0x%x,", shape->id[i]); | |
} | |
print_paint(shape->fill); | |
printf(" // fill\n"); | |
print_paint(shape->stroke); | |
printf(" // stroke\n"); | |
f2hex(shape->opacity); | |
printf(" // opacity\n"); | |
f2hex(shape->strokeWidth); | |
printf(" // strokeWidth\n"); | |
f2hex(shape->strokeDashOffset); | |
printf(" // strokeDashOffset\n"); | |
printf("// strokeDashArray\n"); | |
for (i = 0; i < 8; ++i) { | |
f2hex(shape->strokeDashArray[i]); | |
if ((i+1) % 4 == 0) putchar('\n'); | |
} | |
printf("0x%x, // strokeDashCount\n", shape->strokeDashCount); | |
printf("0x%x, // strokeLineJoin\n", shape->strokeLineJoin); | |
printf("0x%x, // strokeLineCap\n", shape->strokeLineCap); | |
f2hex(shape->miterLimit); | |
printf(" // miterLimit\n"); | |
printf("0x%x, // fillRule\n", shape->fillRule); | |
printf("0x%x, // flags\n", shape->flags); | |
for (i = 0; i < 4; ++i) { | |
f2hex(shape->bounds[i]); | |
} | |
printf(" // bounds\n"); | |
for (path = shape->paths; path != NULL; path = path->next) { | |
printf("\n0x01, // path\n"); | |
int2hex(path->npts); | |
printf(" // npts\n"); | |
if (path->npts > 0) { | |
printf("// pts\n"); | |
for (i = 0; i < path->npts; ++i) { | |
f2hex(path->pts[i]); | |
if ((i+1) % 4 == 0) putchar('\n'); | |
} | |
putchar('\n'); | |
} | |
printf("0x%x, // closed\n", path->closed); | |
for (i = 0; i < 4; ++i) { | |
f2hex(path->bounds[i]); | |
} | |
printf(" // bounds\n"); | |
} | |
printf("\n0x0, // end paths\n"); | |
} | |
printf("\n\n0x0, // end shapes\n"); | |
printf("0x0 // extra byte so we can safely iterate another step\n"); | |
printf("};\n"); | |
error: | |
nsvgDelete(image); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment