]> Pileus Git - ~andy/gtk/blob - gdk/win32/gdkimage-win32.c
need to cast image->mem away from void* to avoid 'error C2036: 'void *' :
[~andy/gtk] / gdk / win32 / gdkimage-win32.c
1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser 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.
8  *
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  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser 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.
18  */
19
20 /*
21  * Modified by the GTK+ Team and others 1997-2000.  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/. 
25  */
26
27 #include "gdkimage.h"
28 #include "gdkpixmap.h"
29 #include "gdkprivate-win32.h"
30
31 static GList *image_list = NULL;
32 static gpointer parent_class = NULL;
33
34 static void gdk_win32_image_destroy (GdkImage      *image);
35 static void gdk_image_init          (GdkImage      *image);
36 static void gdk_image_class_init    (GdkImageClass *klass);
37 static void gdk_image_finalize      (GObject       *object);
38
39 GType
40 gdk_image_get_type (void)
41 {
42   static GType object_type = 0;
43
44   if (!object_type)
45     {
46       static const GTypeInfo object_info =
47       {
48         sizeof (GdkImageClass),
49         (GBaseInitFunc) NULL,
50         (GBaseFinalizeFunc) NULL,
51         (GClassInitFunc) gdk_image_class_init,
52         NULL,           /* class_finalize */
53         NULL,           /* class_data */
54         sizeof (GdkImage),
55         0,              /* n_preallocs */
56         (GInstanceInitFunc) gdk_image_init,
57       };
58       
59       object_type = g_type_register_static (G_TYPE_OBJECT,
60                                             "GdkImage",
61                                             &object_info, 0);
62     }
63   
64   return object_type;
65 }
66
67 static void
68 gdk_image_init (GdkImage *image)
69 {
70   image->windowing_data = g_new0 (GdkImagePrivateWin32, 1);
71 }
72
73 static void
74 gdk_image_class_init (GdkImageClass *klass)
75 {
76   GObjectClass *object_class = G_OBJECT_CLASS (klass);
77
78   parent_class = g_type_class_peek_parent (klass);
79
80   object_class->finalize = gdk_image_finalize;
81 }
82
83 static void
84 gdk_image_finalize (GObject *object)
85 {
86   GdkImage *image = GDK_IMAGE (object);
87
88   gdk_win32_image_destroy (image);
89   
90   G_OBJECT_CLASS (parent_class)->finalize (object);
91 }
92
93 void
94 _gdk_image_exit (void)
95 {
96   GdkImage *image;
97
98   while (image_list)
99     {
100       image = image_list->data;
101       gdk_win32_image_destroy (image);
102     }
103 }
104
105 GdkImage *
106 gdk_image_new_bitmap (GdkVisual *visual,
107                       gpointer   data,
108                       gint       w,
109                       gint       h)
110 /*
111  * Desc: create a new bitmap image
112  */
113 {
114   Visual *xvisual;
115   GdkImage *image;
116   GdkImagePrivateWin32 *private;
117   struct {
118     BITMAPINFOHEADER bmiHeader;
119     union {
120       WORD bmiIndices[2];
121       RGBQUAD bmiColors[2];
122     } u;
123   } bmi;
124   char *bits;
125   int bpl = (w-1)/8 + 1;
126   int bpl32 = ((w-1)/32 + 1)*4;
127
128   image = g_object_new (gdk_image_get_type (), NULL);
129   private = IMAGE_PRIVATE_DATA (image);
130
131   image->type = GDK_IMAGE_SHARED;
132   image->visual = visual;
133   image->width = w;
134   image->height = h;
135   image->depth = 1;
136   xvisual = ((GdkVisualPrivate*) visual)->xvisual;
137
138   GDK_NOTE (MISC, g_print ("gdk_image_new_bitmap: %dx%d\n", w, h));
139   
140   bmi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
141   bmi.bmiHeader.biWidth = w;
142   bmi.bmiHeader.biHeight = -h;
143   bmi.bmiHeader.biPlanes = 1;
144   bmi.bmiHeader.biBitCount = 1;
145   bmi.bmiHeader.biCompression = BI_RGB;
146   bmi.bmiHeader.biSizeImage = 0;
147   bmi.bmiHeader.biXPelsPerMeter =
148     bmi.bmiHeader.biYPelsPerMeter = 0;
149   bmi.bmiHeader.biClrUsed = 0;
150   bmi.bmiHeader.biClrImportant = 0;
151   
152   bmi.u.bmiColors[0].rgbBlue = 
153     bmi.u.bmiColors[0].rgbGreen = 
154     bmi.u.bmiColors[0].rgbRed = 0x00;
155   bmi.u.bmiColors[0].rgbReserved = 0x00;
156
157   bmi.u.bmiColors[1].rgbBlue = 
158     bmi.u.bmiColors[1].rgbGreen = 
159     bmi.u.bmiColors[1].rgbRed = 0xFF;
160   bmi.u.bmiColors[1].rgbReserved = 0x00;
161   
162   private->hbitmap = CreateDIBSection (gdk_display_hdc, (BITMAPINFO *) &bmi,
163                                        DIB_RGB_COLORS, &bits, NULL, 0);
164   if (bpl != bpl32)
165     {
166       /* Win32 expects scanlines in DIBs to be 32 bit aligned */
167       int i;
168       for (i = 0; i < h; i++)
169         memmove (bits + i*bpl32, ((char *) data) + i*bpl, bpl);
170     }
171   else
172     memmove (bits, data, bpl*h);
173   image->mem = bits;
174   image->bpl = bpl32;
175   image->byte_order = GDK_MSB_FIRST;
176
177   image->bits_per_pixel = 1;
178   image->bpp = 1;
179
180   /* free data right now, in contrast to the X11 version we have made
181    * our own copy. Use free, it was malloc()ed.
182    */
183   free (data);
184   return(image);
185 } /* gdk_image_new_bitmap() */
186
187 void
188 _gdk_windowing_image_init (void)
189 {
190   /* Nothing needed AFAIK */
191 }
192
193 GdkImage*
194 _gdk_image_new_for_depth (GdkImageType  type,
195                           GdkVisual    *visual,
196                           gint          width,
197                           gint          height,
198                           gint          depth)
199 {
200   GdkImage *image;
201   GdkImagePrivateWin32 *private;
202   Visual *xvisual = NULL;
203   struct {
204     BITMAPINFOHEADER bmiHeader;
205     union {
206       WORD bmiIndices[256];
207       DWORD bmiMasks[3];
208       RGBQUAD bmiColors[256];
209     } u;
210   } bmi;
211   UINT iUsage;
212   int i;
213
214   g_return_val_if_fail (!visual || GDK_IS_VISUAL (visual), NULL);
215   g_return_val_if_fail (visual || depth != -1, NULL);
216  
217   if (visual)
218     depth = visual->depth;
219
220   if (type == GDK_IMAGE_FASTEST || type == GDK_IMAGE_NORMAL)
221     type = GDK_IMAGE_SHARED;
222
223   GDK_NOTE (MISC, g_print ("gdk_image_new: %dx%d %s\n",
224                            width, height,
225                            (type == GDK_IMAGE_SHARED ? "shared" :
226                             "???")));
227   
228   image = g_object_new (gdk_image_get_type (), NULL);
229   private = IMAGE_PRIVATE_DATA (image);
230
231   image->type = type;
232   image->visual = visual;
233   image->width = width;
234   image->height = height;
235   image->depth = depth;
236   
237   if (visual)
238     xvisual = ((GdkVisualPrivate*) visual)->xvisual;
239   
240   bmi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
241   bmi.bmiHeader.biWidth = width;
242   bmi.bmiHeader.biHeight = -height;
243   bmi.bmiHeader.biPlanes = 1;
244   if (image->depth == 15)
245     bmi.bmiHeader.biBitCount = 16;
246   else
247     bmi.bmiHeader.biBitCount = image->depth;
248   if (image->depth == 16)
249     bmi.bmiHeader.biCompression = BI_BITFIELDS;
250   else
251     bmi.bmiHeader.biCompression = BI_RGB;
252   bmi.bmiHeader.biSizeImage = 0;
253   bmi.bmiHeader.biXPelsPerMeter =
254     bmi.bmiHeader.biYPelsPerMeter = 0;
255   bmi.bmiHeader.biClrUsed = 0;
256   bmi.bmiHeader.biClrImportant = 0;
257
258   if (   (image->visual && image->visual->type == GDK_VISUAL_PSEUDO_COLOR)
259       || (8 == image->depth))
260     {
261       iUsage = DIB_PAL_COLORS;
262       for (i = 0; i < 256; i++)
263         bmi.u.bmiIndices[i] = i;
264     }
265   else
266     {
267       iUsage = DIB_RGB_COLORS;
268       if (image->depth == 1)
269         {
270           bmi.u.bmiColors[0].rgbBlue = 
271             bmi.u.bmiColors[0].rgbGreen =
272             bmi.u.bmiColors[0].rgbRed = 0x00;
273           bmi.u.bmiColors[0].rgbReserved = 0x00;
274
275           bmi.u.bmiColors[1].rgbBlue = 
276             bmi.u.bmiColors[1].rgbGreen =
277             bmi.u.bmiColors[1].rgbRed = 0xFF;
278           bmi.u.bmiColors[1].rgbReserved = 0x00;
279
280         }
281       else if (image->depth == 16)
282         {
283           bmi.u.bmiMasks[0] = visual ? visual->red_mask   : 0x0000F800;
284           bmi.u.bmiMasks[1] = visual ? visual->green_mask : 0x000007E0;
285           bmi.u.bmiMasks[2] = visual ? visual->blue_mask  : 0x0000001F;
286         }
287     }
288
289   private->hbitmap = CreateDIBSection (gdk_display_hdc, (BITMAPINFO *) &bmi,
290                                        iUsage, &image->mem, NULL, 0);
291
292   if (private->hbitmap == NULL)
293     {
294       WIN32_GDI_FAILED ("CreateDIBSection");
295       g_free (image);
296       return NULL;
297     }
298
299   switch (image->depth)
300     {
301     case 1:
302     case 8:
303       image->bpp = 1;
304       break;
305     case 15:
306     case 16:
307       image->bpp = 2;
308       break;
309     case 24:
310       image->bpp = 3;
311       break;
312     case 32:
313       image->bpp = 4;
314       break;
315     default:
316       g_warning ("gdk_image_new: depth = %d", image->depth);
317       g_assert_not_reached ();
318     }
319   image->bits_per_pixel = image->depth;
320   image->byte_order = GDK_LSB_FIRST;
321   if (image->depth == 1)
322     image->bpl = ((width-1)/32 + 1)*4;
323   else
324     image->bpl = ((width*image->bpp - 1)/4 + 1)*4;
325
326   GDK_NOTE (MISC, g_print ("... = %#x mem = %p, bpl = %d\n",
327                            (guint) private->hbitmap, image->mem, image->bpl));
328
329   return image;
330 }
331
332 GdkImage*
333 gdk_image_new (GdkImageType  type,
334                GdkVisual    *visual,
335                gint          width,
336                gint          height)
337 {
338   return _gdk_image_new_for_depth (type, visual, width, height, -1);
339 }
340
341
342 GdkImage*
343 _gdk_win32_get_image (GdkDrawable *drawable,
344                       gint         x,
345                       gint         y,
346                       gint         width,
347                       gint         height)
348 {
349   GdkImage *image;
350   GdkImagePrivateWin32 *private;
351   GdkDrawableImplWin32 *impl;
352   HDC hdc, memdc;
353   struct {
354     BITMAPINFOHEADER bmiHeader;
355     union {
356       WORD bmiIndices[256];
357       DWORD bmiMasks[3];
358       RGBQUAD bmiColors[256];
359     } u;
360   } bmi;
361   HGDIOBJ oldbitmap1 = NULL, oldbitmap2;
362   UINT iUsage;
363   BITMAP bm;
364   int i;
365
366   g_return_val_if_fail (GDK_IS_DRAWABLE_IMPL_WIN32 (drawable), NULL);
367
368   GDK_NOTE (MISC, g_print ("_gdk_win32_get_image: %#x %dx%d@+%d+%d\n",
369                            (guint) GDK_DRAWABLE_IMPL_WIN32 (drawable)->handle,
370                            width, height, x, y));
371
372   impl = GDK_DRAWABLE_IMPL_WIN32 (drawable);
373
374   image = g_object_new (gdk_image_get_type (), NULL);
375   private = IMAGE_PRIVATE_DATA (image);
376
377   image->type = GDK_IMAGE_SHARED;
378   image->visual = gdk_drawable_get_visual (drawable);
379   image->width = width;
380   image->height = height;
381
382   /* This function is called both to blit from a window and from
383    * a pixmap.
384    */
385   if (GDK_IS_PIXMAP_IMPL_WIN32 (drawable))
386     {
387       if ((hdc = CreateCompatibleDC (NULL)) == NULL)
388         {
389           WIN32_GDI_FAILED ("CreateCompatibleDC");
390           g_free (image);
391           return NULL;
392         }
393       if ((oldbitmap1 = SelectObject (hdc, impl->handle)) == NULL)
394         {
395           WIN32_GDI_FAILED ("SelectObject");
396           DeleteDC (hdc);
397           g_free (image);
398           return NULL;
399         }
400       GetObject (impl->handle, sizeof (BITMAP), &bm);
401       GDK_NOTE (MISC,
402                 g_print ("gdk_image_get: bmWidth:%ld bmHeight:%ld bmWidthBytes:%ld bmBitsPixel:%d\n",
403                          bm.bmWidth, bm.bmHeight, bm.bmWidthBytes, bm.bmBitsPixel));
404       image->depth = bm.bmBitsPixel;
405       if (image->depth <= 8)
406         {
407           iUsage = DIB_PAL_COLORS;
408           for (i = 0; i < 256; i++)
409             bmi.u.bmiIndices[i] = i;
410         }
411       else
412         iUsage = DIB_RGB_COLORS;
413     }
414   else
415     {
416       if ((hdc = GetDC (impl->handle)) == NULL)
417         {
418           WIN32_GDI_FAILED ("GetDC");
419           g_free (image);
420           return NULL;
421         }
422       image->depth = gdk_visual_get_system ()->depth;
423       if (image->visual && image->visual->type == GDK_VISUAL_PSEUDO_COLOR)
424         {
425           iUsage = DIB_PAL_COLORS;
426           for (i = 0; i < 256; i++)
427             bmi.u.bmiIndices[i] = i;
428         }
429       else
430         iUsage = DIB_RGB_COLORS;
431     }
432
433   if ((memdc = CreateCompatibleDC (hdc)) == NULL)
434     {
435       WIN32_GDI_FAILED ("CreateCompatibleDC");
436       if (GDK_IS_PIXMAP_IMPL_WIN32 (drawable))
437         {
438           SelectObject (hdc, oldbitmap1);
439           if (!DeleteDC (hdc))
440             WIN32_GDI_FAILED ("DeleteDC");
441         }
442       else
443         {
444           if (!ReleaseDC (impl->handle, hdc))
445             WIN32_GDI_FAILED ("ReleaseDC");
446         }
447       g_free (image);
448       return NULL;
449     }
450
451   bmi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
452   bmi.bmiHeader.biWidth = width;
453   bmi.bmiHeader.biHeight = -height;
454   bmi.bmiHeader.biPlanes = 1;
455   bmi.bmiHeader.biBitCount = image->depth;
456   if (image->depth == 16)
457     {
458       bmi.bmiHeader.biCompression = BI_BITFIELDS;
459       if (image->visual == NULL)
460         {
461           /* XXX ??? Is it always this if depth==16 and a pixmap? Guess so. */
462           bmi.u.bmiMasks[0] = 0xf800;
463           bmi.u.bmiMasks[1] = 0x07e0;
464           bmi.u.bmiMasks[2] = 0x001f;
465         }
466       else
467         {
468           bmi.u.bmiMasks[0] = image->visual->red_mask;
469           bmi.u.bmiMasks[1] = image->visual->green_mask;
470           bmi.u.bmiMasks[2] = image->visual->blue_mask;
471         }
472     }
473   else
474     bmi.bmiHeader.biCompression = BI_RGB;
475   bmi.bmiHeader.biSizeImage = 0;
476   bmi.bmiHeader.biXPelsPerMeter =
477     bmi.bmiHeader.biYPelsPerMeter = 0;
478   bmi.bmiHeader.biClrUsed = 0;
479   bmi.bmiHeader.biClrImportant = 0;
480
481   if ((private->hbitmap = CreateDIBSection (hdc, (BITMAPINFO *) &bmi, iUsage,
482                                             &image->mem, NULL, 0)) == NULL)
483     {
484       WIN32_GDI_FAILED ("CreateDIBSection");
485       DeleteDC (memdc);
486       if (GDK_IS_PIXMAP (drawable))
487         {
488           SelectObject (hdc, oldbitmap1);
489           DeleteDC (hdc);
490         }
491       else
492         {
493           ReleaseDC (impl->handle, hdc);
494         }
495       g_free (image);
496       return NULL;
497     }
498
499   if ((oldbitmap2 = SelectObject (memdc, private->hbitmap)) == NULL)
500     {
501       WIN32_GDI_FAILED ("SelectObject");
502       DeleteObject (private->hbitmap);
503       DeleteDC (memdc);
504       if (GDK_IS_PIXMAP (drawable))
505         {
506           SelectObject (hdc, oldbitmap1);
507           DeleteDC (hdc);
508         }
509       else
510         {
511           ReleaseDC (impl->handle, hdc);
512         }
513       g_free (image);
514       return NULL;
515     }
516
517   if (!BitBlt (memdc, 0, 0, width, height, hdc, x, y, SRCCOPY))
518     {
519       WIN32_GDI_FAILED ("BitBlt");
520       SelectObject (memdc, oldbitmap2);
521       DeleteObject (private->hbitmap);
522       DeleteDC (memdc);
523       if (GDK_IS_PIXMAP (drawable))
524         {
525           SelectObject (hdc, oldbitmap1);
526           DeleteDC (hdc);
527         }
528       else
529         {
530           ReleaseDC (impl->handle, hdc);
531         }
532       g_free (image);
533       return NULL;
534     }
535
536   if (SelectObject (memdc, oldbitmap2) == NULL)
537     WIN32_GDI_FAILED ("SelectObject");
538
539   if (!DeleteDC (memdc))
540     WIN32_GDI_FAILED ("DeleteDC");
541
542   if (GDK_IS_PIXMAP_IMPL_WIN32 (drawable))
543     {
544       SelectObject (hdc, oldbitmap1);
545       DeleteDC (hdc);
546     }
547   else
548     {
549       ReleaseDC (impl->handle, hdc);
550     }
551
552   switch (image->depth)
553     {
554     case 1:
555     case 8:
556       image->bpp = 1;
557       break;
558     case 15:
559     case 16:
560       image->bpp = 2;
561       break;
562     case 24:
563       image->bpp = 3;
564       break;
565     case 32:
566       image->bpp = 4;
567       break;
568     default:
569       g_warning ("_gdk_win32_get_image: image->depth = %d", image->depth);
570       g_assert_not_reached ();
571     }
572   image->bits_per_pixel = image->depth;
573   image->byte_order = GDK_LSB_FIRST;
574   if (image->depth == 1)
575     image->bpl = ((width - 1)/32 + 1)*4;
576   else
577     image->bpl = ((width*image->bpp - 1)/4 + 1)*4;
578
579   GDK_NOTE (MISC, g_print ("... = %#x mem = %p, bpl = %d\n",
580                            (guint) private->hbitmap, image->mem, image->bpl));
581
582   return image;
583 }
584
585 GdkImage*
586 _gdk_win32_copy_to_image (GdkDrawable    *drawable,
587                           GdkImage       *image,
588                           gint            src_x,
589                           gint            src_y,
590                           gint            dest_x,
591                           gint            dest_y,
592                           gint            width,
593                           gint            height)
594 {
595   GdkImagePrivateWin32 *private;
596   GdkDrawableImplWin32 *impl;
597   GdkVisual *visual;
598   GdkGC *gc = NULL;
599   gboolean ok = TRUE, is_window_impl;
600   HBITMAP holdbmp = NULL;
601   HDC src_dc = NULL, dest_dc = NULL;
602   
603   g_return_val_if_fail (GDK_IS_DRAWABLE_IMPL_WIN32 (drawable), NULL);
604   g_return_val_if_fail (image != NULL || (dest_x == 0 && dest_y == 0), NULL);
605
606   visual = gdk_drawable_get_visual (drawable);
607   impl = GDK_DRAWABLE_IMPL_WIN32 (drawable);
608   is_window_impl = GDK_IS_WINDOW_IMPL_WIN32 (drawable);
609   
610   if (!image && !is_window_impl)
611     return _gdk_win32_get_image (drawable, src_x, src_y, width, height);
612
613   if (!image)
614     image = _gdk_image_new_for_depth (GDK_IMAGE_FASTEST, visual, width, height, -1);
615
616   private = IMAGE_PRIVATE_DATA (image);
617
618   if (is_window_impl)
619     src_dc = GetDC (impl->handle);
620   else
621     {
622        gc = gdk_gc_new (drawable);
623        src_dc = gdk_win32_hdc_get (drawable, gc, 0);
624     }
625   ok = !!src_dc;
626
627   if (ok)
628     {
629       dest_dc = CreateCompatibleDC (NULL);
630       ok = !!dest_dc;
631     }
632
633   if (ok)
634     {
635       holdbmp = SelectObject (dest_dc, private->hbitmap);
636       ok = !!holdbmp;
637     }
638
639   if (ok && !BitBlt (dest_dc, dest_x, dest_y, width, height,
640                      src_dc, src_x, src_y, SRCCOPY))
641     WIN32_GDI_FAILED ("BitBlt");
642
643   if (is_window_impl)
644     {
645       if (src_dc && !ReleaseDC (impl->handle, src_dc))
646         WIN32_GDI_FAILED ("ReleaseDC");
647     }
648   else
649     {
650       gdk_win32_hdc_release (drawable, gc, 0);
651       g_object_unref (gc);
652     }
653
654   if (dest_dc)
655     {
656       if (holdbmp)
657         SelectObject (dest_dc, holdbmp);
658       if (!DeleteDC (dest_dc))
659         WIN32_GDI_FAILED ("DeleteDC");
660     }
661   g_return_val_if_fail (ok, image);
662
663   return image;
664 }
665
666 guint32
667 gdk_image_get_pixel (GdkImage *image,
668                      gint      x,
669                      gint      y)
670 {
671   guint32 pixel = 0;
672
673   g_return_val_if_fail (GDK_IS_IMAGE (image), 0);
674
675   if (!(x >= 0 && x < image->width && y >= 0 && y < image->height))
676       return 0;
677
678   if (image->depth == 1)
679     pixel = (((char *) image->mem)[y * image->bpl + (x >> 3)] & (1 << (7 - (x & 0x7)))) != 0;
680   else
681     {
682       guchar *pixelp = (guchar *) image->mem + y * image->bpl + x * image->bpp;
683       
684       switch (image->bpp)
685         {
686         case 1:
687           pixel = *pixelp;
688           break;
689
690         /* Windows is always LSB, no need to check image->byte_order. */
691         case 2:
692           pixel = pixelp[0] | (pixelp[1] << 8);
693           break;
694
695         case 3:
696           pixel = pixelp[0] | (pixelp[1] << 8) | (pixelp[2] << 16);
697           break;
698
699         case 4:
700           pixel = pixelp[0] | (pixelp[1] << 8) | (pixelp[2] << 16);
701           break;
702
703         default:
704           g_warning ("gdk_image_get_pixel(): bpp = %d", image->bpp);
705           g_assert_not_reached ();
706         }
707     }
708
709   return pixel;
710 }
711
712 void
713 gdk_image_put_pixel (GdkImage *image,
714                      gint       x,
715                      gint       y,
716                      guint32    pixel)
717 {
718   g_return_if_fail (image != NULL);
719
720   if  (!(x >= 0 && x < image->width && y >= 0 && y < image->height))
721     return;
722
723   if (image->depth == 1)
724     if (pixel & 1)
725       ((guchar *) image->mem)[y * image->bpl + (x >> 3)] |= (1 << (7 - (x & 0x7)));
726     else
727       ((guchar *) image->mem)[y * image->bpl + (x >> 3)] &= ~(1 << (7 - (x & 0x7)));
728   else
729     {
730       guchar *pixelp = (guchar *) image->mem + y * image->bpl + x * image->bpp;
731       
732       /* Windows is always LSB, no need to check image->byte_order. */
733       switch (image->bpp)
734         {
735         case 4:
736           pixelp[3] = 0;
737         case 3:
738           pixelp[2] = ((pixel >> 16) & 0xFF);
739         case 2:
740           pixelp[1] = ((pixel >> 8) & 0xFF);
741         case 1:
742           pixelp[0] = (pixel & 0xFF);
743         }
744     }
745 }
746
747 static void
748 gdk_win32_image_destroy (GdkImage *image)
749 {
750   GdkImagePrivateWin32 *private;
751
752   g_return_if_fail (GDK_IS_IMAGE (image));
753
754   private = IMAGE_PRIVATE_DATA (image);
755
756   if (private == NULL) /* This means that _gdk_image_exit() destroyed the
757                         * image already, and now we're called a second
758                         * time from _finalize()
759                         */
760     return;
761   
762   GDK_NOTE (MISC, g_print ("gdk_win32_image_destroy: %#x\n",
763                            (guint) private->hbitmap));
764   
765   switch (image->type)
766     {
767     case GDK_IMAGE_SHARED:
768       if (!DeleteObject (private->hbitmap))
769         WIN32_GDI_FAILED ("DeleteObject");
770       break;
771
772     default:
773       g_assert_not_reached ();
774     }
775
776   g_free (private);
777   image->windowing_data = NULL;
778 }
779
780 gint
781 _gdk_windowing_get_bits_for_depth (gint depth)
782 {
783   if ((1 == depth) || (8 == depth) || (16 == depth) || 
784       (24 == depth) || (32 == depth))
785     return depth;
786   else if (15 == depth)
787     return 16;
788   else
789     g_assert_not_reached ();
790
791   return 0;
792 }