summaryrefslogtreecommitdiffstats
path: root/unix
diff options
context:
space:
mode:
authorgriffin <briang42@easystreet.net>2023-01-24 00:26:09 (GMT)
committergriffin <briang42@easystreet.net>2023-01-24 00:26:09 (GMT)
commit9d09beabe5d3ec53df4cbcce6014f50453e6254d (patch)
tree41ec262936af90e0742d867bacbdaf0a30ff10c7 /unix
parent772967c2e7aaf60a4956b9b54a46791761df7036 (diff)
downloadtk-9d09beabe5d3ec53df4cbcce6014f50453e6254d.zip
tk-9d09beabe5d3ec53df4cbcce6014f50453e6254d.tar.gz
tk-9d09beabe5d3ec53df4cbcce6014f50453e6254d.tar.bz2
Combine scaling-aware-classic-simple implemenation with 3D check and radio button images. Improve icon placement.
Diffstat (limited to 'unix')
-rw-r--r--unix/tkUnixButton.c521
1 files changed, 303 insertions, 218 deletions
diff --git a/unix/tkUnixButton.c b/unix/tkUnixButton.c
index 6f24c9e..ed00517 100644
--- a/unix/tkUnixButton.c
+++ b/unix/tkUnixButton.c
@@ -38,94 +38,165 @@ typedef struct UnixButton {
const Tk_ClassProcs tkpButtonProcs = {
sizeof(Tk_ClassProcs), /* size */
TkButtonWorldChanged, /* worldChangedProc */
- NULL, /* createProc */
- NULL /* modalProc */
+ NULL, /* createProc */
+ NULL /* modalProc */
};
/*
- * The button image.
- * The header info here is ignored, it's the image that's important. The
- * colors will be applied as follows:
- * A = Background
- * B = Background
- * C = 3D light
- * D = selectColor
- * E = 3D dark
- * F = Background
- * G = Indicator Color
- * H = disabled Indicator Color
+ * Indicator draw modes
*/
-/* XPM */
-static const char *const button_images[] = {
- /* width height ncolors chars_per_pixel */
- "52 26 7 1",
- /* colors */
- "A c #808000000000",
- "B c #000080800000",
- "C c #808080800000",
- "D c #000000008080",
- "E c #808000008080",
- "F c #000080808080",
- "G c #000000000000",
- "H c #000080800000",
- /* pixels */
- "AAAAAAAAAAAABAAAAAAAAAAAABAAAAAAAAAAAABAAAAAAAAAAAAB",
- "AEEEEEEEEEECBAEEEEEEEEEECBAEEEEEEEEEECBAEEEEEEEEEECB",
- "AEDDDDDDDDDCBAEDDDDDDDDDCBAEFFFFFFFFFCBAEFFFFFFFFFCB",
- "AEDDDDDDDDDCBAEDDDDDDDGDCBAEFFFFFFFFFCBAEFFFFFFFHFCB",
- "AEDDDDDDDDDCBAEDDDDDDGGDCBAEFFFFFFFFFCBAEFFFFFFHHFCB",
- "AEDDDDDDDDDCBAEDGDDDGGGDCBAEFFFFFFFFFCBAEFHFFFHHHFCB",
- "AEDDDDDDDDDCBAEDGGDGGGDDCBAEFFFFFFFFFCBAEFHHFHHHFFCB",
- "AEDDDDDDDDDCBAEDGGGGGDDDCBAEFFFFFFFFFCBAEFHHHHHFFFCB",
- "AEDDDDDDDDDCBAEDDGGGDDDDCBAEFFFFFFFFFCBAEFFHHHFFFFCB",
- "AEDDDDDDDDDCBAEDDDGDDDDDCBAEFFFFFFFFFCBAEFFFHFFFFFCB",
- "AEDDDDDDDDDCBAEDDDDDDDDDCBAEFFFFFFFFFCBAEFFFFFFFFFCB",
- "ACCCCCCCCCCCBACCCCCCCCCCCBACCCCCCCCCCCBACCCCCCCCCCCB",
- "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB",
- "FFFFAAAAFFFFFFFFFAAAAFFFFFFFFFAAAAFFFFFFFFFAAAAFFFFF",
- "FFAAEEEEAAFFFFFAAEEEEAAFFFFFAAEEEEAAFFFFFAAEEEEAAFFF",
- "FAEEDDDDEEBFFFAEEDDDDEEBFFFAEEFFFFEEBFFFAEEFFFFEEBFF",
- "FAEDDDDDDCBFFFAEDDDDDDCBFFFAEFFFFFFCBFFFAEFFFFFFCBFF",
- "AEDDDDDDDDCBFAEDDDGGDDDCBFAEFFFFFFFFCBFAEFFFHHFFFCBF",
- "AEDDDDDDDDCBFAEDDGGGGDDCBFAEFFFFFFFFCBFAEFFHHHHFFCBF",
- "AEDDDDDDDDCBFAEDDGGGGDDCBFAEFFFFFFFFCBFAEFFHHHHFFCBF",
- "AEDDDDDDDDCBFAEDDDGGDDDCBFAEFFFFFFFFCBFAEFFFHHFFFCBF",
- "FAEDDDDDDCBFFFAEDDDDDDCBFFFAEFFFFFFCBFFFAEFFFFFFCBFF",
- "FACCDDDDCCBFFFACCDDDDCCBFFFACCFFFFCCBFFFACCFFFFCCBFF",
- "FFBBCCCCBBFFFFFBBCCCCBBFFFFFBBCCCCBBFFFFFBBCCCCBBFFF",
- "FFFFBBBBFFFFFFFFFBBBBFFFFFFFFFBBBBFFFFFFFFFBBBBFFFFF",
- "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
-};
+#define CHECK_BUTTON 0
+#define CHECK_MENU 1
+#define RADIO_BUTTON 2
+#define RADIO_MENU 3
/*
- * Sizes and offsets into above XPM file.
+ * Indicator sizes
*/
-#define CHECK_BUTTON_DIM 13
-#define CHECK_MENU_DIM 9
-#define CHECK_START 9
-#define CHECK_ON_OFFSET 13
-#define CHECK_OFF_OFFSET 0
-#define CHECK_DISON_OFFSET 39
-#define CHECK_DISOFF_OFFSET 26
-#define RADIO_BUTTON_DIM 12
-#define RADIO_MENU_DIM 6
-#define RADIO_WIDTH 13
-#define RADIO_START 22
-#define RADIO_ON_OFFSET 13
-#define RADIO_OFF_OFFSET 0
-#define RADIO_DISON_OFFSET 39
-#define RADIO_DISOFF_OFFSET 26
+#define CHECK_BUTTON_DIM 16
+#define CHECK_MENU_DIM 8
+#define RADIO_BUTTON_DIM 16
+#define RADIO_MENU_DIM 8
/*
- * Indicator Draw Modes
+ * The SVG images used here are based on some icons provided by the
+ * official open source SVG icon library for the Bootstrap project,
+ * licensed under the MIT license (https://opensource.org/licenses/MIT).
+ *
+ * See https://github.com/twbs/icons.
*/
-#define CHECK_BUTTON 0
-#define CHECK_MENU 1
-#define RADIO_BUTTON 2
-#define RADIO_MENU 3
+static const char *const checkbtnOffData =
+" <svg id='classiccheckbox' width='16' height='16' version='1.1' xmlns='http://www.w3.org/2000/svg'>\n"
+" <defs id='defs325'>\n"
+" <linearGradient id='linearGradientLeft' gradientUnits='userSpaceOnUse'\n"
+" x1='2' y1='7.5' x2='2' y2='7.5'>\n"
+" <stop style='stop-color:#DARKKK;stop-opacity:1;' offset='1' id='stop1885' />\n"
+" <stop style='stop-color:#000000;stop-opacity:1;' offset='0' id='stop1887' />\n"
+" </linearGradient>\n"
+" <linearGradient id='LinearGradientBottom' gradientUnits='userSpaceOnUse'\n"
+" x1='7.5' y1='16' x2='7.5' y2='15'>\n"
+" <stop style='stop-color:#LIGHTT;stop-opacity:1;' offset='0' id='stop2672' />\n"
+" <stop style='stop-color:#ffffff;stop-opacity:1;' offset='1' id='stop2674' />\n"
+" </linearGradient>\n"
+" <linearGradient id='linearGradientRight' gradientUnits='userSpaceOnUse'\n"
+" x1='16' y1='7.5' x2='16' y2='7.5'>\n"
+" <stop style='stop-color:#LIGHTT;stop-opacity:1;' offset='0' id='stop2672' />\n"
+" <stop style='stop-color:#ffffff;stop-opacity:1;' offset='1' id='stop2674' />\n"
+" </linearGradient>\n"
+" <linearGradient id='linearGradientTop' gradientUnits='userSpaceOnUse'\n"
+" x1='7.5' y1='1.5' x2='7.5' y2='1.5'>\n"
+" <stop style='stop-color:#DARKKK;stop-opacity:1;' offset='1' id='stop1885' />\n"
+" <stop style='stop-color:#000000;stop-opacity:1;' offset='0' id='stop1887' />\n"
+" </linearGradient>\n"
+" </defs>\n"
+" <g id='layer1'>\n"
+" <rect id='rectbackdrop'\n"
+" style='fill:#INTROR;stroke-width:11;paint-order:stroke markers fill;fill-opacity:1'\n"
+" width='12' height='12' x='2' y='2' />\n"
+" <path id='recttopside'\n"
+" style='stroke-width:10.16;paint-order:stroke markers fill;fill-opacity:1;fill:url(#linearGradientTop)'\n"
+" d='M 0,0 L 13,0 12,1 1,1 0,0' />\n"
+" <path id='rectleftside'\n"
+" style='stroke-width:10.16;paint-order:stroke markers fill;fill-opacity:1;fill:url(#linearGradientLeft)'\n"
+" d='M 0,0 L 1,1 1,12 0,13' />\n"
+" <path id='rectrightside'\n"
+" style='stroke-width:10.16;paint-order:stroke markers fill;fill-opacity:1;fill:url(#linearGradientRight)'\n"
+" d='M 13,0 L 12,1 12,12 13,13 13,0' />\n"
+" <path id='rectbottomside'\n"
+" style='stroke-width:10.16;paint-order:stroke markers fill;fill-opacity:1;fill:url(#LinearGradientBottom)'\n"
+" d='M 0,13 L 1,12 12,12 13,13 0,13' />\n"
+" </g>\n"
+"</svg>";
+
+static const char *const checkbtnOnData =
+" <svg id='classiccheckbox' width='16' height='16' version='1.1' xmlns='http://www.w3.org/2000/svg'>\n"
+" <defs id='defs325'>\n"
+" <linearGradient id='linearGradientLeft' gradientUnits='userSpaceOnUse'\n"
+" x1='2' y1='7.5' x2='2' y2='7.5'>\n"
+" <stop style='stop-color:#DARKKK;stop-opacity:1;' offset='1' id='stop1885' />\n"
+" <stop style='stop-color:#000000;stop-opacity:1;' offset='0' id='stop1887' />\n"
+" </linearGradient>\n"
+" <linearGradient id='LinearGradientBottom' gradientUnits='userSpaceOnUse'\n"
+" x1='7.5' y1='16' x2='7.5' y2='15'>\n"
+" <stop style='stop-color:#LIGHTT;stop-opacity:1;' offset='0' id='stop2672' />\n"
+" <stop style='stop-color:#ffffff;stop-opacity:1;' offset='1' id='stop2674' />\n"
+" </linearGradient>\n"
+" <linearGradient id='linearGradientRight' gradientUnits='userSpaceOnUse'\n"
+" x1='16' y1='7.5' x2='16' y2='7.5'>\n"
+" <stop style='stop-color:#LIGHTT;stop-opacity:1;' offset='0' id='stop2672' />\n"
+" <stop style='stop-color:#ffffff;stop-opacity:1;' offset='1' id='stop2674' />\n"
+" </linearGradient>\n"
+" <linearGradient id='linearGradientTop' gradientUnits='userSpaceOnUse'\n"
+" x1='7.5' y1='1.5' x2='7.5' y2='1.5'>\n"
+" <stop style='stop-color:#DARKKK;stop-opacity:1;' offset='1' id='stop1885' />\n"
+" <stop style='stop-color:#000000;stop-opacity:1;' offset='0' id='stop1887' />\n"
+" </linearGradient>\n"
+" </defs>\n"
+" <g id='layer1'>\n"
+" <rect id='rectbackdrop'\n"
+" style='fill:#INTROR;stroke-width:11;paint-order:stroke markers fill;fill-opacity:1'\n"
+" width='12' height='12' x='2' y='2' />\n"
+" <path id='recttopside'\n"
+" style='stroke-width:10.16;paint-order:stroke markers fill;fill-opacity:1;fill:url(#linearGradientTop)'\n"
+" d='M 0,0 L 13,0 12,1 1,1 0,0' />\n"
+" <path id='rectleftside'\n"
+" style='stroke-width:10.16;paint-order:stroke markers fill;fill-opacity:1;fill:url(#linearGradientLeft)'\n"
+" d='M 0,0 L 1,1 1,12 0,13' />\n"
+" <path id='rectrightside'\n"
+" style='stroke-width:10.16;paint-order:stroke markers fill;fill-opacity:1;fill:url(#linearGradientRight)'\n"
+" d='M 13,0 L 12,1 12,12 13,13 13,0' />\n"
+" <path id='rectbottomside'\n"
+" style='stroke-width:10.16;paint-order:stroke markers fill;fill-opacity:1;fill:url(#LinearGradientBottom)'\n"
+" d='M 0,13 L 1,12 12,12 13,13 0,13' />\n"
+" <path id='indicator'\n"
+" style='fill:none;stroke:#INDCTR;stroke-width:2px;stroke-linecap:butt;stroke-linejoin:miter;paint-order:stroke markers fill;stroke-opacity:1'\n"
+" d='M 3,7 L 6,10 10,3' />\n"
+" </g>\n"
+"</svg>";
+
+static const char *const radiobtnOffData =
+ "<svg width='16px' height='16px' version='1.1' id='radiobutton' xmlns:svg='http://www.w3.org/2000/svg'>\n"
+ " <defs id='defs4785'>\n"
+ " <linearGradient id='gradient1' x1='2' y1='2' x2='11' y2='11' gradientUnits='userSpaceOnUse'>\n"
+ " <stop id='stop0' style='stop-color:#DARKKK;stop-opacity:1;' offset='0' />\n"
+ " <stop id='stop1' style='stop-color:#LIGHTT;stop-opacity:0;' offset='1' />\n"
+ " </linearGradient>\n"
+ " </defs>\n"
+ " <circle id='path4803' cx='8' cy='8' r='8' style='fill:url(#gradient1);fill-opacity:1;fill-rule:evenodd;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none' />\n"
+ " <circle id='path4803-6' cx='8' cy='8' r='6.5' style='fill:#INTROR;fill-opacity:1;fill-rule:evenodd;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none'/>\n"
+ "</svg>";
+
+static const char *const radiobtnOnData =
+ "<svg width='16px' height='16px' version='1.1' id='radiobutton' xmlns:svg='http://www.w3.org/2000/svg'>\n"
+ " <defs id='defs4785'>\n"
+ " <linearGradient id='gradient1' x1='2' y1='2' x2='11' y2='11' gradientUnits='userSpaceOnUse'>\n"
+ " <stop id='stop0' style='stop-color:#DARKKK;stop-opacity:1;' offset='0' />\n"
+ " <stop id='stop1' style='stop-color:#LIGHTT;stop-opacity:0;' offset='1' />\n"
+ " </linearGradient>\n"
+ " </defs>\n"
+ " <circle id='path4803' cx='8' cy='8' r='8' style='fill:url(#gradient1);fill-opacity:1;fill-rule:evenodd;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none' />\n"
+ " <circle id='path4803-6' cx='8' cy='8' r='7' style='fill:#INTROR;fill-opacity:1;fill-rule:evenodd;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none'/>\n"
+ " <circle id='path4820' cx='8' cy='8' r='4' style='fill:#INDCTR;fill-opacity:1;fill-rule:evenodd;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none'/>\n"
+ "</svg>";
+
+static const char *const menuOffData =
+" <svg width='8' height='8' version='1.1' viewBox='0 0 8 8' xmlns='http://www.w3.org/2000/svg'></svg>\n";
+
+static const char *const checkmenuOnData =
+" <svg width='8' height='8' version='1.1' viewBox='0 0 8 8' xmlns='http://www.w3.org/2000/svg'>\n"
+" <path id='indicator'\n"
+" style='fill:none;stroke:#INDCTR;stroke-width:2px;stroke-linecap:butt;stroke-linejoin:miter;paint-order:stroke markers fill;stroke-opacity:1'\n"
+" d='M 0,3 L 4,7 8,0' />\n"
+" </svg>";
+
+static const char *const radiomenuOnData =
+" <svg width='8' height='8' version='1.1' viewBox='0 0 8 8' xmlns='http://www.w3.org/2000/svg'>\n"
+" <circle id='path4820' cx='4' cy='4' r='3' style='fill:#INDCTR;fill-opacity:1;fill-rule:evenodd;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none'/>\n"
+" </svg>";
+
/*
*----------------------------------------------------------------------
@@ -133,7 +204,7 @@ static const char *const button_images[] = {
* TkpDrawCheckIndicator -
*
* Draws the checkbox image in the drawable at the (x,y) location, value,
- * and state given. This routine is use by the button and menu widgets
+ * and state given. This routine is used by the button and menu widgets.
*
* Results:
* None.
@@ -144,6 +215,30 @@ static const char *const button_images[] = {
*----------------------------------------------------------------------
*/
+static void
+ColorToStr(
+ const XColor *colorPtr, /* specifies a color */
+ char *colorStr) /* memory area to which the color is to be
+ output in the format "RRGGBB" */
+{
+ char str[13];
+
+ snprintf(str, sizeof(str), "%04x%04x%04x",
+ colorPtr->red, colorPtr->green, colorPtr->blue);
+ snprintf(colorStr, 7, "%.2s%.2s%.2s", str, str + 4, str + 8);
+}
+
+static void
+ImageChanged( /* to be passed to Tk_GetImage() */
+ ClientData clientData,
+ int x, int y, int width, int height,
+ int imageWidth, int imageHeight)
+{
+ (void)clientData;
+ (void)x; (void)y; (void)width; (void)height;
+ (void)imageWidth; (void)imageHeight;
+}
+
void
TkpDrawCheckIndicator(
Tk_Window tkwin, /* handle for resource alloc */
@@ -158,19 +253,23 @@ TkpDrawCheckIndicator(
int disabled, /* are we disabled? */
int mode) /* kind of indicator to draw */
{
- int ix, iy;
- int dim;
- int imgsel, imgstart;
+ const char *svgDataPtr;
+ int hasBorder, hasInterior, dim;
TkBorder *bg_brdr = (TkBorder*)bgBorder;
- XGCValues gcValues;
- GC copyGC;
- unsigned long imgColors[8];
- XImage *img;
- Pixmap pixmap;
- int depth;
+ char borderColorStr[7], lightColorStr[7], interiorColorStr[7], indicatorColorStr[7];
+ char imgName[50];
+ Tk_Image img;
+ size_t svgDataLen;
+ char *svgDataCopy;
+ char *borderColorPtr, *lightColorPtr, *interiorColorPtr, *indicatorColorPtr;
+ Tcl_Interp *interp = Tk_Interp(tkwin);
+ char *script;
+ int code;
+ const char *scalingPctPtr;
+ double scalingFactor;
/*
- * Sanity check.
+ * Sanity check
*/
if (tkwin == NULL || display == NULL || d == None || bgBorder == NULL
@@ -186,128 +285,161 @@ TkpDrawCheckIndicator(
selectColor = bg_brdr->bgColorPtr;
}
- depth = Tk_Depth(tkwin);
-
/*
- * Compute starting point and dimensions of image inside button_images to
- * be used.
+ * Determine the SVG data to use for the
+ * photo image and the latter's dimensions
*/
switch (mode) {
default:
case CHECK_BUTTON:
- imgsel = on == 2 ? CHECK_DISON_OFFSET :
- on == 1 ? CHECK_ON_OFFSET : CHECK_OFF_OFFSET;
- imgsel += disabled && on != 2 ? CHECK_DISOFF_OFFSET : 0;
- imgstart = CHECK_START;
+ svgDataPtr = (on == 0 ? checkbtnOffData : checkbtnOnData);
+ hasBorder = 1; hasInterior = 1;
dim = CHECK_BUTTON_DIM;
break;
case CHECK_MENU:
- imgsel = on == 2 ? CHECK_DISOFF_OFFSET :
- on == 1 ? CHECK_ON_OFFSET : CHECK_OFF_OFFSET;
- imgsel += disabled && on != 2 ? CHECK_DISOFF_OFFSET : 0;
- imgstart = CHECK_START + 2;
- imgsel += 2;
+ svgDataPtr = (on == 0 ? menuOffData : checkmenuOnData);
+ hasBorder = 0; hasInterior = 0;
dim = CHECK_MENU_DIM;
break;
case RADIO_BUTTON:
- imgsel = on == 2 ? RADIO_DISON_OFFSET :
- on==1 ? RADIO_ON_OFFSET : RADIO_OFF_OFFSET;
- imgsel += disabled && on != 2 ? RADIO_DISOFF_OFFSET : 0;
- imgstart = RADIO_START;
+ svgDataPtr = (on == 0 ? radiobtnOffData : radiobtnOnData);
+ hasBorder = 1; hasInterior = 1;
dim = RADIO_BUTTON_DIM;
break;
case RADIO_MENU:
- imgsel = on == 2 ? RADIO_DISOFF_OFFSET :
- on==1 ? RADIO_ON_OFFSET : RADIO_OFF_OFFSET;
- imgsel += disabled && on != 2 ? RADIO_DISOFF_OFFSET : 0;
- imgstart = RADIO_START + 3;
- imgsel += 3;
+ svgDataPtr = (on == 0 ? menuOffData : radiomenuOnData);
+ hasBorder = 0; hasInterior = 0;
dim = RADIO_MENU_DIM;
break;
}
/*
- * Allocate the drawing areas to use. Note that we use double-buffering
- * here because not all code paths leading to this function do so.
+ * Construct the color strings borderColorStr,
+ * interiorColorStr, and indicatorColorStr
*/
- pixmap = Tk_GetPixmap(display, d, dim, dim, depth);
- if (pixmap == None) {
- return;
- }
-
- x -= dim/2;
- y -= dim/2;
+ TkpGetShadows(bg_brdr, tkwin);
- img = XGetImage(display, pixmap, 0, 0,
- (unsigned int)dim, (unsigned int)dim, AllPlanes, ZPixmap);
- if (img == NULL) {
- return;
+ if (bg_brdr->darkColorPtr == NULL) {
+ strcpy(borderColorStr, "000000");
+ } else {
+ ColorToStr(Tk_GetColorByValue(tkwin, bg_brdr->darkColorPtr),
+ borderColorStr);
+ }
+ if (bg_brdr->lightColorPtr == NULL) {
+ strcpy(lightColorStr, "ffffff");
+ } else {
+ ColorToStr(Tk_GetColorByValue(tkwin, bg_brdr->lightColorPtr),
+ lightColorStr);
+ }
+ if (on == 2 || disabled) { /* tri-state or disabled */
+ ColorToStr(Tk_GetColorByValue(tkwin, bg_brdr->bgColorPtr),
+ interiorColorStr);
+ ColorToStr(Tk_GetColorByValue(tkwin, disableColor),
+ indicatorColorStr);
+ } else {
+ ColorToStr(Tk_GetColorByValue(tkwin, selectColor),
+ interiorColorStr);
+ ColorToStr(Tk_GetColorByValue(tkwin, indicatorColor),
+ indicatorColorStr);
}
/*
- * Set up the color mapping table.
+ * Check whether there is an SVG image for
+ * the value of mode and these color strings
*/
- TkpGetShadows(bg_brdr, tkwin);
+ snprintf(imgName, sizeof(imgName), "::tk::icons::indicator%d_%s_%s_%s",
+ mode,
+ hasBorder ? borderColorStr : "XXXXXX",
+ hasInterior ? interiorColorStr : "XXXXXX",
+ on ? indicatorColorStr : "XXXXXX");
+ img = Tk_GetImage(interp, tkwin, imgName, ImageChanged, NULL);
+ if (img == NULL) {
+ /*
+ * Copy the string pointed to by svgDataPtr to a newly allocated memory
+ * area svgDataCopy and assign the latter's address to svgDataPtr
+ */
- imgColors[0 /*A*/] = /* BorderBackground */
- Tk_GetColorByValue(tkwin, bg_brdr->bgColorPtr)->pixel;
- imgColors[1 /*B*/] = /* BorderBackground */
- Tk_GetColorByValue(tkwin, bg_brdr->bgColorPtr)->pixel;
- imgColors[2 /*C*/] = /* BorderLightColor */
- (bg_brdr->lightColorPtr != NULL) ?
- Tk_GetColorByValue(tkwin, bg_brdr->lightColorPtr)->pixel :
- WhitePixelOfScreen(bg_brdr->screen);
- imgColors[3 /*D*/] = /* SelectColor */
- Tk_GetColorByValue(tkwin, selectColor)->pixel;
- imgColors[4 /*E*/] = /* BorderDarkColor */
- (bg_brdr->darkColorPtr != NULL) ?
- Tk_GetColorByValue(tkwin, bg_brdr->darkColorPtr)->pixel :
- BlackPixelOfScreen(bg_brdr->screen);
- imgColors[5 /*F*/] = /* BorderBackground */
- Tk_GetColorByValue(tkwin, bg_brdr->bgColorPtr)->pixel;
- imgColors[6 /*G*/] = /* IndicatorColor */
- Tk_GetColorByValue(tkwin, indicatorColor)->pixel;
- imgColors[7 /*H*/] = /* DisableColor */
- Tk_GetColorByValue(tkwin, disableColor)->pixel;
+ svgDataLen = strlen(svgDataPtr);
+ svgDataCopy = (char *)attemptckalloc(svgDataLen + 1);
+ if (svgDataCopy == NULL) {
+ return;
+ }
+ memcpy(svgDataCopy, svgDataPtr, svgDataLen);
+ svgDataCopy[svgDataLen] = '\0';
+ svgDataPtr = svgDataCopy;
- /*
- * Create the image, painting it into an XImage one pixel at a time.
- */
+ /*
+ * Update the colors within svgDataCopy
+ */
- for (iy=0 ; iy<dim ; iy++) {
- for (ix=0 ; ix<dim ; ix++) {
- XPutPixel(img, ix, iy,
- imgColors[button_images[imgstart+iy][imgsel+ix] - 'A']);
+ borderColorPtr = strstr(svgDataPtr, "DARKKK"); //888888
+ lightColorPtr = strstr(svgDataPtr, "LIGHTT"); //
+ interiorColorPtr = strstr(svgDataPtr, "INTROR"); //ffffff
+ indicatorColorPtr = strstr(svgDataPtr, "INDCTR"); //000000
+
+ while (borderColorPtr != NULL) {
+ memcpy(borderColorPtr, borderColorStr, 6);
+ borderColorPtr = strstr(borderColorPtr, "DARKKK"); //888888
+ }
+ while (lightColorPtr != NULL) {
+ memcpy(lightColorPtr, lightColorStr, 6);
+ lightColorPtr = strstr(lightColorPtr, "LIGHTT"); //888888
+ }
+ while (interiorColorPtr != NULL) {
+ memcpy(interiorColorPtr, interiorColorStr, 6);
+ interiorColorPtr = strstr(interiorColorPtr, "INTROR"); //ffffff
}
+ while (indicatorColorPtr != NULL) {
+ memcpy(indicatorColorPtr, indicatorColorStr, 6);
+ indicatorColorPtr = strstr(indicatorColorPtr, "INDCTR"); //000000
+ }
+
+ /*
+ * Create an SVG photo image from svgDataCopy
+ */
+ const char *cmdfmt = "image create photo %s -format $::tk::svgFmt -data {%s}";
+ size_t scriptsz = strlen(cmdfmt) + strlen(imgName) + svgDataLen;
+ script = (char *)attemptckalloc(scriptsz);
+ if (script == NULL) {
+ ckfree(svgDataCopy);
+ return;
+ }
+ snprintf(script, scriptsz, cmdfmt, imgName, svgDataCopy);
+ ckfree(svgDataCopy);
+ code = Tcl_EvalEx(interp, script, -1, TCL_EVAL_GLOBAL);
+ ckfree(script);
+ if (code != TCL_OK) {
+ Tcl_BackgroundException(interp, code);
+ return;
+ }
+ img = Tk_GetImage(interp, tkwin, imgName, ImageChanged, NULL);
}
/*
- * Copy onto our target drawable surface.
+ * Retrieve the scaling factor and multiply dim by it
*/
- memset(&gcValues, 0, sizeof(gcValues));
- gcValues.background = bg_brdr->bgColorPtr->pixel;
- gcValues.graphics_exposures = False;
- copyGC = Tk_GetGC(tkwin, 0, &gcValues);
-
- XPutImage(display, pixmap, copyGC, img, 0, 0, 0, 0,
- (unsigned)dim, (unsigned)dim);
- XCopyArea(display, pixmap, d, copyGC, 0, 0,
- (unsigned)dim, (unsigned)dim, x, y);
+ scalingPctPtr = Tcl_GetVar(interp, "::tk::scalingPct", TCL_GLOBAL_ONLY);
+ if (scalingPctPtr == NULL) {
+ scalingPctPtr = "100";
+ }
+ scalingFactor = atof(scalingPctPtr) / 100; /* 1.0, 1.25, 1.5, 1.75, ... */
+ dim *= scalingFactor;
/*
- * Tidy up.
+ * Adjust the image's coordinates in the drawable and display the image
*/
- Tk_FreeGC(display, copyGC);
- XDestroyImage(img);
- Tk_FreePixmap(display, pixmap);
+ x -= dim/2;
+ y -= dim/2;
+ Tk_RedrawImage(img, 0, 0, dim, dim, d, x, y);
+ Tk_FreeImage(img);
}
@@ -492,9 +624,6 @@ TkpDisplayButton(
} else if (butPtr->bitmap != None) {
Tk_SizeOfBitmap(butPtr->display, butPtr->bitmap, &width, &height);
haveImage = 1;
- } else if (butPtr->defImage[1] != NULL) {
- /* assume all 4 images are the same size by definition */
- Tk_SizeOfImage(butPtr->defImage[1], &width, &height);
}
imageWidth = width;
imageHeight = height;
@@ -694,58 +823,19 @@ TkpDisplayButton(
if (butPtr->indicatorDiameter > 2*butPtr->borderWidth) {
TkBorder *selBorder = (TkBorder *) butPtr->selectBorder;
XColor *selColor = NULL;
- int on = ((butPtr->flags & SELECTED) ? 1 : 0) |
- ((butPtr->flags & TRISTATED) ? 2 : 0);
if (selBorder != NULL) {
selColor = selBorder->bgColorPtr;
}
-
- /* Draw scalable image */
- if (butPtr->indicatorOn < 2 && butPtr->defImage[on]) {
-
- imageXOffset += (butPtr->indicatorSpace - imageWidth)/2;
- imageYOffset += (Tk_Height(tkwin) - imageHeight)/2;
-
- /*
- * Do boundary clipping, so that Tk_RedrawImage is passed
- * valid coordinates. [Bug 979239]
- */
-
- if (imageXOffset < 0) {
- imageXOffset = 0;
- }
- if (imageYOffset < 0) {
- imageYOffset = 0;
- }
- if (width > Tk_Width(tkwin)) {
- width = Tk_Width(tkwin);
- }
- if (height > Tk_Height(tkwin)) {
- height = Tk_Height(tkwin);
- }
- if ((width + imageXOffset) > Tk_Width(tkwin)) {
- imageXOffset = Tk_Width(tkwin) - width;
- }
- if ((height + imageYOffset) > Tk_Height(tkwin)) {
- imageYOffset = Tk_Height(tkwin) - height;
- }
-
- Tk_RedrawImage(butPtr->defImage[on], 0, 0, width, height,
- pixmap, imageXOffset, imageYOffset);
-
- } else {
- /* Draw old "classic" pixmap */
- x -= butPtr->indicatorSpace/2;
- y = Tk_Height(tkwin)/2;
- int btype = (butPtr->type == TYPE_CHECK_BUTTON ?
- CHECK_BUTTON : RADIO_BUTTON);
- TkpDrawCheckIndicator(tkwin, butPtr->display, pixmap, x, y,
+ x -= butPtr->indicatorSpace/2;
+ y = Tk_Height(tkwin)/2 + butPtr->borderWidth*2;
+ int btype = (butPtr->type == TYPE_CHECK_BUTTON ?
+ CHECK_BUTTON : RADIO_BUTTON);
+ TkpDrawCheckIndicator(tkwin, butPtr->display, pixmap, x, y,
border, butPtr->normalFg, selColor, butPtr->disabledFg,
((butPtr->flags & SELECTED) ? 1 :
- (butPtr->flags & TRISTATED) ? 2 : 0),
- (butPtr->state == STATE_DISABLED), btype);
- }
+ (butPtr->flags & TRISTATED) ? 2 : 0),
+ (butPtr->state == STATE_DISABLED), btype);
}
}
@@ -1018,11 +1108,6 @@ TkpComputeButtonGeometry(
}
if ((butPtr->type >= TYPE_CHECK_BUTTON) && butPtr->indicatorOn) {
butPtr->indicatorDiameter = fm.linespace;
- if (butPtr->indicatorOn /*> 1 && butPtr->type == TYPE_CHECK_BUTTON*/) {
- /* Scale down old classic pixmap */
- butPtr->indicatorDiameter =
- (80*butPtr->indicatorDiameter)/100;
- }
butPtr->indicatorSpace = butPtr->indicatorDiameter + avgWidth;
}
}