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