]> Pileus Git - ~andy/gtk/blob - gdk/win32/gdkimage-win32.c
Change GDK_WINDOWING_WIN32 usage to #ifdef also here.
[~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 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.
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  * Library General Public License for more details.
13  *
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.
18  */
19
20 /*
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/. 
25  */
26
27 #include "config.h"
28
29 #include "gdk.h"                /* For gdk_error_trap_* / gdk_flush_* */
30 #include "gdkimage.h"
31 #include "gdkprivate.h"
32
33 static void gdk_image_put_normal (GdkDrawable *drawable,
34                                   GdkGC       *gc,
35                                   GdkImage    *image,
36                                   gint         xsrc,
37                                   gint         ysrc,
38                                   gint         xdest,
39                                   gint         ydest,
40                                   gint         width,
41                                   gint         height);
42 static GList *image_list = NULL;
43
44 void
45 gdk_image_exit (void)
46 {
47   GdkImage *image;
48
49   while (image_list)
50     {
51       image = image_list->data;
52       gdk_image_destroy (image);
53     }
54 }
55
56 GdkImage *
57 gdk_image_new_bitmap (GdkVisual *visual, gpointer data, gint w, gint h)
58 /*
59  * Desc: create a new bitmap image
60  */
61 {
62   Visual *xvisual;
63   GdkImage *image;
64   GdkImagePrivate *private;
65   struct {
66     BITMAPINFOHEADER bmiHeader;
67     union {
68       WORD bmiIndices[2];
69       RGBQUAD bmiColors[2];
70     } u;
71   } bmi;
72   char *bits;
73   int bpl = (w-1)/8 + 1;
74   int bpl32 = ((w-1)/32 + 1)*4;
75
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;
81   image->width = w;
82   image->height = h;
83   image->depth = 1;
84   xvisual = ((GdkVisualPrivate*) visual)->xvisual;
85
86   GDK_NOTE (MISC, g_print ("gdk_image_new_bitmap: %dx%d\n", w, h));
87   
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;
99   
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;
104
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;
109   
110   private->ximage = CreateDIBSection (gdk_DC, (BITMAPINFO *) &bmi,
111                                       DIB_RGB_COLORS, &bits, NULL, 0);
112   if (bpl != bpl32)
113     {
114       /* Win32 expects scanlines in DIBs to be 32 bit aligned */
115       int i;
116       for (i = 0; i < h; i++)
117         memmove (bits + i*bpl32, ((char *) data) + i*bpl, bpl);
118     }
119   else
120     memmove (bits, data, bpl*h);
121   image->mem = bits;
122   image->bpl = bpl32;
123   image->byte_order = GDK_MSB_FIRST;
124
125   image->bpp = 1;
126   return(image);
127 } /* gdk_image_new_bitmap() */
128
129 void
130 gdk_image_init (void)
131 {
132 }
133
134 static GdkImage*
135 gdk_image_new_with_depth (GdkImageType  type,
136                           GdkVisual    *visual,
137                           gint          width,
138                           gint          height,
139                           gint          depth)
140 {
141   GdkImage *image;
142   GdkImagePrivate *private;
143   Visual *xvisual;
144   struct {
145     BITMAPINFOHEADER bmiHeader;
146     union {
147       WORD bmiIndices[256];
148       DWORD bmiMasks[3];
149       RGBQUAD bmiColors[256];
150     } u;
151   } bmi;
152   UINT iUsage;
153   int i;
154
155   if (type == GDK_IMAGE_FASTEST || type == GDK_IMAGE_NORMAL)
156     type = GDK_IMAGE_SHARED;
157
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" :
162                              "???"))));
163
164   private = g_new (GdkImagePrivate, 1);
165   image = (GdkImage*) private;
166
167   private->image_put = NULL;
168
169   image->type = type;
170   image->visual = visual;
171   image->width = width;
172   image->height = height;
173   image->depth = depth;
174   
175   xvisual = ((GdkVisualPrivate*) visual)->xvisual;
176   
177   private->image_put = gdk_image_put_normal;
178       
179   bmi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
180   bmi.bmiHeader.biWidth = width;
181   bmi.bmiHeader.biHeight = -height;
182   bmi.bmiHeader.biPlanes = 1;
183   if (depth == 15)
184     bmi.bmiHeader.biBitCount = 16;
185   else
186     bmi.bmiHeader.biBitCount = depth;
187 #if 1
188   if (depth == 16)
189     bmi.bmiHeader.biCompression = BI_BITFIELDS;
190   else
191 #endif
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;
198
199   if (image->visual->type == GDK_VISUAL_PSEUDO_COLOR)
200     {
201       iUsage = DIB_PAL_COLORS;
202       for (i = 0; i < 256; i++)
203         bmi.u.bmiIndices[i] = i;
204     }
205   else
206     {
207       if (depth == 1)
208         {
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;
213
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;
218
219         }
220 #if 1
221       else if (depth == 16)
222         {
223           bmi.u.bmiMasks[0] = visual->red_mask;
224           bmi.u.bmiMasks[1] = visual->green_mask;
225           bmi.u.bmiMasks[2] = visual->blue_mask;
226         }
227 #endif
228       iUsage = DIB_RGB_COLORS;
229     }
230
231   private->ximage =
232     CreateDIBSection (gdk_DC, (BITMAPINFO *) &bmi, iUsage,
233                       &image->mem, NULL, 0);
234
235   if (private->ximage == NULL)
236     {
237       g_warning ("gdk_image_new_with_depth: CreateDIBSection failed");
238       g_free (image);
239       return NULL;
240     }
241
242   switch (depth)
243     {
244     case 1:
245     case 8:
246       image->bpp = 1;
247       break;
248     case 15:
249     case 16:
250       image->bpp = 2;
251       break;
252     case 24:
253       image->bpp = 3;
254       break;
255     case 32:
256       image->bpp = 4;
257       break;
258     default:
259       g_warning ("gdk_image_new_with_depth: depth = %d", depth);
260       g_assert_not_reached ();
261     }
262   image->byte_order = GDK_LSB_FIRST;
263   if (depth == 1)
264     image->bpl = ((width-1)/32 + 1)*4;
265   else
266     image->bpl = ((width*image->bpp - 1)/4 + 1)*4;
267
268   GDK_NOTE (MISC, g_print ("... = %#x mem = %#x, bpl = %d\n",
269                            private->ximage, image->mem, image->bpl));
270
271   return image;
272 }
273
274 GdkImage*
275 gdk_image_new (GdkImageType  type,
276                GdkVisual    *visual,
277                gint          width,
278                gint          height)
279 {
280   GdkVisualPrivate *visual_private = (GdkVisualPrivate *) visual;
281   return gdk_image_new_with_depth (type, visual, width, height,
282                                    visual_private->xvisual->bitspixel);
283 }
284
285 GdkImage*
286 gdk_image_bitmap_new (GdkImageType  type,
287                       GdkVisual    *visual,
288                       gint          width,
289                       gint          height)
290 {
291   return gdk_image_new_with_depth (type, visual, width, height, 1);
292 }
293
294 GdkImage*
295 gdk_image_get (GdkWindow *window,
296                gint       x,
297                gint       y,
298                gint       width,
299                gint       height)
300 {
301   GdkImage *image;
302   GdkImagePrivate *private;
303   GdkWindowPrivate *win_private;
304   HDC hdc, memdc;
305   struct {
306     BITMAPINFOHEADER bmiHeader;
307     union {
308       WORD bmiIndices[256];
309       DWORD bmiMasks[3];
310       RGBQUAD bmiColors[256];
311     } u;
312   } bmi;
313   HGDIOBJ oldbitmap1, oldbitmap2;
314   UINT iUsage;
315   BITMAP bm;
316   int i;
317
318   g_return_val_if_fail (window != NULL, NULL);
319
320   win_private = (GdkWindowPrivate *) window;
321   if (win_private->destroyed)
322     return NULL;
323
324   GDK_NOTE (MISC, g_print ("gdk_image_get: %#x %dx%d@+%d+%d\n",
325                            win_private->xwindow, width, height, x, y));
326
327   private = g_new (GdkImagePrivate, 1);
328   image = (GdkImage*) private;
329
330   private->image_put = gdk_image_put_normal;
331
332   image->type = GDK_IMAGE_SHARED;
333   image->visual = gdk_window_get_visual (window);
334   image->width = width;
335   image->height = height;
336
337   /* This function is called both to blit from a window and from
338    * a pixmap.
339    */
340   if (win_private->window_type == GDK_WINDOW_PIXMAP)
341     {
342       if ((hdc = CreateCompatibleDC (NULL)) == NULL)
343         {
344           g_warning ("gdk_image_get: CreateCompatibleDC #1 failed");
345           g_free (image);
346           return NULL;
347         }
348       if ((oldbitmap1 = SelectObject (hdc, win_private->xwindow)) == NULL)
349         {
350           g_warning ("gdk_image_get: SelectObject #1 failed");
351           DeleteDC (hdc);
352           g_free (image);
353           return NULL;
354         }
355       GetObject (win_private->xwindow, sizeof (BITMAP), &bm);
356       GDK_NOTE (MISC,
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)
361         {
362           iUsage = DIB_PAL_COLORS;
363           for (i = 0; i < 256; i++)
364             bmi.u.bmiIndices[i] = i;
365         }
366       else
367         iUsage = DIB_RGB_COLORS;
368     }
369   else
370     {
371       if ((hdc = GetDC (win_private->xwindow)) == NULL)
372         {
373           g_warning ("gdk_image_get: GetDC failed");
374           g_free (image);
375           return NULL;
376         }
377       image->depth = gdk_visual_get_system ()->depth;
378       if (image->visual->type == GDK_VISUAL_PSEUDO_COLOR)
379         {
380           iUsage = DIB_PAL_COLORS;
381           for (i = 0; i < 256; i++)
382             bmi.u.bmiIndices[i] = i;
383         }
384       else
385         iUsage = DIB_RGB_COLORS;
386     }
387
388   if ((memdc = CreateCompatibleDC (hdc)) == NULL)
389     {
390       g_warning ("gdk_image_get: CreateCompatibleDC #2 failed");
391       if (win_private->window_type == GDK_WINDOW_PIXMAP)
392         {
393           SelectObject (hdc, oldbitmap1);
394           DeleteDC (hdc);
395         }
396       else
397         {
398           ReleaseDC (win_private->xwindow, hdc);
399         }
400       g_free (image);
401       return NULL;
402     }
403
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)
410     {
411       bmi.bmiHeader.biCompression = BI_BITFIELDS;
412       if (image->visual == NULL)
413         {
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;
418         }
419       else
420         {
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;
424         }
425     }
426   else
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;
433
434   if ((private->ximage =
435        CreateDIBSection (hdc, (BITMAPINFO *) &bmi, iUsage,
436                          &image->mem, NULL, 0)) == NULL)
437     {
438       g_warning ("gdk_image_get: CreateDIBSection failed");
439       DeleteDC (memdc);
440       if (win_private->window_type == GDK_WINDOW_PIXMAP)
441         {
442           SelectObject (hdc, oldbitmap1);
443           DeleteDC (hdc);
444         }
445       else
446         {
447           ReleaseDC (win_private->xwindow, hdc);
448         }
449       g_free (image);
450       return NULL;
451     }
452
453   if ((oldbitmap2 = SelectObject (memdc, private->ximage)) == NULL)
454     {
455       g_warning ("gdk_image_get: SelectObject #2 failed");
456       DeleteObject (private->ximage);
457       DeleteDC (memdc);
458       if (win_private->window_type == GDK_WINDOW_PIXMAP)
459         {
460           SelectObject (hdc, oldbitmap1);
461           DeleteDC (hdc);
462         }
463       else
464         {
465           ReleaseDC (win_private->xwindow, hdc);
466         }
467       g_free (image);
468       return NULL;
469     }
470
471   if (!BitBlt (memdc, 0, 0, width, height, hdc, x, y, SRCCOPY))
472     {
473       g_warning ("gdk_image_get: BitBlt failed");
474       SelectObject (memdc, oldbitmap2);
475       DeleteObject (private->ximage);
476       DeleteDC (memdc);
477       if (win_private->window_type == GDK_WINDOW_PIXMAP)
478         {
479           SelectObject (hdc, oldbitmap1);
480           DeleteDC (hdc);
481         }
482       else
483         {
484           ReleaseDC (win_private->xwindow, hdc);
485         }
486       g_free (image);
487       return NULL;
488     }
489
490   if (SelectObject (memdc, oldbitmap2) == NULL)
491     g_warning ("gdk_image_get: SelectObject #3 failed");
492
493   if (!DeleteDC (memdc))
494     g_warning ("gdk_image_get: DeleteDC failed");
495
496   if (win_private->window_type == GDK_WINDOW_PIXMAP)
497     {
498       SelectObject (hdc, oldbitmap1);
499       DeleteDC (hdc);
500     }
501   else
502     {
503       ReleaseDC (win_private->xwindow, hdc);
504     }
505
506   switch (image->depth)
507     {
508     case 1:
509     case 8:
510       image->bpp = 1;
511       break;
512     case 15:
513     case 16:
514       image->bpp = 2;
515       break;
516     case 24:
517       image->bpp = 3;
518       break;
519     case 32:
520       image->bpp = 4;
521       break;
522     default:
523       g_warning ("gdk_image_get: image->depth = %d", image->depth);
524       g_assert_not_reached ();
525     }
526   image->byte_order = GDK_LSB_FIRST;
527   if (image->depth == 1)
528     image->bpl = ((width - 1)/32 + 1)*4;
529   else
530     image->bpl = ((width*image->bpp - 1)/4 + 1)*4;
531
532   GDK_NOTE (MISC, g_print ("... = %#x mem = %#x, bpl = %d\n",
533                            private->ximage, image->mem, image->bpl));
534
535   return image;
536 }
537
538 guint32
539 gdk_image_get_pixel (GdkImage *image,
540                      gint x,
541                      gint y)
542 {
543   guint32 pixel;
544   GdkImagePrivate *private;
545
546   g_return_val_if_fail (image != NULL, 0);
547
548   private = (GdkImagePrivate *) image;
549
550   g_return_val_if_fail (x >= 0 && x < image->width
551                         && y >= 0 && y < image->height, 0);
552
553   if (image->depth == 1)
554     pixel = (((char *) image->mem)[y * image->bpl + (x >> 3)] & (1 << (7 - (x & 0x7)))) != 0;
555   else
556     {
557       guchar *pixelp = (guchar *) image->mem + y * image->bpl + x * image->bpp;
558       
559       switch (image->bpp)
560         {
561         case 1:
562           pixel = *pixelp;
563           break;
564
565         /* Windows is always LSB, no need to check image->byte_order. */
566         case 2:
567           pixel = pixelp[0] | (pixelp[1] << 8);
568           break;
569
570         case 3:
571           pixel = pixelp[0] | (pixelp[1] << 8) | (pixelp[2] << 16);
572           break;
573
574         case 4:
575           pixel = pixelp[0] | (pixelp[1] << 8) | (pixelp[2] << 16);
576           break;
577         }
578     }
579
580   return pixel;
581 }
582
583 void
584 gdk_image_put_pixel (GdkImage *image,
585                      gint x,
586                      gint y,
587                      guint32 pixel)
588 {
589   GdkImagePrivate *private;
590
591   g_return_if_fail (image != NULL);
592
593   private = (GdkImagePrivate *) image;
594
595   g_return_if_fail (x >= 0 && x < image->width && y >= 0 && y < image->height);
596
597   if (image->depth == 1)
598     if (pixel & 1)
599       ((guchar *) image->mem)[y * image->bpl + (x >> 3)] |= (1 << (7 - (x & 0x7)));
600     else
601       ((guchar *) image->mem)[y * image->bpl + (x >> 3)] &= ~(1 << (7 - (x & 0x7)));
602   else
603     {
604       guchar *pixelp = (guchar *) image->mem + y * image->bpl + x * image->bpp;
605       
606       /* Windows is always LSB, no need to check image->byte_order. */
607       switch (image->bpp)
608         {
609         case 4:
610           pixelp[3] = 0;
611         case 3:
612           pixelp[2] = ((pixel >> 16) & 0xFF);
613         case 2:
614           pixelp[1] = ((pixel >> 8) & 0xFF);
615         case 1:
616           pixelp[0] = (pixel & 0xFF);
617         }
618     }
619 }
620
621 void
622 gdk_image_destroy (GdkImage *image)
623 {
624   GdkImagePrivate *private;
625
626   g_return_if_fail (image != NULL);
627
628   private = (GdkImagePrivate*) image;
629
630   GDK_NOTE (MISC, g_print ("gdk_image_destroy: %#x%s\n",
631                            private->ximage,
632                            (image->type == GDK_IMAGE_SHARED_PIXMAP ?
633                             " (shared pixmap)" : "")));
634   
635   switch (image->type)
636     {
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.
641                                  */
642
643     case GDK_IMAGE_SHARED:
644       if (!DeleteObject (private->ximage))
645         g_warning ("gdk_image_destroy: DeleteObject failed");
646       break;
647
648     default:
649       g_assert_not_reached ();
650     }
651
652   g_free (image);
653 }
654
655 static void
656 gdk_image_put_normal (GdkDrawable *drawable,
657                       GdkGC       *gc,
658                       GdkImage    *image,
659                       gint         xsrc,
660                       gint         ysrc,
661                       gint         xdest,
662                       gint         ydest,
663                       gint         width,
664                       gint         height)
665 {
666   GdkWindowPrivate *drawable_private;
667   GdkImagePrivate *image_private;
668   GdkGCPrivate *gc_private;
669   HDC hdc;
670   GdkColormapPrivate *colormap_private;
671
672   g_return_if_fail (drawable != NULL);
673   g_return_if_fail (image != NULL);
674   g_return_if_fail (gc != NULL);
675
676   drawable_private = (GdkWindowPrivate*) drawable;
677   if (drawable_private->destroyed)
678     return;
679   image_private = (GdkImagePrivate*) image;
680   gc_private = (GdkGCPrivate*) gc;
681
682   /* The image can in fact be "shared", so don't test */
683
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)
687     {
688       DIBSECTION ds;
689       static struct {
690         BITMAPINFOHEADER bmiHeader;
691         WORD bmiIndices[256];
692       } bmi;
693       static gboolean bmi_inited = FALSE;
694       int i;
695
696       if (!bmi_inited)
697         {
698           for (i = 0; i < 256; i++)
699             bmi.bmiIndices[i] = i;
700           bmi_inited = TRUE;
701         }
702
703       if (GetObject (image_private->ximage, sizeof (DIBSECTION),
704                      &ds) != sizeof (DIBSECTION))
705         {
706           g_warning ("gdk_image_put_normal: GetObject failed");
707         }
708 #if 0
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);
715 #endif
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.
720        */
721       if (SetDIBitsToDevice (hdc,
722                              xdest, ydest,
723                              width, height,
724                              xsrc, (-ds.dsBmih.biHeight)-height-ysrc,
725                              0, -ds.dsBmih.biHeight,
726                              ds.dsBm.bmBits,
727                              (CONST BITMAPINFO *) &bmi,
728                              DIB_PAL_COLORS) == 0)
729         g_warning ("SetDIBitsToDevice failed");
730     }
731   else
732     {
733       HDC memdc;
734       HGDIOBJ oldbitmap;
735
736       if ((memdc = CreateCompatibleDC (hdc)) == NULL)
737         {
738           g_warning ("gdk_image_put_normal: CreateCompatibleDC failed");
739           gdk_gc_postdraw (drawable_private, gc_private);
740           return;
741         }
742
743       if ((oldbitmap = SelectObject (memdc, image_private->ximage)) == NULL)
744         {
745           g_warning ("gdk_image_put_normal: SelectObject #1 failed");
746           gdk_gc_postdraw (drawable_private, gc_private);
747           return;
748         }
749       if (!BitBlt (hdc, xdest, ydest, width, height,
750                    memdc, xsrc, ysrc, SRCCOPY))
751         g_warning ("gdk_image_put_normal: BitBlt failed");
752
753       if (SelectObject (memdc, oldbitmap) == NULL)
754         g_warning ("gdk_image_put_normal: SelectObject #2 failed");
755
756       if (!DeleteDC (memdc))
757         g_warning ("gdk_image_put_normal: DeleteDC failed");
758     }
759   gdk_gc_postdraw (drawable_private, gc_private);
760 }