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"
33 static void gdk_image_put_normal (GdkDrawable *drawable,
42 static GList *image_list = NULL;
51 image = image_list->data;
52 gdk_image_destroy (image);
57 gdk_image_new_bitmap (GdkVisual *visual, gpointer data, gint w, gint h)
59 * Desc: create a new bitmap image
64 GdkImagePrivate *private;
66 BITMAPINFOHEADER bmiHeader;
73 int bpl = (w-1)/8 + 1;
74 int bpl32 = ((w-1)/32 + 1)*4;
76 private = g_new(GdkImagePrivate, 1);
77 image = (GdkImage *) private;
78 private->image_put = gdk_image_put_normal;
79 image->type = GDK_IMAGE_SHARED;
80 image->visual = visual;
84 xvisual = ((GdkVisualPrivate*) visual)->xvisual;
86 GDK_NOTE (MISC, g_print ("gdk_image_new_bitmap: %dx%d\n", w, h));
88 bmi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
89 bmi.bmiHeader.biWidth = w;
90 bmi.bmiHeader.biHeight = -h;
91 bmi.bmiHeader.biPlanes = 1;
92 bmi.bmiHeader.biBitCount = 1;
93 bmi.bmiHeader.biCompression = BI_RGB;
94 bmi.bmiHeader.biSizeImage = 0;
95 bmi.bmiHeader.biXPelsPerMeter =
96 bmi.bmiHeader.biYPelsPerMeter = 0;
97 bmi.bmiHeader.biClrUsed = 0;
98 bmi.bmiHeader.biClrImportant = 0;
100 bmi.u.bmiColors[0].rgbBlue =
101 bmi.u.bmiColors[0].rgbGreen =
102 bmi.u.bmiColors[0].rgbRed = 0x00;
103 bmi.u.bmiColors[0].rgbReserved = 0x00;
105 bmi.u.bmiColors[1].rgbBlue =
106 bmi.u.bmiColors[1].rgbGreen =
107 bmi.u.bmiColors[1].rgbRed = 0xFF;
108 bmi.u.bmiColors[1].rgbReserved = 0x00;
110 private->ximage = CreateDIBSection (gdk_DC, (BITMAPINFO *) &bmi,
111 DIB_RGB_COLORS, &bits, NULL, 0);
114 /* Win32 expects scanlines in DIBs to be 32 bit aligned */
116 for (i = 0; i < h; i++)
117 memmove (bits + i*bpl32, ((char *) data) + i*bpl, bpl);
120 memmove (bits, data, bpl*h);
123 image->byte_order = GDK_MSB_FIRST;
127 } /* gdk_image_new_bitmap() */
130 gdk_image_init (void)
135 gdk_image_new_with_depth (GdkImageType type,
142 GdkImagePrivate *private;
145 BITMAPINFOHEADER bmiHeader;
147 WORD bmiIndices[256];
149 RGBQUAD bmiColors[256];
155 if (type == GDK_IMAGE_FASTEST || type == GDK_IMAGE_NORMAL)
156 type = GDK_IMAGE_SHARED;
158 GDK_NOTE (MISC, g_print ("gdk_image_new_with_depth: %dx%dx%d %s\n",
159 width, height, depth,
160 (type == GDK_IMAGE_SHARED ? "shared" :
161 (type == GDK_IMAGE_SHARED_PIXMAP ? "shared_pixmap" :
164 private = g_new (GdkImagePrivate, 1);
165 image = (GdkImage*) private;
167 private->image_put = NULL;
170 image->visual = visual;
171 image->width = width;
172 image->height = height;
173 image->depth = depth;
175 xvisual = ((GdkVisualPrivate*) visual)->xvisual;
177 private->image_put = gdk_image_put_normal;
179 bmi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
180 bmi.bmiHeader.biWidth = width;
181 bmi.bmiHeader.biHeight = -height;
182 bmi.bmiHeader.biPlanes = 1;
184 bmi.bmiHeader.biBitCount = 16;
186 bmi.bmiHeader.biBitCount = depth;
189 bmi.bmiHeader.biCompression = BI_BITFIELDS;
192 bmi.bmiHeader.biCompression = BI_RGB;
193 bmi.bmiHeader.biSizeImage = 0;
194 bmi.bmiHeader.biXPelsPerMeter =
195 bmi.bmiHeader.biYPelsPerMeter = 0;
196 bmi.bmiHeader.biClrUsed = 0;
197 bmi.bmiHeader.biClrImportant = 0;
199 if (image->visual->type == GDK_VISUAL_PSEUDO_COLOR)
201 iUsage = DIB_PAL_COLORS;
202 for (i = 0; i < 256; i++)
203 bmi.u.bmiIndices[i] = i;
209 bmi.u.bmiColors[0].rgbBlue =
210 bmi.u.bmiColors[0].rgbGreen =
211 bmi.u.bmiColors[0].rgbRed = 0x00;
212 bmi.u.bmiColors[0].rgbReserved = 0x00;
214 bmi.u.bmiColors[1].rgbBlue =
215 bmi.u.bmiColors[1].rgbGreen =
216 bmi.u.bmiColors[1].rgbRed = 0xFF;
217 bmi.u.bmiColors[1].rgbReserved = 0x00;
221 else if (depth == 16)
223 bmi.u.bmiMasks[0] = visual->red_mask;
224 bmi.u.bmiMasks[1] = visual->green_mask;
225 bmi.u.bmiMasks[2] = visual->blue_mask;
228 iUsage = DIB_RGB_COLORS;
232 CreateDIBSection (gdk_DC, (BITMAPINFO *) &bmi, iUsage,
233 &image->mem, NULL, 0);
235 if (private->ximage == NULL)
237 g_warning ("gdk_image_new_with_depth: CreateDIBSection failed");
259 g_warning ("gdk_image_new_with_depth: depth = %d", depth);
260 g_assert_not_reached ();
262 image->byte_order = GDK_LSB_FIRST;
264 image->bpl = ((width-1)/32 + 1)*4;
266 image->bpl = ((width*image->bpp - 1)/4 + 1)*4;
268 GDK_NOTE (MISC, g_print ("... = %#x mem = %#x, bpl = %d\n",
269 private->ximage, image->mem, image->bpl));
275 gdk_image_new (GdkImageType type,
280 GdkVisualPrivate *visual_private = (GdkVisualPrivate *) visual;
281 return gdk_image_new_with_depth (type, visual, width, height,
282 visual_private->xvisual->bitspixel);
286 gdk_image_bitmap_new (GdkImageType type,
291 return gdk_image_new_with_depth (type, visual, width, height, 1);
295 gdk_image_get (GdkWindow *window,
302 GdkImagePrivate *private;
303 GdkWindowPrivate *win_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 win_private = (GdkWindowPrivate *) window;
321 if (win_private->destroyed)
324 GDK_NOTE (MISC, g_print ("gdk_image_get: %#x %dx%d@+%d+%d\n",
325 win_private->xwindow, width, height, x, y));
327 private = g_new (GdkImagePrivate, 1);
328 image = (GdkImage*) private;
330 private->image_put = gdk_image_put_normal;
332 image->type = GDK_IMAGE_SHARED;
333 image->visual = gdk_window_get_visual (window);
334 image->width = width;
335 image->height = height;
337 /* This function is called both to blit from a window and from
340 if (win_private->window_type == GDK_WINDOW_PIXMAP)
342 if ((hdc = CreateCompatibleDC (NULL)) == NULL)
344 g_warning ("gdk_image_get: CreateCompatibleDC #1 failed");
348 if ((oldbitmap1 = SelectObject (hdc, win_private->xwindow)) == NULL)
350 g_warning ("gdk_image_get: SelectObject #1 failed");
355 GetObject (win_private->xwindow, sizeof (BITMAP), &bm);
357 g_print ("gdk_image_get: bmWidth = %d, bmHeight = %d, bmWidthBytes = %d, bmBitsPixel = %d\n",
358 bm.bmWidth, bm.bmHeight, bm.bmWidthBytes, bm.bmBitsPixel));
359 image->depth = bm.bmBitsPixel;
360 if (image->depth <= 8)
362 iUsage = DIB_PAL_COLORS;
363 for (i = 0; i < 256; i++)
364 bmi.u.bmiIndices[i] = i;
367 iUsage = DIB_RGB_COLORS;
371 if ((hdc = GetDC (win_private->xwindow)) == NULL)
373 g_warning ("gdk_image_get: GetDC failed");
377 image->depth = gdk_visual_get_system ()->depth;
378 if (image->visual->type == GDK_VISUAL_PSEUDO_COLOR)
380 iUsage = DIB_PAL_COLORS;
381 for (i = 0; i < 256; i++)
382 bmi.u.bmiIndices[i] = i;
385 iUsage = DIB_RGB_COLORS;
388 if ((memdc = CreateCompatibleDC (hdc)) == NULL)
390 g_warning ("gdk_image_get: CreateCompatibleDC #2 failed");
391 if (win_private->window_type == GDK_WINDOW_PIXMAP)
393 SelectObject (hdc, oldbitmap1);
398 ReleaseDC (win_private->xwindow, hdc);
404 bmi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
405 bmi.bmiHeader.biWidth = width;
406 bmi.bmiHeader.biHeight = -height;
407 bmi.bmiHeader.biPlanes = 1;
408 bmi.bmiHeader.biBitCount = image->depth;
409 if (image->depth == 16)
411 bmi.bmiHeader.biCompression = BI_BITFIELDS;
412 if (image->visual == NULL)
414 /* XXX ??? Is it always this if depth==16 and a pixmap? Guess so. */
415 bmi.u.bmiMasks[0] = 0xf800;
416 bmi.u.bmiMasks[1] = 0x07e0;
417 bmi.u.bmiMasks[2] = 0x001f;
421 bmi.u.bmiMasks[0] = image->visual->red_mask;
422 bmi.u.bmiMasks[1] = image->visual->green_mask;
423 bmi.u.bmiMasks[2] = image->visual->blue_mask;
427 bmi.bmiHeader.biCompression = BI_RGB;
428 bmi.bmiHeader.biSizeImage = 0;
429 bmi.bmiHeader.biXPelsPerMeter =
430 bmi.bmiHeader.biYPelsPerMeter = 0;
431 bmi.bmiHeader.biClrUsed = 0;
432 bmi.bmiHeader.biClrImportant = 0;
434 if ((private->ximage =
435 CreateDIBSection (hdc, (BITMAPINFO *) &bmi, iUsage,
436 &image->mem, NULL, 0)) == NULL)
438 g_warning ("gdk_image_get: CreateDIBSection failed");
440 if (win_private->window_type == GDK_WINDOW_PIXMAP)
442 SelectObject (hdc, oldbitmap1);
447 ReleaseDC (win_private->xwindow, hdc);
453 if ((oldbitmap2 = SelectObject (memdc, private->ximage)) == NULL)
455 g_warning ("gdk_image_get: SelectObject #2 failed");
456 DeleteObject (private->ximage);
458 if (win_private->window_type == GDK_WINDOW_PIXMAP)
460 SelectObject (hdc, oldbitmap1);
465 ReleaseDC (win_private->xwindow, hdc);
471 if (!BitBlt (memdc, 0, 0, width, height, hdc, x, y, SRCCOPY))
473 g_warning ("gdk_image_get: BitBlt failed");
474 SelectObject (memdc, oldbitmap2);
475 DeleteObject (private->ximage);
477 if (win_private->window_type == GDK_WINDOW_PIXMAP)
479 SelectObject (hdc, oldbitmap1);
484 ReleaseDC (win_private->xwindow, hdc);
490 if (SelectObject (memdc, oldbitmap2) == NULL)
491 g_warning ("gdk_image_get: SelectObject #3 failed");
493 if (!DeleteDC (memdc))
494 g_warning ("gdk_image_get: DeleteDC failed");
496 if (win_private->window_type == GDK_WINDOW_PIXMAP)
498 SelectObject (hdc, oldbitmap1);
503 ReleaseDC (win_private->xwindow, hdc);
506 switch (image->depth)
523 g_warning ("gdk_image_get: image->depth = %d", image->depth);
524 g_assert_not_reached ();
526 image->byte_order = GDK_LSB_FIRST;
527 if (image->depth == 1)
528 image->bpl = ((width - 1)/32 + 1)*4;
530 image->bpl = ((width*image->bpp - 1)/4 + 1)*4;
532 GDK_NOTE (MISC, g_print ("... = %#x mem = %#x, bpl = %d\n",
533 private->ximage, image->mem, image->bpl));
539 gdk_image_get_pixel (GdkImage *image,
544 GdkImagePrivate *private;
546 g_return_val_if_fail (image != NULL, 0);
548 private = (GdkImagePrivate *) image;
550 g_return_val_if_fail (x >= 0 && x < image->width
551 && y >= 0 && y < image->height, 0);
553 if (image->depth == 1)
554 pixel = (((char *) image->mem)[y * image->bpl + (x >> 3)] & (1 << (7 - (x & 0x7)))) != 0;
557 guchar *pixelp = (guchar *) image->mem + y * image->bpl + x * image->bpp;
565 /* Windows is always LSB, no need to check image->byte_order. */
567 pixel = pixelp[0] | (pixelp[1] << 8);
571 pixel = pixelp[0] | (pixelp[1] << 8) | (pixelp[2] << 16);
575 pixel = pixelp[0] | (pixelp[1] << 8) | (pixelp[2] << 16);
584 gdk_image_put_pixel (GdkImage *image,
589 GdkImagePrivate *private;
591 g_return_if_fail (image != NULL);
593 private = (GdkImagePrivate *) image;
595 g_return_if_fail (x >= 0 && x < image->width && y >= 0 && y < image->height);
597 if (image->depth == 1)
599 ((guchar *) image->mem)[y * image->bpl + (x >> 3)] |= (1 << (7 - (x & 0x7)));
601 ((guchar *) image->mem)[y * image->bpl + (x >> 3)] &= ~(1 << (7 - (x & 0x7)));
604 guchar *pixelp = (guchar *) image->mem + y * image->bpl + x * image->bpp;
606 /* Windows is always LSB, no need to check image->byte_order. */
612 pixelp[2] = ((pixel >> 16) & 0xFF);
614 pixelp[1] = ((pixel >> 8) & 0xFF);
616 pixelp[0] = (pixel & 0xFF);
622 gdk_image_destroy (GdkImage *image)
624 GdkImagePrivate *private;
626 g_return_if_fail (image != NULL);
628 private = (GdkImagePrivate*) image;
630 GDK_NOTE (MISC, g_print ("gdk_image_destroy: %#x%s\n",
632 (image->type == GDK_IMAGE_SHARED_PIXMAP ?
633 " (shared pixmap)" : "")));
637 case GDK_IMAGE_SHARED_PIXMAP:
638 break; /* The Windows bitmap has already been
639 * (or will be) deleted when freeing
640 * the corresponding pixmap.
643 case GDK_IMAGE_SHARED:
644 if (!DeleteObject (private->ximage))
645 g_warning ("gdk_image_destroy: DeleteObject failed");
649 g_assert_not_reached ();
656 gdk_image_put_normal (GdkDrawable *drawable,
666 GdkWindowPrivate *drawable_private;
667 GdkImagePrivate *image_private;
668 GdkGCPrivate *gc_private;
670 GdkColormapPrivate *colormap_private;
672 g_return_if_fail (drawable != NULL);
673 g_return_if_fail (image != NULL);
674 g_return_if_fail (gc != NULL);
676 drawable_private = (GdkWindowPrivate*) drawable;
677 if (drawable_private->destroyed)
679 image_private = (GdkImagePrivate*) image;
680 gc_private = (GdkGCPrivate*) gc;
682 /* The image can in fact be "shared", so don't test */
684 hdc = gdk_gc_predraw (drawable_private, gc_private);
685 colormap_private = (GdkColormapPrivate *) drawable_private->colormap;
686 if (colormap_private && colormap_private->xcolormap->rc_palette)
690 BITMAPINFOHEADER bmiHeader;
691 WORD bmiIndices[256];
693 static gboolean bmi_inited = FALSE;
698 for (i = 0; i < 256; i++)
699 bmi.bmiIndices[i] = i;
703 if (GetObject (image_private->ximage, sizeof (DIBSECTION),
704 &ds) != sizeof (DIBSECTION))
706 g_warning ("gdk_image_put_normal: GetObject failed");
709 g_print("xdest = %d, ydest = %d, xsrc = %d, ysrc = %d, width = %d, height = %d\n",
710 xdest, ydest, xsrc, ysrc, width, height);
711 g_print("bmWidth = %d, bmHeight = %d, bmBitsPixel = %d, bmBits = %p\n",
712 ds.dsBm.bmWidth, ds.dsBm.bmHeight, ds.dsBm.bmBitsPixel, ds.dsBm.bmBits);
713 g_print("biWidth = %d, biHeight = %d, biBitCount = %d, biClrUsed = %d\n",
714 ds.dsBmih.biWidth, ds.dsBmih.biHeight, ds.dsBmih.biBitCount, ds.dsBmih.biClrUsed);
716 bmi.bmiHeader = ds.dsBmih;
717 /* I have spent hours on getting the parameters to
718 * SetDIBitsToDevice right. I wonder what drugs the guys in
719 * Redmond were on when they designed this API.
721 if (SetDIBitsToDevice (hdc,
724 xsrc, (-ds.dsBmih.biHeight)-height-ysrc,
725 0, -ds.dsBmih.biHeight,
727 (CONST BITMAPINFO *) &bmi,
728 DIB_PAL_COLORS) == 0)
729 g_warning ("SetDIBitsToDevice failed");
736 if ((memdc = CreateCompatibleDC (hdc)) == NULL)
738 g_warning ("gdk_image_put_normal: CreateCompatibleDC failed");
739 gdk_gc_postdraw (drawable_private, gc_private);
743 if ((oldbitmap = SelectObject (memdc, image_private->ximage)) == NULL)
745 g_warning ("gdk_image_put_normal: SelectObject #1 failed");
746 gdk_gc_postdraw (drawable_private, gc_private);
749 if (!BitBlt (hdc, xdest, ydest, width, height,
750 memdc, xsrc, ysrc, SRCCOPY))
751 g_warning ("gdk_image_put_normal: BitBlt failed");
753 if (SelectObject (memdc, oldbitmap) == NULL)
754 g_warning ("gdk_image_put_normal: SelectObject #2 failed");
756 if (!DeleteDC (memdc))
757 g_warning ("gdk_image_put_normal: DeleteDC failed");
759 gdk_gc_postdraw (drawable_private, gc_private);