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