Menu

#56 New canvas item 'buffer'

open
5
2015-02-24
2000-11-01
No

OriginalBugID: 926 RFE
Version: 8.0.4
SubmitDate: '1998-12-04'
LastModified: '1999-08-15'
Severity: SER
Status: UnAssn
Submitter: welch
ChangedBy: hobbs
OS: Other
Machine: NA

Name:

Sebastian Wangnick

DesiredBehavior:

I've implemented a new canvas item "buffer", which stores everything below it in the drawing list into a Pixmap, refreshing from this Pixmap when redrawing items above it in the display list.

The implementation required quite some changes to the canvas drawing algorithm and is therefore contained in tkCanvas.c.

To properly distribute dirtyness two new canvas API functions had to be added, namely Tk_CanvasEventuallyRedrawItem and Tk_CanvasEventuallyRedrawItemPartially; however, only tkCanvImg.c from the standard distribution had to be changed to make use of these new functions instead of Tk_CanvasEventuallyRedraw (which is obsolete, but retained for backwards-compatibility reasons).

This implementation gives a speed improvement for animations on top of complex backgrounds such as geographic maps of about 10x.

Patch:

diff -brc ../tk8.0.4.orig/generic/tk.h ./generic/tk.h

*** ../tk8.0.4.orig/generic/tk.h Fri Oct 16 17:22:59 1998

--- ./generic/tk.h Wed Dec 2 07:32:33 1998

***************

*** 653,658 ****

--- 653,664 ----

* items in this canvas. Later items

* in list are drawn on top of earlier

* ones. */

+ struct Tk_Item *prevBufferPtr; /* Points to the buffer prior in sequence

+ * that dirty rectangles are attributed to,

+ * or NULL if below us is no buffer,

+ * only the canvas background.

+ * Note that buffers point to their

+ * predecessor as well. */

Tk_Uid staticTagSpace[TK_TAG_SPACE];/* Built-in space for limited # of

* tags. */

Tk_Uid *tagPtr; /* Pointer to array of tags. Usually

***************

*** 1074,1079 ****

--- 1080,1090 ----

EXTERN void Tk_CanvasEventuallyRedraw _ANSI_ARGS_((

Tk_Canvas canvas, int x1, int y1, int x2,

int y2));

+ EXTERN void Tk_CanvasEventuallyRedrawItem _ANSI_ARGS_((

+ Tk_Canvas canvas, Tk_Item* itemPtr));

+ EXTERN void Tk_CanvasEventuallyRedrawItemPartially _ANSI_ARGS_((

+ Tk_Canvas canvas, Tk_Item* itemPtr, int x1, int y1,

+ int x2, int y2));

EXTERN int Tk_CanvasGetCoord _ANSI_ARGS_((Tcl_Interp *interp,

Tk_Canvas canvas, char *string,

double *doublePtr));

diff -brc ../tk8.0.4.orig/generic/tkCanvImg.c ./generic/tkCanvImg.c

*** ../tk8.0.4.orig/generic/tkCanvImg.c Mon Sep 14 18:23:05 1998

--- ./generic/tkCanvImg.c Wed Dec 2 07:32:33 1998

***************

*** 667,677 ****

x = y = 0;

width = imgWidth;

height = imgHeight;

! Tk_CanvasEventuallyRedraw(imgPtr->canvas, imgPtr->header.x1,

! imgPtr->header.y1, imgPtr->header.x2, imgPtr->header.y2);

}

ComputeImageBbox(imgPtr->canvas, imgPtr);

! Tk_CanvasEventuallyRedraw(imgPtr->canvas, imgPtr->header.x1 + x,

! imgPtr->header.y1 + y, (int) (imgPtr->header.x1 + x + width),

(int) (imgPtr->header.y1 + y + height));

}

--- 667,677 ----

x = y = 0;

width = imgWidth;

height = imgHeight;

! Tk_CanvasEventuallyRedrawItem(imgPtr->canvas, &imgPtr->header);

}

ComputeImageBbox(imgPtr->canvas, imgPtr);

! Tk_CanvasEventuallyRedrawItemPartially(imgPtr->canvas, &imgPtr->header,

! imgPtr->header.x1 + x, imgPtr->header.y1 + y,

! (int) (imgPtr->header.x1 + x + width),

(int) (imgPtr->header.y1 + y + height));

}

diff -brc ../tk8.0.4.orig/generic/tkCanvas.c ./generic/tkCanvas.c

*** ../tk8.0.4.orig/generic/tkCanvas.c Tue Oct 13 18:13:06 1998

--- ./generic/tkCanvas.c Wed Dec 2 10:48:35 1998

***************

*** 151,156 ****

--- 151,497 ----

extern Tk_ItemType tkOvalType, tkPolygonType;

extern Tk_ItemType tkRectangleType, tkTextType, tkWindowType;

+

+ /*

+ * The structure below defines the record for each buffer item.

+ */

