# SDL\_image: nanosvg: sync with mainstream:

**URL:** <https://discourse.libsdl.org/t/sdl-image-nanosvg-sync-with-mainstream/36581>\
**Category:** SDL Commits\
**Created:** [May 27, 2022, 2:52pm UTC](https://discourse.libsdl.org/t/sdl-image-nanosvg-sync-with-mainstream/36581 "2022-05-27T14:52:02Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![SDLPushPostBot](https://discourse.libsdl.org/user_avatar/discourse.libsdl.org/sdlpushpostbot/32/4370_2.png) [@SDLPushPostBot](https://discourse.libsdl.org/u/SDLPushPostBot)\
**Post date:** [May 27, 2022, 2:52pm UTC](https://discourse.libsdl.org/t/sdl-image-nanosvg-sync-with-mainstream/36581/1 "2022-05-27T14:52:02Z")

</div>

> <https://github.com/libsdl-org/SDL_image/commit/acfe4770cdcddf37457f90980e55fe658773a070>
>
> This imports the following four commits from mainstream nanosvg:
> https://github.…com/memononen/nanosvg/commit/3cdd4a9d788695699799b37d492e45e2c3625790
> https://github.com/memononen/nanosvg/commit/ccdb1995134d340a93fb20e3a3d323ccb3838dd0
> https://github.com/memononen/nanosvg/commit/214cf85efcdc67524335ad0e2a2d5982246b6a72
> https://github.com/memononen/nanosvg/commit/3bcdf2f3cdc1bf9197c2dce81368bfc6f99205a7
> 
> This adds roundf() as a new dependency: Since SDL\_roundf() requires
> SDL \>= 2.0.16, invented a tiny local SDLIMAGE\_roundf() function for
> it instead.

```diff
From acfe4770cdcddf37457f90980e55fe658773a070 Mon Sep 17 00:00:00 2001
From: Ozkan Sezer <[EMAIL REDACTED]>
Date: Fri, 27 May 2022 17:29:50 +0300
Subject: [PATCH] nanosvg: sync with mainstream:

This imports the following four commits from mainstream nanosvg:
https://github.com/memononen/nanosvg/commit/3cdd4a9d788695699799b37d492e45e2c3625790
https://github.com/memononen/nanosvg/commit/ccdb1995134d340a93fb20e3a3d323ccb3838dd0
https://github.com/memononen/nanosvg/commit/214cf85efcdc67524335ad0e2a2d5982246b6a72
https://github.com/memononen/nanosvg/commit/3bcdf2f3cdc1bf9197c2dce81368bfc6f99205a7

This adds roundf() as a new dependency: Since SDL_roundf() requires
SDL >= 2.0.16, invented a tiny local SDLIMAGE_roundf() function for
it instead.
---
 IMG_svg.c | 5 ++++
 nanosvg.h | 69 ++++++++++++++++++++++-----------------------------
 nanosvgrast.h | 4 +--
 3 files changed, 36 insertions(+), 42 deletions(-)

diff --git a/IMG_svg.c b/IMG_svg.c
index e834c7db..03f281da 100644
--- a/IMG_svg.c
+++ b/IMG_svg.c
@@ -27,6 +27,10 @@
 
 #ifdef LOAD_SVG
 
+static float SDLCALL SDLIMAGE_roundf(float x) {
+ return (x >= 0.0f) ? SDL_floorf(x + 0.5f) : SDL_ceilf(x - 0.5f);
+}
+
 /* Replace C runtime functions with SDL C runtime functions for building on Windows */
 #define free SDL_free
 #define malloc SDL_malloc
@@ -63,6 +67,7 @@
 #define sqrt SDL_sqrt
 #define sqrtf SDL_sqrtf
 #define tanf SDL_tanf
+#define roundf SDLIMAGE_roundf
 #ifndef FLT_MAX
 #define FLT_MAX 3.402823466e+38F
 #endif
diff --git a/nanosvg.h b/nanosvg.h
index bc45cfb2..0ceb2c75 100644
--- a/nanosvg.h
+++ b/nanosvg.h
@@ -189,8 +189,6 @@ NSVG_EXPORT void nsvgDelete(NSVGimage* image);
 #endif
 #endif
 
-#endif // NANOSVG_H
-
 #ifdef NANOSVG_IMPLEMENTATION
 
 /*
@@ -1246,35 +1244,23 @@ static const char* nsvg__getNextPathItem(const char* s, char* it)
 
 static unsigned int nsvg__parseColorHex(const char* str)
 {
-	unsigned int c = 0, r = 0, g = 0, b = 0;
-	int n = 0;
-	str++; // skip #
-	// Calculate number of characters.
-	while(str[n] && !nsvg__isspace(str[n]))
- n++;
-	if (n == 6) {
- sscanf(str, "%x", &c);
-	} else if (n == 3) {
- sscanf(str, "%x", &c);
- c = (c&0xf) | ((c&0xf0) << 4) | ((c&0xf00) << 8);
- c |= c<<4;
-	}
-	r = (c >> 16) & 0xff;
-	g = (c >> 8) & 0xff;
-	b = c & 0xff;
-	return NSVG_RGB(r,g,b);
+	unsigned int r=0, g=0, b=0;
+	if (sscanf(str, "#%2x%2x%2x", &r, &g, &b) == 3 ) // 2 digit hex
+ return NSVG_RGB(r, g, b);
+	if (sscanf(str, "#%1x%1x%1x", &r, &g, &b) == 3 ) // 1 digit hex, e.g. #abc -> 0xccbbaa
+ return NSVG_RGB(r*17, g*17, b*17); // same effect as (r<<4|r), (g<<4|g), ..
+	return NSVG_RGB(128, 128, 128);
 }
 
 static unsigned int nsvg__parseColorRGB(const char* str)
 {
-	int r = -1, g = -1, b = -1;
-	char s1[32]="", s2[32]="";
-	sscanf(str + 4, "%d%[%%, \t]%d%[%%, \t]%d", &r, s1, &g, s2, &b);
-	if (strchr(s1, '%')) {
- return NSVG_RGB((r*255)/100,(g*255)/100,(b*255)/100);
-	} else {
- return NSVG_RGB(r,g,b);
-	}
+	unsigned int r=0, g=0, b=0;
+	float rf=0, gf=0, bf=0;
+	if (sscanf(str, "rgb(%u, %u, %u)", &r, &g, &b) == 3) // decimal integers
+ return NSVG_RGB(r, g, b);
+	if (sscanf(str, "rgb(%f%%, %f%%, %f%%)", &rf, &gf, &bf) == 3)	// decimal integer percentage
+ return NSVG_RGB(roundf(rf*2.55f), roundf(gf*2.55f), roundf(bf*2.55f)); // (255 / 100.0f)
+	return NSVG_RGB(128, 128, 128);
 }
 
 typedef struct NSVGNamedColor {
@@ -1849,10 +1835,9 @@ static int nsvg__parseAttr(NSVGparser* p, const char* name, const char* value)
 		if (style) {
 			nsvg__parseStyle(p, style->description);
 		}
-	} 
-	else {
+	} else {
 		return 0;
-	} 
+	}
 	return 1;
 }
 
@@ -2232,7 +2217,12 @@ static void nsvg__pathArcTo(NSVGparser* p, float* cpx, float* cpy, float* args,
 	// The loop assumes an iteration per end point (including start and end), this +1.
 	ndivs = (int)(fabsf(da) / (NSVG_PI*0.5f) + 1.0f);
 	hda = (da / (float)ndivs) / 2.0f;
-	kappa = fabsf(4.0f / 3.0f * (1.0f - cosf(hda)) / sinf(hda));
+	// Fix for ticket #179: division by 0: avoid cotangens around 0 (infinite)
+	if ((hda < 1e-3f) && (hda > -1e-3f))
+ hda *= 0.5f;
+	else
+ hda = (1.0f - cosf(hda)) / sinf(hda);
+	kappa = fabsf(4.0f / 3.0f * hda);
 	if (da < 0.0f)
 		kappa = -kappa;
 
@@ -2844,10 +2834,10 @@ static char *nsvg__strndup(const char *s, size_t n)
 static void nsvg__content(void* ud, const char* s)
 {
 	NSVGparser* p = (NSVGparser*)ud;
-	if (p->styleFlag) {
 
+	if (p->styleFlag) {
 		int state = 0;
- const char* start = s;		
+ const char* start = s;
 		while (*s) {
 			char c = *s;
 			if (nsvg__isspace(c) || c == '{') {
@@ -2859,15 +2849,14 @@ static void nsvg__content(void* ud, const char* s)
 					p->styles->name = nsvg__strndup(start, (size_t)(s - start));
 					start = s + 1;
 					state = 2;
- }				
+ }
 			} else if (state == 2 && c == '}') {
 				p->styles->description = nsvg__strndup(start, (size_t)(s - start));
 				state = 0;
- }
- else if (state == 0) {
+ } else if (state == 0) {
 				start = s;
 				state = 1;
- }  
+ }
 			s++;
 		}
 		//	if (*s == '{' && state == NSVG_XML_CONTENT) {
@@ -2888,9 +2877,7 @@ static void nsvg__content(void* ud, const char* s)
 		// s++;
 		//	}
 		//}
-
 	}
-	// empty
 }
 
 static void nsvg__imageBounds(NSVGparser* p, float* bounds)
@@ -3109,7 +3096,7 @@ NSVG_EXPORT NSVGpath* nsvgDuplicatePath(NSVGpath* p)
     }
     return NULL;
 }
-#endif // 0
+#endif
 
 NSVG_EXPORT void nsvgDelete(NSVGimage* image)
 {
@@ -3128,3 +3115,5 @@ NSVG_EXPORT void nsvgDelete(NSVGimage* image)
 }
 
 #endif
+
+#endif // NANOSVG_H
diff --git a/nanosvgrast.h b/nanosvgrast.h
index b45430ac..b2a7cf59 100644
--- a/nanosvgrast.h
+++ b/nanosvgrast.h
@@ -76,8 +76,6 @@ NSVG_EXPORT void nsvgDeleteRasterizer(NSVGrasterizer*);
 #endif
 #endif
 
-#endif // NANOSVGRAST_H
-
 #ifdef NANOSVGRAST_IMPLEMENTATION
 
 /*
@@ -1463,3 +1461,5 @@ NSVG_EXPORT void nsvgRasterize(NSVGrasterizer* r,
 }
 
 #endif
+
+#endif // NANOSVGRAST_H

```
