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