winealsa: Fix AudioRenderClient Get/ReleaseBuffer protocol.
[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
33     
34   * The palettes are stored in different formats:
35
36     - BITMAPCOREINFO: Array of RGBTRIPLE
37     - BITMAPINFO:     Array of RGBQUAD
38
39     
40   * There are even more DIB headers, but they all extend BITMAPINFOHEADER:
41     
42     - BITMAPV4HEADER: Introduced in Windows 95 / NT 4.0
43     - BITMAPV5HEADER: Introduced in Windows 98 / 2000
44     
45     If biCompression is BI_BITFIELDS, the color masks are at the same position
46     in all the headers (they start at bmiColors of BITMAPINFOHEADER), because
47     the new headers have structure members for the masks.
48
49
50   * You should never access the color table using the bmiColors member,
51     because the passed structure may have one of the extended headers
52     mentioned above. Use this to calculate the location:
53     
54     BITMAPINFO* info;
55     void* colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
56
57     
58   * More information:
59     Search for "Bitmap Structures" in MSDN
60 */
61
62 #include <stdarg.h>
63 #include <stdlib.h>
64 #include <string.h>
65 #include <assert.h>
66
67 #include "windef.h"
68 #include "winbase.h"
69 #include "gdi_private.h"
70 #include "wine/debug.h"
71
72 WINE_DEFAULT_DEBUG_CHANNEL(bitmap);
73
74
75 /***********************************************************************
76  *           bitmap_info_size
77  *
78  * Return the size of the bitmap info structure including color table.
79  */
80 int bitmap_info_size( const BITMAPINFO * info, WORD coloruse )
81 {
82     unsigned int colors, size, masks = 0;
83
84     if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
85     {
86         const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
87         colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
88         return sizeof(BITMAPCOREHEADER) + colors *
89              ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
90     }
91     else  /* assume BITMAPINFOHEADER */
92     {
93         if (info->bmiHeader.biClrUsed) colors = min( info->bmiHeader.biClrUsed, 256 );
94         else colors = info->bmiHeader.biBitCount > 8 ? 0 : 1 << info->bmiHeader.biBitCount;
95         if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3;
96         size = max( info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) );
97         return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
98     }
99 }
100
101 /*******************************************************************************************
102  * Verify that the DIB parameters are valid.
103  */
104 static BOOL is_valid_dib_format( const BITMAPINFOHEADER *info, BOOL allow_compression )
105 {
106     if (info->biWidth <= 0) return FALSE;
107     if (info->biHeight == 0) return FALSE;
108
109     if (allow_compression && (info->biCompression == BI_RLE4 || info->biCompression == BI_RLE8))
110     {
111         if (info->biHeight < 0) return FALSE;
112         if (!info->biSizeImage) return FALSE;
113         return info->biBitCount == (info->biCompression == BI_RLE4 ? 4 : 8);
114     }
115
116     if (!info->biPlanes) return FALSE;
117
118     switch (info->biBitCount)
119     {
120     case 1:
121     case 4:
122     case 8:
123     case 24:
124         return (info->biCompression == BI_RGB);
125     case 16:
126     case 32:
127         return (info->biCompression == BI_BITFIELDS || info->biCompression == BI_RGB);
128     default:
129         return FALSE;
130     }
131 }
132
133 /*******************************************************************************************
134  *  Fill out a true BITMAPINFOHEADER from a variable sized BITMAPINFOHEADER / BITMAPCOREHEADER.
135  */
136 static BOOL bitmapinfoheader_from_user_bitmapinfo( BITMAPINFOHEADER *dst, const BITMAPINFOHEADER *info )
137 {
138     if (!info) return FALSE;
139
140     if (info->biSize == sizeof(BITMAPCOREHEADER))
141     {
142         const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
143         dst->biWidth         = core->bcWidth;
144         dst->biHeight        = core->bcHeight;
145         dst->biPlanes        = core->bcPlanes;
146         dst->biBitCount      = core->bcBitCount;
147         dst->biCompression   = BI_RGB;
148         dst->biXPelsPerMeter = 0;
149         dst->biYPelsPerMeter = 0;
150         dst->biClrUsed       = 0;
151         dst->biClrImportant  = 0;
152     }
153     else if (info->biSize >= sizeof(BITMAPINFOHEADER)) /* assume BITMAPINFOHEADER */
154     {
155         *dst = *info;
156     }
157     else
158     {
159         WARN( "(%u): unknown/wrong size for header\n", info->biSize );
160         return FALSE;
161     }
162
163     dst->biSize = sizeof(*dst);
164     if (dst->biCompression == BI_RGB || dst->biCompression == BI_BITFIELDS)
165         dst->biSizeImage = get_dib_image_size( (BITMAPINFO *)dst );
166     return TRUE;
167 }
168
169 /*******************************************************************************************
170  *  Fill out a true BITMAPINFO from a variable sized BITMAPINFO / BITMAPCOREINFO.
171  *
172  * The resulting sanitized BITMAPINFO is guaranteed to have:
173  * - biSize set to sizeof(BITMAPINFOHEADER)
174  * - biSizeImage set to the actual image size even for non-compressed DIB
175  * - biClrUsed set to the size of the color table, and 0 only when there is no color table
176  * - color table present only for <= 8 bpp, always starts at info->bmiColors
177  */
178 static BOOL bitmapinfo_from_user_bitmapinfo( BITMAPINFO *dst, const BITMAPINFO *info,
179                                              UINT coloruse, BOOL allow_compression )
180 {
181     void *src_colors;
182
183     if (coloruse > DIB_PAL_COLORS + 1) return FALSE;  /* FIXME: handle DIB_PAL_COLORS+1 format */
184     if (!bitmapinfoheader_from_user_bitmapinfo( &dst->bmiHeader, &info->bmiHeader )) return FALSE;
185     if (!is_valid_dib_format( &dst->bmiHeader, allow_compression )) return FALSE;
186
187     src_colors = (char *)info + info->bmiHeader.biSize;
188
189     if (dst->bmiHeader.biCompression == BI_BITFIELDS)
190     {
191         /* bitfields are always at bmiColors even in larger structures */
192         memcpy( dst->bmiColors, info->bmiColors, 3 * sizeof(DWORD) );
193         dst->bmiHeader.biClrUsed = 0;
194     }
195     else if (dst->bmiHeader.biBitCount <= 8)
196     {
197         unsigned int colors = dst->bmiHeader.biClrUsed;
198         unsigned int max_colors = 1 << dst->bmiHeader.biBitCount;
199
200         if (!colors) colors = max_colors;
201         else colors = min( colors, max_colors );
202
203         if (coloruse == DIB_PAL_COLORS)
204         {
205             memcpy( dst->bmiColors, src_colors, colors * sizeof(WORD) );
206             max_colors = colors;
207         }
208         else if (info->bmiHeader.biSize != sizeof(BITMAPCOREHEADER))
209         {
210             memcpy( dst->bmiColors, src_colors, colors * sizeof(RGBQUAD) );
211         }
212         else
213         {
214             unsigned int i;
215             RGBTRIPLE *triple = (RGBTRIPLE *)src_colors;
216             for (i = 0; i < colors; i++)
217             {
218                 dst->bmiColors[i].rgbRed      = triple[i].rgbtRed;
219                 dst->bmiColors[i].rgbGreen    = triple[i].rgbtGreen;
220                 dst->bmiColors[i].rgbBlue     = triple[i].rgbtBlue;
221                 dst->bmiColors[i].rgbReserved = 0;
222             }
223         }
224         memset( dst->bmiColors + colors, 0, (max_colors - colors) * sizeof(RGBQUAD) );
225         dst->bmiHeader.biClrUsed = max_colors;
226     }
227     else dst->bmiHeader.biClrUsed = 0;
228
229     return TRUE;
230 }
231
232 static int fill_color_table_from_palette( BITMAPINFO *info, HDC hdc )
233 {
234     PALETTEENTRY palEntry[256];
235     HPALETTE palette = GetCurrentObject( hdc, OBJ_PAL );
236     int i, colors = 1 << info->bmiHeader.biBitCount;
237
238     info->bmiHeader.biClrUsed = colors;
239
240     if (!palette) return 0;
241
242     memset( palEntry, 0, sizeof(palEntry) );
243     if (!GetPaletteEntries( palette, 0, colors, palEntry ))
244         return 0;
245
246     for (i = 0; i < colors; i++)
247     {
248         info->bmiColors[i].rgbRed      = palEntry[i].peRed;
249         info->bmiColors[i].rgbGreen    = palEntry[i].peGreen;
250         info->bmiColors[i].rgbBlue     = palEntry[i].peBlue;
251         info->bmiColors[i].rgbReserved = 0;
252     }
253
254     return colors;
255 }
256
257 BOOL fill_color_table_from_pal_colors( BITMAPINFO *info, HDC hdc )
258 {
259     PALETTEENTRY entries[256];
260     RGBQUAD table[256];
261     HPALETTE palette;
262     const WORD *index = (const WORD *)info->bmiColors;
263     int i, count, colors = info->bmiHeader.biClrUsed;
264
265     if (!colors) return TRUE;
266     if (!(palette = GetCurrentObject( hdc, OBJ_PAL ))) return FALSE;
267     if (!(count = GetPaletteEntries( palette, 0, colors, entries ))) return FALSE;
268
269     for (i = 0; i < colors; i++, index++)
270     {
271         table[i].rgbRed   = entries[*index % count].peRed;
272         table[i].rgbGreen = entries[*index % count].peGreen;
273         table[i].rgbBlue  = entries[*index % count].peBlue;
274         table[i].rgbReserved = 0;
275     }
276     info->bmiHeader.biClrUsed = 1 << info->bmiHeader.biBitCount;
277     memcpy( info->bmiColors, table, colors * sizeof(RGBQUAD) );
278     memset( info->bmiColors + colors, 0, (info->bmiHeader.biClrUsed - colors) * sizeof(RGBQUAD) );
279     return TRUE;
280 }
281
282 static void *get_pixel_ptr( const BITMAPINFO *info, void *bits, int x, int y )
283 {
284     const int width = info->bmiHeader.biWidth, height = info->bmiHeader.biHeight;
285     const int bpp = info->bmiHeader.biBitCount;
286
287     if (height > 0)
288         return (char *)bits + (height - y - 1) * get_dib_stride( width, bpp ) + x * bpp / 8;
289     else
290         return (char *)bits + y * get_dib_stride( width, bpp ) + x * bpp / 8;
291 }
292
293 static BOOL build_rle_bitmap( const BITMAPINFO *info, struct gdi_image_bits *bits, HRGN *clip )
294 {
295     int i = 0;
296     int left, right;
297     int x, y, width = info->bmiHeader.biWidth, height = info->bmiHeader.biHeight;
298     HRGN run = NULL;
299     BYTE skip, num, data;
300     BYTE *out_bits, *in_bits = bits->ptr;
301
302     if (clip) *clip = NULL;
303
304     assert( info->bmiHeader.biBitCount == 4 || info->bmiHeader.biBitCount == 8 );
305
306     out_bits = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, get_dib_image_size( info ) );
307     if (!out_bits) goto fail;
308
309     if (clip)
310     {
311         *clip = CreateRectRgn( 0, 0, 0, 0 );
312         run   = CreateRectRgn( 0, 0, 0, 0 );
313         if (!*clip || !run) goto fail;
314     }
315
316     x = left = right = 0;
317     y = height - 1;
318
319     while (i < info->bmiHeader.biSizeImage - 1)
320     {
321         num = in_bits[i];
322         data = in_bits[i + 1];
323         i += 2;
324
325         if (num)
326         {
327             if (x + num > width) num = width - x;
328             if (num)
329             {
330                 BYTE s = data, *out_ptr = get_pixel_ptr( info, out_bits, x, y );
331                 if (info->bmiHeader.biBitCount == 8)
332                     memset( out_ptr, s, num );
333                 else
334                 {
335                     if(x & 1)
336                     {
337                         s = ((s >> 4) & 0x0f) | ((s << 4) & 0xf0);
338                         *out_ptr = (*out_ptr & 0xf0) | (s & 0x0f);
339                         out_ptr++;
340                         x++;
341                         num--;
342                     }
343                     /* this will write one too many if num is odd, but that doesn't matter */
344                     if (num) memset( out_ptr, s, (num + 1) / 2 );
345                 }
346             }
347             x += num;
348             right = x;
349         }
350         else
351         {
352             if (data < 3)
353             {
354                 if(left != right && clip)
355                 {
356                     SetRectRgn( run, left, y, right, y + 1 );
357                     CombineRgn( *clip, run, *clip, RGN_OR );
358                 }
359                 switch (data)
360                 {
361                 case 0: /* eol */
362                     left = right = x = 0;
363                     y--;
364                     if(y < 0) goto done;
365                     break;
366
367                 case 1: /* eod */
368                     goto done;
369
370                 case 2: /* delta */
371                     if (i >= info->bmiHeader.biSizeImage - 1) goto done;
372                     x += in_bits[i];
373                     if (x > width) x = width;
374                     left = right = x;
375                     y -= in_bits[i + 1];
376                     if(y < 0) goto done;
377                     i += 2;
378                 }
379             }
380             else /* data bytes of data */
381             {
382                 num = data;
383                 skip = (num * info->bmiHeader.biBitCount + 7) / 8;
384                 if (skip > info->bmiHeader.biSizeImage - i) goto done;
385                 skip = (skip + 1) & ~1;
386                 if (x + num > width) num = width - x;
387                 if (num)
388                 {
389                     BYTE *out_ptr = get_pixel_ptr( info, out_bits, x, y );
390                     if (info->bmiHeader.biBitCount == 8)
391                         memcpy( out_ptr, in_bits + i, num );
392                     else
393                     {
394                         if(x & 1)
395                         {
396                             const BYTE *in_ptr = in_bits + i;
397                             for ( ; num; num--, x++)
398                             {
399                                 if (x & 1)
400                                 {
401                                     *out_ptr = (*out_ptr & 0xf0) | ((*in_ptr >> 4) & 0x0f);
402                                     out_ptr++;
403                                 }
404                                 else
405                                     *out_ptr = (*in_ptr++ << 4) & 0xf0;
406                             }
407                         }
408                         else
409                             memcpy( out_ptr, in_bits + i, (num + 1) / 2);
410                     }
411                 }
412                 x += num;
413                 right = x;
414                 i += skip;
415             }
416         }
417     }
418
419 done:
420     if (run) DeleteObject( run );
421     if (bits->free) bits->free( bits );
422
423     bits->ptr     = out_bits;
424     bits->is_copy = TRUE;
425     bits->free    = free_heap_bits;
426
427     return TRUE;
428
429 fail:
430     if (run) DeleteObject( run );
431     if (clip && *clip) DeleteObject( *clip );
432     HeapFree( GetProcessHeap(), 0, out_bits );
433     return FALSE;
434 }
435
436
437
438 INT nulldrv_StretchDIBits( PHYSDEV dev, INT xDst, INT yDst, INT widthDst, INT heightDst,
439                            INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
440                            BITMAPINFO *src_info, UINT coloruse, DWORD rop )
441 {
442     DC *dc = get_nulldrv_dc( dev );
443     char dst_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
444     BITMAPINFO *dst_info = (BITMAPINFO *)dst_buffer;
445     struct bitblt_coords src, dst;
446     struct gdi_image_bits src_bits;
447     DWORD err;
448     HRGN clip = NULL;
449     INT ret = 0;
450     INT height = abs( src_info->bmiHeader.biHeight );
451     BOOL top_down = src_info->bmiHeader.biHeight < 0, non_stretch_from_origin = FALSE;
452     RECT rect;
453
454     TRACE("%d %d %d %d <- %d %d %d %d rop %08x\n", xDst, yDst, widthDst, heightDst,
455           xSrc, ySrc, widthSrc, heightSrc, rop);
456
457     src_bits.ptr = (void*)bits;
458     src_bits.is_copy = FALSE;
459     src_bits.free = NULL;
460
461     if (coloruse == DIB_PAL_COLORS && !fill_color_table_from_pal_colors( src_info, dev->hdc )) return 0;
462
463     rect.left   = xDst;
464     rect.top    = yDst;
465     rect.right  = xDst + widthDst;
466     rect.bottom = yDst + heightDst;
467     LPtoDP( dc->hSelf, (POINT *)&rect, 2 );
468     dst.x      = rect.left;
469     dst.y      = rect.top;
470     dst.width  = rect.right - rect.left;
471     dst.height = rect.bottom - rect.top;
472
473     if (dc->layout & LAYOUT_RTL && rop & NOMIRRORBITMAP)
474     {
475         dst.x += dst.width;
476         dst.width = -dst.width;
477     }
478     rop &= ~NOMIRRORBITMAP;
479
480     src.x      = xSrc;
481     src.width  = widthSrc;
482     src.y      = ySrc;
483     src.height = heightSrc;
484
485     if (src.x == 0 && src.y == 0 && src.width == dst.width && src.height == dst.height)
486         non_stretch_from_origin = TRUE;
487
488     if (src_info->bmiHeader.biCompression == BI_RLE4 || src_info->bmiHeader.biCompression == BI_RLE8)
489     {
490         BOOL want_clip = non_stretch_from_origin && (rop == SRCCOPY);
491         if (!build_rle_bitmap( src_info, &src_bits, want_clip ? &clip : NULL )) return 0;
492     }
493
494     if (rop != SRCCOPY || non_stretch_from_origin)
495     {
496         if (dst.width == 1 && src.width > 1) src.width--;
497         if (dst.height == 1 && src.height > 1) src.height--;
498     }
499
500     if (rop != SRCCOPY)
501     {
502         if (dst.width < 0 && dst.width == src.width)
503         {
504             /* This is off-by-one, but that's what Windows does */
505             dst.x += dst.width;
506             src.x += src.width;
507             dst.width = -dst.width;
508             src.width = -src.width;
509         }
510         if (dst.height < 0 && dst.height == src.height)
511         {
512             dst.y += dst.height;
513             src.y += src.height;
514             dst.height = -dst.height;
515             src.height = -src.height;
516         }
517     }
518
519     if (!top_down || (rop == SRCCOPY && !non_stretch_from_origin)) src.y = height - src.y - src.height;
520
521     if (src.y >= height && src.y + src.height + 1 < height)
522         src.y = height - 1;
523     else if (src.y > 0 && src.y + src.height + 1 < 0)
524         src.y = -src.height - 1;
525
526     get_bounding_rect( &rect, src.x, src.y, src.width, src.height );
527
528     src.visrect.left   = 0;
529     src.visrect.right  = src_info->bmiHeader.biWidth;
530     src.visrect.top    = 0;
531     src.visrect.bottom = height;
532     if (!intersect_rect( &src.visrect, &src.visrect, &rect )) goto done;
533
534     get_bounding_rect( &rect, dst.x, dst.y, dst.width, dst.height );
535
536     if (!clip_visrect( dc, &dst.visrect, &rect )) goto done;
537
538     if (!intersect_vis_rectangles( &dst, &src )) goto done;
539
540     if (clip) OffsetRgn( clip, dst.x - src.x, dst.y - src.y );
541
542     dev = GET_DC_PHYSDEV( dc, pPutImage );
543     copy_bitmapinfo( dst_info, src_info );
544     err = dev->funcs->pPutImage( dev, 0, clip, dst_info, &src_bits, &src, &dst, rop );
545     if (err == ERROR_BAD_FORMAT)
546     {
547         /* 1-bpp destination without a color table requires a fake 1-entry table
548          * that contains only the background color */
549         if (dst_info->bmiHeader.biBitCount == 1 && !dst_info->bmiHeader.biClrUsed)
550         {
551             COLORREF color = GetBkColor( dev->hdc );
552             dst_info->bmiColors[0].rgbRed      = GetRValue( color );
553             dst_info->bmiColors[0].rgbGreen    = GetGValue( color );
554             dst_info->bmiColors[0].rgbBlue     = GetBValue( color );
555             dst_info->bmiColors[0].rgbReserved = 0;
556             dst_info->bmiHeader.biClrUsed = 1;
557         }
558
559         if (!(err = convert_bits( src_info, &src, dst_info, &src_bits, FALSE )))
560         {
561             /* get rid of the fake 1-bpp table */
562             if (dst_info->bmiHeader.biClrUsed == 1) dst_info->bmiHeader.biClrUsed = 0;
563             err = dev->funcs->pPutImage( dev, 0, clip, dst_info, &src_bits, &src, &dst, rop );
564         }
565     }
566
567     if (err == ERROR_TRANSFORM_NOT_SUPPORTED)
568     {
569         copy_bitmapinfo( src_info, dst_info );
570         err = stretch_bits( src_info, &src, dst_info, &dst, &src_bits, GetStretchBltMode( dev->hdc ) );
571         if (!err) err = dev->funcs->pPutImage( dev, 0, NULL, dst_info, &src_bits, &src, &dst, rop );
572     }
573     if (err) ret = 0;
574     else if (rop == SRCCOPY) ret = height;
575     else ret = src_info->bmiHeader.biHeight;
576
577 done:
578     if (src_bits.free) src_bits.free( &src_bits );
579     if (clip) DeleteObject( clip );
580     return ret;
581 }
582
583 /***********************************************************************
584  *           StretchDIBits   (GDI32.@)
585  */
586 INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst, INT heightDst,
587                          INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
588                          const BITMAPINFO *bmi, UINT coloruse, DWORD rop )
589 {
590     char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
591     BITMAPINFO *info = (BITMAPINFO *)buffer;
592     DC *dc;
593     INT ret = 0;
594
595     if (!bits) return 0;
596     if (!bitmapinfo_from_user_bitmapinfo( info, bmi, coloruse, TRUE ))
597     {
598         SetLastError( ERROR_INVALID_PARAMETER );
599         return 0;
600     }
601
602     if ((dc = get_dc_ptr( hdc )))
603     {
604         PHYSDEV physdev = GET_DC_PHYSDEV( dc, pStretchDIBits );
605         update_dc( dc );
606         ret = physdev->funcs->pStretchDIBits( physdev, xDst, yDst, widthDst, heightDst,
607                                               xSrc, ySrc, widthSrc, heightSrc, bits, info, coloruse, rop );
608         release_dc_ptr( dc );
609     }
610     return ret;
611 }
612
613
614 /******************************************************************************
615  * SetDIBits [GDI32.@]
616  *
617  * Sets pixels in a bitmap using colors from DIB.
618  *
619  * PARAMS
620  *    hdc       [I] Handle to device context
621  *    hbitmap   [I] Handle to bitmap
622  *    startscan [I] Starting scan line
623  *    lines     [I] Number of scan lines
624  *    bits      [I] Array of bitmap bits
625  *    info      [I] Address of structure with data
626  *    coloruse  [I] Type of color indexes to use
627  *
628  * RETURNS
629  *    Success: Number of scan lines copied
630  *    Failure: 0
631  */
632 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
633                       UINT lines, LPCVOID bits, const BITMAPINFO *info,
634                       UINT coloruse )
635 {
636     BITMAPOBJ *bitmap;
637     char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
638     BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
639     char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
640     BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf;
641     INT result = 0;
642     DWORD err;
643     struct gdi_image_bits src_bits;
644     struct bitblt_coords src, dst;
645     INT src_to_dst_offset;
646     HRGN clip = 0;
647     const struct gdi_dc_funcs *funcs;
648
649     if (!bitmapinfo_from_user_bitmapinfo( src_info, info, coloruse, TRUE ) || coloruse > DIB_PAL_COLORS)
650     {
651         SetLastError( ERROR_INVALID_PARAMETER );
652         return 0;
653     }
654     if (src_info->bmiHeader.biCompression == BI_BITFIELDS)
655     {
656         DWORD *masks = (DWORD *)src_info->bmiColors;
657         if (!masks[0] || !masks[1] || !masks[2])
658         {
659             SetLastError( ERROR_INVALID_PARAMETER );
660             return 0;
661         }
662     }
663
664     src_bits.ptr = (void *)bits;
665     src_bits.is_copy = FALSE;
666     src_bits.free = NULL;
667     src_bits.param = NULL;
668
669     if (coloruse == DIB_PAL_COLORS && !fill_color_table_from_pal_colors( src_info, hdc )) return 0;
670
671     if (!(bitmap = GDI_GetObjPtr( hbitmap, OBJ_BITMAP ))) return 0;
672
673     if (src_info->bmiHeader.biCompression == BI_RLE4 || src_info->bmiHeader.biCompression == BI_RLE8)
674     {
675         if (lines == 0) goto done;
676         else lines = src_info->bmiHeader.biHeight;
677         startscan = 0;
678
679         if (!build_rle_bitmap( src_info, &src_bits, &clip )) goto done;
680     }
681
682     dst.visrect.left   = 0;
683     dst.visrect.top    = 0;
684     dst.visrect.right  = bitmap->bitmap.bmWidth;
685     dst.visrect.bottom = bitmap->bitmap.bmHeight;
686
687     src.visrect.left   = 0;
688     src.visrect.top    = 0;
689     src.visrect.right  = src_info->bmiHeader.biWidth;
690     src.visrect.bottom = abs( src_info->bmiHeader.biHeight );
691
692     if (src_info->bmiHeader.biHeight > 0)
693     {
694         src_to_dst_offset = -startscan;
695         lines = min( lines, src.visrect.bottom - startscan );
696         if (lines < src.visrect.bottom) src.visrect.top = src.visrect.bottom - lines;
697     }
698     else
699     {
700         src_to_dst_offset = src.visrect.bottom - lines - startscan;
701         /* Unlike the bottom-up case, Windows doesn't limit lines. */
702         if (lines < src.visrect.bottom) src.visrect.bottom = lines;
703     }
704
705     funcs = get_bitmap_funcs( bitmap );
706
707     result = lines;
708
709     offset_rect( &src.visrect, 0, src_to_dst_offset );
710     if (!intersect_rect( &dst.visrect, &src.visrect, &dst.visrect )) goto done;
711     src.visrect = dst.visrect;
712     offset_rect( &src.visrect, 0, -src_to_dst_offset );
713
714     src.x      = src.visrect.left;
715     src.y      = src.visrect.top;
716     src.width  = src.visrect.right - src.visrect.left;
717     src.height = src.visrect.bottom - src.visrect.top;
718
719     dst.x      = dst.visrect.left;
720     dst.y      = dst.visrect.top;
721     dst.width  = dst.visrect.right - dst.visrect.left;
722     dst.height = dst.visrect.bottom - dst.visrect.top;
723
724     copy_bitmapinfo( dst_info, src_info );
725
726     err = funcs->pPutImage( NULL, hbitmap, clip, dst_info, &src_bits, &src, &dst, 0 );
727     if (err == ERROR_BAD_FORMAT)
728     {
729         err = convert_bits( src_info, &src, dst_info, &src_bits, FALSE );
730         if (!err) err = funcs->pPutImage( NULL, hbitmap, clip, dst_info, &src_bits, &src, &dst, 0 );
731     }
732     if(err) result = 0;
733
734 done:
735     if (src_bits.free) src_bits.free( &src_bits );
736     if (clip) DeleteObject( clip );
737     GDI_ReleaseObj( hbitmap );
738     return result;
739 }
740
741
742 INT nulldrv_SetDIBitsToDevice( PHYSDEV dev, INT x_dst, INT y_dst, DWORD cx, DWORD cy,
743                                INT x_src, INT y_src, UINT startscan, UINT lines,
744                                const void *bits, BITMAPINFO *src_info, UINT coloruse )
745 {
746     DC *dc = get_nulldrv_dc( dev );
747     char dst_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
748     BITMAPINFO *dst_info = (BITMAPINFO *)dst_buffer;
749     struct bitblt_coords src, dst;
750     struct gdi_image_bits src_bits;
751     HRGN clip = 0;
752     DWORD err;
753     UINT height;
754     BOOL top_down;
755     POINT pt;
756     RECT rect;
757
758     top_down = (src_info->bmiHeader.biHeight < 0);
759     height = abs( src_info->bmiHeader.biHeight );
760
761     src_bits.ptr = (void *)bits;
762     src_bits.is_copy = FALSE;
763     src_bits.free = NULL;
764
765     if (!lines) return 0;
766     if (coloruse == DIB_PAL_COLORS && !fill_color_table_from_pal_colors( src_info, dev->hdc )) return 0;
767
768     if (src_info->bmiHeader.biCompression == BI_RLE4 || src_info->bmiHeader.biCompression == BI_RLE8)
769     {
770         startscan = 0;
771         lines = height;
772         src_info->bmiHeader.biWidth = x_src + cx;
773         src_info->bmiHeader.biHeight = y_src + cy;
774         if (src_info->bmiHeader.biWidth <= 0 || src_info->bmiHeader.biHeight <= 0) return 0;
775         src.x = x_src;
776         src.y = 0;
777         src.width = cx;
778         src.height = cy;
779         if (!build_rle_bitmap( src_info, &src_bits, &clip )) return 0;
780     }
781     else
782     {
783         if (startscan >= height) return 0;
784         if (!top_down && lines > height - startscan) lines = height - startscan;
785
786         /* map src to top-down coordinates with startscan as origin */
787         src.x = x_src;
788         src.y = startscan + lines - (y_src + cy);
789         src.width = cx;
790         src.height = cy;
791         if (src.y > 0)
792         {
793             if (!top_down)
794             {
795                 /* get rid of unnecessary lines */
796                 if (src.y >= lines) return 0;
797                 lines -= src.y;
798                 src.y = 0;
799             }
800             else if (src.y >= lines) return lines;
801         }
802         src_info->bmiHeader.biHeight = top_down ? -lines : lines;
803     }
804
805     src.visrect.left = src.x;
806     src.visrect.top = src.y;
807     src.visrect.right = src.x + cx;
808     src.visrect.bottom = src.y + cy;
809     rect.left = 0;
810     rect.top = 0;
811     rect.right = src_info->bmiHeader.biWidth;
812     rect.bottom = abs( src_info->bmiHeader.biHeight );
813     if (!intersect_rect( &src.visrect, &src.visrect, &rect ))
814     {
815         lines = 0;
816         goto done;
817     }
818
819     pt.x = x_dst;
820     pt.y = y_dst;
821     LPtoDP( dev->hdc, &pt, 1 );
822     dst.x = pt.x;
823     dst.y = pt.y;
824     dst.width = cx;
825     dst.height = cy;
826     if (GetLayout( dev->hdc ) & LAYOUT_RTL) dst.x -= cx - 1;
827
828     rect.left = dst.x;
829     rect.top = dst.y;
830     rect.right = dst.x + cx;
831     rect.bottom = dst.y + cy;
832     if (!clip_visrect( dc, &dst.visrect, &rect )) goto done;
833
834     offset_rect( &src.visrect, dst.x - src.x, dst.y - src.y );
835     intersect_rect( &rect, &src.visrect, &dst.visrect );
836     src.visrect = dst.visrect = rect;
837     offset_rect( &src.visrect, src.x - dst.x, src.y - dst.y );
838     if (is_rect_empty( &dst.visrect )) goto done;
839     if (clip) OffsetRgn( clip, dst.x - src.x, dst.y - src.y );
840
841     dev = GET_DC_PHYSDEV( dc, pPutImage );
842     copy_bitmapinfo( dst_info, src_info );
843     err = dev->funcs->pPutImage( dev, 0, clip, dst_info, &src_bits, &src, &dst, SRCCOPY );
844     if (err == ERROR_BAD_FORMAT)
845     {
846         err = convert_bits( src_info, &src, dst_info, &src_bits, FALSE );
847         if (!err) err = dev->funcs->pPutImage( dev, 0, clip, dst_info, &src_bits, &src, &dst, SRCCOPY );
848     }
849     if (err) lines = 0;
850
851 done:
852     if (src_bits.free) src_bits.free( &src_bits );
853     if (clip) DeleteObject( clip );
854     return lines;
855 }
856
857 /***********************************************************************
858  *           SetDIBitsToDevice   (GDI32.@)
859  */
860 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
861                            DWORD cy, INT xSrc, INT ySrc, UINT startscan,
862                            UINT lines, LPCVOID bits, const BITMAPINFO *bmi,
863                            UINT coloruse )
864 {
865     char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
866     BITMAPINFO *info = (BITMAPINFO *)buffer;
867     INT ret = 0;
868     DC *dc;
869
870     if (!bits) return 0;
871     if (!bitmapinfo_from_user_bitmapinfo( info, bmi, coloruse, TRUE ))
872     {
873         SetLastError( ERROR_INVALID_PARAMETER );
874         return 0;
875     }
876
877     if ((dc = get_dc_ptr( hdc )))
878     {
879         PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBitsToDevice );
880         update_dc( dc );
881         ret = physdev->funcs->pSetDIBitsToDevice( physdev, xDest, yDest, cx, cy, xSrc,
882                                                   ySrc, startscan, lines, bits, info, coloruse );
883         release_dc_ptr( dc );
884     }
885     return ret;
886 }
887
888 /***********************************************************************
889  *           SetDIBColorTable    (GDI32.@)
890  */
891 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUAD *colors )
892 {
893     DC * dc;
894     UINT result = 0;
895     BITMAPOBJ * bitmap;
896
897     if (!(dc = get_dc_ptr( hdc ))) return 0;
898
899     if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
900     {
901         /* Check if currently selected bitmap is a DIB */
902         if (bitmap->color_table)
903         {
904             if (startpos < bitmap->dib->dsBmih.biClrUsed)
905             {
906                 result = min( entries, bitmap->dib->dsBmih.biClrUsed - startpos );
907                 memcpy(bitmap->color_table + startpos, colors, result * sizeof(RGBQUAD));
908             }
909         }
910         GDI_ReleaseObj( dc->hBitmap );
911
912         if (result)  /* update colors of selected objects */
913         {
914             SetTextColor( hdc, dc->textColor );
915             SetBkColor( hdc, dc->backgroundColor );
916             SelectObject( hdc, dc->hPen );
917             SelectObject( hdc, dc->hBrush );
918         }
919     }
920     release_dc_ptr( dc );
921     return result;
922 }
923
924
925 /***********************************************************************
926  *           GetDIBColorTable    (GDI32.@)
927  */
928 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
929 {
930     DC * dc;
931     BITMAPOBJ *bitmap;
932     UINT result = 0;
933
934     if (!(dc = get_dc_ptr( hdc ))) return 0;
935
936     if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
937     {
938         /* Check if currently selected bitmap is a DIB */
939         if (bitmap->color_table)
940         {
941             if (startpos < bitmap->dib->dsBmih.biClrUsed)
942             {
943                 result = min( entries, bitmap->dib->dsBmih.biClrUsed - startpos );
944                 memcpy(colors, bitmap->color_table + startpos, result * sizeof(RGBQUAD));
945             }
946         }
947         GDI_ReleaseObj( dc->hBitmap );
948     }
949     release_dc_ptr( dc );
950     return result;
951 }
952
953 static const DWORD bit_fields_888[3] = {0xff0000, 0x00ff00, 0x0000ff};
954 static const DWORD bit_fields_565[3] = {0xf800, 0x07e0, 0x001f};
955 static const DWORD bit_fields_555[3] = {0x7c00, 0x03e0, 0x001f};
956
957 static int fill_query_info( BITMAPINFO *info, BITMAPOBJ *bmp )
958 {
959     BITMAPINFOHEADER header;
960
961     header.biSize   = info->bmiHeader.biSize; /* Ensure we don't overwrite the original size when we copy back */
962     header.biWidth  = bmp->bitmap.bmWidth;
963     header.biHeight = bmp->bitmap.bmHeight;
964     header.biPlanes = 1;
965
966     if (bmp->dib)
967     {
968         header.biBitCount = bmp->dib->dsBm.bmBitsPixel;
969         switch (bmp->dib->dsBm.bmBitsPixel)
970         {
971         case 16:
972         case 32:
973             header.biCompression = BI_BITFIELDS;
974             break;
975         default:
976             header.biCompression = BI_RGB;
977             break;
978         }
979     }
980     else
981     {
982         header.biCompression = (bmp->bitmap.bmBitsPixel > 8) ? BI_BITFIELDS : BI_RGB;
983         header.biBitCount = bmp->bitmap.bmBitsPixel;
984     }
985
986     header.biSizeImage = get_dib_image_size( (BITMAPINFO *)&header );
987     header.biXPelsPerMeter = 0;
988     header.biYPelsPerMeter = 0;
989     header.biClrUsed       = 0;
990     header.biClrImportant  = 0;
991
992     if ( info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER) )
993     {
994         BITMAPCOREHEADER *coreheader = (BITMAPCOREHEADER *)info;
995
996         coreheader->bcWidth    = header.biWidth;
997         coreheader->bcHeight   = header.biHeight;
998         coreheader->bcPlanes   = header.biPlanes;
999         coreheader->bcBitCount = header.biBitCount;
1000     }
1001     else
1002         info->bmiHeader = header;
1003
1004     return abs(bmp->bitmap.bmHeight);
1005 }
1006
1007 /************************************************************************
1008  *      copy_color_info
1009  *
1010  * Copy BITMAPINFO color information where dst may be a BITMAPCOREINFO.
1011  */
1012 static void copy_color_info(BITMAPINFO *dst, const BITMAPINFO *src, UINT coloruse)
1013 {
1014     assert( src->bmiHeader.biSize == sizeof(BITMAPINFOHEADER) );
1015
1016     if (dst->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1017     {
1018         BITMAPCOREINFO *core = (BITMAPCOREINFO *)dst;
1019         if (coloruse == DIB_PAL_COLORS)
1020             memcpy( core->bmciColors, src->bmiColors, src->bmiHeader.biClrUsed * sizeof(WORD) );
1021         else
1022         {
1023             unsigned int i;
1024             for (i = 0; i < src->bmiHeader.biClrUsed; i++)
1025             {
1026                 core->bmciColors[i].rgbtRed   = src->bmiColors[i].rgbRed;
1027                 core->bmciColors[i].rgbtGreen = src->bmiColors[i].rgbGreen;
1028                 core->bmciColors[i].rgbtBlue  = src->bmiColors[i].rgbBlue;
1029             }
1030         }
1031     }
1032     else
1033     {
1034         dst->bmiHeader.biClrUsed   = src->bmiHeader.biClrUsed;
1035         dst->bmiHeader.biSizeImage = src->bmiHeader.biSizeImage;
1036
1037         if (src->bmiHeader.biCompression == BI_BITFIELDS)
1038             /* bitfields are always at bmiColors even in larger structures */
1039             memcpy( dst->bmiColors, src->bmiColors, 3 * sizeof(DWORD) );
1040         else if (src->bmiHeader.biClrUsed)
1041         {
1042             void *colorptr = (char *)dst + dst->bmiHeader.biSize;
1043             unsigned int size;
1044
1045             if (coloruse == DIB_PAL_COLORS)
1046                 size = src->bmiHeader.biClrUsed * sizeof(WORD);
1047             else
1048                 size = src->bmiHeader.biClrUsed * sizeof(RGBQUAD);
1049             memcpy( colorptr, src->bmiColors, size );
1050         }
1051     }
1052 }
1053
1054 const RGBQUAD *get_default_color_table( int bpp )
1055 {
1056     static const RGBQUAD table_1[2] =
1057     {
1058         { 0x00, 0x00, 0x00 }, { 0xff, 0xff, 0xff }
1059     };
1060     static const RGBQUAD table_4[16] =
1061     {
1062         { 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x80 }, { 0x00, 0x80, 0x00 }, { 0x00, 0x80, 0x80 },
1063         { 0x80, 0x00, 0x00 }, { 0x80, 0x00, 0x80 }, { 0x80, 0x80, 0x00 }, { 0x80, 0x80, 0x80 },
1064         { 0xc0, 0xc0, 0xc0 }, { 0x00, 0x00, 0xff }, { 0x00, 0xff, 0x00 }, { 0x00, 0xff, 0xff },
1065         { 0xff, 0x00, 0x00 }, { 0xff, 0x00, 0xff }, { 0xff, 0xff, 0x00 }, { 0xff, 0xff, 0xff },
1066     };
1067     static const RGBQUAD table_8[256] =
1068     {
1069         /* first and last 10 entries are the default system palette entries */
1070         { 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x80 }, { 0x00, 0x80, 0x00 }, { 0x00, 0x80, 0x80 },
1071         { 0x80, 0x00, 0x00 }, { 0x80, 0x00, 0x80 }, { 0x80, 0x80, 0x00 }, { 0xc0, 0xc0, 0xc0 },
1072         { 0xc0, 0xdc, 0xc0 }, { 0xf0, 0xca, 0xa6 }, { 0x00, 0x20, 0x40 }, { 0x00, 0x20, 0x60 },
1073         { 0x00, 0x20, 0x80 }, { 0x00, 0x20, 0xa0 }, { 0x00, 0x20, 0xc0 }, { 0x00, 0x20, 0xe0 },
1074         { 0x00, 0x40, 0x00 }, { 0x00, 0x40, 0x20 }, { 0x00, 0x40, 0x40 }, { 0x00, 0x40, 0x60 },
1075         { 0x00, 0x40, 0x80 }, { 0x00, 0x40, 0xa0 }, { 0x00, 0x40, 0xc0 }, { 0x00, 0x40, 0xe0 },
1076         { 0x00, 0x60, 0x00 }, { 0x00, 0x60, 0x20 }, { 0x00, 0x60, 0x40 }, { 0x00, 0x60, 0x60 },
1077         { 0x00, 0x60, 0x80 }, { 0x00, 0x60, 0xa0 }, { 0x00, 0x60, 0xc0 }, { 0x00, 0x60, 0xe0 },
1078         { 0x00, 0x80, 0x00 }, { 0x00, 0x80, 0x20 }, { 0x00, 0x80, 0x40 }, { 0x00, 0x80, 0x60 },
1079         { 0x00, 0x80, 0x80 }, { 0x00, 0x80, 0xa0 }, { 0x00, 0x80, 0xc0 }, { 0x00, 0x80, 0xe0 },
1080         { 0x00, 0xa0, 0x00 }, { 0x00, 0xa0, 0x20 }, { 0x00, 0xa0, 0x40 }, { 0x00, 0xa0, 0x60 },
1081         { 0x00, 0xa0, 0x80 }, { 0x00, 0xa0, 0xa0 }, { 0x00, 0xa0, 0xc0 }, { 0x00, 0xa0, 0xe0 },
1082         { 0x00, 0xc0, 0x00 }, { 0x00, 0xc0, 0x20 }, { 0x00, 0xc0, 0x40 }, { 0x00, 0xc0, 0x60 },
1083         { 0x00, 0xc0, 0x80 }, { 0x00, 0xc0, 0xa0 }, { 0x00, 0xc0, 0xc0 }, { 0x00, 0xc0, 0xe0 },
1084         { 0x00, 0xe0, 0x00 }, { 0x00, 0xe0, 0x20 }, { 0x00, 0xe0, 0x40 }, { 0x00, 0xe0, 0x60 },
1085         { 0x00, 0xe0, 0x80 }, { 0x00, 0xe0, 0xa0 }, { 0x00, 0xe0, 0xc0 }, { 0x00, 0xe0, 0xe0 },
1086         { 0x40, 0x00, 0x00 }, { 0x40, 0x00, 0x20 }, { 0x40, 0x00, 0x40 }, { 0x40, 0x00, 0x60 },
1087         { 0x40, 0x00, 0x80 }, { 0x40, 0x00, 0xa0 }, { 0x40, 0x00, 0xc0 }, { 0x40, 0x00, 0xe0 },
1088         { 0x40, 0x20, 0x00 }, { 0x40, 0x20, 0x20 }, { 0x40, 0x20, 0x40 }, { 0x40, 0x20, 0x60 },
1089         { 0x40, 0x20, 0x80 }, { 0x40, 0x20, 0xa0 }, { 0x40, 0x20, 0xc0 }, { 0x40, 0x20, 0xe0 },
1090         { 0x40, 0x40, 0x00 }, { 0x40, 0x40, 0x20 }, { 0x40, 0x40, 0x40 }, { 0x40, 0x40, 0x60 },
1091         { 0x40, 0x40, 0x80 }, { 0x40, 0x40, 0xa0 }, { 0x40, 0x40, 0xc0 }, { 0x40, 0x40, 0xe0 },
1092         { 0x40, 0x60, 0x00 }, { 0x40, 0x60, 0x20 }, { 0x40, 0x60, 0x40 }, { 0x40, 0x60, 0x60 },
1093         { 0x40, 0x60, 0x80 }, { 0x40, 0x60, 0xa0 }, { 0x40, 0x60, 0xc0 }, { 0x40, 0x60, 0xe0 },
1094         { 0x40, 0x80, 0x00 }, { 0x40, 0x80, 0x20 }, { 0x40, 0x80, 0x40 }, { 0x40, 0x80, 0x60 },
1095         { 0x40, 0x80, 0x80 }, { 0x40, 0x80, 0xa0 }, { 0x40, 0x80, 0xc0 }, { 0x40, 0x80, 0xe0 },
1096         { 0x40, 0xa0, 0x00 }, { 0x40, 0xa0, 0x20 }, { 0x40, 0xa0, 0x40 }, { 0x40, 0xa0, 0x60 },
1097         { 0x40, 0xa0, 0x80 }, { 0x40, 0xa0, 0xa0 }, { 0x40, 0xa0, 0xc0 }, { 0x40, 0xa0, 0xe0 },
1098         { 0x40, 0xc0, 0x00 }, { 0x40, 0xc0, 0x20 }, { 0x40, 0xc0, 0x40 }, { 0x40, 0xc0, 0x60 },
1099         { 0x40, 0xc0, 0x80 }, { 0x40, 0xc0, 0xa0 }, { 0x40, 0xc0, 0xc0 }, { 0x40, 0xc0, 0xe0 },
1100         { 0x40, 0xe0, 0x00 }, { 0x40, 0xe0, 0x20 }, { 0x40, 0xe0, 0x40 }, { 0x40, 0xe0, 0x60 },
1101         { 0x40, 0xe0, 0x80 }, { 0x40, 0xe0, 0xa0 }, { 0x40, 0xe0, 0xc0 }, { 0x40, 0xe0, 0xe0 },
1102         { 0x80, 0x00, 0x00 }, { 0x80, 0x00, 0x20 }, { 0x80, 0x00, 0x40 }, { 0x80, 0x00, 0x60 },
1103         { 0x80, 0x00, 0x80 }, { 0x80, 0x00, 0xa0 }, { 0x80, 0x00, 0xc0 }, { 0x80, 0x00, 0xe0 },
1104         { 0x80, 0x20, 0x00 }, { 0x80, 0x20, 0x20 }, { 0x80, 0x20, 0x40 }, { 0x80, 0x20, 0x60 },
1105         { 0x80, 0x20, 0x80 }, { 0x80, 0x20, 0xa0 }, { 0x80, 0x20, 0xc0 }, { 0x80, 0x20, 0xe0 },
1106         { 0x80, 0x40, 0x00 }, { 0x80, 0x40, 0x20 }, { 0x80, 0x40, 0x40 }, { 0x80, 0x40, 0x60 },
1107         { 0x80, 0x40, 0x80 }, { 0x80, 0x40, 0xa0 }, { 0x80, 0x40, 0xc0 }, { 0x80, 0x40, 0xe0 },
1108         { 0x80, 0x60, 0x00 }, { 0x80, 0x60, 0x20 }, { 0x80, 0x60, 0x40 }, { 0x80, 0x60, 0x60 },
1109         { 0x80, 0x60, 0x80 }, { 0x80, 0x60, 0xa0 }, { 0x80, 0x60, 0xc0 }, { 0x80, 0x60, 0xe0 },
1110         { 0x80, 0x80, 0x00 }, { 0x80, 0x80, 0x20 }, { 0x80, 0x80, 0x40 }, { 0x80, 0x80, 0x60 },
1111         { 0x80, 0x80, 0x80 }, { 0x80, 0x80, 0xa0 }, { 0x80, 0x80, 0xc0 }, { 0x80, 0x80, 0xe0 },
1112         { 0x80, 0xa0, 0x00 }, { 0x80, 0xa0, 0x20 }, { 0x80, 0xa0, 0x40 }, { 0x80, 0xa0, 0x60 },
1113         { 0x80, 0xa0, 0x80 }, { 0x80, 0xa0, 0xa0 }, { 0x80, 0xa0, 0xc0 }, { 0x80, 0xa0, 0xe0 },
1114         { 0x80, 0xc0, 0x00 }, { 0x80, 0xc0, 0x20 }, { 0x80, 0xc0, 0x40 }, { 0x80, 0xc0, 0x60 },
1115         { 0x80, 0xc0, 0x80 }, { 0x80, 0xc0, 0xa0 }, { 0x80, 0xc0, 0xc0 }, { 0x80, 0xc0, 0xe0 },
1116         { 0x80, 0xe0, 0x00 }, { 0x80, 0xe0, 0x20 }, { 0x80, 0xe0, 0x40 }, { 0x80, 0xe0, 0x60 },
1117         { 0x80, 0xe0, 0x80 }, { 0x80, 0xe0, 0xa0 }, { 0x80, 0xe0, 0xc0 }, { 0x80, 0xe0, 0xe0 },
1118         { 0xc0, 0x00, 0x00 }, { 0xc0, 0x00, 0x20 }, { 0xc0, 0x00, 0x40 }, { 0xc0, 0x00, 0x60 },
1119         { 0xc0, 0x00, 0x80 }, { 0xc0, 0x00, 0xa0 }, { 0xc0, 0x00, 0xc0 }, { 0xc0, 0x00, 0xe0 },
1120         { 0xc0, 0x20, 0x00 }, { 0xc0, 0x20, 0x20 }, { 0xc0, 0x20, 0x40 }, { 0xc0, 0x20, 0x60 },
1121         { 0xc0, 0x20, 0x80 }, { 0xc0, 0x20, 0xa0 }, { 0xc0, 0x20, 0xc0 }, { 0xc0, 0x20, 0xe0 },
1122         { 0xc0, 0x40, 0x00 }, { 0xc0, 0x40, 0x20 }, { 0xc0, 0x40, 0x40 }, { 0xc0, 0x40, 0x60 },
1123         { 0xc0, 0x40, 0x80 }, { 0xc0, 0x40, 0xa0 }, { 0xc0, 0x40, 0xc0 }, { 0xc0, 0x40, 0xe0 },
1124         { 0xc0, 0x60, 0x00 }, { 0xc0, 0x60, 0x20 }, { 0xc0, 0x60, 0x40 }, { 0xc0, 0x60, 0x60 },
1125         { 0xc0, 0x60, 0x80 }, { 0xc0, 0x60, 0xa0 }, { 0xc0, 0x60, 0xc0 }, { 0xc0, 0x60, 0xe0 },
1126         { 0xc0, 0x80, 0x00 }, { 0xc0, 0x80, 0x20 }, { 0xc0, 0x80, 0x40 }, { 0xc0, 0x80, 0x60 },
1127         { 0xc0, 0x80, 0x80 }, { 0xc0, 0x80, 0xa0 }, { 0xc0, 0x80, 0xc0 }, { 0xc0, 0x80, 0xe0 },
1128         { 0xc0, 0xa0, 0x00 }, { 0xc0, 0xa0, 0x20 }, { 0xc0, 0xa0, 0x40 }, { 0xc0, 0xa0, 0x60 },
1129         { 0xc0, 0xa0, 0x80 }, { 0xc0, 0xa0, 0xa0 }, { 0xc0, 0xa0, 0xc0 }, { 0xc0, 0xa0, 0xe0 },
1130         { 0xc0, 0xc0, 0x00 }, { 0xc0, 0xc0, 0x20 }, { 0xc0, 0xc0, 0x40 }, { 0xc0, 0xc0, 0x60 },
1131         { 0xc0, 0xc0, 0x80 }, { 0xc0, 0xc0, 0xa0 }, { 0xf0, 0xfb, 0xff }, { 0xa4, 0xa0, 0xa0 },
1132         { 0x80, 0x80, 0x80 }, { 0x00, 0x00, 0xff }, { 0x00, 0xff, 0x00 }, { 0x00, 0xff, 0xff },
1133         { 0xff, 0x00, 0x00 }, { 0xff, 0x00, 0xff }, { 0xff, 0xff, 0x00 }, { 0xff, 0xff, 0xff },
1134     };
1135
1136     switch (bpp)
1137     {
1138     case 1: return table_1;
1139     case 4: return table_4;
1140     case 8: return table_8;
1141     default: return NULL;
1142     }
1143 }
1144
1145 void fill_default_color_table( BITMAPINFO *info )
1146 {
1147     info->bmiHeader.biClrUsed = 1 << info->bmiHeader.biBitCount;
1148     memcpy( info->bmiColors, get_default_color_table( info->bmiHeader.biBitCount ),
1149             info->bmiHeader.biClrUsed * sizeof(RGBQUAD) );
1150 }
1151
1152 void get_ddb_bitmapinfo( BITMAPOBJ *bmp, BITMAPINFO *info )
1153 {
1154     info->bmiHeader.biSize          = sizeof(info->bmiHeader);
1155     info->bmiHeader.biWidth         = bmp->bitmap.bmWidth;
1156     info->bmiHeader.biHeight        = -bmp->bitmap.bmHeight;
1157     info->bmiHeader.biPlanes        = 1;
1158     info->bmiHeader.biBitCount      = bmp->bitmap.bmBitsPixel;
1159     info->bmiHeader.biCompression   = BI_RGB;
1160     info->bmiHeader.biXPelsPerMeter = 0;
1161     info->bmiHeader.biYPelsPerMeter = 0;
1162     info->bmiHeader.biClrUsed       = 0;
1163     info->bmiHeader.biClrImportant  = 0;
1164 }
1165
1166 BITMAPINFO *copy_packed_dib( const BITMAPINFO *src_info, UINT usage )
1167 {
1168     char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1169     BITMAPINFO *ret, *info = (BITMAPINFO *)buffer;
1170     unsigned int info_size;
1171
1172     if (!bitmapinfo_from_user_bitmapinfo( info, src_info, usage, FALSE )) return NULL;
1173
1174     info_size = get_dib_info_size( info, usage );
1175     if ((ret = HeapAlloc( GetProcessHeap(), 0, info_size + info->bmiHeader.biSizeImage )))
1176     {
1177         memcpy( ret, info, info_size );
1178         memcpy( (char *)ret + info_size, (char *)src_info + bitmap_info_size( src_info, usage ),
1179                 info->bmiHeader.biSizeImage );
1180     }
1181     return ret;
1182 }
1183
1184 /******************************************************************************
1185  * GetDIBits [GDI32.@]
1186  *
1187  * Retrieves bits of bitmap and copies to buffer.
1188  *
1189  * RETURNS
1190  *    Success: Number of scan lines copied from bitmap
1191  *    Failure: 0
1192  */
1193 INT WINAPI GetDIBits(
1194     HDC hdc,         /* [in]  Handle to device context */
1195     HBITMAP hbitmap, /* [in]  Handle to bitmap */
1196     UINT startscan,  /* [in]  First scan line to set in dest bitmap */
1197     UINT lines,      /* [in]  Number of scan lines to copy */
1198     LPVOID bits,       /* [out] Address of array for bitmap bits */
1199     BITMAPINFO * info, /* [out] Address of structure with bitmap data */
1200     UINT coloruse)   /* [in]  RGB or palette index */
1201 {
1202     DC * dc;
1203     BITMAPOBJ * bmp;
1204     int i, dst_to_src_offset, ret = 0;
1205     DWORD err;
1206     char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1207     BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf;
1208     char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1209     BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
1210     const struct gdi_dc_funcs *funcs;
1211     struct gdi_image_bits src_bits;
1212     struct bitblt_coords src, dst;
1213     BOOL empty_rect = FALSE;
1214
1215     /* Since info may be a BITMAPCOREINFO or any of the larger BITMAPINFO structures, we'll use our
1216        own copy and transfer the colour info back at the end */
1217     if (!bitmapinfoheader_from_user_bitmapinfo( &dst_info->bmiHeader, &info->bmiHeader )) return 0;
1218     if (coloruse > DIB_PAL_COLORS) return 0;
1219     if (bits &&
1220         (dst_info->bmiHeader.biCompression == BI_JPEG || dst_info->bmiHeader.biCompression == BI_PNG))
1221         return 0;
1222     dst_info->bmiHeader.biClrUsed = 0;
1223     dst_info->bmiHeader.biClrImportant = 0;
1224
1225     if (!(dc = get_dc_ptr( hdc )))
1226     {
1227         SetLastError( ERROR_INVALID_PARAMETER );
1228         return 0;
1229     }
1230     update_dc( dc );
1231     if (!(bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
1232     {
1233         release_dc_ptr( dc );
1234         return 0;
1235     }
1236
1237     funcs = get_bitmap_funcs( bmp );
1238
1239     src.visrect.left   = 0;
1240     src.visrect.top    = 0;
1241     src.visrect.right  = bmp->bitmap.bmWidth;
1242     src.visrect.bottom = bmp->bitmap.bmHeight;
1243
1244     dst.visrect.left   = 0;
1245     dst.visrect.top    = 0;
1246     dst.visrect.right  = dst_info->bmiHeader.biWidth;
1247     dst.visrect.bottom = abs( dst_info->bmiHeader.biHeight );
1248
1249     if (lines == 0 || startscan >= dst.visrect.bottom)
1250         bits = NULL;
1251
1252     if (!bits && dst_info->bmiHeader.biBitCount == 0) /* query bitmap info only */
1253     {
1254         ret = fill_query_info( info, bmp );
1255         goto done;
1256     }
1257
1258     /* validate parameters */
1259
1260     if (dst_info->bmiHeader.biWidth <= 0) goto done;
1261     if (dst_info->bmiHeader.biHeight == 0) goto done;
1262
1263     switch (dst_info->bmiHeader.biCompression)
1264     {
1265     case BI_RLE4:
1266         if (dst_info->bmiHeader.biBitCount != 4) goto done;
1267         if (dst_info->bmiHeader.biHeight < 0) goto done;
1268         if (bits) goto done;  /* can't retrieve compressed bits */
1269         break;
1270     case BI_RLE8:
1271         if (dst_info->bmiHeader.biBitCount != 8) goto done;
1272         if (dst_info->bmiHeader.biHeight < 0) goto done;
1273         if (bits) goto done;  /* can't retrieve compressed bits */
1274         break;
1275     case BI_BITFIELDS:
1276         if (dst_info->bmiHeader.biBitCount != 16 && dst_info->bmiHeader.biBitCount != 32) goto done;
1277         /* fall through */
1278     case BI_RGB:
1279         if (lines && !dst_info->bmiHeader.biPlanes) goto done;
1280         if (dst_info->bmiHeader.biBitCount == 1) break;
1281         if (dst_info->bmiHeader.biBitCount == 4) break;
1282         if (dst_info->bmiHeader.biBitCount == 8) break;
1283         if (dst_info->bmiHeader.biBitCount == 16) break;
1284         if (dst_info->bmiHeader.biBitCount == 24) break;
1285         if (dst_info->bmiHeader.biBitCount == 32) break;
1286         /* fall through */
1287     default:
1288         goto done;
1289     }
1290
1291     if (bits)
1292     {
1293         if (dst_info->bmiHeader.biHeight > 0)
1294         {
1295             dst_to_src_offset = -startscan;
1296             lines = min( lines, dst.visrect.bottom - startscan );
1297             if (lines < dst.visrect.bottom) dst.visrect.top = dst.visrect.bottom - lines;
1298         }
1299         else
1300         {
1301             dst_to_src_offset = dst.visrect.bottom - lines - startscan;
1302             if (dst_to_src_offset < 0)
1303             {
1304                 dst_to_src_offset = 0;
1305                 lines = dst.visrect.bottom - startscan;
1306             }
1307             if (lines < dst.visrect.bottom) dst.visrect.bottom = lines;
1308         }
1309
1310         offset_rect( &dst.visrect, 0, dst_to_src_offset );
1311         empty_rect = !intersect_rect( &src.visrect, &src.visrect, &dst.visrect );
1312         dst.visrect = src.visrect;
1313         offset_rect( &dst.visrect, 0, -dst_to_src_offset );
1314
1315         if (dst_info->bmiHeader.biHeight > 0)
1316         {
1317             if (dst.visrect.bottom < dst_info->bmiHeader.biHeight)
1318             {
1319                 int pad_lines = min( dst_info->bmiHeader.biHeight - dst.visrect.bottom, lines );
1320                 int pad_bytes = pad_lines * get_dib_stride( dst_info->bmiHeader.biWidth, dst_info->bmiHeader.biBitCount );
1321                 memset( bits, 0, pad_bytes );
1322                 bits = (char *)bits + pad_bytes;
1323             }
1324         }
1325         else
1326         {
1327             if (dst.visrect.bottom < lines)
1328             {
1329                 int pad_lines = lines - dst.visrect.bottom;
1330                 int stride = get_dib_stride( dst_info->bmiHeader.biWidth, dst_info->bmiHeader.biBitCount );
1331                 int pad_bytes = pad_lines * stride;
1332                 memset( (char *)bits + dst.visrect.bottom * stride, 0, pad_bytes );
1333             }
1334         }
1335
1336         if (empty_rect) bits = NULL;
1337
1338         src.x      = src.visrect.left;
1339         src.y      = src.visrect.top;
1340         src.width  = src.visrect.right - src.visrect.left;
1341         src.height = src.visrect.bottom - src.visrect.top;
1342
1343         lines = src.height;
1344     }
1345
1346     err = funcs->pGetImage( NULL, hbitmap, src_info, bits ? &src_bits : NULL, bits ? &src : NULL );
1347
1348     if (err) goto done;
1349
1350     /* fill out the src colour table, if it needs one */
1351     if (src_info->bmiHeader.biBitCount <= 8 && src_info->bmiHeader.biClrUsed == 0)
1352         fill_default_color_table( src_info );
1353
1354     /* if the src and dst are the same depth, copy the colour info across */
1355     if (dst_info->bmiHeader.biBitCount == src_info->bmiHeader.biBitCount && coloruse == DIB_RGB_COLORS )
1356     {
1357         switch (src_info->bmiHeader.biBitCount)
1358         {
1359         case 16:
1360             if (src_info->bmiHeader.biCompression == BI_RGB)
1361             {
1362                 src_info->bmiHeader.biCompression = BI_BITFIELDS;
1363                 memcpy( src_info->bmiColors, bit_fields_555, sizeof(bit_fields_555) );
1364             }
1365             break;
1366         case 32:
1367             if (src_info->bmiHeader.biCompression == BI_RGB)
1368             {
1369                 src_info->bmiHeader.biCompression = BI_BITFIELDS;
1370                 memcpy( src_info->bmiColors, bit_fields_888, sizeof(bit_fields_888) );
1371             }
1372             break;
1373         }
1374         src_info->bmiHeader.biSizeImage = get_dib_image_size( dst_info );
1375         copy_color_info( dst_info, src_info, coloruse );
1376     }
1377     else if (dst_info->bmiHeader.biBitCount <= 8) /* otherwise construct a default colour table for the dst, if needed */
1378     {
1379         if( coloruse == DIB_PAL_COLORS )
1380         {
1381             if (!fill_color_table_from_palette( dst_info, hdc )) goto done;
1382         }
1383         else
1384         {
1385             fill_default_color_table( dst_info );
1386         }
1387     }
1388
1389     if (bits)
1390     {
1391         if(dst_info->bmiHeader.biHeight > 0)
1392             dst_info->bmiHeader.biHeight = src.height;
1393         else
1394             dst_info->bmiHeader.biHeight = -src.height;
1395
1396         convert_bitmapinfo( src_info, src_bits.ptr, &src, dst_info, bits, FALSE );
1397         if (src_bits.free) src_bits.free( &src_bits );
1398         ret = lines;
1399     }
1400     else
1401         ret = empty_rect ? FALSE : TRUE;
1402
1403     if (coloruse == DIB_PAL_COLORS)
1404     {
1405         WORD *index = (WORD *)dst_info->bmiColors;
1406         for (i = 0; i < dst_info->bmiHeader.biClrUsed; i++, index++)
1407             *index = i;
1408     }
1409
1410     copy_color_info( info, dst_info, coloruse );
1411     if (info->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) info->bmiHeader.biClrUsed = 0;
1412
1413 done:
1414     release_dc_ptr( dc );
1415     GDI_ReleaseObj( hbitmap );
1416     return ret;
1417 }
1418
1419
1420 /***********************************************************************
1421  *           CreateDIBitmap    (GDI32.@)
1422  *
1423  * Creates a DDB (device dependent bitmap) from a DIB.
1424  * The DDB will have the same color depth as the reference DC.
1425  */
1426 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
1427                             DWORD init, LPCVOID bits, const BITMAPINFO *data,
1428                             UINT coloruse )
1429 {
1430     BITMAPINFOHEADER info;
1431     HBITMAP handle;
1432     LONG height;
1433
1434     if (!bitmapinfoheader_from_user_bitmapinfo( &info, header )) return 0;
1435     if (info.biCompression == BI_JPEG || info.biCompression == BI_PNG) return 0;
1436     if (coloruse > DIB_PAL_COLORS + 1) return 0;
1437     if (info.biWidth < 0) return 0;
1438
1439     /* Top-down DIBs have a negative height */
1440     height = abs( info.biHeight );
1441
1442     TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1443           hdc, header, init, bits, data, coloruse, info.biWidth, info.biHeight,
1444           info.biBitCount, info.biCompression);
1445
1446     if (hdc == NULL)
1447         handle = CreateBitmap( info.biWidth, height, 1, 1, NULL );
1448     else
1449         handle = CreateCompatibleBitmap( hdc, info.biWidth, height );
1450
1451     if (handle)
1452     {
1453         if (init & CBM_INIT)
1454         {
1455             if (SetDIBits( hdc, handle, 0, height, bits, data, coloruse ) == 0)
1456             {
1457                 DeleteObject( handle );
1458                 handle = 0;
1459             }
1460         }
1461     }
1462
1463     return handle;
1464 }
1465
1466
1467 /***********************************************************************
1468  *           CreateDIBSection    (GDI32.@)
1469  */
1470 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1471                                 VOID **bits, HANDLE section, DWORD offset)
1472 {
1473     char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1474     BITMAPINFO *info = (BITMAPINFO *)buffer;
1475     HBITMAP ret = 0;
1476     DC *dc;
1477     BOOL bDesktopDC = FALSE;
1478     DIBSECTION *dib;
1479     BITMAPOBJ *bmp;
1480     RGBQUAD *color_table = NULL;
1481     void *mapBits = NULL;
1482
1483     if (bits) *bits = NULL;
1484     if (!bitmapinfo_from_user_bitmapinfo( info, bmi, usage, FALSE )) return 0;
1485     if (usage > DIB_PAL_COLORS) return 0;
1486     if (info->bmiHeader.biPlanes != 1)
1487     {
1488         if (info->bmiHeader.biPlanes * info->bmiHeader.biBitCount > 16) return 0;
1489         WARN( "%u planes not properly supported\n", info->bmiHeader.biPlanes );
1490     }
1491
1492     if (!(dib = HeapAlloc( GetProcessHeap(), 0, sizeof(*dib) ))) return 0;
1493
1494     TRACE("format (%d,%d), planes %d, bpp %d, %s, size %d %s\n",
1495           info->bmiHeader.biWidth, info->bmiHeader.biHeight,
1496           info->bmiHeader.biPlanes, info->bmiHeader.biBitCount,
1497           info->bmiHeader.biCompression == BI_BITFIELDS? "BI_BITFIELDS" : "BI_RGB",
1498           info->bmiHeader.biSizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1499
1500     dib->dsBm.bmType       = 0;
1501     dib->dsBm.bmWidth      = info->bmiHeader.biWidth;
1502     dib->dsBm.bmHeight     = abs( info->bmiHeader.biHeight );
1503     dib->dsBm.bmWidthBytes = get_dib_stride( info->bmiHeader.biWidth, info->bmiHeader.biBitCount );
1504     dib->dsBm.bmPlanes     = info->bmiHeader.biPlanes;
1505     dib->dsBm.bmBitsPixel  = info->bmiHeader.biBitCount;
1506     dib->dsBm.bmBits       = NULL;
1507     dib->dsBmih            = info->bmiHeader;
1508
1509     if (info->bmiHeader.biBitCount <= 8)  /* build the color table */
1510     {
1511         if (usage == DIB_PAL_COLORS && !fill_color_table_from_pal_colors( info, hdc ))
1512             goto error;
1513         dib->dsBmih.biClrUsed = info->bmiHeader.biClrUsed;
1514         if (!(color_table = HeapAlloc( GetProcessHeap(), 0, dib->dsBmih.biClrUsed * sizeof(RGBQUAD) )))
1515             goto error;
1516         memcpy( color_table, info->bmiColors, dib->dsBmih.biClrUsed * sizeof(RGBQUAD) );
1517     }
1518
1519     /* set dsBitfields values */
1520     if (info->bmiHeader.biBitCount == 16 && info->bmiHeader.biCompression == BI_RGB)
1521     {
1522         dib->dsBmih.biCompression = BI_BITFIELDS;
1523         dib->dsBitfields[0] = 0x7c00;
1524         dib->dsBitfields[1] = 0x03e0;
1525         dib->dsBitfields[2] = 0x001f;
1526     }
1527     else if (info->bmiHeader.biCompression == BI_BITFIELDS)
1528     {
1529         if (usage == DIB_PAL_COLORS) goto error;
1530         dib->dsBitfields[0] =  *(const DWORD *)info->bmiColors;
1531         dib->dsBitfields[1] =  *((const DWORD *)info->bmiColors + 1);
1532         dib->dsBitfields[2] =  *((const DWORD *)info->bmiColors + 2);
1533         if (!dib->dsBitfields[0] || !dib->dsBitfields[1] || !dib->dsBitfields[2]) goto error;
1534     }
1535     else dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1536
1537     /* get storage location for DIB bits */
1538
1539     if (section)
1540     {
1541         SYSTEM_INFO SystemInfo;
1542         DWORD mapOffset;
1543         INT mapSize;
1544
1545         GetSystemInfo( &SystemInfo );
1546         mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
1547         mapSize = dib->dsBmih.biSizeImage + (offset - mapOffset);
1548         mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
1549         if (mapBits) dib->dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1550     }
1551     else
1552     {
1553         offset = 0;
1554         dib->dsBm.bmBits = VirtualAlloc( NULL, dib->dsBmih.biSizeImage,
1555                                          MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1556     }
1557     dib->dshSection = section;
1558     dib->dsOffset = offset;
1559
1560     if (!dib->dsBm.bmBits) goto error;
1561
1562     /* If the reference hdc is null, take the desktop dc */
1563     if (hdc == 0)
1564     {
1565         hdc = CreateCompatibleDC(0);
1566         bDesktopDC = TRUE;
1567     }
1568
1569     if (!(dc = get_dc_ptr( hdc ))) goto error;
1570
1571     /* create Device Dependent Bitmap and add DIB pointer */
1572     ret = CreateBitmap( dib->dsBm.bmWidth, dib->dsBm.bmHeight, 1,
1573                         (info->bmiHeader.biBitCount == 1) ? 1 : GetDeviceCaps(hdc, BITSPIXEL), NULL );
1574
1575     if (ret && ((bmp = GDI_GetObjPtr(ret, OBJ_BITMAP))))
1576     {
1577         PHYSDEV physdev = GET_DC_PHYSDEV( dc, pCreateDIBSection );
1578         bmp->dib = dib;
1579         bmp->funcs = physdev->funcs;
1580         bmp->color_table = color_table;
1581         GDI_ReleaseObj( ret );
1582
1583         if (!physdev->funcs->pCreateDIBSection( physdev, ret, info, usage ))
1584         {
1585             DeleteObject( ret );
1586             ret = 0;
1587         }
1588     }
1589
1590     release_dc_ptr( dc );
1591     if (bDesktopDC) DeleteDC( hdc );
1592     if (ret && bits) *bits = dib->dsBm.bmBits;
1593     return ret;
1594
1595 error:
1596     if (bDesktopDC) DeleteDC( hdc );
1597     if (section) UnmapViewOfFile( mapBits );
1598     else if (!offset) VirtualFree( dib->dsBm.bmBits, 0, MEM_RELEASE );
1599     HeapFree( GetProcessHeap(), 0, color_table );
1600     HeapFree( GetProcessHeap(), 0, dib );
1601     return 0;
1602 }