Fixed asm() constraints.
[wine/multimedia.git] / graphics / x11drv / dib.c
blobdb8e083b0e3cee212c2f2d72e87969f29b4075db
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 "windef.h"
23 #include "bitmap.h"
24 #include "x11drv.h"
25 #include "debugtools.h"
26 #include "dc.h"
27 #include "color.h"
28 #include "callback.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 /***********************************************************************
41 * X11DRV_DIB_Init
43 BOOL X11DRV_DIB_Init(void)
45 int i;
46 XImage* testimage;
48 for( i = 0; bitmapDepthTable[i]; i++ )
50 testimage = TSXCreateImage(display, X11DRV_GetVisual(),
51 bitmapDepthTable[i], ZPixmap, 0, NULL, 1, 1, 32, 20 );
52 if( testimage ) ximageDepthTable[i] = testimage->bits_per_pixel;
53 else return FALSE;
54 TSXDestroyImage(testimage);
56 return TRUE;
60 /***********************************************************************
61 * X11DRV_DIB_GetXImageWidthBytes
63 * Return the width of an X image in bytes
65 int X11DRV_DIB_GetXImageWidthBytes( int width, int depth )
67 int i;
69 if (!ximageDepthTable[0]) {
70 X11DRV_DIB_Init();
72 for( i = 0; bitmapDepthTable[i] ; i++ )
73 if( bitmapDepthTable[i] == depth )
74 return (4 * ((width * ximageDepthTable[i] + 31)/32));
76 WARN("(%d): Unsupported depth\n", depth );
77 return (4 * width);
80 /***********************************************************************
81 * X11DRV_DIB_BuildColorMap
83 * Build the color map from the bitmap palette. Should not be called
84 * for a >8-bit deep bitmap.
86 int *X11DRV_DIB_BuildColorMap( DC *dc, WORD coloruse, WORD depth,
87 const BITMAPINFO *info, int *nColors )
89 int i, colors;
90 BOOL isInfo;
91 WORD *colorPtr;
92 int *colorMapping;
94 if ((isInfo = (info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))))
96 colors = info->bmiHeader.biClrUsed;
97 if (!colors) colors = 1 << info->bmiHeader.biBitCount;
98 colorPtr = (WORD *)info->bmiColors;
100 else /* assume BITMAPCOREINFO */
102 colors = 1 << ((BITMAPCOREHEADER *)&info->bmiHeader)->bcBitCount;
103 colorPtr = (WORD *)((BITMAPCOREINFO *)info)->bmciColors;
106 if (colors > 256)
108 ERR("called with >256 colors!\n");
109 return NULL;
112 if (!(colorMapping = (int *)HeapAlloc(GetProcessHeap(), 0,
113 colors * sizeof(int) )))
114 return NULL;
116 if (coloruse == DIB_RGB_COLORS)
118 if (isInfo)
120 RGBQUAD * rgb = (RGBQUAD *)colorPtr;
122 if (depth == 1) /* Monochrome */
123 for (i = 0; i < colors; i++, rgb++)
124 colorMapping[i] = (rgb->rgbRed + rgb->rgbGreen +
125 rgb->rgbBlue > 255*3/2);
126 else
127 for (i = 0; i < colors; i++, rgb++)
128 colorMapping[i] = X11DRV_PALETTE_ToPhysical( dc, RGB(rgb->rgbRed,
129 rgb->rgbGreen,
130 rgb->rgbBlue));
132 else
134 RGBTRIPLE * rgb = (RGBTRIPLE *)colorPtr;
136 if (depth == 1) /* Monochrome */
137 for (i = 0; i < colors; i++, rgb++)
138 colorMapping[i] = (rgb->rgbtRed + rgb->rgbtGreen +
139 rgb->rgbtBlue > 255*3/2);
140 else
141 for (i = 0; i < colors; i++, rgb++)
142 colorMapping[i] = X11DRV_PALETTE_ToPhysical( dc, RGB(rgb->rgbtRed,
143 rgb->rgbtGreen,
144 rgb->rgbtBlue));
147 else /* DIB_PAL_COLORS */
149 for (i = 0; i < colors; i++, colorPtr++)
150 colorMapping[i] = X11DRV_PALETTE_ToPhysical( dc, PALETTEINDEX(*colorPtr) );
153 *nColors = colors;
154 return colorMapping;
158 /***********************************************************************
159 * X11DRV_DIB_MapColor
161 int X11DRV_DIB_MapColor( int *physMap, int nPhysMap, int phys )
163 int color;
165 for (color = 0; color < nPhysMap; color++)
166 if (physMap[color] == phys)
167 return color;
169 WARN("Strange color %08x\n", phys);
170 return 0;
174 /*********************************************************************
175 * X11DRV_DIB_GetNearestIndex
177 * Helper for X11DRV_DIB_GetDIBits.
178 * Returns the nearest colour table index for a given RGB.
179 * Nearest is defined by minimizing the sum of the squares.
181 static INT X11DRV_DIB_GetNearestIndex(RGBQUAD *colormap, int numColors, BYTE r, BYTE g, BYTE b)
183 INT i, best = -1, diff, bestdiff = -1;
184 RGBQUAD *color;
186 for(color = colormap, i = 0; i < numColors; color++, i++) {
187 diff = (r - color->rgbRed) * (r - color->rgbRed) +
188 (g - color->rgbGreen) * (g - color->rgbGreen) +
189 (b - color->rgbBlue) * (b - color->rgbBlue);
190 if(diff == 0)
191 return i;
192 if(best == -1 || diff < bestdiff) {
193 best = i;
194 bestdiff = diff;
197 return best;
200 /***********************************************************************
201 * X11DRV_DIB_SetImageBits_1_Line
203 * Handles a single line of 1 bit data.
205 static void X11DRV_DIB_SetImageBits_1_Line(DWORD dstwidth, int left, int *colors,
206 XImage *bmpImage, int h, const BYTE *bits)
208 BYTE pix, extra;
209 DWORD i, x;
211 if((extra = (left & 7)) != 0) {
212 left &= ~7;
213 dstwidth += extra;
216 bits += left >> 3;
218 /* FIXME: should avoid putting x<left pixels (minor speed issue) */
219 for (i = dstwidth/8, x = left; i > 0; i--)
221 pix = *bits++;
222 XPutPixel( bmpImage, x++, h, colors[pix >> 7] );
223 XPutPixel( bmpImage, x++, h, colors[(pix >> 6) & 1] );
224 XPutPixel( bmpImage, x++, h, colors[(pix >> 5) & 1] );
225 XPutPixel( bmpImage, x++, h, colors[(pix >> 4) & 1] );
226 XPutPixel( bmpImage, x++, h, colors[(pix >> 3) & 1] );
227 XPutPixel( bmpImage, x++, h, colors[(pix >> 2) & 1] );
228 XPutPixel( bmpImage, x++, h, colors[(pix >> 1) & 1] );
229 XPutPixel( bmpImage, x++, h, colors[pix & 1] );
231 pix = *bits;
232 switch(dstwidth & 7)
234 case 7: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
235 case 6: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
236 case 5: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
237 case 4: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
238 case 3: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
239 case 2: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
240 case 1: XPutPixel( bmpImage, x++, h, colors[pix >> 7] );
244 /***********************************************************************
245 * X11DRV_DIB_SetImageBits_1
247 * SetDIBits for a 1-bit deep DIB.
249 static void X11DRV_DIB_SetImageBits_1( int lines, const BYTE *srcbits,
250 DWORD srcwidth, DWORD dstwidth, int left,
251 int *colors, XImage *bmpImage )
253 int h;
255 /* 32 bit aligned */
256 DWORD linebytes = ((srcwidth + 31) & ~31) / 8;
258 if (lines > 0) {
259 for (h = lines-1; h >=0; h--) {
260 X11DRV_DIB_SetImageBits_1_Line(dstwidth, left, colors, bmpImage, h,
261 srcbits);
262 srcbits += linebytes;
264 } else {
265 lines = -lines;
266 for (h = 0; h < lines; h++) {
267 X11DRV_DIB_SetImageBits_1_Line(dstwidth, left, colors, bmpImage, h,
268 srcbits);
269 srcbits += linebytes;
274 /***********************************************************************
275 * X11DRV_DIB_GetImageBits_1
277 * GetDIBits for a 1-bit deep DIB.
279 static void X11DRV_DIB_GetImageBits_1( int lines, BYTE *dstbits,
280 DWORD dstwidth, DWORD srcwidth,
281 RGBQUAD *colors, PALETTEENTRY *srccolors,
282 XImage *bmpImage )
284 DWORD x;
285 int h;
286 BYTE *bits;
288 /* 32 bit aligned */
289 DWORD linebytes = ((dstwidth + 31) & ~31) / 8;
291 if (lines < 0 ) {
292 lines = -lines;
293 dstbits = dstbits + linebytes * (lines - 1);
294 linebytes = -linebytes;
297 bits = dstbits;
299 switch(bmpImage->depth) {
301 case 1:
302 /* ==== monochrome bitmap to monochrome dib ==== */
303 case 4:
304 /* ==== 4 colormap bitmap to monochrome dib ==== */
305 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
307 PALETTEENTRY val;
309 for (h = lines - 1; h >= 0; h--) {
310 for (x = 0; x < dstwidth; x++) {
311 val = srccolors[XGetPixel(bmpImage, x, h)];
312 if (!(x&7)) *bits = 0;
313 *bits |= (X11DRV_DIB_GetNearestIndex(colors, 2,
314 val.peRed,
315 val.peGreen,
316 val.peBlue) << (7 - (x & 7)));
317 if ((x&7)==7) bits++;
319 bits = (dstbits += linebytes);
322 else goto notsupported;
324 break;
326 case 8:
327 /* ==== 8 colormap bitmap to monochrome dib ==== */
328 if ( bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
330 BYTE *srcpixel;
331 PALETTEENTRY val;
333 for( h = lines- 1; h >= 0; h-- ) {
334 srcpixel = bmpImage->data + (h*bmpImage->bytes_per_line);
335 for( x = 0; x < dstwidth; x++ ) {
336 if (!(x&7)) *bits = 0;
337 val = srccolors[(int)*srcpixel++];
338 *bits |= ( X11DRV_DIB_GetNearestIndex(colors, 2,
339 val.peRed,
340 val.peGreen,
341 val.peBlue) << (7-(x&7)) );
342 if ((x&7)==7) bits++;
344 bits = (dstbits += linebytes);
347 else goto notsupported;
349 break;
351 case 15:
353 LPWORD srcpixel;
354 WORD val;
356 /* ==== 555 BGR bitmap to monochrome dib ==== */
357 if (bmpImage->red_mask == 0x7c00 && bmpImage->blue_mask == 0x1f)
359 for( h = lines - 1; h >= 0; h--) {
360 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
361 for( x = 0; x < dstwidth; x++) {
362 if (!(x&7)) *bits = 0;
363 val = *srcpixel++;
364 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 2,
365 ((val >> 7) & 0xf8) |
366 ((val >> 12) & 0x7),
367 ((val >> 2) & 0xf8) |
368 ((val >> 7) & 0x3),
369 ((val << 3) & 0xf8) |
370 ((val >> 2) & 0x7) ) << (7-(x&7)) );
371 if ((x&7)==7) bits++;
373 bits = (dstbits += linebytes);
376 /* ==== 555 RGB bitmap to monochrome dib ==== */
377 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0xf800)
379 for( h = lines - 1; h >= 0; h--)
381 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
382 for( x = 0; x < dstwidth; x++) {
383 if (!(x&1)) *bits = 0;
384 val = *srcpixel++;
385 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 2,
386 ((val << 3) & 0xf8) |
387 ((val >> 2) & 0x7),
388 ((val >> 2) & 0xf8) |
389 ((val >> 7) & 0x3),
390 ((val >> 7) & 0xf8) |
391 ((val >> 12) & 0x7) ) << (7-(x&7)) );
392 if ((x&7)==7) bits++;
394 bits = (dstbits += linebytes);
397 else goto notsupported;
399 break;
401 case 16:
403 LPWORD srcpixel;
404 WORD val;
406 /* ==== 565 BGR bitmap to monochrome dib ==== */
407 if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f)
409 for( h = lines - 1; h >= 0; h--)
411 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
412 for( x = 0; x < dstwidth; x++) {
413 if (!(x&7)) *bits = 0;
414 val = *srcpixel++;
415 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 2,
416 ((val >> 8) & 0xf8) |
417 ((val >> 13) & 0x7),
418 ((val >> 3) & 0xfc) |
419 ((val >> 9) & 0x3),
420 ((val << 3) & 0xf8) |
421 ((val >> 2) & 0x7) ) << (7-(x&7)) );
422 if ((x&7)==7) bits++;
424 bits = (dstbits += linebytes);
427 /* ==== 565 RGB bitmap to monochrome dib ==== */
428 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0xf800)
430 for( h = lines - 1; h >= 0; h--)
432 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
433 for( x = 0; x < dstwidth; x++) {
434 if (!(x&7)) *bits = 0;
435 val = *srcpixel++;
436 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 2,
437 ((val << 3) & 0xf8) |
438 ((val >> 2) & 0x7),
439 ((val >> 3) & 0xfc) |
440 ((val >> 9) & 0x3),
441 ((val >> 8) & 0xf8) |
442 ((val >> 13) & 0x7) ) << (7-(x&7)) );
443 if ((x&7)==7) bits++;
445 bits = (dstbits += linebytes);
448 else goto notsupported;
450 break;
452 case 24:
453 case 32:
455 BYTE *srcpixel;
457 /* ==== 24/32 BGR bitmap to monochrome dib ==== */
458 if (bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff)
460 for (h = lines - 1; h >= 0; h--)
462 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
463 for (x = 0; x < dstwidth; x++, srcpixel+=4) {
464 if (!(x&7)) *bits = 0;
465 *bits |= (X11DRV_DIB_GetNearestIndex(colors, 2, srcpixel[2] , srcpixel[1], srcpixel[0]) << (7-(x&7)) );
466 if ((x&7)==7) bits++;
468 bits = (dstbits += linebytes);
471 /* ==== 24/32 RGB bitmap to monochrome dib ==== */
472 else if (bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000)
474 for (h = lines - 1; h >= 0; h--)
476 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
477 for (x = 0; x < dstwidth; x++, srcpixel+=4) {
478 if (!(x & 7)) *bits = 0;
479 *bits |= (X11DRV_DIB_GetNearestIndex(colors, 2, srcpixel[0] , srcpixel[1], srcpixel[2]) << (7-(x&7)) );
480 if ((x & 7) == 7) bits++;
482 bits = (dstbits += linebytes);
485 else goto notsupported;
487 break;
489 default: /* ? bit bmp -> monochrome DIB */
490 notsupported:
492 unsigned long white = (1 << bmpImage->bits_per_pixel) - 1;
494 FIXME("from %d bit bitmap with mask R,G,B %x,%x,%x to 1 bit DIB\n",
495 bmpImage->bits_per_pixel, (int)bmpImage->red_mask,
496 (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
498 for( h = lines - 1; h >= 0; h-- ) {
499 for( x = 0; x < dstwidth; x++ ) {
500 if (!(x&7)) *bits = 0;
501 *bits |= (XGetPixel( bmpImage, x, h) >= white)
502 << (7 - (x&7));
503 if ((x&7)==7) bits++;
505 bits = (dstbits += linebytes);
508 break;
512 /***********************************************************************
513 * X11DRV_DIB_SetImageBits_4
515 * SetDIBits for a 4-bit deep DIB.
517 static void X11DRV_DIB_SetImageBits_4( int lines, const BYTE *srcbits,
518 DWORD srcwidth, DWORD dstwidth, int left,
519 int *colors, XImage *bmpImage )
521 DWORD i, x;
522 int h;
523 const BYTE *bits = srcbits + (left >> 1);
525 /* 32 bit aligned */
526 DWORD linebytes = ((srcwidth+7)&~7)/2;
528 if(left & 1) {
529 left--;
530 dstwidth++;
533 if (lines > 0) {
534 for (h = lines-1; h >= 0; h--) {
535 for (i = dstwidth/2, x = left; i > 0; i--) {
536 BYTE pix = *bits++;
537 XPutPixel( bmpImage, x++, h, colors[pix >> 4] );
538 XPutPixel( bmpImage, x++, h, colors[pix & 0x0f] );
540 if (dstwidth & 1) XPutPixel( bmpImage, x, h, colors[*bits >> 4] );
541 srcbits += linebytes;
542 bits = srcbits + (left >> 1);
544 } else {
545 lines = -lines;
546 for (h = 0; h < lines; h++) {
547 for (i = dstwidth/2, x = left; i > 0; i--) {
548 BYTE pix = *bits++;
549 XPutPixel( bmpImage, x++, h, colors[pix >> 4] );
550 XPutPixel( bmpImage, x++, h, colors[pix & 0x0f] );
552 if (dstwidth & 1) XPutPixel( bmpImage, x, h, colors[*bits >> 4] );
553 srcbits += linebytes;
554 bits = srcbits + (left >> 1);
561 /***********************************************************************
562 * X11DRV_DIB_GetImageBits_4
564 * GetDIBits for a 4-bit deep DIB.
566 static void X11DRV_DIB_GetImageBits_4( int lines, BYTE *dstbits,
567 DWORD srcwidth, DWORD dstwidth,
568 RGBQUAD *colors, PALETTEENTRY *srccolors,
569 XImage *bmpImage )
571 DWORD x;
572 int h;
573 BYTE *bits;
574 LPBYTE srcpixel;
576 /* 32 bit aligned */
577 DWORD linebytes = ((srcwidth+7)&~7)/2;
579 if (lines < 0 )
581 lines = -lines;
582 dstbits = dstbits + ( linebytes * (lines-1) );
583 linebytes = -linebytes;
586 bits = dstbits;
588 switch(bmpImage->depth) {
590 case 1:
591 /* ==== monochrome bitmap to 4 colormap dib ==== */
592 case 4:
593 /* ==== 4 colormap bitmap to 4 colormap dib ==== */
594 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
596 PALETTEENTRY val;
598 for (h = lines-1; h >= 0; h--) {
599 for (x = 0; x < dstwidth; x++) {
600 if (!(x&1)) *bits = 0;
601 val = srccolors[XGetPixel(bmpImage, x, h)];
602 *bits |= (X11DRV_DIB_GetNearestIndex(colors, 16,
603 val.peRed,
604 val.peGreen,
605 val.peBlue) << (4-((x&1)<<2)));
606 if ((x&1)==1) bits++;
608 bits = (dstbits += linebytes);
611 else goto notsupported;
613 break;
615 case 8:
616 /* ==== 8 colormap bitmap to 4 colormap dib ==== */
617 if ( bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
619 PALETTEENTRY val;
621 for( h = lines - 1; h >= 0; h-- ) {
622 srcpixel = bmpImage->data + (h*bmpImage->bytes_per_line);
623 for( x = 0; x < dstwidth; x++ ) {
624 if (!(x&1)) *bits = 0;
625 val = srccolors[(int)*srcpixel++];
626 *bits |= ( X11DRV_DIB_GetNearestIndex(colors, 16,
627 val.peRed,
628 val.peGreen,
629 val.peBlue) << (4*(1-(x&1))) );
630 if ((x&1)==1) bits++;
632 bits = (dstbits += linebytes);
635 else goto notsupported;
637 break;
639 case 15:
641 LPWORD srcpixel;
642 WORD val;
644 /* ==== 555 BGR bitmap to 4 colormap dib ==== */
645 if (bmpImage->red_mask == 0x7c00 && bmpImage->blue_mask == 0x1f)
647 for( h = lines - 1; h >= 0; h--) {
648 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
649 for( x = 0; x < dstwidth; x++) {
650 if (!(x&1)) *bits = 0;
651 val = *srcpixel++;
652 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 16,
653 ((val >> 7) & 0xf8) |
654 ((val >> 12) & 0x7),
655 ((val >> 2) & 0xf8) |
656 ((val >> 7) & 0x3),
657 ((val << 3) & 0xf8) |
658 ((val >> 2) & 0x7) ) << ((1-(x&1))<<2) );
659 if ((x&1)==1) bits++;
661 bits = (dstbits += linebytes);
664 /* ==== 555 RGB bitmap to 4 colormap dib ==== */
665 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0x7c00)
667 for( h = lines - 1; h >= 0; h--)
669 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
670 for( x = 0; x < dstwidth; x++) {
671 if (!(x&1)) *bits = 0;
672 val = *srcpixel++;
673 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 16,
674 ((val << 3) & 0xf8) |
675 ((val >> 2) & 0x7),
676 ((val >> 2) & 0xfc) |
677 ((val >> 7) & 0x3),
678 ((val >> 7) & 0xf8) |
679 ((val >> 12) & 0x7) ) << ((1-(x&1))<<2) );
680 if ((x&1)==1) bits++;
682 bits = (dstbits += linebytes);
685 else goto notsupported;
687 break;
689 case 16:
691 LPWORD srcpixel;
692 WORD val;
694 /* ==== 565 BGR bitmap to 4 colormap dib ==== */
695 if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f)
697 for( h = lines - 1; h >= 0; h--)
699 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
700 for( x = 0; x < dstwidth; x++) {
701 if (!(x&1)) *bits = 0;
702 val = *srcpixel++;
703 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 16,
704 ((val >> 8) & 0xf8) |
705 ((val >> 13) & 0x7),
706 ((val >> 3) & 0xfc) |
707 ((val >> 9) & 0x3),
708 ((val << 3) & 0xf8) |
709 ((val >> 2) & 0x7) ) << ((1-(x&1))<<2) );
710 if ((x&1)==1) bits++;
712 bits = (dstbits += linebytes);
715 /* ==== 565 RGB bitmap to 4 colormap dib ==== */
716 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0xf800)
718 for( h = lines - 1; h >= 0; h--)
720 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
721 for( x = 0; x < dstwidth; x++) {
722 if (!(x&1)) *bits = 0;
723 val = *srcpixel++;
724 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 16,
725 ((val << 3) & 0xf8) |
726 ((val >> 2) & 0x7),
727 ((val >> 3) & 0xfc) |
728 ((val >> 9) & 0x3),
729 ((val >> 8) & 0xf8) |
730 ((val >> 13) & 0x7) ) << ((1-(x&1))<<2) );
731 if ((x&1)==1) bits++;
733 bits = (dstbits += linebytes);
736 else goto notsupported;
738 break;
740 case 24:
741 case 32:
743 BYTE *srcpixel;
745 /* ==== 24/32 BGR bitmap to 4 colormap dib ==== */
746 if (bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff)
748 for (h = lines - 1; h >= 0; h--)
750 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
751 for (x = 0; x < dstwidth; x+=2, srcpixel+=8) /* 2 pixels at a time */
752 *bits++ = (X11DRV_DIB_GetNearestIndex(colors, 16, srcpixel[2] , srcpixel[1], srcpixel[0]) << 4) |
753 X11DRV_DIB_GetNearestIndex(colors, 16, srcpixel[6] , srcpixel[5], srcpixel[4]);
754 bits = (dstbits += linebytes);
757 /* ==== 24/32 RGB bitmap to 4 colormap dib ==== */
758 else if (bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000)
760 for (h = lines - 1; h >= 0; h--)
762 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
763 for (x = 0; x < dstwidth; x+=2, srcpixel+=8) /* 2 pixels at a time */
764 *bits++ = (X11DRV_DIB_GetNearestIndex(colors, 16, srcpixel[0] , srcpixel[1], srcpixel[2]) << 4) |
765 X11DRV_DIB_GetNearestIndex(colors, 16, srcpixel[4] , srcpixel[5], srcpixel[6]);
766 bits = (dstbits += linebytes);
769 else goto notsupported;
771 break;
773 default: /* ? bit bmp -> 4 bit DIB */
774 notsupported:
775 FIXME("from %d bit bitmap with mask R,G,B %x,%x,%x to 4 bit DIB\n",
776 bmpImage->bits_per_pixel, (int)bmpImage->red_mask,
777 (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
778 for (h = lines-1; h >= 0; h--) {
779 for (x = 0; x < dstwidth/2; x++) {
780 *bits++ = (X11DRV_DIB_MapColor((int *)colors, 16,
781 XGetPixel( bmpImage, x++, h )) << 4)
782 | (X11DRV_DIB_MapColor((int *)colors, 16,
783 XGetPixel( bmpImage, x++, h )) & 0x0f);
785 if (dstwidth & 1)
786 *bits = (X11DRV_DIB_MapColor((int *)colors, 16,
787 XGetPixel( bmpImage, x++, h )) << 4);
788 bits = (dstbits += linebytes);
790 break;
794 /***********************************************************************
795 * X11DRV_DIB_SetImageBits_RLE4
797 * SetDIBits for a 4-bit deep compressed DIB.
799 static void X11DRV_DIB_SetImageBits_RLE4( int lines, const BYTE *bits,
800 DWORD width, DWORD dstwidth,
801 int left, int *colors,
802 XImage *bmpImage )
804 int x = 0, c, length;
805 const BYTE *begin = bits;
807 lines--;
809 while ((int)lines >= 0) {
810 length = *bits++;
811 if (length) { /* encoded */
812 c = *bits++;
813 while (length--) {
814 if(x >= width) {
815 x = 0;
816 if(--lines < 0)
817 return;
819 XPutPixel(bmpImage, x++, lines, colors[c >>4]);
820 if (length) {
821 length--;
822 if(x >= width) {
823 x = 0;
824 if(--lines < 0)
825 return;
827 XPutPixel(bmpImage, x++, lines, colors[c & 0xf]);
830 } else {
831 length = *bits++;
832 switch (length) {
833 case 0: /* eol */
834 x = 0;
835 lines--;
836 continue;
838 case 1: /* eopicture */
839 return;
841 case 2: /* delta */
842 x += *bits++;
843 if(x >= width) {
844 FIXME_(x11drv)("x-delta is too large?\n");
845 return;
847 lines -= *bits++;
848 continue;
850 default: /* absolute */
851 while (length--) {
852 c = *bits++;
853 if(x >= width) {
854 x = 0;
855 if(--lines < 0)
856 return;
858 XPutPixel(bmpImage, x++, lines, colors[c >> 4]);
859 if (length) {
860 length--;
861 if(x >= width) {
862 x = 0;
863 if(--lines < 0)
864 return;
866 XPutPixel(bmpImage, x++, lines, colors[c & 0xf]);
869 if ((bits - begin) & 1)
870 bits++;
878 /***********************************************************************
879 * X11DRV_DIB_SetImageBits_8
881 * SetDIBits for an 8-bit deep DIB.
883 static void X11DRV_DIB_SetImageBits_8( int lines, const BYTE *srcbits,
884 DWORD srcwidth, DWORD dstwidth, int left,
885 const int *colors, XImage *bmpImage )
887 DWORD x;
888 int h, color;
889 const BYTE *bits;
891 /* align to 32 bit */
892 DWORD linebytes = (srcwidth + 3) & ~3;
894 dstwidth += left;
896 if (lines < 0 )
898 lines = -lines;
899 srcbits = srcbits + ( linebytes * (lines-1) );
900 linebytes = -linebytes;
903 bits = srcbits + left;
905 switch (bmpImage->depth) {
906 case 15:
907 case 16:
908 #if defined(__i386__) && defined(__GNUC__)
909 /* Some X servers might have 32 bit/ 16bit deep pixel */
910 if (lines && (dstwidth!=left) && (bmpImage->bits_per_pixel == 16))
912 for (h = lines ; h--; ) {
913 int _cl1,_cl2; /* temp outputs for asm below */
914 /* Borrowed from DirectDraw */
915 __asm__ __volatile__(
916 "xor %%eax,%%eax\n"
917 "cld\n"
918 "1:\n"
919 " lodsb\n"
920 " movw (%%edx,%%eax,4),%%ax\n"
921 " stosw\n"
922 " xor %%eax,%%eax\n"
923 " loop 1b\n"
924 :"=S" (bits), "=D" (_cl1), "=c" (_cl2)
925 :"S" (bits),
926 "D" (bmpImage->data+h*bmpImage->bytes_per_line+left*2),
927 "c" (dstwidth-left),
928 "d" (colors)
929 :"eax", "cc", "memory"
931 bits = (srcbits += linebytes) + left;
933 return;
935 break;
936 #endif
937 default:
938 break; /* use slow generic case below */
941 for (h = lines - 1; h >= 0; h--) {
942 for (x = left; x < dstwidth; x++, bits++) {
943 color = colors[*bits];
944 XPutPixel( bmpImage, x, h, colors[*bits] );
946 bits = (srcbits += linebytes) + left;
950 /***********************************************************************
951 * X11DRV_DIB_GetImageBits_8
953 * GetDIBits for an 8-bit deep DIB.
955 static void X11DRV_DIB_GetImageBits_8( int lines, BYTE *dstbits,
956 DWORD srcwidth, DWORD dstwidth,
957 RGBQUAD *colors, PALETTEENTRY *srccolors,
958 XImage *bmpImage )
960 DWORD x;
961 int h;
962 BYTE *bits;
964 /* align to 32 bit */
965 DWORD linebytes = (srcwidth + 3) & ~3;
967 if (lines < 0 )
969 lines = -lines;
970 dstbits = dstbits + ( linebytes * (lines-1) );
971 linebytes = -linebytes;
974 bits = dstbits;
977 Hack for now
978 This condition is true when GetImageBits has been called by UpdateDIBSection.
979 For now, GetNearestIndex is too slow to support 256 colormaps, so we'll just use for
980 for GetDIBits calls. (In somes cases, in a updateDIBSection, the returned colors are bad too)
982 if (!srccolors) goto updatesection;
984 switch(bmpImage->depth) {
986 case 1:
987 /* ==== monochrome bitmap to 8 colormap dib ==== */
988 case 4:
989 /* ==== 4 colormap bitmap to 8 colormap dib ==== */
990 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
992 PALETTEENTRY val;
994 for (h = lines - 1; h >= 0; h--) {
995 for (x = 0; x < dstwidth; x++) {
996 val = srccolors[XGetPixel(bmpImage, x, h)];
997 *bits++ = X11DRV_DIB_GetNearestIndex(colors, 256, val.peRed,
998 val.peGreen, val.peBlue);
1000 bits = (dstbits += linebytes);
1003 else goto notsupported;
1005 break;
1007 case 8:
1008 /* ==== 8 colormap bitmap to 8 colormap dib ==== */
1009 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
1011 BYTE *srcpixel;
1012 PALETTEENTRY val;
1014 for (h = lines - 1; h >= 0; h--) {
1015 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
1016 for (x = 0; x < dstwidth; x++) {
1017 val = srccolors[(int)*srcpixel++];
1018 *bits++ = X11DRV_DIB_GetNearestIndex(colors, 256, val.peRed,
1019 val.peGreen, val.peBlue);
1021 bits = (dstbits += linebytes);
1024 else goto notsupported;
1026 break;
1028 case 15:
1030 LPWORD srcpixel;
1031 WORD val;
1033 /* ==== 555 BGR bitmap to 8 colormap dib ==== */
1034 if (bmpImage->red_mask == 0x7c00 && bmpImage->blue_mask == 0x001f)
1036 for( h = lines - 1; h >= 0; h--)
1038 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
1039 for( x = 0; x < dstwidth; x++ )
1041 val = *srcpixel++;
1042 *bits++ = X11DRV_DIB_GetNearestIndex( colors, 256,
1043 ((val >> 7) & 0xf8) |
1044 ((val >> 12) & 0x7),
1045 ((val >> 2) & 0xf8) |
1046 ((val >> 7) & 0x3),
1047 ((val << 3) & 0xf8) |
1048 ((val >> 2) & 0x7) );
1050 bits = (dstbits += linebytes);
1053 /* ==== 555 RGB bitmap to 8 colormap dib ==== */
1054 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0x7c00)
1056 for( h = lines - 1; h >= 0; h--)
1058 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
1059 for( x = 0; x < dstwidth; x++ )
1061 val = *srcpixel++;
1062 *bits++ = X11DRV_DIB_GetNearestIndex( colors, 256,
1063 ((val << 3) & 0xf8) |
1064 ((val >> 2) & 0x7),
1065 ((val >> 2) & 0xf8) |
1066 ((val >> 7) & 0x3),
1067 ((val >> 7) & 0xf8) |
1068 ((val >> 12) & 0x7) );
1070 bits = (dstbits += linebytes);
1073 else goto notsupported;
1075 break;
1077 case 16:
1079 LPWORD srcpixel;
1080 WORD val;
1082 /* ==== 565 BGR bitmap to 8 colormap dib ==== */
1083 if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f)
1085 for( h = lines - 1; h >= 0; h--)
1087 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
1088 for( x = 0; x < dstwidth; x++ )
1090 val = *srcpixel++;
1091 *bits++ = X11DRV_DIB_GetNearestIndex( colors, 256,
1092 ((val >> 8) & 0xf8) |
1093 ((val >> 13) & 0x7),
1094 ((val >> 3) & 0xfc) |
1095 ((val >> 9) & 0x3),
1096 ((val << 3) & 0xf8) |
1097 ((val >> 2) & 0x7) );
1099 bits = (dstbits += linebytes);
1102 /* ==== 565 RGB bitmap to 8 colormap dib ==== */
1103 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0xf800)
1105 for( h = lines - 1; h >= 0; h--)
1107 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
1108 for( x = 0; x < dstwidth; x++ )
1110 val = *srcpixel++;
1111 *bits++ = X11DRV_DIB_GetNearestIndex( colors, 256,
1112 ((val << 3) & 0xf8) |
1113 ((val >> 2) & 0x7),
1114 ((val >> 3) & 0x00fc) |
1115 ((val >> 9) & 0x3),
1116 ((val >> 8) & 0x00f8) |
1117 ((val >> 13) & 0x7) );
1119 bits = (dstbits += linebytes);
1122 else goto notsupported;
1124 break;
1126 case 24:
1127 case 32:
1129 BYTE *srcpixel;
1131 /* ==== 24/32 BGR bitmap to 8 colormap dib ==== */
1132 if (bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff)
1134 for (h = lines - 1; h >= 0; h--)
1136 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
1137 for (x = 0; x < dstwidth; x++, srcpixel+=4)
1138 *bits++ = X11DRV_DIB_GetNearestIndex(colors, 256,
1139 srcpixel[2] , srcpixel[1], *srcpixel);
1140 bits = (dstbits += linebytes);
1143 /* ==== 24/32 RGB bitmap to 8 colormap dib ==== */
1144 else if (bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000)
1146 for (h = lines - 1; h >= 0; h--)
1148 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
1149 for (x = 0; x < dstwidth; x++, srcpixel+=4)
1150 *bits++ = X11DRV_DIB_GetNearestIndex(colors, 256,
1151 *srcpixel, srcpixel[1], srcpixel[2]);
1152 bits = (dstbits += linebytes);
1156 else goto notsupported;
1158 break;
1160 default: /* ? bit bmp -> 8 bit DIB */
1161 notsupported:
1162 FIXME("from %d bit bitmap with mask R,G,B %x,%x,%x to 8 bit DIB\n",
1163 bmpImage->depth, (int)bmpImage->red_mask,
1164 (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
1165 updatesection:
1166 for (h = lines - 1; h >= 0; h--) {
1167 for (x = 0; x < dstwidth; x++, bits++) {
1168 *bits = X11DRV_DIB_MapColor((int *)colors, 256,
1169 XGetPixel( bmpImage, x, h ) );
1171 bits = (dstbits += linebytes);
1173 break;
1177 /***********************************************************************
1178 * X11DRV_DIB_SetImageBits_RLE8
1180 * SetDIBits for an 8-bit deep compressed DIB.
1182 * This function rewritten 941113 by James Youngman. WINE blew out when I
1183 * first ran it because my desktop wallpaper is a (large) RLE8 bitmap.
1185 * This was because the algorithm assumed that all RLE8 bitmaps end with the
1186 * 'End of bitmap' escape code. This code is very much laxer in what it
1187 * allows to end the expansion. Possibly too lax. See the note by
1188 * case RleDelta. BTW, MS's documentation implies that a correct RLE8
1189 * bitmap should end with RleEnd, but on the other hand, software exists
1190 * that produces ones that don't and Windows 3.1 doesn't complain a bit
1191 * about it.
1193 * (No) apologies for my English spelling. [Emacs users: c-indent-level=4].
1194 * James A. Youngman <mbcstjy@afs.man.ac.uk>
1195 * [JAY]
1198 enum Rle8_EscapeCodes
1201 * Apologies for polluting your file's namespace...
1203 RleEol = 0, /* End of line */
1204 RleEnd = 1, /* End of bitmap */
1205 RleDelta = 2 /* Delta */
1208 static void X11DRV_DIB_SetImageBits_RLE8( int lines, const BYTE *bits,
1209 DWORD width, DWORD dstwidth,
1210 int left, int *colors,
1211 XImage *bmpImage )
1213 int x; /* X-positon on each line. Increases. */
1214 int line; /* Line #. Starts at lines-1, decreases */
1215 const BYTE *pIn = bits; /* Pointer to current position in bits */
1216 BYTE length; /* The length pf a run */
1217 BYTE color_index; /* index into colors[] as read from bits */
1218 BYTE escape_code; /* See enum Rle8_EscapeCodes.*/
1219 int color; /* value of colour[color_index] */
1221 if (lines == 0) /* Let's hope this doesn't happen. */
1222 return;
1225 * Note that the bitmap data is stored by Windows starting at the
1226 * bottom line of the bitmap and going upwards. Within each line,
1227 * the data is stored left-to-right. That's the reason why line
1228 * goes from lines-1 to 0. [JAY]
1231 x = 0;
1232 line = lines-1;
1235 length = *pIn++;
1238 * If the length byte is not zero (which is the escape value),
1239 * We have a run of length pixels all the same colour. The colour
1240 * index is stored next.
1242 * If the length byte is zero, we need to read the next byte to
1243 * know what to do. [JAY]
1245 if (length != 0)
1248 * [Run-Length] Encoded mode
1250 color_index = (*pIn++); /* Get the colour index. */
1251 color = colors[color_index];
1253 while(length--)
1254 XPutPixel(bmpImage, x++, line, color);
1256 else
1259 * Escape codes (may be an absolute sequence though)
1261 escape_code = (*pIn++);
1262 switch(escape_code)
1264 case RleEol: /* =0, end of line */
1266 x = 0;
1267 line--;
1268 break;
1271 case RleEnd: /* =1, end of bitmap */
1274 * Not all RLE8 bitmaps end with this
1275 * code. For example, Paint Shop Pro
1276 * produces some that don't. That's (I think)
1277 * what caused the previous implementation to
1278 * fail. [JAY]
1280 line=-1; /* Cause exit from do loop. */
1281 break;
1284 case RleDelta: /* =2, a delta */
1287 * Note that deltaing to line 0
1288 * will cause an exit from the loop,
1289 * which may not be what is intended.
1290 * The fact that there is a delta in the bits
1291 * almost certainly implies that there is data
1292 * to follow. You may feel that we should
1293 * jump to the top of the loop to avoid exiting
1294 * in this case.
1296 * TODO: Decide what to do here in that case. [JAY]
1298 x += (*pIn++);
1299 line -= (*pIn++);
1300 if (line == 0)
1302 TRACE("Delta to last line of bitmap "
1303 "(wrongly?) causes loop exit\n");
1305 break;
1308 default: /* >2, switch to absolute mode */
1311 * Absolute Mode
1313 length = escape_code;
1314 while(length--)
1316 color_index = (*pIn++);
1317 XPutPixel(bmpImage, x++, line,
1318 colors[color_index]);
1322 * If you think for a moment you'll realise that the
1323 * only time we could ever possibly read an odd
1324 * number of bytes is when there is a 0x00 (escape),
1325 * a value >0x02 (absolute mode) and then an odd-
1326 * length run. Therefore this is the only place we
1327 * need to worry about it. Everywhere else the
1328 * bytes are always read in pairs. [JAY]
1330 if (escape_code & 1)
1331 pIn++; /* Throw away the pad byte. */
1332 break;
1334 } /* switch (escape_code) : Escape sequence */
1335 } /* process either an encoded sequence or an escape sequence */
1337 /* We expect to come here more than once per line. */
1338 } while (line >= 0); /* Do this until the bitmap is filled */
1341 * Everybody comes here at the end.
1342 * Check how we exited the loop and print a message if it's a bit odd.
1343 * [JAY]
1345 if ( (*(pIn-2) != 0/*escape*/) || (*(pIn-1)!= RleEnd) )
1347 TRACE("End-of-bitmap without (strictly) proper escape code. Last two "
1348 "bytes were: %02X %02X.\n", (int)*(pIn-2),(int)*(pIn-1));
1353 /***********************************************************************
1354 * X11DRV_DIB_SetImageBits_16
1356 * SetDIBits for a 16-bit deep DIB.
1358 static void X11DRV_DIB_SetImageBits_16( int lines, const BYTE *srcbits,
1359 DWORD srcwidth, DWORD dstwidth, int left,
1360 DC *dc, DWORD rSrc, DWORD gSrc, DWORD bSrc,
1361 XImage *bmpImage )
1363 DWORD x;
1364 int h;
1366 /* align to 32 bit */
1367 DWORD linebytes = (srcwidth * 2 + 3) & ~3;
1369 if (lines < 0 )
1371 lines = -lines;
1372 srcbits = srcbits + ( linebytes * (lines-1));
1373 linebytes = -linebytes;
1376 switch ( bmpImage->depth )
1378 case 15:
1379 /* using same format as XImage */
1380 if (rSrc == bmpImage->red_mask && gSrc == bmpImage->green_mask && bSrc == bmpImage->blue_mask)
1381 for (h = lines - 1; h >= 0; h--, srcbits += linebytes)
1382 memcpy ( bmpImage->data + h * bmpImage->bytes_per_line + left*2, srcbits + left*2, dstwidth*2 );
1383 else /* We need to do a conversion from a 565 dib */
1385 LPDWORD dstpixel, ptr = (LPDWORD)(srcbits + left*2);
1386 DWORD val;
1387 int div = dstwidth % 2;
1389 for (h = lines - 1; h >= 0; h--) {
1390 dstpixel = (LPDWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1391 for (x = 0; x < dstwidth/2; x++) { /* Do 2 pixels at a time */
1392 val = *ptr++;
1393 *dstpixel++ = ((val >> 1) & 0x7fe07fe0) | (val & 0x001f001f); /* Red & Green & Blue */
1395 if (div != 0) /* Odd width? */
1396 *dstpixel = ((*(WORD *)ptr >> 1) & 0x7fe0) | (*(WORD *)ptr & 0x001f);
1397 ptr = (LPDWORD) ((srcbits += linebytes) + left*2);
1400 break;
1402 case 16:
1403 /* using same format as XImage */
1404 if (rSrc == bmpImage->red_mask && gSrc == bmpImage->green_mask && bSrc == bmpImage->blue_mask)
1405 for (h = lines - 1; h >= 0; h--, srcbits += linebytes)
1406 memcpy ( bmpImage->data + h * bmpImage->bytes_per_line + left*2, srcbits + left*2, dstwidth*2 );
1407 else /* We need to do a conversion from a 555 dib */
1409 LPDWORD dstpixel, ptr = (LPDWORD)(srcbits + left*2);
1410 DWORD val;
1411 int div = dstwidth % 2;
1413 for (h = lines - 1; h >= 0; h--) {
1414 dstpixel = (LPDWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1415 for (x = 0; x < dstwidth/2; x++) { /* Do 2 pixels at a time */
1416 val = *ptr++;
1417 *dstpixel++ = ((val << 1) & 0xffc0ffc0) | ((val >> 4) & 0x00200020) | /* Red & Green */
1418 (val & 0x001f001f); /* Blue */
1420 if (div != 0) /* Odd width? */
1421 *dstpixel = ((*(WORD *)ptr << 1) & 0xffc0) | ((*(WORD *)ptr >> 4) & 0x0020)
1422 | (*(WORD *)ptr & 0x001f);
1423 ptr = (LPDWORD) ((srcbits += linebytes) + left*2);
1426 break;
1428 case 24:
1429 case 32:
1431 DWORD *dstpixel;
1432 LPWORD ptr = (LPWORD)srcbits + left;
1433 DWORD val;
1435 /* ==== 555 BGR dib to 24/32 BGR bitmap ==== */
1436 if (bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff)
1438 for (h = lines - 1; h >= 0; h--) {
1439 dstpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line + left*4);
1440 for (x = 0; x < dstwidth; x++) {
1442 val = *ptr++;
1443 *dstpixel++ = ((val << 9) & 0xf80000) | ((val << 4) & 0x070000) | /* Red */
1444 ((val << 6) & 0x00f800) | ((val << 1) & 0x000700) | /* Green */
1445 ((val << 3) & 0x0000f8) | ((val >> 2) & 0x000007); /* Blue */
1447 ptr = (LPWORD)(srcbits += linebytes) + left;
1450 /* ==== 555 BGR dib to 24/32 RGB bitmap ==== */
1451 else if (bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000)
1453 for (h = lines - 1; h >= 0; h--) {
1454 dstpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line + left*4);
1455 for (x = 0; x < dstwidth; x++) {
1457 val = *ptr++;
1458 *dstpixel++ = ((val >> 7) & 0x0000f8) | ((val >> 12) & 0x000007) | /* Red */
1459 ((val << 6) & 0x00f800) | ((val << 1) & 0x000700) | /* Green */
1460 ((val << 19) & 0xf80000) | ((val >> 14) & 0x070000); /* Blue */
1462 ptr = (LPWORD)(srcbits += linebytes) + left;
1467 break;
1469 case 1:
1470 case 4:
1471 case 8:
1473 LPWORD ptr = (LPWORD)srcbits + left;
1474 WORD val;
1475 int sc1, sc2;
1477 /* Set color scaling values */
1478 if ( rSrc == 0x7c00 ) { sc1 = 7; sc2 = 2; } /* 555 dib */
1479 else { sc1 = 8; sc2 = 3; } /* 565 dib */
1481 for (h = lines - 1; h >= 0; h--) {
1482 for (x = left; x < dstwidth+left; x++) {
1483 val = *ptr++;
1484 XPutPixel( bmpImage, x, h,
1485 X11DRV_PALETTE_ToPhysical(dc, RGB(((val & rSrc) >> sc1), /* Red */
1486 ((val & gSrc) >> sc2), /* Green */
1487 ((val & bSrc) << 3)))); /* Blue */
1489 ptr = (LPWORD) (srcbits += linebytes) + left;
1492 break;
1494 default:
1495 FIXME("16 bit DIB %d bit bitmap\n", bmpImage->bits_per_pixel);
1496 break;
1502 /***********************************************************************
1503 * X11DRV_DIB_GetImageBits_16
1505 * GetDIBits for an 16-bit deep DIB.
1507 static void X11DRV_DIB_GetImageBits_16( int lines, BYTE *dstbits,
1508 DWORD dstwidth, DWORD srcwidth,
1509 PALETTEENTRY *srccolors, XImage *bmpImage )
1511 DWORD x;
1512 int h;
1514 /* align to 32 bit */
1515 DWORD linebytes = (dstwidth * 2 + 3) & ~3;
1517 if (lines < 0 )
1519 lines = -lines;
1520 dstbits = dstbits + ( linebytes * (lines-1));
1521 linebytes = -linebytes;
1524 switch ( bmpImage->depth )
1526 case 15:
1527 /* ==== 555 BGR bitmap to 555 BGR dib ==== */
1528 if (bmpImage->red_mask == 0x7c00 && bmpImage->blue_mask == 0x001f)
1529 for (h = lines - 1; h >= 0; h--, dstbits += linebytes)
1530 memcpy( dstbits, bmpImage->data + h*bmpImage->bytes_per_line, srcwidth*2 );
1532 /* ==== 555 RGB bitmap to 555 BGR dib ==== */
1533 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0x7c00)
1535 LPDWORD srcpixel, ptr = (LPDWORD)dstbits;
1536 DWORD val;
1537 int div = srcwidth % 2;
1539 for (h = lines - 1; h >= 0; h--) {
1540 srcpixel = (LPDWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
1541 for (x = 0; x < srcwidth/2; x++) { /* Do 2 pixels at a time */
1542 val = *srcpixel++;
1543 *ptr++ = ((val << 10) & 0xf800f800) | (val & 0x03e003e0) | /* Red & Green */
1544 ((val >> 10) & 0x001f001f); /* Blue */
1546 if (div != 0) /* Odd width? */
1547 *ptr = ((*(WORD *)srcpixel << 1) & 0xffc0) | ((*(WORD *)srcpixel >> 4) & 0x0020) |
1548 (*(WORD *)srcpixel & 0x001f);
1549 ptr = (LPDWORD)(dstbits += linebytes);
1552 else goto notsupported;
1554 break;
1556 case 16:
1558 LPDWORD srcpixel, ptr = (LPDWORD)dstbits;
1559 DWORD val;
1560 int div = srcwidth % 2;
1562 /* ==== 565 BGR bitmap to 555 BGR dib ==== */
1563 if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f )
1565 for (h = lines - 1; h >= 0; h--) {
1566 srcpixel = (LPDWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
1567 for (x = 0; x < srcwidth/2; x++) { /* Do 2 pixels at a time */
1568 val = *srcpixel++;
1569 *ptr++ = ((val >> 1) & 0x7fe07fe0) | /* Red & Green */
1570 (val & 0x001f001f); /* Blue */
1572 if (div != 0) /* Odd width? */
1573 *ptr = ((*(WORD *)srcpixel >> 1) & 0x7fe0) | (*(WORD *)srcpixel & 0x001f);
1574 ptr = (LPDWORD) (dstbits += linebytes);
1577 /* ==== 565 RGB bitmap to 555 BGR dib ==== */
1578 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0xf800)
1580 for (h = lines - 1; h >= 0; h--) {
1581 srcpixel = (LPDWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
1582 for (x = 0; x < srcwidth/2; x++) { /* Do 2 pixels at a time */
1583 val = *srcpixel++;
1584 *ptr++ = ((val << 10) & 0x7c007c00) | ((val >> 1) & 0x03e003e0) | /* Red & Green */
1585 ((val >> 11) & 0x001f001f); /* Blue */
1587 if (div != 0) /* Odd width? */
1588 *ptr = ((*(WORD *)srcpixel >> 1) & 0x7fe0) | (*(WORD *)srcpixel & 0x001f);
1589 ptr = (LPDWORD) (dstbits += linebytes);
1592 else goto notsupported;
1594 break;
1596 case 24:
1597 case 32:
1599 DWORD *srcpixel;
1600 LPWORD ptr = (LPWORD)dstbits;
1601 DWORD val;
1603 /* ==== 24/32 BGR bitmap to 555 BGR dib ==== */
1604 if (bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff)
1606 for (h = lines - 1; h >= 0; h--) {
1607 srcpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line);
1608 for (x = 0; x < srcwidth; x++, ptr++) {
1609 val = *srcpixel++;
1610 *ptr = ((val >> 9) & 0x7c00) | /* Red */
1611 ((val >> 6) & 0x03e0) | /* Green */
1612 ((val >> 3) & 0x001f); /* Blue */
1614 ptr = (LPWORD)(dstbits += linebytes);
1617 /* ==== 24/32 RGB bitmap to 555 BGR dib ==== */
1618 else if (bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000)
1620 for (h = lines - 1; h >= 0; h--) {
1621 srcpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line);
1622 for (x = 0; x < srcwidth; x++, ptr++) {
1623 val = *srcpixel++;
1624 *ptr = ((val << 7) & 0x7c00) | /* Red */
1625 ((val >> 6) & 0x03e0) | /* Green */
1626 ((val >> 19) & 0x001f); /* Blue */
1628 ptr = (LPWORD) (dstbits += linebytes);
1631 else goto notsupported;
1633 break;
1635 case 1:
1636 /* ==== monochrome bitmap to 16 BGR dib ==== */
1637 case 4:
1638 /* ==== 4 colormap bitmap to 16 BGR dib ==== */
1639 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
1641 LPWORD ptr = (LPWORD)dstbits;
1642 PALETTEENTRY val;
1644 for (h = lines - 1; h >= 0; h--) {
1645 for (x = 0; x < dstwidth; x++) {
1646 val = srccolors[XGetPixel(bmpImage, x, h)];
1647 *ptr++ = ((val.peRed << 7) & 0x7c00) |
1648 ((val.peGreen << 2) & 0x03e0) |
1649 ((val.peBlue >> 3) & 0x001f);
1651 ptr = (LPWORD)(dstbits += linebytes);
1654 else goto notsupported;
1656 break;
1658 case 8:
1659 /* ==== 8 colormap bitmap to 16 BGR dib ==== */
1660 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
1662 LPWORD ptr = (LPWORD)dstbits;
1663 BYTE *srcpixel;
1664 PALETTEENTRY val;
1666 for (h = lines - 1; h >= 0; h--) {
1667 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
1668 for (x = 0; x < dstwidth; x++) {
1669 val = srccolors[(int)*srcpixel++];
1670 *ptr++ = ((val.peRed << 7) & 0x7c00) |
1671 ((val.peGreen << 2) & 0x03e0) |
1672 ((val.peBlue >> 3) & 0x001f);
1674 ptr = (LPWORD)(dstbits += linebytes);
1677 else goto notsupported;
1679 break;
1681 default:
1682 notsupported:
1684 BYTE r,g, b;
1685 LPWORD ptr = (LPWORD)dstbits;
1687 FIXME("from %d bit bitmap with mask R,G,B %x,%x,%x to 16 bit DIB\n",
1688 bmpImage->depth, (int)bmpImage->red_mask,
1689 (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
1690 for (h = lines - 1; h >= 0; h--)
1692 for (x = 0; x < dstwidth; x++, ptr++)
1694 COLORREF pixel = X11DRV_PALETTE_ToLogical( XGetPixel( bmpImage, x, h ) );
1695 r = (BYTE) GetRValue(pixel);
1696 g = (BYTE) GetGValue(pixel);
1697 b = (BYTE) GetBValue(pixel);
1698 *ptr = ( ((r << 7) & 0x7c00) | ((g << 2) & 0x03e0) | ((b >> 3) & 0x001f) );
1700 ptr = (LPWORD) (dstbits += linebytes);
1703 break;
1708 /***********************************************************************
1709 * X11DRV_DIB_SetImageBits_24
1711 * SetDIBits for a 24-bit deep DIB.
1713 static void X11DRV_DIB_SetImageBits_24( int lines, const BYTE *srcbits,
1714 DWORD srcwidth, DWORD dstwidth, int left,
1715 DC *dc, XImage *bmpImage )
1717 DWORD x;
1718 int h;
1720 /* align to 32 bit */
1721 DWORD linebytes = (srcwidth * 3 + 3) & ~3;
1723 if (lines < 0 )
1725 lines = -lines;
1726 srcbits = srcbits + linebytes * (lines - 1);
1727 linebytes = -linebytes;
1730 switch ( bmpImage->depth )
1732 case 24:
1734 if (bmpImage->bits_per_pixel == 24) {
1735 int dstlinebytes = linebytes;
1736 BYTE *dstpixel;
1737 BYTE *ptr = (BYTE *)(srcbits+left*3);
1739 if (dstlinebytes < 0 ) dstlinebytes = -dstlinebytes;
1740 dstpixel = bmpImage->data + lines*dstlinebytes + left*3;
1741 for(h = lines ; h-- ; ) {
1742 dstpixel-=dstlinebytes;
1743 memcpy(dstpixel,ptr,dstwidth*3);
1744 ptr +=linebytes;
1746 break;
1749 case 32:
1751 if( bmpImage->blue_mask == 0xff && bmpImage->red_mask == 0xff0000 ) /* packed BGR to unpacked BGR */
1753 DWORD *dstpixel, val, buf;
1754 DWORD *ptr = (DWORD *)(srcbits + left*3);
1755 BYTE *bits;
1756 int div = dstwidth % 4;
1757 int divk;
1759 for(h = lines - 1; h >= 0; h--)
1761 dstpixel = (DWORD *) (bmpImage->data + h*bmpImage->bytes_per_line + left*4);
1763 for (x = 0; x < dstwidth/4; x++) { /* do 3 dwords source, 4 dwords dest at a time */
1764 buf = *ptr++;
1765 *dstpixel++ = buf&0x00ffffff; /* b1, g1, r1 */
1766 val = (buf >> 24); /* b2 */
1767 buf = *ptr++;
1768 *dstpixel++ = (val | (buf<<8)) &0x00ffffff; /* g2, r2 */
1769 val = (buf >> 16); /* b3, g3 */
1770 buf = *ptr++;
1771 *dstpixel++ = (val | (buf<<16)) &0x00ffffff; /* r3 */
1772 *dstpixel++ = (buf >> 8); /* b4, g4, r4 */
1774 for ( divk=div, bits=(BYTE*)ptr; divk>0; divk--, bits+=3 ) /* do remainder */
1776 *dstpixel++ = *(DWORD*)bits & 0x00ffffff; /* b, g, r */
1778 ptr = (DWORD*)((srcbits+=linebytes)+left*3);
1781 else if( bmpImage->blue_mask == 0xff0000 && bmpImage->red_mask == 0xff ) /* packed BGR to unpacked RGB */
1783 DWORD *dstpixel, val, buf;
1784 DWORD *ptr = (DWORD *)(srcbits + left*3);
1785 BYTE *bits;
1786 int div = dstwidth % 4;
1787 int divk;
1789 for(h = lines - 1; h >= 0; h--)
1791 dstpixel = (DWORD *) (bmpImage->data + h*bmpImage->bytes_per_line + left*4);
1793 for (x = 0; x < dstwidth/4; x++) { /* do 3 dwords source, 4 dwords dest at a time */
1794 buf = *ptr++;
1795 *dstpixel++ = ((buf&0xff)<<16) | (buf&0xff00) | ((buf&0xff0000)>>16); /* b1, g1, r1 */
1796 val = ((buf&0xff000000)>>8); /* b2 */
1797 buf = *ptr++;
1798 *dstpixel++ = val | ((buf&0xff)<<8) | ((buf&0xff00)>>8); /* g2, r2 */
1799 val = (buf&0xff0000) | ((buf&0xff000000)>>16); /* b3, g3 */
1800 buf = *ptr++;
1801 *dstpixel++ = val | (buf&0xff); /* r3 */
1802 *dstpixel++ = ((buf&0xff00)<<8) | ((buf&0xff0000)>>8) | (buf>>24); /* b4, g4, r4 */
1804 for ( divk=div, bits=(BYTE*)ptr; divk>0; divk--, bits+=3 ) /* do remainder */
1806 buf = *(DWORD*)bits;
1807 *dstpixel++ = ((buf&0xff)<<16) | (buf&0xff00) | ((buf&0xff0000)>>16); /* b, g, r */
1809 ptr = (DWORD*)((srcbits+=linebytes)+left*3);
1812 else
1813 goto notsupported;
1815 break;
1817 case 15:
1819 if( bmpImage->blue_mask == 0x7c00 && bmpImage->red_mask == 0x1f ) /* BGR888 to RGB555 */
1821 DWORD *ptr = (DWORD *)(srcbits + left*3), val;
1822 LPBYTE bits;
1823 LPWORD dstpixel;
1824 int div = dstwidth % 4;
1825 int divk;
1827 for (h = lines - 1; h >= 0; h--) { /* Do 4 pixels at a time */
1828 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1829 for (x = 0; x < dstwidth/4; x++) {
1830 *dstpixel++ = (WORD)((((val = *ptr++) << 7) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 19) & 0x1f));
1831 *dstpixel++ = (WORD)(((val >> 17) & 0x7c00) | (((val = *ptr++) << 2) & 0x03e0) | ((val >> 11) & 0x1f));
1832 *dstpixel++ = (WORD)(((val >> 9) & 0x07c00) | ((val >> 22) & 0x03e0) | (((val = *ptr++) >> 3) & 0x1f));
1833 *dstpixel++ = (WORD)(((val >> 1) & 0x07c00) | ((val >> 14) & 0x03e0) | ((val >> 27) & 0x1f));
1835 for (bits = (LPBYTE)ptr, divk=div; divk > 0; divk--, bits+=3) /* dstwidth not divisible by 4? */
1836 *dstpixel++ = (((WORD)bits[0] << 7) & 0x07c00) |
1837 (((WORD)bits[1] << 2) & 0x03e0) |
1838 (((WORD)bits[2] >> 3) & 0x001f);
1839 ptr = (DWORD *)((srcbits += linebytes) + left * 3);
1842 else if( bmpImage->blue_mask == 0x1f && bmpImage->red_mask == 0x7c00 ) /* BGR888 to BGR555 */
1844 DWORD *ptr = (DWORD *)(srcbits + left*3), val;
1845 LPBYTE bits;
1846 LPWORD dstpixel;
1847 int div = dstwidth % 4;
1848 int divk;
1850 for (h = lines - 1; h >= 0; h--) { /* Do 4 pixels at a time */
1851 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1852 for (x = 0; x < dstwidth/4; x++) {
1853 *dstpixel++ = (WORD)((((val = *ptr++) >> 3) & 0x1f) | ((val >> 6) & 0x03e0) | ((val >> 9) & 0x7c00));
1854 *dstpixel++ = (WORD)(((val >> 27) & 0x1f) | (((val = *ptr++) << 2) & 0x03e0) | ((val >> 1) & 0x7c00));
1855 *dstpixel++ = (WORD)(((val >> 19) & 0x1f) | ((val >> 22) & 0x03e0) | (((val = *ptr++) << 7) & 0x7c00));
1856 *dstpixel++ = (WORD)(((val >> 11) & 0x1f) | ((val >> 14) & 0x03e0) | ((val >> 17) & 0x7c00));
1858 for (bits = (LPBYTE)ptr, divk=div; divk > 0; divk--, bits+=3) /* dstwidth not divisible by 4? */
1859 *dstpixel++ = (((WORD)bits[2] << 7) & 0x07c00) |
1860 (((WORD)bits[1] << 2) & 0x03e0) |
1861 (((WORD)bits[0] >> 3) & 0x001f);
1862 ptr = (DWORD *)((srcbits += linebytes) + left * 3);
1865 else
1866 goto notsupported;
1868 break;
1870 case 16:
1872 DWORD *ptr = (DWORD *)(srcbits + left*3), val;
1873 LPBYTE bits;
1874 LPWORD dstpixel;
1875 int div = dstwidth % 4;
1876 int divk;
1878 if( bmpImage->blue_mask == 0x001f && bmpImage->red_mask == 0xf800 ) /* BGR888 to BGR565 */
1880 for (h = lines - 1; h >= 0; h--) { /* Do 4 pixels at a time */
1881 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1882 for (x = 0; x < dstwidth/4; x++) {
1883 *dstpixel++ = (WORD)((((val = *ptr++) >> 3) & 0x1f) | ((val >> 5) & 0x07e0) | ((val >> 8) & 0xf800));
1884 *dstpixel++ = (WORD)(((val >> 27) & 0x1f) | (((val = *ptr++) << 3) & 0x07e0) | ((val) & 0xf800));
1885 *dstpixel++ = (WORD)(((val >> 19) & 0x1f) | ((val >> 21) & 0x07e0) | (((val = *ptr++) << 8) & 0xf800));
1886 *dstpixel++ = (WORD)(((val >> 11) & 0x1f) | ((val >> 13) & 0x07e0) | ((val >> 16) & 0xf800));
1888 for ( bits = (LPBYTE)ptr, divk=div; divk > 0; divk--, bits+=3) /* dstwidth is not divisible by 4? */
1889 *dstpixel++ = (((WORD)bits[2] << 8) & 0xf800) |
1890 (((WORD)bits[1] << 3) & 0x07e0) |
1891 (((WORD)bits[0] >> 3) & 0x001f);
1892 ptr = (DWORD *)((srcbits += linebytes) + left * 3);
1895 else if( bmpImage->blue_mask == 0xf800 && bmpImage->red_mask == 0x001f ) /* BGR888 to RGB565 */
1897 for (h = lines - 1; h >= 0; h--) { /* Do 4 pixels at a time */
1898 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1899 for (x = 0; x < dstwidth/4; x++) {
1900 *dstpixel++ = (WORD)((((val = *ptr++) << 8) & 0xf800) | ((val >> 5) & 0x07e0) | ((val >> 19) & 0x1f));
1901 *dstpixel++ = (WORD)(((val >> 16) & 0xf800) | (((val = *ptr++) << 3) & 0x07e0) | ((val >> 11) & 0x1f));
1902 *dstpixel++ = (WORD)(((val >> 8) & 0xf800) | ((val >> 21) & 0x07e0) | (((val = *ptr++) >> 3) & 0x1f));
1903 *dstpixel++ = (WORD)((val & 0xf800) | ((val >> 13) & 0x07e0) | ((val >> 27) & 0x1f));
1905 for ( bits = (LPBYTE)ptr, divk=div; divk > 0; divk--, bits+=3) /* dstwidth is not divisible by 4? */
1906 *dstpixel++ = (((WORD)bits[0] << 8) & 0xf800) |
1907 (((WORD)bits[1] << 3) & 0x07e0) |
1908 (((WORD)bits[2] >> 3) & 0x001f);
1909 ptr = (DWORD *)((srcbits += linebytes) + left * 3);
1912 else
1913 goto notsupported;
1915 break;
1917 case 1:
1918 case 4:
1919 case 8:
1921 LPBYTE bits = (LPBYTE)srcbits + left*3;
1923 for (h = lines - 1; h >= 0; h--) {
1924 for (x = left; x < dstwidth+left; x++, bits+=3)
1925 XPutPixel( bmpImage, x, h,
1926 X11DRV_PALETTE_ToPhysical(dc, RGB(bits[2], bits[1], bits[0])));
1927 bits = (LPBYTE)(srcbits += linebytes) + left * 3;
1930 break;
1932 default:
1933 notsupported:
1934 FIXME("from 24 bit DIB to %d bit bitmap with mask R,G,B %x,%x,%x\n",
1935 bmpImage->bits_per_pixel, (int)bmpImage->red_mask,
1936 (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
1937 break;
1942 /***********************************************************************
1943 * X11DRV_DIB_GetImageBits_24
1945 * GetDIBits for an 24-bit deep DIB.
1947 static void X11DRV_DIB_GetImageBits_24( int lines, BYTE *dstbits,
1948 DWORD dstwidth, DWORD srcwidth,
1949 PALETTEENTRY *srccolors, XImage *bmpImage )
1951 DWORD x, val;
1952 int h;
1954 /* align to 32 bit */
1955 DWORD linebytes = (dstwidth * 3 + 3) & ~3;
1957 if (lines < 0 )
1959 lines = -lines;
1960 dstbits = dstbits + ( linebytes * (lines-1) );
1961 linebytes = -linebytes;
1964 switch ( bmpImage->depth )
1966 case 24:
1968 if (bmpImage->bits_per_pixel == 24) {
1969 int tocopy = linebytes;
1970 BYTE *srcpixel;
1971 BYTE *ptr = (LPBYTE)dstbits;
1973 if (tocopy < 0 ) tocopy = -tocopy;
1974 srcpixel = bmpImage->data + lines*tocopy;
1975 for(h = lines ; h-- ; ) {
1976 srcpixel-=tocopy;
1977 memcpy(ptr,srcpixel,tocopy);
1978 ptr = (LPBYTE)(dstbits+=linebytes);
1980 break;
1983 case 32:
1985 DWORD *srcpixel, buf;
1986 LPBYTE bits;
1987 DWORD *ptr=(DWORD *)dstbits;
1988 int quotient = dstwidth / 4;
1989 int remainder = dstwidth % 4;
1990 int remk;
1992 /* ==== 24/32 BGR bitmap to 24 BGR dib==== */
1993 if( bmpImage->blue_mask == 0xff && bmpImage->red_mask == 0xff0000 )
1995 for(h = lines - 1; h >= 0; h--)
1997 srcpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line);
1999 for (x = 0; x < quotient; x++) { /* do 4 dwords source, 3 dwords dest at a time*/
2000 buf = ((*srcpixel++)&0x00ffffff); /* b1, g1, r1*/
2001 *ptr++ = buf | ((*srcpixel)<<24); /* b2 */
2002 buf = ((*srcpixel++>>8)&0x0000ffff); /* g2, r2 */
2003 *ptr++ = buf | ((*srcpixel)<<16); /* b3, g3 */
2004 buf = ((*srcpixel++>>16)&0x000000ff); /* r3 */
2005 *ptr++ = buf | ((*srcpixel++)<<8); /* b4, g4, r4 */
2007 for ( remk=remainder, bits=(BYTE*)ptr; remk>0; remk--, bits+=3 ) /* do remainder */
2009 buf=*srcpixel++;
2010 *(WORD*)bits = buf; /* b, g */
2011 *(bits+2) = buf>>16; /* r */
2013 ptr = (DWORD*)(dstbits+=linebytes);
2017 /* ==== 24/32 RGB bitmap to 24 BGR dib ==== */
2018 else if( bmpImage->blue_mask == 0xff0000 && bmpImage->red_mask == 0xff )
2020 for(h = lines - 1; h >= 0; h--)
2022 srcpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line);
2024 for (x = 0; x < quotient; x++) { /* do 4 dwords source, 3 dwords dest at a time */
2025 buf = *srcpixel++;
2026 val = ((buf&0xff0000)>>16) | (buf&0xff00) | ((buf&0xff)<<16); /* b1, g1, r1 */
2027 buf = *srcpixel++;
2028 *ptr++ = val | ((buf&0xff0000)<<8); /* b2 */
2029 val = ((buf&0xff00)>>8) | ((buf&0xff)<<8); /* g2, r2 */
2030 buf = *srcpixel++;
2031 *ptr++ = val | (buf&0xff0000) | ((buf&0xff00)<<16); /* b3, g3 */
2032 val = (buf&0xff); /* r3 */
2033 buf = *srcpixel++;
2034 *ptr++ = val | ((buf&0xff0000)>>8) | ((buf&0xff00)<<8) | (buf<<24); /* b4, g4, r4 */
2036 for ( remk=remainder, bits=(BYTE*)ptr; remk>0; remk--, bits+=3 ) /* do remainder */
2038 buf=*srcpixel++;
2039 *(WORD*)bits = (buf&0xff00) | ((buf&0xff0000)>>16) ; /* b, g */
2040 *(bits+2) = buf; /* r */
2042 ptr = (DWORD*)(dstbits+=linebytes);
2045 else goto notsupported;
2047 break;
2049 case 15:
2051 LPWORD srcpixel;
2052 LPBYTE bits = dstbits;
2053 WORD val;
2055 /* ==== 555 BGR bitmap to 24 BGR dib ==== */
2056 if( bmpImage->blue_mask == 0x1f && bmpImage->red_mask == 0x7c00 )
2058 for (h = lines - 1; h >= 0; h--) {
2059 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2060 for (x = 0; x < srcwidth; x++, bits += 3) {
2061 val = *srcpixel++;
2062 bits[2] = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07)); /*Red*/
2063 bits[1] = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07)); /*Green*/
2064 bits[0] = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07)); /*Blue*/
2066 bits = (dstbits += linebytes);
2069 /* ==== 555 RGB bitmap to 24 RGB dib==== */
2070 else if( bmpImage->blue_mask == 0x7c00 && bmpImage->red_mask == 0x1f )
2072 for (h = lines - 1; h >= 0; h--) {
2073 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2074 for (x = 0; x < srcwidth; x++, bits += 3) {
2075 val = *srcpixel++;
2076 bits[0] = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07)); /*Red*/
2077 bits[1] = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07)); /*Green*/
2078 bits[2] = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07)); /*Blue*/
2080 bits = (dstbits += linebytes);
2083 else goto notsupported;
2085 break;
2087 case 16:
2089 LPWORD srcpixel;
2090 LPBYTE bits = dstbits;
2091 WORD val;
2093 /* ==== 565 BGR bitmap to 24 BGR dib ==== */
2094 if( bmpImage->blue_mask == 0x1f && bmpImage->red_mask == 0xf800 )
2096 for (h = lines - 1; h >= 0; h--) {
2097 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2098 for (x = 0; x < srcwidth; x++, bits += 3) {
2099 val = *srcpixel++;
2100 bits[2] = (BYTE)(((val >> 8) & 0xf8) | ((val >> 13) & 0x07)); /*Red*/
2101 bits[1] = (BYTE)(((val >> 3) & 0xfc) | ((val >> 9) & 0x03)); /*Green*/
2102 bits[0] = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07)); /*Blue*/
2104 bits = (dstbits += linebytes);
2107 /* ==== 565 RGB bitmap to 24 BGR dib ==== */
2108 else if( bmpImage->blue_mask == 0xf800 && bmpImage->red_mask == 0x1f )
2110 for (h = lines - 1; h >= 0; h--) {
2111 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2112 for (x = 0; x < srcwidth; x++, bits += 3) {
2113 val = *srcpixel++;
2114 bits[0] = (BYTE)(((val >> 8) & 0xf8) | ((val >> 13) & 0x07)); /*Red*/
2115 bits[1] = (BYTE)(((val >> 3) & 0xfc) | ((val >> 9) & 0x03)); /*Green*/
2116 bits[2] = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07)); /*Blue*/
2118 bits = (dstbits += linebytes);
2121 else goto notsupported;
2123 break;
2125 case 1:
2126 /* ==== monochrome bitmap to 24 BGR dib ==== */
2127 case 4:
2128 /* ==== 4 colormap bitmap to 24 BGR dib ==== */
2129 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
2131 LPBYTE bits = dstbits;
2132 PALETTEENTRY val;
2134 for (h = lines - 1; h >= 0; h--) {
2135 for (x = 0; x < dstwidth; x++) {
2136 val = srccolors[XGetPixel(bmpImage, x, h)];
2137 *bits++ = val.peBlue;
2138 *bits++ = val.peGreen;
2139 *bits++ = val.peRed;
2141 bits = (dstbits += linebytes);
2144 else goto notsupported;
2146 break;
2148 case 8:
2149 /* ==== 8 colormap bitmap to 24 BGR dib ==== */
2150 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask == 0 && srccolors)
2152 BYTE *srcpixel;
2153 LPBYTE bits = dstbits;
2154 PALETTEENTRY val;
2156 for (h = lines - 1; h >= 0; h--) {
2157 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
2158 for (x = 0; x < dstwidth; x++ ) {
2159 val = srccolors[(int)*srcpixel++];
2160 *bits++ = val.peBlue; /*Blue*/
2161 *bits++ = val.peGreen; /*Green*/
2162 *bits++ = val.peRed; /*Red*/
2164 bits = (dstbits += linebytes);
2167 else goto notsupported;
2169 break;
2171 default:
2172 notsupported:
2174 LPBYTE bits = dstbits;
2176 FIXME("from %d bit bitmap with mask R,G,B %x,%x,%x to 24 bit DIB\n",
2177 bmpImage->depth, (int)bmpImage->red_mask,
2178 (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
2179 for (h = lines - 1; h >= 0; h--)
2181 for (x = 0; x < dstwidth; x++, bits += 3)
2183 COLORREF pixel = X11DRV_PALETTE_ToLogical( XGetPixel( bmpImage, x, h ) );
2184 bits[0] = GetBValue(pixel);
2185 bits[1] = GetGValue(pixel);
2186 bits[2] = GetRValue(pixel);
2188 bits = (dstbits += linebytes);
2191 break;
2196 /***********************************************************************
2197 * X11DRV_DIB_SetImageBits_32
2199 * SetDIBits for a 32-bit deep DIB.
2201 static void X11DRV_DIB_SetImageBits_32( int lines, const BYTE *srcbits,
2202 DWORD srcwidth, DWORD dstwidth, int left,
2203 DC *dc, XImage *bmpImage )
2205 DWORD x, *ptr;
2206 int h;
2208 DWORD linebytes = (srcwidth * 4);
2210 if (lines < 0 )
2212 lines = -lines;
2213 srcbits = srcbits + ( linebytes * (lines-1) );
2214 linebytes = -linebytes;
2217 ptr = (DWORD *) srcbits + left;
2219 switch ( bmpImage->depth )
2221 case 24:
2222 case 32:
2223 /* ==== 32 BGR dib to 24/32 BGR bitmap ==== */
2224 if (bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff) {
2225 for (h = lines - 1; h >= 0; h--, srcbits+=linebytes) {
2226 memcpy( bmpImage->data + h * bmpImage->bytes_per_line, srcbits + left*4, dstwidth*4 );
2230 /* ==== 32 BGR dib to 24/32 RGB bitmap ==== */
2231 else if (bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000)
2233 DWORD *dstpixel;
2235 for (h = lines - 1; h >= 0; h--) {
2236 dstpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line);
2237 for (x = 0; x < dstwidth; x++, ptr++) {
2238 *dstpixel++ = ((*ptr << 16) & 0xff0000) | (*ptr & 0xff00) | ((*ptr >> 16) & 0xff);
2240 ptr = (DWORD *) (srcbits += linebytes) + left;
2243 else goto notsupported;
2245 break;
2247 case 15:
2248 /* ==== 32 BGR dib to 555 BGR bitmap ==== */
2249 if (bmpImage->red_mask == 0x7c00 && bmpImage->blue_mask == 0x001f)
2251 LPWORD dstpixel;
2253 for (h = lines - 1; h >= 0; h--) {
2254 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2255 for (x = 0; x < dstwidth; x++, ptr++) {
2256 *dstpixel++ = (WORD) (((*ptr >> 9) & 0x7c00) | ((*ptr >> 6) & 0x03e0) | ((*ptr >> 3) & 0x001f));
2258 ptr = (DWORD *) (srcbits += linebytes) + left;
2261 /* ==== 32 BGR dib to 555 RGB bitmap ==== */
2262 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0x7c00)
2264 LPWORD dstpixel;
2266 for (h = lines - 1; h >= 0; h--) {
2267 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2268 for (x = 0; x < dstwidth; x++, ptr++) {
2269 *dstpixel++ = (WORD) (((*ptr << 7) & 0x7c00) | ((*ptr >> 6) & 0x03e0) | ((*ptr >> 19) & 0x001f));
2271 ptr = (DWORD *) (srcbits += linebytes) + left;
2274 else goto notsupported;
2276 break;
2278 case 16:
2279 /* ==== 32 BGR dib to 565 BGR bitmap ==== */
2280 if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f)
2282 LPWORD dstpixel;
2284 for (h = lines - 1; h >= 0; h--) {
2285 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2286 for (x = 0; x < dstwidth; x++, ptr++) {
2287 *dstpixel++ = (WORD) (((*ptr >> 8) & 0xf800) | ((*ptr >> 5) & 0x07e0) | ((*ptr >> 3) & 0x001f));
2289 ptr = (DWORD *) (srcbits += linebytes) + left;
2292 /* ==== 32 BGR dib to 565 RGB bitmap ==== */
2293 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0xf800)
2295 LPWORD dstpixel;
2297 for (h = lines - 1; h >= 0; h--) {
2298 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2299 for (x = 0; x < dstwidth; x++, ptr++) {
2300 *dstpixel++ = (WORD) (((*ptr << 8) & 0xf800) | ((*ptr >> 5) & 0x07e0) | ((*ptr >> 19) & 0x001f));
2302 ptr = (DWORD *) (srcbits += linebytes) + left;
2305 else goto notsupported;
2307 break;
2309 case 1:
2310 case 4:
2311 case 8:
2313 LPBYTE bits = (LPBYTE)srcbits + left*4;
2315 for (h = lines - 1; h >= 0; h--) {
2316 for (x = left; x < dstwidth+left; x++, bits += 4)
2317 XPutPixel( bmpImage, x, h,
2318 X11DRV_PALETTE_ToPhysical(dc, RGB( bits[2], bits[1], *bits )));
2319 bits = (LPBYTE)(srcbits += linebytes) + left * 4;
2322 break;
2324 default:
2325 notsupported:
2326 FIXME("32 bit DIB %d bit bitmap\n", bmpImage->bits_per_pixel);
2327 break;
2332 /***********************************************************************
2333 * X11DRV_DIB_GetImageBits_32
2335 * GetDIBits for an 32-bit deep DIB.
2337 static void X11DRV_DIB_GetImageBits_32( int lines, BYTE *dstbits,
2338 DWORD dstwidth, DWORD srcwidth,
2339 PALETTEENTRY *srccolors, XImage *bmpImage )
2341 DWORD x;
2342 int h;
2343 BYTE *bits;
2345 /* align to 32 bit */
2346 DWORD linebytes = (srcwidth * 4);
2347 DWORD copybytes = linebytes;
2349 if (lines < 0 )
2351 lines = -lines;
2352 dstbits = dstbits + ( linebytes * (lines-1) );
2353 linebytes = -linebytes;
2356 bits = dstbits;
2358 switch ( bmpImage->depth )
2360 case 24:
2361 case 32:
2362 /* ==== 24/32 BGR bitmap to 32 BGR dib ==== */
2363 if ( bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff )
2364 for (h = lines - 1; h >= 0; h--, dstbits+=linebytes)
2365 memcpy( dstbits, bmpImage->data + h*bmpImage->bytes_per_line, copybytes );
2367 /* ==== 24/32 RGB bitmap to 32 BGR dib ==== */
2368 else if ( bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000 )
2370 LPBYTE srcbits;
2372 for (h = lines - 1; h >= 0; h--) {
2373 srcbits = bmpImage->data + h * bmpImage->bytes_per_line;
2374 for (x = 0; x < dstwidth; x++, bits+=4, srcbits+=2) {
2375 *(bits + 2) = *srcbits++;
2376 *(bits + 1) = *srcbits++;
2377 *bits = *srcbits;
2379 bits = (dstbits += linebytes);
2382 else goto notsupported;
2383 break;
2385 case 15:
2387 LPWORD srcpixel;
2388 WORD val;
2390 /* ==== 555 BGR bitmap to 32 BGR dib ==== */
2391 if (bmpImage->red_mask == 0x7c00 && bmpImage->blue_mask == 0x001f)
2393 for (h = lines - 1; h >= 0; h--) {
2394 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2395 for (x = 0; x < dstwidth; x++, bits+=2) {
2396 val = *srcpixel++;
2397 *bits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x03)); /*Blue*/
2398 *bits++ = (BYTE)(((val >> 2) & 0xfc) | ((val >> 8) & 0x03)); /*Green*/
2399 *bits = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07)); /*Red*/
2401 bits = (dstbits += linebytes);
2404 /* ==== 555 RGB bitmap to 32 BGR dib ==== */
2405 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0x7c00)
2407 for (h = lines - 1; h >= 0; h--) {
2408 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2409 for (x = 0; x < dstwidth; x++, bits+=2) {
2410 val = *srcpixel++;
2411 *bits++ = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07));/*Blue*/
2412 *bits++ = (BYTE)(((val >> 2) & 0xfc) | ((val >> 8) & 0x03)); /*Green*/
2413 *bits = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x03)); /*Red*/
2415 bits = (dstbits += linebytes);
2418 else goto notsupported;
2420 break;
2422 case 16:
2424 LPWORD srcpixel;
2425 WORD val;
2427 /* ==== 565 BGR bitmap to 32 BGR dib ==== */
2428 if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f)
2430 for (h = lines - 1; h >= 0; h--) {
2431 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2432 for (x = 0; x < srcwidth; x++, bits+=2) {
2433 val = *srcpixel++;
2434 *bits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x03)); /*Blue*/
2435 *bits++ = (BYTE)(((val >> 3) & 0xfc) | ((val >> 9) & 0x03)); /*Green*/
2436 *bits = (BYTE)(((val >> 8) & 0xf8) | ((val >> 13) & 0x07)); /*Red*/
2438 bits = (dstbits += linebytes);
2441 /* ==== 565 RGB bitmap to 32 BGR dib ==== */
2442 else if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f)
2444 for (h = lines - 1; h >= 0; h--) {
2445 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2446 for (x = 0; x < srcwidth; x++, bits+=2) {
2447 val = *srcpixel++;
2448 *bits++ = (BYTE)(((val >> 8) & 0xf8) | ((val >> 13) & 0x07));/*Blue*/
2449 *bits++ = (BYTE)(((val >> 3) & 0xfc) | ((val >> 9) & 0x03)); /*Green*/
2450 *bits = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x03)); /*Red*/
2452 bits = (dstbits += linebytes);
2455 else goto notsupported;
2457 break;
2459 case 1:
2460 /* ==== monochrome bitmap to 32 BGR dib ==== */
2461 case 4:
2462 /* ==== 4 colormap bitmap to 32 BGR dib ==== */
2463 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
2465 PALETTEENTRY val;
2467 for (h = lines - 1; h >= 0; h--) {
2468 for (x = 0; x < dstwidth; x++) {
2469 val = srccolors[XGetPixel(bmpImage, x, h)];
2470 *bits++ = val.peBlue;
2471 *bits++ = val.peGreen;
2472 *bits++ = val.peRed;
2473 *bits++ = 0;
2475 bits = (dstbits += linebytes);
2478 else goto notsupported;
2480 break;
2482 case 8:
2483 /* ==== 8 colormap bitmap to 32 BGR dib ==== */
2484 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
2486 BYTE *srcpixel;
2487 PALETTEENTRY val;
2489 for (h = lines - 1; h >= 0; h--) {
2490 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
2491 for (x = 0; x < dstwidth; x++) {
2492 val = srccolors[(int)*srcpixel++];
2493 *bits++ = val.peBlue; /*Blue*/
2494 *bits++ = val.peGreen; /*Green*/
2495 *bits++ = val.peRed; /*Red*/
2496 *bits++ = 0;
2498 bits = (dstbits += linebytes);
2501 else goto notsupported;
2502 break;
2504 default:
2505 notsupported:
2506 FIXME("from %d bit bitmap with mask R,G,B %x,%x,%x to 32 bit DIB\n",
2507 bmpImage->depth, (int)bmpImage->red_mask,
2508 (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
2509 for (h = lines - 1; h >= 0; h--)
2511 for (x = 0; x < dstwidth; x++, bits += 4)
2513 COLORREF pixel = X11DRV_PALETTE_ToLogical( XGetPixel( bmpImage, x, h ) );
2514 bits[0] = GetBValue(pixel);
2515 bits[1] = GetGValue(pixel);
2516 bits[2] = GetRValue(pixel);
2518 bits = (dstbits += linebytes);
2520 break;
2524 /***********************************************************************
2525 * X11DRV_DIB_SetImageBits
2527 * Transfer the bits to an X image.
2528 * Helper function for SetDIBits() and SetDIBitsToDevice().
2529 * The Xlib critical section must be entered before calling this function.
2531 int X11DRV_DIB_SetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
2533 int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
2534 XImage *bmpImage;
2536 if ( descr->dc && descr->dc->w.flags & DC_DIRTY )
2537 CLIPPING_UpdateGCRegion( descr->dc );
2539 if (descr->image)
2540 bmpImage = descr->image;
2541 else {
2542 bmpImage = XCreateImage( display, X11DRV_GetVisual(), descr->depth, ZPixmap, 0, NULL,
2543 descr->infoWidth, lines, 32, 0 );
2544 bmpImage->data = calloc( lines, bmpImage->bytes_per_line );
2545 if(bmpImage->data == NULL) {
2546 ERR("Out of memory!");
2547 XDestroyImage( bmpImage );
2548 return lines;
2552 /* Transfer the pixels */
2553 switch(descr->infoBpp)
2555 case 1:
2556 X11DRV_DIB_SetImageBits_1( descr->lines, descr->bits, descr->infoWidth,
2557 descr->width, descr->xSrc, (int *)(descr->colorMap),
2558 bmpImage );
2559 break;
2560 case 4:
2561 if (descr->compression) {
2562 XGetSubImage( display, descr->drawable, descr->xDest, descr->yDest,
2563 descr->width, descr->height, AllPlanes, ZPixmap,
2564 bmpImage, descr->xSrc, descr->ySrc );
2566 X11DRV_DIB_SetImageBits_RLE4( descr->lines, descr->bits,
2567 descr->infoWidth, descr->width,
2568 descr->xSrc, (int *)(descr->colorMap),
2569 bmpImage );
2570 } else
2571 X11DRV_DIB_SetImageBits_4( descr->lines, descr->bits,
2572 descr->infoWidth, descr->width,
2573 descr->xSrc, (int*)(descr->colorMap),
2574 bmpImage );
2575 break;
2576 case 8:
2577 if (descr->compression) {
2578 XGetSubImage( display, descr->drawable, descr->xDest, descr->yDest,
2579 descr->width, descr->height, AllPlanes, ZPixmap,
2580 bmpImage, descr->xSrc, descr->ySrc );
2581 X11DRV_DIB_SetImageBits_RLE8( descr->lines, descr->bits,
2582 descr->infoWidth, descr->width,
2583 descr->xSrc, (int *)(descr->colorMap),
2584 bmpImage );
2585 } else
2586 X11DRV_DIB_SetImageBits_8( descr->lines, descr->bits,
2587 descr->infoWidth, descr->width,
2588 descr->xSrc, (int *)(descr->colorMap),
2589 bmpImage );
2590 break;
2591 case 15:
2592 case 16:
2593 X11DRV_DIB_SetImageBits_16( descr->lines, descr->bits,
2594 descr->infoWidth, descr->width,
2595 descr->xSrc, descr->dc,
2596 descr->rMask, descr->gMask, descr->bMask,
2597 bmpImage);
2598 break;
2599 case 24:
2600 X11DRV_DIB_SetImageBits_24( descr->lines, descr->bits,
2601 descr->infoWidth, descr->width,
2602 descr->xSrc, descr->dc, bmpImage );
2603 break;
2604 case 32:
2605 X11DRV_DIB_SetImageBits_32( descr->lines, descr->bits,
2606 descr->infoWidth, descr->width,
2607 descr->xSrc, descr->dc,
2608 bmpImage);
2609 break;
2610 default:
2611 WARN("(%d): Invalid depth\n", descr->infoBpp );
2612 break;
2615 if (descr->useShm)
2617 XShmPutImage( display, descr->drawable, descr->gc, bmpImage,
2618 descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
2619 descr->width, descr->height, FALSE );
2620 XSync( display, 0 );
2622 else
2623 XPutImage( display, descr->drawable, descr->gc, bmpImage,
2624 descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
2625 descr->width, descr->height );
2627 if (!descr->image) XDestroyImage( bmpImage );
2628 return lines;
2631 /***********************************************************************
2632 * X11DRV_DIB_GetImageBits
2634 * Transfer the bits from an X image.
2635 * The Xlib critical section must be entered before calling this function.
2637 int X11DRV_DIB_GetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
2639 int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
2640 XImage *bmpImage;
2642 if (descr->image)
2643 bmpImage = descr->image;
2644 else {
2645 bmpImage = XCreateImage( display, X11DRV_GetVisual(), descr->depth, ZPixmap, 0, NULL,
2646 descr->infoWidth, lines, 32, 0 );
2647 bmpImage->data = calloc( lines, bmpImage->bytes_per_line );
2648 if(bmpImage->data == NULL) {
2649 ERR("Out of memory!");
2650 XDestroyImage( bmpImage );
2651 return lines;
2654 XGetSubImage( display, descr->drawable, descr->xDest, descr->yDest,
2655 descr->width, descr->height, AllPlanes, ZPixmap,
2656 bmpImage, descr->xSrc, descr->ySrc );
2658 /* Transfer the pixels */
2659 switch(descr->infoBpp)
2661 case 1:
2662 X11DRV_DIB_GetImageBits_1( descr->lines,(LPVOID)descr->bits,
2663 descr->infoWidth, descr->width,
2664 descr->colorMap, descr->palentry,
2665 bmpImage );
2666 break;
2668 case 4:
2669 if (descr->compression)
2670 FIXME("Compression not yet supported!\n");
2671 else
2672 X11DRV_DIB_GetImageBits_4( descr->lines,(LPVOID)descr->bits,
2673 descr->infoWidth, descr->width,
2674 descr->colorMap, descr->palentry,
2675 bmpImage );
2676 break;
2678 case 8:
2679 if (descr->compression)
2680 FIXME("Compression not yet supported!\n");
2681 else
2682 X11DRV_DIB_GetImageBits_8( descr->lines, (LPVOID)descr->bits,
2683 descr->infoWidth, descr->width,
2684 descr->colorMap, descr->palentry,
2685 bmpImage );
2686 break;
2687 case 15:
2688 case 16:
2689 X11DRV_DIB_GetImageBits_16( descr->lines, (LPVOID)descr->bits,
2690 descr->infoWidth,descr->width,
2691 descr->palentry, bmpImage );
2692 break;
2694 case 24:
2695 X11DRV_DIB_GetImageBits_24( descr->lines, (LPVOID)descr->bits,
2696 descr->infoWidth,descr->width,
2697 descr->palentry, bmpImage );
2698 break;
2700 case 32:
2701 X11DRV_DIB_GetImageBits_32( descr->lines, (LPVOID)descr->bits,
2702 descr->infoWidth, descr->width,
2703 descr->palentry, bmpImage );
2704 break;
2706 default:
2707 WARN("(%d): Invalid depth\n", descr->infoBpp );
2708 break;
2711 if (!descr->image) XDestroyImage( bmpImage );
2712 return lines;
2715 /*************************************************************************
2716 * X11DRV_SetDIBitsToDevice
2719 INT X11DRV_SetDIBitsToDevice( DC *dc, INT xDest, INT yDest, DWORD cx,
2720 DWORD cy, INT xSrc, INT ySrc,
2721 UINT startscan, UINT lines, LPCVOID bits,
2722 const BITMAPINFO *info, UINT coloruse )
2724 X11DRV_DIB_IMAGEBITS_DESCR descr;
2725 DWORD width, oldcy = cy;
2726 INT result;
2727 int height, tmpheight;
2728 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
2731 if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height,
2732 &descr.infoBpp, &descr.compression ) == -1)
2733 return 0;
2734 tmpheight = height;
2735 if (height < 0) height = -height;
2736 if (!lines || (startscan >= height)) return 0;
2737 if (startscan + lines > height) lines = height - startscan;
2738 if (ySrc < startscan) ySrc = startscan;
2739 else if (ySrc >= startscan + lines) return 0;
2740 if (xSrc >= width) return 0;
2741 if (ySrc + cy >= startscan + lines) cy = startscan + lines - ySrc;
2742 if (xSrc + cx >= width) cx = width - xSrc;
2743 if (!cx || !cy) return 0;
2745 X11DRV_SetupGCForText( dc ); /* To have the correct colors */
2746 TSXSetFunction(display, physDev->gc, X11DRV_XROPfunction[dc->w.ROPmode-1]);
2748 switch (descr.infoBpp)
2750 case 1:
2751 case 4:
2752 case 8:
2753 descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap(
2754 coloruse == DIB_PAL_COLORS ? dc : NULL, coloruse,
2755 dc->w.bitsPerPixel, info, &descr.nColorMap );
2756 if (!descr.colorMap) return 0;
2757 descr.rMask = descr.gMask = descr.bMask = 0;
2758 break;
2759 case 15:
2760 case 16:
2761 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
2762 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x03e0;
2763 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x001f;
2764 descr.colorMap = 0;
2765 break;
2767 case 24:
2768 descr.rMask = descr.gMask = descr.bMask = 0;
2769 descr.colorMap = 0;
2770 break;
2772 case 32:
2773 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
2774 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0xff00;
2775 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0xff;
2776 descr.colorMap = 0;
2777 break;
2780 descr.dc = dc;
2781 descr.bits = bits;
2782 descr.image = NULL;
2783 descr.palentry = NULL;
2784 descr.lines = tmpheight >= 0 ? lines : -lines;
2785 descr.infoWidth = width;
2786 descr.depth = dc->w.bitsPerPixel;
2787 descr.drawable = physDev->drawable;
2788 descr.gc = physDev->gc;
2789 descr.xSrc = xSrc;
2790 descr.ySrc = tmpheight >= 0 ? lines-(ySrc-startscan)-cy+(oldcy-cy)
2791 : ySrc - startscan;
2792 descr.xDest = dc->w.DCOrgX + XLPTODP( dc, xDest );
2793 descr.yDest = dc->w.DCOrgY + YLPTODP( dc, yDest ) +
2794 (tmpheight >= 0 ? oldcy-cy : 0);
2795 descr.width = cx;
2796 descr.height = cy;
2797 descr.useShm = FALSE;
2799 EnterCriticalSection( &X11DRV_CritSection );
2800 result = CALL_LARGE_STACK( X11DRV_DIB_SetImageBits, &descr );
2801 LeaveCriticalSection( &X11DRV_CritSection );
2803 if (descr.infoBpp <= 8)
2804 HeapFree(GetProcessHeap(), 0, descr.colorMap);
2805 return result;
2808 /***********************************************************************
2809 * X11DRV_DIB_SetDIBits
2811 INT X11DRV_DIB_SetDIBits(
2812 BITMAPOBJ *bmp, DC *dc, UINT startscan,
2813 UINT lines, LPCVOID bits, const BITMAPINFO *info,
2814 UINT coloruse, HBITMAP hbitmap)
2816 X11DRV_DIB_IMAGEBITS_DESCR descr;
2817 int height, tmpheight;
2818 INT result;
2820 descr.dc = dc;
2822 if (DIB_GetBitmapInfo( &info->bmiHeader, &descr.infoWidth, &height,
2823 &descr.infoBpp, &descr.compression ) == -1)
2824 return 0;
2826 tmpheight = height;
2827 if (height < 0) height = -height;
2828 if (!lines || (startscan >= height))
2829 return 0;
2831 if (startscan + lines > height) lines = height - startscan;
2833 switch (descr.infoBpp)
2835 case 1:
2836 case 4:
2837 case 8:
2838 descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap(
2839 coloruse == DIB_PAL_COLORS ? descr.dc : NULL, coloruse,
2840 bmp->bitmap.bmBitsPixel,
2841 info, &descr.nColorMap );
2842 if (!descr.colorMap) return 0;
2843 descr.rMask = descr.gMask = descr.bMask = 0;
2844 break;
2845 case 15:
2846 case 16:
2847 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
2848 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x03e0;
2849 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x001f;
2850 descr.colorMap = 0;
2851 break;
2853 case 24:
2854 descr.rMask = descr.gMask = descr.bMask = 0;
2855 descr.colorMap = 0;
2856 break;
2858 case 32:
2859 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
2860 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0xff00;
2861 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0xff;
2862 descr.colorMap = 0;
2863 break;
2865 default: break;
2868 /* HACK for now */
2869 if(!bmp->physBitmap)
2870 X11DRV_CreateBitmap(hbitmap);
2872 descr.bits = bits;
2873 descr.image = NULL;
2874 descr.palentry = NULL;
2875 descr.lines = tmpheight >= 0 ? lines : -lines;
2876 descr.depth = bmp->bitmap.bmBitsPixel;
2877 descr.drawable = (Pixmap)bmp->physBitmap;
2878 descr.gc = BITMAP_GC(bmp);
2879 descr.xSrc = 0;
2880 descr.ySrc = 0;
2881 descr.xDest = 0;
2882 descr.yDest = height - startscan - lines;
2883 descr.width = bmp->bitmap.bmWidth;
2884 descr.height = lines;
2885 descr.useShm = FALSE;
2887 EnterCriticalSection( &X11DRV_CritSection );
2888 result = CALL_LARGE_STACK( X11DRV_DIB_SetImageBits, &descr );
2889 LeaveCriticalSection( &X11DRV_CritSection );
2891 if (descr.colorMap) HeapFree(GetProcessHeap(), 0, descr.colorMap);
2893 return result;
2896 /***********************************************************************
2897 * X11DRV_DIB_GetDIBits
2899 INT X11DRV_DIB_GetDIBits(
2900 BITMAPOBJ *bmp, DC *dc, UINT startscan,
2901 UINT lines, LPVOID bits, BITMAPINFO *info,
2902 UINT coloruse, HBITMAP hbitmap)
2904 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
2905 X11DRV_DIB_IMAGEBITS_DESCR descr;
2906 PALETTEOBJ * palette;
2908 TRACE("%u scanlines of (%i,%i) -> (%i,%i) starting from %u\n",
2909 lines, bmp->bitmap.bmWidth, bmp->bitmap.bmHeight,
2910 (int)info->bmiHeader.biWidth, (int)info->bmiHeader.biHeight,
2911 startscan );
2913 if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->w.hPalette, PALETTE_MAGIC )))
2914 return 0;
2916 if( lines > info->bmiHeader.biHeight ) lines = info->bmiHeader.biHeight;
2917 /* Top-down images have a negative biHeight, the scanlines of theses images
2918 * were inverted in X11DRV_DIB_GetImageBits_xx
2919 * To prevent this we simply change the sign of lines
2920 * (the number of scan lines to copy).
2921 * Negative lines are correctly handled by X11DRV_DIB_GetImageBits_xx.
2923 if( info->bmiHeader.biHeight < 0 && lines > 0) lines = -lines;
2925 if( startscan >= bmp->bitmap.bmHeight ) return FALSE;
2927 if (DIB_GetBitmapInfo( &info->bmiHeader, &descr.infoWidth, &descr.lines,
2928 &descr.infoBpp, &descr.compression ) == -1)
2929 return FALSE;
2931 switch (descr.infoBpp)
2933 case 1:
2934 case 4:
2935 case 8:
2936 case 24:
2937 descr.rMask = descr.gMask = descr.bMask = 0;
2938 break;
2939 case 15:
2940 case 16:
2941 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
2942 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x03e0;
2943 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x001f;
2944 break;
2946 case 32:
2947 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
2948 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0xff00;
2949 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0xff;
2950 break;
2953 /* Hack for now */
2954 if(!bmp->physBitmap)
2955 X11DRV_CreateBitmap(hbitmap);
2958 descr.dc = dc;
2959 descr.palentry = palette->logpalette.palPalEntry;
2960 descr.bits = bits;
2961 descr.lines = lines;
2962 descr.depth = bmp->bitmap.bmBitsPixel;
2963 descr.drawable = (Pixmap)bmp->physBitmap;
2964 descr.gc = BITMAP_GC(bmp);
2965 descr.xSrc = 0;
2966 descr.ySrc = startscan;
2967 descr.xDest = 0;
2968 descr.yDest = 0;
2969 descr.width = bmp->bitmap.bmWidth;
2970 descr.height = bmp->bitmap.bmHeight;
2971 descr.colorMap = info->bmiColors;
2973 if (dib)
2974 descr.useShm = (dib->shminfo.shmid != -1);
2975 else
2976 descr.useShm = FALSE;
2978 EnterCriticalSection( &X11DRV_CritSection );
2980 descr.image = (XImage *)CALL_LARGE_STACK( X11DRV_BITMAP_GetXImage, bmp );
2981 CALL_LARGE_STACK( X11DRV_DIB_GetImageBits, &descr );
2983 LeaveCriticalSection( &X11DRV_CritSection );
2985 if(info->bmiHeader.biSizeImage == 0) /* Fill in biSizeImage */
2986 info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(
2987 info->bmiHeader.biWidth,
2988 info->bmiHeader.biHeight,
2989 info->bmiHeader.biBitCount );
2991 info->bmiHeader.biCompression = 0;
2993 GDI_HEAP_UNLOCK( dc->w.hPalette );
2995 return lines;
2998 /***********************************************************************
2999 * DIB_DoProtectDIBSection
3001 static void X11DRV_DIB_DoProtectDIBSection( BITMAPOBJ *bmp, DWORD new_prot )
3003 DIBSECTION *dib = bmp->dib;
3004 INT effHeight = dib->dsBm.bmHeight >= 0? dib->dsBm.bmHeight
3005 : -dib->dsBm.bmHeight;
3006 INT totalSize = dib->dsBmih.biSizeImage? dib->dsBmih.biSizeImage
3007 : dib->dsBm.bmWidthBytes * effHeight;
3008 DWORD old_prot;
3010 VirtualProtect(dib->dsBm.bmBits, totalSize, new_prot, &old_prot);
3011 TRACE("Changed protection from %ld to %ld\n", old_prot, new_prot);
3014 /***********************************************************************
3015 * X11DRV_DIB_DoUpdateDIBSection
3017 static void X11DRV_DIB_DoUpdateDIBSection(BITMAPOBJ *bmp, BOOL toDIB)
3019 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
3020 X11DRV_DIB_IMAGEBITS_DESCR descr;
3022 if (DIB_GetBitmapInfo( &dib->dibSection.dsBmih, &descr.infoWidth, &descr.lines,
3023 &descr.infoBpp, &descr.compression ) == -1)
3024 return;
3026 descr.dc = NULL;
3027 descr.palentry = NULL;
3028 descr.image = dib->image;
3029 descr.colorMap = (RGBQUAD *)dib->colorMap;
3030 descr.nColorMap = dib->nColorMap;
3031 descr.bits = dib->dibSection.dsBm.bmBits;
3032 descr.depth = bmp->bitmap.bmBitsPixel;
3034 switch (descr.infoBpp)
3036 case 1:
3037 case 4:
3038 case 8:
3039 case 24:
3040 descr.rMask = descr.gMask = descr.bMask = 0;
3041 break;
3042 case 15:
3043 case 16:
3044 descr.rMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[0] : 0x7c00;
3045 descr.gMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[1] : 0x03e0;
3046 descr.bMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[2] : 0x001f;
3047 break;
3049 case 32:
3050 descr.rMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[0] : 0xff;
3051 descr.gMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[1] : 0xff00;
3052 descr.bMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[2] : 0xff0000;
3053 break;
3056 /* Hack for now */
3057 descr.drawable = (Pixmap)bmp->physBitmap;
3058 descr.gc = BITMAP_GC(bmp);
3059 descr.xSrc = 0;
3060 descr.ySrc = 0;
3061 descr.xDest = 0;
3062 descr.yDest = 0;
3063 descr.width = bmp->bitmap.bmWidth;
3064 descr.height = bmp->bitmap.bmHeight;
3065 descr.useShm = (dib->shminfo.shmid != -1);
3067 if (toDIB)
3069 TRACE("Copying from Pixmap to DIB bits\n");
3070 EnterCriticalSection( &X11DRV_CritSection );
3071 CALL_LARGE_STACK( X11DRV_DIB_GetImageBits, &descr );
3072 LeaveCriticalSection( &X11DRV_CritSection );
3074 else
3076 TRACE("Copying from DIB bits to Pixmap\n");
3077 EnterCriticalSection( &X11DRV_CritSection );
3078 CALL_LARGE_STACK( X11DRV_DIB_SetImageBits, &descr );
3079 LeaveCriticalSection( &X11DRV_CritSection );
3083 /***********************************************************************
3084 * X11DRV_DIB_FaultHandler
3086 static BOOL X11DRV_DIB_FaultHandler( LPVOID res, LPCVOID addr )
3088 BOOL handled = FALSE;
3089 BITMAPOBJ *bmp;
3091 bmp = (BITMAPOBJ *)GDI_GetObjPtr( (HBITMAP)res, BITMAP_MAGIC );
3092 if (!bmp) return FALSE;
3094 if (bmp->dib)
3095 switch (((X11DRV_DIBSECTION *) bmp->dib)->status)
3097 case X11DRV_DIB_GdiMod:
3098 TRACE("called in status DIB_GdiMod\n" );
3099 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
3100 X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
3101 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
3102 ((X11DRV_DIBSECTION *) bmp->dib)->status = X11DRV_DIB_InSync;
3103 handled = TRUE;
3104 break;
3106 case X11DRV_DIB_InSync:
3107 TRACE("called in status X11DRV_DIB_InSync\n" );
3108 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
3109 ((X11DRV_DIBSECTION *) bmp->dib)->status = X11DRV_DIB_AppMod;
3110 handled = TRUE;
3111 break;
3113 case X11DRV_DIB_AppMod:
3114 FIXME("called in status X11DRV_DIB_AppMod: this can't happen!\n" );
3115 break;
3117 case X11DRV_DIB_NoHandler:
3118 FIXME("called in status DIB_NoHandler: this can't happen!\n" );
3119 break;
3122 GDI_HEAP_UNLOCK( (HBITMAP)res );
3123 return handled;
3126 /***********************************************************************
3127 * X11DRV_DIB_UpdateDIBSection
3129 void X11DRV_DIB_UpdateDIBSection(DC *dc, BOOL toDIB)
3131 BITMAPOBJ *bmp;
3133 /* Ensure this is a Compatible DC that has a DIB section selected */
3135 if (!dc) return;
3136 if (!(dc->w.flags & DC_MEMORY)) return;
3138 bmp = (BITMAPOBJ *)GDI_GetObjPtr( dc->w.hBitmap, BITMAP_MAGIC );
3139 if (!bmp) return;
3141 if (!bmp->dib)
3143 GDI_HEAP_UNLOCK(dc->w.hBitmap);
3144 return;
3147 if (!toDIB)
3149 /* Prepare for access to the DIB by GDI functions */
3151 switch (((X11DRV_DIBSECTION *) bmp->dib)->status)
3153 default:
3154 case X11DRV_DIB_NoHandler:
3155 X11DRV_DIB_DoUpdateDIBSection( bmp, FALSE );
3156 break;
3158 case X11DRV_DIB_GdiMod:
3159 TRACE("fromDIB called in status X11DRV_DIB_GdiMod\n" );
3160 /* nothing to do */
3161 break;
3163 case X11DRV_DIB_InSync:
3164 TRACE("fromDIB called in status X11DRV_DIB_InSync\n" );
3165 /* nothing to do */
3166 break;
3168 case X11DRV_DIB_AppMod:
3169 TRACE("fromDIB called in status X11DRV_DIB_AppMod\n" );
3170 X11DRV_DIB_DoUpdateDIBSection( bmp, FALSE );
3171 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
3172 ((X11DRV_DIBSECTION *) bmp->dib)->status = X11DRV_DIB_InSync;
3173 break;
3176 else
3178 /* Acknowledge write access to the DIB by GDI functions */
3180 switch (((X11DRV_DIBSECTION *) bmp->dib)->status)
3182 default:
3183 case X11DRV_DIB_NoHandler:
3184 X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
3185 break;
3187 case X11DRV_DIB_GdiMod:
3188 TRACE(" toDIB called in status X11DRV_DIB_GdiMod\n" );
3189 /* nothing to do */
3190 break;
3192 case X11DRV_DIB_InSync:
3193 TRACE(" toDIB called in status X11DRV_DIB_InSync\n" );
3194 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
3195 ((X11DRV_DIBSECTION *) bmp->dib)->status = X11DRV_DIB_GdiMod;
3196 break;
3198 case X11DRV_DIB_AppMod:
3199 FIXME(" toDIB called in status X11DRV_DIB_AppMod: "
3200 "this can't happen!\n" );
3201 break;
3205 GDI_HEAP_UNLOCK(dc->w.hBitmap);
3208 /***********************************************************************
3209 * X11DRV_DIB_CreateDIBSection16
3211 HBITMAP16 X11DRV_DIB_CreateDIBSection16(
3212 DC *dc, BITMAPINFO *bmi, UINT16 usage,
3213 SEGPTR *bits, HANDLE section,
3214 DWORD offset, DWORD ovr_pitch)
3216 HBITMAP res = X11DRV_DIB_CreateDIBSection(dc, bmi, usage, NULL,
3217 section, offset, ovr_pitch);
3218 if ( res )
3220 BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr(res, BITMAP_MAGIC);
3221 if ( bmp && bmp->dib )
3223 DIBSECTION *dib = bmp->dib;
3224 INT height = dib->dsBm.bmHeight >= 0 ?
3225 dib->dsBm.bmHeight : -dib->dsBm.bmHeight;
3226 INT size = dib->dsBmih.biSizeImage ?
3227 dib->dsBmih.biSizeImage : dib->dsBm.bmWidthBytes * height;
3228 if ( dib->dsBm.bmBits )
3230 ((X11DRV_DIBSECTION *) bmp->dib)->selector =
3231 SELECTOR_AllocBlock( dib->dsBm.bmBits, size,
3232 SEGMENT_DATA, FALSE, FALSE );
3234 TRACE("ptr = %p, size =%d, selector = %04x, segptr = %ld\n",
3235 dib->dsBm.bmBits, size, ((X11DRV_DIBSECTION *) bmp->dib)->selector,
3236 PTR_SEG_OFF_TO_SEGPTR(((X11DRV_DIBSECTION *) bmp->dib)->selector, 0));
3238 GDI_HEAP_UNLOCK( res );
3240 if ( bits )
3241 *bits = PTR_SEG_OFF_TO_SEGPTR( ((X11DRV_DIBSECTION *) bmp->dib)->selector, 0 );
3244 return res;
3247 /***********************************************************************
3248 * X11DRV_XShmErrorHandler
3251 static int XShmErrorHandler(Display *dpy, XErrorEvent *event)
3253 XShmErrorFlag = 1;
3254 return 0;
3257 /***********************************************************************
3258 * X11DRV_XShmCreateImage
3262 extern BOOL X11DRV_XShmCreateImage(XImage** image, int width, int height, int bpp,
3263 XShmSegmentInfo* shminfo)
3265 int (*WineXHandler)(Display *, XErrorEvent *);
3267 *image = TSXShmCreateImage(display, X11DRV_GetVisual(), bpp, ZPixmap, NULL, shminfo, width, height);
3268 if( *image != NULL )
3270 EnterCriticalSection( &X11DRV_CritSection );
3271 shminfo->shmid = shmget(IPC_PRIVATE, (*image)->bytes_per_line * height,
3272 IPC_CREAT|0700);
3273 if( shminfo->shmid != -1 )
3275 shminfo->shmaddr = (*image)->data = shmat(shminfo->shmid, 0, 0);
3276 if( shminfo->shmaddr != (char*)-1 )
3278 shminfo->readOnly = FALSE;
3279 if( TSXShmAttach( display, shminfo ) != 0)
3281 /* Reset the error flag */
3282 XShmErrorFlag = 0;
3283 WineXHandler = XSetErrorHandler(XShmErrorHandler);
3284 XSync( display, 0 );
3286 if (!XShmErrorFlag)
3288 shmctl(shminfo->shmid, IPC_RMID, 0);
3290 XSetErrorHandler(WineXHandler);
3291 LeaveCriticalSection( &X11DRV_CritSection );
3293 return TRUE; /* Success! */
3295 /* An error occured */
3296 XShmErrorFlag = 0;
3297 XSetErrorHandler(WineXHandler);
3299 shmdt(shminfo->shmaddr);
3301 shmctl(shminfo->shmid, IPC_RMID, 0);
3303 XFlush(display);
3304 XDestroyImage(*image);
3305 LeaveCriticalSection( &X11DRV_CritSection );
3307 return FALSE;
3313 /***********************************************************************
3314 * X11DRV_DIB_CreateDIBSection
3316 HBITMAP X11DRV_DIB_CreateDIBSection(
3317 DC *dc, BITMAPINFO *bmi, UINT usage,
3318 LPVOID *bits, HANDLE section,
3319 DWORD offset, DWORD ovr_pitch)
3321 HBITMAP res = 0;
3322 BITMAPOBJ *bmp = NULL;
3323 X11DRV_DIBSECTION *dib = NULL;
3324 int *colorMap = NULL;
3325 int nColorMap;
3327 /* Fill BITMAP32 structure with DIB data */
3328 BITMAPINFOHEADER *bi = &bmi->bmiHeader;
3329 INT effHeight, totalSize;
3330 BITMAP bm;
3332 TRACE("format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
3333 bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
3334 bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
3336 effHeight = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
3337 bm.bmType = 0;
3338 bm.bmWidth = bi->biWidth;
3339 bm.bmHeight = effHeight;
3340 bm.bmWidthBytes = ovr_pitch ? ovr_pitch
3341 : DIB_GetDIBWidthBytes(bm.bmWidth, bi->biBitCount);
3342 bm.bmPlanes = bi->biPlanes;
3343 bm.bmBitsPixel = bi->biBitCount;
3344 bm.bmBits = NULL;
3346 /* Get storage location for DIB bits */
3347 totalSize = bi->biSizeImage? bi->biSizeImage : bm.bmWidthBytes * effHeight;
3349 if (section)
3350 bm.bmBits = MapViewOfFile(section, FILE_MAP_ALL_ACCESS,
3351 0L, offset, totalSize);
3352 else if (ovr_pitch && offset)
3353 bm.bmBits = (LPVOID) offset;
3354 else {
3355 offset = 0;
3356 bm.bmBits = VirtualAlloc(NULL, totalSize,
3357 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
3360 /* Create Color Map */
3361 if (bm.bmBits && bm.bmBitsPixel <= 8)
3362 colorMap = X11DRV_DIB_BuildColorMap( usage == DIB_PAL_COLORS? dc : NULL,
3363 usage, bm.bmBitsPixel, bmi, &nColorMap );
3365 /* Allocate Memory for DIB and fill structure */
3366 if (bm.bmBits)
3367 dib = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(X11DRV_DIBSECTION));
3368 if (dib)
3370 dib->dibSection.dsBm = bm;
3371 dib->dibSection.dsBmih = *bi;
3373 /* Set dsBitfields values */
3374 if ( usage == DIB_PAL_COLORS || bi->biBitCount <= 8)
3376 dib->dibSection.dsBitfields[0] = dib->dibSection.dsBitfields[1] = dib->dibSection.dsBitfields[2] = 0;
3378 else switch( bi->biBitCount )
3380 case 16:
3381 dib->dibSection.dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors : 0x7c00;
3382 dib->dibSection.dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0x03e0;
3383 dib->dibSection.dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0x001f;
3384 break;
3386 case 24:
3387 dib->dibSection.dsBitfields[0] = 0xff;
3388 dib->dibSection.dsBitfields[1] = 0xff00;
3389 dib->dibSection.dsBitfields[2] = 0xff0000;
3390 break;
3392 case 32:
3393 dib->dibSection.dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors : 0xff;
3394 dib->dibSection.dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0xff00;
3395 dib->dibSection.dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0xff0000;
3396 break;
3398 dib->dibSection.dshSection = section;
3399 dib->dibSection.dsOffset = offset;
3401 dib->status = X11DRV_DIB_NoHandler;
3402 dib->selector = 0;
3404 dib->nColorMap = nColorMap;
3405 dib->colorMap = colorMap;
3408 /* Create Device Dependent Bitmap and add DIB pointer */
3409 if (dib)
3411 res = CreateDIBitmap(dc->hSelf, bi, 0, NULL, bmi, usage);
3412 if (res)
3414 bmp = (BITMAPOBJ *) GDI_GetObjPtr(res, BITMAP_MAGIC);
3415 if (bmp)
3417 bmp->dib = (DIBSECTION *) dib;
3418 /* HACK for now */
3419 if(!bmp->physBitmap)
3420 X11DRV_CreateBitmap(res);
3425 /* Create XImage */
3426 if (dib && bmp)
3428 if (TSXShmQueryExtension(display) &&
3429 X11DRV_XShmCreateImage( &dib->image, bm.bmWidth, effHeight,
3430 bmp->bitmap.bmBitsPixel, &dib->shminfo ) )
3432 ; /* Created Image */
3433 } else {
3434 XCREATEIMAGE( dib->image, bm.bmWidth, effHeight, bmp->bitmap.bmBitsPixel );
3435 dib->shminfo.shmid = -1;
3439 /* Clean up in case of errors */
3440 if (!res || !bmp || !dib || !bm.bmBits || (bm.bmBitsPixel <= 8 && !colorMap))
3442 TRACE("got an error res=%08x, bmp=%p, dib=%p, bm.bmBits=%p\n",
3443 res, bmp, dib, bm.bmBits);
3444 if (bm.bmBits)
3446 if (section)
3447 UnmapViewOfFile(bm.bmBits), bm.bmBits = NULL;
3448 else if (!offset)
3449 VirtualFree(bm.bmBits, 0L, MEM_RELEASE), bm.bmBits = NULL;
3452 if (dib && dib->image) { XDestroyImage(dib->image); dib->image = NULL; }
3453 if (colorMap) { HeapFree(GetProcessHeap(), 0, colorMap); colorMap = NULL; }
3454 if (dib) { HeapFree(GetProcessHeap(), 0, dib); dib = NULL; }
3455 if (res) { DeleteObject(res); res = 0; }
3458 /* Install fault handler, if possible */
3459 if (bm.bmBits)
3461 if (VIRTUAL_SetFaultHandler(bm.bmBits, X11DRV_DIB_FaultHandler, (LPVOID)res))
3463 if (section || offset)
3465 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
3466 if (dib) dib->status = X11DRV_DIB_AppMod;
3468 else
3470 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
3471 if (dib) dib->status = X11DRV_DIB_InSync;
3476 /* Return BITMAP handle and storage location */
3477 if (res) GDI_HEAP_UNLOCK(res);
3478 if (bm.bmBits && bits) *bits = bm.bmBits;
3479 return res;
3482 /***********************************************************************
3483 * X11DRV_DIB_DeleteDIBSection
3485 void X11DRV_DIB_DeleteDIBSection(BITMAPOBJ *bmp)
3487 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
3489 if (dib->image)
3491 if (dib->shminfo.shmid != -1)
3493 TSXShmDetach (display, &(dib->shminfo));
3494 XDestroyImage (dib->image);
3495 shmdt (dib->shminfo.shmaddr);
3496 dib->shminfo.shmid = -1;
3498 else
3499 XDestroyImage( dib->image );
3502 if (dib->colorMap)
3503 HeapFree(GetProcessHeap(), 0, dib->colorMap);
3505 if (dib->selector)
3507 WORD count = (GET_SEL_LIMIT( dib->selector ) >> 16) + 1;
3508 SELECTOR_FreeBlock( dib->selector, count );
3513 /**************************************************************************
3514 * X11DRV_DIB_CreateDIBFromPixmap
3516 * Allocates a packed DIB and copies the Pixmap data into it.
3517 * If bDeletePixmap is TRUE, the Pixmap passed in is deleted after the conversion.
3519 HGLOBAL X11DRV_DIB_CreateDIBFromPixmap(Pixmap pixmap, HDC hdc, BOOL bDeletePixmap)
3521 HBITMAP hBmp = 0;
3522 BITMAPOBJ *pBmp = NULL;
3523 HGLOBAL hPackedDIB = 0;
3525 /* Allocates an HBITMAP which references the Pixmap passed to us */
3526 hBmp = X11DRV_BITMAP_CreateBitmapHeaderFromPixmap(pixmap);
3527 if (!hBmp)
3529 TRACE("\tCould not create bitmap header for Pixmap\n");
3530 goto END;
3534 * Create a packed DIB from the Pixmap wrapper bitmap created above.
3535 * A packed DIB contains a BITMAPINFO structure followed immediately by
3536 * an optional color palette and the pixel data.
3538 hPackedDIB = DIB_CreateDIBFromBitmap(hdc, hBmp);
3540 /* Get a pointer to the BITMAPOBJ structure */
3541 pBmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
3543 /* We can now get rid of the HBITMAP wrapper we created earlier.
3544 * Note: Simply calling DeleteObject will free the embedded Pixmap as well.
3546 if (!bDeletePixmap)
3548 /* Clear the physBitmap to prevent the Pixmap from being deleted by DeleteObject */
3549 pBmp->physBitmap = NULL;
3550 pBmp->funcs = NULL;
3552 DeleteObject(hBmp);
3554 END:
3555 TRACE("\tReturning packed DIB %x\n", hPackedDIB);
3556 return hPackedDIB;
3560 /**************************************************************************
3561 * X11DRV_DIB_CreatePixmapFromDIB
3563 * Creates a Pixmap from a packed DIB
3565 Pixmap X11DRV_DIB_CreatePixmapFromDIB( HGLOBAL hPackedDIB, HDC hdc )
3567 Pixmap pixmap = None;
3568 HBITMAP hBmp = 0;
3569 BITMAPOBJ *pBmp = NULL;
3570 LPBYTE pPackedDIB = NULL;
3571 LPBITMAPINFO pbmi = NULL;
3572 LPBITMAPINFOHEADER pbmiHeader = NULL;
3573 LPBYTE pbits = NULL;
3575 /* Get a pointer to the packed DIB's data */
3576 pPackedDIB = (LPBYTE)GlobalLock(hPackedDIB);
3577 pbmiHeader = (LPBITMAPINFOHEADER)pPackedDIB;
3578 pbmi = (LPBITMAPINFO)pPackedDIB;
3579 pbits = (LPBYTE)(pPackedDIB
3580 + DIB_BitmapInfoSize( (LPBITMAPINFO)pbmiHeader, DIB_RGB_COLORS ));
3582 /* Create a DDB from the DIB */
3584 hBmp = CreateDIBitmap(hdc,
3585 pbmiHeader,
3586 CBM_INIT,
3587 (LPVOID)pbits,
3588 pbmi,
3589 DIB_RGB_COLORS);
3591 GlobalUnlock(hPackedDIB);
3593 TRACE("CreateDIBitmap returned %x\n", hBmp);
3595 /* Retrieve the internal Pixmap from the DDB */
3597 pBmp = (BITMAPOBJ *) GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
3599 pixmap = (Pixmap)pBmp->physBitmap;
3600 /* clear the physBitmap so that we can steal its pixmap */
3601 pBmp->physBitmap = NULL;
3602 pBmp->funcs = NULL;
3604 /* Delete the DDB we created earlier now that we have stolen its pixmap */
3605 DeleteObject(hBmp);
3607 TRACE("\tReturning Pixmap %ld\n", pixmap);
3608 return pixmap;