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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include <X11/extensions/XShm.h>
26 # ifdef HAVE_SYS_SHM_H
29 # ifdef HAVE_SYS_IPC_H
32 #endif /* defined(HAVE_LIBXXSHM) */
41 #include "wine/debug.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(bitmap
);
44 WINE_DECLARE_DEBUG_CHANNEL(x11drv
);
46 static int ximageDepthTable
[32];
48 /* This structure holds the arguments for DIB_SetImageBits() */
51 X11DRV_PDEVICE
*physDev
;
54 PALETTEENTRY
*palentry
;
76 } X11DRV_DIB_IMAGEBITS_DESCR
;
81 RLE_EOL
= 0, /* End of line */
82 RLE_END
= 1, /* End of bitmap */
83 RLE_DELTA
= 2 /* Delta */
87 static INT
X11DRV_DIB_Coerce(X_PHYSBITMAP
*,INT
,BOOL
);
88 static INT
X11DRV_DIB_Lock(X_PHYSBITMAP
*,INT
,BOOL
);
89 static void X11DRV_DIB_Unlock(X_PHYSBITMAP
*,BOOL
);
92 Some of the following helper functions are duplicated in
96 /***********************************************************************
97 * X11DRV_DIB_GetXImageWidthBytes
99 * Return the width of an X image in bytes
101 inline static int X11DRV_DIB_GetXImageWidthBytes( int width
, int depth
)
103 if (!depth
|| depth
> 32) goto error
;
105 if (!ximageDepthTable
[depth
-1])
107 XImage
*testimage
= XCreateImage( gdi_display
, visual
, depth
,
108 ZPixmap
, 0, NULL
, 1, 1, 32, 20 );
111 ximageDepthTable
[depth
-1] = testimage
->bits_per_pixel
;
112 XDestroyImage( testimage
);
114 else ximageDepthTable
[depth
-1] = -1;
116 if (ximageDepthTable
[depth
-1] != -1)
117 return (4 * ((width
* ximageDepthTable
[depth
-1] + 31) / 32));
120 WARN( "(%d): Unsupported depth\n", depth
);
125 /***********************************************************************
126 * X11DRV_DIB_GetDIBWidthBytes
128 * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
130 static int X11DRV_DIB_GetDIBWidthBytes( int width
, int depth
)
136 case 1: words
= (width
+ 31) / 32; break;
137 case 4: words
= (width
+ 7) / 8; break;
138 case 8: words
= (width
+ 3) / 4; break;
140 case 16: words
= (width
+ 1) / 2; break;
141 case 24: words
= (width
* 3 + 3) / 4; break;
143 WARN("(%d): Unsupported depth\n", depth
);
152 /***********************************************************************
153 * X11DRV_DIB_GetDIBImageBytes
155 * Return the number of bytes used to hold the image in a DIB bitmap.
157 static int X11DRV_DIB_GetDIBImageBytes( int width
, int height
, int depth
)
159 return X11DRV_DIB_GetDIBWidthBytes( width
, depth
) * abs( height
);
163 /***********************************************************************
164 * X11DRV_DIB_BitmapInfoSize
166 * Return the size of the bitmap info structure including color table.
168 int X11DRV_DIB_BitmapInfoSize( const BITMAPINFO
* info
, WORD coloruse
)
172 if (info
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
174 const BITMAPCOREHEADER
*core
= (const BITMAPCOREHEADER
*)info
;
175 colors
= (core
->bcBitCount
<= 8) ? 1 << core
->bcBitCount
: 0;
176 return sizeof(BITMAPCOREHEADER
) + colors
*
177 ((coloruse
== DIB_RGB_COLORS
) ? sizeof(RGBTRIPLE
) : sizeof(WORD
));
179 else /* assume BITMAPINFOHEADER */
181 colors
= info
->bmiHeader
.biClrUsed
;
182 if (!colors
&& (info
->bmiHeader
.biBitCount
<= 8))
183 colors
= 1 << info
->bmiHeader
.biBitCount
;
184 return sizeof(BITMAPINFOHEADER
) + colors
*
185 ((coloruse
== DIB_RGB_COLORS
) ? sizeof(RGBQUAD
) : sizeof(WORD
));
190 /***********************************************************************
191 * X11DRV_DIB_CreateXImage
195 XImage
*X11DRV_DIB_CreateXImage( int width
, int height
, int depth
)
201 width_bytes
= X11DRV_DIB_GetXImageWidthBytes( width
, depth
);
202 image
= XCreateImage( gdi_display
, visual
, depth
, ZPixmap
, 0,
203 calloc( height
, width_bytes
),
204 width
, height
, 32, width_bytes
);
210 /***********************************************************************
211 * DIB_GetBitmapInfoEx
213 * Get the info from a bitmap header.
214 * Return 1 for INFOHEADER, 0 for COREHEADER, -1 for error.
216 static int DIB_GetBitmapInfoEx( const BITMAPINFOHEADER
*header
, LONG
*width
,
217 LONG
*height
, WORD
*planes
, WORD
*bpp
,
218 WORD
*compr
, DWORD
*size
)
220 if (header
->biSize
== sizeof(BITMAPCOREHEADER
))
222 const BITMAPCOREHEADER
*core
= (const BITMAPCOREHEADER
*)header
;
223 *width
= core
->bcWidth
;
224 *height
= core
->bcHeight
;
225 *planes
= core
->bcPlanes
;
226 *bpp
= core
->bcBitCount
;
231 if (header
->biSize
>= sizeof(BITMAPINFOHEADER
))
233 *width
= header
->biWidth
;
234 *height
= header
->biHeight
;
235 *planes
= header
->biPlanes
;
236 *bpp
= header
->biBitCount
;
237 *compr
= header
->biCompression
;
238 *size
= header
->biSizeImage
;
241 ERR("(%ld): unknown/wrong size for header\n", header
->biSize
);
246 /***********************************************************************
249 * Get the info from a bitmap header.
250 * Return 1 for INFOHEADER, 0 for COREHEADER, -1 for error.
252 static int DIB_GetBitmapInfo( const BITMAPINFOHEADER
*header
, LONG
*width
,
253 LONG
*height
, WORD
*bpp
, WORD
*compr
)
258 return DIB_GetBitmapInfoEx( header
, width
, height
, &planes
, bpp
, compr
, &size
);
262 /***********************************************************************
263 * X11DRV_DIB_GenColorMap
265 * Fills the color map of a bitmap palette. Should not be called
266 * for a >8-bit deep bitmap.
268 int *X11DRV_DIB_GenColorMap( X11DRV_PDEVICE
*physDev
, int *colorMapping
,
269 WORD coloruse
, WORD depth
, BOOL quads
,
270 const void *colorPtr
, int start
, int end
)
274 if (coloruse
== DIB_RGB_COLORS
)
278 const RGBQUAD
* rgb
= (const RGBQUAD
*)colorPtr
;
280 if (depth
== 1) /* Monochrome */
281 for (i
= start
; i
< end
; i
++, rgb
++)
282 colorMapping
[i
] = (rgb
->rgbRed
+ rgb
->rgbGreen
+
283 rgb
->rgbBlue
> 255*3/2);
285 for (i
= start
; i
< end
; i
++, rgb
++)
286 colorMapping
[i
] = X11DRV_PALETTE_ToPhysical( physDev
, RGB(rgb
->rgbRed
,
292 const RGBTRIPLE
* rgb
= (const RGBTRIPLE
*)colorPtr
;
294 if (depth
== 1) /* Monochrome */
295 for (i
= start
; i
< end
; i
++, rgb
++)
296 colorMapping
[i
] = (rgb
->rgbtRed
+ rgb
->rgbtGreen
+
297 rgb
->rgbtBlue
> 255*3/2);
299 for (i
= start
; i
< end
; i
++, rgb
++)
300 colorMapping
[i
] = X11DRV_PALETTE_ToPhysical( physDev
, RGB(rgb
->rgbtRed
,
305 else /* DIB_PAL_COLORS */
308 const WORD
* index
= (const WORD
*)colorPtr
;
310 for (i
= start
; i
< end
; i
++, index
++)
311 colorMapping
[i
] = X11DRV_PALETTE_ToPhysical( physDev
, PALETTEINDEX(*index
) );
313 for (i
= start
; i
< end
; i
++)
314 colorMapping
[i
] = X11DRV_PALETTE_ToPhysical( physDev
, PALETTEINDEX(i
) );
321 /***********************************************************************
322 * X11DRV_DIB_BuildColorMap
324 * Build the color map from the bitmap palette. Should not be called
325 * for a >8-bit deep bitmap.
327 int *X11DRV_DIB_BuildColorMap( X11DRV_PDEVICE
*physDev
, WORD coloruse
, WORD depth
,
328 const BITMAPINFO
*info
, int *nColors
)
332 const void *colorPtr
;
335 isInfo
= info
->bmiHeader
.biSize
!= sizeof(BITMAPCOREHEADER
);
339 colors
= info
->bmiHeader
.biClrUsed
;
340 if (!colors
) colors
= 1 << info
->bmiHeader
.biBitCount
;
344 colors
= 1 << ((const BITMAPCOREHEADER
*)info
)->bcBitCount
;
347 colorPtr
= (const BYTE
*) info
+ (WORD
) info
->bmiHeader
.biSize
;
351 ERR("called with >256 colors!\n");
355 /* just so CopyDIBSection doesn't have to create an identity palette */
356 if (coloruse
== (WORD
)-1) colorPtr
= NULL
;
358 if (!(colorMapping
= HeapAlloc(GetProcessHeap(), 0, colors
* sizeof(int) )))
362 return X11DRV_DIB_GenColorMap( physDev
, colorMapping
, coloruse
, depth
,
363 isInfo
, colorPtr
, 0, colors
);
366 /***********************************************************************
367 * X11DRV_DIB_BuildColorTable
369 * Build the dib color table. This either keeps a copy of the bmiColors array if
370 * usage is DIB_RGB_COLORS, or looks up the palette indicies if usage is
372 * Should not be called for a >8-bit deep bitmap.
374 static RGBQUAD
*X11DRV_DIB_BuildColorTable( X11DRV_PDEVICE
*physDev
, WORD coloruse
, WORD depth
,
375 const BITMAPINFO
*info
)
380 BOOL core_info
= info
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
);
384 colors
= 1 << ((BITMAPCOREINFO
*) info
)->bmciHeader
.bcBitCount
;
388 colors
= info
->bmiHeader
.biClrUsed
;
389 if (!colors
) colors
= 1 << info
->bmiHeader
.biBitCount
;
393 ERR("called with >256 colors!\n");
397 if (!(colorTable
= HeapAlloc(GetProcessHeap(), 0, colors
* sizeof(RGBQUAD
) )))
400 if(coloruse
== DIB_RGB_COLORS
)
404 /* Convert RGBTRIPLEs to RGBQUADs */
405 for (i
=0; i
< colors
; i
++)
407 colorTable
[i
].rgbRed
= ((BITMAPCOREINFO
*) info
)->bmciColors
[i
].rgbtRed
;
408 colorTable
[i
].rgbGreen
= ((BITMAPCOREINFO
*) info
)->bmciColors
[i
].rgbtGreen
;
409 colorTable
[i
].rgbBlue
= ((BITMAPCOREINFO
*) info
)->bmciColors
[i
].rgbtBlue
;
410 colorTable
[i
].rgbReserved
= 0;
415 memcpy(colorTable
, (LPBYTE
) info
+ (WORD
) info
->bmiHeader
.biSize
, colors
* sizeof(RGBQUAD
));
420 HPALETTE hpal
= GetCurrentObject(physDev
->hdc
, OBJ_PAL
);
421 PALETTEENTRY
* pal_ents
;
422 WORD
*index
= (WORD
*) ((LPBYTE
) info
+ (WORD
) info
->bmiHeader
.biSize
);
423 int logcolors
, entry
;
425 logcolors
= GetPaletteEntries( hpal
, 0, 0, NULL
);
426 pal_ents
= HeapAlloc(GetProcessHeap(), 0, logcolors
* sizeof(*pal_ents
));
427 logcolors
= GetPaletteEntries( hpal
, 0, logcolors
, pal_ents
);
429 for(i
= 0; i
< colors
; i
++, index
++)
431 entry
= *index
% logcolors
;
432 colorTable
[i
].rgbRed
= pal_ents
[entry
].peRed
;
433 colorTable
[i
].rgbGreen
= pal_ents
[entry
].peGreen
;
434 colorTable
[i
].rgbBlue
= pal_ents
[entry
].peBlue
;
435 colorTable
[i
].rgbReserved
= 0;
438 HeapFree(GetProcessHeap(), 0, pal_ents
);
444 /***********************************************************************
445 * X11DRV_DIB_MapColor
447 int X11DRV_DIB_MapColor( int *physMap
, int nPhysMap
, int phys
, int oldcol
)
451 if ((oldcol
< nPhysMap
) && (physMap
[oldcol
] == phys
))
454 for (color
= 0; color
< nPhysMap
; color
++)
455 if (physMap
[color
] == phys
)
458 WARN("Strange color %08x\n", phys
);
463 /*********************************************************************
464 * X11DRV_DIB_GetNearestIndex
466 * Helper for X11DRV_DIB_GetDIBits.
467 * Returns the nearest colour table index for a given RGB.
468 * Nearest is defined by minimizing the sum of the squares.
470 static INT
X11DRV_DIB_GetNearestIndex(RGBQUAD
*colormap
, int numColors
, BYTE r
, BYTE g
, BYTE b
)
472 INT i
, best
= -1, diff
, bestdiff
= -1;
475 for(color
= colormap
, i
= 0; i
< numColors
; color
++, i
++) {
476 diff
= (r
- color
->rgbRed
) * (r
- color
->rgbRed
) +
477 (g
- color
->rgbGreen
) * (g
- color
->rgbGreen
) +
478 (b
- color
->rgbBlue
) * (b
- color
->rgbBlue
);
481 if(best
== -1 || diff
< bestdiff
) {
488 /*********************************************************************
489 * X11DRV_DIB_MaskToShift
491 * Helper for X11DRV_DIB_GetDIBits.
492 * Returns the by how many bits to shift a given color so that it is
493 * in the proper position.
495 INT
X11DRV_DIB_MaskToShift(DWORD mask
)
503 while ((mask
&1)==0) {
510 /***********************************************************************
511 * X11DRV_DIB_SetImageBits_1
513 * SetDIBits for a 1-bit deep DIB.
515 static void X11DRV_DIB_SetImageBits_1( int lines
, const BYTE
*srcbits
,
516 DWORD srcwidth
, DWORD dstwidth
, int left
,
517 int *colors
, XImage
*bmpImage
, DWORD linebytes
)
526 srcbits
= srcbits
+ linebytes
* (lines
- 1);
527 linebytes
= -linebytes
;
530 if ((extra
= (left
& 7)) != 0) {
534 srcbits
+= left
>> 3;
535 width
= min(srcwidth
, dstwidth
);
537 /* ==== pal 1 dib -> any bmp format ==== */
538 for (h
= lines
-1; h
>=0; h
--) {
540 /* FIXME: should avoid putting x<left pixels (minor speed issue) */
541 for (i
= width
/8, x
= left
; i
> 0; i
--) {
543 XPutPixel( bmpImage
, x
++, h
, colors
[ srcval
>> 7] );
544 XPutPixel( bmpImage
, x
++, h
, colors
[(srcval
>> 6) & 1] );
545 XPutPixel( bmpImage
, x
++, h
, colors
[(srcval
>> 5) & 1] );
546 XPutPixel( bmpImage
, x
++, h
, colors
[(srcval
>> 4) & 1] );
547 XPutPixel( bmpImage
, x
++, h
, colors
[(srcval
>> 3) & 1] );
548 XPutPixel( bmpImage
, x
++, h
, colors
[(srcval
>> 2) & 1] );
549 XPutPixel( bmpImage
, x
++, h
, colors
[(srcval
>> 1) & 1] );
550 XPutPixel( bmpImage
, x
++, h
, colors
[ srcval
& 1] );
556 case 7: XPutPixel(bmpImage
, x
++, h
, colors
[srcval
>> 7]); srcval
<<=1;
557 case 6: XPutPixel(bmpImage
, x
++, h
, colors
[srcval
>> 7]); srcval
<<=1;
558 case 5: XPutPixel(bmpImage
, x
++, h
, colors
[srcval
>> 7]); srcval
<<=1;
559 case 4: XPutPixel(bmpImage
, x
++, h
, colors
[srcval
>> 7]); srcval
<<=1;
560 case 3: XPutPixel(bmpImage
, x
++, h
, colors
[srcval
>> 7]); srcval
<<=1;
561 case 2: XPutPixel(bmpImage
, x
++, h
, colors
[srcval
>> 7]); srcval
<<=1;
562 case 1: XPutPixel(bmpImage
, x
++, h
, colors
[srcval
>> 7]);
565 srcbits
+= linebytes
;
569 /***********************************************************************
570 * X11DRV_DIB_GetImageBits_1
572 * GetDIBits for a 1-bit deep DIB.
574 static void X11DRV_DIB_GetImageBits_1( int lines
, BYTE
*dstbits
,
575 DWORD dstwidth
, DWORD srcwidth
,
576 RGBQUAD
*colors
, PALETTEENTRY
*srccolors
,
577 XImage
*bmpImage
, DWORD linebytes
)
580 int h
, width
= min(dstwidth
, srcwidth
);
584 dstbits
= dstbits
+ linebytes
* (lines
- 1);
585 linebytes
= -linebytes
;
588 switch (bmpImage
->depth
)
592 if (bmpImage
->red_mask
==0 && bmpImage
->green_mask
==0 && bmpImage
->blue_mask
==0 && srccolors
) {
593 /* ==== pal 1 or 4 bmp -> pal 1 dib ==== */
596 for (h
=lines
-1; h
>=0; h
--) {
600 for (x
=0; x
<width
; x
++) {
602 srcval
=srccolors
[XGetPixel(bmpImage
, x
, h
)];
603 dstval
|=(X11DRV_DIB_GetNearestIndex
607 srcval
.peBlue
) << (7 - (x
& 7)));
616 dstbits
+= linebytes
;
624 if (bmpImage
->red_mask
==0 && bmpImage
->green_mask
==0 && bmpImage
->blue_mask
==0 && srccolors
) {
625 /* ==== pal 8 bmp -> pal 1 dib ==== */
627 const BYTE
* srcpixel
;
630 srcbits
=bmpImage
->data
+(lines
-1)*bmpImage
->bytes_per_line
;
632 for (h
=0; h
<lines
; h
++) {
637 for (x
=0; x
<width
; x
++) {
639 srcval
=srccolors
[(int)*srcpixel
++];
640 dstval
|=(X11DRV_DIB_GetNearestIndex
644 srcval
.peBlue
) << (7-(x
&7)) );
653 srcbits
= (const char*)srcbits
- bmpImage
->bytes_per_line
;
654 dstbits
+= linebytes
;
665 const WORD
* srcpixel
;
668 srcbits
=bmpImage
->data
+(lines
-1)*bmpImage
->bytes_per_line
;
670 if (bmpImage
->green_mask
==0x03e0) {
671 if (bmpImage
->red_mask
==0x7c00) {
672 /* ==== rgb 555 bmp -> pal 1 dib ==== */
673 for (h
=0; h
<lines
; h
++) {
678 for (x
=0; x
<width
; x
++) {
681 dstval
|=(X11DRV_DIB_GetNearestIndex
683 ((srcval
>> 7) & 0xf8) | /* r */
684 ((srcval
>> 12) & 0x07),
685 ((srcval
>> 2) & 0xf8) | /* g */
686 ((srcval
>> 7) & 0x07),
687 ((srcval
<< 3) & 0xf8) | /* b */
688 ((srcval
>> 2) & 0x07) ) << (7-(x
&7)) );
697 srcbits
= (const char*)srcbits
- bmpImage
->bytes_per_line
;
698 dstbits
+= linebytes
;
700 } else if (bmpImage
->blue_mask
==0x7c00) {
701 /* ==== bgr 555 bmp -> pal 1 dib ==== */
702 for (h
=0; h
<lines
; h
++) {
707 for (x
=0; x
<width
; x
++) {
710 dstval
|=(X11DRV_DIB_GetNearestIndex
712 ((srcval
<< 3) & 0xf8) | /* r */
713 ((srcval
>> 2) & 0x07),
714 ((srcval
>> 2) & 0xf8) | /* g */
715 ((srcval
>> 7) & 0x07),
716 ((srcval
>> 7) & 0xf8) | /* b */
717 ((srcval
>> 12) & 0x07) ) << (7-(x
&7)) );
726 srcbits
= (const char*)srcbits
- bmpImage
->bytes_per_line
;
727 dstbits
+= linebytes
;
732 } else if (bmpImage
->green_mask
==0x07e0) {
733 if (bmpImage
->red_mask
==0xf800) {
734 /* ==== rgb 565 bmp -> pal 1 dib ==== */
735 for (h
=0; h
<lines
; h
++) {
740 for (x
=0; x
<width
; x
++) {
743 dstval
|=(X11DRV_DIB_GetNearestIndex
745 ((srcval
>> 8) & 0xf8) | /* r */
746 ((srcval
>> 13) & 0x07),
747 ((srcval
>> 3) & 0xfc) | /* g */
748 ((srcval
>> 9) & 0x03),
749 ((srcval
<< 3) & 0xf8) | /* b */
750 ((srcval
>> 2) & 0x07) ) << (7-(x
&7)) );
759 srcbits
= (const char*)srcbits
- bmpImage
->bytes_per_line
;
760 dstbits
+= linebytes
;
762 } else if (bmpImage
->blue_mask
==0xf800) {
763 /* ==== bgr 565 bmp -> pal 1 dib ==== */
764 for (h
=0; h
<lines
; h
++) {
769 for (x
=0; x
<width
; x
++) {
772 dstval
|=(X11DRV_DIB_GetNearestIndex
774 ((srcval
<< 3) & 0xf8) | /* r */
775 ((srcval
>> 2) & 0x07),
776 ((srcval
>> 3) & 0xfc) | /* g */
777 ((srcval
>> 9) & 0x03),
778 ((srcval
>> 8) & 0xf8) | /* b */
779 ((srcval
>> 13) & 0x07) ) << (7-(x
&7)) );
788 srcbits
= (const char*)srcbits
- bmpImage
->bytes_per_line
;
789 dstbits
+= linebytes
;
808 srcbits
=bmpImage
->data
+(lines
-1)*bmpImage
->bytes_per_line
;
809 bytes_per_pixel
=(bmpImage
->bits_per_pixel
==24?3:4);
811 if (bmpImage
->green_mask
!=0x00ff00 ||
812 (bmpImage
->red_mask
|bmpImage
->blue_mask
)!=0xff00ff) {
814 } else if (bmpImage
->blue_mask
==0xff) {
815 /* ==== rgb 888 or 0888 bmp -> pal 1 dib ==== */
816 for (h
=0; h
<lines
; h
++) {
821 for (x
=0; x
<width
; x
++) {
822 dstval
|=(X11DRV_DIB_GetNearestIndex
826 srcbyte
[0]) << (7-(x
&7)) );
827 srcbyte
+=bytes_per_pixel
;
836 srcbits
= (const char*)srcbits
- bmpImage
->bytes_per_line
;
837 dstbits
+= linebytes
;
840 /* ==== bgr 888 or 0888 bmp -> pal 1 dib ==== */
841 for (h
=0; h
<lines
; h
++) {
846 for (x
=0; x
<width
; x
++) {
847 dstval
|=(X11DRV_DIB_GetNearestIndex
851 srcbyte
[2]) << (7-(x
&7)) );
852 srcbyte
+=bytes_per_pixel
;
861 srcbits
= (const char*)srcbits
- bmpImage
->bytes_per_line
;
862 dstbits
+= linebytes
;
872 unsigned long white
= (1 << bmpImage
->bits_per_pixel
) - 1;
874 /* ==== any bmp format -> pal 1 dib ==== */
875 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 1 bit DIB\n",
876 bmpImage
->bits_per_pixel
, bmpImage
->red_mask
,
877 bmpImage
->green_mask
, bmpImage
->blue_mask
);
879 for (h
=lines
-1; h
>=0; h
--) {
883 for (x
=0; x
<width
; x
++) {
884 dstval
|=(XGetPixel( bmpImage
, x
, h
) >= white
) << (7 - (x
&7));
893 dstbits
+= linebytes
;
900 /***********************************************************************
901 * X11DRV_DIB_SetImageBits_4
903 * SetDIBits for a 4-bit deep DIB.
905 static void X11DRV_DIB_SetImageBits_4( int lines
, const BYTE
*srcbits
,
906 DWORD srcwidth
, DWORD dstwidth
, int left
,
907 int *colors
, XImage
*bmpImage
, DWORD linebytes
)
915 srcbits
= srcbits
+ linebytes
* (lines
- 1);
916 linebytes
= -linebytes
;
923 srcbits
+= left
>> 1;
924 width
= min(srcwidth
, dstwidth
);
926 /* ==== pal 4 dib -> any bmp format ==== */
927 for (h
= lines
-1; h
>= 0; h
--) {
929 for (i
= width
/2, x
= left
; i
> 0; i
--) {
930 BYTE srcval
=*srcbyte
++;
931 XPutPixel( bmpImage
, x
++, h
, colors
[srcval
>> 4] );
932 XPutPixel( bmpImage
, x
++, h
, colors
[srcval
& 0x0f] );
935 XPutPixel( bmpImage
, x
, h
, colors
[*srcbyte
>> 4] );
936 srcbits
+= linebytes
;
942 /***********************************************************************
943 * X11DRV_DIB_GetImageBits_4
945 * GetDIBits for a 4-bit deep DIB.
947 static void X11DRV_DIB_GetImageBits_4( int lines
, BYTE
*dstbits
,
948 DWORD srcwidth
, DWORD dstwidth
,
949 RGBQUAD
*colors
, PALETTEENTRY
*srccolors
,
950 XImage
*bmpImage
, DWORD linebytes
)
953 int h
, width
= min(srcwidth
, dstwidth
);
959 dstbits
= dstbits
+ ( linebytes
* (lines
-1) );
960 linebytes
= -linebytes
;
965 switch (bmpImage
->depth
) {
968 if (bmpImage
->red_mask
==0 && bmpImage
->green_mask
==0 && bmpImage
->blue_mask
==0 && srccolors
) {
969 /* ==== pal 1 or 4 bmp -> pal 4 dib ==== */
972 for (h
= lines
-1; h
>= 0; h
--) {
976 for (x
= 0; x
< width
; x
++) {
978 srcval
=srccolors
[XGetPixel(bmpImage
, x
, h
)];
979 dstval
|=(X11DRV_DIB_GetNearestIndex
983 srcval
.peBlue
) << (4-((x
&1)<<2)));
992 dstbits
+= linebytes
;
1000 if (bmpImage
->red_mask
==0 && bmpImage
->green_mask
==0 && bmpImage
->blue_mask
==0 && srccolors
) {
1001 /* ==== pal 8 bmp -> pal 4 dib ==== */
1002 const void* srcbits
;
1003 const BYTE
*srcpixel
;
1006 srcbits
=bmpImage
->data
+(lines
-1)*bmpImage
->bytes_per_line
;
1007 for (h
=0; h
<lines
; h
++) {
1012 for (x
=0; x
<width
; x
++) {
1013 PALETTEENTRY srcval
;
1014 srcval
= srccolors
[(int)*srcpixel
++];
1015 dstval
|=(X11DRV_DIB_GetNearestIndex
1019 srcval
.peBlue
) << (4*(1-(x
&1))) );
1028 srcbits
= (const char*)srcbits
- bmpImage
->bytes_per_line
;
1029 dstbits
+= linebytes
;
1039 const void* srcbits
;
1040 const WORD
* srcpixel
;
1043 srcbits
=bmpImage
->data
+(lines
-1)*bmpImage
->bytes_per_line
;
1045 if (bmpImage
->green_mask
==0x03e0) {
1046 if (bmpImage
->red_mask
==0x7c00) {
1047 /* ==== rgb 555 bmp -> pal 4 dib ==== */
1048 for (h
=0; h
<lines
; h
++) {
1053 for (x
=0; x
<width
; x
++) {
1056 dstval
|=(X11DRV_DIB_GetNearestIndex
1058 ((srcval
>> 7) & 0xf8) | /* r */
1059 ((srcval
>> 12) & 0x07),
1060 ((srcval
>> 2) & 0xf8) | /* g */
1061 ((srcval
>> 7) & 0x07),
1062 ((srcval
<< 3) & 0xf8) | /* b */
1063 ((srcval
>> 2) & 0x07) ) << ((1-(x
&1))<<2) );
1072 srcbits
= (const char*)srcbits
- bmpImage
->bytes_per_line
;
1073 dstbits
+= linebytes
;
1075 } else if (bmpImage
->blue_mask
==0x7c00) {
1076 /* ==== bgr 555 bmp -> pal 4 dib ==== */
1077 for (h
=0; h
<lines
; h
++) {
1082 for (x
=0; x
<width
; x
++) {
1085 dstval
|=(X11DRV_DIB_GetNearestIndex
1087 ((srcval
<< 3) & 0xf8) | /* r */
1088 ((srcval
>> 2) & 0x07),
1089 ((srcval
>> 2) & 0xf8) | /* g */
1090 ((srcval
>> 7) & 0x07),
1091 ((srcval
>> 7) & 0xf8) | /* b */
1092 ((srcval
>> 12) & 0x07) ) << ((1-(x
&1))<<2) );
1101 srcbits
= (const char*)srcbits
- bmpImage
->bytes_per_line
;
1102 dstbits
+= linebytes
;
1107 } else if (bmpImage
->green_mask
==0x07e0) {
1108 if (bmpImage
->red_mask
==0xf800) {
1109 /* ==== rgb 565 bmp -> pal 4 dib ==== */
1110 for (h
=0; h
<lines
; h
++) {
1115 for (x
=0; x
<width
; x
++) {
1118 dstval
|=(X11DRV_DIB_GetNearestIndex
1120 ((srcval
>> 8) & 0xf8) | /* r */
1121 ((srcval
>> 13) & 0x07),
1122 ((srcval
>> 3) & 0xfc) | /* g */
1123 ((srcval
>> 9) & 0x03),
1124 ((srcval
<< 3) & 0xf8) | /* b */
1125 ((srcval
>> 2) & 0x07) ) << ((1-(x
&1))<<2) );
1134 srcbits
= (const char*)srcbits
- bmpImage
->bytes_per_line
;
1135 dstbits
+= linebytes
;
1137 } else if (bmpImage
->blue_mask
==0xf800) {
1138 /* ==== bgr 565 bmp -> pal 4 dib ==== */
1139 for (h
=0; h
<lines
; h
++) {
1144 for (x
=0; x
<width
; x
++) {
1147 dstval
|=(X11DRV_DIB_GetNearestIndex
1149 ((srcval
<< 3) & 0xf8) | /* r */
1150 ((srcval
>> 2) & 0x07),
1151 ((srcval
>> 3) & 0xfc) | /* g */
1152 ((srcval
>> 9) & 0x03),
1153 ((srcval
>> 8) & 0xf8) | /* b */
1154 ((srcval
>> 13) & 0x07) ) << ((1-(x
&1))<<2) );
1163 srcbits
= (const char*)srcbits
- bmpImage
->bytes_per_line
;
1164 dstbits
+= linebytes
;
1176 if (bmpImage
->bits_per_pixel
==24) {
1177 const void* srcbits
;
1178 const BYTE
*srcbyte
;
1181 srcbits
=bmpImage
->data
+(lines
-1)*bmpImage
->bytes_per_line
;
1183 if (bmpImage
->green_mask
!=0x00ff00 ||
1184 (bmpImage
->red_mask
|bmpImage
->blue_mask
)!=0xff00ff) {
1186 } else if (bmpImage
->blue_mask
==0xff) {
1187 /* ==== rgb 888 bmp -> pal 4 dib ==== */
1188 for (h
=0; h
<lines
; h
++) {
1191 for (x
=0; x
<width
/2; x
++) {
1192 /* Do 2 pixels at a time */
1193 *dstbyte
++=(X11DRV_DIB_GetNearestIndex
1198 X11DRV_DIB_GetNearestIndex
1206 /* And the the odd pixel */
1207 *dstbyte
++=(X11DRV_DIB_GetNearestIndex
1213 srcbits
= (const char*)srcbits
- bmpImage
->bytes_per_line
;
1214 dstbits
+= linebytes
;
1217 /* ==== bgr 888 bmp -> pal 4 dib ==== */
1218 for (h
=0; h
<lines
; h
++) {
1221 for (x
=0; x
<width
/2; x
++) {
1222 /* Do 2 pixels at a time */
1223 *dstbyte
++=(X11DRV_DIB_GetNearestIndex
1228 X11DRV_DIB_GetNearestIndex
1236 /* And the the odd pixel */
1237 *dstbyte
++=(X11DRV_DIB_GetNearestIndex
1243 srcbits
= (const char*)srcbits
- bmpImage
->bytes_per_line
;
1244 dstbits
+= linebytes
;
1253 const void* srcbits
;
1254 const BYTE
*srcbyte
;
1257 srcbits
=bmpImage
->data
+(lines
-1)*bmpImage
->bytes_per_line
;
1259 if (bmpImage
->green_mask
!=0x00ff00 ||
1260 (bmpImage
->red_mask
|bmpImage
->blue_mask
)!=0xff00ff) {
1262 } else if (bmpImage
->blue_mask
==0xff) {
1263 /* ==== rgb 0888 bmp -> pal 4 dib ==== */
1264 for (h
=0; h
<lines
; h
++) {
1267 for (x
=0; x
<width
/2; x
++) {
1268 /* Do 2 pixels at a time */
1269 *dstbyte
++=(X11DRV_DIB_GetNearestIndex
1274 X11DRV_DIB_GetNearestIndex
1282 /* And the the odd pixel */
1283 *dstbyte
++=(X11DRV_DIB_GetNearestIndex
1289 srcbits
= (const char*)srcbits
- bmpImage
->bytes_per_line
;
1290 dstbits
+= linebytes
;
1293 /* ==== bgr 0888 bmp -> pal 4 dib ==== */
1294 for (h
=0; h
<lines
; h
++) {
1297 for (x
=0; x
<width
/2; x
++) {
1298 /* Do 2 pixels at a time */
1299 *dstbyte
++=(X11DRV_DIB_GetNearestIndex
1304 X11DRV_DIB_GetNearestIndex
1312 /* And the the odd pixel */
1313 *dstbyte
++=(X11DRV_DIB_GetNearestIndex
1319 srcbits
= (const char*)srcbits
- bmpImage
->bytes_per_line
;
1320 dstbits
+= linebytes
;
1331 /* ==== any bmp format -> pal 4 dib ==== */
1332 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 4 bit DIB\n",
1333 bmpImage
->bits_per_pixel
, bmpImage
->red_mask
,
1334 bmpImage
->green_mask
, bmpImage
->blue_mask
);
1335 for (h
=lines
-1; h
>=0; h
--) {
1337 for (x
=0; x
<(width
& ~1); x
+=2) {
1338 *dstbyte
++=(X11DRV_DIB_MapColor((int*)colors
, 16, XGetPixel(bmpImage
, x
, h
), 0) << 4) |
1339 X11DRV_DIB_MapColor((int*)colors
, 16, XGetPixel(bmpImage
, x
+1, h
), 0);
1342 *dstbyte
=(X11DRV_DIB_MapColor((int *)colors
, 16, XGetPixel(bmpImage
, x
, h
), 0) << 4);
1344 dstbits
+= linebytes
;
1351 /***********************************************************************
1352 * X11DRV_DIB_SetImageBits_RLE4
1354 * SetDIBits for a 4-bit deep compressed DIB.
1356 static void X11DRV_DIB_SetImageBits_RLE4( int lines
, const BYTE
*bits
,
1357 DWORD srcwidth
, DWORD dstwidth
,
1358 int left
, int *colors
,
1361 unsigned int x
= 0, width
= min(srcwidth
, dstwidth
);
1362 int y
= lines
- 1, c
, length
;
1363 const BYTE
*begin
= bits
;
1368 if (length
) { /* encoded */
1371 if (x
>= (left
+ width
)) break;
1372 if( x
>= left
) XPutPixel(bmpImage
, x
, y
, colors
[c
>> 4]);
1374 if (!length
--) break;
1375 if (x
>= (left
+ width
)) break;
1376 if( x
>= left
) XPutPixel(bmpImage
, x
, y
, colors
[c
& 0xf]);
1396 default: /* absolute */
1399 if (x
>= left
&& x
< (left
+ width
))
1400 XPutPixel(bmpImage
, x
, y
, colors
[c
>> 4]);
1402 if (!length
--) break;
1403 if (x
>= left
&& x
< (left
+ width
))
1404 XPutPixel(bmpImage
, x
, y
, colors
[c
& 0xf]);
1407 if ((bits
- begin
) & 1)
1416 /***********************************************************************
1417 * X11DRV_DIB_SetImageBits_8
1419 * SetDIBits for an 8-bit deep DIB.
1421 static void X11DRV_DIB_SetImageBits_8( int lines
, const BYTE
*srcbits
,
1422 DWORD srcwidth
, DWORD dstwidth
, int left
,
1423 const int *colors
, XImage
*bmpImage
,
1427 int h
, width
= min(srcwidth
, dstwidth
);
1428 const BYTE
* srcbyte
;
1434 srcbits
= srcbits
+ linebytes
* (lines
-1);
1435 linebytes
= -linebytes
;
1440 switch (bmpImage
->depth
) {
1443 #if defined(__i386__) && defined(__GNUC__)
1444 /* Some X servers might have 32 bit/ 16bit deep pixel */
1445 if (lines
&& width
&& (bmpImage
->bits_per_pixel
== 16) &&
1446 (ImageByteOrder(gdi_display
)==LSBFirst
) )
1448 dstbits
=bmpImage
->data
+left
*2+(lines
-1)*bmpImage
->bytes_per_line
;
1449 /* FIXME: Does this really handle all these cases correctly? */
1450 /* ==== pal 8 dib -> rgb or bgr 555 or 565 bmp ==== */
1451 for (h
= lines
; h
--; ) {
1452 int _cl1
,_cl2
; /* temp outputs for asm below */
1453 /* Borrowed from DirectDraw */
1454 __asm__
__volatile__(
1459 " movw (%%edx,%%eax,4),%%ax\n"
1461 " xor %%eax,%%eax\n"
1463 :"=S" (srcbyte
), "=D" (_cl1
), "=c" (_cl2
)
1468 :"eax", "cc", "memory"
1470 srcbyte
= (srcbits
+= linebytes
);
1471 dstbits
-= bmpImage
->bytes_per_line
;
1479 #if defined(__i386__) && defined(__GNUC__)
1480 if (lines
&& width
&& (bmpImage
->bits_per_pixel
== 32) &&
1481 (ImageByteOrder(gdi_display
)==LSBFirst
) )
1483 dstbits
=bmpImage
->data
+left
*4+(lines
-1)*bmpImage
->bytes_per_line
;
1484 /* FIXME: Does this really handle both cases correctly? */
1485 /* ==== pal 8 dib -> rgb or bgr 0888 bmp ==== */
1486 for (h
= lines
; h
--; ) {
1487 int _cl1
,_cl2
; /* temp outputs for asm below */
1488 /* Borrowed from DirectDraw */
1489 __asm__
__volatile__(
1494 " movl (%%edx,%%eax,4),%%eax\n"
1496 " xor %%eax,%%eax\n"
1498 :"=S" (srcbyte
), "=D" (_cl1
), "=c" (_cl2
)
1503 :"eax", "cc", "memory"
1505 srcbyte
= (srcbits
+= linebytes
);
1506 dstbits
-= bmpImage
->bytes_per_line
;
1513 break; /* use slow generic case below */
1516 /* ==== pal 8 dib -> any bmp format ==== */
1517 for (h
=lines
-1; h
>=0; h
--) {
1518 for (x
=left
; x
<width
+left
; x
++) {
1519 XPutPixel(bmpImage
, x
, h
, colors
[*srcbyte
++]);
1521 srcbyte
= (srcbits
+= linebytes
);
1525 /***********************************************************************
1526 * X11DRV_DIB_GetImageBits_8
1528 * GetDIBits for an 8-bit deep DIB.
1530 static void X11DRV_DIB_GetImageBits_8( int lines
, BYTE
*dstbits
,
1531 DWORD srcwidth
, DWORD dstwidth
,
1532 RGBQUAD
*colors
, PALETTEENTRY
*srccolors
,
1533 XImage
*bmpImage
, DWORD linebytes
)
1536 int h
, width
= min(srcwidth
, dstwidth
);
1542 dstbits
= dstbits
+ ( linebytes
* (lines
-1) );
1543 linebytes
= -linebytes
;
1548 * This condition is true when GetImageBits has been called by
1549 * UpdateDIBSection. For now, GetNearestIndex is too slow to support
1550 * 256 colormaps, so we'll just use for for GetDIBits calls.
1551 * (In somes cases, in a updateDIBSection, the returned colors are bad too)
1553 if (!srccolors
) goto updatesection
;
1555 switch (bmpImage
->depth
) {
1558 if (bmpImage
->red_mask
==0 && bmpImage
->green_mask
==0 && bmpImage
->blue_mask
==0 && srccolors
) {
1560 /* ==== pal 1 bmp -> pal 8 dib ==== */
1561 /* ==== pal 4 bmp -> pal 8 dib ==== */
1562 for (h
=lines
-1; h
>=0; h
--) {
1564 for (x
=0; x
<width
; x
++) {
1565 PALETTEENTRY srcval
;
1566 srcval
=srccolors
[XGetPixel(bmpImage
, x
, h
)];
1567 *dstbyte
++=X11DRV_DIB_GetNearestIndex(colors
, 256,
1572 dstbits
+= linebytes
;
1580 if (bmpImage
->red_mask
==0 && bmpImage
->green_mask
==0 && bmpImage
->blue_mask
==0 && srccolors
) {
1581 /* ==== pal 8 bmp -> pal 8 dib ==== */
1582 const void* srcbits
;
1583 const BYTE
* srcpixel
;
1585 srcbits
=bmpImage
->data
+(lines
-1)*bmpImage
->bytes_per_line
;
1586 for (h
=0; h
<lines
; h
++) {
1589 for (x
= 0; x
< width
; x
++) {
1590 PALETTEENTRY srcval
;
1591 srcval
=srccolors
[(int)*srcpixel
++];
1592 *dstbyte
++=X11DRV_DIB_GetNearestIndex(colors
, 256,
1597 srcbits
= (const char*)srcbits
- bmpImage
->bytes_per_line
;
1598 dstbits
+= linebytes
;
1608 const void* srcbits
;
1609 const WORD
* srcpixel
;
1612 srcbits
=bmpImage
->data
+(lines
-1)*bmpImage
->bytes_per_line
;
1614 if (bmpImage
->green_mask
==0x03e0) {
1615 if (bmpImage
->red_mask
==0x7c00) {
1616 /* ==== rgb 555 bmp -> pal 8 dib ==== */
1617 for (h
=0; h
<lines
; h
++) {
1620 for (x
=0; x
<width
; x
++) {
1623 *dstbyte
++=X11DRV_DIB_GetNearestIndex
1625 ((srcval
>> 7) & 0xf8) | /* r */
1626 ((srcval
>> 12) & 0x07),
1627 ((srcval
>> 2) & 0xf8) | /* g */
1628 ((srcval
>> 7) & 0x07),
1629 ((srcval
<< 3) & 0xf8) | /* b */
1630 ((srcval
>> 2) & 0x07) );
1632 srcbits
= (const char*)srcbits
- bmpImage
->bytes_per_line
;
1633 dstbits
+= linebytes
;
1635 } else if (bmpImage
->blue_mask
==0x7c00) {
1636 /* ==== bgr 555 bmp -> pal 8 dib ==== */
1637 for (h
=0; h
<lines
; h
++) {
1640 for (x
=0; x
<width
; x
++) {
1643 *dstbyte
++=X11DRV_DIB_GetNearestIndex
1645 ((srcval
<< 3) & 0xf8) | /* r */
1646 ((srcval
>> 2) & 0x07),
1647 ((srcval
>> 2) & 0xf8) | /* g */
1648 ((srcval
>> 7) & 0x07),
1649 ((srcval
>> 7) & 0xf8) | /* b */
1650 ((srcval
>> 12) & 0x07) );
1652 srcbits
= (const char*)srcbits
- bmpImage
->bytes_per_line
;
1653 dstbits
+= linebytes
;
1658 } else if (bmpImage
->green_mask
==0x07e0) {
1659 if (bmpImage
->red_mask
==0xf800) {
1660 /* ==== rgb 565 bmp -> pal 8 dib ==== */
1661 for (h
=0; h
<lines
; h
++) {
1664 for (x
=0; x
<width
; x
++) {
1667 *dstbyte
++=X11DRV_DIB_GetNearestIndex
1669 ((srcval
>> 8) & 0xf8) | /* r */
1670 ((srcval
>> 13) & 0x07),
1671 ((srcval
>> 3) & 0xfc) | /* g */
1672 ((srcval
>> 9) & 0x03),
1673 ((srcval
<< 3) & 0xf8) | /* b */
1674 ((srcval
>> 2) & 0x07) );
1676 srcbits
= (const char*)srcbits
- bmpImage
->bytes_per_line
;
1677 dstbits
+= linebytes
;
1679 } else if (bmpImage
->blue_mask
==0xf800) {
1680 /* ==== bgr 565 bmp -> pal 8 dib ==== */
1681 for (h
=0; h
<lines
; h
++) {
1684 for (x
=0; x
<width
; x
++) {
1687 *dstbyte
++=X11DRV_DIB_GetNearestIndex
1689 ((srcval
<< 3) & 0xf8) | /* r */
1690 ((srcval
>> 2) & 0x07),
1691 ((srcval
>> 3) & 0xfc) | /* g */
1692 ((srcval
>> 9) & 0x03),
1693 ((srcval
>> 8) & 0xf8) | /* b */
1694 ((srcval
>> 13) & 0x07) );
1696 srcbits
= (const char*)srcbits
- bmpImage
->bytes_per_line
;
1697 dstbits
+= linebytes
;
1711 const void* srcbits
;
1712 const BYTE
*srcbyte
;
1714 int bytes_per_pixel
;
1716 srcbits
=bmpImage
->data
+(lines
-1)*bmpImage
->bytes_per_line
;
1717 bytes_per_pixel
=(bmpImage
->bits_per_pixel
==24?3:4);
1719 if (bmpImage
->green_mask
!=0x00ff00 ||
1720 (bmpImage
->red_mask
|bmpImage
->blue_mask
)!=0xff00ff) {
1722 } else if (bmpImage
->blue_mask
==0xff) {
1723 /* ==== rgb 888 or 0888 bmp -> pal 8 dib ==== */
1724 for (h
=0; h
<lines
; h
++) {
1727 for (x
=0; x
<width
; x
++) {
1728 *dstbyte
++=X11DRV_DIB_GetNearestIndex
1733 srcbyte
+=bytes_per_pixel
;
1735 srcbits
= (const char*)srcbits
- bmpImage
->bytes_per_line
;
1736 dstbits
+= linebytes
;
1739 /* ==== bgr 888 or 0888 bmp -> pal 8 dib ==== */
1740 for (h
=0; h
<lines
; h
++) {
1743 for (x
=0; x
<width
; x
++) {
1744 *dstbyte
++=X11DRV_DIB_GetNearestIndex
1749 srcbyte
+=bytes_per_pixel
;
1751 srcbits
= (const char*)srcbits
- bmpImage
->bytes_per_line
;
1752 dstbits
+= linebytes
;
1760 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 8 bit DIB\n",
1761 bmpImage
->depth
, bmpImage
->red_mask
,
1762 bmpImage
->green_mask
, bmpImage
->blue_mask
);
1764 /* ==== any bmp format -> pal 8 dib ==== */
1765 for (h
=lines
-1; h
>=0; h
--) {
1767 for (x
=0; x
<width
; x
++) {
1768 *dstbyte
=X11DRV_DIB_MapColor
1770 XGetPixel(bmpImage
, x
, h
), *dstbyte
);
1773 dstbits
+= linebytes
;
1779 /***********************************************************************
1780 * X11DRV_DIB_SetImageBits_RLE8
1782 * SetDIBits for an 8-bit deep compressed DIB.
1784 * This function rewritten 941113 by James Youngman. WINE blew out when I
1785 * first ran it because my desktop wallpaper is a (large) RLE8 bitmap.
1787 * This was because the algorithm assumed that all RLE8 bitmaps end with the
1788 * 'End of bitmap' escape code. This code is very much laxer in what it
1789 * allows to end the expansion. Possibly too lax. See the note by
1790 * case RleDelta. BTW, MS's documentation implies that a correct RLE8
1791 * bitmap should end with RleEnd, but on the other hand, software exists
1792 * that produces ones that don't and Windows 3.1 doesn't complain a bit
1795 * (No) apologies for my English spelling. [Emacs users: c-indent-level=4].
1796 * James A. Youngman <mbcstjy@afs.man.ac.uk>
1799 static void X11DRV_DIB_SetImageBits_RLE8( int lines
, const BYTE
*bits
,
1800 DWORD srcwidth
, DWORD dstwidth
,
1801 int left
, int *colors
,
1804 unsigned int x
; /* X-position on each line. Increases. */
1805 int y
; /* Line #. Starts at lines-1, decreases */
1806 const BYTE
*pIn
= bits
; /* Pointer to current position in bits */
1807 BYTE length
; /* The length pf a run */
1808 BYTE escape_code
; /* See enum Rle8_EscapeCodes.*/
1811 * Note that the bitmap data is stored by Windows starting at the
1812 * bottom line of the bitmap and going upwards. Within each line,
1813 * the data is stored left-to-right. That's the reason why line
1814 * goes from lines-1 to 0. [JAY]
1824 * If the length byte is not zero (which is the escape value),
1825 * We have a run of length pixels all the same colour. The colour
1826 * index is stored next.
1828 * If the length byte is zero, we need to read the next byte to
1829 * know what to do. [JAY]
1834 * [Run-Length] Encoded mode
1836 int color
= colors
[*pIn
++];
1837 while (length
-- && x
< (left
+ dstwidth
)) {
1838 if( x
>= left
) XPutPixel(bmpImage
, x
, y
, color
);
1845 * Escape codes (may be an absolute sequence though)
1847 escape_code
= (*pIn
++);
1856 /* Not all RLE8 bitmaps end with this code. For
1857 * example, Paint Shop Pro produces some that don't.
1858 * That's (I think) what caused the previous
1859 * implementation to fail. [JAY]
1868 default: /* switch to absolute mode */
1869 length
= escape_code
;
1872 int color
= colors
[*pIn
++];
1873 if (x
>= (left
+ dstwidth
))
1878 if( x
>= left
) XPutPixel(bmpImage
, x
, y
, color
);
1882 * If you think for a moment you'll realise that the
1883 * only time we could ever possibly read an odd
1884 * number of bytes is when there is a 0x00 (escape),
1885 * a value >0x02 (absolute mode) and then an odd-
1886 * length run. Therefore this is the only place we
1887 * need to worry about it. Everywhere else the
1888 * bytes are always read in pairs. [JAY]
1890 if (escape_code
& 1) pIn
++; /* Throw away the pad byte. */
1892 } /* switch (escape_code) : Escape sequence */
1898 /***********************************************************************
1899 * X11DRV_DIB_SetImageBits_16
1901 * SetDIBits for a 16-bit deep DIB.
1903 static void X11DRV_DIB_SetImageBits_16( int lines
, const BYTE
*srcbits
,
1904 DWORD srcwidth
, DWORD dstwidth
, int left
,
1905 X11DRV_PDEVICE
*physDev
, DWORD rSrc
, DWORD gSrc
, DWORD bSrc
,
1906 XImage
*bmpImage
, DWORD linebytes
)
1909 int h
, width
= min(srcwidth
, dstwidth
);
1910 const dib_conversions
*convs
= (bmpImage
->byte_order
== LSBFirst
) ? &dib_normal
: &dib_dst_byteswap
;
1915 srcbits
= srcbits
+ ( linebytes
* (lines
-1));
1916 linebytes
= -linebytes
;
1919 switch (bmpImage
->depth
)
1926 srcbits
=srcbits
+left
*2;
1927 dstbits
=bmpImage
->data
+left
*2+(lines
-1)*bmpImage
->bytes_per_line
;
1929 if (bmpImage
->green_mask
==0x03e0) {
1930 if (gSrc
==bmpImage
->green_mask
) {
1931 if (rSrc
==bmpImage
->red_mask
) {
1932 /* ==== rgb 555 dib -> rgb 555 bmp ==== */
1933 /* ==== bgr 555 dib -> bgr 555 bmp ==== */
1934 convs
->Convert_5x5_asis
1937 dstbits
,-bmpImage
->bytes_per_line
);
1938 } else if (rSrc
==bmpImage
->blue_mask
) {
1939 /* ==== rgb 555 dib -> bgr 555 bmp ==== */
1940 /* ==== bgr 555 dib -> rgb 555 bmp ==== */
1941 convs
->Convert_555_reverse
1944 dstbits
,-bmpImage
->bytes_per_line
);
1947 if (rSrc
==bmpImage
->red_mask
|| bSrc
==bmpImage
->blue_mask
) {
1948 /* ==== rgb 565 dib -> rgb 555 bmp ==== */
1949 /* ==== bgr 565 dib -> bgr 555 bmp ==== */
1950 convs
->Convert_565_to_555_asis
1953 dstbits
,-bmpImage
->bytes_per_line
);
1955 /* ==== rgb 565 dib -> bgr 555 bmp ==== */
1956 /* ==== bgr 565 dib -> rgb 555 bmp ==== */
1957 convs
->Convert_565_to_555_reverse
1960 dstbits
,-bmpImage
->bytes_per_line
);
1963 } else if (bmpImage
->green_mask
==0x07e0) {
1964 if (gSrc
==bmpImage
->green_mask
) {
1965 if (rSrc
==bmpImage
->red_mask
) {
1966 /* ==== rgb 565 dib -> rgb 565 bmp ==== */
1967 /* ==== bgr 565 dib -> bgr 565 bmp ==== */
1968 convs
->Convert_5x5_asis
1971 dstbits
,-bmpImage
->bytes_per_line
);
1973 /* ==== rgb 565 dib -> bgr 565 bmp ==== */
1974 /* ==== bgr 565 dib -> rgb 565 bmp ==== */
1975 convs
->Convert_565_reverse
1978 dstbits
,-bmpImage
->bytes_per_line
);
1981 if (rSrc
==bmpImage
->red_mask
|| bSrc
==bmpImage
->blue_mask
) {
1982 /* ==== rgb 555 dib -> rgb 565 bmp ==== */
1983 /* ==== bgr 555 dib -> bgr 565 bmp ==== */
1984 convs
->Convert_555_to_565_asis
1987 dstbits
,-bmpImage
->bytes_per_line
);
1989 /* ==== rgb 555 dib -> bgr 565 bmp ==== */
1990 /* ==== bgr 555 dib -> rgb 565 bmp ==== */
1991 convs
->Convert_555_to_565_reverse
1994 dstbits
,-bmpImage
->bytes_per_line
);
2004 if (bmpImage
->bits_per_pixel
==24) {
2007 srcbits
=srcbits
+left
*2;
2008 dstbits
=bmpImage
->data
+left
*3+(lines
-1)*bmpImage
->bytes_per_line
;
2010 if (bmpImage
->green_mask
!=0x00ff00 ||
2011 (bmpImage
->red_mask
|bmpImage
->blue_mask
)!=0xff00ff) {
2013 } else if ((rSrc
==0x1f && bmpImage
->red_mask
==0xff) ||
2014 (bSrc
==0x1f && bmpImage
->blue_mask
==0xff)) {
2016 /* ==== rgb 555 dib -> rgb 888 bmp ==== */
2017 /* ==== bgr 555 dib -> bgr 888 bmp ==== */
2018 convs
->Convert_555_to_888_asis
2021 dstbits
,-bmpImage
->bytes_per_line
);
2023 /* ==== rgb 565 dib -> rgb 888 bmp ==== */
2024 /* ==== bgr 565 dib -> bgr 888 bmp ==== */
2025 convs
->Convert_565_to_888_asis
2028 dstbits
,-bmpImage
->bytes_per_line
);
2032 /* ==== rgb 555 dib -> bgr 888 bmp ==== */
2033 /* ==== bgr 555 dib -> rgb 888 bmp ==== */
2034 convs
->Convert_555_to_888_reverse
2037 dstbits
,-bmpImage
->bytes_per_line
);
2039 /* ==== rgb 565 dib -> bgr 888 bmp ==== */
2040 /* ==== bgr 565 dib -> rgb 888 bmp ==== */
2041 convs
->Convert_565_to_888_reverse
2044 dstbits
,-bmpImage
->bytes_per_line
);
2055 srcbits
=srcbits
+left
*2;
2056 dstbits
=bmpImage
->data
+left
*4+(lines
-1)*bmpImage
->bytes_per_line
;
2058 if (bmpImage
->green_mask
!=0x00ff00 ||
2059 (bmpImage
->red_mask
|bmpImage
->blue_mask
)!=0xff00ff) {
2061 } else if ((rSrc
==0x1f && bmpImage
->red_mask
==0xff) ||
2062 (bSrc
==0x1f && bmpImage
->blue_mask
==0xff)) {
2064 /* ==== rgb 555 dib -> rgb 0888 bmp ==== */
2065 /* ==== bgr 555 dib -> bgr 0888 bmp ==== */
2066 convs
->Convert_555_to_0888_asis
2069 dstbits
,-bmpImage
->bytes_per_line
);
2071 /* ==== rgb 565 dib -> rgb 0888 bmp ==== */
2072 /* ==== bgr 565 dib -> bgr 0888 bmp ==== */
2073 convs
->Convert_565_to_0888_asis
2076 dstbits
,-bmpImage
->bytes_per_line
);
2080 /* ==== rgb 555 dib -> bgr 0888 bmp ==== */
2081 /* ==== bgr 555 dib -> rgb 0888 bmp ==== */
2082 convs
->Convert_555_to_0888_reverse
2085 dstbits
,-bmpImage
->bytes_per_line
);
2087 /* ==== rgb 565 dib -> bgr 0888 bmp ==== */
2088 /* ==== bgr 565 dib -> rgb 0888 bmp ==== */
2089 convs
->Convert_565_to_0888_reverse
2092 dstbits
,-bmpImage
->bytes_per_line
);
2100 WARN("from 16 bit DIB (%lx,%lx,%lx) to unknown %d bit bitmap (%lx,%lx,%lx)\n",
2101 rSrc
, gSrc
, bSrc
, bmpImage
->bits_per_pixel
, bmpImage
->red_mask
,
2102 bmpImage
->green_mask
, bmpImage
->blue_mask
);
2108 /* ==== rgb or bgr 555 or 565 dib -> pal 1, 4 or 8 ==== */
2109 const WORD
* srcpixel
;
2110 int rShift1
,gShift1
,bShift1
;
2111 int rShift2
,gShift2
,bShift2
;
2114 /* Set color scaling values */
2115 rShift1
=16+X11DRV_DIB_MaskToShift(rSrc
)-3;
2116 gShift1
=16+X11DRV_DIB_MaskToShift(gSrc
)-3;
2117 bShift1
=16+X11DRV_DIB_MaskToShift(bSrc
)-3;
2122 /* Green has 5 bits, like the others */
2126 /* Green has 6 bits, not 5. Compensate. */
2135 /* We could split it into four separate cases to optimize
2136 * but it is probably not worth it.
2138 for (h
=lines
-1; h
>=0; h
--) {
2139 srcpixel
=(const WORD
*)srcbits
;
2140 for (x
=left
; x
<width
+left
; x
++) {
2142 BYTE red
,green
,blue
;
2143 srcval
=*srcpixel
++ << 16;
2144 red
= ((srcval
>> rShift1
) & 0xf8) |
2145 ((srcval
>> rShift2
) & 0x07);
2146 green
=((srcval
>> gShift1
) & gMask1
) |
2147 ((srcval
>> gShift2
) & gMask2
);
2148 blue
= ((srcval
>> bShift1
) & 0xf8) |
2149 ((srcval
>> bShift2
) & 0x07);
2150 XPutPixel(bmpImage
, x
, h
,
2151 X11DRV_PALETTE_ToPhysical
2152 (physDev
, RGB(red
,green
,blue
)));
2154 srcbits
+= linebytes
;
2162 /***********************************************************************
2163 * X11DRV_DIB_GetImageBits_16
2165 * GetDIBits for an 16-bit deep DIB.
2167 static void X11DRV_DIB_GetImageBits_16( int lines
, BYTE
*dstbits
,
2168 DWORD dstwidth
, DWORD srcwidth
,
2169 PALETTEENTRY
*srccolors
,
2170 DWORD rDst
, DWORD gDst
, DWORD bDst
,
2171 XImage
*bmpImage
, DWORD dibpitch
)
2174 int h
, width
= min(srcwidth
, dstwidth
);
2175 const dib_conversions
*convs
= (bmpImage
->byte_order
== LSBFirst
) ? &dib_normal
: &dib_src_byteswap
;
2177 DWORD linebytes
= dibpitch
;
2182 dstbits
= dstbits
+ ( linebytes
* (lines
-1));
2183 linebytes
= -linebytes
;
2186 switch (bmpImage
->depth
)
2191 const char* srcbits
;
2193 srcbits
=bmpImage
->data
+(lines
-1)*bmpImage
->bytes_per_line
;
2195 if (bmpImage
->green_mask
==0x03e0) {
2196 if (gDst
==bmpImage
->green_mask
) {
2197 if (rDst
==bmpImage
->red_mask
) {
2198 /* ==== rgb 555 bmp -> rgb 555 dib ==== */
2199 /* ==== bgr 555 bmp -> bgr 555 dib ==== */
2200 convs
->Convert_5x5_asis
2202 srcbits
,-bmpImage
->bytes_per_line
,
2205 /* ==== rgb 555 bmp -> bgr 555 dib ==== */
2206 /* ==== bgr 555 bmp -> rgb 555 dib ==== */
2207 convs
->Convert_555_reverse
2209 srcbits
,-bmpImage
->bytes_per_line
,
2213 if (rDst
==bmpImage
->red_mask
|| bDst
==bmpImage
->blue_mask
) {
2214 /* ==== rgb 555 bmp -> rgb 565 dib ==== */
2215 /* ==== bgr 555 bmp -> bgr 565 dib ==== */
2216 convs
->Convert_555_to_565_asis
2218 srcbits
,-bmpImage
->bytes_per_line
,
2221 /* ==== rgb 555 bmp -> bgr 565 dib ==== */
2222 /* ==== bgr 555 bmp -> rgb 565 dib ==== */
2223 convs
->Convert_555_to_565_reverse
2225 srcbits
,-bmpImage
->bytes_per_line
,
2229 } else if (bmpImage
->green_mask
==0x07e0) {
2230 if (gDst
==bmpImage
->green_mask
) {
2231 if (rDst
== bmpImage
->red_mask
) {
2232 /* ==== rgb 565 bmp -> rgb 565 dib ==== */
2233 /* ==== bgr 565 bmp -> bgr 565 dib ==== */
2234 convs
->Convert_5x5_asis
2236 srcbits
,-bmpImage
->bytes_per_line
,
2239 /* ==== rgb 565 bmp -> bgr 565 dib ==== */
2240 /* ==== bgr 565 bmp -> rgb 565 dib ==== */
2241 convs
->Convert_565_reverse
2243 srcbits
,-bmpImage
->bytes_per_line
,
2247 if (rDst
==bmpImage
->red_mask
|| bDst
==bmpImage
->blue_mask
) {
2248 /* ==== rgb 565 bmp -> rgb 555 dib ==== */
2249 /* ==== bgr 565 bmp -> bgr 555 dib ==== */
2250 convs
->Convert_565_to_555_asis
2252 srcbits
,-bmpImage
->bytes_per_line
,
2255 /* ==== rgb 565 bmp -> bgr 555 dib ==== */
2256 /* ==== bgr 565 bmp -> rgb 555 dib ==== */
2257 convs
->Convert_565_to_555_reverse
2259 srcbits
,-bmpImage
->bytes_per_line
,
2270 if (bmpImage
->bits_per_pixel
== 24) {
2271 const char* srcbits
;
2273 srcbits
=bmpImage
->data
+(lines
-1)*bmpImage
->bytes_per_line
;
2275 if (bmpImage
->green_mask
!=0x00ff00 ||
2276 (bmpImage
->red_mask
|bmpImage
->blue_mask
)!=0xff00ff) {
2278 } else if ((rDst
==0x1f && bmpImage
->red_mask
==0xff) ||
2279 (bDst
==0x1f && bmpImage
->blue_mask
==0xff)) {
2281 /* ==== rgb 888 bmp -> rgb 555 dib ==== */
2282 /* ==== bgr 888 bmp -> bgr 555 dib ==== */
2283 convs
->Convert_888_to_555_asis
2285 srcbits
,-bmpImage
->bytes_per_line
,
2288 /* ==== rgb 888 bmp -> rgb 565 dib ==== */
2289 /* ==== rgb 888 bmp -> rgb 565 dib ==== */
2290 convs
->Convert_888_to_565_asis
2292 srcbits
,-bmpImage
->bytes_per_line
,
2297 /* ==== rgb 888 bmp -> bgr 555 dib ==== */
2298 /* ==== bgr 888 bmp -> rgb 555 dib ==== */
2299 convs
->Convert_888_to_555_reverse
2301 srcbits
,-bmpImage
->bytes_per_line
,
2304 /* ==== rgb 888 bmp -> bgr 565 dib ==== */
2305 /* ==== bgr 888 bmp -> rgb 565 dib ==== */
2306 convs
->Convert_888_to_565_reverse
2308 srcbits
,-bmpImage
->bytes_per_line
,
2318 const char* srcbits
;
2320 srcbits
=bmpImage
->data
+(lines
-1)*bmpImage
->bytes_per_line
;
2322 if (bmpImage
->green_mask
!=0x00ff00 ||
2323 (bmpImage
->red_mask
|bmpImage
->blue_mask
)!=0xff00ff) {
2325 } else if ((rDst
==0x1f && bmpImage
->red_mask
==0xff) ||
2326 (bDst
==0x1f && bmpImage
->blue_mask
==0xff)) {
2328 /* ==== rgb 0888 bmp -> rgb 555 dib ==== */
2329 /* ==== bgr 0888 bmp -> bgr 555 dib ==== */
2330 convs
->Convert_0888_to_555_asis
2332 srcbits
,-bmpImage
->bytes_per_line
,
2335 /* ==== rgb 0888 bmp -> rgb 565 dib ==== */
2336 /* ==== bgr 0888 bmp -> bgr 565 dib ==== */
2337 convs
->Convert_0888_to_565_asis
2339 srcbits
,-bmpImage
->bytes_per_line
,
2344 /* ==== rgb 0888 bmp -> bgr 555 dib ==== */
2345 /* ==== bgr 0888 bmp -> rgb 555 dib ==== */
2346 convs
->Convert_0888_to_555_reverse
2348 srcbits
,-bmpImage
->bytes_per_line
,
2351 /* ==== rgb 0888 bmp -> bgr 565 dib ==== */
2352 /* ==== bgr 0888 bmp -> rgb 565 dib ==== */
2353 convs
->Convert_0888_to_565_reverse
2355 srcbits
,-bmpImage
->bytes_per_line
,
2364 if (bmpImage
->red_mask
==0 && bmpImage
->green_mask
==0 && bmpImage
->blue_mask
==0 && srccolors
) {
2365 /* ==== pal 1 or 4 bmp -> rgb or bgr 555 or 565 dib ==== */
2366 int rShift
,gShift
,bShift
;
2369 /* Shift everything 16 bits left so that all shifts are >0,
2370 * even for BGR DIBs. Then a single >> 16 will bring everything
2373 rShift
=16+X11DRV_DIB_MaskToShift(rDst
)-3;
2374 gShift
=16+X11DRV_DIB_MaskToShift(gDst
)-3;
2375 bShift
=16+X11DRV_DIB_MaskToShift(bDst
)-3;
2377 /* 6 bits for the green */
2383 for (h
= lines
- 1; h
>= 0; h
--) {
2384 dstpixel
=(LPWORD
)dstbits
;
2385 for (x
= 0; x
< width
; x
++) {
2386 PALETTEENTRY srcval
;
2388 srcval
=srccolors
[XGetPixel(bmpImage
, x
, h
)];
2389 dstval
=((srcval
.peRed
<< rShift
) & rDst
) |
2390 ((srcval
.peGreen
<< gShift
) & gDst
) |
2391 ((srcval
.peBlue
<< bShift
) & bDst
);
2392 *dstpixel
++=dstval
>> 16;
2394 dstbits
+= linebytes
;
2402 if (bmpImage
->red_mask
==0 && bmpImage
->green_mask
==0 && bmpImage
->blue_mask
==0 && srccolors
) {
2403 /* ==== pal 8 bmp -> rgb or bgr 555 or 565 dib ==== */
2404 int rShift
,gShift
,bShift
;
2405 const BYTE
* srcbits
;
2406 const BYTE
* srcpixel
;
2409 /* Shift everything 16 bits left so that all shifts are >0,
2410 * even for BGR DIBs. Then a single >> 16 will bring everything
2413 rShift
=16+X11DRV_DIB_MaskToShift(rDst
)-3;
2414 gShift
=16+X11DRV_DIB_MaskToShift(gDst
)-3;
2415 bShift
=16+X11DRV_DIB_MaskToShift(bDst
)-3;
2417 /* 6 bits for the green */
2423 srcbits
=bmpImage
->data
+(lines
-1)*bmpImage
->bytes_per_line
;
2424 for (h
=0; h
<lines
; h
++) {
2426 dstpixel
=(LPWORD
)dstbits
;
2427 for (x
= 0; x
< width
; x
++) {
2428 PALETTEENTRY srcval
;
2430 srcval
=srccolors
[(int)*srcpixel
++];
2431 dstval
=((srcval
.peRed
<< rShift
) & rDst
) |
2432 ((srcval
.peGreen
<< gShift
) & gDst
) |
2433 ((srcval
.peBlue
<< bShift
) & bDst
);
2434 *dstpixel
++=dstval
>> 16;
2436 srcbits
-= bmpImage
->bytes_per_line
;
2437 dstbits
+= linebytes
;
2447 /* ==== any bmp format -> rgb or bgr 555 or 565 dib ==== */
2448 int rShift
,gShift
,bShift
;
2451 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 16 bit DIB (%lx,%lx,%lx)\n",
2452 bmpImage
->depth
, bmpImage
->red_mask
,
2453 bmpImage
->green_mask
, bmpImage
->blue_mask
,
2456 /* Shift everything 16 bits left so that all shifts are >0,
2457 * even for BGR DIBs. Then a single >> 16 will bring everything
2460 rShift
=16+X11DRV_DIB_MaskToShift(rDst
)-3;
2461 gShift
=16+X11DRV_DIB_MaskToShift(gDst
)-3;
2462 bShift
=16+X11DRV_DIB_MaskToShift(bDst
)-3;
2464 /* 6 bits for the green */
2470 for (h
= lines
- 1; h
>= 0; h
--) {
2471 dstpixel
=(LPWORD
)dstbits
;
2472 for (x
= 0; x
< width
; x
++) {
2475 srcval
=X11DRV_PALETTE_ToLogical(XGetPixel(bmpImage
, x
, h
));
2476 dstval
=((GetRValue(srcval
) << rShift
) & rDst
) |
2477 ((GetGValue(srcval
) << gShift
) & gDst
) |
2478 ((GetBValue(srcval
) << bShift
) & bDst
);
2479 *dstpixel
++=dstval
>> 16;
2481 dstbits
+= linebytes
;
2489 /***********************************************************************
2490 * X11DRV_DIB_SetImageBits_24
2492 * SetDIBits for a 24-bit deep DIB.
2494 static void X11DRV_DIB_SetImageBits_24( int lines
, const BYTE
*srcbits
,
2495 DWORD srcwidth
, DWORD dstwidth
, int left
,
2496 X11DRV_PDEVICE
*physDev
,
2497 DWORD rSrc
, DWORD gSrc
, DWORD bSrc
,
2498 XImage
*bmpImage
, DWORD linebytes
)
2501 int h
, width
= min(srcwidth
, dstwidth
);
2502 const dib_conversions
*convs
= (bmpImage
->byte_order
== LSBFirst
) ? &dib_normal
: &dib_dst_byteswap
;
2507 srcbits
= srcbits
+ linebytes
* (lines
- 1);
2508 linebytes
= -linebytes
;
2511 switch (bmpImage
->depth
)
2514 if (bmpImage
->bits_per_pixel
==24) {
2517 srcbits
=srcbits
+left
*3;
2518 dstbits
=bmpImage
->data
+left
*3+(lines
-1)*bmpImage
->bytes_per_line
;
2520 if (bmpImage
->green_mask
!=0x00ff00 ||
2521 (bmpImage
->red_mask
|bmpImage
->blue_mask
)!=0xff00ff) {
2523 } else if (rSrc
==bmpImage
->red_mask
) {
2524 /* ==== rgb 888 dib -> rgb 888 bmp ==== */
2525 /* ==== bgr 888 dib -> bgr 888 bmp ==== */
2526 convs
->Convert_888_asis
2529 dstbits
,-bmpImage
->bytes_per_line
);
2531 /* ==== rgb 888 dib -> bgr 888 bmp ==== */
2532 /* ==== bgr 888 dib -> rgb 888 bmp ==== */
2533 convs
->Convert_888_reverse
2536 dstbits
,-bmpImage
->bytes_per_line
);
2546 srcbits
=srcbits
+left
*3;
2547 dstbits
=bmpImage
->data
+left
*4+(lines
-1)*bmpImage
->bytes_per_line
;
2549 if (bmpImage
->green_mask
!=0x00ff00 ||
2550 (bmpImage
->red_mask
|bmpImage
->blue_mask
)!=0xff00ff) {
2552 } else if (rSrc
==bmpImage
->red_mask
) {
2553 /* ==== rgb 888 dib -> rgb 0888 bmp ==== */
2554 /* ==== bgr 888 dib -> bgr 0888 bmp ==== */
2555 convs
->Convert_888_to_0888_asis
2558 dstbits
,-bmpImage
->bytes_per_line
);
2560 /* ==== rgb 888 dib -> bgr 0888 bmp ==== */
2561 /* ==== bgr 888 dib -> rgb 0888 bmp ==== */
2562 convs
->Convert_888_to_0888_reverse
2565 dstbits
,-bmpImage
->bytes_per_line
);
2575 srcbits
=srcbits
+left
*3;
2576 dstbits
=bmpImage
->data
+left
*2+(lines
-1)*bmpImage
->bytes_per_line
;
2578 if (bmpImage
->green_mask
==0x03e0) {
2579 if ((rSrc
==0xff0000 && bmpImage
->red_mask
==0x7f00) ||
2580 (bSrc
==0xff0000 && bmpImage
->blue_mask
==0x7f00)) {
2581 /* ==== rgb 888 dib -> rgb 555 bmp ==== */
2582 /* ==== bgr 888 dib -> bgr 555 bmp ==== */
2583 convs
->Convert_888_to_555_asis
2586 dstbits
,-bmpImage
->bytes_per_line
);
2587 } else if ((rSrc
==0xff && bmpImage
->red_mask
==0x7f00) ||
2588 (bSrc
==0xff && bmpImage
->blue_mask
==0x7f00)) {
2589 /* ==== rgb 888 dib -> bgr 555 bmp ==== */
2590 /* ==== bgr 888 dib -> rgb 555 bmp ==== */
2591 convs
->Convert_888_to_555_reverse
2594 dstbits
,-bmpImage
->bytes_per_line
);
2598 } else if (bmpImage
->green_mask
==0x07e0) {
2599 if ((rSrc
==0xff0000 && bmpImage
->red_mask
==0xf800) ||
2600 (bSrc
==0xff0000 && bmpImage
->blue_mask
==0xf800)) {
2601 /* ==== rgb 888 dib -> rgb 565 bmp ==== */
2602 /* ==== bgr 888 dib -> bgr 565 bmp ==== */
2603 convs
->Convert_888_to_565_asis
2606 dstbits
,-bmpImage
->bytes_per_line
);
2607 } else if ((rSrc
==0xff && bmpImage
->red_mask
==0xf800) ||
2608 (bSrc
==0xff && bmpImage
->blue_mask
==0xf800)) {
2609 /* ==== rgb 888 dib -> bgr 565 bmp ==== */
2610 /* ==== bgr 888 dib -> rgb 565 bmp ==== */
2611 convs
->Convert_888_to_565_reverse
2614 dstbits
,-bmpImage
->bytes_per_line
);
2626 WARN("from 24 bit DIB (%lx,%lx,%lx) to unknown %d bit bitmap (%lx,%lx,%lx)\n",
2627 rSrc
, gSrc
, bSrc
, bmpImage
->bits_per_pixel
, bmpImage
->red_mask
,
2628 bmpImage
->green_mask
, bmpImage
->blue_mask
);
2634 /* ==== rgb 888 dib -> any bmp bormat ==== */
2635 const BYTE
* srcbyte
;
2637 /* Windows only supports one 24bpp DIB format: RGB888 */
2639 for (h
= lines
- 1; h
>= 0; h
--) {
2640 srcbyte
=(const BYTE
*)srcbits
;
2641 for (x
= left
; x
< width
+left
; x
++) {
2642 XPutPixel(bmpImage
, x
, h
,
2643 X11DRV_PALETTE_ToPhysical
2644 (physDev
, RGB(srcbyte
[2], srcbyte
[1], srcbyte
[0])));
2647 srcbits
+= linebytes
;
2655 /***********************************************************************
2656 * X11DRV_DIB_GetImageBits_24
2658 * GetDIBits for an 24-bit deep DIB.
2660 static void X11DRV_DIB_GetImageBits_24( int lines
, BYTE
*dstbits
,
2661 DWORD dstwidth
, DWORD srcwidth
,
2662 PALETTEENTRY
*srccolors
,
2663 DWORD rDst
, DWORD gDst
, DWORD bDst
,
2664 XImage
*bmpImage
, DWORD linebytes
)
2667 int h
, width
= min(srcwidth
, dstwidth
);
2668 const dib_conversions
*convs
= (bmpImage
->byte_order
== LSBFirst
) ? &dib_normal
: &dib_src_byteswap
;
2673 dstbits
= dstbits
+ ( linebytes
* (lines
-1) );
2674 linebytes
= -linebytes
;
2677 switch (bmpImage
->depth
)
2680 if (bmpImage
->bits_per_pixel
==24) {
2681 const char* srcbits
;
2683 srcbits
=bmpImage
->data
+(lines
-1)*bmpImage
->bytes_per_line
;
2685 if (bmpImage
->green_mask
!=0x00ff00 ||
2686 (bmpImage
->red_mask
|bmpImage
->blue_mask
)!=0xff00ff) {
2688 } else if (rDst
==bmpImage
->red_mask
) {
2689 /* ==== rgb 888 bmp -> rgb 888 dib ==== */
2690 /* ==== bgr 888 bmp -> bgr 888 dib ==== */
2691 convs
->Convert_888_asis
2693 srcbits
,-bmpImage
->bytes_per_line
,
2696 /* ==== rgb 888 bmp -> bgr 888 dib ==== */
2697 /* ==== bgr 888 bmp -> rgb 888 dib ==== */
2698 convs
->Convert_888_reverse
2700 srcbits
,-bmpImage
->bytes_per_line
,
2709 const char* srcbits
;
2711 srcbits
=bmpImage
->data
+(lines
-1)*bmpImage
->bytes_per_line
;
2713 if (bmpImage
->green_mask
!=0x00ff00 ||
2714 (bmpImage
->red_mask
|bmpImage
->blue_mask
)!=0xff00ff) {
2716 } else if (rDst
==bmpImage
->red_mask
) {
2717 /* ==== rgb 888 bmp -> rgb 0888 dib ==== */
2718 /* ==== bgr 888 bmp -> bgr 0888 dib ==== */
2719 convs
->Convert_0888_to_888_asis
2721 srcbits
,-bmpImage
->bytes_per_line
,
2724 /* ==== rgb 888 bmp -> bgr 0888 dib ==== */
2725 /* ==== bgr 888 bmp -> rgb 0888 dib ==== */
2726 convs
->Convert_0888_to_888_reverse
2728 srcbits
,-bmpImage
->bytes_per_line
,
2737 const char* srcbits
;
2739 srcbits
=bmpImage
->data
+(lines
-1)*bmpImage
->bytes_per_line
;
2741 if (bmpImage
->green_mask
==0x03e0) {
2742 if ((rDst
==0xff0000 && bmpImage
->red_mask
==0x7f00) ||
2743 (bDst
==0xff0000 && bmpImage
->blue_mask
==0x7f00)) {
2744 /* ==== rgb 555 bmp -> rgb 888 dib ==== */
2745 /* ==== bgr 555 bmp -> bgr 888 dib ==== */
2746 convs
->Convert_555_to_888_asis
2748 srcbits
,-bmpImage
->bytes_per_line
,
2750 } else if ((rDst
==0xff && bmpImage
->red_mask
==0x7f00) ||
2751 (bDst
==0xff && bmpImage
->blue_mask
==0x7f00)) {
2752 /* ==== rgb 555 bmp -> bgr 888 dib ==== */
2753 /* ==== bgr 555 bmp -> rgb 888 dib ==== */
2754 convs
->Convert_555_to_888_reverse
2756 srcbits
,-bmpImage
->bytes_per_line
,
2761 } else if (bmpImage
->green_mask
==0x07e0) {
2762 if ((rDst
==0xff0000 && bmpImage
->red_mask
==0xf800) ||
2763 (bDst
==0xff0000 && bmpImage
->blue_mask
==0xf800)) {
2764 /* ==== rgb 565 bmp -> rgb 888 dib ==== */
2765 /* ==== bgr 565 bmp -> bgr 888 dib ==== */
2766 convs
->Convert_565_to_888_asis
2768 srcbits
,-bmpImage
->bytes_per_line
,
2770 } else if ((rDst
==0xff && bmpImage
->red_mask
==0xf800) ||
2771 (bDst
==0xff && bmpImage
->blue_mask
==0xf800)) {
2772 /* ==== rgb 565 bmp -> bgr 888 dib ==== */
2773 /* ==== bgr 565 bmp -> rgb 888 dib ==== */
2774 convs
->Convert_565_to_888_reverse
2776 srcbits
,-bmpImage
->bytes_per_line
,
2789 if (bmpImage
->red_mask
==0 && bmpImage
->green_mask
==0 && bmpImage
->blue_mask
==0 && srccolors
) {
2790 /* ==== pal 1 or 4 bmp -> rgb 888 dib ==== */
2793 /* Windows only supports one 24bpp DIB format: rgb 888 */
2794 for (h
= lines
- 1; h
>= 0; h
--) {
2796 for (x
= 0; x
< width
; x
++) {
2797 PALETTEENTRY srcval
;
2798 srcval
=srccolors
[XGetPixel(bmpImage
, x
, h
)];
2799 dstbyte
[0]=srcval
.peBlue
;
2800 dstbyte
[1]=srcval
.peGreen
;
2801 dstbyte
[2]=srcval
.peRed
;
2804 dstbits
+= linebytes
;
2812 if (bmpImage
->red_mask
==0 && bmpImage
->green_mask
==0 && bmpImage
->blue_mask
== 0 && srccolors
) {
2813 /* ==== pal 8 bmp -> rgb 888 dib ==== */
2814 const void* srcbits
;
2815 const BYTE
* srcpixel
;
2818 /* Windows only supports one 24bpp DIB format: rgb 888 */
2819 srcbits
=bmpImage
->data
+(lines
-1)*bmpImage
->bytes_per_line
;
2820 for (h
= lines
- 1; h
>= 0; h
--) {
2823 for (x
= 0; x
< width
; x
++ ) {
2824 PALETTEENTRY srcval
;
2825 srcval
=srccolors
[(int)*srcpixel
++];
2826 dstbyte
[0]=srcval
.peBlue
;
2827 dstbyte
[1]=srcval
.peGreen
;
2828 dstbyte
[2]=srcval
.peRed
;
2831 srcbits
= (const char*)srcbits
- bmpImage
->bytes_per_line
;
2832 dstbits
+= linebytes
;
2842 /* ==== any bmp format -> 888 dib ==== */
2845 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 24 bit DIB (%lx,%lx,%lx)\n",
2846 bmpImage
->depth
, bmpImage
->red_mask
,
2847 bmpImage
->green_mask
, bmpImage
->blue_mask
,
2850 /* Windows only supports one 24bpp DIB format: rgb 888 */
2851 for (h
= lines
- 1; h
>= 0; h
--) {
2853 for (x
= 0; x
< width
; x
++) {
2854 COLORREF srcval
=X11DRV_PALETTE_ToLogical
2855 (XGetPixel( bmpImage
, x
, h
));
2856 dstbyte
[0]=GetBValue(srcval
);
2857 dstbyte
[1]=GetGValue(srcval
);
2858 dstbyte
[2]=GetRValue(srcval
);
2861 dstbits
+= linebytes
;
2869 /***********************************************************************
2870 * X11DRV_DIB_SetImageBits_32
2872 * SetDIBits for a 32-bit deep DIB.
2874 static void X11DRV_DIB_SetImageBits_32(int lines
, const BYTE
*srcbits
,
2875 DWORD srcwidth
, DWORD dstwidth
, int left
,
2876 X11DRV_PDEVICE
*physDev
,
2877 DWORD rSrc
, DWORD gSrc
, DWORD bSrc
,
2883 int h
, width
= min(srcwidth
, dstwidth
);
2884 const dib_conversions
*convs
= (bmpImage
->byte_order
== LSBFirst
) ? &dib_normal
: &dib_dst_byteswap
;
2889 srcbits
= srcbits
+ ( linebytes
* (lines
-1) );
2890 linebytes
= -linebytes
;
2893 ptr
= (const DWORD
*) srcbits
+ left
;
2895 switch (bmpImage
->depth
)
2898 if (bmpImage
->bits_per_pixel
==24) {
2901 srcbits
=srcbits
+left
*4;
2902 dstbits
=bmpImage
->data
+left
*3+(lines
-1)*bmpImage
->bytes_per_line
;
2904 if (rSrc
==bmpImage
->red_mask
&& gSrc
==bmpImage
->green_mask
&& bSrc
==bmpImage
->blue_mask
) {
2905 /* ==== rgb 0888 dib -> rgb 888 bmp ==== */
2906 /* ==== bgr 0888 dib -> bgr 888 bmp ==== */
2907 convs
->Convert_0888_to_888_asis
2910 dstbits
,-bmpImage
->bytes_per_line
);
2911 } else if (bmpImage
->green_mask
!=0x00ff00 ||
2912 (bmpImage
->red_mask
|bmpImage
->blue_mask
)!=0xff00ff) {
2914 /* the tests below assume sane bmpImage masks */
2915 } else if (rSrc
==bmpImage
->blue_mask
&& gSrc
==bmpImage
->green_mask
&& bSrc
==bmpImage
->red_mask
) {
2916 /* ==== rgb 0888 dib -> bgr 888 bmp ==== */
2917 /* ==== bgr 0888 dib -> rgb 888 bmp ==== */
2918 convs
->Convert_0888_to_888_reverse
2921 dstbits
,-bmpImage
->bytes_per_line
);
2922 } else if (bmpImage
->blue_mask
==0xff) {
2923 /* ==== any 0888 dib -> rgb 888 bmp ==== */
2924 convs
->Convert_any0888_to_rgb888
2928 dstbits
,-bmpImage
->bytes_per_line
);
2930 /* ==== any 0888 dib -> bgr 888 bmp ==== */
2931 convs
->Convert_any0888_to_bgr888
2935 dstbits
,-bmpImage
->bytes_per_line
);
2945 srcbits
=srcbits
+left
*4;
2946 dstbits
=bmpImage
->data
+left
*4+(lines
-1)*bmpImage
->bytes_per_line
;
2948 if (gSrc
==bmpImage
->green_mask
) {
2949 if (rSrc
==bmpImage
->red_mask
&& bSrc
==bmpImage
->blue_mask
) {
2950 /* ==== rgb 0888 dib -> rgb 0888 bmp ==== */
2951 /* ==== bgr 0888 dib -> bgr 0888 bmp ==== */
2952 convs
->Convert_0888_asis
2955 dstbits
,-bmpImage
->bytes_per_line
);
2956 } else if (bmpImage
->green_mask
!=0x00ff00 ||
2957 (bmpImage
->red_mask
|bmpImage
->blue_mask
)!=0xff00ff) {
2959 /* the tests below assume sane bmpImage masks */
2960 } else if (rSrc
==bmpImage
->blue_mask
&& bSrc
==bmpImage
->red_mask
) {
2961 /* ==== rgb 0888 dib -> bgr 0888 bmp ==== */
2962 /* ==== bgr 0888 dib -> rgb 0888 bmp ==== */
2963 convs
->Convert_0888_reverse
2966 dstbits
,-bmpImage
->bytes_per_line
);
2968 /* ==== any 0888 dib -> any 0888 bmp ==== */
2969 convs
->Convert_0888_any
2973 dstbits
,-bmpImage
->bytes_per_line
,
2974 bmpImage
->red_mask
,bmpImage
->green_mask
,bmpImage
->blue_mask
);
2976 } else if (bmpImage
->green_mask
!=0x00ff00 ||
2977 (bmpImage
->red_mask
|bmpImage
->blue_mask
)!=0xff00ff) {
2979 /* the tests below assume sane bmpImage masks */
2981 /* ==== any 0888 dib -> any 0888 bmp ==== */
2982 convs
->Convert_0888_any
2986 dstbits
,-bmpImage
->bytes_per_line
,
2987 bmpImage
->red_mask
,bmpImage
->green_mask
,bmpImage
->blue_mask
);
2997 srcbits
=srcbits
+left
*4;
2998 dstbits
=bmpImage
->data
+left
*2+(lines
-1)*bmpImage
->bytes_per_line
;
3000 if (rSrc
==0xff0000 && gSrc
==0x00ff00 && bSrc
==0x0000ff) {
3001 if (bmpImage
->green_mask
==0x03e0) {
3002 if (bmpImage
->red_mask
==0x7f00) {
3003 /* ==== rgb 0888 dib -> rgb 555 bmp ==== */
3004 convs
->Convert_0888_to_555_asis
3007 dstbits
,-bmpImage
->bytes_per_line
);
3008 } else if (bmpImage
->blue_mask
==0x7f00) {
3009 /* ==== rgb 0888 dib -> bgr 555 bmp ==== */
3010 convs
->Convert_0888_to_555_reverse
3013 dstbits
,-bmpImage
->bytes_per_line
);
3017 } else if (bmpImage
->green_mask
==0x07e0) {
3018 if (bmpImage
->red_mask
==0xf800) {
3019 /* ==== rgb 0888 dib -> rgb 565 bmp ==== */
3020 convs
->Convert_0888_to_565_asis
3023 dstbits
,-bmpImage
->bytes_per_line
);
3024 } else if (bmpImage
->blue_mask
==0xf800) {
3025 /* ==== rgb 0888 dib -> bgr 565 bmp ==== */
3026 convs
->Convert_0888_to_565_reverse
3029 dstbits
,-bmpImage
->bytes_per_line
);
3036 } else if (rSrc
==0x0000ff && gSrc
==0x00ff00 && bSrc
==0xff0000) {
3037 if (bmpImage
->green_mask
==0x03e0) {
3038 if (bmpImage
->blue_mask
==0x7f00) {
3039 /* ==== bgr 0888 dib -> bgr 555 bmp ==== */
3040 convs
->Convert_0888_to_555_asis
3043 dstbits
,-bmpImage
->bytes_per_line
);
3044 } else if (bmpImage
->red_mask
==0x7f00) {
3045 /* ==== bgr 0888 dib -> rgb 555 bmp ==== */
3046 convs
->Convert_0888_to_555_reverse
3049 dstbits
,-bmpImage
->bytes_per_line
);
3053 } else if (bmpImage
->green_mask
==0x07e0) {
3054 if (bmpImage
->blue_mask
==0xf800) {
3055 /* ==== bgr 0888 dib -> bgr 565 bmp ==== */
3056 convs
->Convert_0888_to_565_asis
3059 dstbits
,-bmpImage
->bytes_per_line
);
3060 } else if (bmpImage
->red_mask
==0xf800) {
3061 /* ==== bgr 0888 dib -> rgb 565 bmp ==== */
3062 convs
->Convert_0888_to_565_reverse
3065 dstbits
,-bmpImage
->bytes_per_line
);
3073 if (bmpImage
->green_mask
==0x03e0 &&
3074 (bmpImage
->red_mask
==0x7f00 ||
3075 bmpImage
->blue_mask
==0x7f00)) {
3076 /* ==== any 0888 dib -> rgb or bgr 555 bmp ==== */
3077 convs
->Convert_any0888_to_5x5
3081 dstbits
,-bmpImage
->bytes_per_line
,
3082 bmpImage
->red_mask
,bmpImage
->green_mask
,bmpImage
->blue_mask
);
3083 } else if (bmpImage
->green_mask
==0x07e0 &&
3084 (bmpImage
->red_mask
==0xf800 ||
3085 bmpImage
->blue_mask
==0xf800)) {
3086 /* ==== any 0888 dib -> rgb or bgr 565 bmp ==== */
3087 convs
->Convert_any0888_to_5x5
3091 dstbits
,-bmpImage
->bytes_per_line
,
3092 bmpImage
->red_mask
,bmpImage
->green_mask
,bmpImage
->blue_mask
);
3102 WARN("from 32 bit DIB (%lx,%lx,%lx) to unknown %d bit bitmap (%lx,%lx,%lx)\n",
3103 rSrc
, gSrc
, bSrc
, bmpImage
->bits_per_pixel
, bmpImage
->red_mask
,
3104 bmpImage
->green_mask
, bmpImage
->blue_mask
);
3110 /* ==== any 0888 dib -> pal 1, 4 or 8 bmp ==== */
3111 const DWORD
* srcpixel
;
3112 int rShift
,gShift
,bShift
;
3114 rShift
=X11DRV_DIB_MaskToShift(rSrc
);
3115 gShift
=X11DRV_DIB_MaskToShift(gSrc
);
3116 bShift
=X11DRV_DIB_MaskToShift(bSrc
);
3118 for (h
= lines
- 1; h
>= 0; h
--) {
3119 srcpixel
=(const DWORD
*)srcbits
;
3120 for (x
= left
; x
< width
+left
; x
++) {
3122 BYTE red
,green
,blue
;
3123 srcvalue
=*srcpixel
++;
3124 red
= (srcvalue
>> rShift
) & 0xff;
3125 green
=(srcvalue
>> gShift
) & 0xff;
3126 blue
= (srcvalue
>> bShift
) & 0xff;
3127 XPutPixel(bmpImage
, x
, h
, X11DRV_PALETTE_ToPhysical
3128 (physDev
, RGB(red
,green
,blue
)));
3130 srcbits
+= linebytes
;
3138 /***********************************************************************
3139 * X11DRV_DIB_GetImageBits_32
3141 * GetDIBits for an 32-bit deep DIB.
3143 static void X11DRV_DIB_GetImageBits_32( int lines
, BYTE
*dstbits
,
3144 DWORD dstwidth
, DWORD srcwidth
,
3145 PALETTEENTRY
*srccolors
,
3146 DWORD rDst
, DWORD gDst
, DWORD bDst
,
3147 XImage
*bmpImage
, DWORD linebytes
)
3150 int h
, width
= min(srcwidth
, dstwidth
);
3152 const dib_conversions
*convs
= (bmpImage
->byte_order
== LSBFirst
) ? &dib_normal
: &dib_src_byteswap
;
3157 dstbits
= dstbits
+ ( linebytes
* (lines
-1) );
3158 linebytes
= -linebytes
;
3163 switch (bmpImage
->depth
)
3166 if (bmpImage
->bits_per_pixel
==24) {
3167 const void* srcbits
;
3169 srcbits
=bmpImage
->data
+(lines
-1)*bmpImage
->bytes_per_line
;
3171 if (rDst
==bmpImage
->red_mask
&& gDst
==bmpImage
->green_mask
&& bDst
==bmpImage
->blue_mask
) {
3172 /* ==== rgb 888 bmp -> rgb 0888 dib ==== */
3173 /* ==== bgr 888 bmp -> bgr 0888 dib ==== */
3174 convs
->Convert_888_to_0888_asis
3176 srcbits
,-bmpImage
->bytes_per_line
,
3178 } else if (bmpImage
->green_mask
!=0x00ff00 ||
3179 (bmpImage
->red_mask
|bmpImage
->blue_mask
)!=0xff00ff) {
3181 /* the tests below assume sane bmpImage masks */
3182 } else if (rDst
==bmpImage
->blue_mask
&& gDst
==bmpImage
->green_mask
&& bDst
==bmpImage
->red_mask
) {
3183 /* ==== rgb 888 bmp -> bgr 0888 dib ==== */
3184 /* ==== bgr 888 bmp -> rgb 0888 dib ==== */
3185 convs
->Convert_888_to_0888_reverse
3187 srcbits
,-bmpImage
->bytes_per_line
,
3189 } else if (bmpImage
->blue_mask
==0xff) {
3190 /* ==== rgb 888 bmp -> any 0888 dib ==== */
3191 convs
->Convert_rgb888_to_any0888
3193 srcbits
,-bmpImage
->bytes_per_line
,
3197 /* ==== bgr 888 bmp -> any 0888 dib ==== */
3198 convs
->Convert_bgr888_to_any0888
3200 srcbits
,-bmpImage
->bytes_per_line
,
3210 const char* srcbits
;
3212 srcbits
=bmpImage
->data
+(lines
-1)*bmpImage
->bytes_per_line
;
3214 if (gDst
==bmpImage
->green_mask
) {
3215 if (rDst
==bmpImage
->red_mask
&& bDst
==bmpImage
->blue_mask
) {
3216 /* ==== rgb 0888 bmp -> rgb 0888 dib ==== */
3217 /* ==== bgr 0888 bmp -> bgr 0888 dib ==== */
3218 convs
->Convert_0888_asis
3220 srcbits
,-bmpImage
->bytes_per_line
,
3222 } else if (bmpImage
->green_mask
!=0x00ff00 ||
3223 (bmpImage
->red_mask
|bmpImage
->blue_mask
)!=0xff00ff) {
3225 /* the tests below assume sane bmpImage masks */
3226 } else if (rDst
==bmpImage
->blue_mask
&& bDst
==bmpImage
->red_mask
) {
3227 /* ==== rgb 0888 bmp -> bgr 0888 dib ==== */
3228 /* ==== bgr 0888 bmp -> rgb 0888 dib ==== */
3229 convs
->Convert_0888_reverse
3231 srcbits
,-bmpImage
->bytes_per_line
,
3234 /* ==== any 0888 bmp -> any 0888 dib ==== */
3235 convs
->Convert_0888_any
3237 srcbits
,-bmpImage
->bytes_per_line
,
3238 bmpImage
->red_mask
,bmpImage
->green_mask
,bmpImage
->blue_mask
,
3242 } else if (bmpImage
->green_mask
!=0x00ff00 ||
3243 (bmpImage
->red_mask
|bmpImage
->blue_mask
)!=0xff00ff) {
3245 /* the tests below assume sane bmpImage masks */
3247 /* ==== any 0888 bmp -> any 0888 dib ==== */
3248 convs
->Convert_0888_any
3250 srcbits
,-bmpImage
->bytes_per_line
,
3251 bmpImage
->red_mask
,bmpImage
->green_mask
,bmpImage
->blue_mask
,
3261 const char* srcbits
;
3263 srcbits
=bmpImage
->data
+(lines
-1)*bmpImage
->bytes_per_line
;
3265 if (rDst
==0xff0000 && gDst
==0x00ff00 && bDst
==0x0000ff) {
3266 if (bmpImage
->green_mask
==0x03e0) {
3267 if (bmpImage
->red_mask
==0x7f00) {
3268 /* ==== rgb 555 bmp -> rgb 0888 dib ==== */
3269 convs
->Convert_555_to_0888_asis
3271 srcbits
,-bmpImage
->bytes_per_line
,
3273 } else if (bmpImage
->blue_mask
==0x7f00) {
3274 /* ==== bgr 555 bmp -> rgb 0888 dib ==== */
3275 convs
->Convert_555_to_0888_reverse
3277 srcbits
,-bmpImage
->bytes_per_line
,
3282 } else if (bmpImage
->green_mask
==0x07e0) {
3283 if (bmpImage
->red_mask
==0xf800) {
3284 /* ==== rgb 565 bmp -> rgb 0888 dib ==== */
3285 convs
->Convert_565_to_0888_asis
3287 srcbits
,-bmpImage
->bytes_per_line
,
3289 } else if (bmpImage
->blue_mask
==0xf800) {
3290 /* ==== bgr 565 bmp -> rgb 0888 dib ==== */
3291 convs
->Convert_565_to_0888_reverse
3293 srcbits
,-bmpImage
->bytes_per_line
,
3301 } else if (rDst
==0x0000ff && gDst
==0x00ff00 && bDst
==0xff0000) {
3302 if (bmpImage
->green_mask
==0x03e0) {
3303 if (bmpImage
->blue_mask
==0x7f00) {
3304 /* ==== bgr 555 bmp -> bgr 0888 dib ==== */
3305 convs
->Convert_555_to_0888_asis
3307 srcbits
,-bmpImage
->bytes_per_line
,
3309 } else if (bmpImage
->red_mask
==0x7f00) {
3310 /* ==== rgb 555 bmp -> bgr 0888 dib ==== */
3311 convs
->Convert_555_to_0888_reverse
3313 srcbits
,-bmpImage
->bytes_per_line
,
3318 } else if (bmpImage
->green_mask
==0x07e0) {
3319 if (bmpImage
->blue_mask
==0xf800) {
3320 /* ==== bgr 565 bmp -> bgr 0888 dib ==== */
3321 convs
->Convert_565_to_0888_asis
3323 srcbits
,-bmpImage
->bytes_per_line
,
3325 } else if (bmpImage
->red_mask
==0xf800) {
3326 /* ==== rgb 565 bmp -> bgr 0888 dib ==== */
3327 convs
->Convert_565_to_0888_reverse
3329 srcbits
,-bmpImage
->bytes_per_line
,
3338 if (bmpImage
->green_mask
==0x03e0 &&
3339 (bmpImage
->red_mask
==0x7f00 ||
3340 bmpImage
->blue_mask
==0x7f00)) {
3341 /* ==== rgb or bgr 555 bmp -> any 0888 dib ==== */
3342 convs
->Convert_5x5_to_any0888
3344 srcbits
,-bmpImage
->bytes_per_line
,
3345 bmpImage
->red_mask
,bmpImage
->green_mask
,bmpImage
->blue_mask
,
3348 } else if (bmpImage
->green_mask
==0x07e0 &&
3349 (bmpImage
->red_mask
==0xf800 ||
3350 bmpImage
->blue_mask
==0xf800)) {
3351 /* ==== rgb or bgr 565 bmp -> any 0888 dib ==== */
3352 convs
->Convert_5x5_to_any0888
3354 srcbits
,-bmpImage
->bytes_per_line
,
3355 bmpImage
->red_mask
,bmpImage
->green_mask
,bmpImage
->blue_mask
,
3367 if (bmpImage
->red_mask
==0 && bmpImage
->green_mask
==0 && bmpImage
->blue_mask
==0 && srccolors
) {
3368 /* ==== pal 1 or 4 bmp -> any 0888 dib ==== */
3369 int rShift
,gShift
,bShift
;
3372 rShift
=X11DRV_DIB_MaskToShift(rDst
);
3373 gShift
=X11DRV_DIB_MaskToShift(gDst
);
3374 bShift
=X11DRV_DIB_MaskToShift(bDst
);
3375 for (h
= lines
- 1; h
>= 0; h
--) {
3376 dstpixel
=(DWORD
*)dstbits
;
3377 for (x
= 0; x
< width
; x
++) {
3378 PALETTEENTRY srcval
;
3379 srcval
= srccolors
[XGetPixel(bmpImage
, x
, h
)];
3380 *dstpixel
++=(srcval
.peRed
<< rShift
) |
3381 (srcval
.peGreen
<< gShift
) |
3382 (srcval
.peBlue
<< bShift
);
3384 dstbits
+= linebytes
;
3392 if (bmpImage
->red_mask
==0 && bmpImage
->green_mask
==0 && bmpImage
->blue_mask
==0 && srccolors
) {
3393 /* ==== pal 8 bmp -> any 0888 dib ==== */
3394 int rShift
,gShift
,bShift
;
3395 const void* srcbits
;
3396 const BYTE
* srcpixel
;
3399 rShift
=X11DRV_DIB_MaskToShift(rDst
);
3400 gShift
=X11DRV_DIB_MaskToShift(gDst
);
3401 bShift
=X11DRV_DIB_MaskToShift(bDst
);
3402 srcbits
=bmpImage
->data
+(lines
-1)*bmpImage
->bytes_per_line
;
3403 for (h
= lines
- 1; h
>= 0; h
--) {
3405 dstpixel
=(DWORD
*)dstbits
;
3406 for (x
= 0; x
< width
; x
++) {
3407 PALETTEENTRY srcval
;
3408 srcval
=srccolors
[(int)*srcpixel
++];
3409 *dstpixel
++=(srcval
.peRed
<< rShift
) |
3410 (srcval
.peGreen
<< gShift
) |
3411 (srcval
.peBlue
<< bShift
);
3413 srcbits
= (const char*)srcbits
- bmpImage
->bytes_per_line
;
3414 dstbits
+= linebytes
;
3424 /* ==== any bmp format -> any 0888 dib ==== */
3425 int rShift
,gShift
,bShift
;
3428 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 32 bit DIB (%lx,%lx,%lx)\n",
3429 bmpImage
->depth
, bmpImage
->red_mask
,
3430 bmpImage
->green_mask
, bmpImage
->blue_mask
,
3433 rShift
=X11DRV_DIB_MaskToShift(rDst
);
3434 gShift
=X11DRV_DIB_MaskToShift(gDst
);
3435 bShift
=X11DRV_DIB_MaskToShift(bDst
);
3436 for (h
= lines
- 1; h
>= 0; h
--) {
3437 dstpixel
=(DWORD
*)dstbits
;
3438 for (x
= 0; x
< width
; x
++) {
3440 srcval
=X11DRV_PALETTE_ToLogical(XGetPixel(bmpImage
, x
, h
));
3441 *dstpixel
++=(GetRValue(srcval
) << rShift
) |
3442 (GetGValue(srcval
) << gShift
) |
3443 (GetBValue(srcval
) << bShift
);
3445 dstbits
+= linebytes
;
3452 static int XGetSubImageErrorHandler(Display
*dpy
, XErrorEvent
*event
, void *arg
)
3454 return (event
->request_code
== X_GetImage
&& event
->error_code
== BadMatch
);
3457 /***********************************************************************
3458 * X11DRV_DIB_SetImageBits_GetSubImage
3460 * Helper for X11DRV_DIB_SetImageBits
3462 static void X11DRV_DIB_SetImageBits_GetSubImage(
3463 const X11DRV_DIB_IMAGEBITS_DESCR
*descr
, XImage
*bmpImage
)
3465 /* compressed bitmaps may contain gaps in them. So make a copy
3466 * of the existing pixels first */
3469 SetRect( &bmprc
, descr
->xDest
, descr
->yDest
,
3470 descr
->xDest
+ descr
->width
, descr
->yDest
+ descr
->height
);
3471 GetRgnBox( descr
->physDev
->region
, &rc
);
3472 /* convert from dc to drawable origin */
3473 OffsetRect( &rc
, descr
->physDev
->org
.x
, descr
->physDev
->org
.y
);
3474 /* clip visible rect with bitmap */
3475 if( IntersectRect( &rc
, &rc
, &bmprc
))
3477 X11DRV_expect_error( gdi_display
, XGetSubImageErrorHandler
, NULL
);
3478 XGetSubImage( gdi_display
, descr
->drawable
, rc
.left
, rc
.top
,
3479 rc
.right
- rc
.left
, rc
.bottom
- rc
.top
, AllPlanes
,
3481 descr
->xSrc
+ rc
.left
- bmprc
.left
,
3482 descr
->ySrc
+ rc
.top
- bmprc
.top
);
3483 X11DRV_check_error();
3487 /***********************************************************************
3488 * X11DRV_DIB_SetImageBits
3490 * Transfer the bits to an X image.
3491 * Helper function for SetDIBits() and SetDIBitsToDevice().
3493 static int X11DRV_DIB_SetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR
*descr
)
3495 int lines
= descr
->lines
>= 0 ? descr
->lines
: -descr
->lines
;
3500 bmpImage
= descr
->image
;
3502 bmpImage
= XCreateImage( gdi_display
, visual
, descr
->depth
, ZPixmap
, 0, NULL
,
3503 descr
->infoWidth
, lines
, 32, 0 );
3504 bmpImage
->data
= calloc( lines
, bmpImage
->bytes_per_line
);
3505 if(bmpImage
->data
== NULL
) {
3506 ERR("Out of memory!\n");
3507 XDestroyImage( bmpImage
);
3508 wine_tsx11_unlock();
3513 TRACE("Dib: depth=%d r=%lx g=%lx b=%lx\n",
3514 descr
->infoBpp
,descr
->rMask
,descr
->gMask
,descr
->bMask
);
3515 TRACE("Bmp: depth=%d/%d r=%lx g=%lx b=%lx\n",
3516 bmpImage
->depth
,bmpImage
->bits_per_pixel
,
3517 bmpImage
->red_mask
,bmpImage
->green_mask
,bmpImage
->blue_mask
);
3519 /* Transfer the pixels */
3520 switch(descr
->infoBpp
)
3523 X11DRV_DIB_SetImageBits_1( descr
->lines
, descr
->bits
, descr
->infoWidth
,
3524 descr
->width
, descr
->xSrc
, (int *)(descr
->colorMap
),
3525 bmpImage
, descr
->dibpitch
);
3528 if (descr
->compression
) {
3529 X11DRV_DIB_SetImageBits_GetSubImage( descr
, bmpImage
);
3530 X11DRV_DIB_SetImageBits_RLE4( descr
->lines
, descr
->bits
,
3531 descr
->infoWidth
, descr
->width
,
3532 descr
->xSrc
, (int *)(descr
->colorMap
),
3535 X11DRV_DIB_SetImageBits_4( descr
->lines
, descr
->bits
,
3536 descr
->infoWidth
, descr
->width
,
3537 descr
->xSrc
, (int*)(descr
->colorMap
),
3538 bmpImage
, descr
->dibpitch
);
3541 if (descr
->compression
) {
3542 X11DRV_DIB_SetImageBits_GetSubImage( descr
, bmpImage
);
3543 X11DRV_DIB_SetImageBits_RLE8( descr
->lines
, descr
->bits
,
3544 descr
->infoWidth
, descr
->width
,
3545 descr
->xSrc
, (int *)(descr
->colorMap
),
3548 X11DRV_DIB_SetImageBits_8( descr
->lines
, descr
->bits
,
3549 descr
->infoWidth
, descr
->width
,
3550 descr
->xSrc
, (int *)(descr
->colorMap
),
3551 bmpImage
, descr
->dibpitch
);
3555 X11DRV_DIB_SetImageBits_16( descr
->lines
, descr
->bits
,
3556 descr
->infoWidth
, descr
->width
,
3557 descr
->xSrc
, descr
->physDev
,
3558 descr
->rMask
, descr
->gMask
, descr
->bMask
,
3559 bmpImage
, descr
->dibpitch
);
3562 X11DRV_DIB_SetImageBits_24( descr
->lines
, descr
->bits
,
3563 descr
->infoWidth
, descr
->width
,
3564 descr
->xSrc
, descr
->physDev
,
3565 descr
->rMask
, descr
->gMask
, descr
->bMask
,
3566 bmpImage
, descr
->dibpitch
);
3569 X11DRV_DIB_SetImageBits_32( descr
->lines
, descr
->bits
,
3570 descr
->infoWidth
, descr
->width
,
3571 descr
->xSrc
, descr
->physDev
,
3572 descr
->rMask
, descr
->gMask
, descr
->bMask
,
3573 bmpImage
, descr
->dibpitch
);
3576 WARN("(%d): Invalid depth\n", descr
->infoBpp
);
3580 TRACE("XPutImage(%ld,%p,%p,%d,%d,%d,%d,%d,%d)\n",
3581 descr
->drawable
, descr
->gc
, bmpImage
,
3582 descr
->xSrc
, descr
->ySrc
, descr
->xDest
, descr
->yDest
,
3583 descr
->width
, descr
->height
);
3584 #ifdef HAVE_LIBXXSHM
3587 XShmPutImage( gdi_display
, descr
->drawable
, descr
->gc
, bmpImage
,
3588 descr
->xSrc
, descr
->ySrc
, descr
->xDest
, descr
->yDest
,
3589 descr
->width
, descr
->height
, FALSE
);
3590 XSync( gdi_display
, 0 );
3594 XPutImage( gdi_display
, descr
->drawable
, descr
->gc
, bmpImage
,
3595 descr
->xSrc
, descr
->ySrc
, descr
->xDest
, descr
->yDest
,
3596 descr
->width
, descr
->height
);
3598 if (!descr
->image
) XDestroyImage( bmpImage
);
3599 wine_tsx11_unlock();
3603 /***********************************************************************
3604 * X11DRV_DIB_GetImageBits
3606 * Transfer the bits from an X image.
3608 static int X11DRV_DIB_GetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR
*descr
)
3610 int lines
= descr
->lines
>= 0 ? descr
->lines
: -descr
->lines
;
3615 bmpImage
= descr
->image
;
3617 bmpImage
= XCreateImage( gdi_display
, visual
, descr
->depth
, ZPixmap
, 0, NULL
,
3618 descr
->infoWidth
, lines
, 32, 0 );
3619 bmpImage
->data
= calloc( lines
, bmpImage
->bytes_per_line
);
3620 if(bmpImage
->data
== NULL
) {
3621 ERR("Out of memory!\n");
3622 XDestroyImage( bmpImage
);
3623 wine_tsx11_unlock();
3628 #ifdef HAVE_LIBXXSHM
3631 int saveRed
, saveGreen
, saveBlue
;
3633 TRACE("XShmGetImage(%p, %ld, %p, %d, %d, %ld)\n",
3634 gdi_display
, descr
->drawable
, bmpImage
,
3635 descr
->xSrc
, descr
->ySrc
, AllPlanes
);
3637 /* We must save and restore the bmpImage's masks in order
3638 * to preserve them across the call to XShmGetImage, which
3639 * decides to eleminate them since it doesn't happen to know
3640 * what the format of the image is supposed to be, even though
3642 saveRed
= bmpImage
->red_mask
;
3643 saveBlue
= bmpImage
->blue_mask
;
3644 saveGreen
= bmpImage
->green_mask
;
3646 XShmGetImage( gdi_display
, descr
->drawable
, bmpImage
,
3647 descr
->xSrc
, descr
->ySrc
, AllPlanes
);
3649 bmpImage
->red_mask
= saveRed
;
3650 bmpImage
->blue_mask
= saveBlue
;
3651 bmpImage
->green_mask
= saveGreen
;
3654 #endif /* HAVE_LIBXXSHM */
3656 TRACE("XGetSubImage(%p,%ld,%d,%d,%d,%d,%ld,%d,%p,%d,%d)\n",
3657 gdi_display
, descr
->drawable
, descr
->xSrc
, descr
->ySrc
, descr
->width
,
3658 lines
, AllPlanes
, ZPixmap
, bmpImage
, descr
->xDest
, descr
->yDest
);
3659 XGetSubImage( gdi_display
, descr
->drawable
, descr
->xSrc
, descr
->ySrc
,
3660 descr
->width
, lines
, AllPlanes
, ZPixmap
,
3661 bmpImage
, descr
->xDest
, descr
->yDest
);
3664 TRACE("Dib: depth=%2d r=%lx g=%lx b=%lx\n",
3665 descr
->infoBpp
,descr
->rMask
,descr
->gMask
,descr
->bMask
);
3666 TRACE("Bmp: depth=%2d/%2d r=%lx g=%lx b=%lx\n",
3667 bmpImage
->depth
,bmpImage
->bits_per_pixel
,
3668 bmpImage
->red_mask
,bmpImage
->green_mask
,bmpImage
->blue_mask
);
3669 /* Transfer the pixels */
3670 switch(descr
->infoBpp
)
3673 X11DRV_DIB_GetImageBits_1( descr
->lines
,(LPVOID
)descr
->bits
,
3674 descr
->infoWidth
, descr
->width
,
3675 descr
->colorMap
, descr
->palentry
,
3676 bmpImage
, descr
->dibpitch
);
3680 if (descr
->compression
) {
3681 FIXME("Compression not yet supported!\n");
3682 if(descr
->sizeImage
< X11DRV_DIB_GetDIBWidthBytes( descr
->infoWidth
, 4 ) * abs(descr
->lines
))
3685 X11DRV_DIB_GetImageBits_4( descr
->lines
,(LPVOID
)descr
->bits
,
3686 descr
->infoWidth
, descr
->width
,
3687 descr
->colorMap
, descr
->palentry
,
3688 bmpImage
, descr
->dibpitch
);
3691 if (descr
->compression
) {
3692 FIXME("Compression not yet supported!\n");
3693 if(descr
->sizeImage
< X11DRV_DIB_GetDIBWidthBytes( descr
->infoWidth
, 8 ) * abs(descr
->lines
))
3696 X11DRV_DIB_GetImageBits_8( descr
->lines
, (LPVOID
)descr
->bits
,
3697 descr
->infoWidth
, descr
->width
,
3698 descr
->colorMap
, descr
->palentry
,
3699 bmpImage
, descr
->dibpitch
);
3703 X11DRV_DIB_GetImageBits_16( descr
->lines
, (LPVOID
)descr
->bits
,
3704 descr
->infoWidth
,descr
->width
,
3706 descr
->rMask
, descr
->gMask
, descr
->bMask
,
3707 bmpImage
, descr
->dibpitch
);
3711 X11DRV_DIB_GetImageBits_24( descr
->lines
, (LPVOID
)descr
->bits
,
3712 descr
->infoWidth
,descr
->width
,
3714 descr
->rMask
, descr
->gMask
, descr
->bMask
,
3715 bmpImage
, descr
->dibpitch
);
3719 X11DRV_DIB_GetImageBits_32( descr
->lines
, (LPVOID
)descr
->bits
,
3720 descr
->infoWidth
, descr
->width
,
3722 descr
->rMask
, descr
->gMask
, descr
->bMask
,
3723 bmpImage
, descr
->dibpitch
);
3727 WARN("(%d): Invalid depth\n", descr
->infoBpp
);
3731 if (!descr
->image
) XDestroyImage( bmpImage
);
3732 wine_tsx11_unlock();
3736 /*************************************************************************
3737 * X11DRV_SetDIBitsToDevice
3740 INT
X11DRV_SetDIBitsToDevice( X11DRV_PDEVICE
*physDev
, INT xDest
, INT yDest
, DWORD cx
,
3741 DWORD cy
, INT xSrc
, INT ySrc
,
3742 UINT startscan
, UINT lines
, LPCVOID bits
,
3743 const BITMAPINFO
*info
, UINT coloruse
)
3745 X11DRV_DIB_IMAGEBITS_DESCR descr
;
3752 if (DIB_GetBitmapInfo( &info
->bmiHeader
, &width
, &height
,
3753 &descr
.infoBpp
, &descr
.compression
) == -1)
3756 top_down
= (height
< 0);
3757 if (top_down
) height
= -height
;
3761 LPtoDP(physDev
->hdc
, &pt
, 1);
3763 if (!lines
|| (startscan
>= height
)) return 0;
3764 if (!top_down
&& startscan
+ lines
> height
) lines
= height
- startscan
;
3766 /* make xSrc,ySrc point to the upper-left corner, not the lower-left one,
3767 * and clamp all values to fit inside [startscan,startscan+lines]
3769 if (ySrc
+ cy
<= startscan
+ lines
)
3771 UINT y
= startscan
+ lines
- (ySrc
+ cy
);
3772 if (ySrc
< startscan
) cy
-= (startscan
- ySrc
);
3775 /* avoid getting unnecessary lines */
3777 if (y
>= lines
) return 0;
3782 if (y
>= lines
) return lines
;
3783 ySrc
= y
; /* need to get all lines in top down mode */
3788 if (ySrc
>= startscan
+ lines
) return lines
;
3789 pt
.y
+= ySrc
+ cy
- (startscan
+ lines
);
3790 cy
= startscan
+ lines
- ySrc
;
3792 if (cy
> lines
) cy
= lines
;
3794 if (xSrc
>= width
) return lines
;
3795 if (xSrc
+ cx
>= width
) cx
= width
- xSrc
;
3796 if (!cx
|| !cy
) return lines
;
3798 /* Update the pixmap from the DIB section */
3799 X11DRV_LockDIBSection(physDev
, DIB_Status_GdiMod
, FALSE
);
3801 X11DRV_SetupGCForText( physDev
); /* To have the correct colors */
3803 XSetFunction(gdi_display
, physDev
->gc
, X11DRV_XROPfunction
[GetROP2(physDev
->hdc
) - 1]);
3804 wine_tsx11_unlock();
3806 colorPtr
= (LPBYTE
) info
+ (WORD
) info
->bmiHeader
.biSize
;
3808 switch (descr
.infoBpp
)
3813 descr
.colorMap
= (RGBQUAD
*)X11DRV_DIB_BuildColorMap(
3814 coloruse
== DIB_PAL_COLORS
? physDev
: NULL
, coloruse
,
3815 physDev
->depth
, info
, &descr
.nColorMap
);
3816 if (!descr
.colorMap
) return 0;
3817 descr
.rMask
= descr
.gMask
= descr
.bMask
= 0;
3821 descr
.rMask
= (descr
.compression
== BI_BITFIELDS
) ? *((const DWORD
*)colorPtr
) : 0x7c00;
3822 descr
.gMask
= (descr
.compression
== BI_BITFIELDS
) ? *((const DWORD
*)colorPtr
+ 1) : 0x03e0;
3823 descr
.bMask
= (descr
.compression
== BI_BITFIELDS
) ? *((const DWORD
*)colorPtr
+ 2) : 0x001f;
3829 descr
.rMask
= (descr
.compression
== BI_BITFIELDS
) ? *((const DWORD
*)colorPtr
) : 0xff0000;
3830 descr
.gMask
= (descr
.compression
== BI_BITFIELDS
) ? *((const DWORD
*)colorPtr
+ 1) : 0x00ff00;
3831 descr
.bMask
= (descr
.compression
== BI_BITFIELDS
) ? *((const DWORD
*)colorPtr
+ 2) : 0x0000ff;
3836 descr
.physDev
= physDev
;
3839 descr
.palentry
= NULL
;
3840 descr
.lines
= top_down
? -lines
: lines
;
3841 descr
.infoWidth
= width
;
3842 descr
.depth
= physDev
->depth
;
3843 descr
.drawable
= physDev
->drawable
;
3844 descr
.gc
= physDev
->gc
;
3847 descr
.xDest
= physDev
->org
.x
+ pt
.x
;
3848 descr
.yDest
= physDev
->org
.y
+ pt
.y
;
3851 descr
.useShm
= FALSE
;
3852 descr
.dibpitch
= ((width
* descr
.infoBpp
+ 31) &~31) / 8;
3854 result
= X11DRV_DIB_SetImageBits( &descr
);
3856 if (descr
.infoBpp
<= 8)
3857 HeapFree(GetProcessHeap(), 0, descr
.colorMap
);
3859 /* Update the DIBSection of the pixmap */
3860 X11DRV_UnlockDIBSection(physDev
, TRUE
);
3865 /***********************************************************************
3866 * SetDIBits (X11DRV.@)
3868 INT
X11DRV_SetDIBits( X11DRV_PDEVICE
*physDev
, HBITMAP hbitmap
, UINT startscan
,
3869 UINT lines
, LPCVOID bits
, const BITMAPINFO
*info
, UINT coloruse
)
3871 X_PHYSBITMAP
*physBitmap
= X11DRV_get_phys_bitmap( hbitmap
);
3872 X11DRV_DIB_IMAGEBITS_DESCR descr
;
3874 LONG height
, tmpheight
;
3878 descr
.physDev
= physDev
;
3880 if (!physBitmap
) return 0;
3882 if (DIB_GetBitmapInfo( &info
->bmiHeader
, &descr
.infoWidth
, &height
,
3883 &descr
.infoBpp
, &descr
.compression
) == -1)
3887 if (height
< 0) height
= -height
;
3888 if (!lines
|| (startscan
>= height
))
3891 if (!GetObjectW( hbitmap
, sizeof(bitmap
), &bitmap
)) return 0;
3893 if (startscan
+ lines
> height
) lines
= height
- startscan
;
3895 colorPtr
= (LPBYTE
) info
+ (WORD
) info
->bmiHeader
.biSize
;
3897 switch (descr
.infoBpp
)
3902 descr
.colorMap
= (RGBQUAD
*)X11DRV_DIB_BuildColorMap(
3903 coloruse
== DIB_PAL_COLORS
? descr
.physDev
: NULL
, coloruse
,
3904 physBitmap
->pixmap_depth
,
3905 info
, &descr
.nColorMap
);
3906 if (!descr
.colorMap
) return 0;
3907 descr
.rMask
= descr
.gMask
= descr
.bMask
= 0;
3911 descr
.rMask
= (descr
.compression
== BI_BITFIELDS
) ? *((const DWORD
*)colorPtr
) : 0x7c00;
3912 descr
.gMask
= (descr
.compression
== BI_BITFIELDS
) ? *((const DWORD
*)colorPtr
+ 1) : 0x03e0;
3913 descr
.bMask
= (descr
.compression
== BI_BITFIELDS
) ? *((const DWORD
*)colorPtr
+ 2) : 0x001f;
3919 descr
.rMask
= (descr
.compression
== BI_BITFIELDS
) ? *((const DWORD
*)colorPtr
) : 0xff0000;
3920 descr
.gMask
= (descr
.compression
== BI_BITFIELDS
) ? *((const DWORD
*)colorPtr
+ 1) : 0x00ff00;
3921 descr
.bMask
= (descr
.compression
== BI_BITFIELDS
) ? *((const DWORD
*)colorPtr
+ 2) : 0x0000ff;
3930 descr
.palentry
= NULL
;
3931 descr
.lines
= tmpheight
>= 0 ? lines
: -lines
;
3932 descr
.depth
= physBitmap
->pixmap_depth
;
3933 descr
.drawable
= physBitmap
->pixmap
;
3934 descr
.gc
= BITMAP_GC(physBitmap
);
3938 descr
.yDest
= height
- startscan
- lines
;
3939 descr
.width
= bitmap
.bmWidth
;
3940 descr
.height
= lines
;
3941 descr
.useShm
= FALSE
;
3942 descr
.dibpitch
= ((descr
.infoWidth
* descr
.infoBpp
+ 31) &~31) / 8;
3943 X11DRV_DIB_Lock( physBitmap
, DIB_Status_GdiMod
, FALSE
);
3944 result
= X11DRV_DIB_SetImageBits( &descr
);
3945 X11DRV_DIB_Unlock( physBitmap
, TRUE
);
3947 HeapFree(GetProcessHeap(), 0, descr
.colorMap
);
3952 /***********************************************************************
3953 * GetDIBits (X11DRV.@)
3955 INT
X11DRV_GetDIBits( X11DRV_PDEVICE
*physDev
, HBITMAP hbitmap
, UINT startscan
, UINT lines
,
3956 LPVOID bits
, BITMAPINFO
*info
, UINT coloruse
)
3958 X_PHYSBITMAP
*physBitmap
= X11DRV_get_phys_bitmap( hbitmap
);
3960 X11DRV_DIB_IMAGEBITS_DESCR descr
;
3961 PALETTEENTRY palette
[256];
3969 GetPaletteEntries( GetCurrentObject( physDev
->hdc
, OBJ_PAL
), 0, 256, palette
);
3971 if (!physBitmap
) return 0;
3972 if (!(obj_size
= GetObjectW( hbitmap
, sizeof(dib
), &dib
))) return 0;
3974 bitmap_type
= DIB_GetBitmapInfo( (BITMAPINFOHEADER
*) info
, &descr
.infoWidth
, &tempHeight
, &descr
.infoBpp
, &descr
.compression
);
3975 descr
.lines
= tempHeight
;
3976 if (bitmap_type
== -1)
3978 ERR("Invalid bitmap\n");
3981 core_header
= (bitmap_type
== 0);
3982 colorPtr
= (LPBYTE
) info
+ (WORD
) info
->bmiHeader
.biSize
;
3984 TRACE("%u scanlines of (%i,%i) -> (%i,%i) starting from %u\n",
3985 lines
, dib
.dsBm
.bmWidth
, dib
.dsBm
.bmHeight
, (int)descr
.infoWidth
, descr
.lines
, startscan
);
3987 if( lines
> dib
.dsBm
.bmHeight
) lines
= dib
.dsBm
.bmHeight
;
3989 height
= descr
.lines
;
3990 if (height
< 0) height
= -height
;
3991 if( lines
> height
) lines
= height
;
3992 /* Top-down images have a negative biHeight, the scanlines of theses images
3993 * were inverted in X11DRV_DIB_GetImageBits_xx
3994 * To prevent this we simply change the sign of lines
3995 * (the number of scan lines to copy).
3996 * Negative lines are correctly handled by X11DRV_DIB_GetImageBits_xx.
3998 if( descr
.lines
< 0 && lines
> 0) lines
= -lines
;
4000 if( startscan
>= dib
.dsBm
.bmHeight
) return 0;
4002 descr
.colorMap
= NULL
;
4004 switch (descr
.infoBpp
)
4009 descr
.rMask
= descr
.gMask
= descr
.bMask
= 0;
4010 if(coloruse
== DIB_RGB_COLORS
)
4011 descr
.colorMap
= colorPtr
;
4013 int num_colors
= 1 << descr
.infoBpp
, i
;
4016 WORD
*index
= (WORD
*)colorPtr
;
4017 descr
.colorMap
= rgb
= HeapAlloc(GetProcessHeap(), 0, num_colors
* sizeof(RGBQUAD
));
4018 for(i
= 0; i
< num_colors
; i
++, rgb
++, index
++) {
4019 colref
= X11DRV_PALETTE_ToLogical(X11DRV_PALETTE_ToPhysical(physDev
, PALETTEINDEX(*index
)));
4020 rgb
->rgbRed
= GetRValue(colref
);
4021 rgb
->rgbGreen
= GetGValue(colref
);
4022 rgb
->rgbBlue
= GetBValue(colref
);
4023 rgb
->rgbReserved
= 0;
4029 descr
.rMask
= (descr
.compression
== BI_BITFIELDS
) ? *((DWORD
*)colorPtr
) : 0x7c00;
4030 descr
.gMask
= (descr
.compression
== BI_BITFIELDS
) ? *((DWORD
*)colorPtr
+ 1) : 0x03e0;
4031 descr
.bMask
= (descr
.compression
== BI_BITFIELDS
) ? *((DWORD
*)colorPtr
+ 2) : 0x001f;
4035 descr
.rMask
= (descr
.compression
== BI_BITFIELDS
) ? *((DWORD
*)colorPtr
) : 0xff0000;
4036 descr
.gMask
= (descr
.compression
== BI_BITFIELDS
) ? *((DWORD
*)colorPtr
+ 1) : 0x00ff00;
4037 descr
.bMask
= (descr
.compression
== BI_BITFIELDS
) ? *((DWORD
*)colorPtr
+ 2) : 0x0000ff;
4041 descr
.physDev
= physDev
;
4042 descr
.palentry
= palette
;
4045 descr
.lines
= lines
;
4046 descr
.depth
= physBitmap
->pixmap_depth
;
4047 descr
.drawable
= physBitmap
->pixmap
;
4048 descr
.gc
= BITMAP_GC(physBitmap
);
4049 descr
.width
= dib
.dsBm
.bmWidth
;
4050 descr
.height
= dib
.dsBm
.bmHeight
;
4054 descr
.sizeImage
= core_header
? 0 : info
->bmiHeader
.biSizeImage
;
4056 if (descr
.lines
> 0)
4058 descr
.ySrc
= (descr
.height
-1) - (startscan
+ (lines
-1));
4062 descr
.ySrc
= startscan
;
4064 #ifdef HAVE_LIBXXSHM
4065 descr
.useShm
= (obj_size
== sizeof(DIBSECTION
)) && (physBitmap
->shminfo
.shmid
!= -1);
4067 descr
.useShm
= FALSE
;
4069 descr
.dibpitch
= (obj_size
== sizeof(DIBSECTION
)) ? dib
.dsBm
.bmWidthBytes
4070 : (((descr
.infoWidth
* descr
.infoBpp
+ 31) &~31) / 8);
4072 X11DRV_DIB_Lock( physBitmap
, DIB_Status_GdiMod
, FALSE
);
4073 X11DRV_DIB_GetImageBits( &descr
);
4074 X11DRV_DIB_Unlock( physBitmap
, TRUE
);
4076 if(!core_header
&& info
->bmiHeader
.biSizeImage
== 0) /* Fill in biSizeImage */
4077 info
->bmiHeader
.biSizeImage
= X11DRV_DIB_GetDIBImageBytes( descr
.infoWidth
,
4081 if (descr
.compression
== BI_BITFIELDS
)
4083 *(DWORD
*) colorPtr
= descr
.rMask
;
4084 *((DWORD
*)colorPtr
+ 1) = descr
.gMask
;
4085 *((DWORD
*)colorPtr
+ 2) = descr
.bMask
;
4087 else if (!core_header
)
4089 /* if RLE or JPEG compression were supported,
4090 * this line would be invalid. */
4091 info
->bmiHeader
.biCompression
= 0;
4094 if(descr
.colorMap
&& descr
.colorMap
!= colorPtr
)
4095 HeapFree(GetProcessHeap(), 0, descr
.colorMap
);
4099 /***********************************************************************
4100 * DIB_DoProtectDIBSection
4102 static void X11DRV_DIB_DoProtectDIBSection( X_PHYSBITMAP
*physBitmap
, DWORD new_prot
)
4107 GetObjectW( physBitmap
->hbitmap
, sizeof(dib
), &dib
);
4108 VirtualProtect(dib
.dsBm
.bmBits
, dib
.dsBmih
.biSizeImage
, new_prot
, &old_prot
);
4109 TRACE("Changed protection from %ld to %ld\n", old_prot
, new_prot
);
4112 /***********************************************************************
4113 * X11DRV_DIB_DoCopyDIBSection
4115 static void X11DRV_DIB_DoCopyDIBSection(X_PHYSBITMAP
*physBitmap
, BOOL toDIB
,
4116 void *colorMap
, int nColorMap
,
4118 DWORD xSrc
, DWORD ySrc
,
4119 DWORD xDest
, DWORD yDest
,
4120 DWORD width
, DWORD height
)
4122 DIBSECTION dibSection
;
4123 X11DRV_DIB_IMAGEBITS_DESCR descr
;
4124 int identity
[2] = {0,1};
4126 if (!GetObjectW( physBitmap
->hbitmap
, sizeof(dibSection
), &dibSection
)) return;
4128 descr
.physDev
= NULL
;
4129 descr
.palentry
= NULL
;
4130 descr
.infoWidth
= dibSection
.dsBmih
.biWidth
;
4131 descr
.infoBpp
= dibSection
.dsBmih
.biBitCount
;
4132 descr
.lines
= dibSection
.dsBmih
.biHeight
;
4133 descr
.image
= physBitmap
->image
;
4134 descr
.colorMap
= colorMap
;
4135 descr
.nColorMap
= nColorMap
;
4136 descr
.bits
= dibSection
.dsBm
.bmBits
;
4137 descr
.depth
= physBitmap
->pixmap_depth
;
4138 descr
.compression
= dibSection
.dsBmih
.biCompression
;
4140 if(descr
.infoBpp
== 1)
4141 descr
.colorMap
= (void*)identity
;
4143 switch (descr
.infoBpp
)
4148 descr
.rMask
= descr
.gMask
= descr
.bMask
= 0;
4152 descr
.rMask
= (descr
.compression
== BI_BITFIELDS
) ? dibSection
.dsBitfields
[0] : 0x7c00;
4153 descr
.gMask
= (descr
.compression
== BI_BITFIELDS
) ? dibSection
.dsBitfields
[1] : 0x03e0;
4154 descr
.bMask
= (descr
.compression
== BI_BITFIELDS
) ? dibSection
.dsBitfields
[2] : 0x001f;
4159 descr
.rMask
= (descr
.compression
== BI_BITFIELDS
) ? dibSection
.dsBitfields
[0] : 0xff0000;
4160 descr
.gMask
= (descr
.compression
== BI_BITFIELDS
) ? dibSection
.dsBitfields
[1] : 0x00ff00;
4161 descr
.bMask
= (descr
.compression
== BI_BITFIELDS
) ? dibSection
.dsBitfields
[2] : 0x0000ff;
4166 descr
.drawable
= dest
;
4167 descr
.gc
= BITMAP_GC(physBitmap
);
4170 descr
.xDest
= xDest
;
4171 descr
.yDest
= yDest
;
4172 descr
.width
= width
;
4173 descr
.height
= height
;
4174 descr
.sizeImage
= 0;
4176 #ifdef HAVE_LIBXXSHM
4177 descr
.useShm
= (physBitmap
->shminfo
.shmid
!= -1);
4179 descr
.useShm
= FALSE
;
4181 descr
.dibpitch
= dibSection
.dsBm
.bmWidthBytes
;
4185 TRACE("Copying from Pixmap to DIB bits\n");
4186 X11DRV_DIB_GetImageBits( &descr
);
4190 TRACE("Copying from DIB bits to Pixmap\n");
4191 X11DRV_DIB_SetImageBits( &descr
);
4195 /***********************************************************************
4196 * X11DRV_DIB_CopyDIBSection
4198 void X11DRV_DIB_CopyDIBSection(X11DRV_PDEVICE
*physDevSrc
, X11DRV_PDEVICE
*physDevDst
,
4199 DWORD xSrc
, DWORD ySrc
, DWORD xDest
, DWORD yDest
,
4200 DWORD width
, DWORD height
)
4203 X_PHYSBITMAP
*physBitmap
;
4204 int nColorMap
= 0, *colorMap
= NULL
, aColorMap
= FALSE
;
4206 TRACE("(%p,%p,%ld,%ld,%ld,%ld,%ld,%ld)\n", physDevSrc
->hdc
, physDevDst
->hdc
,
4207 xSrc
, ySrc
, xDest
, yDest
, width
, height
);
4208 /* this function is meant as an optimization for BitBlt,
4209 * not to be called otherwise */
4210 physBitmap
= physDevSrc
->bitmap
;
4211 if (!physBitmap
|| GetObjectW( physBitmap
->hbitmap
, sizeof(dib
), &dib
) != sizeof(dib
))
4213 ERR("called for non-DIBSection!?\n");
4216 /* while BitBlt should already have made sure we only get
4217 * positive values, we should check for oversize values */
4218 if ((xSrc
< dib
.dsBm
.bmWidth
) &&
4219 (ySrc
< dib
.dsBm
.bmHeight
)) {
4220 if (xSrc
+ width
> dib
.dsBm
.bmWidth
)
4221 width
= dib
.dsBm
.bmWidth
- xSrc
;
4222 if (ySrc
+ height
> dib
.dsBm
.bmHeight
)
4223 height
= dib
.dsBm
.bmHeight
- ySrc
;
4224 /* if the source bitmap is 8bpp or less, we're supposed to use the
4225 * DC's palette for color conversion (not the DIB color table) */
4226 if (dib
.dsBm
.bmBitsPixel
<= 8) {
4227 HPALETTE hPalette
= GetCurrentObject( physDevSrc
->hdc
, OBJ_PAL
);
4228 if (!hPalette
|| (hPalette
== GetStockObject(DEFAULT_PALETTE
))) {
4229 /* HACK: no palette has been set in the source DC,
4230 * use the DIB colormap instead - this is necessary in some
4231 * cases since we need to do depth conversion in some places
4232 * where real Windows can just copy data straight over */
4233 colorMap
= physBitmap
->colorMap
;
4234 nColorMap
= physBitmap
->nColorMap
;
4236 colorMap
= X11DRV_DIB_BuildColorMap( physDevSrc
, (WORD
)-1,
4237 dib
.dsBm
.bmBitsPixel
,
4238 (BITMAPINFO
*)&dib
.dsBmih
,
4240 if (colorMap
) aColorMap
= TRUE
;
4243 /* perform the copy */
4244 X11DRV_DIB_DoCopyDIBSection(physBitmap
, FALSE
, colorMap
, nColorMap
,
4245 physDevDst
->drawable
, xSrc
, ySrc
,
4246 physDevDst
->org
.x
+ xDest
, physDevDst
->org
.y
+ yDest
,
4248 /* free color mapping */
4250 HeapFree(GetProcessHeap(), 0, colorMap
);
4254 /***********************************************************************
4255 * X11DRV_DIB_DoUpdateDIBSection
4257 static void X11DRV_DIB_DoUpdateDIBSection(X_PHYSBITMAP
*physBitmap
, BOOL toDIB
)
4261 GetObjectW( physBitmap
->hbitmap
, sizeof(bitmap
), &bitmap
);
4262 X11DRV_DIB_DoCopyDIBSection(physBitmap
, toDIB
,
4263 physBitmap
->colorMap
, physBitmap
->nColorMap
,
4264 physBitmap
->pixmap
, 0, 0, 0, 0,
4265 bitmap
.bmWidth
, bitmap
.bmHeight
);
4268 /***********************************************************************
4269 * X11DRV_DIB_FaultHandler
4271 static BOOL
X11DRV_DIB_FaultHandler( LPVOID res
, LPCVOID addr
)
4273 X_PHYSBITMAP
*physBitmap
= res
;
4274 INT state
= X11DRV_DIB_Lock( physBitmap
, DIB_Status_None
, FALSE
);
4276 if (state
!= DIB_Status_InSync
) {
4277 /* no way to tell whether app needs read or write yet,
4279 X11DRV_DIB_Coerce( physBitmap
, DIB_Status_InSync
, FALSE
);
4281 /* hm, apparently the app must have write access */
4282 X11DRV_DIB_Coerce( physBitmap
, DIB_Status_AppMod
, FALSE
);
4284 X11DRV_DIB_Unlock( physBitmap
, TRUE
);
4289 /***********************************************************************
4292 static INT
X11DRV_DIB_Coerce(X_PHYSBITMAP
*physBitmap
, INT req
, BOOL lossy
)
4294 INT ret
= DIB_Status_None
;
4296 if (!physBitmap
->image
) return ret
; /* not a DIB section */
4297 EnterCriticalSection(&physBitmap
->lock
);
4298 ret
= physBitmap
->status
;
4300 case DIB_Status_GdiMod
:
4301 /* GDI access - request to draw on pixmap */
4302 switch (physBitmap
->status
)
4305 case DIB_Status_None
:
4306 physBitmap
->p_status
= DIB_Status_GdiMod
;
4307 X11DRV_DIB_DoUpdateDIBSection( physBitmap
, FALSE
);
4310 case DIB_Status_GdiMod
:
4311 TRACE("GdiMod requested in status GdiMod\n" );
4312 physBitmap
->p_status
= DIB_Status_GdiMod
;
4315 case DIB_Status_InSync
:
4316 TRACE("GdiMod requested in status InSync\n" );
4317 X11DRV_DIB_DoProtectDIBSection( physBitmap
, PAGE_NOACCESS
);
4318 physBitmap
->status
= DIB_Status_GdiMod
;
4319 physBitmap
->p_status
= DIB_Status_InSync
;
4322 case DIB_Status_AppMod
:
4323 TRACE("GdiMod requested in status AppMod\n" );
4325 /* make it readonly to avoid app changing data while we copy */
4326 X11DRV_DIB_DoProtectDIBSection( physBitmap
, PAGE_READONLY
);
4327 X11DRV_DIB_DoUpdateDIBSection( physBitmap
, FALSE
);
4329 X11DRV_DIB_DoProtectDIBSection( physBitmap
, PAGE_NOACCESS
);
4330 physBitmap
->p_status
= DIB_Status_AppMod
;
4331 physBitmap
->status
= DIB_Status_GdiMod
;
4336 case DIB_Status_InSync
:
4337 /* App access - request access to read DIB surface */
4338 /* (typically called from signal handler) */
4339 switch (physBitmap
->status
)
4342 case DIB_Status_None
:
4343 /* shouldn't happen from signal handler */
4346 case DIB_Status_GdiMod
:
4347 TRACE("InSync requested in status GdiMod\n" );
4349 X11DRV_DIB_DoProtectDIBSection( physBitmap
, PAGE_READWRITE
);
4350 X11DRV_DIB_DoUpdateDIBSection( physBitmap
, TRUE
);
4352 X11DRV_DIB_DoProtectDIBSection( physBitmap
, PAGE_READONLY
);
4353 physBitmap
->status
= DIB_Status_InSync
;
4356 case DIB_Status_InSync
:
4357 TRACE("InSync requested in status InSync\n" );
4358 /* shouldn't happen from signal handler */
4361 case DIB_Status_AppMod
:
4362 TRACE("InSync requested in status AppMod\n" );
4363 /* no reason to do anything here, and this
4364 * shouldn't happen from signal handler */
4369 case DIB_Status_AppMod
:
4370 /* App access - request access to write DIB surface */
4371 /* (typically called from signal handler) */
4372 switch (physBitmap
->status
)
4375 case DIB_Status_None
:
4376 /* shouldn't happen from signal handler */
4379 case DIB_Status_GdiMod
:
4380 TRACE("AppMod requested in status GdiMod\n" );
4381 X11DRV_DIB_DoProtectDIBSection( physBitmap
, PAGE_READWRITE
);
4382 if (!lossy
) X11DRV_DIB_DoUpdateDIBSection( physBitmap
, TRUE
);
4383 physBitmap
->status
= DIB_Status_AppMod
;
4386 case DIB_Status_InSync
:
4387 TRACE("AppMod requested in status InSync\n" );
4388 X11DRV_DIB_DoProtectDIBSection( physBitmap
, PAGE_READWRITE
);
4389 physBitmap
->status
= DIB_Status_AppMod
;
4392 case DIB_Status_AppMod
:
4393 TRACE("AppMod requested in status AppMod\n" );
4394 /* shouldn't happen from signal handler */
4399 /* it is up to the caller to do the copy/conversion, probably
4400 * using the return value to decide where to copy from */
4402 LeaveCriticalSection(&physBitmap
->lock
);
4406 /***********************************************************************
4409 static INT
X11DRV_DIB_Lock(X_PHYSBITMAP
*physBitmap
, INT req
, BOOL lossy
)
4411 INT ret
= DIB_Status_None
;
4413 if (!physBitmap
->image
) return ret
; /* not a DIB section */
4414 TRACE("Locking %p from thread %04lx\n", physBitmap
->hbitmap
, GetCurrentThreadId());
4415 EnterCriticalSection(&physBitmap
->lock
);
4416 ret
= physBitmap
->status
;
4417 if (req
!= DIB_Status_None
)
4418 X11DRV_DIB_Coerce(physBitmap
, req
, lossy
);
4422 /***********************************************************************
4425 static void X11DRV_DIB_Unlock(X_PHYSBITMAP
*physBitmap
, BOOL commit
)
4427 if (!physBitmap
->image
) return; /* not a DIB section */
4428 switch (physBitmap
->status
)
4431 case DIB_Status_None
:
4432 /* in case anyone is wondering, this is the "signal handler doesn't
4433 * work" case, where we always have to be ready for app access */
4435 switch (physBitmap
->p_status
)
4437 case DIB_Status_GdiMod
:
4438 TRACE("Unlocking and syncing from GdiMod\n" );
4439 X11DRV_DIB_DoUpdateDIBSection( physBitmap
, TRUE
);
4443 TRACE("Unlocking without needing to sync\n" );
4447 else TRACE("Unlocking with no changes\n");
4448 physBitmap
->p_status
= DIB_Status_None
;
4451 case DIB_Status_GdiMod
:
4452 TRACE("Unlocking in status GdiMod\n" );
4453 /* DIB was protected in Coerce */
4455 /* no commit, revert to InSync if applicable */
4456 if ((physBitmap
->p_status
== DIB_Status_InSync
) ||
4457 (physBitmap
->p_status
== DIB_Status_AppMod
)) {
4458 X11DRV_DIB_DoProtectDIBSection( physBitmap
, PAGE_READONLY
);
4459 physBitmap
->status
= DIB_Status_InSync
;
4464 case DIB_Status_InSync
:
4465 TRACE("Unlocking in status InSync\n" );
4466 /* DIB was already protected in Coerce */
4469 case DIB_Status_AppMod
:
4470 TRACE("Unlocking in status AppMod\n" );
4471 /* DIB was already protected in Coerce */
4472 /* this case is ordinary only called from the signal handler,
4473 * so we don't bother to check for !commit */
4476 LeaveCriticalSection(&physBitmap
->lock
);
4477 TRACE("Unlocked %p\n", physBitmap
->hbitmap
);
4480 /***********************************************************************
4481 * X11DRV_CoerceDIBSection
4483 INT
X11DRV_CoerceDIBSection(X11DRV_PDEVICE
*physDev
, INT req
, BOOL lossy
)
4485 if (!physDev
|| !physDev
->bitmap
) return DIB_Status_None
;
4486 return X11DRV_DIB_Coerce(physDev
->bitmap
, req
, lossy
);
4489 /***********************************************************************
4490 * X11DRV_LockDIBSection
4492 INT
X11DRV_LockDIBSection(X11DRV_PDEVICE
*physDev
, INT req
, BOOL lossy
)
4494 if (!physDev
|| !physDev
->bitmap
) return DIB_Status_None
;
4495 return X11DRV_DIB_Lock(physDev
->bitmap
, req
, lossy
);
4498 /***********************************************************************
4499 * X11DRV_UnlockDIBSection
4501 void X11DRV_UnlockDIBSection(X11DRV_PDEVICE
*physDev
, BOOL commit
)
4503 if (!physDev
|| !physDev
->bitmap
) return;
4504 X11DRV_DIB_Unlock(physDev
->bitmap
, commit
);
4508 #ifdef HAVE_LIBXXSHM
4509 /***********************************************************************
4510 * X11DRV_XShmErrorHandler
4513 static int XShmErrorHandler( Display
*dpy
, XErrorEvent
*event
, void *arg
)
4515 return 1; /* FIXME: should check event contents */
4518 /***********************************************************************
4519 * X11DRV_XShmCreateImage
4522 static XImage
*X11DRV_XShmCreateImage( int width
, int height
, int bpp
,
4523 XShmSegmentInfo
* shminfo
)
4527 image
= XShmCreateImage(gdi_display
, visual
, bpp
, ZPixmap
, NULL
, shminfo
, width
, height
);
4530 shminfo
->shmid
= shmget(IPC_PRIVATE
, image
->bytes_per_line
* height
,
4532 if( shminfo
->shmid
!= -1 )
4534 shminfo
->shmaddr
= image
->data
= shmat(shminfo
->shmid
, 0, 0);
4535 if( shminfo
->shmaddr
!= (char*)-1 )
4539 shminfo
->readOnly
= FALSE
;
4540 X11DRV_expect_error( gdi_display
, XShmErrorHandler
, NULL
);
4541 ok
= (XShmAttach( gdi_display
, shminfo
) != 0);
4542 XSync( gdi_display
, False
);
4543 if (X11DRV_check_error()) ok
= FALSE
;
4546 shmctl(shminfo
->shmid
, IPC_RMID
, 0);
4547 return image
; /* Success! */
4549 /* An error occurred */
4550 shmdt(shminfo
->shmaddr
);
4552 shmctl(shminfo
->shmid
, IPC_RMID
, 0);
4554 XFlush(gdi_display
);
4555 XDestroyImage(image
);
4560 #endif /* HAVE_LIBXXSHM */
4563 /***********************************************************************
4564 * X11DRV_CreateDIBSection (X11DRV.@)
4566 HBITMAP
X11DRV_CreateDIBSection( X11DRV_PDEVICE
*physDev
, HBITMAP hbitmap
,
4567 const BITMAPINFO
*bmi
, UINT usage
)
4569 extern BOOL
VIRTUAL_SetFaultHandler(LPCVOID addr
, BOOL (*proc
)(LPVOID
, LPCVOID
), LPVOID arg
);
4570 X_PHYSBITMAP
*physBitmap
;
4573 if (!(physBitmap
= X11DRV_init_phys_bitmap( hbitmap
))) return 0;
4574 physBitmap
->status
= DIB_Status_None
;
4576 GetObjectW( hbitmap
, sizeof(dib
), &dib
);
4578 /* create color map */
4579 if (dib
.dsBm
.bmBitsPixel
<= 8)
4581 physBitmap
->colorMap
= X11DRV_DIB_BuildColorMap( usage
== DIB_PAL_COLORS
? physDev
: NULL
,
4582 usage
, dib
.dsBm
.bmBitsPixel
, bmi
,
4583 &physBitmap
->nColorMap
);
4584 physBitmap
->colorTable
= X11DRV_DIB_BuildColorTable( physDev
, usage
, dib
.dsBm
.bmBitsPixel
, bmi
);
4587 /* create pixmap and X image */
4589 physBitmap
->pixmap_depth
= (dib
.dsBm
.bmBitsPixel
== 1) ? 1 : screen_depth
;
4590 physBitmap
->pixmap
= XCreatePixmap( gdi_display
, root_window
, dib
.dsBm
.bmWidth
,
4591 dib
.dsBm
.bmHeight
, physBitmap
->pixmap_depth
);
4592 #ifdef HAVE_LIBXXSHM
4593 physBitmap
->shminfo
.shmid
= -1;
4594 if (!XShmQueryExtension(gdi_display
) ||
4595 !(physBitmap
->image
= X11DRV_XShmCreateImage( dib
.dsBm
.bmWidth
, dib
.dsBm
.bmHeight
,
4596 physBitmap
->pixmap_depth
, &physBitmap
->shminfo
)) )
4598 physBitmap
->image
= X11DRV_DIB_CreateXImage( dib
.dsBm
.bmWidth
, dib
.dsBm
.bmHeight
,
4599 physBitmap
->pixmap_depth
);
4600 wine_tsx11_unlock();
4601 if (!physBitmap
->pixmap
|| !physBitmap
->image
) return 0;
4603 /* install fault handler */
4604 InitializeCriticalSection( &physBitmap
->lock
);
4605 if (VIRTUAL_SetFaultHandler(dib
.dsBm
.bmBits
, X11DRV_DIB_FaultHandler
, physBitmap
))
4607 X11DRV_DIB_DoProtectDIBSection( physBitmap
, PAGE_READWRITE
);
4608 physBitmap
->status
= DIB_Status_AppMod
;
4614 /***********************************************************************
4615 * X11DRV_DIB_DeleteDIBSection
4617 void X11DRV_DIB_DeleteDIBSection(X_PHYSBITMAP
*physBitmap
, DIBSECTION
*dib
)
4619 if (dib
->dshSection
)
4620 X11DRV_DIB_Coerce(physBitmap
, DIB_Status_InSync
, FALSE
);
4622 if (physBitmap
->image
)
4625 #ifdef HAVE_LIBXXSHM
4626 if (physBitmap
->shminfo
.shmid
!= -1)
4628 XShmDetach( gdi_display
, &(physBitmap
->shminfo
) );
4629 XDestroyImage( physBitmap
->image
);
4630 shmdt( physBitmap
->shminfo
.shmaddr
);
4631 physBitmap
->shminfo
.shmid
= -1;
4635 XDestroyImage( physBitmap
->image
);
4636 wine_tsx11_unlock();
4639 HeapFree(GetProcessHeap(), 0, physBitmap
->colorMap
);
4640 HeapFree(GetProcessHeap(), 0, physBitmap
->colorTable
);
4641 DeleteCriticalSection(&physBitmap
->lock
);
4644 /***********************************************************************
4645 * SetDIBColorTable (X11DRV.@)
4647 UINT
X11DRV_SetDIBColorTable( X11DRV_PDEVICE
*physDev
, UINT start
, UINT count
, const RGBQUAD
*colors
)
4651 X_PHYSBITMAP
*physBitmap
= physDev
->bitmap
;
4653 if (!physBitmap
) return 0;
4654 GetObjectW( physBitmap
->hbitmap
, sizeof(dib
), &dib
);
4656 if (physBitmap
->colorMap
&& start
< physBitmap
->nColorMap
) {
4657 UINT end
= count
+ start
;
4658 if (end
> physBitmap
->nColorMap
) end
= physBitmap
->nColorMap
;
4660 * Changing color table might change the mapping between
4661 * DIB colors and X11 colors and thus alter the visible state
4662 * of the bitmap object.
4664 X11DRV_DIB_Lock( physBitmap
, DIB_Status_AppMod
, FALSE
);
4665 memcpy(physBitmap
->colorTable
+ start
, colors
, (end
- start
) * sizeof(RGBQUAD
));
4666 X11DRV_DIB_GenColorMap( physDev
, physBitmap
->colorMap
, DIB_RGB_COLORS
,
4667 dib
.dsBm
.bmBitsPixel
,
4668 TRUE
, colors
, start
, end
);
4669 X11DRV_DIB_Unlock( physBitmap
, TRUE
);
4675 /***********************************************************************
4676 * GetDIBColorTable (X11DRV.@)
4678 UINT
X11DRV_GetDIBColorTable( X11DRV_PDEVICE
*physDev
, UINT start
, UINT count
, RGBQUAD
*colors
)
4681 X_PHYSBITMAP
*physBitmap
= physDev
->bitmap
;
4683 if (physBitmap
&& physBitmap
->colorTable
&& start
< physBitmap
->nColorMap
) {
4684 if (start
+ count
> physBitmap
->nColorMap
) count
= physBitmap
->nColorMap
- start
;
4685 memcpy(colors
, physBitmap
->colorTable
+ start
, count
* sizeof(RGBQUAD
));
4693 /***********************************************************************
4694 * X11DRV_DIB_CreateDIBFromBitmap
4696 * Allocates a packed DIB and copies the bitmap data into it.
4698 HGLOBAL
X11DRV_DIB_CreateDIBFromBitmap(HDC hdc
, HBITMAP hBmp
)
4703 LPBITMAPINFOHEADER pbmiHeader
;
4704 unsigned int cDataSize
, cPackedSize
, OffsetBits
;
4707 if (!GetObjectW( hBmp
, sizeof(bmp
), &bmp
)) return 0;
4710 * A packed DIB contains a BITMAPINFO structure followed immediately by
4711 * an optional color palette and the pixel data.
4714 /* Calculate the size of the packed DIB */
4715 cDataSize
= X11DRV_DIB_GetDIBWidthBytes( bmp
.bmWidth
, bmp
.bmBitsPixel
) * abs( bmp
.bmHeight
);
4716 cPackedSize
= sizeof(BITMAPINFOHEADER
)
4717 + ( (bmp
.bmBitsPixel
<= 8) ? (sizeof(RGBQUAD
) * (1 << bmp
.bmBitsPixel
)) : 0 )
4719 /* Get the offset to the bits */
4720 OffsetBits
= cPackedSize
- cDataSize
;
4722 /* Allocate the packed DIB */
4723 TRACE("\tAllocating packed DIB of size %d\n", cPackedSize
);
4724 hPackedDIB
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_DDESHARE
/*| GMEM_ZEROINIT*/,
4728 WARN("Could not allocate packed DIB!\n");
4732 /* A packed DIB starts with a BITMAPINFOHEADER */
4733 pPackedDIB
= GlobalLock(hPackedDIB
);
4734 pbmiHeader
= (LPBITMAPINFOHEADER
)pPackedDIB
;
4736 /* Init the BITMAPINFOHEADER */
4737 pbmiHeader
->biSize
= sizeof(BITMAPINFOHEADER
);
4738 pbmiHeader
->biWidth
= bmp
.bmWidth
;
4739 pbmiHeader
->biHeight
= bmp
.bmHeight
;
4740 pbmiHeader
->biPlanes
= 1;
4741 pbmiHeader
->biBitCount
= bmp
.bmBitsPixel
;
4742 pbmiHeader
->biCompression
= BI_RGB
;
4743 pbmiHeader
->biSizeImage
= 0;
4744 pbmiHeader
->biXPelsPerMeter
= pbmiHeader
->biYPelsPerMeter
= 0;
4745 pbmiHeader
->biClrUsed
= 0;
4746 pbmiHeader
->biClrImportant
= 0;
4748 /* Retrieve the DIB bits from the bitmap and fill in the
4749 * DIB color table if present */
4751 nLinesCopied
= GetDIBits(hdc
, /* Handle to device context */
4752 hBmp
, /* Handle to bitmap */
4753 0, /* First scan line to set in dest bitmap */
4754 bmp
.bmHeight
, /* Number of scan lines to copy */
4755 pPackedDIB
+ OffsetBits
, /* [out] Address of array for bitmap bits */
4756 (LPBITMAPINFO
) pbmiHeader
, /* [out] Address of BITMAPINFO structure */
4757 0); /* RGB or palette index */
4758 GlobalUnlock(hPackedDIB
);
4760 /* Cleanup if GetDIBits failed */
4761 if (nLinesCopied
!= bmp
.bmHeight
)
4763 TRACE("\tGetDIBits returned %d. Actual lines=%d\n", nLinesCopied
, bmp
.bmHeight
);
4764 GlobalFree(hPackedDIB
);
4771 /**************************************************************************
4772 * X11DRV_DIB_CreateDIBFromPixmap
4774 * Allocates a packed DIB and copies the Pixmap data into it.
4775 * The Pixmap passed in is deleted after the conversion.
4777 HGLOBAL
X11DRV_DIB_CreateDIBFromPixmap(Pixmap pixmap
, HDC hdc
)
4780 X_PHYSBITMAP
*physBitmap
;
4781 HBITMAP hBmp
= 0, old
;
4782 HGLOBAL hPackedDIB
= 0;
4784 int x
,y
; /* Unused */
4785 unsigned border_width
; /* Unused */
4786 unsigned int depth
, width
, height
;
4788 /* Get the Pixmap dimensions and bit depth */
4790 if (!XGetGeometry(gdi_display
, pixmap
, &root
, &x
, &y
, &width
, &height
,
4791 &border_width
, &depth
)) depth
= 0;
4792 wine_tsx11_unlock();
4793 if (!depth
) return 0;
4795 TRACE("\tPixmap properties: width=%d, height=%d, depth=%d\n",
4796 width
, height
, depth
);
4799 * Create an HBITMAP with the same dimensions and BPP as the pixmap,
4800 * and make it a container for the pixmap passed.
4802 hBmp
= CreateBitmap( width
, height
, 1, depth
, NULL
);
4804 /* force bitmap to be owned by a screen DC */
4805 hdcMem
= CreateCompatibleDC( hdc
);
4806 old
= SelectObject( hdcMem
, hBmp
);
4808 physBitmap
= X11DRV_get_phys_bitmap( hBmp
);
4811 if (physBitmap
->pixmap
) XFreePixmap( gdi_display
, physBitmap
->pixmap
);
4812 physBitmap
->pixmap
= pixmap
;
4813 wine_tsx11_unlock();
4815 SelectObject( hdcMem
, old
);
4819 * Create a packed DIB from the Pixmap wrapper bitmap created above.
4820 * A packed DIB contains a BITMAPINFO structure followed immediately by
4821 * an optional color palette and the pixel data.
4823 hPackedDIB
= X11DRV_DIB_CreateDIBFromBitmap(hdc
, hBmp
);
4825 /* We can now get rid of the HBITMAP wrapper we created earlier.
4826 * Note: Simply calling DeleteObject will free the embedded Pixmap as well.
4830 TRACE("\tReturning packed DIB %p\n", hPackedDIB
);
4835 /**************************************************************************
4836 * X11DRV_DIB_CreatePixmapFromDIB
4838 * Creates a Pixmap from a packed DIB
4840 Pixmap
X11DRV_DIB_CreatePixmapFromDIB( HGLOBAL hPackedDIB
, HDC hdc
)
4843 X_PHYSBITMAP
*physBitmap
;
4847 /* Create a DDB from the DIB */
4849 pbmi
= GlobalLock(hPackedDIB
);
4850 hBmp
= CreateDIBitmap(hdc
, &pbmi
->bmiHeader
, CBM_INIT
,
4851 (LPBYTE
)pbmi
+ X11DRV_DIB_BitmapInfoSize( pbmi
, DIB_RGB_COLORS
),
4852 pbmi
, DIB_RGB_COLORS
);
4853 GlobalUnlock(hPackedDIB
);
4855 /* clear the physBitmap so that we can steal its pixmap */
4856 physBitmap
= X11DRV_get_phys_bitmap( hBmp
);
4857 pixmap
= physBitmap
->pixmap
;
4858 physBitmap
->pixmap
= 0;
4860 /* Delete the DDB we created earlier now that we have stolen its pixmap */
4863 TRACE("Returning Pixmap %ld\n", pixmap
);