2 * X11DRV device-independent bitmaps
4 * Copyright 1993,1994 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "wine/port.h"
26 #include <X11/extensions/XShm.h>
27 # ifdef HAVE_SYS_SHM_H
30 # ifdef HAVE_SYS_IPC_H
33 #endif /* defined(HAVE_LIBXXSHM) */
42 #include "wine/exception.h"
43 #include "wine/debug.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(bitmap
);
47 static struct list dibs_list
= LIST_INIT(dibs_list
);
49 static CRITICAL_SECTION dibs_cs
;
50 static CRITICAL_SECTION_DEBUG dibs_cs_debug
=
53 { &dibs_cs_debug
.ProcessLocksList
, &dibs_cs_debug
.ProcessLocksList
},
54 0, 0, { (DWORD_PTR
)(__FILE__
": dibs_cs") }
56 static CRITICAL_SECTION dibs_cs
= { &dibs_cs_debug
, -1, 0, 0, 0, 0 };
58 static PVOID dibs_handler
;
60 static int ximageDepthTable
[32];
62 /* This structure holds the arguments for DIB_SetImageBits() */
65 X11DRV_PDEVICE
*physDev
;
68 PALETTEENTRY
*palentry
;
90 } X11DRV_DIB_IMAGEBITS_DESCR
;
95 RLE_EOL
= 0, /* End of line */
96 RLE_END
= 1, /* End of bitmap */
97 RLE_DELTA
= 2 /* Delta */
101 static INT
X11DRV_DIB_Coerce(X_PHYSBITMAP
*,INT
);
102 static INT
X11DRV_DIB_Lock(X_PHYSBITMAP
*,INT
);
103 static void X11DRV_DIB_Unlock(X_PHYSBITMAP
*,BOOL
);
106 Some of the following helper functions are duplicated in
110 /***********************************************************************
111 * DIB_DoProtectDIBSection
113 static void X11DRV_DIB_DoProtectDIBSection( X_PHYSBITMAP
*physBitmap
, DWORD new_prot
)
117 VirtualProtect(physBitmap
->base
, physBitmap
->size
, new_prot
, &old_prot
);
118 TRACE("Changed protection from %d to %d\n", old_prot
, new_prot
);
121 /***********************************************************************
122 * X11DRV_DIB_GetXImageWidthBytes
124 * Return the width of an X image in bytes
126 static inline int X11DRV_DIB_GetXImageWidthBytes( int width
, int depth
)
128 if (!depth
|| depth
> 32) goto error
;
130 if (!ximageDepthTable
[depth
-1])
132 XImage
*testimage
= XCreateImage( gdi_display
, visual
, depth
,
133 ZPixmap
, 0, NULL
, 1, 1, 32, 20 );
136 ximageDepthTable
[depth
-1] = testimage
->bits_per_pixel
;
137 XDestroyImage( testimage
);
139 else ximageDepthTable
[depth
-1] = -1;
141 if (ximageDepthTable
[depth
-1] != -1)
142 return (4 * ((width
* ximageDepthTable
[depth
-1] + 31) / 32));
145 WARN( "(%d): Unsupported depth\n", depth
);
150 /***********************************************************************
151 * X11DRV_DIB_GetDIBWidthBytes
153 * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
155 static int X11DRV_DIB_GetDIBWidthBytes( int width
, int depth
)
161 case 1: words
= (width
+ 31) / 32; break;
162 case 4: words
= (width
+ 7) / 8; break;
163 case 8: words
= (width
+ 3) / 4; break;
165 case 16: words
= (width
+ 1) / 2; break;
166 case 24: words
= (width
* 3 + 3) / 4; break;
168 WARN("(%d): Unsupported depth\n", depth
);
177 /***********************************************************************
178 * X11DRV_DIB_GetDIBImageBytes
180 * Return the number of bytes used to hold the image in a DIB bitmap.
182 static int X11DRV_DIB_GetDIBImageBytes( int width
, int height
, int depth
)
184 return X11DRV_DIB_GetDIBWidthBytes( width
, depth
) * abs( height
);
188 /***********************************************************************
191 * Return the size of the bitmap info structure including color table.
193 int bitmap_info_size( const BITMAPINFO
* info
, WORD coloruse
)
195 unsigned int colors
, masks
= 0;
197 if (info
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
199 const BITMAPCOREHEADER
*core
= (const BITMAPCOREHEADER
*)info
;
200 colors
= (core
->bcBitCount
<= 8) ? 1 << core
->bcBitCount
: 0;
201 return sizeof(BITMAPCOREHEADER
) + colors
*
202 ((coloruse
== DIB_RGB_COLORS
) ? sizeof(RGBTRIPLE
) : sizeof(WORD
));
204 else /* assume BITMAPINFOHEADER */
206 colors
= info
->bmiHeader
.biClrUsed
;
207 if (!colors
&& (info
->bmiHeader
.biBitCount
<= 8))
208 colors
= 1 << info
->bmiHeader
.biBitCount
;
209 if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
) masks
= 3;
210 return sizeof(BITMAPINFOHEADER
) + masks
* sizeof(DWORD
) + colors
*
211 ((coloruse
== DIB_RGB_COLORS
) ? sizeof(RGBQUAD
) : sizeof(WORD
));
216 /***********************************************************************
217 * X11DRV_DIB_CreateXImage
221 XImage
*X11DRV_DIB_CreateXImage( int width
, int height
, int depth
)
224 XImage
*image
= NULL
;
228 width_bytes
= X11DRV_DIB_GetXImageWidthBytes( width
, depth
);
229 data
= HeapAlloc( GetProcessHeap(), 0, height
* width_bytes
);
230 if (data
) image
= XCreateImage( gdi_display
, visual
, depth
, ZPixmap
, 0,
231 data
, width
, height
, 32, width_bytes
);
232 if (!image
) HeapFree( GetProcessHeap(), 0, data
);
238 /***********************************************************************
239 * X11DRV_DIB_DestroyXImage
241 * Destroy an X image created with X11DRV_DIB_CreateXImage.
243 void X11DRV_DIB_DestroyXImage( XImage
*image
)
245 HeapFree( GetProcessHeap(), 0, image
->data
);
248 XDestroyImage( image
);
253 /***********************************************************************
254 * DIB_GetBitmapInfoEx
256 * Get the info from a bitmap header.
257 * Return 1 for INFOHEADER, 0 for COREHEADER, -1 for error.
259 static int DIB_GetBitmapInfoEx( const BITMAPINFOHEADER
*header
, LONG
*width
,
260 LONG
*height
, WORD
*planes
, WORD
*bpp
,
261 WORD
*compr
, DWORD
*size
)
263 if (header
->biSize
== sizeof(BITMAPCOREHEADER
))
265 const BITMAPCOREHEADER
*core
= (const BITMAPCOREHEADER
*)header
;
266 *width
= core
->bcWidth
;
267 *height
= core
->bcHeight
;
268 *planes
= core
->bcPlanes
;
269 *bpp
= core
->bcBitCount
;
274 if (header
->biSize
>= sizeof(BITMAPINFOHEADER
))
276 *width
= header
->biWidth
;
277 *height
= header
->biHeight
;
278 *planes
= header
->biPlanes
;
279 *bpp
= header
->biBitCount
;
280 *compr
= header
->biCompression
;
281 *size
= header
->biSizeImage
;
284 ERR("(%d): unknown/wrong size for header\n", header
->biSize
);
289 /***********************************************************************
290 * X11DRV_DIB_GetColorCount
292 * Computes the number of colors for the bitmap palette.
293 * Should not be called for a >8-bit deep bitmap.
295 static unsigned int X11DRV_DIB_GetColorCount(const BITMAPINFO
*info
)
298 BOOL core_info
= info
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
);
302 colors
= 1 << ((const BITMAPCOREINFO
*)info
)->bmciHeader
.bcBitCount
;
306 colors
= info
->bmiHeader
.biClrUsed
;
307 if (!colors
) colors
= 1 << info
->bmiHeader
.biBitCount
;
311 ERR("called with >256 colors!\n");
317 /***********************************************************************
320 * Get the info from a bitmap header.
321 * Return 1 for INFOHEADER, 0 for COREHEADER, -1 for error.
323 static int DIB_GetBitmapInfo( const BITMAPINFOHEADER
*header
, LONG
*width
,
324 LONG
*height
, WORD
*bpp
, WORD
*compr
)
329 return DIB_GetBitmapInfoEx( header
, width
, height
, &planes
, bpp
, compr
, &size
);
333 static inline BOOL
colour_is_brighter(RGBQUAD c1
, RGBQUAD c2
)
335 return (c1
.rgbRed
* c1
.rgbRed
+ c1
.rgbGreen
* c1
.rgbGreen
+ c1
.rgbBlue
* c1
.rgbBlue
) >
336 (c2
.rgbRed
* c2
.rgbRed
+ c2
.rgbGreen
* c2
.rgbGreen
+ c2
.rgbBlue
* c2
.rgbBlue
);
339 /***********************************************************************
340 * X11DRV_DIB_GenColorMap
342 * Fills the color map of a bitmap palette. Should not be called
343 * for a >8-bit deep bitmap.
345 static int *X11DRV_DIB_GenColorMap( X11DRV_PDEVICE
*physDev
, int *colorMapping
,
346 WORD coloruse
, WORD depth
, BOOL quads
,
347 const void *colorPtr
, int start
, int end
)
351 if (coloruse
== DIB_RGB_COLORS
)
355 const RGBQUAD
* rgb
= colorPtr
;
357 if (depth
== 1) /* Monochrome */
362 if (GetDIBColorTable( physDev
->hdc
, 0, 2, table
) == 2)
363 invert
= !colour_is_brighter(table
[1], table
[0]);
365 for (i
= start
; i
< end
; i
++, rgb
++)
366 colorMapping
[i
] = ((rgb
->rgbRed
+ rgb
->rgbGreen
+
367 rgb
->rgbBlue
> 255*3/2 && !invert
) ||
368 (rgb
->rgbRed
+ rgb
->rgbGreen
+
369 rgb
->rgbBlue
<= 255*3/2 && invert
));
372 for (i
= start
; i
< end
; i
++, rgb
++)
373 colorMapping
[i
] = X11DRV_PALETTE_ToPhysical( NULL
, RGB(rgb
->rgbRed
,
379 const RGBTRIPLE
* rgb
= colorPtr
;
381 if (depth
== 1) /* Monochrome */
386 if (GetDIBColorTable( physDev
->hdc
, 0, 2, table
) == 2)
387 invert
= !colour_is_brighter(table
[1], table
[0]);
389 for (i
= start
; i
< end
; i
++, rgb
++)
390 colorMapping
[i
] = ((rgb
->rgbtRed
+ rgb
->rgbtGreen
+
391 rgb
->rgbtBlue
> 255*3/2 && !invert
) ||
392 (rgb
->rgbtRed
+ rgb
->rgbtGreen
+
393 rgb
->rgbtBlue
<= 255*3/2 && invert
));
396 for (i
= start
; i
< end
; i
++, rgb
++)
397 colorMapping
[i
] = X11DRV_PALETTE_ToPhysical( NULL
, RGB(rgb
->rgbtRed
,
402 else /* DIB_PAL_COLORS */
404 const WORD
* index
= colorPtr
;
406 for (i
= start
; i
< end
; i
++, index
++)
407 colorMapping
[i
] = X11DRV_PALETTE_ToPhysical( physDev
, PALETTEINDEX(*index
) );
413 /***********************************************************************
414 * X11DRV_DIB_BuildColorMap
416 * Build the color map from the bitmap palette. Should not be called
417 * for a >8-bit deep bitmap.
419 static int *X11DRV_DIB_BuildColorMap( X11DRV_PDEVICE
*physDev
, WORD coloruse
, WORD depth
,
420 const BITMAPINFO
*info
, int *nColors
)
423 const void *colorPtr
;
427 *nColors
= X11DRV_DIB_GetColorCount(info
);
428 if (!*nColors
) return NULL
;
430 isInfo
= info
->bmiHeader
.biSize
!= sizeof(BITMAPCOREHEADER
);
431 colorPtr
= (const BYTE
*)info
+ (WORD
)info
->bmiHeader
.biSize
;
432 if (!(colorMapping
= HeapAlloc(GetProcessHeap(), 0, *nColors
* sizeof(int) )))
435 return X11DRV_DIB_GenColorMap( physDev
, colorMapping
, coloruse
, depth
,
436 isInfo
, colorPtr
, 0, *nColors
);
439 /***********************************************************************
440 * X11DRV_DIB_MapColor
442 static int X11DRV_DIB_MapColor( int *physMap
, int nPhysMap
, int phys
, int oldcol
)
446 if ((oldcol
< nPhysMap
) && (physMap
[oldcol
] == phys
))
449 for (color
= 0; color
< nPhysMap
; color
++)
450 if (physMap
[color
] == phys
)
453 WARN("Strange color %08x\n", phys
);
458 /*********************************************************************
459 * X11DRV_DIB_GetNearestIndex
461 * Helper for X11DRV_DIB_GetDIBits.
462 * Returns the nearest colour table index for a given RGB.
463 * Nearest is defined by minimizing the sum of the squares.
465 static INT
X11DRV_DIB_GetNearestIndex(RGBQUAD
*colormap
, int numColors
, BYTE r
, BYTE g
, BYTE b
)
467 INT i
, best
= -1, diff
, bestdiff
= -1;
470 for(color
= colormap
, i
= 0; i
< numColors
; color
++, i
++) {
471 diff
= (r
- color
->rgbRed
) * (r
- color
->rgbRed
) +
472 (g
- color
->rgbGreen
) * (g
- color
->rgbGreen
) +
473 (b
- color
->rgbBlue
) * (b
- color
->rgbBlue
);
476 if(best
== -1 || diff
< bestdiff
) {
483 /*********************************************************************
484 * X11DRV_DIB_MaskToShift
486 * Helper for X11DRV_DIB_GetDIBits.
487 * Returns the by how many bits to shift a given color so that it is
488 * in the proper position.
490 INT
X11DRV_DIB_MaskToShift(DWORD mask
)
498 while ((mask
&1)==0) {
505 /***********************************************************************
506 * X11DRV_DIB_CheckMask
508 * Check RGB mask if it is either 0 or matches visual's mask.
510 static inline int X11DRV_DIB_CheckMask(int red_mask
, int green_mask
, int blue_mask
)
512 return ( red_mask
== 0 && green_mask
== 0 && blue_mask
== 0 ) ||
513 ( red_mask
== visual
->red_mask
&& green_mask
== visual
->green_mask
&&
514 blue_mask
== visual
->blue_mask
);
517 /***********************************************************************
518 * X11DRV_DIB_SetImageBits_1
520 * SetDIBits for a 1-bit deep DIB.
522 static void X11DRV_DIB_SetImageBits_1( int lines
, const BYTE
*srcbits
,
523 DWORD srcwidth
, DWORD dstwidth
, int left
,
524 int *colors
, XImage
*bmpImage
, DWORD linebytes
)
533 srcbits
= srcbits
+ linebytes
* (lines
- 1);
534 linebytes
= -linebytes
;
537 if ((extra
= (left
& 7)) != 0) {
541 srcbits
+= left
>> 3;
542 width
= min(srcwidth
, dstwidth
);
544 /* ==== pal 1 dib -> any bmp format ==== */
545 for (h
= lines
-1; h
>=0; h
--) {
547 for (i
= width
/8, x
= left
; i
> 0; i
--) {
549 XPutPixel( bmpImage
, x
++, h
, colors
[ srcval
>> 7] );
550 XPutPixel( bmpImage
, x
++, h
, colors
[(srcval
>> 6) & 1] );
551 XPutPixel( bmpImage
, x
++, h
, colors
[(srcval
>> 5) & 1] );
552 XPutPixel( bmpImage
, x
++, h
, colors
[(srcval
>> 4) & 1] );
553 XPutPixel( bmpImage
, x
++, h
, colors
[(srcval
>> 3) & 1] );
554 XPutPixel( bmpImage
, x
++, h
, colors
[(srcval
>> 2) & 1] );
555 XPutPixel( bmpImage
, x
++, h
, colors
[(srcval
>> 1) & 1] );
556 XPutPixel( bmpImage
, x
++, h
, colors
[ srcval
& 1] );
562 case 7: XPutPixel(bmpImage
, x
++, h
, colors
[srcval
>> 7]); srcval
<<=1;
563 case 6: XPutPixel(bmpImage
, x
++, h
, colors
[srcval
>> 7]); srcval
<<=1;
564 case 5: XPutPixel(bmpImage
, x
++, h
, colors
[srcval
>> 7]); srcval
<<=1;
565 case 4: XPutPixel(bmpImage
, x
++, h
, colors
[srcval
>> 7]); srcval
<<=1;
566 case 3: XPutPixel(bmpImage
, x
++, h
, colors
[srcval
>> 7]); srcval
<<=1;
567 case 2: XPutPixel(bmpImage
, x
++, h
, colors
[srcval
>> 7]); srcval
<<=1;
568 case 1: XPutPixel(bmpImage
, x
++, h
, colors
[srcval
>> 7]);
571 srcbits
+= linebytes
;
575 /***********************************************************************
576 * X11DRV_DIB_GetImageBits_1
578 * GetDIBits for a 1-bit deep DIB.
580 static void X11DRV_DIB_GetImageBits_1( int lines
, BYTE
*dstbits
,
581 DWORD dstwidth
, DWORD srcwidth
,
582 RGBQUAD
*colors
, PALETTEENTRY
*srccolors
,
583 XImage
*bmpImage
, DWORD linebytes
)
586 int h
, width
= min(dstwidth
, srcwidth
);
590 dstbits
= dstbits
+ linebytes
* (lines
- 1);
591 linebytes
= -linebytes
;
594 switch (bmpImage
->depth
)
598 if (X11DRV_DIB_CheckMask(bmpImage
->red_mask
,bmpImage
->green_mask
,bmpImage
->blue_mask
)
600 /* ==== pal 1 or 4 bmp -> pal 1 dib ==== */
603 for (h
=lines
-1; h
>=0; h
--) {
607 for (x
=0; x
<width
; x
++) {
609 srcval
=srccolors
[XGetPixel(bmpImage
, x
, h
)];
610 dstval
|=(X11DRV_DIB_GetNearestIndex
614 srcval
.peBlue
) << (7 - (x
& 7)));
623 /* pad with 0 to DWORD alignment */
624 for (x
= (x
+7)&~7; x
< ((width
+ 31) & ~31); x
+=8)
626 dstbits
+= linebytes
;
634 if (X11DRV_DIB_CheckMask(bmpImage
->red_mask
, bmpImage
->green_mask
, bmpImage
->blue_mask
)
636 /* ==== pal 8 bmp -> pal 1 dib ==== */
638 const BYTE
* srcpixel
;
641 srcbits
=bmpImage
->data
+(lines
-1)*bmpImage
->bytes_per_line
;
643 for (h
=0; h
<lines
; h
++) {
648 for (x
=0; x
<width
; x
++) {
650 srcval
=srccolors
[*srcpixel
++];
651 dstval
|=(X11DRV_DIB_GetNearestIndex
655 srcval
.peBlue
) << (7-(x
&7)) );
664 srcbits
= (const char*)srcbits
- bmpImage
->bytes_per_line
;
665 dstbits
+= linebytes
;
676 const WORD
* srcpixel
;
679 srcbits
=bmpImage
->data
+(lines
-1)*bmpImage
->bytes_per_line
;
681 if (bmpImage
->green_mask
==0x03e0) {
682 if (bmpImage
->red_mask
==0x7c00) {
683 /* ==== rgb 555 bmp -> pal 1 dib ==== */
684 for (h
=0; h
<lines
; h
++) {
689 for (x
=0; x
<width
; x
++) {
692 dstval
|=(X11DRV_DIB_GetNearestIndex
694 ((srcval
>> 7) & 0xf8) | /* r */
695 ((srcval
>> 12) & 0x07),
696 ((srcval
>> 2) & 0xf8) | /* g */
697 ((srcval
>> 7) & 0x07),
698 ((srcval
<< 3) & 0xf8) | /* b */
699 ((srcval
>> 2) & 0x07) ) << (7-(x
&7)) );
708 srcbits
= (const char*)srcbits
- bmpImage
->bytes_per_line
;
709 dstbits
+= linebytes
;
711 } else if (bmpImage
->blue_mask
==0x7c00) {
712 /* ==== bgr 555 bmp -> pal 1 dib ==== */
713 for (h
=0; h
<lines
; h
++) {
718 for (x
=0; x
<width
; x
++) {
721 dstval
|=(X11DRV_DIB_GetNearestIndex
723 ((srcval
<< 3) & 0xf8) | /* r */
724 ((srcval
>> 2) & 0x07),
725 ((srcval
>> 2) & 0xf8) | /* g */
726 ((srcval
>> 7) & 0x07),
727 ((srcval
>> 7) & 0xf8) | /* b */
728 ((srcval
>> 12) & 0x07) ) << (7-(x
&7)) );
737 srcbits
= (const char*)srcbits
- bmpImage
->bytes_per_line
;
738 dstbits
+= linebytes
;
743 } else if (bmpImage
->green_mask
==0x07e0) {
744 if (bmpImage
->red_mask
==0xf800) {
745 /* ==== rgb 565 bmp -> pal 1 dib ==== */
746 for (h
=0; h
<lines
; h
++) {
751 for (x
=0; x
<width
; x
++) {
754 dstval
|=(X11DRV_DIB_GetNearestIndex
756 ((srcval
>> 8) & 0xf8) | /* r */
757 ((srcval
>> 13) & 0x07),
758 ((srcval
>> 3) & 0xfc) | /* g */
759 ((srcval
>> 9) & 0x03),
760 ((srcval
<< 3) & 0xf8) | /* b */
761 ((srcval
>> 2) & 0x07) ) << (7-(x
&7)) );
770 srcbits
= (const char*)srcbits
- bmpImage
->bytes_per_line
;
771 dstbits
+= linebytes
;
773 } else if (bmpImage
->blue_mask
==0xf800) {
774 /* ==== bgr 565 bmp -> pal 1 dib ==== */
775 for (h
=0; h
<lines
; h
++) {
780 for (x
=0; x
<width
; x
++) {
783 dstval
|=(X11DRV_DIB_GetNearestIndex
785 ((srcval
<< 3) & 0xf8) | /* r */
786 ((srcval
>> 2) & 0x07),
787 ((srcval
>> 3) & 0xfc) | /* g */
788 ((srcval
>> 9) & 0x03),
789 ((srcval
>> 8) & 0xf8) | /* b */
790 ((srcval
>> 13) & 0x07) ) << (7-(x
&7)) );
799 srcbits
= (const char*)srcbits
- bmpImage
->bytes_per_line
;
800 dstbits
+= linebytes
;
819 srcbits
=bmpImage
->data
+(lines
-1)*bmpImage
->bytes_per_line
;
820 bytes_per_pixel
=(bmpImage
->bits_per_pixel
==24?3:4);
822 if (bmpImage
->green_mask
!=0x00ff00 ||
823 (bmpImage
->red_mask
|bmpImage
->blue_mask
)!=0xff00ff) {
825 } else if (bmpImage
->blue_mask
==0xff) {
826 /* ==== rgb 888 or 0888 bmp -> pal 1 dib ==== */
827 for (h
=0; h
<lines
; h
++) {
832 for (x
=0; x
<width
; x
++) {
833 dstval
|=(X11DRV_DIB_GetNearestIndex
837 srcbyte
[0]) << (7-(x
&7)) );
838 srcbyte
+=bytes_per_pixel
;
847 srcbits
= (const char*)srcbits
- bmpImage
->bytes_per_line
;
848 dstbits
+= linebytes
;
851 /* ==== bgr 888 or 0888 bmp -> pal 1 dib ==== */
852 for (h
=0; h
<lines
; h
++) {
857 for (x
=0; x
<width
; x
++) {
858 dstval
|=(X11DRV_DIB_GetNearestIndex
862 srcbyte
[2]) << (7-(x
&7)) );
863 srcbyte
+=bytes_per_pixel
;
872 srcbits
= (const char*)srcbits
- bmpImage
->bytes_per_line
;
873 dstbits
+= linebytes
;
884 unsigned long white
= (1 << bmpImage
->bits_per_pixel
) - 1;
886 /* ==== any bmp format -> pal 1 dib ==== */
887 if ((unsigned)colors
[0].rgbRed
+colors
[0].rgbGreen
+colors
[0].rgbBlue
>=
888 (unsigned)colors
[1].rgbRed
+colors
[1].rgbGreen
+colors
[1].rgbBlue
)
891 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 1 bit DIB, "
892 "%s color mapping\n",
893 bmpImage
->bits_per_pixel
, bmpImage
->red_mask
,
894 bmpImage
->green_mask
, bmpImage
->blue_mask
,
895 neg
?"negative":"direct" );
897 for (h
=lines
-1; h
>=0; h
--) {
901 for (x
=0; x
<width
; x
++) {
902 dstval
|=((XGetPixel( bmpImage
, x
, h
) >= white
) ^ neg
) << (7 - (x
&7));
911 dstbits
+= linebytes
;
918 /***********************************************************************
919 * X11DRV_DIB_SetImageBits_4
921 * SetDIBits for a 4-bit deep DIB.
923 static void X11DRV_DIB_SetImageBits_4( int lines
, const BYTE
*srcbits
,
924 DWORD srcwidth
, DWORD dstwidth
, int left
,
925 int *colors
, XImage
*bmpImage
, DWORD linebytes
)
933 srcbits
= srcbits
+ linebytes
* (lines
- 1);
934 linebytes
= -linebytes
;
941 srcbits
+= left
>> 1;
942 width
= min(srcwidth
, dstwidth
);
944 /* ==== pal 4 dib -> any bmp format ==== */
945 for (h
= lines
-1; h
>= 0; h
--) {
947 for (i
= width
/2, x
= left
; i
> 0; i
--) {
948 BYTE srcval
=*srcbyte
++;
949 XPutPixel( bmpImage
, x
++, h
, colors
[srcval
>> 4] );
950 XPutPixel( bmpImage
, x
++, h
, colors
[srcval
& 0x0f] );
953 XPutPixel( bmpImage
, x
, h
, colors
[*srcbyte
>> 4] );
954 srcbits
+= linebytes
;
960 /***********************************************************************
961 * X11DRV_DIB_GetImageBits_4
963 * GetDIBits for a 4-bit deep DIB.
965 static void X11DRV_DIB_GetImageBits_4( int lines
, BYTE
*dstbits
,
966 DWORD srcwidth
, DWORD dstwidth
,
967 RGBQUAD
*colors
, PALETTEENTRY
*srccolors
,
968 XImage
*bmpImage
, DWORD linebytes
)
971 int h
, width
= min(srcwidth
, dstwidth
);
977 dstbits
= dstbits
+ ( linebytes
* (lines
-1) );
978 linebytes
= -linebytes
;
983 switch (bmpImage
->depth
) {
986 if (X11DRV_DIB_CheckMask(bmpImage
->red_mask
,bmpImage
->green_mask
,bmpImage
->blue_mask
)
988 /* ==== pal 1 or 4 bmp -> pal 4 dib ==== */
991 for (h
= lines
-1; h
>= 0; h
--) {
995 for (x
= 0; x
< width
; x
++) {
997 srcval
=srccolors
[XGetPixel(bmpImage
, x
, h
)];
998 dstval
|=(X11DRV_DIB_GetNearestIndex
1002 srcval
.peBlue
) << (4-((x
&1)<<2)));
1011 dstbits
+= linebytes
;
1019 if (X11DRV_DIB_CheckMask(bmpImage
->red_mask
,bmpImage
->green_mask
,bmpImage
->blue_mask
)
1021 /* ==== pal 8 bmp -> pal 4 dib ==== */
1022 const void* srcbits
;
1023 const BYTE
*srcpixel
;
1026 srcbits
=bmpImage
->data
+(lines
-1)*bmpImage
->bytes_per_line
;
1027 for (h
=0; h
<lines
; h
++) {
1032 for (x
=0; x
<width
; x
++) {
1033 PALETTEENTRY srcval
;
1034 srcval
= srccolors
[*srcpixel
++];
1035 dstval
|=(X11DRV_DIB_GetNearestIndex
1039 srcval
.peBlue
) << (4*(1-(x
&1))) );
1048 srcbits
= (const char*)srcbits
- bmpImage
->bytes_per_line
;
1049 dstbits
+= linebytes
;
1059 const void* srcbits
;
1060 const WORD
* srcpixel
;
1063 srcbits
=bmpImage
->data
+(lines
-1)*bmpImage
->bytes_per_line
;
1065 if (bmpImage
->green_mask
==0x03e0) {
1066 if (bmpImage
->red_mask
==0x7c00) {
1067 /* ==== rgb 555 bmp -> pal 4 dib ==== */
1068 for (h
=0; h
<lines
; h
++) {
1073 for (x
=0; x
<width
; x
++) {
1076 dstval
|=(X11DRV_DIB_GetNearestIndex
1078 ((srcval
>> 7) & 0xf8) | /* r */
1079 ((srcval
>> 12) & 0x07),
1080 ((srcval
>> 2) & 0xf8) | /* g */
1081 ((srcval
>> 7) & 0x07),
1082 ((srcval
<< 3) & 0xf8) | /* b */
1083 ((srcval
>> 2) & 0x07) ) << ((1-(x
&1))<<2) );
1092 srcbits
= (const char*)srcbits
- bmpImage
->bytes_per_line
;
1093 dstbits
+= linebytes
;
1095 } else if (bmpImage
->blue_mask
==0x7c00) {
1096 /* ==== bgr 555 bmp -> pal 4 dib ==== */
1097 for (h
=0; h
<lines
; h
++) {
1102 for (x
=0; x
<width
; x
++) {
1105 dstval
|=(X11DRV_DIB_GetNearestIndex
1107 ((srcval
<< 3) & 0xf8) | /* r */
1108 ((srcval
>> 2) & 0x07),
1109 ((srcval
>> 2) & 0xf8) | /* g */
1110 ((srcval
>> 7) & 0x07),
1111 ((srcval
>> 7) & 0xf8) | /* b */
1112 ((srcval
>> 12) & 0x07) ) << ((1-(x
&1))<<2) );
1121 srcbits
= (const char*)srcbits
- bmpImage
->bytes_per_line
;
1122 dstbits
+= linebytes
;
1127 } else if (bmpImage
->green_mask
==0x07e0) {
1128 if (bmpImage
->red_mask
==0xf800) {
1129 /* ==== rgb 565 bmp -> pal 4 dib ==== */
1130 for (h
=0; h
<lines
; h
++) {
1135 for (x
=0; x
<width
; x
++) {
1138 dstval
|=(X11DRV_DIB_GetNearestIndex
1140 ((srcval
>> 8) & 0xf8) | /* r */
1141 ((srcval
>> 13) & 0x07),
1142 ((srcval
>> 3) & 0xfc) | /* g */
1143 ((srcval
>> 9) & 0x03),
1144 ((srcval
<< 3) & 0xf8) | /* b */
1145 ((srcval
>> 2) & 0x07) ) << ((1-(x
&1))<<2) );
1154 srcbits
= (const char*)srcbits
- bmpImage
->bytes_per_line
;
1155 dstbits
+= linebytes
;
1157 } else if (bmpImage
->blue_mask
==0xf800) {
1158 /* ==== bgr 565 bmp -> pal 4 dib ==== */
1159 for (h
=0; h
<lines
; h
++) {
1164 for (x
=0; x
<width
; x
++) {
1167 dstval
|=(X11DRV_DIB_GetNearestIndex
1169 ((srcval
<< 3) & 0xf8) | /* r */
1170 ((srcval
>> 2) & 0x07),
1171 ((srcval
>> 3) & 0xfc) | /* g */
1172 ((srcval
>> 9) & 0x03),
1173 ((srcval
>> 8) & 0xf8) | /* b */
1174 ((srcval
>> 13) & 0x07) ) << ((1-(x
&1))<<2) );
1183 srcbits
= (const char*)srcbits
- bmpImage
->bytes_per_line
;
1184 dstbits
+= linebytes
;
1196 if (bmpImage
->bits_per_pixel
==24) {
1197 const void* srcbits
;
1198 const BYTE
*srcbyte
;
1201 srcbits
=bmpImage
->data
+(lines
-1)*bmpImage
->bytes_per_line
;
1203 if (bmpImage
->green_mask
!=0x00ff00 ||
1204 (bmpImage
->red_mask
|bmpImage
->blue_mask
)!=0xff00ff) {
1206 } else if (bmpImage
->blue_mask
==0xff) {
1207 /* ==== rgb 888 bmp -> pal 4 dib ==== */
1208 for (h
=0; h
<lines
; h
++) {
1211 for (x
=0; x
<width
/2; x
++) {
1212 /* Do 2 pixels at a time */
1213 *dstbyte
++=(X11DRV_DIB_GetNearestIndex
1218 X11DRV_DIB_GetNearestIndex
1226 /* And then the odd pixel */
1227 *dstbyte
++=(X11DRV_DIB_GetNearestIndex
1233 srcbits
= (const char*)srcbits
- bmpImage
->bytes_per_line
;
1234 dstbits
+= linebytes
;
1237 /* ==== bgr 888 bmp -> pal 4 dib ==== */
1238 for (h
=0; h
<lines
; h
++) {
1241 for (x
=0; x
<width
/2; x
++) {
1242 /* Do 2 pixels at a time */
1243 *dstbyte
++=(X11DRV_DIB_GetNearestIndex
1248 X11DRV_DIB_GetNearestIndex
1256 /* And then the odd pixel */
1257 *dstbyte
++=(X11DRV_DIB_GetNearestIndex
1263 srcbits
= (const char*)srcbits
- bmpImage
->bytes_per_line
;
1264 dstbits
+= linebytes
;
1273 const void* srcbits
;
1274 const BYTE
*srcbyte
;
1277 srcbits
=bmpImage
->data
+(lines
-1)*bmpImage
->bytes_per_line
;
1279 if (bmpImage
->green_mask
!=0x00ff00 ||
1280 (bmpImage
->red_mask
|bmpImage
->blue_mask
)!=0xff00ff) {
1282 } else if (bmpImage
->blue_mask
==0xff) {
1283 /* ==== rgb 0888 bmp -> pal 4 dib ==== */
1284 for (h
=0; h
<lines
; h
++) {
1287 for (x
=0; x
<width
/2; x
++) {
1288 /* Do 2 pixels at a time */
1289 *dstbyte
++=(X11DRV_DIB_GetNearestIndex
1294 X11DRV_DIB_GetNearestIndex
1302 /* And then the odd pixel */
1303 *dstbyte
++=(X11DRV_DIB_GetNearestIndex
1309 srcbits
= (const char*)srcbits
- bmpImage
->bytes_per_line
;
1310 dstbits
+= linebytes
;
1313 /* ==== bgr 0888 bmp -> pal 4 dib ==== */
1314 for (h
=0; h
<lines
; h
++) {
1317 for (x
=0; x
<width
/2; x
++) {
1318 /* Do 2 pixels at a time */
1319 *dstbyte
++=(X11DRV_DIB_GetNearestIndex
1324 X11DRV_DIB_GetNearestIndex
1332 /* And then the odd pixel */
1333 *dstbyte
++=(X11DRV_DIB_GetNearestIndex
1339 srcbits
= (const char*)srcbits
- bmpImage
->bytes_per_line
;
1340 dstbits
+= linebytes
;
1351 /* ==== any bmp format -> pal 4 dib ==== */
1352 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 4 bit DIB\n",
1353 bmpImage
->bits_per_pixel
, bmpImage
->red_mask
,
1354 bmpImage
->green_mask
, bmpImage
->blue_mask
);
1355 for (h
=lines
-1; h
>=0; h
--) {
1357 for (x
=0; x
<(width
& ~1); x
+=2) {
1358 *dstbyte
++=(X11DRV_DIB_MapColor((int*)colors
, 16, XGetPixel(bmpImage
, x
, h
), 0) << 4) |
1359 X11DRV_DIB_MapColor((int*)colors
, 16, XGetPixel(bmpImage
, x
+1, h
), 0);
1362 *dstbyte
=(X11DRV_DIB_MapColor((int *)colors
, 16, XGetPixel(bmpImage
, x
, h
), 0) << 4);
1364 dstbits
+= linebytes
;
1371 /***********************************************************************
1372 * X11DRV_DIB_SetImageBits_RLE4
1374 * SetDIBits for a 4-bit deep compressed DIB.
1376 static void X11DRV_DIB_SetImageBits_RLE4( int lines
, const BYTE
*bits
,
1377 DWORD srcwidth
, DWORD dstwidth
,
1378 int left
, int *colors
,
1381 unsigned int x
= 0, width
= min(srcwidth
, dstwidth
);
1382 int y
= lines
- 1, c
, length
;
1383 const BYTE
*begin
= bits
;
1388 if (length
) { /* encoded */
1391 if (x
>= (left
+ width
)) break;
1392 if( x
>= left
) XPutPixel(bmpImage
, x
, y
, colors
[c
>> 4]);
1394 if (!length
--) break;
1395 if (x
>= (left
+ width
)) break;
1396 if( x
>= left
) XPutPixel(bmpImage
, x
, y
, colors
[c
& 0xf]);
1416 default: /* absolute */
1419 if (x
>= left
&& x
< (left
+ width
))
1420 XPutPixel(bmpImage
, x
, y
, colors
[c
>> 4]);
1422 if (!length
--) break;
1423 if (x
>= left
&& x
< (left
+ width
))
1424 XPutPixel(bmpImage
, x
, y
, colors
[c
& 0xf]);
1427 if ((bits
- begin
) & 1)
1436 /***********************************************************************
1437 * X11DRV_DIB_SetImageBits_8
1439 * SetDIBits for an 8-bit deep DIB.
1441 static void X11DRV_DIB_SetImageBits_8( int lines
, const BYTE
*srcbits
,
1442 DWORD srcwidth
, DWORD dstwidth
, int left
,
1443 const int *colors
, XImage
*bmpImage
,
1447 int h
, width
= min(srcwidth
, dstwidth
);
1448 const BYTE
* srcbyte
;
1454 srcbits
= srcbits
+ linebytes
* (lines
-1);
1455 linebytes
= -linebytes
;
1460 switch (bmpImage
->depth
) {
1463 /* Some X servers might have 32 bit/ 16bit deep pixel */
1464 if (lines
&& width
&& (bmpImage
->bits_per_pixel
== 16) &&
1465 (ImageByteOrder(gdi_display
)==LSBFirst
) )
1467 /* ==== pal 8 dib -> rgb or bgr 555 or 565 bmp ==== */
1468 dstbits
=(BYTE
*)bmpImage
->data
+left
*2+(lines
-1)*bmpImage
->bytes_per_line
;
1469 for (h
= lines
; h
--; ) {
1470 #if defined(__i386__) && defined(__GNUC__)
1471 int _cl1
,_cl2
; /* temp outputs for asm below */
1472 /* Borrowed from DirectDraw */
1473 __asm__
__volatile__(
1478 " movw (%%edx,%%eax,4),%%ax\n"
1480 " xor %%eax,%%eax\n"
1482 :"=S" (srcbyte
), "=D" (_cl1
), "=c" (_cl2
)
1487 :"eax", "cc", "memory"
1490 DWORD
* dstpixel
=(DWORD
*)dstbits
;
1491 for (x
=0; x
<width
/2; x
++) {
1492 /* Do 2 pixels at a time */
1493 *dstpixel
++=(colors
[srcbyte
[1]] << 16) | colors
[srcbyte
[0]];
1497 /* And then the odd pixel */
1498 *((WORD
*)dstpixel
)=colors
[srcbyte
[0]];
1501 srcbyte
= (srcbits
+= linebytes
);
1502 dstbits
-= bmpImage
->bytes_per_line
;
1509 if (lines
&& width
&& (bmpImage
->bits_per_pixel
== 32) &&
1510 (ImageByteOrder(gdi_display
)==LSBFirst
) )
1512 dstbits
=(BYTE
*)bmpImage
->data
+left
*4+(lines
-1)*bmpImage
->bytes_per_line
;
1513 /* ==== pal 8 dib -> rgb or bgr 0888 bmp ==== */
1514 for (h
= lines
; h
--; ) {
1515 #if defined(__i386__) && defined(__GNUC__)
1516 int _cl1
,_cl2
; /* temp outputs for asm below */
1517 /* Borrowed from DirectDraw */
1518 __asm__
__volatile__(
1523 " movl (%%edx,%%eax,4),%%eax\n"
1525 " xor %%eax,%%eax\n"
1527 :"=S" (srcbyte
), "=D" (_cl1
), "=c" (_cl2
)
1532 :"eax", "cc", "memory"
1535 DWORD
* dstpixel
=(DWORD
*)dstbits
;
1536 for (x
=0; x
<width
; x
++) {
1537 *dstpixel
++=colors
[*srcbyte
++];
1540 srcbyte
= (srcbits
+= linebytes
);
1541 dstbits
-= bmpImage
->bytes_per_line
;
1547 break; /* use slow generic case below */
1550 /* ==== pal 8 dib -> any bmp format ==== */
1551 for (h
=lines
-1; h
>=0; h
--) {
1552 for (x
=left
; x
<width
+left
; x
++) {
1553 XPutPixel(bmpImage
, x
, h
, colors
[*srcbyte
++]);
1555 srcbyte
= (srcbits
+= linebytes
);
1559 /***********************************************************************
1560 * X11DRV_DIB_GetImageBits_8
1562 * GetDIBits for an 8-bit deep DIB.
1564 static void X11DRV_DIB_GetImageBits_8( int lines
, BYTE
*dstbits
,
1565 DWORD srcwidth
, DWORD dstwidth
,
1566 RGBQUAD
*colors
, PALETTEENTRY
*srccolors
,
1567 XImage
*bmpImage
, DWORD linebytes
)
1570 int h
, width
= min(srcwidth
, dstwidth
);
1576 dstbits
= dstbits
+ ( linebytes
* (lines
-1) );
1577 linebytes
= -linebytes
;
1582 * This condition is true when GetImageBits has been called by
1583 * UpdateDIBSection. For now, GetNearestIndex is too slow to support
1584 * 256 colormaps, so we'll just use it for GetDIBits calls.
1585 * (In some cases, in an updateDIBSection, the returned colors are bad too)
1587 if (!srccolors
) goto updatesection
;
1589 switch (bmpImage
->depth
) {
1592 if (X11DRV_DIB_CheckMask(bmpImage
->red_mask
,bmpImage
->green_mask
,bmpImage
->blue_mask
)
1595 /* ==== pal 1 bmp -> pal 8 dib ==== */
1596 /* ==== pal 4 bmp -> pal 8 dib ==== */
1597 for (h
=lines
-1; h
>=0; h
--) {
1599 for (x
=0; x
<width
; x
++) {
1600 PALETTEENTRY srcval
;
1601 srcval
=srccolors
[XGetPixel(bmpImage
, x
, h
)];
1602 *dstbyte
++=X11DRV_DIB_GetNearestIndex(colors
, 256,
1607 dstbits
+= linebytes
;
1615 if (X11DRV_DIB_CheckMask(bmpImage
->red_mask
,bmpImage
->green_mask
,bmpImage
->blue_mask
)
1617 /* ==== pal 8 bmp -> pal 8 dib ==== */
1618 const void* srcbits
;
1619 const BYTE
* srcpixel
;
1621 srcbits
=bmpImage
->data
+(lines
-1)*bmpImage
->bytes_per_line
;
1622 for (h
=0; h
<lines
; h
++) {
1625 for (x
= 0; x
< width
; x
++) {
1626 PALETTEENTRY srcval
;
1627 srcval
=srccolors
[*srcpixel
++];
1628 *dstbyte
++=X11DRV_DIB_GetNearestIndex(colors
, 256,
1633 srcbits
= (const char*)srcbits
- bmpImage
->bytes_per_line
;
1634 dstbits
+= linebytes
;
1644 const void* srcbits
;
1645 const WORD
* srcpixel
;
1648 srcbits
=bmpImage
->data
+(lines
-1)*bmpImage
->bytes_per_line
;
1650 if (bmpImage
->green_mask
==0x03e0) {
1651 if (bmpImage
->red_mask
==0x7c00) {
1652 /* ==== rgb 555 bmp -> pal 8 dib ==== */
1653 for (h
=0; h
<lines
; h
++) {
1656 for (x
=0; x
<width
; x
++) {
1659 *dstbyte
++=X11DRV_DIB_GetNearestIndex
1661 ((srcval
>> 7) & 0xf8) | /* r */
1662 ((srcval
>> 12) & 0x07),
1663 ((srcval
>> 2) & 0xf8) | /* g */
1664 ((srcval
>> 7) & 0x07),
1665 ((srcval
<< 3) & 0xf8) | /* b */
1666 ((srcval
>> 2) & 0x07) );
1668 srcbits
= (const char*)srcbits
- bmpImage
->bytes_per_line
;
1669 dstbits
+= linebytes
;
1671 } else if (bmpImage
->blue_mask
==0x7c00) {
1672 /* ==== bgr 555 bmp -> pal 8 dib ==== */
1673 for (h
=0; h
<lines
; h
++) {
1676 for (x
=0; x
<width
; x
++) {
1679 *dstbyte
++=X11DRV_DIB_GetNearestIndex
1681 ((srcval
<< 3) & 0xf8) | /* r */
1682 ((srcval
>> 2) & 0x07),
1683 ((srcval
>> 2) & 0xf8) | /* g */
1684 ((srcval
>> 7) & 0x07),
1685 ((srcval
>> 7) & 0xf8) | /* b */
1686 ((srcval
>> 12) & 0x07) );
1688 srcbits
= (const char*)srcbits
- bmpImage
->bytes_per_line
;
1689 dstbits
+= linebytes
;
1694 } else if (bmpImage
->green_mask
==0x07e0) {
1695 if (bmpImage
->red_mask
==0xf800) {
1696 /* ==== rgb 565 bmp -> pal 8 dib ==== */
1697 for (h
=0; h
<lines
; h
++) {
1700 for (x
=0; x
<width
; x
++) {
1703 *dstbyte
++=X11DRV_DIB_GetNearestIndex
1705 ((srcval
>> 8) & 0xf8) | /* r */
1706 ((srcval
>> 13) & 0x07),
1707 ((srcval
>> 3) & 0xfc) | /* g */
1708 ((srcval
>> 9) & 0x03),
1709 ((srcval
<< 3) & 0xf8) | /* b */
1710 ((srcval
>> 2) & 0x07) );
1712 srcbits
= (const char*)srcbits
- bmpImage
->bytes_per_line
;
1713 dstbits
+= linebytes
;
1715 } else if (bmpImage
->blue_mask
==0xf800) {
1716 /* ==== bgr 565 bmp -> pal 8 dib ==== */
1717 for (h
=0; h
<lines
; h
++) {
1720 for (x
=0; x
<width
; x
++) {
1723 *dstbyte
++=X11DRV_DIB_GetNearestIndex
1725 ((srcval
<< 3) & 0xf8) | /* r */
1726 ((srcval
>> 2) & 0x07),
1727 ((srcval
>> 3) & 0xfc) | /* g */
1728 ((srcval
>> 9) & 0x03),
1729 ((srcval
>> 8) & 0xf8) | /* b */
1730 ((srcval
>> 13) & 0x07) );
1732 srcbits
= (const char*)srcbits
- bmpImage
->bytes_per_line
;
1733 dstbits
+= linebytes
;
1747 const void* srcbits
;
1748 const BYTE
*srcbyte
;
1750 int bytes_per_pixel
;
1752 srcbits
=bmpImage
->data
+(lines
-1)*bmpImage
->bytes_per_line
;
1753 bytes_per_pixel
=(bmpImage
->bits_per_pixel
==24?3:4);
1755 if (bmpImage
->green_mask
!=0x00ff00 ||
1756 (bmpImage
->red_mask
|bmpImage
->blue_mask
)!=0xff00ff) {
1758 } else if (bmpImage
->blue_mask
==0xff) {
1759 /* ==== rgb 888 or 0888 bmp -> pal 8 dib ==== */
1760 for (h
=0; h
<lines
; h
++) {
1763 for (x
=0; x
<width
; x
++) {
1764 *dstbyte
++=X11DRV_DIB_GetNearestIndex
1769 srcbyte
+=bytes_per_pixel
;
1771 srcbits
= (const char*)srcbits
- bmpImage
->bytes_per_line
;
1772 dstbits
+= linebytes
;
1775 /* ==== bgr 888 or 0888 bmp -> pal 8 dib ==== */
1776 for (h
=0; h
<lines
; h
++) {
1779 for (x
=0; x
<width
; x
++) {
1780 *dstbyte
++=X11DRV_DIB_GetNearestIndex
1785 srcbyte
+=bytes_per_pixel
;
1787 srcbits
= (const char*)srcbits
- bmpImage
->bytes_per_line
;
1788 dstbits
+= linebytes
;
1796 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 8 bit DIB\n",
1797 bmpImage
->depth
, bmpImage
->red_mask
,
1798 bmpImage
->green_mask
, bmpImage
->blue_mask
);
1800 /* ==== any bmp format -> pal 8 dib ==== */
1801 for (h
=lines
-1; h
>=0; h
--) {
1803 for (x
=0; x
<width
; x
++) {
1804 *dstbyte
=X11DRV_DIB_MapColor
1806 XGetPixel(bmpImage
, x
, h
), *dstbyte
);
1809 dstbits
+= linebytes
;
1815 /***********************************************************************
1816 * X11DRV_DIB_SetImageBits_RLE8
1818 * SetDIBits for an 8-bit deep compressed DIB.
1820 * This function rewritten 941113 by James Youngman. WINE blew out when I
1821 * first ran it because my desktop wallpaper is a (large) RLE8 bitmap.
1823 * This was because the algorithm assumed that all RLE8 bitmaps end with the
1824 * 'End of bitmap' escape code. This code is very much laxer in what it
1825 * allows to end the expansion. Possibly too lax. See the note by
1826 * case RleDelta. BTW, MS's documentation implies that a correct RLE8
1827 * bitmap should end with RleEnd, but on the other hand, software exists
1828 * that produces ones that don't and Windows 3.1 doesn't complain a bit
1831 * (No) apologies for my English spelling. [Emacs users: c-indent-level=4].
1832 * James A. Youngman <mbcstjy@afs.man.ac.uk>
1835 static void X11DRV_DIB_SetImageBits_RLE8( int lines
, const BYTE
*bits
,
1836 DWORD srcwidth
, DWORD dstwidth
,
1837 int left
, int *colors
,
1840 unsigned int x
; /* X-position on each line. Increases. */
1841 int y
; /* Line #. Starts at lines-1, decreases */
1842 const BYTE
*pIn
= bits
; /* Pointer to current position in bits */
1843 BYTE length
; /* The length pf a run */
1844 BYTE escape_code
; /* See enum Rle8_EscapeCodes.*/
1847 * Note that the bitmap data is stored by Windows starting at the
1848 * bottom line of the bitmap and going upwards. Within each line,
1849 * the data is stored left-to-right. That's the reason why line
1850 * goes from lines-1 to 0. [JAY]
1860 * If the length byte is not zero (which is the escape value),
1861 * We have a run of length pixels all the same colour. The colour
1862 * index is stored next.
1864 * If the length byte is zero, we need to read the next byte to
1865 * know what to do. [JAY]
1870 * [Run-Length] Encoded mode
1872 int color
= colors
[*pIn
++];
1873 while (length
-- && x
< (left
+ dstwidth
)) {
1874 if( x
>= left
) XPutPixel(bmpImage
, x
, y
, color
);
1881 * Escape codes (may be an absolute sequence though)
1883 escape_code
= (*pIn
++);
1892 /* Not all RLE8 bitmaps end with this code. For
1893 * example, Paint Shop Pro produces some that don't.
1894 * That's (I think) what caused the previous
1895 * implementation to fail. [JAY]
1904 default: /* switch to absolute mode */
1905 length
= escape_code
;
1908 int color
= colors
[*pIn
++];
1909 if (x
>= (left
+ dstwidth
))
1914 if( x
>= left
) XPutPixel(bmpImage
, x
, y
, color
);
1918 * If you think for a moment you'll realise that the
1919 * only time we could ever possibly read an odd
1920 * number of bytes is when there is a 0x00 (escape),
1921 * a value >0x02 (absolute mode) and then an odd-
1922 * length run. Therefore this is the only place we
1923 * need to worry about it. Everywhere else the
1924 * bytes are always read in pairs. [JAY]
1926 if (escape_code
& 1) pIn
++; /* Throw away the pad byte. */
1928 } /* switch (escape_code) : Escape sequence */
1934 /***********************************************************************
1935 * X11DRV_DIB_SetImageBits_16
1937 * SetDIBits for a 16-bit deep DIB.
1939 static void X11DRV_DIB_SetImageBits_16( int lines
, const BYTE
*srcbits
,
1940 DWORD srcwidth
, DWORD dstwidth
, int left
,
1941 X11DRV_PDEVICE
*physDev
, DWORD rSrc
, DWORD gSrc
, DWORD bSrc
,
1942 XImage
*bmpImage
, DWORD linebytes
)
1945 int h
, width
= min(srcwidth
, dstwidth
);
1946 const dib_conversions
*convs
= (bmpImage
->byte_order
== LSBFirst
) ? &dib_normal
: &dib_dst_byteswap
;
1951 srcbits
= srcbits
+ ( linebytes
* (lines
-1));
1952 linebytes
= -linebytes
;
1955 switch (bmpImage
->depth
)
1962 srcbits
=srcbits
+left
*2;
1963 dstbits
=bmpImage
->data
+left
*2+(lines
-1)*bmpImage
->bytes_per_line
;
1965 if (bmpImage
->green_mask
==0x03e0) {
1966 if (gSrc
==bmpImage
->green_mask
) {
1967 if (rSrc
==bmpImage
->red_mask
) {
1968 /* ==== rgb 555 dib -> rgb 555 bmp ==== */
1969 /* ==== bgr 555 dib -> bgr 555 bmp ==== */
1970 convs
->Convert_5x5_asis
1973 dstbits
,-bmpImage
->bytes_per_line
);
1974 } else if (rSrc
==bmpImage
->blue_mask
) {
1975 /* ==== rgb 555 dib -> bgr 555 bmp ==== */
1976 /* ==== bgr 555 dib -> rgb 555 bmp ==== */
1977 convs
->Convert_555_reverse
1980 dstbits
,-bmpImage
->bytes_per_line
);
1983 if (rSrc
==bmpImage
->red_mask
|| bSrc
==bmpImage
->blue_mask
) {
1984 /* ==== rgb 565 dib -> rgb 555 bmp ==== */
1985 /* ==== bgr 565 dib -> bgr 555 bmp ==== */
1986 convs
->Convert_565_to_555_asis
1989 dstbits
,-bmpImage
->bytes_per_line
);
1991 /* ==== rgb 565 dib -> bgr 555 bmp ==== */
1992 /* ==== bgr 565 dib -> rgb 555 bmp ==== */
1993 convs
->Convert_565_to_555_reverse
1996 dstbits
,-bmpImage
->bytes_per_line
);
1999 } else if (bmpImage
->green_mask
==0x07e0) {
2000 if (gSrc
==bmpImage
->green_mask
) {
2001 if (rSrc
==bmpImage
->red_mask
) {
2002 /* ==== rgb 565 dib -> rgb 565 bmp ==== */
2003 /* ==== bgr 565 dib -> bgr 565 bmp ==== */
2004 convs
->Convert_5x5_asis
2007 dstbits
,-bmpImage
->bytes_per_line
);
2009 /* ==== rgb 565 dib -> bgr 565 bmp ==== */
2010 /* ==== bgr 565 dib -> rgb 565 bmp ==== */
2011 convs
->Convert_565_reverse
2014 dstbits
,-bmpImage
->bytes_per_line
);
2017 if (rSrc
==bmpImage
->red_mask
|| bSrc
==bmpImage
->blue_mask
) {
2018 /* ==== rgb 555 dib -> rgb 565 bmp ==== */
2019 /* ==== bgr 555 dib -> bgr 565 bmp ==== */
2020 convs
->Convert_555_to_565_asis
2023 dstbits
,-bmpImage
->bytes_per_line
);
2025 /* ==== rgb 555 dib -> bgr 565 bmp ==== */
2026 /* ==== bgr 555 dib -> rgb 565 bmp ==== */
2027 convs
->Convert_555_to_565_reverse
2030 dstbits
,-bmpImage
->bytes_per_line
);
2040 if (bmpImage
->bits_per_pixel
==24) {
2043 srcbits
=srcbits
+left
*2;
2044 dstbits
=bmpImage
->data
+left
*3+(lines
-1)*bmpImage
->bytes_per_line
;
2046 if (bmpImage
->green_mask
!=0x00ff00 ||
2047 (bmpImage
->red_mask
|bmpImage
->blue_mask
)!=0xff00ff) {
2049 } else if ((rSrc
==0x1f && bmpImage
->red_mask
==0xff) ||
2050 (bSrc
==0x1f && bmpImage
->blue_mask
==0xff)) {
2052 /* ==== rgb 555 dib -> rgb 888 bmp ==== */
2053 /* ==== bgr 555 dib -> bgr 888 bmp ==== */
2054 convs
->Convert_555_to_888_asis
2057 dstbits
,-bmpImage
->bytes_per_line
);
2059 /* ==== rgb 565 dib -> rgb 888 bmp ==== */
2060 /* ==== bgr 565 dib -> bgr 888 bmp ==== */
2061 convs
->Convert_565_to_888_asis
2064 dstbits
,-bmpImage
->bytes_per_line
);
2068 /* ==== rgb 555 dib -> bgr 888 bmp ==== */
2069 /* ==== bgr 555 dib -> rgb 888 bmp ==== */
2070 convs
->Convert_555_to_888_reverse
2073 dstbits
,-bmpImage
->bytes_per_line
);
2075 /* ==== rgb 565 dib -> bgr 888 bmp ==== */
2076 /* ==== bgr 565 dib -> rgb 888 bmp ==== */
2077 convs
->Convert_565_to_888_reverse
2080 dstbits
,-bmpImage
->bytes_per_line
);
2091 srcbits
=srcbits
+left
*2;
2092 dstbits
=bmpImage
->data
+left
*4+(lines
-1)*bmpImage
->bytes_per_line
;
2094 if (bmpImage
->green_mask
!=0x00ff00 ||
2095 (bmpImage
->red_mask
|bmpImage
->blue_mask
)!=0xff00ff) {
2097 } else if ((rSrc
==0x1f && bmpImage
->red_mask
==0xff) ||
2098 (bSrc
==0x1f && bmpImage
->blue_mask
==0xff)) {
2100 /* ==== rgb 555 dib -> rgb 0888 bmp ==== */
2101 /* ==== bgr 555 dib -> bgr 0888 bmp ==== */
2102 convs
->Convert_555_to_0888_asis
2105 dstbits
,-bmpImage
->bytes_per_line
);
2107 /* ==== rgb 565 dib -> rgb 0888 bmp ==== */
2108 /* ==== bgr 565 dib -> bgr 0888 bmp ==== */
2109 convs
->Convert_565_to_0888_asis
2112 dstbits
,-bmpImage
->bytes_per_line
);
2116 /* ==== rgb 555 dib -> bgr 0888 bmp ==== */
2117 /* ==== bgr 555 dib -> rgb 0888 bmp ==== */
2118 convs
->Convert_555_to_0888_reverse
2121 dstbits
,-bmpImage
->bytes_per_line
);
2123 /* ==== rgb 565 dib -> bgr 0888 bmp ==== */
2124 /* ==== bgr 565 dib -> rgb 0888 bmp ==== */
2125 convs
->Convert_565_to_0888_reverse
2128 dstbits
,-bmpImage
->bytes_per_line
);
2136 WARN("from 16 bit DIB (%x,%x,%x) to unknown %d bit bitmap (%lx,%lx,%lx)\n",
2137 rSrc
, gSrc
, bSrc
, bmpImage
->bits_per_pixel
, bmpImage
->red_mask
,
2138 bmpImage
->green_mask
, bmpImage
->blue_mask
);
2144 /* ==== rgb or bgr 555 or 565 dib -> pal 1, 4 or 8 ==== */
2145 const WORD
* srcpixel
;
2146 int rShift1
,gShift1
,bShift1
;
2147 int rShift2
,gShift2
,bShift2
;
2150 /* Set color scaling values */
2151 rShift1
=16+X11DRV_DIB_MaskToShift(rSrc
)-3;
2152 gShift1
=16+X11DRV_DIB_MaskToShift(gSrc
)-3;
2153 bShift1
=16+X11DRV_DIB_MaskToShift(bSrc
)-3;
2158 /* Green has 5 bits, like the others */
2162 /* Green has 6 bits, not 5. Compensate. */
2171 /* We could split it into four separate cases to optimize
2172 * but it is probably not worth it.
2174 for (h
=lines
-1; h
>=0; h
--) {
2175 srcpixel
=(const WORD
*)srcbits
;
2176 for (x
=left
; x
<width
+left
; x
++) {
2178 BYTE red
,green
,blue
;
2179 srcval
=*srcpixel
++ << 16;
2180 red
= ((srcval
>> rShift1
) & 0xf8) |
2181 ((srcval
>> rShift2
) & 0x07);
2182 green
=((srcval
>> gShift1
) & gMask1
) |
2183 ((srcval
>> gShift2
) & gMask2
);
2184 blue
= ((srcval
>> bShift1
) & 0xf8) |
2185 ((srcval
>> bShift2
) & 0x07);
2186 XPutPixel(bmpImage
, x
, h
,
2187 X11DRV_PALETTE_ToPhysical
2188 (physDev
, RGB(red
,green
,blue
)));
2190 srcbits
+= linebytes
;
2198 /***********************************************************************
2199 * X11DRV_DIB_GetImageBits_16
2201 * GetDIBits for an 16-bit deep DIB.
2203 static void X11DRV_DIB_GetImageBits_16( int lines
, BYTE
*dstbits
,
2204 DWORD dstwidth
, DWORD srcwidth
,
2205 PALETTEENTRY
*srccolors
,
2206 DWORD rDst
, DWORD gDst
, DWORD bDst
,
2207 XImage
*bmpImage
, DWORD dibpitch
)
2210 int h
, width
= min(srcwidth
, dstwidth
);
2211 const dib_conversions
*convs
= (bmpImage
->byte_order
== LSBFirst
) ? &dib_normal
: &dib_src_byteswap
;
2213 DWORD linebytes
= dibpitch
;
2218 dstbits
= dstbits
+ ( linebytes
* (lines
-1));
2219 linebytes
= -linebytes
;
2222 switch (bmpImage
->depth
)
2227 const char* srcbits
;
2229 srcbits
=bmpImage
->data
+(lines
-1)*bmpImage
->bytes_per_line
;
2231 if (bmpImage
->green_mask
==0x03e0) {
2232 if (gDst
==bmpImage
->green_mask
) {
2233 if (rDst
==bmpImage
->red_mask
) {
2234 /* ==== rgb 555 bmp -> rgb 555 dib ==== */
2235 /* ==== bgr 555 bmp -> bgr 555 dib ==== */
2236 convs
->Convert_5x5_asis
2238 srcbits
,-bmpImage
->bytes_per_line
,
2241 /* ==== rgb 555 bmp -> bgr 555 dib ==== */
2242 /* ==== bgr 555 bmp -> rgb 555 dib ==== */
2243 convs
->Convert_555_reverse
2245 srcbits
,-bmpImage
->bytes_per_line
,
2249 if (rDst
==bmpImage
->red_mask
|| bDst
==bmpImage
->blue_mask
) {
2250 /* ==== rgb 555 bmp -> rgb 565 dib ==== */
2251 /* ==== bgr 555 bmp -> bgr 565 dib ==== */
2252 convs
->Convert_555_to_565_asis
2254 srcbits
,-bmpImage
->bytes_per_line
,
2257 /* ==== rgb 555 bmp -> bgr 565 dib ==== */
2258 /* ==== bgr 555 bmp -> rgb 565 dib ==== */
2259 convs
->Convert_555_to_565_reverse
2261 srcbits
,-bmpImage
->bytes_per_line
,
2265 } else if (bmpImage
->green_mask
==0x07e0) {
2266 if (gDst
==bmpImage
->green_mask
) {
2267 if (rDst
== bmpImage
->red_mask
) {
2268 /* ==== rgb 565 bmp -> rgb 565 dib ==== */
2269 /* ==== bgr 565 bmp -> bgr 565 dib ==== */
2270 convs
->Convert_5x5_asis
2272 srcbits
,-bmpImage
->bytes_per_line
,
2275 /* ==== rgb 565 bmp -> bgr 565 dib ==== */
2276 /* ==== bgr 565 bmp -> rgb 565 dib ==== */
2277 convs
->Convert_565_reverse
2279 srcbits
,-bmpImage
->bytes_per_line
,
2283 if (rDst
==bmpImage
->red_mask
|| bDst
==bmpImage
->blue_mask
) {
2284 /* ==== rgb 565 bmp -> rgb 555 dib ==== */
2285 /* ==== bgr 565 bmp -> bgr 555 dib ==== */
2286 convs
->Convert_565_to_555_asis
2288 srcbits
,-bmpImage
->bytes_per_line
,
2291 /* ==== rgb 565 bmp -> bgr 555 dib ==== */
2292 /* ==== bgr 565 bmp -> rgb 555 dib ==== */
2293 convs
->Convert_565_to_555_reverse
2295 srcbits
,-bmpImage
->bytes_per_line
,
2306 if (bmpImage
->bits_per_pixel
== 24) {
2307 const char* srcbits
;
2309 srcbits
=bmpImage
->data
+(lines
-1)*bmpImage
->bytes_per_line
;
2311 if (bmpImage
->green_mask
!=0x00ff00 ||
2312 (bmpImage
->red_mask
|bmpImage
->blue_mask
)!=0xff00ff) {
2314 } else if ((rDst
==0x1f && bmpImage
->red_mask
==0xff) ||
2315 (bDst
==0x1f && bmpImage
->blue_mask
==0xff)) {
2317 /* ==== rgb 888 bmp -> rgb 555 dib ==== */
2318 /* ==== bgr 888 bmp -> bgr 555 dib ==== */
2319 convs
->Convert_888_to_555_asis
2321 srcbits
,-bmpImage
->bytes_per_line
,
2324 /* ==== rgb 888 bmp -> rgb 565 dib ==== */
2325 /* ==== rgb 888 bmp -> rgb 565 dib ==== */
2326 convs
->Convert_888_to_565_asis
2328 srcbits
,-bmpImage
->bytes_per_line
,
2333 /* ==== rgb 888 bmp -> bgr 555 dib ==== */
2334 /* ==== bgr 888 bmp -> rgb 555 dib ==== */
2335 convs
->Convert_888_to_555_reverse
2337 srcbits
,-bmpImage
->bytes_per_line
,
2340 /* ==== rgb 888 bmp -> bgr 565 dib ==== */
2341 /* ==== bgr 888 bmp -> rgb 565 dib ==== */
2342 convs
->Convert_888_to_565_reverse
2344 srcbits
,-bmpImage
->bytes_per_line
,
2354 const char* srcbits
;
2356 srcbits
=bmpImage
->data
+(lines
-1)*bmpImage
->bytes_per_line
;
2358 if (bmpImage
->green_mask
!=0x00ff00 ||
2359 (bmpImage
->red_mask
|bmpImage
->blue_mask
)!=0xff00ff) {
2361 } else if ((rDst
==0x1f && bmpImage
->red_mask
==0xff) ||
2362 (bDst
==0x1f && bmpImage
->blue_mask
==0xff)) {
2364 /* ==== rgb 0888 bmp -> rgb 555 dib ==== */
2365 /* ==== bgr 0888 bmp -> bgr 555 dib ==== */
2366 convs
->Convert_0888_to_555_asis
2368 srcbits
,-bmpImage
->bytes_per_line
,
2371 /* ==== rgb 0888 bmp -> rgb 565 dib ==== */
2372 /* ==== bgr 0888 bmp -> bgr 565 dib ==== */
2373 convs
->Convert_0888_to_565_asis
2375 srcbits
,-bmpImage
->bytes_per_line
,
2380 /* ==== rgb 0888 bmp -> bgr 555 dib ==== */
2381 /* ==== bgr 0888 bmp -> rgb 555 dib ==== */
2382 convs
->Convert_0888_to_555_reverse
2384 srcbits
,-bmpImage
->bytes_per_line
,
2387 /* ==== rgb 0888 bmp -> bgr 565 dib ==== */
2388 /* ==== bgr 0888 bmp -> rgb 565 dib ==== */
2389 convs
->Convert_0888_to_565_reverse
2391 srcbits
,-bmpImage
->bytes_per_line
,
2400 if (X11DRV_DIB_CheckMask(bmpImage
->red_mask
,bmpImage
->green_mask
,bmpImage
->blue_mask
)
2402 /* ==== pal 1 or 4 bmp -> rgb or bgr 555 or 565 dib ==== */
2403 int rShift
,gShift
,bShift
;
2406 /* Shift everything 16 bits left so that all shifts are >0,
2407 * even for BGR DIBs. Then a single >> 16 will bring everything
2410 rShift
=16+X11DRV_DIB_MaskToShift(rDst
)-3;
2411 gShift
=16+X11DRV_DIB_MaskToShift(gDst
)-3;
2412 bShift
=16+X11DRV_DIB_MaskToShift(bDst
)-3;
2414 /* 6 bits for the green */
2420 for (h
= lines
- 1; h
>= 0; h
--) {
2421 dstpixel
=(LPWORD
)dstbits
;
2422 for (x
= 0; x
< width
; x
++) {
2423 PALETTEENTRY srcval
;
2425 srcval
=srccolors
[XGetPixel(bmpImage
, x
, h
)];
2426 dstval
=((srcval
.peRed
<< rShift
) & rDst
) |
2427 ((srcval
.peGreen
<< gShift
) & gDst
) |
2428 ((srcval
.peBlue
<< bShift
) & bDst
);
2429 *dstpixel
++=dstval
>> 16;
2431 dstbits
+= linebytes
;
2439 if (X11DRV_DIB_CheckMask(bmpImage
->red_mask
,bmpImage
->green_mask
,bmpImage
->blue_mask
)
2441 /* ==== pal 8 bmp -> rgb or bgr 555 or 565 dib ==== */
2442 int rShift
,gShift
,bShift
;
2443 const BYTE
* srcbits
;
2444 const BYTE
* srcpixel
;
2447 /* Shift everything 16 bits left so that all shifts are >0,
2448 * even for BGR DIBs. Then a single >> 16 will bring everything
2451 rShift
=16+X11DRV_DIB_MaskToShift(rDst
)-3;
2452 gShift
=16+X11DRV_DIB_MaskToShift(gDst
)-3;
2453 bShift
=16+X11DRV_DIB_MaskToShift(bDst
)-3;
2455 /* 6 bits for the green */
2461 srcbits
=(BYTE
*)bmpImage
->data
+(lines
-1)*bmpImage
->bytes_per_line
;
2462 for (h
=0; h
<lines
; h
++) {
2464 dstpixel
=(LPWORD
)dstbits
;
2465 for (x
= 0; x
< width
; x
++) {
2466 PALETTEENTRY srcval
;
2468 srcval
=srccolors
[*srcpixel
++];
2469 dstval
=((srcval
.peRed
<< rShift
) & rDst
) |
2470 ((srcval
.peGreen
<< gShift
) & gDst
) |
2471 ((srcval
.peBlue
<< bShift
) & bDst
);
2472 *dstpixel
++=dstval
>> 16;
2474 srcbits
-= bmpImage
->bytes_per_line
;
2475 dstbits
+= linebytes
;
2485 /* ==== any bmp format -> rgb or bgr 555 or 565 dib ==== */
2486 int rShift
,gShift
,bShift
;
2489 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 16 bit DIB (%x,%x,%x)\n",
2490 bmpImage
->depth
, bmpImage
->red_mask
,
2491 bmpImage
->green_mask
, bmpImage
->blue_mask
,
2494 /* Shift everything 16 bits left so that all shifts are >0,
2495 * even for BGR DIBs. Then a single >> 16 will bring everything
2498 rShift
=16+X11DRV_DIB_MaskToShift(rDst
)-3;
2499 gShift
=16+X11DRV_DIB_MaskToShift(gDst
)-3;
2500 bShift
=16+X11DRV_DIB_MaskToShift(bDst
)-3;
2502 /* 6 bits for the green */
2508 for (h
= lines
- 1; h
>= 0; h
--) {
2509 dstpixel
=(LPWORD
)dstbits
;
2510 for (x
= 0; x
< width
; x
++) {
2513 srcval
=X11DRV_PALETTE_ToLogical(XGetPixel(bmpImage
, x
, h
));
2514 dstval
=((GetRValue(srcval
) << rShift
) & rDst
) |
2515 ((GetGValue(srcval
) << gShift
) & gDst
) |
2516 ((GetBValue(srcval
) << bShift
) & bDst
);
2517 *dstpixel
++=dstval
>> 16;
2519 dstbits
+= linebytes
;
2527 /***********************************************************************
2528 * X11DRV_DIB_SetImageBits_24
2530 * SetDIBits for a 24-bit deep DIB.
2532 static void X11DRV_DIB_SetImageBits_24( int lines
, const BYTE
*srcbits
,
2533 DWORD srcwidth
, DWORD dstwidth
, int left
,
2534 X11DRV_PDEVICE
*physDev
,
2535 DWORD rSrc
, DWORD gSrc
, DWORD bSrc
,
2536 XImage
*bmpImage
, DWORD linebytes
)
2539 int h
, width
= min(srcwidth
, dstwidth
);
2540 const dib_conversions
*convs
= (bmpImage
->byte_order
== LSBFirst
) ? &dib_normal
: &dib_dst_byteswap
;
2545 srcbits
= srcbits
+ linebytes
* (lines
- 1);
2546 linebytes
= -linebytes
;
2549 switch (bmpImage
->depth
)
2552 if (bmpImage
->bits_per_pixel
==24) {
2555 srcbits
=srcbits
+left
*3;
2556 dstbits
=bmpImage
->data
+left
*3+(lines
-1)*bmpImage
->bytes_per_line
;
2558 if (bmpImage
->green_mask
!=0x00ff00 ||
2559 (bmpImage
->red_mask
|bmpImage
->blue_mask
)!=0xff00ff) {
2561 } else if (rSrc
==bmpImage
->red_mask
) {
2562 /* ==== rgb 888 dib -> rgb 888 bmp ==== */
2563 /* ==== bgr 888 dib -> bgr 888 bmp ==== */
2564 convs
->Convert_888_asis
2567 dstbits
,-bmpImage
->bytes_per_line
);
2569 /* ==== rgb 888 dib -> bgr 888 bmp ==== */
2570 /* ==== bgr 888 dib -> rgb 888 bmp ==== */
2571 convs
->Convert_888_reverse
2574 dstbits
,-bmpImage
->bytes_per_line
);
2584 srcbits
=srcbits
+left
*3;
2585 dstbits
=bmpImage
->data
+left
*4+(lines
-1)*bmpImage
->bytes_per_line
;
2587 if (bmpImage
->green_mask
!=0x00ff00 ||
2588 (bmpImage
->red_mask
|bmpImage
->blue_mask
)!=0xff00ff) {
2590 } else if (rSrc
==bmpImage
->red_mask
) {
2591 /* ==== rgb 888 dib -> rgb 0888 bmp ==== */
2592 /* ==== bgr 888 dib -> bgr 0888 bmp ==== */
2593 convs
->Convert_888_to_0888_asis
2596 dstbits
,-bmpImage
->bytes_per_line
);
2598 /* ==== rgb 888 dib -> bgr 0888 bmp ==== */
2599 /* ==== bgr 888 dib -> rgb 0888 bmp ==== */
2600 convs
->Convert_888_to_0888_reverse
2603 dstbits
,-bmpImage
->bytes_per_line
);
2613 srcbits
=srcbits
+left
*3;
2614 dstbits
=bmpImage
->data
+left
*2+(lines
-1)*bmpImage
->bytes_per_line
;
2616 if (bmpImage
->green_mask
==0x03e0) {
2617 if ((rSrc
==0xff0000 && bmpImage
->red_mask
==0x7f00) ||
2618 (bSrc
==0xff0000 && bmpImage
->blue_mask
==0x7f00)) {
2619 /* ==== rgb 888 dib -> rgb 555 bmp ==== */
2620 /* ==== bgr 888 dib -> bgr 555 bmp ==== */
2621 convs
->Convert_888_to_555_asis
2624 dstbits
,-bmpImage
->bytes_per_line
);
2625 } else if ((rSrc
==0xff && bmpImage
->red_mask
==0x7f00) ||
2626 (bSrc
==0xff && bmpImage
->blue_mask
==0x7f00)) {
2627 /* ==== rgb 888 dib -> bgr 555 bmp ==== */
2628 /* ==== bgr 888 dib -> rgb 555 bmp ==== */
2629 convs
->Convert_888_to_555_reverse
2632 dstbits
,-bmpImage
->bytes_per_line
);
2636 } else if (bmpImage
->green_mask
==0x07e0) {
2637 if ((rSrc
==0xff0000 && bmpImage
->red_mask
==0xf800) ||
2638 (bSrc
==0xff0000 && bmpImage
->blue_mask
==0xf800)) {
2639 /* ==== rgb 888 dib -> rgb 565 bmp ==== */
2640 /* ==== bgr 888 dib -> bgr 565 bmp ==== */
2641 convs
->Convert_888_to_565_asis
2644 dstbits
,-bmpImage
->bytes_per_line
);
2645 } else if ((rSrc
==0xff && bmpImage
->red_mask
==0xf800) ||
2646 (bSrc
==0xff && bmpImage
->blue_mask
==0xf800)) {
2647 /* ==== rgb 888 dib -> bgr 565 bmp ==== */
2648 /* ==== bgr 888 dib -> rgb 565 bmp ==== */
2649 convs
->Convert_888_to_565_reverse
2652 dstbits
,-bmpImage
->bytes_per_line
);
2664 WARN("from 24 bit DIB (%x,%x,%x) to unknown %d bit bitmap (%lx,%lx,%lx)\n",
2665 rSrc
, gSrc
, bSrc
, bmpImage
->bits_per_pixel
, bmpImage
->red_mask
,
2666 bmpImage
->green_mask
, bmpImage
->blue_mask
);
2672 /* ==== rgb 888 dib -> any bmp format ==== */
2673 const BYTE
* srcbyte
;
2675 /* Windows only supports one 24bpp DIB format: RGB888 */
2677 for (h
= lines
- 1; h
>= 0; h
--) {
2679 for (x
= left
; x
< width
+left
; x
++) {
2680 XPutPixel(bmpImage
, x
, h
,
2681 X11DRV_PALETTE_ToPhysical
2682 (physDev
, RGB(srcbyte
[2], srcbyte
[1], srcbyte
[0])));
2685 srcbits
+= linebytes
;
2693 /***********************************************************************
2694 * X11DRV_DIB_GetImageBits_24
2696 * GetDIBits for an 24-bit deep DIB.
2698 static void X11DRV_DIB_GetImageBits_24( int lines
, BYTE
*dstbits
,
2699 DWORD dstwidth
, DWORD srcwidth
,
2700 PALETTEENTRY
*srccolors
,
2701 DWORD rDst
, DWORD gDst
, DWORD bDst
,
2702 XImage
*bmpImage
, DWORD linebytes
)
2705 int h
, width
= min(srcwidth
, dstwidth
);
2706 const dib_conversions
*convs
= (bmpImage
->byte_order
== LSBFirst
) ? &dib_normal
: &dib_src_byteswap
;
2711 dstbits
= dstbits
+ ( linebytes
* (lines
-1) );
2712 linebytes
= -linebytes
;
2715 switch (bmpImage
->depth
)
2718 if (bmpImage
->bits_per_pixel
==24) {
2719 const char* srcbits
;
2721 srcbits
=bmpImage
->data
+(lines
-1)*bmpImage
->bytes_per_line
;
2723 if (bmpImage
->green_mask
!=0x00ff00 ||
2724 (bmpImage
->red_mask
|bmpImage
->blue_mask
)!=0xff00ff) {
2726 } else if (rDst
==bmpImage
->red_mask
) {
2727 /* ==== rgb 888 bmp -> rgb 888 dib ==== */
2728 /* ==== bgr 888 bmp -> bgr 888 dib ==== */
2729 convs
->Convert_888_asis
2731 srcbits
,-bmpImage
->bytes_per_line
,
2734 /* ==== rgb 888 bmp -> bgr 888 dib ==== */
2735 /* ==== bgr 888 bmp -> rgb 888 dib ==== */
2736 convs
->Convert_888_reverse
2738 srcbits
,-bmpImage
->bytes_per_line
,
2747 const char* srcbits
;
2749 srcbits
=bmpImage
->data
+(lines
-1)*bmpImage
->bytes_per_line
;
2751 if (bmpImage
->green_mask
!=0x00ff00 ||
2752 (bmpImage
->red_mask
|bmpImage
->blue_mask
)!=0xff00ff) {
2754 } else if (rDst
==bmpImage
->red_mask
) {
2755 /* ==== rgb 888 bmp -> rgb 0888 dib ==== */
2756 /* ==== bgr 888 bmp -> bgr 0888 dib ==== */
2757 convs
->Convert_0888_to_888_asis
2759 srcbits
,-bmpImage
->bytes_per_line
,
2762 /* ==== rgb 888 bmp -> bgr 0888 dib ==== */
2763 /* ==== bgr 888 bmp -> rgb 0888 dib ==== */
2764 convs
->Convert_0888_to_888_reverse
2766 srcbits
,-bmpImage
->bytes_per_line
,
2775 const char* srcbits
;
2777 srcbits
=bmpImage
->data
+(lines
-1)*bmpImage
->bytes_per_line
;
2779 if (bmpImage
->green_mask
==0x03e0) {
2780 if ((rDst
==0xff0000 && bmpImage
->red_mask
==0x7f00) ||
2781 (bDst
==0xff0000 && bmpImage
->blue_mask
==0x7f00)) {
2782 /* ==== rgb 555 bmp -> rgb 888 dib ==== */
2783 /* ==== bgr 555 bmp -> bgr 888 dib ==== */
2784 convs
->Convert_555_to_888_asis
2786 srcbits
,-bmpImage
->bytes_per_line
,
2788 } else if ((rDst
==0xff && bmpImage
->red_mask
==0x7f00) ||
2789 (bDst
==0xff && bmpImage
->blue_mask
==0x7f00)) {
2790 /* ==== rgb 555 bmp -> bgr 888 dib ==== */
2791 /* ==== bgr 555 bmp -> rgb 888 dib ==== */
2792 convs
->Convert_555_to_888_reverse
2794 srcbits
,-bmpImage
->bytes_per_line
,
2799 } else if (bmpImage
->green_mask
==0x07e0) {
2800 if ((rDst
==0xff0000 && bmpImage
->red_mask
==0xf800) ||
2801 (bDst
==0xff0000 && bmpImage
->blue_mask
==0xf800)) {
2802 /* ==== rgb 565 bmp -> rgb 888 dib ==== */
2803 /* ==== bgr 565 bmp -> bgr 888 dib ==== */
2804 convs
->Convert_565_to_888_asis
2806 srcbits
,-bmpImage
->bytes_per_line
,
2808 } else if ((rDst
==0xff && bmpImage
->red_mask
==0xf800) ||
2809 (bDst
==0xff && bmpImage
->blue_mask
==0xf800)) {
2810 /* ==== rgb 565 bmp -> bgr 888 dib ==== */
2811 /* ==== bgr 565 bmp -> rgb 888 dib ==== */
2812 convs
->Convert_565_to_888_reverse
2814 srcbits
,-bmpImage
->bytes_per_line
,
2827 if (X11DRV_DIB_CheckMask(bmpImage
->red_mask
,bmpImage
->green_mask
,bmpImage
->blue_mask
)
2829 /* ==== pal 1 or 4 bmp -> rgb 888 dib ==== */
2832 /* Windows only supports one 24bpp DIB format: rgb 888 */
2833 for (h
= lines
- 1; h
>= 0; h
--) {
2835 for (x
= 0; x
< width
; x
++) {
2836 PALETTEENTRY srcval
;
2837 srcval
=srccolors
[XGetPixel(bmpImage
, x
, h
)];
2838 dstbyte
[0]=srcval
.peBlue
;
2839 dstbyte
[1]=srcval
.peGreen
;
2840 dstbyte
[2]=srcval
.peRed
;
2843 dstbits
+= linebytes
;
2851 if (X11DRV_DIB_CheckMask(bmpImage
->red_mask
,bmpImage
->green_mask
,bmpImage
->blue_mask
)
2853 /* ==== pal 8 bmp -> rgb 888 dib ==== */
2854 const void* srcbits
;
2855 const BYTE
* srcpixel
;
2858 /* Windows only supports one 24bpp DIB format: rgb 888 */
2859 srcbits
=bmpImage
->data
+(lines
-1)*bmpImage
->bytes_per_line
;
2860 for (h
= lines
- 1; h
>= 0; h
--) {
2863 for (x
= 0; x
< width
; x
++ ) {
2864 PALETTEENTRY srcval
;
2865 srcval
=srccolors
[*srcpixel
++];
2866 dstbyte
[0]=srcval
.peBlue
;
2867 dstbyte
[1]=srcval
.peGreen
;
2868 dstbyte
[2]=srcval
.peRed
;
2871 srcbits
= (const char*)srcbits
- bmpImage
->bytes_per_line
;
2872 dstbits
+= linebytes
;
2882 /* ==== any bmp format -> 888 dib ==== */
2885 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 24 bit DIB (%x,%x,%x)\n",
2886 bmpImage
->depth
, bmpImage
->red_mask
,
2887 bmpImage
->green_mask
, bmpImage
->blue_mask
,
2890 /* Windows only supports one 24bpp DIB format: rgb 888 */
2891 for (h
= lines
- 1; h
>= 0; h
--) {
2893 for (x
= 0; x
< width
; x
++) {
2894 COLORREF srcval
=X11DRV_PALETTE_ToLogical
2895 (XGetPixel( bmpImage
, x
, h
));
2896 dstbyte
[0]=GetBValue(srcval
);
2897 dstbyte
[1]=GetGValue(srcval
);
2898 dstbyte
[2]=GetRValue(srcval
);
2901 dstbits
+= linebytes
;
2909 /***********************************************************************
2910 * X11DRV_DIB_SetImageBits_32
2912 * SetDIBits for a 32-bit deep DIB.
2914 static void X11DRV_DIB_SetImageBits_32(int lines
, const BYTE
*srcbits
,
2915 DWORD srcwidth
, DWORD dstwidth
, int left
,
2916 X11DRV_PDEVICE
*physDev
,
2917 DWORD rSrc
, DWORD gSrc
, DWORD bSrc
,
2922 int h
, width
= min(srcwidth
, dstwidth
);
2923 const dib_conversions
*convs
= (bmpImage
->byte_order
== LSBFirst
) ? &dib_normal
: &dib_dst_byteswap
;
2928 srcbits
= srcbits
+ ( linebytes
* (lines
-1) );
2929 linebytes
= -linebytes
;
2932 switch (bmpImage
->depth
)
2935 if (bmpImage
->bits_per_pixel
==24) {
2938 srcbits
=srcbits
+left
*4;
2939 dstbits
=bmpImage
->data
+left
*3+(lines
-1)*bmpImage
->bytes_per_line
;
2941 if (rSrc
==bmpImage
->red_mask
&& gSrc
==bmpImage
->green_mask
&& bSrc
==bmpImage
->blue_mask
) {
2942 /* ==== rgb 0888 dib -> rgb 888 bmp ==== */
2943 /* ==== bgr 0888 dib -> bgr 888 bmp ==== */
2944 convs
->Convert_0888_to_888_asis
2947 dstbits
,-bmpImage
->bytes_per_line
);
2948 } else if (bmpImage
->green_mask
!=0x00ff00 ||
2949 (bmpImage
->red_mask
|bmpImage
->blue_mask
)!=0xff00ff) {
2951 /* the tests below assume sane bmpImage masks */
2952 } else if (rSrc
==bmpImage
->blue_mask
&& gSrc
==bmpImage
->green_mask
&& bSrc
==bmpImage
->red_mask
) {
2953 /* ==== rgb 0888 dib -> bgr 888 bmp ==== */
2954 /* ==== bgr 0888 dib -> rgb 888 bmp ==== */
2955 convs
->Convert_0888_to_888_reverse
2958 dstbits
,-bmpImage
->bytes_per_line
);
2959 } else if (bmpImage
->blue_mask
==0xff) {
2960 /* ==== any 0888 dib -> rgb 888 bmp ==== */
2961 convs
->Convert_any0888_to_rgb888
2965 dstbits
,-bmpImage
->bytes_per_line
);
2967 /* ==== any 0888 dib -> bgr 888 bmp ==== */
2968 convs
->Convert_any0888_to_bgr888
2972 dstbits
,-bmpImage
->bytes_per_line
);
2982 srcbits
=srcbits
+left
*4;
2983 dstbits
=bmpImage
->data
+left
*4+(lines
-1)*bmpImage
->bytes_per_line
;
2985 if (gSrc
==bmpImage
->green_mask
) {
2986 if (rSrc
==bmpImage
->red_mask
&& bSrc
==bmpImage
->blue_mask
) {
2987 /* ==== rgb 0888 dib -> rgb 0888 bmp ==== */
2988 /* ==== bgr 0888 dib -> bgr 0888 bmp ==== */
2989 convs
->Convert_0888_asis
2992 dstbits
,-bmpImage
->bytes_per_line
);
2993 } else if (bmpImage
->green_mask
!=0x00ff00 ||
2994 (bmpImage
->red_mask
|bmpImage
->blue_mask
)!=0xff00ff) {
2996 /* the tests below assume sane bmpImage masks */
2997 } else if (rSrc
==bmpImage
->blue_mask
&& bSrc
==bmpImage
->red_mask
) {
2998 /* ==== rgb 0888 dib -> bgr 0888 bmp ==== */
2999 /* ==== bgr 0888 dib -> rgb 0888 bmp ==== */
3000 convs
->Convert_0888_reverse
3003 dstbits
,-bmpImage
->bytes_per_line
);
3005 /* ==== any 0888 dib -> any 0888 bmp ==== */
3006 convs
->Convert_0888_any
3010 dstbits
,-bmpImage
->bytes_per_line
,
3011 bmpImage
->red_mask
,bmpImage
->green_mask
,bmpImage
->blue_mask
);
3013 } else if (bmpImage
->green_mask
!=0x00ff00 ||
3014 (bmpImage
->red_mask
|bmpImage
->blue_mask
)!=0xff00ff) {
3016 /* the tests below assume sane bmpImage masks */
3018 /* ==== any 0888 dib -> any 0888 bmp ==== */
3019 convs
->Convert_0888_any
3023 dstbits
,-bmpImage
->bytes_per_line
,
3024 bmpImage
->red_mask
,bmpImage
->green_mask
,bmpImage
->blue_mask
);
3034 srcbits
=srcbits
+left
*4;
3035 dstbits
=bmpImage
->data
+left
*2+(lines
-1)*bmpImage
->bytes_per_line
;
3037 if (rSrc
==0xff0000 && gSrc
==0x00ff00 && bSrc
==0x0000ff) {
3038 if (bmpImage
->green_mask
==0x03e0) {
3039 if (bmpImage
->red_mask
==0x7f00) {
3040 /* ==== rgb 0888 dib -> rgb 555 bmp ==== */
3041 convs
->Convert_0888_to_555_asis
3044 dstbits
,-bmpImage
->bytes_per_line
);
3045 } else if (bmpImage
->blue_mask
==0x7f00) {
3046 /* ==== rgb 0888 dib -> bgr 555 bmp ==== */
3047 convs
->Convert_0888_to_555_reverse
3050 dstbits
,-bmpImage
->bytes_per_line
);
3054 } else if (bmpImage
->green_mask
==0x07e0) {
3055 if (bmpImage
->red_mask
==0xf800) {
3056 /* ==== rgb 0888 dib -> rgb 565 bmp ==== */
3057 convs
->Convert_0888_to_565_asis
3060 dstbits
,-bmpImage
->bytes_per_line
);
3061 } else if (bmpImage
->blue_mask
==0xf800) {
3062 /* ==== rgb 0888 dib -> bgr 565 bmp ==== */
3063 convs
->Convert_0888_to_565_reverse
3066 dstbits
,-bmpImage
->bytes_per_line
);
3073 } else if (rSrc
==0x0000ff && gSrc
==0x00ff00 && bSrc
==0xff0000) {
3074 if (bmpImage
->green_mask
==0x03e0) {
3075 if (bmpImage
->blue_mask
==0x7f00) {
3076 /* ==== bgr 0888 dib -> bgr 555 bmp ==== */
3077 convs
->Convert_0888_to_555_asis
3080 dstbits
,-bmpImage
->bytes_per_line
);
3081 } else if (bmpImage
->red_mask
==0x7f00) {
3082 /* ==== bgr 0888 dib -> rgb 555 bmp ==== */
3083 convs
->Convert_0888_to_555_reverse
3086 dstbits
,-bmpImage
->bytes_per_line
);
3090 } else if (bmpImage
->green_mask
==0x07e0) {
3091 if (bmpImage
->blue_mask
==0xf800) {
3092 /* ==== bgr 0888 dib -> bgr 565 bmp ==== */
3093 convs
->Convert_0888_to_565_asis
3096 dstbits
,-bmpImage
->bytes_per_line
);
3097 } else if (bmpImage
->red_mask
==0xf800) {
3098 /* ==== bgr 0888 dib -> rgb 565 bmp ==== */
3099 convs
->Convert_0888_to_565_reverse
3102 dstbits
,-bmpImage
->bytes_per_line
);
3110 if (bmpImage
->green_mask
==0x03e0 &&
3111 (bmpImage
->red_mask
==0x7f00 ||
3112 bmpImage
->blue_mask
==0x7f00)) {
3113 /* ==== any 0888 dib -> rgb or bgr 555 bmp ==== */
3114 convs
->Convert_any0888_to_5x5
3118 dstbits
,-bmpImage
->bytes_per_line
,
3119 bmpImage
->red_mask
,bmpImage
->green_mask
,bmpImage
->blue_mask
);
3120 } else if (bmpImage
->green_mask
==0x07e0 &&
3121 (bmpImage
->red_mask
==0xf800 ||
3122 bmpImage
->blue_mask
==0xf800)) {
3123 /* ==== any 0888 dib -> rgb or bgr 565 bmp ==== */
3124 convs
->Convert_any0888_to_5x5
3128 dstbits
,-bmpImage
->bytes_per_line
,
3129 bmpImage
->red_mask
,bmpImage
->green_mask
,bmpImage
->blue_mask
);
3139 WARN("from 32 bit DIB (%x,%x,%x) to unknown %d bit bitmap (%lx,%lx,%lx)\n",
3140 rSrc
, gSrc
, bSrc
, bmpImage
->bits_per_pixel
, bmpImage
->red_mask
,
3141 bmpImage
->green_mask
, bmpImage
->blue_mask
);
3147 /* ==== any 0888 dib -> pal 1, 4 or 8 bmp ==== */
3148 const DWORD
* srcpixel
;
3149 int rShift
,gShift
,bShift
;
3151 rShift
=X11DRV_DIB_MaskToShift(rSrc
);
3152 gShift
=X11DRV_DIB_MaskToShift(gSrc
);
3153 bShift
=X11DRV_DIB_MaskToShift(bSrc
);
3155 for (h
= lines
- 1; h
>= 0; h
--) {
3156 srcpixel
=(const DWORD
*)srcbits
;
3157 for (x
= left
; x
< width
+left
; x
++) {
3159 BYTE red
,green
,blue
;
3160 srcvalue
=*srcpixel
++;
3161 red
= (srcvalue
>> rShift
) & 0xff;
3162 green
=(srcvalue
>> gShift
) & 0xff;
3163 blue
= (srcvalue
>> bShift
) & 0xff;
3164 XPutPixel(bmpImage
, x
, h
, X11DRV_PALETTE_ToPhysical
3165 (physDev
, RGB(red
,green
,blue
)));
3167 srcbits
+= linebytes
;
3175 /***********************************************************************
3176 * X11DRV_DIB_GetImageBits_32
3178 * GetDIBits for an 32-bit deep DIB.
3180 static void X11DRV_DIB_GetImageBits_32( int lines
, BYTE
*dstbits
,
3181 DWORD dstwidth
, DWORD srcwidth
,
3182 PALETTEENTRY
*srccolors
,
3183 DWORD rDst
, DWORD gDst
, DWORD bDst
,
3184 XImage
*bmpImage
, DWORD linebytes
)
3187 int h
, width
= min(srcwidth
, dstwidth
);
3189 const dib_conversions
*convs
= (bmpImage
->byte_order
== LSBFirst
) ? &dib_normal
: &dib_src_byteswap
;
3194 dstbits
= dstbits
+ ( linebytes
* (lines
-1) );
3195 linebytes
= -linebytes
;
3200 switch (bmpImage
->depth
)
3203 if (bmpImage
->bits_per_pixel
==24) {
3204 const void* srcbits
;
3206 srcbits
=bmpImage
->data
+(lines
-1)*bmpImage
->bytes_per_line
;
3208 if (rDst
==bmpImage
->red_mask
&& gDst
==bmpImage
->green_mask
&& bDst
==bmpImage
->blue_mask
) {
3209 /* ==== rgb 888 bmp -> rgb 0888 dib ==== */
3210 /* ==== bgr 888 bmp -> bgr 0888 dib ==== */
3211 convs
->Convert_888_to_0888_asis
3213 srcbits
,-bmpImage
->bytes_per_line
,
3215 } else if (bmpImage
->green_mask
!=0x00ff00 ||
3216 (bmpImage
->red_mask
|bmpImage
->blue_mask
)!=0xff00ff) {
3218 /* the tests below assume sane bmpImage masks */
3219 } else if (rDst
==bmpImage
->blue_mask
&& gDst
==bmpImage
->green_mask
&& bDst
==bmpImage
->red_mask
) {
3220 /* ==== rgb 888 bmp -> bgr 0888 dib ==== */
3221 /* ==== bgr 888 bmp -> rgb 0888 dib ==== */
3222 convs
->Convert_888_to_0888_reverse
3224 srcbits
,-bmpImage
->bytes_per_line
,
3226 } else if (bmpImage
->blue_mask
==0xff) {
3227 /* ==== rgb 888 bmp -> any 0888 dib ==== */
3228 convs
->Convert_rgb888_to_any0888
3230 srcbits
,-bmpImage
->bytes_per_line
,
3234 /* ==== bgr 888 bmp -> any 0888 dib ==== */
3235 convs
->Convert_bgr888_to_any0888
3237 srcbits
,-bmpImage
->bytes_per_line
,
3247 const char* srcbits
;
3249 srcbits
=bmpImage
->data
+(lines
-1)*bmpImage
->bytes_per_line
;
3251 if (gDst
==bmpImage
->green_mask
) {
3252 if (rDst
==bmpImage
->red_mask
&& bDst
==bmpImage
->blue_mask
) {
3253 /* ==== rgb 0888 bmp -> rgb 0888 dib ==== */
3254 /* ==== bgr 0888 bmp -> bgr 0888 dib ==== */
3255 convs
->Convert_0888_asis
3257 srcbits
,-bmpImage
->bytes_per_line
,
3259 } else if (bmpImage
->green_mask
!=0x00ff00 ||
3260 (bmpImage
->red_mask
|bmpImage
->blue_mask
)!=0xff00ff) {
3262 /* the tests below assume sane bmpImage masks */
3263 } else if (rDst
==bmpImage
->blue_mask
&& bDst
==bmpImage
->red_mask
) {
3264 /* ==== rgb 0888 bmp -> bgr 0888 dib ==== */
3265 /* ==== bgr 0888 bmp -> rgb 0888 dib ==== */
3266 convs
->Convert_0888_reverse
3268 srcbits
,-bmpImage
->bytes_per_line
,
3271 /* ==== any 0888 bmp -> any 0888 dib ==== */
3272 convs
->Convert_0888_any
3274 srcbits
,-bmpImage
->bytes_per_line
,
3275 bmpImage
->red_mask
,bmpImage
->green_mask
,bmpImage
->blue_mask
,
3279 } else if (bmpImage
->green_mask
!=0x00ff00 ||
3280 (bmpImage
->red_mask
|bmpImage
->blue_mask
)!=0xff00ff) {
3282 /* the tests below assume sane bmpImage masks */
3284 /* ==== any 0888 bmp -> any 0888 dib ==== */
3285 convs
->Convert_0888_any
3287 srcbits
,-bmpImage
->bytes_per_line
,
3288 bmpImage
->red_mask
,bmpImage
->green_mask
,bmpImage
->blue_mask
,
3298 const char* srcbits
;
3300 srcbits
=bmpImage
->data
+(lines
-1)*bmpImage
->bytes_per_line
;
3302 if (rDst
==0xff0000 && gDst
==0x00ff00 && bDst
==0x0000ff) {
3303 if (bmpImage
->green_mask
==0x03e0) {
3304 if (bmpImage
->red_mask
==0x7f00) {
3305 /* ==== rgb 555 bmp -> rgb 0888 dib ==== */
3306 convs
->Convert_555_to_0888_asis
3308 srcbits
,-bmpImage
->bytes_per_line
,
3310 } else if (bmpImage
->blue_mask
==0x7f00) {
3311 /* ==== bgr 555 bmp -> rgb 0888 dib ==== */
3312 convs
->Convert_555_to_0888_reverse
3314 srcbits
,-bmpImage
->bytes_per_line
,
3319 } else if (bmpImage
->green_mask
==0x07e0) {
3320 if (bmpImage
->red_mask
==0xf800) {
3321 /* ==== rgb 565 bmp -> rgb 0888 dib ==== */
3322 convs
->Convert_565_to_0888_asis
3324 srcbits
,-bmpImage
->bytes_per_line
,
3326 } else if (bmpImage
->blue_mask
==0xf800) {
3327 /* ==== bgr 565 bmp -> rgb 0888 dib ==== */
3328 convs
->Convert_565_to_0888_reverse
3330 srcbits
,-bmpImage
->bytes_per_line
,
3338 } else if (rDst
==0x0000ff && gDst
==0x00ff00 && bDst
==0xff0000) {
3339 if (bmpImage
->green_mask
==0x03e0) {
3340 if (bmpImage
->blue_mask
==0x7f00) {
3341 /* ==== bgr 555 bmp -> bgr 0888 dib ==== */
3342 convs
->Convert_555_to_0888_asis
3344 srcbits
,-bmpImage
->bytes_per_line
,
3346 } else if (bmpImage
->red_mask
==0x7f00) {
3347 /* ==== rgb 555 bmp -> bgr 0888 dib ==== */
3348 convs
->Convert_555_to_0888_reverse
3350 srcbits
,-bmpImage
->bytes_per_line
,
3355 } else if (bmpImage
->green_mask
==0x07e0) {
3356 if (bmpImage
->blue_mask
==0xf800) {
3357 /* ==== bgr 565 bmp -> bgr 0888 dib ==== */
3358 convs
->Convert_565_to_0888_asis
3360 srcbits
,-bmpImage
->bytes_per_line
,
3362 } else if (bmpImage
->red_mask
==0xf800) {
3363 /* ==== rgb 565 bmp -> bgr 0888 dib ==== */
3364 convs
->Convert_565_to_0888_reverse
3366 srcbits
,-bmpImage
->bytes_per_line
,
3375 if (bmpImage
->green_mask
==0x03e0 &&
3376 (bmpImage
->red_mask
==0x7f00 ||
3377 bmpImage
->blue_mask
==0x7f00)) {
3378 /* ==== rgb or bgr 555 bmp -> any 0888 dib ==== */
3379 convs
->Convert_5x5_to_any0888
3381 srcbits
,-bmpImage
->bytes_per_line
,
3382 bmpImage
->red_mask
,bmpImage
->green_mask
,bmpImage
->blue_mask
,
3385 } else if (bmpImage
->green_mask
==0x07e0 &&
3386 (bmpImage
->red_mask
==0xf800 ||
3387 bmpImage
->blue_mask
==0xf800)) {
3388 /* ==== rgb or bgr 565 bmp -> any 0888 dib ==== */
3389 convs
->Convert_5x5_to_any0888
3391 srcbits
,-bmpImage
->bytes_per_line
,
3392 bmpImage
->red_mask
,bmpImage
->green_mask
,bmpImage
->blue_mask
,
3404 if (X11DRV_DIB_CheckMask(bmpImage
->red_mask
,bmpImage
->green_mask
,bmpImage
->blue_mask
)
3406 /* ==== pal 1 or 4 bmp -> any 0888 dib ==== */
3407 int rShift
,gShift
,bShift
;
3410 rShift
=X11DRV_DIB_MaskToShift(rDst
);
3411 gShift
=X11DRV_DIB_MaskToShift(gDst
);
3412 bShift
=X11DRV_DIB_MaskToShift(bDst
);
3413 for (h
= lines
- 1; h
>= 0; h
--) {
3414 dstpixel
=(DWORD
*)dstbits
;
3415 for (x
= 0; x
< width
; x
++) {
3416 PALETTEENTRY srcval
;
3417 srcval
= srccolors
[XGetPixel(bmpImage
, x
, h
)];
3418 *dstpixel
++=(srcval
.peRed
<< rShift
) |
3419 (srcval
.peGreen
<< gShift
) |
3420 (srcval
.peBlue
<< bShift
);
3422 dstbits
+= linebytes
;
3430 if (X11DRV_DIB_CheckMask(bmpImage
->red_mask
,bmpImage
->green_mask
,bmpImage
->blue_mask
)
3432 /* ==== pal 8 bmp -> any 0888 dib ==== */
3433 int rShift
,gShift
,bShift
;
3434 const void* srcbits
;
3435 const BYTE
* srcpixel
;
3438 rShift
=X11DRV_DIB_MaskToShift(rDst
);
3439 gShift
=X11DRV_DIB_MaskToShift(gDst
);
3440 bShift
=X11DRV_DIB_MaskToShift(bDst
);
3441 srcbits
=bmpImage
->data
+(lines
-1)*bmpImage
->bytes_per_line
;
3442 for (h
= lines
- 1; h
>= 0; h
--) {
3444 dstpixel
=(DWORD
*)dstbits
;
3445 for (x
= 0; x
< width
; x
++) {
3446 PALETTEENTRY srcval
;
3447 srcval
=srccolors
[*srcpixel
++];
3448 *dstpixel
++=(srcval
.peRed
<< rShift
) |
3449 (srcval
.peGreen
<< gShift
) |
3450 (srcval
.peBlue
<< bShift
);
3452 srcbits
= (const char*)srcbits
- bmpImage
->bytes_per_line
;
3453 dstbits
+= linebytes
;
3463 /* ==== any bmp format -> any 0888 dib ==== */
3464 int rShift
,gShift
,bShift
;
3467 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 32 bit DIB (%x,%x,%x)\n",
3468 bmpImage
->depth
, bmpImage
->red_mask
,
3469 bmpImage
->green_mask
, bmpImage
->blue_mask
,
3472 rShift
=X11DRV_DIB_MaskToShift(rDst
);
3473 gShift
=X11DRV_DIB_MaskToShift(gDst
);
3474 bShift
=X11DRV_DIB_MaskToShift(bDst
);
3475 for (h
= lines
- 1; h
>= 0; h
--) {
3476 dstpixel
=(DWORD
*)dstbits
;
3477 for (x
= 0; x
< width
; x
++) {
3479 srcval
=X11DRV_PALETTE_ToLogical(XGetPixel(bmpImage
, x
, h
));
3480 *dstpixel
++=(GetRValue(srcval
) << rShift
) |
3481 (GetGValue(srcval
) << gShift
) |
3482 (GetBValue(srcval
) << bShift
);
3484 dstbits
+= linebytes
;
3491 static int XGetSubImageErrorHandler(Display
*dpy
, XErrorEvent
*event
, void *arg
)
3493 return (event
->request_code
== X_GetImage
&& event
->error_code
== BadMatch
);
3496 /***********************************************************************
3497 * X11DRV_DIB_SetImageBits_GetSubImage
3499 * Helper for X11DRV_DIB_SetImageBits
3501 static void X11DRV_DIB_SetImageBits_GetSubImage(
3502 const X11DRV_DIB_IMAGEBITS_DESCR
*descr
, XImage
*bmpImage
)
3504 /* compressed bitmaps may contain gaps in them. So make a copy
3505 * of the existing pixels first */
3508 SetRect( &bmprc
, descr
->xDest
, descr
->yDest
,
3509 descr
->xDest
+ descr
->width
, descr
->yDest
+ descr
->height
);
3510 GetRgnBox( descr
->physDev
->region
, &rc
);
3511 /* convert from dc to drawable origin */
3512 OffsetRect( &rc
, descr
->physDev
->dc_rect
.left
, descr
->physDev
->dc_rect
.top
);
3513 /* clip visible rect with bitmap */
3514 if( IntersectRect( &rc
, &rc
, &bmprc
))
3516 X11DRV_expect_error( gdi_display
, XGetSubImageErrorHandler
, NULL
);
3517 XGetSubImage( gdi_display
, descr
->drawable
, rc
.left
, rc
.top
,
3518 rc
.right
- rc
.left
, rc
.bottom
- rc
.top
, AllPlanes
,
3520 descr
->xSrc
+ rc
.left
- bmprc
.left
,
3521 descr
->ySrc
+ rc
.top
- bmprc
.top
);
3522 X11DRV_check_error();
3526 /***********************************************************************
3527 * X11DRV_DIB_SetImageBits
3529 * Transfer the bits to an X image.
3530 * Helper function for SetDIBits() and SetDIBitsToDevice().
3532 static int X11DRV_DIB_SetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR
*descr
)
3534 int lines
= descr
->lines
>= 0 ? descr
->lines
: -descr
->lines
;
3539 bmpImage
= descr
->image
;
3541 bmpImage
= XCreateImage( gdi_display
, visual
, descr
->depth
, ZPixmap
, 0, NULL
,
3542 descr
->infoWidth
, lines
, 32, 0 );
3543 bmpImage
->data
= HeapAlloc( GetProcessHeap(), 0, lines
* bmpImage
->bytes_per_line
);
3544 if(bmpImage
->data
== NULL
) {
3545 ERR("Out of memory!\n");
3546 XDestroyImage( bmpImage
);
3547 wine_tsx11_unlock();
3551 wine_tsx11_unlock();
3553 TRACE("Dib: depth=%d r=%x g=%x b=%x\n",
3554 descr
->infoBpp
,descr
->rMask
,descr
->gMask
,descr
->bMask
);
3555 TRACE("Bmp: depth=%d/%d r=%lx g=%lx b=%lx\n",
3556 bmpImage
->depth
,bmpImage
->bits_per_pixel
,
3557 bmpImage
->red_mask
,bmpImage
->green_mask
,bmpImage
->blue_mask
);
3559 /* Transfer the pixels */
3562 switch(descr
->infoBpp
)
3565 X11DRV_DIB_SetImageBits_1( descr
->lines
, descr
->bits
, descr
->infoWidth
,
3566 descr
->width
, descr
->xSrc
, (int *)(descr
->colorMap
),
3567 bmpImage
, descr
->dibpitch
);
3570 if (descr
->compression
) {
3571 X11DRV_DIB_SetImageBits_GetSubImage( descr
, bmpImage
);
3572 X11DRV_DIB_SetImageBits_RLE4( descr
->lines
, descr
->bits
,
3573 descr
->infoWidth
, descr
->width
,
3574 descr
->xSrc
, (int *)(descr
->colorMap
),
3577 X11DRV_DIB_SetImageBits_4( descr
->lines
, descr
->bits
,
3578 descr
->infoWidth
, descr
->width
,
3579 descr
->xSrc
, (int*)(descr
->colorMap
),
3580 bmpImage
, descr
->dibpitch
);
3583 if (descr
->compression
) {
3584 X11DRV_DIB_SetImageBits_GetSubImage( descr
, bmpImage
);
3585 X11DRV_DIB_SetImageBits_RLE8( descr
->lines
, descr
->bits
,
3586 descr
->infoWidth
, descr
->width
,
3587 descr
->xSrc
, (int *)(descr
->colorMap
),
3590 X11DRV_DIB_SetImageBits_8( descr
->lines
, descr
->bits
,
3591 descr
->infoWidth
, descr
->width
,
3592 descr
->xSrc
, (int *)(descr
->colorMap
),
3593 bmpImage
, descr
->dibpitch
);
3597 X11DRV_DIB_SetImageBits_16( descr
->lines
, descr
->bits
,
3598 descr
->infoWidth
, descr
->width
,
3599 descr
->xSrc
, descr
->physDev
,
3600 descr
->rMask
, descr
->gMask
, descr
->bMask
,
3601 bmpImage
, descr
->dibpitch
);
3604 X11DRV_DIB_SetImageBits_24( descr
->lines
, descr
->bits
,
3605 descr
->infoWidth
, descr
->width
,
3606 descr
->xSrc
, descr
->physDev
,
3607 descr
->rMask
, descr
->gMask
, descr
->bMask
,
3608 bmpImage
, descr
->dibpitch
);
3611 X11DRV_DIB_SetImageBits_32( descr
->lines
, descr
->bits
,
3612 descr
->infoWidth
, descr
->width
,
3613 descr
->xSrc
, descr
->physDev
,
3614 descr
->rMask
, descr
->gMask
, descr
->bMask
,
3615 bmpImage
, descr
->dibpitch
);
3618 WARN("(%d): Invalid depth\n", descr
->infoBpp
);
3624 WARN( "invalid bits pointer %p\n", descr
->bits
);
3629 TRACE("XPutImage(%ld,%p,%p,%d,%d,%d,%d,%d,%d)\n",
3630 descr
->drawable
, descr
->gc
, bmpImage
,
3631 descr
->xSrc
, descr
->ySrc
, descr
->xDest
, descr
->yDest
,
3632 descr
->width
, descr
->height
);
3637 #ifdef HAVE_LIBXXSHM
3638 if (descr
->image
&& descr
->useShm
)
3640 XShmPutImage( gdi_display
, descr
->drawable
, descr
->gc
, bmpImage
,
3641 descr
->xSrc
, descr
->ySrc
, descr
->xDest
, descr
->yDest
,
3642 descr
->width
, descr
->height
, FALSE
);
3643 XSync( gdi_display
, 0 );
3647 XPutImage( gdi_display
, descr
->drawable
, descr
->gc
, bmpImage
,
3648 descr
->xSrc
, descr
->ySrc
, descr
->xDest
, descr
->yDest
,
3649 descr
->width
, descr
->height
);
3651 if (!descr
->image
) X11DRV_DIB_DestroyXImage( bmpImage
);
3652 wine_tsx11_unlock();
3656 /***********************************************************************
3657 * X11DRV_DIB_GetImageBits
3659 * Transfer the bits from an X image.
3661 static int X11DRV_DIB_GetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR
*descr
)
3663 int lines
= descr
->lines
>= 0 ? descr
->lines
: -descr
->lines
;
3668 bmpImage
= descr
->image
;
3670 bmpImage
= XCreateImage( gdi_display
, visual
, descr
->depth
, ZPixmap
, 0, NULL
,
3671 descr
->infoWidth
, lines
, 32, 0 );
3672 bmpImage
->data
= HeapAlloc( GetProcessHeap(), 0, lines
* bmpImage
->bytes_per_line
);
3673 if(bmpImage
->data
== NULL
) {
3674 ERR("Out of memory!\n");
3675 XDestroyImage( bmpImage
);
3676 wine_tsx11_unlock();
3681 #ifdef HAVE_LIBXXSHM
3683 /* We must not call XShmGetImage() with a bitmap which is bigger than the available area.
3684 If we do, XShmGetImage() will fail (X exception), as it checks for this internally. */
3685 if((descr
->image
&& descr
->useShm
) && (bmpImage
->width
<= (descr
->width
- descr
->xSrc
))
3686 && (bmpImage
->height
<= (descr
->height
- descr
->ySrc
)))
3688 int saveRed
, saveGreen
, saveBlue
;
3690 TRACE("XShmGetImage(%p, %ld, %p, %d, %d, %ld)\n",
3691 gdi_display
, descr
->drawable
, bmpImage
,
3692 descr
->xSrc
, descr
->ySrc
, AllPlanes
);
3694 /* We must save and restore the bmpImage's masks in order
3695 * to preserve them across the call to XShmGetImage, which
3696 * decides to eliminate them since it doesn't happen to know
3697 * what the format of the image is supposed to be, even though
3699 saveRed
= bmpImage
->red_mask
;
3700 saveBlue
= bmpImage
->blue_mask
;
3701 saveGreen
= bmpImage
->green_mask
;
3703 XShmGetImage( gdi_display
, descr
->drawable
, bmpImage
,
3704 descr
->xSrc
, descr
->ySrc
, AllPlanes
);
3706 bmpImage
->red_mask
= saveRed
;
3707 bmpImage
->blue_mask
= saveBlue
;
3708 bmpImage
->green_mask
= saveGreen
;
3711 #endif /* HAVE_LIBXXSHM */
3713 TRACE("XGetSubImage(%p,%ld,%d,%d,%d,%d,%ld,%d,%p,%d,%d)\n",
3714 gdi_display
, descr
->drawable
, descr
->xSrc
, descr
->ySrc
, descr
->width
,
3715 lines
, AllPlanes
, ZPixmap
, bmpImage
, descr
->xDest
, descr
->yDest
);
3716 XGetSubImage( gdi_display
, descr
->drawable
, descr
->xSrc
, descr
->ySrc
,
3717 descr
->width
, lines
, AllPlanes
, ZPixmap
,
3718 bmpImage
, descr
->xDest
, descr
->yDest
);
3720 wine_tsx11_unlock();
3722 TRACE("Dib: depth=%2d r=%x g=%x b=%x\n",
3723 descr
->infoBpp
,descr
->rMask
,descr
->gMask
,descr
->bMask
);
3724 TRACE("Bmp: depth=%2d/%2d r=%lx g=%lx b=%lx\n",
3725 bmpImage
->depth
,bmpImage
->bits_per_pixel
,
3726 bmpImage
->red_mask
,bmpImage
->green_mask
,bmpImage
->blue_mask
);
3727 /* Transfer the pixels */
3728 switch(descr
->infoBpp
)
3731 X11DRV_DIB_GetImageBits_1( descr
->lines
,(LPVOID
)descr
->bits
,
3732 descr
->infoWidth
, descr
->width
,
3733 descr
->colorMap
, descr
->palentry
,
3734 bmpImage
, descr
->dibpitch
);
3738 if (descr
->compression
) {
3739 FIXME("Compression not yet supported!\n");
3740 if(descr
->sizeImage
< X11DRV_DIB_GetDIBWidthBytes( descr
->infoWidth
, 4 ) * abs(descr
->lines
))
3743 X11DRV_DIB_GetImageBits_4( descr
->lines
,(LPVOID
)descr
->bits
,
3744 descr
->infoWidth
, descr
->width
,
3745 descr
->colorMap
, descr
->palentry
,
3746 bmpImage
, descr
->dibpitch
);
3749 if (descr
->compression
) {
3750 FIXME("Compression not yet supported!\n");
3751 if(descr
->sizeImage
< X11DRV_DIB_GetDIBWidthBytes( descr
->infoWidth
, 8 ) * abs(descr
->lines
))
3754 X11DRV_DIB_GetImageBits_8( descr
->lines
, (LPVOID
)descr
->bits
,
3755 descr
->infoWidth
, descr
->width
,
3756 descr
->colorMap
, descr
->palentry
,
3757 bmpImage
, descr
->dibpitch
);
3761 X11DRV_DIB_GetImageBits_16( descr
->lines
, (LPVOID
)descr
->bits
,
3762 descr
->infoWidth
,descr
->width
,
3764 descr
->rMask
, descr
->gMask
, descr
->bMask
,
3765 bmpImage
, descr
->dibpitch
);
3769 X11DRV_DIB_GetImageBits_24( descr
->lines
, (LPVOID
)descr
->bits
,
3770 descr
->infoWidth
,descr
->width
,
3772 descr
->rMask
, descr
->gMask
, descr
->bMask
,
3773 bmpImage
, descr
->dibpitch
);
3777 X11DRV_DIB_GetImageBits_32( descr
->lines
, (LPVOID
)descr
->bits
,
3778 descr
->infoWidth
, descr
->width
,
3780 descr
->rMask
, descr
->gMask
, descr
->bMask
,
3781 bmpImage
, descr
->dibpitch
);
3785 WARN("(%d): Invalid depth\n", descr
->infoBpp
);
3789 if (!descr
->image
) X11DRV_DIB_DestroyXImage( bmpImage
);
3793 /*************************************************************************
3794 * X11DRV_SetDIBitsToDevice
3797 INT CDECL
X11DRV_SetDIBitsToDevice( X11DRV_PDEVICE
*physDev
, INT xDest
, INT yDest
, DWORD cx
,
3798 DWORD cy
, INT xSrc
, INT ySrc
,
3799 UINT startscan
, UINT lines
, LPCVOID bits
,
3800 const BITMAPINFO
*info
, UINT coloruse
)
3802 X11DRV_DIB_IMAGEBITS_DESCR descr
;
3807 int rop
= X11DRV_XROPfunction
[GetROP2(physDev
->hdc
) - 1];
3809 if (DIB_GetBitmapInfo( &info
->bmiHeader
, &width
, &height
,
3810 &descr
.infoBpp
, &descr
.compression
) == -1)
3813 top_down
= (height
< 0);
3814 if (top_down
) height
= -height
;
3818 LPtoDP(physDev
->hdc
, &pt
, 1);
3820 if (!lines
|| (startscan
>= height
)) return 0;
3821 if (!top_down
&& startscan
+ lines
> height
) lines
= height
- startscan
;
3823 /* make xSrc,ySrc point to the upper-left corner, not the lower-left one,
3824 * and clamp all values to fit inside [startscan,startscan+lines]
3826 if (ySrc
+ cy
<= startscan
+ lines
)
3828 UINT y
= startscan
+ lines
- (ySrc
+ cy
);
3829 if (ySrc
< startscan
) cy
-= (startscan
- ySrc
);
3832 /* avoid getting unnecessary lines */
3834 if (y
>= lines
) return 0;
3839 if (y
>= lines
) return lines
;
3840 ySrc
= y
; /* need to get all lines in top down mode */
3845 if (ySrc
>= startscan
+ lines
) return lines
;
3846 pt
.y
+= ySrc
+ cy
- (startscan
+ lines
);
3847 cy
= startscan
+ lines
- ySrc
;
3849 if (cy
> lines
) cy
= lines
;
3851 if (xSrc
>= width
) return lines
;
3852 if (xSrc
+ cx
>= width
) cx
= width
- xSrc
;
3853 if (!cx
|| !cy
) return lines
;
3855 /* Update the pixmap from the DIB section */
3856 X11DRV_LockDIBSection(physDev
, DIB_Status_GdiMod
);
3858 X11DRV_SetupGCForText( physDev
); /* To have the correct colors */
3860 XSetFunction(gdi_display
, physDev
->gc
, rop
);
3861 wine_tsx11_unlock();
3863 switch (descr
.infoBpp
)
3868 descr
.colorMap
= (RGBQUAD
*)X11DRV_DIB_BuildColorMap(
3870 physDev
->depth
, info
, &descr
.nColorMap
);
3871 if (!descr
.colorMap
) return 0;
3872 descr
.rMask
= descr
.gMask
= descr
.bMask
= 0;
3876 descr
.rMask
= (descr
.compression
== BI_BITFIELDS
) ? *(const DWORD
*)info
->bmiColors
: 0x7c00;
3877 descr
.gMask
= (descr
.compression
== BI_BITFIELDS
) ? *((const DWORD
*)info
->bmiColors
+ 1) : 0x03e0;
3878 descr
.bMask
= (descr
.compression
== BI_BITFIELDS
) ? *((const DWORD
*)info
->bmiColors
+ 2) : 0x001f;
3884 descr
.rMask
= (descr
.compression
== BI_BITFIELDS
) ? *(const DWORD
*)info
->bmiColors
: 0xff0000;
3885 descr
.gMask
= (descr
.compression
== BI_BITFIELDS
) ? *((const DWORD
*)info
->bmiColors
+ 1) : 0x00ff00;
3886 descr
.bMask
= (descr
.compression
== BI_BITFIELDS
) ? *((const DWORD
*)info
->bmiColors
+ 2) : 0x0000ff;
3891 descr
.physDev
= physDev
;
3894 descr
.palentry
= NULL
;
3895 descr
.lines
= top_down
? -lines
: lines
;
3896 descr
.infoWidth
= width
;
3897 descr
.depth
= physDev
->depth
;
3898 descr
.drawable
= physDev
->drawable
;
3899 descr
.gc
= physDev
->gc
;
3902 descr
.xDest
= physDev
->dc_rect
.left
+ pt
.x
;
3903 descr
.yDest
= physDev
->dc_rect
.top
+ pt
.y
;
3906 descr
.useShm
= FALSE
;
3907 descr
.dibpitch
= ((width
* descr
.infoBpp
+ 31) &~31) / 8;
3909 result
= X11DRV_DIB_SetImageBits( &descr
);
3911 if (descr
.infoBpp
<= 8)
3912 HeapFree(GetProcessHeap(), 0, descr
.colorMap
);
3914 /* Update the DIBSection of the pixmap */
3915 X11DRV_UnlockDIBSection(physDev
, TRUE
);
3920 /***********************************************************************
3921 * SetDIBits (X11DRV.@)
3923 INT CDECL
X11DRV_SetDIBits( X11DRV_PDEVICE
*physDev
, HBITMAP hbitmap
, UINT startscan
,
3924 UINT lines
, LPCVOID bits
, const BITMAPINFO
*info
, UINT coloruse
)
3926 X_PHYSBITMAP
*physBitmap
= X11DRV_get_phys_bitmap( hbitmap
);
3927 X11DRV_DIB_IMAGEBITS_DESCR descr
;
3929 LONG width
, height
, tmpheight
;
3932 descr
.physDev
= physDev
;
3934 if (!physBitmap
) return 0;
3936 if (DIB_GetBitmapInfo( &info
->bmiHeader
, &width
, &height
,
3937 &descr
.infoBpp
, &descr
.compression
) == -1)
3941 if (height
< 0) height
= -height
;
3942 if (!lines
|| (startscan
>= height
))
3945 if (!GetObjectW( hbitmap
, sizeof(ds
), &ds
)) return 0;
3947 if (startscan
+ lines
> height
) lines
= height
- startscan
;
3949 switch (descr
.infoBpp
)
3954 descr
.colorMap
= (RGBQUAD
*)X11DRV_DIB_BuildColorMap(
3955 descr
.physDev
, coloruse
,
3956 physBitmap
->pixmap_depth
,
3957 info
, &descr
.nColorMap
);
3958 if (!descr
.colorMap
) return 0;
3959 descr
.rMask
= descr
.gMask
= descr
.bMask
= 0;
3963 descr
.rMask
= (descr
.compression
== BI_BITFIELDS
) ? *(const DWORD
*)info
->bmiColors
: 0x7c00;
3964 descr
.gMask
= (descr
.compression
== BI_BITFIELDS
) ? *((const DWORD
*)info
->bmiColors
+ 1) : 0x03e0;
3965 descr
.bMask
= (descr
.compression
== BI_BITFIELDS
) ? *((const DWORD
*)info
->bmiColors
+ 2) : 0x001f;
3971 descr
.rMask
= (descr
.compression
== BI_BITFIELDS
) ? *(const DWORD
*)info
->bmiColors
: 0xff0000;
3972 descr
.gMask
= (descr
.compression
== BI_BITFIELDS
) ? *((const DWORD
*)info
->bmiColors
+ 1) : 0x00ff00;
3973 descr
.bMask
= (descr
.compression
== BI_BITFIELDS
) ? *((const DWORD
*)info
->bmiColors
+ 2) : 0x0000ff;
3982 descr
.palentry
= NULL
;
3983 descr
.infoWidth
= width
;
3984 descr
.lines
= tmpheight
>= 0 ? lines
: -lines
;
3985 descr
.depth
= physBitmap
->pixmap_depth
;
3986 descr
.drawable
= physBitmap
->pixmap
;
3987 descr
.gc
= BITMAP_GC(physBitmap
);
3991 descr
.yDest
= height
- startscan
- lines
;
3992 descr
.width
= ds
.dsBm
.bmWidth
;
3993 descr
.height
= lines
;
3994 descr
.useShm
= FALSE
;
3995 descr
.dibpitch
= ((descr
.infoWidth
* descr
.infoBpp
+ 31) &~31) / 8;
3996 X11DRV_DIB_Lock( physBitmap
, DIB_Status_GdiMod
);
3997 result
= X11DRV_DIB_SetImageBits( &descr
);
3999 /* optimisation for the case where the input bits are in exactly the same
4000 * format as the internal representation and copying to the app bits is
4001 * cheap - saves a round trip to the X server */
4002 if (descr
.compression
== BI_RGB
&&
4003 coloruse
== DIB_RGB_COLORS
&&
4004 descr
.infoBpp
== ds
.dsBm
.bmBitsPixel
&&
4005 physBitmap
->base
&& physBitmap
->size
< 65536)
4007 unsigned int srcwidthb
= ds
.dsBm
.bmWidthBytes
;
4008 int dstwidthb
= X11DRV_DIB_GetDIBWidthBytes( width
, descr
.infoBpp
);
4009 LPBYTE dbits
= physBitmap
->base
, sbits
= (LPBYTE
)bits
+ (startscan
* srcwidthb
);
4013 TRACE("syncing compatible set bits to app bits\n");
4014 if ((tmpheight
< 0) ^ (ds
.dsBmih
.biHeight
< 0))
4016 dbits
+= dstwidthb
* (lines
-1);
4017 dstwidthb
= -dstwidthb
;
4019 X11DRV_DIB_DoProtectDIBSection( physBitmap
, PAGE_READWRITE
);
4020 widthb
= min(srcwidthb
, abs(dstwidthb
));
4021 for (y
= 0; y
< lines
; y
++, dbits
+= dstwidthb
, sbits
+= srcwidthb
)
4022 memcpy(dbits
, sbits
, widthb
);
4023 X11DRV_DIB_DoProtectDIBSection( physBitmap
, PAGE_READONLY
);
4024 physBitmap
->status
= DIB_Status_InSync
;
4026 X11DRV_DIB_Unlock( physBitmap
, TRUE
);
4028 HeapFree(GetProcessHeap(), 0, descr
.colorMap
);
4033 /***********************************************************************
4034 * GetDIBits (X11DRV.@)
4036 INT CDECL
X11DRV_GetDIBits( X11DRV_PDEVICE
*physDev
, HBITMAP hbitmap
, UINT startscan
, UINT lines
,
4037 LPVOID bits
, BITMAPINFO
*info
, UINT coloruse
)
4039 X_PHYSBITMAP
*physBitmap
= X11DRV_get_phys_bitmap( hbitmap
);
4041 X11DRV_DIB_IMAGEBITS_DESCR descr
;
4042 PALETTEENTRY palette
[256];
4045 LONG width
, tempHeight
;
4049 static const PALETTEENTRY peBlack
= {0,0,0,0};
4050 static const PALETTEENTRY peWhite
= {255,255,255,0};
4052 if (!physBitmap
) return 0;
4053 if (!(obj_size
= GetObjectW( hbitmap
, sizeof(dib
), &dib
))) return 0;
4055 bitmap_type
= DIB_GetBitmapInfo( (BITMAPINFOHEADER
*)info
, &width
, &tempHeight
, &descr
.infoBpp
, &descr
.compression
);
4057 if (physBitmap
->pixmap_depth
> 1)
4059 GetPaletteEntries( GetCurrentObject( physDev
->hdc
, OBJ_PAL
), 0, 256, palette
);
4063 palette
[0] = peBlack
;
4064 palette
[1] = peWhite
;
4067 if (bitmap_type
== -1)
4069 ERR("Invalid bitmap\n");
4072 descr
.lines
= tempHeight
;
4073 core_header
= (bitmap_type
== 0);
4074 colorPtr
= (LPBYTE
) info
+ (WORD
) info
->bmiHeader
.biSize
;
4076 TRACE("%u scanlines of (%i,%i) -> (%i,%i) starting from %u\n",
4077 lines
, dib
.dsBm
.bmWidth
, dib
.dsBm
.bmHeight
, width
, descr
.lines
, startscan
);
4079 if( lines
> dib
.dsBm
.bmHeight
) lines
= dib
.dsBm
.bmHeight
;
4081 height
= descr
.lines
;
4082 if (height
< 0) height
= -height
;
4083 if( lines
> height
) lines
= height
;
4084 /* Top-down images have a negative biHeight, the scanlines of these images
4085 * were inverted in X11DRV_DIB_GetImageBits_xx
4086 * To prevent this we simply change the sign of lines
4087 * (the number of scan lines to copy).
4088 * Negative lines are correctly handled by X11DRV_DIB_GetImageBits_xx.
4090 if( descr
.lines
< 0 && lines
> 0) lines
= -lines
;
4092 if( startscan
>= dib
.dsBm
.bmHeight
) return 0;
4094 descr
.colorMap
= NULL
;
4096 switch (descr
.infoBpp
)
4101 descr
.rMask
= descr
.gMask
= descr
.bMask
= 0;
4102 if(coloruse
== DIB_RGB_COLORS
)
4103 descr
.colorMap
= colorPtr
;
4105 int num_colors
= 1 << descr
.infoBpp
, i
;
4108 WORD
*index
= colorPtr
;
4109 descr
.colorMap
= rgb
= HeapAlloc(GetProcessHeap(), 0, num_colors
* sizeof(RGBQUAD
));
4110 for(i
= 0; i
< num_colors
; i
++, rgb
++, index
++) {
4111 colref
= X11DRV_PALETTE_ToLogical(X11DRV_PALETTE_ToPhysical(physDev
, PALETTEINDEX(*index
)));
4112 rgb
->rgbRed
= GetRValue(colref
);
4113 rgb
->rgbGreen
= GetGValue(colref
);
4114 rgb
->rgbBlue
= GetBValue(colref
);
4115 rgb
->rgbReserved
= 0;
4121 descr
.rMask
= (descr
.compression
== BI_BITFIELDS
) ? *(const DWORD
*)info
->bmiColors
: 0x7c00;
4122 descr
.gMask
= (descr
.compression
== BI_BITFIELDS
) ? *((const DWORD
*)info
->bmiColors
+ 1) : 0x03e0;
4123 descr
.bMask
= (descr
.compression
== BI_BITFIELDS
) ? *((const DWORD
*)info
->bmiColors
+ 2) : 0x001f;
4127 descr
.rMask
= (descr
.compression
== BI_BITFIELDS
) ? *(const DWORD
*)info
->bmiColors
: 0xff0000;
4128 descr
.gMask
= (descr
.compression
== BI_BITFIELDS
) ? *((const DWORD
*)info
->bmiColors
+ 1) : 0x00ff00;
4129 descr
.bMask
= (descr
.compression
== BI_BITFIELDS
) ? *((const DWORD
*)info
->bmiColors
+ 2) : 0x0000ff;
4133 descr
.physDev
= physDev
;
4134 descr
.palentry
= palette
;
4136 descr
.image
= physBitmap
->image
;
4137 descr
.infoWidth
= width
;
4138 descr
.lines
= lines
;
4139 descr
.depth
= physBitmap
->pixmap_depth
;
4140 descr
.drawable
= physBitmap
->pixmap
;
4141 descr
.gc
= BITMAP_GC(physBitmap
);
4142 descr
.width
= dib
.dsBm
.bmWidth
;
4143 descr
.height
= dib
.dsBm
.bmHeight
;
4147 descr
.sizeImage
= core_header
? 0 : info
->bmiHeader
.biSizeImage
;
4149 if (descr
.lines
> 0)
4151 descr
.ySrc
= (descr
.height
-1) - (startscan
+ (lines
-1));
4155 descr
.ySrc
= startscan
;
4157 #ifdef HAVE_LIBXXSHM
4158 descr
.useShm
= (obj_size
== sizeof(DIBSECTION
)) && (physBitmap
->shminfo
.shmid
!= -1);
4160 descr
.useShm
= FALSE
;
4162 descr
.dibpitch
= (obj_size
== sizeof(DIBSECTION
)) ? dib
.dsBm
.bmWidthBytes
4163 : (((descr
.infoWidth
* descr
.infoBpp
+ 31) &~31) / 8);
4165 X11DRV_DIB_Lock( physBitmap
, DIB_Status_GdiMod
);
4166 X11DRV_DIB_GetImageBits( &descr
);
4167 X11DRV_DIB_Unlock( physBitmap
, TRUE
);
4169 if(!core_header
&& info
->bmiHeader
.biSizeImage
== 0) /* Fill in biSizeImage */
4170 info
->bmiHeader
.biSizeImage
= X11DRV_DIB_GetDIBImageBytes( descr
.infoWidth
,
4174 if (descr
.compression
== BI_BITFIELDS
)
4176 *(DWORD
*)info
->bmiColors
= descr
.rMask
;
4177 *((DWORD
*)info
->bmiColors
+ 1) = descr
.gMask
;
4178 *((DWORD
*)info
->bmiColors
+ 2) = descr
.bMask
;
4180 else if (!core_header
)
4182 /* if RLE or JPEG compression were supported,
4183 * this line would be invalid. */
4184 info
->bmiHeader
.biCompression
= 0;
4187 if(descr
.colorMap
!= colorPtr
)
4188 HeapFree(GetProcessHeap(), 0, descr
.colorMap
);
4192 /***********************************************************************
4193 * X11DRV_DIB_DoCopyDIBSection
4195 static void X11DRV_DIB_DoCopyDIBSection(X_PHYSBITMAP
*physBitmap
, BOOL toDIB
,
4196 void *colorMap
, int nColorMap
,
4197 Drawable dest
, GC gc
,
4198 DWORD xSrc
, DWORD ySrc
,
4199 DWORD xDest
, DWORD yDest
,
4200 DWORD width
, DWORD height
)
4202 DIBSECTION dibSection
;
4203 X11DRV_DIB_IMAGEBITS_DESCR descr
;
4204 int identity
[2] = {0,1};
4206 if (!GetObjectW( physBitmap
->hbitmap
, sizeof(dibSection
), &dibSection
)) return;
4208 descr
.physDev
= NULL
;
4209 descr
.palentry
= NULL
;
4210 descr
.infoWidth
= dibSection
.dsBmih
.biWidth
;
4211 descr
.infoBpp
= dibSection
.dsBmih
.biBitCount
;
4212 descr
.lines
= dibSection
.dsBmih
.biHeight
;
4213 descr
.image
= physBitmap
->image
;
4214 descr
.colorMap
= colorMap
;
4215 descr
.nColorMap
= nColorMap
;
4216 descr
.bits
= dibSection
.dsBm
.bmBits
;
4217 descr
.depth
= physBitmap
->pixmap_depth
;
4218 descr
.compression
= dibSection
.dsBmih
.biCompression
;
4220 if(descr
.infoBpp
== 1)
4221 descr
.colorMap
= (void*)identity
;
4223 switch (descr
.infoBpp
)
4228 descr
.rMask
= descr
.gMask
= descr
.bMask
= 0;
4232 descr
.rMask
= (descr
.compression
== BI_BITFIELDS
) ? dibSection
.dsBitfields
[0] : 0x7c00;
4233 descr
.gMask
= (descr
.compression
== BI_BITFIELDS
) ? dibSection
.dsBitfields
[1] : 0x03e0;
4234 descr
.bMask
= (descr
.compression
== BI_BITFIELDS
) ? dibSection
.dsBitfields
[2] : 0x001f;
4239 descr
.rMask
= (descr
.compression
== BI_BITFIELDS
) ? dibSection
.dsBitfields
[0] : 0xff0000;
4240 descr
.gMask
= (descr
.compression
== BI_BITFIELDS
) ? dibSection
.dsBitfields
[1] : 0x00ff00;
4241 descr
.bMask
= (descr
.compression
== BI_BITFIELDS
) ? dibSection
.dsBitfields
[2] : 0x0000ff;
4246 descr
.drawable
= dest
;
4250 descr
.xDest
= xDest
;
4251 descr
.yDest
= yDest
;
4252 descr
.width
= width
;
4253 descr
.height
= height
;
4254 descr
.sizeImage
= 0;
4256 #ifdef HAVE_LIBXXSHM
4257 descr
.useShm
= (physBitmap
->shminfo
.shmid
!= -1);
4259 descr
.useShm
= FALSE
;
4261 descr
.dibpitch
= dibSection
.dsBm
.bmWidthBytes
;
4265 TRACE("Copying from Pixmap to DIB bits\n");
4266 X11DRV_DIB_GetImageBits( &descr
);
4270 TRACE("Copying from DIB bits to Pixmap\n");
4271 X11DRV_DIB_SetImageBits( &descr
);
4275 /***********************************************************************
4276 * X11DRV_DIB_CopyDIBSection
4278 void X11DRV_DIB_CopyDIBSection(X11DRV_PDEVICE
*physDevSrc
, X11DRV_PDEVICE
*physDevDst
,
4279 DWORD xSrc
, DWORD ySrc
, DWORD xDest
, DWORD yDest
,
4280 DWORD width
, DWORD height
)
4283 X_PHYSBITMAP
*physBitmap
;
4284 unsigned int nColorMap
;
4288 TRACE("(%p,%p,%d,%d,%d,%d,%d,%d)\n", physDevSrc
->hdc
, physDevDst
->hdc
,
4289 xSrc
, ySrc
, xDest
, yDest
, width
, height
);
4290 /* this function is meant as an optimization for BitBlt,
4291 * not to be called otherwise */
4292 physBitmap
= physDevSrc
->bitmap
;
4293 if (!physBitmap
|| GetObjectW( physBitmap
->hbitmap
, sizeof(dib
), &dib
) != sizeof(dib
))
4295 ERR("called for non-DIBSection!?\n");
4298 /* while BitBlt should already have made sure we only get
4299 * positive values, we should check for oversize values */
4300 if ((xSrc
< dib
.dsBm
.bmWidth
) &&
4301 (ySrc
< dib
.dsBm
.bmHeight
)) {
4302 if (xSrc
+ width
> dib
.dsBm
.bmWidth
)
4303 width
= dib
.dsBm
.bmWidth
- xSrc
;
4304 if (ySrc
+ height
> dib
.dsBm
.bmHeight
)
4305 height
= dib
.dsBm
.bmHeight
- ySrc
;
4306 /* if the source bitmap is 8bpp or less, we're supposed to use the
4307 * DC's palette for color conversion (not the DIB color table) */
4308 if (dib
.dsBm
.bmBitsPixel
<= 8) {
4309 HPALETTE hPalette
= GetCurrentObject( physDevSrc
->hdc
, OBJ_PAL
);
4310 if (!hPalette
|| (hPalette
== GetStockObject(DEFAULT_PALETTE
))) {
4311 /* HACK: no palette has been set in the source DC,
4312 * use the DIB colormap instead - this is necessary in some
4313 * cases since we need to do depth conversion in some places
4314 * where real Windows can just copy data straight over */
4315 x11ColorMap
= physBitmap
->colorMap
;
4316 nColorMap
= physBitmap
->nColorMap
;
4317 freeColorMap
= FALSE
;
4319 const BITMAPINFO
* info
= (BITMAPINFO
*)&dib
.dsBmih
;
4322 nColorMap
= X11DRV_DIB_GetColorCount(info
);
4323 x11ColorMap
= HeapAlloc(GetProcessHeap(), 0, nColorMap
* sizeof(int));
4324 for (i
= 0; i
< nColorMap
; i
++)
4325 x11ColorMap
[i
] = X11DRV_PALETTE_ToPhysical(physDevSrc
, PALETTEINDEX(i
));
4326 freeColorMap
= TRUE
;
4333 freeColorMap
= FALSE
;
4335 /* perform the copy */
4336 X11DRV_DIB_DoCopyDIBSection(physBitmap
, FALSE
, x11ColorMap
, nColorMap
,
4337 physDevDst
->drawable
, physDevDst
->gc
, xSrc
, ySrc
,
4338 physDevDst
->dc_rect
.left
+ xDest
, physDevDst
->dc_rect
.top
+ yDest
,
4340 /* free color mapping */
4342 HeapFree(GetProcessHeap(), 0, x11ColorMap
);
4346 /***********************************************************************
4347 * X11DRV_DIB_DoUpdateDIBSection
4349 static void X11DRV_DIB_DoUpdateDIBSection(X_PHYSBITMAP
*physBitmap
, BOOL toDIB
)
4353 GetObjectW( physBitmap
->hbitmap
, sizeof(bitmap
), &bitmap
);
4354 X11DRV_DIB_DoCopyDIBSection(physBitmap
, toDIB
,
4355 physBitmap
->colorMap
, physBitmap
->nColorMap
,
4356 physBitmap
->pixmap
, BITMAP_GC(physBitmap
),
4357 0, 0, 0, 0, bitmap
.bmWidth
, bitmap
.bmHeight
);
4360 /***********************************************************************
4361 * X11DRV_DIB_FaultHandler
4363 static LONG CALLBACK
X11DRV_DIB_FaultHandler( PEXCEPTION_POINTERS ep
)
4365 X_PHYSBITMAP
*physBitmap
= NULL
;
4369 const size_t pagemask
= getpagesize() - 1;
4371 if (ep
->ExceptionRecord
->ExceptionCode
!= EXCEPTION_ACCESS_VIOLATION
)
4372 return EXCEPTION_CONTINUE_SEARCH
;
4374 addr
= (BYTE
*)ep
->ExceptionRecord
->ExceptionInformation
[1];
4376 EnterCriticalSection(&dibs_cs
);
4377 LIST_FOR_EACH( ptr
, &dibs_list
)
4379 physBitmap
= LIST_ENTRY( ptr
, X_PHYSBITMAP
, entry
);
4380 if ((physBitmap
->base
<= addr
) &&
4381 (addr
< physBitmap
->base
+ ((physBitmap
->size
+ pagemask
) & ~pagemask
)))
4387 LeaveCriticalSection(&dibs_cs
);
4389 if (!found
) return EXCEPTION_CONTINUE_SEARCH
;
4391 if (addr
>= physBitmap
->base
+ physBitmap
->size
)
4392 WARN( "%p: access to %p beyond the end of the DIB\n", physBitmap
->hbitmap
, addr
);
4394 X11DRV_DIB_Lock( physBitmap
, DIB_Status_None
);
4395 if (ep
->ExceptionRecord
->ExceptionInformation
[0] == EXCEPTION_WRITE_FAULT
) {
4396 /* the app tried to write the DIB bits */
4397 X11DRV_DIB_Coerce( physBitmap
, DIB_Status_AppMod
);
4399 /* the app tried to read the DIB bits */
4400 X11DRV_DIB_Coerce( physBitmap
, DIB_Status_InSync
);
4402 X11DRV_DIB_Unlock( physBitmap
, TRUE
);
4404 return EXCEPTION_CONTINUE_EXECUTION
;
4407 /***********************************************************************
4410 static INT
X11DRV_DIB_Coerce(X_PHYSBITMAP
*physBitmap
, INT req
)
4412 INT ret
= DIB_Status_None
;
4414 if (!physBitmap
->image
) return ret
; /* not a DIB section */
4415 EnterCriticalSection(&physBitmap
->lock
);
4416 ret
= physBitmap
->status
;
4418 case DIB_Status_GdiMod
:
4419 /* GDI access - request to draw on pixmap */
4420 switch (physBitmap
->status
)
4423 case DIB_Status_None
:
4424 physBitmap
->p_status
= DIB_Status_GdiMod
;
4425 X11DRV_DIB_DoUpdateDIBSection( physBitmap
, FALSE
);
4428 case DIB_Status_GdiMod
:
4429 TRACE("GdiMod requested in status GdiMod\n" );
4430 physBitmap
->p_status
= DIB_Status_GdiMod
;
4433 case DIB_Status_InSync
:
4434 TRACE("GdiMod requested in status InSync\n" );
4435 X11DRV_DIB_DoProtectDIBSection( physBitmap
, PAGE_NOACCESS
);
4436 physBitmap
->status
= DIB_Status_GdiMod
;
4437 physBitmap
->p_status
= DIB_Status_InSync
;
4440 case DIB_Status_AppMod
:
4441 TRACE("GdiMod requested in status AppMod\n" );
4442 /* make it readonly to avoid app changing data while we copy */
4443 X11DRV_DIB_DoProtectDIBSection( physBitmap
, PAGE_READONLY
);
4444 X11DRV_DIB_DoUpdateDIBSection( physBitmap
, FALSE
);
4445 X11DRV_DIB_DoProtectDIBSection( physBitmap
, PAGE_NOACCESS
);
4446 physBitmap
->p_status
= DIB_Status_AppMod
;
4447 physBitmap
->status
= DIB_Status_GdiMod
;
4452 case DIB_Status_InSync
:
4453 /* App access - request access to read DIB surface */
4454 /* (typically called from signal handler) */
4455 switch (physBitmap
->status
)
4458 case DIB_Status_None
:
4459 /* shouldn't happen from signal handler */
4462 case DIB_Status_GdiMod
:
4463 TRACE("InSync requested in status GdiMod\n" );
4464 X11DRV_DIB_DoProtectDIBSection( physBitmap
, PAGE_READWRITE
);
4465 X11DRV_DIB_DoUpdateDIBSection( physBitmap
, TRUE
);
4466 X11DRV_DIB_DoProtectDIBSection( physBitmap
, PAGE_READONLY
);
4467 physBitmap
->status
= DIB_Status_InSync
;
4470 case DIB_Status_InSync
:
4471 TRACE("InSync requested in status InSync\n" );
4472 /* shouldn't happen from signal handler */
4475 case DIB_Status_AppMod
:
4476 TRACE("InSync requested in status AppMod\n" );
4477 /* no reason to do anything here, and this
4478 * shouldn't happen from signal handler */
4483 case DIB_Status_AppMod
:
4484 /* App access - request access to write DIB surface */
4485 /* (typically called from signal handler) */
4486 switch (physBitmap
->status
)
4489 case DIB_Status_None
:
4490 /* shouldn't happen from signal handler */
4493 case DIB_Status_GdiMod
:
4494 TRACE("AppMod requested in status GdiMod\n" );
4495 X11DRV_DIB_DoProtectDIBSection( physBitmap
, PAGE_READWRITE
);
4496 X11DRV_DIB_DoUpdateDIBSection( physBitmap
, TRUE
);
4497 physBitmap
->status
= DIB_Status_AppMod
;
4500 case DIB_Status_InSync
:
4501 TRACE("AppMod requested in status InSync\n" );
4502 X11DRV_DIB_DoProtectDIBSection( physBitmap
, PAGE_READWRITE
);
4503 physBitmap
->status
= DIB_Status_AppMod
;
4506 case DIB_Status_AppMod
:
4507 TRACE("AppMod requested in status AppMod\n" );
4508 /* shouldn't happen from signal handler */
4513 /* it is up to the caller to do the copy/conversion, probably
4514 * using the return value to decide where to copy from */
4516 LeaveCriticalSection(&physBitmap
->lock
);
4520 /***********************************************************************
4523 static INT
X11DRV_DIB_Lock(X_PHYSBITMAP
*physBitmap
, INT req
)
4525 INT ret
= DIB_Status_None
;
4527 if (!physBitmap
->image
) return ret
; /* not a DIB section */
4528 TRACE("Locking %p from thread %04x\n", physBitmap
->hbitmap
, GetCurrentThreadId());
4529 EnterCriticalSection(&physBitmap
->lock
);
4530 ret
= physBitmap
->status
;
4531 if (req
!= DIB_Status_None
)
4532 X11DRV_DIB_Coerce(physBitmap
, req
);
4536 /***********************************************************************
4539 static void X11DRV_DIB_Unlock(X_PHYSBITMAP
*physBitmap
, BOOL commit
)
4541 if (!physBitmap
->image
) return; /* not a DIB section */
4542 switch (physBitmap
->status
)
4545 case DIB_Status_None
:
4546 /* in case anyone is wondering, this is the "signal handler doesn't
4547 * work" case, where we always have to be ready for app access */
4549 switch (physBitmap
->p_status
)
4551 case DIB_Status_GdiMod
:
4552 TRACE("Unlocking and syncing from GdiMod\n" );
4553 X11DRV_DIB_DoUpdateDIBSection( physBitmap
, TRUE
);
4557 TRACE("Unlocking without needing to sync\n" );
4561 else TRACE("Unlocking with no changes\n");
4562 physBitmap
->p_status
= DIB_Status_None
;
4565 case DIB_Status_GdiMod
:
4566 TRACE("Unlocking in status GdiMod\n" );
4567 /* DIB was protected in Coerce */
4569 /* no commit, revert to InSync if applicable */
4570 if ((physBitmap
->p_status
== DIB_Status_InSync
) ||
4571 (physBitmap
->p_status
== DIB_Status_AppMod
)) {
4572 X11DRV_DIB_DoProtectDIBSection( physBitmap
, PAGE_READONLY
);
4573 physBitmap
->status
= DIB_Status_InSync
;
4578 case DIB_Status_InSync
:
4579 TRACE("Unlocking in status InSync\n" );
4580 /* DIB was already protected in Coerce */
4583 case DIB_Status_AppMod
:
4584 TRACE("Unlocking in status AppMod\n" );
4585 /* DIB was already protected in Coerce */
4586 /* this case is ordinary only called from the signal handler,
4587 * so we don't bother to check for !commit */
4590 LeaveCriticalSection(&physBitmap
->lock
);
4591 TRACE("Unlocked %p\n", physBitmap
->hbitmap
);
4594 /***********************************************************************
4595 * X11DRV_CoerceDIBSection
4597 INT
X11DRV_CoerceDIBSection(X11DRV_PDEVICE
*physDev
, INT req
)
4599 if (!physDev
|| !physDev
->bitmap
) return DIB_Status_None
;
4600 return X11DRV_DIB_Coerce(physDev
->bitmap
, req
);
4603 /***********************************************************************
4604 * X11DRV_LockDIBSection
4606 INT
X11DRV_LockDIBSection(X11DRV_PDEVICE
*physDev
, INT req
)
4608 if (!physDev
|| !physDev
->bitmap
) return DIB_Status_None
;
4609 return X11DRV_DIB_Lock(physDev
->bitmap
, req
);
4612 /***********************************************************************
4613 * X11DRV_UnlockDIBSection
4615 void X11DRV_UnlockDIBSection(X11DRV_PDEVICE
*physDev
, BOOL commit
)
4617 if (!physDev
|| !physDev
->bitmap
) return;
4618 X11DRV_DIB_Unlock(physDev
->bitmap
, commit
);
4622 #ifdef HAVE_LIBXXSHM
4623 /***********************************************************************
4624 * X11DRV_XShmErrorHandler
4627 static int XShmErrorHandler( Display
*dpy
, XErrorEvent
*event
, void *arg
)
4629 return 1; /* FIXME: should check event contents */
4632 /***********************************************************************
4633 * X11DRV_XShmCreateImage
4636 static XImage
*X11DRV_XShmCreateImage( int width
, int height
, int bpp
,
4637 XShmSegmentInfo
* shminfo
)
4641 image
= XShmCreateImage(gdi_display
, visual
, bpp
, ZPixmap
, NULL
, shminfo
, width
, height
);
4644 shminfo
->shmid
= shmget(IPC_PRIVATE
, image
->bytes_per_line
* height
,
4646 if( shminfo
->shmid
!= -1 )
4648 shminfo
->shmaddr
= image
->data
= shmat(shminfo
->shmid
, 0, 0);
4649 if( shminfo
->shmaddr
!= (char*)-1 )
4653 shminfo
->readOnly
= FALSE
;
4654 X11DRV_expect_error( gdi_display
, XShmErrorHandler
, NULL
);
4655 ok
= (XShmAttach( gdi_display
, shminfo
) != 0);
4656 XSync( gdi_display
, False
);
4657 if (X11DRV_check_error()) ok
= FALSE
;
4660 shmctl(shminfo
->shmid
, IPC_RMID
, 0);
4661 return image
; /* Success! */
4663 /* An error occurred */
4664 shmdt(shminfo
->shmaddr
);
4666 shmctl(shminfo
->shmid
, IPC_RMID
, 0);
4667 shminfo
->shmid
= -1;
4669 XFlush(gdi_display
);
4670 XDestroyImage(image
);
4675 #endif /* HAVE_LIBXXSHM */
4678 /***********************************************************************
4679 * X11DRV_CreateDIBSection (X11DRV.@)
4681 HBITMAP CDECL
X11DRV_CreateDIBSection( X11DRV_PDEVICE
*physDev
, HBITMAP hbitmap
,
4682 const BITMAPINFO
*bmi
, UINT usage
)
4684 X_PHYSBITMAP
*physBitmap
;
4687 if (!(physBitmap
= X11DRV_init_phys_bitmap( hbitmap
))) return 0;
4688 physBitmap
->status
= DIB_Status_None
;
4690 GetObjectW( hbitmap
, sizeof(dib
), &dib
);
4692 /* create color map */
4693 if (dib
.dsBm
.bmBitsPixel
<= 8)
4695 physBitmap
->colorMap
= X11DRV_DIB_BuildColorMap( physDev
,
4696 usage
, dib
.dsBm
.bmBitsPixel
, bmi
,
4697 &physBitmap
->nColorMap
);
4700 /* create pixmap and X image */
4702 physBitmap
->pixmap_depth
= (dib
.dsBm
.bmBitsPixel
== 1) ? 1 : screen_depth
;
4703 physBitmap
->pixmap
= XCreatePixmap( gdi_display
, root_window
, dib
.dsBm
.bmWidth
,
4704 dib
.dsBm
.bmHeight
, physBitmap
->pixmap_depth
);
4705 #ifdef HAVE_LIBXXSHM
4706 physBitmap
->shminfo
.shmid
= -1;
4707 if (!XShmQueryExtension(gdi_display
) ||
4708 !(physBitmap
->image
= X11DRV_XShmCreateImage( dib
.dsBm
.bmWidth
, dib
.dsBm
.bmHeight
,
4709 physBitmap
->pixmap_depth
, &physBitmap
->shminfo
)) )
4711 physBitmap
->image
= X11DRV_DIB_CreateXImage( dib
.dsBm
.bmWidth
, dib
.dsBm
.bmHeight
,
4712 physBitmap
->pixmap_depth
);
4713 wine_tsx11_unlock();
4714 if (!physBitmap
->pixmap
|| !physBitmap
->image
) return 0;
4716 /* install fault handler */
4717 InitializeCriticalSection( &physBitmap
->lock
);
4718 physBitmap
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": X_PHYSBITMAP.lock");
4720 physBitmap
->base
= dib
.dsBm
.bmBits
;
4721 physBitmap
->size
= dib
.dsBmih
.biSizeImage
;
4722 physBitmap
->status
= DIB_Status_AppMod
;
4725 dibs_handler
= AddVectoredExceptionHandler( TRUE
, X11DRV_DIB_FaultHandler
);
4726 EnterCriticalSection( &dibs_cs
);
4727 list_add_head( &dibs_list
, &physBitmap
->entry
);
4728 LeaveCriticalSection( &dibs_cs
);
4730 X11DRV_DIB_DoProtectDIBSection( physBitmap
, PAGE_READWRITE
);
4735 /***********************************************************************
4736 * X11DRV_DIB_DeleteDIBSection
4738 void X11DRV_DIB_DeleteDIBSection(X_PHYSBITMAP
*physBitmap
, DIBSECTION
*dib
)
4742 EnterCriticalSection( &dibs_cs
);
4743 list_remove( &physBitmap
->entry
);
4744 last
= list_empty( &dibs_list
);
4745 LeaveCriticalSection( &dibs_cs
);
4749 RemoveVectoredExceptionHandler( dibs_handler
);
4750 dibs_handler
= NULL
;
4753 if (dib
->dshSection
)
4754 X11DRV_DIB_Coerce(physBitmap
, DIB_Status_InSync
);
4756 if (physBitmap
->image
)
4759 #ifdef HAVE_LIBXXSHM
4760 if (physBitmap
->shminfo
.shmid
!= -1)
4762 XShmDetach( gdi_display
, &(physBitmap
->shminfo
) );
4763 XDestroyImage( physBitmap
->image
);
4764 shmdt( physBitmap
->shminfo
.shmaddr
);
4765 physBitmap
->shminfo
.shmid
= -1;
4769 X11DRV_DIB_DestroyXImage( physBitmap
->image
);
4770 wine_tsx11_unlock();
4773 HeapFree(GetProcessHeap(), 0, physBitmap
->colorMap
);
4774 physBitmap
->lock
.DebugInfo
->Spare
[0] = 0;
4775 DeleteCriticalSection(&physBitmap
->lock
);
4778 /***********************************************************************
4779 * SetDIBColorTable (X11DRV.@)
4781 UINT CDECL
X11DRV_SetDIBColorTable( X11DRV_PDEVICE
*physDev
, UINT start
, UINT count
, const RGBQUAD
*colors
)
4785 X_PHYSBITMAP
*physBitmap
= physDev
->bitmap
;
4787 if (!physBitmap
) return 0;
4788 GetObjectW( physBitmap
->hbitmap
, sizeof(dib
), &dib
);
4790 if (physBitmap
->colorMap
&& start
< physBitmap
->nColorMap
) {
4791 UINT end
= count
+ start
;
4792 if (end
> physBitmap
->nColorMap
) end
= physBitmap
->nColorMap
;
4794 * Changing color table might change the mapping between
4795 * DIB colors and X11 colors and thus alter the visible state
4796 * of the bitmap object.
4799 * FIXME we need to recalculate the pen, brush, text and bkgnd pixels here,
4800 * at least for a 1 bpp dibsection
4802 X11DRV_DIB_Lock( physBitmap
, DIB_Status_AppMod
);
4803 X11DRV_DIB_GenColorMap( physDev
, physBitmap
->colorMap
, DIB_RGB_COLORS
,
4804 dib
.dsBm
.bmBitsPixel
,
4805 TRUE
, colors
, start
, end
);
4806 X11DRV_DIB_Unlock( physBitmap
, TRUE
);
4813 /***********************************************************************
4814 * X11DRV_DIB_CreateDIBFromBitmap
4816 * Allocates a packed DIB and copies the bitmap data into it.
4818 HGLOBAL
X11DRV_DIB_CreateDIBFromBitmap(HDC hdc
, HBITMAP hBmp
)
4823 LPBITMAPINFOHEADER pbmiHeader
;
4824 unsigned int cDataSize
, cPackedSize
, OffsetBits
;
4827 if (!GetObjectW( hBmp
, sizeof(bmp
), &bmp
)) return 0;
4830 * A packed DIB contains a BITMAPINFO structure followed immediately by
4831 * an optional color palette and the pixel data.
4834 /* Calculate the size of the packed DIB */
4835 cDataSize
= X11DRV_DIB_GetDIBWidthBytes( bmp
.bmWidth
, bmp
.bmBitsPixel
) * abs( bmp
.bmHeight
);
4836 cPackedSize
= sizeof(BITMAPINFOHEADER
)
4837 + ( (bmp
.bmBitsPixel
<= 8) ? (sizeof(RGBQUAD
) * (1 << bmp
.bmBitsPixel
)) : 0 )
4839 /* Get the offset to the bits */
4840 OffsetBits
= cPackedSize
- cDataSize
;
4842 /* Allocate the packed DIB */
4843 TRACE("\tAllocating packed DIB of size %d\n", cPackedSize
);
4844 hPackedDIB
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_DDESHARE
/*| GMEM_ZEROINIT*/,
4848 WARN("Could not allocate packed DIB!\n");
4852 /* A packed DIB starts with a BITMAPINFOHEADER */
4853 pPackedDIB
= GlobalLock(hPackedDIB
);
4854 pbmiHeader
= (LPBITMAPINFOHEADER
)pPackedDIB
;
4856 /* Init the BITMAPINFOHEADER */
4857 pbmiHeader
->biSize
= sizeof(BITMAPINFOHEADER
);
4858 pbmiHeader
->biWidth
= bmp
.bmWidth
;
4859 pbmiHeader
->biHeight
= bmp
.bmHeight
;
4860 pbmiHeader
->biPlanes
= 1;
4861 pbmiHeader
->biBitCount
= bmp
.bmBitsPixel
;
4862 pbmiHeader
->biCompression
= BI_RGB
;
4863 pbmiHeader
->biSizeImage
= 0;
4864 pbmiHeader
->biXPelsPerMeter
= pbmiHeader
->biYPelsPerMeter
= 0;
4865 pbmiHeader
->biClrUsed
= 0;
4866 pbmiHeader
->biClrImportant
= 0;
4868 /* Retrieve the DIB bits from the bitmap and fill in the
4869 * DIB color table if present */
4871 nLinesCopied
= GetDIBits(hdc
, /* Handle to device context */
4872 hBmp
, /* Handle to bitmap */
4873 0, /* First scan line to set in dest bitmap */
4874 bmp
.bmHeight
, /* Number of scan lines to copy */
4875 pPackedDIB
+ OffsetBits
, /* [out] Address of array for bitmap bits */
4876 (LPBITMAPINFO
) pbmiHeader
, /* [out] Address of BITMAPINFO structure */
4877 0); /* RGB or palette index */
4878 GlobalUnlock(hPackedDIB
);
4880 /* Cleanup if GetDIBits failed */
4881 if (nLinesCopied
!= bmp
.bmHeight
)
4883 TRACE("\tGetDIBits returned %d. Actual lines=%d\n", nLinesCopied
, bmp
.bmHeight
);
4884 GlobalFree(hPackedDIB
);
4891 /**************************************************************************
4892 * X11DRV_DIB_CreateDIBFromPixmap
4894 * Allocates a packed DIB and copies the Pixmap data into it.
4895 * The Pixmap passed in is deleted after the conversion.
4897 HGLOBAL
X11DRV_DIB_CreateDIBFromPixmap(Pixmap pixmap
, HDC hdc
)
4900 X_PHYSBITMAP
*physBitmap
;
4903 HGLOBAL hPackedDIB
= 0;
4905 int x
,y
; /* Unused */
4906 unsigned border_width
; /* Unused */
4907 unsigned int depth
, width
, height
;
4909 /* Get the Pixmap dimensions and bit depth */
4911 if (!XGetGeometry(gdi_display
, pixmap
, &root
, &x
, &y
, &width
, &height
,
4912 &border_width
, &depth
)) depth
= 0;
4913 wine_tsx11_unlock();
4914 if (!depth
) return 0;
4916 TRACE("\tPixmap properties: width=%d, height=%d, depth=%d\n",
4917 width
, height
, depth
);
4920 * Create an HBITMAP with the same dimensions and BPP as the pixmap,
4921 * and make it a container for the pixmap passed.
4923 if (!(hBmp
= CreateBitmap( width
, height
, 1, depth_to_bpp(depth
), NULL
))) return 0;
4925 /* force bitmap to be owned by a screen DC */
4926 hdcMem
= CreateCompatibleDC( hdc
);
4927 SelectObject( hdcMem
, SelectObject( hdcMem
, hBmp
));
4930 physBitmap
= X11DRV_get_phys_bitmap( hBmp
);
4932 /* swap the new pixmap in */
4933 orig_pixmap
= physBitmap
->pixmap
;
4934 physBitmap
->pixmap
= pixmap
;
4937 * Create a packed DIB from the Pixmap wrapper bitmap created above.
4938 * A packed DIB contains a BITMAPINFO structure followed immediately by
4939 * an optional color palette and the pixel data.
4941 hPackedDIB
= X11DRV_DIB_CreateDIBFromBitmap(hdc
, hBmp
);
4943 /* we can now get rid of the HBITMAP and its original pixmap */
4944 physBitmap
->pixmap
= orig_pixmap
;
4947 TRACE("\tReturning packed DIB %p\n", hPackedDIB
);
4952 /**************************************************************************
4953 * X11DRV_DIB_CreatePixmapFromDIB
4955 * Creates a Pixmap from a packed DIB
4957 Pixmap
X11DRV_DIB_CreatePixmapFromDIB( HGLOBAL hPackedDIB
, HDC hdc
)
4960 X_PHYSBITMAP
*physBitmap
;
4964 /* Create a DDB from the DIB */
4966 pbmi
= GlobalLock(hPackedDIB
);
4967 hBmp
= CreateDIBitmap(hdc
, &pbmi
->bmiHeader
, CBM_INIT
,
4968 (LPBYTE
)pbmi
+ bitmap_info_size( pbmi
, DIB_RGB_COLORS
),
4969 pbmi
, DIB_RGB_COLORS
);
4970 GlobalUnlock(hPackedDIB
);
4972 /* clear the physBitmap so that we can steal its pixmap */
4973 physBitmap
= X11DRV_get_phys_bitmap( hBmp
);
4974 pixmap
= physBitmap
->pixmap
;
4975 physBitmap
->pixmap
= 0;
4977 /* Delete the DDB we created earlier now that we have stolen its pixmap */
4980 TRACE("Returning Pixmap %lx\n", pixmap
);