--- /dev/null
+/*
+ * bltWinop.c --
+ *
+ * This module implements simple window commands for the BLT toolkit.
+ *
+ * Copyright 1991-1998 Lucent Technologies, Inc.
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice appear in all
+ * copies and that both that the copyright notice and warranty
+ * disclaimer appear in supporting documentation, and that the names
+ * of Lucent Technologies any of their entities not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission.
+ *
+ * Lucent Technologies disclaims all warranties with regard to this
+ * software, including all implied warranties of merchantability and
+ * fitness. In no event shall Lucent Technologies be liable for any
+ * special, indirect or consequential damages or any damages
+ * whatsoever resulting from loss of use, data or profits, whether in
+ * an action of contract, negligence or other tortuous action, arising
+ * out of or in connection with the use or performance of this
+ * software.
+ */
+
+#include "bltInt.h"
+
+#ifndef NO_WINOP
+
+#include "bltImage.h"
+#include <X11/Xutil.h>
+#ifndef WIN32
+#include <X11/Xproto.h>
+#endif
+
+static Tcl_CmdProc WinopCmd;
+
+static int
+GetRealizedWindow(interp, string, tkwinPtr)
+ Tcl_Interp *interp;
+ char *string;
+ Tk_Window *tkwinPtr;
+{
+ Tk_Window tkwin;
+
+ tkwin = Tk_NameToWindow(interp, string, Tk_MainWindow(interp));
+ if (tkwin == NULL) {
+ return TCL_ERROR;
+ }
+ if (Tk_WindowId(tkwin) == None) {
+ Tk_MakeWindowExist(tkwin);
+ }
+ *tkwinPtr = tkwin;
+ return TCL_OK;
+}
+
+static Window
+StringToWindow(interp, string)
+ Tcl_Interp *interp;
+ char *string;
+{
+ int xid;
+
+ if (string[0] == '.') {
+ Tk_Window tkwin;
+
+ if (GetRealizedWindow(interp, string, &tkwin) != TCL_OK) {
+ return None;
+ }
+ if (Tk_IsTopLevel(tkwin)) {
+ return Blt_GetRealWindowId(tkwin);
+ } else {
+ return Tk_WindowId(tkwin);
+ }
+ } else if (Tcl_GetInt(interp, string, &xid) == TCL_OK) {
+#ifdef WIN32
+ static TkWinWindow tkWinWindow;
+
+ tkWinWindow.handle = (HWND)xid;
+ tkWinWindow.winPtr = NULL;
+ tkWinWindow.type = TWD_WINDOW;
+ return (Window)&tkWinWindow;
+#else
+ return (Window)xid;
+#endif
+ }
+ return None;
+}
+
+#ifdef WIN32
+
+static int
+GetWindowSize(
+ Tcl_Interp *interp,
+ Window window,
+ int *widthPtr,
+ int *heightPtr)
+{
+ int result;
+ RECT region;
+ TkWinWindow *winPtr = (TkWinWindow *)window;
+
+ result = GetWindowRect(winPtr->handle, ®ion);
+ if (result) {
+ *widthPtr = region.right - region.left;
+ *heightPtr = region.bottom - region.top;
+ return TCL_OK;
+ }
+ return TCL_ERROR;
+}
+
+#else
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XGeometryErrorProc --
+ *
+ * Flags errors generated from XGetGeometry calls to the X server.
+ *
+ * Results:
+ * Always returns 0.
+ *
+ * Side Effects:
+ * Sets a flag, indicating an error occurred.
+ *
+ *----------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+XGeometryErrorProc(clientData, errEventPtr)
+ ClientData clientData;
+ XErrorEvent *errEventPtr;
+{
+ int *errorPtr = clientData;
+
+ *errorPtr = TCL_ERROR;
+ return 0;
+}
+
+static int
+GetWindowSize(interp, window, widthPtr, heightPtr)
+ Tcl_Interp *interp;
+ Window window;
+ int *widthPtr, *heightPtr;
+{
+ int result;
+ int any = -1;
+ int x, y, borderWidth, depth;
+ Window root;
+ Tk_ErrorHandler handler;
+ Tk_Window tkwin;
+
+ tkwin = Tk_MainWindow(interp);
+ handler = Tk_CreateErrorHandler(Tk_Display(tkwin), any, X_GetGeometry,
+ any, XGeometryErrorProc, &result);
+ result = XGetGeometry(Tk_Display(tkwin), window, &root, &x, &y,
+ (unsigned int *)widthPtr, (unsigned int *)heightPtr,
+ (unsigned int *)&borderWidth, (unsigned int *)&depth);
+ Tk_DeleteErrorHandler(handler);
+ XSync(Tk_Display(tkwin), False);
+ if (result) {
+ return TCL_OK;
+ }
+ return TCL_ERROR;
+}
+#endif /*WIN32*/
+
+
+#ifndef WIN32
+/*ARGSUSED*/
+static int
+ColormapOp(clientData, interp, argc, argv)
+ ClientData clientData;
+ Tcl_Interp *interp;
+ int argc; /* Not used. */
+ char **argv;
+{
+ register int i;
+ Tk_Window tkwin;
+#define MAXCOLORS 256
+ register XColor *colorPtr;
+ XColor colorArr[MAXCOLORS];
+ unsigned long int pixelValues[MAXCOLORS];
+ int inUse[MAXCOLORS];
+ char string[20];
+ unsigned long int *indexPtr;
+ int nFree;
+
+ if (GetRealizedWindow(interp, argv[2], &tkwin) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ /* Initially, we assume all color cells are allocated. */
+ memset((char *)inUse, 0, sizeof(int) * MAXCOLORS);
+
+ /*
+ * Start allocating color cells. This will tell us which color cells
+ * haven't already been allocated in the colormap. We'll release the
+ * cells as soon as we find out how many there are.
+ */
+ nFree = 0;
+ for (indexPtr = pixelValues, i = 0; i < MAXCOLORS; i++, indexPtr++) {
+ if (!XAllocColorCells(Tk_Display(tkwin), Tk_Colormap(tkwin),
+ False, NULL, 0, indexPtr, 1)) {
+ break;
+ }
+ inUse[*indexPtr] = TRUE;/* Indicate the cell is unallocated */
+ nFree++;
+ }
+ XFreeColors(Tk_Display(tkwin), Tk_Colormap(tkwin), pixelValues, nFree, 0);
+ for (colorPtr = colorArr, i = 0; i < MAXCOLORS; i++, colorPtr++) {
+ colorPtr->pixel = i;
+ }
+ XQueryColors(Tk_Display(tkwin), Tk_Colormap(tkwin), colorArr, MAXCOLORS);
+ for (colorPtr = colorArr, i = 0; i < MAXCOLORS; i++, colorPtr++) {
+ if (!inUse[colorPtr->pixel]) {
+ sprintf(string, "#%02x%02x%02x", (colorPtr->red >> 8),
+ (colorPtr->green >> 8), (colorPtr->blue >> 8));
+ Tcl_AppendElement(interp, string);
+ sprintf(string, "%ld", colorPtr->pixel);
+ Tcl_AppendElement(interp, string);
+ }
+ }
+ return TCL_OK;
+}
+
+#endif
+
+/*ARGSUSED*/
+static int
+LowerOp(clientData, interp, argc, argv)
+ ClientData clientData;
+ Tcl_Interp *interp;
+ int argc; /* Not used. */
+ char **argv;
+{
+ register int i;
+ Window window;
+ Display *display;
+
+ display = Tk_Display(Tk_MainWindow(interp));
+ for (i = 2; i < argc; i++) {
+ window = StringToWindow(interp, argv[i]);
+ if (window == None) {
+ return TCL_ERROR;
+ }
+ XLowerWindow(display, window);
+ }
+ return TCL_OK;
+}
+
+/*ARGSUSED*/
+static int
+RaiseOp(clientData, interp, argc, argv)
+ ClientData clientData;
+ Tcl_Interp *interp;
+ int argc; /* Not used. */
+ char **argv;
+{
+ register int i;
+ Window window;
+ Display *display;
+
+ display = Tk_Display(Tk_MainWindow(interp));
+ for (i = 2; i < argc; i++) {
+ window = StringToWindow(interp, argv[i]);
+ if (window == None) {
+ return TCL_ERROR;
+ }
+ XRaiseWindow(display, window);
+ }
+ return TCL_OK;
+}
+
+/*ARGSUSED*/
+static int
+MapOp(clientData, interp, argc, argv)
+ ClientData clientData;
+ Tcl_Interp *interp;
+ int argc; /* Not used. */
+ char **argv;
+{
+ register int i;
+ Window window;
+ Display *display;
+
+ display = Tk_Display(Tk_MainWindow(interp));
+ for (i = 2; i < argc; i++) {
+ if (argv[i][0] == '.') {
+ Tk_Window tkwin;
+ Tk_FakeWin *fakePtr;
+
+ if (GetRealizedWindow(interp, argv[i], &tkwin) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ fakePtr = (Tk_FakeWin *) tkwin;
+ fakePtr->flags |= TK_MAPPED;
+ window = Tk_WindowId(tkwin);
+ } else {
+ int xid;
+
+ if (Tcl_GetInt(interp, argv[i], &xid) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ window = (Window)xid;
+ }
+ XMapWindow(display, window);
+ }
+ return TCL_OK;
+}
+
+/*ARGSUSED*/
+static int
+MoveOp(clientData, interp, argc, argv)
+ ClientData clientData;
+ Tcl_Interp *interp;
+ int argc; /* Not Used. */
+ char **argv;
+{
+ int x, y;
+ Tk_Window tkwin;
+ Window window;
+ Display *display;
+
+ tkwin = Tk_MainWindow(interp);
+ display = Tk_Display(tkwin);
+ window = StringToWindow(interp, argv[2]);
+ if (window == None) {
+ return TCL_ERROR;
+ }
+ if (Tk_GetPixels(interp, tkwin, argv[3], &x) != TCL_OK) {
+ Tcl_AppendResult(interp, ": bad window x-coordinate", (char *)NULL);
+ return TCL_ERROR;
+ }
+ if (Tk_GetPixels(interp, tkwin, argv[4], &y) != TCL_OK) {
+ Tcl_AppendResult(interp, ": bad window y-coordinate", (char *)NULL);
+ return TCL_ERROR;
+ }
+ XMoveWindow(display, window, x, y);
+ return TCL_OK;
+}
+
+/*ARGSUSED*/
+static int
+UnmapOp(clientData, interp, argc, argv)
+ ClientData clientData;
+ Tcl_Interp *interp;
+ int argc; /* Not used. */
+ char **argv;
+{
+ register int i;
+ Window window;
+ Display *display;
+
+ display = Tk_Display(Tk_MainWindow(interp));
+ for (i = 2; i < argc; i++) {
+ if (argv[i][0] == '.') {
+ Tk_Window tkwin;
+ Tk_FakeWin *fakePtr;
+
+ if (GetRealizedWindow(interp, argv[i], &tkwin) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ fakePtr = (Tk_FakeWin *) tkwin;
+ fakePtr->flags &= ~TK_MAPPED;
+ window = Tk_WindowId(tkwin);
+ } else {
+ int xid;
+
+ if (Tcl_GetInt(interp, argv[i], &xid) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ window = (Window)xid;
+ }
+ XMapWindow(display, window);
+ }
+ return TCL_OK;
+}
+
+/* ARGSUSED */
+static int
+ChangesOp(clientData, interp, argc, argv)
+ ClientData clientData;
+ Tcl_Interp *interp;
+ int argc; /* Not used. */
+ char **argv; /* Not used. */
+{
+ Tk_Window tkwin;
+
+ if (GetRealizedWindow(interp, argv[2], &tkwin) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (Tk_IsTopLevel(tkwin)) {
+ XSetWindowAttributes attrs;
+ Window window;
+ unsigned int mask;
+
+ window = Blt_GetRealWindowId(tkwin);
+ attrs.backing_store = WhenMapped;
+ attrs.save_under = True;
+ mask = CWBackingStore | CWSaveUnder;
+ XChangeWindowAttributes(Tk_Display(tkwin), window, mask, &attrs);
+ }
+ return TCL_OK;
+}
+
+/* ARGSUSED */
+static int
+ParentOp(clientData, interp, argc, argv)
+ClientData clientData;
+Tcl_Interp *interp;
+int argc; /* Not used. */
+char **argv; /* Not used. */
+{
+ Window window;
+ int value;
+ char buf[50];
+
+ if (Tcl_GetInt(interp, argv[2], &value) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ window = Blt_GetParent(Tk_Display(Tk_MainWindow(interp)), (Window)value);
+ if (window) {
+ sprintf(buf, "0x%x", (int)window);
+ Tcl_AppendResult(interp, buf, 0);
+ }
+ return TCL_OK;
+}
+
+/* ARGSUSED */
+static int
+QueryOp(clientData, interp, argc, argv)
+ ClientData clientData;
+ Tcl_Interp *interp;
+ int argc; /* Not used. */
+ char **argv; /* Not used. */
+{
+ int rootX, rootY, childX, childY;
+ Window root, child;
+ unsigned int mask;
+ Tk_Window tkwin = (Tk_Window)clientData;
+
+ /* GetCursorPos */
+ if (XQueryPointer(Tk_Display(tkwin), Tk_WindowId(tkwin), &root,
+ &child, &rootX, &rootY, &childX, &childY, &mask)) {
+ char string[200];
+
+ sprintf(string, "@%d,%d", rootX, rootY);
+ Tcl_SetResult(interp, string, TCL_VOLATILE);
+ }
+ return TCL_OK;
+}
+
+/*ARGSUSED*/
+static int
+WarpToOp(clientData, interp, argc, argv)
+ ClientData clientData;
+ Tcl_Interp *interp;
+ int argc; /* Not used. */
+ char **argv;
+{
+ Tk_Window tkwin, mainWindow;
+
+ mainWindow = (Tk_Window)clientData;
+ if (argc > 2) {
+ if (argv[2][0] == '@') {
+ int x, y;
+ Window root;
+
+ if (Blt_GetXY(interp, mainWindow, argv[2], &x, &y) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ root = RootWindow(Tk_Display(mainWindow),
+ Tk_ScreenNumber(mainWindow));
+ XWarpPointer(Tk_Display(mainWindow), None, root, 0, 0, 0, 0, x, y);
+ } else {
+ if (GetRealizedWindow(interp, argv[2], &tkwin) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (!Tk_IsMapped(tkwin)) {
+ Tcl_AppendResult(interp, "can't warp to unmapped window \"",
+ Tk_PathName(tkwin), "\"", (char *)NULL);
+ return TCL_ERROR;
+ }
+ XWarpPointer(Tk_Display(tkwin), None, Tk_WindowId(tkwin),
+ 0, 0, 0, 0, Tk_Width(tkwin) / 2, Tk_Height(tkwin) / 2);
+ }
+ }
+ return QueryOp(clientData, interp, 0, (char **)NULL);
+}
+
+#ifdef notdef
+static int
+ReparentOp(clientData, interp, argc, argv)
+ ClientData clientData;
+ Tcl_Interp *interp;
+ int argc;
+ char **argv;
+{
+ Tk_Window tkwin;
+
+ if (GetRealizedWindow(interp, argv[2], &tkwin) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (argc == 4) {
+ Tk_Window newParent;
+
+ if (GetRealizedWindow(interp, argv[3], &newParent) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Blt_RelinkWindow2(tkwin, Blt_GetRealWindowId(tkwin), newParent, 0, 0);
+ } else {
+ Blt_UnlinkWindow(tkwin);
+ }
+ return TCL_OK;
+}
+#endif
+
+
+/*
+ * This is a temporary home for these image routines. They will be
+ * moved when a new image type is created for them.
+ */
+/*ARGSUSED*/
+static int
+ConvolveOp(clientData, interp, argc, argv)
+ ClientData clientData; /* Not used. */
+ Tcl_Interp *interp;
+ int argc; /* Not used. */
+ char **argv;
+{
+ Tk_PhotoHandle srcPhoto, destPhoto;
+ Blt_ColorImage srcImage, destImage;
+ Filter2D filter;
+ int nValues;
+ char **valueArr;
+ double *kernel;
+ double value, sum;
+ register int i;
+ int dim;
+ int result = TCL_ERROR;
+
+ srcPhoto = Blt_FindPhoto(interp, argv[2]);
+ if (srcPhoto == NULL) {
+ Tcl_AppendResult(interp, "source image \"", argv[2], "\" doesn't",
+ " exist or is not a photo image", (char *)NULL);
+ return TCL_ERROR;
+ }
+ destPhoto = Blt_FindPhoto(interp, argv[3]);
+ if (destPhoto == NULL) {
+ Tcl_AppendResult(interp, "destination image \"", argv[3], "\" doesn't",
+ " exist or is not a photo image", (char *)NULL);
+ return TCL_ERROR;
+ }
+ if (Tcl_SplitList(interp, argv[4], &nValues, &valueArr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ kernel = NULL;
+ if (nValues == 0) {
+ Tcl_AppendResult(interp, "empty kernel", (char *)NULL);
+ goto error;
+ }
+ dim = (int)sqrt((double)nValues);
+ if ((dim * dim) != nValues) {
+ Tcl_AppendResult(interp, "kernel must be square", (char *)NULL);
+ goto error;
+ }
+ kernel = Blt_Malloc(sizeof(double) * nValues);
+ sum = 0.0;
+ for (i = 0; i < nValues; i++) {
+ if (Tcl_GetDouble(interp, valueArr[i], &value) != TCL_OK) {
+ goto error;
+ }
+ kernel[i] = value;
+ sum += value;
+ }
+ filter.kernel = kernel;
+ filter.support = dim * 0.5;
+ filter.sum = (sum == 0.0) ? 1.0 : sum;
+ filter.scale = 1.0 / nValues;
+
+ srcImage = Blt_PhotoToColorImage(srcPhoto);
+ destImage = Blt_ConvolveColorImage(srcImage, &filter);
+ Blt_FreeColorImage(srcImage);
+ Blt_ColorImageToPhoto(destImage, destPhoto);
+ Blt_FreeColorImage(destImage);
+ result = TCL_OK;
+ error:
+ if (valueArr != NULL) {
+ Blt_Free(valueArr);
+ }
+ if (kernel != NULL) {
+ Blt_Free(kernel);
+ }
+ return result;
+}
+
+/*ARGSUSED*/
+static int
+QuantizeOp(clientData, interp, argc, argv)
+ ClientData clientData; /* Not used. */
+ Tcl_Interp *interp;
+ int argc; /* Not used. */
+ char **argv;
+{
+ Tk_PhotoHandle srcPhoto, destPhoto;
+ Tk_PhotoImageBlock src, dest;
+ Blt_ColorImage srcImage, destImage;
+ int nColors = 1;
+ int result;
+
+ srcPhoto = Blt_FindPhoto(interp, argv[2]);
+ if (srcPhoto == NULL) {
+ Tcl_AppendResult(interp, "source image \"", argv[2], "\" doesn't",
+ " exist or is not a photo image", (char *)NULL);
+ return TCL_ERROR;
+ }
+ Tk_PhotoGetImage(srcPhoto, &src);
+ if ((src.width <= 1) || (src.height <= 1)) {
+ Tcl_AppendResult(interp, "source image \"", argv[2], "\" is empty",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ destPhoto = Blt_FindPhoto(interp, argv[3]);
+ if (destPhoto == NULL) {
+ Tcl_AppendResult(interp, "destination image \"", argv[3], "\" doesn't",
+ " exist or is not a photo image", (char *)NULL);
+ return TCL_ERROR;
+ }
+ Tk_PhotoGetImage(destPhoto, &dest);
+ if ((dest.width != src.width) || (dest.height != src.height)) {
+ Tk_PhotoSetSize(destPhoto, src.width, src.height);
+ }
+ if (argc>4) {
+ if (Tcl_GetInt(interp, argv[4], &nColors) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ srcImage = Blt_PhotoToColorImage(srcPhoto);
+ destImage = Blt_PhotoToColorImage(destPhoto);
+ result = Blt_QuantizeColorImage(srcImage, destImage, nColors);
+ if (result == TCL_OK) {
+ Blt_ColorImageToPhoto(destImage, destPhoto);
+ }
+ Blt_FreeColorImage(srcImage);
+ Blt_FreeColorImage(destImage);
+ return result;
+}
+
+static int
+GetColorPix32(Tcl_Interp *interp, Tk_Window tkwin, char *color, Pix32 *colPtr) {
+ XColor *xCol;
+ int red, green, blue;
+
+ colPtr->Alpha = 255;
+ if (*color == '#' && strlen(color) == 7 && 3 ==
+ sscanf(color+1, "%02x%02x%02x", &red, &green, &blue)) {
+ colPtr->Red = red;
+ colPtr->Green = green;
+ colPtr->Blue = blue;
+ return TCL_OK;
+ }
+ xCol = Tk_GetColor(interp, tkwin, Tk_GetUid(color));
+ if (xCol == NULL) {
+ return TCL_ERROR;
+ }
+ colPtr->Red = (xCol->red >> 8);
+ colPtr->Green = (xCol->green >> 8);
+ colPtr->Blue = (xCol->blue >> 8);
+ return TCL_OK;
+}
+
+static int
+XColorToPix32(XColor *xCol, Pix32 *colPtr) {
+
+ colPtr->Alpha = 255;
+ colPtr->Red = (xCol->red >> 8);
+ colPtr->Green = (xCol->green >> 8);
+ colPtr->Blue = (xCol->blue >> 8);
+ return TCL_OK;
+}
+
+/*ARGSUSED*/
+static int
+AlphaOp(clientData, interp, argc, argv)
+ ClientData clientData; /* Not used. */
+ Tcl_Interp *interp;
+ int argc; /* Not used. */
+ char **argv;
+{
+ Tk_PhotoHandle srcPhoto, destPhoto;
+ Tk_PhotoImageBlock src, dest;
+ Blt_ColorImage srcImage, destImage;
+ int result, alpha, anycolor = 0, withAlpha, hasWith = 0;
+ Tk_Window tkwin = (Tk_Window)clientData;
+ Pix32 oldColor;
+ char *string;
+ int negate = 0, shift = 0;
+
+ alpha = 0;
+ if (!strcmp("-shift", argv[2])) {
+ shift = 1;
+ argc -= 1;
+ argv += 1;
+ }
+
+ srcPhoto = Blt_FindPhoto(interp, argv[2]);
+ if (srcPhoto == NULL) {
+ Tcl_AppendResult(interp, "source image \"", argv[2], "\" doesn't",
+ " exist or is not a photo image", (char *)NULL);
+ return TCL_ERROR;
+ }
+ Tk_PhotoGetImage(srcPhoto, &src);
+ if ((src.width <= 1) || (src.height <= 1)) {
+ Tcl_AppendResult(interp, "source image \"", argv[2], "\" is empty",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ destPhoto = Blt_FindPhoto(interp, argv[3]);
+ if (destPhoto == NULL) {
+ Tcl_AppendResult(interp, "destination image \"", argv[3], "\" doesn't",
+ " exist or is not a photo image", (char *)NULL);
+ return TCL_ERROR;
+ }
+ Tk_PhotoGetImage(destPhoto, &dest);
+ if (0 && srcPhoto == destPhoto) {
+ Tcl_AppendResult(interp, "src and dest images must be different",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ string = argv[4];
+ if (string[0] == '!') {
+ negate = 1;
+ string++;
+ }
+ if (!strcmp(string, "*")) {
+ anycolor = 1;
+ if (argc <= 5) {
+ Tcl_AppendResult(interp, "must give an alpha", 0);
+ return TCL_ERROR;
+ }
+
+ } else {
+ if (GetColorPix32(interp, tkwin, string, &oldColor) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ if (argc > 5) {
+ if (Tcl_GetInt(interp, argv[5], &alpha) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (alpha<0 || alpha > 255) {
+ Tcl_AppendResult(interp, "alpha must be >= 0 and <= 255", argv[3],
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ }
+ if (argc > 6) {
+ if (Tcl_GetInt(interp, argv[6], &withAlpha) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ hasWith = 1;
+ if (withAlpha<0 || withAlpha > 255) {
+ Tcl_AppendResult(interp, "withalpha must be >= 0 and <= 255", argv[3],
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ }
+ if ((dest.width != src.width) || (dest.height != src.height)) {
+ Tk_PhotoSetSize(destPhoto, src.width, src.height);
+ }
+ srcImage = Blt_PhotoToColorImage(srcPhoto);
+ destImage = Blt_PhotoToColorImage(destPhoto);
+ result = TCL_OK;
+ {
+ int width, height;
+ int count, same;
+ Pix32 *srcPtr, *destPtr, *endPtr, *color;
+ unsigned char origAlpha;
+
+ width = Blt_ColorImageWidth(srcImage);
+ height = Blt_ColorImageHeight(srcImage);
+ count = width * height;
+ color = &oldColor;
+
+ srcPtr = Blt_ColorImageBits(srcImage);
+ destPtr = Blt_ColorImageBits(destImage);
+ if (shift) {
+ for (endPtr = destPtr + count; destPtr < endPtr; srcPtr++, destPtr++) {
+ origAlpha = srcPtr->Alpha;
+ if (origAlpha == 0) {
+ destPtr->value = srcPtr->value;
+ continue;
+ }
+ destPtr->value = color->value;
+ destPtr->Alpha = srcPtr->Blue;
+ }
+ } else if (!anycolor) {
+ color = &oldColor;
+ for (endPtr = destPtr + count; destPtr < endPtr; srcPtr++, destPtr++) {
+ origAlpha = srcPtr->Alpha;
+ destPtr->value = srcPtr->value;
+ same = (srcPtr->Red == color->Red && srcPtr->Green == color->Green &&
+ srcPtr->Blue == color->Blue);
+ if (hasWith && origAlpha != withAlpha) {
+
+ } else if (negate) {
+ if ((!same) && (origAlpha != (unsigned char)-1)) {
+ origAlpha = alpha;
+ }
+ } else {
+ if (same) {
+ origAlpha = alpha;
+ }
+ }
+ destPtr->Alpha = origAlpha;
+ }
+ } else {
+ for (endPtr = destPtr + count; destPtr < endPtr; srcPtr++, destPtr++) {
+ origAlpha = srcPtr->Alpha;
+ destPtr->value = srcPtr->value;
+ if (hasWith && origAlpha == withAlpha) {
+ destPtr->Alpha = alpha;
+ } else if (origAlpha == (unsigned char)-1) {
+ destPtr->Alpha = alpha;
+ }
+ }
+ }
+ }
+
+ if (result == TCL_OK) {
+ Blt_ColorImageToPhoto(destImage, destPhoto);
+ }
+ Blt_FreeColorImage(srcImage);
+ Blt_FreeColorImage(destImage);
+ return result;
+}
+
+/*ARGSUSED*/
+static int
+RecolorOp(clientData, interp, argc, argv)
+ ClientData clientData; /* Not used. */
+ Tcl_Interp *interp;
+ int argc; /* Not used. */
+ char **argv;
+{
+ Tk_PhotoHandle srcPhoto, destPhoto;
+ Tk_PhotoImageBlock src, dest;
+ Blt_ColorImage srcImage, destImage;
+ int result, alpha;
+ Tk_Window tkwin = (Tk_Window)clientData;
+ Pix32 oldColor, newColor;
+
+ alpha = -1;
+ srcPhoto = Blt_FindPhoto(interp, argv[2]);
+ if (srcPhoto == NULL) {
+ Tcl_AppendResult(interp, "source image \"", argv[2], "\" doesn't",
+ " exist or is not a photo image", (char *)NULL);
+ return TCL_ERROR;
+ }
+ Tk_PhotoGetImage(srcPhoto, &src);
+ if ((src.width <= 1) || (src.height <= 1)) {
+ Tcl_AppendResult(interp, "source image \"", argv[2], "\" is empty",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ destPhoto = Blt_FindPhoto(interp, argv[3]);
+ if (destPhoto == NULL) {
+ Tcl_AppendResult(interp, "destination image \"", argv[3], "\" doesn't",
+ " exist or is not a photo image", (char *)NULL);
+ return TCL_ERROR;
+ }
+ Tk_PhotoGetImage(destPhoto, &dest);
+ if (GetColorPix32(interp, tkwin, argv[4], &oldColor) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (GetColorPix32(interp, tkwin, argv[5], &newColor) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (argc > 6) {
+ if (Tcl_GetInt(interp, argv[6], &alpha) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (alpha<0 || alpha > 255) {
+ Tcl_AppendResult(interp, "alpha must be >= 0 and <= 255", argv[3],
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ }
+ if ((dest.width != src.width) || (dest.height != src.height)) {
+ Tk_PhotoSetSize(destPhoto, src.width, src.height);
+ }
+ srcImage = Blt_PhotoToColorImage(srcPhoto);
+ destImage = Blt_PhotoToColorImage(destPhoto);
+ result = Blt_RecolorImage(srcImage, destImage, &oldColor, &newColor, alpha);
+ if (result == TCL_OK) {
+ Blt_ColorImageToPhoto(destImage, destPhoto);
+ }
+ Blt_FreeColorImage(srcImage);
+ Blt_FreeColorImage(destImage);
+ return result;
+}
+
+/*ARGSUSED*/
+static int
+ColorsOp(clientData, interp, argc, argv)
+ ClientData clientData; /* Not used. */
+ Tcl_Interp *interp;
+ int argc; /* Not used. */
+ char **argv;
+{
+ Tk_PhotoHandle srcPhoto;
+ Tk_PhotoImageBlock src;
+ Blt_ColorImage srcImage;
+ int top, x, y, isalph, iscnt, isNew, cnt;
+ int i, rng[4], from = 0;
+ register Pix32 *srcPtr;
+ Tcl_Obj *listPtr;
+ char buf[100];
+ Blt_HashEntry *hPtr;
+ Blt_HashTable hTbl;
+ Blt_HashSearch cursor;
+
+ top = 0;
+ isalph = 0;
+ iscnt = 0;
+ while (argc > 3) {
+ if (!strcmp(argv[2], "-alpha")) {
+ isalph = 1;
+ } else if (!strcmp(argv[2], "-from")) {
+ from = 1;
+ if (argc<7) {
+ Tcl_AppendResult(interp, "expected 4 args: x1 y1 x2 y2", (char *)NULL);
+ return TCL_ERROR;
+ }
+ for (i=0; i<4; i++) {
+ if (Tcl_GetInt(interp, argv[i+3], rng+i)) {
+ return TCL_ERROR;
+ }
+ }
+ argc -= 4;
+ argv += 4;
+ } else if (!strcmp(argv[2], "-count")) {
+ iscnt = 1;
+ } else {
+ Tcl_AppendResult(interp, "expected -from, -alpha or -count", (char *)NULL);
+ return TCL_ERROR;
+ }
+ argc--;
+ argv++;
+ }
+ if (argc != 3) {
+ Tcl_AppendResult(interp, "too few arguments", (char *)NULL);
+ return TCL_ERROR;
+ }
+ srcPhoto = Blt_FindPhoto(interp, argv[2]);
+ if (srcPhoto == NULL) {
+ Tcl_AppendResult(interp, "source image \"", argv[2], "\" doesn't",
+ " exist or is not a photo image", (char *)NULL);
+ return TCL_ERROR;
+ }
+ Tk_PhotoGetImage(srcPhoto, &src);
+ if ((src.width < 1) || (src.height < 1)) {
+ return TCL_OK;
+ }
+ srcImage = Blt_PhotoToColorImage(srcPhoto);
+ srcPtr = Blt_ColorImageBits(srcImage);
+
+ Blt_InitHashTable(&hTbl, BLT_STRING_KEYS);
+ for (y = 0; y < src.height; y++) {
+ if (from && (y < rng[1] || y > rng[3])) continue;
+ for (x = 0; x < src.width; x++) {
+ if (from && (x < rng[0] || x > rng[2])) continue;
+ if (!isalph) {
+ sprintf(buf, "#%02x%02x%02x", srcPtr->Red, srcPtr->Green, srcPtr->Blue);
+ } else {
+ sprintf(buf, "#%02x%02x%02x:%02x", srcPtr->Red, srcPtr->Green, srcPtr->Blue, srcPtr->Alpha);
+ }
+ hPtr = Blt_CreateHashEntry(&hTbl, buf, &isNew);
+ if (isNew) {
+ Blt_SetHashValue(hPtr, 1);
+ } else {
+ cnt = (int)Blt_GetHashValue(hPtr);
+ cnt++;
+ Blt_SetHashValue(hPtr, cnt);
+ }
+ srcPtr++;
+ }
+ }
+ listPtr = Tcl_NewListObj(0,0);
+ for (hPtr = Blt_FirstHashEntry(&hTbl, &cursor);
+ hPtr != NULL; hPtr = Blt_NextHashEntry(&cursor)) {
+
+ Tcl_Obj *objPtr = Tcl_NewStringObj(Blt_GetHashKey(&hTbl, hPtr), -1);
+ Tcl_ListObjAppendElement(interp, listPtr, objPtr);
+ if (iscnt) {
+ cnt = (int)Blt_GetHashValue(hPtr);
+ sprintf(buf, "%d", cnt);
+ objPtr = Tcl_NewStringObj(buf, -1);
+ Tcl_ListObjAppendElement(interp, listPtr, objPtr);
+ }
+ }
+ Tcl_SetObjResult(interp, listPtr);
+ Blt_DeleteHashTable(&hTbl);
+ return TCL_OK;
+}
+
+/*ARGSUSED*/
+static int
+TransOp(clientData, interp, argc, argv)
+ ClientData clientData; /* Not used. */
+ Tcl_Interp *interp;
+ int argc; /* Not used. */
+ char **argv;
+{
+ Tk_PhotoHandle srcPhoto;
+ Tk_PhotoImageBlock src;
+ Blt_ColorImage srcImage;
+ int x, y, alpha,isSet = 0;
+ register Pix32 *srcPtr;
+ char buf[100];
+
+ if (argc == 6) {
+ isSet = 1;
+ if (Tcl_GetInt(interp, argv[5], &alpha) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (alpha<0 || alpha > 255) {
+ Tcl_AppendResult(interp, "alpha must be >= 0 and <= 255", argv[3],
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ }
+ if (Tcl_GetInt(interp, argv[3], &x) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (Tcl_GetInt(interp, argv[4], &y) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ srcPhoto = Blt_FindPhoto(interp, argv[2]);
+ if (srcPhoto == NULL) {
+ Tcl_AppendResult(interp, "source image \"", argv[2], "\" doesn't",
+ " exist or is not a photo image", (char *)NULL);
+ return TCL_ERROR;
+ }
+ Tk_PhotoGetImage(srcPhoto, &src);
+ if ((src.width < 1) || (src.height < 1)) {
+ Tcl_AppendResult(interp, "empty image", (char *)NULL);
+ return TCL_ERROR;
+ }
+ srcImage = Blt_PhotoToColorImage(srcPhoto);
+ srcPtr = Blt_ColorImageBits(srcImage);
+ if (y < 0 || y >= src.height || x < 0 || x >= src.width) {
+ Tcl_AppendResult(interp, "out of range", (char *)NULL);
+ return TCL_ERROR;
+ }
+ srcPtr = srcPtr + y*src.width + x;
+ if (isSet) {
+ srcPtr->Alpha = alpha;
+ Blt_ColorImageToPhoto(srcImage, srcPhoto);
+ } else {
+ sprintf(buf, "%d", srcPtr->Alpha);
+ Tcl_AppendResult(interp, buf, 0);
+ }
+ return TCL_OK;
+}
+
+#define PD_SRC_OVER(srcColor,srcAlpha,dstColor,dstAlpha) \
+ (srcColor*srcAlpha/255) + dstAlpha*(255-srcAlpha)/255*dstColor/255
+#define PD_SRC_OVER_ALPHA(srcAlpha,dstAlpha) \
+ (srcAlpha + (255-srcAlpha)*dstAlpha/255)
+
+static
+void PixBlend(
+ Pix32 *srcPtr, Pix32 *src2Ptr, Pix32 *destPtr,
+ unsigned char alpha, unsigned char dAlpha
+) {
+ dAlpha = 255-alpha;
+ destPtr->Red = PD_SRC_OVER(srcPtr->Red, alpha, src2Ptr->Red, dAlpha);
+ destPtr->Green = PD_SRC_OVER(srcPtr->Green, alpha, src2Ptr->Green, dAlpha);
+ destPtr->Blue = PD_SRC_OVER(srcPtr->Blue, alpha, src2Ptr->Blue, dAlpha);
+ destPtr->Alpha = 255; /* PD_SRC_OVER_ALPHA(alpha, dAlpha); */
+}
+
+static
+void PixMerged( Pix32 *srcPtr, Pix32 *src2Ptr, Pix32 *destPtr, Pix32 *colorPtr) {
+ unsigned char alpha;
+ int isdead;
+
+ alpha = srcPtr->Blue;
+ isdead = (srcPtr->Red == 0xde && srcPtr->Green == 0xad);
+ if (alpha == 0 && isdead) { /* "," inner fill */
+ destPtr->value = src2Ptr->value;
+ } else if (alpha == 0) { /* "." none or transparent */
+ destPtr->value = 0;
+ } else if (isdead == 0) { /* solid color with alpha */
+ destPtr->value = colorPtr->value;
+ destPtr->Alpha = alpha;
+ } else { /* Blend color with inner fill */
+ PixBlend( colorPtr, src2Ptr, destPtr, alpha, src2Ptr->Alpha);
+ }
+}
+
+
+/* For RGB grab alpha from blue and substitute maskcolor for RG="#DEAD"*/
+int Blt_ImageMergeInner(Tcl_Interp *interp, char *srcName, char *src2Name,
+ char * destName, XColor *maskColor, int leaveMsg) {
+ Tk_PhotoHandle srcPhoto, srcPhoto2, destPhoto;
+ Tk_PhotoImageBlock src, src2, dest;
+ Blt_ColorImage srcImage, srcImage2, destImage;
+ double opacity;
+ double opacity2;
+ int result, isWc;
+ Pix32 withColor;
+
+ isWc = 0;
+ opacity = 0.5;
+ opacity2 = -1;
+ srcPhoto = Blt_FindPhoto(interp, srcName);
+ if (srcPhoto == NULL) {
+ if (leaveMsg)
+ Tcl_AppendResult(interp, "source image \"", srcName, "\" doesn't",
+ " exist or is not a photo image", (char *)NULL);
+ return TCL_ERROR;
+ }
+ Tk_PhotoGetImage(srcPhoto, &src);
+ if ((src.width <= 1) || (src.height <= 1)) {
+ if (leaveMsg)
+ Tcl_AppendResult(interp, "source image \"", srcName, "\" is empty",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+
+ srcPhoto2 = Blt_FindPhoto(interp, src2Name);
+ if (srcPhoto2 == NULL) {
+ if (leaveMsg)
+ Tcl_AppendResult(interp, "source image \"", src2Name, "\" doesn't",
+ " exist or is not a photo image", (char *)NULL);
+ return TCL_ERROR;
+ }
+ Tk_PhotoGetImage(srcPhoto2, &src2);
+ if ((src2.width <= 1) || (src2.height <= 1)) {
+ if (leaveMsg)
+ Tcl_AppendResult(interp, "source image \"", src2Name, "\" is empty",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ if (maskColor) {
+ XColorToPix32(maskColor, &withColor);
+ isWc = 1;
+ goto domerge;
+ }
+ /*
+ if (argc>5) {
+
+ if (isdigit(argv[5][0]) == 0 && argv[5][0] != '.') {
+ Tk_Window tkwin;
+ char *colStr;
+
+ tkwin = Tk_MainWindow(interp);
+ isWc = 1;
+
+ colStr = argv[5];
+ if (colStr[0] == '!') {
+ colStr++;
+ isWc = 2;
+ }
+
+ return TCL_ERROR;
+ }
+ if (src.width < 4 || src.height < 4) {
+ Tcl_AppendResult(interp, "src image too small ", 0);
+ return TCL_ERROR;
+ }
+ if (src2.width < 4 || src2.height < 4) {
+ Tcl_AppendResult(interp, "src2 image too small ", 0);
+ return TCL_ERROR;
+ }
+ if (dest.width < 4 || dest.height < 4) {
+ Tcl_AppendResult(interp, "dest image too small ", 0);
+ return TCL_ERROR;
+ }
+ goto domerge;
+ }
+
+ if (Tcl_GetDouble(interp, argv[5], &opacity) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (opacity < 0.0 || opacity > 1.0) {
+ Tcl_AppendResult(interp, "opacity must be >= 0.0 and <= 1.0: ", argv[5], (char *)NULL);
+ return TCL_ERROR;
+ }
+ }
+ if (argc>6) {
+ if (Tcl_GetDouble(interp, argv[6], &opacity2) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (opacity2 < 0.0 || opacity2 > 1.0) {
+ Tcl_AppendResult(interp, "opacity must be >= 0.0 and <= 1.0: ", argv[6], (char *)NULL);
+ return TCL_ERROR;
+ }
+ }
+ */
+ if (isWc == 0 && ((src2.width != src.width) || (src2.height != src.height))) {
+ int sh, sw;
+ sw = (src2.width>src.width?src2.width:src.width);
+ sh = (src2.height>src.height?src2.height:src.height);
+ Tk_PhotoSetSize(srcPhoto2, sw, sh);
+ Tk_PhotoGetImage(srcPhoto2, &src2);
+ if (sw != src.width || sh != src.height) {
+ Tk_PhotoSetSize(srcPhoto, sw, sh);
+ Tk_PhotoGetImage(srcPhoto, &src);
+ }
+ }
+
+ domerge:
+ destPhoto = Blt_FindPhoto(interp, destName);
+ if (destPhoto == NULL) {
+ if (leaveMsg)
+ Tcl_AppendResult(interp, "destination image \"", destName, "\" doesn't",
+ " exist or is not a photo image", (char *)NULL);
+ return TCL_ERROR;
+ }
+ Tk_PhotoGetImage(destPhoto, &dest);
+
+ if ((dest.width != src.width) || (dest.height != src.height)) {
+ Tk_PhotoSetSize(destPhoto, src.width, src.height);
+ }
+ srcImage = Blt_PhotoToColorImage(srcPhoto);
+ srcImage2 = Blt_PhotoToColorImage(srcPhoto2);
+ destImage = Blt_PhotoToColorImage(destPhoto);
+
+ Tk_PhotoGetImage(destPhoto, &dest);
+ if ((dest.width != src.width) || (dest.height != src.height)) {
+ Tk_PhotoSetSize(destPhoto, src.width, src.height);
+ destImage = Blt_PhotoToColorImage(destPhoto);
+ }
+ if (isWc != 1) {
+ result = Blt_MergeColorImage(srcImage, srcImage2, destImage, opacity, opacity2,
+ isWc ? &withColor : NULL);
+ } else {
+ int xs1, xs2, xd1, xd2, xsc, xdc;
+ int ys1, ys2, yd1, yd2, ysc, ydc;
+ Pix32 *srcPtr, *src2Ptr, *destPtr;
+
+ srcPtr = Blt_ColorImageBits(srcImage);
+ src2Ptr = Blt_ColorImageBits(srcImage2);
+ destPtr = Blt_ColorImageBits(destImage);
+
+ xsc = (src2.width/2);
+ ysc = (src2.height/2);
+ xdc = (dest.width/2);
+ ydc = (dest.height/2);
+ for (xs1 = xsc-1, xs2=xsc, xd1 = xdc-1, xd2=xd1+1;
+ xd1>=0; xd1--, xs1--, xd2++, xs2++) {
+ if (xs1<0) { xs1 = xsc-1; xs2 = xs1+1; }
+ for (ys1 = ysc-1, ys2 = ysc, yd1 = ydc-1, yd2=yd1+1;
+ yd1>=0; yd1--, ys1--, yd2++, ys2++) {
+ if (ys1<0) { ys1 = ysc-1; ys2 = ys1+1; }
+
+#define DDDC_O(ind,ind2) if ( withColor.value == srcPtr[ind].value) destPtr[ind].value = src2Ptr[ind2].value
+#define DDDC(ind,ind2) PixMerged(srcPtr+(ind), src2Ptr+(ind2), destPtr+(ind), &withColor)
+
+ DDDC(yd1*dest.width+xd1, ys1*src2.width+xs1);
+ if (ys2>=src2.height) { ys2--; }
+ if (xs2>=src2.width) { xs2--; }
+ if (yd2<dest.height && xd2<dest.width) {
+ DDDC(yd2*dest.width+xd2, ys2*src2.width+xs2);
+ }
+ if (xd2<dest.width) {
+ DDDC(yd1*dest.width+xd2, ys1*src2.width+xs2);
+ }
+ if (yd2<dest.height) {
+ DDDC(yd2*dest.width+xd1, ys2*src2.width+xs1);
+ }
+ }
+ }
+ result = TCL_OK;
+
+ }
+ if (result == TCL_OK) {
+ Blt_ColorImageToPhoto(destImage, destPhoto);
+ }
+ Blt_FreeColorImage(srcImage);
+ Blt_FreeColorImage(srcImage2);
+ Blt_FreeColorImage(destImage);
+ return result;
+}
+
+
+/*ARGSUSED*/
+static int
+MergeOp(clientData, interp, argc, argv)
+ ClientData clientData; /* Not used. */
+ Tcl_Interp *interp;
+ int argc; /* Not used. */
+ char **argv;
+{
+ Tk_PhotoHandle srcPhoto, srcPhoto2, destPhoto;
+ Tk_PhotoImageBlock src, src2, dest;
+ Blt_ColorImage srcImage, srcImage2, destImage;
+ double opacity;
+ double opacity2;
+ int result, isWc;
+ Pix32 withColor;
+
+ isWc = 0;
+ opacity = 0.5;
+ opacity2 = -1;
+ srcPhoto = Blt_FindPhoto(interp, argv[2]);
+ if (srcPhoto == NULL) {
+ Tcl_AppendResult(interp, "source image \"", argv[2], "\" doesn't",
+ " exist or is not a photo image", (char *)NULL);
+ return TCL_ERROR;
+ }
+ Tk_PhotoGetImage(srcPhoto, &src);
+ if ((src.width <= 1) || (src.height <= 1)) {
+ Tcl_AppendResult(interp, "source image \"", argv[2], "\" is empty",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+
+ srcPhoto2 = Blt_FindPhoto(interp, argv[3]);
+ if (srcPhoto2 == NULL) {
+ Tcl_AppendResult(interp, "source image \"", argv[3], "\" doesn't",
+ " exist or is not a photo image", (char *)NULL);
+ return TCL_ERROR;
+ }
+ Tk_PhotoGetImage(srcPhoto2, &src2);
+ if ((src2.width <= 1) || (src2.height <= 1)) {
+ Tcl_AppendResult(interp, "source image \"", argv[3], "\" is empty",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ if (argc>5) {
+
+ if (isdigit(argv[5][0]) == 0 && argv[5][0] != '.') {
+ Tk_Window tkwin;
+ char *colStr;
+
+ tkwin = Tk_MainWindow(interp);
+ isWc = 1;
+
+ colStr = argv[5];
+ if (colStr[0] == '!') {
+ colStr++;
+ isWc = 2;
+ }
+
+ if (GetColorPix32(interp, tkwin, colStr, &withColor) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (src.width < 4 || src.height < 4) {
+ Tcl_AppendResult(interp, "src image too small ", 0);
+ return TCL_ERROR;
+ }
+ if (src2.width < 4 || src2.height < 4) {
+ Tcl_AppendResult(interp, "src2 image too small ", 0);
+ return TCL_ERROR;
+ }
+ goto domerge;
+ }
+
+ if (Tcl_GetDouble(interp, argv[5], &opacity) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (opacity < 0.0 || opacity > 1.0) {
+ Tcl_AppendResult(interp, "opacity must be >= 0.0 and <= 1.0: ", argv[5], (char *)NULL);
+ return TCL_ERROR;
+ }
+ }
+ if (argc>6) {
+ if (Tcl_GetDouble(interp, argv[6], &opacity2) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (opacity2 < 0.0 || opacity2 > 1.0) {
+ Tcl_AppendResult(interp, "opacity must be >= 0.0 and <= 1.0: ", argv[6], (char *)NULL);
+ return TCL_ERROR;
+ }
+ }
+
+ if (isWc == 0 && ((src2.width != src.width) || (src2.height != src.height))) {
+ int sh, sw;
+ sw = (src2.width>src.width?src2.width:src.width);
+ sh = (src2.height>src.height?src2.height:src.height);
+ Tk_PhotoSetSize(srcPhoto2, sw, sh);
+ Tk_PhotoGetImage(srcPhoto2, &src2);
+ if (sw != src.width || sh != src.height) {
+ Tk_PhotoSetSize(srcPhoto, sw, sh);
+ Tk_PhotoGetImage(srcPhoto, &src);
+ }
+ }
+
+domerge:
+ destPhoto = Blt_FindPhoto(interp, argv[4]);
+ if (destPhoto == NULL) {
+ Tcl_AppendResult(interp, "destination image \"", argv[4], "\" doesn't",
+ " exist or is not a photo image", (char *)NULL);
+ return TCL_ERROR;
+ }
+ Tk_PhotoGetImage(destPhoto, &dest);
+
+ srcImage = Blt_PhotoToColorImage(srcPhoto);
+ srcImage2 = Blt_PhotoToColorImage(srcPhoto2);
+ destImage = Blt_PhotoToColorImage(destPhoto);
+
+ Tk_PhotoGetImage(destPhoto, &dest);
+ if ((dest.width != src.width) || (dest.height != src.height)) {
+ Tk_PhotoSetSize(destPhoto, src.width, src.height);
+ destImage = Blt_PhotoToColorImage(destPhoto);
+ }
+ if (isWc != 1) {
+ result = Blt_MergeColorImage(srcImage, srcImage2, destImage, opacity, opacity2,
+ isWc ? &withColor : NULL);
+ } else {
+ int xs1, xs2, xd1, xd2, xsc, xdc;
+ int ys1, ys2, yd1, yd2, ysc, ydc;
+ Pix32 *srcPtr, *src2Ptr, *destPtr;
+
+ srcPtr = Blt_ColorImageBits(srcImage);
+ src2Ptr = Blt_ColorImageBits(srcImage2);
+ destPtr = Blt_ColorImageBits(destImage);
+
+ xsc = (src2.width/2);
+ ysc = (src2.height/2);
+ xdc = (dest.width/2);
+ ydc = (dest.height/2);
+ for (xs1 = xsc-1, xs2=xs1+1, xd1 = xdc-1, xd2=xdc;
+ xd1>=0; xd1--, xs1--, xd2++, xs2++) {
+ if (xs1<0) { xs1 = xsc-1; xs2 = xs1+1; }
+ for (ys1 = ysc-1, ys2 = ys1+1, yd1 = ydc-1, yd2=yd1+1;
+ yd1>=0; yd1--, ys1--, yd2++, ys2++) {
+ if (ys1<0) { ys1 = ysc-1; ys2 = ys1+1; }
+
+#define DDC(ind,ind2) destPtr[ind].value = ( withColor.value == srcPtr[ind].value ? src2Ptr[ind2].value : srcPtr[ind].value)
+
+ DDC(yd1*dest.width+xd1, ys1*src2.width+xs1);
+ //destPtr[yd1*dest.width+xd1].value = srcPtr[ys1*src2.width+xs1].value;
+ if (ys2>=src2.height) { ys2--; }
+ if (xs2>=src2.width) { xs2--; }
+ if (yd2<dest.height && xd2<dest.width)
+ DDC(yd2*dest.width+xd2, ys2*src2.width+xs2);
+ // destPtr[yd2*dest.width+xd2].value = srcPtr[ys2*src2.width+xs2].value;
+ if (xd2<dest.width)
+ DDC(yd1*dest.width+xd2, ys1*src2.width+xs2);
+ //destPtr[yd1*dest.width+xd2].value = srcPtr[ys1*src2.width+xs2].value;
+ if (yd2<dest.height)
+ DDC(yd2*dest.width+xd1, ys2*src2.width+xs1);
+ //destPtr[yd2*dest.width+xd1].value = srcPtr[ys2*src2.width+xs1].value;
+ //if (ya<src.height && ya2<dest.height && xa<src.width && xa2<dest.width) {}
+ }
+ }
+ result = TCL_OK;
+
+ }
+ if (result == TCL_OK) {
+ Blt_ColorImageToPhoto(destImage, destPhoto);
+ }
+ Blt_FreeColorImage(srcImage);
+ Blt_FreeColorImage(srcImage2);
+ Blt_FreeColorImage(destImage);
+ return result;
+}
+
+
+/*ARGSUSED*/
+static int
+ReadJPEGOp(clientData, interp, argc, argv)
+ ClientData clientData; /* Not used. */
+ Tcl_Interp *interp;
+ int argc; /* Not used. */
+ char **argv;
+{
+#if HAVE_JPEGLIB_H
+ int result;
+ Tcl_DString dString;
+ char *fileName;
+ Tk_PhotoHandle photo; /* The photo image to write into. */
+
+ photo = Blt_FindPhoto(interp, argv[3]);
+ if (photo == NULL) {
+ Tcl_AppendResult(interp, "image \"", argv[3], "\" doesn't",
+ " exist or is not a photo image", (char *)NULL);
+ return TCL_ERROR;
+ }
+ Tcl_DStringInit(&dString);
+ fileName = Tcl_TranslateFileName(interp, argv[2], &dString);
+
+ result = Blt_JPEGToPhoto(interp, fileName, photo);
+ Tcl_DStringInit(&dString);
+ return result;
+#else
+ Tcl_AppendResult(interp, "JPEG support not compiled", (char *)NULL);
+ return TCL_ERROR;
+#endif
+}
+
+static double Drand( double val) {
+#ifdef HAVE_DRAND48
+ return drand48();
+#else
+ return (double)random()/RAND_MAX;
+#endif
+}
+
+#define SLANTX(x,y) (doslant==0 || slant == 0.0?x:(((int)(x + (y * slant)))%src.width))
+#define ARCX(x,y) (doarc==0 || sineVal == 0.0?x:(((int)(x + (src.width*sqrt(0.5*0.5-((double)y/src.height-0.5)*((double)y/src.height-0.5)) * sineVal)))%src.width))
+#define SINEX(x,y) (dosine==0 || sineVal == 0.0?x:(((int)(x + (src.width*(*tfunc)(M_PI *y/src.height) * sineVal)))%src.width))
+#ifdef HAVE_DRAND48
+#define RANDX(c) (dorand==0 || randVal == 0.0?c:(c+(Drand(0) * randVal - (randVal/2.0))))
+#else
+#define RANDX(c) c
+#endif
+#define SKEWX(c) ((doskew==0 || skew == 1.0)?c:(ox>=skew?1.0:c/skew))
+#define CLAMP(c) ((((c) < 0.0) ? 0.0 : ((c) > 1.0) ? 1.0 : (c)))
+
+static int
+GradientsOp(clientData, interp, argc, argv)
+ ClientData clientData; /* Not used. */
+ Tcl_Interp *interp;
+ int argc; /* Not used. */
+ char **argv;
+{
+ double range[3];
+ double left[3];
+ int x, y, width;
+ double t;
+ XColor C;
+ XColor *leftPtr, *rightPtr;
+ Tk_Window tkwin;
+
+ tkwin = Tk_MainWindow(interp);
+
+ leftPtr = Tk_GetColor(interp, tkwin, Tk_GetUid(argv[2]));
+ if (leftPtr == NULL) {
+ return TCL_ERROR;
+ }
+ rightPtr = Tk_GetColor(interp, tkwin, Tk_GetUid(argv[3]));
+ if (rightPtr == NULL) {
+ return TCL_ERROR;
+ }
+ if (Tcl_GetInt(interp, argv[4], &width) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (width<=2) {
+ Tcl_AppendResult(interp, "width must be > 2", 0);
+ return TCL_ERROR;
+ }
+ left[0] = (double)(leftPtr->red >> 8);
+ left[1] = (double)(leftPtr->green >> 8);
+ left[2] = (double)(leftPtr->blue >> 8);
+ range[0] = (double)((rightPtr->red - leftPtr->red) / 257.0);
+ range[1] = (double)((rightPtr->green - leftPtr->green) / 257.0);
+ range[2] = (double)((rightPtr->blue - leftPtr->blue) / 257.0);
+
+ y =0;
+ for (x = 0; x < width; x++) {
+ char cbuf[100];
+ t = ((double)( sin(M_PI_2 * (double)x / (double)width)));
+ t = CLAMP(t);
+ C.red = (unsigned short)(left[0] + t * range[0]);
+ C.green = (unsigned short)(left[1] + t * range[1]);
+ C.blue = (unsigned short)(left[2] + t * range[2]);
+ sprintf(cbuf, "#%02x%02x%02x", C.red, C.green, C.blue);
+ if (x) { Tcl_AppendResult(interp, " ", 0); }
+ Tcl_AppendResult(interp, cbuf, 0);
+ }
+ return TCL_OK;
+}
+
+int
+Blt_GetGradient(Tcl_Interp *interp, Tk_Window tkwin, Gradient *gradPtr) {
+ XColor *leftPtr, *rightPtr;
+ double range[3];
+ double left[3];
+ int x, y, width;
+ double t;
+ XColor **destPtr, C;
+
+ leftPtr = gradPtr->color;
+ rightPtr = gradPtr->color2;
+ left[0] = (double)(leftPtr->red >> 8);
+ left[1] = (double)(leftPtr->green >> 8);
+ left[2] = (double)(leftPtr->blue >> 8);
+ range[0] = (double)((rightPtr->red - leftPtr->red) / 257.0);
+ range[1] = (double)((rightPtr->green - leftPtr->green) / 257.0);
+ range[2] = (double)((rightPtr->blue - leftPtr->blue) / 257.0);
+
+ y =0;
+ width = gradPtr->width;
+ if (gradPtr->grads) {
+ Blt_FreeGradient(gradPtr);
+ }
+ destPtr = gradPtr->grads = (XColor**)Blt_Calloc(width+1, sizeof(XColor*));
+ for (x = 0; x < width; x++) {
+ char cbuf[100];
+ t = ((double)( sin(M_PI_2 * (double)x / (double)width)));
+ t = CLAMP(t);
+ C.red = (unsigned short)(left[0] + t * range[0]);
+ C.green = (unsigned short)(left[1] + t * range[1]);
+ C.blue = (unsigned short)(left[2] + t * range[2]);
+ /**destPtr = Tk_GetColorByValue(tkwin, &C); */
+ sprintf(cbuf, "#%02x%02x%02x", C.red, C.green, C.blue);
+ *destPtr = Tk_GetColor(interp, tkwin, Tk_GetUid(cbuf));
+ if (*destPtr == NULL) break;
+ destPtr++;
+ }
+ gradPtr->origColor = gradPtr->color;
+ gradPtr->origColor2 = gradPtr->color2;
+ gradPtr->origWidth = gradPtr->width;
+ return TCL_OK;
+}
+
+int
+Blt_FreeGradient(Gradient *gradPtr) {
+ XColor **destPtr;
+ if (gradPtr->grads) {
+ destPtr = gradPtr->grads;
+ while (*destPtr) {
+ Tk_FreeColor(*destPtr);
+ destPtr++;
+ }
+ Blt_Free( gradPtr->grads);
+ }
+ gradPtr->grads = NULL;
+ return TCL_OK;
+
+}
+
+/*ARGSUSED*/
+static int
+GradientOp(clientData, interp, argc, argv)
+ ClientData clientData; /* Not used. */
+ Tcl_Interp *interp;
+ int argc; /* Not used. */
+ char **argv;
+{
+ Tk_PhotoHandle photo;
+ Tk_PhotoImageBlock src;
+ XColor *leftPtr, *rightPtr;
+ Tk_Window tkwin;
+ double range[3];
+ double left[3];
+ Pix32 *destPtr;
+ Blt_ColorImage destImage;
+ double skew, randVal, slant, sineVal;
+ int dorand, doslant, doskew, doarc, dosine, gtype, result, ox;
+ int nWidth = 0, nHeight = 0;
+ Tcl_Obj *objPtr;
+ static char *types[] = { "linear", "radial", "sine", "halfsine", "rectangular", "split", "blank", 0 };
+ enum ITypeIdx {
+ ILinearIdx, IRadialIdx, ISineIdx, IHalfSineIdx, IRectIdx, ISplitIdx,
+ IBlankIdx
+ };
+ double (*tfunc)(double);
+ int alpha;
+ unsigned char aVal;
+
+ aVal = 255;
+ tfunc = &sin;
+ dorand = 0;
+ doskew = 0;
+ doslant = 0;
+ dosine = 0;
+ doarc = 0;
+ skew = 1.0;
+ gtype = ISineIdx;
+ tkwin = Tk_MainWindow(interp);
+ photo = Blt_FindPhoto(interp, argv[2]);
+ if (photo == NULL) {
+ Tcl_AppendResult(interp, "source image \"", argv[2], "\" doesn't",
+ " exist or is not a photo image", (char *)NULL);
+ return TCL_ERROR;
+ }
+ Tk_PhotoGetImage(photo, &src);
+ leftPtr = Tk_GetColor(interp, tkwin, Tk_GetUid(argv[3]));
+ if (leftPtr == NULL) {
+ return TCL_ERROR;
+ }
+ rightPtr = Tk_GetColor(interp, tkwin, Tk_GetUid(argv[4]));
+ if (rightPtr == NULL) {
+ return TCL_ERROR;
+ }
+ while (argc > 5) {
+ if (argc < 7) {
+ Tcl_AppendResult(interp, "expected argument", argv[5], (char *)NULL);
+ return TCL_ERROR;
+ }
+ if (!strcmp("-alpha", argv[5])) {
+ if (Tcl_GetInt(interp, argv[6], &alpha) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (alpha<=0 || alpha > 255) {
+ Tcl_AppendResult(interp, "alpha must be > 0 and <= 255", argv[6],
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ aVal = (unsigned char) alpha;
+
+ } else if (!strcmp("-type", argv[5])) {
+ objPtr = Tcl_NewStringObj(argv[6],-1);
+ Tcl_IncrRefCount(objPtr);
+ result = Tcl_GetIndexFromObj(interp, objPtr, types, "type", 0,
+ >ype);
+ Tcl_DecrRefCount(objPtr);
+ if (result != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ } else if (!strcmp("-skew", argv[5])) {
+ doskew = 1;
+ if (Tcl_GetDouble(interp, argv[6], &skew) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (skew<0.0 || skew>1.0) {
+ Tcl_AppendResult(interp, "skew must be >=0 && <=1.0: ", argv[6],
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ } else if (!strcmp("-width", argv[5])) {
+ if (Tk_GetPixels(interp, tkwin, argv[6], &nWidth) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (nWidth<1 || nWidth>5000) {
+ Tcl_AppendResult(interp, "width must be >=1 && <=5000: ", argv[6],
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ } else if (!strcmp("-height", argv[5])) {
+ if (Tk_GetPixels(interp, tkwin, argv[6], &nHeight) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (nHeight<1 || nHeight>5000) {
+ Tcl_AppendResult(interp, "width must be >=1 && <=5000: ", argv[6],
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ } else if (!strcmp("-rand", argv[5])) {
+ dorand = 1;
+ if (Tcl_GetDouble(interp, argv[6], &randVal) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (randVal<0.0 || randVal>0.1) {
+ Tcl_AppendResult(interp, "randVal must be >= 0.0 && <= 0.1: ", argv[6],
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ } else if (!strcmp("-slant", argv[5])) {
+ doslant = 1;
+ if (Tcl_GetDouble(interp, argv[6], &slant) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (slant<-1000.0 || slant>1000.0) {
+ Tcl_AppendResult(interp, "slant must be >= -1000.0 && <= 1000.0: ", argv[6],
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ } else if (!strcmp("-mathval", argv[5])) {
+ dosine = 1;
+ if (Tcl_GetDouble(interp, argv[6], &sineVal) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (sineVal<-1000.0 || sineVal>1000.0) {
+ Tcl_AppendResult(interp, "mathval must be >= -1000.0 && <= 1000.0: ", argv[6],
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ } else if (!strcmp("-mathfunc", argv[5])) {
+ if (!strcmp("circle", argv[6])) {
+ dosine = 0;
+ doarc = 1;
+ } else if (!strcmp("sin", argv[6])) {
+ tfunc = &sin;
+ } else if (!strcmp("cos", argv[6])) {
+ tfunc = &cos;
+ } else if (!strcmp("atan", argv[6])) {
+ tfunc = &atan;
+ } else if (!strcmp("acos", argv[6])) {
+ tfunc = &acos;
+ } else if (!strcmp("asin", argv[6])) {
+ tfunc = &asin;
+ } else if (!strcmp("rand", argv[6])) {
+ tfunc = &Drand;
+ } else if (!strcmp("cosh", argv[6])) {
+ tfunc = &cosh;
+ } else if (!strcmp("sinh", argv[6])) {
+ tfunc = &sinh;
+ } else if (!strcmp("tan", argv[6])) {
+ tfunc = &tan;
+ } else if (!strcmp("tanh", argv[6])) {
+ tfunc = &tanh;
+ } else if (!strcmp("log", argv[6])) {
+ tfunc = &log;
+ } else if (!strcmp("log10", argv[6])) {
+ tfunc = &log10;
+ } else if (!strcmp("exp", argv[6])) {
+ tfunc = &exp;
+ } else if (!strcmp("sqrt", argv[6])) {
+ tfunc = &sqrt;
+ } else {
+ Tcl_AppendResult(interp, "mathfunc ", argv[6], " not one of: ",
+ "sin cos tan sinh cosh tanh asin acos atan log log10 exp sqrt rand circle", (char *)NULL);
+ return TCL_ERROR;
+ }
+ } else {
+ Tcl_AppendResult(interp, "argument \"", argv[5], "\" not one of: -type -skew -rand -slant -curve -circle",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ argc -= 2;
+ argv += 2;
+ }
+ if ((nWidth>0 || nHeight>0) && ((nWidth != src.width) || (nHeight != src.height))) {
+ if (nWidth<=0) { nWidth = src.width; }
+ if (nHeight<=0) { nHeight = src.height; }
+ Tk_PhotoSetSize(photo, nWidth, nHeight);
+ Tk_PhotoGetImage(photo, &src);
+ }
+ left[0] = (double)(leftPtr->red >> 8);
+ left[1] = (double)(leftPtr->green >> 8);
+ left[2] = (double)(leftPtr->blue >> 8);
+ range[0] = (double)((rightPtr->red - leftPtr->red) / 257.0);
+ range[1] = (double)((rightPtr->green - leftPtr->green) / 257.0);
+ range[2] = (double)((rightPtr->blue - leftPtr->blue) / 257.0);
+
+ destImage = Blt_CreateColorImage(src.width, src.height);
+ destPtr = Blt_ColorImageBits(destImage);
+
+ if (gtype == ILinearIdx) {
+ register int x, y, sx;
+ double t;
+
+ for (y = 0; y < src.height; y++) {
+ for (x = 0; x < src.width; x++) {
+ ox = (double)x / src.width;
+ sx = SLANTX(x,y);
+ sx = ARCX(sx,y);
+ sx = SINEX(sx,y);
+ t = (double)sx / src.width;
+ t = SKEWX(t);
+ t = RANDX(t);
+ t = CLAMP(t);
+ destPtr->Red = (unsigned char)(left[0] + t * range[0]);
+ destPtr->Green = (unsigned char)(left[1] + t * range[1]);
+ destPtr->Blue = (unsigned char)(left[2] + t * range[2]);
+ destPtr->Alpha = aVal;
+ destPtr++;
+ }
+ }
+ } else if (gtype == ISineIdx) {
+ register int x, y, sx;
+ double t;
+
+ for (y = 0; y < src.height; y++) {
+ for (x = 0; x < src.width; x++) {
+ ox = (double)x / src.width;
+ sx = SLANTX(x,y);
+ sx = ARCX(sx,y);
+ sx = SINEX(sx,y);
+ t = ((double)(sin(2*M_PI_2 * (double)sx / (double)src.width)));
+ t = SKEWX(t);
+ t = RANDX(t);
+ t = CLAMP(t);
+ destPtr->Red = (unsigned char)(left[0] + t * range[0]);
+ destPtr->Green = (unsigned char)(left[1] + t * range[1]);
+ destPtr->Blue = (unsigned char)(left[2] + t * range[2]);
+ destPtr->Alpha = aVal;
+ destPtr++;
+ }
+ }
+ } else if (gtype == IHalfSineIdx) {
+ register int x, y, sx;
+ double t;
+
+ for (y = 0; y < src.height; y++) {
+ for (x = 0; x < src.width; x++) {
+ ox = (double)x / src.width;
+ sx = SLANTX(x,y);
+ sx = ARCX(sx,y);
+ sx = SINEX(sx,y);
+ t = ((double)( sin(M_PI_2 * (double)sx / (double)src.width)));
+ t = SKEWX(t);
+ t = RANDX(t);
+ t = CLAMP(t);
+ destPtr->Red = (unsigned char)(left[0] + t * range[0]);
+ destPtr->Green = (unsigned char)(left[1] + t * range[1]);
+ destPtr->Blue = (unsigned char)(left[2] + t * range[2]);
+ destPtr->Alpha = aVal;
+ destPtr++;
+ }
+ }
+ } else if (gtype == IRadialIdx) {
+ register int x, y, sx;
+ register double dx, dy;
+ double dy2;
+ double t;
+ double midX, midY;
+
+ midX = midY = 0.5;
+ for (y = 0; y < src.height; y++) {
+ dy = (y / (double)src.height) - midY;
+ dy2 = dy * dy;
+ for (x = 0; x < src.width; x++) {
+ ox = (double)x / src.width;
+ sx = SLANTX(x,y);
+ sx = ARCX(sx,y);
+ sx = SINEX(sx,y);
+ dx = (sx / (double)src.width) - midX;
+ t = 1.0 - (double)sqrt(dx * dx + dy2);
+ t = SKEWX(t);
+ t = RANDX(t);
+ t = CLAMP(t);
+ destPtr->Red = (unsigned char)(left[0] + t * range[0]);
+ destPtr->Green = (unsigned char)(left[1] + t * range[1]);
+ destPtr->Blue = (unsigned char)(left[2] + t * range[2]);
+ destPtr->Alpha = aVal;
+ destPtr++;
+ }
+ }
+
+ } else if (gtype == IRectIdx) {
+ register int x, y, sx;
+ register double dx, dy;
+ double t, px, py;
+ double midX, midY;
+ double cosTheta, sinTheta;
+ double angle;
+
+ angle = M_PI_2 * -0.3;
+ cosTheta = cos(angle);
+ sinTheta = sin(angle);
+
+ midX = 0.5, midY = 0.5;
+ for (y = 0; y < src.height; y++) {
+ dy = (y / (double)src.height) - midY;
+ for (x = 0; x < src.width; x++) {
+ ox = (double)x / src.width;
+ sx = SLANTX(x,y);
+ sx = ARCX(sx,y);
+ sx = SINEX(sx,y);
+ dx = (sx / (double)src.width) - midX;
+ px = dx * cosTheta - dy * sinTheta;
+ py = dx * sinTheta + dy * cosTheta;
+ t = FABS(px) + FABS(py);
+ t = SKEWX(t);
+ t = RANDX(t);
+ t = CLAMP(t);
+ destPtr->Red = (unsigned char)(left[0] + t * range[0]);
+ destPtr->Green = (unsigned char)(left[1] + t * range[1]);
+ destPtr->Blue = (unsigned char)(left[2] + t * range[2]);
+ destPtr->Alpha = aVal;
+ destPtr++;
+ }
+ }
+ } else if (gtype == ISplitIdx) {
+ register int x, y, sx, midx;
+ double t;
+
+ midx = src.width/2;
+ for (y = 0; y < src.height; y++) {
+ for (x = 0; x < src.width; x++) {
+ ox = (double)x / src.width;
+ sx = SLANTX(x,y);
+ sx = ARCX(sx,y);
+ sx = SINEX(sx,y);
+ if (x<midx) {
+ sx += (0.1 * src.width);
+ } else {
+ sx -= (0.1 * src.width);
+ }
+ t = (double)sx / src.width;
+ t = SKEWX(t);
+ t = RANDX(t);
+ t = CLAMP(t);
+ destPtr->Red = (unsigned char)(left[0] + t * range[0]);
+ destPtr->Green = (unsigned char)(left[1] + t * range[1]);
+ destPtr->Blue = (unsigned char)(left[2] + t * range[2]);
+ destPtr->Alpha = aVal;
+ destPtr++;
+ }
+ }
+ } else if (gtype == IBlankIdx) {
+ register int x, y;
+
+ for (y = 0; y < src.height; y++) {
+ for (x = 0; x < src.width; x++) {
+ destPtr->Red = (unsigned char)0xFF;
+ destPtr->Green = (unsigned char)0xFF;
+ destPtr->Blue = (unsigned char)0xFF;
+ destPtr->Alpha = aVal;
+ destPtr++;
+ }
+ }
+ }
+ Blt_ColorImageToPhoto(destImage, photo);
+ Blt_FreeColorImage(destImage);
+ return TCL_OK;
+}
+
+/*ARGSUSED*/
+static int
+ResampleOp(clientData, interp, argc, argv)
+ ClientData clientData; /* Not used. */
+ Tcl_Interp *interp;
+ int argc; /* Not used. */
+ char **argv;
+{
+ Tk_PhotoHandle srcPhoto, destPhoto;
+ Tk_PhotoImageBlock src, dest;
+ ResampleFilter *filterPtr, *vertFilterPtr, *horzFilterPtr;
+ char *filterName;
+
+ srcPhoto = Blt_FindPhoto(interp, argv[2]);
+ if (srcPhoto == NULL) {
+ Tcl_AppendResult(interp, "source image \"", argv[2], "\" doesn't",
+ " exist or is not a photo image", (char *)NULL);
+ return TCL_ERROR;
+ }
+ destPhoto = Blt_FindPhoto(interp, argv[3]);
+ if (destPhoto == NULL) {
+ Tcl_AppendResult(interp, "destination image \"", argv[3], "\" doesn't",
+ " exist or is not a photo image", (char *)NULL);
+ return TCL_ERROR;
+ }
+ filterName = (argc > 4) ? argv[4] : "none";
+ if (Blt_GetResampleFilter(interp, filterName, &filterPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ vertFilterPtr = horzFilterPtr = filterPtr;
+ if ((filterPtr != NULL) && (argc > 5)) {
+ if (Blt_GetResampleFilter(interp, argv[5], &filterPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ vertFilterPtr = filterPtr;
+ }
+ Tk_PhotoGetImage(srcPhoto, &src);
+ if ((src.width <= 1) || (src.height <= 1)) {
+ Tcl_AppendResult(interp, "source image \"", argv[2], "\" is empty",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ Tk_PhotoGetImage(destPhoto, &dest);
+ if ((dest.width <= 1) || (dest.height <= 1)) {
+ Tk_PhotoSetSize(destPhoto, src.width, src.height);
+ goto copyImage;
+ }
+ if ((src.width == dest.width) && (src.height == dest.height)) {
+ copyImage:
+ /* Source and destination image sizes are the same. Don't
+ * resample. Simply make copy of image */
+ dest.width = src.width;
+ dest.height = src.height;
+ dest.pixelPtr = src.pixelPtr;
+ dest.pixelSize = src.pixelSize;
+ dest.pitch = src.pitch;
+ dest.offset[0] = src.offset[0];
+ dest.offset[1] = src.offset[1];
+ dest.offset[2] = src.offset[2];
+ Tk_PhotoPutBlock(destPhoto, &dest, 0, 0, dest.width, dest.height);
+ return TCL_OK;
+ }
+ if (filterPtr == NULL) {
+ Blt_ResizePhoto(srcPhoto, 0, 0, src.width, src.height, destPhoto);
+ } else {
+ Blt_ResamplePhoto(srcPhoto, 0, 0, src.width, src.height, destPhoto,
+ horzFilterPtr, vertFilterPtr);
+ }
+ return TCL_OK;
+}
+
+/*ARGSUSED*/
+static int
+BlurOp(clientData, interp, argc, argv)
+ ClientData clientData; /* Not used. */
+ Tcl_Interp *interp;
+ int argc; /* Not used. */
+ char **argv;
+{
+ Tk_PhotoHandle srcPhoto, destPhoto;
+ Tk_PhotoImageBlock src, dest;
+ double radius;
+
+ radius = 3;
+ srcPhoto = Blt_FindPhoto(interp, argv[2]);
+ if (srcPhoto == NULL) {
+ Tcl_AppendResult(interp, "source image \"", argv[2], "\" doesn't",
+ " exist or is not a photo image", (char *)NULL);
+ return TCL_ERROR;
+ }
+ destPhoto = Blt_FindPhoto(interp, argv[3]);
+ if (destPhoto == NULL) {
+ Tcl_AppendResult(interp, "destination image \"", argv[3], "\" doesn't",
+ " exist or is not a photo image", (char *)NULL);
+ return TCL_ERROR;
+ }
+ if (argc > 4) {
+ if (Tcl_GetDouble(interp, argv[4], &radius) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ Tk_PhotoGetImage(srcPhoto, &src);
+ if ((src.width <= 1) || (src.height <= 1)) {
+ Tcl_AppendResult(interp, "source image \"", argv[2], "\" is empty",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ Tk_PhotoGetImage(destPhoto, &dest);
+ Tk_PhotoSetSize(destPhoto, src.width, src.height);
+ return Blt_BlurColorImage(srcPhoto, destPhoto, (int)(radius + 0.5) );
+}
+
+/*ARGSUSED*/
+static int
+RotateOp(clientData, interp, argc, argv)
+ ClientData clientData; /* Not used. */
+ Tcl_Interp *interp;
+ int argc; /* Not used. */
+ char **argv;
+{
+ Tk_PhotoHandle srcPhoto, destPhoto;
+ Blt_ColorImage srcImage, destImage;
+ double theta;
+
+ srcPhoto = Blt_FindPhoto(interp, argv[2]);
+ if (srcPhoto == NULL) {
+ Tcl_AppendResult(interp, "image \"", argv[2], "\" doesn't",
+ " exist or is not a photo image", (char *)NULL);
+ return TCL_ERROR;
+ }
+ destPhoto = Blt_FindPhoto(interp, argv[3]);
+ if (destPhoto == NULL) {
+ Tcl_AppendResult(interp, "destination image \"", argv[3], "\" doesn't",
+ " exist or is not a photo image", (char *)NULL);
+ return TCL_ERROR;
+ }
+ if (Tcl_ExprDouble(interp, argv[4], &theta) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ srcImage = Blt_PhotoToColorImage(srcPhoto);
+ destImage = Blt_RotateColorImage(srcImage, theta);
+
+ Blt_ColorImageToPhoto(destImage, destPhoto);
+ Blt_FreeColorImage(srcImage);
+ Blt_FreeColorImage(destImage);
+ return TCL_OK;
+}
+
+/*ARGSUSED*/
+int
+Blt_ImageMirror(Tcl_Interp *interp, char *srcImg, char *dstImg, int flip, int flags) {
+ Tk_PhotoHandle srcPhoto, destPhoto;
+ Blt_ColorImage srcImage, destImage;
+ int x, y, x1, x2, y2;
+ Tk_PhotoImageBlock src, dest;
+ Pix32 *destPtr, *srcPtr;
+
+ srcPhoto = Blt_FindPhoto(interp, srcImg);
+ if (srcPhoto == NULL) {
+ Tcl_AppendResult(interp, "image \"", srcImg, "\" doesn't",
+ " exist or is not a photo image", (char *)NULL);
+ return TCL_ERROR;
+ }
+ Tk_PhotoGetImage(srcPhoto, &src);
+ destPhoto = Blt_FindPhoto(interp, dstImg);
+ if (destPhoto == NULL) {
+ Tcl_AppendResult(interp, "destination image \"", dstImg, "\" doesn't",
+ " exist or is not a photo image", (char *)NULL);
+ return TCL_ERROR;
+ }
+
+
+ if ((flip == MIRROR_TILE || flip == MIRROR_INNER || flip == MIRROR_OUTER ) && srcPhoto == destPhoto) {
+ Tcl_AppendResult(interp, "image must be different", (char *)NULL);
+ return TCL_ERROR;
+ }
+ Tk_PhotoGetImage(destPhoto, &dest);
+ if (src.width <= 0 || src.height <= 0) {
+ Tcl_AppendResult(interp, "src image empty ", 0);
+ return TCL_ERROR;
+ }
+
+ if (flip == MIRROR_TILE) {
+ if ((dest.width != (src.width *2)) || (dest.height <= (src.height*2))) {
+ Tk_PhotoSetSize(destPhoto, 2*src.width, 2*src.height);
+ Tk_PhotoGetImage(destPhoto, &dest);
+ }
+ } else if (flip != MIRROR_OUTER && flip != MIRROR_INNER) {
+ if ((dest.width != src.width) || (dest.height <= src.height)) {
+ Tk_PhotoSetSize(destPhoto, src.width, src.height);
+ Tk_PhotoGetImage(destPhoto, &dest);
+ }
+ }
+
+ srcImage = Blt_PhotoToColorImage(srcPhoto);
+ destImage = Blt_PhotoToColorImage(destPhoto);
+ destPtr = Blt_ColorImageBits(destImage);
+ srcPtr = Blt_ColorImageBits(srcImage);
+
+ if (flip == MIRROR_INNER) {
+ /* Center */
+ int xs1, xs2, xd1, xd2, xsc, xdc;
+ int ys1, ys2, yd1, yd2, ysc, ydc;
+
+ if (src.width < 4 || src.height < 4) {
+ Tcl_AppendResult(interp, "src image too small ", 0);
+ return TCL_ERROR;
+ }
+ if (dest.width < 4 || dest.height < 4) {
+ Tcl_AppendResult(interp, "dest image too small ", 0);
+ return TCL_ERROR;
+ }
+ xsc = (src.width/2);
+ ysc = (src.height/2);
+ xdc = (dest.width/2);
+ ydc = (dest.height/2);
+ for (xs1 = xsc-1, xs2=xs1+1, xd1 = xdc-1, xd2=xd1+1;
+ xd1>=0; xd1--, xs1--, xd2++, xs2++) {
+ if (xs1<0) { xs1 = xsc-1; xs2 = xs1+1; }
+ for (ys1 = ysc-1, ys2 = ys1+1, yd1 = ydc-1, yd2=yd1+1;
+ yd1>=0; yd1--, ys1--, yd2++, ys2++) {
+ if (ys1<0) { ys1 = ysc-1; ys2 = ys1+1; }
+ destPtr[yd1*dest.width+xd1].value = srcPtr[ys1*src.width+xs1].value;
+ if (ys2>=src.height) { ys2--; }
+ if (xs2>=src.width) { xs2--; }
+ if (yd2<dest.height && xd2<dest.width)
+ destPtr[yd2*dest.width+xd2].value = srcPtr[ys2*src.width+xs2].value;
+ if (xd2<dest.width)
+ destPtr[yd1*dest.width+xd2].value = srcPtr[ys1*src.width+xs2].value;
+ if (yd2<dest.height)
+ destPtr[yd2*dest.width+xd1].value = srcPtr[ys2*src.width+xs1].value;
+ //if (ya<src.height && ya2<dest.height && xa<src.width && xa2<dest.width) {}
+ }
+ }
+ }
+ if (flip == MIRROR_X) {
+ /* Flip X */
+ for (y = 0; y < src.height; y++) {
+ for (x = 0, x1 = src.width*y, x2 = src.width*(y+1)-1;
+ x < src.width;
+ x++, x1++, x2--) {
+ destPtr[x2].value = srcPtr[x1].value;
+ }
+ }
+ }
+ if (flip == MIRROR_Y) {
+ /* Flip Y */
+ for (x = 0; x < src.width; x++) {
+ for (y = 0, y2 = src.height-1; y < src.height; y++, y2--) {
+ destPtr[y2*dest.width+x].value = srcPtr[y*src.width+x].value;
+ }
+ }
+ }
+ if (flip == MIRROR_XY) {
+ /* Flip X and Y */
+ for (x = 0, x2 = src.width-1; x < src.width; x++, x2--) {
+ for (y = 0, y2 = src.height-1; y < src.height; y++, y2--) {
+ destPtr[y2*dest.width+x2].value = srcPtr[y*src.width+x].value;
+ }
+ }
+ }
+
+ if (flip == MIRROR_TILE) {
+ for (y = 0; y < src.height; y++) {
+ for (x = 0; x < src.width; x++) {
+ destPtr[y*dest.width+x].value = srcPtr[y*src.width+x].value;
+ }
+ }
+ /* Flip X */
+ for (y = 0; y < src.height; y++) {
+ for (x = 0, x1 = src.width*y, x2 = 2*src.width*(y+1)-1;
+ x < src.width;
+ x++, x1++, x2--) {
+ destPtr[x2].value = srcPtr[x1].value;
+ }
+ }
+ /* Flip Y */
+ for (x = 0; x < src.width; x++) {
+ for (y = 0, y2 = 2*src.height-1; y < src.height; y++, y2--) {
+ destPtr[y2*dest.width+x].value = srcPtr[y*src.width+x].value;
+ }
+ }
+ /* Flip X and Y */
+ for (x = 0, x2 = 2*src.width-1; x < src.width; x++, x2--) {
+ for (y = 0, y2 = 2*src.height-1; y < src.height; y++, y2--) {
+ destPtr[y2*dest.width+x2].value = srcPtr[y*src.width+x].value;
+ }
+ }
+ }
+
+ if (flip == MIRROR_OUTER) {
+ int split = (flags&1);
+ int sx1, sx2, sy1, sy2,
+ smx = (src.width/2), smy=(src.height/2),
+ dmx = (dest.width/2), dmy=(dest.height/2);
+
+ /* Initialize whole background to center pixel. */
+ int sind = (src.height/2)*src.width+src.width/2;
+ for (x = 0; x < dest.width; x++) {
+ for (y = 0; y < dest.height; y++) {
+ destPtr[y*dest.width+x].value =
+ srcPtr[sind].value;
+ }
+ }
+
+ /* Copy top & bottom pixels. */
+ for (y = 0, y2 = dest.height-1, sy1 = 0, sy2 = src.height-1;
+ y < dmy;
+ y++, y2--, sy1++, sy2--) {
+ if (sy1 >= smy) { if (split) { sy1--; sy2++; } else { sy1 = sy2 = smy; }}
+ for (x = 0, x2 = dest.width-1, sx1 = 0, sx2 = src.width-1;
+ x < dmx; x++, x2--, sx1++, sx2--) {
+ if (sx1 >= smx) { if (split) { sx1--; sx2++; } else { sx1 = sx2 = smx; }}
+ /* Top - left & right */
+ destPtr[y*dest.width+x].value = srcPtr[sy1*src.width+sx1].value;
+ destPtr[y*dest.width+x2].value = srcPtr[sy1*src.width+sx2].value;
+ /* Bottom - left & right */
+ destPtr[y2*dest.width+x].value = srcPtr[sy2*src.width+sx1].value;
+ destPtr[y2*dest.width+x2].value = srcPtr[sy2*src.width+sx2].value;
+ }
+ }
+ /* Copy left & right pixels. */
+ for (x = 0, x2 = dest.width-1, sx1 = 0, sx2 = src.width-1;
+ x < smx && x < dmx;
+ x++, x2--, sx1++, sx2--) {
+ if (sx1 >= smx) { if (split) { sx1--; sx2++; } else { sx1 = sx2 = smx; }}
+ for (y = 0, y2 = dest.height-1, sy1 = 0, sy2 = src.height-1;
+ y < dmy; y++, y2--, sy1++, sy2--) {
+ if (sy1 >= smy) { if (split) { sy1--; sy2++; } else { sy1 = sy2 = smy; }}
+ /* Left - top & bottom */
+ destPtr[y*dest.width+x].value = srcPtr[sy1*src.width+sx1].value;
+ destPtr[y*dest.width+x2].value = srcPtr[sy1*src.width+sx2].value;
+ /* Right - top & bottom */
+ destPtr[y2*dest.width+x].value = srcPtr[sy2*src.width+sx1].value;
+ destPtr[y2*dest.width+x2].value = srcPtr[sy2*src.width+sx2].value;
+ }
+ }
+ }
+
+ Blt_ColorImageToPhoto(destImage, destPhoto);
+ Blt_FreeColorImage(srcImage);
+ Blt_FreeColorImage(destImage);
+ return TCL_OK;
+}
+
+
+/*ARGSUSED*/
+static int
+MirrorOp(clientData, interp, argc, argv)
+ ClientData clientData; /* Not used. */
+ Tcl_Interp *interp;
+ int argc; /* Not used. */
+ char **argv;
+{
+ Tk_PhotoHandle srcPhoto, destPhoto;
+ int flip, halo;
+
+ flip = 3;
+ halo = 0;
+ srcPhoto = Blt_FindPhoto(interp, argv[2]);
+ if (srcPhoto == NULL) {
+ Tcl_AppendResult(interp, "image \"", argv[2], "\" doesn't",
+ " exist or is not a photo image", (char *)NULL);
+ return TCL_ERROR;
+ }
+ destPhoto = Blt_FindPhoto(interp, argv[3]);
+ if (destPhoto == NULL) {
+ Tcl_AppendResult(interp, "destination image \"", argv[3], "\" doesn't",
+ " exist or is not a photo image", (char *)NULL);
+ return TCL_ERROR;
+ }
+ if (argc>4) {
+ if (!strcmp(argv[4],"x")) {
+ flip = MIRROR_X; /* 1 */
+ } else if (!strcmp(argv[4],"y")) {
+ flip = MIRROR_Y; /* 2 */
+ } else if (!strcmp(argv[4],"xy")) {
+ flip = MIRROR_XY; /* 3 */
+ } else if (!strcmp(argv[4],"tile")) {
+ flip = MIRROR_TILE; /* 4 */
+ } else if (!strcmp(argv[4],"outer")) {
+ flip = MIRROR_OUTER; /* 5 */
+ } else if (!strcmp(argv[4],"inner")) {
+ flip = MIRROR_INNER; /* 6 */
+ } else {
+ Tcl_AppendResult(interp, "direction ", argv[4],
+ " must be \"x\", \"y\", \"xy\",\"tile\", \"inner\", or \"outer\"", (char *)NULL);
+ return TCL_ERROR;
+ }
+ }
+ if (argc>5) {
+ if (flip != MIRROR_OUTER) {
+ Tcl_AppendResult(interp, "halo is for outer only", 0);
+ return TCL_ERROR;
+ }
+ if (Tcl_GetInt(interp, argv[5], &halo) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ return Blt_ImageMirror(interp, argv[2], argv[3], flip, halo);
+}
+
+
+/*
+ * --------------------------------------------------------------------------
+ *
+ * SnapOp --
+ *
+ * Snaps a picture of a window and stores it in a designated
+ * photo image. The window must be completely visible or
+ * the snap will fail.
+ *
+ * Results:
+ * Returns a standard Tcl result. interp->result contains
+ * the list of the graph coordinates. If an error occurred
+ * while parsing the window positions, TCL_ERROR is returned,
+ * then interp->result will contain an error message.
+ *
+ * -------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+SnapOp(clientData, interp, argc, argv)
+ ClientData clientData;
+ Tcl_Interp *interp;
+ int argc; /* Not used. */
+ char **argv;
+{
+ Tk_Window tkwin;
+ int width, height, destWidth, destHeight;
+ Window window;
+
+ tkwin = Tk_MainWindow(interp);
+ window = StringToWindow(interp, argv[2]);
+ if (window == None) {
+ return TCL_ERROR;
+ }
+ if (GetWindowSize(interp, window, &width, &height) != TCL_OK) {
+ Tcl_AppendResult(interp, "can't get window geometry of \"", argv[2],
+ "\"", (char *)NULL);
+ return TCL_ERROR;
+ }
+ destWidth = width, destHeight = height;
+ if ((argc > 4) && (Blt_GetPixels(interp, tkwin, argv[4], PIXELS_POSITIVE,
+ &destWidth) != TCL_OK)) {
+ return TCL_ERROR;
+ }
+ if ((argc > 5) && (Blt_GetPixels(interp, tkwin, argv[5], PIXELS_POSITIVE,
+ &destHeight) != TCL_OK)) {
+ return TCL_ERROR;
+ }
+ return Blt_SnapPhoto(interp, tkwin, window, 0, 0, width, height, destWidth,
+ destHeight, argv[3], GAMMA);
+}
+
+/*ARGSUSED*/
+static int
+SubsampleOp(clientData, interp, argc, argv)
+ ClientData clientData; /* Main window of the interpreter. */
+ Tcl_Interp *interp;
+ int argc; /* Not used. */
+ char **argv;
+{
+ Tk_Window tkwin;
+ Tk_PhotoHandle srcPhoto, destPhoto;
+ Tk_PhotoImageBlock src, dest;
+ ResampleFilter *filterPtr, *vertFilterPtr, *horzFilterPtr;
+ char *filterName;
+ int flag;
+ int x, y;
+ int width, height;
+
+ srcPhoto = Blt_FindPhoto(interp, argv[2]);
+ if (srcPhoto == NULL) {
+ Tcl_AppendResult(interp, "source image \"", argv[2], "\" doesn't",
+ " exist or is not a photo image", (char *)NULL);
+ return TCL_ERROR;
+ }
+ destPhoto = Blt_FindPhoto(interp, argv[3]);
+ if (destPhoto == NULL) {
+ Tcl_AppendResult(interp, "destination image \"", argv[3], "\" doesn't",
+ " exist or is not a photo image", (char *)NULL);
+ return TCL_ERROR;
+ }
+ tkwin = (Tk_Window)clientData;
+ flag = PIXELS_NONNEGATIVE;
+ if (Blt_GetPixels(interp, tkwin, argv[4], flag, &x) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (Blt_GetPixels(interp, tkwin, argv[5], flag, &y) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ flag = PIXELS_POSITIVE;
+ if (Blt_GetPixels(interp, tkwin, argv[6], flag, &width) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (Blt_GetPixels(interp, tkwin, argv[7], flag, &height) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ filterName = (argc > 8) ? argv[8] : "none";
+ if (Blt_GetResampleFilter(interp, filterName, &filterPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ vertFilterPtr = horzFilterPtr = filterPtr;
+ if ((filterPtr != NULL) && (argc > 9)) {
+ if (Blt_GetResampleFilter(interp, argv[9], &filterPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ vertFilterPtr = filterPtr;
+ }
+ Tk_PhotoGetImage(srcPhoto, &src);
+ Tk_PhotoGetImage(destPhoto, &dest);
+ if ((src.width <= 1) || (src.height <= 1)) {
+ Tcl_AppendResult(interp, "source image \"", argv[2], "\" is empty",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ if (((x + width) > src.width) || ((y + height) > src.height)) {
+ Tcl_AppendResult(interp, "nonsensical dimensions for subregion: x=",
+ argv[4], " y=", argv[5], " width=", argv[6], " height=",
+ argv[7], (char *)NULL);
+ return TCL_ERROR;
+ }
+ if ((dest.width <= 1) || (dest.height <= 1)) {
+ Tk_PhotoSetSize(destPhoto, width, height);
+ }
+ if (filterPtr == NULL) {
+ Blt_ResizePhoto(srcPhoto, x, y, width, height, destPhoto);
+ } else {
+ Blt_ResamplePhoto(srcPhoto, x, y, width, height, destPhoto,
+ horzFilterPtr, vertFilterPtr);
+ }
+ return TCL_OK;
+}
+
+static Blt_OpSpec imageOps[] =
+{
+ {"alpha", 2, (Blt_Op)AlphaOp, 6, 10, "?-shift? srcPhoto destPhoto Color ?alpha? ?withalpha?",},
+ {"blur", 2, (Blt_Op)BlurOp, 5, 6, "srcPhoto destPhoto ?radius?",},
+ {"colors", 3, (Blt_Op)ColorsOp, 4, 0, "?-alpha? ?-count? ?-from x1 y1 x2 y2? srcPhoto",},
+ {"convolve", 3, (Blt_Op)ConvolveOp, 6, 6, "srcPhoto destPhoto filter",},
+ {"gradient", 1, (Blt_Op)GradientOp, 6, 0, "photo left right ?-type lines|normal|radial|rectangular|linear|sine|halfsine? ?-skew val? ?-slant val? ?-rand val? ?-mathval val? ?-mathfunc circle|sin|cos|tan|asin|acos|atan|sinh|cosh|tanh|exp|sqrt|log|log10|rand?",},
+ {"merge", 2, (Blt_Op)MergeOp, 6, 7, "srcPhoto1 srcPhoto2 destPhoto ?opacity? ?opacity2?",},
+ {"mirror", 3, (Blt_Op)MirrorOp, 5, 7, "srcPhoto destPhoto ?x|y|xy|tile|outer|innert? ?halo?",},
+ {"quantize", 2, (Blt_Op)QuantizeOp, 4, 5, "srcPhoto destPhoto ?nColors?",},
+ {"readjpeg", 3, (Blt_Op)ReadJPEGOp, 5, 5, "fileName photoName",},
+ {"recolor", 3, (Blt_Op)RecolorOp, 7, 8, "srcPhoto destPhoto oldColor newColor ?alpha?",},
+ {"resample", 3, (Blt_Op)ResampleOp, 5, 7,
+ "srcPhoto destPhoto ?horzFilter vertFilter?",},
+ {"rotate", 2, (Blt_Op)RotateOp, 6, 6, "srcPhoto destPhoto angle",},
+ {"subsample", 2, (Blt_Op)SubsampleOp, 9, 11,
+ "srcPhoto destPhoto x y width height ?horzFilter? ?vertFilter?",},
+ {"trans", 2, (Blt_Op)TransOp, 6, 7, "image x y ?alpha?",},
+};
+
+static int nImageOps = sizeof(imageOps) / sizeof(Blt_OpSpec);
+
+/* ARGSUSED */
+static int
+ImageOp(clientData, interp, argc, argv)
+ ClientData clientData; /* Main window of interpreter. */
+ Tcl_Interp *interp; /* Current interpreter. */
+ int argc; /* Number of arguments. */
+ char **argv; /* Argument strings. */
+{
+ Blt_Op proc;
+ int result;
+
+ proc = Blt_GetOp(interp, nImageOps, imageOps, BLT_OP_ARG2, argc, argv, 0);
+ if (proc == NULL) {
+ return TCL_ERROR;
+ }
+ clientData = (ClientData)Tk_MainWindow(interp);
+ result = (*proc) (clientData, interp, argc - 1, argv + 1);
+ return result;
+}
+
+static Blt_OpSpec winOps[] =
+{
+ {"changes", 3, (Blt_Op)ChangesOp, 3, 3, "window",},
+#ifndef WIN32
+ {"colormap", 3, (Blt_Op)ColormapOp, 3, 3, "window",},
+#endif
+ {"gradients", 1, (Blt_Op)GradientsOp, 5, 5, "color1 color2 width",},
+ {"image", 1, (Blt_Op)ImageOp, 2, 0, "args",},
+ {"lower", 1, (Blt_Op)LowerOp, 2, 0, "window ?window?...",},
+ {"map", 2, (Blt_Op)MapOp, 2, 0, "window ?window?...",},
+ {"move", 2, (Blt_Op)MoveOp, 5, 5, "window x y",},
+ {"parent", 3, (Blt_Op)ParentOp, 3, 3, "window",},
+ {"query", 3, (Blt_Op)QueryOp, 2, 2, "",},
+ {"raise", 2, (Blt_Op)RaiseOp, 2, 0, "window ?window?...",},
+#ifdef notdef
+ {"reparent", 3, (Blt_Op)ReparentOp, 3, 4, "window ?parent?",},
+#endif
+ {"snap", 2, (Blt_Op)SnapOp, 4, 8, "window photoName ?width height?",},
+ {"unmap", 1, (Blt_Op)UnmapOp, 2, 0, "window ?window?...",},
+ {"warpto", 1, (Blt_Op)WarpToOp, 2, 5, "?window?",},
+};
+
+static int nWinOps = sizeof(winOps) / sizeof(Blt_OpSpec);
+
+/* ARGSUSED */
+static int
+WinopCmd(clientData, interp, argc, argv)
+ ClientData clientData; /* Main window of interpreter. */
+ Tcl_Interp *interp; /* Current interpreter. */
+ int argc; /* Number of arguments. */
+ char **argv; /* Argument strings. */
+{
+ Blt_Op proc;
+ int result;
+
+ proc = Blt_GetOp(interp, nWinOps, winOps, BLT_OP_ARG1, argc, argv, 0);
+ if (proc == NULL) {
+ return TCL_ERROR;
+ }
+ clientData = (ClientData)Tk_MainWindow(interp);
+ result = (*proc) (clientData, interp, argc, argv);
+ return result;
+}
+
+int
+Blt_WinopInit(interp)
+ Tcl_Interp *interp;
+{
+ static Blt_CmdSpec cmdSpec = {"winop", WinopCmd,};
+
+ if (Blt_InitCmd(interp, "blt", &cmdSpec) == NULL) {
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+#endif /* NO_WINOP */