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