Added handlers for some IME messages in DefWindowProc.
[wine] / objects / dib.c
1 /*
2  * GDI device-independent bitmaps
3  *
4  * Copyright 1993,1994  Alexandre Julliard
5  *
6  */
7
8 #include <stdlib.h>
9
10 #include "winbase.h"
11 #include "bitmap.h"
12 #include "callback.h"
13 #include "gdi.h"
14 #include "debugtools.h"
15 #include "palette.h"
16
17 DEFAULT_DEBUG_CHANNEL(bitmap);
18
19 /***********************************************************************
20  *           DIB_GetDIBWidthBytes
21  *
22  * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
23  * http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/struc/src/str01.htm
24  */
25 int DIB_GetDIBWidthBytes( int width, int depth )
26 {
27     int words;
28
29     switch(depth)
30     {
31         case 1:  words = (width + 31) / 32; break;
32         case 4:  words = (width + 7) / 8; break;
33         case 8:  words = (width + 3) / 4; break;
34         case 15:
35         case 16: words = (width + 1) / 2; break;
36         case 24: words = (width * 3 + 3)/4; break;
37
38         default:
39             WARN("(%d): Unsupported depth\n", depth );
40         /* fall through */
41         case 32:
42                 words = width;
43     }
44     return 4 * words;
45 }
46
47 /***********************************************************************
48  *           DIB_GetDIBImageBytes
49  *
50  * Return the number of bytes used to hold the image in a DIB bitmap.
51  */
52 int DIB_GetDIBImageBytes( int width, int height, int depth )
53 {
54     return DIB_GetDIBWidthBytes( width, depth ) * abs( height );
55 }
56
57
58 /***********************************************************************
59  *           DIB_BitmapInfoSize
60  *
61  * Return the size of the bitmap info structure including color table.
62  */
63 int DIB_BitmapInfoSize( const BITMAPINFO * info, WORD coloruse )
64 {
65     int colors;
66
67     if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
68     {
69         BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)info;
70         colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
71         return sizeof(BITMAPCOREHEADER) + colors *
72              ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
73     }
74     else  /* assume BITMAPINFOHEADER */
75     {
76         colors = info->bmiHeader.biClrUsed;
77         if (!colors && (info->bmiHeader.biBitCount <= 8))
78             colors = 1 << info->bmiHeader.biBitCount;
79         return sizeof(BITMAPINFOHEADER) + colors *
80                ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
81     }
82 }
83
84
85 /***********************************************************************
86  *           DIB_GetBitmapInfo
87  *
88  * Get the info from a bitmap header.
89  * Return 1 for INFOHEADER, 0 for COREHEADER, -1 for error.
90  */
91 int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, DWORD *width,
92                               int *height, WORD *bpp, WORD *compr )
93 {
94     if (header->biSize == sizeof(BITMAPINFOHEADER))
95     {
96         *width  = header->biWidth;
97         *height = header->biHeight;
98         *bpp    = header->biBitCount;
99         *compr  = header->biCompression;
100         return 1;
101     }
102     if (header->biSize == sizeof(BITMAPCOREHEADER))
103     {
104         BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)header;
105         *width  = core->bcWidth;
106         *height = core->bcHeight;
107         *bpp    = core->bcBitCount;
108         *compr  = 0;
109         return 0;
110     }
111     WARN("(%ld): wrong size for header\n", header->biSize );
112     return -1;
113 }
114
115
116 /***********************************************************************
117  *           StretchDIBits16   (GDI.439)
118  */
119 INT16 WINAPI StretchDIBits16(HDC16 hdc, INT16 xDst, INT16 yDst, INT16 widthDst,
120                        INT16 heightDst, INT16 xSrc, INT16 ySrc, INT16 widthSrc,
121                        INT16 heightSrc, const VOID *bits,
122                        const BITMAPINFO *info, UINT16 wUsage, DWORD dwRop )
123 {
124     return (INT16)StretchDIBits( hdc, xDst, yDst, widthDst, heightDst,
125                                    xSrc, ySrc, widthSrc, heightSrc, bits,
126                                    info, wUsage, dwRop );
127 }
128
129
130 /***********************************************************************
131  *           StretchDIBits   (GDI32.351)
132  */
133 INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst,
134                        INT heightDst, INT xSrc, INT ySrc, INT widthSrc,
135                        INT heightSrc, const void *bits,
136                        const BITMAPINFO *info, UINT wUsage, DWORD dwRop )
137 {
138     DC *dc = DC_GetDCUpdate( hdc );
139     if(!dc) return FALSE;
140
141     if(dc->funcs->pStretchDIBits)
142            heightSrc = dc->funcs->pStretchDIBits(dc, xDst, yDst, widthDst, 
143                                             heightDst, xSrc, ySrc, widthSrc,
144                                             heightSrc, bits, info, wUsage,
145                                             dwRop);
146     else { /* use StretchBlt */
147         HBITMAP hBitmap, hOldBitmap;
148         HDC hdcMem;
149
150         hdcMem = CreateCompatibleDC( hdc );
151         if (info->bmiHeader.biCompression == BI_RLE4 ||
152             info->bmiHeader.biCompression == BI_RLE8) {
153
154            /* when RLE compression is used, there may be some gaps (ie the DIB doesn't
155             * contain all the rectangle described in bmiHeader, but only part of it.
156             * This mean that those undescribed pixels must be left untouched.
157             * So, we first copy on a memory bitmap the current content of the 
158             * destination rectangle, blit the DIB bits on top of it - hence leaving
159             * the gaps untouched -, and blitting the rectangle back.
160             * This insure that gaps are untouched on the destination rectangle
161             * Not doing so leads to trashed images (the gaps contain what was on the
162             * memory bitmap => generally black or garbage)
163             * Unfortunately, RLE DIBs without gaps will be slowed down. But this is
164             * another speed vs correctness issue. Anyway, if speed is needed, then the
165             * pStretchDIBits function shall be implemented.
166             * ericP (2000/09/09)
167             */
168            hBitmap = CreateCompatibleBitmap(hdc, info->bmiHeader.biWidth, 
169                                             info->bmiHeader.biHeight);
170            hOldBitmap = SelectObject( hdcMem, hBitmap );
171            
172            /* copy existing bitmap from destination dc */
173            StretchBlt( hdcMem, xSrc, abs(info->bmiHeader.biHeight) - heightSrc - ySrc,
174                        widthSrc, heightSrc, hdc, xDst, yDst, widthDst, heightDst,
175                        dwRop );
176            SetDIBits(hdcMem, hBitmap, 0, info->bmiHeader.biHeight, bits, 
177                      info, DIB_RGB_COLORS); 
178            
179         } else {
180            hBitmap = CreateDIBitmap( hdc, &info->bmiHeader, CBM_INIT,
181                                      bits, info, wUsage );
182            hOldBitmap = SelectObject( hdcMem, hBitmap );
183         }
184
185         /* Origin for DIBitmap may be bottom left (positive biHeight) or top
186            left (negative biHeight) */
187         StretchBlt( hdc, xDst, yDst, widthDst, heightDst,
188                     hdcMem, xSrc, abs(info->bmiHeader.biHeight) - heightSrc - ySrc, 
189                     widthSrc, heightSrc, dwRop );
190         SelectObject( hdcMem, hOldBitmap );
191         DeleteDC( hdcMem );
192         DeleteObject( hBitmap );
193     }
194     GDI_ReleaseObj( hdc );
195     return heightSrc;
196 }
197
198
199 /***********************************************************************
200  *           SetDIBits16    (GDI.440)
201  */
202 INT16 WINAPI SetDIBits16( HDC16 hdc, HBITMAP16 hbitmap, UINT16 startscan,
203                           UINT16 lines, LPCVOID bits, const BITMAPINFO *info,
204                           UINT16 coloruse )
205 {
206     return SetDIBits( hdc, hbitmap, startscan, lines, bits, info, coloruse );
207 }
208
209
210 /******************************************************************************
211  * SetDIBits [GDI32.312]  Sets pixels in a bitmap using colors from DIB
212  *
213  * PARAMS
214  *    hdc       [I] Handle to device context
215  *    hbitmap   [I] Handle to bitmap
216  *    startscan [I] Starting scan line
217  *    lines     [I] Number of scan lines
218  *    bits      [I] Array of bitmap bits
219  *    info      [I] Address of structure with data
220  *    coloruse  [I] Type of color indexes to use
221  *
222  * RETURNS
223  *    Success: Number of scan lines copied
224  *    Failure: 0
225  */
226 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
227                       UINT lines, LPCVOID bits, const BITMAPINFO *info,
228                       UINT coloruse )
229 {
230     DC *dc;
231     BITMAPOBJ *bitmap;
232     INT result;
233
234     /* Check parameters */
235     if (!(dc = DC_GetDCUpdate( hdc ))) return 0;
236
237     if (!(bitmap = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
238     {
239         GDI_ReleaseObj( hdc );
240         return 0;
241     }
242
243     result = BITMAP_Driver->pSetDIBits(bitmap, dc, startscan, 
244                                        lines, bits, info, 
245                                        coloruse, hbitmap);
246
247     GDI_ReleaseObj( hbitmap );
248     GDI_ReleaseObj( hdc );
249
250     return result;
251 }
252
253
254 /***********************************************************************
255  *           SetDIBitsToDevice16    (GDI.443)
256  */
257 INT16 WINAPI SetDIBitsToDevice16(HDC16 hdc, INT16 xDest, INT16 yDest, INT16 cx,
258                            INT16 cy, INT16 xSrc, INT16 ySrc, UINT16 startscan,
259                            UINT16 lines, LPCVOID bits, const BITMAPINFO *info,
260                            UINT16 coloruse )
261 {
262     return SetDIBitsToDevice( hdc, xDest, yDest, cx, cy, xSrc, ySrc,
263                                 startscan, lines, bits, info, coloruse );
264 }
265
266
267 /***********************************************************************
268  *           SetDIBitsToDevice   (GDI32.313)
269  */
270 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
271                            DWORD cy, INT xSrc, INT ySrc, UINT startscan,
272                            UINT lines, LPCVOID bits, const BITMAPINFO *info,
273                            UINT coloruse )
274 {
275     INT ret;
276     DC *dc;
277
278     if (!(dc = DC_GetDCUpdate( hdc ))) return 0;
279
280     if(dc->funcs->pSetDIBitsToDevice)
281         ret = dc->funcs->pSetDIBitsToDevice( dc, xDest, yDest, cx, cy, xSrc,
282                                              ySrc, startscan, lines, bits,
283                                              info, coloruse );
284     else {
285         FIXME("unimplemented on hdc %08x\n", hdc);
286         ret = 0;
287     }
288
289     GDI_ReleaseObj( hdc );
290     return ret;
291 }
292
293 /***********************************************************************
294  *           SetDIBColorTable16    (GDI.602)
295  */
296 UINT16 WINAPI SetDIBColorTable16( HDC16 hdc, UINT16 startpos, UINT16 entries,
297                                   RGBQUAD *colors )
298 {
299     return SetDIBColorTable( hdc, startpos, entries, colors );
300 }
301
302 /***********************************************************************
303  *           SetDIBColorTable    (GDI32.311)
304  */
305 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries,
306                                   RGBQUAD *colors )
307 {
308     DC * dc;
309     BITMAPOBJ * bmp;
310     UINT result;
311
312     if (!(dc = DC_GetDCUpdate( hdc ))) return 0;
313
314     if (!(bmp = (BITMAPOBJ*)GDI_GetObjPtr( dc->hBitmap, BITMAP_MAGIC )))
315     {
316         GDI_ReleaseObj( hdc );
317         return 0;
318     }
319
320     result = BITMAP_Driver->pSetDIBColorTable(bmp, dc, startpos, entries, colors);
321
322     GDI_ReleaseObj( dc->hBitmap );
323     GDI_ReleaseObj( hdc );
324     return result;
325 }
326
327 /***********************************************************************
328  *           GetDIBColorTable16    (GDI.603)
329  */
330 UINT16 WINAPI GetDIBColorTable16( HDC16 hdc, UINT16 startpos, UINT16 entries,
331                                   RGBQUAD *colors )
332 {
333     return GetDIBColorTable( hdc, startpos, entries, colors );
334 }
335
336 /***********************************************************************
337  *           GetDIBColorTable    (GDI32.169)
338  */
339 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries,
340                                   RGBQUAD *colors )
341 {
342     DC * dc;
343     BITMAPOBJ * bmp;
344     UINT result;
345
346     if (!(dc = DC_GetDCUpdate( hdc ))) return 0;
347
348     if (!(bmp = (BITMAPOBJ*)GDI_GetObjPtr( dc->hBitmap, BITMAP_MAGIC )))
349     {
350         GDI_ReleaseObj( hdc );
351         return 0;
352     }
353
354     result = BITMAP_Driver->pGetDIBColorTable(bmp, dc, startpos, entries, colors);
355
356     GDI_ReleaseObj( dc->hBitmap );
357     GDI_ReleaseObj( hdc );
358     return result;
359 }
360
361 /* FIXME the following two structs should be combined with __sysPalTemplate in
362    objects/color.c - this should happen after de-X11-ing both of these
363    files.
364    NB. RGBQUAD and PALETTENTRY have different orderings of red, green
365    and blue - sigh */
366
367 static RGBQUAD EGAColors[16] = { 
368 /* rgbBlue, rgbGreen, rgbRed, rgbReserverd */
369     { 0x00, 0x00, 0x00, 0x00 },
370     { 0x00, 0x00, 0x80, 0x00 },
371     { 0x00, 0x80, 0x00, 0x00 },
372     { 0x00, 0x80, 0x80, 0x00 },
373     { 0x80, 0x00, 0x00, 0x00 },
374     { 0x80, 0x00, 0x80, 0x00 },
375     { 0x80, 0x80, 0x00, 0x00 },
376     { 0x80, 0x80, 0x80, 0x00 },
377     { 0xc0, 0xc0, 0xc0, 0x00 },
378     { 0x00, 0x00, 0xff, 0x00 },
379     { 0x00, 0xff, 0x00, 0x00 },
380     { 0x00, 0xff, 0xff, 0x00 },
381     { 0xff, 0x00, 0x00, 0x00 },
382     { 0xff, 0x00, 0xff, 0x00 },
383     { 0xff, 0xff, 0x00, 0x00 },
384     { 0xff, 0xff, 0xff, 0x00 }
385 };
386
387
388 static RGBQUAD DefLogPalette[20] = { /* Copy of Default Logical Palette */
389 /* rgbBlue, rgbGreen, rgbRed, rgbReserverd */
390     { 0x00, 0x00, 0x00, 0x00 },
391     { 0x00, 0x00, 0x80, 0x00 },
392     { 0x00, 0x80, 0x00, 0x00 },
393     { 0x00, 0x80, 0x80, 0x00 },
394     { 0x80, 0x00, 0x00, 0x00 },
395     { 0x80, 0x00, 0x80, 0x00 },
396     { 0x80, 0x80, 0x00, 0x00 },
397     { 0xc0, 0xc0, 0xc0, 0x00 },
398     { 0xc0, 0xdc, 0xc0, 0x00 },
399     { 0xf0, 0xca, 0xa6, 0x00 },
400     { 0xf0, 0xfb, 0xff, 0x00 },
401     { 0xa4, 0xa0, 0xa0, 0x00 },
402     { 0x80, 0x80, 0x80, 0x00 },
403     { 0x00, 0x00, 0xf0, 0x00 },
404     { 0x00, 0xff, 0x00, 0x00 },
405     { 0x00, 0xff, 0xff, 0x00 },
406     { 0xff, 0x00, 0x00, 0x00 },
407     { 0xff, 0x00, 0xff, 0x00 },
408     { 0xff, 0xff, 0x00, 0x00 },
409     { 0xff, 0xff, 0xff, 0x00 }
410 };
411
412 /***********************************************************************
413  *           GetDIBits16    (GDI.441)
414  */
415 INT16 WINAPI GetDIBits16( HDC16 hdc, HBITMAP16 hbitmap, UINT16 startscan,
416                           UINT16 lines, LPVOID bits, BITMAPINFO * info,
417                           UINT16 coloruse )
418 {
419     return GetDIBits( hdc, hbitmap, startscan, lines, bits, info, coloruse );
420 }
421
422
423 /******************************************************************************
424  * GetDIBits [GDI32.170]  Retrieves bits of bitmap and copies to buffer
425  *
426  * RETURNS
427  *    Success: Number of scan lines copied from bitmap
428  *    Failure: 0
429  *
430  * http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/func/src/f30_14.htm
431  */
432 INT WINAPI GetDIBits(
433     HDC hdc,         /* [in]  Handle to device context */
434     HBITMAP hbitmap, /* [in]  Handle to bitmap */
435     UINT startscan,  /* [in]  First scan line to set in dest bitmap */
436     UINT lines,      /* [in]  Number of scan lines to copy */
437     LPVOID bits,       /* [out] Address of array for bitmap bits */
438     BITMAPINFO * info, /* [out] Address of structure with bitmap data */
439     UINT coloruse)   /* [in]  RGB or palette index */
440 {
441     DC * dc;
442     BITMAPOBJ * bmp;
443     PALETTEENTRY * palEntry;
444     PALETTEOBJ * palette;
445     int i;
446
447     if (!info) return 0;
448     if (!(dc = DC_GetDCUpdate( hdc ))) return 0;
449     if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
450     {
451         GDI_ReleaseObj( hdc );
452         return 0;
453     }
454     if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->hPalette, PALETTE_MAGIC )))
455     {
456         GDI_ReleaseObj( hdc );
457         GDI_ReleaseObj( hbitmap );
458         return 0;
459     }
460
461     /* Transfer color info */
462
463     if (info->bmiHeader.biBitCount <= 8 && info->bmiHeader.biBitCount > 0 ) {
464
465         info->bmiHeader.biClrUsed = 0;
466
467         if(info->bmiHeader.biBitCount >= bmp->bitmap.bmBitsPixel) {
468             palEntry = palette->logpalette.palPalEntry;
469             for (i = 0; i < (1 << bmp->bitmap.bmBitsPixel); i++, palEntry++) {
470                 if (coloruse == DIB_RGB_COLORS) {
471                     info->bmiColors[i].rgbRed      = palEntry->peRed;
472                     info->bmiColors[i].rgbGreen    = palEntry->peGreen;
473                     info->bmiColors[i].rgbBlue     = palEntry->peBlue;
474                     info->bmiColors[i].rgbReserved = 0;
475                 }
476                 else ((WORD *)info->bmiColors)[i] = (WORD)i;
477             }
478         } else {
479             switch (info->bmiHeader.biBitCount) {
480             case 1:
481                 info->bmiColors[0].rgbRed = info->bmiColors[0].rgbGreen =
482                   info->bmiColors[0].rgbBlue = 0;
483                 info->bmiColors[0].rgbReserved = 0;
484                 info->bmiColors[1].rgbRed = info->bmiColors[1].rgbGreen =
485                   info->bmiColors[1].rgbBlue = 0xff;
486                 info->bmiColors[1].rgbReserved = 0;
487                 break;
488
489             case 4:
490                 memcpy(info->bmiColors, EGAColors, sizeof(EGAColors));
491                 break;
492
493             case 8:
494                 {
495                 INT r, g, b;
496                 RGBQUAD *color;
497
498                 memcpy(info->bmiColors, DefLogPalette,
499                        10 * sizeof(RGBQUAD));
500                 memcpy(info->bmiColors + 246, DefLogPalette + 10,
501                        10 * sizeof(RGBQUAD));
502                 color = info->bmiColors + 10;
503                 for(r = 0; r <= 5; r++) /* FIXME */
504                     for(g = 0; g <= 5; g++)
505                         for(b = 0; b <= 5; b++) {
506                             color->rgbRed =   (r * 0xff) / 5;
507                             color->rgbGreen = (g * 0xff) / 5;
508                             color->rgbBlue =  (b * 0xff) / 5;
509                             color->rgbReserved = 0;
510                             color++;
511                         }
512                 }
513             }
514         }
515     }
516
517     GDI_ReleaseObj( dc->hPalette );
518
519     if (bits && lines)
520     {
521         /* If the bitmap object already have a dib section that contains image data, get the bits from it*/
522         if(bmp->dib && bmp->dib->dsBm.bmBitsPixel >= 15 && info->bmiHeader.biBitCount >= 15)
523         {
524             /*FIXME: Only RGB dibs supported for now */
525             int srcwidth = bmp->dib->dsBm.bmWidth, srcwidthb = bmp->dib->dsBm.bmWidthBytes;
526             int dstwidthb = DIB_GetDIBWidthBytes( info->bmiHeader.biWidth, info->bmiHeader.biBitCount );
527             LPBYTE dbits = bits, sbits = (LPBYTE) bmp->dib->dsBm.bmBits + (startscan * srcwidthb);
528             int x, y;
529
530             if ((info->bmiHeader.biHeight < 0) ^ (bmp->dib->dsBmih.biHeight < 0))
531             {
532                 dbits = (LPBYTE)bits + (dstwidthb * (lines-1));
533                 dstwidthb = -dstwidthb;
534             }
535
536             switch( info->bmiHeader.biBitCount ) {
537
538             case 15:
539             case 16: /* 16 bpp dstDIB */
540                 {
541                     LPWORD dstbits = (LPWORD)dbits;
542                     WORD rmask = 0x7c00, gmask= 0x03e0, bmask = 0x001f;
543
544                     /* FIXME: BI_BITFIELDS not supported yet */
545
546                     switch(bmp->dib->dsBm.bmBitsPixel) {
547
548                     case 16: /* 16 bpp srcDIB -> 16 bpp dstDIB */
549                         {
550                             /* FIXME: BI_BITFIELDS not supported yet */
551                             for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
552                                 memcpy(dbits, sbits, srcwidthb);
553                         }
554                         break;
555
556                     case 24: /* 24 bpp srcDIB -> 16 bpp dstDIB */
557                         {
558                             LPBYTE srcbits = sbits;
559
560                             for( y = 0; y < lines; y++) {
561                                 for( x = 0; x < srcwidth; x++ )
562                                     *dstbits++ = ((*srcbits++ >> 3) & bmask) |
563                                                  (((WORD)*srcbits++ << 2) & gmask) |
564                                                  (((WORD)*srcbits++ << 7) & rmask);
565                                 dstbits = (LPWORD)(dbits+=dstwidthb);
566                                 srcbits = (sbits += srcwidthb);
567                             }
568                         }
569                         break;
570
571                     case 32: /* 32 bpp srcDIB -> 16 bpp dstDIB */
572                         {
573                             LPDWORD srcbits = (LPDWORD)sbits;
574                             DWORD val;
575
576                             for( y = 0; y < lines; y++) {
577                                 for( x = 0; x < srcwidth; x++ ) {
578                                     val = *srcbits++;
579                                     *dstbits++ = (WORD)(((val >> 3) & bmask) | ((val >> 6) & gmask) |
580                                                        ((val >> 9) & rmask));
581                                 }
582                                 dstbits = (LPWORD)(dbits+=dstwidthb);
583                                 srcbits = (LPDWORD)(sbits+=srcwidthb);
584                             }
585                         }
586                         break;
587
588                     default: /* ? bit bmp -> 16 bit DIB */
589                         FIXME("15/16 bit DIB %d bit bitmap\n",
590                         bmp->bitmap.bmBitsPixel);
591                         break;
592                     }
593                 }
594                 break;
595
596             case 24: /* 24 bpp dstDIB */
597                 {
598                     LPBYTE dstbits = dbits;
599
600                     switch(bmp->dib->dsBm.bmBitsPixel) {
601
602                     case 16: /* 16 bpp srcDIB -> 24 bpp dstDIB */
603                         {
604                             LPWORD srcbits = (LPWORD)sbits;
605                             WORD val;
606
607                             /* FIXME: BI_BITFIELDS not supported yet */
608                             for( y = 0; y < lines; y++) {
609                                 for( x = 0; x < srcwidth; x++ ) {
610                                     val = *srcbits++;
611                                     *dstbits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07));
612                                     *dstbits++ = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07));
613                                     *dstbits++ = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07));
614                                 }
615                                 dstbits = (LPBYTE)(dbits+=dstwidthb);
616                                 srcbits = (LPWORD)(sbits+=srcwidthb);
617                             }
618                         }
619                         break;
620
621                     case 24: /* 24 bpp srcDIB -> 24 bpp dstDIB */
622                         {
623                             for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
624                                 memcpy(dbits, sbits, srcwidthb);
625                         }
626                         break;
627
628                     case 32: /* 32 bpp srcDIB -> 24 bpp dstDIB */
629                         {
630                             LPBYTE srcbits = (LPBYTE)sbits;
631
632                             for( y = 0; y < lines; y++) {
633                                 for( x = 0; x < srcwidth; x++, srcbits++ ) {
634                                     *dstbits++ = *srcbits++;
635                                     *dstbits++ = *srcbits++;
636                                     *dstbits++ = *srcbits++;
637                                 }
638                                 dstbits=(LPBYTE)(dbits+=dstwidthb);
639                                 srcbits = (LPBYTE)(sbits+=srcwidthb);
640                             }
641                         }
642                         break;
643
644                     default: /* ? bit bmp -> 24 bit DIB */
645                         FIXME("24 bit DIB %d bit bitmap\n",
646                               bmp->bitmap.bmBitsPixel);
647                         break;
648                     }
649                 }
650                 break;
651
652             case 32: /* 32 bpp dstDIB */
653                 {
654                     LPDWORD dstbits = (LPDWORD)dbits;
655
656                     /* FIXME: BI_BITFIELDS not supported yet */
657
658                     switch(bmp->dib->dsBm.bmBitsPixel) {
659                         case 16: /* 16 bpp srcDIB -> 32 bpp dstDIB */
660                         {
661                             LPWORD srcbits = (LPWORD)sbits;
662                             DWORD val;
663
664                             /* FIXME: BI_BITFIELDS not supported yet */
665                             for( y = 0; y < lines; y++) {
666                                 for( x = 0; x < srcwidth; x++ ) {
667                                     val = (DWORD)*srcbits++;
668                                     *dstbits++ = ((val << 3) & 0xf8) | ((val >> 2) & 0x07) |
669                                                  ((val << 6) & 0xf800) | ((val << 1) & 0x0700) |
670                                                  ((val << 9) & 0xf80000) | ((val << 4) & 0x070000);
671                                 }
672                                 dstbits=(LPDWORD)(dbits+=dstwidthb);
673                                 srcbits=(LPWORD)(sbits+=srcwidthb);
674                             }
675                         }
676                         break;
677
678                     case 24: /* 24 bpp srcDIB -> 32 bpp dstDIB */
679                         {
680                             LPBYTE srcbits = sbits;
681
682                             for( y = 0; y < lines; y++) {
683                                 for( x = 0; x < srcwidth; x++, srcbits+=3 )
684                                     *dstbits++ = ((DWORD)*srcbits) & 0x00ffffff; 
685                                 dstbits=(LPDWORD)(dbits+=dstwidthb);
686                                 srcbits=(sbits+=srcwidthb);
687                             }
688                         }
689                         break;
690
691                     case 32: /* 32 bpp srcDIB -> 16 bpp dstDIB */
692                         {
693                             /* FIXME: BI_BITFIELDS not supported yet */
694                             for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
695                                 memcpy(dbits, sbits, srcwidthb);
696                         }
697                         break;
698
699                     default: /* ? bit bmp -> 16 bit DIB */
700                         FIXME("15/16 bit DIB %d bit bitmap\n",
701                         bmp->bitmap.bmBitsPixel);
702                         break;
703                     }
704                 }
705                 break;
706
707             default: /* ? bit DIB */
708                 FIXME("Unsupported DIB depth %d\n", info->bmiHeader.biBitCount);
709                 break;
710             }
711         }
712         /* Otherwise, get bits from the XImage */
713         else if(!BITMAP_Driver->pGetDIBits(bmp, dc, startscan, lines, bits, info, coloruse, hbitmap))
714         {
715             GDI_ReleaseObj( hdc );
716             GDI_ReleaseObj( hbitmap );
717
718             return 0;
719         }
720     }
721     else if( info->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) ) 
722     {
723         /* fill in struct members */
724
725         if( info->bmiHeader.biBitCount == 0)
726         {
727             info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
728             info->bmiHeader.biHeight = bmp->bitmap.bmHeight;
729             info->bmiHeader.biPlanes = 1;
730             info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
731             info->bmiHeader.biSizeImage = 
732                              DIB_GetDIBImageBytes( bmp->bitmap.bmWidth,
733                                                    bmp->bitmap.bmHeight,
734                                                    bmp->bitmap.bmBitsPixel );
735             info->bmiHeader.biCompression = 0;
736         }
737         else
738         {
739             info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(
740                                                info->bmiHeader.biWidth,
741                                                info->bmiHeader.biHeight,
742                                                info->bmiHeader.biBitCount );
743         }
744     }
745
746     TRACE("biSizeImage = %ld, biWidth = %ld, biHeight = %ld\n",
747           info->bmiHeader.biSizeImage, info->bmiHeader.biWidth,
748           info->bmiHeader.biHeight);
749
750     GDI_ReleaseObj( hdc );
751     GDI_ReleaseObj( hbitmap );
752
753     return lines;
754 }
755
756
757 /***********************************************************************
758  *           CreateDIBitmap16    (GDI.442)
759  */
760 HBITMAP16 WINAPI CreateDIBitmap16( HDC16 hdc, const BITMAPINFOHEADER * header,
761                             DWORD init, LPCVOID bits, const BITMAPINFO * data,
762                             UINT16 coloruse )
763 {
764     return CreateDIBitmap( hdc, header, init, bits, data, coloruse );
765 }
766
767
768 /***********************************************************************
769  *           CreateDIBitmap    (GDI32.37)
770  */
771 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
772                             DWORD init, LPCVOID bits, const BITMAPINFO *data,
773                             UINT coloruse )
774 {
775     HBITMAP handle;
776     BOOL fColor;
777     DWORD width;
778     int height;
779     WORD bpp;
780     WORD compr;
781
782     if (DIB_GetBitmapInfo( header, &width, &height, &bpp, &compr ) == -1) return 0;
783     if (height < 0) height = -height;
784
785     /* Check if we should create a monochrome or color bitmap. */
786     /* We create a monochrome bitmap only if it has exactly 2  */
787     /* colors, which are black followed by white, nothing else.  */
788     /* In all other cases, we create a color bitmap.           */
789
790     if (bpp != 1) fColor = TRUE;
791     else if ((coloruse != DIB_RGB_COLORS) ||
792              (init != CBM_INIT) || !data) fColor = FALSE;
793     else
794     {
795         if (data->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
796         {
797             RGBQUAD *rgb = data->bmiColors;
798             DWORD col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
799
800             /* Check if the first color of the colormap is black */ 
801             if ((col == RGB(0,0,0)))
802             {
803                 rgb++;
804                 col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
805                 /* If the second color is white, create a monochrome bitmap */
806                 fColor =  (col != RGB(0xff,0xff,0xff));
807             }
808             /* Note : If the first color of the colormap is white 
809                followed by black, we have to create a color bitmap. 
810                If we don't the white will be displayed in black later on!*/ 
811             else fColor = TRUE;
812         }
813         else if (data->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
814         {
815             RGBTRIPLE *rgb = ((BITMAPCOREINFO *)data)->bmciColors;
816             DWORD col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue );
817             if ((col == RGB(0,0,0)))
818             {
819                 rgb++;
820                 col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue );
821                 fColor = (col != RGB(0xff,0xff,0xff));
822             }
823             else fColor = TRUE;
824         }
825         else
826         {
827             WARN("(%ld): wrong size for data\n",
828                      data->bmiHeader.biSize );
829             return 0;
830         }
831     }
832
833     /* Now create the bitmap */
834
835     if (fColor)
836     {
837         HDC tmpdc = CreateDCA( "DISPLAY", NULL, NULL, NULL );
838         handle = CreateCompatibleBitmap( tmpdc, width, height );
839         DeleteDC( tmpdc );
840     }
841     else handle = CreateBitmap( width, height, 1, 1, NULL );
842
843     if (!handle) return 0;
844
845     if (init == CBM_INIT)
846         SetDIBits( hdc, handle, 0, height, bits, data, coloruse );
847     return handle;
848 }
849
850 /***********************************************************************
851  *           CreateDIBSection16    (GDI.489)
852  */
853 HBITMAP16 WINAPI CreateDIBSection16 (HDC16 hdc, BITMAPINFO *bmi, UINT16 usage,
854                                      SEGPTR *bits, HANDLE section,
855                                      DWORD offset)
856 {
857     HBITMAP16 hbitmap = 0;
858     DC *dc;
859     BOOL bDesktopDC = FALSE;
860
861     /* If the reference hdc is null, take the desktop dc */
862     if (hdc == 0)
863     {
864         hdc = CreateCompatibleDC(0);
865         bDesktopDC = TRUE;
866     }
867
868     if ((dc = DC_GetDCPtr( hdc )))
869     {
870         hbitmap = dc->funcs->pCreateDIBSection16(dc, bmi, usage, bits, section, offset, 0);
871         GDI_ReleaseObj(hdc);
872     }
873
874     if (bDesktopDC)
875       DeleteDC(hdc);
876
877     return hbitmap;
878 }
879
880 /***********************************************************************
881  *           DIB_CreateDIBSection
882  */
883 HBITMAP DIB_CreateDIBSection(HDC hdc, BITMAPINFO *bmi, UINT usage,
884                              LPVOID *bits, HANDLE section,
885                              DWORD offset, DWORD ovr_pitch)
886 {
887     HBITMAP hbitmap = 0;
888     DC *dc;
889     BOOL bDesktopDC = FALSE;
890
891     /* If the reference hdc is null, take the desktop dc */
892     if (hdc == 0)
893     {
894         hdc = CreateCompatibleDC(0);
895         bDesktopDC = TRUE;
896     }
897
898     if ((dc = DC_GetDCPtr( hdc )))
899     {
900         hbitmap = dc->funcs->pCreateDIBSection(dc, bmi, usage, bits, section, offset, ovr_pitch);
901         GDI_ReleaseObj(hdc);
902     }
903
904     if (bDesktopDC)
905       DeleteDC(hdc);
906
907     return hbitmap;
908 }
909
910 /***********************************************************************
911  *           CreateDIBSection    (GDI32.36)
912  */
913 HBITMAP WINAPI CreateDIBSection(HDC hdc, BITMAPINFO *bmi, UINT usage,
914                                 LPVOID *bits, HANDLE section,
915                                 DWORD offset)
916 {
917     return DIB_CreateDIBSection(hdc, bmi, usage, bits, section, offset, 0);
918 }
919
920 /***********************************************************************
921  *           DIB_DeleteDIBSection
922  */
923 void DIB_DeleteDIBSection( BITMAPOBJ *bmp )
924 {
925     if (bmp && bmp->dib)
926     {
927         DIBSECTION *dib = bmp->dib;
928
929         if (dib->dsBm.bmBits)
930         {
931             if (dib->dshSection)
932                 UnmapViewOfFile(dib->dsBm.bmBits);
933             else if (!dib->dsOffset)
934                 VirtualFree(dib->dsBm.bmBits, 0L, MEM_RELEASE );
935         }
936
937         BITMAP_Driver->pDeleteDIBSection(bmp);
938
939         HeapFree(GetProcessHeap(), 0, dib);
940         bmp->dib = NULL;
941     }
942 }
943
944 /***********************************************************************
945  *           DIB_CreateDIBFromBitmap
946  *  Allocates a packed DIB and copies the bitmap data into it.
947  */
948 HGLOBAL DIB_CreateDIBFromBitmap(HDC hdc, HBITMAP hBmp)
949 {
950     BITMAPOBJ *pBmp = NULL;
951     HGLOBAL hPackedDIB = 0;
952     LPBYTE pPackedDIB = NULL;
953     LPBITMAPINFOHEADER pbmiHeader = NULL;
954     unsigned int width, height, depth, cDataSize = 0, cPackedSize = 0,
955                  OffsetBits = 0, nLinesCopied = 0;
956
957     /* Get a pointer to the BITMAPOBJ structure */
958     pBmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
959     if (!pBmp) return hPackedDIB;
960
961     /* Get the bitmap dimensions */
962     width = pBmp->bitmap.bmWidth;
963     height = pBmp->bitmap.bmHeight;
964     depth = pBmp->bitmap.bmBitsPixel;
965                  
966     /*
967      * A packed DIB contains a BITMAPINFO structure followed immediately by
968      * an optional color palette and the pixel data.
969      */
970
971     /* Calculate the size of the packed DIB */
972     cDataSize = DIB_GetDIBImageBytes( width, height, depth );
973     cPackedSize = sizeof(BITMAPINFOHEADER)
974                   + ( (depth <= 8) ? (sizeof(RGBQUAD) * (1 << depth)) : 0 )
975                   + cDataSize;
976     /* Get the offset to the bits */
977     OffsetBits = cPackedSize - cDataSize;
978
979     /* Allocate the packed DIB */
980     TRACE("\tAllocating packed DIB of size %d\n", cPackedSize);
981     hPackedDIB = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE /*| GMEM_ZEROINIT*/,
982                              cPackedSize );
983     if ( !hPackedDIB )
984     {
985         WARN("Could not allocate packed DIB!\n");
986         goto END;
987     }
988     
989     /* A packed DIB starts with a BITMAPINFOHEADER */
990     pPackedDIB = (LPBYTE)GlobalLock(hPackedDIB);
991     pbmiHeader = (LPBITMAPINFOHEADER)pPackedDIB;
992
993     /* Init the BITMAPINFOHEADER */
994     pbmiHeader->biSize = sizeof(BITMAPINFOHEADER);
995     pbmiHeader->biWidth = width;
996     pbmiHeader->biHeight = height;
997     pbmiHeader->biPlanes = 1;
998     pbmiHeader->biBitCount = depth;
999     pbmiHeader->biCompression = BI_RGB;
1000     pbmiHeader->biSizeImage = 0;
1001     pbmiHeader->biXPelsPerMeter = pbmiHeader->biYPelsPerMeter = 0;
1002     pbmiHeader->biClrUsed = 0;
1003     pbmiHeader->biClrImportant = 0;
1004
1005     /* Retrieve the DIB bits from the bitmap and fill in the
1006      * DIB color table if present */
1007     
1008     nLinesCopied = GetDIBits(hdc,                       /* Handle to device context */
1009                              hBmp,                      /* Handle to bitmap */
1010                              0,                         /* First scan line to set in dest bitmap */
1011                              height,                    /* Number of scan lines to copy */
1012                              pPackedDIB + OffsetBits,   /* [out] Address of array for bitmap bits */
1013                              (LPBITMAPINFO) pbmiHeader, /* [out] Address of BITMAPINFO structure */
1014                              0);                        /* RGB or palette index */
1015     GlobalUnlock(hPackedDIB);
1016
1017     /* Cleanup if GetDIBits failed */
1018     if (nLinesCopied != height)
1019     {
1020         TRACE("\tGetDIBits returned %d. Actual lines=%d\n", nLinesCopied, height);
1021         GlobalFree(hPackedDIB);
1022         hPackedDIB = 0;
1023     }
1024
1025 END:
1026     GDI_ReleaseObj( hBmp );
1027     return hPackedDIB;
1028 }