From c910863e19f9c9cc3db56924634315a37ecfe2bb Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Fri, 10 Feb 2012 23:55:24 +0000 Subject: proposed fix for bug-3486474 --- doc/GetColor.3 | 5 ++-- generic/tkColor.c | 55 ++++++++++++++++++++++++++++++++++ generic/tkCursor.c | 4 +-- generic/tkImgBmap.c | 4 +-- generic/tkImgPhoto.c | 2 +- generic/tkInt.h | 7 +++++ mac/tkMacColor.c | 2 +- macosx/tkMacOSXColor.c | 2 +- unix/tkUnixColor.c | 2 +- unix/tkUnixCursor.c | 10 +++---- win/tkWinColor.c | 2 +- xlib/xcolors.c | 81 +++++++++++++++++++++++++++++++++++++++----------- 12 files changed, 143 insertions(+), 33 deletions(-) diff --git a/doc/GetColor.3 b/doc/GetColor.3 index 201edab..abd1620 100644 --- a/doc/GetColor.3 +++ b/doc/GetColor.3 @@ -95,8 +95,9 @@ to use to display the color. Each \fIR\fR, \fIG\fR, or \fIB\fR represents a single hexadecimal digit. The four forms permit colors to be specified with 4-bit, 8-bit, 12-bit or 16-bit values. When fewer than 16 bits are provided for each color, they represent -the most significant bits of the color. For example, #3a7 is the -same as #3000a0007000. +the most significant bits of the color, while the lower unfilled +bits will be repeatedly replicated from the available higher bits. +For example, #3a7 is the same as #3333aaaa7777. .PP .VS 8.1 \fBTk_AllocColorFromObj\fR returns a pointer to diff --git a/generic/tkColor.c b/generic/tkColor.c index f06c43f..87f3209 100644 --- a/generic/tkColor.c +++ b/generic/tkColor.c @@ -809,3 +809,58 @@ TkDebugColor(tkwin, name) } return resultPtr; } + +#ifndef __WIN32__ +/* This function is not necessary for Win32, + * since XParseColor already does the right thing */ +Status +TkParseColor(display, map, spec, colorPtr) + Display * display; /* The display */ + Colormap map; /* Color map */ + _Xconst char* spec; /* String to be parsed */ + XColor * colorPtr; +{ + if (*spec == '#') { + char buf[14]; + buf[0] = '#'; buf[13] = '\0'; + if (!spec[1] || !spec[2] || !spec[3]) { + /* Not at least 3 hex digits, so invalid */ + return 0; + } else if (!spec[4]) { + /* Exactly 3 hex digits */ + buf[1] = buf[2] = buf[3] = buf[4] = spec[1]; + buf[5] = buf[6] = buf[7] = buf[8] = spec[2]; + buf[9] = buf[10] = buf[11] = buf[12] = spec[3]; + return XParseColor(display, map, buf, colorPtr); + } else if (!spec[5] || !spec[6]) { + /* Not at least 6 hex digits, so invalid */ + return 0; + } else if (!spec[7]) { + /* Exactly 6 hex digits */ + buf[1] = buf[3] = spec[1]; + buf[2] = buf[4] = spec[2]; + buf[5] = buf[7] = spec[3]; + buf[6] = buf[8] = spec[4]; + buf[9] = buf[11] = spec[5]; + buf[10] = buf[12] = spec[6]; + return XParseColor(display, map, buf, colorPtr); + } else if (!spec[8] || !spec[9]) { + /* Not at least 9 hex digits, so invalid */ + return 0; + } else if (!spec[10]) { + /* Exactly 9 hex digits */ + buf[1] = buf[4] = spec[1]; + buf[2] = spec[2]; + buf[3] = spec[3]; + buf[5] = buf[8] = spec[4]; + buf[6] = spec[5]; + buf[7] = spec[6]; + buf[9] = buf[12] = spec[7]; + buf[10] = spec[8]; + buf[11] = spec[9]; + return XParseColor(display, map, buf, colorPtr); + } + } + return XParseColor(display, map, spec, colorPtr); +} +#endif /* __WIN32__ */ diff --git a/generic/tkCursor.c b/generic/tkCursor.c index 466d0ef..f599083 100644 --- a/generic/tkCursor.c +++ b/generic/tkCursor.c @@ -357,12 +357,12 @@ Tk_GetCursorFromData(interp, tkwin, source, mask, width, height, * available and add it to the database. */ - if (XParseColor(dataKey.display, Tk_Colormap(tkwin), fg, &fgColor) == 0) { + if (TkParseColor(dataKey.display, Tk_Colormap(tkwin), fg, &fgColor) == 0) { Tcl_AppendResult(interp, "invalid color name \"", fg, "\"", (char *) NULL); goto error; } - if (XParseColor(dataKey.display, Tk_Colormap(tkwin), bg, &bgColor) == 0) { + if (TkParseColor(dataKey.display, Tk_Colormap(tkwin), bg, &bgColor) == 0) { Tcl_AppendResult(interp, "invalid color name \"", bg, "\"", (char *) NULL); goto error; diff --git a/generic/tkImgBmap.c b/generic/tkImgBmap.c index 99ae050..e1ccecb 100644 --- a/generic/tkImgBmap.c +++ b/generic/tkImgBmap.c @@ -1266,7 +1266,7 @@ ImgBmapPostscript(clientData, interp, tkwin, psinfo, x, y, width, height, */ if ((masterPtr->bgUid != NULL) && (masterPtr->bgUid[0] != '\000')) { XColor color; - XParseColor(Tk_Display(tkwin), Tk_Colormap(tkwin), masterPtr->bgUid, + TkParseColor(Tk_Display(tkwin), Tk_Colormap(tkwin), masterPtr->bgUid, &color); if (Tk_PostscriptColor(interp, psinfo, &color) != TCL_OK) { return TCL_ERROR; @@ -1286,7 +1286,7 @@ ImgBmapPostscript(clientData, interp, tkwin, psinfo, x, y, width, height, */ if ( (masterPtr->fgUid != NULL) && (masterPtr->data != NULL) ) { XColor color; - XParseColor(Tk_Display(tkwin), Tk_Colormap(tkwin), masterPtr->fgUid, + TkParseColor(Tk_Display(tkwin), Tk_Colormap(tkwin), masterPtr->fgUid, &color); if (Tk_PostscriptColor(interp, psinfo, &color) != TCL_OK) { return TCL_ERROR; diff --git a/generic/tkImgPhoto.c b/generic/tkImgPhoto.c index 80b44d7..ffbb47c 100644 --- a/generic/tkImgPhoto.c +++ b/generic/tkImgPhoto.c @@ -1150,7 +1150,7 @@ ImgPhotoCmd(clientData, interp, objc, objv) break; } for (x = 0; x < dataWidth; ++x) { - if (!XParseColor(Tk_Display(tkwin), Tk_Colormap(tkwin), + if (!TkParseColor(Tk_Display(tkwin), Tk_Colormap(tkwin), listArgv[x], &color)) { Tcl_AppendResult(interp, "can't parse color \"", listArgv[x], "\"", (char *) NULL); diff --git a/generic/tkInt.h b/generic/tkInt.h index 777201e..c274236 100644 --- a/generic/tkInt.h +++ b/generic/tkInt.h @@ -1213,6 +1213,13 @@ EXTERN int TkParsePadAmount _ANSI_ARGS_((Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr, int *pad1Ptr, int *pad2Ptr)); EXTERN int TkpAlwaysShowSelection _ANSI_ARGS_((Tk_Window tkwin)); +#ifdef __WIN32__ +#define TkParseColor XParseColor +#else +EXTERN Status TkParseColor _ANSI_ARGS_((Display * display, + Colormap map, _Xconst char* spec, + XColor * colorPtr)); +#endif /* * Unsupported commands. diff --git a/mac/tkMacColor.c b/mac/tkMacColor.c index 6fd0263..6c3c230 100644 --- a/mac/tkMacColor.c +++ b/mac/tkMacColor.c @@ -274,7 +274,7 @@ TkpGetColor( } } - if (XParseColor(display, colormap, name, &color) == 0) { + if (TkParseColor(display, colormap, name, &color) == 0) { return (TkColor *) NULL; } diff --git a/macosx/tkMacOSXColor.c b/macosx/tkMacOSXColor.c index 6ddb95e..9520a77 100644 --- a/macosx/tkMacOSXColor.c +++ b/macosx/tkMacOSXColor.c @@ -591,7 +591,7 @@ TkpGetColor( } } - if (XParseColor(display, colormap, name, &color) == 0) { + if (TkParseColor(display, colormap, name, &color) == 0) { return (TkColor *) NULL; } diff --git a/unix/tkUnixColor.c b/unix/tkUnixColor.c index d001be5..aebbbca 100644 --- a/unix/tkUnixColor.c +++ b/unix/tkUnixColor.c @@ -168,7 +168,7 @@ TkpGetColor(tkwin, name) FindClosestColor(tkwin, &screen, &color); } } else { - if (XParseColor(display, colormap, buf, &color) == 0) { + if (TkParseColor(display, colormap, buf, &color) == 0) { return (TkColor *) NULL; } if (XAllocColor(display, colormap, &color) != 0) { diff --git a/unix/tkUnixCursor.c b/unix/tkUnixCursor.c index 70e8b93..a4ee0cb 100644 --- a/unix/tkUnixCursor.c +++ b/unix/tkUnixCursor.c @@ -194,7 +194,7 @@ TkGetCursorByName(interp, tkwin, string) fg.red = fg.green = fg.blue = 0; bg.red = bg.green = bg.blue = 65535; } else { - if (XParseColor(display, Tk_Colormap(tkwin), argv[1], + if (TkParseColor(display, Tk_Colormap(tkwin), argv[1], &fg) == 0) { Tcl_AppendResult(interp, "invalid color name \"", argv[1], "\"", (char *) NULL); @@ -204,7 +204,7 @@ TkGetCursorByName(interp, tkwin, string) bg.red = bg.green = bg.blue = 0; maskIndex = namePtr->shape; } else { - if (XParseColor(display, Tk_Colormap(tkwin), argv[2], + if (TkParseColor(display, Tk_Colormap(tkwin), argv[2], &bg) == 0) { Tcl_AppendResult(interp, "invalid color name \"", argv[2], "\"", (char *) NULL); @@ -262,7 +262,7 @@ TkGetCursorByName(interp, tkwin, string) goto cleanup; } if (argc == 2) { - if (XParseColor(display, Tk_Colormap(tkwin), argv[1], + if (TkParseColor(display, Tk_Colormap(tkwin), argv[1], &fg) == 0) { Tcl_AppendResult(interp, "invalid color name \"", argv[1], "\"", (char *) NULL); @@ -285,13 +285,13 @@ TkGetCursorByName(interp, tkwin, string) TCL_STATIC); goto cleanup; } - if (XParseColor(display, Tk_Colormap(tkwin), argv[2], + if (TkParseColor(display, Tk_Colormap(tkwin), argv[2], &fg) == 0) { Tcl_AppendResult(interp, "invalid color name \"", argv[2], "\"", (char *) NULL); goto cleanup; } - if (XParseColor(display, Tk_Colormap(tkwin), argv[3], + if (TkParseColor(display, Tk_Colormap(tkwin), argv[3], &bg) == 0) { Tcl_AppendResult(interp, "invalid color name \"", argv[3], "\"", (char *) NULL); diff --git a/win/tkWinColor.c b/win/tkWinColor.c index d3b3cad..088c216 100644 --- a/win/tkWinColor.c +++ b/win/tkWinColor.c @@ -201,7 +201,7 @@ TkpGetColor(tkwin, name) if (((strncasecmp(name, "system", 6) == 0) && FindSystemColor(name+6, &color, &index)) - || XParseColor(Tk_Display(tkwin), Tk_Colormap(tkwin), name, + || TkParseColor(Tk_Display(tkwin), Tk_Colormap(tkwin), name, &color)) { winColPtr = (WinColor *) ckalloc(sizeof(WinColor)); winColPtr->info.color = color; diff --git a/xlib/xcolors.c b/xlib/xcolors.c index 32c53bd..598f27b 100644 --- a/xlib/xcolors.c +++ b/xlib/xcolors.c @@ -882,24 +882,71 @@ XParseColor(display, map, spec, colorPtr) XColor *colorPtr; { if (spec[0] == '#') { - char fmt[16]; - int i, red, green, blue; + char rstr[5], gstr[5], bstr[5]; - if ((i = (int) strlen(spec+1))%3) { - return 0; - } - i /= 3; - - sprintf(fmt, "%%%dx%%%dx%%%dx", i, i, i); - if (sscanf(spec+1, fmt, &red, &green, &blue) != 3) { - return 0; - } - colorPtr->red = (((unsigned short) red) << (4 * (4 - i))) - | ((unsigned short) red); - colorPtr->green = (((unsigned short) green) << (4 * (4 - i))) - | ((unsigned short) green); - colorPtr->blue = (((unsigned short) blue) << (4 * (4 - i))) - | ((unsigned short) blue); + if (!isxdigit((unsigned char) spec[1]) + || !isxdigit((unsigned char) spec[2]) + || !isxdigit((unsigned char) spec[3])) { + /* Not at least 3 hex digits, so invalid */ + return 0; + } else if (!spec[4]) { + /* Exactly 3 hex digits */ + rstr[0] = rstr[1] = rstr[2] = rstr[3] = spec[1]; + gstr[0] = gstr[1] = gstr[2] = gstr[3] = spec[2]; + bstr[0] = bstr[1] = bstr[2] = bstr[3] = spec[3]; + } else if (!isxdigit((unsigned char) spec[4]) + || !isxdigit((unsigned char) spec[5]) + || !isxdigit((unsigned char) spec[6])) { + /* Not at least 6 hex digits, so invalid */ + return 0; + } else if (!spec[7]) { + /* Exactly 6 hex digits */ + rstr[0] = rstr[2] = spec[1]; + rstr[1] = rstr[3] = spec[2]; + gstr[0] = gstr[2] = spec[3]; + gstr[1] = gstr[3] = spec[4]; + bstr[0] = bstr[2] = spec[5]; + bstr[1] = bstr[3] = spec[6]; + } else if (!isxdigit((unsigned char) spec[7]) + || !isxdigit((unsigned char) spec[8]) + || !isxdigit((unsigned char) spec[9])) { + /* Not at least 9 hex digits, so invalid */ + return 0; + } else if (!spec[10]) { + /* Exactly 9 hex digits */ + rstr[0] = rstr[3] = spec[1]; + rstr[1] = spec[2]; + rstr[2] = spec[3]; + gstr[0] = gstr[3] = spec[4]; + gstr[1] = spec[5]; + gstr[2] = spec[6]; + bstr[0] = bstr[3] = spec[7]; + bstr[1] = spec[8]; + bstr[2] = spec[9]; + } else if (!isxdigit((unsigned char) spec[10]) + || !isxdigit((unsigned char) spec[11]) + || !isxdigit((unsigned char) spec[12]) || spec[13]) { + /* Not exactly 12 hex digits, so invalid */ + return 0; + } else { + /* Exactly 12 hex digits */ + rstr[0] = spec[1]; + rstr[1] = spec[2]; + rstr[2] = spec[3]; + rstr[3] = spec[4]; + gstr[0] = spec[5]; + gstr[1] = spec[6]; + gstr[2] = spec[7]; + gstr[3] = spec[8]; + bstr[0] = spec[9]; + bstr[1] = spec[10]; + bstr[2] = spec[11]; + bstr[3] = spec[12]; + } + rstr[4] = gstr[4] = bstr[4] = '\0'; + colorPtr->red = strtol(rstr, NULL, 16); + colorPtr->green = strtol(gstr, NULL, 16); + colorPtr->blue = strtol(bstr, NULL, 16); } else { if (!FindColor(spec, colorPtr)) { return 0; -- cgit v0.12 From 9ec06c1450bc3f4984cbee812e30d3c9bfc202b8 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Sat, 11 Feb 2012 00:19:20 +0000 Subject: let Tk_NameOfColor output a shorter color-name, when possible --- generic/tkColor.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/generic/tkColor.c b/generic/tkColor.c index 87f3209..a9b1fc1 100644 --- a/generic/tkColor.c +++ b/generic/tkColor.c @@ -375,6 +375,21 @@ Tk_NameOfColor(colorPtr) Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); sprintf(tsdPtr->rgbString, "#%04x%04x%04x", colorPtr->red, colorPtr->green, colorPtr->blue); + /* If the string has the form #RSRSTUTUVWVW (where equal + * letters denote equal hexdigits) then this is + * equivalent to #RSTUVW. Then output the shorter form */ + if ((tsdPtr->rgbString[1] == tsdPtr->rgbString[3]) + && (tsdPtr->rgbString[2] == tsdPtr->rgbString[4]) + && (tsdPtr->rgbString[5] == tsdPtr->rgbString[7]) + && (tsdPtr->rgbString[6] == tsdPtr->rgbString[8]) + && (tsdPtr->rgbString[9] == tsdPtr->rgbString[11]) + && (tsdPtr->rgbString[10] == tsdPtr->rgbString[12])) { + tsdPtr->rgbString[3] = tsdPtr->rgbString[5]; + tsdPtr->rgbString[4] = tsdPtr->rgbString[6]; + tsdPtr->rgbString[5] = tsdPtr->rgbString[9]; + tsdPtr->rgbString[6] = tsdPtr->rgbString[10]; + tsdPtr->rgbString[7] = '\0'; + } return tsdPtr->rgbString; } } -- cgit v0.12 From 505d8dc8bc999b995961dbd32c518620d843bdfe Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Sun, 12 Feb 2012 17:46:18 +0000 Subject: improved, faster implementations of XParseColor and TkParseColor --- ChangeLog | 7 ++++ generic/tkColor.c | 57 +++++++++++++++++---------------- generic/tkStubInit.c | 6 ++++ xlib/xcolors.c | 90 +++++++++++++++------------------------------------- 4 files changed, 68 insertions(+), 92 deletions(-) diff --git a/ChangeLog b/ChangeLog index dcbc39f..b1e68e6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2012-02-?? Jan Nijtmans + + * xlib/xcolors.c: [Bug 3486474]: Inconsistent color scaling + * generic/tkColor.c: new internal function TkParseColor + * generic/tkInt.h: + * generic/tk*.c: Change XParseColor() to TkParseColor() everywhere. + 2012-01-25 Jan Nijtmans * generic/tkImgPhoto.c: [Bug 2433260]: non-critical error in diff --git a/generic/tkColor.c b/generic/tkColor.c index a9b1fc1..d130ed6 100644 --- a/generic/tkColor.c +++ b/generic/tkColor.c @@ -377,7 +377,8 @@ Tk_NameOfColor(colorPtr) colorPtr->green, colorPtr->blue); /* If the string has the form #RSRSTUTUVWVW (where equal * letters denote equal hexdigits) then this is - * equivalent to #RSTUVW. Then output the shorter form */ + * equivalent to #RSTUVW. Then output the shorter form + * !!!! Only to be merged to Tcl 8.6, not earlier versions!!! */ if ((tsdPtr->rgbString[1] == tsdPtr->rgbString[3]) && (tsdPtr->rgbString[2] == tsdPtr->rgbString[4]) && (tsdPtr->rgbString[5] == tsdPtr->rgbString[7]) @@ -838,42 +839,42 @@ TkParseColor(display, map, spec, colorPtr) if (*spec == '#') { char buf[14]; buf[0] = '#'; buf[13] = '\0'; - if (!spec[1] || !spec[2] || !spec[3]) { + if (!*(++spec) || !*(++spec) || !*(++spec)) { /* Not at least 3 hex digits, so invalid */ return 0; - } else if (!spec[4]) { + } else if (!*(++spec)) { /* Exactly 3 hex digits */ - buf[1] = buf[2] = buf[3] = buf[4] = spec[1]; - buf[5] = buf[6] = buf[7] = buf[8] = spec[2]; - buf[9] = buf[10] = buf[11] = buf[12] = spec[3]; - return XParseColor(display, map, buf, colorPtr); - } else if (!spec[5] || !spec[6]) { + buf[9] = buf[10] = buf[11] = buf[12] = *(--spec); + buf[5] = buf[6] = buf[7] = buf[8] = *(--spec); + buf[1] = buf[2] = buf[3] = buf[4] = *(--spec); + spec = buf; + } else if (!*(++spec) || !*(++spec)) { /* Not at least 6 hex digits, so invalid */ return 0; - } else if (!spec[7]) { + } else if (!*(++spec)) { /* Exactly 6 hex digits */ - buf[1] = buf[3] = spec[1]; - buf[2] = buf[4] = spec[2]; - buf[5] = buf[7] = spec[3]; - buf[6] = buf[8] = spec[4]; - buf[9] = buf[11] = spec[5]; - buf[10] = buf[12] = spec[6]; - return XParseColor(display, map, buf, colorPtr); - } else if (!spec[8] || !spec[9]) { + buf[10] = buf[12] = *(--spec); + buf[9] = buf[11] = *(--spec); + buf[6] = buf[8] = *(--spec); + buf[5] = buf[7] = *(--spec); + buf[2] = buf[4] = *(--spec); + buf[1] = buf[3] = *(--spec); + spec = buf; + } else if (!*(++spec) || !*(++spec)) { /* Not at least 9 hex digits, so invalid */ return 0; - } else if (!spec[10]) { + } else if (!*(++spec)) { /* Exactly 9 hex digits */ - buf[1] = buf[4] = spec[1]; - buf[2] = spec[2]; - buf[3] = spec[3]; - buf[5] = buf[8] = spec[4]; - buf[6] = spec[5]; - buf[7] = spec[6]; - buf[9] = buf[12] = spec[7]; - buf[10] = spec[8]; - buf[11] = spec[9]; - return XParseColor(display, map, buf, colorPtr); + buf[11] = *(--spec); + buf[10] = *(--spec); + buf[9] = buf[12] = *(--spec); + buf[7] = *(--spec); + buf[6] = *(--spec); + buf[5] = buf[8] = *(--spec); + buf[3] = *(--spec); + buf[2] = *(--spec); + buf[1] = buf[4] = *(--spec); + spec = buf; } } return XParseColor(display, map, spec, colorPtr); diff --git a/generic/tkStubInit.c b/generic/tkStubInit.c index 6df1f2d..a82e044 100644 --- a/generic/tkStubInit.c +++ b/generic/tkStubInit.c @@ -46,6 +46,12 @@ #define Tk_GetCanvasVisitor ((VOID * (*) _ANSI_ARGS_((Tcl_Interp * interp, \ CONST char * name))) NULL) +#ifndef __WIN32__ +/* Make sure that extensions which call XParseColor through + * the stub table, call TkParseColor in stead. See bug #3486474 */ +# define XParseColor TkParseColor +#endif + /* * WARNING: The contents of this file is automatically generated by the * tools/genStubs.tcl script. Any modifications to the function declarations diff --git a/xlib/xcolors.c b/xlib/xcolors.c index 598f27b..7e88b2a 100644 --- a/xlib/xcolors.c +++ b/xlib/xcolors.c @@ -882,71 +882,33 @@ XParseColor(display, map, spec, colorPtr) XColor *colorPtr; { if (spec[0] == '#') { - char rstr[5], gstr[5], bstr[5]; + char *p; + Tcl_WideInt value = _strtoi64(++spec, &p, 16); - if (!isxdigit((unsigned char) spec[1]) - || !isxdigit((unsigned char) spec[2]) - || !isxdigit((unsigned char) spec[3])) { - /* Not at least 3 hex digits, so invalid */ - return 0; - } else if (!spec[4]) { - /* Exactly 3 hex digits */ - rstr[0] = rstr[1] = rstr[2] = rstr[3] = spec[1]; - gstr[0] = gstr[1] = gstr[2] = gstr[3] = spec[2]; - bstr[0] = bstr[1] = bstr[2] = bstr[3] = spec[3]; - } else if (!isxdigit((unsigned char) spec[4]) - || !isxdigit((unsigned char) spec[5]) - || !isxdigit((unsigned char) spec[6])) { - /* Not at least 6 hex digits, so invalid */ - return 0; - } else if (!spec[7]) { - /* Exactly 6 hex digits */ - rstr[0] = rstr[2] = spec[1]; - rstr[1] = rstr[3] = spec[2]; - gstr[0] = gstr[2] = spec[3]; - gstr[1] = gstr[3] = spec[4]; - bstr[0] = bstr[2] = spec[5]; - bstr[1] = bstr[3] = spec[6]; - } else if (!isxdigit((unsigned char) spec[7]) - || !isxdigit((unsigned char) spec[8]) - || !isxdigit((unsigned char) spec[9])) { - /* Not at least 9 hex digits, so invalid */ - return 0; - } else if (!spec[10]) { - /* Exactly 9 hex digits */ - rstr[0] = rstr[3] = spec[1]; - rstr[1] = spec[2]; - rstr[2] = spec[3]; - gstr[0] = gstr[3] = spec[4]; - gstr[1] = spec[5]; - gstr[2] = spec[6]; - bstr[0] = bstr[3] = spec[7]; - bstr[1] = spec[8]; - bstr[2] = spec[9]; - } else if (!isxdigit((unsigned char) spec[10]) - || !isxdigit((unsigned char) spec[11]) - || !isxdigit((unsigned char) spec[12]) || spec[13]) { - /* Not exactly 12 hex digits, so invalid */ - return 0; - } else { - /* Exactly 12 hex digits */ - rstr[0] = spec[1]; - rstr[1] = spec[2]; - rstr[2] = spec[3]; - rstr[3] = spec[4]; - gstr[0] = spec[5]; - gstr[1] = spec[6]; - gstr[2] = spec[7]; - gstr[3] = spec[8]; - bstr[0] = spec[9]; - bstr[1] = spec[10]; - bstr[2] = spec[11]; - bstr[3] = spec[12]; - } - rstr[4] = gstr[4] = bstr[4] = '\0'; - colorPtr->red = strtol(rstr, NULL, 16); - colorPtr->green = strtol(gstr, NULL, 16); - colorPtr->blue = strtol(bstr, NULL, 16); + switch ((int)(p-spec)) { + case 3: + colorPtr->red = (unsigned short) (((value >> 8) & 0xf) * 0x1111); + colorPtr->green = (unsigned short) (((value >> 4) & 0xf) * 0x1111); + colorPtr->blue = (unsigned short) ((value & 0xf) * 0x1111); + break; + case 6: + colorPtr->red = (unsigned short) (((value >> 16) & 0xff) | ((value >> 8) & 0xff00)); + colorPtr->green = (unsigned short) (((value >> 8) & 0xff) | (value & 0xff00)); + colorPtr->blue = (unsigned short) ((value & 0xff) | (value << 8)); + break; + case 9: + colorPtr->red = (unsigned short) (((value >> 32) & 0xf) | ((value >> 20) & 0xfff0)); + colorPtr->green = (unsigned short) (((value >> 20) & 0xf) | ((value >> 8) & 0xfff0)); + colorPtr->blue = (unsigned short) (((value >> 8) & 0xf) | (value << 4)); + break; + case 12: + colorPtr->red = (unsigned short) (value >> 32); + colorPtr->green = (unsigned short) (value >> 16); + colorPtr->blue = (unsigned short) value; + break; + default: + return 0; + } } else { if (!FindColor(spec, colorPtr)) { return 0; -- cgit v0.12