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