Jean-Claude Batista (Macadamian/Corel)
[wine/multimedia.git] / graphics / x11drv / dib.c
blob9a501280681c03913f10a6bdfdc323fb94dc8add
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 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 for (h = lines - 1; h >= 0; h--) {
906 for (x = left; x < dstwidth; x++, bits++) {
907 color = colors[*bits];
908 XPutPixel( bmpImage, x, h, colors[*bits] );
910 bits = (srcbits += linebytes) + left;
914 /***********************************************************************
915 * X11DRV_DIB_GetImageBits_8
917 * GetDIBits for an 8-bit deep DIB.
919 static void X11DRV_DIB_GetImageBits_8( int lines, BYTE *dstbits,
920 DWORD srcwidth, DWORD dstwidth,
921 RGBQUAD *colors, PALETTEENTRY *srccolors,
922 XImage *bmpImage )
924 DWORD x;
925 int h;
926 BYTE *bits;
928 /* align to 32 bit */
929 DWORD linebytes = (srcwidth + 3) & ~3;
931 if (lines < 0 )
933 lines = -lines;
934 dstbits = dstbits + ( linebytes * (lines-1) );
935 linebytes = -linebytes;
938 bits = dstbits;
941 Hack for now
942 This condition is true when GetImageBits has been called by UpdateDIBSection.
943 For now, GetNearestIndex is too slow to support 256 colormaps, so we'll just use for
944 for GetDIBits calls. (In somes cases, in a updateDIBSection, the returned colors are bad too)
946 if (!srccolors) goto updatesection;
948 switch(bmpImage->depth) {
950 case 1:
951 /* ==== monochrome bitmap to 8 colormap dib ==== */
952 case 4:
953 /* ==== 4 colormap bitmap to 8 colormap dib ==== */
954 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
956 PALETTEENTRY val;
958 for (h = lines - 1; h >= 0; h--) {
959 for (x = 0; x < dstwidth; x++) {
960 val = srccolors[XGetPixel(bmpImage, x, h)];
961 *bits++ = X11DRV_DIB_GetNearestIndex(colors, 256, val.peRed,
962 val.peGreen, val.peBlue);
964 bits = (dstbits += linebytes);
967 else goto notsupported;
969 break;
971 case 8:
972 /* ==== 8 colormap bitmap to 8 colormap dib ==== */
973 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
975 BYTE *srcpixel;
976 PALETTEENTRY val;
978 for (h = lines - 1; h >= 0; h--) {
979 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
980 for (x = 0; x < dstwidth; x++) {
981 val = srccolors[(int)*srcpixel++];
982 *bits++ = X11DRV_DIB_GetNearestIndex(colors, 256, val.peRed,
983 val.peGreen, val.peBlue);
985 bits = (dstbits += linebytes);
988 else goto notsupported;
990 break;
992 case 15:
994 LPWORD srcpixel;
995 WORD val;
997 /* ==== 555 BGR bitmap to 8 colormap dib ==== */
998 if (bmpImage->red_mask == 0x7c00 && bmpImage->blue_mask == 0x001f)
1000 for( h = lines - 1; h >= 0; h--)
1002 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
1003 for( x = 0; x < dstwidth; x++ )
1005 val = *srcpixel++;
1006 *bits++ = X11DRV_DIB_GetNearestIndex( colors, 256,
1007 ((val >> 7) & 0xf8) |
1008 ((val >> 12) & 0x7),
1009 ((val >> 2) & 0xf8) |
1010 ((val >> 7) & 0x3),
1011 ((val << 3) & 0xf8) |
1012 ((val >> 2) & 0x7) );
1014 bits = (dstbits += linebytes);
1017 /* ==== 555 RGB bitmap to 8 colormap dib ==== */
1018 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0x7c00)
1020 for( h = lines - 1; h >= 0; h--)
1022 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
1023 for( x = 0; x < dstwidth; x++ )
1025 val = *srcpixel++;
1026 *bits++ = X11DRV_DIB_GetNearestIndex( colors, 256,
1027 ((val << 3) & 0xf8) |
1028 ((val >> 2) & 0x7),
1029 ((val >> 2) & 0xf8) |
1030 ((val >> 7) & 0x3),
1031 ((val >> 7) & 0xf8) |
1032 ((val >> 12) & 0x7) );
1034 bits = (dstbits += linebytes);
1037 else goto notsupported;
1039 break;
1041 case 16:
1043 LPWORD srcpixel;
1044 WORD val;
1046 /* ==== 565 BGR bitmap to 8 colormap dib ==== */
1047 if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f)
1049 for( h = lines - 1; h >= 0; h--)
1051 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
1052 for( x = 0; x < dstwidth; x++ )
1054 val = *srcpixel++;
1055 *bits++ = X11DRV_DIB_GetNearestIndex( colors, 256,
1056 ((val >> 8) & 0xf8) |
1057 ((val >> 13) & 0x7),
1058 ((val >> 3) & 0xfc) |
1059 ((val >> 9) & 0x3),
1060 ((val << 3) & 0xf8) |
1061 ((val >> 2) & 0x7) );
1063 bits = (dstbits += linebytes);
1066 /* ==== 565 RGB bitmap to 8 colormap dib ==== */
1067 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0xf800)
1069 for( h = lines - 1; h >= 0; h--)
1071 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
1072 for( x = 0; x < dstwidth; x++ )
1074 val = *srcpixel++;
1075 *bits++ = X11DRV_DIB_GetNearestIndex( colors, 256,
1076 ((val << 3) & 0xf8) |
1077 ((val >> 2) & 0x7),
1078 ((val >> 3) & 0x00fc) |
1079 ((val >> 9) & 0x3),
1080 ((val >> 8) & 0x00f8) |
1081 ((val >> 13) & 0x7) );
1083 bits = (dstbits += linebytes);
1086 else goto notsupported;
1088 break;
1090 case 24:
1091 case 32:
1093 BYTE *srcpixel;
1095 /* ==== 24/32 BGR bitmap to 8 colormap dib ==== */
1096 if (bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff)
1098 for (h = lines - 1; h >= 0; h--)
1100 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
1101 for (x = 0; x < dstwidth; x++, srcpixel+=4)
1102 *bits++ = X11DRV_DIB_GetNearestIndex(colors, 256,
1103 srcpixel[2] , srcpixel[1], *srcpixel);
1104 bits = (dstbits += linebytes);
1107 /* ==== 24/32 RGB bitmap to 8 colormap dib ==== */
1108 else if (bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000)
1110 for (h = lines - 1; h >= 0; h--)
1112 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
1113 for (x = 0; x < dstwidth; x++, srcpixel+=4)
1114 *bits++ = X11DRV_DIB_GetNearestIndex(colors, 256,
1115 *srcpixel, srcpixel[1], srcpixel[2]);
1116 bits = (dstbits += linebytes);
1120 else goto notsupported;
1122 break;
1124 default: /* ? bit bmp -> 8 bit DIB */
1125 notsupported:
1126 FIXME("from %d bit bitmap with mask R,G,B %x,%x,%x to 8 bit DIB\n",
1127 bmpImage->depth, (int)bmpImage->red_mask,
1128 (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
1129 updatesection:
1130 for (h = lines - 1; h >= 0; h--) {
1131 for (x = 0; x < dstwidth; x++, bits++) {
1132 *bits = X11DRV_DIB_MapColor((int *)colors, 256,
1133 XGetPixel( bmpImage, x, h ) );
1135 bits = (dstbits += linebytes);
1137 break;
1141 /***********************************************************************
1142 * X11DRV_DIB_SetImageBits_RLE8
1144 * SetDIBits for an 8-bit deep compressed DIB.
1146 * This function rewritten 941113 by James Youngman. WINE blew out when I
1147 * first ran it because my desktop wallpaper is a (large) RLE8 bitmap.
1149 * This was because the algorithm assumed that all RLE8 bitmaps end with the
1150 * 'End of bitmap' escape code. This code is very much laxer in what it
1151 * allows to end the expansion. Possibly too lax. See the note by
1152 * case RleDelta. BTW, MS's documentation implies that a correct RLE8
1153 * bitmap should end with RleEnd, but on the other hand, software exists
1154 * that produces ones that don't and Windows 3.1 doesn't complain a bit
1155 * about it.
1157 * (No) apologies for my English spelling. [Emacs users: c-indent-level=4].
1158 * James A. Youngman <mbcstjy@afs.man.ac.uk>
1159 * [JAY]
1162 enum Rle8_EscapeCodes
1165 * Apologies for polluting your file's namespace...
1167 RleEol = 0, /* End of line */
1168 RleEnd = 1, /* End of bitmap */
1169 RleDelta = 2 /* Delta */
1172 static void X11DRV_DIB_SetImageBits_RLE8( int lines, const BYTE *bits,
1173 DWORD width, DWORD dstwidth,
1174 int left, int *colors,
1175 XImage *bmpImage )
1177 int x; /* X-positon on each line. Increases. */
1178 int line; /* Line #. Starts at lines-1, decreases */
1179 const BYTE *pIn = bits; /* Pointer to current position in bits */
1180 BYTE length; /* The length pf a run */
1181 BYTE color_index; /* index into colors[] as read from bits */
1182 BYTE escape_code; /* See enum Rle8_EscapeCodes.*/
1183 int color; /* value of colour[color_index] */
1185 if (lines == 0) /* Let's hope this doesn't happen. */
1186 return;
1189 * Note that the bitmap data is stored by Windows starting at the
1190 * bottom line of the bitmap and going upwards. Within each line,
1191 * the data is stored left-to-right. That's the reason why line
1192 * goes from lines-1 to 0. [JAY]
1195 x = 0;
1196 line = lines-1;
1199 length = *pIn++;
1202 * If the length byte is not zero (which is the escape value),
1203 * We have a run of length pixels all the same colour. The colour
1204 * index is stored next.
1206 * If the length byte is zero, we need to read the next byte to
1207 * know what to do. [JAY]
1209 if (length != 0)
1212 * [Run-Length] Encoded mode
1214 color_index = (*pIn++); /* Get the colour index. */
1215 color = colors[color_index];
1217 while(length--)
1218 XPutPixel(bmpImage, x++, line, color);
1220 else
1223 * Escape codes (may be an absolute sequence though)
1225 escape_code = (*pIn++);
1226 switch(escape_code)
1228 case RleEol: /* =0, end of line */
1230 x = 0;
1231 line--;
1232 break;
1235 case RleEnd: /* =1, end of bitmap */
1238 * Not all RLE8 bitmaps end with this
1239 * code. For example, Paint Shop Pro
1240 * produces some that don't. That's (I think)
1241 * what caused the previous implementation to
1242 * fail. [JAY]
1244 line=-1; /* Cause exit from do loop. */
1245 break;
1248 case RleDelta: /* =2, a delta */
1251 * Note that deltaing to line 0
1252 * will cause an exit from the loop,
1253 * which may not be what is intended.
1254 * The fact that there is a delta in the bits
1255 * almost certainly implies that there is data
1256 * to follow. You may feel that we should
1257 * jump to the top of the loop to avoid exiting
1258 * in this case.
1260 * TODO: Decide what to do here in that case. [JAY]
1262 x += (*pIn++);
1263 line -= (*pIn++);
1264 if (line == 0)
1266 TRACE("Delta to last line of bitmap "
1267 "(wrongly?) causes loop exit\n");
1269 break;
1272 default: /* >2, switch to absolute mode */
1275 * Absolute Mode
1277 length = escape_code;
1278 while(length--)
1280 color_index = (*pIn++);
1281 XPutPixel(bmpImage, x++, line,
1282 colors[color_index]);
1286 * If you think for a moment you'll realise that the
1287 * only time we could ever possibly read an odd
1288 * number of bytes is when there is a 0x00 (escape),
1289 * a value >0x02 (absolute mode) and then an odd-
1290 * length run. Therefore this is the only place we
1291 * need to worry about it. Everywhere else the
1292 * bytes are always read in pairs. [JAY]
1294 if (escape_code & 1)
1295 pIn++; /* Throw away the pad byte. */
1296 break;
1298 } /* switch (escape_code) : Escape sequence */
1299 } /* process either an encoded sequence or an escape sequence */
1301 /* We expect to come here more than once per line. */
1302 } while (line >= 0); /* Do this until the bitmap is filled */
1305 * Everybody comes here at the end.
1306 * Check how we exited the loop and print a message if it's a bit odd.
1307 * [JAY]
1309 if ( (*(pIn-2) != 0/*escape*/) || (*(pIn-1)!= RleEnd) )
1311 TRACE("End-of-bitmap without (strictly) proper escape code. Last two "
1312 "bytes were: %02X %02X.\n", (int)*(pIn-2),(int)*(pIn-1));
1317 /***********************************************************************
1318 * X11DRV_DIB_SetImageBits_16
1320 * SetDIBits for a 16-bit deep DIB.
1322 static void X11DRV_DIB_SetImageBits_16( int lines, const BYTE *srcbits,
1323 DWORD srcwidth, DWORD dstwidth, int left,
1324 DC *dc, DWORD rSrc, DWORD gSrc, DWORD bSrc,
1325 XImage *bmpImage )
1327 DWORD x;
1328 int h;
1330 /* align to 32 bit */
1331 DWORD linebytes = (srcwidth * 2 + 3) & ~3;
1333 if (lines < 0 )
1335 lines = -lines;
1336 srcbits = srcbits + ( linebytes * (lines-1));
1337 linebytes = -linebytes;
1340 switch ( bmpImage->depth )
1342 case 15:
1343 /* using same format as XImage */
1344 if (rSrc == bmpImage->red_mask && gSrc == bmpImage->green_mask && bSrc == bmpImage->blue_mask)
1345 for (h = lines - 1; h >= 0; h--, srcbits += linebytes)
1346 memcpy ( bmpImage->data + h * bmpImage->bytes_per_line + left*2, srcbits + left*2, dstwidth*2 );
1347 else /* We need to do a conversion from a 565 dib */
1349 LPDWORD dstpixel, ptr = (LPDWORD)(srcbits + left*2);
1350 DWORD val;
1351 int div = dstwidth % 2;
1353 for (h = lines - 1; h >= 0; h--) {
1354 dstpixel = (LPDWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1355 for (x = 0; x < dstwidth/2; x++) { /* Do 2 pixels at a time */
1356 val = *ptr++;
1357 *dstpixel++ = ((val >> 1) & 0x7fe07fe0) | (val & 0x001f001f); /* Red & Green & Blue */
1359 if (div != 0) /* Odd width? */
1360 *dstpixel = ((*(WORD *)ptr >> 1) & 0x7fe0) | (*(WORD *)ptr & 0x001f);
1361 ptr = (LPDWORD) ((srcbits += linebytes) + left*2);
1364 break;
1366 case 16:
1367 /* using same format as XImage */
1368 if (rSrc == bmpImage->red_mask && gSrc == bmpImage->green_mask && bSrc == bmpImage->blue_mask)
1369 for (h = lines - 1; h >= 0; h--, srcbits += linebytes)
1370 memcpy ( bmpImage->data + h * bmpImage->bytes_per_line + left*2, srcbits + left*2, dstwidth*2 );
1371 else /* We need to do a conversion from a 555 dib */
1373 LPDWORD dstpixel, ptr = (LPDWORD)(srcbits + left*2);
1374 DWORD val;
1375 int div = dstwidth % 2;
1377 for (h = lines - 1; h >= 0; h--) {
1378 dstpixel = (LPDWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1379 for (x = 0; x < dstwidth/2; x++) { /* Do 2 pixels at a time */
1380 val = *ptr++;
1381 *dstpixel++ = ((val << 1) & 0xffc0ffc0) | ((val >> 4) & 0x00200020) | /* Red & Green */
1382 (val & 0x001f001f); /* Blue */
1384 if (div != 0) /* Odd width? */
1385 *dstpixel = ((*(WORD *)ptr << 1) & 0xffc0) | ((*(WORD *)ptr >> 4) & 0x0020)
1386 | (*(WORD *)ptr & 0x001f);
1387 ptr = (LPDWORD) ((srcbits += linebytes) + left*2);
1390 break;
1392 case 24:
1393 case 32:
1395 DWORD *dstpixel;
1396 LPWORD ptr = (LPWORD)srcbits + left;
1397 DWORD val;
1399 /* ==== 555 BGR dib to 24/32 BGR bitmap ==== */
1400 if (bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff)
1402 for (h = lines - 1; h >= 0; h--) {
1403 dstpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line + left*4);
1404 for (x = 0; x < dstwidth; x++) {
1406 val = *ptr++;
1407 *dstpixel++ = ((val << 9) & 0xf80000) | ((val << 4) & 0x070000) | /* Red */
1408 ((val << 6) & 0x00f800) | ((val << 1) & 0x000700) | /* Green */
1409 ((val << 3) & 0x0000f8) | ((val >> 2) & 0x000007); /* Blue */
1411 ptr = (LPWORD)(srcbits += linebytes) + left;
1414 /* ==== 555 BGR dib to 24/32 RGB bitmap ==== */
1415 else if (bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000)
1417 for (h = lines - 1; h >= 0; h--) {
1418 dstpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line + left*4);
1419 for (x = 0; x < dstwidth; x++) {
1421 val = *ptr++;
1422 *dstpixel++ = ((val >> 7) & 0x0000f8) | ((val >> 12) & 0x000007) | /* Red */
1423 ((val << 6) & 0x00f800) | ((val << 1) & 0x000700) | /* Green */
1424 ((val << 19) & 0xf80000) | ((val >> 14) & 0x070000); /* Blue */
1426 ptr = (LPWORD)(srcbits += linebytes) + left;
1431 break;
1433 case 1:
1434 case 4:
1435 case 8:
1437 LPWORD ptr = (LPWORD)srcbits + left;
1438 WORD val;
1439 int sc1, sc2;
1441 /* Set color scaling values */
1442 if ( rSrc == 0x7c00 ) { sc1 = 7; sc2 = 2; } /* 555 dib */
1443 else { sc1 = 8; sc2 = 3; } /* 565 dib */
1445 for (h = lines - 1; h >= 0; h--) {
1446 for (x = left; x < dstwidth+left; x++) {
1447 val = *ptr++;
1448 XPutPixel( bmpImage, x, h,
1449 X11DRV_PALETTE_ToPhysical(dc, RGB(((val & rSrc) >> sc1), /* Red */
1450 ((val & gSrc) >> sc2), /* Green */
1451 ((val & bSrc) << 3)))); /* Blue */
1453 ptr = (LPWORD) (srcbits += linebytes) + left;
1456 break;
1458 default:
1459 FIXME("16 bit DIB %d bit bitmap\n", bmpImage->bits_per_pixel);
1460 break;
1466 /***********************************************************************
1467 * X11DRV_DIB_GetImageBits_16
1469 * GetDIBits for an 16-bit deep DIB.
1471 static void X11DRV_DIB_GetImageBits_16( int lines, BYTE *dstbits,
1472 DWORD dstwidth, DWORD srcwidth,
1473 PALETTEENTRY *srccolors, XImage *bmpImage )
1475 DWORD x;
1476 int h;
1478 /* align to 32 bit */
1479 DWORD linebytes = (dstwidth * 2 + 3) & ~3;
1481 if (lines < 0 )
1483 lines = -lines;
1484 dstbits = dstbits + ( linebytes * (lines-1));
1485 linebytes = -linebytes;
1488 switch ( bmpImage->depth )
1490 case 15:
1491 /* ==== 555 BGR bitmap to 555 BGR dib ==== */
1492 if (bmpImage->red_mask == 0x7c00 && bmpImage->blue_mask == 0x001f)
1493 for (h = lines - 1; h >= 0; h--, dstbits += linebytes)
1494 memcpy( dstbits, bmpImage->data + h*bmpImage->bytes_per_line, srcwidth*2 );
1496 /* ==== 555 RGB bitmap to 555 BGR dib ==== */
1497 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0x7c00)
1499 LPDWORD srcpixel, ptr = (LPDWORD)dstbits;
1500 DWORD val;
1501 int div = srcwidth % 2;
1503 for (h = lines - 1; h >= 0; h--) {
1504 srcpixel = (LPDWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
1505 for (x = 0; x < srcwidth/2; x++) { /* Do 2 pixels at a time */
1506 val = *srcpixel++;
1507 *ptr++ = ((val << 10) & 0xf800f800) | (val & 0x03e003e0) | /* Red & Green */
1508 ((val >> 10) & 0x001f001f); /* Blue */
1510 if (div != 0) /* Odd width? */
1511 *ptr = ((*(WORD *)srcpixel << 1) & 0xffc0) | ((*(WORD *)srcpixel >> 4) & 0x0020) |
1512 (*(WORD *)srcpixel & 0x001f);
1513 ptr = (LPDWORD)(dstbits += linebytes);
1516 else goto notsupported;
1518 break;
1520 case 16:
1522 LPDWORD srcpixel, ptr = (LPDWORD)dstbits;
1523 DWORD val;
1524 int div = srcwidth % 2;
1526 /* ==== 565 BGR bitmap to 555 BGR dib ==== */
1527 if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f )
1529 for (h = lines - 1; h >= 0; h--) {
1530 srcpixel = (LPDWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
1531 for (x = 0; x < srcwidth/2; x++) { /* Do 2 pixels at a time */
1532 val = *srcpixel++;
1533 *ptr++ = ((val >> 1) & 0x7fe07fe0) | /* Red & Green */
1534 (val & 0x001f001f); /* Blue */
1536 if (div != 0) /* Odd width? */
1537 *ptr = ((*(WORD *)srcpixel >> 1) & 0x7fe0) | (*(WORD *)srcpixel & 0x001f);
1538 ptr = (LPDWORD) (dstbits += linebytes);
1541 /* ==== 565 RGB bitmap to 555 BGR dib ==== */
1542 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0xf800)
1544 for (h = lines - 1; h >= 0; h--) {
1545 srcpixel = (LPDWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
1546 for (x = 0; x < srcwidth/2; x++) { /* Do 2 pixels at a time */
1547 val = *srcpixel++;
1548 *ptr++ = ((val << 10) & 0x7c007c00) | ((val >> 1) & 0x03e003e0) | /* Red & Green */
1549 ((val >> 11) & 0x001f001f); /* Blue */
1551 if (div != 0) /* Odd width? */
1552 *ptr = ((*(WORD *)srcpixel >> 1) & 0x7fe0) | (*(WORD *)srcpixel & 0x001f);
1553 ptr = (LPDWORD) (dstbits += linebytes);
1556 else goto notsupported;
1558 break;
1560 case 24:
1561 case 32:
1563 DWORD *srcpixel;
1564 LPWORD ptr = (LPWORD)dstbits;
1565 DWORD val;
1567 /* ==== 24/32 BGR bitmap to 555 BGR dib ==== */
1568 if (bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff)
1570 for (h = lines - 1; h >= 0; h--) {
1571 srcpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line);
1572 for (x = 0; x < srcwidth; x++, ptr++) {
1573 val = *srcpixel++;
1574 *ptr = ((val >> 9) & 0x7c00) | /* Red */
1575 ((val >> 6) & 0x03e0) | /* Green */
1576 ((val >> 3) & 0x001f); /* Blue */
1578 ptr = (LPWORD)(dstbits += linebytes);
1581 /* ==== 24/32 RGB bitmap to 555 BGR dib ==== */
1582 else if (bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000)
1584 for (h = lines - 1; h >= 0; h--) {
1585 srcpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line);
1586 for (x = 0; x < srcwidth; x++, ptr++) {
1587 val = *srcpixel++;
1588 *ptr = ((val << 7) & 0x7c00) | /* Red */
1589 ((val >> 6) & 0x03e0) | /* Green */
1590 ((val >> 19) & 0x001f); /* Blue */
1592 ptr = (LPWORD) (dstbits += linebytes);
1595 else goto notsupported;
1597 break;
1599 case 1:
1600 /* ==== monochrome bitmap to 16 BGR dib ==== */
1601 case 4:
1602 /* ==== 4 colormap bitmap to 16 BGR dib ==== */
1603 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
1605 LPWORD ptr = (LPWORD)dstbits;
1606 PALETTEENTRY val;
1608 for (h = lines - 1; h >= 0; h--) {
1609 for (x = 0; x < dstwidth; x++) {
1610 val = srccolors[XGetPixel(bmpImage, x, h)];
1611 *ptr++ = ((val.peRed << 7) & 0x7c00) |
1612 ((val.peGreen << 2) & 0x03e0) |
1613 ((val.peBlue >> 3) & 0x001f);
1615 ptr = (LPWORD)(dstbits += linebytes);
1618 else goto notsupported;
1620 break;
1622 case 8:
1623 /* ==== 8 colormap bitmap to 16 BGR dib ==== */
1624 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
1626 LPWORD ptr = (LPWORD)dstbits;
1627 BYTE *srcpixel;
1628 PALETTEENTRY val;
1630 for (h = lines - 1; h >= 0; h--) {
1631 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
1632 for (x = 0; x < dstwidth; x++) {
1633 val = srccolors[(int)*srcpixel++];
1634 *ptr++ = ((val.peRed << 7) & 0x7c00) |
1635 ((val.peGreen << 2) & 0x03e0) |
1636 ((val.peBlue >> 3) & 0x001f);
1638 ptr = (LPWORD)(dstbits += linebytes);
1641 else goto notsupported;
1643 break;
1645 default:
1646 notsupported:
1648 BYTE r,g, b;
1649 LPWORD ptr = (LPWORD)dstbits;
1651 FIXME("from %d bit bitmap with mask R,G,B %x,%x,%x to 16 bit DIB\n",
1652 bmpImage->depth, (int)bmpImage->red_mask,
1653 (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
1654 for (h = lines - 1; h >= 0; h--)
1656 for (x = 0; x < dstwidth; x++, ptr++)
1658 COLORREF pixel = X11DRV_PALETTE_ToLogical( XGetPixel( bmpImage, x, h ) );
1659 r = (BYTE) GetRValue(pixel);
1660 g = (BYTE) GetGValue(pixel);
1661 b = (BYTE) GetBValue(pixel);
1662 *ptr = ( ((r << 7) & 0x7c00) | ((g << 2) & 0x03e0) | ((b >> 3) & 0x001f) );
1664 ptr = (LPWORD) (dstbits += linebytes);
1667 break;
1672 /***********************************************************************
1673 * X11DRV_DIB_SetImageBits_24
1675 * SetDIBits for a 24-bit deep DIB.
1677 static void X11DRV_DIB_SetImageBits_24( int lines, const BYTE *srcbits,
1678 DWORD srcwidth, DWORD dstwidth, int left,
1679 DC *dc, XImage *bmpImage )
1681 DWORD x;
1682 int h;
1684 /* align to 32 bit */
1685 DWORD linebytes = (srcwidth * 3 + 3) & ~3;
1687 if (lines < 0 )
1689 lines = -lines;
1690 srcbits = srcbits + linebytes * (lines - 1);
1691 linebytes = -linebytes;
1694 switch ( bmpImage->depth )
1696 case 24:
1698 if (bmpImage->bits_per_pixel == 24) {
1699 int dstlinebytes = linebytes;
1700 BYTE *dstpixel;
1701 BYTE *ptr = (BYTE *)(srcbits+left*3);
1703 if (dstlinebytes < 0 ) dstlinebytes = -dstlinebytes;
1704 dstpixel = bmpImage->data + lines*dstlinebytes + left*3;
1705 for(h = lines ; h-- ; ) {
1706 dstpixel-=dstlinebytes;
1707 memcpy(dstpixel,ptr,dstwidth*3);
1708 ptr +=linebytes;
1710 break;
1713 case 32:
1715 if( bmpImage->blue_mask == 0xff && bmpImage->red_mask == 0xff0000 ) /* packed BGR to unpacked BGR */
1717 DWORD *dstpixel, val, buf;
1718 DWORD *ptr = (DWORD *)(srcbits + left*3);
1719 BYTE *bits;
1720 int div = dstwidth % 4;
1721 int divk;
1723 for(h = lines - 1; h >= 0; h--)
1725 dstpixel = (DWORD *) (bmpImage->data + h*bmpImage->bytes_per_line + left*4);
1727 for (x = 0; x < dstwidth/4; x++) { /* do 3 dwords source, 4 dwords dest at a time */
1728 buf = *ptr++;
1729 *dstpixel++ = buf&0x00ffffff; /* b1, g1, r1 */
1730 val = (buf >> 24); /* b2 */
1731 buf = *ptr++;
1732 *dstpixel++ = (val | (buf<<8)) &0x00ffffff; /* g2, r2 */
1733 val = (buf >> 16); /* b3, g3 */
1734 buf = *ptr++;
1735 *dstpixel++ = (val | (buf<<16)) &0x00ffffff; /* r3 */
1736 *dstpixel++ = (buf >> 8); /* b4, g4, r4 */
1738 for ( divk=div, bits=(BYTE*)ptr; divk>0; divk--, bits+=3 ) /* do remainder */
1740 *dstpixel++ = *(DWORD*)bits & 0x00ffffff; /* b, g, r */
1742 ptr = (DWORD*)((srcbits+=linebytes)+left*3);
1745 else if( bmpImage->blue_mask == 0xff0000 && bmpImage->red_mask == 0xff ) /* packed BGR to unpacked RGB */
1747 DWORD *dstpixel, val, buf;
1748 DWORD *ptr = (DWORD *)(srcbits + left*3);
1749 BYTE *bits;
1750 int div = dstwidth % 4;
1751 int divk;
1753 for(h = lines - 1; h >= 0; h--)
1755 dstpixel = (DWORD *) (bmpImage->data + h*bmpImage->bytes_per_line + left*4);
1757 for (x = 0; x < dstwidth/4; x++) { /* do 3 dwords source, 4 dwords dest at a time */
1758 buf = *ptr++;
1759 *dstpixel++ = ((buf&0xff)<<16) | (buf&0xff00) | ((buf&0xff0000)>>16); /* b1, g1, r1 */
1760 val = ((buf&0xff000000)>>8); /* b2 */
1761 buf = *ptr++;
1762 *dstpixel++ = val | ((buf&0xff)<<8) | ((buf&0xff00)>>8); /* g2, r2 */
1763 val = (buf&0xff0000) | ((buf&0xff000000)>>16); /* b3, g3 */
1764 buf = *ptr++;
1765 *dstpixel++ = val | (buf&0xff); /* r3 */
1766 *dstpixel++ = ((buf&0xff00)<<8) | ((buf&0xff0000)>>8) | (buf>>24); /* b4, g4, r4 */
1768 for ( divk=div, bits=(BYTE*)ptr; divk>0; divk--, bits+=3 ) /* do remainder */
1770 buf = *(DWORD*)bits;
1771 *dstpixel++ = ((buf&0xff)<<16) | (buf&0xff00) | ((buf&0xff0000)>>16); /* b, g, r */
1773 ptr = (DWORD*)((srcbits+=linebytes)+left*3);
1776 else
1777 goto notsupported;
1779 break;
1781 case 15:
1783 if( bmpImage->blue_mask == 0x7c00 && bmpImage->red_mask == 0x1f ) /* BGR888 to RGB555 */
1785 DWORD *ptr = (DWORD *)(srcbits + left*3), val;
1786 LPBYTE bits;
1787 LPWORD dstpixel;
1788 int div = dstwidth % 4;
1789 int divk;
1791 for (h = lines - 1; h >= 0; h--) { /* Do 4 pixels at a time */
1792 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1793 for (x = 0; x < dstwidth/4; x++) {
1794 *dstpixel++ = (WORD)((((val = *ptr++) << 7) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 19) & 0x1f));
1795 *dstpixel++ = (WORD)(((val >> 17) & 0x7c00) | (((val = *ptr++) << 2) & 0x03e0) | ((val >> 11) & 0x1f));
1796 *dstpixel++ = (WORD)(((val >> 9) & 0x07c00) | ((val >> 22) & 0x03e0) | (((val = *ptr++) >> 3) & 0x1f));
1797 *dstpixel++ = (WORD)(((val >> 1) & 0x07c00) | ((val >> 14) & 0x03e0) | ((val >> 27) & 0x1f));
1799 for (bits = (LPBYTE)ptr, divk=div; divk > 0; divk--, bits+=3) /* dstwidth not divisible by 4? */
1800 *dstpixel++ = (((WORD)bits[0] << 7) & 0x07c00) |
1801 (((WORD)bits[1] << 2) & 0x03e0) |
1802 (((WORD)bits[2] >> 3) & 0x001f);
1803 ptr = (DWORD *)((srcbits += linebytes) + left * 3);
1806 else if( bmpImage->blue_mask == 0x1f && bmpImage->red_mask == 0x7c00 ) /* BGR888 to BGR555 */
1808 DWORD *ptr = (DWORD *)(srcbits + left*3), val;
1809 LPBYTE bits;
1810 LPWORD dstpixel;
1811 int div = dstwidth % 4;
1812 int divk;
1814 for (h = lines - 1; h >= 0; h--) { /* Do 4 pixels at a time */
1815 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1816 for (x = 0; x < dstwidth/4; x++) {
1817 *dstpixel++ = (WORD)((((val = *ptr++) >> 3) & 0x1f) | ((val >> 6) & 0x03e0) | ((val >> 9) & 0x7c00));
1818 *dstpixel++ = (WORD)(((val >> 27) & 0x1f) | (((val = *ptr++) << 2) & 0x03e0) | ((val >> 1) & 0x7c00));
1819 *dstpixel++ = (WORD)(((val >> 19) & 0x1f) | ((val >> 22) & 0x03e0) | (((val = *ptr++) << 7) & 0x7c00));
1820 *dstpixel++ = (WORD)(((val >> 11) & 0x1f) | ((val >> 14) & 0x03e0) | ((val >> 17) & 0x7c00));
1822 for (bits = (LPBYTE)ptr, divk=div; divk > 0; divk--, bits+=3) /* dstwidth not divisible by 4? */
1823 *dstpixel++ = (((WORD)bits[2] << 7) & 0x07c00) |
1824 (((WORD)bits[1] << 2) & 0x03e0) |
1825 (((WORD)bits[0] >> 3) & 0x001f);
1826 ptr = (DWORD *)((srcbits += linebytes) + left * 3);
1829 else
1830 goto notsupported;
1832 break;
1834 case 16:
1836 DWORD *ptr = (DWORD *)(srcbits + left*3), val;
1837 LPBYTE bits;
1838 LPWORD dstpixel;
1839 int div = dstwidth % 4;
1840 int divk;
1842 if( bmpImage->blue_mask == 0x001f && bmpImage->red_mask == 0xf800 ) /* BGR888 to BGR565 */
1844 for (h = lines - 1; h >= 0; h--) { /* Do 4 pixels at a time */
1845 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1846 for (x = 0; x < dstwidth/4; x++) {
1847 *dstpixel++ = (WORD)((((val = *ptr++) >> 3) & 0x1f) | ((val >> 5) & 0x07e0) | ((val >> 8) & 0xf800));
1848 *dstpixel++ = (WORD)(((val >> 27) & 0x1f) | (((val = *ptr++) << 3) & 0x07e0) | ((val) & 0xf800));
1849 *dstpixel++ = (WORD)(((val >> 19) & 0x1f) | ((val >> 21) & 0x07e0) | (((val = *ptr++) << 8) & 0xf800));
1850 *dstpixel++ = (WORD)(((val >> 11) & 0x1f) | ((val >> 13) & 0x07e0) | ((val >> 16) & 0xf800));
1852 for ( bits = (LPBYTE)ptr, divk=div; divk > 0; divk--, bits+=3) /* dstwidth is not divisible by 4? */
1853 *dstpixel++ = (((WORD)bits[2] << 8) & 0xf800) |
1854 (((WORD)bits[1] << 3) & 0x07e0) |
1855 (((WORD)bits[0] >> 3) & 0x001f);
1856 ptr = (DWORD *)((srcbits += linebytes) + left * 3);
1859 else if( bmpImage->blue_mask == 0xf800 && bmpImage->red_mask == 0x001f ) /* BGR888 to RGB565 */
1861 for (h = lines - 1; h >= 0; h--) { /* Do 4 pixels at a time */
1862 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1863 for (x = 0; x < dstwidth/4; x++) {
1864 *dstpixel++ = (WORD)((((val = *ptr++) << 8) & 0xf800) | ((val >> 5) & 0x07e0) | ((val >> 19) & 0x1f));
1865 *dstpixel++ = (WORD)(((val >> 16) & 0xf800) | (((val = *ptr++) << 3) & 0x07e0) | ((val >> 11) & 0x1f));
1866 *dstpixel++ = (WORD)(((val >> 8) & 0xf800) | ((val >> 21) & 0x07e0) | (((val = *ptr++) >> 3) & 0x1f));
1867 *dstpixel++ = (WORD)((val & 0xf800) | ((val >> 13) & 0x07e0) | ((val >> 27) & 0x1f));
1869 for ( bits = (LPBYTE)ptr, divk=div; divk > 0; divk--, bits+=3) /* dstwidth is not divisible by 4? */
1870 *dstpixel++ = (((WORD)bits[0] << 8) & 0xf800) |
1871 (((WORD)bits[1] << 3) & 0x07e0) |
1872 (((WORD)bits[2] >> 3) & 0x001f);
1873 ptr = (DWORD *)((srcbits += linebytes) + left * 3);
1876 else
1877 goto notsupported;
1879 break;
1881 case 1:
1882 case 4:
1883 case 8:
1885 LPBYTE bits = (LPBYTE)srcbits + left*3;
1887 for (h = lines - 1; h >= 0; h--) {
1888 for (x = left; x < dstwidth+left; x++, bits+=3)
1889 XPutPixel( bmpImage, x, h,
1890 X11DRV_PALETTE_ToPhysical(dc, RGB(bits[2], bits[1], bits[0])));
1891 bits = (LPBYTE)(srcbits += linebytes) + left * 3;
1894 break;
1896 default:
1897 notsupported:
1898 FIXME("from 24 bit DIB to %d bit bitmap with mask R,G,B %x,%x,%x\n",
1899 bmpImage->bits_per_pixel, (int)bmpImage->red_mask,
1900 (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
1901 break;
1906 /***********************************************************************
1907 * X11DRV_DIB_GetImageBits_24
1909 * GetDIBits for an 24-bit deep DIB.
1911 static void X11DRV_DIB_GetImageBits_24( int lines, BYTE *dstbits,
1912 DWORD dstwidth, DWORD srcwidth,
1913 PALETTEENTRY *srccolors, XImage *bmpImage )
1915 DWORD x, val;
1916 int h;
1918 /* align to 32 bit */
1919 DWORD linebytes = (dstwidth * 3 + 3) & ~3;
1921 if (lines < 0 )
1923 lines = -lines;
1924 dstbits = dstbits + ( linebytes * (lines-1) );
1925 linebytes = -linebytes;
1928 switch ( bmpImage->depth )
1930 case 24:
1932 if (bmpImage->bits_per_pixel == 24) {
1933 int tocopy = linebytes;
1934 BYTE *srcpixel;
1935 BYTE *ptr = (LPBYTE)dstbits;
1937 if (tocopy < 0 ) tocopy = -tocopy;
1938 srcpixel = bmpImage->data + lines*tocopy;
1939 for(h = lines ; h-- ; ) {
1940 srcpixel-=tocopy;
1941 memcpy(ptr,srcpixel,tocopy);
1942 ptr = (LPBYTE)(dstbits+=linebytes);
1944 break;
1947 case 32:
1949 DWORD *srcpixel, buf;
1950 LPBYTE bits;
1951 DWORD *ptr=(DWORD *)dstbits;
1952 int quotient = dstwidth / 4;
1953 int remainder = dstwidth % 4;
1954 int remk;
1956 /* ==== 24/32 BGR bitmap to 24 BGR dib==== */
1957 if( bmpImage->blue_mask == 0xff && bmpImage->red_mask == 0xff0000 )
1959 for(h = lines - 1; h >= 0; h--)
1961 srcpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line);
1963 for (x = 0; x < quotient; x++) { /* do 4 dwords source, 3 dwords dest at a time*/
1964 buf = ((*srcpixel++)&0x00ffffff); /* b1, g1, r1*/
1965 *ptr++ = buf | ((*srcpixel)<<24); /* b2 */
1966 buf = ((*srcpixel++>>8)&0x0000ffff); /* g2, r2 */
1967 *ptr++ = buf | ((*srcpixel)<<16); /* b3, g3 */
1968 buf = ((*srcpixel++>>16)&0x000000ff); /* r3 */
1969 *ptr++ = buf | ((*srcpixel++)<<8); /* b4, g4, r4 */
1971 for ( remk=remainder, bits=(BYTE*)ptr; remk>0; remk--, bits+=3 ) /* do remainder */
1973 buf=*srcpixel++;
1974 *(WORD*)bits = buf; /* b, g */
1975 *(bits+2) = buf>>16; /* r */
1977 ptr = (DWORD*)(dstbits+=linebytes);
1981 /* ==== 24/32 RGB bitmap to 24 BGR dib ==== */
1982 else if( bmpImage->blue_mask == 0xff0000 && bmpImage->red_mask == 0xff )
1984 for(h = lines - 1; h >= 0; h--)
1986 srcpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line);
1988 for (x = 0; x < quotient; x++) { /* do 4 dwords source, 3 dwords dest at a time */
1989 buf = *srcpixel++;
1990 val = ((buf&0xff0000)>>16) | (buf&0xff00) | ((buf&0xff)<<16); /* b1, g1, r1 */
1991 buf = *srcpixel++;
1992 *ptr++ = val | ((buf&0xff0000)<<8); /* b2 */
1993 val = ((buf&0xff00)>>8) | ((buf&0xff)<<8); /* g2, r2 */
1994 buf = *srcpixel++;
1995 *ptr++ = val | (buf&0xff0000) | ((buf&0xff00)<<16); /* b3, g3 */
1996 val = (buf&0xff); /* r3 */
1997 buf = *srcpixel++;
1998 *ptr++ = val | ((buf&0xff0000)>>8) | ((buf&0xff00)<<8) | (buf<<24); /* b4, g4, r4 */
2000 for ( remk=remainder, bits=(BYTE*)ptr; remk>0; remk--, bits+=3 ) /* do remainder */
2002 buf=*srcpixel++;
2003 *(WORD*)bits = (buf&0xff00) | ((buf&0xff0000)>>16) ; /* b, g */
2004 *(bits+2) = buf; /* r */
2006 ptr = (DWORD*)(dstbits+=linebytes);
2009 else goto notsupported;
2011 break;
2013 case 15:
2015 LPWORD srcpixel;
2016 LPBYTE bits = dstbits;
2017 WORD val;
2019 /* ==== 555 BGR bitmap to 24 BGR dib ==== */
2020 if( bmpImage->blue_mask == 0x1f && bmpImage->red_mask == 0x7c00 )
2022 for (h = lines - 1; h >= 0; h--) {
2023 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2024 for (x = 0; x < srcwidth; x++, bits += 3) {
2025 val = *srcpixel++;
2026 bits[2] = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07)); /*Red*/
2027 bits[1] = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07)); /*Green*/
2028 bits[0] = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07)); /*Blue*/
2030 bits = (dstbits += linebytes);
2033 /* ==== 555 RGB bitmap to 24 RGB dib==== */
2034 else if( bmpImage->blue_mask == 0x7c00 && bmpImage->red_mask == 0x1f )
2036 for (h = lines - 1; h >= 0; h--) {
2037 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2038 for (x = 0; x < srcwidth; x++, bits += 3) {
2039 val = *srcpixel++;
2040 bits[0] = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07)); /*Red*/
2041 bits[1] = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07)); /*Green*/
2042 bits[2] = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07)); /*Blue*/
2044 bits = (dstbits += linebytes);
2047 else goto notsupported;
2049 break;
2051 case 16:
2053 LPWORD srcpixel;
2054 LPBYTE bits = dstbits;
2055 WORD val;
2057 /* ==== 565 BGR bitmap to 24 BGR dib ==== */
2058 if( bmpImage->blue_mask == 0x1f && bmpImage->red_mask == 0xf800 )
2060 for (h = lines - 1; h >= 0; h--) {
2061 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2062 for (x = 0; x < srcwidth; x++, bits += 3) {
2063 val = *srcpixel++;
2064 bits[2] = (BYTE)(((val >> 8) & 0xf8) | ((val >> 13) & 0x07)); /*Red*/
2065 bits[1] = (BYTE)(((val >> 3) & 0xfc) | ((val >> 9) & 0x03)); /*Green*/
2066 bits[0] = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07)); /*Blue*/
2068 bits = (dstbits += linebytes);
2071 /* ==== 565 RGB bitmap to 24 BGR dib ==== */
2072 else if( bmpImage->blue_mask == 0xf800 && bmpImage->red_mask == 0x1f )
2074 for (h = lines - 1; h >= 0; h--) {
2075 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2076 for (x = 0; x < srcwidth; x++, bits += 3) {
2077 val = *srcpixel++;
2078 bits[0] = (BYTE)(((val >> 8) & 0xf8) | ((val >> 13) & 0x07)); /*Red*/
2079 bits[1] = (BYTE)(((val >> 3) & 0xfc) | ((val >> 9) & 0x03)); /*Green*/
2080 bits[2] = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07)); /*Blue*/
2082 bits = (dstbits += linebytes);
2085 else goto notsupported;
2087 break;
2089 case 1:
2090 /* ==== monochrome bitmap to 24 BGR dib ==== */
2091 case 4:
2092 /* ==== 4 colormap bitmap to 24 BGR dib ==== */
2093 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
2095 LPBYTE bits = dstbits;
2096 PALETTEENTRY val;
2098 for (h = lines - 1; h >= 0; h--) {
2099 for (x = 0; x < dstwidth; x++) {
2100 val = srccolors[XGetPixel(bmpImage, x, h)];
2101 *bits++ = val.peBlue;
2102 *bits++ = val.peGreen;
2103 *bits++ = val.peRed;
2105 bits = (dstbits += linebytes);
2108 else goto notsupported;
2110 break;
2112 case 8:
2113 /* ==== 8 colormap bitmap to 24 BGR dib ==== */
2114 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask == 0 && srccolors)
2116 BYTE *srcpixel;
2117 LPBYTE bits = dstbits;
2118 PALETTEENTRY val;
2120 for (h = lines - 1; h >= 0; h--) {
2121 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
2122 for (x = 0; x < dstwidth; x++ ) {
2123 val = srccolors[(int)*srcpixel++];
2124 *bits++ = val.peBlue; /*Blue*/
2125 *bits++ = val.peGreen; /*Green*/
2126 *bits++ = val.peRed; /*Red*/
2128 bits = (dstbits += linebytes);
2131 else goto notsupported;
2133 break;
2135 default:
2136 notsupported:
2138 LPBYTE bits = dstbits;
2140 FIXME("from %d bit bitmap with mask R,G,B %x,%x,%x to 24 bit DIB\n",
2141 bmpImage->depth, (int)bmpImage->red_mask,
2142 (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
2143 for (h = lines - 1; h >= 0; h--)
2145 for (x = 0; x < dstwidth; x++, bits += 3)
2147 COLORREF pixel = X11DRV_PALETTE_ToLogical( XGetPixel( bmpImage, x, h ) );
2148 bits[0] = GetBValue(pixel);
2149 bits[1] = GetGValue(pixel);
2150 bits[2] = GetRValue(pixel);
2152 bits = (dstbits += linebytes);
2155 break;
2160 /***********************************************************************
2161 * X11DRV_DIB_SetImageBits_32
2163 * SetDIBits for a 32-bit deep DIB.
2165 static void X11DRV_DIB_SetImageBits_32( int lines, const BYTE *srcbits,
2166 DWORD srcwidth, DWORD dstwidth, int left,
2167 DC *dc, XImage *bmpImage )
2169 DWORD x, *ptr;
2170 int h;
2172 DWORD linebytes = (srcwidth * 4);
2174 if (lines < 0 )
2176 lines = -lines;
2177 srcbits = srcbits + ( linebytes * (lines-1) );
2178 linebytes = -linebytes;
2181 ptr = (DWORD *) srcbits + left;
2183 switch ( bmpImage->depth )
2185 case 24:
2186 case 32:
2187 /* ==== 32 BGR dib to 24/32 BGR bitmap ==== */
2188 if (bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff) {
2189 for (h = lines - 1; h >= 0; h--, srcbits+=linebytes) {
2190 memcpy( bmpImage->data + h * bmpImage->bytes_per_line, srcbits + left*4, dstwidth*4 );
2194 /* ==== 32 BGR dib to 24/32 RGB bitmap ==== */
2195 else if (bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000)
2197 DWORD *dstpixel;
2199 for (h = lines - 1; h >= 0; h--) {
2200 dstpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line);
2201 for (x = 0; x < dstwidth; x++, ptr++) {
2202 *dstpixel++ = ((*ptr << 16) & 0xff0000) | (*ptr & 0xff00) | ((*ptr >> 16) & 0xff);
2204 ptr = (DWORD *) (srcbits += linebytes) + left;
2207 else goto notsupported;
2209 break;
2211 case 15:
2212 /* ==== 32 BGR dib to 555 BGR bitmap ==== */
2213 if (bmpImage->red_mask == 0x7c00 && bmpImage->blue_mask == 0x001f)
2215 LPWORD dstpixel;
2217 for (h = lines - 1; h >= 0; h--) {
2218 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2219 for (x = 0; x < dstwidth; x++, ptr++) {
2220 *dstpixel++ = (WORD) (((*ptr >> 9) & 0x7c00) | ((*ptr >> 6) & 0x03e0) | ((*ptr >> 3) & 0x001f));
2222 ptr = (DWORD *) (srcbits += linebytes) + left;
2225 /* ==== 32 BGR dib to 555 RGB bitmap ==== */
2226 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0x7c00)
2228 LPWORD dstpixel;
2230 for (h = lines - 1; h >= 0; h--) {
2231 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2232 for (x = 0; x < dstwidth; x++, ptr++) {
2233 *dstpixel++ = (WORD) (((*ptr << 7) & 0x7c00) | ((*ptr >> 6) & 0x03e0) | ((*ptr >> 19) & 0x001f));
2235 ptr = (DWORD *) (srcbits += linebytes) + left;
2238 else goto notsupported;
2240 break;
2242 case 16:
2243 /* ==== 32 BGR dib to 565 BGR bitmap ==== */
2244 if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f)
2246 LPWORD dstpixel;
2248 for (h = lines - 1; h >= 0; h--) {
2249 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2250 for (x = 0; x < dstwidth; x++, ptr++) {
2251 *dstpixel++ = (WORD) (((*ptr >> 8) & 0xf800) | ((*ptr >> 5) & 0x07e0) | ((*ptr >> 3) & 0x001f));
2253 ptr = (DWORD *) (srcbits += linebytes) + left;
2256 /* ==== 32 BGR dib to 565 RGB bitmap ==== */
2257 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0xf800)
2259 LPWORD dstpixel;
2261 for (h = lines - 1; h >= 0; h--) {
2262 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2263 for (x = 0; x < dstwidth; x++, ptr++) {
2264 *dstpixel++ = (WORD) (((*ptr << 8) & 0xf800) | ((*ptr >> 5) & 0x07e0) | ((*ptr >> 19) & 0x001f));
2266 ptr = (DWORD *) (srcbits += linebytes) + left;
2269 else goto notsupported;
2271 break;
2273 case 1:
2274 case 4:
2275 case 8:
2277 LPBYTE bits = (LPBYTE)srcbits + left*4;
2279 for (h = lines - 1; h >= 0; h--) {
2280 for (x = left; x < dstwidth+left; x++, bits += 4)
2281 XPutPixel( bmpImage, x, h,
2282 X11DRV_PALETTE_ToPhysical(dc, RGB( bits[2], bits[1], *bits )));
2283 bits = (LPBYTE)(srcbits += linebytes) + left * 4;
2286 break;
2288 default:
2289 notsupported:
2290 FIXME("32 bit DIB %d bit bitmap\n", bmpImage->bits_per_pixel);
2291 break;
2296 /***********************************************************************
2297 * X11DRV_DIB_GetImageBits_32
2299 * GetDIBits for an 32-bit deep DIB.
2301 static void X11DRV_DIB_GetImageBits_32( int lines, BYTE *dstbits,
2302 DWORD dstwidth, DWORD srcwidth,
2303 PALETTEENTRY *srccolors, XImage *bmpImage )
2305 DWORD x;
2306 int h;
2307 BYTE *bits;
2309 /* align to 32 bit */
2310 DWORD linebytes = (srcwidth * 4);
2311 DWORD copybytes = linebytes;
2313 if (lines < 0 )
2315 lines = -lines;
2316 dstbits = dstbits + ( linebytes * (lines-1) );
2317 linebytes = -linebytes;
2320 bits = dstbits;
2322 switch ( bmpImage->depth )
2324 case 24:
2325 case 32:
2326 /* ==== 24/32 BGR bitmap to 32 BGR dib ==== */
2327 if ( bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff )
2328 for (h = lines - 1; h >= 0; h--, dstbits+=linebytes)
2329 memcpy( dstbits, bmpImage->data + h*bmpImage->bytes_per_line, copybytes );
2331 /* ==== 24/32 RGB bitmap to 32 BGR dib ==== */
2332 else if ( bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000 )
2334 LPBYTE srcbits;
2336 for (h = lines - 1; h >= 0; h--) {
2337 srcbits = bmpImage->data + h * bmpImage->bytes_per_line;
2338 for (x = 0; x < dstwidth; x++, bits+=4, srcbits+=2) {
2339 *(bits + 2) = *srcbits++;
2340 *(bits + 1) = *srcbits++;
2341 *bits = *srcbits;
2343 bits = (dstbits += linebytes);
2346 else goto notsupported;
2347 break;
2349 case 15:
2351 LPWORD srcpixel;
2352 WORD val;
2354 /* ==== 555 BGR bitmap to 32 BGR dib ==== */
2355 if (bmpImage->red_mask == 0x7c00 && bmpImage->blue_mask == 0x001f)
2357 for (h = lines - 1; h >= 0; h--) {
2358 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2359 for (x = 0; x < dstwidth; x++, bits+=2) {
2360 val = *srcpixel++;
2361 *bits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x03)); /*Blue*/
2362 *bits++ = (BYTE)(((val >> 2) & 0xfc) | ((val >> 8) & 0x03)); /*Green*/
2363 *bits = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07)); /*Red*/
2365 bits = (dstbits += linebytes);
2368 /* ==== 555 RGB bitmap to 32 BGR dib ==== */
2369 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0x7c00)
2371 for (h = lines - 1; h >= 0; h--) {
2372 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2373 for (x = 0; x < dstwidth; x++, bits+=2) {
2374 val = *srcpixel++;
2375 *bits++ = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07));/*Blue*/
2376 *bits++ = (BYTE)(((val >> 2) & 0xfc) | ((val >> 8) & 0x03)); /*Green*/
2377 *bits = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x03)); /*Red*/
2379 bits = (dstbits += linebytes);
2382 else goto notsupported;
2384 break;
2386 case 16:
2388 LPWORD srcpixel;
2389 WORD val;
2391 /* ==== 565 BGR bitmap to 32 BGR dib ==== */
2392 if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f)
2394 for (h = lines - 1; h >= 0; h--) {
2395 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2396 for (x = 0; x < srcwidth; x++, bits+=2) {
2397 val = *srcpixel++;
2398 *bits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x03)); /*Blue*/
2399 *bits++ = (BYTE)(((val >> 3) & 0xfc) | ((val >> 9) & 0x03)); /*Green*/
2400 *bits = (BYTE)(((val >> 8) & 0xf8) | ((val >> 13) & 0x07)); /*Red*/
2402 bits = (dstbits += linebytes);
2405 /* ==== 565 RGB bitmap to 32 BGR dib ==== */
2406 else if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f)
2408 for (h = lines - 1; h >= 0; h--) {
2409 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2410 for (x = 0; x < srcwidth; x++, bits+=2) {
2411 val = *srcpixel++;
2412 *bits++ = (BYTE)(((val >> 8) & 0xf8) | ((val >> 13) & 0x07));/*Blue*/
2413 *bits++ = (BYTE)(((val >> 3) & 0xfc) | ((val >> 9) & 0x03)); /*Green*/
2414 *bits = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x03)); /*Red*/
2416 bits = (dstbits += linebytes);
2419 else goto notsupported;
2421 break;
2423 case 1:
2424 /* ==== monochrome bitmap to 32 BGR dib ==== */
2425 case 4:
2426 /* ==== 4 colormap bitmap to 32 BGR dib ==== */
2427 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
2429 PALETTEENTRY val;
2431 for (h = lines - 1; h >= 0; h--) {
2432 for (x = 0; x < dstwidth; x++) {
2433 val = srccolors[XGetPixel(bmpImage, x, h)];
2434 *bits++ = val.peBlue;
2435 *bits++ = val.peGreen;
2436 *bits++ = val.peRed;
2437 *bits++ = 0;
2439 bits = (dstbits += linebytes);
2442 else goto notsupported;
2444 break;
2446 case 8:
2447 /* ==== 8 colormap bitmap to 32 BGR dib ==== */
2448 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
2450 BYTE *srcpixel;
2451 PALETTEENTRY val;
2453 for (h = lines - 1; h >= 0; h--) {
2454 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
2455 for (x = 0; x < dstwidth; x++) {
2456 val = srccolors[(int)*srcpixel++];
2457 *bits++ = val.peBlue; /*Blue*/
2458 *bits++ = val.peGreen; /*Green*/
2459 *bits++ = val.peRed; /*Red*/
2460 *bits++ = 0;
2462 bits = (dstbits += linebytes);
2465 else goto notsupported;
2466 break;
2468 default:
2469 notsupported:
2470 FIXME("from %d bit bitmap with mask R,G,B %x,%x,%x to 32 bit DIB\n",
2471 bmpImage->depth, (int)bmpImage->red_mask,
2472 (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
2473 for (h = lines - 1; h >= 0; h--)
2475 for (x = 0; x < dstwidth; x++, bits += 4)
2477 COLORREF pixel = X11DRV_PALETTE_ToLogical( XGetPixel( bmpImage, x, h ) );
2478 bits[0] = GetBValue(pixel);
2479 bits[1] = GetGValue(pixel);
2480 bits[2] = GetRValue(pixel);
2482 bits = (dstbits += linebytes);
2484 break;
2488 /***********************************************************************
2489 * X11DRV_DIB_SetImageBits
2491 * Transfer the bits to an X image.
2492 * Helper function for SetDIBits() and SetDIBitsToDevice().
2493 * The Xlib critical section must be entered before calling this function.
2495 int X11DRV_DIB_SetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
2497 int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
2498 XImage *bmpImage;
2500 if ( descr->dc && descr->dc->w.flags & DC_DIRTY )
2501 CLIPPING_UpdateGCRegion( descr->dc );
2503 if (descr->image)
2504 bmpImage = descr->image;
2505 else {
2506 bmpImage = XCreateImage( display, X11DRV_GetVisual(), descr->depth, ZPixmap, 0, NULL,
2507 descr->infoWidth, lines, 32, 0 );
2508 bmpImage->data = calloc( lines, bmpImage->bytes_per_line );
2509 if(bmpImage->data == NULL) {
2510 ERR("Out of memory!");
2511 XDestroyImage( bmpImage );
2512 return lines;
2516 /* Transfer the pixels */
2517 switch(descr->infoBpp)
2519 case 1:
2520 X11DRV_DIB_SetImageBits_1( descr->lines, descr->bits, descr->infoWidth,
2521 descr->width, descr->xSrc, (int *)(descr->colorMap),
2522 bmpImage );
2523 break;
2524 case 4:
2525 if (descr->compression) {
2526 XGetSubImage( display, descr->drawable, descr->xDest, descr->yDest,
2527 descr->width, descr->height, AllPlanes, ZPixmap,
2528 bmpImage, descr->xSrc, descr->ySrc );
2530 X11DRV_DIB_SetImageBits_RLE4( descr->lines, descr->bits,
2531 descr->infoWidth, descr->width,
2532 descr->xSrc, (int *)(descr->colorMap),
2533 bmpImage );
2534 } else
2535 X11DRV_DIB_SetImageBits_4( descr->lines, descr->bits,
2536 descr->infoWidth, descr->width,
2537 descr->xSrc, (int*)(descr->colorMap),
2538 bmpImage );
2539 break;
2540 case 8:
2541 if (descr->compression) {
2542 XGetSubImage( display, descr->drawable, descr->xDest, descr->yDest,
2543 descr->width, descr->height, AllPlanes, ZPixmap,
2544 bmpImage, descr->xSrc, descr->ySrc );
2545 X11DRV_DIB_SetImageBits_RLE8( descr->lines, descr->bits,
2546 descr->infoWidth, descr->width,
2547 descr->xSrc, (int *)(descr->colorMap),
2548 bmpImage );
2549 } else
2550 X11DRV_DIB_SetImageBits_8( descr->lines, descr->bits,
2551 descr->infoWidth, descr->width,
2552 descr->xSrc, (int *)(descr->colorMap),
2553 bmpImage );
2554 break;
2555 case 15:
2556 case 16:
2557 X11DRV_DIB_SetImageBits_16( descr->lines, descr->bits,
2558 descr->infoWidth, descr->width,
2559 descr->xSrc, descr->dc,
2560 descr->rMask, descr->gMask, descr->bMask,
2561 bmpImage);
2562 break;
2563 case 24:
2564 X11DRV_DIB_SetImageBits_24( descr->lines, descr->bits,
2565 descr->infoWidth, descr->width,
2566 descr->xSrc, descr->dc, bmpImage );
2567 break;
2568 case 32:
2569 X11DRV_DIB_SetImageBits_32( descr->lines, descr->bits,
2570 descr->infoWidth, descr->width,
2571 descr->xSrc, descr->dc,
2572 bmpImage);
2573 break;
2574 default:
2575 WARN("(%d): Invalid depth\n", descr->infoBpp );
2576 break;
2579 if (descr->useShm)
2581 XShmPutImage( display, descr->drawable, descr->gc, bmpImage,
2582 descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
2583 descr->width, descr->height, FALSE );
2584 XSync( display, 0 );
2586 else
2587 XPutImage( display, descr->drawable, descr->gc, bmpImage,
2588 descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
2589 descr->width, descr->height );
2591 if (!descr->image) XDestroyImage( bmpImage );
2592 return lines;
2595 /***********************************************************************
2596 * X11DRV_DIB_GetImageBits
2598 * Transfer the bits from an X image.
2599 * The Xlib critical section must be entered before calling this function.
2601 int X11DRV_DIB_GetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
2603 int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
2604 XImage *bmpImage;
2606 if (descr->image)
2607 bmpImage = descr->image;
2608 else {
2609 bmpImage = XCreateImage( display, X11DRV_GetVisual(), descr->depth, ZPixmap, 0, NULL,
2610 descr->infoWidth, lines, 32, 0 );
2611 bmpImage->data = calloc( lines, bmpImage->bytes_per_line );
2612 if(bmpImage->data == NULL) {
2613 ERR("Out of memory!");
2614 XDestroyImage( bmpImage );
2615 return lines;
2618 XGetSubImage( display, descr->drawable, descr->xDest, descr->yDest,
2619 descr->width, descr->height, AllPlanes, ZPixmap,
2620 bmpImage, descr->xSrc, descr->ySrc );
2622 /* Transfer the pixels */
2623 switch(descr->infoBpp)
2625 case 1:
2626 X11DRV_DIB_GetImageBits_1( descr->lines,(LPVOID)descr->bits,
2627 descr->infoWidth, descr->width,
2628 descr->colorMap, descr->palentry,
2629 bmpImage );
2630 break;
2632 case 4:
2633 if (descr->compression)
2634 FIXME("Compression not yet supported!\n");
2635 else
2636 X11DRV_DIB_GetImageBits_4( descr->lines,(LPVOID)descr->bits,
2637 descr->infoWidth, descr->width,
2638 descr->colorMap, descr->palentry,
2639 bmpImage );
2640 break;
2642 case 8:
2643 if (descr->compression)
2644 FIXME("Compression not yet supported!\n");
2645 else
2646 X11DRV_DIB_GetImageBits_8( descr->lines, (LPVOID)descr->bits,
2647 descr->infoWidth, descr->width,
2648 descr->colorMap, descr->palentry,
2649 bmpImage );
2650 break;
2651 case 15:
2652 case 16:
2653 X11DRV_DIB_GetImageBits_16( descr->lines, (LPVOID)descr->bits,
2654 descr->infoWidth,descr->width,
2655 descr->palentry, bmpImage );
2656 break;
2658 case 24:
2659 X11DRV_DIB_GetImageBits_24( descr->lines, (LPVOID)descr->bits,
2660 descr->infoWidth,descr->width,
2661 descr->palentry, bmpImage );
2662 break;
2664 case 32:
2665 X11DRV_DIB_GetImageBits_32( descr->lines, (LPVOID)descr->bits,
2666 descr->infoWidth, descr->width,
2667 descr->palentry, bmpImage );
2668 break;
2670 default:
2671 WARN("(%d): Invalid depth\n", descr->infoBpp );
2672 break;
2675 if (!descr->image) XDestroyImage( bmpImage );
2676 return lines;
2679 /*************************************************************************
2680 * X11DRV_SetDIBitsToDevice
2683 INT X11DRV_SetDIBitsToDevice( DC *dc, INT xDest, INT yDest, DWORD cx,
2684 DWORD cy, INT xSrc, INT ySrc,
2685 UINT startscan, UINT lines, LPCVOID bits,
2686 const BITMAPINFO *info, UINT coloruse )
2688 X11DRV_DIB_IMAGEBITS_DESCR descr;
2689 DWORD width, oldcy = cy;
2690 INT result;
2691 int height, tmpheight;
2692 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
2695 if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height,
2696 &descr.infoBpp, &descr.compression ) == -1)
2697 return 0;
2698 tmpheight = height;
2699 if (height < 0) height = -height;
2700 if (!lines || (startscan >= height)) return 0;
2701 if (startscan + lines > height) lines = height - startscan;
2702 if (ySrc < startscan) ySrc = startscan;
2703 else if (ySrc >= startscan + lines) return 0;
2704 if (xSrc >= width) return 0;
2705 if (ySrc + cy >= startscan + lines) cy = startscan + lines - ySrc;
2706 if (xSrc + cx >= width) cx = width - xSrc;
2707 if (!cx || !cy) return 0;
2709 X11DRV_SetupGCForText( dc ); /* To have the correct colors */
2710 TSXSetFunction(display, physDev->gc, X11DRV_XROPfunction[dc->w.ROPmode-1]);
2712 switch (descr.infoBpp)
2714 case 1:
2715 case 4:
2716 case 8:
2717 descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap(
2718 coloruse == DIB_PAL_COLORS ? dc : NULL, coloruse,
2719 dc->w.bitsPerPixel, info, &descr.nColorMap );
2720 if (!descr.colorMap) return 0;
2721 descr.rMask = descr.gMask = descr.bMask = 0;
2722 break;
2723 case 15:
2724 case 16:
2725 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
2726 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x03e0;
2727 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x001f;
2728 descr.colorMap = 0;
2729 break;
2731 case 24:
2732 descr.rMask = descr.gMask = descr.bMask = 0;
2733 descr.colorMap = 0;
2734 break;
2736 case 32:
2737 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
2738 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0xff00;
2739 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0xff;
2740 descr.colorMap = 0;
2741 break;
2744 descr.dc = dc;
2745 descr.bits = bits;
2746 descr.image = NULL;
2747 descr.palentry = NULL;
2748 descr.lines = tmpheight >= 0 ? lines : -lines;
2749 descr.infoWidth = width;
2750 descr.depth = dc->w.bitsPerPixel;
2751 descr.drawable = physDev->drawable;
2752 descr.gc = physDev->gc;
2753 descr.xSrc = xSrc;
2754 descr.ySrc = tmpheight >= 0 ? lines-(ySrc-startscan)-cy+(oldcy-cy)
2755 : ySrc - startscan;
2756 descr.xDest = dc->w.DCOrgX + XLPTODP( dc, xDest );
2757 descr.yDest = dc->w.DCOrgY + YLPTODP( dc, yDest ) +
2758 (tmpheight >= 0 ? oldcy-cy : 0);
2759 descr.width = cx;
2760 descr.height = cy;
2761 descr.useShm = FALSE;
2763 EnterCriticalSection( &X11DRV_CritSection );
2764 result = CALL_LARGE_STACK( X11DRV_DIB_SetImageBits, &descr );
2765 LeaveCriticalSection( &X11DRV_CritSection );
2767 if (descr.infoBpp <= 8)
2768 HeapFree(GetProcessHeap(), 0, descr.colorMap);
2769 return result;
2772 /***********************************************************************
2773 * X11DRV_DIB_SetDIBits
2775 INT X11DRV_DIB_SetDIBits(
2776 BITMAPOBJ *bmp, DC *dc, UINT startscan,
2777 UINT lines, LPCVOID bits, const BITMAPINFO *info,
2778 UINT coloruse, HBITMAP hbitmap)
2780 X11DRV_DIB_IMAGEBITS_DESCR descr;
2781 int height, tmpheight;
2782 INT result;
2784 descr.dc = dc;
2786 if (DIB_GetBitmapInfo( &info->bmiHeader, &descr.infoWidth, &height,
2787 &descr.infoBpp, &descr.compression ) == -1)
2788 return 0;
2790 tmpheight = height;
2791 if (height < 0) height = -height;
2792 if (!lines || (startscan >= height))
2793 return 0;
2795 if (startscan + lines > height) lines = height - startscan;
2797 switch (descr.infoBpp)
2799 case 1:
2800 case 4:
2801 case 8:
2802 descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap(
2803 coloruse == DIB_PAL_COLORS ? descr.dc : NULL, coloruse,
2804 bmp->bitmap.bmBitsPixel,
2805 info, &descr.nColorMap );
2806 if (!descr.colorMap) return 0;
2807 descr.rMask = descr.gMask = descr.bMask = 0;
2808 break;
2809 case 15:
2810 case 16:
2811 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
2812 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x03e0;
2813 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x001f;
2814 descr.colorMap = 0;
2815 break;
2817 case 24:
2818 descr.rMask = descr.gMask = descr.bMask = 0;
2819 descr.colorMap = 0;
2820 break;
2822 case 32:
2823 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
2824 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0xff00;
2825 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0xff;
2826 descr.colorMap = 0;
2827 break;
2829 default: break;
2832 /* HACK for now */
2833 if(!bmp->physBitmap)
2834 X11DRV_CreateBitmap(hbitmap);
2836 descr.bits = bits;
2837 descr.image = NULL;
2838 descr.palentry = NULL;
2839 descr.lines = tmpheight >= 0 ? lines : -lines;
2840 descr.depth = bmp->bitmap.bmBitsPixel;
2841 descr.drawable = (Pixmap)bmp->physBitmap;
2842 descr.gc = BITMAP_GC(bmp);
2843 descr.xSrc = 0;
2844 descr.ySrc = 0;
2845 descr.xDest = 0;
2846 descr.yDest = height - startscan - lines;
2847 descr.width = bmp->bitmap.bmWidth;
2848 descr.height = lines;
2849 descr.useShm = FALSE;
2851 EnterCriticalSection( &X11DRV_CritSection );
2852 result = CALL_LARGE_STACK( X11DRV_DIB_SetImageBits, &descr );
2853 LeaveCriticalSection( &X11DRV_CritSection );
2855 if (descr.colorMap) HeapFree(GetProcessHeap(), 0, descr.colorMap);
2857 return result;
2860 /***********************************************************************
2861 * X11DRV_DIB_GetDIBits
2863 INT X11DRV_DIB_GetDIBits(
2864 BITMAPOBJ *bmp, DC *dc, UINT startscan,
2865 UINT lines, LPVOID bits, BITMAPINFO *info,
2866 UINT coloruse, HBITMAP hbitmap)
2868 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
2869 X11DRV_DIB_IMAGEBITS_DESCR descr;
2870 PALETTEOBJ * palette;
2872 TRACE("%u scanlines of (%i,%i) -> (%i,%i) starting from %u\n",
2873 lines, bmp->bitmap.bmWidth, bmp->bitmap.bmHeight,
2874 (int)info->bmiHeader.biWidth, (int)info->bmiHeader.biHeight,
2875 startscan );
2877 if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->w.hPalette, PALETTE_MAGIC )))
2878 return 0;
2880 if( lines > info->bmiHeader.biHeight ) lines = info->bmiHeader.biHeight;
2881 /* Top-down images have a negative biHeight, the scanlines of theses images
2882 * were inverted in X11DRV_DIB_GetImageBits_xx
2883 * To prevent this we simply change the sign of lines
2884 * (the number of scan lines to copy).
2885 * Negative lines are correctly handled by X11DRV_DIB_GetImageBits_xx.
2887 if( info->bmiHeader.biHeight < 0 && lines > 0) lines = -lines;
2889 if( startscan >= bmp->bitmap.bmHeight ) return FALSE;
2891 if (DIB_GetBitmapInfo( &info->bmiHeader, &descr.infoWidth, &descr.lines,
2892 &descr.infoBpp, &descr.compression ) == -1)
2893 return FALSE;
2895 switch (descr.infoBpp)
2897 case 1:
2898 case 4:
2899 case 8:
2900 case 24:
2901 descr.rMask = descr.gMask = descr.bMask = 0;
2902 break;
2903 case 15:
2904 case 16:
2905 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
2906 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x03e0;
2907 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x001f;
2908 break;
2910 case 32:
2911 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
2912 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0xff00;
2913 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0xff;
2914 break;
2917 /* Hack for now */
2918 if(!bmp->physBitmap)
2919 X11DRV_CreateBitmap(hbitmap);
2922 descr.dc = dc;
2923 descr.palentry = palette->logpalette.palPalEntry;
2924 descr.bits = bits;
2925 descr.lines = lines;
2926 descr.depth = bmp->bitmap.bmBitsPixel;
2927 descr.drawable = (Pixmap)bmp->physBitmap;
2928 descr.gc = BITMAP_GC(bmp);
2929 descr.xSrc = 0;
2930 descr.ySrc = startscan;
2931 descr.xDest = 0;
2932 descr.yDest = 0;
2933 descr.width = bmp->bitmap.bmWidth;
2934 descr.height = bmp->bitmap.bmHeight;
2935 descr.colorMap = info->bmiColors;
2937 if (dib)
2938 descr.useShm = (dib->shminfo.shmid != -1);
2939 else
2940 descr.useShm = FALSE;
2942 EnterCriticalSection( &X11DRV_CritSection );
2944 descr.image = (XImage *)CALL_LARGE_STACK( X11DRV_BITMAP_GetXImage, bmp );
2945 CALL_LARGE_STACK( X11DRV_DIB_GetImageBits, &descr );
2947 LeaveCriticalSection( &X11DRV_CritSection );
2949 if(info->bmiHeader.biSizeImage == 0) /* Fill in biSizeImage */
2950 info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(
2951 info->bmiHeader.biWidth,
2952 info->bmiHeader.biHeight,
2953 info->bmiHeader.biBitCount );
2955 info->bmiHeader.biCompression = 0;
2957 GDI_HEAP_UNLOCK( dc->w.hPalette );
2959 return lines;
2962 /***********************************************************************
2963 * DIB_DoProtectDIBSection
2965 static void X11DRV_DIB_DoProtectDIBSection( BITMAPOBJ *bmp, DWORD new_prot )
2967 DIBSECTION *dib = bmp->dib;
2968 INT effHeight = dib->dsBm.bmHeight >= 0? dib->dsBm.bmHeight
2969 : -dib->dsBm.bmHeight;
2970 INT totalSize = dib->dsBmih.biSizeImage? dib->dsBmih.biSizeImage
2971 : dib->dsBm.bmWidthBytes * effHeight;
2972 DWORD old_prot;
2974 VirtualProtect(dib->dsBm.bmBits, totalSize, new_prot, &old_prot);
2975 TRACE("Changed protection from %ld to %ld\n", old_prot, new_prot);
2978 /***********************************************************************
2979 * X11DRV_DIB_DoUpdateDIBSection
2981 static void X11DRV_DIB_DoUpdateDIBSection(BITMAPOBJ *bmp, BOOL toDIB)
2983 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
2984 X11DRV_DIB_IMAGEBITS_DESCR descr;
2986 if (DIB_GetBitmapInfo( &dib->dibSection.dsBmih, &descr.infoWidth, &descr.lines,
2987 &descr.infoBpp, &descr.compression ) == -1)
2988 return;
2990 descr.dc = NULL;
2991 descr.palentry = NULL;
2992 descr.image = dib->image;
2993 descr.colorMap = (RGBQUAD *)dib->colorMap;
2994 descr.nColorMap = dib->nColorMap;
2995 descr.bits = dib->dibSection.dsBm.bmBits;
2996 descr.depth = bmp->bitmap.bmBitsPixel;
2998 switch (descr.infoBpp)
3000 case 1:
3001 case 4:
3002 case 8:
3003 case 24:
3004 descr.rMask = descr.gMask = descr.bMask = 0;
3005 break;
3006 case 15:
3007 case 16:
3008 descr.rMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[0] : 0x7c00;
3009 descr.gMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[1] : 0x03e0;
3010 descr.bMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[2] : 0x001f;
3011 break;
3013 case 32:
3014 descr.rMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[0] : 0xff;
3015 descr.gMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[1] : 0xff00;
3016 descr.bMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[2] : 0xff0000;
3017 break;
3020 /* Hack for now */
3021 descr.drawable = (Pixmap)bmp->physBitmap;
3022 descr.gc = BITMAP_GC(bmp);
3023 descr.xSrc = 0;
3024 descr.ySrc = 0;
3025 descr.xDest = 0;
3026 descr.yDest = 0;
3027 descr.width = bmp->bitmap.bmWidth;
3028 descr.height = bmp->bitmap.bmHeight;
3029 descr.useShm = (dib->shminfo.shmid != -1);
3031 if (toDIB)
3033 TRACE("Copying from Pixmap to DIB bits\n");
3034 EnterCriticalSection( &X11DRV_CritSection );
3035 CALL_LARGE_STACK( X11DRV_DIB_GetImageBits, &descr );
3036 LeaveCriticalSection( &X11DRV_CritSection );
3038 else
3040 TRACE("Copying from DIB bits to Pixmap\n");
3041 EnterCriticalSection( &X11DRV_CritSection );
3042 CALL_LARGE_STACK( X11DRV_DIB_SetImageBits, &descr );
3043 LeaveCriticalSection( &X11DRV_CritSection );
3047 /***********************************************************************
3048 * X11DRV_DIB_FaultHandler
3050 static BOOL X11DRV_DIB_FaultHandler( LPVOID res, LPCVOID addr )
3052 BOOL handled = FALSE;
3053 BITMAPOBJ *bmp;
3055 bmp = (BITMAPOBJ *)GDI_GetObjPtr( (HBITMAP)res, BITMAP_MAGIC );
3056 if (!bmp) return FALSE;
3058 if (bmp->dib)
3059 switch (((X11DRV_DIBSECTION *) bmp->dib)->status)
3061 case X11DRV_DIB_GdiMod:
3062 TRACE("called in status DIB_GdiMod\n" );
3063 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
3064 X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
3065 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
3066 ((X11DRV_DIBSECTION *) bmp->dib)->status = X11DRV_DIB_InSync;
3067 handled = TRUE;
3068 break;
3070 case X11DRV_DIB_InSync:
3071 TRACE("called in status X11DRV_DIB_InSync\n" );
3072 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
3073 ((X11DRV_DIBSECTION *) bmp->dib)->status = X11DRV_DIB_AppMod;
3074 handled = TRUE;
3075 break;
3077 case X11DRV_DIB_AppMod:
3078 FIXME("called in status X11DRV_DIB_AppMod: this can't happen!\n" );
3079 break;
3081 case X11DRV_DIB_NoHandler:
3082 FIXME("called in status DIB_NoHandler: this can't happen!\n" );
3083 break;
3086 GDI_HEAP_UNLOCK( (HBITMAP)res );
3087 return handled;
3090 /***********************************************************************
3091 * X11DRV_DIB_UpdateDIBSection
3093 void X11DRV_DIB_UpdateDIBSection(DC *dc, BOOL toDIB)
3095 BITMAPOBJ *bmp;
3097 /* Ensure this is a Compatible DC that has a DIB section selected */
3099 if (!dc) return;
3100 if (!(dc->w.flags & DC_MEMORY)) return;
3102 bmp = (BITMAPOBJ *)GDI_GetObjPtr( dc->w.hBitmap, BITMAP_MAGIC );
3103 if (!bmp) return;
3105 if (!bmp->dib)
3107 GDI_HEAP_UNLOCK(dc->w.hBitmap);
3108 return;
3111 if (!toDIB)
3113 /* Prepare for access to the DIB by GDI functions */
3115 switch (((X11DRV_DIBSECTION *) bmp->dib)->status)
3117 default:
3118 case X11DRV_DIB_NoHandler:
3119 X11DRV_DIB_DoUpdateDIBSection( bmp, FALSE );
3120 break;
3122 case X11DRV_DIB_GdiMod:
3123 TRACE("fromDIB called in status X11DRV_DIB_GdiMod\n" );
3124 /* nothing to do */
3125 break;
3127 case X11DRV_DIB_InSync:
3128 TRACE("fromDIB called in status X11DRV_DIB_InSync\n" );
3129 /* nothing to do */
3130 break;
3132 case X11DRV_DIB_AppMod:
3133 TRACE("fromDIB called in status X11DRV_DIB_AppMod\n" );
3134 X11DRV_DIB_DoUpdateDIBSection( bmp, FALSE );
3135 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
3136 ((X11DRV_DIBSECTION *) bmp->dib)->status = X11DRV_DIB_InSync;
3137 break;
3140 else
3142 /* Acknowledge write access to the DIB by GDI functions */
3144 switch (((X11DRV_DIBSECTION *) bmp->dib)->status)
3146 default:
3147 case X11DRV_DIB_NoHandler:
3148 X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
3149 break;
3151 case X11DRV_DIB_GdiMod:
3152 TRACE(" toDIB called in status X11DRV_DIB_GdiMod\n" );
3153 /* nothing to do */
3154 break;
3156 case X11DRV_DIB_InSync:
3157 TRACE(" toDIB called in status X11DRV_DIB_InSync\n" );
3158 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
3159 ((X11DRV_DIBSECTION *) bmp->dib)->status = X11DRV_DIB_GdiMod;
3160 break;
3162 case X11DRV_DIB_AppMod:
3163 FIXME(" toDIB called in status X11DRV_DIB_AppMod: "
3164 "this can't happen!\n" );
3165 break;
3169 GDI_HEAP_UNLOCK(dc->w.hBitmap);
3172 /***********************************************************************
3173 * X11DRV_DIB_CreateDIBSection16
3175 HBITMAP16 X11DRV_DIB_CreateDIBSection16(
3176 DC *dc, BITMAPINFO *bmi, UINT16 usage,
3177 SEGPTR *bits, HANDLE section,
3178 DWORD offset, DWORD ovr_pitch)
3180 HBITMAP res = X11DRV_DIB_CreateDIBSection(dc, bmi, usage, NULL,
3181 section, offset, ovr_pitch);
3182 if ( res )
3184 BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr(res, BITMAP_MAGIC);
3185 if ( bmp && bmp->dib )
3187 DIBSECTION *dib = bmp->dib;
3188 INT height = dib->dsBm.bmHeight >= 0 ?
3189 dib->dsBm.bmHeight : -dib->dsBm.bmHeight;
3190 INT size = dib->dsBmih.biSizeImage ?
3191 dib->dsBmih.biSizeImage : dib->dsBm.bmWidthBytes * height;
3192 if ( dib->dsBm.bmBits )
3194 ((X11DRV_DIBSECTION *) bmp->dib)->selector =
3195 SELECTOR_AllocBlock( dib->dsBm.bmBits, size,
3196 SEGMENT_DATA, FALSE, FALSE );
3198 TRACE("ptr = %p, size =%d, selector = %04x, segptr = %ld\n",
3199 dib->dsBm.bmBits, size, ((X11DRV_DIBSECTION *) bmp->dib)->selector,
3200 PTR_SEG_OFF_TO_SEGPTR(((X11DRV_DIBSECTION *) bmp->dib)->selector, 0));
3202 GDI_HEAP_UNLOCK( res );
3204 if ( bits )
3205 *bits = PTR_SEG_OFF_TO_SEGPTR( ((X11DRV_DIBSECTION *) bmp->dib)->selector, 0 );
3208 return res;
3211 /***********************************************************************
3212 * X11DRV_XShmErrorHandler
3215 static int XShmErrorHandler(Display *dpy, XErrorEvent *event)
3217 XShmErrorFlag = 1;
3218 return 0;
3221 /***********************************************************************
3222 * X11DRV_XShmCreateImage
3226 extern BOOL X11DRV_XShmCreateImage(XImage** image, int width, int height, int bpp,
3227 XShmSegmentInfo* shminfo)
3229 int (*WineXHandler)(Display *, XErrorEvent *);
3231 *image = TSXShmCreateImage(display, X11DRV_GetVisual(), bpp, ZPixmap, NULL, shminfo, width, height);
3232 if( *image != NULL )
3234 EnterCriticalSection( &X11DRV_CritSection );
3235 shminfo->shmid = shmget(IPC_PRIVATE, (*image)->bytes_per_line * height,
3236 IPC_CREAT|0700);
3237 if( shminfo->shmid != -1 )
3239 shminfo->shmaddr = (*image)->data = shmat(shminfo->shmid, 0, 0);
3240 if( shminfo->shmaddr != (char*)-1 )
3242 shminfo->readOnly = FALSE;
3243 if( TSXShmAttach( display, shminfo ) != 0)
3245 /* Reset the error flag */
3246 XShmErrorFlag = 0;
3247 WineXHandler = XSetErrorHandler(XShmErrorHandler);
3248 XSync( display, 0 );
3250 if (!XShmErrorFlag)
3252 shmctl(shminfo->shmid, IPC_RMID, 0);
3254 XSetErrorHandler(WineXHandler);
3255 LeaveCriticalSection( &X11DRV_CritSection );
3257 return TRUE; /* Success! */
3259 /* An error occured */
3260 XShmErrorFlag = 0;
3261 XSetErrorHandler(WineXHandler);
3263 shmdt(shminfo->shmaddr);
3265 shmctl(shminfo->shmid, IPC_RMID, 0);
3267 XFlush(display);
3268 XDestroyImage(*image);
3269 LeaveCriticalSection( &X11DRV_CritSection );
3271 return FALSE;
3277 /***********************************************************************
3278 * X11DRV_DIB_CreateDIBSection
3280 HBITMAP X11DRV_DIB_CreateDIBSection(
3281 DC *dc, BITMAPINFO *bmi, UINT usage,
3282 LPVOID *bits, HANDLE section,
3283 DWORD offset, DWORD ovr_pitch)
3285 HBITMAP res = 0;
3286 BITMAPOBJ *bmp = NULL;
3287 X11DRV_DIBSECTION *dib = NULL;
3288 int *colorMap = NULL;
3289 int nColorMap;
3291 /* Fill BITMAP32 structure with DIB data */
3292 BITMAPINFOHEADER *bi = &bmi->bmiHeader;
3293 INT effHeight, totalSize;
3294 BITMAP bm;
3296 TRACE("format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
3297 bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
3298 bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
3300 effHeight = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
3301 bm.bmType = 0;
3302 bm.bmWidth = bi->biWidth;
3303 bm.bmHeight = effHeight;
3304 bm.bmWidthBytes = ovr_pitch ? ovr_pitch
3305 : DIB_GetDIBWidthBytes(bm.bmWidth, bi->biBitCount);
3306 bm.bmPlanes = bi->biPlanes;
3307 bm.bmBitsPixel = bi->biBitCount;
3308 bm.bmBits = NULL;
3310 /* Get storage location for DIB bits */
3311 totalSize = bi->biSizeImage? bi->biSizeImage : bm.bmWidthBytes * effHeight;
3313 if (section)
3314 bm.bmBits = MapViewOfFile(section, FILE_MAP_ALL_ACCESS,
3315 0L, offset, totalSize);
3316 else if (ovr_pitch && offset)
3317 bm.bmBits = (LPVOID) offset;
3318 else {
3319 offset = 0;
3320 bm.bmBits = VirtualAlloc(NULL, totalSize,
3321 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
3324 /* Create Color Map */
3325 if (bm.bmBits && bm.bmBitsPixel <= 8)
3326 colorMap = X11DRV_DIB_BuildColorMap( usage == DIB_PAL_COLORS? dc : NULL,
3327 usage, bm.bmBitsPixel, bmi, &nColorMap );
3329 /* Allocate Memory for DIB and fill structure */
3330 if (bm.bmBits)
3331 dib = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(X11DRV_DIBSECTION));
3332 if (dib)
3334 dib->dibSection.dsBm = bm;
3335 dib->dibSection.dsBmih = *bi;
3337 /* Set dsBitfields values */
3338 if ( usage == DIB_PAL_COLORS || bi->biBitCount <= 8)
3340 dib->dibSection.dsBitfields[0] = dib->dibSection.dsBitfields[1] = dib->dibSection.dsBitfields[2] = 0;
3342 else switch( bi->biBitCount )
3344 case 16:
3345 dib->dibSection.dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors : 0x7c00;
3346 dib->dibSection.dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0x03e0;
3347 dib->dibSection.dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0x001f;
3348 break;
3350 case 24:
3351 dib->dibSection.dsBitfields[0] = 0xff;
3352 dib->dibSection.dsBitfields[1] = 0xff00;
3353 dib->dibSection.dsBitfields[2] = 0xff0000;
3354 break;
3356 case 32:
3357 dib->dibSection.dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors : 0xff;
3358 dib->dibSection.dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0xff00;
3359 dib->dibSection.dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0xff0000;
3360 break;
3362 dib->dibSection.dshSection = section;
3363 dib->dibSection.dsOffset = offset;
3365 dib->status = X11DRV_DIB_NoHandler;
3366 dib->selector = 0;
3368 dib->nColorMap = nColorMap;
3369 dib->colorMap = colorMap;
3372 /* Create Device Dependent Bitmap and add DIB pointer */
3373 if (dib)
3375 res = CreateDIBitmap(dc->hSelf, bi, 0, NULL, bmi, usage);
3376 if (res)
3378 bmp = (BITMAPOBJ *) GDI_GetObjPtr(res, BITMAP_MAGIC);
3379 if (bmp)
3381 bmp->dib = (DIBSECTION *) dib;
3382 /* HACK for now */
3383 if(!bmp->physBitmap)
3384 X11DRV_CreateBitmap(res);
3389 /* Create XImage */
3390 if (dib && bmp)
3392 if (TSXShmQueryExtension(display) &&
3393 X11DRV_XShmCreateImage( &dib->image, bm.bmWidth, effHeight,
3394 bmp->bitmap.bmBitsPixel, &dib->shminfo ) )
3396 ; /* Created Image */
3397 } else {
3398 XCREATEIMAGE( dib->image, bm.bmWidth, effHeight, bmp->bitmap.bmBitsPixel );
3399 dib->shminfo.shmid = -1;
3403 /* Clean up in case of errors */
3404 if (!res || !bmp || !dib || !bm.bmBits || (bm.bmBitsPixel <= 8 && !colorMap))
3406 TRACE("got an error res=%08x, bmp=%p, dib=%p, bm.bmBits=%p\n",
3407 res, bmp, dib, bm.bmBits);
3408 if (bm.bmBits)
3410 if (section)
3411 UnmapViewOfFile(bm.bmBits), bm.bmBits = NULL;
3412 else if (!offset)
3413 VirtualFree(bm.bmBits, 0L, MEM_RELEASE), bm.bmBits = NULL;
3416 if (dib && dib->image) { XDestroyImage(dib->image); dib->image = NULL; }
3417 if (colorMap) { HeapFree(GetProcessHeap(), 0, colorMap); colorMap = NULL; }
3418 if (dib) { HeapFree(GetProcessHeap(), 0, dib); dib = NULL; }
3419 if (res) { DeleteObject(res); res = 0; }
3422 /* Install fault handler, if possible */
3423 if (bm.bmBits)
3425 if (VIRTUAL_SetFaultHandler(bm.bmBits, X11DRV_DIB_FaultHandler, (LPVOID)res))
3427 if (section || offset)
3429 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
3430 if (dib) dib->status = X11DRV_DIB_AppMod;
3432 else
3434 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
3435 if (dib) dib->status = X11DRV_DIB_InSync;
3440 /* Return BITMAP handle and storage location */
3441 if (res) GDI_HEAP_UNLOCK(res);
3442 if (bm.bmBits && bits) *bits = bm.bmBits;
3443 return res;
3446 /***********************************************************************
3447 * X11DRV_DIB_DeleteDIBSection
3449 void X11DRV_DIB_DeleteDIBSection(BITMAPOBJ *bmp)
3451 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
3453 if (dib->image)
3455 if (dib->shminfo.shmid != -1)
3457 TSXShmDetach (display, &(dib->shminfo));
3458 XDestroyImage (dib->image);
3459 shmdt (dib->shminfo.shmaddr);
3460 dib->shminfo.shmid = -1;
3462 else
3463 XDestroyImage( dib->image );
3466 if (dib->colorMap)
3467 HeapFree(GetProcessHeap(), 0, dib->colorMap);
3469 if (dib->selector)
3471 WORD count = (GET_SEL_LIMIT( dib->selector ) >> 16) + 1;
3472 SELECTOR_FreeBlock( dib->selector, count );
3477 /**************************************************************************
3478 * X11DRV_DIB_CreateDIBFromPixmap
3480 * Allocates a packed DIB and copies the Pixmap data into it.
3481 * If bDeletePixmap is TRUE, the Pixmap passed in is deleted after the conversion.
3483 HGLOBAL X11DRV_DIB_CreateDIBFromPixmap(Pixmap pixmap, HDC hdc, BOOL bDeletePixmap)
3485 HBITMAP hBmp = 0;
3486 BITMAPOBJ *pBmp = NULL;
3487 HGLOBAL hPackedDIB = 0;
3489 /* Allocates an HBITMAP which references the Pixmap passed to us */
3490 hBmp = X11DRV_BITMAP_CreateBitmapHeaderFromPixmap(pixmap);
3491 if (!hBmp)
3493 TRACE("\tCould not create bitmap header for Pixmap\n");
3494 goto END;
3498 * Create a packed DIB from the Pixmap wrapper bitmap created above.
3499 * A packed DIB contains a BITMAPINFO structure followed immediately by
3500 * an optional color palette and the pixel data.
3502 hPackedDIB = DIB_CreateDIBFromBitmap(hdc, hBmp);
3504 /* Get a pointer to the BITMAPOBJ structure */
3505 pBmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
3507 /* We can now get rid of the HBITMAP wrapper we created earlier.
3508 * Note: Simply calling DeleteObject will free the embedded Pixmap as well.
3510 if (!bDeletePixmap)
3512 /* Clear the physBitmap to prevent the Pixmap from being deleted by DeleteObject */
3513 pBmp->physBitmap = NULL;
3514 pBmp->funcs = NULL;
3516 DeleteObject(hBmp);
3518 END:
3519 TRACE("\tReturning packed DIB %x\n", hPackedDIB);
3520 return hPackedDIB;
3524 /**************************************************************************
3525 * X11DRV_DIB_CreatePixmapFromDIB
3527 * Creates a Pixmap from a packed DIB
3529 Pixmap X11DRV_DIB_CreatePixmapFromDIB( HGLOBAL hPackedDIB, HDC hdc )
3531 Pixmap pixmap = None;
3532 HBITMAP hBmp = 0;
3533 BITMAPOBJ *pBmp = NULL;
3534 LPBYTE pPackedDIB = NULL;
3535 LPBITMAPINFO pbmi = NULL;
3536 LPBITMAPINFOHEADER pbmiHeader = NULL;
3537 LPBYTE pbits = NULL;
3539 /* Get a pointer to the packed DIB's data */
3540 pPackedDIB = (LPBYTE)GlobalLock(hPackedDIB);
3541 pbmiHeader = (LPBITMAPINFOHEADER)pPackedDIB;
3542 pbmi = (LPBITMAPINFO)pPackedDIB;
3543 pbits = (LPBYTE)(pPackedDIB
3544 + DIB_BitmapInfoSize( (LPBITMAPINFO)pbmiHeader, DIB_RGB_COLORS ));
3546 /* Create a DDB from the DIB */
3548 hBmp = CreateDIBitmap(hdc,
3549 pbmiHeader,
3550 CBM_INIT,
3551 (LPVOID)pbits,
3552 pbmi,
3553 DIB_RGB_COLORS);
3555 GlobalUnlock(hPackedDIB);
3557 TRACE("CreateDIBitmap returned %x\n", hBmp);
3559 /* Retrieve the internal Pixmap from the DDB */
3561 pBmp = (BITMAPOBJ *) GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
3563 pixmap = (Pixmap)pBmp->physBitmap;
3564 /* clear the physBitmap so that we can steal its pixmap */
3565 pBmp->physBitmap = NULL;
3566 pBmp->funcs = NULL;
3568 /* Delete the DDB we created earlier now that we have stolen its pixmap */
3569 DeleteObject(hBmp);
3571 TRACE("\tReturning Pixmap %ld\n", pixmap);
3572 return pixmap;