summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog46
-rw-r--r--doc/FindPhoto.337
-rw-r--r--doc/photo.n14
-rw-r--r--generic/tk.decls18
-rw-r--r--generic/tk.h31
-rw-r--r--generic/tkDecls.h43
-rw-r--r--generic/tkImgGIF.c5
-rw-r--r--generic/tkImgPPM.c5
-rw-r--r--generic/tkImgPhoto.c532
-rw-r--r--generic/tkInt.decls6
-rw-r--r--generic/tkIntDecls.h33
-rw-r--r--generic/tkStubInit.c17
-rw-r--r--mac/tkMacRegion.c32
-rw-r--r--tests/imgPhoto.test49
-rw-r--r--unix/tkUnixPort.h4
-rw-r--r--win/tkWinRegion.c27
16 files changed, 675 insertions, 224 deletions
diff --git a/ChangeLog b/ChangeLog
index 2ddbb75..58650ea 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,49 @@
+2002-06-14 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * tests/imgPhoto.test: Added tests of -compositingrule
+
+ * doc/photo.n: Added documentation for "-compositingrule".
+ * generic/tkImgPhoto.c (ImgPhotoCmd,ParseSubcommandOptions): New
+ "-compositingrule" option for [$photo copy] subcommand, using
+ OPT_COMPOSITE flag and compositingRule field in SubcommandOptions
+ structure.
+
+ * doc/FindPhoto.3: Documented the extra argument for the
+ compositing rule and the action to take if anyone wants to
+ maintain total backward-compatability.
+
+ * generic/tk.h (TK_PHOTO_COMPOSITE_*): Defined values for use as
+ compositing rules.
+ (USE_OLD_PHOTO_PUT_BLOCK): Added a way for users to select the old
+ interface to Tk_PhotoPutBlock to provide an easier upgrade path.
+
+ * generic/tk.decls: Alter Tk_PhotoPut*Block to Tk_PhotoPut*Block_Old
+ and introduce new slots for the old name of function with an extra
+ argument at the end for the compositing rule.
+
+ * generic/tkImgPhoto.c (ImgPhotoCmd): Updated "transparency set"
+ subcommand to use TkSubtractRegion().
+
+ * win/tkWinRegion.c (TkSubtractRegion):
+ * mac/tkMacRegion.c (TkSubtractRegion):
+ * generic/tkInt.decls (TkSubtractRegion):
+ * unix/tkUnixPort.h (TkSubtractRegion): Added function to perform
+ the set-difference operation on regions; it seems all platforms
+ can support it, and it makes removing rectangular bits from
+ regions much easier.
+
+ * generic/tkImgPPM.c (FileReadPPM): Reading a PPM/PGM always uses
+ the SET compositing rule because it is faster and the format does
+ not have any transparency information.
+
+ * generic/tkImgGIF.c (FileReadGIF): Reading a GIF always uses the
+ SET compositing rule because GIF files model transparency as a
+ single special colour.
+
+ * generic/tkImgPhoto.c (Tk_PhotoPutBlock, Tk_PhotoPutZoomedBlock):
+ Added a compositing rule to allow better control over what happens
+ to transparent pixels when inserting data into a photo image.
+
2002-06-13 Mo DeJong <mdejong@users.sourceforge.net>
* tests/winfo.test: Add basic tests for winfo ismapped.
diff --git a/doc/FindPhoto.3 b/doc/FindPhoto.3
index 47f5df2..d1c96d1 100644
--- a/doc/FindPhoto.3
+++ b/doc/FindPhoto.3
@@ -9,7 +9,7 @@
'\" Department of Computer Science,
'\" Australian National University.
'\"
-'\" RCS: @(#) $Id: FindPhoto.3,v 1.3 1999/10/29 03:57:40 hobbs Exp $
+'\" RCS: @(#) $Id: FindPhoto.3,v 1.4 2002/06/14 13:35:47 dkf Exp $
'\"
.so man.macros
.TH Tk_FindPhoto 3 8.0 Tk "Tk Library Procedures"
@@ -27,11 +27,11 @@ Tk_PhotoHandle
.VE
.sp
void
-\fBTk_PhotoPutBlock\fR(\fIhandle, blockPtr, x, y, width, height\fR)
+\fBTk_PhotoPutBlock\fR(\fIhandle, blockPtr, x, y, width, height, compRule\fR)
.sp
void
\fBTk_PhotoPutZoomedBlock\fR(\fIhandle, blockPtr, x, y, width, height,\
-zoomX, zoomY, subsampleX, subsampleY\fR)
+zoomX, zoomY, subsampleX, subsampleY, compRule\fR)
.sp
int
\fBTk_PhotoGetImage\fR(\fIhandle, blockPtr\fR)
@@ -69,6 +69,16 @@ to be placed within the image.
Specifies the width of the image area to be affected (for
\fBTk_PhotoPutBlock\fR) or the desired image width (for
\fBTk_PhotoExpand\fR and \fBTk_PhotoSetSize\fR).
+.VS 8.4
+.AP int compRule in
+Specifies the compositing rule used when combining transparent pixels
+in a block of data with a photo image. Must be one of
+TK_PHOTO_COMPOSITE_OVERLAY (which puts the block of data over the top
+of the existing photo image, with the previous contents showing
+through in the transparent bits) or TK_PHOTO_COMPOSITE_SET (which
+discards the existing photo image contents in the rectangle covered by
+the data block.)
+.VE 8.4
.AP int height in
Specifies the height of the image area to be affected (for
\fBTk_PhotoPutBlock\fR) or the desired image height (for
@@ -135,6 +145,17 @@ to the addresses of the bytes containing the red, green, blue and alpha
have other values, e.g., for images that are stored as separate red,
green and blue planes.
.PP
+.VS 8.4
+The \fIcompRule\fR parameter to \fBTk_PhotoPutBlock\fR specifies a
+compositing rule that says what to do with transparent pixels. The
+value TK_PHOTO_COMPOSITE_OVERLAY says that the previous contents of
+the photo image should show through, and the value
+TK_PHOTO_COMPOSITE_SET says that the previous contents of the photo
+image should be completely ignored, and the values from the block be
+copied directly across. The behavior in Tk8.3 and earlier was
+equivalent to having TK_PHOTO_COMPOSITE_OVERLAY as a compositing rule.
+.VE 8.4
+.PP
The value given for the \fIwidth\fR and \fIheight\fR parameters to
\fBTk_PhotoPutBlock\fR do not have to correspond to the values specified
in \fIblock\fR. If they are smaller, \fBTk_PhotoPutBlock\fR extracts a
@@ -193,6 +214,16 @@ calls to \fBTk_PhotoPutBlock\fR, \fBTk_PhotoPutZoomedBlock\fR or
\fBTk_PhotoGetSize\fR returns the dimensions of the image in
*\fIwidthPtr\fR and *\fIheightPtr\fR.
+.SH PORTABILITY
+.VS 8.4
+.PP
+In Tk 8.3 and earlier, \fBTk_PhotoPutBlock\fR and
+\fBTk_PhotoPutZoomedBlock\fR had different signatures. If you want to
+compile code that uses the old interface against 8.4 without updating
+your code, compile it with the flag -DUSE_OLD_PHOTO_PUT_BLOCK. Code
+linked using Stubs against older versions of Tk will continue to work.
+.VE 8.4
+
.SH CREDITS
.PP
The code for the photo image type was developed by Paul Mackerras,
diff --git a/doc/photo.n b/doc/photo.n
index 5e16f92..83a5966 100644
--- a/doc/photo.n
+++ b/doc/photo.n
@@ -9,7 +9,7 @@
'\" Department of Computer Science,
'\" Australian National University.
'\"
-'\" RCS: @(#) $Id: photo.n,v 1.10 2002/03/14 10:19:40 dkf Exp $
+'\" RCS: @(#) $Id: photo.n,v 1.11 2002/06/14 13:35:47 dkf Exp $
'\"
.so man.macros
.TH photo n 4.0 Tk "Tk Built-In Commands"
@@ -189,6 +189,18 @@ only every \fIx\fRth pixel in the X direction and \fIy\fRth pixel in
the Y direction. Negative values will cause the image to be flipped
about the Y or X axes, respectively. If \fIy\fR is not given, the
default value is the same as \fIx\fR.
+.TP
+\fB\-compositingrule \fIrule\fR
+.VS 8.4
+Specifies how transparent pixels in the source image are combined with
+the destination image. When a compositing rule of \fIoverlay\fR is
+set, the old contents of the destination image are visible, as if the
+source image were printed on a piece of transparent film and placed
+over the top of the destination. When a compositing rule of \fIset\R
+is set, the old contents of the destination image are discarded and
+the source image is used as-is. The default compositing rule is
+\fIoverlay\fR.
+.VE 8.4
.RE
.TP
\fIimageName \fBdata ?\fIoption value(s) ...\fR?
diff --git a/generic/tk.decls b/generic/tk.decls
index 78564de..445845a 100644
--- a/generic/tk.decls
+++ b/generic/tk.decls
@@ -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: tk.decls,v 1.18 2002/04/05 08:38:22 hobbs Exp $
+# RCS: @(#) $Id: tk.decls,v 1.19 2002/06/14 13:35:47 dkf Exp $
library tk
@@ -708,13 +708,13 @@ declare 143 generic {
}
declare 144 generic {
- void Tk_PhotoPutBlock (Tk_PhotoHandle handle, \
+ void Tk_PhotoPutBlock_Old (Tk_PhotoHandle handle, \
Tk_PhotoImageBlock *blockPtr, int x, int y, \
int width, int height)
}
declare 145 generic {
- void Tk_PhotoPutZoomedBlock (Tk_PhotoHandle handle, \
+ void Tk_PhotoPutZoomedBlock_Old (Tk_PhotoHandle handle, \
Tk_PhotoImageBlock *blockPtr, int x, int y, \
int width, int height, int zoomX, int zoomY, \
int subsampleX, int subsampleY)
@@ -1164,6 +1164,18 @@ declare 245 generic {
void Tk_SetCaretPos (Tk_Window tkwin, int x, int y, int height)
}
+declare 246 generic {
+ void Tk_PhotoPutBlock (Tk_PhotoHandle handle,
+ Tk_PhotoImageBlock *blockPtr, int x, int y,
+ int width, int height, int compRule)
+}
+declare 247 generic {
+ void Tk_PhotoPutZoomedBlock (Tk_PhotoHandle handle,
+ Tk_PhotoImageBlock *blockPtr, int x, int y,
+ int width, int height, int zoomX, int zoomY,
+ int subsampleX, int subsampleY, int compRule)
+}
+
# Define the platform specific public Tk interface. These functions are
# only available on the designated platform.
diff --git a/generic/tk.h b/generic/tk.h
index 2f082b1..fecb2ab 100644
--- a/generic/tk.h
+++ b/generic/tk.h
@@ -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: tk.h,v 1.58 2002/03/06 15:36:17 dkf Exp $
+ * RCS: @(#) $Id: tk.h,v 1.59 2002/06/14 13:35:47 dkf Exp $
*/
#ifndef _TK
@@ -1270,6 +1270,15 @@ typedef struct Tk_PhotoImageBlock {
} Tk_PhotoImageBlock;
/*
+ * The following values control how blocks are combined into photo
+ * images when the alpha component of a pixel is not 255, a.k.a. the
+ * compositing rule.
+ */
+
+#define TK_PHOTO_COMPOSITE_OVERLAY 0
+#define TK_PHOTO_COMPOSITE_SET 1
+
+/*
* Procedure prototypes and structures used in reading and
* writing photo images:
*/
@@ -1459,6 +1468,26 @@ typedef int (Tk_SelectionProc) _ANSI_ARGS_((ClientData clientData,
#include "tkDecls.h"
/*
+ * Allow users to say that they don't want to alter their source to
+ * add the extra argument to Tk_PhotoPutBlock(); DO NOT DEFINE THIS
+ * WHEN BUILDING TK.
+ *
+ * This goes after the inclusion of the stubbed-decls so that the
+ * declarations of what is actually there can be correct.
+ */
+
+#ifdef USE_OLD_PHOTO_PUT_BLOCK
+# ifdef Tk_PhotoPutBlock
+# undef Tk_PhotoPutBlock
+# endif
+# define Tk_PhotoPutBlock Tk_PhotoPutBlock_Old
+# ifdef Tk_PhotoPutZoomedBlock
+# undef Tk_PhotoPutZoomedBlock
+# endif
+# define Tk_PhotoPutZoomedBlock Tk_PhotoPutZoomedBlock_Old
+#endif /* USE_OLD_PHOTO_PUT_BLOCK */
+
+/*
* Tcl commands exported by Tk:
*/
diff --git a/generic/tkDecls.h b/generic/tkDecls.h
index 057295e..09e5014 100644
--- a/generic/tkDecls.h
+++ b/generic/tkDecls.h
@@ -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: tkDecls.h,v 1.18 2002/04/05 08:38:22 hobbs Exp $
+ * RCS: @(#) $Id: tkDecls.h,v 1.19 2002/06/14 13:35:47 dkf Exp $
*/
#ifndef _TKDECLS
@@ -510,11 +510,12 @@ EXTERN int Tk_ParseArgv _ANSI_ARGS_((Tcl_Interp * interp,
CONST84 char ** argv, Tk_ArgvInfo * argTable,
int flags));
/* 144 */
-EXTERN void Tk_PhotoPutBlock _ANSI_ARGS_((Tk_PhotoHandle handle,
+EXTERN void Tk_PhotoPutBlock_Old _ANSI_ARGS_((
+ Tk_PhotoHandle handle,
Tk_PhotoImageBlock * blockPtr, int x, int y,
int width, int height));
/* 145 */
-EXTERN void Tk_PhotoPutZoomedBlock _ANSI_ARGS_((
+EXTERN void Tk_PhotoPutZoomedBlock_Old _ANSI_ARGS_((
Tk_PhotoHandle handle,
Tk_PhotoImageBlock * blockPtr, int x, int y,
int width, int height, int zoomX, int zoomY,
@@ -846,6 +847,16 @@ EXTERN void Tk_SetMinimumRequestSize _ANSI_ARGS_((
/* 245 */
EXTERN void Tk_SetCaretPos _ANSI_ARGS_((Tk_Window tkwin, int x,
int y, int height));
+/* 246 */
+EXTERN void Tk_PhotoPutBlock _ANSI_ARGS_((Tk_PhotoHandle handle,
+ Tk_PhotoImageBlock * blockPtr, int x, int y,
+ int width, int height, int compRule));
+/* 247 */
+EXTERN void Tk_PhotoPutZoomedBlock _ANSI_ARGS_((
+ Tk_PhotoHandle handle,
+ Tk_PhotoImageBlock * blockPtr, int x, int y,
+ int width, int height, int zoomX, int zoomY,
+ int subsampleX, int subsampleY, int compRule));
typedef struct TkStubHooks {
struct TkPlatStubs *tkPlatStubs;
@@ -1002,8 +1013,8 @@ typedef struct TkStubs {
Tk_Window (*tk_NameToWindow) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * pathName, Tk_Window tkwin)); /* 141 */
void (*tk_OwnSelection) _ANSI_ARGS_((Tk_Window tkwin, Atom selection, Tk_LostSelProc * proc, ClientData clientData)); /* 142 */
int (*tk_ParseArgv) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin, int * argcPtr, CONST84 char ** argv, Tk_ArgvInfo * argTable, int flags)); /* 143 */
- void (*tk_PhotoPutBlock) _ANSI_ARGS_((Tk_PhotoHandle handle, Tk_PhotoImageBlock * blockPtr, int x, int y, int width, int height)); /* 144 */
- void (*tk_PhotoPutZoomedBlock) _ANSI_ARGS_((Tk_PhotoHandle handle, Tk_PhotoImageBlock * blockPtr, int x, int y, int width, int height, int zoomX, int zoomY, int subsampleX, int subsampleY)); /* 145 */
+ void (*tk_PhotoPutBlock_Old) _ANSI_ARGS_((Tk_PhotoHandle handle, Tk_PhotoImageBlock * blockPtr, int x, int y, int width, int height)); /* 144 */
+ void (*tk_PhotoPutZoomedBlock_Old) _ANSI_ARGS_((Tk_PhotoHandle handle, Tk_PhotoImageBlock * blockPtr, int x, int y, int width, int height, int zoomX, int zoomY, int subsampleX, int subsampleY)); /* 145 */
int (*tk_PhotoGetImage) _ANSI_ARGS_((Tk_PhotoHandle handle, Tk_PhotoImageBlock * blockPtr)); /* 146 */
void (*tk_PhotoBlank) _ANSI_ARGS_((Tk_PhotoHandle handle)); /* 147 */
void (*tk_PhotoExpand) _ANSI_ARGS_((Tk_PhotoHandle handle, int width, int height)); /* 148 */
@@ -1104,6 +1115,8 @@ typedef struct TkStubs {
void (*tk_SetInternalBorderEx) _ANSI_ARGS_((Tk_Window tkwin, int left, int right, int top, int bottom)); /* 243 */
void (*tk_SetMinimumRequestSize) _ANSI_ARGS_((Tk_Window tkwin, int minWidth, int minHeight)); /* 244 */
void (*tk_SetCaretPos) _ANSI_ARGS_((Tk_Window tkwin, int x, int y, int height)); /* 245 */
+ void (*tk_PhotoPutBlock) _ANSI_ARGS_((Tk_PhotoHandle handle, Tk_PhotoImageBlock * blockPtr, int x, int y, int width, int height, int compRule)); /* 246 */
+ void (*tk_PhotoPutZoomedBlock) _ANSI_ARGS_((Tk_PhotoHandle handle, Tk_PhotoImageBlock * blockPtr, int x, int y, int width, int height, int zoomX, int zoomY, int subsampleX, int subsampleY, int compRule)); /* 247 */
} TkStubs;
#ifdef __cplusplus
@@ -1696,13 +1709,13 @@ extern TkStubs *tkStubsPtr;
#define Tk_ParseArgv \
(tkStubsPtr->tk_ParseArgv) /* 143 */
#endif
-#ifndef Tk_PhotoPutBlock
-#define Tk_PhotoPutBlock \
- (tkStubsPtr->tk_PhotoPutBlock) /* 144 */
+#ifndef Tk_PhotoPutBlock_Old
+#define Tk_PhotoPutBlock_Old \
+ (tkStubsPtr->tk_PhotoPutBlock_Old) /* 144 */
#endif
-#ifndef Tk_PhotoPutZoomedBlock
-#define Tk_PhotoPutZoomedBlock \
- (tkStubsPtr->tk_PhotoPutZoomedBlock) /* 145 */
+#ifndef Tk_PhotoPutZoomedBlock_Old
+#define Tk_PhotoPutZoomedBlock_Old \
+ (tkStubsPtr->tk_PhotoPutZoomedBlock_Old) /* 145 */
#endif
#ifndef Tk_PhotoGetImage
#define Tk_PhotoGetImage \
@@ -2098,6 +2111,14 @@ extern TkStubs *tkStubsPtr;
#define Tk_SetCaretPos \
(tkStubsPtr->tk_SetCaretPos) /* 245 */
#endif
+#ifndef Tk_PhotoPutBlock
+#define Tk_PhotoPutBlock \
+ (tkStubsPtr->tk_PhotoPutBlock) /* 246 */
+#endif
+#ifndef Tk_PhotoPutZoomedBlock
+#define Tk_PhotoPutZoomedBlock \
+ (tkStubsPtr->tk_PhotoPutZoomedBlock) /* 247 */
+#endif
#endif /* defined(USE_TK_STUBS) && !defined(USE_TK_STUB_PROCS) */
diff --git a/generic/tkImgGIF.c b/generic/tkImgGIF.c
index 6fe4ed9..cad9ea8 100644
--- a/generic/tkImgGIF.c
+++ b/generic/tkImgGIF.c
@@ -29,7 +29,7 @@
* | provided "as is" without express or implied warranty. |
* +-------------------------------------------------------------------+
*
- * RCS: @(#) $Id: tkImgGIF.c,v 1.20 2002/02/19 14:05:43 dkf Exp $
+ * RCS: @(#) $Id: tkImgGIF.c,v 1.21 2002/06/14 13:35:48 dkf Exp $
*/
/*
@@ -481,7 +481,8 @@ FileReadGIF(interp, chan, fileName, format, imageHandle, destX, destY,
break;
}
- Tk_PhotoPutBlock(imageHandle, &block, destX, destY, width, height);
+ Tk_PhotoPutBlock(imageHandle, &block, destX, destY, width, height,
+ TK_PHOTO_COMPOSITE_SET);
noerror:
if (block.pixelPtr) {
diff --git a/generic/tkImgPPM.c b/generic/tkImgPPM.c
index ab99679..9715cf4 100644
--- a/generic/tkImgPPM.c
+++ b/generic/tkImgPPM.c
@@ -13,7 +13,7 @@
* Department of Computer Science,
* Australian National University.
*
- * RCS: @(#) $Id: tkImgPPM.c,v 1.9 2002/02/19 16:30:26 dkf Exp $
+ * RCS: @(#) $Id: tkImgPPM.c,v 1.10 2002/06/14 13:35:48 dkf Exp $
*/
#define USE_OLD_IMAGE
@@ -228,7 +228,8 @@ FileReadPPM(interp, chan, fileName, formatString, imageHandle, destX, destY,
}
}
block.height = nLines;
- Tk_PhotoPutBlock(imageHandle, &block, destX, destY, width, nLines);
+ Tk_PhotoPutBlock(imageHandle, &block, destX, destY, width, nLines,
+ TK_PHOTO_COMPOSITE_SET);
destY += nLines;
}
diff --git a/generic/tkImgPhoto.c b/generic/tkImgPhoto.c
index ca524df..032ce89 100644
--- a/generic/tkImgPhoto.c
+++ b/generic/tkImgPhoto.c
@@ -16,7 +16,7 @@
* Department of Computer Science,
* Australian National University.
*
- * RCS: @(#) $Id: tkImgPhoto.c,v 1.30 2002/04/12 06:48:58 hobbs Exp $
+ * RCS: @(#) $Id: tkImgPhoto.c,v 1.31 2002/06/14 13:35:48 dkf Exp $
*/
#include "tkInt.h"
@@ -232,6 +232,7 @@ struct SubcommandOptions {
int subsampleX, subsampleY; /* Values specified for -subsample option. */
Tcl_Obj *format; /* Value specified for -format option. */
XColor *background; /* Value specified for -background option. */
+ int compositingRule; /* Value specified for -compositingrule opt */
};
/*
@@ -242,6 +243,7 @@ struct SubcommandOptions {
* field of the SubcommandOptions structure if that option was specified.
*
* OPT_BACKGROUND: Set if -format option allowed/specified.
+ * OPT_COMPOSITE: Set if -compositingrule option allowed/spec'd.
* OPT_FORMAT: Set if -format option allowed/specified.
* OPT_FROM: Set if -from option allowed/specified.
* OPT_GRAYSCALE: Set if -grayscale option allowed/specified.
@@ -252,13 +254,14 @@ struct SubcommandOptions {
*/
#define OPT_BACKGROUND 1
-#define OPT_FORMAT 2
-#define OPT_FROM 4
-#define OPT_GRAYSCALE 8
-#define OPT_SHRINK 0x10
-#define OPT_SUBSAMPLE 0x20
-#define OPT_TO 0x40
-#define OPT_ZOOM 0x80
+#define OPT_COMPOSITE 2
+#define OPT_FORMAT 4
+#define OPT_FROM 8
+#define OPT_GRAYSCALE 0x10
+#define OPT_SHRINK 0x20
+#define OPT_SUBSAMPLE 0x40
+#define OPT_TO 0x80
+#define OPT_ZOOM 0x100
/*
* List of option names. The order here must match the order of
@@ -267,6 +270,7 @@ struct SubcommandOptions {
static char *optionNames[] = {
"-background",
+ "-compositingrule",
"-format",
"-from",
"-grayscale",
@@ -775,14 +779,15 @@ ImgPhotoCmd(clientData, interp, objc, objv)
options.zoomX = options.zoomY = 1;
options.subsampleX = options.subsampleY = 1;
options.name = NULL;
+ options.compositingRule = TK_PHOTO_COMPOSITE_OVERLAY;
if (ParseSubcommandOptions(&options, interp,
- OPT_FROM | OPT_TO | OPT_ZOOM | OPT_SUBSAMPLE | OPT_SHRINK,
- &index, objc, objv) != TCL_OK) {
+ OPT_FROM | OPT_TO | OPT_ZOOM | OPT_SUBSAMPLE | OPT_SHRINK |
+ OPT_COMPOSITE, &index, objc, objv) != TCL_OK) {
return TCL_ERROR;
}
if (options.name == NULL || index < objc) {
Tcl_WrongNumArgs(interp, 2, objv,
- "source-image ?-from x1 y1 x2 y2? ?-to x1 y1 x2 y2? ?-zoom x y? ?-subsample x y?");
+ "source-image ?-compositingrule rule? ?-from x1 y1 x2 y2? ?-to x1 y1 x2 y2? ?-zoom x y? ?-subsample x y?");
return TCL_ERROR;
}
@@ -858,7 +863,8 @@ ImgPhotoCmd(clientData, interp, objc, objv)
Tk_PhotoPutZoomedBlock((Tk_PhotoHandle) masterPtr, &block,
options.toX, options.toY, options.toX2 - options.toX,
options.toY2 - options.toY, options.zoomX, options.zoomY,
- options.subsampleX, options.subsampleY);
+ options.subsampleX, options.subsampleY,
+ options.compositingRule);
break;
@@ -946,9 +952,9 @@ ImgPhotoCmd(clientData, interp, objc, objv)
}
return result;
break;
- }
+ }
- case PHOTO_GET: {
+ case PHOTO_GET: {
/*
* photo get command - first parse and check parameters.
*/
@@ -979,9 +985,9 @@ ImgPhotoCmd(clientData, interp, objc, objv)
pixelPtr[2]);
Tcl_AppendResult(interp, string, (char *) NULL);
break;
- }
+ }
- case PHOTO_PUT:
+ case PHOTO_PUT:
/*
* photo put command - first parse the options and colors specified.
*/
@@ -1104,7 +1110,7 @@ ImgPhotoCmd(clientData, interp, objc, objv)
block.offset[3] = 0;
Tk_PhotoPutBlock((ClientData)masterPtr, &block,
options.toX, options.toY, options.toX2 - options.toX,
- options.toY2 - options.toY);
+ options.toY2 - options.toY, TK_PHOTO_COMPOSITE_SET);
ckfree((char *) block.pixelPtr);
break;
@@ -1326,59 +1332,43 @@ ImgPhotoCmd(clientData, interp, objc, objv)
return TCL_ERROR;
}
+ setBox.x = x;
+ setBox.y = y;
+ setBox.width = 1;
+ setBox.height = 1;
+ pixelPtr = masterPtr->pix24 + (y * masterPtr->width + x) * 4;
+
if (transFlag) {
/*
- * Make pixel transparent. Do by building a mask for
- * all the other pixels in the image and setting the
- * validRegion to the intersection of that with the
- * old validRegion. There isn't a neater way to do
- * this given the limited set of operations available
- * in the platform-independent region operations.
+ * Make pixel transparent.
*/
- TkRegion setRegion = TkCreateRegion();
-
- if (y > 0) {
- setBox.x = 0;
- setBox.y = 0;
- setBox.width = masterPtr->width;
- setBox.height = y;
- TkUnionRectWithRegion(&setBox, setRegion, setRegion);
- }
- if (x > 0) {
- setBox.x = 0;
- setBox.y = y;
- setBox.width = x;
- setBox.height = 1;
- TkUnionRectWithRegion(&setBox, setRegion, setRegion);
- }
- if (x < masterPtr->width-1) {
- setBox.x = x+1;
- setBox.y = y;
- setBox.width = masterPtr->width-1 - x;
- setBox.height = 1;
- TkUnionRectWithRegion(&setBox, setRegion, setRegion);
- }
- if (y < masterPtr->height-1) {
- setBox.x = 0;
- setBox.y = y+1;
- setBox.width = masterPtr->width;
- setBox.height = masterPtr->height-1 - y;
- TkUnionRectWithRegion(&setBox, setRegion, setRegion);
- }
- TkIntersectRegion(masterPtr->validRegion, setRegion,
+ TkRegion clearRegion = TkCreateRegion();
+
+ TkUnionRectWithRegion(&setBox, clearRegion, clearRegion);
+ TkSubtractRegion(masterPtr->validRegion, clearRegion,
masterPtr->validRegion);
- TkDestroyRegion(setRegion);
+ TkDestroyRegion(clearRegion);
+ /*
+ * Set the alpha value correctly.
+ */
+ pixelPtr[3] = 0;
} else {
/*
* Make pixel opaque.
*/
- setBox.x = x;
- setBox.y = y;
- setBox.width = 1;
- setBox.height = 1;
TkUnionRectWithRegion(&setBox, masterPtr->validRegion,
masterPtr->validRegion);
+ pixelPtr[3] = 255;
}
+
+ /*
+ * Inform the generic image code that the image
+ * has (potentially) changed.
+ */
+
+ Tk_ImageChanged(masterPtr->tkMaster, x, y, 1, 1,
+ masterPtr->width, masterPtr->height);
+ masterPtr->flags &= ~IMAGE_CHANGED;
}
}
@@ -1514,7 +1504,8 @@ ImgPhotoCmd(clientData, interp, objc, objv)
*
* This procedure is invoked to process one of the options
* which may be specified for the photo image subcommands,
- * namely, -from, -to, -zoom, -subsample, -format, and -shrink.
+ * namely, -from, -to, -zoom, -subsample, -format, -shrink,
+ * and -compositingrule.
*
* Results:
* A standard Tcl result.
@@ -1629,7 +1620,9 @@ ParseSubcommandOptions(optPtr, interp, allowedOptions, optIndexPtr, objc, objv)
}
} else if (bit == OPT_FORMAT) {
/*
- * The -format option takes a single string value.
+ * The -format option takes a single string value. Note
+ * that parsing this is outside the scope of this
+ * function.
*/
if (index + 1 < objc) {
@@ -1640,6 +1633,34 @@ ParseSubcommandOptions(optPtr, interp, allowedOptions, optIndexPtr, objc, objv)
"requires a value", (char *) NULL);
return TCL_ERROR;
}
+ } else if (bit == OPT_COMPOSITE) {
+ /*
+ * The -compositingrule option takes a single value from
+ * a well-known set.
+ */
+
+ if (index + 1 < objc) {
+ /*
+ * Note that these must match the TK_PHOTO_COMPOSITE_*
+ * constants.
+ */
+ static CONST char *compositingRules[] = {
+ "overlay", "set",
+ NULL
+ };
+
+ index++;
+ if (Tcl_GetIndexFromObj(interp, objv[index], compositingRules,
+ "compositing rule", 0, &optPtr->compositingRule)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ *optIndexPtr = index;
+ } else {
+ Tcl_AppendResult(interp, "the \"-compositingrule\" option ",
+ "requires a value", (char *) NULL);
+ return TCL_ERROR;
+ }
} else if ((bit != OPT_SHRINK) && (bit != OPT_GRAYSCALE)) {
char *val;
maxValues = ((bit == OPT_FROM) || (bit == OPT_TO))? 4: 2;
@@ -1935,7 +1956,7 @@ ImgPhotoConfigureMaster(interp, masterPtr, objc, objv, flags)
&& ((masterPtr->dataString != oldData)
|| (masterPtr->format != oldFormat))) {
- if (MatchStringFormat(interp, masterPtr->dataString,
+ if (MatchStringFormat(interp, masterPtr->dataString,
masterPtr->format, &imageFormat, &imageWidth,
&imageHeight, &oldformat) != TCL_OK) {
return TCL_ERROR;
@@ -2090,6 +2111,8 @@ ImgPhotoConfigureInstance(instancePtr)
* to byte-swap any 16 or 32 bit values that we store in the
* image in those situations where the server's endianness
* is different from ours.
+ *
+ * Can't we use autoconf to figure this out?
*/
if (imagePtr != NULL) {
@@ -2660,12 +2683,10 @@ ImgPhotoSetSize(masterPtr, width, height)
masterPtr->ditherX = 0;
masterPtr->ditherY = validBox.height;
}
- } else {
- if ((masterPtr->ditherY > 0)
- || ((int) validBox.width < masterPtr->ditherX)) {
- masterPtr->ditherX = validBox.width;
- masterPtr->ditherY = 0;
- }
+ } else if ((masterPtr->ditherY > 0)
+ || ((int) validBox.width < masterPtr->ditherX)) {
+ masterPtr->ditherX = validBox.width;
+ masterPtr->ditherY = 0;
}
}
@@ -2721,7 +2742,7 @@ ImgPhotoInstanceSetSize(instancePtr)
(masterPtr->width > 0) ? masterPtr->width: 1,
(masterPtr->height > 0) ? masterPtr->height: 1,
instancePtr->visualInfo.depth);
- if(!newPixmap) {
+ if (!newPixmap) {
panic("Fail to create pixmap with Tk_GetPixmap in ImgPhotoInstanceSetSize.\n");
return;
}
@@ -3635,35 +3656,35 @@ MatchFileFormat(interp, chan, fileName, formatObj, imageFormatPtr,
}
}
if (formatPtr == NULL) {
- useoldformat = 1;
- for (formatPtr = tsdPtr->oldFormatList; formatPtr != NULL;
- formatPtr = formatPtr->nextPtr) {
- if (formatString != NULL) {
- if (strncasecmp(formatString,
- formatPtr->name, strlen(formatPtr->name)) != 0) {
- continue;
- }
- matched = 1;
- if (formatPtr->fileMatchProc == NULL) {
- Tcl_AppendResult(interp, "-file option isn't supported for ",
- formatString, " images", (char *) NULL);
- return TCL_ERROR;
- }
- }
- if (formatPtr->fileMatchProc != NULL) {
- (void) Tcl_Seek(chan, Tcl_LongAsWide(0L), SEEK_SET);
- if ((*formatPtr->fileMatchProc)(chan, fileName, (Tcl_Obj *) formatString,
- widthPtr, heightPtr, interp)) {
- if (*widthPtr < 1) {
- *widthPtr = 1;
+ useoldformat = 1;
+ for (formatPtr = tsdPtr->oldFormatList; formatPtr != NULL;
+ formatPtr = formatPtr->nextPtr) {
+ if (formatString != NULL) {
+ if (strncasecmp(formatString,
+ formatPtr->name, strlen(formatPtr->name)) != 0) {
+ continue;
}
- if (*heightPtr < 1) {
- *heightPtr = 1;
+ matched = 1;
+ if (formatPtr->fileMatchProc == NULL) {
+ Tcl_AppendResult(interp, "-file option isn't supported",
+ " for ", formatString, " images", (char *) NULL);
+ return TCL_ERROR;
+ }
+ }
+ if (formatPtr->fileMatchProc != NULL) {
+ (void) Tcl_Seek(chan, Tcl_LongAsWide(0L), SEEK_SET);
+ if ((*formatPtr->fileMatchProc)(chan, fileName, (Tcl_Obj *)
+ formatString, widthPtr, heightPtr, interp)) {
+ if (*widthPtr < 1) {
+ *widthPtr = 1;
+ }
+ if (*heightPtr < 1) {
+ *heightPtr = 1;
+ }
+ break;
}
- break;
}
}
- }
}
if (formatPtr == NULL) {
@@ -3760,34 +3781,34 @@ MatchStringFormat(interp, data, formatObj, imageFormatPtr,
}
if (formatPtr == NULL) {
- useoldformat = 1;
- for (formatPtr = tsdPtr->oldFormatList; formatPtr != NULL;
- formatPtr = formatPtr->nextPtr) {
- if (formatObj != NULL) {
- if (strncasecmp(formatString,
- formatPtr->name, strlen(formatPtr->name)) != 0) {
- continue;
+ useoldformat = 1;
+ for (formatPtr = tsdPtr->oldFormatList; formatPtr != NULL;
+ formatPtr = formatPtr->nextPtr) {
+ if (formatObj != NULL) {
+ if (strncasecmp(formatString,
+ formatPtr->name, strlen(formatPtr->name)) != 0) {
+ continue;
+ }
+ matched = 1;
+ if (formatPtr->stringMatchProc == NULL) {
+ Tcl_AppendResult(interp, "-data option isn't supported",
+ " for ", formatString, " images", (char *) NULL);
+ return TCL_ERROR;
+ }
}
- matched = 1;
- if (formatPtr->stringMatchProc == NULL) {
- Tcl_AppendResult(interp, "-data option isn't supported for ",
- formatString, " images", (char *) NULL);
- return TCL_ERROR;
+ if ((formatPtr->stringMatchProc != NULL)
+ && (formatPtr->stringReadProc != NULL)
+ && (*formatPtr->stringMatchProc)(
+ (Tcl_Obj *) Tcl_GetString(data),
+ (Tcl_Obj *) formatString,
+ widthPtr, heightPtr, interp)) {
+ break;
}
}
- if ((formatPtr->stringMatchProc != NULL)
- && (formatPtr->stringReadProc != NULL)
- && (*formatPtr->stringMatchProc)((Tcl_Obj *) Tcl_GetString(data),
- (Tcl_Obj *) formatString,
- widthPtr, heightPtr, interp)) {
- break;
- }
- }
}
if (formatPtr == NULL) {
if ((formatObj != NULL) && !matched) {
- Tcl_AppendResult(interp, "image format \"",
- formatString,
+ Tcl_AppendResult(interp, "image format \"", formatString,
"\" is not supported", (char *) NULL);
} else {
Tcl_AppendResult(interp, "couldn't recognize image data",
@@ -3854,7 +3875,7 @@ Tk_FindPhoto(interp, imageName)
*---------------------------------------------------------------------- */
void
-Tk_PhotoPutBlock(handle, blockPtr, x, y, width, height)
+Tk_PhotoPutBlock(handle, blockPtr, x, y, width, height, compRule)
Tk_PhotoHandle handle; /* Opaque handle for the photo image
* to be updated. */
register Tk_PhotoImageBlock *blockPtr;
@@ -3864,6 +3885,8 @@ Tk_PhotoPutBlock(handle, blockPtr, x, y, width, height)
* be updated in the image. */
int width, height; /* Dimensions of the area of the image
* to be updated. */
+ int compRule; /* Compositing rule to use when processing
+ * transparent pixels. */
{
register PhotoMaster *masterPtr;
int xEnd, yEnd;
@@ -3884,8 +3907,9 @@ Tk_PhotoPutBlock(handle, blockPtr, x, y, width, height)
&& ((y + height) > masterPtr->userHeight)) {
height = masterPtr->userHeight - y;
}
- if ((width <= 0) || (height <= 0))
+ if ((width <= 0) || (height <= 0)) {
return;
+ }
xEnd = x + width;
yEnd = y + height;
@@ -3937,7 +3961,8 @@ Tk_PhotoPutBlock(handle, blockPtr, x, y, width, height)
&& (greenOffset == 1) && (blueOffset == 2) && (alphaOffset == 3)
&& (width <= blockPtr->width) && (height <= blockPtr->height)
&& ((height == 1) || ((x == 0) && (width == masterPtr->width)
- && (blockPtr->pitch == pitch)))) {
+ && (blockPtr->pitch == pitch)))
+ && (compRule == TK_PHOTO_COMPOSITE_SET)) {
memcpy((VOID *) destLinePtr,
(VOID *) (blockPtr->pixelPtr + blockPtr->offset[0]),
(size_t) (height * width * 4));
@@ -3948,35 +3973,70 @@ Tk_PhotoPutBlock(handle, blockPtr, x, y, width, height)
hCopy = MIN(hLeft, blockPtr->height);
hLeft -= hCopy;
for (; hCopy > 0; --hCopy) {
- destPtr = destLinePtr;
- for (wLeft = width; wLeft > 0;) {
- wCopy = MIN(wLeft, blockPtr->width);
- wLeft -= wCopy;
- srcPtr = srcLinePtr;
- for (; wCopy > 0; --wCopy) {
- alpha = srcPtr[alphaOffset];
- if (!destPtr[3]) {
- destPtr[0] = destPtr[1] = destPtr[2] = 0xd9;
- }
- if (!alphaOffset || (alpha == 255)) {
- /* new solid part of the image */
- *destPtr++ = srcPtr[0];
- *destPtr++ = srcPtr[greenOffset];
- *destPtr++ = srcPtr[blueOffset];
- *destPtr++ = 255;
- } else {
- if (alpha) {
- destPtr[0] += (srcPtr[0] - destPtr[0]) * alpha / 255;
- destPtr[1] += (srcPtr[greenOffset] - destPtr[1]) * alpha / 255;
- destPtr[2] += (srcPtr[blueOffset] - destPtr[2]) * alpha / 255;
- destPtr[3] += (255 - destPtr[3]) * alpha / 255;
+ if ((blockPtr->pixelSize == 4) && (greenOffset == 1)
+ && (blueOffset == 2) && (alphaOffset == 3)
+ && (width <= blockPtr->width)
+ && (compRule == TK_PHOTO_COMPOSITE_SET)) {
+ memcpy((VOID *) destLinePtr, (VOID *) srcLinePtr,
+ (size_t) (width * 4));
+ } else {
+ destPtr = destLinePtr;
+ for (wLeft = width; wLeft > 0;) {
+ wCopy = MIN(wLeft, blockPtr->width);
+ wLeft -= wCopy;
+ srcPtr = srcLinePtr;
+ for (; wCopy > 0; --wCopy) {
+ alpha = srcPtr[alphaOffset];
+ /*
+ * In the easy case, we can just copy.
+ */
+ if (!alphaOffset || (alpha == 255)) {
+ /* new solid part of the image */
+ *destPtr++ = srcPtr[0];
+ *destPtr++ = srcPtr[greenOffset];
+ *destPtr++ = srcPtr[blueOffset];
+ *destPtr++ = 255;
+ srcPtr += blockPtr->pixelSize;
+ continue;
}
+
/*
- * else should be empty space
+ * Combine according to the compositing rule.
*/
- destPtr += 4;
+ switch (compRule) {
+ case TK_PHOTO_COMPOSITE_SET:
+ *destPtr++ = srcPtr[0];
+ *destPtr++ = srcPtr[greenOffset];
+ *destPtr++ = srcPtr[blueOffset];
+ *destPtr++ = alpha;
+ break;
+
+ case TK_PHOTO_COMPOSITE_OVERLAY:
+ if (!destPtr[3]) {
+ /*
+ * There must be a better way to select a
+ * background colour!
+ */
+ destPtr[0] = destPtr[1] = destPtr[2] = 0xd9;
+ }
+
+ if (alpha) {
+ destPtr[0] += (srcPtr[0] - destPtr[0]) * alpha / 255;
+ destPtr[1] += (srcPtr[greenOffset] - destPtr[1]) * alpha / 255;
+ destPtr[2] += (srcPtr[blueOffset] - destPtr[2]) * alpha / 255;
+ destPtr[3] += (255 - destPtr[3]) * alpha / 255;
+ }
+ /*
+ * else should be empty space
+ */
+ destPtr += 4;
+ break;
+
+ default:
+ panic("unknown compositing rule: %d", compRule);
+ }
+ srcPtr += blockPtr->pixelSize;
}
- srcPtr += blockPtr->pixelSize;
}
}
srcLinePtr += blockPtr->pitch;
@@ -4011,6 +4071,23 @@ Tk_PhotoPutBlock(handle, blockPtr, x, y, width, height)
* expensive.
*/
+ if (compRule != TK_PHOTO_COMPOSITE_OVERLAY) {
+ /*
+ * Don't need this when using the OVERLAY compositing rule,
+ * which always strictly increases the valid region.
+ */
+ TkRegion workRgn = TkCreateRegion();
+
+ rect.x = x;
+ rect.y = y;
+ rect.width = width;
+ rect.height = height;
+ TkUnionRectWithRegion(&rect, workRgn, workRgn);
+ TkSubtractRegion(masterPtr->validRegion, workRgn,
+ masterPtr->validRegion);
+ TkDestroyRegion(workRgn);
+ }
+
destLinePtr = masterPtr->pix24 + (y * masterPtr->width + x) * 4 + 3;
for (y1 = 0; y1 < height; y1++) {
x1 = 0;
@@ -4018,12 +4095,14 @@ Tk_PhotoPutBlock(handle, blockPtr, x, y, width, height)
while (x1 < width) {
/* search for first non-transparent pixel */
while ((x1 < width) && !*destPtr) {
- x1++; destPtr += 4;
+ x1++;
+ destPtr += 4;
}
end = x1;
/* search for first transparent pixel */
while ((end < width) && *destPtr) {
- end++; destPtr += 4;
+ end++;
+ destPtr += 4;
}
if (end > x1) {
rect.x = x + x1;
@@ -4080,7 +4159,7 @@ Tk_PhotoPutBlock(handle, blockPtr, x, y, width, height)
void
Tk_PhotoPutZoomedBlock(handle, blockPtr, x, y, width, height, zoomX, zoomY,
- subsampleX, subsampleY)
+ subsampleX, subsampleY, compRule)
Tk_PhotoHandle handle; /* Opaque handle for the photo image
* to be updated. */
register Tk_PhotoImageBlock *blockPtr;
@@ -4092,6 +4171,8 @@ Tk_PhotoPutZoomedBlock(handle, blockPtr, x, y, width, height, zoomX, zoomY,
* to be updated. */
int zoomX, zoomY; /* Zoom factors for the X and Y axes. */
int subsampleX, subsampleY; /* Subsampling factors for the X and Y axes. */
+ int compRule; /* Compositing rule to use when processing
+ * transparent pixels. */
{
register PhotoMaster *masterPtr;
int xEnd, yEnd;
@@ -4106,16 +4187,16 @@ Tk_PhotoPutZoomedBlock(handle, blockPtr, x, y, width, height, zoomX, zoomY,
int blockXSkip, blockYSkip;
XRectangle rect;
- if ((zoomX == 1) && (zoomY == 1) && (subsampleX == 1)
- && (subsampleY == 1)) {
- Tk_PhotoPutBlock(handle, blockPtr, x, y, width, height);
+ if (zoomX==1 && zoomY==1 && subsampleX==1 && subsampleY==1) {
+ Tk_PhotoPutBlock(handle, blockPtr, x, y, width, height, compRule);
return;
}
masterPtr = (PhotoMaster *) handle;
- if ((zoomX <= 0) || (zoomY <= 0))
+ if (zoomX <= 0 || zoomY <= 0) {
return;
+ }
if ((masterPtr->userWidth != 0) && ((x + width) > masterPtr->userWidth)) {
width = masterPtr->userWidth - x;
}
@@ -4123,8 +4204,9 @@ Tk_PhotoPutZoomedBlock(handle, blockPtr, x, y, width, height, zoomX, zoomY,
&& ((y + height) > masterPtr->userHeight)) {
height = masterPtr->userHeight - y;
}
- if ((width <= 0) || (height <= 0))
+ if (width <= 0 || height <= 0) {
return;
+ }
xEnd = x + width;
yEnd = y + height;
@@ -4171,18 +4253,20 @@ Tk_PhotoPutZoomedBlock(handle, blockPtr, x, y, width, height, zoomX, zoomY,
blockXSkip = subsampleX * blockPtr->pixelSize;
blockYSkip = subsampleY * blockPtr->pitch;
- if (subsampleX > 0)
+ if (subsampleX > 0) {
blockWid = ((blockPtr->width + subsampleX - 1) / subsampleX) * zoomX;
- else if (subsampleX == 0)
+ } else if (subsampleX == 0) {
blockWid = width;
- else
+ } else {
blockWid = ((blockPtr->width - subsampleX - 1) / -subsampleX) * zoomX;
- if (subsampleY > 0)
+ }
+ if (subsampleY > 0) {
blockHt = ((blockPtr->height + subsampleY - 1) / subsampleY) * zoomY;
- else if (subsampleY == 0)
+ } else if (subsampleY == 0) {
blockHt = height;
- else
+ } else {
blockHt = ((blockPtr->height - subsampleY - 1) / -subsampleY) * zoomY;
+ }
/*
* Copy the data into our local 24-bit/pixel array.
@@ -4211,23 +4295,43 @@ Tk_PhotoPutZoomedBlock(handle, blockPtr, x, y, width, height, zoomX, zoomY,
srcPtr = srcLinePtr;
for (; wCopy > 0; wCopy -= zoomX) {
for (xRepeat = MIN(wCopy, zoomX); xRepeat > 0; xRepeat--) {
- if (!destPtr[3]) {
- destPtr[0] = destPtr[1] = destPtr[2] = 0xd9;
- }
- if (!alphaOffset || (srcPtr[alphaOffset] == 255)) {
- *destPtr++ = srcPtr[0];
- *destPtr++ = srcPtr[greenOffset];
- *destPtr++ = srcPtr[blueOffset];
- *destPtr++ = 255;
- } else {
- if (srcPtr[alphaOffset]) {
- destPtr[0] += (srcPtr[0] - destPtr[0]) * srcPtr[alphaOffset] / 255;
- destPtr[1] += (srcPtr[greenOffset] - destPtr[1]) * srcPtr[alphaOffset] / 255;
- destPtr[2] += (srcPtr[blueOffset] - destPtr[2]) * srcPtr[alphaOffset] / 255;
- destPtr[3] += (255 - destPtr[3]) * srcPtr[alphaOffset] / 255;
- }
- destPtr+=4;
- }
+ /*
+ * Common case (solid pixels) first
+ */
+ if (!alphaOffset || (srcPtr[alphaOffset] == 255)) {
+ *destPtr++ = srcPtr[0];
+ *destPtr++ = srcPtr[greenOffset];
+ *destPtr++ = srcPtr[blueOffset];
+ *destPtr++ = 255;
+ continue;
+ }
+
+ switch (compRule) {
+ case TK_PHOTO_COMPOSITE_SET:
+ *destPtr++ = srcPtr[0];
+ *destPtr++ = srcPtr[greenOffset];
+ *destPtr++ = srcPtr[blueOffset];
+ *destPtr++ = srcPtr[alphaOffset];
+ break;
+ case TK_PHOTO_COMPOSITE_OVERLAY:
+ if (!destPtr[3]) {
+ /*
+ * There must be a better way to select a
+ * background colour!
+ */
+ destPtr[0] = destPtr[1] = destPtr[2] = 0xd9;
+ }
+ if (srcPtr[alphaOffset]) {
+ destPtr[0] += (srcPtr[0] - destPtr[0]) * srcPtr[alphaOffset] / 255;
+ destPtr[1] += (srcPtr[greenOffset] - destPtr[1]) * srcPtr[alphaOffset] / 255;
+ destPtr[2] += (srcPtr[blueOffset] - destPtr[2]) * srcPtr[alphaOffset] / 255;
+ destPtr[3] += (255 - destPtr[3]) * srcPtr[alphaOffset] / 255;
+ }
+ destPtr += 4;
+ break;
+ default:
+ panic("unknown compositing rule: %d", compRule);
+ }
}
srcPtr += blockXSkip;
}
@@ -4242,12 +4346,29 @@ Tk_PhotoPutZoomedBlock(handle, blockPtr, x, y, width, height, zoomX, zoomY,
}
/*
- * Add this new block to the region that specifies which data is valid.
+ * Recompute the region of data for which we have valid pixels to plot.
*/
if (alphaOffset) {
int x1, y1, end;
+ if (compRule != TK_PHOTO_COMPOSITE_OVERLAY) {
+ /*
+ * Don't need this when using the OVERLAY compositing rule, which
+ * always strictly increases the valid region.
+ */
+ TkRegion workRgn = TkCreateRegion();
+
+ rect.x = x;
+ rect.y = y;
+ rect.width = width;
+ rect.height = 1;
+ TkUnionRectWithRegion(&rect, workRgn, workRgn);
+ TkSubtractRegion(masterPtr->validRegion, workRgn,
+ masterPtr->validRegion);
+ TkDestroyRegion(workRgn);
+ }
+
destLinePtr = masterPtr->pix24 + (y * masterPtr->width + x) * 4 + 3;
for (y1 = 0; y1 < height; y1++) {
x1 = 0;
@@ -4255,12 +4376,14 @@ Tk_PhotoPutZoomedBlock(handle, blockPtr, x, y, width, height, zoomX, zoomY,
while (x1 < width) {
/* search for first non-transparent pixel */
while ((x1 < width) && !*destPtr) {
- x1++; destPtr += 4;
+ x1++;
+ destPtr += 4;
}
end = x1;
/* search for first transparent pixel */
while ((end < width) && *destPtr) {
- end++; destPtr += 4;
+ end++;
+ destPtr += 4;
}
if (end > x1) {
rect.x = x + x1;
@@ -4976,11 +5099,14 @@ ImgGetPhoto(masterPtr, blockPtr, optPtr)
+ blockPtr->pixelSize - 1;
for (x = 0; x < blockPtr->width; x++) {
if (*pixelPtr != 255) {
- alphaOffset = 3; break;
+ alphaOffset = 3;
+ break;
}
pixelPtr += blockPtr->pixelSize;
}
- if (alphaOffset) break;
+ if (alphaOffset) {
+ break;
+ }
}
if (!alphaOffset) {
blockPtr->pixelPtr--;
@@ -5360,13 +5486,13 @@ Tk_CreatePhotoOption(interp, name, proc)
static int
ImgPhotoPostscript(clientData, interp, tkwin, psInfo,
x, y, width, height, prepass)
- ClientData clientData;
- Tcl_Interp *interp;
- Tk_Window tkwin;
- Tk_PostscriptInfo psInfo; /* postscript info */
- int x, y; /* First pixel to output */
- int width, height; /* Width and height of area */
- int prepass;
+ ClientData clientData; /* Handle for the photo image */
+ Tcl_Interp *interp; /* Interpreter */
+ Tk_Window tkwin; /* (unused) */
+ Tk_PostscriptInfo psInfo; /* postscript info */
+ int x, y; /* First pixel to output */
+ int width, height; /* Width and height of area */
+ int prepass; /* (unused) */
{
Tk_PhotoImageBlock block;
@@ -5375,3 +5501,35 @@ ImgPhotoPostscript(clientData, interp, tkwin, psInfo,
return Tk_PostscriptPhoto(interp, &block, psInfo, width, height);
}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_PhotoPutBlock_Old, Tk_PhotoPutZoomedBlock_Old --
+ *
+ * These backward-compatability functions just exist to fill slots in
+ * stubs table. For the behaviour of *_Old, refer to the
+ * corresponding function without the extra suffix.
+ *
+ *----------------------------------------------------------------------
+ */
+void
+Tk_PhotoPutBlock_Old(handle, blockPtr, x, y, width, height)
+ Tk_PhotoHandle handle;
+ Tk_PhotoImageBlock *blockPtr;
+ int x, y, width, height;
+{
+ Tk_PhotoPutBlock(handle, blockPtr, x, y, width, height,
+ TK_PHOTO_COMPOSITE_OVERLAY);
+}
+
+void
+Tk_PhotoPutZoomedBlock_Old(handle, blockPtr, x, y, width, height,
+ zoomX, zoomY, subsampleX, subsampleY)
+ Tk_PhotoHandle handle;
+ Tk_PhotoImageBlock *blockPtr;
+ int x, y, width, height, zoomX, zoomY, subsampleX, subsampleY;
+{
+ Tk_PhotoPutZoomedBlock(handle, blockPtr, x, y, width, height,
+ zoomX, zoomY, subsampleX, subsampleY, TK_PHOTO_COMPOSITE_OVERLAY);
+}
diff --git a/generic/tkInt.decls b/generic/tkInt.decls
index 64ea04b..d0e2fd7 100644
--- a/generic/tkInt.decls
+++ b/generic/tkInt.decls
@@ -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: tkInt.decls,v 1.26 2002/05/27 19:49:32 mdejong Exp $
+# RCS: @(#) $Id: tkInt.decls,v 1.27 2002/06/14 13:35:48 dkf Exp $
library tk
@@ -657,6 +657,10 @@ declare 144 generic {
void TkGCCleanup(TkDisplay *dispPtr)
}
+declare 145 {mac win} {
+ void TkSubtractRegion (TkRegion sra, TkRegion srcb, TkRegion dr_return)
+}
+
##############################################################################
# Define the platform specific internal Tcl interface. These functions are
diff --git a/generic/tkIntDecls.h b/generic/tkIntDecls.h
index ecd9a28..4fcdf63 100644
--- a/generic/tkIntDecls.h
+++ b/generic/tkIntDecls.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: tkIntDecls.h,v 1.17 2002/04/12 10:10:48 hobbs Exp $
+ * RCS: @(#) $Id: tkIntDecls.h,v 1.18 2002/06/14 13:35:49 dkf Exp $
*/
#ifndef _TKINTDECLS
@@ -489,6 +489,16 @@ EXTERN void TkFocusFree _ANSI_ARGS_((TkMainInfo * mainPtr));
EXTERN void TkClipCleanup _ANSI_ARGS_((TkDisplay * dispPtr));
/* 144 */
EXTERN void TkGCCleanup _ANSI_ARGS_((TkDisplay * dispPtr));
+#ifdef __WIN32__
+/* 145 */
+EXTERN void TkSubtractRegion _ANSI_ARGS_((TkRegion sra,
+ TkRegion srcb, TkRegion dr_return));
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+/* 145 */
+EXTERN void TkSubtractRegion _ANSI_ARGS_((TkRegion sra,
+ TkRegion srcb, TkRegion dr_return));
+#endif /* MAC_TCL */
typedef struct TkIntStubs {
int magic;
@@ -719,6 +729,15 @@ typedef struct TkIntStubs {
void (*tkFocusFree) _ANSI_ARGS_((TkMainInfo * mainPtr)); /* 142 */
void (*tkClipCleanup) _ANSI_ARGS_((TkDisplay * dispPtr)); /* 143 */
void (*tkGCCleanup) _ANSI_ARGS_((TkDisplay * dispPtr)); /* 144 */
+#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+ void *reserved145;
+#endif /* UNIX */
+#ifdef __WIN32__
+ void (*tkSubtractRegion) _ANSI_ARGS_((TkRegion sra, TkRegion srcb, TkRegion dr_return)); /* 145 */
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+ void (*tkSubtractRegion) _ANSI_ARGS_((TkRegion sra, TkRegion srcb, TkRegion dr_return)); /* 145 */
+#endif /* MAC_TCL */
} TkIntStubs;
#ifdef __cplusplus
@@ -1338,6 +1357,18 @@ extern TkIntStubs *tkIntStubsPtr;
#define TkGCCleanup \
(tkIntStubsPtr->tkGCCleanup) /* 144 */
#endif
+#ifdef __WIN32__
+#ifndef TkSubtractRegion
+#define TkSubtractRegion \
+ (tkIntStubsPtr->tkSubtractRegion) /* 145 */
+#endif
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+#ifndef TkSubtractRegion
+#define TkSubtractRegion \
+ (tkIntStubsPtr->tkSubtractRegion) /* 145 */
+#endif
+#endif /* MAC_TCL */
#endif /* defined(USE_TK_STUBS) && !defined(USE_TK_STUB_PROCS) */
diff --git a/generic/tkStubInit.c b/generic/tkStubInit.c
index cebe2ad..699defc 100644
--- a/generic/tkStubInit.c
+++ b/generic/tkStubInit.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: tkStubInit.c,v 1.33 2002/05/27 19:49:32 mdejong Exp $
+ * RCS: @(#) $Id: tkStubInit.c,v 1.34 2002/06/14 13:35:49 dkf Exp $
*/
#include "tkInt.h"
@@ -272,6 +272,15 @@ TkIntStubs tkIntStubs = {
TkFocusFree, /* 142 */
TkClipCleanup, /* 143 */
TkGCCleanup, /* 144 */
+#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+ NULL, /* 145 */
+#endif /* UNIX */
+#ifdef __WIN32__
+ TkSubtractRegion, /* 145 */
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+ TkSubtractRegion, /* 145 */
+#endif /* MAC_TCL */
};
TkIntPlatStubs tkIntPlatStubs = {
@@ -785,8 +794,8 @@ TkStubs tkStubs = {
Tk_NameToWindow, /* 141 */
Tk_OwnSelection, /* 142 */
Tk_ParseArgv, /* 143 */
- Tk_PhotoPutBlock, /* 144 */
- Tk_PhotoPutZoomedBlock, /* 145 */
+ Tk_PhotoPutBlock_Old, /* 144 */
+ Tk_PhotoPutZoomedBlock_Old, /* 145 */
Tk_PhotoGetImage, /* 146 */
Tk_PhotoBlank, /* 147 */
Tk_PhotoExpand, /* 148 */
@@ -887,6 +896,8 @@ TkStubs tkStubs = {
Tk_SetInternalBorderEx, /* 243 */
Tk_SetMinimumRequestSize, /* 244 */
Tk_SetCaretPos, /* 245 */
+ Tk_PhotoPutBlock, /* 246 */
+ Tk_PhotoPutZoomedBlock, /* 247 */
};
/* !END!: Do not edit above this line. */
diff --git a/mac/tkMacRegion.c b/mac/tkMacRegion.c
index c2a70ae..86e193e 100644
--- a/mac/tkMacRegion.c
+++ b/mac/tkMacRegion.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: tkMacRegion.c,v 1.3 1999/05/22 06:35:00 jingham Exp $
+ * RCS: @(#) $Id: tkMacRegion.c,v 1.4 2002/06/14 13:35:49 dkf Exp $
*/
#include "tkInt.h"
@@ -216,3 +216,33 @@ TkClipBox(
rect_return->width = (**rgn).rgnBBox.right - (**rgn).rgnBBox.left;
rect_return->height = (**rgn).rgnBBox.bottom - (**rgn).rgnBBox.top;
}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkSubtractRegion --
+ *
+ * Implements the equivilent of the X window function
+ * XSubtractRegion. See X window documentation for more details.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkSubtractRegion(
+ TkRegion sra,
+ TkRegion srb,
+ TkRegion dr_return)
+{
+ RgnHandle srcRgnA = (RgnHandle) sra;
+ RgnHandle srcRgnB = (RgnHandle) srb;
+ RgnHandle destRgn = (RgnHandle) dr_return;
+
+ DiffRgn(srcRgnA, srcRgnB, destRgn);
+}
diff --git a/tests/imgPhoto.test b/tests/imgPhoto.test
index 320b289..04c813d 100644
--- a/tests/imgPhoto.test
+++ b/tests/imgPhoto.test
@@ -9,7 +9,7 @@
#
# Author: Paul Mackerras (paulus@cs.anu.edu.au)
#
-# RCS: @(#) $Id: imgPhoto.test,v 1.9 2002/02/01 14:27:30 dkf Exp $
+# RCS: @(#) $Id: imgPhoto.test,v 1.10 2002/06/14 13:35:49 dkf Exp $
if {[lsearch [namespace children] ::tcltest] == -1} {
source [file join [pwd] [file dirname [info script]] defs.tcl]
@@ -27,7 +27,7 @@ canvas .c
pack .c
update
-# temporarily copy the README fiel from testsDir to tmpDir
+# temporarily copy the README file from testsDir to tmpDir
if {![file exists README]} {
set newREADME [file join $::tcltest::workingDir README]
file copy [file join $::tcltest::testsDir README] $newREADME
@@ -95,7 +95,7 @@ test imgPhoto-2.2 {ImgPhotoCreate procedure} {
eval image delete [image names]
image create photo image1
list [info commands image1] [image names] \
- [image width image1] [image height image1]
+ [image width image1] [image height image1]
} {image1 image1 0 0}
# test imgPhoto-2.3 {ImgPhotoCreate procedure: creation failure} {
# image create photo p1
@@ -167,13 +167,13 @@ test imgPhoto-4.10 {ImgPhotoCmd procedure: copy option} {
} {256 256 {169 117 90}}
test imgPhoto-4.11 {ImgPhotoCmd procedure: copy option} {
list [catch {p1 copy} msg] $msg
-} {1 {wrong # args: should be "p1 copy source-image ?-from x1 y1 x2 y2? ?-to x1 y1 x2 y2? ?-zoom x y? ?-subsample x y?"}}
+} {1 {wrong # args: should be "p1 copy source-image ?-compositingrule rule? ?-from x1 y1 x2 y2? ?-to x1 y1 x2 y2? ?-zoom x y? ?-subsample x y?"}}
test imgPhoto-4.12 {ImgPhotoCmd procedure: copy option} {
list [catch {p1 copy blah} msg] $msg
} {1 {image "blah" doesn't exist or is not a photo image}}
test imgPhoto-4.13 {ImgPhotoCmd procedure: copy option} {
list [catch {p1 copy p2 -blah} msg] $msg
-} {1 {unrecognized option "-blah": must be -from, -shrink, -subsample, -to, or -zoom}}
+} {1 {unrecognized option "-blah": must be -compositingrule, -from, -shrink, -subsample, -to, or -zoom}}
test imgPhoto-4.14 {ImgPhotoCmd procedure: copy option} {
list [catch {p1 copy p2 -from -to} msg] $msg
} {1 {the "-from" option requires one to four integer values}}
@@ -415,9 +415,46 @@ proc checkImgTransLoopResetSet {img width height} {
test imgPhoto-4.68 {ImgPhotoCmd procedure: transparency set option} {
checkImgTransLoopResetSet p1 3 3
} {0 1 0 2 1 0 1 1 1 2 2 0 2 1 2 2 , 0 0 0 1 0 2 1 0 1 1 1 2 2 0 2 1 2 2 . 0 0 0 2 1 0 1 1 1 2 2 0 2 1 2 2 , 0 0 0 1 0 2 1 0 1 1 1 2 2 0 2 1 2 2 . 0 0 0 1 1 0 1 1 1 2 2 0 2 1 2 2 , 0 0 0 1 0 2 1 0 1 1 1 2 2 0 2 1 2 2 . 0 0 0 1 0 2 1 1 1 2 2 0 2 1 2 2 , 0 0 0 1 0 2 1 0 1 1 1 2 2 0 2 1 2 2 . 0 0 0 1 0 2 1 0 1 2 2 0 2 1 2 2 , 0 0 0 1 0 2 1 0 1 1 1 2 2 0 2 1 2 2 . 0 0 0 1 0 2 1 0 1 1 2 0 2 1 2 2 , 0 0 0 1 0 2 1 0 1 1 1 2 2 0 2 1 2 2 . 0 0 0 1 0 2 1 0 1 1 1 2 2 1 2 2 , 0 0 0 1 0 2 1 0 1 1 1 2 2 0 2 1 2 2 . 0 0 0 1 0 2 1 0 1 1 1 2 2 0 2 2 , 0 0 0 1 0 2 1 0 1 1 1 2 2 0 2 1 2 2 . 0 0 0 1 0 2 1 0 1 1 1 2 2 0 2 1 , 0 0 0 1 0 2 1 0 1 1 1 2 2 0 2 1 2 2 .}
-catch {rename checkImgTrans {}}
catch {rename checkImgTransLoopSetReset {}}
catch {rename checkImgTransLoopResetSet {}}
+# Test the compositing rules for copying images
+image create photo p1 -width 3 -height 3
+image create photo p2 -width 2 -height 2
+test imgPhoto-4.68 {ImgPhotoCmd procedure: copy with -compositingrule} {
+ list [catch {p1 copy p2 -to 1 1 -compositingrule} msg] $msg
+} {1 {the "-compositingrule" option requires a value}}
+test imgPhoto-4.69 {ImgPhotoCmd procedure: copy with -compositingrule} {
+ list [catch {p1 copy p2 -to 1 1 -compositingrule BAD} msg] $msg
+} {1 {bad compositing rule "BAD": must be overlay or set}}
+test imgPhoto-4.70 {ImgPhotoCmd procedure: copy with -compositingrule} {
+ # Tests default compositing rule
+ p1 blank
+ p2 blank
+ p1 put white -to 0 0 2 2
+ p2 put white -to 0 0 2 2
+ p2 transparency set 0 0 true
+ p1 copy p2 -to 1 1
+ checkImgTrans p1 3 3
+} {0 2 2 0}
+test imgPhoto-4.71 {ImgPhotoCmd procedure: copy with -compositingrule} {
+ p1 blank
+ p2 blank
+ p1 put white -to 0 0 2 2
+ p2 put white -to 0 0 2 2
+ p2 transparency set 0 0 true
+ p1 copy p2 -to 1 1 -compositingrule overlay
+ checkImgTrans p1 3 3
+} {0 2 2 0}
+test imgPhoto-4.72 {ImgPhotoCmd procedure: copy with -compositingrule} {
+ p1 blank
+ p2 blank
+ p1 put white -to 0 0 2 2
+ p2 put white -to 0 0 2 2
+ p2 transparency set 0 0 true
+ p1 copy p2 -to 1 1 -compositingrule set
+ checkImgTrans p1 3 3
+} {0 2 1 1 2 0}
+catch {rename checkImgTrans {}}
test imgPhoto-5.1 {ImgPhotoGet/Free procedures, shared instances} {
eval image delete [image names]
diff --git a/unix/tkUnixPort.h b/unix/tkUnixPort.h
index 6e51fe7..dbde1f2 100644
--- a/unix/tkUnixPort.h
+++ b/unix/tkUnixPort.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: tkUnixPort.h,v 1.7 2001/09/25 16:25:20 dgp Exp $
+ * RCS: @(#) $Id: tkUnixPort.h,v 1.8 2002/06/14 13:35:49 dkf Exp $
*/
#ifndef _UNIXPORT
@@ -145,6 +145,8 @@ extern int errno;
(Region) b, (Region) r)
#define TkRectInRegion(r, x, y, w, h) XRectInRegion((Region) r, x, y, w, h)
#define TkSetRegion(d, gc, rgn) XSetRegion(d, gc, (Region) rgn)
+#define TkSubtractRegion(a, b, r) XSubtractRegion((Region) a, \
+ (Region) b, (Region) r)
#define TkUnionRectWithRegion(rect, src, ret) XUnionRectWithRegion(rect, \
(Region) src, (Region) ret)
diff --git a/win/tkWinRegion.c b/win/tkWinRegion.c
index c7be771..8a50620 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.2 1998/09/14 18:24:01 stanton Exp $
+ * RCS: @(#) $Id: tkWinRegion.c,v 1.3 2002/06/14 13:35:49 dkf Exp $
*/
#include "tkWinInt.h"
@@ -177,3 +177,28 @@ TkRectInRegion(r, x, y, width, height)
rect.right = x+width;
return RectInRegion((HRGN)r, &rect) ? RectanglePart : RectangleOut;
}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkSubtractRegion --
+ *
+ * Compute the set-difference of two regions.
+ *
+ * Results:
+ * Returns the result in the dr_return region.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkSubtractRegion(sra, srb, dr_return)
+ TkRegion sra;
+ TkRegion srb;
+ TkRegion dr_return;
+{
+ CombineRgn((HRGN) dr_return, (HRGN) sra, (HRGN) srb, RGN_DIFF);
+}