Release 20000326.
[wine/gsoc-2012-control.git] / graphics / x11drv / dib.c
blob7d76ffc8527a1b9bf78db878428fe6abb156ff0a
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 <stdlib.h>
25 #include "windef.h"
26 #include "bitmap.h"
27 #include "x11drv.h"
28 #include "debugtools.h"
29 #include "dc.h"
30 #include "color.h"
31 #include "callback.h"
32 #include "selectors.h"
33 #include "global.h"
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, X11DRV_GetVisual(),
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:
1701 if (bmpImage->bits_per_pixel == 24) {
1702 int tocopy = linebytes;
1703 BYTE *dstpixel;
1704 BYTE *ptr = (BYTE *)(srcbits+left*3);
1706 if (tocopy < 0 ) tocopy = -tocopy;
1707 dstpixel = bmpImage->data + lines*tocopy + left*3;
1708 for(h = lines ; h-- ; ) {
1709 dstpixel-=tocopy;
1710 memcpy(dstpixel,ptr,tocopy);
1711 ptr +=linebytes;
1713 break;
1716 case 32:
1718 if( bmpImage->blue_mask == 0xff && bmpImage->red_mask == 0xff0000 ) /* packed BGR to unpacked BGR */
1720 DWORD *dstpixel, val, buf;
1721 DWORD *ptr = (DWORD *)(srcbits + left*3);
1722 BYTE *bits;
1723 int div = dstwidth % 4;
1724 int divk;
1726 for(h = lines - 1; h >= 0; h--)
1728 dstpixel = (DWORD *) (bmpImage->data + h*bmpImage->bytes_per_line + left*4);
1730 for (x = 0; x < dstwidth/4; x++) { /* do 3 dwords source, 4 dwords dest at a time */
1731 buf = *ptr++;
1732 *dstpixel++ = buf&0x00ffffff; /* b1, g1, r1 */
1733 val = (buf >> 24); /* b2 */
1734 buf = *ptr++;
1735 *dstpixel++ = (val | (buf<<8)) &0x00ffffff; /* g2, r2 */
1736 val = (buf >> 16); /* b3, g3 */
1737 buf = *ptr++;
1738 *dstpixel++ = (val | (buf<<16)) &0x00ffffff; /* r3 */
1739 *dstpixel++ = (buf >> 8); /* b4, g4, r4 */
1741 for ( divk=div, bits=(BYTE*)ptr; divk>0; divk--, bits+=3 ) /* do remainder */
1743 *dstpixel++ = *(DWORD*)bits & 0x00ffffff; /* b, g, r */
1745 ptr = (DWORD*)((srcbits+=linebytes)+left*3);
1748 else if( bmpImage->blue_mask == 0xff0000 && bmpImage->red_mask == 0xff ) /* packed BGR to unpacked RGB */
1750 DWORD *dstpixel, val, buf;
1751 DWORD *ptr = (DWORD *)(srcbits + left*3);
1752 BYTE *bits;
1753 int div = dstwidth % 4;
1754 int divk;
1756 for(h = lines - 1; h >= 0; h--)
1758 dstpixel = (DWORD *) (bmpImage->data + h*bmpImage->bytes_per_line + left*4);
1760 for (x = 0; x < dstwidth/4; x++) { /* do 3 dwords source, 4 dwords dest at a time */
1761 buf = *ptr++;
1762 *dstpixel++ = ((buf&0xff)<<16) | (buf&0xff00) | ((buf&0xff0000)>>16); /* b1, g1, r1 */
1763 val = ((buf&0xff000000)>>8); /* b2 */
1764 buf = *ptr++;
1765 *dstpixel++ = val | ((buf&0xff)<<8) | ((buf&0xff00)>>8); /* g2, r2 */
1766 val = (buf&0xff0000) | ((buf&0xff000000)>>16); /* b3, g3 */
1767 buf = *ptr++;
1768 *dstpixel++ = val | (buf&0xff); /* r3 */
1769 *dstpixel++ = ((buf&0xff00)<<8) | ((buf&0xff0000)>>8) | (buf>>24); /* b4, g4, r4 */
1771 for ( divk=div, bits=(BYTE*)ptr; divk>0; divk--, bits+=3 ) /* do remainder */
1773 buf = *(DWORD*)bits;
1774 *dstpixel++ = ((buf&0xff)<<16) | (buf&0xff00) | ((buf&0xff0000)>>16); /* b, g, r */
1776 ptr = (DWORD*)((srcbits+=linebytes)+left*3);
1779 else
1780 goto notsupported;
1782 break;
1784 case 15:
1786 if( bmpImage->blue_mask == 0x7c00 && bmpImage->red_mask == 0x1f ) /* BGR888 to RGB555 */
1788 DWORD *ptr = (DWORD *)(srcbits + left*3), val;
1789 LPBYTE bits;
1790 LPWORD dstpixel;
1791 int div = dstwidth % 4;
1792 int divk;
1794 for (h = lines - 1; h >= 0; h--) { /* Do 4 pixels at a time */
1795 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1796 for (x = 0; x < dstwidth/4; x++) {
1797 *dstpixel++ = (WORD)((((val = *ptr++) << 7) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 19) & 0x1f));
1798 *dstpixel++ = (WORD)(((val >> 17) & 0x7c00) | (((val = *ptr++) << 2) & 0x03e0) | ((val >> 11) & 0x1f));
1799 *dstpixel++ = (WORD)(((val >> 9) & 0x07c00) | ((val >> 22) & 0x03e0) | (((val = *ptr++) >> 3) & 0x1f));
1800 *dstpixel++ = (WORD)(((val >> 1) & 0x07c00) | ((val >> 14) & 0x03e0) | ((val >> 27) & 0x1f));
1802 for (bits = (LPBYTE)ptr, divk=div; divk > 0; divk--, bits+=3) /* dstwidth not divisible by 4? */
1803 *dstpixel++ = (((WORD)bits[0] << 7) & 0x07c00) |
1804 (((WORD)bits[1] << 2) & 0x03e0) |
1805 (((WORD)bits[2] >> 3) & 0x001f);
1806 ptr = (DWORD *)((srcbits += linebytes) + left * 3);
1809 else if( bmpImage->blue_mask == 0x1f && bmpImage->red_mask == 0x7c00 ) /* BGR888 to BGR555 */
1811 DWORD *ptr = (DWORD *)(srcbits + left*3), val;
1812 LPBYTE bits;
1813 LPWORD dstpixel;
1814 int div = dstwidth % 4;
1815 int divk;
1817 for (h = lines - 1; h >= 0; h--) { /* Do 4 pixels at a time */
1818 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1819 for (x = 0; x < dstwidth/4; x++) {
1820 *dstpixel++ = (WORD)((((val = *ptr++) >> 3) & 0x1f) | ((val >> 6) & 0x03e0) | ((val >> 9) & 0x7c00));
1821 *dstpixel++ = (WORD)(((val >> 27) & 0x1f) | (((val = *ptr++) << 2) & 0x03e0) | ((val >> 1) & 0x7c00));
1822 *dstpixel++ = (WORD)(((val >> 19) & 0x1f) | ((val >> 22) & 0x03e0) | (((val = *ptr++) << 7) & 0x7c00));
1823 *dstpixel++ = (WORD)(((val >> 11) & 0x1f) | ((val >> 14) & 0x03e0) | ((val >> 17) & 0x7c00));
1825 for (bits = (LPBYTE)ptr, divk=div; divk > 0; divk--, bits+=3) /* dstwidth not divisible by 4? */
1826 *dstpixel++ = (((WORD)bits[2] << 7) & 0x07c00) |
1827 (((WORD)bits[1] << 2) & 0x03e0) |
1828 (((WORD)bits[0] >> 3) & 0x001f);
1829 ptr = (DWORD *)((srcbits += linebytes) + left * 3);
1832 else
1833 goto notsupported;
1835 break;
1837 case 16:
1839 DWORD *ptr = (DWORD *)(srcbits + left*3), val;
1840 LPBYTE bits;
1841 LPWORD dstpixel;
1842 int div = dstwidth % 4;
1843 int divk;
1845 if( bmpImage->blue_mask == 0x001f && bmpImage->red_mask == 0xf800 ) /* BGR888 to BGR565 */
1847 for (h = lines - 1; h >= 0; h--) { /* Do 4 pixels at a time */
1848 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1849 for (x = 0; x < dstwidth/4; x++) {
1850 *dstpixel++ = (WORD)((((val = *ptr++) >> 3) & 0x1f) | ((val >> 5) & 0x07e0) | ((val >> 8) & 0xf800));
1851 *dstpixel++ = (WORD)(((val >> 27) & 0x1f) | (((val = *ptr++) << 3) & 0x07e0) | ((val) & 0xf800));
1852 *dstpixel++ = (WORD)(((val >> 19) & 0x1f) | ((val >> 21) & 0x07e0) | (((val = *ptr++) << 8) & 0xf800));
1853 *dstpixel++ = (WORD)(((val >> 11) & 0x1f) | ((val >> 13) & 0x07e0) | ((val >> 16) & 0xf800));
1855 for ( bits = (LPBYTE)ptr, divk=div; divk > 0; divk--, bits+=3) /* dstwidth is not divisible by 4? */
1856 *dstpixel++ = (((WORD)bits[2] << 8) & 0xf800) |
1857 (((WORD)bits[1] << 3) & 0x07e0) |
1858 (((WORD)bits[0] >> 3) & 0x001f);
1859 ptr = (DWORD *)((srcbits += linebytes) + left * 3);
1862 else if( bmpImage->blue_mask == 0xf800 && bmpImage->red_mask == 0x001f ) /* BGR888 to RGB565 */
1864 for (h = lines - 1; h >= 0; h--) { /* Do 4 pixels at a time */
1865 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1866 for (x = 0; x < dstwidth/4; x++) {
1867 *dstpixel++ = (WORD)((((val = *ptr++) << 8) & 0xf800) | ((val >> 5) & 0x07e0) | ((val >> 19) & 0x1f));
1868 *dstpixel++ = (WORD)(((val >> 16) & 0xf800) | (((val = *ptr++) << 3) & 0x07e0) | ((val >> 11) & 0x1f));
1869 *dstpixel++ = (WORD)(((val >> 8) & 0xf800) | ((val >> 21) & 0x07e0) | (((val = *ptr++) >> 3) & 0x1f));
1870 *dstpixel++ = (WORD)((val & 0xf800) | ((val >> 13) & 0x07e0) | ((val >> 27) & 0x1f));
1872 for ( bits = (LPBYTE)ptr, divk=div; divk > 0; divk--, bits+=3) /* dstwidth is not divisible by 4? */
1873 *dstpixel++ = (((WORD)bits[0] << 8) & 0xf800) |
1874 (((WORD)bits[1] << 3) & 0x07e0) |
1875 (((WORD)bits[2] >> 3) & 0x001f);
1876 ptr = (DWORD *)((srcbits += linebytes) + left * 3);
1879 else
1880 goto notsupported;
1882 break;
1884 case 1:
1885 case 4:
1886 case 8:
1888 LPBYTE bits = (LPBYTE)srcbits + left*3;
1890 for (h = lines - 1; h >= 0; h--) {
1891 for (x = left; x < dstwidth+left; x++, bits+=3)
1892 XPutPixel( bmpImage, x, h,
1893 X11DRV_PALETTE_ToPhysical(dc, RGB(bits[2], bits[1], bits[0])));
1894 bits = (LPBYTE)(srcbits += linebytes) + left * 3;
1897 break;
1899 default:
1900 notsupported:
1901 FIXME("from 24 bit DIB to %d bit bitmap with mask R,G,B %x,%x,%x\n",
1902 bmpImage->bits_per_pixel, (int)bmpImage->red_mask,
1903 (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
1904 break;
1909 /***********************************************************************
1910 * X11DRV_DIB_GetImageBits_24
1912 * GetDIBits for an 24-bit deep DIB.
1914 static void X11DRV_DIB_GetImageBits_24( int lines, BYTE *dstbits,
1915 DWORD dstwidth, DWORD srcwidth,
1916 PALETTEENTRY *srccolors, XImage *bmpImage )
1918 DWORD x, val;
1919 int h;
1921 /* align to 32 bit */
1922 DWORD linebytes = (dstwidth * 3 + 3) & ~3;
1924 if (lines < 0 )
1926 lines = -lines;
1927 dstbits = dstbits + ( linebytes * (lines-1) );
1928 linebytes = -linebytes;
1931 switch ( bmpImage->depth )
1933 case 24:
1935 if (bmpImage->bits_per_pixel == 24) {
1936 int tocopy = linebytes;
1937 BYTE *srcpixel;
1938 BYTE *ptr = (LPBYTE)dstbits;
1940 if (tocopy < 0 ) tocopy = -tocopy;
1941 srcpixel = bmpImage->data + lines*tocopy;
1942 for(h = lines ; h-- ; ) {
1943 srcpixel-=tocopy;
1944 memcpy(ptr,srcpixel,tocopy);
1945 ptr = (LPBYTE)(dstbits+=linebytes);
1947 break;
1950 case 32:
1952 DWORD *srcpixel, buf;
1953 LPBYTE bits;
1954 DWORD *ptr=(DWORD *)dstbits;
1955 int quotient = dstwidth / 4;
1956 int remainder = dstwidth % 4;
1957 int remk;
1959 /* ==== 24/32 BGR bitmap to 24 BGR dib==== */
1960 if( bmpImage->blue_mask == 0xff && bmpImage->red_mask == 0xff0000 )
1962 for(h = lines - 1; h >= 0; h--)
1964 srcpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line);
1966 for (x = 0; x < quotient; x++) { /* do 4 dwords source, 3 dwords dest at a time*/
1967 buf = ((*srcpixel++)&0x00ffffff); /* b1, g1, r1*/
1968 *ptr++ = buf | ((*srcpixel)<<24); /* b2 */
1969 buf = ((*srcpixel++>>8)&0x0000ffff); /* g2, r2 */
1970 *ptr++ = buf | ((*srcpixel)<<16); /* b3, g3 */
1971 buf = ((*srcpixel++>>16)&0x000000ff); /* r3 */
1972 *ptr++ = buf | ((*srcpixel++)<<8); /* b4, g4, r4 */
1974 for ( remk=remainder, bits=(BYTE*)ptr; remk>0; remk--, bits+=3 ) /* do remainder */
1976 buf=*srcpixel++;
1977 *(WORD*)bits = buf; /* b, g */
1978 *(bits+2) = buf>>16; /* r */
1980 ptr = (DWORD*)(dstbits+=linebytes);
1984 /* ==== 24/32 RGB bitmap to 24 BGR dib ==== */
1985 else if( bmpImage->blue_mask == 0xff0000 && bmpImage->red_mask == 0xff )
1987 for(h = lines - 1; h >= 0; h--)
1989 srcpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line);
1991 for (x = 0; x < quotient; x++) { /* do 4 dwords source, 3 dwords dest at a time */
1992 buf = *srcpixel++;
1993 val = ((buf&0xff0000)>>16) | (buf&0xff00) | ((buf&0xff)<<16); /* b1, g1, r1 */
1994 buf = *srcpixel++;
1995 *ptr++ = val | ((buf&0xff0000)<<8); /* b2 */
1996 val = ((buf&0xff00)>>8) | ((buf&0xff)<<8); /* g2, r2 */
1997 buf = *srcpixel++;
1998 *ptr++ = val | (buf&0xff0000) | ((buf&0xff00)<<16); /* b3, g3 */
1999 val = (buf&0xff); /* r3 */
2000 buf = *srcpixel++;
2001 *ptr++ = val | ((buf&0xff0000)>>8) | ((buf&0xff00)<<8) | (buf<<24); /* b4, g4, r4 */
2003 for ( remk=remainder, bits=(BYTE*)ptr; remk>0; remk--, bits+=3 ) /* do remainder */
2005 buf=*srcpixel++;
2006 *(WORD*)bits = (buf&0xff00) | ((buf&0xff0000)>>16) ; /* b, g */
2007 *(bits+2) = buf; /* r */
2009 ptr = (DWORD*)(dstbits+=linebytes);
2012 else goto notsupported;
2014 break;
2016 case 15:
2018 LPWORD srcpixel;
2019 LPBYTE bits = dstbits;
2020 WORD val;
2022 /* ==== 555 BGR bitmap to 24 BGR dib ==== */
2023 if( bmpImage->blue_mask == 0x1f && bmpImage->red_mask == 0x7c00 )
2025 for (h = lines - 1; h >= 0; h--) {
2026 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2027 for (x = 0; x < srcwidth; x++, bits += 3) {
2028 val = *srcpixel++;
2029 bits[2] = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07)); /*Red*/
2030 bits[1] = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07)); /*Green*/
2031 bits[0] = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07)); /*Blue*/
2033 bits = (dstbits += linebytes);
2036 /* ==== 555 RGB bitmap to 24 RGB dib==== */
2037 else if( bmpImage->blue_mask == 0x7c00 && bmpImage->red_mask == 0x1f )
2039 for (h = lines - 1; h >= 0; h--) {
2040 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2041 for (x = 0; x < srcwidth; x++, bits += 3) {
2042 val = *srcpixel++;
2043 bits[0] = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07)); /*Red*/
2044 bits[1] = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07)); /*Green*/
2045 bits[2] = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07)); /*Blue*/
2047 bits = (dstbits += linebytes);
2050 else goto notsupported;
2052 break;
2054 case 16:
2056 LPWORD srcpixel;
2057 LPBYTE bits = dstbits;
2058 WORD val;
2060 /* ==== 565 BGR bitmap to 24 BGR dib ==== */
2061 if( bmpImage->blue_mask == 0x1f && bmpImage->red_mask == 0xf800 )
2063 for (h = lines - 1; h >= 0; h--) {
2064 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2065 for (x = 0; x < srcwidth; x++, bits += 3) {
2066 val = *srcpixel++;
2067 bits[2] = (BYTE)(((val >> 8) & 0xf8) | ((val >> 13) & 0x07)); /*Red*/
2068 bits[1] = (BYTE)(((val >> 3) & 0xfc) | ((val >> 9) & 0x03)); /*Green*/
2069 bits[0] = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07)); /*Blue*/
2071 bits = (dstbits += linebytes);
2074 /* ==== 565 RGB bitmap to 24 BGR dib ==== */
2075 else if( bmpImage->blue_mask == 0xf800 && bmpImage->red_mask == 0x1f )
2077 for (h = lines - 1; h >= 0; h--) {
2078 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2079 for (x = 0; x < srcwidth; x++, bits += 3) {
2080 val = *srcpixel++;
2081 bits[0] = (BYTE)(((val >> 8) & 0xf8) | ((val >> 13) & 0x07)); /*Red*/
2082 bits[1] = (BYTE)(((val >> 3) & 0xfc) | ((val >> 9) & 0x03)); /*Green*/
2083 bits[2] = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07)); /*Blue*/
2085 bits = (dstbits += linebytes);
2088 else goto notsupported;
2090 break;
2092 case 1:
2093 /* ==== monochrome bitmap to 24 BGR dib ==== */
2094 case 4:
2095 /* ==== 4 colormap bitmap to 24 BGR dib ==== */
2096 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
2098 LPBYTE bits = dstbits;
2099 PALETTEENTRY val;
2101 for (h = lines - 1; h >= 0; h--) {
2102 for (x = 0; x < dstwidth; x++) {
2103 val = srccolors[XGetPixel(bmpImage, x, h)];
2104 *bits++ = val.peBlue;
2105 *bits++ = val.peGreen;
2106 *bits++ = val.peRed;
2108 bits = (dstbits += linebytes);
2111 else goto notsupported;
2113 break;
2115 case 8:
2116 /* ==== 8 colormap bitmap to 24 BGR dib ==== */
2117 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask == 0 && srccolors)
2119 BYTE *srcpixel;
2120 LPBYTE bits = dstbits;
2121 PALETTEENTRY val;
2123 for (h = lines - 1; h >= 0; h--) {
2124 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
2125 for (x = 0; x < dstwidth; x++ ) {
2126 val = srccolors[(int)*srcpixel++];
2127 *bits++ = val.peBlue; /*Blue*/
2128 *bits++ = val.peGreen; /*Green*/
2129 *bits++ = val.peRed; /*Red*/
2131 bits = (dstbits += linebytes);
2134 else goto notsupported;
2136 break;
2138 default:
2139 notsupported:
2141 LPBYTE bits = dstbits;
2143 FIXME("from %d bit bitmap with mask R,G,B %x,%x,%x to 24 bit DIB\n",
2144 bmpImage->depth, (int)bmpImage->red_mask,
2145 (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
2146 for (h = lines - 1; h >= 0; h--)
2148 for (x = 0; x < dstwidth; x++, bits += 3)
2150 COLORREF pixel = X11DRV_PALETTE_ToLogical( XGetPixel( bmpImage, x, h ) );
2151 bits[0] = GetBValue(pixel);
2152 bits[1] = GetGValue(pixel);
2153 bits[2] = GetRValue(pixel);
2155 bits = (dstbits += linebytes);
2158 break;
2163 /***********************************************************************
2164 * X11DRV_DIB_SetImageBits_32
2166 * SetDIBits for a 32-bit deep DIB.
2168 static void X11DRV_DIB_SetImageBits_32( int lines, const BYTE *srcbits,
2169 DWORD srcwidth, DWORD dstwidth, int left,
2170 DC *dc, XImage *bmpImage )
2172 DWORD x, *ptr;
2173 int h;
2175 DWORD linebytes = (srcwidth * 4);
2177 if (lines < 0 )
2179 lines = -lines;
2180 srcbits = srcbits + ( linebytes * (lines-1) );
2181 linebytes = -linebytes;
2184 ptr = (DWORD *) srcbits + left;
2186 switch ( bmpImage->depth )
2188 case 24:
2189 case 32:
2190 /* ==== 32 BGR dib to 24/32 BGR bitmap ==== */
2191 if (bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff) {
2192 for (h = lines - 1; h >= 0; h--, srcbits+=linebytes) {
2193 memcpy( bmpImage->data + h * bmpImage->bytes_per_line, srcbits + left*4, dstwidth*4 );
2197 /* ==== 32 BGR dib to 24/32 RGB bitmap ==== */
2198 else if (bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000)
2200 DWORD *dstpixel;
2202 for (h = lines - 1; h >= 0; h--) {
2203 dstpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line);
2204 for (x = 0; x < dstwidth; x++, ptr++) {
2205 *dstpixel++ = ((*ptr << 16) & 0xff0000) | (*ptr & 0xff00) | ((*ptr >> 16) & 0xff);
2207 ptr = (DWORD *) (srcbits += linebytes) + left;
2210 else goto notsupported;
2212 break;
2214 case 15:
2215 /* ==== 32 BGR dib to 555 BGR bitmap ==== */
2216 if (bmpImage->red_mask == 0x7c00 && bmpImage->blue_mask == 0x001f)
2218 LPWORD dstpixel;
2220 for (h = lines - 1; h >= 0; h--) {
2221 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2222 for (x = 0; x < dstwidth; x++, ptr++) {
2223 *dstpixel++ = (WORD) (((*ptr >> 9) & 0x7c00) | ((*ptr >> 6) & 0x03e0) | ((*ptr >> 3) & 0x001f));
2225 ptr = (DWORD *) (srcbits += linebytes) + left;
2228 /* ==== 32 BGR dib to 555 RGB bitmap ==== */
2229 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0x7c00)
2231 LPWORD dstpixel;
2233 for (h = lines - 1; h >= 0; h--) {
2234 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2235 for (x = 0; x < dstwidth; x++, ptr++) {
2236 *dstpixel++ = (WORD) (((*ptr << 7) & 0x7c00) | ((*ptr >> 6) & 0x03e0) | ((*ptr >> 19) & 0x001f));
2238 ptr = (DWORD *) (srcbits += linebytes) + left;
2241 else goto notsupported;
2243 break;
2245 case 16:
2246 /* ==== 32 BGR dib to 565 BGR bitmap ==== */
2247 if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f)
2249 LPWORD dstpixel;
2251 for (h = lines - 1; h >= 0; h--) {
2252 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2253 for (x = 0; x < dstwidth; x++, ptr++) {
2254 *dstpixel++ = (WORD) (((*ptr >> 8) & 0xf800) | ((*ptr >> 5) & 0x07e0) | ((*ptr >> 3) & 0x001f));
2256 ptr = (DWORD *) (srcbits += linebytes) + left;
2259 /* ==== 32 BGR dib to 565 RGB bitmap ==== */
2260 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0xf800)
2262 LPWORD dstpixel;
2264 for (h = lines - 1; h >= 0; h--) {
2265 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2266 for (x = 0; x < dstwidth; x++, ptr++) {
2267 *dstpixel++ = (WORD) (((*ptr << 8) & 0xf800) | ((*ptr >> 5) & 0x07e0) | ((*ptr >> 19) & 0x001f));
2269 ptr = (DWORD *) (srcbits += linebytes) + left;
2272 else goto notsupported;
2274 break;
2276 case 1:
2277 case 4:
2278 case 8:
2280 LPBYTE bits = (LPBYTE)srcbits + left*4;
2282 for (h = lines - 1; h >= 0; h--) {
2283 for (x = left; x < dstwidth+left; x++, bits += 4)
2284 XPutPixel( bmpImage, x, h,
2285 X11DRV_PALETTE_ToPhysical(dc, RGB( bits[2], bits[1], *bits )));
2286 bits = (LPBYTE)(srcbits += linebytes) + left * 4;
2289 break;
2291 default:
2292 notsupported:
2293 FIXME("32 bit DIB %d bit bitmap\n", bmpImage->bits_per_pixel);
2294 break;
2299 /***********************************************************************
2300 * X11DRV_DIB_GetImageBits_32
2302 * GetDIBits for an 32-bit deep DIB.
2304 static void X11DRV_DIB_GetImageBits_32( int lines, BYTE *dstbits,
2305 DWORD dstwidth, DWORD srcwidth,
2306 PALETTEENTRY *srccolors, XImage *bmpImage )
2308 DWORD x;
2309 int h;
2310 BYTE *bits;
2312 /* align to 32 bit */
2313 DWORD linebytes = (srcwidth * 4);
2314 DWORD copybytes = linebytes;
2316 if (lines < 0 )
2318 lines = -lines;
2319 dstbits = dstbits + ( linebytes * (lines-1) );
2320 linebytes = -linebytes;
2323 bits = dstbits;
2325 switch ( bmpImage->depth )
2327 case 24:
2328 case 32:
2329 /* ==== 24/32 BGR bitmap to 32 BGR dib ==== */
2330 if ( bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff )
2331 for (h = lines - 1; h >= 0; h--, dstbits+=linebytes)
2332 memcpy( dstbits, bmpImage->data + h*bmpImage->bytes_per_line, copybytes );
2334 /* ==== 24/32 RGB bitmap to 32 BGR dib ==== */
2335 else if ( bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000 )
2337 LPBYTE srcbits;
2339 for (h = lines - 1; h >= 0; h--) {
2340 srcbits = bmpImage->data + h * bmpImage->bytes_per_line;
2341 for (x = 0; x < dstwidth; x++, bits+=4, srcbits+=2) {
2342 *(bits + 2) = *srcbits++;
2343 *(bits + 1) = *srcbits++;
2344 *bits = *srcbits;
2346 bits = (dstbits += linebytes);
2349 else goto notsupported;
2350 break;
2352 case 15:
2354 LPWORD srcpixel;
2355 WORD val;
2357 /* ==== 555 BGR bitmap to 32 BGR dib ==== */
2358 if (bmpImage->red_mask == 0x7c00 && bmpImage->blue_mask == 0x001f)
2360 for (h = lines - 1; h >= 0; h--) {
2361 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2362 for (x = 0; x < dstwidth; x++, bits+=2) {
2363 val = *srcpixel++;
2364 *bits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x03)); /*Blue*/
2365 *bits++ = (BYTE)(((val >> 2) & 0xfc) | ((val >> 8) & 0x03)); /*Green*/
2366 *bits = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07)); /*Red*/
2368 bits = (dstbits += linebytes);
2371 /* ==== 555 RGB bitmap to 32 BGR dib ==== */
2372 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0x7c00)
2374 for (h = lines - 1; h >= 0; h--) {
2375 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2376 for (x = 0; x < dstwidth; x++, bits+=2) {
2377 val = *srcpixel++;
2378 *bits++ = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07));/*Blue*/
2379 *bits++ = (BYTE)(((val >> 2) & 0xfc) | ((val >> 8) & 0x03)); /*Green*/
2380 *bits = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x03)); /*Red*/
2382 bits = (dstbits += linebytes);
2385 else goto notsupported;
2387 break;
2389 case 16:
2391 LPWORD srcpixel;
2392 WORD val;
2394 /* ==== 565 BGR bitmap to 32 BGR dib ==== */
2395 if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f)
2397 for (h = lines - 1; h >= 0; h--) {
2398 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2399 for (x = 0; x < srcwidth; x++, bits+=2) {
2400 val = *srcpixel++;
2401 *bits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x03)); /*Blue*/
2402 *bits++ = (BYTE)(((val >> 3) & 0xfc) | ((val >> 9) & 0x03)); /*Green*/
2403 *bits = (BYTE)(((val >> 8) & 0xf8) | ((val >> 13) & 0x07)); /*Red*/
2405 bits = (dstbits += linebytes);
2408 /* ==== 565 RGB bitmap to 32 BGR dib ==== */
2409 else if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f)
2411 for (h = lines - 1; h >= 0; h--) {
2412 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2413 for (x = 0; x < srcwidth; x++, bits+=2) {
2414 val = *srcpixel++;
2415 *bits++ = (BYTE)(((val >> 8) & 0xf8) | ((val >> 13) & 0x07));/*Blue*/
2416 *bits++ = (BYTE)(((val >> 3) & 0xfc) | ((val >> 9) & 0x03)); /*Green*/
2417 *bits = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x03)); /*Red*/
2419 bits = (dstbits += linebytes);
2422 else goto notsupported;
2424 break;
2426 case 1:
2427 /* ==== monochrome bitmap to 32 BGR dib ==== */
2428 case 4:
2429 /* ==== 4 colormap bitmap to 32 BGR dib ==== */
2430 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
2432 PALETTEENTRY val;
2434 for (h = lines - 1; h >= 0; h--) {
2435 for (x = 0; x < dstwidth; x++) {
2436 val = srccolors[XGetPixel(bmpImage, x, h)];
2437 *bits++ = val.peBlue;
2438 *bits++ = val.peGreen;
2439 *bits++ = val.peRed;
2440 *bits++ = 0;
2442 bits = (dstbits += linebytes);
2445 else goto notsupported;
2447 break;
2449 case 8:
2450 /* ==== 8 colormap bitmap to 32 BGR dib ==== */
2451 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
2453 BYTE *srcpixel;
2454 PALETTEENTRY val;
2456 for (h = lines - 1; h >= 0; h--) {
2457 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
2458 for (x = 0; x < dstwidth; x++) {
2459 val = srccolors[(int)*srcpixel++];
2460 *bits++ = val.peBlue; /*Blue*/
2461 *bits++ = val.peGreen; /*Green*/
2462 *bits++ = val.peRed; /*Red*/
2463 *bits++ = 0;
2465 bits = (dstbits += linebytes);
2468 else goto notsupported;
2469 break;
2471 default:
2472 notsupported:
2473 FIXME("from %d bit bitmap with mask R,G,B %x,%x,%x to 32 bit DIB\n",
2474 bmpImage->depth, (int)bmpImage->red_mask,
2475 (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
2476 for (h = lines - 1; h >= 0; h--)
2478 for (x = 0; x < dstwidth; x++, bits += 4)
2480 COLORREF pixel = X11DRV_PALETTE_ToLogical( XGetPixel( bmpImage, x, h ) );
2481 bits[0] = GetBValue(pixel);
2482 bits[1] = GetGValue(pixel);
2483 bits[2] = GetRValue(pixel);
2485 bits = (dstbits += linebytes);
2487 break;
2491 /***********************************************************************
2492 * X11DRV_DIB_SetImageBits
2494 * Transfer the bits to an X image.
2495 * Helper function for SetDIBits() and SetDIBitsToDevice().
2496 * The Xlib critical section must be entered before calling this function.
2498 int X11DRV_DIB_SetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
2500 int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
2501 XImage *bmpImage;
2503 if ( descr->dc && descr->dc->w.flags & DC_DIRTY )
2504 CLIPPING_UpdateGCRegion( descr->dc );
2506 if (descr->image)
2507 bmpImage = descr->image;
2508 else {
2509 bmpImage = XCreateImage( display, X11DRV_GetVisual(), descr->depth, ZPixmap, 0, NULL,
2510 descr->infoWidth, lines, 32, 0 );
2511 bmpImage->data = calloc( lines, bmpImage->bytes_per_line );
2512 if(bmpImage->data == NULL) {
2513 ERR("Out of memory!");
2514 XDestroyImage( bmpImage );
2515 return lines;
2519 /* Transfer the pixels */
2520 switch(descr->infoBpp)
2522 case 1:
2523 X11DRV_DIB_SetImageBits_1( descr->lines, descr->bits, descr->infoWidth,
2524 descr->width, descr->xSrc, (int *)(descr->colorMap),
2525 bmpImage );
2526 break;
2527 case 4:
2528 if (descr->compression) {
2529 XGetSubImage( display, descr->drawable, descr->xDest, descr->yDest,
2530 descr->width, descr->height, AllPlanes, ZPixmap,
2531 bmpImage, descr->xSrc, descr->ySrc );
2533 X11DRV_DIB_SetImageBits_RLE4( descr->lines, descr->bits,
2534 descr->infoWidth, descr->width,
2535 descr->xSrc, (int *)(descr->colorMap),
2536 bmpImage );
2537 } else
2538 X11DRV_DIB_SetImageBits_4( descr->lines, descr->bits,
2539 descr->infoWidth, descr->width,
2540 descr->xSrc, (int*)(descr->colorMap),
2541 bmpImage );
2542 break;
2543 case 8:
2544 if (descr->compression) {
2545 XGetSubImage( display, descr->drawable, descr->xDest, descr->yDest,
2546 descr->width, descr->height, AllPlanes, ZPixmap,
2547 bmpImage, descr->xSrc, descr->ySrc );
2548 X11DRV_DIB_SetImageBits_RLE8( descr->lines, descr->bits,
2549 descr->infoWidth, descr->width,
2550 descr->xSrc, (int *)(descr->colorMap),
2551 bmpImage );
2552 } else
2553 X11DRV_DIB_SetImageBits_8( descr->lines, descr->bits,
2554 descr->infoWidth, descr->width,
2555 descr->xSrc, (int *)(descr->colorMap),
2556 bmpImage );
2557 break;
2558 case 15:
2559 case 16:
2560 X11DRV_DIB_SetImageBits_16( descr->lines, descr->bits,
2561 descr->infoWidth, descr->width,
2562 descr->xSrc, descr->dc,
2563 descr->rMask, descr->gMask, descr->bMask,
2564 bmpImage);
2565 break;
2566 case 24:
2567 X11DRV_DIB_SetImageBits_24( descr->lines, descr->bits,
2568 descr->infoWidth, descr->width,
2569 descr->xSrc, descr->dc, bmpImage );
2570 break;
2571 case 32:
2572 X11DRV_DIB_SetImageBits_32( descr->lines, descr->bits,
2573 descr->infoWidth, descr->width,
2574 descr->xSrc, descr->dc,
2575 bmpImage);
2576 break;
2577 default:
2578 WARN("(%d): Invalid depth\n", descr->infoBpp );
2579 break;
2582 if (descr->useShm)
2584 XShmPutImage( display, descr->drawable, descr->gc, bmpImage,
2585 descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
2586 descr->width, descr->height, FALSE );
2587 XSync( display, 0 );
2589 else
2590 XPutImage( display, descr->drawable, descr->gc, bmpImage,
2591 descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
2592 descr->width, descr->height );
2594 if (!descr->image) XDestroyImage( bmpImage );
2595 return lines;
2598 /***********************************************************************
2599 * X11DRV_DIB_GetImageBits
2601 * Transfer the bits from an X image.
2602 * The Xlib critical section must be entered before calling this function.
2604 int X11DRV_DIB_GetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
2606 int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
2607 XImage *bmpImage;
2609 if (descr->image)
2610 bmpImage = descr->image;
2611 else {
2612 bmpImage = XCreateImage( display, X11DRV_GetVisual(), descr->depth, ZPixmap, 0, NULL,
2613 descr->infoWidth, lines, 32, 0 );
2614 bmpImage->data = calloc( lines, bmpImage->bytes_per_line );
2615 if(bmpImage->data == NULL) {
2616 ERR("Out of memory!");
2617 XDestroyImage( bmpImage );
2618 return lines;
2621 XGetSubImage( display, descr->drawable, descr->xDest, descr->yDest,
2622 descr->width, descr->height, AllPlanes, ZPixmap,
2623 bmpImage, descr->xSrc, descr->ySrc );
2625 /* Transfer the pixels */
2626 switch(descr->infoBpp)
2628 case 1:
2629 X11DRV_DIB_GetImageBits_1( descr->lines,(LPVOID)descr->bits,
2630 descr->infoWidth, descr->width,
2631 descr->colorMap, descr->palentry,
2632 bmpImage );
2633 break;
2635 case 4:
2636 if (descr->compression)
2637 FIXME("Compression not yet supported!\n");
2638 else
2639 X11DRV_DIB_GetImageBits_4( descr->lines,(LPVOID)descr->bits,
2640 descr->infoWidth, descr->width,
2641 descr->colorMap, descr->palentry,
2642 bmpImage );
2643 break;
2645 case 8:
2646 if (descr->compression)
2647 FIXME("Compression not yet supported!\n");
2648 else
2649 X11DRV_DIB_GetImageBits_8( descr->lines, (LPVOID)descr->bits,
2650 descr->infoWidth, descr->width,
2651 descr->colorMap, descr->palentry,
2652 bmpImage );
2653 break;
2654 case 15:
2655 case 16:
2656 X11DRV_DIB_GetImageBits_16( descr->lines, (LPVOID)descr->bits,
2657 descr->infoWidth,descr->width,
2658 descr->palentry, bmpImage );
2659 break;
2661 case 24:
2662 X11DRV_DIB_GetImageBits_24( descr->lines, (LPVOID)descr->bits,
2663 descr->infoWidth,descr->width,
2664 descr->palentry, bmpImage );
2665 break;
2667 case 32:
2668 X11DRV_DIB_GetImageBits_32( descr->lines, (LPVOID)descr->bits,
2669 descr->infoWidth, descr->width,
2670 descr->palentry, bmpImage );
2671 break;
2673 default:
2674 WARN("(%d): Invalid depth\n", descr->infoBpp );
2675 break;
2678 if (!descr->image) XDestroyImage( bmpImage );
2679 return lines;
2682 /*************************************************************************
2683 * X11DRV_SetDIBitsToDevice
2686 INT X11DRV_SetDIBitsToDevice( DC *dc, INT xDest, INT yDest, DWORD cx,
2687 DWORD cy, INT xSrc, INT ySrc,
2688 UINT startscan, UINT lines, LPCVOID bits,
2689 const BITMAPINFO *info, UINT coloruse )
2691 X11DRV_DIB_IMAGEBITS_DESCR descr;
2692 DWORD width, oldcy = cy;
2693 INT result;
2694 int height, tmpheight;
2695 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
2698 if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height,
2699 &descr.infoBpp, &descr.compression ) == -1)
2700 return 0;
2701 tmpheight = height;
2702 if (height < 0) height = -height;
2703 if (!lines || (startscan >= height)) return 0;
2704 if (startscan + lines > height) lines = height - startscan;
2705 if (ySrc < startscan) ySrc = startscan;
2706 else if (ySrc >= startscan + lines) return 0;
2707 if (xSrc >= width) return 0;
2708 if (ySrc + cy >= startscan + lines) cy = startscan + lines - ySrc;
2709 if (xSrc + cx >= width) cx = width - xSrc;
2710 if (!cx || !cy) return 0;
2712 X11DRV_SetupGCForText( dc ); /* To have the correct colors */
2713 TSXSetFunction(display, physDev->gc, X11DRV_XROPfunction[dc->w.ROPmode-1]);
2715 switch (descr.infoBpp)
2717 case 1:
2718 case 4:
2719 case 8:
2720 descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap(
2721 coloruse == DIB_PAL_COLORS ? dc : NULL, coloruse,
2722 dc->w.bitsPerPixel, info, &descr.nColorMap );
2723 if (!descr.colorMap) return 0;
2724 descr.rMask = descr.gMask = descr.bMask = 0;
2725 break;
2726 case 15:
2727 case 16:
2728 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
2729 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x03e0;
2730 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x001f;
2731 descr.colorMap = 0;
2732 break;
2734 case 24:
2735 descr.rMask = descr.gMask = descr.bMask = 0;
2736 descr.colorMap = 0;
2737 break;
2739 case 32:
2740 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
2741 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0xff00;
2742 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0xff;
2743 descr.colorMap = 0;
2744 break;
2747 descr.dc = dc;
2748 descr.bits = bits;
2749 descr.image = NULL;
2750 descr.palentry = NULL;
2751 descr.lines = tmpheight >= 0 ? lines : -lines;
2752 descr.infoWidth = width;
2753 descr.depth = dc->w.bitsPerPixel;
2754 descr.drawable = physDev->drawable;
2755 descr.gc = physDev->gc;
2756 descr.xSrc = xSrc;
2757 descr.ySrc = tmpheight >= 0 ? lines-(ySrc-startscan)-cy+(oldcy-cy)
2758 : ySrc - startscan;
2759 descr.xDest = dc->w.DCOrgX + XLPTODP( dc, xDest );
2760 descr.yDest = dc->w.DCOrgY + YLPTODP( dc, yDest ) +
2761 (tmpheight >= 0 ? oldcy-cy : 0);
2762 descr.width = cx;
2763 descr.height = cy;
2764 descr.useShm = FALSE;
2766 EnterCriticalSection( &X11DRV_CritSection );
2767 result = CALL_LARGE_STACK( X11DRV_DIB_SetImageBits, &descr );
2768 LeaveCriticalSection( &X11DRV_CritSection );
2770 if (descr.infoBpp <= 8)
2771 HeapFree(GetProcessHeap(), 0, descr.colorMap);
2772 return result;
2775 /***********************************************************************
2776 * X11DRV_DIB_SetDIBits
2778 INT X11DRV_DIB_SetDIBits(
2779 BITMAPOBJ *bmp, DC *dc, UINT startscan,
2780 UINT lines, LPCVOID bits, const BITMAPINFO *info,
2781 UINT coloruse, HBITMAP hbitmap)
2783 X11DRV_DIB_IMAGEBITS_DESCR descr;
2784 X11DRV_PHYSBITMAP *pbitmap;
2785 int height, tmpheight;
2786 INT result;
2788 descr.dc = dc;
2790 if (DIB_GetBitmapInfo( &info->bmiHeader, &descr.infoWidth, &height,
2791 &descr.infoBpp, &descr.compression ) == -1)
2792 return 0;
2794 tmpheight = height;
2795 if (height < 0) height = -height;
2796 if (!lines || (startscan >= height))
2797 return 0;
2799 if (startscan + lines > height) lines = height - startscan;
2801 switch (descr.infoBpp)
2803 case 1:
2804 case 4:
2805 case 8:
2806 descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap(
2807 coloruse == DIB_PAL_COLORS ? descr.dc : NULL, coloruse,
2808 bmp->bitmap.bmBitsPixel,
2809 info, &descr.nColorMap );
2810 if (!descr.colorMap) return 0;
2811 descr.rMask = descr.gMask = descr.bMask = 0;
2812 break;
2813 case 15:
2814 case 16:
2815 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
2816 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x03e0;
2817 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x001f;
2818 descr.colorMap = 0;
2819 break;
2821 case 24:
2822 descr.rMask = descr.gMask = descr.bMask = 0;
2823 descr.colorMap = 0;
2824 break;
2826 case 32:
2827 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
2828 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0xff00;
2829 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0xff;
2830 descr.colorMap = 0;
2831 break;
2833 default: break;
2836 /* HACK for now */
2837 if(!bmp->DDBitmap)
2838 X11DRV_CreateBitmap(hbitmap);
2840 pbitmap = bmp->DDBitmap->physBitmap;
2842 descr.bits = bits;
2843 descr.image = NULL;
2844 descr.palentry = NULL;
2845 descr.lines = tmpheight >= 0 ? lines : -lines;
2846 descr.depth = bmp->bitmap.bmBitsPixel;
2847 descr.drawable = pbitmap->pixmap;
2848 descr.gc = BITMAP_GC(bmp);
2849 descr.xSrc = 0;
2850 descr.ySrc = 0;
2851 descr.xDest = 0;
2852 descr.yDest = height - startscan - lines;
2853 descr.width = bmp->bitmap.bmWidth;
2854 descr.height = lines;
2855 descr.useShm = FALSE;
2857 EnterCriticalSection( &X11DRV_CritSection );
2858 result = CALL_LARGE_STACK( X11DRV_DIB_SetImageBits, &descr );
2859 LeaveCriticalSection( &X11DRV_CritSection );
2861 if (descr.colorMap) HeapFree(GetProcessHeap(), 0, descr.colorMap);
2863 return result;
2866 /***********************************************************************
2867 * X11DRV_DIB_GetDIBits
2869 INT X11DRV_DIB_GetDIBits(
2870 BITMAPOBJ *bmp, DC *dc, UINT startscan,
2871 UINT lines, LPVOID bits, BITMAPINFO *info,
2872 UINT coloruse, HBITMAP hbitmap)
2874 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
2875 X11DRV_DIB_IMAGEBITS_DESCR descr;
2876 X11DRV_PHYSBITMAP *pbitmap;
2877 PALETTEOBJ * palette;
2879 TRACE("%u scanlines of (%i,%i) -> (%i,%i) starting from %u\n",
2880 lines, bmp->bitmap.bmWidth, bmp->bitmap.bmHeight,
2881 (int)info->bmiHeader.biWidth, (int)info->bmiHeader.biHeight,
2882 startscan );
2884 if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->w.hPalette, PALETTE_MAGIC )))
2885 return 0;
2887 if( lines > info->bmiHeader.biHeight ) lines = info->bmiHeader.biHeight;
2888 if( startscan >= bmp->bitmap.bmHeight ) return FALSE;
2890 if (DIB_GetBitmapInfo( &info->bmiHeader, &descr.infoWidth, &descr.lines,
2891 &descr.infoBpp, &descr.compression ) == -1)
2892 return FALSE;
2894 switch (descr.infoBpp)
2896 case 1:
2897 case 4:
2898 case 8:
2899 case 24:
2900 descr.rMask = descr.gMask = descr.bMask = 0;
2901 break;
2902 case 15:
2903 case 16:
2904 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
2905 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x03e0;
2906 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x001f;
2907 break;
2909 case 32:
2910 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
2911 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0xff00;
2912 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0xff;
2913 break;
2916 /* Hack for now */
2917 if(!bmp->DDBitmap)
2918 X11DRV_CreateBitmap(hbitmap);
2920 pbitmap = bmp->DDBitmap->physBitmap;
2922 descr.dc = dc;
2923 descr.palentry = palette->logpalette.palPalEntry;
2924 descr.bits = bits;
2925 descr.lines = lines;
2926 descr.depth = bmp->bitmap.bmBitsPixel;
2927 descr.drawable = pbitmap->pixmap;
2928 descr.gc = BITMAP_GC(bmp);
2929 descr.xSrc = 0;
2930 descr.ySrc = startscan;
2931 descr.xDest = 0;
2932 descr.yDest = 0;
2933 descr.width = bmp->bitmap.bmWidth;
2934 descr.height = bmp->bitmap.bmHeight;
2935 descr.colorMap = info->bmiColors;
2937 if (dib)
2938 descr.useShm = (dib->shminfo.shmid != -1);
2939 else
2940 descr.useShm = FALSE;
2942 EnterCriticalSection( &X11DRV_CritSection );
2944 descr.image = (XImage *)CALL_LARGE_STACK( X11DRV_BITMAP_GetXImage, bmp );
2945 CALL_LARGE_STACK( X11DRV_DIB_GetImageBits, &descr );
2947 LeaveCriticalSection( &X11DRV_CritSection );
2949 if(info->bmiHeader.biSizeImage == 0) /* Fill in biSizeImage */
2950 info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(
2951 info->bmiHeader.biWidth,
2952 info->bmiHeader.biHeight,
2953 info->bmiHeader.biBitCount );
2955 info->bmiHeader.biCompression = 0;
2957 GDI_HEAP_UNLOCK( dc->w.hPalette );
2959 return lines;
2962 /***********************************************************************
2963 * DIB_DoProtectDIBSection
2965 static void X11DRV_DIB_DoProtectDIBSection( BITMAPOBJ *bmp, DWORD new_prot )
2967 DIBSECTION *dib = bmp->dib;
2968 INT effHeight = dib->dsBm.bmHeight >= 0? dib->dsBm.bmHeight
2969 : -dib->dsBm.bmHeight;
2970 INT totalSize = dib->dsBmih.biSizeImage? dib->dsBmih.biSizeImage
2971 : dib->dsBm.bmWidthBytes * effHeight;
2972 DWORD old_prot;
2974 VirtualProtect(dib->dsBm.bmBits, totalSize, new_prot, &old_prot);
2975 TRACE("Changed protection from %ld to %ld\n", old_prot, new_prot);
2978 /***********************************************************************
2979 * X11DRV_DIB_DoUpdateDIBSection
2981 static void X11DRV_DIB_DoUpdateDIBSection(BITMAPOBJ *bmp, BOOL toDIB)
2983 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
2984 X11DRV_DIB_IMAGEBITS_DESCR descr;
2986 if (DIB_GetBitmapInfo( &dib->dibSection.dsBmih, &descr.infoWidth, &descr.lines,
2987 &descr.infoBpp, &descr.compression ) == -1)
2988 return;
2990 descr.dc = NULL;
2991 descr.palentry = NULL;
2992 descr.image = dib->image;
2993 descr.colorMap = (RGBQUAD *)dib->colorMap;
2994 descr.nColorMap = dib->nColorMap;
2995 descr.bits = dib->dibSection.dsBm.bmBits;
2996 descr.depth = bmp->bitmap.bmBitsPixel;
2998 switch (descr.infoBpp)
3000 case 1:
3001 case 4:
3002 case 8:
3003 case 24:
3004 descr.rMask = descr.gMask = descr.bMask = 0;
3005 break;
3006 case 15:
3007 case 16:
3008 descr.rMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[0] : 0x7c00;
3009 descr.gMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[1] : 0x03e0;
3010 descr.bMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[2] : 0x001f;
3011 break;
3013 case 32:
3014 descr.rMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[0] : 0xff;
3015 descr.gMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[1] : 0xff00;
3016 descr.bMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[2] : 0xff0000;
3017 break;
3020 /* Hack for now */
3021 descr.drawable = ((X11DRV_PHYSBITMAP *)bmp->DDBitmap->physBitmap)->pixmap;
3022 descr.gc = BITMAP_GC(bmp);
3023 descr.xSrc = 0;
3024 descr.ySrc = 0;
3025 descr.xDest = 0;
3026 descr.yDest = 0;
3027 descr.width = bmp->bitmap.bmWidth;
3028 descr.height = bmp->bitmap.bmHeight;
3029 descr.useShm = (dib->shminfo.shmid != -1);
3031 if (toDIB)
3033 TRACE("Copying from Pixmap to DIB bits\n");
3034 EnterCriticalSection( &X11DRV_CritSection );
3035 CALL_LARGE_STACK( X11DRV_DIB_GetImageBits, &descr );
3036 LeaveCriticalSection( &X11DRV_CritSection );
3038 else
3040 TRACE("Copying from DIB bits to Pixmap\n");
3041 EnterCriticalSection( &X11DRV_CritSection );
3042 CALL_LARGE_STACK( X11DRV_DIB_SetImageBits, &descr );
3043 LeaveCriticalSection( &X11DRV_CritSection );
3047 /***********************************************************************
3048 * X11DRV_DIB_FaultHandler
3050 static BOOL X11DRV_DIB_FaultHandler( LPVOID res, LPCVOID addr )
3052 BOOL handled = FALSE;
3053 BITMAPOBJ *bmp;
3055 bmp = (BITMAPOBJ *)GDI_GetObjPtr( (HBITMAP)res, BITMAP_MAGIC );
3056 if (!bmp) return FALSE;
3058 if (bmp->dib)
3059 switch (((X11DRV_DIBSECTION *) bmp->dib)->status)
3061 case X11DRV_DIB_GdiMod:
3062 TRACE("called in status DIB_GdiMod\n" );
3063 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
3064 X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
3065 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
3066 ((X11DRV_DIBSECTION *) bmp->dib)->status = X11DRV_DIB_InSync;
3067 handled = TRUE;
3068 break;
3070 case X11DRV_DIB_InSync:
3071 TRACE("called in status X11DRV_DIB_InSync\n" );
3072 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
3073 ((X11DRV_DIBSECTION *) bmp->dib)->status = X11DRV_DIB_AppMod;
3074 handled = TRUE;
3075 break;
3077 case X11DRV_DIB_AppMod:
3078 FIXME("called in status X11DRV_DIB_AppMod: this can't happen!\n" );
3079 break;
3081 case X11DRV_DIB_NoHandler:
3082 FIXME("called in status DIB_NoHandler: this can't happen!\n" );
3083 break;
3086 GDI_HEAP_UNLOCK( (HBITMAP)res );
3087 return handled;
3090 /***********************************************************************
3091 * X11DRV_DIB_UpdateDIBSection
3093 void X11DRV_DIB_UpdateDIBSection(DC *dc, BOOL toDIB)
3095 BITMAPOBJ *bmp;
3097 /* Ensure this is a Compatible DC that has a DIB section selected */
3099 if (!dc) return;
3100 if (!(dc->w.flags & DC_MEMORY)) return;
3102 bmp = (BITMAPOBJ *)GDI_GetObjPtr( dc->w.hBitmap, BITMAP_MAGIC );
3103 if (!bmp) return;
3105 if (!bmp->dib)
3107 GDI_HEAP_UNLOCK(dc->w.hBitmap);
3108 return;
3111 if (!toDIB)
3113 /* Prepare for access to the DIB by GDI functions */
3115 switch (((X11DRV_DIBSECTION *) bmp->dib)->status)
3117 default:
3118 case X11DRV_DIB_NoHandler:
3119 X11DRV_DIB_DoUpdateDIBSection( bmp, FALSE );
3120 break;
3122 case X11DRV_DIB_GdiMod:
3123 TRACE("fromDIB called in status X11DRV_DIB_GdiMod\n" );
3124 /* nothing to do */
3125 break;
3127 case X11DRV_DIB_InSync:
3128 TRACE("fromDIB called in status X11DRV_DIB_InSync\n" );
3129 /* nothing to do */
3130 break;
3132 case X11DRV_DIB_AppMod:
3133 TRACE("fromDIB called in status X11DRV_DIB_AppMod\n" );
3134 X11DRV_DIB_DoUpdateDIBSection( bmp, FALSE );
3135 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
3136 ((X11DRV_DIBSECTION *) bmp->dib)->status = X11DRV_DIB_InSync;
3137 break;
3140 else
3142 /* Acknowledge write access to the DIB by GDI functions */
3144 switch (((X11DRV_DIBSECTION *) bmp->dib)->status)
3146 default:
3147 case X11DRV_DIB_NoHandler:
3148 X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
3149 break;
3151 case X11DRV_DIB_GdiMod:
3152 TRACE(" toDIB called in status X11DRV_DIB_GdiMod\n" );
3153 /* nothing to do */
3154 break;
3156 case X11DRV_DIB_InSync:
3157 TRACE(" toDIB called in status X11DRV_DIB_InSync\n" );
3158 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
3159 ((X11DRV_DIBSECTION *) bmp->dib)->status = X11DRV_DIB_GdiMod;
3160 break;
3162 case X11DRV_DIB_AppMod:
3163 FIXME(" toDIB called in status X11DRV_DIB_AppMod: "
3164 "this can't happen!\n" );
3165 break;
3169 GDI_HEAP_UNLOCK(dc->w.hBitmap);
3172 /***********************************************************************
3173 * X11DRV_DIB_CreateDIBSection16
3175 HBITMAP16 X11DRV_DIB_CreateDIBSection16(
3176 DC *dc, BITMAPINFO *bmi, UINT16 usage,
3177 SEGPTR *bits, HANDLE section,
3178 DWORD offset)
3180 HBITMAP res = X11DRV_DIB_CreateDIBSection(dc, bmi, usage, NULL,
3181 section, offset);
3182 if ( res )
3184 BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr(res, BITMAP_MAGIC);
3185 if ( bmp && bmp->dib )
3187 DIBSECTION *dib = bmp->dib;
3188 INT height = dib->dsBm.bmHeight >= 0 ?
3189 dib->dsBm.bmHeight : -dib->dsBm.bmHeight;
3190 INT size = dib->dsBmih.biSizeImage ?
3191 dib->dsBmih.biSizeImage : dib->dsBm.bmWidthBytes * height;
3192 if ( dib->dsBm.bmBits )
3194 ((X11DRV_DIBSECTION *) bmp->dib)->selector =
3195 SELECTOR_AllocBlock( dib->dsBm.bmBits, size,
3196 SEGMENT_DATA, FALSE, FALSE );
3198 TRACE("ptr = %p, size =%d, selector = %04x, segptr = %ld\n",
3199 dib->dsBm.bmBits, size, ((X11DRV_DIBSECTION *) bmp->dib)->selector,
3200 PTR_SEG_OFF_TO_SEGPTR(((X11DRV_DIBSECTION *) bmp->dib)->selector, 0));
3202 GDI_HEAP_UNLOCK( res );
3204 if ( bits )
3205 *bits = PTR_SEG_OFF_TO_SEGPTR( ((X11DRV_DIBSECTION *) bmp->dib)->selector, 0 );
3208 return res;
3211 /***********************************************************************
3212 * X11DRV_XShmErrorHandler
3215 static int XShmErrorHandler(Display *dpy, XErrorEvent *event)
3217 XShmErrorFlag = 1;
3218 return 0;
3221 /***********************************************************************
3222 * X11DRV_XShmCreateImage
3226 extern BOOL X11DRV_XShmCreateImage(XImage** image, int width, int height, int bpp,
3227 XShmSegmentInfo* shminfo)
3229 int (*WineXHandler)(Display *, XErrorEvent *);
3231 *image = TSXShmCreateImage(display, X11DRV_GetVisual(), bpp, ZPixmap, NULL, shminfo, width, height);
3232 if( *image != NULL )
3234 EnterCriticalSection( &X11DRV_CritSection );
3235 shminfo->shmid = shmget(IPC_PRIVATE, (*image)->bytes_per_line * height,
3236 IPC_CREAT|0700);
3237 if( shminfo->shmid != -1 )
3239 shminfo->shmaddr = (*image)->data = shmat(shminfo->shmid, 0, 0);
3240 if( shminfo->shmaddr != (char*)-1 )
3242 shminfo->readOnly = FALSE;
3243 if( TSXShmAttach( display, shminfo ) != 0)
3245 /* Reset the error flag */
3246 XShmErrorFlag = 0;
3247 WineXHandler = XSetErrorHandler(XShmErrorHandler);
3248 XSync( display, 0 );
3250 if (!XShmErrorFlag)
3252 shmctl(shminfo->shmid, IPC_RMID, 0);
3254 XSetErrorHandler(WineXHandler);
3255 LeaveCriticalSection( &X11DRV_CritSection );
3257 return TRUE; /* Success! */
3259 /* An error occured */
3260 XShmErrorFlag = 0;
3261 XSetErrorHandler(WineXHandler);
3263 shmdt(shminfo->shmaddr);
3265 shmctl(shminfo->shmid, IPC_RMID, 0);
3267 XFlush(display);
3268 XDestroyImage(*image);
3269 LeaveCriticalSection( &X11DRV_CritSection );
3271 return FALSE;
3277 /***********************************************************************
3278 * X11DRV_DIB_CreateDIBSection
3280 HBITMAP X11DRV_DIB_CreateDIBSection(
3281 DC *dc, BITMAPINFO *bmi, UINT usage,
3282 LPVOID *bits, HANDLE section,
3283 DWORD offset)
3285 HBITMAP res = 0;
3286 BITMAPOBJ *bmp = NULL;
3287 X11DRV_DIBSECTION *dib = NULL;
3288 int *colorMap = NULL;
3289 int nColorMap;
3291 /* Fill BITMAP32 structure with DIB data */
3292 BITMAPINFOHEADER *bi = &bmi->bmiHeader;
3293 INT effHeight, totalSize;
3294 BITMAP bm;
3296 TRACE("format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
3297 bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
3298 bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
3300 effHeight = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
3301 bm.bmType = 0;
3302 bm.bmWidth = bi->biWidth;
3303 bm.bmHeight = effHeight;
3304 bm.bmWidthBytes = DIB_GetDIBWidthBytes(bm.bmWidth, bi->biBitCount);
3305 bm.bmPlanes = bi->biPlanes;
3306 bm.bmBitsPixel = bi->biBitCount;
3307 bm.bmBits = NULL;
3309 /* Get storage location for DIB bits */
3310 totalSize = bi->biSizeImage? bi->biSizeImage : bm.bmWidthBytes * effHeight;
3312 if (section)
3313 bm.bmBits = MapViewOfFile(section, FILE_MAP_ALL_ACCESS,
3314 0L, offset, totalSize);
3315 else
3316 bm.bmBits = VirtualAlloc(NULL, totalSize,
3317 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
3319 /* Create Color Map */
3320 if (bm.bmBits && bm.bmBitsPixel <= 8)
3321 colorMap = X11DRV_DIB_BuildColorMap( usage == DIB_PAL_COLORS? dc : NULL,
3322 usage, bm.bmBitsPixel, bmi, &nColorMap );
3324 /* Allocate Memory for DIB and fill structure */
3325 if (bm.bmBits)
3326 dib = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(X11DRV_DIBSECTION));
3327 if (dib)
3329 dib->dibSection.dsBm = bm;
3330 dib->dibSection.dsBmih = *bi;
3332 /* Set dsBitfields values */
3333 if ( usage == DIB_PAL_COLORS || bi->biBitCount <= 8)
3335 dib->dibSection.dsBitfields[0] = dib->dibSection.dsBitfields[1] = dib->dibSection.dsBitfields[2] = 0;
3337 else switch( bi->biBitCount )
3339 case 16:
3340 dib->dibSection.dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors : 0x7c00;
3341 dib->dibSection.dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0x03e0;
3342 dib->dibSection.dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0x001f;
3343 break;
3345 case 24:
3346 dib->dibSection.dsBitfields[0] = 0xff;
3347 dib->dibSection.dsBitfields[1] = 0xff00;
3348 dib->dibSection.dsBitfields[2] = 0xff0000;
3349 break;
3351 case 32:
3352 dib->dibSection.dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors : 0xff;
3353 dib->dibSection.dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0xff00;
3354 dib->dibSection.dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0xff0000;
3355 break;
3357 dib->dibSection.dshSection = section;
3358 dib->dibSection.dsOffset = offset;
3360 dib->status = X11DRV_DIB_NoHandler;
3361 dib->selector = 0;
3363 dib->nColorMap = nColorMap;
3364 dib->colorMap = colorMap;
3367 /* Create Device Dependent Bitmap and add DIB pointer */
3368 if (dib)
3370 res = CreateDIBitmap(dc->hSelf, bi, 0, NULL, bmi, usage);
3371 if (res)
3373 bmp = (BITMAPOBJ *) GDI_GetObjPtr(res, BITMAP_MAGIC);
3374 if (bmp)
3376 bmp->dib = (DIBSECTION *) dib;
3377 /* HACK for now */
3378 if(!bmp->DDBitmap)
3379 X11DRV_CreateBitmap(res);
3384 /* Create XImage */
3385 if (dib && bmp)
3387 if (TSXShmQueryExtension(display) &&
3388 X11DRV_XShmCreateImage( &dib->image, bm.bmWidth, effHeight,
3389 bmp->bitmap.bmBitsPixel, &dib->shminfo ) )
3391 ; /* Created Image */
3392 } else {
3393 XCREATEIMAGE( dib->image, bm.bmWidth, effHeight, bmp->bitmap.bmBitsPixel );
3394 dib->shminfo.shmid = -1;
3398 /* Clean up in case of errors */
3399 if (!res || !bmp || !dib || !bm.bmBits || (bm.bmBitsPixel <= 8 && !colorMap))
3401 TRACE("got an error res=%08x, bmp=%p, dib=%p, bm.bmBits=%p\n",
3402 res, bmp, dib, bm.bmBits);
3403 if (bm.bmBits)
3405 if (section)
3406 UnmapViewOfFile(bm.bmBits), bm.bmBits = NULL;
3407 else
3408 VirtualFree(bm.bmBits, 0L, MEM_RELEASE), bm.bmBits = NULL;
3411 if (dib && dib->image) { XDestroyImage(dib->image); dib->image = NULL; }
3412 if (colorMap) { HeapFree(GetProcessHeap(), 0, colorMap); colorMap = NULL; }
3413 if (dib) { HeapFree(GetProcessHeap(), 0, dib); dib = NULL; }
3414 if (res) { DeleteObject(res); res = 0; }
3417 /* Install fault handler, if possible */
3418 if (bm.bmBits)
3420 if (VIRTUAL_SetFaultHandler(bm.bmBits, X11DRV_DIB_FaultHandler, (LPVOID)res))
3422 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
3423 if (dib) dib->status = X11DRV_DIB_InSync;
3427 /* Return BITMAP handle and storage location */
3428 if (res) GDI_HEAP_UNLOCK(res);
3429 if (bm.bmBits && bits) *bits = bm.bmBits;
3430 return res;
3433 /***********************************************************************
3434 * X11DRV_DIB_DeleteDIBSection
3436 void X11DRV_DIB_DeleteDIBSection(BITMAPOBJ *bmp)
3438 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
3440 if (dib->image)
3442 if (dib->shminfo.shmid != -1)
3444 TSXShmDetach (display, &(dib->shminfo));
3445 XDestroyImage (dib->image);
3446 shmdt (dib->shminfo.shmaddr);
3447 dib->shminfo.shmid = -1;
3449 else
3450 XDestroyImage( dib->image );
3453 if (dib->colorMap)
3454 HeapFree(GetProcessHeap(), 0, dib->colorMap);
3456 if (dib->selector)
3458 WORD count = (GET_SEL_LIMIT( dib->selector ) >> 16) + 1;
3459 SELECTOR_FreeBlock( dib->selector, count );
3464 /**************************************************************************
3465 * X11DRV_DIB_CreateDIBFromPixmap
3467 * Allocates a packed DIB and copies the Pixmap data into it.
3468 * If bDeletePixmap is TRUE, the Pixmap passed in is deleted after the conversion.
3470 HGLOBAL X11DRV_DIB_CreateDIBFromPixmap(Pixmap pixmap, HDC hdc, BOOL bDeletePixmap)
3472 HBITMAP hBmp = 0;
3473 BITMAPOBJ *pBmp = NULL;
3474 HGLOBAL hPackedDIB = 0;
3476 /* Allocates an HBITMAP which references the Pixmap passed to us */
3477 hBmp = X11DRV_BITMAP_CreateBitmapHeaderFromPixmap(pixmap);
3478 if (!hBmp)
3480 TRACE("\tCould not create bitmap header for Pixmap\n");
3481 goto END;
3485 * Create a packed DIB from the Pixmap wrapper bitmap created above.
3486 * A packed DIB contains a BITMAPINFO structure followed immediately by
3487 * an optional color palette and the pixel data.
3489 hPackedDIB = DIB_CreateDIBFromBitmap(hdc, hBmp);
3491 /* Get a pointer to the BITMAPOBJ structure */
3492 pBmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
3494 /* We can now get rid of the HBITMAP wrapper we created earlier.
3495 * Note: Simply calling DeleteObject will free the embedded Pixmap as well.
3497 if (!bDeletePixmap)
3499 /* Manually free the DDBitmap internals to prevent the Pixmap
3500 * from being deleted by DeleteObject.
3502 HeapFree( GetProcessHeap(), 0, pBmp->DDBitmap->physBitmap );
3503 HeapFree( GetProcessHeap(), 0, pBmp->DDBitmap );
3504 pBmp->DDBitmap = NULL;
3506 DeleteObject(hBmp);
3508 END:
3509 TRACE("\tReturning packed DIB %x\n", hPackedDIB);
3510 return hPackedDIB;
3514 /**************************************************************************
3515 * X11DRV_DIB_CreatePixmapFromDIB
3517 * Creates a Pixmap from a packed DIB
3519 Pixmap X11DRV_DIB_CreatePixmapFromDIB( HGLOBAL hPackedDIB, HDC hdc )
3521 Pixmap pixmap = None;
3522 HBITMAP hBmp = 0;
3523 BITMAPOBJ *pBmp = NULL;
3524 LPBYTE pPackedDIB = NULL;
3525 LPBITMAPINFO pbmi = NULL;
3526 LPBITMAPINFOHEADER pbmiHeader = NULL;
3527 LPBYTE pbits = NULL;
3529 /* Get a pointer to the packed DIB's data */
3530 pPackedDIB = (LPBYTE)GlobalLock(hPackedDIB);
3531 pbmiHeader = (LPBITMAPINFOHEADER)pPackedDIB;
3532 pbmi = (LPBITMAPINFO)pPackedDIB;
3533 pbits = (LPBYTE)(pPackedDIB
3534 + DIB_BitmapInfoSize( (LPBITMAPINFO)pbmiHeader, DIB_RGB_COLORS ));
3536 /* Create a DDB from the DIB */
3538 hBmp = CreateDIBitmap(hdc,
3539 pbmiHeader,
3540 CBM_INIT,
3541 (LPVOID)pbits,
3542 pbmi,
3543 DIB_RGB_COLORS);
3545 GlobalUnlock(hPackedDIB);
3547 TRACE("CreateDIBitmap returned %x\n", hBmp);
3549 /* Retrieve the internal Pixmap from the DDB */
3551 pBmp = (BITMAPOBJ *) GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
3553 if (pBmp->DDBitmap && pBmp->DDBitmap->physBitmap)
3555 pixmap = ((X11DRV_PHYSBITMAP *)(pBmp->DDBitmap->physBitmap))->pixmap;
3556 if (!pixmap)
3557 TRACE("NULL Pixmap in DDBitmap->physBitmap!\n");
3559 /* Manually free the BITMAPOBJ internals so that we can steal its pixmap */
3560 HeapFree( GetProcessHeap(), 0, pBmp->DDBitmap->physBitmap );
3561 HeapFree( GetProcessHeap(), 0, pBmp->DDBitmap );
3562 pBmp->DDBitmap = NULL; /* Its not a DDB anymore */
3565 /* Delete the DDB we created earlier now that we have stolen its pixmap */
3566 DeleteObject(hBmp);
3568 TRACE("\tReturning Pixmap %ld\n", pixmap);
3569 return pixmap;
3572 #endif /* !defined(X_DISPLAY_MISSING) */