From 5e40f524d201a69d005903615a1e02aea2a8ac27 Mon Sep 17 00:00:00 2001 From: treectrl Date: Wed, 6 Dec 2006 00:52:03 +0000 Subject: Created a stack of TkRegions to avoid creating/destroying them repeatedly. Fixed a leak on X11 where the clipping region was not being freed after drawing dotted rectangles. --- generic/tkTreeCtrl.c | 6 ++++- generic/tkTreeCtrl.h | 7 +++++- generic/tkTreeDisplay.c | 52 ++++++++++++++++++++-------------------- generic/tkTreeElem.c | 10 ++++---- generic/tkTreeUtils.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++-- 5 files changed, 103 insertions(+), 35 deletions(-) diff --git a/generic/tkTreeCtrl.c b/generic/tkTreeCtrl.c index 77607cf..bc6b540 100644 --- a/generic/tkTreeCtrl.c +++ b/generic/tkTreeCtrl.c @@ -7,7 +7,7 @@ * Copyright (c) 2002-2003 Christian Krone * Copyright (c) 2003-2005 ActiveState, a division of Sophos * - * RCS: @(#) $Id: tkTreeCtrl.c,v 1.94 2006/12/06 00:03:21 treectrl Exp $ + * RCS: @(#) $Id: tkTreeCtrl.c,v 1.95 2006/12/06 00:52:03 treectrl Exp $ */ #include "tkTreeCtrl.h" @@ -1782,6 +1782,10 @@ TreeDestroy( Tree_FreeColumns(tree); +dbwin("tree->regionStackLen = %d", tree->regionStackLen); + while (tree->regionStackLen > 0) + TkDestroyRegion(tree->regionStack[--tree->regionStackLen]); + QE_DeleteBindingTable(tree->bindingTable); for (i = STATE_USER - 1; i < 32; i++) diff --git a/generic/tkTreeCtrl.h b/generic/tkTreeCtrl.h index 2cb1ef3..79e52bc 100644 --- a/generic/tkTreeCtrl.h +++ b/generic/tkTreeCtrl.h @@ -7,7 +7,7 @@ * Copyright (c) 2002-2003 Christian Krone * Copyright (c) 2003 ActiveState Corporation * - * RCS: @(#) $Id: tkTreeCtrl.h,v 1.82 2006/12/06 00:03:21 treectrl Exp $ + * RCS: @(#) $Id: tkTreeCtrl.h,v 1.83 2006/12/06 00:52:04 treectrl Exp $ */ #include "tkPort.h" @@ -376,6 +376,9 @@ struct TreeCtrl TreeThemeData themeData; GCCache *gcCache; /* Graphics contexts for elements. */ + + TkRegion regionStack[8]; /* Temp region stack. */ + int regionStackLen; /* Number of unused regions in regionStack. */ }; #define TREE_CONF_FONT 0x0001 @@ -877,6 +880,8 @@ extern void Tree_DrawBitmapWithGC(TreeCtrl *tree, Pixmap bitmap, Drawable drawab extern void Tree_DrawBitmap(TreeCtrl *tree, Pixmap bitmap, Drawable drawable, XColor *fg, XColor *bg, int src_x, int src_y, int width, int height, int dest_x, int dest_y); +extern TkRegion Tree_GetRegion(TreeCtrl *tree); +extern void Tree_FreeRegion(TreeCtrl *tree, TkRegion region); extern void Tk_FillRegion(Display *display, Drawable drawable, GC gc, TkRegion rgn); extern void Tk_OffsetRegion(TkRegion region, int xOffset, int yOffset); extern int Tree_ScrollWindow(TreeCtrl *tree, GC gc, int x, int y, diff --git a/generic/tkTreeDisplay.c b/generic/tkTreeDisplay.c index 0842889..3e1150b 100644 --- a/generic/tkTreeDisplay.c +++ b/generic/tkTreeDisplay.c @@ -5,7 +5,7 @@ * * Copyright (c) 2002-2006 Tim Baker * - * RCS: @(#) $Id: tkTreeDisplay.c,v 1.73 2006/12/06 00:03:21 treectrl Exp $ + * RCS: @(#) $Id: tkTreeDisplay.c,v 1.74 2006/12/06 00:52:04 treectrl Exp $ */ #include "tkTreeCtrl.h" @@ -3792,13 +3792,13 @@ ScrollVerticalComplex( } /* Copy */ - damageRgn = TkCreateRegion(); + damageRgn = Tree_GetRegion(tree); if (Tree_ScrollWindow(tree, dInfo->scrollGC, oldX, oldY, width, height, 0, offset, damageRgn)) { DisplayDelay(tree); Tree_InvalidateRegion(tree, damageRgn); } - TkDestroyRegion(damageRgn); + Tree_FreeRegion(tree, damageRgn); } return numCopy; } @@ -3888,7 +3888,7 @@ ScrollHorizontalSimple( dirtyMin = minX + width; dirtyMax = maxX - width; - damageRgn = TkCreateRegion(); + damageRgn = Tree_GetRegion(tree); if (tree->doubleBuffer == DOUBLEBUFFER_WINDOW) { XCopyArea(tree->display, dInfo->pixmap, dInfo->pixmap, @@ -3900,7 +3900,7 @@ ScrollHorizontalSimple( else dirtyMin = minX; Tree_InvalidateArea(tree, dirtyMin, minY, dirtyMax, maxY); - TkDestroyRegion(damageRgn); + Tree_FreeRegion(tree, damageRgn); return; } @@ -3909,7 +3909,7 @@ ScrollHorizontalSimple( DisplayDelay(tree); Tree_InvalidateRegion(tree, damageRgn); } - TkDestroyRegion(damageRgn); + Tree_FreeRegion(tree, damageRgn); #ifndef WIN32 if (offset < 0) dirtyMax = maxX; @@ -3996,7 +3996,7 @@ ScrollVerticalSimple( dirtyMin = minY + height; dirtyMax = maxY - height; - damageRgn = TkCreateRegion(); + damageRgn = Tree_GetRegion(tree); if (tree->doubleBuffer == DOUBLEBUFFER_WINDOW) { XCopyArea(tree->display, dInfo->pixmap, dInfo->pixmap, @@ -4008,7 +4008,7 @@ ScrollVerticalSimple( else dirtyMin = minY; Tree_InvalidateArea(tree, minX, dirtyMin, maxX, dirtyMax); - TkDestroyRegion(damageRgn); + Tree_FreeRegion(tree, damageRgn); return; } @@ -4017,7 +4017,7 @@ ScrollVerticalSimple( DisplayDelay(tree); Tree_InvalidateRegion(tree, damageRgn); } - TkDestroyRegion(damageRgn); + Tree_FreeRegion(tree, damageRgn); #ifndef WIN32 if (offset < 0) dirtyMax = maxY; @@ -4177,13 +4177,13 @@ ScrollHorizontalComplex( } /* Copy */ - damageRgn = TkCreateRegion(); + damageRgn = Tree_GetRegion(tree); if (Tree_ScrollWindow(tree, dInfo->scrollGC, oldX, oldY, width, height, offset, 0, damageRgn)) { DisplayDelay(tree); Tree_InvalidateRegion(tree, damageRgn); } - TkDestroyRegion(damageRgn); + Tree_FreeRegion(tree, damageRgn); } return numCopy; } @@ -4395,7 +4395,7 @@ CalcWhiteSpaceRegion( x = 0 - tree->xOrigin; y = 0 - tree->yOrigin; - wsRgn = TkCreateRegion(); + wsRgn = Tree_GetRegion(tree); /* Erase area below left columns */ if (!dInfo->emptyL) { @@ -4853,7 +4853,7 @@ DrawWhitespace( else height = tree->minItemHeight; - columnRgn = TkCreateRegion(); + columnRgn = Tree_GetRegion(tree); range = dInfo->rangeFirst; if (range == NULL) @@ -4934,7 +4934,7 @@ DrawWhitespace( } } - TkDestroyRegion(columnRgn); + Tree_FreeRegion(tree, columnRgn); } #endif /* COMPLEX_WHITESPACE */ @@ -5572,7 +5572,7 @@ displayRetry: dInfo->yOrigin != tree->yOrigin) { wsRgnDif = wsRgnNew; } else { - wsRgnDif = TkCreateRegion(); + wsRgnDif = Tree_GetRegion(tree); TkSubtractRegion(wsRgnNew, dInfo->wsRgn, wsRgnDif); } TkClipBox(wsRgnDif, &wsBox); @@ -5618,8 +5618,8 @@ displayRetry: } } if (wsRgnDif != wsRgnNew) - TkDestroyRegion(wsRgnDif); - TkDestroyRegion(dInfo->wsRgn); + Tree_FreeRegion(tree, wsRgnDif); + Tree_FreeRegion(tree, dInfo->wsRgn); dInfo->wsRgn = wsRgnNew; } @@ -5633,7 +5633,7 @@ displayRetry: /* Calculate the current whitespace region, subtract the old whitespace * region, and fill the difference with the background color. */ wsRgnNew = CalcWhiteSpaceRegion(tree); - wsRgnDif = TkCreateRegion(); + wsRgnDif = Tree_GetRegion(tree); TkSubtractRegion(wsRgnNew, dInfo->wsRgn, wsRgnDif); TkClipBox(wsRgnDif, &wsBox); if ((wsBox.width > 0) && (wsBox.height > 0)) { @@ -5657,8 +5657,8 @@ displayRetry: dInfo->dirty[BOTTOM] = MAX(dInfo->dirty[BOTTOM], wsBox.y + wsBox.height); } } - TkDestroyRegion(wsRgnDif); - TkDestroyRegion(dInfo->wsRgn); + Tree_FreeRegion(tree, wsRgnDif); + Tree_FreeRegion(tree, dInfo->wsRgn); dInfo->wsRgn = wsRgnNew; } @@ -6946,7 +6946,7 @@ Tree_InvalidateArea( if ((x1 < x2 && y1 < y2) && TkRectInRegion(dInfo->wsRgn, x1, y1, x2 - x1, y2 - y1)) { XRectangle rect; - TkRegion rgn = TkCreateRegion(); + TkRegion rgn = Tree_GetRegion(tree); rect.x = x1; rect.y = y1; @@ -6954,7 +6954,7 @@ Tree_InvalidateArea( rect.height = y2 - y1; TkUnionRectWithRegion(&rect, rgn, rgn); TkSubtractRegion(dInfo->wsRgn, rgn, dInfo->wsRgn); - TkDestroyRegion(rgn); + Tree_FreeRegion(tree, rgn); } if (tree->debug.enable && tree->debug.display && tree->debug.eraseColor) { @@ -7005,7 +7005,7 @@ Tree_InvalidateRegion( != RectangleOut) dInfo->flags |= DINFO_DRAW_HEADER; - rgn = TkCreateRegion(); + rgn = Tree_GetRegion(tree); dItem = dInfo->dItem; while (dItem != NULL) { @@ -7071,7 +7071,7 @@ Tree_InvalidateRegion( /* Invalidate part of the whitespace */ TkSubtractRegion(dInfo->wsRgn, region, dInfo->wsRgn); - TkDestroyRegion(rgn); + Tree_FreeRegion(tree, rgn); if (tree->debug.enable && tree->debug.display && tree->debug.eraseColor) { Tk_FillRegion(tree->display, Tk_WindowId(tree->tkwin), @@ -7180,7 +7180,7 @@ TreeDInfo_Init( gcValues.graphics_exposures = True; dInfo->scrollGC = Tk_GetGC(tree->tkwin, GCGraphicsExposures, &gcValues); dInfo->flags = DINFO_OUT_OF_DATE; - dInfo->wsRgn = TkCreateRegion(); + dInfo->wsRgn = Tree_GetRegion(tree); Tcl_InitHashTable(&dInfo->itemVisHash, TCL_ONE_WORD_KEYS); tree->dInfo = dInfo; } @@ -7236,7 +7236,7 @@ TreeDInfo_Free( ckfree((char *) dInfo->xScrollIncrements); if (dInfo->yScrollIncrements != NULL) ckfree((char *) dInfo->yScrollIncrements); - TkDestroyRegion(dInfo->wsRgn); + Tree_FreeRegion(tree, dInfo->wsRgn); #ifdef DCOLUMN hPtr = Tcl_FirstHashEntry(&dInfo->itemVisHash, &search); while (hPtr != NULL) { diff --git a/generic/tkTreeElem.c b/generic/tkTreeElem.c index 98e761a..c0cd626 100644 --- a/generic/tkTreeElem.c +++ b/generic/tkTreeElem.c @@ -5,7 +5,7 @@ * * Copyright (c) 2002-2006 Tim Baker * - * RCS: @(#) $Id: tkTreeElem.c,v 1.57 2006/12/06 00:03:21 treectrl Exp $ + * RCS: @(#) $Id: tkTreeElem.c,v 1.58 2006/12/06 00:52:04 treectrl Exp $ */ #include "tkTreeCtrl.h" @@ -3020,7 +3020,7 @@ static void DisplayProcText(ElementArgs *args) /* Use clipping if text is taller than display height */ if (height > args->display.height) { XRectangle rect; - clipRgn = TkCreateRegion(); + clipRgn = Tree_GetRegion(tree); rect.x = x; rect.y = y; rect.width = args->display.width; @@ -3032,7 +3032,7 @@ static void DisplayProcText(ElementArgs *args) layout, x, y, 0, -1, underline); if (clipRgn != NULL) { UnsetClipMask(tree, args->display.drawable, gc); - TkDestroyRegion(clipRgn); + Tree_FreeRegion(tree, clipRgn); } return; } @@ -3054,7 +3054,7 @@ static void DisplayProcText(ElementArgs *args) /* Use clipping if text is taller than display height */ if (height > args->display.height) { XRectangle rect; - clipRgn = TkCreateRegion(); + clipRgn = Tree_GetRegion(tree); rect.x = x; rect.y = y; rect.width = args->display.width; @@ -3102,7 +3102,7 @@ static void DisplayProcText(ElementArgs *args) } if (clipRgn != NULL) { UnsetClipMask(tree, args->display.drawable, gc); - TkDestroyRegion(clipRgn); + Tree_FreeRegion(tree, clipRgn); } } diff --git a/generic/tkTreeUtils.c b/generic/tkTreeUtils.c index 2b81889..f4d6e4b 100644 --- a/generic/tkTreeUtils.c +++ b/generic/tkTreeUtils.c @@ -5,7 +5,7 @@ * * Copyright (c) 2002-2006 Tim Baker * - * RCS: @(#) $Id: tkTreeUtils.c,v 1.58 2006/12/06 00:03:22 treectrl Exp $ + * RCS: @(#) $Id: tkTreeUtils.c,v 1.59 2006/12/06 00:52:04 treectrl Exp $ */ #include "tkTreeCtrl.h" @@ -569,7 +569,7 @@ DotRect_Setup( dotState->gc = Tk_GetGC(tree->tkwin, mask, &gcValues); /* Keep drawing inside the contentbox */ - dotState->rgn = TkCreateRegion(); + dotState->rgn = Tree_GetRegion(tree); xrect.x = Tree_ContentLeft(tree); xrect.y = Tree_ContentTop(tree); xrect.width = Tree_ContentRight(tree) - xrect.x; @@ -721,6 +721,7 @@ DotRect_Restore( SetGWorld(dotState->saveWorld, dotState->saveDevice); #else XSetClipMask(dotState->tree->display, dotState->gc, None); + Tree_FreeRegion(dotState->tree, dotState->rgn); Tk_FreeGC(dotState->tree->display, dotState->gc); #endif } @@ -780,6 +781,64 @@ DrawXORLine( /* *---------------------------------------------------------------------- * + * Tree_GetRegion -- + * + * Return a pre-allocated TkRegion or create a new one. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +TkRegion +Tree_GetRegion( + TreeCtrl *tree /* Widget info. */ + ) +{ + TkRegion region; + + if (tree->regionStackLen == 0) { + return TkCreateRegion(); + } + region = tree->regionStack[--tree->regionStackLen]; + TkSubtractRegion(region, region, region); + return region; +} + +/* + *---------------------------------------------------------------------- + * + * Tree_FreeRegion -- + * + * Push a region onto the free stack. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +Tree_FreeRegion( + TreeCtrl *tree, /* Widget info. */ + TkRegion region /* Region being released. */ + ) +{ + if (tree->regionStackLen == sizeof(tree->regionStack) / sizeof(TkRegion)) + panic("Tree_FreeRegion: the stack is full"); + tree->regionStack[tree->regionStackLen++] = region; +} + +/* + *---------------------------------------------------------------------- + * * Tk_FillRegion -- * * Paint a region with the foreground color of a graphics context. -- cgit v0.12