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