Sync with dibsection in SetDIBitsToDevice.
[wine/multimedia.git] / dlls / x11drv / dib.c
blob50431f32e49cdc83a21341c32691d7f519c604fc
1 /*
2 * X11DRV device-independent bitmaps
4 * Copyright 1993,1994 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "config.h"
23 #include <X11/Xlib.h>
24 #ifdef HAVE_LIBXXSHM
25 #include <X11/extensions/XShm.h>
26 # ifdef HAVE_SYS_SHM_H
27 # include <sys/shm.h>
28 # endif
29 # ifdef HAVE_SYS_IPC_H
30 # include <sys/ipc.h>
31 # endif
32 #endif /* defined(HAVE_LIBXXSHM) */
34 #include <stdarg.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include "windef.h"
38 #include "winbase.h"
39 #include "gdi.h"
40 #include "x11drv.h"
41 #include "wine/debug.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(bitmap);
44 WINE_DECLARE_DEBUG_CHANNEL(x11drv);
46 static int ximageDepthTable[32];
48 /* This structure holds the arguments for DIB_SetImageBits() */
49 typedef struct
51 X11DRV_PDEVICE *physDev;
52 LPCVOID bits;
53 XImage *image;
54 PALETTEENTRY *palentry;
55 int lines;
56 DWORD infoWidth;
57 WORD depth;
58 WORD infoBpp;
59 WORD compression;
60 RGBQUAD *colorMap;
61 int nColorMap;
62 Drawable drawable;
63 GC gc;
64 int xSrc;
65 int ySrc;
66 int xDest;
67 int yDest;
68 int width;
69 int height;
70 DWORD rMask;
71 DWORD gMask;
72 DWORD bMask;
73 BOOL useShm;
74 int dibpitch;
75 DWORD sizeImage;
76 } X11DRV_DIB_IMAGEBITS_DESCR;
79 enum Rle_EscapeCodes
81 RLE_EOL = 0, /* End of line */
82 RLE_END = 1, /* End of bitmap */
83 RLE_DELTA = 2 /* Delta */
86 /***********************************************************************
87 * X11DRV_DIB_GetXImageWidthBytes
89 * Return the width of an X image in bytes
91 inline static int X11DRV_DIB_GetXImageWidthBytes( int width, int depth )
93 if (!depth || depth > 32) goto error;
95 if (!ximageDepthTable[depth-1])
97 XImage *testimage = XCreateImage( gdi_display, visual, depth,
98 ZPixmap, 0, NULL, 1, 1, 32, 20 );
99 if (testimage)
101 ximageDepthTable[depth-1] = testimage->bits_per_pixel;
102 XDestroyImage( testimage );
104 else ximageDepthTable[depth-1] = -1;
106 if (ximageDepthTable[depth-1] != -1)
107 return (4 * ((width * ximageDepthTable[depth-1] + 31) / 32));
109 error:
110 WARN( "(%d): Unsupported depth\n", depth );
111 return 4 * width;
115 /***********************************************************************
116 * X11DRV_DIB_GetDIBWidthBytes
118 * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
120 static int X11DRV_DIB_GetDIBWidthBytes( int width, int depth )
122 int words;
124 switch(depth)
126 case 1: words = (width + 31) / 32; break;
127 case 4: words = (width + 7) / 8; break;
128 case 8: words = (width + 3) / 4; break;
129 case 15:
130 case 16: words = (width + 1) / 2; break;
131 case 24: words = (width * 3 + 3) / 4; break;
132 default:
133 WARN("(%d): Unsupported depth\n", depth );
134 /* fall through */
135 case 32:
136 words = width;
138 return 4 * words;
142 /***********************************************************************
143 * X11DRV_DIB_BitmapInfoSize
145 * Return the size of the bitmap info structure including color table.
147 int X11DRV_DIB_BitmapInfoSize( const BITMAPINFO * info, WORD coloruse )
149 int colors;
151 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
153 BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)info;
154 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
155 return sizeof(BITMAPCOREHEADER) + colors *
156 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
158 else /* assume BITMAPINFOHEADER */
160 colors = info->bmiHeader.biClrUsed;
161 if (!colors && (info->bmiHeader.biBitCount <= 8))
162 colors = 1 << info->bmiHeader.biBitCount;
163 return sizeof(BITMAPINFOHEADER) + colors *
164 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
169 /***********************************************************************
170 * X11DRV_DIB_CreateXImage
172 * Create an X image.
174 XImage *X11DRV_DIB_CreateXImage( int width, int height, int depth )
176 int width_bytes;
177 XImage *image;
179 wine_tsx11_lock();
180 width_bytes = X11DRV_DIB_GetXImageWidthBytes( width, depth );
181 image = XCreateImage( gdi_display, visual, depth, ZPixmap, 0,
182 calloc( height, width_bytes ),
183 width, height, 32, width_bytes );
184 wine_tsx11_unlock();
185 return image;
189 /***********************************************************************
190 * DIB_GetBitmapInfo
192 * Get the info from a bitmap header.
193 * Return 1 for INFOHEADER, 0 for COREHEADER, -1 for error.
195 static int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, DWORD *width,
196 int *height, WORD *bpp, WORD *compr )
198 if (header->biSize == sizeof(BITMAPCOREHEADER))
200 BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)header;
201 *width = core->bcWidth;
202 *height = core->bcHeight;
203 *bpp = core->bcBitCount;
204 *compr = 0;
205 return 0;
207 if (header->biSize >= sizeof(BITMAPINFOHEADER))
209 *width = header->biWidth;
210 *height = header->biHeight;
211 *bpp = header->biBitCount;
212 *compr = header->biCompression;
213 return 1;
215 ERR("(%ld): unknown/wrong size for header\n", header->biSize );
216 return -1;
220 /***********************************************************************
221 * X11DRV_DIB_GenColorMap
223 * Fills the color map of a bitmap palette. Should not be called
224 * for a >8-bit deep bitmap.
226 int *X11DRV_DIB_GenColorMap( X11DRV_PDEVICE *physDev, int *colorMapping,
227 WORD coloruse, WORD depth, BOOL quads,
228 const void *colorPtr, int start, int end )
230 int i;
232 if (coloruse == DIB_RGB_COLORS)
234 int max = 1 << depth;
236 if (end > max) end = max;
238 if (quads)
240 RGBQUAD * rgb = (RGBQUAD *)colorPtr;
242 if (depth == 1) /* Monochrome */
243 for (i = start; i < end; i++, rgb++)
244 colorMapping[i] = (rgb->rgbRed + rgb->rgbGreen +
245 rgb->rgbBlue > 255*3/2);
246 else
247 for (i = start; i < end; i++, rgb++)
248 colorMapping[i] = X11DRV_PALETTE_ToPhysical( physDev, RGB(rgb->rgbRed,
249 rgb->rgbGreen,
250 rgb->rgbBlue));
252 else
254 RGBTRIPLE * rgb = (RGBTRIPLE *)colorPtr;
256 if (depth == 1) /* Monochrome */
257 for (i = start; i < end; i++, rgb++)
258 colorMapping[i] = (rgb->rgbtRed + rgb->rgbtGreen +
259 rgb->rgbtBlue > 255*3/2);
260 else
261 for (i = start; i < end; i++, rgb++)
262 colorMapping[i] = X11DRV_PALETTE_ToPhysical( physDev, RGB(rgb->rgbtRed,
263 rgb->rgbtGreen,
264 rgb->rgbtBlue));
267 else /* DIB_PAL_COLORS */
269 if (colorPtr) {
270 WORD * index = (WORD *)colorPtr;
272 for (i = start; i < end; i++, index++)
273 colorMapping[i] = X11DRV_PALETTE_ToPhysical( physDev, PALETTEINDEX(*index) );
274 } else {
275 for (i = start; i < end; i++)
276 colorMapping[i] = X11DRV_PALETTE_ToPhysical( physDev, PALETTEINDEX(i) );
280 return colorMapping;
283 /***********************************************************************
284 * X11DRV_DIB_BuildColorMap
286 * Build the color map from the bitmap palette. Should not be called
287 * for a >8-bit deep bitmap.
289 int *X11DRV_DIB_BuildColorMap( X11DRV_PDEVICE *physDev, WORD coloruse, WORD depth,
290 const BITMAPINFO *info, int *nColors )
292 int colors;
293 BOOL isInfo;
294 const void *colorPtr;
295 int *colorMapping;
297 if ((isInfo = (info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))))
299 colors = info->bmiHeader.biClrUsed;
300 if (!colors) colors = 1 << info->bmiHeader.biBitCount;
301 colorPtr = info->bmiColors;
303 else /* assume BITMAPCOREINFO */
305 colors = 1 << ((BITMAPCOREHEADER *)&info->bmiHeader)->bcBitCount;
306 colorPtr = (WORD *)((BITMAPCOREINFO *)info)->bmciColors;
309 if (colors > 256)
311 ERR("called with >256 colors!\n");
312 return NULL;
315 /* just so CopyDIBSection doesn't have to create an identity palette */
316 if (coloruse == (WORD)-1) colorPtr = NULL;
318 if (!(colorMapping = (int *)HeapAlloc(GetProcessHeap(), 0,
319 colors * sizeof(int) )))
320 return NULL;
322 *nColors = colors;
323 return X11DRV_DIB_GenColorMap( physDev, colorMapping, coloruse, depth,
324 isInfo, colorPtr, 0, colors);
328 /***********************************************************************
329 * X11DRV_DIB_MapColor
331 int X11DRV_DIB_MapColor( int *physMap, int nPhysMap, int phys, int oldcol )
333 int color;
335 if ((oldcol < nPhysMap) && (physMap[oldcol] == phys))
336 return oldcol;
338 for (color = 0; color < nPhysMap; color++)
339 if (physMap[color] == phys)
340 return color;
342 WARN("Strange color %08x\n", phys);
343 return 0;
347 /*********************************************************************
348 * X11DRV_DIB_GetNearestIndex
350 * Helper for X11DRV_DIB_GetDIBits.
351 * Returns the nearest colour table index for a given RGB.
352 * Nearest is defined by minimizing the sum of the squares.
354 static INT X11DRV_DIB_GetNearestIndex(RGBQUAD *colormap, int numColors, BYTE r, BYTE g, BYTE b)
356 INT i, best = -1, diff, bestdiff = -1;
357 RGBQUAD *color;
359 for(color = colormap, i = 0; i < numColors; color++, i++) {
360 diff = (r - color->rgbRed) * (r - color->rgbRed) +
361 (g - color->rgbGreen) * (g - color->rgbGreen) +
362 (b - color->rgbBlue) * (b - color->rgbBlue);
363 if(diff == 0)
364 return i;
365 if(best == -1 || diff < bestdiff) {
366 best = i;
367 bestdiff = diff;
370 return best;
372 /*********************************************************************
373 * X11DRV_DIB_MaskToShift
375 * Helper for X11DRV_DIB_GetDIBits.
376 * Returns the by how many bits to shift a given color so that it is
377 * in the proper position.
379 INT X11DRV_DIB_MaskToShift(DWORD mask)
381 int shift;
383 if (mask==0)
384 return 0;
386 shift=0;
387 while ((mask&1)==0) {
388 mask>>=1;
389 shift++;
391 return shift;
394 /***********************************************************************
395 * X11DRV_DIB_SetImageBits_1
397 * SetDIBits for a 1-bit deep DIB.
399 static void X11DRV_DIB_SetImageBits_1( int lines, const BYTE *srcbits,
400 DWORD srcwidth, DWORD dstwidth, int left,
401 int *colors, XImage *bmpImage, DWORD linebytes)
403 int h, width;
404 const BYTE* srcbyte;
405 BYTE srcval, extra;
406 DWORD i, x;
408 if (lines < 0 ) {
409 lines = -lines;
410 srcbits = srcbits + linebytes * (lines - 1);
411 linebytes = -linebytes;
414 if ((extra = (left & 7)) != 0) {
415 left &= ~7;
416 dstwidth += extra;
418 srcbits += left >> 3;
419 width = min(srcwidth, dstwidth);
421 /* ==== pal 1 dib -> any bmp format ==== */
422 for (h = lines-1; h >=0; h--) {
423 srcbyte=srcbits;
424 /* FIXME: should avoid putting x<left pixels (minor speed issue) */
425 for (i = width/8, x = left; i > 0; i--) {
426 srcval=*srcbyte++;
427 XPutPixel( bmpImage, x++, h, colors[ srcval >> 7] );
428 XPutPixel( bmpImage, x++, h, colors[(srcval >> 6) & 1] );
429 XPutPixel( bmpImage, x++, h, colors[(srcval >> 5) & 1] );
430 XPutPixel( bmpImage, x++, h, colors[(srcval >> 4) & 1] );
431 XPutPixel( bmpImage, x++, h, colors[(srcval >> 3) & 1] );
432 XPutPixel( bmpImage, x++, h, colors[(srcval >> 2) & 1] );
433 XPutPixel( bmpImage, x++, h, colors[(srcval >> 1) & 1] );
434 XPutPixel( bmpImage, x++, h, colors[ srcval & 1] );
436 if (width % 8){
437 srcval=*srcbyte;
438 switch (width & 7)
440 case 7: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
441 case 6: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
442 case 5: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
443 case 4: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
444 case 3: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
445 case 2: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
446 case 1: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]);
449 srcbits += linebytes;
453 /***********************************************************************
454 * X11DRV_DIB_GetImageBits_1
456 * GetDIBits for a 1-bit deep DIB.
458 static void X11DRV_DIB_GetImageBits_1( int lines, BYTE *dstbits,
459 DWORD dstwidth, DWORD srcwidth,
460 RGBQUAD *colors, PALETTEENTRY *srccolors,
461 XImage *bmpImage, DWORD linebytes )
463 DWORD x;
464 int h, width = min(dstwidth, srcwidth);
466 if (lines < 0 ) {
467 lines = -lines;
468 dstbits = dstbits + linebytes * (lines - 1);
469 linebytes = -linebytes;
472 switch (bmpImage->depth)
474 case 1:
475 case 4:
476 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
477 /* ==== pal 1 or 4 bmp -> pal 1 dib ==== */
478 BYTE* dstbyte;
480 for (h=lines-1; h>=0; h--) {
481 BYTE dstval;
482 dstbyte=dstbits;
483 dstval=0;
484 for (x=0; x<width; x++) {
485 PALETTEENTRY srcval;
486 srcval=srccolors[XGetPixel(bmpImage, x, h)];
487 dstval|=(X11DRV_DIB_GetNearestIndex
488 (colors, 2,
489 srcval.peRed,
490 srcval.peGreen,
491 srcval.peBlue) << (7 - (x & 7)));
492 if ((x&7)==7) {
493 *dstbyte++=dstval;
494 dstval=0;
497 if ((width&7)!=0) {
498 *dstbyte=dstval;
500 dstbits += linebytes;
502 } else {
503 goto notsupported;
505 break;
507 case 8:
508 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
509 /* ==== pal 8 bmp -> pal 1 dib ==== */
510 const void* srcbits;
511 const BYTE* srcpixel;
512 BYTE* dstbyte;
514 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
516 for (h=0; h<lines; h++) {
517 BYTE dstval;
518 srcpixel=srcbits;
519 dstbyte=dstbits;
520 dstval=0;
521 for (x=0; x<width; x++) {
522 PALETTEENTRY srcval;
523 srcval=srccolors[(int)*srcpixel++];
524 dstval|=(X11DRV_DIB_GetNearestIndex
525 (colors, 2,
526 srcval.peRed,
527 srcval.peGreen,
528 srcval.peBlue) << (7-(x&7)) );
529 if ((x&7)==7) {
530 *dstbyte++=dstval;
531 dstval=0;
534 if ((width&7)!=0) {
535 *dstbyte=dstval;
537 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
538 dstbits += linebytes;
540 } else {
541 goto notsupported;
543 break;
545 case 15:
546 case 16:
548 const void* srcbits;
549 const WORD* srcpixel;
550 BYTE* dstbyte;
552 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
554 if (bmpImage->green_mask==0x03e0) {
555 if (bmpImage->red_mask==0x7c00) {
556 /* ==== rgb 555 bmp -> pal 1 dib ==== */
557 for (h=0; h<lines; h++) {
558 BYTE dstval;
559 srcpixel=srcbits;
560 dstbyte=dstbits;
561 dstval=0;
562 for (x=0; x<width; x++) {
563 WORD srcval;
564 srcval=*srcpixel++;
565 dstval|=(X11DRV_DIB_GetNearestIndex
566 (colors, 2,
567 ((srcval >> 7) & 0xf8) | /* r */
568 ((srcval >> 12) & 0x07),
569 ((srcval >> 2) & 0xf8) | /* g */
570 ((srcval >> 7) & 0x07),
571 ((srcval << 3) & 0xf8) | /* b */
572 ((srcval >> 2) & 0x07) ) << (7-(x&7)) );
573 if ((x&7)==7) {
574 *dstbyte++=dstval;
575 dstval=0;
578 if ((width&7)!=0) {
579 *dstbyte=dstval;
581 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
582 dstbits += linebytes;
584 } else if (bmpImage->blue_mask==0x7c00) {
585 /* ==== bgr 555 bmp -> pal 1 dib ==== */
586 for (h=0; h<lines; h++) {
587 WORD dstval;
588 srcpixel=srcbits;
589 dstbyte=dstbits;
590 dstval=0;
591 for (x=0; x<width; x++) {
592 BYTE srcval;
593 srcval=*srcpixel++;
594 dstval|=(X11DRV_DIB_GetNearestIndex
595 (colors, 2,
596 ((srcval << 3) & 0xf8) | /* r */
597 ((srcval >> 2) & 0x07),
598 ((srcval >> 2) & 0xf8) | /* g */
599 ((srcval >> 7) & 0x07),
600 ((srcval >> 7) & 0xf8) | /* b */
601 ((srcval >> 12) & 0x07) ) << (7-(x&7)) );
602 if ((x&7)==7) {
603 *dstbyte++=dstval;
604 dstval=0;
607 if ((width&7)!=0) {
608 *dstbyte=dstval;
610 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
611 dstbits += linebytes;
613 } else {
614 goto notsupported;
616 } else if (bmpImage->green_mask==0x07e0) {
617 if (bmpImage->red_mask==0xf800) {
618 /* ==== rgb 565 bmp -> pal 1 dib ==== */
619 for (h=0; h<lines; h++) {
620 BYTE dstval;
621 srcpixel=srcbits;
622 dstbyte=dstbits;
623 dstval=0;
624 for (x=0; x<width; x++) {
625 WORD srcval;
626 srcval=*srcpixel++;
627 dstval|=(X11DRV_DIB_GetNearestIndex
628 (colors, 2,
629 ((srcval >> 8) & 0xf8) | /* r */
630 ((srcval >> 13) & 0x07),
631 ((srcval >> 3) & 0xfc) | /* g */
632 ((srcval >> 9) & 0x03),
633 ((srcval << 3) & 0xf8) | /* b */
634 ((srcval >> 2) & 0x07) ) << (7-(x&7)) );
635 if ((x&7)==7) {
636 *dstbyte++=dstval;
637 dstval=0;
640 if ((width&7)!=0) {
641 *dstbyte=dstval;
643 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
644 dstbits += linebytes;
646 } else if (bmpImage->blue_mask==0xf800) {
647 /* ==== bgr 565 bmp -> pal 1 dib ==== */
648 for (h=0; h<lines; h++) {
649 BYTE dstval;
650 srcpixel=srcbits;
651 dstbyte=dstbits;
652 dstval=0;
653 for (x=0; x<width; x++) {
654 WORD srcval;
655 srcval=*srcpixel++;
656 dstval|=(X11DRV_DIB_GetNearestIndex
657 (colors, 2,
658 ((srcval << 3) & 0xf8) | /* r */
659 ((srcval >> 2) & 0x07),
660 ((srcval >> 3) & 0xfc) | /* g */
661 ((srcval >> 9) & 0x03),
662 ((srcval >> 8) & 0xf8) | /* b */
663 ((srcval >> 13) & 0x07) ) << (7-(x&7)) );
664 if ((x&7)==7) {
665 *dstbyte++=dstval;
666 dstval=0;
669 if ((width&7)!=0) {
670 *dstbyte=dstval;
672 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
673 dstbits += linebytes;
675 } else {
676 goto notsupported;
678 } else {
679 goto notsupported;
682 break;
684 case 24:
685 case 32:
687 const void* srcbits;
688 const BYTE *srcbyte;
689 BYTE* dstbyte;
690 int bytes_per_pixel;
692 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
693 bytes_per_pixel=(bmpImage->bits_per_pixel==24?3:4);
695 if (bmpImage->green_mask!=0x00ff00 ||
696 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
697 goto notsupported;
698 } else if (bmpImage->blue_mask==0xff) {
699 /* ==== rgb 888 or 0888 bmp -> pal 1 dib ==== */
700 for (h=0; h<lines; h++) {
701 BYTE dstval;
702 srcbyte=srcbits;
703 dstbyte=dstbits;
704 dstval=0;
705 for (x=0; x<width; x++) {
706 dstval|=(X11DRV_DIB_GetNearestIndex
707 (colors, 2,
708 srcbyte[2],
709 srcbyte[1],
710 srcbyte[0]) << (7-(x&7)) );
711 srcbyte+=bytes_per_pixel;
712 if ((x&7)==7) {
713 *dstbyte++=dstval;
714 dstval=0;
717 if ((width&7)!=0) {
718 *dstbyte=dstval;
720 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
721 dstbits += linebytes;
723 } else {
724 /* ==== bgr 888 or 0888 bmp -> pal 1 dib ==== */
725 for (h=0; h<lines; h++) {
726 BYTE dstval;
727 srcbyte=srcbits;
728 dstbyte=dstbits;
729 dstval=0;
730 for (x=0; x<width; x++) {
731 dstval|=(X11DRV_DIB_GetNearestIndex
732 (colors, 2,
733 srcbyte[0],
734 srcbyte[1],
735 srcbyte[2]) << (7-(x&7)) );
736 srcbyte+=bytes_per_pixel;
737 if ((x&7)==7) {
738 *dstbyte++=dstval;
739 dstval=0;
742 if ((width&7)!=0) {
743 *dstbyte=dstval;
745 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
746 dstbits += linebytes;
750 break;
752 default:
753 notsupported:
755 BYTE* dstbyte;
756 unsigned long white = (1 << bmpImage->bits_per_pixel) - 1;
758 /* ==== any bmp format -> pal 1 dib ==== */
759 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 1 bit DIB\n",
760 bmpImage->bits_per_pixel, bmpImage->red_mask,
761 bmpImage->green_mask, bmpImage->blue_mask );
763 for (h=lines-1; h>=0; h--) {
764 BYTE dstval;
765 dstbyte=dstbits;
766 dstval=0;
767 for (x=0; x<width; x++) {
768 dstval|=(XGetPixel( bmpImage, x, h) >= white) << (7 - (x&7));
769 if ((x&7)==7) {
770 *dstbyte++=dstval;
771 dstval=0;
774 if ((width&7)!=0) {
775 *dstbyte=dstval;
777 dstbits += linebytes;
780 break;
784 /***********************************************************************
785 * X11DRV_DIB_SetImageBits_4
787 * SetDIBits for a 4-bit deep DIB.
789 static void X11DRV_DIB_SetImageBits_4( int lines, const BYTE *srcbits,
790 DWORD srcwidth, DWORD dstwidth, int left,
791 int *colors, XImage *bmpImage, DWORD linebytes)
793 int h, width;
794 const BYTE* srcbyte;
795 DWORD i, x;
797 if (lines < 0 ) {
798 lines = -lines;
799 srcbits = srcbits + linebytes * (lines - 1);
800 linebytes = -linebytes;
803 if (left & 1) {
804 left--;
805 dstwidth++;
807 srcbits += left >> 1;
808 width = min(srcwidth, dstwidth);
810 /* ==== pal 4 dib -> any bmp format ==== */
811 for (h = lines-1; h >= 0; h--) {
812 srcbyte=srcbits;
813 for (i = width/2, x = left; i > 0; i--) {
814 BYTE srcval=*srcbyte++;
815 XPutPixel( bmpImage, x++, h, colors[srcval >> 4] );
816 XPutPixel( bmpImage, x++, h, colors[srcval & 0x0f] );
818 if (width & 1)
819 XPutPixel( bmpImage, x, h, colors[*srcbyte >> 4] );
820 srcbits += linebytes;
826 /***********************************************************************
827 * X11DRV_DIB_GetImageBits_4
829 * GetDIBits for a 4-bit deep DIB.
831 static void X11DRV_DIB_GetImageBits_4( int lines, BYTE *dstbits,
832 DWORD srcwidth, DWORD dstwidth,
833 RGBQUAD *colors, PALETTEENTRY *srccolors,
834 XImage *bmpImage, DWORD linebytes )
836 DWORD x;
837 int h, width = min(srcwidth, dstwidth);
838 BYTE *bits;
840 if (lines < 0 )
842 lines = -lines;
843 dstbits = dstbits + ( linebytes * (lines-1) );
844 linebytes = -linebytes;
847 bits = dstbits;
849 switch (bmpImage->depth) {
850 case 1:
851 case 4:
852 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
853 /* ==== pal 1 or 4 bmp -> pal 4 dib ==== */
854 BYTE* dstbyte;
856 for (h = lines-1; h >= 0; h--) {
857 BYTE dstval;
858 dstbyte=dstbits;
859 dstval=0;
860 for (x = 0; x < width; x++) {
861 PALETTEENTRY srcval;
862 srcval=srccolors[XGetPixel(bmpImage, x, h)];
863 dstval|=(X11DRV_DIB_GetNearestIndex
864 (colors, 16,
865 srcval.peRed,
866 srcval.peGreen,
867 srcval.peBlue) << (4-((x&1)<<2)));
868 if ((x&1)==1) {
869 *dstbyte++=dstval;
870 dstval=0;
873 if ((width&1)!=0) {
874 *dstbyte=dstval;
876 dstbits += linebytes;
878 } else {
879 goto notsupported;
881 break;
883 case 8:
884 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
885 /* ==== pal 8 bmp -> pal 4 dib ==== */
886 const void* srcbits;
887 const BYTE *srcpixel;
888 BYTE* dstbyte;
890 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
891 for (h=0; h<lines; h++) {
892 BYTE dstval;
893 srcpixel=srcbits;
894 dstbyte=dstbits;
895 dstval=0;
896 for (x=0; x<width; x++) {
897 PALETTEENTRY srcval;
898 srcval = srccolors[(int)*srcpixel++];
899 dstval|=(X11DRV_DIB_GetNearestIndex
900 (colors, 16,
901 srcval.peRed,
902 srcval.peGreen,
903 srcval.peBlue) << (4*(1-(x&1))) );
904 if ((x&1)==1) {
905 *dstbyte++=dstval;
906 dstval=0;
909 if ((width&1)!=0) {
910 *dstbyte=dstval;
912 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
913 dstbits += linebytes;
915 } else {
916 goto notsupported;
918 break;
920 case 15:
921 case 16:
923 const void* srcbits;
924 const WORD* srcpixel;
925 BYTE* dstbyte;
927 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
929 if (bmpImage->green_mask==0x03e0) {
930 if (bmpImage->red_mask==0x7c00) {
931 /* ==== rgb 555 bmp -> pal 4 dib ==== */
932 for (h=0; h<lines; h++) {
933 BYTE dstval;
934 srcpixel=srcbits;
935 dstbyte=dstbits;
936 dstval=0;
937 for (x=0; x<width; x++) {
938 WORD srcval;
939 srcval=*srcpixel++;
940 dstval|=(X11DRV_DIB_GetNearestIndex
941 (colors, 16,
942 ((srcval >> 7) & 0xf8) | /* r */
943 ((srcval >> 12) & 0x07),
944 ((srcval >> 2) & 0xf8) | /* g */
945 ((srcval >> 7) & 0x07),
946 ((srcval << 3) & 0xf8) | /* b */
947 ((srcval >> 2) & 0x07) ) << ((1-(x&1))<<2) );
948 if ((x&1)==1) {
949 *dstbyte++=dstval;
950 dstval=0;
953 if ((width&1)!=0) {
954 *dstbyte=dstval;
956 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
957 dstbits += linebytes;
959 } else if (bmpImage->blue_mask==0x7c00) {
960 /* ==== bgr 555 bmp -> pal 4 dib ==== */
961 for (h=0; h<lines; h++) {
962 WORD dstval;
963 srcpixel=srcbits;
964 dstbyte=dstbits;
965 dstval=0;
966 for (x=0; x<width; x++) {
967 WORD srcval;
968 srcval=*srcpixel++;
969 dstval|=(X11DRV_DIB_GetNearestIndex
970 (colors, 16,
971 ((srcval << 3) & 0xf8) | /* r */
972 ((srcval >> 2) & 0x07),
973 ((srcval >> 2) & 0xf8) | /* g */
974 ((srcval >> 7) & 0x07),
975 ((srcval >> 7) & 0xf8) | /* b */
976 ((srcval >> 12) & 0x07) ) << ((1-(x&1))<<2) );
977 if ((x&1)==1) {
978 *dstbyte++=dstval;
979 dstval=0;
982 if ((width&1)!=0) {
983 *dstbyte=dstval;
985 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
986 dstbits += linebytes;
988 } else {
989 goto notsupported;
991 } else if (bmpImage->green_mask==0x07e0) {
992 if (bmpImage->red_mask==0xf800) {
993 /* ==== rgb 565 bmp -> pal 4 dib ==== */
994 for (h=0; h<lines; h++) {
995 BYTE dstval;
996 srcpixel=srcbits;
997 dstbyte=dstbits;
998 dstval=0;
999 for (x=0; x<width; x++) {
1000 WORD srcval;
1001 srcval=*srcpixel++;
1002 dstval|=(X11DRV_DIB_GetNearestIndex
1003 (colors, 16,
1004 ((srcval >> 8) & 0xf8) | /* r */
1005 ((srcval >> 13) & 0x07),
1006 ((srcval >> 3) & 0xfc) | /* g */
1007 ((srcval >> 9) & 0x03),
1008 ((srcval << 3) & 0xf8) | /* b */
1009 ((srcval >> 2) & 0x07) ) << ((1-(x&1))<<2) );
1010 if ((x&1)==1) {
1011 *dstbyte++=dstval;
1012 dstval=0;
1015 if ((width&1)!=0) {
1016 *dstbyte=dstval;
1018 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1019 dstbits += linebytes;
1021 } else if (bmpImage->blue_mask==0xf800) {
1022 /* ==== bgr 565 bmp -> pal 4 dib ==== */
1023 for (h=0; h<lines; h++) {
1024 WORD dstval;
1025 srcpixel=srcbits;
1026 dstbyte=dstbits;
1027 dstval=0;
1028 for (x=0; x<width; x++) {
1029 WORD srcval;
1030 srcval=*srcpixel++;
1031 dstval|=(X11DRV_DIB_GetNearestIndex
1032 (colors, 16,
1033 ((srcval << 3) & 0xf8) | /* r */
1034 ((srcval >> 2) & 0x07),
1035 ((srcval >> 3) & 0xfc) | /* g */
1036 ((srcval >> 9) & 0x03),
1037 ((srcval >> 8) & 0xf8) | /* b */
1038 ((srcval >> 13) & 0x07) ) << ((1-(x&1))<<2) );
1039 if ((x&1)==1) {
1040 *dstbyte++=dstval;
1041 dstval=0;
1044 if ((width&1)!=0) {
1045 *dstbyte=dstval;
1047 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1048 dstbits += linebytes;
1050 } else {
1051 goto notsupported;
1053 } else {
1054 goto notsupported;
1057 break;
1059 case 24:
1060 if (bmpImage->bits_per_pixel==24) {
1061 const void* srcbits;
1062 const BYTE *srcbyte;
1063 BYTE* dstbyte;
1065 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1067 if (bmpImage->green_mask!=0x00ff00 ||
1068 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
1069 goto notsupported;
1070 } else if (bmpImage->blue_mask==0xff) {
1071 /* ==== rgb 888 bmp -> pal 4 dib ==== */
1072 for (h=0; h<lines; h++) {
1073 srcbyte=srcbits;
1074 dstbyte=dstbits;
1075 for (x=0; x<width/2; x++) {
1076 /* Do 2 pixels at a time */
1077 *dstbyte++=(X11DRV_DIB_GetNearestIndex
1078 (colors, 16,
1079 srcbyte[2],
1080 srcbyte[1],
1081 srcbyte[0]) << 4) |
1082 X11DRV_DIB_GetNearestIndex
1083 (colors, 16,
1084 srcbyte[5],
1085 srcbyte[4],
1086 srcbyte[3]);
1087 srcbyte+=6;
1089 if (width&1) {
1090 /* And the the odd pixel */
1091 *dstbyte++=(X11DRV_DIB_GetNearestIndex
1092 (colors, 16,
1093 srcbyte[2],
1094 srcbyte[1],
1095 srcbyte[0]) << 4);
1097 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1098 dstbits += linebytes;
1100 } else {
1101 /* ==== bgr 888 bmp -> pal 4 dib ==== */
1102 for (h=0; h<lines; h++) {
1103 srcbyte=srcbits;
1104 dstbyte=dstbits;
1105 for (x=0; x<width/2; x++) {
1106 /* Do 2 pixels at a time */
1107 *dstbyte++=(X11DRV_DIB_GetNearestIndex
1108 (colors, 16,
1109 srcbyte[0],
1110 srcbyte[1],
1111 srcbyte[2]) << 4) |
1112 X11DRV_DIB_GetNearestIndex
1113 (colors, 16,
1114 srcbyte[3],
1115 srcbyte[4],
1116 srcbyte[5]);
1117 srcbyte+=6;
1119 if (width&1) {
1120 /* And the the odd pixel */
1121 *dstbyte++=(X11DRV_DIB_GetNearestIndex
1122 (colors, 16,
1123 srcbyte[0],
1124 srcbyte[1],
1125 srcbyte[2]) << 4);
1127 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1128 dstbits += linebytes;
1131 break;
1133 /* Fall through */
1135 case 32:
1137 const void* srcbits;
1138 const BYTE *srcbyte;
1139 BYTE* dstbyte;
1141 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1143 if (bmpImage->green_mask!=0x00ff00 ||
1144 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
1145 goto notsupported;
1146 } else if (bmpImage->blue_mask==0xff) {
1147 /* ==== rgb 0888 bmp -> pal 4 dib ==== */
1148 for (h=0; h<lines; h++) {
1149 srcbyte=srcbits;
1150 dstbyte=dstbits;
1151 for (x=0; x<width/2; x++) {
1152 /* Do 2 pixels at a time */
1153 *dstbyte++=(X11DRV_DIB_GetNearestIndex
1154 (colors, 16,
1155 srcbyte[2],
1156 srcbyte[1],
1157 srcbyte[0]) << 4) |
1158 X11DRV_DIB_GetNearestIndex
1159 (colors, 16,
1160 srcbyte[6],
1161 srcbyte[5],
1162 srcbyte[4]);
1163 srcbyte+=8;
1165 if (width&1) {
1166 /* And the the odd pixel */
1167 *dstbyte++=(X11DRV_DIB_GetNearestIndex
1168 (colors, 16,
1169 srcbyte[2],
1170 srcbyte[1],
1171 srcbyte[0]) << 4);
1173 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1174 dstbits += linebytes;
1176 } else {
1177 /* ==== bgr 0888 bmp -> pal 4 dib ==== */
1178 for (h=0; h<lines; h++) {
1179 srcbyte=srcbits;
1180 dstbyte=dstbits;
1181 for (x=0; x<width/2; x++) {
1182 /* Do 2 pixels at a time */
1183 *dstbyte++=(X11DRV_DIB_GetNearestIndex
1184 (colors, 16,
1185 srcbyte[0],
1186 srcbyte[1],
1187 srcbyte[2]) << 4) |
1188 X11DRV_DIB_GetNearestIndex
1189 (colors, 16,
1190 srcbyte[4],
1191 srcbyte[5],
1192 srcbyte[6]);
1193 srcbyte+=8;
1195 if (width&1) {
1196 /* And the the odd pixel */
1197 *dstbyte++=(X11DRV_DIB_GetNearestIndex
1198 (colors, 16,
1199 srcbyte[0],
1200 srcbyte[1],
1201 srcbyte[2]) << 4);
1203 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1204 dstbits += linebytes;
1208 break;
1210 default:
1211 notsupported:
1213 BYTE* dstbyte;
1215 /* ==== any bmp format -> pal 4 dib ==== */
1216 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 4 bit DIB\n",
1217 bmpImage->bits_per_pixel, bmpImage->red_mask,
1218 bmpImage->green_mask, bmpImage->blue_mask );
1219 for (h=lines-1; h>=0; h--) {
1220 dstbyte=dstbits;
1221 for (x=0; x<(width & ~1); x+=2) {
1222 *dstbyte++=(X11DRV_DIB_MapColor((int*)colors, 16, XGetPixel(bmpImage, x, h), 0) << 4) |
1223 X11DRV_DIB_MapColor((int*)colors, 16, XGetPixel(bmpImage, x+1, h), 0);
1225 if (width & 1) {
1226 *dstbyte=(X11DRV_DIB_MapColor((int *)colors, 16, XGetPixel(bmpImage, x, h), 0) << 4);
1228 dstbits += linebytes;
1231 break;
1235 /***********************************************************************
1236 * X11DRV_DIB_SetImageBits_RLE4
1238 * SetDIBits for a 4-bit deep compressed DIB.
1240 static void X11DRV_DIB_SetImageBits_RLE4( int lines, const BYTE *bits,
1241 DWORD srcwidth, DWORD dstwidth,
1242 int left, int *colors,
1243 XImage *bmpImage )
1245 unsigned int x = 0, width = min(srcwidth, dstwidth);
1246 int y = lines - 1, c, length;
1247 const BYTE *begin = bits;
1249 while (y >= 0)
1251 length = *bits++;
1252 if (length) { /* encoded */
1253 c = *bits++;
1254 while (length--) {
1255 if (x >= width) break;
1256 XPutPixel(bmpImage, x++, y, colors[c >> 4]);
1257 if (!length--) break;
1258 if (x >= width) break;
1259 XPutPixel(bmpImage, x++, y, colors[c & 0xf]);
1261 } else {
1262 length = *bits++;
1263 switch (length)
1265 case RLE_EOL:
1266 x = 0;
1267 y--;
1268 break;
1270 case RLE_END:
1271 return;
1273 case RLE_DELTA:
1274 x += *bits++;
1275 y -= *bits++;
1276 break;
1278 default: /* absolute */
1279 while (length--) {
1280 c = *bits++;
1281 if (x < width) XPutPixel(bmpImage, x++, y, colors[c >> 4]);
1282 if (!length--) break;
1283 if (x < width) XPutPixel(bmpImage, x++, y, colors[c & 0xf]);
1285 if ((bits - begin) & 1)
1286 bits++;
1294 /***********************************************************************
1295 * X11DRV_DIB_SetImageBits_8
1297 * SetDIBits for an 8-bit deep DIB.
1299 static void X11DRV_DIB_SetImageBits_8( int lines, const BYTE *srcbits,
1300 DWORD srcwidth, DWORD dstwidth, int left,
1301 const int *colors, XImage *bmpImage,
1302 DWORD linebytes )
1304 DWORD x;
1305 int h, width = min(srcwidth, dstwidth);
1306 const BYTE* srcbyte;
1307 BYTE* dstbits;
1309 if (lines < 0 )
1311 lines = -lines;
1312 srcbits = srcbits + linebytes * (lines-1);
1313 linebytes = -linebytes;
1315 srcbits += left;
1316 srcbyte = srcbits;
1318 switch (bmpImage->depth) {
1319 case 15:
1320 case 16:
1321 #if defined(__i386__) && defined(__GNUC__)
1322 /* Some X servers might have 32 bit/ 16bit deep pixel */
1323 if (lines && width && (bmpImage->bits_per_pixel == 16) &&
1324 (ImageByteOrder(gdi_display)==LSBFirst) )
1326 dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
1327 /* FIXME: Does this really handle all these cases correctly? */
1328 /* ==== pal 8 dib -> rgb or bgr 555 or 565 bmp ==== */
1329 for (h = lines ; h--; ) {
1330 int _cl1,_cl2; /* temp outputs for asm below */
1331 /* Borrowed from DirectDraw */
1332 __asm__ __volatile__(
1333 "xor %%eax,%%eax\n"
1334 "cld\n"
1335 "1:\n"
1336 " lodsb\n"
1337 " movw (%%edx,%%eax,4),%%ax\n"
1338 " stosw\n"
1339 " xor %%eax,%%eax\n"
1340 " loop 1b\n"
1341 :"=S" (srcbyte), "=D" (_cl1), "=c" (_cl2)
1342 :"S" (srcbyte),
1343 "D" (dstbits),
1344 "c" (width),
1345 "d" (colors)
1346 :"eax", "cc", "memory"
1348 srcbyte = (srcbits += linebytes);
1349 dstbits -= bmpImage->bytes_per_line;
1351 return;
1353 break;
1354 #endif
1355 case 24:
1356 case 32:
1357 #if defined(__i386__) && defined(__GNUC__)
1358 if (lines && width && (bmpImage->bits_per_pixel == 32) &&
1359 (ImageByteOrder(gdi_display)==LSBFirst) )
1361 dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
1362 /* FIXME: Does this really handle both cases correctly? */
1363 /* ==== pal 8 dib -> rgb or bgr 0888 bmp ==== */
1364 for (h = lines ; h--; ) {
1365 int _cl1,_cl2; /* temp outputs for asm below */
1366 /* Borrowed from DirectDraw */
1367 __asm__ __volatile__(
1368 "xor %%eax,%%eax\n"
1369 "cld\n"
1370 "1:\n"
1371 " lodsb\n"
1372 " movl (%%edx,%%eax,4),%%eax\n"
1373 " stosl\n"
1374 " xor %%eax,%%eax\n"
1375 " loop 1b\n"
1376 :"=S" (srcbyte), "=D" (_cl1), "=c" (_cl2)
1377 :"S" (srcbyte),
1378 "D" (dstbits),
1379 "c" (width),
1380 "d" (colors)
1381 :"eax", "cc", "memory"
1383 srcbyte = (srcbits += linebytes);
1384 dstbits -= bmpImage->bytes_per_line;
1386 return;
1388 break;
1389 #endif
1390 default:
1391 break; /* use slow generic case below */
1394 /* ==== pal 8 dib -> any bmp format ==== */
1395 for (h=lines-1; h>=0; h--) {
1396 for (x=left; x<width+left; x++) {
1397 XPutPixel(bmpImage, x, h, colors[*srcbyte++]);
1399 srcbyte = (srcbits += linebytes);
1403 /***********************************************************************
1404 * X11DRV_DIB_GetImageBits_8
1406 * GetDIBits for an 8-bit deep DIB.
1408 static void X11DRV_DIB_GetImageBits_8( int lines, BYTE *dstbits,
1409 DWORD srcwidth, DWORD dstwidth,
1410 RGBQUAD *colors, PALETTEENTRY *srccolors,
1411 XImage *bmpImage, DWORD linebytes )
1413 DWORD x;
1414 int h, width = min(srcwidth, dstwidth);
1415 BYTE* dstbyte;
1417 if (lines < 0 )
1419 lines = -lines;
1420 dstbits = dstbits + ( linebytes * (lines-1) );
1421 linebytes = -linebytes;
1425 * Hack for now
1426 * This condition is true when GetImageBits has been called by
1427 * UpdateDIBSection. For now, GetNearestIndex is too slow to support
1428 * 256 colormaps, so we'll just use for for GetDIBits calls.
1429 * (In somes cases, in a updateDIBSection, the returned colors are bad too)
1431 if (!srccolors) goto updatesection;
1433 switch (bmpImage->depth) {
1434 case 1:
1435 case 4:
1436 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
1438 /* ==== pal 1 bmp -> pal 8 dib ==== */
1439 /* ==== pal 4 bmp -> pal 8 dib ==== */
1440 for (h=lines-1; h>=0; h--) {
1441 dstbyte=dstbits;
1442 for (x=0; x<width; x++) {
1443 PALETTEENTRY srcval;
1444 srcval=srccolors[XGetPixel(bmpImage, x, h)];
1445 *dstbyte++=X11DRV_DIB_GetNearestIndex(colors, 256,
1446 srcval.peRed,
1447 srcval.peGreen,
1448 srcval.peBlue);
1450 dstbits += linebytes;
1452 } else {
1453 goto notsupported;
1455 break;
1457 case 8:
1458 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
1459 /* ==== pal 8 bmp -> pal 8 dib ==== */
1460 const void* srcbits;
1461 const BYTE* srcpixel;
1463 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1464 for (h=0; h<lines; h++) {
1465 srcpixel=srcbits;
1466 dstbyte=dstbits;
1467 for (x = 0; x < width; x++) {
1468 PALETTEENTRY srcval;
1469 srcval=srccolors[(int)*srcpixel++];
1470 *dstbyte++=X11DRV_DIB_GetNearestIndex(colors, 256,
1471 srcval.peRed,
1472 srcval.peGreen,
1473 srcval.peBlue);
1475 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1476 dstbits += linebytes;
1478 } else {
1479 goto notsupported;
1481 break;
1483 case 15:
1484 case 16:
1486 const void* srcbits;
1487 const WORD* srcpixel;
1488 BYTE* dstbyte;
1490 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1492 if (bmpImage->green_mask==0x03e0) {
1493 if (bmpImage->red_mask==0x7c00) {
1494 /* ==== rgb 555 bmp -> pal 8 dib ==== */
1495 for (h=0; h<lines; h++) {
1496 srcpixel=srcbits;
1497 dstbyte=dstbits;
1498 for (x=0; x<width; x++) {
1499 WORD srcval;
1500 srcval=*srcpixel++;
1501 *dstbyte++=X11DRV_DIB_GetNearestIndex
1502 (colors, 256,
1503 ((srcval >> 7) & 0xf8) | /* r */
1504 ((srcval >> 12) & 0x07),
1505 ((srcval >> 2) & 0xf8) | /* g */
1506 ((srcval >> 7) & 0x07),
1507 ((srcval << 3) & 0xf8) | /* b */
1508 ((srcval >> 2) & 0x07) );
1510 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1511 dstbits += linebytes;
1513 } else if (bmpImage->blue_mask==0x7c00) {
1514 /* ==== bgr 555 bmp -> pal 8 dib ==== */
1515 for (h=0; h<lines; h++) {
1516 srcpixel=srcbits;
1517 dstbyte=dstbits;
1518 for (x=0; x<width; x++) {
1519 WORD srcval;
1520 srcval=*srcpixel++;
1521 *dstbyte++=X11DRV_DIB_GetNearestIndex
1522 (colors, 256,
1523 ((srcval << 3) & 0xf8) | /* r */
1524 ((srcval >> 2) & 0x07),
1525 ((srcval >> 2) & 0xf8) | /* g */
1526 ((srcval >> 7) & 0x07),
1527 ((srcval >> 7) & 0xf8) | /* b */
1528 ((srcval >> 12) & 0x07) );
1530 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1531 dstbits += linebytes;
1533 } else {
1534 goto notsupported;
1536 } else if (bmpImage->green_mask==0x07e0) {
1537 if (bmpImage->red_mask==0xf800) {
1538 /* ==== rgb 565 bmp -> pal 8 dib ==== */
1539 for (h=0; h<lines; h++) {
1540 srcpixel=srcbits;
1541 dstbyte=dstbits;
1542 for (x=0; x<width; x++) {
1543 WORD srcval;
1544 srcval=*srcpixel++;
1545 *dstbyte++=X11DRV_DIB_GetNearestIndex
1546 (colors, 256,
1547 ((srcval >> 8) & 0xf8) | /* r */
1548 ((srcval >> 13) & 0x07),
1549 ((srcval >> 3) & 0xfc) | /* g */
1550 ((srcval >> 9) & 0x03),
1551 ((srcval << 3) & 0xf8) | /* b */
1552 ((srcval >> 2) & 0x07) );
1554 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1555 dstbits += linebytes;
1557 } else if (bmpImage->blue_mask==0xf800) {
1558 /* ==== bgr 565 bmp -> pal 8 dib ==== */
1559 for (h=0; h<lines; h++) {
1560 srcpixel=srcbits;
1561 dstbyte=dstbits;
1562 for (x=0; x<width; x++) {
1563 WORD srcval;
1564 srcval=*srcpixel++;
1565 *dstbyte++=X11DRV_DIB_GetNearestIndex
1566 (colors, 256,
1567 ((srcval << 3) & 0xf8) | /* r */
1568 ((srcval >> 2) & 0x07),
1569 ((srcval >> 3) & 0xfc) | /* g */
1570 ((srcval >> 9) & 0x03),
1571 ((srcval >> 8) & 0xf8) | /* b */
1572 ((srcval >> 13) & 0x07) );
1574 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1575 dstbits += linebytes;
1577 } else {
1578 goto notsupported;
1580 } else {
1581 goto notsupported;
1584 break;
1586 case 24:
1587 case 32:
1589 const void* srcbits;
1590 const BYTE *srcbyte;
1591 BYTE* dstbyte;
1592 int bytes_per_pixel;
1594 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1595 bytes_per_pixel=(bmpImage->bits_per_pixel==24?3:4);
1597 if (bmpImage->green_mask!=0x00ff00 ||
1598 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
1599 goto notsupported;
1600 } else if (bmpImage->blue_mask==0xff) {
1601 /* ==== rgb 888 or 0888 bmp -> pal 8 dib ==== */
1602 for (h=0; h<lines; h++) {
1603 srcbyte=srcbits;
1604 dstbyte=dstbits;
1605 for (x=0; x<width; x++) {
1606 *dstbyte++=X11DRV_DIB_GetNearestIndex
1607 (colors, 256,
1608 srcbyte[2],
1609 srcbyte[1],
1610 srcbyte[0]);
1611 srcbyte+=bytes_per_pixel;
1613 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1614 dstbits += linebytes;
1616 } else {
1617 /* ==== bgr 888 or 0888 bmp -> pal 8 dib ==== */
1618 for (h=0; h<lines; h++) {
1619 srcbyte=srcbits;
1620 dstbyte=dstbits;
1621 for (x=0; x<width; x++) {
1622 *dstbyte++=X11DRV_DIB_GetNearestIndex
1623 (colors, 256,
1624 srcbyte[0],
1625 srcbyte[1],
1626 srcbyte[2]);
1627 srcbyte+=bytes_per_pixel;
1629 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1630 dstbits += linebytes;
1634 break;
1636 default:
1637 notsupported:
1638 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 8 bit DIB\n",
1639 bmpImage->depth, bmpImage->red_mask,
1640 bmpImage->green_mask, bmpImage->blue_mask );
1641 updatesection:
1642 /* ==== any bmp format -> pal 8 dib ==== */
1643 for (h=lines-1; h>=0; h--) {
1644 dstbyte=dstbits;
1645 for (x=0; x<width; x++) {
1646 *dstbyte=X11DRV_DIB_MapColor
1647 ((int*)colors, 256,
1648 XGetPixel(bmpImage, x, h), *dstbyte);
1649 dstbyte++;
1651 dstbits += linebytes;
1653 break;
1657 /***********************************************************************
1658 * X11DRV_DIB_SetImageBits_RLE8
1660 * SetDIBits for an 8-bit deep compressed DIB.
1662 * This function rewritten 941113 by James Youngman. WINE blew out when I
1663 * first ran it because my desktop wallpaper is a (large) RLE8 bitmap.
1665 * This was because the algorithm assumed that all RLE8 bitmaps end with the
1666 * 'End of bitmap' escape code. This code is very much laxer in what it
1667 * allows to end the expansion. Possibly too lax. See the note by
1668 * case RleDelta. BTW, MS's documentation implies that a correct RLE8
1669 * bitmap should end with RleEnd, but on the other hand, software exists
1670 * that produces ones that don't and Windows 3.1 doesn't complain a bit
1671 * about it.
1673 * (No) apologies for my English spelling. [Emacs users: c-indent-level=4].
1674 * James A. Youngman <mbcstjy@afs.man.ac.uk>
1675 * [JAY]
1677 static void X11DRV_DIB_SetImageBits_RLE8( int lines, const BYTE *bits,
1678 DWORD srcwidth, DWORD dstwidth,
1679 int left, int *colors,
1680 XImage *bmpImage )
1682 unsigned int x; /* X-position on each line. Increases. */
1683 int y; /* Line #. Starts at lines-1, decreases */
1684 const BYTE *pIn = bits; /* Pointer to current position in bits */
1685 BYTE length; /* The length pf a run */
1686 BYTE escape_code; /* See enum Rle8_EscapeCodes.*/
1689 * Note that the bitmap data is stored by Windows starting at the
1690 * bottom line of the bitmap and going upwards. Within each line,
1691 * the data is stored left-to-right. That's the reason why line
1692 * goes from lines-1 to 0. [JAY]
1695 x = 0;
1696 y = lines - 1;
1697 while (y >= 0)
1699 length = *pIn++;
1702 * If the length byte is not zero (which is the escape value),
1703 * We have a run of length pixels all the same colour. The colour
1704 * index is stored next.
1706 * If the length byte is zero, we need to read the next byte to
1707 * know what to do. [JAY]
1709 if (length != 0)
1712 * [Run-Length] Encoded mode
1714 int color = colors[*pIn++];
1715 while (length-- && x < dstwidth) XPutPixel(bmpImage, x++, y, color);
1717 else
1720 * Escape codes (may be an absolute sequence though)
1722 escape_code = (*pIn++);
1723 switch(escape_code)
1725 case RLE_EOL:
1726 x = 0;
1727 y--;
1728 break;
1730 case RLE_END:
1731 /* Not all RLE8 bitmaps end with this code. For
1732 * example, Paint Shop Pro produces some that don't.
1733 * That's (I think) what caused the previous
1734 * implementation to fail. [JAY]
1736 return;
1738 case RLE_DELTA:
1739 x += (*pIn++);
1740 y -= (*pIn++);
1741 break;
1743 default: /* switch to absolute mode */
1744 length = escape_code;
1745 while (length--)
1747 int color = colors[*pIn++];
1748 if (x >= dstwidth)
1750 pIn += length;
1751 break;
1753 XPutPixel(bmpImage, x++, y, color);
1756 * If you think for a moment you'll realise that the
1757 * only time we could ever possibly read an odd
1758 * number of bytes is when there is a 0x00 (escape),
1759 * a value >0x02 (absolute mode) and then an odd-
1760 * length run. Therefore this is the only place we
1761 * need to worry about it. Everywhere else the
1762 * bytes are always read in pairs. [JAY]
1764 if (escape_code & 1) pIn++; /* Throw away the pad byte. */
1765 break;
1766 } /* switch (escape_code) : Escape sequence */
1772 /***********************************************************************
1773 * X11DRV_DIB_SetImageBits_16
1775 * SetDIBits for a 16-bit deep DIB.
1777 static void X11DRV_DIB_SetImageBits_16( int lines, const BYTE *srcbits,
1778 DWORD srcwidth, DWORD dstwidth, int left,
1779 X11DRV_PDEVICE *physDev, DWORD rSrc, DWORD gSrc, DWORD bSrc,
1780 XImage *bmpImage, DWORD linebytes )
1782 DWORD x;
1783 int h, width = min(srcwidth, dstwidth);
1784 const dib_conversions *convs = (bmpImage->byte_order == LSBFirst) ? &dib_normal : &dib_dst_byteswap;
1786 if (lines < 0 )
1788 lines = -lines;
1789 srcbits = srcbits + ( linebytes * (lines-1));
1790 linebytes = -linebytes;
1793 switch (bmpImage->depth)
1795 case 15:
1796 case 16:
1798 char* dstbits;
1800 srcbits=srcbits+left*2;
1801 dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
1803 if (bmpImage->green_mask==0x03e0) {
1804 if (gSrc==bmpImage->green_mask) {
1805 if (rSrc==bmpImage->red_mask) {
1806 /* ==== rgb 555 dib -> rgb 555 bmp ==== */
1807 /* ==== bgr 555 dib -> bgr 555 bmp ==== */
1808 convs->Convert_5x5_asis
1809 (width,lines,
1810 srcbits,linebytes,
1811 dstbits,-bmpImage->bytes_per_line);
1812 } else if (rSrc==bmpImage->blue_mask) {
1813 /* ==== rgb 555 dib -> bgr 555 bmp ==== */
1814 /* ==== bgr 555 dib -> rgb 555 bmp ==== */
1815 convs->Convert_555_reverse
1816 (width,lines,
1817 srcbits,linebytes,
1818 dstbits,-bmpImage->bytes_per_line);
1820 } else {
1821 if (rSrc==bmpImage->red_mask || bSrc==bmpImage->blue_mask) {
1822 /* ==== rgb 565 dib -> rgb 555 bmp ==== */
1823 /* ==== bgr 565 dib -> bgr 555 bmp ==== */
1824 convs->Convert_565_to_555_asis
1825 (width,lines,
1826 srcbits,linebytes,
1827 dstbits,-bmpImage->bytes_per_line);
1828 } else {
1829 /* ==== rgb 565 dib -> bgr 555 bmp ==== */
1830 /* ==== bgr 565 dib -> rgb 555 bmp ==== */
1831 convs->Convert_565_to_555_reverse
1832 (width,lines,
1833 srcbits,linebytes,
1834 dstbits,-bmpImage->bytes_per_line);
1837 } else if (bmpImage->green_mask==0x07e0) {
1838 if (gSrc==bmpImage->green_mask) {
1839 if (rSrc==bmpImage->red_mask) {
1840 /* ==== rgb 565 dib -> rgb 565 bmp ==== */
1841 /* ==== bgr 565 dib -> bgr 565 bmp ==== */
1842 convs->Convert_5x5_asis
1843 (width,lines,
1844 srcbits,linebytes,
1845 dstbits,-bmpImage->bytes_per_line);
1846 } else {
1847 /* ==== rgb 565 dib -> bgr 565 bmp ==== */
1848 /* ==== bgr 565 dib -> rgb 565 bmp ==== */
1849 convs->Convert_565_reverse
1850 (width,lines,
1851 srcbits,linebytes,
1852 dstbits,-bmpImage->bytes_per_line);
1854 } else {
1855 if (rSrc==bmpImage->red_mask || bSrc==bmpImage->blue_mask) {
1856 /* ==== rgb 555 dib -> rgb 565 bmp ==== */
1857 /* ==== bgr 555 dib -> bgr 565 bmp ==== */
1858 convs->Convert_555_to_565_asis
1859 (width,lines,
1860 srcbits,linebytes,
1861 dstbits,-bmpImage->bytes_per_line);
1862 } else {
1863 /* ==== rgb 555 dib -> bgr 565 bmp ==== */
1864 /* ==== bgr 555 dib -> rgb 565 bmp ==== */
1865 convs->Convert_555_to_565_reverse
1866 (width,lines,
1867 srcbits,linebytes,
1868 dstbits,-bmpImage->bytes_per_line);
1871 } else {
1872 goto notsupported;
1875 break;
1877 case 24:
1878 if (bmpImage->bits_per_pixel==24) {
1879 char* dstbits;
1881 srcbits=srcbits+left*2;
1882 dstbits=bmpImage->data+left*3+(lines-1)*bmpImage->bytes_per_line;
1884 if (bmpImage->green_mask!=0x00ff00 ||
1885 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
1886 goto notsupported;
1887 } else if ((rSrc==0x1f && bmpImage->red_mask==0xff) ||
1888 (bSrc==0x1f && bmpImage->blue_mask==0xff)) {
1889 if (gSrc==0x03e0) {
1890 /* ==== rgb 555 dib -> rgb 888 bmp ==== */
1891 /* ==== bgr 555 dib -> bgr 888 bmp ==== */
1892 convs->Convert_555_to_888_asis
1893 (width,lines,
1894 srcbits,linebytes,
1895 dstbits,-bmpImage->bytes_per_line);
1896 } else {
1897 /* ==== rgb 565 dib -> rgb 888 bmp ==== */
1898 /* ==== bgr 565 dib -> bgr 888 bmp ==== */
1899 convs->Convert_565_to_888_asis
1900 (width,lines,
1901 srcbits,linebytes,
1902 dstbits,-bmpImage->bytes_per_line);
1904 } else {
1905 if (gSrc==0x03e0) {
1906 /* ==== rgb 555 dib -> bgr 888 bmp ==== */
1907 /* ==== bgr 555 dib -> rgb 888 bmp ==== */
1908 convs->Convert_555_to_888_reverse
1909 (width,lines,
1910 srcbits,linebytes,
1911 dstbits,-bmpImage->bytes_per_line);
1912 } else {
1913 /* ==== rgb 565 dib -> bgr 888 bmp ==== */
1914 /* ==== bgr 565 dib -> rgb 888 bmp ==== */
1915 convs->Convert_565_to_888_reverse
1916 (width,lines,
1917 srcbits,linebytes,
1918 dstbits,-bmpImage->bytes_per_line);
1921 break;
1923 /* Fall through */
1925 case 32:
1927 char* dstbits;
1929 srcbits=srcbits+left*2;
1930 dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
1932 if (bmpImage->green_mask!=0x00ff00 ||
1933 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
1934 goto notsupported;
1935 } else if ((rSrc==0x1f && bmpImage->red_mask==0xff) ||
1936 (bSrc==0x1f && bmpImage->blue_mask==0xff)) {
1937 if (gSrc==0x03e0) {
1938 /* ==== rgb 555 dib -> rgb 0888 bmp ==== */
1939 /* ==== bgr 555 dib -> bgr 0888 bmp ==== */
1940 convs->Convert_555_to_0888_asis
1941 (width,lines,
1942 srcbits,linebytes,
1943 dstbits,-bmpImage->bytes_per_line);
1944 } else {
1945 /* ==== rgb 565 dib -> rgb 0888 bmp ==== */
1946 /* ==== bgr 565 dib -> bgr 0888 bmp ==== */
1947 convs->Convert_565_to_0888_asis
1948 (width,lines,
1949 srcbits,linebytes,
1950 dstbits,-bmpImage->bytes_per_line);
1952 } else {
1953 if (gSrc==0x03e0) {
1954 /* ==== rgb 555 dib -> bgr 0888 bmp ==== */
1955 /* ==== bgr 555 dib -> rgb 0888 bmp ==== */
1956 convs->Convert_555_to_0888_reverse
1957 (width,lines,
1958 srcbits,linebytes,
1959 dstbits,-bmpImage->bytes_per_line);
1960 } else {
1961 /* ==== rgb 565 dib -> bgr 0888 bmp ==== */
1962 /* ==== bgr 565 dib -> rgb 0888 bmp ==== */
1963 convs->Convert_565_to_0888_reverse
1964 (width,lines,
1965 srcbits,linebytes,
1966 dstbits,-bmpImage->bytes_per_line);
1970 break;
1972 default:
1973 notsupported:
1974 WARN("from 16 bit DIB (%lx,%lx,%lx) to unknown %d bit bitmap (%lx,%lx,%lx)\n",
1975 rSrc, gSrc, bSrc, bmpImage->bits_per_pixel, bmpImage->red_mask,
1976 bmpImage->green_mask, bmpImage->blue_mask );
1977 /* fall through */
1978 case 1:
1979 case 4:
1980 case 8:
1982 /* ==== rgb or bgr 555 or 565 dib -> pal 1, 4 or 8 ==== */
1983 const WORD* srcpixel;
1984 int rShift1,gShift1,bShift1;
1985 int rShift2,gShift2,bShift2;
1986 BYTE gMask1,gMask2;
1988 /* Set color scaling values */
1989 rShift1=16+X11DRV_DIB_MaskToShift(rSrc)-3;
1990 gShift1=16+X11DRV_DIB_MaskToShift(gSrc)-3;
1991 bShift1=16+X11DRV_DIB_MaskToShift(bSrc)-3;
1992 rShift2=rShift1+5;
1993 gShift2=gShift1+5;
1994 bShift2=bShift1+5;
1995 if (gSrc==0x03e0) {
1996 /* Green has 5 bits, like the others */
1997 gMask1=0xf8;
1998 gMask2=0x07;
1999 } else {
2000 /* Green has 6 bits, not 5. Compensate. */
2001 gShift1++;
2002 gShift2+=2;
2003 gMask1=0xfc;
2004 gMask2=0x03;
2007 srcbits+=2*left;
2009 /* We could split it into four separate cases to optimize
2010 * but it is probably not worth it.
2012 for (h=lines-1; h>=0; h--) {
2013 srcpixel=(const WORD*)srcbits;
2014 for (x=left; x<width+left; x++) {
2015 DWORD srcval;
2016 BYTE red,green,blue;
2017 srcval=*srcpixel++ << 16;
2018 red= ((srcval >> rShift1) & 0xf8) |
2019 ((srcval >> rShift2) & 0x07);
2020 green=((srcval >> gShift1) & gMask1) |
2021 ((srcval >> gShift2) & gMask2);
2022 blue= ((srcval >> bShift1) & 0xf8) |
2023 ((srcval >> bShift2) & 0x07);
2024 XPutPixel(bmpImage, x, h,
2025 X11DRV_PALETTE_ToPhysical
2026 (physDev, RGB(red,green,blue)));
2028 srcbits += linebytes;
2031 break;
2036 /***********************************************************************
2037 * X11DRV_DIB_GetImageBits_16
2039 * GetDIBits for an 16-bit deep DIB.
2041 static void X11DRV_DIB_GetImageBits_16( int lines, BYTE *dstbits,
2042 DWORD dstwidth, DWORD srcwidth,
2043 PALETTEENTRY *srccolors,
2044 DWORD rDst, DWORD gDst, DWORD bDst,
2045 XImage *bmpImage, DWORD dibpitch )
2047 DWORD x;
2048 int h, width = min(srcwidth, dstwidth);
2049 const dib_conversions *convs = (bmpImage->byte_order == LSBFirst) ? &dib_normal : &dib_src_byteswap;
2051 DWORD linebytes = dibpitch;
2053 if (lines < 0 )
2055 lines = -lines;
2056 dstbits = dstbits + ( linebytes * (lines-1));
2057 linebytes = -linebytes;
2060 switch (bmpImage->depth)
2062 case 15:
2063 case 16:
2065 const char* srcbits;
2067 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2069 if (bmpImage->green_mask==0x03e0) {
2070 if (gDst==bmpImage->green_mask) {
2071 if (rDst==bmpImage->red_mask) {
2072 /* ==== rgb 555 bmp -> rgb 555 dib ==== */
2073 /* ==== bgr 555 bmp -> bgr 555 dib ==== */
2074 convs->Convert_5x5_asis
2075 (width,lines,
2076 srcbits,-bmpImage->bytes_per_line,
2077 dstbits,linebytes);
2078 } else {
2079 /* ==== rgb 555 bmp -> bgr 555 dib ==== */
2080 /* ==== bgr 555 bmp -> rgb 555 dib ==== */
2081 convs->Convert_555_reverse
2082 (width,lines,
2083 srcbits,-bmpImage->bytes_per_line,
2084 dstbits,linebytes);
2086 } else {
2087 if (rDst==bmpImage->red_mask || bDst==bmpImage->blue_mask) {
2088 /* ==== rgb 555 bmp -> rgb 565 dib ==== */
2089 /* ==== bgr 555 bmp -> bgr 565 dib ==== */
2090 convs->Convert_555_to_565_asis
2091 (width,lines,
2092 srcbits,-bmpImage->bytes_per_line,
2093 dstbits,linebytes);
2094 } else {
2095 /* ==== rgb 555 bmp -> bgr 565 dib ==== */
2096 /* ==== bgr 555 bmp -> rgb 565 dib ==== */
2097 convs->Convert_555_to_565_reverse
2098 (width,lines,
2099 srcbits,-bmpImage->bytes_per_line,
2100 dstbits,linebytes);
2103 } else if (bmpImage->green_mask==0x07e0) {
2104 if (gDst==bmpImage->green_mask) {
2105 if (rDst == bmpImage->red_mask) {
2106 /* ==== rgb 565 bmp -> rgb 565 dib ==== */
2107 /* ==== bgr 565 bmp -> bgr 565 dib ==== */
2108 convs->Convert_5x5_asis
2109 (width,lines,
2110 srcbits,-bmpImage->bytes_per_line,
2111 dstbits,linebytes);
2112 } else {
2113 /* ==== rgb 565 bmp -> bgr 565 dib ==== */
2114 /* ==== bgr 565 bmp -> rgb 565 dib ==== */
2115 convs->Convert_565_reverse
2116 (width,lines,
2117 srcbits,-bmpImage->bytes_per_line,
2118 dstbits,linebytes);
2120 } else {
2121 if (rDst==bmpImage->red_mask || bDst==bmpImage->blue_mask) {
2122 /* ==== rgb 565 bmp -> rgb 555 dib ==== */
2123 /* ==== bgr 565 bmp -> bgr 555 dib ==== */
2124 convs->Convert_565_to_555_asis
2125 (width,lines,
2126 srcbits,-bmpImage->bytes_per_line,
2127 dstbits,linebytes);
2128 } else {
2129 /* ==== rgb 565 bmp -> bgr 555 dib ==== */
2130 /* ==== bgr 565 bmp -> rgb 555 dib ==== */
2131 convs->Convert_565_to_555_reverse
2132 (width,lines,
2133 srcbits,-bmpImage->bytes_per_line,
2134 dstbits,linebytes);
2137 } else {
2138 goto notsupported;
2141 break;
2143 case 24:
2144 if (bmpImage->bits_per_pixel == 24) {
2145 const char* srcbits;
2147 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2149 if (bmpImage->green_mask!=0x00ff00 ||
2150 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2151 goto notsupported;
2152 } else if ((rDst==0x1f && bmpImage->red_mask==0xff) ||
2153 (bDst==0x1f && bmpImage->blue_mask==0xff)) {
2154 if (gDst==0x03e0) {
2155 /* ==== rgb 888 bmp -> rgb 555 dib ==== */
2156 /* ==== bgr 888 bmp -> bgr 555 dib ==== */
2157 convs->Convert_888_to_555_asis
2158 (width,lines,
2159 srcbits,-bmpImage->bytes_per_line,
2160 dstbits,linebytes);
2161 } else {
2162 /* ==== rgb 888 bmp -> rgb 565 dib ==== */
2163 /* ==== rgb 888 bmp -> rgb 565 dib ==== */
2164 convs->Convert_888_to_565_asis
2165 (width,lines,
2166 srcbits,-bmpImage->bytes_per_line,
2167 dstbits,linebytes);
2169 } else {
2170 if (gDst==0x03e0) {
2171 /* ==== rgb 888 bmp -> bgr 555 dib ==== */
2172 /* ==== bgr 888 bmp -> rgb 555 dib ==== */
2173 convs->Convert_888_to_555_reverse
2174 (width,lines,
2175 srcbits,-bmpImage->bytes_per_line,
2176 dstbits,linebytes);
2177 } else {
2178 /* ==== rgb 888 bmp -> bgr 565 dib ==== */
2179 /* ==== bgr 888 bmp -> rgb 565 dib ==== */
2180 convs->Convert_888_to_565_reverse
2181 (width,lines,
2182 srcbits,-bmpImage->bytes_per_line,
2183 dstbits,linebytes);
2186 break;
2188 /* Fall through */
2190 case 32:
2192 const char* srcbits;
2194 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2196 if (bmpImage->green_mask!=0x00ff00 ||
2197 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2198 goto notsupported;
2199 } else if ((rDst==0x1f && bmpImage->red_mask==0xff) ||
2200 (bDst==0x1f && bmpImage->blue_mask==0xff)) {
2201 if (gDst==0x03e0) {
2202 /* ==== rgb 0888 bmp -> rgb 555 dib ==== */
2203 /* ==== bgr 0888 bmp -> bgr 555 dib ==== */
2204 convs->Convert_0888_to_555_asis
2205 (width,lines,
2206 srcbits,-bmpImage->bytes_per_line,
2207 dstbits,linebytes);
2208 } else {
2209 /* ==== rgb 0888 bmp -> rgb 565 dib ==== */
2210 /* ==== bgr 0888 bmp -> bgr 565 dib ==== */
2211 convs->Convert_0888_to_565_asis
2212 (width,lines,
2213 srcbits,-bmpImage->bytes_per_line,
2214 dstbits,linebytes);
2216 } else {
2217 if (gDst==0x03e0) {
2218 /* ==== rgb 0888 bmp -> bgr 555 dib ==== */
2219 /* ==== bgr 0888 bmp -> rgb 555 dib ==== */
2220 convs->Convert_0888_to_555_reverse
2221 (width,lines,
2222 srcbits,-bmpImage->bytes_per_line,
2223 dstbits,linebytes);
2224 } else {
2225 /* ==== rgb 0888 bmp -> bgr 565 dib ==== */
2226 /* ==== bgr 0888 bmp -> rgb 565 dib ==== */
2227 convs->Convert_0888_to_565_reverse
2228 (width,lines,
2229 srcbits,-bmpImage->bytes_per_line,
2230 dstbits,linebytes);
2234 break;
2236 case 1:
2237 case 4:
2238 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
2239 /* ==== pal 1 or 4 bmp -> rgb or bgr 555 or 565 dib ==== */
2240 int rShift,gShift,bShift;
2241 WORD* dstpixel;
2243 /* Shift everything 16 bits left so that all shifts are >0,
2244 * even for BGR DIBs. Then a single >> 16 will bring everything
2245 * back into place.
2247 rShift=16+X11DRV_DIB_MaskToShift(rDst)-3;
2248 gShift=16+X11DRV_DIB_MaskToShift(gDst)-3;
2249 bShift=16+X11DRV_DIB_MaskToShift(bDst)-3;
2250 if (gDst==0x07e0) {
2251 /* 6 bits for the green */
2252 gShift++;
2254 rDst=rDst << 16;
2255 gDst=gDst << 16;
2256 bDst=bDst << 16;
2257 for (h = lines - 1; h >= 0; h--) {
2258 dstpixel=(LPWORD)dstbits;
2259 for (x = 0; x < width; x++) {
2260 PALETTEENTRY srcval;
2261 DWORD dstval;
2262 srcval=srccolors[XGetPixel(bmpImage, x, h)];
2263 dstval=((srcval.peRed << rShift) & rDst) |
2264 ((srcval.peGreen << gShift) & gDst) |
2265 ((srcval.peBlue << bShift) & bDst);
2266 *dstpixel++=dstval >> 16;
2268 dstbits += linebytes;
2270 } else {
2271 goto notsupported;
2273 break;
2275 case 8:
2276 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
2277 /* ==== pal 8 bmp -> rgb or bgr 555 or 565 dib ==== */
2278 int rShift,gShift,bShift;
2279 const BYTE* srcbits;
2280 const BYTE* srcpixel;
2281 WORD* dstpixel;
2283 /* Shift everything 16 bits left so that all shifts are >0,
2284 * even for BGR DIBs. Then a single >> 16 will bring everything
2285 * back into place.
2287 rShift=16+X11DRV_DIB_MaskToShift(rDst)-3;
2288 gShift=16+X11DRV_DIB_MaskToShift(gDst)-3;
2289 bShift=16+X11DRV_DIB_MaskToShift(bDst)-3;
2290 if (gDst==0x07e0) {
2291 /* 6 bits for the green */
2292 gShift++;
2294 rDst=rDst << 16;
2295 gDst=gDst << 16;
2296 bDst=bDst << 16;
2297 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2298 for (h=0; h<lines; h++) {
2299 srcpixel=srcbits;
2300 dstpixel=(LPWORD)dstbits;
2301 for (x = 0; x < width; x++) {
2302 PALETTEENTRY srcval;
2303 DWORD dstval;
2304 srcval=srccolors[(int)*srcpixel++];
2305 dstval=((srcval.peRed << rShift) & rDst) |
2306 ((srcval.peGreen << gShift) & gDst) |
2307 ((srcval.peBlue << bShift) & bDst);
2308 *dstpixel++=dstval >> 16;
2310 srcbits -= bmpImage->bytes_per_line;
2311 dstbits += linebytes;
2313 } else {
2314 goto notsupported;
2316 break;
2318 default:
2319 notsupported:
2321 /* ==== any bmp format -> rgb or bgr 555 or 565 dib ==== */
2322 int rShift,gShift,bShift;
2323 WORD* dstpixel;
2325 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 16 bit DIB (%lx,%lx,%lx)\n",
2326 bmpImage->depth, bmpImage->red_mask,
2327 bmpImage->green_mask, bmpImage->blue_mask,
2328 rDst, gDst, bDst);
2330 /* Shift everything 16 bits left so that all shifts are >0,
2331 * even for BGR DIBs. Then a single >> 16 will bring everything
2332 * back into place.
2334 rShift=16+X11DRV_DIB_MaskToShift(rDst)-3;
2335 gShift=16+X11DRV_DIB_MaskToShift(gDst)-3;
2336 bShift=16+X11DRV_DIB_MaskToShift(bDst)-3;
2337 if (gDst==0x07e0) {
2338 /* 6 bits for the green */
2339 gShift++;
2341 rDst=rDst << 16;
2342 gDst=gDst << 16;
2343 bDst=bDst << 16;
2344 for (h = lines - 1; h >= 0; h--) {
2345 dstpixel=(LPWORD)dstbits;
2346 for (x = 0; x < width; x++) {
2347 COLORREF srcval;
2348 DWORD dstval;
2349 srcval=X11DRV_PALETTE_ToLogical(XGetPixel(bmpImage, x, h));
2350 dstval=((GetRValue(srcval) << rShift) & rDst) |
2351 ((GetGValue(srcval) << gShift) & gDst) |
2352 ((GetBValue(srcval) << bShift) & bDst);
2353 *dstpixel++=dstval >> 16;
2355 dstbits += linebytes;
2358 break;
2363 /***********************************************************************
2364 * X11DRV_DIB_SetImageBits_24
2366 * SetDIBits for a 24-bit deep DIB.
2368 static void X11DRV_DIB_SetImageBits_24( int lines, const BYTE *srcbits,
2369 DWORD srcwidth, DWORD dstwidth, int left,
2370 X11DRV_PDEVICE *physDev,
2371 DWORD rSrc, DWORD gSrc, DWORD bSrc,
2372 XImage *bmpImage, DWORD linebytes )
2374 DWORD x;
2375 int h, width = min(srcwidth, dstwidth);
2376 const dib_conversions *convs = (bmpImage->byte_order == LSBFirst) ? &dib_normal : &dib_dst_byteswap;
2378 if (lines < 0 )
2380 lines = -lines;
2381 srcbits = srcbits + linebytes * (lines - 1);
2382 linebytes = -linebytes;
2385 switch (bmpImage->depth)
2387 case 24:
2388 if (bmpImage->bits_per_pixel==24) {
2389 char* dstbits;
2391 srcbits=srcbits+left*3;
2392 dstbits=bmpImage->data+left*3+(lines-1)*bmpImage->bytes_per_line;
2394 if (bmpImage->green_mask!=0x00ff00 ||
2395 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2396 goto notsupported;
2397 } else if (rSrc==bmpImage->red_mask) {
2398 /* ==== rgb 888 dib -> rgb 888 bmp ==== */
2399 /* ==== bgr 888 dib -> bgr 888 bmp ==== */
2400 convs->Convert_888_asis
2401 (width,lines,
2402 srcbits,linebytes,
2403 dstbits,-bmpImage->bytes_per_line);
2404 } else {
2405 /* ==== rgb 888 dib -> bgr 888 bmp ==== */
2406 /* ==== bgr 888 dib -> rgb 888 bmp ==== */
2407 convs->Convert_888_reverse
2408 (width,lines,
2409 srcbits,linebytes,
2410 dstbits,-bmpImage->bytes_per_line);
2412 break;
2414 /* fall through */
2416 case 32:
2418 char* dstbits;
2420 srcbits=srcbits+left*3;
2421 dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
2423 if (bmpImage->green_mask!=0x00ff00 ||
2424 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2425 goto notsupported;
2426 } else if (rSrc==bmpImage->red_mask) {
2427 /* ==== rgb 888 dib -> rgb 0888 bmp ==== */
2428 /* ==== bgr 888 dib -> bgr 0888 bmp ==== */
2429 convs->Convert_888_to_0888_asis
2430 (width,lines,
2431 srcbits,linebytes,
2432 dstbits,-bmpImage->bytes_per_line);
2433 } else {
2434 /* ==== rgb 888 dib -> bgr 0888 bmp ==== */
2435 /* ==== bgr 888 dib -> rgb 0888 bmp ==== */
2436 convs->Convert_888_to_0888_reverse
2437 (width,lines,
2438 srcbits,linebytes,
2439 dstbits,-bmpImage->bytes_per_line);
2441 break;
2444 case 15:
2445 case 16:
2447 char* dstbits;
2449 srcbits=srcbits+left*3;
2450 dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
2452 if (bmpImage->green_mask==0x03e0) {
2453 if ((rSrc==0xff0000 && bmpImage->red_mask==0x7f00) ||
2454 (bSrc==0xff0000 && bmpImage->blue_mask==0x7f00)) {
2455 /* ==== rgb 888 dib -> rgb 555 bmp ==== */
2456 /* ==== bgr 888 dib -> bgr 555 bmp ==== */
2457 convs->Convert_888_to_555_asis
2458 (width,lines,
2459 srcbits,linebytes,
2460 dstbits,-bmpImage->bytes_per_line);
2461 } else if ((rSrc==0xff && bmpImage->red_mask==0x7f00) ||
2462 (bSrc==0xff && bmpImage->blue_mask==0x7f00)) {
2463 /* ==== rgb 888 dib -> bgr 555 bmp ==== */
2464 /* ==== bgr 888 dib -> rgb 555 bmp ==== */
2465 convs->Convert_888_to_555_reverse
2466 (width,lines,
2467 srcbits,linebytes,
2468 dstbits,-bmpImage->bytes_per_line);
2469 } else {
2470 goto notsupported;
2472 } else if (bmpImage->green_mask==0x07e0) {
2473 if ((rSrc==0xff0000 && bmpImage->red_mask==0xf800) ||
2474 (bSrc==0xff0000 && bmpImage->blue_mask==0xf800)) {
2475 /* ==== rgb 888 dib -> rgb 565 bmp ==== */
2476 /* ==== bgr 888 dib -> bgr 565 bmp ==== */
2477 convs->Convert_888_to_565_asis
2478 (width,lines,
2479 srcbits,linebytes,
2480 dstbits,-bmpImage->bytes_per_line);
2481 } else if ((rSrc==0xff && bmpImage->red_mask==0xf800) ||
2482 (bSrc==0xff && bmpImage->blue_mask==0xf800)) {
2483 /* ==== rgb 888 dib -> bgr 565 bmp ==== */
2484 /* ==== bgr 888 dib -> rgb 565 bmp ==== */
2485 convs->Convert_888_to_565_reverse
2486 (width,lines,
2487 srcbits,linebytes,
2488 dstbits,-bmpImage->bytes_per_line);
2489 } else {
2490 goto notsupported;
2492 } else {
2493 goto notsupported;
2496 break;
2498 default:
2499 notsupported:
2500 WARN("from 24 bit DIB (%lx,%lx,%lx) to unknown %d bit bitmap (%lx,%lx,%lx)\n",
2501 rSrc, gSrc, bSrc, bmpImage->bits_per_pixel, bmpImage->red_mask,
2502 bmpImage->green_mask, bmpImage->blue_mask );
2503 /* fall through */
2504 case 1:
2505 case 4:
2506 case 8:
2508 /* ==== rgb 888 dib -> any bmp bormat ==== */
2509 const BYTE* srcbyte;
2511 /* Windows only supports one 24bpp DIB format: RGB888 */
2512 srcbits+=left*3;
2513 for (h = lines - 1; h >= 0; h--) {
2514 srcbyte=(const BYTE*)srcbits;
2515 for (x = left; x < width+left; x++) {
2516 XPutPixel(bmpImage, x, h,
2517 X11DRV_PALETTE_ToPhysical
2518 (physDev, RGB(srcbyte[2], srcbyte[1], srcbyte[0])));
2519 srcbyte+=3;
2521 srcbits += linebytes;
2524 break;
2529 /***********************************************************************
2530 * X11DRV_DIB_GetImageBits_24
2532 * GetDIBits for an 24-bit deep DIB.
2534 static void X11DRV_DIB_GetImageBits_24( int lines, BYTE *dstbits,
2535 DWORD dstwidth, DWORD srcwidth,
2536 PALETTEENTRY *srccolors,
2537 DWORD rDst, DWORD gDst, DWORD bDst,
2538 XImage *bmpImage, DWORD linebytes )
2540 DWORD x;
2541 int h, width = min(srcwidth, dstwidth);
2542 const dib_conversions *convs = (bmpImage->byte_order == LSBFirst) ? &dib_normal : &dib_src_byteswap;
2544 if (lines < 0 )
2546 lines = -lines;
2547 dstbits = dstbits + ( linebytes * (lines-1) );
2548 linebytes = -linebytes;
2551 switch (bmpImage->depth)
2553 case 24:
2554 if (bmpImage->bits_per_pixel==24) {
2555 const char* srcbits;
2557 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2559 if (bmpImage->green_mask!=0x00ff00 ||
2560 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2561 goto notsupported;
2562 } else if (rDst==bmpImage->red_mask) {
2563 /* ==== rgb 888 bmp -> rgb 888 dib ==== */
2564 /* ==== bgr 888 bmp -> bgr 888 dib ==== */
2565 convs->Convert_888_asis
2566 (width,lines,
2567 srcbits,-bmpImage->bytes_per_line,
2568 dstbits,linebytes);
2569 } else {
2570 /* ==== rgb 888 bmp -> bgr 888 dib ==== */
2571 /* ==== bgr 888 bmp -> rgb 888 dib ==== */
2572 convs->Convert_888_reverse
2573 (width,lines,
2574 srcbits,-bmpImage->bytes_per_line,
2575 dstbits,linebytes);
2577 break;
2579 /* fall through */
2581 case 32:
2583 const char* srcbits;
2585 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2587 if (bmpImage->green_mask!=0x00ff00 ||
2588 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2589 goto notsupported;
2590 } else if (rDst==bmpImage->red_mask) {
2591 /* ==== rgb 888 bmp -> rgb 0888 dib ==== */
2592 /* ==== bgr 888 bmp -> bgr 0888 dib ==== */
2593 convs->Convert_0888_to_888_asis
2594 (width,lines,
2595 srcbits,-bmpImage->bytes_per_line,
2596 dstbits,linebytes);
2597 } else {
2598 /* ==== rgb 888 bmp -> bgr 0888 dib ==== */
2599 /* ==== bgr 888 bmp -> rgb 0888 dib ==== */
2600 convs->Convert_0888_to_888_reverse
2601 (width,lines,
2602 srcbits,-bmpImage->bytes_per_line,
2603 dstbits,linebytes);
2605 break;
2608 case 15:
2609 case 16:
2611 const char* srcbits;
2613 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2615 if (bmpImage->green_mask==0x03e0) {
2616 if ((rDst==0xff0000 && bmpImage->red_mask==0x7f00) ||
2617 (bDst==0xff0000 && bmpImage->blue_mask==0x7f00)) {
2618 /* ==== rgb 555 bmp -> rgb 888 dib ==== */
2619 /* ==== bgr 555 bmp -> bgr 888 dib ==== */
2620 convs->Convert_555_to_888_asis
2621 (width,lines,
2622 srcbits,-bmpImage->bytes_per_line,
2623 dstbits,linebytes);
2624 } else if ((rDst==0xff && bmpImage->red_mask==0x7f00) ||
2625 (bDst==0xff && bmpImage->blue_mask==0x7f00)) {
2626 /* ==== rgb 555 bmp -> bgr 888 dib ==== */
2627 /* ==== bgr 555 bmp -> rgb 888 dib ==== */
2628 convs->Convert_555_to_888_reverse
2629 (width,lines,
2630 srcbits,-bmpImage->bytes_per_line,
2631 dstbits,linebytes);
2632 } else {
2633 goto notsupported;
2635 } else if (bmpImage->green_mask==0x07e0) {
2636 if ((rDst==0xff0000 && bmpImage->red_mask==0xf800) ||
2637 (bDst==0xff0000 && bmpImage->blue_mask==0xf800)) {
2638 /* ==== rgb 565 bmp -> rgb 888 dib ==== */
2639 /* ==== bgr 565 bmp -> bgr 888 dib ==== */
2640 convs->Convert_565_to_888_asis
2641 (width,lines,
2642 srcbits,-bmpImage->bytes_per_line,
2643 dstbits,linebytes);
2644 } else if ((rDst==0xff && bmpImage->red_mask==0xf800) ||
2645 (bDst==0xff && bmpImage->blue_mask==0xf800)) {
2646 /* ==== rgb 565 bmp -> bgr 888 dib ==== */
2647 /* ==== bgr 565 bmp -> rgb 888 dib ==== */
2648 convs->Convert_565_to_888_reverse
2649 (width,lines,
2650 srcbits,-bmpImage->bytes_per_line,
2651 dstbits,linebytes);
2652 } else {
2653 goto notsupported;
2655 } else {
2656 goto notsupported;
2659 break;
2661 case 1:
2662 case 4:
2663 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
2664 /* ==== pal 1 or 4 bmp -> rgb 888 dib ==== */
2665 BYTE* dstbyte;
2667 /* Windows only supports one 24bpp DIB format: rgb 888 */
2668 for (h = lines - 1; h >= 0; h--) {
2669 dstbyte=dstbits;
2670 for (x = 0; x < width; x++) {
2671 PALETTEENTRY srcval;
2672 srcval=srccolors[XGetPixel(bmpImage, x, h)];
2673 dstbyte[0]=srcval.peBlue;
2674 dstbyte[1]=srcval.peGreen;
2675 dstbyte[2]=srcval.peRed;
2676 dstbyte+=3;
2678 dstbits += linebytes;
2680 } else {
2681 goto notsupported;
2683 break;
2685 case 8:
2686 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask == 0 && srccolors) {
2687 /* ==== pal 8 bmp -> rgb 888 dib ==== */
2688 const void* srcbits;
2689 const BYTE* srcpixel;
2690 BYTE* dstbyte;
2692 /* Windows only supports one 24bpp DIB format: rgb 888 */
2693 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2694 for (h = lines - 1; h >= 0; h--) {
2695 srcpixel=srcbits;
2696 dstbyte=dstbits;
2697 for (x = 0; x < width; x++ ) {
2698 PALETTEENTRY srcval;
2699 srcval=srccolors[(int)*srcpixel++];
2700 dstbyte[0]=srcval.peBlue;
2701 dstbyte[1]=srcval.peGreen;
2702 dstbyte[2]=srcval.peRed;
2703 dstbyte+=3;
2705 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2706 dstbits += linebytes;
2708 } else {
2709 goto notsupported;
2711 break;
2713 default:
2714 notsupported:
2716 /* ==== any bmp format -> 888 dib ==== */
2717 BYTE* dstbyte;
2719 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 24 bit DIB (%lx,%lx,%lx)\n",
2720 bmpImage->depth, bmpImage->red_mask,
2721 bmpImage->green_mask, bmpImage->blue_mask,
2722 rDst, gDst, bDst );
2724 /* Windows only supports one 24bpp DIB format: rgb 888 */
2725 for (h = lines - 1; h >= 0; h--) {
2726 dstbyte=dstbits;
2727 for (x = 0; x < width; x++) {
2728 COLORREF srcval=X11DRV_PALETTE_ToLogical
2729 (XGetPixel( bmpImage, x, h ));
2730 dstbyte[0]=GetBValue(srcval);
2731 dstbyte[1]=GetGValue(srcval);
2732 dstbyte[2]=GetRValue(srcval);
2733 dstbyte+=3;
2735 dstbits += linebytes;
2738 break;
2743 /***********************************************************************
2744 * X11DRV_DIB_SetImageBits_32
2746 * SetDIBits for a 32-bit deep DIB.
2748 static void X11DRV_DIB_SetImageBits_32(int lines, const BYTE *srcbits,
2749 DWORD srcwidth, DWORD dstwidth, int left,
2750 X11DRV_PDEVICE *physDev,
2751 DWORD rSrc, DWORD gSrc, DWORD bSrc,
2752 XImage *bmpImage,
2753 DWORD linebytes)
2755 DWORD x, *ptr;
2756 int h, width = min(srcwidth, dstwidth);
2757 const dib_conversions *convs = (bmpImage->byte_order == LSBFirst) ? &dib_normal : &dib_dst_byteswap;
2759 if (lines < 0 )
2761 lines = -lines;
2762 srcbits = srcbits + ( linebytes * (lines-1) );
2763 linebytes = -linebytes;
2766 ptr = (DWORD *) srcbits + left;
2768 switch (bmpImage->depth)
2770 case 24:
2771 if (bmpImage->bits_per_pixel==24) {
2772 char* dstbits;
2774 srcbits=srcbits+left*4;
2775 dstbits=bmpImage->data+left*3+(lines-1)*bmpImage->bytes_per_line;
2777 if (rSrc==bmpImage->red_mask && gSrc==bmpImage->green_mask && bSrc==bmpImage->blue_mask) {
2778 /* ==== rgb 0888 dib -> rgb 888 bmp ==== */
2779 /* ==== bgr 0888 dib -> bgr 888 bmp ==== */
2780 convs->Convert_0888_to_888_asis
2781 (width,lines,
2782 srcbits,linebytes,
2783 dstbits,-bmpImage->bytes_per_line);
2784 } else if (bmpImage->green_mask!=0x00ff00 ||
2785 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2786 goto notsupported;
2787 /* the tests below assume sane bmpImage masks */
2788 } else if (rSrc==bmpImage->blue_mask && gSrc==bmpImage->green_mask && bSrc==bmpImage->red_mask) {
2789 /* ==== rgb 0888 dib -> bgr 888 bmp ==== */
2790 /* ==== bgr 0888 dib -> rgb 888 bmp ==== */
2791 convs->Convert_0888_to_888_reverse
2792 (width,lines,
2793 srcbits,linebytes,
2794 dstbits,-bmpImage->bytes_per_line);
2795 } else if (bmpImage->blue_mask==0xff) {
2796 /* ==== any 0888 dib -> rgb 888 bmp ==== */
2797 convs->Convert_any0888_to_rgb888
2798 (width,lines,
2799 srcbits,linebytes,
2800 rSrc,gSrc,bSrc,
2801 dstbits,-bmpImage->bytes_per_line);
2802 } else {
2803 /* ==== any 0888 dib -> bgr 888 bmp ==== */
2804 convs->Convert_any0888_to_bgr888
2805 (width,lines,
2806 srcbits,linebytes,
2807 rSrc,gSrc,bSrc,
2808 dstbits,-bmpImage->bytes_per_line);
2810 break;
2812 /* fall through */
2814 case 32:
2816 char* dstbits;
2818 srcbits=srcbits+left*4;
2819 dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
2821 if (gSrc==bmpImage->green_mask) {
2822 if (rSrc==bmpImage->red_mask && bSrc==bmpImage->blue_mask) {
2823 /* ==== rgb 0888 dib -> rgb 0888 bmp ==== */
2824 /* ==== bgr 0888 dib -> bgr 0888 bmp ==== */
2825 convs->Convert_0888_asis
2826 (width,lines,
2827 srcbits,linebytes,
2828 dstbits,-bmpImage->bytes_per_line);
2829 } else if (bmpImage->green_mask!=0x00ff00 ||
2830 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2831 goto notsupported;
2832 /* the tests below assume sane bmpImage masks */
2833 } else if (rSrc==bmpImage->blue_mask && bSrc==bmpImage->red_mask) {
2834 /* ==== rgb 0888 dib -> bgr 0888 bmp ==== */
2835 /* ==== bgr 0888 dib -> rgb 0888 bmp ==== */
2836 convs->Convert_0888_reverse
2837 (width,lines,
2838 srcbits,linebytes,
2839 dstbits,-bmpImage->bytes_per_line);
2840 } else {
2841 /* ==== any 0888 dib -> any 0888 bmp ==== */
2842 convs->Convert_0888_any
2843 (width,lines,
2844 srcbits,linebytes,
2845 rSrc,gSrc,bSrc,
2846 dstbits,-bmpImage->bytes_per_line,
2847 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
2849 } else if (bmpImage->green_mask!=0x00ff00 ||
2850 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2851 goto notsupported;
2852 /* the tests below assume sane bmpImage masks */
2853 } else {
2854 /* ==== any 0888 dib -> any 0888 bmp ==== */
2855 convs->Convert_0888_any
2856 (width,lines,
2857 srcbits,linebytes,
2858 rSrc,gSrc,bSrc,
2859 dstbits,-bmpImage->bytes_per_line,
2860 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
2863 break;
2865 case 15:
2866 case 16:
2868 char* dstbits;
2870 srcbits=srcbits+left*4;
2871 dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
2873 if (rSrc==0xff0000 && gSrc==0x00ff00 && bSrc==0x0000ff) {
2874 if (bmpImage->green_mask==0x03e0) {
2875 if (bmpImage->red_mask==0x7f00) {
2876 /* ==== rgb 0888 dib -> rgb 555 bmp ==== */
2877 convs->Convert_0888_to_555_asis
2878 (width,lines,
2879 srcbits,linebytes,
2880 dstbits,-bmpImage->bytes_per_line);
2881 } else if (bmpImage->blue_mask==0x7f00) {
2882 /* ==== rgb 0888 dib -> bgr 555 bmp ==== */
2883 convs->Convert_0888_to_555_reverse
2884 (width,lines,
2885 srcbits,linebytes,
2886 dstbits,-bmpImage->bytes_per_line);
2887 } else {
2888 goto notsupported;
2890 } else if (bmpImage->green_mask==0x07e0) {
2891 if (bmpImage->red_mask==0xf800) {
2892 /* ==== rgb 0888 dib -> rgb 565 bmp ==== */
2893 convs->Convert_0888_to_565_asis
2894 (width,lines,
2895 srcbits,linebytes,
2896 dstbits,-bmpImage->bytes_per_line);
2897 } else if (bmpImage->blue_mask==0xf800) {
2898 /* ==== rgb 0888 dib -> bgr 565 bmp ==== */
2899 convs->Convert_0888_to_565_reverse
2900 (width,lines,
2901 srcbits,linebytes,
2902 dstbits,-bmpImage->bytes_per_line);
2903 } else {
2904 goto notsupported;
2906 } else {
2907 goto notsupported;
2909 } else if (rSrc==0x0000ff && gSrc==0x00ff00 && bSrc==0xff0000) {
2910 if (bmpImage->green_mask==0x03e0) {
2911 if (bmpImage->blue_mask==0x7f00) {
2912 /* ==== bgr 0888 dib -> bgr 555 bmp ==== */
2913 convs->Convert_0888_to_555_asis
2914 (width,lines,
2915 srcbits,linebytes,
2916 dstbits,-bmpImage->bytes_per_line);
2917 } else if (bmpImage->red_mask==0x7f00) {
2918 /* ==== bgr 0888 dib -> rgb 555 bmp ==== */
2919 convs->Convert_0888_to_555_reverse
2920 (width,lines,
2921 srcbits,linebytes,
2922 dstbits,-bmpImage->bytes_per_line);
2923 } else {
2924 goto notsupported;
2926 } else if (bmpImage->green_mask==0x07e0) {
2927 if (bmpImage->blue_mask==0xf800) {
2928 /* ==== bgr 0888 dib -> bgr 565 bmp ==== */
2929 convs->Convert_0888_to_565_asis
2930 (width,lines,
2931 srcbits,linebytes,
2932 dstbits,-bmpImage->bytes_per_line);
2933 } else if (bmpImage->red_mask==0xf800) {
2934 /* ==== bgr 0888 dib -> rgb 565 bmp ==== */
2935 convs->Convert_0888_to_565_reverse
2936 (width,lines,
2937 srcbits,linebytes,
2938 dstbits,-bmpImage->bytes_per_line);
2939 } else {
2940 goto notsupported;
2942 } else {
2943 goto notsupported;
2945 } else {
2946 if (bmpImage->green_mask==0x03e0 &&
2947 (bmpImage->red_mask==0x7f00 ||
2948 bmpImage->blue_mask==0x7f00)) {
2949 /* ==== any 0888 dib -> rgb or bgr 555 bmp ==== */
2950 convs->Convert_any0888_to_5x5
2951 (width,lines,
2952 srcbits,linebytes,
2953 rSrc,gSrc,bSrc,
2954 dstbits,-bmpImage->bytes_per_line,
2955 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
2956 } else if (bmpImage->green_mask==0x07e0 &&
2957 (bmpImage->red_mask==0xf800 ||
2958 bmpImage->blue_mask==0xf800)) {
2959 /* ==== any 0888 dib -> rgb or bgr 565 bmp ==== */
2960 convs->Convert_any0888_to_5x5
2961 (width,lines,
2962 srcbits,linebytes,
2963 rSrc,gSrc,bSrc,
2964 dstbits,-bmpImage->bytes_per_line,
2965 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
2966 } else {
2967 goto notsupported;
2971 break;
2973 default:
2974 notsupported:
2975 WARN("from 32 bit DIB (%lx,%lx,%lx) to unknown %d bit bitmap (%lx,%lx,%lx)\n",
2976 rSrc, gSrc, bSrc, bmpImage->bits_per_pixel, bmpImage->red_mask,
2977 bmpImage->green_mask, bmpImage->blue_mask );
2978 /* fall through */
2979 case 1:
2980 case 4:
2981 case 8:
2983 /* ==== any 0888 dib -> pal 1, 4 or 8 bmp ==== */
2984 const DWORD* srcpixel;
2985 int rShift,gShift,bShift;
2987 rShift=X11DRV_DIB_MaskToShift(rSrc);
2988 gShift=X11DRV_DIB_MaskToShift(gSrc);
2989 bShift=X11DRV_DIB_MaskToShift(bSrc);
2990 srcbits+=left*4;
2991 for (h = lines - 1; h >= 0; h--) {
2992 srcpixel=(const DWORD*)srcbits;
2993 for (x = left; x < width+left; x++) {
2994 DWORD srcvalue;
2995 BYTE red,green,blue;
2996 srcvalue=*srcpixel++;
2997 red= (srcvalue >> rShift) & 0xff;
2998 green=(srcvalue >> gShift) & 0xff;
2999 blue= (srcvalue >> bShift) & 0xff;
3000 XPutPixel(bmpImage, x, h, X11DRV_PALETTE_ToPhysical
3001 (physDev, RGB(red,green,blue)));
3003 srcbits += linebytes;
3006 break;
3011 /***********************************************************************
3012 * X11DRV_DIB_GetImageBits_32
3014 * GetDIBits for an 32-bit deep DIB.
3016 static void X11DRV_DIB_GetImageBits_32( int lines, BYTE *dstbits,
3017 DWORD dstwidth, DWORD srcwidth,
3018 PALETTEENTRY *srccolors,
3019 DWORD rDst, DWORD gDst, DWORD bDst,
3020 XImage *bmpImage, DWORD linebytes )
3022 DWORD x;
3023 int h, width = min(srcwidth, dstwidth);
3024 BYTE *bits;
3025 const dib_conversions *convs = (bmpImage->byte_order == LSBFirst) ? &dib_normal : &dib_src_byteswap;
3027 if (lines < 0 )
3029 lines = -lines;
3030 dstbits = dstbits + ( linebytes * (lines-1) );
3031 linebytes = -linebytes;
3034 bits = dstbits;
3036 switch (bmpImage->depth)
3038 case 24:
3039 if (bmpImage->bits_per_pixel==24) {
3040 const void* srcbits;
3042 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3044 if (rDst==bmpImage->red_mask && gDst==bmpImage->green_mask && bDst==bmpImage->blue_mask) {
3045 /* ==== rgb 888 bmp -> rgb 0888 dib ==== */
3046 /* ==== bgr 888 bmp -> bgr 0888 dib ==== */
3047 convs->Convert_888_to_0888_asis
3048 (width,lines,
3049 srcbits,-bmpImage->bytes_per_line,
3050 dstbits,linebytes);
3051 } else if (bmpImage->green_mask!=0x00ff00 ||
3052 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3053 goto notsupported;
3054 /* the tests below assume sane bmpImage masks */
3055 } else if (rDst==bmpImage->blue_mask && gDst==bmpImage->green_mask && bDst==bmpImage->red_mask) {
3056 /* ==== rgb 888 bmp -> bgr 0888 dib ==== */
3057 /* ==== bgr 888 bmp -> rgb 0888 dib ==== */
3058 convs->Convert_888_to_0888_reverse
3059 (width,lines,
3060 srcbits,-bmpImage->bytes_per_line,
3061 dstbits,linebytes);
3062 } else if (bmpImage->blue_mask==0xff) {
3063 /* ==== rgb 888 bmp -> any 0888 dib ==== */
3064 convs->Convert_rgb888_to_any0888
3065 (width,lines,
3066 srcbits,-bmpImage->bytes_per_line,
3067 dstbits,linebytes,
3068 rDst,gDst,bDst);
3069 } else {
3070 /* ==== bgr 888 bmp -> any 0888 dib ==== */
3071 convs->Convert_bgr888_to_any0888
3072 (width,lines,
3073 srcbits,-bmpImage->bytes_per_line,
3074 dstbits,linebytes,
3075 rDst,gDst,bDst);
3077 break;
3079 /* fall through */
3081 case 32:
3083 const char* srcbits;
3085 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3087 if (gDst==bmpImage->green_mask) {
3088 if (rDst==bmpImage->red_mask && bDst==bmpImage->blue_mask) {
3089 /* ==== rgb 0888 bmp -> rgb 0888 dib ==== */
3090 /* ==== bgr 0888 bmp -> bgr 0888 dib ==== */
3091 convs->Convert_0888_asis
3092 (width,lines,
3093 srcbits,-bmpImage->bytes_per_line,
3094 dstbits,linebytes);
3095 } else if (bmpImage->green_mask!=0x00ff00 ||
3096 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3097 goto notsupported;
3098 /* the tests below assume sane bmpImage masks */
3099 } else if (rDst==bmpImage->blue_mask && bDst==bmpImage->red_mask) {
3100 /* ==== rgb 0888 bmp -> bgr 0888 dib ==== */
3101 /* ==== bgr 0888 bmp -> rgb 0888 dib ==== */
3102 convs->Convert_0888_reverse
3103 (width,lines,
3104 srcbits,-bmpImage->bytes_per_line,
3105 dstbits,linebytes);
3106 } else {
3107 /* ==== any 0888 bmp -> any 0888 dib ==== */
3108 convs->Convert_0888_any
3109 (width,lines,
3110 srcbits,-bmpImage->bytes_per_line,
3111 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
3112 dstbits,linebytes,
3113 rDst,gDst,bDst);
3115 } else if (bmpImage->green_mask!=0x00ff00 ||
3116 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3117 goto notsupported;
3118 /* the tests below assume sane bmpImage masks */
3119 } else {
3120 /* ==== any 0888 bmp -> any 0888 dib ==== */
3121 convs->Convert_0888_any
3122 (width,lines,
3123 srcbits,-bmpImage->bytes_per_line,
3124 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
3125 dstbits,linebytes,
3126 rDst,gDst,bDst);
3129 break;
3131 case 15:
3132 case 16:
3134 const char* srcbits;
3136 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3138 if (rDst==0xff0000 && gDst==0x00ff00 && bDst==0x0000ff) {
3139 if (bmpImage->green_mask==0x03e0) {
3140 if (bmpImage->red_mask==0x7f00) {
3141 /* ==== rgb 555 bmp -> rgb 0888 dib ==== */
3142 convs->Convert_555_to_0888_asis
3143 (width,lines,
3144 srcbits,-bmpImage->bytes_per_line,
3145 dstbits,linebytes);
3146 } else if (bmpImage->blue_mask==0x7f00) {
3147 /* ==== bgr 555 bmp -> rgb 0888 dib ==== */
3148 convs->Convert_555_to_0888_reverse
3149 (width,lines,
3150 srcbits,-bmpImage->bytes_per_line,
3151 dstbits,linebytes);
3152 } else {
3153 goto notsupported;
3155 } else if (bmpImage->green_mask==0x07e0) {
3156 if (bmpImage->red_mask==0xf800) {
3157 /* ==== rgb 565 bmp -> rgb 0888 dib ==== */
3158 convs->Convert_565_to_0888_asis
3159 (width,lines,
3160 srcbits,-bmpImage->bytes_per_line,
3161 dstbits,linebytes);
3162 } else if (bmpImage->blue_mask==0xf800) {
3163 /* ==== bgr 565 bmp -> rgb 0888 dib ==== */
3164 convs->Convert_565_to_0888_reverse
3165 (width,lines,
3166 srcbits,-bmpImage->bytes_per_line,
3167 dstbits,linebytes);
3168 } else {
3169 goto notsupported;
3171 } else {
3172 goto notsupported;
3174 } else if (rDst==0x0000ff && gDst==0x00ff00 && bDst==0xff0000) {
3175 if (bmpImage->green_mask==0x03e0) {
3176 if (bmpImage->blue_mask==0x7f00) {
3177 /* ==== bgr 555 bmp -> bgr 0888 dib ==== */
3178 convs->Convert_555_to_0888_asis
3179 (width,lines,
3180 srcbits,-bmpImage->bytes_per_line,
3181 dstbits,linebytes);
3182 } else if (bmpImage->red_mask==0x7f00) {
3183 /* ==== rgb 555 bmp -> bgr 0888 dib ==== */
3184 convs->Convert_555_to_0888_reverse
3185 (width,lines,
3186 srcbits,-bmpImage->bytes_per_line,
3187 dstbits,linebytes);
3188 } else {
3189 goto notsupported;
3191 } else if (bmpImage->green_mask==0x07e0) {
3192 if (bmpImage->blue_mask==0xf800) {
3193 /* ==== bgr 565 bmp -> bgr 0888 dib ==== */
3194 convs->Convert_565_to_0888_asis
3195 (width,lines,
3196 srcbits,-bmpImage->bytes_per_line,
3197 dstbits,linebytes);
3198 } else if (bmpImage->red_mask==0xf800) {
3199 /* ==== rgb 565 bmp -> bgr 0888 dib ==== */
3200 convs->Convert_565_to_0888_reverse
3201 (width,lines,
3202 srcbits,-bmpImage->bytes_per_line,
3203 dstbits,linebytes);
3204 } else {
3205 goto notsupported;
3207 } else {
3208 goto notsupported;
3210 } else {
3211 if (bmpImage->green_mask==0x03e0 &&
3212 (bmpImage->red_mask==0x7f00 ||
3213 bmpImage->blue_mask==0x7f00)) {
3214 /* ==== rgb or bgr 555 bmp -> any 0888 dib ==== */
3215 convs->Convert_5x5_to_any0888
3216 (width,lines,
3217 srcbits,-bmpImage->bytes_per_line,
3218 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
3219 dstbits,linebytes,
3220 rDst,gDst,bDst);
3221 } else if (bmpImage->green_mask==0x07e0 &&
3222 (bmpImage->red_mask==0xf800 ||
3223 bmpImage->blue_mask==0xf800)) {
3224 /* ==== rgb or bgr 565 bmp -> any 0888 dib ==== */
3225 convs->Convert_5x5_to_any0888
3226 (width,lines,
3227 srcbits,-bmpImage->bytes_per_line,
3228 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
3229 dstbits,linebytes,
3230 rDst,gDst,bDst);
3231 } else {
3232 goto notsupported;
3236 break;
3238 case 1:
3239 case 4:
3240 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
3241 /* ==== pal 1 or 4 bmp -> any 0888 dib ==== */
3242 int rShift,gShift,bShift;
3243 DWORD* dstpixel;
3245 rShift=X11DRV_DIB_MaskToShift(rDst);
3246 gShift=X11DRV_DIB_MaskToShift(gDst);
3247 bShift=X11DRV_DIB_MaskToShift(bDst);
3248 for (h = lines - 1; h >= 0; h--) {
3249 dstpixel=(DWORD*)dstbits;
3250 for (x = 0; x < width; x++) {
3251 PALETTEENTRY srcval;
3252 srcval = srccolors[XGetPixel(bmpImage, x, h)];
3253 *dstpixel++=(srcval.peRed << rShift) |
3254 (srcval.peGreen << gShift) |
3255 (srcval.peBlue << bShift);
3257 dstbits += linebytes;
3259 } else {
3260 goto notsupported;
3262 break;
3264 case 8:
3265 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
3266 /* ==== pal 8 bmp -> any 0888 dib ==== */
3267 int rShift,gShift,bShift;
3268 const void* srcbits;
3269 const BYTE* srcpixel;
3270 DWORD* dstpixel;
3272 rShift=X11DRV_DIB_MaskToShift(rDst);
3273 gShift=X11DRV_DIB_MaskToShift(gDst);
3274 bShift=X11DRV_DIB_MaskToShift(bDst);
3275 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3276 for (h = lines - 1; h >= 0; h--) {
3277 srcpixel=srcbits;
3278 dstpixel=(DWORD*)dstbits;
3279 for (x = 0; x < width; x++) {
3280 PALETTEENTRY srcval;
3281 srcval=srccolors[(int)*srcpixel++];
3282 *dstpixel++=(srcval.peRed << rShift) |
3283 (srcval.peGreen << gShift) |
3284 (srcval.peBlue << bShift);
3286 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
3287 dstbits += linebytes;
3289 } else {
3290 goto notsupported;
3292 break;
3294 default:
3295 notsupported:
3297 /* ==== any bmp format -> any 0888 dib ==== */
3298 int rShift,gShift,bShift;
3299 DWORD* dstpixel;
3301 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 32 bit DIB (%lx,%lx,%lx)\n",
3302 bmpImage->depth, bmpImage->red_mask,
3303 bmpImage->green_mask, bmpImage->blue_mask,
3304 rDst,gDst,bDst);
3306 rShift=X11DRV_DIB_MaskToShift(rDst);
3307 gShift=X11DRV_DIB_MaskToShift(gDst);
3308 bShift=X11DRV_DIB_MaskToShift(bDst);
3309 for (h = lines - 1; h >= 0; h--) {
3310 dstpixel=(DWORD*)dstbits;
3311 for (x = 0; x < width; x++) {
3312 COLORREF srcval;
3313 srcval=X11DRV_PALETTE_ToLogical(XGetPixel(bmpImage, x, h));
3314 *dstpixel++=(GetRValue(srcval) << rShift) |
3315 (GetGValue(srcval) << gShift) |
3316 (GetBValue(srcval) << bShift);
3318 dstbits += linebytes;
3321 break;
3325 /***********************************************************************
3326 * X11DRV_DIB_SetImageBits
3328 * Transfer the bits to an X image.
3329 * Helper function for SetDIBits() and SetDIBitsToDevice().
3331 static int X11DRV_DIB_SetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
3333 int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
3334 XImage *bmpImage;
3336 wine_tsx11_lock();
3337 if (descr->image)
3338 bmpImage = descr->image;
3339 else {
3340 bmpImage = XCreateImage( gdi_display, visual, descr->depth, ZPixmap, 0, NULL,
3341 descr->infoWidth, lines, 32, 0 );
3342 bmpImage->data = calloc( lines, bmpImage->bytes_per_line );
3343 if(bmpImage->data == NULL) {
3344 ERR("Out of memory!\n");
3345 XDestroyImage( bmpImage );
3346 wine_tsx11_unlock();
3347 return lines;
3351 TRACE("Dib: depth=%d r=%lx g=%lx b=%lx\n",
3352 descr->infoBpp,descr->rMask,descr->gMask,descr->bMask);
3353 TRACE("Bmp: depth=%d/%d r=%lx g=%lx b=%lx\n",
3354 bmpImage->depth,bmpImage->bits_per_pixel,
3355 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
3357 /* Transfer the pixels */
3358 switch(descr->infoBpp)
3360 case 1:
3361 X11DRV_DIB_SetImageBits_1( descr->lines, descr->bits, descr->infoWidth,
3362 descr->width, descr->xSrc, (int *)(descr->colorMap),
3363 bmpImage, descr->dibpitch );
3364 break;
3365 case 4:
3366 if (descr->compression) {
3367 XGetSubImage( gdi_display, descr->drawable, descr->xDest, descr->yDest,
3368 descr->width, descr->height, AllPlanes, ZPixmap,
3369 bmpImage, descr->xSrc, descr->ySrc );
3371 X11DRV_DIB_SetImageBits_RLE4( descr->lines, descr->bits,
3372 descr->infoWidth, descr->width,
3373 descr->xSrc, (int *)(descr->colorMap),
3374 bmpImage );
3375 } else
3376 X11DRV_DIB_SetImageBits_4( descr->lines, descr->bits,
3377 descr->infoWidth, descr->width,
3378 descr->xSrc, (int*)(descr->colorMap),
3379 bmpImage, descr->dibpitch );
3380 break;
3381 case 8:
3382 if (descr->compression) {
3383 XGetSubImage( gdi_display, descr->drawable, descr->xDest, descr->yDest,
3384 descr->width, descr->height, AllPlanes, ZPixmap,
3385 bmpImage, descr->xSrc, descr->ySrc );
3386 X11DRV_DIB_SetImageBits_RLE8( descr->lines, descr->bits,
3387 descr->infoWidth, descr->width,
3388 descr->xSrc, (int *)(descr->colorMap),
3389 bmpImage );
3390 } else
3391 X11DRV_DIB_SetImageBits_8( descr->lines, descr->bits,
3392 descr->infoWidth, descr->width,
3393 descr->xSrc, (int *)(descr->colorMap),
3394 bmpImage, descr->dibpitch );
3395 break;
3396 case 15:
3397 case 16:
3398 X11DRV_DIB_SetImageBits_16( descr->lines, descr->bits,
3399 descr->infoWidth, descr->width,
3400 descr->xSrc, descr->physDev,
3401 descr->rMask, descr->gMask, descr->bMask,
3402 bmpImage, descr->dibpitch);
3403 break;
3404 case 24:
3405 X11DRV_DIB_SetImageBits_24( descr->lines, descr->bits,
3406 descr->infoWidth, descr->width,
3407 descr->xSrc, descr->physDev,
3408 descr->rMask, descr->gMask, descr->bMask,
3409 bmpImage, descr->dibpitch);
3410 break;
3411 case 32:
3412 X11DRV_DIB_SetImageBits_32( descr->lines, descr->bits,
3413 descr->infoWidth, descr->width,
3414 descr->xSrc, descr->physDev,
3415 descr->rMask, descr->gMask, descr->bMask,
3416 bmpImage, descr->dibpitch);
3417 break;
3418 default:
3419 WARN("(%d): Invalid depth\n", descr->infoBpp );
3420 break;
3423 TRACE("XPutImage(%ld,%p,%p,%d,%d,%d,%d,%d,%d)\n",
3424 descr->drawable, descr->gc, bmpImage,
3425 descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
3426 descr->width, descr->height);
3427 #ifdef HAVE_LIBXXSHM
3428 if (descr->useShm)
3430 XShmPutImage( gdi_display, descr->drawable, descr->gc, bmpImage,
3431 descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
3432 descr->width, descr->height, FALSE );
3433 XSync( gdi_display, 0 );
3435 else
3436 #endif
3437 XPutImage( gdi_display, descr->drawable, descr->gc, bmpImage,
3438 descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
3439 descr->width, descr->height );
3441 if (!descr->image) XDestroyImage( bmpImage );
3442 wine_tsx11_unlock();
3443 return lines;
3446 /***********************************************************************
3447 * X11DRV_DIB_GetImageBits
3449 * Transfer the bits from an X image.
3451 static int X11DRV_DIB_GetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
3453 int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
3454 XImage *bmpImage;
3456 wine_tsx11_lock();
3457 if (descr->image)
3458 bmpImage = descr->image;
3459 else {
3460 bmpImage = XCreateImage( gdi_display, visual, descr->depth, ZPixmap, 0, NULL,
3461 descr->infoWidth, lines, 32, 0 );
3462 bmpImage->data = calloc( lines, bmpImage->bytes_per_line );
3463 if(bmpImage->data == NULL) {
3464 ERR("Out of memory!\n");
3465 XDestroyImage( bmpImage );
3466 wine_tsx11_unlock();
3467 return lines;
3471 #ifdef HAVE_LIBXXSHM
3472 if (descr->useShm)
3474 int saveRed, saveGreen, saveBlue;
3476 TRACE("XShmGetImage(%p, %ld, %p, %d, %d, %ld)\n",
3477 gdi_display, descr->drawable, bmpImage,
3478 descr->xSrc, descr->ySrc, AllPlanes);
3480 /* We must save and restore the bmpImage's masks in order
3481 * to preserve them across the call to XShmGetImage, which
3482 * decides to eleminate them since it doesn't happen to know
3483 * what the format of the image is supposed to be, even though
3484 * we do. */
3485 saveRed = bmpImage->red_mask;
3486 saveBlue= bmpImage->blue_mask;
3487 saveGreen = bmpImage->green_mask;
3489 XShmGetImage( gdi_display, descr->drawable, bmpImage,
3490 descr->xSrc, descr->ySrc, AllPlanes);
3492 bmpImage->red_mask = saveRed;
3493 bmpImage->blue_mask = saveBlue;
3494 bmpImage->green_mask = saveGreen;
3496 else
3497 #endif /* HAVE_LIBXXSHM */
3499 TRACE("XGetSubImage(%p,%ld,%d,%d,%d,%d,%ld,%d,%p,%d,%d)\n",
3500 gdi_display, descr->drawable, descr->xSrc, descr->ySrc, descr->width,
3501 lines, AllPlanes, ZPixmap, bmpImage, descr->xDest, descr->yDest);
3502 XGetSubImage( gdi_display, descr->drawable, descr->xSrc, descr->ySrc,
3503 descr->width, lines, AllPlanes, ZPixmap,
3504 bmpImage, descr->xDest, descr->yDest );
3507 TRACE("Dib: depth=%2d r=%lx g=%lx b=%lx\n",
3508 descr->infoBpp,descr->rMask,descr->gMask,descr->bMask);
3509 TRACE("Bmp: depth=%2d/%2d r=%lx g=%lx b=%lx\n",
3510 bmpImage->depth,bmpImage->bits_per_pixel,
3511 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
3512 /* Transfer the pixels */
3513 switch(descr->infoBpp)
3515 case 1:
3516 X11DRV_DIB_GetImageBits_1( descr->lines,(LPVOID)descr->bits,
3517 descr->infoWidth, descr->width,
3518 descr->colorMap, descr->palentry,
3519 bmpImage, descr->dibpitch );
3520 break;
3522 case 4:
3523 if (descr->compression) {
3524 FIXME("Compression not yet supported!\n");
3525 if(descr->sizeImage < X11DRV_DIB_GetDIBWidthBytes( descr->infoWidth, 4 ) * abs(descr->lines))
3526 break;
3528 X11DRV_DIB_GetImageBits_4( descr->lines,(LPVOID)descr->bits,
3529 descr->infoWidth, descr->width,
3530 descr->colorMap, descr->palentry,
3531 bmpImage, descr->dibpitch );
3532 break;
3533 case 8:
3534 if (descr->compression) {
3535 FIXME("Compression not yet supported!\n");
3536 if(descr->sizeImage < X11DRV_DIB_GetDIBWidthBytes( descr->infoWidth, 8 ) * abs(descr->lines))
3537 break;
3539 X11DRV_DIB_GetImageBits_8( descr->lines, (LPVOID)descr->bits,
3540 descr->infoWidth, descr->width,
3541 descr->colorMap, descr->palentry,
3542 bmpImage, descr->dibpitch );
3543 break;
3544 case 15:
3545 case 16:
3546 X11DRV_DIB_GetImageBits_16( descr->lines, (LPVOID)descr->bits,
3547 descr->infoWidth,descr->width,
3548 descr->palentry,
3549 descr->rMask, descr->gMask, descr->bMask,
3550 bmpImage, descr->dibpitch );
3551 break;
3553 case 24:
3554 X11DRV_DIB_GetImageBits_24( descr->lines, (LPVOID)descr->bits,
3555 descr->infoWidth,descr->width,
3556 descr->palentry,
3557 descr->rMask, descr->gMask, descr->bMask,
3558 bmpImage, descr->dibpitch);
3559 break;
3561 case 32:
3562 X11DRV_DIB_GetImageBits_32( descr->lines, (LPVOID)descr->bits,
3563 descr->infoWidth, descr->width,
3564 descr->palentry,
3565 descr->rMask, descr->gMask, descr->bMask,
3566 bmpImage, descr->dibpitch);
3567 break;
3569 default:
3570 WARN("(%d): Invalid depth\n", descr->infoBpp );
3571 break;
3574 if (!descr->image) XDestroyImage( bmpImage );
3575 wine_tsx11_unlock();
3576 return lines;
3579 /*************************************************************************
3580 * X11DRV_SetDIBitsToDevice
3583 INT X11DRV_SetDIBitsToDevice( X11DRV_PDEVICE *physDev, INT xDest, INT yDest, DWORD cx,
3584 DWORD cy, INT xSrc, INT ySrc,
3585 UINT startscan, UINT lines, LPCVOID bits,
3586 const BITMAPINFO *info, UINT coloruse )
3588 X11DRV_DIB_IMAGEBITS_DESCR descr;
3589 DWORD width;
3590 INT result;
3591 int height;
3592 BOOL top_down;
3593 POINT pt;
3595 if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height,
3596 &descr.infoBpp, &descr.compression ) == -1)
3597 return 0;
3598 top_down = (height < 0);
3599 if (top_down) height = -height;
3601 pt.x = xDest;
3602 pt.y = yDest;
3603 LPtoDP(physDev->hdc, &pt, 1);
3605 if (!lines || (startscan >= height)) return 0;
3606 if (!top_down && startscan + lines > height) lines = height - startscan;
3608 /* make xSrc,ySrc point to the upper-left corner, not the lower-left one,
3609 * and clamp all values to fit inside [startscan,startscan+lines]
3611 if (ySrc + cy <= startscan + lines)
3613 UINT y = startscan + lines - (ySrc + cy);
3614 if (ySrc < startscan) cy -= (startscan - ySrc);
3615 if (!top_down)
3617 /* avoid getting unnecessary lines */
3618 ySrc = 0;
3619 if (y >= lines) return 0;
3620 lines -= y;
3622 else
3624 if (y >= lines) return lines;
3625 ySrc = y; /* need to get all lines in top down mode */
3628 else
3630 if (ySrc >= startscan + lines) return lines;
3631 pt.y += ySrc + cy - (startscan + lines);
3632 cy = startscan + lines - ySrc;
3633 ySrc = 0;
3634 if (cy > lines) cy = lines;
3636 if (xSrc >= width) return lines;
3637 if (xSrc + cx >= width) cx = width - xSrc;
3638 if (!cx || !cy) return lines;
3640 /* Update the pixmap from the DIB section */
3641 X11DRV_LockDIBSection(physDev, DIB_Status_GdiMod, FALSE);
3643 X11DRV_SetupGCForText( physDev ); /* To have the correct colors */
3644 wine_tsx11_lock();
3645 XSetFunction(gdi_display, physDev->gc, X11DRV_XROPfunction[GetROP2(physDev->hdc) - 1]);
3646 wine_tsx11_unlock();
3648 switch (descr.infoBpp)
3650 case 1:
3651 case 4:
3652 case 8:
3653 descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap(
3654 coloruse == DIB_PAL_COLORS ? physDev : NULL, coloruse,
3655 physDev->depth, info, &descr.nColorMap );
3656 if (!descr.colorMap) return 0;
3657 descr.rMask = descr.gMask = descr.bMask = 0;
3658 break;
3659 case 15:
3660 case 16:
3661 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
3662 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x03e0;
3663 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x001f;
3664 descr.colorMap = 0;
3665 break;
3667 case 24:
3668 case 32:
3669 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
3670 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x00ff00;
3671 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x0000ff;
3672 descr.colorMap = 0;
3673 break;
3676 descr.physDev = physDev;
3677 descr.bits = bits;
3678 descr.image = NULL;
3679 descr.palentry = NULL;
3680 descr.lines = top_down ? -lines : lines;
3681 descr.infoWidth = width;
3682 descr.depth = physDev->depth;
3683 descr.drawable = physDev->drawable;
3684 descr.gc = physDev->gc;
3685 descr.xSrc = xSrc;
3686 descr.ySrc = ySrc;
3687 descr.xDest = physDev->org.x + pt.x;
3688 descr.yDest = physDev->org.y + pt.y;
3689 descr.width = cx;
3690 descr.height = cy;
3691 descr.useShm = FALSE;
3692 descr.dibpitch = ((width * descr.infoBpp + 31) &~31) / 8;
3694 result = X11DRV_DIB_SetImageBits( &descr );
3696 if (descr.infoBpp <= 8)
3697 HeapFree(GetProcessHeap(), 0, descr.colorMap);
3699 /* Update the DIBSection of the pixmap */
3700 X11DRV_UnlockDIBSection(physDev, TRUE);
3702 return result;
3705 /***********************************************************************
3706 * SetDIBits (X11DRV.@)
3708 INT X11DRV_SetDIBits( X11DRV_PDEVICE *physDev, HBITMAP hbitmap, UINT startscan,
3709 UINT lines, LPCVOID bits, const BITMAPINFO *info, UINT coloruse )
3711 X11DRV_DIB_IMAGEBITS_DESCR descr;
3712 BITMAPOBJ *bmp;
3713 int height, tmpheight;
3714 INT result;
3716 descr.physDev = physDev;
3718 if (DIB_GetBitmapInfo( &info->bmiHeader, &descr.infoWidth, &height,
3719 &descr.infoBpp, &descr.compression ) == -1)
3720 return 0;
3722 tmpheight = height;
3723 if (height < 0) height = -height;
3724 if (!lines || (startscan >= height))
3725 return 0;
3727 if (!(bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC ))) return 0;
3729 if (startscan + lines > height) lines = height - startscan;
3731 switch (descr.infoBpp)
3733 case 1:
3734 case 4:
3735 case 8:
3736 descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap(
3737 coloruse == DIB_PAL_COLORS ? descr.physDev : NULL, coloruse,
3738 bmp->bitmap.bmBitsPixel,
3739 info, &descr.nColorMap );
3740 if (!descr.colorMap)
3742 GDI_ReleaseObj( hbitmap );
3743 return 0;
3745 descr.rMask = descr.gMask = descr.bMask = 0;
3746 break;
3747 case 15:
3748 case 16:
3749 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
3750 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x03e0;
3751 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x001f;
3752 descr.colorMap = 0;
3753 break;
3755 case 24:
3756 case 32:
3757 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
3758 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x00ff00;
3759 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x0000ff;
3760 descr.colorMap = 0;
3761 break;
3763 default: break;
3766 descr.bits = bits;
3767 descr.image = NULL;
3768 descr.palentry = NULL;
3769 descr.lines = tmpheight >= 0 ? lines : -lines;
3770 descr.depth = bmp->bitmap.bmBitsPixel;
3771 descr.drawable = (Pixmap)bmp->physBitmap;
3772 descr.gc = BITMAP_GC(bmp);
3773 descr.xSrc = 0;
3774 descr.ySrc = 0;
3775 descr.xDest = 0;
3776 descr.yDest = height - startscan - lines;
3777 descr.width = bmp->bitmap.bmWidth;
3778 descr.height = lines;
3779 descr.useShm = FALSE;
3780 descr.dibpitch = ((descr.infoWidth * descr.infoBpp + 31) &~31) / 8;
3781 X11DRV_DIB_Lock(bmp, DIB_Status_GdiMod, FALSE);
3782 result = X11DRV_DIB_SetImageBits( &descr );
3783 X11DRV_DIB_Unlock(bmp, TRUE);
3785 if (descr.colorMap) HeapFree(GetProcessHeap(), 0, descr.colorMap);
3787 GDI_ReleaseObj( hbitmap );
3788 return result;
3791 /***********************************************************************
3792 * GetDIBits (X11DRV.@)
3794 INT X11DRV_GetDIBits( X11DRV_PDEVICE *physDev, HBITMAP hbitmap, UINT startscan, UINT lines,
3795 LPVOID bits, BITMAPINFO *info, UINT coloruse )
3797 X11DRV_DIBSECTION *dib;
3798 X11DRV_DIB_IMAGEBITS_DESCR descr;
3799 PALETTEENTRY palette[256];
3800 BITMAPOBJ *bmp;
3801 int height;
3803 GetPaletteEntries( GetCurrentObject( physDev->hdc, OBJ_PAL ), 0, 256, palette );
3805 if (!(bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC ))) return 0;
3807 dib = (X11DRV_DIBSECTION *) bmp->dib;
3809 TRACE("%u scanlines of (%i,%i) -> (%i,%i) starting from %u\n",
3810 lines, bmp->bitmap.bmWidth, bmp->bitmap.bmHeight,
3811 (int)info->bmiHeader.biWidth, (int)info->bmiHeader.biHeight,
3812 startscan );
3814 if( lines > bmp->bitmap.bmHeight ) lines = bmp->bitmap.bmHeight;
3816 height = info->bmiHeader.biHeight;
3817 if (height < 0) height = -height;
3818 if( lines > height ) lines = height;
3819 /* Top-down images have a negative biHeight, the scanlines of theses images
3820 * were inverted in X11DRV_DIB_GetImageBits_xx
3821 * To prevent this we simply change the sign of lines
3822 * (the number of scan lines to copy).
3823 * Negative lines are correctly handled by X11DRV_DIB_GetImageBits_xx.
3825 if( info->bmiHeader.biHeight < 0 && lines > 0) lines = -lines;
3827 if( startscan >= bmp->bitmap.bmHeight )
3829 lines = 0;
3830 goto done;
3833 if (DIB_GetBitmapInfo( &info->bmiHeader, &descr.infoWidth, &descr.lines,
3834 &descr.infoBpp, &descr.compression ) == -1)
3836 lines = 0;
3837 goto done;
3840 descr.colorMap = NULL;
3842 switch (descr.infoBpp)
3844 case 1:
3845 case 4:
3846 case 8:
3847 descr.rMask= descr.gMask = descr.bMask = 0;
3848 if(coloruse == DIB_RGB_COLORS)
3849 descr.colorMap = info->bmiColors;
3850 else {
3851 int num_colors = 1 << descr.infoBpp, i;
3852 RGBQUAD *rgb;
3853 COLORREF colref;
3854 WORD *index = (WORD*)info->bmiColors;
3855 descr.colorMap = rgb = HeapAlloc(GetProcessHeap(), 0, num_colors * sizeof(RGBQUAD));
3856 for(i = 0; i < num_colors; i++, rgb++, index++) {
3857 colref = X11DRV_PALETTE_ToLogical(X11DRV_PALETTE_ToPhysical(physDev, PALETTEINDEX(*index)));
3858 rgb->rgbRed = GetRValue(colref);
3859 rgb->rgbGreen = GetGValue(colref);
3860 rgb->rgbBlue = GetBValue(colref);
3861 rgb->rgbReserved = 0;
3864 break;
3865 case 15:
3866 case 16:
3867 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
3868 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x03e0;
3869 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x001f;
3870 break;
3871 case 24:
3872 case 32:
3873 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
3874 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x00ff00;
3875 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x0000ff;
3876 break;
3879 descr.physDev = physDev;
3880 descr.palentry = palette;
3881 descr.bits = bits;
3882 descr.image = NULL;
3883 descr.lines = lines;
3884 descr.depth = bmp->bitmap.bmBitsPixel;
3885 descr.drawable = (Pixmap)bmp->physBitmap;
3886 descr.gc = BITMAP_GC(bmp);
3887 descr.width = bmp->bitmap.bmWidth;
3888 descr.height = bmp->bitmap.bmHeight;
3889 descr.xDest = 0;
3890 descr.yDest = 0;
3891 descr.xSrc = 0;
3892 descr.sizeImage = info->bmiHeader.biSizeImage;
3894 if (descr.lines > 0)
3896 descr.ySrc = (descr.height-1) - (startscan + (lines-1));
3898 else
3900 descr.ySrc = startscan;
3902 #ifdef HAVE_LIBXXSHM
3903 descr.useShm = dib ? (dib->shminfo.shmid != -1) : FALSE;
3904 #else
3905 descr.useShm = FALSE;
3906 #endif
3907 descr.dibpitch = dib ? (dib->dibSection.dsBm.bmWidthBytes)
3908 : (((descr.infoWidth * descr.infoBpp + 31) &~31) / 8);
3910 X11DRV_DIB_Lock(bmp, DIB_Status_GdiMod, FALSE);
3911 X11DRV_DIB_GetImageBits( &descr );
3912 X11DRV_DIB_Unlock(bmp, TRUE);
3914 if(info->bmiHeader.biSizeImage == 0) /* Fill in biSizeImage */
3915 info->bmiHeader.biSizeImage = X11DRV_DIB_GetDIBWidthBytes( info->bmiHeader.biWidth,
3916 info->bmiHeader.biBitCount )
3917 * abs( info->bmiHeader.biHeight );
3919 if (descr.compression == BI_BITFIELDS)
3921 *(DWORD *)info->bmiColors = descr.rMask;
3922 *((DWORD *)info->bmiColors+1) = descr.gMask;
3923 *((DWORD *)info->bmiColors+2) = descr.bMask;
3925 else
3927 /* if RLE or JPEG compression were supported,
3928 * this line would be invalid. */
3929 info->bmiHeader.biCompression = 0;
3932 if(descr.colorMap && descr.colorMap != info->bmiColors)
3933 HeapFree(GetProcessHeap(), 0, descr.colorMap);
3934 done:
3935 GDI_ReleaseObj( hbitmap );
3936 return lines;
3939 /***********************************************************************
3940 * DIB_DoProtectDIBSection
3942 static void X11DRV_DIB_DoProtectDIBSection( BITMAPOBJ *bmp, DWORD new_prot )
3944 DWORD old_prot;
3945 INT totalSize;
3946 DIBSECTION *dib = bmp->dib;
3947 INT effHeight = dib->dsBm.bmHeight >= 0? dib->dsBm.bmHeight
3948 : -dib->dsBm.bmHeight;
3950 /* use the biSizeImage data as the memory size only if we're dealing with a
3951 compressed image where the value is set. Otherwise, calculate based on
3952 width * height */
3953 if (dib->dsBmih.biSizeImage &&
3954 (dib->dsBmih.biCompression == BI_RLE4 || dib->dsBmih.biCompression == BI_RLE8))
3955 totalSize = dib->dsBmih.biSizeImage;
3956 else
3957 totalSize = dib->dsBm.bmWidthBytes * effHeight;
3959 VirtualProtect(dib->dsBm.bmBits, totalSize, new_prot, &old_prot);
3960 TRACE("Changed protection from %ld to %ld\n", old_prot, new_prot);
3963 /***********************************************************************
3964 * X11DRV_DIB_DoUpdateDIBSection
3966 static void X11DRV_DIB_DoCopyDIBSection(BITMAPOBJ *bmp, BOOL toDIB,
3967 void *colorMap, int nColorMap,
3968 Drawable dest,
3969 DWORD xSrc, DWORD ySrc,
3970 DWORD xDest, DWORD yDest,
3971 DWORD width, DWORD height)
3973 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
3974 X11DRV_DIB_IMAGEBITS_DESCR descr;
3976 if (DIB_GetBitmapInfo( &dib->dibSection.dsBmih, &descr.infoWidth, &descr.lines,
3977 &descr.infoBpp, &descr.compression ) == -1)
3978 return;
3980 descr.physDev = NULL;
3981 descr.palentry = NULL;
3982 descr.image = dib->image;
3983 descr.colorMap = colorMap;
3984 descr.nColorMap = nColorMap;
3985 descr.bits = dib->dibSection.dsBm.bmBits;
3986 descr.depth = bmp->bitmap.bmBitsPixel;
3988 switch (descr.infoBpp)
3990 case 1:
3991 case 4:
3992 case 8:
3993 descr.rMask = descr.gMask = descr.bMask = 0;
3994 break;
3995 case 15:
3996 case 16:
3997 descr.rMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[0] : 0x7c00;
3998 descr.gMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[1] : 0x03e0;
3999 descr.bMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[2] : 0x001f;
4000 break;
4002 case 24:
4003 case 32:
4004 descr.rMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[0] : 0xff0000;
4005 descr.gMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[1] : 0x00ff00;
4006 descr.bMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[2] : 0x0000ff;
4007 break;
4010 /* Hack for now */
4011 descr.drawable = dest;
4012 descr.gc = BITMAP_GC(bmp);
4013 descr.xSrc = xSrc;
4014 descr.ySrc = ySrc;
4015 descr.xDest = xDest;
4016 descr.yDest = yDest;
4017 descr.width = width;
4018 descr.height = height;
4019 descr.sizeImage = 0;
4021 #ifdef HAVE_LIBXXSHM
4022 descr.useShm = (dib->shminfo.shmid != -1);
4023 #else
4024 descr.useShm = FALSE;
4025 #endif
4026 descr.dibpitch = dib->dibSection.dsBm.bmWidthBytes;
4028 if (toDIB)
4030 TRACE("Copying from Pixmap to DIB bits\n");
4031 X11DRV_DIB_GetImageBits( &descr );
4033 else
4035 TRACE("Copying from DIB bits to Pixmap\n");
4036 X11DRV_DIB_SetImageBits( &descr );
4040 /***********************************************************************
4041 * X11DRV_DIB_CopyDIBSection
4043 void X11DRV_DIB_CopyDIBSection(X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE *physDevDst,
4044 DWORD xSrc, DWORD ySrc, DWORD xDest, DWORD yDest,
4045 DWORD width, DWORD height)
4047 BITMAPOBJ *bmp;
4048 HBITMAP hBitmap;
4049 int nColorMap = 0, *colorMap = NULL, aColorMap = FALSE;
4051 TRACE("(%p,%p,%ld,%ld,%ld,%ld,%ld,%ld)\n", physDevSrc->hdc, physDevDst->hdc,
4052 xSrc, ySrc, xDest, yDest, width, height);
4053 /* this function is meant as an optimization for BitBlt,
4054 * not to be called otherwise */
4055 if (GetObjectType( physDevSrc->hdc ) != OBJ_MEMDC) {
4056 ERR("called for non-memory source DC!?\n");
4057 return;
4060 hBitmap = GetCurrentObject( physDevSrc->hdc, OBJ_BITMAP );
4061 bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBitmap, BITMAP_MAGIC );
4062 if (!(bmp && bmp->dib)) {
4063 ERR("called for non-DIBSection!?\n");
4064 GDI_ReleaseObj( hBitmap );
4065 return;
4067 /* while BitBlt should already have made sure we only get
4068 * positive values, we should check for oversize values */
4069 if ((xSrc < bmp->bitmap.bmWidth) &&
4070 (ySrc < bmp->bitmap.bmHeight)) {
4071 if (xSrc + width > bmp->bitmap.bmWidth)
4072 width = bmp->bitmap.bmWidth - xSrc;
4073 if (ySrc + height > bmp->bitmap.bmHeight)
4074 height = bmp->bitmap.bmHeight - ySrc;
4075 /* if the source bitmap is 8bpp or less, we're supposed to use the
4076 * DC's palette for color conversion (not the DIB color table) */
4077 if (bmp->dib->dsBm.bmBitsPixel <= 8) {
4078 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
4079 HPALETTE hPalette = GetCurrentObject( physDevSrc->hdc, OBJ_PAL );
4080 if (!hPalette || (hPalette == GetStockObject(DEFAULT_PALETTE))) {
4081 /* HACK: no palette has been set in the source DC,
4082 * use the DIB colormap instead - this is necessary in some
4083 * cases since we need to do depth conversion in some places
4084 * where real Windows can just copy data straight over */
4085 colorMap = dib->colorMap;
4086 nColorMap = dib->nColorMap;
4087 } else {
4088 colorMap = X11DRV_DIB_BuildColorMap( physDevSrc, (WORD)-1,
4089 bmp->dib->dsBm.bmBitsPixel,
4090 (BITMAPINFO*)&(bmp->dib->dsBmih),
4091 &nColorMap );
4092 if (colorMap) aColorMap = TRUE;
4095 /* perform the copy */
4096 X11DRV_DIB_DoCopyDIBSection(bmp, FALSE, colorMap, nColorMap,
4097 physDevDst->drawable, xSrc, ySrc,
4098 physDevDst->org.x + xDest, physDevDst->org.y + yDest,
4099 width, height);
4100 /* free color mapping */
4101 if (aColorMap)
4102 HeapFree(GetProcessHeap(), 0, colorMap);
4104 GDI_ReleaseObj( hBitmap );
4107 /***********************************************************************
4108 * X11DRV_DIB_DoUpdateDIBSection
4110 static void X11DRV_DIB_DoUpdateDIBSection(BITMAPOBJ *bmp, BOOL toDIB)
4112 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
4113 X11DRV_DIB_DoCopyDIBSection(bmp, toDIB, dib->colorMap, dib->nColorMap,
4114 (Drawable)bmp->physBitmap, 0, 0, 0, 0,
4115 bmp->bitmap.bmWidth, bmp->bitmap.bmHeight);
4118 /***********************************************************************
4119 * X11DRV_DIB_FaultHandler
4121 static BOOL X11DRV_DIB_FaultHandler( LPVOID res, LPCVOID addr )
4123 BITMAPOBJ *bmp;
4124 INT state;
4126 bmp = (BITMAPOBJ *)GDI_GetObjPtr( (HBITMAP)res, BITMAP_MAGIC );
4127 if (!bmp) return FALSE;
4129 state = X11DRV_DIB_Lock(bmp, DIB_Status_None, FALSE);
4130 if (state != DIB_Status_InSync) {
4131 /* no way to tell whether app needs read or write yet,
4132 * try read first */
4133 X11DRV_DIB_Coerce(bmp, DIB_Status_InSync, FALSE);
4134 } else {
4135 /* hm, apparently the app must have write access */
4136 X11DRV_DIB_Coerce(bmp, DIB_Status_AppMod, FALSE);
4138 X11DRV_DIB_Unlock(bmp, TRUE);
4140 GDI_ReleaseObj( (HBITMAP)res );
4141 return TRUE;
4144 /***********************************************************************
4145 * X11DRV_DIB_Coerce
4147 INT X11DRV_DIB_Coerce(BITMAPOBJ *bmp, INT req, BOOL lossy)
4149 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
4150 INT ret = DIB_Status_None;
4152 if (dib) {
4153 EnterCriticalSection(&(dib->lock));
4154 ret = dib->status;
4155 switch (req) {
4156 case DIB_Status_GdiMod:
4157 /* GDI access - request to draw on pixmap */
4158 switch (dib->status)
4160 default:
4161 case DIB_Status_None:
4162 dib->p_status = DIB_Status_GdiMod;
4163 X11DRV_DIB_DoUpdateDIBSection( bmp, FALSE );
4164 break;
4166 case DIB_Status_GdiMod:
4167 TRACE("GdiMod requested in status GdiMod\n" );
4168 break;
4170 case DIB_Status_InSync:
4171 TRACE("GdiMod requested in status InSync\n" );
4172 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
4173 dib->status = DIB_Status_GdiMod;
4174 dib->p_status = DIB_Status_InSync;
4175 break;
4177 case DIB_Status_AuxMod:
4178 TRACE("GdiMod requested in status AuxMod\n" );
4179 if (lossy) dib->status = DIB_Status_GdiMod;
4180 else (*dib->copy_aux)(dib->aux_ctx, DIB_Status_GdiMod);
4181 dib->p_status = DIB_Status_AuxMod;
4182 if (dib->status != DIB_Status_AppMod) {
4183 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
4184 break;
4186 /* fall through if copy_aux() had to change to AppMod state */
4188 case DIB_Status_AppMod:
4189 TRACE("GdiMod requested in status AppMod\n" );
4190 if (!lossy) {
4191 /* make it readonly to avoid app changing data while we copy */
4192 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
4193 X11DRV_DIB_DoUpdateDIBSection( bmp, FALSE );
4195 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
4196 dib->p_status = DIB_Status_AppMod;
4197 dib->status = DIB_Status_GdiMod;
4198 break;
4200 break;
4202 case DIB_Status_InSync:
4203 /* App access - request access to read DIB surface */
4204 /* (typically called from signal handler) */
4205 switch (dib->status)
4207 default:
4208 case DIB_Status_None:
4209 /* shouldn't happen from signal handler */
4210 break;
4212 case DIB_Status_AuxMod:
4213 TRACE("InSync requested in status AuxMod\n" );
4214 if (lossy) dib->status = DIB_Status_InSync;
4215 else {
4216 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
4217 (*dib->copy_aux)(dib->aux_ctx, DIB_Status_InSync);
4219 if (dib->status != DIB_Status_GdiMod) {
4220 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
4221 break;
4223 /* fall through if copy_aux() had to change to GdiMod state */
4225 case DIB_Status_GdiMod:
4226 TRACE("InSync requested in status GdiMod\n" );
4227 if (!lossy) {
4228 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
4229 X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
4231 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
4232 dib->status = DIB_Status_InSync;
4233 break;
4235 case DIB_Status_InSync:
4236 TRACE("InSync requested in status InSync\n" );
4237 /* shouldn't happen from signal handler */
4238 break;
4240 case DIB_Status_AppMod:
4241 TRACE("InSync requested in status AppMod\n" );
4242 /* no reason to do anything here, and this
4243 * shouldn't happen from signal handler */
4244 break;
4246 break;
4248 case DIB_Status_AppMod:
4249 /* App access - request access to write DIB surface */
4250 /* (typically called from signal handler) */
4251 switch (dib->status)
4253 default:
4254 case DIB_Status_None:
4255 /* shouldn't happen from signal handler */
4256 break;
4258 case DIB_Status_AuxMod:
4259 TRACE("AppMod requested in status AuxMod\n" );
4260 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
4261 if (lossy) dib->status = DIB_Status_AppMod;
4262 else (*dib->copy_aux)(dib->aux_ctx, DIB_Status_AppMod);
4263 if (dib->status != DIB_Status_GdiMod)
4264 break;
4265 /* fall through if copy_aux() had to change to GdiMod state */
4267 case DIB_Status_GdiMod:
4268 TRACE("AppMod requested in status GdiMod\n" );
4269 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
4270 if (!lossy) X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
4271 dib->status = DIB_Status_AppMod;
4272 break;
4274 case DIB_Status_InSync:
4275 TRACE("AppMod requested in status InSync\n" );
4276 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
4277 dib->status = DIB_Status_AppMod;
4278 break;
4280 case DIB_Status_AppMod:
4281 TRACE("AppMod requested in status AppMod\n" );
4282 /* shouldn't happen from signal handler */
4283 break;
4285 break;
4287 case DIB_Status_AuxMod:
4288 if (dib->status == DIB_Status_None) {
4289 dib->p_status = req;
4290 } else {
4291 if (dib->status != DIB_Status_AuxMod)
4292 dib->p_status = dib->status;
4293 dib->status = DIB_Status_AuxMod;
4295 break;
4296 /* it is up to the caller to do the copy/conversion, probably
4297 * using the return value to decide where to copy from */
4299 LeaveCriticalSection(&(dib->lock));
4301 return ret;
4304 /***********************************************************************
4305 * X11DRV_DIB_Lock
4307 INT X11DRV_DIB_Lock(BITMAPOBJ *bmp, INT req, BOOL lossy)
4309 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
4310 INT ret = DIB_Status_None;
4312 if (dib) {
4313 TRACE("Locking %p from thread %04lx\n", bmp, GetCurrentThreadId());
4314 EnterCriticalSection(&(dib->lock));
4315 ret = dib->status;
4316 if (req != DIB_Status_None)
4317 X11DRV_DIB_Coerce(bmp, req, lossy);
4319 return ret;
4322 /***********************************************************************
4323 * X11DRV_DIB_Unlock
4325 void X11DRV_DIB_Unlock(BITMAPOBJ *bmp, BOOL commit)
4327 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
4329 if (dib) {
4330 switch (dib->status)
4332 default:
4333 case DIB_Status_None:
4334 /* in case anyone is wondering, this is the "signal handler doesn't
4335 * work" case, where we always have to be ready for app access */
4336 if (commit) {
4337 switch (dib->p_status)
4339 case DIB_Status_AuxMod:
4340 TRACE("Unlocking and syncing from AuxMod\n" );
4341 (*dib->copy_aux)(dib->aux_ctx, DIB_Status_AppMod);
4342 if (dib->status != DIB_Status_None) {
4343 dib->p_status = dib->status;
4344 dib->status = DIB_Status_None;
4346 if (dib->p_status != DIB_Status_GdiMod)
4347 break;
4348 /* fall through if copy_aux() had to change to GdiMod state */
4350 case DIB_Status_GdiMod:
4351 TRACE("Unlocking and syncing from GdiMod\n" );
4352 X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
4353 break;
4355 default:
4356 TRACE("Unlocking without needing to sync\n" );
4357 break;
4360 else TRACE("Unlocking with no changes\n");
4361 dib->p_status = DIB_Status_None;
4362 break;
4364 case DIB_Status_GdiMod:
4365 TRACE("Unlocking in status GdiMod\n" );
4366 /* DIB was protected in Coerce */
4367 if (!commit) {
4368 /* no commit, revert to InSync if applicable */
4369 if ((dib->p_status == DIB_Status_InSync) ||
4370 (dib->p_status == DIB_Status_AppMod)) {
4371 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
4372 dib->status = DIB_Status_InSync;
4375 break;
4377 case DIB_Status_InSync:
4378 TRACE("Unlocking in status InSync\n" );
4379 /* DIB was already protected in Coerce */
4380 break;
4382 case DIB_Status_AppMod:
4383 TRACE("Unlocking in status AppMod\n" );
4384 /* DIB was already protected in Coerce */
4385 /* this case is ordinary only called from the signal handler,
4386 * so we don't bother to check for !commit */
4387 break;
4389 case DIB_Status_AuxMod:
4390 TRACE("Unlocking in status AuxMod\n" );
4391 if (commit) {
4392 /* DIB may need protection now */
4393 if ((dib->p_status == DIB_Status_InSync) ||
4394 (dib->p_status == DIB_Status_AppMod))
4395 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
4396 } else {
4397 /* no commit, revert to previous state */
4398 if (dib->p_status != DIB_Status_None)
4399 dib->status = dib->p_status;
4400 /* no protections changed */
4402 dib->p_status = DIB_Status_None;
4403 break;
4405 LeaveCriticalSection(&(dib->lock));
4406 TRACE("Unlocked %p\n", bmp);
4410 /***********************************************************************
4411 * X11DRV_CoerceDIBSection2
4413 INT X11DRV_CoerceDIBSection2(HBITMAP hBmp, INT req, BOOL lossy)
4415 BITMAPOBJ *bmp;
4416 INT ret;
4418 bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
4419 if (!bmp) return DIB_Status_None;
4420 ret = X11DRV_DIB_Coerce(bmp, req, lossy);
4421 GDI_ReleaseObj( hBmp );
4422 return ret;
4425 /***********************************************************************
4426 * X11DRV_LockDIBSection2
4428 INT X11DRV_LockDIBSection2(HBITMAP hBmp, INT req, BOOL lossy)
4430 BITMAPOBJ *bmp;
4431 INT ret;
4433 bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
4434 if (!bmp) return DIB_Status_None;
4435 ret = X11DRV_DIB_Lock(bmp, req, lossy);
4436 GDI_ReleaseObj( hBmp );
4437 return ret;
4440 /***********************************************************************
4441 * X11DRV_UnlockDIBSection2
4443 void X11DRV_UnlockDIBSection2(HBITMAP hBmp, BOOL commit)
4445 BITMAPOBJ *bmp;
4447 bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
4448 if (!bmp) return;
4449 X11DRV_DIB_Unlock(bmp, commit);
4450 GDI_ReleaseObj( hBmp );
4453 /***********************************************************************
4454 * X11DRV_CoerceDIBSection
4456 INT X11DRV_CoerceDIBSection(X11DRV_PDEVICE *physDev, INT req, BOOL lossy)
4458 if (!physDev) return DIB_Status_None;
4459 return X11DRV_CoerceDIBSection2( GetCurrentObject( physDev->hdc, OBJ_BITMAP ), req, lossy );
4462 /***********************************************************************
4463 * X11DRV_LockDIBSection
4465 INT X11DRV_LockDIBSection(X11DRV_PDEVICE *physDev, INT req, BOOL lossy)
4467 if (!physDev) return DIB_Status_None;
4468 if (GetObjectType( physDev->hdc ) != OBJ_MEMDC) return DIB_Status_None;
4470 return X11DRV_LockDIBSection2( GetCurrentObject( physDev->hdc, OBJ_BITMAP ), req, lossy );
4473 /***********************************************************************
4474 * X11DRV_UnlockDIBSection
4476 void X11DRV_UnlockDIBSection(X11DRV_PDEVICE *physDev, BOOL commit)
4478 if (!physDev) return;
4479 if (GetObjectType( physDev->hdc ) != OBJ_MEMDC) return;
4481 X11DRV_UnlockDIBSection2( GetCurrentObject( physDev->hdc, OBJ_BITMAP ), commit );
4485 #ifdef HAVE_LIBXXSHM
4486 /***********************************************************************
4487 * X11DRV_XShmErrorHandler
4490 static int XShmErrorHandler( Display *dpy, XErrorEvent *event, void *arg )
4492 return 1; /* FIXME: should check event contents */
4495 /***********************************************************************
4496 * X11DRV_XShmCreateImage
4499 static XImage *X11DRV_XShmCreateImage( int width, int height, int bpp,
4500 XShmSegmentInfo* shminfo)
4502 XImage *image;
4504 image = XShmCreateImage(gdi_display, visual, bpp, ZPixmap, NULL, shminfo, width, height);
4505 if (image)
4507 shminfo->shmid = shmget(IPC_PRIVATE, image->bytes_per_line * height,
4508 IPC_CREAT|0700);
4509 if( shminfo->shmid != -1 )
4511 shminfo->shmaddr = image->data = shmat(shminfo->shmid, 0, 0);
4512 if( shminfo->shmaddr != (char*)-1 )
4514 BOOL ok;
4516 shminfo->readOnly = FALSE;
4517 X11DRV_expect_error( gdi_display, XShmErrorHandler, NULL );
4518 ok = (XShmAttach( gdi_display, shminfo ) != 0);
4519 XSync( gdi_display, False );
4520 if (X11DRV_check_error()) ok = FALSE;
4521 if (ok)
4523 shmctl(shminfo->shmid, IPC_RMID, 0);
4524 return image; /* Success! */
4526 /* An error occurred */
4527 shmdt(shminfo->shmaddr);
4529 shmctl(shminfo->shmid, IPC_RMID, 0);
4531 XFlush(gdi_display);
4532 XDestroyImage(image);
4533 image = NULL;
4535 return image;
4537 #endif /* HAVE_LIBXXSHM */
4540 /***********************************************************************
4541 * X11DRV_DIB_CreateDIBSection
4543 HBITMAP X11DRV_DIB_CreateDIBSection(
4544 X11DRV_PDEVICE *physDev, const BITMAPINFO *bmi, UINT usage,
4545 VOID **bits, HANDLE section,
4546 DWORD offset, DWORD ovr_pitch)
4548 HBITMAP res = 0;
4549 BITMAPOBJ *bmp = NULL;
4550 X11DRV_DIBSECTION *dib = NULL;
4551 int *colorMap = NULL;
4552 int nColorMap;
4554 /* Fill BITMAP32 structure with DIB data */
4555 const BITMAPINFOHEADER *bi = &bmi->bmiHeader;
4556 INT effHeight, totalSize;
4557 BITMAP bm;
4558 LPVOID mapBits = NULL;
4560 TRACE("format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
4561 bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
4562 bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
4564 effHeight = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
4565 bm.bmType = 0;
4566 bm.bmWidth = bi->biWidth;
4567 bm.bmHeight = effHeight;
4568 bm.bmWidthBytes = ovr_pitch ? ovr_pitch : X11DRV_DIB_GetDIBWidthBytes(bm.bmWidth, bi->biBitCount);
4569 bm.bmPlanes = bi->biPlanes;
4570 bm.bmBitsPixel = bi->biBitCount;
4571 bm.bmBits = NULL;
4573 /* Get storage location for DIB bits. Only use biSizeImage if it's valid and
4574 we're dealing with a compressed bitmap. Otherwise, use width * height. */
4575 if (bi->biSizeImage && (bi->biCompression == BI_RLE4 || bi->biCompression == BI_RLE8))
4576 totalSize = bi->biSizeImage;
4577 else
4578 totalSize = bm.bmWidthBytes * effHeight;
4580 if (section)
4582 SYSTEM_INFO SystemInfo;
4583 DWORD mapOffset;
4584 INT mapSize;
4586 GetSystemInfo( &SystemInfo );
4587 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
4588 mapSize = totalSize + (offset - mapOffset);
4589 mapBits = MapViewOfFile( section,
4590 FILE_MAP_ALL_ACCESS,
4592 mapOffset,
4593 mapSize );
4594 bm.bmBits = (char *)mapBits + (offset - mapOffset);
4596 else if (ovr_pitch && offset)
4597 bm.bmBits = (LPVOID) offset;
4598 else {
4599 offset = 0;
4600 bm.bmBits = VirtualAlloc(NULL, totalSize,
4601 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
4604 /* Create Color Map */
4605 if (bm.bmBits && bm.bmBitsPixel <= 8)
4606 colorMap = X11DRV_DIB_BuildColorMap( usage == DIB_PAL_COLORS? physDev : NULL,
4607 usage, bm.bmBitsPixel, bmi, &nColorMap );
4609 /* Allocate Memory for DIB and fill structure */
4610 if (bm.bmBits)
4611 dib = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(X11DRV_DIBSECTION));
4612 if (dib)
4614 dib->dibSection.dsBm = bm;
4615 dib->dibSection.dsBmih = *bi;
4616 dib->dibSection.dsBmih.biSizeImage = totalSize;
4618 /* Set dsBitfields values */
4619 if ( usage == DIB_PAL_COLORS || bi->biBitCount <= 8)
4621 dib->dibSection.dsBitfields[0] = dib->dibSection.dsBitfields[1] = dib->dibSection.dsBitfields[2] = 0;
4623 else switch( bi->biBitCount )
4625 case 15:
4626 case 16:
4627 dib->dibSection.dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors : 0x7c00;
4628 dib->dibSection.dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0x03e0;
4629 dib->dibSection.dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0x001f;
4630 break;
4632 case 24:
4633 case 32:
4634 dib->dibSection.dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors : 0xff0000;
4635 dib->dibSection.dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0x00ff00;
4636 dib->dibSection.dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0x0000ff;
4637 break;
4639 dib->dibSection.dshSection = section;
4640 dib->dibSection.dsOffset = offset;
4642 dib->status = DIB_Status_None;
4643 dib->nColorMap = nColorMap;
4644 dib->colorMap = colorMap;
4647 /* Create Device Dependent Bitmap and add DIB pointer */
4648 if (dib)
4650 res = CreateDIBitmap(physDev->hdc, bi, 0, NULL, bmi, usage);
4651 if (res)
4653 bmp = (BITMAPOBJ *) GDI_GetObjPtr(res, BITMAP_MAGIC);
4654 if (bmp) bmp->dib = (DIBSECTION *) dib;
4658 /* Create XImage */
4659 if (dib && bmp)
4661 wine_tsx11_lock();
4662 #ifdef HAVE_LIBXXSHM
4663 if (XShmQueryExtension(gdi_display) &&
4664 (dib->image = X11DRV_XShmCreateImage( bm.bmWidth, effHeight,
4665 bmp->bitmap.bmBitsPixel, &dib->shminfo )) )
4667 ; /* Created Image */
4668 } else {
4669 dib->image = X11DRV_DIB_CreateXImage( bm.bmWidth, effHeight, bmp->bitmap.bmBitsPixel );
4670 dib->shminfo.shmid = -1;
4672 #else
4673 dib->image = X11DRV_DIB_CreateXImage( bm.bmWidth, effHeight, bmp->bitmap.bmBitsPixel );
4674 #endif
4675 wine_tsx11_unlock();
4678 /* Clean up in case of errors */
4679 if (!res || !bmp || !dib || !bm.bmBits || (bm.bmBitsPixel <= 8 && !colorMap))
4681 TRACE("got an error res=%p, bmp=%p, dib=%p, bm.bmBits=%p\n",
4682 res, bmp, dib, bm.bmBits);
4683 if (bm.bmBits)
4685 if (section)
4686 UnmapViewOfFile(mapBits), bm.bmBits = NULL;
4687 else if (!offset)
4688 VirtualFree(bm.bmBits, 0L, MEM_RELEASE), bm.bmBits = NULL;
4691 if (dib && dib->image) { XDestroyImage(dib->image); dib->image = NULL; }
4692 if (colorMap) { HeapFree(GetProcessHeap(), 0, colorMap); colorMap = NULL; }
4693 if (dib) { HeapFree(GetProcessHeap(), 0, dib); dib = NULL; }
4694 if (bmp) { GDI_ReleaseObj(res); bmp = NULL; }
4695 if (res) { DeleteObject(res); res = 0; }
4697 else if (bm.bmBits)
4699 extern BOOL VIRTUAL_SetFaultHandler(LPCVOID addr, BOOL (*proc)(LPVOID, LPCVOID), LPVOID arg);
4700 /* Install fault handler, if possible */
4701 InitializeCriticalSection(&(dib->lock));
4702 if (VIRTUAL_SetFaultHandler(bm.bmBits, X11DRV_DIB_FaultHandler, (LPVOID)res))
4704 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
4705 if (dib) dib->status = DIB_Status_AppMod;
4709 /* Return BITMAP handle and storage location */
4710 if (bmp) GDI_ReleaseObj(res);
4711 if (bm.bmBits && bits) *bits = bm.bmBits;
4712 return res;
4715 /***********************************************************************
4716 * X11DRV_DIB_DeleteDIBSection
4718 void X11DRV_DIB_DeleteDIBSection(BITMAPOBJ *bmp)
4720 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
4722 if (dib->image)
4724 wine_tsx11_lock();
4725 #ifdef HAVE_LIBXXSHM
4726 if (dib->shminfo.shmid != -1)
4728 XShmDetach (gdi_display, &(dib->shminfo));
4729 XDestroyImage (dib->image);
4730 shmdt (dib->shminfo.shmaddr);
4731 dib->shminfo.shmid = -1;
4733 else
4734 #endif
4735 XDestroyImage( dib->image );
4736 wine_tsx11_unlock();
4739 if (dib->colorMap)
4740 HeapFree(GetProcessHeap(), 0, dib->colorMap);
4742 DeleteCriticalSection(&(dib->lock));
4745 /***********************************************************************
4746 * SetDIBColorTable (X11DRV.@)
4748 UINT X11DRV_SetDIBColorTable( X11DRV_PDEVICE *physDev, UINT start, UINT count, const RGBQUAD *colors )
4750 BITMAPOBJ * bmp;
4751 X11DRV_DIBSECTION *dib;
4752 UINT ret = 0;
4753 HBITMAP hBitmap = GetCurrentObject( physDev->hdc, OBJ_BITMAP );
4755 if (!(bmp = (BITMAPOBJ*)GDI_GetObjPtr( hBitmap, BITMAP_MAGIC ))) return 0;
4756 dib = (X11DRV_DIBSECTION *) bmp->dib;
4758 if (dib && dib->colorMap) {
4759 UINT end = count + start;
4760 if (end > dib->nColorMap) end = dib->nColorMap;
4762 * Changing color table might change the mapping between
4763 * DIB colors and X11 colors and thus alter the visible state
4764 * of the bitmap object.
4766 X11DRV_DIB_Lock(bmp, DIB_Status_AppMod, FALSE);
4767 X11DRV_DIB_GenColorMap( physDev, dib->colorMap, DIB_RGB_COLORS,
4768 dib->dibSection.dsBm.bmBitsPixel,
4769 TRUE, colors, start, end );
4770 X11DRV_DIB_Unlock(bmp, TRUE);
4771 ret = end - start;
4773 GDI_ReleaseObj( hBitmap );
4774 return ret;
4777 /***********************************************************************
4778 * GetDIBColorTable (X11DRV.@)
4780 UINT X11DRV_GetDIBColorTable( X11DRV_PDEVICE *physDev, UINT start, UINT count, RGBQUAD *colors )
4782 BITMAPOBJ * bmp;
4783 X11DRV_DIBSECTION *dib;
4784 UINT ret = 0;
4785 HBITMAP hBitmap = GetCurrentObject( physDev->hdc, OBJ_BITMAP );
4787 if (!(bmp = (BITMAPOBJ*)GDI_GetObjPtr( hBitmap, BITMAP_MAGIC ))) return 0;
4788 dib = (X11DRV_DIBSECTION *) bmp->dib;
4790 if (dib && dib->colorMap) {
4791 UINT i, end = count + start;
4792 if (end > dib->nColorMap) end = dib->nColorMap;
4793 for (i = start; i < end; i++,colors++) {
4794 COLORREF col = X11DRV_PALETTE_ToLogical( dib->colorMap[i] );
4795 colors->rgbBlue = GetBValue(col);
4796 colors->rgbGreen = GetGValue(col);
4797 colors->rgbRed = GetRValue(col);
4798 colors->rgbReserved = 0;
4800 ret = end-start;
4802 GDI_ReleaseObj( hBitmap );
4803 return ret;
4808 /***********************************************************************
4809 * X11DRV_DIB_CreateDIBFromBitmap
4811 * Allocates a packed DIB and copies the bitmap data into it.
4813 HGLOBAL X11DRV_DIB_CreateDIBFromBitmap(HDC hdc, HBITMAP hBmp)
4815 BITMAP bmp;
4816 HGLOBAL hPackedDIB;
4817 LPBYTE pPackedDIB;
4818 LPBITMAPINFOHEADER pbmiHeader;
4819 unsigned int cDataSize, cPackedSize, OffsetBits;
4820 int nLinesCopied;
4822 if (!GetObjectW( hBmp, sizeof(bmp), &bmp )) return 0;
4825 * A packed DIB contains a BITMAPINFO structure followed immediately by
4826 * an optional color palette and the pixel data.
4829 /* Calculate the size of the packed DIB */
4830 cDataSize = X11DRV_DIB_GetDIBWidthBytes( bmp.bmWidth, bmp.bmBitsPixel ) * abs( bmp.bmHeight );
4831 cPackedSize = sizeof(BITMAPINFOHEADER)
4832 + ( (bmp.bmBitsPixel <= 8) ? (sizeof(RGBQUAD) * (1 << bmp.bmBitsPixel)) : 0 )
4833 + cDataSize;
4834 /* Get the offset to the bits */
4835 OffsetBits = cPackedSize - cDataSize;
4837 /* Allocate the packed DIB */
4838 TRACE("\tAllocating packed DIB of size %d\n", cPackedSize);
4839 hPackedDIB = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE /*| GMEM_ZEROINIT*/,
4840 cPackedSize );
4841 if ( !hPackedDIB )
4843 WARN("Could not allocate packed DIB!\n");
4844 return 0;
4847 /* A packed DIB starts with a BITMAPINFOHEADER */
4848 pPackedDIB = GlobalLock(hPackedDIB);
4849 pbmiHeader = (LPBITMAPINFOHEADER)pPackedDIB;
4851 /* Init the BITMAPINFOHEADER */
4852 pbmiHeader->biSize = sizeof(BITMAPINFOHEADER);
4853 pbmiHeader->biWidth = bmp.bmWidth;
4854 pbmiHeader->biHeight = bmp.bmHeight;
4855 pbmiHeader->biPlanes = 1;
4856 pbmiHeader->biBitCount = bmp.bmBitsPixel;
4857 pbmiHeader->biCompression = BI_RGB;
4858 pbmiHeader->biSizeImage = 0;
4859 pbmiHeader->biXPelsPerMeter = pbmiHeader->biYPelsPerMeter = 0;
4860 pbmiHeader->biClrUsed = 0;
4861 pbmiHeader->biClrImportant = 0;
4863 /* Retrieve the DIB bits from the bitmap and fill in the
4864 * DIB color table if present */
4866 nLinesCopied = GetDIBits(hdc, /* Handle to device context */
4867 hBmp, /* Handle to bitmap */
4868 0, /* First scan line to set in dest bitmap */
4869 bmp.bmHeight, /* Number of scan lines to copy */
4870 pPackedDIB + OffsetBits, /* [out] Address of array for bitmap bits */
4871 (LPBITMAPINFO) pbmiHeader, /* [out] Address of BITMAPINFO structure */
4872 0); /* RGB or palette index */
4873 GlobalUnlock(hPackedDIB);
4875 /* Cleanup if GetDIBits failed */
4876 if (nLinesCopied != bmp.bmHeight)
4878 TRACE("\tGetDIBits returned %d. Actual lines=%d\n", nLinesCopied, bmp.bmHeight);
4879 GlobalFree(hPackedDIB);
4880 hPackedDIB = 0;
4882 return hPackedDIB;
4886 /**************************************************************************
4887 * X11DRV_DIB_CreateDIBFromPixmap
4889 * Allocates a packed DIB and copies the Pixmap data into it.
4890 * If bDeletePixmap is TRUE, the Pixmap passed in is deleted after the conversion.
4892 HGLOBAL X11DRV_DIB_CreateDIBFromPixmap(Pixmap pixmap, HDC hdc, BOOL bDeletePixmap)
4894 HBITMAP hBmp = 0;
4895 BITMAPOBJ *pBmp = NULL;
4896 HGLOBAL hPackedDIB = 0;
4898 /* Allocates an HBITMAP which references the Pixmap passed to us */
4899 hBmp = X11DRV_BITMAP_CreateBitmapHeaderFromPixmap(hdc, pixmap);
4900 if (!hBmp)
4902 TRACE("\tCould not create bitmap header for Pixmap\n");
4903 goto END;
4907 * Create a packed DIB from the Pixmap wrapper bitmap created above.
4908 * A packed DIB contains a BITMAPINFO structure followed immediately by
4909 * an optional color palette and the pixel data.
4911 hPackedDIB = X11DRV_DIB_CreateDIBFromBitmap(hdc, hBmp);
4913 /* Get a pointer to the BITMAPOBJ structure */
4914 pBmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
4916 /* We can now get rid of the HBITMAP wrapper we created earlier.
4917 * Note: Simply calling DeleteObject will free the embedded Pixmap as well.
4919 if (!bDeletePixmap)
4921 /* Clear the physBitmap to prevent the Pixmap from being deleted by DeleteObject */
4922 pBmp->physBitmap = NULL;
4923 pBmp->funcs = NULL;
4925 GDI_ReleaseObj( hBmp );
4926 DeleteObject(hBmp);
4928 END:
4929 TRACE("\tReturning packed DIB %p\n", hPackedDIB);
4930 return hPackedDIB;
4934 /**************************************************************************
4935 * X11DRV_DIB_CreatePixmapFromDIB
4937 * Creates a Pixmap from a packed DIB
4939 Pixmap X11DRV_DIB_CreatePixmapFromDIB( HGLOBAL hPackedDIB, HDC hdc )
4941 Pixmap pixmap = None;
4942 HBITMAP hBmp = 0;
4943 BITMAPOBJ *pBmp = NULL;
4944 LPBYTE pPackedDIB = NULL;
4945 LPBITMAPINFO pbmi = NULL;
4946 LPBITMAPINFOHEADER pbmiHeader = NULL;
4947 LPBYTE pbits = NULL;
4949 /* Get a pointer to the packed DIB's data */
4950 pPackedDIB = (LPBYTE)GlobalLock(hPackedDIB);
4951 pbmiHeader = (LPBITMAPINFOHEADER)pPackedDIB;
4952 pbmi = (LPBITMAPINFO)pPackedDIB;
4953 pbits = (LPBYTE)(pPackedDIB
4954 + X11DRV_DIB_BitmapInfoSize( (LPBITMAPINFO)pbmiHeader, DIB_RGB_COLORS ));
4956 /* Create a DDB from the DIB */
4958 hBmp = CreateDIBitmap(hdc,
4959 pbmiHeader,
4960 CBM_INIT,
4961 (LPVOID)pbits,
4962 pbmi,
4963 DIB_RGB_COLORS);
4965 GlobalUnlock(hPackedDIB);
4967 TRACE("CreateDIBitmap returned %p\n", hBmp);
4969 /* Retrieve the internal Pixmap from the DDB */
4971 pBmp = (BITMAPOBJ *) GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
4973 pixmap = (Pixmap)pBmp->physBitmap;
4974 /* clear the physBitmap so that we can steal its pixmap */
4975 pBmp->physBitmap = NULL;
4976 pBmp->funcs = NULL;
4978 /* Delete the DDB we created earlier now that we have stolen its pixmap */
4979 GDI_ReleaseObj( hBmp );
4980 DeleteObject(hBmp);
4982 TRACE("\tReturning Pixmap %ld\n", pixmap);
4983 return pixmap;