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