From d51ac32dd61c871b05bea14dc748b896e4568496 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 FossilOrigin-Name: acbeaf88e1a8db42cf869b5128c3bd32be31f5f8 --- 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