1 /*
2 SDL_image: An example image loading library for use with SDL
3 Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20 */
21
22 /* This is an SVG image file loading framework, based on Nano SVG:
23 * https://github.com/memononen/nanosvg
24 */
25
26 #include "SDL_image.h"
27
28 #ifdef LOAD_SVG
29
30 /* Replace C runtime functions with SDL C runtime functions for building on Windows */
31 #define acosf SDL_acosf
32 #define atan2f SDL_atan2f
33 #define cosf SDL_cosf
34 #define ceilf SDL_ceilf
35 #define fabs SDL_fabs
36 #define fabsf SDL_fabsf
37 #define floorf SDL_floorf
38 #define fmodf SDL_fmodf
39 #define free SDL_free
40 #define malloc SDL_malloc
41 #undef memcpy
42 #define memcpy SDL_memcpy
43 #undef memset
44 #define memset SDL_memset
45 #define pow SDL_pow
46 #define qsort SDL_qsort
47 #define realloc SDL_realloc
48 #define sinf SDL_sinf
49 #define sqrt SDL_sqrt
50 #define sqrtf SDL_sqrtf
51 #define sscanf SDL_sscanf
52 #undef strchr
53 #define strchr SDL_strchr
54 #undef strcmp
55 #define strcmp SDL_strcmp
56 #undef strncmp
57 #define strncmp SDL_strncmp
58 #undef strncpy
59 #define strncpy SDL_strlcpy
60 #define strlen SDL_strlen
61 #define strstr SDL_strstr
62 #define strtol SDL_strtol
63 #define strtoll SDL_strtoll
64 #define tanf SDL_tanf
65 #ifndef FLT_MAX
66 #define FLT_MAX 3.402823466e+38F
67 #endif
68 #undef HAVE_STDIO_H
69
70 #define NANOSVG_IMPLEMENTATION
71 #include "nanosvg.h"
72 #define NANOSVGRAST_IMPLEMENTATION
73 #include "nanosvgrast.h"
74
75 /* See if an image is contained in a data source */
IMG_isSVG(SDL_RWops * src)76 int IMG_isSVG(SDL_RWops *src)
77 {
78 Sint64 start;
79 int is_SVG;
80 char magic[4096];
81 size_t magic_len;
82
83 if ( !src )
84 return 0;
85 start = SDL_RWtell(src);
86 is_SVG = 0;
87 magic_len = SDL_RWread(src, magic, 1, sizeof(magic) - 1);
88 magic[magic_len] = '\0';
89 if ( SDL_strstr(magic, "<svg") ) {
90 is_SVG = 1;
91 }
92 SDL_RWseek(src, start, RW_SEEK_SET);
93 return(is_SVG);
94 }
95
96 /* Load a SVG type image from an SDL datasource */
IMG_LoadSVG_RW(SDL_RWops * src)97 SDL_Surface *IMG_LoadSVG_RW(SDL_RWops *src)
98 {
99 char *data;
100 struct NSVGimage *image;
101 struct NSVGrasterizer *rasterizer;
102 SDL_Surface *surface = NULL;
103 float scale = 1.0f;
104
105 data = (char *)SDL_LoadFile_RW(src, NULL, SDL_FALSE);
106 if ( !data ) {
107 return NULL;
108 }
109
110 /* For now just use default units of pixels at 96 DPI */
111 image = nsvgParse(data, "px", 96.0f);
112 SDL_free(data);
113 if ( !image ) {
114 IMG_SetError("Couldn't parse SVG image");
115 return NULL;
116 }
117
118 rasterizer = nsvgCreateRasterizer();
119 if ( !rasterizer ) {
120 IMG_SetError("Couldn't create SVG rasterizer");
121 nsvgDelete( image );
122 return NULL;
123 }
124
125 surface = SDL_CreateRGBSurface(SDL_SWSURFACE,
126 (int)(image->width * scale),
127 (int)(image->height * scale),
128 32,
129 0x000000FF,
130 0x0000FF00,
131 0x00FF0000,
132 0xFF000000);
133 if ( !surface ) {
134 nsvgDeleteRasterizer( rasterizer );
135 nsvgDelete( image );
136 return NULL;
137 }
138
139 nsvgRasterize(rasterizer, image, 0.0f, 0.0f, scale, (unsigned char *)surface->pixels, surface->w, surface->h, surface->pitch);
140 nsvgDeleteRasterizer( rasterizer );
141 nsvgDelete( image );
142
143 return surface;
144 }
145
146 #else
147
148 /* See if an image is contained in a data source */
IMG_isSVG(SDL_RWops * src)149 int IMG_isSVG(SDL_RWops *src)
150 {
151 return(0);
152 }
153
154 /* Load a SVG type image from an SDL datasource */
IMG_LoadSVG_RW(SDL_RWops * src)155 SDL_Surface *IMG_LoadSVG_RW(SDL_RWops *src)
156 {
157 return(NULL);
158 }
159
160 #endif /* LOAD_SVG */
161