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