summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog7
-rw-r--r--carbon/tkMacOSXColor.c2
-rw-r--r--doc/GetColor.35
-rw-r--r--generic/tkColor.c73
-rw-r--r--generic/tkCursor.c4
-rw-r--r--generic/tkImgBmap.c4
-rw-r--r--generic/tkImgPhoto.c2
-rw-r--r--generic/tkInt.h8
-rw-r--r--generic/tkStubInit.c6
-rw-r--r--macosx/tkMacOSXColor.c2
-rw-r--r--unix/tkUnixColor.c2
-rw-r--r--unix/tkUnixCursor.c10
-rw-r--r--win/tkWinColor.c2
-rw-r--r--xlib/xcolors.c39
14 files changed, 134 insertions, 32 deletions
diff --git a/ChangeLog b/ChangeLog
index 8233212..16ae1dd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2012-02-15 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * 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-02-10 Donal K. Fellows <dkf@users.sf.net>
* win/tkWinDialog.c (GetFileName): Ensure that we do not convert a
diff --git a/carbon/tkMacOSXColor.c b/carbon/tkMacOSXColor.c
index 3217c69..2c9100d 100644
--- a/carbon/tkMacOSXColor.c
+++ b/carbon/tkMacOSXColor.c
@@ -591,7 +591,7 @@ TkpGetColor(
}
}
- if (XParseColor(display, colormap, name, &color) == 0) {
+ if (TkParseColor(display, colormap, name, &color) == 0) {
return NULL;
}
diff --git a/doc/GetColor.3 b/doc/GetColor.3
index f41a87a..5b7a553 100644
--- a/doc/GetColor.3
+++ b/doc/GetColor.3
@@ -86,8 +86,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
\fBTk_AllocColorFromObj\fR returns a pointer to
an XColor structure; the structure indicates the exact intensities of
diff --git a/generic/tkColor.c b/generic/tkColor.c
index 168664c..db649d3 100644
--- a/generic/tkColor.c
+++ b/generic/tkColor.c
@@ -371,6 +371,23 @@ Tk_NameOfColor(
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;
}
}
@@ -807,7 +824,61 @@ TkDebugColor(
}
return resultPtr;
}
-
+
+#ifndef __WIN32__
+/* This function is not necessary for Win32,
+ * since XParseColor already does the right thing */
+Status
+TkParseColor(
+ 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) || !*(++spec) || !*(++spec)) {
+ /* Not at least 3 hex digits, so invalid */
+ return 0;
+ } else if (!*(++spec)) {
+ /* Exactly 3 hex digits */
+ 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)) {
+ /* Exactly 6 hex digits */
+ 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)) {
+ /* Exactly 9 hex digits */
+ 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);
+}
+#endif /* __WIN32__ */
/*
* Local Variables:
* mode: c
diff --git a/generic/tkCursor.c b/generic/tkCursor.c
index 54184b3..2bbf861 100644
--- a/generic/tkCursor.c
+++ b/generic/tkCursor.c
@@ -351,11 +351,11 @@ Tk_GetCursorFromData(
* 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, "\"", 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, "\"", NULL);
goto error;
}
diff --git a/generic/tkImgBmap.c b/generic/tkImgBmap.c
index 87c6283..82374cb 100644
--- a/generic/tkImgBmap.c
+++ b/generic/tkImgBmap.c
@@ -1247,7 +1247,7 @@ ImgBmapPostscript(
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;
@@ -1269,7 +1269,7 @@ ImgBmapPostscript(
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 7d8bf0d..5b172f1 100644
--- a/generic/tkImgPhoto.c
+++ b/generic/tkImgPhoto.c
@@ -918,7 +918,7 @@ ImgPhotoCmd(
}
}
- if (!XParseColor(Tk_Display(tkwin), Tk_Colormap(tkwin),
+ if (!TkParseColor(Tk_Display(tkwin), Tk_Colormap(tkwin),
colorString, &color)) {
Tcl_AppendResult(interp, "can't parse color \"",
colorString, "\"", NULL);
diff --git a/generic/tkInt.h b/generic/tkInt.h
index 51bc896..4faf908 100644
--- a/generic/tkInt.h
+++ b/generic/tkInt.h
@@ -1211,6 +1211,14 @@ MODULE_SCOPE int TkInitFontchooser(Tcl_Interp *interp,
ClientData clientData);
MODULE_SCOPE void TkpWarpPointer(TkDisplay *dispPtr);
+#ifdef __WIN32__
+#define TkParseColor XParseColor
+#else
+MODULE_SCOPE Status TkParseColor (Display * display,
+ Colormap map, _Xconst char* spec,
+ XColor * colorPtr);
+#endif
+
/*
* Unsupported commands.
*/
diff --git a/generic/tkStubInit.c b/generic/tkStubInit.c
index 2b87360..c62d143 100644
--- a/generic/tkStubInit.c
+++ b/generic/tkStubInit.c
@@ -44,6 +44,12 @@ MODULE_SCOPE const TkStubs tkStubs;
#undef Tk_MainEx
+#ifndef __WIN32__
+/* Make sure that extensions which call XParseColor through
+ * the stub table, call TkParseColor in stead. See bug #3486474 */
+# define XParseColor TkParseColor
+#endif
+
/* !BEGIN!: Do not edit below this line. */
static const TkIntStubs tkIntStubs = {
diff --git a/macosx/tkMacOSXColor.c b/macosx/tkMacOSXColor.c
index 3cd7c66..ebbaec2 100644
--- a/macosx/tkMacOSXColor.c
+++ b/macosx/tkMacOSXColor.c
@@ -606,7 +606,7 @@ TkpGetColor(
}
}
- if (XParseColor(display, colormap, name, &color) == 0) {
+ if (TkParseColor(display, colormap, name, &color) == 0) {
return NULL;
}
diff --git a/unix/tkUnixColor.c b/unix/tkUnixColor.c
index afa9d24..df754bd 100644
--- a/unix/tkUnixColor.c
+++ b/unix/tkUnixColor.c
@@ -166,7 +166,7 @@ TkpGetColor(
FindClosestColor(tkwin, &screen, &color);
}
} else {
- if (XParseColor(display, colormap, buf, &color) == 0) {
+ if (TkParseColor(display, colormap, buf, &color) == 0) {
return NULL;
}
if (XAllocColor(display, colormap, &color) != 0) {
diff --git a/unix/tkUnixCursor.c b/unix/tkUnixCursor.c
index 1603ee3..bbf5206 100644
--- a/unix/tkUnixCursor.c
+++ b/unix/tkUnixCursor.c
@@ -274,7 +274,7 @@ TkGetCursorByName(
fg.red = fg.green = fg.blue = 0;
bg.red = bg.green = bg.blue = 65535;
} else {
- if (XParseColor(display, Tk_Colormap(tkwin), argv[1], &fg) == 0) {
+ if (TkParseColor(display, Tk_Colormap(tkwin), argv[1], &fg) == 0) {
Tcl_AppendResult(interp, "invalid color name \"", argv[1],
"\"", NULL);
goto cleanup;
@@ -282,7 +282,7 @@ TkGetCursorByName(
if (argc == 2) {
bg.red = bg.green = bg.blue = 0;
maskIndex = namePtr->shape;
- } else if (XParseColor(display, Tk_Colormap(tkwin), argv[2],
+ } else if (TkParseColor(display, Tk_Colormap(tkwin), argv[2],
&bg) == 0) {
Tcl_AppendResult(interp, "invalid color name \"", argv[2],
"\"", NULL);
@@ -456,7 +456,7 @@ CreateCursorFromTableOrFile(
bg.red = bg.green = bg.blue = 65535;
} else if (argc == 2) {
fgColor = argv[1];
- if (XParseColor(display, Tk_Colormap(tkwin), fgColor, &fg) == 0) {
+ if (TkParseColor(display, Tk_Colormap(tkwin), fgColor, &fg) == 0) {
Tcl_AppendResult(interp, "invalid color name \"",
fgColor, "\"", NULL);
goto cleanup;
@@ -475,12 +475,12 @@ CreateCursorFromTableOrFile(
fgColor = argv[2];
bgColor = argv[3];
}
- if (XParseColor(display, Tk_Colormap(tkwin), fgColor, &fg) == 0) {
+ if (TkParseColor(display, Tk_Colormap(tkwin), fgColor, &fg) == 0) {
Tcl_AppendResult(interp, "invalid color name \"",
fgColor, "\"", NULL);
goto cleanup;
}
- if (XParseColor(display, Tk_Colormap(tkwin), bgColor, &bg) == 0) {
+ if (TkParseColor(display, Tk_Colormap(tkwin), bgColor, &bg) == 0) {
Tcl_AppendResult(interp, "invalid color name \"",
bgColor, "\"", NULL);
goto cleanup;
diff --git a/win/tkWinColor.c b/win/tkWinColor.c
index 0057573..d93143d 100644
--- a/win/tkWinColor.c
+++ b/win/tkWinColor.c
@@ -180,7 +180,7 @@ TkpGetColor(
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 = ckalloc(sizeof(WinColor));
winColPtr->info.color = color;
diff --git a/xlib/xcolors.c b/xlib/xcolors.c
index be9e479..0f3085c 100644
--- a/xlib/xcolors.c
+++ b/xlib/xcolors.c
@@ -879,24 +879,33 @@ XParseColor(
XColor *colorPtr)
{
if (spec[0] == '#') {
- char fmt[16];
- int i, red, green, blue;
+ char *p;
+ Tcl_WideInt value = _strtoi64(++spec, &p, 16);
- 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) {
+ 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;
}
- 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);
} else {
if (!FindColor(spec, colorPtr)) {
return 0;