summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog8
-rw-r--r--generic/tkImgPhoto.c40
-rw-r--r--generic/tkInt.h7
-rw-r--r--macosx/tkMacOSXRegion.c70
-rw-r--r--unix/tkUnix.c61
-rw-r--r--win/tkWinRegion.c63
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 <donal.k.fellows@man.ac.uk>
+
+ * 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 <donal.k.fellows@man.ac.uk>
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 <tkInt.h>
@@ -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.