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