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