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