Release 950522
[wine] / objects / dib.c
1 /*
2  * GDI device-independent bitmaps
3  *
4  * Copyright 1993,1994  Alexandre Julliard
5  */
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <X11/Xlib.h>
10 #include <X11/Xutil.h>
11 #include "dc.h"
12 #include "bitmap.h"
13 #include "palette.h"
14 #include "icon.h"
15 #include "stackframe.h"
16 #include "stddebug.h"
17 #include "color.h"
18 #include "debug.h"
19
20
21 /***********************************************************************
22  *           DIB_GetImageWidthBytes
23  *
24  * Return the width of an X image in bytes
25  */
26 int DIB_GetImageWidthBytes( int width, int depth )
27 {
28     int words;
29
30     switch(depth)
31     {
32     case 1:  words = (width + 31) / 32; break;
33     case 4:  words = (width + 7) / 8; break;
34     case 8:  words = (width + 3) / 4; break;
35     case 15:
36     case 16: words = (width + 1) / 2; break;
37     case 24: words = width; break;
38     default:
39         fprintf(stderr, "DIB: unsupported depth %d.\n", depth );
40         exit(1);
41     }
42     return 4 * words;
43 }
44
45
46 /***********************************************************************
47  *           DIB_BitmapInfoSize
48  *
49  * Return the size of the bitmap info structure.
50  */
51 int DIB_BitmapInfoSize( BITMAPINFO * info, WORD coloruse )
52 {
53     int size = info->bmiHeader.biClrUsed;
54     if (!size && (info->bmiHeader.biBitCount != 24))
55         size = 1 << info->bmiHeader.biBitCount;
56     if (coloruse == DIB_RGB_COLORS) 
57         size = info->bmiHeader.biSize + size * sizeof(RGBQUAD);
58     else
59         size = info->bmiHeader.biSize + size * sizeof(WORD);
60     return size;
61 }
62
63
64 /***********************************************************************
65  *           DIB_DIBmpToImage
66  *
67  * Create an XImage pointing to the bitmap data.
68  */
69 static XImage *DIB_DIBmpToImage( BITMAPINFOHEADER * bmp, void * bmpData )
70 {
71     extern void _XInitImageFuncPtrs( XImage* );
72     XImage * image;
73
74     image = XCreateImage(display, DefaultVisualOfScreen( screen ),
75                          bmp->biBitCount, ZPixmap, 0, bmpData,
76                          bmp->biWidth, bmp->biHeight, 32,
77                          DIB_GetImageWidthBytes(bmp->biWidth,bmp->biBitCount));
78     if (!image) return 0;
79     image->byte_order = MSBFirst;
80     image->bitmap_bit_order = MSBFirst;
81     image->bitmap_unit = 16;
82     _XInitImageFuncPtrs(image);
83     return image;
84 }
85
86
87 /***********************************************************************
88  *           DIB_SetImageBits_1
89  *
90  * SetDIBits for a 1-bit deep DIB.
91  */
92 static void DIB_SetImageBits_1( WORD lines, BYTE *bits, WORD width,
93                                 int *colors, XImage *bmpImage )
94 {
95     WORD i, x;
96     BYTE pad, pix;
97
98     if (!(width & 31)) pad = 0;
99     else pad = ((32 - (width & 31)) + 7) / 8;
100
101     while (lines--)
102     {
103         for (i = width/8, x = 0; (i > 0); i--)
104         {
105             pix = *bits++;
106             XPutPixel( bmpImage, x++, lines, colors[pix >> 7] );
107             XPutPixel( bmpImage, x++, lines, colors[(pix >> 6) & 1] );
108             XPutPixel( bmpImage, x++, lines, colors[(pix >> 5) & 1] );
109             XPutPixel( bmpImage, x++, lines, colors[(pix >> 4) & 1] );
110             XPutPixel( bmpImage, x++, lines, colors[(pix >> 3) & 1] );
111             XPutPixel( bmpImage, x++, lines, colors[(pix >> 2) & 1] );
112             XPutPixel( bmpImage, x++, lines, colors[(pix >> 1) & 1] );
113             XPutPixel( bmpImage, x++, lines, colors[pix & 1] );
114         }
115         pix = *bits;
116         switch(width & 7)
117         {
118         case 7: XPutPixel( bmpImage, x++, lines, colors[pix >> 7] ); pix <<= 1;
119         case 6: XPutPixel( bmpImage, x++, lines, colors[pix >> 7] ); pix <<= 1;
120         case 5: XPutPixel( bmpImage, x++, lines, colors[pix >> 7] ); pix <<= 1;
121         case 4: XPutPixel( bmpImage, x++, lines, colors[pix >> 7] ); pix <<= 1;
122         case 3: XPutPixel( bmpImage, x++, lines, colors[pix >> 7] ); pix <<= 1;
123         case 2: XPutPixel( bmpImage, x++, lines, colors[pix >> 7] ); pix <<= 1;
124         case 1: XPutPixel( bmpImage, x++, lines, colors[pix >> 7] );
125         }
126         bits += pad;
127     }
128 }
129
130
131 /***********************************************************************
132  *           DIB_SetImageBits_4
133  *
134  * SetDIBits for a 4-bit deep DIB.
135  */
136 static void DIB_SetImageBits_4( WORD lines, BYTE *bits, WORD width,
137                                 int *colors, XImage *bmpImage )
138 {
139     WORD i, x;
140     BYTE pad;
141
142     if (!(width & 7)) pad = 0;
143     else pad = ((8 - (width & 7)) + 1) / 2;
144
145     while (lines--)
146     {
147         for (i = width/2, x = 0; i > 0; i--)
148         {
149             BYTE pix = *bits++;
150             XPutPixel( bmpImage, x++, lines, colors[pix >> 4] );
151             XPutPixel( bmpImage, x++, lines, colors[pix & 0x0f] );
152         }
153         if (width & 1) XPutPixel( bmpImage, x, lines, colors[*bits >> 4] );
154         bits += pad;
155     }
156 }
157
158 #define check_xy(x,y) \
159         if (x > width) { \
160                 x = 0; \
161                 if (lines) \
162                         lines--; \
163         }
164
165 /***********************************************************************
166  *           DIB_SetImageBits_RLE4
167  *
168  * SetDIBits for a 4-bit deep compressed DIB.
169  */
170 static void DIB_SetImageBits_RLE4( WORD lines, BYTE *bits, WORD width,
171                                    int *colors, XImage *bmpImage )
172 {
173         int x = 0, c, length;
174         BYTE *begin = bits;
175         
176         lines--;
177         while (1) {
178                 length = *bits++;
179                 if (length) {   /* encoded */
180                         c = *bits++;
181                         while (length--) {
182                                 XPutPixel(bmpImage, x++, lines, colors[c >> 4]);
183                                 check_xy(x, y);
184                                 if (length) {
185                                         length--;
186                                         XPutPixel(bmpImage, x++, lines, colors[c & 0xf]);
187                                         check_xy(x, y);
188                                 }
189                         }
190                 } else {
191                         length = *bits++;
192                         switch (length) {
193                                 case 0: /* eol */
194                                         x = 0;
195                                         lines--;
196                                         continue;
197
198                                 case 1: /* eopicture */
199                                         return;
200
201                                 case 2: /* delta */
202                                         x += *bits++;
203                                         lines -= *bits++;
204                                         continue;
205
206                                 default: /* absolute */
207                                         while (length--) {
208                                                 c = *bits++;
209                                                 XPutPixel(bmpImage, x++, lines, colors[c >> 4]);
210                                                 check_xy(x, y);
211                                                 if (length) {
212                                                         length--;
213                                                         XPutPixel(bmpImage, x++, lines, colors[c & 0xf]);
214                                                         check_xy(x, y);
215                                                 }
216                                         }
217                                         if ((bits - begin) & 1)
218                                                 bits++;
219                         }
220                 }
221         }
222 }
223
224 /***********************************************************************
225  *           DIB_SetImageBits_8
226  *
227  * SetDIBits for an 8-bit deep DIB.
228  */
229 static void DIB_SetImageBits_8( WORD lines, BYTE *bits, WORD width,
230                                 int *colors, XImage *bmpImage )
231 {
232     WORD x;
233     BYTE pad = (4 - (width & 3)) & 3;
234
235     while (lines--)
236     {
237         for (x = 0; x < width; x++)
238             XPutPixel( bmpImage, x, lines, colors[*bits++] );
239         bits += pad;
240     }
241 }
242
243 /***********************************************************************
244  *            DIB_SetImageBits_RLE8
245  *
246  * SetDIBits for an 8-bit deep compressed DIB.
247  *
248  * This function rewritten 941113 by James Youngman.  WINE blew out when I
249  * first ran it because my desktop wallpaper is a (large) RLE8 bitmap.  
250  *
251  * This was because the algorithm assumed that all RLE8 bitmaps end with the  
252  * 'End of bitmap' escape code.  This code is very much laxer in what it
253  * allows to end the expansion.  Possibly too lax.  See the note by 
254  * case RleDelta.  BTW, MS's documentation implies that a correct RLE8
255  * bitmap should end with RleEnd, but on the other hand, software exists 
256  * that produces ones that don't and Windows 3.1 doesn't complain a bit
257  * about it.
258  *
259  * (No) apologies for my English spelling.  [Emacs users: c-indent-level=4].
260  *                      James A. Youngman <mbcstjy@afs.man.ac.uk>
261  *                                              [JAY]
262  */
263
264 enum Rle8_EscapeCodes           
265 {
266   /* 
267    * Apologies for polluting your file's namespace...
268    */
269   RleEol        = 0,            /* End of line */
270   RleEnd        = 1,            /* End of bitmap */
271   RleDelta      = 2             /* Delta */
272 };
273   
274 static void DIB_SetImageBits_RLE8(WORD lines, 
275                                   BYTE *bits, 
276                                   WORD width,
277                                   int *colors, 
278                                   XImage *bmpImage)
279 {
280     int x;                      /* X-positon on each line.  Increases. */
281     int line;                   /* Line #.  Starts at lines-1, decreases */
282     BYTE *pIn = bits;           /* Pointer to current position in bits */
283     BYTE length;                /* The length pf a run */
284     BYTE color_index;           /* index into colors[] as read from bits */
285     BYTE escape_code;           /* See enum Rle8_EscapeCodes.*/
286     WORD color;                 /* value of colour[color_index] */
287     
288     if (lines == 0)             /* Let's hope this doesn't happen. */
289       return;
290     
291     /*
292      * Note that the bitmap data is stored by Windows starting at the
293      * bottom line of the bitmap and going upwards.  Within each line,
294      * the data is stored left-to-right.  That's the reason why line
295      * goes from lines-1 to 0.                  [JAY]
296      */
297     
298     x = 0;
299     line = lines-1;
300     do
301       {
302           length = *pIn++;
303           
304           /* 
305            * If the length byte is not zero (which is the escape value),
306            * We have a run of length pixels all the same colour.  The colour 
307            * index is stored next. 
308            *
309            * If the length byte is zero, we need to read the next byte to
310            * know what to do.                   [JAY]
311            */
312           if (length != 0) 
313             {                                   
314                 /* 
315                  * [Run-Length] Encoded mode 
316                  */
317                 color_index = (*pIn++); /* Get the colour index. */
318                 color = colors[color_index];
319
320                 while(length--)
321                   XPutPixel(bmpImage, x++, line, color);
322             }
323           else 
324             {    
325                 /* 
326                  * Escape codes (may be an absolute sequence though)
327                  */
328                 escape_code = (*pIn++);
329                 switch(escape_code)
330                   {
331                     case RleEol: /* =0, end of line */
332                       {
333                           x = 0;  
334                           line--;  
335                           break;
336                       }
337                       
338                     case RleEnd: /* =1, end of bitmap */
339                       {
340                           /*
341                            * Not all RLE8 bitmaps end with this 
342                            * code.  For example, Paint Shop Pro 
343                            * produces some that don't.  That's (I think)
344                            * what caused the previous implementation to 
345                            * fail.                      [JAY]
346                            */
347                           line=0; /* Cause exit from do loop. */
348                       }
349                       
350                     case RleDelta: /* =2, a delta */
351                       {
352                           /* 
353                            * Note that deltaing to line 0 
354                            * will cause an exit from the loop, 
355                            * which may not be what is intended. 
356                            * The fact that there is a delta in the bits
357                            * almost certainly implies that there is data
358                            * to follow.  You may feel that we should 
359                            * jump to the top of the loop to avoid exiting
360                            * in this case.  
361                            *
362                            * TODO: Decide what to do here in that case. [JAY]
363                            */
364                           x     += (*pIn++); 
365                           line  -= (*pIn++);
366                           if (line == 0)
367                             {
368                               dprintf_bitmap(stddeb, 
369                                              "DIB_SetImageBits_RLE8(): "
370                                              "Delta to last line of bitmap "
371                                              "(wrongly?) causes loop exit\n");
372                             }
373                           break;
374                       }
375                       
376                     default:    /* >2, switch to absolute mode */
377                       {
378                           /* 
379                            * Absolute Mode 
380                            */
381                           length = escape_code;
382                           while(length--)
383                             {
384                                 color_index = (*pIn++);
385                                 XPutPixel(bmpImage, x++, line, 
386                                           colors[color_index]);
387                             }
388                           
389                           /*
390                            * If you think for a moment you'll realise that the
391                            * only time we could ever possibly read an odd
392                            * number of bytes is when there is a 0x00 (escape),
393                            * a value >0x02 (absolute mode) and then an odd-
394                            * length run.  Therefore this is the only place we
395                            * need to worry about it.  Everywhere else the
396                            * bytes are always read in pairs.  [JAY]
397                            */
398                           if (escape_code & 1) 
399                             pIn++; /* Throw away the pad byte. */
400                           break;
401                       }
402                   } /* switch (escape_code) : Escape sequence */
403             }  /* process either an encoded sequence or an escape sequence */
404           
405           /* We expect to come here more than once per line. */
406       } while (line > 0);  /* Do this until the bitmap is filled */
407     
408     /*
409      * Everybody comes here at the end.
410      * Check how we exited the loop and print a message if it's a bit odd.
411      *                                          [JAY]
412      */
413     if ( (*(pIn-2) != 0/*escape*/) || (*(pIn-1)!= RleEnd) )
414       {
415         dprintf_bitmap(stddeb, "DIB_SetImageBits_RLE8(): End-of-bitmap "
416                        "without (strictly) proper escape code.  Last two "
417                        "bytes were: %02X %02X.\n",
418                        (int)*(pIn-2),
419                        (int)*(pIn-1));           
420       }
421 }  
422
423
424 /***********************************************************************
425  *           DIB_SetImageBits_24
426  *
427  * SetDIBits for a 24-bit deep DIB.
428  */
429 static void DIB_SetImageBits_24( WORD lines, BYTE *bits, WORD width,
430                                  DC *dc, XImage *bmpImage )
431 {
432     WORD x;
433     BYTE pad = (4 - ((width*3) & 3)) & 3;
434
435     while (lines--)
436     {
437         for (x = 0; x < width; x++, bits += 3)
438         {
439             XPutPixel( bmpImage, x, lines,
440                        COLOR_ToPhysical( dc, RGB(bits[0],bits[1],bits[2]) ));
441         }
442         bits += pad;
443     }
444 }
445
446
447 /***********************************************************************
448  *           DIB_SetImageBits
449  *
450  * Transfer the bits to an X image.
451  * Helper function for SetDIBits() and SetDIBitsToDevice().
452  */
453 static int DIB_SetImageBits( DC *dc, WORD lines, WORD depth, LPSTR bits,
454                              BITMAPINFO *info, WORD coloruse,
455                              Drawable drawable, GC gc, int xSrc, int ySrc,
456                              int xDest, int yDest, int width, int height )
457 {
458     int *colorMapping;
459     XImage *bmpImage;
460     int i, colors;
461
462       /* Build the color mapping table */
463
464     if (info->bmiHeader.biBitCount == 24) colorMapping = NULL;
465     else
466     {
467         colors = info->bmiHeader.biClrUsed;
468         if (!colors) colors = 1 << info->bmiHeader.biBitCount;
469         if (!(colorMapping = (int *)malloc( colors * sizeof(int) )))
470             return 0;
471         if (coloruse == DIB_RGB_COLORS)
472         {
473             RGBQUAD * rgbPtr = info->bmiColors;
474             for (i = 0; i < colors; i++, rgbPtr++)
475                 colorMapping[i] = COLOR_ToPhysical( dc, RGB(rgbPtr->rgbRed,
476                                                             rgbPtr->rgbGreen,
477                                                             rgbPtr->rgbBlue) );
478         }
479         else
480         {
481             WORD * index = (WORD *)info->bmiColors;
482             for (i = 0; i < colors; i++, index++)
483                 colorMapping[i] = COLOR_ToPhysical( dc, PALETTEINDEX(*index) );
484         }
485     }
486
487       /* Transfer the pixels */
488     XCREATEIMAGE(bmpImage, info->bmiHeader.biWidth, lines, depth );
489
490     switch(info->bmiHeader.biBitCount)
491     {
492     case 1:
493         DIB_SetImageBits_1( lines, bits, info->bmiHeader.biWidth,
494                             colorMapping, bmpImage );
495         break;
496     case 4:
497         if (info->bmiHeader.biCompression)
498                 DIB_SetImageBits_RLE4( lines, bits, info->bmiHeader.biWidth,
499                             colorMapping, bmpImage );
500         else    
501                 DIB_SetImageBits_4( lines, bits, info->bmiHeader.biWidth,
502                             colorMapping, bmpImage );
503         break;
504     case 8:
505         if (info->bmiHeader.biCompression)
506                 DIB_SetImageBits_RLE8( lines, bits, info->bmiHeader.biWidth,
507                             colorMapping, bmpImage );
508         else
509                 DIB_SetImageBits_8( lines, bits, info->bmiHeader.biWidth,
510                             colorMapping, bmpImage );
511         break;
512     case 24:
513         DIB_SetImageBits_24( lines, bits, info->bmiHeader.biWidth,
514                              dc, bmpImage );
515         break;
516     }
517     if (colorMapping) free(colorMapping);
518     {
519       WORD saved_ds = CURRENT_DS;
520       XPutImage( display, drawable, gc, bmpImage, xSrc, ySrc,
521                 xDest, yDest, width, height );
522       if (saved_ds != CURRENT_DS) {
523         fprintf(stderr,"Uh oh. XPutImage clobbered the 16 bit stack.\n"
524                 "Please report: %s compression, %d bitplanes!!\n",
525                 info->bmiHeader.biCompression ? "" : "no", 
526                 info->bmiHeader.biBitCount);
527       }
528     }
529     XDestroyImage( bmpImage );
530     return lines;
531 }
532
533
534 /***********************************************************************
535  *           StretchDIBits      (GDI.439)
536  */
537 int StretchDIBits( HDC hdc, 
538         WORD xDest, WORD yDest, WORD wDestWidth, WORD wDestHeight,
539         WORD xSrc, WORD ySrc, WORD wSrcWidth, WORD wSrcHeight,
540         LPSTR bits, LPBITMAPINFO info, WORD wUsage, DWORD dwRop )
541 {
542         printf("StretchDIBits // call SetDIBitsToDevice for now !!!!\n");
543         return SetDIBitsToDevice(hdc, xDest, yDest, wDestWidth, wDestHeight,
544                 xSrc, ySrc, 1, 1, bits, info, wUsage);
545 }
546
547 /***********************************************************************
548  *           SetDIBits    (GDI.440)
549  */
550 int SetDIBits( HDC hdc, HBITMAP hbitmap, WORD startscan, WORD lines,
551                LPSTR bits, BITMAPINFO * info, WORD coloruse )
552 {
553     DC * dc;
554     BITMAPOBJ * bmp;
555
556       /* Check parameters */
557
558     if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
559     if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
560         return 0;
561     if (!lines || (startscan >= (WORD)info->bmiHeader.biHeight)) return 0;
562     if (startscan+lines > info->bmiHeader.biHeight)
563         lines = info->bmiHeader.biHeight - startscan;
564
565     return DIB_SetImageBits( dc, lines, bmp->bitmap.bmBitsPixel,
566                              bits, info, coloruse, bmp->pixmap, BITMAP_GC(bmp),
567                              0, 0, 0, startscan, bmp->bitmap.bmWidth, lines );
568 }
569
570
571 /***********************************************************************
572  *           SetDIBitsToDevice    (GDI.443)
573  */
574 int SetDIBitsToDevice( HDC hdc, short xDest, short yDest, WORD cx, WORD cy,
575                        WORD xSrc, WORD ySrc, WORD startscan, WORD lines,
576                        LPSTR bits, BITMAPINFO * info, WORD coloruse )
577 {
578     DC * dc;
579
580       /* Check parameters */
581
582     if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
583     if (!lines || (startscan >= info->bmiHeader.biHeight)) return 0;
584     if (startscan+lines > info->bmiHeader.biHeight)
585         lines = info->bmiHeader.biHeight - startscan;
586     if (ySrc < startscan) ySrc = startscan;
587     else if (ySrc >= startscan+lines) return 0;
588     if (xSrc >= info->bmiHeader.biWidth) return 0;
589     if (ySrc+cy >= startscan+lines) cy = startscan + lines - ySrc;
590     if (xSrc+cx >= info->bmiHeader.biWidth) cx = info->bmiHeader.biWidth-xSrc;
591     if (!cx || !cy) return 0;
592
593     DC_SetupGCForText( dc );  /* To have the correct colors */
594     XSetFunction( display, dc->u.x.gc, DC_XROPfunction[dc->w.ROPmode-1] );
595     return DIB_SetImageBits( dc, lines, dc->w.bitsPerPixel,
596                              bits, info, coloruse,
597                              dc->u.x.drawable, dc->u.x.gc,
598                              xSrc, ySrc - startscan,
599                              dc->w.DCOrgX + XLPTODP( dc, xDest ),
600                              dc->w.DCOrgY + YLPTODP( dc, yDest ),
601                              cx, cy );
602 }
603
604
605
606 /***********************************************************************
607  *           GetDIBits    (GDI.441)
608  */
609 int GetDIBits( HDC hdc, HBITMAP hbitmap, WORD startscan, WORD lines,
610                LPSTR bits, BITMAPINFO * info, WORD coloruse )
611 {
612     DC * dc;
613     BITMAPOBJ * bmp;
614     PALETTEENTRY * palEntry;
615     PALETTEOBJ * palette;
616     XImage * bmpImage, * dibImage;
617     int i, x, y;
618         
619     if (!lines) return 0;
620     if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
621     if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
622         return 0;
623     if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->w.hPalette, PALETTE_MAGIC )))
624         return 0;
625
626       /* Transfer color info */
627     
628     palEntry = palette->logpalette.palPalEntry;
629     for (i = 0; i < info->bmiHeader.biClrUsed; i++, palEntry++)
630     {
631         if (coloruse == DIB_RGB_COLORS)
632         {
633             info->bmiColors[i].rgbRed      = palEntry->peRed;
634             info->bmiColors[i].rgbGreen    = palEntry->peGreen;
635             info->bmiColors[i].rgbBlue     = palEntry->peBlue;
636             info->bmiColors[i].rgbReserved = 0;
637         }
638         else ((WORD *)info->bmiColors)[i] = (WORD)i;
639     }
640     
641       /* Transfer the pixels (very slow...) */
642
643     if (bits)
644     {   
645         bmpImage = XGetImage( display, bmp->pixmap, 0, 0, bmp->bitmap.bmWidth,
646                               bmp->bitmap.bmHeight, AllPlanes, ZPixmap );
647         dibImage = DIB_DIBmpToImage( &info->bmiHeader, bits );
648
649         for (y = 0; y < lines; y++)
650         {
651             for (x = 0; x < info->bmiHeader.biWidth; x++)
652             {
653                 XPutPixel( dibImage, x, y,
654                   XGetPixel(bmpImage, x, bmp->bitmap.bmHeight-startscan-y-1) );
655                 
656             }
657         }
658         
659         dibImage->data = NULL;
660         XDestroyImage( dibImage );
661         XDestroyImage( bmpImage );
662     }
663     return lines;
664 }
665
666
667 /***********************************************************************
668  *           CreateDIBitmap    (GDI.442)
669  */
670 HBITMAP CreateDIBitmap( HDC hdc, BITMAPINFOHEADER * header, DWORD init,
671                         LPSTR bits, BITMAPINFO * data, WORD coloruse )
672 {
673     HBITMAP handle;
674     
675     handle = CreateCompatibleBitmap( hdc, header->biWidth, header->biHeight );
676     if (!handle) return 0;
677     if (init == CBM_INIT) SetDIBits( hdc, handle, 0, header->biHeight,
678                                     bits, data, coloruse );
679     return handle;
680 }
681
682 /***********************************************************************
683  *           DrawIcon    (USER.84)
684  */
685 BOOL DrawIcon(HDC hDC, short x, short y, HICON hIcon)
686 {
687     ICONALLOC   *lpico;
688     BITMAP      bm;
689     HBITMAP     hBitTemp;
690     HDC         hMemDC;
691     COLORREF    oldFg, oldBg;
692
693     oldFg = SetTextColor( hDC, RGB(0,0,0) );
694     oldBg = SetBkColor( hDC, RGB(255,255,255) );
695     dprintf_icon(stddeb,"DrawIcon(%04X, %d, %d, %04X) \n", hDC, x, y, hIcon);
696     if (hIcon == (HICON)NULL) return FALSE;
697     lpico = (ICONALLOC *)GlobalLock(hIcon);
698     GetObject(lpico->hBitmap, sizeof(BITMAP), (LPSTR)&bm);
699     hMemDC = CreateCompatibleDC(hDC);
700     if (lpico->hBitMask)
701     {
702         hBitTemp = SelectObject(hMemDC, lpico->hBitMask);
703         BitBlt(hDC, x, y, bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCAND);
704         SelectObject(hMemDC, lpico->hBitmap);
705         BitBlt(hDC, x, y, bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCINVERT);
706     }
707     else  /* no mask -> everything is masked; so use SRCCOPY as it's faster */
708     {
709         hBitTemp = SelectObject(hMemDC, lpico->hBitmap);
710         BitBlt(hDC, x, y, bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
711     }
712     SelectObject( hMemDC, hBitTemp );
713     DeleteDC(hMemDC);
714     GlobalUnlock( hIcon );
715     SetTextColor( hDC, oldFg );
716     SetBkColor( hDC, oldBg );
717     return TRUE;
718 }
719