+

+ static int CreateBuffer _ANSI_ARGS_((Tcl_Interp *interp,

+ Tk_Canvas canvas, Tk_Item *itemPtr,

+ int argc, char **argv));

+ static void DeleteBuffer _ANSI_ARGS_((Tk_Canvas canvas,

+ Tk_Item *itemPtr, Display *display));

+ static int ConfigureBuffer _ANSI_ARGS_((Tcl_Interp *interp,

+ Tk_Canvas canvas, Tk_Item *itemPtr, int argc,

+ char **argv, int flags));

+ static void DisplayBuffer _ANSI_ARGS_((Tk_Canvas canvas,

+ Tk_Item *itemPtr, Display *display, Drawable dst,

+ int x, int y, int width, int height));

+ static void ScaleBuffer _ANSI_ARGS_((Tk_Canvas canvas,

+ Tk_Item *itemPtr, double originX, double originY,

+ double scaleX, double scaleY));

+ static void TranslateBuffer _ANSI_ARGS_((Tk_Canvas canvas,

+ Tk_Item *itemPtr, double deltaX, double deltaY));

+ static int BufferToArea _ANSI_ARGS_((Tk_Canvas canvas,

+ Tk_Item *itemPtr, double *rectPtr));

+ static double BufferToPoint _ANSI_ARGS_((Tk_Canvas canvas,

+ Tk_Item *itemPtr, double *pointPtr));

+

+ static Tk_ConfigSpec bufferConfigSpecs[] = {

+ {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,

+ (char *) NULL, 0, 0}

+ };

+

+ typedef struct BufferItem {

+ Tk_Item header; /* Generic stuff that's the same for all

+ * types. MUST BE FIRST IN STRUCTURE. */

+

+ /*

+ * Fields that are set by widget commands other than "configure".

+ */

+

+ /*

+ * Configuration settings that are updated by Tk_ConfigureWidget.

+ */

+

+ /*

+ * Fields whose values are derived from the current values of the

+ * configuration settings above.

+ */

+

+ Pixmap buffer; /* Buffer caching drawing from below, or None. */

+ int width, height; /* Size of buffer in non-None. */

+ int x1, y1, x2, y2; /* Accumulated dirty area that trickled down on

+ * us, to be redrawn (at least, depending on dirty

+ * stuff below us) to next buffer or window. */

+ struct BufferItem *nextBufferPtr; /* Pointer to next buffer structure in sequence,

+ * or NULL if our stuff (and the stuff on top)

+ * goes directly into window. */

+ } BufferItem;

+

+ Tk_ItemType tkBufferType = {

+ "buffer", /* name */

+ sizeof(BufferItem), /* itemSize */

+ CreateBuffer, /* createProc */

+ bufferConfigSpecs, /* configSpecs */

+ ConfigureBuffer, /* configureProc */

+ NULL, /* coordProc */

+ DeleteBuffer, /* deleteProc */

+ DisplayBuffer, /* displayProc */

+ 0, /* alwaysRedraw */

+ BufferToPoint, /* pointProc */

+ BufferToArea, /* areaProc */

+ NULL, /* postscriptProc */

+ ScaleBuffer, /* scaleProc */

+ TranslateBuffer, /* translateProc */

+ NULL, /* indexProc */

+ NULL, /* icursorProc */

+ NULL, /* selectionProc */

+ NULL, /* insertProc */

+ NULL, /* dTextProc */

+ (Tk_ItemType *) NULL /* nextPtr */

+ };

+

+ static void CanvasEventuallyRedrawBuffer _ANSI_ARGS_((

+ TkCanvas *canvasPtr, Tk_Item* itemPtr));

+ static int CanvasIsBuffer _ANSI_ARGS_((Tk_Item* itemPtr));

+ static BufferItem* CanvasFindBuffer _ANSI_ARGS_((TkCanvas *canvasPtr,

+ Tk_Item* itemPtr));

+ /*

+ *----------------------------------------------------------------------

+ *

+ * CanvasIsBuffer --

+ *

+ * Results:

+ * Checks whether an item is a buffer item.

+ *

+ * Side effects:

+ * None.

+ *

+ *----------------------------------------------------------------------

+ */

+

+ static int

+ CanvasIsBuffer(itemPtr)

+ Tk_Item *itemPtr;

+ {

+ return itemPtr->typePtr==&tkBufferType;

+ }

+

