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