Handle wParam in WM_PAINT properly: if non-null, it is the hdc we are
[wine] / dlls / x11drv / dib.c
1 /*
2  * X11DRV 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22
23 #include <X11/Xlib.h>
24 #ifdef HAVE_LIBXXSHM
25 #include <X11/extensions/XShm.h>
26 # ifdef HAVE_SYS_SHM_H
27 #  include <sys/shm.h>
28 # endif
29 # ifdef HAVE_SYS_IPC_H
30 #  include <sys/ipc.h>
31 # endif
32 #endif /* defined(HAVE_LIBXXSHM) */
33
34 #include <stdarg.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include "windef.h"
38 #include "winbase.h"
39 #include "gdi.h"
40 #include "x11drv.h"
41 #include "wine/debug.h"
42
43 WINE_DEFAULT_DEBUG_CHANNEL(bitmap);
44 WINE_DECLARE_DEBUG_CHANNEL(x11drv);
45
46 static int ximageDepthTable[32];
47
48 /* This structure holds the arguments for DIB_SetImageBits() */
49 typedef struct
50 {
51     X11DRV_PDEVICE *physDev;
52     LPCVOID         bits;
53     XImage         *image;
54     PALETTEENTRY   *palentry;
55     int             lines;
56     DWORD           infoWidth;
57     WORD            depth;
58     WORD            infoBpp;
59     WORD            compression;
60     RGBQUAD        *colorMap;
61     int             nColorMap;
62     Drawable        drawable;
63     GC              gc;
64     int             xSrc;
65     int             ySrc;
66     int             xDest;
67     int             yDest;
68     int             width;
69     int             height;
70     DWORD           rMask;
71     DWORD           gMask;
72     DWORD           bMask;
73     BOOL            useShm;
74     int             dibpitch;
75     DWORD           sizeImage;  
76 } X11DRV_DIB_IMAGEBITS_DESCR;
77
78
79 enum Rle_EscapeCodes
80 {
81   RLE_EOL   = 0, /* End of line */
82   RLE_END   = 1, /* End of bitmap */
83   RLE_DELTA = 2  /* Delta */
84 };
85
86
87 /* 
88   Some of the following helper functions are duplicated in
89   dlls/gdi/dib.c
90 */
91
92 /***********************************************************************
93  *           X11DRV_DIB_GetXImageWidthBytes
94  *
95  * Return the width of an X image in bytes
96  */
97 inline static int X11DRV_DIB_GetXImageWidthBytes( int width, int depth )
98 {
99     if (!depth || depth > 32) goto error;
100
101     if (!ximageDepthTable[depth-1])
102     {
103         XImage *testimage = XCreateImage( gdi_display, visual, depth,
104                                           ZPixmap, 0, NULL, 1, 1, 32, 20 );
105         if (testimage)
106         {
107             ximageDepthTable[depth-1] = testimage->bits_per_pixel;
108             XDestroyImage( testimage );
109         }
110         else ximageDepthTable[depth-1] = -1;
111     }
112     if (ximageDepthTable[depth-1] != -1)
113         return (4 * ((width * ximageDepthTable[depth-1] + 31) / 32));
114
115  error:
116     WARN( "(%d): Unsupported depth\n", depth );
117     return 4 * width;
118 }
119
120
121 /***********************************************************************
122  *           X11DRV_DIB_GetDIBWidthBytes
123  *
124  * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
125  */
126 static int X11DRV_DIB_GetDIBWidthBytes( int width, int depth )
127 {
128     int words;
129
130     switch(depth)
131     {
132     case 1:  words = (width + 31) / 32; break;
133     case 4:  words = (width + 7) / 8; break;
134     case 8:  words = (width + 3) / 4; break;
135     case 15:
136     case 16: words = (width + 1) / 2; break;
137     case 24: words = (width * 3 + 3) / 4; break;
138     default:
139         WARN("(%d): Unsupported depth\n", depth );
140         /* fall through */
141     case 32:
142         words = width;
143     }
144     return 4 * words;
145 }
146
147
148 /***********************************************************************
149  *           X11DRV_DIB_GetDIBImageBytes
150  *
151  * Return the number of bytes used to hold the image in a DIB bitmap.
152  */
153 static int X11DRV_DIB_GetDIBImageBytes( int width, int height, int depth )
154 {
155     return X11DRV_DIB_GetDIBWidthBytes( width, depth ) * abs( height );
156 }
157
158
159 /***********************************************************************
160  *           X11DRV_DIB_BitmapInfoSize
161  *
162  * Return the size of the bitmap info structure including color table.
163  */
164 int X11DRV_DIB_BitmapInfoSize( const BITMAPINFO * info, WORD coloruse )
165 {
166     unsigned int colors;
167
168     if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
169     {
170         const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
171         colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
172         return sizeof(BITMAPCOREHEADER) + colors *
173              ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
174     }
175     else  /* assume BITMAPINFOHEADER */
176     {
177         colors = info->bmiHeader.biClrUsed;
178         if (!colors && (info->bmiHeader.biBitCount <= 8))
179             colors = 1 << info->bmiHeader.biBitCount;
180         return sizeof(BITMAPINFOHEADER) + colors *
181                ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
182     }
183 }
184
185
186 /***********************************************************************
187  *           X11DRV_DIB_CreateXImage
188  *
189  * Create an X image.
190  */
191 XImage *X11DRV_DIB_CreateXImage( int width, int height, int depth )
192 {
193     int width_bytes;
194     XImage *image;
195
196     wine_tsx11_lock();
197     width_bytes = X11DRV_DIB_GetXImageWidthBytes( width, depth );
198     image = XCreateImage( gdi_display, visual, depth, ZPixmap, 0,
199                           calloc( height, width_bytes ),
200                           width, height, 32, width_bytes );
201     wine_tsx11_unlock();
202     return image;
203 }
204
205
206 /***********************************************************************
207  *           DIB_GetBitmapInfoEx
208  *
209  * Get the info from a bitmap header.
210  * Return 1 for INFOHEADER, 0 for COREHEADER, -1 for error.
211  */
212 static int DIB_GetBitmapInfoEx( const BITMAPINFOHEADER *header, LONG *width,
213                                 LONG *height, WORD *planes, WORD *bpp,
214                                 WORD *compr, DWORD *size )
215 {
216     if (header->biSize == sizeof(BITMAPCOREHEADER))
217     {
218         const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)header;
219         *width  = core->bcWidth;
220         *height = core->bcHeight;
221         *planes = core->bcPlanes;
222         *bpp    = core->bcBitCount;
223         *compr  = 0;
224         *size   = 0;
225         return 0;
226     }
227     if (header->biSize >= sizeof(BITMAPINFOHEADER))
228     {
229         *width  = header->biWidth;
230         *height = header->biHeight;
231         *planes = header->biPlanes;
232         *bpp    = header->biBitCount;
233         *compr  = header->biCompression;
234         *size   = header->biSizeImage;
235         return 1;
236     }
237     ERR("(%ld): unknown/wrong size for header\n", header->biSize );
238     return -1;
239 }
240
241
242 /***********************************************************************
243  *           DIB_GetBitmapInfo
244  *
245  * Get the info from a bitmap header.
246  * Return 1 for INFOHEADER, 0 for COREHEADER, -1 for error.
247  */
248 static int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
249                               LONG *height, WORD *bpp, WORD *compr )
250 {
251     WORD planes;
252     DWORD size;
253     
254     return DIB_GetBitmapInfoEx( header, width, height, &planes, bpp, compr, &size);    
255 }
256
257
258 /***********************************************************************
259  *           X11DRV_DIB_GenColorMap
260  *
261  * Fills the color map of a bitmap palette. Should not be called
262  * for a >8-bit deep bitmap.
263  */
264 int *X11DRV_DIB_GenColorMap( X11DRV_PDEVICE *physDev, int *colorMapping,
265                              WORD coloruse, WORD depth, BOOL quads,
266                              const void *colorPtr, int start, int end )
267 {
268     int i;
269
270     if (coloruse == DIB_RGB_COLORS)
271     {
272         if (quads)
273         {
274             const RGBQUAD * rgb = (const RGBQUAD *)colorPtr;
275
276             if (depth == 1)  /* Monochrome */
277                 for (i = start; i < end; i++, rgb++)
278                     colorMapping[i] = (rgb->rgbRed + rgb->rgbGreen +
279                                        rgb->rgbBlue > 255*3/2);
280             else
281                 for (i = start; i < end; i++, rgb++)
282                     colorMapping[i] = X11DRV_PALETTE_ToPhysical( physDev, RGB(rgb->rgbRed,
283                                                                 rgb->rgbGreen,
284                                                                 rgb->rgbBlue));
285         }
286         else
287         {
288             const RGBTRIPLE * rgb = (const RGBTRIPLE *)colorPtr;
289
290             if (depth == 1)  /* Monochrome */
291                 for (i = start; i < end; i++, rgb++)
292                     colorMapping[i] = (rgb->rgbtRed + rgb->rgbtGreen +
293                                        rgb->rgbtBlue > 255*3/2);
294             else
295                 for (i = start; i < end; i++, rgb++)
296                     colorMapping[i] = X11DRV_PALETTE_ToPhysical( physDev, RGB(rgb->rgbtRed,
297                                                                rgb->rgbtGreen,
298                                                                rgb->rgbtBlue));
299         }
300     }
301     else  /* DIB_PAL_COLORS */
302     {
303         if (colorPtr) {
304             const WORD * index = (const WORD *)colorPtr;
305
306             for (i = start; i < end; i++, index++)
307                 colorMapping[i] = X11DRV_PALETTE_ToPhysical( physDev, PALETTEINDEX(*index) );
308         } else {
309             for (i = start; i < end; i++)
310                 colorMapping[i] = X11DRV_PALETTE_ToPhysical( physDev, PALETTEINDEX(i) );
311         }
312     }
313
314     return colorMapping;
315 }
316
317 /***********************************************************************
318  *           X11DRV_DIB_BuildColorMap
319  *
320  * Build the color map from the bitmap palette. Should not be called
321  * for a >8-bit deep bitmap.
322  */
323 int *X11DRV_DIB_BuildColorMap( X11DRV_PDEVICE *physDev, WORD coloruse, WORD depth,
324                                const BITMAPINFO *info, int *nColors )
325 {
326     unsigned int colors;
327     BOOL isInfo;
328     const void *colorPtr;
329     int *colorMapping;
330
331     isInfo = info->bmiHeader.biSize != sizeof(BITMAPCOREHEADER);
332
333     if (isInfo)
334     {
335         colors = info->bmiHeader.biClrUsed;
336         if (!colors) colors = 1 << info->bmiHeader.biBitCount;
337     }
338     else
339     {
340         colors = 1 << ((const BITMAPCOREHEADER *)info)->bcBitCount;
341     }
342
343     colorPtr = (const BYTE*) info + (WORD) info->bmiHeader.biSize;
344
345     if (colors > 256)
346     {
347         ERR("called with >256 colors!\n");
348         return NULL;
349     }
350
351     /* just so CopyDIBSection doesn't have to create an identity palette */
352     if (coloruse == (WORD)-1) colorPtr = NULL;
353
354     if (!(colorMapping = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(int) )))
355         return NULL;
356
357     *nColors = colors;
358     return X11DRV_DIB_GenColorMap( physDev, colorMapping, coloruse, depth,
359                                    isInfo, colorPtr, 0, colors);
360 }
361
362 /***********************************************************************
363  *           X11DRV_DIB_BuildColorTable
364  *
365  * Build the dib color table. This either keeps a copy of the bmiColors array if
366  * usage is DIB_RGB_COLORS, or looks up the palette indicies if usage is
367  * DIB_PAL_COLORS.
368  * Should not be called for a >8-bit deep bitmap.
369  */
370 static RGBQUAD *X11DRV_DIB_BuildColorTable( X11DRV_PDEVICE *physDev, WORD coloruse, WORD depth,
371                                             const BITMAPINFO *info )
372 {
373     RGBQUAD *colorTable;
374     unsigned int colors;
375     int i;
376     BOOL core_info = info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER);
377
378     if (core_info)
379     {
380         colors = 1 << ((BITMAPCOREINFO*) info)->bmciHeader.bcBitCount;
381     }
382     else
383     {
384         colors = info->bmiHeader.biClrUsed;
385         if (!colors) colors = 1 << info->bmiHeader.biBitCount;
386     }
387
388     if (colors > 256) {
389         ERR("called with >256 colors!\n");
390         return NULL;
391     }
392
393     if (!(colorTable = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(RGBQUAD) )))
394         return NULL;
395
396     if(coloruse == DIB_RGB_COLORS)
397     {
398         if (core_info)
399         {
400            /* Convert RGBTRIPLEs to RGBQUADs */
401            for (i=0; i < colors; i++)
402            {
403                colorTable[i].rgbRed   = ((BITMAPCOREINFO*) info)->bmciColors[i].rgbtRed;
404                colorTable[i].rgbGreen = ((BITMAPCOREINFO*) info)->bmciColors[i].rgbtGreen;
405                colorTable[i].rgbBlue  = ((BITMAPCOREINFO*) info)->bmciColors[i].rgbtBlue;
406                colorTable[i].rgbReserved = 0;
407            }
408         }
409         else
410         {
411             memcpy(colorTable, (LPBYTE) info + (WORD) info->bmiHeader.biSize, colors * sizeof(RGBQUAD));
412         }
413     }
414     else
415     {
416         HPALETTE hpal = GetCurrentObject(physDev->hdc, OBJ_PAL);
417         PALETTEENTRY pal_ents[256];
418         WORD *index = (WORD*) ((LPBYTE) info + (WORD) info->bmiHeader.biSize);
419
420         GetPaletteEntries(hpal, 0, 256, pal_ents);
421
422         for(i = 0; i < colors; i++, index++)
423         {
424             colorTable[i].rgbRed = pal_ents[*index].peRed;
425             colorTable[i].rgbGreen = pal_ents[*index].peGreen;
426             colorTable[i].rgbBlue = pal_ents[*index].peBlue;
427             colorTable[i].rgbReserved = 0;
428         }
429     }
430     return colorTable;
431 }
432         
433     
434 /***********************************************************************
435  *           X11DRV_DIB_MapColor
436  */
437 int X11DRV_DIB_MapColor( int *physMap, int nPhysMap, int phys, int oldcol )
438 {
439     unsigned int color;
440
441     if ((oldcol < nPhysMap) && (physMap[oldcol] == phys))
442         return oldcol;
443
444     for (color = 0; color < nPhysMap; color++)
445         if (physMap[color] == phys)
446             return color;
447
448     WARN("Strange color %08x\n", phys);
449     return 0;
450 }
451
452
453 /*********************************************************************
454  *         X11DRV_DIB_GetNearestIndex
455  *
456  * Helper for X11DRV_DIB_GetDIBits.
457  * Returns the nearest colour table index for a given RGB.
458  * Nearest is defined by minimizing the sum of the squares.
459  */
460 static INT X11DRV_DIB_GetNearestIndex(RGBQUAD *colormap, int numColors, BYTE r, BYTE g, BYTE b)
461 {
462     INT i, best = -1, diff, bestdiff = -1;
463     RGBQUAD *color;
464
465     for(color = colormap, i = 0; i < numColors; color++, i++) {
466         diff = (r - color->rgbRed) * (r - color->rgbRed) +
467                (g - color->rgbGreen) * (g - color->rgbGreen) +
468                (b - color->rgbBlue) * (b - color->rgbBlue);
469         if(diff == 0)
470             return i;
471         if(best == -1 || diff < bestdiff) {
472             best = i;
473             bestdiff = diff;
474         }
475     }
476     return best;
477 }
478 /*********************************************************************
479  *         X11DRV_DIB_MaskToShift
480  *
481  * Helper for X11DRV_DIB_GetDIBits.
482  * Returns the by how many bits to shift a given color so that it is
483  * in the proper position.
484  */
485 INT X11DRV_DIB_MaskToShift(DWORD mask)
486 {
487     int shift;
488
489     if (mask==0)
490         return 0;
491
492     shift=0;
493     while ((mask&1)==0) {
494         mask>>=1;
495         shift++;
496     }
497     return shift;
498 }
499
500 /***********************************************************************
501  *           X11DRV_DIB_SetImageBits_1
502  *
503  * SetDIBits for a 1-bit deep DIB.
504  */
505 static void X11DRV_DIB_SetImageBits_1( int lines, const BYTE *srcbits,
506                                 DWORD srcwidth, DWORD dstwidth, int left,
507                                 int *colors, XImage *bmpImage, DWORD linebytes)
508 {
509     int h, width;
510     const BYTE* srcbyte;
511     BYTE srcval, extra;
512     DWORD i, x;
513
514     if (lines < 0 ) {
515         lines = -lines;
516         srcbits = srcbits + linebytes * (lines - 1);
517         linebytes = -linebytes;
518     }
519
520     if ((extra = (left & 7)) != 0) {
521         left &= ~7;
522         dstwidth += extra;
523     }
524     srcbits += left >> 3;
525     width = min(srcwidth, dstwidth);
526
527     /* ==== pal 1 dib -> any bmp format ==== */
528     for (h = lines-1; h >=0; h--) {
529         srcbyte=srcbits;
530         /* FIXME: should avoid putting x<left pixels (minor speed issue) */
531         for (i = width/8, x = left; i > 0; i--) {
532             srcval=*srcbyte++;
533             XPutPixel( bmpImage, x++, h, colors[ srcval >> 7] );
534             XPutPixel( bmpImage, x++, h, colors[(srcval >> 6) & 1] );
535             XPutPixel( bmpImage, x++, h, colors[(srcval >> 5) & 1] );
536             XPutPixel( bmpImage, x++, h, colors[(srcval >> 4) & 1] );
537             XPutPixel( bmpImage, x++, h, colors[(srcval >> 3) & 1] );
538             XPutPixel( bmpImage, x++, h, colors[(srcval >> 2) & 1] );
539             XPutPixel( bmpImage, x++, h, colors[(srcval >> 1) & 1] );
540             XPutPixel( bmpImage, x++, h, colors[ srcval       & 1] );
541         }
542         if (width % 8){
543             srcval=*srcbyte;
544             switch (width & 7)
545             {
546             case 7: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
547             case 6: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
548             case 5: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
549             case 4: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
550             case 3: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
551             case 2: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
552             case 1: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]);
553             }
554         }
555         srcbits += linebytes;
556     }
557 }
558
559 /***********************************************************************
560  *           X11DRV_DIB_GetImageBits_1
561  *
562  * GetDIBits for a 1-bit deep DIB.
563  */
564 static void X11DRV_DIB_GetImageBits_1( int lines, BYTE *dstbits,
565                                        DWORD dstwidth, DWORD srcwidth,
566                                        RGBQUAD *colors, PALETTEENTRY *srccolors,
567                                 XImage *bmpImage, DWORD linebytes )
568 {
569     DWORD x;
570     int h, width = min(dstwidth, srcwidth);
571
572     if (lines < 0 ) {
573         lines = -lines;
574         dstbits = dstbits + linebytes * (lines - 1);
575         linebytes = -linebytes;
576     }
577
578     switch (bmpImage->depth)
579     {
580     case 1:
581     case 4:
582         if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
583             /* ==== pal 1 or 4 bmp -> pal 1 dib ==== */
584             BYTE* dstbyte;
585
586             for (h=lines-1; h>=0; h--) {
587                 BYTE dstval;
588                 dstbyte=dstbits;
589                 dstval=0;
590                 for (x=0; x<width; x++) {
591                     PALETTEENTRY srcval;
592                     srcval=srccolors[XGetPixel(bmpImage, x, h)];
593                     dstval|=(X11DRV_DIB_GetNearestIndex
594                              (colors, 2,
595                               srcval.peRed,
596                               srcval.peGreen,
597                               srcval.peBlue) << (7 - (x & 7)));
598                     if ((x&7)==7) {
599                         *dstbyte++=dstval;
600                         dstval=0;
601                     }
602                 }
603                 if ((width&7)!=0) {
604                     *dstbyte=dstval;
605                 }
606                 dstbits += linebytes;
607             }
608         } else {
609             goto notsupported;
610         }
611         break;
612
613     case 8:
614         if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
615             /* ==== pal 8 bmp -> pal 1 dib ==== */
616             const void* srcbits;
617             const BYTE* srcpixel;
618             BYTE* dstbyte;
619
620             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
621
622             for (h=0; h<lines; h++) {
623                 BYTE dstval;
624                 srcpixel=srcbits;
625                 dstbyte=dstbits;
626                 dstval=0;
627                 for (x=0; x<width; x++) {
628                     PALETTEENTRY srcval;
629                     srcval=srccolors[(int)*srcpixel++];
630                     dstval|=(X11DRV_DIB_GetNearestIndex
631                              (colors, 2,
632                               srcval.peRed,
633                               srcval.peGreen,
634                               srcval.peBlue) << (7-(x&7)) );
635                     if ((x&7)==7) {
636                         *dstbyte++=dstval;
637                         dstval=0;
638                     }
639                 }
640                 if ((width&7)!=0) {
641                     *dstbyte=dstval;
642                 }
643                 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
644                 dstbits += linebytes;
645             }
646         } else {
647             goto notsupported;
648         }
649         break;
650
651     case 15:
652     case 16:
653         {
654             const void* srcbits;
655             const WORD* srcpixel;
656             BYTE* dstbyte;
657
658             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
659
660             if (bmpImage->green_mask==0x03e0) {
661                 if (bmpImage->red_mask==0x7c00) {
662                     /* ==== rgb 555 bmp -> pal 1 dib ==== */
663                     for (h=0; h<lines; h++) {
664                         BYTE dstval;
665                         srcpixel=srcbits;
666                         dstbyte=dstbits;
667                         dstval=0;
668                         for (x=0; x<width; x++) {
669                             WORD srcval;
670                             srcval=*srcpixel++;
671                             dstval|=(X11DRV_DIB_GetNearestIndex
672                                      (colors, 2,
673                                       ((srcval >>  7) & 0xf8) | /* r */
674                                       ((srcval >> 12) & 0x07),
675                                       ((srcval >>  2) & 0xf8) | /* g */
676                                       ((srcval >>  7) & 0x07),
677                                       ((srcval <<  3) & 0xf8) | /* b */
678                                       ((srcval >>  2) & 0x07) ) << (7-(x&7)) );
679                             if ((x&7)==7) {
680                                 *dstbyte++=dstval;
681                                 dstval=0;
682                             }
683                         }
684                         if ((width&7)!=0) {
685                             *dstbyte=dstval;
686                         }
687                         srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
688                         dstbits += linebytes;
689                     }
690                 } else if (bmpImage->blue_mask==0x7c00) {
691                     /* ==== bgr 555 bmp -> pal 1 dib ==== */
692                     for (h=0; h<lines; h++) {
693                         WORD dstval;
694                         srcpixel=srcbits;
695                         dstbyte=dstbits;
696                         dstval=0;
697                         for (x=0; x<width; x++) {
698                             BYTE srcval;
699                             srcval=*srcpixel++;
700                             dstval|=(X11DRV_DIB_GetNearestIndex
701                                      (colors, 2,
702                                       ((srcval <<  3) & 0xf8) | /* r */
703                                       ((srcval >>  2) & 0x07),
704                                       ((srcval >>  2) & 0xf8) | /* g */
705                                       ((srcval >>  7) & 0x07),
706                                       ((srcval >>  7) & 0xf8) | /* b */
707                                       ((srcval >> 12) & 0x07) ) << (7-(x&7)) );
708                             if ((x&7)==7) {
709                                 *dstbyte++=dstval;
710                                 dstval=0;
711                             }
712                         }
713                         if ((width&7)!=0) {
714                             *dstbyte=dstval;
715                         }
716                         srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
717                         dstbits += linebytes;
718                     }
719                 } else {
720                     goto notsupported;
721                 }
722             } else if (bmpImage->green_mask==0x07e0) {
723                 if (bmpImage->red_mask==0xf800) {
724                     /* ==== rgb 565 bmp -> pal 1 dib ==== */
725                     for (h=0; h<lines; h++) {
726                         BYTE dstval;
727                         srcpixel=srcbits;
728                         dstbyte=dstbits;
729                         dstval=0;
730                         for (x=0; x<width; x++) {
731                             WORD srcval;
732                             srcval=*srcpixel++;
733                             dstval|=(X11DRV_DIB_GetNearestIndex
734                                      (colors, 2,
735                                       ((srcval >>  8) & 0xf8) | /* r */
736                                       ((srcval >> 13) & 0x07),
737                                       ((srcval >>  3) & 0xfc) | /* g */
738                                       ((srcval >>  9) & 0x03),
739                                       ((srcval <<  3) & 0xf8) | /* b */
740                                       ((srcval >>  2) & 0x07) ) << (7-(x&7)) );
741                             if ((x&7)==7) {
742                                 *dstbyte++=dstval;
743                                 dstval=0;
744                             }
745                         }
746                         if ((width&7)!=0) {
747                             *dstbyte=dstval;
748                         }
749                         srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
750                         dstbits += linebytes;
751                     }
752                 } else if (bmpImage->blue_mask==0xf800) {
753                     /* ==== bgr 565 bmp -> pal 1 dib ==== */
754                     for (h=0; h<lines; h++) {
755                         BYTE dstval;
756                         srcpixel=srcbits;
757                         dstbyte=dstbits;
758                         dstval=0;
759                         for (x=0; x<width; x++) {
760                             WORD srcval;
761                             srcval=*srcpixel++;
762                             dstval|=(X11DRV_DIB_GetNearestIndex
763                                      (colors, 2,
764                                       ((srcval <<  3) & 0xf8) | /* r */
765                                       ((srcval >>  2) & 0x07),
766                                       ((srcval >>  3) & 0xfc) | /* g */
767                                       ((srcval >>  9) & 0x03),
768                                       ((srcval >>  8) & 0xf8) | /* b */
769                                       ((srcval >> 13) & 0x07) ) << (7-(x&7)) );
770                             if ((x&7)==7) {
771                                 *dstbyte++=dstval;
772                                 dstval=0;
773                             }
774                         }
775                         if ((width&7)!=0) {
776                             *dstbyte=dstval;
777                         }
778                         srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
779                         dstbits += linebytes;
780                     }
781                 } else {
782                     goto notsupported;
783                 }
784             } else {
785                 goto notsupported;
786             }
787         }
788         break;
789
790     case 24:
791     case 32:
792         {
793             const void* srcbits;
794             const BYTE *srcbyte;
795             BYTE* dstbyte;
796             int bytes_per_pixel;
797
798             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
799             bytes_per_pixel=(bmpImage->bits_per_pixel==24?3:4);
800
801             if (bmpImage->green_mask!=0x00ff00 ||
802                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
803                 goto notsupported;
804             } else if (bmpImage->blue_mask==0xff) {
805                 /* ==== rgb 888 or 0888 bmp -> pal 1 dib ==== */
806                 for (h=0; h<lines; h++) {
807                     BYTE dstval;
808                     srcbyte=srcbits;
809                     dstbyte=dstbits;
810                     dstval=0;
811                     for (x=0; x<width; x++) {
812                         dstval|=(X11DRV_DIB_GetNearestIndex
813                                  (colors, 2,
814                                   srcbyte[2],
815                                   srcbyte[1],
816                                   srcbyte[0]) << (7-(x&7)) );
817                         srcbyte+=bytes_per_pixel;
818                         if ((x&7)==7) {
819                             *dstbyte++=dstval;
820                             dstval=0;
821                         }
822                     }
823                     if ((width&7)!=0) {
824                         *dstbyte=dstval;
825                     }
826                     srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
827                     dstbits += linebytes;
828                 }
829             } else {
830                 /* ==== bgr 888 or 0888 bmp -> pal 1 dib ==== */
831                 for (h=0; h<lines; h++) {
832                     BYTE dstval;
833                     srcbyte=srcbits;
834                     dstbyte=dstbits;
835                     dstval=0;
836                     for (x=0; x<width; x++) {
837                         dstval|=(X11DRV_DIB_GetNearestIndex
838                                  (colors, 2,
839                                   srcbyte[0],
840                                   srcbyte[1],
841                                   srcbyte[2]) << (7-(x&7)) );
842                         srcbyte+=bytes_per_pixel;
843                         if ((x&7)==7) {
844                             *dstbyte++=dstval;
845                             dstval=0;
846                         }
847                     }
848                     if ((width&7)!=0) {
849                         *dstbyte=dstval;
850                     }
851                     srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
852                     dstbits += linebytes;
853                 }
854             }
855         }
856         break;
857
858     default:
859     notsupported:
860         {
861             BYTE* dstbyte;
862             unsigned long white = (1 << bmpImage->bits_per_pixel) - 1;
863
864             /* ==== any bmp format -> pal 1 dib ==== */
865             WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 1 bit DIB\n",
866                   bmpImage->bits_per_pixel, bmpImage->red_mask,
867                   bmpImage->green_mask, bmpImage->blue_mask );
868
869             for (h=lines-1; h>=0; h--) {
870                 BYTE dstval;
871                 dstbyte=dstbits;
872                 dstval=0;
873                 for (x=0; x<width; x++) {
874                     dstval|=(XGetPixel( bmpImage, x, h) >= white) << (7 - (x&7));
875                     if ((x&7)==7) {
876                         *dstbyte++=dstval;
877                         dstval=0;
878                     }
879                 }
880                 if ((width&7)!=0) {
881                     *dstbyte=dstval;
882                 }
883                 dstbits += linebytes;
884             }
885         }
886         break;
887     }
888 }
889
890 /***********************************************************************
891  *           X11DRV_DIB_SetImageBits_4
892  *
893  * SetDIBits for a 4-bit deep DIB.
894  */
895 static void X11DRV_DIB_SetImageBits_4( int lines, const BYTE *srcbits,
896                                 DWORD srcwidth, DWORD dstwidth, int left,
897                                 int *colors, XImage *bmpImage, DWORD linebytes)
898 {
899     int h, width;
900     const BYTE* srcbyte;
901     DWORD i, x;
902
903     if (lines < 0 ) {
904         lines = -lines;
905         srcbits = srcbits + linebytes * (lines - 1);
906         linebytes = -linebytes;
907     }
908
909     if (left & 1) {
910         left--;
911         dstwidth++;
912     }
913     srcbits += left >> 1;
914     width = min(srcwidth, dstwidth);
915
916     /* ==== pal 4 dib -> any bmp format ==== */
917     for (h = lines-1; h >= 0; h--) {
918         srcbyte=srcbits;
919         for (i = width/2, x = left; i > 0; i--) {
920             BYTE srcval=*srcbyte++;
921             XPutPixel( bmpImage, x++, h, colors[srcval >> 4] );
922             XPutPixel( bmpImage, x++, h, colors[srcval & 0x0f] );
923         }
924         if (width & 1)
925             XPutPixel( bmpImage, x, h, colors[*srcbyte >> 4] );
926         srcbits += linebytes;
927     }
928 }
929
930
931
932 /***********************************************************************
933  *           X11DRV_DIB_GetImageBits_4
934  *
935  * GetDIBits for a 4-bit deep DIB.
936  */
937 static void X11DRV_DIB_GetImageBits_4( int lines, BYTE *dstbits,
938                                        DWORD srcwidth, DWORD dstwidth,
939                                        RGBQUAD *colors, PALETTEENTRY *srccolors,
940                                        XImage *bmpImage, DWORD linebytes )
941 {
942     DWORD x;
943     int h, width = min(srcwidth, dstwidth);
944     BYTE *bits;
945
946     if (lines < 0 )
947     {
948        lines = -lines;
949        dstbits = dstbits + ( linebytes * (lines-1) );
950        linebytes = -linebytes;
951     }
952
953     bits = dstbits;
954
955     switch (bmpImage->depth) {
956     case 1:
957     case 4:
958         if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
959             /* ==== pal 1 or 4 bmp -> pal 4 dib ==== */
960             BYTE* dstbyte;
961
962             for (h = lines-1; h >= 0; h--) {
963                 BYTE dstval;
964                 dstbyte=dstbits;
965                 dstval=0;
966                 for (x = 0; x < width; x++) {
967                     PALETTEENTRY srcval;
968                     srcval=srccolors[XGetPixel(bmpImage, x, h)];
969                     dstval|=(X11DRV_DIB_GetNearestIndex
970                              (colors, 16,
971                               srcval.peRed,
972                               srcval.peGreen,
973                               srcval.peBlue) << (4-((x&1)<<2)));
974                     if ((x&1)==1) {
975                         *dstbyte++=dstval;
976                         dstval=0;
977                     }
978                 }
979                 if ((width&1)!=0) {
980                     *dstbyte=dstval;
981                 }
982                 dstbits += linebytes;
983             }
984         } else {
985             goto notsupported;
986         }
987         break;
988
989     case 8:
990         if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
991             /* ==== pal 8 bmp -> pal 4 dib ==== */
992             const void* srcbits;
993             const BYTE *srcpixel;
994             BYTE* dstbyte;
995
996             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
997             for (h=0; h<lines; h++) {
998                 BYTE dstval;
999                 srcpixel=srcbits;
1000                 dstbyte=dstbits;
1001                 dstval=0;
1002                 for (x=0; x<width; x++) {
1003                     PALETTEENTRY srcval;
1004                     srcval = srccolors[(int)*srcpixel++];
1005                     dstval|=(X11DRV_DIB_GetNearestIndex
1006                              (colors, 16,
1007                               srcval.peRed,
1008                               srcval.peGreen,
1009                               srcval.peBlue) << (4*(1-(x&1))) );
1010                     if ((x&1)==1) {
1011                         *dstbyte++=dstval;
1012                         dstval=0;
1013                     }
1014                 }
1015                 if ((width&1)!=0) {
1016                     *dstbyte=dstval;
1017                 }
1018                 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1019                 dstbits += linebytes;
1020             }
1021         } else {
1022             goto notsupported;
1023         }
1024         break;
1025
1026     case 15:
1027     case 16:
1028         {
1029             const void* srcbits;
1030             const WORD* srcpixel;
1031             BYTE* dstbyte;
1032
1033             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1034
1035             if (bmpImage->green_mask==0x03e0) {
1036                 if (bmpImage->red_mask==0x7c00) {
1037                     /* ==== rgb 555 bmp -> pal 4 dib ==== */
1038                     for (h=0; h<lines; h++) {
1039                         BYTE dstval;
1040                         srcpixel=srcbits;
1041                         dstbyte=dstbits;
1042                         dstval=0;
1043                         for (x=0; x<width; x++) {
1044                             WORD srcval;
1045                             srcval=*srcpixel++;
1046                             dstval|=(X11DRV_DIB_GetNearestIndex
1047                                      (colors, 16,
1048                                       ((srcval >>  7) & 0xf8) | /* r */
1049                                       ((srcval >> 12) & 0x07),
1050                                       ((srcval >>  2) & 0xf8) | /* g */
1051                                       ((srcval >>  7) & 0x07),
1052                                       ((srcval <<  3) & 0xf8) | /* b */
1053                                       ((srcval >>  2) & 0x07) ) << ((1-(x&1))<<2) );
1054                             if ((x&1)==1) {
1055                                 *dstbyte++=dstval;
1056                                 dstval=0;
1057                             }
1058                         }
1059                         if ((width&1)!=0) {
1060                             *dstbyte=dstval;
1061                         }
1062                         srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1063                         dstbits += linebytes;
1064                     }
1065                 } else if (bmpImage->blue_mask==0x7c00) {
1066                     /* ==== bgr 555 bmp -> pal 4 dib ==== */
1067                     for (h=0; h<lines; h++) {
1068                         WORD dstval;
1069                         srcpixel=srcbits;
1070                         dstbyte=dstbits;
1071                         dstval=0;
1072                         for (x=0; x<width; x++) {
1073                             WORD srcval;
1074                             srcval=*srcpixel++;
1075                             dstval|=(X11DRV_DIB_GetNearestIndex
1076                                      (colors, 16,
1077                                       ((srcval <<  3) & 0xf8) | /* r */
1078                                       ((srcval >>  2) & 0x07),
1079                                       ((srcval >>  2) & 0xf8) | /* g */
1080                                       ((srcval >>  7) & 0x07),
1081                                       ((srcval >>  7) & 0xf8) | /* b */
1082                                       ((srcval >> 12) & 0x07) ) << ((1-(x&1))<<2) );
1083                             if ((x&1)==1) {
1084                                 *dstbyte++=dstval;
1085                                 dstval=0;
1086                             }
1087                         }
1088                         if ((width&1)!=0) {
1089                             *dstbyte=dstval;
1090                         }
1091                         srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1092                         dstbits += linebytes;
1093                     }
1094                 } else {
1095                     goto notsupported;
1096                 }
1097             } else if (bmpImage->green_mask==0x07e0) {
1098                 if (bmpImage->red_mask==0xf800) {
1099                     /* ==== rgb 565 bmp -> pal 4 dib ==== */
1100                     for (h=0; h<lines; h++) {
1101                         BYTE dstval;
1102                         srcpixel=srcbits;
1103                         dstbyte=dstbits;
1104                         dstval=0;
1105                         for (x=0; x<width; x++) {
1106                             WORD srcval;
1107                             srcval=*srcpixel++;
1108                             dstval|=(X11DRV_DIB_GetNearestIndex
1109                                      (colors, 16,
1110                                       ((srcval >>  8) & 0xf8) | /* r */
1111                                       ((srcval >> 13) & 0x07),
1112                                       ((srcval >>  3) & 0xfc) | /* g */
1113                                       ((srcval >>  9) & 0x03),
1114                                       ((srcval <<  3) & 0xf8) | /* b */
1115                                       ((srcval >>  2) & 0x07) ) << ((1-(x&1))<<2) );
1116                             if ((x&1)==1) {
1117                                 *dstbyte++=dstval;
1118                                 dstval=0;
1119                             }
1120                         }
1121                         if ((width&1)!=0) {
1122                             *dstbyte=dstval;
1123                         }
1124                         srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1125                         dstbits += linebytes;
1126                     }
1127                 } else if (bmpImage->blue_mask==0xf800) {
1128                     /* ==== bgr 565 bmp -> pal 4 dib ==== */
1129                     for (h=0; h<lines; h++) {
1130                         WORD dstval;
1131                         srcpixel=srcbits;
1132                         dstbyte=dstbits;
1133                         dstval=0;
1134                         for (x=0; x<width; x++) {
1135                             WORD srcval;
1136                             srcval=*srcpixel++;
1137                             dstval|=(X11DRV_DIB_GetNearestIndex
1138                                      (colors, 16,
1139                                       ((srcval <<  3) & 0xf8) | /* r */
1140                                       ((srcval >>  2) & 0x07),
1141                                       ((srcval >>  3) & 0xfc) | /* g */
1142                                       ((srcval >>  9) & 0x03),
1143                                       ((srcval >>  8) & 0xf8) | /* b */
1144                                       ((srcval >> 13) & 0x07) ) << ((1-(x&1))<<2) );
1145                             if ((x&1)==1) {
1146                                 *dstbyte++=dstval;
1147                                 dstval=0;
1148                             }
1149                         }
1150                         if ((width&1)!=0) {
1151                             *dstbyte=dstval;
1152                         }
1153                         srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1154                         dstbits += linebytes;
1155                     }
1156                 } else {
1157                     goto notsupported;
1158                 }
1159             } else {
1160                 goto notsupported;
1161             }
1162         }
1163         break;
1164
1165     case 24:
1166         if (bmpImage->bits_per_pixel==24) {
1167             const void* srcbits;
1168             const BYTE *srcbyte;
1169             BYTE* dstbyte;
1170
1171             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1172
1173             if (bmpImage->green_mask!=0x00ff00 ||
1174                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
1175                 goto notsupported;
1176             } else if (bmpImage->blue_mask==0xff) {
1177                 /* ==== rgb 888 bmp -> pal 4 dib ==== */
1178                 for (h=0; h<lines; h++) {
1179                     srcbyte=srcbits;
1180                     dstbyte=dstbits;
1181                     for (x=0; x<width/2; x++) {
1182                         /* Do 2 pixels at a time */
1183                         *dstbyte++=(X11DRV_DIB_GetNearestIndex
1184                                     (colors, 16,
1185                                      srcbyte[2],
1186                                      srcbyte[1],
1187                                      srcbyte[0]) << 4) |
1188                                     X11DRV_DIB_GetNearestIndex
1189                                     (colors, 16,
1190                                      srcbyte[5],
1191                                      srcbyte[4],
1192                                      srcbyte[3]);
1193                         srcbyte+=6;
1194                     }
1195                     if (width&1) {
1196                         /* And the the odd pixel */
1197                         *dstbyte++=(X11DRV_DIB_GetNearestIndex
1198                                     (colors, 16,
1199                                      srcbyte[2],
1200                                      srcbyte[1],
1201                                      srcbyte[0]) << 4);
1202                     }
1203                     srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1204                     dstbits += linebytes;
1205                 }
1206             } else {
1207                 /* ==== bgr 888 bmp -> pal 4 dib ==== */
1208                 for (h=0; h<lines; h++) {
1209                     srcbyte=srcbits;
1210                     dstbyte=dstbits;
1211                     for (x=0; x<width/2; x++) {
1212                         /* Do 2 pixels at a time */
1213                         *dstbyte++=(X11DRV_DIB_GetNearestIndex
1214                                     (colors, 16,
1215                                      srcbyte[0],
1216                                      srcbyte[1],
1217                                      srcbyte[2]) << 4) |
1218                                     X11DRV_DIB_GetNearestIndex
1219                                     (colors, 16,
1220                                      srcbyte[3],
1221                                      srcbyte[4],
1222                                      srcbyte[5]);
1223                         srcbyte+=6;
1224                     }
1225                     if (width&1) {
1226                         /* And the the odd pixel */
1227                         *dstbyte++=(X11DRV_DIB_GetNearestIndex
1228                                     (colors, 16,
1229                                      srcbyte[0],
1230                                      srcbyte[1],
1231                                      srcbyte[2]) << 4);
1232                     }
1233                     srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1234                     dstbits += linebytes;
1235                 }
1236             }
1237             break;
1238         }
1239         /* Fall through */
1240
1241     case 32:
1242         {
1243             const void* srcbits;
1244             const BYTE *srcbyte;
1245             BYTE* dstbyte;
1246
1247             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1248
1249             if (bmpImage->green_mask!=0x00ff00 ||
1250                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
1251                 goto notsupported;
1252             } else if (bmpImage->blue_mask==0xff) {
1253                 /* ==== rgb 0888 bmp -> pal 4 dib ==== */
1254                 for (h=0; h<lines; h++) {
1255                     srcbyte=srcbits;
1256                     dstbyte=dstbits;
1257                     for (x=0; x<width/2; x++) {
1258                         /* Do 2 pixels at a time */
1259                         *dstbyte++=(X11DRV_DIB_GetNearestIndex
1260                                     (colors, 16,
1261                                      srcbyte[2],
1262                                      srcbyte[1],
1263                                      srcbyte[0]) << 4) |
1264                                     X11DRV_DIB_GetNearestIndex
1265                                     (colors, 16,
1266                                      srcbyte[6],
1267                                      srcbyte[5],
1268                                      srcbyte[4]);
1269                         srcbyte+=8;
1270                     }
1271                     if (width&1) {
1272                         /* And the the odd pixel */
1273                         *dstbyte++=(X11DRV_DIB_GetNearestIndex
1274                                     (colors, 16,
1275                                      srcbyte[2],
1276                                      srcbyte[1],
1277                                      srcbyte[0]) << 4);
1278                     }
1279                     srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1280                     dstbits += linebytes;
1281                 }
1282             } else {
1283                 /* ==== bgr 0888 bmp -> pal 4 dib ==== */
1284                 for (h=0; h<lines; h++) {
1285                     srcbyte=srcbits;
1286                     dstbyte=dstbits;
1287                     for (x=0; x<width/2; x++) {
1288                         /* Do 2 pixels at a time */
1289                         *dstbyte++=(X11DRV_DIB_GetNearestIndex
1290                                     (colors, 16,
1291                                      srcbyte[0],
1292                                      srcbyte[1],
1293                                      srcbyte[2]) << 4) |
1294                                     X11DRV_DIB_GetNearestIndex
1295                                     (colors, 16,
1296                                      srcbyte[4],
1297                                      srcbyte[5],
1298                                      srcbyte[6]);
1299                         srcbyte+=8;
1300                     }
1301                     if (width&1) {
1302                         /* And the the odd pixel */
1303                         *dstbyte++=(X11DRV_DIB_GetNearestIndex
1304                                     (colors, 16,
1305                                      srcbyte[0],
1306                                      srcbyte[1],
1307                                      srcbyte[2]) << 4);
1308                     }
1309                     srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1310                     dstbits += linebytes;
1311                 }
1312             }
1313         }
1314         break;
1315
1316     default:
1317     notsupported:
1318         {
1319             BYTE* dstbyte;
1320
1321             /* ==== any bmp format -> pal 4 dib ==== */
1322             WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 4 bit DIB\n",
1323                   bmpImage->bits_per_pixel, bmpImage->red_mask,
1324                   bmpImage->green_mask, bmpImage->blue_mask );
1325             for (h=lines-1; h>=0; h--) {
1326                 dstbyte=dstbits;
1327                 for (x=0; x<(width & ~1); x+=2) {
1328                     *dstbyte++=(X11DRV_DIB_MapColor((int*)colors, 16, XGetPixel(bmpImage, x, h), 0) << 4) |
1329                         X11DRV_DIB_MapColor((int*)colors, 16, XGetPixel(bmpImage, x+1, h), 0);
1330                 }
1331                 if (width & 1) {
1332                     *dstbyte=(X11DRV_DIB_MapColor((int *)colors, 16, XGetPixel(bmpImage, x, h), 0) << 4);
1333                 }
1334                 dstbits += linebytes;
1335             }
1336         }
1337         break;
1338     }
1339 }
1340
1341 /***********************************************************************
1342  *           X11DRV_DIB_SetImageBits_RLE4
1343  *
1344  * SetDIBits for a 4-bit deep compressed DIB.
1345  */
1346 static void X11DRV_DIB_SetImageBits_RLE4( int lines, const BYTE *bits,
1347                                           DWORD srcwidth, DWORD dstwidth,
1348                                           int left, int *colors,
1349                                           XImage *bmpImage )
1350 {
1351     unsigned int x = 0, width = min(srcwidth, dstwidth);
1352     int y = lines - 1, c, length;
1353     const BYTE *begin = bits;
1354
1355     while (y >= 0)
1356     {
1357         length = *bits++;
1358         if (length) {   /* encoded */
1359             c = *bits++;
1360             while (length--) {
1361                 if (x >= width) break;
1362                 XPutPixel(bmpImage, x++, y, colors[c >> 4]);
1363                 if (!length--) break;
1364                 if (x >= width) break;
1365                 XPutPixel(bmpImage, x++, y, colors[c & 0xf]);
1366             }
1367         } else {
1368             length = *bits++;
1369             switch (length)
1370             {
1371             case RLE_EOL:
1372                 x = 0;
1373                 y--;
1374                 break;
1375
1376             case RLE_END:
1377                 return;
1378
1379             case RLE_DELTA:
1380                 x += *bits++;
1381                 y -= *bits++;
1382                 break;
1383
1384             default: /* absolute */
1385                 while (length--) {
1386                     c = *bits++;
1387                     if (x < width) XPutPixel(bmpImage, x++, y, colors[c >> 4]);
1388                     if (!length--) break;
1389                     if (x < width) XPutPixel(bmpImage, x++, y, colors[c & 0xf]);
1390                 }
1391                 if ((bits - begin) & 1)
1392                     bits++;
1393             }
1394         }
1395     }
1396 }
1397
1398
1399
1400 /***********************************************************************
1401  *           X11DRV_DIB_SetImageBits_8
1402  *
1403  * SetDIBits for an 8-bit deep DIB.
1404  */
1405 static void X11DRV_DIB_SetImageBits_8( int lines, const BYTE *srcbits,
1406                                 DWORD srcwidth, DWORD dstwidth, int left,
1407                                 const int *colors, XImage *bmpImage,
1408                                 DWORD linebytes )
1409 {
1410     DWORD x;
1411     int h, width = min(srcwidth, dstwidth);
1412     const BYTE* srcbyte;
1413     BYTE* dstbits;
1414
1415     if (lines < 0 )
1416     {
1417         lines = -lines;
1418         srcbits = srcbits + linebytes * (lines-1);
1419         linebytes = -linebytes;
1420     }
1421     srcbits += left;
1422     srcbyte = srcbits;
1423
1424     switch (bmpImage->depth) {
1425     case 15:
1426     case 16:
1427 #if defined(__i386__) && defined(__GNUC__)
1428         /* Some X servers might have 32 bit/ 16bit deep pixel */
1429         if (lines && width && (bmpImage->bits_per_pixel == 16) &&
1430             (ImageByteOrder(gdi_display)==LSBFirst) )
1431         {
1432             dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
1433             /* FIXME: Does this really handle all these cases correctly? */
1434             /* ==== pal 8 dib -> rgb or bgr 555 or 565 bmp ==== */
1435             for (h = lines ; h--; ) {
1436                 int _cl1,_cl2; /* temp outputs for asm below */
1437                 /* Borrowed from DirectDraw */
1438                 __asm__ __volatile__(
1439                 "xor %%eax,%%eax\n"
1440                 "cld\n"
1441                 "1:\n"
1442                 "    lodsb\n"
1443                 "    movw (%%edx,%%eax,4),%%ax\n"
1444                 "    stosw\n"
1445                 "      xor %%eax,%%eax\n"
1446                 "    loop 1b\n"
1447                 :"=S" (srcbyte), "=D" (_cl1), "=c" (_cl2)
1448                 :"S" (srcbyte),
1449                  "D" (dstbits),
1450                  "c" (width),
1451                  "d" (colors)
1452                 :"eax", "cc", "memory"
1453                 );
1454                 srcbyte = (srcbits += linebytes);
1455                 dstbits -= bmpImage->bytes_per_line;
1456             }
1457             return;
1458         }
1459         break;
1460 #endif
1461     case 24:
1462     case 32:
1463 #if defined(__i386__) && defined(__GNUC__)
1464         if (lines && width && (bmpImage->bits_per_pixel == 32) &&
1465             (ImageByteOrder(gdi_display)==LSBFirst) )
1466         {
1467             dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
1468             /* FIXME: Does this really handle both cases correctly? */
1469             /* ==== pal 8 dib -> rgb or bgr 0888 bmp ==== */
1470             for (h = lines ; h--; ) {
1471                 int _cl1,_cl2; /* temp outputs for asm below */
1472                 /* Borrowed from DirectDraw */
1473                 __asm__ __volatile__(
1474                 "xor %%eax,%%eax\n"
1475                 "cld\n"
1476                 "1:\n"
1477                 "    lodsb\n"
1478                 "    movl (%%edx,%%eax,4),%%eax\n"
1479                 "    stosl\n"
1480                 "      xor %%eax,%%eax\n"
1481                 "    loop 1b\n"
1482                 :"=S" (srcbyte), "=D" (_cl1), "=c" (_cl2)
1483                 :"S" (srcbyte),
1484                  "D" (dstbits),
1485                  "c" (width),
1486                  "d" (colors)
1487                 :"eax", "cc", "memory"
1488                 );
1489                 srcbyte = (srcbits += linebytes);
1490                 dstbits -= bmpImage->bytes_per_line;
1491             }
1492             return;
1493         }
1494         break;
1495 #endif
1496     default:
1497         break; /* use slow generic case below */
1498     }
1499
1500     /* ==== pal 8 dib -> any bmp format ==== */
1501     for (h=lines-1; h>=0; h--) {
1502         for (x=left; x<width+left; x++) {
1503             XPutPixel(bmpImage, x, h, colors[*srcbyte++]);
1504         }
1505         srcbyte = (srcbits += linebytes);
1506     }
1507 }
1508
1509 /***********************************************************************
1510  *           X11DRV_DIB_GetImageBits_8
1511  *
1512  * GetDIBits for an 8-bit deep DIB.
1513  */
1514 static void X11DRV_DIB_GetImageBits_8( int lines, BYTE *dstbits,
1515                                        DWORD srcwidth, DWORD dstwidth,
1516                                        RGBQUAD *colors, PALETTEENTRY *srccolors,
1517                                        XImage *bmpImage, DWORD linebytes )
1518 {
1519     DWORD x;
1520     int h, width = min(srcwidth, dstwidth);
1521     BYTE* dstbyte;
1522
1523     if (lines < 0 )
1524     {
1525        lines = -lines;
1526        dstbits = dstbits + ( linebytes * (lines-1) );
1527        linebytes = -linebytes;
1528     }
1529
1530     /*
1531      * Hack for now
1532      * This condition is true when GetImageBits has been called by
1533      * UpdateDIBSection. For now, GetNearestIndex is too slow to support
1534      * 256 colormaps, so we'll just use for for GetDIBits calls.
1535      * (In somes cases, in a updateDIBSection, the returned colors are bad too)
1536      */
1537     if (!srccolors) goto updatesection;
1538
1539     switch (bmpImage->depth) {
1540     case 1:
1541     case 4:
1542         if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
1543
1544             /* ==== pal 1 bmp -> pal 8 dib ==== */
1545             /* ==== pal 4 bmp -> pal 8 dib ==== */
1546             for (h=lines-1; h>=0; h--) {
1547                 dstbyte=dstbits;
1548                 for (x=0; x<width; x++) {
1549                     PALETTEENTRY srcval;
1550                     srcval=srccolors[XGetPixel(bmpImage, x, h)];
1551                     *dstbyte++=X11DRV_DIB_GetNearestIndex(colors, 256,
1552                                                           srcval.peRed,
1553                                                           srcval.peGreen,
1554                                                           srcval.peBlue);
1555                 }
1556                 dstbits += linebytes;
1557             }
1558         } else {
1559             goto notsupported;
1560         }
1561         break;
1562
1563     case 8:
1564        if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
1565             /* ==== pal 8 bmp -> pal 8 dib ==== */
1566            const void* srcbits;
1567            const BYTE* srcpixel;
1568
1569            srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1570            for (h=0; h<lines; h++) {
1571                srcpixel=srcbits;
1572                dstbyte=dstbits;
1573                for (x = 0; x < width; x++) {
1574                    PALETTEENTRY srcval;
1575                    srcval=srccolors[(int)*srcpixel++];
1576                    *dstbyte++=X11DRV_DIB_GetNearestIndex(colors, 256,
1577                                                          srcval.peRed,
1578                                                          srcval.peGreen,
1579                                                          srcval.peBlue);
1580                }
1581                srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1582                dstbits += linebytes;
1583            }
1584        } else {
1585            goto notsupported;
1586        }
1587        break;
1588
1589     case 15:
1590     case 16:
1591         {
1592             const void* srcbits;
1593             const WORD* srcpixel;
1594             BYTE* dstbyte;
1595
1596             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1597
1598             if (bmpImage->green_mask==0x03e0) {
1599                 if (bmpImage->red_mask==0x7c00) {
1600                     /* ==== rgb 555 bmp -> pal 8 dib ==== */
1601                     for (h=0; h<lines; h++) {
1602                         srcpixel=srcbits;
1603                         dstbyte=dstbits;
1604                         for (x=0; x<width; x++) {
1605                             WORD srcval;
1606                             srcval=*srcpixel++;
1607                             *dstbyte++=X11DRV_DIB_GetNearestIndex
1608                                 (colors, 256,
1609                                  ((srcval >>  7) & 0xf8) | /* r */
1610                                  ((srcval >> 12) & 0x07),
1611                                  ((srcval >>  2) & 0xf8) | /* g */
1612                                  ((srcval >>  7) & 0x07),
1613                                  ((srcval <<  3) & 0xf8) | /* b */
1614                                  ((srcval >>  2) & 0x07) );
1615                         }
1616                         srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1617                         dstbits += linebytes;
1618                     }
1619                 } else if (bmpImage->blue_mask==0x7c00) {
1620                     /* ==== bgr 555 bmp -> pal 8 dib ==== */
1621                     for (h=0; h<lines; h++) {
1622                         srcpixel=srcbits;
1623                         dstbyte=dstbits;
1624                         for (x=0; x<width; x++) {
1625                             WORD srcval;
1626                             srcval=*srcpixel++;
1627                             *dstbyte++=X11DRV_DIB_GetNearestIndex
1628                                 (colors, 256,
1629                                  ((srcval <<  3) & 0xf8) | /* r */
1630                                  ((srcval >>  2) & 0x07),
1631                                  ((srcval >>  2) & 0xf8) | /* g */
1632                                  ((srcval >>  7) & 0x07),
1633                                  ((srcval >>  7) & 0xf8) | /* b */
1634                                  ((srcval >> 12) & 0x07) );
1635                         }
1636                         srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1637                         dstbits += linebytes;
1638                     }
1639                 } else {
1640                     goto notsupported;
1641                 }
1642             } else if (bmpImage->green_mask==0x07e0) {
1643                 if (bmpImage->red_mask==0xf800) {
1644                     /* ==== rgb 565 bmp -> pal 8 dib ==== */
1645                     for (h=0; h<lines; h++) {
1646                         srcpixel=srcbits;
1647                         dstbyte=dstbits;
1648                         for (x=0; x<width; x++) {
1649                             WORD srcval;
1650                             srcval=*srcpixel++;
1651                             *dstbyte++=X11DRV_DIB_GetNearestIndex
1652                                 (colors, 256,
1653                                  ((srcval >>  8) & 0xf8) | /* r */
1654                                  ((srcval >> 13) & 0x07),
1655                                  ((srcval >>  3) & 0xfc) | /* g */
1656                                  ((srcval >>  9) & 0x03),
1657                                  ((srcval <<  3) & 0xf8) | /* b */
1658                                  ((srcval >>  2) & 0x07) );
1659                         }
1660                         srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1661                         dstbits += linebytes;
1662                     }
1663                 } else if (bmpImage->blue_mask==0xf800) {
1664                     /* ==== bgr 565 bmp -> pal 8 dib ==== */
1665                     for (h=0; h<lines; h++) {
1666                         srcpixel=srcbits;
1667                         dstbyte=dstbits;
1668                         for (x=0; x<width; x++) {
1669                             WORD srcval;
1670                             srcval=*srcpixel++;
1671                             *dstbyte++=X11DRV_DIB_GetNearestIndex
1672                                 (colors, 256,
1673                                  ((srcval <<  3) & 0xf8) | /* r */
1674                                  ((srcval >>  2) & 0x07),
1675                                  ((srcval >>  3) & 0xfc) | /* g */
1676                                  ((srcval >>  9) & 0x03),
1677                                  ((srcval >>  8) & 0xf8) | /* b */
1678                                  ((srcval >> 13) & 0x07) );
1679                         }
1680                         srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1681                         dstbits += linebytes;
1682                     }
1683                 } else {
1684                     goto notsupported;
1685                 }
1686             } else {
1687                 goto notsupported;
1688             }
1689         }
1690         break;
1691
1692     case 24:
1693     case 32:
1694         {
1695             const void* srcbits;
1696             const BYTE *srcbyte;
1697             BYTE* dstbyte;
1698             int bytes_per_pixel;
1699
1700             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1701             bytes_per_pixel=(bmpImage->bits_per_pixel==24?3:4);
1702
1703             if (bmpImage->green_mask!=0x00ff00 ||
1704                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
1705                 goto notsupported;
1706             } else if (bmpImage->blue_mask==0xff) {
1707                 /* ==== rgb 888 or 0888 bmp -> pal 8 dib ==== */
1708                 for (h=0; h<lines; h++) {
1709                     srcbyte=srcbits;
1710                     dstbyte=dstbits;
1711                     for (x=0; x<width; x++) {
1712                         *dstbyte++=X11DRV_DIB_GetNearestIndex
1713                             (colors, 256,
1714                              srcbyte[2],
1715                              srcbyte[1],
1716                              srcbyte[0]);
1717                         srcbyte+=bytes_per_pixel;
1718                     }
1719                     srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1720                     dstbits += linebytes;
1721                 }
1722             } else {
1723                 /* ==== bgr 888 or 0888 bmp -> pal 8 dib ==== */
1724                 for (h=0; h<lines; h++) {
1725                     srcbyte=srcbits;
1726                     dstbyte=dstbits;
1727                     for (x=0; x<width; x++) {
1728                         *dstbyte++=X11DRV_DIB_GetNearestIndex
1729                             (colors, 256,
1730                              srcbyte[0],
1731                              srcbyte[1],
1732                              srcbyte[2]);
1733                         srcbyte+=bytes_per_pixel;
1734                     }
1735                     srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1736                     dstbits += linebytes;
1737                 }
1738             }
1739         }
1740         break;
1741
1742     default:
1743     notsupported:
1744         WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 8 bit DIB\n",
1745               bmpImage->depth, bmpImage->red_mask,
1746               bmpImage->green_mask, bmpImage->blue_mask );
1747     updatesection:
1748         /* ==== any bmp format -> pal 8 dib ==== */
1749         for (h=lines-1; h>=0; h--) {
1750             dstbyte=dstbits;
1751             for (x=0; x<width; x++) {
1752                 *dstbyte=X11DRV_DIB_MapColor
1753                     ((int*)colors, 256,
1754                      XGetPixel(bmpImage, x, h), *dstbyte);
1755                 dstbyte++;
1756             }
1757             dstbits += linebytes;
1758         }
1759         break;
1760     }
1761 }
1762
1763 /***********************************************************************
1764  *            X11DRV_DIB_SetImageBits_RLE8
1765  *
1766  * SetDIBits for an 8-bit deep compressed DIB.
1767  *
1768  * This function rewritten 941113 by James Youngman.  WINE blew out when I
1769  * first ran it because my desktop wallpaper is a (large) RLE8 bitmap.
1770  *
1771  * This was because the algorithm assumed that all RLE8 bitmaps end with the
1772  * 'End of bitmap' escape code.  This code is very much laxer in what it
1773  * allows to end the expansion.  Possibly too lax.  See the note by
1774  * case RleDelta.  BTW, MS's documentation implies that a correct RLE8
1775  * bitmap should end with RleEnd, but on the other hand, software exists
1776  * that produces ones that don't and Windows 3.1 doesn't complain a bit
1777  * about it.
1778  *
1779  * (No) apologies for my English spelling.  [Emacs users: c-indent-level=4].
1780  *                      James A. Youngman <mbcstjy@afs.man.ac.uk>
1781  *                                              [JAY]
1782  */
1783 static void X11DRV_DIB_SetImageBits_RLE8( int lines, const BYTE *bits,
1784                                           DWORD srcwidth, DWORD dstwidth,
1785                                           int left, int *colors,
1786                                           XImage *bmpImage )
1787 {
1788     unsigned int x;             /* X-position on each line.  Increases. */
1789     int y;                      /* Line #.  Starts at lines-1, decreases */
1790     const BYTE *pIn = bits;     /* Pointer to current position in bits */
1791     BYTE length;                /* The length pf a run */
1792     BYTE escape_code;           /* See enum Rle8_EscapeCodes.*/
1793
1794     /*
1795      * Note that the bitmap data is stored by Windows starting at the
1796      * bottom line of the bitmap and going upwards.  Within each line,
1797      * the data is stored left-to-right.  That's the reason why line
1798      * goes from lines-1 to 0.                  [JAY]
1799      */
1800
1801     x = 0;
1802     y = lines - 1;
1803     while (y >= 0)
1804     {
1805         length = *pIn++;
1806
1807         /*
1808          * If the length byte is not zero (which is the escape value),
1809          * We have a run of length pixels all the same colour.  The colour
1810          * index is stored next.
1811          *
1812          * If the length byte is zero, we need to read the next byte to
1813          * know what to do.                     [JAY]
1814          */
1815         if (length != 0)
1816         {
1817             /*
1818              * [Run-Length] Encoded mode
1819              */
1820             int color = colors[*pIn++];
1821             while (length-- && x < dstwidth) XPutPixel(bmpImage, x++, y, color);
1822         }
1823         else
1824         {
1825             /*
1826              * Escape codes (may be an absolute sequence though)
1827              */
1828             escape_code = (*pIn++);
1829             switch(escape_code)
1830             {
1831             case RLE_EOL:
1832                 x = 0;
1833                 y--;
1834                 break;
1835
1836             case RLE_END:
1837                 /* Not all RLE8 bitmaps end with this code.  For
1838                  * example, Paint Shop Pro produces some that don't.
1839                  * That's (I think) what caused the previous
1840                  * implementation to fail.  [JAY]
1841                  */
1842                 return;
1843
1844             case RLE_DELTA:
1845                 x += (*pIn++);
1846                 y -= (*pIn++);
1847                 break;
1848
1849             default:  /* switch to absolute mode */
1850                 length = escape_code;
1851                 while (length--)
1852                 {
1853                     int color = colors[*pIn++];
1854                     if (x >= dstwidth)
1855                     {
1856                         pIn += length;
1857                         break;
1858                     }
1859                     XPutPixel(bmpImage, x++, y, color);
1860                 }
1861                 /*
1862                  * If you think for a moment you'll realise that the
1863                  * only time we could ever possibly read an odd
1864                  * number of bytes is when there is a 0x00 (escape),
1865                  * a value >0x02 (absolute mode) and then an odd-
1866                  * length run.  Therefore this is the only place we
1867                  * need to worry about it.  Everywhere else the
1868                  * bytes are always read in pairs.  [JAY]
1869                  */
1870                 if (escape_code & 1) pIn++; /* Throw away the pad byte. */
1871                 break;
1872             } /* switch (escape_code) : Escape sequence */
1873         }
1874     }
1875 }
1876
1877
1878 /***********************************************************************
1879  *           X11DRV_DIB_SetImageBits_16
1880  *
1881  * SetDIBits for a 16-bit deep DIB.
1882  */
1883 static void X11DRV_DIB_SetImageBits_16( int lines, const BYTE *srcbits,
1884                                  DWORD srcwidth, DWORD dstwidth, int left,
1885                                        X11DRV_PDEVICE *physDev, DWORD rSrc, DWORD gSrc, DWORD bSrc,
1886                                        XImage *bmpImage, DWORD linebytes )
1887 {
1888     DWORD x;
1889     int h, width = min(srcwidth, dstwidth);
1890     const dib_conversions *convs = (bmpImage->byte_order == LSBFirst) ? &dib_normal : &dib_dst_byteswap;
1891
1892     if (lines < 0 )
1893     {
1894         lines = -lines;
1895         srcbits = srcbits + ( linebytes * (lines-1));
1896         linebytes = -linebytes;
1897     }
1898
1899     switch (bmpImage->depth)
1900     {
1901     case 15:
1902     case 16:
1903         {
1904             char* dstbits;
1905
1906             srcbits=srcbits+left*2;
1907             dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
1908
1909             if (bmpImage->green_mask==0x03e0) {
1910                 if (gSrc==bmpImage->green_mask) {
1911                     if (rSrc==bmpImage->red_mask) {
1912                         /* ==== rgb 555 dib -> rgb 555 bmp ==== */
1913                         /* ==== bgr 555 dib -> bgr 555 bmp ==== */
1914                         convs->Convert_5x5_asis
1915                             (width,lines,
1916                              srcbits,linebytes,
1917                              dstbits,-bmpImage->bytes_per_line);
1918                     } else if (rSrc==bmpImage->blue_mask) {
1919                         /* ==== rgb 555 dib -> bgr 555 bmp ==== */
1920                         /* ==== bgr 555 dib -> rgb 555 bmp ==== */
1921                         convs->Convert_555_reverse
1922                             (width,lines,
1923                              srcbits,linebytes,
1924                              dstbits,-bmpImage->bytes_per_line);
1925                     }
1926                 } else {
1927                     if (rSrc==bmpImage->red_mask || bSrc==bmpImage->blue_mask) {
1928                         /* ==== rgb 565 dib -> rgb 555 bmp ==== */
1929                         /* ==== bgr 565 dib -> bgr 555 bmp ==== */
1930                         convs->Convert_565_to_555_asis
1931                             (width,lines,
1932                              srcbits,linebytes,
1933                              dstbits,-bmpImage->bytes_per_line);
1934                     } else {
1935                         /* ==== rgb 565 dib -> bgr 555 bmp ==== */
1936                         /* ==== bgr 565 dib -> rgb 555 bmp ==== */
1937                         convs->Convert_565_to_555_reverse
1938                             (width,lines,
1939                              srcbits,linebytes,
1940                              dstbits,-bmpImage->bytes_per_line);
1941                     }
1942                 }
1943             } else if (bmpImage->green_mask==0x07e0) {
1944                 if (gSrc==bmpImage->green_mask) {
1945                     if (rSrc==bmpImage->red_mask) {
1946                         /* ==== rgb 565 dib -> rgb 565 bmp ==== */
1947                         /* ==== bgr 565 dib -> bgr 565 bmp ==== */
1948                         convs->Convert_5x5_asis
1949                             (width,lines,
1950                              srcbits,linebytes,
1951                              dstbits,-bmpImage->bytes_per_line);
1952                     } else {
1953                         /* ==== rgb 565 dib -> bgr 565 bmp ==== */
1954                         /* ==== bgr 565 dib -> rgb 565 bmp ==== */
1955                         convs->Convert_565_reverse
1956                             (width,lines,
1957                              srcbits,linebytes,
1958                              dstbits,-bmpImage->bytes_per_line);
1959                     }
1960                 } else {
1961                     if (rSrc==bmpImage->red_mask || bSrc==bmpImage->blue_mask) {
1962                         /* ==== rgb 555 dib -> rgb 565 bmp ==== */
1963                         /* ==== bgr 555 dib -> bgr 565 bmp ==== */
1964                         convs->Convert_555_to_565_asis
1965                             (width,lines,
1966                              srcbits,linebytes,
1967                              dstbits,-bmpImage->bytes_per_line);
1968                     } else {
1969                         /* ==== rgb 555 dib -> bgr 565 bmp ==== */
1970                         /* ==== bgr 555 dib -> rgb 565 bmp ==== */
1971                         convs->Convert_555_to_565_reverse
1972                             (width,lines,
1973                              srcbits,linebytes,
1974                              dstbits,-bmpImage->bytes_per_line);
1975                     }
1976                 }
1977             } else {
1978                 goto notsupported;
1979             }
1980         }
1981         break;
1982
1983     case 24:
1984         if (bmpImage->bits_per_pixel==24) {
1985             char* dstbits;
1986
1987             srcbits=srcbits+left*2;
1988             dstbits=bmpImage->data+left*3+(lines-1)*bmpImage->bytes_per_line;
1989
1990             if (bmpImage->green_mask!=0x00ff00 ||
1991                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
1992                 goto notsupported;
1993             } else if ((rSrc==0x1f && bmpImage->red_mask==0xff) ||
1994                        (bSrc==0x1f && bmpImage->blue_mask==0xff)) {
1995                 if (gSrc==0x03e0) {
1996                     /* ==== rgb 555 dib -> rgb 888 bmp ==== */
1997                     /* ==== bgr 555 dib -> bgr 888 bmp ==== */
1998                     convs->Convert_555_to_888_asis
1999                         (width,lines,
2000                          srcbits,linebytes,
2001                          dstbits,-bmpImage->bytes_per_line);
2002                 } else {
2003                     /* ==== rgb 565 dib -> rgb 888 bmp ==== */
2004                     /* ==== bgr 565 dib -> bgr 888 bmp ==== */
2005                     convs->Convert_565_to_888_asis
2006                         (width,lines,
2007                          srcbits,linebytes,
2008                          dstbits,-bmpImage->bytes_per_line);
2009                 }
2010             } else {
2011                 if (gSrc==0x03e0) {
2012                     /* ==== rgb 555 dib -> bgr 888 bmp ==== */
2013                     /* ==== bgr 555 dib -> rgb 888 bmp ==== */
2014                     convs->Convert_555_to_888_reverse
2015                         (width,lines,
2016                          srcbits,linebytes,
2017                          dstbits,-bmpImage->bytes_per_line);
2018                 } else {
2019                     /* ==== rgb 565 dib -> bgr 888 bmp ==== */
2020                     /* ==== bgr 565 dib -> rgb 888 bmp ==== */
2021                     convs->Convert_565_to_888_reverse
2022                         (width,lines,
2023                          srcbits,linebytes,
2024                          dstbits,-bmpImage->bytes_per_line);
2025                 }
2026             }
2027             break;
2028         }
2029         /* Fall through */
2030
2031     case 32:
2032         {
2033             char* dstbits;
2034
2035             srcbits=srcbits+left*2;
2036             dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
2037
2038             if (bmpImage->green_mask!=0x00ff00 ||
2039                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2040                 goto notsupported;
2041             } else if ((rSrc==0x1f && bmpImage->red_mask==0xff) ||
2042                        (bSrc==0x1f && bmpImage->blue_mask==0xff)) {
2043                 if (gSrc==0x03e0) {
2044                     /* ==== rgb 555 dib -> rgb 0888 bmp ==== */
2045                     /* ==== bgr 555 dib -> bgr 0888 bmp ==== */
2046                     convs->Convert_555_to_0888_asis
2047                         (width,lines,
2048                          srcbits,linebytes,
2049                          dstbits,-bmpImage->bytes_per_line);
2050                 } else {
2051                     /* ==== rgb 565 dib -> rgb 0888 bmp ==== */
2052                     /* ==== bgr 565 dib -> bgr 0888 bmp ==== */
2053                     convs->Convert_565_to_0888_asis
2054                         (width,lines,
2055                          srcbits,linebytes,
2056                          dstbits,-bmpImage->bytes_per_line);
2057                 }
2058             } else {
2059                 if (gSrc==0x03e0) {
2060                     /* ==== rgb 555 dib -> bgr 0888 bmp ==== */
2061                     /* ==== bgr 555 dib -> rgb 0888 bmp ==== */
2062                     convs->Convert_555_to_0888_reverse
2063                         (width,lines,
2064                          srcbits,linebytes,
2065                          dstbits,-bmpImage->bytes_per_line);
2066                 } else {
2067                     /* ==== rgb 565 dib -> bgr 0888 bmp ==== */
2068                     /* ==== bgr 565 dib -> rgb 0888 bmp ==== */
2069                     convs->Convert_565_to_0888_reverse
2070                         (width,lines,
2071                          srcbits,linebytes,
2072                          dstbits,-bmpImage->bytes_per_line);
2073                 }
2074             }
2075         }
2076         break;
2077
2078     default:
2079     notsupported:
2080         WARN("from 16 bit DIB (%lx,%lx,%lx) to unknown %d bit bitmap (%lx,%lx,%lx)\n",
2081               rSrc, gSrc, bSrc, bmpImage->bits_per_pixel, bmpImage->red_mask,
2082               bmpImage->green_mask, bmpImage->blue_mask );
2083         /* fall through */
2084     case 1:
2085     case 4:
2086     case 8:
2087         {
2088             /* ==== rgb or bgr 555 or 565 dib -> pal 1, 4 or 8 ==== */
2089             const WORD* srcpixel;
2090             int rShift1,gShift1,bShift1;
2091             int rShift2,gShift2,bShift2;
2092             BYTE gMask1,gMask2;
2093
2094             /* Set color scaling values */
2095             rShift1=16+X11DRV_DIB_MaskToShift(rSrc)-3;
2096             gShift1=16+X11DRV_DIB_MaskToShift(gSrc)-3;
2097             bShift1=16+X11DRV_DIB_MaskToShift(bSrc)-3;
2098             rShift2=rShift1+5;
2099             gShift2=gShift1+5;
2100             bShift2=bShift1+5;
2101             if (gSrc==0x03e0) {
2102                 /* Green has 5 bits, like the others */
2103                 gMask1=0xf8;
2104                 gMask2=0x07;
2105             } else {
2106                 /* Green has 6 bits, not 5. Compensate. */
2107                 gShift1++;
2108                 gShift2+=2;
2109                 gMask1=0xfc;
2110                 gMask2=0x03;
2111             }
2112
2113             srcbits+=2*left;
2114
2115             /* We could split it into four separate cases to optimize
2116              * but it is probably not worth it.
2117              */
2118             for (h=lines-1; h>=0; h--) {
2119                 srcpixel=(const WORD*)srcbits;
2120                 for (x=left; x<width+left; x++) {
2121                     DWORD srcval;
2122                     BYTE red,green,blue;
2123                     srcval=*srcpixel++ << 16;
2124                     red=  ((srcval >> rShift1) & 0xf8) |
2125                         ((srcval >> rShift2) & 0x07);
2126                     green=((srcval >> gShift1) & gMask1) |
2127                         ((srcval >> gShift2) & gMask2);
2128                     blue= ((srcval >> bShift1) & 0xf8) |
2129                         ((srcval >> bShift2) & 0x07);
2130                     XPutPixel(bmpImage, x, h,
2131                               X11DRV_PALETTE_ToPhysical
2132                               (physDev, RGB(red,green,blue)));
2133                 }
2134                 srcbits += linebytes;
2135             }
2136         }
2137         break;
2138     }
2139 }
2140
2141
2142 /***********************************************************************
2143  *           X11DRV_DIB_GetImageBits_16
2144  *
2145  * GetDIBits for an 16-bit deep DIB.
2146  */
2147 static void X11DRV_DIB_GetImageBits_16( int lines, BYTE *dstbits,
2148                                         DWORD dstwidth, DWORD srcwidth,
2149                                         PALETTEENTRY *srccolors,
2150                                         DWORD rDst, DWORD gDst, DWORD bDst,
2151                                         XImage *bmpImage, DWORD dibpitch )
2152 {
2153     DWORD x;
2154     int h, width = min(srcwidth, dstwidth);
2155     const dib_conversions *convs = (bmpImage->byte_order == LSBFirst) ? &dib_normal : &dib_src_byteswap;
2156
2157     DWORD linebytes = dibpitch;
2158
2159     if (lines < 0 )
2160     {
2161         lines = -lines;
2162         dstbits = dstbits + ( linebytes * (lines-1));
2163         linebytes = -linebytes;
2164     }
2165
2166     switch (bmpImage->depth)
2167     {
2168     case 15:
2169     case 16:
2170         {
2171             const char* srcbits;
2172
2173             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2174
2175             if (bmpImage->green_mask==0x03e0) {
2176                 if (gDst==bmpImage->green_mask) {
2177                     if (rDst==bmpImage->red_mask) {
2178                         /* ==== rgb 555 bmp -> rgb 555 dib ==== */
2179                         /* ==== bgr 555 bmp -> bgr 555 dib ==== */
2180                         convs->Convert_5x5_asis
2181                             (width,lines,
2182                              srcbits,-bmpImage->bytes_per_line,
2183                              dstbits,linebytes);
2184                     } else {
2185                         /* ==== rgb 555 bmp -> bgr 555 dib ==== */
2186                         /* ==== bgr 555 bmp -> rgb 555 dib ==== */
2187                         convs->Convert_555_reverse
2188                             (width,lines,
2189                              srcbits,-bmpImage->bytes_per_line,
2190                              dstbits,linebytes);
2191                     }
2192                 } else {
2193                     if (rDst==bmpImage->red_mask || bDst==bmpImage->blue_mask) {
2194                         /* ==== rgb 555 bmp -> rgb 565 dib ==== */
2195                         /* ==== bgr 555 bmp -> bgr 565 dib ==== */
2196                         convs->Convert_555_to_565_asis
2197                             (width,lines,
2198                              srcbits,-bmpImage->bytes_per_line,
2199                              dstbits,linebytes);
2200                     } else {
2201                         /* ==== rgb 555 bmp -> bgr 565 dib ==== */
2202                         /* ==== bgr 555 bmp -> rgb 565 dib ==== */
2203                         convs->Convert_555_to_565_reverse
2204                             (width,lines,
2205                              srcbits,-bmpImage->bytes_per_line,
2206                              dstbits,linebytes);
2207                     }
2208                 }
2209             } else if (bmpImage->green_mask==0x07e0) {
2210                 if (gDst==bmpImage->green_mask) {
2211                     if (rDst == bmpImage->red_mask) {
2212                         /* ==== rgb 565 bmp -> rgb 565 dib ==== */
2213                         /* ==== bgr 565 bmp -> bgr 565 dib ==== */
2214                         convs->Convert_5x5_asis
2215                             (width,lines,
2216                              srcbits,-bmpImage->bytes_per_line,
2217                              dstbits,linebytes);
2218                     } else {
2219                         /* ==== rgb 565 bmp -> bgr 565 dib ==== */
2220                         /* ==== bgr 565 bmp -> rgb 565 dib ==== */
2221                         convs->Convert_565_reverse
2222                             (width,lines,
2223                              srcbits,-bmpImage->bytes_per_line,
2224                              dstbits,linebytes);
2225                     }
2226                 } else {
2227                     if (rDst==bmpImage->red_mask || bDst==bmpImage->blue_mask) {
2228                         /* ==== rgb 565 bmp -> rgb 555 dib ==== */
2229                         /* ==== bgr 565 bmp -> bgr 555 dib ==== */
2230                         convs->Convert_565_to_555_asis
2231                             (width,lines,
2232                              srcbits,-bmpImage->bytes_per_line,
2233                              dstbits,linebytes);
2234                     } else {
2235                         /* ==== rgb 565 bmp -> bgr 555 dib ==== */
2236                         /* ==== bgr 565 bmp -> rgb 555 dib ==== */
2237                         convs->Convert_565_to_555_reverse
2238                             (width,lines,
2239                              srcbits,-bmpImage->bytes_per_line,
2240                              dstbits,linebytes);
2241                     }
2242                 }
2243             } else {
2244                 goto notsupported;
2245             }
2246         }
2247         break;
2248
2249     case 24:
2250         if (bmpImage->bits_per_pixel == 24) {
2251             const char* srcbits;
2252
2253             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2254
2255             if (bmpImage->green_mask!=0x00ff00 ||
2256                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2257                 goto notsupported;
2258             } else if ((rDst==0x1f && bmpImage->red_mask==0xff) ||
2259                     (bDst==0x1f && bmpImage->blue_mask==0xff)) {
2260                 if (gDst==0x03e0) {
2261                     /* ==== rgb 888 bmp -> rgb 555 dib ==== */
2262                     /* ==== bgr 888 bmp -> bgr 555 dib ==== */
2263                     convs->Convert_888_to_555_asis
2264                         (width,lines,
2265                          srcbits,-bmpImage->bytes_per_line,
2266                          dstbits,linebytes);
2267                 } else {
2268                     /* ==== rgb 888 bmp -> rgb 565 dib ==== */
2269                     /* ==== rgb 888 bmp -> rgb 565 dib ==== */
2270                     convs->Convert_888_to_565_asis
2271                         (width,lines,
2272                          srcbits,-bmpImage->bytes_per_line,
2273                          dstbits,linebytes);
2274                 }
2275             } else {
2276                 if (gDst==0x03e0) {
2277                     /* ==== rgb 888 bmp -> bgr 555 dib ==== */
2278                     /* ==== bgr 888 bmp -> rgb 555 dib ==== */
2279                     convs->Convert_888_to_555_reverse
2280                         (width,lines,
2281                          srcbits,-bmpImage->bytes_per_line,
2282                          dstbits,linebytes);
2283                 } else {
2284                     /* ==== rgb 888 bmp -> bgr 565 dib ==== */
2285                     /* ==== bgr 888 bmp -> rgb 565 dib ==== */
2286                     convs->Convert_888_to_565_reverse
2287                         (width,lines,
2288                          srcbits,-bmpImage->bytes_per_line,
2289                          dstbits,linebytes);
2290                 }
2291             }
2292             break;
2293         }
2294         /* Fall through */
2295
2296     case 32:
2297         {
2298             const char* srcbits;
2299
2300             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2301
2302             if (bmpImage->green_mask!=0x00ff00 ||
2303                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2304                 goto notsupported;
2305             } else if ((rDst==0x1f && bmpImage->red_mask==0xff) ||
2306                        (bDst==0x1f && bmpImage->blue_mask==0xff)) {
2307                 if (gDst==0x03e0) {
2308                     /* ==== rgb 0888 bmp -> rgb 555 dib ==== */
2309                     /* ==== bgr 0888 bmp -> bgr 555 dib ==== */
2310                     convs->Convert_0888_to_555_asis
2311                         (width,lines,
2312                          srcbits,-bmpImage->bytes_per_line,
2313                          dstbits,linebytes);
2314                 } else {
2315                     /* ==== rgb 0888 bmp -> rgb 565 dib ==== */
2316                     /* ==== bgr 0888 bmp -> bgr 565 dib ==== */
2317                     convs->Convert_0888_to_565_asis
2318                         (width,lines,
2319                          srcbits,-bmpImage->bytes_per_line,
2320                          dstbits,linebytes);
2321                 }
2322             } else {
2323                 if (gDst==0x03e0) {
2324                     /* ==== rgb 0888 bmp -> bgr 555 dib ==== */
2325                     /* ==== bgr 0888 bmp -> rgb 555 dib ==== */
2326                     convs->Convert_0888_to_555_reverse
2327                         (width,lines,
2328                          srcbits,-bmpImage->bytes_per_line,
2329                          dstbits,linebytes);
2330                 } else {
2331                     /* ==== rgb 0888 bmp -> bgr 565 dib ==== */
2332                     /* ==== bgr 0888 bmp -> rgb 565 dib ==== */
2333                     convs->Convert_0888_to_565_reverse
2334                         (width,lines,
2335                          srcbits,-bmpImage->bytes_per_line,
2336                          dstbits,linebytes);
2337                 }
2338             }
2339         }
2340         break;
2341
2342     case 1:
2343     case 4:
2344         if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
2345             /* ==== pal 1 or 4 bmp -> rgb or bgr 555 or 565 dib ==== */
2346             int rShift,gShift,bShift;
2347             WORD* dstpixel;
2348
2349             /* Shift everything 16 bits left so that all shifts are >0,
2350              * even for BGR DIBs. Then a single >> 16 will bring everything
2351              * back into place.
2352              */
2353             rShift=16+X11DRV_DIB_MaskToShift(rDst)-3;
2354             gShift=16+X11DRV_DIB_MaskToShift(gDst)-3;
2355             bShift=16+X11DRV_DIB_MaskToShift(bDst)-3;
2356             if (gDst==0x07e0) {
2357                 /* 6 bits for the green */
2358                 gShift++;
2359             }
2360             rDst=rDst << 16;
2361             gDst=gDst << 16;
2362             bDst=bDst << 16;
2363             for (h = lines - 1; h >= 0; h--) {
2364                 dstpixel=(LPWORD)dstbits;
2365                 for (x = 0; x < width; x++) {
2366                     PALETTEENTRY srcval;
2367                     DWORD dstval;
2368                     srcval=srccolors[XGetPixel(bmpImage, x, h)];
2369                     dstval=((srcval.peRed   << rShift) & rDst) |
2370                            ((srcval.peGreen << gShift) & gDst) |
2371                            ((srcval.peBlue  << bShift) & bDst);
2372                     *dstpixel++=dstval >> 16;
2373                 }
2374                 dstbits += linebytes;
2375             }
2376         } else {
2377             goto notsupported;
2378         }
2379         break;
2380
2381     case 8:
2382         if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
2383             /* ==== pal 8 bmp -> rgb or bgr 555 or 565 dib ==== */
2384             int rShift,gShift,bShift;
2385             const BYTE* srcbits;
2386             const BYTE* srcpixel;
2387             WORD* dstpixel;
2388
2389             /* Shift everything 16 bits left so that all shifts are >0,
2390              * even for BGR DIBs. Then a single >> 16 will bring everything
2391              * back into place.
2392              */
2393             rShift=16+X11DRV_DIB_MaskToShift(rDst)-3;
2394             gShift=16+X11DRV_DIB_MaskToShift(gDst)-3;
2395             bShift=16+X11DRV_DIB_MaskToShift(bDst)-3;
2396             if (gDst==0x07e0) {
2397                 /* 6 bits for the green */
2398                 gShift++;
2399             }
2400             rDst=rDst << 16;
2401             gDst=gDst << 16;
2402             bDst=bDst << 16;
2403             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2404             for (h=0; h<lines; h++) {
2405                 srcpixel=srcbits;
2406                 dstpixel=(LPWORD)dstbits;
2407                 for (x = 0; x < width; x++) {
2408                     PALETTEENTRY srcval;
2409                     DWORD dstval;
2410                     srcval=srccolors[(int)*srcpixel++];
2411                     dstval=((srcval.peRed   << rShift) & rDst) |
2412                            ((srcval.peGreen << gShift) & gDst) |
2413                            ((srcval.peBlue  << bShift) & bDst);
2414                     *dstpixel++=dstval >> 16;
2415                 }
2416                 srcbits -= bmpImage->bytes_per_line;
2417                 dstbits += linebytes;
2418             }
2419         } else {
2420             goto notsupported;
2421         }
2422         break;
2423
2424     default:
2425     notsupported:
2426         {
2427             /* ==== any bmp format -> rgb or bgr 555 or 565 dib ==== */
2428             int rShift,gShift,bShift;
2429             WORD* dstpixel;
2430
2431             WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 16 bit DIB (%lx,%lx,%lx)\n",
2432                   bmpImage->depth, bmpImage->red_mask,
2433                   bmpImage->green_mask, bmpImage->blue_mask,
2434                   rDst, gDst, bDst);
2435
2436             /* Shift everything 16 bits left so that all shifts are >0,
2437              * even for BGR DIBs. Then a single >> 16 will bring everything
2438              * back into place.
2439              */
2440             rShift=16+X11DRV_DIB_MaskToShift(rDst)-3;
2441             gShift=16+X11DRV_DIB_MaskToShift(gDst)-3;
2442             bShift=16+X11DRV_DIB_MaskToShift(bDst)-3;
2443             if (gDst==0x07e0) {
2444                 /* 6 bits for the green */
2445                 gShift++;
2446             }
2447             rDst=rDst << 16;
2448             gDst=gDst << 16;
2449             bDst=bDst << 16;
2450             for (h = lines - 1; h >= 0; h--) {
2451                 dstpixel=(LPWORD)dstbits;
2452                 for (x = 0; x < width; x++) {
2453                     COLORREF srcval;
2454                     DWORD dstval;
2455                     srcval=X11DRV_PALETTE_ToLogical(XGetPixel(bmpImage, x, h));
2456                     dstval=((GetRValue(srcval) << rShift) & rDst) |
2457                            ((GetGValue(srcval) << gShift) & gDst) |
2458                            ((GetBValue(srcval) << bShift) & bDst);
2459                     *dstpixel++=dstval >> 16;
2460                 }
2461                 dstbits += linebytes;
2462             }
2463         }
2464         break;
2465     }
2466 }
2467
2468
2469 /***********************************************************************
2470  *           X11DRV_DIB_SetImageBits_24
2471  *
2472  * SetDIBits for a 24-bit deep DIB.
2473  */
2474 static void X11DRV_DIB_SetImageBits_24( int lines, const BYTE *srcbits,
2475                                  DWORD srcwidth, DWORD dstwidth, int left,
2476                                  X11DRV_PDEVICE *physDev,
2477                                  DWORD rSrc, DWORD gSrc, DWORD bSrc,
2478                                  XImage *bmpImage, DWORD linebytes )
2479 {
2480     DWORD x;
2481     int h, width = min(srcwidth, dstwidth);
2482     const dib_conversions *convs = (bmpImage->byte_order == LSBFirst) ? &dib_normal : &dib_dst_byteswap;
2483
2484     if (lines < 0 )
2485     {
2486         lines = -lines;
2487         srcbits = srcbits + linebytes * (lines - 1);
2488         linebytes = -linebytes;
2489     }
2490
2491     switch (bmpImage->depth)
2492     {
2493     case 24:
2494         if (bmpImage->bits_per_pixel==24) {
2495             char* dstbits;
2496
2497             srcbits=srcbits+left*3;
2498             dstbits=bmpImage->data+left*3+(lines-1)*bmpImage->bytes_per_line;
2499
2500             if (bmpImage->green_mask!=0x00ff00 ||
2501                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2502                 goto notsupported;
2503             } else if (rSrc==bmpImage->red_mask) {
2504                 /* ==== rgb 888 dib -> rgb 888 bmp ==== */
2505                 /* ==== bgr 888 dib -> bgr 888 bmp ==== */
2506                 convs->Convert_888_asis
2507                     (width,lines,
2508                      srcbits,linebytes,
2509                      dstbits,-bmpImage->bytes_per_line);
2510             } else {
2511                 /* ==== rgb 888 dib -> bgr 888 bmp ==== */
2512                 /* ==== bgr 888 dib -> rgb 888 bmp ==== */
2513                 convs->Convert_888_reverse
2514                     (width,lines,
2515                      srcbits,linebytes,
2516                      dstbits,-bmpImage->bytes_per_line);
2517             }
2518             break;
2519         }
2520         /* fall through */
2521
2522     case 32:
2523         {
2524             char* dstbits;
2525
2526             srcbits=srcbits+left*3;
2527             dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
2528
2529             if (bmpImage->green_mask!=0x00ff00 ||
2530                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2531                 goto notsupported;
2532             } else if (rSrc==bmpImage->red_mask) {
2533                 /* ==== rgb 888 dib -> rgb 0888 bmp ==== */
2534                 /* ==== bgr 888 dib -> bgr 0888 bmp ==== */
2535                 convs->Convert_888_to_0888_asis
2536                     (width,lines,
2537                      srcbits,linebytes,
2538                      dstbits,-bmpImage->bytes_per_line);
2539             } else {
2540                 /* ==== rgb 888 dib -> bgr 0888 bmp ==== */
2541                 /* ==== bgr 888 dib -> rgb 0888 bmp ==== */
2542                 convs->Convert_888_to_0888_reverse
2543                     (width,lines,
2544                      srcbits,linebytes,
2545                      dstbits,-bmpImage->bytes_per_line);
2546             }
2547             break;
2548         }
2549
2550     case 15:
2551     case 16:
2552         {
2553             char* dstbits;
2554
2555             srcbits=srcbits+left*3;
2556             dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
2557
2558             if (bmpImage->green_mask==0x03e0) {
2559                 if ((rSrc==0xff0000 && bmpImage->red_mask==0x7f00) ||
2560                     (bSrc==0xff0000 && bmpImage->blue_mask==0x7f00)) {
2561                     /* ==== rgb 888 dib -> rgb 555 bmp ==== */
2562                     /* ==== bgr 888 dib -> bgr 555 bmp ==== */
2563                     convs->Convert_888_to_555_asis
2564                         (width,lines,
2565                          srcbits,linebytes,
2566                          dstbits,-bmpImage->bytes_per_line);
2567                 } else if ((rSrc==0xff && bmpImage->red_mask==0x7f00) ||
2568                            (bSrc==0xff && bmpImage->blue_mask==0x7f00)) {
2569                     /* ==== rgb 888 dib -> bgr 555 bmp ==== */
2570                     /* ==== bgr 888 dib -> rgb 555 bmp ==== */
2571                     convs->Convert_888_to_555_reverse
2572                         (width,lines,
2573                          srcbits,linebytes,
2574                          dstbits,-bmpImage->bytes_per_line);
2575                 } else {
2576                     goto notsupported;
2577                 }
2578             } else if (bmpImage->green_mask==0x07e0) {
2579                 if ((rSrc==0xff0000 && bmpImage->red_mask==0xf800) ||
2580                     (bSrc==0xff0000 && bmpImage->blue_mask==0xf800)) {
2581                     /* ==== rgb 888 dib -> rgb 565 bmp ==== */
2582                     /* ==== bgr 888 dib -> bgr 565 bmp ==== */
2583                     convs->Convert_888_to_565_asis
2584                         (width,lines,
2585                          srcbits,linebytes,
2586                          dstbits,-bmpImage->bytes_per_line);
2587                 } else if ((rSrc==0xff && bmpImage->red_mask==0xf800) ||
2588                            (bSrc==0xff && bmpImage->blue_mask==0xf800)) {
2589                     /* ==== rgb 888 dib -> bgr 565 bmp ==== */
2590                     /* ==== bgr 888 dib -> rgb 565 bmp ==== */
2591                     convs->Convert_888_to_565_reverse
2592                         (width,lines,
2593                          srcbits,linebytes,
2594                          dstbits,-bmpImage->bytes_per_line);
2595                 } else {
2596                     goto notsupported;
2597                 }
2598             } else {
2599                 goto notsupported;
2600             }
2601         }
2602         break;
2603
2604     default:
2605     notsupported:
2606         WARN("from 24 bit DIB (%lx,%lx,%lx) to unknown %d bit bitmap (%lx,%lx,%lx)\n",
2607               rSrc, gSrc, bSrc, bmpImage->bits_per_pixel, bmpImage->red_mask,
2608               bmpImage->green_mask, bmpImage->blue_mask );
2609         /* fall through */
2610     case 1:
2611     case 4:
2612     case 8:
2613         {
2614             /* ==== rgb 888 dib -> any bmp bormat ==== */
2615             const BYTE* srcbyte;
2616
2617             /* Windows only supports one 24bpp DIB format: RGB888 */
2618             srcbits+=left*3;
2619             for (h = lines - 1; h >= 0; h--) {
2620                 srcbyte=(const BYTE*)srcbits;
2621                 for (x = left; x < width+left; x++) {
2622                     XPutPixel(bmpImage, x, h,
2623                               X11DRV_PALETTE_ToPhysical
2624                               (physDev, RGB(srcbyte[2], srcbyte[1], srcbyte[0])));
2625                     srcbyte+=3;
2626                 }
2627                 srcbits += linebytes;
2628             }
2629         }
2630         break;
2631     }
2632 }
2633
2634
2635 /***********************************************************************
2636  *           X11DRV_DIB_GetImageBits_24
2637  *
2638  * GetDIBits for an 24-bit deep DIB.
2639  */
2640 static void X11DRV_DIB_GetImageBits_24( int lines, BYTE *dstbits,
2641                                         DWORD dstwidth, DWORD srcwidth,
2642                                         PALETTEENTRY *srccolors,
2643                                         DWORD rDst, DWORD gDst, DWORD bDst,
2644                                         XImage *bmpImage, DWORD linebytes )
2645 {
2646     DWORD x;
2647     int h, width = min(srcwidth, dstwidth);
2648     const dib_conversions *convs = (bmpImage->byte_order == LSBFirst) ? &dib_normal : &dib_src_byteswap;
2649
2650     if (lines < 0 )
2651     {
2652         lines = -lines;
2653         dstbits = dstbits + ( linebytes * (lines-1) );
2654         linebytes = -linebytes;
2655     }
2656
2657     switch (bmpImage->depth)
2658     {
2659     case 24:
2660         if (bmpImage->bits_per_pixel==24) {
2661             const char* srcbits;
2662
2663             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2664
2665             if (bmpImage->green_mask!=0x00ff00 ||
2666                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2667                 goto notsupported;
2668             } else if (rDst==bmpImage->red_mask) {
2669                 /* ==== rgb 888 bmp -> rgb 888 dib ==== */
2670                 /* ==== bgr 888 bmp -> bgr 888 dib ==== */
2671                 convs->Convert_888_asis
2672                     (width,lines,
2673                      srcbits,-bmpImage->bytes_per_line,
2674                      dstbits,linebytes);
2675             } else {
2676                 /* ==== rgb 888 bmp -> bgr 888 dib ==== */
2677                 /* ==== bgr 888 bmp -> rgb 888 dib ==== */
2678                 convs->Convert_888_reverse
2679                     (width,lines,
2680                      srcbits,-bmpImage->bytes_per_line,
2681                      dstbits,linebytes);
2682             }
2683             break;
2684         }
2685         /* fall through */
2686
2687     case 32:
2688         {
2689             const char* srcbits;
2690
2691             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2692
2693             if (bmpImage->green_mask!=0x00ff00 ||
2694                 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2695                 goto notsupported;
2696             } else if (rDst==bmpImage->red_mask) {
2697                 /* ==== rgb 888 bmp -> rgb 0888 dib ==== */
2698                 /* ==== bgr 888 bmp -> bgr 0888 dib ==== */
2699                 convs->Convert_0888_to_888_asis
2700                     (width,lines,
2701                      srcbits,-bmpImage->bytes_per_line,
2702                      dstbits,linebytes);
2703             } else {
2704                 /* ==== rgb 888 bmp -> bgr 0888 dib ==== */
2705                 /* ==== bgr 888 bmp -> rgb 0888 dib ==== */
2706                 convs->Convert_0888_to_888_reverse
2707                     (width,lines,
2708                      srcbits,-bmpImage->bytes_per_line,
2709                      dstbits,linebytes);
2710             }
2711             break;
2712         }
2713
2714     case 15:
2715     case 16:
2716         {
2717             const char* srcbits;
2718
2719             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2720
2721             if (bmpImage->green_mask==0x03e0) {
2722                 if ((rDst==0xff0000 && bmpImage->red_mask==0x7f00) ||
2723                     (bDst==0xff0000 && bmpImage->blue_mask==0x7f00)) {
2724                     /* ==== rgb 555 bmp -> rgb 888 dib ==== */
2725                     /* ==== bgr 555 bmp -> bgr 888 dib ==== */
2726                     convs->Convert_555_to_888_asis
2727                         (width,lines,
2728                          srcbits,-bmpImage->bytes_per_line,
2729                          dstbits,linebytes);
2730                 } else if ((rDst==0xff && bmpImage->red_mask==0x7f00) ||
2731                            (bDst==0xff && bmpImage->blue_mask==0x7f00)) {
2732                     /* ==== rgb 555 bmp -> bgr 888 dib ==== */
2733                     /* ==== bgr 555 bmp -> rgb 888 dib ==== */
2734                     convs->Convert_555_to_888_reverse
2735                         (width,lines,
2736                          srcbits,-bmpImage->bytes_per_line,
2737                          dstbits,linebytes);
2738                 } else {
2739                     goto notsupported;
2740                 }
2741             } else if (bmpImage->green_mask==0x07e0) {
2742                 if ((rDst==0xff0000 && bmpImage->red_mask==0xf800) ||
2743                     (bDst==0xff0000 && bmpImage->blue_mask==0xf800)) {
2744                     /* ==== rgb 565 bmp -> rgb 888 dib ==== */
2745                     /* ==== bgr 565 bmp -> bgr 888 dib ==== */
2746                     convs->Convert_565_to_888_asis
2747                         (width,lines,
2748                          srcbits,-bmpImage->bytes_per_line,
2749                          dstbits,linebytes);
2750                 } else if ((rDst==0xff && bmpImage->red_mask==0xf800) ||
2751                            (bDst==0xff && bmpImage->blue_mask==0xf800)) {
2752                     /* ==== rgb 565 bmp -> bgr 888 dib ==== */
2753                     /* ==== bgr 565 bmp -> rgb 888 dib ==== */
2754                     convs->Convert_565_to_888_reverse
2755                         (width,lines,
2756                          srcbits,-bmpImage->bytes_per_line,
2757                          dstbits,linebytes);
2758                 } else {
2759                     goto notsupported;
2760                 }
2761             } else {
2762                 goto notsupported;
2763             }
2764         }
2765         break;
2766
2767     case 1:
2768     case 4:
2769         if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
2770             /* ==== pal 1 or 4 bmp -> rgb 888 dib ==== */
2771             BYTE* dstbyte;
2772
2773             /* Windows only supports one 24bpp DIB format: rgb 888 */
2774             for (h = lines - 1; h >= 0; h--) {
2775                 dstbyte=dstbits;
2776                 for (x = 0; x < width; x++) {
2777                     PALETTEENTRY srcval;
2778                     srcval=srccolors[XGetPixel(bmpImage, x, h)];
2779                     dstbyte[0]=srcval.peBlue;
2780                     dstbyte[1]=srcval.peGreen;
2781                     dstbyte[2]=srcval.peRed;
2782                     dstbyte+=3;
2783                 }
2784                 dstbits += linebytes;
2785             }
2786         } else {
2787             goto notsupported;
2788         }
2789         break;
2790
2791     case 8:
2792         if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask == 0 && srccolors) {
2793             /* ==== pal 8 bmp -> rgb 888 dib ==== */
2794             const void* srcbits;
2795             const BYTE* srcpixel;
2796             BYTE* dstbyte;
2797
2798             /* Windows only supports one 24bpp DIB format: rgb 888 */
2799             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2800             for (h = lines - 1; h >= 0; h--) {
2801                 srcpixel=srcbits;
2802                 dstbyte=dstbits;
2803                 for (x = 0; x < width; x++ ) {
2804                     PALETTEENTRY srcval;
2805                     srcval=srccolors[(int)*srcpixel++];
2806                     dstbyte[0]=srcval.peBlue;
2807                     dstbyte[1]=srcval.peGreen;
2808                     dstbyte[2]=srcval.peRed;
2809                     dstbyte+=3;
2810                 }
2811                 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
2812                 dstbits += linebytes;
2813             }
2814         } else {
2815             goto notsupported;
2816         }
2817         break;
2818
2819     default:
2820     notsupported:
2821         {
2822             /* ==== any bmp format -> 888 dib ==== */
2823             BYTE* dstbyte;
2824
2825             WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 24 bit DIB (%lx,%lx,%lx)\n",
2826                   bmpImage->depth, bmpImage->red_mask,
2827                   bmpImage->green_mask, bmpImage->blue_mask,
2828                   rDst, gDst, bDst );
2829
2830             /* Windows only supports one 24bpp DIB format: rgb 888 */
2831             for (h = lines - 1; h >= 0; h--) {
2832                 dstbyte=dstbits;
2833                 for (x = 0; x < width; x++) {
2834                     COLORREF srcval=X11DRV_PALETTE_ToLogical
2835                         (XGetPixel( bmpImage, x, h ));
2836                     dstbyte[0]=GetBValue(srcval);
2837                     dstbyte[1]=GetGValue(srcval);
2838                     dstbyte[2]=GetRValue(srcval);
2839                     dstbyte+=3;
2840                 }
2841                 dstbits += linebytes;
2842             }
2843         }
2844         break;
2845     }
2846 }
2847
2848
2849 /***********************************************************************
2850  *           X11DRV_DIB_SetImageBits_32
2851  *
2852  * SetDIBits for a 32-bit deep DIB.
2853  */
2854 static void X11DRV_DIB_SetImageBits_32(int lines, const BYTE *srcbits,
2855                                        DWORD srcwidth, DWORD dstwidth, int left,
2856                                        X11DRV_PDEVICE *physDev,
2857                                        DWORD rSrc, DWORD gSrc, DWORD bSrc,
2858                                        XImage *bmpImage,
2859                                        DWORD linebytes)
2860 {
2861     DWORD x;
2862     const DWORD *ptr;
2863     int h, width = min(srcwidth, dstwidth);
2864     const dib_conversions *convs = (bmpImage->byte_order == LSBFirst) ? &dib_normal : &dib_dst_byteswap;
2865
2866     if (lines < 0 )
2867     {
2868        lines = -lines;
2869        srcbits = srcbits + ( linebytes * (lines-1) );
2870        linebytes = -linebytes;
2871     }
2872
2873     ptr = (const DWORD *) srcbits + left;
2874
2875     switch (bmpImage->depth)
2876     {
2877     case 24:
2878         if (bmpImage->bits_per_pixel==24) {
2879             char* dstbits;
2880
2881             srcbits=srcbits+left*4;
2882             dstbits=bmpImage->data+left*3+(lines-1)*bmpImage->bytes_per_line;
2883
2884             if (rSrc==bmpImage->red_mask && gSrc==bmpImage->green_mask && bSrc==bmpImage->blue_mask) {
2885                 /* ==== rgb 0888 dib -> rgb 888 bmp ==== */
2886                 /* ==== bgr 0888 dib -> bgr 888 bmp ==== */
2887                 convs->Convert_0888_to_888_asis
2888                     (width,lines,
2889                      srcbits,linebytes,
2890                      dstbits,-bmpImage->bytes_per_line);
2891             } else if (bmpImage->green_mask!=0x00ff00 ||
2892                        (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2893                 goto notsupported;
2894                 /* the tests below assume sane bmpImage masks */
2895             } else if (rSrc==bmpImage->blue_mask && gSrc==bmpImage->green_mask && bSrc==bmpImage->red_mask) {
2896                 /* ==== rgb 0888 dib -> bgr 888 bmp ==== */
2897                 /* ==== bgr 0888 dib -> rgb 888 bmp ==== */
2898                 convs->Convert_0888_to_888_reverse
2899                     (width,lines,
2900                      srcbits,linebytes,
2901                      dstbits,-bmpImage->bytes_per_line);
2902             } else if (bmpImage->blue_mask==0xff) {
2903                 /* ==== any 0888 dib -> rgb 888 bmp ==== */
2904                 convs->Convert_any0888_to_rgb888
2905                     (width,lines,
2906                      srcbits,linebytes,
2907                      rSrc,gSrc,bSrc,
2908                      dstbits,-bmpImage->bytes_per_line);
2909             } else {
2910                 /* ==== any 0888 dib -> bgr 888 bmp ==== */
2911                 convs->Convert_any0888_to_bgr888
2912                     (width,lines,
2913                      srcbits,linebytes,
2914                      rSrc,gSrc,bSrc,
2915                      dstbits,-bmpImage->bytes_per_line);
2916             }
2917             break;
2918         }
2919         /* fall through */
2920
2921     case 32:
2922         {
2923             char* dstbits;
2924
2925             srcbits=srcbits+left*4;
2926             dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
2927
2928             if (gSrc==bmpImage->green_mask) {
2929                 if (rSrc==bmpImage->red_mask && bSrc==bmpImage->blue_mask) {
2930                     /* ==== rgb 0888 dib -> rgb 0888 bmp ==== */
2931                     /* ==== bgr 0888 dib -> bgr 0888 bmp ==== */
2932                     convs->Convert_0888_asis
2933                         (width,lines,
2934                          srcbits,linebytes,
2935                          dstbits,-bmpImage->bytes_per_line);
2936                 } else if (bmpImage->green_mask!=0x00ff00 ||
2937                            (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2938                     goto notsupported;
2939                     /* the tests below assume sane bmpImage masks */
2940                 } else if (rSrc==bmpImage->blue_mask && bSrc==bmpImage->red_mask) {
2941                     /* ==== rgb 0888 dib -> bgr 0888 bmp ==== */
2942                     /* ==== bgr 0888 dib -> rgb 0888 bmp ==== */
2943                     convs->Convert_0888_reverse
2944                         (width,lines,
2945                          srcbits,linebytes,
2946                          dstbits,-bmpImage->bytes_per_line);
2947                 } else {
2948                     /* ==== any 0888 dib -> any 0888 bmp ==== */
2949                     convs->Convert_0888_any
2950                         (width,lines,
2951                          srcbits,linebytes,
2952                          rSrc,gSrc,bSrc,
2953                          dstbits,-bmpImage->bytes_per_line,
2954                          bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
2955                 }
2956             } else if (bmpImage->green_mask!=0x00ff00 ||
2957                        (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2958                 goto notsupported;
2959                 /* the tests below assume sane bmpImage masks */
2960             } else {
2961                 /* ==== any 0888 dib -> any 0888 bmp ==== */
2962                 convs->Convert_0888_any
2963                     (width,lines,
2964                      srcbits,linebytes,
2965                      rSrc,gSrc,bSrc,
2966                      dstbits,-bmpImage->bytes_per_line,
2967                      bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
2968             }
2969         }
2970         break;
2971
2972     case 15:
2973     case 16:
2974         {
2975             char* dstbits;
2976
2977             srcbits=srcbits+left*4;
2978             dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
2979
2980             if (rSrc==0xff0000 && gSrc==0x00ff00 && bSrc==0x0000ff) {
2981                 if (bmpImage->green_mask==0x03e0) {
2982                     if (bmpImage->red_mask==0x7f00) {
2983                         /* ==== rgb 0888 dib -> rgb 555 bmp ==== */
2984                         convs->Convert_0888_to_555_asis
2985                             (width,lines,
2986                              srcbits,linebytes,
2987                              dstbits,-bmpImage->bytes_per_line);
2988                     } else if (bmpImage->blue_mask==0x7f00) {
2989                         /* ==== rgb 0888 dib -> bgr 555 bmp ==== */
2990                         convs->Convert_0888_to_555_reverse
2991                             (width,lines,
2992                              srcbits,linebytes,
2993                              dstbits,-bmpImage->bytes_per_line);
2994                     } else {
2995                         goto notsupported;
2996                     }
2997                 } else if (bmpImage->green_mask==0x07e0) {
2998                     if (bmpImage->red_mask==0xf800) {
2999                         /* ==== rgb 0888 dib -> rgb 565 bmp ==== */
3000                         convs->Convert_0888_to_565_asis
3001                             (width,lines,
3002                              srcbits,linebytes,
3003                              dstbits,-bmpImage->bytes_per_line);
3004                     } else if (bmpImage->blue_mask==0xf800) {
3005                         /* ==== rgb 0888 dib -> bgr 565 bmp ==== */
3006                         convs->Convert_0888_to_565_reverse
3007                             (width,lines,
3008                              srcbits,linebytes,
3009                              dstbits,-bmpImage->bytes_per_line);
3010                     } else {
3011                         goto notsupported;
3012                     }
3013                 } else {
3014                     goto notsupported;
3015                 }
3016             } else if (rSrc==0x0000ff && gSrc==0x00ff00 && bSrc==0xff0000) {
3017                 if (bmpImage->green_mask==0x03e0) {
3018                     if (bmpImage->blue_mask==0x7f00) {
3019                         /* ==== bgr 0888 dib -> bgr 555 bmp ==== */
3020                         convs->Convert_0888_to_555_asis
3021                             (width,lines,
3022                              srcbits,linebytes,
3023                              dstbits,-bmpImage->bytes_per_line);
3024                     } else if (bmpImage->red_mask==0x7f00) {
3025                         /* ==== bgr 0888 dib -> rgb 555 bmp ==== */
3026                         convs->Convert_0888_to_555_reverse
3027                             (width,lines,
3028                              srcbits,linebytes,
3029                              dstbits,-bmpImage->bytes_per_line);
3030                     } else {
3031                         goto notsupported;
3032                     }
3033                 } else if (bmpImage->green_mask==0x07e0) {
3034                     if (bmpImage->blue_mask==0xf800) {
3035                         /* ==== bgr 0888 dib -> bgr 565 bmp ==== */
3036                         convs->Convert_0888_to_565_asis
3037                             (width,lines,
3038                              srcbits,linebytes,
3039                              dstbits,-bmpImage->bytes_per_line);
3040                     } else if (bmpImage->red_mask==0xf800) {
3041                         /* ==== bgr 0888 dib -> rgb 565 bmp ==== */
3042                         convs->Convert_0888_to_565_reverse
3043                             (width,lines,
3044                              srcbits,linebytes,
3045                              dstbits,-bmpImage->bytes_per_line);
3046                     } else {
3047                         goto notsupported;
3048                     }
3049                 } else {
3050                     goto notsupported;
3051                 }
3052             } else {
3053                 if (bmpImage->green_mask==0x03e0 &&
3054                     (bmpImage->red_mask==0x7f00 ||
3055                      bmpImage->blue_mask==0x7f00)) {
3056                     /* ==== any 0888 dib -> rgb or bgr 555 bmp ==== */
3057                     convs->Convert_any0888_to_5x5
3058                         (width,lines,
3059                          srcbits,linebytes,
3060                          rSrc,gSrc,bSrc,
3061                          dstbits,-bmpImage->bytes_per_line,
3062                          bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
3063                 } else if (bmpImage->green_mask==0x07e0 &&
3064                            (bmpImage->red_mask==0xf800 ||
3065                             bmpImage->blue_mask==0xf800)) {
3066                     /* ==== any 0888 dib -> rgb or bgr 565 bmp ==== */
3067                     convs->Convert_any0888_to_5x5
3068                         (width,lines,
3069                          srcbits,linebytes,
3070                          rSrc,gSrc,bSrc,
3071                          dstbits,-bmpImage->bytes_per_line,
3072                          bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
3073                 } else {
3074                     goto notsupported;
3075                 }
3076             }
3077         }
3078         break;
3079
3080     default:
3081     notsupported:
3082         WARN("from 32 bit DIB (%lx,%lx,%lx) to unknown %d bit bitmap (%lx,%lx,%lx)\n",
3083               rSrc, gSrc, bSrc, bmpImage->bits_per_pixel, bmpImage->red_mask,
3084               bmpImage->green_mask, bmpImage->blue_mask );
3085         /* fall through */
3086     case 1:
3087     case 4:
3088     case 8:
3089         {
3090             /* ==== any 0888 dib -> pal 1, 4 or 8 bmp ==== */
3091             const DWORD* srcpixel;
3092             int rShift,gShift,bShift;
3093
3094             rShift=X11DRV_DIB_MaskToShift(rSrc);
3095             gShift=X11DRV_DIB_MaskToShift(gSrc);
3096             bShift=X11DRV_DIB_MaskToShift(bSrc);
3097             srcbits+=left*4;
3098             for (h = lines - 1; h >= 0; h--) {
3099                 srcpixel=(const DWORD*)srcbits;
3100                 for (x = left; x < width+left; x++) {
3101                     DWORD srcvalue;
3102                     BYTE red,green,blue;
3103                     srcvalue=*srcpixel++;
3104                     red=  (srcvalue >> rShift) & 0xff;
3105                     green=(srcvalue >> gShift) & 0xff;
3106                     blue= (srcvalue >> bShift) & 0xff;
3107                     XPutPixel(bmpImage, x, h, X11DRV_PALETTE_ToPhysical
3108                               (physDev, RGB(red,green,blue)));
3109                 }
3110                 srcbits += linebytes;
3111             }
3112         }
3113         break;
3114     }
3115
3116 }
3117
3118 /***********************************************************************
3119  *           X11DRV_DIB_GetImageBits_32
3120  *
3121  * GetDIBits for an 32-bit deep DIB.
3122  */
3123 static void X11DRV_DIB_GetImageBits_32( int lines, BYTE *dstbits,
3124                                         DWORD dstwidth, DWORD srcwidth,
3125                                         PALETTEENTRY *srccolors,
3126                                         DWORD rDst, DWORD gDst, DWORD bDst,
3127                                         XImage *bmpImage, DWORD linebytes )
3128 {
3129     DWORD x;
3130     int h, width = min(srcwidth, dstwidth);
3131     BYTE *bits;
3132     const dib_conversions *convs = (bmpImage->byte_order == LSBFirst) ? &dib_normal : &dib_src_byteswap;
3133
3134     if (lines < 0 )
3135     {
3136         lines = -lines;
3137         dstbits = dstbits + ( linebytes * (lines-1) );
3138         linebytes = -linebytes;
3139     }
3140
3141     bits = dstbits;
3142
3143     switch (bmpImage->depth)
3144     {
3145     case 24:
3146         if (bmpImage->bits_per_pixel==24) {
3147             const void* srcbits;
3148
3149             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3150
3151             if (rDst==bmpImage->red_mask && gDst==bmpImage->green_mask && bDst==bmpImage->blue_mask) {
3152                 /* ==== rgb 888 bmp -> rgb 0888 dib ==== */
3153                 /* ==== bgr 888 bmp -> bgr 0888 dib ==== */
3154                 convs->Convert_888_to_0888_asis
3155                     (width,lines,
3156                      srcbits,-bmpImage->bytes_per_line,
3157                      dstbits,linebytes);
3158             } else if (bmpImage->green_mask!=0x00ff00 ||
3159                        (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3160                 goto notsupported;
3161                 /* the tests below assume sane bmpImage masks */
3162             } else if (rDst==bmpImage->blue_mask && gDst==bmpImage->green_mask && bDst==bmpImage->red_mask) {
3163                 /* ==== rgb 888 bmp -> bgr 0888 dib ==== */
3164                 /* ==== bgr 888 bmp -> rgb 0888 dib ==== */
3165                 convs->Convert_888_to_0888_reverse
3166                     (width,lines,
3167                      srcbits,-bmpImage->bytes_per_line,
3168                      dstbits,linebytes);
3169             } else if (bmpImage->blue_mask==0xff) {
3170                 /* ==== rgb 888 bmp -> any 0888 dib ==== */
3171                 convs->Convert_rgb888_to_any0888
3172                     (width,lines,
3173                      srcbits,-bmpImage->bytes_per_line,
3174                      dstbits,linebytes,
3175                      rDst,gDst,bDst);
3176             } else {
3177                 /* ==== bgr 888 bmp -> any 0888 dib ==== */
3178                 convs->Convert_bgr888_to_any0888
3179                     (width,lines,
3180                      srcbits,-bmpImage->bytes_per_line,
3181                      dstbits,linebytes,
3182                      rDst,gDst,bDst);
3183             }
3184             break;
3185         }
3186         /* fall through */
3187
3188     case 32:
3189         {
3190             const char* srcbits;
3191
3192             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3193
3194             if (gDst==bmpImage->green_mask) {
3195                 if (rDst==bmpImage->red_mask && bDst==bmpImage->blue_mask) {
3196                     /* ==== rgb 0888 bmp -> rgb 0888 dib ==== */
3197                     /* ==== bgr 0888 bmp -> bgr 0888 dib ==== */
3198                     convs->Convert_0888_asis
3199                         (width,lines,
3200                          srcbits,-bmpImage->bytes_per_line,
3201                          dstbits,linebytes);
3202                 } else if (bmpImage->green_mask!=0x00ff00 ||
3203                            (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3204                     goto notsupported;
3205                     /* the tests below assume sane bmpImage masks */
3206                 } else if (rDst==bmpImage->blue_mask && bDst==bmpImage->red_mask) {
3207                     /* ==== rgb 0888 bmp -> bgr 0888 dib ==== */
3208                     /* ==== bgr 0888 bmp -> rgb 0888 dib ==== */
3209                     convs->Convert_0888_reverse
3210                         (width,lines,
3211                          srcbits,-bmpImage->bytes_per_line,
3212                          dstbits,linebytes);
3213                 } else {
3214                     /* ==== any 0888 bmp -> any 0888 dib ==== */
3215                     convs->Convert_0888_any
3216                         (width,lines,
3217                          srcbits,-bmpImage->bytes_per_line,
3218                          bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
3219                          dstbits,linebytes,
3220                          rDst,gDst,bDst);
3221                 }
3222             } else if (bmpImage->green_mask!=0x00ff00 ||
3223                        (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3224                 goto notsupported;
3225                 /* the tests below assume sane bmpImage masks */
3226             } else {
3227                 /* ==== any 0888 bmp -> any 0888 dib ==== */
3228                 convs->Convert_0888_any
3229                     (width,lines,
3230                      srcbits,-bmpImage->bytes_per_line,
3231                      bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
3232                      dstbits,linebytes,
3233                      rDst,gDst,bDst);
3234             }
3235         }
3236         break;
3237
3238     case 15:
3239     case 16:
3240         {
3241             const char* srcbits;
3242
3243             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3244
3245             if (rDst==0xff0000 && gDst==0x00ff00 && bDst==0x0000ff) {
3246                 if (bmpImage->green_mask==0x03e0) {
3247                     if (bmpImage->red_mask==0x7f00) {
3248                         /* ==== rgb 555 bmp -> rgb 0888 dib ==== */
3249                         convs->Convert_555_to_0888_asis
3250                             (width,lines,
3251                              srcbits,-bmpImage->bytes_per_line,
3252                              dstbits,linebytes);
3253                     } else if (bmpImage->blue_mask==0x7f00) {
3254                         /* ==== bgr 555 bmp -> rgb 0888 dib ==== */
3255                         convs->Convert_555_to_0888_reverse
3256                             (width,lines,
3257                              srcbits,-bmpImage->bytes_per_line,
3258                              dstbits,linebytes);
3259                     } else {
3260                         goto notsupported;
3261                     }
3262                 } else if (bmpImage->green_mask==0x07e0) {
3263                     if (bmpImage->red_mask==0xf800) {
3264                         /* ==== rgb 565 bmp -> rgb 0888 dib ==== */
3265                         convs->Convert_565_to_0888_asis
3266                             (width,lines,
3267                              srcbits,-bmpImage->bytes_per_line,
3268                              dstbits,linebytes);
3269                     } else if (bmpImage->blue_mask==0xf800) {
3270                         /* ==== bgr 565 bmp -> rgb 0888 dib ==== */
3271                         convs->Convert_565_to_0888_reverse
3272                             (width,lines,
3273                              srcbits,-bmpImage->bytes_per_line,
3274                              dstbits,linebytes);
3275                     } else {
3276                         goto notsupported;
3277                     }
3278                 } else {
3279                     goto notsupported;
3280                 }
3281             } else if (rDst==0x0000ff && gDst==0x00ff00 && bDst==0xff0000) {
3282                 if (bmpImage->green_mask==0x03e0) {
3283                     if (bmpImage->blue_mask==0x7f00) {
3284                         /* ==== bgr 555 bmp -> bgr 0888 dib ==== */
3285                         convs->Convert_555_to_0888_asis
3286                             (width,lines,
3287                              srcbits,-bmpImage->bytes_per_line,
3288                              dstbits,linebytes);
3289                     } else if (bmpImage->red_mask==0x7f00) {
3290                         /* ==== rgb 555 bmp -> bgr 0888 dib ==== */
3291                         convs->Convert_555_to_0888_reverse
3292                             (width,lines,
3293                              srcbits,-bmpImage->bytes_per_line,
3294                              dstbits,linebytes);
3295                     } else {
3296                         goto notsupported;
3297                     }
3298                 } else if (bmpImage->green_mask==0x07e0) {
3299                     if (bmpImage->blue_mask==0xf800) {
3300                         /* ==== bgr 565 bmp -> bgr 0888 dib ==== */
3301                         convs->Convert_565_to_0888_asis
3302                             (width,lines,
3303                              srcbits,-bmpImage->bytes_per_line,
3304                              dstbits,linebytes);
3305                     } else if (bmpImage->red_mask==0xf800) {
3306                         /* ==== rgb 565 bmp -> bgr 0888 dib ==== */
3307                         convs->Convert_565_to_0888_reverse
3308                             (width,lines,
3309                              srcbits,-bmpImage->bytes_per_line,
3310                              dstbits,linebytes);
3311                     } else {
3312                         goto notsupported;
3313                     }
3314                 } else {
3315                     goto notsupported;
3316                 }
3317             } else {
3318                 if (bmpImage->green_mask==0x03e0 &&
3319                     (bmpImage->red_mask==0x7f00 ||
3320                      bmpImage->blue_mask==0x7f00)) {
3321                     /* ==== rgb or bgr 555 bmp -> any 0888 dib ==== */
3322                     convs->Convert_5x5_to_any0888
3323                         (width,lines,
3324                          srcbits,-bmpImage->bytes_per_line,
3325                          bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
3326                          dstbits,linebytes,
3327                          rDst,gDst,bDst);
3328                 } else if (bmpImage->green_mask==0x07e0 &&
3329                            (bmpImage->red_mask==0xf800 ||
3330                             bmpImage->blue_mask==0xf800)) {
3331                     /* ==== rgb or bgr 565 bmp -> any 0888 dib ==== */
3332                     convs->Convert_5x5_to_any0888
3333                         (width,lines,
3334                          srcbits,-bmpImage->bytes_per_line,
3335                          bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
3336                          dstbits,linebytes,
3337                          rDst,gDst,bDst);
3338                 } else {
3339                     goto notsupported;
3340                 }
3341             }
3342         }
3343         break;
3344
3345     case 1:
3346     case 4:
3347         if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
3348             /* ==== pal 1 or 4 bmp -> any 0888 dib ==== */
3349             int rShift,gShift,bShift;
3350             DWORD* dstpixel;
3351
3352             rShift=X11DRV_DIB_MaskToShift(rDst);
3353             gShift=X11DRV_DIB_MaskToShift(gDst);
3354             bShift=X11DRV_DIB_MaskToShift(bDst);
3355             for (h = lines - 1; h >= 0; h--) {
3356                 dstpixel=(DWORD*)dstbits;
3357                 for (x = 0; x < width; x++) {
3358                     PALETTEENTRY srcval;
3359                     srcval = srccolors[XGetPixel(bmpImage, x, h)];
3360                     *dstpixel++=(srcval.peRed   << rShift) |
3361                                 (srcval.peGreen << gShift) |
3362                                 (srcval.peBlue  << bShift);
3363                 }
3364                 dstbits += linebytes;
3365             }
3366         } else {
3367             goto notsupported;
3368         }
3369         break;
3370
3371     case 8:
3372         if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
3373             /* ==== pal 8 bmp -> any 0888 dib ==== */
3374             int rShift,gShift,bShift;
3375             const void* srcbits;
3376             const BYTE* srcpixel;
3377             DWORD* dstpixel;
3378
3379             rShift=X11DRV_DIB_MaskToShift(rDst);
3380             gShift=X11DRV_DIB_MaskToShift(gDst);
3381             bShift=X11DRV_DIB_MaskToShift(bDst);
3382             srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3383             for (h = lines - 1; h >= 0; h--) {
3384                 srcpixel=srcbits;
3385                 dstpixel=(DWORD*)dstbits;
3386                 for (x = 0; x < width; x++) {
3387                     PALETTEENTRY srcval;
3388                     srcval=srccolors[(int)*srcpixel++];
3389                     *dstpixel++=(srcval.peRed   << rShift) |
3390                                 (srcval.peGreen << gShift) |
3391                                 (srcval.peBlue  << bShift);
3392                 }
3393                 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
3394                 dstbits += linebytes;
3395             }
3396         } else {
3397             goto notsupported;
3398         }
3399         break;
3400
3401     default:
3402     notsupported:
3403         {
3404             /* ==== any bmp format -> any 0888 dib ==== */
3405             int rShift,gShift,bShift;
3406             DWORD* dstpixel;
3407
3408             WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 32 bit DIB (%lx,%lx,%lx)\n",
3409                   bmpImage->depth, bmpImage->red_mask,
3410                   bmpImage->green_mask, bmpImage->blue_mask,
3411                   rDst,gDst,bDst);
3412
3413             rShift=X11DRV_DIB_MaskToShift(rDst);
3414             gShift=X11DRV_DIB_MaskToShift(gDst);
3415             bShift=X11DRV_DIB_MaskToShift(bDst);
3416             for (h = lines - 1; h >= 0; h--) {
3417                 dstpixel=(DWORD*)dstbits;
3418                 for (x = 0; x < width; x++) {
3419                     COLORREF srcval;
3420                     srcval=X11DRV_PALETTE_ToLogical(XGetPixel(bmpImage, x, h));
3421                     *dstpixel++=(GetRValue(srcval) << rShift) |
3422                                 (GetGValue(srcval) << gShift) |
3423                                 (GetBValue(srcval) << bShift);
3424                 }
3425                 dstbits += linebytes;
3426             }
3427         }
3428         break;
3429     }
3430 }
3431
3432 /***********************************************************************
3433  *           X11DRV_DIB_SetImageBits
3434  *
3435  * Transfer the bits to an X image.
3436  * Helper function for SetDIBits() and SetDIBitsToDevice().
3437  */
3438 static int X11DRV_DIB_SetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
3439 {
3440     int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
3441     XImage *bmpImage;
3442
3443     wine_tsx11_lock();
3444     if (descr->image)
3445         bmpImage = descr->image;
3446     else {
3447         bmpImage = XCreateImage( gdi_display, visual, descr->depth, ZPixmap, 0, NULL,
3448                                  descr->infoWidth, lines, 32, 0 );
3449         bmpImage->data = calloc( lines, bmpImage->bytes_per_line );
3450         if(bmpImage->data == NULL) {
3451             ERR("Out of memory!\n");
3452             XDestroyImage( bmpImage );
3453             wine_tsx11_unlock();
3454             return lines;
3455         }
3456     }
3457
3458     TRACE("Dib: depth=%d r=%lx g=%lx b=%lx\n",
3459           descr->infoBpp,descr->rMask,descr->gMask,descr->bMask);
3460     TRACE("Bmp: depth=%d/%d r=%lx g=%lx b=%lx\n",
3461           bmpImage->depth,bmpImage->bits_per_pixel,
3462           bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
3463
3464       /* Transfer the pixels */
3465     switch(descr->infoBpp)
3466     {
3467     case 1:
3468         X11DRV_DIB_SetImageBits_1( descr->lines, descr->bits, descr->infoWidth,
3469                                    descr->width, descr->xSrc, (int *)(descr->colorMap),
3470                                    bmpImage, descr->dibpitch );
3471         break;
3472     case 4:
3473         if (descr->compression) {
3474             XGetSubImage( gdi_display, descr->drawable, descr->xDest, descr->yDest,
3475                           descr->width, descr->height, AllPlanes, ZPixmap,
3476                           bmpImage, descr->xSrc, descr->ySrc );
3477
3478             X11DRV_DIB_SetImageBits_RLE4( descr->lines, descr->bits,
3479                                           descr->infoWidth, descr->width,
3480                                           descr->xSrc, (int *)(descr->colorMap),
3481                                           bmpImage );
3482         } else
3483             X11DRV_DIB_SetImageBits_4( descr->lines, descr->bits,
3484                                        descr->infoWidth, descr->width,
3485                                        descr->xSrc, (int*)(descr->colorMap),
3486                                        bmpImage, descr->dibpitch );
3487         break;
3488     case 8:
3489         if (descr->compression) {
3490             XGetSubImage( gdi_display, descr->drawable, descr->xDest, descr->yDest,
3491                           descr->width, descr->height, AllPlanes, ZPixmap,
3492                           bmpImage, descr->xSrc, descr->ySrc );
3493             X11DRV_DIB_SetImageBits_RLE8( descr->lines, descr->bits,
3494                                           descr->infoWidth, descr->width,
3495                                           descr->xSrc, (int *)(descr->colorMap),
3496                                           bmpImage );
3497         } else
3498             X11DRV_DIB_SetImageBits_8( descr->lines, descr->bits,
3499                                        descr->infoWidth, descr->width,
3500                                        descr->xSrc, (int *)(descr->colorMap),
3501                                        bmpImage, descr->dibpitch );
3502         break;
3503     case 15:
3504     case 16:
3505         X11DRV_DIB_SetImageBits_16( descr->lines, descr->bits,
3506                                     descr->infoWidth, descr->width,
3507                                    descr->xSrc, descr->physDev,
3508                                    descr->rMask, descr->gMask, descr->bMask,
3509                                    bmpImage, descr->dibpitch);
3510         break;
3511     case 24:
3512         X11DRV_DIB_SetImageBits_24( descr->lines, descr->bits,
3513                                     descr->infoWidth, descr->width,
3514                                     descr->xSrc, descr->physDev,
3515                                     descr->rMask, descr->gMask, descr->bMask,
3516                                     bmpImage, descr->dibpitch);
3517         break;
3518     case 32:
3519         X11DRV_DIB_SetImageBits_32( descr->lines, descr->bits,
3520                                     descr->infoWidth, descr->width,
3521                                    descr->xSrc, descr->physDev,
3522                                    descr->rMask, descr->gMask, descr->bMask,
3523                                    bmpImage, descr->dibpitch);
3524         break;
3525     default:
3526         WARN("(%d): Invalid depth\n", descr->infoBpp );
3527         break;
3528     }
3529
3530     TRACE("XPutImage(%ld,%p,%p,%d,%d,%d,%d,%d,%d)\n",
3531      descr->drawable, descr->gc, bmpImage,
3532      descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
3533      descr->width, descr->height);
3534 #ifdef HAVE_LIBXXSHM
3535     if (descr->useShm)
3536     {
3537         XShmPutImage( gdi_display, descr->drawable, descr->gc, bmpImage,
3538                       descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
3539                       descr->width, descr->height, FALSE );
3540         XSync( gdi_display, 0 );
3541     }
3542     else
3543 #endif
3544         XPutImage( gdi_display, descr->drawable, descr->gc, bmpImage,
3545                    descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
3546                    descr->width, descr->height );
3547
3548     if (!descr->image) XDestroyImage( bmpImage );
3549     wine_tsx11_unlock();
3550     return lines;
3551 }
3552
3553 /***********************************************************************
3554  *           X11DRV_DIB_GetImageBits
3555  *
3556  * Transfer the bits from an X image.
3557  */
3558 static int X11DRV_DIB_GetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
3559 {
3560     int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
3561     XImage *bmpImage;
3562
3563     wine_tsx11_lock();
3564    if (descr->image)
3565         bmpImage = descr->image;
3566     else {
3567         bmpImage = XCreateImage( gdi_display, visual, descr->depth, ZPixmap, 0, NULL,
3568                                  descr->infoWidth, lines, 32, 0 );
3569         bmpImage->data = calloc( lines, bmpImage->bytes_per_line );
3570         if(bmpImage->data == NULL) {
3571             ERR("Out of memory!\n");
3572             XDestroyImage( bmpImage );
3573             wine_tsx11_unlock();
3574             return lines;
3575         }
3576     }
3577
3578 #ifdef HAVE_LIBXXSHM
3579     if (descr->useShm)
3580     {
3581         int saveRed, saveGreen, saveBlue;
3582
3583         TRACE("XShmGetImage(%p, %ld, %p, %d, %d, %ld)\n",
3584                             gdi_display, descr->drawable, bmpImage,
3585                             descr->xSrc, descr->ySrc, AllPlanes);
3586
3587         /* We must save and restore the bmpImage's masks in order
3588          * to preserve them across the call to XShmGetImage, which
3589          * decides to eleminate them since it doesn't happen to know
3590          * what the format of the image is supposed to be, even though
3591          * we do. */
3592         saveRed = bmpImage->red_mask;
3593         saveBlue= bmpImage->blue_mask;
3594         saveGreen = bmpImage->green_mask;
3595
3596         XShmGetImage( gdi_display, descr->drawable, bmpImage,
3597                       descr->xSrc, descr->ySrc, AllPlanes);
3598
3599         bmpImage->red_mask = saveRed;
3600         bmpImage->blue_mask = saveBlue;
3601         bmpImage->green_mask = saveGreen;
3602     }
3603     else
3604 #endif /* HAVE_LIBXXSHM */
3605     {
3606         TRACE("XGetSubImage(%p,%ld,%d,%d,%d,%d,%ld,%d,%p,%d,%d)\n",
3607               gdi_display, descr->drawable, descr->xSrc, descr->ySrc, descr->width,
3608               lines, AllPlanes, ZPixmap, bmpImage, descr->xDest, descr->yDest);
3609         XGetSubImage( gdi_display, descr->drawable, descr->xSrc, descr->ySrc,
3610                       descr->width, lines, AllPlanes, ZPixmap,
3611                       bmpImage, descr->xDest, descr->yDest );
3612     }
3613
3614     TRACE("Dib: depth=%2d r=%lx g=%lx b=%lx\n",
3615           descr->infoBpp,descr->rMask,descr->gMask,descr->bMask);
3616     TRACE("Bmp: depth=%2d/%2d r=%lx g=%lx b=%lx\n",
3617           bmpImage->depth,bmpImage->bits_per_pixel,
3618           bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
3619       /* Transfer the pixels */
3620     switch(descr->infoBpp)
3621     {
3622     case 1:
3623           X11DRV_DIB_GetImageBits_1( descr->lines,(LPVOID)descr->bits,
3624                                      descr->infoWidth, descr->width,
3625                                      descr->colorMap, descr->palentry,
3626                                      bmpImage, descr->dibpitch );
3627        break;
3628
3629     case 4:
3630         if (descr->compression) {
3631            FIXME("Compression not yet supported!\n");
3632            if(descr->sizeImage < X11DRV_DIB_GetDIBWidthBytes( descr->infoWidth, 4 ) * abs(descr->lines))
3633                break;
3634         }
3635         X11DRV_DIB_GetImageBits_4( descr->lines,(LPVOID)descr->bits,
3636                                    descr->infoWidth, descr->width,
3637                                    descr->colorMap, descr->palentry,
3638                                    bmpImage, descr->dibpitch );
3639         break;
3640     case 8:
3641         if (descr->compression) {
3642            FIXME("Compression not yet supported!\n");
3643            if(descr->sizeImage < X11DRV_DIB_GetDIBWidthBytes( descr->infoWidth, 8 ) * abs(descr->lines))
3644                break;
3645         }
3646         X11DRV_DIB_GetImageBits_8( descr->lines, (LPVOID)descr->bits,
3647                                    descr->infoWidth, descr->width,
3648                                    descr->colorMap, descr->palentry,
3649                                    bmpImage, descr->dibpitch );
3650         break;
3651     case 15:
3652     case 16:
3653        X11DRV_DIB_GetImageBits_16( descr->lines, (LPVOID)descr->bits,
3654                                    descr->infoWidth,descr->width,
3655                                    descr->palentry,
3656                                    descr->rMask, descr->gMask, descr->bMask,
3657                                    bmpImage, descr->dibpitch );
3658        break;
3659
3660     case 24:
3661        X11DRV_DIB_GetImageBits_24( descr->lines, (LPVOID)descr->bits,
3662                                    descr->infoWidth,descr->width,
3663                                    descr->palentry,
3664                                    descr->rMask, descr->gMask, descr->bMask,
3665                                    bmpImage, descr->dibpitch);
3666        break;
3667
3668     case 32:
3669        X11DRV_DIB_GetImageBits_32( descr->lines, (LPVOID)descr->bits,
3670                                    descr->infoWidth, descr->width,
3671                                    descr->palentry,
3672                                    descr->rMask, descr->gMask, descr->bMask,
3673                                    bmpImage, descr->dibpitch);
3674        break;
3675
3676     default:
3677         WARN("(%d): Invalid depth\n", descr->infoBpp );
3678         break;
3679     }
3680
3681     if (!descr->image) XDestroyImage( bmpImage );
3682     wine_tsx11_unlock();
3683     return lines;
3684 }
3685
3686 /*************************************************************************
3687  *              X11DRV_SetDIBitsToDevice
3688  *
3689  */
3690 INT X11DRV_SetDIBitsToDevice( X11DRV_PDEVICE *physDev, INT xDest, INT yDest, DWORD cx,
3691                                 DWORD cy, INT xSrc, INT ySrc,
3692                                 UINT startscan, UINT lines, LPCVOID bits,
3693                                 const BITMAPINFO *info, UINT coloruse )
3694 {
3695     X11DRV_DIB_IMAGEBITS_DESCR descr;
3696     INT result;
3697     LONG width, height;
3698     BOOL top_down;
3699     POINT pt;
3700     void* colorPtr;
3701
3702     if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height,
3703                            &descr.infoBpp, &descr.compression ) == -1)
3704         return 0;
3705
3706     top_down = (height < 0);
3707     if (top_down) height = -height;
3708
3709     pt.x = xDest;
3710     pt.y = yDest;
3711     LPtoDP(physDev->hdc, &pt, 1);
3712
3713     if (!lines || (startscan >= height)) return 0;
3714     if (!top_down && startscan + lines > height) lines = height - startscan;
3715
3716     /* make xSrc,ySrc point to the upper-left corner, not the lower-left one,
3717      * and clamp all values to fit inside [startscan,startscan+lines]
3718      */
3719     if (ySrc + cy <= startscan + lines)
3720     {
3721         UINT y = startscan + lines - (ySrc + cy);
3722         if (ySrc < startscan) cy -= (startscan - ySrc);
3723         if (!top_down)
3724         {
3725             /* avoid getting unnecessary lines */
3726             ySrc = 0;
3727             if (y >= lines) return 0;
3728             lines -= y;
3729         }
3730         else
3731         {
3732             if (y >= lines) return lines;
3733             ySrc = y;  /* need to get all lines in top down mode */
3734         }
3735     }
3736     else
3737     {
3738         if (ySrc >= startscan + lines) return lines;
3739         pt.y += ySrc + cy - (startscan + lines);
3740         cy = startscan + lines - ySrc;
3741         ySrc = 0;
3742         if (cy > lines) cy = lines;
3743     }
3744     if (xSrc >= width) return lines;
3745     if (xSrc + cx >= width) cx = width - xSrc;
3746     if (!cx || !cy) return lines;
3747
3748     /* Update the pixmap from the DIB section */
3749     X11DRV_LockDIBSection(physDev, DIB_Status_GdiMod, FALSE);
3750
3751     X11DRV_SetupGCForText( physDev );  /* To have the correct colors */
3752     wine_tsx11_lock();
3753     XSetFunction(gdi_display, physDev->gc, X11DRV_XROPfunction[GetROP2(physDev->hdc) - 1]);
3754     wine_tsx11_unlock();
3755
3756     colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
3757
3758     switch (descr.infoBpp)
3759     {
3760        case 1:
3761        case 4:
3762        case 8:
3763                descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap(
3764                                             coloruse == DIB_PAL_COLORS ? physDev : NULL, coloruse,
3765                                             physDev->depth, info, &descr.nColorMap );
3766                if (!descr.colorMap) return 0;
3767                descr.rMask = descr.gMask = descr.bMask = 0;
3768                break;
3769        case 15:
3770        case 16:
3771                descr.rMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)colorPtr    ) : 0x7c00;
3772                descr.gMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)colorPtr + 1) : 0x03e0;
3773                descr.bMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)colorPtr + 2) : 0x001f;
3774                descr.colorMap = 0;
3775                break;
3776
3777        case 24:
3778        case 32:
3779                descr.rMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)colorPtr    ) : 0xff0000;
3780                descr.gMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)colorPtr + 1) : 0x00ff00;
3781                descr.bMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)colorPtr + 2) : 0x0000ff;
3782                descr.colorMap = 0;
3783                break;
3784     }
3785
3786     descr.physDev   = physDev;
3787     descr.bits      = bits;
3788     descr.image     = NULL;
3789     descr.palentry  = NULL;
3790     descr.lines     = top_down ? -lines : lines;
3791     descr.infoWidth = width;
3792     descr.depth     = physDev->depth;
3793     descr.drawable  = physDev->drawable;
3794     descr.gc        = physDev->gc;
3795     descr.xSrc      = xSrc;
3796     descr.ySrc      = ySrc;
3797     descr.xDest     = physDev->org.x + pt.x;
3798     descr.yDest     = physDev->org.y + pt.y;
3799     descr.width     = cx;
3800     descr.height    = cy;
3801     descr.useShm    = FALSE;
3802     descr.dibpitch  = ((width * descr.infoBpp + 31) &~31) / 8;
3803
3804     result = X11DRV_DIB_SetImageBits( &descr );
3805
3806     if (descr.infoBpp <= 8)
3807        HeapFree(GetProcessHeap(), 0, descr.colorMap);
3808
3809     /* Update the DIBSection of the pixmap */
3810     X11DRV_UnlockDIBSection(physDev, TRUE);
3811
3812     return result;
3813 }
3814
3815 /***********************************************************************
3816  *           SetDIBits   (X11DRV.@)
3817  */
3818 INT X11DRV_SetDIBits( X11DRV_PDEVICE *physDev, HBITMAP hbitmap, UINT startscan,
3819                       UINT lines, LPCVOID bits, const BITMAPINFO *info, UINT coloruse )
3820 {
3821   X11DRV_DIB_IMAGEBITS_DESCR descr;
3822   BITMAPOBJ *bmp;
3823   LONG height, tmpheight;
3824   INT result;
3825   void* colorPtr;
3826
3827   descr.physDev = physDev;
3828
3829   if (DIB_GetBitmapInfo( &info->bmiHeader, &descr.infoWidth, &height,
3830                          &descr.infoBpp, &descr.compression ) == -1)
3831       return 0;
3832
3833   tmpheight = height;
3834   if (height < 0) height = -height;
3835   if (!lines || (startscan >= height))
3836       return 0;
3837
3838   if (!(bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC ))) return 0;
3839
3840   if (startscan + lines > height) lines = height - startscan;
3841
3842   colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
3843
3844   switch (descr.infoBpp)
3845   {
3846        case 1:
3847        case 4:
3848        case 8:
3849                descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap(
3850                         coloruse == DIB_PAL_COLORS ? descr.physDev : NULL, coloruse,
3851                                                           bmp->bitmap.bmBitsPixel,
3852                                                           info, &descr.nColorMap );
3853                if (!descr.colorMap)
3854                {
3855                    GDI_ReleaseObj( hbitmap );
3856                    return 0;
3857                }
3858                descr.rMask = descr.gMask = descr.bMask = 0;
3859                break;
3860        case 15:
3861        case 16:
3862                descr.rMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD*)colorPtr    ) : 0x7c00;
3863                descr.gMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD*)colorPtr + 1) : 0x03e0;
3864                descr.bMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD*)colorPtr + 2) : 0x001f;
3865                descr.colorMap = 0;
3866                break;
3867
3868        case 24:
3869        case 32:
3870                descr.rMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD*)colorPtr    ) : 0xff0000;
3871                descr.gMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD*)colorPtr + 1) : 0x00ff00;
3872                descr.bMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD*)colorPtr + 2) : 0x0000ff;
3873                descr.colorMap = 0;
3874                break;
3875
3876        default: break;
3877   }
3878
3879   descr.bits      = bits;
3880   descr.image     = NULL;
3881   descr.palentry  = NULL;
3882   descr.lines     = tmpheight >= 0 ? lines : -lines;
3883   descr.depth     = bmp->bitmap.bmBitsPixel;
3884   descr.drawable  = (Pixmap)bmp->physBitmap;
3885   descr.gc        = BITMAP_GC(bmp);
3886   descr.xSrc      = 0;
3887   descr.ySrc      = 0;
3888   descr.xDest     = 0;
3889   descr.yDest     = height - startscan - lines;
3890   descr.width     = bmp->bitmap.bmWidth;
3891   descr.height    = lines;
3892   descr.useShm    = FALSE;
3893   descr.dibpitch  = ((descr.infoWidth * descr.infoBpp + 31) &~31) / 8;
3894   X11DRV_DIB_Lock(bmp, DIB_Status_GdiMod, FALSE);
3895   result = X11DRV_DIB_SetImageBits( &descr );
3896   X11DRV_DIB_Unlock(bmp, TRUE);
3897
3898   HeapFree(GetProcessHeap(), 0, descr.colorMap);
3899
3900   GDI_ReleaseObj( hbitmap );
3901   return result;
3902 }
3903
3904 /***********************************************************************
3905  *           GetDIBits   (X11DRV.@)
3906  */
3907 INT X11DRV_GetDIBits( X11DRV_PDEVICE *physDev, HBITMAP hbitmap, UINT startscan, UINT lines,
3908                       LPVOID bits, BITMAPINFO *info, UINT coloruse )
3909 {
3910   X11DRV_DIBSECTION *dib;
3911   X11DRV_DIB_IMAGEBITS_DESCR descr;
3912   PALETTEENTRY palette[256];
3913   BITMAPOBJ *bmp;
3914   int height;
3915   LONG tempHeight;
3916   int bitmap_type;
3917   BOOL core_header;
3918   void* colorPtr;
3919
3920   GetPaletteEntries( GetCurrentObject( physDev->hdc, OBJ_PAL ), 0, 256, palette );
3921
3922   if (!(bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC ))) return 0;
3923
3924   dib = (X11DRV_DIBSECTION *) bmp->dib;
3925   
3926   bitmap_type = DIB_GetBitmapInfo( (BITMAPINFOHEADER*) info, &descr.infoWidth, &tempHeight, &descr.infoBpp, &descr.compression);
3927   descr.lines = tempHeight;
3928   if (bitmap_type == -1)
3929   {
3930       ERR("Invalid bitmap\n");
3931       lines = 0;
3932       goto done;
3933   }
3934   core_header = (bitmap_type == 0);
3935   colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
3936
3937   TRACE("%u scanlines of (%i,%i) -> (%i,%i) starting from %u\n",
3938         lines, bmp->bitmap.bmWidth, bmp->bitmap.bmHeight,
3939         (int)descr.infoWidth, descr.lines, startscan);
3940
3941   if( lines > bmp->bitmap.bmHeight ) lines = bmp->bitmap.bmHeight;
3942
3943   height = descr.lines;
3944   if (height < 0) height = -height;
3945   if( lines > height ) lines = height;
3946   /* Top-down images have a negative biHeight, the scanlines of theses images
3947    * were inverted in X11DRV_DIB_GetImageBits_xx
3948    * To prevent this we simply change the sign of lines
3949    * (the number of scan lines to copy).
3950    * Negative lines are correctly handled by X11DRV_DIB_GetImageBits_xx.
3951    */
3952   if( descr.lines < 0 && lines > 0) lines = -lines;
3953
3954   if( startscan >= bmp->bitmap.bmHeight )
3955   {
3956       lines = 0;
3957       goto done;
3958   }
3959
3960   descr.colorMap = NULL;
3961
3962   switch (descr.infoBpp)
3963   {
3964       case 1:
3965       case 4:
3966       case 8:
3967           descr.rMask= descr.gMask = descr.bMask = 0;
3968           if(coloruse == DIB_RGB_COLORS)
3969               descr.colorMap = colorPtr;
3970           else {
3971               int num_colors = 1 << descr.infoBpp, i;
3972               RGBQUAD *rgb;
3973               COLORREF colref;
3974               WORD *index = (WORD*)colorPtr;
3975               descr.colorMap = rgb = HeapAlloc(GetProcessHeap(), 0, num_colors * sizeof(RGBQUAD));
3976               for(i = 0; i < num_colors; i++, rgb++, index++) {
3977                   colref = X11DRV_PALETTE_ToLogical(X11DRV_PALETTE_ToPhysical(physDev, PALETTEINDEX(*index)));
3978                   rgb->rgbRed = GetRValue(colref);
3979                   rgb->rgbGreen = GetGValue(colref);
3980                   rgb->rgbBlue = GetBValue(colref);
3981                   rgb->rgbReserved = 0;
3982               }
3983           }
3984           break;
3985       case 15:
3986       case 16:
3987           descr.rMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)colorPtr    ) : 0x7c00;
3988           descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)colorPtr + 1) : 0x03e0;
3989           descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)colorPtr + 2) : 0x001f;
3990           break;
3991       case 24:
3992       case 32:
3993           descr.rMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)colorPtr    ) : 0xff0000;
3994           descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)colorPtr + 1) : 0x00ff00;
3995           descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)colorPtr + 2) : 0x0000ff;
3996           break;
3997   }
3998
3999   descr.physDev   = physDev;
4000   descr.palentry  = palette;
4001   descr.bits      = bits;
4002   descr.image     = NULL;
4003   descr.lines     = lines;
4004   descr.depth     = bmp->bitmap.bmBitsPixel;
4005   descr.drawable  = (Pixmap)bmp->physBitmap;
4006   descr.gc        = BITMAP_GC(bmp);
4007   descr.width     = bmp->bitmap.bmWidth;
4008   descr.height    = bmp->bitmap.bmHeight;
4009   descr.xDest     = 0;
4010   descr.yDest     = 0;
4011   descr.xSrc      = 0;
4012   descr.sizeImage = core_header ? 0 : info->bmiHeader.biSizeImage;
4013
4014   if (descr.lines > 0)
4015   {
4016      descr.ySrc = (descr.height-1) - (startscan + (lines-1));
4017   }
4018   else
4019   {
4020      descr.ySrc = startscan;
4021   }
4022 #ifdef HAVE_LIBXXSHM
4023   descr.useShm = dib ? (dib->shminfo.shmid != -1) : FALSE;
4024 #else
4025   descr.useShm = FALSE;
4026 #endif
4027   descr.dibpitch = dib ? (dib->dibSection.dsBm.bmWidthBytes)
4028                        : (((descr.infoWidth * descr.infoBpp + 31) &~31) / 8);
4029
4030   X11DRV_DIB_Lock(bmp, DIB_Status_GdiMod, FALSE);
4031   X11DRV_DIB_GetImageBits( &descr );
4032   X11DRV_DIB_Unlock(bmp, TRUE);
4033
4034   if(!core_header && info->bmiHeader.biSizeImage == 0) /* Fill in biSizeImage */
4035       info->bmiHeader.biSizeImage = X11DRV_DIB_GetDIBImageBytes( descr.infoWidth,
4036                                                                  descr.lines,
4037                                                                  descr.infoBpp);
4038
4039   if (descr.compression == BI_BITFIELDS)
4040   {
4041     *(DWORD *) colorPtr      = descr.rMask;
4042     *((DWORD *)colorPtr + 1) = descr.gMask;
4043     *((DWORD *)colorPtr + 2) = descr.bMask;
4044   }
4045   else if (!core_header)
4046   {
4047     /* if RLE or JPEG compression were supported,
4048      * this line would be invalid. */
4049     info->bmiHeader.biCompression = 0;
4050   }
4051
4052   if(descr.colorMap && descr.colorMap != colorPtr)
4053       HeapFree(GetProcessHeap(), 0, descr.colorMap);
4054 done:
4055   GDI_ReleaseObj( hbitmap );
4056   return lines;
4057 }
4058
4059 /***********************************************************************
4060  *           DIB_DoProtectDIBSection
4061  */
4062 static void X11DRV_DIB_DoProtectDIBSection( BITMAPOBJ *bmp, DWORD new_prot )
4063 {
4064     DWORD old_prot;
4065     INT totalSize;
4066     DIBSECTION *dib = bmp->dib;
4067     INT effHeight = dib->dsBm.bmHeight >= 0? dib->dsBm.bmHeight
4068                                              : -dib->dsBm.bmHeight;
4069
4070     /* use the biSizeImage data as the memory size only if we're dealing with a
4071        compressed image where the value is set.  Otherwise, calculate based on
4072        width * height */
4073     if (dib->dsBmih.biSizeImage &&
4074         (dib->dsBmih.biCompression == BI_RLE4 || dib->dsBmih.biCompression == BI_RLE8))
4075         totalSize = dib->dsBmih.biSizeImage;
4076     else
4077         totalSize = dib->dsBm.bmWidthBytes * effHeight;
4078
4079     VirtualProtect(dib->dsBm.bmBits, totalSize, new_prot, &old_prot);
4080     TRACE("Changed protection from %ld to %ld\n", old_prot, new_prot);
4081 }
4082
4083 /***********************************************************************
4084  *           X11DRV_DIB_DoUpdateDIBSection
4085  */
4086 static void X11DRV_DIB_DoCopyDIBSection(BITMAPOBJ *bmp, BOOL toDIB,
4087                                         void *colorMap, int nColorMap,
4088                                         Drawable dest,
4089                                         DWORD xSrc, DWORD ySrc,
4090                                         DWORD xDest, DWORD yDest,
4091                                         DWORD width, DWORD height)
4092 {
4093   X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
4094   X11DRV_DIB_IMAGEBITS_DESCR descr;
4095   int identity[2] = {0,1};
4096
4097   if (DIB_GetBitmapInfo( &dib->dibSection.dsBmih, &descr.infoWidth, (DWORD*) &descr.lines,
4098                          &descr.infoBpp, &descr.compression ) == -1)
4099     return;
4100
4101   descr.physDev   = NULL;
4102   descr.palentry  = NULL;
4103   descr.image     = dib->image;
4104   descr.colorMap  = colorMap;
4105   descr.nColorMap = nColorMap;
4106   descr.bits      = dib->dibSection.dsBm.bmBits;
4107   descr.depth     = bmp->bitmap.bmBitsPixel;
4108
4109   if(descr.infoBpp == 1)
4110       descr.colorMap = (void*)identity;
4111
4112   switch (descr.infoBpp)
4113   {
4114     case 1:
4115     case 4:
4116     case 8:
4117       descr.rMask = descr.gMask = descr.bMask = 0;
4118       break;
4119     case 15:
4120     case 16:
4121       descr.rMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[0] : 0x7c00;
4122       descr.gMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[1] : 0x03e0;
4123       descr.bMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[2] : 0x001f;
4124       break;
4125
4126     case 24:
4127     case 32:
4128       descr.rMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[0] : 0xff0000;
4129       descr.gMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[1] : 0x00ff00;
4130       descr.bMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[2] : 0x0000ff;
4131       break;
4132   }
4133
4134   /* Hack for now */
4135   descr.drawable  = dest;
4136   descr.gc        = BITMAP_GC(bmp);
4137   descr.xSrc      = xSrc;
4138   descr.ySrc      = ySrc;
4139   descr.xDest     = xDest;
4140   descr.yDest     = yDest;
4141   descr.width     = width;
4142   descr.height    = height;
4143   descr.sizeImage = 0;
4144
4145 #ifdef HAVE_LIBXXSHM
4146   descr.useShm = (dib->shminfo.shmid != -1);
4147 #else
4148   descr.useShm = FALSE;
4149 #endif
4150   descr.dibpitch = dib->dibSection.dsBm.bmWidthBytes;
4151
4152   if (toDIB)
4153     {
4154       TRACE("Copying from Pixmap to DIB bits\n");
4155       X11DRV_DIB_GetImageBits( &descr );
4156     }
4157   else
4158     {
4159       TRACE("Copying from DIB bits to Pixmap\n");
4160       X11DRV_DIB_SetImageBits( &descr );
4161     }
4162 }
4163
4164 /***********************************************************************
4165  *           X11DRV_DIB_CopyDIBSection
4166  */
4167 void X11DRV_DIB_CopyDIBSection(X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE *physDevDst,
4168                                DWORD xSrc, DWORD ySrc, DWORD xDest, DWORD yDest,
4169                                DWORD width, DWORD height)
4170 {
4171   BITMAPOBJ *bmp;
4172   HBITMAP hBitmap;
4173   int nColorMap = 0, *colorMap = NULL, aColorMap = FALSE;
4174
4175   TRACE("(%p,%p,%ld,%ld,%ld,%ld,%ld,%ld)\n", physDevSrc->hdc, physDevDst->hdc,
4176     xSrc, ySrc, xDest, yDest, width, height);
4177   /* this function is meant as an optimization for BitBlt,
4178    * not to be called otherwise */
4179   if (GetObjectType( physDevSrc->hdc ) != OBJ_MEMDC) {
4180     ERR("called for non-memory source DC!?\n");
4181     return;
4182   }
4183
4184   hBitmap = GetCurrentObject( physDevSrc->hdc, OBJ_BITMAP );
4185   bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBitmap, BITMAP_MAGIC );
4186   if (!(bmp && bmp->dib)) {
4187     ERR("called for non-DIBSection!?\n");
4188     GDI_ReleaseObj( hBitmap );
4189     return;
4190   }
4191   /* while BitBlt should already have made sure we only get
4192    * positive values, we should check for oversize values */
4193   if ((xSrc < bmp->bitmap.bmWidth) &&
4194       (ySrc < bmp->bitmap.bmHeight)) {
4195     if (xSrc + width > bmp->bitmap.bmWidth)
4196       width = bmp->bitmap.bmWidth - xSrc;
4197     if (ySrc + height > bmp->bitmap.bmHeight)
4198       height = bmp->bitmap.bmHeight - ySrc;
4199     /* if the source bitmap is 8bpp or less, we're supposed to use the
4200      * DC's palette for color conversion (not the DIB color table) */
4201     if (bmp->dib->dsBm.bmBitsPixel <= 8) {
4202       X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
4203       HPALETTE hPalette = GetCurrentObject( physDevSrc->hdc, OBJ_PAL );
4204       if (!hPalette || (hPalette == GetStockObject(DEFAULT_PALETTE))) {
4205         /* HACK: no palette has been set in the source DC,
4206          * use the DIB colormap instead - this is necessary in some
4207          * cases since we need to do depth conversion in some places
4208          * where real Windows can just copy data straight over */
4209         colorMap = dib->colorMap;
4210         nColorMap = dib->nColorMap;
4211       } else {
4212         colorMap = X11DRV_DIB_BuildColorMap( physDevSrc, (WORD)-1,
4213                                              bmp->dib->dsBm.bmBitsPixel,
4214                                              (BITMAPINFO*)&(bmp->dib->dsBmih),
4215                                              &nColorMap );
4216         if (colorMap) aColorMap = TRUE;
4217       }
4218     }
4219     /* perform the copy */
4220     X11DRV_DIB_DoCopyDIBSection(bmp, FALSE, colorMap, nColorMap,
4221                                 physDevDst->drawable, xSrc, ySrc,
4222                                 physDevDst->org.x + xDest, physDevDst->org.y + yDest,
4223                                 width, height);
4224     /* free color mapping */
4225     if (aColorMap)
4226       HeapFree(GetProcessHeap(), 0, colorMap);
4227   }
4228   GDI_ReleaseObj( hBitmap );
4229 }
4230
4231 /***********************************************************************
4232  *           X11DRV_DIB_DoUpdateDIBSection
4233  */
4234 static void X11DRV_DIB_DoUpdateDIBSection(BITMAPOBJ *bmp, BOOL toDIB)
4235 {
4236   X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
4237   X11DRV_DIB_DoCopyDIBSection(bmp, toDIB, dib->colorMap, dib->nColorMap,
4238                               (Drawable)bmp->physBitmap, 0, 0, 0, 0,
4239                               bmp->bitmap.bmWidth, bmp->bitmap.bmHeight);
4240 }
4241
4242 /***********************************************************************
4243  *           X11DRV_DIB_FaultHandler
4244  */
4245 static BOOL X11DRV_DIB_FaultHandler( LPVOID res, LPCVOID addr )
4246 {
4247   BITMAPOBJ *bmp;
4248   INT state;
4249
4250   bmp = (BITMAPOBJ *)GDI_GetObjPtr( (HBITMAP)res, BITMAP_MAGIC );
4251   if (!bmp) return FALSE;
4252
4253   state = X11DRV_DIB_Lock(bmp, DIB_Status_None, FALSE);
4254   if (state != DIB_Status_InSync) {
4255     /* no way to tell whether app needs read or write yet,
4256      * try read first */
4257     X11DRV_DIB_Coerce(bmp, DIB_Status_InSync, FALSE);
4258   } else {
4259     /* hm, apparently the app must have write access */
4260     X11DRV_DIB_Coerce(bmp, DIB_Status_AppMod, FALSE);
4261   }
4262   X11DRV_DIB_Unlock(bmp, TRUE);
4263
4264   GDI_ReleaseObj( (HBITMAP)res );
4265   return TRUE;
4266 }
4267
4268 /***********************************************************************
4269  *           X11DRV_DIB_Coerce
4270  */
4271 INT X11DRV_DIB_Coerce(BITMAPOBJ *bmp, INT req, BOOL lossy)
4272 {
4273   X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
4274   INT ret = DIB_Status_None;
4275
4276   if (dib) {
4277     EnterCriticalSection(&(dib->lock));
4278     ret = dib->status;
4279     switch (req) {
4280     case DIB_Status_GdiMod:
4281       /* GDI access - request to draw on pixmap */
4282       switch (dib->status)
4283       {
4284         default:
4285         case DIB_Status_None:
4286           dib->p_status = DIB_Status_GdiMod;
4287           X11DRV_DIB_DoUpdateDIBSection( bmp, FALSE );
4288           break;
4289
4290         case DIB_Status_GdiMod:
4291           TRACE("GdiMod requested in status GdiMod\n" );
4292           dib->p_status = DIB_Status_GdiMod;
4293           break;
4294
4295         case DIB_Status_InSync:
4296           TRACE("GdiMod requested in status InSync\n" );
4297           X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
4298           dib->status = DIB_Status_GdiMod;
4299           dib->p_status = DIB_Status_InSync;
4300           break;
4301
4302         case DIB_Status_AuxMod:
4303           TRACE("GdiMod requested in status AuxMod\n" );
4304           if (lossy) dib->status = DIB_Status_GdiMod;
4305           else (*dib->copy_aux)(dib->aux_ctx, DIB_Status_GdiMod);
4306           dib->p_status = DIB_Status_AuxMod;
4307           if (dib->status != DIB_Status_AppMod) {
4308             X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
4309             break;
4310           }
4311           /* fall through if copy_aux() had to change to AppMod state */
4312
4313         case DIB_Status_AppMod:
4314           TRACE("GdiMod requested in status AppMod\n" );
4315           if (!lossy) {
4316             /* make it readonly to avoid app changing data while we copy */
4317             X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
4318             X11DRV_DIB_DoUpdateDIBSection( bmp, FALSE );
4319           }
4320           X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
4321           dib->p_status = DIB_Status_AppMod;
4322           dib->status = DIB_Status_GdiMod;
4323           break;
4324       }
4325       break;
4326
4327     case DIB_Status_InSync:
4328       /* App access - request access to read DIB surface */
4329       /* (typically called from signal handler) */
4330       switch (dib->status)
4331       {
4332         default:
4333         case DIB_Status_None:
4334           /* shouldn't happen from signal handler */
4335           break;
4336
4337         case DIB_Status_AuxMod:
4338           TRACE("InSync requested in status AuxMod\n" );
4339           if (lossy) dib->status = DIB_Status_InSync;
4340           else {
4341             X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
4342             (*dib->copy_aux)(dib->aux_ctx, DIB_Status_InSync);
4343           }
4344           if (dib->status != DIB_Status_GdiMod) {
4345             X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
4346             break;
4347           }
4348           /* fall through if copy_aux() had to change to GdiMod state */
4349
4350         case DIB_Status_GdiMod:
4351           TRACE("InSync requested in status GdiMod\n" );
4352           if (!lossy) {
4353             X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
4354             X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
4355           }
4356           X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
4357           dib->status = DIB_Status_InSync;
4358           break;
4359
4360         case DIB_Status_InSync:
4361           TRACE("InSync requested in status InSync\n" );
4362           /* shouldn't happen from signal handler */
4363           break;
4364
4365         case DIB_Status_AppMod:
4366           TRACE("InSync requested in status AppMod\n" );
4367           /* no reason to do anything here, and this
4368            * shouldn't happen from signal handler */
4369           break;
4370       }
4371       break;
4372
4373     case DIB_Status_AppMod:
4374       /* App access - request access to write DIB surface */
4375       /* (typically called from signal handler) */
4376       switch (dib->status)
4377       {
4378         default:
4379         case DIB_Status_None:
4380           /* shouldn't happen from signal handler */
4381           break;
4382
4383         case DIB_Status_AuxMod:
4384           TRACE("AppMod requested in status AuxMod\n" );
4385           X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
4386           if (lossy) dib->status = DIB_Status_AppMod;
4387           else (*dib->copy_aux)(dib->aux_ctx, DIB_Status_AppMod);
4388           if (dib->status != DIB_Status_GdiMod)
4389             break;
4390           /* fall through if copy_aux() had to change to GdiMod state */
4391
4392         case DIB_Status_GdiMod:
4393           TRACE("AppMod requested in status GdiMod\n" );
4394           X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
4395           if (!lossy) X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
4396           dib->status = DIB_Status_AppMod;
4397           break;
4398
4399         case DIB_Status_InSync:
4400           TRACE("AppMod requested in status InSync\n" );
4401           X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
4402           dib->status = DIB_Status_AppMod;
4403           break;
4404
4405         case DIB_Status_AppMod:
4406           TRACE("AppMod requested in status AppMod\n" );
4407           /* shouldn't happen from signal handler */
4408           break;
4409       }
4410       break;
4411
4412     case DIB_Status_AuxMod:
4413       if (dib->status == DIB_Status_None) {
4414         dib->p_status = req;
4415       } else {
4416         if (dib->status != DIB_Status_AuxMod)
4417           dib->p_status = dib->status;
4418         dib->status = DIB_Status_AuxMod;
4419       }
4420       break;
4421       /* it is up to the caller to do the copy/conversion, probably
4422        * using the return value to decide where to copy from */
4423     }
4424     LeaveCriticalSection(&(dib->lock));
4425   }
4426   return ret;
4427 }
4428
4429 /***********************************************************************
4430  *           X11DRV_DIB_Lock
4431  */
4432 INT X11DRV_DIB_Lock(BITMAPOBJ *bmp, INT req, BOOL lossy)
4433 {
4434   X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
4435   INT ret = DIB_Status_None;
4436
4437   if (dib) {
4438     TRACE("Locking %p from thread %04lx\n", bmp, GetCurrentThreadId());
4439     EnterCriticalSection(&(dib->lock));
4440     ret = dib->status;
4441     if (req != DIB_Status_None)
4442       X11DRV_DIB_Coerce(bmp, req, lossy);
4443   }
4444   return ret;
4445 }
4446
4447 /***********************************************************************
4448  *           X11DRV_DIB_Unlock
4449  */
4450 void X11DRV_DIB_Unlock(BITMAPOBJ *bmp, BOOL commit)
4451 {
4452   X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
4453
4454   if (dib) {
4455     switch (dib->status)
4456     {
4457       default:
4458       case DIB_Status_None:
4459         /* in case anyone is wondering, this is the "signal handler doesn't
4460          * work" case, where we always have to be ready for app access */
4461         if (commit) {
4462           switch (dib->p_status)
4463           {
4464             case DIB_Status_AuxMod:
4465               TRACE("Unlocking and syncing from AuxMod\n" );
4466               (*dib->copy_aux)(dib->aux_ctx, DIB_Status_AppMod);
4467               if (dib->status != DIB_Status_None) {
4468                 dib->p_status = dib->status;
4469                 dib->status = DIB_Status_None;
4470               }
4471               if (dib->p_status != DIB_Status_GdiMod)
4472                 break;
4473               /* fall through if copy_aux() had to change to GdiMod state */
4474
4475             case DIB_Status_GdiMod:
4476               TRACE("Unlocking and syncing from GdiMod\n" );
4477               X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
4478               break;
4479
4480             default:
4481               TRACE("Unlocking without needing to sync\n" );
4482               break;
4483           }
4484         }
4485         else TRACE("Unlocking with no changes\n");
4486         dib->p_status = DIB_Status_None;
4487         break;
4488
4489       case DIB_Status_GdiMod:
4490         TRACE("Unlocking in status GdiMod\n" );
4491         /* DIB was protected in Coerce */
4492         if (!commit) {
4493           /* no commit, revert to InSync if applicable */
4494           if ((dib->p_status == DIB_Status_InSync) ||
4495               (dib->p_status == DIB_Status_AppMod)) {
4496             X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
4497             dib->status = DIB_Status_InSync;
4498           }
4499         }
4500         break;
4501
4502       case DIB_Status_InSync:
4503         TRACE("Unlocking in status InSync\n" );
4504         /* DIB was already protected in Coerce */
4505         break;
4506
4507       case DIB_Status_AppMod:
4508         TRACE("Unlocking in status AppMod\n" );
4509         /* DIB was already protected in Coerce */
4510         /* this case is ordinary only called from the signal handler,
4511          * so we don't bother to check for !commit */
4512         break;
4513
4514       case DIB_Status_AuxMod:
4515         TRACE("Unlocking in status AuxMod\n" );
4516         if (commit) {
4517           /* DIB may need protection now */
4518           if ((dib->p_status == DIB_Status_InSync) ||
4519               (dib->p_status == DIB_Status_AppMod))
4520             X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
4521         } else {
4522           /* no commit, revert to previous state */
4523           if (dib->p_status != DIB_Status_None)
4524             dib->status = dib->p_status;
4525           /* no protections changed */
4526         }
4527         dib->p_status = DIB_Status_None;
4528         break;
4529     }
4530     LeaveCriticalSection(&(dib->lock));
4531     TRACE("Unlocked %p\n", bmp);
4532   }
4533 }
4534
4535 /***********************************************************************
4536  *           X11DRV_CoerceDIBSection2
4537  */
4538 INT X11DRV_CoerceDIBSection2(HBITMAP hBmp, INT req, BOOL lossy)
4539 {
4540   BITMAPOBJ *bmp;
4541   INT ret;
4542
4543   bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
4544   if (!bmp) return DIB_Status_None;
4545   ret = X11DRV_DIB_Coerce(bmp, req, lossy);
4546   GDI_ReleaseObj( hBmp );
4547   return ret;
4548 }
4549
4550 /***********************************************************************
4551  *           X11DRV_LockDIBSection2
4552  */
4553 INT X11DRV_LockDIBSection2(HBITMAP hBmp, INT req, BOOL lossy)
4554 {
4555   BITMAPOBJ *bmp;
4556   INT ret;
4557
4558   bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
4559   if (!bmp) return DIB_Status_None;
4560   ret = X11DRV_DIB_Lock(bmp, req, lossy);
4561   GDI_ReleaseObj( hBmp );
4562   return ret;
4563 }
4564
4565 /***********************************************************************
4566  *           X11DRV_UnlockDIBSection2
4567  */
4568 void X11DRV_UnlockDIBSection2(HBITMAP hBmp, BOOL commit)
4569 {
4570   BITMAPOBJ *bmp;
4571
4572   bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
4573   if (!bmp) return;
4574   X11DRV_DIB_Unlock(bmp, commit);
4575   GDI_ReleaseObj( hBmp );
4576 }
4577
4578 /***********************************************************************
4579  *           X11DRV_CoerceDIBSection
4580  */
4581 INT X11DRV_CoerceDIBSection(X11DRV_PDEVICE *physDev, INT req, BOOL lossy)
4582 {
4583   if (!physDev) return DIB_Status_None;
4584   return X11DRV_CoerceDIBSection2( GetCurrentObject( physDev->hdc, OBJ_BITMAP ), req, lossy );
4585 }
4586
4587 /***********************************************************************
4588  *           X11DRV_LockDIBSection
4589  */
4590 INT X11DRV_LockDIBSection(X11DRV_PDEVICE *physDev, INT req, BOOL lossy)
4591 {
4592   if (!physDev) return DIB_Status_None;
4593   if (GetObjectType( physDev->hdc ) != OBJ_MEMDC) return DIB_Status_None;
4594
4595   return X11DRV_LockDIBSection2( GetCurrentObject( physDev->hdc, OBJ_BITMAP ), req, lossy );
4596 }
4597
4598 /***********************************************************************
4599  *           X11DRV_UnlockDIBSection
4600  */
4601 void X11DRV_UnlockDIBSection(X11DRV_PDEVICE *physDev, BOOL commit)
4602 {
4603   if (!physDev) return;
4604   if (GetObjectType( physDev->hdc ) != OBJ_MEMDC) return;
4605
4606   X11DRV_UnlockDIBSection2( GetCurrentObject( physDev->hdc, OBJ_BITMAP ), commit );
4607 }
4608
4609
4610 #ifdef HAVE_LIBXXSHM
4611 /***********************************************************************
4612  *           X11DRV_XShmErrorHandler
4613  *
4614  */
4615 static int XShmErrorHandler( Display *dpy, XErrorEvent *event, void *arg )
4616 {
4617     return 1;  /* FIXME: should check event contents */
4618 }
4619
4620 /***********************************************************************
4621  *           X11DRV_XShmCreateImage
4622  *
4623  */
4624 static XImage *X11DRV_XShmCreateImage( int width, int height, int bpp,
4625                                        XShmSegmentInfo* shminfo)
4626 {
4627     XImage *image;
4628
4629     image = XShmCreateImage(gdi_display, visual, bpp, ZPixmap, NULL, shminfo, width, height);
4630     if (image)
4631     {
4632         shminfo->shmid = shmget(IPC_PRIVATE, image->bytes_per_line * height,
4633                                   IPC_CREAT|0700);
4634         if( shminfo->shmid != -1 )
4635         {
4636             shminfo->shmaddr = image->data = shmat(shminfo->shmid, 0, 0);
4637             if( shminfo->shmaddr != (char*)-1 )
4638             {
4639                 BOOL ok;
4640
4641                 shminfo->readOnly = FALSE;
4642                 X11DRV_expect_error( gdi_display, XShmErrorHandler, NULL );
4643                 ok = (XShmAttach( gdi_display, shminfo ) != 0);
4644                 XSync( gdi_display, False );
4645                 if (X11DRV_check_error()) ok = FALSE;
4646                 if (ok)
4647                 {
4648                     shmctl(shminfo->shmid, IPC_RMID, 0);
4649                     return image; /* Success! */
4650                 }
4651                 /* An error occurred */
4652                 shmdt(shminfo->shmaddr);
4653             }
4654             shmctl(shminfo->shmid, IPC_RMID, 0);
4655         }
4656         XFlush(gdi_display);
4657         XDestroyImage(image);
4658         image = NULL;
4659     }
4660     return image;
4661 }
4662 #endif /* HAVE_LIBXXSHM */
4663
4664
4665 /***********************************************************************
4666  *           X11DRV_DIB_CreateDIBSection
4667  */
4668 HBITMAP X11DRV_DIB_CreateDIBSection(
4669   X11DRV_PDEVICE *physDev, const BITMAPINFO *bmi, UINT usage,
4670   VOID **bits, HANDLE section,
4671   DWORD offset, DWORD ovr_pitch)
4672 {
4673   HBITMAP res = 0;
4674   BITMAPOBJ *bmp = NULL;
4675   X11DRV_DIBSECTION *dib = NULL;
4676   int *colorMap = NULL;
4677   int nColorMap;
4678   RGBQUAD *colorTable = NULL;
4679
4680   /* Fill BITMAP structure with DIB data */
4681   INT effHeight, totalSize;
4682   BITMAP bm;
4683   LPVOID mapBits = NULL;
4684
4685   int bitmap_type;
4686   BOOL core_header;
4687   LONG width, height;
4688   WORD planes, bpp, compression;
4689   DWORD sizeImage;
4690   void* colorPtr;
4691
4692   if (((bitmap_type = DIB_GetBitmapInfoEx((BITMAPINFOHEADER*) bmi,
4693         &width, &height, &planes, &bpp, &compression, &sizeImage)) == -1))
4694   {
4695       ERR("Invalid bitmap\n");
4696       return 0;
4697   }
4698   core_header = (bitmap_type == 0);
4699   
4700   TRACE("format (%ld,%ld), planes %d, bpp %d, size %ld, %s\n",
4701         width, height, planes, bpp, 
4702         sizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
4703
4704   effHeight = height >= 0 ? height : -height;
4705   bm.bmType = 0;
4706   bm.bmWidth = width;
4707   bm.bmHeight = effHeight;
4708   bm.bmWidthBytes = ovr_pitch ? ovr_pitch : X11DRV_DIB_GetDIBWidthBytes(bm.bmWidth, bpp);
4709   bm.bmPlanes = planes;
4710   bm.bmBitsPixel = bpp;
4711   bm.bmBits = NULL;
4712
4713   /* Get storage location for DIB bits.  Only use sizeImage if it's valid and
4714      we're dealing with a compressed bitmap.  Otherwise, use width * height. */
4715   if (sizeImage && (compression == BI_RLE4 || compression == BI_RLE8))
4716       totalSize = sizeImage;
4717   else
4718       totalSize = bm.bmWidthBytes * effHeight;
4719
4720   if (section)
4721   {
4722       SYSTEM_INFO SystemInfo;
4723       DWORD mapOffset;
4724       INT mapSize;
4725
4726       GetSystemInfo( &SystemInfo );
4727       mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
4728       mapSize = totalSize + (offset - mapOffset);
4729       mapBits = MapViewOfFile( section,
4730                                FILE_MAP_ALL_ACCESS,
4731                                0L,
4732                                mapOffset,
4733                                mapSize );
4734       bm.bmBits = (char *)mapBits + (offset - mapOffset);
4735   }
4736   else if (ovr_pitch && offset)
4737     bm.bmBits = (LPVOID) offset;
4738   else {
4739     offset = 0;
4740     bm.bmBits = VirtualAlloc(NULL, totalSize,
4741                              MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
4742   }
4743
4744   /* Create Color Map */
4745   if (bm.bmBits && bm.bmBitsPixel <= 8) {
4746       colorMap = X11DRV_DIB_BuildColorMap( usage == DIB_PAL_COLORS? physDev : NULL,
4747                                            usage, bm.bmBitsPixel, bmi, &nColorMap );
4748       colorTable = X11DRV_DIB_BuildColorTable( physDev, usage, bm.bmBitsPixel, bmi );
4749   }
4750   /* Allocate Memory for DIB and fill structure */
4751   if (bm.bmBits)
4752     dib = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(X11DRV_DIBSECTION));
4753   if (dib)
4754     {
4755       dib->dibSection.dsBm = bm;
4756
4757       if (core_header)
4758       {
4759           /* Convert the BITMAPCOREHEADER to a BITMAPINFOHEADER.
4760              The structure is already filled with zeros */
4761           dib->dibSection.dsBmih.biSize = sizeof(BITMAPINFOHEADER);
4762           dib->dibSection.dsBmih.biWidth = width;
4763           dib->dibSection.dsBmih.biHeight = height;
4764           dib->dibSection.dsBmih.biPlanes = planes;
4765           dib->dibSection.dsBmih.biBitCount = bpp;
4766           dib->dibSection.dsBmih.biCompression = compression;
4767       }
4768       else
4769       {
4770           /* Truncate extended bitmap headers (BITMAPV4HEADER etc.) */
4771           dib->dibSection.dsBmih = *((BITMAPINFOHEADER*) bmi);
4772           dib->dibSection.dsBmih.biSize = sizeof(BITMAPINFOHEADER);
4773       }
4774
4775       dib->dibSection.dsBmih.biSizeImage = totalSize;
4776       colorPtr = (LPBYTE) bmi + (WORD) bmi->bmiHeader.biSize;
4777
4778       /* Set dsBitfields values */
4779        if ( usage == DIB_PAL_COLORS || bpp <= 8)
4780        {
4781            dib->dibSection.dsBitfields[0] = dib->dibSection.dsBitfields[1] = dib->dibSection.dsBitfields[2] = 0;
4782        }
4783        else switch( bpp )
4784        {
4785            case 15:
4786            case 16:
4787                dib->dibSection.dsBitfields[0] = (compression == BI_BITFIELDS) ? *((const DWORD *)colorPtr    ) : 0x7c00;
4788                dib->dibSection.dsBitfields[1] = (compression == BI_BITFIELDS) ? *((const DWORD *)colorPtr + 1) : 0x03e0;
4789                dib->dibSection.dsBitfields[2] = (compression == BI_BITFIELDS) ? *((const DWORD *)colorPtr + 2) : 0x001f;
4790                break;
4791
4792            case 24:
4793            case 32:
4794                dib->dibSection.dsBitfields[0] = (compression == BI_BITFIELDS) ? *((const DWORD *)colorPtr    ) : 0xff0000;
4795                dib->dibSection.dsBitfields[1] = (compression == BI_BITFIELDS) ? *((const DWORD *)colorPtr + 1) : 0x00ff00;
4796                dib->dibSection.dsBitfields[2] = (compression == BI_BITFIELDS) ? *((const DWORD *)colorPtr + 2) : 0x0000ff;
4797                break;
4798        }
4799       dib->dibSection.dshSection = section;
4800       dib->dibSection.dsOffset = offset;
4801
4802       dib->status    = DIB_Status_None;
4803       dib->nColorMap = nColorMap;
4804       dib->colorMap  = colorMap;
4805       dib->colorTable = colorTable;
4806     }
4807
4808   /* Create Device Dependent Bitmap and add DIB pointer */
4809   if (dib)
4810     {
4811       int depth = (bpp == 1) ? 1 : GetDeviceCaps(physDev->hdc, BITSPIXEL);
4812       res = CreateBitmap(width, effHeight, 1, depth, NULL);
4813
4814       if (res)
4815         {
4816           bmp = (BITMAPOBJ *) GDI_GetObjPtr(res, BITMAP_MAGIC);
4817           if (bmp) bmp->dib = (DIBSECTION *) dib;
4818         }
4819     }
4820
4821   /* Create XImage */
4822   if (dib && bmp)
4823   {
4824       wine_tsx11_lock();
4825 #ifdef HAVE_LIBXXSHM
4826       if (XShmQueryExtension(gdi_display) &&
4827           (dib->image = X11DRV_XShmCreateImage( bm.bmWidth, effHeight,
4828                                                 bmp->bitmap.bmBitsPixel, &dib->shminfo )) )
4829       {
4830         ; /* Created Image */
4831       } else {
4832           dib->image = X11DRV_DIB_CreateXImage( bm.bmWidth, effHeight, bmp->bitmap.bmBitsPixel );
4833           dib->shminfo.shmid = -1;
4834       }
4835 #else
4836       dib->image = X11DRV_DIB_CreateXImage( bm.bmWidth, effHeight, bmp->bitmap.bmBitsPixel );
4837 #endif
4838       wine_tsx11_unlock();
4839   }
4840
4841   /* Clean up in case of errors */
4842   if (!res || !bmp || !dib || !bm.bmBits || (bm.bmBitsPixel <= 8 && !colorMap))
4843     {
4844       TRACE("got an error res=%p, bmp=%p, dib=%p, bm.bmBits=%p\n",
4845             res, bmp, dib, bm.bmBits);
4846       if (bm.bmBits)
4847         {
4848           if (section)
4849             UnmapViewOfFile(mapBits), bm.bmBits = NULL;
4850           else if (!offset)
4851             VirtualFree(bm.bmBits, 0L, MEM_RELEASE), bm.bmBits = NULL;
4852         }
4853
4854       if (dib && dib->image) { XDestroyImage(dib->image); dib->image = NULL; }
4855       HeapFree(GetProcessHeap(), 0, colorMap); colorMap = NULL;
4856       HeapFree(GetProcessHeap(), 0, colorTable); colorTable = NULL;
4857       HeapFree(GetProcessHeap(), 0, dib); dib = NULL;
4858       if (bmp) { GDI_ReleaseObj(res); bmp = NULL; }
4859       if (res) { DeleteObject(res); res = 0; }
4860     }
4861   else if (bm.bmBits)
4862     {
4863       extern BOOL VIRTUAL_SetFaultHandler(LPCVOID addr, BOOL (*proc)(LPVOID, LPCVOID), LPVOID arg);
4864       /* Install fault handler, if possible */
4865       InitializeCriticalSection(&(dib->lock));
4866       if (VIRTUAL_SetFaultHandler(bm.bmBits, X11DRV_DIB_FaultHandler, (LPVOID)res))
4867         {
4868           X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
4869           if (dib) dib->status = DIB_Status_AppMod;
4870         }
4871     }
4872
4873   /* Return BITMAP handle and storage location */
4874   if (bmp) GDI_ReleaseObj(res);
4875   if (bm.bmBits && bits) *bits = bm.bmBits;
4876   return res;
4877 }
4878
4879 /***********************************************************************
4880  *           X11DRV_DIB_DeleteDIBSection
4881  */
4882 void X11DRV_DIB_DeleteDIBSection(BITMAPOBJ *bmp)
4883 {
4884   X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
4885
4886   if (dib->dibSection.dshSection)
4887       X11DRV_DIB_Coerce(bmp, DIB_Status_InSync, FALSE);
4888
4889   if (dib->image)
4890   {
4891       wine_tsx11_lock();
4892 #ifdef HAVE_LIBXXSHM
4893       if (dib->shminfo.shmid != -1)
4894       {
4895           XShmDetach (gdi_display, &(dib->shminfo));
4896           XDestroyImage (dib->image);
4897           shmdt (dib->shminfo.shmaddr);
4898           dib->shminfo.shmid = -1;
4899       }
4900       else
4901 #endif
4902           XDestroyImage( dib->image );
4903       wine_tsx11_unlock();
4904   }
4905
4906   HeapFree(GetProcessHeap(), 0, dib->colorMap);
4907   HeapFree(GetProcessHeap(), 0, dib->colorTable);
4908
4909   DeleteCriticalSection(&(dib->lock));
4910 }
4911
4912 /***********************************************************************
4913  *           SetDIBColorTable   (X11DRV.@)
4914  */
4915 UINT X11DRV_SetDIBColorTable( X11DRV_PDEVICE *physDev, UINT start, UINT count, const RGBQUAD *colors )
4916 {
4917     BITMAPOBJ * bmp;
4918     X11DRV_DIBSECTION *dib;
4919     UINT ret = 0;
4920     HBITMAP hBitmap = GetCurrentObject( physDev->hdc, OBJ_BITMAP );
4921
4922     if (!(bmp = (BITMAPOBJ*)GDI_GetObjPtr( hBitmap, BITMAP_MAGIC ))) return 0;
4923     dib = (X11DRV_DIBSECTION *) bmp->dib;
4924
4925     if (dib && dib->colorMap && start < dib->nColorMap) {
4926         UINT end = count + start;
4927         if (end > dib->nColorMap) end = dib->nColorMap;
4928         /*
4929          * Changing color table might change the mapping between
4930          * DIB colors and X11 colors and thus alter the visible state
4931          * of the bitmap object.
4932          */
4933         X11DRV_DIB_Lock(bmp, DIB_Status_AppMod, FALSE);
4934         memcpy(dib->colorTable + start, colors, (end - start) * sizeof(RGBQUAD));
4935         X11DRV_DIB_GenColorMap( physDev, dib->colorMap, DIB_RGB_COLORS,
4936                                 dib->dibSection.dsBm.bmBitsPixel,
4937                                 TRUE, colors, start, end );
4938         X11DRV_DIB_Unlock(bmp, TRUE);
4939         ret = end - start;
4940     }
4941     GDI_ReleaseObj( hBitmap );
4942     return ret;
4943 }
4944
4945 /***********************************************************************
4946  *           GetDIBColorTable   (X11DRV.@)
4947  */
4948 UINT X11DRV_GetDIBColorTable( X11DRV_PDEVICE *physDev, UINT start, UINT count, RGBQUAD *colors )
4949 {
4950     BITMAPOBJ * bmp;
4951     X11DRV_DIBSECTION *dib;
4952     UINT ret = 0;
4953     HBITMAP hBitmap = GetCurrentObject( physDev->hdc, OBJ_BITMAP );
4954
4955     if (!(bmp = (BITMAPOBJ*)GDI_GetObjPtr( hBitmap, BITMAP_MAGIC ))) return 0;
4956     dib = (X11DRV_DIBSECTION *) bmp->dib;
4957
4958     if (dib && dib->colorTable && start < dib->nColorMap) {
4959         if (start + count > dib->nColorMap) count = dib->nColorMap - start;
4960         memcpy(colors, dib->colorTable + start, count * sizeof(RGBQUAD));
4961         ret = count;
4962     }
4963     GDI_ReleaseObj( hBitmap );
4964     return ret;
4965 }
4966
4967
4968
4969 /***********************************************************************
4970  *           X11DRV_DIB_CreateDIBFromBitmap
4971  *
4972  *  Allocates a packed DIB and copies the bitmap data into it.
4973  */
4974 HGLOBAL X11DRV_DIB_CreateDIBFromBitmap(HDC hdc, HBITMAP hBmp)
4975 {
4976     BITMAP bmp;
4977     HGLOBAL hPackedDIB;
4978     LPBYTE pPackedDIB;
4979     LPBITMAPINFOHEADER pbmiHeader;
4980     unsigned int cDataSize, cPackedSize, OffsetBits;
4981     int nLinesCopied;
4982
4983     if (!GetObjectW( hBmp, sizeof(bmp), &bmp )) return 0;
4984
4985     /*
4986      * A packed DIB contains a BITMAPINFO structure followed immediately by
4987      * an optional color palette and the pixel data.
4988      */
4989
4990     /* Calculate the size of the packed DIB */
4991     cDataSize = X11DRV_DIB_GetDIBWidthBytes( bmp.bmWidth, bmp.bmBitsPixel ) * abs( bmp.bmHeight );
4992     cPackedSize = sizeof(BITMAPINFOHEADER)
4993                   + ( (bmp.bmBitsPixel <= 8) ? (sizeof(RGBQUAD) * (1 << bmp.bmBitsPixel)) : 0 )
4994                   + cDataSize;
4995     /* Get the offset to the bits */
4996     OffsetBits = cPackedSize - cDataSize;
4997
4998     /* Allocate the packed DIB */
4999     TRACE("\tAllocating packed DIB of size %d\n", cPackedSize);
5000     hPackedDIB = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE /*| GMEM_ZEROINIT*/,
5001                              cPackedSize );
5002     if ( !hPackedDIB )
5003     {
5004         WARN("Could not allocate packed DIB!\n");
5005         return 0;
5006     }
5007
5008     /* A packed DIB starts with a BITMAPINFOHEADER */
5009     pPackedDIB = GlobalLock(hPackedDIB);
5010     pbmiHeader = (LPBITMAPINFOHEADER)pPackedDIB;
5011
5012     /* Init the BITMAPINFOHEADER */
5013     pbmiHeader->biSize = sizeof(BITMAPINFOHEADER);
5014     pbmiHeader->biWidth = bmp.bmWidth;
5015     pbmiHeader->biHeight = bmp.bmHeight;
5016     pbmiHeader->biPlanes = 1;
5017     pbmiHeader->biBitCount = bmp.bmBitsPixel;
5018     pbmiHeader->biCompression = BI_RGB;
5019     pbmiHeader->biSizeImage = 0;
5020     pbmiHeader->biXPelsPerMeter = pbmiHeader->biYPelsPerMeter = 0;
5021     pbmiHeader->biClrUsed = 0;
5022     pbmiHeader->biClrImportant = 0;
5023
5024     /* Retrieve the DIB bits from the bitmap and fill in the
5025      * DIB color table if present */
5026
5027     nLinesCopied = GetDIBits(hdc,                       /* Handle to device context */
5028                              hBmp,                      /* Handle to bitmap */
5029                              0,                         /* First scan line to set in dest bitmap */
5030                              bmp.bmHeight,              /* Number of scan lines to copy */
5031                              pPackedDIB + OffsetBits,   /* [out] Address of array for bitmap bits */
5032                              (LPBITMAPINFO) pbmiHeader, /* [out] Address of BITMAPINFO structure */
5033                              0);                        /* RGB or palette index */
5034     GlobalUnlock(hPackedDIB);
5035
5036     /* Cleanup if GetDIBits failed */
5037     if (nLinesCopied != bmp.bmHeight)
5038     {
5039         TRACE("\tGetDIBits returned %d. Actual lines=%d\n", nLinesCopied, bmp.bmHeight);
5040         GlobalFree(hPackedDIB);
5041         hPackedDIB = 0;
5042     }
5043     return hPackedDIB;
5044 }
5045
5046
5047 /**************************************************************************
5048  *              X11DRV_DIB_CreateDIBFromPixmap
5049  *
5050  *  Allocates a packed DIB and copies the Pixmap data into it.
5051  *  If bDeletePixmap is TRUE, the Pixmap passed in is deleted after the conversion.
5052  */
5053 HGLOBAL X11DRV_DIB_CreateDIBFromPixmap(Pixmap pixmap, HDC hdc, BOOL bDeletePixmap)
5054 {
5055     HBITMAP hBmp = 0;
5056     BITMAPOBJ *pBmp = NULL;
5057     HGLOBAL hPackedDIB = 0;
5058
5059     /* Allocates an HBITMAP which references the Pixmap passed to us */
5060     hBmp = X11DRV_BITMAP_CreateBitmapHeaderFromPixmap(hdc, pixmap);
5061     if (!hBmp)
5062     {
5063         TRACE("\tCould not create bitmap header for Pixmap\n");
5064         goto END;
5065     }
5066
5067     /*
5068      * Create a packed DIB from the Pixmap wrapper bitmap created above.
5069      * A packed DIB contains a BITMAPINFO structure followed immediately by
5070      * an optional color palette and the pixel data.
5071      */
5072     hPackedDIB = X11DRV_DIB_CreateDIBFromBitmap(hdc, hBmp);
5073
5074     /* Get a pointer to the BITMAPOBJ structure */
5075     pBmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
5076
5077     /* We can now get rid of the HBITMAP wrapper we created earlier.
5078      * Note: Simply calling DeleteObject will free the embedded Pixmap as well.
5079      */
5080     if (!bDeletePixmap)
5081     {
5082         /* Clear the physBitmap to prevent the Pixmap from being deleted by DeleteObject */
5083         pBmp->physBitmap = NULL;
5084         pBmp->funcs = NULL;
5085     }
5086     GDI_ReleaseObj( hBmp );
5087     DeleteObject(hBmp);
5088
5089 END:
5090     TRACE("\tReturning packed DIB %p\n", hPackedDIB);
5091     return hPackedDIB;
5092 }
5093
5094
5095 /**************************************************************************
5096  *                 X11DRV_DIB_CreatePixmapFromDIB
5097  *
5098  *    Creates a Pixmap from a packed DIB
5099  */
5100 Pixmap X11DRV_DIB_CreatePixmapFromDIB( HGLOBAL hPackedDIB, HDC hdc )
5101 {
5102     Pixmap pixmap = None;
5103     HBITMAP hBmp = 0;
5104     BITMAPOBJ *pBmp = NULL;
5105     LPBYTE pPackedDIB = NULL;
5106     LPBITMAPINFO pbmi = NULL;
5107     LPBITMAPINFOHEADER pbmiHeader = NULL;
5108     LPBYTE pbits = NULL;
5109
5110     /* Get a pointer to the packed DIB's data  */
5111     pPackedDIB = (LPBYTE)GlobalLock(hPackedDIB);
5112     pbmiHeader = (LPBITMAPINFOHEADER)pPackedDIB;
5113     pbmi = (LPBITMAPINFO)pPackedDIB;
5114     pbits = (LPBYTE)(pPackedDIB
5115                      + X11DRV_DIB_BitmapInfoSize( (LPBITMAPINFO)pbmiHeader, DIB_RGB_COLORS ));
5116
5117     /* Create a DDB from the DIB */
5118
5119     hBmp = CreateDIBitmap(hdc,
5120                           pbmiHeader,
5121                           CBM_INIT,
5122                           (LPVOID)pbits,
5123                           pbmi,
5124                           DIB_RGB_COLORS);
5125
5126     GlobalUnlock(hPackedDIB);
5127
5128     TRACE("CreateDIBitmap returned %p\n", hBmp);
5129
5130     /* Retrieve the internal Pixmap from the DDB */
5131
5132     pBmp = (BITMAPOBJ *) GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
5133
5134     pixmap = (Pixmap)pBmp->physBitmap;
5135     /* clear the physBitmap so that we can steal its pixmap */
5136     pBmp->physBitmap = NULL;
5137     pBmp->funcs = NULL;
5138
5139     /* Delete the DDB we created earlier now that we have stolen its pixmap */
5140     GDI_ReleaseObj( hBmp );
5141     DeleteObject(hBmp);
5142
5143     TRACE("\tReturning Pixmap %ld\n", pixmap);
5144     return pixmap;
5145 }