- made string operations consistent wrt whitespace handling (which
[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 /*
22   Important information:
23   
24   * Current Windows versions support two different DIB structures:
25
26     - BITMAPCOREINFO / BITMAPCOREHEADER (legacy structures; used in OS/2)
27     - BITMAPINFO / BITMAPINFOHEADER
28   
29     Most Windows API functions taking a BITMAPINFO* / BITMAPINFOHEADER* also
30     accept the old "core" structures, and so must WINE.
31     You can distinguish them by looking at the first member (bcSize/biSize),
32     or use the internal function DIB_GetBitmapInfo.
33
34     
35   * The palettes are stored in different formats:
36
37     - BITMAPCOREINFO: Array of RGBTRIPLE
38     - BITMAPINFO:     Array of RGBQUAD
39
40     
41   * There are even more DIB headers, but they all extend BITMAPINFOHEADER:
42     
43     - BITMAPV4HEADER: Introduced in Windows 95 / NT 4.0
44     - BITMAPV5HEADER: Introduced in Windows 98 / 2000
45
46
47   * You should never access the color table using the bmiColors member,
48     because the passed structure may have one of the extended headers
49     mentioned above. Use this to calculate the location:
50     
51     BITMAPINFO* info;
52     void* colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
53
54     
55   * More information:
56     Search for "Bitmap Structures" in MSDN
57 */
58
59 #include <stdarg.h>
60 #include <stdlib.h>
61 #include <string.h>
62
63 #include "windef.h"
64 #include "winbase.h"
65 #include "gdi.h"
66 #include "wownt32.h"
67 #include "gdi_private.h"
68 #include "wine/debug.h"
69
70 WINE_DEFAULT_DEBUG_CHANNEL(bitmap);
71
72
73 /*
74   Some of the following helper functions are duplicated in
75   dlls/x11drv/dib.c
76 */
77
78 /***********************************************************************
79  *           DIB_GetDIBWidthBytes
80  *
81  * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
82  * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/bitmaps_87eb.asp
83  */
84 int DIB_GetDIBWidthBytes( int width, int depth )
85 {
86     int words;
87
88     switch(depth)
89     {
90         case 1:  words = (width + 31) / 32; break;
91         case 4:  words = (width + 7) / 8; break;
92         case 8:  words = (width + 3) / 4; break;
93         case 15:
94         case 16: words = (width + 1) / 2; break;
95         case 24: words = (width * 3 + 3)/4; break;
96
97         default:
98             WARN("(%d): Unsupported depth\n", depth );
99         /* fall through */
100         case 32:
101                 words = width;
102     }
103     return 4 * words;
104 }
105
106 /***********************************************************************
107  *           DIB_GetDIBImageBytes
108  *
109  * Return the number of bytes used to hold the image in a DIB bitmap.
110  */
111 int DIB_GetDIBImageBytes( int width, int height, int depth )
112 {
113     return DIB_GetDIBWidthBytes( width, depth ) * abs( height );
114 }
115
116
117 /***********************************************************************
118  *           DIB_BitmapInfoSize
119  *
120  * Return the size of the bitmap info structure including color table.
121  */
122 int DIB_BitmapInfoSize( const BITMAPINFO * info, WORD coloruse )
123 {
124     int colors;
125
126     if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
127     {
128         BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)info;
129         colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
130         return sizeof(BITMAPCOREHEADER) + colors *
131              ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
132     }
133     else  /* assume BITMAPINFOHEADER */
134     {
135         colors = info->bmiHeader.biClrUsed;
136         if (colors > 256) colors = 256;
137         if (!colors && (info->bmiHeader.biBitCount <= 8))
138             colors = 1 << info->bmiHeader.biBitCount;
139         return sizeof(BITMAPINFOHEADER) + colors *
140                ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
141     }
142 }
143
144
145 /***********************************************************************
146  *           DIB_GetBitmapInfo
147  *
148  * Get the info from a bitmap header.
149  * Return 1 for INFOHEADER, 0 for COREHEADER,
150  * 4 for V4HEADER, 5 for V5HEADER, -1 for error.
151  */
152 static int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
153                               LONG *height, WORD *bpp, DWORD *compr )
154 {
155     if (header->biSize == sizeof(BITMAPINFOHEADER))
156     {
157         *width  = header->biWidth;
158         *height = header->biHeight;
159         *bpp    = header->biBitCount;
160         *compr  = header->biCompression;
161         return 1;
162     }
163     if (header->biSize == sizeof(BITMAPCOREHEADER))
164     {
165         BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)header;
166         *width  = core->bcWidth;
167         *height = core->bcHeight;
168         *bpp    = core->bcBitCount;
169         *compr  = 0;
170         return 0;
171     }
172     if (header->biSize == sizeof(BITMAPV4HEADER))
173     {
174         BITMAPV4HEADER *v4hdr = (BITMAPV4HEADER *)header;
175         *width  = v4hdr->bV4Width;
176         *height = v4hdr->bV4Height;
177         *bpp    = v4hdr->bV4BitCount;
178         *compr  = v4hdr->bV4V4Compression;
179         return 4;
180     }
181     if (header->biSize == sizeof(BITMAPV5HEADER))
182     {
183         BITMAPV5HEADER *v5hdr = (BITMAPV5HEADER *)header;
184         *width  = v5hdr->bV5Width;
185         *height = v5hdr->bV5Height;
186         *bpp    = v5hdr->bV5BitCount;
187         *compr  = v5hdr->bV5Compression;
188         return 5;
189     }
190     ERR("(%ld): unknown/wrong size for header\n", header->biSize );
191     return -1;
192 }
193
194
195 /***********************************************************************
196  *           StretchDIBits   (GDI32.@)
197  */
198 INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst,
199                        INT heightDst, INT xSrc, INT ySrc, INT widthSrc,
200                        INT heightSrc, const void *bits,
201                        const BITMAPINFO *info, UINT wUsage, DWORD dwRop )
202 {
203     DC *dc;
204
205     if (!bits || !info)
206         return 0;
207
208     dc = DC_GetDCUpdate( hdc );
209     if(!dc) return FALSE;
210
211     if(dc->funcs->pStretchDIBits)
212     {
213         heightSrc = dc->funcs->pStretchDIBits(dc->physDev, xDst, yDst, widthDst,
214                                               heightDst, xSrc, ySrc, widthSrc,
215                                               heightSrc, bits, info, wUsage, dwRop);
216         GDI_ReleaseObj( hdc );
217     }
218     else /* use StretchBlt */
219     {
220         HBITMAP hBitmap, hOldBitmap;
221         HPALETTE hpal = NULL;
222         HDC hdcMem;
223         LONG height;
224         LONG width;
225         WORD bpp;
226         DWORD compr;
227
228         if (DIB_GetBitmapInfo( (BITMAPINFOHEADER*) info, &width, &height, &bpp, &compr ) == -1)
229         {
230             ERR("Invalid bitmap\n");
231             return 0;
232         }
233
234         if (width < 0)
235         {
236             ERR("Bitmap has a negative width\n");
237             return 0;
238         }
239
240         GDI_ReleaseObj( hdc );
241         hdcMem = CreateCompatibleDC( hdc );
242         hBitmap = CreateCompatibleBitmap(hdc, width, height);
243         hOldBitmap = SelectObject( hdcMem, hBitmap );
244         if(wUsage == DIB_PAL_COLORS)
245         {
246             hpal = GetCurrentObject(hdc, OBJ_PAL);
247             hpal = SelectPalette(hdcMem, hpal, FALSE);
248         }
249
250         if (info->bmiHeader.biCompression == BI_RLE4 ||
251             info->bmiHeader.biCompression == BI_RLE8) {
252
253            /* when RLE compression is used, there may be some gaps (ie the DIB doesn't
254             * contain all the rectangle described in bmiHeader, but only part of it.
255             * This mean that those undescribed pixels must be left untouched.
256             * So, we first copy on a memory bitmap the current content of the
257             * destination rectangle, blit the DIB bits on top of it - hence leaving
258             * the gaps untouched -, and blitting the rectangle back.
259             * This insure that gaps are untouched on the destination rectangle
260             * Not doing so leads to trashed images (the gaps contain what was on the
261             * memory bitmap => generally black or garbage)
262             * Unfortunately, RLE DIBs without gaps will be slowed down. But this is
263             * another speed vs correctness issue. Anyway, if speed is needed, then the
264             * pStretchDIBits function shall be implemented.
265             * ericP (2000/09/09)
266             */
267
268             /* copy existing bitmap from destination dc */
269             StretchBlt( hdcMem, xSrc, abs(height) - heightSrc - ySrc,
270                         widthSrc, heightSrc, hdc, xDst, yDst, widthDst, heightDst,
271                         dwRop );
272         }
273
274         SetDIBits(hdcMem, hBitmap, 0, height, bits, info, wUsage);
275
276         /* Origin for DIBitmap may be bottom left (positive biHeight) or top
277            left (negative biHeight) */
278         StretchBlt( hdc, xDst, yDst, widthDst, heightDst,
279                     hdcMem, xSrc, abs(height) - heightSrc - ySrc,
280                     widthSrc, heightSrc, dwRop );
281         if(hpal)
282             SelectPalette(hdcMem, hpal, FALSE);
283         SelectObject( hdcMem, hOldBitmap );
284         DeleteDC( hdcMem );
285         DeleteObject( hBitmap );
286     }
287     return heightSrc;
288 }
289
290
291 /******************************************************************************
292  * SetDIBits [GDI32.@]
293  *
294  * Sets pixels in a bitmap using colors from DIB.
295  *
296  * PARAMS
297  *    hdc       [I] Handle to device context
298  *    hbitmap   [I] Handle to bitmap
299  *    startscan [I] Starting scan line
300  *    lines     [I] Number of scan lines
301  *    bits      [I] Array of bitmap bits
302  *    info      [I] Address of structure with data
303  *    coloruse  [I] Type of color indexes to use
304  *
305  * RETURNS
306  *    Success: Number of scan lines copied
307  *    Failure: 0
308  */
309 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
310                       UINT lines, LPCVOID bits, const BITMAPINFO *info,
311                       UINT coloruse )
312 {
313     DC *dc;
314     BITMAPOBJ *bitmap;
315     INT result = 0;
316
317     if (!(dc = DC_GetDCUpdate( hdc )))
318     {
319         if (coloruse == DIB_RGB_COLORS) FIXME( "shouldn't require a DC for DIB_RGB_COLORS\n" );
320         return 0;
321     }
322
323     if (!(bitmap = GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
324     {
325         GDI_ReleaseObj( hdc );
326         return 0;
327     }
328
329     if (!bitmap->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) goto done;
330
331     if (bitmap->funcs && bitmap->funcs->pSetDIBits)
332         result = bitmap->funcs->pSetDIBits( dc->physDev, hbitmap, startscan, lines,
333                                             bits, info, coloruse );
334     else
335         result = lines;
336
337  done:
338     GDI_ReleaseObj( hbitmap );
339     GDI_ReleaseObj( hdc );
340     return result;
341 }
342
343
344 /***********************************************************************
345  *           SetDIBitsToDevice   (GDI32.@)
346  */
347 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
348                            DWORD cy, INT xSrc, INT ySrc, UINT startscan,
349                            UINT lines, LPCVOID bits, const BITMAPINFO *info,
350                            UINT coloruse )
351 {
352     INT ret;
353     DC *dc;
354
355     if (!(dc = DC_GetDCUpdate( hdc ))) return 0;
356
357     if(dc->funcs->pSetDIBitsToDevice)
358         ret = dc->funcs->pSetDIBitsToDevice( dc->physDev, xDest, yDest, cx, cy, xSrc,
359                                              ySrc, startscan, lines, bits,
360                                              info, coloruse );
361     else {
362         FIXME("unimplemented on hdc %p\n", hdc);
363         ret = 0;
364     }
365
366     GDI_ReleaseObj( hdc );
367     return ret;
368 }
369
370 /***********************************************************************
371  *           SetDIBColorTable    (GDI32.@)
372  */
373 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUAD *colors )
374 {
375     DC * dc;
376     UINT result = 0;
377
378     if (!(dc = DC_GetDCUpdate( hdc ))) return 0;
379
380     if (dc->funcs->pSetDIBColorTable)
381         result = dc->funcs->pSetDIBColorTable(dc->physDev, startpos, entries, colors);
382
383     GDI_ReleaseObj( hdc );
384     return result;
385 }
386
387
388 /***********************************************************************
389  *           GetDIBColorTable    (GDI32.@)
390  */
391 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
392 {
393     DC * dc;
394     UINT result = 0;
395
396     if (!(dc = DC_GetDCUpdate( hdc ))) return 0;
397
398     if (dc->funcs->pGetDIBColorTable)
399         result = dc->funcs->pGetDIBColorTable(dc->physDev, startpos, entries, colors);
400
401     GDI_ReleaseObj( hdc );
402     return result;
403 }
404
405 /* FIXME the following two structs should be combined with __sysPalTemplate in
406    objects/color.c - this should happen after de-X11-ing both of these
407    files.
408    NB. RGBQUAD and PALETTEENTRY have different orderings of red, green
409    and blue - sigh */
410
411 static RGBQUAD EGAColorsQuads[16] = {
412 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
413     { 0x00, 0x00, 0x00, 0x00 },
414     { 0x00, 0x00, 0x80, 0x00 },
415     { 0x00, 0x80, 0x00, 0x00 },
416     { 0x00, 0x80, 0x80, 0x00 },
417     { 0x80, 0x00, 0x00, 0x00 },
418     { 0x80, 0x00, 0x80, 0x00 },
419     { 0x80, 0x80, 0x00, 0x00 },
420     { 0x80, 0x80, 0x80, 0x00 },
421     { 0xc0, 0xc0, 0xc0, 0x00 },
422     { 0x00, 0x00, 0xff, 0x00 },
423     { 0x00, 0xff, 0x00, 0x00 },
424     { 0x00, 0xff, 0xff, 0x00 },
425     { 0xff, 0x00, 0x00, 0x00 },
426     { 0xff, 0x00, 0xff, 0x00 },
427     { 0xff, 0xff, 0x00, 0x00 },
428     { 0xff, 0xff, 0xff, 0x00 }
429 };
430
431 static RGBTRIPLE EGAColorsTriples[16] = {
432 /* rgbBlue, rgbGreen, rgbRed */
433     { 0x00, 0x00, 0x00 },
434     { 0x00, 0x00, 0x80 },
435     { 0x00, 0x80, 0x00 },
436     { 0x00, 0x80, 0x80 },
437     { 0x80, 0x00, 0x00 },
438     { 0x80, 0x00, 0x80 },
439     { 0x80, 0x80, 0x00 },
440     { 0x80, 0x80, 0x80 },
441     { 0xc0, 0xc0, 0xc0 },
442     { 0x00, 0x00, 0xff },
443     { 0x00, 0xff, 0x00 },
444     { 0x00, 0xff, 0xff },
445     { 0xff, 0x00, 0x00 } ,
446     { 0xff, 0x00, 0xff },
447     { 0xff, 0xff, 0x00 },
448     { 0xff, 0xff, 0xff }
449 };
450
451 static RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
452 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
453     { 0x00, 0x00, 0x00, 0x00 },
454     { 0x00, 0x00, 0x80, 0x00 },
455     { 0x00, 0x80, 0x00, 0x00 },
456     { 0x00, 0x80, 0x80, 0x00 },
457     { 0x80, 0x00, 0x00, 0x00 },
458     { 0x80, 0x00, 0x80, 0x00 },
459     { 0x80, 0x80, 0x00, 0x00 },
460     { 0xc0, 0xc0, 0xc0, 0x00 },
461     { 0xc0, 0xdc, 0xc0, 0x00 },
462     { 0xf0, 0xca, 0xa6, 0x00 },
463     { 0xf0, 0xfb, 0xff, 0x00 },
464     { 0xa4, 0xa0, 0xa0, 0x00 },
465     { 0x80, 0x80, 0x80, 0x00 },
466     { 0x00, 0x00, 0xf0, 0x00 },
467     { 0x00, 0xff, 0x00, 0x00 },
468     { 0x00, 0xff, 0xff, 0x00 },
469     { 0xff, 0x00, 0x00, 0x00 },
470     { 0xff, 0x00, 0xff, 0x00 },
471     { 0xff, 0xff, 0x00, 0x00 },
472     { 0xff, 0xff, 0xff, 0x00 }
473 };
474
475 static RGBTRIPLE DefLogPaletteTriples[20] = { /* Copy of Default Logical Palette */
476 /* rgbBlue, rgbGreen, rgbRed */
477     { 0x00, 0x00, 0x00 },
478     { 0x00, 0x00, 0x80 },
479     { 0x00, 0x80, 0x00 },
480     { 0x00, 0x80, 0x80 },
481     { 0x80, 0x00, 0x00 },
482     { 0x80, 0x00, 0x80 },
483     { 0x80, 0x80, 0x00 },
484     { 0xc0, 0xc0, 0xc0 },
485     { 0xc0, 0xdc, 0xc0 },
486     { 0xf0, 0xca, 0xa6 },
487     { 0xf0, 0xfb, 0xff },
488     { 0xa4, 0xa0, 0xa0 },
489     { 0x80, 0x80, 0x80 },
490     { 0x00, 0x00, 0xf0 },
491     { 0x00, 0xff, 0x00 },
492     { 0x00, 0xff, 0xff },
493     { 0xff, 0x00, 0x00 },
494     { 0xff, 0x00, 0xff },
495     { 0xff, 0xff, 0x00 },
496     { 0xff, 0xff, 0xff}
497 };
498
499
500 /******************************************************************************
501  * GetDIBits [GDI32.@]
502  *
503  * Retrieves bits of bitmap and copies to buffer.
504  *
505  * RETURNS
506  *    Success: Number of scan lines copied from bitmap
507  *    Failure: 0
508  *
509  * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/bitmaps_87eb.asp
510  */
511 INT WINAPI GetDIBits(
512     HDC hdc,         /* [in]  Handle to device context */
513     HBITMAP hbitmap, /* [in]  Handle to bitmap */
514     UINT startscan,  /* [in]  First scan line to set in dest bitmap */
515     UINT lines,      /* [in]  Number of scan lines to copy */
516     LPVOID bits,       /* [out] Address of array for bitmap bits */
517     BITMAPINFO * info, /* [out] Address of structure with bitmap data */
518     UINT coloruse)   /* [in]  RGB or palette index */
519 {
520     DC * dc;
521     BITMAPOBJ * bmp;
522     int i;
523     HDC memdc;
524     int bitmap_type;
525     BOOL core_header;
526     LONG width;
527     LONG height;
528     WORD bpp;
529     DWORD compr;
530     void* colorPtr;
531     RGBTRIPLE* rgbTriples;
532     RGBQUAD* rgbQuads;
533
534     if (!info) return 0;
535
536     bitmap_type = DIB_GetBitmapInfo( (BITMAPINFOHEADER*) info, &width, &height, &bpp, &compr);
537     if (bitmap_type == -1)
538     {
539         ERR("Invalid bitmap format\n");
540         return 0;
541     }
542     core_header = (bitmap_type == 0);
543     memdc = CreateCompatibleDC(hdc);
544     if (!(dc = DC_GetDCUpdate( hdc )))
545     {
546         DeleteDC(memdc);
547         return 0;
548     }
549     if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
550     {
551         GDI_ReleaseObj( hdc );
552         DeleteDC(memdc);
553         return 0;
554     }
555
556     colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
557     rgbTriples = (RGBTRIPLE *) colorPtr;
558     rgbQuads = (RGBQUAD *) colorPtr;
559
560     /* Transfer color info */
561
562     if (bpp <= 8 && bpp > 0)
563     {
564         if (!core_header) info->bmiHeader.biClrUsed = 0;
565
566         /* If the bitmap object already has a dib section at the
567            same color depth then get the color map from it */
568         if (bmp->dib && bmp->dib->dsBm.bmBitsPixel == bpp) {
569             if(coloruse == DIB_RGB_COLORS) {
570                 HBITMAP oldbm = SelectObject(memdc, hbitmap);
571                 unsigned int colors = 1 << bpp;
572
573                 if (core_header)
574                 {
575                     /* Convert the color table (RGBQUAD to RGBTRIPLE) */                    
576                     RGBQUAD* buffer = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(RGBQUAD));
577
578                     if (buffer)
579                     {
580                         RGBTRIPLE* index = rgbTriples;
581                         GetDIBColorTable(memdc, 0, colors, buffer);
582
583                         for (i=0; i < colors; i++, index++)
584                         {
585                             index->rgbtRed   = buffer[i].rgbRed;
586                             index->rgbtGreen = buffer[i].rgbGreen;
587                             index->rgbtBlue  = buffer[i].rgbBlue;
588                         }
589
590                         HeapFree(GetProcessHeap(), 0, buffer);
591                     }
592                 }
593                 else
594                 {
595                     GetDIBColorTable(memdc, 0, colors, colorPtr);
596                 }
597                 SelectObject(memdc, oldbm);
598             }
599             else {
600                 WORD *index = colorPtr;
601                 for(i = 0; i < 1 << info->bmiHeader.biBitCount; i++, index++)
602                     *index = i;
603             }
604         }
605         else {
606             if(bpp >= bmp->bitmap.bmBitsPixel) {
607                 /* Generate the color map from the selected palette */
608                 PALETTEENTRY * palEntry;
609                 PALETTEOBJ * palette;
610                 if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->hPalette, PALETTE_MAGIC ))) {
611                     GDI_ReleaseObj( hdc );
612                     GDI_ReleaseObj( hbitmap );
613                     DeleteDC(memdc);
614                     return 0;
615                 }
616                 palEntry = palette->logpalette.palPalEntry;
617                 for (i = 0; i < (1 << bmp->bitmap.bmBitsPixel); i++, palEntry++) {
618                     if (coloruse == DIB_RGB_COLORS) {
619                         if (core_header)
620                         {
621                             rgbTriples[i].rgbtRed   = palEntry->peRed;
622                             rgbTriples[i].rgbtGreen = palEntry->peGreen;
623                             rgbTriples[i].rgbtBlue  = palEntry->peBlue;
624                         }
625                         else
626                         {
627                             rgbQuads[i].rgbRed      = palEntry->peRed;
628                             rgbQuads[i].rgbGreen    = palEntry->peGreen;
629                             rgbQuads[i].rgbBlue     = palEntry->peBlue;
630                             rgbQuads[i].rgbReserved = 0;
631                         }
632                     }
633                     else ((WORD *)colorPtr)[i] = (WORD)i;
634                 }
635                 GDI_ReleaseObj( dc->hPalette );
636             } else {
637                 switch (bpp) {
638                 case 1:
639                     if (core_header)
640                     {
641                         rgbTriples[0].rgbtRed = rgbTriples[0].rgbtGreen =
642                             rgbTriples[0].rgbtBlue = 0;
643                         rgbTriples[1].rgbtRed = rgbTriples[1].rgbtGreen =
644                             rgbTriples[1].rgbtBlue = 0xff;
645                     }
646                     else
647                     {    
648                         rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen =
649                             rgbQuads[0].rgbBlue = 0;
650                         rgbQuads[0].rgbReserved = 0;
651                         rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen =
652                             rgbQuads[1].rgbBlue = 0xff;
653                         rgbQuads[1].rgbReserved = 0;
654                     }
655                     break;
656
657                 case 4:
658                     if (core_header)
659                         memcpy(colorPtr, EGAColorsTriples, sizeof(EGAColorsTriples));
660                     else
661                         memcpy(colorPtr, EGAColorsQuads, sizeof(EGAColorsQuads));
662
663                     break;
664
665                 case 8:
666                     {
667                         if (core_header)
668                         {
669                             INT r, g, b;
670                             RGBTRIPLE *color;
671
672                             memcpy(rgbTriples, DefLogPaletteTriples,
673                                        10 * sizeof(RGBTRIPLE));
674                             memcpy(rgbTriples + 246, DefLogPaletteTriples + 10,
675                                        10 * sizeof(RGBTRIPLE));
676                             color = rgbTriples + 10;
677                             for(r = 0; r <= 5; r++) /* FIXME */
678                                 for(g = 0; g <= 5; g++)
679                                     for(b = 0; b <= 5; b++) {
680                                         color->rgbtRed =   (r * 0xff) / 5;
681                                         color->rgbtGreen = (g * 0xff) / 5;
682                                         color->rgbtBlue =  (b * 0xff) / 5;
683                                         color++;
684                                     }
685                         }
686                         else
687                         {
688                             INT r, g, b;
689                             RGBQUAD *color;
690
691                             memcpy(rgbQuads, DefLogPaletteQuads,
692                                        10 * sizeof(RGBQUAD));
693                             memcpy(rgbQuads + 246, DefLogPaletteQuads + 10,
694                                    10 * sizeof(RGBQUAD));
695                             color = rgbQuads + 10;
696                             for(r = 0; r <= 5; r++) /* FIXME */
697                                 for(g = 0; g <= 5; g++)
698                                     for(b = 0; b <= 5; b++) {
699                                         color->rgbRed =   (r * 0xff) / 5;
700                                         color->rgbGreen = (g * 0xff) / 5;
701                                         color->rgbBlue =  (b * 0xff) / 5;
702                                         color->rgbReserved = 0;
703                                         color++;
704                                     }
705                         }
706                     }
707                 }
708             }
709         }
710     }
711
712     if (bits && lines)
713     {
714         /* If the bitmap object already have a dib section that contains image data, get the bits from it */
715         if(bmp->dib && bmp->dib->dsBm.bmBitsPixel >= 15 && bpp >= 15)
716         {
717             /*FIXME: Only RGB dibs supported for now */
718             unsigned int srcwidth = bmp->dib->dsBm.bmWidth, srcwidthb = bmp->dib->dsBm.bmWidthBytes;
719             unsigned int dstwidth = width;
720             int dstwidthb = DIB_GetDIBWidthBytes( width, bpp );
721             LPBYTE dbits = bits, sbits = (LPBYTE) bmp->dib->dsBm.bmBits + (startscan * srcwidthb);
722             unsigned int x, y, width, widthb;
723
724             if ((height < 0) ^ (bmp->dib->dsBmih.biHeight < 0))
725             {
726                 dbits = (LPBYTE)bits + (dstwidthb * (lines-1));
727                 dstwidthb = -dstwidthb;
728             }
729
730             switch( bpp ) {
731
732             case 15:
733             case 16: /* 16 bpp dstDIB */
734                 {
735                     LPWORD dstbits = (LPWORD)dbits;
736                     WORD rmask = 0x7c00, gmask= 0x03e0, bmask = 0x001f;
737
738                     /* FIXME: BI_BITFIELDS not supported yet */
739
740                     switch(bmp->dib->dsBm.bmBitsPixel) {
741
742                     case 16: /* 16 bpp srcDIB -> 16 bpp dstDIB */
743                         {
744                             widthb = min(srcwidthb, abs(dstwidthb));
745                             /* FIXME: BI_BITFIELDS not supported yet */
746                             for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
747                                 memcpy(dbits, sbits, widthb);
748                         }
749                         break;
750
751                     case 24: /* 24 bpp srcDIB -> 16 bpp dstDIB */
752                         {
753                             LPBYTE srcbits = sbits;
754
755                             width = min(srcwidth, dstwidth);
756                             for( y = 0; y < lines; y++) {
757                                 for( x = 0; x < width; x++, srcbits += 3)
758                                     *dstbits++ = ((srcbits[0] >> 3) & bmask) |
759                                                  (((WORD)srcbits[1] << 2) & gmask) |
760                                                  (((WORD)srcbits[2] << 7) & rmask);
761
762                                 dstbits = (LPWORD)(dbits+=dstwidthb);
763                                 srcbits = (sbits += srcwidthb);
764                             }
765                         }
766                         break;
767
768                     case 32: /* 32 bpp srcDIB -> 16 bpp dstDIB */
769                         {
770                             LPDWORD srcbits = (LPDWORD)sbits;
771                             DWORD val;
772
773                             width = min(srcwidth, dstwidth);
774                             for( y = 0; y < lines; y++) {
775                                 for( x = 0; x < width; x++ ) {
776                                     val = *srcbits++;
777                                     *dstbits++ = (WORD)(((val >> 3) & bmask) | ((val >> 6) & gmask) |
778                                                        ((val >> 9) & rmask));
779                                 }
780                                 dstbits = (LPWORD)(dbits+=dstwidthb);
781                                 srcbits = (LPDWORD)(sbits+=srcwidthb);
782                             }
783                         }
784                         break;
785
786                     default: /* ? bit bmp -> 16 bit DIB */
787                         FIXME("15/16 bit DIB %d bit bitmap\n",
788                         bmp->bitmap.bmBitsPixel);
789                         break;
790                     }
791                 }
792                 break;
793
794             case 24: /* 24 bpp dstDIB */
795                 {
796                     LPBYTE dstbits = dbits;
797
798                     switch(bmp->dib->dsBm.bmBitsPixel) {
799
800                     case 16: /* 16 bpp srcDIB -> 24 bpp dstDIB */
801                         {
802                             LPWORD srcbits = (LPWORD)sbits;
803                             WORD val;
804
805                             width = min(srcwidth, dstwidth);
806                             /* FIXME: BI_BITFIELDS not supported yet */
807                             for( y = 0; y < lines; y++) {
808                                 for( x = 0; x < width; x++ ) {
809                                     val = *srcbits++;
810                                     *dstbits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07));
811                                     *dstbits++ = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07));
812                                     *dstbits++ = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07));
813                                 }
814                                 dstbits = (LPBYTE)(dbits+=dstwidthb);
815                                 srcbits = (LPWORD)(sbits+=srcwidthb);
816                             }
817                         }
818                         break;
819
820                     case 24: /* 24 bpp srcDIB -> 24 bpp dstDIB */
821                         {
822                             widthb = min(srcwidthb, abs(dstwidthb));
823                             for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
824                                 memcpy(dbits, sbits, widthb);
825                         }
826                         break;
827
828                     case 32: /* 32 bpp srcDIB -> 24 bpp dstDIB */
829                         {
830                             LPBYTE srcbits = (LPBYTE)sbits;
831
832                             width = min(srcwidth, dstwidth);
833                             for( y = 0; y < lines; y++) {
834                                 for( x = 0; x < width; x++, srcbits++ ) {
835                                     *dstbits++ = *srcbits++;
836                                     *dstbits++ = *srcbits++;
837                                     *dstbits++ = *srcbits++;
838                                 }
839                                 dstbits=(LPBYTE)(dbits+=dstwidthb);
840                                 srcbits = (LPBYTE)(sbits+=srcwidthb);
841                             }
842                         }
843                         break;
844
845                     default: /* ? bit bmp -> 24 bit DIB */
846                         FIXME("24 bit DIB %d bit bitmap\n",
847                               bmp->bitmap.bmBitsPixel);
848                         break;
849                     }
850                 }
851                 break;
852
853             case 32: /* 32 bpp dstDIB */
854                 {
855                     LPDWORD dstbits = (LPDWORD)dbits;
856
857                     /* FIXME: BI_BITFIELDS not supported yet */
858
859                     switch(bmp->dib->dsBm.bmBitsPixel) {
860                         case 16: /* 16 bpp srcDIB -> 32 bpp dstDIB */
861                         {
862                             LPWORD srcbits = (LPWORD)sbits;
863                             DWORD val;
864
865                             width = min(srcwidth, dstwidth);
866                             /* FIXME: BI_BITFIELDS not supported yet */
867                             for( y = 0; y < lines; y++) {
868                                 for( x = 0; x < width; x++ ) {
869                                     val = (DWORD)*srcbits++;
870                                     *dstbits++ = ((val << 3) & 0xf8) | ((val >> 2) & 0x07) |
871                                                  ((val << 6) & 0xf800) | ((val << 1) & 0x0700) |
872                                                  ((val << 9) & 0xf80000) | ((val << 4) & 0x070000);
873                                 }
874                                 dstbits=(LPDWORD)(dbits+=dstwidthb);
875                                 srcbits=(LPWORD)(sbits+=srcwidthb);
876                             }
877                         }
878                         break;
879
880                     case 24: /* 24 bpp srcDIB -> 32 bpp dstDIB */
881                         {
882                             LPBYTE srcbits = sbits;
883
884                             width = min(srcwidth, dstwidth);
885                             for( y = 0; y < lines; y++) {
886                                 for( x = 0; x < width; x++, srcbits+=3 )
887                                     *dstbits++ = ((DWORD)*srcbits) & 0x00ffffff;
888                                 dstbits=(LPDWORD)(dbits+=dstwidthb);
889                                 srcbits=(sbits+=srcwidthb);
890                             }
891                         }
892                         break;
893
894                     case 32: /* 32 bpp srcDIB -> 32 bpp dstDIB */
895                         {
896                             widthb = min(srcwidthb, abs(dstwidthb));
897                             /* FIXME: BI_BITFIELDS not supported yet */
898                             for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb) {
899                                 memcpy(dbits, sbits, widthb);
900                             }
901                         }
902                         break;
903
904                     default: /* ? bit bmp -> 32 bit DIB */
905                         FIXME("32 bit DIB %d bit bitmap\n",
906                         bmp->bitmap.bmBitsPixel);
907                         break;
908                     }
909                 }
910                 break;
911
912             default: /* ? bit DIB */
913                 FIXME("Unsupported DIB depth %d\n", info->bmiHeader.biBitCount);
914                 break;
915             }
916         }
917         /* Otherwise, get bits from the XImage */
918         else
919         {
920             if (!bmp->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) lines = 0;
921             else
922             {
923                 if (bmp->funcs && bmp->funcs->pGetDIBits)
924                     lines = bmp->funcs->pGetDIBits( dc->physDev, hbitmap, startscan,
925                                                     lines, bits, info, coloruse );
926                 else
927                     lines = 0;  /* FIXME: should copy from bmp->bitmap.bmBits */
928             }
929         }
930     }
931     else
932     {
933         /* fill in struct members */
934
935         if (bpp == 0)
936         {
937             if (core_header)
938             {
939                 BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) info;
940                 coreheader->bcWidth = bmp->bitmap.bmWidth;
941                 coreheader->bcHeight = bmp->bitmap.bmHeight;
942                 coreheader->bcPlanes = 1;
943                 coreheader->bcBitCount = bmp->bitmap.bmBitsPixel;
944             }
945             else
946             {
947                 info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
948                 info->bmiHeader.biHeight = bmp->bitmap.bmHeight;
949                 info->bmiHeader.biPlanes = 1;
950                 info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
951                 info->bmiHeader.biSizeImage =
952                                  DIB_GetDIBImageBytes( bmp->bitmap.bmWidth,
953                                                        bmp->bitmap.bmHeight,
954                                                        bmp->bitmap.bmBitsPixel );
955                 info->bmiHeader.biCompression = 0;
956             }
957             lines = abs(bmp->bitmap.bmHeight);
958         }
959     }
960
961     if (!core_header)
962     {
963         TRACE("biSizeImage = %ld, ", info->bmiHeader.biSizeImage);
964     }
965     TRACE("biWidth = %ld, biHeight = %ld\n", width, height);
966
967     GDI_ReleaseObj( hdc );
968     GDI_ReleaseObj( hbitmap );
969     DeleteDC(memdc);
970     return lines;
971 }
972
973
974 /***********************************************************************
975  *           CreateDIBitmap    (GDI32.@)
976  *
977  * Creates a DDB (device dependent bitmap) from a DIB.
978  * The DDB will have the same color depth as the reference DC.
979  */
980 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
981                             DWORD init, LPCVOID bits, const BITMAPINFO *data,
982                             UINT coloruse )
983 {
984     HBITMAP handle;
985     LONG width;
986     LONG height;
987     WORD bpp;
988     DWORD compr;
989     DC *dc;
990
991     if (DIB_GetBitmapInfo( header, &width, &height, &bpp, &compr ) == -1) return 0;
992     
993     if (width < 0)
994     {
995         TRACE("Bitmap has a negative width\n");
996         return 0;
997     }
998     
999     /* Top-down DIBs have a negative height */
1000     if (height < 0) height = -height;
1001
1002     TRACE("hdc=%p, header=%p, init=%lu, bits=%p, data=%p, coloruse=%u (bitmap: width=%ld, height=%ld, bpp=%u, compr=%lu)\n",
1003            hdc, header, init, bits, data, coloruse, width, height, bpp, compr);
1004     
1005     if (hdc == NULL)
1006         handle = CreateBitmap( width, height, 1, 1, NULL );
1007     else
1008         handle = CreateCompatibleBitmap( hdc, width, height );
1009
1010     if (handle)
1011     {
1012         if (init == CBM_INIT) SetDIBits( hdc, handle, 0, height, bits, data, coloruse );
1013
1014         else if (hdc && ((dc = DC_GetDCPtr( hdc )) != NULL) )
1015         {
1016             if (!BITMAP_SetOwnerDC( handle, dc ))
1017             {
1018                 DeleteObject( handle );
1019                 handle = 0;
1020             }
1021             GDI_ReleaseObj( hdc );
1022         }
1023     }
1024
1025     return handle;
1026 }
1027
1028 /***********************************************************************
1029  *           CreateDIBSection    (GDI.489)
1030  */
1031 HBITMAP16 WINAPI CreateDIBSection16 (HDC16 hdc, const BITMAPINFO *bmi, UINT16 usage,
1032                                      SEGPTR *bits16, HANDLE section, DWORD offset)
1033 {
1034     LPVOID bits32;
1035     HBITMAP hbitmap;
1036
1037     hbitmap = CreateDIBSection( HDC_32(hdc), bmi, usage, &bits32, section, offset );
1038     if (hbitmap)
1039     {
1040         BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr(hbitmap, BITMAP_MAGIC);
1041         if (bmp && bmp->dib && bits32)
1042         {
1043             const BITMAPINFOHEADER *bi = &bmi->bmiHeader;
1044             LONG width, height;
1045             WORD bpp;
1046             DWORD compr;
1047             BOOL core_header;
1048             INT width_bytes;
1049             INT size;
1050             WORD count, sel;
1051             int i;
1052
1053             core_header = (DIB_GetBitmapInfo(bi, &width, &height, &bpp, &compr) == 0);
1054
1055             height = height >= 0 ? height : -height;
1056             width_bytes = DIB_GetDIBWidthBytes(width, bpp);
1057             
1058             if (core_header)
1059             {
1060                 size = width_bytes * height;
1061             }
1062             else
1063             {
1064                 size = (bi->biSizeImage && compr != BI_RGB) ?
1065                         bi->biSizeImage : width_bytes * height;
1066             }
1067
1068             /* calculate number of sel's needed for size with 64K steps */
1069             count = (size + 0xffff) / 0x10000;
1070             sel = AllocSelectorArray16(count);
1071
1072             for (i = 0; i < count; i++)
1073             {
1074                 SetSelectorBase(sel + (i << __AHSHIFT), (DWORD)bits32 + i * 0x10000);
1075                 SetSelectorLimit16(sel + (i << __AHSHIFT), size - 1); /* yep, limit is correct */
1076                 size -= 0x10000;
1077             }
1078             bmp->segptr_bits = MAKESEGPTR( sel, 0 );
1079             if (bits16) *bits16 = bmp->segptr_bits;
1080         }
1081         if (bmp) GDI_ReleaseObj( hbitmap );
1082     }
1083     return HBITMAP_16(hbitmap);
1084 }
1085
1086 /***********************************************************************
1087  *           DIB_CreateDIBSection
1088  */
1089 HBITMAP DIB_CreateDIBSection(HDC hdc, const BITMAPINFO *bmi, UINT usage,
1090                              VOID **bits, HANDLE section,
1091                              DWORD offset, DWORD ovr_pitch)
1092 {
1093     HBITMAP hbitmap = 0;
1094     DC *dc;
1095     BOOL bDesktopDC = FALSE;
1096
1097     /* If the reference hdc is null, take the desktop dc */
1098     if (hdc == 0)
1099     {
1100         hdc = CreateCompatibleDC(0);
1101         bDesktopDC = TRUE;
1102     }
1103
1104     if ((dc = DC_GetDCPtr( hdc )))
1105     {
1106         if(dc->funcs->pCreateDIBSection)
1107             hbitmap = dc->funcs->pCreateDIBSection(dc->physDev, bmi, usage, bits, section, offset, ovr_pitch);
1108         GDI_ReleaseObj(hdc);
1109     }
1110
1111     if (bDesktopDC)
1112       DeleteDC(hdc);
1113
1114     return hbitmap;
1115 }
1116
1117 /***********************************************************************
1118  *           CreateDIBSection    (GDI32.@)
1119  */
1120 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1121                                 VOID **bits, HANDLE section,
1122                                 DWORD offset)
1123 {
1124     return DIB_CreateDIBSection(hdc, bmi, usage, bits, section, offset, 0);
1125 }