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