Release 950706
[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     HBITMAP hBitmap, hOldBitmap;
545     HDC hdcMem;
546
547     hBitmap = CreateDIBitmap( hdc, &info->bmiHeader, CBM_INIT,
548                               bits, info, wUsage );
549     hdcMem = CreateCompatibleDC( hdc );
550     hOldBitmap = SelectObject( hdcMem, hBitmap );
551     StretchBlt( hdc, xDest, yDest, wDestWidth, wDestHeight,
552                 hdcMem, xSrc, ySrc, wSrcWidth, wSrcHeight, dwRop );
553     SelectObject( hdcMem, hOldBitmap );
554     DeleteDC( hdcMem );
555     DeleteObject( hBitmap );
556     return wSrcHeight;
557 }
558
559 /***********************************************************************
560  *           SetDIBits    (GDI.440)
561  */
562 int SetDIBits( HDC hdc, HBITMAP hbitmap, WORD startscan, WORD lines,
563                LPSTR bits, BITMAPINFO * info, WORD coloruse )
564 {
565     DC * dc;
566     BITMAPOBJ * bmp;
567
568       /* Check parameters */
569
570     if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
571     if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
572         return 0;
573     if (!lines || (startscan >= (WORD)info->bmiHeader.biHeight)) return 0;
574     if (startscan+lines > info->bmiHeader.biHeight)
575         lines = info->bmiHeader.biHeight - startscan;
576
577     return CallTo32_LargeStack( (int(*)())DIB_SetImageBits, 14,
578                                 dc, lines, bmp->bitmap.bmBitsPixel,
579                                 bits, info, coloruse, bmp->pixmap,
580                                 BITMAP_GC(bmp), 0, 0, 0, startscan,
581                                 bmp->bitmap.bmWidth, lines );
582 }
583
584
585 /***********************************************************************
586  *           SetDIBitsToDevice    (GDI.443)
587  */
588 int SetDIBitsToDevice( HDC hdc, short xDest, short yDest, WORD cx, WORD cy,
589                        WORD xSrc, WORD ySrc, WORD startscan, WORD lines,
590                        LPSTR bits, BITMAPINFO * info, WORD coloruse )
591 {
592     DC * dc;
593
594       /* Check parameters */
595
596     if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
597     if (!lines || (startscan >= info->bmiHeader.biHeight)) return 0;
598     if (startscan+lines > info->bmiHeader.biHeight)
599         lines = info->bmiHeader.biHeight - startscan;
600     if (ySrc < startscan) ySrc = startscan;
601     else if (ySrc >= startscan+lines) return 0;
602     if (xSrc >= info->bmiHeader.biWidth) return 0;
603     if (ySrc+cy >= startscan+lines) cy = startscan + lines - ySrc;
604     if (xSrc+cx >= info->bmiHeader.biWidth) cx = info->bmiHeader.biWidth-xSrc;
605     if (!cx || !cy) return 0;
606
607     DC_SetupGCForText( dc );  /* To have the correct colors */
608     XSetFunction( display, dc->u.x.gc, DC_XROPfunction[dc->w.ROPmode-1] );
609     return CallTo32_LargeStack( (int(*)())DIB_SetImageBits, 14,
610                                 dc, lines, dc->w.bitsPerPixel, bits, info,
611                                 coloruse, dc->u.x.drawable, dc->u.x.gc,
612                                 xSrc, ySrc - startscan,
613                                 dc->w.DCOrgX + XLPTODP( dc, xDest ),
614                                 dc->w.DCOrgY + YLPTODP( dc, yDest ),
615                                 cx, cy );
616 }
617
618
619
620 /***********************************************************************
621  *           GetDIBits    (GDI.441)
622  */
623 int GetDIBits( HDC hdc, HBITMAP hbitmap, WORD startscan, WORD lines,
624                LPSTR bits, BITMAPINFO * info, WORD coloruse )
625 {
626     DC * dc;
627     BITMAPOBJ * bmp;
628     PALETTEENTRY * palEntry;
629     PALETTEOBJ * palette;
630     XImage * bmpImage, * dibImage;
631     int i, x, y;
632         
633     if (!lines) return 0;
634     if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
635     if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
636         return 0;
637     if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->w.hPalette, PALETTE_MAGIC )))
638         return 0;
639
640       /* Transfer color info */
641     
642     palEntry = palette->logpalette.palPalEntry;
643     for (i = 0; i < info->bmiHeader.biClrUsed; i++, palEntry++)
644     {
645         if (coloruse == DIB_RGB_COLORS)
646         {
647             info->bmiColors[i].rgbRed      = palEntry->peRed;
648             info->bmiColors[i].rgbGreen    = palEntry->peGreen;
649             info->bmiColors[i].rgbBlue     = palEntry->peBlue;
650             info->bmiColors[i].rgbReserved = 0;
651         }
652         else ((WORD *)info->bmiColors)[i] = (WORD)i;
653     }
654     
655       /* Transfer the pixels (very slow...) */
656
657     if (bits)
658     {   
659         bmpImage = XGetImage( display, bmp->pixmap, 0, 0, bmp->bitmap.bmWidth,
660                               bmp->bitmap.bmHeight, AllPlanes, ZPixmap );
661         dibImage = DIB_DIBmpToImage( &info->bmiHeader, bits );
662
663         for (y = 0; y < lines; y++)
664         {
665             for (x = 0; x < info->bmiHeader.biWidth; x++)
666             {
667                 XPutPixel( dibImage, x, y,
668                   XGetPixel(bmpImage, x, bmp->bitmap.bmHeight-startscan-y-1) );
669                 
670             }
671         }
672         
673         dibImage->data = NULL;
674         XDestroyImage( dibImage );
675         XDestroyImage( bmpImage );
676     }
677     return lines;
678 }
679
680
681 /***********************************************************************
682  *           CreateDIBitmap    (GDI.442)
683  */
684 HBITMAP CreateDIBitmap( HDC hdc, BITMAPINFOHEADER * header, DWORD init,
685                         LPSTR bits, BITMAPINFO * data, WORD coloruse )
686 {
687     HBITMAP handle;
688     
689     handle = CreateCompatibleBitmap( hdc, header->biWidth, header->biHeight );
690 /*    handle = CreateBitmap( header->biWidth, header->biHeight,
691                            1, header->biBitCount, NULL );
692 */
693     if (!handle) return 0;
694     if (init == CBM_INIT) SetDIBits( hdc, handle, 0, header->biHeight,
695                                     bits, data, coloruse );
696     return handle;
697 }
698
699 /***********************************************************************
700  *           DrawIcon    (USER.84)
701  */
702 BOOL DrawIcon(HDC hDC, short x, short y, HICON hIcon)
703 {
704     ICONALLOC   *lpico;
705     BITMAP      bm;
706     HBITMAP     hBitTemp;
707     HDC         hMemDC;
708     COLORREF    oldFg, oldBg;
709
710     oldFg = SetTextColor( hDC, RGB(0,0,0) );
711     oldBg = SetBkColor( hDC, RGB(255,255,255) );
712     dprintf_icon(stddeb,"DrawIcon(%04X, %d, %d, %04X) \n", hDC, x, y, hIcon);
713     if (hIcon == (HICON)NULL) return FALSE;
714     lpico = (ICONALLOC *)GlobalLock(hIcon);
715     GetObject(lpico->hBitmap, sizeof(BITMAP), (LPSTR)&bm);
716     hMemDC = CreateCompatibleDC(hDC);
717     if (lpico->hBitMask)
718     {
719         hBitTemp = SelectObject(hMemDC, lpico->hBitMask);
720         BitBlt(hDC, x, y, bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCAND);
721         SelectObject(hMemDC, lpico->hBitmap);
722         BitBlt(hDC, x, y, bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCINVERT);
723     }
724     else  /* no mask -> everything is masked; so use SRCCOPY as it's faster */
725     {
726         hBitTemp = SelectObject(hMemDC, lpico->hBitmap);
727         BitBlt(hDC, x, y, bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
728     }
729     SelectObject( hMemDC, hBitTemp );
730     DeleteDC(hMemDC);
731     GlobalUnlock( hIcon );
732     SetTextColor( hDC, oldFg );
733     SetBkColor( hDC, oldBg );
734     return TRUE;
735 }
736