Skip to content

Commit

Permalink
Nano SVG is still locale dependent #139, memononen/nanosvg#139 (comment)
Browse files Browse the repository at this point in the history
  • Loading branch information
oehhar committed Aug 2, 2022
1 parent e467731 commit a2a8879
Showing 1 changed file with 54 additions and 7 deletions.
61 changes: 54 additions & 7 deletions generic/nanosvg.h
Original file line number Diff line number Diff line change
Expand Up @@ -1294,15 +1294,62 @@ static unsigned int nsvg__parseColorHex(const char* str)
return NSVG_RGB(128, 128, 128);
}

/*
* Parse rgb color. The pointer 'str' must point at "rgb(" (4+ characters).
* This function returns gray (rgb(128, 128, 128) == '#808080') on parse errors
* for backwards compatibility. Note: other image viewers return black instead.
*/

static unsigned int nsvg__parseColorRGB(const char* str)
{
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);
int i;
unsigned int rgbi[3];
float rgbf[3];
/* try decimal integers first */
if (sscanf(str, "rgb(%u, %u, %u)", &rgbi[0], &rgbi[1], &rgbi[2]) != 3) {
/* integers failed, try percent values (float, locale independent) */
const char delimiter[3] = {',', ',', ')'};
str += 4; /* skip "rgb(" */
for (i = 0; i < 3; i++) {
while (*str && (nsvg__isspace(*str))) str++; /* skip leading spaces */
if (*str == '+') str++; /* skip '+' (don't allow '-') */
if (!*str) break;
rgbf[i] = nsvg__atof(str);

/*
* Note 1: it would be great if nsvg__atof() returned how many
* bytes it consumed but it doesn't. We need to skip the number,
* the '%' character, spaces, and the delimiter ',' or ')'.
*
* Note 2: The following code does not allow values like "33.%",
* i.e. a decimal point w/o fractional part, but this is consistent
* with other image viewers, e.g. firefox, chrome, eog, gimp.
*/

while (*str && nsvg__isdigit(*str)) str++; /* skip integer part */
if (*str == '.') {
str++;
if (!nsvg__isdigit(*str)) break; /* error: no digit after '.' */
while (*str && nsvg__isdigit(*str)) str++; /* skip fractional part */
}
if (*str == '%') str++; else break;
while (nsvg__isspace(*str)) str++;
if (*str == delimiter[i]) str++;
else break;
}
if (i == 3) {
rgbi[0] = roundf(rgbf[0] * 2.55f);
rgbi[1] = roundf(rgbf[1] * 2.55f);
rgbi[2] = roundf(rgbf[2] * 2.55f);
} else {
rgbi[0] = rgbi[1] = rgbi[2] = 128;
}
}
/* clip values as the CSS spec requires */
for (i = 0; i < 3; i++) {
if (rgbi[i] > 255) rgbi[i] = 255;
}
return NSVG_RGB(rgbi[0], rgbi[1], rgbi[2]);
}

typedef struct NSVGNamedColor {
Expand Down

0 comments on commit a2a8879

Please sign in to comment.