From 11d28d2d5f37a716602ab4a62b274b16536d72b4 Mon Sep 17 00:00:00 2001 From: Dennis Meinen Date: Wed, 5 Oct 2022 23:09:33 +0200 Subject: [PATCH] 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. --- src/config.h | 1 + src/raylib.h | 4 +-- src/rtextures.c | 86 ++++++++++++++++++++++++++----------------------- 3 files changed, 49 insertions(+), 42 deletions(-) diff --git a/src/config.h b/src/config.h index a7ec2523f..39d0b0f89 100644 --- a/src/config.h +++ b/src/config.h @@ -152,6 +152,7 @@ //#define SUPPORT_FILEFORMAT_ASTC 1 //#define SUPPORT_FILEFORMAT_PKM 1 //#define SUPPORT_FILEFORMAT_PVR 1 +#define SUPPORT_FILEFORMAT_SVG 1 // Support image export functionality (.png, .bmp, .tga, .jpg, .qoi) #define SUPPORT_IMAGE_EXPORT 1 diff --git a/src/raylib.h b/src/raylib.h index 08d46d022..9bbb8874b 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1226,8 +1226,8 @@ RLAPI Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2); // NOTE: This functions do not require GPU access RLAPI Image LoadImage(const char *fileName); // Load image from file into CPU memory (RAM) RLAPI Image LoadImageRaw(const char *fileName, int width, int height, int format, int headerSize); // Load image from RAW file data -RLAPI Image LoadImageSvg(const char* fileName); // Load image from SVG file data with default size from SVG -RLAPI Image LoadImageSvgWithSize(const char* fileName, int width, int height); // Load image from SVG file data with specified size +RLAPI Image LoadImageSvg(const char *fileName, int width, int height); // Load image from SVG file data with specified size +RLAPI Image LoadImageSvgFromString(const char *string, int width, int height); // Load an image from a SVG string with custom size RLAPI Image LoadImageAnim(const char *fileName, int *frames); // Load image sequence from file (frames appended to image.data) RLAPI Image LoadImageFromMemory(const char *fileType, const unsigned char *fileData, int dataSize); // Load image from memory buffer, fileType refers to extension: i.e. '.png' RLAPI Image LoadImageFromTexture(Texture2D texture); // Load image from GPU texture data diff --git a/src/rtextures.c b/src/rtextures.c index 8befa5b9e..b481af62b 100644 --- a/src/rtextures.c +++ b/src/rtextures.c @@ -187,12 +187,13 @@ #include "external/stb_image_resize.h" // Required for: stbir_resize_uint8() [ImageResize()] #endif -#define NANOSVG_IMPLEMENTATION // Expands implementation -#include "external/nanosvg.h" - -#define NANOSVGRAST_IMPLEMENTATION -#include "external/nanosvgrast.h" +#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 @@ -282,70 +283,57 @@ Image LoadImageRaw(const char *fileName, int width, int height, int format, int return image; } -// Load image from SVG file data with default size from SVG -Image LoadImageSvg(const char* fileName) +// 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* fileData = LoadFileData(fileName, &dataSize); + unsigned char *string = LoadFileData(fileName, &dataSize); - if (fileData != NULL) + if (string != NULL) { - struct NSVGimage* svgImage = nsvgParse(fileData, "px", 96.0f); - - const int width = (int)svgImage->width; - const int height = (int)svgImage->height; - // Delete - nsvgDelete(svgImage); - - return LoadImageSvgWithSize(fileName, width, height); + image = LoadImageSvgFromString(string, width, height); + RL_FREE(string); } - return image; } -// Load an image from SVG file data with a custom size -Image LoadImageSvgWithSize(const char* fileName, int width, int height) +// Load an image from a SVG string with custom size +Image LoadImageSvgFromString(const char *string, int width, int height) { Image image = { 0 }; - unsigned int dataSize = 0; - unsigned char* fileData = LoadFileData(fileName, &dataSize); - - if (fileData != NULL) + if (string != NULL) { - struct NSVGimage* svgImage = nsvgParse(fileData, "px", 96.0f); - - + struct NSVGimage *svgImage = nsvgParse(string, "px", 96.0f); // Allocate memory for image - unsigned char* img = malloc(width * height * 4); + 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; + 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; + const float scale = (scaleHeight > scaleWidth) ? scaleWidth : scaleHeight; int offsetX = 0; int offsetY = 0; if (scaleHeight > scaleWidth) { - offsetY = (height - svgImage->height * scale) / 2; + offsetY = (height - svgImage->height*scale) / 2; } - else + else { - offsetX = (width - svgImage->width * scale) / 2; + offsetX = (width - svgImage->width*scale) / 2; } - - // Rasterize + // Rasterize struct NSVGrasterizer* rast = nsvgCreateRasterizer(); - nsvgRasterize(rast, svgImage, (int)offsetX, (int)offsetY, scale, img, width, height, width * 4); + nsvgRasterize(rast, svgImage, (int)offsetX, (int)offsetY, scale, img, width, height, width*4); // Populate image struct with all data image.data = img; @@ -354,16 +342,13 @@ Image LoadImageSvgWithSize(const char* fileName, int width, int height) image.mipmaps = 1; image.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8; - // Delete nsvgDelete(svgImage); - RL_FREE(fileData); } 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 @@ -517,6 +502,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");