summaryrefslogtreecommitdiff
path: root/nanosvg/nanosvg.h
diff options
context:
space:
mode:
Diffstat (limited to 'nanosvg/nanosvg.h')
-rw-r--r--nanosvg/nanosvg.h65
1 files changed, 53 insertions, 12 deletions
diff --git a/nanosvg/nanosvg.h b/nanosvg/nanosvg.h
index 0175ade74..24bdd46ce 100644
--- a/nanosvg/nanosvg.h
+++ b/nanosvg/nanosvg.h
@@ -181,12 +181,11 @@ void nsvgDelete(NSVGimage* image);
#endif
#endif
-#endif // NANOSVG_H
-
#ifdef NANOSVG_IMPLEMENTATION
#include <string.h>
#include <stdlib.h>
+#include <stdio.h>
#include <math.h>
#define NSVG_PI (3.14159265358979323846264338327f)
@@ -1231,18 +1230,58 @@ 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;
- if (sscanf(str, "rgb(%u, %u, %u)", &r, &g, &b) == 3) // decimal integers
- return NSVG_RGB(r, g, b);
- if (sscanf(str, "rgb(%u%%, %u%%, %u%%)", &r, &g, &b) == 3) { // decimal integer percentage
- r = (r <= 100) ? ((r*255)/100) : 255; // FLTK: clip percentages >100
- g = (g <= 100) ? ((g*255)/100) : 255;
- b = (b <= 100) ? ((b*255)/100) : 255;
- return NSVG_RGB(r, g, b);
+ 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;
+ }
}
- return NSVG_RGB(128, 128, 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 {
@@ -3017,4 +3056,6 @@ void nsvgDelete(NSVGimage* image)
free(image);
}
-#endif
+#endif // NANOSVG_IMPLEMENTATION
+
+#endif // NANOSVG_H