Authors: Ove Kaaven <ovek@transgaming.com>, Andrew Lewycky <andrew@transgaming.com...
[wine/multimedia.git] / graphics / x11drv / dib.c
blob9a6ba92dabaa80b3f4d1bb07d3e0e31875128e84
1 /*
2 * X11DRV device-independent bitmaps
4 * Copyright 1993,1994 Alexandre Julliard
5 */
7 #include "config.h"
9 #include "ts_xlib.h"
10 #include "ts_xutil.h"
11 #ifdef HAVE_LIBXXSHM
12 # include "ts_xshm.h"
13 # ifdef HAVE_SYS_SHM_H
14 # include <sys/shm.h>
15 # endif
16 # ifdef HAVE_SYS_IPC_H
17 # include <sys/ipc.h>
18 # endif
19 #endif /* defined(HAVE_LIBXXSHM) */
21 #include <stdlib.h>
22 #include "windef.h"
23 #include "bitmap.h"
24 #include "x11drv.h"
25 #include "debugtools.h"
26 #include "gdi.h"
27 #include "color.h"
28 #include "callback.h"
29 #include "selectors.h"
30 #include "global.h"
32 DEFAULT_DEBUG_CHANNEL(bitmap);
33 DECLARE_DEBUG_CHANNEL(x11drv);
35 static int bitmapDepthTable[] = { 8, 1, 32, 16, 24, 15, 4, 0 };
36 static int ximageDepthTable[] = { 0, 0, 0, 0, 0, 0, 0 };
38 static int XShmErrorFlag = 0;
40 /***********************************************************************
41 * X11DRV_DIB_Init
43 BOOL X11DRV_DIB_Init(void)
45 int i;
46 XImage* testimage;
48 for( i = 0; bitmapDepthTable[i]; i++ )
50 testimage = TSXCreateImage(display, X11DRV_GetVisual(),
51 bitmapDepthTable[i], ZPixmap, 0, NULL, 1, 1, 32, 20 );
52 if( testimage ) ximageDepthTable[i] = testimage->bits_per_pixel;
53 else return FALSE;
54 TSXDestroyImage(testimage);
56 return TRUE;
60 /***********************************************************************
61 * X11DRV_DIB_GetXImageWidthBytes
63 * Return the width of an X image in bytes
65 int X11DRV_DIB_GetXImageWidthBytes( int width, int depth )
67 int i;
69 if (!ximageDepthTable[0]) {
70 X11DRV_DIB_Init();
72 for( i = 0; bitmapDepthTable[i] ; i++ )
73 if( bitmapDepthTable[i] == depth )
74 return (4 * ((width * ximageDepthTable[i] + 31)/32));
76 WARN("(%d): Unsupported depth\n", depth );
77 return (4 * width);
80 /***********************************************************************
81 * X11DRV_DIB_GenColorMap
83 * Fills the color map of a bitmap palette. Should not be called
84 * for a >8-bit deep bitmap.
86 int *X11DRV_DIB_GenColorMap( DC *dc, int *colorMapping,
87 WORD coloruse, WORD depth, BOOL quads,
88 const void *colorPtr, int start, int end )
90 int i;
92 if (coloruse == DIB_RGB_COLORS)
94 if (quads)
96 RGBQUAD * rgb = (RGBQUAD *)colorPtr;
98 if (depth == 1) /* Monochrome */
99 for (i = start; i < end; i++, rgb++)
100 colorMapping[i] = (rgb->rgbRed + rgb->rgbGreen +
101 rgb->rgbBlue > 255*3/2);
102 else
103 for (i = start; i < end; i++, rgb++)
104 colorMapping[i] = X11DRV_PALETTE_ToPhysical( dc, RGB(rgb->rgbRed,
105 rgb->rgbGreen,
106 rgb->rgbBlue));
108 else
110 RGBTRIPLE * rgb = (RGBTRIPLE *)colorPtr;
112 if (depth == 1) /* Monochrome */
113 for (i = start; i < end; i++, rgb++)
114 colorMapping[i] = (rgb->rgbtRed + rgb->rgbtGreen +
115 rgb->rgbtBlue > 255*3/2);
116 else
117 for (i = start; i < end; i++, rgb++)
118 colorMapping[i] = X11DRV_PALETTE_ToPhysical( dc, RGB(rgb->rgbtRed,
119 rgb->rgbtGreen,
120 rgb->rgbtBlue));
123 else /* DIB_PAL_COLORS */
125 WORD * index = (WORD *)colorPtr;
127 for (i = start; i < end; i++, index++)
128 colorMapping[i] = X11DRV_PALETTE_ToPhysical( dc, PALETTEINDEX(*index) );
131 return colorMapping;
134 /***********************************************************************
135 * X11DRV_DIB_BuildColorMap
137 * Build the color map from the bitmap palette. Should not be called
138 * for a >8-bit deep bitmap.
140 int *X11DRV_DIB_BuildColorMap( DC *dc, WORD coloruse, WORD depth,
141 const BITMAPINFO *info, int *nColors )
143 int colors;
144 BOOL isInfo;
145 WORD *colorPtr;
146 int *colorMapping;
148 if ((isInfo = (info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))))
150 colors = info->bmiHeader.biClrUsed;
151 if (!colors) colors = 1 << info->bmiHeader.biBitCount;
152 colorPtr = (WORD *)info->bmiColors;
154 else /* assume BITMAPCOREINFO */
156 colors = 1 << ((BITMAPCOREHEADER *)&info->bmiHeader)->bcBitCount;
157 colorPtr = (WORD *)((BITMAPCOREINFO *)info)->bmciColors;
160 if (colors > 256)
162 ERR("called with >256 colors!\n");
163 return NULL;
166 if (!(colorMapping = (int *)HeapAlloc(GetProcessHeap(), 0,
167 colors * sizeof(int) )))
168 return NULL;
170 *nColors = colors;
171 return X11DRV_DIB_GenColorMap( dc, colorMapping, coloruse, depth,
172 isInfo, colorPtr, 0, colors);
176 /***********************************************************************
177 * X11DRV_DIB_MapColor
179 int X11DRV_DIB_MapColor( int *physMap, int nPhysMap, int phys, int oldcol )
181 int color;
183 if ((oldcol < nPhysMap) && (physMap[oldcol] == phys))
184 return oldcol;
186 for (color = 0; color < nPhysMap; color++)
187 if (physMap[color] == phys)
188 return color;
190 WARN("Strange color %08x\n", phys);
191 return 0;
195 /*********************************************************************
196 * X11DRV_DIB_GetNearestIndex
198 * Helper for X11DRV_DIB_GetDIBits.
199 * Returns the nearest colour table index for a given RGB.
200 * Nearest is defined by minimizing the sum of the squares.
202 static INT X11DRV_DIB_GetNearestIndex(RGBQUAD *colormap, int numColors, BYTE r, BYTE g, BYTE b)
204 INT i, best = -1, diff, bestdiff = -1;
205 RGBQUAD *color;
207 for(color = colormap, i = 0; i < numColors; color++, i++) {
208 diff = (r - color->rgbRed) * (r - color->rgbRed) +
209 (g - color->rgbGreen) * (g - color->rgbGreen) +
210 (b - color->rgbBlue) * (b - color->rgbBlue);
211 if(diff == 0)
212 return i;
213 if(best == -1 || diff < bestdiff) {
214 best = i;
215 bestdiff = diff;
218 return best;
221 /***********************************************************************
222 * X11DRV_DIB_SetImageBits_1_Line
224 * Handles a single line of 1 bit data.
226 static void X11DRV_DIB_SetImageBits_1_Line(DWORD dstwidth, int left, int *colors,
227 XImage *bmpImage, int h, const BYTE *bits)
229 BYTE pix, extra;
230 DWORD i, x;
232 if((extra = (left & 7)) != 0) {
233 left &= ~7;
234 dstwidth += extra;
237 bits += left >> 3;
239 /* FIXME: should avoid putting x<left pixels (minor speed issue) */
240 for (i = dstwidth/8, x = left; i > 0; i--)
242 pix = *bits++;
243 XPutPixel( bmpImage, x++, h, colors[pix >> 7] );
244 XPutPixel( bmpImage, x++, h, colors[(pix >> 6) & 1] );
245 XPutPixel( bmpImage, x++, h, colors[(pix >> 5) & 1] );
246 XPutPixel( bmpImage, x++, h, colors[(pix >> 4) & 1] );
247 XPutPixel( bmpImage, x++, h, colors[(pix >> 3) & 1] );
248 XPutPixel( bmpImage, x++, h, colors[(pix >> 2) & 1] );
249 XPutPixel( bmpImage, x++, h, colors[(pix >> 1) & 1] );
250 XPutPixel( bmpImage, x++, h, colors[pix & 1] );
252 pix = *bits;
253 switch(dstwidth & 7)
255 case 7: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
256 case 6: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
257 case 5: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
258 case 4: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
259 case 3: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
260 case 2: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
261 case 1: XPutPixel( bmpImage, x++, h, colors[pix >> 7] );
265 /***********************************************************************
266 * X11DRV_DIB_SetImageBits_1
268 * SetDIBits for a 1-bit deep DIB.
270 static void X11DRV_DIB_SetImageBits_1( int lines, const BYTE *srcbits,
271 DWORD srcwidth, DWORD dstwidth, int left,
272 int *colors, XImage *bmpImage, DWORD linebytes)
274 int h;
276 if (lines > 0) {
277 for (h = lines-1; h >=0; h--) {
278 X11DRV_DIB_SetImageBits_1_Line(dstwidth, left, colors, bmpImage, h,
279 srcbits);
280 srcbits += linebytes;
282 } else {
283 lines = -lines;
284 for (h = 0; h < lines; h++) {
285 X11DRV_DIB_SetImageBits_1_Line(dstwidth, left, colors, bmpImage, h,
286 srcbits);
287 srcbits += linebytes;
292 /***********************************************************************
293 * X11DRV_DIB_GetImageBits_1
295 * GetDIBits for a 1-bit deep DIB.
297 static void X11DRV_DIB_GetImageBits_1( int lines, BYTE *dstbits,
298 DWORD dstwidth, DWORD srcwidth,
299 RGBQUAD *colors, PALETTEENTRY *srccolors,
300 XImage *bmpImage, DWORD linebytes )
302 DWORD x;
303 int h;
304 BYTE *bits;
306 if (lines < 0 ) {
307 lines = -lines;
308 dstbits = dstbits + linebytes * (lines - 1);
309 linebytes = -linebytes;
312 bits = dstbits;
314 switch(bmpImage->depth) {
316 case 1:
317 /* ==== monochrome bitmap to monochrome dib ==== */
318 case 4:
319 /* ==== 4 colormap bitmap to monochrome dib ==== */
320 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
322 PALETTEENTRY val;
324 for (h = lines - 1; h >= 0; h--) {
325 for (x = 0; x < dstwidth; x++) {
326 val = srccolors[XGetPixel(bmpImage, x, h)];
327 if (!(x&7)) *bits = 0;
328 *bits |= (X11DRV_DIB_GetNearestIndex(colors, 2,
329 val.peRed,
330 val.peGreen,
331 val.peBlue) << (7 - (x & 7)));
332 if ((x&7)==7) bits++;
334 bits = (dstbits += linebytes);
337 else goto notsupported;
339 break;
341 case 8:
342 /* ==== 8 colormap bitmap to monochrome dib ==== */
343 if ( bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
345 BYTE *srcpixel;
346 PALETTEENTRY val;
348 for( h = lines- 1; h >= 0; h-- ) {
349 srcpixel = bmpImage->data + (h*bmpImage->bytes_per_line);
350 for( x = 0; x < dstwidth; x++ ) {
351 if (!(x&7)) *bits = 0;
352 val = srccolors[(int)*srcpixel++];
353 *bits |= ( X11DRV_DIB_GetNearestIndex(colors, 2,
354 val.peRed,
355 val.peGreen,
356 val.peBlue) << (7-(x&7)) );
357 if ((x&7)==7) bits++;
359 bits = (dstbits += linebytes);
362 else goto notsupported;
364 break;
366 case 15:
368 LPWORD srcpixel;
369 WORD val;
371 /* ==== 555 BGR bitmap to monochrome dib ==== */
372 if (bmpImage->red_mask == 0x7c00 && bmpImage->blue_mask == 0x1f)
374 for( h = lines - 1; h >= 0; h--) {
375 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
376 for( x = 0; x < dstwidth; x++) {
377 if (!(x&7)) *bits = 0;
378 val = *srcpixel++;
379 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 2,
380 ((val >> 7) & 0xf8) |
381 ((val >> 12) & 0x7),
382 ((val >> 2) & 0xf8) |
383 ((val >> 7) & 0x3),
384 ((val << 3) & 0xf8) |
385 ((val >> 2) & 0x7) ) << (7-(x&7)) );
386 if ((x&7)==7) bits++;
388 bits = (dstbits += linebytes);
391 /* ==== 555 RGB bitmap to monochrome dib ==== */
392 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0xf800)
394 for( h = lines - 1; h >= 0; h--)
396 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
397 for( x = 0; x < dstwidth; x++) {
398 if (!(x&1)) *bits = 0;
399 val = *srcpixel++;
400 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 2,
401 ((val << 3) & 0xf8) |
402 ((val >> 2) & 0x7),
403 ((val >> 2) & 0xf8) |
404 ((val >> 7) & 0x3),
405 ((val >> 7) & 0xf8) |
406 ((val >> 12) & 0x7) ) << (7-(x&7)) );
407 if ((x&7)==7) bits++;
409 bits = (dstbits += linebytes);
412 else goto notsupported;
414 break;
416 case 16:
418 LPWORD srcpixel;
419 WORD val;
421 /* ==== 565 BGR bitmap to monochrome dib ==== */
422 if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f)
424 for( h = lines - 1; h >= 0; h--)
426 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
427 for( x = 0; x < dstwidth; x++) {
428 if (!(x&7)) *bits = 0;
429 val = *srcpixel++;
430 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 2,
431 ((val >> 8) & 0xf8) |
432 ((val >> 13) & 0x7),
433 ((val >> 3) & 0xfc) |
434 ((val >> 9) & 0x3),
435 ((val << 3) & 0xf8) |
436 ((val >> 2) & 0x7) ) << (7-(x&7)) );
437 if ((x&7)==7) bits++;
439 bits = (dstbits += linebytes);
442 /* ==== 565 RGB bitmap to monochrome dib ==== */
443 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0xf800)
445 for( h = lines - 1; h >= 0; h--)
447 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
448 for( x = 0; x < dstwidth; x++) {
449 if (!(x&7)) *bits = 0;
450 val = *srcpixel++;
451 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 2,
452 ((val << 3) & 0xf8) |
453 ((val >> 2) & 0x7),
454 ((val >> 3) & 0xfc) |
455 ((val >> 9) & 0x3),
456 ((val >> 8) & 0xf8) |
457 ((val >> 13) & 0x7) ) << (7-(x&7)) );
458 if ((x&7)==7) bits++;
460 bits = (dstbits += linebytes);
463 else goto notsupported;
465 break;
467 case 24:
468 case 32:
470 BYTE *srcpixel;
472 /* ==== 24/32 BGR bitmap to monochrome dib ==== */
473 if (bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff)
475 for (h = lines - 1; h >= 0; h--)
477 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
478 for (x = 0; x < dstwidth; x++, srcpixel+=4) {
479 if (!(x&7)) *bits = 0;
480 *bits |= (X11DRV_DIB_GetNearestIndex(colors, 2, srcpixel[2] , srcpixel[1], srcpixel[0]) << (7-(x&7)) );
481 if ((x&7)==7) bits++;
483 bits = (dstbits += linebytes);
486 /* ==== 24/32 RGB bitmap to monochrome dib ==== */
487 else if (bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000)
489 for (h = lines - 1; h >= 0; h--)
491 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
492 for (x = 0; x < dstwidth; x++, srcpixel+=4) {
493 if (!(x & 7)) *bits = 0;
494 *bits |= (X11DRV_DIB_GetNearestIndex(colors, 2, srcpixel[0] , srcpixel[1], srcpixel[2]) << (7-(x&7)) );
495 if ((x & 7) == 7) bits++;
497 bits = (dstbits += linebytes);
500 else goto notsupported;
502 break;
504 default: /* ? bit bmp -> monochrome DIB */
505 notsupported:
507 unsigned long white = (1 << bmpImage->bits_per_pixel) - 1;
509 FIXME("from %d bit bitmap with mask R,G,B %x,%x,%x to 1 bit DIB\n",
510 bmpImage->bits_per_pixel, (int)bmpImage->red_mask,
511 (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
513 for( h = lines - 1; h >= 0; h-- ) {
514 for( x = 0; x < dstwidth; x++ ) {
515 if (!(x&7)) *bits = 0;
516 *bits |= (XGetPixel( bmpImage, x, h) >= white)
517 << (7 - (x&7));
518 if ((x&7)==7) bits++;
520 bits = (dstbits += linebytes);
523 break;
527 /***********************************************************************
528 * X11DRV_DIB_SetImageBits_4
530 * SetDIBits for a 4-bit deep DIB.
532 static void X11DRV_DIB_SetImageBits_4( int lines, const BYTE *srcbits,
533 DWORD srcwidth, DWORD dstwidth, int left,
534 int *colors, XImage *bmpImage, DWORD linebytes)
536 DWORD i, x;
537 int h;
538 const BYTE *bits = srcbits + (left >> 1);
540 if(left & 1) {
541 left--;
542 dstwidth++;
545 if (lines > 0) {
546 for (h = lines-1; h >= 0; h--) {
547 for (i = dstwidth/2, x = left; i > 0; i--) {
548 BYTE pix = *bits++;
549 XPutPixel( bmpImage, x++, h, colors[pix >> 4] );
550 XPutPixel( bmpImage, x++, h, colors[pix & 0x0f] );
552 if (dstwidth & 1) XPutPixel( bmpImage, x, h, colors[*bits >> 4] );
553 srcbits += linebytes;
554 bits = srcbits + (left >> 1);
556 } else {
557 lines = -lines;
558 for (h = 0; h < lines; h++) {
559 for (i = dstwidth/2, x = left; i > 0; i--) {
560 BYTE pix = *bits++;
561 XPutPixel( bmpImage, x++, h, colors[pix >> 4] );
562 XPutPixel( bmpImage, x++, h, colors[pix & 0x0f] );
564 if (dstwidth & 1) XPutPixel( bmpImage, x, h, colors[*bits >> 4] );
565 srcbits += linebytes;
566 bits = srcbits + (left >> 1);
573 /***********************************************************************
574 * X11DRV_DIB_GetImageBits_4
576 * GetDIBits for a 4-bit deep DIB.
578 static void X11DRV_DIB_GetImageBits_4( int lines, BYTE *dstbits,
579 DWORD srcwidth, DWORD dstwidth,
580 RGBQUAD *colors, PALETTEENTRY *srccolors,
581 XImage *bmpImage, DWORD linebytes )
583 DWORD x;
584 int h;
585 BYTE *bits;
586 LPBYTE srcpixel;
588 if (lines < 0 )
590 lines = -lines;
591 dstbits = dstbits + ( linebytes * (lines-1) );
592 linebytes = -linebytes;
595 bits = dstbits;
597 switch(bmpImage->depth) {
599 case 1:
600 /* ==== monochrome bitmap to 4 colormap dib ==== */
601 case 4:
602 /* ==== 4 colormap bitmap to 4 colormap dib ==== */
603 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
605 PALETTEENTRY val;
607 for (h = lines-1; h >= 0; h--) {
608 for (x = 0; x < dstwidth; x++) {
609 if (!(x&1)) *bits = 0;
610 val = srccolors[XGetPixel(bmpImage, x, h)];
611 *bits |= (X11DRV_DIB_GetNearestIndex(colors, 16,
612 val.peRed,
613 val.peGreen,
614 val.peBlue) << (4-((x&1)<<2)));
615 if ((x&1)==1) bits++;
617 bits = (dstbits += linebytes);
620 else goto notsupported;
622 break;
624 case 8:
625 /* ==== 8 colormap bitmap to 4 colormap dib ==== */
626 if ( bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
628 PALETTEENTRY val;
630 for( h = lines - 1; h >= 0; h-- ) {
631 srcpixel = bmpImage->data + (h*bmpImage->bytes_per_line);
632 for( x = 0; x < dstwidth; x++ ) {
633 if (!(x&1)) *bits = 0;
634 val = srccolors[(int)*srcpixel++];
635 *bits |= ( X11DRV_DIB_GetNearestIndex(colors, 16,
636 val.peRed,
637 val.peGreen,
638 val.peBlue) << (4*(1-(x&1))) );
639 if ((x&1)==1) bits++;
641 bits = (dstbits += linebytes);
644 else goto notsupported;
646 break;
648 case 15:
650 LPWORD srcpixel;
651 WORD val;
653 /* ==== 555 BGR bitmap to 4 colormap dib ==== */
654 if (bmpImage->red_mask == 0x7c00 && bmpImage->blue_mask == 0x1f)
656 for( h = lines - 1; h >= 0; h--) {
657 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
658 for( x = 0; x < dstwidth; x++) {
659 if (!(x&1)) *bits = 0;
660 val = *srcpixel++;
661 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 16,
662 ((val >> 7) & 0xf8) |
663 ((val >> 12) & 0x7),
664 ((val >> 2) & 0xf8) |
665 ((val >> 7) & 0x3),
666 ((val << 3) & 0xf8) |
667 ((val >> 2) & 0x7) ) << ((1-(x&1))<<2) );
668 if ((x&1)==1) bits++;
670 bits = (dstbits += linebytes);
673 /* ==== 555 RGB bitmap to 4 colormap dib ==== */
674 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0x7c00)
676 for( h = lines - 1; h >= 0; h--)
678 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
679 for( x = 0; x < dstwidth; x++) {
680 if (!(x&1)) *bits = 0;
681 val = *srcpixel++;
682 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 16,
683 ((val << 3) & 0xf8) |
684 ((val >> 2) & 0x7),
685 ((val >> 2) & 0xfc) |
686 ((val >> 7) & 0x3),
687 ((val >> 7) & 0xf8) |
688 ((val >> 12) & 0x7) ) << ((1-(x&1))<<2) );
689 if ((x&1)==1) bits++;
691 bits = (dstbits += linebytes);
694 else goto notsupported;
696 break;
698 case 16:
700 LPWORD srcpixel;
701 WORD val;
703 /* ==== 565 BGR bitmap to 4 colormap dib ==== */
704 if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f)
706 for( h = lines - 1; h >= 0; h--)
708 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
709 for( x = 0; x < dstwidth; x++) {
710 if (!(x&1)) *bits = 0;
711 val = *srcpixel++;
712 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 16,
713 ((val >> 8) & 0xf8) |
714 ((val >> 13) & 0x7),
715 ((val >> 3) & 0xfc) |
716 ((val >> 9) & 0x3),
717 ((val << 3) & 0xf8) |
718 ((val >> 2) & 0x7) ) << ((1-(x&1))<<2) );
719 if ((x&1)==1) bits++;
721 bits = (dstbits += linebytes);
724 /* ==== 565 RGB bitmap to 4 colormap dib ==== */
725 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0xf800)
727 for( h = lines - 1; h >= 0; h--)
729 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
730 for( x = 0; x < dstwidth; x++) {
731 if (!(x&1)) *bits = 0;
732 val = *srcpixel++;
733 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 16,
734 ((val << 3) & 0xf8) |
735 ((val >> 2) & 0x7),
736 ((val >> 3) & 0xfc) |
737 ((val >> 9) & 0x3),
738 ((val >> 8) & 0xf8) |
739 ((val >> 13) & 0x7) ) << ((1-(x&1))<<2) );
740 if ((x&1)==1) bits++;
742 bits = (dstbits += linebytes);
745 else goto notsupported;
747 break;
749 case 24:
750 case 32:
752 BYTE *srcpixel;
754 /* ==== 24/32 BGR bitmap to 4 colormap dib ==== */
755 if (bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff)
757 for (h = lines - 1; h >= 0; h--)
759 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
760 for (x = 0; x < dstwidth; x+=2, srcpixel+=8) /* 2 pixels at a time */
761 *bits++ = (X11DRV_DIB_GetNearestIndex(colors, 16, srcpixel[2] , srcpixel[1], srcpixel[0]) << 4) |
762 X11DRV_DIB_GetNearestIndex(colors, 16, srcpixel[6] , srcpixel[5], srcpixel[4]);
763 bits = (dstbits += linebytes);
766 /* ==== 24/32 RGB bitmap to 4 colormap dib ==== */
767 else if (bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000)
769 for (h = lines - 1; h >= 0; h--)
771 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
772 for (x = 0; x < dstwidth; x+=2, srcpixel+=8) /* 2 pixels at a time */
773 *bits++ = (X11DRV_DIB_GetNearestIndex(colors, 16, srcpixel[0] , srcpixel[1], srcpixel[2]) << 4) |
774 X11DRV_DIB_GetNearestIndex(colors, 16, srcpixel[4] , srcpixel[5], srcpixel[6]);
775 bits = (dstbits += linebytes);
778 else goto notsupported;
780 break;
782 default: /* ? bit bmp -> 4 bit DIB */
783 notsupported:
784 FIXME("from %d bit bitmap with mask R,G,B %x,%x,%x to 4 bit DIB\n",
785 bmpImage->bits_per_pixel, (int)bmpImage->red_mask,
786 (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
787 for (h = lines-1; h >= 0; h--) {
788 for (x = 0; x < dstwidth/2; x++) {
789 *bits++ = (X11DRV_DIB_MapColor((int *)colors, 16,
790 XGetPixel( bmpImage, x++, h ), 0) << 4)
791 | (X11DRV_DIB_MapColor((int *)colors, 16,
792 XGetPixel( bmpImage, x++, h ), 0) & 0x0f);
794 if (dstwidth & 1)
795 *bits = (X11DRV_DIB_MapColor((int *)colors, 16,
796 XGetPixel( bmpImage, x++, h ), 0) << 4);
797 bits = (dstbits += linebytes);
799 break;
803 /***********************************************************************
804 * X11DRV_DIB_SetImageBits_RLE4
806 * SetDIBits for a 4-bit deep compressed DIB.
808 static void X11DRV_DIB_SetImageBits_RLE4( int lines, const BYTE *bits,
809 DWORD width, DWORD dstwidth,
810 int left, int *colors,
811 XImage *bmpImage )
813 int x = 0, c, length;
814 const BYTE *begin = bits;
816 lines--;
818 while ((int)lines >= 0) {
819 length = *bits++;
820 if (length) { /* encoded */
821 c = *bits++;
822 while (length--) {
823 if(x >= width) {
824 x = 0;
825 if(--lines < 0)
826 return;
828 XPutPixel(bmpImage, x++, lines, colors[c >>4]);
829 if (length) {
830 length--;
831 if(x >= width) {
832 x = 0;
833 if(--lines < 0)
834 return;
836 XPutPixel(bmpImage, x++, lines, colors[c & 0xf]);
839 } else {
840 length = *bits++;
841 switch (length) {
842 case 0: /* eol */
843 x = 0;
844 lines--;
845 continue;
847 case 1: /* eopicture */
848 return;
850 case 2: /* delta */
851 x += *bits++;
852 if(x >= width) {
853 FIXME_(x11drv)("x-delta is too large?\n");
854 return;
856 lines -= *bits++;
857 continue;
859 default: /* absolute */
860 while (length--) {
861 c = *bits++;
862 if(x >= width) {
863 x = 0;
864 if(--lines < 0)
865 return;
867 XPutPixel(bmpImage, x++, lines, colors[c >> 4]);
868 if (length) {
869 length--;
870 if(x >= width) {
871 x = 0;
872 if(--lines < 0)
873 return;
875 XPutPixel(bmpImage, x++, lines, colors[c & 0xf]);
878 if ((bits - begin) & 1)
879 bits++;
887 /***********************************************************************
888 * X11DRV_DIB_SetImageBits_8
890 * SetDIBits for an 8-bit deep DIB.
892 static void X11DRV_DIB_SetImageBits_8( int lines, const BYTE *srcbits,
893 DWORD srcwidth, DWORD dstwidth, int left,
894 const int *colors, XImage *bmpImage,
895 DWORD linebytes )
897 DWORD x;
898 int h, color;
899 const BYTE *bits;
901 dstwidth += left;
903 if (lines < 0 )
905 lines = -lines;
906 srcbits = srcbits + ( linebytes * (lines-1) );
907 linebytes = -linebytes;
910 bits = srcbits + left;
912 switch (bmpImage->depth) {
913 case 15:
914 case 16:
915 #if defined(__i386__) && defined(__GNUC__)
916 /* Some X servers might have 32 bit/ 16bit deep pixel */
917 if (lines && (dstwidth!=left) && (bmpImage->bits_per_pixel == 16))
919 for (h = lines ; h--; ) {
920 int _cl1,_cl2; /* temp outputs for asm below */
921 /* Borrowed from DirectDraw */
922 __asm__ __volatile__(
923 "xor %%eax,%%eax\n"
924 "cld\n"
925 "1:\n"
926 " lodsb\n"
927 " movw (%%edx,%%eax,4),%%ax\n"
928 " stosw\n"
929 " xor %%eax,%%eax\n"
930 " loop 1b\n"
931 :"=S" (bits), "=D" (_cl1), "=c" (_cl2)
932 :"S" (bits),
933 "D" (bmpImage->data+h*bmpImage->bytes_per_line+left*2),
934 "c" (dstwidth-left),
935 "d" (colors)
936 :"eax", "cc", "memory"
938 bits = (srcbits += linebytes) + left;
940 return;
942 break;
943 #endif
944 default:
945 break; /* use slow generic case below */
948 for (h = lines - 1; h >= 0; h--) {
949 for (x = left; x < dstwidth; x++, bits++) {
950 color = colors[*bits];
951 XPutPixel( bmpImage, x, h, colors[*bits] );
953 bits = (srcbits += linebytes) + left;
957 /***********************************************************************
958 * X11DRV_DIB_GetImageBits_8
960 * GetDIBits for an 8-bit deep DIB.
962 static void X11DRV_DIB_GetImageBits_8( int lines, BYTE *dstbits,
963 DWORD srcwidth, DWORD dstwidth,
964 RGBQUAD *colors, PALETTEENTRY *srccolors,
965 XImage *bmpImage, DWORD linebytes )
967 DWORD x;
968 int h;
969 BYTE *bits;
971 if (lines < 0 )
973 lines = -lines;
974 dstbits = dstbits + ( linebytes * (lines-1) );
975 linebytes = -linebytes;
978 bits = dstbits;
981 Hack for now
982 This condition is true when GetImageBits has been called by UpdateDIBSection.
983 For now, GetNearestIndex is too slow to support 256 colormaps, so we'll just use for
984 for GetDIBits calls. (In somes cases, in a updateDIBSection, the returned colors are bad too)
986 if (!srccolors) goto updatesection;
988 switch(bmpImage->depth) {
990 case 1:
991 /* ==== monochrome bitmap to 8 colormap dib ==== */
992 case 4:
993 /* ==== 4 colormap bitmap to 8 colormap dib ==== */
994 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
996 PALETTEENTRY val;
998 for (h = lines - 1; h >= 0; h--) {
999 for (x = 0; x < dstwidth; x++) {
1000 val = srccolors[XGetPixel(bmpImage, x, h)];
1001 *bits++ = X11DRV_DIB_GetNearestIndex(colors, 256, val.peRed,
1002 val.peGreen, val.peBlue);
1004 bits = (dstbits += linebytes);
1007 else goto notsupported;
1009 break;
1011 case 8:
1012 /* ==== 8 colormap bitmap to 8 colormap dib ==== */
1013 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
1015 BYTE *srcpixel;
1016 PALETTEENTRY val;
1018 for (h = lines - 1; h >= 0; h--) {
1019 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
1020 for (x = 0; x < dstwidth; x++) {
1021 val = srccolors[(int)*srcpixel++];
1022 *bits++ = X11DRV_DIB_GetNearestIndex(colors, 256, val.peRed,
1023 val.peGreen, val.peBlue);
1025 bits = (dstbits += linebytes);
1028 else goto notsupported;
1030 break;
1032 case 15:
1034 LPWORD srcpixel;
1035 WORD val;
1037 /* ==== 555 BGR bitmap to 8 colormap dib ==== */
1038 if (bmpImage->red_mask == 0x7c00 && bmpImage->blue_mask == 0x001f)
1040 for( h = lines - 1; h >= 0; h--)
1042 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
1043 for( x = 0; x < dstwidth; x++ )
1045 val = *srcpixel++;
1046 *bits++ = X11DRV_DIB_GetNearestIndex( colors, 256,
1047 ((val >> 7) & 0xf8) |
1048 ((val >> 12) & 0x7),
1049 ((val >> 2) & 0xf8) |
1050 ((val >> 7) & 0x3),
1051 ((val << 3) & 0xf8) |
1052 ((val >> 2) & 0x7) );
1054 bits = (dstbits += linebytes);
1057 /* ==== 555 RGB bitmap to 8 colormap dib ==== */
1058 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0x7c00)
1060 for( h = lines - 1; h >= 0; h--)
1062 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
1063 for( x = 0; x < dstwidth; x++ )
1065 val = *srcpixel++;
1066 *bits++ = X11DRV_DIB_GetNearestIndex( colors, 256,
1067 ((val << 3) & 0xf8) |
1068 ((val >> 2) & 0x7),
1069 ((val >> 2) & 0xf8) |
1070 ((val >> 7) & 0x3),
1071 ((val >> 7) & 0xf8) |
1072 ((val >> 12) & 0x7) );
1074 bits = (dstbits += linebytes);
1077 else goto notsupported;
1079 break;
1081 case 16:
1083 LPWORD srcpixel;
1084 WORD val;
1086 /* ==== 565 BGR bitmap to 8 colormap dib ==== */
1087 if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f)
1089 for( h = lines - 1; h >= 0; h--)
1091 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
1092 for( x = 0; x < dstwidth; x++ )
1094 val = *srcpixel++;
1095 *bits++ = X11DRV_DIB_GetNearestIndex( colors, 256,
1096 ((val >> 8) & 0xf8) |
1097 ((val >> 13) & 0x7),
1098 ((val >> 3) & 0xfc) |
1099 ((val >> 9) & 0x3),
1100 ((val << 3) & 0xf8) |
1101 ((val >> 2) & 0x7) );
1103 bits = (dstbits += linebytes);
1106 /* ==== 565 RGB bitmap to 8 colormap dib ==== */
1107 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0xf800)
1109 for( h = lines - 1; h >= 0; h--)
1111 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
1112 for( x = 0; x < dstwidth; x++ )
1114 val = *srcpixel++;
1115 *bits++ = X11DRV_DIB_GetNearestIndex( colors, 256,
1116 ((val << 3) & 0xf8) |
1117 ((val >> 2) & 0x7),
1118 ((val >> 3) & 0x00fc) |
1119 ((val >> 9) & 0x3),
1120 ((val >> 8) & 0x00f8) |
1121 ((val >> 13) & 0x7) );
1123 bits = (dstbits += linebytes);
1126 else goto notsupported;
1128 break;
1130 case 24:
1131 case 32:
1133 BYTE *srcpixel;
1135 /* ==== 24/32 BGR bitmap to 8 colormap dib ==== */
1136 if (bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff)
1138 for (h = lines - 1; h >= 0; h--)
1140 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
1141 for (x = 0; x < dstwidth; x++, srcpixel+=4)
1142 *bits++ = X11DRV_DIB_GetNearestIndex(colors, 256,
1143 srcpixel[2] , srcpixel[1], *srcpixel);
1144 bits = (dstbits += linebytes);
1147 /* ==== 24/32 RGB bitmap to 8 colormap dib ==== */
1148 else if (bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000)
1150 for (h = lines - 1; h >= 0; h--)
1152 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
1153 for (x = 0; x < dstwidth; x++, srcpixel+=4)
1154 *bits++ = X11DRV_DIB_GetNearestIndex(colors, 256,
1155 *srcpixel, srcpixel[1], srcpixel[2]);
1156 bits = (dstbits += linebytes);
1160 else goto notsupported;
1162 break;
1164 default: /* ? bit bmp -> 8 bit DIB */
1165 notsupported:
1166 FIXME("from %d bit bitmap with mask R,G,B %x,%x,%x to 8 bit DIB\n",
1167 bmpImage->depth, (int)bmpImage->red_mask,
1168 (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
1169 updatesection:
1170 for (h = lines - 1; h >= 0; h--) {
1171 for (x = 0; x < dstwidth; x++, bits++) {
1172 *bits = X11DRV_DIB_MapColor((int *)colors, 256,
1173 XGetPixel( bmpImage, x, h ), *bits);
1175 bits = (dstbits += linebytes);
1177 break;
1181 /***********************************************************************
1182 * X11DRV_DIB_SetImageBits_RLE8
1184 * SetDIBits for an 8-bit deep compressed DIB.
1186 * This function rewritten 941113 by James Youngman. WINE blew out when I
1187 * first ran it because my desktop wallpaper is a (large) RLE8 bitmap.
1189 * This was because the algorithm assumed that all RLE8 bitmaps end with the
1190 * 'End of bitmap' escape code. This code is very much laxer in what it
1191 * allows to end the expansion. Possibly too lax. See the note by
1192 * case RleDelta. BTW, MS's documentation implies that a correct RLE8
1193 * bitmap should end with RleEnd, but on the other hand, software exists
1194 * that produces ones that don't and Windows 3.1 doesn't complain a bit
1195 * about it.
1197 * (No) apologies for my English spelling. [Emacs users: c-indent-level=4].
1198 * James A. Youngman <mbcstjy@afs.man.ac.uk>
1199 * [JAY]
1202 enum Rle8_EscapeCodes
1205 * Apologies for polluting your file's namespace...
1207 RleEol = 0, /* End of line */
1208 RleEnd = 1, /* End of bitmap */
1209 RleDelta = 2 /* Delta */
1212 static void X11DRV_DIB_SetImageBits_RLE8( int lines, const BYTE *bits,
1213 DWORD width, DWORD dstwidth,
1214 int left, int *colors,
1215 XImage *bmpImage )
1217 int x; /* X-positon on each line. Increases. */
1218 int line; /* Line #. Starts at lines-1, decreases */
1219 const BYTE *pIn = bits; /* Pointer to current position in bits */
1220 BYTE length; /* The length pf a run */
1221 BYTE color_index; /* index into colors[] as read from bits */
1222 BYTE escape_code; /* See enum Rle8_EscapeCodes.*/
1223 int color; /* value of colour[color_index] */
1225 if (lines == 0) /* Let's hope this doesn't happen. */
1226 return;
1229 * Note that the bitmap data is stored by Windows starting at the
1230 * bottom line of the bitmap and going upwards. Within each line,
1231 * the data is stored left-to-right. That's the reason why line
1232 * goes from lines-1 to 0. [JAY]
1235 x = 0;
1236 line = lines-1;
1239 length = *pIn++;
1242 * If the length byte is not zero (which is the escape value),
1243 * We have a run of length pixels all the same colour. The colour
1244 * index is stored next.
1246 * If the length byte is zero, we need to read the next byte to
1247 * know what to do. [JAY]
1249 if (length != 0)
1252 * [Run-Length] Encoded mode
1254 color_index = (*pIn++); /* Get the colour index. */
1255 color = colors[color_index];
1257 while(length--)
1259 if (x>=dstwidth)
1261 x=0;
1262 line--;
1264 XPutPixel(bmpImage, x++, line, color);
1267 else
1270 * Escape codes (may be an absolute sequence though)
1272 escape_code = (*pIn++);
1273 switch(escape_code)
1275 case RleEol: /* =0, end of line */
1277 x = 0;
1278 line--;
1279 break;
1282 case RleEnd: /* =1, end of bitmap */
1285 * Not all RLE8 bitmaps end with this
1286 * code. For example, Paint Shop Pro
1287 * produces some that don't. That's (I think)
1288 * what caused the previous implementation to
1289 * fail. [JAY]
1291 line=-1; /* Cause exit from do loop. */
1292 break;
1295 case RleDelta: /* =2, a delta */
1298 * Note that deltaing to line 0
1299 * will cause an exit from the loop,
1300 * which may not be what is intended.
1301 * The fact that there is a delta in the bits
1302 * almost certainly implies that there is data
1303 * to follow. You may feel that we should
1304 * jump to the top of the loop to avoid exiting
1305 * in this case.
1307 * TODO: Decide what to do here in that case. [JAY]
1309 x += (*pIn++);
1310 line -= (*pIn++);
1311 if (line == 0)
1313 TRACE("Delta to last line of bitmap "
1314 "(wrongly?) causes loop exit\n");
1316 break;
1319 default: /* >2, switch to absolute mode */
1322 * Absolute Mode
1324 length = escape_code;
1325 while(length--)
1327 color_index = (*pIn++);
1328 if (x>=dstwidth)
1330 x=0;
1331 line--;
1333 XPutPixel(bmpImage, x++, line,
1334 colors[color_index]);
1338 * If you think for a moment you'll realise that the
1339 * only time we could ever possibly read an odd
1340 * number of bytes is when there is a 0x00 (escape),
1341 * a value >0x02 (absolute mode) and then an odd-
1342 * length run. Therefore this is the only place we
1343 * need to worry about it. Everywhere else the
1344 * bytes are always read in pairs. [JAY]
1346 if (escape_code & 1)
1347 pIn++; /* Throw away the pad byte. */
1348 break;
1350 } /* switch (escape_code) : Escape sequence */
1351 } /* process either an encoded sequence or an escape sequence */
1353 /* We expect to come here more than once per line. */
1354 } while (line >= 0); /* Do this until the bitmap is filled */
1357 * Everybody comes here at the end.
1358 * Check how we exited the loop and print a message if it's a bit odd.
1359 * [JAY]
1361 if ( (*(pIn-2) != 0/*escape*/) || (*(pIn-1)!= RleEnd) )
1363 TRACE("End-of-bitmap without (strictly) proper escape code. Last two "
1364 "bytes were: %02X %02X.\n", (int)*(pIn-2),(int)*(pIn-1));
1369 /***********************************************************************
1370 * X11DRV_DIB_SetImageBits_16
1372 * SetDIBits for a 16-bit deep DIB.
1374 static void X11DRV_DIB_SetImageBits_16( int lines, const BYTE *srcbits,
1375 DWORD srcwidth, DWORD dstwidth, int left,
1376 DC *dc, DWORD rSrc, DWORD gSrc, DWORD bSrc,
1377 XImage *bmpImage, DWORD linebytes )
1379 DWORD x;
1380 int h;
1382 if (lines < 0 )
1384 lines = -lines;
1385 srcbits = srcbits + ( linebytes * (lines-1));
1386 linebytes = -linebytes;
1389 switch ( bmpImage->depth )
1391 case 15:
1392 /* using same format as XImage */
1393 if (rSrc == bmpImage->red_mask && gSrc == bmpImage->green_mask && bSrc == bmpImage->blue_mask)
1394 for (h = lines - 1; h >= 0; h--, srcbits += linebytes)
1395 memcpy ( bmpImage->data + h * bmpImage->bytes_per_line + left*2, srcbits + left*2, dstwidth*2 );
1396 else /* We need to do a conversion from a 565 dib */
1398 LPDWORD dstpixel, ptr = (LPDWORD)(srcbits + left*2);
1399 DWORD val;
1400 int div = dstwidth % 2;
1402 for (h = lines - 1; h >= 0; h--) {
1403 dstpixel = (LPDWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1404 for (x = 0; x < dstwidth/2; x++) { /* Do 2 pixels at a time */
1405 val = *ptr++;
1406 *dstpixel++ = ((val >> 1) & 0x7fe07fe0) | (val & 0x001f001f); /* Red & Green & Blue */
1408 if (div != 0) /* Odd width? */
1409 *dstpixel = ((*(WORD *)ptr >> 1) & 0x7fe0) | (*(WORD *)ptr & 0x001f);
1410 ptr = (LPDWORD) ((srcbits += linebytes) + left*2);
1413 break;
1415 case 16:
1416 /* using same format as XImage */
1417 if (rSrc == bmpImage->red_mask && gSrc == bmpImage->green_mask && bSrc == bmpImage->blue_mask)
1418 for (h = lines - 1; h >= 0; h--, srcbits += linebytes)
1419 memcpy ( bmpImage->data + h * bmpImage->bytes_per_line + left*2, srcbits + left*2, dstwidth*2 );
1420 else /* We need to do a conversion from a 555 dib */
1422 LPDWORD dstpixel, ptr = (LPDWORD)(srcbits + left*2);
1423 DWORD val;
1424 int div = dstwidth % 2;
1426 for (h = lines - 1; h >= 0; h--) {
1427 dstpixel = (LPDWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1428 for (x = 0; x < dstwidth/2; x++) { /* Do 2 pixels at a time */
1429 val = *ptr++;
1430 *dstpixel++ = ((val << 1) & 0xffc0ffc0) | ((val >> 4) & 0x00200020) | /* Red & Green */
1431 (val & 0x001f001f); /* Blue */
1433 if (div != 0) /* Odd width? */
1434 *dstpixel = ((*(WORD *)ptr << 1) & 0xffc0) | ((*(WORD *)ptr >> 4) & 0x0020)
1435 | (*(WORD *)ptr & 0x001f);
1436 ptr = (LPDWORD) ((srcbits += linebytes) + left*2);
1439 break;
1441 case 24:
1442 case 32:
1444 DWORD *dstpixel;
1445 LPWORD ptr = (LPWORD)srcbits + left;
1446 DWORD val;
1448 /* ==== 555 BGR dib to 24/32 BGR bitmap ==== */
1449 if (bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff)
1451 for (h = lines - 1; h >= 0; h--) {
1452 dstpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line + left*4);
1453 for (x = 0; x < dstwidth; x++) {
1455 val = *ptr++;
1456 *dstpixel++ = ((val << 9) & 0xf80000) | ((val << 4) & 0x070000) | /* Red */
1457 ((val << 6) & 0x00f800) | ((val << 1) & 0x000700) | /* Green */
1458 ((val << 3) & 0x0000f8) | ((val >> 2) & 0x000007); /* Blue */
1460 ptr = (LPWORD)(srcbits += linebytes) + left;
1463 /* ==== 555 BGR dib to 24/32 RGB bitmap ==== */
1464 else if (bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000)
1466 for (h = lines - 1; h >= 0; h--) {
1467 dstpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line + left*4);
1468 for (x = 0; x < dstwidth; x++) {
1470 val = *ptr++;
1471 *dstpixel++ = ((val >> 7) & 0x0000f8) | ((val >> 12) & 0x000007) | /* Red */
1472 ((val << 6) & 0x00f800) | ((val << 1) & 0x000700) | /* Green */
1473 ((val << 19) & 0xf80000) | ((val >> 14) & 0x070000); /* Blue */
1475 ptr = (LPWORD)(srcbits += linebytes) + left;
1480 break;
1482 case 1:
1483 case 4:
1484 case 8:
1486 LPWORD ptr = (LPWORD)srcbits + left;
1487 WORD val;
1488 int sc1, sc2;
1490 /* Set color scaling values */
1491 if ( rSrc == 0x7c00 ) { sc1 = 7; sc2 = 2; } /* 555 dib */
1492 else { sc1 = 8; sc2 = 3; } /* 565 dib */
1494 for (h = lines - 1; h >= 0; h--) {
1495 for (x = left; x < dstwidth+left; x++) {
1496 val = *ptr++;
1497 XPutPixel( bmpImage, x, h,
1498 X11DRV_PALETTE_ToPhysical(dc, RGB(((val & rSrc) >> sc1), /* Red */
1499 ((val & gSrc) >> sc2), /* Green */
1500 ((val & bSrc) << 3)))); /* Blue */
1502 ptr = (LPWORD) (srcbits += linebytes) + left;
1505 break;
1507 default:
1508 FIXME("16 bit DIB %d bit bitmap\n", bmpImage->bits_per_pixel);
1509 break;
1515 /***********************************************************************
1516 * X11DRV_DIB_GetImageBits_16
1518 * GetDIBits for an 16-bit deep DIB.
1520 static void X11DRV_DIB_GetImageBits_16( int lines, BYTE *dstbits,
1521 DWORD dstwidth, DWORD srcwidth,
1522 PALETTEENTRY *srccolors,
1523 DWORD rDst, DWORD gDst, DWORD bDst,
1524 XImage *bmpImage, DWORD dibpitch )
1526 DWORD x;
1527 int h, rsc, gsc;
1529 DWORD linebytes = dibpitch;
1531 if (lines < 0 )
1533 lines = -lines;
1534 dstbits = dstbits + ( linebytes * (lines-1));
1535 linebytes = -linebytes;
1538 /* Set color scaling values */
1539 if ( rDst == 0x7c00 ) { rsc = 7; gsc = 2; } /* 555 dib */
1540 else { rsc = 8; gsc = 3; } /* 565 dib */
1542 switch ( bmpImage->depth )
1544 case 15:
1545 /* using same format as XImage */
1546 if (rDst == bmpImage->red_mask && bDst == bmpImage->blue_mask)
1547 for (h = lines - 1; h >= 0; h--, dstbits += linebytes)
1548 memcpy( dstbits, bmpImage->data + h*bmpImage->bytes_per_line, srcwidth*2 );
1549 /* reversed format (BGR <=> RGB) */
1550 else if (rDst == bmpImage->blue_mask && bDst == bmpImage->red_mask)
1552 LPDWORD srcpixel, ptr = (LPDWORD)dstbits;
1553 DWORD val;
1554 int div = srcwidth % 2;
1556 for (h = lines - 1; h >= 0; h--) {
1557 srcpixel = (LPDWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
1558 for (x = 0; x < srcwidth/2; x++) { /* Do 2 pixels at a time */
1559 val = *srcpixel++;
1560 *ptr++ = ((val << 10) & 0xf800f800) | (val & 0x03e003e0) | /* Red & Green */
1561 ((val >> 10) & 0x001f001f); /* Blue */
1563 if (div != 0) /* Odd width? */
1564 *ptr = ((*(WORD *)srcpixel << 1) & 0xffc0) | ((*(WORD *)srcpixel >> 4) & 0x0020) |
1565 (*(WORD *)srcpixel & 0x001f);
1566 ptr = (LPDWORD)(dstbits += linebytes);
1569 else goto notsupported;
1571 break;
1573 case 16:
1575 LPDWORD srcpixel, ptr = (LPDWORD)dstbits;
1576 DWORD val;
1577 int div = srcwidth % 2;
1579 /* using same format as XImage */
1580 if (rDst == bmpImage->red_mask && bDst == bmpImage->blue_mask)
1581 for (h = lines - 1; h >= 0; h--, dstbits += linebytes)
1582 memcpy( dstbits, bmpImage->data + h*bmpImage->bytes_per_line, srcwidth*2 );
1583 /* ==== 565 BGR bitmap to 555 BGR dib ==== */
1584 else if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f &&
1585 rDst == 0x7c00 && bDst == 0x001f)
1587 for (h = lines - 1; h >= 0; h--) {
1588 srcpixel = (LPDWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
1589 for (x = 0; x < srcwidth/2; x++) { /* Do 2 pixels at a time */
1590 val = *srcpixel++;
1591 *ptr++ = ((val >> 1) & 0x7fe07fe0) | /* Red & Green */
1592 (val & 0x001f001f); /* Blue */
1594 if (div != 0) /* Odd width? */
1595 *ptr = ((*(WORD *)srcpixel >> 1) & 0x7fe0) | (*(WORD *)srcpixel & 0x001f);
1596 ptr = (LPDWORD) (dstbits += linebytes);
1599 /* ==== 565 RGB bitmap to 555 BGR dib ==== */
1600 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0xf800 &&
1601 rDst == 0x7c00 && bDst == 0x001f)
1603 for (h = lines - 1; h >= 0; h--) {
1604 srcpixel = (LPDWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
1605 for (x = 0; x < srcwidth/2; x++) { /* Do 2 pixels at a time */
1606 val = *srcpixel++;
1607 *ptr++ = ((val << 10) & 0x7c007c00) | ((val >> 1) & 0x03e003e0) | /* Red & Green */
1608 ((val >> 11) & 0x001f001f); /* Blue */
1610 if (div != 0) /* Odd width? */
1611 *ptr = ((*(WORD *)srcpixel >> 1) & 0x7fe0) | (*(WORD *)srcpixel & 0x001f);
1612 ptr = (LPDWORD) (dstbits += linebytes);
1615 else goto notsupported;
1617 break;
1619 case 24:
1620 case 32:
1622 DWORD *srcpixel;
1623 LPWORD ptr = (LPWORD)dstbits;
1624 DWORD val;
1626 /* ==== 24/32 BGR bitmap ==== */
1627 if (bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff)
1629 int rsc2 = 16-rsc, gsc2 = 8-gsc;
1630 for (h = lines - 1; h >= 0; h--) {
1631 srcpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line);
1632 for (x = 0; x < srcwidth; x++, ptr++) {
1633 val = *srcpixel++;
1634 *ptr = ((val >> rsc2) & rDst) |
1635 ((val >> gsc2) & gDst) |
1636 ((val >> 3) & bDst);
1638 ptr = (LPWORD)(dstbits += linebytes);
1641 /* ==== 24/32 RGB bitmap ==== */
1642 else if (bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000)
1644 int gsc2 = 8-gsc;
1645 for (h = lines - 1; h >= 0; h--) {
1646 srcpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line);
1647 for (x = 0; x < srcwidth; x++, ptr++) {
1648 val = *srcpixel++;
1649 *ptr = ((val << rsc) & rDst) |
1650 ((val >> gsc2) & gDst) |
1651 ((val >> 19) & bDst);
1653 ptr = (LPWORD) (dstbits += linebytes);
1656 else goto notsupported;
1658 break;
1660 case 1:
1661 /* ==== monochrome bitmap ==== */
1662 case 4:
1663 /* ==== 4 colormap bitmap ==== */
1664 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
1666 LPWORD ptr = (LPWORD)dstbits;
1667 PALETTEENTRY val;
1669 for (h = lines - 1; h >= 0; h--) {
1670 for (x = 0; x < dstwidth; x++) {
1671 val = srccolors[XGetPixel(bmpImage, x, h)];
1672 *ptr++ = ((val.peRed << rsc) & rDst) |
1673 ((val.peGreen << gsc) & gDst) |
1674 ((val.peBlue >> 3) & bDst);
1676 ptr = (LPWORD)(dstbits += linebytes);
1679 else goto notsupported;
1681 break;
1683 case 8:
1684 /* ==== 8 colormap bitmap ==== */
1685 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
1687 LPWORD ptr = (LPWORD)dstbits;
1688 BYTE *srcpixel;
1689 PALETTEENTRY val;
1691 for (h = lines - 1; h >= 0; h--) {
1692 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
1693 for (x = 0; x < dstwidth; x++) {
1694 val = srccolors[(int)*srcpixel++];
1695 *ptr++ = ((val.peRed << rsc) & rDst) |
1696 ((val.peGreen << gsc) & gDst) |
1697 ((val.peBlue >> 3) & bDst);
1699 ptr = (LPWORD)(dstbits += linebytes);
1702 else goto notsupported;
1704 break;
1706 default:
1707 notsupported:
1709 BYTE r,g, b;
1710 LPWORD ptr = (LPWORD)dstbits;
1712 FIXME("from %d bit bitmap with mask R,G,B %lx,%lx,%lx to 16 bit DIB %lx,%lx,%lx\n",
1713 bmpImage->depth, bmpImage->red_mask,
1714 bmpImage->green_mask, bmpImage->blue_mask,
1715 rDst, gDst, bDst);
1717 for (h = lines - 1; h >= 0; h--)
1719 for (x = 0; x < dstwidth; x++, ptr++)
1721 COLORREF pixel = X11DRV_PALETTE_ToLogical( XGetPixel( bmpImage, x, h ) );
1722 r = (BYTE) GetRValue(pixel);
1723 g = (BYTE) GetGValue(pixel);
1724 b = (BYTE) GetBValue(pixel);
1725 *ptr = ( ((r << rsc) & rDst) | ((g << gsc) & gDst) | ((b >> 3) & bDst) );
1727 ptr = (LPWORD) (dstbits += linebytes);
1730 break;
1735 /***********************************************************************
1736 * X11DRV_DIB_SetImageBits_24
1738 * SetDIBits for a 24-bit deep DIB.
1740 static void X11DRV_DIB_SetImageBits_24( int lines, const BYTE *srcbits,
1741 DWORD srcwidth, DWORD dstwidth, int left,
1742 DC *dc, XImage *bmpImage, DWORD linebytes )
1744 DWORD x;
1745 int h;
1747 if (lines < 0 )
1749 lines = -lines;
1750 srcbits = srcbits + linebytes * (lines - 1);
1751 linebytes = -linebytes;
1754 switch ( bmpImage->depth )
1756 case 24:
1758 if (bmpImage->bits_per_pixel == 24) {
1759 int dstlinebytes = linebytes;
1760 BYTE *dstpixel;
1761 BYTE *ptr = (BYTE *)(srcbits+left*3);
1763 if (dstlinebytes < 0 ) dstlinebytes = -dstlinebytes;
1764 dstpixel = bmpImage->data + lines*dstlinebytes + left*3;
1765 for(h = lines ; h-- ; ) {
1766 dstpixel-=dstlinebytes;
1767 memcpy(dstpixel,ptr,dstwidth*3);
1768 ptr +=linebytes;
1770 break;
1773 case 32:
1775 if( bmpImage->blue_mask == 0xff && bmpImage->red_mask == 0xff0000 ) /* packed BGR to unpacked BGR */
1777 DWORD *dstpixel, val, buf;
1778 DWORD *ptr = (DWORD *)(srcbits + left*3);
1779 BYTE *bits;
1780 int div = dstwidth % 4;
1781 int divk;
1783 for(h = lines - 1; h >= 0; h--)
1785 dstpixel = (DWORD *) (bmpImage->data + h*bmpImage->bytes_per_line + left*4);
1787 for (x = 0; x < dstwidth/4; x++) { /* do 3 dwords source, 4 dwords dest at a time */
1788 buf = *ptr++;
1789 *dstpixel++ = buf&0x00ffffff; /* b1, g1, r1 */
1790 val = (buf >> 24); /* b2 */
1791 buf = *ptr++;
1792 *dstpixel++ = (val | (buf<<8)) &0x00ffffff; /* g2, r2 */
1793 val = (buf >> 16); /* b3, g3 */
1794 buf = *ptr++;
1795 *dstpixel++ = (val | (buf<<16)) &0x00ffffff; /* r3 */
1796 *dstpixel++ = (buf >> 8); /* b4, g4, r4 */
1798 for ( divk=div, bits=(BYTE*)ptr; divk>0; divk--, bits+=3 ) /* do remainder */
1800 *dstpixel++ = *(DWORD*)bits & 0x00ffffff; /* b, g, r */
1802 ptr = (DWORD*)((srcbits+=linebytes)+left*3);
1805 else if( bmpImage->blue_mask == 0xff0000 && bmpImage->red_mask == 0xff ) /* packed BGR to unpacked RGB */
1807 DWORD *dstpixel, val, buf;
1808 DWORD *ptr = (DWORD *)(srcbits + left*3);
1809 BYTE *bits;
1810 int div = dstwidth % 4;
1811 int divk;
1813 for(h = lines - 1; h >= 0; h--)
1815 dstpixel = (DWORD *) (bmpImage->data + h*bmpImage->bytes_per_line + left*4);
1817 for (x = 0; x < dstwidth/4; x++) { /* do 3 dwords source, 4 dwords dest at a time */
1818 buf = *ptr++;
1819 *dstpixel++ = ((buf&0xff)<<16) | (buf&0xff00) | ((buf&0xff0000)>>16); /* b1, g1, r1 */
1820 val = ((buf&0xff000000)>>8); /* b2 */
1821 buf = *ptr++;
1822 *dstpixel++ = val | ((buf&0xff)<<8) | ((buf&0xff00)>>8); /* g2, r2 */
1823 val = (buf&0xff0000) | ((buf&0xff000000)>>16); /* b3, g3 */
1824 buf = *ptr++;
1825 *dstpixel++ = val | (buf&0xff); /* r3 */
1826 *dstpixel++ = ((buf&0xff00)<<8) | ((buf&0xff0000)>>8) | (buf>>24); /* b4, g4, r4 */
1828 for ( divk=div, bits=(BYTE*)ptr; divk>0; divk--, bits+=3 ) /* do remainder */
1830 buf = *(DWORD*)bits;
1831 *dstpixel++ = ((buf&0xff)<<16) | (buf&0xff00) | ((buf&0xff0000)>>16); /* b, g, r */
1833 ptr = (DWORD*)((srcbits+=linebytes)+left*3);
1836 else
1837 goto notsupported;
1839 break;
1841 case 15:
1843 if( bmpImage->blue_mask == 0x7c00 && bmpImage->red_mask == 0x1f ) /* BGR888 to RGB555 */
1845 DWORD *ptr = (DWORD *)(srcbits + left*3), val;
1846 LPBYTE bits;
1847 LPWORD dstpixel;
1848 int div = dstwidth % 4;
1849 int divk;
1851 for (h = lines - 1; h >= 0; h--) { /* Do 4 pixels at a time */
1852 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1853 for (x = 0; x < dstwidth/4; x++) {
1854 *dstpixel++ = (WORD)((((val = *ptr++) << 7) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 19) & 0x1f));
1855 *dstpixel++ = (WORD)(((val >> 17) & 0x7c00) | (((val = *ptr++) << 2) & 0x03e0) | ((val >> 11) & 0x1f));
1856 *dstpixel++ = (WORD)(((val >> 9) & 0x07c00) | ((val >> 22) & 0x03e0) | (((val = *ptr++) >> 3) & 0x1f));
1857 *dstpixel++ = (WORD)(((val >> 1) & 0x07c00) | ((val >> 14) & 0x03e0) | ((val >> 27) & 0x1f));
1859 for (bits = (LPBYTE)ptr, divk=div; divk > 0; divk--, bits+=3) /* dstwidth not divisible by 4? */
1860 *dstpixel++ = (((WORD)bits[0] << 7) & 0x07c00) |
1861 (((WORD)bits[1] << 2) & 0x03e0) |
1862 (((WORD)bits[2] >> 3) & 0x001f);
1863 ptr = (DWORD *)((srcbits += linebytes) + left * 3);
1866 else if( bmpImage->blue_mask == 0x1f && bmpImage->red_mask == 0x7c00 ) /* BGR888 to BGR555 */
1868 DWORD *ptr = (DWORD *)(srcbits + left*3), val;
1869 LPBYTE bits;
1870 LPWORD dstpixel;
1871 int div = dstwidth % 4;
1872 int divk;
1874 for (h = lines - 1; h >= 0; h--) { /* Do 4 pixels at a time */
1875 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1876 for (x = 0; x < dstwidth/4; x++) {
1877 *dstpixel++ = (WORD)((((val = *ptr++) >> 3) & 0x1f) | ((val >> 6) & 0x03e0) | ((val >> 9) & 0x7c00));
1878 *dstpixel++ = (WORD)(((val >> 27) & 0x1f) | (((val = *ptr++) << 2) & 0x03e0) | ((val >> 1) & 0x7c00));
1879 *dstpixel++ = (WORD)(((val >> 19) & 0x1f) | ((val >> 22) & 0x03e0) | (((val = *ptr++) << 7) & 0x7c00));
1880 *dstpixel++ = (WORD)(((val >> 11) & 0x1f) | ((val >> 14) & 0x03e0) | ((val >> 17) & 0x7c00));
1882 for (bits = (LPBYTE)ptr, divk=div; divk > 0; divk--, bits+=3) /* dstwidth not divisible by 4? */
1883 *dstpixel++ = (((WORD)bits[2] << 7) & 0x07c00) |
1884 (((WORD)bits[1] << 2) & 0x03e0) |
1885 (((WORD)bits[0] >> 3) & 0x001f);
1886 ptr = (DWORD *)((srcbits += linebytes) + left * 3);
1889 else
1890 goto notsupported;
1892 break;
1894 case 16:
1896 DWORD *ptr = (DWORD *)(srcbits + left*3), val;
1897 LPBYTE bits;
1898 LPWORD dstpixel;
1899 int div = dstwidth % 4;
1900 int divk;
1902 if( bmpImage->blue_mask == 0x001f && bmpImage->red_mask == 0xf800 ) /* BGR888 to BGR565 */
1904 for (h = lines - 1; h >= 0; h--) { /* Do 4 pixels at a time */
1905 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1906 for (x = 0; x < dstwidth/4; x++) {
1907 *dstpixel++ = (WORD)((((val = *ptr++) >> 3) & 0x1f) | ((val >> 5) & 0x07e0) | ((val >> 8) & 0xf800));
1908 *dstpixel++ = (WORD)(((val >> 27) & 0x1f) | (((val = *ptr++) << 3) & 0x07e0) | ((val) & 0xf800));
1909 *dstpixel++ = (WORD)(((val >> 19) & 0x1f) | ((val >> 21) & 0x07e0) | (((val = *ptr++) << 8) & 0xf800));
1910 *dstpixel++ = (WORD)(((val >> 11) & 0x1f) | ((val >> 13) & 0x07e0) | ((val >> 16) & 0xf800));
1912 for ( bits = (LPBYTE)ptr, divk=div; divk > 0; divk--, bits+=3) /* dstwidth is not divisible by 4? */
1913 *dstpixel++ = (((WORD)bits[2] << 8) & 0xf800) |
1914 (((WORD)bits[1] << 3) & 0x07e0) |
1915 (((WORD)bits[0] >> 3) & 0x001f);
1916 ptr = (DWORD *)((srcbits += linebytes) + left * 3);
1919 else if( bmpImage->blue_mask == 0xf800 && bmpImage->red_mask == 0x001f ) /* BGR888 to RGB565 */
1921 for (h = lines - 1; h >= 0; h--) { /* Do 4 pixels at a time */
1922 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1923 for (x = 0; x < dstwidth/4; x++) {
1924 *dstpixel++ = (WORD)((((val = *ptr++) << 8) & 0xf800) | ((val >> 5) & 0x07e0) | ((val >> 19) & 0x1f));
1925 *dstpixel++ = (WORD)(((val >> 16) & 0xf800) | (((val = *ptr++) << 3) & 0x07e0) | ((val >> 11) & 0x1f));
1926 *dstpixel++ = (WORD)(((val >> 8) & 0xf800) | ((val >> 21) & 0x07e0) | (((val = *ptr++) >> 3) & 0x1f));
1927 *dstpixel++ = (WORD)((val & 0xf800) | ((val >> 13) & 0x07e0) | ((val >> 27) & 0x1f));
1929 for ( bits = (LPBYTE)ptr, divk=div; divk > 0; divk--, bits+=3) /* dstwidth is not divisible by 4? */
1930 *dstpixel++ = (((WORD)bits[0] << 8) & 0xf800) |
1931 (((WORD)bits[1] << 3) & 0x07e0) |
1932 (((WORD)bits[2] >> 3) & 0x001f);
1933 ptr = (DWORD *)((srcbits += linebytes) + left * 3);
1936 else
1937 goto notsupported;
1939 break;
1941 case 1:
1942 case 4:
1943 case 8:
1945 LPBYTE bits = (LPBYTE)srcbits + left*3;
1947 for (h = lines - 1; h >= 0; h--) {
1948 for (x = left; x < dstwidth+left; x++, bits+=3)
1949 XPutPixel( bmpImage, x, h,
1950 X11DRV_PALETTE_ToPhysical(dc, RGB(bits[2], bits[1], bits[0])));
1951 bits = (LPBYTE)(srcbits += linebytes) + left * 3;
1954 break;
1956 default:
1957 notsupported:
1958 FIXME("from 24 bit DIB to %d bit bitmap with mask R,G,B %x,%x,%x\n",
1959 bmpImage->bits_per_pixel, (int)bmpImage->red_mask,
1960 (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
1961 break;
1966 /***********************************************************************
1967 * X11DRV_DIB_GetImageBits_24
1969 * GetDIBits for an 24-bit deep DIB.
1971 static void X11DRV_DIB_GetImageBits_24( int lines, BYTE *dstbits,
1972 DWORD dstwidth, DWORD srcwidth,
1973 PALETTEENTRY *srccolors,
1974 XImage *bmpImage, DWORD linebytes )
1976 DWORD x, val;
1977 int h;
1979 if (lines < 0 )
1981 lines = -lines;
1982 dstbits = dstbits + ( linebytes * (lines-1) );
1983 linebytes = -linebytes;
1986 switch ( bmpImage->depth )
1988 case 24:
1990 if (bmpImage->bits_per_pixel == 24) {
1991 int tocopy = linebytes;
1992 BYTE *srcpixel;
1993 BYTE *ptr = (LPBYTE)dstbits;
1995 if (tocopy < 0 ) tocopy = -tocopy;
1996 srcpixel = bmpImage->data + lines*tocopy;
1997 for(h = lines ; h-- ; ) {
1998 srcpixel-=tocopy;
1999 memcpy(ptr,srcpixel,tocopy);
2000 ptr = (LPBYTE)(dstbits+=linebytes);
2002 break;
2005 case 32:
2007 DWORD *srcpixel, buf;
2008 LPBYTE bits;
2009 DWORD *ptr=(DWORD *)dstbits;
2010 int quotient = dstwidth / 4;
2011 int remainder = dstwidth % 4;
2012 int remk;
2014 /* ==== 24/32 BGR bitmap to 24 BGR dib==== */
2015 if( bmpImage->blue_mask == 0xff && bmpImage->red_mask == 0xff0000 )
2017 for(h = lines - 1; h >= 0; h--)
2019 srcpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line);
2021 for (x = 0; x < quotient; x++) { /* do 4 dwords source, 3 dwords dest at a time */
2022 buf = ((*srcpixel++)&0x00ffffff); /* b1, g1, r1*/
2023 *ptr++ = buf | ((*srcpixel)<<24); /* b2 */
2024 buf = ((*srcpixel++>>8)&0x0000ffff); /* g2, r2 */
2025 *ptr++ = buf | ((*srcpixel)<<16); /* b3, g3 */
2026 buf = ((*srcpixel++>>16)&0x000000ff); /* r3 */
2027 *ptr++ = buf | ((*srcpixel++)<<8); /* b4, g4, r4 */
2029 for ( remk=remainder, bits=(BYTE*)ptr; remk>0; remk--, bits+=3 ) /* do remainder */
2031 buf=*srcpixel++;
2032 *(WORD*)bits = buf; /* b, g */
2033 *(bits+2) = buf>>16; /* r */
2035 ptr = (DWORD*)(dstbits+=linebytes);
2039 /* ==== 24/32 RGB bitmap to 24 BGR dib ==== */
2040 else if( bmpImage->blue_mask == 0xff0000 && bmpImage->red_mask == 0xff )
2042 for(h = lines - 1; h >= 0; h--)
2044 srcpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line);
2046 for (x = 0; x < quotient; x++) { /* do 4 dwords source, 3 dwords dest at a time */
2047 buf = *srcpixel++;
2048 val = ((buf&0xff0000)>>16) | (buf&0xff00) | ((buf&0xff)<<16); /* b1, g1, r1 */
2049 buf = *srcpixel++;
2050 *ptr++ = val | ((buf&0xff0000)<<8); /* b2 */
2051 val = ((buf&0xff00)>>8) | ((buf&0xff)<<8); /* g2, r2 */
2052 buf = *srcpixel++;
2053 *ptr++ = val | (buf&0xff0000) | ((buf&0xff00)<<16); /* b3, g3 */
2054 val = (buf&0xff); /* r3 */
2055 buf = *srcpixel++;
2056 *ptr++ = val | ((buf&0xff0000)>>8) | ((buf&0xff00)<<8) | (buf<<24); /* b4, g4, r4 */
2058 for ( remk=remainder, bits=(BYTE*)ptr; remk>0; remk--, bits+=3 ) /* do remainder */
2060 buf=*srcpixel++;
2061 *(WORD*)bits = (buf&0xff00) | ((buf&0xff0000)>>16) ; /* b, g */
2062 *(bits+2) = buf; /* r */
2064 ptr = (DWORD*)(dstbits+=linebytes);
2067 else goto notsupported;
2069 break;
2071 case 15:
2073 LPWORD srcpixel;
2074 LPBYTE bits = dstbits;
2075 WORD val;
2077 /* ==== 555 BGR bitmap to 24 BGR dib ==== */
2078 if( bmpImage->blue_mask == 0x1f && bmpImage->red_mask == 0x7c00 )
2080 for (h = lines - 1; h >= 0; h--) {
2081 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2082 for (x = 0; x < srcwidth; x++, bits += 3) {
2083 val = *srcpixel++;
2084 bits[2] = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07)); /*Red*/
2085 bits[1] = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07)); /*Green*/
2086 bits[0] = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07)); /*Blue*/
2088 bits = (dstbits += linebytes);
2091 /* ==== 555 RGB bitmap to 24 RGB dib==== */
2092 else if( bmpImage->blue_mask == 0x7c00 && bmpImage->red_mask == 0x1f )
2094 for (h = lines - 1; h >= 0; h--) {
2095 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2096 for (x = 0; x < srcwidth; x++, bits += 3) {
2097 val = *srcpixel++;
2098 bits[0] = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07)); /*Red*/
2099 bits[1] = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07)); /*Green*/
2100 bits[2] = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07)); /*Blue*/
2102 bits = (dstbits += linebytes);
2105 else goto notsupported;
2107 break;
2109 case 16:
2111 LPWORD srcpixel;
2112 LPBYTE bits = dstbits;
2113 WORD val;
2115 /* ==== 565 BGR bitmap to 24 BGR dib ==== */
2116 if( bmpImage->blue_mask == 0x1f && bmpImage->red_mask == 0xf800 )
2118 for (h = lines - 1; h >= 0; h--) {
2119 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2120 for (x = 0; x < srcwidth; x++, bits += 3) {
2121 val = *srcpixel++;
2122 bits[2] = (BYTE)(((val >> 8) & 0xf8) | ((val >> 13) & 0x07)); /*Red*/
2123 bits[1] = (BYTE)(((val >> 3) & 0xfc) | ((val >> 9) & 0x03)); /*Green*/
2124 bits[0] = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07)); /*Blue*/
2126 bits = (dstbits += linebytes);
2129 /* ==== 565 RGB bitmap to 24 BGR dib ==== */
2130 else if( bmpImage->blue_mask == 0xf800 && bmpImage->red_mask == 0x1f )
2132 for (h = lines - 1; h >= 0; h--) {
2133 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2134 for (x = 0; x < srcwidth; x++, bits += 3) {
2135 val = *srcpixel++;
2136 bits[0] = (BYTE)(((val >> 8) & 0xf8) | ((val >> 13) & 0x07)); /*Red*/
2137 bits[1] = (BYTE)(((val >> 3) & 0xfc) | ((val >> 9) & 0x03)); /*Green*/
2138 bits[2] = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07)); /*Blue*/
2140 bits = (dstbits += linebytes);
2143 else goto notsupported;
2145 break;
2147 case 1:
2148 /* ==== monochrome bitmap to 24 BGR dib ==== */
2149 case 4:
2150 /* ==== 4 colormap bitmap to 24 BGR dib ==== */
2151 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
2153 LPBYTE bits = dstbits;
2154 PALETTEENTRY val;
2156 for (h = lines - 1; h >= 0; h--) {
2157 for (x = 0; x < dstwidth; x++) {
2158 val = srccolors[XGetPixel(bmpImage, x, h)];
2159 *bits++ = val.peBlue;
2160 *bits++ = val.peGreen;
2161 *bits++ = val.peRed;
2163 bits = (dstbits += linebytes);
2166 else goto notsupported;
2168 break;
2170 case 8:
2171 /* ==== 8 colormap bitmap to 24 BGR dib ==== */
2172 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask == 0 && srccolors)
2174 BYTE *srcpixel;
2175 LPBYTE bits = dstbits;
2176 PALETTEENTRY val;
2178 for (h = lines - 1; h >= 0; h--) {
2179 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
2180 for (x = 0; x < dstwidth; x++ ) {
2181 val = srccolors[(int)*srcpixel++];
2182 *bits++ = val.peBlue; /*Blue*/
2183 *bits++ = val.peGreen; /*Green*/
2184 *bits++ = val.peRed; /*Red*/
2186 bits = (dstbits += linebytes);
2189 else goto notsupported;
2191 break;
2193 default:
2194 notsupported:
2196 LPBYTE bits = dstbits;
2198 FIXME("from %d bit bitmap with mask R,G,B %x,%x,%x to 24 bit DIB\n",
2199 bmpImage->depth, (int)bmpImage->red_mask,
2200 (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
2201 for (h = lines - 1; h >= 0; h--)
2203 for (x = 0; x < dstwidth; x++, bits += 3)
2205 COLORREF pixel = X11DRV_PALETTE_ToLogical( XGetPixel( bmpImage, x, h ) );
2206 bits[0] = GetBValue(pixel);
2207 bits[1] = GetGValue(pixel);
2208 bits[2] = GetRValue(pixel);
2210 bits = (dstbits += linebytes);
2213 break;
2218 /***********************************************************************
2219 * X11DRV_DIB_SetImageBits_32
2221 * SetDIBits for a 32-bit deep DIB.
2223 static void X11DRV_DIB_SetImageBits_32( int lines, const BYTE *srcbits,
2224 DWORD srcwidth, DWORD dstwidth, int left,
2225 DC *dc, XImage *bmpImage,
2226 DWORD linebytes )
2228 DWORD x, *ptr;
2229 int h;
2231 if (lines < 0 )
2233 lines = -lines;
2234 srcbits = srcbits + ( linebytes * (lines-1) );
2235 linebytes = -linebytes;
2238 ptr = (DWORD *) srcbits + left;
2240 switch ( bmpImage->depth )
2242 case 32:
2243 /* ==== 32 BGR dib to 24/32 BGR bitmap ==== */
2244 if (bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff) {
2245 for (h = lines - 1; h >= 0; h--, srcbits+=linebytes) {
2246 memcpy( bmpImage->data + h * bmpImage->bytes_per_line, srcbits + left*4, dstwidth*4 );
2250 /* ==== 32 BGR dib to 24/32 RGB bitmap ==== */
2251 else if (bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000)
2253 DWORD *dstpixel;
2255 for (h = lines - 1; h >= 0; h--) {
2256 dstpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line);
2257 for (x = 0; x < dstwidth; x++, ptr++) {
2258 *dstpixel++ = ((*ptr << 16) & 0xff0000) | (*ptr & 0xff00) | ((*ptr >> 16) & 0xff);
2260 ptr = (DWORD *) (srcbits += linebytes) + left;
2263 else goto notsupported;
2265 break;
2267 case 24:
2268 /* ==== 32 BGR dib to 24 (888) BGR bitmap ==== */
2269 /* we need to check that source mask matches destination */
2270 if (bmpImage->bits_per_pixel == 32)
2272 for (h = lines - 1; h >= 0; h--, srcbits+=linebytes) {
2273 memcpy( bmpImage->data + h * bmpImage->bytes_per_line, srcbits + left*4, dstwidth*4 );
2276 else
2278 BYTE *bptr;
2280 ptr = (DWORD *) srcbits + left;
2281 bptr = bmpImage->data;
2283 for (h = lines - 1; h >= 0; h--) {
2284 for (x = 0; x < dstwidth; x++) {
2285 /* *ptr is a 32bit value */
2286 /* bptr points to first of 3 bytes */
2287 *bptr++ = (*ptr >> 16) & 0xff;
2288 *bptr++ = (*ptr >> 8) & 0xff;
2289 *bptr++ = (*ptr ) & 0xff;
2290 ptr++;
2292 ptr = (DWORD *) (srcbits += linebytes) + left;
2295 break;
2297 case 15:
2298 /* ==== 32 BGR dib to 555 BGR bitmap ==== */
2299 if (bmpImage->red_mask == 0x7c00 && bmpImage->blue_mask == 0x001f) {
2300 LPWORD dstpixel;
2302 for (h = lines - 1; h >= 0; h--) {
2303 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2304 for (x = 0; x < dstwidth; x++, ptr++) {
2305 *dstpixel++ = (WORD) (((*ptr >> 9) & 0x7c00) | ((*ptr >> 6) & 0x03e0) | ((*ptr >> 3) & 0x001f));
2307 ptr = (DWORD *) (srcbits += linebytes) + left;
2310 /* ==== 32 BGR dib to 555 RGB bitmap ==== */
2311 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0x7c00)
2313 LPWORD dstpixel;
2315 for (h = lines - 1; h >= 0; h--) {
2316 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2317 for (x = 0; x < dstwidth; x++, ptr++) {
2318 *dstpixel++ = (WORD) (((*ptr << 7) & 0x7c00) | ((*ptr >> 6) & 0x03e0) | ((*ptr >> 19) & 0x001f));
2320 ptr = (DWORD *) (srcbits += linebytes) + left;
2323 else goto notsupported;
2325 break;
2327 case 16:
2328 /* ==== 32 BGR dib to 565 BGR bitmap ==== */
2329 if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f)
2331 LPWORD dstpixel;
2333 for (h = lines - 1; h >= 0; h--) {
2334 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2335 for (x = 0; x < dstwidth; x++, ptr++) {
2336 *dstpixel++ = (WORD) (((*ptr >> 8) & 0xf800) | ((*ptr >> 5) & 0x07e0) | ((*ptr >> 3) & 0x001f));
2338 ptr = (DWORD *) (srcbits += linebytes) + left;
2341 /* ==== 32 BGR dib to 565 RGB bitmap ==== */
2342 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0xf800)
2344 LPWORD dstpixel;
2346 for (h = lines - 1; h >= 0; h--) {
2347 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2348 for (x = 0; x < dstwidth; x++, ptr++) {
2349 *dstpixel++ = (WORD) (((*ptr << 8) & 0xf800) | ((*ptr >> 5) & 0x07e0) | ((*ptr >> 19) & 0x001f));
2351 ptr = (DWORD *) (srcbits += linebytes) + left;
2354 else goto notsupported;
2356 break;
2358 case 1:
2359 case 4:
2360 case 8:
2362 LPBYTE bits = (LPBYTE)srcbits + left*4;
2364 for (h = lines - 1; h >= 0; h--) {
2365 for (x = left; x < dstwidth+left; x++, bits += 4)
2366 XPutPixel( bmpImage, x, h,
2367 X11DRV_PALETTE_ToPhysical(dc, RGB( bits[2], bits[1], *bits )));
2368 bits = (LPBYTE)(srcbits += linebytes) + left * 4;
2371 break;
2373 default:
2374 notsupported:
2375 FIXME("32 bit DIB %d bit bitmap\n", bmpImage->bits_per_pixel);
2376 break;
2381 /***********************************************************************
2382 * X11DRV_DIB_GetImageBits_32
2384 * GetDIBits for an 32-bit deep DIB.
2386 static void X11DRV_DIB_GetImageBits_32( int lines, BYTE *dstbits,
2387 DWORD dstwidth, DWORD srcwidth,
2388 PALETTEENTRY *srccolors,
2389 XImage *bmpImage, DWORD linebytes )
2391 DWORD x;
2392 int h;
2393 BYTE *bits;
2395 DWORD copybytes = srcwidth * 4;
2397 if (lines < 0 )
2399 lines = -lines;
2400 dstbits = dstbits + ( linebytes * (lines-1) );
2401 linebytes = -linebytes;
2404 bits = dstbits;
2406 switch ( bmpImage->depth )
2408 case 32:
2409 /* ==== 24/32 BGR bitmap to 32 BGR dib ==== */
2410 if ( bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff )
2411 for (h = lines - 1; h >= 0; h--, dstbits+=linebytes)
2412 memcpy( dstbits, bmpImage->data + h*bmpImage->bytes_per_line, copybytes );
2414 /* ==== 24/32 RGB bitmap to 32 BGR dib ==== */
2415 else if ( bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000 )
2417 LPBYTE srcbits;
2419 for (h = lines - 1; h >= 0; h--) {
2420 srcbits = bmpImage->data + h * bmpImage->bytes_per_line;
2421 for (x = 0; x < dstwidth; x++, bits+=4, srcbits+=2) {
2422 *(bits + 2) = *srcbits++;
2423 *(bits + 1) = *srcbits++;
2424 *bits = *srcbits;
2426 bits = (dstbits += linebytes);
2429 else goto notsupported;
2430 break;
2432 case 24:
2433 /* ==== 24 BGR bitmap to 32 (0888) BGR dib ==== */
2434 /* we need to check that source mask matches destination */
2436 DWORD *srcpixel;
2437 BYTE *bptr;
2438 DWORD srcdata;
2440 srcpixel = (DWORD *) dstbits;
2441 bptr = bmpImage->data;
2443 for (h = lines - 1; h >= 0; h--) {
2444 for (x = 0; x < dstwidth; x++) {
2445 /* *srcpixel is a 32bit value */
2446 /* bptr points to first of 3 bytes */
2447 srcdata = 0;
2448 srcdata = srcdata << 8 | *bptr++;
2449 srcdata = srcdata << 8 | *bptr++;
2450 srcdata = srcdata << 8 | *bptr++;
2452 *srcpixel++ = srcdata;
2454 srcpixel = (DWORD *) (dstbits += linebytes);
2457 break;
2459 case 15:
2461 LPWORD srcpixel;
2462 WORD val;
2464 /* ==== 555 BGR bitmap to 32 BGR dib ==== */
2465 if (bmpImage->red_mask == 0x7c00 && bmpImage->blue_mask == 0x001f)
2467 for (h = lines - 1; h >= 0; h--) {
2468 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2469 for (x = 0; x < dstwidth; x++, bits+=2) {
2470 val = *srcpixel++;
2471 *bits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x03)); /*Blue*/
2472 *bits++ = (BYTE)(((val >> 2) & 0xfc) | ((val >> 8) & 0x03)); /*Green*/
2473 *bits = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07)); /*Red*/
2475 bits = (dstbits += linebytes);
2478 /* ==== 555 RGB bitmap to 32 BGR dib ==== */
2479 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0x7c00)
2481 for (h = lines - 1; h >= 0; h--) {
2482 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2483 for (x = 0; x < dstwidth; x++, bits+=2) {
2484 val = *srcpixel++;
2485 *bits++ = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07));/*Blue*/
2486 *bits++ = (BYTE)(((val >> 2) & 0xfc) | ((val >> 8) & 0x03)); /*Green*/
2487 *bits = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x03)); /*Red*/
2489 bits = (dstbits += linebytes);
2492 else goto notsupported;
2494 break;
2496 case 16:
2498 LPWORD srcpixel;
2499 WORD val;
2501 /* ==== 565 BGR bitmap to 32 BGR dib ==== */
2502 if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f)
2504 for (h = lines - 1; h >= 0; h--) {
2505 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2506 for (x = 0; x < srcwidth; x++, bits+=2) {
2507 val = *srcpixel++;
2508 *bits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x03)); /*Blue*/
2509 *bits++ = (BYTE)(((val >> 3) & 0xfc) | ((val >> 9) & 0x03)); /*Green*/
2510 *bits = (BYTE)(((val >> 8) & 0xf8) | ((val >> 13) & 0x07)); /*Red*/
2512 bits = (dstbits += linebytes);
2515 /* ==== 565 RGB bitmap to 32 BGR dib ==== */
2516 else if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f)
2518 for (h = lines - 1; h >= 0; h--) {
2519 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2520 for (x = 0; x < srcwidth; x++, bits+=2) {
2521 val = *srcpixel++;
2522 *bits++ = (BYTE)(((val >> 8) & 0xf8) | ((val >> 13) & 0x07));/*Blue*/
2523 *bits++ = (BYTE)(((val >> 3) & 0xfc) | ((val >> 9) & 0x03)); /*Green*/
2524 *bits = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x03)); /*Red*/
2526 bits = (dstbits += linebytes);
2529 else goto notsupported;
2531 break;
2533 case 1:
2534 /* ==== monochrome bitmap to 32 BGR dib ==== */
2535 case 4:
2536 /* ==== 4 colormap bitmap to 32 BGR dib ==== */
2537 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
2539 PALETTEENTRY val;
2541 for (h = lines - 1; h >= 0; h--) {
2542 for (x = 0; x < dstwidth; x++) {
2543 val = srccolors[XGetPixel(bmpImage, x, h)];
2544 *bits++ = val.peBlue;
2545 *bits++ = val.peGreen;
2546 *bits++ = val.peRed;
2547 *bits++ = 0;
2549 bits = (dstbits += linebytes);
2552 else goto notsupported;
2554 break;
2556 case 8:
2557 /* ==== 8 colormap bitmap to 32 BGR dib ==== */
2558 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
2560 BYTE *srcpixel;
2561 PALETTEENTRY val;
2563 for (h = lines - 1; h >= 0; h--) {
2564 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
2565 for (x = 0; x < dstwidth; x++) {
2566 val = srccolors[(int)*srcpixel++];
2567 *bits++ = val.peBlue; /*Blue*/
2568 *bits++ = val.peGreen; /*Green*/
2569 *bits++ = val.peRed; /*Red*/
2570 *bits++ = 0;
2572 bits = (dstbits += linebytes);
2575 else goto notsupported;
2576 break;
2578 default:
2579 notsupported:
2580 FIXME("from %d bit bitmap with mask R,G,B %x,%x,%x to 32 bit DIB\n",
2581 bmpImage->depth, (int)bmpImage->red_mask,
2582 (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
2583 for (h = lines - 1; h >= 0; h--)
2585 for (x = 0; x < dstwidth; x++, bits += 4)
2587 COLORREF pixel = X11DRV_PALETTE_ToLogical( XGetPixel( bmpImage, x, h ) );
2588 bits[0] = GetBValue(pixel);
2589 bits[1] = GetGValue(pixel);
2590 bits[2] = GetRValue(pixel);
2592 bits = (dstbits += linebytes);
2594 break;
2598 /***********************************************************************
2599 * X11DRV_DIB_SetImageBits
2601 * Transfer the bits to an X image.
2602 * Helper function for SetDIBits() and SetDIBitsToDevice().
2603 * The Xlib critical section must be entered before calling this function.
2605 int X11DRV_DIB_SetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
2607 int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
2608 XImage *bmpImage;
2610 if (descr->image)
2611 bmpImage = descr->image;
2612 else {
2613 bmpImage = XCreateImage( display, X11DRV_GetVisual(), descr->depth, ZPixmap, 0, NULL,
2614 descr->infoWidth, lines, 32, 0 );
2615 bmpImage->data = calloc( lines, bmpImage->bytes_per_line );
2616 if(bmpImage->data == NULL) {
2617 ERR("Out of memory!\n");
2618 XDestroyImage( bmpImage );
2619 return lines;
2623 /* Transfer the pixels */
2624 switch(descr->infoBpp)
2626 case 1:
2627 X11DRV_DIB_SetImageBits_1( descr->lines, descr->bits, descr->infoWidth,
2628 descr->width, descr->xSrc, (int *)(descr->colorMap),
2629 bmpImage, descr->dibpitch );
2630 break;
2631 case 4:
2632 if (descr->compression) {
2633 XGetSubImage( display, descr->drawable, descr->xDest, descr->yDest,
2634 descr->width, descr->height, AllPlanes, ZPixmap,
2635 bmpImage, descr->xSrc, descr->ySrc );
2637 X11DRV_DIB_SetImageBits_RLE4( descr->lines, descr->bits,
2638 descr->infoWidth, descr->width,
2639 descr->xSrc, (int *)(descr->colorMap),
2640 bmpImage );
2641 } else
2642 X11DRV_DIB_SetImageBits_4( descr->lines, descr->bits,
2643 descr->infoWidth, descr->width,
2644 descr->xSrc, (int*)(descr->colorMap),
2645 bmpImage, descr->dibpitch );
2646 break;
2647 case 8:
2648 if (descr->compression) {
2649 XGetSubImage( display, descr->drawable, descr->xDest, descr->yDest,
2650 descr->width, descr->height, AllPlanes, ZPixmap,
2651 bmpImage, descr->xSrc, descr->ySrc );
2652 X11DRV_DIB_SetImageBits_RLE8( descr->lines, descr->bits,
2653 descr->infoWidth, descr->width,
2654 descr->xSrc, (int *)(descr->colorMap),
2655 bmpImage );
2656 } else
2657 X11DRV_DIB_SetImageBits_8( descr->lines, descr->bits,
2658 descr->infoWidth, descr->width,
2659 descr->xSrc, (int *)(descr->colorMap),
2660 bmpImage, descr->dibpitch );
2661 break;
2662 case 15:
2663 case 16:
2664 X11DRV_DIB_SetImageBits_16( descr->lines, descr->bits,
2665 descr->infoWidth, descr->width,
2666 descr->xSrc, descr->dc,
2667 descr->rMask, descr->gMask, descr->bMask,
2668 bmpImage, descr->dibpitch);
2669 break;
2670 case 24:
2671 X11DRV_DIB_SetImageBits_24( descr->lines, descr->bits,
2672 descr->infoWidth, descr->width,
2673 descr->xSrc, descr->dc, bmpImage,
2674 descr->dibpitch);
2675 break;
2676 case 32:
2677 X11DRV_DIB_SetImageBits_32( descr->lines, descr->bits,
2678 descr->infoWidth, descr->width,
2679 descr->xSrc, descr->dc,
2680 bmpImage, descr->dibpitch);
2681 break;
2682 default:
2683 WARN("(%d): Invalid depth\n", descr->infoBpp );
2684 break;
2687 if (descr->useShm)
2689 XShmPutImage( display, descr->drawable, descr->gc, bmpImage,
2690 descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
2691 descr->width, descr->height, FALSE );
2692 XSync( display, 0 );
2694 else
2695 XPutImage( display, descr->drawable, descr->gc, bmpImage,
2696 descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
2697 descr->width, descr->height );
2699 if (!descr->image) XDestroyImage( bmpImage );
2700 return lines;
2703 /***********************************************************************
2704 * X11DRV_DIB_GetImageBits
2706 * Transfer the bits from an X image.
2707 * The Xlib critical section must be entered before calling this function.
2709 int X11DRV_DIB_GetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
2711 int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
2712 XImage *bmpImage;
2714 if (descr->image)
2715 bmpImage = descr->image;
2716 else {
2717 bmpImage = XCreateImage( display, X11DRV_GetVisual(), descr->depth, ZPixmap, 0, NULL,
2718 descr->infoWidth, lines, 32, 0 );
2719 bmpImage->data = calloc( lines, bmpImage->bytes_per_line );
2720 if(bmpImage->data == NULL) {
2721 ERR("Out of memory!\n");
2722 XDestroyImage( bmpImage );
2723 return lines;
2726 TRACE("XGetSubImage(%p,%ld,%d,%d,%d,%d,%ld,%d,%p,%d,%d)\n",
2727 display, descr->drawable, descr->xSrc, descr->ySrc, descr->width,
2728 lines, AllPlanes, ZPixmap, bmpImage, descr->xDest, descr->yDest);
2729 XGetSubImage( display, descr->drawable, descr->xSrc, descr->ySrc,
2730 descr->width, lines, AllPlanes, ZPixmap,
2731 bmpImage, descr->xDest, descr->yDest );
2733 /* Transfer the pixels */
2734 switch(descr->infoBpp)
2736 case 1:
2737 X11DRV_DIB_GetImageBits_1( descr->lines,(LPVOID)descr->bits,
2738 descr->infoWidth, descr->width,
2739 descr->colorMap, descr->palentry,
2740 bmpImage, descr->dibpitch );
2741 break;
2743 case 4:
2744 if (descr->compression)
2745 FIXME("Compression not yet supported!\n");
2746 else
2747 X11DRV_DIB_GetImageBits_4( descr->lines,(LPVOID)descr->bits,
2748 descr->infoWidth, descr->width,
2749 descr->colorMap, descr->palentry,
2750 bmpImage, descr->dibpitch );
2751 break;
2753 case 8:
2754 if (descr->compression)
2755 FIXME("Compression not yet supported!\n");
2756 else
2757 X11DRV_DIB_GetImageBits_8( descr->lines, (LPVOID)descr->bits,
2758 descr->infoWidth, descr->width,
2759 descr->colorMap, descr->palentry,
2760 bmpImage, descr->dibpitch );
2761 break;
2762 case 15:
2763 case 16:
2764 X11DRV_DIB_GetImageBits_16( descr->lines, (LPVOID)descr->bits,
2765 descr->infoWidth,descr->width,
2766 descr->palentry,
2767 descr->rMask, descr->gMask, descr->bMask,
2768 bmpImage, descr->dibpitch );
2769 break;
2771 case 24:
2772 X11DRV_DIB_GetImageBits_24( descr->lines, (LPVOID)descr->bits,
2773 descr->infoWidth,descr->width,
2774 descr->palentry, bmpImage, descr->dibpitch);
2775 break;
2777 case 32:
2778 X11DRV_DIB_GetImageBits_32( descr->lines, (LPVOID)descr->bits,
2779 descr->infoWidth, descr->width,
2780 descr->palentry, bmpImage, descr->dibpitch);
2781 break;
2783 default:
2784 WARN("(%d): Invalid depth\n", descr->infoBpp );
2785 break;
2788 if (!descr->image) XDestroyImage( bmpImage );
2789 return lines;
2792 /*************************************************************************
2793 * X11DRV_SetDIBitsToDevice
2796 INT X11DRV_SetDIBitsToDevice( DC *dc, INT xDest, INT yDest, DWORD cx,
2797 DWORD cy, INT xSrc, INT ySrc,
2798 UINT startscan, UINT lines, LPCVOID bits,
2799 const BITMAPINFO *info, UINT coloruse )
2801 X11DRV_DIB_IMAGEBITS_DESCR descr;
2802 DWORD width, oldcy = cy;
2803 INT result;
2804 int height, tmpheight;
2805 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
2808 if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height,
2809 &descr.infoBpp, &descr.compression ) == -1)
2810 return 0;
2811 tmpheight = height;
2812 if (height < 0) height = -height;
2813 if (!lines || (startscan >= height)) return 0;
2814 if (startscan + lines > height) lines = height - startscan;
2815 if (ySrc < startscan) ySrc = startscan;
2816 else if (ySrc >= startscan + lines) return 0;
2817 if (xSrc >= width) return 0;
2818 if (ySrc + cy >= startscan + lines) cy = startscan + lines - ySrc;
2819 if (xSrc + cx >= width) cx = width - xSrc;
2820 if (!cx || !cy) return 0;
2822 X11DRV_SetupGCForText( dc ); /* To have the correct colors */
2823 TSXSetFunction(display, physDev->gc, X11DRV_XROPfunction[dc->ROPmode-1]);
2825 switch (descr.infoBpp)
2827 case 1:
2828 case 4:
2829 case 8:
2830 descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap(
2831 coloruse == DIB_PAL_COLORS ? dc : NULL, coloruse,
2832 dc->bitsPerPixel, info, &descr.nColorMap );
2833 if (!descr.colorMap) return 0;
2834 descr.rMask = descr.gMask = descr.bMask = 0;
2835 break;
2836 case 15:
2837 case 16:
2838 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
2839 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x03e0;
2840 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x001f;
2841 descr.colorMap = 0;
2842 break;
2844 case 24:
2845 descr.rMask = descr.gMask = descr.bMask = 0;
2846 descr.colorMap = 0;
2847 break;
2849 case 32:
2850 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
2851 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0xff00;
2852 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0xff;
2853 descr.colorMap = 0;
2854 break;
2857 descr.dc = dc;
2858 descr.bits = bits;
2859 descr.image = NULL;
2860 descr.palentry = NULL;
2861 descr.lines = tmpheight >= 0 ? lines : -lines;
2862 descr.infoWidth = width;
2863 descr.depth = dc->bitsPerPixel;
2864 descr.drawable = physDev->drawable;
2865 descr.gc = physDev->gc;
2866 descr.xSrc = xSrc;
2867 descr.ySrc = tmpheight >= 0 ? lines-(ySrc-startscan)-cy+(oldcy-cy)
2868 : ySrc - startscan;
2869 descr.xDest = dc->DCOrgX + XLPTODP( dc, xDest );
2870 descr.yDest = dc->DCOrgY + YLPTODP( dc, yDest ) +
2871 (tmpheight >= 0 ? oldcy-cy : 0);
2872 descr.width = cx;
2873 descr.height = cy;
2874 descr.useShm = FALSE;
2875 descr.dibpitch = ((width * descr.infoBpp + 31) &~31) / 8;
2877 EnterCriticalSection( &X11DRV_CritSection );
2878 result = CALL_LARGE_STACK( X11DRV_DIB_SetImageBits, &descr );
2879 LeaveCriticalSection( &X11DRV_CritSection );
2881 if (descr.infoBpp <= 8)
2882 HeapFree(GetProcessHeap(), 0, descr.colorMap);
2883 return result;
2886 /***********************************************************************
2887 * X11DRV_DIB_SetDIBits
2889 INT X11DRV_DIB_SetDIBits(
2890 BITMAPOBJ *bmp, DC *dc, UINT startscan,
2891 UINT lines, LPCVOID bits, const BITMAPINFO *info,
2892 UINT coloruse, HBITMAP hbitmap)
2894 X11DRV_DIB_IMAGEBITS_DESCR descr;
2895 int height, tmpheight;
2896 INT result;
2898 descr.dc = dc;
2900 if (DIB_GetBitmapInfo( &info->bmiHeader, &descr.infoWidth, &height,
2901 &descr.infoBpp, &descr.compression ) == -1)
2902 return 0;
2904 tmpheight = height;
2905 if (height < 0) height = -height;
2906 if (!lines || (startscan >= height))
2907 return 0;
2909 if (startscan + lines > height) lines = height - startscan;
2911 switch (descr.infoBpp)
2913 case 1:
2914 case 4:
2915 case 8:
2916 descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap(
2917 coloruse == DIB_PAL_COLORS ? descr.dc : NULL, coloruse,
2918 bmp->bitmap.bmBitsPixel,
2919 info, &descr.nColorMap );
2920 if (!descr.colorMap) return 0;
2921 descr.rMask = descr.gMask = descr.bMask = 0;
2922 break;
2923 case 15:
2924 case 16:
2925 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
2926 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x03e0;
2927 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x001f;
2928 descr.colorMap = 0;
2929 break;
2931 case 24:
2932 descr.rMask = descr.gMask = descr.bMask = 0;
2933 descr.colorMap = 0;
2934 break;
2936 case 32:
2937 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
2938 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0xff00;
2939 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0xff;
2940 descr.colorMap = 0;
2941 break;
2943 default: break;
2946 /* HACK for now */
2947 if(!bmp->physBitmap)
2948 X11DRV_CreateBitmap(hbitmap);
2950 descr.bits = bits;
2951 descr.image = NULL;
2952 descr.palentry = NULL;
2953 descr.lines = tmpheight >= 0 ? lines : -lines;
2954 descr.depth = bmp->bitmap.bmBitsPixel;
2955 descr.drawable = (Pixmap)bmp->physBitmap;
2956 descr.gc = BITMAP_GC(bmp);
2957 descr.xSrc = 0;
2958 descr.ySrc = 0;
2959 descr.xDest = 0;
2960 descr.yDest = height - startscan - lines;
2961 descr.width = bmp->bitmap.bmWidth;
2962 descr.height = lines;
2963 descr.useShm = FALSE;
2964 descr.dibpitch = ((descr.infoWidth * descr.infoBpp + 31) &~31) / 8;
2966 EnterCriticalSection( &X11DRV_CritSection );
2967 result = CALL_LARGE_STACK( X11DRV_DIB_SetImageBits, &descr );
2968 LeaveCriticalSection( &X11DRV_CritSection );
2970 if (descr.colorMap) HeapFree(GetProcessHeap(), 0, descr.colorMap);
2972 return result;
2975 /***********************************************************************
2976 * X11DRV_DIB_GetDIBits
2978 INT X11DRV_DIB_GetDIBits(
2979 BITMAPOBJ *bmp, DC *dc, UINT startscan,
2980 UINT lines, LPVOID bits, BITMAPINFO *info,
2981 UINT coloruse, HBITMAP hbitmap)
2983 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
2984 X11DRV_DIB_IMAGEBITS_DESCR descr;
2985 PALETTEOBJ * palette;
2986 int height;
2988 TRACE("%u scanlines of (%i,%i) -> (%i,%i) starting from %u\n",
2989 lines, bmp->bitmap.bmWidth, bmp->bitmap.bmHeight,
2990 (int)info->bmiHeader.biWidth, (int)info->bmiHeader.biHeight,
2991 startscan );
2993 if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->hPalette, PALETTE_MAGIC )))
2994 return 0;
2996 if( lines > bmp->bitmap.bmHeight ) lines = bmp->bitmap.bmHeight;
2998 height = info->bmiHeader.biHeight;
2999 if (height < 0) height = -height;
3000 if( lines > height ) lines = height;
3001 /* Top-down images have a negative biHeight, the scanlines of theses images
3002 * were inverted in X11DRV_DIB_GetImageBits_xx
3003 * To prevent this we simply change the sign of lines
3004 * (the number of scan lines to copy).
3005 * Negative lines are correctly handled by X11DRV_DIB_GetImageBits_xx.
3007 if( info->bmiHeader.biHeight < 0 && lines > 0) lines = -lines;
3009 if( startscan >= bmp->bitmap.bmHeight )
3011 lines = 0;
3012 goto done;
3015 if (DIB_GetBitmapInfo( &info->bmiHeader, &descr.infoWidth, &descr.lines,
3016 &descr.infoBpp, &descr.compression ) == -1)
3018 lines = 0;
3019 goto done;
3022 switch (descr.infoBpp)
3024 case 1:
3025 case 4:
3026 case 8:
3027 case 24:
3028 descr.rMask = descr.gMask = descr.bMask = 0;
3029 break;
3030 case 15:
3031 case 16:
3032 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
3033 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x03e0;
3034 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x001f;
3035 break;
3037 case 32:
3038 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
3039 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0xff00;
3040 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0xff;
3041 break;
3044 /* Hack for now */
3045 if(!bmp->physBitmap)
3046 X11DRV_CreateBitmap(hbitmap);
3049 descr.dc = dc;
3050 descr.palentry = palette->logpalette.palPalEntry;
3051 descr.bits = bits;
3052 descr.image = NULL;
3053 descr.lines = lines;
3054 descr.depth = bmp->bitmap.bmBitsPixel;
3055 descr.drawable = (Pixmap)bmp->physBitmap;
3056 descr.gc = BITMAP_GC(bmp);
3057 descr.width = bmp->bitmap.bmWidth;
3058 descr.height = bmp->bitmap.bmHeight;
3059 descr.colorMap = info->bmiColors;
3060 descr.xDest = 0;
3061 descr.yDest = 0;
3062 descr.xSrc = 0;
3064 if (descr.lines > 0)
3066 descr.ySrc = (descr.height-1) - (startscan + (lines-1));
3068 else
3070 descr.ySrc = startscan;
3072 #ifdef HAVE_LIBXXSHM
3073 descr.useShm = dib ? (dib->shminfo.shmid != -1) : FALSE;
3074 #else
3075 descr.useShm = FALSE;
3076 #endif
3077 descr.dibpitch = dib ? (dib->dibSection.dsBm.bmWidthBytes)
3078 : (((descr.infoWidth * descr.infoBpp + 31) &~31) / 8);
3080 EnterCriticalSection( &X11DRV_CritSection );
3082 CALL_LARGE_STACK( X11DRV_DIB_GetImageBits, &descr );
3084 LeaveCriticalSection( &X11DRV_CritSection );
3086 if(info->bmiHeader.biSizeImage == 0) /* Fill in biSizeImage */
3087 info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(
3088 info->bmiHeader.biWidth,
3089 info->bmiHeader.biHeight,
3090 info->bmiHeader.biBitCount );
3092 info->bmiHeader.biCompression = 0;
3094 done:
3095 GDI_ReleaseObj( dc->hPalette );
3097 return lines;
3100 /***********************************************************************
3101 * DIB_DoProtectDIBSection
3103 static void X11DRV_DIB_DoProtectDIBSection( BITMAPOBJ *bmp, DWORD new_prot )
3105 DIBSECTION *dib = bmp->dib;
3106 INT effHeight = dib->dsBm.bmHeight >= 0? dib->dsBm.bmHeight
3107 : -dib->dsBm.bmHeight;
3108 /* use the biSizeImage data as the memory size only if we're dealing with a
3109 compressed image where the value is set. Otherwise, calculate based on
3110 width * height */
3111 INT totalSize = dib->dsBmih.biSizeImage && dib->dsBmih.biCompression != BI_RGB
3112 ? dib->dsBmih.biSizeImage
3113 : dib->dsBm.bmWidthBytes * effHeight;
3114 DWORD old_prot;
3116 VirtualProtect(dib->dsBm.bmBits, totalSize, new_prot, &old_prot);
3117 TRACE("Changed protection from %ld to %ld\n", old_prot, new_prot);
3120 /***********************************************************************
3121 * X11DRV_DIB_DoUpdateDIBSection
3123 static void X11DRV_DIB_DoUpdateDIBSection(BITMAPOBJ *bmp, BOOL toDIB)
3125 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
3126 X11DRV_DIB_IMAGEBITS_DESCR descr;
3128 if (DIB_GetBitmapInfo( &dib->dibSection.dsBmih, &descr.infoWidth, &descr.lines,
3129 &descr.infoBpp, &descr.compression ) == -1)
3130 return;
3132 descr.dc = NULL;
3133 descr.palentry = NULL;
3134 descr.image = dib->image;
3135 descr.colorMap = (RGBQUAD *)dib->colorMap;
3136 descr.nColorMap = dib->nColorMap;
3137 descr.bits = dib->dibSection.dsBm.bmBits;
3138 descr.depth = bmp->bitmap.bmBitsPixel;
3140 switch (descr.infoBpp)
3142 case 1:
3143 case 4:
3144 case 8:
3145 case 24:
3146 descr.rMask = descr.gMask = descr.bMask = 0;
3147 break;
3148 case 15:
3149 case 16:
3150 descr.rMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[0] : 0x7c00;
3151 descr.gMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[1] : 0x03e0;
3152 descr.bMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[2] : 0x001f;
3153 break;
3155 case 32:
3156 descr.rMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[0] : 0xff;
3157 descr.gMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[1] : 0xff00;
3158 descr.bMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[2] : 0xff0000;
3159 break;
3162 /* Hack for now */
3163 descr.drawable = (Pixmap)bmp->physBitmap;
3164 descr.gc = BITMAP_GC(bmp);
3165 descr.xSrc = 0;
3166 descr.ySrc = 0;
3167 descr.xDest = 0;
3168 descr.yDest = 0;
3169 descr.width = bmp->bitmap.bmWidth;
3170 descr.height = bmp->bitmap.bmHeight;
3171 #ifdef HAVE_LIBXXSHM
3172 descr.useShm = (dib->shminfo.shmid != -1);
3173 #else
3174 descr.useShm = FALSE;
3175 #endif
3176 descr.dibpitch = dib->dibSection.dsBm.bmWidthBytes;
3178 if (toDIB)
3180 TRACE("Copying from Pixmap to DIB bits\n");
3181 EnterCriticalSection( &X11DRV_CritSection );
3182 CALL_LARGE_STACK( X11DRV_DIB_GetImageBits, &descr );
3183 LeaveCriticalSection( &X11DRV_CritSection );
3185 else
3187 TRACE("Copying from DIB bits to Pixmap\n");
3188 EnterCriticalSection( &X11DRV_CritSection );
3189 CALL_LARGE_STACK( X11DRV_DIB_SetImageBits, &descr );
3190 LeaveCriticalSection( &X11DRV_CritSection );
3194 /***********************************************************************
3195 * X11DRV_DIB_FaultHandler
3197 static BOOL X11DRV_DIB_FaultHandler( LPVOID res, LPCVOID addr )
3199 BITMAPOBJ *bmp;
3200 INT state;
3202 bmp = (BITMAPOBJ *)GDI_GetObjPtr( (HBITMAP)res, BITMAP_MAGIC );
3203 if (!bmp) return FALSE;
3205 state = X11DRV_DIB_Lock(bmp, DIB_Status_None, FALSE);
3206 if (state != DIB_Status_InSync) {
3207 /* no way to tell whether app needs read or write yet,
3208 * try read first */
3209 X11DRV_DIB_Coerce(bmp, DIB_Status_InSync, FALSE);
3210 } else {
3211 /* hm, apparently the app must have write access */
3212 X11DRV_DIB_Coerce(bmp, DIB_Status_AppMod, FALSE);
3214 X11DRV_DIB_Unlock(bmp, TRUE);
3216 GDI_ReleaseObj( (HBITMAP)res );
3217 return TRUE;
3220 /***********************************************************************
3221 * X11DRV_DIB_Coerce
3223 INT X11DRV_DIB_Coerce(BITMAPOBJ *bmp, INT req, BOOL lossy)
3225 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
3226 INT ret = DIB_Status_None;
3228 if (dib) {
3229 EnterCriticalSection(&(dib->lock));
3230 ret = dib->status;
3231 switch (req) {
3232 case DIB_Status_GdiMod:
3233 /* GDI access - request to draw on pixmap */
3234 switch (dib->status)
3236 default:
3237 case DIB_Status_None:
3238 dib->p_status = DIB_Status_GdiMod;
3239 X11DRV_DIB_DoUpdateDIBSection( bmp, FALSE );
3240 break;
3242 case DIB_Status_GdiMod:
3243 TRACE("GdiMod requested in status GdiMod\n" );
3244 break;
3246 case DIB_Status_InSync:
3247 TRACE("GdiMod requested in status InSync\n" );
3248 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
3249 dib->status = DIB_Status_GdiMod;
3250 dib->p_status = DIB_Status_InSync;
3251 break;
3253 case DIB_Status_AuxMod:
3254 TRACE("GdiMod requested in status AuxMod\n" );
3255 if (lossy) dib->status = DIB_Status_GdiMod;
3256 else (*dib->copy_aux)(dib->aux_ctx, DIB_Status_GdiMod);
3257 dib->p_status = DIB_Status_AuxMod;
3258 if (dib->status != DIB_Status_AppMod) {
3259 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
3260 break;
3262 /* fall through if copy_aux() had to change to AppMod state */
3264 case DIB_Status_AppMod:
3265 TRACE("GdiMod requested in status AppMod\n" );
3266 if (!lossy) {
3267 /* make it readonly to avoid app changing data while we copy */
3268 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
3269 X11DRV_DIB_DoUpdateDIBSection( bmp, FALSE );
3271 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
3272 dib->p_status = DIB_Status_AppMod;
3273 dib->status = DIB_Status_GdiMod;
3274 break;
3276 break;
3278 case DIB_Status_InSync:
3279 /* App access - request access to read DIB surface */
3280 /* (typically called from signal handler) */
3281 switch (dib->status)
3283 default:
3284 case DIB_Status_None:
3285 /* shouldn't happen from signal handler */
3286 break;
3288 case DIB_Status_AuxMod:
3289 TRACE("InSync requested in status AuxMod\n" );
3290 if (lossy) dib->status = DIB_Status_InSync;
3291 else {
3292 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
3293 (*dib->copy_aux)(dib->aux_ctx, DIB_Status_InSync);
3295 if (dib->status != DIB_Status_GdiMod) {
3296 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
3297 break;
3299 /* fall through if copy_aux() had to change to GdiMod state */
3301 case DIB_Status_GdiMod:
3302 TRACE("InSync requested in status GdiMod\n" );
3303 if (!lossy) {
3304 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
3305 X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
3307 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
3308 dib->status = DIB_Status_InSync;
3309 break;
3311 case DIB_Status_InSync:
3312 TRACE("InSync requested in status InSync\n" );
3313 /* shouldn't happen from signal handler */
3314 break;
3316 case DIB_Status_AppMod:
3317 TRACE("InSync requested in status AppMod\n" );
3318 /* no reason to do anything here, and this
3319 * shouldn't happen from signal handler */
3320 break;
3322 break;
3324 case DIB_Status_AppMod:
3325 /* App access - request access to write DIB surface */
3326 /* (typically called from signal handler) */
3327 switch (dib->status)
3329 default:
3330 case DIB_Status_None:
3331 /* shouldn't happen from signal handler */
3332 break;
3334 case DIB_Status_AuxMod:
3335 TRACE("AppMod requested in status AuxMod\n" );
3336 if (lossy) dib->status = DIB_Status_AppMod;
3337 else {
3338 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
3339 (*dib->copy_aux)(dib->aux_ctx, DIB_Status_AppMod);
3341 if (dib->status != DIB_Status_GdiMod)
3342 break;
3343 /* fall through if copy_aux() had to change to GdiMod state */
3345 case DIB_Status_GdiMod:
3346 TRACE("AppMod requested in status GdiMod\n" );
3347 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
3348 if (!lossy) X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
3349 /* fall through */
3351 case DIB_Status_InSync:
3352 TRACE("AppMod requested in status InSync\n" );
3353 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
3354 dib->status = DIB_Status_AppMod;
3355 break;
3357 case DIB_Status_AppMod:
3358 TRACE("AppMod requested in status AppMod\n" );
3359 /* shouldn't happen from signal handler */
3360 break;
3362 break;
3364 case DIB_Status_AuxMod:
3365 if (dib->status == DIB_Status_None) {
3366 dib->p_status = req;
3367 } else {
3368 if (dib->status != DIB_Status_AuxMod)
3369 dib->p_status = dib->status;
3370 dib->status = DIB_Status_AuxMod;
3372 break;
3373 /* it is up to the caller to do the copy/conversion, probably
3374 * using the return value to decide where to copy from */
3376 LeaveCriticalSection(&(dib->lock));
3378 return ret;
3381 /***********************************************************************
3382 * X11DRV_DIB_Lock
3384 INT X11DRV_DIB_Lock(BITMAPOBJ *bmp, INT req, BOOL lossy)
3386 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
3387 INT ret = DIB_Status_None;
3389 if (dib) {
3390 EnterCriticalSection(&(dib->lock));
3391 ret = dib->status;
3392 if (req != DIB_Status_None)
3393 X11DRV_DIB_Coerce(bmp, req, lossy);
3395 return ret;
3398 /***********************************************************************
3399 * X11DRV_DIB_Unlock
3401 void X11DRV_DIB_Unlock(BITMAPOBJ *bmp, BOOL commit)
3403 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
3405 if (dib) {
3406 switch (dib->status)
3408 default:
3409 case DIB_Status_None:
3410 /* in case anyone is wondering, this is the "signal handler doesn't
3411 * work" case, where we always have to be ready for app access */
3412 if (commit) {
3413 switch (dib->p_status)
3415 case DIB_Status_AuxMod:
3416 TRACE("Unlocking and syncing from AuxMod\n" );
3417 (*dib->copy_aux)(dib->aux_ctx, DIB_Status_AppMod);
3418 if (dib->status != DIB_Status_None) {
3419 dib->p_status = dib->status;
3420 dib->status = DIB_Status_None;
3422 if (dib->p_status != DIB_Status_GdiMod)
3423 break;
3424 /* fall through if copy_aux() had to change to GdiMod state */
3426 case DIB_Status_GdiMod:
3427 TRACE("Unlocking and syncing from GdiMod\n" );
3428 X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
3429 break;
3431 default:
3432 TRACE("Unlocking without needing to sync\n" );
3433 break;
3436 else TRACE("Unlocking with no changes\n");
3437 dib->p_status = DIB_Status_None;
3438 break;
3440 case DIB_Status_GdiMod:
3441 TRACE("Unlocking in status GdiMod\n" );
3442 /* DIB was protected in Coerce */
3443 if (!commit) {
3444 /* no commit, revert to InSync if applicable */
3445 if ((dib->p_status == DIB_Status_InSync) ||
3446 (dib->p_status == DIB_Status_AppMod)) {
3447 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
3448 dib->status = DIB_Status_InSync;
3451 break;
3453 case DIB_Status_InSync:
3454 TRACE("Unlocking in status InSync\n" );
3455 /* DIB was already protected in Coerce */
3456 break;
3458 case DIB_Status_AppMod:
3459 TRACE("Unlocking in status AppMod\n" );
3460 /* DIB was already protected in Coerce */
3461 /* this case is ordinary only called from the signal handler,
3462 * so we don't bother to check for !commit */
3463 break;
3465 case DIB_Status_AuxMod:
3466 TRACE("Unlocking in status AuxMod\n" );
3467 if (commit) {
3468 /* DIB may need protection now */
3469 if ((dib->p_status == DIB_Status_InSync) ||
3470 (dib->p_status == DIB_Status_AppMod))
3471 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
3472 } else {
3473 /* no commit, revert to previous state */
3474 if (dib->p_status != DIB_Status_None)
3475 dib->status = dib->p_status;
3476 /* no protections changed */
3478 dib->p_status = DIB_Status_None;
3479 break;
3481 LeaveCriticalSection(&(dib->lock));
3485 /***********************************************************************
3486 * X11DRV_CoerceDIBSection
3488 INT X11DRV_CoerceDIBSection(DC *dc, INT req, BOOL lossy)
3490 BITMAPOBJ *bmp;
3491 INT ret;
3493 if (!dc) return DIB_Status_None;
3494 if (!(dc->flags & DC_MEMORY)) return DIB_Status_None;
3496 bmp = (BITMAPOBJ *)GDI_GetObjPtr( dc->hBitmap, BITMAP_MAGIC );
3497 ret = X11DRV_DIB_Coerce(bmp, req, lossy);
3498 GDI_ReleaseObj( dc->hBitmap );
3499 return ret;
3502 /***********************************************************************
3503 * X11DRV_LockDIBSection2
3505 INT X11DRV_LockDIBSection2(HBITMAP hBmp, INT req, BOOL lossy)
3507 BITMAPOBJ *bmp;
3508 INT ret;
3510 bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
3511 ret = X11DRV_DIB_Lock(bmp, req, lossy);
3512 GDI_ReleaseObj( hBmp );
3513 return ret;
3516 /***********************************************************************
3517 * X11DRV_UnlockDIBSection2
3519 void X11DRV_UnlockDIBSection2(HBITMAP hBmp, BOOL commit)
3521 BITMAPOBJ *bmp;
3523 bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
3524 X11DRV_DIB_Unlock(bmp, commit);
3525 GDI_ReleaseObj( hBmp );
3528 /***********************************************************************
3529 * X11DRV_LockDIBSection
3531 INT X11DRV_LockDIBSection(DC *dc, INT req, BOOL lossy)
3533 if (!dc) return DIB_Status_None;
3534 if (!(dc->flags & DC_MEMORY)) return DIB_Status_None;
3536 return X11DRV_LockDIBSection2( dc->hBitmap, req, lossy );
3539 /***********************************************************************
3540 * X11DRV_UnlockDIBSection
3542 void X11DRV_UnlockDIBSection(DC *dc, BOOL commit)
3544 if (!dc) return;
3545 if (!(dc->flags & DC_MEMORY)) return;
3547 X11DRV_UnlockDIBSection2( dc->hBitmap, commit );
3550 /***********************************************************************
3551 * X11DRV_DIB_CreateDIBSection16
3553 HBITMAP16 X11DRV_DIB_CreateDIBSection16(
3554 DC *dc, BITMAPINFO *bmi, UINT16 usage,
3555 SEGPTR *bits, HANDLE section,
3556 DWORD offset, DWORD ovr_pitch)
3558 HBITMAP res = X11DRV_DIB_CreateDIBSection(dc, bmi, usage, NULL,
3559 section, offset, ovr_pitch);
3560 if ( res )
3562 BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr(res, BITMAP_MAGIC);
3563 if ( bmp && bmp->dib )
3565 DIBSECTION *dib = bmp->dib;
3566 INT height = dib->dsBm.bmHeight >= 0 ?
3567 dib->dsBm.bmHeight : -dib->dsBm.bmHeight;
3568 /* same as above - only use biSizeImage as the correct size if it a
3569 compressed image and it's currently non-zero. In other cases, use
3570 width * height as the value. */
3571 INT size = dib->dsBmih.biSizeImage && dib->dsBmih.biCompression != BI_RGB
3572 ? dib->dsBmih.biSizeImage
3573 : dib->dsBm.bmWidthBytes * height;
3574 if ( dib->dsBm.bmBits )
3576 ((X11DRV_DIBSECTION *) bmp->dib)->selector =
3577 SELECTOR_AllocBlock( dib->dsBm.bmBits, size, WINE_LDT_FLAGS_DATA );
3579 TRACE("ptr = %p, size =%d, selector = %04x, segptr = %ld\n",
3580 dib->dsBm.bmBits, size, ((X11DRV_DIBSECTION *) bmp->dib)->selector,
3581 PTR_SEG_OFF_TO_SEGPTR(((X11DRV_DIBSECTION *) bmp->dib)->selector, 0));
3582 if ( bits )
3583 *bits = PTR_SEG_OFF_TO_SEGPTR( ((X11DRV_DIBSECTION *) bmp->dib)->selector, 0 );
3585 if (bmp) GDI_ReleaseObj( res );
3588 return res;
3591 /***********************************************************************
3592 * X11DRV_XShmErrorHandler
3595 static int XShmErrorHandler(Display *dpy, XErrorEvent *event)
3597 XShmErrorFlag = 1;
3598 return 0;
3601 /***********************************************************************
3602 * X11DRV_XShmCreateImage
3606 #ifdef HAVE_LIBXXSHM
3607 extern BOOL X11DRV_XShmCreateImage(XImage** image, int width, int height, int bpp,
3608 XShmSegmentInfo* shminfo)
3610 int (*WineXHandler)(Display *, XErrorEvent *);
3612 *image = TSXShmCreateImage(display, X11DRV_GetVisual(), bpp, ZPixmap, NULL, shminfo, width, height);
3613 if( *image != NULL )
3615 EnterCriticalSection( &X11DRV_CritSection );
3616 shminfo->shmid = shmget(IPC_PRIVATE, (*image)->bytes_per_line * height,
3617 IPC_CREAT|0700);
3618 if( shminfo->shmid != -1 )
3620 shminfo->shmaddr = (*image)->data = shmat(shminfo->shmid, 0, 0);
3621 if( shminfo->shmaddr != (char*)-1 )
3623 shminfo->readOnly = FALSE;
3624 if( TSXShmAttach( display, shminfo ) != 0)
3626 /* Reset the error flag */
3627 XShmErrorFlag = 0;
3628 WineXHandler = XSetErrorHandler(XShmErrorHandler);
3629 XSync( display, 0 );
3631 if (!XShmErrorFlag)
3633 shmctl(shminfo->shmid, IPC_RMID, 0);
3635 XSetErrorHandler(WineXHandler);
3636 LeaveCriticalSection( &X11DRV_CritSection );
3638 return TRUE; /* Success! */
3640 /* An error occured */
3641 XShmErrorFlag = 0;
3642 XSetErrorHandler(WineXHandler);
3644 shmdt(shminfo->shmaddr);
3646 shmctl(shminfo->shmid, IPC_RMID, 0);
3648 XFlush(display);
3649 XDestroyImage(*image);
3650 LeaveCriticalSection( &X11DRV_CritSection );
3652 return FALSE;
3654 #endif /* HAVE_LIBXXSHM */
3658 /***********************************************************************
3659 * X11DRV_DIB_CreateDIBSection
3661 HBITMAP X11DRV_DIB_CreateDIBSection(
3662 DC *dc, BITMAPINFO *bmi, UINT usage,
3663 LPVOID *bits, HANDLE section,
3664 DWORD offset, DWORD ovr_pitch)
3666 HBITMAP res = 0;
3667 BITMAPOBJ *bmp = NULL;
3668 X11DRV_DIBSECTION *dib = NULL;
3669 int *colorMap = NULL;
3670 int nColorMap;
3672 /* Fill BITMAP32 structure with DIB data */
3673 BITMAPINFOHEADER *bi = &bmi->bmiHeader;
3674 INT effHeight, totalSize;
3675 BITMAP bm;
3677 TRACE("format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
3678 bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
3679 bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
3681 effHeight = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
3682 bm.bmType = 0;
3683 bm.bmWidth = bi->biWidth;
3684 bm.bmHeight = effHeight;
3685 bm.bmWidthBytes = ovr_pitch ? ovr_pitch
3686 : DIB_GetDIBWidthBytes(bm.bmWidth, bi->biBitCount);
3687 bm.bmPlanes = bi->biPlanes;
3688 bm.bmBitsPixel = bi->biBitCount;
3689 bm.bmBits = NULL;
3691 /* Get storage location for DIB bits. Only use biSizeImage if it's valid and
3692 we're dealing with a compressed bitmap. Otherwise, use width * height. */
3693 totalSize = bi->biSizeImage && bi->biCompression != BI_RGB
3694 ? bi->biSizeImage : bm.bmWidthBytes * effHeight;
3696 if (section)
3697 bm.bmBits = MapViewOfFile(section, FILE_MAP_ALL_ACCESS,
3698 0L, offset, totalSize);
3699 else if (ovr_pitch && offset)
3700 bm.bmBits = (LPVOID) offset;
3701 else {
3702 offset = 0;
3703 bm.bmBits = VirtualAlloc(NULL, totalSize,
3704 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
3707 /* Create Color Map */
3708 if (bm.bmBits && bm.bmBitsPixel <= 8)
3709 colorMap = X11DRV_DIB_BuildColorMap( usage == DIB_PAL_COLORS? dc : NULL,
3710 usage, bm.bmBitsPixel, bmi, &nColorMap );
3712 /* Allocate Memory for DIB and fill structure */
3713 if (bm.bmBits)
3714 dib = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(X11DRV_DIBSECTION));
3715 if (dib)
3717 dib->dibSection.dsBm = bm;
3718 dib->dibSection.dsBmih = *bi;
3719 dib->dibSection.dsBmih.biSizeImage = totalSize;
3721 /* Set dsBitfields values */
3722 if ( usage == DIB_PAL_COLORS || bi->biBitCount <= 8)
3724 dib->dibSection.dsBitfields[0] = dib->dibSection.dsBitfields[1] = dib->dibSection.dsBitfields[2] = 0;
3726 else switch( bi->biBitCount )
3728 case 16:
3729 dib->dibSection.dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors : 0x7c00;
3730 dib->dibSection.dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0x03e0;
3731 dib->dibSection.dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0x001f;
3732 break;
3734 case 24:
3735 dib->dibSection.dsBitfields[0] = 0xff;
3736 dib->dibSection.dsBitfields[1] = 0xff00;
3737 dib->dibSection.dsBitfields[2] = 0xff0000;
3738 break;
3740 case 32:
3741 dib->dibSection.dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors : 0xff;
3742 dib->dibSection.dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0xff00;
3743 dib->dibSection.dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0xff0000;
3744 break;
3746 dib->dibSection.dshSection = section;
3747 dib->dibSection.dsOffset = offset;
3749 dib->status = DIB_Status_None;
3750 dib->selector = 0;
3752 dib->nColorMap = nColorMap;
3753 dib->colorMap = colorMap;
3756 /* Create Device Dependent Bitmap and add DIB pointer */
3757 if (dib)
3759 res = CreateDIBitmap(dc->hSelf, bi, 0, NULL, bmi, usage);
3760 if (res)
3762 bmp = (BITMAPOBJ *) GDI_GetObjPtr(res, BITMAP_MAGIC);
3763 if (bmp)
3765 bmp->dib = (DIBSECTION *) dib;
3766 /* HACK for now */
3767 if(!bmp->physBitmap)
3768 X11DRV_CreateBitmap(res);
3773 /* Create XImage */
3774 if (dib && bmp)
3776 #ifdef HAVE_LIBXXSHM
3777 if (TSXShmQueryExtension(display) &&
3778 X11DRV_XShmCreateImage( &dib->image, bm.bmWidth, effHeight,
3779 bmp->bitmap.bmBitsPixel, &dib->shminfo ) )
3781 ; /* Created Image */
3782 } else {
3783 XCREATEIMAGE( dib->image, bm.bmWidth, effHeight, bmp->bitmap.bmBitsPixel );
3784 dib->shminfo.shmid = -1;
3786 #else
3787 XCREATEIMAGE( dib->image, bm.bmWidth, effHeight, bmp->bitmap.bmBitsPixel );
3788 #endif
3791 /* Clean up in case of errors */
3792 if (!res || !bmp || !dib || !bm.bmBits || (bm.bmBitsPixel <= 8 && !colorMap))
3794 TRACE("got an error res=%08x, bmp=%p, dib=%p, bm.bmBits=%p\n",
3795 res, bmp, dib, bm.bmBits);
3796 if (bm.bmBits)
3798 if (section)
3799 UnmapViewOfFile(bm.bmBits), bm.bmBits = NULL;
3800 else if (!offset)
3801 VirtualFree(bm.bmBits, 0L, MEM_RELEASE), bm.bmBits = NULL;
3804 if (dib && dib->image) { XDestroyImage(dib->image); dib->image = NULL; }
3805 if (colorMap) { HeapFree(GetProcessHeap(), 0, colorMap); colorMap = NULL; }
3806 if (dib) { HeapFree(GetProcessHeap(), 0, dib); dib = NULL; }
3807 if (bmp) { GDI_ReleaseObj(res); bmp = NULL; }
3808 if (res) { DeleteObject(res); res = 0; }
3810 else if (bm.bmBits)
3812 /* Install fault handler, if possible */
3813 InitializeCriticalSection(&(dib->lock));
3814 if (VIRTUAL_SetFaultHandler(bm.bmBits, X11DRV_DIB_FaultHandler, (LPVOID)res))
3816 if (section || offset)
3818 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
3819 if (dib) dib->status = DIB_Status_AppMod;
3821 else
3823 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
3824 if (dib) dib->status = DIB_Status_InSync;
3829 /* Return BITMAP handle and storage location */
3830 if (bmp) GDI_ReleaseObj(res);
3831 if (bm.bmBits && bits) *bits = bm.bmBits;
3832 return res;
3835 /***********************************************************************
3836 * X11DRV_DIB_DeleteDIBSection
3838 void X11DRV_DIB_DeleteDIBSection(BITMAPOBJ *bmp)
3840 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
3842 if (dib->image)
3844 #ifdef HAVE_LIBXXSHM
3845 if (dib->shminfo.shmid != -1)
3847 TSXShmDetach (display, &(dib->shminfo));
3848 XDestroyImage (dib->image);
3849 shmdt (dib->shminfo.shmaddr);
3850 dib->shminfo.shmid = -1;
3852 else
3853 #endif
3854 XDestroyImage( dib->image );
3857 if (dib->colorMap)
3858 HeapFree(GetProcessHeap(), 0, dib->colorMap);
3860 if (dib->selector) SELECTOR_FreeBlock( dib->selector );
3861 DeleteCriticalSection(&(dib->lock));
3864 /***********************************************************************
3865 * X11DRV_DIB_SetDIBColorTable
3867 UINT X11DRV_DIB_SetDIBColorTable(BITMAPOBJ *bmp, DC *dc, UINT start, UINT count, const RGBQUAD *colors)
3869 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
3871 if (dib && dib->colorMap) {
3872 X11DRV_DIB_GenColorMap( dc, dib->colorMap, DIB_RGB_COLORS, dib->dibSection.dsBm.bmBitsPixel,
3873 TRUE, colors, start, count + start );
3874 return count;
3876 return 0;
3879 /***********************************************************************
3880 * X11DRV_DIB_GetDIBColorTable
3882 UINT X11DRV_DIB_GetDIBColorTable(BITMAPOBJ *bmp, DC *dc, UINT start, UINT count, RGBQUAD *colors)
3884 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
3886 if (dib && dib->colorMap) {
3887 int i, end = count + start;
3888 if (end > dib->nColorMap) end = dib->nColorMap;
3889 for (i = start; i < end; i++,colors++) {
3890 COLORREF col = X11DRV_PALETTE_ToLogical( dib->colorMap[i] );
3891 colors->rgbBlue = GetBValue(col);
3892 colors->rgbGreen = GetGValue(col);
3893 colors->rgbRed = GetRValue(col);
3894 colors->rgbReserved = 0;
3896 return end-start;
3898 return 0;
3902 /**************************************************************************
3903 * X11DRV_DIB_CreateDIBFromPixmap
3905 * Allocates a packed DIB and copies the Pixmap data into it.
3906 * If bDeletePixmap is TRUE, the Pixmap passed in is deleted after the conversion.
3908 HGLOBAL X11DRV_DIB_CreateDIBFromPixmap(Pixmap pixmap, HDC hdc, BOOL bDeletePixmap)
3910 HBITMAP hBmp = 0;
3911 BITMAPOBJ *pBmp = NULL;
3912 HGLOBAL hPackedDIB = 0;
3914 /* Allocates an HBITMAP which references the Pixmap passed to us */
3915 hBmp = X11DRV_BITMAP_CreateBitmapHeaderFromPixmap(pixmap);
3916 if (!hBmp)
3918 TRACE("\tCould not create bitmap header for Pixmap\n");
3919 goto END;
3923 * Create a packed DIB from the Pixmap wrapper bitmap created above.
3924 * A packed DIB contains a BITMAPINFO structure followed immediately by
3925 * an optional color palette and the pixel data.
3927 hPackedDIB = DIB_CreateDIBFromBitmap(hdc, hBmp);
3929 /* Get a pointer to the BITMAPOBJ structure */
3930 pBmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
3932 /* We can now get rid of the HBITMAP wrapper we created earlier.
3933 * Note: Simply calling DeleteObject will free the embedded Pixmap as well.
3935 if (!bDeletePixmap)
3937 /* Clear the physBitmap to prevent the Pixmap from being deleted by DeleteObject */
3938 pBmp->physBitmap = NULL;
3939 pBmp->funcs = NULL;
3941 GDI_ReleaseObj( hBmp );
3942 DeleteObject(hBmp);
3944 END:
3945 TRACE("\tReturning packed DIB %x\n", hPackedDIB);
3946 return hPackedDIB;
3950 /**************************************************************************
3951 * X11DRV_DIB_CreatePixmapFromDIB
3953 * Creates a Pixmap from a packed DIB
3955 Pixmap X11DRV_DIB_CreatePixmapFromDIB( HGLOBAL hPackedDIB, HDC hdc )
3957 Pixmap pixmap = None;
3958 HBITMAP hBmp = 0;
3959 BITMAPOBJ *pBmp = NULL;
3960 LPBYTE pPackedDIB = NULL;
3961 LPBITMAPINFO pbmi = NULL;
3962 LPBITMAPINFOHEADER pbmiHeader = NULL;
3963 LPBYTE pbits = NULL;
3965 /* Get a pointer to the packed DIB's data */
3966 pPackedDIB = (LPBYTE)GlobalLock(hPackedDIB);
3967 pbmiHeader = (LPBITMAPINFOHEADER)pPackedDIB;
3968 pbmi = (LPBITMAPINFO)pPackedDIB;
3969 pbits = (LPBYTE)(pPackedDIB
3970 + DIB_BitmapInfoSize( (LPBITMAPINFO)pbmiHeader, DIB_RGB_COLORS ));
3972 /* Create a DDB from the DIB */
3974 hBmp = CreateDIBitmap(hdc,
3975 pbmiHeader,
3976 CBM_INIT,
3977 (LPVOID)pbits,
3978 pbmi,
3979 DIB_RGB_COLORS);
3981 GlobalUnlock(hPackedDIB);
3983 TRACE("CreateDIBitmap returned %x\n", hBmp);
3985 /* Retrieve the internal Pixmap from the DDB */
3987 pBmp = (BITMAPOBJ *) GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
3989 pixmap = (Pixmap)pBmp->physBitmap;
3990 /* clear the physBitmap so that we can steal its pixmap */
3991 pBmp->physBitmap = NULL;
3992 pBmp->funcs = NULL;
3994 /* Delete the DDB we created earlier now that we have stolen its pixmap */
3995 GDI_ReleaseObj( hBmp );
3996 DeleteObject(hBmp);
3998 TRACE("\tReturning Pixmap %ld\n", pixmap);
3999 return pixmap;