+ /*

+ *----------------------------------------------------------------------

+ *

+ * CanvasFindBuffer --

+ *

+ * Given an item, find the first buffer below it, i.e., the one

+ * that we attribute dirty rectangles induced by the item to.

+ * In case of the item NULL find the topmost buffer of the canvas,

+ * i.e., the one to refresh the window from without any item changes.

+ *

+ * Results:

+ * The return value is a pointer to the buffer,

+ * or NULL if there is no buffer below itemPtr.

+ *

+ * Side effects:

+ * None.

+ *

+ *----------------------------------------------------------------------

+ */

+

+ static BufferItem *

+ CanvasFindBuffer(canvasPtr, itemPtr)

+ TkCanvas *canvasPtr; /* Canvas widget to search. */

+ Tk_Item *itemPtr;

+ {

+ if (itemPtr) {

+ itemPtr = itemPtr->prevBufferPtr;

+ } else {

+ itemPtr = canvasPtr->lastItemPtr;

+ if (itemPtr && !CanvasIsBuffer(itemPtr)) {

+ itemPtr = itemPtr->prevBufferPtr;

+ }

+ }

+ return (BufferItem*) itemPtr;

+ }

+

+ /*--------------------------------------------------------------

+ *

+ * CreateBuffer --

+ *

+ * This procedure is invoked to create a new buffer item

+ * in a canvas.

+ *

+ * Results:

+ * A standard Tcl return value. If an error occurred in

+ * creating the item then an error message is left in

+ * interp->result; in this case itemPtr is left uninitialized

+ * so it can be safely freed by the caller.

+ *

+ * Side effects:

+ * A new buffer item is created.

+ *

+ *--------------------------------------------------------------

+ */

+

+ static int

+ CreateBuffer(interp, canvas, itemPtr, argc, argv)

+ Tcl_Interp *interp; /* Interpreter for error reporting. */

+ Tk_Canvas canvas; /* Canvas to hold new item. */

+ Tk_Item *itemPtr; /* Record to hold new item; header

+ * has been initialized by caller. */

+ int argc; /* Number of arguments in argv. */

+ char **argv; /* Arguments describing rectangle. */

+ {

+ TkCanvas *canvasPtr = (TkCanvas *) canvas;

+ BufferItem *bufferPtr = (BufferItem *) itemPtr;

+ BufferItem *prevBufferPtr;

+

+ if (argc != 0) {

+ Tcl_AppendResult(interp, "wrong # args: should be \"",

+ Tk_PathName(Tk_CanvasTkwin(canvas)), " create ",

+ itemPtr->typePtr->name, "\"", (char *) NULL);

+ return TCL_ERROR;

+ }

+

+ /*

+ * Carry out initialization that is needed in order to clean

+ * up after errors during the the remainder of this procedure.

+ */

+

+ bufferPtr->buffer = None;

+ bufferPtr->x1 = 0;

+ bufferPtr->y1 = 0;

+ bufferPtr->x2 = 0;

+ bufferPtr->y2 = 0;

+

+ /* Append to list of buffers. */

+ bufferPtr->nextBufferPtr = NULL;

+ prevBufferPtr = CanvasFindBuffer((TkCanvas*)canvas,itemPtr);

+ if (prevBufferPtr)

+ prevBufferPtr->nextBufferPtr = bufferPtr;

+ else

+ canvasPtr->firstBufferPtr = bufferPtr;

+

+ CanvasEventuallyRedrawBuffer(canvasPtr, itemPtr);

+

+ return TCL_OK;

+ }

+

+ /*

+ *--------------------------------------------------------------

+ *

+ * DeleteBuffer --

+ *

+ * This procedure is called to clean up the data structure

+ * associated with a buffer item.

+ *

+ * Results:

+ * None.

+ *

+ * Side effects:

+ * Resources associated with itemPtr are released.

+ *

+ *--------------------------------------------------------------

+ */

+

+ static void

+ DeleteBuffer(canvas, itemPtr, display)

+ Tk_Canvas canvas; /* Info about overall canvas widget. */

+ Tk_Item *itemPtr; /* Item that is being deleted. */

+ Display *display; /* Display containing window for

+ * canvas. */

+ {

+ TkCanvas *canvasPtr = (TkCanvas *) canvas;

+ BufferItem *bufferPtr = (BufferItem *) itemPtr;

+ BufferItem *prevBufferPtr;

+

+ if (bufferPtr->buffer != None) {

+ Tk_FreePixmap(display, bufferPtr->buffer);

+

+ CanvasEventuallyRedrawBuffer(canvasPtr, itemPtr);

+

+ /* Unlink from list of buffers. */

+ prevBufferPtr = CanvasFindBuffer((TkCanvas*)canvas,itemPtr);

+ if (prevBufferPtr)

+ prevBufferPtr->nextBufferPtr = bufferPtr->nextBufferPtr;

+ else

+ canvasPtr->firstBufferPtr = bufferPtr->nextBufferPtr;

+ }

+ }

