From 8c9c2515b6c3ff39cf095d04bbcb0e2192d9ac41 Mon Sep 17 00:00:00 2001 From: das Date: Wed, 14 Jun 2006 21:20:11 +0000 Subject: * macosx/tkMacOSXSubwindows.c (TkMacOSXInvalidateWindow): ensure invalid clip regions are recreated via TkMacOSXUpdateClipRgn() before they are used; correct call order of TkMacOSXInvalidateWindow() and TkMacOSXInvalClipRgns() throughout. [Bug 1501922] * macosx/tkMacOSXDraw.c (TkPutImage): implement drawing of very wide images in slices of less than 4096 pixels to workaround CopyBits limitation. [Bug 950121] --- ChangeLog | 31 ++++--- macosx/tkMacOSXDraw.c | 202 ++++++++++++++++++++++++++++---------------- macosx/tkMacOSXSubwindows.c | 20 ++--- 3 files changed, 160 insertions(+), 93 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6f06c34..5cd6786 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,19 +1,30 @@ +2006-06-14 Daniel Steffen + + * macosx/tkMacOSXSubwindows.c (TkMacOSXInvalidateWindow): ensure invalid + clip regions are recreated via TkMacOSXUpdateClipRgn() before they are + used; correct call order of TkMacOSXInvalidateWindow() and + TkMacOSXInvalClipRgns() throughout. [Bug 1501922] + + * macosx/tkMacOSXDraw.c (TkPutImage): implement drawing of very wide + images in slices of less than 4096 pixels to workaround CopyBits + limitation. [Bug 950121] + 2006-06-09 Don Porter - * generic/tkMain.c: Added Tcl_Preserve() call on the master - interp as crash protection against any Tcl_DeleteInterp() call - that might happen. + * generic/tkMain.c: Added Tcl_Preserve() call on the master + interp as crash protection against any Tcl_DeleteInterp() call + that might happen. -2006-06-05 Don Porter +2006-06-05 Don Porter - * generic/tkInt.h: Thread safety for the data structures of - * generic/tkConsole.c: the wish [console]. [Bug 1188340]. + * generic/tkInt.h: Thread safety for the data structures of + * generic/tkConsole.c: the wish [console]. [Bug 1188340]. -2006-06-01 Don Porter +2006-06-01 Don Porter - * generic/tkConsole.c: Added Tcl_RegisterChannel() calls to bump - the refcount of channels passed to Tcl_SetStdChannel(). This prevents - early free-ing of the channels that leads to crashes. [Bug 912571]. + * generic/tkConsole.c: Added Tcl_RegisterChannel() calls to bump + the refcount of channels passed to Tcl_SetStdChannel(). This prevents + early free-ing of the channels that leads to crashes. [Bug 912571]. 2006-05-29 Jeff Hobbs diff --git a/macosx/tkMacOSXDraw.c b/macosx/tkMacOSXDraw.c index 9302fe6..befcd5e 100644 --- a/macosx/tkMacOSXDraw.c +++ b/macosx/tkMacOSXDraw.c @@ -12,7 +12,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMacOSXDraw.c,v 1.2.2.16 2006/05/16 07:33:50 das Exp $ + * RCS: @(#) $Id: tkMacOSXDraw.c,v 1.2.2.17 2006/06/14 21:20:12 das Exp $ */ #include "tkMacOSXInt.h" @@ -398,16 +398,17 @@ TkPutImage( const BitMap * destBits; MacDrawable *dstDraw = (MacDrawable *) d; int i, j; - BitMap bitmap; char *newData = NULL; Rect destRect, srcRect, *destPtr, *srcPtr; - - destPort = TkMacOSXGetDrawablePort(d); + char *dataPtr, *newPtr, *oldPtr; + int rowBytes = image->bytes_per_line; + int slices, sliceRowBytes, lastSliceRowBytes, sliceWidth, lastSliceWidth; display->request++; GetGWorld(&saveWorld, &saveDevice); + destPort = TkMacOSXGetDrawablePort(d); SetGWorld(destPort, NULL); - + destBits = GetPortBitMapForCopyBits(destPort); TkMacOSXSetUpClippingRgn(d); srcPtr = &srcRect; @@ -431,81 +432,136 @@ TkPutImage( } if (image->obdata) { - /* Image from XGetImage, copy from containing GWorld directly */ - GWorldPtr srcPort = TkMacOSXGetDrawablePort((Drawable)image->obdata); - CopyBits(GetPortBitMapForCopyBits(srcPort), - GetPortBitMapForCopyBits(destPort), - srcPtr, destPtr, srcCopy, NULL); + /* Image from XGetImage, copy from containing GWorld directly */ + GWorldPtr srcPort = TkMacOSXGetDrawablePort((Drawable)image->obdata); + CopyBits(GetPortBitMapForCopyBits(srcPort), + destBits, srcPtr, destPtr, srcCopy, NULL); } else if (image->depth == 1) { - /* - * This code assumes a pixel depth of 1 - */ - - bitmap.bounds.top = bitmap.bounds.left = 0; - bitmap.bounds.right = (short) image->width; - bitmap.bounds.bottom = (short) image->height; - if ((image->bytes_per_line % 2) == 1) { - char *newPtr, *oldPtr; - newData = (char *) ckalloc(image->height * - (image->bytes_per_line + 1)); - newPtr = newData; - oldPtr = image->data; - for (i = 0; i < image->height; i++) { - for (j = 0; j < image->bytes_per_line; j++) { - *newPtr = InvertByte((unsigned char) *oldPtr); - newPtr++, oldPtr++; - } - *newPtr = 0; - newPtr++; - } - bitmap.baseAddr = newData; - bitmap.rowBytes = image->bytes_per_line + 1; - } else { - size_t size = image->height * image->bytes_per_line; - newData = (char *) ckalloc((int) size); - for (i = 0; i < size; i++) { - newData[i] = InvertByte((unsigned char) image->data[i]); - } - bitmap.baseAddr = newData; - bitmap.rowBytes = image->bytes_per_line; - } - destBits = GetPortBitMapForCopyBits(destPort); - CopyBits(&bitmap, destBits, srcPtr, destPtr, srcCopy, NULL); + /* + * BW image + */ + const int maxRowBytes = 0x3ffe; + BitMap bitmap; + int odd; + + if (rowBytes > maxRowBytes) { + slices = rowBytes / maxRowBytes; + sliceRowBytes = maxRowBytes; + lastSliceRowBytes = rowBytes - (slices * maxRowBytes); + if (!lastSliceRowBytes) { + slices--; + lastSliceRowBytes = maxRowBytes; + } + sliceWidth = (long) image->width * maxRowBytes / rowBytes; + lastSliceWidth = image->width - (sliceWidth * slices); + } else { + slices = 0; + sliceRowBytes = lastSliceRowBytes = rowBytes; + sliceWidth = lastSliceWidth = image->width; + } + bitmap.bounds.top = bitmap.bounds.left = 0; + bitmap.bounds.bottom = (short) image->height; + dataPtr = image->data; + do { + if (slices) { + bitmap.bounds.right = bitmap.bounds.left + sliceWidth; + } else { + sliceRowBytes = lastSliceRowBytes; + bitmap.bounds.right = bitmap.bounds.left + lastSliceWidth; + } + oldPtr = dataPtr; + odd = sliceRowBytes % 2; + if (!newData) { + newData = (char *) ckalloc(image->height * (sliceRowBytes + odd)); + } + newPtr = newData; + for (i = 0; i < image->height; i++) { + for (j = 0; j < sliceRowBytes; j++) { + *newPtr = InvertByte((unsigned char) *oldPtr); + newPtr++; oldPtr++; + } + if (odd) { + *newPtr++ = 0; + } + oldPtr += rowBytes - sliceRowBytes; + } + bitmap.baseAddr = newData; + bitmap.rowBytes = sliceRowBytes + odd; + CopyBits(&bitmap, destBits, srcPtr, destPtr, srcCopy, NULL); + if (slices) { + bitmap.bounds.left = bitmap.bounds.right; + dataPtr += sliceRowBytes; + } + } while (slices--); } else { - /* - * Color image - */ - PixMap pixmap; - - pixmap.bounds.left = 0; - pixmap.bounds.top = 0; - pixmap.bounds.right = (short) image->width; - pixmap.bounds.bottom = (short) image->height; - pixmap.pixelType = RGBDirect; - pixmap.pmVersion = baseAddr32; /* 32bit clean */ - pixmap.packType = 0; - pixmap.packSize = 0; - pixmap.hRes = 0x00480000; - pixmap.vRes = 0x00480000; - pixmap.pixelSize = 32; - pixmap.cmpCount = 3; - pixmap.cmpSize = 8; + /* + * Color image + */ + const int maxRowBytes = 0x3ffc; + PixMap pixmap; + + pixmap.bounds.left = 0; + pixmap.bounds.top = 0; + pixmap.bounds.bottom = (short) image->height; + pixmap.pixelType = RGBDirect; + pixmap.pmVersion = baseAddr32; /* 32bit clean */ + pixmap.packType = 0; + pixmap.packSize = 0; + pixmap.hRes = 0x00480000; + pixmap.vRes = 0x00480000; + pixmap.pixelSize = 32; + pixmap.cmpCount = 3; + pixmap.cmpSize = 8; #ifdef WORDS_BIGENDIAN - pixmap.pixelFormat = k32ARGBPixelFormat; + pixmap.pixelFormat = k32ARGBPixelFormat; #else - pixmap.pixelFormat = k32BGRAPixelFormat; + pixmap.pixelFormat = k32BGRAPixelFormat; #endif - pixmap.pmTable = NULL; - pixmap.pmExt = 0; - pixmap.baseAddr = image->data; - pixmap.rowBytes = image->bytes_per_line | 0x8000; - - CopyBits((BitMap *) &pixmap, GetPortBitMapForCopyBits(destPort), - srcPtr, destPtr, srcCopy, NULL); + pixmap.pmTable = NULL; + pixmap.pmExt = 0; + if (rowBytes > maxRowBytes) { + slices = rowBytes / maxRowBytes; + sliceRowBytes = maxRowBytes; + lastSliceRowBytes = rowBytes - (slices * maxRowBytes); + if (!lastSliceRowBytes) { + slices--; + lastSliceRowBytes = maxRowBytes; + } + sliceWidth = (long) image->width * maxRowBytes / rowBytes; + lastSliceWidth = image->width - (sliceWidth * slices); + dataPtr = image->data; + newData = (char *) ckalloc(image->height * sliceRowBytes); + do { + if (slices) { + pixmap.bounds.right = pixmap.bounds.left + sliceWidth; + } else { + sliceRowBytes = lastSliceRowBytes; + pixmap.bounds.right = pixmap.bounds.left + lastSliceWidth; + } + oldPtr = dataPtr; + newPtr = newData; + for (i = 0; i < image->height; i++) { + memcpy(newPtr, oldPtr, sliceRowBytes); + oldPtr += rowBytes; + newPtr += sliceRowBytes; + } + pixmap.baseAddr = newData; + pixmap.rowBytes = sliceRowBytes | 0x8000; + CopyBits((BitMap *) &pixmap, destBits, srcPtr, destPtr, srcCopy, NULL); + if (slices) { + pixmap.bounds.left = pixmap.bounds.right; + dataPtr += sliceRowBytes; + } + } while (slices--); + } else { + pixmap.bounds.right = (short) image->width; + pixmap.baseAddr = image->data; + pixmap.rowBytes = rowBytes | 0x8000; + CopyBits((BitMap *) &pixmap, destBits, srcPtr, destPtr, srcCopy, NULL); + } } - if (newData != NULL) { - ckfree(newData); + ckfree(newData); } SetGWorld(saveWorld, saveDevice); } diff --git a/macosx/tkMacOSXSubwindows.c b/macosx/tkMacOSXSubwindows.c index b12c620..55dc905 100644 --- a/macosx/tkMacOSXSubwindows.c +++ b/macosx/tkMacOSXSubwindows.c @@ -10,7 +10,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMacOSXSubwindows.c,v 1.2.2.10 2006/05/12 18:17:55 das Exp $ + * RCS: @(#) $Id: tkMacOSXSubwindows.c,v 1.2.2.11 2006/06/14 21:20:12 das Exp $ */ #include "tkMacOSXInt.h" @@ -231,8 +231,8 @@ XMapWindow( * Generate damage for that area of the window */ SetGWorld(destPort, NULL); - TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW); TkMacOSXInvalClipRgns((Tk_Window) macWin->winPtr->parentPtr); + TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW); } } @@ -368,8 +368,8 @@ XResizeWindow( if (havePort) { SetPort(destPort); - TkMacOSXInvalClipRgns((Tk_Window) macParent->winPtr); TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW); + TkMacOSXInvalClipRgns((Tk_Window) macParent->winPtr); } deltaX = macParent->xOff + macWin->winPtr->changes.x - macWin->xOff; @@ -402,8 +402,8 @@ XResizeWindow( if (havePort) { SetPort(destPort); - TkMacOSXInvalClipRgns((Tk_Window) macParent->winPtr); TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW); + TkMacOSXInvalClipRgns((Tk_Window) macParent->winPtr); } deltaX = - macWin->xOff; deltaY = - macWin->yOff; @@ -497,14 +497,12 @@ XMoveResizeWindow( * region. It is currently assumed that Tk will need * to completely redraw anway. */ - if (havePort) { SetPort( destPort); SizeWindow(GetWindowFromPort(destPort), (short) width, (short) height, false); MoveWindowStructure(GetWindowFromPort(destPort), x, y); - /* TODO: is the following right? */ TkMacOSXInvalidateWindow(macWin, TK_WINDOW_ONLY); TkMacOSXInvalClipRgns((Tk_Window) macWin->winPtr); } @@ -541,8 +539,8 @@ XMoveResizeWindow( if (havePort) { SetPort( destPort); - TkMacOSXInvalClipRgns((Tk_Window) macParent->winPtr); TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW); + TkMacOSXInvalClipRgns((Tk_Window) macParent->winPtr); } deltaX = - macWin->xOff; @@ -615,7 +613,6 @@ XMoveWindow( SetPort(destPort); MoveWindowStructure( GetWindowFromPort(destPort), x, y); - /* TODO: is the following right? */ TkMacOSXInvalidateWindow(macWin, TK_WINDOW_ONLY); TkMacOSXInvalClipRgns((Tk_Window) macWin->winPtr); } @@ -651,8 +648,8 @@ XMoveWindow( if (havePort) { SetPort(destPort); - TkMacOSXInvalClipRgns((Tk_Window) macParent->winPtr); TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW); + TkMacOSXInvalClipRgns((Tk_Window) macParent->winPtr); } deltaX = - macWin->xOff; @@ -1046,8 +1043,11 @@ TkMacOSXInvalidateWindow( grafPtr = TkMacOSXGetDrawablePort((Drawable)macWin); windowRef = GetWindowFromPort(grafPtr); + if (macWin->flags & TK_CLIP_INVALID) { + TkMacOSXUpdateClipRgn(macWin->winPtr); + } if (flag == TK_WINDOW_ONLY) { - InvalWindowRgn(windowRef,macWin->clipRgn); + InvalWindowRgn(windowRef, macWin->clipRgn); } else { if (!EmptyRgn(macWin->aboveClipRgn)) { InvalWindowRgn(windowRef, macWin->aboveClipRgn); -- cgit v0.12