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