Moved more GDI definitions to gdi_private.h.
[wine] / objects / 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://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/struc/src/str01.htm
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         HDC hdcMem;
177
178         GDI_ReleaseObj( hdc );
179         hdcMem = CreateCompatibleDC( hdc );
180         hBitmap = CreateCompatibleBitmap(hdc, info->bmiHeader.biWidth,
181                                          info->bmiHeader.biHeight);
182         hOldBitmap = SelectObject( hdcMem, hBitmap );
183
184         if (info->bmiHeader.biCompression == BI_RLE4 ||
185             info->bmiHeader.biCompression == BI_RLE8) {
186
187            /* when RLE compression is used, there may be some gaps (ie the DIB doesn't
188             * contain all the rectangle described in bmiHeader, but only part of it.
189             * This mean that those undescribed pixels must be left untouched.
190             * So, we first copy on a memory bitmap the current content of the
191             * destination rectangle, blit the DIB bits on top of it - hence leaving
192             * the gaps untouched -, and blitting the rectangle back.
193             * This insure that gaps are untouched on the destination rectangle
194             * Not doing so leads to trashed images (the gaps contain what was on the
195             * memory bitmap => generally black or garbage)
196             * Unfortunately, RLE DIBs without gaps will be slowed down. But this is
197             * another speed vs correctness issue. Anyway, if speed is needed, then the
198             * pStretchDIBits function shall be implemented.
199             * ericP (2000/09/09)
200             */
201
202             /* copy existing bitmap from destination dc */
203             StretchBlt( hdcMem, xSrc, abs(info->bmiHeader.biHeight) - heightSrc - ySrc,
204                         widthSrc, heightSrc, hdc, xDst, yDst, widthDst, heightDst,
205                         dwRop );
206         }
207
208         SetDIBits(hdcMem, hBitmap, 0, info->bmiHeader.biHeight, bits,
209                      info, wUsage);
210
211         /* Origin for DIBitmap may be bottom left (positive biHeight) or top
212            left (negative biHeight) */
213         StretchBlt( hdc, xDst, yDst, widthDst, heightDst,
214                     hdcMem, xSrc, abs(info->bmiHeader.biHeight) - heightSrc - ySrc,
215                     widthSrc, heightSrc, dwRop );
216         SelectObject( hdcMem, hOldBitmap );
217         DeleteDC( hdcMem );
218         DeleteObject( hBitmap );
219     }
220     return heightSrc;
221 }
222
223
224 /******************************************************************************
225  * SetDIBits [GDI32.@]
226  *
227  * Sets pixels in a bitmap using colors from DIB.
228  *
229  * PARAMS
230  *    hdc       [I] Handle to device context
231  *    hbitmap   [I] Handle to bitmap
232  *    startscan [I] Starting scan line
233  *    lines     [I] Number of scan lines
234  *    bits      [I] Array of bitmap bits
235  *    info      [I] Address of structure with data
236  *    coloruse  [I] Type of color indexes to use
237  *
238  * RETURNS
239  *    Success: Number of scan lines copied
240  *    Failure: 0
241  */
242 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
243                       UINT lines, LPCVOID bits, const BITMAPINFO *info,
244                       UINT coloruse )
245 {
246     DC *dc;
247     BITMAPOBJ *bitmap;
248     INT result = 0;
249
250     if (!(bitmap = GDI_GetObjPtr( hbitmap, BITMAP_MAGIC ))) return 0;
251
252     if (!(dc = DC_GetDCUpdate( hdc )))
253     {
254         if (coloruse == DIB_RGB_COLORS) FIXME( "shouldn't require a DC for DIB_RGB_COLORS\n" );
255         GDI_ReleaseObj( hbitmap );
256         return 0;
257     }
258
259     if (!bitmap->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) goto done;
260
261     if (bitmap->funcs && bitmap->funcs->pSetDIBits)
262         result = bitmap->funcs->pSetDIBits( dc->physDev, hbitmap, startscan, lines,
263                                             bits, info, coloruse );
264     else
265         result = lines;
266
267  done:
268     GDI_ReleaseObj( hdc );
269     GDI_ReleaseObj( hbitmap );
270     return result;
271 }
272
273
274 /***********************************************************************
275  *           SetDIBitsToDevice   (GDI32.@)
276  */
277 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
278                            DWORD cy, INT xSrc, INT ySrc, UINT startscan,
279                            UINT lines, LPCVOID bits, const BITMAPINFO *info,
280                            UINT coloruse )
281 {
282     INT ret;
283     DC *dc;
284
285     if (!(dc = DC_GetDCUpdate( hdc ))) return 0;
286
287     if(dc->funcs->pSetDIBitsToDevice)
288         ret = dc->funcs->pSetDIBitsToDevice( dc->physDev, xDest, yDest, cx, cy, xSrc,
289                                              ySrc, startscan, lines, bits,
290                                              info, coloruse );
291     else {
292         FIXME("unimplemented on hdc %p\n", hdc);
293         ret = 0;
294     }
295
296     GDI_ReleaseObj( hdc );
297     return ret;
298 }
299
300 /***********************************************************************
301  *           SetDIBColorTable    (GDI32.@)
302  */
303 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
304 {
305     DC * dc;
306     UINT result = 0;
307
308     if (!(dc = DC_GetDCUpdate( hdc ))) return 0;
309
310     if (dc->funcs->pSetDIBColorTable)
311         result = dc->funcs->pSetDIBColorTable(dc->physDev, startpos, entries, colors);
312
313     GDI_ReleaseObj( hdc );
314     return result;
315 }
316
317
318 /***********************************************************************
319  *           GetDIBColorTable    (GDI32.@)
320  */
321 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
322 {
323     DC * dc;
324     UINT result = 0;
325
326     if (!(dc = DC_GetDCUpdate( hdc ))) return 0;
327
328     if (dc->funcs->pGetDIBColorTable)
329         result = dc->funcs->pGetDIBColorTable(dc->physDev, startpos, entries, colors);
330
331     GDI_ReleaseObj( hdc );
332     return result;
333 }
334
335 /* FIXME the following two structs should be combined with __sysPalTemplate in
336    objects/color.c - this should happen after de-X11-ing both of these
337    files.
338    NB. RGBQUAD and PALETTEENTRY have different orderings of red, green
339    and blue - sigh */
340
341 static RGBQUAD EGAColors[16] = {
342 /* rgbBlue, rgbGreen, rgbRed, rgbReserverd */
343     { 0x00, 0x00, 0x00, 0x00 },
344     { 0x00, 0x00, 0x80, 0x00 },
345     { 0x00, 0x80, 0x00, 0x00 },
346     { 0x00, 0x80, 0x80, 0x00 },
347     { 0x80, 0x00, 0x00, 0x00 },
348     { 0x80, 0x00, 0x80, 0x00 },
349     { 0x80, 0x80, 0x00, 0x00 },
350     { 0x80, 0x80, 0x80, 0x00 },
351     { 0xc0, 0xc0, 0xc0, 0x00 },
352     { 0x00, 0x00, 0xff, 0x00 },
353     { 0x00, 0xff, 0x00, 0x00 },
354     { 0x00, 0xff, 0xff, 0x00 },
355     { 0xff, 0x00, 0x00, 0x00 },
356     { 0xff, 0x00, 0xff, 0x00 },
357     { 0xff, 0xff, 0x00, 0x00 },
358     { 0xff, 0xff, 0xff, 0x00 }
359 };
360
361
362 static RGBQUAD DefLogPalette[20] = { /* Copy of Default Logical Palette */
363 /* rgbBlue, rgbGreen, rgbRed, rgbReserverd */
364     { 0x00, 0x00, 0x00, 0x00 },
365     { 0x00, 0x00, 0x80, 0x00 },
366     { 0x00, 0x80, 0x00, 0x00 },
367     { 0x00, 0x80, 0x80, 0x00 },
368     { 0x80, 0x00, 0x00, 0x00 },
369     { 0x80, 0x00, 0x80, 0x00 },
370     { 0x80, 0x80, 0x00, 0x00 },
371     { 0xc0, 0xc0, 0xc0, 0x00 },
372     { 0xc0, 0xdc, 0xc0, 0x00 },
373     { 0xf0, 0xca, 0xa6, 0x00 },
374     { 0xf0, 0xfb, 0xff, 0x00 },
375     { 0xa4, 0xa0, 0xa0, 0x00 },
376     { 0x80, 0x80, 0x80, 0x00 },
377     { 0x00, 0x00, 0xf0, 0x00 },
378     { 0x00, 0xff, 0x00, 0x00 },
379     { 0x00, 0xff, 0xff, 0x00 },
380     { 0xff, 0x00, 0x00, 0x00 },
381     { 0xff, 0x00, 0xff, 0x00 },
382     { 0xff, 0xff, 0x00, 0x00 },
383     { 0xff, 0xff, 0xff, 0x00 }
384 };
385
386
387 /******************************************************************************
388  * GetDIBits [GDI32.@]
389  *
390  * Retrieves bits of bitmap and copies to buffer.
391  *
392  * RETURNS
393  *    Success: Number of scan lines copied from bitmap
394  *    Failure: 0
395  *
396  * http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/func/src/f30_14.htm
397  */
398 INT WINAPI GetDIBits(
399     HDC hdc,         /* [in]  Handle to device context */
400     HBITMAP hbitmap, /* [in]  Handle to bitmap */
401     UINT startscan,  /* [in]  First scan line to set in dest bitmap */
402     UINT lines,      /* [in]  Number of scan lines to copy */
403     LPVOID bits,       /* [out] Address of array for bitmap bits */
404     BITMAPINFO * info, /* [out] Address of structure with bitmap data */
405     UINT coloruse)   /* [in]  RGB or palette index */
406 {
407     DC * dc;
408     BITMAPOBJ * bmp;
409     int i;
410
411     if (!info) return 0;
412     if (!(dc = DC_GetDCUpdate( hdc ))) return 0;
413     if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
414     {
415         GDI_ReleaseObj( hdc );
416         return 0;
417     }
418
419     /* Transfer color info */
420
421     if (info->bmiHeader.biBitCount <= 8 && info->bmiHeader.biBitCount > 0 ) {
422
423         info->bmiHeader.biClrUsed = 0;
424
425         /* If the bitmap object already has a dib section at the
426            same color depth then get the color map from it */
427         if (bmp->dib && bmp->dib->dsBm.bmBitsPixel == info->bmiHeader.biBitCount) {
428             GetDIBColorTable(hdc, 0, 1 << info->bmiHeader.biBitCount, info->bmiColors);
429         }
430         else {
431             if(info->bmiHeader.biBitCount >= bmp->bitmap.bmBitsPixel) {
432                 /* Generate the color map from the selected palette */
433                 PALETTEENTRY * palEntry;
434                 PALETTEOBJ * palette;
435                 if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->hPalette, PALETTE_MAGIC ))) {
436                     GDI_ReleaseObj( hdc );
437                     GDI_ReleaseObj( hbitmap );
438                     return 0;
439                 }
440                 palEntry = palette->logpalette.palPalEntry;
441                 for (i = 0; i < (1 << bmp->bitmap.bmBitsPixel); i++, palEntry++) {
442                     if (coloruse == DIB_RGB_COLORS) {
443                         info->bmiColors[i].rgbRed      = palEntry->peRed;
444                         info->bmiColors[i].rgbGreen    = palEntry->peGreen;
445                         info->bmiColors[i].rgbBlue     = palEntry->peBlue;
446                         info->bmiColors[i].rgbReserved = 0;
447                     }
448                     else ((WORD *)info->bmiColors)[i] = (WORD)i;
449                 }
450                 GDI_ReleaseObj( dc->hPalette );
451             } else {
452                 switch (info->bmiHeader.biBitCount) {
453                 case 1:
454                     info->bmiColors[0].rgbRed = info->bmiColors[0].rgbGreen =
455                         info->bmiColors[0].rgbBlue = 0;
456                     info->bmiColors[0].rgbReserved = 0;
457                     info->bmiColors[1].rgbRed = info->bmiColors[1].rgbGreen =
458                         info->bmiColors[1].rgbBlue = 0xff;
459                     info->bmiColors[1].rgbReserved = 0;
460                     break;
461
462                 case 4:
463                     memcpy(info->bmiColors, EGAColors, sizeof(EGAColors));
464                     break;
465
466                 case 8:
467                     {
468                         INT r, g, b;
469                         RGBQUAD *color;
470
471                         memcpy(info->bmiColors, DefLogPalette,
472                                10 * sizeof(RGBQUAD));
473                         memcpy(info->bmiColors + 246, DefLogPalette + 10,
474                                10 * sizeof(RGBQUAD));
475                         color = info->bmiColors + 10;
476                         for(r = 0; r <= 5; r++) /* FIXME */
477                             for(g = 0; g <= 5; g++)
478                                 for(b = 0; b <= 5; b++) {
479                                     color->rgbRed =   (r * 0xff) / 5;
480                                     color->rgbGreen = (g * 0xff) / 5;
481                                     color->rgbBlue =  (b * 0xff) / 5;
482                                     color->rgbReserved = 0;
483                                     color++;
484                                 }
485                     }
486                 }
487             }
488         }
489     }
490
491     if (bits && lines)
492     {
493         /* If the bitmap object already have a dib section that contains image data, get the bits from it */
494         if(bmp->dib && bmp->dib->dsBm.bmBitsPixel >= 15 && info->bmiHeader.biBitCount >= 15)
495         {
496             /*FIXME: Only RGB dibs supported for now */
497             unsigned int srcwidth = bmp->dib->dsBm.bmWidth, srcwidthb = bmp->dib->dsBm.bmWidthBytes;
498             int dstwidthb = DIB_GetDIBWidthBytes( info->bmiHeader.biWidth, info->bmiHeader.biBitCount );
499             LPBYTE dbits = bits, sbits = (LPBYTE) bmp->dib->dsBm.bmBits + (startscan * srcwidthb);
500             unsigned int x, y;
501
502             if ((info->bmiHeader.biHeight < 0) ^ (bmp->dib->dsBmih.biHeight < 0))
503             {
504                 dbits = (LPBYTE)bits + (dstwidthb * (lines-1));
505                 dstwidthb = -dstwidthb;
506             }
507
508             switch( info->bmiHeader.biBitCount ) {
509
510             case 15:
511             case 16: /* 16 bpp dstDIB */
512                 {
513                     LPWORD dstbits = (LPWORD)dbits;
514                     WORD rmask = 0x7c00, gmask= 0x03e0, bmask = 0x001f;
515
516                     /* FIXME: BI_BITFIELDS not supported yet */
517
518                     switch(bmp->dib->dsBm.bmBitsPixel) {
519
520                     case 16: /* 16 bpp srcDIB -> 16 bpp dstDIB */
521                         {
522                             /* FIXME: BI_BITFIELDS not supported yet */
523                             for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
524                                 memcpy(dbits, sbits, srcwidthb);
525                         }
526                         break;
527
528                     case 24: /* 24 bpp srcDIB -> 16 bpp dstDIB */
529                         {
530                             LPBYTE srcbits = sbits;
531
532                             for( y = 0; y < lines; y++) {
533                                 for( x = 0; x < srcwidth; x++, srcbits += 3)
534                                     *dstbits++ = ((srcbits[0] >> 3) & bmask) |
535                                                  (((WORD)srcbits[1] << 2) & gmask) |
536                                                  (((WORD)srcbits[2] << 7) & rmask);
537
538                                 dstbits = (LPWORD)(dbits+=dstwidthb);
539                                 srcbits = (sbits += srcwidthb);
540                             }
541                         }
542                         break;
543
544                     case 32: /* 32 bpp srcDIB -> 16 bpp dstDIB */
545                         {
546                             LPDWORD srcbits = (LPDWORD)sbits;
547                             DWORD val;
548
549                             for( y = 0; y < lines; y++) {
550                                 for( x = 0; x < srcwidth; x++ ) {
551                                     val = *srcbits++;
552                                     *dstbits++ = (WORD)(((val >> 3) & bmask) | ((val >> 6) & gmask) |
553                                                        ((val >> 9) & rmask));
554                                 }
555                                 dstbits = (LPWORD)(dbits+=dstwidthb);
556                                 srcbits = (LPDWORD)(sbits+=srcwidthb);
557                             }
558                         }
559                         break;
560
561                     default: /* ? bit bmp -> 16 bit DIB */
562                         FIXME("15/16 bit DIB %d bit bitmap\n",
563                         bmp->bitmap.bmBitsPixel);
564                         break;
565                     }
566                 }
567                 break;
568
569             case 24: /* 24 bpp dstDIB */
570                 {
571                     LPBYTE dstbits = dbits;
572
573                     switch(bmp->dib->dsBm.bmBitsPixel) {
574
575                     case 16: /* 16 bpp srcDIB -> 24 bpp dstDIB */
576                         {
577                             LPWORD srcbits = (LPWORD)sbits;
578                             WORD val;
579
580                             /* FIXME: BI_BITFIELDS not supported yet */
581                             for( y = 0; y < lines; y++) {
582                                 for( x = 0; x < srcwidth; x++ ) {
583                                     val = *srcbits++;
584                                     *dstbits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07));
585                                     *dstbits++ = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07));
586                                     *dstbits++ = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07));
587                                 }
588                                 dstbits = (LPBYTE)(dbits+=dstwidthb);
589                                 srcbits = (LPWORD)(sbits+=srcwidthb);
590                             }
591                         }
592                         break;
593
594                     case 24: /* 24 bpp srcDIB -> 24 bpp dstDIB */
595                         {
596                             for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
597                                 memcpy(dbits, sbits, srcwidthb);
598                         }
599                         break;
600
601                     case 32: /* 32 bpp srcDIB -> 24 bpp dstDIB */
602                         {
603                             LPBYTE srcbits = (LPBYTE)sbits;
604
605                             for( y = 0; y < lines; y++) {
606                                 for( x = 0; x < srcwidth; x++, srcbits++ ) {
607                                     *dstbits++ = *srcbits++;
608                                     *dstbits++ = *srcbits++;
609                                     *dstbits++ = *srcbits++;
610                                 }
611                                 dstbits=(LPBYTE)(dbits+=dstwidthb);
612                                 srcbits = (LPBYTE)(sbits+=srcwidthb);
613                             }
614                         }
615                         break;
616
617                     default: /* ? bit bmp -> 24 bit DIB */
618                         FIXME("24 bit DIB %d bit bitmap\n",
619                               bmp->bitmap.bmBitsPixel);
620                         break;
621                     }
622                 }
623                 break;
624
625             case 32: /* 32 bpp dstDIB */
626                 {
627                     LPDWORD dstbits = (LPDWORD)dbits;
628
629                     /* FIXME: BI_BITFIELDS not supported yet */
630
631                     switch(bmp->dib->dsBm.bmBitsPixel) {
632                         case 16: /* 16 bpp srcDIB -> 32 bpp dstDIB */
633                         {
634                             LPWORD srcbits = (LPWORD)sbits;
635                             DWORD val;
636
637                             /* FIXME: BI_BITFIELDS not supported yet */
638                             for( y = 0; y < lines; y++) {
639                                 for( x = 0; x < srcwidth; x++ ) {
640                                     val = (DWORD)*srcbits++;
641                                     *dstbits++ = ((val << 3) & 0xf8) | ((val >> 2) & 0x07) |
642                                                  ((val << 6) & 0xf800) | ((val << 1) & 0x0700) |
643                                                  ((val << 9) & 0xf80000) | ((val << 4) & 0x070000);
644                                 }
645                                 dstbits=(LPDWORD)(dbits+=dstwidthb);
646                                 srcbits=(LPWORD)(sbits+=srcwidthb);
647                             }
648                         }
649                         break;
650
651                     case 24: /* 24 bpp srcDIB -> 32 bpp dstDIB */
652                         {
653                             LPBYTE srcbits = sbits;
654
655                             for( y = 0; y < lines; y++) {
656                                 for( x = 0; x < srcwidth; x++, srcbits+=3 )
657                                     *dstbits++ = ((DWORD)*srcbits) & 0x00ffffff;
658                                 dstbits=(LPDWORD)(dbits+=dstwidthb);
659                                 srcbits=(sbits+=srcwidthb);
660                             }
661                         }
662                         break;
663
664                     case 32: /* 32 bpp srcDIB -> 16 bpp dstDIB */
665                         {
666                             /* FIXME: BI_BITFIELDS not supported yet */
667                             for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
668                                 memcpy(dbits, sbits, srcwidthb);
669                         }
670                         break;
671
672                     default: /* ? bit bmp -> 32 bit DIB */
673                         FIXME("32 bit DIB %d bit bitmap\n",
674                         bmp->bitmap.bmBitsPixel);
675                         break;
676                     }
677                 }
678                 break;
679
680             default: /* ? bit DIB */
681                 FIXME("Unsupported DIB depth %d\n", info->bmiHeader.biBitCount);
682                 break;
683             }
684         }
685         /* Otherwise, get bits from the XImage */
686         else
687         {
688             if (!bmp->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) lines = 0;
689             else
690             {
691                 if (bmp->funcs && bmp->funcs->pGetDIBits)
692                     lines = bmp->funcs->pGetDIBits( dc->physDev, hbitmap, startscan,
693                                                     lines, bits, info, coloruse );
694                 else
695                     lines = 0;  /* FIXME: should copy from bmp->bitmap.bmBits */
696             }
697         }
698     }
699     else if( info->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) )
700     {
701         /* fill in struct members */
702
703         if( info->bmiHeader.biBitCount == 0)
704         {
705             info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
706             info->bmiHeader.biHeight = bmp->bitmap.bmHeight;
707             info->bmiHeader.biPlanes = 1;
708             info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
709             info->bmiHeader.biSizeImage =
710                              DIB_GetDIBImageBytes( bmp->bitmap.bmWidth,
711                                                    bmp->bitmap.bmHeight,
712                                                    bmp->bitmap.bmBitsPixel );
713             info->bmiHeader.biCompression = 0;
714         }
715         else
716         {
717             info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(
718                                                info->bmiHeader.biWidth,
719                                                info->bmiHeader.biHeight,
720                                                info->bmiHeader.biBitCount );
721         }
722     }
723
724     TRACE("biSizeImage = %ld, biWidth = %ld, biHeight = %ld\n",
725           info->bmiHeader.biSizeImage, info->bmiHeader.biWidth,
726           info->bmiHeader.biHeight);
727
728     GDI_ReleaseObj( hdc );
729     GDI_ReleaseObj( hbitmap );
730
731     return lines;
732 }
733
734
735 /***********************************************************************
736  *           CreateDIBitmap    (GDI32.@)
737  */
738 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
739                             DWORD init, LPCVOID bits, const BITMAPINFO *data,
740                             UINT coloruse )
741 {
742     HBITMAP handle;
743     BOOL fColor;
744     DWORD width;
745     int height;
746     WORD bpp;
747     WORD compr;
748     DC *dc;
749
750     if (DIB_GetBitmapInfo( header, &width, &height, &bpp, &compr ) == -1) return 0;
751     if (height < 0) height = -height;
752
753     /* Check if we should create a monochrome or color bitmap. */
754     /* We create a monochrome bitmap only if it has exactly 2  */
755     /* colors, which are black followed by white, nothing else.  */
756     /* In all other cases, we create a color bitmap.           */
757
758     if (bpp != 1) fColor = TRUE;
759     else if ((coloruse != DIB_RGB_COLORS) || !data) fColor = FALSE;
760     else
761     {
762         if (data->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
763         {
764             RGBQUAD *rgb = data->bmiColors;
765             DWORD col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
766
767             /* Check if the first color of the colormap is black */
768             if ((col == RGB(0,0,0)))
769             {
770                 rgb++;
771                 col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
772                 /* If the second color is white, create a monochrome bitmap */
773                 fColor =  (col != RGB(0xff,0xff,0xff));
774             }
775             /* Note : If the first color of the colormap is white
776                followed by black, we have to create a color bitmap.
777                If we don't the white will be displayed in black later on!*/
778             else fColor = TRUE;
779         }
780         else if (data->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
781         {
782             RGBTRIPLE *rgb = ((BITMAPCOREINFO *)data)->bmciColors;
783             DWORD col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue );
784             if ((col == RGB(0,0,0)))
785             {
786                 rgb++;
787                 col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue );
788                 fColor = (col != RGB(0xff,0xff,0xff));
789             }
790             else fColor = TRUE;
791         }
792         else if (data->bmiHeader.biSize == sizeof(BITMAPV4HEADER))
793         { /* FIXME: correct ? */
794             RGBQUAD *rgb = data->bmiColors;
795             DWORD col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
796
797             /* Check if the first color of the colormap is black */
798             if ((col == RGB(0,0,0)))
799             {
800                 rgb++;
801                 col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
802                 /* If the second color is white, create a monochrome bitmap */
803                 fColor =  (col != RGB(0xff,0xff,0xff));
804             }
805             /* Note : If the first color of the colormap is white
806                followed by black, we have to create a color bitmap.
807                If we don't the white will be displayed in black later on!*/
808             else fColor = TRUE;
809         }
810         else
811         {
812             ERR("(%ld): wrong/unknown size for data\n",
813                      data->bmiHeader.biSize );
814             return 0;
815         }
816     }
817
818     /* Now create the bitmap */
819
820     if (!(dc = DC_GetDCPtr( hdc ))) return 0;
821
822     if (fColor)
823         handle = CreateBitmap( width, height, GetDeviceCaps( hdc, PLANES ),
824                                GetDeviceCaps( hdc, BITSPIXEL ), NULL );
825     else handle = CreateBitmap( width, height, 1, 1, NULL );
826
827     if (handle)
828     {
829         if (init == CBM_INIT) SetDIBits( hdc, handle, 0, height, bits, data, coloruse );
830         else if (!BITMAP_SetOwnerDC( handle, dc ))
831         {
832             DeleteObject( handle );
833             handle = 0;
834         }
835     }
836
837     GDI_ReleaseObj( hdc );
838     return handle;
839 }
840
841 /***********************************************************************
842  *           CreateDIBSection    (GDI.489)
843  */
844 HBITMAP16 WINAPI CreateDIBSection16 (HDC16 hdc, BITMAPINFO *bmi, UINT16 usage,
845                                      SEGPTR *bits16, HANDLE section, DWORD offset)
846 {
847     LPVOID bits32;
848     HBITMAP hbitmap;
849
850     hbitmap = CreateDIBSection( HDC_32(hdc), bmi, usage, &bits32, section, offset );
851     if (hbitmap)
852     {
853         BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr(hbitmap, BITMAP_MAGIC);
854         if (bmp && bmp->dib && bits32)
855         {
856             BITMAPINFOHEADER *bi = &bmi->bmiHeader;
857             INT height = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
858             INT width_bytes = DIB_GetDIBWidthBytes(bi->biWidth, bi->biBitCount);
859             INT size  = (bi->biSizeImage && bi->biCompression != BI_RGB) ?
860                          bi->biSizeImage : width_bytes * height;
861
862             /* calculate number of sel's needed for size with 64K steps */
863             WORD count = (size + 0xffff) / 0x10000;
864             WORD sel = AllocSelectorArray16(count);
865             int i;
866
867             for (i = 0; i < count; i++)
868             {
869                 SetSelectorBase(sel + (i << __AHSHIFT), (DWORD)bits32 + i * 0x10000);
870                 SetSelectorLimit16(sel + (i << __AHSHIFT), size - 1); /* yep, limit is correct */
871                 size -= 0x10000;
872             }
873             bmp->segptr_bits = MAKESEGPTR( sel, 0 );
874             if (bits16) *bits16 = bmp->segptr_bits;
875         }
876         if (bmp) GDI_ReleaseObj( hbitmap );
877     }
878     return HBITMAP_16(hbitmap);
879 }
880
881 /***********************************************************************
882  *           DIB_CreateDIBSection
883  */
884 HBITMAP DIB_CreateDIBSection(HDC hdc, BITMAPINFO *bmi, UINT usage,
885                              LPVOID *bits, HANDLE section,
886                              DWORD offset, DWORD ovr_pitch)
887 {
888     HBITMAP hbitmap = 0;
889     DC *dc;
890     BOOL bDesktopDC = FALSE;
891
892     /* If the reference hdc is null, take the desktop dc */
893     if (hdc == 0)
894     {
895         hdc = CreateCompatibleDC(0);
896         bDesktopDC = TRUE;
897     }
898
899     /* Windows ignores the supplied values of biClrUsed and biClrImportant thus: */
900     if (bmi->bmiHeader.biBitCount >= 1 && bmi->bmiHeader.biBitCount <= 8)
901         bmi->bmiHeader.biClrUsed = bmi->bmiHeader.biClrImportant = 1L << bmi->bmiHeader.biBitCount;
902     else
903         bmi->bmiHeader.biClrUsed = bmi->bmiHeader.biClrImportant = 0;
904
905     if ((dc = DC_GetDCPtr( hdc )))
906     {
907         if(dc->funcs->pCreateDIBSection)
908             hbitmap = dc->funcs->pCreateDIBSection(dc->physDev, bmi, usage, bits, section, offset, ovr_pitch);
909         GDI_ReleaseObj(hdc);
910     }
911
912     if (bDesktopDC)
913       DeleteDC(hdc);
914
915     return hbitmap;
916 }
917
918 /***********************************************************************
919  *           CreateDIBSection    (GDI32.@)
920  */
921 HBITMAP WINAPI CreateDIBSection(HDC hdc, BITMAPINFO *bmi, UINT usage,
922                                 LPVOID *bits, HANDLE section,
923                                 DWORD offset)
924 {
925     return DIB_CreateDIBSection(hdc, bmi, usage, bits, section, offset, 0);
926 }