+

+ /*

+ *--------------------------------------------------------------

+ *

+ * Further Buffer routines --

+ *

+ * These are the buffer type manager required routines.

+ * For buffers, they do nothing and/or return an error.

+ *

+ *--------------------------------------------------------------

+ */

+

+ static void

+ CanvasEventuallyRedrawBuffer (canvasPtr, itemPtr)

+ TkCanvas *canvasPtr; /* Canvas to invalidate. */

+ Tk_Item *itemPtr; /* Buffer to be redrawn. */

+ {

+ if (!canvasPtr->tkwin)

+ return;

+ Tk_CanvasEventuallyRedrawItemPartially((Tk_Canvas) canvasPtr, itemPtr,

+ canvasPtr->xOrigin, canvasPtr->yOrigin,

+ canvasPtr->xOrigin + Tk_Width(canvasPtr->tkwin),

+ canvasPtr->yOrigin + Tk_Height(canvasPtr->tkwin));

+ }

+

+ static int

+ ConfigureBuffer (interp, canvas, itemPtr, argc, argv, flags)

+ Tcl_Interp *interp; /* Interpreter for error reporting. */

+ Tk_Canvas canvas; /* Canvas containing itemPtr. */

+ Tk_Item *itemPtr; /* Buffer item to reconfigure. */

+ int argc; /* Number of elements in argv. */

+ char **argv; /* Arguments describing things to configure. */

+ int flags; /* Flags to pass to Tk_ConfigureWidget. */

+ {

+ if (Tk_ConfigureWidget(interp, Tk_CanvasTkwin(canvas), bufferConfigSpecs,

+ argc, argv, (char *) itemPtr, flags) != TCL_OK) {

+ return TCL_ERROR;

+ }

+ return TCL_OK;

+ }

+

+ static void

+ DisplayBuffer (canvas, itemPtr, display, drawable, x, y, width, height)

+ Tk_Canvas canvas; /* Canvas that contains item. */

+ Tk_Item *itemPtr; /* Item to be displayed. */

+ Display *display; /* Display on which to draw item. */

+ Drawable drawable; /* Pixmap or window in which to draw

+ * item. */

+ int x, y, width, height; /* Describes region of canvas that

+ * must be redisplayed (not used). */

+ {

+ panic("tried to display buffer %d in canvas %s", itemPtr->id,

+ Tk_PathName(Tk_CanvasTkwin(canvas)));

+ }

+

+ static void

+ ScaleBuffer (canvas, itemPtr, originX, originY, scaleX, scaleY)

+ Tk_Canvas canvas; /* Canvas containing buffer. */

+ Tk_Item *itemPtr; /* Buffer to be scaled. */

+ double originX, originY; /* Origin about which to scale buffer. */

+ double scaleX; /* Amount to scale in X direction. */

+ double scaleY; /* Amount to scale in Y direction. */

+ {

+ }

+

+ static void

+ TranslateBuffer (canvas, itemPtr, deltaX, deltaY)

+ Tk_Canvas canvas; /* Canvas containing buffer. */

+ Tk_Item *itemPtr; /* Buffer that is being moved. */

+ double deltaX, deltaY; /* Amount by which buffer is to be

+ * moved. */

+ {

+ }

+

+ static int

+ BufferToArea(canvas, itemPtr, rectPtr)

+ Tk_Canvas canvas; /* Canvas containing itemPtr. */

+ Tk_Item *itemPtr; /* Item to check against rectangle. */

+ double *rectPtr; /* Pointer to array of four coordinates

+ * (x1, y1, x2, y2) describing rectangular

+ * area. */

+ {

+ return -1;

+ }

+

+ static double

+ BufferToPoint(canvas, itemPtr, pointPtr)

+ Tk_Canvas canvas; /* Canvas containing itemPtr. */

+ Tk_Item *itemPtr; /* Item to check against point. */

+ double *pointPtr; /* Pointer to x and y coordinates. */

+ {

+ return 1.7E308;

+ }

+

/*

* Various Tk_Uid's used by this module (set up during initialization):

*/

***************

*** 166,171 ****

--- 507,519 ----

static int numSlowSearches;

/*

+ * Boolean variable indicating whether or not special debugging code

+ * should be executed.

+ */

+

+ int tkCanvasDebug = 0;

+

+ /*

* Prototypes for procedures defined later in this file:

*/

