In X11DRV_DIB_SetImageBits avoid BadMatch errors when calling
[wine.git] / dlls / x11drv / dib.c
blobe9aef6f8b9311bcca71a50e33af51dea9a02e124
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 "wingdi.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 static INT X11DRV_DIB_Coerce(X_PHYSBITMAP *,INT,BOOL);
88 static INT X11DRV_DIB_Lock(X_PHYSBITMAP *,INT,BOOL);
89 static void X11DRV_DIB_Unlock(X_PHYSBITMAP *,BOOL);
91 /*
92 Some of the following helper functions are duplicated in
93 dlls/gdi/dib.c
96 /***********************************************************************
97 * X11DRV_DIB_GetXImageWidthBytes
99 * Return the width of an X image in bytes
101 inline static int X11DRV_DIB_GetXImageWidthBytes( int width, int depth )
103 if (!depth || depth > 32) goto error;
105 if (!ximageDepthTable[depth-1])
107 XImage *testimage = XCreateImage( gdi_display, visual, depth,
108 ZPixmap, 0, NULL, 1, 1, 32, 20 );
109 if (testimage)
111 ximageDepthTable[depth-1] = testimage->bits_per_pixel;
112 XDestroyImage( testimage );
114 else ximageDepthTable[depth-1] = -1;
116 if (ximageDepthTable[depth-1] != -1)
117 return (4 * ((width * ximageDepthTable[depth-1] + 31) / 32));
119 error:
120 WARN( "(%d): Unsupported depth\n", depth );
121 return 4 * width;
125 /***********************************************************************
126 * X11DRV_DIB_GetDIBWidthBytes
128 * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
130 static int X11DRV_DIB_GetDIBWidthBytes( int width, int depth )
132 int words;
134 switch(depth)
136 case 1: words = (width + 31) / 32; break;
137 case 4: words = (width + 7) / 8; break;
138 case 8: words = (width + 3) / 4; break;
139 case 15:
140 case 16: words = (width + 1) / 2; break;
141 case 24: words = (width * 3 + 3) / 4; break;
142 default:
143 WARN("(%d): Unsupported depth\n", depth );
144 /* fall through */
145 case 32:
146 words = width;
148 return 4 * words;
152 /***********************************************************************
153 * X11DRV_DIB_GetDIBImageBytes
155 * Return the number of bytes used to hold the image in a DIB bitmap.
157 static int X11DRV_DIB_GetDIBImageBytes( int width, int height, int depth )
159 return X11DRV_DIB_GetDIBWidthBytes( width, depth ) * abs( height );
163 /***********************************************************************
164 * X11DRV_DIB_BitmapInfoSize
166 * Return the size of the bitmap info structure including color table.
168 int X11DRV_DIB_BitmapInfoSize( const BITMAPINFO * info, WORD coloruse )
170 unsigned int colors;
172 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
174 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
175 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
176 return sizeof(BITMAPCOREHEADER) + colors *
177 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
179 else /* assume BITMAPINFOHEADER */
181 colors = info->bmiHeader.biClrUsed;
182 if (!colors && (info->bmiHeader.biBitCount <= 8))
183 colors = 1 << info->bmiHeader.biBitCount;
184 return sizeof(BITMAPINFOHEADER) + colors *
185 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
190 /***********************************************************************
191 * X11DRV_DIB_CreateXImage
193 * Create an X image.
195 XImage *X11DRV_DIB_CreateXImage( int width, int height, int depth )
197 int width_bytes;
198 XImage *image;
200 wine_tsx11_lock();
201 width_bytes = X11DRV_DIB_GetXImageWidthBytes( width, depth );
202 image = XCreateImage( gdi_display, visual, depth, ZPixmap, 0,
203 calloc( height, width_bytes ),
204 width, height, 32, width_bytes );
205 wine_tsx11_unlock();
206 return image;
210 /***********************************************************************
211 * DIB_GetBitmapInfoEx
213 * Get the info from a bitmap header.
214 * Return 1 for INFOHEADER, 0 for COREHEADER, -1 for error.
216 static int DIB_GetBitmapInfoEx( const BITMAPINFOHEADER *header, LONG *width,
217 LONG *height, WORD *planes, WORD *bpp,
218 WORD *compr, DWORD *size )
220 if (header->biSize == sizeof(BITMAPCOREHEADER))
222 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)header;
223 *width = core->bcWidth;
224 *height = core->bcHeight;
225 *planes = core->bcPlanes;
226 *bpp = core->bcBitCount;
227 *compr = 0;
228 *size = 0;
229 return 0;
231 if (header->biSize >= sizeof(BITMAPINFOHEADER))
233 *width = header->biWidth;
234 *height = header->biHeight;
235 *planes = header->biPlanes;
236 *bpp = header->biBitCount;
237 *compr = header->biCompression;
238 *size = header->biSizeImage;
239 return 1;
241 ERR("(%ld): unknown/wrong size for header\n", header->biSize );
242 return -1;
246 /***********************************************************************
247 * DIB_GetBitmapInfo
249 * Get the info from a bitmap header.
250 * Return 1 for INFOHEADER, 0 for COREHEADER, -1 for error.
252 static int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
253 LONG *height, WORD *bpp, WORD *compr )
255 WORD planes;
256 DWORD size;
258 return DIB_GetBitmapInfoEx( header, width, height, &planes, bpp, compr, &size);
262 /***********************************************************************
263 * X11DRV_DIB_GenColorMap
265 * Fills the color map of a bitmap palette. Should not be called
266 * for a >8-bit deep bitmap.
268 int *X11DRV_DIB_GenColorMap( X11DRV_PDEVICE *physDev, int *colorMapping,
269 WORD coloruse, WORD depth, BOOL quads,
270 const void *colorPtr, int start, int end )
272 int i;
274 if (coloruse == DIB_RGB_COLORS)
276 if (quads)
278 const RGBQUAD * rgb = (const RGBQUAD *)colorPtr;
280 if (depth == 1) /* Monochrome */
281 for (i = start; i < end; i++, rgb++)
282 colorMapping[i] = (rgb->rgbRed + rgb->rgbGreen +
283 rgb->rgbBlue > 255*3/2);
284 else
285 for (i = start; i < end; i++, rgb++)
286 colorMapping[i] = X11DRV_PALETTE_ToPhysical( physDev, RGB(rgb->rgbRed,
287 rgb->rgbGreen,
288 rgb->rgbBlue));
290 else
292 const RGBTRIPLE * rgb = (const RGBTRIPLE *)colorPtr;
294 if (depth == 1) /* Monochrome */
295 for (i = start; i < end; i++, rgb++)
296 colorMapping[i] = (rgb->rgbtRed + rgb->rgbtGreen +
297 rgb->rgbtBlue > 255*3/2);
298 else
299 for (i = start; i < end; i++, rgb++)
300 colorMapping[i] = X11DRV_PALETTE_ToPhysical( physDev, RGB(rgb->rgbtRed,
301 rgb->rgbtGreen,
302 rgb->rgbtBlue));
305 else /* DIB_PAL_COLORS */
307 if (colorPtr) {
308 const WORD * index = (const WORD *)colorPtr;
310 for (i = start; i < end; i++, index++)
311 colorMapping[i] = X11DRV_PALETTE_ToPhysical( physDev, PALETTEINDEX(*index) );
312 } else {
313 for (i = start; i < end; i++)
314 colorMapping[i] = X11DRV_PALETTE_ToPhysical( physDev, PALETTEINDEX(i) );
318 return colorMapping;
321 /***********************************************************************
322 * X11DRV_DIB_BuildColorMap
324 * Build the color map from the bitmap palette. Should not be called
325 * for a >8-bit deep bitmap.
327 int *X11DRV_DIB_BuildColorMap( X11DRV_PDEVICE *physDev, WORD coloruse, WORD depth,
328 const BITMAPINFO *info, int *nColors )
330 unsigned int colors;
331 BOOL isInfo;
332 const void *colorPtr;
333 int *colorMapping;
335 isInfo = info->bmiHeader.biSize != sizeof(BITMAPCOREHEADER);
337 if (isInfo)
339 colors = info->bmiHeader.biClrUsed;
340 if (!colors) colors = 1 << info->bmiHeader.biBitCount;
342 else
344 colors = 1 << ((const BITMAPCOREHEADER *)info)->bcBitCount;
347 colorPtr = (const BYTE*) info + (WORD) info->bmiHeader.biSize;
349 if (colors > 256)
351 ERR("called with >256 colors!\n");
352 return NULL;
355 /* just so CopyDIBSection doesn't have to create an identity palette */
356 if (coloruse == (WORD)-1) colorPtr = NULL;
358 if (!(colorMapping = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(int) )))
359 return NULL;
361 *nColors = colors;
362 return X11DRV_DIB_GenColorMap( physDev, colorMapping, coloruse, depth,
363 isInfo, colorPtr, 0, colors);
366 /***********************************************************************
367 * X11DRV_DIB_BuildColorTable
369 * Build the dib color table. This either keeps a copy of the bmiColors array if
370 * usage is DIB_RGB_COLORS, or looks up the palette indicies if usage is
371 * DIB_PAL_COLORS.
372 * Should not be called for a >8-bit deep bitmap.
374 static RGBQUAD *X11DRV_DIB_BuildColorTable( X11DRV_PDEVICE *physDev, WORD coloruse, WORD depth,
375 const BITMAPINFO *info )
377 RGBQUAD *colorTable;
378 unsigned int colors;
379 int i;
380 BOOL core_info = info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER);
382 if (core_info)
384 colors = 1 << ((BITMAPCOREINFO*) info)->bmciHeader.bcBitCount;
386 else
388 colors = info->bmiHeader.biClrUsed;
389 if (!colors) colors = 1 << info->bmiHeader.biBitCount;
392 if (colors > 256) {
393 ERR("called with >256 colors!\n");
394 return NULL;
397 if (!(colorTable = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(RGBQUAD) )))
398 return NULL;
400 if(coloruse == DIB_RGB_COLORS)
402 if (core_info)
404 /* Convert RGBTRIPLEs to RGBQUADs */
405 for (i=0; i < colors; i++)
407 colorTable[i].rgbRed = ((BITMAPCOREINFO*) info)->bmciColors[i].rgbtRed;
408 colorTable[i].rgbGreen = ((BITMAPCOREINFO*) info)->bmciColors[i].rgbtGreen;
409 colorTable[i].rgbBlue = ((BITMAPCOREINFO*) info)->bmciColors[i].rgbtBlue;
410 colorTable[i].rgbReserved = 0;
413 else
415 memcpy(colorTable, (LPBYTE) info + (WORD) info->bmiHeader.biSize, colors * sizeof(RGBQUAD));
418 else
420 HPALETTE hpal = GetCurrentObject(physDev->hdc, OBJ_PAL);
421 PALETTEENTRY * pal_ents;
422 WORD *index = (WORD*) ((LPBYTE) info + (WORD) info->bmiHeader.biSize);
423 int logcolors, entry;
425 logcolors = GetPaletteEntries( hpal, 0, 0, NULL );
426 pal_ents = HeapAlloc(GetProcessHeap(), 0, logcolors * sizeof(*pal_ents));
427 logcolors = GetPaletteEntries( hpal, 0, logcolors, pal_ents );
429 for(i = 0; i < colors; i++, index++)
431 entry = *index % logcolors;
432 colorTable[i].rgbRed = pal_ents[entry].peRed;
433 colorTable[i].rgbGreen = pal_ents[entry].peGreen;
434 colorTable[i].rgbBlue = pal_ents[entry].peBlue;
435 colorTable[i].rgbReserved = 0;
438 HeapFree(GetProcessHeap(), 0, pal_ents);
440 return colorTable;
444 /***********************************************************************
445 * X11DRV_DIB_MapColor
447 int X11DRV_DIB_MapColor( int *physMap, int nPhysMap, int phys, int oldcol )
449 unsigned int color;
451 if ((oldcol < nPhysMap) && (physMap[oldcol] == phys))
452 return oldcol;
454 for (color = 0; color < nPhysMap; color++)
455 if (physMap[color] == phys)
456 return color;
458 WARN("Strange color %08x\n", phys);
459 return 0;
463 /*********************************************************************
464 * X11DRV_DIB_GetNearestIndex
466 * Helper for X11DRV_DIB_GetDIBits.
467 * Returns the nearest colour table index for a given RGB.
468 * Nearest is defined by minimizing the sum of the squares.
470 static INT X11DRV_DIB_GetNearestIndex(RGBQUAD *colormap, int numColors, BYTE r, BYTE g, BYTE b)
472 INT i, best = -1, diff, bestdiff = -1;
473 RGBQUAD *color;
475 for(color = colormap, i = 0; i < numColors; color++, i++) {
476 diff = (r - color->rgbRed) * (r - color->rgbRed) +
477 (g - color->rgbGreen) * (g - color->rgbGreen) +
478 (b - color->rgbBlue) * (b - color->rgbBlue);
479 if(diff == 0)
480 return i;
481 if(best == -1 || diff < bestdiff) {
482 best = i;
483 bestdiff = diff;
486 return best;
488 /*********************************************************************
489 * X11DRV_DIB_MaskToShift
491 * Helper for X11DRV_DIB_GetDIBits.
492 * Returns the by how many bits to shift a given color so that it is
493 * in the proper position.
495 INT X11DRV_DIB_MaskToShift(DWORD mask)
497 int shift;
499 if (mask==0)
500 return 0;
502 shift=0;
503 while ((mask&1)==0) {
504 mask>>=1;
505 shift++;
507 return shift;
510 /***********************************************************************
511 * X11DRV_DIB_SetImageBits_1
513 * SetDIBits for a 1-bit deep DIB.
515 static void X11DRV_DIB_SetImageBits_1( int lines, const BYTE *srcbits,
516 DWORD srcwidth, DWORD dstwidth, int left,
517 int *colors, XImage *bmpImage, DWORD linebytes)
519 int h, width;
520 const BYTE* srcbyte;
521 BYTE srcval, extra;
522 DWORD i, x;
524 if (lines < 0 ) {
525 lines = -lines;
526 srcbits = srcbits + linebytes * (lines - 1);
527 linebytes = -linebytes;
530 if ((extra = (left & 7)) != 0) {
531 left &= ~7;
532 dstwidth += extra;
534 srcbits += left >> 3;
535 width = min(srcwidth, dstwidth);
537 /* ==== pal 1 dib -> any bmp format ==== */
538 for (h = lines-1; h >=0; h--) {
539 srcbyte=srcbits;
540 /* FIXME: should avoid putting x<left pixels (minor speed issue) */
541 for (i = width/8, x = left; i > 0; i--) {
542 srcval=*srcbyte++;
543 XPutPixel( bmpImage, x++, h, colors[ srcval >> 7] );
544 XPutPixel( bmpImage, x++, h, colors[(srcval >> 6) & 1] );
545 XPutPixel( bmpImage, x++, h, colors[(srcval >> 5) & 1] );
546 XPutPixel( bmpImage, x++, h, colors[(srcval >> 4) & 1] );
547 XPutPixel( bmpImage, x++, h, colors[(srcval >> 3) & 1] );
548 XPutPixel( bmpImage, x++, h, colors[(srcval >> 2) & 1] );
549 XPutPixel( bmpImage, x++, h, colors[(srcval >> 1) & 1] );
550 XPutPixel( bmpImage, x++, h, colors[ srcval & 1] );
552 if (width % 8){
553 srcval=*srcbyte;
554 switch (width & 7)
556 case 7: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
557 case 6: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
558 case 5: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
559 case 4: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
560 case 3: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
561 case 2: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
562 case 1: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]);
565 srcbits += linebytes;
569 /***********************************************************************
570 * X11DRV_DIB_GetImageBits_1
572 * GetDIBits for a 1-bit deep DIB.
574 static void X11DRV_DIB_GetImageBits_1( int lines, BYTE *dstbits,
575 DWORD dstwidth, DWORD srcwidth,
576 RGBQUAD *colors, PALETTEENTRY *srccolors,
577 XImage *bmpImage, DWORD linebytes )
579 DWORD x;
580 int h, width = min(dstwidth, srcwidth);
582 if (lines < 0 ) {
583 lines = -lines;
584 dstbits = dstbits + linebytes * (lines - 1);
585 linebytes = -linebytes;
588 switch (bmpImage->depth)
590 case 1:
591 case 4:
592 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
593 /* ==== pal 1 or 4 bmp -> pal 1 dib ==== */
594 BYTE* dstbyte;
596 for (h=lines-1; h>=0; h--) {
597 BYTE dstval;
598 dstbyte=dstbits;
599 dstval=0;
600 for (x=0; x<width; x++) {
601 PALETTEENTRY srcval;
602 srcval=srccolors[XGetPixel(bmpImage, x, h)];
603 dstval|=(X11DRV_DIB_GetNearestIndex
604 (colors, 2,
605 srcval.peRed,
606 srcval.peGreen,
607 srcval.peBlue) << (7 - (x & 7)));
608 if ((x&7)==7) {
609 *dstbyte++=dstval;
610 dstval=0;
613 if ((width&7)!=0) {
614 *dstbyte=dstval;
616 dstbits += linebytes;
618 } else {
619 goto notsupported;
621 break;
623 case 8:
624 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
625 /* ==== pal 8 bmp -> pal 1 dib ==== */
626 const void* srcbits;
627 const BYTE* srcpixel;
628 BYTE* dstbyte;
630 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
632 for (h=0; h<lines; h++) {
633 BYTE dstval;
634 srcpixel=srcbits;
635 dstbyte=dstbits;
636 dstval=0;
637 for (x=0; x<width; x++) {
638 PALETTEENTRY srcval;
639 srcval=srccolors[(int)*srcpixel++];
640 dstval|=(X11DRV_DIB_GetNearestIndex
641 (colors, 2,
642 srcval.peRed,
643 srcval.peGreen,
644 srcval.peBlue) << (7-(x&7)) );
645 if ((x&7)==7) {
646 *dstbyte++=dstval;
647 dstval=0;
650 if ((width&7)!=0) {
651 *dstbyte=dstval;
653 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
654 dstbits += linebytes;
656 } else {
657 goto notsupported;
659 break;
661 case 15:
662 case 16:
664 const void* srcbits;
665 const WORD* srcpixel;
666 BYTE* dstbyte;
668 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
670 if (bmpImage->green_mask==0x03e0) {
671 if (bmpImage->red_mask==0x7c00) {
672 /* ==== rgb 555 bmp -> pal 1 dib ==== */
673 for (h=0; h<lines; h++) {
674 BYTE dstval;
675 srcpixel=srcbits;
676 dstbyte=dstbits;
677 dstval=0;
678 for (x=0; x<width; x++) {
679 WORD srcval;
680 srcval=*srcpixel++;
681 dstval|=(X11DRV_DIB_GetNearestIndex
682 (colors, 2,
683 ((srcval >> 7) & 0xf8) | /* r */
684 ((srcval >> 12) & 0x07),
685 ((srcval >> 2) & 0xf8) | /* g */
686 ((srcval >> 7) & 0x07),
687 ((srcval << 3) & 0xf8) | /* b */
688 ((srcval >> 2) & 0x07) ) << (7-(x&7)) );
689 if ((x&7)==7) {
690 *dstbyte++=dstval;
691 dstval=0;
694 if ((width&7)!=0) {
695 *dstbyte=dstval;
697 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
698 dstbits += linebytes;
700 } else if (bmpImage->blue_mask==0x7c00) {
701 /* ==== bgr 555 bmp -> pal 1 dib ==== */
702 for (h=0; h<lines; h++) {
703 WORD dstval;
704 srcpixel=srcbits;
705 dstbyte=dstbits;
706 dstval=0;
707 for (x=0; x<width; x++) {
708 BYTE srcval;
709 srcval=*srcpixel++;
710 dstval|=(X11DRV_DIB_GetNearestIndex
711 (colors, 2,
712 ((srcval << 3) & 0xf8) | /* r */
713 ((srcval >> 2) & 0x07),
714 ((srcval >> 2) & 0xf8) | /* g */
715 ((srcval >> 7) & 0x07),
716 ((srcval >> 7) & 0xf8) | /* b */
717 ((srcval >> 12) & 0x07) ) << (7-(x&7)) );
718 if ((x&7)==7) {
719 *dstbyte++=dstval;
720 dstval=0;
723 if ((width&7)!=0) {
724 *dstbyte=dstval;
726 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
727 dstbits += linebytes;
729 } else {
730 goto notsupported;
732 } else if (bmpImage->green_mask==0x07e0) {
733 if (bmpImage->red_mask==0xf800) {
734 /* ==== rgb 565 bmp -> pal 1 dib ==== */
735 for (h=0; h<lines; h++) {
736 BYTE dstval;
737 srcpixel=srcbits;
738 dstbyte=dstbits;
739 dstval=0;
740 for (x=0; x<width; x++) {
741 WORD srcval;
742 srcval=*srcpixel++;
743 dstval|=(X11DRV_DIB_GetNearestIndex
744 (colors, 2,
745 ((srcval >> 8) & 0xf8) | /* r */
746 ((srcval >> 13) & 0x07),
747 ((srcval >> 3) & 0xfc) | /* g */
748 ((srcval >> 9) & 0x03),
749 ((srcval << 3) & 0xf8) | /* b */
750 ((srcval >> 2) & 0x07) ) << (7-(x&7)) );
751 if ((x&7)==7) {
752 *dstbyte++=dstval;
753 dstval=0;
756 if ((width&7)!=0) {
757 *dstbyte=dstval;
759 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
760 dstbits += linebytes;
762 } else if (bmpImage->blue_mask==0xf800) {
763 /* ==== bgr 565 bmp -> pal 1 dib ==== */
764 for (h=0; h<lines; h++) {
765 BYTE dstval;
766 srcpixel=srcbits;
767 dstbyte=dstbits;
768 dstval=0;
769 for (x=0; x<width; x++) {
770 WORD srcval;
771 srcval=*srcpixel++;
772 dstval|=(X11DRV_DIB_GetNearestIndex
773 (colors, 2,
774 ((srcval << 3) & 0xf8) | /* r */
775 ((srcval >> 2) & 0x07),
776 ((srcval >> 3) & 0xfc) | /* g */
777 ((srcval >> 9) & 0x03),
778 ((srcval >> 8) & 0xf8) | /* b */
779 ((srcval >> 13) & 0x07) ) << (7-(x&7)) );
780 if ((x&7)==7) {
781 *dstbyte++=dstval;
782 dstval=0;
785 if ((width&7)!=0) {
786 *dstbyte=dstval;
788 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
789 dstbits += linebytes;
791 } else {
792 goto notsupported;
794 } else {
795 goto notsupported;
798 break;
800 case 24:
801 case 32:
803 const void* srcbits;
804 const BYTE *srcbyte;
805 BYTE* dstbyte;
806 int bytes_per_pixel;
808 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
809 bytes_per_pixel=(bmpImage->bits_per_pixel==24?3:4);
811 if (bmpImage->green_mask!=0x00ff00 ||
812 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
813 goto notsupported;
814 } else if (bmpImage->blue_mask==0xff) {
815 /* ==== rgb 888 or 0888 bmp -> pal 1 dib ==== */
816 for (h=0; h<lines; h++) {
817 BYTE dstval;
818 srcbyte=srcbits;
819 dstbyte=dstbits;
820 dstval=0;
821 for (x=0; x<width; x++) {
822 dstval|=(X11DRV_DIB_GetNearestIndex
823 (colors, 2,
824 srcbyte[2],
825 srcbyte[1],
826 srcbyte[0]) << (7-(x&7)) );
827 srcbyte+=bytes_per_pixel;
828 if ((x&7)==7) {
829 *dstbyte++=dstval;
830 dstval=0;
833 if ((width&7)!=0) {
834 *dstbyte=dstval;
836 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
837 dstbits += linebytes;
839 } else {
840 /* ==== bgr 888 or 0888 bmp -> pal 1 dib ==== */
841 for (h=0; h<lines; h++) {
842 BYTE dstval;
843 srcbyte=srcbits;
844 dstbyte=dstbits;
845 dstval=0;
846 for (x=0; x<width; x++) {
847 dstval|=(X11DRV_DIB_GetNearestIndex
848 (colors, 2,
849 srcbyte[0],
850 srcbyte[1],
851 srcbyte[2]) << (7-(x&7)) );
852 srcbyte+=bytes_per_pixel;
853 if ((x&7)==7) {
854 *dstbyte++=dstval;
855 dstval=0;
858 if ((width&7)!=0) {
859 *dstbyte=dstval;
861 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
862 dstbits += linebytes;
866 break;
868 default:
869 notsupported:
871 BYTE* dstbyte;
872 unsigned long white = (1 << bmpImage->bits_per_pixel) - 1;
874 /* ==== any bmp format -> pal 1 dib ==== */
875 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 1 bit DIB\n",
876 bmpImage->bits_per_pixel, bmpImage->red_mask,
877 bmpImage->green_mask, bmpImage->blue_mask );
879 for (h=lines-1; h>=0; h--) {
880 BYTE dstval;
881 dstbyte=dstbits;
882 dstval=0;
883 for (x=0; x<width; x++) {
884 dstval|=(XGetPixel( bmpImage, x, h) >= white) << (7 - (x&7));
885 if ((x&7)==7) {
886 *dstbyte++=dstval;
887 dstval=0;
890 if ((width&7)!=0) {
891 *dstbyte=dstval;
893 dstbits += linebytes;
896 break;
900 /***********************************************************************
901 * X11DRV_DIB_SetImageBits_4
903 * SetDIBits for a 4-bit deep DIB.
905 static void X11DRV_DIB_SetImageBits_4( int lines, const BYTE *srcbits,
906 DWORD srcwidth, DWORD dstwidth, int left,
907 int *colors, XImage *bmpImage, DWORD linebytes)
909 int h, width;
910 const BYTE* srcbyte;
911 DWORD i, x;
913 if (lines < 0 ) {
914 lines = -lines;
915 srcbits = srcbits + linebytes * (lines - 1);
916 linebytes = -linebytes;
919 if (left & 1) {
920 left--;
921 dstwidth++;
923 srcbits += left >> 1;
924 width = min(srcwidth, dstwidth);
926 /* ==== pal 4 dib -> any bmp format ==== */
927 for (h = lines-1; h >= 0; h--) {
928 srcbyte=srcbits;
929 for (i = width/2, x = left; i > 0; i--) {
930 BYTE srcval=*srcbyte++;
931 XPutPixel( bmpImage, x++, h, colors[srcval >> 4] );
932 XPutPixel( bmpImage, x++, h, colors[srcval & 0x0f] );
934 if (width & 1)
935 XPutPixel( bmpImage, x, h, colors[*srcbyte >> 4] );
936 srcbits += linebytes;
942 /***********************************************************************
943 * X11DRV_DIB_GetImageBits_4
945 * GetDIBits for a 4-bit deep DIB.
947 static void X11DRV_DIB_GetImageBits_4( int lines, BYTE *dstbits,
948 DWORD srcwidth, DWORD dstwidth,
949 RGBQUAD *colors, PALETTEENTRY *srccolors,
950 XImage *bmpImage, DWORD linebytes )
952 DWORD x;
953 int h, width = min(srcwidth, dstwidth);
954 BYTE *bits;
956 if (lines < 0 )
958 lines = -lines;
959 dstbits = dstbits + ( linebytes * (lines-1) );
960 linebytes = -linebytes;
963 bits = dstbits;
965 switch (bmpImage->depth) {
966 case 1:
967 case 4:
968 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
969 /* ==== pal 1 or 4 bmp -> pal 4 dib ==== */
970 BYTE* dstbyte;
972 for (h = lines-1; h >= 0; h--) {
973 BYTE dstval;
974 dstbyte=dstbits;
975 dstval=0;
976 for (x = 0; x < width; x++) {
977 PALETTEENTRY srcval;
978 srcval=srccolors[XGetPixel(bmpImage, x, h)];
979 dstval|=(X11DRV_DIB_GetNearestIndex
980 (colors, 16,
981 srcval.peRed,
982 srcval.peGreen,
983 srcval.peBlue) << (4-((x&1)<<2)));
984 if ((x&1)==1) {
985 *dstbyte++=dstval;
986 dstval=0;
989 if ((width&1)!=0) {
990 *dstbyte=dstval;
992 dstbits += linebytes;
994 } else {
995 goto notsupported;
997 break;
999 case 8:
1000 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
1001 /* ==== pal 8 bmp -> pal 4 dib ==== */
1002 const void* srcbits;
1003 const BYTE *srcpixel;
1004 BYTE* dstbyte;
1006 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1007 for (h=0; h<lines; h++) {
1008 BYTE dstval;
1009 srcpixel=srcbits;
1010 dstbyte=dstbits;
1011 dstval=0;
1012 for (x=0; x<width; x++) {
1013 PALETTEENTRY srcval;
1014 srcval = srccolors[(int)*srcpixel++];
1015 dstval|=(X11DRV_DIB_GetNearestIndex
1016 (colors, 16,
1017 srcval.peRed,
1018 srcval.peGreen,
1019 srcval.peBlue) << (4*(1-(x&1))) );
1020 if ((x&1)==1) {
1021 *dstbyte++=dstval;
1022 dstval=0;
1025 if ((width&1)!=0) {
1026 *dstbyte=dstval;
1028 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1029 dstbits += linebytes;
1031 } else {
1032 goto notsupported;
1034 break;
1036 case 15:
1037 case 16:
1039 const void* srcbits;
1040 const WORD* srcpixel;
1041 BYTE* dstbyte;
1043 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1045 if (bmpImage->green_mask==0x03e0) {
1046 if (bmpImage->red_mask==0x7c00) {
1047 /* ==== rgb 555 bmp -> pal 4 dib ==== */
1048 for (h=0; h<lines; h++) {
1049 BYTE dstval;
1050 srcpixel=srcbits;
1051 dstbyte=dstbits;
1052 dstval=0;
1053 for (x=0; x<width; x++) {
1054 WORD srcval;
1055 srcval=*srcpixel++;
1056 dstval|=(X11DRV_DIB_GetNearestIndex
1057 (colors, 16,
1058 ((srcval >> 7) & 0xf8) | /* r */
1059 ((srcval >> 12) & 0x07),
1060 ((srcval >> 2) & 0xf8) | /* g */
1061 ((srcval >> 7) & 0x07),
1062 ((srcval << 3) & 0xf8) | /* b */
1063 ((srcval >> 2) & 0x07) ) << ((1-(x&1))<<2) );
1064 if ((x&1)==1) {
1065 *dstbyte++=dstval;
1066 dstval=0;
1069 if ((width&1)!=0) {
1070 *dstbyte=dstval;
1072 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1073 dstbits += linebytes;
1075 } else if (bmpImage->blue_mask==0x7c00) {
1076 /* ==== bgr 555 bmp -> pal 4 dib ==== */
1077 for (h=0; h<lines; h++) {
1078 WORD dstval;
1079 srcpixel=srcbits;
1080 dstbyte=dstbits;
1081 dstval=0;
1082 for (x=0; x<width; x++) {
1083 WORD srcval;
1084 srcval=*srcpixel++;
1085 dstval|=(X11DRV_DIB_GetNearestIndex
1086 (colors, 16,
1087 ((srcval << 3) & 0xf8) | /* r */
1088 ((srcval >> 2) & 0x07),
1089 ((srcval >> 2) & 0xf8) | /* g */
1090 ((srcval >> 7) & 0x07),
1091 ((srcval >> 7) & 0xf8) | /* b */
1092 ((srcval >> 12) & 0x07) ) << ((1-(x&1))<<2) );
1093 if ((x&1)==1) {
1094 *dstbyte++=dstval;
1095 dstval=0;
1098 if ((width&1)!=0) {
1099 *dstbyte=dstval;
1101 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1102 dstbits += linebytes;
1104 } else {
1105 goto notsupported;
1107 } else if (bmpImage->green_mask==0x07e0) {
1108 if (bmpImage->red_mask==0xf800) {
1109 /* ==== rgb 565 bmp -> pal 4 dib ==== */
1110 for (h=0; h<lines; h++) {
1111 BYTE dstval;
1112 srcpixel=srcbits;
1113 dstbyte=dstbits;
1114 dstval=0;
1115 for (x=0; x<width; x++) {
1116 WORD srcval;
1117 srcval=*srcpixel++;
1118 dstval|=(X11DRV_DIB_GetNearestIndex
1119 (colors, 16,
1120 ((srcval >> 8) & 0xf8) | /* r */
1121 ((srcval >> 13) & 0x07),
1122 ((srcval >> 3) & 0xfc) | /* g */
1123 ((srcval >> 9) & 0x03),
1124 ((srcval << 3) & 0xf8) | /* b */
1125 ((srcval >> 2) & 0x07) ) << ((1-(x&1))<<2) );
1126 if ((x&1)==1) {
1127 *dstbyte++=dstval;
1128 dstval=0;
1131 if ((width&1)!=0) {
1132 *dstbyte=dstval;
1134 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1135 dstbits += linebytes;
1137 } else if (bmpImage->blue_mask==0xf800) {
1138 /* ==== bgr 565 bmp -> pal 4 dib ==== */
1139 for (h=0; h<lines; h++) {
1140 WORD dstval;
1141 srcpixel=srcbits;
1142 dstbyte=dstbits;
1143 dstval=0;
1144 for (x=0; x<width; x++) {
1145 WORD srcval;
1146 srcval=*srcpixel++;
1147 dstval|=(X11DRV_DIB_GetNearestIndex
1148 (colors, 16,
1149 ((srcval << 3) & 0xf8) | /* r */
1150 ((srcval >> 2) & 0x07),
1151 ((srcval >> 3) & 0xfc) | /* g */
1152 ((srcval >> 9) & 0x03),
1153 ((srcval >> 8) & 0xf8) | /* b */
1154 ((srcval >> 13) & 0x07) ) << ((1-(x&1))<<2) );
1155 if ((x&1)==1) {
1156 *dstbyte++=dstval;
1157 dstval=0;
1160 if ((width&1)!=0) {
1161 *dstbyte=dstval;
1163 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1164 dstbits += linebytes;
1166 } else {
1167 goto notsupported;
1169 } else {
1170 goto notsupported;
1173 break;
1175 case 24:
1176 if (bmpImage->bits_per_pixel==24) {
1177 const void* srcbits;
1178 const BYTE *srcbyte;
1179 BYTE* dstbyte;
1181 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1183 if (bmpImage->green_mask!=0x00ff00 ||
1184 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
1185 goto notsupported;
1186 } else if (bmpImage->blue_mask==0xff) {
1187 /* ==== rgb 888 bmp -> pal 4 dib ==== */
1188 for (h=0; h<lines; h++) {
1189 srcbyte=srcbits;
1190 dstbyte=dstbits;
1191 for (x=0; x<width/2; x++) {
1192 /* Do 2 pixels at a time */
1193 *dstbyte++=(X11DRV_DIB_GetNearestIndex
1194 (colors, 16,
1195 srcbyte[2],
1196 srcbyte[1],
1197 srcbyte[0]) << 4) |
1198 X11DRV_DIB_GetNearestIndex
1199 (colors, 16,
1200 srcbyte[5],
1201 srcbyte[4],
1202 srcbyte[3]);
1203 srcbyte+=6;
1205 if (width&1) {
1206 /* And the the odd pixel */
1207 *dstbyte++=(X11DRV_DIB_GetNearestIndex
1208 (colors, 16,
1209 srcbyte[2],
1210 srcbyte[1],
1211 srcbyte[0]) << 4);
1213 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1214 dstbits += linebytes;
1216 } else {
1217 /* ==== bgr 888 bmp -> pal 4 dib ==== */
1218 for (h=0; h<lines; h++) {
1219 srcbyte=srcbits;
1220 dstbyte=dstbits;
1221 for (x=0; x<width/2; x++) {
1222 /* Do 2 pixels at a time */
1223 *dstbyte++=(X11DRV_DIB_GetNearestIndex
1224 (colors, 16,
1225 srcbyte[0],
1226 srcbyte[1],
1227 srcbyte[2]) << 4) |
1228 X11DRV_DIB_GetNearestIndex
1229 (colors, 16,
1230 srcbyte[3],
1231 srcbyte[4],
1232 srcbyte[5]);
1233 srcbyte+=6;
1235 if (width&1) {
1236 /* And the the odd pixel */
1237 *dstbyte++=(X11DRV_DIB_GetNearestIndex
1238 (colors, 16,
1239 srcbyte[0],
1240 srcbyte[1],
1241 srcbyte[2]) << 4);
1243 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1244 dstbits += linebytes;
1247 break;
1249 /* Fall through */
1251 case 32:
1253 const void* srcbits;
1254 const BYTE *srcbyte;
1255 BYTE* dstbyte;
1257 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1259 if (bmpImage->green_mask!=0x00ff00 ||
1260 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
1261 goto notsupported;
1262 } else if (bmpImage->blue_mask==0xff) {
1263 /* ==== rgb 0888 bmp -> pal 4 dib ==== */
1264 for (h=0; h<lines; h++) {
1265 srcbyte=srcbits;
1266 dstbyte=dstbits;
1267 for (x=0; x<width/2; x++) {
1268 /* Do 2 pixels at a time */
1269 *dstbyte++=(X11DRV_DIB_GetNearestIndex
1270 (colors, 16,
1271 srcbyte[2],
1272 srcbyte[1],
1273 srcbyte[0]) << 4) |
1274 X11DRV_DIB_GetNearestIndex
1275 (colors, 16,
1276 srcbyte[6],
1277 srcbyte[5],
1278 srcbyte[4]);
1279 srcbyte+=8;
1281 if (width&1) {
1282 /* And the the odd pixel */
1283 *dstbyte++=(X11DRV_DIB_GetNearestIndex
1284 (colors, 16,
1285 srcbyte[2],
1286 srcbyte[1],
1287 srcbyte[0]) << 4);
1289 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1290 dstbits += linebytes;
1292 } else {
1293 /* ==== bgr 0888 bmp -> pal 4 dib ==== */
1294 for (h=0; h<lines; h++) {
1295 srcbyte=srcbits;
1296 dstbyte=dstbits;
1297 for (x=0; x<width/2; x++) {
1298 /* Do 2 pixels at a time */
1299 *dstbyte++=(X11DRV_DIB_GetNearestIndex
1300 (colors, 16,
1301 srcbyte[0],
1302 srcbyte[1],
1303 srcbyte[2]) << 4) |
1304 X11DRV_DIB_GetNearestIndex
1305 (colors, 16,
1306 srcbyte[4],
1307 srcbyte[5],
1308 srcbyte[6]);
1309 srcbyte+=8;
1311 if (width&1) {
1312 /* And the the odd pixel */
1313 *dstbyte++=(X11DRV_DIB_GetNearestIndex
1314 (colors, 16,
1315 srcbyte[0],
1316 srcbyte[1],
1317 srcbyte[2]) << 4);
1319 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1320 dstbits += linebytes;
1324 break;
1326 default:
1327 notsupported:
1329 BYTE* dstbyte;
1331 /* ==== any bmp format -> pal 4 dib ==== */
1332 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 4 bit DIB\n",
1333 bmpImage->bits_per_pixel, bmpImage->red_mask,
1334 bmpImage->green_mask, bmpImage->blue_mask );
1335 for (h=lines-1; h>=0; h--) {
1336 dstbyte=dstbits;
1337 for (x=0; x<(width & ~1); x+=2) {
1338 *dstbyte++=(X11DRV_DIB_MapColor((int*)colors, 16, XGetPixel(bmpImage, x, h), 0) << 4) |
1339 X11DRV_DIB_MapColor((int*)colors, 16, XGetPixel(bmpImage, x+1, h), 0);
1341 if (width & 1) {
1342 *dstbyte=(X11DRV_DIB_MapColor((int *)colors, 16, XGetPixel(bmpImage, x, h), 0) << 4);
1344 dstbits += linebytes;
1347 break;
1351 /***********************************************************************
1352 * X11DRV_DIB_SetImageBits_RLE4
1354 * SetDIBits for a 4-bit deep compressed DIB.
1356 static void X11DRV_DIB_SetImageBits_RLE4( int lines, const BYTE *bits,
1357 DWORD srcwidth, DWORD dstwidth,
1358 int left, int *colors,
1359 XImage *bmpImage )
1361 unsigned int x = 0, width = min(srcwidth, dstwidth);
1362 int y = lines - 1, c, length;
1363 const BYTE *begin = bits;
1365 while (y >= 0)
1367 length = *bits++;
1368 if (length) { /* encoded */
1369 c = *bits++;
1370 while (length--) {
1371 if (x >= (left + width)) break;
1372 if( x >= left) XPutPixel(bmpImage, x, y, colors[c >> 4]);
1373 x++;
1374 if (!length--) break;
1375 if (x >= (left + width)) break;
1376 if( x >= left) XPutPixel(bmpImage, x, y, colors[c & 0xf]);
1377 x++;
1379 } else {
1380 length = *bits++;
1381 switch (length)
1383 case RLE_EOL:
1384 x = 0;
1385 y--;
1386 break;
1388 case RLE_END:
1389 return;
1391 case RLE_DELTA:
1392 x += *bits++;
1393 y -= *bits++;
1394 break;
1396 default: /* absolute */
1397 while (length--) {
1398 c = *bits++;
1399 if (x >= left && x < (left + width))
1400 XPutPixel(bmpImage, x, y, colors[c >> 4]);
1401 x++;
1402 if (!length--) break;
1403 if (x >= left && x < (left + width))
1404 XPutPixel(bmpImage, x, y, colors[c & 0xf]);
1405 x++;
1407 if ((bits - begin) & 1)
1408 bits++;
1416 /***********************************************************************
1417 * X11DRV_DIB_SetImageBits_8
1419 * SetDIBits for an 8-bit deep DIB.
1421 static void X11DRV_DIB_SetImageBits_8( int lines, const BYTE *srcbits,
1422 DWORD srcwidth, DWORD dstwidth, int left,
1423 const int *colors, XImage *bmpImage,
1424 DWORD linebytes )
1426 DWORD x;
1427 int h, width = min(srcwidth, dstwidth);
1428 const BYTE* srcbyte;
1429 BYTE* dstbits;
1431 if (lines < 0 )
1433 lines = -lines;
1434 srcbits = srcbits + linebytes * (lines-1);
1435 linebytes = -linebytes;
1437 srcbits += left;
1438 srcbyte = srcbits;
1440 switch (bmpImage->depth) {
1441 case 15:
1442 case 16:
1443 #if defined(__i386__) && defined(__GNUC__)
1444 /* Some X servers might have 32 bit/ 16bit deep pixel */
1445 if (lines && width && (bmpImage->bits_per_pixel == 16) &&
1446 (ImageByteOrder(gdi_display)==LSBFirst) )
1448 dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
1449 /* FIXME: Does this really handle all these cases correctly? */
1450 /* ==== pal 8 dib -> rgb or bgr 555 or 565 bmp ==== */
1451 for (h = lines ; h--; ) {
1452 int _cl1,_cl2; /* temp outputs for asm below */
1453 /* Borrowed from DirectDraw */
1454 __asm__ __volatile__(
1455 "xor %%eax,%%eax\n"
1456 "cld\n"
1457 "1:\n"
1458 " lodsb\n"
1459 " movw (%%edx,%%eax,4),%%ax\n"
1460 " stosw\n"
1461 " xor %%eax,%%eax\n"
1462 " loop 1b\n"
1463 :"=S" (srcbyte), "=D" (_cl1), "=c" (_cl2)
1464 :"S" (srcbyte),
1465 "D" (dstbits),
1466 "c" (width),
1467 "d" (colors)
1468 :"eax", "cc", "memory"
1470 srcbyte = (srcbits += linebytes);
1471 dstbits -= bmpImage->bytes_per_line;
1473 return;
1475 break;
1476 #endif
1477 case 24:
1478 case 32:
1479 #if defined(__i386__) && defined(__GNUC__)
1480 if (lines && width && (bmpImage->bits_per_pixel == 32) &&
1481 (ImageByteOrder(gdi_display)==LSBFirst) )
1483 dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
1484 /* FIXME: Does this really handle both cases correctly? */
1485 /* ==== pal 8 dib -> rgb or bgr 0888 bmp ==== */
1486 for (h = lines ; h--; ) {
1487 int _cl1,_cl2; /* temp outputs for asm below */
1488 /* Borrowed from DirectDraw */
1489 __asm__ __volatile__(
1490 "xor %%eax,%%eax\n"
1491 "cld\n"
1492 "1:\n"
1493 " lodsb\n"
1494 " movl (%%edx,%%eax,4),%%eax\n"
1495 " stosl\n"
1496 " xor %%eax,%%eax\n"
1497 " loop 1b\n"
1498 :"=S" (srcbyte), "=D" (_cl1), "=c" (_cl2)
1499 :"S" (srcbyte),
1500 "D" (dstbits),
1501 "c" (width),
1502 "d" (colors)
1503 :"eax", "cc", "memory"
1505 srcbyte = (srcbits += linebytes);
1506 dstbits -= bmpImage->bytes_per_line;
1508 return;
1510 break;
1511 #endif
1512 default:
1513 break; /* use slow generic case below */
1516 /* ==== pal 8 dib -> any bmp format ==== */
1517 for (h=lines-1; h>=0; h--) {
1518 for (x=left; x<width+left; x++) {
1519 XPutPixel(bmpImage, x, h, colors[*srcbyte++]);
1521 srcbyte = (srcbits += linebytes);
1525 /***********************************************************************
1526 * X11DRV_DIB_GetImageBits_8
1528 * GetDIBits for an 8-bit deep DIB.
1530 static void X11DRV_DIB_GetImageBits_8( int lines, BYTE *dstbits,
1531 DWORD srcwidth, DWORD dstwidth,
1532 RGBQUAD *colors, PALETTEENTRY *srccolors,
1533 XImage *bmpImage, DWORD linebytes )
1535 DWORD x;
1536 int h, width = min(srcwidth, dstwidth);
1537 BYTE* dstbyte;
1539 if (lines < 0 )
1541 lines = -lines;
1542 dstbits = dstbits + ( linebytes * (lines-1) );
1543 linebytes = -linebytes;
1547 * Hack for now
1548 * This condition is true when GetImageBits has been called by
1549 * UpdateDIBSection. For now, GetNearestIndex is too slow to support
1550 * 256 colormaps, so we'll just use for for GetDIBits calls.
1551 * (In somes cases, in a updateDIBSection, the returned colors are bad too)
1553 if (!srccolors) goto updatesection;
1555 switch (bmpImage->depth) {
1556 case 1:
1557 case 4:
1558 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
1560 /* ==== pal 1 bmp -> pal 8 dib ==== */
1561 /* ==== pal 4 bmp -> pal 8 dib ==== */
1562 for (h=lines-1; h>=0; h--) {
1563 dstbyte=dstbits;
1564 for (x=0; x<width; x++) {
1565 PALETTEENTRY srcval;
1566 srcval=srccolors[XGetPixel(bmpImage, x, h)];
1567 *dstbyte++=X11DRV_DIB_GetNearestIndex(colors, 256,
1568 srcval.peRed,
1569 srcval.peGreen,
1570 srcval.peBlue);
1572 dstbits += linebytes;
1574 } else {
1575 goto notsupported;
1577 break;
1579 case 8:
1580 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
1581 /* ==== pal 8 bmp -> pal 8 dib ==== */
1582 const void* srcbits;
1583 const BYTE* srcpixel;
1585 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1586 for (h=0; h<lines; h++) {
1587 srcpixel=srcbits;
1588 dstbyte=dstbits;
1589 for (x = 0; x < width; x++) {
1590 PALETTEENTRY srcval;
1591 srcval=srccolors[(int)*srcpixel++];
1592 *dstbyte++=X11DRV_DIB_GetNearestIndex(colors, 256,
1593 srcval.peRed,
1594 srcval.peGreen,
1595 srcval.peBlue);
1597 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1598 dstbits += linebytes;
1600 } else {
1601 goto notsupported;
1603 break;
1605 case 15:
1606 case 16:
1608 const void* srcbits;
1609 const WORD* srcpixel;
1610 BYTE* dstbyte;
1612 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1614 if (bmpImage->green_mask==0x03e0) {
1615 if (bmpImage->red_mask==0x7c00) {
1616 /* ==== rgb 555 bmp -> pal 8 dib ==== */
1617 for (h=0; h<lines; h++) {
1618 srcpixel=srcbits;
1619 dstbyte=dstbits;
1620 for (x=0; x<width; x++) {
1621 WORD srcval;
1622 srcval=*srcpixel++;
1623 *dstbyte++=X11DRV_DIB_GetNearestIndex
1624 (colors, 256,
1625 ((srcval >> 7) & 0xf8) | /* r */
1626 ((srcval >> 12) & 0x07),
1627 ((srcval >> 2) & 0xf8) | /* g */
1628 ((srcval >> 7) & 0x07),
1629 ((srcval << 3) & 0xf8) | /* b */
1630 ((srcval >> 2) & 0x07) );
1632 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1633 dstbits += linebytes;
1635 } else if (bmpImage->blue_mask==0x7c00) {
1636 /* ==== bgr 555 bmp -> pal 8 dib ==== */
1637 for (h=0; h<lines; h++) {
1638 srcpixel=srcbits;
1639 dstbyte=dstbits;
1640 for (x=0; x<width; x++) {
1641 WORD srcval;
1642 srcval=*srcpixel++;
1643 *dstbyte++=X11DRV_DIB_GetNearestIndex
1644 (colors, 256,
1645 ((srcval << 3) & 0xf8) | /* r */
1646 ((srcval >> 2) & 0x07),
1647 ((srcval >> 2) & 0xf8) | /* g */
1648 ((srcval >> 7) & 0x07),
1649 ((srcval >> 7) & 0xf8) | /* b */
1650 ((srcval >> 12) & 0x07) );
1652 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1653 dstbits += linebytes;
1655 } else {
1656 goto notsupported;
1658 } else if (bmpImage->green_mask==0x07e0) {
1659 if (bmpImage->red_mask==0xf800) {
1660 /* ==== rgb 565 bmp -> pal 8 dib ==== */
1661 for (h=0; h<lines; h++) {
1662 srcpixel=srcbits;
1663 dstbyte=dstbits;
1664 for (x=0; x<width; x++) {
1665 WORD srcval;
1666 srcval=*srcpixel++;
1667 *dstbyte++=X11DRV_DIB_GetNearestIndex
1668 (colors, 256,
1669 ((srcval >> 8) & 0xf8) | /* r */
1670 ((srcval >> 13) & 0x07),
1671 ((srcval >> 3) & 0xfc) | /* g */
1672 ((srcval >> 9) & 0x03),
1673 ((srcval << 3) & 0xf8) | /* b */
1674 ((srcval >> 2) & 0x07) );
1676 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1677 dstbits += linebytes;
1679 } else if (bmpImage->blue_mask==0xf800) {
1680 /* ==== bgr 565 bmp -> pal 8 dib ==== */
1681 for (h=0; h<lines; h++) {
1682 srcpixel=srcbits;
1683 dstbyte=dstbits;
1684 for (x=0; x<width; x++) {
1685 WORD srcval;
1686 srcval=*srcpixel++;
1687 *dstbyte++=X11DRV_DIB_GetNearestIndex
1688 (colors, 256,
1689 ((srcval << 3) & 0xf8) | /* r */
1690 ((srcval >> 2) & 0x07),
1691 ((srcval >> 3) & 0xfc) | /* g */
1692 ((srcval >> 9) & 0x03),
1693 ((srcval >> 8) & 0xf8) | /* b */
1694 ((srcval >> 13) & 0x07) );
1696 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1697 dstbits += linebytes;
1699 } else {
1700 goto notsupported;
1702 } else {
1703 goto notsupported;
1706 break;
1708 case 24:
1709 case 32:
1711 const void* srcbits;
1712 const BYTE *srcbyte;
1713 BYTE* dstbyte;
1714 int bytes_per_pixel;
1716 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1717 bytes_per_pixel=(bmpImage->bits_per_pixel==24?3:4);
1719 if (bmpImage->green_mask!=0x00ff00 ||
1720 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
1721 goto notsupported;
1722 } else if (bmpImage->blue_mask==0xff) {
1723 /* ==== rgb 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[2],
1731 srcbyte[1],
1732 srcbyte[0]);
1733 srcbyte+=bytes_per_pixel;
1735 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1736 dstbits += linebytes;
1738 } else {
1739 /* ==== bgr 888 or 0888 bmp -> pal 8 dib ==== */
1740 for (h=0; h<lines; h++) {
1741 srcbyte=srcbits;
1742 dstbyte=dstbits;
1743 for (x=0; x<width; x++) {
1744 *dstbyte++=X11DRV_DIB_GetNearestIndex
1745 (colors, 256,
1746 srcbyte[0],
1747 srcbyte[1],
1748 srcbyte[2]);
1749 srcbyte+=bytes_per_pixel;
1751 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
1752 dstbits += linebytes;
1756 break;
1758 default:
1759 notsupported:
1760 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 8 bit DIB\n",
1761 bmpImage->depth, bmpImage->red_mask,
1762 bmpImage->green_mask, bmpImage->blue_mask );
1763 updatesection:
1764 /* ==== any bmp format -> pal 8 dib ==== */
1765 for (h=lines-1; h>=0; h--) {
1766 dstbyte=dstbits;
1767 for (x=0; x<width; x++) {
1768 *dstbyte=X11DRV_DIB_MapColor
1769 ((int*)colors, 256,
1770 XGetPixel(bmpImage, x, h), *dstbyte);
1771 dstbyte++;
1773 dstbits += linebytes;
1775 break;
1779 /***********************************************************************
1780 * X11DRV_DIB_SetImageBits_RLE8
1782 * SetDIBits for an 8-bit deep compressed DIB.
1784 * This function rewritten 941113 by James Youngman. WINE blew out when I
1785 * first ran it because my desktop wallpaper is a (large) RLE8 bitmap.
1787 * This was because the algorithm assumed that all RLE8 bitmaps end with the
1788 * 'End of bitmap' escape code. This code is very much laxer in what it
1789 * allows to end the expansion. Possibly too lax. See the note by
1790 * case RleDelta. BTW, MS's documentation implies that a correct RLE8
1791 * bitmap should end with RleEnd, but on the other hand, software exists
1792 * that produces ones that don't and Windows 3.1 doesn't complain a bit
1793 * about it.
1795 * (No) apologies for my English spelling. [Emacs users: c-indent-level=4].
1796 * James A. Youngman <mbcstjy@afs.man.ac.uk>
1797 * [JAY]
1799 static void X11DRV_DIB_SetImageBits_RLE8( int lines, const BYTE *bits,
1800 DWORD srcwidth, DWORD dstwidth,
1801 int left, int *colors,
1802 XImage *bmpImage )
1804 unsigned int x; /* X-position on each line. Increases. */
1805 int y; /* Line #. Starts at lines-1, decreases */
1806 const BYTE *pIn = bits; /* Pointer to current position in bits */
1807 BYTE length; /* The length pf a run */
1808 BYTE escape_code; /* See enum Rle8_EscapeCodes.*/
1811 * Note that the bitmap data is stored by Windows starting at the
1812 * bottom line of the bitmap and going upwards. Within each line,
1813 * the data is stored left-to-right. That's the reason why line
1814 * goes from lines-1 to 0. [JAY]
1817 x = 0;
1818 y = lines - 1;
1819 while (y >= 0)
1821 length = *pIn++;
1824 * If the length byte is not zero (which is the escape value),
1825 * We have a run of length pixels all the same colour. The colour
1826 * index is stored next.
1828 * If the length byte is zero, we need to read the next byte to
1829 * know what to do. [JAY]
1831 if (length != 0)
1834 * [Run-Length] Encoded mode
1836 int color = colors[*pIn++];
1837 while (length-- && x < (left + dstwidth)) {
1838 if( x >= left) XPutPixel(bmpImage, x, y, color);
1839 x++;
1842 else
1845 * Escape codes (may be an absolute sequence though)
1847 escape_code = (*pIn++);
1848 switch(escape_code)
1850 case RLE_EOL:
1851 x = 0;
1852 y--;
1853 break;
1855 case RLE_END:
1856 /* Not all RLE8 bitmaps end with this code. For
1857 * example, Paint Shop Pro produces some that don't.
1858 * That's (I think) what caused the previous
1859 * implementation to fail. [JAY]
1861 return;
1863 case RLE_DELTA:
1864 x += (*pIn++);
1865 y -= (*pIn++);
1866 break;
1868 default: /* switch to absolute mode */
1869 length = escape_code;
1870 while (length--)
1872 int color = colors[*pIn++];
1873 if (x >= (left + dstwidth))
1875 pIn += length;
1876 break;
1878 if( x >= left) XPutPixel(bmpImage, x, y, color);
1879 x++;
1882 * If you think for a moment you'll realise that the
1883 * only time we could ever possibly read an odd
1884 * number of bytes is when there is a 0x00 (escape),
1885 * a value >0x02 (absolute mode) and then an odd-
1886 * length run. Therefore this is the only place we
1887 * need to worry about it. Everywhere else the
1888 * bytes are always read in pairs. [JAY]
1890 if (escape_code & 1) pIn++; /* Throw away the pad byte. */
1891 break;
1892 } /* switch (escape_code) : Escape sequence */
1898 /***********************************************************************
1899 * X11DRV_DIB_SetImageBits_16
1901 * SetDIBits for a 16-bit deep DIB.
1903 static void X11DRV_DIB_SetImageBits_16( int lines, const BYTE *srcbits,
1904 DWORD srcwidth, DWORD dstwidth, int left,
1905 X11DRV_PDEVICE *physDev, DWORD rSrc, DWORD gSrc, DWORD bSrc,
1906 XImage *bmpImage, DWORD linebytes )
1908 DWORD x;
1909 int h, width = min(srcwidth, dstwidth);
1910 const dib_conversions *convs = (bmpImage->byte_order == LSBFirst) ? &dib_normal : &dib_dst_byteswap;
1912 if (lines < 0 )
1914 lines = -lines;
1915 srcbits = srcbits + ( linebytes * (lines-1));
1916 linebytes = -linebytes;
1919 switch (bmpImage->depth)
1921 case 15:
1922 case 16:
1924 char* dstbits;
1926 srcbits=srcbits+left*2;
1927 dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
1929 if (bmpImage->green_mask==0x03e0) {
1930 if (gSrc==bmpImage->green_mask) {
1931 if (rSrc==bmpImage->red_mask) {
1932 /* ==== rgb 555 dib -> rgb 555 bmp ==== */
1933 /* ==== bgr 555 dib -> bgr 555 bmp ==== */
1934 convs->Convert_5x5_asis
1935 (width,lines,
1936 srcbits,linebytes,
1937 dstbits,-bmpImage->bytes_per_line);
1938 } else if (rSrc==bmpImage->blue_mask) {
1939 /* ==== rgb 555 dib -> bgr 555 bmp ==== */
1940 /* ==== bgr 555 dib -> rgb 555 bmp ==== */
1941 convs->Convert_555_reverse
1942 (width,lines,
1943 srcbits,linebytes,
1944 dstbits,-bmpImage->bytes_per_line);
1946 } else {
1947 if (rSrc==bmpImage->red_mask || bSrc==bmpImage->blue_mask) {
1948 /* ==== rgb 565 dib -> rgb 555 bmp ==== */
1949 /* ==== bgr 565 dib -> bgr 555 bmp ==== */
1950 convs->Convert_565_to_555_asis
1951 (width,lines,
1952 srcbits,linebytes,
1953 dstbits,-bmpImage->bytes_per_line);
1954 } else {
1955 /* ==== rgb 565 dib -> bgr 555 bmp ==== */
1956 /* ==== bgr 565 dib -> rgb 555 bmp ==== */
1957 convs->Convert_565_to_555_reverse
1958 (width,lines,
1959 srcbits,linebytes,
1960 dstbits,-bmpImage->bytes_per_line);
1963 } else if (bmpImage->green_mask==0x07e0) {
1964 if (gSrc==bmpImage->green_mask) {
1965 if (rSrc==bmpImage->red_mask) {
1966 /* ==== rgb 565 dib -> rgb 565 bmp ==== */
1967 /* ==== bgr 565 dib -> bgr 565 bmp ==== */
1968 convs->Convert_5x5_asis
1969 (width,lines,
1970 srcbits,linebytes,
1971 dstbits,-bmpImage->bytes_per_line);
1972 } else {
1973 /* ==== rgb 565 dib -> bgr 565 bmp ==== */
1974 /* ==== bgr 565 dib -> rgb 565 bmp ==== */
1975 convs->Convert_565_reverse
1976 (width,lines,
1977 srcbits,linebytes,
1978 dstbits,-bmpImage->bytes_per_line);
1980 } else {
1981 if (rSrc==bmpImage->red_mask || bSrc==bmpImage->blue_mask) {
1982 /* ==== rgb 555 dib -> rgb 565 bmp ==== */
1983 /* ==== bgr 555 dib -> bgr 565 bmp ==== */
1984 convs->Convert_555_to_565_asis
1985 (width,lines,
1986 srcbits,linebytes,
1987 dstbits,-bmpImage->bytes_per_line);
1988 } else {
1989 /* ==== rgb 555 dib -> bgr 565 bmp ==== */
1990 /* ==== bgr 555 dib -> rgb 565 bmp ==== */
1991 convs->Convert_555_to_565_reverse
1992 (width,lines,
1993 srcbits,linebytes,
1994 dstbits,-bmpImage->bytes_per_line);
1997 } else {
1998 goto notsupported;
2001 break;
2003 case 24:
2004 if (bmpImage->bits_per_pixel==24) {
2005 char* dstbits;
2007 srcbits=srcbits+left*2;
2008 dstbits=bmpImage->data+left*3+(lines-1)*bmpImage->bytes_per_line;
2010 if (bmpImage->green_mask!=0x00ff00 ||
2011 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2012 goto notsupported;
2013 } else if ((rSrc==0x1f && bmpImage->red_mask==0xff) ||
2014 (bSrc==0x1f && bmpImage->blue_mask==0xff)) {
2015 if (gSrc==0x03e0) {
2016 /* ==== rgb 555 dib -> rgb 888 bmp ==== */
2017 /* ==== bgr 555 dib -> bgr 888 bmp ==== */
2018 convs->Convert_555_to_888_asis
2019 (width,lines,
2020 srcbits,linebytes,
2021 dstbits,-bmpImage->bytes_per_line);
2022 } else {
2023 /* ==== rgb 565 dib -> rgb 888 bmp ==== */
2024 /* ==== bgr 565 dib -> bgr 888 bmp ==== */
2025 convs->Convert_565_to_888_asis
2026 (width,lines,
2027 srcbits,linebytes,
2028 dstbits,-bmpImage->bytes_per_line);
2030 } else {
2031 if (gSrc==0x03e0) {
2032 /* ==== rgb 555 dib -> bgr 888 bmp ==== */
2033 /* ==== bgr 555 dib -> rgb 888 bmp ==== */
2034 convs->Convert_555_to_888_reverse
2035 (width,lines,
2036 srcbits,linebytes,
2037 dstbits,-bmpImage->bytes_per_line);
2038 } else {
2039 /* ==== rgb 565 dib -> bgr 888 bmp ==== */
2040 /* ==== bgr 565 dib -> rgb 888 bmp ==== */
2041 convs->Convert_565_to_888_reverse
2042 (width,lines,
2043 srcbits,linebytes,
2044 dstbits,-bmpImage->bytes_per_line);
2047 break;
2049 /* Fall through */
2051 case 32:
2053 char* dstbits;
2055 srcbits=srcbits+left*2;
2056 dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
2058 if (bmpImage->green_mask!=0x00ff00 ||
2059 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2060 goto notsupported;
2061 } else if ((rSrc==0x1f && bmpImage->red_mask==0xff) ||
2062 (bSrc==0x1f && bmpImage->blue_mask==0xff)) {
2063 if (gSrc==0x03e0) {
2064 /* ==== rgb 555 dib -> rgb 0888 bmp ==== */
2065 /* ==== bgr 555 dib -> bgr 0888 bmp ==== */
2066 convs->Convert_555_to_0888_asis
2067 (width,lines,
2068 srcbits,linebytes,
2069 dstbits,-bmpImage->bytes_per_line);
2070 } else {
2071 /* ==== rgb 565 dib -> rgb 0888 bmp ==== */
2072 /* ==== bgr 565 dib -> bgr 0888 bmp ==== */
2073 convs->Convert_565_to_0888_asis
2074 (width,lines,
2075 srcbits,linebytes,
2076 dstbits,-bmpImage->bytes_per_line);
2078 } else {
2079 if (gSrc==0x03e0) {
2080 /* ==== rgb 555 dib -> bgr 0888 bmp ==== */
2081 /* ==== bgr 555 dib -> rgb 0888 bmp ==== */
2082 convs->Convert_555_to_0888_reverse
2083 (width,lines,
2084 srcbits,linebytes,
2085 dstbits,-bmpImage->bytes_per_line);
2086 } else {
2087 /* ==== rgb 565 dib -> bgr 0888 bmp ==== */
2088 /* ==== bgr 565 dib -> rgb 0888 bmp ==== */
2089 convs->Convert_565_to_0888_reverse
2090 (width,lines,
2091 srcbits,linebytes,
2092 dstbits,-bmpImage->bytes_per_line);
2096 break;
2098 default:
2099 notsupported:
2100 WARN("from 16 bit DIB (%lx,%lx,%lx) to unknown %d bit bitmap (%lx,%lx,%lx)\n",
2101 rSrc, gSrc, bSrc, bmpImage->bits_per_pixel, bmpImage->red_mask,
2102 bmpImage->green_mask, bmpImage->blue_mask );
2103 /* fall through */
2104 case 1:
2105 case 4:
2106 case 8:
2108 /* ==== rgb or bgr 555 or 565 dib -> pal 1, 4 or 8 ==== */
2109 const WORD* srcpixel;
2110 int rShift1,gShift1,bShift1;
2111 int rShift2,gShift2,bShift2;
2112 BYTE gMask1,gMask2;
2114 /* Set color scaling values */
2115 rShift1=16+X11DRV_DIB_MaskToShift(rSrc)-3;
2116 gShift1=16+X11DRV_DIB_MaskToShift(gSrc)-3;
2117 bShift1=16+X11DRV_DIB_MaskToShift(bSrc)-3;
2118 rShift2=rShift1+5;
2119 gShift2=gShift1+5;
2120 bShift2=bShift1+5;
2121 if (gSrc==0x03e0) {
2122 /* Green has 5 bits, like the others */
2123 gMask1=0xf8;
2124 gMask2=0x07;
2125 } else {
2126 /* Green has 6 bits, not 5. Compensate. */
2127 gShift1++;
2128 gShift2+=2;
2129 gMask1=0xfc;
2130 gMask2=0x03;
2133 srcbits+=2*left;
2135 /* We could split it into four separate cases to optimize
2136 * but it is probably not worth it.
2138 for (h=lines-1; h>=0; h--) {
2139 srcpixel=(const WORD*)srcbits;
2140 for (x=left; x<width+left; x++) {
2141 DWORD srcval;
2142 BYTE red,green,blue;
2143 srcval=*srcpixel++ << 16;
2144 red= ((srcval >> rShift1) & 0xf8) |
2145 ((srcval >> rShift2) & 0x07);
2146 green=((srcval >> gShift1) & gMask1) |
2147 ((srcval >> gShift2) & gMask2);
2148 blue= ((srcval >> bShift1) & 0xf8) |
2149 ((srcval >> bShift2) & 0x07);
2150 XPutPixel(bmpImage, x, h,
2151 X11DRV_PALETTE_ToPhysical
2152 (physDev, RGB(red,green,blue)));
2154 srcbits += linebytes;
2157 break;
2162 /***********************************************************************
2163 * X11DRV_DIB_GetImageBits_16
2165 * GetDIBits for an 16-bit deep DIB.
2167 static void X11DRV_DIB_GetImageBits_16( int lines, BYTE *dstbits,
2168 DWORD dstwidth, DWORD srcwidth,
2169 PALETTEENTRY *srccolors,
2170 DWORD rDst, DWORD gDst, DWORD bDst,
2171 XImage *bmpImage, DWORD dibpitch )
2173 DWORD x;
2174 int h, width = min(srcwidth, dstwidth);
2175 const dib_conversions *convs = (bmpImage->byte_order == LSBFirst) ? &dib_normal : &dib_src_byteswap;
2177 DWORD linebytes = dibpitch;
2179 if (lines < 0 )
2181 lines = -lines;
2182 dstbits = dstbits + ( linebytes * (lines-1));
2183 linebytes = -linebytes;
2186 switch (bmpImage->depth)
2188 case 15:
2189 case 16:
2191 const char* srcbits;
2193 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2195 if (bmpImage->green_mask==0x03e0) {
2196 if (gDst==bmpImage->green_mask) {
2197 if (rDst==bmpImage->red_mask) {
2198 /* ==== rgb 555 bmp -> rgb 555 dib ==== */
2199 /* ==== bgr 555 bmp -> bgr 555 dib ==== */
2200 convs->Convert_5x5_asis
2201 (width,lines,
2202 srcbits,-bmpImage->bytes_per_line,
2203 dstbits,linebytes);
2204 } else {
2205 /* ==== rgb 555 bmp -> bgr 555 dib ==== */
2206 /* ==== bgr 555 bmp -> rgb 555 dib ==== */
2207 convs->Convert_555_reverse
2208 (width,lines,
2209 srcbits,-bmpImage->bytes_per_line,
2210 dstbits,linebytes);
2212 } else {
2213 if (rDst==bmpImage->red_mask || bDst==bmpImage->blue_mask) {
2214 /* ==== rgb 555 bmp -> rgb 565 dib ==== */
2215 /* ==== bgr 555 bmp -> bgr 565 dib ==== */
2216 convs->Convert_555_to_565_asis
2217 (width,lines,
2218 srcbits,-bmpImage->bytes_per_line,
2219 dstbits,linebytes);
2220 } else {
2221 /* ==== rgb 555 bmp -> bgr 565 dib ==== */
2222 /* ==== bgr 555 bmp -> rgb 565 dib ==== */
2223 convs->Convert_555_to_565_reverse
2224 (width,lines,
2225 srcbits,-bmpImage->bytes_per_line,
2226 dstbits,linebytes);
2229 } else if (bmpImage->green_mask==0x07e0) {
2230 if (gDst==bmpImage->green_mask) {
2231 if (rDst == bmpImage->red_mask) {
2232 /* ==== rgb 565 bmp -> rgb 565 dib ==== */
2233 /* ==== bgr 565 bmp -> bgr 565 dib ==== */
2234 convs->Convert_5x5_asis
2235 (width,lines,
2236 srcbits,-bmpImage->bytes_per_line,
2237 dstbits,linebytes);
2238 } else {
2239 /* ==== rgb 565 bmp -> bgr 565 dib ==== */
2240 /* ==== bgr 565 bmp -> rgb 565 dib ==== */
2241 convs->Convert_565_reverse
2242 (width,lines,
2243 srcbits,-bmpImage->bytes_per_line,
2244 dstbits,linebytes);
2246 } else {
2247 if (rDst==bmpImage->red_mask || bDst==bmpImage->blue_mask) {
2248 /* ==== rgb 565 bmp -> rgb 555 dib ==== */
2249 /* ==== bgr 565 bmp -> bgr 555 dib ==== */
2250 convs->Convert_565_to_555_asis
2251 (width,lines,
2252 srcbits,-bmpImage->bytes_per_line,
2253 dstbits,linebytes);
2254 } else {
2255 /* ==== rgb 565 bmp -> bgr 555 dib ==== */
2256 /* ==== bgr 565 bmp -> rgb 555 dib ==== */
2257 convs->Convert_565_to_555_reverse
2258 (width,lines,
2259 srcbits,-bmpImage->bytes_per_line,
2260 dstbits,linebytes);
2263 } else {
2264 goto notsupported;
2267 break;
2269 case 24:
2270 if (bmpImage->bits_per_pixel == 24) {
2271 const char* srcbits;
2273 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2275 if (bmpImage->green_mask!=0x00ff00 ||
2276 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2277 goto notsupported;
2278 } else if ((rDst==0x1f && bmpImage->red_mask==0xff) ||
2279 (bDst==0x1f && bmpImage->blue_mask==0xff)) {
2280 if (gDst==0x03e0) {
2281 /* ==== rgb 888 bmp -> rgb 555 dib ==== */
2282 /* ==== bgr 888 bmp -> bgr 555 dib ==== */
2283 convs->Convert_888_to_555_asis
2284 (width,lines,
2285 srcbits,-bmpImage->bytes_per_line,
2286 dstbits,linebytes);
2287 } else {
2288 /* ==== rgb 888 bmp -> rgb 565 dib ==== */
2289 /* ==== rgb 888 bmp -> rgb 565 dib ==== */
2290 convs->Convert_888_to_565_asis
2291 (width,lines,
2292 srcbits,-bmpImage->bytes_per_line,
2293 dstbits,linebytes);
2295 } else {
2296 if (gDst==0x03e0) {
2297 /* ==== rgb 888 bmp -> bgr 555 dib ==== */
2298 /* ==== bgr 888 bmp -> rgb 555 dib ==== */
2299 convs->Convert_888_to_555_reverse
2300 (width,lines,
2301 srcbits,-bmpImage->bytes_per_line,
2302 dstbits,linebytes);
2303 } else {
2304 /* ==== rgb 888 bmp -> bgr 565 dib ==== */
2305 /* ==== bgr 888 bmp -> rgb 565 dib ==== */
2306 convs->Convert_888_to_565_reverse
2307 (width,lines,
2308 srcbits,-bmpImage->bytes_per_line,
2309 dstbits,linebytes);
2312 break;
2314 /* Fall through */
2316 case 32:
2318 const char* srcbits;
2320 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2322 if (bmpImage->green_mask!=0x00ff00 ||
2323 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2324 goto notsupported;
2325 } else if ((rDst==0x1f && bmpImage->red_mask==0xff) ||
2326 (bDst==0x1f && bmpImage->blue_mask==0xff)) {
2327 if (gDst==0x03e0) {
2328 /* ==== rgb 0888 bmp -> rgb 555 dib ==== */
2329 /* ==== bgr 0888 bmp -> bgr 555 dib ==== */
2330 convs->Convert_0888_to_555_asis
2331 (width,lines,
2332 srcbits,-bmpImage->bytes_per_line,
2333 dstbits,linebytes);
2334 } else {
2335 /* ==== rgb 0888 bmp -> rgb 565 dib ==== */
2336 /* ==== bgr 0888 bmp -> bgr 565 dib ==== */
2337 convs->Convert_0888_to_565_asis
2338 (width,lines,
2339 srcbits,-bmpImage->bytes_per_line,
2340 dstbits,linebytes);
2342 } else {
2343 if (gDst==0x03e0) {
2344 /* ==== rgb 0888 bmp -> bgr 555 dib ==== */
2345 /* ==== bgr 0888 bmp -> rgb 555 dib ==== */
2346 convs->Convert_0888_to_555_reverse
2347 (width,lines,
2348 srcbits,-bmpImage->bytes_per_line,
2349 dstbits,linebytes);
2350 } else {
2351 /* ==== rgb 0888 bmp -> bgr 565 dib ==== */
2352 /* ==== bgr 0888 bmp -> rgb 565 dib ==== */
2353 convs->Convert_0888_to_565_reverse
2354 (width,lines,
2355 srcbits,-bmpImage->bytes_per_line,
2356 dstbits,linebytes);
2360 break;
2362 case 1:
2363 case 4:
2364 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
2365 /* ==== pal 1 or 4 bmp -> rgb or bgr 555 or 565 dib ==== */
2366 int rShift,gShift,bShift;
2367 WORD* dstpixel;
2369 /* Shift everything 16 bits left so that all shifts are >0,
2370 * even for BGR DIBs. Then a single >> 16 will bring everything
2371 * back into place.
2373 rShift=16+X11DRV_DIB_MaskToShift(rDst)-3;
2374 gShift=16+X11DRV_DIB_MaskToShift(gDst)-3;
2375 bShift=16+X11DRV_DIB_MaskToShift(bDst)-3;
2376 if (gDst==0x07e0) {
2377 /* 6 bits for the green */
2378 gShift++;
2380 rDst=rDst << 16;
2381 gDst=gDst << 16;
2382 bDst=bDst << 16;
2383 for (h = lines - 1; h >= 0; h--) {
2384 dstpixel=(LPWORD)dstbits;
2385 for (x = 0; x < width; x++) {
2386 PALETTEENTRY srcval;
2387 DWORD dstval;
2388 srcval=srccolors[XGetPixel(bmpImage, x, h)];
2389 dstval=((srcval.peRed << rShift) & rDst) |
2390 ((srcval.peGreen << gShift) & gDst) |
2391 ((srcval.peBlue << bShift) & bDst);
2392 *dstpixel++=dstval >> 16;
2394 dstbits += linebytes;
2396 } else {
2397 goto notsupported;
2399 break;
2401 case 8:
2402 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
2403 /* ==== pal 8 bmp -> rgb or bgr 555 or 565 dib ==== */
2404 int rShift,gShift,bShift;
2405 const BYTE* srcbits;
2406 const BYTE* srcpixel;
2407 WORD* dstpixel;
2409 /* Shift everything 16 bits left so that all shifts are >0,
2410 * even for BGR DIBs. Then a single >> 16 will bring everything
2411 * back into place.
2413 rShift=16+X11DRV_DIB_MaskToShift(rDst)-3;
2414 gShift=16+X11DRV_DIB_MaskToShift(gDst)-3;
2415 bShift=16+X11DRV_DIB_MaskToShift(bDst)-3;
2416 if (gDst==0x07e0) {
2417 /* 6 bits for the green */
2418 gShift++;
2420 rDst=rDst << 16;
2421 gDst=gDst << 16;
2422 bDst=bDst << 16;
2423 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2424 for (h=0; h<lines; h++) {
2425 srcpixel=srcbits;
2426 dstpixel=(LPWORD)dstbits;
2427 for (x = 0; x < width; x++) {
2428 PALETTEENTRY srcval;
2429 DWORD dstval;
2430 srcval=srccolors[(int)*srcpixel++];
2431 dstval=((srcval.peRed << rShift) & rDst) |
2432 ((srcval.peGreen << gShift) & gDst) |
2433 ((srcval.peBlue << bShift) & bDst);
2434 *dstpixel++=dstval >> 16;
2436 srcbits -= bmpImage->bytes_per_line;
2437 dstbits += linebytes;
2439 } else {
2440 goto notsupported;
2442 break;
2444 default:
2445 notsupported:
2447 /* ==== any bmp format -> rgb or bgr 555 or 565 dib ==== */
2448 int rShift,gShift,bShift;
2449 WORD* dstpixel;
2451 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 16 bit DIB (%lx,%lx,%lx)\n",
2452 bmpImage->depth, bmpImage->red_mask,
2453 bmpImage->green_mask, bmpImage->blue_mask,
2454 rDst, gDst, bDst);
2456 /* Shift everything 16 bits left so that all shifts are >0,
2457 * even for BGR DIBs. Then a single >> 16 will bring everything
2458 * back into place.
2460 rShift=16+X11DRV_DIB_MaskToShift(rDst)-3;
2461 gShift=16+X11DRV_DIB_MaskToShift(gDst)-3;
2462 bShift=16+X11DRV_DIB_MaskToShift(bDst)-3;
2463 if (gDst==0x07e0) {
2464 /* 6 bits for the green */
2465 gShift++;
2467 rDst=rDst << 16;
2468 gDst=gDst << 16;
2469 bDst=bDst << 16;
2470 for (h = lines - 1; h >= 0; h--) {
2471 dstpixel=(LPWORD)dstbits;
2472 for (x = 0; x < width; x++) {
2473 COLORREF srcval;
2474 DWORD dstval;
2475 srcval=X11DRV_PALETTE_ToLogical(XGetPixel(bmpImage, x, h));
2476 dstval=((GetRValue(srcval) << rShift) & rDst) |
2477 ((GetGValue(srcval) << gShift) & gDst) |
2478 ((GetBValue(srcval) << bShift) & bDst);
2479 *dstpixel++=dstval >> 16;
2481 dstbits += linebytes;
2484 break;
2489 /***********************************************************************
2490 * X11DRV_DIB_SetImageBits_24
2492 * SetDIBits for a 24-bit deep DIB.
2494 static void X11DRV_DIB_SetImageBits_24( int lines, const BYTE *srcbits,
2495 DWORD srcwidth, DWORD dstwidth, int left,
2496 X11DRV_PDEVICE *physDev,
2497 DWORD rSrc, DWORD gSrc, DWORD bSrc,
2498 XImage *bmpImage, DWORD linebytes )
2500 DWORD x;
2501 int h, width = min(srcwidth, dstwidth);
2502 const dib_conversions *convs = (bmpImage->byte_order == LSBFirst) ? &dib_normal : &dib_dst_byteswap;
2504 if (lines < 0 )
2506 lines = -lines;
2507 srcbits = srcbits + linebytes * (lines - 1);
2508 linebytes = -linebytes;
2511 switch (bmpImage->depth)
2513 case 24:
2514 if (bmpImage->bits_per_pixel==24) {
2515 char* dstbits;
2517 srcbits=srcbits+left*3;
2518 dstbits=bmpImage->data+left*3+(lines-1)*bmpImage->bytes_per_line;
2520 if (bmpImage->green_mask!=0x00ff00 ||
2521 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2522 goto notsupported;
2523 } else if (rSrc==bmpImage->red_mask) {
2524 /* ==== rgb 888 dib -> rgb 888 bmp ==== */
2525 /* ==== bgr 888 dib -> bgr 888 bmp ==== */
2526 convs->Convert_888_asis
2527 (width,lines,
2528 srcbits,linebytes,
2529 dstbits,-bmpImage->bytes_per_line);
2530 } else {
2531 /* ==== rgb 888 dib -> bgr 888 bmp ==== */
2532 /* ==== bgr 888 dib -> rgb 888 bmp ==== */
2533 convs->Convert_888_reverse
2534 (width,lines,
2535 srcbits,linebytes,
2536 dstbits,-bmpImage->bytes_per_line);
2538 break;
2540 /* fall through */
2542 case 32:
2544 char* dstbits;
2546 srcbits=srcbits+left*3;
2547 dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
2549 if (bmpImage->green_mask!=0x00ff00 ||
2550 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2551 goto notsupported;
2552 } else if (rSrc==bmpImage->red_mask) {
2553 /* ==== rgb 888 dib -> rgb 0888 bmp ==== */
2554 /* ==== bgr 888 dib -> bgr 0888 bmp ==== */
2555 convs->Convert_888_to_0888_asis
2556 (width,lines,
2557 srcbits,linebytes,
2558 dstbits,-bmpImage->bytes_per_line);
2559 } else {
2560 /* ==== rgb 888 dib -> bgr 0888 bmp ==== */
2561 /* ==== bgr 888 dib -> rgb 0888 bmp ==== */
2562 convs->Convert_888_to_0888_reverse
2563 (width,lines,
2564 srcbits,linebytes,
2565 dstbits,-bmpImage->bytes_per_line);
2567 break;
2570 case 15:
2571 case 16:
2573 char* dstbits;
2575 srcbits=srcbits+left*3;
2576 dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
2578 if (bmpImage->green_mask==0x03e0) {
2579 if ((rSrc==0xff0000 && bmpImage->red_mask==0x7f00) ||
2580 (bSrc==0xff0000 && bmpImage->blue_mask==0x7f00)) {
2581 /* ==== rgb 888 dib -> rgb 555 bmp ==== */
2582 /* ==== bgr 888 dib -> bgr 555 bmp ==== */
2583 convs->Convert_888_to_555_asis
2584 (width,lines,
2585 srcbits,linebytes,
2586 dstbits,-bmpImage->bytes_per_line);
2587 } else if ((rSrc==0xff && bmpImage->red_mask==0x7f00) ||
2588 (bSrc==0xff && bmpImage->blue_mask==0x7f00)) {
2589 /* ==== rgb 888 dib -> bgr 555 bmp ==== */
2590 /* ==== bgr 888 dib -> rgb 555 bmp ==== */
2591 convs->Convert_888_to_555_reverse
2592 (width,lines,
2593 srcbits,linebytes,
2594 dstbits,-bmpImage->bytes_per_line);
2595 } else {
2596 goto notsupported;
2598 } else if (bmpImage->green_mask==0x07e0) {
2599 if ((rSrc==0xff0000 && bmpImage->red_mask==0xf800) ||
2600 (bSrc==0xff0000 && bmpImage->blue_mask==0xf800)) {
2601 /* ==== rgb 888 dib -> rgb 565 bmp ==== */
2602 /* ==== bgr 888 dib -> bgr 565 bmp ==== */
2603 convs->Convert_888_to_565_asis
2604 (width,lines,
2605 srcbits,linebytes,
2606 dstbits,-bmpImage->bytes_per_line);
2607 } else if ((rSrc==0xff && bmpImage->red_mask==0xf800) ||
2608 (bSrc==0xff && bmpImage->blue_mask==0xf800)) {
2609 /* ==== rgb 888 dib -> bgr 565 bmp ==== */
2610 /* ==== bgr 888 dib -> rgb 565 bmp ==== */
2611 convs->Convert_888_to_565_reverse
2612 (width,lines,
2613 srcbits,linebytes,
2614 dstbits,-bmpImage->bytes_per_line);
2615 } else {
2616 goto notsupported;
2618 } else {
2619 goto notsupported;
2622 break;
2624 default:
2625 notsupported:
2626 WARN("from 24 bit DIB (%lx,%lx,%lx) to unknown %d bit bitmap (%lx,%lx,%lx)\n",
2627 rSrc, gSrc, bSrc, bmpImage->bits_per_pixel, bmpImage->red_mask,
2628 bmpImage->green_mask, bmpImage->blue_mask );
2629 /* fall through */
2630 case 1:
2631 case 4:
2632 case 8:
2634 /* ==== rgb 888 dib -> any bmp bormat ==== */
2635 const BYTE* srcbyte;
2637 /* Windows only supports one 24bpp DIB format: RGB888 */
2638 srcbits+=left*3;
2639 for (h = lines - 1; h >= 0; h--) {
2640 srcbyte=(const BYTE*)srcbits;
2641 for (x = left; x < width+left; x++) {
2642 XPutPixel(bmpImage, x, h,
2643 X11DRV_PALETTE_ToPhysical
2644 (physDev, RGB(srcbyte[2], srcbyte[1], srcbyte[0])));
2645 srcbyte+=3;
2647 srcbits += linebytes;
2650 break;
2655 /***********************************************************************
2656 * X11DRV_DIB_GetImageBits_24
2658 * GetDIBits for an 24-bit deep DIB.
2660 static void X11DRV_DIB_GetImageBits_24( int lines, BYTE *dstbits,
2661 DWORD dstwidth, DWORD srcwidth,
2662 PALETTEENTRY *srccolors,
2663 DWORD rDst, DWORD gDst, DWORD bDst,
2664 XImage *bmpImage, DWORD linebytes )
2666 DWORD x;
2667 int h, width = min(srcwidth, dstwidth);
2668 const dib_conversions *convs = (bmpImage->byte_order == LSBFirst) ? &dib_normal : &dib_src_byteswap;
2670 if (lines < 0 )
2672 lines = -lines;
2673 dstbits = dstbits + ( linebytes * (lines-1) );
2674 linebytes = -linebytes;
2677 switch (bmpImage->depth)
2679 case 24:
2680 if (bmpImage->bits_per_pixel==24) {
2681 const char* srcbits;
2683 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2685 if (bmpImage->green_mask!=0x00ff00 ||
2686 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2687 goto notsupported;
2688 } else if (rDst==bmpImage->red_mask) {
2689 /* ==== rgb 888 bmp -> rgb 888 dib ==== */
2690 /* ==== bgr 888 bmp -> bgr 888 dib ==== */
2691 convs->Convert_888_asis
2692 (width,lines,
2693 srcbits,-bmpImage->bytes_per_line,
2694 dstbits,linebytes);
2695 } else {
2696 /* ==== rgb 888 bmp -> bgr 888 dib ==== */
2697 /* ==== bgr 888 bmp -> rgb 888 dib ==== */
2698 convs->Convert_888_reverse
2699 (width,lines,
2700 srcbits,-bmpImage->bytes_per_line,
2701 dstbits,linebytes);
2703 break;
2705 /* fall through */
2707 case 32:
2709 const char* srcbits;
2711 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2713 if (bmpImage->green_mask!=0x00ff00 ||
2714 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2715 goto notsupported;
2716 } else if (rDst==bmpImage->red_mask) {
2717 /* ==== rgb 888 bmp -> rgb 0888 dib ==== */
2718 /* ==== bgr 888 bmp -> bgr 0888 dib ==== */
2719 convs->Convert_0888_to_888_asis
2720 (width,lines,
2721 srcbits,-bmpImage->bytes_per_line,
2722 dstbits,linebytes);
2723 } else {
2724 /* ==== rgb 888 bmp -> bgr 0888 dib ==== */
2725 /* ==== bgr 888 bmp -> rgb 0888 dib ==== */
2726 convs->Convert_0888_to_888_reverse
2727 (width,lines,
2728 srcbits,-bmpImage->bytes_per_line,
2729 dstbits,linebytes);
2731 break;
2734 case 15:
2735 case 16:
2737 const char* srcbits;
2739 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2741 if (bmpImage->green_mask==0x03e0) {
2742 if ((rDst==0xff0000 && bmpImage->red_mask==0x7f00) ||
2743 (bDst==0xff0000 && bmpImage->blue_mask==0x7f00)) {
2744 /* ==== rgb 555 bmp -> rgb 888 dib ==== */
2745 /* ==== bgr 555 bmp -> bgr 888 dib ==== */
2746 convs->Convert_555_to_888_asis
2747 (width,lines,
2748 srcbits,-bmpImage->bytes_per_line,
2749 dstbits,linebytes);
2750 } else if ((rDst==0xff && bmpImage->red_mask==0x7f00) ||
2751 (bDst==0xff && bmpImage->blue_mask==0x7f00)) {
2752 /* ==== rgb 555 bmp -> bgr 888 dib ==== */
2753 /* ==== bgr 555 bmp -> rgb 888 dib ==== */
2754 convs->Convert_555_to_888_reverse
2755 (width,lines,
2756 srcbits,-bmpImage->bytes_per_line,
2757 dstbits,linebytes);
2758 } else {
2759 goto notsupported;
2761 } else if (bmpImage->green_mask==0x07e0) {
2762 if ((rDst==0xff0000 && bmpImage->red_mask==0xf800) ||
2763 (bDst==0xff0000 && bmpImage->blue_mask==0xf800)) {
2764 /* ==== rgb 565 bmp -> rgb 888 dib ==== */
2765 /* ==== bgr 565 bmp -> bgr 888 dib ==== */
2766 convs->Convert_565_to_888_asis
2767 (width,lines,
2768 srcbits,-bmpImage->bytes_per_line,
2769 dstbits,linebytes);
2770 } else if ((rDst==0xff && bmpImage->red_mask==0xf800) ||
2771 (bDst==0xff && bmpImage->blue_mask==0xf800)) {
2772 /* ==== rgb 565 bmp -> bgr 888 dib ==== */
2773 /* ==== bgr 565 bmp -> rgb 888 dib ==== */
2774 convs->Convert_565_to_888_reverse
2775 (width,lines,
2776 srcbits,-bmpImage->bytes_per_line,
2777 dstbits,linebytes);
2778 } else {
2779 goto notsupported;
2781 } else {
2782 goto notsupported;
2785 break;
2787 case 1:
2788 case 4:
2789 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
2790 /* ==== pal 1 or 4 bmp -> rgb 888 dib ==== */
2791 BYTE* dstbyte;
2793 /* Windows only supports one 24bpp DIB format: rgb 888 */
2794 for (h = lines - 1; h >= 0; h--) {
2795 dstbyte=dstbits;
2796 for (x = 0; x < width; x++) {
2797 PALETTEENTRY srcval;
2798 srcval=srccolors[XGetPixel(bmpImage, x, h)];
2799 dstbyte[0]=srcval.peBlue;
2800 dstbyte[1]=srcval.peGreen;
2801 dstbyte[2]=srcval.peRed;
2802 dstbyte+=3;
2804 dstbits += linebytes;
2806 } else {
2807 goto notsupported;
2809 break;
2811 case 8:
2812 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask == 0 && srccolors) {
2813 /* ==== pal 8 bmp -> rgb 888 dib ==== */
2814 const void* srcbits;
2815 const BYTE* srcpixel;
2816 BYTE* dstbyte;
2818 /* Windows only supports one 24bpp DIB format: rgb 888 */
2819 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2820 for (h = lines - 1; h >= 0; h--) {
2821 srcpixel=srcbits;
2822 dstbyte=dstbits;
2823 for (x = 0; x < width; x++ ) {
2824 PALETTEENTRY srcval;
2825 srcval=srccolors[(int)*srcpixel++];
2826 dstbyte[0]=srcval.peBlue;
2827 dstbyte[1]=srcval.peGreen;
2828 dstbyte[2]=srcval.peRed;
2829 dstbyte+=3;
2831 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
2832 dstbits += linebytes;
2834 } else {
2835 goto notsupported;
2837 break;
2839 default:
2840 notsupported:
2842 /* ==== any bmp format -> 888 dib ==== */
2843 BYTE* dstbyte;
2845 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 24 bit DIB (%lx,%lx,%lx)\n",
2846 bmpImage->depth, bmpImage->red_mask,
2847 bmpImage->green_mask, bmpImage->blue_mask,
2848 rDst, gDst, bDst );
2850 /* Windows only supports one 24bpp DIB format: rgb 888 */
2851 for (h = lines - 1; h >= 0; h--) {
2852 dstbyte=dstbits;
2853 for (x = 0; x < width; x++) {
2854 COLORREF srcval=X11DRV_PALETTE_ToLogical
2855 (XGetPixel( bmpImage, x, h ));
2856 dstbyte[0]=GetBValue(srcval);
2857 dstbyte[1]=GetGValue(srcval);
2858 dstbyte[2]=GetRValue(srcval);
2859 dstbyte+=3;
2861 dstbits += linebytes;
2864 break;
2869 /***********************************************************************
2870 * X11DRV_DIB_SetImageBits_32
2872 * SetDIBits for a 32-bit deep DIB.
2874 static void X11DRV_DIB_SetImageBits_32(int lines, const BYTE *srcbits,
2875 DWORD srcwidth, DWORD dstwidth, int left,
2876 X11DRV_PDEVICE *physDev,
2877 DWORD rSrc, DWORD gSrc, DWORD bSrc,
2878 XImage *bmpImage,
2879 DWORD linebytes)
2881 DWORD x;
2882 const DWORD *ptr;
2883 int h, width = min(srcwidth, dstwidth);
2884 const dib_conversions *convs = (bmpImage->byte_order == LSBFirst) ? &dib_normal : &dib_dst_byteswap;
2886 if (lines < 0 )
2888 lines = -lines;
2889 srcbits = srcbits + ( linebytes * (lines-1) );
2890 linebytes = -linebytes;
2893 ptr = (const DWORD *) srcbits + left;
2895 switch (bmpImage->depth)
2897 case 24:
2898 if (bmpImage->bits_per_pixel==24) {
2899 char* dstbits;
2901 srcbits=srcbits+left*4;
2902 dstbits=bmpImage->data+left*3+(lines-1)*bmpImage->bytes_per_line;
2904 if (rSrc==bmpImage->red_mask && gSrc==bmpImage->green_mask && bSrc==bmpImage->blue_mask) {
2905 /* ==== rgb 0888 dib -> rgb 888 bmp ==== */
2906 /* ==== bgr 0888 dib -> bgr 888 bmp ==== */
2907 convs->Convert_0888_to_888_asis
2908 (width,lines,
2909 srcbits,linebytes,
2910 dstbits,-bmpImage->bytes_per_line);
2911 } else if (bmpImage->green_mask!=0x00ff00 ||
2912 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2913 goto notsupported;
2914 /* the tests below assume sane bmpImage masks */
2915 } else if (rSrc==bmpImage->blue_mask && gSrc==bmpImage->green_mask && bSrc==bmpImage->red_mask) {
2916 /* ==== rgb 0888 dib -> bgr 888 bmp ==== */
2917 /* ==== bgr 0888 dib -> rgb 888 bmp ==== */
2918 convs->Convert_0888_to_888_reverse
2919 (width,lines,
2920 srcbits,linebytes,
2921 dstbits,-bmpImage->bytes_per_line);
2922 } else if (bmpImage->blue_mask==0xff) {
2923 /* ==== any 0888 dib -> rgb 888 bmp ==== */
2924 convs->Convert_any0888_to_rgb888
2925 (width,lines,
2926 srcbits,linebytes,
2927 rSrc,gSrc,bSrc,
2928 dstbits,-bmpImage->bytes_per_line);
2929 } else {
2930 /* ==== any 0888 dib -> bgr 888 bmp ==== */
2931 convs->Convert_any0888_to_bgr888
2932 (width,lines,
2933 srcbits,linebytes,
2934 rSrc,gSrc,bSrc,
2935 dstbits,-bmpImage->bytes_per_line);
2937 break;
2939 /* fall through */
2941 case 32:
2943 char* dstbits;
2945 srcbits=srcbits+left*4;
2946 dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
2948 if (gSrc==bmpImage->green_mask) {
2949 if (rSrc==bmpImage->red_mask && bSrc==bmpImage->blue_mask) {
2950 /* ==== rgb 0888 dib -> rgb 0888 bmp ==== */
2951 /* ==== bgr 0888 dib -> bgr 0888 bmp ==== */
2952 convs->Convert_0888_asis
2953 (width,lines,
2954 srcbits,linebytes,
2955 dstbits,-bmpImage->bytes_per_line);
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 if (rSrc==bmpImage->blue_mask && bSrc==bmpImage->red_mask) {
2961 /* ==== rgb 0888 dib -> bgr 0888 bmp ==== */
2962 /* ==== bgr 0888 dib -> rgb 0888 bmp ==== */
2963 convs->Convert_0888_reverse
2964 (width,lines,
2965 srcbits,linebytes,
2966 dstbits,-bmpImage->bytes_per_line);
2967 } else {
2968 /* ==== any 0888 dib -> any 0888 bmp ==== */
2969 convs->Convert_0888_any
2970 (width,lines,
2971 srcbits,linebytes,
2972 rSrc,gSrc,bSrc,
2973 dstbits,-bmpImage->bytes_per_line,
2974 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
2976 } else if (bmpImage->green_mask!=0x00ff00 ||
2977 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2978 goto notsupported;
2979 /* the tests below assume sane bmpImage masks */
2980 } else {
2981 /* ==== any 0888 dib -> any 0888 bmp ==== */
2982 convs->Convert_0888_any
2983 (width,lines,
2984 srcbits,linebytes,
2985 rSrc,gSrc,bSrc,
2986 dstbits,-bmpImage->bytes_per_line,
2987 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
2990 break;
2992 case 15:
2993 case 16:
2995 char* dstbits;
2997 srcbits=srcbits+left*4;
2998 dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
3000 if (rSrc==0xff0000 && gSrc==0x00ff00 && bSrc==0x0000ff) {
3001 if (bmpImage->green_mask==0x03e0) {
3002 if (bmpImage->red_mask==0x7f00) {
3003 /* ==== rgb 0888 dib -> rgb 555 bmp ==== */
3004 convs->Convert_0888_to_555_asis
3005 (width,lines,
3006 srcbits,linebytes,
3007 dstbits,-bmpImage->bytes_per_line);
3008 } else if (bmpImage->blue_mask==0x7f00) {
3009 /* ==== rgb 0888 dib -> bgr 555 bmp ==== */
3010 convs->Convert_0888_to_555_reverse
3011 (width,lines,
3012 srcbits,linebytes,
3013 dstbits,-bmpImage->bytes_per_line);
3014 } else {
3015 goto notsupported;
3017 } else if (bmpImage->green_mask==0x07e0) {
3018 if (bmpImage->red_mask==0xf800) {
3019 /* ==== rgb 0888 dib -> rgb 565 bmp ==== */
3020 convs->Convert_0888_to_565_asis
3021 (width,lines,
3022 srcbits,linebytes,
3023 dstbits,-bmpImage->bytes_per_line);
3024 } else if (bmpImage->blue_mask==0xf800) {
3025 /* ==== rgb 0888 dib -> bgr 565 bmp ==== */
3026 convs->Convert_0888_to_565_reverse
3027 (width,lines,
3028 srcbits,linebytes,
3029 dstbits,-bmpImage->bytes_per_line);
3030 } else {
3031 goto notsupported;
3033 } else {
3034 goto notsupported;
3036 } else if (rSrc==0x0000ff && gSrc==0x00ff00 && bSrc==0xff0000) {
3037 if (bmpImage->green_mask==0x03e0) {
3038 if (bmpImage->blue_mask==0x7f00) {
3039 /* ==== bgr 0888 dib -> bgr 555 bmp ==== */
3040 convs->Convert_0888_to_555_asis
3041 (width,lines,
3042 srcbits,linebytes,
3043 dstbits,-bmpImage->bytes_per_line);
3044 } else if (bmpImage->red_mask==0x7f00) {
3045 /* ==== bgr 0888 dib -> rgb 555 bmp ==== */
3046 convs->Convert_0888_to_555_reverse
3047 (width,lines,
3048 srcbits,linebytes,
3049 dstbits,-bmpImage->bytes_per_line);
3050 } else {
3051 goto notsupported;
3053 } else if (bmpImage->green_mask==0x07e0) {
3054 if (bmpImage->blue_mask==0xf800) {
3055 /* ==== bgr 0888 dib -> bgr 565 bmp ==== */
3056 convs->Convert_0888_to_565_asis
3057 (width,lines,
3058 srcbits,linebytes,
3059 dstbits,-bmpImage->bytes_per_line);
3060 } else if (bmpImage->red_mask==0xf800) {
3061 /* ==== bgr 0888 dib -> rgb 565 bmp ==== */
3062 convs->Convert_0888_to_565_reverse
3063 (width,lines,
3064 srcbits,linebytes,
3065 dstbits,-bmpImage->bytes_per_line);
3066 } else {
3067 goto notsupported;
3069 } else {
3070 goto notsupported;
3072 } else {
3073 if (bmpImage->green_mask==0x03e0 &&
3074 (bmpImage->red_mask==0x7f00 ||
3075 bmpImage->blue_mask==0x7f00)) {
3076 /* ==== any 0888 dib -> rgb or bgr 555 bmp ==== */
3077 convs->Convert_any0888_to_5x5
3078 (width,lines,
3079 srcbits,linebytes,
3080 rSrc,gSrc,bSrc,
3081 dstbits,-bmpImage->bytes_per_line,
3082 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
3083 } else if (bmpImage->green_mask==0x07e0 &&
3084 (bmpImage->red_mask==0xf800 ||
3085 bmpImage->blue_mask==0xf800)) {
3086 /* ==== any 0888 dib -> rgb or bgr 565 bmp ==== */
3087 convs->Convert_any0888_to_5x5
3088 (width,lines,
3089 srcbits,linebytes,
3090 rSrc,gSrc,bSrc,
3091 dstbits,-bmpImage->bytes_per_line,
3092 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
3093 } else {
3094 goto notsupported;
3098 break;
3100 default:
3101 notsupported:
3102 WARN("from 32 bit DIB (%lx,%lx,%lx) to unknown %d bit bitmap (%lx,%lx,%lx)\n",
3103 rSrc, gSrc, bSrc, bmpImage->bits_per_pixel, bmpImage->red_mask,
3104 bmpImage->green_mask, bmpImage->blue_mask );
3105 /* fall through */
3106 case 1:
3107 case 4:
3108 case 8:
3110 /* ==== any 0888 dib -> pal 1, 4 or 8 bmp ==== */
3111 const DWORD* srcpixel;
3112 int rShift,gShift,bShift;
3114 rShift=X11DRV_DIB_MaskToShift(rSrc);
3115 gShift=X11DRV_DIB_MaskToShift(gSrc);
3116 bShift=X11DRV_DIB_MaskToShift(bSrc);
3117 srcbits+=left*4;
3118 for (h = lines - 1; h >= 0; h--) {
3119 srcpixel=(const DWORD*)srcbits;
3120 for (x = left; x < width+left; x++) {
3121 DWORD srcvalue;
3122 BYTE red,green,blue;
3123 srcvalue=*srcpixel++;
3124 red= (srcvalue >> rShift) & 0xff;
3125 green=(srcvalue >> gShift) & 0xff;
3126 blue= (srcvalue >> bShift) & 0xff;
3127 XPutPixel(bmpImage, x, h, X11DRV_PALETTE_ToPhysical
3128 (physDev, RGB(red,green,blue)));
3130 srcbits += linebytes;
3133 break;
3138 /***********************************************************************
3139 * X11DRV_DIB_GetImageBits_32
3141 * GetDIBits for an 32-bit deep DIB.
3143 static void X11DRV_DIB_GetImageBits_32( int lines, BYTE *dstbits,
3144 DWORD dstwidth, DWORD srcwidth,
3145 PALETTEENTRY *srccolors,
3146 DWORD rDst, DWORD gDst, DWORD bDst,
3147 XImage *bmpImage, DWORD linebytes )
3149 DWORD x;
3150 int h, width = min(srcwidth, dstwidth);
3151 BYTE *bits;
3152 const dib_conversions *convs = (bmpImage->byte_order == LSBFirst) ? &dib_normal : &dib_src_byteswap;
3154 if (lines < 0 )
3156 lines = -lines;
3157 dstbits = dstbits + ( linebytes * (lines-1) );
3158 linebytes = -linebytes;
3161 bits = dstbits;
3163 switch (bmpImage->depth)
3165 case 24:
3166 if (bmpImage->bits_per_pixel==24) {
3167 const void* srcbits;
3169 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3171 if (rDst==bmpImage->red_mask && gDst==bmpImage->green_mask && bDst==bmpImage->blue_mask) {
3172 /* ==== rgb 888 bmp -> rgb 0888 dib ==== */
3173 /* ==== bgr 888 bmp -> bgr 0888 dib ==== */
3174 convs->Convert_888_to_0888_asis
3175 (width,lines,
3176 srcbits,-bmpImage->bytes_per_line,
3177 dstbits,linebytes);
3178 } else if (bmpImage->green_mask!=0x00ff00 ||
3179 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3180 goto notsupported;
3181 /* the tests below assume sane bmpImage masks */
3182 } else if (rDst==bmpImage->blue_mask && gDst==bmpImage->green_mask && bDst==bmpImage->red_mask) {
3183 /* ==== rgb 888 bmp -> bgr 0888 dib ==== */
3184 /* ==== bgr 888 bmp -> rgb 0888 dib ==== */
3185 convs->Convert_888_to_0888_reverse
3186 (width,lines,
3187 srcbits,-bmpImage->bytes_per_line,
3188 dstbits,linebytes);
3189 } else if (bmpImage->blue_mask==0xff) {
3190 /* ==== rgb 888 bmp -> any 0888 dib ==== */
3191 convs->Convert_rgb888_to_any0888
3192 (width,lines,
3193 srcbits,-bmpImage->bytes_per_line,
3194 dstbits,linebytes,
3195 rDst,gDst,bDst);
3196 } else {
3197 /* ==== bgr 888 bmp -> any 0888 dib ==== */
3198 convs->Convert_bgr888_to_any0888
3199 (width,lines,
3200 srcbits,-bmpImage->bytes_per_line,
3201 dstbits,linebytes,
3202 rDst,gDst,bDst);
3204 break;
3206 /* fall through */
3208 case 32:
3210 const char* srcbits;
3212 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3214 if (gDst==bmpImage->green_mask) {
3215 if (rDst==bmpImage->red_mask && bDst==bmpImage->blue_mask) {
3216 /* ==== rgb 0888 bmp -> rgb 0888 dib ==== */
3217 /* ==== bgr 0888 bmp -> bgr 0888 dib ==== */
3218 convs->Convert_0888_asis
3219 (width,lines,
3220 srcbits,-bmpImage->bytes_per_line,
3221 dstbits,linebytes);
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 if (rDst==bmpImage->blue_mask && bDst==bmpImage->red_mask) {
3227 /* ==== rgb 0888 bmp -> bgr 0888 dib ==== */
3228 /* ==== bgr 0888 bmp -> rgb 0888 dib ==== */
3229 convs->Convert_0888_reverse
3230 (width,lines,
3231 srcbits,-bmpImage->bytes_per_line,
3232 dstbits,linebytes);
3233 } else {
3234 /* ==== any 0888 bmp -> any 0888 dib ==== */
3235 convs->Convert_0888_any
3236 (width,lines,
3237 srcbits,-bmpImage->bytes_per_line,
3238 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
3239 dstbits,linebytes,
3240 rDst,gDst,bDst);
3242 } else if (bmpImage->green_mask!=0x00ff00 ||
3243 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3244 goto notsupported;
3245 /* the tests below assume sane bmpImage masks */
3246 } else {
3247 /* ==== any 0888 bmp -> any 0888 dib ==== */
3248 convs->Convert_0888_any
3249 (width,lines,
3250 srcbits,-bmpImage->bytes_per_line,
3251 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
3252 dstbits,linebytes,
3253 rDst,gDst,bDst);
3256 break;
3258 case 15:
3259 case 16:
3261 const char* srcbits;
3263 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3265 if (rDst==0xff0000 && gDst==0x00ff00 && bDst==0x0000ff) {
3266 if (bmpImage->green_mask==0x03e0) {
3267 if (bmpImage->red_mask==0x7f00) {
3268 /* ==== rgb 555 bmp -> rgb 0888 dib ==== */
3269 convs->Convert_555_to_0888_asis
3270 (width,lines,
3271 srcbits,-bmpImage->bytes_per_line,
3272 dstbits,linebytes);
3273 } else if (bmpImage->blue_mask==0x7f00) {
3274 /* ==== bgr 555 bmp -> rgb 0888 dib ==== */
3275 convs->Convert_555_to_0888_reverse
3276 (width,lines,
3277 srcbits,-bmpImage->bytes_per_line,
3278 dstbits,linebytes);
3279 } else {
3280 goto notsupported;
3282 } else if (bmpImage->green_mask==0x07e0) {
3283 if (bmpImage->red_mask==0xf800) {
3284 /* ==== rgb 565 bmp -> rgb 0888 dib ==== */
3285 convs->Convert_565_to_0888_asis
3286 (width,lines,
3287 srcbits,-bmpImage->bytes_per_line,
3288 dstbits,linebytes);
3289 } else if (bmpImage->blue_mask==0xf800) {
3290 /* ==== bgr 565 bmp -> rgb 0888 dib ==== */
3291 convs->Convert_565_to_0888_reverse
3292 (width,lines,
3293 srcbits,-bmpImage->bytes_per_line,
3294 dstbits,linebytes);
3295 } else {
3296 goto notsupported;
3298 } else {
3299 goto notsupported;
3301 } else if (rDst==0x0000ff && gDst==0x00ff00 && bDst==0xff0000) {
3302 if (bmpImage->green_mask==0x03e0) {
3303 if (bmpImage->blue_mask==0x7f00) {
3304 /* ==== bgr 555 bmp -> bgr 0888 dib ==== */
3305 convs->Convert_555_to_0888_asis
3306 (width,lines,
3307 srcbits,-bmpImage->bytes_per_line,
3308 dstbits,linebytes);
3309 } else if (bmpImage->red_mask==0x7f00) {
3310 /* ==== rgb 555 bmp -> bgr 0888 dib ==== */
3311 convs->Convert_555_to_0888_reverse
3312 (width,lines,
3313 srcbits,-bmpImage->bytes_per_line,
3314 dstbits,linebytes);
3315 } else {
3316 goto notsupported;
3318 } else if (bmpImage->green_mask==0x07e0) {
3319 if (bmpImage->blue_mask==0xf800) {
3320 /* ==== bgr 565 bmp -> bgr 0888 dib ==== */
3321 convs->Convert_565_to_0888_asis
3322 (width,lines,
3323 srcbits,-bmpImage->bytes_per_line,
3324 dstbits,linebytes);
3325 } else if (bmpImage->red_mask==0xf800) {
3326 /* ==== rgb 565 bmp -> bgr 0888 dib ==== */
3327 convs->Convert_565_to_0888_reverse
3328 (width,lines,
3329 srcbits,-bmpImage->bytes_per_line,
3330 dstbits,linebytes);
3331 } else {
3332 goto notsupported;
3334 } else {
3335 goto notsupported;
3337 } else {
3338 if (bmpImage->green_mask==0x03e0 &&
3339 (bmpImage->red_mask==0x7f00 ||
3340 bmpImage->blue_mask==0x7f00)) {
3341 /* ==== rgb or bgr 555 bmp -> any 0888 dib ==== */
3342 convs->Convert_5x5_to_any0888
3343 (width,lines,
3344 srcbits,-bmpImage->bytes_per_line,
3345 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
3346 dstbits,linebytes,
3347 rDst,gDst,bDst);
3348 } else if (bmpImage->green_mask==0x07e0 &&
3349 (bmpImage->red_mask==0xf800 ||
3350 bmpImage->blue_mask==0xf800)) {
3351 /* ==== rgb or bgr 565 bmp -> any 0888 dib ==== */
3352 convs->Convert_5x5_to_any0888
3353 (width,lines,
3354 srcbits,-bmpImage->bytes_per_line,
3355 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
3356 dstbits,linebytes,
3357 rDst,gDst,bDst);
3358 } else {
3359 goto notsupported;
3363 break;
3365 case 1:
3366 case 4:
3367 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
3368 /* ==== pal 1 or 4 bmp -> any 0888 dib ==== */
3369 int rShift,gShift,bShift;
3370 DWORD* dstpixel;
3372 rShift=X11DRV_DIB_MaskToShift(rDst);
3373 gShift=X11DRV_DIB_MaskToShift(gDst);
3374 bShift=X11DRV_DIB_MaskToShift(bDst);
3375 for (h = lines - 1; h >= 0; h--) {
3376 dstpixel=(DWORD*)dstbits;
3377 for (x = 0; x < width; x++) {
3378 PALETTEENTRY srcval;
3379 srcval = srccolors[XGetPixel(bmpImage, x, h)];
3380 *dstpixel++=(srcval.peRed << rShift) |
3381 (srcval.peGreen << gShift) |
3382 (srcval.peBlue << bShift);
3384 dstbits += linebytes;
3386 } else {
3387 goto notsupported;
3389 break;
3391 case 8:
3392 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
3393 /* ==== pal 8 bmp -> any 0888 dib ==== */
3394 int rShift,gShift,bShift;
3395 const void* srcbits;
3396 const BYTE* srcpixel;
3397 DWORD* dstpixel;
3399 rShift=X11DRV_DIB_MaskToShift(rDst);
3400 gShift=X11DRV_DIB_MaskToShift(gDst);
3401 bShift=X11DRV_DIB_MaskToShift(bDst);
3402 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3403 for (h = lines - 1; h >= 0; h--) {
3404 srcpixel=srcbits;
3405 dstpixel=(DWORD*)dstbits;
3406 for (x = 0; x < width; x++) {
3407 PALETTEENTRY srcval;
3408 srcval=srccolors[(int)*srcpixel++];
3409 *dstpixel++=(srcval.peRed << rShift) |
3410 (srcval.peGreen << gShift) |
3411 (srcval.peBlue << bShift);
3413 srcbits = (const char*)srcbits - bmpImage->bytes_per_line;
3414 dstbits += linebytes;
3416 } else {
3417 goto notsupported;
3419 break;
3421 default:
3422 notsupported:
3424 /* ==== any bmp format -> any 0888 dib ==== */
3425 int rShift,gShift,bShift;
3426 DWORD* dstpixel;
3428 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 32 bit DIB (%lx,%lx,%lx)\n",
3429 bmpImage->depth, bmpImage->red_mask,
3430 bmpImage->green_mask, bmpImage->blue_mask,
3431 rDst,gDst,bDst);
3433 rShift=X11DRV_DIB_MaskToShift(rDst);
3434 gShift=X11DRV_DIB_MaskToShift(gDst);
3435 bShift=X11DRV_DIB_MaskToShift(bDst);
3436 for (h = lines - 1; h >= 0; h--) {
3437 dstpixel=(DWORD*)dstbits;
3438 for (x = 0; x < width; x++) {
3439 COLORREF srcval;
3440 srcval=X11DRV_PALETTE_ToLogical(XGetPixel(bmpImage, x, h));
3441 *dstpixel++=(GetRValue(srcval) << rShift) |
3442 (GetGValue(srcval) << gShift) |
3443 (GetBValue(srcval) << bShift);
3445 dstbits += linebytes;
3448 break;
3452 static int XGetSubImageErrorHandler(Display *dpy, XErrorEvent *event, void *arg)
3454 return (event->request_code == X_GetImage && event->error_code == BadMatch);
3457 /***********************************************************************
3458 * X11DRV_DIB_SetImageBits_GetSubImage
3460 * Helper for X11DRV_DIB_SetImageBits
3462 static void X11DRV_DIB_SetImageBits_GetSubImage(
3463 const X11DRV_DIB_IMAGEBITS_DESCR *descr, XImage *bmpImage)
3465 /* compressed bitmaps may contain gaps in them. So make a copy
3466 * of the existing pixels first */
3467 RECT bmprc, rc;
3469 SetRect( &bmprc, descr->xDest, descr->yDest,
3470 descr->xDest + descr->width , descr->yDest + descr->height );
3471 GetRgnBox( descr->physDev->region, &rc );
3472 /* convert from dc to drawable origin */
3473 OffsetRect( &rc, descr->physDev->org.x, descr->physDev->org.y);
3474 /* clip visible rect with bitmap */
3475 if( IntersectRect( &rc, &rc, &bmprc))
3477 X11DRV_expect_error( gdi_display, XGetSubImageErrorHandler, NULL );
3478 XGetSubImage( gdi_display, descr->drawable, rc.left, rc.top,
3479 rc.right - rc.left, rc.bottom - rc.top, AllPlanes,
3480 ZPixmap, bmpImage,
3481 descr->xSrc + rc.left - bmprc.left,
3482 descr->ySrc + rc.top - bmprc.top);
3483 X11DRV_check_error();
3487 /***********************************************************************
3488 * X11DRV_DIB_SetImageBits
3490 * Transfer the bits to an X image.
3491 * Helper function for SetDIBits() and SetDIBitsToDevice().
3493 static int X11DRV_DIB_SetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
3495 int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
3496 XImage *bmpImage;
3498 wine_tsx11_lock();
3499 if (descr->image)
3500 bmpImage = descr->image;
3501 else {
3502 bmpImage = XCreateImage( gdi_display, visual, descr->depth, ZPixmap, 0, NULL,
3503 descr->infoWidth, lines, 32, 0 );
3504 bmpImage->data = calloc( lines, bmpImage->bytes_per_line );
3505 if(bmpImage->data == NULL) {
3506 ERR("Out of memory!\n");
3507 XDestroyImage( bmpImage );
3508 wine_tsx11_unlock();
3509 return lines;
3513 TRACE("Dib: depth=%d r=%lx g=%lx b=%lx\n",
3514 descr->infoBpp,descr->rMask,descr->gMask,descr->bMask);
3515 TRACE("Bmp: depth=%d/%d r=%lx g=%lx b=%lx\n",
3516 bmpImage->depth,bmpImage->bits_per_pixel,
3517 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
3519 /* Transfer the pixels */
3520 switch(descr->infoBpp)
3522 case 1:
3523 X11DRV_DIB_SetImageBits_1( descr->lines, descr->bits, descr->infoWidth,
3524 descr->width, descr->xSrc, (int *)(descr->colorMap),
3525 bmpImage, descr->dibpitch );
3526 break;
3527 case 4:
3528 if (descr->compression) {
3529 X11DRV_DIB_SetImageBits_GetSubImage( descr, bmpImage);
3530 X11DRV_DIB_SetImageBits_RLE4( descr->lines, descr->bits,
3531 descr->infoWidth, descr->width,
3532 descr->xSrc, (int *)(descr->colorMap),
3533 bmpImage );
3534 } else
3535 X11DRV_DIB_SetImageBits_4( descr->lines, descr->bits,
3536 descr->infoWidth, descr->width,
3537 descr->xSrc, (int*)(descr->colorMap),
3538 bmpImage, descr->dibpitch );
3539 break;
3540 case 8:
3541 if (descr->compression) {
3542 X11DRV_DIB_SetImageBits_GetSubImage( descr, bmpImage);
3543 X11DRV_DIB_SetImageBits_RLE8( descr->lines, descr->bits,
3544 descr->infoWidth, descr->width,
3545 descr->xSrc, (int *)(descr->colorMap),
3546 bmpImage );
3547 } else
3548 X11DRV_DIB_SetImageBits_8( descr->lines, descr->bits,
3549 descr->infoWidth, descr->width,
3550 descr->xSrc, (int *)(descr->colorMap),
3551 bmpImage, descr->dibpitch );
3552 break;
3553 case 15:
3554 case 16:
3555 X11DRV_DIB_SetImageBits_16( descr->lines, descr->bits,
3556 descr->infoWidth, descr->width,
3557 descr->xSrc, descr->physDev,
3558 descr->rMask, descr->gMask, descr->bMask,
3559 bmpImage, descr->dibpitch);
3560 break;
3561 case 24:
3562 X11DRV_DIB_SetImageBits_24( descr->lines, descr->bits,
3563 descr->infoWidth, descr->width,
3564 descr->xSrc, descr->physDev,
3565 descr->rMask, descr->gMask, descr->bMask,
3566 bmpImage, descr->dibpitch);
3567 break;
3568 case 32:
3569 X11DRV_DIB_SetImageBits_32( descr->lines, descr->bits,
3570 descr->infoWidth, descr->width,
3571 descr->xSrc, descr->physDev,
3572 descr->rMask, descr->gMask, descr->bMask,
3573 bmpImage, descr->dibpitch);
3574 break;
3575 default:
3576 WARN("(%d): Invalid depth\n", descr->infoBpp );
3577 break;
3580 TRACE("XPutImage(%ld,%p,%p,%d,%d,%d,%d,%d,%d)\n",
3581 descr->drawable, descr->gc, bmpImage,
3582 descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
3583 descr->width, descr->height);
3584 #ifdef HAVE_LIBXXSHM
3585 if (descr->useShm)
3587 XShmPutImage( gdi_display, descr->drawable, descr->gc, bmpImage,
3588 descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
3589 descr->width, descr->height, FALSE );
3590 XSync( gdi_display, 0 );
3592 else
3593 #endif
3594 XPutImage( gdi_display, descr->drawable, descr->gc, bmpImage,
3595 descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
3596 descr->width, descr->height );
3598 if (!descr->image) XDestroyImage( bmpImage );
3599 wine_tsx11_unlock();
3600 return lines;
3603 /***********************************************************************
3604 * X11DRV_DIB_GetImageBits
3606 * Transfer the bits from an X image.
3608 static int X11DRV_DIB_GetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
3610 int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
3611 XImage *bmpImage;
3613 wine_tsx11_lock();
3614 if (descr->image)
3615 bmpImage = descr->image;
3616 else {
3617 bmpImage = XCreateImage( gdi_display, visual, descr->depth, ZPixmap, 0, NULL,
3618 descr->infoWidth, lines, 32, 0 );
3619 bmpImage->data = calloc( lines, bmpImage->bytes_per_line );
3620 if(bmpImage->data == NULL) {
3621 ERR("Out of memory!\n");
3622 XDestroyImage( bmpImage );
3623 wine_tsx11_unlock();
3624 return lines;
3628 #ifdef HAVE_LIBXXSHM
3629 if (descr->useShm)
3631 int saveRed, saveGreen, saveBlue;
3633 TRACE("XShmGetImage(%p, %ld, %p, %d, %d, %ld)\n",
3634 gdi_display, descr->drawable, bmpImage,
3635 descr->xSrc, descr->ySrc, AllPlanes);
3637 /* We must save and restore the bmpImage's masks in order
3638 * to preserve them across the call to XShmGetImage, which
3639 * decides to eleminate them since it doesn't happen to know
3640 * what the format of the image is supposed to be, even though
3641 * we do. */
3642 saveRed = bmpImage->red_mask;
3643 saveBlue= bmpImage->blue_mask;
3644 saveGreen = bmpImage->green_mask;
3646 XShmGetImage( gdi_display, descr->drawable, bmpImage,
3647 descr->xSrc, descr->ySrc, AllPlanes);
3649 bmpImage->red_mask = saveRed;
3650 bmpImage->blue_mask = saveBlue;
3651 bmpImage->green_mask = saveGreen;
3653 else
3654 #endif /* HAVE_LIBXXSHM */
3656 TRACE("XGetSubImage(%p,%ld,%d,%d,%d,%d,%ld,%d,%p,%d,%d)\n",
3657 gdi_display, descr->drawable, descr->xSrc, descr->ySrc, descr->width,
3658 lines, AllPlanes, ZPixmap, bmpImage, descr->xDest, descr->yDest);
3659 XGetSubImage( gdi_display, descr->drawable, descr->xSrc, descr->ySrc,
3660 descr->width, lines, AllPlanes, ZPixmap,
3661 bmpImage, descr->xDest, descr->yDest );
3664 TRACE("Dib: depth=%2d r=%lx g=%lx b=%lx\n",
3665 descr->infoBpp,descr->rMask,descr->gMask,descr->bMask);
3666 TRACE("Bmp: depth=%2d/%2d r=%lx g=%lx b=%lx\n",
3667 bmpImage->depth,bmpImage->bits_per_pixel,
3668 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
3669 /* Transfer the pixels */
3670 switch(descr->infoBpp)
3672 case 1:
3673 X11DRV_DIB_GetImageBits_1( descr->lines,(LPVOID)descr->bits,
3674 descr->infoWidth, descr->width,
3675 descr->colorMap, descr->palentry,
3676 bmpImage, descr->dibpitch );
3677 break;
3679 case 4:
3680 if (descr->compression) {
3681 FIXME("Compression not yet supported!\n");
3682 if(descr->sizeImage < X11DRV_DIB_GetDIBWidthBytes( descr->infoWidth, 4 ) * abs(descr->lines))
3683 break;
3685 X11DRV_DIB_GetImageBits_4( descr->lines,(LPVOID)descr->bits,
3686 descr->infoWidth, descr->width,
3687 descr->colorMap, descr->palentry,
3688 bmpImage, descr->dibpitch );
3689 break;
3690 case 8:
3691 if (descr->compression) {
3692 FIXME("Compression not yet supported!\n");
3693 if(descr->sizeImage < X11DRV_DIB_GetDIBWidthBytes( descr->infoWidth, 8 ) * abs(descr->lines))
3694 break;
3696 X11DRV_DIB_GetImageBits_8( descr->lines, (LPVOID)descr->bits,
3697 descr->infoWidth, descr->width,
3698 descr->colorMap, descr->palentry,
3699 bmpImage, descr->dibpitch );
3700 break;
3701 case 15:
3702 case 16:
3703 X11DRV_DIB_GetImageBits_16( descr->lines, (LPVOID)descr->bits,
3704 descr->infoWidth,descr->width,
3705 descr->palentry,
3706 descr->rMask, descr->gMask, descr->bMask,
3707 bmpImage, descr->dibpitch );
3708 break;
3710 case 24:
3711 X11DRV_DIB_GetImageBits_24( descr->lines, (LPVOID)descr->bits,
3712 descr->infoWidth,descr->width,
3713 descr->palentry,
3714 descr->rMask, descr->gMask, descr->bMask,
3715 bmpImage, descr->dibpitch);
3716 break;
3718 case 32:
3719 X11DRV_DIB_GetImageBits_32( descr->lines, (LPVOID)descr->bits,
3720 descr->infoWidth, descr->width,
3721 descr->palentry,
3722 descr->rMask, descr->gMask, descr->bMask,
3723 bmpImage, descr->dibpitch);
3724 break;
3726 default:
3727 WARN("(%d): Invalid depth\n", descr->infoBpp );
3728 break;
3731 if (!descr->image) XDestroyImage( bmpImage );
3732 wine_tsx11_unlock();
3733 return lines;
3736 /*************************************************************************
3737 * X11DRV_SetDIBitsToDevice
3740 INT X11DRV_SetDIBitsToDevice( X11DRV_PDEVICE *physDev, INT xDest, INT yDest, DWORD cx,
3741 DWORD cy, INT xSrc, INT ySrc,
3742 UINT startscan, UINT lines, LPCVOID bits,
3743 const BITMAPINFO *info, UINT coloruse )
3745 X11DRV_DIB_IMAGEBITS_DESCR descr;
3746 INT result;
3747 LONG width, height;
3748 BOOL top_down;
3749 POINT pt;
3750 void* colorPtr;
3752 if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height,
3753 &descr.infoBpp, &descr.compression ) == -1)
3754 return 0;
3756 top_down = (height < 0);
3757 if (top_down) height = -height;
3759 pt.x = xDest;
3760 pt.y = yDest;
3761 LPtoDP(physDev->hdc, &pt, 1);
3763 if (!lines || (startscan >= height)) return 0;
3764 if (!top_down && startscan + lines > height) lines = height - startscan;
3766 /* make xSrc,ySrc point to the upper-left corner, not the lower-left one,
3767 * and clamp all values to fit inside [startscan,startscan+lines]
3769 if (ySrc + cy <= startscan + lines)
3771 UINT y = startscan + lines - (ySrc + cy);
3772 if (ySrc < startscan) cy -= (startscan - ySrc);
3773 if (!top_down)
3775 /* avoid getting unnecessary lines */
3776 ySrc = 0;
3777 if (y >= lines) return 0;
3778 lines -= y;
3780 else
3782 if (y >= lines) return lines;
3783 ySrc = y; /* need to get all lines in top down mode */
3786 else
3788 if (ySrc >= startscan + lines) return lines;
3789 pt.y += ySrc + cy - (startscan + lines);
3790 cy = startscan + lines - ySrc;
3791 ySrc = 0;
3792 if (cy > lines) cy = lines;
3794 if (xSrc >= width) return lines;
3795 if (xSrc + cx >= width) cx = width - xSrc;
3796 if (!cx || !cy) return lines;
3798 /* Update the pixmap from the DIB section */
3799 X11DRV_LockDIBSection(physDev, DIB_Status_GdiMod, FALSE);
3801 X11DRV_SetupGCForText( physDev ); /* To have the correct colors */
3802 wine_tsx11_lock();
3803 XSetFunction(gdi_display, physDev->gc, X11DRV_XROPfunction[GetROP2(physDev->hdc) - 1]);
3804 wine_tsx11_unlock();
3806 colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
3808 switch (descr.infoBpp)
3810 case 1:
3811 case 4:
3812 case 8:
3813 descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap(
3814 coloruse == DIB_PAL_COLORS ? physDev : NULL, coloruse,
3815 physDev->depth, info, &descr.nColorMap );
3816 if (!descr.colorMap) return 0;
3817 descr.rMask = descr.gMask = descr.bMask = 0;
3818 break;
3819 case 15:
3820 case 16:
3821 descr.rMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)colorPtr ) : 0x7c00;
3822 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)colorPtr + 1) : 0x03e0;
3823 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)colorPtr + 2) : 0x001f;
3824 descr.colorMap = 0;
3825 break;
3827 case 24:
3828 case 32:
3829 descr.rMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)colorPtr ) : 0xff0000;
3830 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)colorPtr + 1) : 0x00ff00;
3831 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)colorPtr + 2) : 0x0000ff;
3832 descr.colorMap = 0;
3833 break;
3836 descr.physDev = physDev;
3837 descr.bits = bits;
3838 descr.image = NULL;
3839 descr.palentry = NULL;
3840 descr.lines = top_down ? -lines : lines;
3841 descr.infoWidth = width;
3842 descr.depth = physDev->depth;
3843 descr.drawable = physDev->drawable;
3844 descr.gc = physDev->gc;
3845 descr.xSrc = xSrc;
3846 descr.ySrc = ySrc;
3847 descr.xDest = physDev->org.x + pt.x;
3848 descr.yDest = physDev->org.y + pt.y;
3849 descr.width = cx;
3850 descr.height = cy;
3851 descr.useShm = FALSE;
3852 descr.dibpitch = ((width * descr.infoBpp + 31) &~31) / 8;
3854 result = X11DRV_DIB_SetImageBits( &descr );
3856 if (descr.infoBpp <= 8)
3857 HeapFree(GetProcessHeap(), 0, descr.colorMap);
3859 /* Update the DIBSection of the pixmap */
3860 X11DRV_UnlockDIBSection(physDev, TRUE);
3862 return result;
3865 /***********************************************************************
3866 * SetDIBits (X11DRV.@)
3868 INT X11DRV_SetDIBits( X11DRV_PDEVICE *physDev, HBITMAP hbitmap, UINT startscan,
3869 UINT lines, LPCVOID bits, const BITMAPINFO *info, UINT coloruse )
3871 X_PHYSBITMAP *physBitmap = X11DRV_get_phys_bitmap( hbitmap );
3872 X11DRV_DIB_IMAGEBITS_DESCR descr;
3873 BITMAP bitmap;
3874 LONG height, tmpheight;
3875 INT result;
3876 void* colorPtr;
3878 descr.physDev = physDev;
3880 if (!physBitmap) return 0;
3882 if (DIB_GetBitmapInfo( &info->bmiHeader, &descr.infoWidth, &height,
3883 &descr.infoBpp, &descr.compression ) == -1)
3884 return 0;
3886 tmpheight = height;
3887 if (height < 0) height = -height;
3888 if (!lines || (startscan >= height))
3889 return 0;
3891 if (!GetObjectW( hbitmap, sizeof(bitmap), &bitmap )) return 0;
3893 if (startscan + lines > height) lines = height - startscan;
3895 colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
3897 switch (descr.infoBpp)
3899 case 1:
3900 case 4:
3901 case 8:
3902 descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap(
3903 coloruse == DIB_PAL_COLORS ? descr.physDev : NULL, coloruse,
3904 physBitmap->pixmap_depth,
3905 info, &descr.nColorMap );
3906 if (!descr.colorMap) return 0;
3907 descr.rMask = descr.gMask = descr.bMask = 0;
3908 break;
3909 case 15:
3910 case 16:
3911 descr.rMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD*)colorPtr ) : 0x7c00;
3912 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD*)colorPtr + 1) : 0x03e0;
3913 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD*)colorPtr + 2) : 0x001f;
3914 descr.colorMap = 0;
3915 break;
3917 case 24:
3918 case 32:
3919 descr.rMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD*)colorPtr ) : 0xff0000;
3920 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD*)colorPtr + 1) : 0x00ff00;
3921 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD*)colorPtr + 2) : 0x0000ff;
3922 descr.colorMap = 0;
3923 break;
3925 default: break;
3928 descr.bits = bits;
3929 descr.image = NULL;
3930 descr.palentry = NULL;
3931 descr.lines = tmpheight >= 0 ? lines : -lines;
3932 descr.depth = physBitmap->pixmap_depth;
3933 descr.drawable = physBitmap->pixmap;
3934 descr.gc = BITMAP_GC(physBitmap);
3935 descr.xSrc = 0;
3936 descr.ySrc = 0;
3937 descr.xDest = 0;
3938 descr.yDest = height - startscan - lines;
3939 descr.width = bitmap.bmWidth;
3940 descr.height = lines;
3941 descr.useShm = FALSE;
3942 descr.dibpitch = ((descr.infoWidth * descr.infoBpp + 31) &~31) / 8;
3943 X11DRV_DIB_Lock( physBitmap, DIB_Status_GdiMod, FALSE );
3944 result = X11DRV_DIB_SetImageBits( &descr );
3945 X11DRV_DIB_Unlock( physBitmap, TRUE );
3947 HeapFree(GetProcessHeap(), 0, descr.colorMap);
3949 return result;
3952 /***********************************************************************
3953 * GetDIBits (X11DRV.@)
3955 INT X11DRV_GetDIBits( X11DRV_PDEVICE *physDev, HBITMAP hbitmap, UINT startscan, UINT lines,
3956 LPVOID bits, BITMAPINFO *info, UINT coloruse )
3958 X_PHYSBITMAP *physBitmap = X11DRV_get_phys_bitmap( hbitmap );
3959 DIBSECTION dib;
3960 X11DRV_DIB_IMAGEBITS_DESCR descr;
3961 PALETTEENTRY palette[256];
3962 size_t obj_size;
3963 int height;
3964 LONG tempHeight;
3965 int bitmap_type;
3966 BOOL core_header;
3967 void* colorPtr;
3969 GetPaletteEntries( GetCurrentObject( physDev->hdc, OBJ_PAL ), 0, 256, palette );
3971 if (!physBitmap) return 0;
3972 if (!(obj_size = GetObjectW( hbitmap, sizeof(dib), &dib ))) return 0;
3974 bitmap_type = DIB_GetBitmapInfo( (BITMAPINFOHEADER*) info, &descr.infoWidth, &tempHeight, &descr.infoBpp, &descr.compression);
3975 descr.lines = tempHeight;
3976 if (bitmap_type == -1)
3978 ERR("Invalid bitmap\n");
3979 return 0;
3981 core_header = (bitmap_type == 0);
3982 colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
3984 TRACE("%u scanlines of (%i,%i) -> (%i,%i) starting from %u\n",
3985 lines, dib.dsBm.bmWidth, dib.dsBm.bmHeight, (int)descr.infoWidth, descr.lines, startscan);
3987 if( lines > dib.dsBm.bmHeight ) lines = dib.dsBm.bmHeight;
3989 height = descr.lines;
3990 if (height < 0) height = -height;
3991 if( lines > height ) lines = height;
3992 /* Top-down images have a negative biHeight, the scanlines of theses images
3993 * were inverted in X11DRV_DIB_GetImageBits_xx
3994 * To prevent this we simply change the sign of lines
3995 * (the number of scan lines to copy).
3996 * Negative lines are correctly handled by X11DRV_DIB_GetImageBits_xx.
3998 if( descr.lines < 0 && lines > 0) lines = -lines;
4000 if( startscan >= dib.dsBm.bmHeight ) return 0;
4002 descr.colorMap = NULL;
4004 switch (descr.infoBpp)
4006 case 1:
4007 case 4:
4008 case 8:
4009 descr.rMask= descr.gMask = descr.bMask = 0;
4010 if(coloruse == DIB_RGB_COLORS)
4011 descr.colorMap = colorPtr;
4012 else {
4013 int num_colors = 1 << descr.infoBpp, i;
4014 RGBQUAD *rgb;
4015 COLORREF colref;
4016 WORD *index = (WORD*)colorPtr;
4017 descr.colorMap = rgb = HeapAlloc(GetProcessHeap(), 0, num_colors * sizeof(RGBQUAD));
4018 for(i = 0; i < num_colors; i++, rgb++, index++) {
4019 colref = X11DRV_PALETTE_ToLogical(X11DRV_PALETTE_ToPhysical(physDev, PALETTEINDEX(*index)));
4020 rgb->rgbRed = GetRValue(colref);
4021 rgb->rgbGreen = GetGValue(colref);
4022 rgb->rgbBlue = GetBValue(colref);
4023 rgb->rgbReserved = 0;
4026 break;
4027 case 15:
4028 case 16:
4029 descr.rMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)colorPtr ) : 0x7c00;
4030 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)colorPtr + 1) : 0x03e0;
4031 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)colorPtr + 2) : 0x001f;
4032 break;
4033 case 24:
4034 case 32:
4035 descr.rMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)colorPtr ) : 0xff0000;
4036 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)colorPtr + 1) : 0x00ff00;
4037 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)colorPtr + 2) : 0x0000ff;
4038 break;
4041 descr.physDev = physDev;
4042 descr.palentry = palette;
4043 descr.bits = bits;
4044 descr.image = NULL;
4045 descr.lines = lines;
4046 descr.depth = physBitmap->pixmap_depth;
4047 descr.drawable = physBitmap->pixmap;
4048 descr.gc = BITMAP_GC(physBitmap);
4049 descr.width = dib.dsBm.bmWidth;
4050 descr.height = dib.dsBm.bmHeight;
4051 descr.xDest = 0;
4052 descr.yDest = 0;
4053 descr.xSrc = 0;
4054 descr.sizeImage = core_header ? 0 : info->bmiHeader.biSizeImage;
4056 if (descr.lines > 0)
4058 descr.ySrc = (descr.height-1) - (startscan + (lines-1));
4060 else
4062 descr.ySrc = startscan;
4064 #ifdef HAVE_LIBXXSHM
4065 descr.useShm = (obj_size == sizeof(DIBSECTION)) && (physBitmap->shminfo.shmid != -1);
4066 #else
4067 descr.useShm = FALSE;
4068 #endif
4069 descr.dibpitch = (obj_size == sizeof(DIBSECTION)) ? dib.dsBm.bmWidthBytes
4070 : (((descr.infoWidth * descr.infoBpp + 31) &~31) / 8);
4072 X11DRV_DIB_Lock( physBitmap, DIB_Status_GdiMod, FALSE );
4073 X11DRV_DIB_GetImageBits( &descr );
4074 X11DRV_DIB_Unlock( physBitmap, TRUE );
4076 if(!core_header && info->bmiHeader.biSizeImage == 0) /* Fill in biSizeImage */
4077 info->bmiHeader.biSizeImage = X11DRV_DIB_GetDIBImageBytes( descr.infoWidth,
4078 descr.lines,
4079 descr.infoBpp);
4081 if (descr.compression == BI_BITFIELDS)
4083 *(DWORD *) colorPtr = descr.rMask;
4084 *((DWORD *)colorPtr + 1) = descr.gMask;
4085 *((DWORD *)colorPtr + 2) = descr.bMask;
4087 else if (!core_header)
4089 /* if RLE or JPEG compression were supported,
4090 * this line would be invalid. */
4091 info->bmiHeader.biCompression = 0;
4094 if(descr.colorMap && descr.colorMap != colorPtr)
4095 HeapFree(GetProcessHeap(), 0, descr.colorMap);
4096 return lines;
4099 /***********************************************************************
4100 * DIB_DoProtectDIBSection
4102 static void X11DRV_DIB_DoProtectDIBSection( X_PHYSBITMAP *physBitmap, DWORD new_prot )
4104 DWORD old_prot;
4105 DIBSECTION dib;
4107 GetObjectW( physBitmap->hbitmap, sizeof(dib), &dib );
4108 VirtualProtect(dib.dsBm.bmBits, dib.dsBmih.biSizeImage, new_prot, &old_prot);
4109 TRACE("Changed protection from %ld to %ld\n", old_prot, new_prot);
4112 /***********************************************************************
4113 * X11DRV_DIB_DoCopyDIBSection
4115 static void X11DRV_DIB_DoCopyDIBSection(X_PHYSBITMAP *physBitmap, BOOL toDIB,
4116 void *colorMap, int nColorMap,
4117 Drawable dest,
4118 DWORD xSrc, DWORD ySrc,
4119 DWORD xDest, DWORD yDest,
4120 DWORD width, DWORD height)
4122 DIBSECTION dibSection;
4123 X11DRV_DIB_IMAGEBITS_DESCR descr;
4124 int identity[2] = {0,1};
4126 if (!GetObjectW( physBitmap->hbitmap, sizeof(dibSection), &dibSection )) return;
4128 descr.physDev = NULL;
4129 descr.palentry = NULL;
4130 descr.infoWidth = dibSection.dsBmih.biWidth;
4131 descr.infoBpp = dibSection.dsBmih.biBitCount;
4132 descr.lines = dibSection.dsBmih.biHeight;
4133 descr.image = physBitmap->image;
4134 descr.colorMap = colorMap;
4135 descr.nColorMap = nColorMap;
4136 descr.bits = dibSection.dsBm.bmBits;
4137 descr.depth = physBitmap->pixmap_depth;
4138 descr.compression = dibSection.dsBmih.biCompression;
4140 if(descr.infoBpp == 1)
4141 descr.colorMap = (void*)identity;
4143 switch (descr.infoBpp)
4145 case 1:
4146 case 4:
4147 case 8:
4148 descr.rMask = descr.gMask = descr.bMask = 0;
4149 break;
4150 case 15:
4151 case 16:
4152 descr.rMask = (descr.compression == BI_BITFIELDS) ? dibSection.dsBitfields[0] : 0x7c00;
4153 descr.gMask = (descr.compression == BI_BITFIELDS) ? dibSection.dsBitfields[1] : 0x03e0;
4154 descr.bMask = (descr.compression == BI_BITFIELDS) ? dibSection.dsBitfields[2] : 0x001f;
4155 break;
4157 case 24:
4158 case 32:
4159 descr.rMask = (descr.compression == BI_BITFIELDS) ? dibSection.dsBitfields[0] : 0xff0000;
4160 descr.gMask = (descr.compression == BI_BITFIELDS) ? dibSection.dsBitfields[1] : 0x00ff00;
4161 descr.bMask = (descr.compression == BI_BITFIELDS) ? dibSection.dsBitfields[2] : 0x0000ff;
4162 break;
4165 /* Hack for now */
4166 descr.drawable = dest;
4167 descr.gc = BITMAP_GC(physBitmap);
4168 descr.xSrc = xSrc;
4169 descr.ySrc = ySrc;
4170 descr.xDest = xDest;
4171 descr.yDest = yDest;
4172 descr.width = width;
4173 descr.height = height;
4174 descr.sizeImage = 0;
4176 #ifdef HAVE_LIBXXSHM
4177 descr.useShm = (physBitmap->shminfo.shmid != -1);
4178 #else
4179 descr.useShm = FALSE;
4180 #endif
4181 descr.dibpitch = dibSection.dsBm.bmWidthBytes;
4183 if (toDIB)
4185 TRACE("Copying from Pixmap to DIB bits\n");
4186 X11DRV_DIB_GetImageBits( &descr );
4188 else
4190 TRACE("Copying from DIB bits to Pixmap\n");
4191 X11DRV_DIB_SetImageBits( &descr );
4195 /***********************************************************************
4196 * X11DRV_DIB_CopyDIBSection
4198 void X11DRV_DIB_CopyDIBSection(X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE *physDevDst,
4199 DWORD xSrc, DWORD ySrc, DWORD xDest, DWORD yDest,
4200 DWORD width, DWORD height)
4202 DIBSECTION dib;
4203 X_PHYSBITMAP *physBitmap;
4204 int nColorMap = 0, *colorMap = NULL, aColorMap = FALSE;
4206 TRACE("(%p,%p,%ld,%ld,%ld,%ld,%ld,%ld)\n", physDevSrc->hdc, physDevDst->hdc,
4207 xSrc, ySrc, xDest, yDest, width, height);
4208 /* this function is meant as an optimization for BitBlt,
4209 * not to be called otherwise */
4210 physBitmap = physDevSrc->bitmap;
4211 if (!physBitmap || GetObjectW( physBitmap->hbitmap, sizeof(dib), &dib ) != sizeof(dib))
4213 ERR("called for non-DIBSection!?\n");
4214 return;
4216 /* while BitBlt should already have made sure we only get
4217 * positive values, we should check for oversize values */
4218 if ((xSrc < dib.dsBm.bmWidth) &&
4219 (ySrc < dib.dsBm.bmHeight)) {
4220 if (xSrc + width > dib.dsBm.bmWidth)
4221 width = dib.dsBm.bmWidth - xSrc;
4222 if (ySrc + height > dib.dsBm.bmHeight)
4223 height = dib.dsBm.bmHeight - ySrc;
4224 /* if the source bitmap is 8bpp or less, we're supposed to use the
4225 * DC's palette for color conversion (not the DIB color table) */
4226 if (dib.dsBm.bmBitsPixel <= 8) {
4227 HPALETTE hPalette = GetCurrentObject( physDevSrc->hdc, OBJ_PAL );
4228 if (!hPalette || (hPalette == GetStockObject(DEFAULT_PALETTE))) {
4229 /* HACK: no palette has been set in the source DC,
4230 * use the DIB colormap instead - this is necessary in some
4231 * cases since we need to do depth conversion in some places
4232 * where real Windows can just copy data straight over */
4233 colorMap = physBitmap->colorMap;
4234 nColorMap = physBitmap->nColorMap;
4235 } else {
4236 colorMap = X11DRV_DIB_BuildColorMap( physDevSrc, (WORD)-1,
4237 dib.dsBm.bmBitsPixel,
4238 (BITMAPINFO*)&dib.dsBmih,
4239 &nColorMap );
4240 if (colorMap) aColorMap = TRUE;
4243 /* perform the copy */
4244 X11DRV_DIB_DoCopyDIBSection(physBitmap, FALSE, colorMap, nColorMap,
4245 physDevDst->drawable, xSrc, ySrc,
4246 physDevDst->org.x + xDest, physDevDst->org.y + yDest,
4247 width, height);
4248 /* free color mapping */
4249 if (aColorMap)
4250 HeapFree(GetProcessHeap(), 0, colorMap);
4254 /***********************************************************************
4255 * X11DRV_DIB_DoUpdateDIBSection
4257 static void X11DRV_DIB_DoUpdateDIBSection(X_PHYSBITMAP *physBitmap, BOOL toDIB)
4259 BITMAP bitmap;
4261 GetObjectW( physBitmap->hbitmap, sizeof(bitmap), &bitmap );
4262 X11DRV_DIB_DoCopyDIBSection(physBitmap, toDIB,
4263 physBitmap->colorMap, physBitmap->nColorMap,
4264 physBitmap->pixmap, 0, 0, 0, 0,
4265 bitmap.bmWidth, bitmap.bmHeight);
4268 /***********************************************************************
4269 * X11DRV_DIB_FaultHandler
4271 static BOOL X11DRV_DIB_FaultHandler( LPVOID res, LPCVOID addr )
4273 X_PHYSBITMAP *physBitmap = res;
4274 INT state = X11DRV_DIB_Lock( physBitmap, DIB_Status_None, FALSE );
4276 if (state != DIB_Status_InSync) {
4277 /* no way to tell whether app needs read or write yet,
4278 * try read first */
4279 X11DRV_DIB_Coerce( physBitmap, DIB_Status_InSync, FALSE );
4280 } else {
4281 /* hm, apparently the app must have write access */
4282 X11DRV_DIB_Coerce( physBitmap, DIB_Status_AppMod, FALSE );
4284 X11DRV_DIB_Unlock( physBitmap, TRUE );
4286 return TRUE;
4289 /***********************************************************************
4290 * X11DRV_DIB_Coerce
4292 static INT X11DRV_DIB_Coerce(X_PHYSBITMAP *physBitmap, INT req, BOOL lossy)
4294 INT ret = DIB_Status_None;
4296 if (!physBitmap->image) return ret; /* not a DIB section */
4297 EnterCriticalSection(&physBitmap->lock);
4298 ret = physBitmap->status;
4299 switch (req) {
4300 case DIB_Status_GdiMod:
4301 /* GDI access - request to draw on pixmap */
4302 switch (physBitmap->status)
4304 default:
4305 case DIB_Status_None:
4306 physBitmap->p_status = DIB_Status_GdiMod;
4307 X11DRV_DIB_DoUpdateDIBSection( physBitmap, FALSE );
4308 break;
4310 case DIB_Status_GdiMod:
4311 TRACE("GdiMod requested in status GdiMod\n" );
4312 physBitmap->p_status = DIB_Status_GdiMod;
4313 break;
4315 case DIB_Status_InSync:
4316 TRACE("GdiMod requested in status InSync\n" );
4317 X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_NOACCESS );
4318 physBitmap->status = DIB_Status_GdiMod;
4319 physBitmap->p_status = DIB_Status_InSync;
4320 break;
4322 case DIB_Status_AppMod:
4323 TRACE("GdiMod requested in status AppMod\n" );
4324 if (!lossy) {
4325 /* make it readonly to avoid app changing data while we copy */
4326 X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_READONLY );
4327 X11DRV_DIB_DoUpdateDIBSection( physBitmap, FALSE );
4329 X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_NOACCESS );
4330 physBitmap->p_status = DIB_Status_AppMod;
4331 physBitmap->status = DIB_Status_GdiMod;
4332 break;
4334 break;
4336 case DIB_Status_InSync:
4337 /* App access - request access to read DIB surface */
4338 /* (typically called from signal handler) */
4339 switch (physBitmap->status)
4341 default:
4342 case DIB_Status_None:
4343 /* shouldn't happen from signal handler */
4344 break;
4346 case DIB_Status_GdiMod:
4347 TRACE("InSync requested in status GdiMod\n" );
4348 if (!lossy) {
4349 X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_READWRITE );
4350 X11DRV_DIB_DoUpdateDIBSection( physBitmap, TRUE );
4352 X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_READONLY );
4353 physBitmap->status = DIB_Status_InSync;
4354 break;
4356 case DIB_Status_InSync:
4357 TRACE("InSync requested in status InSync\n" );
4358 /* shouldn't happen from signal handler */
4359 break;
4361 case DIB_Status_AppMod:
4362 TRACE("InSync requested in status AppMod\n" );
4363 /* no reason to do anything here, and this
4364 * shouldn't happen from signal handler */
4365 break;
4367 break;
4369 case DIB_Status_AppMod:
4370 /* App access - request access to write DIB surface */
4371 /* (typically called from signal handler) */
4372 switch (physBitmap->status)
4374 default:
4375 case DIB_Status_None:
4376 /* shouldn't happen from signal handler */
4377 break;
4379 case DIB_Status_GdiMod:
4380 TRACE("AppMod requested in status GdiMod\n" );
4381 X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_READWRITE );
4382 if (!lossy) X11DRV_DIB_DoUpdateDIBSection( physBitmap, TRUE );
4383 physBitmap->status = DIB_Status_AppMod;
4384 break;
4386 case DIB_Status_InSync:
4387 TRACE("AppMod requested in status InSync\n" );
4388 X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_READWRITE );
4389 physBitmap->status = DIB_Status_AppMod;
4390 break;
4392 case DIB_Status_AppMod:
4393 TRACE("AppMod requested in status AppMod\n" );
4394 /* shouldn't happen from signal handler */
4395 break;
4397 break;
4399 /* it is up to the caller to do the copy/conversion, probably
4400 * using the return value to decide where to copy from */
4402 LeaveCriticalSection(&physBitmap->lock);
4403 return ret;
4406 /***********************************************************************
4407 * X11DRV_DIB_Lock
4409 static INT X11DRV_DIB_Lock(X_PHYSBITMAP *physBitmap, INT req, BOOL lossy)
4411 INT ret = DIB_Status_None;
4413 if (!physBitmap->image) return ret; /* not a DIB section */
4414 TRACE("Locking %p from thread %04lx\n", physBitmap->hbitmap, GetCurrentThreadId());
4415 EnterCriticalSection(&physBitmap->lock);
4416 ret = physBitmap->status;
4417 if (req != DIB_Status_None)
4418 X11DRV_DIB_Coerce(physBitmap, req, lossy);
4419 return ret;
4422 /***********************************************************************
4423 * X11DRV_DIB_Unlock
4425 static void X11DRV_DIB_Unlock(X_PHYSBITMAP *physBitmap, BOOL commit)
4427 if (!physBitmap->image) return; /* not a DIB section */
4428 switch (physBitmap->status)
4430 default:
4431 case DIB_Status_None:
4432 /* in case anyone is wondering, this is the "signal handler doesn't
4433 * work" case, where we always have to be ready for app access */
4434 if (commit) {
4435 switch (physBitmap->p_status)
4437 case DIB_Status_GdiMod:
4438 TRACE("Unlocking and syncing from GdiMod\n" );
4439 X11DRV_DIB_DoUpdateDIBSection( physBitmap, TRUE );
4440 break;
4442 default:
4443 TRACE("Unlocking without needing to sync\n" );
4444 break;
4447 else TRACE("Unlocking with no changes\n");
4448 physBitmap->p_status = DIB_Status_None;
4449 break;
4451 case DIB_Status_GdiMod:
4452 TRACE("Unlocking in status GdiMod\n" );
4453 /* DIB was protected in Coerce */
4454 if (!commit) {
4455 /* no commit, revert to InSync if applicable */
4456 if ((physBitmap->p_status == DIB_Status_InSync) ||
4457 (physBitmap->p_status == DIB_Status_AppMod)) {
4458 X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_READONLY );
4459 physBitmap->status = DIB_Status_InSync;
4462 break;
4464 case DIB_Status_InSync:
4465 TRACE("Unlocking in status InSync\n" );
4466 /* DIB was already protected in Coerce */
4467 break;
4469 case DIB_Status_AppMod:
4470 TRACE("Unlocking in status AppMod\n" );
4471 /* DIB was already protected in Coerce */
4472 /* this case is ordinary only called from the signal handler,
4473 * so we don't bother to check for !commit */
4474 break;
4476 LeaveCriticalSection(&physBitmap->lock);
4477 TRACE("Unlocked %p\n", physBitmap->hbitmap);
4480 /***********************************************************************
4481 * X11DRV_CoerceDIBSection
4483 INT X11DRV_CoerceDIBSection(X11DRV_PDEVICE *physDev, INT req, BOOL lossy)
4485 if (!physDev || !physDev->bitmap) return DIB_Status_None;
4486 return X11DRV_DIB_Coerce(physDev->bitmap, req, lossy);
4489 /***********************************************************************
4490 * X11DRV_LockDIBSection
4492 INT X11DRV_LockDIBSection(X11DRV_PDEVICE *physDev, INT req, BOOL lossy)
4494 if (!physDev || !physDev->bitmap) return DIB_Status_None;
4495 return X11DRV_DIB_Lock(physDev->bitmap, req, lossy);
4498 /***********************************************************************
4499 * X11DRV_UnlockDIBSection
4501 void X11DRV_UnlockDIBSection(X11DRV_PDEVICE *physDev, BOOL commit)
4503 if (!physDev || !physDev->bitmap) return;
4504 X11DRV_DIB_Unlock(physDev->bitmap, commit);
4508 #ifdef HAVE_LIBXXSHM
4509 /***********************************************************************
4510 * X11DRV_XShmErrorHandler
4513 static int XShmErrorHandler( Display *dpy, XErrorEvent *event, void *arg )
4515 return 1; /* FIXME: should check event contents */
4518 /***********************************************************************
4519 * X11DRV_XShmCreateImage
4522 static XImage *X11DRV_XShmCreateImage( int width, int height, int bpp,
4523 XShmSegmentInfo* shminfo)
4525 XImage *image;
4527 image = XShmCreateImage(gdi_display, visual, bpp, ZPixmap, NULL, shminfo, width, height);
4528 if (image)
4530 shminfo->shmid = shmget(IPC_PRIVATE, image->bytes_per_line * height,
4531 IPC_CREAT|0700);
4532 if( shminfo->shmid != -1 )
4534 shminfo->shmaddr = image->data = shmat(shminfo->shmid, 0, 0);
4535 if( shminfo->shmaddr != (char*)-1 )
4537 BOOL ok;
4539 shminfo->readOnly = FALSE;
4540 X11DRV_expect_error( gdi_display, XShmErrorHandler, NULL );
4541 ok = (XShmAttach( gdi_display, shminfo ) != 0);
4542 XSync( gdi_display, False );
4543 if (X11DRV_check_error()) ok = FALSE;
4544 if (ok)
4546 shmctl(shminfo->shmid, IPC_RMID, 0);
4547 return image; /* Success! */
4549 /* An error occurred */
4550 shmdt(shminfo->shmaddr);
4552 shmctl(shminfo->shmid, IPC_RMID, 0);
4554 XFlush(gdi_display);
4555 XDestroyImage(image);
4556 image = NULL;
4558 return image;
4560 #endif /* HAVE_LIBXXSHM */
4563 /***********************************************************************
4564 * X11DRV_CreateDIBSection (X11DRV.@)
4566 HBITMAP X11DRV_CreateDIBSection( X11DRV_PDEVICE *physDev, HBITMAP hbitmap,
4567 const BITMAPINFO *bmi, UINT usage )
4569 extern BOOL VIRTUAL_SetFaultHandler(LPCVOID addr, BOOL (*proc)(LPVOID, LPCVOID), LPVOID arg);
4570 X_PHYSBITMAP *physBitmap;
4571 DIBSECTION dib;
4573 if (!(physBitmap = X11DRV_init_phys_bitmap( hbitmap ))) return 0;
4574 physBitmap->status = DIB_Status_None;
4576 GetObjectW( hbitmap, sizeof(dib), &dib );
4578 /* create color map */
4579 if (dib.dsBm.bmBitsPixel <= 8)
4581 physBitmap->colorMap = X11DRV_DIB_BuildColorMap( usage == DIB_PAL_COLORS ? physDev : NULL,
4582 usage, dib.dsBm.bmBitsPixel, bmi,
4583 &physBitmap->nColorMap );
4584 physBitmap->colorTable = X11DRV_DIB_BuildColorTable( physDev, usage, dib.dsBm.bmBitsPixel, bmi );
4587 /* create pixmap and X image */
4588 wine_tsx11_lock();
4589 physBitmap->pixmap_depth = (dib.dsBm.bmBitsPixel == 1) ? 1 : screen_depth;
4590 physBitmap->pixmap = XCreatePixmap( gdi_display, root_window, dib.dsBm.bmWidth,
4591 dib.dsBm.bmHeight, physBitmap->pixmap_depth );
4592 #ifdef HAVE_LIBXXSHM
4593 physBitmap->shminfo.shmid = -1;
4594 if (!XShmQueryExtension(gdi_display) ||
4595 !(physBitmap->image = X11DRV_XShmCreateImage( dib.dsBm.bmWidth, dib.dsBm.bmHeight,
4596 physBitmap->pixmap_depth, &physBitmap->shminfo )) )
4597 #endif
4598 physBitmap->image = X11DRV_DIB_CreateXImage( dib.dsBm.bmWidth, dib.dsBm.bmHeight,
4599 physBitmap->pixmap_depth );
4600 wine_tsx11_unlock();
4601 if (!physBitmap->pixmap || !physBitmap->image) return 0;
4603 /* install fault handler */
4604 InitializeCriticalSection( &physBitmap->lock );
4605 if (VIRTUAL_SetFaultHandler(dib.dsBm.bmBits, X11DRV_DIB_FaultHandler, physBitmap))
4607 X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_READWRITE );
4608 physBitmap->status = DIB_Status_AppMod;
4611 return hbitmap;
4614 /***********************************************************************
4615 * X11DRV_DIB_DeleteDIBSection
4617 void X11DRV_DIB_DeleteDIBSection(X_PHYSBITMAP *physBitmap, DIBSECTION *dib)
4619 if (dib->dshSection)
4620 X11DRV_DIB_Coerce(physBitmap, DIB_Status_InSync, FALSE);
4622 if (physBitmap->image)
4624 wine_tsx11_lock();
4625 #ifdef HAVE_LIBXXSHM
4626 if (physBitmap->shminfo.shmid != -1)
4628 XShmDetach( gdi_display, &(physBitmap->shminfo) );
4629 XDestroyImage( physBitmap->image );
4630 shmdt( physBitmap->shminfo.shmaddr );
4631 physBitmap->shminfo.shmid = -1;
4633 else
4634 #endif
4635 XDestroyImage( physBitmap->image );
4636 wine_tsx11_unlock();
4639 HeapFree(GetProcessHeap(), 0, physBitmap->colorMap);
4640 HeapFree(GetProcessHeap(), 0, physBitmap->colorTable);
4641 DeleteCriticalSection(&physBitmap->lock);
4644 /***********************************************************************
4645 * SetDIBColorTable (X11DRV.@)
4647 UINT X11DRV_SetDIBColorTable( X11DRV_PDEVICE *physDev, UINT start, UINT count, const RGBQUAD *colors )
4649 DIBSECTION dib;
4650 UINT ret = 0;
4651 X_PHYSBITMAP *physBitmap = physDev->bitmap;
4653 if (!physBitmap) return 0;
4654 GetObjectW( physBitmap->hbitmap, sizeof(dib), &dib );
4656 if (physBitmap->colorMap && start < physBitmap->nColorMap) {
4657 UINT end = count + start;
4658 if (end > physBitmap->nColorMap) end = physBitmap->nColorMap;
4660 * Changing color table might change the mapping between
4661 * DIB colors and X11 colors and thus alter the visible state
4662 * of the bitmap object.
4664 X11DRV_DIB_Lock( physBitmap, DIB_Status_AppMod, FALSE );
4665 memcpy(physBitmap->colorTable + start, colors, (end - start) * sizeof(RGBQUAD));
4666 X11DRV_DIB_GenColorMap( physDev, physBitmap->colorMap, DIB_RGB_COLORS,
4667 dib.dsBm.bmBitsPixel,
4668 TRUE, colors, start, end );
4669 X11DRV_DIB_Unlock( physBitmap, TRUE );
4670 ret = end - start;
4672 return ret;
4675 /***********************************************************************
4676 * GetDIBColorTable (X11DRV.@)
4678 UINT X11DRV_GetDIBColorTable( X11DRV_PDEVICE *physDev, UINT start, UINT count, RGBQUAD *colors )
4680 UINT ret = 0;
4681 X_PHYSBITMAP *physBitmap = physDev->bitmap;
4683 if (physBitmap && physBitmap->colorTable && start < physBitmap->nColorMap) {
4684 if (start + count > physBitmap->nColorMap) count = physBitmap->nColorMap - start;
4685 memcpy(colors, physBitmap->colorTable + start, count * sizeof(RGBQUAD));
4686 ret = count;
4688 return ret;
4693 /***********************************************************************
4694 * X11DRV_DIB_CreateDIBFromBitmap
4696 * Allocates a packed DIB and copies the bitmap data into it.
4698 HGLOBAL X11DRV_DIB_CreateDIBFromBitmap(HDC hdc, HBITMAP hBmp)
4700 BITMAP bmp;
4701 HGLOBAL hPackedDIB;
4702 LPBYTE pPackedDIB;
4703 LPBITMAPINFOHEADER pbmiHeader;
4704 unsigned int cDataSize, cPackedSize, OffsetBits;
4705 int nLinesCopied;
4707 if (!GetObjectW( hBmp, sizeof(bmp), &bmp )) return 0;
4710 * A packed DIB contains a BITMAPINFO structure followed immediately by
4711 * an optional color palette and the pixel data.
4714 /* Calculate the size of the packed DIB */
4715 cDataSize = X11DRV_DIB_GetDIBWidthBytes( bmp.bmWidth, bmp.bmBitsPixel ) * abs( bmp.bmHeight );
4716 cPackedSize = sizeof(BITMAPINFOHEADER)
4717 + ( (bmp.bmBitsPixel <= 8) ? (sizeof(RGBQUAD) * (1 << bmp.bmBitsPixel)) : 0 )
4718 + cDataSize;
4719 /* Get the offset to the bits */
4720 OffsetBits = cPackedSize - cDataSize;
4722 /* Allocate the packed DIB */
4723 TRACE("\tAllocating packed DIB of size %d\n", cPackedSize);
4724 hPackedDIB = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE /*| GMEM_ZEROINIT*/,
4725 cPackedSize );
4726 if ( !hPackedDIB )
4728 WARN("Could not allocate packed DIB!\n");
4729 return 0;
4732 /* A packed DIB starts with a BITMAPINFOHEADER */
4733 pPackedDIB = GlobalLock(hPackedDIB);
4734 pbmiHeader = (LPBITMAPINFOHEADER)pPackedDIB;
4736 /* Init the BITMAPINFOHEADER */
4737 pbmiHeader->biSize = sizeof(BITMAPINFOHEADER);
4738 pbmiHeader->biWidth = bmp.bmWidth;
4739 pbmiHeader->biHeight = bmp.bmHeight;
4740 pbmiHeader->biPlanes = 1;
4741 pbmiHeader->biBitCount = bmp.bmBitsPixel;
4742 pbmiHeader->biCompression = BI_RGB;
4743 pbmiHeader->biSizeImage = 0;
4744 pbmiHeader->biXPelsPerMeter = pbmiHeader->biYPelsPerMeter = 0;
4745 pbmiHeader->biClrUsed = 0;
4746 pbmiHeader->biClrImportant = 0;
4748 /* Retrieve the DIB bits from the bitmap and fill in the
4749 * DIB color table if present */
4751 nLinesCopied = GetDIBits(hdc, /* Handle to device context */
4752 hBmp, /* Handle to bitmap */
4753 0, /* First scan line to set in dest bitmap */
4754 bmp.bmHeight, /* Number of scan lines to copy */
4755 pPackedDIB + OffsetBits, /* [out] Address of array for bitmap bits */
4756 (LPBITMAPINFO) pbmiHeader, /* [out] Address of BITMAPINFO structure */
4757 0); /* RGB or palette index */
4758 GlobalUnlock(hPackedDIB);
4760 /* Cleanup if GetDIBits failed */
4761 if (nLinesCopied != bmp.bmHeight)
4763 TRACE("\tGetDIBits returned %d. Actual lines=%d\n", nLinesCopied, bmp.bmHeight);
4764 GlobalFree(hPackedDIB);
4765 hPackedDIB = 0;
4767 return hPackedDIB;
4771 /**************************************************************************
4772 * X11DRV_DIB_CreateDIBFromPixmap
4774 * Allocates a packed DIB and copies the Pixmap data into it.
4775 * The Pixmap passed in is deleted after the conversion.
4777 HGLOBAL X11DRV_DIB_CreateDIBFromPixmap(Pixmap pixmap, HDC hdc)
4779 HDC hdcMem;
4780 X_PHYSBITMAP *physBitmap;
4781 HBITMAP hBmp = 0, old;
4782 HGLOBAL hPackedDIB = 0;
4783 Window root;
4784 int x,y; /* Unused */
4785 unsigned border_width; /* Unused */
4786 unsigned int depth, width, height;
4788 /* Get the Pixmap dimensions and bit depth */
4789 wine_tsx11_lock();
4790 if (!XGetGeometry(gdi_display, pixmap, &root, &x, &y, &width, &height,
4791 &border_width, &depth)) depth = 0;
4792 wine_tsx11_unlock();
4793 if (!depth) return 0;
4795 TRACE("\tPixmap properties: width=%d, height=%d, depth=%d\n",
4796 width, height, depth);
4799 * Create an HBITMAP with the same dimensions and BPP as the pixmap,
4800 * and make it a container for the pixmap passed.
4802 hBmp = CreateBitmap( width, height, 1, depth, NULL );
4804 /* force bitmap to be owned by a screen DC */
4805 hdcMem = CreateCompatibleDC( hdc );
4806 old = SelectObject( hdcMem, hBmp );
4808 physBitmap = X11DRV_get_phys_bitmap( hBmp );
4810 wine_tsx11_lock();
4811 if (physBitmap->pixmap) XFreePixmap( gdi_display, physBitmap->pixmap );
4812 physBitmap->pixmap = pixmap;
4813 wine_tsx11_unlock();
4815 SelectObject( hdcMem, old );
4816 DeleteDC( hdcMem );
4819 * Create a packed DIB from the Pixmap wrapper bitmap created above.
4820 * A packed DIB contains a BITMAPINFO structure followed immediately by
4821 * an optional color palette and the pixel data.
4823 hPackedDIB = X11DRV_DIB_CreateDIBFromBitmap(hdc, hBmp);
4825 /* We can now get rid of the HBITMAP wrapper we created earlier.
4826 * Note: Simply calling DeleteObject will free the embedded Pixmap as well.
4828 DeleteObject(hBmp);
4830 TRACE("\tReturning packed DIB %p\n", hPackedDIB);
4831 return hPackedDIB;
4835 /**************************************************************************
4836 * X11DRV_DIB_CreatePixmapFromDIB
4838 * Creates a Pixmap from a packed DIB
4840 Pixmap X11DRV_DIB_CreatePixmapFromDIB( HGLOBAL hPackedDIB, HDC hdc )
4842 Pixmap pixmap;
4843 X_PHYSBITMAP *physBitmap;
4844 HBITMAP hBmp;
4845 LPBITMAPINFO pbmi;
4847 /* Create a DDB from the DIB */
4849 pbmi = GlobalLock(hPackedDIB);
4850 hBmp = CreateDIBitmap(hdc, &pbmi->bmiHeader, CBM_INIT,
4851 (LPBYTE)pbmi + X11DRV_DIB_BitmapInfoSize( pbmi, DIB_RGB_COLORS ),
4852 pbmi, DIB_RGB_COLORS);
4853 GlobalUnlock(hPackedDIB);
4855 /* clear the physBitmap so that we can steal its pixmap */
4856 physBitmap = X11DRV_get_phys_bitmap( hBmp );
4857 pixmap = physBitmap->pixmap;
4858 physBitmap->pixmap = 0;
4860 /* Delete the DDB we created earlier now that we have stolen its pixmap */
4861 DeleteObject(hBmp);
4863 TRACE("Returning Pixmap %ld\n", pixmap);
4864 return pixmap;