mirror of
				https://github.com/raysan5/raylib.git
				synced 2025-10-26 12:27:01 +00:00 
			
		
		
		
	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 <raysan5@gmail.com>
This commit is contained in:
		| @@ -475,7 +475,8 @@ TEXTURES = \ | |||||||
|     textures/textures_draw_tiled \ |     textures/textures_draw_tiled \ | ||||||
|     textures/textures_polygon \ |     textures/textures_polygon \ | ||||||
|     textures/textures_gif_player \ |     textures/textures_gif_player \ | ||||||
|     textures/textures_fog_of_war |     textures/textures_fog_of_war \ | ||||||
|  |     textures/textures_svg_loading | ||||||
|  |  | ||||||
| TEXT = \ | TEXT = \ | ||||||
|     text/text_raylib_fonts \ |     text/text_raylib_fonts \ | ||||||
|   | |||||||
| @@ -450,7 +450,8 @@ TEXTURES = \ | |||||||
|     textures/textures_draw_tiled \ |     textures/textures_draw_tiled \ | ||||||
|     textures/textures_polygon \ |     textures/textures_polygon \ | ||||||
|     textures/textures_gif_player \ |     textures/textures_gif_player \ | ||||||
|     textures/textures_fog_of_war |     textures/textures_fog_of_war \ | ||||||
|  |     textures/textures_svg_loading | ||||||
|  |  | ||||||
| TEXT = \ | TEXT = \ | ||||||
|     text/text_raylib_fonts \ |     text/text_raylib_fonts \ | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								examples/textures/resources/test.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								examples/textures/resources/test.svg
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| After Width: | Height: | Size: 5.6 KiB | 
							
								
								
									
										72
									
								
								examples/textures/textures_svg_loading.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								examples/textures/textures_svg_loading.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,72 @@ | |||||||
