HTTP_DealWithProxy: Only add http:// to proxy string when needed.
[wine/multimedia.git] / dlls / x11drv / dib.c
blob487b21d2b0f29e91a5c206f98be0bb464a572a9f
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 "bitmap.h"
40 #include "x11drv.h"
41 #include "wine/debug.h"
42 #include "gdi.h"
43 #include "palette.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(bitmap);
46 WINE_DECLARE_DEBUG_CHANNEL(x11drv);
48 static int ximageDepthTable[32];
50 /* This structure holds the arguments for DIB_SetImageBits() */
51 typedef struct
53 X11DRV_PDEVICE *physDev;
54 LPCVOID bits;
55 XImage *image;
56 PALETTEENTRY *palentry;
57 int lines;
58 DWORD infoWidth;
59 WORD depth;
60 WORD infoBpp;
61 WORD compression;
62 RGBQUAD *colorMap;
63 int nColorMap;
64 Drawable drawable;
65 GC gc;
66 int xSrc;
67 int ySrc;
68 int xDest;
69 int yDest;
70 int width;
71 int height;
72 DWORD rMask;
73 DWORD gMask;
74 DWORD bMask;
75 BOOL useShm;
76 int dibpitch;
77 } X11DRV_DIB_IMAGEBITS_DESCR;
80 enum Rle_EscapeCodes
82 RLE_EOL = 0, /* End of line */
83 RLE_END = 1, /* End of bitmap */
84 RLE_DELTA = 2 /* Delta */
87 /***********************************************************************
88 * X11DRV_DIB_GetXImageWidthBytes
90 * Return the width of an X image in bytes
92 inline static int X11DRV_DIB_GetXImageWidthBytes( int width, int depth )
94 if (!depth || depth > 32) goto error;
96 if (!ximageDepthTable[depth-1])
98 XImage *testimage = XCreateImage( gdi_display, visual, depth,
99 ZPixmap, 0, NULL, 1, 1, 32, 20 );
100 if (testimage)
102 ximageDepthTable[depth-1] = testimage->bits_per_pixel;
103 XDestroyImage( testimage );
105 else ximageDepthTable[depth-1] = -1;
107 if (ximageDepthTable[depth-1] != -1)
108 return (4 * ((width * ximageDepthTable[depth-1] + 31) / 32));
110 error:
111 WARN( "(%d): Unsupported depth\n", depth );
112 return 4 * width;
116 /***********************************************************************
117 * X11DRV_DIB_CreateXImage
119 * Create an X image.
121 XImage *X11DRV_DIB_CreateXImage( int width, int height, int depth )
123 int width_bytes;
124 XImage *image;
126 wine_tsx11_lock();
127 width_bytes = X11DRV_DIB_GetXImageWidthBytes( width, depth );
128 image = XCreateImage( gdi_display, visual, depth, ZPixmap, 0,
129 calloc( height, width_bytes ),
130 width, height, 32, width_bytes );
131 wine_tsx11_unlock();
132 return image;
136 /***********************************************************************
137 * DIB_GetBitmapInfo
139 * Get the info from a bitmap header.
140 * Return 1 for INFOHEADER, 0 for COREHEADER, -1 for error.
142 static int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, DWORD *width,
143 int *height, WORD *bpp, WORD *compr )
145 if (header->biSize == sizeof(BITMAPCOREHEADER))
147 BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)header;
148 *width = core->bcWidth;
149 *height = core->bcHeight;
150 *bpp = core->bcBitCount;
151 *compr = 0;
152 return 0;
154 if (header->biSize >= sizeof(BITMAPINFOHEADER))
156 *width = header->biWidth;
157 *height = header->biHeight;
158 *bpp = header->biBitCount;
159 *compr = header->biCompression;
160 return 1;
162 ERR("(%ld): unknown/wrong size for header\n", header->biSize );
163 return -1;
167 /***********************************************************************
168 * X11DRV_DIB_GenColorMap
170 * Fills the color map of a bitmap palette. Should not be called
171 * for a >8-bit deep bitmap.
173 int *X11DRV_DIB_GenColorMap( X11DRV_PDEVICE *physDev, int *colorMapping,
174 WORD coloruse, WORD depth, BOOL quads,
175 const void *colorPtr, int start, int end )
177 int i;
179 if (coloruse == DIB_RGB_COLORS)
181 int max = 1 << depth;
183 if (end > max) end = max;
185 if (quads)
187 RGBQUAD * rgb = (RGBQUAD *)colorPtr;
189 if (depth == 1) /* Monochrome */
190 for (i = start; i < end; i++, rgb++)
191 colorMapping[i] = (rgb->rgbRed + rgb->rgbGreen +
192 rgb->rgbBlue > 255*3/2);
193 else
194 for (i = start; i < end; i++, rgb++)
195 colorMapping[i] = X11DRV_PALETTE_ToPhysical( physDev, RGB(rgb->rgbRed,
196 rgb->rgbGreen,
197 rgb->rgbBlue));
199 else
201 RGBTRIPLE * rgb = (RGBTRIPLE *)colorPtr;
203 if (depth == 1) /* Monochrome */
204 for (i = start; i < end; i++, rgb++)
205 colorMapping[i] = (rgb->rgbtRed + rgb->rgbtGreen +
206 rgb->rgbtBlue > 255*3/2);
207 else
208 for (i = start; i < end; i++, rgb++)
209 colorMapping[i] = X11DRV_PALETTE_ToPhysical( physDev, RGB(rgb->rgbtRed,
210 rgb->rgbtGreen,
211 rgb->rgbtBlue));
214 else /* DIB_PAL_COLORS */
216 if (colorPtr) {
217 WORD * index = (WORD *)colorPtr;
219 for (i = start; i < end; i++, index++)
220 colorMapping[i] = X11DRV_PALETTE_ToPhysical( physDev, PALETTEINDEX(*index) );
221 } else {
222 for (i = start; i < end; i++)
223 colorMapping[i] = X11DRV_PALETTE_ToPhysical( physDev, PALETTEINDEX(i) );
227 return colorMapping;
230 /***********************************************************************
231 * X11DRV_DIB_BuildColorMap
233 * Build the color map from the bitmap palette. Should not be called
234 * for a >8-bit deep bitmap.
236 int *X11DRV_DIB_BuildColorMap( X11DRV_PDEVICE *physDev, WORD coloruse, WORD depth,
237 const BITMAPINFO *info, int *nColors )
239 int colors;
240 BOOL isInfo;
241 const void *colorPtr;
242 int *colorMapping;
244 if ((isInfo = (info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))))
246 colors = info->bmiHeader.biClrUsed;
247 if (!colors) colors = 1 << info->bmiHeader.biBitCount;
248 colorPtr = info->bmiColors;
250 else /* assume BITMAPCOREINFO */
252 colors = 1 << ((BITMAPCOREHEADER *)&info->bmiHeader)->bcBitCount;
253 colorPtr = (WORD *)((BITMAPCOREINFO *)info)->bmciColors;
256 if (colors > 256)
258 ERR("called with >256 colors!\n");
259 return NULL;
262 /* just so CopyDIBSection doesn't have to create an identity palette */
263 if (coloruse == (WORD)-1) colorPtr = NULL;
265 if (!(colorMapping = (int *)HeapAlloc(GetProcessHeap(), 0,
266 colors * sizeof(int) )))
267 return NULL;
269 *nColors = colors;
270 return X11DRV_DIB_GenColorMap( physDev, colorMapping, coloruse, depth,
271 isInfo, colorPtr, 0, colors);
275 /***********************************************************************
276 * X11DRV_DIB_MapColor
278 int X11DRV_DIB_MapColor( int *physMap, int nPhysMap, int phys, int oldcol )
280 int color;
282 if ((oldcol < nPhysMap) && (physMap[oldcol] == phys))
283 return oldcol;
285 for (color = 0; color < nPhysMap; color++)
286 if (physMap[color] == phys)
287 return color;
289 WARN("Strange color %08x\n", phys);
290 return 0;
294 /*********************************************************************
295 * X11DRV_DIB_GetNearestIndex
297 * Helper for X11DRV_DIB_GetDIBits.
298 * Returns the nearest colour table index for a given RGB.
299 * Nearest is defined by minimizing the sum of the squares.
301 static INT X11DRV_DIB_GetNearestIndex(RGBQUAD *colormap, int numColors, BYTE r, BYTE g, BYTE b)
303 INT i, best = -1, diff, bestdiff = -1;
304 RGBQUAD *color;
306 for(color = colormap, i = 0; i < numColors; color++, i++) {
307 diff = (r - color->rgbRed) * (r - color->rgbRed) +
308 (g - color->rgbGreen) * (g - color->rgbGreen) +
309 (b - color->rgbBlue) * (b - color->rgbBlue);
310 if(diff == 0)
311 return i;
312 if(best == -1 || diff < bestdiff) {
313 best = i;
314 bestdiff = diff;
317 return best;
319 /*********************************************************************
320 * X11DRV_DIB_MaskToShift
322 * Helper for X11DRV_DIB_GetDIBits.
323 * Returns the by how many bits to shift a given color so that it is
324 * in the proper position.
326 INT X11DRV_DIB_MaskToShift(DWORD mask)
328 int shift;
330 if (mask==0)
331 return 0;
333 shift=0;
334 while ((mask&1)==0) {
335 mask>>=1;
336 shift++;
338 return shift;
341 /***********************************************************************
342 * X11DRV_DIB_SetImageBits_1
344 * SetDIBits for a 1-bit deep DIB.
346 static void X11DRV_DIB_SetImageBits_1( int lines, const BYTE *srcbits,
347 DWORD srcwidth, DWORD dstwidth, int left,
348 int *colors, XImage *bmpImage, DWORD linebytes)
350 int h;
351 const BYTE* srcbyte;
352 BYTE srcval, extra;
353 DWORD i, x;
355 if (lines < 0 ) {
356 lines = -lines;
357 srcbits = srcbits + linebytes * (lines - 1);
358 linebytes = -linebytes;
361 if ((extra = (left & 7)) != 0) {
362 left &= ~7;
363 dstwidth += extra;
365 srcbits += left >> 3;
367 /* ==== pal 1 dib -> any bmp format ==== */
368 for (h = lines-1; h >=0; h--) {
369 srcbyte=srcbits;
370 /* FIXME: should avoid putting x<left pixels (minor speed issue) */
371 for (i = dstwidth/8, x = left; i > 0; i--) {
372 srcval=*srcbyte++;
373 XPutPixel( bmpImage, x++, h, colors[ srcval >> 7] );
374 XPutPixel( bmpImage, x++, h, colors[(srcval >> 6) & 1] );
375 XPutPixel( bmpImage, x++, h, colors[(srcval >> 5) & 1] );
376 XPutPixel( bmpImage, x++, h, colors[(srcval >> 4) & 1] );
377 XPutPixel( bmpImage, x++, h, colors[(srcval >> 3) & 1] );
378 XPutPixel( bmpImage, x++, h, colors[(srcval >> 2) & 1] );
379 XPutPixel( bmpImage, x++, h, colors[(srcval >> 1) & 1] );
380 XPutPixel( bmpImage, x++, h, colors[ srcval & 1] );
382 if (dstwidth % 8){
383 srcval=*srcbyte;
384 switch (dstwidth & 7)
386 case 7: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
387 case 6: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
388 case 5: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
389 case 4: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
390 case 3: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
391 case 2: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
392 case 1: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]);
395 srcbits += linebytes;
399 /***********************************************************************
400 * X11DRV_DIB_GetImageBits_1
402 * GetDIBits for a 1-bit deep DIB.
404 static void X11DRV_DIB_GetImageBits_1( int lines, BYTE *dstbits,
405 DWORD dstwidth, DWORD srcwidth,
406 RGBQUAD *colors, PALETTEENTRY *srccolors,
407 XImage *bmpImage, DWORD linebytes )
409 DWORD x;
410 int h;
412 if (lines < 0 ) {
413 lines = -lines;
414 dstbits = dstbits + linebytes * (lines - 1);
415 linebytes = -linebytes;
418 switch (bmpImage->depth)
420 case 1:
421 case 4:
422 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
423 /* ==== pal 1 or 4 bmp -> pal 1 dib ==== */
424 BYTE* dstbyte;
426 for (h=lines-1; h>=0; h--) {
427 BYTE dstval;
428 dstbyte=dstbits;
429 dstval=0;
430 for (x=0; x<dstwidth; x++) {
431 PALETTEENTRY srcval;
432 srcval=srccolors[XGetPixel(bmpImage, x, h)];
433 dstval|=(X11DRV_DIB_GetNearestIndex
434 (colors, 2,
435 srcval.peRed,
436 srcval.peGreen,
437 srcval.peBlue) << (7 - (x & 7)));
438 if ((x&7)==7) {
439 *dstbyte++=dstval;
440 dstval=0;
443 if ((dstwidth&7)!=0) {
444 *dstbyte=dstval;
446 dstbits += linebytes;
448 } else {
449 goto notsupported;
451 break;
453 case 8:
454 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
455 /* ==== pal 8 bmp -> pal 1 dib ==== */
456 const void* srcbits;
457 const BYTE* srcpixel;
458 BYTE* dstbyte;
460 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
462 for (h=0; h<lines; h++) {
463 BYTE dstval;
464 srcpixel=srcbits;
465 dstbyte=dstbits;
466 dstval=0;
467 for (x=0; x<dstwidth; x++) {
468 PALETTEENTRY srcval;
469 srcval=srccolors[(int)*srcpixel++];
470 dstval|=(X11DRV_DIB_GetNearestIndex
471 (colors, 2,
472 srcval.peRed,
473 srcval.peGreen,
474 srcval.peBlue) << (7-(x&7)) );
475 if ((x&7)==7) {
476 *dstbyte++=dstval;
477 dstval=0;
480 if ((dstwidth&7)!=0) {
481 *dstbyte=dstval;
483 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
484 dstbits += linebytes;
486 } else {
487 goto notsupported;
489 break;
491 case 15:
492 case 16:
494 const void* srcbits;
495 const WORD* srcpixel;
496 BYTE* dstbyte;
498 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
500 if (bmpImage->green_mask==0x03e0) {
501 if (bmpImage->red_mask==0x7c00) {
502 /* ==== rgb 555 bmp -> pal 1 dib ==== */
503 for (h=0; h<lines; h++) {
504 BYTE dstval;
505 srcpixel=srcbits;
506 dstbyte=dstbits;
507 dstval=0;
508 for (x=0; x<dstwidth; x++) {
509 WORD srcval;
510 srcval=*srcpixel++;
511 dstval|=(X11DRV_DIB_GetNearestIndex
512 (colors, 2,
513 ((srcval >> 7) & 0xf8) | /* r */
514 ((srcval >> 12) & 0x07),
515 ((srcval >> 2) & 0xf8) | /* g */
516 ((srcval >> 7) & 0x07),
517 ((srcval << 3) & 0xf8) | /* b */
518 ((srcval >> 2) & 0x07) ) << (7-(x&7)) );
519 if ((x&7)==7) {
520 *dstbyte++=dstval;
521 dstval=0;
524 if ((dstwidth&7)!=0) {
525 *dstbyte=dstval;
527 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
528 dstbits += linebytes;
530 } else if (bmpImage->blue_mask==0x7c00) {
531 /* ==== bgr 555 bmp -> pal 1 dib ==== */
532 for (h=0; h<lines; h++) {
533 WORD dstval;
534 srcpixel=srcbits;
535 dstbyte=dstbits;
536 dstval=0;
537 for (x=0; x<dstwidth; x++) {
538 BYTE srcval;
539 srcval=*srcpixel++;
540 dstval|=(X11DRV_DIB_GetNearestIndex
541 (colors, 2,
542 ((srcval << 3) & 0xf8) | /* r */
543 ((srcval >> 2) & 0x07),
544 ((srcval >> 2) & 0xf8) | /* g */
545 ((srcval >> 7) & 0x07),
546 ((srcval >> 7) & 0xf8) | /* b */
547 ((srcval >> 12) & 0x07) ) << (7-(x&7)) );
548 if ((x&7)==7) {
549 *dstbyte++=dstval;
550 dstval=0;
553 if ((dstwidth&7)!=0) {
554 *dstbyte=dstval;
556 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
557 dstbits += linebytes;
559 } else {
560 goto notsupported;
562 } else if (bmpImage->green_mask==0x07e0) {
563 if (bmpImage->red_mask==0xf800) {
564 /* ==== rgb 565 bmp -> pal 1 dib ==== */
565 for (h=0; h<lines; h++) {
566 BYTE dstval;
567 srcpixel=srcbits;
568 dstbyte=dstbits;
569 dstval=0;
570 for (x=0; x<dstwidth; x++) {
571 WORD srcval;
572 srcval=*srcpixel++;
573 dstval|=(X11DRV_DIB_GetNearestIndex
574 (colors, 2,
575 ((srcval >> 8) & 0xf8) | /* r */
576 ((srcval >> 13) & 0x07),
577 ((srcval >> 3) & 0xfc) | /* g */
578 ((srcval >> 9) & 0x03),
579 ((srcval << 3) & 0xf8) | /* b */
580 ((srcval >> 2) & 0x07) ) << (7-(x&7)) );
581 if ((x&7)==7) {
582 *dstbyte++=dstval;
583 dstval=0;
586 if ((dstwidth&7)!=0) {
587 *dstbyte=dstval;
589 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
590 dstbits += linebytes;
592 } else if (bmpImage->blue_mask==0xf800) {
593 /* ==== bgr 565 bmp -> pal 1 dib ==== */
594 for (h=0; h<lines; h++) {
595 BYTE dstval;
596 srcpixel=srcbits;
597 dstbyte=dstbits;
598 dstval=0;
599 for (x=0; x<dstwidth; x++) {
600 WORD srcval;
601 srcval=*srcpixel++;
602 dstval|=(X11DRV_DIB_GetNearestIndex
603 (colors, 2,
604 ((srcval << 3) & 0xf8) | /* r */
605 ((srcval >> 2) & 0x07),
606 ((srcval >> 3) & 0xfc) | /* g */
607 ((srcval >> 9) & 0x03),
608 ((srcval >> 8) & 0xf8) | /* b */
609 ((srcval >> 13) & 0x07) ) << (7-(x&7)) );
610 if ((x&7)==7) {
611 *dstbyte++=dstval;
612 dstval=0;
615 if ((dstwidth&7)!=0) {
616 *dstbyte=dstval;
618 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
619 dstbits += linebytes;
621 } else {
622 goto notsupported;
624 } else {
625 goto notsupported;
628 break;
630 case 24:
631 case 32:
633 const void* srcbits;
634 const BYTE *srcbyte;
635 BYTE* dstbyte;
636 int bytes_per_pixel;
638 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
639 bytes_per_pixel=(bmpImage->bits_per_pixel==24?3:4);
641 if (bmpImage->green_mask!=0x00ff00 ||
642 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
643 goto notsupported;
644 } else if (bmpImage->blue_mask==0xff) {
645 /* ==== rgb 888 or 0888 bmp -> pal 1 dib ==== */
646 for (h=0; h<lines; h++) {
647 BYTE dstval;
648 srcbyte=srcbits;
649 dstbyte=dstbits;
650 dstval=0;
651 for (x=0; x<dstwidth; x++) {
652 dstval|=(X11DRV_DIB_GetNearestIndex
653 (colors, 2,
654 srcbyte[2],
655 srcbyte[1],
656 srcbyte[0]) << (7-(x&7)) );
657 srcbyte+=bytes_per_pixel;
658 if ((x&7)==7) {
659 *dstbyte++=dstval;
660 dstval=0;
663 if ((dstwidth&7)!=0) {
664 *dstbyte=dstval;
666 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
667 dstbits += linebytes;
669 } else {
670 /* ==== bgr 888 or 0888 bmp -> pal 1 dib ==== */
671 for (h=0; h<lines; h++) {
672 BYTE dstval;
673 srcbyte=srcbits;
674 dstbyte=dstbits;
675 dstval=0;
676 for (x=0; x<dstwidth; x++) {
677 dstval|=(X11DRV_DIB_GetNearestIndex
678 (colors, 2,
679 srcbyte[0],
680 srcbyte[1],
681 srcbyte[2]) << (7-(x&7)) );
682 srcbyte+=bytes_per_pixel;
683 if ((x&7)==7) {
684 *dstbyte++=dstval;
685 dstval=0;
688 if ((dstwidth&7)!=0) {
689 *dstbyte=dstval;
691 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
692 dstbits += linebytes;
696 break;
698 default:
699 notsupported:
701 BYTE* dstbyte;
702 unsigned long white = (1 << bmpImage->bits_per_pixel) - 1;
704 /* ==== any bmp format -> pal 1 dib ==== */
705 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 1 bit DIB\n",
706 bmpImage->bits_per_pixel, bmpImage->red_mask,
707 bmpImage->green_mask, bmpImage->blue_mask );
709 for (h=lines-1; h>=0; h--) {
710 BYTE dstval;
711 dstbyte=dstbits;
712 dstval=0;
713 for (x=0; x<dstwidth; x++) {
714 dstval|=(XGetPixel( bmpImage, x, h) >= white) << (7 - (x&7));
715 if ((x&7)==7) {
716 *dstbyte++=dstval;
717 dstval=0;
720 if ((dstwidth&7)!=0) {
721 *dstbyte=dstval;
723 dstbits += linebytes;
726 break;
730 /***********************************************************************
731 * X11DRV_DIB_SetImageBits_4
733 * SetDIBits for a 4-bit deep DIB.
735 static void X11DRV_DIB_SetImageBits_4( int lines, const BYTE *srcbits,
736 DWORD srcwidth, DWORD dstwidth, int left,
737 int *colors, XImage *bmpImage, DWORD linebytes)
739 int h;
740 const BYTE* srcbyte;
741 DWORD i, x;
743 if (lines < 0 ) {
744 lines = -lines;
745 srcbits = srcbits + linebytes * (lines - 1);
746 linebytes = -linebytes;
749 if (left & 1) {
750 left--;
751 dstwidth++;
753 srcbits += left >> 1;
755 /* ==== pal 4 dib -> any bmp format ==== */
756 for (h = lines-1; h >= 0; h--) {
757 srcbyte=srcbits;
758 for (i = dstwidth/2, x = left; i > 0; i--) {
759 BYTE srcval=*srcbyte++;
760 XPutPixel( bmpImage, x++, h, colors[srcval >> 4] );
761 XPutPixel( bmpImage, x++, h, colors[srcval & 0x0f] );
763 if (dstwidth & 1)
764 XPutPixel( bmpImage, x, h, colors[*srcbyte >> 4] );
765 srcbits += linebytes;
771 /***********************************************************************
772 * X11DRV_DIB_GetImageBits_4
774 * GetDIBits for a 4-bit deep DIB.
776 static void X11DRV_DIB_GetImageBits_4( int lines, BYTE *dstbits,
777 DWORD srcwidth, DWORD dstwidth,
778 RGBQUAD *colors, PALETTEENTRY *srccolors,
779 XImage *bmpImage, DWORD linebytes )
781 DWORD x;
782 int h;
783 BYTE *bits;
785 if (lines < 0 )
787 lines = -lines;
788 dstbits = dstbits + ( linebytes * (lines-1) );
789 linebytes = -linebytes;
792 bits = dstbits;
794 switch (bmpImage->depth) {
795 case 1:
796 case 4:
797 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
798 /* ==== pal 1 or 4 bmp -> pal 4 dib ==== */
799 BYTE* dstbyte;
801 for (h = lines-1; h >= 0; h--) {
802 BYTE dstval;
803 dstbyte=dstbits;
804 dstval=0;
805 for (x = 0; x < dstwidth; x++) {
806 PALETTEENTRY srcval;
807 srcval=srccolors[XGetPixel(bmpImage, x, h)];
808 dstval|=(X11DRV_DIB_GetNearestIndex
809 (colors, 16,
810 srcval.peRed,
811 srcval.peGreen,
812 srcval.peBlue) << (4-((x&1)<<2)));
813 if ((x&1)==1) {
814 *dstbyte++=dstval;
815 dstval=0;
818 if ((dstwidth&1)!=0) {
819 *dstbyte=dstval;
821 dstbits += linebytes;
823 } else {
824 goto notsupported;
826 break;
828 case 8:
829 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
830 /* ==== pal 8 bmp -> pal 4 dib ==== */
831 const void* srcbits;
832 const BYTE *srcpixel;
833 BYTE* dstbyte;
835 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
836 for (h=0; h<lines; h++) {
837 BYTE dstval;
838 srcpixel=srcbits;
839 dstbyte=dstbits;
840 dstval=0;
841 for (x=0; x<dstwidth; x++) {
842 PALETTEENTRY srcval;
843 srcval = srccolors[(int)*srcpixel++];
844 dstval|=(X11DRV_DIB_GetNearestIndex
845 (colors, 16,
846 srcval.peRed,
847 srcval.peGreen,
848 srcval.peBlue) << (4*(1-(x&1))) );
849 if ((x&1)==1) {
850 *dstbyte++=dstval;
851 dstval=0;
854 if ((dstwidth&1)!=0) {
855 *dstbyte=dstval;
857 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
858 dstbits += linebytes;
860 } else {
861 goto notsupported;
863 break;
865 case 15:
866 case 16:
868 const void* srcbits;
869 const WORD* srcpixel;
870 BYTE* dstbyte;
872 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
874 if (bmpImage->green_mask==0x03e0) {
875 if (bmpImage->red_mask==0x7c00) {
876 /* ==== rgb 555 bmp -> pal 4 dib ==== */
877 for (h=0; h<lines; h++) {
878 BYTE dstval;
879 srcpixel=srcbits;
880 dstbyte=dstbits;
881 dstval=0;
882 for (x=0; x<dstwidth; x++) {
883 WORD srcval;
884 srcval=*srcpixel++;
885 dstval|=(X11DRV_DIB_GetNearestIndex
886 (colors, 16,
887 ((srcval >> 7) & 0xf8) | /* r */
888 ((srcval >> 12) & 0x07),
889 ((srcval >> 2) & 0xf8) | /* g */
890 ((srcval >> 7) & 0x07),
891 ((srcval << 3) & 0xf8) | /* b */
892 ((srcval >> 2) & 0x07) ) << ((1-(x&1))<<2) );
893 if ((x&1)==1) {
894 *dstbyte++=dstval;
895 dstval=0;
898 if ((dstwidth&1)!=0) {
899 *dstbyte=dstval;
901 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
902 dstbits += linebytes;
904 } else if (bmpImage->blue_mask==0x7c00) {
905 /* ==== bgr 555 bmp -> pal 4 dib ==== */
906 for (h=0; h<lines; h++) {
907 WORD dstval;
908 srcpixel=srcbits;
909 dstbyte=dstbits;
910 dstval=0;
911 for (x=0; x<dstwidth; x++) {
912 WORD srcval;
913 srcval=*srcpixel++;
914 dstval|=(X11DRV_DIB_GetNearestIndex
915 (colors, 16,
916 ((srcval << 3) & 0xf8) | /* r */
917 ((srcval >> 2) & 0x07),
918 ((srcval >> 2) & 0xf8) | /* g */
919 ((srcval >> 7) & 0x07),
920 ((srcval >> 7) & 0xf8) | /* b */
921 ((srcval >> 12) & 0x07) ) << ((1-(x&1))<<2) );
922 if ((x&1)==1) {
923 *dstbyte++=dstval;
924 dstval=0;
927 if ((dstwidth&1)!=0) {
928 *dstbyte=dstval;
930 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
931 dstbits += linebytes;
933 } else {
934 goto notsupported;
936 } else if (bmpImage->green_mask==0x07e0) {
937 if (bmpImage->red_mask==0xf800) {
938 /* ==== rgb 565 bmp -> pal 4 dib ==== */
939 for (h=0; h<lines; h++) {
940 BYTE dstval;
941 srcpixel=srcbits;
942 dstbyte=dstbits;
943 dstval=0;
944 for (x=0; x<dstwidth; x++) {
945 WORD srcval;
946 srcval=*srcpixel++;
947 dstval|=(X11DRV_DIB_GetNearestIndex
948 (colors, 16,
949 ((srcval >> 8) & 0xf8) | /* r */
950 ((srcval >> 13) & 0x07),
951 ((srcval >> 3) & 0xfc) | /* g */
952 ((srcval >> 9) & 0x03),
953 ((srcval << 3) & 0xf8) | /* b */
954 ((srcval >> 2) & 0x07) ) << ((1-(x&1))<<2) );
955 if ((x&1)==1) {
956 *dstbyte++=dstval;
957 dstval=0;
960 if ((dstwidth&1)!=0) {
961 *dstbyte=dstval;
963 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
964 dstbits += linebytes;
966 } else if (bmpImage->blue_mask==0xf800) {
967 /* ==== bgr 565 bmp -> pal 4 dib ==== */
968 for (h=0; h<lines; h++) {
969 WORD dstval;
970 srcpixel=srcbits;
971 dstbyte=dstbits;
972 dstval=0;
973 for (x=0; x<dstwidth; x++) {
974 WORD srcval;
975 srcval=*srcpixel++;
976 dstval|=(X11DRV_DIB_GetNearestIndex
977 (colors, 16,
978 ((srcval << 3) & 0xf8) | /* r */
979 ((srcval >> 2) & 0x07),
980 ((srcval >> 3) & 0xfc) | /* g */
981 ((srcval >> 9) & 0x03),
982 ((srcval >> 8) & 0xf8) | /* b */
983 ((srcval >> 13) & 0x07) ) << ((1-(x&1))<<2) );
984 if ((x&1)==1) {
985 *dstbyte++=dstval;
986 dstval=0;
989 if ((dstwidth&1)!=0) {
990 *dstbyte=dstval;
992 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
993 dstbits += linebytes;
995 } else {
996 goto notsupported;
998 } else {
999 goto notsupported;
1002 break;
1004 case 24:
1005 if (bmpImage->bits_per_pixel==24) {
1006 const void* srcbits;
1007 const BYTE *srcbyte;
1008 BYTE* dstbyte;
1010 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1012 if (bmpImage->green_mask!=0x00ff00 ||
1013 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
1014 goto notsupported;
1015 } else if (bmpImage->blue_mask==0xff) {
1016 /* ==== rgb 888 bmp -> pal 4 dib ==== */
1017 for (h=0; h<lines; h++) {
1018 srcbyte=srcbits;
1019 dstbyte=dstbits;
1020 for (x=0; x<dstwidth/2; x++) {
1021 /* Do 2 pixels at a time */
1022 *dstbyte++=(X11DRV_DIB_GetNearestIndex
1023 (colors, 16,
1024 srcbyte[2],
1025 srcbyte[1],
1026 srcbyte[0]) << 4) |
1027 X11DRV_DIB_GetNearestIndex
1028 (colors, 16,
1029 srcbyte[5],
1030 srcbyte[4],
1031 srcbyte[3]);
1032 srcbyte+=6;
1034 if (dstwidth&1) {
1035 /* And the the odd pixel */
1036 *dstbyte++=(X11DRV_DIB_GetNearestIndex
1037 (colors, 16,
1038 srcbyte[2],
1039 srcbyte[1],
1040 srcbyte[0]) << 4);
1042 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1043 dstbits += linebytes;
1045 } else {
1046 /* ==== bgr 888 bmp -> pal 4 dib ==== */
1047 for (h=0; h<lines; h++) {
1048 srcbyte=srcbits;
1049 dstbyte=dstbits;
1050 for (x=0; x<dstwidth/2; x++) {
1051 /* Do 2 pixels at a time */
1052 *dstbyte++=(X11DRV_DIB_GetNearestIndex
1053 (colors, 16,
1054 srcbyte[0],
1055 srcbyte[1],
1056 srcbyte[2]) << 4) |
1057 X11DRV_DIB_GetNearestIndex
1058 (colors, 16,
1059 srcbyte[3],
1060 srcbyte[4],
1061 srcbyte[5]);
1062 srcbyte+=6;
1064 if (dstwidth&1) {
1065 /* And the the odd pixel */
1066 *dstbyte++=(X11DRV_DIB_GetNearestIndex
1067 (colors, 16,
1068 srcbyte[0],
1069 srcbyte[1],
1070 srcbyte[2]) << 4);
1072 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1073 dstbits += linebytes;
1076 break;
1078 /* Fall through */
1080 case 32:
1082 const void* srcbits;
1083 const BYTE *srcbyte;
1084 BYTE* dstbyte;
1086 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1088 if (bmpImage->green_mask!=0x00ff00 ||
1089 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
1090 goto notsupported;
1091 } else if (bmpImage->blue_mask==0xff) {
1092 /* ==== rgb 0888 bmp -> pal 4 dib ==== */
1093 for (h=0; h<lines; h++) {
1094 srcbyte=srcbits;
1095 dstbyte=dstbits;
1096 for (x=0; x<dstwidth/2; x++) {
1097 /* Do 2 pixels at a time */
1098 *dstbyte++=(X11DRV_DIB_GetNearestIndex
1099 (colors, 16,
1100 srcbyte[2],
1101 srcbyte[1],
1102 srcbyte[0]) << 4) |
1103 X11DRV_DIB_GetNearestIndex
1104 (colors, 16,
1105 srcbyte[6],
1106 srcbyte[5],
1107 srcbyte[4]);
1108 srcbyte+=8;
1110 if (dstwidth&1) {
1111 /* And the the odd pixel */
1112 *dstbyte++=(X11DRV_DIB_GetNearestIndex
1113 (colors, 16,
1114 srcbyte[2],
1115 srcbyte[1],
1116 srcbyte[0]) << 4);
1118 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1119 dstbits += linebytes;
1121 } else {
1122 /* ==== bgr 0888 bmp -> pal 4 dib ==== */
1123 for (h=0; h<lines; h++) {
1124 srcbyte=srcbits;
1125 dstbyte=dstbits;
1126 for (x=0; x<dstwidth/2; x++) {
1127 /* Do 2 pixels at a time */
1128 *dstbyte++=(X11DRV_DIB_GetNearestIndex
1129 (colors, 16,
1130 srcbyte[0],
1131 srcbyte[1],
1132 srcbyte[2]) << 4) |
1133 X11DRV_DIB_GetNearestIndex
1134 (colors, 16,
1135 srcbyte[4],
1136 srcbyte[5],
1137 srcbyte[6]);
1138 srcbyte+=8;
1140 if (dstwidth&1) {
1141 /* And the the odd pixel */
1142 *dstbyte++=(X11DRV_DIB_GetNearestIndex
1143 (colors, 16,
1144 srcbyte[0],
1145 srcbyte[1],
1146 srcbyte[2]) << 4);
1148 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1149 dstbits += linebytes;
1153 break;
1155 default:
1156 notsupported:
1158 BYTE* dstbyte;
1160 /* ==== any bmp format -> pal 4 dib ==== */
1161 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 4 bit DIB\n",
1162 bmpImage->bits_per_pixel, bmpImage->red_mask,
1163 bmpImage->green_mask, bmpImage->blue_mask );
1164 for (h=lines-1; h>=0; h--) {
1165 dstbyte=dstbits;
1166 for (x=0; x<(dstwidth & ~1); x+=2) {
1167 *dstbyte++=(X11DRV_DIB_MapColor((int*)colors, 16, XGetPixel(bmpImage, x, h), 0) << 4) |
1168 X11DRV_DIB_MapColor((int*)colors, 16, XGetPixel(bmpImage, x+1, h), 0);
1170 if (dstwidth & 1) {
1171 *dstbyte=(X11DRV_DIB_MapColor((int *)colors, 16, XGetPixel(bmpImage, x, h), 0) << 4);
1173 dstbits += linebytes;
1176 break;
1180 /***********************************************************************
1181 * X11DRV_DIB_SetImageBits_RLE4
1183 * SetDIBits for a 4-bit deep compressed DIB.
1185 static void X11DRV_DIB_SetImageBits_RLE4( int lines, const BYTE *bits,
1186 DWORD width, DWORD dstwidth,
1187 int left, int *colors,
1188 XImage *bmpImage )
1190 int x = 0, y = lines - 1, c, length;
1191 const BYTE *begin = bits;
1193 while (y >= 0)
1195 length = *bits++;
1196 if (length) { /* encoded */
1197 c = *bits++;
1198 while (length--) {
1199 if (x >= width) break;
1200 XPutPixel(bmpImage, x++, y, colors[c >> 4]);
1201 if (!length--) break;
1202 if (x >= width) break;
1203 XPutPixel(bmpImage, x++, y, colors[c & 0xf]);
1205 } else {
1206 length = *bits++;
1207 switch (length)
1209 case RLE_EOL:
1210 x = 0;
1211 y--;
1212 break;
1214 case RLE_END:
1215 return;
1217 case RLE_DELTA:
1218 x += *bits++;
1219 y -= *bits++;
1220 break;
1222 default: /* absolute */
1223 while (length--) {
1224 c = *bits++;
1225 if (x < width) XPutPixel(bmpImage, x++, y, colors[c >> 4]);
1226 if (!length--) break;
1227 if (x < width) XPutPixel(bmpImage, x++, y, colors[c & 0xf]);
1229 if ((bits - begin) & 1)
1230 bits++;
1238 /***********************************************************************
1239 * X11DRV_DIB_SetImageBits_8
1241 * SetDIBits for an 8-bit deep DIB.
1243 static void X11DRV_DIB_SetImageBits_8( int lines, const BYTE *srcbits,
1244 DWORD srcwidth, DWORD dstwidth, int left,
1245 const int *colors, XImage *bmpImage,
1246 DWORD linebytes )
1248 DWORD x;
1249 int h;
1250 const BYTE* srcbyte;
1251 BYTE* dstbits;
1253 if (lines < 0 )
1255 lines = -lines;
1256 srcbits = srcbits + linebytes * (lines-1);
1257 linebytes = -linebytes;
1259 srcbits += left;
1260 srcbyte = srcbits;
1262 switch (bmpImage->depth) {
1263 case 15:
1264 case 16:
1265 #if defined(__i386__) && defined(__GNUC__)
1266 /* Some X servers might have 32 bit/ 16bit deep pixel */
1267 if (lines && dstwidth && (bmpImage->bits_per_pixel == 16) &&
1268 (ImageByteOrder(gdi_display)==LSBFirst) )
1270 dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
1271 /* FIXME: Does this really handle all these cases correctly? */
1272 /* ==== pal 8 dib -> rgb or bgr 555 or 565 bmp ==== */
1273 for (h = lines ; h--; ) {
1274 int _cl1,_cl2; /* temp outputs for asm below */
1275 /* Borrowed from DirectDraw */
1276 __asm__ __volatile__(
1277 "xor %%eax,%%eax\n"
1278 "cld\n"
1279 "1:\n"
1280 " lodsb\n"
1281 " movw (%%edx,%%eax,4),%%ax\n"
1282 " stosw\n"
1283 " xor %%eax,%%eax\n"
1284 " loop 1b\n"
1285 :"=S" (srcbyte), "=D" (_cl1), "=c" (_cl2)
1286 :"S" (srcbyte),
1287 "D" (dstbits),
1288 "c" (dstwidth),
1289 "d" (colors)
1290 :"eax", "cc", "memory"
1292 srcbyte = (srcbits += linebytes);
1293 dstbits -= bmpImage->bytes_per_line;
1295 return;
1297 break;
1298 #endif
1299 case 24:
1300 case 32:
1301 #if defined(__i386__) && defined(__GNUC__)
1302 if (lines && dstwidth && (bmpImage->bits_per_pixel == 32) &&
1303 (ImageByteOrder(gdi_display)==LSBFirst) )
1305 dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
1306 /* FIXME: Does this really handle both cases correctly? */
1307 /* ==== pal 8 dib -> rgb or bgr 0888 bmp ==== */
1308 for (h = lines ; h--; ) {
1309 int _cl1,_cl2; /* temp outputs for asm below */
1310 /* Borrowed from DirectDraw */
1311 __asm__ __volatile__(
1312 "xor %%eax,%%eax\n"
1313 "cld\n"
1314 "1:\n"
1315 " lodsb\n"
1316 " movl (%%edx,%%eax,4),%%eax\n"
1317 " stosl\n"
1318 " xor %%eax,%%eax\n"
1319 " loop 1b\n"
1320 :"=S" (srcbyte), "=D" (_cl1), "=c" (_cl2)
1321 :"S" (srcbyte),
1322 "D" (dstbits),
1323 "c" (dstwidth),
1324 "d" (colors)
1325 :"eax", "cc", "memory"
1327 srcbyte = (srcbits += linebytes);
1328 dstbits -= bmpImage->bytes_per_line;
1330 return;
1332 break;
1333 #endif
1334 default:
1335 break; /* use slow generic case below */
1338 /* ==== pal 8 dib -> any bmp format ==== */
1339 for (h=lines-1; h>=0; h--) {
1340 for (x=left; x<dstwidth+left; x++) {
1341 XPutPixel(bmpImage, x, h, colors[*srcbyte++]);
1343 srcbyte = (srcbits += linebytes);
1347 /***********************************************************************
1348 * X11DRV_DIB_GetImageBits_8
1350 * GetDIBits for an 8-bit deep DIB.
1352 static void X11DRV_DIB_GetImageBits_8( int lines, BYTE *dstbits,
1353 DWORD srcwidth, DWORD dstwidth,
1354 RGBQUAD *colors, PALETTEENTRY *srccolors,
1355 XImage *bmpImage, DWORD linebytes )
1357 DWORD x;
1358 int h;
1359 BYTE* dstbyte;
1361 if (lines < 0 )
1363 lines = -lines;
1364 dstbits = dstbits + ( linebytes * (lines-1) );
1365 linebytes = -linebytes;
1369 * Hack for now
1370 * This condition is true when GetImageBits has been called by
1371 * UpdateDIBSection. For now, GetNearestIndex is too slow to support
1372 * 256 colormaps, so we'll just use for for GetDIBits calls.
1373 * (In somes cases, in a updateDIBSection, the returned colors are bad too)
1375 if (!srccolors) goto updatesection;
1377 switch (bmpImage->depth) {
1378 case 1:
1379 case 4:
1380 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
1382 /* ==== pal 1 bmp -> pal 8 dib ==== */
1383 /* ==== pal 4 bmp -> pal 8 dib ==== */
1384 for (h=lines-1; h>=0; h--) {
1385 dstbyte=dstbits;
1386 for (x=0; x<dstwidth; x++) {
1387 PALETTEENTRY srcval;
1388 srcval=srccolors[XGetPixel(bmpImage, x, h)];
1389 *dstbyte++=X11DRV_DIB_GetNearestIndex(colors, 256,
1390 srcval.peRed,
1391 srcval.peGreen,
1392 srcval.peBlue);
1394 dstbits += linebytes;
1396 } else {
1397 goto notsupported;
1399 break;
1401 case 8:
1402 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
1403 /* ==== pal 8 bmp -> pal 8 dib ==== */
1404 const void* srcbits;
1405 const BYTE* srcpixel;
1407 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1408 for (h=0; h<lines; h++) {
1409 srcpixel=srcbits;
1410 dstbyte=dstbits;
1411 for (x = 0; x < dstwidth; x++) {
1412 PALETTEENTRY srcval;
1413 srcval=srccolors[(int)*srcpixel++];
1414 *dstbyte++=X11DRV_DIB_GetNearestIndex(colors, 256,
1415 srcval.peRed,
1416 srcval.peGreen,
1417 srcval.peBlue);
1419 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1420 dstbits += linebytes;
1422 } else {
1423 goto notsupported;
1425 break;
1427 case 15:
1428 case 16:
1430 const void* srcbits;
1431 const WORD* srcpixel;
1432 BYTE* dstbyte;
1434 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1436 if (bmpImage->green_mask==0x03e0) {
1437 if (bmpImage->red_mask==0x7c00) {
1438 /* ==== rgb 555 bmp -> pal 8 dib ==== */
1439 for (h=0; h<lines; h++) {
1440 srcpixel=srcbits;
1441 dstbyte=dstbits;
1442 for (x=0; x<dstwidth; x++) {
1443 WORD srcval;
1444 srcval=*srcpixel++;
1445 *dstbyte++=X11DRV_DIB_GetNearestIndex
1446 (colors, 256,
1447 ((srcval >> 7) & 0xf8) | /* r */
1448 ((srcval >> 12) & 0x07),
1449 ((srcval >> 2) & 0xf8) | /* g */
1450 ((srcval >> 7) & 0x07),
1451 ((srcval << 3) & 0xf8) | /* b */
1452 ((srcval >> 2) & 0x07) );
1454 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1455 dstbits += linebytes;
1457 } else if (bmpImage->blue_mask==0x7c00) {
1458 /* ==== bgr 555 bmp -> pal 8 dib ==== */
1459 for (h=0; h<lines; h++) {
1460 srcpixel=srcbits;
1461 dstbyte=dstbits;
1462 for (x=0; x<dstwidth; x++) {
1463 WORD srcval;
1464 srcval=*srcpixel++;
1465 *dstbyte++=X11DRV_DIB_GetNearestIndex
1466 (colors, 256,
1467 ((srcval << 3) & 0xf8) | /* r */
1468 ((srcval >> 2) & 0x07),
1469 ((srcval >> 2) & 0xf8) | /* g */
1470 ((srcval >> 7) & 0x07),
1471 ((srcval >> 7) & 0xf8) | /* b */
1472 ((srcval >> 12) & 0x07) );
1474 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1475 dstbits += linebytes;
1477 } else {
1478 goto notsupported;
1480 } else if (bmpImage->green_mask==0x07e0) {
1481 if (bmpImage->red_mask==0xf800) {
1482 /* ==== rgb 565 bmp -> pal 8 dib ==== */
1483 for (h=0; h<lines; h++) {
1484 srcpixel=srcbits;
1485 dstbyte=dstbits;
1486 for (x=0; x<dstwidth; x++) {
1487 WORD srcval;
1488 srcval=*srcpixel++;
1489 *dstbyte++=X11DRV_DIB_GetNearestIndex
1490 (colors, 256,
1491 ((srcval >> 8) & 0xf8) | /* r */
1492 ((srcval >> 13) & 0x07),
1493 ((srcval >> 3) & 0xfc) | /* g */
1494 ((srcval >> 9) & 0x03),
1495 ((srcval << 3) & 0xf8) | /* b */
1496 ((srcval >> 2) & 0x07) );
1498 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1499 dstbits += linebytes;
1501 } else if (bmpImage->blue_mask==0xf800) {
1502 /* ==== bgr 565 bmp -> pal 8 dib ==== */
1503 for (h=0; h<lines; h++) {
1504 srcpixel=srcbits;
1505 dstbyte=dstbits;
1506 for (x=0; x<dstwidth; x++) {
1507 WORD srcval;
1508 srcval=*srcpixel++;
1509 *dstbyte++=X11DRV_DIB_GetNearestIndex
1510 (colors, 256,
1511 ((srcval << 3) & 0xf8) | /* r */
1512 ((srcval >> 2) & 0x07),
1513 ((srcval >> 3) & 0xfc) | /* g */
1514 ((srcval >> 9) & 0x03),
1515 ((srcval >> 8) & 0xf8) | /* b */
1516 ((srcval >> 13) & 0x07) );
1518 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1519 dstbits += linebytes;
1521 } else {
1522 goto notsupported;
1524 } else {
1525 goto notsupported;
1528 break;
1530 case 24:
1531 case 32:
1533 const void* srcbits;
1534 const BYTE *srcbyte;
1535 BYTE* dstbyte;
1536 int bytes_per_pixel;
1538 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1539 bytes_per_pixel=(bmpImage->bits_per_pixel==24?3:4);
1541 if (bmpImage->green_mask!=0x00ff00 ||
1542 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
1543 goto notsupported;
1544 } else if (bmpImage->blue_mask==0xff) {
1545 /* ==== rgb 888 or 0888 bmp -> pal 8 dib ==== */
1546 for (h=0; h<lines; h++) {
1547 srcbyte=srcbits;
1548 dstbyte=dstbits;
1549 for (x=0; x<dstwidth; x++) {
1550 *dstbyte++=X11DRV_DIB_GetNearestIndex
1551 (colors, 256,
1552 srcbyte[2],
1553 srcbyte[1],
1554 srcbyte[0]);
1555 srcbyte+=bytes_per_pixel;
1557 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1558 dstbits += linebytes;
1560 } else {
1561 /* ==== bgr 888 or 0888 bmp -> pal 8 dib ==== */
1562 for (h=0; h<lines; h++) {
1563 srcbyte=srcbits;
1564 dstbyte=dstbits;
1565 for (x=0; x<dstwidth; x++) {
1566 *dstbyte++=X11DRV_DIB_GetNearestIndex
1567 (colors, 256,
1568 srcbyte[0],
1569 srcbyte[1],
1570 srcbyte[2]);
1571 srcbyte+=bytes_per_pixel;
1573 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1574 dstbits += linebytes;
1578 break;
1580 default:
1581 notsupported:
1582 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 8 bit DIB\n",
1583 bmpImage->depth, bmpImage->red_mask,
1584 bmpImage->green_mask, bmpImage->blue_mask );
1585 updatesection:
1586 /* ==== any bmp format -> pal 8 dib ==== */
1587 for (h=lines-1; h>=0; h--) {
1588 dstbyte=dstbits;
1589 for (x=0; x<dstwidth; x++) {
1590 *dstbyte=X11DRV_DIB_MapColor
1591 ((int*)colors, 256,
1592 XGetPixel(bmpImage, x, h), *dstbyte);
1593 dstbyte++;
1595 dstbits += linebytes;
1597 break;
1601 /***********************************************************************
1602 * X11DRV_DIB_SetImageBits_RLE8
1604 * SetDIBits for an 8-bit deep compressed DIB.
1606 * This function rewritten 941113 by James Youngman. WINE blew out when I
1607 * first ran it because my desktop wallpaper is a (large) RLE8 bitmap.
1609 * This was because the algorithm assumed that all RLE8 bitmaps end with the
1610 * 'End of bitmap' escape code. This code is very much laxer in what it
1611 * allows to end the expansion. Possibly too lax. See the note by
1612 * case RleDelta. BTW, MS's documentation implies that a correct RLE8
1613 * bitmap should end with RleEnd, but on the other hand, software exists
1614 * that produces ones that don't and Windows 3.1 doesn't complain a bit
1615 * about it.
1617 * (No) apologies for my English spelling. [Emacs users: c-indent-level=4].
1618 * James A. Youngman <mbcstjy@afs.man.ac.uk>
1619 * [JAY]
1621 static void X11DRV_DIB_SetImageBits_RLE8( int lines, const BYTE *bits,
1622 DWORD width, DWORD dstwidth,
1623 int left, int *colors,
1624 XImage *bmpImage )
1626 int x; /* X-positon on each line. Increases. */
1627 int y; /* Line #. Starts at lines-1, decreases */
1628 const BYTE *pIn = bits; /* Pointer to current position in bits */
1629 BYTE length; /* The length pf a run */
1630 BYTE escape_code; /* See enum Rle8_EscapeCodes.*/
1633 * Note that the bitmap data is stored by Windows starting at the
1634 * bottom line of the bitmap and going upwards. Within each line,
1635 * the data is stored left-to-right. That's the reason why line
1636 * goes from lines-1 to 0. [JAY]
1639 x = 0;
1640 y = lines - 1;
1641 while (y >= 0)
1643 length = *pIn++;
1646 * If the length byte is not zero (which is the escape value),
1647 * We have a run of length pixels all the same colour. The colour
1648 * index is stored next.
1650 * If the length byte is zero, we need to read the next byte to
1651 * know what to do. [JAY]
1653 if (length != 0)
1656 * [Run-Length] Encoded mode
1658 int color = colors[*pIn++];
1659 while (length-- && x < dstwidth) XPutPixel(bmpImage, x++, y, color);
1661 else
1664 * Escape codes (may be an absolute sequence though)
1666 escape_code = (*pIn++);
1667 switch(escape_code)
1669 case RLE_EOL:
1670 x = 0;
1671 y--;
1672 break;
1674 case RLE_END:
1675 /* Not all RLE8 bitmaps end with this code. For
1676 * example, Paint Shop Pro produces some that don't.
1677 * That's (I think) what caused the previous
1678 * implementation to fail. [JAY]
1680 return;
1682 case RLE_DELTA:
1683 x += (*pIn++);
1684 y -= (*pIn++);
1685 break;
1687 default: /* switch to absolute mode */
1688 length = escape_code;
1689 while (length--)
1691 int color = colors[*pIn++];
1692 if (x >= dstwidth)
1694 pIn += length;
1695 break;
1697 XPutPixel(bmpImage, x++, y, color);
1700 * If you think for a moment you'll realise that the
1701 * only time we could ever possibly read an odd
1702 * number of bytes is when there is a 0x00 (escape),
1703 * a value >0x02 (absolute mode) and then an odd-
1704 * length run. Therefore this is the only place we
1705 * need to worry about it. Everywhere else the
1706 * bytes are always read in pairs. [JAY]
1708 if (escape_code & 1) pIn++; /* Throw away the pad byte. */
1709 break;
1710 } /* switch (escape_code) : Escape sequence */
1716 /***********************************************************************
1717 * X11DRV_DIB_SetImageBits_16
1719 * SetDIBits for a 16-bit deep DIB.
1721 static void X11DRV_DIB_SetImageBits_16( int lines, const BYTE *srcbits,
1722 DWORD srcwidth, DWORD dstwidth, int left,
1723 X11DRV_PDEVICE *physDev, DWORD rSrc, DWORD gSrc, DWORD bSrc,
1724 XImage *bmpImage, DWORD linebytes )
1726 DWORD x;
1727 int h;
1728 const dib_conversions *convs = (bmpImage->byte_order == LSBFirst) ? &dib_normal : &dib_dst_byteswap;
1730 if (lines < 0 )
1732 lines = -lines;
1733 srcbits = srcbits + ( linebytes * (lines-1));
1734 linebytes = -linebytes;
1737 switch (bmpImage->depth)
1739 case 15:
1740 case 16:
1742 char* dstbits;
1744 srcbits=srcbits+left*2;
1745 dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
1747 if (bmpImage->green_mask==0x03e0) {
1748 if (gSrc==bmpImage->green_mask) {
1749 if (rSrc==bmpImage->red_mask) {
1750 /* ==== rgb 555 dib -> rgb 555 bmp ==== */
1751 /* ==== bgr 555 dib -> bgr 555 bmp ==== */
1752 convs->Convert_5x5_asis
1753 (dstwidth,lines,
1754 srcbits,linebytes,
1755 dstbits,-bmpImage->bytes_per_line);
1756 } else if (rSrc==bmpImage->blue_mask) {
1757 /* ==== rgb 555 dib -> bgr 555 bmp ==== */
1758 /* ==== bgr 555 dib -> rgb 555 bmp ==== */
1759 convs->Convert_555_reverse
1760 (dstwidth,lines,
1761 srcbits,linebytes,
1762 dstbits,-bmpImage->bytes_per_line);
1764 } else {
1765 if (rSrc==bmpImage->red_mask || bSrc==bmpImage->blue_mask) {
1766 /* ==== rgb 565 dib -> rgb 555 bmp ==== */
1767 /* ==== bgr 565 dib -> bgr 555 bmp ==== */
1768 convs->Convert_565_to_555_asis
1769 (dstwidth,lines,
1770 srcbits,linebytes,
1771 dstbits,-bmpImage->bytes_per_line);
1772 } else {
1773 /* ==== rgb 565 dib -> bgr 555 bmp ==== */
1774 /* ==== bgr 565 dib -> rgb 555 bmp ==== */
1775 convs->Convert_565_to_555_reverse
1776 (dstwidth,lines,
1777 srcbits,linebytes,
1778 dstbits,-bmpImage->bytes_per_line);
1781 } else if (bmpImage->green_mask==0x07e0) {
1782 if (gSrc==bmpImage->green_mask) {
1783 if (rSrc==bmpImage->red_mask) {
1784 /* ==== rgb 565 dib -> rgb 565 bmp ==== */
1785 /* ==== bgr 565 dib -> bgr 565 bmp ==== */
1786 convs->Convert_5x5_asis
1787 (dstwidth,lines,
1788 srcbits,linebytes,
1789 dstbits,-bmpImage->bytes_per_line);
1790 } else {
1791 /* ==== rgb 565 dib -> bgr 565 bmp ==== */
1792 /* ==== bgr 565 dib -> rgb 565 bmp ==== */
1793 convs->Convert_565_reverse
1794 (dstwidth,lines,
1795 srcbits,linebytes,
1796 dstbits,-bmpImage->bytes_per_line);
1798 } else {
1799 if (rSrc==bmpImage->red_mask || bSrc==bmpImage->blue_mask) {
1800 /* ==== rgb 555 dib -> rgb 565 bmp ==== */
1801 /* ==== bgr 555 dib -> bgr 565 bmp ==== */
1802 convs->Convert_555_to_565_asis
1803 (dstwidth,lines,
1804 srcbits,linebytes,
1805 dstbits,-bmpImage->bytes_per_line);
1806 } else {
1807 /* ==== rgb 555 dib -> bgr 565 bmp ==== */
1808 /* ==== bgr 555 dib -> rgb 565 bmp ==== */
1809 convs->Convert_555_to_565_reverse
1810 (dstwidth,lines,
1811 srcbits,linebytes,
1812 dstbits,-bmpImage->bytes_per_line);
1815 } else {
1816 goto notsupported;
1819 break;
1821 case 24:
1822 if (bmpImage->bits_per_pixel==24) {
1823 char* dstbits;
1825 srcbits=srcbits+left*2;
1826 dstbits=bmpImage->data+left*3+(lines-1)*bmpImage->bytes_per_line;
1828 if (bmpImage->green_mask!=0x00ff00 ||
1829 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
1830 goto notsupported;
1831 } else if ((rSrc==0x1f && bmpImage->red_mask==0xff) ||
1832 (bSrc==0x1f && bmpImage->blue_mask==0xff)) {
1833 if (gSrc==0x03e0) {
1834 /* ==== rgb 555 dib -> rgb 888 bmp ==== */
1835 /* ==== bgr 555 dib -> bgr 888 bmp ==== */
1836 convs->Convert_555_to_888_asis
1837 (dstwidth,lines,
1838 srcbits,linebytes,
1839 dstbits,-bmpImage->bytes_per_line);
1840 } else {
1841 /* ==== rgb 565 dib -> rgb 888 bmp ==== */
1842 /* ==== bgr 565 dib -> bgr 888 bmp ==== */
1843 convs->Convert_565_to_888_asis
1844 (dstwidth,lines,
1845 srcbits,linebytes,
1846 dstbits,-bmpImage->bytes_per_line);
1848 } else {
1849 if (gSrc==0x03e0) {
1850 /* ==== rgb 555 dib -> bgr 888 bmp ==== */
1851 /* ==== bgr 555 dib -> rgb 888 bmp ==== */
1852 convs->Convert_555_to_888_reverse
1853 (dstwidth,lines,
1854 srcbits,linebytes,
1855 dstbits,-bmpImage->bytes_per_line);
1856 } else {
1857 /* ==== rgb 565 dib -> bgr 888 bmp ==== */
1858 /* ==== bgr 565 dib -> rgb 888 bmp ==== */
1859 convs->Convert_565_to_888_reverse
1860 (dstwidth,lines,
1861 srcbits,linebytes,
1862 dstbits,-bmpImage->bytes_per_line);
1865 break;
1867 /* Fall through */
1869 case 32:
1871 char* dstbits;
1873 srcbits=srcbits+left*2;
1874 dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
1876 if (bmpImage->green_mask!=0x00ff00 ||
1877 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
1878 goto notsupported;
1879 } else if ((rSrc==0x1f && bmpImage->red_mask==0xff) ||
1880 (bSrc==0x1f && bmpImage->blue_mask==0xff)) {
1881 if (gSrc==0x03e0) {
1882 /* ==== rgb 555 dib -> rgb 0888 bmp ==== */
1883 /* ==== bgr 555 dib -> bgr 0888 bmp ==== */
1884 convs->Convert_555_to_0888_asis
1885 (dstwidth,lines,
1886 srcbits,linebytes,
1887 dstbits,-bmpImage->bytes_per_line);
1888 } else {
1889 /* ==== rgb 565 dib -> rgb 0888 bmp ==== */
1890 /* ==== bgr 565 dib -> bgr 0888 bmp ==== */
1891 convs->Convert_565_to_0888_asis
1892 (dstwidth,lines,
1893 srcbits,linebytes,
1894 dstbits,-bmpImage->bytes_per_line);
1896 } else {
1897 if (gSrc==0x03e0) {
1898 /* ==== rgb 555 dib -> bgr 0888 bmp ==== */
1899 /* ==== bgr 555 dib -> rgb 0888 bmp ==== */
1900 convs->Convert_555_to_0888_reverse
1901 (dstwidth,lines,
1902 srcbits,linebytes,
1903 dstbits,-bmpImage->bytes_per_line);
1904 } else {
1905 /* ==== rgb 565 dib -> bgr 0888 bmp ==== */
1906 /* ==== bgr 565 dib -> rgb 0888 bmp ==== */
1907 convs->Convert_565_to_0888_reverse
1908 (dstwidth,lines,
1909 srcbits,linebytes,
1910 dstbits,-bmpImage->bytes_per_line);
1914 break;
1916 default:
1917 notsupported:
1918 WARN("from 16 bit DIB (%lx,%lx,%lx) to unknown %d bit bitmap (%lx,%lx,%lx)\n",
1919 rSrc, gSrc, bSrc, bmpImage->bits_per_pixel, bmpImage->red_mask,
1920 bmpImage->green_mask, bmpImage->blue_mask );
1921 /* fall through */
1922 case 1:
1923 case 4:
1924 case 8:
1926 /* ==== rgb or bgr 555 or 565 dib -> pal 1, 4 or 8 ==== */
1927 const WORD* srcpixel;
1928 int rShift1,gShift1,bShift1;
1929 int rShift2,gShift2,bShift2;
1930 BYTE gMask1,gMask2;
1932 /* Set color scaling values */
1933 rShift1=16+X11DRV_DIB_MaskToShift(rSrc)-3;
1934 gShift1=16+X11DRV_DIB_MaskToShift(gSrc)-3;
1935 bShift1=16+X11DRV_DIB_MaskToShift(bSrc)-3;
1936 rShift2=rShift1+5;
1937 gShift2=gShift1+5;
1938 bShift2=bShift1+5;
1939 if (gSrc==0x03e0) {
1940 /* Green has 5 bits, like the others */
1941 gMask1=0xf8;
1942 gMask2=0x07;
1943 } else {
1944 /* Green has 6 bits, not 5. Compensate. */
1945 gShift1++;
1946 gShift2+=2;
1947 gMask1=0xfc;
1948 gMask2=0x03;
1951 srcbits+=2*left;
1953 /* We could split it into four separate cases to optimize
1954 * but it is probably not worth it.
1956 for (h=lines-1; h>=0; h--) {
1957 srcpixel=(const WORD*)srcbits;
1958 for (x=left; x<dstwidth+left; x++) {
1959 DWORD srcval;
1960 BYTE red,green,blue;
1961 srcval=*srcpixel++ << 16;
1962 red= ((srcval >> rShift1) & 0xf8) |
1963 ((srcval >> rShift2) & 0x07);
1964 green=((srcval >> gShift1) & gMask1) |
1965 ((srcval >> gShift2) & gMask2);
1966 blue= ((srcval >> bShift1) & 0xf8) |
1967 ((srcval >> bShift2) & 0x07);
1968 XPutPixel(bmpImage, x, h,
1969 X11DRV_PALETTE_ToPhysical
1970 (physDev, RGB(red,green,blue)));
1972 srcbits += linebytes;
1975 break;
1980 /***********************************************************************
1981 * X11DRV_DIB_GetImageBits_16
1983 * GetDIBits for an 16-bit deep DIB.
1985 static void X11DRV_DIB_GetImageBits_16( int lines, BYTE *dstbits,
1986 DWORD dstwidth, DWORD srcwidth,
1987 PALETTEENTRY *srccolors,
1988 DWORD rDst, DWORD gDst, DWORD bDst,
1989 XImage *bmpImage, DWORD dibpitch )
1991 DWORD x;
1992 int h;
1993 const dib_conversions *convs = (bmpImage->byte_order == LSBFirst) ? &dib_normal : &dib_src_byteswap;
1995 DWORD linebytes = dibpitch;
1997 if (lines < 0 )
1999 lines = -lines;
2000 dstbits = dstbits + ( linebytes * (lines-1));
2001 linebytes = -linebytes;
2004 switch (bmpImage->depth)
2006 case 15:
2007 case 16:
2009 const char* srcbits;
2011 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2013 if (bmpImage->green_mask==0x03e0) {
2014 if (gDst==bmpImage->green_mask) {
2015 if (rDst==bmpImage->red_mask) {
2016 /* ==== rgb 555 bmp -> rgb 555 dib ==== */
2017 /* ==== bgr 555 bmp -> bgr 555 dib ==== */
2018 convs->Convert_5x5_asis
2019 (dstwidth,lines,
2020 srcbits,-bmpImage->bytes_per_line,
2021 dstbits,linebytes);
2022 } else {
2023 /* ==== rgb 555 bmp -> bgr 555 dib ==== */
2024 /* ==== bgr 555 bmp -> rgb 555 dib ==== */
2025 convs->Convert_555_reverse
2026 (dstwidth,lines,
2027 srcbits,-bmpImage->bytes_per_line,
2028 dstbits,linebytes);
2030 } else {
2031 if (rDst==bmpImage->red_mask || bDst==bmpImage->blue_mask) {
2032 /* ==== rgb 555 bmp -> rgb 565 dib ==== */
2033 /* ==== bgr 555 bmp -> bgr 565 dib ==== */
2034 convs->Convert_555_to_565_asis
2035 (dstwidth,lines,
2036 srcbits,-bmpImage->bytes_per_line,
2037 dstbits,linebytes);
2038 } else {
2039 /* ==== rgb 555 bmp -> bgr 565 dib ==== */
2040 /* ==== bgr 555 bmp -> rgb 565 dib ==== */
2041 convs->Convert_555_to_565_reverse
2042 (dstwidth,lines,
2043 srcbits,-bmpImage->bytes_per_line,
2044 dstbits,linebytes);
2047 } else if (bmpImage->green_mask==0x07e0) {
2048 if (gDst==bmpImage->green_mask) {
2049 if (rDst == bmpImage->red_mask) {
2050 /* ==== rgb 565 bmp -> rgb 565 dib ==== */
2051 /* ==== bgr 565 bmp -> bgr 565 dib ==== */
2052 convs->Convert_5x5_asis
2053 (dstwidth,lines,
2054 srcbits,-bmpImage->bytes_per_line,
2055 dstbits,linebytes);
2056 } else {
2057 /* ==== rgb 565 bmp -> bgr 565 dib ==== */
2058 /* ==== bgr 565 bmp -> rgb 565 dib ==== */
2059 convs->Convert_565_reverse
2060 (dstwidth,lines,
2061 srcbits,-bmpImage->bytes_per_line,
2062 dstbits,linebytes);
2064 } else {
2065 if (rDst==bmpImage->red_mask || bDst==bmpImage->blue_mask) {
2066 /* ==== rgb 565 bmp -> rgb 555 dib ==== */
2067 /* ==== bgr 565 bmp -> bgr 555 dib ==== */
2068 convs->Convert_565_to_555_asis
2069 (dstwidth,lines,
2070 srcbits,-bmpImage->bytes_per_line,
2071 dstbits,linebytes);
2072 } else {
2073 /* ==== rgb 565 bmp -> bgr 555 dib ==== */
2074 /* ==== bgr 565 bmp -> rgb 555 dib ==== */
2075 convs->Convert_565_to_555_reverse
2076 (dstwidth,lines,
2077 srcbits,-bmpImage->bytes_per_line,
2078 dstbits,linebytes);
2081 } else {
2082 goto notsupported;
2085 break;
2087 case 24:
2088 if (bmpImage->bits_per_pixel == 24) {
2089 const char* srcbits;
2091 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2093 if (bmpImage->green_mask!=0x00ff00 ||
2094 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2095 goto notsupported;
2096 } else if ((rDst==0x1f && bmpImage->red_mask==0xff) ||
2097 (bDst==0x1f && bmpImage->blue_mask==0xff)) {
2098 if (gDst==0x03e0) {
2099 /* ==== rgb 888 bmp -> rgb 555 dib ==== */
2100 /* ==== bgr 888 bmp -> bgr 555 dib ==== */
2101 convs->Convert_888_to_555_asis
2102 (dstwidth,lines,
2103 srcbits,-bmpImage->bytes_per_line,
2104 dstbits,linebytes);
2105 } else {
2106 /* ==== rgb 888 bmp -> rgb 565 dib ==== */
2107 /* ==== rgb 888 bmp -> rgb 565 dib ==== */
2108 convs->Convert_888_to_565_asis
2109 (dstwidth,lines,
2110 srcbits,-bmpImage->bytes_per_line,
2111 dstbits,linebytes);
2113 } else {
2114 if (gDst==0x03e0) {
2115 /* ==== rgb 888 bmp -> bgr 555 dib ==== */
2116 /* ==== bgr 888 bmp -> rgb 555 dib ==== */
2117 convs->Convert_888_to_555_reverse
2118 (dstwidth,lines,
2119 srcbits,-bmpImage->bytes_per_line,
2120 dstbits,linebytes);
2121 } else {
2122 /* ==== rgb 888 bmp -> bgr 565 dib ==== */
2123 /* ==== bgr 888 bmp -> rgb 565 dib ==== */
2124 convs->Convert_888_to_565_reverse
2125 (dstwidth,lines,
2126 srcbits,-bmpImage->bytes_per_line,
2127 dstbits,linebytes);
2130 break;
2132 /* Fall through */
2134 case 32:
2136 const char* srcbits;
2138 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2140 if (bmpImage->green_mask!=0x00ff00 ||
2141 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2142 goto notsupported;
2143 } else if ((rDst==0x1f && bmpImage->red_mask==0xff) ||
2144 (bDst==0x1f && bmpImage->blue_mask==0xff)) {
2145 if (gDst==0x03e0) {
2146 /* ==== rgb 0888 bmp -> rgb 555 dib ==== */
2147 /* ==== bgr 0888 bmp -> bgr 555 dib ==== */
2148 convs->Convert_0888_to_555_asis
2149 (dstwidth,lines,
2150 srcbits,-bmpImage->bytes_per_line,
2151 dstbits,linebytes);
2152 } else {
2153 /* ==== rgb 0888 bmp -> rgb 565 dib ==== */
2154 /* ==== bgr 0888 bmp -> bgr 565 dib ==== */
2155 convs->Convert_0888_to_565_asis
2156 (dstwidth,lines,
2157 srcbits,-bmpImage->bytes_per_line,
2158 dstbits,linebytes);
2160 } else {
2161 if (gDst==0x03e0) {
2162 /* ==== rgb 0888 bmp -> bgr 555 dib ==== */
2163 /* ==== bgr 0888 bmp -> rgb 555 dib ==== */
2164 convs->Convert_0888_to_555_reverse
2165 (dstwidth,lines,
2166 srcbits,-bmpImage->bytes_per_line,
2167 dstbits,linebytes);
2168 } else {
2169 /* ==== rgb 0888 bmp -> bgr 565 dib ==== */
2170 /* ==== bgr 0888 bmp -> rgb 565 dib ==== */
2171 convs->Convert_0888_to_565_reverse
2172 (dstwidth,lines,
2173 srcbits,-bmpImage->bytes_per_line,
2174 dstbits,linebytes);
2178 break;
2180 case 1:
2181 case 4:
2182 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
2183 /* ==== pal 1 or 4 bmp -> rgb or bgr 555 or 565 dib ==== */
2184 int rShift,gShift,bShift;
2185 WORD* dstpixel;
2187 /* Shift everything 16 bits left so that all shifts are >0,
2188 * even for BGR DIBs. Then a single >> 16 will bring everything
2189 * back into place.
2191 rShift=16+X11DRV_DIB_MaskToShift(rDst)-3;
2192 gShift=16+X11DRV_DIB_MaskToShift(gDst)-3;
2193 bShift=16+X11DRV_DIB_MaskToShift(bDst)-3;
2194 if (gDst==0x07e0) {
2195 /* 6 bits for the green */
2196 gShift++;
2198 rDst=rDst << 16;
2199 gDst=gDst << 16;
2200 bDst=bDst << 16;
2201 for (h = lines - 1; h >= 0; h--) {
2202 dstpixel=(LPWORD)dstbits;
2203 for (x = 0; x < dstwidth; x++) {
2204 PALETTEENTRY srcval;
2205 DWORD dstval;
2206 srcval=srccolors[XGetPixel(bmpImage, x, h)];
2207 dstval=((srcval.peRed << rShift) & rDst) |
2208 ((srcval.peGreen << gShift) & gDst) |
2209 ((srcval.peBlue << bShift) & bDst);
2210 *dstpixel++=dstval >> 16;
2212 dstbits += linebytes;
2214 } else {
2215 goto notsupported;
2217 break;
2219 case 8:
2220 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
2221 /* ==== pal 8 bmp -> rgb or bgr 555 or 565 dib ==== */
2222 int rShift,gShift,bShift;
2223 const BYTE* srcbits;
2224 const BYTE* srcpixel;
2225 WORD* dstpixel;
2227 /* Shift everything 16 bits left so that all shifts are >0,
2228 * even for BGR DIBs. Then a single >> 16 will bring everything
2229 * back into place.
2231 rShift=16+X11DRV_DIB_MaskToShift(rDst)-3;
2232 gShift=16+X11DRV_DIB_MaskToShift(gDst)-3;
2233 bShift=16+X11DRV_DIB_MaskToShift(bDst)-3;
2234 if (gDst==0x07e0) {
2235 /* 6 bits for the green */
2236 gShift++;
2238 rDst=rDst << 16;
2239 gDst=gDst << 16;
2240 bDst=bDst << 16;
2241 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2242 for (h=0; h<lines; h++) {
2243 srcpixel=srcbits;
2244 dstpixel=(LPWORD)dstbits;
2245 for (x = 0; x < dstwidth; x++) {
2246 PALETTEENTRY srcval;
2247 DWORD dstval;
2248 srcval=srccolors[(int)*srcpixel++];
2249 dstval=((srcval.peRed << rShift) & rDst) |
2250 ((srcval.peGreen << gShift) & gDst) |
2251 ((srcval.peBlue << bShift) & bDst);
2252 *dstpixel++=dstval >> 16;
2254 srcbits -= bmpImage->bytes_per_line;
2255 dstbits += linebytes;
2257 } else {
2258 goto notsupported;
2260 break;
2262 default:
2263 notsupported:
2265 /* ==== any bmp format -> rgb or bgr 555 or 565 dib ==== */
2266 int rShift,gShift,bShift;
2267 WORD* dstpixel;
2269 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 16 bit DIB (%lx,%lx,%lx)\n",
2270 bmpImage->depth, bmpImage->red_mask,
2271 bmpImage->green_mask, bmpImage->blue_mask,
2272 rDst, gDst, bDst);
2274 /* Shift everything 16 bits left so that all shifts are >0,
2275 * even for BGR DIBs. Then a single >> 16 will bring everything
2276 * back into place.
2278 rShift=16+X11DRV_DIB_MaskToShift(rDst)-3;
2279 gShift=16+X11DRV_DIB_MaskToShift(gDst)-3;
2280 bShift=16+X11DRV_DIB_MaskToShift(bDst)-3;
2281 if (gDst==0x07e0) {
2282 /* 6 bits for the green */
2283 gShift++;
2285 rDst=rDst << 16;
2286 gDst=gDst << 16;
2287 bDst=bDst << 16;
2288 for (h = lines - 1; h >= 0; h--) {
2289 dstpixel=(LPWORD)dstbits;
2290 for (x = 0; x < dstwidth; x++) {
2291 COLORREF srcval;
2292 DWORD dstval;
2293 srcval=X11DRV_PALETTE_ToLogical(XGetPixel(bmpImage, x, h));
2294 dstval=((GetRValue(srcval) << rShift) & rDst) |
2295 ((GetGValue(srcval) << gShift) & gDst) |
2296 ((GetBValue(srcval) << bShift) & bDst);
2297 *dstpixel++=dstval >> 16;
2299 dstbits += linebytes;
2302 break;
2307 /***********************************************************************
2308 * X11DRV_DIB_SetImageBits_24
2310 * SetDIBits for a 24-bit deep DIB.
2312 static void X11DRV_DIB_SetImageBits_24( int lines, const BYTE *srcbits,
2313 DWORD srcwidth, DWORD dstwidth, int left,
2314 X11DRV_PDEVICE *physDev,
2315 DWORD rSrc, DWORD gSrc, DWORD bSrc,
2316 XImage *bmpImage, DWORD linebytes )
2318 DWORD x;
2319 int h;
2320 const dib_conversions *convs = (bmpImage->byte_order == LSBFirst) ? &dib_normal : &dib_dst_byteswap;
2322 if (lines < 0 )
2324 lines = -lines;
2325 srcbits = srcbits + linebytes * (lines - 1);
2326 linebytes = -linebytes;
2329 switch (bmpImage->depth)
2331 case 24:
2332 if (bmpImage->bits_per_pixel==24) {
2333 char* dstbits;
2335 srcbits=srcbits+left*3;
2336 dstbits=bmpImage->data+left*3+(lines-1)*bmpImage->bytes_per_line;
2338 if (bmpImage->green_mask!=0x00ff00 ||
2339 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2340 goto notsupported;
2341 } else if (rSrc==bmpImage->red_mask) {
2342 /* ==== rgb 888 dib -> rgb 888 bmp ==== */
2343 /* ==== bgr 888 dib -> bgr 888 bmp ==== */
2344 convs->Convert_888_asis
2345 (dstwidth,lines,
2346 srcbits,linebytes,
2347 dstbits,-bmpImage->bytes_per_line);
2348 } else {
2349 /* ==== rgb 888 dib -> bgr 888 bmp ==== */
2350 /* ==== bgr 888 dib -> rgb 888 bmp ==== */
2351 convs->Convert_888_reverse
2352 (dstwidth,lines,
2353 srcbits,linebytes,
2354 dstbits,-bmpImage->bytes_per_line);
2356 break;
2358 /* fall through */
2360 case 32:
2362 char* dstbits;
2364 srcbits=srcbits+left*3;
2365 dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
2367 if (bmpImage->green_mask!=0x00ff00 ||
2368 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2369 goto notsupported;
2370 } else if (rSrc==bmpImage->red_mask) {
2371 /* ==== rgb 888 dib -> rgb 0888 bmp ==== */
2372 /* ==== bgr 888 dib -> bgr 0888 bmp ==== */
2373 convs->Convert_888_to_0888_asis
2374 (dstwidth,lines,
2375 srcbits,linebytes,
2376 dstbits,-bmpImage->bytes_per_line);
2377 } else {
2378 /* ==== rgb 888 dib -> bgr 0888 bmp ==== */
2379 /* ==== bgr 888 dib -> rgb 0888 bmp ==== */
2380 convs->Convert_888_to_0888_reverse
2381 (dstwidth,lines,
2382 srcbits,linebytes,
2383 dstbits,-bmpImage->bytes_per_line);
2385 break;
2388 case 15:
2389 case 16:
2391 char* dstbits;
2393 srcbits=srcbits+left*3;
2394 dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
2396 if (bmpImage->green_mask==0x03e0) {
2397 if ((rSrc==0xff0000 && bmpImage->red_mask==0x7f00) ||
2398 (bSrc==0xff0000 && bmpImage->blue_mask==0x7f00)) {
2399 /* ==== rgb 888 dib -> rgb 555 bmp ==== */
2400 /* ==== bgr 888 dib -> bgr 555 bmp ==== */
2401 convs->Convert_888_to_555_asis
2402 (dstwidth,lines,
2403 srcbits,linebytes,
2404 dstbits,-bmpImage->bytes_per_line);
2405 } else if ((rSrc==0xff && bmpImage->red_mask==0x7f00) ||
2406 (bSrc==0xff && bmpImage->blue_mask==0x7f00)) {
2407 /* ==== rgb 888 dib -> bgr 555 bmp ==== */
2408 /* ==== bgr 888 dib -> rgb 555 bmp ==== */
2409 convs->Convert_888_to_555_reverse
2410 (dstwidth,lines,
2411 srcbits,linebytes,
2412 dstbits,-bmpImage->bytes_per_line);
2413 } else {
2414 goto notsupported;
2416 } else if (bmpImage->green_mask==0x07e0) {
2417 if ((rSrc==0xff0000 && bmpImage->red_mask==0xf800) ||
2418 (bSrc==0xff0000 && bmpImage->blue_mask==0xf800)) {
2419 /* ==== rgb 888 dib -> rgb 565 bmp ==== */
2420 /* ==== bgr 888 dib -> bgr 565 bmp ==== */
2421 convs->Convert_888_to_565_asis
2422 (dstwidth,lines,
2423 srcbits,linebytes,
2424 dstbits,-bmpImage->bytes_per_line);
2425 } else if ((rSrc==0xff && bmpImage->red_mask==0xf800) ||
2426 (bSrc==0xff && bmpImage->blue_mask==0xf800)) {
2427 /* ==== rgb 888 dib -> bgr 565 bmp ==== */
2428 /* ==== bgr 888 dib -> rgb 565 bmp ==== */
2429 convs->Convert_888_to_565_reverse
2430 (dstwidth,lines,
2431 srcbits,linebytes,
2432 dstbits,-bmpImage->bytes_per_line);
2433 } else {
2434 goto notsupported;
2436 } else {
2437 goto notsupported;
2440 break;
2442 default:
2443 notsupported:
2444 WARN("from 24 bit DIB (%lx,%lx,%lx) to unknown %d bit bitmap (%lx,%lx,%lx)\n",
2445 rSrc, gSrc, bSrc, bmpImage->bits_per_pixel, bmpImage->red_mask,
2446 bmpImage->green_mask, bmpImage->blue_mask );
2447 /* fall through */
2448 case 1:
2449 case 4:
2450 case 8:
2452 /* ==== rgb 888 dib -> any bmp bormat ==== */
2453 const BYTE* srcbyte;
2455 /* Windows only supports one 24bpp DIB format: RGB888 */
2456 srcbits+=left*3;
2457 for (h = lines - 1; h >= 0; h--) {
2458 srcbyte=(const BYTE*)srcbits;
2459 for (x = left; x < dstwidth+left; x++) {
2460 XPutPixel(bmpImage, x, h,
2461 X11DRV_PALETTE_ToPhysical
2462 (physDev, RGB(srcbyte[2], srcbyte[1], srcbyte[0])));
2463 srcbyte+=3;
2465 srcbits += linebytes;
2468 break;
2473 /***********************************************************************
2474 * X11DRV_DIB_GetImageBits_24
2476 * GetDIBits for an 24-bit deep DIB.
2478 static void X11DRV_DIB_GetImageBits_24( int lines, BYTE *dstbits,
2479 DWORD dstwidth, DWORD srcwidth,
2480 PALETTEENTRY *srccolors,
2481 DWORD rDst, DWORD gDst, DWORD bDst,
2482 XImage *bmpImage, DWORD linebytes )
2484 DWORD x;
2485 int h;
2486 const dib_conversions *convs = (bmpImage->byte_order == LSBFirst) ? &dib_normal : &dib_src_byteswap;
2488 if (lines < 0 )
2490 lines = -lines;
2491 dstbits = dstbits + ( linebytes * (lines-1) );
2492 linebytes = -linebytes;
2495 switch (bmpImage->depth)
2497 case 24:
2498 if (bmpImage->bits_per_pixel==24) {
2499 const char* srcbits;
2501 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2503 if (bmpImage->green_mask!=0x00ff00 ||
2504 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2505 goto notsupported;
2506 } else if (rDst==bmpImage->red_mask) {
2507 /* ==== rgb 888 bmp -> rgb 888 dib ==== */
2508 /* ==== bgr 888 bmp -> bgr 888 dib ==== */
2509 convs->Convert_888_asis
2510 (dstwidth,lines,
2511 srcbits,-bmpImage->bytes_per_line,
2512 dstbits,linebytes);
2513 } else {
2514 /* ==== rgb 888 bmp -> bgr 888 dib ==== */
2515 /* ==== bgr 888 bmp -> rgb 888 dib ==== */
2516 convs->Convert_888_reverse
2517 (dstwidth,lines,
2518 srcbits,-bmpImage->bytes_per_line,
2519 dstbits,linebytes);
2521 break;
2523 /* fall through */
2525 case 32:
2527 const char* srcbits;
2529 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2531 if (bmpImage->green_mask!=0x00ff00 ||
2532 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2533 goto notsupported;
2534 } else if (rDst==bmpImage->red_mask) {
2535 /* ==== rgb 888 bmp -> rgb 0888 dib ==== */
2536 /* ==== bgr 888 bmp -> bgr 0888 dib ==== */
2537 convs->Convert_0888_to_888_asis
2538 (dstwidth,lines,
2539 srcbits,-bmpImage->bytes_per_line,
2540 dstbits,linebytes);
2541 } else {
2542 /* ==== rgb 888 bmp -> bgr 0888 dib ==== */
2543 /* ==== bgr 888 bmp -> rgb 0888 dib ==== */
2544 convs->Convert_0888_to_888_reverse
2545 (dstwidth,lines,
2546 srcbits,-bmpImage->bytes_per_line,
2547 dstbits,linebytes);
2549 break;
2552 case 15:
2553 case 16:
2555 const char* srcbits;
2557 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2559 if (bmpImage->green_mask==0x03e0) {
2560 if ((rDst==0xff0000 && bmpImage->red_mask==0x7f00) ||
2561 (bDst==0xff0000 && bmpImage->blue_mask==0x7f00)) {
2562 /* ==== rgb 555 bmp -> rgb 888 dib ==== */
2563 /* ==== bgr 555 bmp -> bgr 888 dib ==== */
2564 convs->Convert_555_to_888_asis
2565 (dstwidth,lines,
2566 srcbits,-bmpImage->bytes_per_line,
2567 dstbits,linebytes);
2568 } else if ((rDst==0xff && bmpImage->red_mask==0x7f00) ||
2569 (bDst==0xff && bmpImage->blue_mask==0x7f00)) {
2570 /* ==== rgb 555 bmp -> bgr 888 dib ==== */
2571 /* ==== bgr 555 bmp -> rgb 888 dib ==== */
2572 convs->Convert_555_to_888_reverse
2573 (dstwidth,lines,
2574 srcbits,-bmpImage->bytes_per_line,
2575 dstbits,linebytes);
2576 } else {
2577 goto notsupported;
2579 } else if (bmpImage->green_mask==0x07e0) {
2580 if ((rDst==0xff0000 && bmpImage->red_mask==0xf800) ||
2581 (bDst==0xff0000 && bmpImage->blue_mask==0xf800)) {
2582 /* ==== rgb 565 bmp -> rgb 888 dib ==== */
2583 /* ==== bgr 565 bmp -> bgr 888 dib ==== */
2584 convs->Convert_565_to_888_asis
2585 (dstwidth,lines,
2586 srcbits,-bmpImage->bytes_per_line,
2587 dstbits,linebytes);
2588 } else if ((rDst==0xff && bmpImage->red_mask==0xf800) ||
2589 (bDst==0xff && bmpImage->blue_mask==0xf800)) {
2590 /* ==== rgb 565 bmp -> bgr 888 dib ==== */
2591 /* ==== bgr 565 bmp -> rgb 888 dib ==== */
2592 convs->Convert_565_to_888_reverse
2593 (dstwidth,lines,
2594 srcbits,-bmpImage->bytes_per_line,
2595 dstbits,linebytes);
2596 } else {
2597 goto notsupported;
2599 } else {
2600 goto notsupported;
2603 break;
2605 case 1:
2606 case 4:
2607 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
2608 /* ==== pal 1 or 4 bmp -> rgb 888 dib ==== */
2609 BYTE* dstbyte;
2611 /* Windows only supports one 24bpp DIB format: rgb 888 */
2612 for (h = lines - 1; h >= 0; h--) {
2613 dstbyte=dstbits;
2614 for (x = 0; x < dstwidth; x++) {
2615 PALETTEENTRY srcval;
2616 srcval=srccolors[XGetPixel(bmpImage, x, h)];
2617 dstbyte[0]=srcval.peBlue;
2618 dstbyte[1]=srcval.peGreen;
2619 dstbyte[2]=srcval.peRed;
2620 dstbyte+=3;
2622 dstbits += linebytes;
2624 } else {
2625 goto notsupported;
2627 break;
2629 case 8:
2630 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask == 0 && srccolors) {
2631 /* ==== pal 8 bmp -> rgb 888 dib ==== */
2632 const void* srcbits;
2633 const BYTE* srcpixel;
2634 BYTE* dstbyte;
2636 /* Windows only supports one 24bpp DIB format: rgb 888 */
2637 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2638 for (h = lines - 1; h >= 0; h--) {
2639 srcpixel=srcbits;
2640 dstbyte=dstbits;
2641 for (x = 0; x < dstwidth; x++ ) {
2642 PALETTEENTRY srcval;
2643 srcval=srccolors[(int)*srcpixel++];
2644 dstbyte[0]=srcval.peBlue;
2645 dstbyte[1]=srcval.peGreen;
2646 dstbyte[2]=srcval.peRed;
2647 dstbyte+=3;
2649 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2650 dstbits += linebytes;
2652 } else {
2653 goto notsupported;
2655 break;
2657 default:
2658 notsupported:
2660 /* ==== any bmp format -> 888 dib ==== */
2661 BYTE* dstbyte;
2663 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 24 bit DIB (%lx,%lx,%lx)\n",
2664 bmpImage->depth, bmpImage->red_mask,
2665 bmpImage->green_mask, bmpImage->blue_mask,
2666 rDst, gDst, bDst );
2668 /* Windows only supports one 24bpp DIB format: rgb 888 */
2669 for (h = lines - 1; h >= 0; h--) {
2670 dstbyte=dstbits;
2671 for (x = 0; x < dstwidth; x++) {
2672 COLORREF srcval=X11DRV_PALETTE_ToLogical
2673 (XGetPixel( bmpImage, x, h ));
2674 dstbyte[0]=GetBValue(srcval);
2675 dstbyte[1]=GetGValue(srcval);
2676 dstbyte[2]=GetRValue(srcval);
2677 dstbyte+=3;
2679 dstbits += linebytes;
2682 break;
2687 /***********************************************************************
2688 * X11DRV_DIB_SetImageBits_32
2690 * SetDIBits for a 32-bit deep DIB.
2692 static void X11DRV_DIB_SetImageBits_32(int lines, const BYTE *srcbits,
2693 DWORD srcwidth, DWORD dstwidth, int left,
2694 X11DRV_PDEVICE *physDev,
2695 DWORD rSrc, DWORD gSrc, DWORD bSrc,
2696 XImage *bmpImage,
2697 DWORD linebytes)
2699 DWORD x, *ptr;
2700 int h;
2701 const dib_conversions *convs = (bmpImage->byte_order == LSBFirst) ? &dib_normal : &dib_dst_byteswap;
2703 if (lines < 0 )
2705 lines = -lines;
2706 srcbits = srcbits + ( linebytes * (lines-1) );
2707 linebytes = -linebytes;
2710 ptr = (DWORD *) srcbits + left;
2712 switch (bmpImage->depth)
2714 case 24:
2715 if (bmpImage->bits_per_pixel==24) {
2716 char* dstbits;
2718 srcbits=srcbits+left*4;
2719 dstbits=bmpImage->data+left*3+(lines-1)*bmpImage->bytes_per_line;
2721 if (rSrc==bmpImage->red_mask && gSrc==bmpImage->green_mask && bSrc==bmpImage->blue_mask) {
2722 /* ==== rgb 0888 dib -> rgb 888 bmp ==== */
2723 /* ==== bgr 0888 dib -> bgr 888 bmp ==== */
2724 convs->Convert_0888_to_888_asis
2725 (dstwidth,lines,
2726 srcbits,linebytes,
2727 dstbits,-bmpImage->bytes_per_line);
2728 } else if (bmpImage->green_mask!=0x00ff00 ||
2729 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2730 goto notsupported;
2731 /* the tests below assume sane bmpImage masks */
2732 } else if (rSrc==bmpImage->blue_mask && gSrc==bmpImage->green_mask && bSrc==bmpImage->red_mask) {
2733 /* ==== rgb 0888 dib -> bgr 888 bmp ==== */
2734 /* ==== bgr 0888 dib -> rgb 888 bmp ==== */
2735 convs->Convert_0888_to_888_reverse
2736 (dstwidth,lines,
2737 srcbits,linebytes,
2738 dstbits,-bmpImage->bytes_per_line);
2739 } else if (bmpImage->blue_mask==0xff) {
2740 /* ==== any 0888 dib -> rgb 888 bmp ==== */
2741 convs->Convert_any0888_to_rgb888
2742 (dstwidth,lines,
2743 srcbits,linebytes,
2744 rSrc,gSrc,bSrc,
2745 dstbits,-bmpImage->bytes_per_line);
2746 } else {
2747 /* ==== any 0888 dib -> bgr 888 bmp ==== */
2748 convs->Convert_any0888_to_bgr888
2749 (dstwidth,lines,
2750 srcbits,linebytes,
2751 rSrc,gSrc,bSrc,
2752 dstbits,-bmpImage->bytes_per_line);
2754 break;
2756 /* fall through */
2758 case 32:
2760 char* dstbits;
2762 srcbits=srcbits+left*4;
2763 dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
2765 if (gSrc==bmpImage->green_mask) {
2766 if (rSrc==bmpImage->red_mask && bSrc==bmpImage->blue_mask) {
2767 /* ==== rgb 0888 dib -> rgb 0888 bmp ==== */
2768 /* ==== bgr 0888 dib -> bgr 0888 bmp ==== */
2769 convs->Convert_0888_asis
2770 (dstwidth,lines,
2771 srcbits,linebytes,
2772 dstbits,-bmpImage->bytes_per_line);
2773 } else if (bmpImage->green_mask!=0x00ff00 ||
2774 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2775 goto notsupported;
2776 /* the tests below assume sane bmpImage masks */
2777 } else if (rSrc==bmpImage->blue_mask && bSrc==bmpImage->red_mask) {
2778 /* ==== rgb 0888 dib -> bgr 0888 bmp ==== */
2779 /* ==== bgr 0888 dib -> rgb 0888 bmp ==== */
2780 convs->Convert_0888_reverse
2781 (dstwidth,lines,
2782 srcbits,linebytes,
2783 dstbits,-bmpImage->bytes_per_line);
2784 } else {
2785 /* ==== any 0888 dib -> any 0888 bmp ==== */
2786 convs->Convert_0888_any
2787 (dstwidth,lines,
2788 srcbits,linebytes,
2789 rSrc,gSrc,bSrc,
2790 dstbits,-bmpImage->bytes_per_line,
2791 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
2793 } else if (bmpImage->green_mask!=0x00ff00 ||
2794 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2795 goto notsupported;
2796 /* the tests below assume sane bmpImage masks */
2797 } else {
2798 /* ==== any 0888 dib -> any 0888 bmp ==== */
2799 convs->Convert_0888_any
2800 (dstwidth,lines,
2801 srcbits,linebytes,
2802 rSrc,gSrc,bSrc,
2803 dstbits,-bmpImage->bytes_per_line,
2804 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
2807 break;
2809 case 15:
2810 case 16:
2812 char* dstbits;
2814 srcbits=srcbits+left*4;
2815 dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
2817 if (rSrc==0xff0000 && gSrc==0x00ff00 && bSrc==0x0000ff) {
2818 if (bmpImage->green_mask==0x03e0) {
2819 if (bmpImage->red_mask==0x7f00) {
2820 /* ==== rgb 0888 dib -> rgb 555 bmp ==== */
2821 convs->Convert_0888_to_555_asis
2822 (dstwidth,lines,
2823 srcbits,linebytes,
2824 dstbits,-bmpImage->bytes_per_line);
2825 } else if (bmpImage->blue_mask==0x7f00) {
2826 /* ==== rgb 0888 dib -> bgr 555 bmp ==== */
2827 convs->Convert_0888_to_555_reverse
2828 (dstwidth,lines,
2829 srcbits,linebytes,
2830 dstbits,-bmpImage->bytes_per_line);
2831 } else {
2832 goto notsupported;
2834 } else if (bmpImage->green_mask==0x07e0) {
2835 if (bmpImage->red_mask==0xf800) {
2836 /* ==== rgb 0888 dib -> rgb 565 bmp ==== */
2837 convs->Convert_0888_to_565_asis
2838 (dstwidth,lines,
2839 srcbits,linebytes,
2840 dstbits,-bmpImage->bytes_per_line);
2841 } else if (bmpImage->blue_mask==0xf800) {
2842 /* ==== rgb 0888 dib -> bgr 565 bmp ==== */
2843 convs->Convert_0888_to_565_reverse
2844 (dstwidth,lines,
2845 srcbits,linebytes,
2846 dstbits,-bmpImage->bytes_per_line);
2847 } else {
2848 goto notsupported;
2850 } else {
2851 goto notsupported;
2853 } else if (rSrc==0x0000ff && gSrc==0x00ff00 && bSrc==0xff0000) {
2854 if (bmpImage->green_mask==0x03e0) {
2855 if (bmpImage->blue_mask==0x7f00) {
2856 /* ==== bgr 0888 dib -> bgr 555 bmp ==== */
2857 convs->Convert_0888_to_555_asis
2858 (dstwidth,lines,
2859 srcbits,linebytes,
2860 dstbits,-bmpImage->bytes_per_line);
2861 } else if (bmpImage->red_mask==0x7f00) {
2862 /* ==== bgr 0888 dib -> rgb 555 bmp ==== */
2863 convs->Convert_0888_to_555_reverse
2864 (dstwidth,lines,
2865 srcbits,linebytes,
2866 dstbits,-bmpImage->bytes_per_line);
2867 } else {
2868 goto notsupported;
2870 } else if (bmpImage->green_mask==0x07e0) {
2871 if (bmpImage->blue_mask==0xf800) {
2872 /* ==== bgr 0888 dib -> bgr 565 bmp ==== */
2873 convs->Convert_0888_to_565_asis
2874 (dstwidth,lines,
2875 srcbits,linebytes,
2876 dstbits,-bmpImage->bytes_per_line);
2877 } else if (bmpImage->red_mask==0xf800) {
2878 /* ==== bgr 0888 dib -> rgb 565 bmp ==== */
2879 convs->Convert_0888_to_565_reverse
2880 (dstwidth,lines,
2881 srcbits,linebytes,
2882 dstbits,-bmpImage->bytes_per_line);
2883 } else {
2884 goto notsupported;
2886 } else {
2887 goto notsupported;
2889 } else {
2890 if (bmpImage->green_mask==0x03e0 &&
2891 (bmpImage->red_mask==0x7f00 ||
2892 bmpImage->blue_mask==0x7f00)) {
2893 /* ==== any 0888 dib -> rgb or bgr 555 bmp ==== */
2894 convs->Convert_any0888_to_5x5
2895 (dstwidth,lines,
2896 srcbits,linebytes,
2897 rSrc,gSrc,bSrc,
2898 dstbits,-bmpImage->bytes_per_line,
2899 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
2900 } else if (bmpImage->green_mask==0x07e0 &&
2901 (bmpImage->red_mask==0xf800 ||
2902 bmpImage->blue_mask==0xf800)) {
2903 /* ==== any 0888 dib -> rgb or bgr 565 bmp ==== */
2904 convs->Convert_any0888_to_5x5
2905 (dstwidth,lines,
2906 srcbits,linebytes,
2907 rSrc,gSrc,bSrc,
2908 dstbits,-bmpImage->bytes_per_line,
2909 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
2910 } else {
2911 goto notsupported;
2915 break;
2917 default:
2918 notsupported:
2919 WARN("from 32 bit DIB (%lx,%lx,%lx) to unknown %d bit bitmap (%lx,%lx,%lx)\n",
2920 rSrc, gSrc, bSrc, bmpImage->bits_per_pixel, bmpImage->red_mask,
2921 bmpImage->green_mask, bmpImage->blue_mask );
2922 /* fall through */
2923 case 1:
2924 case 4:
2925 case 8:
2927 /* ==== any 0888 dib -> pal 1, 4 or 8 bmp ==== */
2928 const DWORD* srcpixel;
2929 int rShift,gShift,bShift;
2931 rShift=X11DRV_DIB_MaskToShift(rSrc);
2932 gShift=X11DRV_DIB_MaskToShift(gSrc);
2933 bShift=X11DRV_DIB_MaskToShift(bSrc);
2934 srcbits+=left*4;
2935 for (h = lines - 1; h >= 0; h--) {
2936 srcpixel=(const DWORD*)srcbits;
2937 for (x = left; x < dstwidth+left; x++) {
2938 DWORD srcvalue;
2939 BYTE red,green,blue;
2940 srcvalue=*srcpixel++;
2941 red= (srcvalue >> rShift) & 0xff;
2942 green=(srcvalue >> gShift) & 0xff;
2943 blue= (srcvalue >> bShift) & 0xff;
2944 XPutPixel(bmpImage, x, h, X11DRV_PALETTE_ToPhysical
2945 (physDev, RGB(red,green,blue)));
2947 srcbits += linebytes;
2950 break;
2955 /***********************************************************************
2956 * X11DRV_DIB_GetImageBits_32
2958 * GetDIBits for an 32-bit deep DIB.
2960 static void X11DRV_DIB_GetImageBits_32( int lines, BYTE *dstbits,
2961 DWORD dstwidth, DWORD srcwidth,
2962 PALETTEENTRY *srccolors,
2963 DWORD rDst, DWORD gDst, DWORD bDst,
2964 XImage *bmpImage, DWORD linebytes )
2966 DWORD x;
2967 int h;
2968 BYTE *bits;
2969 const dib_conversions *convs = (bmpImage->byte_order == LSBFirst) ? &dib_normal : &dib_src_byteswap;
2971 if (lines < 0 )
2973 lines = -lines;
2974 dstbits = dstbits + ( linebytes * (lines-1) );
2975 linebytes = -linebytes;
2978 bits = dstbits;
2980 switch (bmpImage->depth)
2982 case 24:
2983 if (bmpImage->bits_per_pixel==24) {
2984 const void* srcbits;
2986 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2988 if (rDst==bmpImage->red_mask && gDst==bmpImage->green_mask && bDst==bmpImage->blue_mask) {
2989 /* ==== rgb 888 bmp -> rgb 0888 dib ==== */
2990 /* ==== bgr 888 bmp -> bgr 0888 dib ==== */
2991 convs->Convert_888_to_0888_asis
2992 (dstwidth,lines,
2993 srcbits,-bmpImage->bytes_per_line,
2994 dstbits,linebytes);
2995 } else if (bmpImage->green_mask!=0x00ff00 ||
2996 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2997 goto notsupported;
2998 /* the tests below assume sane bmpImage masks */
2999 } else if (rDst==bmpImage->blue_mask && gDst==bmpImage->green_mask && bDst==bmpImage->red_mask) {
3000 /* ==== rgb 888 bmp -> bgr 0888 dib ==== */
3001 /* ==== bgr 888 bmp -> rgb 0888 dib ==== */
3002 convs->Convert_888_to_0888_reverse
3003 (dstwidth,lines,
3004 srcbits,-bmpImage->bytes_per_line,
3005 dstbits,linebytes);
3006 } else if (bmpImage->blue_mask==0xff) {
3007 /* ==== rgb 888 bmp -> any 0888 dib ==== */
3008 convs->Convert_rgb888_to_any0888
3009 (dstwidth,lines,
3010 srcbits,-bmpImage->bytes_per_line,
3011 dstbits,linebytes,
3012 rDst,gDst,bDst);
3013 } else {
3014 /* ==== bgr 888 bmp -> any 0888 dib ==== */
3015 convs->Convert_bgr888_to_any0888
3016 (dstwidth,lines,
3017 srcbits,-bmpImage->bytes_per_line,
3018 dstbits,linebytes,
3019 rDst,gDst,bDst);
3021 break;
3023 /* fall through */
3025 case 32:
3027 const char* srcbits;
3029 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3031 if (gDst==bmpImage->green_mask) {
3032 if (rDst==bmpImage->red_mask && bDst==bmpImage->blue_mask) {
3033 /* ==== rgb 0888 bmp -> rgb 0888 dib ==== */
3034 /* ==== bgr 0888 bmp -> bgr 0888 dib ==== */
3035 convs->Convert_0888_asis
3036 (dstwidth,lines,
3037 srcbits,-bmpImage->bytes_per_line,
3038 dstbits,linebytes);
3039 } else if (bmpImage->green_mask!=0x00ff00 ||
3040 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3041 goto notsupported;
3042 /* the tests below assume sane bmpImage masks */
3043 } else if (rDst==bmpImage->blue_mask && bDst==bmpImage->red_mask) {
3044 /* ==== rgb 0888 bmp -> bgr 0888 dib ==== */
3045 /* ==== bgr 0888 bmp -> rgb 0888 dib ==== */
3046 convs->Convert_0888_reverse
3047 (dstwidth,lines,
3048 srcbits,-bmpImage->bytes_per_line,
3049 dstbits,linebytes);
3050 } else {
3051 /* ==== any 0888 bmp -> any 0888 dib ==== */
3052 convs->Convert_0888_any
3053 (dstwidth,lines,
3054 srcbits,-bmpImage->bytes_per_line,
3055 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
3056 dstbits,linebytes,
3057 rDst,gDst,bDst);
3059 } else if (bmpImage->green_mask!=0x00ff00 ||
3060 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3061 goto notsupported;
3062 /* the tests below assume sane bmpImage masks */
3063 } else {
3064 /* ==== any 0888 bmp -> any 0888 dib ==== */
3065 convs->Convert_0888_any
3066 (dstwidth,lines,
3067 srcbits,-bmpImage->bytes_per_line,
3068 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
3069 dstbits,linebytes,
3070 rDst,gDst,bDst);
3073 break;
3075 case 15:
3076 case 16:
3078 const char* srcbits;
3080 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3082 if (rDst==0xff0000 && gDst==0x00ff00 && bDst==0x0000ff) {
3083 if (bmpImage->green_mask==0x03e0) {
3084 if (bmpImage->red_mask==0x7f00) {
3085 /* ==== rgb 555 bmp -> rgb 0888 dib ==== */
3086 convs->Convert_555_to_0888_asis
3087 (dstwidth,lines,
3088 srcbits,-bmpImage->bytes_per_line,
3089 dstbits,linebytes);
3090 } else if (bmpImage->blue_mask==0x7f00) {
3091 /* ==== bgr 555 bmp -> rgb 0888 dib ==== */
3092 convs->Convert_555_to_0888_reverse
3093 (dstwidth,lines,
3094 srcbits,-bmpImage->bytes_per_line,
3095 dstbits,linebytes);
3096 } else {
3097 goto notsupported;
3099 } else if (bmpImage->green_mask==0x07e0) {
3100 if (bmpImage->red_mask==0xf800) {
3101 /* ==== rgb 565 bmp -> rgb 0888 dib ==== */
3102 convs->Convert_565_to_0888_asis
3103 (dstwidth,lines,
3104 srcbits,-bmpImage->bytes_per_line,
3105 dstbits,linebytes);
3106 } else if (bmpImage->blue_mask==0xf800) {
3107 /* ==== bgr 565 bmp -> rgb 0888 dib ==== */
3108 convs->Convert_565_to_0888_reverse
3109 (dstwidth,lines,
3110 srcbits,-bmpImage->bytes_per_line,
3111 dstbits,linebytes);
3112 } else {
3113 goto notsupported;
3115 } else {
3116 goto notsupported;
3118 } else if (rDst==0x0000ff && gDst==0x00ff00 && bDst==0xff0000) {
3119 if (bmpImage->green_mask==0x03e0) {
3120 if (bmpImage->blue_mask==0x7f00) {
3121 /* ==== bgr 555 bmp -> bgr 0888 dib ==== */
3122 convs->Convert_555_to_0888_asis
3123 (dstwidth,lines,
3124 srcbits,-bmpImage->bytes_per_line,
3125 dstbits,linebytes);
3126 } else if (bmpImage->red_mask==0x7f00) {
3127 /* ==== rgb 555 bmp -> bgr 0888 dib ==== */
3128 convs->Convert_555_to_0888_reverse
3129 (dstwidth,lines,
3130 srcbits,-bmpImage->bytes_per_line,
3131 dstbits,linebytes);
3132 } else {
3133 goto notsupported;
3135 } else if (bmpImage->green_mask==0x07e0) {
3136 if (bmpImage->blue_mask==0xf800) {
3137 /* ==== bgr 565 bmp -> bgr 0888 dib ==== */
3138 convs->Convert_565_to_0888_asis
3139 (dstwidth,lines,
3140 srcbits,-bmpImage->bytes_per_line,
3141 dstbits,linebytes);
3142 } else if (bmpImage->red_mask==0xf800) {
3143 /* ==== rgb 565 bmp -> bgr 0888 dib ==== */
3144 convs->Convert_565_to_0888_reverse
3145 (dstwidth,lines,
3146 srcbits,-bmpImage->bytes_per_line,
3147 dstbits,linebytes);
3148 } else {
3149 goto notsupported;
3151 } else {
3152 goto notsupported;
3154 } else {
3155 if (bmpImage->green_mask==0x03e0 &&
3156 (bmpImage->red_mask==0x7f00 ||
3157 bmpImage->blue_mask==0x7f00)) {
3158 /* ==== rgb or bgr 555 bmp -> any 0888 dib ==== */
3159 convs->Convert_5x5_to_any0888
3160 (dstwidth,lines,
3161 srcbits,-bmpImage->bytes_per_line,
3162 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
3163 dstbits,linebytes,
3164 rDst,gDst,bDst);
3165 } else if (bmpImage->green_mask==0x07e0 &&
3166 (bmpImage->red_mask==0xf800 ||
3167 bmpImage->blue_mask==0xf800)) {
3168 /* ==== rgb or bgr 565 bmp -> any 0888 dib ==== */
3169 convs->Convert_5x5_to_any0888
3170 (dstwidth,lines,
3171 srcbits,-bmpImage->bytes_per_line,
3172 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
3173 dstbits,linebytes,
3174 rDst,gDst,bDst);
3175 } else {
3176 goto notsupported;
3180 break;
3182 case 1:
3183 case 4:
3184 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
3185 /* ==== pal 1 or 4 bmp -> any 0888 dib ==== */
3186 int rShift,gShift,bShift;
3187 DWORD* dstpixel;
3189 rShift=X11DRV_DIB_MaskToShift(rDst);
3190 gShift=X11DRV_DIB_MaskToShift(gDst);
3191 bShift=X11DRV_DIB_MaskToShift(bDst);
3192 for (h = lines - 1; h >= 0; h--) {
3193 dstpixel=(DWORD*)dstbits;
3194 for (x = 0; x < dstwidth; x++) {
3195 PALETTEENTRY srcval;
3196 srcval = srccolors[XGetPixel(bmpImage, x, h)];
3197 *dstpixel++=(srcval.peRed << rShift) |
3198 (srcval.peGreen << gShift) |
3199 (srcval.peBlue << bShift);
3201 dstbits += linebytes;
3203 } else {
3204 goto notsupported;
3206 break;
3208 case 8:
3209 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
3210 /* ==== pal 8 bmp -> any 0888 dib ==== */
3211 int rShift,gShift,bShift;
3212 const void* srcbits;
3213 const BYTE* srcpixel;
3214 DWORD* dstpixel;
3216 rShift=X11DRV_DIB_MaskToShift(rDst);
3217 gShift=X11DRV_DIB_MaskToShift(gDst);
3218 bShift=X11DRV_DIB_MaskToShift(bDst);
3219 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3220 for (h = lines - 1; h >= 0; h--) {
3221 srcpixel=srcbits;
3222 dstpixel=(DWORD*)dstbits;
3223 for (x = 0; x < dstwidth; x++) {
3224 PALETTEENTRY srcval;
3225 srcval=srccolors[(int)*srcpixel++];
3226 *dstpixel++=(srcval.peRed << rShift) |
3227 (srcval.peGreen << gShift) |
3228 (srcval.peBlue << bShift);
3230 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
3231 dstbits += linebytes;
3233 } else {
3234 goto notsupported;
3236 break;
3238 default:
3239 notsupported:
3241 /* ==== any bmp format -> any 0888 dib ==== */
3242 int rShift,gShift,bShift;
3243 DWORD* dstpixel;
3245 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 32 bit DIB (%lx,%lx,%lx)\n",
3246 bmpImage->depth, bmpImage->red_mask,
3247 bmpImage->green_mask, bmpImage->blue_mask,
3248 rDst,gDst,bDst);
3250 rShift=X11DRV_DIB_MaskToShift(rDst);
3251 gShift=X11DRV_DIB_MaskToShift(gDst);
3252 bShift=X11DRV_DIB_MaskToShift(bDst);
3253 for (h = lines - 1; h >= 0; h--) {
3254 dstpixel=(DWORD*)dstbits;
3255 for (x = 0; x < dstwidth; x++) {
3256 COLORREF srcval;
3257 srcval=X11DRV_PALETTE_ToLogical(XGetPixel(bmpImage, x, h));
3258 *dstpixel++=(GetRValue(srcval) << rShift) |
3259 (GetGValue(srcval) << gShift) |
3260 (GetBValue(srcval) << bShift);
3262 dstbits += linebytes;
3265 break;
3269 /***********************************************************************
3270 * X11DRV_DIB_SetImageBits
3272 * Transfer the bits to an X image.
3273 * Helper function for SetDIBits() and SetDIBitsToDevice().
3275 static int X11DRV_DIB_SetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
3277 int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
3278 XImage *bmpImage;
3280 wine_tsx11_lock();
3281 if (descr->image)
3282 bmpImage = descr->image;
3283 else {
3284 bmpImage = XCreateImage( gdi_display, visual, descr->depth, ZPixmap, 0, NULL,
3285 descr->infoWidth, lines, 32, 0 );
3286 bmpImage->data = calloc( lines, bmpImage->bytes_per_line );
3287 if(bmpImage->data == NULL) {
3288 ERR("Out of memory!\n");
3289 XDestroyImage( bmpImage );
3290 wine_tsx11_unlock();
3291 return lines;
3295 TRACE("Dib: depth=%d r=%lx g=%lx b=%lx\n",
3296 descr->infoBpp,descr->rMask,descr->gMask,descr->bMask);
3297 TRACE("Bmp: depth=%d/%d r=%lx g=%lx b=%lx\n",
3298 bmpImage->depth,bmpImage->bits_per_pixel,
3299 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
3301 /* Transfer the pixels */
3302 switch(descr->infoBpp)
3304 case 1:
3305 X11DRV_DIB_SetImageBits_1( descr->lines, descr->bits, descr->infoWidth,
3306 descr->width, descr->xSrc, (int *)(descr->colorMap),
3307 bmpImage, descr->dibpitch );
3308 break;
3309 case 4:
3310 if (descr->compression) {
3311 XGetSubImage( gdi_display, descr->drawable, descr->xDest, descr->yDest,
3312 descr->width, descr->height, AllPlanes, ZPixmap,
3313 bmpImage, descr->xSrc, descr->ySrc );
3315 X11DRV_DIB_SetImageBits_RLE4( descr->lines, descr->bits,
3316 descr->infoWidth, descr->width,
3317 descr->xSrc, (int *)(descr->colorMap),
3318 bmpImage );
3319 } else
3320 X11DRV_DIB_SetImageBits_4( descr->lines, descr->bits,
3321 descr->infoWidth, descr->width,
3322 descr->xSrc, (int*)(descr->colorMap),
3323 bmpImage, descr->dibpitch );
3324 break;
3325 case 8:
3326 if (descr->compression) {
3327 XGetSubImage( gdi_display, descr->drawable, descr->xDest, descr->yDest,
3328 descr->width, descr->height, AllPlanes, ZPixmap,
3329 bmpImage, descr->xSrc, descr->ySrc );
3330 X11DRV_DIB_SetImageBits_RLE8( descr->lines, descr->bits,
3331 descr->infoWidth, descr->width,
3332 descr->xSrc, (int *)(descr->colorMap),
3333 bmpImage );
3334 } else
3335 X11DRV_DIB_SetImageBits_8( descr->lines, descr->bits,
3336 descr->infoWidth, descr->width,
3337 descr->xSrc, (int *)(descr->colorMap),
3338 bmpImage, descr->dibpitch );
3339 break;
3340 case 15:
3341 case 16:
3342 X11DRV_DIB_SetImageBits_16( descr->lines, descr->bits,
3343 descr->infoWidth, descr->width,
3344 descr->xSrc, descr->physDev,
3345 descr->rMask, descr->gMask, descr->bMask,
3346 bmpImage, descr->dibpitch);
3347 break;
3348 case 24:
3349 X11DRV_DIB_SetImageBits_24( descr->lines, descr->bits,
3350 descr->infoWidth, descr->width,
3351 descr->xSrc, descr->physDev,
3352 descr->rMask, descr->gMask, descr->bMask,
3353 bmpImage, descr->dibpitch);
3354 break;
3355 case 32:
3356 X11DRV_DIB_SetImageBits_32( descr->lines, descr->bits,
3357 descr->infoWidth, descr->width,
3358 descr->xSrc, descr->physDev,
3359 descr->rMask, descr->gMask, descr->bMask,
3360 bmpImage, descr->dibpitch);
3361 break;
3362 default:
3363 WARN("(%d): Invalid depth\n", descr->infoBpp );
3364 break;
3367 TRACE("XPutImage(%ld,%p,%p,%d,%d,%d,%d,%d,%d)\n",
3368 descr->drawable, descr->gc, bmpImage,
3369 descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
3370 descr->width, descr->height);
3371 #ifdef HAVE_LIBXXSHM
3372 if (descr->useShm)
3374 XShmPutImage( gdi_display, descr->drawable, descr->gc, bmpImage,
3375 descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
3376 descr->width, descr->height, FALSE );
3377 XSync( gdi_display, 0 );
3379 else
3380 #endif
3381 XPutImage( gdi_display, descr->drawable, descr->gc, bmpImage,
3382 descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
3383 descr->width, descr->height );
3385 if (!descr->image) XDestroyImage( bmpImage );
3386 wine_tsx11_unlock();
3387 return lines;
3390 /***********************************************************************
3391 * X11DRV_DIB_GetImageBits
3393 * Transfer the bits from an X image.
3395 static int X11DRV_DIB_GetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
3397 int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
3398 XImage *bmpImage;
3400 wine_tsx11_lock();
3401 if (descr->image)
3402 bmpImage = descr->image;
3403 else {
3404 bmpImage = XCreateImage( gdi_display, visual, descr->depth, ZPixmap, 0, NULL,
3405 descr->infoWidth, lines, 32, 0 );
3406 bmpImage->data = calloc( lines, bmpImage->bytes_per_line );
3407 if(bmpImage->data == NULL) {
3408 ERR("Out of memory!\n");
3409 XDestroyImage( bmpImage );
3410 wine_tsx11_unlock();
3411 return lines;
3415 #ifdef HAVE_LIBXXSHM
3416 if (descr->useShm)
3418 int saveRed, saveGreen, saveBlue;
3420 TRACE("XShmGetImage(%p, %ld, %p, %d, %d, %ld)\n",
3421 gdi_display, descr->drawable, bmpImage,
3422 descr->xSrc, descr->ySrc, AllPlanes);
3424 /* We must save and restore the bmpImage's masks in order
3425 * to preserve them across the call to XShmGetImage, which
3426 * decides to eleminate them since it doesn't happen to know
3427 * what the format of the image is supposed to be, even though
3428 * we do. */
3429 saveRed = bmpImage->red_mask;
3430 saveBlue= bmpImage->blue_mask;
3431 saveGreen = bmpImage->green_mask;
3433 XShmGetImage( gdi_display, descr->drawable, bmpImage,
3434 descr->xSrc, descr->ySrc, AllPlanes);
3436 bmpImage->red_mask = saveRed;
3437 bmpImage->blue_mask = saveBlue;
3438 bmpImage->green_mask = saveGreen;
3440 else
3441 #endif /* HAVE_LIBXXSHM */
3443 TRACE("XGetSubImage(%p,%ld,%d,%d,%d,%d,%ld,%d,%p,%d,%d)\n",
3444 gdi_display, descr->drawable, descr->xSrc, descr->ySrc, descr->width,
3445 lines, AllPlanes, ZPixmap, bmpImage, descr->xDest, descr->yDest);
3446 XGetSubImage( gdi_display, descr->drawable, descr->xSrc, descr->ySrc,
3447 descr->width, lines, AllPlanes, ZPixmap,
3448 bmpImage, descr->xDest, descr->yDest );
3451 TRACE("Dib: depth=%2d r=%lx g=%lx b=%lx\n",
3452 descr->infoBpp,descr->rMask,descr->gMask,descr->bMask);
3453 TRACE("Bmp: depth=%2d/%2d r=%lx g=%lx b=%lx\n",
3454 bmpImage->depth,bmpImage->bits_per_pixel,
3455 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
3456 /* Transfer the pixels */
3457 switch(descr->infoBpp)
3459 case 1:
3460 X11DRV_DIB_GetImageBits_1( descr->lines,(LPVOID)descr->bits,
3461 descr->infoWidth, descr->width,
3462 descr->colorMap, descr->palentry,
3463 bmpImage, descr->dibpitch );
3464 break;
3466 case 4:
3467 if (descr->compression)
3468 FIXME("Compression not yet supported!\n");
3469 else
3470 X11DRV_DIB_GetImageBits_4( descr->lines,(LPVOID)descr->bits,
3471 descr->infoWidth, descr->width,
3472 descr->colorMap, descr->palentry,
3473 bmpImage, descr->dibpitch );
3474 break;
3476 case 8:
3477 if (descr->compression)
3478 FIXME("Compression not yet supported!\n");
3479 else
3480 X11DRV_DIB_GetImageBits_8( descr->lines, (LPVOID)descr->bits,
3481 descr->infoWidth, descr->width,
3482 descr->colorMap, descr->palentry,
3483 bmpImage, descr->dibpitch );
3484 break;
3485 case 15:
3486 case 16:
3487 X11DRV_DIB_GetImageBits_16( descr->lines, (LPVOID)descr->bits,
3488 descr->infoWidth,descr->width,
3489 descr->palentry,
3490 descr->rMask, descr->gMask, descr->bMask,
3491 bmpImage, descr->dibpitch );
3492 break;
3494 case 24:
3495 X11DRV_DIB_GetImageBits_24( descr->lines, (LPVOID)descr->bits,
3496 descr->infoWidth,descr->width,
3497 descr->palentry,
3498 descr->rMask, descr->gMask, descr->bMask,
3499 bmpImage, descr->dibpitch);
3500 break;
3502 case 32:
3503 X11DRV_DIB_GetImageBits_32( descr->lines, (LPVOID)descr->bits,
3504 descr->infoWidth, descr->width,
3505 descr->palentry,
3506 descr->rMask, descr->gMask, descr->bMask,
3507 bmpImage, descr->dibpitch);
3508 break;
3510 default:
3511 WARN("(%d): Invalid depth\n", descr->infoBpp );
3512 break;
3515 if (!descr->image) XDestroyImage( bmpImage );
3516 wine_tsx11_unlock();
3517 return lines;
3520 /*************************************************************************
3521 * X11DRV_SetDIBitsToDevice
3524 INT X11DRV_SetDIBitsToDevice( X11DRV_PDEVICE *physDev, INT xDest, INT yDest, DWORD cx,
3525 DWORD cy, INT xSrc, INT ySrc,
3526 UINT startscan, UINT lines, LPCVOID bits,
3527 const BITMAPINFO *info, UINT coloruse )
3529 X11DRV_DIB_IMAGEBITS_DESCR descr;
3530 DWORD width;
3531 INT result;
3532 int height;
3533 BOOL top_down;
3534 POINT pt;
3535 DC *dc = physDev->dc;
3537 if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height,
3538 &descr.infoBpp, &descr.compression ) == -1)
3539 return 0;
3540 top_down = (height < 0);
3541 if (top_down) height = -height;
3543 pt.x = xDest;
3544 pt.y = yDest;
3545 LPtoDP(physDev->hdc, &pt, 1);
3547 if (!lines || (startscan >= height)) return 0;
3548 if (!top_down && startscan + lines > height) lines = height - startscan;
3550 /* make xSrc,ySrc point to the upper-left corner, not the lower-left one,
3551 * and clamp all values to fit inside [startscan,startscan+lines]
3553 if (ySrc + cy <= startscan + lines)
3555 INT y = startscan + lines - (ySrc + cy);
3556 if (ySrc < startscan) cy -= (startscan - ySrc);
3557 if (!top_down)
3559 /* avoid getting unnecessary lines */
3560 ySrc = 0;
3561 if (y >= lines) return 0;
3562 lines -= y;
3564 else
3566 if (y >= lines) return lines;
3567 ySrc = y; /* need to get all lines in top down mode */
3570 else
3572 if (ySrc >= startscan + lines) return lines;
3573 pt.y += ySrc + cy - (startscan + lines);
3574 cy = startscan + lines - ySrc;
3575 ySrc = 0;
3576 if (cy > lines) cy = lines;
3578 if (xSrc >= width) return lines;
3579 if (xSrc + cx >= width) cx = width - xSrc;
3580 if (!cx || !cy) return lines;
3582 X11DRV_SetupGCForText( physDev ); /* To have the correct colors */
3583 wine_tsx11_lock();
3584 XSetFunction(gdi_display, physDev->gc, X11DRV_XROPfunction[dc->ROPmode-1]);
3585 wine_tsx11_unlock();
3587 switch (descr.infoBpp)
3589 case 1:
3590 case 4:
3591 case 8:
3592 descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap(
3593 coloruse == DIB_PAL_COLORS ? physDev : NULL, coloruse,
3594 dc->bitsPerPixel, info, &descr.nColorMap );
3595 if (!descr.colorMap) return 0;
3596 descr.rMask = descr.gMask = descr.bMask = 0;
3597 break;
3598 case 15:
3599 case 16:
3600 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
3601 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x03e0;
3602 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x001f;
3603 descr.colorMap = 0;
3604 break;
3606 case 24:
3607 case 32:
3608 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
3609 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x00ff00;
3610 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x0000ff;
3611 descr.colorMap = 0;
3612 break;
3615 descr.physDev = physDev;
3616 descr.bits = bits;
3617 descr.image = NULL;
3618 descr.palentry = NULL;
3619 descr.lines = top_down ? -lines : lines;
3620 descr.infoWidth = width;
3621 descr.depth = dc->bitsPerPixel;
3622 descr.drawable = physDev->drawable;
3623 descr.gc = physDev->gc;
3624 descr.xSrc = xSrc;
3625 descr.ySrc = ySrc;
3626 descr.xDest = physDev->org.x + pt.x;
3627 descr.yDest = physDev->org.y + pt.y;
3628 descr.width = cx;
3629 descr.height = cy;
3630 descr.useShm = FALSE;
3631 descr.dibpitch = ((width * descr.infoBpp + 31) &~31) / 8;
3633 result = X11DRV_DIB_SetImageBits( &descr );
3635 if (descr.infoBpp <= 8)
3636 HeapFree(GetProcessHeap(), 0, descr.colorMap);
3637 return result;
3640 /***********************************************************************
3641 * SetDIBits (X11DRV.@)
3643 INT X11DRV_SetDIBits( X11DRV_PDEVICE *physDev, HBITMAP hbitmap, UINT startscan,
3644 UINT lines, LPCVOID bits, const BITMAPINFO *info, UINT coloruse )
3646 X11DRV_DIB_IMAGEBITS_DESCR descr;
3647 BITMAPOBJ *bmp;
3648 int height, tmpheight;
3649 INT result;
3651 descr.physDev = physDev;
3653 if (DIB_GetBitmapInfo( &info->bmiHeader, &descr.infoWidth, &height,
3654 &descr.infoBpp, &descr.compression ) == -1)
3655 return 0;
3657 tmpheight = height;
3658 if (height < 0) height = -height;
3659 if (!lines || (startscan >= height))
3660 return 0;
3662 if (!(bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC ))) return 0;
3664 if (startscan + lines > height) lines = height - startscan;
3666 switch (descr.infoBpp)
3668 case 1:
3669 case 4:
3670 case 8:
3671 descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap(
3672 coloruse == DIB_PAL_COLORS ? descr.physDev : NULL, coloruse,
3673 bmp->bitmap.bmBitsPixel,
3674 info, &descr.nColorMap );
3675 if (!descr.colorMap)
3677 GDI_ReleaseObj( hbitmap );
3678 return 0;
3680 descr.rMask = descr.gMask = descr.bMask = 0;
3681 break;
3682 case 15:
3683 case 16:
3684 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
3685 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x03e0;
3686 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x001f;
3687 descr.colorMap = 0;
3688 break;
3690 case 24:
3691 case 32:
3692 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
3693 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x00ff00;
3694 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x0000ff;
3695 descr.colorMap = 0;
3696 break;
3698 default: break;
3701 descr.bits = bits;
3702 descr.image = NULL;
3703 descr.palentry = NULL;
3704 descr.lines = tmpheight >= 0 ? lines : -lines;
3705 descr.depth = bmp->bitmap.bmBitsPixel;
3706 descr.drawable = (Pixmap)bmp->physBitmap;
3707 descr.gc = BITMAP_GC(bmp);
3708 descr.xSrc = 0;
3709 descr.ySrc = 0;
3710 descr.xDest = 0;
3711 descr.yDest = height - startscan - lines;
3712 descr.width = bmp->bitmap.bmWidth;
3713 descr.height = lines;
3714 descr.useShm = FALSE;
3715 descr.dibpitch = ((descr.infoWidth * descr.infoBpp + 31) &~31) / 8;
3716 X11DRV_DIB_Lock(bmp, DIB_Status_GdiMod, FALSE);
3717 result = X11DRV_DIB_SetImageBits( &descr );
3718 X11DRV_DIB_Unlock(bmp, TRUE);
3720 if (descr.colorMap) HeapFree(GetProcessHeap(), 0, descr.colorMap);
3722 GDI_ReleaseObj( hbitmap );
3723 return result;
3726 /***********************************************************************
3727 * GetDIBits (X11DRV.@)
3729 INT X11DRV_GetDIBits( X11DRV_PDEVICE *physDev, HBITMAP hbitmap, UINT startscan, UINT lines,
3730 LPVOID bits, BITMAPINFO *info, UINT coloruse )
3732 X11DRV_DIBSECTION *dib;
3733 X11DRV_DIB_IMAGEBITS_DESCR descr;
3734 PALETTEOBJ * palette;
3735 BITMAPOBJ *bmp;
3736 int height;
3737 DC *dc = physDev->dc;
3739 if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->hPalette, PALETTE_MAGIC )))
3740 return 0;
3741 if (!(bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
3743 GDI_ReleaseObj( dc->hPalette );
3744 return 0;
3746 dib = (X11DRV_DIBSECTION *) bmp->dib;
3748 TRACE("%u scanlines of (%i,%i) -> (%i,%i) starting from %u\n",
3749 lines, bmp->bitmap.bmWidth, bmp->bitmap.bmHeight,
3750 (int)info->bmiHeader.biWidth, (int)info->bmiHeader.biHeight,
3751 startscan );
3753 if( lines > bmp->bitmap.bmHeight ) lines = bmp->bitmap.bmHeight;
3755 height = info->bmiHeader.biHeight;
3756 if (height < 0) height = -height;
3757 if( lines > height ) lines = height;
3758 /* Top-down images have a negative biHeight, the scanlines of theses images
3759 * were inverted in X11DRV_DIB_GetImageBits_xx
3760 * To prevent this we simply change the sign of lines
3761 * (the number of scan lines to copy).
3762 * Negative lines are correctly handled by X11DRV_DIB_GetImageBits_xx.
3764 if( info->bmiHeader.biHeight < 0 && lines > 0) lines = -lines;
3766 if( startscan >= bmp->bitmap.bmHeight )
3768 lines = 0;
3769 goto done;
3772 if (DIB_GetBitmapInfo( &info->bmiHeader, &descr.infoWidth, &descr.lines,
3773 &descr.infoBpp, &descr.compression ) == -1)
3775 lines = 0;
3776 goto done;
3779 switch (descr.infoBpp)
3781 case 1:
3782 case 4:
3783 case 8:
3784 descr.rMask= descr.gMask = descr.bMask = 0;
3785 break;
3786 case 15:
3787 case 16:
3788 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
3789 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x03e0;
3790 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x001f;
3791 break;
3792 case 24:
3793 case 32:
3794 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
3795 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x00ff00;
3796 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x0000ff;
3797 break;
3800 descr.physDev = physDev;
3801 descr.palentry = palette->logpalette.palPalEntry;
3802 descr.bits = bits;
3803 descr.image = NULL;
3804 descr.lines = lines;
3805 descr.depth = bmp->bitmap.bmBitsPixel;
3806 descr.drawable = (Pixmap)bmp->physBitmap;
3807 descr.gc = BITMAP_GC(bmp);
3808 descr.width = bmp->bitmap.bmWidth;
3809 descr.height = bmp->bitmap.bmHeight;
3810 descr.colorMap = info->bmiColors;
3811 descr.xDest = 0;
3812 descr.yDest = 0;
3813 descr.xSrc = 0;
3815 if (descr.lines > 0)
3817 descr.ySrc = (descr.height-1) - (startscan + (lines-1));
3819 else
3821 descr.ySrc = startscan;
3823 #ifdef HAVE_LIBXXSHM
3824 descr.useShm = dib ? (dib->shminfo.shmid != -1) : FALSE;
3825 #else
3826 descr.useShm = FALSE;
3827 #endif
3828 descr.dibpitch = dib ? (dib->dibSection.dsBm.bmWidthBytes)
3829 : (((descr.infoWidth * descr.infoBpp + 31) &~31) / 8);
3831 X11DRV_DIB_Lock(bmp, DIB_Status_GdiMod, FALSE);
3832 X11DRV_DIB_GetImageBits( &descr );
3833 X11DRV_DIB_Unlock(bmp, TRUE);
3835 if(info->bmiHeader.biSizeImage == 0) /* Fill in biSizeImage */
3836 info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(
3837 info->bmiHeader.biWidth,
3838 info->bmiHeader.biHeight,
3839 info->bmiHeader.biBitCount );
3841 if (descr.compression == BI_BITFIELDS)
3843 *(DWORD *)info->bmiColors = descr.rMask;
3844 *((DWORD *)info->bmiColors+1) = descr.gMask;
3845 *((DWORD *)info->bmiColors+2) = descr.bMask;
3847 else
3849 /* if RLE or JPEG compression were supported,
3850 * this line would be invalid. */
3851 info->bmiHeader.biCompression = 0;
3854 done:
3855 GDI_ReleaseObj( dc->hPalette );
3856 GDI_ReleaseObj( hbitmap );
3857 return lines;
3860 /***********************************************************************
3861 * DIB_DoProtectDIBSection
3863 static void X11DRV_DIB_DoProtectDIBSection( BITMAPOBJ *bmp, DWORD new_prot )
3865 DIBSECTION *dib = bmp->dib;
3866 INT effHeight = dib->dsBm.bmHeight >= 0? dib->dsBm.bmHeight
3867 : -dib->dsBm.bmHeight;
3868 /* use the biSizeImage data as the memory size only if we're dealing with a
3869 compressed image where the value is set. Otherwise, calculate based on
3870 width * height */
3871 INT totalSize = dib->dsBmih.biSizeImage && dib->dsBmih.biCompression != BI_RGB
3872 ? dib->dsBmih.biSizeImage
3873 : dib->dsBm.bmWidthBytes * effHeight;
3874 DWORD old_prot;
3876 VirtualProtect(dib->dsBm.bmBits, totalSize, new_prot, &old_prot);
3877 TRACE("Changed protection from %ld to %ld\n", old_prot, new_prot);
3880 /***********************************************************************
3881 * X11DRV_DIB_DoUpdateDIBSection
3883 static void X11DRV_DIB_DoCopyDIBSection(BITMAPOBJ *bmp, BOOL toDIB,
3884 void *colorMap, int nColorMap,
3885 Drawable dest,
3886 DWORD xSrc, DWORD ySrc,
3887 DWORD xDest, DWORD yDest,
3888 DWORD width, DWORD height)
3890 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
3891 X11DRV_DIB_IMAGEBITS_DESCR descr;
3893 if (DIB_GetBitmapInfo( &dib->dibSection.dsBmih, &descr.infoWidth, &descr.lines,
3894 &descr.infoBpp, &descr.compression ) == -1)
3895 return;
3897 descr.physDev = NULL;
3898 descr.palentry = NULL;
3899 descr.image = dib->image;
3900 descr.colorMap = colorMap;
3901 descr.nColorMap = nColorMap;
3902 descr.bits = dib->dibSection.dsBm.bmBits;
3903 descr.depth = bmp->bitmap.bmBitsPixel;
3905 switch (descr.infoBpp)
3907 case 1:
3908 case 4:
3909 case 8:
3910 descr.rMask = descr.gMask = descr.bMask = 0;
3911 break;
3912 case 15:
3913 case 16:
3914 descr.rMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[0] : 0x7c00;
3915 descr.gMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[1] : 0x03e0;
3916 descr.bMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[2] : 0x001f;
3917 break;
3919 case 24:
3920 case 32:
3921 descr.rMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[0] : 0xff0000;
3922 descr.gMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[1] : 0x00ff00;
3923 descr.bMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[2] : 0x0000ff;
3924 break;
3927 /* Hack for now */
3928 descr.drawable = dest;
3929 descr.gc = BITMAP_GC(bmp);
3930 descr.xSrc = xSrc;
3931 descr.ySrc = ySrc;
3932 descr.xDest = xDest;
3933 descr.yDest = yDest;
3934 descr.width = width;
3935 descr.height = height;
3936 #ifdef HAVE_LIBXXSHM
3937 descr.useShm = (dib->shminfo.shmid != -1);
3938 #else
3939 descr.useShm = FALSE;
3940 #endif
3941 descr.dibpitch = dib->dibSection.dsBm.bmWidthBytes;
3943 if (toDIB)
3945 TRACE("Copying from Pixmap to DIB bits\n");
3946 X11DRV_DIB_GetImageBits( &descr );
3948 else
3950 TRACE("Copying from DIB bits to Pixmap\n");
3951 X11DRV_DIB_SetImageBits( &descr );
3955 /***********************************************************************
3956 * X11DRV_DIB_CopyDIBSection
3958 void X11DRV_DIB_CopyDIBSection(X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE *physDevDst,
3959 DWORD xSrc, DWORD ySrc, DWORD xDest, DWORD yDest,
3960 DWORD width, DWORD height)
3962 BITMAPOBJ *bmp;
3963 DC *dcSrc = physDevSrc->dc;
3964 DC *dcDst = physDevDst->dc;
3965 int nColorMap = 0, *colorMap = NULL, aColorMap = FALSE;
3967 TRACE("(%p,%p,%ld,%ld,%ld,%ld,%ld,%ld)\n", dcSrc, dcDst,
3968 xSrc, ySrc, xDest, yDest, width, height);
3969 /* this function is meant as an optimization for BitBlt,
3970 * not to be called otherwise */
3971 if (GetObjectType( physDevSrc->hdc ) != OBJ_MEMDC) {
3972 ERR("called for non-memory source DC!?\n");
3973 return;
3976 bmp = (BITMAPOBJ *)GDI_GetObjPtr( dcSrc->hBitmap, BITMAP_MAGIC );
3977 if (!(bmp && bmp->dib)) {
3978 ERR("called for non-DIBSection!?\n");
3979 GDI_ReleaseObj( dcSrc->hBitmap );
3980 return;
3982 /* while BitBlt should already have made sure we only get
3983 * positive values, we should check for oversize values */
3984 if ((xSrc < bmp->bitmap.bmWidth) &&
3985 (ySrc < bmp->bitmap.bmHeight)) {
3986 if (xSrc + width > bmp->bitmap.bmWidth)
3987 width = bmp->bitmap.bmWidth - xSrc;
3988 if (ySrc + height > bmp->bitmap.bmHeight)
3989 height = bmp->bitmap.bmHeight - ySrc;
3990 /* if the source bitmap is 8bpp or less, we're supposed to use the
3991 * DC's palette for color conversion (not the DIB color table) */
3992 if (bmp->dib->dsBm.bmBitsPixel <= 8) {
3993 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
3994 if ((!dcSrc->hPalette) ||
3995 (dcSrc->hPalette == GetStockObject(DEFAULT_PALETTE))) {
3996 /* HACK: no palette has been set in the source DC,
3997 * use the DIB colormap instead - this is necessary in some
3998 * cases since we need to do depth conversion in some places
3999 * where real Windows can just copy data straight over */
4000 colorMap = dib->colorMap;
4001 nColorMap = dib->nColorMap;
4002 } else {
4003 colorMap = X11DRV_DIB_BuildColorMap( physDevSrc, (WORD)-1,
4004 bmp->dib->dsBm.bmBitsPixel,
4005 (BITMAPINFO*)&(bmp->dib->dsBmih),
4006 &nColorMap );
4007 if (colorMap) aColorMap = TRUE;
4010 /* perform the copy */
4011 X11DRV_DIB_DoCopyDIBSection(bmp, FALSE, colorMap, nColorMap,
4012 physDevDst->drawable, xSrc, ySrc,
4013 physDevDst->org.x + xDest, physDevDst->org.y + yDest,
4014 width, height);
4015 /* free color mapping */
4016 if (aColorMap)
4017 HeapFree(GetProcessHeap(), 0, colorMap);
4019 GDI_ReleaseObj( dcSrc->hBitmap );
4022 /***********************************************************************
4023 * X11DRV_DIB_DoUpdateDIBSection
4025 static void X11DRV_DIB_DoUpdateDIBSection(BITMAPOBJ *bmp, BOOL toDIB)
4027 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
4028 X11DRV_DIB_DoCopyDIBSection(bmp, toDIB, dib->colorMap, dib->nColorMap,
4029 (Drawable)bmp->physBitmap, 0, 0, 0, 0,
4030 bmp->bitmap.bmWidth, bmp->bitmap.bmHeight);
4033 /***********************************************************************
4034 * X11DRV_DIB_FaultHandler
4036 static BOOL X11DRV_DIB_FaultHandler( LPVOID res, LPCVOID addr )
4038 BITMAPOBJ *bmp;
4039 INT state;
4041 bmp = (BITMAPOBJ *)GDI_GetObjPtr( (HBITMAP)res, BITMAP_MAGIC );
4042 if (!bmp) return FALSE;
4044 state = X11DRV_DIB_Lock(bmp, DIB_Status_None, FALSE);
4045 if (state != DIB_Status_InSync) {
4046 /* no way to tell whether app needs read or write yet,
4047 * try read first */
4048 X11DRV_DIB_Coerce(bmp, DIB_Status_InSync, FALSE);
4049 } else {
4050 /* hm, apparently the app must have write access */
4051 X11DRV_DIB_Coerce(bmp, DIB_Status_AppMod, FALSE);
4053 X11DRV_DIB_Unlock(bmp, TRUE);
4055 GDI_ReleaseObj( (HBITMAP)res );
4056 return TRUE;
4059 /***********************************************************************
4060 * X11DRV_DIB_Coerce
4062 INT X11DRV_DIB_Coerce(BITMAPOBJ *bmp, INT req, BOOL lossy)
4064 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
4065 INT ret = DIB_Status_None;
4067 if (dib) {
4068 EnterCriticalSection(&(dib->lock));
4069 ret = dib->status;
4070 switch (req) {
4071 case DIB_Status_GdiMod:
4072 /* GDI access - request to draw on pixmap */
4073 switch (dib->status)
4075 default:
4076 case DIB_Status_None:
4077 dib->p_status = DIB_Status_GdiMod;
4078 X11DRV_DIB_DoUpdateDIBSection( bmp, FALSE );
4079 break;
4081 case DIB_Status_GdiMod:
4082 TRACE("GdiMod requested in status GdiMod\n" );
4083 break;
4085 case DIB_Status_InSync:
4086 TRACE("GdiMod requested in status InSync\n" );
4087 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
4088 dib->status = DIB_Status_GdiMod;
4089 dib->p_status = DIB_Status_InSync;
4090 break;
4092 case DIB_Status_AuxMod:
4093 TRACE("GdiMod requested in status AuxMod\n" );
4094 if (lossy) dib->status = DIB_Status_GdiMod;
4095 else (*dib->copy_aux)(dib->aux_ctx, DIB_Status_GdiMod);
4096 dib->p_status = DIB_Status_AuxMod;
4097 if (dib->status != DIB_Status_AppMod) {
4098 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
4099 break;
4101 /* fall through if copy_aux() had to change to AppMod state */
4103 case DIB_Status_AppMod:
4104 TRACE("GdiMod requested in status AppMod\n" );
4105 if (!lossy) {
4106 /* make it readonly to avoid app changing data while we copy */
4107 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
4108 X11DRV_DIB_DoUpdateDIBSection( bmp, FALSE );
4110 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
4111 dib->p_status = DIB_Status_AppMod;
4112 dib->status = DIB_Status_GdiMod;
4113 break;
4115 break;
4117 case DIB_Status_InSync:
4118 /* App access - request access to read DIB surface */
4119 /* (typically called from signal handler) */
4120 switch (dib->status)
4122 default:
4123 case DIB_Status_None:
4124 /* shouldn't happen from signal handler */
4125 break;
4127 case DIB_Status_AuxMod:
4128 TRACE("InSync requested in status AuxMod\n" );
4129 if (lossy) dib->status = DIB_Status_InSync;
4130 else {
4131 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
4132 (*dib->copy_aux)(dib->aux_ctx, DIB_Status_InSync);
4134 if (dib->status != DIB_Status_GdiMod) {
4135 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
4136 break;
4138 /* fall through if copy_aux() had to change to GdiMod state */
4140 case DIB_Status_GdiMod:
4141 TRACE("InSync requested in status GdiMod\n" );
4142 if (!lossy) {
4143 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
4144 X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
4146 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
4147 dib->status = DIB_Status_InSync;
4148 break;
4150 case DIB_Status_InSync:
4151 TRACE("InSync requested in status InSync\n" );
4152 /* shouldn't happen from signal handler */
4153 break;
4155 case DIB_Status_AppMod:
4156 TRACE("InSync requested in status AppMod\n" );
4157 /* no reason to do anything here, and this
4158 * shouldn't happen from signal handler */
4159 break;
4161 break;
4163 case DIB_Status_AppMod:
4164 /* App access - request access to write DIB surface */
4165 /* (typically called from signal handler) */
4166 switch (dib->status)
4168 default:
4169 case DIB_Status_None:
4170 /* shouldn't happen from signal handler */
4171 break;
4173 case DIB_Status_AuxMod:
4174 TRACE("AppMod requested in status AuxMod\n" );
4175 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
4176 if (lossy) dib->status = DIB_Status_AppMod;
4177 else (*dib->copy_aux)(dib->aux_ctx, DIB_Status_AppMod);
4178 if (dib->status != DIB_Status_GdiMod)
4179 break;
4180 /* fall through if copy_aux() had to change to GdiMod state */
4182 case DIB_Status_GdiMod:
4183 TRACE("AppMod requested in status GdiMod\n" );
4184 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
4185 if (!lossy) X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
4186 dib->status = DIB_Status_AppMod;
4187 break;
4189 case DIB_Status_InSync:
4190 TRACE("AppMod requested in status InSync\n" );
4191 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
4192 dib->status = DIB_Status_AppMod;
4193 break;
4195 case DIB_Status_AppMod:
4196 TRACE("AppMod requested in status AppMod\n" );
4197 /* shouldn't happen from signal handler */
4198 break;
4200 break;
4202 case DIB_Status_AuxMod:
4203 if (dib->status == DIB_Status_None) {
4204 dib->p_status = req;
4205 } else {
4206 if (dib->status != DIB_Status_AuxMod)
4207 dib->p_status = dib->status;
4208 dib->status = DIB_Status_AuxMod;
4210 break;
4211 /* it is up to the caller to do the copy/conversion, probably
4212 * using the return value to decide where to copy from */
4214 LeaveCriticalSection(&(dib->lock));
4216 return ret;
4219 /***********************************************************************
4220 * X11DRV_DIB_Lock
4222 INT X11DRV_DIB_Lock(BITMAPOBJ *bmp, INT req, BOOL lossy)
4224 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
4225 INT ret = DIB_Status_None;
4227 if (dib) {
4228 TRACE("Locking %p from thread %04lx\n", bmp, GetCurrentThreadId());
4229 EnterCriticalSection(&(dib->lock));
4230 ret = dib->status;
4231 if (req != DIB_Status_None)
4232 X11DRV_DIB_Coerce(bmp, req, lossy);
4234 return ret;
4237 /***********************************************************************
4238 * X11DRV_DIB_Unlock
4240 void X11DRV_DIB_Unlock(BITMAPOBJ *bmp, BOOL commit)
4242 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
4244 if (dib) {
4245 switch (dib->status)
4247 default:
4248 case DIB_Status_None:
4249 /* in case anyone is wondering, this is the "signal handler doesn't
4250 * work" case, where we always have to be ready for app access */
4251 if (commit) {
4252 switch (dib->p_status)
4254 case DIB_Status_AuxMod:
4255 TRACE("Unlocking and syncing from AuxMod\n" );
4256 (*dib->copy_aux)(dib->aux_ctx, DIB_Status_AppMod);
4257 if (dib->status != DIB_Status_None) {
4258 dib->p_status = dib->status;
4259 dib->status = DIB_Status_None;
4261 if (dib->p_status != DIB_Status_GdiMod)
4262 break;
4263 /* fall through if copy_aux() had to change to GdiMod state */
4265 case DIB_Status_GdiMod:
4266 TRACE("Unlocking and syncing from GdiMod\n" );
4267 X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
4268 break;
4270 default:
4271 TRACE("Unlocking without needing to sync\n" );
4272 break;
4275 else TRACE("Unlocking with no changes\n");
4276 dib->p_status = DIB_Status_None;
4277 break;
4279 case DIB_Status_GdiMod:
4280 TRACE("Unlocking in status GdiMod\n" );
4281 /* DIB was protected in Coerce */
4282 if (!commit) {
4283 /* no commit, revert to InSync if applicable */
4284 if ((dib->p_status == DIB_Status_InSync) ||
4285 (dib->p_status == DIB_Status_AppMod)) {
4286 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
4287 dib->status = DIB_Status_InSync;
4290 break;
4292 case DIB_Status_InSync:
4293 TRACE("Unlocking in status InSync\n" );
4294 /* DIB was already protected in Coerce */
4295 break;
4297 case DIB_Status_AppMod:
4298 TRACE("Unlocking in status AppMod\n" );
4299 /* DIB was already protected in Coerce */
4300 /* this case is ordinary only called from the signal handler,
4301 * so we don't bother to check for !commit */
4302 break;
4304 case DIB_Status_AuxMod:
4305 TRACE("Unlocking in status AuxMod\n" );
4306 if (commit) {
4307 /* DIB may need protection now */
4308 if ((dib->p_status == DIB_Status_InSync) ||
4309 (dib->p_status == DIB_Status_AppMod))
4310 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
4311 } else {
4312 /* no commit, revert to previous state */
4313 if (dib->p_status != DIB_Status_None)
4314 dib->status = dib->p_status;
4315 /* no protections changed */
4317 dib->p_status = DIB_Status_None;
4318 break;
4320 LeaveCriticalSection(&(dib->lock));
4321 TRACE("Unlocked %p\n", bmp);
4325 /***********************************************************************
4326 * X11DRV_CoerceDIBSection2
4328 INT X11DRV_CoerceDIBSection2(HBITMAP hBmp, INT req, BOOL lossy)
4330 BITMAPOBJ *bmp;
4331 INT ret;
4333 bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
4334 if (!bmp) return DIB_Status_None;
4335 ret = X11DRV_DIB_Coerce(bmp, req, lossy);
4336 GDI_ReleaseObj( hBmp );
4337 return ret;
4340 /***********************************************************************
4341 * X11DRV_LockDIBSection2
4343 INT X11DRV_LockDIBSection2(HBITMAP hBmp, INT req, BOOL lossy)
4345 BITMAPOBJ *bmp;
4346 INT ret;
4348 bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
4349 if (!bmp) return DIB_Status_None;
4350 ret = X11DRV_DIB_Lock(bmp, req, lossy);
4351 GDI_ReleaseObj( hBmp );
4352 return ret;
4355 /***********************************************************************
4356 * X11DRV_UnlockDIBSection2
4358 void X11DRV_UnlockDIBSection2(HBITMAP hBmp, BOOL commit)
4360 BITMAPOBJ *bmp;
4362 bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
4363 if (!bmp) return;
4364 X11DRV_DIB_Unlock(bmp, commit);
4365 GDI_ReleaseObj( hBmp );
4368 /***********************************************************************
4369 * X11DRV_CoerceDIBSection
4371 INT X11DRV_CoerceDIBSection(X11DRV_PDEVICE *physDev, INT req, BOOL lossy)
4373 if (!physDev) return DIB_Status_None;
4374 return X11DRV_CoerceDIBSection2( physDev->dc->hBitmap, req, lossy );
4377 /***********************************************************************
4378 * X11DRV_LockDIBSection
4380 INT X11DRV_LockDIBSection(X11DRV_PDEVICE *physDev, INT req, BOOL lossy)
4382 if (!physDev) return DIB_Status_None;
4383 if (GetObjectType( physDev->hdc ) != OBJ_MEMDC) return DIB_Status_None;
4385 return X11DRV_LockDIBSection2( physDev->dc->hBitmap, req, lossy );
4388 /***********************************************************************
4389 * X11DRV_UnlockDIBSection
4391 void X11DRV_UnlockDIBSection(X11DRV_PDEVICE *physDev, BOOL commit)
4393 if (!physDev) return;
4394 if (GetObjectType( physDev->hdc ) != OBJ_MEMDC) return;
4396 X11DRV_UnlockDIBSection2( physDev->dc->hBitmap, commit );
4400 #ifdef HAVE_LIBXXSHM
4401 /***********************************************************************
4402 * X11DRV_XShmErrorHandler
4405 static int XShmErrorHandler( Display *dpy, XErrorEvent *event, void *arg )
4407 return 1; /* FIXME: should check event contents */
4410 /***********************************************************************
4411 * X11DRV_XShmCreateImage
4414 static XImage *X11DRV_XShmCreateImage( int width, int height, int bpp,
4415 XShmSegmentInfo* shminfo)
4417 XImage *image;
4419 image = XShmCreateImage(gdi_display, visual, bpp, ZPixmap, NULL, shminfo, width, height);
4420 if (image)
4422 shminfo->shmid = shmget(IPC_PRIVATE, image->bytes_per_line * height,
4423 IPC_CREAT|0700);
4424 if( shminfo->shmid != -1 )
4426 shminfo->shmaddr = image->data = shmat(shminfo->shmid, 0, 0);
4427 if( shminfo->shmaddr != (char*)-1 )
4429 BOOL ok;
4431 shminfo->readOnly = FALSE;
4432 X11DRV_expect_error( gdi_display, XShmErrorHandler, NULL );
4433 ok = (XShmAttach( gdi_display, shminfo ) != 0);
4434 XSync( gdi_display, False );
4435 if (X11DRV_check_error()) ok = FALSE;
4436 if (ok)
4438 shmctl(shminfo->shmid, IPC_RMID, 0);
4439 return image; /* Success! */
4441 /* An error occurred */
4442 shmdt(shminfo->shmaddr);
4444 shmctl(shminfo->shmid, IPC_RMID, 0);
4446 XFlush(gdi_display);
4447 XDestroyImage(image);
4448 image = NULL;
4450 return image;
4452 #endif /* HAVE_LIBXXSHM */
4455 /***********************************************************************
4456 * X11DRV_DIB_CreateDIBSection
4458 HBITMAP X11DRV_DIB_CreateDIBSection(
4459 X11DRV_PDEVICE *physDev, BITMAPINFO *bmi, UINT usage,
4460 LPVOID *bits, HANDLE section,
4461 DWORD offset, DWORD ovr_pitch)
4463 HBITMAP res = 0;
4464 BITMAPOBJ *bmp = NULL;
4465 X11DRV_DIBSECTION *dib = NULL;
4466 int *colorMap = NULL;
4467 int nColorMap;
4469 /* Fill BITMAP32 structure with DIB data */
4470 BITMAPINFOHEADER *bi = &bmi->bmiHeader;
4471 INT effHeight, totalSize;
4472 BITMAP bm;
4473 LPVOID mapBits = NULL;
4475 TRACE("format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
4476 bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
4477 bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
4479 effHeight = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
4480 bm.bmType = 0;
4481 bm.bmWidth = bi->biWidth;
4482 bm.bmHeight = effHeight;
4483 bm.bmWidthBytes = ovr_pitch ? ovr_pitch
4484 : DIB_GetDIBWidthBytes(bm.bmWidth, bi->biBitCount);
4485 bm.bmPlanes = bi->biPlanes;
4486 bm.bmBitsPixel = bi->biBitCount;
4487 bm.bmBits = NULL;
4489 /* Get storage location for DIB bits. Only use biSizeImage if it's valid and
4490 we're dealing with a compressed bitmap. Otherwise, use width * height. */
4491 totalSize = bi->biSizeImage && bi->biCompression != BI_RGB
4492 ? bi->biSizeImage : bm.bmWidthBytes * effHeight;
4494 if (section)
4496 SYSTEM_INFO SystemInfo;
4497 DWORD mapOffset;
4498 INT mapSize;
4500 GetSystemInfo( &SystemInfo );
4501 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
4502 mapSize = totalSize + (offset - mapOffset);
4503 mapBits = MapViewOfFile( section,
4504 FILE_MAP_ALL_ACCESS,
4506 mapOffset,
4507 mapSize );
4508 bm.bmBits = (char *)mapBits + (offset - mapOffset);
4510 else if (ovr_pitch && offset)
4511 bm.bmBits = (LPVOID) offset;
4512 else {
4513 offset = 0;
4514 bm.bmBits = VirtualAlloc(NULL, totalSize,
4515 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
4518 /* Create Color Map */
4519 if (bm.bmBits && bm.bmBitsPixel <= 8)
4520 colorMap = X11DRV_DIB_BuildColorMap( usage == DIB_PAL_COLORS? physDev : NULL,
4521 usage, bm.bmBitsPixel, bmi, &nColorMap );
4523 /* Allocate Memory for DIB and fill structure */
4524 if (bm.bmBits)
4525 dib = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(X11DRV_DIBSECTION));
4526 if (dib)
4528 dib->dibSection.dsBm = bm;
4529 dib->dibSection.dsBmih = *bi;
4530 dib->dibSection.dsBmih.biSizeImage = totalSize;
4532 /* Set dsBitfields values */
4533 if ( usage == DIB_PAL_COLORS || bi->biBitCount <= 8)
4535 dib->dibSection.dsBitfields[0] = dib->dibSection.dsBitfields[1] = dib->dibSection.dsBitfields[2] = 0;
4537 else switch( bi->biBitCount )
4539 case 15:
4540 case 16:
4541 dib->dibSection.dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors : 0x7c00;
4542 dib->dibSection.dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0x03e0;
4543 dib->dibSection.dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0x001f;
4544 break;
4546 case 24:
4547 case 32:
4548 dib->dibSection.dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors : 0xff0000;
4549 dib->dibSection.dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0x00ff00;
4550 dib->dibSection.dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0x0000ff;
4551 break;
4553 dib->dibSection.dshSection = section;
4554 dib->dibSection.dsOffset = offset;
4556 dib->status = DIB_Status_None;
4557 dib->nColorMap = nColorMap;
4558 dib->colorMap = colorMap;
4561 /* Create Device Dependent Bitmap and add DIB pointer */
4562 if (dib)
4564 res = CreateDIBitmap(physDev->hdc, bi, 0, NULL, bmi, usage);
4565 if (res)
4567 bmp = (BITMAPOBJ *) GDI_GetObjPtr(res, BITMAP_MAGIC);
4568 if (bmp) bmp->dib = (DIBSECTION *) dib;
4572 /* Create XImage */
4573 if (dib && bmp)
4575 wine_tsx11_lock();
4576 #ifdef HAVE_LIBXXSHM
4577 if (XShmQueryExtension(gdi_display) &&
4578 (dib->image = X11DRV_XShmCreateImage( bm.bmWidth, effHeight,
4579 bmp->bitmap.bmBitsPixel, &dib->shminfo )) )
4581 ; /* Created Image */
4582 } else {
4583 dib->image = X11DRV_DIB_CreateXImage( bm.bmWidth, effHeight, bmp->bitmap.bmBitsPixel );
4584 dib->shminfo.shmid = -1;
4586 #else
4587 dib->image = X11DRV_DIB_CreateXImage( bm.bmWidth, effHeight, bmp->bitmap.bmBitsPixel );
4588 #endif
4589 wine_tsx11_unlock();
4592 /* Clean up in case of errors */
4593 if (!res || !bmp || !dib || !bm.bmBits || (bm.bmBitsPixel <= 8 && !colorMap))
4595 TRACE("got an error res=%p, bmp=%p, dib=%p, bm.bmBits=%p\n",
4596 res, bmp, dib, bm.bmBits);
4597 if (bm.bmBits)
4599 if (section)
4600 UnmapViewOfFile(mapBits), bm.bmBits = NULL;
4601 else if (!offset)
4602 VirtualFree(bm.bmBits, 0L, MEM_RELEASE), bm.bmBits = NULL;
4605 if (dib && dib->image) { XDestroyImage(dib->image); dib->image = NULL; }
4606 if (colorMap) { HeapFree(GetProcessHeap(), 0, colorMap); colorMap = NULL; }
4607 if (dib) { HeapFree(GetProcessHeap(), 0, dib); dib = NULL; }
4608 if (bmp) { GDI_ReleaseObj(res); bmp = NULL; }
4609 if (res) { DeleteObject(res); res = 0; }
4611 else if (bm.bmBits)
4613 extern BOOL VIRTUAL_SetFaultHandler(LPCVOID addr, BOOL (*proc)(LPVOID, LPCVOID), LPVOID arg);
4614 /* Install fault handler, if possible */
4615 InitializeCriticalSection(&(dib->lock));
4616 if (VIRTUAL_SetFaultHandler(bm.bmBits, X11DRV_DIB_FaultHandler, (LPVOID)res))
4618 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
4619 if (dib) dib->status = DIB_Status_AppMod;
4623 /* Return BITMAP handle and storage location */
4624 if (bmp) GDI_ReleaseObj(res);
4625 if (bm.bmBits && bits) *bits = bm.bmBits;
4626 return res;
4629 /***********************************************************************
4630 * X11DRV_DIB_DeleteDIBSection
4632 void X11DRV_DIB_DeleteDIBSection(BITMAPOBJ *bmp)
4634 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
4636 if (dib->image)
4638 wine_tsx11_lock();
4639 #ifdef HAVE_LIBXXSHM
4640 if (dib->shminfo.shmid != -1)
4642 XShmDetach (gdi_display, &(dib->shminfo));
4643 XDestroyImage (dib->image);
4644 shmdt (dib->shminfo.shmaddr);
4645 dib->shminfo.shmid = -1;
4647 else
4648 #endif
4649 XDestroyImage( dib->image );
4650 wine_tsx11_unlock();
4653 if (dib->colorMap)
4654 HeapFree(GetProcessHeap(), 0, dib->colorMap);
4656 DeleteCriticalSection(&(dib->lock));
4659 /***********************************************************************
4660 * SetDIBColorTable (X11DRV.@)
4662 UINT X11DRV_SetDIBColorTable( X11DRV_PDEVICE *physDev, UINT start, UINT count, const RGBQUAD *colors )
4664 BITMAPOBJ * bmp;
4665 X11DRV_DIBSECTION *dib;
4666 UINT ret = 0;
4668 if (!(bmp = (BITMAPOBJ*)GDI_GetObjPtr( physDev->dc->hBitmap, BITMAP_MAGIC ))) return 0;
4669 dib = (X11DRV_DIBSECTION *) bmp->dib;
4671 if (dib && dib->colorMap) {
4672 UINT end = count + start;
4673 if (end > dib->nColorMap) end = dib->nColorMap;
4675 * Changing color table might change the mapping between
4676 * DIB colors and X11 colors and thus alter the visible state
4677 * of the bitmap object.
4679 X11DRV_DIB_Lock(bmp, DIB_Status_AppMod, FALSE);
4680 X11DRV_DIB_GenColorMap( physDev, dib->colorMap, DIB_RGB_COLORS,
4681 dib->dibSection.dsBm.bmBitsPixel,
4682 TRUE, colors, start, end );
4683 X11DRV_DIB_Unlock(bmp, TRUE);
4684 ret = end - start;
4686 GDI_ReleaseObj( physDev->dc->hBitmap );
4687 return ret;
4690 /***********************************************************************
4691 * GetDIBColorTable (X11DRV.@)
4693 UINT X11DRV_GetDIBColorTable( X11DRV_PDEVICE *physDev, UINT start, UINT count, RGBQUAD *colors )
4695 BITMAPOBJ * bmp;
4696 X11DRV_DIBSECTION *dib;
4697 UINT ret = 0;
4699 if (!(bmp = (BITMAPOBJ*)GDI_GetObjPtr( physDev->dc->hBitmap, BITMAP_MAGIC ))) return 0;
4700 dib = (X11DRV_DIBSECTION *) bmp->dib;
4702 if (dib && dib->colorMap) {
4703 UINT i, end = count + start;
4704 if (end > dib->nColorMap) end = dib->nColorMap;
4705 for (i = start; i < end; i++,colors++) {
4706 COLORREF col = X11DRV_PALETTE_ToLogical( dib->colorMap[i] );
4707 colors->rgbBlue = GetBValue(col);
4708 colors->rgbGreen = GetGValue(col);
4709 colors->rgbRed = GetRValue(col);
4710 colors->rgbReserved = 0;
4712 ret = end-start;
4714 GDI_ReleaseObj( physDev->dc->hBitmap );
4715 return ret;
4719 /**************************************************************************
4720 * X11DRV_DIB_CreateDIBFromPixmap
4722 * Allocates a packed DIB and copies the Pixmap data into it.
4723 * If bDeletePixmap is TRUE, the Pixmap passed in is deleted after the conversion.
4725 HGLOBAL X11DRV_DIB_CreateDIBFromPixmap(Pixmap pixmap, HDC hdc, BOOL bDeletePixmap)
4727 HBITMAP hBmp = 0;
4728 BITMAPOBJ *pBmp = NULL;
4729 HGLOBAL hPackedDIB = 0;
4731 /* Allocates an HBITMAP which references the Pixmap passed to us */
4732 hBmp = X11DRV_BITMAP_CreateBitmapHeaderFromPixmap(pixmap);
4733 if (!hBmp)
4735 TRACE("\tCould not create bitmap header for Pixmap\n");
4736 goto END;
4740 * Create a packed DIB from the Pixmap wrapper bitmap created above.
4741 * A packed DIB contains a BITMAPINFO structure followed immediately by
4742 * an optional color palette and the pixel data.
4744 hPackedDIB = DIB_CreateDIBFromBitmap(hdc, hBmp);
4746 /* Get a pointer to the BITMAPOBJ structure */
4747 pBmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
4749 /* We can now get rid of the HBITMAP wrapper we created earlier.
4750 * Note: Simply calling DeleteObject will free the embedded Pixmap as well.
4752 if (!bDeletePixmap)
4754 /* Clear the physBitmap to prevent the Pixmap from being deleted by DeleteObject */
4755 pBmp->physBitmap = NULL;
4756 pBmp->funcs = NULL;
4758 GDI_ReleaseObj( hBmp );
4759 DeleteObject(hBmp);
4761 END:
4762 TRACE("\tReturning packed DIB %p\n", hPackedDIB);
4763 return hPackedDIB;
4767 /**************************************************************************
4768 * X11DRV_DIB_CreatePixmapFromDIB
4770 * Creates a Pixmap from a packed DIB
4772 Pixmap X11DRV_DIB_CreatePixmapFromDIB( HGLOBAL hPackedDIB, HDC hdc )
4774 Pixmap pixmap = None;
4775 HBITMAP hBmp = 0;
4776 BITMAPOBJ *pBmp = NULL;
4777 LPBYTE pPackedDIB = NULL;
4778 LPBITMAPINFO pbmi = NULL;
4779 LPBITMAPINFOHEADER pbmiHeader = NULL;
4780 LPBYTE pbits = NULL;
4782 /* Get a pointer to the packed DIB's data */
4783 pPackedDIB = (LPBYTE)GlobalLock(hPackedDIB);
4784 pbmiHeader = (LPBITMAPINFOHEADER)pPackedDIB;
4785 pbmi = (LPBITMAPINFO)pPackedDIB;
4786 pbits = (LPBYTE)(pPackedDIB
4787 + DIB_BitmapInfoSize( (LPBITMAPINFO)pbmiHeader, DIB_RGB_COLORS ));
4789 /* Create a DDB from the DIB */
4791 hBmp = CreateDIBitmap(hdc,
4792 pbmiHeader,
4793 CBM_INIT,
4794 (LPVOID)pbits,
4795 pbmi,
4796 DIB_RGB_COLORS);
4798 GlobalUnlock(hPackedDIB);
4800 TRACE("CreateDIBitmap returned %p\n", hBmp);
4802 /* Retrieve the internal Pixmap from the DDB */
4804 pBmp = (BITMAPOBJ *) GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
4806 pixmap = (Pixmap)pBmp->physBitmap;
4807 /* clear the physBitmap so that we can steal its pixmap */
4808 pBmp->physBitmap = NULL;
4809 pBmp->funcs = NULL;
4811 /* Delete the DDB we created earlier now that we have stolen its pixmap */
4812 GDI_ReleaseObj( hBmp );
4813 DeleteObject(hBmp);
4815 TRACE("\tReturning Pixmap %ld\n", pixmap);
4816 return pixmap;