***************

*** 178,183 ****

--- 526,536 ----

XEvent *eventPtr));

static void CanvasEventProc _ANSI_ARGS_((ClientData clientData,

XEvent *eventPtr));

+ static void CanvasEventuallyRedrawAll _ANSI_ARGS_((

+ TkCanvas *canvasPtr));

+ static void CanvasEventuallyRedrawExpose _ANSI_ARGS_((

+ TkCanvas *canvasPtr,

+ int x1, int y1, int x2, int y2));

static int CanvasFetchSelection _ANSI_ARGS_((

ClientData clientData, int offset,

char *buffer, int maxBytes));

***************

*** 295,300 ****

--- 648,654 ----

(ClientData) canvasPtr, CanvasCmdDeletedProc);

canvasPtr->firstItemPtr = NULL;

canvasPtr->lastItemPtr = NULL;

+ canvasPtr->firstBufferPtr = NULL;

canvasPtr->borderWidth = 0;

canvasPtr->bgBorder = NULL;

canvasPtr->relief = TK_RELIEF_FLAT;

***************

*** 650,665 ****

itemPtr = StartTagSearch(canvasPtr, argv[2], &search);

if (itemPtr != NULL) {

if (argc != 3) {

! Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,

! itemPtr->x1, itemPtr->y1, itemPtr->x2, itemPtr->y2);

}

if (itemPtr->typePtr->coordProc != NULL) {

result = (*itemPtr->typePtr->coordProc)(interp,

(Tk_Canvas) canvasPtr, itemPtr, argc-3, argv+3);

}

if (argc != 3) {

! Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,

! itemPtr->x1, itemPtr->y1, itemPtr->x2, itemPtr->y2);

}

}

} else if ((c == 'c') && (strncmp(argv[1], "create", length) == 0)

--- 1004,1017 ----

itemPtr = StartTagSearch(canvasPtr, argv[2], &search);

if (itemPtr != NULL) {

if (argc != 3) {

! Tk_CanvasEventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr);

}

if (itemPtr->typePtr->coordProc != NULL) {

result = (*itemPtr->typePtr->coordProc)(interp,

(Tk_Canvas) canvasPtr, itemPtr, argc-3, argv+3);

}

if (argc != 3) {

! Tk_CanvasEventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr);

}

}

} else if ((c == 'c') && (strncmp(argv[1], "create", length) == 0)

***************

*** 701,706 ****

--- 1053,1062 ----

itemPtr->tagSpace = TK_TAG_SPACE;

itemPtr->numTags = 0;

itemPtr->typePtr = typePtr;

+ itemPtr->prevBufferPtr = canvasPtr->lastItemPtr;

+ if (itemPtr->prevBufferPtr && !CanvasIsBuffer(itemPtr->prevBufferPtr)) {

+ itemPtr->prevBufferPtr = itemPtr->prevBufferPtr->prevBufferPtr;

+ }

if ((*typePtr->createProc)(interp, (Tk_Canvas) canvasPtr,

itemPtr, argc-3, argv+3) != TCL_OK) {

ckfree((char *) itemPtr);

***************

*** 719,726 ****

canvasPtr->lastItemPtr->nextPtr = itemPtr;

}

canvasPtr->lastItemPtr = itemPtr;

! Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,

! itemPtr->x1, itemPtr->y1, itemPtr->x2, itemPtr->y2);

canvasPtr->flags |= REPICK_NEEDED;

sprintf(interp->result, "%d", itemPtr->id);

} else if ((c == 'd') && (strncmp(argv[1], "dchars", length) == 0)

--- 1075,1081 ----

canvasPtr->lastItemPtr->nextPtr = itemPtr;

}

canvasPtr->lastItemPtr = itemPtr;

! Tk_CanvasEventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr);

canvasPtr->flags |= REPICK_NEEDED;

sprintf(interp->result, "%d", itemPtr->id);

} else if ((c == 'd') && (strncmp(argv[1], "dchars", length) == 0)

***************

*** 759,770 ****

* the old area.

*/

! Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,

! itemPtr->x1, itemPtr->y1, itemPtr->x2, itemPtr->y2);

(*itemPtr->typePtr->dCharsProc)((Tk_Canvas) canvasPtr,

itemPtr, first, last);

! Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,

! itemPtr->x1, itemPtr->y1, itemPtr->x2, itemPtr->y2);

}

} else if ((c == 'd') && (strncmp(argv[1], "delete", length) == 0)

&& (length >= 2)) {

--- 1114,1137 ----

* the old area.

*/

! Tk_CanvasEventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr);

