gdi32: Allow the PutImage entry point to optionally support stretching.
[wine] / dlls / gdi32 / 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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     If biCompression is BI_BITFIELDS, the color masks are at the same position
47     in all the headers (they start at bmiColors of BITMAPINFOHEADER), because
48     the new headers have structure members for the masks.
49
50
51   * You should never access the color table using the bmiColors member,
52     because the passed structure may have one of the extended headers
53     mentioned above. Use this to calculate the location:
54     
55     BITMAPINFO* info;
56     void* colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
57
58     
59   * More information:
60     Search for "Bitmap Structures" in MSDN
61 */
62
63 #include <stdarg.h>
64 #include <stdlib.h>
65 #include <string.h>
66 #include <assert.h>
67
68 #include "windef.h"
69 #include "winbase.h"
70 #include "gdi_private.h"
71 #include "wine/debug.h"
72
73 WINE_DEFAULT_DEBUG_CHANNEL(bitmap);
74
75
76 /***********************************************************************
77  *           bitmap_info_size
78  *
79  * Return the size of the bitmap info structure including color table.
80  */
81 int bitmap_info_size( const BITMAPINFO * info, WORD coloruse )
82 {
83     unsigned int colors, size, masks = 0;
84
85     if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
86     {
87         const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
88         colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
89         return sizeof(BITMAPCOREHEADER) + colors *
90              ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
91     }
92     else  /* assume BITMAPINFOHEADER */
93     {
94         colors = info->bmiHeader.biClrUsed;
95         if (colors > 256) colors = 256;
96         if (!colors && (info->bmiHeader.biBitCount <= 8))
97             colors = 1 << info->bmiHeader.biBitCount;
98         if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3;
99         size = max( info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) );
100         return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
101     }
102 }
103
104
105 /***********************************************************************
106  *           DIB_GetBitmapInfo
107  *
108  * Get the info from a bitmap header.
109  * Return 0 for COREHEADER, 1 for INFOHEADER, -1 for error.
110  */
111 int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
112                        LONG *height, WORD *planes, WORD *bpp, DWORD *compr, DWORD *size )
113 {
114     if (header->biSize == sizeof(BITMAPCOREHEADER))
115     {
116         const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)header;
117         *width  = core->bcWidth;
118         *height = core->bcHeight;
119         *planes = core->bcPlanes;
120         *bpp    = core->bcBitCount;
121         *compr  = 0;
122         *size   = 0;
123         return 0;
124     }
125     if (header->biSize >= sizeof(BITMAPINFOHEADER)) /* assume BITMAPINFOHEADER */
126     {
127         *width  = header->biWidth;
128         *height = header->biHeight;
129         *planes = header->biPlanes;
130         *bpp    = header->biBitCount;
131         *compr  = header->biCompression;
132         *size   = header->biSizeImage;
133         return 1;
134     }
135     ERR("(%d): unknown/wrong size for header\n", header->biSize );
136     return -1;
137 }
138
139 /* nulldrv fallback implementation using SetDIBits/StretchBlt */
140 INT nulldrv_StretchDIBits( PHYSDEV dev, INT xDst, INT yDst, INT widthDst, INT heightDst,
141                            INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
142                            const BITMAPINFO *info, UINT coloruse, DWORD rop )
143 {
144     DC *dc = get_nulldrv_dc( dev );
145     INT ret;
146     LONG width, height;
147     WORD planes, bpp;
148     DWORD compr, size;
149     HBITMAP hBitmap;
150     HDC hdcMem;
151
152     /* make sure we have a real implementation for StretchBlt and SetDIBits */
153     if (GET_DC_PHYSDEV( dc, pStretchBlt ) == dev || GET_DC_PHYSDEV( dc, pSetDIBits ) == dev)
154         return 0;
155
156     if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size ) == -1)
157         return 0;
158
159     if (width < 0) return 0;
160
161     if (xSrc == 0 && ySrc == 0 && widthDst == widthSrc && heightDst == heightSrc &&
162         info->bmiHeader.biCompression == BI_RGB)
163     {
164         /* Windows appears to have a fast case optimization
165          * that uses the wrong origin for top-down DIBs */
166         if (height < 0 && heightSrc < abs(height)) ySrc = abs(height) - heightSrc;
167
168         if (xDst == 0 && yDst == 0 && info->bmiHeader.biCompression == BI_RGB && rop == SRCCOPY)
169         {
170             BITMAP bm;
171             hBitmap = GetCurrentObject( dev->hdc, OBJ_BITMAP );
172             if (GetObjectW( hBitmap, sizeof(bm), &bm ) &&
173                 bm.bmWidth == widthSrc && bm.bmHeight == heightSrc &&
174                 bm.bmBitsPixel == bpp && bm.bmPlanes == planes)
175             {
176                 /* fast path */
177                 return SetDIBits( dev->hdc, hBitmap, 0, height, bits, info, coloruse );
178             }
179         }
180     }
181
182     hdcMem = CreateCompatibleDC( dev->hdc );
183     hBitmap = CreateCompatibleBitmap( dev->hdc, width, height );
184     SelectObject( hdcMem, hBitmap );
185     if (coloruse == DIB_PAL_COLORS)
186         SelectPalette( hdcMem, GetCurrentObject( dev->hdc, OBJ_PAL ), FALSE );
187
188     if (info->bmiHeader.biCompression == BI_RLE4 || info->bmiHeader.biCompression == BI_RLE8)
189     {
190         /* when RLE compression is used, there may be some gaps (ie the DIB doesn't
191          * contain all the rectangle described in bmiHeader, but only part of it.
192          * This mean that those undescribed pixels must be left untouched.
193          * So, we first copy on a memory bitmap the current content of the
194          * destination rectangle, blit the DIB bits on top of it - hence leaving
195          * the gaps untouched -, and blitting the rectangle back.
196          * This insure that gaps are untouched on the destination rectangle
197          */
198         StretchBlt( hdcMem, xSrc, abs(height) - heightSrc - ySrc, widthSrc, heightSrc,
199                     dev->hdc, xDst, yDst, widthDst, heightDst, rop );
200     }
201     ret = SetDIBits( hdcMem, hBitmap, 0, height, bits, info, coloruse );
202     if (ret) StretchBlt( dev->hdc, xDst, yDst, widthDst, heightDst,
203                          hdcMem, xSrc, abs(height) - heightSrc - ySrc, widthSrc, heightSrc, rop );
204     DeleteDC( hdcMem );
205     DeleteObject( hBitmap );
206     return ret;
207 }
208
209 /***********************************************************************
210  *           StretchDIBits   (GDI32.@)
211  */
212 INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst, INT heightDst,
213                          INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
214                          const BITMAPINFO *info, UINT coloruse, DWORD rop )
215 {
216     DC *dc;
217     INT ret = 0;
218
219     if (!bits || !info) return 0;
220
221     if ((dc = get_dc_ptr( hdc )))
222     {
223         PHYSDEV physdev = GET_DC_PHYSDEV( dc, pStretchDIBits );
224         update_dc( dc );
225         ret = physdev->funcs->pStretchDIBits( physdev, xDst, yDst, widthDst, heightDst,
226                                               xSrc, ySrc, widthSrc, heightSrc, bits, info, coloruse, rop );
227         release_dc_ptr( dc );
228     }
229     return ret;
230 }
231
232
233 /******************************************************************************
234  * SetDIBits [GDI32.@]
235  *
236  * Sets pixels in a bitmap using colors from DIB.
237  *
238  * PARAMS
239  *    hdc       [I] Handle to device context
240  *    hbitmap   [I] Handle to bitmap
241  *    startscan [I] Starting scan line
242  *    lines     [I] Number of scan lines
243  *    bits      [I] Array of bitmap bits
244  *    info      [I] Address of structure with data
245  *    coloruse  [I] Type of color indexes to use
246  *
247  * RETURNS
248  *    Success: Number of scan lines copied
249  *    Failure: 0
250  */
251 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
252                       UINT lines, LPCVOID bits, const BITMAPINFO *info,
253                       UINT coloruse )
254 {
255     DC *dc = get_dc_ptr( hdc );
256     BOOL delete_hdc = FALSE;
257     PHYSDEV physdev;
258     BITMAPOBJ *bitmap;
259     INT result = 0;
260
261     if (coloruse == DIB_RGB_COLORS && !dc)
262     {
263         hdc = CreateCompatibleDC(0);
264         dc = get_dc_ptr( hdc );
265         delete_hdc = TRUE;
266     }
267
268     if (!dc) return 0;
269
270     update_dc( dc );
271
272     if (!(bitmap = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
273     {
274         release_dc_ptr( dc );
275         if (delete_hdc) DeleteDC(hdc);
276         return 0;
277     }
278
279     physdev = GET_DC_PHYSDEV( dc, pSetDIBits );
280     if (BITMAP_SetOwnerDC( hbitmap, physdev ))
281         result = physdev->funcs->pSetDIBits( physdev, hbitmap, startscan, lines, bits, info, coloruse );
282
283     GDI_ReleaseObj( hbitmap );
284     release_dc_ptr( dc );
285     if (delete_hdc) DeleteDC(hdc);
286     return result;
287 }
288
289
290 /***********************************************************************
291  *           SetDIBitsToDevice   (GDI32.@)
292  */
293 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
294                            DWORD cy, INT xSrc, INT ySrc, UINT startscan,
295                            UINT lines, LPCVOID bits, const BITMAPINFO *info,
296                            UINT coloruse )
297 {
298     INT ret = 0;
299     DC *dc;
300
301     if (!bits) return 0;
302
303     if ((dc = get_dc_ptr( hdc )))
304     {
305         PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBitsToDevice );
306         update_dc( dc );
307         ret = physdev->funcs->pSetDIBitsToDevice( physdev, xDest, yDest, cx, cy, xSrc,
308                                                   ySrc, startscan, lines, bits, info, coloruse );
309         release_dc_ptr( dc );
310     }
311     return ret;
312 }
313
314 /***********************************************************************
315  *           SetDIBColorTable    (GDI32.@)
316  */
317 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUAD *colors )
318 {
319     DC * dc;
320     UINT result = 0;
321     BITMAPOBJ * bitmap;
322
323     if (!(dc = get_dc_ptr( hdc ))) return 0;
324
325     if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
326     {
327         PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBColorTable );
328
329         /* Check if currently selected bitmap is a DIB */
330         if (bitmap->color_table)
331         {
332             if (startpos < bitmap->nb_colors)
333             {
334                 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
335                 memcpy(bitmap->color_table + startpos, colors, entries * sizeof(RGBQUAD));
336                 result = entries;
337             }
338         }
339         GDI_ReleaseObj( dc->hBitmap );
340         physdev->funcs->pSetDIBColorTable( physdev, startpos, entries, colors );
341     }
342     release_dc_ptr( dc );
343     return result;
344 }
345
346
347 /***********************************************************************
348  *           GetDIBColorTable    (GDI32.@)
349  */
350 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
351 {
352     DC * dc;
353     BITMAPOBJ *bitmap;
354     UINT result = 0;
355
356     if (!(dc = get_dc_ptr( hdc ))) return 0;
357
358     if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
359     {
360         /* Check if currently selected bitmap is a DIB */
361         if (bitmap->color_table)
362         {
363             if (startpos < bitmap->nb_colors)
364             {
365                 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
366                 memcpy(colors, bitmap->color_table + startpos, entries * sizeof(RGBQUAD));
367                 result = entries;
368             }
369         }
370         GDI_ReleaseObj( dc->hBitmap );
371     }
372     release_dc_ptr( dc );
373     return result;
374 }
375
376 static const RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
377 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
378     { 0x00, 0x00, 0x00, 0x00 },
379     { 0x00, 0x00, 0x80, 0x00 },
380     { 0x00, 0x80, 0x00, 0x00 },
381     { 0x00, 0x80, 0x80, 0x00 },
382     { 0x80, 0x00, 0x00, 0x00 },
383     { 0x80, 0x00, 0x80, 0x00 },
384     { 0x80, 0x80, 0x00, 0x00 },
385     { 0xc0, 0xc0, 0xc0, 0x00 },
386     { 0xc0, 0xdc, 0xc0, 0x00 },
387     { 0xf0, 0xca, 0xa6, 0x00 },
388     { 0xf0, 0xfb, 0xff, 0x00 },
389     { 0xa4, 0xa0, 0xa0, 0x00 },
390     { 0x80, 0x80, 0x80, 0x00 },
391     { 0x00, 0x00, 0xff, 0x00 },
392     { 0x00, 0xff, 0x00, 0x00 },
393     { 0x00, 0xff, 0xff, 0x00 },
394     { 0xff, 0x00, 0x00, 0x00 },
395     { 0xff, 0x00, 0xff, 0x00 },
396     { 0xff, 0xff, 0x00, 0x00 },
397     { 0xff, 0xff, 0xff, 0x00 }
398 };
399
400 static const DWORD bit_fields_888[3] = {0xff0000, 0x00ff00, 0x0000ff};
401 static const DWORD bit_fields_565[3] = {0xf800, 0x07e0, 0x001f};
402 static const DWORD bit_fields_555[3] = {0x7c00, 0x03e0, 0x001f};
403
404 static int fill_query_info( BITMAPINFO *info, BITMAPOBJ *bmp )
405 {
406     BITMAPINFOHEADER header;
407
408     header.biSize   = info->bmiHeader.biSize; /* Ensure we don't overwrite the original size when we copy back */
409     header.biWidth  = bmp->bitmap.bmWidth;
410     header.biHeight = bmp->bitmap.bmHeight;
411     header.biPlanes = 1;
412
413     if (bmp->dib)
414     {
415         header.biBitCount = bmp->dib->dsBm.bmBitsPixel;
416         switch (bmp->dib->dsBm.bmBitsPixel)
417         {
418         case 16:
419         case 32:
420             header.biCompression = BI_BITFIELDS;
421             break;
422         default:
423             header.biCompression = BI_RGB;
424             break;
425         }
426     }
427     else
428     {
429         header.biCompression = (bmp->bitmap.bmBitsPixel > 8) ? BI_BITFIELDS : BI_RGB;
430         header.biBitCount = bmp->bitmap.bmBitsPixel;
431     }
432
433     header.biSizeImage = get_dib_image_size( (BITMAPINFO *)&header );
434     header.biXPelsPerMeter = 0;
435     header.biYPelsPerMeter = 0;
436     header.biClrUsed       = 0;
437     header.biClrImportant  = 0;
438
439     if ( info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER) )
440     {
441         BITMAPCOREHEADER *coreheader = (BITMAPCOREHEADER *)info;
442
443         coreheader->bcWidth    = header.biWidth;
444         coreheader->bcHeight   = header.biHeight;
445         coreheader->bcPlanes   = header.biPlanes;
446         coreheader->bcBitCount = header.biBitCount;
447     }
448     else
449         info->bmiHeader = header;
450
451     return abs(bmp->bitmap.bmHeight);
452 }
453
454 /************************************************************************
455  *      copy_color_info
456  *
457  * Copy BITMAPINFO color information where dst may be a BITMAPCOREINFO.
458  */
459 static void copy_color_info(BITMAPINFO *dst, const BITMAPINFO *src, UINT coloruse)
460 {
461     unsigned int colors = src->bmiHeader.biBitCount > 8 ? 0 : 1 << src->bmiHeader.biBitCount;
462     RGBQUAD *src_colors = (RGBQUAD *)((char *)src + src->bmiHeader.biSize);
463
464     assert( src->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) );
465
466     if (src->bmiHeader.biClrUsed) colors = src->bmiHeader.biClrUsed;
467
468     if (dst->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
469     {
470         BITMAPCOREINFO *core = (BITMAPCOREINFO *)dst;
471         if (coloruse == DIB_PAL_COLORS)
472             memcpy( core->bmciColors, src_colors, colors * sizeof(WORD) );
473         else
474         {
475             unsigned int i;
476             for (i = 0; i < colors; i++)
477             {
478                 core->bmciColors[i].rgbtRed   = src_colors[i].rgbRed;
479                 core->bmciColors[i].rgbtGreen = src_colors[i].rgbGreen;
480                 core->bmciColors[i].rgbtBlue  = src_colors[i].rgbBlue;
481             }
482         }
483     }
484     else
485     {
486         dst->bmiHeader.biClrUsed   = src->bmiHeader.biClrUsed;
487         dst->bmiHeader.biSizeImage = src->bmiHeader.biSizeImage;
488
489         if (src->bmiHeader.biCompression == BI_BITFIELDS)
490             /* bitfields are always at bmiColors even in larger structures */
491             memcpy( dst->bmiColors, src->bmiColors, 3 * sizeof(DWORD) );
492         else if (colors)
493         {
494             void *colorptr = (char *)dst + dst->bmiHeader.biSize;
495             unsigned int size;
496
497             if (coloruse == DIB_PAL_COLORS)
498                 size = colors * sizeof(WORD);
499             else
500                 size = colors * sizeof(RGBQUAD);
501             memcpy( colorptr, src_colors, size );
502         }
503     }
504 }
505
506 static void fill_default_color_table( BITMAPINFO *info )
507 {
508     int i;
509
510     switch (info->bmiHeader.biBitCount)
511     {
512     case 1:
513         info->bmiColors[0].rgbRed = info->bmiColors[0].rgbGreen = info->bmiColors[0].rgbBlue = 0;
514         info->bmiColors[0].rgbReserved = 0;
515         info->bmiColors[1].rgbRed = info->bmiColors[1].rgbGreen = info->bmiColors[1].rgbBlue = 0xff;
516         info->bmiColors[1].rgbReserved = 0;
517         break;
518
519     case 4:
520         /* The EGA palette is the first and last 8 colours of the default palette
521            with the innermost pair swapped */
522         memcpy(info->bmiColors,     DefLogPaletteQuads,      7 * sizeof(RGBQUAD));
523         memcpy(info->bmiColors + 7, DefLogPaletteQuads + 12, 1 * sizeof(RGBQUAD));
524         memcpy(info->bmiColors + 8, DefLogPaletteQuads +  7, 1 * sizeof(RGBQUAD));
525         memcpy(info->bmiColors + 9, DefLogPaletteQuads + 13, 7 * sizeof(RGBQUAD));
526         break;
527
528     case 8:
529         memcpy(info->bmiColors, DefLogPaletteQuads, 10 * sizeof(RGBQUAD));
530         memcpy(info->bmiColors + 246, DefLogPaletteQuads + 10, 10 * sizeof(RGBQUAD));
531         for (i = 10; i < 246; i++)
532         {
533             info->bmiColors[i].rgbRed      = (i & 0x07) << 5;
534             info->bmiColors[i].rgbGreen    = (i & 0x38) << 2;
535             info->bmiColors[i].rgbBlue     =  i & 0xc0;
536             info->bmiColors[i].rgbReserved = 0;
537         }
538         break;
539
540     default:
541         ERR("called with bitcount %d\n", info->bmiHeader.biBitCount);
542     }
543 }
544
545 /******************************************************************************
546  * GetDIBits [GDI32.@]
547  *
548  * Retrieves bits of bitmap and copies to buffer.
549  *
550  * RETURNS
551  *    Success: Number of scan lines copied from bitmap
552  *    Failure: 0
553  */
554 INT WINAPI GetDIBits(
555     HDC hdc,         /* [in]  Handle to device context */
556     HBITMAP hbitmap, /* [in]  Handle to bitmap */
557     UINT startscan,  /* [in]  First scan line to set in dest bitmap */
558     UINT lines,      /* [in]  Number of scan lines to copy */
559     LPVOID bits,       /* [out] Address of array for bitmap bits */
560     BITMAPINFO * info, /* [out] Address of structure with bitmap data */
561     UINT coloruse)   /* [in]  RGB or palette index */
562 {
563     DC * dc;
564     BITMAPOBJ * bmp;
565     int i;
566     int bitmap_type;
567     LONG width;
568     LONG height;
569     WORD planes, bpp;
570     DWORD compr, size;
571     char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
572     BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf;
573     unsigned int colors = 0;
574
575     if (!info) return 0;
576
577     bitmap_type = DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size);
578     if (bitmap_type == -1)
579     {
580         ERR("Invalid bitmap format\n");
581         return 0;
582     }
583     if (!(dc = get_dc_ptr( hdc )))
584     {
585         SetLastError( ERROR_INVALID_PARAMETER );
586         return 0;
587     }
588     update_dc( dc );
589     if (!(bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
590     {
591         release_dc_ptr( dc );
592         return 0;
593     }
594
595
596     if (bpp == 0) /* query bitmap info only */
597     {
598         lines = fill_query_info( info, bmp );
599         goto done;
600     }
601
602     /* Since info may be a BITMAPCOREINFO or any of the larger BITMAPINFO structures, we'll use our
603        own copy and transfer the colour info back at the end */
604
605     dst_info->bmiHeader.biSize          = sizeof(dst_info->bmiHeader);
606     dst_info->bmiHeader.biWidth         = width;
607     dst_info->bmiHeader.biHeight        = height;
608     dst_info->bmiHeader.biPlanes        = planes;
609     dst_info->bmiHeader.biBitCount      = bpp;
610     dst_info->bmiHeader.biCompression   = compr;
611     dst_info->bmiHeader.biSizeImage     = get_dib_image_size( dst_info );
612     dst_info->bmiHeader.biXPelsPerMeter = 0;
613     dst_info->bmiHeader.biYPelsPerMeter = 0;
614     dst_info->bmiHeader.biClrUsed       = 0;
615     dst_info->bmiHeader.biClrImportant  = 0;
616
617     switch (bpp)
618     {
619     case 1:
620     case 4:
621     case 8:
622     {
623         colors = 1 << bpp;
624
625         /* If the bitmap object is a dib section at the
626            same color depth then get the color map from it */
627         if (bmp->dib && bpp == bmp->dib->dsBm.bmBitsPixel && coloruse == DIB_RGB_COLORS)
628         {
629             colors = min( colors, bmp->nb_colors );
630             if (colors != 1 << bpp) dst_info->bmiHeader.biClrUsed = colors;
631             memcpy( dst_info->bmiColors, bmp->color_table, colors * sizeof(RGBQUAD) );
632         }
633
634         /* For color DDBs in native depth (mono DDBs always have a black/white palette):
635            Generate the color map from the selected palette.  In the DIB_PAL_COLORS
636            case we'll fix up the indices after the format conversion. */
637         else if ( (bpp > 1 && bpp == bmp->bitmap.bmBitsPixel) || coloruse == DIB_PAL_COLORS )
638         {
639             PALETTEENTRY palEntry[256];
640
641             memset( palEntry, 0, sizeof(palEntry) );
642             if (!GetPaletteEntries( dc->hPalette, 0, colors, palEntry ))
643             {
644                 lines = 0;
645                 goto done;
646             }
647
648             for (i = 0; i < colors; i++)
649             {
650                 dst_info->bmiColors[i].rgbRed      = palEntry[i].peRed;
651                 dst_info->bmiColors[i].rgbGreen    = palEntry[i].peGreen;
652                 dst_info->bmiColors[i].rgbBlue     = palEntry[i].peBlue;
653                 dst_info->bmiColors[i].rgbReserved = 0;
654             }
655         }
656         else
657             fill_default_color_table( dst_info );
658         break;
659     }
660
661     case 15:
662         if (dst_info->bmiHeader.biCompression == BI_BITFIELDS)
663             memcpy( dst_info->bmiColors, bit_fields_555, sizeof(bit_fields_555) );
664         break;
665
666     case 16:
667         if (dst_info->bmiHeader.biCompression == BI_BITFIELDS)
668         {
669             if (bmp->dib)
670             {
671                 if (bmp->dib->dsBmih.biCompression == BI_BITFIELDS && bmp->dib->dsBmih.biBitCount == bpp)
672                     memcpy( dst_info->bmiColors, bmp->dib->dsBitfields, 3 * sizeof(DWORD) );
673                 else
674                     memcpy( dst_info->bmiColors, bit_fields_555, sizeof(bit_fields_555) );
675             }
676             else
677                 memcpy( dst_info->bmiColors, bit_fields_565, sizeof(bit_fields_565) );
678         }
679         break;
680
681     case 24:
682     case 32:
683         if (dst_info->bmiHeader.biCompression == BI_BITFIELDS)
684         {
685             if (bmp->dib && bmp->dib->dsBmih.biCompression == BI_BITFIELDS && bmp->dib->dsBmih.biBitCount == bpp)
686                 memcpy( dst_info->bmiColors, bmp->dib->dsBitfields, 3 * sizeof(DWORD) );
687             else
688                 memcpy( dst_info->bmiColors, bit_fields_888, sizeof(bit_fields_888) );
689         }
690         break;
691     }
692
693     if (bits && lines)
694     {
695         PHYSDEV physdev;
696         char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
697         BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
698         struct gdi_image_bits src_bits;
699         struct bitblt_coords src;
700         DWORD err;
701
702         /* FIXME: will need updating once the dib driver has pGetImage. */
703         physdev = GET_DC_PHYSDEV( dc, pGetImage );
704
705         if (!BITMAP_SetOwnerDC( hbitmap, physdev )) lines = 0;
706
707         src.visrect.left = 0;
708         src.visrect.right = min( width, bmp->bitmap.bmWidth );
709
710         if (startscan >= bmp->bitmap.bmHeight)                       /* constrain lines to within src bitmap */
711             lines = 0;
712         else
713             lines = min( lines, bmp->bitmap.bmHeight - startscan );
714         lines = min( lines, abs(height) );                           /* and constrain to within dest bitmap */
715
716         if (lines == 0) goto done;
717
718         src.visrect.bottom = bmp->bitmap.bmHeight - startscan;
719         src.visrect.top = src.visrect.bottom - lines;
720         src.x = src.visrect.left;
721         src.y = src.visrect.top;
722         src.width = src.visrect.right - src.visrect.left;
723         src.height = src.visrect.bottom - src.visrect.top;
724
725         err = physdev->funcs->pGetImage( physdev, hbitmap, src_info, &src_bits, &src );
726
727         if(err)
728         {
729             lines = 0;
730             goto done;
731         }
732
733         if (src_info->bmiHeader.biBitCount <= 8 && src_info->bmiHeader.biClrUsed == 0)
734         {
735             if (bmp->dib)
736                 memcpy( src_info->bmiColors, bmp->color_table, bmp->nb_colors * sizeof(RGBQUAD) );
737             else
738                 fill_default_color_table( src_info );
739         }
740
741         if(dst_info->bmiHeader.biHeight > 0)
742             dst_info->bmiHeader.biHeight = lines;
743         else
744             dst_info->bmiHeader.biHeight = -lines;
745
746         convert_bitmapinfo( src_info, src_bits.ptr, &src.visrect, dst_info, bits );
747         if (src_bits.free) src_bits.free( &src_bits );
748     }
749     else lines = abs(height);
750
751     if (coloruse == DIB_PAL_COLORS)
752     {
753         WORD *index = (WORD *)dst_info->bmiColors;
754         for (i = 0; i < colors; i++, index++)
755             *index = i;
756     }
757
758     copy_color_info( info, dst_info, coloruse );
759
760 done:
761     release_dc_ptr( dc );
762     GDI_ReleaseObj( hbitmap );
763     return lines;
764 }
765
766
767 /***********************************************************************
768  *           CreateDIBitmap    (GDI32.@)
769  *
770  * Creates a DDB (device dependent bitmap) from a DIB.
771  * The DDB will have the same color depth as the reference DC.
772  */
773 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
774                             DWORD init, LPCVOID bits, const BITMAPINFO *data,
775                             UINT coloruse )
776 {
777     HBITMAP handle;
778     LONG width;
779     LONG height;
780     WORD planes, bpp;
781     DWORD compr, size;
782
783     if (!header) return 0;
784
785     if (DIB_GetBitmapInfo( header, &width, &height, &planes, &bpp, &compr, &size ) == -1) return 0;
786     
787     if (width < 0)
788     {
789         TRACE("Bitmap has a negative width\n");
790         return 0;
791     }
792     
793     /* Top-down DIBs have a negative height */
794     if (height < 0) height = -height;
795
796     TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
797            hdc, header, init, bits, data, coloruse, width, height, bpp, compr);
798     
799     if (hdc == NULL)
800         handle = CreateBitmap( width, height, 1, 1, NULL );
801     else
802         handle = CreateCompatibleBitmap( hdc, width, height );
803
804     if (handle)
805     {
806         if (init & CBM_INIT)
807         {
808             if (SetDIBits( hdc, handle, 0, height, bits, data, coloruse ) == 0)
809             {
810                 DeleteObject( handle );
811                 handle = 0;
812             }
813         }
814     }
815
816     return handle;
817 }
818
819 /* Copy/synthesize RGB palette from BITMAPINFO. Ripped from dlls/winex11.drv/dib.c */
820 static void DIB_CopyColorTable( DC *dc, BITMAPOBJ *bmp, WORD coloruse, const BITMAPINFO *info )
821 {
822     RGBQUAD *colorTable;
823     unsigned int colors, i;
824     BOOL core_info = info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER);
825
826     if (core_info)
827     {
828         colors = 1 << ((const BITMAPCOREINFO*) info)->bmciHeader.bcBitCount;
829     }
830     else
831     {
832         colors = info->bmiHeader.biClrUsed;
833         if (!colors) colors = 1 << info->bmiHeader.biBitCount;
834     }
835
836     if (colors > 256) {
837         ERR("called with >256 colors!\n");
838         return;
839     }
840
841     if (!(colorTable = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(RGBQUAD) ))) return;
842
843     if(coloruse == DIB_RGB_COLORS)
844     {
845         if (core_info)
846         {
847            /* Convert RGBTRIPLEs to RGBQUADs */
848            for (i=0; i < colors; i++)
849            {
850                colorTable[i].rgbRed   = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtRed;
851                colorTable[i].rgbGreen = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtGreen;
852                colorTable[i].rgbBlue  = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtBlue;
853                colorTable[i].rgbReserved = 0;
854            }
855         }
856         else
857         {
858             memcpy(colorTable, (const BYTE*) info + (WORD) info->bmiHeader.biSize, colors * sizeof(RGBQUAD));
859         }
860     }
861     else
862     {
863         PALETTEENTRY entries[256];
864         const WORD *index = (const WORD*) ((const BYTE*) info + (WORD) info->bmiHeader.biSize);
865         UINT count = GetPaletteEntries( dc->hPalette, 0, colors, entries );
866
867         for (i = 0; i < colors; i++, index++)
868         {
869             PALETTEENTRY *entry = &entries[*index % count];
870             colorTable[i].rgbRed = entry->peRed;
871             colorTable[i].rgbGreen = entry->peGreen;
872             colorTable[i].rgbBlue = entry->peBlue;
873             colorTable[i].rgbReserved = 0;
874         }
875     }
876     bmp->color_table = colorTable;
877     bmp->nb_colors = colors;
878 }
879
880 /***********************************************************************
881  *           CreateDIBSection    (GDI32.@)
882  */
883 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
884                                 VOID **bits, HANDLE section, DWORD offset)
885 {
886     HBITMAP ret = 0;
887     DC *dc;
888     BOOL bDesktopDC = FALSE;
889     DIBSECTION *dib;
890     BITMAPOBJ *bmp;
891     int bitmap_type;
892     LONG width, height;
893     WORD planes, bpp;
894     DWORD compression, sizeImage;
895     void *mapBits = NULL;
896
897     if(!bmi){
898         if(bits) *bits = NULL;
899         return NULL;
900     }
901
902     if (((bitmap_type = DIB_GetBitmapInfo( &bmi->bmiHeader, &width, &height,
903                                            &planes, &bpp, &compression, &sizeImage )) == -1))
904         return 0;
905
906     switch (bpp)
907     {
908     case 16:
909     case 32:
910         if (compression == BI_BITFIELDS) break;
911         /* fall through */
912     case 1:
913     case 4:
914     case 8:
915     case 24:
916         if (compression == BI_RGB) break;
917         /* fall through */
918     default:
919         WARN( "invalid %u bpp compression %u\n", bpp, compression );
920         return 0;
921     }
922
923     if (!(dib = HeapAlloc( GetProcessHeap(), 0, sizeof(*dib) ))) return 0;
924
925     TRACE("format (%d,%d), planes %d, bpp %d, %s, size %d %s\n",
926           width, height, planes, bpp, compression == BI_BITFIELDS? "BI_BITFIELDS" : "BI_RGB",
927           sizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
928
929     dib->dsBm.bmType       = 0;
930     dib->dsBm.bmWidth      = width;
931     dib->dsBm.bmHeight     = height >= 0 ? height : -height;
932     dib->dsBm.bmWidthBytes = get_dib_stride( width, bpp );
933     dib->dsBm.bmPlanes     = planes;
934     dib->dsBm.bmBitsPixel  = bpp;
935     dib->dsBm.bmBits       = NULL;
936
937     if (!bitmap_type)  /* core header */
938     {
939         /* convert the BITMAPCOREHEADER to a BITMAPINFOHEADER */
940         dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
941         dib->dsBmih.biWidth = width;
942         dib->dsBmih.biHeight = height;
943         dib->dsBmih.biPlanes = planes;
944         dib->dsBmih.biBitCount = bpp;
945         dib->dsBmih.biCompression = compression;
946         dib->dsBmih.biXPelsPerMeter = 0;
947         dib->dsBmih.biYPelsPerMeter = 0;
948         dib->dsBmih.biClrUsed = 0;
949         dib->dsBmih.biClrImportant = 0;
950     }
951     else
952     {
953         /* truncate extended bitmap headers (BITMAPV4HEADER etc.) */
954         dib->dsBmih = bmi->bmiHeader;
955         dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
956     }
957
958     /* set number of entries in bmi.bmiColors table */
959     if( bpp <= 8 )
960         dib->dsBmih.biClrUsed = 1 << bpp;
961
962     dib->dsBmih.biSizeImage = dib->dsBm.bmWidthBytes * dib->dsBm.bmHeight;
963
964     /* set dsBitfields values */
965     dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
966
967     if((bpp == 15 || bpp == 16) && compression == BI_RGB)
968     {
969         /* In this case Windows changes biCompression to BI_BITFIELDS,
970            however for now we won't do this, as there are a lot
971            of places where BI_BITFIELDS is currently unsupported. */
972
973         /* dib->dsBmih.biCompression = compression = BI_BITFIELDS;*/
974         dib->dsBitfields[0] = 0x7c00;
975         dib->dsBitfields[1] = 0x03e0;
976         dib->dsBitfields[2] = 0x001f;
977     }
978     else if(compression == BI_BITFIELDS)
979     {
980         dib->dsBitfields[0] =  *(const DWORD *)bmi->bmiColors;
981         dib->dsBitfields[1] =  *((const DWORD *)bmi->bmiColors + 1);
982         dib->dsBitfields[2] =  *((const DWORD *)bmi->bmiColors + 2);
983     }
984
985     /* get storage location for DIB bits */
986
987     if (section)
988     {
989         SYSTEM_INFO SystemInfo;
990         DWORD mapOffset;
991         INT mapSize;
992
993         GetSystemInfo( &SystemInfo );
994         mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
995         mapSize = dib->dsBmih.biSizeImage + (offset - mapOffset);
996         mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
997         if (mapBits) dib->dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
998     }
999     else
1000     {
1001         offset = 0;
1002         dib->dsBm.bmBits = VirtualAlloc( NULL, dib->dsBmih.biSizeImage,
1003                                          MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1004     }
1005     dib->dshSection = section;
1006     dib->dsOffset = offset;
1007
1008     if (!dib->dsBm.bmBits)
1009     {
1010         HeapFree( GetProcessHeap(), 0, dib );
1011         return 0;
1012     }
1013
1014     /* If the reference hdc is null, take the desktop dc */
1015     if (hdc == 0)
1016     {
1017         hdc = CreateCompatibleDC(0);
1018         bDesktopDC = TRUE;
1019     }
1020
1021     if (!(dc = get_dc_ptr( hdc ))) goto error;
1022
1023     /* create Device Dependent Bitmap and add DIB pointer */
1024     ret = CreateBitmap( dib->dsBm.bmWidth, dib->dsBm.bmHeight, 1,
1025                         (bpp == 1) ? 1 : GetDeviceCaps(hdc, BITSPIXEL), NULL );
1026
1027     if (ret && ((bmp = GDI_GetObjPtr(ret, OBJ_BITMAP))))
1028     {
1029         PHYSDEV physdev = GET_DC_PHYSDEV( dc, pCreateDIBSection );
1030         bmp->dib = dib;
1031         bmp->funcs = physdev->funcs;
1032         /* create local copy of DIB palette */
1033         if (bpp <= 8) DIB_CopyColorTable( dc, bmp, usage, bmi );
1034         GDI_ReleaseObj( ret );
1035
1036         if (!physdev->funcs->pCreateDIBSection( physdev, ret, bmi, usage ))
1037         {
1038             DeleteObject( ret );
1039             ret = 0;
1040         }
1041     }
1042
1043     release_dc_ptr( dc );
1044     if (bDesktopDC) DeleteDC( hdc );
1045     if (ret && bits) *bits = dib->dsBm.bmBits;
1046     return ret;
1047
1048 error:
1049     if (bDesktopDC) DeleteDC( hdc );
1050     if (section) UnmapViewOfFile( mapBits );
1051     else if (!offset) VirtualFree( dib->dsBm.bmBits, 0, MEM_RELEASE );
1052     HeapFree( GetProcessHeap(), 0, dib );
1053     return 0;
1054 }