1 /* GDK - The GIMP Drawing Kit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
22 * file for a list of people on the GTK+ Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
29 #include "gdk.h" /* For gdk_error_trap_* / gdk_flush_* */
31 #include "gdkprivate.h"
34 static void gdk_win32_image_destroy (GdkImage *image);
35 static void gdk_image_put (GdkImage *image,
36 GdkDrawable *drawable,
45 static GdkImageClass image_class = {
46 gdk_win32_image_destroy,
50 static GList *image_list = NULL;
59 image = image_list->data;
60 gdk_win32_image_destroy (image);
65 gdk_image_new_bitmap (GdkVisual *visual, gpointer data, gint w, gint h)
67 * Desc: create a new bitmap image
72 GdkImagePrivateWin32 *private;
74 BITMAPINFOHEADER bmiHeader;
81 int bpl = (w-1)/8 + 1;
82 int bpl32 = ((w-1)/32 + 1)*4;
84 private = g_new (GdkImagePrivateWin32, 1);
85 image = (GdkImage *) private;
86 private->base.ref_count = 1;
87 private->base.klass = &image_class;
89 image->type = GDK_IMAGE_SHARED;
90 image->visual = visual;
94 xvisual = ((GdkVisualPrivate*) visual)->xvisual;
96 GDK_NOTE (MISC, g_print ("gdk_image_new_bitmap: %dx%d\n", w, h));
98 bmi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
99 bmi.bmiHeader.biWidth = w;
100 bmi.bmiHeader.biHeight = -h;
101 bmi.bmiHeader.biPlanes = 1;
102 bmi.bmiHeader.biBitCount = 1;
103 bmi.bmiHeader.biCompression = BI_RGB;
104 bmi.bmiHeader.biSizeImage = 0;
105 bmi.bmiHeader.biXPelsPerMeter =
106 bmi.bmiHeader.biYPelsPerMeter = 0;
107 bmi.bmiHeader.biClrUsed = 0;
108 bmi.bmiHeader.biClrImportant = 0;
110 bmi.u.bmiColors[0].rgbBlue =
111 bmi.u.bmiColors[0].rgbGreen =
112 bmi.u.bmiColors[0].rgbRed = 0x00;
113 bmi.u.bmiColors[0].rgbReserved = 0x00;
115 bmi.u.bmiColors[1].rgbBlue =
116 bmi.u.bmiColors[1].rgbGreen =
117 bmi.u.bmiColors[1].rgbRed = 0xFF;
118 bmi.u.bmiColors[1].rgbReserved = 0x00;
120 private->ximage = CreateDIBSection (gdk_DC, (BITMAPINFO *) &bmi,
121 DIB_RGB_COLORS, &bits, NULL, 0);
124 /* Win32 expects scanlines in DIBs to be 32 bit aligned */
126 for (i = 0; i < h; i++)
127 memmove (bits + i*bpl32, ((char *) data) + i*bpl, bpl);
130 memmove (bits, data, bpl*h);
133 image->byte_order = GDK_MSB_FIRST;
137 } /* gdk_image_new_bitmap() */
140 gdk_image_init (void)
145 gdk_image_new_with_depth (GdkImageType type,
152 GdkImagePrivateWin32 *private;
155 BITMAPINFOHEADER bmiHeader;
157 WORD bmiIndices[256];
159 RGBQUAD bmiColors[256];
165 if (type == GDK_IMAGE_FASTEST || type == GDK_IMAGE_NORMAL)
166 type = GDK_IMAGE_SHARED;
168 GDK_NOTE (MISC, g_print ("gdk_image_new_with_depth: %dx%dx%d %s\n",
169 width, height, depth,
170 (type == GDK_IMAGE_SHARED ? "shared" :
171 (type == GDK_IMAGE_SHARED_PIXMAP ? "shared_pixmap" :
174 private = g_new (GdkImagePrivateWin32, 1);
175 image = (GdkImage *) private;
177 private->base.ref_count = 1;
178 private->base.klass = &image_class;
181 image->visual = visual;
182 image->width = width;
183 image->height = height;
184 image->depth = depth;
186 xvisual = ((GdkVisualPrivate*) visual)->xvisual;
188 bmi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
189 bmi.bmiHeader.biWidth = width;
190 bmi.bmiHeader.biHeight = -height;
191 bmi.bmiHeader.biPlanes = 1;
193 bmi.bmiHeader.biBitCount = 16;
195 bmi.bmiHeader.biBitCount = depth;
198 bmi.bmiHeader.biCompression = BI_BITFIELDS;
201 bmi.bmiHeader.biCompression = BI_RGB;
202 bmi.bmiHeader.biSizeImage = 0;
203 bmi.bmiHeader.biXPelsPerMeter =
204 bmi.bmiHeader.biYPelsPerMeter = 0;
205 bmi.bmiHeader.biClrUsed = 0;
206 bmi.bmiHeader.biClrImportant = 0;
208 if (image->visual->type == GDK_VISUAL_PSEUDO_COLOR)
210 iUsage = DIB_PAL_COLORS;
211 for (i = 0; i < 256; i++)
212 bmi.u.bmiIndices[i] = i;
218 bmi.u.bmiColors[0].rgbBlue =
219 bmi.u.bmiColors[0].rgbGreen =
220 bmi.u.bmiColors[0].rgbRed = 0x00;
221 bmi.u.bmiColors[0].rgbReserved = 0x00;
223 bmi.u.bmiColors[1].rgbBlue =
224 bmi.u.bmiColors[1].rgbGreen =
225 bmi.u.bmiColors[1].rgbRed = 0xFF;
226 bmi.u.bmiColors[1].rgbReserved = 0x00;
230 else if (depth == 16)
232 bmi.u.bmiMasks[0] = visual->red_mask;
233 bmi.u.bmiMasks[1] = visual->green_mask;
234 bmi.u.bmiMasks[2] = visual->blue_mask;
237 iUsage = DIB_RGB_COLORS;
241 CreateDIBSection (gdk_DC, (BITMAPINFO *) &bmi, iUsage,
242 &image->mem, NULL, 0);
244 if (private->ximage == NULL)
246 g_warning ("gdk_image_new_with_depth: CreateDIBSection failed");
268 g_warning ("gdk_image_new_with_depth: depth = %d", depth);
269 g_assert_not_reached ();
271 image->byte_order = GDK_LSB_FIRST;
273 image->bpl = ((width-1)/32 + 1)*4;
275 image->bpl = ((width*image->bpp - 1)/4 + 1)*4;
277 GDK_NOTE (MISC, g_print ("... = %#x mem = %#x, bpl = %d\n",
278 private->ximage, image->mem, image->bpl));
284 gdk_image_new (GdkImageType type,
289 GdkVisualPrivate *visual_private = (GdkVisualPrivate *) visual;
290 return gdk_image_new_with_depth (type, visual, width, height,
291 visual_private->xvisual->bitspixel);
295 gdk_image_bitmap_new (GdkImageType type,
300 return gdk_image_new_with_depth (type, visual, width, height, 1);
304 gdk_image_get (GdkWindow *window,
311 GdkImagePrivateWin32 *private;
314 BITMAPINFOHEADER bmiHeader;
316 WORD bmiIndices[256];
318 RGBQUAD bmiColors[256];
321 HGDIOBJ oldbitmap1, oldbitmap2;
326 g_return_val_if_fail (window != NULL, NULL);
328 if (GDK_DRAWABLE_DESTROYED (window))
331 GDK_NOTE (MISC, g_print ("gdk_image_get: %#x %dx%d@+%d+%d\n",
332 GDK_DRAWABLE_XID (window), width, height, x, y));
334 private = g_new (GdkImagePrivateWin32, 1);
335 image = (GdkImage*) private;
337 private->base.ref_count = 1;
338 private->base.klass = &image_class;
340 image->type = GDK_IMAGE_SHARED;
341 image->visual = gdk_window_get_visual (window);
342 image->width = width;
343 image->height = height;
345 /* This function is called both to blit from a window and from
348 if (GDK_DRAWABLE_TYPE (window) == GDK_DRAWABLE_PIXMAP)
350 if ((hdc = CreateCompatibleDC (NULL)) == NULL)
352 g_warning ("gdk_image_get: CreateCompatibleDC #1 failed");
356 if ((oldbitmap1 = SelectObject (hdc, GDK_DRAWABLE_XID (window))) == NULL)
358 g_warning ("gdk_image_get: SelectObject #1 failed");
363 GetObject (GDK_DRAWABLE_XID (window), sizeof (BITMAP), &bm);
365 g_print ("gdk_image_get: bmWidth = %d, bmHeight = %d, bmWidthBytes = %d, bmBitsPixel = %d\n",
366 bm.bmWidth, bm.bmHeight, bm.bmWidthBytes, bm.bmBitsPixel));
367 image->depth = bm.bmBitsPixel;
368 if (image->depth <= 8)
370 iUsage = DIB_PAL_COLORS;
371 for (i = 0; i < 256; i++)
372 bmi.u.bmiIndices[i] = i;
375 iUsage = DIB_RGB_COLORS;
379 if ((hdc = GetDC (GDK_DRAWABLE_XID (window))) == NULL)
381 g_warning ("gdk_image_get: GetDC failed");
385 image->depth = gdk_visual_get_system ()->depth;
386 if (image->visual->type == GDK_VISUAL_PSEUDO_COLOR)
388 iUsage = DIB_PAL_COLORS;
389 for (i = 0; i < 256; i++)
390 bmi.u.bmiIndices[i] = i;
393 iUsage = DIB_RGB_COLORS;
396 if ((memdc = CreateCompatibleDC (hdc)) == NULL)
398 g_warning ("gdk_image_get: CreateCompatibleDC #2 failed");
399 if (GDK_DRAWABLE_TYPE (window) == GDK_DRAWABLE_PIXMAP)
401 SelectObject (hdc, oldbitmap1);
406 ReleaseDC (GDK_DRAWABLE_XID (window), hdc);
412 bmi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
413 bmi.bmiHeader.biWidth = width;
414 bmi.bmiHeader.biHeight = -height;
415 bmi.bmiHeader.biPlanes = 1;
416 bmi.bmiHeader.biBitCount = image->depth;
417 if (image->depth == 16)
419 bmi.bmiHeader.biCompression = BI_BITFIELDS;
420 if (image->visual == NULL)
422 /* XXX ??? Is it always this if depth==16 and a pixmap? Guess so. */
423 bmi.u.bmiMasks[0] = 0xf800;
424 bmi.u.bmiMasks[1] = 0x07e0;
425 bmi.u.bmiMasks[2] = 0x001f;
429 bmi.u.bmiMasks[0] = image->visual->red_mask;
430 bmi.u.bmiMasks[1] = image->visual->green_mask;
431 bmi.u.bmiMasks[2] = image->visual->blue_mask;
435 bmi.bmiHeader.biCompression = BI_RGB;
436 bmi.bmiHeader.biSizeImage = 0;
437 bmi.bmiHeader.biXPelsPerMeter =
438 bmi.bmiHeader.biYPelsPerMeter = 0;
439 bmi.bmiHeader.biClrUsed = 0;
440 bmi.bmiHeader.biClrImportant = 0;
442 if ((private->ximage =
443 CreateDIBSection (hdc, (BITMAPINFO *) &bmi, iUsage,
444 &image->mem, NULL, 0)) == NULL)
446 g_warning ("gdk_image_get: CreateDIBSection failed");
448 if (GDK_DRAWABLE_TYPE (window) == GDK_DRAWABLE_PIXMAP)
450 SelectObject (hdc, oldbitmap1);
455 ReleaseDC (GDK_DRAWABLE_XID (window), hdc);
461 if ((oldbitmap2 = SelectObject (memdc, private->ximage)) == NULL)
463 g_warning ("gdk_image_get: SelectObject #2 failed");
464 DeleteObject (private->ximage);
466 if (GDK_DRAWABLE_TYPE (window) == GDK_DRAWABLE_PIXMAP)
468 SelectObject (hdc, oldbitmap1);
473 ReleaseDC (GDK_DRAWABLE_XID (window), hdc);
479 if (!BitBlt (memdc, 0, 0, width, height, hdc, x, y, SRCCOPY))
481 g_warning ("gdk_image_get: BitBlt failed");
482 SelectObject (memdc, oldbitmap2);
483 DeleteObject (private->ximage);
485 if (GDK_DRAWABLE_TYPE (window) == GDK_DRAWABLE_PIXMAP)
487 SelectObject (hdc, oldbitmap1);
492 ReleaseDC (GDK_DRAWABLE_XID (window), hdc);
498 if (SelectObject (memdc, oldbitmap2) == NULL)
499 g_warning ("gdk_image_get: SelectObject #3 failed");
501 if (!DeleteDC (memdc))
502 g_warning ("gdk_image_get: DeleteDC failed");
504 if (GDK_DRAWABLE_TYPE (window) == GDK_DRAWABLE_PIXMAP)
506 SelectObject (hdc, oldbitmap1);
511 ReleaseDC (GDK_DRAWABLE_XID (window), hdc);
514 switch (image->depth)
531 g_warning ("gdk_image_get: image->depth = %d", image->depth);
532 g_assert_not_reached ();
534 image->byte_order = GDK_LSB_FIRST;
535 if (image->depth == 1)
536 image->bpl = ((width - 1)/32 + 1)*4;
538 image->bpl = ((width*image->bpp - 1)/4 + 1)*4;
540 GDK_NOTE (MISC, g_print ("... = %#x mem = %#x, bpl = %d\n",
541 private->ximage, image->mem, image->bpl));
547 gdk_image_get_pixel (GdkImage *image,
553 g_return_val_if_fail (image != NULL, 0);
555 g_return_val_if_fail (x >= 0 && x < image->width
556 && y >= 0 && y < image->height, 0);
558 if (image->depth == 1)
559 pixel = (((char *) image->mem)[y * image->bpl + (x >> 3)] & (1 << (7 - (x & 0x7)))) != 0;
562 guchar *pixelp = (guchar *) image->mem + y * image->bpl + x * image->bpp;
570 /* Windows is always LSB, no need to check image->byte_order. */
572 pixel = pixelp[0] | (pixelp[1] << 8);
576 pixel = pixelp[0] | (pixelp[1] << 8) | (pixelp[2] << 16);
580 pixel = pixelp[0] | (pixelp[1] << 8) | (pixelp[2] << 16);
589 gdk_image_put_pixel (GdkImage *image,
594 g_return_if_fail (image != NULL);
596 g_return_if_fail (x >= 0 && x < image->width && y >= 0 && y < image->height);
598 if (image->depth == 1)
600 ((guchar *) image->mem)[y * image->bpl + (x >> 3)] |= (1 << (7 - (x & 0x7)));
602 ((guchar *) image->mem)[y * image->bpl + (x >> 3)] &= ~(1 << (7 - (x & 0x7)));
605 guchar *pixelp = (guchar *) image->mem + y * image->bpl + x * image->bpp;
607 /* Windows is always LSB, no need to check image->byte_order. */
613 pixelp[2] = ((pixel >> 16) & 0xFF);
615 pixelp[1] = ((pixel >> 8) & 0xFF);
617 pixelp[0] = (pixel & 0xFF);
623 gdk_win32_image_destroy (GdkImage *image)
625 GdkImagePrivateWin32 *private;
627 g_return_if_fail (image != NULL);
629 private = (GdkImagePrivateWin32 *) image;
631 GDK_NOTE (MISC, g_print ("gdk_win32_image_destroy: %#x%s\n",
633 (image->type == GDK_IMAGE_SHARED_PIXMAP ?
634 " (shared pixmap)" : "")));
638 case GDK_IMAGE_SHARED_PIXMAP:
639 break; /* The Windows bitmap has already been
640 * (or will be) deleted when freeing
641 * the corresponding pixmap.
644 case GDK_IMAGE_SHARED:
645 if (!DeleteObject (private->ximage))
646 g_warning ("gdk_win32_image_destroy: DeleteObject failed");
650 g_assert_not_reached ();
657 gdk_image_put (GdkImage *image,
658 GdkDrawable *drawable,
667 GdkDrawablePrivate *drawable_private;
668 GdkImagePrivateWin32 *image_private;
669 GdkGCPrivate *gc_private;
671 GdkColormapPrivateWin32 *colormap_private;
673 g_return_if_fail (drawable != NULL);
674 g_return_if_fail (image != NULL);
675 g_return_if_fail (gc != NULL);
677 if (GDK_DRAWABLE_DESTROYED (drawable))
679 image_private = (GdkImagePrivateWin32 *) image;
680 drawable_private = (GdkDrawablePrivate *) drawable;
681 gc_private = (GdkGCPrivate *) gc;
683 /* The image can in fact be "shared", so don't test */
685 hdc = gdk_gc_predraw (drawable, gc_private);
686 colormap_private = (GdkColormapPrivateWin32 *) drawable_private->colormap;
687 if (colormap_private && colormap_private->xcolormap->rc_palette)
691 BITMAPINFOHEADER bmiHeader;
692 WORD bmiIndices[256];
694 static gboolean bmi_inited = FALSE;
699 for (i = 0; i < 256; i++)
700 bmi.bmiIndices[i] = i;
704 if (GetObject (image_private->ximage, sizeof (DIBSECTION),
705 &ds) != sizeof (DIBSECTION))
707 g_warning ("gdk_image_put: GetObject failed");
710 g_print("xdest = %d, ydest = %d, xsrc = %d, ysrc = %d, width = %d, height = %d\n",
711 xdest, ydest, xsrc, ysrc, width, height);
712 g_print("bmWidth = %d, bmHeight = %d, bmBitsPixel = %d, bmBits = %p\n",
713 ds.dsBm.bmWidth, ds.dsBm.bmHeight, ds.dsBm.bmBitsPixel, ds.dsBm.bmBits);
714 g_print("biWidth = %d, biHeight = %d, biBitCount = %d, biClrUsed = %d\n",
715 ds.dsBmih.biWidth, ds.dsBmih.biHeight, ds.dsBmih.biBitCount, ds.dsBmih.biClrUsed);
717 bmi.bmiHeader = ds.dsBmih;
718 /* I have spent hours on getting the parameters to
719 * SetDIBitsToDevice right. I wonder what drugs the guys in
720 * Redmond were on when they designed this API.
722 if (SetDIBitsToDevice (hdc,
725 xsrc, (-ds.dsBmih.biHeight)-height-ysrc,
726 0, -ds.dsBmih.biHeight,
728 (CONST BITMAPINFO *) &bmi,
729 DIB_PAL_COLORS) == 0)
730 g_warning ("SetDIBitsToDevice failed");
737 if ((memdc = CreateCompatibleDC (hdc)) == NULL)
739 g_warning ("gdk_image_put: CreateCompatibleDC failed");
740 gdk_gc_postdraw (drawable, gc_private);
744 if ((oldbitmap = SelectObject (memdc, image_private->ximage)) == NULL)
746 g_warning ("gdk_image_put: SelectObject #1 failed");
747 gdk_gc_postdraw (drawable, gc_private);
750 if (!BitBlt (hdc, xdest, ydest, width, height,
751 memdc, xsrc, ysrc, SRCCOPY))
752 g_warning ("gdk_image_put: BitBlt failed");
754 if (SelectObject (memdc, oldbitmap) == NULL)
755 g_warning ("gdk_image_put_normal: SelectObject #2 failed");
757 if (!DeleteDC (memdc))
758 g_warning ("gdk_image_put: DeleteDC failed");
760 gdk_gc_postdraw (drawable, gc_private);