From c32a8775a01fb05973f7b3fdb479194935df2e54 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Mon, 16 May 2022 09:30:21 -0700
Subject: [PATCH] Added IMG_LoadSizedSVG_RW()
Fixes https://github.com/libsdl-org/SDL_image/issues/125
---
CHANGES.txt | 2 ++
IMG_svg.c | 50 +++++++++++++++++++++++++++++++++++---------------
SDL_image.h | 5 +++++
3 files changed, 42 insertions(+), 15 deletions(-)
diff --git a/CHANGES.txt b/CHANGES.txt
index 6813723d..2f4761fc 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,6 @@
2.0.6:
+Sam Lantinga - Mon May 16 09:30:10 PDT 2022
+ * Added IMG_LoadSizedSVG_RW()
Sam Lantinga - Mon May 9 12:42:05 PDT 2022
* Added support for AVIF images (https://github.com/AOMediaCodec/libavif)
Sylvain Becker - Sun May 8 21:59:27 PDT 2022
diff --git a/IMG_svg.c b/IMG_svg.c
index f0b135fa..77798727 100644
--- a/IMG_svg.c
+++ b/IMG_svg.c
@@ -95,13 +95,13 @@ int IMG_isSVG(SDL_RWops *src)
char magic[4096];
size_t magic_len;
- if ( !src )
+ if (!src)
return 0;
start = SDL_RWtell(src);
is_SVG = 0;
magic_len = SDL_RWread(src, magic, 1, sizeof(magic) - 1);
magic[magic_len] = '\0';
- if ( SDL_strstr(magic, "<svg") ) {
+ if (SDL_strstr(magic, "<svg")) {
is_SVG = 1;
}
SDL_RWseek(src, start, RW_SEEK_SET);
@@ -109,7 +109,7 @@ int IMG_isSVG(SDL_RWops *src)
}
/* Load a SVG type image from an SDL datasource */
-SDL_Surface *IMG_LoadSVG_RW(SDL_RWops *src)
+SDL_Surface *IMG_LoadSizedSVG_RW(SDL_RWops *src, int width, int height)
{
char *data;
struct NSVGimage *image;
@@ -118,42 +118,55 @@ SDL_Surface *IMG_LoadSVG_RW(SDL_RWops *src)
float scale = 1.0f;
data = (char *)SDL_LoadFile_RW(src, NULL, SDL_FALSE);
- if ( !data ) {
+ if (!data) {
return NULL;
}
/* For now just use default units of pixels at 96 DPI */
image = nsvgParse(data, "px", 96.0f);
SDL_free(data);
- if ( !image ) {
+ if (!image || image->width <= 0.0f || image->height <= 0.0f) {
IMG_SetError("Couldn't parse SVG image");
return NULL;
}
rasterizer = nsvgCreateRasterizer();
- if ( !rasterizer ) {
+ if (!rasterizer) {
IMG_SetError("Couldn't create SVG rasterizer");
- nsvgDelete( image );
+ 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_CreateRGBSurface(SDL_SWSURFACE,
- (int)(image->width * scale),
- (int)(image->height * scale),
+ (int)SDL_ceilf(image->width * scale),
+ (int)SDL_ceilf(image->height * scale),
32,
0x000000FF,
0x0000FF00,
0x00FF0000,
0xFF000000);
- if ( !surface ) {
- nsvgDeleteRasterizer( rasterizer );
- nsvgDelete( image );
+ 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 );
+ nsvgDeleteRasterizer(rasterizer);
+ nsvgDelete(image);
return surface;
}
@@ -170,9 +183,16 @@ int IMG_isSVG(SDL_RWops *src)
}
/* Load a SVG type image from an SDL datasource */
-SDL_Surface *IMG_LoadSVG_RW(SDL_RWops *src)
+SDL_Surface *IMG_LoadSizedSVG_RW(SDL_RWops *src, int width, int height)
{
return(NULL);
}
#endif /* LOAD_SVG */
+
+/* Load a SVG type image from an SDL datasource */
+SDL_Surface *IMG_LoadSVG_RW(SDL_RWops *src)
+{
+ return IMG_LoadSizedSVG_RW(src, 0, 0);
+}
+
diff --git a/SDL_image.h b/SDL_image.h
index 3808cf51..d749ab84 100644
--- a/SDL_image.h
+++ b/SDL_image.h
@@ -158,6 +158,11 @@ extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadXPM_RW(SDL_RWops *src);
extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadXV_RW(SDL_RWops *src);
extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadWEBP_RW(SDL_RWops *src);
+/* Load an SVG scaled to a specific size
+ Either width or height may be 0 and will be auto-sized to preserve aspect ratio.
+ */
+extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadSizedSVG_RW(SDL_RWops *src, int width, int height);
+
extern DECLSPEC SDL_Surface * SDLCALL IMG_ReadXPMFromArray(char **xpm);
extern DECLSPEC SDL_Surface * SDLCALL IMG_ReadXPMFromArrayToRGB888(char **xpm);