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