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