gdi32: Add a GetBoundsRect driver entry point.
[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->dib.dsBm.bmWidth;
697     dst.visrect.bottom = bitmap->dib.dsBm.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         if (startpos < bitmap->dib.dsBmih.biClrUsed)
912         {
913             result = min( entries, bitmap->dib.dsBmih.biClrUsed - startpos );
914             memcpy(bitmap->color_table + startpos, colors, result * sizeof(RGBQUAD));
915         }
916         GDI_ReleaseObj( dc->hBitmap );
917
918         if (result)  /* update colors of selected objects */
919         {
920             SetTextColor( hdc, dc->textColor );
921             SetBkColor( hdc, dc->backgroundColor );
922             SelectObject( hdc, dc->hPen );
923             SelectObject( hdc, dc->hBrush );
924         }
925     }
926     release_dc_ptr( dc );
927     return result;
928 }
929
930
931 /***********************************************************************
932  *           GetDIBColorTable    (GDI32.@)
933  */
934 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
935 {
936     DC * dc;
937     BITMAPOBJ *bitmap;
938     UINT result = 0;
939
940     if (!(dc = get_dc_ptr( hdc ))) return 0;
941
942     if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
943     {
944         if (startpos < bitmap->dib.dsBmih.biClrUsed)
945         {
946             result = min( entries, bitmap->dib.dsBmih.biClrUsed - startpos );
947             memcpy(colors, bitmap->color_table + startpos, result * sizeof(RGBQUAD));
948         }
949         GDI_ReleaseObj( dc->hBitmap );
950     }
951     release_dc_ptr( dc );
952     return result;
953 }
954
955 static const DWORD bit_fields_888[3] = {0xff0000, 0x00ff00, 0x0000ff};
956 static const DWORD bit_fields_565[3] = {0xf800, 0x07e0, 0x001f};
957 static const DWORD bit_fields_555[3] = {0x7c00, 0x03e0, 0x001f};
958
959 static int fill_query_info( BITMAPINFO *info, BITMAPOBJ *bmp )
960 {
961     BITMAPINFOHEADER header;
962
963     header.biSize   = info->bmiHeader.biSize; /* Ensure we don't overwrite the original size when we copy back */
964     header.biWidth  = bmp->dib.dsBm.bmWidth;
965     header.biHeight = bmp->dib.dsBm.bmHeight;
966     header.biPlanes = 1;
967     header.biBitCount = bmp->dib.dsBm.bmBitsPixel;
968
969     switch (header.biBitCount)
970     {
971     case 16:
972     case 32:
973         header.biCompression = BI_BITFIELDS;
974         break;
975     default:
976         header.biCompression = BI_RGB;
977         break;
978     }
979
980     header.biSizeImage = get_dib_image_size( (BITMAPINFO *)&header );
981     header.biXPelsPerMeter = 0;
982     header.biYPelsPerMeter = 0;
983     header.biClrUsed       = 0;
984     header.biClrImportant  = 0;
985
986     if ( info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER) )
987     {
988         BITMAPCOREHEADER *coreheader = (BITMAPCOREHEADER *)info;
989
990         coreheader->bcWidth    = header.biWidth;
991         coreheader->bcHeight   = header.biHeight;
992         coreheader->bcPlanes   = header.biPlanes;
993         coreheader->bcBitCount = header.biBitCount;
994     }
995     else
996         info->bmiHeader = header;
997
998     return bmp->dib.dsBm.bmHeight;
999 }
1000
1001 /************************************************************************
1002  *      copy_color_info
1003  *
1004  * Copy BITMAPINFO color information where dst may be a BITMAPCOREINFO.
1005  */
1006 static void copy_color_info(BITMAPINFO *dst, const BITMAPINFO *src, UINT coloruse)
1007 {
1008     assert( src->bmiHeader.biSize == sizeof(BITMAPINFOHEADER) );
1009
1010     if (dst->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1011     {
1012         BITMAPCOREINFO *core = (BITMAPCOREINFO *)dst;
1013         if (coloruse == DIB_PAL_COLORS)
1014             memcpy( core->bmciColors, src->bmiColors, src->bmiHeader.biClrUsed * sizeof(WORD) );
1015         else
1016         {
1017             unsigned int i;
1018             for (i = 0; i < src->bmiHeader.biClrUsed; i++)
1019             {
1020                 core->bmciColors[i].rgbtRed   = src->bmiColors[i].rgbRed;
1021                 core->bmciColors[i].rgbtGreen = src->bmiColors[i].rgbGreen;
1022                 core->bmciColors[i].rgbtBlue  = src->bmiColors[i].rgbBlue;
1023             }
1024         }
1025     }
1026     else
1027     {
1028         dst->bmiHeader.biClrUsed   = src->bmiHeader.biClrUsed;
1029         dst->bmiHeader.biSizeImage = src->bmiHeader.biSizeImage;
1030
1031         if (src->bmiHeader.biCompression == BI_BITFIELDS)
1032             /* bitfields are always at bmiColors even in larger structures */
1033             memcpy( dst->bmiColors, src->bmiColors, 3 * sizeof(DWORD) );
1034         else if (src->bmiHeader.biClrUsed)
1035         {
1036             void *colorptr = (char *)dst + dst->bmiHeader.biSize;
1037             unsigned int size;
1038
1039             if (coloruse == DIB_PAL_COLORS)
1040                 size = src->bmiHeader.biClrUsed * sizeof(WORD);
1041             else
1042                 size = src->bmiHeader.biClrUsed * sizeof(RGBQUAD);
1043             memcpy( colorptr, src->bmiColors, size );
1044         }
1045     }
1046 }
1047
1048 const RGBQUAD *get_default_color_table( int bpp )
1049 {
1050     static const RGBQUAD table_1[2] =
1051     {
1052         { 0x00, 0x00, 0x00 }, { 0xff, 0xff, 0xff }
1053     };
1054     static const RGBQUAD table_4[16] =
1055     {
1056         { 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x80 }, { 0x00, 0x80, 0x00 }, { 0x00, 0x80, 0x80 },
1057         { 0x80, 0x00, 0x00 }, { 0x80, 0x00, 0x80 }, { 0x80, 0x80, 0x00 }, { 0x80, 0x80, 0x80 },
1058         { 0xc0, 0xc0, 0xc0 }, { 0x00, 0x00, 0xff }, { 0x00, 0xff, 0x00 }, { 0x00, 0xff, 0xff },
1059         { 0xff, 0x00, 0x00 }, { 0xff, 0x00, 0xff }, { 0xff, 0xff, 0x00 }, { 0xff, 0xff, 0xff },
1060     };
1061     static const RGBQUAD table_8[256] =
1062     {
1063         /* first and last 10 entries are the default system palette entries */
1064         { 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x80 }, { 0x00, 0x80, 0x00 }, { 0x00, 0x80, 0x80 },
1065         { 0x80, 0x00, 0x00 }, { 0x80, 0x00, 0x80 }, { 0x80, 0x80, 0x00 }, { 0xc0, 0xc0, 0xc0 },
1066         { 0xc0, 0xdc, 0xc0 }, { 0xf0, 0xca, 0xa6 }, { 0x00, 0x20, 0x40 }, { 0x00, 0x20, 0x60 },
1067         { 0x00, 0x20, 0x80 }, { 0x00, 0x20, 0xa0 }, { 0x00, 0x20, 0xc0 }, { 0x00, 0x20, 0xe0 },
1068         { 0x00, 0x40, 0x00 }, { 0x00, 0x40, 0x20 }, { 0x00, 0x40, 0x40 }, { 0x00, 0x40, 0x60 },
1069         { 0x00, 0x40, 0x80 }, { 0x00, 0x40, 0xa0 }, { 0x00, 0x40, 0xc0 }, { 0x00, 0x40, 0xe0 },
1070         { 0x00, 0x60, 0x00 }, { 0x00, 0x60, 0x20 }, { 0x00, 0x60, 0x40 }, { 0x00, 0x60, 0x60 },
1071         { 0x00, 0x60, 0x80 }, { 0x00, 0x60, 0xa0 }, { 0x00, 0x60, 0xc0 }, { 0x00, 0x60, 0xe0 },
1072         { 0x00, 0x80, 0x00 }, { 0x00, 0x80, 0x20 }, { 0x00, 0x80, 0x40 }, { 0x00, 0x80, 0x60 },
1073         { 0x00, 0x80, 0x80 }, { 0x00, 0x80, 0xa0 }, { 0x00, 0x80, 0xc0 }, { 0x00, 0x80, 0xe0 },
1074         { 0x00, 0xa0, 0x00 }, { 0x00, 0xa0, 0x20 }, { 0x00, 0xa0, 0x40 }, { 0x00, 0xa0, 0x60 },
1075         { 0x00, 0xa0, 0x80 }, { 0x00, 0xa0, 0xa0 }, { 0x00, 0xa0, 0xc0 }, { 0x00, 0xa0, 0xe0 },
1076         { 0x00, 0xc0, 0x00 }, { 0x00, 0xc0, 0x20 }, { 0x00, 0xc0, 0x40 }, { 0x00, 0xc0, 0x60 },
1077         { 0x00, 0xc0, 0x80 }, { 0x00, 0xc0, 0xa0 }, { 0x00, 0xc0, 0xc0 }, { 0x00, 0xc0, 0xe0 },
1078         { 0x00, 0xe0, 0x00 }, { 0x00, 0xe0, 0x20 }, { 0x00, 0xe0, 0x40 }, { 0x00, 0xe0, 0x60 },
1079         { 0x00, 0xe0, 0x80 }, { 0x00, 0xe0, 0xa0 }, { 0x00, 0xe0, 0xc0 }, { 0x00, 0xe0, 0xe0 },
1080         { 0x40, 0x00, 0x00 }, { 0x40, 0x00, 0x20 }, { 0x40, 0x00, 0x40 }, { 0x40, 0x00, 0x60 },
1081         { 0x40, 0x00, 0x80 }, { 0x40, 0x00, 0xa0 }, { 0x40, 0x00, 0xc0 }, { 0x40, 0x00, 0xe0 },
1082         { 0x40, 0x20, 0x00 }, { 0x40, 0x20, 0x20 }, { 0x40, 0x20, 0x40 }, { 0x40, 0x20, 0x60 },
1083         { 0x40, 0x20, 0x80 }, { 0x40, 0x20, 0xa0 }, { 0x40, 0x20, 0xc0 }, { 0x40, 0x20, 0xe0 },
1084         { 0x40, 0x40, 0x00 }, { 0x40, 0x40, 0x20 }, { 0x40, 0x40, 0x40 }, { 0x40, 0x40, 0x60 },
1085         { 0x40, 0x40, 0x80 }, { 0x40, 0x40, 0xa0 }, { 0x40, 0x40, 0xc0 }, { 0x40, 0x40, 0xe0 },
1086         { 0x40, 0x60, 0x00 }, { 0x40, 0x60, 0x20 }, { 0x40, 0x60, 0x40 }, { 0x40, 0x60, 0x60 },
1087         { 0x40, 0x60, 0x80 }, { 0x40, 0x60, 0xa0 }, { 0x40, 0x60, 0xc0 }, { 0x40, 0x60, 0xe0 },
1088         { 0x40, 0x80, 0x00 }, { 0x40, 0x80, 0x20 }, { 0x40, 0x80, 0x40 }, { 0x40, 0x80, 0x60 },
1089         { 0x40, 0x80, 0x80 }, { 0x40, 0x80, 0xa0 }, { 0x40, 0x80, 0xc0 }, { 0x40, 0x80, 0xe0 },
1090         { 0x40, 0xa0, 0x00 }, { 0x40, 0xa0, 0x20 }, { 0x40, 0xa0, 0x40 }, { 0x40, 0xa0, 0x60 },
1091         { 0x40, 0xa0, 0x80 }, { 0x40, 0xa0, 0xa0 }, { 0x40, 0xa0, 0xc0 }, { 0x40, 0xa0, 0xe0 },
1092         { 0x40, 0xc0, 0x00 }, { 0x40, 0xc0, 0x20 }, { 0x40, 0xc0, 0x40 }, { 0x40, 0xc0, 0x60 },
1093         { 0x40, 0xc0, 0x80 }, { 0x40, 0xc0, 0xa0 }, { 0x40, 0xc0, 0xc0 }, { 0x40, 0xc0, 0xe0 },
1094         { 0x40, 0xe0, 0x00 }, { 0x40, 0xe0, 0x20 }, { 0x40, 0xe0, 0x40 }, { 0x40, 0xe0, 0x60 },
1095         { 0x40, 0xe0, 0x80 }, { 0x40, 0xe0, 0xa0 }, { 0x40, 0xe0, 0xc0 }, { 0x40, 0xe0, 0xe0 },
1096         { 0x80, 0x00, 0x00 }, { 0x80, 0x00, 0x20 }, { 0x80, 0x00, 0x40 }, { 0x80, 0x00, 0x60 },
1097         { 0x80, 0x00, 0x80 }, { 0x80, 0x00, 0xa0 }, { 0x80, 0x00, 0xc0 }, { 0x80, 0x00, 0xe0 },
1098         { 0x80, 0x20, 0x00 }, { 0x80, 0x20, 0x20 }, { 0x80, 0x20, 0x40 }, { 0x80, 0x20, 0x60 },
1099         { 0x80, 0x20, 0x80 }, { 0x80, 0x20, 0xa0 }, { 0x80, 0x20, 0xc0 }, { 0x80, 0x20, 0xe0 },
1100         { 0x80, 0x40, 0x00 }, { 0x80, 0x40, 0x20 }, { 0x80, 0x40, 0x40 }, { 0x80, 0x40, 0x60 },
1101         { 0x80, 0x40, 0x80 }, { 0x80, 0x40, 0xa0 }, { 0x80, 0x40, 0xc0 }, { 0x80, 0x40, 0xe0 },
1102         { 0x80, 0x60, 0x00 }, { 0x80, 0x60, 0x20 }, { 0x80, 0x60, 0x40 }, { 0x80, 0x60, 0x60 },
1103         { 0x80, 0x60, 0x80 }, { 0x80, 0x60, 0xa0 }, { 0x80, 0x60, 0xc0 }, { 0x80, 0x60, 0xe0 },
1104         { 0x80, 0x80, 0x00 }, { 0x80, 0x80, 0x20 }, { 0x80, 0x80, 0x40 }, { 0x80, 0x80, 0x60 },
1105         { 0x80, 0x80, 0x80 }, { 0x80, 0x80, 0xa0 }, { 0x80, 0x80, 0xc0 }, { 0x80, 0x80, 0xe0 },
1106         { 0x80, 0xa0, 0x00 }, { 0x80, 0xa0, 0x20 }, { 0x80, 0xa0, 0x40 }, { 0x80, 0xa0, 0x60 },
1107         { 0x80, 0xa0, 0x80 }, { 0x80, 0xa0, 0xa0 }, { 0x80, 0xa0, 0xc0 }, { 0x80, 0xa0, 0xe0 },
1108         { 0x80, 0xc0, 0x00 }, { 0x80, 0xc0, 0x20 }, { 0x80, 0xc0, 0x40 }, { 0x80, 0xc0, 0x60 },
1109         { 0x80, 0xc0, 0x80 }, { 0x80, 0xc0, 0xa0 }, { 0x80, 0xc0, 0xc0 }, { 0x80, 0xc0, 0xe0 },
1110         { 0x80, 0xe0, 0x00 }, { 0x80, 0xe0, 0x20 }, { 0x80, 0xe0, 0x40 }, { 0x80, 0xe0, 0x60 },
1111         { 0x80, 0xe0, 0x80 }, { 0x80, 0xe0, 0xa0 }, { 0x80, 0xe0, 0xc0 }, { 0x80, 0xe0, 0xe0 },
1112         { 0xc0, 0x00, 0x00 }, { 0xc0, 0x00, 0x20 }, { 0xc0, 0x00, 0x40 }, { 0xc0, 0x00, 0x60 },
1113         { 0xc0, 0x00, 0x80 }, { 0xc0, 0x00, 0xa0 }, { 0xc0, 0x00, 0xc0 }, { 0xc0, 0x00, 0xe0 },
1114         { 0xc0, 0x20, 0x00 }, { 0xc0, 0x20, 0x20 }, { 0xc0, 0x20, 0x40 }, { 0xc0, 0x20, 0x60 },
1115         { 0xc0, 0x20, 0x80 }, { 0xc0, 0x20, 0xa0 }, { 0xc0, 0x20, 0xc0 }, { 0xc0, 0x20, 0xe0 },
1116         { 0xc0, 0x40, 0x00 }, { 0xc0, 0x40, 0x20 }, { 0xc0, 0x40, 0x40 }, { 0xc0, 0x40, 0x60 },
1117         { 0xc0, 0x40, 0x80 }, { 0xc0, 0x40, 0xa0 }, { 0xc0, 0x40, 0xc0 }, { 0xc0, 0x40, 0xe0 },
1118         { 0xc0, 0x60, 0x00 }, { 0xc0, 0x60, 0x20 }, { 0xc0, 0x60, 0x40 }, { 0xc0, 0x60, 0x60 },
1119         { 0xc0, 0x60, 0x80 }, { 0xc0, 0x60, 0xa0 }, { 0xc0, 0x60, 0xc0 }, { 0xc0, 0x60, 0xe0 },
1120         { 0xc0, 0x80, 0x00 }, { 0xc0, 0x80, 0x20 }, { 0xc0, 0x80, 0x40 }, { 0xc0, 0x80, 0x60 },
1121         { 0xc0, 0x80, 0x80 }, { 0xc0, 0x80, 0xa0 }, { 0xc0, 0x80, 0xc0 }, { 0xc0, 0x80, 0xe0 },
1122         { 0xc0, 0xa0, 0x00 }, { 0xc0, 0xa0, 0x20 }, { 0xc0, 0xa0, 0x40 }, { 0xc0, 0xa0, 0x60 },
1123         { 0xc0, 0xa0, 0x80 }, { 0xc0, 0xa0, 0xa0 }, { 0xc0, 0xa0, 0xc0 }, { 0xc0, 0xa0, 0xe0 },
1124         { 0xc0, 0xc0, 0x00 }, { 0xc0, 0xc0, 0x20 }, { 0xc0, 0xc0, 0x40 }, { 0xc0, 0xc0, 0x60 },
1125         { 0xc0, 0xc0, 0x80 }, { 0xc0, 0xc0, 0xa0 }, { 0xf0, 0xfb, 0xff }, { 0xa4, 0xa0, 0xa0 },
1126         { 0x80, 0x80, 0x80 }, { 0x00, 0x00, 0xff }, { 0x00, 0xff, 0x00 }, { 0x00, 0xff, 0xff },
1127         { 0xff, 0x00, 0x00 }, { 0xff, 0x00, 0xff }, { 0xff, 0xff, 0x00 }, { 0xff, 0xff, 0xff },
1128     };
1129
1130     switch (bpp)
1131     {
1132     case 1: return table_1;
1133     case 4: return table_4;
1134     case 8: return table_8;
1135     default: return NULL;
1136     }
1137 }
1138
1139 void fill_default_color_table( BITMAPINFO *info )
1140 {
1141     info->bmiHeader.biClrUsed = 1 << info->bmiHeader.biBitCount;
1142     memcpy( info->bmiColors, get_default_color_table( info->bmiHeader.biBitCount ),
1143             info->bmiHeader.biClrUsed * sizeof(RGBQUAD) );
1144 }
1145
1146 void get_ddb_bitmapinfo( BITMAPOBJ *bmp, BITMAPINFO *info )
1147 {
1148     info->bmiHeader.biSize          = sizeof(info->bmiHeader);
1149     info->bmiHeader.biWidth         = bmp->dib.dsBm.bmWidth;
1150     info->bmiHeader.biHeight        = -bmp->dib.dsBm.bmHeight;
1151     info->bmiHeader.biPlanes        = 1;
1152     info->bmiHeader.biBitCount      = bmp->dib.dsBm.bmBitsPixel;
1153     info->bmiHeader.biCompression   = BI_RGB;
1154     info->bmiHeader.biXPelsPerMeter = 0;
1155     info->bmiHeader.biYPelsPerMeter = 0;
1156     info->bmiHeader.biClrUsed       = 0;
1157     info->bmiHeader.biClrImportant  = 0;
1158 }
1159
1160 BITMAPINFO *copy_packed_dib( const BITMAPINFO *src_info, UINT usage )
1161 {
1162     char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1163     BITMAPINFO *ret, *info = (BITMAPINFO *)buffer;
1164     unsigned int info_size;
1165
1166     if (!bitmapinfo_from_user_bitmapinfo( info, src_info, usage, FALSE )) return NULL;
1167
1168     info_size = get_dib_info_size( info, usage );
1169     if ((ret = HeapAlloc( GetProcessHeap(), 0, info_size + info->bmiHeader.biSizeImage )))
1170     {
1171         memcpy( ret, info, info_size );
1172         memcpy( (char *)ret + info_size, (char *)src_info + bitmap_info_size( src_info, usage ),
1173                 info->bmiHeader.biSizeImage );
1174     }
1175     return ret;
1176 }
1177
1178 /******************************************************************************
1179  * GetDIBits [GDI32.@]
1180  *
1181  * Retrieves bits of bitmap and copies to buffer.
1182  *
1183  * RETURNS
1184  *    Success: Number of scan lines copied from bitmap
1185  *    Failure: 0
1186  */
1187 INT WINAPI GetDIBits(
1188     HDC hdc,         /* [in]  Handle to device context */
1189     HBITMAP hbitmap, /* [in]  Handle to bitmap */
1190     UINT startscan,  /* [in]  First scan line to set in dest bitmap */
1191     UINT lines,      /* [in]  Number of scan lines to copy */
1192     LPVOID bits,       /* [out] Address of array for bitmap bits */
1193     BITMAPINFO * info, /* [out] Address of structure with bitmap data */
1194     UINT coloruse)   /* [in]  RGB or palette index */
1195 {
1196     DC * dc;
1197     BITMAPOBJ * bmp;
1198     int i, dst_to_src_offset, ret = 0;
1199     DWORD err;
1200     char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1201     BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf;
1202     char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1203     BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
1204     struct gdi_image_bits src_bits;
1205     struct bitblt_coords src, dst;
1206     BOOL empty_rect = FALSE;
1207
1208     /* Since info may be a BITMAPCOREINFO or any of the larger BITMAPINFO structures, we'll use our
1209        own copy and transfer the colour info back at the end */
1210     if (!bitmapinfoheader_from_user_bitmapinfo( &dst_info->bmiHeader, &info->bmiHeader )) return 0;
1211     if (coloruse > DIB_PAL_COLORS) return 0;
1212     if (bits &&
1213         (dst_info->bmiHeader.biCompression == BI_JPEG || dst_info->bmiHeader.biCompression == BI_PNG))
1214         return 0;
1215     dst_info->bmiHeader.biClrUsed = 0;
1216     dst_info->bmiHeader.biClrImportant = 0;
1217
1218     if (!(dc = get_dc_ptr( hdc )))
1219     {
1220         SetLastError( ERROR_INVALID_PARAMETER );
1221         return 0;
1222     }
1223     update_dc( dc );
1224     if (!(bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
1225     {
1226         release_dc_ptr( dc );
1227         return 0;
1228     }
1229
1230     src.visrect.left   = 0;
1231     src.visrect.top    = 0;
1232     src.visrect.right  = bmp->dib.dsBm.bmWidth;
1233     src.visrect.bottom = bmp->dib.dsBm.bmHeight;
1234
1235     dst.visrect.left   = 0;
1236     dst.visrect.top    = 0;
1237     dst.visrect.right  = dst_info->bmiHeader.biWidth;
1238     dst.visrect.bottom = abs( dst_info->bmiHeader.biHeight );
1239
1240     if (lines == 0 || startscan >= dst.visrect.bottom)
1241         bits = NULL;
1242
1243     if (!bits && dst_info->bmiHeader.biBitCount == 0) /* query bitmap info only */
1244     {
1245         ret = fill_query_info( info, bmp );
1246         goto done;
1247     }
1248
1249     /* validate parameters */
1250
1251     if (dst_info->bmiHeader.biWidth <= 0) goto done;
1252     if (dst_info->bmiHeader.biHeight == 0) goto done;
1253
1254     switch (dst_info->bmiHeader.biCompression)
1255     {
1256     case BI_RLE4:
1257         if (dst_info->bmiHeader.biBitCount != 4) goto done;
1258         if (dst_info->bmiHeader.biHeight < 0) goto done;
1259         if (bits) goto done;  /* can't retrieve compressed bits */
1260         break;
1261     case BI_RLE8:
1262         if (dst_info->bmiHeader.biBitCount != 8) goto done;
1263         if (dst_info->bmiHeader.biHeight < 0) goto done;
1264         if (bits) goto done;  /* can't retrieve compressed bits */
1265         break;
1266     case BI_BITFIELDS:
1267         if (dst_info->bmiHeader.biBitCount != 16 && dst_info->bmiHeader.biBitCount != 32) goto done;
1268         /* fall through */
1269     case BI_RGB:
1270         if (lines && !dst_info->bmiHeader.biPlanes) goto done;
1271         if (dst_info->bmiHeader.biBitCount == 1) break;
1272         if (dst_info->bmiHeader.biBitCount == 4) break;
1273         if (dst_info->bmiHeader.biBitCount == 8) break;
1274         if (dst_info->bmiHeader.biBitCount == 16) break;
1275         if (dst_info->bmiHeader.biBitCount == 24) break;
1276         if (dst_info->bmiHeader.biBitCount == 32) break;
1277         /* fall through */
1278     default:
1279         goto done;
1280     }
1281
1282     if (bits)
1283     {
1284         if (dst_info->bmiHeader.biHeight > 0)
1285         {
1286             dst_to_src_offset = -startscan;
1287             lines = min( lines, dst.visrect.bottom - startscan );
1288             if (lines < dst.visrect.bottom) dst.visrect.top = dst.visrect.bottom - lines;
1289         }
1290         else
1291         {
1292             dst_to_src_offset = dst.visrect.bottom - lines - startscan;
1293             if (dst_to_src_offset < 0)
1294             {
1295                 dst_to_src_offset = 0;
1296                 lines = dst.visrect.bottom - startscan;
1297             }
1298             if (lines < dst.visrect.bottom) dst.visrect.bottom = lines;
1299         }
1300
1301         offset_rect( &dst.visrect, 0, dst_to_src_offset );
1302         empty_rect = !intersect_rect( &src.visrect, &src.visrect, &dst.visrect );
1303         dst.visrect = src.visrect;
1304         offset_rect( &dst.visrect, 0, -dst_to_src_offset );
1305
1306         if (dst_info->bmiHeader.biHeight > 0)
1307         {
1308             if (dst.visrect.bottom < dst_info->bmiHeader.biHeight)
1309             {
1310                 int pad_lines = min( dst_info->bmiHeader.biHeight - dst.visrect.bottom, lines );
1311                 int pad_bytes = pad_lines * get_dib_stride( dst_info->bmiHeader.biWidth, dst_info->bmiHeader.biBitCount );
1312                 memset( bits, 0, pad_bytes );
1313                 bits = (char *)bits + pad_bytes;
1314             }
1315         }
1316         else
1317         {
1318             if (dst.visrect.bottom < lines)
1319             {
1320                 int pad_lines = lines - dst.visrect.bottom;
1321                 int stride = get_dib_stride( dst_info->bmiHeader.biWidth, dst_info->bmiHeader.biBitCount );
1322                 int pad_bytes = pad_lines * stride;
1323                 memset( (char *)bits + dst.visrect.bottom * stride, 0, pad_bytes );
1324             }
1325         }
1326
1327         if (empty_rect) bits = NULL;
1328
1329         src.x      = src.visrect.left;
1330         src.y      = src.visrect.top;
1331         src.width  = src.visrect.right - src.visrect.left;
1332         src.height = src.visrect.bottom - src.visrect.top;
1333
1334         lines = src.height;
1335     }
1336
1337     err = bmp->funcs->pGetImage( NULL, hbitmap, src_info, bits ? &src_bits : NULL, bits ? &src : NULL );
1338
1339     if (err) goto done;
1340
1341     /* fill out the src colour table, if it needs one */
1342     if (src_info->bmiHeader.biBitCount <= 8 && src_info->bmiHeader.biClrUsed == 0)
1343         fill_default_color_table( src_info );
1344
1345     /* if the src and dst are the same depth, copy the colour info across */
1346     if (dst_info->bmiHeader.biBitCount == src_info->bmiHeader.biBitCount && coloruse == DIB_RGB_COLORS )
1347     {
1348         switch (src_info->bmiHeader.biBitCount)
1349         {
1350         case 16:
1351             if (src_info->bmiHeader.biCompression == BI_RGB)
1352             {
1353                 src_info->bmiHeader.biCompression = BI_BITFIELDS;
1354                 memcpy( src_info->bmiColors, bit_fields_555, sizeof(bit_fields_555) );
1355             }
1356             break;
1357         case 32:
1358             if (src_info->bmiHeader.biCompression == BI_RGB)
1359             {
1360                 src_info->bmiHeader.biCompression = BI_BITFIELDS;
1361                 memcpy( src_info->bmiColors, bit_fields_888, sizeof(bit_fields_888) );
1362             }
1363             break;
1364         }
1365         src_info->bmiHeader.biSizeImage = get_dib_image_size( dst_info );
1366         copy_color_info( dst_info, src_info, coloruse );
1367     }
1368     else if (dst_info->bmiHeader.biBitCount <= 8) /* otherwise construct a default colour table for the dst, if needed */
1369     {
1370         if( coloruse == DIB_PAL_COLORS )
1371         {
1372             if (!fill_color_table_from_palette( dst_info, hdc )) goto done;
1373         }
1374         else
1375         {
1376             fill_default_color_table( dst_info );
1377         }
1378     }
1379
1380     if (bits)
1381     {
1382         if(dst_info->bmiHeader.biHeight > 0)
1383             dst_info->bmiHeader.biHeight = src.height;
1384         else
1385             dst_info->bmiHeader.biHeight = -src.height;
1386
1387         convert_bitmapinfo( src_info, src_bits.ptr, &src, dst_info, bits, FALSE );
1388         if (src_bits.free) src_bits.free( &src_bits );
1389         ret = lines;
1390     }
1391     else
1392         ret = empty_rect ? FALSE : TRUE;
1393
1394     if (coloruse == DIB_PAL_COLORS)
1395     {
1396         WORD *index = (WORD *)dst_info->bmiColors;
1397         for (i = 0; i < dst_info->bmiHeader.biClrUsed; i++, index++)
1398             *index = i;
1399     }
1400
1401     copy_color_info( info, dst_info, coloruse );
1402     if (info->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) info->bmiHeader.biClrUsed = 0;
1403
1404 done:
1405     release_dc_ptr( dc );
1406     GDI_ReleaseObj( hbitmap );
1407     return ret;
1408 }
1409
1410
1411 /***********************************************************************
1412  *           CreateDIBitmap    (GDI32.@)
1413  *
1414  * Creates a DDB (device dependent bitmap) from a DIB.
1415  * The DDB will have the same color depth as the reference DC.
1416  */
1417 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
1418                             DWORD init, LPCVOID bits, const BITMAPINFO *data,
1419                             UINT coloruse )
1420 {
1421     BITMAPINFOHEADER info;
1422     HBITMAP handle;
1423     LONG height;
1424
1425     if (!bitmapinfoheader_from_user_bitmapinfo( &info, header )) return 0;
1426     if (info.biCompression == BI_JPEG || info.biCompression == BI_PNG) return 0;
1427     if (coloruse > DIB_PAL_COLORS + 1) return 0;
1428     if (info.biWidth < 0) return 0;
1429
1430     /* Top-down DIBs have a negative height */
1431     height = abs( info.biHeight );
1432
1433     TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1434           hdc, header, init, bits, data, coloruse, info.biWidth, info.biHeight,
1435           info.biBitCount, info.biCompression);
1436
1437     if (hdc == NULL)
1438         handle = CreateBitmap( info.biWidth, height, 1, 1, NULL );
1439     else
1440         handle = CreateCompatibleBitmap( hdc, info.biWidth, height );
1441
1442     if (handle)
1443     {
1444         if (init & CBM_INIT)
1445         {
1446             if (SetDIBits( hdc, handle, 0, height, bits, data, coloruse ) == 0)
1447             {
1448                 DeleteObject( handle );
1449                 handle = 0;
1450             }
1451         }
1452     }
1453
1454     return handle;
1455 }
1456
1457
1458 /***********************************************************************
1459  *           CreateDIBSection    (GDI32.@)
1460  */
1461 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1462                                 VOID **bits, HANDLE section, DWORD offset)
1463 {
1464     char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1465     BITMAPINFO *info = (BITMAPINFO *)buffer;
1466     HBITMAP ret = 0;
1467     BITMAPOBJ *bmp;
1468     void *mapBits = NULL;
1469
1470     if (bits) *bits = NULL;
1471     if (!bitmapinfo_from_user_bitmapinfo( info, bmi, usage, FALSE )) return 0;
1472     if (usage > DIB_PAL_COLORS) return 0;
1473     if (info->bmiHeader.biPlanes != 1)
1474     {
1475         if (info->bmiHeader.biPlanes * info->bmiHeader.biBitCount > 16) return 0;
1476         WARN( "%u planes not properly supported\n", info->bmiHeader.biPlanes );
1477     }
1478
1479     if (!(bmp = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*bmp) ))) return 0;
1480
1481     TRACE("format (%d,%d), planes %d, bpp %d, %s, size %d %s\n",
1482           info->bmiHeader.biWidth, info->bmiHeader.biHeight,
1483           info->bmiHeader.biPlanes, info->bmiHeader.biBitCount,
1484           info->bmiHeader.biCompression == BI_BITFIELDS? "BI_BITFIELDS" : "BI_RGB",
1485           info->bmiHeader.biSizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1486
1487     bmp->dib.dsBm.bmType       = 0;
1488     bmp->dib.dsBm.bmWidth      = info->bmiHeader.biWidth;
1489     bmp->dib.dsBm.bmHeight     = abs( info->bmiHeader.biHeight );
1490     bmp->dib.dsBm.bmWidthBytes = get_dib_stride( info->bmiHeader.biWidth, info->bmiHeader.biBitCount );
1491     bmp->dib.dsBm.bmPlanes     = info->bmiHeader.biPlanes;
1492     bmp->dib.dsBm.bmBitsPixel  = info->bmiHeader.biBitCount;
1493     bmp->dib.dsBmih            = info->bmiHeader;
1494
1495     bmp->funcs = &dib_driver;
1496
1497     if (info->bmiHeader.biBitCount <= 8)  /* build the color table */
1498     {
1499         if (usage == DIB_PAL_COLORS && !fill_color_table_from_pal_colors( info, hdc ))
1500             goto error;
1501         bmp->dib.dsBmih.biClrUsed = info->bmiHeader.biClrUsed;
1502         if (!(bmp->color_table = HeapAlloc( GetProcessHeap(), 0,
1503                                             bmp->dib.dsBmih.biClrUsed * sizeof(RGBQUAD) )))
1504             goto error;
1505         memcpy( bmp->color_table, info->bmiColors, bmp->dib.dsBmih.biClrUsed * sizeof(RGBQUAD) );
1506     }
1507
1508     /* set dsBitfields values */
1509     if (info->bmiHeader.biBitCount == 16 && info->bmiHeader.biCompression == BI_RGB)
1510     {
1511         bmp->dib.dsBmih.biCompression = BI_BITFIELDS;
1512         bmp->dib.dsBitfields[0] = 0x7c00;
1513         bmp->dib.dsBitfields[1] = 0x03e0;
1514         bmp->dib.dsBitfields[2] = 0x001f;
1515     }
1516     else if (info->bmiHeader.biCompression == BI_BITFIELDS)
1517     {
1518         if (usage == DIB_PAL_COLORS) goto error;
1519         bmp->dib.dsBitfields[0] =  *(const DWORD *)info->bmiColors;
1520         bmp->dib.dsBitfields[1] =  *((const DWORD *)info->bmiColors + 1);
1521         bmp->dib.dsBitfields[2] =  *((const DWORD *)info->bmiColors + 2);
1522         if (!bmp->dib.dsBitfields[0] || !bmp->dib.dsBitfields[1] || !bmp->dib.dsBitfields[2]) goto error;
1523     }
1524     else bmp->dib.dsBitfields[0] = bmp->dib.dsBitfields[1] = bmp->dib.dsBitfields[2] = 0;
1525
1526     /* get storage location for DIB bits */
1527
1528     if (section)
1529     {
1530         SYSTEM_INFO SystemInfo;
1531         DWORD mapOffset;
1532         INT mapSize;
1533
1534         GetSystemInfo( &SystemInfo );
1535         mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
1536         mapSize = bmp->dib.dsBmih.biSizeImage + (offset - mapOffset);
1537         mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
1538         if (mapBits) bmp->dib.dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1539     }
1540     else
1541     {
1542         offset = 0;
1543         bmp->dib.dsBm.bmBits = VirtualAlloc( NULL, bmp->dib.dsBmih.biSizeImage,
1544                                              MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1545     }
1546     bmp->dib.dshSection = section;
1547     bmp->dib.dsOffset = offset;
1548
1549     if (!bmp->dib.dsBm.bmBits) goto error;
1550
1551     if (!(ret = alloc_gdi_handle( &bmp->header, OBJ_BITMAP, &dib_funcs ))) goto error;
1552
1553     if (bits) *bits = bmp->dib.dsBm.bmBits;
1554     return ret;
1555
1556 error:
1557     if (section) UnmapViewOfFile( mapBits );
1558     else VirtualFree( bmp->dib.dsBm.bmBits, 0, MEM_RELEASE );
1559     HeapFree( GetProcessHeap(), 0, bmp->color_table );
1560     HeapFree( GetProcessHeap(), 0, bmp );
1561     return 0;
1562 }
1563
1564
1565 /***********************************************************************
1566  *           DIB_SelectObject
1567  */
1568 static HGDIOBJ DIB_SelectObject( HGDIOBJ handle, HDC hdc )
1569 {
1570     HGDIOBJ ret;
1571     BITMAPOBJ *bitmap;
1572     DC *dc;
1573     PHYSDEV physdev = NULL, old_physdev = NULL, pathdev = NULL;
1574
1575     if (!(dc = get_dc_ptr( hdc ))) return 0;
1576
1577     if (GetObjectType( hdc ) != OBJ_MEMDC)
1578     {
1579         ret = 0;
1580         goto done;
1581     }
1582     ret = dc->hBitmap;
1583     if (handle == dc->hBitmap) goto done;  /* nothing to do */
1584
1585     if (!(bitmap = GDI_GetObjPtr( handle, OBJ_BITMAP )))
1586     {
1587         ret = 0;
1588         goto done;
1589     }
1590
1591     if (bitmap->header.selcount)
1592     {
1593         WARN( "Bitmap already selected in another DC\n" );
1594         GDI_ReleaseObj( handle );
1595         ret = 0;
1596         goto done;
1597     }
1598
1599     if (dc->physDev->funcs == &path_driver) pathdev = pop_dc_driver( &dc->physDev );
1600
1601     old_physdev = GET_DC_PHYSDEV( dc, pSelectBitmap );
1602     physdev = dc->dibdrv;
1603     if (old_physdev != dc->dibdrv)
1604     {
1605         if (physdev) push_dc_driver( &dc->physDev, physdev, physdev->funcs );
1606         else
1607         {
1608             if (!dib_driver.pCreateDC( &dc->physDev, NULL, NULL, NULL, NULL )) goto done;
1609             dc->dibdrv = physdev = dc->physDev;
1610         }
1611     }
1612
1613     if (!physdev->funcs->pSelectBitmap( physdev, handle ))
1614     {
1615         GDI_ReleaseObj( handle );
1616         ret = 0;
1617     }
1618     else
1619     {
1620         dc->hBitmap = handle;
1621         GDI_inc_ref_count( handle );
1622         dc->dirty = 0;
1623         dc->vis_rect.left   = 0;
1624         dc->vis_rect.top    = 0;
1625         dc->vis_rect.right  = bitmap->dib.dsBm.bmWidth;
1626         dc->vis_rect.bottom = bitmap->dib.dsBm.bmHeight;
1627         GDI_ReleaseObj( handle );
1628         DC_InitDC( dc );
1629         GDI_dec_ref_count( ret );
1630     }
1631
1632  done:
1633     if(!ret)
1634     {
1635         if (old_physdev && old_physdev != dc->dibdrv) pop_dc_driver( &dc->physDev );
1636     }
1637     if (pathdev) push_dc_driver( &dc->physDev, pathdev, pathdev->funcs );
1638     release_dc_ptr( dc );
1639     return ret;
1640 }
1641
1642
1643 /***********************************************************************
1644  *           DIB_GetObject
1645  */
1646 static INT DIB_GetObject( HGDIOBJ handle, INT count, LPVOID buffer )
1647 {
1648     INT ret = 0;
1649     BITMAPOBJ *bmp = GDI_GetObjPtr( handle, OBJ_BITMAP );
1650
1651     if (!bmp) return 0;
1652
1653     if (!buffer) ret = sizeof(BITMAP);
1654     else if (count >= sizeof(DIBSECTION))
1655     {
1656         DIBSECTION *dib = buffer;
1657         *dib = bmp->dib;
1658         dib->dsBmih.biHeight = abs( dib->dsBmih.biHeight );
1659         ret = sizeof(DIBSECTION);
1660     }
1661     else if (count >= sizeof(BITMAP))
1662     {
1663         BITMAP *bitmap = buffer;
1664         *bitmap = bmp->dib.dsBm;
1665         ret = sizeof(BITMAP);
1666     }
1667
1668     GDI_ReleaseObj( handle );
1669     return ret;
1670 }
1671
1672
1673 /***********************************************************************
1674  *           DIB_DeleteObject
1675  */
1676 static BOOL DIB_DeleteObject( HGDIOBJ handle )
1677 {
1678     BITMAPOBJ *bmp;
1679
1680     if (!(bmp = free_gdi_handle( handle ))) return FALSE;
1681
1682     if (bmp->dib.dshSection)
1683     {
1684         SYSTEM_INFO SystemInfo;
1685         GetSystemInfo( &SystemInfo );
1686         UnmapViewOfFile( (char *)bmp->dib.dsBm.bmBits -
1687                          (bmp->dib.dsOffset % SystemInfo.dwAllocationGranularity) );
1688     }
1689     else VirtualFree( bmp->dib.dsBm.bmBits, 0, MEM_RELEASE );
1690
1691     HeapFree(GetProcessHeap(), 0, bmp->color_table);
1692     return HeapFree( GetProcessHeap(), 0, bmp );
1693 }