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/.
30 #include "gdkprivate.h"
32 static void gdk_image_put_normal (GdkDrawable *drawable,
41 static GList *image_list = NULL;
50 image = image_list->data;
51 gdk_image_destroy (image);
56 gdk_image_new_bitmap (GdkVisual *visual, gpointer data, gint w, gint h)
58 * Desc: create a new bitmap image
63 GdkImagePrivate *private;
65 BITMAPINFOHEADER bmiHeader;
72 int bpl = (w-1)/8 + 1;
73 int bpl32 = ((w-1)/32 + 1)*4;
75 private = g_new(GdkImagePrivate, 1);
76 image = (GdkImage *) private;
77 private->image_put = gdk_image_put_normal;
78 image->type = GDK_IMAGE_NORMAL;
79 image->visual = visual;
83 xvisual = ((GdkVisualPrivate*) visual)->xvisual;
85 GDK_NOTE (MISC, g_print ("gdk_image_new_bitmap: %dx%d\n", w, h));
87 bmi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
88 bmi.bmiHeader.biWidth = w;
89 bmi.bmiHeader.biHeight = -h;
90 bmi.bmiHeader.biPlanes = 1;
91 bmi.bmiHeader.biBitCount = 1;
92 bmi.bmiHeader.biCompression = BI_RGB;
93 bmi.bmiHeader.biSizeImage = 0;
94 bmi.bmiHeader.biXPelsPerMeter =
95 bmi.bmiHeader.biYPelsPerMeter = 0;
96 bmi.bmiHeader.biClrUsed = 0;
97 bmi.bmiHeader.biClrImportant = 0;
99 bmi.u.bmiColors[0].rgbBlue =
100 bmi.u.bmiColors[0].rgbGreen =
101 bmi.u.bmiColors[0].rgbRed = 0x00;
102 bmi.u.bmiColors[0].rgbReserved = 0x00;
104 bmi.u.bmiColors[1].rgbBlue =
105 bmi.u.bmiColors[1].rgbGreen =
106 bmi.u.bmiColors[1].rgbRed = 0xFF;
107 bmi.u.bmiColors[1].rgbReserved = 0x00;
109 private->ximage = CreateDIBSection (gdk_DC, (BITMAPINFO *) &bmi,
110 DIB_RGB_COLORS, &bits, NULL, 0);
113 /* Win32 expects scanlines in DIBs to be 32 bit aligned */
115 for (i = 0; i < h; i++)
116 memmove (bits + i*bpl32, ((char *) data) + i*bpl, bpl);
119 memmove (bits, data, bpl*h);
122 image->byte_order = GDK_MSB_FIRST;
126 } /* gdk_image_new_bitmap() */
129 gdk_image_init (void)
134 gdk_image_new_with_depth (GdkImageType type,
141 GdkImagePrivate *private;
144 BITMAPINFOHEADER bmiHeader;
146 WORD bmiIndices[256];
148 RGBQUAD bmiColors[256];
154 GDK_NOTE (MISC, g_print ("gdk_image_new_with_depth: %dx%dx%d\n",
155 width, height, depth));
159 case GDK_IMAGE_FASTEST:
160 image = gdk_image_new_with_depth (GDK_IMAGE_SHARED, visual,
161 width, height, depth);
164 image = gdk_image_new_with_depth (GDK_IMAGE_NORMAL, visual,
165 width, height, depth);
169 private = g_new (GdkImagePrivate, 1);
170 image = (GdkImage*) private;
172 private->image_put = NULL;
175 image->visual = visual;
176 image->width = width;
177 image->height = height;
178 image->depth = depth;
180 xvisual = ((GdkVisualPrivate*) visual)->xvisual;
184 case GDK_IMAGE_SHARED:
185 case GDK_IMAGE_SHARED_PIXMAP:
186 /* Fall through, Windows images are always shared */
187 case GDK_IMAGE_NORMAL:
188 private->image_put = gdk_image_put_normal;
190 bmi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
191 bmi.bmiHeader.biWidth = width;
192 bmi.bmiHeader.biHeight = -height;
193 bmi.bmiHeader.biPlanes = 1;
195 bmi.bmiHeader.biBitCount = 16;
197 bmi.bmiHeader.biBitCount = depth;
200 bmi.bmiHeader.biCompression = BI_BITFIELDS;
203 bmi.bmiHeader.biCompression = BI_RGB;
204 bmi.bmiHeader.biSizeImage = 0;
205 bmi.bmiHeader.biXPelsPerMeter =
206 bmi.bmiHeader.biYPelsPerMeter = 0;
207 bmi.bmiHeader.biClrUsed = 0;
208 bmi.bmiHeader.biClrImportant = 0;
210 if (image->visual->type == GDK_VISUAL_PSEUDO_COLOR)
212 iUsage = DIB_PAL_COLORS;
213 for (i = 0; i < 256; i++)
214 bmi.u.bmiIndices[i] = i;
220 bmi.u.bmiColors[0].rgbBlue =
221 bmi.u.bmiColors[0].rgbGreen =
222 bmi.u.bmiColors[0].rgbRed = 0x00;
223 bmi.u.bmiColors[0].rgbReserved = 0x00;
225 bmi.u.bmiColors[1].rgbBlue =
226 bmi.u.bmiColors[1].rgbGreen =
227 bmi.u.bmiColors[1].rgbRed = 0xFF;
228 bmi.u.bmiColors[1].rgbReserved = 0x00;
232 else if (depth == 16)
234 bmi.u.bmiMasks[0] = visual->red_mask;
235 bmi.u.bmiMasks[1] = visual->green_mask;
236 bmi.u.bmiMasks[2] = visual->blue_mask;
239 iUsage = DIB_RGB_COLORS;
243 CreateDIBSection (gdk_DC, (BITMAPINFO *) &bmi, iUsage,
244 &image->mem, NULL, 0);
246 if (private->ximage == NULL)
248 g_warning ("gdk_image_new_with_depth: CreateDIBSection failed");
270 g_warning ("gdk_image_new_with_depth: depth = %d", depth);
271 g_assert_not_reached ();
273 image->byte_order = GDK_LSB_FIRST;
275 image->bpl = ((width-1)/32 + 1)*4;
277 image->bpl = ((width*image->bpp - 1)/4 + 1)*4;
279 GDK_NOTE (MISC, g_print ("... = %#x mem = %#x, bpl = %d\n",
280 private->ximage, image->mem, image->bpl));
284 case GDK_IMAGE_FASTEST:
285 g_assert_not_reached ();
295 gdk_image_new (GdkImageType type,
300 return gdk_image_new_with_depth (type, visual, width, height, visual->depth);
304 gdk_image_bitmap_new (GdkImageType type,
309 return gdk_image_new_with_depth (type, visual, width, height, 1);
313 gdk_image_get (GdkWindow *window,
320 GdkImagePrivate *private;
321 GdkWindowPrivate *win_private;
324 BITMAPINFOHEADER bmiHeader;
326 WORD bmiIndices[256];
328 RGBQUAD bmiColors[256];
331 HGDIOBJ oldbitmap1, oldbitmap2;
336 g_return_val_if_fail (window != NULL, NULL);
338 win_private = (GdkWindowPrivate *) window;
339 if (win_private->destroyed)
342 GDK_NOTE (MISC, g_print ("gdk_image_get: %#x %dx%d@+%d+%d\n",
343 win_private->xwindow, width, height, x, y));
345 private = g_new (GdkImagePrivate, 1);
346 image = (GdkImage*) private;
348 private->image_put = gdk_image_put_normal;
350 image->type = GDK_IMAGE_NORMAL;
351 image->visual = gdk_window_get_visual (window);
352 image->width = width;
353 image->height = height;
355 /* This function is called both to blit from a window and from
358 if (win_private->window_type == GDK_WINDOW_PIXMAP)
360 if ((hdc = CreateCompatibleDC (NULL)) == NULL)
362 g_warning ("gdk_image_get: CreateCompatibleDC #1 failed");
366 if ((oldbitmap1 = SelectObject (hdc, win_private->xwindow)) == NULL)
368 g_warning ("gdk_image_get: SelectObject #1 failed");
373 GetObject (win_private->xwindow, sizeof (BITMAP), &bm);
375 g_print ("gdk_image_get: bmWidth = %d, bmHeight = %d, bmWidthBytes = %d, bmBitsPixel = %d\n",
376 bm.bmWidth, bm.bmHeight, bm.bmWidthBytes, bm.bmBitsPixel));
377 image->depth = bm.bmBitsPixel;
378 if (image->depth <= 8)
380 iUsage = DIB_PAL_COLORS;
381 for (i = 0; i < 256; i++)
382 bmi.u.bmiIndices[i] = i;
385 iUsage = DIB_RGB_COLORS;
389 if ((hdc = GetDC (win_private->xwindow)) == NULL)
391 g_warning ("gdk_image_get: GetDC failed");
395 image->depth = gdk_visual_get_system ()->depth;
396 if (image->visual->type == GDK_VISUAL_PSEUDO_COLOR)
398 iUsage = DIB_PAL_COLORS;
399 for (i = 0; i < 256; i++)
400 bmi.u.bmiIndices[i] = i;
403 iUsage = DIB_RGB_COLORS;
406 if ((memdc = CreateCompatibleDC (hdc)) == NULL)
408 g_warning ("gdk_image_get: CreateCompatibleDC #2 failed");
409 if (win_private->window_type == GDK_WINDOW_PIXMAP)
411 SelectObject (hdc, oldbitmap1);
416 ReleaseDC (win_private->xwindow, hdc);
422 bmi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
423 bmi.bmiHeader.biWidth = width;
424 bmi.bmiHeader.biHeight = -height;
425 bmi.bmiHeader.biPlanes = 1;
426 bmi.bmiHeader.biBitCount = image->depth;
427 if (image->depth == 16)
429 bmi.bmiHeader.biCompression = BI_BITFIELDS;
430 if (image->visual == NULL)
432 /* XXX ??? Is it always this if depth==16 and a pixmap? Guess so. */
433 bmi.u.bmiMasks[0] = 0xf800;
434 bmi.u.bmiMasks[1] = 0x07e0;
435 bmi.u.bmiMasks[2] = 0x001f;
439 bmi.u.bmiMasks[0] = image->visual->red_mask;
440 bmi.u.bmiMasks[1] = image->visual->green_mask;
441 bmi.u.bmiMasks[2] = image->visual->blue_mask;
445 bmi.bmiHeader.biCompression = BI_RGB;
446 bmi.bmiHeader.biSizeImage = 0;
447 bmi.bmiHeader.biXPelsPerMeter =
448 bmi.bmiHeader.biYPelsPerMeter = 0;
449 bmi.bmiHeader.biClrUsed = 0;
450 bmi.bmiHeader.biClrImportant = 0;
452 if ((private->ximage =
453 CreateDIBSection (hdc, (BITMAPINFO *) &bmi, iUsage,
454 &image->mem, NULL, 0)) == NULL)
456 g_warning ("gdk_image_get: CreateDIBSection failed");
458 if (win_private->window_type == GDK_WINDOW_PIXMAP)
460 SelectObject (hdc, oldbitmap1);
465 ReleaseDC (win_private->xwindow, hdc);
471 if ((oldbitmap2 = SelectObject (memdc, private->ximage)) == NULL)
473 g_warning ("gdk_image_get: SelectObject #2 failed");
474 DeleteObject (private->ximage);
476 if (win_private->window_type == GDK_WINDOW_PIXMAP)
478 SelectObject (hdc, oldbitmap1);
483 ReleaseDC (win_private->xwindow, hdc);
489 if (!BitBlt (memdc, 0, 0, width, height, hdc, x, y, SRCCOPY))
491 g_warning ("gdk_image_get: BitBlt failed");
492 SelectObject (memdc, oldbitmap2);
493 DeleteObject (private->ximage);
495 if (win_private->window_type == GDK_WINDOW_PIXMAP)
497 SelectObject (hdc, oldbitmap1);
502 ReleaseDC (win_private->xwindow, hdc);
508 if (SelectObject (memdc, oldbitmap2) == NULL)
509 g_warning ("gdk_image_get: SelectObject #3 failed");
511 if (!DeleteDC (memdc))
512 g_warning ("gdk_image_get: DeleteDC failed");
514 if (win_private->window_type == GDK_WINDOW_PIXMAP)
516 SelectObject (hdc, oldbitmap1);
521 ReleaseDC (win_private->xwindow, hdc);
524 switch (image->depth)
541 g_warning ("gdk_image_get: image->depth = %d", image->depth);
542 g_assert_not_reached ();
544 image->byte_order = GDK_LSB_FIRST;
545 if (image->depth == 1)
546 image->bpl = (width - 1)/8 + 1;
548 image->bpl = ((width*image->bpp - 1)/4 + 1)*4;
550 GDK_NOTE (MISC, g_print ("... = %#x mem = %#x, bpl = %d\n",
551 private->ximage, image->mem, image->bpl));
557 gdk_image_get_pixel (GdkImage *image,
562 GdkImagePrivate *private;
564 g_return_val_if_fail (image != NULL, 0);
566 private = (GdkImagePrivate *) image;
568 g_return_val_if_fail (x >= 0 && x < image->width
569 && y >= 0 && y < image->height, 0);
571 if (image->depth == 1)
572 pixel = (((char *) image->mem)[y * image->bpl + (x >> 3)] & (1 << (7 - (x & 0x7)))) != 0;
575 guchar *pixelp = (guchar *) image->mem + y * image->bpl + x * image->bpp;
583 /* Windows is always LSB, no need to check image->byte_order. */
585 pixel = pixelp[0] | (pixelp[1] << 8);
589 pixel = pixelp[0] | (pixelp[1] << 8) | (pixelp[2] << 16);
593 pixel = pixelp[0] | (pixelp[1] << 8) | (pixelp[2] << 16);
602 gdk_image_put_pixel (GdkImage *image,
607 GdkImagePrivate *private;
609 g_return_if_fail (image != NULL);
611 private = (GdkImagePrivate *) image;
613 g_return_if_fail (x >= 0 && x < image->width && y >= 0 && y < image->height);
615 if (image->depth == 1)
617 ((guchar *) image->mem)[y * image->bpl + (x >> 3)] |= (1 << (7 - (x & 0x7)));
619 ((guchar *) image->mem)[y * image->bpl + (x >> 3)] &= ~(1 << (7 - (x & 0x7)));
622 guchar *pixelp = (guchar *) image->mem + y * image->bpl + x * image->bpp;
624 /* Windows is always LSB, no need to check image->byte_order. */
630 pixelp[2] = ((pixel >> 16) & 0xFF);
632 pixelp[1] = ((pixel >> 8) & 0xFF);
634 pixelp[0] = (pixel & 0xFF);
640 gdk_image_destroy (GdkImage *image)
642 GdkImagePrivate *private;
644 g_return_if_fail (image != NULL);
646 private = (GdkImagePrivate*) image;
648 GDK_NOTE (MISC, g_print ("gdk_image_destroy: %#x%s\n",
650 (image->type == GDK_IMAGE_SHARED_PIXMAP ?
651 " (shared pixmap)" : "")));
655 case GDK_IMAGE_NORMAL:
656 case GDK_IMAGE_SHARED_PIXMAP:
657 break; /* The Windows bitmap has already been
658 * (or will be) deleted when freeing
659 * the corresponding pixmap.
662 case GDK_IMAGE_SHARED: /* All images are shared in Windows */
663 DeleteObject (private->ximage);
666 case GDK_IMAGE_FASTEST:
667 g_assert_not_reached ();
674 gdk_image_put_normal (GdkDrawable *drawable,
684 GdkWindowPrivate *drawable_private;
685 GdkImagePrivate *image_private;
686 GdkGCPrivate *gc_private;
688 GdkColormapPrivate *colormap_private;
690 g_return_if_fail (drawable != NULL);
691 g_return_if_fail (image != NULL);
692 g_return_if_fail (gc != NULL);
694 drawable_private = (GdkWindowPrivate*) drawable;
695 if (drawable_private->destroyed)
697 image_private = (GdkImagePrivate*) image;
698 gc_private = (GdkGCPrivate*) gc;
700 /* The image can in fact be "shared", so don't test */
702 hdc = gdk_gc_predraw (drawable_private, gc_private);
703 colormap_private = (GdkColormapPrivate *) drawable_private->colormap;
704 if (colormap_private && colormap_private->xcolormap->rc_palette)
708 BITMAPINFOHEADER bmiHeader;
709 WORD bmiIndices[256];
711 static gboolean bmi_inited = FALSE;
716 for (i = 0; i < 256; i++)
717 bmi.bmiIndices[i] = i;
721 if (GetObject (image_private->ximage, sizeof (DIBSECTION),
722 &ds) != sizeof (DIBSECTION))
724 g_warning ("gdk_image_put_normal: GetObject failed");
727 g_print("xdest = %d, ydest = %d, xsrc = %d, ysrc = %d, width = %d, height = %d\n",
728 xdest, ydest, xsrc, ysrc, width, height);
729 g_print("bmWidth = %d, bmHeight = %d, bmBitsPixel = %d, bmBits = %p\n",
730 ds.dsBm.bmWidth, ds.dsBm.bmHeight, ds.dsBm.bmBitsPixel, ds.dsBm.bmBits);
731 g_print("biWidth = %d, biHeight = %d, biBitCount = %d, biClrUsed = %d\n",
732 ds.dsBmih.biWidth, ds.dsBmih.biHeight, ds.dsBmih.biBitCount, ds.dsBmih.biClrUsed);
734 bmi.bmiHeader = ds.dsBmih;
735 /* I have spent hours on getting the parameters to
736 * SetDIBitsToDevice right. I wonder what drugs the guys in
737 * Redmond were on when they designed this API.
739 if (SetDIBitsToDevice (hdc,
742 xsrc, (-ds.dsBmih.biHeight)-height-ysrc,
743 0, -ds.dsBmih.biHeight,
745 (CONST BITMAPINFO *) &bmi,
746 DIB_PAL_COLORS) == 0)
747 g_warning ("SetDIBitsToDevice failed");
754 if ((memdc = CreateCompatibleDC (hdc)) == NULL)
756 g_warning ("gdk_image_put_normal: CreateCompatibleDC failed");
757 gdk_gc_postdraw (drawable_private, gc_private);
761 if ((oldbitmap = SelectObject (memdc, image_private->ximage)) == NULL)
763 g_warning ("gdk_image_put_normal: SelectObject #1 failed");
764 gdk_gc_postdraw (drawable_private, gc_private);
767 if (!BitBlt (hdc, xdest, ydest, width, height,
768 memdc, xsrc, ysrc, SRCCOPY))
769 g_warning ("gdk_image_put_normal: BitBlt failed");
771 if (SelectObject (memdc, oldbitmap) == NULL)
772 g_warning ("gdk_image_put_normal: SelectObject #2 failed");
774 if (!DeleteDC (memdc))
775 g_warning ("gdk_image_put_normal: DeleteDC failed");
777 gdk_gc_postdraw (drawable_private, gc_private);