Skip to content

Commit

Permalink
Make a start with [610a73a179]: Canvas widget handles pixel objects i…
Browse files Browse the repository at this point in the history
…ncorrectly in Tk 9.0. WIP
  • Loading branch information
jan.nijtmans committed Aug 29, 2024
1 parent a47de2e commit 5bd07d4
Show file tree
Hide file tree
Showing 10 changed files with 104 additions and 36 deletions.
2 changes: 1 addition & 1 deletion generic/tk.h
Original file line number Diff line number Diff line change
Expand Up @@ -1193,7 +1193,7 @@ typedef struct Tk_Outline {
double width; /* Width of outline. */
double activeWidth; /* Width of outline. */
double disabledWidth; /* Width of outline. */
int offset; /* Dash offset. */
Tcl_Obj *offsetObj; /* Dash offset. */
Tk_Dash dash; /* Dash pattern. */
Tk_Dash activeDash; /* Dash pattern if state is active. */
Tk_Dash disabledDash; /* Dash pattern if state is disabled. */
Expand Down
2 changes: 1 addition & 1 deletion generic/tkCanvArc.c
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ static const Tk_ConfigSpec configSpecs[] = {
NULL, offsetof(ArcItem, outline.dash),
TK_CONFIG_NULL_OK, &dashOption},
{TK_CONFIG_PIXELS, "-dashoffset", NULL, NULL,
"0", offsetof(ArcItem, outline.offset), TK_CONFIG_DONT_SET_DEFAULT, NULL},
"0", offsetof(ArcItem, outline.offsetObj), TK_CONFIG_OBJS, NULL},
{TK_CONFIG_CUSTOM, "-disableddash", NULL, NULL,
NULL, offsetof(ArcItem, outline.disabledDash),
TK_CONFIG_NULL_OK, &dashOption},
Expand Down
2 changes: 1 addition & 1 deletion generic/tkCanvLine.c
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ static const Tk_ConfigSpec configSpecs[] = {
NULL, offsetof(LineItem, outline.dash),
TK_CONFIG_NULL_OK, &dashOption},
{TK_CONFIG_PIXELS, "-dashoffset", NULL, NULL,
"0", offsetof(LineItem, outline.offset), TK_CONFIG_DONT_SET_DEFAULT, NULL},
"0", offsetof(LineItem, outline.offsetObj), TK_CONFIG_OBJS, NULL},
{TK_CONFIG_CUSTOM, "-disableddash", NULL, NULL,
NULL, offsetof(LineItem, outline.disabledDash),
TK_CONFIG_NULL_OK, &dashOption},
Expand Down
3 changes: 1 addition & 2 deletions generic/tkCanvPoly.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,7 @@ static const Tk_ConfigSpec configSpecs[] = {
NULL, offsetof(PolygonItem, outline.dash),
TK_CONFIG_NULL_OK, &dashOption},
{TK_CONFIG_PIXELS, "-dashoffset", NULL, NULL,
"0", offsetof(PolygonItem, outline.offset),
TK_CONFIG_DONT_SET_DEFAULT, NULL},
"0", offsetof(PolygonItem, outline.offsetObj), TK_CONFIG_OBJS, NULL},
{TK_CONFIG_CUSTOM, "-disableddash", NULL, NULL,
NULL, offsetof(PolygonItem, outline.disabledDash),
TK_CONFIG_NULL_OK, &dashOption},
Expand Down
32 changes: 25 additions & 7 deletions generic/tkCanvUtil.c
Original file line number Diff line number Diff line change
Expand Up @@ -970,7 +970,7 @@ Tk_CreateOutline(
outline->width = 1.0;
outline->activeWidth = 0.0;
outline->disabledWidth = 0.0;
outline->offset = 0;
outline->offsetObj = NULL;
outline->dash.number = 0;
outline->activeDash.number = 0;
outline->disabledDash.number = 0;
Expand Down Expand Up @@ -1140,7 +1140,10 @@ Tk_ConfigOutlineGC(
}
if (mask && (dash->number != 0)) {
gcValues->line_style = LineOnOffDash;
gcValues->dash_offset = outline->offset;
if (!outline->offsetObj || Tk_GetPixelsFromObj(NULL, Canvas(canvas)->tkwin,
outline->offsetObj, &gcValues->dash_offset) != TCL_OK) {
gcValues->dash_offset = 0;
}
if ((unsigned int)ABS(dash->number) > sizeof(char *)) {
gcValues->dashes = dash->pattern.pt[0];
} else if (dash->number != 0) {
Expand Down Expand Up @@ -1183,11 +1186,16 @@ Tk_ChangeOutlineGC(
XColor *color;
Pixmap stipple;
Tk_State state = item->state;
int offset;

width = outline->width;
if (width < 1.0) {
width = 1.0;
}
if (!outline->offsetObj || Tk_GetPixelsFromObj(NULL, Canvas(canvas)->tkwin,
outline->offsetObj, &offset) != TCL_OK) {
offset = 0;
}
dash = &(outline->dash);
color = outline->color;
stipple = outline->stipple;
Expand Down Expand Up @@ -1233,13 +1241,13 @@ Tk_ChangeOutlineGC(
p = (i > (int)sizeof(char *)) ? dash->pattern.pt : dash->pattern.array;
q = (char *)ckalloc(2 * i);
i = DashConvert(q, p, i, width);
XSetDashes(Canvas(canvas)->display, outline->gc, outline->offset, q,i);
XSetDashes(Canvas(canvas)->display, outline->gc, offset, q,i);
ckfree(q);
} else if (dash->number>2 || (dash->number==2 &&
(dash->pattern.array[0]!=dash->pattern.array[1]))) {
p = (dash->number > (int) sizeof(char *))
? dash->pattern.pt : dash->pattern.array;
XSetDashes(Canvas(canvas)->display, outline->gc, outline->offset, p,
XSetDashes(Canvas(canvas)->display, outline->gc, offset, p,
dash->number);
}
if (stipple!=None) {
Expand Down Expand Up @@ -1301,11 +1309,16 @@ Tk_ResetOutlineGC(
XColor *color;
Pixmap stipple;
Tk_State state = item->state;
int offset;

width = outline->width;
if (width < 1.0) {
width = 1.0;
}
if (!outline->offsetObj || Tk_GetPixelsFromObj(NULL, Canvas(canvas)->tkwin,
outline->offsetObj, &offset) != TCL_OK) {
offset = 0;
}
dash = &(outline->dash);
color = outline->color;
stipple = outline->stipple;
Expand Down Expand Up @@ -1353,7 +1366,7 @@ Tk_ResetOutlineGC(
} else {
dashList = (char) (4 * width + 0.5);
}
XSetDashes(Canvas(canvas)->display, outline->gc, outline->offset,
XSetDashes(Canvas(canvas)->display, outline->gc, offset,
&dashList , 1);
}
if (stipple != None) {
Expand Down Expand Up @@ -1397,6 +1410,7 @@ Tk_CanvasPsOutline(
Pixmap stipple = outline->stipple;
Tk_State state = item->state;
Tcl_Obj *psObj = GetPostscriptBuffer(interp);
int offset;

if (state == TK_STATE_NULL) {
state = Canvas(canvas)->canvas_state;
Expand Down Expand Up @@ -1430,6 +1444,10 @@ Tk_CanvasPsOutline(
}
}

if (!outline->offsetObj || Tk_GetPixelsFromObj(NULL, Canvas(canvas)->tkwin,
outline->offsetObj, &offset) != TCL_OK) {
offset = 0;
}
Tcl_AppendPrintfToObj(psObj, "%.15g setlinewidth\n", width);

ptr = ((unsigned) ABS(dash->number) > sizeof(char *)) ?
Expand All @@ -1449,7 +1467,7 @@ Tk_CanvasPsOutline(
Tcl_AppendObjToObj(psObj, converted);
}
Tcl_DecrRefCount(converted);
Tcl_AppendPrintfToObj(psObj, "] %d setdash\n", outline->offset);
Tcl_AppendPrintfToObj(psObj, "] %d setdash\n", offset);
} else if (dash->number < 0) {
if (dash->number < -5) {
lptr = (char *)ckalloc(1 - 2*dash->number);
Expand All @@ -1462,7 +1480,7 @@ Tk_CanvasPsOutline(
for (; --i>0 ;) {
Tcl_AppendPrintfToObj(psObj, " %d", *p++ & 0xff);
}
Tcl_AppendPrintfToObj(psObj, "] %d setdash\n", outline->offset);
Tcl_AppendPrintfToObj(psObj, "] %d setdash\n", offset);
} else {
Tcl_AppendToObj(psObj, "] 0 setdash\n", TCL_INDEX_NONE);
}
Expand Down
53 changes: 35 additions & 18 deletions generic/tkCanvas.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ static const Tk_ConfigSpec configSpecs[] = {
{TK_CONFIG_SYNONYM, "-bd", "borderWidth", NULL, NULL, 0, 0, NULL},
{TK_CONFIG_SYNONYM, "-bg", "background", NULL, NULL, 0, 0, NULL},
{TK_CONFIG_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
DEF_CANVAS_BORDER_WIDTH, offsetof(TkCanvas, borderWidth), 0, NULL},
DEF_CANVAS_BORDER_WIDTH, offsetof(TkCanvas, borderWidthObj), TK_CONFIG_OBJS, NULL},
{TK_CONFIG_DOUBLE, "-closeenough", "closeEnough", "CloseEnough",
DEF_CANVAS_CLOSE_ENOUGH, offsetof(TkCanvas, closeEnough), 0, NULL},
{TK_CONFIG_BOOLEAN, "-confine", "confine", "Confine",
Expand All @@ -117,7 +117,7 @@ static const Tk_ConfigSpec configSpecs[] = {
DEF_CANVAS_HIGHLIGHT, offsetof(TkCanvas, highlightColorPtr), 0, NULL},
{TK_CONFIG_PIXELS, "-highlightthickness", "highlightThickness",
"HighlightThickness",
DEF_CANVAS_HIGHLIGHT_WIDTH, offsetof(TkCanvas, highlightWidth), 0, NULL},
DEF_CANVAS_HIGHLIGHT_WIDTH, offsetof(TkCanvas, highlightWidthObj), TK_CONFIG_OBJS, NULL},
{TK_CONFIG_BORDER, "-insertbackground", "insertBackground", "Foreground",
DEF_CANVAS_INSERT_BG, offsetof(TkCanvas, textInfo.insertBorder), 0, NULL},
{TK_CONFIG_PIXELS, "-insertborderwidth", "insertBorderWidth", "BorderWidth",
Expand Down Expand Up @@ -678,10 +678,10 @@ Tk_CanvasObjCmd(
CanvasCmdDeletedProc);
canvasPtr->firstItemPtr = NULL;
canvasPtr->lastItemPtr = NULL;
canvasPtr->borderWidth = 0;
canvasPtr->borderWidthObj = NULL;
canvasPtr->bgBorder = NULL;
canvasPtr->relief = TK_RELIEF_FLAT;
canvasPtr->highlightWidth = 0;
canvasPtr->highlightWidthObj = NULL;
canvasPtr->highlightBgColorPtr = NULL;
canvasPtr->highlightColorPtr = NULL;
canvasPtr->inset = 0;
Expand Down Expand Up @@ -2259,6 +2259,7 @@ ConfigureCanvas(
XGCValues gcValues;
GC newGC;
Tk_State old_canvas_state=canvasPtr->canvas_state;
int borderWidth, highlightWidth;

if (Tk_ConfigureWidget(interp, canvasPtr->tkwin, configSpecs,
objc, objv, canvasPtr,
Expand All @@ -2273,10 +2274,21 @@ ConfigureCanvas(

Tk_SetBackgroundFromBorder(canvasPtr->tkwin, canvasPtr->bgBorder);

if (canvasPtr->highlightWidth < 0) {
canvasPtr->highlightWidth = 0;
Tk_GetPixelsFromObj(NULL, canvasPtr->tkwin, canvasPtr->borderWidthObj, &borderWidth);
Tk_GetPixelsFromObj(NULL, canvasPtr->tkwin, canvasPtr->highlightWidthObj, &highlightWidth);
if (borderWidth < 0) {
borderWidth = 0;
Tcl_DecrRefCount(canvasPtr->borderWidthObj);
canvasPtr->borderWidthObj = Tcl_NewIntObj(0);
Tcl_IncrRefCount(canvasPtr->borderWidthObj);
}
canvasPtr->inset = canvasPtr->borderWidth + canvasPtr->highlightWidth;
if (highlightWidth < 0) {
highlightWidth = 0;
Tcl_DecrRefCount(canvasPtr->highlightWidthObj);
canvasPtr->highlightWidthObj = Tcl_NewIntObj(0);
Tcl_IncrRefCount(canvasPtr->highlightWidthObj);
}
canvasPtr->inset = borderWidth + highlightWidth;

gcValues.function = GXcopy;
gcValues.graphics_exposures = False;
Expand Down Expand Up @@ -2992,6 +3004,7 @@ DisplayCanvas(
Tk_Item *itemPtr;
Pixmap pixmap;
int screenX1, screenX2, screenY1, screenY2, width, height;
int borderWidth, highlightWidth;

if (canvasPtr->tkwin == NULL) {
return;
Expand Down Expand Up @@ -3169,17 +3182,18 @@ DisplayCanvas(
*/

borders:
Tk_GetPixelsFromObj(NULL, canvasPtr->tkwin, canvasPtr->borderWidthObj, &borderWidth);
Tk_GetPixelsFromObj(NULL, canvasPtr->tkwin, canvasPtr->highlightWidthObj, &highlightWidth);
if (canvasPtr->flags & REDRAW_BORDERS) {
canvasPtr->flags &= ~REDRAW_BORDERS;
if (canvasPtr->borderWidth > 0) {
if (borderWidth > 0) {
Tk_Draw3DRectangle(tkwin, Tk_WindowId(tkwin),
canvasPtr->bgBorder, canvasPtr->highlightWidth,
canvasPtr->highlightWidth,
Tk_Width(tkwin) - 2*canvasPtr->highlightWidth,
Tk_Height(tkwin) - 2*canvasPtr->highlightWidth,
canvasPtr->borderWidth, canvasPtr->relief);
canvasPtr->bgBorder, highlightWidth, highlightWidth,
Tk_Width(tkwin) - 2 * highlightWidth,
Tk_Height(tkwin) - 2 * highlightWidth,
borderWidth, canvasPtr->relief);
}
if (canvasPtr->highlightWidth > 0) {
if (highlightWidth > 0) {
GC fgGC, bgGC;

bgGC = Tk_GCForColor(canvasPtr->highlightBgColorPtr,
Expand All @@ -3188,10 +3202,10 @@ DisplayCanvas(
fgGC = Tk_GCForColor(canvasPtr->highlightColorPtr,
Tk_WindowId(tkwin));
Tk_DrawHighlightBorder(tkwin, fgGC, bgGC,
canvasPtr->highlightWidth, Tk_WindowId(tkwin));
highlightWidth, Tk_WindowId(tkwin));
} else {
Tk_DrawHighlightBorder(tkwin, bgGC, bgGC,
canvasPtr->highlightWidth, Tk_WindowId(tkwin));
highlightWidth, Tk_WindowId(tkwin));
}
}
}
Expand Down Expand Up @@ -5565,7 +5579,9 @@ CanvasFocusProc(
int gotFocus) /* 1 means window is getting focus, 0 means
* it's losing it. */
{
Tcl_DeleteTimerHandler(canvasPtr->insertBlinkHandler);
int highlightWidth;

Tcl_DeleteTimerHandler(canvasPtr->insertBlinkHandler);
if (gotFocus) {
canvasPtr->textInfo.gotFocus = 1;
canvasPtr->textInfo.cursorOn = 1;
Expand All @@ -5579,7 +5595,8 @@ CanvasFocusProc(
canvasPtr->insertBlinkHandler = NULL;
}
EventuallyRedrawItem(canvasPtr, canvasPtr->textInfo.focusItemPtr);
if (canvasPtr->highlightWidth > 0) {
Tk_GetPixelsFromObj(NULL, canvasPtr->tkwin, canvasPtr->highlightWidthObj, &highlightWidth);
if (highlightWidth > 0) {
canvasPtr->flags |= REDRAW_BORDERS;
if (!(canvasPtr->flags & REDRAW_PENDING)) {
Tcl_DoWhenIdle(DisplayCanvas, canvasPtr);
Expand Down
4 changes: 2 additions & 2 deletions generic/tkCanvas.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,11 @@ typedef struct TkCanvas {
* Information used when displaying widget:
*/

int borderWidth; /* Width of 3-D border around window. */
Tcl_Obj *borderWidthObj; /* Width of 3-D border around window. */
Tk_3DBorder bgBorder; /* Used for canvas background. */
int relief; /* Indicates whether window as a whole is
* raised, sunken, or flat. */
int highlightWidth; /* Width in pixels of highlight to draw around
Tcl_Obj *highlightWidthObj; /* Width in pixels of highlight to draw around
* widget when it has the focus. <= 0 means
* don't draw a highlight. */
XColor *highlightBgColorPtr;
Expand Down
36 changes: 35 additions & 1 deletion generic/tkOldConfig.c
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,11 @@ DoConfig(
nullValue = 1;
}

if ((specPtr->specFlags & TK_CONFIG_OBJS) && (specPtr->type != TK_CONFIG_PIXELS)) {
/* Prevent surprises for other options than TK_CONFIG_PIXELS */
Tcl_AppendResult(interp, "TK_CONFIG_OBJS not supported", (char *)NULL);
return TCL_ERROR;
}
do {
if (specPtr->offset < 0) {
break;
Expand Down Expand Up @@ -512,7 +517,24 @@ DoConfig(
}
break;
case TK_CONFIG_PIXELS:
if (nullValue) {
if (specPtr->specFlags & TK_CONFIG_OBJS) {
int dummy;
if (nullValue) {
if (*(Tcl_Obj **)ptr != NULL) {
Tcl_DecrRefCount(*(Tcl_Obj **)ptr);
*(Tcl_Obj **)ptr = NULL;
}
} else if (Tk_GetPixelsFromObj(interp, tkwin, arg, &dummy)
!= TCL_OK) {
return TCL_ERROR;
} else {
if (*(Tcl_Obj **)ptr != NULL) {
Tcl_DecrRefCount(*(Tcl_Obj **)ptr);
}
*(Tcl_Obj **)ptr = arg;
Tcl_IncrRefCount(*(Tcl_Obj **)ptr);
}
} else if (nullValue) {
*(int *)ptr = INT_MIN;
} else if (Tk_GetPixelsFromObj(interp, tkwin, arg, (int *)ptr)
!= TCL_OK) {
Expand Down Expand Up @@ -766,6 +788,12 @@ FormatConfigValue(
}
ptr = (char *)widgRec + specPtr->offset;
result = "";
if (specPtr->specFlags & TK_CONFIG_OBJS) {
if (*(Tcl_Obj **)ptr != NULL) {
result = Tcl_GetString(*((Tcl_Obj **)ptr));
}
return result;
}
switch (specPtr->type) {
case TK_CONFIG_BOOLEAN:
if (*((int *)ptr) == 0) {
Expand Down Expand Up @@ -1020,6 +1048,12 @@ Tk_FreeOptions(
*((Tk_3DBorder *) ptr) = NULL;
}
break;
case TK_CONFIG_PIXELS:
if ((specPtr->specFlags & TK_CONFIG_OBJS) && (*((Tcl_Obj **)ptr) != NULL)) {
Tcl_DecrRefCount(*((Tcl_Obj **)ptr));
*((Tcl_Obj **)ptr) = NULL;
}
break;
case TK_CONFIG_CURSOR:
case TK_CONFIG_ACTIVE_CURSOR:
if (*((Tk_Cursor *) ptr) != NULL) {
Expand Down
4 changes: 2 additions & 2 deletions generic/tkRectOval.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ static const Tk_ConfigSpec configSpecs[] = {
NULL, offsetof(RectOvalItem, outline.dash),
TK_CONFIG_NULL_OK, &dashOption},
{TK_CONFIG_PIXELS, "-dashoffset", NULL, NULL,
"0", offsetof(RectOvalItem, outline.offset),
TK_CONFIG_DONT_SET_DEFAULT, NULL},
"0", offsetof(RectOvalItem, outline.offsetObj),
TK_CONFIG_OBJS, NULL},
{TK_CONFIG_CUSTOM, "-disableddash", NULL, NULL,
NULL, offsetof(RectOvalItem, outline.disabledDash),
TK_CONFIG_NULL_OK, &dashOption},
Expand Down
2 changes: 1 addition & 1 deletion tests/canvas.test
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ test canvas-1.6 {configuration options: bad value for "bd"} -body {
test canvas-1.7 {configuration options: good value for "borderwidth"} -body {
.c configure -borderwidth 1.3
.c cget -borderwidth
} -result 1
} -result 1.3
test canvas-1.8 {configuration options: bad value for "borderwidth"} -body {
.c configure -borderwidth badValue
} -returnCodes error -result {expected screen distance but got "badValue"}
Expand Down

0 comments on commit 5bd07d4

Please sign in to comment.