|  | /******************************************************************************************* | ||||||
|  | * | ||||||
|  | *   raylib [textures] example - SVG loading and texture creation | ||||||
|  | * | ||||||
|  | *   NOTE: Images are loaded in CPU memory (RAM); textures are loaded in GPU memory (VRAM) | ||||||
|  | * | ||||||
|  | *   Example originally created with raylib 4.2, last time updated with raylib 4.2 | ||||||
|  | * | ||||||
|  | *   Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, | ||||||
|  | *   BSD-like license that allows static linking with closed source software | ||||||
|  | * | ||||||
|  | *   Copyright (c) 2022 Dennis Meinen (@bixxy#4258 on Discord) | ||||||
|  | * | ||||||
|  | ********************************************************************************************/ | ||||||
|  |  | ||||||
|  | #include "raylib.h" | ||||||
|  |  | ||||||
|  | //------------------------------------------------------------------------------------ | ||||||
|  | // Program main entry point | ||||||
|  | //------------------------------------------------------------------------------------ | ||||||
|  | int main(void) | ||||||
|  | { | ||||||
|  |     // Initialization | ||||||
|  |     //-------------------------------------------------------------------------------------- | ||||||
|  |     const int screenWidth = 800; | ||||||
|  |     const int screenHeight = 450; | ||||||
|  |  | ||||||
|  |     InitWindow(screenWidth, screenHeight, "raylib [textures] example - svg loading"); | ||||||
|  |  | ||||||
|  |     // NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required) | ||||||
|  |  | ||||||
|  |     Image image = LoadImageSvg("resources/test.svg", 400, 350);     // Loaded in CPU memory (RAM) | ||||||
|  |     Texture2D texture = LoadTextureFromImage(image);          // Image converted to texture, GPU memory (VRAM) | ||||||
|  |     UnloadImage(image);   // Once image has been converted to texture and uploaded to VRAM, it can be unloaded from RAM | ||||||
|  |  | ||||||
|  |     SetTargetFPS(60);     // Set our game to run at 60 frames-per-second | ||||||
|  |     //--------------------------------------------------------------------------------------- | ||||||
|  |  | ||||||
|  |     // Main game loop | ||||||
|  |     while (!WindowShouldClose())    // Detect window close button or ESC key | ||||||
|  |     { | ||||||
|  |         // Update | ||||||
|  |         //---------------------------------------------------------------------------------- | ||||||
|  |         // TODO: Update your variables here | ||||||
|  |         //---------------------------------------------------------------------------------- | ||||||
|  |  | ||||||
|  |         // Draw | ||||||
|  |         //---------------------------------------------------------------------------------- | ||||||
|  |         BeginDrawing(); | ||||||
|  |  | ||||||
|  |             ClearBackground(RAYWHITE); | ||||||
|  |  | ||||||
|  |             DrawTexture(texture, screenWidth/2 - texture.width/2, screenHeight/2 - texture.height/2, WHITE); | ||||||
|  |  | ||||||
|  |             //Red border to illustrate how the SVG is centered within the specified dimensions | ||||||
|  |             DrawRectangleLines((screenWidth / 2 - texture.width / 2) - 1, (screenHeight / 2 - texture.height / 2) - 1, texture.width + 2, texture.height + 2, RED); | ||||||
|  |  | ||||||
|  |             DrawText("this IS a texture loaded from an SVG file!", 300, 410, 10, GRAY); | ||||||
|  |  | ||||||
|  |         EndDrawing(); | ||||||
|  |         //---------------------------------------------------------------------------------- | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // De-Initialization | ||||||
|  |     //-------------------------------------------------------------------------------------- | ||||||
|  |     UnloadTexture(texture);       // Texture unloading | ||||||
|  |  | ||||||
|  |     CloseWindow();                // Close window and OpenGL context | ||||||
|  |     //-------------------------------------------------------------------------------------- | ||||||
|  |  | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
							
								
								
									
										
											BIN
										
									
								
								examples/textures/textures_svg_loading.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								examples/textures/textures_svg_loading.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 14 KiB | 
| @@ -141,7 +141,7 @@ | |||||||
| //------------------------------------------------------------------------------------ | //------------------------------------------------------------------------------------ | ||||||
| // Module: rtextures - Configuration Flags | // Module: rtextures - Configuration Flags | ||||||
| //------------------------------------------------------------------------------------ | //------------------------------------------------------------------------------------ | ||||||
| // Select the desired fileformats to be supported for image data loading | // Selecte desired fileformats to be supported for image data loading | ||||||
| #define SUPPORT_FILEFORMAT_PNG      1 | #define SUPPORT_FILEFORMAT_PNG      1 | ||||||
| //#define SUPPORT_FILEFORMAT_BMP      1 | //#define SUPPORT_FILEFORMAT_BMP      1 | ||||||
| //#define SUPPORT_FILEFORMAT_TGA      1 | //#define SUPPORT_FILEFORMAT_TGA      1 | ||||||
| @@ -150,13 +150,13 @@ | |||||||
| #define SUPPORT_FILEFORMAT_QOI      1 | #define SUPPORT_FILEFORMAT_QOI      1 | ||||||
| //#define SUPPORT_FILEFORMAT_PSD      1 | //#define SUPPORT_FILEFORMAT_PSD      1 | ||||||
| #define SUPPORT_FILEFORMAT_DDS      1 | #define SUPPORT_FILEFORMAT_DDS      1 | ||||||
| #define SUPPORT_FILEFORMAT_HDR          1 | //#define SUPPORT_FILEFORMAT_HDR      1 | ||||||
| //#define SUPPORT_FILEFORMAT_PIC          1 | //#define SUPPORT_FILEFORMAT_PIC          1 | ||||||
| //#define SUPPORT_FILEFORMAT_PNM          1 |  | ||||||
| //#define SUPPORT_FILEFORMAT_KTX      1 | //#define SUPPORT_FILEFORMAT_KTX      1 | ||||||
| //#define SUPPORT_FILEFORMAT_ASTC     1 | //#define SUPPORT_FILEFORMAT_ASTC     1 | ||||||
| //#define SUPPORT_FILEFORMAT_PKM      1 | //#define SUPPORT_FILEFORMAT_PKM      1 | ||||||
| //#define SUPPORT_FILEFORMAT_PVR      1 | //#define SUPPORT_FILEFORMAT_PVR      1 | ||||||
|  | #define SUPPORT_FILEFORMAT_SVG      1 | ||||||
|  |  | ||||||
| // Support image export functionality (.png, .bmp, .tga, .jpg, .qoi) | // Support image export functionality (.png, .bmp, .tga, .jpg, .qoi) | ||||||
| #define SUPPORT_IMAGE_EXPORT            1 | #define SUPPORT_IMAGE_EXPORT            1 | ||||||
|   | |||||||
							
								
								
									
										3053
									
								
								src/external/nanosvg.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3053
									
								
								src/external/nanosvg.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1458
									
								
								src/external/nanosvgrast.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1458
									
								
								src/external/nanosvgrast.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1245,6 +1245,8 @@ RLAPI Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2); | |||||||
| // NOTE: These functions do not require GPU access | // NOTE: These functions do not require GPU access | ||||||
| RLAPI Image LoadImage(const char *fileName);                                                             // Load image from file into CPU memory (RAM) | 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 LoadImageRaw(const char *fileName, int width, int height, int format, int headerSize);       // Load image from RAW file data | ||||||
|  | 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 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 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 | RLAPI Image LoadImageFromTexture(Texture2D texture);                                                     // Load image from GPU texture data | ||||||
|   | |||||||
| @@ -215,6 +215,14 @@ | |||||||
| #define STB_IMAGE_RESIZE_IMPLEMENTATION | #define STB_IMAGE_RESIZE_IMPLEMENTATION | ||||||
| #include "external/stb_image_resize.h"  // Required for: stbir_resize_uint8() [ImageResize()] | #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 | // Defines and Macros | ||||||
| //---------------------------------------------------------------------------------- | //---------------------------------------------------------------------------------- | ||||||
| @@ -310,6 +318,72 @@ Image LoadImageRaw(const char *fileName, int width, int height, int format, int | |||||||
|     return image; |     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 | // Load animated image data | ||||||
| //  - Image.data buffer includes all frames: [image#0][image#1][image#2][...] | //  - Image.data buffer includes all frames: [image#0][image#1][image#2][...] | ||||||
| //  - Number of frames is returned through 'frames' parameter | //  - Number of frames is returned through 'frames' parameter | ||||||
| @@ -470,6 +544,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); |         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 | #endif | ||||||
|     else TRACELOG(LOG_WARNING, "IMAGE: Data format not supported"); |     else TRACELOG(LOG_WARNING, "IMAGE: Data format not supported"); | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 bXi
					bXi