mshtml: Added more IHTMLElement_{put, get}_onclick tests.
[wine/multimedia.git] / dlls / winex11.drv / dib.c
blobba58f57af60da856b42e537553fe87dea3308e1b
1 /*
2 * X11DRV device-independent bitmaps
4 * Copyright 1993,1994 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "config.h"
22 #include "wine/port.h"
24 #include <X11/Xlib.h>
25 #ifdef HAVE_LIBXXSHM
26 #include <X11/extensions/XShm.h>
27 # ifdef HAVE_SYS_SHM_H
28 # include <sys/shm.h>
29 # endif
30 # ifdef HAVE_SYS_IPC_H
31 # include <sys/ipc.h>
32 # endif
33 #endif /* defined(HAVE_LIBXXSHM) */
35 #include <stdarg.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include "windef.h"
39 #include "winbase.h"
40 #include "wingdi.h"
41 #include "x11drv.h"
42 #include "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 =
52 0, 0, &dibs_cs,
53 { &dibs_cs_debug.ProcessLocksList, &dibs_cs_debug.ProcessLocksList },
54 0, 0, { (DWORD_PTR)(__FILE__ ": dibs_cs") }
56 static CRITICAL_SECTION dibs_cs = { &dibs_cs_debug, -1, 0, 0, 0, 0 };
58 static PVOID dibs_handler;
60 static int ximageDepthTable[32];
62 /* This structure holds the arguments for DIB_SetImageBits() */
63 typedef struct
65 X11DRV_PDEVICE *physDev;
66 LPCVOID bits;
67 XImage *image;
68 PALETTEENTRY *palentry;
69 int lines;
70 DWORD infoWidth;
71 WORD depth;
72 WORD infoBpp;
73 WORD compression;
74 ColorShifts *shifts;
75 RGBQUAD *colorMap;
76 int nColorMap;
77 Drawable drawable;
78 GC gc;
79 int xSrc;
80 int ySrc;
81 int xDest;
82 int yDest;
83 int width;
84 int height;
85 DWORD rMask;
86 DWORD gMask;
87 DWORD bMask;
88 enum x11drv_shm_mode shm_mode;
89 int dibpitch;
90 DWORD sizeImage;
91 X_PHYSBITMAP *physBitmap;
92 } X11DRV_DIB_IMAGEBITS_DESCR;
95 enum Rle_EscapeCodes
97 RLE_EOL = 0, /* End of line */
98 RLE_END = 1, /* End of bitmap */
99 RLE_DELTA = 2 /* Delta */
103 static INT X11DRV_DIB_Coerce(X_PHYSBITMAP *,INT);
106 Some of the following helper functions are duplicated in
107 dlls/gdi/dib.c
110 /***********************************************************************
111 * DIB_DoProtectDIBSection
113 static void X11DRV_DIB_DoProtectDIBSection( X_PHYSBITMAP *physBitmap, DWORD new_prot )
115 DWORD old_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 );
134 if (testimage)
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));
144 error:
145 WARN( "(%d): Unsupported depth\n", depth );
146 return 4 * width;
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 )
157 return ((width * depth + 31) / 8) & ~3;
161 /***********************************************************************
162 * bitmap_info_size
164 * Return the size of the bitmap info structure including color table.
166 int bitmap_info_size( const BITMAPINFO * info, WORD coloruse )
168 unsigned int colors, size, masks = 0;
170 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
172 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
173 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
174 return sizeof(BITMAPCOREHEADER) + colors *
175 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
177 else /* assume BITMAPINFOHEADER */
179 colors = info->bmiHeader.biClrUsed;
180 if (!colors && (info->bmiHeader.biBitCount <= 8))
181 colors = 1 << info->bmiHeader.biBitCount;
182 if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3;
183 size = max( info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) );
184 return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
189 /***********************************************************************
190 * X11DRV_DIB_CreateXImage
192 * Create an X image.
194 XImage *X11DRV_DIB_CreateXImage( int width, int height, int depth )
196 int width_bytes;
197 XImage *image = NULL;
198 void *data;
200 wine_tsx11_lock();
201 width_bytes = X11DRV_DIB_GetXImageWidthBytes( width, depth );
202 data = HeapAlloc( GetProcessHeap(), 0, height * width_bytes );
203 if (data) image = XCreateImage( gdi_display, visual, depth, ZPixmap, 0,
204 data, width, height, 32, width_bytes );
205 if (!image) HeapFree( GetProcessHeap(), 0, data );
206 wine_tsx11_unlock();
207 return image;
211 /***********************************************************************
212 * X11DRV_DIB_DestroyXImage
214 * Destroy an X image created with X11DRV_DIB_CreateXImage.
216 void X11DRV_DIB_DestroyXImage( XImage *image )
218 HeapFree( GetProcessHeap(), 0, image->data );
219 image->data = NULL;
220 wine_tsx11_lock();
221 XDestroyImage( image );
222 wine_tsx11_unlock();
226 /***********************************************************************
227 * X11DRV_DIB_GetColorCount
229 * Computes the number of colors for the bitmap palette.
230 * Should not be called for a >8-bit deep bitmap.
232 static unsigned int X11DRV_DIB_GetColorCount(const BITMAPINFO *info)
234 unsigned int colors = min( info->bmiHeader.biClrUsed, 256 );
235 if (!colors) colors = 1 << info->bmiHeader.biBitCount;
236 return colors;
240 static inline BOOL colour_is_brighter(RGBQUAD c1, RGBQUAD c2)
242 return (c1.rgbRed * c1.rgbRed + c1.rgbGreen * c1.rgbGreen + c1.rgbBlue * c1.rgbBlue) >
243 (c2.rgbRed * c2.rgbRed + c2.rgbGreen * c2.rgbGreen + c2.rgbBlue * c2.rgbBlue);
246 /***********************************************************************
247 * X11DRV_DIB_GenColorMap
249 * Fills the color map of a bitmap palette. Should not be called
250 * for a >8-bit deep bitmap.
252 static int *X11DRV_DIB_GenColorMap( X11DRV_PDEVICE *physDev, int *colorMapping,
253 WORD coloruse, WORD depth, const void *colorPtr, int start, int end )
255 int i;
257 if (coloruse == DIB_RGB_COLORS)
259 const RGBQUAD * rgb = colorPtr;
261 if (depth == 1) /* Monochrome */
263 BOOL invert = FALSE;
264 RGBQUAD table[2];
266 if (GetDIBColorTable( physDev->dev.hdc, 0, 2, table ) == 2)
267 invert = !colour_is_brighter(table[1], table[0]);
269 for (i = start; i < end; i++, rgb++)
270 colorMapping[i] = ((rgb->rgbRed + rgb->rgbGreen +
271 rgb->rgbBlue > 255*3/2 && !invert) ||
272 (rgb->rgbRed + rgb->rgbGreen +
273 rgb->rgbBlue <= 255*3/2 && invert));
275 else
276 for (i = start; i < end; i++, rgb++)
277 colorMapping[i] = X11DRV_PALETTE_LookupPixel(physDev->color_shifts, RGB(rgb->rgbRed,
278 rgb->rgbGreen,
279 rgb->rgbBlue));
281 else /* DIB_PAL_COLORS */
283 const WORD * index = colorPtr;
285 for (i = start; i < end; i++, index++)
286 colorMapping[i] = X11DRV_PALETTE_ToPhysical( physDev, PALETTEINDEX(*index) );
289 return colorMapping;
292 /***********************************************************************
293 * X11DRV_DIB_BuildColorMap
295 * Build the color map from the bitmap palette. Should not be called
296 * for a >8-bit deep bitmap.
298 static int *X11DRV_DIB_BuildColorMap( X11DRV_PDEVICE *physDev, WORD coloruse, WORD depth,
299 const BITMAPINFO *info, int *nColors )
301 const void *colorPtr;
302 int *colorMapping;
305 *nColors = X11DRV_DIB_GetColorCount(info);
306 if (!*nColors) return NULL;
308 colorPtr = (const BYTE*)info + (WORD)info->bmiHeader.biSize;
309 if (!(colorMapping = HeapAlloc(GetProcessHeap(), 0, *nColors * sizeof(int) )))
310 return NULL;
312 return X11DRV_DIB_GenColorMap( physDev, colorMapping, coloruse, depth,
313 colorPtr, 0, *nColors);
316 /***********************************************************************
317 * X11DRV_DIB_MapColor
319 static int X11DRV_DIB_MapColor( int *physMap, int nPhysMap, int phys, int oldcol )
321 int color;
323 if ((oldcol < nPhysMap) && (physMap[oldcol] == phys))
324 return oldcol;
326 for (color = 0; color < nPhysMap; color++)
327 if (physMap[color] == phys)
328 return color;
330 WARN("Strange color %08x\n", phys);
331 return 0;
335 /*********************************************************************
336 * X11DRV_DIB_GetNearestIndex
338 * Helper for X11DRV_DIB_GetDIBits.
339 * Returns the nearest colour table index for a given RGB.
340 * Nearest is defined by minimizing the sum of the squares.
342 static INT X11DRV_DIB_GetNearestIndex(RGBQUAD *colormap, int numColors, BYTE r, BYTE g, BYTE b)
344 INT i, best = -1, diff, bestdiff = -1;
345 RGBQUAD *color;
347 for(color = colormap, i = 0; i < numColors; color++, i++) {
348 diff = (r - color->rgbRed) * (r - color->rgbRed) +
349 (g - color->rgbGreen) * (g - color->rgbGreen) +
350 (b - color->rgbBlue) * (b - color->rgbBlue);
351 if(diff == 0)
352 return i;
353 if(best == -1 || diff < bestdiff) {
354 best = i;
355 bestdiff = diff;
358 return best;
360 /*********************************************************************
361 * X11DRV_DIB_MaskToShift
363 * Helper for X11DRV_DIB_GetDIBits.
364 * Returns the by how many bits to shift a given color so that it is
365 * in the proper position.
367 INT X11DRV_DIB_MaskToShift(DWORD mask)
369 int shift;
371 if (mask==0)
372 return 0;
374 shift=0;
375 while ((mask&1)==0) {
376 mask>>=1;
377 shift++;
379 return shift;
382 /***********************************************************************
383 * X11DRV_DIB_CheckMask
385 * Check RGB mask if it is either 0 or matches visual's mask.
387 static inline int X11DRV_DIB_CheckMask(int red_mask, int green_mask, int blue_mask)
389 return ( red_mask == 0 && green_mask == 0 && blue_mask == 0 ) ||
390 ( red_mask == visual->red_mask && green_mask == visual->green_mask &&
391 blue_mask == visual->blue_mask );
394 /***********************************************************************
395 * X11DRV_DIB_SetImageBits_1
397 * SetDIBits for a 1-bit deep DIB.
399 static void X11DRV_DIB_SetImageBits_1( int lines, const BYTE *srcbits,
400 DWORD srcwidth, DWORD dstwidth, int left,
401 int *colors, XImage *bmpImage, int linebytes)
403 int h, width;
404 const BYTE* srcbyte;
405 BYTE srcval, extra;
406 DWORD i, x;
408 if (lines < 0 ) {
409 lines = -lines;
410 srcbits = srcbits + linebytes * (lines - 1);
411 linebytes = -linebytes;
414 if ((extra = (left & 7)) != 0) {
415 left &= ~7;
416 dstwidth += extra;
418 srcbits += left >> 3;
419 width = min(srcwidth, dstwidth);
421 /* ==== pal 1 dib -> any bmp format ==== */
422 for (h = lines-1; h >=0; h--) {
423 srcbyte=srcbits;
424 for (i = width/8, x = left; i > 0; i--) {
425 srcval=*srcbyte++;
426 XPutPixel( bmpImage, x++, h, colors[ srcval >> 7] );
427 XPutPixel( bmpImage, x++, h, colors[(srcval >> 6) & 1] );
428 XPutPixel( bmpImage, x++, h, colors[(srcval >> 5) & 1] );
429 XPutPixel( bmpImage, x++, h, colors[(srcval >> 4) & 1] );
430 XPutPixel( bmpImage, x++, h, colors[(srcval >> 3) & 1] );
431 XPutPixel( bmpImage, x++, h, colors[(srcval >> 2) & 1] );
432 XPutPixel( bmpImage, x++, h, colors[(srcval >> 1) & 1] );
433 XPutPixel( bmpImage, x++, h, colors[ srcval & 1] );
435 if (width % 8){
436 srcval=*srcbyte;
437 switch (width & 7)
439 case 7: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
440 case 6: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
441 case 5: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
442 case 4: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
443 case 3: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
444 case 2: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
445 case 1: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]);
448 srcbits += linebytes;
452 /***********************************************************************
453 * X11DRV_DIB_GetImageBits_1
455 * GetDIBits for a 1-bit deep DIB.
457 static void X11DRV_DIB_GetImageBits_1( int lines, BYTE *dstbits,
458 DWORD dstwidth, DWORD srcwidth,
459 RGBQUAD *colors, PALETTEENTRY *srccolors,
460 XImage *bmpImage, int linebytes )
462 DWORD x;
463 int h, width = min(dstwidth, srcwidth);
465 if (lines < 0 ) {
466 lines = -lines;
467 dstbits = dstbits + linebytes * (lines - 1);
468 linebytes = -linebytes;
471 switch (bmpImage->depth)
473 case 1:
474 case 4:
475 if (X11DRV_DIB_CheckMask(bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask)
476 && srccolors) {
477 /* ==== pal 1 or 4 bmp -> pal 1 dib ==== */
478 BYTE* dstbyte;
480 for (h=lines-1; h>=0; h--) {
481 BYTE dstval;
482 dstbyte=dstbits;
483 dstval=0;
484 for (x=0; x<width; x++) {
485 PALETTEENTRY srcval;
486 srcval=srccolors[XGetPixel(bmpImage, x, h)];
487 dstval|=(X11DRV_DIB_GetNearestIndex
488 (colors, 2,
489 srcval.peRed,
490 srcval.peGreen,
491 srcval.peBlue) << (7 - (x & 7)));
492 if ((x&7)==7) {
493 *dstbyte++=dstval;
494 dstval=0;
497 if ((width&7)!=0) {
498 *dstbyte++=dstval;
500 /* pad with 0 to DWORD alignment */
501 for (x = (x+7)&~7; x < ((width + 31) & ~31); x+=8)
502 *dstbyte++ = 0;
503 dstbits += linebytes;
505 } else {
506 goto notsupported;
508 break;
510 case 8:
511 if (X11DRV_DIB_CheckMask(bmpImage->red_mask, bmpImage->green_mask, bmpImage->blue_mask)
512 && srccolors) {
513 /* ==== pal 8 bmp -> pal 1 dib ==== */
514 const void* srcbits;
515 const BYTE* srcpixel;
516 BYTE* dstbyte;
518 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
520 for (h=0; h<lines; h++) {
521 BYTE dstval;
522 srcpixel=srcbits;
523 dstbyte=dstbits;
524 dstval=0;
525 for (x=0; x<width; x++) {
526 PALETTEENTRY srcval;
527 srcval=srccolors[*srcpixel++];
528 dstval|=(X11DRV_DIB_GetNearestIndex
529 (colors, 2,
530 srcval.peRed,
531 srcval.peGreen,
532 srcval.peBlue) << (7-(x&7)) );
533 if ((x&7)==7) {
534 *dstbyte++=dstval;
535 dstval=0;
538 if ((width&7)!=0) {
539 *dstbyte=dstval;
541 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
542 dstbits += linebytes;
544 } else {
545 goto notsupported;
547 break;
549 case 15:
550 case 16:
552 const void* srcbits;
553 const WORD* srcpixel;
554 BYTE* dstbyte;
556 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
558 if (bmpImage->green_mask==0x03e0) {
559 if (bmpImage->red_mask==0x7c00) {
560 /* ==== rgb 555 bmp -> pal 1 dib ==== */
561 for (h=0; h<lines; h++) {
562 BYTE dstval;
563 srcpixel=srcbits;
564 dstbyte=dstbits;
565 dstval=0;
566 for (x=0; x<width; x++) {
567 WORD srcval;
568 srcval=*srcpixel++;
569 dstval|=(X11DRV_DIB_GetNearestIndex
570 (colors, 2,
571 ((srcval >> 7) & 0xf8) | /* r */
572 ((srcval >> 12) & 0x07),
573 ((srcval >> 2) & 0xf8) | /* g */
574 ((srcval >> 7) & 0x07),
575 ((srcval << 3) & 0xf8) | /* b */
576 ((srcval >> 2) & 0x07) ) << (7-(x&7)) );
577 if ((x&7)==7) {
578 *dstbyte++=dstval;
579 dstval=0;
582 if ((width&7)!=0) {
583 *dstbyte=dstval;
585 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
586 dstbits += linebytes;
588 } else if (bmpImage->blue_mask==0x7c00) {
589 /* ==== bgr 555 bmp -> pal 1 dib ==== */
590 for (h=0; h<lines; h++) {
591 WORD dstval;
592 srcpixel=srcbits;
593 dstbyte=dstbits;
594 dstval=0;
595 for (x=0; x<width; x++) {
596 BYTE srcval;
597 srcval=*srcpixel++;
598 dstval|=(X11DRV_DIB_GetNearestIndex
599 (colors, 2,
600 ((srcval << 3) & 0xf8) | /* r */
601 ((srcval >> 2) & 0x07),
602 ((srcval >> 2) & 0xf8) | /* g */
603 ((srcval >> 7) & 0x07),
604 ((srcval >> 7) & 0xf8) | /* b */
605 ((srcval >> 12) & 0x07) ) << (7-(x&7)) );
606 if ((x&7)==7) {
607 *dstbyte++=dstval;
608 dstval=0;
611 if ((width&7)!=0) {
612 *dstbyte=dstval;
614 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
615 dstbits += linebytes;
617 } else {
618 goto notsupported;
620 } else if (bmpImage->green_mask==0x07e0) {
621 if (bmpImage->red_mask==0xf800) {
622 /* ==== rgb 565 bmp -> pal 1 dib ==== */
623 for (h=0; h<lines; h++) {
624 BYTE dstval;
625 srcpixel=srcbits;
626 dstbyte=dstbits;
627 dstval=0;
628 for (x=0; x<width; x++) {
629 WORD srcval;
630 srcval=*srcpixel++;
631 dstval|=(X11DRV_DIB_GetNearestIndex
632 (colors, 2,
633 ((srcval >> 8) & 0xf8) | /* r */
634 ((srcval >> 13) & 0x07),
635 ((srcval >> 3) & 0xfc) | /* g */
636 ((srcval >> 9) & 0x03),
637 ((srcval << 3) & 0xf8) | /* b */
638 ((srcval >> 2) & 0x07) ) << (7-(x&7)) );
639 if ((x&7)==7) {
640 *dstbyte++=dstval;
641 dstval=0;
644 if ((width&7)!=0) {
645 *dstbyte=dstval;
647 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
648 dstbits += linebytes;
650 } else if (bmpImage->blue_mask==0xf800) {
651 /* ==== bgr 565 bmp -> pal 1 dib ==== */
652 for (h=0; h<lines; h++) {
653 BYTE dstval;
654 srcpixel=srcbits;
655 dstbyte=dstbits;
656 dstval=0;
657 for (x=0; x<width; x++) {
658 WORD srcval;
659 srcval=*srcpixel++;
660 dstval|=(X11DRV_DIB_GetNearestIndex
661 (colors, 2,
662 ((srcval << 3) & 0xf8) | /* r */
663 ((srcval >> 2) & 0x07),
664 ((srcval >> 3) & 0xfc) | /* g */
665 ((srcval >> 9) & 0x03),
666 ((srcval >> 8) & 0xf8) | /* b */
667 ((srcval >> 13) & 0x07) ) << (7-(x&7)) );
668 if ((x&7)==7) {
669 *dstbyte++=dstval;
670 dstval=0;
673 if ((width&7)!=0) {
674 *dstbyte=dstval;
676 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
677 dstbits += linebytes;
679 } else {
680 goto notsupported;
682 } else {
683 goto notsupported;
686 break;
688 case 24:
689 case 32:
691 const void* srcbits;
692 const BYTE *srcbyte;
693 BYTE* dstbyte;
694 int bytes_per_pixel;
696 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
697 bytes_per_pixel=(bmpImage->bits_per_pixel==24?3:4);
699 if (bmpImage->green_mask!=0x00ff00 ||
700 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
701 goto notsupported;
702 } else if (bmpImage->blue_mask==0xff) {
703 /* ==== rgb 888 or 0888 bmp -> pal 1 dib ==== */
704 for (h=0; h<lines; h++) {
705 BYTE dstval;
706 srcbyte=srcbits;
707 dstbyte=dstbits;
708 dstval=0;
709 for (x=0; x<width; x++) {
710 dstval|=(X11DRV_DIB_GetNearestIndex
711 (colors, 2,
712 srcbyte[2],
713 srcbyte[1],
714 srcbyte[0]) << (7-(x&7)) );
715 srcbyte+=bytes_per_pixel;
716 if ((x&7)==7) {
717 *dstbyte++=dstval;
718 dstval=0;
721 if ((width&7)!=0) {
722 *dstbyte=dstval;
724 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
725 dstbits += linebytes;
727 } else {
728 /* ==== bgr 888 or 0888 bmp -> pal 1 dib ==== */
729 for (h=0; h<lines; h++) {
730 BYTE dstval;
731 srcbyte=srcbits;
732 dstbyte=dstbits;
733 dstval=0;
734 for (x=0; x<width; x++) {
735 dstval|=(X11DRV_DIB_GetNearestIndex
736 (colors, 2,
737 srcbyte[0],
738 srcbyte[1],
739 srcbyte[2]) << (7-(x&7)) );
740 srcbyte+=bytes_per_pixel;
741 if ((x&7)==7) {
742 *dstbyte++=dstval;
743 dstval=0;
746 if ((width&7)!=0) {
747 *dstbyte=dstval;
749 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
750 dstbits += linebytes;
754 break;
756 default:
757 notsupported:
759 BYTE* dstbyte;
760 BYTE neg = 0;
761 unsigned long white = (1 << bmpImage->bits_per_pixel) - 1;
763 /* ==== any bmp format -> pal 1 dib ==== */
764 if ((unsigned)colors[0].rgbRed+colors[0].rgbGreen+colors[0].rgbBlue >=
765 (unsigned)colors[1].rgbRed+colors[1].rgbGreen+colors[1].rgbBlue )
766 neg = 1;
768 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 1 bit DIB, "
769 "%s color mapping\n",
770 bmpImage->bits_per_pixel, bmpImage->red_mask,
771 bmpImage->green_mask, bmpImage->blue_mask,
772 neg?"negative":"direct" );
774 for (h=lines-1; h>=0; h--) {
775 BYTE dstval;
776 dstbyte=dstbits;
777 dstval=0;
778 for (x=0; x<width; x++) {
779 dstval|=((XGetPixel( bmpImage, x, h) >= white) ^ neg) << (7 - (x&7));
780 if ((x&7)==7) {
781 *dstbyte++=dstval;
782 dstval=0;
785 if ((width&7)!=0) {
786 *dstbyte=dstval;
788 dstbits += linebytes;
791 break;
795 /***********************************************************************
796 * X11DRV_DIB_SetImageBits_4
798 * SetDIBits for a 4-bit deep DIB.
800 static void X11DRV_DIB_SetImageBits_4( int lines, const BYTE *srcbits,
801 DWORD srcwidth, DWORD dstwidth, int left,
802 int *colors, XImage *bmpImage, int linebytes)
804 int h, width;
805 const BYTE* srcbyte;
806 DWORD i, x;
808 if (lines < 0 ) {
809 lines = -lines;
810 srcbits = srcbits + linebytes * (lines - 1);
811 linebytes = -linebytes;
814 if (left & 1) {
815 left--;
816 dstwidth++;
818 srcbits += left >> 1;
819 width = min(srcwidth, dstwidth);
821 /* ==== pal 4 dib -> any bmp format ==== */
822 for (h = lines-1; h >= 0; h--) {
823 srcbyte=srcbits;
824 for (i = width/2, x = left; i > 0; i--) {
825 BYTE srcval=*srcbyte++;
826 XPutPixel( bmpImage, x++, h, colors[srcval >> 4] );
827 XPutPixel( bmpImage, x++, h, colors[srcval & 0x0f] );
829 if (width & 1)
830 XPutPixel( bmpImage, x, h, colors[*srcbyte >> 4] );
831 srcbits += linebytes;
837 /***********************************************************************
838 * X11DRV_DIB_GetImageBits_4
840 * GetDIBits for a 4-bit deep DIB.
842 static void X11DRV_DIB_GetImageBits_4( int lines, BYTE *dstbits,
843 DWORD srcwidth, DWORD dstwidth,
844 RGBQUAD *colors, PALETTEENTRY *srccolors,
845 XImage *bmpImage, int linebytes )
847 DWORD x;
848 int h, width = min(srcwidth, dstwidth);
850 if (lines < 0 )
852 lines = -lines;
853 dstbits = dstbits + ( linebytes * (lines-1) );
854 linebytes = -linebytes;
857 switch (bmpImage->depth) {
858 case 1:
859 case 4:
860 if (X11DRV_DIB_CheckMask(bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask)
861 && srccolors) {
862 /* ==== pal 1 or 4 bmp -> pal 4 dib ==== */
863 BYTE* dstbyte;
865 for (h = lines-1; h >= 0; h--) {
866 BYTE dstval;
867 dstbyte=dstbits;
868 dstval=0;
869 for (x = 0; x < width; x++) {
870 PALETTEENTRY srcval;
871 srcval=srccolors[XGetPixel(bmpImage, x, h)];
872 dstval|=(X11DRV_DIB_GetNearestIndex
873 (colors, 16,
874 srcval.peRed,
875 srcval.peGreen,
876 srcval.peBlue) << (4-((x&1)<<2)));
877 if ((x&1)==1) {
878 *dstbyte++=dstval;
879 dstval=0;
882 if ((width&1)!=0) {
883 *dstbyte=dstval;
885 dstbits += linebytes;
887 } else {
888 goto notsupported;
890 break;
892 case 8:
893 if (X11DRV_DIB_CheckMask(bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask)
894 && srccolors) {
895 /* ==== pal 8 bmp -> pal 4 dib ==== */
896 const void* srcbits;
897 const BYTE *srcpixel;
898 BYTE* dstbyte;
900 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
901 for (h=0; h<lines; h++) {
902 BYTE dstval;
903 srcpixel=srcbits;
904 dstbyte=dstbits;
905 dstval=0;
906 for (x=0; x<width; x++) {
907 PALETTEENTRY srcval;
908 srcval = srccolors[*srcpixel++];
909 dstval|=(X11DRV_DIB_GetNearestIndex
910 (colors, 16,
911 srcval.peRed,
912 srcval.peGreen,
913 srcval.peBlue) << (4*(1-(x&1))) );
914 if ((x&1)==1) {
915 *dstbyte++=dstval;
916 dstval=0;
919 if ((width&1)!=0) {
920 *dstbyte=dstval;
922 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
923 dstbits += linebytes;
925 } else {
926 goto notsupported;
928 break;
930 case 15:
931 case 16:
933 const void* srcbits;
934 const WORD* srcpixel;
935 BYTE* dstbyte;
937 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
939 if (bmpImage->green_mask==0x03e0) {
940 if (bmpImage->red_mask==0x7c00) {
941 /* ==== rgb 555 bmp -> pal 4 dib ==== */
942 for (h=0; h<lines; h++) {
943 BYTE dstval;
944 srcpixel=srcbits;
945 dstbyte=dstbits;
946 dstval=0;
947 for (x=0; x<width; x++) {
948 WORD srcval;
949 srcval=*srcpixel++;
950 dstval|=(X11DRV_DIB_GetNearestIndex
951 (colors, 16,
952 ((srcval >> 7) & 0xf8) | /* r */
953 ((srcval >> 12) & 0x07),
954 ((srcval >> 2) & 0xf8) | /* g */
955 ((srcval >> 7) & 0x07),
956 ((srcval << 3) & 0xf8) | /* b */
957 ((srcval >> 2) & 0x07) ) << ((1-(x&1))<<2) );
958 if ((x&1)==1) {
959 *dstbyte++=dstval;
960 dstval=0;
963 if ((width&1)!=0) {
964 *dstbyte=dstval;
966 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
967 dstbits += linebytes;
969 } else if (bmpImage->blue_mask==0x7c00) {
970 /* ==== bgr 555 bmp -> pal 4 dib ==== */
971 for (h=0; h<lines; h++) {
972 WORD dstval;
973 srcpixel=srcbits;
974 dstbyte=dstbits;
975 dstval=0;
976 for (x=0; x<width; x++) {
977 WORD srcval;
978 srcval=*srcpixel++;
979 dstval|=(X11DRV_DIB_GetNearestIndex
980 (colors, 16,
981 ((srcval << 3) & 0xf8) | /* r */
982 ((srcval >> 2) & 0x07),
983 ((srcval >> 2) & 0xf8) | /* g */
984 ((srcval >> 7) & 0x07),
985 ((srcval >> 7) & 0xf8) | /* b */
986 ((srcval >> 12) & 0x07) ) << ((1-(x&1))<<2) );
987 if ((x&1)==1) {
988 *dstbyte++=dstval;
989 dstval=0;
992 if ((width&1)!=0) {
993 *dstbyte=dstval;
995 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
996 dstbits += linebytes;
998 } else {
999 goto notsupported;
1001 } else if (bmpImage->green_mask==0x07e0) {
1002 if (bmpImage->red_mask==0xf800) {
1003 /* ==== rgb 565 bmp -> pal 4 dib ==== */
1004 for (h=0; h<lines; h++) {
1005 BYTE dstval;
1006 srcpixel=srcbits;
1007 dstbyte=dstbits;
1008 dstval=0;
1009 for (x=0; x<width; x++) {
1010 WORD srcval;
1011 srcval=*srcpixel++;
1012 dstval|=(X11DRV_DIB_GetNearestIndex
1013 (colors, 16,
1014 ((srcval >> 8) & 0xf8) | /* r */
1015 ((srcval >> 13) & 0x07),
1016 ((srcval >> 3) & 0xfc) | /* g */
1017 ((srcval >> 9) & 0x03),
1018 ((srcval << 3) & 0xf8) | /* b */
1019 ((srcval >> 2) & 0x07) ) << ((1-(x&1))<<2) );
1020 if ((x&1)==1) {
1021 *dstbyte++=dstval;
1022 dstval=0;
1025 if ((width&1)!=0) {
1026 *dstbyte=dstval;
1028 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1029 dstbits += linebytes;
1031 } else if (bmpImage->blue_mask==0xf800) {
1032 /* ==== bgr 565 bmp -> pal 4 dib ==== */
1033 for (h=0; h<lines; h++) {
1034 WORD dstval;
1035 srcpixel=srcbits;
1036 dstbyte=dstbits;
1037 dstval=0;
1038 for (x=0; x<width; x++) {
1039 WORD srcval;
1040 srcval=*srcpixel++;
1041 dstval|=(X11DRV_DIB_GetNearestIndex
1042 (colors, 16,
1043 ((srcval << 3) & 0xf8) | /* r */
1044 ((srcval >> 2) & 0x07),
1045 ((srcval >> 3) & 0xfc) | /* g */
1046 ((srcval >> 9) & 0x03),
1047 ((srcval >> 8) & 0xf8) | /* b */
1048 ((srcval >> 13) & 0x07) ) << ((1-(x&1))<<2) );
1049 if ((x&1)==1) {
1050 *dstbyte++=dstval;
1051 dstval=0;
1054 if ((width&1)!=0) {
1055 *dstbyte=dstval;
1057 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1058 dstbits += linebytes;
1060 } else {
1061 goto notsupported;
1063 } else {
1064 goto notsupported;
1067 break;
1069 case 24:
1070 if (bmpImage->bits_per_pixel==24) {
1071 const void* srcbits;
1072 const BYTE *srcbyte;
1073 BYTE* dstbyte;
1075 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1077 if (bmpImage->green_mask!=0x00ff00 ||
1078 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
1079 goto notsupported;
1080 } else if (bmpImage->blue_mask==0xff) {
1081 /* ==== rgb 888 bmp -> pal 4 dib ==== */
1082 for (h=0; h<lines; h++) {
1083 srcbyte=srcbits;
1084 dstbyte=dstbits;
1085 for (x=0; x<width/2; x++) {
1086 /* Do 2 pixels at a time */
1087 *dstbyte++=(X11DRV_DIB_GetNearestIndex
1088 (colors, 16,
1089 srcbyte[2],
1090 srcbyte[1],
1091 srcbyte[0]) << 4) |
1092 X11DRV_DIB_GetNearestIndex
1093 (colors, 16,
1094 srcbyte[5],
1095 srcbyte[4],
1096 srcbyte[3]);
1097 srcbyte+=6;
1099 if (width&1) {
1100 /* And then the odd pixel */
1101 *dstbyte++=(X11DRV_DIB_GetNearestIndex
1102 (colors, 16,
1103 srcbyte[2],
1104 srcbyte[1],
1105 srcbyte[0]) << 4);
1107 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1108 dstbits += linebytes;
1110 } else {
1111 /* ==== bgr 888 bmp -> pal 4 dib ==== */
1112 for (h=0; h<lines; h++) {
1113 srcbyte=srcbits;
1114 dstbyte=dstbits;
1115 for (x=0; x<width/2; x++) {
1116 /* Do 2 pixels at a time */
1117 *dstbyte++=(X11DRV_DIB_GetNearestIndex
1118 (colors, 16,
1119 srcbyte[0],
1120 srcbyte[1],
1121 srcbyte[2]) << 4) |
1122 X11DRV_DIB_GetNearestIndex
1123 (colors, 16,
1124 srcbyte[3],
1125 srcbyte[4],
1126 srcbyte[5]);
1127 srcbyte+=6;
1129 if (width&1) {
1130 /* And then the odd pixel */
1131 *dstbyte++=(X11DRV_DIB_GetNearestIndex
1132 (colors, 16,
1133 srcbyte[0],
1134 srcbyte[1],
1135 srcbyte[2]) << 4);
1137 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1138 dstbits += linebytes;
1141 break;
1143 /* Fall through */
1145 case 32:
1147 const void* srcbits;
1148 const BYTE *srcbyte;
1149 BYTE* dstbyte;
1151 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1153 if (bmpImage->green_mask!=0x00ff00 ||
1154 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
1155 goto notsupported;
1156 } else if (bmpImage->blue_mask==0xff) {
1157 /* ==== rgb 0888 bmp -> pal 4 dib ==== */
1158 for (h=0; h<lines; h++) {
1159 srcbyte=srcbits;
1160 dstbyte=dstbits;
1161 for (x=0; x<width/2; x++) {
1162 /* Do 2 pixels at a time */
1163 *dstbyte++=(X11DRV_DIB_GetNearestIndex
1164 (colors, 16,
1165 srcbyte[2],
1166 srcbyte[1],
1167 srcbyte[0]) << 4) |
1168 X11DRV_DIB_GetNearestIndex
1169 (colors, 16,
1170 srcbyte[6],
1171 srcbyte[5],
1172 srcbyte[4]);
1173 srcbyte+=8;
1175 if (width&1) {
1176 /* And then the odd pixel */
1177 *dstbyte++=(X11DRV_DIB_GetNearestIndex
1178 (colors, 16,
1179 srcbyte[2],
1180 srcbyte[1],
1181 srcbyte[0]) << 4);
1183 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1184 dstbits += linebytes;
1186 } else {
1187 /* ==== bgr 0888 bmp -> pal 4 dib ==== */
1188 for (h=0; h<lines; h++) {
1189 srcbyte=srcbits;
1190 dstbyte=dstbits;
1191 for (x=0; x<width/2; x++) {
1192 /* Do 2 pixels at a time */
1193 *dstbyte++=(X11DRV_DIB_GetNearestIndex
1194 (colors, 16,
1195 srcbyte[0],
1196 srcbyte[1],
1197 srcbyte[2]) << 4) |
1198 X11DRV_DIB_GetNearestIndex
1199 (colors, 16,
1200 srcbyte[4],
1201 srcbyte[5],
1202 srcbyte[6]);
1203 srcbyte+=8;
1205 if (width&1) {
1206 /* And then the odd pixel */
1207 *dstbyte++=(X11DRV_DIB_GetNearestIndex
1208 (colors, 16,
1209 srcbyte[0],
1210 srcbyte[1],
1211 srcbyte[2]) << 4);
1213 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1214 dstbits += linebytes;
1218 break;
1220 default:
1221 notsupported:
1223 BYTE* dstbyte;
1225 /* ==== any bmp format -> pal 4 dib ==== */
1226 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 4 bit DIB\n",
1227 bmpImage->bits_per_pixel, bmpImage->red_mask,
1228 bmpImage->green_mask, bmpImage->blue_mask );
1229 for (h=lines-1; h>=0; h--) {
1230 dstbyte=dstbits;
1231 for (x=0; x<(width & ~1); x+=2) {
1232 *dstbyte++=(X11DRV_DIB_MapColor((int*)colors, 16, XGetPixel(bmpImage, x, h), 0) << 4) |
1233 X11DRV_DIB_MapColor((int*)colors, 16, XGetPixel(bmpImage, x+1, h), 0);
1235 if (width & 1) {
1236 *dstbyte=(X11DRV_DIB_MapColor((int *)colors, 16, XGetPixel(bmpImage, x, h), 0) << 4);
1238 dstbits += linebytes;
1241 break;
1245 /***********************************************************************
1246 * X11DRV_DIB_SetImageBits_RLE4
1248 * SetDIBits for a 4-bit deep compressed DIB.
1250 static void X11DRV_DIB_SetImageBits_RLE4( int lines, const BYTE *bits,
1251 DWORD srcwidth, DWORD dstwidth,
1252 int left, int *colors,
1253 XImage *bmpImage )
1255 unsigned int x = 0, width = min(srcwidth, dstwidth);
1256 int y = lines - 1, c, length;
1257 const BYTE *begin = bits;
1259 while (y >= 0)
1261 length = *bits++;
1262 if (length) { /* encoded */
1263 c = *bits++;
1264 while (length--) {
1265 if (x >= (left + width)) break;
1266 if( x >= left) XPutPixel(bmpImage, x, y, colors[c >> 4]);
1267 x++;
1268 if (!length--) break;
1269 if (x >= (left + width)) break;
1270 if( x >= left) XPutPixel(bmpImage, x, y, colors[c & 0xf]);
1271 x++;
1273 } else {
1274 length = *bits++;
1275 switch (length)
1277 case RLE_EOL:
1278 x = 0;
1279 y--;
1280 break;
1282 case RLE_END:
1283 return;
1285 case RLE_DELTA:
1286 x += *bits++;
1287 y -= *bits++;
1288 break;
1290 default: /* absolute */
1291 while (length--) {
1292 c = *bits++;
1293 if (x >= left && x < (left + width))
1294 XPutPixel(bmpImage, x, y, colors[c >> 4]);
1295 x++;
1296 if (!length--) break;
1297 if (x >= left && x < (left + width))
1298 XPutPixel(bmpImage, x, y, colors[c & 0xf]);
1299 x++;
1301 if ((bits - begin) & 1)
1302 bits++;
1310 /***********************************************************************
1311 * X11DRV_DIB_SetImageBits_8
1313 * SetDIBits for an 8-bit deep DIB.
1315 static void X11DRV_DIB_SetImageBits_8( int lines, const BYTE *srcbits,
1316 DWORD srcwidth, DWORD dstwidth, int left,
1317 const int *colors, XImage *bmpImage,
1318 int linebytes )
1320 DWORD x;
1321 int h, width = min(srcwidth, dstwidth);
1322 const BYTE* srcbyte;
1323 BYTE* dstbits;
1325 if (lines < 0 )
1327 lines = -lines;
1328 srcbits = srcbits + linebytes * (lines-1);
1329 linebytes = -linebytes;
1331 srcbits += left;
1332 srcbyte = srcbits;
1334 switch (bmpImage->depth) {
1335 case 15:
1336 case 16:
1337 /* Some X servers might have 32 bit/ 16bit deep pixel */
1338 if (lines && width && (bmpImage->bits_per_pixel == 16) &&
1339 (ImageByteOrder(gdi_display)==LSBFirst) )
1341 /* ==== pal 8 dib -> rgb or bgr 555 or 565 bmp ==== */
1342 dstbits=(BYTE*)bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
1343 for (h = lines ; h--; ) {
1344 #if defined(__i386__) && defined(__GNUC__)
1345 int _cl1,_cl2; /* temp outputs for asm below */
1346 /* Borrowed from DirectDraw */
1347 __asm__ __volatile__(
1348 "xor %%eax,%%eax\n"
1349 "cld\n"
1350 "1:\n"
1351 " lodsb\n"
1352 " movw (%%edx,%%eax,4),%%ax\n"
1353 " stosw\n"
1354 " xor %%eax,%%eax\n"
1355 " loop 1b\n"
1356 :"=S" (srcbyte), "=D" (_cl1), "=c" (_cl2)
1357 :"S" (srcbyte),
1358 "D" (dstbits),
1359 "c" (width),
1360 "d" (colors)
1361 :"eax", "cc", "memory"
1363 #else
1364 DWORD* dstpixel=(DWORD*)dstbits;
1365 for (x=0; x<width/2; x++) {
1366 /* Do 2 pixels at a time */
1367 *dstpixel++=(colors[srcbyte[1]] << 16) | colors[srcbyte[0]];
1368 srcbyte+=2;
1370 if (width&1) {
1371 /* And then the odd pixel */
1372 *((WORD*)dstpixel)=colors[srcbyte[0]];
1374 #endif
1375 srcbyte = (srcbits += linebytes);
1376 dstbits -= bmpImage->bytes_per_line;
1378 return;
1380 break;
1381 case 24:
1382 case 32:
1383 if (lines && width && (bmpImage->bits_per_pixel == 32) &&
1384 (ImageByteOrder(gdi_display)==LSBFirst) )
1386 dstbits=(BYTE*)bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
1387 /* ==== pal 8 dib -> rgb or bgr 0888 bmp ==== */
1388 for (h = lines ; h--; ) {
1389 #if defined(__i386__) && defined(__GNUC__)
1390 int _cl1,_cl2; /* temp outputs for asm below */
1391 /* Borrowed from DirectDraw */
1392 __asm__ __volatile__(
1393 "xor %%eax,%%eax\n"
1394 "cld\n"
1395 "1:\n"
1396 " lodsb\n"
1397 " movl (%%edx,%%eax,4),%%eax\n"
1398 " stosl\n"
1399 " xor %%eax,%%eax\n"
1400 " loop 1b\n"
1401 :"=S" (srcbyte), "=D" (_cl1), "=c" (_cl2)
1402 :"S" (srcbyte),
1403 "D" (dstbits),
1404 "c" (width),
1405 "d" (colors)
1406 :"eax", "cc", "memory"
1408 #else
1409 DWORD* dstpixel=(DWORD*)dstbits;
1410 for (x=0; x<width; x++) {
1411 *dstpixel++=colors[*srcbyte++];
1413 #endif
1414 srcbyte = (srcbits += linebytes);
1415 dstbits -= bmpImage->bytes_per_line;
1417 return;
1419 break;
1420 default:
1421 break; /* use slow generic case below */
1424 /* ==== pal 8 dib -> any bmp format ==== */
1425 for (h=lines-1; h>=0; h--) {
1426 for (x=left; x<width+left; x++) {
1427 XPutPixel(bmpImage, x, h, colors[*srcbyte++]);
1429 srcbyte = (srcbits += linebytes);
1433 /***********************************************************************
1434 * X11DRV_DIB_GetImageBits_8
1436 * GetDIBits for an 8-bit deep DIB.
1438 static void X11DRV_DIB_GetImageBits_8( int lines, BYTE *dstbits,
1439 DWORD srcwidth, DWORD dstwidth,
1440 RGBQUAD *colors, PALETTEENTRY *srccolors,
1441 XImage *bmpImage, int linebytes )
1443 DWORD x;
1444 int h, width = min(srcwidth, dstwidth);
1445 BYTE* dstbyte;
1447 if (lines < 0 )
1449 lines = -lines;
1450 dstbits = dstbits + ( linebytes * (lines-1) );
1451 linebytes = -linebytes;
1455 * Hack for now
1456 * This condition is true when GetImageBits has been called by
1457 * UpdateDIBSection. For now, GetNearestIndex is too slow to support
1458 * 256 colormaps, so we'll just use it for GetDIBits calls.
1459 * (In some cases, in an updateDIBSection, the returned colors are bad too)
1461 if (!srccolors) goto updatesection;
1463 switch (bmpImage->depth) {
1464 case 1:
1465 case 4:
1466 if (X11DRV_DIB_CheckMask(bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask)
1467 && srccolors) {
1469 /* ==== pal 1 bmp -> pal 8 dib ==== */
1470 /* ==== pal 4 bmp -> pal 8 dib ==== */
1471 for (h=lines-1; h>=0; h--) {
1472 dstbyte=dstbits;
1473 for (x=0; x<width; x++) {
1474 PALETTEENTRY srcval;
1475 srcval=srccolors[XGetPixel(bmpImage, x, h)];
1476 *dstbyte++=X11DRV_DIB_GetNearestIndex(colors, 256,
1477 srcval.peRed,
1478 srcval.peGreen,
1479 srcval.peBlue);
1481 dstbits += linebytes;
1483 } else {
1484 goto notsupported;
1486 break;
1488 case 8:
1489 if (X11DRV_DIB_CheckMask(bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask)
1490 && srccolors) {
1491 /* ==== pal 8 bmp -> pal 8 dib ==== */
1492 const void* srcbits;
1493 const BYTE* srcpixel;
1495 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1496 for (h=0; h<lines; h++) {
1497 srcpixel=srcbits;
1498 dstbyte=dstbits;
1499 for (x = 0; x < width; x++) {
1500 PALETTEENTRY srcval;
1501 srcval=srccolors[*srcpixel++];
1502 *dstbyte++=X11DRV_DIB_GetNearestIndex(colors, 256,
1503 srcval.peRed,
1504 srcval.peGreen,
1505 srcval.peBlue);
1507 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1508 dstbits += linebytes;
1510 } else {
1511 goto notsupported;
1513 break;
1515 case 15:
1516 case 16:
1518 const void* srcbits;
1519 const WORD* srcpixel;
1520 BYTE* dstbyte;
1522 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1524 if (bmpImage->green_mask==0x03e0) {
1525 if (bmpImage->red_mask==0x7c00) {
1526 /* ==== rgb 555 bmp -> pal 8 dib ==== */
1527 for (h=0; h<lines; h++) {
1528 srcpixel=srcbits;
1529 dstbyte=dstbits;
1530 for (x=0; x<width; x++) {
1531 WORD srcval;
1532 srcval=*srcpixel++;
1533 *dstbyte++=X11DRV_DIB_GetNearestIndex
1534 (colors, 256,
1535 ((srcval >> 7) & 0xf8) | /* r */
1536 ((srcval >> 12) & 0x07),
1537 ((srcval >> 2) & 0xf8) | /* g */
1538 ((srcval >> 7) & 0x07),
1539 ((srcval << 3) & 0xf8) | /* b */
1540 ((srcval >> 2) & 0x07) );
1542 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1543 dstbits += linebytes;
1545 } else if (bmpImage->blue_mask==0x7c00) {
1546 /* ==== bgr 555 bmp -> pal 8 dib ==== */
1547 for (h=0; h<lines; h++) {
1548 srcpixel=srcbits;
1549 dstbyte=dstbits;
1550 for (x=0; x<width; x++) {
1551 WORD srcval;
1552 srcval=*srcpixel++;
1553 *dstbyte++=X11DRV_DIB_GetNearestIndex
1554 (colors, 256,
1555 ((srcval << 3) & 0xf8) | /* r */
1556 ((srcval >> 2) & 0x07),
1557 ((srcval >> 2) & 0xf8) | /* g */
1558 ((srcval >> 7) & 0x07),
1559 ((srcval >> 7) & 0xf8) | /* b */
1560 ((srcval >> 12) & 0x07) );
1562 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1563 dstbits += linebytes;
1565 } else {
1566 goto notsupported;
1568 } else if (bmpImage->green_mask==0x07e0) {
1569 if (bmpImage->red_mask==0xf800) {
1570 /* ==== rgb 565 bmp -> pal 8 dib ==== */
1571 for (h=0; h<lines; h++) {
1572 srcpixel=srcbits;
1573 dstbyte=dstbits;
1574 for (x=0; x<width; x++) {
1575 WORD srcval;
1576 srcval=*srcpixel++;
1577 *dstbyte++=X11DRV_DIB_GetNearestIndex
1578 (colors, 256,
1579 ((srcval >> 8) & 0xf8) | /* r */
1580 ((srcval >> 13) & 0x07),
1581 ((srcval >> 3) & 0xfc) | /* g */
1582 ((srcval >> 9) & 0x03),
1583 ((srcval << 3) & 0xf8) | /* b */
1584 ((srcval >> 2) & 0x07) );
1586 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1587 dstbits += linebytes;
1589 } else if (bmpImage->blue_mask==0xf800) {
1590 /* ==== bgr 565 bmp -> pal 8 dib ==== */
1591 for (h=0; h<lines; h++) {
1592 srcpixel=srcbits;
1593 dstbyte=dstbits;
1594 for (x=0; x<width; x++) {
1595 WORD srcval;
1596 srcval=*srcpixel++;
1597 *dstbyte++=X11DRV_DIB_GetNearestIndex
1598 (colors, 256,
1599 ((srcval << 3) & 0xf8) | /* r */
1600 ((srcval >> 2) & 0x07),
1601 ((srcval >> 3) & 0xfc) | /* g */
1602 ((srcval >> 9) & 0x03),
1603 ((srcval >> 8) & 0xf8) | /* b */
1604 ((srcval >> 13) & 0x07) );
1606 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1607 dstbits += linebytes;
1609 } else {
1610 goto notsupported;
1612 } else {
1613 goto notsupported;
1616 break;
1618 case 24:
1619 case 32:
1621 const void* srcbits;
1622 const BYTE *srcbyte;
1623 BYTE* dstbyte;
1624 int bytes_per_pixel;
1626 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1627 bytes_per_pixel=(bmpImage->bits_per_pixel==24?3:4);
1629 if (bmpImage->green_mask!=0x00ff00 ||
1630 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
1631 goto notsupported;
1632 } else if (bmpImage->blue_mask==0xff) {
1633 /* ==== rgb 888 or 0888 bmp -> pal 8 dib ==== */
1634 for (h=0; h<lines; h++) {
1635 srcbyte=srcbits;
1636 dstbyte=dstbits;
1637 for (x=0; x<width; x++) {
1638 *dstbyte++=X11DRV_DIB_GetNearestIndex
1639 (colors, 256,
1640 srcbyte[2],
1641 srcbyte[1],
1642 srcbyte[0]);
1643 srcbyte+=bytes_per_pixel;
1645 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1646 dstbits += linebytes;
1648 } else {
1649 /* ==== bgr 888 or 0888 bmp -> pal 8 dib ==== */
1650 for (h=0; h<lines; h++) {
1651 srcbyte=srcbits;
1652 dstbyte=dstbits;
1653 for (x=0; x<width; x++) {
1654 *dstbyte++=X11DRV_DIB_GetNearestIndex
1655 (colors, 256,
1656 srcbyte[0],
1657 srcbyte[1],
1658 srcbyte[2]);
1659 srcbyte+=bytes_per_pixel;
1661 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1662 dstbits += linebytes;
1666 break;
1668 default:
1669 notsupported:
1670 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 8 bit DIB\n",
1671 bmpImage->depth, bmpImage->red_mask,
1672 bmpImage->green_mask, bmpImage->blue_mask );
1673 updatesection:
1674 /* ==== any bmp format -> pal 8 dib ==== */
1675 for (h=lines-1; h>=0; h--) {
1676 dstbyte=dstbits;
1677 for (x=0; x<width; x++) {
1678 *dstbyte=X11DRV_DIB_MapColor
1679 ((int*)colors, 256,
1680 XGetPixel(bmpImage, x, h), *dstbyte);
1681 dstbyte++;
1683 dstbits += linebytes;
1685 break;
1689 /***********************************************************************
1690 * X11DRV_DIB_SetImageBits_RLE8
1692 * SetDIBits for an 8-bit deep compressed DIB.
1694 * This function rewritten 941113 by James Youngman. WINE blew out when I
1695 * first ran it because my desktop wallpaper is a (large) RLE8 bitmap.
1697 * This was because the algorithm assumed that all RLE8 bitmaps end with the
1698 * 'End of bitmap' escape code. This code is very much laxer in what it
1699 * allows to end the expansion. Possibly too lax. See the note by
1700 * case RleDelta. BTW, MS's documentation implies that a correct RLE8
1701 * bitmap should end with RleEnd, but on the other hand, software exists
1702 * that produces ones that don't and Windows 3.1 doesn't complain a bit
1703 * about it.
1705 * (No) apologies for my English spelling. [Emacs users: c-indent-level=4].
1706 * James A. Youngman <mbcstjy@afs.man.ac.uk>
1707 * [JAY]
1709 static void X11DRV_DIB_SetImageBits_RLE8( int lines, const BYTE *bits,
1710 DWORD srcwidth, DWORD dstwidth,
1711 int left, int *colors,
1712 XImage *bmpImage )
1714 unsigned int x; /* X-position on each line. Increases. */
1715 int y; /* Line #. Starts at lines-1, decreases */
1716 const BYTE *pIn = bits; /* Pointer to current position in bits */
1717 BYTE length; /* The length pf a run */
1718 BYTE escape_code; /* See enum Rle8_EscapeCodes.*/
1721 * Note that the bitmap data is stored by Windows starting at the
1722 * bottom line of the bitmap and going upwards. Within each line,
1723 * the data is stored left-to-right. That's the reason why line
1724 * goes from lines-1 to 0. [JAY]
1727 x = 0;
1728 y = lines - 1;
1729 while (y >= 0)
1731 length = *pIn++;
1734 * If the length byte is not zero (which is the escape value),
1735 * We have a run of length pixels all the same colour. The colour
1736 * index is stored next.
1738 * If the length byte is zero, we need to read the next byte to
1739 * know what to do. [JAY]
1741 if (length != 0)
1744 * [Run-Length] Encoded mode
1746 int color = colors[*pIn++];
1747 while (length-- && x < (left + dstwidth)) {
1748 if( x >= left) XPutPixel(bmpImage, x, y, color);
1749 x++;
1752 else
1755 * Escape codes (may be an absolute sequence though)
1757 escape_code = (*pIn++);
1758 switch(escape_code)
1760 case RLE_EOL:
1761 x = 0;
1762 y--;
1763 break;
1765 case RLE_END:
1766 /* Not all RLE8 bitmaps end with this code. For
1767 * example, Paint Shop Pro produces some that don't.
1768 * That's (I think) what caused the previous
1769 * implementation to fail. [JAY]
1771 return;
1773 case RLE_DELTA:
1774 x += (*pIn++);
1775 y -= (*pIn++);
1776 break;
1778 default: /* switch to absolute mode */
1779 length = escape_code;
1780 while (length--)
1782 int color = colors[*pIn++];
1783 if (x >= (left + dstwidth))
1785 pIn += length;
1786 break;
1788 if( x >= left) XPutPixel(bmpImage, x, y, color);
1789 x++;
1792 * If you think for a moment you'll realise that the
1793 * only time we could ever possibly read an odd
1794 * number of bytes is when there is a 0x00 (escape),
1795 * a value >0x02 (absolute mode) and then an odd-
1796 * length run. Therefore this is the only place we
1797 * need to worry about it. Everywhere else the
1798 * bytes are always read in pairs. [JAY]
1800 if (escape_code & 1) pIn++; /* Throw away the pad byte. */
1801 break;
1802 } /* switch (escape_code) : Escape sequence */
1808 /***********************************************************************
1809 * X11DRV_DIB_SetImageBits_16
1811 * SetDIBits for a 16-bit deep DIB.
1813 static void X11DRV_DIB_SetImageBits_16( int lines, const BYTE *srcbits,
1814 DWORD srcwidth, DWORD dstwidth, int left,
1815 X11DRV_PDEVICE *physDev, DWORD rSrc, DWORD gSrc, DWORD bSrc,
1816 XImage *bmpImage, int linebytes )
1818 DWORD x;
1819 int h, width = min(srcwidth, dstwidth);
1820 const dib_conversions *convs = (bmpImage->byte_order == LSBFirst) ? &dib_normal : &dib_dst_byteswap;
1822 if (lines < 0 )
1824 lines = -lines;
1825 srcbits = srcbits + ( linebytes * (lines-1));
1826 linebytes = -linebytes;
1829 switch (bmpImage->depth)
1831 case 15:
1832 case 16:
1834 char* dstbits;
1836 srcbits=srcbits+left*2;
1837 dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
1839 if (bmpImage->green_mask==0x03e0) {
1840 if (gSrc==bmpImage->green_mask) {
1841 if (rSrc==bmpImage->red_mask) {
1842 /* ==== rgb 555 dib -> rgb 555 bmp ==== */
1843 /* ==== bgr 555 dib -> bgr 555 bmp ==== */
1844 convs->Convert_5x5_asis
1845 (width,lines,
1846 srcbits,linebytes,
1847 dstbits,-bmpImage->bytes_per_line);
1848 } else if (rSrc==bmpImage->blue_mask) {
1849 /* ==== rgb 555 dib -> bgr 555 bmp ==== */
1850 /* ==== bgr 555 dib -> rgb 555 bmp ==== */
1851 convs->Convert_555_reverse
1852 (width,lines,
1853 srcbits,linebytes,
1854 dstbits,-bmpImage->bytes_per_line);
1856 } else {
1857 if (rSrc==bmpImage->red_mask || bSrc==bmpImage->blue_mask) {
1858 /* ==== rgb 565 dib -> rgb 555 bmp ==== */
1859 /* ==== bgr 565 dib -> bgr 555 bmp ==== */
1860 convs->Convert_565_to_555_asis
1861 (width,lines,
1862 srcbits,linebytes,
1863 dstbits,-bmpImage->bytes_per_line);
1864 } else {
1865 /* ==== rgb 565 dib -> bgr 555 bmp ==== */
1866 /* ==== bgr 565 dib -> rgb 555 bmp ==== */
1867 convs->Convert_565_to_555_reverse
1868 (width,lines,
1869 srcbits,linebytes,
1870 dstbits,-bmpImage->bytes_per_line);
1873 } else if (bmpImage->green_mask==0x07e0) {
1874 if (gSrc==bmpImage->green_mask) {
1875 if (rSrc==bmpImage->red_mask) {
1876 /* ==== rgb 565 dib -> rgb 565 bmp ==== */
1877 /* ==== bgr 565 dib -> bgr 565 bmp ==== */
1878 convs->Convert_5x5_asis
1879 (width,lines,
1880 srcbits,linebytes,
1881 dstbits,-bmpImage->bytes_per_line);
1882 } else {
1883 /* ==== rgb 565 dib -> bgr 565 bmp ==== */
1884 /* ==== bgr 565 dib -> rgb 565 bmp ==== */
1885 convs->Convert_565_reverse
1886 (width,lines,
1887 srcbits,linebytes,
1888 dstbits,-bmpImage->bytes_per_line);
1890 } else {
1891 if (rSrc==bmpImage->red_mask || bSrc==bmpImage->blue_mask) {
1892 /* ==== rgb 555 dib -> rgb 565 bmp ==== */
1893 /* ==== bgr 555 dib -> bgr 565 bmp ==== */
1894 convs->Convert_555_to_565_asis
1895 (width,lines,
1896 srcbits,linebytes,
1897 dstbits,-bmpImage->bytes_per_line);
1898 } else {
1899 /* ==== rgb 555 dib -> bgr 565 bmp ==== */
1900 /* ==== bgr 555 dib -> rgb 565 bmp ==== */
1901 convs->Convert_555_to_565_reverse
1902 (width,lines,
1903 srcbits,linebytes,
1904 dstbits,-bmpImage->bytes_per_line);
1907 } else {
1908 goto notsupported;
1911 break;
1913 case 24:
1914 if (bmpImage->bits_per_pixel==24) {
1915 char* dstbits;
1917 srcbits=srcbits+left*2;
1918 dstbits=bmpImage->data+left*3+(lines-1)*bmpImage->bytes_per_line;
1920 if (bmpImage->green_mask!=0x00ff00 ||
1921 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
1922 goto notsupported;
1923 } else if ((rSrc==0x1f && bmpImage->red_mask==0xff) ||
1924 (bSrc==0x1f && bmpImage->blue_mask==0xff)) {
1925 if (gSrc==0x03e0) {
1926 /* ==== rgb 555 dib -> rgb 888 bmp ==== */
1927 /* ==== bgr 555 dib -> bgr 888 bmp ==== */
1928 convs->Convert_555_to_888_asis
1929 (width,lines,
1930 srcbits,linebytes,
1931 dstbits,-bmpImage->bytes_per_line);
1932 } else {
1933 /* ==== rgb 565 dib -> rgb 888 bmp ==== */
1934 /* ==== bgr 565 dib -> bgr 888 bmp ==== */
1935 convs->Convert_565_to_888_asis
1936 (width,lines,
1937 srcbits,linebytes,
1938 dstbits,-bmpImage->bytes_per_line);
1940 } else {
1941 if (gSrc==0x03e0) {
1942 /* ==== rgb 555 dib -> bgr 888 bmp ==== */
1943 /* ==== bgr 555 dib -> rgb 888 bmp ==== */
1944 convs->Convert_555_to_888_reverse
1945 (width,lines,
1946 srcbits,linebytes,
1947 dstbits,-bmpImage->bytes_per_line);
1948 } else {
1949 /* ==== rgb 565 dib -> bgr 888 bmp ==== */
1950 /* ==== bgr 565 dib -> rgb 888 bmp ==== */
1951 convs->Convert_565_to_888_reverse
1952 (width,lines,
1953 srcbits,linebytes,
1954 dstbits,-bmpImage->bytes_per_line);
1957 break;
1959 /* Fall through */
1961 case 32:
1963 char* dstbits;
1965 srcbits=srcbits+left*2;
1966 dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
1968 if (bmpImage->green_mask!=0x00ff00 ||
1969 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
1970 goto notsupported;
1971 } else if ((rSrc==0x1f && bmpImage->red_mask==0xff) ||
1972 (bSrc==0x1f && bmpImage->blue_mask==0xff)) {
1973 if (gSrc==0x03e0) {
1974 /* ==== rgb 555 dib -> rgb 0888 bmp ==== */
1975 /* ==== bgr 555 dib -> bgr 0888 bmp ==== */
1976 convs->Convert_555_to_0888_asis
1977 (width,lines,
1978 srcbits,linebytes,
1979 dstbits,-bmpImage->bytes_per_line);
1980 } else {
1981 /* ==== rgb 565 dib -> rgb 0888 bmp ==== */
1982 /* ==== bgr 565 dib -> bgr 0888 bmp ==== */
1983 convs->Convert_565_to_0888_asis
1984 (width,lines,
1985 srcbits,linebytes,
1986 dstbits,-bmpImage->bytes_per_line);
1988 } else {
1989 if (gSrc==0x03e0) {
1990 /* ==== rgb 555 dib -> bgr 0888 bmp ==== */
1991 /* ==== bgr 555 dib -> rgb 0888 bmp ==== */
1992 convs->Convert_555_to_0888_reverse
1993 (width,lines,
1994 srcbits,linebytes,
1995 dstbits,-bmpImage->bytes_per_line);
1996 } else {
1997 /* ==== rgb 565 dib -> bgr 0888 bmp ==== */
1998 /* ==== bgr 565 dib -> rgb 0888 bmp ==== */
1999 convs->Convert_565_to_0888_reverse
2000 (width,lines,
2001 srcbits,linebytes,
2002 dstbits,-bmpImage->bytes_per_line);
2006 break;
2008 default:
2009 notsupported:
2010 WARN("from 16 bit DIB (%x,%x,%x) to unknown %d bit bitmap (%lx,%lx,%lx)\n",
2011 rSrc, gSrc, bSrc, bmpImage->bits_per_pixel, bmpImage->red_mask,
2012 bmpImage->green_mask, bmpImage->blue_mask );
2013 /* fall through */
2014 case 1:
2015 case 4:
2016 case 8:
2018 /* ==== rgb or bgr 555 or 565 dib -> pal 1, 4 or 8 ==== */
2019 const WORD* srcpixel;
2020 int rShift1,gShift1,bShift1;
2021 int rShift2,gShift2,bShift2;
2022 BYTE gMask1,gMask2;
2024 /* Set color scaling values */
2025 rShift1=16+X11DRV_DIB_MaskToShift(rSrc)-3;
2026 gShift1=16+X11DRV_DIB_MaskToShift(gSrc)-3;
2027 bShift1=16+X11DRV_DIB_MaskToShift(bSrc)-3;
2028 rShift2=rShift1+5;
2029 gShift2=gShift1+5;
2030 bShift2=bShift1+5;
2031 if (gSrc==0x03e0) {
2032 /* Green has 5 bits, like the others */
2033 gMask1=0xf8;
2034 gMask2=0x07;
2035 } else {
2036 /* Green has 6 bits, not 5. Compensate. */
2037 gShift1++;
2038 gShift2+=2;
2039 gMask1=0xfc;
2040 gMask2=0x03;
2043 srcbits+=2*left;
2045 /* We could split it into four separate cases to optimize
2046 * but it is probably not worth it.
2048 for (h=lines-1; h>=0; h--) {
2049 srcpixel=(const WORD*)srcbits;
2050 for (x=left; x<width+left; x++) {
2051 DWORD srcval;
2052 BYTE red,green,blue;
2053 srcval=*srcpixel++ << 16;
2054 red= ((srcval >> rShift1) & 0xf8) |
2055 ((srcval >> rShift2) & 0x07);
2056 green=((srcval >> gShift1) & gMask1) |
2057 ((srcval >> gShift2) & gMask2);
2058 blue= ((srcval >> bShift1) & 0xf8) |
2059 ((srcval >> bShift2) & 0x07);
2060 XPutPixel(bmpImage, x, h,
2061 X11DRV_PALETTE_ToPhysical
2062 (physDev, RGB(red,green,blue)));
2064 srcbits += linebytes;
2067 break;
2072 /***********************************************************************
2073 * X11DRV_DIB_GetImageBits_16
2075 * GetDIBits for an 16-bit deep DIB.
2077 static void X11DRV_DIB_GetImageBits_16( X11DRV_PDEVICE *physDev, int lines, BYTE *dstbits,
2078 DWORD dstwidth, DWORD srcwidth,
2079 PALETTEENTRY *srccolors,
2080 DWORD rDst, DWORD gDst, DWORD bDst,
2081 XImage *bmpImage, int linebytes )
2083 DWORD x;
2084 int h, width = min(srcwidth, dstwidth);
2085 const dib_conversions *convs = (bmpImage->byte_order == LSBFirst) ? &dib_normal : &dib_src_byteswap;
2087 if (lines < 0 )
2089 lines = -lines;
2090 dstbits = dstbits + ( linebytes * (lines-1));
2091 linebytes = -linebytes;
2094 switch (bmpImage->depth)
2096 case 15:
2097 case 16:
2099 const char* srcbits;
2101 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2103 if (bmpImage->green_mask==0x03e0) {
2104 if (gDst==bmpImage->green_mask) {
2105 if (rDst==bmpImage->red_mask) {
2106 /* ==== rgb 555 bmp -> rgb 555 dib ==== */
2107 /* ==== bgr 555 bmp -> bgr 555 dib ==== */
2108 convs->Convert_5x5_asis
2109 (width,lines,
2110 srcbits,-bmpImage->bytes_per_line,
2111 dstbits,linebytes);
2112 } else {
2113 /* ==== rgb 555 bmp -> bgr 555 dib ==== */
2114 /* ==== bgr 555 bmp -> rgb 555 dib ==== */
2115 convs->Convert_555_reverse
2116 (width,lines,
2117 srcbits,-bmpImage->bytes_per_line,
2118 dstbits,linebytes);
2120 } else {
2121 if (rDst==bmpImage->red_mask || bDst==bmpImage->blue_mask) {
2122 /* ==== rgb 555 bmp -> rgb 565 dib ==== */
2123 /* ==== bgr 555 bmp -> bgr 565 dib ==== */
2124 convs->Convert_555_to_565_asis
2125 (width,lines,
2126 srcbits,-bmpImage->bytes_per_line,
2127 dstbits,linebytes);
2128 } else {
2129 /* ==== rgb 555 bmp -> bgr 565 dib ==== */
2130 /* ==== bgr 555 bmp -> rgb 565 dib ==== */
2131 convs->Convert_555_to_565_reverse
2132 (width,lines,
2133 srcbits,-bmpImage->bytes_per_line,
2134 dstbits,linebytes);
2137 } else if (bmpImage->green_mask==0x07e0) {
2138 if (gDst==bmpImage->green_mask) {
2139 if (rDst == bmpImage->red_mask) {
2140 /* ==== rgb 565 bmp -> rgb 565 dib ==== */
2141 /* ==== bgr 565 bmp -> bgr 565 dib ==== */
2142 convs->Convert_5x5_asis
2143 (width,lines,
2144 srcbits,-bmpImage->bytes_per_line,
2145 dstbits,linebytes);
2146 } else {
2147 /* ==== rgb 565 bmp -> bgr 565 dib ==== */
2148 /* ==== bgr 565 bmp -> rgb 565 dib ==== */
2149 convs->Convert_565_reverse
2150 (width,lines,
2151 srcbits,-bmpImage->bytes_per_line,
2152 dstbits,linebytes);
2154 } else {
2155 if (rDst==bmpImage->red_mask || bDst==bmpImage->blue_mask) {
2156 /* ==== rgb 565 bmp -> rgb 555 dib ==== */
2157 /* ==== bgr 565 bmp -> bgr 555 dib ==== */
2158 convs->Convert_565_to_555_asis
2159 (width,lines,
2160 srcbits,-bmpImage->bytes_per_line,
2161 dstbits,linebytes);
2162 } else {
2163 /* ==== rgb 565 bmp -> bgr 555 dib ==== */
2164 /* ==== bgr 565 bmp -> rgb 555 dib ==== */
2165 convs->Convert_565_to_555_reverse
2166 (width,lines,
2167 srcbits,-bmpImage->bytes_per_line,
2168 dstbits,linebytes);
2171 } else {
2172 goto notsupported;
2175 break;
2177 case 24:
2178 if (bmpImage->bits_per_pixel == 24) {
2179 const char* srcbits;
2181 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2183 if (bmpImage->green_mask!=0x00ff00 ||
2184 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2185 goto notsupported;
2186 } else if ((rDst==0x1f && bmpImage->red_mask==0xff) ||
2187 (bDst==0x1f && bmpImage->blue_mask==0xff)) {
2188 if (gDst==0x03e0) {
2189 /* ==== rgb 888 bmp -> rgb 555 dib ==== */
2190 /* ==== bgr 888 bmp -> bgr 555 dib ==== */
2191 convs->Convert_888_to_555_asis
2192 (width,lines,
2193 srcbits,-bmpImage->bytes_per_line,
2194 dstbits,linebytes);
2195 } else {
2196 /* ==== rgb 888 bmp -> rgb 565 dib ==== */
2197 /* ==== rgb 888 bmp -> rgb 565 dib ==== */
2198 convs->Convert_888_to_565_asis
2199 (width,lines,
2200 srcbits,-bmpImage->bytes_per_line,
2201 dstbits,linebytes);
2203 } else {
2204 if (gDst==0x03e0) {
2205 /* ==== rgb 888 bmp -> bgr 555 dib ==== */
2206 /* ==== bgr 888 bmp -> rgb 555 dib ==== */
2207 convs->Convert_888_to_555_reverse
2208 (width,lines,
2209 srcbits,-bmpImage->bytes_per_line,
2210 dstbits,linebytes);
2211 } else {
2212 /* ==== rgb 888 bmp -> bgr 565 dib ==== */
2213 /* ==== bgr 888 bmp -> rgb 565 dib ==== */
2214 convs->Convert_888_to_565_reverse
2215 (width,lines,
2216 srcbits,-bmpImage->bytes_per_line,
2217 dstbits,linebytes);
2220 break;
2222 /* Fall through */
2224 case 32:
2226 const char* srcbits;
2228 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2230 if (bmpImage->green_mask!=0x00ff00 ||
2231 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2232 goto notsupported;
2233 } else if ((rDst==0x1f && bmpImage->red_mask==0xff) ||
2234 (bDst==0x1f && bmpImage->blue_mask==0xff)) {
2235 if (gDst==0x03e0) {
2236 /* ==== rgb 0888 bmp -> rgb 555 dib ==== */
2237 /* ==== bgr 0888 bmp -> bgr 555 dib ==== */
2238 convs->Convert_0888_to_555_asis
2239 (width,lines,
2240 srcbits,-bmpImage->bytes_per_line,
2241 dstbits,linebytes);
2242 } else {
2243 /* ==== rgb 0888 bmp -> rgb 565 dib ==== */
2244 /* ==== bgr 0888 bmp -> bgr 565 dib ==== */
2245 convs->Convert_0888_to_565_asis
2246 (width,lines,
2247 srcbits,-bmpImage->bytes_per_line,
2248 dstbits,linebytes);
2250 } else {
2251 if (gDst==0x03e0) {
2252 /* ==== rgb 0888 bmp -> bgr 555 dib ==== */
2253 /* ==== bgr 0888 bmp -> rgb 555 dib ==== */
2254 convs->Convert_0888_to_555_reverse
2255 (width,lines,
2256 srcbits,-bmpImage->bytes_per_line,
2257 dstbits,linebytes);
2258 } else {
2259 /* ==== rgb 0888 bmp -> bgr 565 dib ==== */
2260 /* ==== bgr 0888 bmp -> rgb 565 dib ==== */
2261 convs->Convert_0888_to_565_reverse
2262 (width,lines,
2263 srcbits,-bmpImage->bytes_per_line,
2264 dstbits,linebytes);
2268 break;
2270 case 1:
2271 case 4:
2272 if (X11DRV_DIB_CheckMask(bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask)
2273 && srccolors) {
2274 /* ==== pal 1 or 4 bmp -> rgb or bgr 555 or 565 dib ==== */
2275 int rShift,gShift,bShift;
2276 WORD* dstpixel;
2278 /* Shift everything 16 bits left so that all shifts are >0,
2279 * even for BGR DIBs. Then a single >> 16 will bring everything
2280 * back into place.
2282 rShift=16+X11DRV_DIB_MaskToShift(rDst)-3;
2283 gShift=16+X11DRV_DIB_MaskToShift(gDst)-3;
2284 bShift=16+X11DRV_DIB_MaskToShift(bDst)-3;
2285 if (gDst==0x07e0) {
2286 /* 6 bits for the green */
2287 gShift++;
2289 rDst=rDst << 16;
2290 gDst=gDst << 16;
2291 bDst=bDst << 16;
2292 for (h = lines - 1; h >= 0; h--) {
2293 dstpixel=(LPWORD)dstbits;
2294 for (x = 0; x < width; x++) {
2295 PALETTEENTRY srcval;
2296 DWORD dstval;
2297 srcval=srccolors[XGetPixel(bmpImage, x, h)];
2298 dstval=((srcval.peRed << rShift) & rDst) |
2299 ((srcval.peGreen << gShift) & gDst) |
2300 ((srcval.peBlue << bShift) & bDst);
2301 *dstpixel++=dstval >> 16;
2303 dstbits += linebytes;
2305 } else {
2306 goto notsupported;
2308 break;
2310 case 8:
2311 if (X11DRV_DIB_CheckMask(bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask)
2312 && srccolors) {
2313 /* ==== pal 8 bmp -> rgb or bgr 555 or 565 dib ==== */
2314 int rShift,gShift,bShift;
2315 const BYTE* srcbits;
2316 const BYTE* srcpixel;
2317 WORD* dstpixel;
2319 /* Shift everything 16 bits left so that all shifts are >0,
2320 * even for BGR DIBs. Then a single >> 16 will bring everything
2321 * back into place.
2323 rShift=16+X11DRV_DIB_MaskToShift(rDst)-3;
2324 gShift=16+X11DRV_DIB_MaskToShift(gDst)-3;
2325 bShift=16+X11DRV_DIB_MaskToShift(bDst)-3;
2326 if (gDst==0x07e0) {
2327 /* 6 bits for the green */
2328 gShift++;
2330 rDst=rDst << 16;
2331 gDst=gDst << 16;
2332 bDst=bDst << 16;
2333 srcbits=(BYTE*)bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2334 for (h=0; h<lines; h++) {
2335 srcpixel=srcbits;
2336 dstpixel=(LPWORD)dstbits;
2337 for (x = 0; x < width; x++) {
2338 PALETTEENTRY srcval;
2339 DWORD dstval;
2340 srcval=srccolors[*srcpixel++];
2341 dstval=((srcval.peRed << rShift) & rDst) |
2342 ((srcval.peGreen << gShift) & gDst) |
2343 ((srcval.peBlue << bShift) & bDst);
2344 *dstpixel++=dstval >> 16;
2346 srcbits -= bmpImage->bytes_per_line;
2347 dstbits += linebytes;
2349 } else {
2350 goto notsupported;
2352 break;
2354 default:
2355 notsupported:
2357 /* ==== any bmp format -> rgb or bgr 555 or 565 dib ==== */
2358 int rShift,gShift,bShift;
2359 WORD* dstpixel;
2361 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 16 bit DIB (%x,%x,%x)\n",
2362 bmpImage->depth, bmpImage->red_mask,
2363 bmpImage->green_mask, bmpImage->blue_mask,
2364 rDst, gDst, bDst);
2366 /* Shift everything 16 bits left so that all shifts are >0,
2367 * even for BGR DIBs. Then a single >> 16 will bring everything
2368 * back into place.
2370 rShift=16+X11DRV_DIB_MaskToShift(rDst)-3;
2371 gShift=16+X11DRV_DIB_MaskToShift(gDst)-3;
2372 bShift=16+X11DRV_DIB_MaskToShift(bDst)-3;
2373 if (gDst==0x07e0) {
2374 /* 6 bits for the green */
2375 gShift++;
2377 rDst=rDst << 16;
2378 gDst=gDst << 16;
2379 bDst=bDst << 16;
2380 for (h = lines - 1; h >= 0; h--) {
2381 dstpixel=(LPWORD)dstbits;
2382 for (x = 0; x < width; x++) {
2383 COLORREF srcval;
2384 DWORD dstval;
2385 srcval=X11DRV_PALETTE_ToLogical(physDev, XGetPixel(bmpImage, x, h));
2386 dstval=((GetRValue(srcval) << rShift) & rDst) |
2387 ((GetGValue(srcval) << gShift) & gDst) |
2388 ((GetBValue(srcval) << bShift) & bDst);
2389 *dstpixel++=dstval >> 16;
2391 dstbits += linebytes;
2394 break;
2399 /***********************************************************************
2400 * X11DRV_DIB_SetImageBits_24
2402 * SetDIBits for a 24-bit deep DIB.
2404 static void X11DRV_DIB_SetImageBits_24( int lines, const BYTE *srcbits,
2405 DWORD srcwidth, DWORD dstwidth, int left,
2406 X11DRV_PDEVICE *physDev,
2407 DWORD rSrc, DWORD gSrc, DWORD bSrc,
2408 XImage *bmpImage, DWORD linebytes )
2410 DWORD x;
2411 int h, width = min(srcwidth, dstwidth);
2412 const dib_conversions *convs = (bmpImage->byte_order == LSBFirst) ? &dib_normal : &dib_dst_byteswap;
2414 if (lines < 0 )
2416 lines = -lines;
2417 srcbits = srcbits + linebytes * (lines - 1);
2418 linebytes = -linebytes;
2421 switch (bmpImage->depth)
2423 case 24:
2424 if (bmpImage->bits_per_pixel==24) {
2425 char* dstbits;
2427 srcbits=srcbits+left*3;
2428 dstbits=bmpImage->data+left*3+(lines-1)*bmpImage->bytes_per_line;
2430 if (bmpImage->green_mask!=0x00ff00 ||
2431 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2432 goto notsupported;
2433 } else if (rSrc==bmpImage->red_mask) {
2434 /* ==== rgb 888 dib -> rgb 888 bmp ==== */
2435 /* ==== bgr 888 dib -> bgr 888 bmp ==== */
2436 convs->Convert_888_asis
2437 (width,lines,
2438 srcbits,linebytes,
2439 dstbits,-bmpImage->bytes_per_line);
2440 } else {
2441 /* ==== rgb 888 dib -> bgr 888 bmp ==== */
2442 /* ==== bgr 888 dib -> rgb 888 bmp ==== */
2443 convs->Convert_888_reverse
2444 (width,lines,
2445 srcbits,linebytes,
2446 dstbits,-bmpImage->bytes_per_line);
2448 break;
2450 /* fall through */
2452 case 32:
2454 char* dstbits;
2456 srcbits=srcbits+left*3;
2457 dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
2459 if (bmpImage->green_mask!=0x00ff00 ||
2460 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2461 goto notsupported;
2462 } else if (rSrc==bmpImage->red_mask) {
2463 /* ==== rgb 888 dib -> rgb 0888 bmp ==== */
2464 /* ==== bgr 888 dib -> bgr 0888 bmp ==== */
2465 convs->Convert_888_to_0888_asis
2466 (width,lines,
2467 srcbits,linebytes,
2468 dstbits,-bmpImage->bytes_per_line);
2469 } else {
2470 /* ==== rgb 888 dib -> bgr 0888 bmp ==== */
2471 /* ==== bgr 888 dib -> rgb 0888 bmp ==== */
2472 convs->Convert_888_to_0888_reverse
2473 (width,lines,
2474 srcbits,linebytes,
2475 dstbits,-bmpImage->bytes_per_line);
2477 break;
2480 case 15:
2481 case 16:
2483 char* dstbits;
2485 srcbits=srcbits+left*3;
2486 dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
2488 if (bmpImage->green_mask==0x03e0) {
2489 if ((rSrc==0xff0000 && bmpImage->red_mask==0x7f00) ||
2490 (bSrc==0xff0000 && bmpImage->blue_mask==0x7f00)) {
2491 /* ==== rgb 888 dib -> rgb 555 bmp ==== */
2492 /* ==== bgr 888 dib -> bgr 555 bmp ==== */
2493 convs->Convert_888_to_555_asis
2494 (width,lines,
2495 srcbits,linebytes,
2496 dstbits,-bmpImage->bytes_per_line);
2497 } else if ((rSrc==0xff && bmpImage->red_mask==0x7f00) ||
2498 (bSrc==0xff && bmpImage->blue_mask==0x7f00)) {
2499 /* ==== rgb 888 dib -> bgr 555 bmp ==== */
2500 /* ==== bgr 888 dib -> rgb 555 bmp ==== */
2501 convs->Convert_888_to_555_reverse
2502 (width,lines,
2503 srcbits,linebytes,
2504 dstbits,-bmpImage->bytes_per_line);
2505 } else {
2506 goto notsupported;
2508 } else if (bmpImage->green_mask==0x07e0) {
2509 if ((rSrc==0xff0000 && bmpImage->red_mask==0xf800) ||
2510 (bSrc==0xff0000 && bmpImage->blue_mask==0xf800)) {
2511 /* ==== rgb 888 dib -> rgb 565 bmp ==== */
2512 /* ==== bgr 888 dib -> bgr 565 bmp ==== */
2513 convs->Convert_888_to_565_asis
2514 (width,lines,
2515 srcbits,linebytes,
2516 dstbits,-bmpImage->bytes_per_line);
2517 } else if ((rSrc==0xff && bmpImage->red_mask==0xf800) ||
2518 (bSrc==0xff && bmpImage->blue_mask==0xf800)) {
2519 /* ==== rgb 888 dib -> bgr 565 bmp ==== */
2520 /* ==== bgr 888 dib -> rgb 565 bmp ==== */
2521 convs->Convert_888_to_565_reverse
2522 (width,lines,
2523 srcbits,linebytes,
2524 dstbits,-bmpImage->bytes_per_line);
2525 } else {
2526 goto notsupported;
2528 } else {
2529 goto notsupported;
2532 break;
2534 default:
2535 notsupported:
2536 WARN("from 24 bit DIB (%x,%x,%x) to unknown %d bit bitmap (%lx,%lx,%lx)\n",
2537 rSrc, gSrc, bSrc, bmpImage->bits_per_pixel, bmpImage->red_mask,
2538 bmpImage->green_mask, bmpImage->blue_mask );
2539 /* fall through */
2540 case 1:
2541 case 4:
2542 case 8:
2544 /* ==== rgb 888 dib -> any bmp format ==== */
2545 const BYTE* srcbyte;
2547 /* Windows only supports one 24bpp DIB format: RGB888 */
2548 srcbits+=left*3;
2549 for (h = lines - 1; h >= 0; h--) {
2550 srcbyte = srcbits;
2551 for (x = left; x < width+left; x++) {
2552 XPutPixel(bmpImage, x, h,
2553 X11DRV_PALETTE_ToPhysical
2554 (physDev, RGB(srcbyte[2], srcbyte[1], srcbyte[0])));
2555 srcbyte+=3;
2557 srcbits += linebytes;
2560 break;
2565 /***********************************************************************
2566 * X11DRV_DIB_GetImageBits_24
2568 * GetDIBits for an 24-bit deep DIB.
2570 static void X11DRV_DIB_GetImageBits_24( X11DRV_PDEVICE *physDev, int lines, BYTE *dstbits,
2571 DWORD dstwidth, DWORD srcwidth,
2572 PALETTEENTRY *srccolors,
2573 DWORD rDst, DWORD gDst, DWORD bDst,
2574 XImage *bmpImage, DWORD linebytes )
2576 DWORD x;
2577 int h, width = min(srcwidth, dstwidth);
2578 const dib_conversions *convs = (bmpImage->byte_order == LSBFirst) ? &dib_normal : &dib_src_byteswap;
2580 if (lines < 0 )
2582 lines = -lines;
2583 dstbits = dstbits + ( linebytes * (lines-1) );
2584 linebytes = -linebytes;
2587 switch (bmpImage->depth)
2589 case 24:
2590 if (bmpImage->bits_per_pixel==24) {
2591 const char* srcbits;
2593 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2595 if (bmpImage->green_mask!=0x00ff00 ||
2596 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2597 goto notsupported;
2598 } else if (rDst==bmpImage->red_mask) {
2599 /* ==== rgb 888 bmp -> rgb 888 dib ==== */
2600 /* ==== bgr 888 bmp -> bgr 888 dib ==== */
2601 convs->Convert_888_asis
2602 (width,lines,
2603 srcbits,-bmpImage->bytes_per_line,
2604 dstbits,linebytes);
2605 } else {
2606 /* ==== rgb 888 bmp -> bgr 888 dib ==== */
2607 /* ==== bgr 888 bmp -> rgb 888 dib ==== */
2608 convs->Convert_888_reverse
2609 (width,lines,
2610 srcbits,-bmpImage->bytes_per_line,
2611 dstbits,linebytes);
2613 break;
2615 /* fall through */
2617 case 32:
2619 const char* srcbits;
2621 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2623 if (bmpImage->green_mask!=0x00ff00 ||
2624 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2625 goto notsupported;
2626 } else if (rDst==bmpImage->red_mask) {
2627 /* ==== rgb 888 bmp -> rgb 0888 dib ==== */
2628 /* ==== bgr 888 bmp -> bgr 0888 dib ==== */
2629 convs->Convert_0888_to_888_asis
2630 (width,lines,
2631 srcbits,-bmpImage->bytes_per_line,
2632 dstbits,linebytes);
2633 } else {
2634 /* ==== rgb 888 bmp -> bgr 0888 dib ==== */
2635 /* ==== bgr 888 bmp -> rgb 0888 dib ==== */
2636 convs->Convert_0888_to_888_reverse
2637 (width,lines,
2638 srcbits,-bmpImage->bytes_per_line,
2639 dstbits,linebytes);
2641 break;
2644 case 15:
2645 case 16:
2647 const char* srcbits;
2649 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2651 if (bmpImage->green_mask==0x03e0) {
2652 if ((rDst==0xff0000 && bmpImage->red_mask==0x7f00) ||
2653 (bDst==0xff0000 && bmpImage->blue_mask==0x7f00)) {
2654 /* ==== rgb 555 bmp -> rgb 888 dib ==== */
2655 /* ==== bgr 555 bmp -> bgr 888 dib ==== */
2656 convs->Convert_555_to_888_asis
2657 (width,lines,
2658 srcbits,-bmpImage->bytes_per_line,
2659 dstbits,linebytes);
2660 } else if ((rDst==0xff && bmpImage->red_mask==0x7f00) ||
2661 (bDst==0xff && bmpImage->blue_mask==0x7f00)) {
2662 /* ==== rgb 555 bmp -> bgr 888 dib ==== */
2663 /* ==== bgr 555 bmp -> rgb 888 dib ==== */
2664 convs->Convert_555_to_888_reverse
2665 (width,lines,
2666 srcbits,-bmpImage->bytes_per_line,
2667 dstbits,linebytes);
2668 } else {
2669 goto notsupported;
2671 } else if (bmpImage->green_mask==0x07e0) {
2672 if ((rDst==0xff0000 && bmpImage->red_mask==0xf800) ||
2673 (bDst==0xff0000 && bmpImage->blue_mask==0xf800)) {
2674 /* ==== rgb 565 bmp -> rgb 888 dib ==== */
2675 /* ==== bgr 565 bmp -> bgr 888 dib ==== */
2676 convs->Convert_565_to_888_asis
2677 (width,lines,
2678 srcbits,-bmpImage->bytes_per_line,
2679 dstbits,linebytes);
2680 } else if ((rDst==0xff && bmpImage->red_mask==0xf800) ||
2681 (bDst==0xff && bmpImage->blue_mask==0xf800)) {
2682 /* ==== rgb 565 bmp -> bgr 888 dib ==== */
2683 /* ==== bgr 565 bmp -> rgb 888 dib ==== */
2684 convs->Convert_565_to_888_reverse
2685 (width,lines,
2686 srcbits,-bmpImage->bytes_per_line,
2687 dstbits,linebytes);
2688 } else {
2689 goto notsupported;
2691 } else {
2692 goto notsupported;
2695 break;
2697 case 1:
2698 case 4:
2699 if (X11DRV_DIB_CheckMask(bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask)
2700 && srccolors) {
2701 /* ==== pal 1 or 4 bmp -> rgb 888 dib ==== */
2702 BYTE* dstbyte;
2704 /* Windows only supports one 24bpp DIB format: rgb 888 */
2705 for (h = lines - 1; h >= 0; h--) {
2706 dstbyte=dstbits;
2707 for (x = 0; x < width; x++) {
2708 PALETTEENTRY srcval;
2709 srcval=srccolors[XGetPixel(bmpImage, x, h)];
2710 dstbyte[0]=srcval.peBlue;
2711 dstbyte[1]=srcval.peGreen;
2712 dstbyte[2]=srcval.peRed;
2713 dstbyte+=3;
2715 dstbits += linebytes;
2717 } else {
2718 goto notsupported;
2720 break;
2722 case 8:
2723 if (X11DRV_DIB_CheckMask(bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask)
2724 && srccolors) {
2725 /* ==== pal 8 bmp -> rgb 888 dib ==== */
2726 const void* srcbits;
2727 const BYTE* srcpixel;
2728 BYTE* dstbyte;
2730 /* Windows only supports one 24bpp DIB format: rgb 888 */
2731 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2732 for (h = lines - 1; h >= 0; h--) {
2733 srcpixel=srcbits;
2734 dstbyte=dstbits;
2735 for (x = 0; x < width; x++ ) {
2736 PALETTEENTRY srcval;
2737 srcval=srccolors[*srcpixel++];
2738 dstbyte[0]=srcval.peBlue;
2739 dstbyte[1]=srcval.peGreen;
2740 dstbyte[2]=srcval.peRed;
2741 dstbyte+=3;
2743 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
2744 dstbits += linebytes;
2746 } else {
2747 goto notsupported;
2749 break;
2751 default:
2752 notsupported:
2754 /* ==== any bmp format -> 888 dib ==== */
2755 BYTE* dstbyte;
2757 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 24 bit DIB (%x,%x,%x)\n",
2758 bmpImage->depth, bmpImage->red_mask,
2759 bmpImage->green_mask, bmpImage->blue_mask,
2760 rDst, gDst, bDst );
2762 /* Windows only supports one 24bpp DIB format: rgb 888 */
2763 for (h = lines - 1; h >= 0; h--) {
2764 dstbyte=dstbits;
2765 for (x = 0; x < width; x++) {
2766 COLORREF srcval=X11DRV_PALETTE_ToLogical
2767 (physDev, XGetPixel( bmpImage, x, h ));
2768 dstbyte[0]=GetBValue(srcval);
2769 dstbyte[1]=GetGValue(srcval);
2770 dstbyte[2]=GetRValue(srcval);
2771 dstbyte+=3;
2773 dstbits += linebytes;
2776 break;
2781 /***********************************************************************
2782 * X11DRV_DIB_SetImageBits_32
2784 * SetDIBits for a 32-bit deep DIB.
2786 static void X11DRV_DIB_SetImageBits_32(int lines, const BYTE *srcbits,
2787 DWORD srcwidth, DWORD dstwidth, int left,
2788 X11DRV_PDEVICE *physDev,
2789 DWORD rSrc, DWORD gSrc, DWORD bSrc,
2790 XImage *bmpImage,
2791 DWORD linebytes)
2793 DWORD x;
2794 int h, width = min(srcwidth, dstwidth);
2795 const dib_conversions *convs = (bmpImage->byte_order == LSBFirst) ? &dib_normal : &dib_dst_byteswap;
2797 if (lines < 0 )
2799 lines = -lines;
2800 srcbits = srcbits + ( linebytes * (lines-1) );
2801 linebytes = -linebytes;
2804 switch (bmpImage->depth)
2806 case 24:
2807 if (bmpImage->bits_per_pixel==24) {
2808 char* dstbits;
2810 srcbits=srcbits+left*4;
2811 dstbits=bmpImage->data+left*3+(lines-1)*bmpImage->bytes_per_line;
2813 if (rSrc==bmpImage->red_mask && gSrc==bmpImage->green_mask && bSrc==bmpImage->blue_mask) {
2814 /* ==== rgb 0888 dib -> rgb 888 bmp ==== */
2815 /* ==== bgr 0888 dib -> bgr 888 bmp ==== */
2816 convs->Convert_0888_to_888_asis
2817 (width,lines,
2818 srcbits,linebytes,
2819 dstbits,-bmpImage->bytes_per_line);
2820 } else if (bmpImage->green_mask!=0x00ff00 ||
2821 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2822 goto notsupported;
2823 /* the tests below assume sane bmpImage masks */
2824 } else if (rSrc==bmpImage->blue_mask && gSrc==bmpImage->green_mask && bSrc==bmpImage->red_mask) {
2825 /* ==== rgb 0888 dib -> bgr 888 bmp ==== */
2826 /* ==== bgr 0888 dib -> rgb 888 bmp ==== */
2827 convs->Convert_0888_to_888_reverse
2828 (width,lines,
2829 srcbits,linebytes,
2830 dstbits,-bmpImage->bytes_per_line);
2831 } else if (bmpImage->blue_mask==0xff) {
2832 /* ==== any 0888 dib -> rgb 888 bmp ==== */
2833 convs->Convert_any0888_to_rgb888
2834 (width,lines,
2835 srcbits,linebytes,
2836 rSrc,gSrc,bSrc,
2837 dstbits,-bmpImage->bytes_per_line);
2838 } else {
2839 /* ==== any 0888 dib -> bgr 888 bmp ==== */
2840 convs->Convert_any0888_to_bgr888
2841 (width,lines,
2842 srcbits,linebytes,
2843 rSrc,gSrc,bSrc,
2844 dstbits,-bmpImage->bytes_per_line);
2846 break;
2848 /* fall through */
2850 case 32:
2852 char* dstbits;
2854 srcbits=srcbits+left*4;
2855 dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
2857 if (gSrc==bmpImage->green_mask) {
2858 if (rSrc==bmpImage->red_mask && bSrc==bmpImage->blue_mask) {
2859 /* ==== rgb 0888 dib -> rgb 0888 bmp ==== */
2860 /* ==== bgr 0888 dib -> bgr 0888 bmp ==== */
2861 convs->Convert_0888_asis
2862 (width,lines,
2863 srcbits,linebytes,
2864 dstbits,-bmpImage->bytes_per_line);
2865 } else if (bmpImage->green_mask!=0x00ff00 ||
2866 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2867 goto notsupported;
2868 /* the tests below assume sane bmpImage masks */
2869 } else if (rSrc==bmpImage->blue_mask && bSrc==bmpImage->red_mask) {
2870 /* ==== rgb 0888 dib -> bgr 0888 bmp ==== */
2871 /* ==== bgr 0888 dib -> rgb 0888 bmp ==== */
2872 convs->Convert_0888_reverse
2873 (width,lines,
2874 srcbits,linebytes,
2875 dstbits,-bmpImage->bytes_per_line);
2876 } else {
2877 /* ==== any 0888 dib -> any 0888 bmp ==== */
2878 convs->Convert_0888_any
2879 (width,lines,
2880 srcbits,linebytes,
2881 rSrc,gSrc,bSrc,
2882 dstbits,-bmpImage->bytes_per_line,
2883 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
2885 } else if (bmpImage->green_mask!=0x00ff00 ||
2886 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2887 goto notsupported;
2888 /* the tests below assume sane bmpImage masks */
2889 } else {
2890 /* ==== any 0888 dib -> any 0888 bmp ==== */
2891 convs->Convert_0888_any
2892 (width,lines,
2893 srcbits,linebytes,
2894 rSrc,gSrc,bSrc,
2895 dstbits,-bmpImage->bytes_per_line,
2896 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
2899 break;
2901 case 15:
2902 case 16:
2904 char* dstbits;
2906 srcbits=srcbits+left*4;
2907 dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
2909 if (rSrc==0xff0000 && gSrc==0x00ff00 && bSrc==0x0000ff) {
2910 if (bmpImage->green_mask==0x03e0) {
2911 if (bmpImage->red_mask==0x7f00) {
2912 /* ==== rgb 0888 dib -> rgb 555 bmp ==== */
2913 convs->Convert_0888_to_555_asis
2914 (width,lines,
2915 srcbits,linebytes,
2916 dstbits,-bmpImage->bytes_per_line);
2917 } else if (bmpImage->blue_mask==0x7f00) {
2918 /* ==== rgb 0888 dib -> bgr 555 bmp ==== */
2919 convs->Convert_0888_to_555_reverse
2920 (width,lines,
2921 srcbits,linebytes,
2922 dstbits,-bmpImage->bytes_per_line);
2923 } else {
2924 goto notsupported;
2926 } else if (bmpImage->green_mask==0x07e0) {
2927 if (bmpImage->red_mask==0xf800) {
2928 /* ==== rgb 0888 dib -> rgb 565 bmp ==== */
2929 convs->Convert_0888_to_565_asis
2930 (width,lines,
2931 srcbits,linebytes,
2932 dstbits,-bmpImage->bytes_per_line);
2933 } else if (bmpImage->blue_mask==0xf800) {
2934 /* ==== rgb 0888 dib -> bgr 565 bmp ==== */
2935 convs->Convert_0888_to_565_reverse
2936 (width,lines,
2937 srcbits,linebytes,
2938 dstbits,-bmpImage->bytes_per_line);
2939 } else {
2940 goto notsupported;
2942 } else {
2943 goto notsupported;
2945 } else if (rSrc==0x0000ff && gSrc==0x00ff00 && bSrc==0xff0000) {
2946 if (bmpImage->green_mask==0x03e0) {
2947 if (bmpImage->blue_mask==0x7f00) {
2948 /* ==== bgr 0888 dib -> bgr 555 bmp ==== */
2949 convs->Convert_0888_to_555_asis
2950 (width,lines,
2951 srcbits,linebytes,
2952 dstbits,-bmpImage->bytes_per_line);
2953 } else if (bmpImage->red_mask==0x7f00) {
2954 /* ==== bgr 0888 dib -> rgb 555 bmp ==== */
2955 convs->Convert_0888_to_555_reverse
2956 (width,lines,
2957 srcbits,linebytes,
2958 dstbits,-bmpImage->bytes_per_line);
2959 } else {
2960 goto notsupported;
2962 } else if (bmpImage->green_mask==0x07e0) {
2963 if (bmpImage->blue_mask==0xf800) {
2964 /* ==== bgr 0888 dib -> bgr 565 bmp ==== */
2965 convs->Convert_0888_to_565_asis
2966 (width,lines,
2967 srcbits,linebytes,
2968 dstbits,-bmpImage->bytes_per_line);
2969 } else if (bmpImage->red_mask==0xf800) {
2970 /* ==== bgr 0888 dib -> rgb 565 bmp ==== */
2971 convs->Convert_0888_to_565_reverse
2972 (width,lines,
2973 srcbits,linebytes,
2974 dstbits,-bmpImage->bytes_per_line);
2975 } else {
2976 goto notsupported;
2978 } else {
2979 goto notsupported;
2981 } else {
2982 if (bmpImage->green_mask==0x03e0 &&
2983 (bmpImage->red_mask==0x7f00 ||
2984 bmpImage->blue_mask==0x7f00)) {
2985 /* ==== any 0888 dib -> rgb or bgr 555 bmp ==== */
2986 convs->Convert_any0888_to_5x5
2987 (width,lines,
2988 srcbits,linebytes,
2989 rSrc,gSrc,bSrc,
2990 dstbits,-bmpImage->bytes_per_line,
2991 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
2992 } else if (bmpImage->green_mask==0x07e0 &&
2993 (bmpImage->red_mask==0xf800 ||
2994 bmpImage->blue_mask==0xf800)) {
2995 /* ==== any 0888 dib -> rgb or bgr 565 bmp ==== */
2996 convs->Convert_any0888_to_5x5
2997 (width,lines,
2998 srcbits,linebytes,
2999 rSrc,gSrc,bSrc,
3000 dstbits,-bmpImage->bytes_per_line,
3001 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
3002 } else {
3003 goto notsupported;
3007 break;
3009 default:
3010 notsupported:
3011 WARN("from 32 bit DIB (%x,%x,%x) to unknown %d bit bitmap (%lx,%lx,%lx)\n",
3012 rSrc, gSrc, bSrc, bmpImage->bits_per_pixel, bmpImage->red_mask,
3013 bmpImage->green_mask, bmpImage->blue_mask );
3014 /* fall through */
3015 case 1:
3016 case 4:
3017 case 8:
3019 /* ==== any 0888 dib -> pal 1, 4 or 8 bmp ==== */
3020 const DWORD* srcpixel;
3021 int rShift,gShift,bShift;
3023 rShift=X11DRV_DIB_MaskToShift(rSrc);
3024 gShift=X11DRV_DIB_MaskToShift(gSrc);
3025 bShift=X11DRV_DIB_MaskToShift(bSrc);
3026 srcbits+=left*4;
3027 for (h = lines - 1; h >= 0; h--) {
3028 srcpixel=(const DWORD*)srcbits;
3029 for (x = left; x < width+left; x++) {
3030 DWORD srcvalue;
3031 BYTE red,green,blue;
3032 srcvalue=*srcpixel++;
3033 red= (srcvalue >> rShift) & 0xff;
3034 green=(srcvalue >> gShift) & 0xff;
3035 blue= (srcvalue >> bShift) & 0xff;
3036 XPutPixel(bmpImage, x, h, X11DRV_PALETTE_ToPhysical
3037 (physDev, RGB(red,green,blue)));
3039 srcbits += linebytes;
3042 break;
3047 /***********************************************************************
3048 * X11DRV_DIB_GetImageBits_32
3050 * GetDIBits for an 32-bit deep DIB.
3052 static void X11DRV_DIB_GetImageBits_32( X11DRV_PDEVICE *physDev, int lines, BYTE *dstbits,
3053 DWORD dstwidth, DWORD srcwidth,
3054 PALETTEENTRY *srccolors,
3055 DWORD rDst, DWORD gDst, DWORD bDst,
3056 XImage *bmpImage, int linebytes )
3058 DWORD x;
3059 int h, width = min(srcwidth, dstwidth);
3060 const dib_conversions *convs = (bmpImage->byte_order == LSBFirst) ? &dib_normal : &dib_src_byteswap;
3062 if (lines < 0 )
3064 lines = -lines;
3065 dstbits = dstbits + ( linebytes * (lines-1) );
3066 linebytes = -linebytes;
3069 switch (bmpImage->depth)
3071 case 24:
3072 if (bmpImage->bits_per_pixel==24) {
3073 const void* srcbits;
3075 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3077 if (rDst==bmpImage->red_mask && gDst==bmpImage->green_mask && bDst==bmpImage->blue_mask) {
3078 /* ==== rgb 888 bmp -> rgb 0888 dib ==== */
3079 /* ==== bgr 888 bmp -> bgr 0888 dib ==== */
3080 convs->Convert_888_to_0888_asis
3081 (width,lines,
3082 srcbits,-bmpImage->bytes_per_line,
3083 dstbits,linebytes);
3084 } else if (bmpImage->green_mask!=0x00ff00 ||
3085 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3086 goto notsupported;
3087 /* the tests below assume sane bmpImage masks */
3088 } else if (rDst==bmpImage->blue_mask && gDst==bmpImage->green_mask && bDst==bmpImage->red_mask) {
3089 /* ==== rgb 888 bmp -> bgr 0888 dib ==== */
3090 /* ==== bgr 888 bmp -> rgb 0888 dib ==== */
3091 convs->Convert_888_to_0888_reverse
3092 (width,lines,
3093 srcbits,-bmpImage->bytes_per_line,
3094 dstbits,linebytes);
3095 } else if (bmpImage->blue_mask==0xff) {
3096 /* ==== rgb 888 bmp -> any 0888 dib ==== */
3097 convs->Convert_rgb888_to_any0888
3098 (width,lines,
3099 srcbits,-bmpImage->bytes_per_line,
3100 dstbits,linebytes,
3101 rDst,gDst,bDst);
3102 } else {
3103 /* ==== bgr 888 bmp -> any 0888 dib ==== */
3104 convs->Convert_bgr888_to_any0888
3105 (width,lines,
3106 srcbits,-bmpImage->bytes_per_line,
3107 dstbits,linebytes,
3108 rDst,gDst,bDst);
3110 break;
3112 /* fall through */
3114 case 32:
3116 const char* srcbits;
3118 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3120 if (gDst==bmpImage->green_mask) {
3121 if (rDst==bmpImage->red_mask && bDst==bmpImage->blue_mask) {
3122 /* ==== rgb 0888 bmp -> rgb 0888 dib ==== */
3123 /* ==== bgr 0888 bmp -> bgr 0888 dib ==== */
3124 convs->Convert_0888_asis
3125 (width,lines,
3126 srcbits,-bmpImage->bytes_per_line,
3127 dstbits,linebytes);
3128 } else if (bmpImage->green_mask!=0x00ff00 ||
3129 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3130 goto notsupported;
3131 /* the tests below assume sane bmpImage masks */
3132 } else if (rDst==bmpImage->blue_mask && bDst==bmpImage->red_mask) {
3133 /* ==== rgb 0888 bmp -> bgr 0888 dib ==== */
3134 /* ==== bgr 0888 bmp -> rgb 0888 dib ==== */
3135 convs->Convert_0888_reverse
3136 (width,lines,
3137 srcbits,-bmpImage->bytes_per_line,
3138 dstbits,linebytes);
3139 } else {
3140 /* ==== any 0888 bmp -> any 0888 dib ==== */
3141 convs->Convert_0888_any
3142 (width,lines,
3143 srcbits,-bmpImage->bytes_per_line,
3144 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
3145 dstbits,linebytes,
3146 rDst,gDst,bDst);
3148 } else if (bmpImage->green_mask!=0x00ff00 ||
3149 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3150 goto notsupported;
3151 /* the tests below assume sane bmpImage masks */
3152 } else {
3153 /* ==== any 0888 bmp -> any 0888 dib ==== */
3154 convs->Convert_0888_any
3155 (width,lines,
3156 srcbits,-bmpImage->bytes_per_line,
3157 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
3158 dstbits,linebytes,
3159 rDst,gDst,bDst);
3162 break;
3164 case 15:
3165 case 16:
3167 const char* srcbits;
3169 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3171 if (rDst==0xff0000 && gDst==0x00ff00 && bDst==0x0000ff) {
3172 if (bmpImage->green_mask==0x03e0) {
3173 if (bmpImage->red_mask==0x7f00) {
3174 /* ==== rgb 555 bmp -> rgb 0888 dib ==== */
3175 convs->Convert_555_to_0888_asis
3176 (width,lines,
3177 srcbits,-bmpImage->bytes_per_line,
3178 dstbits,linebytes);
3179 } else if (bmpImage->blue_mask==0x7f00) {
3180 /* ==== bgr 555 bmp -> rgb 0888 dib ==== */
3181 convs->Convert_555_to_0888_reverse
3182 (width,lines,
3183 srcbits,-bmpImage->bytes_per_line,
3184 dstbits,linebytes);
3185 } else {
3186 goto notsupported;
3188 } else if (bmpImage->green_mask==0x07e0) {
3189 if (bmpImage->red_mask==0xf800) {
3190 /* ==== rgb 565 bmp -> rgb 0888 dib ==== */
3191 convs->Convert_565_to_0888_asis
3192 (width,lines,
3193 srcbits,-bmpImage->bytes_per_line,
3194 dstbits,linebytes);
3195 } else if (bmpImage->blue_mask==0xf800) {
3196 /* ==== bgr 565 bmp -> rgb 0888 dib ==== */
3197 convs->Convert_565_to_0888_reverse
3198 (width,lines,
3199 srcbits,-bmpImage->bytes_per_line,
3200 dstbits,linebytes);
3201 } else {
3202 goto notsupported;
3204 } else {
3205 goto notsupported;
3207 } else if (rDst==0x0000ff && gDst==0x00ff00 && bDst==0xff0000) {
3208 if (bmpImage->green_mask==0x03e0) {
3209 if (bmpImage->blue_mask==0x7f00) {
3210 /* ==== bgr 555 bmp -> bgr 0888 dib ==== */
3211 convs->Convert_555_to_0888_asis
3212 (width,lines,
3213 srcbits,-bmpImage->bytes_per_line,
3214 dstbits,linebytes);
3215 } else if (bmpImage->red_mask==0x7f00) {
3216 /* ==== rgb 555 bmp -> bgr 0888 dib ==== */
3217 convs->Convert_555_to_0888_reverse
3218 (width,lines,
3219 srcbits,-bmpImage->bytes_per_line,
3220 dstbits,linebytes);
3221 } else {
3222 goto notsupported;
3224 } else if (bmpImage->green_mask==0x07e0) {
3225 if (bmpImage->blue_mask==0xf800) {
3226 /* ==== bgr 565 bmp -> bgr 0888 dib ==== */
3227 convs->Convert_565_to_0888_asis
3228 (width,lines,
3229 srcbits,-bmpImage->bytes_per_line,
3230 dstbits,linebytes);
3231 } else if (bmpImage->red_mask==0xf800) {
3232 /* ==== rgb 565 bmp -> bgr 0888 dib ==== */
3233 convs->Convert_565_to_0888_reverse
3234 (width,lines,
3235 srcbits,-bmpImage->bytes_per_line,
3236 dstbits,linebytes);
3237 } else {
3238 goto notsupported;
3240 } else {
3241 goto notsupported;
3243 } else {
3244 if (bmpImage->green_mask==0x03e0 &&
3245 (bmpImage->red_mask==0x7f00 ||
3246 bmpImage->blue_mask==0x7f00)) {
3247 /* ==== rgb or bgr 555 bmp -> any 0888 dib ==== */
3248 convs->Convert_5x5_to_any0888
3249 (width,lines,
3250 srcbits,-bmpImage->bytes_per_line,
3251 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
3252 dstbits,linebytes,
3253 rDst,gDst,bDst);
3254 } else if (bmpImage->green_mask==0x07e0 &&
3255 (bmpImage->red_mask==0xf800 ||
3256 bmpImage->blue_mask==0xf800)) {
3257 /* ==== rgb or bgr 565 bmp -> any 0888 dib ==== */
3258 convs->Convert_5x5_to_any0888
3259 (width,lines,
3260 srcbits,-bmpImage->bytes_per_line,
3261 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
3262 dstbits,linebytes,
3263 rDst,gDst,bDst);
3264 } else {
3265 goto notsupported;
3269 break;
3271 case 1:
3272 case 4:
3273 if (X11DRV_DIB_CheckMask(bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask)
3274 && srccolors) {
3275 /* ==== pal 1 or 4 bmp -> any 0888 dib ==== */
3276 int rShift,gShift,bShift;
3277 DWORD* dstpixel;
3279 rShift=X11DRV_DIB_MaskToShift(rDst);
3280 gShift=X11DRV_DIB_MaskToShift(gDst);
3281 bShift=X11DRV_DIB_MaskToShift(bDst);
3282 for (h = lines - 1; h >= 0; h--) {
3283 dstpixel=(DWORD*)dstbits;
3284 for (x = 0; x < width; x++) {
3285 PALETTEENTRY srcval;
3286 srcval = srccolors[XGetPixel(bmpImage, x, h)];
3287 *dstpixel++=(srcval.peRed << rShift) |
3288 (srcval.peGreen << gShift) |
3289 (srcval.peBlue << bShift);
3291 dstbits += linebytes;
3293 } else {
3294 goto notsupported;
3296 break;
3298 case 8:
3299 if (X11DRV_DIB_CheckMask(bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask)
3300 && srccolors) {
3301 /* ==== pal 8 bmp -> any 0888 dib ==== */
3302 int rShift,gShift,bShift;
3303 const void* srcbits;
3304 const BYTE* srcpixel;
3305 DWORD* dstpixel;
3307 rShift=X11DRV_DIB_MaskToShift(rDst);
3308 gShift=X11DRV_DIB_MaskToShift(gDst);
3309 bShift=X11DRV_DIB_MaskToShift(bDst);
3310 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3311 for (h = lines - 1; h >= 0; h--) {
3312 srcpixel=srcbits;
3313 dstpixel=(DWORD*)dstbits;
3314 for (x = 0; x < width; x++) {
3315 PALETTEENTRY srcval;
3316 srcval=srccolors[*srcpixel++];
3317 *dstpixel++=(srcval.peRed << rShift) |
3318 (srcval.peGreen << gShift) |
3319 (srcval.peBlue << bShift);
3321 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
3322 dstbits += linebytes;
3324 } else {
3325 goto notsupported;
3327 break;
3329 default:
3330 notsupported:
3332 /* ==== any bmp format -> any 0888 dib ==== */
3333 int rShift,gShift,bShift;
3334 DWORD* dstpixel;
3336 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 32 bit DIB (%x,%x,%x)\n",
3337 bmpImage->depth, bmpImage->red_mask,
3338 bmpImage->green_mask, bmpImage->blue_mask,
3339 rDst,gDst,bDst);
3341 rShift=X11DRV_DIB_MaskToShift(rDst);
3342 gShift=X11DRV_DIB_MaskToShift(gDst);
3343 bShift=X11DRV_DIB_MaskToShift(bDst);
3344 for (h = lines - 1; h >= 0; h--) {
3345 dstpixel=(DWORD*)dstbits;
3346 for (x = 0; x < width; x++) {
3347 COLORREF srcval;
3348 srcval=X11DRV_PALETTE_ToLogical(physDev, XGetPixel(bmpImage, x, h));
3349 *dstpixel++=(GetRValue(srcval) << rShift) |
3350 (GetGValue(srcval) << gShift) |
3351 (GetBValue(srcval) << bShift);
3353 dstbits += linebytes;
3356 break;
3360 static int XGetSubImageErrorHandler(Display *dpy, XErrorEvent *event, void *arg)
3362 return (event->request_code == X_GetImage && event->error_code == BadMatch);
3365 /***********************************************************************
3366 * X11DRV_DIB_SetImageBits_GetSubImage
3368 * Helper for X11DRV_DIB_SetImageBits
3370 static void X11DRV_DIB_SetImageBits_GetSubImage(
3371 const X11DRV_DIB_IMAGEBITS_DESCR *descr, XImage *bmpImage)
3373 /* compressed bitmaps may contain gaps in them. So make a copy
3374 * of the existing pixels first */
3375 RECT bmprc, rc;
3377 SetRect( &bmprc, descr->xDest, descr->yDest,
3378 descr->xDest + descr->width , descr->yDest + descr->height );
3379 GetRgnBox( descr->physDev->region, &rc );
3380 /* convert from dc to drawable origin */
3381 OffsetRect( &rc, descr->physDev->dc_rect.left, descr->physDev->dc_rect.top);
3382 /* clip visible rect with bitmap */
3383 if( IntersectRect( &rc, &rc, &bmprc))
3385 X11DRV_expect_error( gdi_display, XGetSubImageErrorHandler, NULL );
3386 XGetSubImage( gdi_display, descr->drawable, rc.left, rc.top,
3387 rc.right - rc.left, rc.bottom - rc.top, AllPlanes,
3388 ZPixmap, bmpImage,
3389 descr->xSrc + rc.left - bmprc.left,
3390 descr->ySrc + rc.top - bmprc.top);
3391 X11DRV_check_error();
3395 /***********************************************************************
3396 * X11DRV_DIB_SetImageBits
3398 * Transfer the bits to an X image.
3399 * Helper function for SetDIBits() and SetDIBitsToDevice().
3401 static int X11DRV_DIB_SetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
3403 int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
3404 void *old_data = NULL;
3405 XImage *bmpImage;
3407 wine_tsx11_lock();
3408 if (descr->image)
3409 bmpImage = descr->image;
3410 else {
3411 bmpImage = XCreateImage( gdi_display, visual, descr->depth, ZPixmap, 0, NULL,
3412 descr->infoWidth, lines, 32, 0 );
3413 bmpImage->data = HeapAlloc( GetProcessHeap(), 0, lines * bmpImage->bytes_per_line );
3414 if(bmpImage->data == NULL) {
3415 ERR("Out of memory!\n");
3416 XDestroyImage( bmpImage );
3417 wine_tsx11_unlock();
3418 return 0;
3420 if (descr->shifts)
3422 bmpImage->red_mask = descr->shifts->physicalRed.max << descr->shifts->physicalRed.shift;
3423 bmpImage->green_mask = descr->shifts->physicalGreen.max << descr->shifts->physicalGreen.shift;
3424 bmpImage->blue_mask = descr->shifts->physicalBlue.max << descr->shifts->physicalBlue.shift;
3427 wine_tsx11_unlock();
3429 TRACE("Dib: depth=%d r=%x g=%x b=%x\n",
3430 descr->infoBpp,descr->rMask,descr->gMask,descr->bMask);
3431 TRACE("Bmp: depth=%d/%d r=%lx g=%lx b=%lx\n",
3432 bmpImage->depth,bmpImage->bits_per_pixel,
3433 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
3435 #ifdef HAVE_LIBXXSHM
3436 if (descr->shm_mode == X11DRV_SHM_PIXMAP
3437 && descr->xSrc == 0 && descr->ySrc == 0
3438 && descr->xDest == 0 && descr->yDest == 0)
3440 TRACE("Using the shared pixmap data.\n");
3442 wine_tsx11_lock();
3443 XSync( gdi_display, False );
3444 wine_tsx11_unlock();
3446 old_data = descr->image->data;
3447 descr->image->data = descr->physBitmap->shminfo.shmaddr;
3449 #endif
3451 /* Transfer the pixels */
3452 __TRY
3454 switch(descr->infoBpp)
3456 case 1:
3457 X11DRV_DIB_SetImageBits_1( descr->lines, descr->bits, descr->infoWidth,
3458 descr->width, descr->xSrc, (int *)(descr->colorMap),
3459 bmpImage, descr->dibpitch );
3460 break;
3461 case 4:
3462 if (descr->compression) {
3463 X11DRV_DIB_SetImageBits_GetSubImage( descr, bmpImage);
3464 X11DRV_DIB_SetImageBits_RLE4( descr->lines, descr->bits,
3465 descr->infoWidth, descr->width,
3466 descr->xSrc, (int *)(descr->colorMap),
3467 bmpImage );
3468 } else
3469 X11DRV_DIB_SetImageBits_4( descr->lines, descr->bits,
3470 descr->infoWidth, descr->width,
3471 descr->xSrc, (int*)(descr->colorMap),
3472 bmpImage, descr->dibpitch );
3473 break;
3474 case 8:
3475 if (descr->compression) {
3476 X11DRV_DIB_SetImageBits_GetSubImage( descr, bmpImage);
3477 X11DRV_DIB_SetImageBits_RLE8( descr->lines, descr->bits,
3478 descr->infoWidth, descr->width,
3479 descr->xSrc, (int *)(descr->colorMap),
3480 bmpImage );
3481 } else
3482 X11DRV_DIB_SetImageBits_8( descr->lines, descr->bits,
3483 descr->infoWidth, descr->width,
3484 descr->xSrc, (int *)(descr->colorMap),
3485 bmpImage, descr->dibpitch );
3486 break;
3487 case 15:
3488 case 16:
3489 X11DRV_DIB_SetImageBits_16( descr->lines, descr->bits,
3490 descr->infoWidth, descr->width,
3491 descr->xSrc, descr->physDev,
3492 descr->rMask, descr->gMask, descr->bMask,
3493 bmpImage, descr->dibpitch);
3494 break;
3495 case 24:
3496 X11DRV_DIB_SetImageBits_24( descr->lines, descr->bits,
3497 descr->infoWidth, descr->width,
3498 descr->xSrc, descr->physDev,
3499 descr->rMask, descr->gMask, descr->bMask,
3500 bmpImage, descr->dibpitch);
3501 break;
3502 case 32:
3503 X11DRV_DIB_SetImageBits_32( descr->lines, descr->bits,
3504 descr->infoWidth, descr->width,
3505 descr->xSrc, descr->physDev,
3506 descr->rMask, descr->gMask, descr->bMask,
3507 bmpImage, descr->dibpitch);
3508 break;
3509 default:
3510 WARN("(%d): Invalid depth\n", descr->infoBpp );
3511 break;
3514 __EXCEPT_PAGE_FAULT
3516 WARN( "invalid bits pointer %p\n", descr->bits );
3517 lines = 0;
3519 __ENDTRY
3521 TRACE("XPutImage(%ld,%p,%p,%d,%d,%d,%d,%d,%d)\n",
3522 descr->drawable, descr->gc, bmpImage,
3523 descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
3524 descr->width, descr->height);
3526 wine_tsx11_lock();
3527 if (lines)
3529 #ifdef HAVE_LIBXXSHM
3530 if (descr->shm_mode == X11DRV_SHM_PIXMAP
3531 && descr->xSrc == 0 && descr->ySrc == 0
3532 && descr->xDest == 0 && descr->yDest == 0)
3534 XSync( gdi_display, False );
3536 else if (descr->shm_mode == X11DRV_SHM_IMAGE && descr->image)
3538 XShmPutImage( gdi_display, descr->drawable, descr->gc, bmpImage,
3539 descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
3540 descr->width, descr->height, FALSE );
3541 XSync( gdi_display, 0 );
3543 else
3544 #endif
3546 XPutImage( gdi_display, descr->drawable, descr->gc, bmpImage,
3547 descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
3548 descr->width, descr->height );
3552 if (old_data) descr->image->data = old_data;
3554 if (!descr->image) X11DRV_DIB_DestroyXImage( bmpImage );
3555 wine_tsx11_unlock();
3556 return lines;
3559 /***********************************************************************
3560 * X11DRV_DIB_GetImageBits
3562 * Transfer the bits from an X image.
3564 static int X11DRV_DIB_GetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
3566 int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
3567 void *old_data = NULL;
3568 XImage *bmpImage;
3570 wine_tsx11_lock();
3571 if (descr->image)
3572 bmpImage = descr->image;
3573 else {
3574 bmpImage = XCreateImage( gdi_display, visual, descr->depth, ZPixmap, 0, NULL,
3575 descr->infoWidth, lines, 32, 0 );
3576 bmpImage->data = HeapAlloc( GetProcessHeap(), 0, lines * bmpImage->bytes_per_line );
3577 if(bmpImage->data == NULL) {
3578 ERR("Out of memory!\n");
3579 XDestroyImage( bmpImage );
3580 wine_tsx11_unlock();
3581 return 0;
3583 if (descr->shifts)
3585 bmpImage->red_mask = descr->shifts->physicalRed.max << descr->shifts->physicalRed.shift;
3586 bmpImage->green_mask = descr->shifts->physicalGreen.max << descr->shifts->physicalGreen.shift;
3587 bmpImage->blue_mask = descr->shifts->physicalBlue.max << descr->shifts->physicalBlue.shift;
3591 #ifdef HAVE_LIBXXSHM
3593 /* We must not call XShmGetImage() with a bitmap which is bigger than the available area.
3594 If we do, XShmGetImage() will fail (X exception), as it checks for this internally. */
3595 if (descr->shm_mode == X11DRV_SHM_PIXMAP && descr->image
3596 && descr->xSrc == 0 && descr->ySrc == 0
3597 && descr->xDest == 0 && descr->yDest == 0
3598 && bmpImage->width <= (descr->width - descr->xSrc)
3599 && bmpImage->height <= (descr->height - descr->ySrc))
3601 XSync( gdi_display, False );
3602 old_data = bmpImage->data;
3603 bmpImage->data = descr->physBitmap->shminfo.shmaddr;
3604 TRACE("Using shared pixmap data.\n");
3606 else if (descr->shm_mode == X11DRV_SHM_IMAGE && descr->image
3607 && bmpImage->width <= (descr->width - descr->xSrc)
3608 && bmpImage->height <= (descr->height - descr->ySrc))
3610 int saveRed, saveGreen, saveBlue;
3612 TRACE("XShmGetImage(%p, %ld, %p, %d, %d, %ld)\n",
3613 gdi_display, descr->drawable, bmpImage,
3614 descr->xSrc, descr->ySrc, AllPlanes);
3616 /* We must save and restore the bmpImage's masks in order
3617 * to preserve them across the call to XShmGetImage, which
3618 * decides to eliminate them since it doesn't happen to know
3619 * what the format of the image is supposed to be, even though
3620 * we do. */
3621 saveRed = bmpImage->red_mask;
3622 saveBlue= bmpImage->blue_mask;
3623 saveGreen = bmpImage->green_mask;
3625 XShmGetImage( gdi_display, descr->drawable, bmpImage,
3626 descr->xSrc, descr->ySrc, AllPlanes);
3628 bmpImage->red_mask = saveRed;
3629 bmpImage->blue_mask = saveBlue;
3630 bmpImage->green_mask = saveGreen;
3632 else
3633 #endif /* HAVE_LIBXXSHM */
3635 TRACE("XGetSubImage(%p,%ld,%d,%d,%d,%d,%ld,%d,%p,%d,%d)\n",
3636 gdi_display, descr->drawable, descr->xSrc, descr->ySrc, descr->width,
3637 lines, AllPlanes, ZPixmap, bmpImage, descr->xDest, descr->yDest);
3638 XGetSubImage( gdi_display, descr->drawable, descr->xSrc, descr->ySrc,
3639 descr->width, lines, AllPlanes, ZPixmap,
3640 bmpImage, descr->xDest, descr->yDest );
3642 wine_tsx11_unlock();
3644 TRACE("Dib: depth=%2d r=%x g=%x b=%x\n",
3645 descr->infoBpp,descr->rMask,descr->gMask,descr->bMask);
3646 TRACE("Bmp: depth=%2d/%2d r=%lx g=%lx b=%lx\n",
3647 bmpImage->depth,bmpImage->bits_per_pixel,
3648 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
3649 /* Transfer the pixels */
3650 switch(descr->infoBpp)
3652 case 1:
3653 X11DRV_DIB_GetImageBits_1( descr->lines,(LPVOID)descr->bits,
3654 descr->infoWidth, descr->width,
3655 descr->colorMap, descr->palentry,
3656 bmpImage, descr->dibpitch );
3657 break;
3659 case 4:
3660 if (descr->compression) {
3661 FIXME("Compression not yet supported!\n");
3662 if(descr->sizeImage < X11DRV_DIB_GetDIBWidthBytes( descr->infoWidth, 4 ) * abs(descr->lines))
3663 break;
3665 X11DRV_DIB_GetImageBits_4( descr->lines,(LPVOID)descr->bits,
3666 descr->infoWidth, descr->width,
3667 descr->colorMap, descr->palentry,
3668 bmpImage, descr->dibpitch );
3669 break;
3670 case 8:
3671 if (descr->compression) {
3672 FIXME("Compression not yet supported!\n");
3673 if(descr->sizeImage < X11DRV_DIB_GetDIBWidthBytes( descr->infoWidth, 8 ) * abs(descr->lines))
3674 break;
3676 X11DRV_DIB_GetImageBits_8( descr->lines, (LPVOID)descr->bits,
3677 descr->infoWidth, descr->width,
3678 descr->colorMap, descr->palentry,
3679 bmpImage, descr->dibpitch );
3680 break;
3681 case 15:
3682 case 16:
3683 X11DRV_DIB_GetImageBits_16( descr->physDev, descr->lines, (LPVOID)descr->bits,
3684 descr->infoWidth,descr->width,
3685 descr->palentry,
3686 descr->rMask, descr->gMask, descr->bMask,
3687 bmpImage, descr->dibpitch );
3688 break;
3690 case 24:
3691 X11DRV_DIB_GetImageBits_24( descr->physDev, descr->lines, (LPVOID)descr->bits,
3692 descr->infoWidth,descr->width,
3693 descr->palentry,
3694 descr->rMask, descr->gMask, descr->bMask,
3695 bmpImage, descr->dibpitch);
3696 break;
3698 case 32:
3699 X11DRV_DIB_GetImageBits_32( descr->physDev, descr->lines, (LPVOID)descr->bits,
3700 descr->infoWidth, descr->width,
3701 descr->palentry,
3702 descr->rMask, descr->gMask, descr->bMask,
3703 bmpImage, descr->dibpitch);
3704 break;
3706 default:
3707 WARN("(%d): Invalid depth\n", descr->infoBpp );
3708 break;
3711 if (old_data) bmpImage->data = old_data;
3712 if (!descr->image) X11DRV_DIB_DestroyXImage( bmpImage );
3713 return lines;
3716 /*************************************************************************
3717 * X11DRV_SetDIBitsToDevice
3720 INT X11DRV_SetDIBitsToDevice( PHYSDEV dev, INT xDest, INT yDest, DWORD cx, DWORD cy,
3721 INT xSrc, INT ySrc, UINT startscan, UINT lines, LPCVOID bits,
3722 BITMAPINFO *info, UINT coloruse )
3724 X11DRV_PDEVICE *physDev = get_x11drv_dev( dev );
3725 X11DRV_DIB_IMAGEBITS_DESCR descr;
3726 INT result;
3727 LONG height;
3728 BOOL top_down;
3729 POINT pt;
3730 int rop = X11DRV_XROPfunction[GetROP2(dev->hdc) - 1];
3732 top_down = (info->bmiHeader.biHeight < 0);
3733 height = abs( info->bmiHeader.biHeight );
3734 descr.infoBpp = info->bmiHeader.biBitCount;
3735 descr.compression = info->bmiHeader.biCompression;
3737 pt.x = xDest;
3738 pt.y = yDest;
3739 LPtoDP(dev->hdc, &pt, 1);
3740 if (GetLayout( dev->hdc ) & LAYOUT_RTL) pt.x -= cx - 1;
3742 if (!lines || (startscan >= height)) return 0;
3743 if (!top_down && startscan + lines > height) lines = height - startscan;
3745 /* make xSrc,ySrc point to the upper-left corner, not the lower-left one,
3746 * and clamp all values to fit inside [startscan,startscan+lines]
3748 if (ySrc + cy <= startscan + lines)
3750 UINT y = startscan + lines - (ySrc + cy);
3751 if (ySrc < startscan) cy -= (startscan - ySrc);
3752 if (!top_down)
3754 /* avoid getting unnecessary lines */
3755 ySrc = 0;
3756 if (y >= lines) return 0;
3757 lines -= y;
3759 else
3761 if (y >= lines) return lines;
3762 ySrc = y; /* need to get all lines in top down mode */
3765 else
3767 if (ySrc >= startscan + lines) return 0;
3768 pt.y += ySrc + cy - (startscan + lines);
3769 cy = startscan + lines - ySrc;
3770 ySrc = 0;
3771 if (cy > lines) cy = lines;
3773 if (xSrc >= info->bmiHeader.biWidth) return lines;
3774 if (xSrc + cx <= 0) return lines;
3775 if (xSrc + cx >= info->bmiHeader.biWidth) cx = info->bmiHeader.biWidth - xSrc;
3776 if (xSrc < 0)
3778 pt.x -= xSrc;
3779 cx += xSrc;
3780 xSrc = 0;
3782 if (!cx || !cy) return lines;
3784 /* Update the pixmap from the DIB section */
3785 X11DRV_LockDIBSection(physDev, DIB_Status_GdiMod);
3787 X11DRV_SetupGCForText( physDev ); /* To have the correct colors */
3788 wine_tsx11_lock();
3789 XSetFunction(gdi_display, physDev->gc, rop);
3790 wine_tsx11_unlock();
3792 switch (descr.infoBpp)
3794 case 1:
3795 case 4:
3796 case 8:
3797 descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap(
3798 physDev, coloruse,
3799 physDev->depth, info, &descr.nColorMap );
3800 if (!descr.colorMap) return 0;
3801 descr.rMask = descr.gMask = descr.bMask = 0;
3802 break;
3803 case 15:
3804 case 16:
3805 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(const DWORD *)info->bmiColors : 0x7c00;
3806 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)info->bmiColors + 1) : 0x03e0;
3807 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)info->bmiColors + 2) : 0x001f;
3808 descr.colorMap = 0;
3809 break;
3811 case 24:
3812 case 32:
3813 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(const DWORD *)info->bmiColors : 0xff0000;
3814 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)info->bmiColors + 1) : 0x00ff00;
3815 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)info->bmiColors + 2) : 0x0000ff;
3816 descr.colorMap = 0;
3817 break;
3820 descr.physDev = physDev;
3821 descr.bits = bits;
3822 descr.image = NULL;
3823 descr.palentry = NULL;
3824 descr.lines = top_down ? -lines : lines;
3825 descr.infoWidth = info->bmiHeader.biWidth;
3826 descr.depth = physDev->depth;
3827 descr.shifts = physDev->color_shifts;
3828 descr.drawable = physDev->drawable;
3829 descr.gc = physDev->gc;
3830 descr.xSrc = xSrc;
3831 descr.ySrc = ySrc;
3832 descr.xDest = physDev->dc_rect.left + pt.x;
3833 descr.yDest = physDev->dc_rect.top + pt.y;
3834 descr.width = cx;
3835 descr.height = cy;
3836 descr.shm_mode = X11DRV_SHM_NONE;
3837 descr.dibpitch = X11DRV_DIB_GetDIBWidthBytes( info->bmiHeader.biWidth, info->bmiHeader.biBitCount );
3838 descr.physBitmap = NULL;
3840 result = X11DRV_DIB_SetImageBits( &descr );
3842 if (descr.infoBpp <= 8)
3843 HeapFree(GetProcessHeap(), 0, descr.colorMap);
3845 /* Update the DIBSection of the pixmap */
3846 X11DRV_UnlockDIBSection(physDev, TRUE);
3848 return result;
3851 /***********************************************************************
3852 * X11DRV_DIB_DoCopyDIBSection
3854 static void X11DRV_DIB_DoCopyDIBSection(X_PHYSBITMAP *physBitmap, BOOL toDIB,
3855 void *colorMap, int nColorMap,
3856 Drawable dest, GC gc,
3857 DWORD xSrc, DWORD ySrc,
3858 DWORD xDest, DWORD yDest,
3859 DWORD width, DWORD height)
3861 DIBSECTION dibSection;
3862 X11DRV_DIB_IMAGEBITS_DESCR descr;
3863 int identity[2] = {0,1};
3865 if (!GetObjectW( physBitmap->hbitmap, sizeof(dibSection), &dibSection )) return;
3867 descr.physDev = NULL;
3868 descr.palentry = NULL;
3869 descr.infoWidth = dibSection.dsBmih.biWidth;
3870 descr.infoBpp = dibSection.dsBmih.biBitCount;
3871 descr.lines = physBitmap->topdown ? -dibSection.dsBmih.biHeight : dibSection.dsBmih.biHeight;
3872 descr.image = physBitmap->image;
3873 descr.colorMap = colorMap;
3874 descr.nColorMap = nColorMap;
3875 descr.bits = dibSection.dsBm.bmBits;
3876 descr.depth = physBitmap->pixmap_depth;
3877 descr.shifts = physBitmap->trueColor ? &physBitmap->pixmap_color_shifts : NULL;
3878 descr.compression = dibSection.dsBmih.biCompression;
3879 descr.physBitmap = physBitmap;
3881 if(descr.infoBpp == 1)
3882 descr.colorMap = (void*)identity;
3884 switch (descr.infoBpp)
3886 case 1:
3887 case 4:
3888 case 8:
3889 descr.rMask = descr.gMask = descr.bMask = 0;
3890 break;
3891 case 15:
3892 case 16:
3893 descr.rMask = (descr.compression == BI_BITFIELDS) ? dibSection.dsBitfields[0] : 0x7c00;
3894 descr.gMask = (descr.compression == BI_BITFIELDS) ? dibSection.dsBitfields[1] : 0x03e0;
3895 descr.bMask = (descr.compression == BI_BITFIELDS) ? dibSection.dsBitfields[2] : 0x001f;
3896 break;
3898 case 24:
3899 case 32:
3900 descr.rMask = (descr.compression == BI_BITFIELDS) ? dibSection.dsBitfields[0] : 0xff0000;
3901 descr.gMask = (descr.compression == BI_BITFIELDS) ? dibSection.dsBitfields[1] : 0x00ff00;
3902 descr.bMask = (descr.compression == BI_BITFIELDS) ? dibSection.dsBitfields[2] : 0x0000ff;
3903 break;
3906 /* Hack for now */
3907 descr.drawable = dest;
3908 descr.gc = gc;
3909 descr.xSrc = xSrc;
3910 descr.ySrc = ySrc;
3911 descr.xDest = xDest;
3912 descr.yDest = yDest;
3913 descr.width = width;
3914 descr.height = height;
3915 descr.sizeImage = 0;
3917 descr.shm_mode = physBitmap->shm_mode;
3918 #ifdef HAVE_LIBXXSHM
3919 if (physBitmap->shm_mode == X11DRV_SHM_PIXMAP && physBitmap->pixmap != dest)
3921 descr.shm_mode = X11DRV_SHM_NONE;
3923 #endif
3924 descr.dibpitch = dibSection.dsBm.bmWidthBytes;
3926 if (toDIB)
3928 TRACE("Copying from Pixmap to DIB bits\n");
3929 X11DRV_DIB_GetImageBits( &descr );
3931 else
3933 TRACE("Copying from DIB bits to Pixmap\n");
3934 X11DRV_DIB_SetImageBits( &descr );
3938 /***********************************************************************
3939 * X11DRV_DIB_CopyDIBSection
3941 void X11DRV_DIB_CopyDIBSection(X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE *physDevDst,
3942 DWORD xSrc, DWORD ySrc, DWORD xDest, DWORD yDest,
3943 DWORD width, DWORD height)
3945 DIBSECTION dib;
3946 X_PHYSBITMAP *physBitmap;
3947 unsigned int nColorMap;
3948 int* x11ColorMap;
3949 int freeColorMap;
3951 TRACE("(%p,%p,%d,%d,%d,%d,%d,%d)\n", physDevSrc->dev.hdc, physDevDst->dev.hdc,
3952 xSrc, ySrc, xDest, yDest, width, height);
3953 /* this function is meant as an optimization for BitBlt,
3954 * not to be called otherwise */
3955 physBitmap = physDevSrc->bitmap;
3956 if (!physBitmap || GetObjectW( physBitmap->hbitmap, sizeof(dib), &dib ) != sizeof(dib))
3958 ERR("called for non-DIBSection!?\n");
3959 return;
3961 /* while BitBlt should already have made sure we only get
3962 * positive values, we should check for oversize values */
3963 if ((xSrc < dib.dsBm.bmWidth) &&
3964 (ySrc < dib.dsBm.bmHeight)) {
3965 if (xSrc + width > dib.dsBm.bmWidth)
3966 width = dib.dsBm.bmWidth - xSrc;
3967 if (ySrc + height > dib.dsBm.bmHeight)
3968 height = dib.dsBm.bmHeight - ySrc;
3969 /* if the source bitmap is 8bpp or less, we're supposed to use the
3970 * DC's palette for color conversion (not the DIB color table) */
3971 if (dib.dsBm.bmBitsPixel <= 8) {
3972 HPALETTE hPalette = GetCurrentObject( physDevSrc->dev.hdc, OBJ_PAL );
3973 if (!hPalette || (hPalette == GetStockObject(DEFAULT_PALETTE))) {
3974 /* HACK: no palette has been set in the source DC,
3975 * use the DIB colormap instead - this is necessary in some
3976 * cases since we need to do depth conversion in some places
3977 * where real Windows can just copy data straight over */
3978 x11ColorMap = physBitmap->colorMap;
3979 nColorMap = physBitmap->nColorMap;
3980 freeColorMap = FALSE;
3981 } else {
3982 const BITMAPINFO* info = (BITMAPINFO*)&dib.dsBmih;
3983 unsigned int i;
3985 nColorMap = X11DRV_DIB_GetColorCount(info);
3986 x11ColorMap = HeapAlloc(GetProcessHeap(), 0, nColorMap * sizeof(int));
3987 for (i = 0; i < nColorMap; i++)
3988 x11ColorMap[i] = X11DRV_PALETTE_ToPhysical(physDevSrc, PALETTEINDEX(i));
3989 freeColorMap = TRUE;
3992 else
3994 nColorMap = 0;
3995 x11ColorMap = NULL;
3996 freeColorMap = FALSE;
3998 /* perform the copy */
3999 X11DRV_DIB_DoCopyDIBSection(physBitmap, FALSE, x11ColorMap, nColorMap,
4000 physDevDst->drawable, physDevDst->gc, xSrc, ySrc,
4001 physDevDst->dc_rect.left + xDest, physDevDst->dc_rect.top + yDest,
4002 width, height);
4003 /* free color mapping */
4004 if (freeColorMap)
4005 HeapFree(GetProcessHeap(), 0, x11ColorMap);
4009 /***********************************************************************
4010 * X11DRV_DIB_DoUpdateDIBSection
4012 static void X11DRV_DIB_DoUpdateDIBSection(X_PHYSBITMAP *physBitmap, BOOL toDIB)
4014 BITMAP bitmap;
4016 GetObjectW( physBitmap->hbitmap, sizeof(bitmap), &bitmap );
4017 X11DRV_DIB_DoCopyDIBSection(physBitmap, toDIB,
4018 physBitmap->colorMap, physBitmap->nColorMap,
4019 physBitmap->pixmap, get_bitmap_gc(physBitmap->pixmap_depth),
4020 0, 0, 0, 0, bitmap.bmWidth, bitmap.bmHeight);
4023 /***********************************************************************
4024 * X11DRV_DIB_FaultHandler
4026 static LONG CALLBACK X11DRV_DIB_FaultHandler( PEXCEPTION_POINTERS ep )
4028 X_PHYSBITMAP *physBitmap = NULL;
4029 BOOL found = FALSE;
4030 BYTE *addr;
4031 struct list *ptr;
4032 const size_t pagemask = getpagesize() - 1;
4034 if (ep->ExceptionRecord->ExceptionCode != EXCEPTION_ACCESS_VIOLATION)
4035 return EXCEPTION_CONTINUE_SEARCH;
4037 addr = (BYTE *)ep->ExceptionRecord->ExceptionInformation[1];
4039 EnterCriticalSection(&dibs_cs);
4040 LIST_FOR_EACH( ptr, &dibs_list )
4042 physBitmap = LIST_ENTRY( ptr, X_PHYSBITMAP, entry );
4043 if ((physBitmap->base <= addr) &&
4044 (addr < physBitmap->base + ((physBitmap->size + pagemask) & ~pagemask)))
4046 found = TRUE;
4047 break;
4050 LeaveCriticalSection(&dibs_cs);
4052 if (!found) return EXCEPTION_CONTINUE_SEARCH;
4054 if (addr >= physBitmap->base + physBitmap->size)
4055 WARN( "%p: access to %p beyond the end of the DIB\n", physBitmap->hbitmap, addr );
4057 X11DRV_DIB_Lock( physBitmap, DIB_Status_None );
4058 if (ep->ExceptionRecord->ExceptionInformation[0] == EXCEPTION_WRITE_FAULT) {
4059 /* the app tried to write the DIB bits */
4060 X11DRV_DIB_Coerce( physBitmap, DIB_Status_AppMod);
4061 } else {
4062 /* the app tried to read the DIB bits */
4063 X11DRV_DIB_Coerce( physBitmap, DIB_Status_InSync);
4065 X11DRV_DIB_Unlock( physBitmap, TRUE );
4067 return EXCEPTION_CONTINUE_EXECUTION;
4070 /***********************************************************************
4071 * X11DRV_DIB_Coerce
4073 static INT X11DRV_DIB_Coerce(X_PHYSBITMAP *physBitmap, INT req)
4075 INT ret = DIB_Status_None;
4077 if (!physBitmap->image) return ret; /* not a DIB section */
4078 EnterCriticalSection(&physBitmap->lock);
4079 ret = physBitmap->status;
4080 switch (req) {
4081 case DIB_Status_GdiMod:
4082 /* GDI access - request to draw on pixmap */
4083 switch (physBitmap->status)
4085 default:
4086 case DIB_Status_None:
4087 physBitmap->p_status = DIB_Status_GdiMod;
4088 X11DRV_DIB_DoUpdateDIBSection( physBitmap, FALSE );
4089 break;
4091 case DIB_Status_GdiMod:
4092 TRACE("GdiMod requested in status GdiMod\n" );
4093 physBitmap->p_status = DIB_Status_GdiMod;
4094 break;
4096 case DIB_Status_InSync:
4097 TRACE("GdiMod requested in status InSync\n" );
4098 X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_NOACCESS );
4099 physBitmap->status = DIB_Status_GdiMod;
4100 physBitmap->p_status = DIB_Status_InSync;
4101 break;
4103 case DIB_Status_AppMod:
4104 TRACE("GdiMod requested in status AppMod\n" );
4105 /* make it readonly to avoid app changing data while we copy */
4106 X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_READONLY );
4107 X11DRV_DIB_DoUpdateDIBSection( physBitmap, FALSE );
4108 X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_NOACCESS );
4109 physBitmap->p_status = DIB_Status_AppMod;
4110 physBitmap->status = DIB_Status_GdiMod;
4111 break;
4113 break;
4115 case DIB_Status_InSync:
4116 /* App access - request access to read DIB surface */
4117 /* (typically called from signal handler) */
4118 switch (physBitmap->status)
4120 default:
4121 case DIB_Status_None:
4122 /* shouldn't happen from signal handler */
4123 break;
4125 case DIB_Status_GdiMod:
4126 TRACE("InSync requested in status GdiMod\n" );
4127 X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_READWRITE );
4128 X11DRV_DIB_DoUpdateDIBSection( physBitmap, TRUE );
4129 X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_READONLY );
4130 physBitmap->status = DIB_Status_InSync;
4131 break;
4133 case DIB_Status_InSync:
4134 TRACE("InSync requested in status InSync\n" );
4135 /* shouldn't happen from signal handler */
4136 break;
4138 case DIB_Status_AppMod:
4139 TRACE("InSync requested in status AppMod\n" );
4140 /* no reason to do anything here, and this
4141 * shouldn't happen from signal handler */
4142 break;
4144 break;
4146 case DIB_Status_AppMod:
4147 /* App access - request access to write DIB surface */
4148 /* (typically called from signal handler) */
4149 switch (physBitmap->status)
4151 default:
4152 case DIB_Status_None:
4153 /* shouldn't happen from signal handler */
4154 break;
4156 case DIB_Status_GdiMod:
4157 TRACE("AppMod requested in status GdiMod\n" );
4158 X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_READWRITE );
4159 X11DRV_DIB_DoUpdateDIBSection( physBitmap, TRUE );
4160 physBitmap->status = DIB_Status_AppMod;
4161 break;
4163 case DIB_Status_InSync:
4164 TRACE("AppMod requested in status InSync\n" );
4165 X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_READWRITE );
4166 physBitmap->status = DIB_Status_AppMod;
4167 break;
4169 case DIB_Status_AppMod:
4170 TRACE("AppMod requested in status AppMod\n" );
4171 /* shouldn't happen from signal handler */
4172 break;
4174 break;
4176 /* it is up to the caller to do the copy/conversion, probably
4177 * using the return value to decide where to copy from */
4179 LeaveCriticalSection(&physBitmap->lock);
4180 return ret;
4183 /***********************************************************************
4184 * X11DRV_DIB_Lock
4186 INT X11DRV_DIB_Lock(X_PHYSBITMAP *physBitmap, INT req)
4188 INT ret = DIB_Status_None;
4190 if (!physBitmap->image) return ret; /* not a DIB section */
4191 TRACE("Locking %p from thread %04x\n", physBitmap->hbitmap, GetCurrentThreadId());
4192 EnterCriticalSection(&physBitmap->lock);
4193 ret = physBitmap->status;
4194 if (req != DIB_Status_None)
4195 X11DRV_DIB_Coerce(physBitmap, req);
4196 return ret;
4199 /***********************************************************************
4200 * X11DRV_DIB_Unlock
4202 void X11DRV_DIB_Unlock(X_PHYSBITMAP *physBitmap, BOOL commit)
4204 if (!physBitmap->image) return; /* not a DIB section */
4205 switch (physBitmap->status)
4207 default:
4208 case DIB_Status_None:
4209 /* in case anyone is wondering, this is the "signal handler doesn't
4210 * work" case, where we always have to be ready for app access */
4211 if (commit) {
4212 switch (physBitmap->p_status)
4214 case DIB_Status_GdiMod:
4215 TRACE("Unlocking and syncing from GdiMod\n" );
4216 X11DRV_DIB_DoUpdateDIBSection( physBitmap, TRUE );
4217 break;
4219 default:
4220 TRACE("Unlocking without needing to sync\n" );
4221 break;
4224 else TRACE("Unlocking with no changes\n");
4225 physBitmap->p_status = DIB_Status_None;
4226 break;
4228 case DIB_Status_GdiMod:
4229 TRACE("Unlocking in status GdiMod\n" );
4230 /* DIB was protected in Coerce */
4231 if (!commit) {
4232 /* no commit, revert to InSync if applicable */
4233 if ((physBitmap->p_status == DIB_Status_InSync) ||
4234 (physBitmap->p_status == DIB_Status_AppMod)) {
4235 X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_READONLY );
4236 physBitmap->status = DIB_Status_InSync;
4239 break;
4241 case DIB_Status_InSync:
4242 TRACE("Unlocking in status InSync\n" );
4243 /* DIB was already protected in Coerce */
4244 break;
4246 case DIB_Status_AppMod:
4247 TRACE("Unlocking in status AppMod\n" );
4248 /* DIB was already protected in Coerce */
4249 /* this case is ordinary only called from the signal handler,
4250 * so we don't bother to check for !commit */
4251 break;
4253 LeaveCriticalSection(&physBitmap->lock);
4254 TRACE("Unlocked %p\n", physBitmap->hbitmap);
4257 /***********************************************************************
4258 * X11DRV_CoerceDIBSection
4260 INT X11DRV_CoerceDIBSection(X11DRV_PDEVICE *physDev, INT req)
4262 if (!physDev || !physDev->bitmap) return DIB_Status_None;
4263 return X11DRV_DIB_Coerce(physDev->bitmap, req);
4266 /***********************************************************************
4267 * X11DRV_LockDIBSection
4269 INT X11DRV_LockDIBSection(X11DRV_PDEVICE *physDev, INT req)
4271 if (!physDev || !physDev->bitmap) return DIB_Status_None;
4272 return X11DRV_DIB_Lock(physDev->bitmap, req);
4275 /***********************************************************************
4276 * X11DRV_UnlockDIBSection
4278 void X11DRV_UnlockDIBSection(X11DRV_PDEVICE *physDev, BOOL commit)
4280 if (!physDev || !physDev->bitmap) return;
4281 X11DRV_DIB_Unlock(physDev->bitmap, commit);
4285 #ifdef HAVE_LIBXXSHM
4286 /***********************************************************************
4287 * X11DRV_XShmErrorHandler
4290 static int XShmErrorHandler( Display *dpy, XErrorEvent *event, void *arg )
4292 return 1; /* FIXME: should check event contents */
4295 /***********************************************************************
4296 * X11DRV_XShmCreateImage
4299 static XImage *X11DRV_XShmCreateImage( int width, int height, int bpp,
4300 XShmSegmentInfo* shminfo)
4302 XImage *image;
4304 image = XShmCreateImage(gdi_display, visual, bpp, ZPixmap, NULL, shminfo, width, height);
4305 if (image)
4307 shminfo->shmid = shmget(IPC_PRIVATE, image->bytes_per_line * height,
4308 IPC_CREAT|0700);
4309 if( shminfo->shmid != -1 )
4311 shminfo->shmaddr = shmat( shminfo->shmid, 0, 0 );
4312 if( shminfo->shmaddr != (char*)-1 )
4314 BOOL ok;
4316 shminfo->readOnly = FALSE;
4317 X11DRV_expect_error( gdi_display, XShmErrorHandler, NULL );
4318 ok = (XShmAttach( gdi_display, shminfo ) != 0);
4319 XSync( gdi_display, False );
4320 if (X11DRV_check_error()) ok = FALSE;
4321 if (ok)
4323 shmctl(shminfo->shmid, IPC_RMID, 0);
4324 return image; /* Success! */
4326 /* An error occurred */
4327 shmdt(shminfo->shmaddr);
4329 shmctl(shminfo->shmid, IPC_RMID, 0);
4330 shminfo->shmid = -1;
4332 XFlush(gdi_display);
4333 XDestroyImage(image);
4334 image = NULL;
4336 return image;
4338 #endif /* HAVE_LIBXXSHM */
4340 static Bool X11DRV_DIB_QueryXShm( Bool *pixmaps )
4342 static Bool have_xshm, have_xshm_pixmaps;
4343 static BOOL initialized;
4345 if (!initialized)
4347 #ifdef HAVE_LIBXXSHM
4348 int major, minor;
4350 have_xshm = XShmQueryVersion( gdi_display, &major, &minor, &have_xshm_pixmaps );
4351 #endif
4352 initialized = TRUE;
4355 *pixmaps = have_xshm_pixmaps;
4356 return have_xshm;
4359 /***********************************************************************
4360 * X11DRV_CreateDIBSection (X11DRV.@)
4362 HBITMAP X11DRV_CreateDIBSection( PHYSDEV dev, HBITMAP hbitmap, BITMAPINFO *bmi, UINT usage )
4364 X11DRV_PDEVICE *physDev = get_x11drv_dev( dev );
4365 X_PHYSBITMAP *physBitmap;
4366 DIBSECTION dib;
4367 #ifdef HAVE_LIBXXSHM
4368 Bool pixmaps;
4369 #endif
4371 if (!(physBitmap = X11DRV_init_phys_bitmap( hbitmap ))) return 0;
4372 physBitmap->topdown = bmi->bmiHeader.biHeight < 0;
4373 physBitmap->status = DIB_Status_None;
4375 GetObjectW( hbitmap, sizeof(dib), &dib );
4377 /* create color map */
4378 if (dib.dsBm.bmBitsPixel <= 8)
4380 physBitmap->colorMap = X11DRV_DIB_BuildColorMap( physDev,
4381 usage, dib.dsBm.bmBitsPixel, bmi,
4382 &physBitmap->nColorMap );
4385 if (!X11DRV_XRender_SetPhysBitmapDepth( physBitmap, dib.dsBm.bmBitsPixel, &dib ))
4387 if (dib.dsBm.bmBitsPixel == 1)
4389 physBitmap->pixmap_depth = 1;
4390 physBitmap->trueColor = FALSE;
4392 else
4394 physBitmap->pixmap_depth = screen_depth;
4395 physBitmap->pixmap_color_shifts = X11DRV_PALETTE_default_shifts;
4396 physBitmap->trueColor = (visual->class == TrueColor || visual->class == DirectColor);
4400 /* create pixmap and X image */
4401 wine_tsx11_lock();
4402 #ifdef HAVE_LIBXXSHM
4403 physBitmap->shminfo.shmid = -1;
4405 if (X11DRV_DIB_QueryXShm( &pixmaps )
4406 && (physBitmap->image = X11DRV_XShmCreateImage( dib.dsBm.bmWidth, dib.dsBm.bmHeight,
4407 physBitmap->pixmap_depth, &physBitmap->shminfo )))
4409 if (pixmaps)
4411 physBitmap->shm_mode = X11DRV_SHM_PIXMAP;
4412 physBitmap->image->data = HeapAlloc( GetProcessHeap(), 0,
4413 dib.dsBm.bmHeight * physBitmap->image->bytes_per_line );
4415 else
4417 physBitmap->shm_mode = X11DRV_SHM_IMAGE;
4418 physBitmap->image->data = physBitmap->shminfo.shmaddr;
4421 else
4422 #endif
4424 physBitmap->shm_mode = X11DRV_SHM_NONE;
4425 physBitmap->image = X11DRV_DIB_CreateXImage( dib.dsBm.bmWidth, dib.dsBm.bmHeight,
4426 physBitmap->pixmap_depth );
4429 #ifdef HAVE_LIBXXSHM
4430 if (physBitmap->shm_mode == X11DRV_SHM_PIXMAP)
4432 TRACE("Creating shared pixmap for bmp %p.\n", physBitmap->hbitmap);
4433 physBitmap->pixmap = XShmCreatePixmap( gdi_display, root_window,
4434 physBitmap->shminfo.shmaddr, &physBitmap->shminfo,
4435 dib.dsBm.bmWidth, dib.dsBm.bmHeight,
4436 physBitmap->pixmap_depth );
4438 else
4439 #endif
4441 physBitmap->pixmap = XCreatePixmap( gdi_display, root_window, dib.dsBm.bmWidth,
4442 dib.dsBm.bmHeight, physBitmap->pixmap_depth );
4445 wine_tsx11_unlock();
4446 if (!physBitmap->pixmap || !physBitmap->image) return 0;
4448 if (physBitmap->trueColor)
4450 ColorShifts *shifts = &physBitmap->pixmap_color_shifts;
4452 /* When XRender is around and used, we also support dibsections in other formats like 16-bit. In these
4453 * cases we need to override the mask of XImages. The reason is that during XImage creation the masks are
4454 * derived from a 24-bit visual (no 16-bit ones are around when X runs at 24-bit). SetImageBits and other
4455 * functions rely on the color masks for proper color conversion, so we need to override the masks here. */
4456 physBitmap->image->red_mask = shifts->physicalRed.max << shifts->physicalRed.shift;
4457 physBitmap->image->green_mask = shifts->physicalGreen.max << shifts->physicalGreen.shift;
4458 physBitmap->image->blue_mask = shifts->physicalBlue.max << shifts->physicalBlue.shift;
4461 /* install fault handler */
4462 InitializeCriticalSection( &physBitmap->lock );
4463 physBitmap->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": X_PHYSBITMAP.lock");
4465 physBitmap->base = dib.dsBm.bmBits;
4466 physBitmap->size = dib.dsBmih.biSizeImage;
4467 physBitmap->status = DIB_Status_AppMod;
4469 if (!dibs_handler)
4470 dibs_handler = AddVectoredExceptionHandler( TRUE, X11DRV_DIB_FaultHandler );
4471 EnterCriticalSection( &dibs_cs );
4472 list_add_head( &dibs_list, &physBitmap->entry );
4473 LeaveCriticalSection( &dibs_cs );
4475 X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_READWRITE );
4477 return hbitmap;
4480 /***********************************************************************
4481 * X11DRV_DIB_DeleteDIBSection
4483 void X11DRV_DIB_DeleteDIBSection(X_PHYSBITMAP *physBitmap, DIBSECTION *dib)
4485 BOOL last;
4487 EnterCriticalSection( &dibs_cs );
4488 list_remove( &physBitmap->entry );
4489 last = list_empty( &dibs_list );
4490 LeaveCriticalSection( &dibs_cs );
4492 if (last)
4494 RemoveVectoredExceptionHandler( dibs_handler );
4495 dibs_handler = NULL;
4498 if (dib->dshSection)
4499 X11DRV_DIB_Coerce(physBitmap, DIB_Status_InSync);
4501 if (physBitmap->image)
4503 wine_tsx11_lock();
4504 #ifdef HAVE_LIBXXSHM
4505 if (physBitmap->shminfo.shmid != -1)
4507 XShmDetach( gdi_display, &(physBitmap->shminfo) );
4508 if (physBitmap->shm_mode == X11DRV_SHM_PIXMAP) X11DRV_DIB_DestroyXImage( physBitmap->image );
4509 else XDestroyImage( physBitmap->image );
4510 shmdt( physBitmap->shminfo.shmaddr );
4511 physBitmap->shminfo.shmid = -1;
4512 physBitmap->shm_mode = X11DRV_SHM_NONE;
4514 else
4515 #endif
4516 X11DRV_DIB_DestroyXImage( physBitmap->image );
4517 wine_tsx11_unlock();
4520 HeapFree(GetProcessHeap(), 0, physBitmap->colorMap);
4521 physBitmap->lock.DebugInfo->Spare[0] = 0;
4522 DeleteCriticalSection(&physBitmap->lock);
4525 /***********************************************************************
4526 * SetDIBColorTable (X11DRV.@)
4528 UINT X11DRV_SetDIBColorTable( PHYSDEV dev, UINT start, UINT count, const RGBQUAD *colors )
4530 X11DRV_PDEVICE *physDev = get_x11drv_dev( dev );
4531 DIBSECTION dib;
4532 UINT ret = 0;
4533 X_PHYSBITMAP *physBitmap = physDev->bitmap;
4535 if (!physBitmap) return 0;
4536 GetObjectW( physBitmap->hbitmap, sizeof(dib), &dib );
4538 if (physBitmap->colorMap && start < physBitmap->nColorMap) {
4539 UINT end = count + start;
4540 if (end > physBitmap->nColorMap) end = physBitmap->nColorMap;
4542 * Changing color table might change the mapping between
4543 * DIB colors and X11 colors and thus alter the visible state
4544 * of the bitmap object.
4547 * FIXME we need to recalculate the pen, brush, text and bkgnd pixels here,
4548 * at least for a 1 bpp dibsection
4550 X11DRV_DIB_Lock( physBitmap, DIB_Status_AppMod );
4551 X11DRV_DIB_GenColorMap( physDev, physBitmap->colorMap, DIB_RGB_COLORS,
4552 dib.dsBm.bmBitsPixel, colors, start, end );
4553 X11DRV_DIB_Unlock( physBitmap, TRUE );
4554 ret = end - start;
4556 return ret;
4560 /***********************************************************************
4561 * X11DRV_DIB_CreateDIBFromBitmap
4563 * Allocates a packed DIB and copies the bitmap data into it.
4565 HGLOBAL X11DRV_DIB_CreateDIBFromBitmap(HDC hdc, HBITMAP hBmp)
4567 BITMAP bmp;
4568 HGLOBAL hPackedDIB;
4569 LPBYTE pPackedDIB;
4570 LPBITMAPINFOHEADER pbmiHeader;
4571 unsigned int cDataSize, cPackedSize, OffsetBits;
4572 int nLinesCopied;
4574 if (!GetObjectW( hBmp, sizeof(bmp), &bmp )) return 0;
4577 * A packed DIB contains a BITMAPINFO structure followed immediately by
4578 * an optional color palette and the pixel data.
4581 /* Calculate the size of the packed DIB */
4582 cDataSize = X11DRV_DIB_GetDIBWidthBytes( bmp.bmWidth, bmp.bmBitsPixel ) * abs( bmp.bmHeight );
4583 cPackedSize = sizeof(BITMAPINFOHEADER)
4584 + ( (bmp.bmBitsPixel <= 8) ? (sizeof(RGBQUAD) * (1 << bmp.bmBitsPixel)) : 0 )
4585 + cDataSize;
4586 /* Get the offset to the bits */
4587 OffsetBits = cPackedSize - cDataSize;
4589 /* Allocate the packed DIB */
4590 TRACE("\tAllocating packed DIB of size %d\n", cPackedSize);
4591 hPackedDIB = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE /*| GMEM_ZEROINIT*/,
4592 cPackedSize );
4593 if ( !hPackedDIB )
4595 WARN("Could not allocate packed DIB!\n");
4596 return 0;
4599 /* A packed DIB starts with a BITMAPINFOHEADER */
4600 pPackedDIB = GlobalLock(hPackedDIB);
4601 pbmiHeader = (LPBITMAPINFOHEADER)pPackedDIB;
4603 /* Init the BITMAPINFOHEADER */
4604 pbmiHeader->biSize = sizeof(BITMAPINFOHEADER);
4605 pbmiHeader->biWidth = bmp.bmWidth;
4606 pbmiHeader->biHeight = bmp.bmHeight;
4607 pbmiHeader->biPlanes = 1;
4608 pbmiHeader->biBitCount = bmp.bmBitsPixel;
4609 pbmiHeader->biCompression = BI_RGB;
4610 pbmiHeader->biSizeImage = 0;
4611 pbmiHeader->biXPelsPerMeter = pbmiHeader->biYPelsPerMeter = 0;
4612 pbmiHeader->biClrUsed = 0;
4613 pbmiHeader->biClrImportant = 0;
4615 /* Retrieve the DIB bits from the bitmap and fill in the
4616 * DIB color table if present */
4618 nLinesCopied = GetDIBits(hdc, /* Handle to device context */
4619 hBmp, /* Handle to bitmap */
4620 0, /* First scan line to set in dest bitmap */
4621 bmp.bmHeight, /* Number of scan lines to copy */
4622 pPackedDIB + OffsetBits, /* [out] Address of array for bitmap bits */
4623 (LPBITMAPINFO) pbmiHeader, /* [out] Address of BITMAPINFO structure */
4624 0); /* RGB or palette index */
4625 GlobalUnlock(hPackedDIB);
4627 /* Cleanup if GetDIBits failed */
4628 if (nLinesCopied != bmp.bmHeight)
4630 TRACE("\tGetDIBits returned %d. Actual lines=%d\n", nLinesCopied, bmp.bmHeight);
4631 GlobalFree(hPackedDIB);
4632 hPackedDIB = 0;
4634 return hPackedDIB;
4638 /**************************************************************************
4639 * X11DRV_DIB_CreateDIBFromPixmap
4641 * Allocates a packed DIB and copies the Pixmap data into it.
4642 * The Pixmap passed in is deleted after the conversion.
4644 HGLOBAL X11DRV_DIB_CreateDIBFromPixmap(Pixmap pixmap, HDC hdc)
4646 HDC hdcMem;
4647 X_PHYSBITMAP *physBitmap;
4648 Pixmap orig_pixmap;
4649 HBITMAP hBmp = 0;
4650 HGLOBAL hPackedDIB = 0;
4651 Window root;
4652 int x,y; /* Unused */
4653 unsigned border_width; /* Unused */
4654 unsigned int depth, width, height;
4656 /* Get the Pixmap dimensions and bit depth */
4657 wine_tsx11_lock();
4658 if (!XGetGeometry(gdi_display, pixmap, &root, &x, &y, &width, &height,
4659 &border_width, &depth)) depth = 0;
4660 wine_tsx11_unlock();
4661 if (!pixmap_formats[depth]) return 0;
4663 TRACE("\tPixmap properties: width=%d, height=%d, depth=%d\n",
4664 width, height, depth);
4667 * Create an HBITMAP with the same dimensions and BPP as the pixmap,
4668 * and make it a container for the pixmap passed.
4670 if (!(hBmp = CreateBitmap( width, height, 1, pixmap_formats[depth]->bits_per_pixel, NULL ))) return 0;
4672 /* force bitmap to be owned by a screen DC */
4673 hdcMem = CreateCompatibleDC( hdc );
4674 SelectObject( hdcMem, SelectObject( hdcMem, hBmp ));
4675 DeleteDC( hdcMem );
4677 physBitmap = X11DRV_get_phys_bitmap( hBmp );
4679 /* swap the new pixmap in */
4680 orig_pixmap = physBitmap->pixmap;
4681 physBitmap->pixmap = pixmap;
4684 * Create a packed DIB from the Pixmap wrapper bitmap created above.
4685 * A packed DIB contains a BITMAPINFO structure followed immediately by
4686 * an optional color palette and the pixel data.
4688 hPackedDIB = X11DRV_DIB_CreateDIBFromBitmap(hdc, hBmp);
4690 /* we can now get rid of the HBITMAP and its original pixmap */
4691 physBitmap->pixmap = orig_pixmap;
4692 DeleteObject(hBmp);
4694 TRACE("\tReturning packed DIB %p\n", hPackedDIB);
4695 return hPackedDIB;
4699 /**************************************************************************
4700 * X11DRV_DIB_CreatePixmapFromDIB
4702 * Creates a Pixmap from a packed DIB
4704 Pixmap X11DRV_DIB_CreatePixmapFromDIB( HGLOBAL hPackedDIB, HDC hdc )
4706 Pixmap pixmap;
4707 X_PHYSBITMAP *physBitmap;
4708 HBITMAP hBmp;
4709 LPBITMAPINFO pbmi;
4711 /* Create a DDB from the DIB */
4713 pbmi = GlobalLock(hPackedDIB);
4714 hBmp = CreateDIBitmap(hdc, &pbmi->bmiHeader, CBM_INIT,
4715 (LPBYTE)pbmi + bitmap_info_size( pbmi, DIB_RGB_COLORS ),
4716 pbmi, DIB_RGB_COLORS);
4717 GlobalUnlock(hPackedDIB);
4719 /* clear the physBitmap so that we can steal its pixmap */
4720 physBitmap = X11DRV_get_phys_bitmap( hBmp );
4721 pixmap = physBitmap->pixmap;
4722 physBitmap->pixmap = 0;
4724 /* Delete the DDB we created earlier now that we have stolen its pixmap */
4725 DeleteObject(hBmp);
4727 TRACE("Returning Pixmap %lx\n", pixmap);
4728 return pixmap;