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_SHARED;
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 if (type == GDK_IMAGE_FASTEST || type == GDK_IMAGE_NORMAL)
155 type = GDK_IMAGE_SHARED;
157 GDK_NOTE (MISC, g_print ("gdk_image_new_with_depth: %dx%dx%d %s\n",
158 width, height, depth,
159 (type == GDK_IMAGE_SHARED ? "shared" :
160 (type == GDK_IMAGE_SHARED_PIXMAP ? "shared_pixmap" :
163 private = g_new (GdkImagePrivate, 1);
164 image = (GdkImage*) private;
166 private->image_put = NULL;
169 image->visual = visual;
170 image->width = width;
171 image->height = height;
172 image->depth = depth;
174 xvisual = ((GdkVisualPrivate*) visual)->xvisual;
176 private->image_put = gdk_image_put_normal;
178 bmi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
179 bmi.bmiHeader.biWidth = width;
180 bmi.bmiHeader.biHeight = -height;
181 bmi.bmiHeader.biPlanes = 1;
183 bmi.bmiHeader.biBitCount = 16;
185 bmi.bmiHeader.biBitCount = depth;
188 bmi.bmiHeader.biCompression = BI_BITFIELDS;
191 bmi.bmiHeader.biCompression = BI_RGB;
192 bmi.bmiHeader.biSizeImage = 0;
193 bmi.bmiHeader.biXPelsPerMeter =
194 bmi.bmiHeader.biYPelsPerMeter = 0;
195 bmi.bmiHeader.biClrUsed = 0;
196 bmi.bmiHeader.biClrImportant = 0;
198 if (image->visual->type == GDK_VISUAL_PSEUDO_COLOR)
200 iUsage = DIB_PAL_COLORS;
201 for (i = 0; i < 256; i++)
202 bmi.u.bmiIndices[i] = i;
208 bmi.u.bmiColors[0].rgbBlue =
209 bmi.u.bmiColors[0].rgbGreen =
210 bmi.u.bmiColors[0].rgbRed = 0x00;
211 bmi.u.bmiColors[0].rgbReserved = 0x00;
213 bmi.u.bmiColors[1].rgbBlue =
214 bmi.u.bmiColors[1].rgbGreen =
215 bmi.u.bmiColors[1].rgbRed = 0xFF;
216 bmi.u.bmiColors[1].rgbReserved = 0x00;
220 else if (depth == 16)
222 bmi.u.bmiMasks[0] = visual->red_mask;
223 bmi.u.bmiMasks[1] = visual->green_mask;
224 bmi.u.bmiMasks[2] = visual->blue_mask;
227 iUsage = DIB_RGB_COLORS;
231 CreateDIBSection (gdk_DC, (BITMAPINFO *) &bmi, iUsage,
232 &image->mem, NULL, 0);
234 if (private->ximage == NULL)
236 g_warning ("gdk_image_new_with_depth: CreateDIBSection failed");
258 g_warning ("gdk_image_new_with_depth: depth = %d", depth);
259 g_assert_not_reached ();
261 image->byte_order = GDK_LSB_FIRST;
263 image->bpl = ((width-1)/32 + 1)*4;
265 image->bpl = ((width*image->bpp - 1)/4 + 1)*4;
267 GDK_NOTE (MISC, g_print ("... = %#x mem = %#x, bpl = %d\n",
268 private->ximage, image->mem, image->bpl));
274 gdk_image_new (GdkImageType type,
279 return gdk_image_new_with_depth (type, visual, width, height, visual->depth);
283 gdk_image_bitmap_new (GdkImageType type,
288 return gdk_image_new_with_depth (type, visual, width, height, 1);
292 gdk_image_get (GdkWindow *window,
299 GdkImagePrivate *private;
300 GdkWindowPrivate *win_private;
303 BITMAPINFOHEADER bmiHeader;
305 WORD bmiIndices[256];
307 RGBQUAD bmiColors[256];
310 HGDIOBJ oldbitmap1, oldbitmap2;
315 g_return_val_if_fail (window != NULL, NULL);
317 win_private = (GdkWindowPrivate *) window;
318 if (win_private->destroyed)
321 GDK_NOTE (MISC, g_print ("gdk_image_get: %#x %dx%d@+%d+%d\n",
322 win_private->xwindow, width, height, x, y));
324 private = g_new (GdkImagePrivate, 1);
325 image = (GdkImage*) private;
327 private->image_put = gdk_image_put_normal;
329 image->type = GDK_IMAGE_SHARED;
330 image->visual = gdk_window_get_visual (window);
331 image->width = width;
332 image->height = height;
334 /* This function is called both to blit from a window and from
337 if (win_private->window_type == GDK_WINDOW_PIXMAP)
339 if ((hdc = CreateCompatibleDC (NULL)) == NULL)
341 g_warning ("gdk_image_get: CreateCompatibleDC #1 failed");
345 if ((oldbitmap1 = SelectObject (hdc, win_private->xwindow)) == NULL)
347 g_warning ("gdk_image_get: SelectObject #1 failed");
352 GetObject (win_private->xwindow, sizeof (BITMAP), &bm);
354 g_print ("gdk_image_get: bmWidth = %d, bmHeight = %d, bmWidthBytes = %d, bmBitsPixel = %d\n",
355 bm.bmWidth, bm.bmHeight, bm.bmWidthBytes, bm.bmBitsPixel));
356 image->depth = bm.bmBitsPixel;
357 if (image->depth <= 8)
359 iUsage = DIB_PAL_COLORS;
360 for (i = 0; i < 256; i++)
361 bmi.u.bmiIndices[i] = i;
364 iUsage = DIB_RGB_COLORS;
368 if ((hdc = GetDC (win_private->xwindow)) == NULL)
370 g_warning ("gdk_image_get: GetDC failed");
374 image->depth = gdk_visual_get_system ()->depth;
375 if (image->visual->type == GDK_VISUAL_PSEUDO_COLOR)
377 iUsage = DIB_PAL_COLORS;
378 for (i = 0; i < 256; i++)
379 bmi.u.bmiIndices[i] = i;
382 iUsage = DIB_RGB_COLORS;
385 if ((memdc = CreateCompatibleDC (hdc)) == NULL)
387 g_warning ("gdk_image_get: CreateCompatibleDC #2 failed");
388 if (win_private->window_type == GDK_WINDOW_PIXMAP)
390 SelectObject (hdc, oldbitmap1);
395 ReleaseDC (win_private->xwindow, hdc);
401 bmi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
402 bmi.bmiHeader.biWidth = width;
403 bmi.bmiHeader.biHeight = -height;
404 bmi.bmiHeader.biPlanes = 1;
405 bmi.bmiHeader.biBitCount = image->depth;
406 if (image->depth == 16)
408 bmi.bmiHeader.biCompression = BI_BITFIELDS;
409 if (image->visual == NULL)
411 /* XXX ??? Is it always this if depth==16 and a pixmap? Guess so. */
412 bmi.u.bmiMasks[0] = 0xf800;
413 bmi.u.bmiMasks[1] = 0x07e0;
414 bmi.u.bmiMasks[2] = 0x001f;
418 bmi.u.bmiMasks[0] = image->visual->red_mask;
419 bmi.u.bmiMasks[1] = image->visual->green_mask;
420 bmi.u.bmiMasks[2] = image->visual->blue_mask;
424 bmi.bmiHeader.biCompression = BI_RGB;
425 bmi.bmiHeader.biSizeImage = 0;
426 bmi.bmiHeader.biXPelsPerMeter =
427 bmi.bmiHeader.biYPelsPerMeter = 0;
428 bmi.bmiHeader.biClrUsed = 0;
429 bmi.bmiHeader.biClrImportant = 0;
431 if ((private->ximage =
432 CreateDIBSection (hdc, (BITMAPINFO *) &bmi, iUsage,
433 &image->mem, NULL, 0)) == NULL)
435 g_warning ("gdk_image_get: CreateDIBSection failed");
437 if (win_private->window_type == GDK_WINDOW_PIXMAP)
439 SelectObject (hdc, oldbitmap1);
444 ReleaseDC (win_private->xwindow, hdc);
450 if ((oldbitmap2 = SelectObject (memdc, private->ximage)) == NULL)
452 g_warning ("gdk_image_get: SelectObject #2 failed");
453 DeleteObject (private->ximage);
455 if (win_private->window_type == GDK_WINDOW_PIXMAP)
457 SelectObject (hdc, oldbitmap1);
462 ReleaseDC (win_private->xwindow, hdc);
468 if (!BitBlt (memdc, 0, 0, width, height, hdc, x, y, SRCCOPY))
470 g_warning ("gdk_image_get: BitBlt failed");
471 SelectObject (memdc, oldbitmap2);
472 DeleteObject (private->ximage);
474 if (win_private->window_type == GDK_WINDOW_PIXMAP)
476 SelectObject (hdc, oldbitmap1);
481 ReleaseDC (win_private->xwindow, hdc);
487 if (SelectObject (memdc, oldbitmap2) == NULL)
488 g_warning ("gdk_image_get: SelectObject #3 failed");
490 if (!DeleteDC (memdc))
491 g_warning ("gdk_image_get: DeleteDC failed");
493 if (win_private->window_type == GDK_WINDOW_PIXMAP)
495 SelectObject (hdc, oldbitmap1);
500 ReleaseDC (win_private->xwindow, hdc);
503 switch (image->depth)
520 g_warning ("gdk_image_get: image->depth = %d", image->depth);
521 g_assert_not_reached ();
523 image->byte_order = GDK_LSB_FIRST;
524 if (image->depth == 1)
525 image->bpl = ((width - 1)/32 + 1)*4;
527 image->bpl = ((width*image->bpp - 1)/4 + 1)*4;
529 GDK_NOTE (MISC, g_print ("... = %#x mem = %#x, bpl = %d\n",
530 private->ximage, image->mem, image->bpl));
536 gdk_image_get_pixel (GdkImage *image,
541 GdkImagePrivate *private;
543 g_return_val_if_fail (image != NULL, 0);
545 private = (GdkImagePrivate *) image;
547 g_return_val_if_fail (x >= 0 && x < image->width
548 && y >= 0 && y < image->height, 0);
550 if (image->depth == 1)
551 pixel = (((char *) image->mem)[y * image->bpl + (x >> 3)] & (1 << (7 - (x & 0x7)))) != 0;
554 guchar *pixelp = (guchar *) image->mem + y * image->bpl + x * image->bpp;
562 /* Windows is always LSB, no need to check image->byte_order. */
564 pixel = pixelp[0] | (pixelp[1] << 8);
568 pixel = pixelp[0] | (pixelp[1] << 8) | (pixelp[2] << 16);
572 pixel = pixelp[0] | (pixelp[1] << 8) | (pixelp[2] << 16);
581 gdk_image_put_pixel (GdkImage *image,
586 GdkImagePrivate *private;
588 g_return_if_fail (image != NULL);
590 private = (GdkImagePrivate *) image;
592 g_return_if_fail (x >= 0 && x < image->width && y >= 0 && y < image->height);
594 if (image->depth == 1)
596 ((guchar *) image->mem)[y * image->bpl + (x >> 3)] |= (1 << (7 - (x & 0x7)));
598 ((guchar *) image->mem)[y * image->bpl + (x >> 3)] &= ~(1 << (7 - (x & 0x7)));
601 guchar *pixelp = (guchar *) image->mem + y * image->bpl + x * image->bpp;
603 /* Windows is always LSB, no need to check image->byte_order. */
609 pixelp[2] = ((pixel >> 16) & 0xFF);
611 pixelp[1] = ((pixel >> 8) & 0xFF);
613 pixelp[0] = (pixel & 0xFF);
619 gdk_image_destroy (GdkImage *image)
621 GdkImagePrivate *private;
623 g_return_if_fail (image != NULL);
625 private = (GdkImagePrivate*) image;
627 GDK_NOTE (MISC, g_print ("gdk_image_destroy: %#x%s\n",
629 (image->type == GDK_IMAGE_SHARED_PIXMAP ?
630 " (shared pixmap)" : "")));
634 case GDK_IMAGE_SHARED_PIXMAP:
635 break; /* The Windows bitmap has already been
636 * (or will be) deleted when freeing
637 * the corresponding pixmap.
640 case GDK_IMAGE_SHARED:
641 if (!DeleteObject (private->ximage))
642 g_warning ("gdk_image_destroy: DeleteObject failed");
646 g_assert_not_reached ();
653 gdk_image_put_normal (GdkDrawable *drawable,
663 GdkWindowPrivate *drawable_private;
664 GdkImagePrivate *image_private;
665 GdkGCPrivate *gc_private;
667 GdkColormapPrivate *colormap_private;
669 g_return_if_fail (drawable != NULL);
670 g_return_if_fail (image != NULL);
671 g_return_if_fail (gc != NULL);
673 drawable_private = (GdkWindowPrivate*) drawable;
674 if (drawable_private->destroyed)
676 image_private = (GdkImagePrivate*) image;
677 gc_private = (GdkGCPrivate*) gc;
679 /* The image can in fact be "shared", so don't test */
681 hdc = gdk_gc_predraw (drawable_private, gc_private);
682 colormap_private = (GdkColormapPrivate *) drawable_private->colormap;
683 if (colormap_private && colormap_private->xcolormap->rc_palette)
687 BITMAPINFOHEADER bmiHeader;
688 WORD bmiIndices[256];
690 static gboolean bmi_inited = FALSE;
695 for (i = 0; i < 256; i++)
696 bmi.bmiIndices[i] = i;
700 if (GetObject (image_private->ximage, sizeof (DIBSECTION),
701 &ds) != sizeof (DIBSECTION))
703 g_warning ("gdk_image_put_normal: GetObject failed");
706 g_print("xdest = %d, ydest = %d, xsrc = %d, ysrc = %d, width = %d, height = %d\n",
707 xdest, ydest, xsrc, ysrc, width, height);
708 g_print("bmWidth = %d, bmHeight = %d, bmBitsPixel = %d, bmBits = %p\n",
709 ds.dsBm.bmWidth, ds.dsBm.bmHeight, ds.dsBm.bmBitsPixel, ds.dsBm.bmBits);
710 g_print("biWidth = %d, biHeight = %d, biBitCount = %d, biClrUsed = %d\n",
711 ds.dsBmih.biWidth, ds.dsBmih.biHeight, ds.dsBmih.biBitCount, ds.dsBmih.biClrUsed);
713 bmi.bmiHeader = ds.dsBmih;
714 /* I have spent hours on getting the parameters to
715 * SetDIBitsToDevice right. I wonder what drugs the guys in
716 * Redmond were on when they designed this API.
718 if (SetDIBitsToDevice (hdc,
721 xsrc, (-ds.dsBmih.biHeight)-height-ysrc,
722 0, -ds.dsBmih.biHeight,
724 (CONST BITMAPINFO *) &bmi,
725 DIB_PAL_COLORS) == 0)
726 g_warning ("SetDIBitsToDevice failed");
733 if ((memdc = CreateCompatibleDC (hdc)) == NULL)
735 g_warning ("gdk_image_put_normal: CreateCompatibleDC failed");
736 gdk_gc_postdraw (drawable_private, gc_private);
740 if ((oldbitmap = SelectObject (memdc, image_private->ximage)) == NULL)
742 g_warning ("gdk_image_put_normal: SelectObject #1 failed");
743 gdk_gc_postdraw (drawable_private, gc_private);
746 if (!BitBlt (hdc, xdest, ydest, width, height,
747 memdc, xsrc, ysrc, SRCCOPY))
748 g_warning ("gdk_image_put_normal: BitBlt failed");
750 if (SelectObject (memdc, oldbitmap) == NULL)
751 g_warning ("gdk_image_put_normal: SelectObject #2 failed");
753 if (!DeleteDC (memdc))
754 g_warning ("gdk_image_put_normal: DeleteDC failed");
756 gdk_gc_postdraw (drawable_private, gc_private);