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