Declaration, implemention and test for BuildTrusteeWithSid.
[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             unsigned int dstwidth = info->bmiHeader.biWidth;
526             int dstwidthb = DIB_GetDIBWidthBytes( info->bmiHeader.biWidth, info->bmiHeader.biBitCount );
527             LPBYTE dbits = bits, sbits = (LPBYTE) bmp->dib->dsBm.bmBits + (startscan * srcwidthb);
528             unsigned int x, y, width, widthb;
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                             widthb = min(srcwidthb, abs(dstwidthb));
551                             /* FIXME: BI_BITFIELDS not supported yet */
552                             for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
553                                 memcpy(dbits, sbits, widthb);
554                         }
555                         break;
556
557                     case 24: /* 24 bpp srcDIB -> 16 bpp dstDIB */
558                         {
559                             LPBYTE srcbits = sbits;
560
561                             width = min(srcwidth, dstwidth);
562                             for( y = 0; y < lines; y++) {
563                                 for( x = 0; x < width; x++, srcbits += 3)
564                                     *dstbits++ = ((srcbits[0] >> 3) & bmask) |
565                                                  (((WORD)srcbits[1] << 2) & gmask) |
566                                                  (((WORD)srcbits[2] << 7) & rmask);
567
568                                 dstbits = (LPWORD)(dbits+=dstwidthb);
569                                 srcbits = (sbits += srcwidthb);
570                             }
571                         }
572                         break;
573
574                     case 32: /* 32 bpp srcDIB -> 16 bpp dstDIB */
575                         {
576                             LPDWORD srcbits = (LPDWORD)sbits;
577                             DWORD val;
578
579                             width = min(srcwidth, dstwidth);
580                             for( y = 0; y < lines; y++) {
581                                 for( x = 0; x < width; x++ ) {
582                                     val = *srcbits++;
583                                     *dstbits++ = (WORD)(((val >> 3) & bmask) | ((val >> 6) & gmask) |
584                                                        ((val >> 9) & rmask));
585                                 }
586                                 dstbits = (LPWORD)(dbits+=dstwidthb);
587                                 srcbits = (LPDWORD)(sbits+=srcwidthb);
588                             }
589                         }
590                         break;
591
592                     default: /* ? bit bmp -> 16 bit DIB */
593                         FIXME("15/16 bit DIB %d bit bitmap\n",
594                         bmp->bitmap.bmBitsPixel);
595                         break;
596                     }
597                 }
598                 break;
599
600             case 24: /* 24 bpp dstDIB */
601                 {
602                     LPBYTE dstbits = dbits;
603
604                     switch(bmp->dib->dsBm.bmBitsPixel) {
605
606                     case 16: /* 16 bpp srcDIB -> 24 bpp dstDIB */
607                         {
608                             LPWORD srcbits = (LPWORD)sbits;
609                             WORD val;
610
611                             width = min(srcwidth, dstwidth);
612                             /* FIXME: BI_BITFIELDS not supported yet */
613                             for( y = 0; y < lines; y++) {
614                                 for( x = 0; x < width; x++ ) {
615                                     val = *srcbits++;
616                                     *dstbits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07));
617                                     *dstbits++ = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07));
618                                     *dstbits++ = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07));
619                                 }
620                                 dstbits = (LPBYTE)(dbits+=dstwidthb);
621                                 srcbits = (LPWORD)(sbits+=srcwidthb);
622                             }
623                         }
624                         break;
625
626                     case 24: /* 24 bpp srcDIB -> 24 bpp dstDIB */
627                         {
628                             widthb = min(srcwidthb, abs(dstwidthb));
629                             for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
630                                 memcpy(dbits, sbits, widthb);
631                         }
632                         break;
633
634                     case 32: /* 32 bpp srcDIB -> 24 bpp dstDIB */
635                         {
636                             LPBYTE srcbits = (LPBYTE)sbits;
637
638                             width = min(srcwidth, dstwidth);
639                             for( y = 0; y < lines; y++) {
640                                 for( x = 0; x < width; x++, srcbits++ ) {
641                                     *dstbits++ = *srcbits++;
642                                     *dstbits++ = *srcbits++;
643                                     *dstbits++ = *srcbits++;
644                                 }
645                                 dstbits=(LPBYTE)(dbits+=dstwidthb);
646                                 srcbits = (LPBYTE)(sbits+=srcwidthb);
647                             }
648                         }
649                         break;
650
651                     default: /* ? bit bmp -> 24 bit DIB */
652                         FIXME("24 bit DIB %d bit bitmap\n",
653                               bmp->bitmap.bmBitsPixel);
654                         break;
655                     }
656                 }
657                 break;
658
659             case 32: /* 32 bpp dstDIB */
660                 {
661                     LPDWORD dstbits = (LPDWORD)dbits;
662
663                     /* FIXME: BI_BITFIELDS not supported yet */
664
665                     switch(bmp->dib->dsBm.bmBitsPixel) {
666                         case 16: /* 16 bpp srcDIB -> 32 bpp dstDIB */
667                         {
668                             LPWORD srcbits = (LPWORD)sbits;
669                             DWORD val;
670
671                             width = min(srcwidth, dstwidth);
672                             /* FIXME: BI_BITFIELDS not supported yet */
673                             for( y = 0; y < lines; y++) {
674                                 for( x = 0; x < width; x++ ) {
675                                     val = (DWORD)*srcbits++;
676                                     *dstbits++ = ((val << 3) & 0xf8) | ((val >> 2) & 0x07) |
677                                                  ((val << 6) & 0xf800) | ((val << 1) & 0x0700) |
678                                                  ((val << 9) & 0xf80000) | ((val << 4) & 0x070000);
679                                 }
680                                 dstbits=(LPDWORD)(dbits+=dstwidthb);
681                                 srcbits=(LPWORD)(sbits+=srcwidthb);
682                             }
683                         }
684                         break;
685
686                     case 24: /* 24 bpp srcDIB -> 32 bpp dstDIB */
687                         {
688                             LPBYTE srcbits = sbits;
689
690                             width = min(srcwidth, dstwidth);
691                             for( y = 0; y < lines; y++) {
692                                 for( x = 0; x < width; x++, srcbits+=3 )
693                                     *dstbits++ = ((DWORD)*srcbits) & 0x00ffffff;
694                                 dstbits=(LPDWORD)(dbits+=dstwidthb);
695                                 srcbits=(sbits+=srcwidthb);
696                             }
697                         }
698                         break;
699
700                     case 32: /* 32 bpp srcDIB -> 32 bpp dstDIB */
701                         {
702                             widthb = min(srcwidthb, abs(dstwidthb));
703                             /* FIXME: BI_BITFIELDS not supported yet */
704                             for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb) {
705                                 memcpy(dbits, sbits, widthb);
706                             }
707                         }
708                         break;
709
710                     default: /* ? bit bmp -> 32 bit DIB */
711                         FIXME("32 bit DIB %d bit bitmap\n",
712                         bmp->bitmap.bmBitsPixel);
713                         break;
714                     }
715                 }
716                 break;
717
718             default: /* ? bit DIB */
719                 FIXME("Unsupported DIB depth %d\n", info->bmiHeader.biBitCount);
720                 break;
721             }
722         }
723         /* Otherwise, get bits from the XImage */
724         else
725         {
726             if (!bmp->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) lines = 0;
727             else
728             {
729                 if (bmp->funcs && bmp->funcs->pGetDIBits)
730                     lines = bmp->funcs->pGetDIBits( dc->physDev, hbitmap, startscan,
731                                                     lines, bits, info, coloruse );
732                 else
733                     lines = 0;  /* FIXME: should copy from bmp->bitmap.bmBits */
734             }
735         }
736     }
737     else if( info->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) )
738     {
739         /* fill in struct members */
740
741         if( info->bmiHeader.biBitCount == 0)
742         {
743             info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
744             info->bmiHeader.biHeight = bmp->bitmap.bmHeight;
745             info->bmiHeader.biPlanes = 1;
746             info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
747             info->bmiHeader.biSizeImage =
748                              DIB_GetDIBImageBytes( bmp->bitmap.bmWidth,
749                                                    bmp->bitmap.bmHeight,
750                                                    bmp->bitmap.bmBitsPixel );
751             info->bmiHeader.biCompression = 0;
752         }
753         else
754         {
755             info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(
756                                                info->bmiHeader.biWidth,
757                                                info->bmiHeader.biHeight,
758                                                info->bmiHeader.biBitCount );
759         }
760         lines = info->bmiHeader.biHeight;
761     }
762
763     TRACE("biSizeImage = %ld, biWidth = %ld, biHeight = %ld\n",
764           info->bmiHeader.biSizeImage, info->bmiHeader.biWidth,
765           info->bmiHeader.biHeight);
766
767     GDI_ReleaseObj( hdc );
768     GDI_ReleaseObj( hbitmap );
769     DeleteDC(memdc);
770     return lines;
771 }
772
773
774 /***********************************************************************
775  *           CreateDIBitmap    (GDI32.@)
776  */
777 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
778                             DWORD init, LPCVOID bits, const BITMAPINFO *data,
779                             UINT coloruse )
780 {
781     HBITMAP handle;
782     BOOL fColor;
783     DWORD width;
784     int height;
785     WORD bpp;
786     WORD compr;
787     DC *dc;
788
789     if (DIB_GetBitmapInfo( header, &width, &height, &bpp, &compr ) == -1) return 0;
790     if (height < 0) height = -height;
791
792     /* Check if we should create a monochrome or color bitmap. */
793     /* We create a monochrome bitmap only if it has exactly 2  */
794     /* colors, which are black followed by white, nothing else.  */
795     /* In all other cases, we create a color bitmap.           */
796
797     if (bpp != 1) fColor = TRUE;
798     else if ((coloruse != DIB_RGB_COLORS) || !data) fColor = FALSE;
799     else
800     {
801         if (data->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
802         {
803             RGBQUAD *rgb = data->bmiColors;
804             DWORD col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
805
806             /* Check if the first color of the colormap is black */
807             if ((col == RGB(0,0,0)))
808             {
809                 rgb++;
810                 col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
811                 /* If the second color is white, create a monochrome bitmap */
812                 fColor =  (col != RGB(0xff,0xff,0xff));
813             }
814             /* Note : If the first color of the colormap is white
815                followed by black, we have to create a color bitmap.
816                If we don't the white will be displayed in black later on!*/
817             else fColor = TRUE;
818         }
819         else if (data->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
820         {
821             RGBTRIPLE *rgb = ((BITMAPCOREINFO *)data)->bmciColors;
822             DWORD col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue );
823             if ((col == RGB(0,0,0)))
824             {
825                 rgb++;
826                 col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue );
827                 fColor = (col != RGB(0xff,0xff,0xff));
828             }
829             else fColor = TRUE;
830         }
831         else if (data->bmiHeader.biSize == sizeof(BITMAPV4HEADER))
832         { /* FIXME: correct ? */
833             RGBQUAD *rgb = data->bmiColors;
834             DWORD col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
835
836             /* Check if the first color of the colormap is black */
837             if ((col == RGB(0,0,0)))
838             {
839                 rgb++;
840                 col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
841                 /* If the second color is white, create a monochrome bitmap */
842                 fColor =  (col != RGB(0xff,0xff,0xff));
843             }
844             /* Note : If the first color of the colormap is white
845                followed by black, we have to create a color bitmap.
846                If we don't the white will be displayed in black later on!*/
847             else fColor = TRUE;
848         }
849         else
850         {
851             ERR("(%ld): wrong/unknown size for data\n",
852                      data->bmiHeader.biSize );
853             return 0;
854         }
855     }
856
857     /* Now create the bitmap */
858
859     if (!(dc = DC_GetDCPtr( hdc ))) return 0;
860
861     if (fColor)
862         handle = CreateBitmap( width, height, GetDeviceCaps( hdc, PLANES ),
863                                GetDeviceCaps( hdc, BITSPIXEL ), NULL );
864     else handle = CreateBitmap( width, height, 1, 1, NULL );
865
866     if (handle)
867     {
868         if (init == CBM_INIT) SetDIBits( hdc, handle, 0, height, bits, data, coloruse );
869         else if (!BITMAP_SetOwnerDC( handle, dc ))
870         {
871             DeleteObject( handle );
872             handle = 0;
873         }
874     }
875
876     GDI_ReleaseObj( hdc );
877     return handle;
878 }
879
880 /***********************************************************************
881  *           CreateDIBSection    (GDI.489)
882  */
883 HBITMAP16 WINAPI CreateDIBSection16 (HDC16 hdc, const BITMAPINFO *bmi, UINT16 usage,
884                                      SEGPTR *bits16, HANDLE section, DWORD offset)
885 {
886     LPVOID bits32;
887     HBITMAP hbitmap;
888
889     hbitmap = CreateDIBSection( HDC_32(hdc), bmi, usage, &bits32, section, offset );
890     if (hbitmap)
891     {
892         BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr(hbitmap, BITMAP_MAGIC);
893         if (bmp && bmp->dib && bits32)
894         {
895             const BITMAPINFOHEADER *bi = &bmi->bmiHeader;
896             INT height = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
897             INT width_bytes = DIB_GetDIBWidthBytes(bi->biWidth, bi->biBitCount);
898             INT size  = (bi->biSizeImage && bi->biCompression != BI_RGB) ?
899                          bi->biSizeImage : width_bytes * height;
900
901             /* calculate number of sel's needed for size with 64K steps */
902             WORD count = (size + 0xffff) / 0x10000;
903             WORD sel = AllocSelectorArray16(count);
904             int i;
905
906             for (i = 0; i < count; i++)
907             {
908                 SetSelectorBase(sel + (i << __AHSHIFT), (DWORD)bits32 + i * 0x10000);
909                 SetSelectorLimit16(sel + (i << __AHSHIFT), size - 1); /* yep, limit is correct */
910                 size -= 0x10000;
911             }
912             bmp->segptr_bits = MAKESEGPTR( sel, 0 );
913             if (bits16) *bits16 = bmp->segptr_bits;
914         }
915         if (bmp) GDI_ReleaseObj( hbitmap );
916     }
917     return HBITMAP_16(hbitmap);
918 }
919
920 /***********************************************************************
921  *           DIB_CreateDIBSection
922  */
923 HBITMAP DIB_CreateDIBSection(HDC hdc, const BITMAPINFO *bmi, UINT usage,
924                              VOID **bits, HANDLE section,
925                              DWORD offset, DWORD ovr_pitch)
926 {
927     HBITMAP hbitmap = 0;
928     DC *dc;
929     BOOL bDesktopDC = FALSE;
930
931     /* If the reference hdc is null, take the desktop dc */
932     if (hdc == 0)
933     {
934         hdc = CreateCompatibleDC(0);
935         bDesktopDC = TRUE;
936     }
937
938     if ((dc = DC_GetDCPtr( hdc )))
939     {
940         if(dc->funcs->pCreateDIBSection)
941             hbitmap = dc->funcs->pCreateDIBSection(dc->physDev, bmi, usage, bits, section, offset, ovr_pitch);
942         GDI_ReleaseObj(hdc);
943     }
944
945     if (bDesktopDC)
946       DeleteDC(hdc);
947
948     return hbitmap;
949 }
950
951 /***********************************************************************
952  *           CreateDIBSection    (GDI32.@)
953  */
954 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
955                                 VOID **bits, HANDLE section,
956                                 DWORD offset)
957 {
958     return DIB_CreateDIBSection(hdc, bmi, usage, bits, section, offset, 0);
959 }