gcc 4.0 warning fixes.
[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 static 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 << ((const 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   = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtRed;
422                colorTable[i].rgbGreen = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtGreen;
423                colorTable[i].rgbBlue  = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtBlue;
424                colorTable[i].rgbReserved = 0;
425            }
426         }
427         else
428         {
429             memcpy(colorTable, (const BYTE*) 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         const WORD *index = (const WORD*) ((const BYTE*) 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 static 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=(BYTE*)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=(BYTE*)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=(BYTE*)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
3765     if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height,
3766                            &descr.infoBpp, &descr.compression ) == -1)
3767         return 0;
3768
3769     top_down = (height < 0);
3770     if (top_down) height = -height;
3771
3772     pt.x = xDest;
3773     pt.y = yDest;
3774     LPtoDP(physDev->hdc, &pt, 1);
3775
3776     if (!lines || (startscan >= height)) return 0;
3777     if (!top_down && startscan + lines > height) lines = height - startscan;
3778
3779     /* make xSrc,ySrc point to the upper-left corner, not the lower-left one,
3780      * and clamp all values to fit inside [startscan,startscan+lines]
3781      */
3782     if (ySrc + cy <= startscan + lines)
3783     {
3784         UINT y = startscan + lines - (ySrc + cy);
3785         if (ySrc < startscan) cy -= (startscan - ySrc);
3786         if (!top_down)
3787         {
3788             /* avoid getting unnecessary lines */
3789             ySrc = 0;
3790             if (y >= lines) return 0;
3791             lines -= y;
3792         }
3793         else
3794         {
3795             if (y >= lines) return lines;
3796             ySrc = y;  /* need to get all lines in top down mode */
3797         }
3798     }
3799     else
3800     {
3801         if (ySrc >= startscan + lines) return lines;
3802         pt.y += ySrc + cy - (startscan + lines);
3803         cy = startscan + lines - ySrc;
3804         ySrc = 0;
3805         if (cy > lines) cy = lines;
3806     }
3807     if (xSrc >= width) return lines;
3808     if (xSrc + cx >= width) cx = width - xSrc;
3809     if (!cx || !cy) return lines;
3810
3811     /* Update the pixmap from the DIB section */
3812     X11DRV_LockDIBSection(physDev, DIB_Status_GdiMod, FALSE);
3813
3814     X11DRV_SetupGCForText( physDev );  /* To have the correct colors */
3815     wine_tsx11_lock();
3816     XSetFunction(gdi_display, physDev->gc, X11DRV_XROPfunction[GetROP2(physDev->hdc) - 1]);
3817     wine_tsx11_unlock();
3818
3819     switch (descr.infoBpp)
3820     {
3821        case 1:
3822        case 4:
3823        case 8:
3824                descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap(
3825                                             coloruse == DIB_PAL_COLORS ? physDev : NULL, coloruse,
3826                                             physDev->depth, info, &descr.nColorMap );
3827                if (!descr.colorMap) return 0;
3828                descr.rMask = descr.gMask = descr.bMask = 0;
3829                break;
3830        case 15:
3831        case 16:
3832                descr.rMask = (descr.compression == BI_BITFIELDS) ? *(const DWORD *)info->bmiColors       : 0x7c00;
3833                descr.gMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)info->bmiColors + 1) : 0x03e0;
3834                descr.bMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)info->bmiColors + 2) : 0x001f;
3835                descr.colorMap = 0;
3836                break;
3837
3838        case 24:
3839        case 32:
3840                descr.rMask = (descr.compression == BI_BITFIELDS) ? *(const DWORD *)info->bmiColors       : 0xff0000;
3841                descr.gMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)info->bmiColors + 1) : 0x00ff00;
3842                descr.bMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)info->bmiColors + 2) : 0x0000ff;
3843                descr.colorMap = 0;
3844                break;
3845     }
3846
3847     descr.physDev   = physDev;
3848     descr.bits      = bits;
3849     descr.image     = NULL;
3850     descr.palentry  = NULL;
3851     descr.lines     = top_down ? -lines : lines;
3852     descr.infoWidth = width;
3853     descr.depth     = physDev->depth;
3854     descr.drawable  = physDev->drawable;
3855     descr.gc        = physDev->gc;
3856     descr.xSrc      = xSrc;
3857     descr.ySrc      = ySrc;
3858     descr.xDest     = physDev->org.x + pt.x;
3859     descr.yDest     = physDev->org.y + pt.y;
3860     descr.width     = cx;
3861     descr.height    = cy;
3862     descr.useShm    = FALSE;
3863     descr.dibpitch  = ((width * descr.infoBpp + 31) &~31) / 8;
3864
3865     result = X11DRV_DIB_SetImageBits( &descr );
3866
3867     if (descr.infoBpp <= 8)
3868        HeapFree(GetProcessHeap(), 0, descr.colorMap);
3869
3870     /* Update the DIBSection of the pixmap */
3871     X11DRV_UnlockDIBSection(physDev, TRUE);
3872
3873     return result;
3874 }
3875
3876 /***********************************************************************
3877  *           SetDIBits   (X11DRV.@)
3878  */
3879 INT X11DRV_SetDIBits( X11DRV_PDEVICE *physDev, HBITMAP hbitmap, UINT startscan,
3880                       UINT lines, LPCVOID bits, const BITMAPINFO *info, UINT coloruse )
3881 {
3882   X_PHYSBITMAP *physBitmap = X11DRV_get_phys_bitmap( hbitmap );
3883   X11DRV_DIB_IMAGEBITS_DESCR descr;
3884   BITMAP bitmap;
3885   LONG height, tmpheight;
3886   INT result;
3887
3888   descr.physDev = physDev;
3889
3890   if (!physBitmap) return 0;
3891
3892   if (DIB_GetBitmapInfo( &info->bmiHeader, &descr.infoWidth, &height,
3893                          &descr.infoBpp, &descr.compression ) == -1)
3894       return 0;
3895
3896   tmpheight = height;
3897   if (height < 0) height = -height;
3898   if (!lines || (startscan >= height))
3899       return 0;
3900
3901   if (!GetObjectW( hbitmap, sizeof(bitmap), &bitmap )) return 0;
3902
3903   if (startscan + lines > height) lines = height - startscan;
3904
3905   switch (descr.infoBpp)
3906   {
3907        case 1:
3908        case 4:
3909        case 8:
3910                descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap(
3911                         coloruse == DIB_PAL_COLORS ? descr.physDev : NULL, coloruse,
3912                                                           physBitmap->pixmap_depth,
3913                                                           info, &descr.nColorMap );
3914                if (!descr.colorMap) return 0;
3915                descr.rMask = descr.gMask = descr.bMask = 0;
3916                break;
3917        case 15:
3918        case 16:
3919                descr.rMask = (descr.compression == BI_BITFIELDS) ? *(const DWORD *)info->bmiColors       : 0x7c00;
3920                descr.gMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)info->bmiColors + 1) : 0x03e0;
3921                descr.bMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)info->bmiColors + 2) : 0x001f;
3922                descr.colorMap = 0;
3923                break;
3924
3925        case 24:
3926        case 32:
3927                descr.rMask = (descr.compression == BI_BITFIELDS) ? *(const DWORD *)info->bmiColors       : 0xff0000;
3928                descr.gMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)info->bmiColors + 1) : 0x00ff00;
3929                descr.bMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)info->bmiColors + 2) : 0x0000ff;
3930                descr.colorMap = 0;
3931                break;
3932
3933        default: break;
3934   }
3935
3936   descr.bits      = bits;
3937   descr.image     = NULL;
3938   descr.palentry  = NULL;
3939   descr.lines     = tmpheight >= 0 ? lines : -lines;
3940   descr.depth     = physBitmap->pixmap_depth;
3941   descr.drawable  = physBitmap->pixmap;
3942   descr.gc        = BITMAP_GC(physBitmap);
3943   descr.xSrc      = 0;
3944   descr.ySrc      = 0;
3945   descr.xDest     = 0;
3946   descr.yDest     = height - startscan - lines;
3947   descr.width     = bitmap.bmWidth;
3948   descr.height    = lines;
3949   descr.useShm    = FALSE;
3950   descr.dibpitch  = ((descr.infoWidth * descr.infoBpp + 31) &~31) / 8;
3951   X11DRV_DIB_Lock( physBitmap, DIB_Status_GdiMod, FALSE );
3952   result = X11DRV_DIB_SetImageBits( &descr );
3953   X11DRV_DIB_Unlock( physBitmap, TRUE );
3954
3955   HeapFree(GetProcessHeap(), 0, descr.colorMap);
3956
3957   return result;
3958 }
3959
3960 /***********************************************************************
3961  *           GetDIBits   (X11DRV.@)
3962  */
3963 INT X11DRV_GetDIBits( X11DRV_PDEVICE *physDev, HBITMAP hbitmap, UINT startscan, UINT lines,
3964                       LPVOID bits, BITMAPINFO *info, UINT coloruse )
3965 {
3966   X_PHYSBITMAP *physBitmap = X11DRV_get_phys_bitmap( hbitmap );
3967   DIBSECTION dib;
3968   X11DRV_DIB_IMAGEBITS_DESCR descr;
3969   PALETTEENTRY palette[256];
3970   size_t obj_size;
3971   int height;
3972   LONG tempHeight;
3973   int bitmap_type;
3974   BOOL core_header;
3975   void* colorPtr;
3976
3977   GetPaletteEntries( GetCurrentObject( physDev->hdc, OBJ_PAL ), 0, 256, palette );
3978
3979   if (!physBitmap) return 0;
3980   if (!(obj_size = GetObjectW( hbitmap, sizeof(dib), &dib ))) return 0;
3981
3982   bitmap_type = DIB_GetBitmapInfo( (BITMAPINFOHEADER*) info, &descr.infoWidth, &tempHeight, &descr.infoBpp, &descr.compression);
3983   descr.lines = tempHeight;
3984   if (bitmap_type == -1)
3985   {
3986       ERR("Invalid bitmap\n");
3987       return 0;
3988   }
3989   core_header = (bitmap_type == 0);
3990   colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
3991
3992   TRACE("%u scanlines of (%i,%i) -> (%i,%i) starting from %u\n",
3993         lines, dib.dsBm.bmWidth, dib.dsBm.bmHeight, (int)descr.infoWidth, descr.lines, startscan);
3994
3995   if( lines > dib.dsBm.bmHeight ) lines = dib.dsBm.bmHeight;
3996
3997   height = descr.lines;
3998   if (height < 0) height = -height;
3999   if( lines > height ) lines = height;
4000   /* Top-down images have a negative biHeight, the scanlines of theses images
4001    * were inverted in X11DRV_DIB_GetImageBits_xx
4002    * To prevent this we simply change the sign of lines
4003    * (the number of scan lines to copy).
4004    * Negative lines are correctly handled by X11DRV_DIB_GetImageBits_xx.
4005    */
4006   if( descr.lines < 0 && lines > 0) lines = -lines;
4007
4008   if( startscan >= dib.dsBm.bmHeight ) return 0;
4009
4010   descr.colorMap = NULL;
4011
4012   switch (descr.infoBpp)
4013   {
4014       case 1:
4015       case 4:
4016       case 8:
4017           descr.rMask= descr.gMask = descr.bMask = 0;
4018           if(coloruse == DIB_RGB_COLORS)
4019               descr.colorMap = colorPtr;
4020           else {
4021               int num_colors = 1 << descr.infoBpp, i;
4022               RGBQUAD *rgb;
4023               COLORREF colref;
4024               WORD *index = (WORD*)colorPtr;
4025               descr.colorMap = rgb = HeapAlloc(GetProcessHeap(), 0, num_colors * sizeof(RGBQUAD));
4026               for(i = 0; i < num_colors; i++, rgb++, index++) {
4027                   colref = X11DRV_PALETTE_ToLogical(X11DRV_PALETTE_ToPhysical(physDev, PALETTEINDEX(*index)));
4028                   rgb->rgbRed = GetRValue(colref);
4029                   rgb->rgbGreen = GetGValue(colref);
4030                   rgb->rgbBlue = GetBValue(colref);
4031                   rgb->rgbReserved = 0;
4032               }
4033           }
4034           break;
4035       case 15:
4036       case 16:
4037           descr.rMask = (descr.compression == BI_BITFIELDS) ? *(const DWORD *)info->bmiColors       : 0x7c00;
4038           descr.gMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)info->bmiColors + 1) : 0x03e0;
4039           descr.bMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)info->bmiColors + 2) : 0x001f;
4040           break;
4041       case 24:
4042       case 32:
4043           descr.rMask = (descr.compression == BI_BITFIELDS) ? *(const DWORD *)info->bmiColors       : 0xff0000;
4044           descr.gMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)info->bmiColors + 1) : 0x00ff00;
4045           descr.bMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)info->bmiColors + 2) : 0x0000ff;
4046           break;
4047   }
4048
4049   descr.physDev   = physDev;
4050   descr.palentry  = palette;
4051   descr.bits      = bits;
4052   descr.image     = NULL;
4053   descr.lines     = lines;
4054   descr.depth     = physBitmap->pixmap_depth;
4055   descr.drawable  = physBitmap->pixmap;
4056   descr.gc        = BITMAP_GC(physBitmap);
4057   descr.width     = dib.dsBm.bmWidth;
4058   descr.height    = dib.dsBm.bmHeight;
4059   descr.xDest     = 0;
4060   descr.yDest     = 0;
4061   descr.xSrc      = 0;
4062   descr.sizeImage = core_header ? 0 : info->bmiHeader.biSizeImage;
4063
4064   if (descr.lines > 0)
4065   {
4066      descr.ySrc = (descr.height-1) - (startscan + (lines-1));
4067   }
4068   else
4069   {
4070      descr.ySrc = startscan;
4071   }
4072 #ifdef HAVE_LIBXXSHM
4073   descr.useShm = (obj_size == sizeof(DIBSECTION)) && (physBitmap->shminfo.shmid != -1);
4074 #else
4075   descr.useShm = FALSE;
4076 #endif
4077   descr.dibpitch = (obj_size == sizeof(DIBSECTION)) ? dib.dsBm.bmWidthBytes
4078                        : (((descr.infoWidth * descr.infoBpp + 31) &~31) / 8);
4079
4080   X11DRV_DIB_Lock( physBitmap, DIB_Status_GdiMod, FALSE );
4081   X11DRV_DIB_GetImageBits( &descr );
4082   X11DRV_DIB_Unlock( physBitmap, TRUE );
4083
4084   if(!core_header && info->bmiHeader.biSizeImage == 0) /* Fill in biSizeImage */
4085       info->bmiHeader.biSizeImage = X11DRV_DIB_GetDIBImageBytes( descr.infoWidth,
4086                                                                  descr.lines,
4087                                                                  descr.infoBpp);
4088
4089   if (descr.compression == BI_BITFIELDS)
4090   {
4091     *(DWORD *)info->bmiColors       = descr.rMask;
4092     *((DWORD *)info->bmiColors + 1) = descr.gMask;
4093     *((DWORD *)info->bmiColors + 2) = descr.bMask;
4094   }
4095   else if (!core_header)
4096   {
4097     /* if RLE or JPEG compression were supported,
4098      * this line would be invalid. */
4099     info->bmiHeader.biCompression = 0;
4100   }
4101
4102   if(descr.colorMap && descr.colorMap != colorPtr)
4103       HeapFree(GetProcessHeap(), 0, descr.colorMap);
4104   return lines;
4105 }
4106
4107 /***********************************************************************
4108  *           DIB_DoProtectDIBSection
4109  */
4110 static void X11DRV_DIB_DoProtectDIBSection( X_PHYSBITMAP *physBitmap, DWORD new_prot )
4111 {
4112     DWORD old_prot;
4113
4114     VirtualProtect(physBitmap->base, physBitmap->size, new_prot, &old_prot);
4115     TRACE("Changed protection from %ld to %ld\n", old_prot, new_prot);
4116 }
4117
4118 /***********************************************************************
4119  *           X11DRV_DIB_DoCopyDIBSection
4120  */
4121 static void X11DRV_DIB_DoCopyDIBSection(X_PHYSBITMAP *physBitmap, BOOL toDIB,
4122                                         void *colorMap, int nColorMap,
4123                                         Drawable dest,
4124                                         DWORD xSrc, DWORD ySrc,
4125                                         DWORD xDest, DWORD yDest,
4126                                         DWORD width, DWORD height)
4127 {
4128   DIBSECTION dibSection;
4129   X11DRV_DIB_IMAGEBITS_DESCR descr;
4130   int identity[2] = {0,1};
4131
4132   if (!GetObjectW( physBitmap->hbitmap, sizeof(dibSection), &dibSection )) return;
4133
4134   descr.physDev   = NULL;
4135   descr.palentry  = NULL;
4136   descr.infoWidth = dibSection.dsBmih.biWidth;
4137   descr.infoBpp   = dibSection.dsBmih.biBitCount;
4138   descr.lines     = dibSection.dsBmih.biHeight;
4139   descr.image     = physBitmap->image;
4140   descr.colorMap  = colorMap;
4141   descr.nColorMap = nColorMap;
4142   descr.bits      = dibSection.dsBm.bmBits;
4143   descr.depth     = physBitmap->pixmap_depth;
4144   descr.compression = dibSection.dsBmih.biCompression;
4145
4146   if(descr.infoBpp == 1)
4147       descr.colorMap = (void*)identity;
4148
4149   switch (descr.infoBpp)
4150   {
4151     case 1:
4152     case 4:
4153     case 8:
4154       descr.rMask = descr.gMask = descr.bMask = 0;
4155       break;
4156     case 15:
4157     case 16:
4158       descr.rMask = (descr.compression == BI_BITFIELDS) ? dibSection.dsBitfields[0] : 0x7c00;
4159       descr.gMask = (descr.compression == BI_BITFIELDS) ? dibSection.dsBitfields[1] : 0x03e0;
4160       descr.bMask = (descr.compression == BI_BITFIELDS) ? dibSection.dsBitfields[2] : 0x001f;
4161       break;
4162
4163     case 24:
4164     case 32:
4165       descr.rMask = (descr.compression == BI_BITFIELDS) ? dibSection.dsBitfields[0] : 0xff0000;
4166       descr.gMask = (descr.compression == BI_BITFIELDS) ? dibSection.dsBitfields[1] : 0x00ff00;
4167       descr.bMask = (descr.compression == BI_BITFIELDS) ? dibSection.dsBitfields[2] : 0x0000ff;
4168       break;
4169   }
4170
4171   /* Hack for now */
4172   descr.drawable  = dest;
4173   descr.gc        = BITMAP_GC(physBitmap);
4174   descr.xSrc      = xSrc;
4175   descr.ySrc      = ySrc;
4176   descr.xDest     = xDest;
4177   descr.yDest     = yDest;
4178   descr.width     = width;
4179   descr.height    = height;
4180   descr.sizeImage = 0;
4181
4182 #ifdef HAVE_LIBXXSHM
4183   descr.useShm = (physBitmap->shminfo.shmid != -1);
4184 #else
4185   descr.useShm = FALSE;
4186 #endif
4187   descr.dibpitch = dibSection.dsBm.bmWidthBytes;
4188
4189   if (toDIB)
4190     {
4191       TRACE("Copying from Pixmap to DIB bits\n");
4192       X11DRV_DIB_GetImageBits( &descr );
4193     }
4194   else
4195     {
4196       TRACE("Copying from DIB bits to Pixmap\n");
4197       X11DRV_DIB_SetImageBits( &descr );
4198     }
4199 }
4200
4201 /***********************************************************************
4202  *           X11DRV_DIB_CopyDIBSection
4203  */
4204 void X11DRV_DIB_CopyDIBSection(X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE *physDevDst,
4205                                DWORD xSrc, DWORD ySrc, DWORD xDest, DWORD yDest,
4206                                DWORD width, DWORD height)
4207 {
4208   DIBSECTION dib;
4209   X_PHYSBITMAP *physBitmap;
4210   int nColorMap = 0, *colorMap = NULL, aColorMap = FALSE;
4211
4212   TRACE("(%p,%p,%ld,%ld,%ld,%ld,%ld,%ld)\n", physDevSrc->hdc, physDevDst->hdc,
4213     xSrc, ySrc, xDest, yDest, width, height);
4214   /* this function is meant as an optimization for BitBlt,
4215    * not to be called otherwise */
4216   physBitmap = physDevSrc->bitmap;
4217   if (!physBitmap || GetObjectW( physBitmap->hbitmap, sizeof(dib), &dib ) != sizeof(dib))
4218   {
4219     ERR("called for non-DIBSection!?\n");
4220     return;
4221   }
4222   /* while BitBlt should already have made sure we only get
4223    * positive values, we should check for oversize values */
4224   if ((xSrc < dib.dsBm.bmWidth) &&
4225       (ySrc < dib.dsBm.bmHeight)) {
4226     if (xSrc + width > dib.dsBm.bmWidth)
4227       width = dib.dsBm.bmWidth - xSrc;
4228     if (ySrc + height > dib.dsBm.bmHeight)
4229       height = dib.dsBm.bmHeight - ySrc;
4230     /* if the source bitmap is 8bpp or less, we're supposed to use the
4231      * DC's palette for color conversion (not the DIB color table) */
4232     if (dib.dsBm.bmBitsPixel <= 8) {
4233       HPALETTE hPalette = GetCurrentObject( physDevSrc->hdc, OBJ_PAL );
4234       if (!hPalette || (hPalette == GetStockObject(DEFAULT_PALETTE))) {
4235         /* HACK: no palette has been set in the source DC,
4236          * use the DIB colormap instead - this is necessary in some
4237          * cases since we need to do depth conversion in some places
4238          * where real Windows can just copy data straight over */
4239         colorMap = physBitmap->colorMap;
4240         nColorMap = physBitmap->nColorMap;
4241       } else {
4242         colorMap = X11DRV_DIB_BuildColorMap( physDevSrc, (WORD)-1,
4243                                              dib.dsBm.bmBitsPixel,
4244                                              (BITMAPINFO*)&dib.dsBmih,
4245                                              &nColorMap );
4246         if (colorMap) aColorMap = TRUE;
4247       }
4248     }
4249     /* perform the copy */
4250     X11DRV_DIB_DoCopyDIBSection(physBitmap, FALSE, colorMap, nColorMap,
4251                                 physDevDst->drawable, xSrc, ySrc,
4252                                 physDevDst->org.x + xDest, physDevDst->org.y + yDest,
4253                                 width, height);
4254     /* free color mapping */
4255     if (aColorMap)
4256       HeapFree(GetProcessHeap(), 0, colorMap);
4257   }
4258 }
4259
4260 /***********************************************************************
4261  *           X11DRV_DIB_DoUpdateDIBSection
4262  */
4263 static void X11DRV_DIB_DoUpdateDIBSection(X_PHYSBITMAP *physBitmap, BOOL toDIB)
4264 {
4265     BITMAP bitmap;
4266
4267     GetObjectW( physBitmap->hbitmap, sizeof(bitmap), &bitmap );
4268     X11DRV_DIB_DoCopyDIBSection(physBitmap, toDIB,
4269                                 physBitmap->colorMap, physBitmap->nColorMap,
4270                                 physBitmap->pixmap, 0, 0, 0, 0,
4271                                 bitmap.bmWidth, bitmap.bmHeight);
4272 }
4273
4274 /***********************************************************************
4275  *           X11DRV_DIB_FaultHandler
4276  */
4277 static LONG CALLBACK X11DRV_DIB_FaultHandler( PEXCEPTION_POINTERS ep )
4278 {
4279     X_PHYSBITMAP *physBitmap = NULL;
4280     BOOL found = FALSE;
4281     BYTE *addr;
4282     struct list *ptr;
4283
4284     if (ep->ExceptionRecord->ExceptionCode != EXCEPTION_ACCESS_VIOLATION)
4285         return EXCEPTION_CONTINUE_SEARCH;
4286
4287     addr = (BYTE *)ep->ExceptionRecord->ExceptionInformation[1];
4288
4289     EnterCriticalSection(&dibs_cs);
4290     LIST_FOR_EACH( ptr, &dibs_list )
4291     {
4292         physBitmap = LIST_ENTRY( ptr, X_PHYSBITMAP, entry );
4293         if ((physBitmap->base <= addr) && (addr < physBitmap->base + physBitmap->size))
4294         {
4295             found = TRUE;
4296             break;
4297         }
4298     }
4299     LeaveCriticalSection(&dibs_cs);
4300
4301     if (!found) return EXCEPTION_CONTINUE_SEARCH;
4302
4303     X11DRV_DIB_Lock( physBitmap, DIB_Status_None, FALSE );
4304     if (ep->ExceptionRecord->ExceptionInformation[0]) {
4305         /* the app tried to write the DIB bits */
4306         X11DRV_DIB_Coerce( physBitmap, DIB_Status_AppMod, FALSE );
4307     } else {
4308         /* the app tried to read the DIB bits */
4309         X11DRV_DIB_Coerce( physBitmap, DIB_Status_InSync, FALSE );
4310     }
4311     X11DRV_DIB_Unlock( physBitmap, TRUE );
4312
4313     return EXCEPTION_CONTINUE_EXECUTION;
4314 }
4315
4316 /***********************************************************************
4317  *           X11DRV_DIB_Coerce
4318  */
4319 static INT X11DRV_DIB_Coerce(X_PHYSBITMAP *physBitmap, INT req, BOOL lossy)
4320 {
4321     INT ret = DIB_Status_None;
4322
4323     if (!physBitmap->image) return ret;  /* not a DIB section */
4324     EnterCriticalSection(&physBitmap->lock);
4325     ret = physBitmap->status;
4326     switch (req) {
4327     case DIB_Status_GdiMod:
4328       /* GDI access - request to draw on pixmap */
4329       switch (physBitmap->status)
4330       {
4331         default:
4332         case DIB_Status_None:
4333           physBitmap->p_status = DIB_Status_GdiMod;
4334           X11DRV_DIB_DoUpdateDIBSection( physBitmap, FALSE );
4335           break;
4336
4337         case DIB_Status_GdiMod:
4338           TRACE("GdiMod requested in status GdiMod\n" );
4339           physBitmap->p_status = DIB_Status_GdiMod;
4340           break;
4341
4342         case DIB_Status_InSync:
4343           TRACE("GdiMod requested in status InSync\n" );
4344           X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_NOACCESS );
4345           physBitmap->status = DIB_Status_GdiMod;
4346           physBitmap->p_status = DIB_Status_InSync;
4347           break;
4348
4349         case DIB_Status_AppMod:
4350           TRACE("GdiMod requested in status AppMod\n" );
4351           if (!lossy) {
4352             /* make it readonly to avoid app changing data while we copy */
4353             X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_READONLY );
4354             X11DRV_DIB_DoUpdateDIBSection( physBitmap, FALSE );
4355           }
4356           X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_NOACCESS );
4357           physBitmap->p_status = DIB_Status_AppMod;
4358           physBitmap->status = DIB_Status_GdiMod;
4359           break;
4360       }
4361       break;
4362
4363     case DIB_Status_InSync:
4364       /* App access - request access to read DIB surface */
4365       /* (typically called from signal handler) */
4366       switch (physBitmap->status)
4367       {
4368         default:
4369         case DIB_Status_None:
4370           /* shouldn't happen from signal handler */
4371           break;
4372
4373         case DIB_Status_GdiMod:
4374           TRACE("InSync requested in status GdiMod\n" );
4375           if (!lossy) {
4376             X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_READWRITE );
4377             X11DRV_DIB_DoUpdateDIBSection( physBitmap, TRUE );
4378           }
4379           X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_READONLY );
4380           physBitmap->status = DIB_Status_InSync;
4381           break;
4382
4383         case DIB_Status_InSync:
4384           TRACE("InSync requested in status InSync\n" );
4385           /* shouldn't happen from signal handler */
4386           break;
4387
4388         case DIB_Status_AppMod:
4389           TRACE("InSync requested in status AppMod\n" );
4390           /* no reason to do anything here, and this
4391            * shouldn't happen from signal handler */
4392           break;
4393       }
4394       break;
4395
4396     case DIB_Status_AppMod:
4397       /* App access - request access to write DIB surface */
4398       /* (typically called from signal handler) */
4399       switch (physBitmap->status)
4400       {
4401         default:
4402         case DIB_Status_None:
4403           /* shouldn't happen from signal handler */
4404           break;
4405
4406         case DIB_Status_GdiMod:
4407           TRACE("AppMod requested in status GdiMod\n" );
4408           X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_READWRITE );
4409           if (!lossy) X11DRV_DIB_DoUpdateDIBSection( physBitmap, TRUE );
4410           physBitmap->status = DIB_Status_AppMod;
4411           break;
4412
4413         case DIB_Status_InSync:
4414           TRACE("AppMod requested in status InSync\n" );
4415           X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_READWRITE );
4416           physBitmap->status = DIB_Status_AppMod;
4417           break;
4418
4419         case DIB_Status_AppMod:
4420           TRACE("AppMod requested in status AppMod\n" );
4421           /* shouldn't happen from signal handler */
4422           break;
4423       }
4424       break;
4425
4426       /* it is up to the caller to do the copy/conversion, probably
4427        * using the return value to decide where to copy from */
4428     }
4429     LeaveCriticalSection(&physBitmap->lock);
4430     return ret;
4431 }
4432
4433 /***********************************************************************
4434  *           X11DRV_DIB_Lock
4435  */
4436 static INT X11DRV_DIB_Lock(X_PHYSBITMAP *physBitmap, INT req, BOOL lossy)
4437 {
4438     INT ret = DIB_Status_None;
4439
4440     if (!physBitmap->image) return ret;  /* not a DIB section */
4441     TRACE("Locking %p from thread %04lx\n", physBitmap->hbitmap, GetCurrentThreadId());
4442     EnterCriticalSection(&physBitmap->lock);
4443     ret = physBitmap->status;
4444     if (req != DIB_Status_None)
4445       X11DRV_DIB_Coerce(physBitmap, req, lossy);
4446     return ret;
4447 }
4448
4449 /***********************************************************************
4450  *           X11DRV_DIB_Unlock
4451  */
4452 static void X11DRV_DIB_Unlock(X_PHYSBITMAP *physBitmap, BOOL commit)
4453 {
4454     if (!physBitmap->image) return;  /* not a DIB section */
4455     switch (physBitmap->status)
4456     {
4457       default:
4458       case DIB_Status_None:
4459         /* in case anyone is wondering, this is the "signal handler doesn't
4460          * work" case, where we always have to be ready for app access */
4461         if (commit) {
4462           switch (physBitmap->p_status)
4463           {
4464             case DIB_Status_GdiMod:
4465               TRACE("Unlocking and syncing from GdiMod\n" );
4466               X11DRV_DIB_DoUpdateDIBSection( physBitmap, TRUE );
4467               break;
4468
4469             default:
4470               TRACE("Unlocking without needing to sync\n" );
4471               break;
4472           }
4473         }
4474         else TRACE("Unlocking with no changes\n");
4475         physBitmap->p_status = DIB_Status_None;
4476         break;
4477
4478       case DIB_Status_GdiMod:
4479         TRACE("Unlocking in status GdiMod\n" );
4480         /* DIB was protected in Coerce */
4481         if (!commit) {
4482           /* no commit, revert to InSync if applicable */
4483           if ((physBitmap->p_status == DIB_Status_InSync) ||
4484               (physBitmap->p_status == DIB_Status_AppMod)) {
4485             X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_READONLY );
4486             physBitmap->status = DIB_Status_InSync;
4487           }
4488         }
4489         break;
4490
4491       case DIB_Status_InSync:
4492         TRACE("Unlocking in status InSync\n" );
4493         /* DIB was already protected in Coerce */
4494         break;
4495
4496       case DIB_Status_AppMod:
4497         TRACE("Unlocking in status AppMod\n" );
4498         /* DIB was already protected in Coerce */
4499         /* this case is ordinary only called from the signal handler,
4500          * so we don't bother to check for !commit */
4501         break;
4502     }
4503     LeaveCriticalSection(&physBitmap->lock);
4504     TRACE("Unlocked %p\n", physBitmap->hbitmap);
4505 }
4506
4507 /***********************************************************************
4508  *           X11DRV_CoerceDIBSection
4509  */
4510 INT X11DRV_CoerceDIBSection(X11DRV_PDEVICE *physDev, INT req, BOOL lossy)
4511 {
4512     if (!physDev || !physDev->bitmap) return DIB_Status_None;
4513     return X11DRV_DIB_Coerce(physDev->bitmap, req, lossy);
4514 }
4515
4516 /***********************************************************************
4517  *           X11DRV_LockDIBSection
4518  */
4519 INT X11DRV_LockDIBSection(X11DRV_PDEVICE *physDev, INT req, BOOL lossy)
4520 {
4521     if (!physDev || !physDev->bitmap) return DIB_Status_None;
4522     return X11DRV_DIB_Lock(physDev->bitmap, req, lossy);
4523 }
4524
4525 /***********************************************************************
4526  *           X11DRV_UnlockDIBSection
4527  */
4528 void X11DRV_UnlockDIBSection(X11DRV_PDEVICE *physDev, BOOL commit)
4529 {
4530     if (!physDev || !physDev->bitmap) return;
4531     X11DRV_DIB_Unlock(physDev->bitmap, commit);
4532 }
4533
4534
4535 #ifdef HAVE_LIBXXSHM
4536 /***********************************************************************
4537  *           X11DRV_XShmErrorHandler
4538  *
4539  */
4540 static int XShmErrorHandler( Display *dpy, XErrorEvent *event, void *arg )
4541 {
4542     return 1;  /* FIXME: should check event contents */
4543 }
4544
4545 /***********************************************************************
4546  *           X11DRV_XShmCreateImage
4547  *
4548  */
4549 static XImage *X11DRV_XShmCreateImage( int width, int height, int bpp,
4550                                        XShmSegmentInfo* shminfo)
4551 {
4552     XImage *image;
4553
4554     image = XShmCreateImage(gdi_display, visual, bpp, ZPixmap, NULL, shminfo, width, height);
4555     if (image)
4556     {
4557         shminfo->shmid = shmget(IPC_PRIVATE, image->bytes_per_line * height,
4558                                   IPC_CREAT|0700);
4559         if( shminfo->shmid != -1 )
4560         {
4561             shminfo->shmaddr = image->data = shmat(shminfo->shmid, 0, 0);
4562             if( shminfo->shmaddr != (char*)-1 )
4563             {
4564                 BOOL ok;
4565
4566                 shminfo->readOnly = FALSE;
4567                 X11DRV_expect_error( gdi_display, XShmErrorHandler, NULL );
4568                 ok = (XShmAttach( gdi_display, shminfo ) != 0);
4569                 XSync( gdi_display, False );
4570                 if (X11DRV_check_error()) ok = FALSE;
4571                 if (ok)
4572                 {
4573                     shmctl(shminfo->shmid, IPC_RMID, 0);
4574                     return image; /* Success! */
4575                 }
4576                 /* An error occurred */
4577                 shmdt(shminfo->shmaddr);
4578             }
4579             shmctl(shminfo->shmid, IPC_RMID, 0);
4580             shminfo->shmid = -1;
4581         }
4582         XFlush(gdi_display);
4583         XDestroyImage(image);
4584         image = NULL;
4585     }
4586     return image;
4587 }
4588 #endif /* HAVE_LIBXXSHM */
4589
4590
4591 /***********************************************************************
4592  *           X11DRV_CreateDIBSection   (X11DRV.@)
4593  */
4594 HBITMAP X11DRV_CreateDIBSection( X11DRV_PDEVICE *physDev, HBITMAP hbitmap,
4595                                  const BITMAPINFO *bmi, UINT usage )
4596 {
4597     X_PHYSBITMAP *physBitmap;
4598     DIBSECTION dib;
4599
4600     if (!(physBitmap = X11DRV_init_phys_bitmap( hbitmap ))) return 0;
4601     physBitmap->status = DIB_Status_None;
4602
4603     GetObjectW( hbitmap, sizeof(dib), &dib );
4604
4605     /* create color map */
4606     if (dib.dsBm.bmBitsPixel <= 8)
4607     {
4608         physBitmap->colorMap = X11DRV_DIB_BuildColorMap( usage == DIB_PAL_COLORS ? physDev : NULL,
4609                                                          usage, dib.dsBm.bmBitsPixel, bmi,
4610                                                          &physBitmap->nColorMap );
4611         physBitmap->colorTable = X11DRV_DIB_BuildColorTable( physDev, usage, dib.dsBm.bmBitsPixel, bmi );
4612     }
4613
4614     /* create pixmap and X image */
4615     wine_tsx11_lock();
4616     physBitmap->pixmap_depth = (dib.dsBm.bmBitsPixel == 1) ? 1 : screen_depth;
4617     physBitmap->pixmap = XCreatePixmap( gdi_display, root_window, dib.dsBm.bmWidth,
4618                                         dib.dsBm.bmHeight, physBitmap->pixmap_depth );
4619 #ifdef HAVE_LIBXXSHM
4620     physBitmap->shminfo.shmid = -1;
4621     if (!XShmQueryExtension(gdi_display) ||
4622         !(physBitmap->image = X11DRV_XShmCreateImage( dib.dsBm.bmWidth, dib.dsBm.bmHeight,
4623                                                       physBitmap->pixmap_depth, &physBitmap->shminfo )) )
4624 #endif
4625         physBitmap->image = X11DRV_DIB_CreateXImage( dib.dsBm.bmWidth, dib.dsBm.bmHeight,
4626                                                      physBitmap->pixmap_depth );
4627     wine_tsx11_unlock();
4628     if (!physBitmap->pixmap || !physBitmap->image) return 0;
4629
4630       /* install fault handler */
4631     InitializeCriticalSection( &physBitmap->lock );
4632
4633     physBitmap->base   = dib.dsBm.bmBits;
4634     physBitmap->size   = dib.dsBmih.biSizeImage;
4635     physBitmap->status = DIB_Status_AppMod;
4636
4637     if (!dibs_handler)
4638         dibs_handler = AddVectoredExceptionHandler( TRUE, X11DRV_DIB_FaultHandler );
4639     EnterCriticalSection( &dibs_cs );
4640     list_add_head( &dibs_list, &physBitmap->entry );
4641     LeaveCriticalSection( &dibs_cs );
4642
4643     X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_READWRITE );
4644
4645     return hbitmap;
4646 }
4647
4648 /***********************************************************************
4649  *           X11DRV_DIB_DeleteDIBSection
4650  */
4651 void X11DRV_DIB_DeleteDIBSection(X_PHYSBITMAP *physBitmap, DIBSECTION *dib)
4652 {
4653   BOOL last;
4654
4655   EnterCriticalSection( &dibs_cs );
4656   list_remove( &physBitmap->entry );
4657   last = list_empty( &dibs_list );
4658   LeaveCriticalSection( &dibs_cs );
4659
4660   if (last)
4661   {
4662       RemoveVectoredExceptionHandler( dibs_handler );
4663       dibs_handler = NULL;
4664   }
4665
4666   if (dib->dshSection)
4667       X11DRV_DIB_Coerce(physBitmap, DIB_Status_InSync, FALSE);
4668
4669   if (physBitmap->image)
4670   {
4671       wine_tsx11_lock();
4672 #ifdef HAVE_LIBXXSHM
4673       if (physBitmap->shminfo.shmid != -1)
4674       {
4675           XShmDetach( gdi_display, &(physBitmap->shminfo) );
4676           XDestroyImage( physBitmap->image );
4677           shmdt( physBitmap->shminfo.shmaddr );
4678           physBitmap->shminfo.shmid = -1;
4679       }
4680       else
4681 #endif
4682           XDestroyImage( physBitmap->image );
4683       wine_tsx11_unlock();
4684   }
4685
4686   HeapFree(GetProcessHeap(), 0, physBitmap->colorMap);
4687   HeapFree(GetProcessHeap(), 0, physBitmap->colorTable);
4688   DeleteCriticalSection(&physBitmap->lock);
4689 }
4690
4691 /***********************************************************************
4692  *           SetDIBColorTable   (X11DRV.@)
4693  */
4694 UINT X11DRV_SetDIBColorTable( X11DRV_PDEVICE *physDev, UINT start, UINT count, const RGBQUAD *colors )
4695 {
4696     DIBSECTION dib;
4697     UINT ret = 0;
4698     X_PHYSBITMAP *physBitmap = physDev->bitmap;
4699
4700     if (!physBitmap) return 0;
4701     GetObjectW( physBitmap->hbitmap, sizeof(dib), &dib );
4702
4703     if (physBitmap->colorMap && start < physBitmap->nColorMap) {
4704         UINT end = count + start;
4705         if (end > physBitmap->nColorMap) end = physBitmap->nColorMap;
4706         /*
4707          * Changing color table might change the mapping between
4708          * DIB colors and X11 colors and thus alter the visible state
4709          * of the bitmap object.
4710          */
4711         X11DRV_DIB_Lock( physBitmap, DIB_Status_AppMod, FALSE );
4712         memcpy(physBitmap->colorTable + start, colors, (end - start) * sizeof(RGBQUAD));
4713         X11DRV_DIB_GenColorMap( physDev, physBitmap->colorMap, DIB_RGB_COLORS,
4714                                 dib.dsBm.bmBitsPixel,
4715                                 TRUE, colors, start, end );
4716         X11DRV_DIB_Unlock( physBitmap, TRUE );
4717         ret = end - start;
4718     }
4719     return ret;
4720 }
4721
4722 /***********************************************************************
4723  *           GetDIBColorTable   (X11DRV.@)
4724  */
4725 UINT X11DRV_GetDIBColorTable( X11DRV_PDEVICE *physDev, UINT start, UINT count, RGBQUAD *colors )
4726 {
4727     UINT ret = 0;
4728     X_PHYSBITMAP *physBitmap = physDev->bitmap;
4729
4730     if (physBitmap && physBitmap->colorTable && start < physBitmap->nColorMap) {
4731         if (start + count > physBitmap->nColorMap) count = physBitmap->nColorMap - start;
4732         memcpy(colors, physBitmap->colorTable + start, count * sizeof(RGBQUAD));
4733         ret = count;
4734     }
4735     return ret;
4736 }
4737
4738
4739
4740 /***********************************************************************
4741  *           X11DRV_DIB_CreateDIBFromBitmap
4742  *
4743  *  Allocates a packed DIB and copies the bitmap data into it.
4744  */
4745 HGLOBAL X11DRV_DIB_CreateDIBFromBitmap(HDC hdc, HBITMAP hBmp)
4746 {
4747     BITMAP bmp;
4748     HGLOBAL hPackedDIB;
4749     LPBYTE pPackedDIB;
4750     LPBITMAPINFOHEADER pbmiHeader;
4751     unsigned int cDataSize, cPackedSize, OffsetBits;
4752     int nLinesCopied;
4753
4754     if (!GetObjectW( hBmp, sizeof(bmp), &bmp )) return 0;
4755
4756     /*
4757      * A packed DIB contains a BITMAPINFO structure followed immediately by
4758      * an optional color palette and the pixel data.
4759      */
4760
4761     /* Calculate the size of the packed DIB */
4762     cDataSize = X11DRV_DIB_GetDIBWidthBytes( bmp.bmWidth, bmp.bmBitsPixel ) * abs( bmp.bmHeight );
4763     cPackedSize = sizeof(BITMAPINFOHEADER)
4764                   + ( (bmp.bmBitsPixel <= 8) ? (sizeof(RGBQUAD) * (1 << bmp.bmBitsPixel)) : 0 )
4765                   + cDataSize;
4766     /* Get the offset to the bits */
4767     OffsetBits = cPackedSize - cDataSize;
4768
4769     /* Allocate the packed DIB */
4770     TRACE("\tAllocating packed DIB of size %d\n", cPackedSize);
4771     hPackedDIB = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE /*| GMEM_ZEROINIT*/,
4772                              cPackedSize );
4773     if ( !hPackedDIB )
4774     {
4775         WARN("Could not allocate packed DIB!\n");
4776         return 0;
4777     }
4778
4779     /* A packed DIB starts with a BITMAPINFOHEADER */
4780     pPackedDIB = GlobalLock(hPackedDIB);
4781     pbmiHeader = (LPBITMAPINFOHEADER)pPackedDIB;
4782
4783     /* Init the BITMAPINFOHEADER */
4784     pbmiHeader->biSize = sizeof(BITMAPINFOHEADER);
4785     pbmiHeader->biWidth = bmp.bmWidth;
4786     pbmiHeader->biHeight = bmp.bmHeight;
4787     pbmiHeader->biPlanes = 1;
4788     pbmiHeader->biBitCount = bmp.bmBitsPixel;
4789     pbmiHeader->biCompression = BI_RGB;
4790     pbmiHeader->biSizeImage = 0;
4791     pbmiHeader->biXPelsPerMeter = pbmiHeader->biYPelsPerMeter = 0;
4792     pbmiHeader->biClrUsed = 0;
4793     pbmiHeader->biClrImportant = 0;
4794
4795     /* Retrieve the DIB bits from the bitmap and fill in the
4796      * DIB color table if present */
4797
4798     nLinesCopied = GetDIBits(hdc,                       /* Handle to device context */
4799                              hBmp,                      /* Handle to bitmap */
4800                              0,                         /* First scan line to set in dest bitmap */
4801                              bmp.bmHeight,              /* Number of scan lines to copy */
4802                              pPackedDIB + OffsetBits,   /* [out] Address of array for bitmap bits */
4803                              (LPBITMAPINFO) pbmiHeader, /* [out] Address of BITMAPINFO structure */
4804                              0);                        /* RGB or palette index */
4805     GlobalUnlock(hPackedDIB);
4806
4807     /* Cleanup if GetDIBits failed */
4808     if (nLinesCopied != bmp.bmHeight)
4809     {
4810         TRACE("\tGetDIBits returned %d. Actual lines=%d\n", nLinesCopied, bmp.bmHeight);
4811         GlobalFree(hPackedDIB);
4812         hPackedDIB = 0;
4813     }
4814     return hPackedDIB;
4815 }
4816
4817
4818 /**************************************************************************
4819  *              X11DRV_DIB_CreateDIBFromPixmap
4820  *
4821  *  Allocates a packed DIB and copies the Pixmap data into it.
4822  *  The Pixmap passed in is deleted after the conversion.
4823  */
4824 HGLOBAL X11DRV_DIB_CreateDIBFromPixmap(Pixmap pixmap, HDC hdc)
4825 {
4826     HDC hdcMem;
4827     X_PHYSBITMAP *physBitmap;
4828     HBITMAP hBmp = 0, old;
4829     HGLOBAL hPackedDIB = 0;
4830     Window root;
4831     int x,y;               /* Unused */
4832     unsigned border_width; /* Unused */
4833     unsigned int depth, width, height;
4834
4835     /* Get the Pixmap dimensions and bit depth */
4836     wine_tsx11_lock();
4837     if (!XGetGeometry(gdi_display, pixmap, &root, &x, &y, &width, &height,
4838                       &border_width, &depth)) depth = 0;
4839     wine_tsx11_unlock();
4840     if (!depth) return 0;
4841
4842     TRACE("\tPixmap properties: width=%d, height=%d, depth=%d\n",
4843           width, height, depth);
4844
4845     /*
4846      * Create an HBITMAP with the same dimensions and BPP as the pixmap,
4847      * and make it a container for the pixmap passed.
4848      */
4849     hBmp = CreateBitmap( width, height, 1, depth, NULL );
4850
4851     /* force bitmap to be owned by a screen DC */
4852     hdcMem = CreateCompatibleDC( hdc );
4853     old = SelectObject( hdcMem, hBmp );
4854
4855     physBitmap = X11DRV_get_phys_bitmap( hBmp );
4856
4857     wine_tsx11_lock();
4858     if (physBitmap->pixmap) XFreePixmap( gdi_display, physBitmap->pixmap );
4859     physBitmap->pixmap = pixmap;
4860     wine_tsx11_unlock();
4861
4862     SelectObject( hdcMem, old );
4863     DeleteDC( hdcMem );
4864
4865     /*
4866      * Create a packed DIB from the Pixmap wrapper bitmap created above.
4867      * A packed DIB contains a BITMAPINFO structure followed immediately by
4868      * an optional color palette and the pixel data.
4869      */
4870     hPackedDIB = X11DRV_DIB_CreateDIBFromBitmap(hdc, hBmp);
4871
4872     /* We can now get rid of the HBITMAP wrapper we created earlier.
4873      * Note: Simply calling DeleteObject will free the embedded Pixmap as well.
4874      */
4875     DeleteObject(hBmp);
4876
4877     TRACE("\tReturning packed DIB %p\n", hPackedDIB);
4878     return hPackedDIB;
4879 }
4880
4881
4882 /**************************************************************************
4883  *                 X11DRV_DIB_CreatePixmapFromDIB
4884  *
4885  *    Creates a Pixmap from a packed DIB
4886  */
4887 Pixmap X11DRV_DIB_CreatePixmapFromDIB( HGLOBAL hPackedDIB, HDC hdc )
4888 {
4889     Pixmap pixmap;
4890     X_PHYSBITMAP *physBitmap;
4891     HBITMAP hBmp;
4892     LPBITMAPINFO pbmi;
4893
4894     /* Create a DDB from the DIB */
4895
4896     pbmi = GlobalLock(hPackedDIB);
4897     hBmp = CreateDIBitmap(hdc, &pbmi->bmiHeader, CBM_INIT,
4898                           (LPBYTE)pbmi + X11DRV_DIB_BitmapInfoSize( pbmi, DIB_RGB_COLORS ),
4899                           pbmi, DIB_RGB_COLORS);
4900     GlobalUnlock(hPackedDIB);
4901
4902     /* clear the physBitmap so that we can steal its pixmap */
4903     physBitmap = X11DRV_get_phys_bitmap( hBmp );
4904     pixmap = physBitmap->pixmap;
4905     physBitmap->pixmap = 0;
4906
4907     /* Delete the DDB we created earlier now that we have stolen its pixmap */
4908     DeleteObject(hBmp);
4909
4910     TRACE("Returning Pixmap %ld\n", pixmap);
4911     return pixmap;
4912 }