Skip to content

Instantly share code, notes, and snippets.

@darealshinji
Created January 23, 2021 14:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save darealshinji/e30847aa20ac428b68a1f5ad3e0dd7f8 to your computer and use it in GitHub Desktop.
Save darealshinji/e30847aa20ac428b68a1f5ad3e0dd7f8 to your computer and use it in GitHub Desktop.
#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;
}
#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