summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhobbs <hobbs>2002-10-10 07:27:12 (GMT)
committerhobbs <hobbs>2002-10-10 07:27:12 (GMT)
commit25389e0fe4affab040640155bbe395076a862673 (patch)
treeef7eda728b2701da1233e333496a53eaefbb67b5
parent7e4adcbf1eb38a5473022365dc5dab9e6712b1dd (diff)
downloadtk-25389e0fe4affab040640155bbe395076a862673.zip
tk-25389e0fe4affab040640155bbe395076a862673.tar.gz
tk-25389e0fe4affab040640155bbe395076a862673.tar.bz2
* generic/tkCanvas.h: moved TkColormapData struct to tkCanvPs.c
* generic/tkCanvPs.c (TkImageGetColor): corrected bogus use of TkColormapData on Windows. Non-separated data may need correction as well. * win/tkWinImage.c (XGetImage, XGetImageZPixmap): added support for generating ps for embedded windows on canvases.
-rw-r--r--ChangeLog13
-rw-r--r--generic/tkCanvPs.c29
-rw-r--r--generic/tkCanvas.h16
-rw-r--r--win/tkWinImage.c351
4 files changed, 365 insertions, 44 deletions
diff --git a/ChangeLog b/ChangeLog
index 4b0849d..49b994b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2002-10-10 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tkCanvas.h: moved TkColormapData struct to tkCanvPs.c
+ * generic/tkCanvPs.c (TkImageGetColor): corrected bogus use of
+ TkColormapData on Windows. Non-separated data may need correction
+ as well.
+ * win/tkWinImage.c (XGetImage, XGetImageZPixmap): added support
+ for generating ps for embedded windows on canvases.
+
+ * unix/configure: regen
+ * unix/tcl.m4: replaced SC_ENABLE_MEMDEBUG with a more intelligent
+ SC_ENABLE_SYMBOLS that takes yes|no|mem|all as options now.
+
2002-07-25 Jeff Hobbs <jeffh@ActiveState.com>
* library/tk.tcl (RestoreFocusGrab): handle the case where the
diff --git a/generic/tkCanvPs.c b/generic/tkCanvPs.c
index 940b754..86812e4 100644
--- a/generic/tkCanvPs.c
+++ b/generic/tkCanvPs.c
@@ -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: tkCanvPs.c,v 1.7 2000/04/25 01:03:06 hobbs Exp $
+ * RCS: @(#) $Id: tkCanvPs.c,v 1.7.2.1 2002/10/10 07:27:12 hobbs Exp $
*/
#include "tkInt.h"
@@ -23,6 +23,20 @@
*/
/*
+ * The following definition is used in generating postscript for images
+ * and windows.
+ */
+
+typedef struct TkColormapData { /* Hold color information for a window */
+ int separated; /* Whether to use separate color bands */
+ int color; /* Whether window is color or black/white */
+ int ncolors; /* Number of color values stored */
+ XColor *colors; /* Pixel value -> RGB mappings */
+ int red_mask, green_mask, blue_mask; /* Masks and shifts for each */
+ int red_shift, green_shift, blue_shift; /* color band */
+} TkColormapData;
+
+/*
* One of the following structures is created to keep track of Postscript
* output being generated. It consists mostly of information provided on
* the widget command line.
@@ -128,7 +142,7 @@ static CONST char * CONST prolog[]= {
\n\
% This is a standard prolog for Postscript generated by Tk's canvas\n\
% widget.\n\
-% RCS: @(#) $Id: tkCanvPs.c,v 1.7 2000/04/25 01:03:06 hobbs Exp $\n\
+% RCS: @(#) $Id: tkCanvPs.c,v 1.7.2.1 2002/10/10 07:27:12 hobbs Exp $\n\
\n\
% The definitions below just define all of the variables used in\n\
% any of the procedures here. This is needed for obscure reasons\n\
@@ -1429,9 +1443,20 @@ TkImageGetColor(cdata, pixel, red, green, blue)
int r = (pixel & cdata->red_mask) >> cdata->red_shift;
int g = (pixel & cdata->green_mask) >> cdata->green_shift;
int b = (pixel & cdata->blue_mask) >> cdata->blue_shift;
+#ifdef WIN32
+ /*
+ * Because XQueryColors is an empty stub on Windows, we need
+ * to just make this simple calculation. The TkColormapData
+ * XColor data is otherwise bogus on Windows. -- hobbs
+ */
+ *red = (double)r / 255.0;
+ *green = (double)g / 255.0;
+ *blue = (double)b / 255.0;
+#else
*red = cdata->colors[r].red / 65535.0;
*green = cdata->colors[g].green / 65535.0;
*blue = cdata->colors[b].blue / 65535.0;
+#endif
} else {
*red = cdata->colors[pixel].red / 65535.0;
*green = cdata->colors[pixel].green / 65535.0;
diff --git a/generic/tkCanvas.h b/generic/tkCanvas.h
index 9d2c392..0b7765a 100644
--- a/generic/tkCanvas.h
+++ b/generic/tkCanvas.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: tkCanvas.h,v 1.4 1999/12/14 06:52:27 hobbs Exp $
+ * RCS: @(#) $Id: tkCanvas.h,v 1.4.2.1 2002/10/10 07:27:12 hobbs Exp $
*/
#ifndef _TKCANVAS
@@ -295,18 +295,4 @@ typedef struct TkCanvas {
extern int TkCanvPostscriptCmd _ANSI_ARGS_((TkCanvas *canvasPtr,
Tcl_Interp *interp, int argc, char **argv));
-/*
- * The following definition is shared between tkCanvPs.c and tkCanvImg.c,
- * and is used in generating postscript for images and windows.
- */
-
-typedef struct TkColormapData { /* Hold color information for a window */
- int separated; /* Whether to use separate color bands */
- int color; /* Whether window is color or black/white */
- int ncolors; /* Number of color values stored */
- XColor *colors; /* Pixel value -> RGB mappings */
- int red_mask, green_mask, blue_mask; /* Masks and shifts for each */
- int red_shift, green_shift, blue_shift; /* color band */
-} TkColormapData;
-
#endif /* _TKCANVAS */
diff --git a/win/tkWinImage.c b/win/tkWinImage.c
index 448ad72..c650a54 100644
--- a/win/tkWinImage.c
+++ b/win/tkWinImage.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: tkWinImage.c,v 1.3 2000/01/06 02:22:51 hobbs Exp $
+ * RCS: @(#) $Id: tkWinImage.c,v 1.3.2.1 2002/10/10 07:27:12 hobbs Exp $
*/
#include "tkWinInt.h"
@@ -221,7 +221,7 @@ XCreateImage(display, visual, depth, format, offset, data, width, height,
imagePtr->data = data;
imagePtr->byte_order = LSBFirst;
imagePtr->bitmap_unit = 8;
- imagePtr->bitmap_bit_order = MSBFirst;
+ imagePtr->bitmap_bit_order = LSBFirst;
imagePtr->bitmap_pad = bitmap_pad;
imagePtr->bits_per_pixel = depth;
imagePtr->depth = depth;
@@ -261,6 +261,242 @@ XCreateImage(display, visual, depth, format, offset, data, width, height,
/*
*----------------------------------------------------------------------
+ * XGetImageZPixmap --
+ *
+ * This function copies data from a pixmap or window into an
+ * XImage. This handles the ZPixmap case only.
+ *
+ * Results:
+ * Returns a newly allocated image containing the data from the
+ * given rectangle of the given drawable.
+ *
+ * Side effects:
+ * None.
+ *
+ * This procedure is adapted from the XGetImage implementation in TkNT.
+ * That code is Copyright (c) 1994 Software Research Associates, Inc.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static XImage *
+XGetImageZPixmap(display, d, x, y, width, height, plane_mask, format)
+ Display* display;
+ Drawable d;
+ int x;
+ int y;
+ unsigned int width;
+ unsigned int height;
+ unsigned long plane_mask;
+ int format;
+{
+ TkWinDrawable *twdPtr = (TkWinDrawable *)d;
+ XImage *ret_image;
+ unsigned char *smallBitData, *smallBitBase, *bigBitData;
+ HDC hdc, hdcMem;
+ HBITMAP hbmp, hbmpPrev;
+ BITMAPINFO *bmInfo = NULL;
+ HPALETTE hPal, hPalPrev1, hPalPrev2;
+ unsigned int byte_width;
+ unsigned int h, w, n;
+ unsigned char plmr, plmg, plmb;
+ unsigned char *data;
+ int size;
+ unsigned int depth;
+ TkWinDCState state;
+ BOOL ret;
+
+ if (format != ZPixmap) {
+ TkpDisplayWarning(
+ "XGetImageZPixmap: only ZPixmap types are implemented",
+ "XGetImageZPixmap Failure");
+ return NULL;
+ }
+
+ hdc = TkWinGetDrawableDC(display, d, &state);
+
+ /* Need to do a Blt operation to copy into a new bitmap */
+ hbmp = CreateCompatibleBitmap(hdc, width, height);
+ hdcMem = CreateCompatibleDC(hdc);
+ hbmpPrev = SelectObject(hdcMem, hbmp);
+ hPal = state.palette;
+ if (hPal) {
+ hPalPrev1 = SelectPalette(hdcMem, hPal, FALSE);
+ n = RealizePalette(hdcMem);
+ if (n > 0) {
+ UpdateColors (hdcMem);
+ }
+ hPalPrev2 = SelectPalette(hdc, hPal, FALSE);
+ n = RealizePalette(hdc);
+ if (n > 0) {
+ UpdateColors (hdc);
+ }
+ }
+
+ ret = BitBlt(hdcMem, 0, 0, width, height, hdc, x, y, SRCCOPY);
+ if (hPal) {
+ SelectPalette(hdc, hPalPrev2, FALSE);
+ }
+ SelectObject(hdcMem, hbmpPrev);
+ TkWinReleaseDrawableDC(d, hdc, &state);
+ if (ret == FALSE) {
+ goto cleanup;
+ }
+ if (twdPtr->type == TWD_WINDOW) {
+ depth = Tk_Depth((Tk_Window) twdPtr->window.winPtr);
+ } else {
+ depth = twdPtr->bitmap.depth;
+ }
+
+ size = sizeof(BITMAPINFO);
+ if (depth <= 8) {
+ size += sizeof(unsigned short) * (1 << depth);
+ }
+ bmInfo = (BITMAPINFO *) ckalloc(size);
+
+ bmInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ bmInfo->bmiHeader.biWidth = width;
+ bmInfo->bmiHeader.biHeight = -(int) height;
+ bmInfo->bmiHeader.biPlanes = 1;
+ bmInfo->bmiHeader.biBitCount = depth;
+ bmInfo->bmiHeader.biCompression = BI_RGB;
+ bmInfo->bmiHeader.biSizeImage = 0;
+ bmInfo->bmiHeader.biXPelsPerMeter = 0;
+ bmInfo->bmiHeader.biYPelsPerMeter = 0;
+ bmInfo->bmiHeader.biClrUsed = 0;
+ bmInfo->bmiHeader.biClrImportant = 0;
+
+ if (depth == 1) {
+ unsigned char *p, *pend;
+ GetDIBits(hdcMem, hbmp, 0, height, NULL, bmInfo, DIB_PAL_COLORS);
+ data = ckalloc(bmInfo->bmiHeader.biSizeImage);
+ if (!data) {
+ /* printf("Failed to allocate data area for XImage.\n"); */
+ ret_image = NULL;
+ goto cleanup;
+ }
+ ret_image = XCreateImage(display, NULL, depth, ZPixmap, 0, data,
+ width, height, 32, ((width + 31) >> 3) & ~1);
+ if (ret_image == NULL) {
+ ckfree(data);
+ goto cleanup;
+ }
+
+ /* Get the BITMAP info into the Image. */
+ if (GetDIBits(hdcMem, hbmp, 0, height, data, bmInfo,
+ DIB_PAL_COLORS) == 0) {
+ ckfree((char *) ret_image->data);
+ ckfree((char *) ret_image);
+ ret_image = NULL;
+ goto cleanup;
+ }
+ p = data;
+ pend = data + bmInfo->bmiHeader.biSizeImage;
+ while (p < pend) {
+ *p = ~*p;
+ p++;
+ }
+ } else if (depth == 8) {
+ unsigned short *palette;
+ unsigned int i;
+ unsigned char *p;
+
+ GetDIBits(hdcMem, hbmp, 0, height, NULL, bmInfo, DIB_PAL_COLORS);
+ data = ckalloc(bmInfo->bmiHeader.biSizeImage);
+ if (!data) {
+ /* printf("Failed to allocate data area for XImage.\n"); */
+ ret_image = NULL;
+ goto cleanup;
+ }
+ ret_image = XCreateImage(display, NULL, 8, ZPixmap, 0, data,
+ width, height, 8, width);
+ if (ret_image == NULL) {
+ ckfree((char *) data);
+ goto cleanup;
+ }
+
+ /* Get the BITMAP info into the Image. */
+ if (GetDIBits(hdcMem, hbmp, 0, height, data, bmInfo,
+ DIB_PAL_COLORS) == 0) {
+ ckfree((char *) ret_image->data);
+ ckfree((char *) ret_image);
+ ret_image = NULL;
+ goto cleanup;
+ }
+ p = data;
+ palette = (unsigned short *) bmInfo->bmiColors;
+ for (i = 0; i < bmInfo->bmiHeader.biSizeImage; i++, p++) {
+ *p = (unsigned char) palette[*p];
+ }
+ } else {
+ GetDIBits(hdcMem, hbmp, 0, height, NULL, bmInfo, DIB_RGB_COLORS);
+ data = ckalloc(width * height * 4);
+ if (!data) {
+ /* printf("Failed to allocate data area for XImage.\n"); */
+ ret_image = NULL;
+ goto cleanup;
+ }
+ ret_image = XCreateImage(display, NULL, 32, ZPixmap, 0, data,
+ width, height, 0, width * 4);
+ if (ret_image == NULL) {
+ ckfree((char *) data);
+ goto cleanup;
+ }
+
+ byte_width = ((width * 3 + 3) & ~3);
+ smallBitBase = ckalloc(byte_width * height);
+ if (!smallBitBase) {
+ ckfree((char *) ret_image->data);
+ ckfree((char *) ret_image);
+ ret_image = NULL;
+ goto cleanup;
+ }
+ smallBitData = smallBitBase;
+
+ /* Get the BITMAP info into the Image. */
+ if (GetDIBits(hdcMem, hbmp, 0, height, smallBitData, bmInfo,
+ DIB_RGB_COLORS) == 0) {
+ ckfree((char *) ret_image->data);
+ ckfree((char *) ret_image);
+ ret_image = NULL;
+ goto cleanup;
+ }
+
+ plmr = (unsigned char) (plane_mask & 0xff0000) >> 16;
+ plmg = (unsigned char) (plane_mask & 0x00ff00) >> 8;
+ plmb = (unsigned char) (plane_mask & 0x0000ff);
+
+ /* Copy the 24 Bit Pixmap to a 32-Bit one. */
+ for (h = 0; h < height; h++) {
+ bigBitData = ret_image->data + h * ret_image->bytes_per_line;
+ smallBitData = smallBitBase + h * byte_width;
+
+ for (w = 0; w < width; w++) {
+ *bigBitData++ = ((*smallBitData++)) /* & plmr */;
+ *bigBitData++ = ((*smallBitData++)) /* & plmg */;
+ *bigBitData++ = ((*smallBitData++)) /* & plmb */;
+ *bigBitData++ = 0;
+ }
+ }
+ /* Free the Device contexts, and the Bitmap */
+ ckfree((char *) smallBitBase);
+ }
+
+ cleanup:
+ if (bmInfo) {
+ ckfree((char *) bmInfo);
+ }
+ if (hPal) {
+ SelectPalette(hdcMem, hPalPrev1, FALSE);
+ }
+ DeleteDC(hdcMem);
+ DeleteObject(hbmp);
+
+ return ret_image;
+}
+
+/*
+ *----------------------------------------------------------------------
*
* XGetImage --
*
@@ -291,39 +527,100 @@ XGetImage(display, d, x, y, width, height, plane_mask, format)
TkWinDrawable *twdPtr = (TkWinDrawable *)d;
XImage *imagePtr;
HDC dc;
- char infoBuf[sizeof(BITMAPINFO) + sizeof(RGBQUAD)];
- BITMAPINFO *infoPtr = (BITMAPINFO*)infoBuf;
- if ((twdPtr->type != TWD_BITMAP) || (twdPtr->bitmap.handle == NULL)
- || (format != XYPixmap) || (plane_mask != 1)) {
- panic("XGetImage: not implemented");
+ display->request++;
+
+ if (twdPtr == NULL) {
+ /*
+ * Avoid unmapped windows or bad drawables
+ */
+ return NULL;
}
+ if (format == ZPixmap) {
+ /*
+ * This actually handles most TWD_WINDOW requests, but it varies
+ * from the one below in that it really does a screen capture of
+ * an area, but that is consistent with the Unix behavior -- hobbs
+ */
+ imagePtr = XGetImageZPixmap(display, d, x, y,
+ width, height, plane_mask, format);
+ } else if (twdPtr->type != TWD_BITMAP) {
+ /*
+ * This handles TWD_WINDOW or TWD_WINDC.
+ * If the window being copied isn't visible (unmapped or obscured),
+ * we quietly stop copying (no user error). The user will see black
+ * where the widget should be.
+ * This branch is likely not followed in favor of XGetImageZPixmap.
+ */
+ TkWinDCState state;
+ unsigned int xx, yy, size;
+ COLORREF pixel;
- imagePtr = XCreateImage(display, NULL, 1, XYBitmap, 0, NULL,
- width, height, 32, 0);
- imagePtr->data = ckalloc(imagePtr->bytes_per_line * imagePtr->height);
+ dc = TkWinGetDrawableDC(display, d, &state);
- dc = GetDC(NULL);
+ imagePtr = XCreateImage(display, NULL, (TkWinGetWinPtr(d))->depth,
+ format, 0, NULL, width, height, 32, 0);
+ size = imagePtr->bytes_per_line * imagePtr->height;
+ imagePtr->data = ckalloc(size);
+ ZeroMemory(imagePtr->data, size);
- GetDIBits(dc, twdPtr->bitmap.handle, 0, height, NULL,
- infoPtr, DIB_RGB_COLORS);
+ for (yy = 0; yy < height; yy++) {
+ for (xx = 0; xx < width; xx++) {
+ pixel = GetPixel(dc, x+(int)xx, y+(int)yy);
+ if (pixel == CLR_INVALID) {
+ break;
+ }
+ PutPixel(imagePtr, xx, yy, pixel);
+ }
+ }
- infoPtr->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- infoPtr->bmiHeader.biWidth = width;
- infoPtr->bmiHeader.biHeight = -(LONG)height;
- infoPtr->bmiHeader.biPlanes = 1;
- infoPtr->bmiHeader.biBitCount = 1;
- infoPtr->bmiHeader.biCompression = BI_RGB;
- infoPtr->bmiHeader.biCompression = 0;
- infoPtr->bmiHeader.biXPelsPerMeter = 0;
- infoPtr->bmiHeader.biYPelsPerMeter = 0;
- infoPtr->bmiHeader.biClrUsed = 0;
- infoPtr->bmiHeader.biClrImportant = 0;
+ TkWinReleaseDrawableDC(d, dc, &state);
+ } else {
+ char *errMsg = NULL;
+ char infoBuf[sizeof(BITMAPINFO) + sizeof(RGBQUAD)];
+ BITMAPINFO *infoPtr = (BITMAPINFO*)infoBuf;
- GetDIBits(dc, twdPtr->bitmap.handle, 0, height, imagePtr->data,
- infoPtr, DIB_RGB_COLORS);
- ReleaseDC(NULL, dc);
+ if (twdPtr->bitmap.handle == NULL) {
+ errMsg = "XGetImage: not implemented for empty bitmap handles";
+ } else if (format != XYPixmap) {
+ errMsg = "XGetImage: not implemented for format != XYPixmap";
+ } else if (plane_mask != 1) {
+ errMsg = "XGetImage: not implemented for plane_mask != 1";
+ }
+ if (errMsg != NULL) {
+ /*
+ * Do a soft warning for the unsupported XGetImage types.
+ */
+ TkpDisplayWarning(errMsg, "XGetImage Failure");
+ return NULL;
+ }
+
+ imagePtr = XCreateImage(display, NULL, 1, XYBitmap, 0, NULL,
+ width, height, 32, 0);
+ imagePtr->data = ckalloc(imagePtr->bytes_per_line * imagePtr->height);
+
+ dc = GetDC(NULL);
+
+ GetDIBits(dc, twdPtr->bitmap.handle, 0, height, NULL,
+ infoPtr, DIB_RGB_COLORS);
+
+ infoPtr->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ infoPtr->bmiHeader.biWidth = width;
+ infoPtr->bmiHeader.biHeight = -(LONG)height;
+ infoPtr->bmiHeader.biPlanes = 1;
+ infoPtr->bmiHeader.biBitCount = 1;
+ infoPtr->bmiHeader.biCompression = BI_RGB;
+ infoPtr->bmiHeader.biCompression = 0;
+ infoPtr->bmiHeader.biXPelsPerMeter = 0;
+ infoPtr->bmiHeader.biYPelsPerMeter = 0;
+ infoPtr->bmiHeader.biClrUsed = 0;
+ infoPtr->bmiHeader.biClrImportant = 0;
+
+ GetDIBits(dc, twdPtr->bitmap.handle, 0, height, imagePtr->data,
+ infoPtr, DIB_RGB_COLORS);
+ ReleaseDC(NULL, dc);
+ }
return imagePtr;
}