summaryrefslogtreecommitdiffhomepage
path: root/src/rtextures.c
diff options
context:
space:
mode:
authorbXi <[email protected]>2023-09-02 07:00:18 -0400
committerGitHub <[email protected]>2023-09-02 13:00:18 +0200
commitc03ab03627232047c63b11c27567ef3d0a74ca3c (patch)
treefe6510daa26e00a6702812a1cd5890cb68130227 /src/rtextures.c
parent75e5cd86d7d1c4c6e0f266f3ae68f3af34fa78ac (diff)
downloadraylib-c03ab03627232047c63b11c27567ef3d0a74ca3c.tar.gz
raylib-c03ab03627232047c63b11c27567ef3d0a74ca3c.zip
Added rudimentary SVG support. (#2738)
* Added rudimentary SVG support. Added 2 functions ImageLoadSvg and ImageLoadSvgWithSize. * Added an example on how to use ImageLoadSvgWithSize and adjusted Makefiles accordingly. * Added actual correct example file. * Reviewed the code to keep the raylib coding conventions in mind. Moved the LoadImageSvg() code into LoadImage() guarded by SUPPORT_FILEFORMAT_SVG. Renamed LoadImageSvgWithSize() to LoadImageSvg(). Added a LoadImageSvgFromString() function to parse the loaded SVG into an actual image. This does the bulk of the work. * Fixed typo. --------- Co-authored-by: Ray <[email protected]>
Diffstat (limited to 'src/rtextures.c')
-rw-r--r--src/rtextures.c95
1 files changed, 95 insertions, 0 deletions
diff --git a/src/rtextures.c b/src/rtextures.c
index 56637111..09202ef7 100644
--- a/src/rtextures.c
+++ b/src/rtextures.c
@@ -215,6 +215,14 @@
#define STB_IMAGE_RESIZE_IMPLEMENTATION
#include "external/stb_image_resize.h" // Required for: stbir_resize_uint8() [ImageResize()]
+#if defined(SUPPORT_FILEFORMAT_SVG)
+ #define NANOSVG_IMPLEMENTATION // Expands implementation
+ #include "external/nanosvg.h"
+
+ #define NANOSVGRAST_IMPLEMENTATION
+ #include "external/nanosvgrast.h"
+#endif
+
//----------------------------------------------------------------------------------
// Defines and Macros
//----------------------------------------------------------------------------------
@@ -310,6 +318,72 @@ Image LoadImageRaw(const char *fileName, int width, int height, int format, int
return image;
}
+// Load an image from SVG file data with a custom size
+Image LoadImageSvg(const char *fileName, int width, int height)
+{
+ Image image = { 0 };
+
+ unsigned int dataSize = 0;
+ unsigned char *string = LoadFileData(fileName, &dataSize);
+
+ if (string != NULL)
+ {
+ image = LoadImageSvgFromString(string, width, height);
+ RL_FREE(string);
+ }
+
+ return image;
+}
+
+// Load an image from a SVG string with custom size
+Image LoadImageSvgFromString(const char *string, int width, int height)
+{
+ Image image = { 0 };
+
+ if (string != NULL)
+ {
+ struct NSVGimage *svgImage = nsvgParse(string, "px", 96.0f);
+
+ // Allocate memory for image
+ unsigned char *img = malloc(width*height*4);
+
+ // Calculate scales for both the width and the height
+ const float scaleWidth = width/svgImage->width;
+ const float scaleHeight = height/svgImage->height;
+
+ // Set the largest of the 2 scales to be the scale to use
+ const float scale = (scaleHeight > scaleWidth) ? scaleWidth : scaleHeight;
+
+ int offsetX = 0;
+ int offsetY = 0;
+
+ if (scaleHeight > scaleWidth)
+ {
+ offsetY = (height - svgImage->height*scale) / 2;
+ }
+ else
+ {
+ offsetX = (width - svgImage->width*scale) / 2;
+ }
+
+ // Rasterize
+ struct NSVGrasterizer* rast = nsvgCreateRasterizer();
+ nsvgRasterize(rast, svgImage, (int)offsetX, (int)offsetY, scale, img, width, height, width*4);
+
+ // Populate image struct with all data
+ image.data = img;
+ image.width = width;
+ image.height = height;
+ image.mipmaps = 1;
+ image.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
+
+ // Delete
+ nsvgDelete(svgImage);
+ }
+
+ return image;
+}
+
// Load animated image data
// - Image.data buffer includes all frames: [image#0][image#1][image#2][...]
// - Number of frames is returned through 'frames' parameter
@@ -471,6 +545,27 @@ Image LoadImageFromMemory(const char *fileType, const unsigned char *fileData, i
image.data = rl_load_astc_from_memory(fileData, dataSize, &image.width, &image.height, &image.format, &image.mipmaps);
}
#endif
+#if defined(SUPPORT_FILEFORMAT_SVG)
+ else if (strcmp(fileType, ".svg") == 0)
+ {
+ if (fileData != NULL)
+ {
+ // Creating a duplicate svg to read sizes from due to nsvgParse modifiying the string buffer.
+ unsigned char *duplicate = (unsigned char*)RL_MALLOC(dataSize);
+ memcpy(duplicate, fileData, dataSize);
+ struct NSVGimage *svgImage = nsvgParse(duplicate, "px", 96.0f);
+ RL_FREE(duplicate);
+
+ const int width = (int)svgImage->width;
+ const int height = (int)svgImage->height;
+ // Delete
+ nsvgDelete(svgImage);
+
+
+ image = LoadImageSvgFromString(fileData, width, height);
+ }
+ }
+#endif
else TRACELOG(LOG_WARNING, "IMAGE: Data format not supported");
if (image.data != NULL) TRACELOG(LOG_INFO, "IMAGE: Data loaded successfully (%ix%i | %s | %i mipmaps)", image.width, image.height, rlGetPixelFormatName(image.format), image.mipmaps);