Implement A->W call for GetNamedSecurityInfo.
[wine] / dlls / gdi / dib.c
1 /*
2  * GDI device-independent bitmaps
3  *
4  * Copyright 1993,1994  Alexandre Julliard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include <stdarg.h>
22 #include <stdlib.h>
23 #include <string.h>
24
25 #include "windef.h"
26 #include "winbase.h"
27 #include "gdi.h"
28 #include "wownt32.h"
29 #include "gdi_private.h"
30 #include "wine/debug.h"
31
32 WINE_DEFAULT_DEBUG_CHANNEL(bitmap);
33
34 /***********************************************************************
35  *           DIB_GetDIBWidthBytes
36  *
37  * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
38  * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/bitmaps_87eb.asp
39  */
40 int DIB_GetDIBWidthBytes( int width, int depth )
41 {
42     int words;
43
44     switch(depth)
45     {
46         case 1:  words = (width + 31) / 32; break;
47         case 4:  words = (width + 7) / 8; break;
48         case 8:  words = (width + 3) / 4; break;
49         case 15:
50         case 16: words = (width + 1) / 2; break;
51         case 24: words = (width * 3 + 3)/4; break;
52
53         default:
54             WARN("(%d): Unsupported depth\n", depth );
55         /* fall through */
56         case 32:
57                 words = width;
58     }
59     return 4 * words;
60 }
61
62 /***********************************************************************
63  *           DIB_GetDIBImageBytes
64  *
65  * Return the number of bytes used to hold the image in a DIB bitmap.
66  */
67 int DIB_GetDIBImageBytes( int width, int height, int depth )
68 {
69     return DIB_GetDIBWidthBytes( width, depth ) * abs( height );
70 }
71
72
73 /***********************************************************************
74  *           DIB_BitmapInfoSize
75  *
76  * Return the size of the bitmap info structure including color table.
77  */
78 int DIB_BitmapInfoSize( const BITMAPINFO * info, WORD coloruse )
79 {
80     int colors;
81
82     if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
83     {
84         BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)info;
85         colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
86         return sizeof(BITMAPCOREHEADER) + colors *
87              ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
88     }
89     else  /* assume BITMAPINFOHEADER */
90     {
91         colors = info->bmiHeader.biClrUsed;
92         if (!colors && (info->bmiHeader.biBitCount <= 8))
93             colors = 1 << info->bmiHeader.biBitCount;
94         return sizeof(BITMAPINFOHEADER) + colors *
95                ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
96     }
97 }
98
99
100 /***********************************************************************
101  *           DIB_GetBitmapInfo
102  *
103  * Get the info from a bitmap header.
104  * Return 1 for INFOHEADER, 0 for COREHEADER,
105  * 4 for V4HEADER, 5 for V5HEADER, -1 for error.
106  */
107 static int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, DWORD *width,
108                               int *height, WORD *bpp, WORD *compr )
109 {
110     if (header->biSize == sizeof(BITMAPINFOHEADER))
111     {
112         *width  = header->biWidth;
113         *height = header->biHeight;
114         *bpp    = header->biBitCount;
115         *compr  = header->biCompression;
116         return 1;
117     }
118     if (header->biSize == sizeof(BITMAPCOREHEADER))
119     {
120         BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)header;
121         *width  = core->bcWidth;
122         *height = core->bcHeight;
123         *bpp    = core->bcBitCount;
124         *compr  = 0;
125         return 0;
126     }
127     if (header->biSize == sizeof(BITMAPV4HEADER))
128     {
129         BITMAPV4HEADER *v4hdr = (BITMAPV4HEADER *)header;
130         *width  = v4hdr->bV4Width;
131         *height = v4hdr->bV4Height;
132         *bpp    = v4hdr->bV4BitCount;
133         *compr  = v4hdr->bV4V4Compression;
134         return 4;
135     }
136     if (header->biSize == sizeof(BITMAPV5HEADER))
137     {
138         BITMAPV5HEADER *v5hdr = (BITMAPV5HEADER *)header;
139         *width  = v5hdr->bV5Width;
140         *height = v5hdr->bV5Height;
141         *bpp    = v5hdr->bV5BitCount;
142         *compr  = v5hdr->bV5Compression;
143         return 5;
144     }
145     ERR("(%ld): unknown/wrong size for header\n", header->biSize );
146     return -1;
147 }
148
149
150 /***********************************************************************
151  *           StretchDIBits   (GDI32.@)
152  */
153 INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst,
154                        INT heightDst, INT xSrc, INT ySrc, INT widthSrc,
155                        INT heightSrc, const void *bits,
156                        const BITMAPINFO *info, UINT wUsage, DWORD dwRop )
157 {
158     DC *dc;
159
160     if (!bits || !info)
161         return 0;
162
163     dc = DC_GetDCUpdate( hdc );
164     if(!dc) return FALSE;
165
166     if(dc->funcs->pStretchDIBits)
167     {
168         heightSrc = dc->funcs->pStretchDIBits(dc->physDev, xDst, yDst, widthDst,
169                                               heightDst, xSrc, ySrc, widthSrc,
170                                               heightSrc, bits, info, wUsage, dwRop);
171         GDI_ReleaseObj( hdc );
172     }
173     else /* use StretchBlt */
174     {
175         HBITMAP hBitmap, hOldBitmap;
176         HPALETTE hpal = NULL;
177         HDC hdcMem;
178
179         GDI_ReleaseObj( hdc );
180         hdcMem = CreateCompatibleDC( hdc );
181         hBitmap = CreateCompatibleBitmap(hdc, info->bmiHeader.biWidth,
182                                          info->bmiHeader.biHeight);
183         hOldBitmap = SelectObject( hdcMem, hBitmap );
184         if(wUsage == DIB_PAL_COLORS)
185         {
186             hpal = GetCurrentObject(hdc, OBJ_PAL);
187             hpal = SelectPalette(hdcMem, hpal, FALSE);
188         }
189
190         if (info->bmiHeader.biCompression == BI_RLE4 ||
191             info->bmiHeader.biCompression == BI_RLE8) {
192
193            /* when RLE compression is used, there may be some gaps (ie the DIB doesn't
194             * contain all the rectangle described in bmiHeader, but only part of it.
195             * This mean that those undescribed pixels must be left untouched.
196             * So, we first copy on a memory bitmap the current content of the
197             * destination rectangle, blit the DIB bits on top of it - hence leaving
198             * the gaps untouched -, and blitting the rectangle back.
199             * This insure that gaps are untouched on the destination rectangle
200             * Not doing so leads to trashed images (the gaps contain what was on the
201             * memory bitmap => generally black or garbage)
202             * Unfortunately, RLE DIBs without gaps will be slowed down. But this is
203             * another speed vs correctness issue. Anyway, if speed is needed, then the
204             * pStretchDIBits function shall be implemented.
205             * ericP (2000/09/09)
206             */
207
208             /* copy existing bitmap from destination dc */
209             StretchBlt( hdcMem, xSrc, abs(info->bmiHeader.biHeight) - heightSrc - ySrc,
210                         widthSrc, heightSrc, hdc, xDst, yDst, widthDst, heightDst,
211                         dwRop );
212         }
213
214         SetDIBits(hdcMem, hBitmap, 0, info->bmiHeader.biHeight, bits,
215                      info, wUsage);
216
217         /* Origin for DIBitmap may be bottom left (positive biHeight) or top
218            left (negative biHeight) */
219         StretchBlt( hdc, xDst, yDst, widthDst, heightDst,
220                     hdcMem, xSrc, abs(info->bmiHeader.biHeight) - heightSrc - ySrc,
221                     widthSrc, heightSrc, dwRop );
222         if(hpal)
223             SelectPalette(hdcMem, hpal, FALSE);
224         SelectObject( hdcMem, hOldBitmap );
225         DeleteDC( hdcMem );
226         DeleteObject( hBitmap );
227     }
228     return heightSrc;
229 }
230
231
232 /******************************************************************************
233  * SetDIBits [GDI32.@]
234  *
235  * Sets pixels in a bitmap using colors from DIB.
236  *
237  * PARAMS
238  *    hdc       [I] Handle to device context
239  *    hbitmap   [I] Handle to bitmap
240  *    startscan [I] Starting scan line
241  *    lines     [I] Number of scan lines
242  *    bits      [I] Array of bitmap bits
243  *    info      [I] Address of structure with data
244  *    coloruse  [I] Type of color indexes to use
245  *
246  * RETURNS
247  *    Success: Number of scan lines copied
248  *    Failure: 0
249  */
250 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
251                       UINT lines, LPCVOID bits, const BITMAPINFO *info,
252                       UINT coloruse )
253 {
254     DC *dc;
255     BITMAPOBJ *bitmap;
256     INT result = 0;
257
258     if (!(bitmap = GDI_GetObjPtr( hbitmap, BITMAP_MAGIC ))) return 0;
259
260     if (!(dc = DC_GetDCUpdate( hdc )))
261     {
262         if (coloruse == DIB_RGB_COLORS) FIXME( "shouldn't require a DC for DIB_RGB_COLORS\n" );
263         GDI_ReleaseObj( hbitmap );
264         return 0;
265     }
266
267     if (!bitmap->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) goto done;
268
269     if (bitmap->funcs && bitmap->funcs->pSetDIBits)
270         result = bitmap->funcs->pSetDIBits( dc->physDev, hbitmap, startscan, lines,
271                                             bits, info, coloruse );
272     else
273         result = lines;
274
275  done:
276     GDI_ReleaseObj( hdc );
277     GDI_ReleaseObj( hbitmap );
278     return result;
279 }
280
281
282 /***********************************************************************
283  *           SetDIBitsToDevice   (GDI32.@)
284  */
285 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
286                            DWORD cy, INT xSrc, INT ySrc, UINT startscan,
287                            UINT lines, LPCVOID bits, const BITMAPINFO *info,
288                            UINT coloruse )
289 {
290     INT ret;
291     DC *dc;
292
293     if (!(dc = DC_GetDCUpdate( hdc ))) return 0;
294
295     if(dc->funcs->pSetDIBitsToDevice)
296         ret = dc->funcs->pSetDIBitsToDevice( dc->physDev, xDest, yDest, cx, cy, xSrc,
297                                              ySrc, startscan, lines, bits,
298                                              info, coloruse );
299     else {
300         FIXME("unimplemented on hdc %p\n", hdc);
301         ret = 0;
302     }
303
304     GDI_ReleaseObj( hdc );
305     return ret;
306 }
307
308 /***********************************************************************
309  *           SetDIBColorTable    (GDI32.@)
310  */
311 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
312 {
313     DC * dc;
314     UINT result = 0;
315
316     if (!(dc = DC_GetDCUpdate( hdc ))) return 0;
317
318     if (dc->funcs->pSetDIBColorTable)
319         result = dc->funcs->pSetDIBColorTable(dc->physDev, startpos, entries, colors);
320
321     GDI_ReleaseObj( hdc );
322     return result;
323 }
324
325
326 /***********************************************************************
327  *           GetDIBColorTable    (GDI32.@)
328  */
329 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
330 {
331     DC * dc;
332     UINT result = 0;
333
334     if (!(dc = DC_GetDCUpdate( hdc ))) return 0;
335
336     if (dc->funcs->pGetDIBColorTable)
337         result = dc->funcs->pGetDIBColorTable(dc->physDev, startpos, entries, colors);
338
339     GDI_ReleaseObj( hdc );
340     return result;
341 }
342
343 /* FIXME the following two structs should be combined with __sysPalTemplate in
344    objects/color.c - this should happen after de-X11-ing both of these
345    files.
346    NB. RGBQUAD and PALETTEENTRY have different orderings of red, green
347    and blue - sigh */
348
349 static RGBQUAD EGAColors[16] = {
350 /* rgbBlue, rgbGreen, rgbRed, rgbReserverd */
351     { 0x00, 0x00, 0x00, 0x00 },
352     { 0x00, 0x00, 0x80, 0x00 },
353     { 0x00, 0x80, 0x00, 0x00 },
354     { 0x00, 0x80, 0x80, 0x00 },
355     { 0x80, 0x00, 0x00, 0x00 },
356     { 0x80, 0x00, 0x80, 0x00 },
357     { 0x80, 0x80, 0x00, 0x00 },
358     { 0x80, 0x80, 0x80, 0x00 },
359     { 0xc0, 0xc0, 0xc0, 0x00 },
360     { 0x00, 0x00, 0xff, 0x00 },
361     { 0x00, 0xff, 0x00, 0x00 },
362     { 0x00, 0xff, 0xff, 0x00 },
363     { 0xff, 0x00, 0x00, 0x00 },
364     { 0xff, 0x00, 0xff, 0x00 },
365     { 0xff, 0xff, 0x00, 0x00 },
366     { 0xff, 0xff, 0xff, 0x00 }
367 };
368
369
370 static RGBQUAD DefLogPalette[20] = { /* Copy of Default Logical Palette */
371 /* rgbBlue, rgbGreen, rgbRed, rgbReserverd */
372     { 0x00, 0x00, 0x00, 0x00 },
373     { 0x00, 0x00, 0x80, 0x00 },
374     { 0x00, 0x80, 0x00, 0x00 },
375     { 0x00, 0x80, 0x80, 0x00 },
376     { 0x80, 0x00, 0x00, 0x00 },
377     { 0x80, 0x00, 0x80, 0x00 },
378     { 0x80, 0x80, 0x00, 0x00 },
379     { 0xc0, 0xc0, 0xc0, 0x00 },
380     { 0xc0, 0xdc, 0xc0, 0x00 },
381     { 0xf0, 0xca, 0xa6, 0x00 },
382     { 0xf0, 0xfb, 0xff, 0x00 },
383     { 0xa4, 0xa0, 0xa0, 0x00 },
384     { 0x80, 0x80, 0x80, 0x00 },
385     { 0x00, 0x00, 0xf0, 0x00 },
386     { 0x00, 0xff, 0x00, 0x00 },
387     { 0x00, 0xff, 0xff, 0x00 },
388     { 0xff, 0x00, 0x00, 0x00 },
389     { 0xff, 0x00, 0xff, 0x00 },
390     { 0xff, 0xff, 0x00, 0x00 },
391     { 0xff, 0xff, 0xff, 0x00 }
392 };
393
394
395 /******************************************************************************
396  * GetDIBits [GDI32.@]
397  *
398  * Retrieves bits of bitmap and copies to buffer.
399  *
400  * RETURNS
401  *    Success: Number of scan lines copied from bitmap
402  *    Failure: 0
403  *
404  * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/bitmaps_87eb.asp
405  */
406 INT WINAPI GetDIBits(
407     HDC hdc,         /* [in]  Handle to device context */
408     HBITMAP hbitmap, /* [in]  Handle to bitmap */
409     UINT startscan,  /* [in]  First scan line to set in dest bitmap */
410     UINT lines,      /* [in]  Number of scan lines to copy */
411     LPVOID bits,       /* [out] Address of array for bitmap bits */
412     BITMAPINFO * info, /* [out] Address of structure with bitmap data */
413     UINT coloruse)   /* [in]  RGB or palette index */
414 {
415     DC * dc;
416     BITMAPOBJ * bmp;
417     int i;
418     HDC memdc;
419
420     if (!info) return 0;
421     memdc = CreateCompatibleDC(hdc);
422     if (!(dc = DC_GetDCUpdate( hdc )))
423     {
424         DeleteDC(memdc);
425         return 0;
426     }
427     if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
428     {
429         GDI_ReleaseObj( hdc );
430         DeleteDC(memdc);
431         return 0;
432     }
433
434     /* Transfer color info */
435
436     if (info->bmiHeader.biBitCount <= 8 && info->bmiHeader.biBitCount > 0 ) {
437
438         info->bmiHeader.biClrUsed = 0;
439
440         /* If the bitmap object already has a dib section at the
441            same color depth then get the color map from it */
442         if (bmp->dib && bmp->dib->dsBm.bmBitsPixel == info->bmiHeader.biBitCount) {
443             if(coloruse == DIB_RGB_COLORS) {
444                 HBITMAP oldbm;
445                 oldbm = SelectObject(memdc, hbitmap);
446                 GetDIBColorTable(memdc, 0, 1 << info->bmiHeader.biBitCount, info->bmiColors);
447                 SelectObject(memdc, oldbm);
448             }
449             else {
450                 WORD *index = (WORD*)info->bmiColors;
451                 int i;
452                 for(i = 0; i < 1 << info->bmiHeader.biBitCount; i++, index++)
453                     *index = i;
454             }
455         }
456         else {
457             if(info->bmiHeader.biBitCount >= bmp->bitmap.bmBitsPixel) {
458                 /* Generate the color map from the selected palette */
459                 PALETTEENTRY * palEntry;
460                 PALETTEOBJ * palette;
461                 if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->hPalette, PALETTE_MAGIC ))) {
462                     GDI_ReleaseObj( hdc );
463                     GDI_ReleaseObj( hbitmap );
464                     DeleteDC(memdc);
465                     return 0;
466                 }
467                 palEntry = palette->logpalette.palPalEntry;
468                 for (i = 0; i < (1 << bmp->bitmap.bmBitsPixel); i++, palEntry++) {
469                     if (coloruse == DIB_RGB_COLORS) {
470                         info->bmiColors[i].rgbRed      = palEntry->peRed;
471                         info->bmiColors[i].rgbGreen    = palEntry->peGreen;
472                         info->bmiColors[i].rgbBlue     = palEntry->peBlue;
473                         info->bmiColors[i].rgbReserved = 0;
474                     }
475                     else ((WORD *)info->bmiColors)[i] = (WORD)i;
476                 }
477                 GDI_ReleaseObj( dc->hPalette );
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
518     if (bits && lines)
519     {
520         /* If the bitmap object already have a dib section that contains image data, get the bits from it */
521         if(bmp->dib && bmp->dib->dsBm.bmBitsPixel >= 15 && info->bmiHeader.biBitCount >= 15)
522         {
523             /*FIXME: Only RGB dibs supported for now */
524             unsigned int srcwidth = bmp->dib->dsBm.bmWidth, srcwidthb = bmp->dib->dsBm.bmWidthBytes;
525             int dstwidthb = DIB_GetDIBWidthBytes( info->bmiHeader.biWidth, info->bmiHeader.biBitCount );
526             LPBYTE dbits = bits, sbits = (LPBYTE) bmp->dib->dsBm.bmBits + (startscan * srcwidthb);
527             unsigned int x, y;
528
529             if ((info->bmiHeader.biHeight < 0) ^ (bmp->dib->dsBmih.biHeight < 0))
530             {
531                 dbits = (LPBYTE)bits + (dstwidthb * (lines-1));
532                 dstwidthb = -dstwidthb;
533             }
534
535             switch( info->bmiHeader.biBitCount ) {
536
537             case 15:
538             case 16: /* 16 bpp dstDIB */
539                 {
540                     LPWORD dstbits = (LPWORD)dbits;
541                     WORD rmask = 0x7c00, gmask= 0x03e0, bmask = 0x001f;
542
543                     /* FIXME: BI_BITFIELDS not supported yet */
544
545                     switch(bmp->dib->dsBm.bmBitsPixel) {
546
547                     case 16: /* 16 bpp srcDIB -> 16 bpp dstDIB */
548                         {
549                             /* FIXME: BI_BITFIELDS not supported yet */
550                             for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
551                                 memcpy(dbits, sbits, srcwidthb);
552                         }
553                         break;
554
555                     case 24: /* 24 bpp srcDIB -> 16 bpp dstDIB */
556                         {
557                             LPBYTE srcbits = sbits;
558
559                             for( y = 0; y < lines; y++) {
560                                 for( x = 0; x < srcwidth; x++, srcbits += 3)
561                                     *dstbits++ = ((srcbits[0] >> 3) & bmask) |
562                                                  (((WORD)srcbits[1] << 2) & gmask) |
563                                                  (((WORD)srcbits[2] << 7) & rmask);
564
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 -> 32 bit DIB */
700                         FIXME("32 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
714         {
715             if (!bmp->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) lines = 0;
716             else
717             {
718                 if (bmp->funcs && bmp->funcs->pGetDIBits)
719                     lines = bmp->funcs->pGetDIBits( dc->physDev, hbitmap, startscan,
720                                                     lines, bits, info, coloruse );
721                 else
722                     lines = 0;  /* FIXME: should copy from bmp->bitmap.bmBits */
723             }
724         }
725     }
726     else if( info->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) )
727     {
728         /* fill in struct members */
729
730         if( info->bmiHeader.biBitCount == 0)
731         {
732             info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
733             info->bmiHeader.biHeight = bmp->bitmap.bmHeight;
734             info->bmiHeader.biPlanes = 1;
735             info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
736             info->bmiHeader.biSizeImage =
737                              DIB_GetDIBImageBytes( bmp->bitmap.bmWidth,
738                                                    bmp->bitmap.bmHeight,
739                                                    bmp->bitmap.bmBitsPixel );
740             info->bmiHeader.biCompression = 0;
741         }
742         else
743         {
744             info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(
745                                                info->bmiHeader.biWidth,
746                                                info->bmiHeader.biHeight,
747                                                info->bmiHeader.biBitCount );
748         }
749         lines = info->bmiHeader.biHeight;
750     }
751
752     TRACE("biSizeImage = %ld, biWidth = %ld, biHeight = %ld\n",
753           info->bmiHeader.biSizeImage, info->bmiHeader.biWidth,
754           info->bmiHeader.biHeight);
755
756     GDI_ReleaseObj( hdc );
757     GDI_ReleaseObj( hbitmap );
758     DeleteDC(memdc);
759     return lines;
760 }
761
762
763 /***********************************************************************
764  *           CreateDIBitmap    (GDI32.@)
765  */
766 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
767                             DWORD init, LPCVOID bits, const BITMAPINFO *data,
768                             UINT coloruse )
769 {
770     HBITMAP handle;
771     BOOL fColor;
772     DWORD width;
773     int height;
774     WORD bpp;
775     WORD compr;
776     DC *dc;
777
778     if (DIB_GetBitmapInfo( header, &width, &height, &bpp, &compr ) == -1) return 0;
779     if (height < 0) height = -height;
780
781     /* Check if we should create a monochrome or color bitmap. */
782     /* We create a monochrome bitmap only if it has exactly 2  */
783     /* colors, which are black followed by white, nothing else.  */
784     /* In all other cases, we create a color bitmap.           */
785
786     if (bpp != 1) fColor = TRUE;
787     else if ((coloruse != DIB_RGB_COLORS) || !data) fColor = FALSE;
788     else
789     {
790         if (data->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
791         {
792             RGBQUAD *rgb = data->bmiColors;
793             DWORD col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
794
795             /* Check if the first color of the colormap is black */
796             if ((col == RGB(0,0,0)))
797             {
798                 rgb++;
799                 col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
800                 /* If the second color is white, create a monochrome bitmap */
801                 fColor =  (col != RGB(0xff,0xff,0xff));
802             }
803             /* Note : If the first color of the colormap is white
804                followed by black, we have to create a color bitmap.
805                If we don't the white will be displayed in black later on!*/
806             else fColor = TRUE;
807         }
808         else if (data->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
809         {
810             RGBTRIPLE *rgb = ((BITMAPCOREINFO *)data)->bmciColors;
811             DWORD col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue );
812             if ((col == RGB(0,0,0)))
813             {
814                 rgb++;
815                 col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue );
816                 fColor = (col != RGB(0xff,0xff,0xff));
817             }
818             else fColor = TRUE;
819         }
820         else if (data->bmiHeader.biSize == sizeof(BITMAPV4HEADER))
821         { /* FIXME: correct ? */
822             RGBQUAD *rgb = data->bmiColors;
823             DWORD col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
824
825             /* Check if the first color of the colormap is black */
826             if ((col == RGB(0,0,0)))
827             {
828                 rgb++;
829                 col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
830                 /* If the second color is white, create a monochrome bitmap */
831                 fColor =  (col != RGB(0xff,0xff,0xff));
832             }
833             /* Note : If the first color of the colormap is white
834                followed by black, we have to create a color bitmap.
835                If we don't the white will be displayed in black later on!*/
836             else fColor = TRUE;
837         }
838         else
839         {
840             ERR("(%ld): wrong/unknown size for data\n",
841                      data->bmiHeader.biSize );
842             return 0;
843         }
844     }
845
846     /* Now create the bitmap */
847
848     if (!(dc = DC_GetDCPtr( hdc ))) return 0;
849
850     if (fColor)
851         handle = CreateBitmap( width, height, GetDeviceCaps( hdc, PLANES ),
852                                GetDeviceCaps( hdc, BITSPIXEL ), NULL );
853     else handle = CreateBitmap( width, height, 1, 1, NULL );
854
855     if (handle)
856     {
857         if (init == CBM_INIT) SetDIBits( hdc, handle, 0, height, bits, data, coloruse );
858         else if (!BITMAP_SetOwnerDC( handle, dc ))
859         {
860             DeleteObject( handle );
861             handle = 0;
862         }
863     }
864
865     GDI_ReleaseObj( hdc );
866     return handle;
867 }
868
869 /***********************************************************************
870  *           CreateDIBSection    (GDI.489)
871  */
872 HBITMAP16 WINAPI CreateDIBSection16 (HDC16 hdc, const BITMAPINFO *bmi, UINT16 usage,
873                                      SEGPTR *bits16, HANDLE section, DWORD offset)
874 {
875     LPVOID bits32;
876     HBITMAP hbitmap;
877
878     hbitmap = CreateDIBSection( HDC_32(hdc), bmi, usage, &bits32, section, offset );
879     if (hbitmap)
880     {
881         BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr(hbitmap, BITMAP_MAGIC);
882         if (bmp && bmp->dib && bits32)
883         {
884             const BITMAPINFOHEADER *bi = &bmi->bmiHeader;
885             INT height = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
886             INT width_bytes = DIB_GetDIBWidthBytes(bi->biWidth, bi->biBitCount);
887             INT size  = (bi->biSizeImage && bi->biCompression != BI_RGB) ?
888                          bi->biSizeImage : width_bytes * height;
889
890             /* calculate number of sel's needed for size with 64K steps */
891             WORD count = (size + 0xffff) / 0x10000;
892             WORD sel = AllocSelectorArray16(count);
893             int i;
894
895             for (i = 0; i < count; i++)
896             {
897                 SetSelectorBase(sel + (i << __AHSHIFT), (DWORD)bits32 + i * 0x10000);
898                 SetSelectorLimit16(sel + (i << __AHSHIFT), size - 1); /* yep, limit is correct */
899                 size -= 0x10000;
900             }
901             bmp->segptr_bits = MAKESEGPTR( sel, 0 );
902             if (bits16) *bits16 = bmp->segptr_bits;
903         }
904         if (bmp) GDI_ReleaseObj( hbitmap );
905     }
906     return HBITMAP_16(hbitmap);
907 }
908
909 /***********************************************************************
910  *           DIB_CreateDIBSection
911  */
912 HBITMAP DIB_CreateDIBSection(HDC hdc, const BITMAPINFO *bmi, UINT usage,
913                              VOID **bits, HANDLE section,
914                              DWORD offset, DWORD ovr_pitch)
915 {
916     HBITMAP hbitmap = 0;
917     DC *dc;
918     BOOL bDesktopDC = FALSE;
919
920     /* If the reference hdc is null, take the desktop dc */
921     if (hdc == 0)
922     {
923         hdc = CreateCompatibleDC(0);
924         bDesktopDC = TRUE;
925     }
926
927     if ((dc = DC_GetDCPtr( hdc )))
928     {
929         if(dc->funcs->pCreateDIBSection)
930             hbitmap = dc->funcs->pCreateDIBSection(dc->physDev, bmi, usage, bits, section, offset, ovr_pitch);
931         GDI_ReleaseObj(hdc);
932     }
933
934     if (bDesktopDC)
935       DeleteDC(hdc);
936
937     return hbitmap;
938 }
939
940 /***********************************************************************
941  *           CreateDIBSection    (GDI32.@)
942  */
943 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
944                                 VOID **bits, HANDLE section,
945                                 DWORD offset)
946 {
947     return DIB_CreateDIBSection(hdc, bmi, usage, bits, section, offset, 0);
948 }