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