(*itemPtr->typePtr->dCharsProc)((Tk_Canvas) canvasPtr,

itemPtr, first, last);

! Tk_CanvasEventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr);

! }

! } else if ((c == 'd') && (strncmp(argv[1], "debug", length) == 0)

! && (length >= 3)) {

! if (argc > 3) {

! Tcl_AppendResult(interp, "wrong # args: should be \"",

! argv[0], " debug ?boolean?\"", (char *) NULL);

! goto error;

! }

! if (argc == 2) {

! interp->result = (tkCanvasDebug) ? "1" : "0";

! } else {

! if (Tcl_GetBoolean(interp, argv[2], &tkCanvasDebug) != TCL_OK) {

! goto error;

! }

}

} else if ((c == 'd') && (strncmp(argv[1], "delete", length) == 0)

&& (length >= 2)) {

***************

*** 774,781 ****

for (i = 2; i < argc; i++) {

for (itemPtr = StartTagSearch(canvasPtr, argv[i], &search);

itemPtr != NULL; itemPtr = NextItem(&search)) {

! Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,

! itemPtr->x1, itemPtr->y1, itemPtr->x2, itemPtr->y2);

if (canvasPtr->bindingTable != NULL) {

Tk_DeleteAllBindings(canvasPtr->bindingTable,

(ClientData) itemPtr);

--- 1141,1147 ----

for (i = 2; i < argc; i++) {

for (itemPtr = StartTagSearch(canvasPtr, argv[i], &search);

itemPtr != NULL; itemPtr = NextItem(&search)) {

! Tk_CanvasEventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr);

if (canvasPtr->bindingTable != NULL) {

Tk_DeleteAllBindings(canvasPtr->bindingTable,

(ClientData) itemPtr);

***************

*** 875,882 ****

goto done;

}

if ((itemPtr != NULL) && (canvasPtr->textInfo.gotFocus)) {

! Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,

! itemPtr->x1, itemPtr->y1, itemPtr->x2, itemPtr->y2);

}

if (argv[2][0] == 0) {

canvasPtr->textInfo.focusItemPtr = NULL;

--- 1241,1247 ----

goto done;

}

if ((itemPtr != NULL) && (canvasPtr->textInfo.gotFocus)) {

! Tk_CanvasEventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr);

}

if (argv[2][0] == 0) {

canvasPtr->textInfo.focusItemPtr = NULL;

***************

*** 893,900 ****

}

canvasPtr->textInfo.focusItemPtr = itemPtr;

if (canvasPtr->textInfo.gotFocus) {

! Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,

! itemPtr->x1, itemPtr->y1, itemPtr->x2, itemPtr->y2);

}

} else if ((c == 'g') && (strncmp(argv[1], "gettags", length) == 0)) {

if (argc != 3) {

--- 1258,1264 ----

}

canvasPtr->textInfo.focusItemPtr = itemPtr;

if (canvasPtr->textInfo.gotFocus) {

! Tk_CanvasEventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr);

}

} else if ((c == 'g') && (strncmp(argv[1], "gettags", length) == 0)) {

if (argc != 3) {

***************

*** 933,940 ****

index);

if ((itemPtr == canvasPtr->textInfo.focusItemPtr)

&& (canvasPtr->textInfo.cursorOn)) {

! Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,

! itemPtr->x1, itemPtr->y1, itemPtr->x2, itemPtr->y2);

}

}

} else if ((c == 'i') && (strncmp(argv[1], "index", length) == 0)

--- 1297,1303 ----

index);

if ((itemPtr == canvasPtr->textInfo.focusItemPtr)

&& (canvasPtr->textInfo.cursorOn)) {

! Tk_CanvasEventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr);

}

}

} else if ((c == 'i') && (strncmp(argv[1], "index", length) == 0)

***************

*** 990,1001 ****

* larger or smaller than the old area.

*/

! Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,

! itemPtr->x1, itemPtr->y1, itemPtr->x2, itemPtr->y2);

(*itemPtr->typePtr->insertProc)((Tk_Canvas) canvasPtr,

itemPtr, beforeThis, argv[4]);

! Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr, itemPtr->x1,

! itemPtr->y1, itemPtr->x2, itemPtr->y2);

}

} else if ((c == 'i') && (strncmp(argv[1], "itemcget", length) == 0)

&& (length >= 6)) {

--- 1353,1362 ----

* larger or smaller than the old area.

*/

! Tk_CanvasEventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr);

(*itemPtr->typePtr->insertProc)((Tk_Canvas) canvasPtr,

itemPtr, beforeThis, argv[4]);

