gdi32: Get rid of the get_bitmap_funcs function.
[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     int 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     get_bounding_rect( &rect, dst.x, dst.y, dst.width, dst.height );
548
549     if (!clip_visrect( dc, &dst.visrect, &rect )) goto done;
550
551     if (!intersect_vis_rectangles( &dst, &src )) goto done;
552
553     if (clip) OffsetRgn( clip, dst.x - src.x, dst.y - src.y );
554
555     dev = GET_DC_PHYSDEV( dc, pPutImage );
556     copy_bitmapinfo( dst_info, src_info );
557     err = dev->funcs->pPutImage( dev, 0, clip, dst_info, &src_bits, &src, &dst, rop );
558     if (err == ERROR_BAD_FORMAT)
559     {
560         /* 1-bpp destination without a color table requires a fake 1-entry table
561          * that contains only the background color */
562         if (dst_info->bmiHeader.biBitCount == 1 && !dst_info->bmiHeader.biClrUsed)
563         {
564             COLORREF color = GetBkColor( dev->hdc );
565             dst_info->bmiColors[0].rgbRed      = GetRValue( color );
566             dst_info->bmiColors[0].rgbGreen    = GetGValue( color );
567             dst_info->bmiColors[0].rgbBlue     = GetBValue( color );
568             dst_info->bmiColors[0].rgbReserved = 0;
569             dst_info->bmiHeader.biClrUsed = 1;
570         }
571
572         if (!(err = convert_bits( src_info, &src, dst_info, &src_bits, FALSE )))
573         {
574             /* get rid of the fake 1-bpp table */
575             if (dst_info->bmiHeader.biClrUsed == 1) dst_info->bmiHeader.biClrUsed = 0;
576             err = dev->funcs->pPutImage( dev, 0, clip, dst_info, &src_bits, &src, &dst, rop );
577         }
578     }
579
580     if (err == ERROR_TRANSFORM_NOT_SUPPORTED)
581     {
582         copy_bitmapinfo( src_info, dst_info );
583         err = stretch_bits( src_info, &src, dst_info, &dst, &src_bits, GetStretchBltMode( dev->hdc ) );
584         if (!err) err = dev->funcs->pPutImage( dev, 0, NULL, dst_info, &src_bits, &src, &dst, rop );
585     }
586     if (err) ret = 0;
587     else if (rop == SRCCOPY) ret = height;
588     else ret = src_info->bmiHeader.biHeight;
589
590 done:
591     if (src_bits.free) src_bits.free( &src_bits );
592     if (clip) DeleteObject( clip );
593     return ret;
594 }
595
596 /***********************************************************************
597  *           StretchDIBits   (GDI32.@)
598  */
599 INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst, INT heightDst,
600                          INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
601                          const BITMAPINFO *bmi, UINT coloruse, DWORD rop )
602 {
603     char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
604     BITMAPINFO *info = (BITMAPINFO *)buffer;
605     DC *dc;
606     INT ret = 0;
607
608     if (!bits) return 0;
609     if (!bitmapinfo_from_user_bitmapinfo( info, bmi, coloruse, TRUE ))
610     {
611         SetLastError( ERROR_INVALID_PARAMETER );
612         return 0;
613     }
614
615     if ((dc = get_dc_ptr( hdc )))
616     {
617         PHYSDEV physdev = GET_DC_PHYSDEV( dc, pStretchDIBits );
618         update_dc( dc );
619         ret = physdev->funcs->pStretchDIBits( physdev, xDst, yDst, widthDst, heightDst,
620                                               xSrc, ySrc, widthSrc, heightSrc, bits, info, coloruse, rop );
621         release_dc_ptr( dc );
622     }
623     return ret;
624 }
625
626
627 /******************************************************************************
628  * SetDIBits [GDI32.@]
629  *
630  * Sets pixels in a bitmap using colors from DIB.
631  *
632  * PARAMS
633  *    hdc       [I] Handle to device context
634  *    hbitmap   [I] Handle to bitmap
635  *    startscan [I] Starting scan line
636  *    lines     [I] Number of scan lines
637  *    bits      [I] Array of bitmap bits
638  *    info      [I] Address of structure with data
639  *    coloruse  [I] Type of color indexes to use
640  *
641  * RETURNS
642  *    Success: Number of scan lines copied
643  *    Failure: 0
644  */
645 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
646                       UINT lines, LPCVOID bits, const BITMAPINFO *info,
647                       UINT coloruse )
648 {
649     BITMAPOBJ *bitmap;
650     char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
651     BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
652     char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
653     BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf;
654     INT result = 0;
655     DWORD err;
656     struct gdi_image_bits src_bits;
657     struct bitblt_coords src, dst;
658     INT src_to_dst_offset;
659     HRGN clip = 0;
660
661     if (!bitmapinfo_from_user_bitmapinfo( src_info, info, coloruse, TRUE ) || coloruse > DIB_PAL_COLORS)
662     {
663         SetLastError( ERROR_INVALID_PARAMETER );
664         return 0;
665     }
666     if (src_info->bmiHeader.biCompression == BI_BITFIELDS)
667     {
668         DWORD *masks = (DWORD *)src_info->bmiColors;
669         if (!masks[0] || !masks[1] || !masks[2])
670         {
671             SetLastError( ERROR_INVALID_PARAMETER );
672             return 0;
673         }
674     }
675
676     src_bits.ptr = (void *)bits;
677     src_bits.is_copy = FALSE;
678     src_bits.free = NULL;
679     src_bits.param = NULL;
680
681     if (coloruse == DIB_PAL_COLORS && !fill_color_table_from_pal_colors( src_info, hdc )) return 0;
682
683     if (!(bitmap = GDI_GetObjPtr( hbitmap, OBJ_BITMAP ))) return 0;
684
685     if (src_info->bmiHeader.biCompression == BI_RLE4 || src_info->bmiHeader.biCompression == BI_RLE8)
686     {
687         if (lines == 0) goto done;
688         else lines = src_info->bmiHeader.biHeight;
689         startscan = 0;
690
691         if (!build_rle_bitmap( src_info, &src_bits, &clip )) goto done;
692     }
693
694     dst.visrect.left   = 0;
695     dst.visrect.top    = 0;
696     dst.visrect.right  = bitmap->bitmap.bmWidth;
697     dst.visrect.bottom = bitmap->bitmap.bmHeight;
698
699     src.visrect.left   = 0;
700     src.visrect.top    = 0;
701     src.visrect.right  = src_info->bmiHeader.biWidth;
702     src.visrect.bottom = abs( src_info->bmiHeader.biHeight );
703
704     if (src_info->bmiHeader.biHeight > 0)
705     {
706         src_to_dst_offset = -startscan;
707         lines = min( lines, src.visrect.bottom - startscan );
708         if (lines < src.visrect.bottom) src.visrect.top = src.visrect.bottom - lines;
709     }
710     else
711     {
712         src_to_dst_offset = src.visrect.bottom - lines - startscan;
713         /* Unlike the bottom-up case, Windows doesn't limit lines. */
714         if (lines < src.visrect.bottom) src.visrect.bottom = lines;
715     }
716
717     result = lines;
718
719     offset_rect( &src.visrect, 0, src_to_dst_offset );
720     if (!intersect_rect( &dst.visrect, &src.visrect, &dst.visrect )) goto done;
721     src.visrect = dst.visrect;
722     offset_rect( &src.visrect, 0, -src_to_dst_offset );
723
724     src.x      = src.visrect.left;
725     src.y      = src.visrect.top;
726     src.width  = src.visrect.right - src.visrect.left;
727     src.height = src.visrect.bottom - src.visrect.top;
728
729     dst.x      = dst.visrect.left;
730     dst.y      = dst.visrect.top;
731     dst.width  = dst.visrect.right - dst.visrect.left;
732     dst.height = dst.visrect.bottom - dst.visrect.top;
733
734     copy_bitmapinfo( dst_info, src_info );
735
736     err = bitmap->funcs->pPutImage( NULL, hbitmap, clip, dst_info, &src_bits, &src, &dst, 0 );
737     if (err == ERROR_BAD_FORMAT)
738     {
739         err = convert_bits( src_info, &src, dst_info, &src_bits, FALSE );
740         if (!err) err = bitmap->funcs->pPutImage( NULL, hbitmap, clip, dst_info, &src_bits, &src, &dst, 0 );
741     }
742     if(err) result = 0;
743
744 done:
745     if (src_bits.free) src_bits.free( &src_bits );
746     if (clip) DeleteObject( clip );
747     GDI_ReleaseObj( hbitmap );
748     return result;
749 }
750
751
752 INT nulldrv_SetDIBitsToDevice( PHYSDEV dev, INT x_dst, INT y_dst, DWORD cx, DWORD cy,
753                                INT x_src, INT y_src, UINT startscan, UINT lines,
754                                const void *bits, BITMAPINFO *src_info, UINT coloruse )
755 {
756     DC *dc = get_nulldrv_dc( dev );
757     char dst_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
758     BITMAPINFO *dst_info = (BITMAPINFO *)dst_buffer;
759     struct bitblt_coords src, dst;
760     struct gdi_image_bits src_bits;
761     HRGN clip = 0;
762     DWORD err;
763     UINT height;
764     BOOL top_down;
765     POINT pt;
766     RECT rect;
767
768     top_down = (src_info->bmiHeader.biHeight < 0);
769     height = abs( src_info->bmiHeader.biHeight );
770
771     src_bits.ptr = (void *)bits;
772     src_bits.is_copy = FALSE;
773     src_bits.free = NULL;
774
775     if (!lines) return 0;
776     if (coloruse == DIB_PAL_COLORS && !fill_color_table_from_pal_colors( src_info, dev->hdc )) return 0;
777
778     if (src_info->bmiHeader.biCompression == BI_RLE4 || src_info->bmiHeader.biCompression == BI_RLE8)
779     {
780         startscan = 0;
781         lines = height;
782         src_info->bmiHeader.biWidth = x_src + cx;
783         src_info->bmiHeader.biHeight = y_src + cy;
784         if (src_info->bmiHeader.biWidth <= 0 || src_info->bmiHeader.biHeight <= 0) return 0;
785         src.x = x_src;
786         src.y = 0;
787         src.width = cx;
788         src.height = cy;
789         if (!build_rle_bitmap( src_info, &src_bits, &clip )) return 0;
790     }
791     else
792     {
793         if (startscan >= height) return 0;
794         if (!top_down && lines > height - startscan) lines = height - startscan;
795
796         /* map src to top-down coordinates with startscan as origin */
797         src.x = x_src;
798         src.y = startscan + lines - (y_src + cy);
799         src.width = cx;
800         src.height = cy;
801         if (src.y > 0)
802         {
803             if (!top_down)
804             {
805                 /* get rid of unnecessary lines */
806                 if (src.y >= lines) return 0;
807                 lines -= src.y;
808                 src.y = 0;
809             }
810             else if (src.y >= lines) return lines;
811         }
812         src_info->bmiHeader.biHeight = top_down ? -lines : lines;
813     }
814
815     src.visrect.left = src.x;
816     src.visrect.top = src.y;
817     src.visrect.right = src.x + cx;
818     src.visrect.bottom = src.y + cy;
819     rect.left = 0;
820     rect.top = 0;
821     rect.right = src_info->bmiHeader.biWidth;
822     rect.bottom = abs( src_info->bmiHeader.biHeight );
823     if (!intersect_rect( &src.visrect, &src.visrect, &rect ))
824     {
825         lines = 0;
826         goto done;
827     }
828
829     pt.x = x_dst;
830     pt.y = y_dst;
831     LPtoDP( dev->hdc, &pt, 1 );
832     dst.x = pt.x;
833     dst.y = pt.y;
834     dst.width = cx;
835     dst.height = cy;
836     if (GetLayout( dev->hdc ) & LAYOUT_RTL) dst.x -= cx - 1;
837
838     rect.left = dst.x;
839     rect.top = dst.y;
840     rect.right = dst.x + cx;
841     rect.bottom = dst.y + cy;
842     if (!clip_visrect( dc, &dst.visrect, &rect )) goto done;
843
844     offset_rect( &src.visrect, dst.x - src.x, dst.y - src.y );
845     intersect_rect( &rect, &src.visrect, &dst.visrect );
846     src.visrect = dst.visrect = rect;
847     offset_rect( &src.visrect, src.x - dst.x, src.y - dst.y );
848     if (is_rect_empty( &dst.visrect )) goto done;
849     if (clip) OffsetRgn( clip, dst.x - src.x, dst.y - src.y );
850
851     dev = GET_DC_PHYSDEV( dc, pPutImage );
852     copy_bitmapinfo( dst_info, src_info );
853     err = dev->funcs->pPutImage( dev, 0, clip, dst_info, &src_bits, &src, &dst, SRCCOPY );
854     if (err == ERROR_BAD_FORMAT)
855     {
856         err = convert_bits( src_info, &src, dst_info, &src_bits, FALSE );
857         if (!err) err = dev->funcs->pPutImage( dev, 0, clip, dst_info, &src_bits, &src, &dst, SRCCOPY );
858     }
859     if (err) lines = 0;
860
861 done:
862     if (src_bits.free) src_bits.free( &src_bits );
863     if (clip) DeleteObject( clip );
864     return lines;
865 }
866
867 /***********************************************************************
868  *           SetDIBitsToDevice   (GDI32.@)
869  */
870 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
871                            DWORD cy, INT xSrc, INT ySrc, UINT startscan,
872                            UINT lines, LPCVOID bits, const BITMAPINFO *bmi,
873                            UINT coloruse )
874 {
875     char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
876     BITMAPINFO *info = (BITMAPINFO *)buffer;
877     INT ret = 0;
878     DC *dc;
879
880     if (!bits) return 0;
881     if (!bitmapinfo_from_user_bitmapinfo( info, bmi, coloruse, TRUE ))
882     {
883         SetLastError( ERROR_INVALID_PARAMETER );
884         return 0;
885     }
886
887     if ((dc = get_dc_ptr( hdc )))
888     {
889         PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBitsToDevice );
890         update_dc( dc );
891         ret = physdev->funcs->pSetDIBitsToDevice( physdev, xDest, yDest, cx, cy, xSrc,
892                                                   ySrc, startscan, lines, bits, info, coloruse );
893         release_dc_ptr( dc );
894     }
895     return ret;
896 }
897
898 /***********************************************************************
899  *           SetDIBColorTable    (GDI32.@)
900  */
901 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUAD *colors )
902 {
903     DC * dc;
904     UINT result = 0;
905     BITMAPOBJ * bitmap;
906
907     if (!(dc = get_dc_ptr( hdc ))) return 0;
908
909     if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
910     {
911         /* Check if currently selected bitmap is a DIB */
912         if (bitmap->color_table)
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         }
920         GDI_ReleaseObj( dc->hBitmap );
921
922         if (result)  /* update colors of selected objects */
923         {
924             SetTextColor( hdc, dc->textColor );
925             SetBkColor( hdc, dc->backgroundColor );
926             SelectObject( hdc, dc->hPen );
927             SelectObject( hdc, dc->hBrush );
928         }
929     }
930     release_dc_ptr( dc );
931     return result;
932 }
933
934
935 /***********************************************************************
936  *           GetDIBColorTable    (GDI32.@)
937  */
938 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
939 {
940     DC * dc;
941     BITMAPOBJ *bitmap;
942     UINT result = 0;
943
944     if (!(dc = get_dc_ptr( hdc ))) return 0;
945
946     if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
947     {
948         /* Check if currently selected bitmap is a DIB */
949         if (bitmap->color_table)
950         {
951             if (startpos < bitmap->dib->dsBmih.biClrUsed)
952             {
953                 result = min( entries, bitmap->dib->dsBmih.biClrUsed - startpos );
954                 memcpy(colors, bitmap->color_table + startpos, result * sizeof(RGBQUAD));
955             }
956         }
957         GDI_ReleaseObj( dc->hBitmap );
958     }
959     release_dc_ptr( dc );
960     return result;
961 }
962
963 static const DWORD bit_fields_888[3] = {0xff0000, 0x00ff00, 0x0000ff};
964 static const DWORD bit_fields_565[3] = {0xf800, 0x07e0, 0x001f};
965 static const DWORD bit_fields_555[3] = {0x7c00, 0x03e0, 0x001f};
966
967 static int fill_query_info( BITMAPINFO *info, BITMAPOBJ *bmp )
968 {
969     BITMAPINFOHEADER header;
970
971     header.biSize   = info->bmiHeader.biSize; /* Ensure we don't overwrite the original size when we copy back */
972     header.biWidth  = bmp->bitmap.bmWidth;
973     header.biHeight = bmp->bitmap.bmHeight;
974     header.biPlanes = 1;
975     header.biBitCount = bmp->bitmap.bmBitsPixel;
976
977     switch (header.biBitCount)
978     {
979     case 16:
980     case 32:
981         header.biCompression = BI_BITFIELDS;
982         break;
983     default:
984         header.biCompression = BI_RGB;
985         break;
986     }
987
988     header.biSizeImage = get_dib_image_size( (BITMAPINFO *)&header );
989     header.biXPelsPerMeter = 0;
990     header.biYPelsPerMeter = 0;
991     header.biClrUsed       = 0;
992     header.biClrImportant  = 0;
993
994     if ( info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER) )
995     {
996         BITMAPCOREHEADER *coreheader = (BITMAPCOREHEADER *)info;
997
998         coreheader->bcWidth    = header.biWidth;
999         coreheader->bcHeight   = header.biHeight;
1000         coreheader->bcPlanes   = header.biPlanes;
1001         coreheader->bcBitCount = header.biBitCount;
1002     }
1003     else
1004         info->bmiHeader = header;
1005
1006     return abs(bmp->bitmap.bmHeight);
1007 }
1008
1009 /************************************************************************
1010  *      copy_color_info
1011  *
1012  * Copy BITMAPINFO color information where dst may be a BITMAPCOREINFO.
1013  */
1014 static void copy_color_info(BITMAPINFO *dst, const BITMAPINFO *src, UINT coloruse)
1015 {
1016     assert( src->bmiHeader.biSize == sizeof(BITMAPINFOHEADER) );
1017
1018     if (dst->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1019     {
1020         BITMAPCOREINFO *core = (BITMAPCOREINFO *)dst;
1021         if (coloruse == DIB_PAL_COLORS)
1022             memcpy( core->bmciColors, src->bmiColors, src->bmiHeader.biClrUsed * sizeof(WORD) );
1023         else
1024         {
1025             unsigned int i;
1026             for (i = 0; i < src->bmiHeader.biClrUsed; i++)
1027             {
1028                 core->bmciColors[i].rgbtRed   = src->bmiColors[i].rgbRed;
1029                 core->bmciColors[i].rgbtGreen = src->bmiColors[i].rgbGreen;
1030                 core->bmciColors[i].rgbtBlue  = src->bmiColors[i].rgbBlue;
1031             }
1032         }
1033     }
1034     else
1035     {
1036         dst->bmiHeader.biClrUsed   = src->bmiHeader.biClrUsed;
1037         dst->bmiHeader.biSizeImage = src->bmiHeader.biSizeImage;
1038
1039         if (src->bmiHeader.biCompression == BI_BITFIELDS)
1040             /* bitfields are always at bmiColors even in larger structures */
1041             memcpy( dst->bmiColors, src->bmiColors, 3 * sizeof(DWORD) );
1042         else if (src->bmiHeader.biClrUsed)
1043         {
1044             void *colorptr = (char *)dst + dst->bmiHeader.biSize;
1045             unsigned int size;
1046
1047             if (coloruse == DIB_PAL_COLORS)
1048                 size = src->bmiHeader.biClrUsed * sizeof(WORD);
1049             else
1050                 size = src->bmiHeader.biClrUsed * sizeof(RGBQUAD);
1051             memcpy( colorptr, src->bmiColors, size );
1052         }
1053     }
1054 }
1055
1056 const RGBQUAD *get_default_color_table( int bpp )
1057 {
1058     static const RGBQUAD table_1[2] =
1059     {
1060         { 0x00, 0x00, 0x00 }, { 0xff, 0xff, 0xff }
1061     };
1062     static const RGBQUAD table_4[16] =
1063     {
1064         { 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x80 }, { 0x00, 0x80, 0x00 }, { 0x00, 0x80, 0x80 },
1065         { 0x80, 0x00, 0x00 }, { 0x80, 0x00, 0x80 }, { 0x80, 0x80, 0x00 }, { 0x80, 0x80, 0x80 },
1066         { 0xc0, 0xc0, 0xc0 }, { 0x00, 0x00, 0xff }, { 0x00, 0xff, 0x00 }, { 0x00, 0xff, 0xff },
1067         { 0xff, 0x00, 0x00 }, { 0xff, 0x00, 0xff }, { 0xff, 0xff, 0x00 }, { 0xff, 0xff, 0xff },
1068     };
1069     static const RGBQUAD table_8[256] =
1070     {
1071         /* first and last 10 entries are the default system palette entries */
1072         { 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x80 }, { 0x00, 0x80, 0x00 }, { 0x00, 0x80, 0x80 },
1073         { 0x80, 0x00, 0x00 }, { 0x80, 0x00, 0x80 }, { 0x80, 0x80, 0x00 }, { 0xc0, 0xc0, 0xc0 },
1074         { 0xc0, 0xdc, 0xc0 }, { 0xf0, 0xca, 0xa6 }, { 0x00, 0x20, 0x40 }, { 0x00, 0x20, 0x60 },
1075         { 0x00, 0x20, 0x80 }, { 0x00, 0x20, 0xa0 }, { 0x00, 0x20, 0xc0 }, { 0x00, 0x20, 0xe0 },
1076         { 0x00, 0x40, 0x00 }, { 0x00, 0x40, 0x20 }, { 0x00, 0x40, 0x40 }, { 0x00, 0x40, 0x60 },
1077         { 0x00, 0x40, 0x80 }, { 0x00, 0x40, 0xa0 }, { 0x00, 0x40, 0xc0 }, { 0x00, 0x40, 0xe0 },
1078         { 0x00, 0x60, 0x00 }, { 0x00, 0x60, 0x20 }, { 0x00, 0x60, 0x40 }, { 0x00, 0x60, 0x60 },
1079         { 0x00, 0x60, 0x80 }, { 0x00, 0x60, 0xa0 }, { 0x00, 0x60, 0xc0 }, { 0x00, 0x60, 0xe0 },
1080         { 0x00, 0x80, 0x00 }, { 0x00, 0x80, 0x20 }, { 0x00, 0x80, 0x40 }, { 0x00, 0x80, 0x60 },
1081         { 0x00, 0x80, 0x80 }, { 0x00, 0x80, 0xa0 }, { 0x00, 0x80, 0xc0 }, { 0x00, 0x80, 0xe0 },
1082         { 0x00, 0xa0, 0x00 }, { 0x00, 0xa0, 0x20 }, { 0x00, 0xa0, 0x40 }, { 0x00, 0xa0, 0x60 },
1083         { 0x00, 0xa0, 0x80 }, { 0x00, 0xa0, 0xa0 }, { 0x00, 0xa0, 0xc0 }, { 0x00, 0xa0, 0xe0 },
1084         { 0x00, 0xc0, 0x00 }, { 0x00, 0xc0, 0x20 }, { 0x00, 0xc0, 0x40 }, { 0x00, 0xc0, 0x60 },
1085         { 0x00, 0xc0, 0x80 }, { 0x00, 0xc0, 0xa0 }, { 0x00, 0xc0, 0xc0 }, { 0x00, 0xc0, 0xe0 },
1086         { 0x00, 0xe0, 0x00 }, { 0x00, 0xe0, 0x20 }, { 0x00, 0xe0, 0x40 }, { 0x00, 0xe0, 0x60 },
1087         { 0x00, 0xe0, 0x80 }, { 0x00, 0xe0, 0xa0 }, { 0x00, 0xe0, 0xc0 }, { 0x00, 0xe0, 0xe0 },
1088         { 0x40, 0x00, 0x00 }, { 0x40, 0x00, 0x20 }, { 0x40, 0x00, 0x40 }, { 0x40, 0x00, 0x60 },
1089         { 0x40, 0x00, 0x80 }, { 0x40, 0x00, 0xa0 }, { 0x40, 0x00, 0xc0 }, { 0x40, 0x00, 0xe0 },
1090         { 0x40, 0x20, 0x00 }, { 0x40, 0x20, 0x20 }, { 0x40, 0x20, 0x40 }, { 0x40, 0x20, 0x60 },
1091         { 0x40, 0x20, 0x80 }, { 0x40, 0x20, 0xa0 }, { 0x40, 0x20, 0xc0 }, { 0x40, 0x20, 0xe0 },
1092         { 0x40, 0x40, 0x00 }, { 0x40, 0x40, 0x20 }, { 0x40, 0x40, 0x40 }, { 0x40, 0x40, 0x60 },
1093         { 0x40, 0x40, 0x80 }, { 0x40, 0x40, 0xa0 }, { 0x40, 0x40, 0xc0 }, { 0x40, 0x40, 0xe0 },
1094         { 0x40, 0x60, 0x00 }, { 0x40, 0x60, 0x20 }, { 0x40, 0x60, 0x40 }, { 0x40, 0x60, 0x60 },
1095         { 0x40, 0x60, 0x80 }, { 0x40, 0x60, 0xa0 }, { 0x40, 0x60, 0xc0 }, { 0x40, 0x60, 0xe0 },
1096         { 0x40, 0x80, 0x00 }, { 0x40, 0x80, 0x20 }, { 0x40, 0x80, 0x40 }, { 0x40, 0x80, 0x60 },
1097         { 0x40, 0x80, 0x80 }, { 0x40, 0x80, 0xa0 }, { 0x40, 0x80, 0xc0 }, { 0x40, 0x80, 0xe0 },
1098         { 0x40, 0xa0, 0x00 }, { 0x40, 0xa0, 0x20 }, { 0x40, 0xa0, 0x40 }, { 0x40, 0xa0, 0x60 },
1099         { 0x40, 0xa0, 0x80 }, { 0x40, 0xa0, 0xa0 }, { 0x40, 0xa0, 0xc0 }, { 0x40, 0xa0, 0xe0 },
1100         { 0x40, 0xc0, 0x00 }, { 0x40, 0xc0, 0x20 }, { 0x40, 0xc0, 0x40 }, { 0x40, 0xc0, 0x60 },
1101         { 0x40, 0xc0, 0x80 }, { 0x40, 0xc0, 0xa0 }, { 0x40, 0xc0, 0xc0 }, { 0x40, 0xc0, 0xe0 },
1102         { 0x40, 0xe0, 0x00 }, { 0x40, 0xe0, 0x20 }, { 0x40, 0xe0, 0x40 }, { 0x40, 0xe0, 0x60 },
1103         { 0x40, 0xe0, 0x80 }, { 0x40, 0xe0, 0xa0 }, { 0x40, 0xe0, 0xc0 }, { 0x40, 0xe0, 0xe0 },
1104         { 0x80, 0x00, 0x00 }, { 0x80, 0x00, 0x20 }, { 0x80, 0x00, 0x40 }, { 0x80, 0x00, 0x60 },
1105         { 0x80, 0x00, 0x80 }, { 0x80, 0x00, 0xa0 }, { 0x80, 0x00, 0xc0 }, { 0x80, 0x00, 0xe0 },
1106         { 0x80, 0x20, 0x00 }, { 0x80, 0x20, 0x20 }, { 0x80, 0x20, 0x40 }, { 0x80, 0x20, 0x60 },
1107         { 0x80, 0x20, 0x80 }, { 0x80, 0x20, 0xa0 }, { 0x80, 0x20, 0xc0 }, { 0x80, 0x20, 0xe0 },
1108         { 0x80, 0x40, 0x00 }, { 0x80, 0x40, 0x20 }, { 0x80, 0x40, 0x40 }, { 0x80, 0x40, 0x60 },
1109         { 0x80, 0x40, 0x80 }, { 0x80, 0x40, 0xa0 }, { 0x80, 0x40, 0xc0 }, { 0x80, 0x40, 0xe0 },
1110         { 0x80, 0x60, 0x00 }, { 0x80, 0x60, 0x20 }, { 0x80, 0x60, 0x40 }, { 0x80, 0x60, 0x60 },
1111         { 0x80, 0x60, 0x80 }, { 0x80, 0x60, 0xa0 }, { 0x80, 0x60, 0xc0 }, { 0x80, 0x60, 0xe0 },
1112         { 0x80, 0x80, 0x00 }, { 0x80, 0x80, 0x20 }, { 0x80, 0x80, 0x40 }, { 0x80, 0x80, 0x60 },
1113         { 0x80, 0x80, 0x80 }, { 0x80, 0x80, 0xa0 }, { 0x80, 0x80, 0xc0 }, { 0x80, 0x80, 0xe0 },
1114         { 0x80, 0xa0, 0x00 }, { 0x80, 0xa0, 0x20 }, { 0x80, 0xa0, 0x40 }, { 0x80, 0xa0, 0x60 },
1115         { 0x80, 0xa0, 0x80 }, { 0x80, 0xa0, 0xa0 }, { 0x80, 0xa0, 0xc0 }, { 0x80, 0xa0, 0xe0 },
1116         { 0x80, 0xc0, 0x00 }, { 0x80, 0xc0, 0x20 }, { 0x80, 0xc0, 0x40 }, { 0x80, 0xc0, 0x60 },
1117         { 0x80, 0xc0, 0x80 }, { 0x80, 0xc0, 0xa0 }, { 0x80, 0xc0, 0xc0 }, { 0x80, 0xc0, 0xe0 },
1118         { 0x80, 0xe0, 0x00 }, { 0x80, 0xe0, 0x20 }, { 0x80, 0xe0, 0x40 }, { 0x80, 0xe0, 0x60 },
1119         { 0x80, 0xe0, 0x80 }, { 0x80, 0xe0, 0xa0 }, { 0x80, 0xe0, 0xc0 }, { 0x80, 0xe0, 0xe0 },
1120         { 0xc0, 0x00, 0x00 }, { 0xc0, 0x00, 0x20 }, { 0xc0, 0x00, 0x40 }, { 0xc0, 0x00, 0x60 },
1121         { 0xc0, 0x00, 0x80 }, { 0xc0, 0x00, 0xa0 }, { 0xc0, 0x00, 0xc0 }, { 0xc0, 0x00, 0xe0 },
1122         { 0xc0, 0x20, 0x00 }, { 0xc0, 0x20, 0x20 }, { 0xc0, 0x20, 0x40 }, { 0xc0, 0x20, 0x60 },
1123         { 0xc0, 0x20, 0x80 }, { 0xc0, 0x20, 0xa0 }, { 0xc0, 0x20, 0xc0 }, { 0xc0, 0x20, 0xe0 },
1124         { 0xc0, 0x40, 0x00 }, { 0xc0, 0x40, 0x20 }, { 0xc0, 0x40, 0x40 }, { 0xc0, 0x40, 0x60 },
1125         { 0xc0, 0x40, 0x80 }, { 0xc0, 0x40, 0xa0 }, { 0xc0, 0x40, 0xc0 }, { 0xc0, 0x40, 0xe0 },
1126         { 0xc0, 0x60, 0x00 }, { 0xc0, 0x60, 0x20 }, { 0xc0, 0x60, 0x40 }, { 0xc0, 0x60, 0x60 },
1127         { 0xc0, 0x60, 0x80 }, { 0xc0, 0x60, 0xa0 }, { 0xc0, 0x60, 0xc0 }, { 0xc0, 0x60, 0xe0 },
1128         { 0xc0, 0x80, 0x00 }, { 0xc0, 0x80, 0x20 }, { 0xc0, 0x80, 0x40 }, { 0xc0, 0x80, 0x60 },
1129         { 0xc0, 0x80, 0x80 }, { 0xc0, 0x80, 0xa0 }, { 0xc0, 0x80, 0xc0 }, { 0xc0, 0x80, 0xe0 },
1130         { 0xc0, 0xa0, 0x00 }, { 0xc0, 0xa0, 0x20 }, { 0xc0, 0xa0, 0x40 }, { 0xc0, 0xa0, 0x60 },
1131         { 0xc0, 0xa0, 0x80 }, { 0xc0, 0xa0, 0xa0 }, { 0xc0, 0xa0, 0xc0 }, { 0xc0, 0xa0, 0xe0 },
1132         { 0xc0, 0xc0, 0x00 }, { 0xc0, 0xc0, 0x20 }, { 0xc0, 0xc0, 0x40 }, { 0xc0, 0xc0, 0x60 },
1133         { 0xc0, 0xc0, 0x80 }, { 0xc0, 0xc0, 0xa0 }, { 0xf0, 0xfb, 0xff }, { 0xa4, 0xa0, 0xa0 },
1134         { 0x80, 0x80, 0x80 }, { 0x00, 0x00, 0xff }, { 0x00, 0xff, 0x00 }, { 0x00, 0xff, 0xff },
1135         { 0xff, 0x00, 0x00 }, { 0xff, 0x00, 0xff }, { 0xff, 0xff, 0x00 }, { 0xff, 0xff, 0xff },
1136     };
1137
1138     switch (bpp)
1139     {
1140     case 1: return table_1;
1141     case 4: return table_4;
1142     case 8: return table_8;
1143     default: return NULL;
1144     }
1145 }
1146
1147 void fill_default_color_table( BITMAPINFO *info )
1148 {
1149     info->bmiHeader.biClrUsed = 1 << info->bmiHeader.biBitCount;
1150     memcpy( info->bmiColors, get_default_color_table( info->bmiHeader.biBitCount ),
1151             info->bmiHeader.biClrUsed * sizeof(RGBQUAD) );
1152 }
1153
1154 void get_ddb_bitmapinfo( BITMAPOBJ *bmp, BITMAPINFO *info )
1155 {
1156     info->bmiHeader.biSize          = sizeof(info->bmiHeader);
1157     info->bmiHeader.biWidth         = bmp->bitmap.bmWidth;
1158     info->bmiHeader.biHeight        = -bmp->bitmap.bmHeight;
1159     info->bmiHeader.biPlanes        = 1;
1160     info->bmiHeader.biBitCount      = bmp->bitmap.bmBitsPixel;
1161     info->bmiHeader.biCompression   = BI_RGB;
1162     info->bmiHeader.biXPelsPerMeter = 0;
1163     info->bmiHeader.biYPelsPerMeter = 0;
1164     info->bmiHeader.biClrUsed       = 0;
1165     info->bmiHeader.biClrImportant  = 0;
1166 }
1167
1168 BITMAPINFO *copy_packed_dib( const BITMAPINFO *src_info, UINT usage )
1169 {
1170     char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1171     BITMAPINFO *ret, *info = (BITMAPINFO *)buffer;
1172     unsigned int info_size;
1173
1174     if (!bitmapinfo_from_user_bitmapinfo( info, src_info, usage, FALSE )) return NULL;
1175
1176     info_size = get_dib_info_size( info, usage );
1177     if ((ret = HeapAlloc( GetProcessHeap(), 0, info_size + info->bmiHeader.biSizeImage )))
1178     {
1179         memcpy( ret, info, info_size );
1180         memcpy( (char *)ret + info_size, (char *)src_info + bitmap_info_size( src_info, usage ),
1181                 info->bmiHeader.biSizeImage );
1182     }
1183     return ret;
1184 }
1185
1186 /******************************************************************************
1187  * GetDIBits [GDI32.@]
1188  *
1189  * Retrieves bits of bitmap and copies to buffer.
1190  *
1191  * RETURNS
1192  *    Success: Number of scan lines copied from bitmap
1193  *    Failure: 0
1194  */
1195 INT WINAPI GetDIBits(
1196     HDC hdc,         /* [in]  Handle to device context */
1197     HBITMAP hbitmap, /* [in]  Handle to bitmap */
1198     UINT startscan,  /* [in]  First scan line to set in dest bitmap */
1199     UINT lines,      /* [in]  Number of scan lines to copy */
1200     LPVOID bits,       /* [out] Address of array for bitmap bits */
1201     BITMAPINFO * info, /* [out] Address of structure with bitmap data */
1202     UINT coloruse)   /* [in]  RGB or palette index */
1203 {
1204     DC * dc;
1205     BITMAPOBJ * bmp;
1206     int i, dst_to_src_offset, ret = 0;
1207     DWORD err;
1208     char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1209     BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf;
1210     char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1211     BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
1212     struct gdi_image_bits src_bits;
1213     struct bitblt_coords src, dst;
1214     BOOL empty_rect = FALSE;
1215
1216     /* Since info may be a BITMAPCOREINFO or any of the larger BITMAPINFO structures, we'll use our
1217        own copy and transfer the colour info back at the end */
1218     if (!bitmapinfoheader_from_user_bitmapinfo( &dst_info->bmiHeader, &info->bmiHeader )) return 0;
1219     if (coloruse > DIB_PAL_COLORS) return 0;
1220     if (bits &&
1221         (dst_info->bmiHeader.biCompression == BI_JPEG || dst_info->bmiHeader.biCompression == BI_PNG))
1222         return 0;
1223     dst_info->bmiHeader.biClrUsed = 0;
1224     dst_info->bmiHeader.biClrImportant = 0;
1225
1226     if (!(dc = get_dc_ptr( hdc )))
1227     {
1228         SetLastError( ERROR_INVALID_PARAMETER );
1229         return 0;
1230     }
1231     update_dc( dc );
1232     if (!(bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
1233     {
1234         release_dc_ptr( dc );
1235         return 0;
1236     }
1237
1238     src.visrect.left   = 0;
1239     src.visrect.top    = 0;
1240     src.visrect.right  = bmp->bitmap.bmWidth;
1241     src.visrect.bottom = bmp->bitmap.bmHeight;
1242
1243     dst.visrect.left   = 0;
1244     dst.visrect.top    = 0;
1245     dst.visrect.right  = dst_info->bmiHeader.biWidth;
1246     dst.visrect.bottom = abs( dst_info->bmiHeader.biHeight );
1247
1248     if (lines == 0 || startscan >= dst.visrect.bottom)
1249         bits = NULL;
1250
1251     if (!bits && dst_info->bmiHeader.biBitCount == 0) /* query bitmap info only */
1252     {
1253         ret = fill_query_info( info, bmp );
1254         goto done;
1255     }
1256
1257     /* validate parameters */
1258
1259     if (dst_info->bmiHeader.biWidth <= 0) goto done;
1260     if (dst_info->bmiHeader.biHeight == 0) goto done;
1261
1262     switch (dst_info->bmiHeader.biCompression)
1263     {
1264     case BI_RLE4:
1265         if (dst_info->bmiHeader.biBitCount != 4) 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_RLE8:
1270         if (dst_info->bmiHeader.biBitCount != 8) goto done;
1271         if (dst_info->bmiHeader.biHeight < 0) goto done;
1272         if (bits) goto done;  /* can't retrieve compressed bits */
1273         break;
1274     case BI_BITFIELDS:
1275         if (dst_info->bmiHeader.biBitCount != 16 && dst_info->bmiHeader.biBitCount != 32) goto done;
1276         /* fall through */
1277     case BI_RGB:
1278         if (lines && !dst_info->bmiHeader.biPlanes) goto done;
1279         if (dst_info->bmiHeader.biBitCount == 1) break;
1280         if (dst_info->bmiHeader.biBitCount == 4) break;
1281         if (dst_info->bmiHeader.biBitCount == 8) break;
1282         if (dst_info->bmiHeader.biBitCount == 16) break;
1283         if (dst_info->bmiHeader.biBitCount == 24) break;
1284         if (dst_info->bmiHeader.biBitCount == 32) break;
1285         /* fall through */
1286     default:
1287         goto done;
1288     }
1289
1290     if (bits)
1291     {
1292         if (dst_info->bmiHeader.biHeight > 0)
1293         {
1294             dst_to_src_offset = -startscan;
1295             lines = min( lines, dst.visrect.bottom - startscan );
1296             if (lines < dst.visrect.bottom) dst.visrect.top = dst.visrect.bottom - lines;
1297         }
1298         else
1299         {
1300             dst_to_src_offset = dst.visrect.bottom - lines - startscan;
1301             if (dst_to_src_offset < 0)
1302             {
1303                 dst_to_src_offset = 0;
1304                 lines = dst.visrect.bottom - startscan;
1305             }
1306             if (lines < dst.visrect.bottom) dst.visrect.bottom = lines;
1307         }
1308
1309         offset_rect( &dst.visrect, 0, dst_to_src_offset );
1310         empty_rect = !intersect_rect( &src.visrect, &src.visrect, &dst.visrect );
1311         dst.visrect = src.visrect;
1312         offset_rect( &dst.visrect, 0, -dst_to_src_offset );
1313
1314         if (dst_info->bmiHeader.biHeight > 0)
1315         {
1316             if (dst.visrect.bottom < dst_info->bmiHeader.biHeight)
1317             {
1318                 int pad_lines = min( dst_info->bmiHeader.biHeight - dst.visrect.bottom, lines );
1319                 int pad_bytes = pad_lines * get_dib_stride( dst_info->bmiHeader.biWidth, dst_info->bmiHeader.biBitCount );
1320                 memset( bits, 0, pad_bytes );
1321                 bits = (char *)bits + pad_bytes;
1322             }
1323         }
1324         else
1325         {
1326             if (dst.visrect.bottom < lines)
1327             {
1328                 int pad_lines = lines - dst.visrect.bottom;
1329                 int stride = get_dib_stride( dst_info->bmiHeader.biWidth, dst_info->bmiHeader.biBitCount );
1330                 int pad_bytes = pad_lines * stride;
1331                 memset( (char *)bits + dst.visrect.bottom * stride, 0, pad_bytes );
1332             }
1333         }
1334
1335         if (empty_rect) bits = NULL;
1336
1337         src.x      = src.visrect.left;
1338         src.y      = src.visrect.top;
1339         src.width  = src.visrect.right - src.visrect.left;
1340         src.height = src.visrect.bottom - src.visrect.top;
1341
1342         lines = src.height;
1343     }
1344
1345     err = bmp->funcs->pGetImage( NULL, hbitmap, src_info, bits ? &src_bits : NULL, bits ? &src : NULL );
1346
1347     if (err) goto done;
1348
1349     /* fill out the src colour table, if it needs one */
1350     if (src_info->bmiHeader.biBitCount <= 8 && src_info->bmiHeader.biClrUsed == 0)
1351         fill_default_color_table( src_info );
1352
1353     /* if the src and dst are the same depth, copy the colour info across */
1354     if (dst_info->bmiHeader.biBitCount == src_info->bmiHeader.biBitCount && coloruse == DIB_RGB_COLORS )
1355     {
1356         switch (src_info->bmiHeader.biBitCount)
1357         {
1358         case 16:
1359             if (src_info->bmiHeader.biCompression == BI_RGB)
1360             {
1361                 src_info->bmiHeader.biCompression = BI_BITFIELDS;
1362                 memcpy( src_info->bmiColors, bit_fields_555, sizeof(bit_fields_555) );
1363             }
1364             break;
1365         case 32:
1366             if (src_info->bmiHeader.biCompression == BI_RGB)
1367             {
1368                 src_info->bmiHeader.biCompression = BI_BITFIELDS;
1369                 memcpy( src_info->bmiColors, bit_fields_888, sizeof(bit_fields_888) );
1370             }
1371             break;
1372         }
1373         src_info->bmiHeader.biSizeImage = get_dib_image_size( dst_info );
1374         copy_color_info( dst_info, src_info, coloruse );
1375     }
1376     else if (dst_info->bmiHeader.biBitCount <= 8) /* otherwise construct a default colour table for the dst, if needed */
1377     {
1378         if( coloruse == DIB_PAL_COLORS )
1379         {
1380             if (!fill_color_table_from_palette( dst_info, hdc )) goto done;
1381         }
1382         else
1383         {
1384             fill_default_color_table( dst_info );
1385         }
1386     }
1387
1388     if (bits)
1389     {
1390         if(dst_info->bmiHeader.biHeight > 0)
1391             dst_info->bmiHeader.biHeight = src.height;
1392         else
1393             dst_info->bmiHeader.biHeight = -src.height;
1394
1395         convert_bitmapinfo( src_info, src_bits.ptr, &src, dst_info, bits, FALSE );
1396         if (src_bits.free) src_bits.free( &src_bits );
1397         ret = lines;
1398     }
1399     else
1400         ret = empty_rect ? FALSE : TRUE;
1401
1402     if (coloruse == DIB_PAL_COLORS)
1403     {
1404         WORD *index = (WORD *)dst_info->bmiColors;
1405         for (i = 0; i < dst_info->bmiHeader.biClrUsed; i++, index++)
1406             *index = i;
1407     }
1408
1409     copy_color_info( info, dst_info, coloruse );
1410     if (info->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) info->bmiHeader.biClrUsed = 0;
1411
1412 done:
1413     release_dc_ptr( dc );
1414     GDI_ReleaseObj( hbitmap );
1415     return ret;
1416 }
1417
1418
1419 /***********************************************************************
1420  *           CreateDIBitmap    (GDI32.@)
1421  *
1422  * Creates a DDB (device dependent bitmap) from a DIB.
1423  * The DDB will have the same color depth as the reference DC.
1424  */
1425 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
1426                             DWORD init, LPCVOID bits, const BITMAPINFO *data,
1427                             UINT coloruse )
1428 {
1429     BITMAPINFOHEADER info;
1430     HBITMAP handle;
1431     LONG height;
1432
1433     if (!bitmapinfoheader_from_user_bitmapinfo( &info, header )) return 0;
1434     if (info.biCompression == BI_JPEG || info.biCompression == BI_PNG) return 0;
1435     if (coloruse > DIB_PAL_COLORS + 1) return 0;
1436     if (info.biWidth < 0) return 0;
1437
1438     /* Top-down DIBs have a negative height */
1439     height = abs( info.biHeight );
1440
1441     TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1442           hdc, header, init, bits, data, coloruse, info.biWidth, info.biHeight,
1443           info.biBitCount, info.biCompression);
1444
1445     if (hdc == NULL)
1446         handle = CreateBitmap( info.biWidth, height, 1, 1, NULL );
1447     else
1448         handle = CreateCompatibleBitmap( hdc, info.biWidth, height );
1449
1450     if (handle)
1451     {
1452         if (init & CBM_INIT)
1453         {
1454             if (SetDIBits( hdc, handle, 0, height, bits, data, coloruse ) == 0)
1455             {
1456                 DeleteObject( handle );
1457                 handle = 0;
1458             }
1459         }
1460     }
1461
1462     return handle;
1463 }
1464
1465
1466 /***********************************************************************
1467  *           CreateDIBSection    (GDI32.@)
1468  */
1469 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1470                                 VOID **bits, HANDLE section, DWORD offset)
1471 {
1472     char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1473     BITMAPINFO *info = (BITMAPINFO *)buffer;
1474     HBITMAP ret = 0;
1475     DIBSECTION *dib;
1476     BITMAPOBJ *bmp;
1477     void *mapBits = NULL;
1478
1479     if (bits) *bits = NULL;
1480     if (!bitmapinfo_from_user_bitmapinfo( info, bmi, usage, FALSE )) return 0;
1481     if (usage > DIB_PAL_COLORS) return 0;
1482     if (info->bmiHeader.biPlanes != 1)
1483     {
1484         if (info->bmiHeader.biPlanes * info->bmiHeader.biBitCount > 16) return 0;
1485         WARN( "%u planes not properly supported\n", info->bmiHeader.biPlanes );
1486     }
1487
1488     if (!(bmp = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*bmp) ))) return 0;
1489     if (!(dib = HeapAlloc( GetProcessHeap(), 0, sizeof(*dib) ))) goto error;
1490
1491     TRACE("format (%d,%d), planes %d, bpp %d, %s, size %d %s\n",
1492           info->bmiHeader.biWidth, info->bmiHeader.biHeight,
1493           info->bmiHeader.biPlanes, info->bmiHeader.biBitCount,
1494           info->bmiHeader.biCompression == BI_BITFIELDS? "BI_BITFIELDS" : "BI_RGB",
1495           info->bmiHeader.biSizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1496
1497     dib->dsBm.bmType       = 0;
1498     dib->dsBm.bmWidth      = info->bmiHeader.biWidth;
1499     dib->dsBm.bmHeight     = abs( info->bmiHeader.biHeight );
1500     dib->dsBm.bmWidthBytes = get_dib_stride( info->bmiHeader.biWidth, info->bmiHeader.biBitCount );
1501     dib->dsBm.bmPlanes     = info->bmiHeader.biPlanes;
1502     dib->dsBm.bmBitsPixel  = info->bmiHeader.biBitCount;
1503     dib->dsBm.bmBits       = NULL;
1504     dib->dsBmih            = info->bmiHeader;
1505
1506     bmp->funcs = &dib_driver;
1507     bmp->dib = dib;
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 (!(bmp->color_table = HeapAlloc( GetProcessHeap(), 0, dib->dsBmih.biClrUsed*sizeof(RGBQUAD) )))
1515             goto error;
1516         memcpy( bmp->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     bmp->bitmap = dib->dsBm;
1563     bmp->bitmap.bmWidthBytes = get_bitmap_stride( info->bmiHeader.biWidth, info->bmiHeader.biBitCount );
1564     bmp->bitmap.bmBits = NULL;
1565
1566     if (!(ret = alloc_gdi_handle( &bmp->header, OBJ_BITMAP, &dib_funcs ))) goto error;
1567
1568     if (bits) *bits = dib->dsBm.bmBits;
1569     return ret;
1570
1571 error:
1572     if (section) UnmapViewOfFile( mapBits );
1573     else VirtualFree( dib->dsBm.bmBits, 0, MEM_RELEASE );
1574     HeapFree( GetProcessHeap(), 0, bmp->color_table );
1575     HeapFree( GetProcessHeap(), 0, dib );
1576     HeapFree( GetProcessHeap(), 0, bmp );
1577     return 0;
1578 }
1579
1580
1581 /***********************************************************************
1582  *           DIB_SelectObject
1583  */
1584 static HGDIOBJ DIB_SelectObject( HGDIOBJ handle, HDC hdc )
1585 {
1586     HGDIOBJ ret;
1587     BITMAPOBJ *bitmap;
1588     DC *dc;
1589     PHYSDEV physdev = NULL, old_physdev = NULL, pathdev = NULL;
1590
1591     if (!(dc = get_dc_ptr( hdc ))) return 0;
1592
1593     if (GetObjectType( hdc ) != OBJ_MEMDC)
1594     {
1595         ret = 0;
1596         goto done;
1597     }
1598     ret = dc->hBitmap;
1599     if (handle == dc->hBitmap) goto done;  /* nothing to do */
1600
1601     if (!(bitmap = GDI_GetObjPtr( handle, OBJ_BITMAP )))
1602     {
1603         ret = 0;
1604         goto done;
1605     }
1606
1607     if (bitmap->header.selcount)
1608     {
1609         WARN( "Bitmap already selected in another DC\n" );
1610         GDI_ReleaseObj( handle );
1611         ret = 0;
1612         goto done;
1613     }
1614
1615     if (dc->physDev->funcs == &path_driver) pathdev = pop_dc_driver( &dc->physDev );
1616
1617     old_physdev = GET_DC_PHYSDEV( dc, pSelectBitmap );
1618     physdev = dc->dibdrv;
1619     if (old_physdev != dc->dibdrv)
1620     {
1621         if (physdev) push_dc_driver( &dc->physDev, physdev, physdev->funcs );
1622         else
1623         {
1624             if (!dib_driver.pCreateDC( &dc->physDev, NULL, NULL, NULL, NULL )) goto done;
1625             dc->dibdrv = physdev = dc->physDev;
1626         }
1627     }
1628
1629     if (!physdev->funcs->pSelectBitmap( physdev, handle ))
1630     {
1631         GDI_ReleaseObj( handle );
1632         ret = 0;
1633     }
1634     else
1635     {
1636         dc->hBitmap = handle;
1637         GDI_inc_ref_count( handle );
1638         dc->dirty = 0;
1639         dc->vis_rect.left   = 0;
1640         dc->vis_rect.top    = 0;
1641         dc->vis_rect.right  = bitmap->bitmap.bmWidth;
1642         dc->vis_rect.bottom = bitmap->bitmap.bmHeight;
1643         GDI_ReleaseObj( handle );
1644         DC_InitDC( dc );
1645         GDI_dec_ref_count( ret );
1646     }
1647
1648  done:
1649     if(!ret)
1650     {
1651         if (old_physdev && old_physdev != dc->dibdrv) pop_dc_driver( &dc->physDev );
1652     }
1653     if (pathdev) push_dc_driver( &dc->physDev, pathdev, pathdev->funcs );
1654     release_dc_ptr( dc );
1655     return ret;
1656 }
1657
1658
1659 /***********************************************************************
1660  *           DIB_GetObject
1661  */
1662 static INT DIB_GetObject( HGDIOBJ handle, INT count, LPVOID buffer )
1663 {
1664     INT ret = 0;
1665     BITMAPOBJ *bmp = GDI_GetObjPtr( handle, OBJ_BITMAP );
1666
1667     if (!bmp) return 0;
1668
1669     if (!buffer) ret = sizeof(BITMAP);
1670     else if (count >= sizeof(DIBSECTION))
1671     {
1672         DIBSECTION *dib = buffer;
1673         *dib = *bmp->dib;
1674         dib->dsBmih.biHeight = abs( dib->dsBmih.biHeight );
1675         ret = sizeof(DIBSECTION);
1676     }
1677     else if (count >= sizeof(BITMAP))
1678     {
1679         BITMAP *bitmap = buffer;
1680         *bitmap = bmp->dib->dsBm;
1681         ret = sizeof(BITMAP);
1682     }
1683
1684     GDI_ReleaseObj( handle );
1685     return ret;
1686 }
1687
1688
1689 /***********************************************************************
1690  *           DIB_DeleteObject
1691  */
1692 static BOOL DIB_DeleteObject( HGDIOBJ handle )
1693 {
1694     BITMAPOBJ *bmp;
1695
1696     if (!(bmp = free_gdi_handle( handle ))) return FALSE;
1697
1698     if (bmp->dib->dshSection)
1699     {
1700         SYSTEM_INFO SystemInfo;
1701         GetSystemInfo( &SystemInfo );
1702         UnmapViewOfFile( (char *)bmp->dib->dsBm.bmBits -
1703                          (bmp->dib->dsOffset % SystemInfo.dwAllocationGranularity) );
1704     }
1705     else VirtualFree( bmp->dib->dsBm.bmBits, 0, MEM_RELEASE );
1706
1707     HeapFree(GetProcessHeap(), 0, bmp->dib);
1708     HeapFree(GetProcessHeap(), 0, bmp->color_table);
1709     return HeapFree( GetProcessHeap(), 0, bmp );
1710 }