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