! Tk_CanvasEventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr);

}

} else if ((c == 'i') && (strncmp(argv[1], "itemcget", length) == 0)

&& (length >= 6)) {

***************

*** 1030,1042 ****

itemPtr->typePtr->configSpecs, (char *) itemPtr,

argv[3], 0);

} else {

! Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,

! itemPtr->x1, itemPtr->y1, itemPtr->x2, itemPtr->y2);

result = (*itemPtr->typePtr->configProc)(interp,

(Tk_Canvas) canvasPtr, itemPtr, argc-3, argv+3,

TK_CONFIG_ARGV_ONLY);

! Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,

! itemPtr->x1, itemPtr->y1, itemPtr->x2, itemPtr->y2);

canvasPtr->flags |= REPICK_NEEDED;

}

if ((result != TCL_OK) || (argc < 5)) {

--- 1391,1401 ----

itemPtr->typePtr->configSpecs, (char *) itemPtr,

argv[3], 0);

} else {

! Tk_CanvasEventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr);

result = (*itemPtr->typePtr->configProc)(interp,

(Tk_Canvas) canvasPtr, itemPtr, argc-3, argv+3,

TK_CONFIG_ARGV_ONLY);

! Tk_CanvasEventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr);

canvasPtr->flags |= REPICK_NEEDED;

}

if ((result != TCL_OK) || (argc < 5)) {

***************

*** 1086,1097 ****

}

for (itemPtr = StartTagSearch(canvasPtr, argv[2], &search);

itemPtr != NULL; itemPtr = NextItem(&search)) {

! Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,

! itemPtr->x1, itemPtr->y1, itemPtr->x2, itemPtr->y2);

(void) (*itemPtr->typePtr->translateProc)((Tk_Canvas) canvasPtr,

itemPtr, xAmount, yAmount);

! Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,

! itemPtr->x1, itemPtr->y1, itemPtr->x2, itemPtr->y2);

canvasPtr->flags |= REPICK_NEEDED;

}

} else if ((c == 'p') && (strncmp(argv[1], "postscript", length) == 0)) {

--- 1445,1454 ----

}

for (itemPtr = StartTagSearch(canvasPtr, argv[2], &search);

itemPtr != NULL; itemPtr = NextItem(&search)) {

! Tk_CanvasEventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr);

(void) (*itemPtr->typePtr->translateProc)((Tk_Canvas) canvasPtr,

itemPtr, xAmount, yAmount);

! Tk_CanvasEventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr);

canvasPtr->flags |= REPICK_NEEDED;

}

} else if ((c == 'p') && (strncmp(argv[1], "postscript", length) == 0)) {

***************

*** 1150,1161 ****

}

for (itemPtr = StartTagSearch(canvasPtr, argv[2], &search);

itemPtr != NULL; itemPtr = NextItem(&search)) {

! Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,

! itemPtr->x1, itemPtr->y1, itemPtr->x2, itemPtr->y2);

(void) (*itemPtr->typePtr->scaleProc)((Tk_Canvas) canvasPtr,

itemPtr, xOrigin, yOrigin, xScale, yScale);

! Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,

! itemPtr->x1, itemPtr->y1, itemPtr->x2, itemPtr->y2);

canvasPtr->flags |= REPICK_NEEDED;

}

} else if ((c == 's') && (strncmp(argv[1], "scan", length) == 0)

--- 1507,1516 ----

}

for (itemPtr = StartTagSearch(canvasPtr, argv[2], &search);

itemPtr != NULL; itemPtr = NextItem(&search)) {

! Tk_CanvasEventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr);

(void) (*itemPtr->typePtr->scaleProc)((Tk_Canvas) canvasPtr,

itemPtr, xOrigin, yOrigin, xScale, yScale);

! Tk_CanvasEventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr);

canvasPtr->flags |= REPICK_NEEDED;

}

} else if ((c == 's') && (strncmp(argv[1], "scan", length) == 0)

***************

*** 1256,1266 ****

goto error;

}

if (canvasPtr->textInfo.selItemPtr != NULL) {

! Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,

! canvasPtr->textInfo.selItemPtr->x1,

! canvasPtr->textInfo.selItemPtr->y1,

! canvasPtr->textInfo.selItemPtr->x2,

! canvasPtr->textInfo.selItemPtr->y2);

canvasPtr->textInfo.selItemPtr = NULL;

}

goto done;

--- 1611,1618 ----

goto error;

}

if (canvasPtr->textInfo.selItemPtr != NULL) {

! Tk_CanvasEventuallyRedrawItem((Tk_Canvas) canvasPtr,

! canvasPtr->textInfo.selItemPtr);

canvasPtr->textInfo.selItemPtr = NULL;

}

goto done;

***************

*** 1584,1593 ****

