diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libppmcolor.c | 115 |
1 files changed, 92 insertions, 23 deletions
diff --git a/lib/libppmcolor.c b/lib/libppmcolor.c index ff1a1e67..7cfacd29 100644 --- a/lib/libppmcolor.c +++ b/lib/libppmcolor.c @@ -25,9 +25,12 @@ static void computeHexTable(int hexit[]) { - int i; + + unsigned int i; + for ( i = 0; i < 256; ++i ) - hexit[i] = 1234567890; + hexit[i] = -1; + hexit['0'] = 0; hexit['1'] = 1; hexit['2'] = 2; @@ -91,16 +94,17 @@ rgbnorm(long const rgb, number of digits isn't valid, issue an error message and identify the complete color color specification in error as 'colorname'. - For example, if the user says 0ff/000/000 and the maxval is 100, + For example, if the user says "0ff" and the maxval is 100, then rgb is 0xff, n is 3, and our result is 0xff / (16**3-1) * 100 = 6. - -----------------------------------------------------------------------------*/ pixval retval; - assert(hexDigitCount > 0); - switch (hexDigitCount) { + case 0: + pm_error("A hexadecimal color specifier in color '%s' is " + "an empty string", colorname); + break; case 1: retval = (pixval)((double) rgb * maxval / 15 + 0.5); break; @@ -131,34 +135,77 @@ rgbnorm(long const rgb, static void -parseNewHexX11(const char colorname[], +parseHexDigits(const char * const string, + char const delim, + int const hexit[], + pixval * const nP, + unsigned int * const digitCountP) { + + unsigned int digitCount; + pixval n; + + digitCount = 0; + while (string[digitCount] != delim) { + char const digit = string[digitCount]; + if (digit == '\0') + pm_error("rgb: color spec ends prematurely"); + else { + int const hexval = hexit[(unsigned int)digit]; + if (hexval == -1) + pm_error("Invalid hex digit in rgb: color spec: 0x%02x", + digit); + n = n * 16 + hexval; + ++digitCount; + } + } + *nP = n; + *digitCountP = digitCount; +} + + + +static void +parseNewHexX11(char const colorname[], pixval const maxval, bool const closeOk, pixel * const colorP) { +/*---------------------------------------------------------------------------- + Determine what color colorname[] specifies in the new style hex + color specification format (e.g. rgb:55/40/55). + Return that color as *colorP. + + Assume colorname[] starts with "rgb:", but otherwise it might be + gibberish. +-----------------------------------------------------------------------------*/ int hexit[256]; - const char* cp; - pixval r,g,b; + const char * cp; + pixval n; + unsigned int digitCount; pixval rNorm, gNorm, bNorm; - int i; - computeHexTable(hexit); - cp = colorname + 4; + cp = &colorname[4]; + + parseHexDigits(cp, '/', hexit, &n, &digitCount); + + rNorm = rgbnorm(n, maxval, digitCount, closeOk, colorname); + + cp += digitCount; + ++cp; /* Skip the slash */ + + parseHexDigits(cp, '/', hexit, &n, &digitCount); - for (i = 0, r = 0; *cp != '/'; ++i, ++cp) - r = r * 16 + hexit[(int)*cp]; - rNorm = rgbnorm(r, maxval, i, closeOk, colorname); + gNorm = rgbnorm(n, maxval, digitCount, closeOk, colorname); - for (i = 0, g = 0,++cp; *cp != '/'; ++i, ++cp ) - g = g * 16 + hexit[(int)*cp]; - gNorm = rgbnorm(g, maxval, i, closeOk, colorname); + cp += digitCount; + ++cp; /* Skip the slash */ - for (i = 0, b = 0, ++cp; *cp != '\0'; ++i, ++cp ) - b = b * 16 + hexit[(int)*cp]; - bNorm = rgbnorm(b, maxval, i, closeOk, colorname); + parseHexDigits(cp, '\0', hexit, &n, &digitCount); + + bNorm = rgbnorm(n, maxval, digitCount, closeOk, colorname); PPM_ASSIGN(*colorP, rNorm, gNorm, bNorm); } @@ -200,18 +247,40 @@ parseNewDecX11(char const colorname[], +static bool +isHexString(char const string[], + int const hexit[]) { + + bool retval; + const char * p; + + for (p = &string[0], retval = true; *p && retval == true; ++p) { + if (hexit[(unsigned int)*p] == -1) + retval = false; + } + return retval; +} + + + static void -parseOldX11(const char colorname[], +parseOldX11(char const colorname[], pixval const maxval, bool const closeOk, pixel * const colorP) { - +/*---------------------------------------------------------------------------- + Return as *colorP the color specified by the old X11 style color + specififier colorname[] (e.g. #554055). +-----------------------------------------------------------------------------*/ int hexit[256]; long r,g,b; pixval rNorm, gNorm, bNorm; computeHexTable(hexit); + if (!isHexString(&colorname[1], hexit)) + pm_error("Non-hexadecimal characters in #-type color specification"); + switch (strlen(colorname) - 1 /* (Number of hex digits) */) { case 3: r = hexit[(int)colorname[1]]; |