Changing DIB color table now updates the DIB visible state.
[wine/multimedia.git] / graphics / x11drv / dib.c
blob2ebc269d72653cf38011222f0e166ad8cebcf6aa
1 /*
2 * X11DRV device-independent bitmaps
4 * Copyright 1993,1994 Alexandre Julliard
5 */
7 #include "config.h"
9 #include "ts_xlib.h"
10 #include "ts_xutil.h"
11 #ifdef HAVE_LIBXXSHM
12 # include "ts_xshm.h"
13 # ifdef HAVE_SYS_SHM_H
14 # include <sys/shm.h>
15 # endif
16 # ifdef HAVE_SYS_IPC_H
17 # include <sys/ipc.h>
18 # endif
19 #endif /* defined(HAVE_LIBXXSHM) */
21 #include <stdlib.h>
22 #include <string.h>
23 #include "windef.h"
24 #include "bitmap.h"
25 #include "x11drv.h"
26 #include "debugtools.h"
27 #include "gdi.h"
28 #include "palette.h"
29 #include "global.h"
31 DEFAULT_DEBUG_CHANNEL(bitmap);
32 DECLARE_DEBUG_CHANNEL(x11drv);
34 static int ximageDepthTable[32];
36 #ifdef HAVE_LIBXXSHM
37 static int XShmErrorFlag = 0;
38 #endif
40 /* This structure holds the arguments for DIB_SetImageBits() */
41 typedef struct
43 struct tagDC *dc;
44 LPCVOID bits;
45 XImage *image;
46 PALETTEENTRY *palentry;
47 int lines;
48 DWORD infoWidth;
49 WORD depth;
50 WORD infoBpp;
51 WORD compression;
52 RGBQUAD *colorMap;
53 int nColorMap;
54 Drawable drawable;
55 GC gc;
56 int xSrc;
57 int ySrc;
58 int xDest;
59 int yDest;
60 int width;
61 int height;
62 DWORD rMask;
63 DWORD gMask;
64 DWORD bMask;
65 BOOL useShm;
66 int dibpitch;
67 } X11DRV_DIB_IMAGEBITS_DESCR;
70 /***********************************************************************
71 * X11DRV_DIB_GetXImageWidthBytes
73 * Return the width of an X image in bytes
75 inline static int X11DRV_DIB_GetXImageWidthBytes( int width, int depth )
77 if (!depth || depth > 32) goto error;
79 if (!ximageDepthTable[depth-1])
81 XImage *testimage = XCreateImage( gdi_display, visual, depth,
82 ZPixmap, 0, NULL, 1, 1, 32, 20 );
83 if (testimage)
85 ximageDepthTable[depth-1] = testimage->bits_per_pixel;
86 XDestroyImage( testimage );
88 else ximageDepthTable[depth-1] = -1;
90 if (ximageDepthTable[depth-1] != -1)
91 return (4 * ((width * ximageDepthTable[depth-1] + 31) / 32));
93 error:
94 WARN( "(%d): Unsupported depth\n", depth );
95 return 4 * width;
99 /***********************************************************************
100 * X11DRV_DIB_CreateXImage
102 * Create an X image.
104 XImage *X11DRV_DIB_CreateXImage( int width, int height, int depth )
106 int width_bytes;
107 XImage *image;
109 wine_tsx11_lock();
110 width_bytes = X11DRV_DIB_GetXImageWidthBytes( width, depth );
111 image = XCreateImage( gdi_display, visual, depth, ZPixmap, 0,
112 calloc( height, width_bytes ),
113 width, height, 32, width_bytes );
114 wine_tsx11_unlock();
115 return image;
119 /***********************************************************************
120 * X11DRV_DIB_GenColorMap
122 * Fills the color map of a bitmap palette. Should not be called
123 * for a >8-bit deep bitmap.
125 int *X11DRV_DIB_GenColorMap( DC *dc, int *colorMapping,
126 WORD coloruse, WORD depth, BOOL quads,
127 const void *colorPtr, int start, int end )
129 int i;
131 if (coloruse == DIB_RGB_COLORS)
133 if (quads)
135 RGBQUAD * rgb = (RGBQUAD *)colorPtr;
137 if (depth == 1) /* Monochrome */
138 for (i = start; i < end; i++, rgb++)
139 colorMapping[i] = (rgb->rgbRed + rgb->rgbGreen +
140 rgb->rgbBlue > 255*3/2);
141 else
142 for (i = start; i < end; i++, rgb++)
143 colorMapping[i] = X11DRV_PALETTE_ToPhysical( dc, RGB(rgb->rgbRed,
144 rgb->rgbGreen,
145 rgb->rgbBlue));
147 else
149 RGBTRIPLE * rgb = (RGBTRIPLE *)colorPtr;
151 if (depth == 1) /* Monochrome */
152 for (i = start; i < end; i++, rgb++)
153 colorMapping[i] = (rgb->rgbtRed + rgb->rgbtGreen +
154 rgb->rgbtBlue > 255*3/2);
155 else
156 for (i = start; i < end; i++, rgb++)
157 colorMapping[i] = X11DRV_PALETTE_ToPhysical( dc, RGB(rgb->rgbtRed,
158 rgb->rgbtGreen,
159 rgb->rgbtBlue));
162 else /* DIB_PAL_COLORS */
164 if (colorPtr) {
165 WORD * index = (WORD *)colorPtr;
167 for (i = start; i < end; i++, index++)
168 colorMapping[i] = X11DRV_PALETTE_ToPhysical( dc, PALETTEINDEX(*index) );
169 } else {
170 for (i = start; i < end; i++)
171 colorMapping[i] = X11DRV_PALETTE_ToPhysical( dc, PALETTEINDEX(i) );
175 return colorMapping;
178 /***********************************************************************
179 * X11DRV_DIB_BuildColorMap
181 * Build the color map from the bitmap palette. Should not be called
182 * for a >8-bit deep bitmap.
184 int *X11DRV_DIB_BuildColorMap( DC *dc, WORD coloruse, WORD depth,
185 const BITMAPINFO *info, int *nColors )
187 int colors;
188 BOOL isInfo;
189 const void *colorPtr;
190 int *colorMapping;
192 if ((isInfo = (info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))))
194 colors = info->bmiHeader.biClrUsed;
195 if (!colors) colors = 1 << info->bmiHeader.biBitCount;
196 colorPtr = info->bmiColors;
198 else /* assume BITMAPCOREINFO */
200 colors = 1 << ((BITMAPCOREHEADER *)&info->bmiHeader)->bcBitCount;
201 colorPtr = (WORD *)((BITMAPCOREINFO *)info)->bmciColors;
204 if (colors > 256)
206 ERR("called with >256 colors!\n");
207 return NULL;
210 /* just so CopyDIBSection doesn't have to create an identity palette */
211 if (coloruse == (WORD)-1) colorPtr = NULL;
213 if (!(colorMapping = (int *)HeapAlloc(GetProcessHeap(), 0,
214 colors * sizeof(int) )))
215 return NULL;
217 *nColors = colors;
218 return X11DRV_DIB_GenColorMap( dc, colorMapping, coloruse, depth,
219 isInfo, colorPtr, 0, colors);
223 /***********************************************************************
224 * X11DRV_DIB_MapColor
226 int X11DRV_DIB_MapColor( int *physMap, int nPhysMap, int phys, int oldcol )
228 int color;
230 if ((oldcol < nPhysMap) && (physMap[oldcol] == phys))
231 return oldcol;
233 for (color = 0; color < nPhysMap; color++)
234 if (physMap[color] == phys)
235 return color;
237 WARN("Strange color %08x\n", phys);
238 return 0;
242 /*********************************************************************
243 * X11DRV_DIB_GetNearestIndex
245 * Helper for X11DRV_DIB_GetDIBits.
246 * Returns the nearest colour table index for a given RGB.
247 * Nearest is defined by minimizing the sum of the squares.
249 static INT X11DRV_DIB_GetNearestIndex(RGBQUAD *colormap, int numColors, BYTE r, BYTE g, BYTE b)
251 INT i, best = -1, diff, bestdiff = -1;
252 RGBQUAD *color;
254 for(color = colormap, i = 0; i < numColors; color++, i++) {
255 diff = (r - color->rgbRed) * (r - color->rgbRed) +
256 (g - color->rgbGreen) * (g - color->rgbGreen) +
257 (b - color->rgbBlue) * (b - color->rgbBlue);
258 if(diff == 0)
259 return i;
260 if(best == -1 || diff < bestdiff) {
261 best = i;
262 bestdiff = diff;
265 return best;
268 /***********************************************************************
269 * X11DRV_DIB_SetImageBits_1_Line
271 * Handles a single line of 1 bit data.
273 static void X11DRV_DIB_SetImageBits_1_Line(DWORD dstwidth, int left, int *colors,
274 XImage *bmpImage, int h, const BYTE *bits)
276 BYTE pix, extra;
277 DWORD i, x;
279 if((extra = (left & 7)) != 0) {
280 left &= ~7;
281 dstwidth += extra;
284 bits += left >> 3;
286 /* FIXME: should avoid putting x<left pixels (minor speed issue) */
287 for (i = dstwidth/8, x = left; i > 0; i--)
289 pix = *bits++;
290 XPutPixel( bmpImage, x++, h, colors[pix >> 7] );
291 XPutPixel( bmpImage, x++, h, colors[(pix >> 6) & 1] );
292 XPutPixel( bmpImage, x++, h, colors[(pix >> 5) & 1] );
293 XPutPixel( bmpImage, x++, h, colors[(pix >> 4) & 1] );
294 XPutPixel( bmpImage, x++, h, colors[(pix >> 3) & 1] );
295 XPutPixel( bmpImage, x++, h, colors[(pix >> 2) & 1] );
296 XPutPixel( bmpImage, x++, h, colors[(pix >> 1) & 1] );
297 XPutPixel( bmpImage, x++, h, colors[pix & 1] );
299 pix = *bits;
300 switch(dstwidth & 7)
302 case 7: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
303 case 6: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
304 case 5: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
305 case 4: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
306 case 3: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
307 case 2: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
308 case 1: XPutPixel( bmpImage, x++, h, colors[pix >> 7] );
312 /***********************************************************************
313 * X11DRV_DIB_SetImageBits_1
315 * SetDIBits for a 1-bit deep DIB.
317 static void X11DRV_DIB_SetImageBits_1( int lines, const BYTE *srcbits,
318 DWORD srcwidth, DWORD dstwidth, int left,
319 int *colors, XImage *bmpImage, DWORD linebytes)
321 int h;
323 if (lines > 0) {
324 for (h = lines-1; h >=0; h--) {
325 X11DRV_DIB_SetImageBits_1_Line(dstwidth, left, colors, bmpImage, h,
326 srcbits);
327 srcbits += linebytes;
329 } else {
330 lines = -lines;
331 for (h = 0; h < lines; h++) {
332 X11DRV_DIB_SetImageBits_1_Line(dstwidth, left, colors, bmpImage, h,
333 srcbits);
334 srcbits += linebytes;
339 /***********************************************************************
340 * X11DRV_DIB_GetImageBits_1
342 * GetDIBits for a 1-bit deep DIB.
344 static void X11DRV_DIB_GetImageBits_1( int lines, BYTE *dstbits,
345 DWORD dstwidth, DWORD srcwidth,
346 RGBQUAD *colors, PALETTEENTRY *srccolors,
347 XImage *bmpImage, DWORD linebytes )
349 DWORD x;
350 int h;
351 BYTE *bits;
353 if (lines < 0 ) {
354 lines = -lines;
355 dstbits = dstbits + linebytes * (lines - 1);
356 linebytes = -linebytes;
359 bits = dstbits;
361 switch(bmpImage->depth) {
363 case 1:
364 /* ==== monochrome bitmap to monochrome dib ==== */
365 case 4:
366 /* ==== 4 colormap bitmap to monochrome dib ==== */
367 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
369 PALETTEENTRY val;
371 for (h = lines - 1; h >= 0; h--) {
372 for (x = 0; x < dstwidth; x++) {
373 val = srccolors[XGetPixel(bmpImage, x, h)];
374 if (!(x&7)) *bits = 0;
375 *bits |= (X11DRV_DIB_GetNearestIndex(colors, 2,
376 val.peRed,
377 val.peGreen,
378 val.peBlue) << (7 - (x & 7)));
379 if ((x&7)==7) bits++;
381 bits = (dstbits += linebytes);
384 else goto notsupported;
386 break;
388 case 8:
389 /* ==== 8 colormap bitmap to monochrome dib ==== */
390 if ( bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
392 BYTE *srcpixel;
393 PALETTEENTRY val;
395 for( h = lines- 1; h >= 0; h-- ) {
396 srcpixel = bmpImage->data + (h*bmpImage->bytes_per_line);
397 for( x = 0; x < dstwidth; x++ ) {
398 if (!(x&7)) *bits = 0;
399 val = srccolors[(int)*srcpixel++];
400 *bits |= ( X11DRV_DIB_GetNearestIndex(colors, 2,
401 val.peRed,
402 val.peGreen,
403 val.peBlue) << (7-(x&7)) );
404 if ((x&7)==7) bits++;
406 bits = (dstbits += linebytes);
409 else goto notsupported;
411 break;
413 case 15:
415 LPWORD srcpixel;
416 WORD val;
418 /* ==== 555 BGR bitmap to monochrome dib ==== */
419 if (bmpImage->red_mask == 0x7c00 && bmpImage->blue_mask == 0x1f)
421 for( h = lines - 1; h >= 0; h--) {
422 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
423 for( x = 0; x < dstwidth; x++) {
424 if (!(x&7)) *bits = 0;
425 val = *srcpixel++;
426 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 2,
427 ((val >> 7) & 0xf8) |
428 ((val >> 12) & 0x7),
429 ((val >> 2) & 0xf8) |
430 ((val >> 7) & 0x3),
431 ((val << 3) & 0xf8) |
432 ((val >> 2) & 0x7) ) << (7-(x&7)) );
433 if ((x&7)==7) bits++;
435 bits = (dstbits += linebytes);
438 /* ==== 555 RGB bitmap to monochrome dib ==== */
439 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0xf800)
441 for( h = lines - 1; h >= 0; h--)
443 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
444 for( x = 0; x < dstwidth; x++) {
445 if (!(x&1)) *bits = 0;
446 val = *srcpixel++;
447 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 2,
448 ((val << 3) & 0xf8) |
449 ((val >> 2) & 0x7),
450 ((val >> 2) & 0xf8) |
451 ((val >> 7) & 0x3),
452 ((val >> 7) & 0xf8) |
453 ((val >> 12) & 0x7) ) << (7-(x&7)) );
454 if ((x&7)==7) bits++;
456 bits = (dstbits += linebytes);
459 else goto notsupported;
461 break;
463 case 16:
465 LPWORD srcpixel;
466 WORD val;
468 /* ==== 565 BGR bitmap to monochrome dib ==== */
469 if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f)
471 for( h = lines - 1; h >= 0; h--)
473 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
474 for( x = 0; x < dstwidth; x++) {
475 if (!(x&7)) *bits = 0;
476 val = *srcpixel++;
477 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 2,
478 ((val >> 8) & 0xf8) |
479 ((val >> 13) & 0x7),
480 ((val >> 3) & 0xfc) |
481 ((val >> 9) & 0x3),
482 ((val << 3) & 0xf8) |
483 ((val >> 2) & 0x7) ) << (7-(x&7)) );
484 if ((x&7)==7) bits++;
486 bits = (dstbits += linebytes);
489 /* ==== 565 RGB bitmap to monochrome dib ==== */
490 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0xf800)
492 for( h = lines - 1; h >= 0; h--)
494 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
495 for( x = 0; x < dstwidth; x++) {
496 if (!(x&7)) *bits = 0;
497 val = *srcpixel++;
498 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 2,
499 ((val << 3) & 0xf8) |
500 ((val >> 2) & 0x7),
501 ((val >> 3) & 0xfc) |
502 ((val >> 9) & 0x3),
503 ((val >> 8) & 0xf8) |
504 ((val >> 13) & 0x7) ) << (7-(x&7)) );
505 if ((x&7)==7) bits++;
507 bits = (dstbits += linebytes);
510 else goto notsupported;
512 break;
514 case 24:
515 case 32:
517 BYTE *srcpixel;
519 /* ==== 24/32 BGR bitmap to monochrome dib ==== */
520 if (bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff)
522 for (h = lines - 1; h >= 0; h--)
524 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
525 for (x = 0; x < dstwidth; x++, srcpixel+=4) {
526 if (!(x&7)) *bits = 0;
527 *bits |= (X11DRV_DIB_GetNearestIndex(colors, 2, srcpixel[2] , srcpixel[1], srcpixel[0]) << (7-(x&7)) );
528 if ((x&7)==7) bits++;
530 bits = (dstbits += linebytes);
533 /* ==== 24/32 RGB bitmap to monochrome dib ==== */
534 else if (bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000)
536 for (h = lines - 1; h >= 0; h--)
538 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
539 for (x = 0; x < dstwidth; x++, srcpixel+=4) {
540 if (!(x & 7)) *bits = 0;
541 *bits |= (X11DRV_DIB_GetNearestIndex(colors, 2, srcpixel[0] , srcpixel[1], srcpixel[2]) << (7-(x&7)) );
542 if ((x & 7) == 7) bits++;
544 bits = (dstbits += linebytes);
547 else goto notsupported;
549 break;
551 default: /* ? bit bmp -> monochrome DIB */
552 notsupported:
554 unsigned long white = (1 << bmpImage->bits_per_pixel) - 1;
556 FIXME("from %d bit bitmap with mask R,G,B %x,%x,%x to 1 bit DIB\n",
557 bmpImage->bits_per_pixel, (int)bmpImage->red_mask,
558 (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
560 for( h = lines - 1; h >= 0; h-- ) {
561 for( x = 0; x < dstwidth; x++ ) {
562 if (!(x&7)) *bits = 0;
563 *bits |= (XGetPixel( bmpImage, x, h) >= white)
564 << (7 - (x&7));
565 if ((x&7)==7) bits++;
567 bits = (dstbits += linebytes);
570 break;
574 /***********************************************************************
575 * X11DRV_DIB_SetImageBits_4
577 * SetDIBits for a 4-bit deep DIB.
579 static void X11DRV_DIB_SetImageBits_4( int lines, const BYTE *srcbits,
580 DWORD srcwidth, DWORD dstwidth, int left,
581 int *colors, XImage *bmpImage, DWORD linebytes)
583 DWORD i, x;
584 int h;
585 const BYTE *bits = srcbits + (left >> 1);
587 if(left & 1) {
588 left--;
589 dstwidth++;
592 if (lines > 0) {
593 for (h = lines-1; h >= 0; h--) {
594 for (i = dstwidth/2, x = left; i > 0; i--) {
595 BYTE pix = *bits++;
596 XPutPixel( bmpImage, x++, h, colors[pix >> 4] );
597 XPutPixel( bmpImage, x++, h, colors[pix & 0x0f] );
599 if (dstwidth & 1) XPutPixel( bmpImage, x, h, colors[*bits >> 4] );
600 srcbits += linebytes;
601 bits = srcbits + (left >> 1);
603 } else {
604 lines = -lines;
605 for (h = 0; h < lines; h++) {
606 for (i = dstwidth/2, x = left; i > 0; i--) {
607 BYTE pix = *bits++;
608 XPutPixel( bmpImage, x++, h, colors[pix >> 4] );
609 XPutPixel( bmpImage, x++, h, colors[pix & 0x0f] );
611 if (dstwidth & 1) XPutPixel( bmpImage, x, h, colors[*bits >> 4] );
612 srcbits += linebytes;
613 bits = srcbits + (left >> 1);
620 /***********************************************************************
621 * X11DRV_DIB_GetImageBits_4
623 * GetDIBits for a 4-bit deep DIB.
625 static void X11DRV_DIB_GetImageBits_4( int lines, BYTE *dstbits,
626 DWORD srcwidth, DWORD dstwidth,
627 RGBQUAD *colors, PALETTEENTRY *srccolors,
628 XImage *bmpImage, DWORD linebytes )
630 DWORD x;
631 int h;
632 BYTE *bits;
633 LPBYTE srcpixel;
635 if (lines < 0 )
637 lines = -lines;
638 dstbits = dstbits + ( linebytes * (lines-1) );
639 linebytes = -linebytes;
642 bits = dstbits;
644 switch(bmpImage->depth) {
646 case 1:
647 /* ==== monochrome bitmap to 4 colormap dib ==== */
648 case 4:
649 /* ==== 4 colormap bitmap to 4 colormap dib ==== */
650 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
652 PALETTEENTRY val;
654 for (h = lines-1; h >= 0; h--) {
655 for (x = 0; x < dstwidth; x++) {
656 if (!(x&1)) *bits = 0;
657 val = srccolors[XGetPixel(bmpImage, x, h)];
658 *bits |= (X11DRV_DIB_GetNearestIndex(colors, 16,
659 val.peRed,
660 val.peGreen,
661 val.peBlue) << (4-((x&1)<<2)));
662 if ((x&1)==1) bits++;
664 bits = (dstbits += linebytes);
667 else goto notsupported;
669 break;
671 case 8:
672 /* ==== 8 colormap bitmap to 4 colormap dib ==== */
673 if ( bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
675 PALETTEENTRY val;
677 for( h = lines - 1; h >= 0; h-- ) {
678 srcpixel = bmpImage->data + (h*bmpImage->bytes_per_line);
679 for( x = 0; x < dstwidth; x++ ) {
680 if (!(x&1)) *bits = 0;
681 val = srccolors[(int)*srcpixel++];
682 *bits |= ( X11DRV_DIB_GetNearestIndex(colors, 16,
683 val.peRed,
684 val.peGreen,
685 val.peBlue) << (4*(1-(x&1))) );
686 if ((x&1)==1) bits++;
688 bits = (dstbits += linebytes);
691 else goto notsupported;
693 break;
695 case 15:
697 LPWORD srcpixel;
698 WORD val;
700 /* ==== 555 BGR bitmap to 4 colormap dib ==== */
701 if (bmpImage->red_mask == 0x7c00 && bmpImage->blue_mask == 0x1f)
703 for( h = lines - 1; h >= 0; h--) {
704 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
705 for( x = 0; x < dstwidth; x++) {
706 if (!(x&1)) *bits = 0;
707 val = *srcpixel++;
708 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 16,
709 ((val >> 7) & 0xf8) |
710 ((val >> 12) & 0x7),
711 ((val >> 2) & 0xf8) |
712 ((val >> 7) & 0x3),
713 ((val << 3) & 0xf8) |
714 ((val >> 2) & 0x7) ) << ((1-(x&1))<<2) );
715 if ((x&1)==1) bits++;
717 bits = (dstbits += linebytes);
720 /* ==== 555 RGB bitmap to 4 colormap dib ==== */
721 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0x7c00)
723 for( h = lines - 1; h >= 0; h--)
725 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
726 for( x = 0; x < dstwidth; x++) {
727 if (!(x&1)) *bits = 0;
728 val = *srcpixel++;
729 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 16,
730 ((val << 3) & 0xf8) |
731 ((val >> 2) & 0x7),
732 ((val >> 2) & 0xfc) |
733 ((val >> 7) & 0x3),
734 ((val >> 7) & 0xf8) |
735 ((val >> 12) & 0x7) ) << ((1-(x&1))<<2) );
736 if ((x&1)==1) bits++;
738 bits = (dstbits += linebytes);
741 else goto notsupported;
743 break;
745 case 16:
747 LPWORD srcpixel;
748 WORD val;
750 /* ==== 565 BGR bitmap to 4 colormap dib ==== */
751 if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f)
753 for( h = lines - 1; h >= 0; h--)
755 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
756 for( x = 0; x < dstwidth; x++) {
757 if (!(x&1)) *bits = 0;
758 val = *srcpixel++;
759 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 16,
760 ((val >> 8) & 0xf8) |
761 ((val >> 13) & 0x7),
762 ((val >> 3) & 0xfc) |
763 ((val >> 9) & 0x3),
764 ((val << 3) & 0xf8) |
765 ((val >> 2) & 0x7) ) << ((1-(x&1))<<2) );
766 if ((x&1)==1) bits++;
768 bits = (dstbits += linebytes);
771 /* ==== 565 RGB bitmap to 4 colormap dib ==== */
772 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0xf800)
774 for( h = lines - 1; h >= 0; h--)
776 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
777 for( x = 0; x < dstwidth; x++) {
778 if (!(x&1)) *bits = 0;
779 val = *srcpixel++;
780 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 16,
781 ((val << 3) & 0xf8) |
782 ((val >> 2) & 0x7),
783 ((val >> 3) & 0xfc) |
784 ((val >> 9) & 0x3),
785 ((val >> 8) & 0xf8) |
786 ((val >> 13) & 0x7) ) << ((1-(x&1))<<2) );
787 if ((x&1)==1) bits++;
789 bits = (dstbits += linebytes);
792 else goto notsupported;
794 break;
796 case 24:
797 case 32:
799 BYTE *srcpixel;
801 /* ==== 24/32 BGR bitmap to 4 colormap dib ==== */
802 if (bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff)
804 for (h = lines - 1; h >= 0; h--)
806 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
807 for (x = 0; x < dstwidth; x+=2, srcpixel+=8) /* 2 pixels at a time */
808 *bits++ = (X11DRV_DIB_GetNearestIndex(colors, 16, srcpixel[2] , srcpixel[1], srcpixel[0]) << 4) |
809 X11DRV_DIB_GetNearestIndex(colors, 16, srcpixel[6] , srcpixel[5], srcpixel[4]);
810 bits = (dstbits += linebytes);
813 /* ==== 24/32 RGB bitmap to 4 colormap dib ==== */
814 else if (bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000)
816 for (h = lines - 1; h >= 0; h--)
818 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
819 for (x = 0; x < dstwidth; x+=2, srcpixel+=8) /* 2 pixels at a time */
820 *bits++ = (X11DRV_DIB_GetNearestIndex(colors, 16, srcpixel[0] , srcpixel[1], srcpixel[2]) << 4) |
821 X11DRV_DIB_GetNearestIndex(colors, 16, srcpixel[4] , srcpixel[5], srcpixel[6]);
822 bits = (dstbits += linebytes);
825 else goto notsupported;
827 break;
829 default: /* ? bit bmp -> 4 bit DIB */
830 notsupported:
831 FIXME("from %d bit bitmap with mask R,G,B %x,%x,%x to 4 bit DIB\n",
832 bmpImage->bits_per_pixel, (int)bmpImage->red_mask,
833 (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
834 for (h = lines-1; h >= 0; h--) {
835 for (x = 0; x < dstwidth-1; x += 2)
837 *bits++ = (X11DRV_DIB_MapColor((int *)colors, 16, XGetPixel( bmpImage, x, h ), 0) << 4)
838 | (X11DRV_DIB_MapColor((int *)colors, 16, XGetPixel( bmpImage, x+1, h ), 0) & 0x0f);
840 if (dstwidth & 1)
841 *bits = (X11DRV_DIB_MapColor((int *)colors, 16, XGetPixel( bmpImage, x, h ), 0) << 4);
842 bits = (dstbits += linebytes);
844 break;
848 /***********************************************************************
849 * X11DRV_DIB_SetImageBits_RLE4
851 * SetDIBits for a 4-bit deep compressed DIB.
853 static void X11DRV_DIB_SetImageBits_RLE4( int lines, const BYTE *bits,
854 DWORD width, DWORD dstwidth,
855 int left, int *colors,
856 XImage *bmpImage )
858 int x = 0, c, length;
859 const BYTE *begin = bits;
861 lines--;
863 while ((int)lines >= 0) {
864 length = *bits++;
865 if (length) { /* encoded */
866 c = *bits++;
867 while (length--) {
868 if(x >= width) {
869 x = 0;
870 if(--lines < 0)
871 return;
873 XPutPixel(bmpImage, x++, lines, colors[c >>4]);
874 if (length) {
875 length--;
876 if(x >= width) {
877 x = 0;
878 if(--lines < 0)
879 return;
881 XPutPixel(bmpImage, x++, lines, colors[c & 0xf]);
884 } else {
885 length = *bits++;
886 switch (length) {
887 case 0: /* eol */
888 x = 0;
889 lines--;
890 continue;
892 case 1: /* eopicture */
893 return;
895 case 2: /* delta */
896 x += *bits++;
897 if(x >= width) {
898 FIXME_(x11drv)("x-delta is too large?\n");
899 return;
901 lines -= *bits++;
902 continue;
904 default: /* absolute */
905 while (length--) {
906 c = *bits++;
907 if(x >= width) {
908 x = 0;
909 if(--lines < 0)
910 return;
912 XPutPixel(bmpImage, x++, lines, colors[c >> 4]);
913 if (length) {
914 length--;
915 if(x >= width) {
916 x = 0;
917 if(--lines < 0)
918 return;
920 XPutPixel(bmpImage, x++, lines, colors[c & 0xf]);
923 if ((bits - begin) & 1)
924 bits++;
932 /***********************************************************************
933 * X11DRV_DIB_SetImageBits_8
935 * SetDIBits for an 8-bit deep DIB.
937 static void X11DRV_DIB_SetImageBits_8( int lines, const BYTE *srcbits,
938 DWORD srcwidth, DWORD dstwidth, int left,
939 const int *colors, XImage *bmpImage,
940 DWORD linebytes )
942 DWORD x;
943 int h, color;
944 const BYTE *bits;
946 dstwidth += left;
948 if (lines < 0 )
950 lines = -lines;
951 srcbits = srcbits + ( linebytes * (lines-1) );
952 linebytes = -linebytes;
955 bits = srcbits + left;
957 switch (bmpImage->depth) {
958 case 15:
959 case 16:
960 #if defined(__i386__) && defined(__GNUC__)
961 /* Some X servers might have 32 bit/ 16bit deep pixel */
962 if (lines && (dstwidth!=left) && (bmpImage->bits_per_pixel == 16))
964 for (h = lines ; h--; ) {
965 int _cl1,_cl2; /* temp outputs for asm below */
966 /* Borrowed from DirectDraw */
967 __asm__ __volatile__(
968 "xor %%eax,%%eax\n"
969 "cld\n"
970 "1:\n"
971 " lodsb\n"
972 " movw (%%edx,%%eax,4),%%ax\n"
973 " stosw\n"
974 " xor %%eax,%%eax\n"
975 " loop 1b\n"
976 :"=S" (bits), "=D" (_cl1), "=c" (_cl2)
977 :"S" (bits),
978 "D" (bmpImage->data+h*bmpImage->bytes_per_line+left*2),
979 "c" (dstwidth-left),
980 "d" (colors)
981 :"eax", "cc", "memory"
983 bits = (srcbits += linebytes) + left;
985 return;
987 break;
988 #endif
989 case 24:
990 #if defined(__i386__) && defined(__GNUC__)
991 if (lines && (dstwidth!=left) && (bmpImage->bits_per_pixel == 32))
993 for (h = lines ; h--; ) {
994 int _cl1,_cl2; /* temp outputs for asm below */
995 /* Borrowed from DirectDraw */
996 __asm__ __volatile__(
997 "xor %%eax,%%eax\n"
998 "cld\n"
999 "1:\n"
1000 " lodsb\n"
1001 " movl (%%edx,%%eax,4),%%eax\n"
1002 " stosl\n"
1003 " xor %%eax,%%eax\n"
1004 " loop 1b\n"
1005 :"=S" (bits), "=D" (_cl1), "=c" (_cl2)
1006 :"S" (bits),
1007 "D" (bmpImage->data+h*bmpImage->bytes_per_line+left*4),
1008 "c" (dstwidth-left),
1009 "d" (colors)
1010 :"eax", "cc", "memory"
1012 bits = (srcbits += linebytes) + left;
1014 return;
1016 break;
1017 #endif
1018 default:
1019 break; /* use slow generic case below */
1022 for (h = lines - 1; h >= 0; h--) {
1023 for (x = left; x < dstwidth; x++, bits++) {
1024 color = colors[*bits];
1025 XPutPixel( bmpImage, x, h, colors[*bits] );
1027 bits = (srcbits += linebytes) + left;
1031 /***********************************************************************
1032 * X11DRV_DIB_GetImageBits_8
1034 * GetDIBits for an 8-bit deep DIB.
1036 static void X11DRV_DIB_GetImageBits_8( int lines, BYTE *dstbits,
1037 DWORD srcwidth, DWORD dstwidth,
1038 RGBQUAD *colors, PALETTEENTRY *srccolors,
1039 XImage *bmpImage, DWORD linebytes )
1041 DWORD x;
1042 int h;
1043 BYTE *bits;
1045 if (lines < 0 )
1047 lines = -lines;
1048 dstbits = dstbits + ( linebytes * (lines-1) );
1049 linebytes = -linebytes;
1052 bits = dstbits;
1055 Hack for now
1056 This condition is true when GetImageBits has been called by UpdateDIBSection.
1057 For now, GetNearestIndex is too slow to support 256 colormaps, so we'll just use for
1058 for GetDIBits calls. (In somes cases, in a updateDIBSection, the returned colors are bad too)
1060 if (!srccolors) goto updatesection;
1062 switch(bmpImage->depth) {
1064 case 1:
1065 /* ==== monochrome bitmap to 8 colormap dib ==== */
1066 case 4:
1067 /* ==== 4 colormap bitmap to 8 colormap dib ==== */
1068 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
1070 PALETTEENTRY val;
1072 for (h = lines - 1; h >= 0; h--) {
1073 for (x = 0; x < dstwidth; x++) {
1074 val = srccolors[XGetPixel(bmpImage, x, h)];
1075 *bits++ = X11DRV_DIB_GetNearestIndex(colors, 256, val.peRed,
1076 val.peGreen, val.peBlue);
1078 bits = (dstbits += linebytes);
1081 else goto notsupported;
1083 break;
1085 case 8:
1086 /* ==== 8 colormap bitmap to 8 colormap dib ==== */
1087 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
1089 BYTE *srcpixel;
1090 PALETTEENTRY val;
1092 for (h = lines - 1; h >= 0; h--) {
1093 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
1094 for (x = 0; x < dstwidth; x++) {
1095 val = srccolors[(int)*srcpixel++];
1096 *bits++ = X11DRV_DIB_GetNearestIndex(colors, 256, val.peRed,
1097 val.peGreen, val.peBlue);
1099 bits = (dstbits += linebytes);
1102 else goto notsupported;
1104 break;
1106 case 15:
1108 LPWORD srcpixel;
1109 WORD val;
1111 /* ==== 555 BGR bitmap to 8 colormap dib ==== */
1112 if (bmpImage->red_mask == 0x7c00 && bmpImage->blue_mask == 0x001f)
1114 for( h = lines - 1; h >= 0; h--)
1116 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
1117 for( x = 0; x < dstwidth; x++ )
1119 val = *srcpixel++;
1120 *bits++ = X11DRV_DIB_GetNearestIndex( colors, 256,
1121 ((val >> 7) & 0xf8) |
1122 ((val >> 12) & 0x7),
1123 ((val >> 2) & 0xf8) |
1124 ((val >> 7) & 0x3),
1125 ((val << 3) & 0xf8) |
1126 ((val >> 2) & 0x7) );
1128 bits = (dstbits += linebytes);
1131 /* ==== 555 RGB bitmap to 8 colormap dib ==== */
1132 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0x7c00)
1134 for( h = lines - 1; h >= 0; h--)
1136 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
1137 for( x = 0; x < dstwidth; x++ )
1139 val = *srcpixel++;
1140 *bits++ = X11DRV_DIB_GetNearestIndex( colors, 256,
1141 ((val << 3) & 0xf8) |
1142 ((val >> 2) & 0x7),
1143 ((val >> 2) & 0xf8) |
1144 ((val >> 7) & 0x3),
1145 ((val >> 7) & 0xf8) |
1146 ((val >> 12) & 0x7) );
1148 bits = (dstbits += linebytes);
1151 else goto notsupported;
1153 break;
1155 case 16:
1157 LPWORD srcpixel;
1158 WORD val;
1160 /* ==== 565 BGR bitmap to 8 colormap dib ==== */
1161 if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f)
1163 for( h = lines - 1; h >= 0; h--)
1165 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
1166 for( x = 0; x < dstwidth; x++ )
1168 val = *srcpixel++;
1169 *bits++ = X11DRV_DIB_GetNearestIndex( colors, 256,
1170 ((val >> 8) & 0xf8) |
1171 ((val >> 13) & 0x7),
1172 ((val >> 3) & 0xfc) |
1173 ((val >> 9) & 0x3),
1174 ((val << 3) & 0xf8) |
1175 ((val >> 2) & 0x7) );
1177 bits = (dstbits += linebytes);
1180 /* ==== 565 RGB bitmap to 8 colormap dib ==== */
1181 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0xf800)
1183 for( h = lines - 1; h >= 0; h--)
1185 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
1186 for( x = 0; x < dstwidth; x++ )
1188 val = *srcpixel++;
1189 *bits++ = X11DRV_DIB_GetNearestIndex( colors, 256,
1190 ((val << 3) & 0xf8) |
1191 ((val >> 2) & 0x7),
1192 ((val >> 3) & 0x00fc) |
1193 ((val >> 9) & 0x3),
1194 ((val >> 8) & 0x00f8) |
1195 ((val >> 13) & 0x7) );
1197 bits = (dstbits += linebytes);
1200 else goto notsupported;
1202 break;
1204 case 24:
1205 case 32:
1207 BYTE *srcpixel;
1209 /* ==== 24/32 BGR bitmap to 8 colormap dib ==== */
1210 if (bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff)
1212 for (h = lines - 1; h >= 0; h--)
1214 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
1215 for (x = 0; x < dstwidth; x++, srcpixel+=4)
1216 *bits++ = X11DRV_DIB_GetNearestIndex(colors, 256,
1217 srcpixel[2] , srcpixel[1], *srcpixel);
1218 bits = (dstbits += linebytes);
1221 /* ==== 24/32 RGB bitmap to 8 colormap dib ==== */
1222 else if (bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000)
1224 for (h = lines - 1; h >= 0; h--)
1226 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
1227 for (x = 0; x < dstwidth; x++, srcpixel+=4)
1228 *bits++ = X11DRV_DIB_GetNearestIndex(colors, 256,
1229 *srcpixel, srcpixel[1], srcpixel[2]);
1230 bits = (dstbits += linebytes);
1234 else goto notsupported;
1236 break;
1238 default: /* ? bit bmp -> 8 bit DIB */
1239 notsupported:
1240 FIXME("from %d bit bitmap with mask R,G,B %x,%x,%x to 8 bit DIB\n",
1241 bmpImage->depth, (int)bmpImage->red_mask,
1242 (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
1243 updatesection:
1244 for (h = lines - 1; h >= 0; h--) {
1245 for (x = 0; x < dstwidth; x++, bits++) {
1246 *bits = X11DRV_DIB_MapColor((int *)colors, 256,
1247 XGetPixel( bmpImage, x, h ), *bits);
1249 bits = (dstbits += linebytes);
1251 break;
1255 /***********************************************************************
1256 * X11DRV_DIB_SetImageBits_RLE8
1258 * SetDIBits for an 8-bit deep compressed DIB.
1260 * This function rewritten 941113 by James Youngman. WINE blew out when I
1261 * first ran it because my desktop wallpaper is a (large) RLE8 bitmap.
1263 * This was because the algorithm assumed that all RLE8 bitmaps end with the
1264 * 'End of bitmap' escape code. This code is very much laxer in what it
1265 * allows to end the expansion. Possibly too lax. See the note by
1266 * case RleDelta. BTW, MS's documentation implies that a correct RLE8
1267 * bitmap should end with RleEnd, but on the other hand, software exists
1268 * that produces ones that don't and Windows 3.1 doesn't complain a bit
1269 * about it.
1271 * (No) apologies for my English spelling. [Emacs users: c-indent-level=4].
1272 * James A. Youngman <mbcstjy@afs.man.ac.uk>
1273 * [JAY]
1276 enum Rle8_EscapeCodes
1279 * Apologies for polluting your file's namespace...
1281 RleEol = 0, /* End of line */
1282 RleEnd = 1, /* End of bitmap */
1283 RleDelta = 2 /* Delta */
1286 static void X11DRV_DIB_SetImageBits_RLE8( int lines, const BYTE *bits,
1287 DWORD width, DWORD dstwidth,
1288 int left, int *colors,
1289 XImage *bmpImage )
1291 int x; /* X-positon on each line. Increases. */
1292 int line; /* Line #. Starts at lines-1, decreases */
1293 const BYTE *pIn = bits; /* Pointer to current position in bits */
1294 BYTE length; /* The length pf a run */
1295 BYTE color_index; /* index into colors[] as read from bits */
1296 BYTE escape_code; /* See enum Rle8_EscapeCodes.*/
1297 int color; /* value of colour[color_index] */
1299 if (lines == 0) /* Let's hope this doesn't happen. */
1300 return;
1303 * Note that the bitmap data is stored by Windows starting at the
1304 * bottom line of the bitmap and going upwards. Within each line,
1305 * the data is stored left-to-right. That's the reason why line
1306 * goes from lines-1 to 0. [JAY]
1309 x = 0;
1310 line = lines-1;
1313 length = *pIn++;
1316 * If the length byte is not zero (which is the escape value),
1317 * We have a run of length pixels all the same colour. The colour
1318 * index is stored next.
1320 * If the length byte is zero, we need to read the next byte to
1321 * know what to do. [JAY]
1323 if (length != 0)
1326 * [Run-Length] Encoded mode
1328 color_index = (*pIn++); /* Get the colour index. */
1329 color = colors[color_index];
1331 while(length--)
1333 if (x>=dstwidth)
1335 x=0;
1336 line--;
1338 XPutPixel(bmpImage, x++, line, color);
1341 else
1344 * Escape codes (may be an absolute sequence though)
1346 escape_code = (*pIn++);
1347 switch(escape_code)
1349 case RleEol: /* =0, end of line */
1351 x = 0;
1352 line--;
1353 break;
1356 case RleEnd: /* =1, end of bitmap */
1359 * Not all RLE8 bitmaps end with this
1360 * code. For example, Paint Shop Pro
1361 * produces some that don't. That's (I think)
1362 * what caused the previous implementation to
1363 * fail. [JAY]
1365 line=-1; /* Cause exit from do loop. */
1366 break;
1369 case RleDelta: /* =2, a delta */
1372 * Note that deltaing to line 0
1373 * will cause an exit from the loop,
1374 * which may not be what is intended.
1375 * The fact that there is a delta in the bits
1376 * almost certainly implies that there is data
1377 * to follow. You may feel that we should
1378 * jump to the top of the loop to avoid exiting
1379 * in this case.
1381 * TODO: Decide what to do here in that case. [JAY]
1383 x += (*pIn++);
1384 line -= (*pIn++);
1385 if (line == 0)
1387 TRACE("Delta to last line of bitmap "
1388 "(wrongly?) causes loop exit\n");
1390 break;
1393 default: /* >2, switch to absolute mode */
1396 * Absolute Mode
1398 length = escape_code;
1399 while(length--)
1401 color_index = (*pIn++);
1402 if (x>=dstwidth)
1404 x=0;
1405 line--;
1407 XPutPixel(bmpImage, x++, line,
1408 colors[color_index]);
1412 * If you think for a moment you'll realise that the
1413 * only time we could ever possibly read an odd
1414 * number of bytes is when there is a 0x00 (escape),
1415 * a value >0x02 (absolute mode) and then an odd-
1416 * length run. Therefore this is the only place we
1417 * need to worry about it. Everywhere else the
1418 * bytes are always read in pairs. [JAY]
1420 if (escape_code & 1)
1421 pIn++; /* Throw away the pad byte. */
1422 break;
1424 } /* switch (escape_code) : Escape sequence */
1425 } /* process either an encoded sequence or an escape sequence */
1427 /* We expect to come here more than once per line. */
1428 } while (line >= 0); /* Do this until the bitmap is filled */
1431 * Everybody comes here at the end.
1432 * Check how we exited the loop and print a message if it's a bit odd.
1433 * [JAY]
1435 if ( (*(pIn-2) != 0/*escape*/) || (*(pIn-1)!= RleEnd) )
1437 TRACE("End-of-bitmap without (strictly) proper escape code. Last two "
1438 "bytes were: %02X %02X.\n", (int)*(pIn-2),(int)*(pIn-1));
1443 /***********************************************************************
1444 * X11DRV_DIB_SetImageBits_16
1446 * SetDIBits for a 16-bit deep DIB.
1448 static void X11DRV_DIB_SetImageBits_16( int lines, const BYTE *srcbits,
1449 DWORD srcwidth, DWORD dstwidth, int left,
1450 DC *dc, DWORD rSrc, DWORD gSrc, DWORD bSrc,
1451 XImage *bmpImage, DWORD linebytes )
1453 DWORD x;
1454 int h;
1456 if (lines < 0 )
1458 lines = -lines;
1459 srcbits = srcbits + ( linebytes * (lines-1));
1460 linebytes = -linebytes;
1463 switch ( bmpImage->depth )
1465 case 15:
1466 /* using same format as XImage */
1467 if (rSrc == bmpImage->red_mask && gSrc == bmpImage->green_mask && bSrc == bmpImage->blue_mask)
1468 for (h = lines - 1; h >= 0; h--, srcbits += linebytes)
1469 memcpy ( bmpImage->data + h * bmpImage->bytes_per_line + left*2, srcbits + left*2, dstwidth*2 );
1470 else /* We need to do a conversion from a 565 dib */
1472 LPDWORD dstpixel, ptr = (LPDWORD)(srcbits + left*2);
1473 DWORD val;
1474 int div = dstwidth % 2;
1476 for (h = lines - 1; h >= 0; h--) {
1477 dstpixel = (LPDWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1478 for (x = 0; x < dstwidth/2; x++) { /* Do 2 pixels at a time */
1479 val = *ptr++;
1480 *dstpixel++ = ((val >> 1) & 0x7fe07fe0) | (val & 0x001f001f); /* Red & Green & Blue */
1482 if (div != 0) /* Odd width? */
1483 *dstpixel = ((*(WORD *)ptr >> 1) & 0x7fe0) | (*(WORD *)ptr & 0x001f);
1484 ptr = (LPDWORD) ((srcbits += linebytes) + left*2);
1487 break;
1489 case 16:
1490 /* using same format as XImage */
1491 if (rSrc == bmpImage->red_mask && gSrc == bmpImage->green_mask && bSrc == bmpImage->blue_mask)
1492 for (h = lines - 1; h >= 0; h--, srcbits += linebytes)
1493 memcpy ( bmpImage->data + h * bmpImage->bytes_per_line + left*2, srcbits + left*2, dstwidth*2 );
1494 else /* We need to do a conversion from a 555 dib */
1496 LPDWORD dstpixel, ptr = (LPDWORD)(srcbits + left*2);
1497 DWORD val;
1498 int div = dstwidth % 2;
1500 for (h = lines - 1; h >= 0; h--) {
1501 dstpixel = (LPDWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1502 for (x = 0; x < dstwidth/2; x++) { /* Do 2 pixels at a time */
1503 val = *ptr++;
1504 *dstpixel++ = ((val << 1) & 0xffc0ffc0) | ((val >> 4) & 0x00200020) | /* Red & Green */
1505 (val & 0x001f001f); /* Blue */
1507 if (div != 0) /* Odd width? */
1508 *dstpixel = ((*(WORD *)ptr << 1) & 0xffc0) | ((*(WORD *)ptr >> 4) & 0x0020)
1509 | (*(WORD *)ptr & 0x001f);
1510 ptr = (LPDWORD) ((srcbits += linebytes) + left*2);
1513 break;
1515 case 24:
1516 case 32:
1518 DWORD *dstpixel;
1519 LPWORD ptr = (LPWORD)srcbits + left;
1520 DWORD val;
1522 if (bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff)
1524 if ((rSrc == 0xF800) && (gSrc == 0x07E0) && (bSrc == 0x001F)) {
1525 /* ==== 555 RGB dib to 24/32 RGB bitmap ==== */
1526 for (h = lines - 1; h >= 0; h--) {
1527 dstpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line + left*4);
1528 for (x = 0; x < dstwidth; x++) {
1529 val = *ptr++;
1530 *dstpixel++ = ((val << 8) & 0xF80000) | /* Red */
1531 ((val << 5) & 0x00FC00) | /* Green */
1532 ((val << 3) & 0x0000FF); /* Blue */
1534 ptr = (LPWORD)(srcbits += linebytes) + left;
1536 } else {
1537 /* ==== 555 BGR dib to 24/32 BGR bitmap ==== */
1538 for (h = lines - 1; h >= 0; h--) {
1539 dstpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line + left*4);
1540 for (x = 0; x < dstwidth; x++) {
1542 val = *ptr++;
1543 *dstpixel++ = ((val << 9) & 0xf80000) | ((val << 4) & 0x070000) | /* Red */
1544 ((val << 6) & 0x00f800) | ((val << 1) & 0x000700) | /* Green */
1545 ((val << 3) & 0x0000f8) | ((val >> 2) & 0x000007); /* Blue */
1547 ptr = (LPWORD)(srcbits += linebytes) + left;
1551 /* ==== 555 BGR dib to 24/32 RGB bitmap ==== */
1552 else if (bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000)
1554 for (h = lines - 1; h >= 0; h--) {
1555 dstpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line + left*4);
1556 for (x = 0; x < dstwidth; x++) {
1558 val = *ptr++;
1559 *dstpixel++ = ((val >> 7) & 0x0000f8) | ((val >> 12) & 0x000007) | /* Red */
1560 ((val << 6) & 0x00f800) | ((val << 1) & 0x000700) | /* Green */
1561 ((val << 19) & 0xf80000) | ((val >> 14) & 0x070000); /* Blue */
1563 ptr = (LPWORD)(srcbits += linebytes) + left;
1568 break;
1570 case 1:
1571 case 4:
1572 case 8:
1574 LPWORD ptr = (LPWORD)srcbits + left;
1575 WORD val;
1576 int sc1, sc2;
1578 /* Set color scaling values */
1579 if ( rSrc == 0x7c00 ) { sc1 = 7; sc2 = 2; } /* 555 dib */
1580 else { sc1 = 8; sc2 = 3; } /* 565 dib */
1582 for (h = lines - 1; h >= 0; h--) {
1583 for (x = left; x < dstwidth+left; x++) {
1584 val = *ptr++;
1585 XPutPixel( bmpImage, x, h,
1586 X11DRV_PALETTE_ToPhysical(dc, RGB(((val & rSrc) >> sc1), /* Red */
1587 ((val & gSrc) >> sc2), /* Green */
1588 ((val & bSrc) << 3)))); /* Blue */
1590 ptr = (LPWORD) (srcbits += linebytes) + left;
1593 break;
1595 default:
1596 FIXME("16 bit DIB %d bit bitmap\n", bmpImage->bits_per_pixel);
1597 break;
1603 /***********************************************************************
1604 * X11DRV_DIB_GetImageBits_16
1606 * GetDIBits for an 16-bit deep DIB.
1608 static void X11DRV_DIB_GetImageBits_16( int lines, BYTE *dstbits,
1609 DWORD dstwidth, DWORD srcwidth,
1610 PALETTEENTRY *srccolors,
1611 DWORD rDst, DWORD gDst, DWORD bDst,
1612 XImage *bmpImage, DWORD dibpitch )
1614 DWORD x;
1615 int h, rsc, gsc;
1617 DWORD linebytes = dibpitch;
1619 if (lines < 0 )
1621 lines = -lines;
1622 dstbits = dstbits + ( linebytes * (lines-1));
1623 linebytes = -linebytes;
1626 /* Set color scaling values */
1627 if ( rDst == 0x7c00 ) { rsc = 7; gsc = 2; } /* 555 dib */
1628 else { rsc = 8; gsc = 3; } /* 565 dib */
1630 switch ( bmpImage->depth )
1632 case 15:
1633 /* using same format as XImage */
1634 if (rDst == bmpImage->red_mask && bDst == bmpImage->blue_mask)
1635 for (h = lines - 1; h >= 0; h--, dstbits += linebytes)
1636 memcpy( dstbits, bmpImage->data + h*bmpImage->bytes_per_line, srcwidth*2 );
1637 /* reversed format (BGR <=> RGB) */
1638 else if (rDst == bmpImage->blue_mask && bDst == bmpImage->red_mask)
1640 LPDWORD srcpixel, ptr = (LPDWORD)dstbits;
1641 DWORD val;
1642 int div = srcwidth % 2;
1644 for (h = lines - 1; h >= 0; h--) {
1645 srcpixel = (LPDWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
1646 for (x = 0; x < srcwidth/2; x++) { /* Do 2 pixels at a time */
1647 val = *srcpixel++;
1648 *ptr++ = ((val << 10) & 0xf800f800) | (val & 0x03e003e0) | /* Red & Green */
1649 ((val >> 10) & 0x001f001f); /* Blue */
1651 if (div != 0) /* Odd width? */
1652 *ptr = ((*(WORD *)srcpixel << 1) & 0xffc0) | ((*(WORD *)srcpixel >> 4) & 0x0020) |
1653 (*(WORD *)srcpixel & 0x001f);
1654 ptr = (LPDWORD)(dstbits += linebytes);
1657 else goto notsupported;
1659 break;
1661 case 16:
1663 LPDWORD srcpixel, ptr = (LPDWORD)dstbits;
1664 DWORD val;
1665 int div = srcwidth % 2;
1667 /* using same format as XImage */
1668 if (rDst == bmpImage->red_mask && bDst == bmpImage->blue_mask)
1669 for (h = lines - 1; h >= 0; h--, dstbits += linebytes)
1670 memcpy( dstbits, bmpImage->data + h*bmpImage->bytes_per_line, srcwidth*2 );
1671 /* ==== 565 BGR bitmap to 555 BGR dib ==== */
1672 else if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f &&
1673 rDst == 0x7c00 && bDst == 0x001f)
1675 for (h = lines - 1; h >= 0; h--) {
1676 srcpixel = (LPDWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
1677 for (x = 0; x < srcwidth/2; x++) { /* Do 2 pixels at a time */
1678 val = *srcpixel++;
1679 *ptr++ = ((val >> 1) & 0x7fe07fe0) | /* Red & Green */
1680 (val & 0x001f001f); /* Blue */
1682 if (div != 0) /* Odd width? */
1683 *ptr = ((*(WORD *)srcpixel >> 1) & 0x7fe0) | (*(WORD *)srcpixel & 0x001f);
1684 ptr = (LPDWORD) (dstbits += linebytes);
1687 /* ==== 565 RGB bitmap to 555 BGR dib ==== */
1688 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0xf800 &&
1689 rDst == 0x7c00 && bDst == 0x001f)
1691 for (h = lines - 1; h >= 0; h--) {
1692 srcpixel = (LPDWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
1693 for (x = 0; x < srcwidth/2; x++) { /* Do 2 pixels at a time */
1694 val = *srcpixel++;
1695 *ptr++ = ((val << 10) & 0x7c007c00) | ((val >> 1) & 0x03e003e0) | /* Red & Green */
1696 ((val >> 11) & 0x001f001f); /* Blue */
1698 if (div != 0) /* Odd width? */
1699 *ptr = ((*(WORD *)srcpixel >> 1) & 0x7fe0) | (*(WORD *)srcpixel & 0x001f);
1700 ptr = (LPDWORD) (dstbits += linebytes);
1703 else goto notsupported;
1705 break;
1707 case 24:
1708 case 32:
1710 DWORD *srcpixel;
1711 LPWORD ptr = (LPWORD)dstbits;
1712 DWORD val;
1714 /* ==== 24/32 BGR bitmap ==== */
1715 if (bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff)
1717 int rsc2 = 16-rsc, gsc2 = 8-gsc;
1718 for (h = lines - 1; h >= 0; h--) {
1719 srcpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line);
1720 for (x = 0; x < srcwidth; x++, ptr++) {
1721 val = *srcpixel++;
1722 *ptr = ((val >> rsc2) & rDst) |
1723 ((val >> gsc2) & gDst) |
1724 ((val >> 3) & bDst);
1726 ptr = (LPWORD)(dstbits += linebytes);
1729 /* ==== 24/32 RGB bitmap ==== */
1730 else if (bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000)
1732 int gsc2 = 8-gsc;
1733 for (h = lines - 1; h >= 0; h--) {
1734 srcpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line);
1735 for (x = 0; x < srcwidth; x++, ptr++) {
1736 val = *srcpixel++;
1737 *ptr = ((val << rsc) & rDst) |
1738 ((val >> gsc2) & gDst) |
1739 ((val >> 19) & bDst);
1741 ptr = (LPWORD) (dstbits += linebytes);
1744 else goto notsupported;
1746 break;
1748 case 1:
1749 /* ==== monochrome bitmap ==== */
1750 case 4:
1751 /* ==== 4 colormap bitmap ==== */
1752 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
1754 LPWORD ptr = (LPWORD)dstbits;
1755 PALETTEENTRY val;
1757 for (h = lines - 1; h >= 0; h--) {
1758 for (x = 0; x < dstwidth; x++) {
1759 val = srccolors[XGetPixel(bmpImage, x, h)];
1760 *ptr++ = ((val.peRed << rsc) & rDst) |
1761 ((val.peGreen << gsc) & gDst) |
1762 ((val.peBlue >> 3) & bDst);
1764 ptr = (LPWORD)(dstbits += linebytes);
1767 else goto notsupported;
1769 break;
1771 case 8:
1772 /* ==== 8 colormap bitmap ==== */
1773 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
1775 LPWORD ptr = (LPWORD)dstbits;
1776 BYTE *srcpixel;
1777 PALETTEENTRY val;
1779 for (h = lines - 1; h >= 0; h--) {
1780 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
1781 for (x = 0; x < dstwidth; x++) {
1782 val = srccolors[(int)*srcpixel++];
1783 *ptr++ = ((val.peRed << rsc) & rDst) |
1784 ((val.peGreen << gsc) & gDst) |
1785 ((val.peBlue >> 3) & bDst);
1787 ptr = (LPWORD)(dstbits += linebytes);
1790 else goto notsupported;
1792 break;
1794 default:
1795 notsupported:
1797 BYTE r,g, b;
1798 LPWORD ptr = (LPWORD)dstbits;
1800 FIXME("from %d bit bitmap with mask R,G,B %lx,%lx,%lx to 16 bit DIB %lx,%lx,%lx\n",
1801 bmpImage->depth, bmpImage->red_mask,
1802 bmpImage->green_mask, bmpImage->blue_mask,
1803 rDst, gDst, bDst);
1805 for (h = lines - 1; h >= 0; h--)
1807 for (x = 0; x < dstwidth; x++, ptr++)
1809 COLORREF pixel = X11DRV_PALETTE_ToLogical( XGetPixel( bmpImage, x, h ) );
1810 r = (BYTE) GetRValue(pixel);
1811 g = (BYTE) GetGValue(pixel);
1812 b = (BYTE) GetBValue(pixel);
1813 *ptr = ( ((r << rsc) & rDst) | ((g << gsc) & gDst) | ((b >> 3) & bDst) );
1815 ptr = (LPWORD) (dstbits += linebytes);
1818 break;
1823 /***********************************************************************
1824 * X11DRV_DIB_SetImageBits_24
1826 * SetDIBits for a 24-bit deep DIB.
1828 static void X11DRV_DIB_SetImageBits_24( int lines, const BYTE *srcbits,
1829 DWORD srcwidth, DWORD dstwidth, int left,
1830 DC *dc, XImage *bmpImage, DWORD linebytes )
1832 DWORD x;
1833 int h;
1835 if (lines < 0 )
1837 lines = -lines;
1838 srcbits = srcbits + linebytes * (lines - 1);
1839 linebytes = -linebytes;
1842 switch ( bmpImage->depth )
1844 case 24:
1846 if (bmpImage->bits_per_pixel == 24) {
1847 int dstlinebytes = linebytes;
1848 BYTE *dstpixel;
1849 BYTE *ptr = (BYTE *)(srcbits+left*3);
1851 if (dstlinebytes < 0 ) dstlinebytes = -dstlinebytes;
1852 dstpixel = bmpImage->data + lines*dstlinebytes + left*3;
1853 for(h = lines ; h-- ; ) {
1854 dstpixel-=dstlinebytes;
1855 memcpy(dstpixel,ptr,dstwidth*3);
1856 ptr +=linebytes;
1858 break;
1861 case 32:
1863 if( bmpImage->blue_mask == 0xff && bmpImage->red_mask == 0xff0000 ) /* packed BGR to unpacked BGR */
1865 DWORD *dstpixel, val, buf;
1866 DWORD *ptr = (DWORD *)(srcbits + left*3);
1867 BYTE *bits;
1868 int div = dstwidth % 4;
1869 int divk;
1871 for(h = lines - 1; h >= 0; h--)
1873 dstpixel = (DWORD *) (bmpImage->data + h*bmpImage->bytes_per_line + left*4);
1875 for (x = 0; x < dstwidth/4; x++) { /* do 3 dwords source, 4 dwords dest at a time */
1876 buf = *ptr++;
1877 *dstpixel++ = buf&0x00ffffff; /* b1, g1, r1 */
1878 val = (buf >> 24); /* b2 */
1879 buf = *ptr++;
1880 *dstpixel++ = (val | (buf<<8)) &0x00ffffff; /* g2, r2 */
1881 val = (buf >> 16); /* b3, g3 */
1882 buf = *ptr++;
1883 *dstpixel++ = (val | (buf<<16)) &0x00ffffff; /* r3 */
1884 *dstpixel++ = (buf >> 8); /* b4, g4, r4 */
1886 for ( divk=div, bits=(BYTE*)ptr; divk>0; divk--, bits+=3 ) /* do remainder */
1888 *dstpixel++ = *(DWORD*)bits & 0x00ffffff; /* b, g, r */
1890 ptr = (DWORD*)((srcbits+=linebytes)+left*3);
1893 else if( bmpImage->blue_mask == 0xff0000 && bmpImage->red_mask == 0xff ) /* packed BGR to unpacked RGB */
1895 DWORD *dstpixel, val, buf;
1896 DWORD *ptr = (DWORD *)(srcbits + left*3);
1897 BYTE *bits;
1898 int div = dstwidth % 4;
1899 int divk;
1901 for(h = lines - 1; h >= 0; h--)
1903 dstpixel = (DWORD *) (bmpImage->data + h*bmpImage->bytes_per_line + left*4);
1905 for (x = 0; x < dstwidth/4; x++) { /* do 3 dwords source, 4 dwords dest at a time */
1906 buf = *ptr++;
1907 *dstpixel++ = ((buf&0xff)<<16) | (buf&0xff00) | ((buf&0xff0000)>>16); /* b1, g1, r1 */
1908 val = ((buf&0xff000000)>>8); /* b2 */
1909 buf = *ptr++;
1910 *dstpixel++ = val | ((buf&0xff)<<8) | ((buf&0xff00)>>8); /* g2, r2 */
1911 val = (buf&0xff0000) | ((buf&0xff000000)>>16); /* b3, g3 */
1912 buf = *ptr++;
1913 *dstpixel++ = val | (buf&0xff); /* r3 */
1914 *dstpixel++ = ((buf&0xff00)<<8) | ((buf&0xff0000)>>8) | (buf>>24); /* b4, g4, r4 */
1916 for ( divk=div, bits=(BYTE*)ptr; divk>0; divk--, bits+=3 ) /* do remainder */
1918 buf = *(DWORD*)bits;
1919 *dstpixel++ = ((buf&0xff)<<16) | (buf&0xff00) | ((buf&0xff0000)>>16); /* b, g, r */
1921 ptr = (DWORD*)((srcbits+=linebytes)+left*3);
1924 else
1925 goto notsupported;
1927 break;
1929 case 15:
1931 if( bmpImage->blue_mask == 0x7c00 && bmpImage->red_mask == 0x1f ) /* BGR888 to RGB555 */
1933 DWORD *ptr = (DWORD *)(srcbits + left*3);
1934 LPBYTE bits;
1935 LPWORD dstpixel;
1936 int div = dstwidth % 4;
1937 int divk;
1939 for (h = lines - 1; h >= 0; h--) { /* Do 4 pixels at a time */
1940 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1941 for (x = 0; x < dstwidth/4; x++, ptr += 3) {
1942 *dstpixel++ = ((ptr[0] << 7) & 0x7c00) | ((ptr[0] >> 6) & 0x03e0) | ((ptr[0] >> 19) & 0x1f);
1943 *dstpixel++ = ((ptr[0] >> 17) & 0x7c00) | ((ptr[1] << 2) & 0x03e0) | ((ptr[1] >> 11) & 0x1f);
1944 *dstpixel++ = ((ptr[1] >> 9) & 0x07c00) | ((ptr[1] >> 22) & 0x03e0) | ((ptr[2] >> 3) & 0x1f);
1945 *dstpixel++ = ((ptr[2] >> 1) & 0x07c00) | ((ptr[2] >> 14) & 0x03e0) | ((ptr[2] >> 27) & 0x1f);
1947 for (bits = (LPBYTE)ptr, divk=div; divk > 0; divk--, bits+=3) /* dstwidth not divisible by 4? */
1948 *dstpixel++ = (((WORD)bits[0] << 7) & 0x07c00) |
1949 (((WORD)bits[1] << 2) & 0x03e0) |
1950 (((WORD)bits[2] >> 3) & 0x001f);
1951 ptr = (DWORD *)((srcbits += linebytes) + left * 3);
1954 else if( bmpImage->blue_mask == 0x1f && bmpImage->red_mask == 0x7c00 ) /* BGR888 to BGR555 */
1956 DWORD *ptr = (DWORD *)(srcbits + left*3);
1957 LPBYTE bits;
1958 LPWORD dstpixel;
1959 int div = dstwidth % 4;
1960 int divk;
1962 for (h = lines - 1; h >= 0; h--) { /* Do 4 pixels at a time */
1963 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1964 for (x = 0; x < dstwidth/4; x++, ptr += 3) {
1965 *dstpixel++ = ((ptr[0] >> 3) & 0x1f) | ((ptr[0] >> 6) & 0x03e0) | ((ptr[0] >> 9) & 0x7c00);
1966 *dstpixel++ = ((ptr[0] >> 27) & 0x1f) | ((ptr[1] << 2) & 0x03e0) | ((ptr[1] >> 1) & 0x7c00);
1967 *dstpixel++ = ((ptr[1] >> 19) & 0x1f) | ((ptr[1] >> 22) & 0x03e0) | ((ptr[2] << 7) & 0x7c00);
1968 *dstpixel++ = ((ptr[2] >> 11) & 0x1f) | ((ptr[2] >> 14) & 0x03e0) | ((ptr[2] >> 17) & 0x7c00);
1970 for (bits = (LPBYTE)ptr, divk=div; divk > 0; divk--, bits+=3) /* dstwidth not divisible by 4? */
1971 *dstpixel++ = (((WORD)bits[2] << 7) & 0x07c00) |
1972 (((WORD)bits[1] << 2) & 0x03e0) |
1973 (((WORD)bits[0] >> 3) & 0x001f);
1974 ptr = (DWORD *)((srcbits += linebytes) + left * 3);
1977 else
1978 goto notsupported;
1980 break;
1982 case 16:
1984 DWORD *ptr = (DWORD *)(srcbits + left*3);
1985 LPBYTE bits;
1986 LPWORD dstpixel;
1987 int div = dstwidth % 4;
1988 int divk;
1990 if( bmpImage->blue_mask == 0x001f && bmpImage->red_mask == 0xf800 ) /* BGR888 to BGR565 */
1992 for (h = lines - 1; h >= 0; h--) { /* Do 4 pixels at a time */
1993 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1994 for (x = 0; x < dstwidth/4; x++, ptr += 3) {
1995 *dstpixel++ = ((ptr[0] >> 3) & 0x1f) | ((ptr[0] >> 5) & 0x07e0) | ((ptr[0] >> 8) & 0xf800);
1996 *dstpixel++ = ((ptr[0] >> 27) & 0x1f) | ((ptr[1] << 3) & 0x07e0) | (ptr[1] & 0xf800);
1997 *dstpixel++ = ((ptr[1] >> 19) & 0x1f) | ((ptr[1] >> 21) & 0x07e0) | ((ptr[2] << 8) & 0xf800);
1998 *dstpixel++ = ((ptr[2] >> 11) & 0x1f) | ((ptr[2] >> 13) & 0x07e0) | ((ptr[2] >> 16) & 0xf800);
2000 for ( bits = (LPBYTE)ptr, divk=div; divk > 0; divk--, bits+=3) /* dstwidth is not divisible by 4? */
2001 *dstpixel++ = (((WORD)bits[2] << 8) & 0xf800) |
2002 (((WORD)bits[1] << 3) & 0x07e0) |
2003 (((WORD)bits[0] >> 3) & 0x001f);
2004 ptr = (DWORD *)((srcbits += linebytes) + left * 3);
2007 else if( bmpImage->blue_mask == 0xf800 && bmpImage->red_mask == 0x001f ) /* BGR888 to RGB565 */
2009 for (h = lines - 1; h >= 0; h--) { /* Do 4 pixels at a time */
2010 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
2011 for (x = 0; x < dstwidth/4; x++, ptr += 3) {
2012 *dstpixel++ = ((ptr[0] << 8) & 0xf800) | ((ptr[0] >> 5) & 0x07e0) | ((ptr[0] >> 19) & 0x1f);
2013 *dstpixel++ = ((ptr[0] >> 16) & 0xf800) | ((ptr[1] << 3) & 0x07e0) | ((ptr[1] >> 11) & 0x1f);
2014 *dstpixel++ = ((ptr[1] >> 8) & 0xf800) | ((ptr[1] >> 21) & 0x07e0) | ((ptr[2] >> 3) & 0x1f);
2015 *dstpixel++ = (ptr[2] & 0xf800) | ((ptr[2] >> 13) & 0x07e0) | ((ptr[2] >> 27) & 0x1f);
2017 for ( bits = (LPBYTE)ptr, divk=div; divk > 0; divk--, bits+=3) /* dstwidth is not divisible by 4? */
2018 *dstpixel++ = (((WORD)bits[0] << 8) & 0xf800) |
2019 (((WORD)bits[1] << 3) & 0x07e0) |
2020 (((WORD)bits[2] >> 3) & 0x001f);
2021 ptr = (DWORD *)((srcbits += linebytes) + left * 3);
2024 else
2025 goto notsupported;
2027 break;
2029 case 1:
2030 case 4:
2031 case 8:
2033 LPBYTE bits = (LPBYTE)srcbits + left*3;
2035 for (h = lines - 1; h >= 0; h--) {
2036 for (x = left; x < dstwidth+left; x++, bits+=3)
2037 XPutPixel( bmpImage, x, h,
2038 X11DRV_PALETTE_ToPhysical(dc, RGB(bits[2], bits[1], bits[0])));
2039 bits = (LPBYTE)(srcbits += linebytes) + left * 3;
2042 break;
2044 default:
2045 notsupported:
2046 FIXME("from 24 bit DIB to %d bit bitmap with mask R,G,B %x,%x,%x\n",
2047 bmpImage->bits_per_pixel, (int)bmpImage->red_mask,
2048 (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
2049 break;
2054 /***********************************************************************
2055 * X11DRV_DIB_GetImageBits_24
2057 * GetDIBits for an 24-bit deep DIB.
2059 static void X11DRV_DIB_GetImageBits_24( int lines, BYTE *dstbits,
2060 DWORD dstwidth, DWORD srcwidth,
2061 PALETTEENTRY *srccolors,
2062 XImage *bmpImage, DWORD linebytes )
2064 DWORD x, val;
2065 int h;
2067 if (lines < 0 )
2069 lines = -lines;
2070 dstbits = dstbits + ( linebytes * (lines-1) );
2071 linebytes = -linebytes;
2074 switch ( bmpImage->depth )
2076 case 24:
2078 if (bmpImage->bits_per_pixel == 24) {
2079 int tocopy = linebytes;
2080 BYTE *srcpixel;
2081 BYTE *ptr = (LPBYTE)dstbits;
2083 if (tocopy < 0 ) tocopy = -tocopy;
2084 srcpixel = bmpImage->data + lines*tocopy;
2085 for(h = lines ; h-- ; ) {
2086 srcpixel-=tocopy;
2087 memcpy(ptr,srcpixel,tocopy);
2088 ptr = (LPBYTE)(dstbits+=linebytes);
2090 break;
2093 case 32:
2095 DWORD *srcpixel, buf;
2096 LPBYTE bits;
2097 DWORD *ptr=(DWORD *)dstbits;
2098 int quotient = dstwidth / 4;
2099 int remainder = dstwidth % 4;
2100 int remk;
2102 /* ==== 24/32 BGR bitmap to 24 BGR dib==== */
2103 if( bmpImage->blue_mask == 0xff && bmpImage->red_mask == 0xff0000 )
2105 for(h = lines - 1; h >= 0; h--)
2107 srcpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line);
2109 for (x = 0; x < quotient; x++) { /* do 4 dwords source, 3 dwords dest at a time */
2110 buf = ((*srcpixel++)&0x00ffffff); /* b1, g1, r1*/
2111 *ptr++ = buf | ((*srcpixel)<<24); /* b2 */
2112 buf = ((*srcpixel++>>8)&0x0000ffff); /* g2, r2 */
2113 *ptr++ = buf | ((*srcpixel)<<16); /* b3, g3 */
2114 buf = ((*srcpixel++>>16)&0x000000ff); /* r3 */
2115 *ptr++ = buf | ((*srcpixel++)<<8); /* b4, g4, r4 */
2117 for ( remk=remainder, bits=(BYTE*)ptr; remk>0; remk--, bits+=3 ) /* do remainder */
2119 buf=*srcpixel++;
2120 *(WORD*)bits = buf; /* b, g */
2121 *(bits+2) = buf>>16; /* r */
2123 ptr = (DWORD*)(dstbits+=linebytes);
2127 /* ==== 24/32 RGB bitmap to 24 BGR dib ==== */
2128 else if( bmpImage->blue_mask == 0xff0000 && bmpImage->red_mask == 0xff )
2130 for(h = lines - 1; h >= 0; h--)
2132 srcpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line);
2134 for (x = 0; x < quotient; x++) { /* do 4 dwords source, 3 dwords dest at a time */
2135 buf = *srcpixel++;
2136 val = ((buf&0xff0000)>>16) | (buf&0xff00) | ((buf&0xff)<<16); /* b1, g1, r1 */
2137 buf = *srcpixel++;
2138 *ptr++ = val | ((buf&0xff0000)<<8); /* b2 */
2139 val = ((buf&0xff00)>>8) | ((buf&0xff)<<8); /* g2, r2 */
2140 buf = *srcpixel++;
2141 *ptr++ = val | (buf&0xff0000) | ((buf&0xff00)<<16); /* b3, g3 */
2142 val = (buf&0xff); /* r3 */
2143 buf = *srcpixel++;
2144 *ptr++ = val | ((buf&0xff0000)>>8) | ((buf&0xff00)<<8) | (buf<<24); /* b4, g4, r4 */
2146 for ( remk=remainder, bits=(BYTE*)ptr; remk>0; remk--, bits+=3 ) /* do remainder */
2148 buf=*srcpixel++;
2149 *(WORD*)bits = (buf&0xff00) | ((buf&0xff0000)>>16) ; /* b, g */
2150 *(bits+2) = buf; /* r */
2152 ptr = (DWORD*)(dstbits+=linebytes);
2155 else goto notsupported;
2157 break;
2159 case 15:
2161 LPWORD srcpixel;
2162 LPBYTE bits = dstbits;
2163 WORD val;
2165 /* ==== 555 BGR bitmap to 24 BGR dib ==== */
2166 if( bmpImage->blue_mask == 0x1f && bmpImage->red_mask == 0x7c00 )
2168 for (h = lines - 1; h >= 0; h--) {
2169 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2170 for (x = 0; x < srcwidth; x++, bits += 3) {
2171 val = *srcpixel++;
2172 bits[2] = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07)); /*Red*/
2173 bits[1] = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07)); /*Green*/
2174 bits[0] = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07)); /*Blue*/
2176 bits = (dstbits += linebytes);
2179 /* ==== 555 RGB bitmap to 24 RGB dib==== */
2180 else if( bmpImage->blue_mask == 0x7c00 && bmpImage->red_mask == 0x1f )
2182 for (h = lines - 1; h >= 0; h--) {
2183 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2184 for (x = 0; x < srcwidth; x++, bits += 3) {
2185 val = *srcpixel++;
2186 bits[0] = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07)); /*Red*/
2187 bits[1] = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07)); /*Green*/
2188 bits[2] = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07)); /*Blue*/
2190 bits = (dstbits += linebytes);
2193 else goto notsupported;
2195 break;
2197 case 16:
2199 LPWORD srcpixel;
2200 LPBYTE bits = dstbits;
2201 WORD val;
2203 /* ==== 565 BGR bitmap to 24 BGR dib ==== */
2204 if( bmpImage->blue_mask == 0x1f && bmpImage->red_mask == 0xf800 )
2206 for (h = lines - 1; h >= 0; h--) {
2207 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2208 for (x = 0; x < srcwidth; x++, bits += 3) {
2209 val = *srcpixel++;
2210 bits[2] = (BYTE)(((val >> 8) & 0xf8) | ((val >> 13) & 0x07)); /*Red*/
2211 bits[1] = (BYTE)(((val >> 3) & 0xfc) | ((val >> 9) & 0x03)); /*Green*/
2212 bits[0] = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07)); /*Blue*/
2214 bits = (dstbits += linebytes);
2217 /* ==== 565 RGB bitmap to 24 BGR dib ==== */
2218 else if( bmpImage->blue_mask == 0xf800 && bmpImage->red_mask == 0x1f )
2220 for (h = lines - 1; h >= 0; h--) {
2221 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2222 for (x = 0; x < srcwidth; x++, bits += 3) {
2223 val = *srcpixel++;
2224 bits[0] = (BYTE)(((val >> 8) & 0xf8) | ((val >> 13) & 0x07)); /*Red*/
2225 bits[1] = (BYTE)(((val >> 3) & 0xfc) | ((val >> 9) & 0x03)); /*Green*/
2226 bits[2] = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07)); /*Blue*/
2228 bits = (dstbits += linebytes);
2231 else goto notsupported;
2233 break;
2235 case 1:
2236 /* ==== monochrome bitmap to 24 BGR dib ==== */
2237 case 4:
2238 /* ==== 4 colormap bitmap to 24 BGR dib ==== */
2239 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
2241 LPBYTE bits = dstbits;
2242 PALETTEENTRY val;
2244 for (h = lines - 1; h >= 0; h--) {
2245 for (x = 0; x < dstwidth; x++) {
2246 val = srccolors[XGetPixel(bmpImage, x, h)];
2247 *bits++ = val.peBlue;
2248 *bits++ = val.peGreen;
2249 *bits++ = val.peRed;
2251 bits = (dstbits += linebytes);
2254 else goto notsupported;
2256 break;
2258 case 8:
2259 /* ==== 8 colormap bitmap to 24 BGR dib ==== */
2260 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask == 0 && srccolors)
2262 BYTE *srcpixel;
2263 LPBYTE bits = dstbits;
2264 PALETTEENTRY val;
2266 for (h = lines - 1; h >= 0; h--) {
2267 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
2268 for (x = 0; x < dstwidth; x++ ) {
2269 val = srccolors[(int)*srcpixel++];
2270 *bits++ = val.peBlue; /*Blue*/
2271 *bits++ = val.peGreen; /*Green*/
2272 *bits++ = val.peRed; /*Red*/
2274 bits = (dstbits += linebytes);
2277 else goto notsupported;
2279 break;
2281 default:
2282 notsupported:
2284 LPBYTE bits = dstbits;
2286 FIXME("from %d bit bitmap with mask R,G,B %x,%x,%x to 24 bit DIB\n",
2287 bmpImage->depth, (int)bmpImage->red_mask,
2288 (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
2289 for (h = lines - 1; h >= 0; h--)
2291 for (x = 0; x < dstwidth; x++, bits += 3)
2293 COLORREF pixel = X11DRV_PALETTE_ToLogical( XGetPixel( bmpImage, x, h ) );
2294 bits[0] = GetBValue(pixel);
2295 bits[1] = GetGValue(pixel);
2296 bits[2] = GetRValue(pixel);
2298 bits = (dstbits += linebytes);
2301 break;
2306 /***********************************************************************
2307 * X11DRV_DIB_SetImageBits_32
2309 * SetDIBits for a 32-bit deep DIB.
2311 static void X11DRV_DIB_SetImageBits_32( int lines, const BYTE *srcbits,
2312 DWORD srcwidth, DWORD dstwidth, int left,
2313 DC *dc, XImage *bmpImage,
2314 DWORD linebytes )
2316 DWORD x, *ptr;
2317 int h;
2319 if (lines < 0 )
2321 lines = -lines;
2322 srcbits = srcbits + ( linebytes * (lines-1) );
2323 linebytes = -linebytes;
2326 ptr = (DWORD *) srcbits + left;
2328 switch ( bmpImage->depth )
2330 case 32:
2331 /* ==== 32 BGR dib to 24/32 BGR bitmap ==== */
2332 if (bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff) {
2333 for (h = lines - 1; h >= 0; h--, srcbits+=linebytes) {
2334 memcpy( bmpImage->data + h * bmpImage->bytes_per_line, srcbits + left*4, dstwidth*4 );
2338 /* ==== 32 BGR dib to 24/32 RGB bitmap ==== */
2339 else if (bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000)
2341 DWORD *dstpixel;
2343 for (h = lines - 1; h >= 0; h--) {
2344 dstpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line);
2345 for (x = 0; x < dstwidth; x++, ptr++) {
2346 *dstpixel++ = ((*ptr << 16) & 0xff0000) | (*ptr & 0xff00) | ((*ptr >> 16) & 0xff);
2348 ptr = (DWORD *) (srcbits += linebytes) + left;
2351 else goto notsupported;
2353 break;
2355 case 24:
2356 /* ==== 32 BGR dib to 24 (888) BGR bitmap ==== */
2357 /* we need to check that source mask matches destination */
2358 if (bmpImage->bits_per_pixel == 32)
2360 for (h = lines - 1; h >= 0; h--, srcbits+=linebytes) {
2361 memcpy( bmpImage->data + h * bmpImage->bytes_per_line, srcbits + left*4, dstwidth*4 );
2364 else
2366 BYTE *bptr;
2368 ptr = (DWORD *) srcbits + left;
2369 bptr = bmpImage->data;
2371 for (h = lines - 1; h >= 0; h--) {
2372 for (x = 0; x < dstwidth; x++) {
2373 /* *ptr is a 32bit value */
2374 /* bptr points to first of 3 bytes */
2375 *bptr++ = (*ptr >> 16) & 0xff;
2376 *bptr++ = (*ptr >> 8) & 0xff;
2377 *bptr++ = (*ptr ) & 0xff;
2378 ptr++;
2380 ptr = (DWORD *) (srcbits += linebytes) + left;
2383 break;
2385 case 15:
2386 /* ==== 32 BGR dib to 555 BGR bitmap ==== */
2387 if (bmpImage->red_mask == 0x7c00 && bmpImage->blue_mask == 0x001f) {
2388 LPWORD dstpixel;
2390 for (h = lines - 1; h >= 0; h--) {
2391 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2392 for (x = 0; x < dstwidth; x++, ptr++) {
2393 *dstpixel++ = (WORD) (((*ptr >> 9) & 0x7c00) | ((*ptr >> 6) & 0x03e0) | ((*ptr >> 3) & 0x001f));
2395 ptr = (DWORD *) (srcbits += linebytes) + left;
2398 /* ==== 32 BGR dib to 555 RGB bitmap ==== */
2399 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0x7c00)
2401 LPWORD dstpixel;
2403 for (h = lines - 1; h >= 0; h--) {
2404 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2405 for (x = 0; x < dstwidth; x++, ptr++) {
2406 *dstpixel++ = (WORD) (((*ptr << 7) & 0x7c00) | ((*ptr >> 6) & 0x03e0) | ((*ptr >> 19) & 0x001f));
2408 ptr = (DWORD *) (srcbits += linebytes) + left;
2411 else goto notsupported;
2413 break;
2415 case 16:
2416 /* ==== 32 BGR dib to 565 BGR bitmap ==== */
2417 if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f)
2419 LPWORD dstpixel;
2421 for (h = lines - 1; h >= 0; h--) {
2422 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2423 for (x = 0; x < dstwidth; x++, ptr++) {
2424 *dstpixel++ = (WORD) (((*ptr >> 8) & 0xf800) | ((*ptr >> 5) & 0x07e0) | ((*ptr >> 3) & 0x001f));
2426 ptr = (DWORD *) (srcbits += linebytes) + left;
2429 /* ==== 32 BGR dib to 565 RGB bitmap ==== */
2430 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0xf800)
2432 LPWORD dstpixel;
2434 for (h = lines - 1; h >= 0; h--) {
2435 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2436 for (x = 0; x < dstwidth; x++, ptr++) {
2437 *dstpixel++ = (WORD) (((*ptr << 8) & 0xf800) | ((*ptr >> 5) & 0x07e0) | ((*ptr >> 19) & 0x001f));
2439 ptr = (DWORD *) (srcbits += linebytes) + left;
2442 else goto notsupported;
2444 break;
2446 case 1:
2447 case 4:
2448 case 8:
2450 LPBYTE bits = (LPBYTE)srcbits + left*4;
2452 for (h = lines - 1; h >= 0; h--) {
2453 for (x = left; x < dstwidth+left; x++, bits += 4)
2454 XPutPixel( bmpImage, x, h,
2455 X11DRV_PALETTE_ToPhysical(dc, RGB( bits[2], bits[1], *bits )));
2456 bits = (LPBYTE)(srcbits += linebytes) + left * 4;
2459 break;
2461 default:
2462 notsupported:
2463 FIXME("32 bit DIB %d bit bitmap\n", bmpImage->bits_per_pixel);
2464 break;
2469 /***********************************************************************
2470 * X11DRV_DIB_GetImageBits_32
2472 * GetDIBits for an 32-bit deep DIB.
2474 static void X11DRV_DIB_GetImageBits_32( int lines, BYTE *dstbits,
2475 DWORD dstwidth, DWORD srcwidth,
2476 PALETTEENTRY *srccolors,
2477 XImage *bmpImage, DWORD linebytes )
2479 DWORD x;
2480 int h;
2481 BYTE *bits;
2483 DWORD copybytes = srcwidth * 4;
2485 if (lines < 0 )
2487 lines = -lines;
2488 dstbits = dstbits + ( linebytes * (lines-1) );
2489 linebytes = -linebytes;
2492 bits = dstbits;
2494 switch ( bmpImage->depth )
2496 case 32:
2497 /* ==== 24/32 BGR bitmap to 32 BGR dib ==== */
2498 if ( bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff )
2499 for (h = lines - 1; h >= 0; h--, dstbits+=linebytes)
2500 memcpy( dstbits, bmpImage->data + h*bmpImage->bytes_per_line, copybytes );
2502 /* ==== 24/32 RGB bitmap to 32 BGR dib ==== */
2503 else if ( bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000 )
2505 LPBYTE srcbits;
2507 for (h = lines - 1; h >= 0; h--) {
2508 srcbits = bmpImage->data + h * bmpImage->bytes_per_line;
2509 for (x = 0; x < dstwidth; x++, bits+=4, srcbits+=2) {
2510 *(bits + 2) = *srcbits++;
2511 *(bits + 1) = *srcbits++;
2512 *bits = *srcbits;
2514 bits = (dstbits += linebytes);
2517 else goto notsupported;
2518 break;
2520 case 24:
2521 /* ==== 24 BGR bitmap to 32 (0888) BGR dib ==== */
2522 /* we need to check that source mask matches destination */
2524 DWORD *srcpixel;
2525 BYTE *bptr;
2526 DWORD srcdata;
2528 srcpixel = (DWORD *) dstbits;
2529 bptr = bmpImage->data;
2531 for (h = lines - 1; h >= 0; h--) {
2532 for (x = 0; x < dstwidth; x++) {
2533 /* *srcpixel is a 32bit value */
2534 /* bptr points to first of 3 bytes */
2535 srcdata = 0;
2536 srcdata = srcdata << 8 | *bptr++;
2537 srcdata = srcdata << 8 | *bptr++;
2538 srcdata = srcdata << 8 | *bptr++;
2540 *srcpixel++ = srcdata;
2542 srcpixel = (DWORD *) (dstbits += linebytes);
2545 break;
2547 case 15:
2549 LPWORD srcpixel;
2550 WORD val;
2552 /* ==== 555 BGR bitmap to 32 BGR dib ==== */
2553 if (bmpImage->red_mask == 0x7c00 && bmpImage->blue_mask == 0x001f)
2555 for (h = lines - 1; h >= 0; h--) {
2556 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2557 for (x = 0; x < dstwidth; x++, bits+=2) {
2558 val = *srcpixel++;
2559 *bits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x03)); /*Blue*/
2560 *bits++ = (BYTE)(((val >> 2) & 0xfc) | ((val >> 8) & 0x03)); /*Green*/
2561 *bits = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07)); /*Red*/
2563 bits = (dstbits += linebytes);
2566 /* ==== 555 RGB bitmap to 32 BGR dib ==== */
2567 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0x7c00)
2569 for (h = lines - 1; h >= 0; h--) {
2570 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2571 for (x = 0; x < dstwidth; x++, bits+=2) {
2572 val = *srcpixel++;
2573 *bits++ = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07));/*Blue*/
2574 *bits++ = (BYTE)(((val >> 2) & 0xfc) | ((val >> 8) & 0x03)); /*Green*/
2575 *bits = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x03)); /*Red*/
2577 bits = (dstbits += linebytes);
2580 else goto notsupported;
2582 break;
2584 case 16:
2586 LPWORD srcpixel;
2587 WORD val;
2589 /* ==== 565 BGR bitmap to 32 BGR dib ==== */
2590 if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f)
2592 for (h = lines - 1; h >= 0; h--) {
2593 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2594 for (x = 0; x < srcwidth; x++, bits+=2) {
2595 val = *srcpixel++;
2596 *bits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x03)); /*Blue*/
2597 *bits++ = (BYTE)(((val >> 3) & 0xfc) | ((val >> 9) & 0x03)); /*Green*/
2598 *bits = (BYTE)(((val >> 8) & 0xf8) | ((val >> 13) & 0x07)); /*Red*/
2600 bits = (dstbits += linebytes);
2603 /* ==== 565 RGB bitmap to 32 BGR dib ==== */
2604 else if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f)
2606 for (h = lines - 1; h >= 0; h--) {
2607 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2608 for (x = 0; x < srcwidth; x++, bits+=2) {
2609 val = *srcpixel++;
2610 *bits++ = (BYTE)(((val >> 8) & 0xf8) | ((val >> 13) & 0x07));/*Blue*/
2611 *bits++ = (BYTE)(((val >> 3) & 0xfc) | ((val >> 9) & 0x03)); /*Green*/
2612 *bits = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x03)); /*Red*/
2614 bits = (dstbits += linebytes);
2617 else goto notsupported;
2619 break;
2621 case 1:
2622 /* ==== monochrome bitmap to 32 BGR dib ==== */
2623 case 4:
2624 /* ==== 4 colormap bitmap to 32 BGR dib ==== */
2625 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
2627 PALETTEENTRY val;
2629 for (h = lines - 1; h >= 0; h--) {
2630 for (x = 0; x < dstwidth; x++) {
2631 val = srccolors[XGetPixel(bmpImage, x, h)];
2632 *bits++ = val.peBlue;
2633 *bits++ = val.peGreen;
2634 *bits++ = val.peRed;
2635 *bits++ = 0;
2637 bits = (dstbits += linebytes);
2640 else goto notsupported;
2642 break;
2644 case 8:
2645 /* ==== 8 colormap bitmap to 32 BGR dib ==== */
2646 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
2648 BYTE *srcpixel;
2649 PALETTEENTRY val;
2651 for (h = lines - 1; h >= 0; h--) {
2652 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
2653 for (x = 0; x < dstwidth; x++) {
2654 val = srccolors[(int)*srcpixel++];
2655 *bits++ = val.peBlue; /*Blue*/
2656 *bits++ = val.peGreen; /*Green*/
2657 *bits++ = val.peRed; /*Red*/
2658 *bits++ = 0;
2660 bits = (dstbits += linebytes);
2663 else goto notsupported;
2664 break;
2666 default:
2667 notsupported:
2668 FIXME("from %d bit bitmap with mask R,G,B %x,%x,%x to 32 bit DIB\n",
2669 bmpImage->depth, (int)bmpImage->red_mask,
2670 (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
2671 for (h = lines - 1; h >= 0; h--)
2673 for (x = 0; x < dstwidth; x++, bits += 4)
2675 COLORREF pixel = X11DRV_PALETTE_ToLogical( XGetPixel( bmpImage, x, h ) );
2676 bits[0] = GetBValue(pixel);
2677 bits[1] = GetGValue(pixel);
2678 bits[2] = GetRValue(pixel);
2680 bits = (dstbits += linebytes);
2682 break;
2686 /***********************************************************************
2687 * X11DRV_DIB_SetImageBits
2689 * Transfer the bits to an X image.
2690 * Helper function for SetDIBits() and SetDIBitsToDevice().
2692 static int X11DRV_DIB_SetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
2694 int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
2695 XImage *bmpImage;
2697 wine_tsx11_lock();
2698 if (descr->image)
2699 bmpImage = descr->image;
2700 else {
2701 bmpImage = XCreateImage( gdi_display, visual, descr->depth, ZPixmap, 0, NULL,
2702 descr->infoWidth, lines, 32, 0 );
2703 bmpImage->data = calloc( lines, bmpImage->bytes_per_line );
2704 if(bmpImage->data == NULL) {
2705 ERR("Out of memory!\n");
2706 XDestroyImage( bmpImage );
2707 wine_tsx11_unlock();
2708 return lines;
2712 /* Transfer the pixels */
2713 switch(descr->infoBpp)
2715 case 1:
2716 X11DRV_DIB_SetImageBits_1( descr->lines, descr->bits, descr->infoWidth,
2717 descr->width, descr->xSrc, (int *)(descr->colorMap),
2718 bmpImage, descr->dibpitch );
2719 break;
2720 case 4:
2721 if (descr->compression) {
2722 XGetSubImage( gdi_display, descr->drawable, descr->xDest, descr->yDest,
2723 descr->width, descr->height, AllPlanes, ZPixmap,
2724 bmpImage, descr->xSrc, descr->ySrc );
2726 X11DRV_DIB_SetImageBits_RLE4( descr->lines, descr->bits,
2727 descr->infoWidth, descr->width,
2728 descr->xSrc, (int *)(descr->colorMap),
2729 bmpImage );
2730 } else
2731 X11DRV_DIB_SetImageBits_4( descr->lines, descr->bits,
2732 descr->infoWidth, descr->width,
2733 descr->xSrc, (int*)(descr->colorMap),
2734 bmpImage, descr->dibpitch );
2735 break;
2736 case 8:
2737 if (descr->compression) {
2738 XGetSubImage( gdi_display, descr->drawable, descr->xDest, descr->yDest,
2739 descr->width, descr->height, AllPlanes, ZPixmap,
2740 bmpImage, descr->xSrc, descr->ySrc );
2741 X11DRV_DIB_SetImageBits_RLE8( descr->lines, descr->bits,
2742 descr->infoWidth, descr->width,
2743 descr->xSrc, (int *)(descr->colorMap),
2744 bmpImage );
2745 } else
2746 X11DRV_DIB_SetImageBits_8( descr->lines, descr->bits,
2747 descr->infoWidth, descr->width,
2748 descr->xSrc, (int *)(descr->colorMap),
2749 bmpImage, descr->dibpitch );
2750 break;
2751 case 15:
2752 case 16:
2753 X11DRV_DIB_SetImageBits_16( descr->lines, descr->bits,
2754 descr->infoWidth, descr->width,
2755 descr->xSrc, descr->dc,
2756 descr->rMask, descr->gMask, descr->bMask,
2757 bmpImage, descr->dibpitch);
2758 break;
2759 case 24:
2760 X11DRV_DIB_SetImageBits_24( descr->lines, descr->bits,
2761 descr->infoWidth, descr->width,
2762 descr->xSrc, descr->dc, bmpImage,
2763 descr->dibpitch);
2764 break;
2765 case 32:
2766 X11DRV_DIB_SetImageBits_32( descr->lines, descr->bits,
2767 descr->infoWidth, descr->width,
2768 descr->xSrc, descr->dc,
2769 bmpImage, descr->dibpitch);
2770 break;
2771 default:
2772 WARN("(%d): Invalid depth\n", descr->infoBpp );
2773 break;
2776 TRACE("XPutImage(%ld,%p,%p,%d,%d,%d,%d,%d,%d)\n",
2777 descr->drawable, descr->gc, bmpImage,
2778 descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
2779 descr->width, descr->height);
2780 #ifdef HAVE_LIBXXSHM
2781 if (descr->useShm)
2783 XShmPutImage( gdi_display, descr->drawable, descr->gc, bmpImage,
2784 descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
2785 descr->width, descr->height, FALSE );
2786 XSync( gdi_display, 0 );
2788 else
2789 #endif
2790 XPutImage( gdi_display, descr->drawable, descr->gc, bmpImage,
2791 descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
2792 descr->width, descr->height );
2794 if (!descr->image) XDestroyImage( bmpImage );
2795 wine_tsx11_unlock();
2796 return lines;
2799 /***********************************************************************
2800 * X11DRV_DIB_GetImageBits
2802 * Transfer the bits from an X image.
2804 static int X11DRV_DIB_GetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
2806 int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
2807 XImage *bmpImage;
2809 wine_tsx11_lock();
2810 if (descr->image)
2811 bmpImage = descr->image;
2812 else {
2813 bmpImage = XCreateImage( gdi_display, visual, descr->depth, ZPixmap, 0, NULL,
2814 descr->infoWidth, lines, 32, 0 );
2815 bmpImage->data = calloc( lines, bmpImage->bytes_per_line );
2816 if(bmpImage->data == NULL) {
2817 ERR("Out of memory!\n");
2818 XDestroyImage( bmpImage );
2819 wine_tsx11_unlock();
2820 return lines;
2824 TRACE("XGetSubImage(%ld,%d,%d,%d,%d,%ld,%d,%p,%d,%d)\n",
2825 descr->drawable, descr->xSrc, descr->ySrc, descr->width,
2826 lines, AllPlanes, ZPixmap, bmpImage, descr->xDest, descr->yDest);
2827 XGetSubImage( gdi_display, descr->drawable, descr->xSrc, descr->ySrc,
2828 descr->width, lines, AllPlanes, ZPixmap,
2829 bmpImage, descr->xDest, descr->yDest );
2831 /* Transfer the pixels */
2832 switch(descr->infoBpp)
2834 case 1:
2835 X11DRV_DIB_GetImageBits_1( descr->lines,(LPVOID)descr->bits,
2836 descr->infoWidth, descr->width,
2837 descr->colorMap, descr->palentry,
2838 bmpImage, descr->dibpitch );
2839 break;
2841 case 4:
2842 if (descr->compression)
2843 FIXME("Compression not yet supported!\n");
2844 else
2845 X11DRV_DIB_GetImageBits_4( descr->lines,(LPVOID)descr->bits,
2846 descr->infoWidth, descr->width,
2847 descr->colorMap, descr->palentry,
2848 bmpImage, descr->dibpitch );
2849 break;
2851 case 8:
2852 if (descr->compression)
2853 FIXME("Compression not yet supported!\n");
2854 else
2855 X11DRV_DIB_GetImageBits_8( descr->lines, (LPVOID)descr->bits,
2856 descr->infoWidth, descr->width,
2857 descr->colorMap, descr->palentry,
2858 bmpImage, descr->dibpitch );
2859 break;
2860 case 15:
2861 case 16:
2862 X11DRV_DIB_GetImageBits_16( descr->lines, (LPVOID)descr->bits,
2863 descr->infoWidth,descr->width,
2864 descr->palentry,
2865 descr->rMask, descr->gMask, descr->bMask,
2866 bmpImage, descr->dibpitch );
2867 break;
2869 case 24:
2870 X11DRV_DIB_GetImageBits_24( descr->lines, (LPVOID)descr->bits,
2871 descr->infoWidth,descr->width,
2872 descr->palentry, bmpImage, descr->dibpitch);
2873 break;
2875 case 32:
2876 X11DRV_DIB_GetImageBits_32( descr->lines, (LPVOID)descr->bits,
2877 descr->infoWidth, descr->width,
2878 descr->palentry, bmpImage, descr->dibpitch);
2879 break;
2881 default:
2882 WARN("(%d): Invalid depth\n", descr->infoBpp );
2883 break;
2886 if (!descr->image) XDestroyImage( bmpImage );
2887 wine_tsx11_unlock();
2888 return lines;
2891 /*************************************************************************
2892 * X11DRV_SetDIBitsToDevice
2895 INT X11DRV_SetDIBitsToDevice( DC *dc, INT xDest, INT yDest, DWORD cx,
2896 DWORD cy, INT xSrc, INT ySrc,
2897 UINT startscan, UINT lines, LPCVOID bits,
2898 const BITMAPINFO *info, UINT coloruse )
2900 X11DRV_DIB_IMAGEBITS_DESCR descr;
2901 DWORD width, oldcy = cy;
2902 INT result;
2903 int height, tmpheight;
2904 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
2907 if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height,
2908 &descr.infoBpp, &descr.compression ) == -1)
2909 return 0;
2910 tmpheight = height;
2911 if (height < 0) height = -height;
2912 if (!lines || (startscan >= height)) return 0;
2913 if (startscan + lines > height) lines = height - startscan;
2914 if (ySrc < startscan) ySrc = startscan;
2915 else if (ySrc >= startscan + lines) return 0;
2916 if (xSrc >= width) return 0;
2917 if (ySrc + cy >= startscan + lines) cy = startscan + lines - ySrc;
2918 if (xSrc + cx >= width) cx = width - xSrc;
2919 if (!cx || !cy) return 0;
2921 X11DRV_SetupGCForText( dc ); /* To have the correct colors */
2922 TSXSetFunction(gdi_display, physDev->gc, X11DRV_XROPfunction[dc->ROPmode-1]);
2924 switch (descr.infoBpp)
2926 case 1:
2927 case 4:
2928 case 8:
2929 descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap(
2930 coloruse == DIB_PAL_COLORS ? dc : NULL, coloruse,
2931 dc->bitsPerPixel, info, &descr.nColorMap );
2932 if (!descr.colorMap) return 0;
2933 descr.rMask = descr.gMask = descr.bMask = 0;
2934 break;
2935 case 15:
2936 case 16:
2937 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
2938 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x03e0;
2939 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x001f;
2940 descr.colorMap = 0;
2941 break;
2943 case 24:
2944 descr.rMask = descr.gMask = descr.bMask = 0;
2945 descr.colorMap = 0;
2946 break;
2948 case 32:
2949 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
2950 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0xff00;
2951 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0xff;
2952 descr.colorMap = 0;
2953 break;
2956 descr.dc = dc;
2957 descr.bits = bits;
2958 descr.image = NULL;
2959 descr.palentry = NULL;
2960 descr.lines = tmpheight >= 0 ? lines : -lines;
2961 descr.infoWidth = width;
2962 descr.depth = dc->bitsPerPixel;
2963 descr.drawable = physDev->drawable;
2964 descr.gc = physDev->gc;
2965 descr.xSrc = xSrc;
2966 descr.ySrc = tmpheight >= 0 ? lines-(ySrc-startscan)-cy+(oldcy-cy)
2967 : ySrc - startscan;
2968 descr.xDest = dc->DCOrgX + XLPTODP( dc, xDest );
2969 descr.yDest = dc->DCOrgY + YLPTODP( dc, yDest ) +
2970 (tmpheight >= 0 ? oldcy-cy : 0);
2971 descr.width = cx;
2972 descr.height = cy;
2973 descr.useShm = FALSE;
2974 descr.dibpitch = ((width * descr.infoBpp + 31) &~31) / 8;
2976 result = X11DRV_DIB_SetImageBits( &descr );
2978 if (descr.infoBpp <= 8)
2979 HeapFree(GetProcessHeap(), 0, descr.colorMap);
2980 return result;
2983 /***********************************************************************
2984 * X11DRV_DIB_SetDIBits
2986 INT X11DRV_DIB_SetDIBits(
2987 BITMAPOBJ *bmp, DC *dc, UINT startscan,
2988 UINT lines, LPCVOID bits, const BITMAPINFO *info,
2989 UINT coloruse, HBITMAP hbitmap)
2991 X11DRV_DIB_IMAGEBITS_DESCR descr;
2992 int height, tmpheight;
2993 INT result;
2995 descr.dc = dc;
2997 if (DIB_GetBitmapInfo( &info->bmiHeader, &descr.infoWidth, &height,
2998 &descr.infoBpp, &descr.compression ) == -1)
2999 return 0;
3001 tmpheight = height;
3002 if (height < 0) height = -height;
3003 if (!lines || (startscan >= height))
3004 return 0;
3006 if (startscan + lines > height) lines = height - startscan;
3008 switch (descr.infoBpp)
3010 case 1:
3011 case 4:
3012 case 8:
3013 descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap(
3014 coloruse == DIB_PAL_COLORS ? descr.dc : NULL, coloruse,
3015 bmp->bitmap.bmBitsPixel,
3016 info, &descr.nColorMap );
3017 if (!descr.colorMap) return 0;
3018 descr.rMask = descr.gMask = descr.bMask = 0;
3019 break;
3020 case 15:
3021 case 16:
3022 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
3023 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x03e0;
3024 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x001f;
3025 descr.colorMap = 0;
3026 break;
3028 case 24:
3029 descr.rMask = descr.gMask = descr.bMask = 0;
3030 descr.colorMap = 0;
3031 break;
3033 case 32:
3034 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
3035 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0xff00;
3036 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0xff;
3037 descr.colorMap = 0;
3038 break;
3040 default: break;
3043 /* HACK for now */
3044 if(!bmp->physBitmap)
3045 X11DRV_CreateBitmap(hbitmap);
3047 descr.bits = bits;
3048 descr.image = NULL;
3049 descr.palentry = NULL;
3050 descr.lines = tmpheight >= 0 ? lines : -lines;
3051 descr.depth = bmp->bitmap.bmBitsPixel;
3052 descr.drawable = (Pixmap)bmp->physBitmap;
3053 descr.gc = BITMAP_GC(bmp);
3054 descr.xSrc = 0;
3055 descr.ySrc = 0;
3056 descr.xDest = 0;
3057 descr.yDest = height - startscan - lines;
3058 descr.width = bmp->bitmap.bmWidth;
3059 descr.height = lines;
3060 descr.useShm = FALSE;
3061 descr.dibpitch = ((descr.infoWidth * descr.infoBpp + 31) &~31) / 8;
3062 result = X11DRV_DIB_SetImageBits( &descr );
3064 if (descr.colorMap) HeapFree(GetProcessHeap(), 0, descr.colorMap);
3066 return result;
3069 /***********************************************************************
3070 * X11DRV_DIB_GetDIBits
3072 INT X11DRV_DIB_GetDIBits(
3073 BITMAPOBJ *bmp, DC *dc, UINT startscan,
3074 UINT lines, LPVOID bits, BITMAPINFO *info,
3075 UINT coloruse, HBITMAP hbitmap)
3077 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
3078 X11DRV_DIB_IMAGEBITS_DESCR descr;
3079 PALETTEOBJ * palette;
3080 int height;
3082 TRACE("%u scanlines of (%i,%i) -> (%i,%i) starting from %u\n",
3083 lines, bmp->bitmap.bmWidth, bmp->bitmap.bmHeight,
3084 (int)info->bmiHeader.biWidth, (int)info->bmiHeader.biHeight,
3085 startscan );
3087 if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->hPalette, PALETTE_MAGIC )))
3088 return 0;
3090 if( lines > bmp->bitmap.bmHeight ) lines = bmp->bitmap.bmHeight;
3092 height = info->bmiHeader.biHeight;
3093 if (height < 0) height = -height;
3094 if( lines > height ) lines = height;
3095 /* Top-down images have a negative biHeight, the scanlines of theses images
3096 * were inverted in X11DRV_DIB_GetImageBits_xx
3097 * To prevent this we simply change the sign of lines
3098 * (the number of scan lines to copy).
3099 * Negative lines are correctly handled by X11DRV_DIB_GetImageBits_xx.
3101 if( info->bmiHeader.biHeight < 0 && lines > 0) lines = -lines;
3103 if( startscan >= bmp->bitmap.bmHeight )
3105 lines = 0;
3106 goto done;
3109 if (DIB_GetBitmapInfo( &info->bmiHeader, &descr.infoWidth, &descr.lines,
3110 &descr.infoBpp, &descr.compression ) == -1)
3112 lines = 0;
3113 goto done;
3116 switch (descr.infoBpp)
3118 case 1:
3119 case 4:
3120 case 8:
3121 case 24:
3122 descr.rMask = descr.gMask = descr.bMask = 0;
3123 break;
3124 case 15:
3125 case 16:
3126 descr.rMask = 0x7c00;
3127 descr.gMask = 0x03e0;
3128 descr.bMask = 0x001f;
3129 break;
3131 case 32:
3132 descr.rMask = 0xff0000;
3133 descr.gMask = 0xff00;
3134 descr.bMask = 0xff;
3135 break;
3138 /* Hack for now */
3139 if(!bmp->physBitmap)
3140 X11DRV_CreateBitmap(hbitmap);
3143 descr.dc = dc;
3144 descr.palentry = palette->logpalette.palPalEntry;
3145 descr.bits = bits;
3146 descr.image = NULL;
3147 descr.lines = lines;
3148 descr.depth = bmp->bitmap.bmBitsPixel;
3149 descr.drawable = (Pixmap)bmp->physBitmap;
3150 descr.gc = BITMAP_GC(bmp);
3151 descr.width = bmp->bitmap.bmWidth;
3152 descr.height = bmp->bitmap.bmHeight;
3153 descr.colorMap = info->bmiColors;
3154 descr.xDest = 0;
3155 descr.yDest = 0;
3156 descr.xSrc = 0;
3158 if (descr.lines > 0)
3160 descr.ySrc = (descr.height-1) - (startscan + (lines-1));
3162 else
3164 descr.ySrc = startscan;
3166 #ifdef HAVE_LIBXXSHM
3167 descr.useShm = dib ? (dib->shminfo.shmid != -1) : FALSE;
3168 #else
3169 descr.useShm = FALSE;
3170 #endif
3171 descr.dibpitch = dib ? (dib->dibSection.dsBm.bmWidthBytes)
3172 : (((descr.infoWidth * descr.infoBpp + 31) &~31) / 8);
3174 X11DRV_DIB_GetImageBits( &descr );
3176 if(info->bmiHeader.biSizeImage == 0) /* Fill in biSizeImage */
3177 info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(
3178 info->bmiHeader.biWidth,
3179 info->bmiHeader.biHeight,
3180 info->bmiHeader.biBitCount );
3182 info->bmiHeader.biCompression = 0;
3183 if (descr.compression == BI_BITFIELDS)
3185 *(DWORD *)info->bmiColors = descr.rMask;
3186 *((DWORD *)info->bmiColors+1) = descr.gMask;
3187 *((DWORD *)info->bmiColors+2) = descr.bMask;
3190 done:
3191 GDI_ReleaseObj( dc->hPalette );
3193 return lines;
3196 /***********************************************************************
3197 * DIB_DoProtectDIBSection
3199 static void X11DRV_DIB_DoProtectDIBSection( BITMAPOBJ *bmp, DWORD new_prot )
3201 DIBSECTION *dib = bmp->dib;
3202 INT effHeight = dib->dsBm.bmHeight >= 0? dib->dsBm.bmHeight
3203 : -dib->dsBm.bmHeight;
3204 /* use the biSizeImage data as the memory size only if we're dealing with a
3205 compressed image where the value is set. Otherwise, calculate based on
3206 width * height */
3207 INT totalSize = dib->dsBmih.biSizeImage && dib->dsBmih.biCompression != BI_RGB
3208 ? dib->dsBmih.biSizeImage
3209 : dib->dsBm.bmWidthBytes * effHeight;
3210 DWORD old_prot;
3212 VirtualProtect(dib->dsBm.bmBits, totalSize, new_prot, &old_prot);
3213 TRACE("Changed protection from %ld to %ld\n", old_prot, new_prot);
3216 /***********************************************************************
3217 * X11DRV_DIB_DoUpdateDIBSection
3219 static void X11DRV_DIB_DoCopyDIBSection(BITMAPOBJ *bmp, BOOL toDIB,
3220 void *colorMap, int nColorMap,
3221 Drawable dest,
3222 DWORD xSrc, DWORD ySrc,
3223 DWORD xDest, DWORD yDest,
3224 DWORD width, DWORD height)
3226 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
3227 X11DRV_DIB_IMAGEBITS_DESCR descr;
3229 if (DIB_GetBitmapInfo( &dib->dibSection.dsBmih, &descr.infoWidth, &descr.lines,
3230 &descr.infoBpp, &descr.compression ) == -1)
3231 return;
3233 descr.dc = NULL;
3234 descr.palentry = NULL;
3235 descr.image = dib->image;
3236 descr.colorMap = colorMap;
3237 descr.nColorMap = nColorMap;
3238 descr.bits = dib->dibSection.dsBm.bmBits;
3239 descr.depth = bmp->bitmap.bmBitsPixel;
3241 switch (descr.infoBpp)
3243 case 1:
3244 case 4:
3245 case 8:
3246 case 24:
3247 descr.rMask = descr.gMask = descr.bMask = 0;
3248 break;
3249 case 15:
3250 case 16:
3251 descr.rMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[0] : 0x7c00;
3252 descr.gMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[1] : 0x03e0;
3253 descr.bMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[2] : 0x001f;
3254 break;
3256 case 32:
3257 descr.rMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[0] : 0xff;
3258 descr.gMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[1] : 0xff00;
3259 descr.bMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[2] : 0xff0000;
3260 break;
3263 /* Hack for now */
3264 descr.drawable = dest;
3265 descr.gc = BITMAP_GC(bmp);
3266 descr.xSrc = xSrc;
3267 descr.ySrc = ySrc;
3268 descr.xDest = xDest;
3269 descr.yDest = yDest;
3270 descr.width = width;
3271 descr.height = height;
3272 #ifdef HAVE_LIBXXSHM
3273 descr.useShm = (dib->shminfo.shmid != -1);
3274 #else
3275 descr.useShm = FALSE;
3276 #endif
3277 descr.dibpitch = dib->dibSection.dsBm.bmWidthBytes;
3279 if (toDIB)
3281 TRACE("Copying from Pixmap to DIB bits\n");
3282 X11DRV_DIB_GetImageBits( &descr );
3284 else
3286 TRACE("Copying from DIB bits to Pixmap\n");
3287 X11DRV_DIB_SetImageBits( &descr );
3291 /***********************************************************************
3292 * X11DRV_DIB_CopyDIBSection
3294 void X11DRV_DIB_CopyDIBSection(DC *dcSrc, DC *dcDst,
3295 DWORD xSrc, DWORD ySrc,
3296 DWORD xDest, DWORD yDest,
3297 DWORD width, DWORD height)
3299 BITMAPOBJ *bmp;
3300 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dcDst->physDev;
3301 int nColorMap = 0, *colorMap = NULL, aColorMap = FALSE;
3303 TRACE("(%p,%p,%ld,%ld,%ld,%ld,%ld,%ld)\n", dcSrc, dcDst,
3304 xSrc, ySrc, xDest, yDest, width, height);
3305 /* this function is meant as an optimization for BitBlt,
3306 * not to be called otherwise */
3307 if (!(dcSrc->flags & DC_MEMORY)) {
3308 ERR("called for non-memory source DC!?\n");
3309 return;
3312 bmp = (BITMAPOBJ *)GDI_GetObjPtr( dcSrc->hBitmap, BITMAP_MAGIC );
3313 if (!(bmp && bmp->dib)) {
3314 ERR("called for non-DIBSection!?\n");
3315 GDI_ReleaseObj( dcSrc->hBitmap );
3316 return;
3318 /* while BitBlt should already have made sure we only get
3319 * positive values, we should check for oversize values */
3320 if ((xSrc < bmp->bitmap.bmWidth) &&
3321 (ySrc < bmp->bitmap.bmHeight)) {
3322 if (xSrc + width > bmp->bitmap.bmWidth)
3323 width = bmp->bitmap.bmWidth - xSrc;
3324 if (ySrc + height > bmp->bitmap.bmHeight)
3325 height = bmp->bitmap.bmHeight - ySrc;
3326 /* if the source bitmap is 8bpp or less, we're supposed to use the
3327 * DC's palette for color conversion (not the DIB color table) */
3328 if (bmp->dib->dsBm.bmBitsPixel <= 8) {
3329 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
3330 if ((!dcSrc->hPalette) ||
3331 (dcSrc->hPalette == GetStockObject(DEFAULT_PALETTE))) {
3332 /* HACK: no palette has been set in the source DC,
3333 * use the DIB colormap instead - this is necessary in some
3334 * cases since we need to do depth conversion in some places
3335 * where real Windows can just copy data straight over */
3336 colorMap = dib->colorMap;
3337 nColorMap = dib->nColorMap;
3338 } else {
3339 colorMap = X11DRV_DIB_BuildColorMap( dcSrc, (WORD)-1,
3340 bmp->dib->dsBm.bmBitsPixel,
3341 (BITMAPINFO*)&(bmp->dib->dsBmih),
3342 &nColorMap );
3343 if (colorMap) aColorMap = TRUE;
3346 /* perform the copy */
3347 X11DRV_DIB_DoCopyDIBSection(bmp, FALSE, colorMap, nColorMap,
3348 physDev->drawable, xSrc, ySrc, xDest, yDest,
3349 width, height);
3350 /* free color mapping */
3351 if (aColorMap)
3352 HeapFree(GetProcessHeap(), 0, colorMap);
3354 GDI_ReleaseObj( dcSrc->hBitmap );
3357 /***********************************************************************
3358 * X11DRV_DIB_DoUpdateDIBSection
3360 static void X11DRV_DIB_DoUpdateDIBSection(BITMAPOBJ *bmp, BOOL toDIB)
3362 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
3363 X11DRV_DIB_DoCopyDIBSection(bmp, toDIB, dib->colorMap, dib->nColorMap,
3364 (Drawable)bmp->physBitmap, 0, 0, 0, 0,
3365 bmp->bitmap.bmWidth, bmp->bitmap.bmHeight);
3368 /***********************************************************************
3369 * X11DRV_DIB_FaultHandler
3371 static BOOL X11DRV_DIB_FaultHandler( LPVOID res, LPCVOID addr )
3373 BITMAPOBJ *bmp;
3374 INT state;
3376 bmp = (BITMAPOBJ *)GDI_GetObjPtr( (HBITMAP)res, BITMAP_MAGIC );
3377 if (!bmp) return FALSE;
3379 state = X11DRV_DIB_Lock(bmp, DIB_Status_None, FALSE);
3380 if (state != DIB_Status_InSync) {
3381 /* no way to tell whether app needs read or write yet,
3382 * try read first */
3383 X11DRV_DIB_Coerce(bmp, DIB_Status_InSync, FALSE);
3384 } else {
3385 /* hm, apparently the app must have write access */
3386 X11DRV_DIB_Coerce(bmp, DIB_Status_AppMod, FALSE);
3388 X11DRV_DIB_Unlock(bmp, TRUE);
3390 GDI_ReleaseObj( (HBITMAP)res );
3391 return TRUE;
3394 /***********************************************************************
3395 * X11DRV_DIB_Coerce
3397 INT X11DRV_DIB_Coerce(BITMAPOBJ *bmp, INT req, BOOL lossy)
3399 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
3400 INT ret = DIB_Status_None;
3402 if (dib) {
3403 EnterCriticalSection(&(dib->lock));
3404 ret = dib->status;
3405 switch (req) {
3406 case DIB_Status_GdiMod:
3407 /* GDI access - request to draw on pixmap */
3408 switch (dib->status)
3410 default:
3411 case DIB_Status_None:
3412 dib->p_status = DIB_Status_GdiMod;
3413 X11DRV_DIB_DoUpdateDIBSection( bmp, FALSE );
3414 break;
3416 case DIB_Status_GdiMod:
3417 TRACE("GdiMod requested in status GdiMod\n" );
3418 break;
3420 case DIB_Status_InSync:
3421 TRACE("GdiMod requested in status InSync\n" );
3422 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
3423 dib->status = DIB_Status_GdiMod;
3424 dib->p_status = DIB_Status_InSync;
3425 break;
3427 case DIB_Status_AuxMod:
3428 TRACE("GdiMod requested in status AuxMod\n" );
3429 if (lossy) dib->status = DIB_Status_GdiMod;
3430 else (*dib->copy_aux)(dib->aux_ctx, DIB_Status_GdiMod);
3431 dib->p_status = DIB_Status_AuxMod;
3432 if (dib->status != DIB_Status_AppMod) {
3433 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
3434 break;
3436 /* fall through if copy_aux() had to change to AppMod state */
3438 case DIB_Status_AppMod:
3439 TRACE("GdiMod requested in status AppMod\n" );
3440 if (!lossy) {
3441 /* make it readonly to avoid app changing data while we copy */
3442 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
3443 X11DRV_DIB_DoUpdateDIBSection( bmp, FALSE );
3445 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
3446 dib->p_status = DIB_Status_AppMod;
3447 dib->status = DIB_Status_GdiMod;
3448 break;
3450 break;
3452 case DIB_Status_InSync:
3453 /* App access - request access to read DIB surface */
3454 /* (typically called from signal handler) */
3455 switch (dib->status)
3457 default:
3458 case DIB_Status_None:
3459 /* shouldn't happen from signal handler */
3460 break;
3462 case DIB_Status_AuxMod:
3463 TRACE("InSync requested in status AuxMod\n" );
3464 if (lossy) dib->status = DIB_Status_InSync;
3465 else {
3466 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
3467 (*dib->copy_aux)(dib->aux_ctx, DIB_Status_InSync);
3469 if (dib->status != DIB_Status_GdiMod) {
3470 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
3471 break;
3473 /* fall through if copy_aux() had to change to GdiMod state */
3475 case DIB_Status_GdiMod:
3476 TRACE("InSync requested in status GdiMod\n" );
3477 if (!lossy) {
3478 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
3479 X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
3481 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
3482 dib->status = DIB_Status_InSync;
3483 break;
3485 case DIB_Status_InSync:
3486 TRACE("InSync requested in status InSync\n" );
3487 /* shouldn't happen from signal handler */
3488 break;
3490 case DIB_Status_AppMod:
3491 TRACE("InSync requested in status AppMod\n" );
3492 /* no reason to do anything here, and this
3493 * shouldn't happen from signal handler */
3494 break;
3496 break;
3498 case DIB_Status_AppMod:
3499 /* App access - request access to write DIB surface */
3500 /* (typically called from signal handler) */
3501 switch (dib->status)
3503 default:
3504 case DIB_Status_None:
3505 /* shouldn't happen from signal handler */
3506 break;
3508 case DIB_Status_AuxMod:
3509 TRACE("AppMod requested in status AuxMod\n" );
3510 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
3511 if (lossy) dib->status = DIB_Status_AppMod;
3512 else (*dib->copy_aux)(dib->aux_ctx, DIB_Status_AppMod);
3513 if (dib->status != DIB_Status_GdiMod)
3514 break;
3515 /* fall through if copy_aux() had to change to GdiMod state */
3517 case DIB_Status_GdiMod:
3518 TRACE("AppMod requested in status GdiMod\n" );
3519 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
3520 if (!lossy) X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
3521 dib->status = DIB_Status_AppMod;
3522 break;
3524 case DIB_Status_InSync:
3525 TRACE("AppMod requested in status InSync\n" );
3526 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
3527 dib->status = DIB_Status_AppMod;
3528 break;
3530 case DIB_Status_AppMod:
3531 TRACE("AppMod requested in status AppMod\n" );
3532 /* shouldn't happen from signal handler */
3533 break;
3535 break;
3537 case DIB_Status_AuxMod:
3538 if (dib->status == DIB_Status_None) {
3539 dib->p_status = req;
3540 } else {
3541 if (dib->status != DIB_Status_AuxMod)
3542 dib->p_status = dib->status;
3543 dib->status = DIB_Status_AuxMod;
3545 break;
3546 /* it is up to the caller to do the copy/conversion, probably
3547 * using the return value to decide where to copy from */
3549 LeaveCriticalSection(&(dib->lock));
3551 return ret;
3554 /***********************************************************************
3555 * X11DRV_DIB_Lock
3557 INT X11DRV_DIB_Lock(BITMAPOBJ *bmp, INT req, BOOL lossy)
3559 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
3560 INT ret = DIB_Status_None;
3562 if (dib) {
3563 TRACE("Locking %p from thread %08lx\n", bmp, GetCurrentThreadId());
3564 EnterCriticalSection(&(dib->lock));
3565 ret = dib->status;
3566 if (req != DIB_Status_None)
3567 X11DRV_DIB_Coerce(bmp, req, lossy);
3569 return ret;
3572 /***********************************************************************
3573 * X11DRV_DIB_Unlock
3575 void X11DRV_DIB_Unlock(BITMAPOBJ *bmp, BOOL commit)
3577 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
3579 if (dib) {
3580 switch (dib->status)
3582 default:
3583 case DIB_Status_None:
3584 /* in case anyone is wondering, this is the "signal handler doesn't
3585 * work" case, where we always have to be ready for app access */
3586 if (commit) {
3587 switch (dib->p_status)
3589 case DIB_Status_AuxMod:
3590 TRACE("Unlocking and syncing from AuxMod\n" );
3591 (*dib->copy_aux)(dib->aux_ctx, DIB_Status_AppMod);
3592 if (dib->status != DIB_Status_None) {
3593 dib->p_status = dib->status;
3594 dib->status = DIB_Status_None;
3596 if (dib->p_status != DIB_Status_GdiMod)
3597 break;
3598 /* fall through if copy_aux() had to change to GdiMod state */
3600 case DIB_Status_GdiMod:
3601 TRACE("Unlocking and syncing from GdiMod\n" );
3602 X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
3603 break;
3605 default:
3606 TRACE("Unlocking without needing to sync\n" );
3607 break;
3610 else TRACE("Unlocking with no changes\n");
3611 dib->p_status = DIB_Status_None;
3612 break;
3614 case DIB_Status_GdiMod:
3615 TRACE("Unlocking in status GdiMod\n" );
3616 /* DIB was protected in Coerce */
3617 if (!commit) {
3618 /* no commit, revert to InSync if applicable */
3619 if ((dib->p_status == DIB_Status_InSync) ||
3620 (dib->p_status == DIB_Status_AppMod)) {
3621 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
3622 dib->status = DIB_Status_InSync;
3625 break;
3627 case DIB_Status_InSync:
3628 TRACE("Unlocking in status InSync\n" );
3629 /* DIB was already protected in Coerce */
3630 break;
3632 case DIB_Status_AppMod:
3633 TRACE("Unlocking in status AppMod\n" );
3634 /* DIB was already protected in Coerce */
3635 /* this case is ordinary only called from the signal handler,
3636 * so we don't bother to check for !commit */
3637 break;
3639 case DIB_Status_AuxMod:
3640 TRACE("Unlocking in status AuxMod\n" );
3641 if (commit) {
3642 /* DIB may need protection now */
3643 if ((dib->p_status == DIB_Status_InSync) ||
3644 (dib->p_status == DIB_Status_AppMod))
3645 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
3646 } else {
3647 /* no commit, revert to previous state */
3648 if (dib->p_status != DIB_Status_None)
3649 dib->status = dib->p_status;
3650 /* no protections changed */
3652 dib->p_status = DIB_Status_None;
3653 break;
3655 LeaveCriticalSection(&(dib->lock));
3656 TRACE("Unlocked %p\n", bmp);
3660 /***********************************************************************
3661 * X11DRV_CoerceDIBSection2
3663 INT X11DRV_CoerceDIBSection2(HBITMAP hBmp, INT req, BOOL lossy)
3665 BITMAPOBJ *bmp;
3666 INT ret;
3668 bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
3669 if (!bmp) return DIB_Status_None;
3670 ret = X11DRV_DIB_Coerce(bmp, req, lossy);
3671 GDI_ReleaseObj( hBmp );
3672 return ret;
3675 /***********************************************************************
3676 * X11DRV_LockDIBSection2
3678 INT X11DRV_LockDIBSection2(HBITMAP hBmp, INT req, BOOL lossy)
3680 BITMAPOBJ *bmp;
3681 INT ret;
3683 bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
3684 if (!bmp) return DIB_Status_None;
3685 ret = X11DRV_DIB_Lock(bmp, req, lossy);
3686 GDI_ReleaseObj( hBmp );
3687 return ret;
3690 /***********************************************************************
3691 * X11DRV_UnlockDIBSection2
3693 void X11DRV_UnlockDIBSection2(HBITMAP hBmp, BOOL commit)
3695 BITMAPOBJ *bmp;
3697 bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
3698 if (!bmp) return;
3699 X11DRV_DIB_Unlock(bmp, commit);
3700 GDI_ReleaseObj( hBmp );
3703 /***********************************************************************
3704 * X11DRV_CoerceDIBSection
3706 INT X11DRV_CoerceDIBSection(DC *dc, INT req, BOOL lossy)
3708 if (!dc) return DIB_Status_None;
3709 return X11DRV_CoerceDIBSection2( dc->hBitmap, req, lossy );
3712 /***********************************************************************
3713 * X11DRV_LockDIBSection
3715 INT X11DRV_LockDIBSection(DC *dc, INT req, BOOL lossy)
3717 if (!dc) return DIB_Status_None;
3718 if (!(dc->flags & DC_MEMORY)) return DIB_Status_None;
3720 return X11DRV_LockDIBSection2( dc->hBitmap, req, lossy );
3723 /***********************************************************************
3724 * X11DRV_UnlockDIBSection
3726 void X11DRV_UnlockDIBSection(DC *dc, BOOL commit)
3728 if (!dc) return;
3729 if (!(dc->flags & DC_MEMORY)) return;
3731 X11DRV_UnlockDIBSection2( dc->hBitmap, commit );
3735 #ifdef HAVE_LIBXXSHM
3736 /***********************************************************************
3737 * X11DRV_XShmErrorHandler
3740 static int XShmErrorHandler(Display *dpy, XErrorEvent *event)
3742 XShmErrorFlag = 1;
3743 return 0;
3746 /***********************************************************************
3747 * X11DRV_XShmCreateImage
3750 static XImage *X11DRV_XShmCreateImage( int width, int height, int bpp,
3751 XShmSegmentInfo* shminfo)
3753 int (*WineXHandler)(Display *, XErrorEvent *);
3754 XImage *image;
3756 wine_tsx11_lock();
3757 image = XShmCreateImage(gdi_display, visual, bpp, ZPixmap, NULL, shminfo, width, height);
3758 if (image)
3760 shminfo->shmid = shmget(IPC_PRIVATE, image->bytes_per_line * height,
3761 IPC_CREAT|0700);
3762 if( shminfo->shmid != -1 )
3764 shminfo->shmaddr = image->data = shmat(shminfo->shmid, 0, 0);
3765 if( shminfo->shmaddr != (char*)-1 )
3767 shminfo->readOnly = FALSE;
3768 if( XShmAttach( gdi_display, shminfo ) != 0)
3770 /* Reset the error flag */
3771 XShmErrorFlag = 0;
3772 WineXHandler = XSetErrorHandler(XShmErrorHandler);
3773 XSync( gdi_display, 0 );
3775 if (!XShmErrorFlag)
3777 shmctl(shminfo->shmid, IPC_RMID, 0);
3779 XSetErrorHandler(WineXHandler);
3780 wine_tsx11_unlock();
3781 return image; /* Success! */
3783 /* An error occured */
3784 XShmErrorFlag = 0;
3785 XSetErrorHandler(WineXHandler);
3787 shmdt(shminfo->shmaddr);
3789 shmctl(shminfo->shmid, IPC_RMID, 0);
3791 XFlush(gdi_display);
3792 XDestroyImage(image);
3793 image = NULL;
3795 wine_tsx11_unlock();
3796 return image;
3798 #endif /* HAVE_LIBXXSHM */
3801 /***********************************************************************
3802 * X11DRV_DIB_CreateDIBSection
3804 HBITMAP X11DRV_DIB_CreateDIBSection(
3805 DC *dc, BITMAPINFO *bmi, UINT usage,
3806 LPVOID *bits, HANDLE section,
3807 DWORD offset, DWORD ovr_pitch)
3809 HBITMAP res = 0;
3810 BITMAPOBJ *bmp = NULL;
3811 X11DRV_DIBSECTION *dib = NULL;
3812 int *colorMap = NULL;
3813 int nColorMap;
3815 /* Fill BITMAP32 structure with DIB data */
3816 BITMAPINFOHEADER *bi = &bmi->bmiHeader;
3817 INT effHeight, totalSize;
3818 BITMAP bm;
3819 LPVOID mapBits = NULL;
3821 TRACE("format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
3822 bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
3823 bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
3825 effHeight = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
3826 bm.bmType = 0;
3827 bm.bmWidth = bi->biWidth;
3828 bm.bmHeight = effHeight;
3829 bm.bmWidthBytes = ovr_pitch ? ovr_pitch
3830 : DIB_GetDIBWidthBytes(bm.bmWidth, bi->biBitCount);
3831 bm.bmPlanes = bi->biPlanes;
3832 bm.bmBitsPixel = bi->biBitCount;
3833 bm.bmBits = NULL;
3835 /* Get storage location for DIB bits. Only use biSizeImage if it's valid and
3836 we're dealing with a compressed bitmap. Otherwise, use width * height. */
3837 totalSize = bi->biSizeImage && bi->biCompression != BI_RGB
3838 ? bi->biSizeImage : bm.bmWidthBytes * effHeight;
3840 if (section)
3842 SYSTEM_INFO SystemInfo;
3843 DWORD mapOffset;
3844 INT mapSize;
3846 GetSystemInfo( &SystemInfo );
3847 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
3848 mapSize = totalSize + (offset - mapOffset);
3849 mapBits = MapViewOfFile( section,
3850 FILE_MAP_ALL_ACCESS,
3852 mapOffset,
3853 mapSize );
3854 bm.bmBits = (char *)mapBits + (offset - mapOffset);
3856 else if (ovr_pitch && offset)
3857 bm.bmBits = (LPVOID) offset;
3858 else {
3859 offset = 0;
3860 bm.bmBits = VirtualAlloc(NULL, totalSize,
3861 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
3864 /* Create Color Map */
3865 if (bm.bmBits && bm.bmBitsPixel <= 8)
3866 colorMap = X11DRV_DIB_BuildColorMap( usage == DIB_PAL_COLORS? dc : NULL,
3867 usage, bm.bmBitsPixel, bmi, &nColorMap );
3869 /* Allocate Memory for DIB and fill structure */
3870 if (bm.bmBits)
3871 dib = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(X11DRV_DIBSECTION));
3872 if (dib)
3874 dib->dibSection.dsBm = bm;
3875 dib->dibSection.dsBmih = *bi;
3876 dib->dibSection.dsBmih.biSizeImage = totalSize;
3878 /* Set dsBitfields values */
3879 if ( usage == DIB_PAL_COLORS || bi->biBitCount <= 8)
3881 dib->dibSection.dsBitfields[0] = dib->dibSection.dsBitfields[1] = dib->dibSection.dsBitfields[2] = 0;
3883 else switch( bi->biBitCount )
3885 case 16:
3886 dib->dibSection.dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors : 0x7c00;
3887 dib->dibSection.dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0x03e0;
3888 dib->dibSection.dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0x001f;
3889 break;
3891 case 24:
3892 dib->dibSection.dsBitfields[0] = 0xff;
3893 dib->dibSection.dsBitfields[1] = 0xff00;
3894 dib->dibSection.dsBitfields[2] = 0xff0000;
3895 break;
3897 case 32:
3898 dib->dibSection.dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors : 0xff;
3899 dib->dibSection.dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0xff00;
3900 dib->dibSection.dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0xff0000;
3901 break;
3903 dib->dibSection.dshSection = section;
3904 dib->dibSection.dsOffset = offset;
3906 dib->status = DIB_Status_None;
3907 dib->nColorMap = nColorMap;
3908 dib->colorMap = colorMap;
3911 /* Create Device Dependent Bitmap and add DIB pointer */
3912 if (dib)
3914 res = CreateDIBitmap(dc->hSelf, bi, 0, NULL, bmi, usage);
3915 if (res)
3917 bmp = (BITMAPOBJ *) GDI_GetObjPtr(res, BITMAP_MAGIC);
3918 if (bmp)
3920 bmp->dib = (DIBSECTION *) dib;
3921 /* HACK for now */
3922 if(!bmp->physBitmap)
3923 X11DRV_CreateBitmap(res);
3928 /* Create XImage */
3929 if (dib && bmp)
3931 #ifdef HAVE_LIBXXSHM
3932 if (TSXShmQueryExtension(gdi_display) &&
3933 (dib->image = X11DRV_XShmCreateImage( bm.bmWidth, effHeight,
3934 bmp->bitmap.bmBitsPixel, &dib->shminfo )) )
3936 ; /* Created Image */
3937 } else {
3938 dib->image = X11DRV_DIB_CreateXImage( bm.bmWidth, effHeight, bmp->bitmap.bmBitsPixel );
3939 dib->shminfo.shmid = -1;
3941 #else
3942 dib->image = X11DRV_DIB_CreateXImage( bm.bmWidth, effHeight, bmp->bitmap.bmBitsPixel );
3943 #endif
3946 /* Clean up in case of errors */
3947 if (!res || !bmp || !dib || !bm.bmBits || (bm.bmBitsPixel <= 8 && !colorMap))
3949 TRACE("got an error res=%08x, bmp=%p, dib=%p, bm.bmBits=%p\n",
3950 res, bmp, dib, bm.bmBits);
3951 if (bm.bmBits)
3953 if (section)
3954 UnmapViewOfFile(mapBits), bm.bmBits = NULL;
3955 else if (!offset)
3956 VirtualFree(bm.bmBits, 0L, MEM_RELEASE), bm.bmBits = NULL;
3959 if (dib && dib->image) { XDestroyImage(dib->image); dib->image = NULL; }
3960 if (colorMap) { HeapFree(GetProcessHeap(), 0, colorMap); colorMap = NULL; }
3961 if (dib) { HeapFree(GetProcessHeap(), 0, dib); dib = NULL; }
3962 if (bmp) { GDI_ReleaseObj(res); bmp = NULL; }
3963 if (res) { DeleteObject(res); res = 0; }
3965 else if (bm.bmBits)
3967 /* Install fault handler, if possible */
3968 InitializeCriticalSection(&(dib->lock));
3969 if (VIRTUAL_SetFaultHandler(bm.bmBits, X11DRV_DIB_FaultHandler, (LPVOID)res))
3971 if (section || offset)
3973 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
3974 if (dib) dib->status = DIB_Status_AppMod;
3976 else
3978 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
3979 if (dib) dib->status = DIB_Status_InSync;
3984 /* Return BITMAP handle and storage location */
3985 if (bmp) GDI_ReleaseObj(res);
3986 if (bm.bmBits && bits) *bits = bm.bmBits;
3987 return res;
3990 /***********************************************************************
3991 * X11DRV_DIB_DeleteDIBSection
3993 void X11DRV_DIB_DeleteDIBSection(BITMAPOBJ *bmp)
3995 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
3997 if (dib->image)
3999 #ifdef HAVE_LIBXXSHM
4000 if (dib->shminfo.shmid != -1)
4002 TSXShmDetach (gdi_display, &(dib->shminfo));
4003 XDestroyImage (dib->image);
4004 shmdt (dib->shminfo.shmaddr);
4005 dib->shminfo.shmid = -1;
4007 else
4008 #endif
4009 XDestroyImage( dib->image );
4012 if (dib->colorMap)
4013 HeapFree(GetProcessHeap(), 0, dib->colorMap);
4015 DeleteCriticalSection(&(dib->lock));
4018 /***********************************************************************
4019 * X11DRV_DIB_SetDIBColorTable
4021 UINT X11DRV_DIB_SetDIBColorTable(BITMAPOBJ *bmp, DC *dc, UINT start, UINT count, const RGBQUAD *colors)
4023 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
4025 if (dib && dib->colorMap) {
4027 * Changing color table might change the mapping between
4028 * DIB colors and X11 colors and thus alter the visible state
4029 * of the bitmap object.
4031 X11DRV_DIB_Lock(bmp, DIB_Status_AppMod, FALSE);
4032 X11DRV_DIB_GenColorMap( dc, dib->colorMap, DIB_RGB_COLORS,
4033 dib->dibSection.dsBm.bmBitsPixel,
4034 TRUE, colors, start, count + start );
4035 X11DRV_DIB_Unlock(bmp, TRUE);
4036 return count;
4038 return 0;
4041 /***********************************************************************
4042 * X11DRV_DIB_GetDIBColorTable
4044 UINT X11DRV_DIB_GetDIBColorTable(BITMAPOBJ *bmp, DC *dc, UINT start, UINT count, RGBQUAD *colors)
4046 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
4048 if (dib && dib->colorMap) {
4049 int i, end = count + start;
4050 if (end > dib->nColorMap) end = dib->nColorMap;
4051 for (i = start; i < end; i++,colors++) {
4052 COLORREF col = X11DRV_PALETTE_ToLogical( dib->colorMap[i] );
4053 colors->rgbBlue = GetBValue(col);
4054 colors->rgbGreen = GetGValue(col);
4055 colors->rgbRed = GetRValue(col);
4056 colors->rgbReserved = 0;
4058 return end-start;
4060 return 0;
4064 /**************************************************************************
4065 * X11DRV_DIB_CreateDIBFromPixmap
4067 * Allocates a packed DIB and copies the Pixmap data into it.
4068 * If bDeletePixmap is TRUE, the Pixmap passed in is deleted after the conversion.
4070 HGLOBAL X11DRV_DIB_CreateDIBFromPixmap(Pixmap pixmap, HDC hdc, BOOL bDeletePixmap)
4072 HBITMAP hBmp = 0;
4073 BITMAPOBJ *pBmp = NULL;
4074 HGLOBAL hPackedDIB = 0;
4076 /* Allocates an HBITMAP which references the Pixmap passed to us */
4077 hBmp = X11DRV_BITMAP_CreateBitmapHeaderFromPixmap(pixmap);
4078 if (!hBmp)
4080 TRACE("\tCould not create bitmap header for Pixmap\n");
4081 goto END;
4085 * Create a packed DIB from the Pixmap wrapper bitmap created above.
4086 * A packed DIB contains a BITMAPINFO structure followed immediately by
4087 * an optional color palette and the pixel data.
4089 hPackedDIB = DIB_CreateDIBFromBitmap(hdc, hBmp);
4091 /* Get a pointer to the BITMAPOBJ structure */
4092 pBmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
4094 /* We can now get rid of the HBITMAP wrapper we created earlier.
4095 * Note: Simply calling DeleteObject will free the embedded Pixmap as well.
4097 if (!bDeletePixmap)
4099 /* Clear the physBitmap to prevent the Pixmap from being deleted by DeleteObject */
4100 pBmp->physBitmap = NULL;
4101 pBmp->funcs = NULL;
4103 GDI_ReleaseObj( hBmp );
4104 DeleteObject(hBmp);
4106 END:
4107 TRACE("\tReturning packed DIB %x\n", hPackedDIB);
4108 return hPackedDIB;
4112 /**************************************************************************
4113 * X11DRV_DIB_CreatePixmapFromDIB
4115 * Creates a Pixmap from a packed DIB
4117 Pixmap X11DRV_DIB_CreatePixmapFromDIB( HGLOBAL hPackedDIB, HDC hdc )
4119 Pixmap pixmap = None;
4120 HBITMAP hBmp = 0;
4121 BITMAPOBJ *pBmp = NULL;
4122 LPBYTE pPackedDIB = NULL;
4123 LPBITMAPINFO pbmi = NULL;
4124 LPBITMAPINFOHEADER pbmiHeader = NULL;
4125 LPBYTE pbits = NULL;
4127 /* Get a pointer to the packed DIB's data */
4128 pPackedDIB = (LPBYTE)GlobalLock(hPackedDIB);
4129 pbmiHeader = (LPBITMAPINFOHEADER)pPackedDIB;
4130 pbmi = (LPBITMAPINFO)pPackedDIB;
4131 pbits = (LPBYTE)(pPackedDIB
4132 + DIB_BitmapInfoSize( (LPBITMAPINFO)pbmiHeader, DIB_RGB_COLORS ));
4134 /* Create a DDB from the DIB */
4136 hBmp = CreateDIBitmap(hdc,
4137 pbmiHeader,
4138 CBM_INIT,
4139 (LPVOID)pbits,
4140 pbmi,
4141 DIB_RGB_COLORS);
4143 GlobalUnlock(hPackedDIB);
4145 TRACE("CreateDIBitmap returned %x\n", hBmp);
4147 /* Retrieve the internal Pixmap from the DDB */
4149 pBmp = (BITMAPOBJ *) GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
4151 pixmap = (Pixmap)pBmp->physBitmap;
4152 /* clear the physBitmap so that we can steal its pixmap */
4153 pBmp->physBitmap = NULL;
4154 pBmp->funcs = NULL;
4156 /* Delete the DDB we created earlier now that we have stolen its pixmap */
4157 GDI_ReleaseObj( hBmp );
4158 DeleteObject(hBmp);
4160 TRACE("\tReturning Pixmap %ld\n", pixmap);
4161 return pixmap;