diff options
| author | bXi <[email protected]> | 2023-09-02 07:00:18 -0400 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-09-02 13:00:18 +0200 |
| commit | c03ab03627232047c63b11c27567ef3d0a74ca3c (patch) | |
| tree | fe6510daa26e00a6702812a1cd5890cb68130227 /src/rtextures.c | |
| parent | 75e5cd86d7d1c4c6e0f266f3ae68f3af34fa78ac (diff) | |
| download | raylib-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.c | 95 |
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); |
