From b646dee7570b4d082ceac3d8a05e48f45eacbfc5 Mon Sep 17 00:00:00 2001 From: dkf Date: Tue, 26 Oct 2004 13:15:07 +0000 Subject: Attempt to fix [Bug 919066] by allowing the code that creates the region much more knowledge of the platform functions available to it. --- ChangeLog | 8 ++++++ generic/tkImgPhoto.c | 40 ++++++++-------------------- generic/tkInt.h | 7 ++++- macosx/tkMacOSXRegion.c | 70 +++++++++++++++++++++++++++++++++++++++++++++---- unix/tkUnix.c | 61 +++++++++++++++++++++++++++++++++++++++++- win/tkWinRegion.c | 63 +++++++++++++++++++++++++++++++++++++++++++- 6 files changed, 212 insertions(+), 37 deletions(-) diff --git a/ChangeLog b/ChangeLog index a7b2e27..7dec571 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2004-10-26 Donal K. Fellows + + * macosx/tkMacOSXRegion.c (TkpBuildRegionFromAlphaData): + * win/tkWinRegion.c (TkpBuildRegionFromAlphaData): Factor out the + * unix/tkUnix.c (TkpBuildRegionFromAlphaData): building of region + * generic/tkImgPhoto.c (Tk_PhotoPutBlock): data to permit + better implementations on particular platforms. [Bug 919066] + 2004-10-24 Donal K. Fellows TIP#177 AND TIP#179 IMPLEMENTATIONS diff --git a/generic/tkImgPhoto.c b/generic/tkImgPhoto.c index b997f28..66ed41f 100644 --- a/generic/tkImgPhoto.c +++ b/generic/tkImgPhoto.c @@ -17,7 +17,7 @@ * Department of Computer Science, * Australian National University. * - * RCS: @(#) $Id: tkImgPhoto.c,v 1.49 2004/08/04 14:47:33 dkf Exp $ + * RCS: @(#) $Id: tkImgPhoto.c,v 1.50 2004/10/26 13:15:09 dkf Exp $ */ #include "tkInt.h" @@ -4558,34 +4558,16 @@ Tk_PhotoPutBlock(interp, handle, blockPtr, x, y, width, height, compRule) TkDestroyRegion(workRgn); } - destLinePtr = masterPtr->pix32 + (y * masterPtr->width + x) * 4 + 3; - for (y1 = 0; y1 < height; y1++) { - x1 = 0; - destPtr = destLinePtr; - while (x1 < width) { - /* search for first non-transparent pixel */ - while ((x1 < width) && !*destPtr) { - x1++; - destPtr += 4; - } - end = x1; - /* search for first transparent pixel */ - while ((end < width) && *destPtr) { - end++; - destPtr += 4; - } - if (end > x1) { - rect.x = x + x1; - rect.y = y + y1; - rect.width = end - x1; - rect.height = 1; - TkUnionRectWithRegion(&rect, masterPtr->validRegion, - masterPtr->validRegion); - } - x1 = end; - } - destLinePtr += masterPtr->width * 4; - } + /* + * Factorize out the main part of the building of the region + * data to allow for more efficient per-platform + * implementations. [Bug 919066] + */ + + TkpBuildRegionFromAlphaData(masterPtr->validRegion, (unsigned) x, + (unsigned) y, (unsigned) width, (unsigned) height, + masterPtr->pix32 + (y * masterPtr->width + x) * 4 + 3, + 4, (unsigned) masterPtr->width * 4); } else { rect.x = x; rect.y = y; diff --git a/generic/tkInt.h b/generic/tkInt.h index 4909404..58482f9 100644 --- a/generic/tkInt.h +++ b/generic/tkInt.h @@ -11,7 +11,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: $Id: tkInt.h,v 1.63 2004/10/05 22:04:44 hobbs Exp $ + * RCS: $Id: tkInt.h,v 1.64 2004/10/26 13:15:09 dkf Exp $ */ #ifndef _TKINT @@ -1176,6 +1176,11 @@ EXTERN void TkCreateExitHandler _ANSI_ARGS_((Tcl_ExitProc *proc, EXTERN void TkDeleteExitHandler _ANSI_ARGS_((Tcl_ExitProc *proc, ClientData clientData)); EXTERN Tcl_ExitProc TkFinalize; +EXTERN void TkpBuildRegionFromAlphaData _ANSI_ARGS_(( + TkRegion region, unsigned int x, unsigned int y, + unsigned int width, unsigned int height, + unsigned char *dataPtr, unsigned int pixelStride, + unsigned int lineStride)); /* * Unsupported commands. diff --git a/macosx/tkMacOSXRegion.c b/macosx/tkMacOSXRegion.c index 0fce0c0..2f12798 100644 --- a/macosx/tkMacOSXRegion.c +++ b/macosx/tkMacOSXRegion.c @@ -9,7 +9,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMacOSXRegion.c,v 1.2 2002/08/31 06:12:30 das Exp $ + * RCS: @(#) $Id: tkMacOSXRegion.c,v 1.3 2004/10/26 13:15:09 dkf Exp $ */ #include "tkInt.h" @@ -139,7 +139,7 @@ TkUnionRectWithRegion( tmpRgn = NewRgn(); } SetRectRgn(tmpRgn, rectangle->x, rectangle->y, - rectangle->x + rectangle->width, rectangle->y + rectangle->height); + rectangle->x + rectangle->width, rectangle->y + rectangle->height); UnionRgn(srcRgn, tmpRgn, destRgn); } @@ -177,11 +177,11 @@ TkRectInRegion( SetRectRgn(rectRgn, x, y, x + width, y + height); SectRgn(rgn, rectRgn, destRgn); if (EmptyRgn(destRgn)) { - result = RectangleOut; + result = RectangleOut; } else if (EqualRgn(rgn, destRgn)) { - result = RectangleIn; + result = RectangleIn; } else { - result = RectanglePart; + result = RectanglePart; } DisposeRgn(rectRgn); DisposeRgn(destRgn); @@ -250,3 +250,63 @@ TkSubtractRegion( DiffRgn(srcRgnA, srcRgnB, destRgn); } + +/* + *---------------------------------------------------------------------- + * + * TkpBuildRegionFromAlphaData -- + * + * Set up a rectangle of the given region based on the supplied + * alpha data. + * + * Results: + * None + * + * Side effects: + * The region is updated, with extra pixels added to it. + * + *---------------------------------------------------------------------- + */ + +void +TkpBuildRegionFromAlphaData( + TkRegion region, /* Region to update. */ + unsigned int x, /* Where in region to update. */ + unsigned int y, /* Where in region to update. */ + unsigned int width, /* Size of rectangle to update. */ + unsigned int height, /* Size of rectangle to update. */ + unsigned char *dataPtr, /* Data to read from. */ + unsigned int pixelStride, /* num bytes from one piece of alpha + * data to the next in the line. */ + unsigned int lineStride) /* num bytes from one line of alpha + * data to the next line. */ +{ + unsigned char *lineDataPtr; + unsigned int x1, y1, end; + XRectangle rect; + + for (y1 = 0; y1 < height; y1++) { + lineDataPtr = dataPtr; + for {x1 = 0; x1 < width; x1 = end) { + /* search for first non-transparent pixel */ + while ((x1 < width) && !*lineDataPtr) { + x1++; + lineDataPtr += pixelStride; + } + end = x1; + /* search for first transparent pixel */ + while ((end < width) && *lineDataPtr) { + end++; + lineDataPtr += pixelStride; + } + if (end > x1) { + rect.x = x + x1; + rect.y = y + y1; + rect.width = end - x1; + rect.height = 1; + TkUnionRectWithRegion(&rect, region, region); + } + } + dataPtr += lineStride; + } +} diff --git a/unix/tkUnix.c b/unix/tkUnix.c index 0d6ecc5..65f1a90 100644 --- a/unix/tkUnix.c +++ b/unix/tkUnix.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: tkUnix.c,v 1.5 2002/01/25 21:09:37 dgp Exp $ + * RCS: @(#) $Id: tkUnix.c,v 1.6 2004/10/26 13:15:09 dkf Exp $ */ #include @@ -106,3 +106,62 @@ Tk_UpdatePointer(tkwin, x, y, state) * This function intentionally left blank */ } + +/* + *---------------------------------------------------------------------- + * + * TkpBuildRegionFromAlphaData -- + * + * Set up a rectangle of the given region based on the supplied + * alpha data. + * + * Results: + * None + * + * Side effects: + * The region is updated, with extra pixels added to it. + * + *---------------------------------------------------------------------- + */ + +void +TkpBuildRegionFromAlphaData(region, x, y, width, height, dataPtr, + pixelStride, lineStride) + TkRegion region; + unsigned int x, y; /* Where in region to update. */ + unsigned int width, height; /* Size of rectangle to update. */ + unsigned char *dataPtr; /* Data to read from. */ + unsigned int pixelStride; /* num bytes from one piece of alpha + * data to the next in the line. */ + unsigned int lineStride; /* num bytes from one line of alpha + * data to the next line. */ +{ + unsigned char *lineDataPtr; + unsigned int x1, y1, end; + XRectangle rect; + + for (y1 = 0; y1 < height; y1++) { + lineDataPtr = dataPtr; + for (x1 = 0; x1 < width; x1 = end) { + /* search for first non-transparent pixel */ + while ((x1 < width) && !*lineDataPtr) { + x1++; + lineDataPtr += pixelStride; + } + end = x1; + /* search for first transparent pixel */ + while ((end < width) && *lineDataPtr) { + end++; + lineDataPtr += pixelStride; + } + if (end > x1) { + rect.x = x + x1; + rect.y = y + y1; + rect.width = end - x1; + rect.height = 1; + TkUnionRectWithRegion(&rect, region, region); + } + } + dataPtr += lineStride; + } +} diff --git a/win/tkWinRegion.c b/win/tkWinRegion.c index 8a50620..27a74b5 100644 --- a/win/tkWinRegion.c +++ b/win/tkWinRegion.c @@ -8,7 +8,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkWinRegion.c,v 1.3 2002/06/14 13:35:49 dkf Exp $ + * RCS: @(#) $Id: tkWinRegion.c,v 1.4 2004/10/26 13:15:09 dkf Exp $ */ #include "tkWinInt.h" @@ -147,6 +147,67 @@ TkUnionRectWithRegion(rectangle, src_region, dest_region_return) /* *---------------------------------------------------------------------- * + * TkpBuildRegionFromAlphaData -- + * + * Set up a rectangle of the given region based on the supplied + * alpha data. + * + * Results: + * None + * + * Side effects: + * The region is updated, with extra pixels added to it. + * + *---------------------------------------------------------------------- + */ + +void +TkpBuildRegionFromAlphaData(region, x, y, width, height, dataPtr, + pixelStride, lineStride) + TkRegion region; + unsigned int x, y; /* Where in region to update. */ + unsigned int width, height; /* Size of rectangle to update. */ + unsigned char *dataPtr; /* Data to read from. */ + unsigned int pixelStride; /* num bytes from one piece of alpha + * data to the next in the line. */ + unsigned int lineStride; /* num bytes from one line of alpha + * data to the next line. */ +{ + unsigned char *lineDataPtr; + unsigned int x1, y1, end; + HRGN rectRgn = CreateRectRgn(0,0,1,1); /* Workspace region. */ + + for (y1 = 0; y1 < height; y1++) { + lineDataPtr = dataPtr; + for {x1 = 0; x1 < width; x1 = end) { + /* search for first non-transparent pixel */ + while ((x1 < width) && !*lineDataPtr) { + x1++; + lineDataPtr += pixelStride; + } + end = x1; + /* search for first transparent pixel */ + while ((end < width) && *lineDataPtr) { + end++; + lineDataPtr += pixelStride; + } + if (end > x1) { + /* + * Manipulate Win32 regions directly; it's more efficient. + */ + SetRectRgn(rectRgn, x+x1, y+y1, x+end, y+y1+1); + CombineRgn((HRGN) region, (HRGN) region, rectRgn, RGN_OR); + } + } + dataPtr += lineStride; + } + + DeleteObject(rectRgn); +} + +/* + *---------------------------------------------------------------------- + * * TkRectInRegion -- * * Test whether a given rectangle overlaps with a region. -- cgit v0.12