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