Fix a sign bug where memcpy was called with negative length.
[wine.git] / graphics / x11drv / dib.c
blob5db9589dd8145908a964c80b7aafc3f2e326efa9
1 /*
2 * X11DRV device-independent bitmaps
4 * Copyright 1993,1994 Alexandre Julliard
5 */
7 #include "config.h"
9 #ifndef X_DISPLAY_MISSING
11 #include "ts_xlib.h"
12 #include "ts_xutil.h"
14 #ifdef HAVE_LIBXXSHM
15 # include "ts_xshm.h"
16 # ifdef HAVE_SYS_SHM_H
17 # include <sys/shm.h>
18 # endif
19 # ifdef HAVE_SYS_IPC_H
20 # include <sys/ipc.h>
21 # endif
22 #endif /* defined(HAVE_LIBXXSHM) */
24 #include "windef.h"
25 #include "bitmap.h"
26 #include "x11drv.h"
27 #include "debugtools.h"
28 #include "dc.h"
29 #include "color.h"
30 #include "callback.h"
31 #include "selectors.h"
32 #include "global.h"
33 #include "xmalloc.h" /* for XCREATEIMAGE macro */
35 DEFAULT_DEBUG_CHANNEL(bitmap)
36 DECLARE_DEBUG_CHANNEL(x11drv)
38 static int bitmapDepthTable[] = { 8, 1, 32, 16, 24, 15, 4, 0 };
39 static int ximageDepthTable[] = { 0, 0, 0, 0, 0, 0, 0 };
41 static int XShmErrorFlag = 0;
43 /***********************************************************************
44 * X11DRV_DIB_Init
46 BOOL X11DRV_DIB_Init(void)
48 int i;
49 XImage* testimage;
51 for( i = 0; bitmapDepthTable[i]; i++ )
53 testimage = TSXCreateImage(display, DefaultVisualOfScreen(X11DRV_GetXScreen()),
54 bitmapDepthTable[i], ZPixmap, 0, NULL, 1, 1, 32, 20 );
55 if( testimage ) ximageDepthTable[i] = testimage->bits_per_pixel;
56 else return FALSE;
57 TSXDestroyImage(testimage);
59 return TRUE;
63 /***********************************************************************
64 * X11DRV_DIB_GetXImageWidthBytes
66 * Return the width of an X image in bytes
68 int X11DRV_DIB_GetXImageWidthBytes( int width, int depth )
70 int i;
72 if (!ximageDepthTable[0]) {
73 X11DRV_DIB_Init();
75 for( i = 0; bitmapDepthTable[i] ; i++ )
76 if( bitmapDepthTable[i] == depth )
77 return (4 * ((width * ximageDepthTable[i] + 31)/32));
79 WARN("(%d): Unsupported depth\n", depth );
80 return (4 * width);
83 /***********************************************************************
84 * X11DRV_DIB_BuildColorMap
86 * Build the color map from the bitmap palette. Should not be called
87 * for a >8-bit deep bitmap.
89 int *X11DRV_DIB_BuildColorMap( DC *dc, WORD coloruse, WORD depth,
90 const BITMAPINFO *info, int *nColors )
92 int i, colors;
93 BOOL isInfo;
94 WORD *colorPtr;
95 int *colorMapping;
97 if ((isInfo = (info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))))
99 colors = info->bmiHeader.biClrUsed;
100 if (!colors) colors = 1 << info->bmiHeader.biBitCount;
101 colorPtr = (WORD *)info->bmiColors;
103 else /* assume BITMAPCOREINFO */
105 colors = 1 << ((BITMAPCOREHEADER *)&info->bmiHeader)->bcBitCount;
106 colorPtr = (WORD *)((BITMAPCOREINFO *)info)->bmciColors;
109 if (colors > 256)
111 ERR("called with >256 colors!\n");
112 return NULL;
115 if (!(colorMapping = (int *)HeapAlloc(GetProcessHeap(), 0,
116 colors * sizeof(int) )))
117 return NULL;
119 if (coloruse == DIB_RGB_COLORS)
121 if (isInfo)
123 RGBQUAD * rgb = (RGBQUAD *)colorPtr;
125 if (depth == 1) /* Monochrome */
126 for (i = 0; i < colors; i++, rgb++)
127 colorMapping[i] = (rgb->rgbRed + rgb->rgbGreen +
128 rgb->rgbBlue > 255*3/2);
129 else
130 for (i = 0; i < colors; i++, rgb++)
131 colorMapping[i] = X11DRV_PALETTE_ToPhysical( dc, RGB(rgb->rgbRed,
132 rgb->rgbGreen,
133 rgb->rgbBlue));
135 else
137 RGBTRIPLE * rgb = (RGBTRIPLE *)colorPtr;
139 if (depth == 1) /* Monochrome */
140 for (i = 0; i < colors; i++, rgb++)
141 colorMapping[i] = (rgb->rgbtRed + rgb->rgbtGreen +
142 rgb->rgbtBlue > 255*3/2);
143 else
144 for (i = 0; i < colors; i++, rgb++)
145 colorMapping[i] = X11DRV_PALETTE_ToPhysical( dc, RGB(rgb->rgbtRed,
146 rgb->rgbtGreen,
147 rgb->rgbtBlue));
150 else /* DIB_PAL_COLORS */
152 for (i = 0; i < colors; i++, colorPtr++)
153 colorMapping[i] = X11DRV_PALETTE_ToPhysical( dc, PALETTEINDEX(*colorPtr) );
156 *nColors = colors;
157 return colorMapping;
161 /***********************************************************************
162 * X11DRV_DIB_MapColor
164 int X11DRV_DIB_MapColor( int *physMap, int nPhysMap, int phys )
166 int color;
168 for (color = 0; color < nPhysMap; color++)
169 if (physMap[color] == phys)
170 return color;
172 WARN("Strange color %08x\n", phys);
173 return 0;
177 /*********************************************************************
178 * X11DRV_DIB_GetNearestIndex
180 * Helper for X11DRV_DIB_GetDIBits.
181 * Returns the nearest colour table index for a given RGB.
182 * Nearest is defined by minimizing the sum of the squares.
184 static INT X11DRV_DIB_GetNearestIndex(RGBQUAD *colormap, int numColors, BYTE r, BYTE g, BYTE b)
186 INT i, best = -1, diff, bestdiff = -1;
187 RGBQUAD *color;
189 for(color = colormap, i = 0; i < numColors; color++, i++) {
190 diff = (r - color->rgbRed) * (r - color->rgbRed) +
191 (g - color->rgbGreen) * (g - color->rgbGreen) +
192 (b - color->rgbBlue) * (b - color->rgbBlue);
193 if(diff == 0)
194 return i;
195 if(best == -1 || diff < bestdiff) {
196 best = i;
197 bestdiff = diff;
200 return best;
203 /***********************************************************************
204 * X11DRV_DIB_SetImageBits_1_Line
206 * Handles a single line of 1 bit data.
208 static void X11DRV_DIB_SetImageBits_1_Line(DWORD dstwidth, int left, int *colors,
209 XImage *bmpImage, int h, const BYTE *bits)
211 BYTE pix, extra;
212 DWORD i, x;
214 if((extra = (left & 7)) != 0) {
215 left &= ~7;
216 dstwidth += extra;
219 bits += left >> 3;
221 /* FIXME: should avoid putting x<left pixels (minor speed issue) */
222 for (i = dstwidth/8, x = left; i > 0; i--)
224 pix = *bits++;
225 XPutPixel( bmpImage, x++, h, colors[pix >> 7] );
226 XPutPixel( bmpImage, x++, h, colors[(pix >> 6) & 1] );
227 XPutPixel( bmpImage, x++, h, colors[(pix >> 5) & 1] );
228 XPutPixel( bmpImage, x++, h, colors[(pix >> 4) & 1] );
229 XPutPixel( bmpImage, x++, h, colors[(pix >> 3) & 1] );
230 XPutPixel( bmpImage, x++, h, colors[(pix >> 2) & 1] );
231 XPutPixel( bmpImage, x++, h, colors[(pix >> 1) & 1] );
232 XPutPixel( bmpImage, x++, h, colors[pix & 1] );
234 pix = *bits;
235 switch(dstwidth & 7)
237 case 7: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
238 case 6: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
239 case 5: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
240 case 4: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
241 case 3: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
242 case 2: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
243 case 1: XPutPixel( bmpImage, x++, h, colors[pix >> 7] );
247 /***********************************************************************
248 * X11DRV_DIB_SetImageBits_1
250 * SetDIBits for a 1-bit deep DIB.
252 static void X11DRV_DIB_SetImageBits_1( int lines, const BYTE *srcbits,
253 DWORD srcwidth, DWORD dstwidth, int left,
254 int *colors, XImage *bmpImage )
256 int h;
258 /* 32 bit aligned */
259 DWORD linebytes = ((srcwidth + 31) & ~31) / 8;
261 if (lines > 0) {
262 for (h = lines-1; h >=0; h--) {
263 X11DRV_DIB_SetImageBits_1_Line(dstwidth, left, colors, bmpImage, h,
264 srcbits);
265 srcbits += linebytes;
267 } else {
268 lines = -lines;
269 for (h = 0; h < lines; h++) {
270 X11DRV_DIB_SetImageBits_1_Line(dstwidth, left, colors, bmpImage, h,
271 srcbits);
272 srcbits += linebytes;
277 /***********************************************************************
278 * X11DRV_DIB_GetImageBits_1
280 * GetDIBits for a 1-bit deep DIB.
282 static void X11DRV_DIB_GetImageBits_1( int lines, BYTE *dstbits,
283 DWORD dstwidth, DWORD srcwidth,
284 RGBQUAD *colors, PALETTEENTRY *srccolors,
285 XImage *bmpImage )
287 DWORD x;
288 int h;
289 BYTE *bits;
291 /* 32 bit aligned */
292 DWORD linebytes = ((dstwidth + 31) & ~31) / 8;
294 if (lines < 0 ) {
295 lines = -lines;
296 dstbits = dstbits + linebytes * (lines - 1);
297 linebytes = -linebytes;
300 bits = dstbits;
302 switch(bmpImage->depth) {
304 case 1:
305 /* ==== monochrome bitmap to monochrome dib ==== */
306 case 4:
307 /* ==== 4 colormap bitmap to monochrome dib ==== */
308 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
310 PALETTEENTRY val;
312 for (h = lines - 1; h >= 0; h--) {
313 for (x = 0; x < dstwidth; x++) {
314 val = srccolors[XGetPixel(bmpImage, x, h)];
315 if (!(x&7)) *bits = 0;
316 *bits |= (X11DRV_DIB_GetNearestIndex(colors, 2,
317 val.peRed,
318 val.peGreen,
319 val.peBlue) << (7 - (x & 7)));
320 if ((x&7)==7) bits++;
322 bits = (dstbits += linebytes);
325 else goto notsupported;
327 break;
329 case 8:
330 /* ==== 8 colormap bitmap to monochrome dib ==== */
331 if ( bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
333 BYTE *srcpixel;
334 PALETTEENTRY val;
336 for( h = lines- 1; h >= 0; h-- ) {
337 srcpixel = bmpImage->data + (h*bmpImage->bytes_per_line);
338 for( x = 0; x < dstwidth; x++ ) {
339 if (!(x&7)) *bits = 0;
340 val = srccolors[(int)*srcpixel++];
341 *bits |= ( X11DRV_DIB_GetNearestIndex(colors, 2,
342 val.peRed,
343 val.peGreen,
344 val.peBlue) << (7-(x&7)) );
345 if ((x&7)==7) bits++;
347 bits = (dstbits += linebytes);
350 else goto notsupported;
352 break;
354 case 15:
356 LPWORD srcpixel;
357 WORD val;
359 /* ==== 555 BGR bitmap to monochrome dib ==== */
360 if (bmpImage->red_mask == 0x7c00 && bmpImage->blue_mask == 0x1f)
362 for( h = lines - 1; h >= 0; h--) {
363 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
364 for( x = 0; x < dstwidth; x++) {
365 if (!(x&7)) *bits = 0;
366 val = *srcpixel++;
367 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 2,
368 ((val >> 7) & 0xf8) |
369 ((val >> 12) & 0x7),
370 ((val >> 2) & 0xf8) |
371 ((val >> 7) & 0x3),
372 ((val << 3) & 0xf8) |
373 ((val >> 2) & 0x7) ) << (7-(x&7)) );
374 if ((x&7)==7) bits++;
376 bits = (dstbits += linebytes);
379 /* ==== 555 RGB bitmap to monochrome dib ==== */
380 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0xf800)
382 for( h = lines - 1; h >= 0; h--)
384 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
385 for( x = 0; x < dstwidth; x++) {
386 if (!(x&1)) *bits = 0;
387 val = *srcpixel++;
388 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 2,
389 ((val << 3) & 0xf8) |
390 ((val >> 2) & 0x7),
391 ((val >> 2) & 0xf8) |
392 ((val >> 7) & 0x3),
393 ((val >> 7) & 0xf8) |
394 ((val >> 12) & 0x7) ) << (7-(x&7)) );
395 if ((x&7)==7) bits++;
397 bits = (dstbits += linebytes);
400 else goto notsupported;
402 break;
404 case 16:
406 LPWORD srcpixel;
407 WORD val;
409 /* ==== 565 BGR bitmap to monochrome dib ==== */
410 if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f)
412 for( h = lines - 1; h >= 0; h--)
414 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
415 for( x = 0; x < dstwidth; x++) {
416 if (!(x&7)) *bits = 0;
417 val = *srcpixel++;
418 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 2,
419 ((val >> 8) & 0xf8) |
420 ((val >> 13) & 0x7),
421 ((val >> 3) & 0xfc) |
422 ((val >> 9) & 0x3),
423 ((val << 3) & 0xf8) |
424 ((val >> 2) & 0x7) ) << (7-(x&7)) );
425 if ((x&7)==7) bits++;
427 bits = (dstbits += linebytes);
430 /* ==== 565 RGB bitmap to monochrome dib ==== */
431 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0xf800)
433 for( h = lines - 1; h >= 0; h--)
435 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
436 for( x = 0; x < dstwidth; x++) {
437 if (!(x&7)) *bits = 0;
438 val = *srcpixel++;
439 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 2,
440 ((val << 3) & 0xf8) |
441 ((val >> 2) & 0x7),
442 ((val >> 3) & 0xfc) |
443 ((val >> 9) & 0x3),
444 ((val >> 8) & 0xf8) |
445 ((val >> 13) & 0x7) ) << (7-(x&7)) );
446 if ((x&7)==7) bits++;
448 bits = (dstbits += linebytes);
451 else goto notsupported;
453 break;
455 case 24:
456 case 32:
458 BYTE *srcpixel;
460 /* ==== 24/32 BGR bitmap to monochrome dib ==== */
461 if (bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff)
463 for (h = lines - 1; h >= 0; h--)
465 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
466 for (x = 0; x < dstwidth; x++, srcpixel+=4) {
467 if (!(x&7)) *bits = 0;
468 *bits |= (X11DRV_DIB_GetNearestIndex(colors, 2, srcpixel[2] , srcpixel[1], srcpixel[0]) << (7-(x&7)) );
469 if ((x&7)==7) bits++;
471 bits = (dstbits += linebytes);
474 /* ==== 24/32 RGB bitmap to monochrome dib ==== */
475 else if (bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000)
477 for (h = lines - 1; h >= 0; h--)
479 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
480 for (x = 0; x < dstwidth; x++, srcpixel+=4) {
481 if (!(x & 7)) *bits = 0;
482 *bits |= (X11DRV_DIB_GetNearestIndex(colors, 2, srcpixel[0] , srcpixel[1], srcpixel[2]) << (7-(x&7)) );
483 if ((x & 7) == 7) bits++;
485 bits = (dstbits += linebytes);
488 else goto notsupported;
490 break;
492 default: /* ? bit bmp -> monochrome DIB */
493 notsupported:
495 unsigned long white = (1 << bmpImage->bits_per_pixel) - 1;
497 FIXME("from %d bit bitmap with mask R,G,B %x,%x,%x to 1 bit DIB\n",
498 bmpImage->bits_per_pixel, (int)bmpImage->red_mask,
499 (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
501 for( h = lines - 1; h >= 0; h-- ) {
502 for( x = 0; x < dstwidth; x++ ) {
503 if (!(x&7)) *bits = 0;
504 *bits |= (XGetPixel( bmpImage, x, h) >= white)
505 << (7 - (x&7));
506 if ((x&7)==7) bits++;
508 bits = (dstbits += linebytes);
511 break;
515 /***********************************************************************
516 * X11DRV_DIB_SetImageBits_4
518 * SetDIBits for a 4-bit deep DIB.
520 static void X11DRV_DIB_SetImageBits_4( int lines, const BYTE *srcbits,
521 DWORD srcwidth, DWORD dstwidth, int left,
522 int *colors, XImage *bmpImage )
524 DWORD i, x;
525 int h;
526 const BYTE *bits = srcbits + (left >> 1);
528 /* 32 bit aligned */
529 DWORD linebytes = ((srcwidth+7)&~7)/2;
531 if(left & 1) {
532 left--;
533 dstwidth++;
536 if (lines > 0) {
537 for (h = lines-1; h >= 0; h--) {
538 for (i = dstwidth/2, x = left; i > 0; i--) {
539 BYTE pix = *bits++;
540 XPutPixel( bmpImage, x++, h, colors[pix >> 4] );
541 XPutPixel( bmpImage, x++, h, colors[pix & 0x0f] );
543 if (dstwidth & 1) XPutPixel( bmpImage, x, h, colors[*bits >> 4] );
544 srcbits += linebytes;
545 bits = srcbits + (left >> 1);
547 } else {
548 lines = -lines;
549 for (h = 0; h < lines; h++) {
550 for (i = dstwidth/2, x = left; i > 0; i--) {
551 BYTE pix = *bits++;
552 XPutPixel( bmpImage, x++, h, colors[pix >> 4] );
553 XPutPixel( bmpImage, x++, h, colors[pix & 0x0f] );
555 if (dstwidth & 1) XPutPixel( bmpImage, x, h, colors[*bits >> 4] );
556 srcbits += linebytes;
557 bits = srcbits + (left >> 1);
564 /***********************************************************************
565 * X11DRV_DIB_GetImageBits_4
567 * GetDIBits for a 4-bit deep DIB.
569 static void X11DRV_DIB_GetImageBits_4( int lines, BYTE *dstbits,
570 DWORD srcwidth, DWORD dstwidth,
571 RGBQUAD *colors, PALETTEENTRY *srccolors,
572 XImage *bmpImage )
574 DWORD x;
575 int h;
576 BYTE *bits;
577 LPBYTE srcpixel;
579 /* 32 bit aligned */
580 DWORD linebytes = ((srcwidth+7)&~7)/2;
582 if (lines < 0 )
584 lines = -lines;
585 dstbits = dstbits + ( linebytes * (lines-1) );
586 linebytes = -linebytes;
589 bits = dstbits;
591 switch(bmpImage->depth) {
593 case 1:
594 /* ==== monochrome bitmap to 4 colormap dib ==== */
595 case 4:
596 /* ==== 4 colormap bitmap to 4 colormap dib ==== */
597 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
599 PALETTEENTRY val;
601 for (h = lines-1; h >= 0; h--) {
602 for (x = 0; x < dstwidth; x++) {
603 if (!(x&1)) *bits = 0;
604 val = srccolors[XGetPixel(bmpImage, x, h)];
605 *bits |= (X11DRV_DIB_GetNearestIndex(colors, 16,
606 val.peRed,
607 val.peGreen,
608 val.peBlue) << (4-((x&1)<<2)));
609 if ((x&1)==1) bits++;
611 bits = (dstbits += linebytes);
614 else goto notsupported;
616 break;
618 case 8:
619 /* ==== 8 colormap bitmap to 4 colormap dib ==== */
620 if ( bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
622 PALETTEENTRY val;
624 for( h = lines - 1; h >= 0; h-- ) {
625 srcpixel = bmpImage->data + (h*bmpImage->bytes_per_line);
626 for( x = 0; x < dstwidth; x++ ) {
627 if (!(x&1)) *bits = 0;
628 val = srccolors[(int)*srcpixel++];
629 *bits |= ( X11DRV_DIB_GetNearestIndex(colors, 16,
630 val.peRed,
631 val.peGreen,
632 val.peBlue) << (4*(1-(x&1))) );
633 if ((x&1)==1) bits++;
635 bits = (dstbits += linebytes);
638 else goto notsupported;
640 break;
642 case 15:
644 LPWORD srcpixel;
645 WORD val;
647 /* ==== 555 BGR bitmap to 4 colormap dib ==== */
648 if (bmpImage->red_mask == 0x7c00 && bmpImage->blue_mask == 0x1f)
650 for( h = lines - 1; h >= 0; h--) {
651 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
652 for( x = 0; x < dstwidth; x++) {
653 if (!(x&1)) *bits = 0;
654 val = *srcpixel++;
655 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 16,
656 ((val >> 7) & 0xf8) |
657 ((val >> 12) & 0x7),
658 ((val >> 2) & 0xf8) |
659 ((val >> 7) & 0x3),
660 ((val << 3) & 0xf8) |
661 ((val >> 2) & 0x7) ) << ((1-(x&1))<<2) );
662 if ((x&1)==1) bits++;
664 bits = (dstbits += linebytes);
667 /* ==== 555 RGB bitmap to 4 colormap dib ==== */
668 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0x7c00)
670 for( h = lines - 1; h >= 0; h--)
672 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
673 for( x = 0; x < dstwidth; x++) {
674 if (!(x&1)) *bits = 0;
675 val = *srcpixel++;
676 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 16,
677 ((val << 3) & 0xf8) |
678 ((val >> 2) & 0x7),
679 ((val >> 2) & 0xfc) |
680 ((val >> 7) & 0x3),
681 ((val >> 7) & 0xf8) |
682 ((val >> 12) & 0x7) ) << ((1-(x&1))<<2) );
683 if ((x&1)==1) bits++;
685 bits = (dstbits += linebytes);
688 else goto notsupported;
690 break;
692 case 16:
694 LPWORD srcpixel;
695 WORD val;
697 /* ==== 565 BGR bitmap to 4 colormap dib ==== */
698 if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f)
700 for( h = lines - 1; h >= 0; h--)
702 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
703 for( x = 0; x < dstwidth; x++) {
704 if (!(x&1)) *bits = 0;
705 val = *srcpixel++;
706 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 16,
707 ((val >> 8) & 0xf8) |
708 ((val >> 13) & 0x7),
709 ((val >> 3) & 0xfc) |
710 ((val >> 9) & 0x3),
711 ((val << 3) & 0xf8) |
712 ((val >> 2) & 0x7) ) << ((1-(x&1))<<2) );
713 if ((x&1)==1) bits++;
715 bits = (dstbits += linebytes);
718 /* ==== 565 RGB bitmap to 4 colormap dib ==== */
719 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0xf800)
721 for( h = lines - 1; h >= 0; h--)
723 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
724 for( x = 0; x < dstwidth; x++) {
725 if (!(x&1)) *bits = 0;
726 val = *srcpixel++;
727 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 16,
728 ((val << 3) & 0xf8) |
729 ((val >> 2) & 0x7),
730 ((val >> 3) & 0xfc) |
731 ((val >> 9) & 0x3),
732 ((val >> 8) & 0xf8) |
733 ((val >> 13) & 0x7) ) << ((1-(x&1))<<2) );
734 if ((x&1)==1) bits++;
736 bits = (dstbits += linebytes);
739 else goto notsupported;
741 break;
743 case 24:
744 case 32:
746 BYTE *srcpixel;
748 /* ==== 24/32 BGR bitmap to 4 colormap dib ==== */
749 if (bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff)
751 for (h = lines - 1; h >= 0; h--)
753 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
754 for (x = 0; x < dstwidth; x+=2, srcpixel+=8) /* 2 pixels at a time */
755 *bits++ = (X11DRV_DIB_GetNearestIndex(colors, 16, srcpixel[2] , srcpixel[1], srcpixel[0]) << 4) |
756 X11DRV_DIB_GetNearestIndex(colors, 16, srcpixel[6] , srcpixel[5], srcpixel[4]);
757 bits = (dstbits += linebytes);
760 /* ==== 24/32 RGB bitmap to 4 colormap dib ==== */
761 else if (bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000)
763 for (h = lines - 1; h >= 0; h--)
765 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
766 for (x = 0; x < dstwidth; x+=2, srcpixel+=8) /* 2 pixels at a time */
767 *bits++ = (X11DRV_DIB_GetNearestIndex(colors, 16, srcpixel[0] , srcpixel[1], srcpixel[2]) << 4) |
768 X11DRV_DIB_GetNearestIndex(colors, 16, srcpixel[4] , srcpixel[5], srcpixel[6]);
769 bits = (dstbits += linebytes);
772 else goto notsupported;
774 break;
776 default: /* ? bit bmp -> 4 bit DIB */
777 notsupported:
778 FIXME("from %d bit bitmap with mask R,G,B %x,%x,%x to 4 bit DIB\n",
779 bmpImage->bits_per_pixel, (int)bmpImage->red_mask,
780 (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
781 for (h = lines-1; h >= 0; h--) {
782 for (x = 0; x < dstwidth/2; x++) {
783 *bits++ = (X11DRV_DIB_MapColor((int *)colors, 16,
784 XGetPixel( bmpImage, x++, h )) << 4)
785 | (X11DRV_DIB_MapColor((int *)colors, 16,
786 XGetPixel( bmpImage, x++, h )) & 0x0f);
788 if (dstwidth & 1)
789 *bits = (X11DRV_DIB_MapColor((int *)colors, 16,
790 XGetPixel( bmpImage, x++, h )) << 4);
791 bits = (dstbits += linebytes);
793 break;
797 /***********************************************************************
798 * X11DRV_DIB_SetImageBits_RLE4
800 * SetDIBits for a 4-bit deep compressed DIB.
802 static void X11DRV_DIB_SetImageBits_RLE4( int lines, const BYTE *bits,
803 DWORD width, DWORD dstwidth,
804 int left, int *colors,
805 XImage *bmpImage )
807 int x = 0, c, length;
808 const BYTE *begin = bits;
810 lines--;
812 while ((int)lines >= 0) {
813 length = *bits++;
814 if (length) { /* encoded */
815 c = *bits++;
816 while (length--) {
817 if(x >= width) {
818 x = 0;
819 if(--lines < 0)
820 return;
822 XPutPixel(bmpImage, x++, lines, colors[c >>4]);
823 if (length) {
824 length--;
825 if(x >= width) {
826 x = 0;
827 if(--lines < 0)
828 return;
830 XPutPixel(bmpImage, x++, lines, colors[c & 0xf]);
833 } else {
834 length = *bits++;
835 switch (length) {
836 case 0: /* eol */
837 x = 0;
838 lines--;
839 continue;
841 case 1: /* eopicture */
842 return;
844 case 2: /* delta */
845 x += *bits++;
846 if(x >= width) {
847 FIXME_(x11drv)("x-delta is too large?\n");
848 return;
850 lines -= *bits++;
851 continue;
853 default: /* absolute */
854 while (length--) {
855 c = *bits++;
856 if(x >= width) {
857 x = 0;
858 if(--lines < 0)
859 return;
861 XPutPixel(bmpImage, x++, lines, colors[c >> 4]);
862 if (length) {
863 length--;
864 if(x >= width) {
865 x = 0;
866 if(--lines < 0)
867 return;
869 XPutPixel(bmpImage, x++, lines, colors[c & 0xf]);
872 if ((bits - begin) & 1)
873 bits++;
881 /***********************************************************************
882 * X11DRV_DIB_SetImageBits_8
884 * SetDIBits for an 8-bit deep DIB.
886 static void X11DRV_DIB_SetImageBits_8( int lines, const BYTE *srcbits,
887 DWORD srcwidth, DWORD dstwidth, int left,
888 int *colors, XImage *bmpImage )
890 DWORD x;
891 int h, color;
892 const BYTE *bits;
894 /* align to 32 bit */
895 DWORD linebytes = (srcwidth + 3) & ~3;
897 dstwidth += left;
899 if (lines < 0 )
901 lines = -lines;
902 srcbits = srcbits + ( linebytes * (lines-1) );
903 linebytes = -linebytes;
906 bits = srcbits + left;
908 for (h = lines - 1; h >= 0; h--) {
909 for (x = left; x < dstwidth; x++, bits++) {
910 color = colors[*bits];
911 XPutPixel( bmpImage, x, h, colors[*bits] );
913 bits = (srcbits += linebytes) + left;
917 /***********************************************************************
918 * X11DRV_DIB_GetImageBits_8
920 * GetDIBits for an 8-bit deep DIB.
922 static void X11DRV_DIB_GetImageBits_8( int lines, BYTE *dstbits,
923 DWORD srcwidth, DWORD dstwidth,
924 RGBQUAD *colors, PALETTEENTRY *srccolors,
925 XImage *bmpImage )
927 DWORD x;
928 int h;
929 BYTE *bits;
931 /* align to 32 bit */
932 DWORD linebytes = (srcwidth + 3) & ~3;
934 if (lines < 0 )
936 lines = -lines;
937 dstbits = dstbits + ( linebytes * (lines-1) );
938 linebytes = -linebytes;
941 bits = dstbits;
944 Hack for now
945 This condition is true when GetImageBits has been called by UpdateDIBSection.
946 For now, GetNearestIndex is too slow to support 256 colormaps, so we'll just use for
947 for GetDIBits calls. (In somes cases, in a updateDIBSection, the returned colors are bad too)
949 if (!srccolors) goto updatesection;
951 switch(bmpImage->depth) {
953 case 1:
954 /* ==== monochrome bitmap to 8 colormap dib ==== */
955 case 4:
956 /* ==== 4 colormap bitmap to 8 colormap dib ==== */
957 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
959 PALETTEENTRY val;
961 for (h = lines - 1; h >= 0; h--) {
962 for (x = 0; x < dstwidth; x++) {
963 val = srccolors[XGetPixel(bmpImage, x, h)];
964 *bits++ = X11DRV_DIB_GetNearestIndex(colors, 256, val.peRed,
965 val.peGreen, val.peBlue);
967 bits = (dstbits += linebytes);
970 else goto notsupported;
972 break;
974 case 8:
975 /* ==== 8 colormap bitmap to 8 colormap dib ==== */
976 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
978 BYTE *srcpixel;
979 PALETTEENTRY val;
981 for (h = lines - 1; h >= 0; h--) {
982 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
983 for (x = 0; x < dstwidth; x++) {
984 val = srccolors[(int)*srcpixel++];
985 *bits++ = X11DRV_DIB_GetNearestIndex(colors, 256, val.peRed,
986 val.peGreen, val.peBlue);
988 bits = (dstbits += linebytes);
991 else goto notsupported;
993 break;
995 case 15:
997 LPWORD srcpixel;
998 WORD val;
1000 /* ==== 555 BGR bitmap to 8 colormap dib ==== */
1001 if (bmpImage->red_mask == 0x7c00 && bmpImage->blue_mask == 0x001f)
1003 for( h = lines - 1; h >= 0; h--)
1005 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
1006 for( x = 0; x < dstwidth; x++ )
1008 val = *srcpixel++;
1009 *bits++ = X11DRV_DIB_GetNearestIndex( colors, 256,
1010 ((val >> 7) & 0xf8) |
1011 ((val >> 12) & 0x7),
1012 ((val >> 2) & 0xf8) |
1013 ((val >> 7) & 0x3),
1014 ((val << 3) & 0xf8) |
1015 ((val >> 2) & 0x7) );
1017 bits = (dstbits += linebytes);
1020 /* ==== 555 RGB bitmap to 8 colormap dib ==== */
1021 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0x7c00)
1023 for( h = lines - 1; h >= 0; h--)
1025 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
1026 for( x = 0; x < dstwidth; x++ )
1028 val = *srcpixel++;
1029 *bits++ = X11DRV_DIB_GetNearestIndex( colors, 256,
1030 ((val << 3) & 0xf8) |
1031 ((val >> 2) & 0x7),
1032 ((val >> 2) & 0xf8) |
1033 ((val >> 7) & 0x3),
1034 ((val >> 7) & 0xf8) |
1035 ((val >> 12) & 0x7) );
1037 bits = (dstbits += linebytes);
1040 else goto notsupported;
1042 break;
1044 case 16:
1046 LPWORD srcpixel;
1047 WORD val;
1049 /* ==== 565 BGR bitmap to 8 colormap dib ==== */
1050 if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f)
1052 for( h = lines - 1; h >= 0; h--)
1054 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
1055 for( x = 0; x < dstwidth; x++ )
1057 val = *srcpixel++;
1058 *bits++ = X11DRV_DIB_GetNearestIndex( colors, 256,
1059 ((val >> 8) & 0xf8) |
1060 ((val >> 13) & 0x7),
1061 ((val >> 3) & 0xfc) |
1062 ((val >> 9) & 0x3),
1063 ((val << 3) & 0xf8) |
1064 ((val >> 2) & 0x7) );
1066 bits = (dstbits += linebytes);
1069 /* ==== 565 RGB bitmap to 8 colormap dib ==== */
1070 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0xf800)
1072 for( h = lines - 1; h >= 0; h--)
1074 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
1075 for( x = 0; x < dstwidth; x++ )
1077 val = *srcpixel++;
1078 *bits++ = X11DRV_DIB_GetNearestIndex( colors, 256,
1079 ((val << 3) & 0xf8) |
1080 ((val >> 2) & 0x7),
1081 ((val >> 3) & 0x00fc) |
1082 ((val >> 9) & 0x3),
1083 ((val >> 8) & 0x00f8) |
1084 ((val >> 13) & 0x7) );
1086 bits = (dstbits += linebytes);
1089 else goto notsupported;
1091 break;
1093 case 24:
1094 case 32:
1096 BYTE *srcpixel;
1098 /* ==== 24/32 BGR bitmap to 8 colormap dib ==== */
1099 if (bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff)
1101 for (h = lines - 1; h >= 0; h--)
1103 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
1104 for (x = 0; x < dstwidth; x++, srcpixel+=4)
1105 *bits++ = X11DRV_DIB_GetNearestIndex(colors, 256,
1106 srcpixel[2] , srcpixel[1], *srcpixel);
1107 bits = (dstbits += linebytes);
1110 /* ==== 24/32 RGB bitmap to 8 colormap dib ==== */
1111 else if (bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000)
1113 for (h = lines - 1; h >= 0; h--)
1115 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
1116 for (x = 0; x < dstwidth; x++, srcpixel+=4)
1117 *bits++ = X11DRV_DIB_GetNearestIndex(colors, 256,
1118 *srcpixel, srcpixel[1], srcpixel[2]);
1119 bits = (dstbits += linebytes);
1123 else goto notsupported;
1125 break;
1127 default: /* ? bit bmp -> 8 bit DIB */
1128 notsupported:
1129 FIXME("from %d bit bitmap with mask R,G,B %x,%x,%x to 8 bit DIB\n",
1130 bmpImage->depth, (int)bmpImage->red_mask,
1131 (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
1132 updatesection:
1133 for (h = lines - 1; h >= 0; h--) {
1134 for (x = 0; x < dstwidth; x++, bits++) {
1135 *bits = X11DRV_DIB_MapColor((int *)colors, 256,
1136 XGetPixel( bmpImage, x, h ) );
1138 bits = (dstbits += linebytes);
1140 break;
1144 /***********************************************************************
1145 * X11DRV_DIB_SetImageBits_RLE8
1147 * SetDIBits for an 8-bit deep compressed DIB.
1149 * This function rewritten 941113 by James Youngman. WINE blew out when I
1150 * first ran it because my desktop wallpaper is a (large) RLE8 bitmap.
1152 * This was because the algorithm assumed that all RLE8 bitmaps end with the
1153 * 'End of bitmap' escape code. This code is very much laxer in what it
1154 * allows to end the expansion. Possibly too lax. See the note by
1155 * case RleDelta. BTW, MS's documentation implies that a correct RLE8
1156 * bitmap should end with RleEnd, but on the other hand, software exists
1157 * that produces ones that don't and Windows 3.1 doesn't complain a bit
1158 * about it.
1160 * (No) apologies for my English spelling. [Emacs users: c-indent-level=4].
1161 * James A. Youngman <mbcstjy@afs.man.ac.uk>
1162 * [JAY]
1165 enum Rle8_EscapeCodes
1168 * Apologies for polluting your file's namespace...
1170 RleEol = 0, /* End of line */
1171 RleEnd = 1, /* End of bitmap */
1172 RleDelta = 2 /* Delta */
1175 static void X11DRV_DIB_SetImageBits_RLE8( int lines, const BYTE *bits,
1176 DWORD width, DWORD dstwidth,
1177 int left, int *colors,
1178 XImage *bmpImage )
1180 int x; /* X-positon on each line. Increases. */
1181 int line; /* Line #. Starts at lines-1, decreases */
1182 const BYTE *pIn = bits; /* Pointer to current position in bits */
1183 BYTE length; /* The length pf a run */
1184 BYTE color_index; /* index into colors[] as read from bits */
1185 BYTE escape_code; /* See enum Rle8_EscapeCodes.*/
1186 int color; /* value of colour[color_index] */
1188 if (lines == 0) /* Let's hope this doesn't happen. */
1189 return;
1192 * Note that the bitmap data is stored by Windows starting at the
1193 * bottom line of the bitmap and going upwards. Within each line,
1194 * the data is stored left-to-right. That's the reason why line
1195 * goes from lines-1 to 0. [JAY]
1198 x = 0;
1199 line = lines-1;
1202 length = *pIn++;
1205 * If the length byte is not zero (which is the escape value),
1206 * We have a run of length pixels all the same colour. The colour
1207 * index is stored next.
1209 * If the length byte is zero, we need to read the next byte to
1210 * know what to do. [JAY]
1212 if (length != 0)
1215 * [Run-Length] Encoded mode
1217 color_index = (*pIn++); /* Get the colour index. */
1218 color = colors[color_index];
1220 while(length--)
1221 XPutPixel(bmpImage, x++, line, color);
1223 else
1226 * Escape codes (may be an absolute sequence though)
1228 escape_code = (*pIn++);
1229 switch(escape_code)
1231 case RleEol: /* =0, end of line */
1233 x = 0;
1234 line--;
1235 break;
1238 case RleEnd: /* =1, end of bitmap */
1241 * Not all RLE8 bitmaps end with this
1242 * code. For example, Paint Shop Pro
1243 * produces some that don't. That's (I think)
1244 * what caused the previous implementation to
1245 * fail. [JAY]
1247 line=-1; /* Cause exit from do loop. */
1248 break;
1251 case RleDelta: /* =2, a delta */
1254 * Note that deltaing to line 0
1255 * will cause an exit from the loop,
1256 * which may not be what is intended.
1257 * The fact that there is a delta in the bits
1258 * almost certainly implies that there is data
1259 * to follow. You may feel that we should
1260 * jump to the top of the loop to avoid exiting
1261 * in this case.
1263 * TODO: Decide what to do here in that case. [JAY]
1265 x += (*pIn++);
1266 line -= (*pIn++);
1267 if (line == 0)
1269 TRACE("Delta to last line of bitmap "
1270 "(wrongly?) causes loop exit\n");
1272 break;
1275 default: /* >2, switch to absolute mode */
1278 * Absolute Mode
1280 length = escape_code;
1281 while(length--)
1283 color_index = (*pIn++);
1284 XPutPixel(bmpImage, x++, line,
1285 colors[color_index]);
1289 * If you think for a moment you'll realise that the
1290 * only time we could ever possibly read an odd
1291 * number of bytes is when there is a 0x00 (escape),
1292 * a value >0x02 (absolute mode) and then an odd-
1293 * length run. Therefore this is the only place we
1294 * need to worry about it. Everywhere else the
1295 * bytes are always read in pairs. [JAY]
1297 if (escape_code & 1)
1298 pIn++; /* Throw away the pad byte. */
1299 break;
1301 } /* switch (escape_code) : Escape sequence */
1302 } /* process either an encoded sequence or an escape sequence */
1304 /* We expect to come here more than once per line. */
1305 } while (line >= 0); /* Do this until the bitmap is filled */
1308 * Everybody comes here at the end.
1309 * Check how we exited the loop and print a message if it's a bit odd.
1310 * [JAY]
1312 if ( (*(pIn-2) != 0/*escape*/) || (*(pIn-1)!= RleEnd) )
1314 TRACE("End-of-bitmap without (strictly) proper escape code. Last two "
1315 "bytes were: %02X %02X.\n", (int)*(pIn-2),(int)*(pIn-1));
1320 /***********************************************************************
1321 * X11DRV_DIB_SetImageBits_16
1323 * SetDIBits for a 16-bit deep DIB.
1325 static void X11DRV_DIB_SetImageBits_16( int lines, const BYTE *srcbits,
1326 DWORD srcwidth, DWORD dstwidth, int left,
1327 DC *dc, DWORD rSrc, DWORD gSrc, DWORD bSrc,
1328 XImage *bmpImage )
1330 DWORD x;
1331 int h;
1333 /* align to 32 bit */
1334 DWORD linebytes = (srcwidth * 2 + 3) & ~3;
1336 if (lines < 0 )
1338 lines = -lines;
1339 srcbits = srcbits + ( linebytes * (lines-1));
1340 linebytes = -linebytes;
1343 switch ( bmpImage->depth )
1345 case 15:
1346 /* using same format as XImage */
1347 if (rSrc == bmpImage->red_mask && gSrc == bmpImage->green_mask && bSrc == bmpImage->blue_mask)
1348 for (h = lines - 1; h >= 0; h--, srcbits += linebytes)
1349 memcpy ( bmpImage->data + h * bmpImage->bytes_per_line + left*2, srcbits + left*2, dstwidth*2 );
1350 else /* We need to do a conversion from a 565 dib */
1352 LPDWORD dstpixel, ptr = (LPDWORD)(srcbits + left*2);
1353 DWORD val;
1354 int div = dstwidth % 2;
1356 for (h = lines - 1; h >= 0; h--) {
1357 dstpixel = (LPDWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1358 for (x = 0; x < dstwidth/2; x++) { /* Do 2 pixels at a time */
1359 val = *ptr++;
1360 *dstpixel++ = ((val >> 1) & 0x7fe07fe0) | (val & 0x001f001f); /* Red & Green & Blue */
1362 if (div != 0) /* Odd width? */
1363 *dstpixel = ((*(WORD *)ptr >> 1) & 0x7fe0) | (*(WORD *)ptr & 0x001f);
1364 ptr = (LPDWORD) ((srcbits += linebytes) + left*2);
1367 break;
1369 case 16:
1370 /* using same format as XImage */
1371 if (rSrc == bmpImage->red_mask && gSrc == bmpImage->green_mask && bSrc == bmpImage->blue_mask)
1372 for (h = lines - 1; h >= 0; h--, srcbits += linebytes)
1373 memcpy ( bmpImage->data + h * bmpImage->bytes_per_line + left*2, srcbits + left*2, dstwidth*2 );
1374 else /* We need to do a conversion from a 555 dib */
1376 LPDWORD dstpixel, ptr = (LPDWORD)(srcbits + left*2);
1377 DWORD val;
1378 int div = dstwidth % 2;
1380 for (h = lines - 1; h >= 0; h--) {
1381 dstpixel = (LPDWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1382 for (x = 0; x < dstwidth/2; x++) { /* Do 2 pixels at a time */
1383 val = *ptr++;
1384 *dstpixel++ = ((val << 1) & 0xffc0ffc0) | ((val >> 4) & 0x00200020) | /* Red & Green */
1385 (val & 0x001f001f); /* Blue */
1387 if (div != 0) /* Odd width? */
1388 *dstpixel = ((*(WORD *)ptr << 1) & 0xffc0) | ((*(WORD *)ptr >> 4) & 0x0020)
1389 | (*(WORD *)ptr & 0x001f);
1390 ptr = (LPDWORD) ((srcbits += linebytes) + left*2);
1393 break;
1395 case 24:
1396 case 32:
1398 DWORD *dstpixel;
1399 LPWORD ptr = (LPWORD)srcbits + left;
1400 DWORD val;
1402 /* ==== 555 BGR dib to 24/32 BGR bitmap ==== */
1403 if (bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff)
1405 for (h = lines - 1; h >= 0; h--) {
1406 dstpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line + left*4);
1407 for (x = 0; x < dstwidth; x++) {
1409 val = *ptr++;
1410 *dstpixel++ = ((val << 9) & 0xf80000) | ((val << 4) & 0x070000) | /* Red */
1411 ((val << 6) & 0x00f800) | ((val << 1) & 0x000700) | /* Green */
1412 ((val << 3) & 0x0000f8) | ((val >> 2) & 0x000007); /* Blue */
1414 ptr = (LPWORD)(srcbits += linebytes) + left;
1417 /* ==== 555 BGR dib to 24/32 RGB bitmap ==== */
1418 else if (bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000)
1420 for (h = lines - 1; h >= 0; h--) {
1421 dstpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line + left*4);
1422 for (x = 0; x < dstwidth; x++) {
1424 val = *ptr++;
1425 *dstpixel++ = ((val >> 7) & 0x0000f8) | ((val >> 12) & 0x000007) | /* Red */
1426 ((val << 6) & 0x00f800) | ((val << 1) & 0x000700) | /* Green */
1427 ((val << 19) & 0xf80000) | ((val >> 14) & 0x070000); /* Blue */
1429 ptr = (LPWORD)(srcbits += linebytes) + left;
1434 break;
1436 case 1:
1437 case 4:
1438 case 8:
1440 LPWORD ptr = (LPWORD)srcbits + left;
1441 WORD val;
1442 int sc1, sc2;
1444 /* Set color scaling values */
1445 if ( rSrc == 0x7c00 ) { sc1 = 7; sc2 = 2; } /* 555 dib */
1446 else { sc1 = 8; sc2 = 3; } /* 565 dib */
1448 for (h = lines - 1; h >= 0; h--) {
1449 for (x = left; x < dstwidth+left; x++) {
1450 val = *ptr++;
1451 XPutPixel( bmpImage, x, h,
1452 X11DRV_PALETTE_ToPhysical(dc, RGB(((val & rSrc) >> sc1), /* Red */
1453 ((val & gSrc) >> sc2), /* Green */
1454 ((val & bSrc) << 3)))); /* Blue */
1456 ptr = (LPWORD) (srcbits += linebytes) + left;
1459 break;
1461 default:
1462 FIXME("16 bit DIB %d bit bitmap\n", bmpImage->bits_per_pixel);
1463 break;
1469 /***********************************************************************
1470 * X11DRV_DIB_GetImageBits_16
1472 * GetDIBits for an 16-bit deep DIB.
1474 static void X11DRV_DIB_GetImageBits_16( int lines, BYTE *dstbits,
1475 DWORD dstwidth, DWORD srcwidth,
1476 PALETTEENTRY *srccolors, XImage *bmpImage )
1478 DWORD x;
1479 int h;
1481 /* align to 32 bit */
1482 DWORD linebytes = (dstwidth * 2 + 3) & ~3;
1484 if (lines < 0 )
1486 lines = -lines;
1487 dstbits = dstbits + ( linebytes * (lines-1));
1488 linebytes = -linebytes;
1491 switch ( bmpImage->depth )
1493 case 15:
1494 /* ==== 555 BGR bitmap to 555 BGR dib ==== */
1495 if (bmpImage->red_mask == 0x7c00 && bmpImage->blue_mask == 0x001f)
1496 for (h = lines - 1; h >= 0; h--, dstbits += linebytes)
1497 memcpy( dstbits, bmpImage->data + h*bmpImage->bytes_per_line, srcwidth*2 );
1499 /* ==== 555 RGB bitmap to 555 BGR dib ==== */
1500 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0x7c00)
1502 LPDWORD srcpixel, ptr = (LPDWORD)dstbits;
1503 DWORD val;
1504 int div = srcwidth % 2;
1506 for (h = lines - 1; h >= 0; h--) {
1507 srcpixel = (LPDWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
1508 for (x = 0; x < srcwidth/2; x++) { /* Do 2 pixels at a time */
1509 val = *srcpixel++;
1510 *ptr++ = ((val << 10) & 0xf800f800) | (val & 0x03e003e0) | /* Red & Green */
1511 ((val >> 10) & 0x001f001f); /* Blue */
1513 if (div != 0) /* Odd width? */
1514 *ptr = ((*(WORD *)srcpixel << 1) & 0xffc0) | ((*(WORD *)srcpixel >> 4) & 0x0020) |
1515 (*(WORD *)srcpixel & 0x001f);
1516 ptr = (LPDWORD)(dstbits += linebytes);
1519 else goto notsupported;
1521 break;
1523 case 16:
1525 LPDWORD srcpixel, ptr = (LPDWORD)dstbits;
1526 DWORD val;
1527 int div = srcwidth % 2;
1529 /* ==== 565 BGR bitmap to 555 BGR dib ==== */
1530 if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f )
1532 for (h = lines - 1; h >= 0; h--) {
1533 srcpixel = (LPDWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
1534 for (x = 0; x < srcwidth/2; x++) { /* Do 2 pixels at a time */
1535 val = *srcpixel++;
1536 *ptr++ = ((val >> 1) & 0x7fe07fe0) | /* Red & Green */
1537 (val & 0x001f001f); /* Blue */
1539 if (div != 0) /* Odd width? */
1540 *ptr = ((*(WORD *)srcpixel >> 1) & 0x7fe0) | (*(WORD *)srcpixel & 0x001f);
1541 ptr = (LPDWORD) (dstbits += linebytes);
1544 /* ==== 565 RGB bitmap to 555 BGR dib ==== */
1545 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0xf800)
1547 for (h = lines - 1; h >= 0; h--) {
1548 srcpixel = (LPDWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
1549 for (x = 0; x < srcwidth/2; x++) { /* Do 2 pixels at a time */
1550 val = *srcpixel++;
1551 *ptr++ = ((val << 10) & 0x7c007c00) | ((val >> 1) & 0x03e003e0) | /* Red & Green */
1552 ((val >> 11) & 0x001f001f); /* Blue */
1554 if (div != 0) /* Odd width? */
1555 *ptr = ((*(WORD *)srcpixel >> 1) & 0x7fe0) | (*(WORD *)srcpixel & 0x001f);
1556 ptr = (LPDWORD) (dstbits += linebytes);
1559 else goto notsupported;
1561 break;
1563 case 24:
1564 case 32:
1566 DWORD *srcpixel;
1567 LPWORD ptr = (LPWORD)dstbits;
1568 DWORD val;
1570 /* ==== 24/32 BGR bitmap to 555 BGR dib ==== */
1571 if (bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff)
1573 for (h = lines - 1; h >= 0; h--) {
1574 srcpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line);
1575 for (x = 0; x < srcwidth; x++, ptr++) {
1576 val = *srcpixel++;
1577 *ptr = ((val >> 9) & 0x7c00) | /* Red */
1578 ((val >> 6) & 0x03e0) | /* Green */
1579 ((val >> 3) & 0x001f); /* Blue */
1581 ptr = (LPWORD)(dstbits += linebytes);
1584 /* ==== 24/32 RGB bitmap to 555 BGR dib ==== */
1585 else if (bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000)
1587 for (h = lines - 1; h >= 0; h--) {
1588 srcpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line);
1589 for (x = 0; x < srcwidth; x++, ptr++) {
1590 val = *srcpixel++;
1591 *ptr = ((val << 7) & 0x7c00) | /* Red */
1592 ((val >> 6) & 0x03e0) | /* Green */
1593 ((val >> 19) & 0x001f); /* Blue */
1595 ptr = (LPWORD) (dstbits += linebytes);
1598 else goto notsupported;
1600 break;
1602 case 1:
1603 /* ==== monochrome bitmap to 16 BGR dib ==== */
1604 case 4:
1605 /* ==== 4 colormap bitmap to 16 BGR dib ==== */
1606 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
1608 LPWORD ptr = (LPWORD)dstbits;
1609 PALETTEENTRY val;
1611 for (h = lines - 1; h >= 0; h--) {
1612 for (x = 0; x < dstwidth; x++) {
1613 val = srccolors[XGetPixel(bmpImage, x, h)];
1614 *ptr++ = ((val.peRed << 7) & 0x7c00) |
1615 ((val.peGreen << 2) & 0x03e0) |
1616 ((val.peBlue >> 3) & 0x001f);
1618 ptr = (LPWORD)(dstbits += linebytes);
1621 else goto notsupported;
1623 break;
1625 case 8:
1626 /* ==== 8 colormap bitmap to 16 BGR dib ==== */
1627 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
1629 LPWORD ptr = (LPWORD)dstbits;
1630 BYTE *srcpixel;
1631 PALETTEENTRY val;
1633 for (h = lines - 1; h >= 0; h--) {
1634 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
1635 for (x = 0; x < dstwidth; x++) {
1636 val = srccolors[(int)*srcpixel++];
1637 *ptr++ = ((val.peRed << 7) & 0x7c00) |
1638 ((val.peGreen << 2) & 0x03e0) |
1639 ((val.peBlue >> 3) & 0x001f);
1641 ptr = (LPWORD)(dstbits += linebytes);
1644 else goto notsupported;
1646 break;
1648 default:
1649 notsupported:
1651 BYTE r,g, b;
1652 LPWORD ptr = (LPWORD)dstbits;
1654 FIXME("from %d bit bitmap with mask R,G,B %x,%x,%x to 16 bit DIB\n",
1655 bmpImage->depth, (int)bmpImage->red_mask,
1656 (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
1657 for (h = lines - 1; h >= 0; h--)
1659 for (x = 0; x < dstwidth; x++, ptr++)
1661 COLORREF pixel = X11DRV_PALETTE_ToLogical( XGetPixel( bmpImage, x, h ) );
1662 r = (BYTE) GetRValue(pixel);
1663 g = (BYTE) GetGValue(pixel);
1664 b = (BYTE) GetBValue(pixel);
1665 *ptr = ( ((r << 7) & 0x7c00) | ((g << 2) & 0x03e0) | ((b >> 3) & 0x001f) );
1667 ptr = (LPWORD) (dstbits += linebytes);
1670 break;
1675 /***********************************************************************
1676 * X11DRV_DIB_SetImageBits_24
1678 * SetDIBits for a 24-bit deep DIB.
1680 static void X11DRV_DIB_SetImageBits_24( int lines, const BYTE *srcbits,
1681 DWORD srcwidth, DWORD dstwidth, int left,
1682 DC *dc, XImage *bmpImage )
1684 DWORD x;
1685 int h;
1687 /* align to 32 bit */
1688 DWORD linebytes = (srcwidth * 3 + 3) & ~3;
1690 if (lines < 0 )
1692 lines = -lines;
1693 srcbits = srcbits + linebytes * (lines - 1);
1694 linebytes = -linebytes;
1697 switch ( bmpImage->depth )
1699 case 24:
1700 case 32:
1702 if( bmpImage->blue_mask == 0xff && bmpImage->red_mask == 0xff0000 ) /* packed BGR to unpacked BGR */
1704 DWORD *dstpixel, val, buf;
1705 DWORD *ptr = (DWORD *)(srcbits + left*3);
1706 BYTE *bits;
1707 int div = dstwidth % 4;
1708 int divk;
1710 for(h = lines - 1; h >= 0; h--)
1712 dstpixel = (DWORD *) (bmpImage->data + h*bmpImage->bytes_per_line + left*4);
1714 for (x = 0; x < dstwidth/4; x++) { /* do 3 dwords source, 4 dwords dest at a time */
1715 buf = *ptr++;
1716 *dstpixel++ = buf&0x00ffffff; /* b1, g1, r1 */
1717 val = (buf >> 24); /* b2 */
1718 buf = *ptr++;
1719 *dstpixel++ = (val | (buf<<8)) &0x00ffffff; /* g2, r2 */
1720 val = (buf >> 16); /* b3, g3 */
1721 buf = *ptr++;
1722 *dstpixel++ = (val | (buf<<16)) &0x00ffffff; /* r3 */
1723 *dstpixel++ = (buf >> 8); /* b4, g4, r4 */
1725 for ( divk=div, bits=(BYTE*)ptr; divk>0; divk--, bits+=3 ) /* do remainder */
1727 *dstpixel++ = *(DWORD*)bits & 0x00ffffff; /* b, g, r */
1729 ptr = (DWORD*)((srcbits+=linebytes)+left*3);
1732 else if( bmpImage->blue_mask == 0xff0000 && bmpImage->red_mask == 0xff ) /* packed BGR to unpacked RGB */
1734 DWORD *dstpixel, val, buf;
1735 DWORD *ptr = (DWORD *)(srcbits + left*3);
1736 BYTE *bits;
1737 int div = dstwidth % 4;
1738 int divk;
1740 for(h = lines - 1; h >= 0; h--)
1742 dstpixel = (DWORD *) (bmpImage->data + h*bmpImage->bytes_per_line + left*4);
1744 for (x = 0; x < dstwidth/4; x++) { /* do 3 dwords source, 4 dwords dest at a time */
1745 buf = *ptr++;
1746 *dstpixel++ = ((buf&0xff)<<16) | (buf&0xff00) | ((buf&0xff0000)>>16); /* b1, g1, r1 */
1747 val = ((buf&0xff000000)>>8); /* b2 */
1748 buf = *ptr++;
1749 *dstpixel++ = val | ((buf&0xff)<<8) | ((buf&0xff00)>>8); /* g2, r2 */
1750 val = (buf&0xff0000) | ((buf&0xff000000)>>16); /* b3, g3 */
1751 buf = *ptr++;
1752 *dstpixel++ = val | (buf&0xff); /* r3 */
1753 *dstpixel++ = ((buf&0xff00)<<8) | ((buf&0xff0000)>>8) | (buf>>24); /* b4, g4, r4 */
1755 for ( divk=div, bits=(BYTE*)ptr; divk>0; divk--, bits+=3 ) /* do remainder */
1757 buf = *(DWORD*)bits;
1758 *dstpixel++ = ((buf&0xff)<<16) | (buf&0xff00) | ((buf&0xff0000)>>16); /* b, g, r */
1760 ptr = (DWORD*)((srcbits+=linebytes)+left*3);
1763 else
1764 goto notsupported;
1766 break;
1768 case 15:
1770 if( bmpImage->blue_mask == 0x7c00 && bmpImage->red_mask == 0x1f ) /* BGR888 to RGB555 */
1772 DWORD *ptr = (DWORD *)(srcbits + left*3), val;
1773 LPBYTE bits;
1774 LPWORD dstpixel;
1775 int div = dstwidth % 4;
1776 int divk;
1778 for (h = lines - 1; h >= 0; h--) { /* Do 4 pixels at a time */
1779 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1780 for (x = 0; x < dstwidth/4; x++) {
1781 *dstpixel++ = (WORD)((((val = *ptr++) << 7) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 19) & 0x1f));
1782 *dstpixel++ = (WORD)(((val >> 17) & 0x7c00) | (((val = *ptr++) << 2) & 0x03e0) | ((val >> 11) & 0x1f));
1783 *dstpixel++ = (WORD)(((val >> 9) & 0x07c00) | ((val >> 22) & 0x03e0) | (((val = *ptr++) >> 3) & 0x1f));
1784 *dstpixel++ = (WORD)(((val >> 1) & 0x07c00) | ((val >> 14) & 0x03e0) | ((val >> 27) & 0x1f));
1786 for (bits = (LPBYTE)ptr, divk=div; divk > 0; divk--, bits+=3) /* dstwidth not divisible by 4? */
1787 *dstpixel++ = (((WORD)bits[0] << 7) & 0x07c00) |
1788 (((WORD)bits[1] << 2) & 0x03e0) |
1789 (((WORD)bits[2] >> 3) & 0x001f);
1790 ptr = (DWORD *)((srcbits += linebytes) + left * 3);
1793 else if( bmpImage->blue_mask == 0x1f && bmpImage->red_mask == 0x7c00 ) /* BGR888 to BGR555 */
1795 DWORD *ptr = (DWORD *)(srcbits + left*3), val;
1796 LPBYTE bits;
1797 LPWORD dstpixel;
1798 int div = dstwidth % 4;
1799 int divk;
1801 for (h = lines - 1; h >= 0; h--) { /* Do 4 pixels at a time */
1802 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1803 for (x = 0; x < dstwidth/4; x++) {
1804 *dstpixel++ = (WORD)((((val = *ptr++) >> 3) & 0x1f) | ((val >> 6) & 0x03e0) | ((val >> 9) & 0x7c00));
1805 *dstpixel++ = (WORD)(((val >> 27) & 0x1f) | (((val = *ptr++) << 2) & 0x03e0) | ((val >> 1) & 0x7c00));
1806 *dstpixel++ = (WORD)(((val >> 19) & 0x1f) | ((val >> 22) & 0x03e0) | (((val = *ptr++) << 7) & 0x7c00));
1807 *dstpixel++ = (WORD)(((val >> 11) & 0x1f) | ((val >> 14) & 0x03e0) | ((val >> 17) & 0x7c00));
1809 for (bits = (LPBYTE)ptr, divk=div; divk > 0; divk--, bits+=3) /* dstwidth not divisible by 4? */
1810 *dstpixel++ = (((WORD)bits[2] << 7) & 0x07c00) |
1811 (((WORD)bits[1] << 2) & 0x03e0) |
1812 (((WORD)bits[0] >> 3) & 0x001f);
1813 ptr = (DWORD *)((srcbits += linebytes) + left * 3);
1816 else
1817 goto notsupported;
1819 break;
1821 case 16:
1823 DWORD *ptr = (DWORD *)(srcbits + left*3), val;
1824 LPBYTE bits;
1825 LPWORD dstpixel;
1826 int div = dstwidth % 4;
1827 int divk;
1829 if( bmpImage->blue_mask == 0x001f && bmpImage->red_mask == 0xf800 ) /* BGR888 to BGR565 */
1831 for (h = lines - 1; h >= 0; h--) { /* Do 4 pixels at a time */
1832 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1833 for (x = 0; x < dstwidth/4; x++) {
1834 *dstpixel++ = (WORD)((((val = *ptr++) >> 3) & 0x1f) | ((val >> 5) & 0x07e0) | ((val >> 8) & 0xf800));
1835 *dstpixel++ = (WORD)(((val >> 27) & 0x1f) | (((val = *ptr++) << 3) & 0x07e0) | ((val) & 0xf800));
1836 *dstpixel++ = (WORD)(((val >> 19) & 0x1f) | ((val >> 21) & 0x07e0) | (((val = *ptr++) << 8) & 0xf800));
1837 *dstpixel++ = (WORD)(((val >> 11) & 0x1f) | ((val >> 13) & 0x07e0) | ((val >> 16) & 0xf800));
1839 for ( bits = (LPBYTE)ptr, divk=div; divk > 0; divk--, bits+=3) /* dstwidth is not divisible by 4? */
1840 *dstpixel++ = (((WORD)bits[2] << 8) & 0xf800) |
1841 (((WORD)bits[1] << 3) & 0x07e0) |
1842 (((WORD)bits[0] >> 3) & 0x001f);
1843 ptr = (DWORD *)((srcbits += linebytes) + left * 3);
1846 else if( bmpImage->blue_mask == 0xf800 && bmpImage->red_mask == 0x001f ) /* BGR888 to RGB565 */
1848 for (h = lines - 1; h >= 0; h--) { /* Do 4 pixels at a time */
1849 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1850 for (x = 0; x < dstwidth/4; x++) {
1851 *dstpixel++ = (WORD)((((val = *ptr++) << 8) & 0xf800) | ((val >> 5) & 0x07e0) | ((val >> 19) & 0x1f));
1852 *dstpixel++ = (WORD)(((val >> 16) & 0xf800) | (((val = *ptr++) << 3) & 0x07e0) | ((val >> 11) & 0x1f));
1853 *dstpixel++ = (WORD)(((val >> 8) & 0xf800) | ((val >> 21) & 0x07e0) | (((val = *ptr++) >> 3) & 0x1f));
1854 *dstpixel++ = (WORD)((val & 0xf800) | ((val >> 13) & 0x07e0) | ((val >> 27) & 0x1f));
1856 for ( bits = (LPBYTE)ptr, divk=div; divk > 0; divk--, bits+=3) /* dstwidth is not divisible by 4? */
1857 *dstpixel++ = (((WORD)bits[0] << 8) & 0xf800) |
1858 (((WORD)bits[1] << 3) & 0x07e0) |
1859 (((WORD)bits[2] >> 3) & 0x001f);
1860 ptr = (DWORD *)((srcbits += linebytes) + left * 3);
1863 else
1864 goto notsupported;
1866 break;
1868 case 1:
1869 case 4:
1870 case 8:
1872 LPBYTE bits = (LPBYTE)srcbits + left*3;
1874 for (h = lines - 1; h >= 0; h--) {
1875 for (x = left; x < dstwidth+left; x++, bits+=3)
1876 XPutPixel( bmpImage, x, h,
1877 X11DRV_PALETTE_ToPhysical(dc, RGB(bits[2], bits[1], bits[0])));
1878 bits = (LPBYTE)(srcbits += linebytes) + left * 3;
1881 break;
1883 default:
1884 notsupported:
1885 FIXME("from 24 bit DIB to %d bit bitmap with mask R,G,B %x,%x,%x\n",
1886 bmpImage->bits_per_pixel, (int)bmpImage->red_mask,
1887 (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
1888 break;
1893 /***********************************************************************
1894 * X11DRV_DIB_GetImageBits_24
1896 * GetDIBits for an 24-bit deep DIB.
1898 static void X11DRV_DIB_GetImageBits_24( int lines, BYTE *dstbits,
1899 DWORD dstwidth, DWORD srcwidth,
1900 PALETTEENTRY *srccolors, XImage *bmpImage )
1902 DWORD x, val;
1903 int h;
1905 /* align to 32 bit */
1906 DWORD linebytes = (dstwidth * 3 + 3) & ~3;
1908 if (lines < 0 )
1910 lines = -lines;
1911 dstbits = dstbits + ( linebytes * (lines-1) );
1912 linebytes = -linebytes;
1915 switch ( bmpImage->depth )
1917 case 24:
1918 case 32:
1920 DWORD *srcpixel, buf;
1921 LPBYTE bits;
1922 DWORD *ptr=(DWORD *)dstbits;
1923 int quotient = dstwidth / 4;
1924 int remainder = dstwidth % 4;
1925 int remk;
1927 /* ==== 24/32 BGR bitmap to 24 BGR dib==== */
1928 if( bmpImage->blue_mask == 0xff && bmpImage->red_mask == 0xff0000 )
1930 for(h = lines - 1; h >= 0; h--)
1932 srcpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line);
1934 for (x = 0; x < quotient; x++) { /* do 4 dwords source, 3 dwords dest at a time*/
1935 buf = ((*srcpixel++)&0x00ffffff); /* b1, g1, r1*/
1936 *ptr++ = buf | ((*srcpixel)<<24); /* b2 */
1937 buf = ((*srcpixel++>>8)&0x0000ffff); /* g2, r2 */
1938 *ptr++ = buf | ((*srcpixel)<<16); /* b3, g3 */
1939 buf = ((*srcpixel++>>16)&0x000000ff); /* r3 */
1940 *ptr++ = buf | ((*srcpixel++)<<8); /* b4, g4, r4 */
1942 for ( remk=remainder, bits=(BYTE*)ptr; remk>0; remk--, bits+=3 ) /* do remainder */
1944 buf=*srcpixel++;
1945 *(WORD*)bits = buf; /* b, g */
1946 *(bits+2) = buf>>16; /* r */
1948 ptr = (DWORD*)(dstbits+=linebytes);
1952 /* ==== 24/32 RGB bitmap to 24 BGR dib ==== */
1953 else if( bmpImage->blue_mask == 0xff0000 && bmpImage->red_mask == 0xff )
1955 for(h = lines - 1; h >= 0; h--)
1957 srcpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line);
1959 for (x = 0; x < quotient; x++) { /* do 4 dwords source, 3 dwords dest at a time */
1960 buf = *srcpixel++;
1961 val = ((buf&0xff0000)>>16) | (buf&0xff00) | ((buf&0xff)<<16); /* b1, g1, r1 */
1962 buf = *srcpixel++;
1963 *ptr++ = val | ((buf&0xff0000)<<8); /* b2 */
1964 val = ((buf&0xff00)>>8) | ((buf&0xff)<<8); /* g2, r2 */
1965 buf = *srcpixel++;
1966 *ptr++ = val | (buf&0xff0000) | ((buf&0xff00)<<16); /* b3, g3 */
1967 val = (buf&0xff); /* r3 */
1968 buf = *srcpixel++;
1969 *ptr++ = val | ((buf&0xff0000)>>8) | ((buf&0xff00)<<8) | (buf<<24); /* b4, g4, r4 */
1971 for ( remk=remainder, bits=(BYTE*)ptr; remk>0; remk--, bits+=3 ) /* do remainder */
1973 buf=*srcpixel++;
1974 *(WORD*)bits = (buf&0xff00) | ((buf&0xff0000)>>16) ; /* b, g */
1975 *(bits+2) = buf; /* r */
1977 ptr = (DWORD*)(dstbits+=linebytes);
1980 else goto notsupported;
1982 break;
1984 case 15:
1986 LPWORD srcpixel;
1987 LPBYTE bits = dstbits;
1988 WORD val;
1990 /* ==== 555 BGR bitmap to 24 BGR dib ==== */
1991 if( bmpImage->blue_mask == 0x1f && bmpImage->red_mask == 0x7c00 )
1993 for (h = lines - 1; h >= 0; h--) {
1994 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
1995 for (x = 0; x < srcwidth; x++, bits += 3) {
1996 val = *srcpixel++;
1997 bits[2] = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07)); /*Red*/
1998 bits[1] = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07)); /*Green*/
1999 bits[0] = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07)); /*Blue*/
2001 bits = (dstbits += linebytes);
2004 /* ==== 555 RGB bitmap to 24 RGB dib==== */
2005 else if( bmpImage->blue_mask == 0x7c00 && bmpImage->red_mask == 0x1f )
2007 for (h = lines - 1; h >= 0; h--) {
2008 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2009 for (x = 0; x < srcwidth; x++, bits += 3) {
2010 val = *srcpixel++;
2011 bits[0] = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07)); /*Red*/
2012 bits[1] = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07)); /*Green*/
2013 bits[2] = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07)); /*Blue*/
2015 bits = (dstbits += linebytes);
2018 else goto notsupported;
2020 break;
2022 case 16:
2024 LPWORD srcpixel;
2025 LPBYTE bits = dstbits;
2026 WORD val;
2028 /* ==== 565 BGR bitmap to 24 BGR dib ==== */
2029 if( bmpImage->blue_mask == 0x1f && bmpImage->red_mask == 0xf800 )
2031 for (h = lines - 1; h >= 0; h--) {
2032 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2033 for (x = 0; x < srcwidth; x++, bits += 3) {
2034 val = *srcpixel++;
2035 bits[2] = (BYTE)(((val >> 8) & 0xf8) | ((val >> 13) & 0x07)); /*Red*/
2036 bits[1] = (BYTE)(((val >> 3) & 0xfc) | ((val >> 9) & 0x03)); /*Green*/
2037 bits[0] = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07)); /*Blue*/
2039 bits = (dstbits += linebytes);
2042 /* ==== 565 RGB bitmap to 24 BGR dib ==== */
2043 else if( bmpImage->blue_mask == 0xf800 && bmpImage->red_mask == 0x1f )
2045 for (h = lines - 1; h >= 0; h--) {
2046 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2047 for (x = 0; x < srcwidth; x++, bits += 3) {
2048 val = *srcpixel++;
2049 bits[0] = (BYTE)(((val >> 8) & 0xf8) | ((val >> 13) & 0x07)); /*Red*/
2050 bits[1] = (BYTE)(((val >> 3) & 0xfc) | ((val >> 9) & 0x03)); /*Green*/
2051 bits[2] = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07)); /*Blue*/
2053 bits = (dstbits += linebytes);
2056 else goto notsupported;
2058 break;
2060 case 1:
2061 /* ==== monochrome bitmap to 24 BGR dib ==== */
2062 case 4:
2063 /* ==== 4 colormap bitmap to 24 BGR dib ==== */
2064 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
2066 LPBYTE bits = dstbits;
2067 PALETTEENTRY val;
2069 for (h = lines - 1; h >= 0; h--) {
2070 for (x = 0; x < dstwidth; x++) {
2071 val = srccolors[XGetPixel(bmpImage, x, h)];
2072 *bits++ = val.peBlue;
2073 *bits++ = val.peGreen;
2074 *bits++ = val.peRed;
2076 bits = (dstbits += linebytes);
2079 else goto notsupported;
2081 break;
2083 case 8:
2084 /* ==== 8 colormap bitmap to 24 BGR dib ==== */
2085 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask == 0 && srccolors)
2087 BYTE *srcpixel;
2088 LPBYTE bits = dstbits;
2089 PALETTEENTRY val;
2091 for (h = lines - 1; h >= 0; h--) {
2092 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
2093 for (x = 0; x < dstwidth; x++ ) {
2094 val = srccolors[(int)*srcpixel++];
2095 *bits++ = val.peBlue; /*Blue*/
2096 *bits++ = val.peGreen; /*Green*/
2097 *bits++ = val.peRed; /*Red*/
2099 bits = (dstbits += linebytes);
2102 else goto notsupported;
2104 break;
2106 default:
2107 notsupported:
2109 LPBYTE bits = dstbits;
2111 FIXME("from %d bit bitmap with mask R,G,B %x,%x,%x to 24 bit DIB\n",
2112 bmpImage->depth, (int)bmpImage->red_mask,
2113 (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
2114 for (h = lines - 1; h >= 0; h--)
2116 for (x = 0; x < dstwidth; x++, bits += 3)
2118 COLORREF pixel = X11DRV_PALETTE_ToLogical( XGetPixel( bmpImage, x, h ) );
2119 bits[0] = GetBValue(pixel);
2120 bits[1] = GetGValue(pixel);
2121 bits[2] = GetRValue(pixel);
2123 bits = (dstbits += linebytes);
2126 break;
2131 /***********************************************************************
2132 * X11DRV_DIB_SetImageBits_32
2134 * SetDIBits for a 32-bit deep DIB.
2136 static void X11DRV_DIB_SetImageBits_32( int lines, const BYTE *srcbits,
2137 DWORD srcwidth, DWORD dstwidth, int left,
2138 DC *dc, XImage *bmpImage )
2140 DWORD x, *ptr;
2141 int h;
2143 DWORD linebytes = (srcwidth * 4);
2145 if (lines < 0 )
2147 lines = -lines;
2148 srcbits = srcbits + ( linebytes * (lines-1) );
2149 linebytes = -linebytes;
2152 ptr = (DWORD *) srcbits + left;
2154 switch ( bmpImage->depth )
2156 case 24:
2157 case 32:
2158 /* ==== 32 BGR dib to 24/32 BGR bitmap ==== */
2159 if (bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff) {
2160 for (h = lines - 1; h >= 0; h--, srcbits+=linebytes) {
2161 memcpy( bmpImage->data + h * bmpImage->bytes_per_line, srcbits + left*4, dstwidth*4 );
2165 /* ==== 32 BGR dib to 24/32 RGB bitmap ==== */
2166 else if (bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000)
2168 DWORD *dstpixel;
2170 for (h = lines - 1; h >= 0; h--) {
2171 dstpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line);
2172 for (x = 0; x < dstwidth; x++, ptr++) {
2173 *dstpixel++ = ((*ptr << 16) & 0xff0000) | (*ptr & 0xff00) | ((*ptr >> 16) & 0xff);
2175 ptr = (DWORD *) (srcbits += linebytes) + left;
2178 else goto notsupported;
2180 break;
2182 case 15:
2183 /* ==== 32 BGR dib to 555 BGR bitmap ==== */
2184 if (bmpImage->red_mask == 0x7c00 && bmpImage->blue_mask == 0x001f)
2186 LPWORD dstpixel;
2188 for (h = lines - 1; h >= 0; h--) {
2189 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2190 for (x = 0; x < dstwidth; x++, ptr++) {
2191 *dstpixel++ = (WORD) (((*ptr >> 9) & 0x7c00) | ((*ptr >> 6) & 0x03e0) | ((*ptr >> 3) & 0x001f));
2193 ptr = (DWORD *) (srcbits += linebytes) + left;
2196 /* ==== 32 BGR dib to 555 RGB bitmap ==== */
2197 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0x7c00)
2199 LPWORD dstpixel;
2201 for (h = lines - 1; h >= 0; h--) {
2202 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2203 for (x = 0; x < dstwidth; x++, ptr++) {
2204 *dstpixel++ = (WORD) (((*ptr << 7) & 0x7c00) | ((*ptr >> 6) & 0x03e0) | ((*ptr >> 19) & 0x001f));
2206 ptr = (DWORD *) (srcbits += linebytes) + left;
2209 else goto notsupported;
2211 break;
2213 case 16:
2214 /* ==== 32 BGR dib to 565 BGR bitmap ==== */
2215 if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f)
2217 LPWORD dstpixel;
2219 for (h = lines - 1; h >= 0; h--) {
2220 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2221 for (x = 0; x < dstwidth; x++, ptr++) {
2222 *dstpixel++ = (WORD) (((*ptr >> 8) & 0xf800) | ((*ptr >> 5) & 0x07e0) | ((*ptr >> 3) & 0x001f));
2224 ptr = (DWORD *) (srcbits += linebytes) + left;
2227 /* ==== 32 BGR dib to 565 RGB bitmap ==== */
2228 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0xf800)
2230 LPWORD dstpixel;
2232 for (h = lines - 1; h >= 0; h--) {
2233 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2234 for (x = 0; x < dstwidth; x++, ptr++) {
2235 *dstpixel++ = (WORD) (((*ptr << 8) & 0xf800) | ((*ptr >> 5) & 0x07e0) | ((*ptr >> 19) & 0x001f));
2237 ptr = (DWORD *) (srcbits += linebytes) + left;
2240 else goto notsupported;
2242 break;
2244 case 1:
2245 case 4:
2246 case 8:
2248 LPBYTE bits = (LPBYTE)srcbits + left*4;
2250 for (h = lines - 1; h >= 0; h--) {
2251 for (x = left; x < dstwidth+left; x++, bits += 4)
2252 XPutPixel( bmpImage, x, h,
2253 X11DRV_PALETTE_ToPhysical(dc, RGB( bits[2], bits[1], *bits )));
2254 bits = (LPBYTE)(srcbits += linebytes) + left * 4;
2257 break;
2259 default:
2260 notsupported:
2261 FIXME("32 bit DIB %d bit bitmap\n", bmpImage->bits_per_pixel);
2262 break;
2267 /***********************************************************************
2268 * X11DRV_DIB_GetImageBits_32
2270 * GetDIBits for an 32-bit deep DIB.
2272 static void X11DRV_DIB_GetImageBits_32( int lines, BYTE *dstbits,
2273 DWORD dstwidth, DWORD srcwidth,
2274 PALETTEENTRY *srccolors, XImage *bmpImage )
2276 DWORD x;
2277 int h;
2278 BYTE *bits;
2280 /* align to 32 bit */
2281 DWORD linebytes = (srcwidth * 4);
2282 DWORD copybytes = linebytes;
2284 if (lines < 0 )
2286 lines = -lines;
2287 dstbits = dstbits + ( linebytes * (lines-1) );
2288 linebytes = -linebytes;
2291 bits = dstbits;
2293 switch ( bmpImage->depth )
2295 case 24:
2296 case 32:
2297 /* ==== 24/32 BGR bitmap to 32 BGR dib ==== */
2298 if ( bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff )
2299 for (h = lines - 1; h >= 0; h--, dstbits+=linebytes)
2300 memcpy( dstbits, bmpImage->data + h*bmpImage->bytes_per_line, copybytes );
2302 /* ==== 24/32 RGB bitmap to 32 BGR dib ==== */
2303 else if ( bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000 )
2305 LPBYTE srcbits;
2307 for (h = lines - 1; h >= 0; h--) {
2308 srcbits = bmpImage->data + h * bmpImage->bytes_per_line;
2309 for (x = 0; x < dstwidth; x++, bits+=4, srcbits+=2) {
2310 *(bits + 2) = *srcbits++;
2311 *(bits + 1) = *srcbits++;
2312 *bits = *srcbits;
2314 bits = (dstbits += linebytes);
2317 else goto notsupported;
2318 break;
2320 case 15:
2322 LPWORD srcpixel;
2323 WORD val;
2325 /* ==== 555 BGR bitmap to 32 BGR dib ==== */
2326 if (bmpImage->red_mask == 0x7c00 && bmpImage->blue_mask == 0x001f)
2328 for (h = lines - 1; h >= 0; h--) {
2329 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2330 for (x = 0; x < dstwidth; x++, bits+=2) {
2331 val = *srcpixel++;
2332 *bits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x03)); /*Blue*/
2333 *bits++ = (BYTE)(((val >> 2) & 0xfc) | ((val >> 8) & 0x03)); /*Green*/
2334 *bits = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07)); /*Red*/
2336 bits = (dstbits += linebytes);
2339 /* ==== 555 RGB bitmap to 32 BGR dib ==== */
2340 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0x7c00)
2342 for (h = lines - 1; h >= 0; h--) {
2343 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2344 for (x = 0; x < dstwidth; x++, bits+=2) {
2345 val = *srcpixel++;
2346 *bits++ = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07));/*Blue*/
2347 *bits++ = (BYTE)(((val >> 2) & 0xfc) | ((val >> 8) & 0x03)); /*Green*/
2348 *bits = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x03)); /*Red*/
2350 bits = (dstbits += linebytes);
2353 else goto notsupported;
2355 break;
2357 case 16:
2359 LPWORD srcpixel;
2360 WORD val;
2362 /* ==== 565 BGR bitmap to 32 BGR dib ==== */
2363 if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f)
2365 for (h = lines - 1; h >= 0; h--) {
2366 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2367 for (x = 0; x < srcwidth; x++, bits+=2) {
2368 val = *srcpixel++;
2369 *bits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x03)); /*Blue*/
2370 *bits++ = (BYTE)(((val >> 3) & 0xfc) | ((val >> 9) & 0x03)); /*Green*/
2371 *bits = (BYTE)(((val >> 8) & 0xf8) | ((val >> 13) & 0x07)); /*Red*/
2373 bits = (dstbits += linebytes);
2376 /* ==== 565 RGB bitmap to 32 BGR dib ==== */
2377 else if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f)
2379 for (h = lines - 1; h >= 0; h--) {
2380 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2381 for (x = 0; x < srcwidth; x++, bits+=2) {
2382 val = *srcpixel++;
2383 *bits++ = (BYTE)(((val >> 8) & 0xf8) | ((val >> 13) & 0x07));/*Blue*/
2384 *bits++ = (BYTE)(((val >> 3) & 0xfc) | ((val >> 9) & 0x03)); /*Green*/
2385 *bits = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x03)); /*Red*/
2387 bits = (dstbits += linebytes);
2390 else goto notsupported;
2392 break;
2394 case 1:
2395 /* ==== monochrome bitmap to 32 BGR dib ==== */
2396 case 4:
2397 /* ==== 4 colormap bitmap to 32 BGR dib ==== */
2398 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
2400 PALETTEENTRY val;
2402 for (h = lines - 1; h >= 0; h--) {
2403 for (x = 0; x < dstwidth; x++) {
2404 val = srccolors[XGetPixel(bmpImage, x, h)];
2405 *bits++ = val.peBlue;
2406 *bits++ = val.peGreen;
2407 *bits++ = val.peRed;
2408 *bits++ = 0;
2410 bits = (dstbits += linebytes);
2413 else goto notsupported;
2415 break;
2417 case 8:
2418 /* ==== 8 colormap bitmap to 32 BGR dib ==== */
2419 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
2421 BYTE *srcpixel;
2422 PALETTEENTRY val;
2424 for (h = lines - 1; h >= 0; h--) {
2425 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
2426 for (x = 0; x < dstwidth; x++) {
2427 val = srccolors[(int)*srcpixel++];
2428 *bits++ = val.peBlue; /*Blue*/
2429 *bits++ = val.peGreen; /*Green*/
2430 *bits++ = val.peRed; /*Red*/
2431 *bits++ = 0;
2433 bits = (dstbits += linebytes);
2436 else goto notsupported;
2437 break;
2439 default:
2440 notsupported:
2441 FIXME("from %d bit bitmap with mask R,G,B %x,%x,%x to 32 bit DIB\n",
2442 bmpImage->depth, (int)bmpImage->red_mask,
2443 (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
2444 for (h = lines - 1; h >= 0; h--)
2446 for (x = 0; x < dstwidth; x++, bits += 4)
2448 COLORREF pixel = X11DRV_PALETTE_ToLogical( XGetPixel( bmpImage, x, h ) );
2449 bits[0] = GetBValue(pixel);
2450 bits[1] = GetGValue(pixel);
2451 bits[2] = GetRValue(pixel);
2453 bits = (dstbits += linebytes);
2455 break;
2459 /***********************************************************************
2460 * X11DRV_DIB_SetImageBits
2462 * Transfer the bits to an X image.
2463 * Helper function for SetDIBits() and SetDIBitsToDevice().
2464 * The Xlib critical section must be entered before calling this function.
2466 int X11DRV_DIB_SetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
2468 int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
2469 XImage *bmpImage;
2471 if ( descr->dc && descr->dc->w.flags & DC_DIRTY )
2472 CLIPPING_UpdateGCRegion( descr->dc );
2474 if (descr->image)
2475 bmpImage = descr->image;
2476 else {
2477 bmpImage = XCreateImage( display,
2478 DefaultVisualOfScreen(X11DRV_GetXScreen()),
2479 descr->depth, ZPixmap, 0, NULL,
2480 descr->infoWidth, lines, 32, 0 );
2481 bmpImage->data = xcalloc( bmpImage->bytes_per_line * lines );
2484 /* Transfer the pixels */
2485 switch(descr->infoBpp)
2487 case 1:
2488 X11DRV_DIB_SetImageBits_1( descr->lines, descr->bits, descr->infoWidth,
2489 descr->width, descr->xSrc, (int *)(descr->colorMap),
2490 bmpImage );
2491 break;
2492 case 4:
2493 if (descr->compression) {
2494 XGetSubImage( display, descr->drawable, descr->xDest, descr->yDest,
2495 descr->width, descr->height, AllPlanes, ZPixmap,
2496 bmpImage, descr->xSrc, descr->ySrc );
2498 X11DRV_DIB_SetImageBits_RLE4( descr->lines, descr->bits,
2499 descr->infoWidth, descr->width,
2500 descr->xSrc, (int *)(descr->colorMap),
2501 bmpImage );
2502 } else
2503 X11DRV_DIB_SetImageBits_4( descr->lines, descr->bits,
2504 descr->infoWidth, descr->width,
2505 descr->xSrc, (int*)(descr->colorMap),
2506 bmpImage );
2507 break;
2508 case 8:
2509 if (descr->compression) {
2510 XGetSubImage( display, descr->drawable, descr->xDest, descr->yDest,
2511 descr->width, descr->height, AllPlanes, ZPixmap,
2512 bmpImage, descr->xSrc, descr->ySrc );
2513 X11DRV_DIB_SetImageBits_RLE8( descr->lines, descr->bits,
2514 descr->infoWidth, descr->width,
2515 descr->xSrc, (int *)(descr->colorMap),
2516 bmpImage );
2517 } else
2518 X11DRV_DIB_SetImageBits_8( descr->lines, descr->bits,
2519 descr->infoWidth, descr->width,
2520 descr->xSrc, (int *)(descr->colorMap),
2521 bmpImage );
2522 break;
2523 case 15:
2524 case 16:
2525 X11DRV_DIB_SetImageBits_16( descr->lines, descr->bits,
2526 descr->infoWidth, descr->width,
2527 descr->xSrc, descr->dc,
2528 descr->rMask, descr->gMask, descr->bMask,
2529 bmpImage);
2530 break;
2531 case 24:
2532 X11DRV_DIB_SetImageBits_24( descr->lines, descr->bits,
2533 descr->infoWidth, descr->width,
2534 descr->xSrc, descr->dc, bmpImage );
2535 break;
2536 case 32:
2537 X11DRV_DIB_SetImageBits_32( descr->lines, descr->bits,
2538 descr->infoWidth, descr->width,
2539 descr->xSrc, descr->dc,
2540 bmpImage);
2541 break;
2542 default:
2543 WARN("(%d): Invalid depth\n", descr->infoBpp );
2544 break;
2547 if (descr->useShm)
2549 XShmPutImage( display, descr->drawable, descr->gc, bmpImage,
2550 descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
2551 descr->width, descr->height, FALSE );
2552 XSync( display, 0 );
2554 else
2555 XPutImage( display, descr->drawable, descr->gc, bmpImage,
2556 descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
2557 descr->width, descr->height );
2559 if (!descr->image) XDestroyImage( bmpImage );
2560 return lines;
2563 /***********************************************************************
2564 * X11DRV_DIB_GetImageBits
2566 * Transfer the bits from an X image.
2567 * The Xlib critical section must be entered before calling this function.
2569 int X11DRV_DIB_GetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
2571 int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
2572 XImage *bmpImage;
2574 if (descr->image)
2575 bmpImage = descr->image;
2576 else {
2577 bmpImage = XCreateImage( display,
2578 DefaultVisualOfScreen(X11DRV_GetXScreen()),
2579 descr->depth, ZPixmap, 0, NULL,
2580 descr->infoWidth, lines, 32, 0 );
2581 bmpImage->data = xcalloc( bmpImage->bytes_per_line * lines );
2584 XGetSubImage( display, descr->drawable, descr->xDest, descr->yDest,
2585 descr->width, descr->height, AllPlanes, ZPixmap,
2586 bmpImage, descr->xSrc, descr->ySrc );
2588 /* Transfer the pixels */
2589 switch(descr->infoBpp)
2591 case 1:
2592 X11DRV_DIB_GetImageBits_1( descr->lines,(LPVOID)descr->bits,
2593 descr->infoWidth, descr->width,
2594 descr->colorMap, descr->palentry,
2595 bmpImage );
2596 break;
2598 case 4:
2599 if (descr->compression)
2600 FIXME("Compression not yet supported!\n");
2601 else
2602 X11DRV_DIB_GetImageBits_4( descr->lines,(LPVOID)descr->bits,
2603 descr->infoWidth, descr->width,
2604 descr->colorMap, descr->palentry,
2605 bmpImage );
2606 break;
2608 case 8:
2609 if (descr->compression)
2610 FIXME("Compression not yet supported!\n");
2611 else
2612 X11DRV_DIB_GetImageBits_8( descr->lines, (LPVOID)descr->bits,
2613 descr->infoWidth, descr->width,
2614 descr->colorMap, descr->palentry,
2615 bmpImage );
2616 break;
2617 case 15:
2618 case 16:
2619 X11DRV_DIB_GetImageBits_16( descr->lines, (LPVOID)descr->bits,
2620 descr->infoWidth,descr->width,
2621 descr->palentry, bmpImage );
2622 break;
2624 case 24:
2625 X11DRV_DIB_GetImageBits_24( descr->lines, (LPVOID)descr->bits,
2626 descr->infoWidth,descr->width,
2627 descr->palentry, bmpImage );
2628 break;
2630 case 32:
2631 X11DRV_DIB_GetImageBits_32( descr->lines, (LPVOID)descr->bits,
2632 descr->infoWidth, descr->width,
2633 descr->palentry, bmpImage );
2634 break;
2636 default:
2637 WARN("(%d): Invalid depth\n", descr->infoBpp );
2638 break;
2641 if (!descr->image) XDestroyImage( bmpImage );
2642 return lines;
2645 /*************************************************************************
2646 * X11DRV_SetDIBitsToDevice
2649 INT X11DRV_SetDIBitsToDevice( DC *dc, INT xDest, INT yDest, DWORD cx,
2650 DWORD cy, INT xSrc, INT ySrc,
2651 UINT startscan, UINT lines, LPCVOID bits,
2652 const BITMAPINFO *info, UINT coloruse )
2654 X11DRV_DIB_IMAGEBITS_DESCR descr;
2655 DWORD width, oldcy = cy;
2656 INT result;
2657 int height, tmpheight;
2658 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
2661 if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height,
2662 &descr.infoBpp, &descr.compression ) == -1)
2663 return 0;
2664 tmpheight = height;
2665 if (height < 0) height = -height;
2666 if (!lines || (startscan >= height)) return 0;
2667 if (startscan + lines > height) lines = height - startscan;
2668 if (ySrc < startscan) ySrc = startscan;
2669 else if (ySrc >= startscan + lines) return 0;
2670 if (xSrc >= width) return 0;
2671 if (ySrc + cy >= startscan + lines) cy = startscan + lines - ySrc;
2672 if (xSrc + cx >= width) cx = width - xSrc;
2673 if (!cx || !cy) return 0;
2675 X11DRV_SetupGCForText( dc ); /* To have the correct colors */
2676 TSXSetFunction(display, physDev->gc, X11DRV_XROPfunction[dc->w.ROPmode-1]);
2678 switch (descr.infoBpp)
2680 case 1:
2681 case 4:
2682 case 8:
2683 descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap(
2684 coloruse == DIB_PAL_COLORS ? dc : NULL, coloruse,
2685 dc->w.bitsPerPixel, info, &descr.nColorMap );
2686 if (!descr.colorMap) return 0;
2687 descr.rMask = descr.gMask = descr.bMask = 0;
2688 break;
2689 case 15:
2690 case 16:
2691 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
2692 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x03e0;
2693 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x001f;
2694 descr.colorMap = 0;
2695 break;
2697 case 24:
2698 descr.rMask = descr.gMask = descr.bMask = 0;
2699 descr.colorMap = 0;
2700 break;
2702 case 32:
2703 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
2704 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0xff00;
2705 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0xff;
2706 descr.colorMap = 0;
2707 break;
2710 descr.dc = dc;
2711 descr.bits = bits;
2712 descr.image = NULL;
2713 descr.palentry = NULL;
2714 descr.lines = tmpheight >= 0 ? lines : -lines;
2715 descr.infoWidth = width;
2716 descr.depth = dc->w.bitsPerPixel;
2717 descr.drawable = physDev->drawable;
2718 descr.gc = physDev->gc;
2719 descr.xSrc = xSrc;
2720 descr.ySrc = tmpheight >= 0 ? lines-(ySrc-startscan)-cy+(oldcy-cy)
2721 : ySrc - startscan;
2722 descr.xDest = dc->w.DCOrgX + XLPTODP( dc, xDest );
2723 descr.yDest = dc->w.DCOrgY + YLPTODP( dc, yDest ) +
2724 (tmpheight >= 0 ? oldcy-cy : 0);
2725 descr.width = cx;
2726 descr.height = cy;
2727 descr.useShm = FALSE;
2729 EnterCriticalSection( &X11DRV_CritSection );
2730 result = CALL_LARGE_STACK( X11DRV_DIB_SetImageBits, &descr );
2731 LeaveCriticalSection( &X11DRV_CritSection );
2733 if (descr.infoBpp <= 8)
2734 HeapFree(GetProcessHeap(), 0, descr.colorMap);
2735 return result;
2738 /***********************************************************************
2739 * X11DRV_DIB_SetDIBits
2741 INT X11DRV_DIB_SetDIBits(
2742 BITMAPOBJ *bmp, DC *dc, UINT startscan,
2743 UINT lines, LPCVOID bits, const BITMAPINFO *info,
2744 UINT coloruse, HBITMAP hbitmap)
2746 X11DRV_DIB_IMAGEBITS_DESCR descr;
2747 X11DRV_PHYSBITMAP *pbitmap;
2748 int height, tmpheight;
2749 INT result;
2751 descr.dc = dc;
2753 if (DIB_GetBitmapInfo( &info->bmiHeader, &descr.infoWidth, &height,
2754 &descr.infoBpp, &descr.compression ) == -1)
2755 return 0;
2757 tmpheight = height;
2758 if (height < 0) height = -height;
2759 if (!lines || (startscan >= height))
2760 return 0;
2762 if (startscan + lines > height) lines = height - startscan;
2764 switch (descr.infoBpp)
2766 case 1:
2767 case 4:
2768 case 8:
2769 descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap(
2770 coloruse == DIB_PAL_COLORS ? descr.dc : NULL, coloruse,
2771 bmp->bitmap.bmBitsPixel,
2772 info, &descr.nColorMap );
2773 if (!descr.colorMap) return 0;
2774 descr.rMask = descr.gMask = descr.bMask = 0;
2775 break;
2776 case 15:
2777 case 16:
2778 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
2779 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x03e0;
2780 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x001f;
2781 descr.colorMap = 0;
2782 break;
2784 case 24:
2785 descr.rMask = descr.gMask = descr.bMask = 0;
2786 descr.colorMap = 0;
2787 break;
2789 case 32:
2790 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
2791 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0xff00;
2792 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0xff;
2793 descr.colorMap = 0;
2794 break;
2796 default: break;
2799 /* HACK for now */
2800 if(!bmp->DDBitmap)
2801 X11DRV_CreateBitmap(hbitmap);
2803 pbitmap = bmp->DDBitmap->physBitmap;
2805 descr.bits = bits;
2806 descr.image = NULL;
2807 descr.palentry = NULL;
2808 descr.lines = tmpheight >= 0 ? lines : -lines;
2809 descr.depth = bmp->bitmap.bmBitsPixel;
2810 descr.drawable = pbitmap->pixmap;
2811 descr.gc = BITMAP_GC(bmp);
2812 descr.xSrc = 0;
2813 descr.ySrc = 0;
2814 descr.xDest = 0;
2815 descr.yDest = height - startscan - lines;
2816 descr.width = bmp->bitmap.bmWidth;
2817 descr.height = lines;
2818 descr.useShm = FALSE;
2820 EnterCriticalSection( &X11DRV_CritSection );
2821 result = CALL_LARGE_STACK( X11DRV_DIB_SetImageBits, &descr );
2822 LeaveCriticalSection( &X11DRV_CritSection );
2824 if (descr.colorMap) HeapFree(GetProcessHeap(), 0, descr.colorMap);
2826 return result;
2829 /***********************************************************************
2830 * X11DRV_DIB_GetDIBits
2832 INT X11DRV_DIB_GetDIBits(
2833 BITMAPOBJ *bmp, DC *dc, UINT startscan,
2834 UINT lines, LPVOID bits, BITMAPINFO *info,
2835 UINT coloruse, HBITMAP hbitmap)
2837 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
2838 X11DRV_DIB_IMAGEBITS_DESCR descr;
2839 X11DRV_PHYSBITMAP *pbitmap;
2840 PALETTEOBJ * palette;
2842 TRACE("%u scanlines of (%i,%i) -> (%i,%i) starting from %u\n",
2843 lines, bmp->bitmap.bmWidth, bmp->bitmap.bmHeight,
2844 (int)info->bmiHeader.biWidth, (int)info->bmiHeader.biHeight,
2845 startscan );
2847 if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->w.hPalette, PALETTE_MAGIC )))
2848 return 0;
2850 if( lines > info->bmiHeader.biHeight ) lines = info->bmiHeader.biHeight;
2851 if( startscan >= bmp->bitmap.bmHeight ) return FALSE;
2853 if (DIB_GetBitmapInfo( &info->bmiHeader, &descr.infoWidth, &descr.lines,
2854 &descr.infoBpp, &descr.compression ) == -1)
2855 return FALSE;
2857 switch (descr.infoBpp)
2859 case 1:
2860 case 4:
2861 case 8:
2862 case 24:
2863 descr.rMask = descr.gMask = descr.bMask = 0;
2864 break;
2865 case 15:
2866 case 16:
2867 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
2868 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x03e0;
2869 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x001f;
2870 break;
2872 case 32:
2873 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
2874 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0xff00;
2875 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0xff;
2876 break;
2879 /* Hack for now */
2880 if(!bmp->DDBitmap)
2881 X11DRV_CreateBitmap(hbitmap);
2883 pbitmap = bmp->DDBitmap->physBitmap;
2885 descr.dc = dc;
2886 descr.palentry = palette->logpalette.palPalEntry;
2887 descr.bits = bits;
2888 descr.lines = lines;
2889 descr.depth = bmp->bitmap.bmBitsPixel;
2890 descr.drawable = pbitmap->pixmap;
2891 descr.gc = BITMAP_GC(bmp);
2892 descr.xSrc = 0;
2893 descr.ySrc = startscan;
2894 descr.xDest = 0;
2895 descr.yDest = 0;
2896 descr.width = bmp->bitmap.bmWidth;
2897 descr.height = bmp->bitmap.bmHeight;
2898 descr.colorMap = info->bmiColors;
2900 if (dib)
2901 descr.useShm = (dib->shminfo.shmid != -1);
2902 else
2903 descr.useShm = FALSE;
2905 EnterCriticalSection( &X11DRV_CritSection );
2907 descr.image = (XImage *)CALL_LARGE_STACK( X11DRV_BITMAP_GetXImage, bmp );
2908 CALL_LARGE_STACK( X11DRV_DIB_GetImageBits, &descr );
2910 LeaveCriticalSection( &X11DRV_CritSection );
2912 if(info->bmiHeader.biSizeImage == 0) /* Fill in biSizeImage */
2913 info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(
2914 info->bmiHeader.biWidth,
2915 info->bmiHeader.biHeight,
2916 info->bmiHeader.biBitCount );
2918 info->bmiHeader.biCompression = 0;
2920 GDI_HEAP_UNLOCK( dc->w.hPalette );
2922 return lines;
2925 /***********************************************************************
2926 * DIB_DoProtectDIBSection
2928 static void X11DRV_DIB_DoProtectDIBSection( BITMAPOBJ *bmp, DWORD new_prot )
2930 DIBSECTION *dib = bmp->dib;
2931 INT effHeight = dib->dsBm.bmHeight >= 0? dib->dsBm.bmHeight
2932 : -dib->dsBm.bmHeight;
2933 INT totalSize = dib->dsBmih.biSizeImage? dib->dsBmih.biSizeImage
2934 : dib->dsBm.bmWidthBytes * effHeight;
2935 DWORD old_prot;
2937 VirtualProtect(dib->dsBm.bmBits, totalSize, new_prot, &old_prot);
2938 TRACE("Changed protection from %ld to %ld\n", old_prot, new_prot);
2941 /***********************************************************************
2942 * X11DRV_DIB_DoUpdateDIBSection
2944 static void X11DRV_DIB_DoUpdateDIBSection(BITMAPOBJ *bmp, BOOL toDIB)
2946 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
2947 X11DRV_DIB_IMAGEBITS_DESCR descr;
2949 if (DIB_GetBitmapInfo( &dib->dibSection.dsBmih, &descr.infoWidth, &descr.lines,
2950 &descr.infoBpp, &descr.compression ) == -1)
2951 return;
2953 descr.dc = NULL;
2954 descr.palentry = NULL;
2955 descr.image = dib->image;
2956 descr.colorMap = (RGBQUAD *)dib->colorMap;
2957 descr.nColorMap = dib->nColorMap;
2958 descr.bits = dib->dibSection.dsBm.bmBits;
2959 descr.depth = bmp->bitmap.bmBitsPixel;
2961 switch (descr.infoBpp)
2963 case 1:
2964 case 4:
2965 case 8:
2966 case 24:
2967 descr.rMask = descr.gMask = descr.bMask = 0;
2968 break;
2969 case 15:
2970 case 16:
2971 descr.rMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[0] : 0x7c00;
2972 descr.gMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[1] : 0x03e0;
2973 descr.bMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[2] : 0x001f;
2974 break;
2976 case 32:
2977 descr.rMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[0] : 0xff;
2978 descr.gMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[1] : 0xff00;
2979 descr.bMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[2] : 0xff0000;
2980 break;
2983 /* Hack for now */
2984 descr.drawable = ((X11DRV_PHYSBITMAP *)bmp->DDBitmap->physBitmap)->pixmap;
2985 descr.gc = BITMAP_GC(bmp);
2986 descr.xSrc = 0;
2987 descr.ySrc = 0;
2988 descr.xDest = 0;
2989 descr.yDest = 0;
2990 descr.width = bmp->bitmap.bmWidth;
2991 descr.height = bmp->bitmap.bmHeight;
2992 descr.useShm = (dib->shminfo.shmid != -1);
2994 if (toDIB)
2996 TRACE("Copying from Pixmap to DIB bits\n");
2997 EnterCriticalSection( &X11DRV_CritSection );
2998 CALL_LARGE_STACK( X11DRV_DIB_GetImageBits, &descr );
2999 LeaveCriticalSection( &X11DRV_CritSection );
3001 else
3003 TRACE("Copying from DIB bits to Pixmap\n");
3004 EnterCriticalSection( &X11DRV_CritSection );
3005 CALL_LARGE_STACK( X11DRV_DIB_SetImageBits, &descr );
3006 LeaveCriticalSection( &X11DRV_CritSection );
3010 /***********************************************************************
3011 * X11DRV_DIB_FaultHandler
3013 static BOOL X11DRV_DIB_FaultHandler( LPVOID res, LPCVOID addr )
3015 BOOL handled = FALSE;
3016 BITMAPOBJ *bmp;
3018 bmp = (BITMAPOBJ *)GDI_GetObjPtr( (HBITMAP)res, BITMAP_MAGIC );
3019 if (!bmp) return FALSE;
3021 if (bmp->dib)
3022 switch (((X11DRV_DIBSECTION *) bmp->dib)->status)
3024 case X11DRV_DIB_GdiMod:
3025 TRACE("called in status DIB_GdiMod\n" );
3026 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
3027 X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
3028 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
3029 ((X11DRV_DIBSECTION *) bmp->dib)->status = X11DRV_DIB_InSync;
3030 handled = TRUE;
3031 break;
3033 case X11DRV_DIB_InSync:
3034 TRACE("called in status X11DRV_DIB_InSync\n" );
3035 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
3036 ((X11DRV_DIBSECTION *) bmp->dib)->status = X11DRV_DIB_AppMod;
3037 handled = TRUE;
3038 break;
3040 case X11DRV_DIB_AppMod:
3041 FIXME("called in status X11DRV_DIB_AppMod: this can't happen!\n" );
3042 break;
3044 case X11DRV_DIB_NoHandler:
3045 FIXME("called in status DIB_NoHandler: this can't happen!\n" );
3046 break;
3049 GDI_HEAP_UNLOCK( (HBITMAP)res );
3050 return handled;
3053 /***********************************************************************
3054 * X11DRV_DIB_UpdateDIBSection
3056 void X11DRV_DIB_UpdateDIBSection(DC *dc, BOOL toDIB)
3058 BITMAPOBJ *bmp;
3060 /* Ensure this is a Compatible DC that has a DIB section selected */
3062 if (!dc) return;
3063 if (!(dc->w.flags & DC_MEMORY)) return;
3065 bmp = (BITMAPOBJ *)GDI_GetObjPtr( dc->w.hBitmap, BITMAP_MAGIC );
3066 if (!bmp) return;
3068 if (!bmp->dib)
3070 GDI_HEAP_UNLOCK(dc->w.hBitmap);
3071 return;
3074 if (!toDIB)
3076 /* Prepare for access to the DIB by GDI functions */
3078 switch (((X11DRV_DIBSECTION *) bmp->dib)->status)
3080 default:
3081 case X11DRV_DIB_NoHandler:
3082 X11DRV_DIB_DoUpdateDIBSection( bmp, FALSE );
3083 break;
3085 case X11DRV_DIB_GdiMod:
3086 TRACE("fromDIB called in status X11DRV_DIB_GdiMod\n" );
3087 /* nothing to do */
3088 break;
3090 case X11DRV_DIB_InSync:
3091 TRACE("fromDIB called in status X11DRV_DIB_InSync\n" );
3092 /* nothing to do */
3093 break;
3095 case X11DRV_DIB_AppMod:
3096 TRACE("fromDIB called in status X11DRV_DIB_AppMod\n" );
3097 X11DRV_DIB_DoUpdateDIBSection( bmp, FALSE );
3098 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
3099 ((X11DRV_DIBSECTION *) bmp->dib)->status = X11DRV_DIB_InSync;
3100 break;
3103 else
3105 /* Acknowledge write access to the DIB by GDI functions */
3107 switch (((X11DRV_DIBSECTION *) bmp->dib)->status)
3109 default:
3110 case X11DRV_DIB_NoHandler:
3111 X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
3112 break;
3114 case X11DRV_DIB_GdiMod:
3115 TRACE(" toDIB called in status X11DRV_DIB_GdiMod\n" );
3116 /* nothing to do */
3117 break;
3119 case X11DRV_DIB_InSync:
3120 TRACE(" toDIB called in status X11DRV_DIB_InSync\n" );
3121 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
3122 ((X11DRV_DIBSECTION *) bmp->dib)->status = X11DRV_DIB_GdiMod;
3123 break;
3125 case X11DRV_DIB_AppMod:
3126 FIXME(" toDIB called in status X11DRV_DIB_AppMod: "
3127 "this can't happen!\n" );
3128 break;
3132 GDI_HEAP_UNLOCK(dc->w.hBitmap);
3135 /***********************************************************************
3136 * X11DRV_DIB_CreateDIBSection16
3138 HBITMAP16 X11DRV_DIB_CreateDIBSection16(
3139 DC *dc, BITMAPINFO *bmi, UINT16 usage,
3140 SEGPTR *bits, HANDLE section,
3141 DWORD offset)
3143 HBITMAP res = X11DRV_DIB_CreateDIBSection(dc, bmi, usage, NULL,
3144 section, offset);
3145 if ( res )
3147 BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr(res, BITMAP_MAGIC);
3148 if ( bmp && bmp->dib )
3150 DIBSECTION *dib = bmp->dib;
3151 INT height = dib->dsBm.bmHeight >= 0 ?
3152 dib->dsBm.bmHeight : -dib->dsBm.bmHeight;
3153 INT size = dib->dsBmih.biSizeImage ?
3154 dib->dsBmih.biSizeImage : dib->dsBm.bmWidthBytes * height;
3155 if ( dib->dsBm.bmBits )
3157 ((X11DRV_DIBSECTION *) bmp->dib)->selector =
3158 SELECTOR_AllocBlock( dib->dsBm.bmBits, size,
3159 SEGMENT_DATA, FALSE, FALSE );
3161 TRACE("ptr = %p, size =%d, selector = %04x, segptr = %ld\n",
3162 dib->dsBm.bmBits, size, ((X11DRV_DIBSECTION *) bmp->dib)->selector,
3163 PTR_SEG_OFF_TO_SEGPTR(((X11DRV_DIBSECTION *) bmp->dib)->selector, 0));
3165 GDI_HEAP_UNLOCK( res );
3167 if ( bits )
3168 *bits = PTR_SEG_OFF_TO_SEGPTR( ((X11DRV_DIBSECTION *) bmp->dib)->selector, 0 );
3171 return res;
3174 /***********************************************************************
3175 * X11DRV_XShmErrorHandler
3178 static int XShmErrorHandler(Display *dpy, XErrorEvent *event)
3180 XShmErrorFlag = 1;
3181 return 0;
3184 /***********************************************************************
3185 * X11DRV_XShmCreateImage
3189 extern BOOL X11DRV_XShmCreateImage(XImage** image, int width, int height, int bpp,
3190 XShmSegmentInfo* shminfo)
3192 int (*WineXHandler)(Display *, XErrorEvent *);
3194 *image = TSXShmCreateImage(display, DefaultVisualOfScreen(X11DRV_GetXScreen()),
3195 bpp, ZPixmap, NULL, shminfo, width, height);
3196 if( *image != NULL )
3198 EnterCriticalSection( &X11DRV_CritSection );
3199 shminfo->shmid = shmget(IPC_PRIVATE, (*image)->bytes_per_line * height,
3200 IPC_CREAT|0700);
3201 if( shminfo->shmid != -1 )
3203 shminfo->shmaddr = (*image)->data = shmat(shminfo->shmid, 0, 0);
3204 if( shminfo->shmaddr != (char*)-1 )
3206 shminfo->readOnly = FALSE;
3207 if( TSXShmAttach( display, shminfo ) != 0)
3209 /* Reset the error flag */
3210 XShmErrorFlag = 0;
3211 WineXHandler = XSetErrorHandler(XShmErrorHandler);
3212 XSync( display, 0 );
3214 if (!XShmErrorFlag)
3216 XSetErrorHandler(WineXHandler);
3217 LeaveCriticalSection( &X11DRV_CritSection );
3219 return TRUE; /* Success! */
3221 /* An error occured */
3222 XShmErrorFlag = 0;
3223 XSetErrorHandler(WineXHandler);
3225 shmdt(shminfo->shmaddr);
3227 shmctl(shminfo->shmid, IPC_RMID, 0);
3229 XFlush(display);
3230 XDestroyImage(*image);
3231 LeaveCriticalSection( &X11DRV_CritSection );
3233 return FALSE;
3239 /***********************************************************************
3240 * X11DRV_DIB_CreateDIBSection
3242 HBITMAP X11DRV_DIB_CreateDIBSection(
3243 DC *dc, BITMAPINFO *bmi, UINT usage,
3244 LPVOID *bits, HANDLE section,
3245 DWORD offset)
3247 HBITMAP res = 0;
3248 BITMAPOBJ *bmp = NULL;
3249 X11DRV_DIBSECTION *dib = NULL;
3250 int *colorMap = NULL;
3251 int nColorMap;
3253 /* Fill BITMAP32 structure with DIB data */
3254 BITMAPINFOHEADER *bi = &bmi->bmiHeader;
3255 INT effHeight, totalSize;
3256 BITMAP bm;
3258 TRACE("format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
3259 bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
3260 bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
3262 effHeight = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
3263 bm.bmType = 0;
3264 bm.bmWidth = bi->biWidth;
3265 bm.bmHeight = effHeight;
3266 bm.bmWidthBytes = DIB_GetDIBWidthBytes(bm.bmWidth, bi->biBitCount);
3267 bm.bmPlanes = bi->biPlanes;
3268 bm.bmBitsPixel = bi->biBitCount;
3269 bm.bmBits = NULL;
3271 /* Get storage location for DIB bits */
3272 totalSize = bi->biSizeImage? bi->biSizeImage : bm.bmWidthBytes * effHeight;
3274 if (section)
3275 bm.bmBits = MapViewOfFile(section, FILE_MAP_ALL_ACCESS,
3276 0L, offset, totalSize);
3277 else
3278 bm.bmBits = VirtualAlloc(NULL, totalSize,
3279 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
3281 /* Create Color Map */
3282 if (bm.bmBits && bm.bmBitsPixel <= 8)
3283 colorMap = X11DRV_DIB_BuildColorMap( usage == DIB_PAL_COLORS? dc : NULL,
3284 usage, bm.bmBitsPixel, bmi, &nColorMap );
3286 /* Allocate Memory for DIB and fill structure */
3287 if (bm.bmBits)
3288 dib = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(X11DRV_DIBSECTION));
3289 if (dib)
3291 dib->dibSection.dsBm = bm;
3292 dib->dibSection.dsBmih = *bi;
3294 /* Set dsBitfields values */
3295 if ( usage == DIB_PAL_COLORS || bi->biBitCount <= 8)
3297 dib->dibSection.dsBitfields[0] = dib->dibSection.dsBitfields[1] = dib->dibSection.dsBitfields[2] = 0;
3299 else switch( bi->biBitCount )
3301 case 16:
3302 dib->dibSection.dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors : 0x7c00;
3303 dib->dibSection.dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0x03e0;
3304 dib->dibSection.dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0x001f;
3305 break;
3307 case 24:
3308 dib->dibSection.dsBitfields[0] = 0xff;
3309 dib->dibSection.dsBitfields[1] = 0xff00;
3310 dib->dibSection.dsBitfields[2] = 0xff0000;
3311 break;
3313 case 32:
3314 dib->dibSection.dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors : 0xff;
3315 dib->dibSection.dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0xff00;
3316 dib->dibSection.dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0xff0000;
3317 break;
3319 dib->dibSection.dshSection = section;
3320 dib->dibSection.dsOffset = offset;
3322 dib->status = X11DRV_DIB_NoHandler;
3323 dib->selector = 0;
3325 dib->nColorMap = nColorMap;
3326 dib->colorMap = colorMap;
3329 /* Create Device Dependent Bitmap and add DIB pointer */
3330 if (dib)
3332 res = CreateDIBitmap(dc->hSelf, bi, 0, NULL, bmi, usage);
3333 if (res)
3335 bmp = (BITMAPOBJ *) GDI_GetObjPtr(res, BITMAP_MAGIC);
3336 if (bmp)
3338 bmp->dib = (DIBSECTION *) dib;
3339 /* HACK for now */
3340 if(!bmp->DDBitmap)
3341 X11DRV_CreateBitmap(res);
3346 /* Create XImage */
3347 if (dib && bmp)
3349 if (TSXShmQueryExtension(display) &&
3350 X11DRV_XShmCreateImage( &dib->image, bm.bmWidth, effHeight,
3351 bmp->bitmap.bmBitsPixel, &dib->shminfo ) )
3353 ; /* Created Image */
3354 } else {
3355 XCREATEIMAGE( dib->image, bm.bmWidth, effHeight, bmp->bitmap.bmBitsPixel );
3356 dib->shminfo.shmid = -1;
3360 /* Clean up in case of errors */
3361 if (!res || !bmp || !dib || !bm.bmBits || (bm.bmBitsPixel <= 8 && !colorMap))
3363 TRACE("got an error res=%08x, bmp=%p, dib=%p, bm.bmBits=%p\n",
3364 res, bmp, dib, bm.bmBits);
3365 if (bm.bmBits)
3367 if (section)
3368 UnmapViewOfFile(bm.bmBits), bm.bmBits = NULL;
3369 else
3370 VirtualFree(bm.bmBits, 0L, MEM_RELEASE), bm.bmBits = NULL;
3373 if (dib && dib->image) { XDestroyImage(dib->image); dib->image = NULL; }
3374 if (colorMap) { HeapFree(GetProcessHeap(), 0, colorMap); colorMap = NULL; }
3375 if (dib) { HeapFree(GetProcessHeap(), 0, dib); dib = NULL; }
3376 if (res) { DeleteObject(res); res = 0; }
3379 /* Install fault handler, if possible */
3380 if (bm.bmBits)
3382 if (VIRTUAL_SetFaultHandler(bm.bmBits, X11DRV_DIB_FaultHandler, (LPVOID)res))
3384 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
3385 if (dib) dib->status = X11DRV_DIB_InSync;
3389 /* Return BITMAP handle and storage location */
3390 if (res) GDI_HEAP_UNLOCK(res);
3391 if (bm.bmBits && bits) *bits = bm.bmBits;
3392 return res;
3395 /***********************************************************************
3396 * X11DRV_DIB_DeleteDIBSection
3398 void X11DRV_DIB_DeleteDIBSection(BITMAPOBJ *bmp)
3400 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
3402 if (dib->image)
3404 if (dib->shminfo.shmid != -1)
3406 TSXShmDetach (display, &(dib->shminfo));
3407 XDestroyImage (dib->image);
3408 shmdt (dib->shminfo.shmaddr);
3409 shmctl (dib->shminfo.shmid, IPC_RMID, 0);
3410 dib->shminfo.shmid = -1;
3412 else
3413 XDestroyImage( dib->image );
3416 if (dib->colorMap)
3417 HeapFree(GetProcessHeap(), 0, dib->colorMap);
3419 if (dib->selector)
3421 WORD count = (GET_SEL_LIMIT( dib->selector ) >> 16) + 1;
3422 SELECTOR_FreeBlock( dib->selector, count );
3427 /**************************************************************************
3428 * X11DRV_DIB_CreateDIBFromPixmap
3430 * Allocates a packed DIB and copies the Pixmap data into it.
3431 * If bDeletePixmap is TRUE, the Pixmap passed in is deleted after the conversion.
3433 HGLOBAL X11DRV_DIB_CreateDIBFromPixmap(Pixmap pixmap, HDC hdc, BOOL bDeletePixmap)
3435 HBITMAP hBmp = 0;
3436 BITMAPOBJ *pBmp = NULL;
3437 HGLOBAL hPackedDIB = 0;
3439 /* Allocates an HBITMAP which references the Pixmap passed to us */
3440 hBmp = X11DRV_BITMAP_CreateBitmapHeaderFromPixmap(pixmap);
3441 if (!hBmp)
3443 TRACE("\tCould not create bitmap header for Pixmap\n");
3444 goto END;
3448 * Create a packed DIB from the Pixmap wrapper bitmap created above.
3449 * A packed DIB contains a BITMAPINFO structure followed immediately by
3450 * an optional color palette and the pixel data.
3452 hPackedDIB = DIB_CreateDIBFromBitmap(hdc, hBmp);
3454 /* Get a pointer to the BITMAPOBJ structure */
3455 pBmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
3457 /* We can now get rid of the HBITMAP wrapper we created earlier.
3458 * Note: Simply calling DeleteObject will free the embedded Pixmap as well.
3460 if (!bDeletePixmap)
3462 /* Manually free the DDBitmap internals to prevent the Pixmap
3463 * from being deleted by DeleteObject.
3465 HeapFree( GetProcessHeap(), 0, pBmp->DDBitmap->physBitmap );
3466 HeapFree( GetProcessHeap(), 0, pBmp->DDBitmap );
3467 pBmp->DDBitmap = NULL;
3469 DeleteObject(hBmp);
3471 END:
3472 TRACE("\tReturning packed DIB %x\n", hPackedDIB);
3473 return hPackedDIB;
3477 /**************************************************************************
3478 * X11DRV_DIB_CreatePixmapFromDIB
3480 * Creates a Pixmap from a packed DIB
3482 Pixmap X11DRV_DIB_CreatePixmapFromDIB( HGLOBAL hPackedDIB, HDC hdc )
3484 Pixmap pixmap = None;
3485 HBITMAP hBmp = 0;
3486 BITMAPOBJ *pBmp = NULL;
3487 LPBYTE pPackedDIB = NULL;
3488 LPBITMAPINFO pbmi = NULL;
3489 LPBITMAPINFOHEADER pbmiHeader = NULL;
3490 LPBYTE pbits = NULL;
3492 /* Get a pointer to the packed DIB's data */
3493 pPackedDIB = (LPBYTE)GlobalLock(hPackedDIB);
3494 pbmiHeader = (LPBITMAPINFOHEADER)pPackedDIB;
3495 pbmi = (LPBITMAPINFO)pPackedDIB;
3496 pbits = (LPBYTE)(pPackedDIB
3497 + DIB_BitmapInfoSize( (LPBITMAPINFO)pbmiHeader, DIB_RGB_COLORS ));
3499 /* Create a DDB from the DIB */
3501 hBmp = CreateDIBitmap(hdc,
3502 pbmiHeader,
3503 CBM_INIT,
3504 (LPVOID)pbits,
3505 pbmi,
3506 DIB_RGB_COLORS);
3508 GlobalUnlock(hPackedDIB);
3510 TRACE("CreateDIBitmap returned %x\n", hBmp);
3512 /* Retrieve the internal Pixmap from the DDB */
3514 pBmp = (BITMAPOBJ *) GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
3516 if (pBmp->DDBitmap && pBmp->DDBitmap->physBitmap)
3518 pixmap = ((X11DRV_PHYSBITMAP *)(pBmp->DDBitmap->physBitmap))->pixmap;
3519 if (!pixmap)
3520 TRACE("NULL Pixmap in DDBitmap->physBitmap!\n");
3522 /* Manually free the BITMAPOBJ internals so that we can steal its pixmap */
3523 HeapFree( GetProcessHeap(), 0, pBmp->DDBitmap->physBitmap );
3524 HeapFree( GetProcessHeap(), 0, pBmp->DDBitmap );
3525 pBmp->DDBitmap = NULL; /* Its not a DDB anymore */
3528 /* Delete the DDB we created earlier now that we have stolen its pixmap */
3529 DeleteObject(hBmp);
3531 TRACE("\tReturning Pixmap %ld\n", pixmap);
3532 return pixmap;
3535 #endif /* !defined(X_DISPLAY_MISSING) */