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_image_put_normal (GdkDrawable *drawable,
43 static GList *image_list = NULL;
52 image = image_list->data;
53 gdk_image_destroy (image);
58 gdk_image_new_bitmap (GdkVisual *visual, gpointer data, gint w, gint h)
60 * Desc: create a new bitmap image
65 GdkImagePrivate *private;
67 BITMAPINFOHEADER bmiHeader;
74 int bpl = (w-1)/8 + 1;
75 int bpl32 = ((w-1)/32 + 1)*4;
77 private = g_new(GdkImagePrivate, 1);
78 image = (GdkImage *) private;
79 private->image_put = gdk_image_put_normal;
80 image->type = GDK_IMAGE_SHARED;
81 image->visual = visual;
85 xvisual = ((GdkVisualPrivate*) visual)->xvisual;
87 GDK_NOTE (MISC, g_print ("gdk_image_new_bitmap: %dx%d\n", w, h));
89 bmi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
90 bmi.bmiHeader.biWidth = w;
91 bmi.bmiHeader.biHeight = -h;
92 bmi.bmiHeader.biPlanes = 1;
93 bmi.bmiHeader.biBitCount = 1;
94 bmi.bmiHeader.biCompression = BI_RGB;
95 bmi.bmiHeader.biSizeImage = 0;
96 bmi.bmiHeader.biXPelsPerMeter =
97 bmi.bmiHeader.biYPelsPerMeter = 0;
98 bmi.bmiHeader.biClrUsed = 0;
99 bmi.bmiHeader.biClrImportant = 0;
101 bmi.u.bmiColors[0].rgbBlue =
102 bmi.u.bmiColors[0].rgbGreen =
103 bmi.u.bmiColors[0].rgbRed = 0x00;
104 bmi.u.bmiColors[0].rgbReserved = 0x00;
106 bmi.u.bmiColors[1].rgbBlue =
107 bmi.u.bmiColors[1].rgbGreen =
108 bmi.u.bmiColors[1].rgbRed = 0xFF;
109 bmi.u.bmiColors[1].rgbReserved = 0x00;
111 private->ximage = CreateDIBSection (gdk_DC, (BITMAPINFO *) &bmi,
112 DIB_RGB_COLORS, &bits, NULL, 0);
115 /* Win32 expects scanlines in DIBs to be 32 bit aligned */
117 for (i = 0; i < h; i++)
118 memmove (bits + i*bpl32, ((char *) data) + i*bpl, bpl);
121 memmove (bits, data, bpl*h);
124 image->byte_order = GDK_MSB_FIRST;
128 } /* gdk_image_new_bitmap() */
131 gdk_image_init (void)
136 gdk_image_new_with_depth (GdkImageType type,
143 GdkImagePrivate *private;
146 BITMAPINFOHEADER bmiHeader;
148 WORD bmiIndices[256];
150 RGBQUAD bmiColors[256];
156 if (type == GDK_IMAGE_FASTEST || type == GDK_IMAGE_NORMAL)
157 type = GDK_IMAGE_SHARED;
159 GDK_NOTE (MISC, g_print ("gdk_image_new_with_depth: %dx%dx%d %s\n",
160 width, height, depth,
161 (type == GDK_IMAGE_SHARED ? "shared" :
162 (type == GDK_IMAGE_SHARED_PIXMAP ? "shared_pixmap" :
165 private = g_new (GdkImagePrivate, 1);
166 image = (GdkImage*) private;
168 private->image_put = NULL;
171 image->visual = visual;
172 image->width = width;
173 image->height = height;
174 image->depth = depth;
176 xvisual = ((GdkVisualPrivate*) visual)->xvisual;
178 private->image_put = gdk_image_put_normal;
180 bmi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
181 bmi.bmiHeader.biWidth = width;
182 bmi.bmiHeader.biHeight = -height;
183 bmi.bmiHeader.biPlanes = 1;
185 bmi.bmiHeader.biBitCount = 16;
187 bmi.bmiHeader.biBitCount = depth;
190 bmi.bmiHeader.biCompression = BI_BITFIELDS;
193 bmi.bmiHeader.biCompression = BI_RGB;
194 bmi.bmiHeader.biSizeImage = 0;
195 bmi.bmiHeader.biXPelsPerMeter =
196 bmi.bmiHeader.biYPelsPerMeter = 0;
197 bmi.bmiHeader.biClrUsed = 0;
198 bmi.bmiHeader.biClrImportant = 0;
200 if (image->visual->type == GDK_VISUAL_PSEUDO_COLOR)
202 iUsage = DIB_PAL_COLORS;
203 for (i = 0; i < 256; i++)
204 bmi.u.bmiIndices[i] = i;
210 bmi.u.bmiColors[0].rgbBlue =
211 bmi.u.bmiColors[0].rgbGreen =
212 bmi.u.bmiColors[0].rgbRed = 0x00;
213 bmi.u.bmiColors[0].rgbReserved = 0x00;
215 bmi.u.bmiColors[1].rgbBlue =
216 bmi.u.bmiColors[1].rgbGreen =
217 bmi.u.bmiColors[1].rgbRed = 0xFF;
218 bmi.u.bmiColors[1].rgbReserved = 0x00;
222 else if (depth == 16)
224 bmi.u.bmiMasks[0] = visual->red_mask;
225 bmi.u.bmiMasks[1] = visual->green_mask;
226 bmi.u.bmiMasks[2] = visual->blue_mask;
229 iUsage = DIB_RGB_COLORS;
233 CreateDIBSection (gdk_DC, (BITMAPINFO *) &bmi, iUsage,
234 &image->mem, NULL, 0);
236 if (private->ximage == NULL)
238 g_warning ("gdk_image_new_with_depth: CreateDIBSection failed");
260 g_warning ("gdk_image_new_with_depth: depth = %d", depth);
261 g_assert_not_reached ();
263 image->byte_order = GDK_LSB_FIRST;
265 image->bpl = ((width-1)/32 + 1)*4;
267 image->bpl = ((width*image->bpp - 1)/4 + 1)*4;
269 GDK_NOTE (MISC, g_print ("... = %#x mem = %#x, bpl = %d\n",
270 private->ximage, image->mem, image->bpl));
276 gdk_image_new (GdkImageType type,
281 GdkVisualPrivate *visual_private = (GdkVisualPrivate *) visual;
282 return gdk_image_new_with_depth (type, visual, width, height,
283 visual_private->xvisual->bitspixel);
287 gdk_image_bitmap_new (GdkImageType type,
292 return gdk_image_new_with_depth (type, visual, width, height, 1);
296 gdk_image_get (GdkWindow *window,
303 GdkImagePrivate *private;
306 BITMAPINFOHEADER bmiHeader;
308 WORD bmiIndices[256];
310 RGBQUAD bmiColors[256];
313 HGDIOBJ oldbitmap1, oldbitmap2;
318 g_return_val_if_fail (window != NULL, NULL);
320 if (GDK_DRAWABLE_DESTROYED (window))
323 GDK_NOTE (MISC, g_print ("gdk_image_get: %#x %dx%d@+%d+%d\n",
324 GDK_DRAWABLE_XID (window), width, height, x, y));
326 private = g_new (GdkImagePrivate, 1);
327 image = (GdkImage*) private;
329 private->image_put = gdk_image_put_normal;
331 image->type = GDK_IMAGE_SHARED;
332 image->visual = gdk_window_get_visual (window);
333 image->width = width;
334 image->height = height;
336 /* This function is called both to blit from a window and from
339 if (GDK_DRAWABLE_TYPE (window) == GDK_DRAWABLE_PIXMAP)
341 if ((hdc = CreateCompatibleDC (NULL)) == NULL)
343 g_warning ("gdk_image_get: CreateCompatibleDC #1 failed");
347 if ((oldbitmap1 = SelectObject (hdc, GDK_DRAWABLE_XID (window))) == NULL)
349 g_warning ("gdk_image_get: SelectObject #1 failed");
354 GetObject (GDK_DRAWABLE_XID (window), sizeof (BITMAP), &bm);
356 g_print ("gdk_image_get: bmWidth = %d, bmHeight = %d, bmWidthBytes = %d, bmBitsPixel = %d\n",
357 bm.bmWidth, bm.bmHeight, bm.bmWidthBytes, bm.bmBitsPixel));
358 image->depth = bm.bmBitsPixel;
359 if (image->depth <= 8)
361 iUsage = DIB_PAL_COLORS;
362 for (i = 0; i < 256; i++)
363 bmi.u.bmiIndices[i] = i;
366 iUsage = DIB_RGB_COLORS;
370 if ((hdc = GetDC (GDK_DRAWABLE_XID (window))) == NULL)
372 g_warning ("gdk_image_get: GetDC failed");
376 image->depth = gdk_visual_get_system ()->depth;
377 if (image->visual->type == GDK_VISUAL_PSEUDO_COLOR)
379 iUsage = DIB_PAL_COLORS;
380 for (i = 0; i < 256; i++)
381 bmi.u.bmiIndices[i] = i;
384 iUsage = DIB_RGB_COLORS;
387 if ((memdc = CreateCompatibleDC (hdc)) == NULL)
389 g_warning ("gdk_image_get: CreateCompatibleDC #2 failed");
390 if (GDK_DRAWABLE_TYPE (window) == GDK_DRAWABLE_PIXMAP)
392 SelectObject (hdc, oldbitmap1);
397 ReleaseDC (GDK_DRAWABLE_XID (window), hdc);
403 bmi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
404 bmi.bmiHeader.biWidth = width;
405 bmi.bmiHeader.biHeight = -height;
406 bmi.bmiHeader.biPlanes = 1;
407 bmi.bmiHeader.biBitCount = image->depth;
408 if (image->depth == 16)
410 bmi.bmiHeader.biCompression = BI_BITFIELDS;
411 if (image->visual == NULL)
413 /* XXX ??? Is it always this if depth==16 and a pixmap? Guess so. */
414 bmi.u.bmiMasks[0] = 0xf800;
415 bmi.u.bmiMasks[1] = 0x07e0;
416 bmi.u.bmiMasks[2] = 0x001f;
420 bmi.u.bmiMasks[0] = image->visual->red_mask;
421 bmi.u.bmiMasks[1] = image->visual->green_mask;
422 bmi.u.bmiMasks[2] = image->visual->blue_mask;
426 bmi.bmiHeader.biCompression = BI_RGB;
427 bmi.bmiHeader.biSizeImage = 0;
428 bmi.bmiHeader.biXPelsPerMeter =
429 bmi.bmiHeader.biYPelsPerMeter = 0;
430 bmi.bmiHeader.biClrUsed = 0;
431 bmi.bmiHeader.biClrImportant = 0;
433 if ((private->ximage =
434 CreateDIBSection (hdc, (BITMAPINFO *) &bmi, iUsage,
435 &image->mem, NULL, 0)) == NULL)
437 g_warning ("gdk_image_get: CreateDIBSection failed");
439 if (GDK_DRAWABLE_TYPE (window) == GDK_DRAWABLE_PIXMAP)
441 SelectObject (hdc, oldbitmap1);
446 ReleaseDC (GDK_DRAWABLE_XID (window), hdc);
452 if ((oldbitmap2 = SelectObject (memdc, private->ximage)) == NULL)
454 g_warning ("gdk_image_get: SelectObject #2 failed");
455 DeleteObject (private->ximage);
457 if (GDK_DRAWABLE_TYPE (window) == GDK_DRAWABLE_PIXMAP)
459 SelectObject (hdc, oldbitmap1);
464 ReleaseDC (GDK_DRAWABLE_XID (window), hdc);
470 if (!BitBlt (memdc, 0, 0, width, height, hdc, x, y, SRCCOPY))
472 g_warning ("gdk_image_get: BitBlt failed");
473 SelectObject (memdc, oldbitmap2);
474 DeleteObject (private->ximage);
476 if (GDK_DRAWABLE_TYPE (window) == GDK_DRAWABLE_PIXMAP)
478 SelectObject (hdc, oldbitmap1);
483 ReleaseDC (GDK_DRAWABLE_XID (window), hdc);
489 if (SelectObject (memdc, oldbitmap2) == NULL)
490 g_warning ("gdk_image_get: SelectObject #3 failed");
492 if (!DeleteDC (memdc))
493 g_warning ("gdk_image_get: DeleteDC failed");
495 if (GDK_DRAWABLE_TYPE (window) == GDK_DRAWABLE_PIXMAP)
497 SelectObject (hdc, oldbitmap1);
502 ReleaseDC (GDK_DRAWABLE_XID (window), hdc);
505 switch (image->depth)
522 g_warning ("gdk_image_get: image->depth = %d", image->depth);
523 g_assert_not_reached ();
525 image->byte_order = GDK_LSB_FIRST;
526 if (image->depth == 1)
527 image->bpl = ((width - 1)/32 + 1)*4;
529 image->bpl = ((width*image->bpp - 1)/4 + 1)*4;
531 GDK_NOTE (MISC, g_print ("... = %#x mem = %#x, bpl = %d\n",
532 private->ximage, image->mem, image->bpl));
538 gdk_image_get_pixel (GdkImage *image,
543 GdkImagePrivate *private;
545 g_return_val_if_fail (image != NULL, 0);
547 private = (GdkImagePrivate *) image;
549 g_return_val_if_fail (x >= 0 && x < image->width
550 && y >= 0 && y < image->height, 0);
552 if (image->depth == 1)
553 pixel = (((char *) image->mem)[y * image->bpl + (x >> 3)] & (1 << (7 - (x & 0x7)))) != 0;
556 guchar *pixelp = (guchar *) image->mem + y * image->bpl + x * image->bpp;
564 /* Windows is always LSB, no need to check image->byte_order. */
566 pixel = pixelp[0] | (pixelp[1] << 8);
570 pixel = pixelp[0] | (pixelp[1] << 8) | (pixelp[2] << 16);
574 pixel = pixelp[0] | (pixelp[1] << 8) | (pixelp[2] << 16);
583 gdk_image_put_pixel (GdkImage *image,
588 GdkImagePrivate *private;
590 g_return_if_fail (image != NULL);
592 private = (GdkImagePrivate *) image;
594 g_return_if_fail (x >= 0 && x < image->width && y >= 0 && y < image->height);
596 if (image->depth == 1)
598 ((guchar *) image->mem)[y * image->bpl + (x >> 3)] |= (1 << (7 - (x & 0x7)));
600 ((guchar *) image->mem)[y * image->bpl + (x >> 3)] &= ~(1 << (7 - (x & 0x7)));
603 guchar *pixelp = (guchar *) image->mem + y * image->bpl + x * image->bpp;
605 /* Windows is always LSB, no need to check image->byte_order. */
611 pixelp[2] = ((pixel >> 16) & 0xFF);
613 pixelp[1] = ((pixel >> 8) & 0xFF);
615 pixelp[0] = (pixel & 0xFF);
621 gdk_image_destroy (GdkImage *image)
623 GdkImagePrivate *private;
625 g_return_if_fail (image != NULL);
627 private = (GdkImagePrivate*) image;
629 GDK_NOTE (MISC, g_print ("gdk_image_destroy: %#x%s\n",
631 (image->type == GDK_IMAGE_SHARED_PIXMAP ?
632 " (shared pixmap)" : "")));
636 case GDK_IMAGE_SHARED_PIXMAP:
637 break; /* The Windows bitmap has already been
638 * (or will be) deleted when freeing
639 * the corresponding pixmap.
642 case GDK_IMAGE_SHARED:
643 if (!DeleteObject (private->ximage))
644 g_warning ("gdk_image_destroy: DeleteObject failed");
648 g_assert_not_reached ();
655 gdk_image_put_normal (GdkDrawable *drawable,
665 GdkDrawablePrivate *drawable_private;
666 GdkImagePrivate *image_private;
667 GdkGCPrivate *gc_private;
669 GdkColormapPrivate *colormap_private;
671 g_return_if_fail (drawable != NULL);
672 g_return_if_fail (image != NULL);
673 g_return_if_fail (gc != NULL);
675 if (GDK_DRAWABLE_DESTROYED (drawable))
677 image_private = (GdkImagePrivate*) image;
678 drawable_private = (GdkDrawablePrivate*) drawable;
679 gc_private = (GdkGCPrivate*) gc;
681 /* The image can in fact be "shared", so don't test */
683 hdc = gdk_gc_predraw (drawable_private, gc_private);
684 colormap_private = (GdkColormapPrivate *) drawable_private->colormap;
685 if (colormap_private && colormap_private->xcolormap->rc_palette)
689 BITMAPINFOHEADER bmiHeader;
690 WORD bmiIndices[256];
692 static gboolean bmi_inited = FALSE;
697 for (i = 0; i < 256; i++)
698 bmi.bmiIndices[i] = i;
702 if (GetObject (image_private->ximage, sizeof (DIBSECTION),
703 &ds) != sizeof (DIBSECTION))
705 g_warning ("gdk_image_put_normal: GetObject failed");
708 g_print("xdest = %d, ydest = %d, xsrc = %d, ysrc = %d, width = %d, height = %d\n",
709 xdest, ydest, xsrc, ysrc, width, height);
710 g_print("bmWidth = %d, bmHeight = %d, bmBitsPixel = %d, bmBits = %p\n",
711 ds.dsBm.bmWidth, ds.dsBm.bmHeight, ds.dsBm.bmBitsPixel, ds.dsBm.bmBits);
712 g_print("biWidth = %d, biHeight = %d, biBitCount = %d, biClrUsed = %d\n",
713 ds.dsBmih.biWidth, ds.dsBmih.biHeight, ds.dsBmih.biBitCount, ds.dsBmih.biClrUsed);
715 bmi.bmiHeader = ds.dsBmih;
716 /* I have spent hours on getting the parameters to
717 * SetDIBitsToDevice right. I wonder what drugs the guys in
718 * Redmond were on when they designed this API.
720 if (SetDIBitsToDevice (hdc,
723 xsrc, (-ds.dsBmih.biHeight)-height-ysrc,
724 0, -ds.dsBmih.biHeight,
726 (CONST BITMAPINFO *) &bmi,
727 DIB_PAL_COLORS) == 0)
728 g_warning ("SetDIBitsToDevice failed");
735 if ((memdc = CreateCompatibleDC (hdc)) == NULL)
737 g_warning ("gdk_image_put_normal: CreateCompatibleDC failed");
738 gdk_gc_postdraw (drawable_private, gc_private);
742 if ((oldbitmap = SelectObject (memdc, image_private->ximage)) == NULL)
744 g_warning ("gdk_image_put_normal: SelectObject #1 failed");
745 gdk_gc_postdraw (drawable_private, gc_private);
748 if (!BitBlt (hdc, xdest, ydest, width, height,
749 memdc, xsrc, ysrc, SRCCOPY))
750 g_warning ("gdk_image_put_normal: BitBlt failed");
752 if (SelectObject (memdc, oldbitmap) == NULL)
753 g_warning ("gdk_image_put_normal: SelectObject #2 failed");
755 if (!DeleteDC (memdc))
756 g_warning ("gdk_image_put_normal: DeleteDC failed");
758 gdk_gc_postdraw (drawable_private, gc_private);