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