#include <SDL3_image/SDL_image.h>
#ifdef LOAD_SVG
#define free SDL_free
#define malloc SDL_malloc
#undef memcpy
#define memcpy SDL_memcpy
#undef memset
#define memset SDL_memset
#define qsort SDL_qsort
#define realloc SDL_realloc
#define sscanf SDL_sscanf
#undef strchr
#define strchr SDL_strchr
#undef strcmp
#define strcmp SDL_strcmp
#undef strncmp
#define strncmp SDL_strncmp
#undef strncpy
#define strncpy SDL_strlcpy
#define strlen SDL_strlen
#define strstr SDL_strstr
#define strtol SDL_strtol
#define strtoll SDL_strtoll
#define acosf SDL_acosf
#define atan2f SDL_atan2f
#define cosf SDL_cosf
#define ceilf SDL_ceilf
#define fabs SDL_fabs
#define fabsf SDL_fabsf
#define floorf SDL_floorf
#define fmodf SDL_fmodf
#define pow SDL_pow
#define sinf SDL_sinf
#define sqrt SDL_sqrt
#define sqrtf SDL_sqrtf
#define tanf SDL_tanf
#define roundf SDL_roundf
#undef isnan
#define isnan SDL_isnanf
#ifndef FLT_MAX
#define FLT_MAX 3.402823466e+38F
#endif
#undef HAVE_STDIO_H
#define NSVG_EXPORT static
#define NANOSVG_IMPLEMENTATION
#include "nanosvg.h"
#define NANOSVGRAST_IMPLEMENTATION
#include "nanosvgrast.h"
bool IMG_isSVG(SDL_IOStream *src)
{
Sint64 start;
bool is_SVG;
char magic[4096];
size_t magic_len;
if (!src) {
return false;
}
start = SDL_TellIO(src);
is_SVG = false;
magic_len = SDL_ReadIO(src, magic, sizeof(magic) - 1);
if (magic_len > 0) {
magic[magic_len] = '\0';
if (SDL_strstr(magic, "<svg")) {
is_SVG = true;
}
}
SDL_SeekIO(src, start, SDL_IO_SEEK_SET);
return is_SVG;
}
SDL_Surface *IMG_LoadSizedSVG_IO(SDL_IOStream *src, int width, int height)
{
char *data;
struct NSVGimage *image;
struct NSVGrasterizer *rasterizer;
SDL_Surface *surface = NULL;
float scale = 1.0f;
data = (char *)SDL_LoadFile_IO(src, NULL, false);
if (!data) {
return NULL;
}
image = nsvgParse(data, "px", 96.0f);
SDL_free(data);
if (!image || image->width <= 0.0f || image->height <= 0.0f) {
SDL_SetError("Couldn't parse SVG image");
return NULL;
}
rasterizer = nsvgCreateRasterizer();
if (!rasterizer) {
SDL_SetError("Couldn't create SVG rasterizer");
nsvgDelete(image);
return NULL;
}
if (width > 0 && height > 0) {
float scale_x = (float)width / image->width;
float scale_y = (float)height / image->height;
scale = SDL_min(scale_x, scale_y);
} else if (width > 0) {
scale = (float)width / image->width;
} else if (height > 0) {
scale = (float)height / image->height;
} else {
scale = 1.0f;
}
surface = SDL_CreateSurface((int)SDL_ceilf(image->width * scale),
(int)SDL_ceilf(image->height * scale),
SDL_PIXELFORMAT_RGBA32);
if (!surface) {
nsvgDeleteRasterizer(rasterizer);
nsvgDelete(image);
return NULL;
}
nsvgRasterize(rasterizer, image, 0.0f, 0.0f, scale, (unsigned char *)surface->pixels, surface->w, surface->h, surface->pitch);
nsvgDeleteRasterizer(rasterizer);
nsvgDelete(image);
return surface;
}
#else
bool IMG_isSVG(SDL_IOStream *src)
{
return false;
}
SDL_Surface *IMG_LoadSizedSVG_IO(SDL_IOStream *src, int width, int height)
{
SDL_SetError("SDL_image built without SVG support");
return NULL;
}
#endif
SDL_Surface *IMG_LoadSVG_IO(SDL_IOStream *src)
{
return IMG_LoadSizedSVG_IO(src, 0, 0);
}