Fixed CoerceDIBSection's AuxMod handling. Added CoerceDIBSection2.
[wine.git] / graphics / x11drv / dib.c
blob58052f705a866f760ba8ec6334956b3eb7c6aa9b
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 "color.h"
29 #include "selectors.h"
30 #include "global.h"
32 DEFAULT_DEBUG_CHANNEL(bitmap);
33 DECLARE_DEBUG_CHANNEL(x11drv);
35 static int bitmapDepthTable[] = { 8, 1, 32, 16, 24, 15, 4, 0 };
36 static int ximageDepthTable[] = { 0, 0, 0, 0, 0, 0, 0 };
38 static int XShmErrorFlag = 0;
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;
69 /***********************************************************************
70 * X11DRV_DIB_Init
72 BOOL X11DRV_DIB_Init(void)
74 int i;
75 XImage* testimage;
77 for( i = 0; bitmapDepthTable[i]; i++ )
79 testimage = TSXCreateImage(display, X11DRV_GetVisual(),
80 bitmapDepthTable[i], ZPixmap, 0, NULL, 1, 1, 32, 20 );
81 if( testimage ) ximageDepthTable[i] = testimage->bits_per_pixel;
82 else return FALSE;
83 TSXDestroyImage(testimage);
85 return TRUE;
89 /***********************************************************************
90 * X11DRV_DIB_GetXImageWidthBytes
92 * Return the width of an X image in bytes
94 int X11DRV_DIB_GetXImageWidthBytes( int width, int depth )
96 int i;
98 if (!ximageDepthTable[0]) {
99 X11DRV_DIB_Init();
101 for( i = 0; bitmapDepthTable[i] ; i++ )
102 if( bitmapDepthTable[i] == depth )
103 return (4 * ((width * ximageDepthTable[i] + 31)/32));
105 WARN("(%d): Unsupported depth\n", depth );
106 return (4 * width);
109 /***********************************************************************
110 * X11DRV_DIB_GenColorMap
112 * Fills the color map of a bitmap palette. Should not be called
113 * for a >8-bit deep bitmap.
115 int *X11DRV_DIB_GenColorMap( DC *dc, int *colorMapping,
116 WORD coloruse, WORD depth, BOOL quads,
117 const void *colorPtr, int start, int end )
119 int i;
121 if (coloruse == DIB_RGB_COLORS)
123 if (quads)
125 RGBQUAD * rgb = (RGBQUAD *)colorPtr;
127 if (depth == 1) /* Monochrome */
128 for (i = start; i < end; i++, rgb++)
129 colorMapping[i] = (rgb->rgbRed + rgb->rgbGreen +
130 rgb->rgbBlue > 255*3/2);
131 else
132 for (i = start; i < end; i++, rgb++)
133 colorMapping[i] = X11DRV_PALETTE_ToPhysical( dc, RGB(rgb->rgbRed,
134 rgb->rgbGreen,
135 rgb->rgbBlue));
137 else
139 RGBTRIPLE * rgb = (RGBTRIPLE *)colorPtr;
141 if (depth == 1) /* Monochrome */
142 for (i = start; i < end; i++, rgb++)
143 colorMapping[i] = (rgb->rgbtRed + rgb->rgbtGreen +
144 rgb->rgbtBlue > 255*3/2);
145 else
146 for (i = start; i < end; i++, rgb++)
147 colorMapping[i] = X11DRV_PALETTE_ToPhysical( dc, RGB(rgb->rgbtRed,
148 rgb->rgbtGreen,
149 rgb->rgbtBlue));
152 else /* DIB_PAL_COLORS */
154 if (colorPtr) {
155 WORD * index = (WORD *)colorPtr;
157 for (i = start; i < end; i++, index++)
158 colorMapping[i] = X11DRV_PALETTE_ToPhysical( dc, PALETTEINDEX(*index) );
159 } else {
160 for (i = start; i < end; i++)
161 colorMapping[i] = X11DRV_PALETTE_ToPhysical( dc, PALETTEINDEX(i) );
165 return colorMapping;
168 /***********************************************************************
169 * X11DRV_DIB_BuildColorMap
171 * Build the color map from the bitmap palette. Should not be called
172 * for a >8-bit deep bitmap.
174 int *X11DRV_DIB_BuildColorMap( DC *dc, WORD coloruse, WORD depth,
175 const BITMAPINFO *info, int *nColors )
177 int colors;
178 BOOL isInfo;
179 const void *colorPtr;
180 int *colorMapping;
182 if ((isInfo = (info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))))
184 colors = info->bmiHeader.biClrUsed;
185 if (!colors) colors = 1 << info->bmiHeader.biBitCount;
186 colorPtr = info->bmiColors;
188 else /* assume BITMAPCOREINFO */
190 colors = 1 << ((BITMAPCOREHEADER *)&info->bmiHeader)->bcBitCount;
191 colorPtr = (WORD *)((BITMAPCOREINFO *)info)->bmciColors;
194 if (colors > 256)
196 ERR("called with >256 colors!\n");
197 return NULL;
200 /* just so CopyDIBSection doesn't have to create an identity palette */
201 if (coloruse == (WORD)-1) colorPtr = NULL;
203 if (!(colorMapping = (int *)HeapAlloc(GetProcessHeap(), 0,
204 colors * sizeof(int) )))
205 return NULL;
207 *nColors = colors;
208 return X11DRV_DIB_GenColorMap( dc, colorMapping, coloruse, depth,
209 isInfo, colorPtr, 0, colors);
213 /***********************************************************************
214 * X11DRV_DIB_MapColor
216 int X11DRV_DIB_MapColor( int *physMap, int nPhysMap, int phys, int oldcol )
218 int color;
220 if ((oldcol < nPhysMap) && (physMap[oldcol] == phys))
221 return oldcol;
223 for (color = 0; color < nPhysMap; color++)
224 if (physMap[color] == phys)
225 return color;
227 WARN("Strange color %08x\n", phys);
228 return 0;
232 /*********************************************************************
233 * X11DRV_DIB_GetNearestIndex
235 * Helper for X11DRV_DIB_GetDIBits.
236 * Returns the nearest colour table index for a given RGB.
237 * Nearest is defined by minimizing the sum of the squares.
239 static INT X11DRV_DIB_GetNearestIndex(RGBQUAD *colormap, int numColors, BYTE r, BYTE g, BYTE b)
241 INT i, best = -1, diff, bestdiff = -1;
242 RGBQUAD *color;
244 for(color = colormap, i = 0; i < numColors; color++, i++) {
245 diff = (r - color->rgbRed) * (r - color->rgbRed) +
246 (g - color->rgbGreen) * (g - color->rgbGreen) +
247 (b - color->rgbBlue) * (b - color->rgbBlue);
248 if(diff == 0)
249 return i;
250 if(best == -1 || diff < bestdiff) {
251 best = i;
252 bestdiff = diff;
255 return best;
258 /***********************************************************************
259 * X11DRV_DIB_SetImageBits_1_Line
261 * Handles a single line of 1 bit data.
263 static void X11DRV_DIB_SetImageBits_1_Line(DWORD dstwidth, int left, int *colors,
264 XImage *bmpImage, int h, const BYTE *bits)
266 BYTE pix, extra;
267 DWORD i, x;
269 if((extra = (left & 7)) != 0) {
270 left &= ~7;
271 dstwidth += extra;
274 bits += left >> 3;
276 /* FIXME: should avoid putting x<left pixels (minor speed issue) */
277 for (i = dstwidth/8, x = left; i > 0; i--)
279 pix = *bits++;
280 XPutPixel( bmpImage, x++, h, colors[pix >> 7] );
281 XPutPixel( bmpImage, x++, h, colors[(pix >> 6) & 1] );
282 XPutPixel( bmpImage, x++, h, colors[(pix >> 5) & 1] );
283 XPutPixel( bmpImage, x++, h, colors[(pix >> 4) & 1] );
284 XPutPixel( bmpImage, x++, h, colors[(pix >> 3) & 1] );
285 XPutPixel( bmpImage, x++, h, colors[(pix >> 2) & 1] );
286 XPutPixel( bmpImage, x++, h, colors[(pix >> 1) & 1] );
287 XPutPixel( bmpImage, x++, h, colors[pix & 1] );
289 pix = *bits;
290 switch(dstwidth & 7)
292 case 7: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
293 case 6: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
294 case 5: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
295 case 4: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
296 case 3: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
297 case 2: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
298 case 1: XPutPixel( bmpImage, x++, h, colors[pix >> 7] );
302 /***********************************************************************
303 * X11DRV_DIB_SetImageBits_1
305 * SetDIBits for a 1-bit deep DIB.
307 static void X11DRV_DIB_SetImageBits_1( int lines, const BYTE *srcbits,
308 DWORD srcwidth, DWORD dstwidth, int left,
309 int *colors, XImage *bmpImage, DWORD linebytes)
311 int h;
313 if (lines > 0) {
314 for (h = lines-1; h >=0; h--) {
315 X11DRV_DIB_SetImageBits_1_Line(dstwidth, left, colors, bmpImage, h,
316 srcbits);
317 srcbits += linebytes;
319 } else {
320 lines = -lines;
321 for (h = 0; h < lines; h++) {
322 X11DRV_DIB_SetImageBits_1_Line(dstwidth, left, colors, bmpImage, h,
323 srcbits);
324 srcbits += linebytes;
329 /***********************************************************************
330 * X11DRV_DIB_GetImageBits_1
332 * GetDIBits for a 1-bit deep DIB.
334 static void X11DRV_DIB_GetImageBits_1( int lines, BYTE *dstbits,
335 DWORD dstwidth, DWORD srcwidth,
336 RGBQUAD *colors, PALETTEENTRY *srccolors,
337 XImage *bmpImage, DWORD linebytes )
339 DWORD x;
340 int h;
341 BYTE *bits;
343 if (lines < 0 ) {
344 lines = -lines;
345 dstbits = dstbits + linebytes * (lines - 1);
346 linebytes = -linebytes;
349 bits = dstbits;
351 switch(bmpImage->depth) {
353 case 1:
354 /* ==== monochrome bitmap to monochrome dib ==== */
355 case 4:
356 /* ==== 4 colormap bitmap to monochrome dib ==== */
357 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
359 PALETTEENTRY val;
361 for (h = lines - 1; h >= 0; h--) {
362 for (x = 0; x < dstwidth; x++) {
363 val = srccolors[XGetPixel(bmpImage, x, h)];
364 if (!(x&7)) *bits = 0;
365 *bits |= (X11DRV_DIB_GetNearestIndex(colors, 2,
366 val.peRed,
367 val.peGreen,
368 val.peBlue) << (7 - (x & 7)));
369 if ((x&7)==7) bits++;
371 bits = (dstbits += linebytes);
374 else goto notsupported;
376 break;
378 case 8:
379 /* ==== 8 colormap bitmap to monochrome dib ==== */
380 if ( bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
382 BYTE *srcpixel;
383 PALETTEENTRY val;
385 for( h = lines- 1; h >= 0; h-- ) {
386 srcpixel = bmpImage->data + (h*bmpImage->bytes_per_line);
387 for( x = 0; x < dstwidth; x++ ) {
388 if (!(x&7)) *bits = 0;
389 val = srccolors[(int)*srcpixel++];
390 *bits |= ( X11DRV_DIB_GetNearestIndex(colors, 2,
391 val.peRed,
392 val.peGreen,
393 val.peBlue) << (7-(x&7)) );
394 if ((x&7)==7) bits++;
396 bits = (dstbits += linebytes);
399 else goto notsupported;
401 break;
403 case 15:
405 LPWORD srcpixel;
406 WORD val;
408 /* ==== 555 BGR bitmap to monochrome dib ==== */
409 if (bmpImage->red_mask == 0x7c00 && bmpImage->blue_mask == 0x1f)
411 for( h = lines - 1; h >= 0; h--) {
412 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
413 for( x = 0; x < dstwidth; x++) {
414 if (!(x&7)) *bits = 0;
415 val = *srcpixel++;
416 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 2,
417 ((val >> 7) & 0xf8) |
418 ((val >> 12) & 0x7),
419 ((val >> 2) & 0xf8) |
420 ((val >> 7) & 0x3),
421 ((val << 3) & 0xf8) |
422 ((val >> 2) & 0x7) ) << (7-(x&7)) );
423 if ((x&7)==7) bits++;
425 bits = (dstbits += linebytes);
428 /* ==== 555 RGB bitmap to monochrome dib ==== */
429 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0xf800)
431 for( h = lines - 1; h >= 0; h--)
433 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
434 for( x = 0; x < dstwidth; x++) {
435 if (!(x&1)) *bits = 0;
436 val = *srcpixel++;
437 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 2,
438 ((val << 3) & 0xf8) |
439 ((val >> 2) & 0x7),
440 ((val >> 2) & 0xf8) |
441 ((val >> 7) & 0x3),
442 ((val >> 7) & 0xf8) |
443 ((val >> 12) & 0x7) ) << (7-(x&7)) );
444 if ((x&7)==7) bits++;
446 bits = (dstbits += linebytes);
449 else goto notsupported;
451 break;
453 case 16:
455 LPWORD srcpixel;
456 WORD val;
458 /* ==== 565 BGR bitmap to monochrome dib ==== */
459 if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f)
461 for( h = lines - 1; h >= 0; h--)
463 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
464 for( x = 0; x < dstwidth; x++) {
465 if (!(x&7)) *bits = 0;
466 val = *srcpixel++;
467 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 2,
468 ((val >> 8) & 0xf8) |
469 ((val >> 13) & 0x7),
470 ((val >> 3) & 0xfc) |
471 ((val >> 9) & 0x3),
472 ((val << 3) & 0xf8) |
473 ((val >> 2) & 0x7) ) << (7-(x&7)) );
474 if ((x&7)==7) bits++;
476 bits = (dstbits += linebytes);
479 /* ==== 565 RGB bitmap to monochrome dib ==== */
480 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0xf800)
482 for( h = lines - 1; h >= 0; h--)
484 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
485 for( x = 0; x < dstwidth; x++) {
486 if (!(x&7)) *bits = 0;
487 val = *srcpixel++;
488 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 2,
489 ((val << 3) & 0xf8) |
490 ((val >> 2) & 0x7),
491 ((val >> 3) & 0xfc) |
492 ((val >> 9) & 0x3),
493 ((val >> 8) & 0xf8) |
494 ((val >> 13) & 0x7) ) << (7-(x&7)) );
495 if ((x&7)==7) bits++;
497 bits = (dstbits += linebytes);
500 else goto notsupported;
502 break;
504 case 24:
505 case 32:
507 BYTE *srcpixel;
509 /* ==== 24/32 BGR bitmap to monochrome dib ==== */
510 if (bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff)
512 for (h = lines - 1; h >= 0; h--)
514 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
515 for (x = 0; x < dstwidth; x++, srcpixel+=4) {
516 if (!(x&7)) *bits = 0;
517 *bits |= (X11DRV_DIB_GetNearestIndex(colors, 2, srcpixel[2] , srcpixel[1], srcpixel[0]) << (7-(x&7)) );
518 if ((x&7)==7) bits++;
520 bits = (dstbits += linebytes);
523 /* ==== 24/32 RGB bitmap to monochrome dib ==== */
524 else if (bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000)
526 for (h = lines - 1; h >= 0; h--)
528 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
529 for (x = 0; x < dstwidth; x++, srcpixel+=4) {
530 if (!(x & 7)) *bits = 0;
531 *bits |= (X11DRV_DIB_GetNearestIndex(colors, 2, srcpixel[0] , srcpixel[1], srcpixel[2]) << (7-(x&7)) );
532 if ((x & 7) == 7) bits++;
534 bits = (dstbits += linebytes);
537 else goto notsupported;
539 break;
541 default: /* ? bit bmp -> monochrome DIB */
542 notsupported:
544 unsigned long white = (1 << bmpImage->bits_per_pixel) - 1;
546 FIXME("from %d bit bitmap with mask R,G,B %x,%x,%x to 1 bit DIB\n",
547 bmpImage->bits_per_pixel, (int)bmpImage->red_mask,
548 (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
550 for( h = lines - 1; h >= 0; h-- ) {
551 for( x = 0; x < dstwidth; x++ ) {
552 if (!(x&7)) *bits = 0;
553 *bits |= (XGetPixel( bmpImage, x, h) >= white)
554 << (7 - (x&7));
555 if ((x&7)==7) bits++;
557 bits = (dstbits += linebytes);
560 break;
564 /***********************************************************************
565 * X11DRV_DIB_SetImageBits_4
567 * SetDIBits for a 4-bit deep DIB.
569 static void X11DRV_DIB_SetImageBits_4( int lines, const BYTE *srcbits,
570 DWORD srcwidth, DWORD dstwidth, int left,
571 int *colors, XImage *bmpImage, DWORD linebytes)
573 DWORD i, x;
574 int h;
575 const BYTE *bits = srcbits + (left >> 1);
577 if(left & 1) {
578 left--;
579 dstwidth++;
582 if (lines > 0) {
583 for (h = lines-1; h >= 0; h--) {
584 for (i = dstwidth/2, x = left; i > 0; i--) {
585 BYTE pix = *bits++;
586 XPutPixel( bmpImage, x++, h, colors[pix >> 4] );
587 XPutPixel( bmpImage, x++, h, colors[pix & 0x0f] );
589 if (dstwidth & 1) XPutPixel( bmpImage, x, h, colors[*bits >> 4] );
590 srcbits += linebytes;
591 bits = srcbits + (left >> 1);
593 } else {
594 lines = -lines;
595 for (h = 0; h < lines; h++) {
596 for (i = dstwidth/2, x = left; i > 0; i--) {
597 BYTE pix = *bits++;
598 XPutPixel( bmpImage, x++, h, colors[pix >> 4] );
599 XPutPixel( bmpImage, x++, h, colors[pix & 0x0f] );
601 if (dstwidth & 1) XPutPixel( bmpImage, x, h, colors[*bits >> 4] );
602 srcbits += linebytes;
603 bits = srcbits + (left >> 1);
610 /***********************************************************************
611 * X11DRV_DIB_GetImageBits_4
613 * GetDIBits for a 4-bit deep DIB.
615 static void X11DRV_DIB_GetImageBits_4( int lines, BYTE *dstbits,
616 DWORD srcwidth, DWORD dstwidth,
617 RGBQUAD *colors, PALETTEENTRY *srccolors,
618 XImage *bmpImage, DWORD linebytes )
620 DWORD x;
621 int h;
622 BYTE *bits;
623 LPBYTE srcpixel;
625 if (lines < 0 )
627 lines = -lines;
628 dstbits = dstbits + ( linebytes * (lines-1) );
629 linebytes = -linebytes;
632 bits = dstbits;
634 switch(bmpImage->depth) {
636 case 1:
637 /* ==== monochrome bitmap to 4 colormap dib ==== */
638 case 4:
639 /* ==== 4 colormap bitmap to 4 colormap dib ==== */
640 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
642 PALETTEENTRY val;
644 for (h = lines-1; h >= 0; h--) {
645 for (x = 0; x < dstwidth; x++) {
646 if (!(x&1)) *bits = 0;
647 val = srccolors[XGetPixel(bmpImage, x, h)];
648 *bits |= (X11DRV_DIB_GetNearestIndex(colors, 16,
649 val.peRed,
650 val.peGreen,
651 val.peBlue) << (4-((x&1)<<2)));
652 if ((x&1)==1) bits++;
654 bits = (dstbits += linebytes);
657 else goto notsupported;
659 break;
661 case 8:
662 /* ==== 8 colormap bitmap to 4 colormap dib ==== */
663 if ( bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
665 PALETTEENTRY val;
667 for( h = lines - 1; h >= 0; h-- ) {
668 srcpixel = bmpImage->data + (h*bmpImage->bytes_per_line);
669 for( x = 0; x < dstwidth; x++ ) {
670 if (!(x&1)) *bits = 0;
671 val = srccolors[(int)*srcpixel++];
672 *bits |= ( X11DRV_DIB_GetNearestIndex(colors, 16,
673 val.peRed,
674 val.peGreen,
675 val.peBlue) << (4*(1-(x&1))) );
676 if ((x&1)==1) bits++;
678 bits = (dstbits += linebytes);
681 else goto notsupported;
683 break;
685 case 15:
687 LPWORD srcpixel;
688 WORD val;
690 /* ==== 555 BGR bitmap to 4 colormap dib ==== */
691 if (bmpImage->red_mask == 0x7c00 && bmpImage->blue_mask == 0x1f)
693 for( h = lines - 1; h >= 0; h--) {
694 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
695 for( x = 0; x < dstwidth; x++) {
696 if (!(x&1)) *bits = 0;
697 val = *srcpixel++;
698 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 16,
699 ((val >> 7) & 0xf8) |
700 ((val >> 12) & 0x7),
701 ((val >> 2) & 0xf8) |
702 ((val >> 7) & 0x3),
703 ((val << 3) & 0xf8) |
704 ((val >> 2) & 0x7) ) << ((1-(x&1))<<2) );
705 if ((x&1)==1) bits++;
707 bits = (dstbits += linebytes);
710 /* ==== 555 RGB bitmap to 4 colormap dib ==== */
711 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0x7c00)
713 for( h = lines - 1; h >= 0; h--)
715 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
716 for( x = 0; x < dstwidth; x++) {
717 if (!(x&1)) *bits = 0;
718 val = *srcpixel++;
719 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 16,
720 ((val << 3) & 0xf8) |
721 ((val >> 2) & 0x7),
722 ((val >> 2) & 0xfc) |
723 ((val >> 7) & 0x3),
724 ((val >> 7) & 0xf8) |
725 ((val >> 12) & 0x7) ) << ((1-(x&1))<<2) );
726 if ((x&1)==1) bits++;
728 bits = (dstbits += linebytes);
731 else goto notsupported;
733 break;
735 case 16:
737 LPWORD srcpixel;
738 WORD val;
740 /* ==== 565 BGR bitmap to 4 colormap dib ==== */
741 if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f)
743 for( h = lines - 1; h >= 0; h--)
745 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
746 for( x = 0; x < dstwidth; x++) {
747 if (!(x&1)) *bits = 0;
748 val = *srcpixel++;
749 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 16,
750 ((val >> 8) & 0xf8) |
751 ((val >> 13) & 0x7),
752 ((val >> 3) & 0xfc) |
753 ((val >> 9) & 0x3),
754 ((val << 3) & 0xf8) |
755 ((val >> 2) & 0x7) ) << ((1-(x&1))<<2) );
756 if ((x&1)==1) bits++;
758 bits = (dstbits += linebytes);
761 /* ==== 565 RGB bitmap to 4 colormap dib ==== */
762 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0xf800)
764 for( h = lines - 1; h >= 0; h--)
766 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
767 for( x = 0; x < dstwidth; x++) {
768 if (!(x&1)) *bits = 0;
769 val = *srcpixel++;
770 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 16,
771 ((val << 3) & 0xf8) |
772 ((val >> 2) & 0x7),
773 ((val >> 3) & 0xfc) |
774 ((val >> 9) & 0x3),
775 ((val >> 8) & 0xf8) |
776 ((val >> 13) & 0x7) ) << ((1-(x&1))<<2) );
777 if ((x&1)==1) bits++;
779 bits = (dstbits += linebytes);
782 else goto notsupported;
784 break;
786 case 24:
787 case 32:
789 BYTE *srcpixel;
791 /* ==== 24/32 BGR bitmap to 4 colormap dib ==== */
792 if (bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff)
794 for (h = lines - 1; h >= 0; h--)
796 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
797 for (x = 0; x < dstwidth; x+=2, srcpixel+=8) /* 2 pixels at a time */
798 *bits++ = (X11DRV_DIB_GetNearestIndex(colors, 16, srcpixel[2] , srcpixel[1], srcpixel[0]) << 4) |
799 X11DRV_DIB_GetNearestIndex(colors, 16, srcpixel[6] , srcpixel[5], srcpixel[4]);
800 bits = (dstbits += linebytes);
803 /* ==== 24/32 RGB bitmap to 4 colormap dib ==== */
804 else if (bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000)
806 for (h = lines - 1; h >= 0; h--)
808 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
809 for (x = 0; x < dstwidth; x+=2, srcpixel+=8) /* 2 pixels at a time */
810 *bits++ = (X11DRV_DIB_GetNearestIndex(colors, 16, srcpixel[0] , srcpixel[1], srcpixel[2]) << 4) |
811 X11DRV_DIB_GetNearestIndex(colors, 16, srcpixel[4] , srcpixel[5], srcpixel[6]);
812 bits = (dstbits += linebytes);
815 else goto notsupported;
817 break;
819 default: /* ? bit bmp -> 4 bit DIB */
820 notsupported:
821 FIXME("from %d bit bitmap with mask R,G,B %x,%x,%x to 4 bit DIB\n",
822 bmpImage->bits_per_pixel, (int)bmpImage->red_mask,
823 (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
824 for (h = lines-1; h >= 0; h--) {
825 for (x = 0; x < dstwidth-1; x += 2)
827 *bits++ = (X11DRV_DIB_MapColor((int *)colors, 16, XGetPixel( bmpImage, x, h ), 0) << 4)
828 | (X11DRV_DIB_MapColor((int *)colors, 16, XGetPixel( bmpImage, x+1, h ), 0) & 0x0f);
830 if (dstwidth & 1)
831 *bits = (X11DRV_DIB_MapColor((int *)colors, 16, XGetPixel( bmpImage, x, h ), 0) << 4);
832 bits = (dstbits += linebytes);
834 break;
838 /***********************************************************************
839 * X11DRV_DIB_SetImageBits_RLE4
841 * SetDIBits for a 4-bit deep compressed DIB.
843 static void X11DRV_DIB_SetImageBits_RLE4( int lines, const BYTE *bits,
844 DWORD width, DWORD dstwidth,
845 int left, int *colors,
846 XImage *bmpImage )
848 int x = 0, c, length;
849 const BYTE *begin = bits;
851 lines--;
853 while ((int)lines >= 0) {
854 length = *bits++;
855 if (length) { /* encoded */
856 c = *bits++;
857 while (length--) {
858 if(x >= width) {
859 x = 0;
860 if(--lines < 0)
861 return;
863 XPutPixel(bmpImage, x++, lines, colors[c >>4]);
864 if (length) {
865 length--;
866 if(x >= width) {
867 x = 0;
868 if(--lines < 0)
869 return;
871 XPutPixel(bmpImage, x++, lines, colors[c & 0xf]);
874 } else {
875 length = *bits++;
876 switch (length) {
877 case 0: /* eol */
878 x = 0;
879 lines--;
880 continue;
882 case 1: /* eopicture */
883 return;
885 case 2: /* delta */
886 x += *bits++;
887 if(x >= width) {
888 FIXME_(x11drv)("x-delta is too large?\n");
889 return;
891 lines -= *bits++;
892 continue;
894 default: /* absolute */
895 while (length--) {
896 c = *bits++;
897 if(x >= width) {
898 x = 0;
899 if(--lines < 0)
900 return;
902 XPutPixel(bmpImage, x++, lines, colors[c >> 4]);
903 if (length) {
904 length--;
905 if(x >= width) {
906 x = 0;
907 if(--lines < 0)
908 return;
910 XPutPixel(bmpImage, x++, lines, colors[c & 0xf]);
913 if ((bits - begin) & 1)
914 bits++;
922 /***********************************************************************
923 * X11DRV_DIB_SetImageBits_8
925 * SetDIBits for an 8-bit deep DIB.
927 static void X11DRV_DIB_SetImageBits_8( int lines, const BYTE *srcbits,
928 DWORD srcwidth, DWORD dstwidth, int left,
929 const int *colors, XImage *bmpImage,
930 DWORD linebytes )
932 DWORD x;
933 int h, color;
934 const BYTE *bits;
936 dstwidth += left;
938 if (lines < 0 )
940 lines = -lines;
941 srcbits = srcbits + ( linebytes * (lines-1) );
942 linebytes = -linebytes;
945 bits = srcbits + left;
947 switch (bmpImage->depth) {
948 case 15:
949 case 16:
950 #if defined(__i386__) && defined(__GNUC__)
951 /* Some X servers might have 32 bit/ 16bit deep pixel */
952 if (lines && (dstwidth!=left) && (bmpImage->bits_per_pixel == 16))
954 for (h = lines ; h--; ) {
955 int _cl1,_cl2; /* temp outputs for asm below */
956 /* Borrowed from DirectDraw */
957 __asm__ __volatile__(
958 "xor %%eax,%%eax\n"
959 "cld\n"
960 "1:\n"
961 " lodsb\n"
962 " movw (%%edx,%%eax,4),%%ax\n"
963 " stosw\n"
964 " xor %%eax,%%eax\n"
965 " loop 1b\n"
966 :"=S" (bits), "=D" (_cl1), "=c" (_cl2)
967 :"S" (bits),
968 "D" (bmpImage->data+h*bmpImage->bytes_per_line+left*2),
969 "c" (dstwidth-left),
970 "d" (colors)
971 :"eax", "cc", "memory"
973 bits = (srcbits += linebytes) + left;
975 return;
977 break;
978 #endif
979 case 24:
980 #if defined(__i386__) && defined(__GNUC__)
981 if (lines && (dstwidth!=left) && (bmpImage->bits_per_pixel == 32))
983 for (h = lines ; h--; ) {
984 int _cl1,_cl2; /* temp outputs for asm below */
985 /* Borrowed from DirectDraw */
986 __asm__ __volatile__(
987 "xor %%eax,%%eax\n"
988 "cld\n"
989 "1:\n"
990 " lodsb\n"
991 " movl (%%edx,%%eax,4),%%eax\n"
992 " stosl\n"
993 " xor %%eax,%%eax\n"
994 " loop 1b\n"
995 :"=S" (bits), "=D" (_cl1), "=c" (_cl2)
996 :"S" (bits),
997 "D" (bmpImage->data+h*bmpImage->bytes_per_line+left*4),
998 "c" (dstwidth-left),
999 "d" (colors)
1000 :"eax", "cc", "memory"
1002 bits = (srcbits += linebytes) + left;
1004 return;
1006 break;
1007 #endif
1008 default:
1009 break; /* use slow generic case below */
1012 for (h = lines - 1; h >= 0; h--) {
1013 for (x = left; x < dstwidth; x++, bits++) {
1014 color = colors[*bits];
1015 XPutPixel( bmpImage, x, h, colors[*bits] );
1017 bits = (srcbits += linebytes) + left;
1021 /***********************************************************************
1022 * X11DRV_DIB_GetImageBits_8
1024 * GetDIBits for an 8-bit deep DIB.
1026 static void X11DRV_DIB_GetImageBits_8( int lines, BYTE *dstbits,
1027 DWORD srcwidth, DWORD dstwidth,
1028 RGBQUAD *colors, PALETTEENTRY *srccolors,
1029 XImage *bmpImage, DWORD linebytes )
1031 DWORD x;
1032 int h;
1033 BYTE *bits;
1035 if (lines < 0 )
1037 lines = -lines;
1038 dstbits = dstbits + ( linebytes * (lines-1) );
1039 linebytes = -linebytes;
1042 bits = dstbits;
1045 Hack for now
1046 This condition is true when GetImageBits has been called by UpdateDIBSection.
1047 For now, GetNearestIndex is too slow to support 256 colormaps, so we'll just use for
1048 for GetDIBits calls. (In somes cases, in a updateDIBSection, the returned colors are bad too)
1050 if (!srccolors) goto updatesection;
1052 switch(bmpImage->depth) {
1054 case 1:
1055 /* ==== monochrome bitmap to 8 colormap dib ==== */
1056 case 4:
1057 /* ==== 4 colormap bitmap to 8 colormap dib ==== */
1058 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
1060 PALETTEENTRY val;
1062 for (h = lines - 1; h >= 0; h--) {
1063 for (x = 0; x < dstwidth; x++) {
1064 val = srccolors[XGetPixel(bmpImage, x, h)];
1065 *bits++ = X11DRV_DIB_GetNearestIndex(colors, 256, val.peRed,
1066 val.peGreen, val.peBlue);
1068 bits = (dstbits += linebytes);
1071 else goto notsupported;
1073 break;
1075 case 8:
1076 /* ==== 8 colormap bitmap to 8 colormap dib ==== */
1077 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
1079 BYTE *srcpixel;
1080 PALETTEENTRY val;
1082 for (h = lines - 1; h >= 0; h--) {
1083 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
1084 for (x = 0; x < dstwidth; x++) {
1085 val = srccolors[(int)*srcpixel++];
1086 *bits++ = X11DRV_DIB_GetNearestIndex(colors, 256, val.peRed,
1087 val.peGreen, val.peBlue);
1089 bits = (dstbits += linebytes);
1092 else goto notsupported;
1094 break;
1096 case 15:
1098 LPWORD srcpixel;
1099 WORD val;
1101 /* ==== 555 BGR bitmap to 8 colormap dib ==== */
1102 if (bmpImage->red_mask == 0x7c00 && bmpImage->blue_mask == 0x001f)
1104 for( h = lines - 1; h >= 0; h--)
1106 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
1107 for( x = 0; x < dstwidth; x++ )
1109 val = *srcpixel++;
1110 *bits++ = X11DRV_DIB_GetNearestIndex( colors, 256,
1111 ((val >> 7) & 0xf8) |
1112 ((val >> 12) & 0x7),
1113 ((val >> 2) & 0xf8) |
1114 ((val >> 7) & 0x3),
1115 ((val << 3) & 0xf8) |
1116 ((val >> 2) & 0x7) );
1118 bits = (dstbits += linebytes);
1121 /* ==== 555 RGB bitmap to 8 colormap dib ==== */
1122 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0x7c00)
1124 for( h = lines - 1; h >= 0; h--)
1126 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
1127 for( x = 0; x < dstwidth; x++ )
1129 val = *srcpixel++;
1130 *bits++ = X11DRV_DIB_GetNearestIndex( colors, 256,
1131 ((val << 3) & 0xf8) |
1132 ((val >> 2) & 0x7),
1133 ((val >> 2) & 0xf8) |
1134 ((val >> 7) & 0x3),
1135 ((val >> 7) & 0xf8) |
1136 ((val >> 12) & 0x7) );
1138 bits = (dstbits += linebytes);
1141 else goto notsupported;
1143 break;
1145 case 16:
1147 LPWORD srcpixel;
1148 WORD val;
1150 /* ==== 565 BGR bitmap to 8 colormap dib ==== */
1151 if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f)
1153 for( h = lines - 1; h >= 0; h--)
1155 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
1156 for( x = 0; x < dstwidth; x++ )
1158 val = *srcpixel++;
1159 *bits++ = X11DRV_DIB_GetNearestIndex( colors, 256,
1160 ((val >> 8) & 0xf8) |
1161 ((val >> 13) & 0x7),
1162 ((val >> 3) & 0xfc) |
1163 ((val >> 9) & 0x3),
1164 ((val << 3) & 0xf8) |
1165 ((val >> 2) & 0x7) );
1167 bits = (dstbits += linebytes);
1170 /* ==== 565 RGB bitmap to 8 colormap dib ==== */
1171 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0xf800)
1173 for( h = lines - 1; h >= 0; h--)
1175 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
1176 for( x = 0; x < dstwidth; x++ )
1178 val = *srcpixel++;
1179 *bits++ = X11DRV_DIB_GetNearestIndex( colors, 256,
1180 ((val << 3) & 0xf8) |
1181 ((val >> 2) & 0x7),
1182 ((val >> 3) & 0x00fc) |
1183 ((val >> 9) & 0x3),
1184 ((val >> 8) & 0x00f8) |
1185 ((val >> 13) & 0x7) );
1187 bits = (dstbits += linebytes);
1190 else goto notsupported;
1192 break;
1194 case 24:
1195 case 32:
1197 BYTE *srcpixel;
1199 /* ==== 24/32 BGR bitmap to 8 colormap dib ==== */
1200 if (bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff)
1202 for (h = lines - 1; h >= 0; h--)
1204 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
1205 for (x = 0; x < dstwidth; x++, srcpixel+=4)
1206 *bits++ = X11DRV_DIB_GetNearestIndex(colors, 256,
1207 srcpixel[2] , srcpixel[1], *srcpixel);
1208 bits = (dstbits += linebytes);
1211 /* ==== 24/32 RGB bitmap to 8 colormap dib ==== */
1212 else if (bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000)
1214 for (h = lines - 1; h >= 0; h--)
1216 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
1217 for (x = 0; x < dstwidth; x++, srcpixel+=4)
1218 *bits++ = X11DRV_DIB_GetNearestIndex(colors, 256,
1219 *srcpixel, srcpixel[1], srcpixel[2]);
1220 bits = (dstbits += linebytes);
1224 else goto notsupported;
1226 break;
1228 default: /* ? bit bmp -> 8 bit DIB */
1229 notsupported:
1230 FIXME("from %d bit bitmap with mask R,G,B %x,%x,%x to 8 bit DIB\n",
1231 bmpImage->depth, (int)bmpImage->red_mask,
1232 (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
1233 updatesection:
1234 for (h = lines - 1; h >= 0; h--) {
1235 for (x = 0; x < dstwidth; x++, bits++) {
1236 *bits = X11DRV_DIB_MapColor((int *)colors, 256,
1237 XGetPixel( bmpImage, x, h ), *bits);
1239 bits = (dstbits += linebytes);
1241 break;
1245 /***********************************************************************
1246 * X11DRV_DIB_SetImageBits_RLE8
1248 * SetDIBits for an 8-bit deep compressed DIB.
1250 * This function rewritten 941113 by James Youngman. WINE blew out when I
1251 * first ran it because my desktop wallpaper is a (large) RLE8 bitmap.
1253 * This was because the algorithm assumed that all RLE8 bitmaps end with the
1254 * 'End of bitmap' escape code. This code is very much laxer in what it
1255 * allows to end the expansion. Possibly too lax. See the note by
1256 * case RleDelta. BTW, MS's documentation implies that a correct RLE8
1257 * bitmap should end with RleEnd, but on the other hand, software exists
1258 * that produces ones that don't and Windows 3.1 doesn't complain a bit
1259 * about it.
1261 * (No) apologies for my English spelling. [Emacs users: c-indent-level=4].
1262 * James A. Youngman <mbcstjy@afs.man.ac.uk>
1263 * [JAY]
1266 enum Rle8_EscapeCodes
1269 * Apologies for polluting your file's namespace...
1271 RleEol = 0, /* End of line */
1272 RleEnd = 1, /* End of bitmap */
1273 RleDelta = 2 /* Delta */
1276 static void X11DRV_DIB_SetImageBits_RLE8( int lines, const BYTE *bits,
1277 DWORD width, DWORD dstwidth,
1278 int left, int *colors,
1279 XImage *bmpImage )
1281 int x; /* X-positon on each line. Increases. */
1282 int line; /* Line #. Starts at lines-1, decreases */
1283 const BYTE *pIn = bits; /* Pointer to current position in bits */
1284 BYTE length; /* The length pf a run */
1285 BYTE color_index; /* index into colors[] as read from bits */
1286 BYTE escape_code; /* See enum Rle8_EscapeCodes.*/
1287 int color; /* value of colour[color_index] */
1289 if (lines == 0) /* Let's hope this doesn't happen. */
1290 return;
1293 * Note that the bitmap data is stored by Windows starting at the
1294 * bottom line of the bitmap and going upwards. Within each line,
1295 * the data is stored left-to-right. That's the reason why line
1296 * goes from lines-1 to 0. [JAY]
1299 x = 0;
1300 line = lines-1;
1303 length = *pIn++;
1306 * If the length byte is not zero (which is the escape value),
1307 * We have a run of length pixels all the same colour. The colour
1308 * index is stored next.
1310 * If the length byte is zero, we need to read the next byte to
1311 * know what to do. [JAY]
1313 if (length != 0)
1316 * [Run-Length] Encoded mode
1318 color_index = (*pIn++); /* Get the colour index. */
1319 color = colors[color_index];
1321 while(length--)
1323 if (x>=dstwidth)
1325 x=0;
1326 line--;
1328 XPutPixel(bmpImage, x++, line, color);
1331 else
1334 * Escape codes (may be an absolute sequence though)
1336 escape_code = (*pIn++);
1337 switch(escape_code)
1339 case RleEol: /* =0, end of line */
1341 x = 0;
1342 line--;
1343 break;
1346 case RleEnd: /* =1, end of bitmap */
1349 * Not all RLE8 bitmaps end with this
1350 * code. For example, Paint Shop Pro
1351 * produces some that don't. That's (I think)
1352 * what caused the previous implementation to
1353 * fail. [JAY]
1355 line=-1; /* Cause exit from do loop. */
1356 break;
1359 case RleDelta: /* =2, a delta */
1362 * Note that deltaing to line 0
1363 * will cause an exit from the loop,
1364 * which may not be what is intended.
1365 * The fact that there is a delta in the bits
1366 * almost certainly implies that there is data
1367 * to follow. You may feel that we should
1368 * jump to the top of the loop to avoid exiting
1369 * in this case.
1371 * TODO: Decide what to do here in that case. [JAY]
1373 x += (*pIn++);
1374 line -= (*pIn++);
1375 if (line == 0)
1377 TRACE("Delta to last line of bitmap "
1378 "(wrongly?) causes loop exit\n");
1380 break;
1383 default: /* >2, switch to absolute mode */
1386 * Absolute Mode
1388 length = escape_code;
1389 while(length--)
1391 color_index = (*pIn++);
1392 if (x>=dstwidth)
1394 x=0;
1395 line--;
1397 XPutPixel(bmpImage, x++, line,
1398 colors[color_index]);
1402 * If you think for a moment you'll realise that the
1403 * only time we could ever possibly read an odd
1404 * number of bytes is when there is a 0x00 (escape),
1405 * a value >0x02 (absolute mode) and then an odd-
1406 * length run. Therefore this is the only place we
1407 * need to worry about it. Everywhere else the
1408 * bytes are always read in pairs. [JAY]
1410 if (escape_code & 1)
1411 pIn++; /* Throw away the pad byte. */
1412 break;
1414 } /* switch (escape_code) : Escape sequence */
1415 } /* process either an encoded sequence or an escape sequence */
1417 /* We expect to come here more than once per line. */
1418 } while (line >= 0); /* Do this until the bitmap is filled */
1421 * Everybody comes here at the end.
1422 * Check how we exited the loop and print a message if it's a bit odd.
1423 * [JAY]
1425 if ( (*(pIn-2) != 0/*escape*/) || (*(pIn-1)!= RleEnd) )
1427 TRACE("End-of-bitmap without (strictly) proper escape code. Last two "
1428 "bytes were: %02X %02X.\n", (int)*(pIn-2),(int)*(pIn-1));
1433 /***********************************************************************
1434 * X11DRV_DIB_SetImageBits_16
1436 * SetDIBits for a 16-bit deep DIB.
1438 static void X11DRV_DIB_SetImageBits_16( int lines, const BYTE *srcbits,
1439 DWORD srcwidth, DWORD dstwidth, int left,
1440 DC *dc, DWORD rSrc, DWORD gSrc, DWORD bSrc,
1441 XImage *bmpImage, DWORD linebytes )
1443 DWORD x;
1444 int h;
1446 if (lines < 0 )
1448 lines = -lines;
1449 srcbits = srcbits + ( linebytes * (lines-1));
1450 linebytes = -linebytes;
1453 switch ( bmpImage->depth )
1455 case 15:
1456 /* using same format as XImage */
1457 if (rSrc == bmpImage->red_mask && gSrc == bmpImage->green_mask && bSrc == bmpImage->blue_mask)
1458 for (h = lines - 1; h >= 0; h--, srcbits += linebytes)
1459 memcpy ( bmpImage->data + h * bmpImage->bytes_per_line + left*2, srcbits + left*2, dstwidth*2 );
1460 else /* We need to do a conversion from a 565 dib */
1462 LPDWORD dstpixel, ptr = (LPDWORD)(srcbits + left*2);
1463 DWORD val;
1464 int div = dstwidth % 2;
1466 for (h = lines - 1; h >= 0; h--) {
1467 dstpixel = (LPDWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1468 for (x = 0; x < dstwidth/2; x++) { /* Do 2 pixels at a time */
1469 val = *ptr++;
1470 *dstpixel++ = ((val >> 1) & 0x7fe07fe0) | (val & 0x001f001f); /* Red & Green & Blue */
1472 if (div != 0) /* Odd width? */
1473 *dstpixel = ((*(WORD *)ptr >> 1) & 0x7fe0) | (*(WORD *)ptr & 0x001f);
1474 ptr = (LPDWORD) ((srcbits += linebytes) + left*2);
1477 break;
1479 case 16:
1480 /* using same format as XImage */
1481 if (rSrc == bmpImage->red_mask && gSrc == bmpImage->green_mask && bSrc == bmpImage->blue_mask)
1482 for (h = lines - 1; h >= 0; h--, srcbits += linebytes)
1483 memcpy ( bmpImage->data + h * bmpImage->bytes_per_line + left*2, srcbits + left*2, dstwidth*2 );
1484 else /* We need to do a conversion from a 555 dib */
1486 LPDWORD dstpixel, ptr = (LPDWORD)(srcbits + left*2);
1487 DWORD val;
1488 int div = dstwidth % 2;
1490 for (h = lines - 1; h >= 0; h--) {
1491 dstpixel = (LPDWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1492 for (x = 0; x < dstwidth/2; x++) { /* Do 2 pixels at a time */
1493 val = *ptr++;
1494 *dstpixel++ = ((val << 1) & 0xffc0ffc0) | ((val >> 4) & 0x00200020) | /* Red & Green */
1495 (val & 0x001f001f); /* Blue */
1497 if (div != 0) /* Odd width? */
1498 *dstpixel = ((*(WORD *)ptr << 1) & 0xffc0) | ((*(WORD *)ptr >> 4) & 0x0020)
1499 | (*(WORD *)ptr & 0x001f);
1500 ptr = (LPDWORD) ((srcbits += linebytes) + left*2);
1503 break;
1505 case 24:
1506 case 32:
1508 DWORD *dstpixel;
1509 LPWORD ptr = (LPWORD)srcbits + left;
1510 DWORD val;
1512 if (bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff)
1514 if ((rSrc == 0xF800) && (gSrc == 0x07E0) && (bSrc == 0x001F)) {
1515 /* ==== 555 RGB dib to 24/32 RGB bitmap ==== */
1516 for (h = lines - 1; h >= 0; h--) {
1517 dstpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line + left*4);
1518 for (x = 0; x < dstwidth; x++) {
1519 val = *ptr++;
1520 *dstpixel++ = ((val << 8) & 0xF80000) | /* Red */
1521 ((val << 5) & 0x00FC00) | /* Green */
1522 ((val << 3) & 0x0000FF); /* Blue */
1524 ptr = (LPWORD)(srcbits += linebytes) + left;
1526 } else {
1527 /* ==== 555 BGR dib to 24/32 BGR bitmap ==== */
1528 for (h = lines - 1; h >= 0; h--) {
1529 dstpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line + left*4);
1530 for (x = 0; x < dstwidth; x++) {
1532 val = *ptr++;
1533 *dstpixel++ = ((val << 9) & 0xf80000) | ((val << 4) & 0x070000) | /* Red */
1534 ((val << 6) & 0x00f800) | ((val << 1) & 0x000700) | /* Green */
1535 ((val << 3) & 0x0000f8) | ((val >> 2) & 0x000007); /* Blue */
1537 ptr = (LPWORD)(srcbits += linebytes) + left;
1541 /* ==== 555 BGR dib to 24/32 RGB bitmap ==== */
1542 else if (bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000)
1544 for (h = lines - 1; h >= 0; h--) {
1545 dstpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line + left*4);
1546 for (x = 0; x < dstwidth; x++) {
1548 val = *ptr++;
1549 *dstpixel++ = ((val >> 7) & 0x0000f8) | ((val >> 12) & 0x000007) | /* Red */
1550 ((val << 6) & 0x00f800) | ((val << 1) & 0x000700) | /* Green */
1551 ((val << 19) & 0xf80000) | ((val >> 14) & 0x070000); /* Blue */
1553 ptr = (LPWORD)(srcbits += linebytes) + left;
1558 break;
1560 case 1:
1561 case 4:
1562 case 8:
1564 LPWORD ptr = (LPWORD)srcbits + left;
1565 WORD val;
1566 int sc1, sc2;
1568 /* Set color scaling values */
1569 if ( rSrc == 0x7c00 ) { sc1 = 7; sc2 = 2; } /* 555 dib */
1570 else { sc1 = 8; sc2 = 3; } /* 565 dib */
1572 for (h = lines - 1; h >= 0; h--) {
1573 for (x = left; x < dstwidth+left; x++) {
1574 val = *ptr++;
1575 XPutPixel( bmpImage, x, h,
1576 X11DRV_PALETTE_ToPhysical(dc, RGB(((val & rSrc) >> sc1), /* Red */
1577 ((val & gSrc) >> sc2), /* Green */
1578 ((val & bSrc) << 3)))); /* Blue */
1580 ptr = (LPWORD) (srcbits += linebytes) + left;
1583 break;
1585 default:
1586 FIXME("16 bit DIB %d bit bitmap\n", bmpImage->bits_per_pixel);
1587 break;
1593 /***********************************************************************
1594 * X11DRV_DIB_GetImageBits_16
1596 * GetDIBits for an 16-bit deep DIB.
1598 static void X11DRV_DIB_GetImageBits_16( int lines, BYTE *dstbits,
1599 DWORD dstwidth, DWORD srcwidth,
1600 PALETTEENTRY *srccolors,
1601 DWORD rDst, DWORD gDst, DWORD bDst,
1602 XImage *bmpImage, DWORD dibpitch )
1604 DWORD x;
1605 int h, rsc, gsc;
1607 DWORD linebytes = dibpitch;
1609 if (lines < 0 )
1611 lines = -lines;
1612 dstbits = dstbits + ( linebytes * (lines-1));
1613 linebytes = -linebytes;
1616 /* Set color scaling values */
1617 if ( rDst == 0x7c00 ) { rsc = 7; gsc = 2; } /* 555 dib */
1618 else { rsc = 8; gsc = 3; } /* 565 dib */
1620 switch ( bmpImage->depth )
1622 case 15:
1623 /* using same format as XImage */
1624 if (rDst == bmpImage->red_mask && bDst == bmpImage->blue_mask)
1625 for (h = lines - 1; h >= 0; h--, dstbits += linebytes)
1626 memcpy( dstbits, bmpImage->data + h*bmpImage->bytes_per_line, srcwidth*2 );
1627 /* reversed format (BGR <=> RGB) */
1628 else if (rDst == bmpImage->blue_mask && bDst == bmpImage->red_mask)
1630 LPDWORD srcpixel, ptr = (LPDWORD)dstbits;
1631 DWORD val;
1632 int div = srcwidth % 2;
1634 for (h = lines - 1; h >= 0; h--) {
1635 srcpixel = (LPDWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
1636 for (x = 0; x < srcwidth/2; x++) { /* Do 2 pixels at a time */
1637 val = *srcpixel++;
1638 *ptr++ = ((val << 10) & 0xf800f800) | (val & 0x03e003e0) | /* Red & Green */
1639 ((val >> 10) & 0x001f001f); /* Blue */
1641 if (div != 0) /* Odd width? */
1642 *ptr = ((*(WORD *)srcpixel << 1) & 0xffc0) | ((*(WORD *)srcpixel >> 4) & 0x0020) |
1643 (*(WORD *)srcpixel & 0x001f);
1644 ptr = (LPDWORD)(dstbits += linebytes);
1647 else goto notsupported;
1649 break;
1651 case 16:
1653 LPDWORD srcpixel, ptr = (LPDWORD)dstbits;
1654 DWORD val;
1655 int div = srcwidth % 2;
1657 /* using same format as XImage */
1658 if (rDst == bmpImage->red_mask && bDst == bmpImage->blue_mask)
1659 for (h = lines - 1; h >= 0; h--, dstbits += linebytes)
1660 memcpy( dstbits, bmpImage->data + h*bmpImage->bytes_per_line, srcwidth*2 );
1661 /* ==== 565 BGR bitmap to 555 BGR dib ==== */
1662 else if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f &&
1663 rDst == 0x7c00 && bDst == 0x001f)
1665 for (h = lines - 1; h >= 0; h--) {
1666 srcpixel = (LPDWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
1667 for (x = 0; x < srcwidth/2; x++) { /* Do 2 pixels at a time */
1668 val = *srcpixel++;
1669 *ptr++ = ((val >> 1) & 0x7fe07fe0) | /* Red & Green */
1670 (val & 0x001f001f); /* Blue */
1672 if (div != 0) /* Odd width? */
1673 *ptr = ((*(WORD *)srcpixel >> 1) & 0x7fe0) | (*(WORD *)srcpixel & 0x001f);
1674 ptr = (LPDWORD) (dstbits += linebytes);
1677 /* ==== 565 RGB bitmap to 555 BGR dib ==== */
1678 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0xf800 &&
1679 rDst == 0x7c00 && bDst == 0x001f)
1681 for (h = lines - 1; h >= 0; h--) {
1682 srcpixel = (LPDWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
1683 for (x = 0; x < srcwidth/2; x++) { /* Do 2 pixels at a time */
1684 val = *srcpixel++;
1685 *ptr++ = ((val << 10) & 0x7c007c00) | ((val >> 1) & 0x03e003e0) | /* Red & Green */
1686 ((val >> 11) & 0x001f001f); /* Blue */
1688 if (div != 0) /* Odd width? */
1689 *ptr = ((*(WORD *)srcpixel >> 1) & 0x7fe0) | (*(WORD *)srcpixel & 0x001f);
1690 ptr = (LPDWORD) (dstbits += linebytes);
1693 else goto notsupported;
1695 break;
1697 case 24:
1698 case 32:
1700 DWORD *srcpixel;
1701 LPWORD ptr = (LPWORD)dstbits;
1702 DWORD val;
1704 /* ==== 24/32 BGR bitmap ==== */
1705 if (bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff)
1707 int rsc2 = 16-rsc, gsc2 = 8-gsc;
1708 for (h = lines - 1; h >= 0; h--) {
1709 srcpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line);
1710 for (x = 0; x < srcwidth; x++, ptr++) {
1711 val = *srcpixel++;
1712 *ptr = ((val >> rsc2) & rDst) |
1713 ((val >> gsc2) & gDst) |
1714 ((val >> 3) & bDst);
1716 ptr = (LPWORD)(dstbits += linebytes);
1719 /* ==== 24/32 RGB bitmap ==== */
1720 else if (bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000)
1722 int gsc2 = 8-gsc;
1723 for (h = lines - 1; h >= 0; h--) {
1724 srcpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line);
1725 for (x = 0; x < srcwidth; x++, ptr++) {
1726 val = *srcpixel++;
1727 *ptr = ((val << rsc) & rDst) |
1728 ((val >> gsc2) & gDst) |
1729 ((val >> 19) & bDst);
1731 ptr = (LPWORD) (dstbits += linebytes);
1734 else goto notsupported;
1736 break;
1738 case 1:
1739 /* ==== monochrome bitmap ==== */
1740 case 4:
1741 /* ==== 4 colormap bitmap ==== */
1742 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
1744 LPWORD ptr = (LPWORD)dstbits;
1745 PALETTEENTRY val;
1747 for (h = lines - 1; h >= 0; h--) {
1748 for (x = 0; x < dstwidth; x++) {
1749 val = srccolors[XGetPixel(bmpImage, x, h)];
1750 *ptr++ = ((val.peRed << rsc) & rDst) |
1751 ((val.peGreen << gsc) & gDst) |
1752 ((val.peBlue >> 3) & bDst);
1754 ptr = (LPWORD)(dstbits += linebytes);
1757 else goto notsupported;
1759 break;
1761 case 8:
1762 /* ==== 8 colormap bitmap ==== */
1763 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
1765 LPWORD ptr = (LPWORD)dstbits;
1766 BYTE *srcpixel;
1767 PALETTEENTRY val;
1769 for (h = lines - 1; h >= 0; h--) {
1770 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
1771 for (x = 0; x < dstwidth; x++) {
1772 val = srccolors[(int)*srcpixel++];
1773 *ptr++ = ((val.peRed << rsc) & rDst) |
1774 ((val.peGreen << gsc) & gDst) |
1775 ((val.peBlue >> 3) & bDst);
1777 ptr = (LPWORD)(dstbits += linebytes);
1780 else goto notsupported;
1782 break;
1784 default:
1785 notsupported:
1787 BYTE r,g, b;
1788 LPWORD ptr = (LPWORD)dstbits;
1790 FIXME("from %d bit bitmap with mask R,G,B %lx,%lx,%lx to 16 bit DIB %lx,%lx,%lx\n",
1791 bmpImage->depth, bmpImage->red_mask,
1792 bmpImage->green_mask, bmpImage->blue_mask,
1793 rDst, gDst, bDst);
1795 for (h = lines - 1; h >= 0; h--)
1797 for (x = 0; x < dstwidth; x++, ptr++)
1799 COLORREF pixel = X11DRV_PALETTE_ToLogical( XGetPixel( bmpImage, x, h ) );
1800 r = (BYTE) GetRValue(pixel);
1801 g = (BYTE) GetGValue(pixel);
1802 b = (BYTE) GetBValue(pixel);
1803 *ptr = ( ((r << rsc) & rDst) | ((g << gsc) & gDst) | ((b >> 3) & bDst) );
1805 ptr = (LPWORD) (dstbits += linebytes);
1808 break;
1813 /***********************************************************************
1814 * X11DRV_DIB_SetImageBits_24
1816 * SetDIBits for a 24-bit deep DIB.
1818 static void X11DRV_DIB_SetImageBits_24( int lines, const BYTE *srcbits,
1819 DWORD srcwidth, DWORD dstwidth, int left,
1820 DC *dc, XImage *bmpImage, DWORD linebytes )
1822 DWORD x;
1823 int h;
1825 if (lines < 0 )
1827 lines = -lines;
1828 srcbits = srcbits + linebytes * (lines - 1);
1829 linebytes = -linebytes;
1832 switch ( bmpImage->depth )
1834 case 24:
1836 if (bmpImage->bits_per_pixel == 24) {
1837 int dstlinebytes = linebytes;
1838 BYTE *dstpixel;
1839 BYTE *ptr = (BYTE *)(srcbits+left*3);
1841 if (dstlinebytes < 0 ) dstlinebytes = -dstlinebytes;
1842 dstpixel = bmpImage->data + lines*dstlinebytes + left*3;
1843 for(h = lines ; h-- ; ) {
1844 dstpixel-=dstlinebytes;
1845 memcpy(dstpixel,ptr,dstwidth*3);
1846 ptr +=linebytes;
1848 break;
1851 case 32:
1853 if( bmpImage->blue_mask == 0xff && bmpImage->red_mask == 0xff0000 ) /* packed BGR to unpacked BGR */
1855 DWORD *dstpixel, val, buf;
1856 DWORD *ptr = (DWORD *)(srcbits + left*3);
1857 BYTE *bits;
1858 int div = dstwidth % 4;
1859 int divk;
1861 for(h = lines - 1; h >= 0; h--)
1863 dstpixel = (DWORD *) (bmpImage->data + h*bmpImage->bytes_per_line + left*4);
1865 for (x = 0; x < dstwidth/4; x++) { /* do 3 dwords source, 4 dwords dest at a time */
1866 buf = *ptr++;
1867 *dstpixel++ = buf&0x00ffffff; /* b1, g1, r1 */
1868 val = (buf >> 24); /* b2 */
1869 buf = *ptr++;
1870 *dstpixel++ = (val | (buf<<8)) &0x00ffffff; /* g2, r2 */
1871 val = (buf >> 16); /* b3, g3 */
1872 buf = *ptr++;
1873 *dstpixel++ = (val | (buf<<16)) &0x00ffffff; /* r3 */
1874 *dstpixel++ = (buf >> 8); /* b4, g4, r4 */
1876 for ( divk=div, bits=(BYTE*)ptr; divk>0; divk--, bits+=3 ) /* do remainder */
1878 *dstpixel++ = *(DWORD*)bits & 0x00ffffff; /* b, g, r */
1880 ptr = (DWORD*)((srcbits+=linebytes)+left*3);
1883 else if( bmpImage->blue_mask == 0xff0000 && bmpImage->red_mask == 0xff ) /* packed BGR to unpacked RGB */
1885 DWORD *dstpixel, val, buf;
1886 DWORD *ptr = (DWORD *)(srcbits + left*3);
1887 BYTE *bits;
1888 int div = dstwidth % 4;
1889 int divk;
1891 for(h = lines - 1; h >= 0; h--)
1893 dstpixel = (DWORD *) (bmpImage->data + h*bmpImage->bytes_per_line + left*4);
1895 for (x = 0; x < dstwidth/4; x++) { /* do 3 dwords source, 4 dwords dest at a time */
1896 buf = *ptr++;
1897 *dstpixel++ = ((buf&0xff)<<16) | (buf&0xff00) | ((buf&0xff0000)>>16); /* b1, g1, r1 */
1898 val = ((buf&0xff000000)>>8); /* b2 */
1899 buf = *ptr++;
1900 *dstpixel++ = val | ((buf&0xff)<<8) | ((buf&0xff00)>>8); /* g2, r2 */
1901 val = (buf&0xff0000) | ((buf&0xff000000)>>16); /* b3, g3 */
1902 buf = *ptr++;
1903 *dstpixel++ = val | (buf&0xff); /* r3 */
1904 *dstpixel++ = ((buf&0xff00)<<8) | ((buf&0xff0000)>>8) | (buf>>24); /* b4, g4, r4 */
1906 for ( divk=div, bits=(BYTE*)ptr; divk>0; divk--, bits+=3 ) /* do remainder */
1908 buf = *(DWORD*)bits;
1909 *dstpixel++ = ((buf&0xff)<<16) | (buf&0xff00) | ((buf&0xff0000)>>16); /* b, g, r */
1911 ptr = (DWORD*)((srcbits+=linebytes)+left*3);
1914 else
1915 goto notsupported;
1917 break;
1919 case 15:
1921 if( bmpImage->blue_mask == 0x7c00 && bmpImage->red_mask == 0x1f ) /* BGR888 to RGB555 */
1923 DWORD *ptr = (DWORD *)(srcbits + left*3);
1924 LPBYTE bits;
1925 LPWORD dstpixel;
1926 int div = dstwidth % 4;
1927 int divk;
1929 for (h = lines - 1; h >= 0; h--) { /* Do 4 pixels at a time */
1930 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1931 for (x = 0; x < dstwidth/4; x++, ptr += 3) {
1932 *dstpixel++ = ((ptr[0] << 7) & 0x7c00) | ((ptr[0] >> 6) & 0x03e0) | ((ptr[0] >> 19) & 0x1f);
1933 *dstpixel++ = ((ptr[0] >> 17) & 0x7c00) | ((ptr[1] << 2) & 0x03e0) | ((ptr[1] >> 11) & 0x1f);
1934 *dstpixel++ = ((ptr[1] >> 9) & 0x07c00) | ((ptr[1] >> 22) & 0x03e0) | ((ptr[2] >> 3) & 0x1f);
1935 *dstpixel++ = ((ptr[2] >> 1) & 0x07c00) | ((ptr[2] >> 14) & 0x03e0) | ((ptr[2] >> 27) & 0x1f);
1937 for (bits = (LPBYTE)ptr, divk=div; divk > 0; divk--, bits+=3) /* dstwidth not divisible by 4? */
1938 *dstpixel++ = (((WORD)bits[0] << 7) & 0x07c00) |
1939 (((WORD)bits[1] << 2) & 0x03e0) |
1940 (((WORD)bits[2] >> 3) & 0x001f);
1941 ptr = (DWORD *)((srcbits += linebytes) + left * 3);
1944 else if( bmpImage->blue_mask == 0x1f && bmpImage->red_mask == 0x7c00 ) /* BGR888 to BGR555 */
1946 DWORD *ptr = (DWORD *)(srcbits + left*3);
1947 LPBYTE bits;
1948 LPWORD dstpixel;
1949 int div = dstwidth % 4;
1950 int divk;
1952 for (h = lines - 1; h >= 0; h--) { /* Do 4 pixels at a time */
1953 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1954 for (x = 0; x < dstwidth/4; x++, ptr += 3) {
1955 *dstpixel++ = ((ptr[0] >> 3) & 0x1f) | ((ptr[0] >> 6) & 0x03e0) | ((ptr[0] >> 9) & 0x7c00);
1956 *dstpixel++ = ((ptr[0] >> 27) & 0x1f) | ((ptr[1] << 2) & 0x03e0) | ((ptr[1] >> 1) & 0x7c00);
1957 *dstpixel++ = ((ptr[1] >> 19) & 0x1f) | ((ptr[1] >> 22) & 0x03e0) | ((ptr[2] << 7) & 0x7c00);
1958 *dstpixel++ = ((ptr[2] >> 11) & 0x1f) | ((ptr[2] >> 14) & 0x03e0) | ((ptr[2] >> 17) & 0x7c00);
1960 for (bits = (LPBYTE)ptr, divk=div; divk > 0; divk--, bits+=3) /* dstwidth not divisible by 4? */
1961 *dstpixel++ = (((WORD)bits[2] << 7) & 0x07c00) |
1962 (((WORD)bits[1] << 2) & 0x03e0) |
1963 (((WORD)bits[0] >> 3) & 0x001f);
1964 ptr = (DWORD *)((srcbits += linebytes) + left * 3);
1967 else
1968 goto notsupported;
1970 break;
1972 case 16:
1974 DWORD *ptr = (DWORD *)(srcbits + left*3);
1975 LPBYTE bits;
1976 LPWORD dstpixel;
1977 int div = dstwidth % 4;
1978 int divk;
1980 if( bmpImage->blue_mask == 0x001f && bmpImage->red_mask == 0xf800 ) /* BGR888 to BGR565 */
1982 for (h = lines - 1; h >= 0; h--) { /* Do 4 pixels at a time */
1983 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1984 for (x = 0; x < dstwidth/4; x++, ptr += 3) {
1985 *dstpixel++ = ((ptr[0] >> 3) & 0x1f) | ((ptr[0] >> 5) & 0x07e0) | ((ptr[0] >> 8) & 0xf800);
1986 *dstpixel++ = ((ptr[0] >> 27) & 0x1f) | ((ptr[1] << 3) & 0x07e0) | (ptr[1] & 0xf800);
1987 *dstpixel++ = ((ptr[1] >> 19) & 0x1f) | ((ptr[1] >> 21) & 0x07e0) | ((ptr[2] << 8) & 0xf800);
1988 *dstpixel++ = ((ptr[2] >> 11) & 0x1f) | ((ptr[2] >> 13) & 0x07e0) | ((ptr[2] >> 16) & 0xf800);
1990 for ( bits = (LPBYTE)ptr, divk=div; divk > 0; divk--, bits+=3) /* dstwidth is not divisible by 4? */
1991 *dstpixel++ = (((WORD)bits[2] << 8) & 0xf800) |
1992 (((WORD)bits[1] << 3) & 0x07e0) |
1993 (((WORD)bits[0] >> 3) & 0x001f);
1994 ptr = (DWORD *)((srcbits += linebytes) + left * 3);
1997 else if( bmpImage->blue_mask == 0xf800 && bmpImage->red_mask == 0x001f ) /* BGR888 to RGB565 */
1999 for (h = lines - 1; h >= 0; h--) { /* Do 4 pixels at a time */
2000 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
2001 for (x = 0; x < dstwidth/4; x++, ptr += 3) {
2002 *dstpixel++ = ((ptr[0] << 8) & 0xf800) | ((ptr[0] >> 5) & 0x07e0) | ((ptr[0] >> 19) & 0x1f);
2003 *dstpixel++ = ((ptr[0] >> 16) & 0xf800) | ((ptr[1] << 3) & 0x07e0) | ((ptr[1] >> 11) & 0x1f);
2004 *dstpixel++ = ((ptr[1] >> 8) & 0xf800) | ((ptr[1] >> 21) & 0x07e0) | ((ptr[2] >> 3) & 0x1f);
2005 *dstpixel++ = (ptr[2] & 0xf800) | ((ptr[2] >> 13) & 0x07e0) | ((ptr[2] >> 27) & 0x1f);
2007 for ( bits = (LPBYTE)ptr, divk=div; divk > 0; divk--, bits+=3) /* dstwidth is not divisible by 4? */
2008 *dstpixel++ = (((WORD)bits[0] << 8) & 0xf800) |
2009 (((WORD)bits[1] << 3) & 0x07e0) |
2010 (((WORD)bits[2] >> 3) & 0x001f);
2011 ptr = (DWORD *)((srcbits += linebytes) + left * 3);
2014 else
2015 goto notsupported;
2017 break;
2019 case 1:
2020 case 4:
2021 case 8:
2023 LPBYTE bits = (LPBYTE)srcbits + left*3;
2025 for (h = lines - 1; h >= 0; h--) {
2026 for (x = left; x < dstwidth+left; x++, bits+=3)
2027 XPutPixel( bmpImage, x, h,
2028 X11DRV_PALETTE_ToPhysical(dc, RGB(bits[2], bits[1], bits[0])));
2029 bits = (LPBYTE)(srcbits += linebytes) + left * 3;
2032 break;
2034 default:
2035 notsupported:
2036 FIXME("from 24 bit DIB to %d bit bitmap with mask R,G,B %x,%x,%x\n",
2037 bmpImage->bits_per_pixel, (int)bmpImage->red_mask,
2038 (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
2039 break;
2044 /***********************************************************************
2045 * X11DRV_DIB_GetImageBits_24
2047 * GetDIBits for an 24-bit deep DIB.
2049 static void X11DRV_DIB_GetImageBits_24( int lines, BYTE *dstbits,
2050 DWORD dstwidth, DWORD srcwidth,
2051 PALETTEENTRY *srccolors,
2052 XImage *bmpImage, DWORD linebytes )
2054 DWORD x, val;
2055 int h;
2057 if (lines < 0 )
2059 lines = -lines;
2060 dstbits = dstbits + ( linebytes * (lines-1) );
2061 linebytes = -linebytes;
2064 switch ( bmpImage->depth )
2066 case 24:
2068 if (bmpImage->bits_per_pixel == 24) {
2069 int tocopy = linebytes;
2070 BYTE *srcpixel;
2071 BYTE *ptr = (LPBYTE)dstbits;
2073 if (tocopy < 0 ) tocopy = -tocopy;
2074 srcpixel = bmpImage->data + lines*tocopy;
2075 for(h = lines ; h-- ; ) {
2076 srcpixel-=tocopy;
2077 memcpy(ptr,srcpixel,tocopy);
2078 ptr = (LPBYTE)(dstbits+=linebytes);
2080 break;
2083 case 32:
2085 DWORD *srcpixel, buf;
2086 LPBYTE bits;
2087 DWORD *ptr=(DWORD *)dstbits;
2088 int quotient = dstwidth / 4;
2089 int remainder = dstwidth % 4;
2090 int remk;
2092 /* ==== 24/32 BGR bitmap to 24 BGR dib==== */
2093 if( bmpImage->blue_mask == 0xff && bmpImage->red_mask == 0xff0000 )
2095 for(h = lines - 1; h >= 0; h--)
2097 srcpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line);
2099 for (x = 0; x < quotient; x++) { /* do 4 dwords source, 3 dwords dest at a time */
2100 buf = ((*srcpixel++)&0x00ffffff); /* b1, g1, r1*/
2101 *ptr++ = buf | ((*srcpixel)<<24); /* b2 */
2102 buf = ((*srcpixel++>>8)&0x0000ffff); /* g2, r2 */
2103 *ptr++ = buf | ((*srcpixel)<<16); /* b3, g3 */
2104 buf = ((*srcpixel++>>16)&0x000000ff); /* r3 */
2105 *ptr++ = buf | ((*srcpixel++)<<8); /* b4, g4, r4 */
2107 for ( remk=remainder, bits=(BYTE*)ptr; remk>0; remk--, bits+=3 ) /* do remainder */
2109 buf=*srcpixel++;
2110 *(WORD*)bits = buf; /* b, g */
2111 *(bits+2) = buf>>16; /* r */
2113 ptr = (DWORD*)(dstbits+=linebytes);
2117 /* ==== 24/32 RGB bitmap to 24 BGR dib ==== */
2118 else if( bmpImage->blue_mask == 0xff0000 && bmpImage->red_mask == 0xff )
2120 for(h = lines - 1; h >= 0; h--)
2122 srcpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line);
2124 for (x = 0; x < quotient; x++) { /* do 4 dwords source, 3 dwords dest at a time */
2125 buf = *srcpixel++;
2126 val = ((buf&0xff0000)>>16) | (buf&0xff00) | ((buf&0xff)<<16); /* b1, g1, r1 */
2127 buf = *srcpixel++;
2128 *ptr++ = val | ((buf&0xff0000)<<8); /* b2 */
2129 val = ((buf&0xff00)>>8) | ((buf&0xff)<<8); /* g2, r2 */
2130 buf = *srcpixel++;
2131 *ptr++ = val | (buf&0xff0000) | ((buf&0xff00)<<16); /* b3, g3 */
2132 val = (buf&0xff); /* r3 */
2133 buf = *srcpixel++;
2134 *ptr++ = val | ((buf&0xff0000)>>8) | ((buf&0xff00)<<8) | (buf<<24); /* b4, g4, r4 */
2136 for ( remk=remainder, bits=(BYTE*)ptr; remk>0; remk--, bits+=3 ) /* do remainder */
2138 buf=*srcpixel++;
2139 *(WORD*)bits = (buf&0xff00) | ((buf&0xff0000)>>16) ; /* b, g */
2140 *(bits+2) = buf; /* r */
2142 ptr = (DWORD*)(dstbits+=linebytes);
2145 else goto notsupported;
2147 break;
2149 case 15:
2151 LPWORD srcpixel;
2152 LPBYTE bits = dstbits;
2153 WORD val;
2155 /* ==== 555 BGR bitmap to 24 BGR dib ==== */
2156 if( bmpImage->blue_mask == 0x1f && bmpImage->red_mask == 0x7c00 )
2158 for (h = lines - 1; h >= 0; h--) {
2159 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2160 for (x = 0; x < srcwidth; x++, bits += 3) {
2161 val = *srcpixel++;
2162 bits[2] = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07)); /*Red*/
2163 bits[1] = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07)); /*Green*/
2164 bits[0] = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07)); /*Blue*/
2166 bits = (dstbits += linebytes);
2169 /* ==== 555 RGB bitmap to 24 RGB dib==== */
2170 else if( bmpImage->blue_mask == 0x7c00 && bmpImage->red_mask == 0x1f )
2172 for (h = lines - 1; h >= 0; h--) {
2173 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2174 for (x = 0; x < srcwidth; x++, bits += 3) {
2175 val = *srcpixel++;
2176 bits[0] = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07)); /*Red*/
2177 bits[1] = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07)); /*Green*/
2178 bits[2] = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07)); /*Blue*/
2180 bits = (dstbits += linebytes);
2183 else goto notsupported;
2185 break;
2187 case 16:
2189 LPWORD srcpixel;
2190 LPBYTE bits = dstbits;
2191 WORD val;
2193 /* ==== 565 BGR bitmap to 24 BGR dib ==== */
2194 if( bmpImage->blue_mask == 0x1f && bmpImage->red_mask == 0xf800 )
2196 for (h = lines - 1; h >= 0; h--) {
2197 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2198 for (x = 0; x < srcwidth; x++, bits += 3) {
2199 val = *srcpixel++;
2200 bits[2] = (BYTE)(((val >> 8) & 0xf8) | ((val >> 13) & 0x07)); /*Red*/
2201 bits[1] = (BYTE)(((val >> 3) & 0xfc) | ((val >> 9) & 0x03)); /*Green*/
2202 bits[0] = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07)); /*Blue*/
2204 bits = (dstbits += linebytes);
2207 /* ==== 565 RGB bitmap to 24 BGR dib ==== */
2208 else if( bmpImage->blue_mask == 0xf800 && bmpImage->red_mask == 0x1f )
2210 for (h = lines - 1; h >= 0; h--) {
2211 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2212 for (x = 0; x < srcwidth; x++, bits += 3) {
2213 val = *srcpixel++;
2214 bits[0] = (BYTE)(((val >> 8) & 0xf8) | ((val >> 13) & 0x07)); /*Red*/
2215 bits[1] = (BYTE)(((val >> 3) & 0xfc) | ((val >> 9) & 0x03)); /*Green*/
2216 bits[2] = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07)); /*Blue*/
2218 bits = (dstbits += linebytes);
2221 else goto notsupported;
2223 break;
2225 case 1:
2226 /* ==== monochrome bitmap to 24 BGR dib ==== */
2227 case 4:
2228 /* ==== 4 colormap bitmap to 24 BGR dib ==== */
2229 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
2231 LPBYTE bits = dstbits;
2232 PALETTEENTRY val;
2234 for (h = lines - 1; h >= 0; h--) {
2235 for (x = 0; x < dstwidth; x++) {
2236 val = srccolors[XGetPixel(bmpImage, x, h)];
2237 *bits++ = val.peBlue;
2238 *bits++ = val.peGreen;
2239 *bits++ = val.peRed;
2241 bits = (dstbits += linebytes);
2244 else goto notsupported;
2246 break;
2248 case 8:
2249 /* ==== 8 colormap bitmap to 24 BGR dib ==== */
2250 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask == 0 && srccolors)
2252 BYTE *srcpixel;
2253 LPBYTE bits = dstbits;
2254 PALETTEENTRY val;
2256 for (h = lines - 1; h >= 0; h--) {
2257 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
2258 for (x = 0; x < dstwidth; x++ ) {
2259 val = srccolors[(int)*srcpixel++];
2260 *bits++ = val.peBlue; /*Blue*/
2261 *bits++ = val.peGreen; /*Green*/
2262 *bits++ = val.peRed; /*Red*/
2264 bits = (dstbits += linebytes);
2267 else goto notsupported;
2269 break;
2271 default:
2272 notsupported:
2274 LPBYTE bits = dstbits;
2276 FIXME("from %d bit bitmap with mask R,G,B %x,%x,%x to 24 bit DIB\n",
2277 bmpImage->depth, (int)bmpImage->red_mask,
2278 (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
2279 for (h = lines - 1; h >= 0; h--)
2281 for (x = 0; x < dstwidth; x++, bits += 3)
2283 COLORREF pixel = X11DRV_PALETTE_ToLogical( XGetPixel( bmpImage, x, h ) );
2284 bits[0] = GetBValue(pixel);
2285 bits[1] = GetGValue(pixel);
2286 bits[2] = GetRValue(pixel);
2288 bits = (dstbits += linebytes);
2291 break;
2296 /***********************************************************************
2297 * X11DRV_DIB_SetImageBits_32
2299 * SetDIBits for a 32-bit deep DIB.
2301 static void X11DRV_DIB_SetImageBits_32( int lines, const BYTE *srcbits,
2302 DWORD srcwidth, DWORD dstwidth, int left,
2303 DC *dc, XImage *bmpImage,
2304 DWORD linebytes )
2306 DWORD x, *ptr;
2307 int h;
2309 if (lines < 0 )
2311 lines = -lines;
2312 srcbits = srcbits + ( linebytes * (lines-1) );
2313 linebytes = -linebytes;
2316 ptr = (DWORD *) srcbits + left;
2318 switch ( bmpImage->depth )
2320 case 32:
2321 /* ==== 32 BGR dib to 24/32 BGR bitmap ==== */
2322 if (bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff) {
2323 for (h = lines - 1; h >= 0; h--, srcbits+=linebytes) {
2324 memcpy( bmpImage->data + h * bmpImage->bytes_per_line, srcbits + left*4, dstwidth*4 );
2328 /* ==== 32 BGR dib to 24/32 RGB bitmap ==== */
2329 else if (bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000)
2331 DWORD *dstpixel;
2333 for (h = lines - 1; h >= 0; h--) {
2334 dstpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line);
2335 for (x = 0; x < dstwidth; x++, ptr++) {
2336 *dstpixel++ = ((*ptr << 16) & 0xff0000) | (*ptr & 0xff00) | ((*ptr >> 16) & 0xff);
2338 ptr = (DWORD *) (srcbits += linebytes) + left;
2341 else goto notsupported;
2343 break;
2345 case 24:
2346 /* ==== 32 BGR dib to 24 (888) BGR bitmap ==== */
2347 /* we need to check that source mask matches destination */
2348 if (bmpImage->bits_per_pixel == 32)
2350 for (h = lines - 1; h >= 0; h--, srcbits+=linebytes) {
2351 memcpy( bmpImage->data + h * bmpImage->bytes_per_line, srcbits + left*4, dstwidth*4 );
2354 else
2356 BYTE *bptr;
2358 ptr = (DWORD *) srcbits + left;
2359 bptr = bmpImage->data;
2361 for (h = lines - 1; h >= 0; h--) {
2362 for (x = 0; x < dstwidth; x++) {
2363 /* *ptr is a 32bit value */
2364 /* bptr points to first of 3 bytes */
2365 *bptr++ = (*ptr >> 16) & 0xff;
2366 *bptr++ = (*ptr >> 8) & 0xff;
2367 *bptr++ = (*ptr ) & 0xff;
2368 ptr++;
2370 ptr = (DWORD *) (srcbits += linebytes) + left;
2373 break;
2375 case 15:
2376 /* ==== 32 BGR dib to 555 BGR bitmap ==== */
2377 if (bmpImage->red_mask == 0x7c00 && bmpImage->blue_mask == 0x001f) {
2378 LPWORD dstpixel;
2380 for (h = lines - 1; h >= 0; h--) {
2381 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2382 for (x = 0; x < dstwidth; x++, ptr++) {
2383 *dstpixel++ = (WORD) (((*ptr >> 9) & 0x7c00) | ((*ptr >> 6) & 0x03e0) | ((*ptr >> 3) & 0x001f));
2385 ptr = (DWORD *) (srcbits += linebytes) + left;
2388 /* ==== 32 BGR dib to 555 RGB bitmap ==== */
2389 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0x7c00)
2391 LPWORD dstpixel;
2393 for (h = lines - 1; h >= 0; h--) {
2394 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2395 for (x = 0; x < dstwidth; x++, ptr++) {
2396 *dstpixel++ = (WORD) (((*ptr << 7) & 0x7c00) | ((*ptr >> 6) & 0x03e0) | ((*ptr >> 19) & 0x001f));
2398 ptr = (DWORD *) (srcbits += linebytes) + left;
2401 else goto notsupported;
2403 break;
2405 case 16:
2406 /* ==== 32 BGR dib to 565 BGR bitmap ==== */
2407 if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f)
2409 LPWORD dstpixel;
2411 for (h = lines - 1; h >= 0; h--) {
2412 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2413 for (x = 0; x < dstwidth; x++, ptr++) {
2414 *dstpixel++ = (WORD) (((*ptr >> 8) & 0xf800) | ((*ptr >> 5) & 0x07e0) | ((*ptr >> 3) & 0x001f));
2416 ptr = (DWORD *) (srcbits += linebytes) + left;
2419 /* ==== 32 BGR dib to 565 RGB bitmap ==== */
2420 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0xf800)
2422 LPWORD dstpixel;
2424 for (h = lines - 1; h >= 0; h--) {
2425 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2426 for (x = 0; x < dstwidth; x++, ptr++) {
2427 *dstpixel++ = (WORD) (((*ptr << 8) & 0xf800) | ((*ptr >> 5) & 0x07e0) | ((*ptr >> 19) & 0x001f));
2429 ptr = (DWORD *) (srcbits += linebytes) + left;
2432 else goto notsupported;
2434 break;
2436 case 1:
2437 case 4:
2438 case 8:
2440 LPBYTE bits = (LPBYTE)srcbits + left*4;
2442 for (h = lines - 1; h >= 0; h--) {
2443 for (x = left; x < dstwidth+left; x++, bits += 4)
2444 XPutPixel( bmpImage, x, h,
2445 X11DRV_PALETTE_ToPhysical(dc, RGB( bits[2], bits[1], *bits )));
2446 bits = (LPBYTE)(srcbits += linebytes) + left * 4;
2449 break;
2451 default:
2452 notsupported:
2453 FIXME("32 bit DIB %d bit bitmap\n", bmpImage->bits_per_pixel);
2454 break;
2459 /***********************************************************************
2460 * X11DRV_DIB_GetImageBits_32
2462 * GetDIBits for an 32-bit deep DIB.
2464 static void X11DRV_DIB_GetImageBits_32( int lines, BYTE *dstbits,
2465 DWORD dstwidth, DWORD srcwidth,
2466 PALETTEENTRY *srccolors,
2467 XImage *bmpImage, DWORD linebytes )
2469 DWORD x;
2470 int h;
2471 BYTE *bits;
2473 DWORD copybytes = srcwidth * 4;
2475 if (lines < 0 )
2477 lines = -lines;
2478 dstbits = dstbits + ( linebytes * (lines-1) );
2479 linebytes = -linebytes;
2482 bits = dstbits;
2484 switch ( bmpImage->depth )
2486 case 32:
2487 /* ==== 24/32 BGR bitmap to 32 BGR dib ==== */
2488 if ( bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff )
2489 for (h = lines - 1; h >= 0; h--, dstbits+=linebytes)
2490 memcpy( dstbits, bmpImage->data + h*bmpImage->bytes_per_line, copybytes );
2492 /* ==== 24/32 RGB bitmap to 32 BGR dib ==== */
2493 else if ( bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000 )
2495 LPBYTE srcbits;
2497 for (h = lines - 1; h >= 0; h--) {
2498 srcbits = bmpImage->data + h * bmpImage->bytes_per_line;
2499 for (x = 0; x < dstwidth; x++, bits+=4, srcbits+=2) {
2500 *(bits + 2) = *srcbits++;
2501 *(bits + 1) = *srcbits++;
2502 *bits = *srcbits;
2504 bits = (dstbits += linebytes);
2507 else goto notsupported;
2508 break;
2510 case 24:
2511 /* ==== 24 BGR bitmap to 32 (0888) BGR dib ==== */
2512 /* we need to check that source mask matches destination */
2514 DWORD *srcpixel;
2515 BYTE *bptr;
2516 DWORD srcdata;
2518 srcpixel = (DWORD *) dstbits;
2519 bptr = bmpImage->data;
2521 for (h = lines - 1; h >= 0; h--) {
2522 for (x = 0; x < dstwidth; x++) {
2523 /* *srcpixel is a 32bit value */
2524 /* bptr points to first of 3 bytes */
2525 srcdata = 0;
2526 srcdata = srcdata << 8 | *bptr++;
2527 srcdata = srcdata << 8 | *bptr++;
2528 srcdata = srcdata << 8 | *bptr++;
2530 *srcpixel++ = srcdata;
2532 srcpixel = (DWORD *) (dstbits += linebytes);
2535 break;
2537 case 15:
2539 LPWORD srcpixel;
2540 WORD val;
2542 /* ==== 555 BGR bitmap to 32 BGR dib ==== */
2543 if (bmpImage->red_mask == 0x7c00 && bmpImage->blue_mask == 0x001f)
2545 for (h = lines - 1; h >= 0; h--) {
2546 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2547 for (x = 0; x < dstwidth; x++, bits+=2) {
2548 val = *srcpixel++;
2549 *bits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x03)); /*Blue*/
2550 *bits++ = (BYTE)(((val >> 2) & 0xfc) | ((val >> 8) & 0x03)); /*Green*/
2551 *bits = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07)); /*Red*/
2553 bits = (dstbits += linebytes);
2556 /* ==== 555 RGB bitmap to 32 BGR dib ==== */
2557 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0x7c00)
2559 for (h = lines - 1; h >= 0; h--) {
2560 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2561 for (x = 0; x < dstwidth; x++, bits+=2) {
2562 val = *srcpixel++;
2563 *bits++ = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07));/*Blue*/
2564 *bits++ = (BYTE)(((val >> 2) & 0xfc) | ((val >> 8) & 0x03)); /*Green*/
2565 *bits = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x03)); /*Red*/
2567 bits = (dstbits += linebytes);
2570 else goto notsupported;
2572 break;
2574 case 16:
2576 LPWORD srcpixel;
2577 WORD val;
2579 /* ==== 565 BGR bitmap to 32 BGR dib ==== */
2580 if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f)
2582 for (h = lines - 1; h >= 0; h--) {
2583 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2584 for (x = 0; x < srcwidth; x++, bits+=2) {
2585 val = *srcpixel++;
2586 *bits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x03)); /*Blue*/
2587 *bits++ = (BYTE)(((val >> 3) & 0xfc) | ((val >> 9) & 0x03)); /*Green*/
2588 *bits = (BYTE)(((val >> 8) & 0xf8) | ((val >> 13) & 0x07)); /*Red*/
2590 bits = (dstbits += linebytes);
2593 /* ==== 565 RGB bitmap to 32 BGR dib ==== */
2594 else if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f)
2596 for (h = lines - 1; h >= 0; h--) {
2597 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2598 for (x = 0; x < srcwidth; x++, bits+=2) {
2599 val = *srcpixel++;
2600 *bits++ = (BYTE)(((val >> 8) & 0xf8) | ((val >> 13) & 0x07));/*Blue*/
2601 *bits++ = (BYTE)(((val >> 3) & 0xfc) | ((val >> 9) & 0x03)); /*Green*/
2602 *bits = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x03)); /*Red*/
2604 bits = (dstbits += linebytes);
2607 else goto notsupported;
2609 break;
2611 case 1:
2612 /* ==== monochrome bitmap to 32 BGR dib ==== */
2613 case 4:
2614 /* ==== 4 colormap bitmap to 32 BGR dib ==== */
2615 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
2617 PALETTEENTRY val;
2619 for (h = lines - 1; h >= 0; h--) {
2620 for (x = 0; x < dstwidth; x++) {
2621 val = srccolors[XGetPixel(bmpImage, x, h)];
2622 *bits++ = val.peBlue;
2623 *bits++ = val.peGreen;
2624 *bits++ = val.peRed;
2625 *bits++ = 0;
2627 bits = (dstbits += linebytes);
2630 else goto notsupported;
2632 break;
2634 case 8:
2635 /* ==== 8 colormap bitmap to 32 BGR dib ==== */
2636 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
2638 BYTE *srcpixel;
2639 PALETTEENTRY val;
2641 for (h = lines - 1; h >= 0; h--) {
2642 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
2643 for (x = 0; x < dstwidth; x++) {
2644 val = srccolors[(int)*srcpixel++];
2645 *bits++ = val.peBlue; /*Blue*/
2646 *bits++ = val.peGreen; /*Green*/
2647 *bits++ = val.peRed; /*Red*/
2648 *bits++ = 0;
2650 bits = (dstbits += linebytes);
2653 else goto notsupported;
2654 break;
2656 default:
2657 notsupported:
2658 FIXME("from %d bit bitmap with mask R,G,B %x,%x,%x to 32 bit DIB\n",
2659 bmpImage->depth, (int)bmpImage->red_mask,
2660 (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
2661 for (h = lines - 1; h >= 0; h--)
2663 for (x = 0; x < dstwidth; x++, bits += 4)
2665 COLORREF pixel = X11DRV_PALETTE_ToLogical( XGetPixel( bmpImage, x, h ) );
2666 bits[0] = GetBValue(pixel);
2667 bits[1] = GetGValue(pixel);
2668 bits[2] = GetRValue(pixel);
2670 bits = (dstbits += linebytes);
2672 break;
2676 /***********************************************************************
2677 * X11DRV_DIB_SetImageBits
2679 * Transfer the bits to an X image.
2680 * Helper function for SetDIBits() and SetDIBitsToDevice().
2682 static int X11DRV_DIB_SetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
2684 int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
2685 XImage *bmpImage;
2687 wine_tsx11_lock();
2688 if (descr->image)
2689 bmpImage = descr->image;
2690 else {
2691 bmpImage = XCreateImage( display, X11DRV_GetVisual(), descr->depth, ZPixmap, 0, NULL,
2692 descr->infoWidth, lines, 32, 0 );
2693 bmpImage->data = calloc( lines, bmpImage->bytes_per_line );
2694 if(bmpImage->data == NULL) {
2695 ERR("Out of memory!\n");
2696 XDestroyImage( bmpImage );
2697 wine_tsx11_unlock();
2698 return lines;
2702 /* Transfer the pixels */
2703 switch(descr->infoBpp)
2705 case 1:
2706 X11DRV_DIB_SetImageBits_1( descr->lines, descr->bits, descr->infoWidth,
2707 descr->width, descr->xSrc, (int *)(descr->colorMap),
2708 bmpImage, descr->dibpitch );
2709 break;
2710 case 4:
2711 if (descr->compression) {
2712 XGetSubImage( display, descr->drawable, descr->xDest, descr->yDest,
2713 descr->width, descr->height, AllPlanes, ZPixmap,
2714 bmpImage, descr->xSrc, descr->ySrc );
2716 X11DRV_DIB_SetImageBits_RLE4( descr->lines, descr->bits,
2717 descr->infoWidth, descr->width,
2718 descr->xSrc, (int *)(descr->colorMap),
2719 bmpImage );
2720 } else
2721 X11DRV_DIB_SetImageBits_4( descr->lines, descr->bits,
2722 descr->infoWidth, descr->width,
2723 descr->xSrc, (int*)(descr->colorMap),
2724 bmpImage, descr->dibpitch );
2725 break;
2726 case 8:
2727 if (descr->compression) {
2728 XGetSubImage( display, descr->drawable, descr->xDest, descr->yDest,
2729 descr->width, descr->height, AllPlanes, ZPixmap,
2730 bmpImage, descr->xSrc, descr->ySrc );
2731 X11DRV_DIB_SetImageBits_RLE8( descr->lines, descr->bits,
2732 descr->infoWidth, descr->width,
2733 descr->xSrc, (int *)(descr->colorMap),
2734 bmpImage );
2735 } else
2736 X11DRV_DIB_SetImageBits_8( descr->lines, descr->bits,
2737 descr->infoWidth, descr->width,
2738 descr->xSrc, (int *)(descr->colorMap),
2739 bmpImage, descr->dibpitch );
2740 break;
2741 case 15:
2742 case 16:
2743 X11DRV_DIB_SetImageBits_16( descr->lines, descr->bits,
2744 descr->infoWidth, descr->width,
2745 descr->xSrc, descr->dc,
2746 descr->rMask, descr->gMask, descr->bMask,
2747 bmpImage, descr->dibpitch);
2748 break;
2749 case 24:
2750 X11DRV_DIB_SetImageBits_24( descr->lines, descr->bits,
2751 descr->infoWidth, descr->width,
2752 descr->xSrc, descr->dc, bmpImage,
2753 descr->dibpitch);
2754 break;
2755 case 32:
2756 X11DRV_DIB_SetImageBits_32( descr->lines, descr->bits,
2757 descr->infoWidth, descr->width,
2758 descr->xSrc, descr->dc,
2759 bmpImage, descr->dibpitch);
2760 break;
2761 default:
2762 WARN("(%d): Invalid depth\n", descr->infoBpp );
2763 break;
2766 TRACE("XPutImage(%p,%ld,%p,%p,%d,%d,%d,%d,%d,%d)\n",
2767 display, descr->drawable, descr->gc, bmpImage,
2768 descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
2769 descr->width, descr->height);
2770 if (descr->useShm)
2772 XShmPutImage( display, descr->drawable, descr->gc, bmpImage,
2773 descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
2774 descr->width, descr->height, FALSE );
2775 XSync( display, 0 );
2777 else
2778 XPutImage( display, descr->drawable, descr->gc, bmpImage,
2779 descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
2780 descr->width, descr->height );
2782 if (!descr->image) XDestroyImage( bmpImage );
2783 wine_tsx11_unlock();
2784 return lines;
2787 /***********************************************************************
2788 * X11DRV_DIB_GetImageBits
2790 * Transfer the bits from an X image.
2792 static int X11DRV_DIB_GetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
2794 int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
2795 XImage *bmpImage;
2797 wine_tsx11_lock();
2798 if (descr->image)
2799 bmpImage = descr->image;
2800 else {
2801 bmpImage = XCreateImage( display, X11DRV_GetVisual(), descr->depth, ZPixmap, 0, NULL,
2802 descr->infoWidth, lines, 32, 0 );
2803 bmpImage->data = calloc( lines, bmpImage->bytes_per_line );
2804 if(bmpImage->data == NULL) {
2805 ERR("Out of memory!\n");
2806 XDestroyImage( bmpImage );
2807 wine_tsx11_unlock();
2808 return lines;
2812 TRACE("XGetSubImage(%p,%ld,%d,%d,%d,%d,%ld,%d,%p,%d,%d)\n",
2813 display, descr->drawable, descr->xSrc, descr->ySrc, descr->width,
2814 lines, AllPlanes, ZPixmap, bmpImage, descr->xDest, descr->yDest);
2815 XGetSubImage( display, descr->drawable, descr->xSrc, descr->ySrc,
2816 descr->width, lines, AllPlanes, ZPixmap,
2817 bmpImage, descr->xDest, descr->yDest );
2819 /* Transfer the pixels */
2820 switch(descr->infoBpp)
2822 case 1:
2823 X11DRV_DIB_GetImageBits_1( descr->lines,(LPVOID)descr->bits,
2824 descr->infoWidth, descr->width,
2825 descr->colorMap, descr->palentry,
2826 bmpImage, descr->dibpitch );
2827 break;
2829 case 4:
2830 if (descr->compression)
2831 FIXME("Compression not yet supported!\n");
2832 else
2833 X11DRV_DIB_GetImageBits_4( descr->lines,(LPVOID)descr->bits,
2834 descr->infoWidth, descr->width,
2835 descr->colorMap, descr->palentry,
2836 bmpImage, descr->dibpitch );
2837 break;
2839 case 8:
2840 if (descr->compression)
2841 FIXME("Compression not yet supported!\n");
2842 else
2843 X11DRV_DIB_GetImageBits_8( descr->lines, (LPVOID)descr->bits,
2844 descr->infoWidth, descr->width,
2845 descr->colorMap, descr->palentry,
2846 bmpImage, descr->dibpitch );
2847 break;
2848 case 15:
2849 case 16:
2850 X11DRV_DIB_GetImageBits_16( descr->lines, (LPVOID)descr->bits,
2851 descr->infoWidth,descr->width,
2852 descr->palentry,
2853 descr->rMask, descr->gMask, descr->bMask,
2854 bmpImage, descr->dibpitch );
2855 break;
2857 case 24:
2858 X11DRV_DIB_GetImageBits_24( descr->lines, (LPVOID)descr->bits,
2859 descr->infoWidth,descr->width,
2860 descr->palentry, bmpImage, descr->dibpitch);
2861 break;
2863 case 32:
2864 X11DRV_DIB_GetImageBits_32( descr->lines, (LPVOID)descr->bits,
2865 descr->infoWidth, descr->width,
2866 descr->palentry, bmpImage, descr->dibpitch);
2867 break;
2869 default:
2870 WARN("(%d): Invalid depth\n", descr->infoBpp );
2871 break;
2874 if (!descr->image) XDestroyImage( bmpImage );
2875 wine_tsx11_unlock();
2876 return lines;
2879 /*************************************************************************
2880 * X11DRV_SetDIBitsToDevice
2883 INT X11DRV_SetDIBitsToDevice( DC *dc, INT xDest, INT yDest, DWORD cx,
2884 DWORD cy, INT xSrc, INT ySrc,
2885 UINT startscan, UINT lines, LPCVOID bits,
2886 const BITMAPINFO *info, UINT coloruse )
2888 X11DRV_DIB_IMAGEBITS_DESCR descr;
2889 DWORD width, oldcy = cy;
2890 INT result;
2891 int height, tmpheight;
2892 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
2895 if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height,
2896 &descr.infoBpp, &descr.compression ) == -1)
2897 return 0;
2898 tmpheight = height;
2899 if (height < 0) height = -height;
2900 if (!lines || (startscan >= height)) return 0;
2901 if (startscan + lines > height) lines = height - startscan;
2902 if (ySrc < startscan) ySrc = startscan;
2903 else if (ySrc >= startscan + lines) return 0;
2904 if (xSrc >= width) return 0;
2905 if (ySrc + cy >= startscan + lines) cy = startscan + lines - ySrc;
2906 if (xSrc + cx >= width) cx = width - xSrc;
2907 if (!cx || !cy) return 0;
2909 X11DRV_SetupGCForText( dc ); /* To have the correct colors */
2910 TSXSetFunction(display, physDev->gc, X11DRV_XROPfunction[dc->ROPmode-1]);
2912 switch (descr.infoBpp)
2914 case 1:
2915 case 4:
2916 case 8:
2917 descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap(
2918 coloruse == DIB_PAL_COLORS ? dc : NULL, coloruse,
2919 dc->bitsPerPixel, info, &descr.nColorMap );
2920 if (!descr.colorMap) return 0;
2921 descr.rMask = descr.gMask = descr.bMask = 0;
2922 break;
2923 case 15:
2924 case 16:
2925 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
2926 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x03e0;
2927 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x001f;
2928 descr.colorMap = 0;
2929 break;
2931 case 24:
2932 descr.rMask = descr.gMask = descr.bMask = 0;
2933 descr.colorMap = 0;
2934 break;
2936 case 32:
2937 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
2938 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0xff00;
2939 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0xff;
2940 descr.colorMap = 0;
2941 break;
2944 descr.dc = dc;
2945 descr.bits = bits;
2946 descr.image = NULL;
2947 descr.palentry = NULL;
2948 descr.lines = tmpheight >= 0 ? lines : -lines;
2949 descr.infoWidth = width;
2950 descr.depth = dc->bitsPerPixel;
2951 descr.drawable = physDev->drawable;
2952 descr.gc = physDev->gc;
2953 descr.xSrc = xSrc;
2954 descr.ySrc = tmpheight >= 0 ? lines-(ySrc-startscan)-cy+(oldcy-cy)
2955 : ySrc - startscan;
2956 descr.xDest = dc->DCOrgX + XLPTODP( dc, xDest );
2957 descr.yDest = dc->DCOrgY + YLPTODP( dc, yDest ) +
2958 (tmpheight >= 0 ? oldcy-cy : 0);
2959 descr.width = cx;
2960 descr.height = cy;
2961 descr.useShm = FALSE;
2962 descr.dibpitch = ((width * descr.infoBpp + 31) &~31) / 8;
2964 result = X11DRV_DIB_SetImageBits( &descr );
2966 if (descr.infoBpp <= 8)
2967 HeapFree(GetProcessHeap(), 0, descr.colorMap);
2968 return result;
2971 /***********************************************************************
2972 * X11DRV_DIB_SetDIBits
2974 INT X11DRV_DIB_SetDIBits(
2975 BITMAPOBJ *bmp, DC *dc, UINT startscan,
2976 UINT lines, LPCVOID bits, const BITMAPINFO *info,
2977 UINT coloruse, HBITMAP hbitmap)
2979 X11DRV_DIB_IMAGEBITS_DESCR descr;
2980 int height, tmpheight;
2981 INT result;
2983 descr.dc = dc;
2985 if (DIB_GetBitmapInfo( &info->bmiHeader, &descr.infoWidth, &height,
2986 &descr.infoBpp, &descr.compression ) == -1)
2987 return 0;
2989 tmpheight = height;
2990 if (height < 0) height = -height;
2991 if (!lines || (startscan >= height))
2992 return 0;
2994 if (startscan + lines > height) lines = height - startscan;
2996 switch (descr.infoBpp)
2998 case 1:
2999 case 4:
3000 case 8:
3001 descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap(
3002 coloruse == DIB_PAL_COLORS ? descr.dc : NULL, coloruse,
3003 bmp->bitmap.bmBitsPixel,
3004 info, &descr.nColorMap );
3005 if (!descr.colorMap) return 0;
3006 descr.rMask = descr.gMask = descr.bMask = 0;
3007 break;
3008 case 15:
3009 case 16:
3010 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
3011 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x03e0;
3012 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x001f;
3013 descr.colorMap = 0;
3014 break;
3016 case 24:
3017 descr.rMask = descr.gMask = descr.bMask = 0;
3018 descr.colorMap = 0;
3019 break;
3021 case 32:
3022 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
3023 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0xff00;
3024 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0xff;
3025 descr.colorMap = 0;
3026 break;
3028 default: break;
3031 /* HACK for now */
3032 if(!bmp->physBitmap)
3033 X11DRV_CreateBitmap(hbitmap);
3035 descr.bits = bits;
3036 descr.image = NULL;
3037 descr.palentry = NULL;
3038 descr.lines = tmpheight >= 0 ? lines : -lines;
3039 descr.depth = bmp->bitmap.bmBitsPixel;
3040 descr.drawable = (Pixmap)bmp->physBitmap;
3041 descr.gc = BITMAP_GC(bmp);
3042 descr.xSrc = 0;
3043 descr.ySrc = 0;
3044 descr.xDest = 0;
3045 descr.yDest = height - startscan - lines;
3046 descr.width = bmp->bitmap.bmWidth;
3047 descr.height = lines;
3048 descr.useShm = FALSE;
3049 descr.dibpitch = ((descr.infoWidth * descr.infoBpp + 31) &~31) / 8;
3050 result = X11DRV_DIB_SetImageBits( &descr );
3052 if (descr.colorMap) HeapFree(GetProcessHeap(), 0, descr.colorMap);
3054 return result;
3057 /***********************************************************************
3058 * X11DRV_DIB_GetDIBits
3060 INT X11DRV_DIB_GetDIBits(
3061 BITMAPOBJ *bmp, DC *dc, UINT startscan,
3062 UINT lines, LPVOID bits, BITMAPINFO *info,
3063 UINT coloruse, HBITMAP hbitmap)
3065 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
3066 X11DRV_DIB_IMAGEBITS_DESCR descr;
3067 PALETTEOBJ * palette;
3068 int height;
3070 TRACE("%u scanlines of (%i,%i) -> (%i,%i) starting from %u\n",
3071 lines, bmp->bitmap.bmWidth, bmp->bitmap.bmHeight,
3072 (int)info->bmiHeader.biWidth, (int)info->bmiHeader.biHeight,
3073 startscan );
3075 if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->hPalette, PALETTE_MAGIC )))
3076 return 0;
3078 if( lines > bmp->bitmap.bmHeight ) lines = bmp->bitmap.bmHeight;
3080 height = info->bmiHeader.biHeight;
3081 if (height < 0) height = -height;
3082 if( lines > height ) lines = height;
3083 /* Top-down images have a negative biHeight, the scanlines of theses images
3084 * were inverted in X11DRV_DIB_GetImageBits_xx
3085 * To prevent this we simply change the sign of lines
3086 * (the number of scan lines to copy).
3087 * Negative lines are correctly handled by X11DRV_DIB_GetImageBits_xx.
3089 if( info->bmiHeader.biHeight < 0 && lines > 0) lines = -lines;
3091 if( startscan >= bmp->bitmap.bmHeight )
3093 lines = 0;
3094 goto done;
3097 if (DIB_GetBitmapInfo( &info->bmiHeader, &descr.infoWidth, &descr.lines,
3098 &descr.infoBpp, &descr.compression ) == -1)
3100 lines = 0;
3101 goto done;
3104 switch (descr.infoBpp)
3106 case 1:
3107 case 4:
3108 case 8:
3109 case 24:
3110 descr.rMask = descr.gMask = descr.bMask = 0;
3111 break;
3112 case 15:
3113 case 16:
3114 descr.rMask = 0x7c00;
3115 descr.gMask = 0x03e0;
3116 descr.bMask = 0x001f;
3117 break;
3119 case 32:
3120 descr.rMask = 0xff0000;
3121 descr.gMask = 0xff00;
3122 descr.bMask = 0xff;
3123 break;
3126 /* Hack for now */
3127 if(!bmp->physBitmap)
3128 X11DRV_CreateBitmap(hbitmap);
3131 descr.dc = dc;
3132 descr.palentry = palette->logpalette.palPalEntry;
3133 descr.bits = bits;
3134 descr.image = NULL;
3135 descr.lines = lines;
3136 descr.depth = bmp->bitmap.bmBitsPixel;
3137 descr.drawable = (Pixmap)bmp->physBitmap;
3138 descr.gc = BITMAP_GC(bmp);
3139 descr.width = bmp->bitmap.bmWidth;
3140 descr.height = bmp->bitmap.bmHeight;
3141 descr.colorMap = info->bmiColors;
3142 descr.xDest = 0;
3143 descr.yDest = 0;
3144 descr.xSrc = 0;
3146 if (descr.lines > 0)
3148 descr.ySrc = (descr.height-1) - (startscan + (lines-1));
3150 else
3152 descr.ySrc = startscan;
3154 #ifdef HAVE_LIBXXSHM
3155 descr.useShm = dib ? (dib->shminfo.shmid != -1) : FALSE;
3156 #else
3157 descr.useShm = FALSE;
3158 #endif
3159 descr.dibpitch = dib ? (dib->dibSection.dsBm.bmWidthBytes)
3160 : (((descr.infoWidth * descr.infoBpp + 31) &~31) / 8);
3162 X11DRV_DIB_GetImageBits( &descr );
3164 if(info->bmiHeader.biSizeImage == 0) /* Fill in biSizeImage */
3165 info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(
3166 info->bmiHeader.biWidth,
3167 info->bmiHeader.biHeight,
3168 info->bmiHeader.biBitCount );
3170 info->bmiHeader.biCompression = 0;
3171 if (descr.compression == BI_BITFIELDS)
3173 *(DWORD *)info->bmiColors = descr.rMask;
3174 *((DWORD *)info->bmiColors+1) = descr.gMask;
3175 *((DWORD *)info->bmiColors+2) = descr.bMask;
3178 done:
3179 GDI_ReleaseObj( dc->hPalette );
3181 return lines;
3184 /***********************************************************************
3185 * DIB_DoProtectDIBSection
3187 static void X11DRV_DIB_DoProtectDIBSection( BITMAPOBJ *bmp, DWORD new_prot )
3189 DIBSECTION *dib = bmp->dib;
3190 INT effHeight = dib->dsBm.bmHeight >= 0? dib->dsBm.bmHeight
3191 : -dib->dsBm.bmHeight;
3192 /* use the biSizeImage data as the memory size only if we're dealing with a
3193 compressed image where the value is set. Otherwise, calculate based on
3194 width * height */
3195 INT totalSize = dib->dsBmih.biSizeImage && dib->dsBmih.biCompression != BI_RGB
3196 ? dib->dsBmih.biSizeImage
3197 : dib->dsBm.bmWidthBytes * effHeight;
3198 DWORD old_prot;
3200 VirtualProtect(dib->dsBm.bmBits, totalSize, new_prot, &old_prot);
3201 TRACE("Changed protection from %ld to %ld\n", old_prot, new_prot);
3204 /***********************************************************************
3205 * X11DRV_DIB_DoUpdateDIBSection
3207 static void X11DRV_DIB_DoCopyDIBSection(BITMAPOBJ *bmp, BOOL toDIB,
3208 void *colorMap, int nColorMap,
3209 Drawable dest,
3210 DWORD xSrc, DWORD ySrc,
3211 DWORD xDest, DWORD yDest,
3212 DWORD width, DWORD height)
3214 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
3215 X11DRV_DIB_IMAGEBITS_DESCR descr;
3217 if (DIB_GetBitmapInfo( &dib->dibSection.dsBmih, &descr.infoWidth, &descr.lines,
3218 &descr.infoBpp, &descr.compression ) == -1)
3219 return;
3221 descr.dc = NULL;
3222 descr.palentry = NULL;
3223 descr.image = dib->image;
3224 descr.colorMap = colorMap;
3225 descr.nColorMap = nColorMap;
3226 descr.bits = dib->dibSection.dsBm.bmBits;
3227 descr.depth = bmp->bitmap.bmBitsPixel;
3229 switch (descr.infoBpp)
3231 case 1:
3232 case 4:
3233 case 8:
3234 case 24:
3235 descr.rMask = descr.gMask = descr.bMask = 0;
3236 break;
3237 case 15:
3238 case 16:
3239 descr.rMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[0] : 0x7c00;
3240 descr.gMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[1] : 0x03e0;
3241 descr.bMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[2] : 0x001f;
3242 break;
3244 case 32:
3245 descr.rMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[0] : 0xff;
3246 descr.gMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[1] : 0xff00;
3247 descr.bMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[2] : 0xff0000;
3248 break;
3251 /* Hack for now */
3252 descr.drawable = dest;
3253 descr.gc = BITMAP_GC(bmp);
3254 descr.xSrc = xSrc;
3255 descr.ySrc = ySrc;
3256 descr.xDest = xDest;
3257 descr.yDest = yDest;
3258 descr.width = width;
3259 descr.height = height;
3260 #ifdef HAVE_LIBXXSHM
3261 descr.useShm = (dib->shminfo.shmid != -1);
3262 #else
3263 descr.useShm = FALSE;
3264 #endif
3265 descr.dibpitch = dib->dibSection.dsBm.bmWidthBytes;
3267 if (toDIB)
3269 TRACE("Copying from Pixmap to DIB bits\n");
3270 X11DRV_DIB_GetImageBits( &descr );
3272 else
3274 TRACE("Copying from DIB bits to Pixmap\n");
3275 X11DRV_DIB_SetImageBits( &descr );
3279 /***********************************************************************
3280 * X11DRV_DIB_CopyDIBSection
3282 void X11DRV_DIB_CopyDIBSection(DC *dcSrc, DC *dcDst,
3283 DWORD xSrc, DWORD ySrc,
3284 DWORD xDest, DWORD yDest,
3285 DWORD width, DWORD height)
3287 BITMAPOBJ *bmp;
3288 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dcDst->physDev;
3289 int nColorMap = 0, *colorMap = NULL, aColorMap = FALSE;
3291 TRACE("(%p,%p,%ld,%ld,%ld,%ld,%ld,%ld)\n", dcSrc, dcDst,
3292 xSrc, ySrc, xDest, yDest, width, height);
3293 /* this function is meant as an optimization for BitBlt,
3294 * not to be called otherwise */
3295 if (!(dcSrc->flags & DC_MEMORY)) {
3296 ERR("called for non-memory source DC!?\n");
3297 return;
3300 bmp = (BITMAPOBJ *)GDI_GetObjPtr( dcSrc->hBitmap, BITMAP_MAGIC );
3301 if (!(bmp && bmp->dib)) {
3302 ERR("called for non-DIBSection!?\n");
3303 GDI_ReleaseObj( dcSrc->hBitmap );
3304 return;
3306 /* while BitBlt should already have made sure we only get
3307 * positive values, we should check for oversize values */
3308 if ((xSrc < bmp->bitmap.bmWidth) &&
3309 (ySrc < bmp->bitmap.bmHeight)) {
3310 if (xSrc + width > bmp->bitmap.bmWidth)
3311 width = bmp->bitmap.bmWidth - xSrc;
3312 if (ySrc + height > bmp->bitmap.bmHeight)
3313 height = bmp->bitmap.bmHeight - ySrc;
3314 /* if the source bitmap is 8bpp or less, we're supposed to use the
3315 * DC's palette for color conversion (not the DIB color table) */
3316 if (bmp->dib->dsBm.bmBitsPixel <= 8) {
3317 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
3318 if ((!dcSrc->hPalette) ||
3319 (dcSrc->hPalette == GetStockObject(DEFAULT_PALETTE))) {
3320 /* HACK: no palette has been set in the source DC,
3321 * use the DIB colormap instead - this is necessary in some
3322 * cases since we need to do depth conversion in some places
3323 * where real Windows can just copy data straight over */
3324 colorMap = dib->colorMap;
3325 nColorMap = dib->nColorMap;
3326 } else {
3327 colorMap = X11DRV_DIB_BuildColorMap( dcSrc, (WORD)-1,
3328 bmp->dib->dsBm.bmBitsPixel,
3329 (BITMAPINFO*)&(bmp->dib->dsBmih),
3330 &nColorMap );
3331 if (colorMap) aColorMap = TRUE;
3334 /* perform the copy */
3335 X11DRV_DIB_DoCopyDIBSection(bmp, FALSE, colorMap, nColorMap,
3336 physDev->drawable, xSrc, ySrc, xDest, yDest,
3337 width, height);
3338 /* free color mapping */
3339 if (aColorMap)
3340 HeapFree(GetProcessHeap(), 0, colorMap);
3342 GDI_ReleaseObj( dcSrc->hBitmap );
3345 /***********************************************************************
3346 * X11DRV_DIB_DoUpdateDIBSection
3348 static void X11DRV_DIB_DoUpdateDIBSection(BITMAPOBJ *bmp, BOOL toDIB)
3350 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
3351 X11DRV_DIB_DoCopyDIBSection(bmp, toDIB, dib->colorMap, dib->nColorMap,
3352 (Drawable)bmp->physBitmap, 0, 0, 0, 0,
3353 bmp->bitmap.bmWidth, bmp->bitmap.bmHeight);
3356 /***********************************************************************
3357 * X11DRV_DIB_FaultHandler
3359 static BOOL X11DRV_DIB_FaultHandler( LPVOID res, LPCVOID addr )
3361 BITMAPOBJ *bmp;
3362 INT state;
3364 bmp = (BITMAPOBJ *)GDI_GetObjPtr( (HBITMAP)res, BITMAP_MAGIC );
3365 if (!bmp) return FALSE;
3367 state = X11DRV_DIB_Lock(bmp, DIB_Status_None, FALSE);
3368 if (state != DIB_Status_InSync) {
3369 /* no way to tell whether app needs read or write yet,
3370 * try read first */
3371 X11DRV_DIB_Coerce(bmp, DIB_Status_InSync, FALSE);
3372 } else {
3373 /* hm, apparently the app must have write access */
3374 X11DRV_DIB_Coerce(bmp, DIB_Status_AppMod, FALSE);
3376 X11DRV_DIB_Unlock(bmp, TRUE);
3378 GDI_ReleaseObj( (HBITMAP)res );
3379 return TRUE;
3382 /***********************************************************************
3383 * X11DRV_DIB_Coerce
3385 INT X11DRV_DIB_Coerce(BITMAPOBJ *bmp, INT req, BOOL lossy)
3387 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
3388 INT ret = DIB_Status_None;
3390 if (dib) {
3391 EnterCriticalSection(&(dib->lock));
3392 ret = dib->status;
3393 switch (req) {
3394 case DIB_Status_GdiMod:
3395 /* GDI access - request to draw on pixmap */
3396 switch (dib->status)
3398 default:
3399 case DIB_Status_None:
3400 dib->p_status = DIB_Status_GdiMod;
3401 X11DRV_DIB_DoUpdateDIBSection( bmp, FALSE );
3402 break;
3404 case DIB_Status_GdiMod:
3405 TRACE("GdiMod requested in status GdiMod\n" );
3406 break;
3408 case DIB_Status_InSync:
3409 TRACE("GdiMod requested in status InSync\n" );
3410 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
3411 dib->status = DIB_Status_GdiMod;
3412 dib->p_status = DIB_Status_InSync;
3413 break;
3415 case DIB_Status_AuxMod:
3416 TRACE("GdiMod requested in status AuxMod\n" );
3417 if (lossy) dib->status = DIB_Status_GdiMod;
3418 else (*dib->copy_aux)(dib->aux_ctx, DIB_Status_GdiMod);
3419 dib->p_status = DIB_Status_AuxMod;
3420 if (dib->status != DIB_Status_AppMod) {
3421 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
3422 break;
3424 /* fall through if copy_aux() had to change to AppMod state */
3426 case DIB_Status_AppMod:
3427 TRACE("GdiMod requested in status AppMod\n" );
3428 if (!lossy) {
3429 /* make it readonly to avoid app changing data while we copy */
3430 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
3431 X11DRV_DIB_DoUpdateDIBSection( bmp, FALSE );
3433 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
3434 dib->p_status = DIB_Status_AppMod;
3435 dib->status = DIB_Status_GdiMod;
3436 break;
3438 break;
3440 case DIB_Status_InSync:
3441 /* App access - request access to read DIB surface */
3442 /* (typically called from signal handler) */
3443 switch (dib->status)
3445 default:
3446 case DIB_Status_None:
3447 /* shouldn't happen from signal handler */
3448 break;
3450 case DIB_Status_AuxMod:
3451 TRACE("InSync requested in status AuxMod\n" );
3452 if (lossy) dib->status = DIB_Status_InSync;
3453 else {
3454 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
3455 (*dib->copy_aux)(dib->aux_ctx, DIB_Status_InSync);
3457 if (dib->status != DIB_Status_GdiMod) {
3458 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
3459 break;
3461 /* fall through if copy_aux() had to change to GdiMod state */
3463 case DIB_Status_GdiMod:
3464 TRACE("InSync requested in status GdiMod\n" );
3465 if (!lossy) {
3466 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
3467 X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
3469 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
3470 dib->status = DIB_Status_InSync;
3471 break;
3473 case DIB_Status_InSync:
3474 TRACE("InSync requested in status InSync\n" );
3475 /* shouldn't happen from signal handler */
3476 break;
3478 case DIB_Status_AppMod:
3479 TRACE("InSync requested in status AppMod\n" );
3480 /* no reason to do anything here, and this
3481 * shouldn't happen from signal handler */
3482 break;
3484 break;
3486 case DIB_Status_AppMod:
3487 /* App access - request access to write DIB surface */
3488 /* (typically called from signal handler) */
3489 switch (dib->status)
3491 default:
3492 case DIB_Status_None:
3493 /* shouldn't happen from signal handler */
3494 break;
3496 case DIB_Status_AuxMod:
3497 TRACE("AppMod requested in status AuxMod\n" );
3498 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
3499 if (lossy) dib->status = DIB_Status_AppMod;
3500 else (*dib->copy_aux)(dib->aux_ctx, DIB_Status_AppMod);
3501 if (dib->status != DIB_Status_GdiMod)
3502 break;
3503 /* fall through if copy_aux() had to change to GdiMod state */
3505 case DIB_Status_GdiMod:
3506 TRACE("AppMod requested in status GdiMod\n" );
3507 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
3508 if (!lossy) X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
3509 dib->status = DIB_Status_AppMod;
3510 break;
3512 case DIB_Status_InSync:
3513 TRACE("AppMod requested in status InSync\n" );
3514 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
3515 dib->status = DIB_Status_AppMod;
3516 break;
3518 case DIB_Status_AppMod:
3519 TRACE("AppMod requested in status AppMod\n" );
3520 /* shouldn't happen from signal handler */
3521 break;
3523 break;
3525 case DIB_Status_AuxMod:
3526 if (dib->status == DIB_Status_None) {
3527 dib->p_status = req;
3528 } else {
3529 if (dib->status != DIB_Status_AuxMod)
3530 dib->p_status = dib->status;
3531 dib->status = DIB_Status_AuxMod;
3533 break;
3534 /* it is up to the caller to do the copy/conversion, probably
3535 * using the return value to decide where to copy from */
3537 LeaveCriticalSection(&(dib->lock));
3539 return ret;
3542 /***********************************************************************
3543 * X11DRV_DIB_Lock
3545 INT X11DRV_DIB_Lock(BITMAPOBJ *bmp, INT req, BOOL lossy)
3547 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
3548 INT ret = DIB_Status_None;
3550 if (dib) {
3551 TRACE("Locking %p from thread %08lx\n", bmp, GetCurrentThreadId());
3552 EnterCriticalSection(&(dib->lock));
3553 ret = dib->status;
3554 if (req != DIB_Status_None)
3555 X11DRV_DIB_Coerce(bmp, req, lossy);
3557 return ret;
3560 /***********************************************************************
3561 * X11DRV_DIB_Unlock
3563 void X11DRV_DIB_Unlock(BITMAPOBJ *bmp, BOOL commit)
3565 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
3567 if (dib) {
3568 switch (dib->status)
3570 default:
3571 case DIB_Status_None:
3572 /* in case anyone is wondering, this is the "signal handler doesn't
3573 * work" case, where we always have to be ready for app access */
3574 if (commit) {
3575 switch (dib->p_status)
3577 case DIB_Status_AuxMod:
3578 TRACE("Unlocking and syncing from AuxMod\n" );
3579 (*dib->copy_aux)(dib->aux_ctx, DIB_Status_AppMod);
3580 if (dib->status != DIB_Status_None) {
3581 dib->p_status = dib->status;
3582 dib->status = DIB_Status_None;
3584 if (dib->p_status != DIB_Status_GdiMod)
3585 break;
3586 /* fall through if copy_aux() had to change to GdiMod state */
3588 case DIB_Status_GdiMod:
3589 TRACE("Unlocking and syncing from GdiMod\n" );
3590 X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
3591 break;
3593 default:
3594 TRACE("Unlocking without needing to sync\n" );
3595 break;
3598 else TRACE("Unlocking with no changes\n");
3599 dib->p_status = DIB_Status_None;
3600 break;
3602 case DIB_Status_GdiMod:
3603 TRACE("Unlocking in status GdiMod\n" );
3604 /* DIB was protected in Coerce */
3605 if (!commit) {
3606 /* no commit, revert to InSync if applicable */
3607 if ((dib->p_status == DIB_Status_InSync) ||
3608 (dib->p_status == DIB_Status_AppMod)) {
3609 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
3610 dib->status = DIB_Status_InSync;
3613 break;
3615 case DIB_Status_InSync:
3616 TRACE("Unlocking in status InSync\n" );
3617 /* DIB was already protected in Coerce */
3618 break;
3620 case DIB_Status_AppMod:
3621 TRACE("Unlocking in status AppMod\n" );
3622 /* DIB was already protected in Coerce */
3623 /* this case is ordinary only called from the signal handler,
3624 * so we don't bother to check for !commit */
3625 break;
3627 case DIB_Status_AuxMod:
3628 TRACE("Unlocking in status AuxMod\n" );
3629 if (commit) {
3630 /* DIB may need protection now */
3631 if ((dib->p_status == DIB_Status_InSync) ||
3632 (dib->p_status == DIB_Status_AppMod))
3633 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
3634 } else {
3635 /* no commit, revert to previous state */
3636 if (dib->p_status != DIB_Status_None)
3637 dib->status = dib->p_status;
3638 /* no protections changed */
3640 dib->p_status = DIB_Status_None;
3641 break;
3643 LeaveCriticalSection(&(dib->lock));
3644 TRACE("Unlocked %p\n", bmp);
3648 /***********************************************************************
3649 * X11DRV_CoerceDIBSection2
3651 INT X11DRV_CoerceDIBSection2(HBITMAP hBmp, INT req, BOOL lossy)
3653 BITMAPOBJ *bmp;
3654 INT ret;
3656 bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
3657 if (!bmp) return DIB_Status_None;
3658 ret = X11DRV_DIB_Coerce(bmp, req, lossy);
3659 GDI_ReleaseObj( hBmp );
3660 return ret;
3663 /***********************************************************************
3664 * X11DRV_LockDIBSection2
3666 INT X11DRV_LockDIBSection2(HBITMAP hBmp, INT req, BOOL lossy)
3668 BITMAPOBJ *bmp;
3669 INT ret;
3671 bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
3672 if (!bmp) return DIB_Status_None;
3673 ret = X11DRV_DIB_Lock(bmp, req, lossy);
3674 GDI_ReleaseObj( hBmp );
3675 return ret;
3678 /***********************************************************************
3679 * X11DRV_UnlockDIBSection2
3681 void X11DRV_UnlockDIBSection2(HBITMAP hBmp, BOOL commit)
3683 BITMAPOBJ *bmp;
3685 bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
3686 if (!bmp) return;
3687 X11DRV_DIB_Unlock(bmp, commit);
3688 GDI_ReleaseObj( hBmp );
3691 /***********************************************************************
3692 * X11DRV_CoerceDIBSection
3694 INT X11DRV_CoerceDIBSection(DC *dc, INT req, BOOL lossy)
3696 if (!dc) return DIB_Status_None;
3697 return X11DRV_CoerceDIBSection2( dc->hBitmap, req, lossy );
3700 /***********************************************************************
3701 * X11DRV_LockDIBSection
3703 INT X11DRV_LockDIBSection(DC *dc, INT req, BOOL lossy)
3705 if (!dc) return DIB_Status_None;
3706 if (!(dc->flags & DC_MEMORY)) return DIB_Status_None;
3708 return X11DRV_LockDIBSection2( dc->hBitmap, req, lossy );
3711 /***********************************************************************
3712 * X11DRV_UnlockDIBSection
3714 void X11DRV_UnlockDIBSection(DC *dc, BOOL commit)
3716 if (!dc) return;
3717 if (!(dc->flags & DC_MEMORY)) return;
3719 X11DRV_UnlockDIBSection2( dc->hBitmap, commit );
3722 /***********************************************************************
3723 * X11DRV_DIB_CreateDIBSection16
3725 HBITMAP16 X11DRV_DIB_CreateDIBSection16(
3726 DC *dc, BITMAPINFO *bmi, UINT16 usage,
3727 SEGPTR *bits, HANDLE section,
3728 DWORD offset, DWORD ovr_pitch)
3730 HBITMAP res = X11DRV_DIB_CreateDIBSection(dc, bmi, usage, NULL,
3731 section, offset, ovr_pitch);
3732 if ( res )
3734 BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr(res, BITMAP_MAGIC);
3735 if ( bmp && bmp->dib )
3737 DIBSECTION *dib = bmp->dib;
3738 INT height = dib->dsBm.bmHeight >= 0 ?
3739 dib->dsBm.bmHeight : -dib->dsBm.bmHeight;
3740 /* same as above - only use biSizeImage as the correct size if it a
3741 compressed image and it's currently non-zero. In other cases, use
3742 width * height as the value. */
3743 INT size = dib->dsBmih.biSizeImage && dib->dsBmih.biCompression != BI_RGB
3744 ? dib->dsBmih.biSizeImage
3745 : dib->dsBm.bmWidthBytes * height;
3746 if ( dib->dsBm.bmBits )
3748 ((X11DRV_DIBSECTION *) bmp->dib)->selector =
3749 SELECTOR_AllocBlock( dib->dsBm.bmBits, size, WINE_LDT_FLAGS_DATA );
3751 TRACE("ptr = %p, size =%d, selector = %04x, segptr = %ld\n",
3752 dib->dsBm.bmBits, size, ((X11DRV_DIBSECTION *) bmp->dib)->selector,
3753 MAKESEGPTR(((X11DRV_DIBSECTION *) bmp->dib)->selector, 0));
3754 if ( bits )
3755 *bits = MAKESEGPTR( ((X11DRV_DIBSECTION *) bmp->dib)->selector, 0 );
3757 if (bmp) GDI_ReleaseObj( res );
3760 return res;
3763 /***********************************************************************
3764 * X11DRV_XShmErrorHandler
3767 static int XShmErrorHandler(Display *dpy, XErrorEvent *event)
3769 XShmErrorFlag = 1;
3770 return 0;
3773 /***********************************************************************
3774 * X11DRV_XShmCreateImage
3778 #ifdef HAVE_LIBXXSHM
3779 extern BOOL X11DRV_XShmCreateImage(XImage** image, int width, int height, int bpp,
3780 XShmSegmentInfo* shminfo)
3782 int (*WineXHandler)(Display *, XErrorEvent *);
3784 *image = TSXShmCreateImage(display, X11DRV_GetVisual(), bpp, ZPixmap, NULL, shminfo, width, height);
3785 if( *image != NULL )
3787 wine_tsx11_lock();
3788 shminfo->shmid = shmget(IPC_PRIVATE, (*image)->bytes_per_line * height,
3789 IPC_CREAT|0700);
3790 if( shminfo->shmid != -1 )
3792 shminfo->shmaddr = (*image)->data = shmat(shminfo->shmid, 0, 0);
3793 if( shminfo->shmaddr != (char*)-1 )
3795 shminfo->readOnly = FALSE;
3796 if( TSXShmAttach( display, shminfo ) != 0)
3798 /* Reset the error flag */
3799 XShmErrorFlag = 0;
3800 WineXHandler = XSetErrorHandler(XShmErrorHandler);
3801 XSync( display, 0 );
3803 if (!XShmErrorFlag)
3805 shmctl(shminfo->shmid, IPC_RMID, 0);
3807 XSetErrorHandler(WineXHandler);
3808 wine_tsx11_unlock();
3809 return TRUE; /* Success! */
3811 /* An error occured */
3812 XShmErrorFlag = 0;
3813 XSetErrorHandler(WineXHandler);
3815 shmdt(shminfo->shmaddr);
3817 shmctl(shminfo->shmid, IPC_RMID, 0);
3819 XFlush(display);
3820 XDestroyImage(*image);
3821 wine_tsx11_unlock();
3823 return FALSE;
3825 #endif /* HAVE_LIBXXSHM */
3829 /***********************************************************************
3830 * X11DRV_DIB_CreateDIBSection
3832 HBITMAP X11DRV_DIB_CreateDIBSection(
3833 DC *dc, BITMAPINFO *bmi, UINT usage,
3834 LPVOID *bits, HANDLE section,
3835 DWORD offset, DWORD ovr_pitch)
3837 HBITMAP res = 0;
3838 BITMAPOBJ *bmp = NULL;
3839 X11DRV_DIBSECTION *dib = NULL;
3840 int *colorMap = NULL;
3841 int nColorMap;
3843 /* Fill BITMAP32 structure with DIB data */
3844 BITMAPINFOHEADER *bi = &bmi->bmiHeader;
3845 INT effHeight, totalSize;
3846 BITMAP bm;
3847 LPVOID mapBits = NULL;
3849 TRACE("format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
3850 bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
3851 bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
3853 effHeight = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
3854 bm.bmType = 0;
3855 bm.bmWidth = bi->biWidth;
3856 bm.bmHeight = effHeight;
3857 bm.bmWidthBytes = ovr_pitch ? ovr_pitch
3858 : DIB_GetDIBWidthBytes(bm.bmWidth, bi->biBitCount);
3859 bm.bmPlanes = bi->biPlanes;
3860 bm.bmBitsPixel = bi->biBitCount;
3861 bm.bmBits = NULL;
3863 /* Get storage location for DIB bits. Only use biSizeImage if it's valid and
3864 we're dealing with a compressed bitmap. Otherwise, use width * height. */
3865 totalSize = bi->biSizeImage && bi->biCompression != BI_RGB
3866 ? bi->biSizeImage : bm.bmWidthBytes * effHeight;
3868 if (section)
3870 SYSTEM_INFO SystemInfo;
3871 DWORD mapOffset;
3872 INT mapSize;
3874 GetSystemInfo( &SystemInfo );
3875 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
3876 mapSize = totalSize + (offset - mapOffset);
3877 mapBits = MapViewOfFile( section,
3878 FILE_MAP_ALL_ACCESS,
3880 mapOffset,
3881 mapSize );
3882 bm.bmBits = (char *)mapBits + (offset - mapOffset);
3884 else if (ovr_pitch && offset)
3885 bm.bmBits = (LPVOID) offset;
3886 else {
3887 offset = 0;
3888 bm.bmBits = VirtualAlloc(NULL, totalSize,
3889 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
3892 /* Create Color Map */
3893 if (bm.bmBits && bm.bmBitsPixel <= 8)
3894 colorMap = X11DRV_DIB_BuildColorMap( usage == DIB_PAL_COLORS? dc : NULL,
3895 usage, bm.bmBitsPixel, bmi, &nColorMap );
3897 /* Allocate Memory for DIB and fill structure */
3898 if (bm.bmBits)
3899 dib = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(X11DRV_DIBSECTION));
3900 if (dib)
3902 dib->dibSection.dsBm = bm;
3903 dib->dibSection.dsBmih = *bi;
3904 dib->dibSection.dsBmih.biSizeImage = totalSize;
3906 /* Set dsBitfields values */
3907 if ( usage == DIB_PAL_COLORS || bi->biBitCount <= 8)
3909 dib->dibSection.dsBitfields[0] = dib->dibSection.dsBitfields[1] = dib->dibSection.dsBitfields[2] = 0;
3911 else switch( bi->biBitCount )
3913 case 16:
3914 dib->dibSection.dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors : 0x7c00;
3915 dib->dibSection.dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0x03e0;
3916 dib->dibSection.dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0x001f;
3917 break;
3919 case 24:
3920 dib->dibSection.dsBitfields[0] = 0xff;
3921 dib->dibSection.dsBitfields[1] = 0xff00;
3922 dib->dibSection.dsBitfields[2] = 0xff0000;
3923 break;
3925 case 32:
3926 dib->dibSection.dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors : 0xff;
3927 dib->dibSection.dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0xff00;
3928 dib->dibSection.dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0xff0000;
3929 break;
3931 dib->dibSection.dshSection = section;
3932 dib->dibSection.dsOffset = offset;
3934 dib->status = DIB_Status_None;
3935 dib->selector = 0;
3937 dib->nColorMap = nColorMap;
3938 dib->colorMap = colorMap;
3941 /* Create Device Dependent Bitmap and add DIB pointer */
3942 if (dib)
3944 res = CreateDIBitmap(dc->hSelf, bi, 0, NULL, bmi, usage);
3945 if (res)
3947 bmp = (BITMAPOBJ *) GDI_GetObjPtr(res, BITMAP_MAGIC);
3948 if (bmp)
3950 bmp->dib = (DIBSECTION *) dib;
3951 /* HACK for now */
3952 if(!bmp->physBitmap)
3953 X11DRV_CreateBitmap(res);
3958 /* Create XImage */
3959 if (dib && bmp)
3961 #ifdef HAVE_LIBXXSHM
3962 if (TSXShmQueryExtension(display) &&
3963 X11DRV_XShmCreateImage( &dib->image, bm.bmWidth, effHeight,
3964 bmp->bitmap.bmBitsPixel, &dib->shminfo ) )
3966 ; /* Created Image */
3967 } else {
3968 XCREATEIMAGE( dib->image, bm.bmWidth, effHeight, bmp->bitmap.bmBitsPixel );
3969 dib->shminfo.shmid = -1;
3971 #else
3972 XCREATEIMAGE( dib->image, bm.bmWidth, effHeight, bmp->bitmap.bmBitsPixel );
3973 #endif
3976 /* Clean up in case of errors */
3977 if (!res || !bmp || !dib || !bm.bmBits || (bm.bmBitsPixel <= 8 && !colorMap))
3979 TRACE("got an error res=%08x, bmp=%p, dib=%p, bm.bmBits=%p\n",
3980 res, bmp, dib, bm.bmBits);
3981 if (bm.bmBits)
3983 if (section)
3984 UnmapViewOfFile(mapBits), bm.bmBits = NULL;
3985 else if (!offset)
3986 VirtualFree(bm.bmBits, 0L, MEM_RELEASE), bm.bmBits = NULL;
3989 if (dib && dib->image) { XDestroyImage(dib->image); dib->image = NULL; }
3990 if (colorMap) { HeapFree(GetProcessHeap(), 0, colorMap); colorMap = NULL; }
3991 if (dib) { HeapFree(GetProcessHeap(), 0, dib); dib = NULL; }
3992 if (bmp) { GDI_ReleaseObj(res); bmp = NULL; }
3993 if (res) { DeleteObject(res); res = 0; }
3995 else if (bm.bmBits)
3997 /* Install fault handler, if possible */
3998 InitializeCriticalSection(&(dib->lock));
3999 if (VIRTUAL_SetFaultHandler(bm.bmBits, X11DRV_DIB_FaultHandler, (LPVOID)res))
4001 if (section || offset)
4003 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
4004 if (dib) dib->status = DIB_Status_AppMod;
4006 else
4008 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
4009 if (dib) dib->status = DIB_Status_InSync;
4014 /* Return BITMAP handle and storage location */
4015 if (bmp) GDI_ReleaseObj(res);
4016 if (bm.bmBits && bits) *bits = bm.bmBits;
4017 return res;
4020 /***********************************************************************
4021 * X11DRV_DIB_DeleteDIBSection
4023 void X11DRV_DIB_DeleteDIBSection(BITMAPOBJ *bmp)
4025 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
4027 if (dib->image)
4029 #ifdef HAVE_LIBXXSHM
4030 if (dib->shminfo.shmid != -1)
4032 TSXShmDetach (display, &(dib->shminfo));
4033 XDestroyImage (dib->image);
4034 shmdt (dib->shminfo.shmaddr);
4035 dib->shminfo.shmid = -1;
4037 else
4038 #endif
4039 XDestroyImage( dib->image );
4042 if (dib->colorMap)
4043 HeapFree(GetProcessHeap(), 0, dib->colorMap);
4045 if (dib->selector) SELECTOR_FreeBlock( dib->selector );
4046 DeleteCriticalSection(&(dib->lock));
4049 /***********************************************************************
4050 * X11DRV_DIB_SetDIBColorTable
4052 UINT X11DRV_DIB_SetDIBColorTable(BITMAPOBJ *bmp, DC *dc, UINT start, UINT count, const RGBQUAD *colors)
4054 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
4056 if (dib && dib->colorMap) {
4057 X11DRV_DIB_GenColorMap( dc, dib->colorMap, DIB_RGB_COLORS, dib->dibSection.dsBm.bmBitsPixel,
4058 TRUE, colors, start, count + start );
4059 return count;
4061 return 0;
4064 /***********************************************************************
4065 * X11DRV_DIB_GetDIBColorTable
4067 UINT X11DRV_DIB_GetDIBColorTable(BITMAPOBJ *bmp, DC *dc, UINT start, UINT count, RGBQUAD *colors)
4069 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
4071 if (dib && dib->colorMap) {
4072 int i, end = count + start;
4073 if (end > dib->nColorMap) end = dib->nColorMap;
4074 for (i = start; i < end; i++,colors++) {
4075 COLORREF col = X11DRV_PALETTE_ToLogical( dib->colorMap[i] );
4076 colors->rgbBlue = GetBValue(col);
4077 colors->rgbGreen = GetGValue(col);
4078 colors->rgbRed = GetRValue(col);
4079 colors->rgbReserved = 0;
4081 return end-start;
4083 return 0;
4087 /**************************************************************************
4088 * X11DRV_DIB_CreateDIBFromPixmap
4090 * Allocates a packed DIB and copies the Pixmap data into it.
4091 * If bDeletePixmap is TRUE, the Pixmap passed in is deleted after the conversion.
4093 HGLOBAL X11DRV_DIB_CreateDIBFromPixmap(Pixmap pixmap, HDC hdc, BOOL bDeletePixmap)
4095 HBITMAP hBmp = 0;
4096 BITMAPOBJ *pBmp = NULL;
4097 HGLOBAL hPackedDIB = 0;
4099 /* Allocates an HBITMAP which references the Pixmap passed to us */
4100 hBmp = X11DRV_BITMAP_CreateBitmapHeaderFromPixmap(pixmap);
4101 if (!hBmp)
4103 TRACE("\tCould not create bitmap header for Pixmap\n");
4104 goto END;
4108 * Create a packed DIB from the Pixmap wrapper bitmap created above.
4109 * A packed DIB contains a BITMAPINFO structure followed immediately by
4110 * an optional color palette and the pixel data.
4112 hPackedDIB = DIB_CreateDIBFromBitmap(hdc, hBmp);
4114 /* Get a pointer to the BITMAPOBJ structure */
4115 pBmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
4117 /* We can now get rid of the HBITMAP wrapper we created earlier.
4118 * Note: Simply calling DeleteObject will free the embedded Pixmap as well.
4120 if (!bDeletePixmap)
4122 /* Clear the physBitmap to prevent the Pixmap from being deleted by DeleteObject */
4123 pBmp->physBitmap = NULL;
4124 pBmp->funcs = NULL;
4126 GDI_ReleaseObj( hBmp );
4127 DeleteObject(hBmp);
4129 END:
4130 TRACE("\tReturning packed DIB %x\n", hPackedDIB);
4131 return hPackedDIB;
4135 /**************************************************************************
4136 * X11DRV_DIB_CreatePixmapFromDIB
4138 * Creates a Pixmap from a packed DIB
4140 Pixmap X11DRV_DIB_CreatePixmapFromDIB( HGLOBAL hPackedDIB, HDC hdc )
4142 Pixmap pixmap = None;
4143 HBITMAP hBmp = 0;
4144 BITMAPOBJ *pBmp = NULL;
4145 LPBYTE pPackedDIB = NULL;
4146 LPBITMAPINFO pbmi = NULL;
4147 LPBITMAPINFOHEADER pbmiHeader = NULL;
4148 LPBYTE pbits = NULL;
4150 /* Get a pointer to the packed DIB's data */
4151 pPackedDIB = (LPBYTE)GlobalLock(hPackedDIB);
4152 pbmiHeader = (LPBITMAPINFOHEADER)pPackedDIB;
4153 pbmi = (LPBITMAPINFO)pPackedDIB;
4154 pbits = (LPBYTE)(pPackedDIB
4155 + DIB_BitmapInfoSize( (LPBITMAPINFO)pbmiHeader, DIB_RGB_COLORS ));
4157 /* Create a DDB from the DIB */
4159 hBmp = CreateDIBitmap(hdc,
4160 pbmiHeader,
4161 CBM_INIT,
4162 (LPVOID)pbits,
4163 pbmi,
4164 DIB_RGB_COLORS);
4166 GlobalUnlock(hPackedDIB);
4168 TRACE("CreateDIBitmap returned %x\n", hBmp);
4170 /* Retrieve the internal Pixmap from the DDB */
4172 pBmp = (BITMAPOBJ *) GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
4174 pixmap = (Pixmap)pBmp->physBitmap;
4175 /* clear the physBitmap so that we can steal its pixmap */
4176 pBmp->physBitmap = NULL;
4177 pBmp->funcs = NULL;
4179 /* Delete the DDB we created earlier now that we have stolen its pixmap */
4180 GDI_ReleaseObj( hBmp );
4181 DeleteObject(hBmp);
4183 TRACE("\tReturning Pixmap %ld\n", pixmap);
4184 return pixmap;