CanvasSetOrigin(canvasPtr, canvasPtr->xOrigin, canvasPtr->yOrigin);

canvasPtr->flags |= UPDATE_SCROLLBARS|REDRAW_BORDERS;

! Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,

! canvasPtr->xOrigin, canvasPtr->yOrigin,

! canvasPtr->xOrigin + Tk_Width(canvasPtr->tkwin),

! canvasPtr->yOrigin + Tk_Height(canvasPtr->tkwin));

return TCL_OK;

}

--- 1936,1942 ----

CanvasSetOrigin(canvasPtr, canvasPtr->xOrigin, canvasPtr->yOrigin);

canvasPtr->flags |= UPDATE_SCROLLBARS|REDRAW_BORDERS;

! CanvasEventuallyRedrawAll(canvasPtr);

return TCL_OK;

}

***************

*** 1622,1627 ****

--- 1971,1977 ----

canvasPtr = (TkCanvas *) instanceData;

itemPtr = canvasPtr->firstItemPtr;

for ( ; itemPtr != NULL; itemPtr = itemPtr->nextPtr) {

+ if (itemPtr->typePtr->configProc) {

result = (*itemPtr->typePtr->configProc)(canvasPtr->interp,

(Tk_Canvas) canvasPtr, itemPtr, 0, NULL,

TK_CONFIG_ARGV_ONLY);

***************

*** 1629,1639 ****

Tcl_ResetResult(canvasPtr->interp);

}

}

canvasPtr->flags |= REPICK_NEEDED;

! Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,

! canvasPtr->xOrigin, canvasPtr->yOrigin,

! canvasPtr->xOrigin + Tk_Width(canvasPtr->tkwin),

! canvasPtr->yOrigin + Tk_Height(canvasPtr->tkwin));

}

/*

--- 1979,1987 ----

Tcl_ResetResult(canvasPtr->interp);

}

}

+ }

canvasPtr->flags |= REPICK_NEEDED;

! CanvasEventuallyRedrawAll(canvasPtr);

}

/*

***************

*** 1661,1672 ****

TkCanvas *canvasPtr = (TkCanvas *) clientData;

Tk_Window tkwin = canvasPtr->tkwin;

Tk_Item *itemPtr;

! Pixmap pixmap;

! int screenX1, screenX2, screenY1, screenY2, width, height;

if (canvasPtr->tkwin == NULL) {

return;

}

if (!Tk_IsMapped(tkwin)) {

goto done;

}

--- 2009,2028 ----

TkCanvas *canvasPtr = (TkCanvas *) clientData;

Tk_Window tkwin = canvasPtr->tkwin;

Tk_Item *itemPtr;

! Tk_Item *lastItemPtr;

! Pixmap tempForClipping = None;

! int sx1, sy1, sx2, sy2;

!

! if (tkCanvasDebug) {

! Tcl_SetVar2(canvasPtr->interp, "tk_canvasRedraw", (char *) NULL,

! Tcl_GetCommandName(canvasPtr->interp, canvasPtr->widgetCmd),

! TCL_GLOBAL_ONLY);

! }

if (canvasPtr->tkwin == NULL) {

return;

}

+

if (!Tk_IsMapped(tkwin)) {

goto done;

}

***************

*** 1688,1741 ****

}

/*

* Compute the intersection between the area that needs redrawing

* and the area that's visible on the screen.

*/

! if ((canvasPtr->redrawX1 < canvasPtr->redrawX2)

! && (canvasPtr->redrawY1 < canvasPtr->redrawY2)) {

! screenX1 = canvasPtr->xOrigin + canvasPtr->inset;

! screenY1 = canvasPtr->yOrigin + canvasPtr->inset;

! screenX2 = canvasPtr->xOrigin + Tk_Wid

I've tried as much as possible to retain backwards-compatibility. However, one should be aware that an additional field had to be added to the Tk_Canvas structure.
Severity is "Severe" because without the patch display of life air traffic (my application) is not possible.
Documentation is outstanding. The only new command, however, is <.canvas> create buffer, there are no further configuration options.

Discussion

  • Don Porter

    Don Porter - 2001-03-23
    • milestone: 102486 -->
    • summary: New canvas item "buffer" --> New canvas item "buffer"
    • labels: 104344 -->
     
  • Don Porter

    Don Porter - 2001-03-23
    • labels: --> 05. Canvas Items
    • summary: New canvas item "buffer" --> New canvas item "buffer"
     
  • Donal K. Fellows

    • summary: New canvas item "buffer" --> New canvas item 'buffer'
     
  • Don Porter

    Don Porter - 2003-11-13
    • assigned_to: nobody --> dkf
     
Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.