Added pow() forward.
[wine.git] / graphics / x11drv / dib.c
blob645795b3a68bee59dee9b8003811cfdf77ab8505
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_BuildColorMap
83 * Build the color map from the bitmap palette. Should not be called
84 * for a >8-bit deep bitmap.
86 int *X11DRV_DIB_BuildColorMap( DC *dc, WORD coloruse, WORD depth,
87 const BITMAPINFO *info, int *nColors )
89 int i, colors;
90 BOOL isInfo;
91 WORD *colorPtr;
92 int *colorMapping;
94 if ((isInfo = (info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))))
96 colors = info->bmiHeader.biClrUsed;
97 if (!colors) colors = 1 << info->bmiHeader.biBitCount;
98 colorPtr = (WORD *)info->bmiColors;
100 else /* assume BITMAPCOREINFO */
102 colors = 1 << ((BITMAPCOREHEADER *)&info->bmiHeader)->bcBitCount;
103 colorPtr = (WORD *)((BITMAPCOREINFO *)info)->bmciColors;
106 if (colors > 256)
108 ERR("called with >256 colors!\n");
109 return NULL;
112 if (!(colorMapping = (int *)HeapAlloc(GetProcessHeap(), 0,
113 colors * sizeof(int) )))
114 return NULL;
116 if (coloruse == DIB_RGB_COLORS)
118 if (isInfo)
120 RGBQUAD * rgb = (RGBQUAD *)colorPtr;
122 if (depth == 1) /* Monochrome */
123 for (i = 0; i < colors; i++, rgb++)
124 colorMapping[i] = (rgb->rgbRed + rgb->rgbGreen +
125 rgb->rgbBlue > 255*3/2);
126 else
127 for (i = 0; i < colors; i++, rgb++)
128 colorMapping[i] = X11DRV_PALETTE_ToPhysical( dc, RGB(rgb->rgbRed,
129 rgb->rgbGreen,
130 rgb->rgbBlue));
132 else
134 RGBTRIPLE * rgb = (RGBTRIPLE *)colorPtr;
136 if (depth == 1) /* Monochrome */
137 for (i = 0; i < colors; i++, rgb++)
138 colorMapping[i] = (rgb->rgbtRed + rgb->rgbtGreen +
139 rgb->rgbtBlue > 255*3/2);
140 else
141 for (i = 0; i < colors; i++, rgb++)
142 colorMapping[i] = X11DRV_PALETTE_ToPhysical( dc, RGB(rgb->rgbtRed,
143 rgb->rgbtGreen,
144 rgb->rgbtBlue));
147 else /* DIB_PAL_COLORS */
149 for (i = 0; i < colors; i++, colorPtr++)
150 colorMapping[i] = X11DRV_PALETTE_ToPhysical( dc, PALETTEINDEX(*colorPtr) );
153 *nColors = colors;
154 return colorMapping;
158 /***********************************************************************
159 * X11DRV_DIB_MapColor
161 int X11DRV_DIB_MapColor( int *physMap, int nPhysMap, int phys, int oldcol )
163 int color;
165 if ((oldcol < nPhysMap) && (physMap[oldcol] == phys))
166 return oldcol;
168 for (color = 0; color < nPhysMap; color++)
169 if (physMap[color] == phys)
170 return color;
172 WARN("Strange color %08x\n", phys);
173 return 0;
177 /*********************************************************************
178 * X11DRV_DIB_GetNearestIndex
180 * Helper for X11DRV_DIB_GetDIBits.
181 * Returns the nearest colour table index for a given RGB.
182 * Nearest is defined by minimizing the sum of the squares.
184 static INT X11DRV_DIB_GetNearestIndex(RGBQUAD *colormap, int numColors, BYTE r, BYTE g, BYTE b)
186 INT i, best = -1, diff, bestdiff = -1;
187 RGBQUAD *color;
189 for(color = colormap, i = 0; i < numColors; color++, i++) {
190 diff = (r - color->rgbRed) * (r - color->rgbRed) +
191 (g - color->rgbGreen) * (g - color->rgbGreen) +
192 (b - color->rgbBlue) * (b - color->rgbBlue);
193 if(diff == 0)
194 return i;
195 if(best == -1 || diff < bestdiff) {
196 best = i;
197 bestdiff = diff;
200 return best;
203 /***********************************************************************
204 * X11DRV_DIB_SetImageBits_1_Line
206 * Handles a single line of 1 bit data.
208 static void X11DRV_DIB_SetImageBits_1_Line(DWORD dstwidth, int left, int *colors,
209 XImage *bmpImage, int h, const BYTE *bits)
211 BYTE pix, extra;
212 DWORD i, x;
214 if((extra = (left & 7)) != 0) {
215 left &= ~7;
216 dstwidth += extra;
219 bits += left >> 3;
221 /* FIXME: should avoid putting x<left pixels (minor speed issue) */
222 for (i = dstwidth/8, x = left; i > 0; i--)
224 pix = *bits++;
225 XPutPixel( bmpImage, x++, h, colors[pix >> 7] );
226 XPutPixel( bmpImage, x++, h, colors[(pix >> 6) & 1] );
227 XPutPixel( bmpImage, x++, h, colors[(pix >> 5) & 1] );
228 XPutPixel( bmpImage, x++, h, colors[(pix >> 4) & 1] );
229 XPutPixel( bmpImage, x++, h, colors[(pix >> 3) & 1] );
230 XPutPixel( bmpImage, x++, h, colors[(pix >> 2) & 1] );
231 XPutPixel( bmpImage, x++, h, colors[(pix >> 1) & 1] );
232 XPutPixel( bmpImage, x++, h, colors[pix & 1] );
234 pix = *bits;
235 switch(dstwidth & 7)
237 case 7: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
238 case 6: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
239 case 5: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
240 case 4: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
241 case 3: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
242 case 2: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
243 case 1: XPutPixel( bmpImage, x++, h, colors[pix >> 7] );
247 /***********************************************************************
248 * X11DRV_DIB_SetImageBits_1
250 * SetDIBits for a 1-bit deep DIB.
252 static void X11DRV_DIB_SetImageBits_1( int lines, const BYTE *srcbits,
253 DWORD srcwidth, DWORD dstwidth, int left,
254 int *colors, XImage *bmpImage )
256 int h;
258 /* 32 bit aligned */
259 DWORD linebytes = ((srcwidth + 31) & ~31) / 8;
261 if (lines > 0) {
262 for (h = lines-1; h >=0; h--) {
263 X11DRV_DIB_SetImageBits_1_Line(dstwidth, left, colors, bmpImage, h,
264 srcbits);
265 srcbits += linebytes;
267 } else {
268 lines = -lines;
269 for (h = 0; h < lines; h++) {
270 X11DRV_DIB_SetImageBits_1_Line(dstwidth, left, colors, bmpImage, h,
271 srcbits);
272 srcbits += linebytes;
277 /***********************************************************************
278 * X11DRV_DIB_GetImageBits_1
280 * GetDIBits for a 1-bit deep DIB.
282 static void X11DRV_DIB_GetImageBits_1( int lines, BYTE *dstbits,
283 DWORD dstwidth, DWORD srcwidth,
284 RGBQUAD *colors, PALETTEENTRY *srccolors,
285 XImage *bmpImage )
287 DWORD x;
288 int h;
289 BYTE *bits;
291 /* 32 bit aligned */
292 DWORD linebytes = ((dstwidth + 31) & ~31) / 8;
294 if (lines < 0 ) {
295 lines = -lines;
296 dstbits = dstbits + linebytes * (lines - 1);
297 linebytes = -linebytes;
300 bits = dstbits;
302 switch(bmpImage->depth) {
304 case 1:
305 /* ==== monochrome bitmap to monochrome dib ==== */
306 case 4:
307 /* ==== 4 colormap bitmap to monochrome dib ==== */
308 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
310 PALETTEENTRY val;
312 for (h = lines - 1; h >= 0; h--) {
313 for (x = 0; x < dstwidth; x++) {
314 val = srccolors[XGetPixel(bmpImage, x, h)];
315 if (!(x&7)) *bits = 0;
316 *bits |= (X11DRV_DIB_GetNearestIndex(colors, 2,
317 val.peRed,
318 val.peGreen,
319 val.peBlue) << (7 - (x & 7)));
320 if ((x&7)==7) bits++;
322 bits = (dstbits += linebytes);
325 else goto notsupported;
327 break;
329 case 8:
330 /* ==== 8 colormap bitmap to monochrome dib ==== */
331 if ( bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
333 BYTE *srcpixel;
334 PALETTEENTRY val;
336 for( h = lines- 1; h >= 0; h-- ) {
337 srcpixel = bmpImage->data + (h*bmpImage->bytes_per_line);
338 for( x = 0; x < dstwidth; x++ ) {
339 if (!(x&7)) *bits = 0;
340 val = srccolors[(int)*srcpixel++];
341 *bits |= ( X11DRV_DIB_GetNearestIndex(colors, 2,
342 val.peRed,
343 val.peGreen,
344 val.peBlue) << (7-(x&7)) );
345 if ((x&7)==7) bits++;
347 bits = (dstbits += linebytes);
350 else goto notsupported;
352 break;
354 case 15:
356 LPWORD srcpixel;
357 WORD val;
359 /* ==== 555 BGR bitmap to monochrome dib ==== */
360 if (bmpImage->red_mask == 0x7c00 && bmpImage->blue_mask == 0x1f)
362 for( h = lines - 1; h >= 0; h--) {
363 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
364 for( x = 0; x < dstwidth; x++) {
365 if (!(x&7)) *bits = 0;
366 val = *srcpixel++;
367 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 2,
368 ((val >> 7) & 0xf8) |
369 ((val >> 12) & 0x7),
370 ((val >> 2) & 0xf8) |
371 ((val >> 7) & 0x3),
372 ((val << 3) & 0xf8) |
373 ((val >> 2) & 0x7) ) << (7-(x&7)) );
374 if ((x&7)==7) bits++;
376 bits = (dstbits += linebytes);
379 /* ==== 555 RGB bitmap to monochrome dib ==== */
380 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0xf800)
382 for( h = lines - 1; h >= 0; h--)
384 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
385 for( x = 0; x < dstwidth; x++) {
386 if (!(x&1)) *bits = 0;
387 val = *srcpixel++;
388 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 2,
389 ((val << 3) & 0xf8) |
390 ((val >> 2) & 0x7),
391 ((val >> 2) & 0xf8) |
392 ((val >> 7) & 0x3),
393 ((val >> 7) & 0xf8) |
394 ((val >> 12) & 0x7) ) << (7-(x&7)) );
395 if ((x&7)==7) bits++;
397 bits = (dstbits += linebytes);
400 else goto notsupported;
402 break;
404 case 16:
406 LPWORD srcpixel;
407 WORD val;
409 /* ==== 565 BGR bitmap to monochrome dib ==== */
410 if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f)
412 for( h = lines - 1; h >= 0; h--)
414 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
415 for( x = 0; x < dstwidth; x++) {
416 if (!(x&7)) *bits = 0;
417 val = *srcpixel++;
418 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 2,
419 ((val >> 8) & 0xf8) |
420 ((val >> 13) & 0x7),
421 ((val >> 3) & 0xfc) |
422 ((val >> 9) & 0x3),
423 ((val << 3) & 0xf8) |
424 ((val >> 2) & 0x7) ) << (7-(x&7)) );
425 if ((x&7)==7) bits++;
427 bits = (dstbits += linebytes);
430 /* ==== 565 RGB bitmap to monochrome dib ==== */
431 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0xf800)
433 for( h = lines - 1; h >= 0; h--)
435 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
436 for( x = 0; x < dstwidth; x++) {
437 if (!(x&7)) *bits = 0;
438 val = *srcpixel++;
439 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 2,
440 ((val << 3) & 0xf8) |
441 ((val >> 2) & 0x7),
442 ((val >> 3) & 0xfc) |
443 ((val >> 9) & 0x3),
444 ((val >> 8) & 0xf8) |
445 ((val >> 13) & 0x7) ) << (7-(x&7)) );
446 if ((x&7)==7) bits++;
448 bits = (dstbits += linebytes);
451 else goto notsupported;
453 break;
455 case 24:
456 case 32:
458 BYTE *srcpixel;
460 /* ==== 24/32 BGR bitmap to monochrome dib ==== */
461 if (bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff)
463 for (h = lines - 1; h >= 0; h--)
465 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
466 for (x = 0; x < dstwidth; x++, srcpixel+=4) {
467 if (!(x&7)) *bits = 0;
468 *bits |= (X11DRV_DIB_GetNearestIndex(colors, 2, srcpixel[2] , srcpixel[1], srcpixel[0]) << (7-(x&7)) );
469 if ((x&7)==7) bits++;
471 bits = (dstbits += linebytes);
474 /* ==== 24/32 RGB bitmap to monochrome dib ==== */
475 else if (bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000)
477 for (h = lines - 1; h >= 0; h--)
479 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
480 for (x = 0; x < dstwidth; x++, srcpixel+=4) {
481 if (!(x & 7)) *bits = 0;
482 *bits |= (X11DRV_DIB_GetNearestIndex(colors, 2, srcpixel[0] , srcpixel[1], srcpixel[2]) << (7-(x&7)) );
483 if ((x & 7) == 7) bits++;
485 bits = (dstbits += linebytes);
488 else goto notsupported;
490 break;
492 default: /* ? bit bmp -> monochrome DIB */
493 notsupported:
495 unsigned long white = (1 << bmpImage->bits_per_pixel) - 1;
497 FIXME("from %d bit bitmap with mask R,G,B %x,%x,%x to 1 bit DIB\n",
498 bmpImage->bits_per_pixel, (int)bmpImage->red_mask,
499 (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
501 for( h = lines - 1; h >= 0; h-- ) {
502 for( x = 0; x < dstwidth; x++ ) {
503 if (!(x&7)) *bits = 0;
504 *bits |= (XGetPixel( bmpImage, x, h) >= white)
505 << (7 - (x&7));
506 if ((x&7)==7) bits++;
508 bits = (dstbits += linebytes);
511 break;
515 /***********************************************************************
516 * X11DRV_DIB_SetImageBits_4
518 * SetDIBits for a 4-bit deep DIB.
520 static void X11DRV_DIB_SetImageBits_4( int lines, const BYTE *srcbits,
521 DWORD srcwidth, DWORD dstwidth, int left,
522 int *colors, XImage *bmpImage )
524 DWORD i, x;
525 int h;
526 const BYTE *bits = srcbits + (left >> 1);
528 /* 32 bit aligned */
529 DWORD linebytes = ((srcwidth+7)&~7)/2;
531 if(left & 1) {
532 left--;
533 dstwidth++;
536 if (lines > 0) {
537 for (h = lines-1; h >= 0; h--) {
538 for (i = dstwidth/2, x = left; i > 0; i--) {
539 BYTE pix = *bits++;
540 XPutPixel( bmpImage, x++, h, colors[pix >> 4] );
541 XPutPixel( bmpImage, x++, h, colors[pix & 0x0f] );
543 if (dstwidth & 1) XPutPixel( bmpImage, x, h, colors[*bits >> 4] );
544 srcbits += linebytes;
545 bits = srcbits + (left >> 1);
547 } else {
548 lines = -lines;
549 for (h = 0; h < lines; h++) {
550 for (i = dstwidth/2, x = left; i > 0; i--) {
551 BYTE pix = *bits++;
552 XPutPixel( bmpImage, x++, h, colors[pix >> 4] );
553 XPutPixel( bmpImage, x++, h, colors[pix & 0x0f] );
555 if (dstwidth & 1) XPutPixel( bmpImage, x, h, colors[*bits >> 4] );
556 srcbits += linebytes;
557 bits = srcbits + (left >> 1);
564 /***********************************************************************
565 * X11DRV_DIB_GetImageBits_4
567 * GetDIBits for a 4-bit deep DIB.
569 static void X11DRV_DIB_GetImageBits_4( int lines, BYTE *dstbits,
570 DWORD srcwidth, DWORD dstwidth,
571 RGBQUAD *colors, PALETTEENTRY *srccolors,
572 XImage *bmpImage )
574 DWORD x;
575 int h;
576 BYTE *bits;
577 LPBYTE srcpixel;
579 /* 32 bit aligned */
580 DWORD linebytes = ((srcwidth+7)&~7)/2;
582 if (lines < 0 )
584 lines = -lines;
585 dstbits = dstbits + ( linebytes * (lines-1) );
586 linebytes = -linebytes;
589 bits = dstbits;
591 switch(bmpImage->depth) {
593 case 1:
594 /* ==== monochrome bitmap to 4 colormap dib ==== */
595 case 4:
596 /* ==== 4 colormap bitmap to 4 colormap dib ==== */
597 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
599 PALETTEENTRY val;
601 for (h = lines-1; h >= 0; h--) {
602 for (x = 0; x < dstwidth; x++) {
603 if (!(x&1)) *bits = 0;
604 val = srccolors[XGetPixel(bmpImage, x, h)];
605 *bits |= (X11DRV_DIB_GetNearestIndex(colors, 16,
606 val.peRed,
607 val.peGreen,
608 val.peBlue) << (4-((x&1)<<2)));
609 if ((x&1)==1) bits++;
611 bits = (dstbits += linebytes);
614 else goto notsupported;
616 break;
618 case 8:
619 /* ==== 8 colormap bitmap to 4 colormap dib ==== */
620 if ( bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
622 PALETTEENTRY val;
624 for( h = lines - 1; h >= 0; h-- ) {
625 srcpixel = bmpImage->data + (h*bmpImage->bytes_per_line);
626 for( x = 0; x < dstwidth; x++ ) {
627 if (!(x&1)) *bits = 0;
628 val = srccolors[(int)*srcpixel++];
629 *bits |= ( X11DRV_DIB_GetNearestIndex(colors, 16,
630 val.peRed,
631 val.peGreen,
632 val.peBlue) << (4*(1-(x&1))) );
633 if ((x&1)==1) bits++;
635 bits = (dstbits += linebytes);
638 else goto notsupported;
640 break;
642 case 15:
644 LPWORD srcpixel;
645 WORD val;
647 /* ==== 555 BGR bitmap to 4 colormap dib ==== */
648 if (bmpImage->red_mask == 0x7c00 && bmpImage->blue_mask == 0x1f)
650 for( h = lines - 1; h >= 0; h--) {
651 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
652 for( x = 0; x < dstwidth; x++) {
653 if (!(x&1)) *bits = 0;
654 val = *srcpixel++;
655 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 16,
656 ((val >> 7) & 0xf8) |
657 ((val >> 12) & 0x7),
658 ((val >> 2) & 0xf8) |
659 ((val >> 7) & 0x3),
660 ((val << 3) & 0xf8) |
661 ((val >> 2) & 0x7) ) << ((1-(x&1))<<2) );
662 if ((x&1)==1) bits++;
664 bits = (dstbits += linebytes);
667 /* ==== 555 RGB bitmap to 4 colormap dib ==== */
668 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0x7c00)
670 for( h = lines - 1; h >= 0; h--)
672 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
673 for( x = 0; x < dstwidth; x++) {
674 if (!(x&1)) *bits = 0;
675 val = *srcpixel++;
676 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 16,
677 ((val << 3) & 0xf8) |
678 ((val >> 2) & 0x7),
679 ((val >> 2) & 0xfc) |
680 ((val >> 7) & 0x3),
681 ((val >> 7) & 0xf8) |
682 ((val >> 12) & 0x7) ) << ((1-(x&1))<<2) );
683 if ((x&1)==1) bits++;
685 bits = (dstbits += linebytes);
688 else goto notsupported;
690 break;
692 case 16:
694 LPWORD srcpixel;
695 WORD val;
697 /* ==== 565 BGR bitmap to 4 colormap dib ==== */
698 if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f)
700 for( h = lines - 1; h >= 0; h--)
702 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
703 for( x = 0; x < dstwidth; x++) {
704 if (!(x&1)) *bits = 0;
705 val = *srcpixel++;
706 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 16,
707 ((val >> 8) & 0xf8) |
708 ((val >> 13) & 0x7),
709 ((val >> 3) & 0xfc) |
710 ((val >> 9) & 0x3),
711 ((val << 3) & 0xf8) |
712 ((val >> 2) & 0x7) ) << ((1-(x&1))<<2) );
713 if ((x&1)==1) bits++;
715 bits = (dstbits += linebytes);
718 /* ==== 565 RGB bitmap to 4 colormap dib ==== */
719 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0xf800)
721 for( h = lines - 1; h >= 0; h--)
723 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
724 for( x = 0; x < dstwidth; x++) {
725 if (!(x&1)) *bits = 0;
726 val = *srcpixel++;
727 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 16,
728 ((val << 3) & 0xf8) |
729 ((val >> 2) & 0x7),
730 ((val >> 3) & 0xfc) |
731 ((val >> 9) & 0x3),
732 ((val >> 8) & 0xf8) |
733 ((val >> 13) & 0x7) ) << ((1-(x&1))<<2) );
734 if ((x&1)==1) bits++;
736 bits = (dstbits += linebytes);
739 else goto notsupported;
741 break;
743 case 24:
744 case 32:
746 BYTE *srcpixel;
748 /* ==== 24/32 BGR bitmap to 4 colormap dib ==== */
749 if (bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff)
751 for (h = lines - 1; h >= 0; h--)
753 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
754 for (x = 0; x < dstwidth; x+=2, srcpixel+=8) /* 2 pixels at a time */
755 *bits++ = (X11DRV_DIB_GetNearestIndex(colors, 16, srcpixel[2] , srcpixel[1], srcpixel[0]) << 4) |
756 X11DRV_DIB_GetNearestIndex(colors, 16, srcpixel[6] , srcpixel[5], srcpixel[4]);
757 bits = (dstbits += linebytes);
760 /* ==== 24/32 RGB bitmap to 4 colormap dib ==== */
761 else if (bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000)
763 for (h = lines - 1; h >= 0; h--)
765 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
766 for (x = 0; x < dstwidth; x+=2, srcpixel+=8) /* 2 pixels at a time */
767 *bits++ = (X11DRV_DIB_GetNearestIndex(colors, 16, srcpixel[0] , srcpixel[1], srcpixel[2]) << 4) |
768 X11DRV_DIB_GetNearestIndex(colors, 16, srcpixel[4] , srcpixel[5], srcpixel[6]);
769 bits = (dstbits += linebytes);
772 else goto notsupported;
774 break;
776 default: /* ? bit bmp -> 4 bit DIB */
777 notsupported:
778 FIXME("from %d bit bitmap with mask R,G,B %x,%x,%x to 4 bit DIB\n",
779 bmpImage->bits_per_pixel, (int)bmpImage->red_mask,
780 (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
781 for (h = lines-1; h >= 0; h--) {
782 for (x = 0; x < dstwidth/2; x++) {
783 *bits++ = (X11DRV_DIB_MapColor((int *)colors, 16,
784 XGetPixel( bmpImage, x++, h ), 0) << 4)
785 | (X11DRV_DIB_MapColor((int *)colors, 16,
786 XGetPixel( bmpImage, x++, h ), 0) & 0x0f);
788 if (dstwidth & 1)
789 *bits = (X11DRV_DIB_MapColor((int *)colors, 16,
790 XGetPixel( bmpImage, x++, h ), 0) << 4);
791 bits = (dstbits += linebytes);
793 break;
797 /***********************************************************************
798 * X11DRV_DIB_SetImageBits_RLE4
800 * SetDIBits for a 4-bit deep compressed DIB.
802 static void X11DRV_DIB_SetImageBits_RLE4( int lines, const BYTE *bits,
803 DWORD width, DWORD dstwidth,
804 int left, int *colors,
805 XImage *bmpImage )
807 int x = 0, c, length;
808 const BYTE *begin = bits;
810 lines--;
812 while ((int)lines >= 0) {
813 length = *bits++;
814 if (length) { /* encoded */
815 c = *bits++;
816 while (length--) {
817 if(x >= width) {
818 x = 0;
819 if(--lines < 0)
820 return;
822 XPutPixel(bmpImage, x++, lines, colors[c >>4]);
823 if (length) {
824 length--;
825 if(x >= width) {
826 x = 0;
827 if(--lines < 0)
828 return;
830 XPutPixel(bmpImage, x++, lines, colors[c & 0xf]);
833 } else {
834 length = *bits++;
835 switch (length) {
836 case 0: /* eol */
837 x = 0;
838 lines--;
839 continue;
841 case 1: /* eopicture */
842 return;
844 case 2: /* delta */
845 x += *bits++;
846 if(x >= width) {
847 FIXME_(x11drv)("x-delta is too large?\n");
848 return;
850 lines -= *bits++;
851 continue;
853 default: /* absolute */
854 while (length--) {
855 c = *bits++;
856 if(x >= width) {
857 x = 0;
858 if(--lines < 0)
859 return;
861 XPutPixel(bmpImage, x++, lines, colors[c >> 4]);
862 if (length) {
863 length--;
864 if(x >= width) {
865 x = 0;
866 if(--lines < 0)
867 return;
869 XPutPixel(bmpImage, x++, lines, colors[c & 0xf]);
872 if ((bits - begin) & 1)
873 bits++;
881 /***********************************************************************
882 * X11DRV_DIB_SetImageBits_8
884 * SetDIBits for an 8-bit deep DIB.
886 static void X11DRV_DIB_SetImageBits_8( int lines, const BYTE *srcbits,
887 DWORD srcwidth, DWORD dstwidth, int left,
888 const int *colors, XImage *bmpImage )
890 DWORD x;
891 int h, color;
892 const BYTE *bits;
894 /* align to 32 bit */
895 DWORD linebytes = (srcwidth + 3) & ~3;
897 dstwidth += left;
899 if (lines < 0 )
901 lines = -lines;
902 srcbits = srcbits + ( linebytes * (lines-1) );
903 linebytes = -linebytes;
906 bits = srcbits + left;
908 switch (bmpImage->depth) {
909 case 15:
910 case 16:
911 #if defined(__i386__) && defined(__GNUC__)
912 /* Some X servers might have 32 bit/ 16bit deep pixel */
913 if (lines && (dstwidth!=left) && (bmpImage->bits_per_pixel == 16))
915 for (h = lines ; h--; ) {
916 int _cl1,_cl2; /* temp outputs for asm below */
917 /* Borrowed from DirectDraw */
918 __asm__ __volatile__(
919 "xor %%eax,%%eax\n"
920 "cld\n"
921 "1:\n"
922 " lodsb\n"
923 " movw (%%edx,%%eax,4),%%ax\n"
924 " stosw\n"
925 " xor %%eax,%%eax\n"
926 " loop 1b\n"
927 :"=S" (bits), "=D" (_cl1), "=c" (_cl2)
928 :"S" (bits),
929 "D" (bmpImage->data+h*bmpImage->bytes_per_line+left*2),
930 "c" (dstwidth-left),
931 "d" (colors)
932 :"eax", "cc", "memory"
934 bits = (srcbits += linebytes) + left;
936 return;
938 break;
939 #endif
940 default:
941 break; /* use slow generic case below */
944 for (h = lines - 1; h >= 0; h--) {
945 for (x = left; x < dstwidth; x++, bits++) {
946 color = colors[*bits];
947 XPutPixel( bmpImage, x, h, colors[*bits] );
949 bits = (srcbits += linebytes) + left;
953 /***********************************************************************
954 * X11DRV_DIB_GetImageBits_8
956 * GetDIBits for an 8-bit deep DIB.
958 static void X11DRV_DIB_GetImageBits_8( int lines, BYTE *dstbits,
959 DWORD srcwidth, DWORD dstwidth,
960 RGBQUAD *colors, PALETTEENTRY *srccolors,
961 XImage *bmpImage )
963 DWORD x;
964 int h;
965 BYTE *bits;
967 /* align to 32 bit */
968 DWORD linebytes = (srcwidth + 3) & ~3;
970 if (lines < 0 )
972 lines = -lines;
973 dstbits = dstbits + ( linebytes * (lines-1) );
974 linebytes = -linebytes;
977 bits = dstbits;
980 Hack for now
981 This condition is true when GetImageBits has been called by UpdateDIBSection.
982 For now, GetNearestIndex is too slow to support 256 colormaps, so we'll just use for
983 for GetDIBits calls. (In somes cases, in a updateDIBSection, the returned colors are bad too)
985 if (!srccolors) goto updatesection;
987 switch(bmpImage->depth) {
989 case 1:
990 /* ==== monochrome bitmap to 8 colormap dib ==== */
991 case 4:
992 /* ==== 4 colormap bitmap to 8 colormap dib ==== */
993 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
995 PALETTEENTRY val;
997 for (h = lines - 1; h >= 0; h--) {
998 for (x = 0; x < dstwidth; x++) {
999 val = srccolors[XGetPixel(bmpImage, x, h)];
1000 *bits++ = X11DRV_DIB_GetNearestIndex(colors, 256, val.peRed,
1001 val.peGreen, val.peBlue);
1003 bits = (dstbits += linebytes);
1006 else goto notsupported;
1008 break;
1010 case 8:
1011 /* ==== 8 colormap bitmap to 8 colormap dib ==== */
1012 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
1014 BYTE *srcpixel;
1015 PALETTEENTRY val;
1017 for (h = lines - 1; h >= 0; h--) {
1018 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
1019 for (x = 0; x < dstwidth; x++) {
1020 val = srccolors[(int)*srcpixel++];
1021 *bits++ = X11DRV_DIB_GetNearestIndex(colors, 256, val.peRed,
1022 val.peGreen, val.peBlue);
1024 bits = (dstbits += linebytes);
1027 else goto notsupported;
1029 break;
1031 case 15:
1033 LPWORD srcpixel;
1034 WORD val;
1036 /* ==== 555 BGR bitmap to 8 colormap dib ==== */
1037 if (bmpImage->red_mask == 0x7c00 && bmpImage->blue_mask == 0x001f)
1039 for( h = lines - 1; h >= 0; h--)
1041 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
1042 for( x = 0; x < dstwidth; x++ )
1044 val = *srcpixel++;
1045 *bits++ = X11DRV_DIB_GetNearestIndex( colors, 256,
1046 ((val >> 7) & 0xf8) |
1047 ((val >> 12) & 0x7),
1048 ((val >> 2) & 0xf8) |
1049 ((val >> 7) & 0x3),
1050 ((val << 3) & 0xf8) |
1051 ((val >> 2) & 0x7) );
1053 bits = (dstbits += linebytes);
1056 /* ==== 555 RGB bitmap to 8 colormap dib ==== */
1057 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0x7c00)
1059 for( h = lines - 1; h >= 0; h--)
1061 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
1062 for( x = 0; x < dstwidth; x++ )
1064 val = *srcpixel++;
1065 *bits++ = X11DRV_DIB_GetNearestIndex( colors, 256,
1066 ((val << 3) & 0xf8) |
1067 ((val >> 2) & 0x7),
1068 ((val >> 2) & 0xf8) |
1069 ((val >> 7) & 0x3),
1070 ((val >> 7) & 0xf8) |
1071 ((val >> 12) & 0x7) );
1073 bits = (dstbits += linebytes);
1076 else goto notsupported;
1078 break;
1080 case 16:
1082 LPWORD srcpixel;
1083 WORD val;
1085 /* ==== 565 BGR bitmap to 8 colormap dib ==== */
1086 if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f)
1088 for( h = lines - 1; h >= 0; h--)
1090 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
1091 for( x = 0; x < dstwidth; x++ )
1093 val = *srcpixel++;
1094 *bits++ = X11DRV_DIB_GetNearestIndex( colors, 256,
1095 ((val >> 8) & 0xf8) |
1096 ((val >> 13) & 0x7),
1097 ((val >> 3) & 0xfc) |
1098 ((val >> 9) & 0x3),
1099 ((val << 3) & 0xf8) |
1100 ((val >> 2) & 0x7) );
1102 bits = (dstbits += linebytes);
1105 /* ==== 565 RGB bitmap to 8 colormap dib ==== */
1106 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0xf800)
1108 for( h = lines - 1; h >= 0; h--)
1110 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
1111 for( x = 0; x < dstwidth; x++ )
1113 val = *srcpixel++;
1114 *bits++ = X11DRV_DIB_GetNearestIndex( colors, 256,
1115 ((val << 3) & 0xf8) |
1116 ((val >> 2) & 0x7),
1117 ((val >> 3) & 0x00fc) |
1118 ((val >> 9) & 0x3),
1119 ((val >> 8) & 0x00f8) |
1120 ((val >> 13) & 0x7) );
1122 bits = (dstbits += linebytes);
1125 else goto notsupported;
1127 break;
1129 case 24:
1130 case 32:
1132 BYTE *srcpixel;
1134 /* ==== 24/32 BGR bitmap to 8 colormap dib ==== */
1135 if (bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff)
1137 for (h = lines - 1; h >= 0; h--)
1139 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
1140 for (x = 0; x < dstwidth; x++, srcpixel+=4)
1141 *bits++ = X11DRV_DIB_GetNearestIndex(colors, 256,
1142 srcpixel[2] , srcpixel[1], *srcpixel);
1143 bits = (dstbits += linebytes);
1146 /* ==== 24/32 RGB bitmap to 8 colormap dib ==== */
1147 else if (bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000)
1149 for (h = lines - 1; h >= 0; h--)
1151 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
1152 for (x = 0; x < dstwidth; x++, srcpixel+=4)
1153 *bits++ = X11DRV_DIB_GetNearestIndex(colors, 256,
1154 *srcpixel, srcpixel[1], srcpixel[2]);
1155 bits = (dstbits += linebytes);
1159 else goto notsupported;
1161 break;
1163 default: /* ? bit bmp -> 8 bit DIB */
1164 notsupported:
1165 FIXME("from %d bit bitmap with mask R,G,B %x,%x,%x to 8 bit DIB\n",
1166 bmpImage->depth, (int)bmpImage->red_mask,
1167 (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
1168 updatesection:
1169 for (h = lines - 1; h >= 0; h--) {
1170 for (x = 0; x < dstwidth; x++, bits++) {
1171 *bits = X11DRV_DIB_MapColor((int *)colors, 256,
1172 XGetPixel( bmpImage, x, h ), *bits);
1174 bits = (dstbits += linebytes);
1176 break;
1180 /***********************************************************************
1181 * X11DRV_DIB_SetImageBits_RLE8
1183 * SetDIBits for an 8-bit deep compressed DIB.
1185 * This function rewritten 941113 by James Youngman. WINE blew out when I
1186 * first ran it because my desktop wallpaper is a (large) RLE8 bitmap.
1188 * This was because the algorithm assumed that all RLE8 bitmaps end with the
1189 * 'End of bitmap' escape code. This code is very much laxer in what it
1190 * allows to end the expansion. Possibly too lax. See the note by
1191 * case RleDelta. BTW, MS's documentation implies that a correct RLE8
1192 * bitmap should end with RleEnd, but on the other hand, software exists
1193 * that produces ones that don't and Windows 3.1 doesn't complain a bit
1194 * about it.
1196 * (No) apologies for my English spelling. [Emacs users: c-indent-level=4].
1197 * James A. Youngman <mbcstjy@afs.man.ac.uk>
1198 * [JAY]
1201 enum Rle8_EscapeCodes
1204 * Apologies for polluting your file's namespace...
1206 RleEol = 0, /* End of line */
1207 RleEnd = 1, /* End of bitmap */
1208 RleDelta = 2 /* Delta */
1211 static void X11DRV_DIB_SetImageBits_RLE8( int lines, const BYTE *bits,
1212 DWORD width, DWORD dstwidth,
1213 int left, int *colors,
1214 XImage *bmpImage )
1216 int x; /* X-positon on each line. Increases. */
1217 int line; /* Line #. Starts at lines-1, decreases */
1218 const BYTE *pIn = bits; /* Pointer to current position in bits */
1219 BYTE length; /* The length pf a run */
1220 BYTE color_index; /* index into colors[] as read from bits */
1221 BYTE escape_code; /* See enum Rle8_EscapeCodes.*/
1222 int color; /* value of colour[color_index] */
1224 if (lines == 0) /* Let's hope this doesn't happen. */
1225 return;
1228 * Note that the bitmap data is stored by Windows starting at the
1229 * bottom line of the bitmap and going upwards. Within each line,
1230 * the data is stored left-to-right. That's the reason why line
1231 * goes from lines-1 to 0. [JAY]
1234 x = 0;
1235 line = lines-1;
1238 length = *pIn++;
1241 * If the length byte is not zero (which is the escape value),
1242 * We have a run of length pixels all the same colour. The colour
1243 * index is stored next.
1245 * If the length byte is zero, we need to read the next byte to
1246 * know what to do. [JAY]
1248 if (length != 0)
1251 * [Run-Length] Encoded mode
1253 color_index = (*pIn++); /* Get the colour index. */
1254 color = colors[color_index];
1256 while(length--)
1258 if (x>=dstwidth)
1260 x=0;
1261 line--;
1263 XPutPixel(bmpImage, x++, line, color);
1266 else
1269 * Escape codes (may be an absolute sequence though)
1271 escape_code = (*pIn++);
1272 switch(escape_code)
1274 case RleEol: /* =0, end of line */
1276 x = 0;
1277 line--;
1278 break;
1281 case RleEnd: /* =1, end of bitmap */
1284 * Not all RLE8 bitmaps end with this
1285 * code. For example, Paint Shop Pro
1286 * produces some that don't. That's (I think)
1287 * what caused the previous implementation to
1288 * fail. [JAY]
1290 line=-1; /* Cause exit from do loop. */
1291 break;
1294 case RleDelta: /* =2, a delta */
1297 * Note that deltaing to line 0
1298 * will cause an exit from the loop,
1299 * which may not be what is intended.
1300 * The fact that there is a delta in the bits
1301 * almost certainly implies that there is data
1302 * to follow. You may feel that we should
1303 * jump to the top of the loop to avoid exiting
1304 * in this case.
1306 * TODO: Decide what to do here in that case. [JAY]
1308 x += (*pIn++);
1309 line -= (*pIn++);
1310 if (line == 0)
1312 TRACE("Delta to last line of bitmap "
1313 "(wrongly?) causes loop exit\n");
1315 break;
1318 default: /* >2, switch to absolute mode */
1321 * Absolute Mode
1323 length = escape_code;
1324 while(length--)
1326 color_index = (*pIn++);
1327 if (x>=dstwidth)
1329 x=0;
1330 line--;
1332 XPutPixel(bmpImage, x++, line,
1333 colors[color_index]);
1337 * If you think for a moment you'll realise that the
1338 * only time we could ever possibly read an odd
1339 * number of bytes is when there is a 0x00 (escape),
1340 * a value >0x02 (absolute mode) and then an odd-
1341 * length run. Therefore this is the only place we
1342 * need to worry about it. Everywhere else the
1343 * bytes are always read in pairs. [JAY]
1345 if (escape_code & 1)
1346 pIn++; /* Throw away the pad byte. */
1347 break;
1349 } /* switch (escape_code) : Escape sequence */
1350 } /* process either an encoded sequence or an escape sequence */
1352 /* We expect to come here more than once per line. */
1353 } while (line >= 0); /* Do this until the bitmap is filled */
1356 * Everybody comes here at the end.
1357 * Check how we exited the loop and print a message if it's a bit odd.
1358 * [JAY]
1360 if ( (*(pIn-2) != 0/*escape*/) || (*(pIn-1)!= RleEnd) )
1362 TRACE("End-of-bitmap without (strictly) proper escape code. Last two "
1363 "bytes were: %02X %02X.\n", (int)*(pIn-2),(int)*(pIn-1));
1368 /***********************************************************************
1369 * X11DRV_DIB_SetImageBits_16
1371 * SetDIBits for a 16-bit deep DIB.
1373 static void X11DRV_DIB_SetImageBits_16( int lines, const BYTE *srcbits,
1374 DWORD srcwidth, DWORD dstwidth, int left,
1375 DC *dc, DWORD rSrc, DWORD gSrc, DWORD bSrc,
1376 XImage *bmpImage )
1378 DWORD x;
1379 int h;
1381 /* align to 32 bit */
1382 DWORD linebytes = (srcwidth * 2 + 3) & ~3;
1384 if (lines < 0 )
1386 lines = -lines;
1387 srcbits = srcbits + ( linebytes * (lines-1));
1388 linebytes = -linebytes;
1391 switch ( bmpImage->depth )
1393 case 15:
1394 /* using same format as XImage */
1395 if (rSrc == bmpImage->red_mask && gSrc == bmpImage->green_mask && bSrc == bmpImage->blue_mask)
1396 for (h = lines - 1; h >= 0; h--, srcbits += linebytes)
1397 memcpy ( bmpImage->data + h * bmpImage->bytes_per_line + left*2, srcbits + left*2, dstwidth*2 );
1398 else /* We need to do a conversion from a 565 dib */
1400 LPDWORD dstpixel, ptr = (LPDWORD)(srcbits + left*2);
1401 DWORD val;
1402 int div = dstwidth % 2;
1404 for (h = lines - 1; h >= 0; h--) {
1405 dstpixel = (LPDWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1406 for (x = 0; x < dstwidth/2; x++) { /* Do 2 pixels at a time */
1407 val = *ptr++;
1408 *dstpixel++ = ((val >> 1) & 0x7fe07fe0) | (val & 0x001f001f); /* Red & Green & Blue */
1410 if (div != 0) /* Odd width? */
1411 *dstpixel = ((*(WORD *)ptr >> 1) & 0x7fe0) | (*(WORD *)ptr & 0x001f);
1412 ptr = (LPDWORD) ((srcbits += linebytes) + left*2);
1415 break;
1417 case 16:
1418 /* using same format as XImage */
1419 if (rSrc == bmpImage->red_mask && gSrc == bmpImage->green_mask && bSrc == bmpImage->blue_mask)
1420 for (h = lines - 1; h >= 0; h--, srcbits += linebytes)
1421 memcpy ( bmpImage->data + h * bmpImage->bytes_per_line + left*2, srcbits + left*2, dstwidth*2 );
1422 else /* We need to do a conversion from a 555 dib */
1424 LPDWORD dstpixel, ptr = (LPDWORD)(srcbits + left*2);
1425 DWORD val;
1426 int div = dstwidth % 2;
1428 for (h = lines - 1; h >= 0; h--) {
1429 dstpixel = (LPDWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1430 for (x = 0; x < dstwidth/2; x++) { /* Do 2 pixels at a time */
1431 val = *ptr++;
1432 *dstpixel++ = ((val << 1) & 0xffc0ffc0) | ((val >> 4) & 0x00200020) | /* Red & Green */
1433 (val & 0x001f001f); /* Blue */
1435 if (div != 0) /* Odd width? */
1436 *dstpixel = ((*(WORD *)ptr << 1) & 0xffc0) | ((*(WORD *)ptr >> 4) & 0x0020)
1437 | (*(WORD *)ptr & 0x001f);
1438 ptr = (LPDWORD) ((srcbits += linebytes) + left*2);
1441 break;
1443 case 24:
1444 case 32:
1446 DWORD *dstpixel;
1447 LPWORD ptr = (LPWORD)srcbits + left;
1448 DWORD val;
1450 /* ==== 555 BGR dib to 24/32 BGR bitmap ==== */
1451 if (bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff)
1453 for (h = lines - 1; h >= 0; h--) {
1454 dstpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line + left*4);
1455 for (x = 0; x < dstwidth; x++) {
1457 val = *ptr++;
1458 *dstpixel++ = ((val << 9) & 0xf80000) | ((val << 4) & 0x070000) | /* Red */
1459 ((val << 6) & 0x00f800) | ((val << 1) & 0x000700) | /* Green */
1460 ((val << 3) & 0x0000f8) | ((val >> 2) & 0x000007); /* Blue */
1462 ptr = (LPWORD)(srcbits += linebytes) + left;
1465 /* ==== 555 BGR dib to 24/32 RGB bitmap ==== */
1466 else if (bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000)
1468 for (h = lines - 1; h >= 0; h--) {
1469 dstpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line + left*4);
1470 for (x = 0; x < dstwidth; x++) {
1472 val = *ptr++;
1473 *dstpixel++ = ((val >> 7) & 0x0000f8) | ((val >> 12) & 0x000007) | /* Red */
1474 ((val << 6) & 0x00f800) | ((val << 1) & 0x000700) | /* Green */
1475 ((val << 19) & 0xf80000) | ((val >> 14) & 0x070000); /* Blue */
1477 ptr = (LPWORD)(srcbits += linebytes) + left;
1482 break;
1484 case 1:
1485 case 4:
1486 case 8:
1488 LPWORD ptr = (LPWORD)srcbits + left;
1489 WORD val;
1490 int sc1, sc2;
1492 /* Set color scaling values */
1493 if ( rSrc == 0x7c00 ) { sc1 = 7; sc2 = 2; } /* 555 dib */
1494 else { sc1 = 8; sc2 = 3; } /* 565 dib */
1496 for (h = lines - 1; h >= 0; h--) {
1497 for (x = left; x < dstwidth+left; x++) {
1498 val = *ptr++;
1499 XPutPixel( bmpImage, x, h,
1500 X11DRV_PALETTE_ToPhysical(dc, RGB(((val & rSrc) >> sc1), /* Red */
1501 ((val & gSrc) >> sc2), /* Green */
1502 ((val & bSrc) << 3)))); /* Blue */
1504 ptr = (LPWORD) (srcbits += linebytes) + left;
1507 break;
1509 default:
1510 FIXME("16 bit DIB %d bit bitmap\n", bmpImage->bits_per_pixel);
1511 break;
1517 /***********************************************************************
1518 * X11DRV_DIB_GetImageBits_16
1520 * GetDIBits for an 16-bit deep DIB.
1522 static void X11DRV_DIB_GetImageBits_16( int lines, BYTE *dstbits,
1523 DWORD dstwidth, DWORD srcwidth,
1524 PALETTEENTRY *srccolors, XImage *bmpImage )
1526 DWORD x;
1527 int h;
1529 /* align to 32 bit */
1530 DWORD linebytes = (dstwidth * 2 + 3) & ~3;
1532 if (lines < 0 )
1534 lines = -lines;
1535 dstbits = dstbits + ( linebytes * (lines-1));
1536 linebytes = -linebytes;
1539 switch ( bmpImage->depth )
1541 case 15:
1542 /* ==== 555 BGR bitmap to 555 BGR dib ==== */
1543 if (bmpImage->red_mask == 0x7c00 && bmpImage->blue_mask == 0x001f)
1544 for (h = lines - 1; h >= 0; h--, dstbits += linebytes)
1545 memcpy( dstbits, bmpImage->data + h*bmpImage->bytes_per_line, srcwidth*2 );
1547 /* ==== 555 RGB bitmap to 555 BGR dib ==== */
1548 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0x7c00)
1550 LPDWORD srcpixel, ptr = (LPDWORD)dstbits;
1551 DWORD val;
1552 int div = srcwidth % 2;
1554 for (h = lines - 1; h >= 0; h--) {
1555 srcpixel = (LPDWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
1556 for (x = 0; x < srcwidth/2; x++) { /* Do 2 pixels at a time */
1557 val = *srcpixel++;
1558 *ptr++ = ((val << 10) & 0xf800f800) | (val & 0x03e003e0) | /* Red & Green */
1559 ((val >> 10) & 0x001f001f); /* Blue */
1561 if (div != 0) /* Odd width? */
1562 *ptr = ((*(WORD *)srcpixel << 1) & 0xffc0) | ((*(WORD *)srcpixel >> 4) & 0x0020) |
1563 (*(WORD *)srcpixel & 0x001f);
1564 ptr = (LPDWORD)(dstbits += linebytes);
1567 else goto notsupported;
1569 break;
1571 case 16:
1573 LPDWORD srcpixel, ptr = (LPDWORD)dstbits;
1574 DWORD val;
1575 int div = srcwidth % 2;
1577 /* ==== 565 BGR bitmap to 555 BGR dib ==== */
1578 if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f )
1580 for (h = lines - 1; h >= 0; h--) {
1581 srcpixel = (LPDWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
1582 for (x = 0; x < srcwidth/2; x++) { /* Do 2 pixels at a time */
1583 val = *srcpixel++;
1584 *ptr++ = ((val >> 1) & 0x7fe07fe0) | /* Red & Green */
1585 (val & 0x001f001f); /* Blue */
1587 if (div != 0) /* Odd width? */
1588 *ptr = ((*(WORD *)srcpixel >> 1) & 0x7fe0) | (*(WORD *)srcpixel & 0x001f);
1589 ptr = (LPDWORD) (dstbits += linebytes);
1592 /* ==== 565 RGB bitmap to 555 BGR dib ==== */
1593 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0xf800)
1595 for (h = lines - 1; h >= 0; h--) {
1596 srcpixel = (LPDWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
1597 for (x = 0; x < srcwidth/2; x++) { /* Do 2 pixels at a time */
1598 val = *srcpixel++;
1599 *ptr++ = ((val << 10) & 0x7c007c00) | ((val >> 1) & 0x03e003e0) | /* Red & Green */
1600 ((val >> 11) & 0x001f001f); /* Blue */
1602 if (div != 0) /* Odd width? */
1603 *ptr = ((*(WORD *)srcpixel >> 1) & 0x7fe0) | (*(WORD *)srcpixel & 0x001f);
1604 ptr = (LPDWORD) (dstbits += linebytes);
1607 else goto notsupported;
1609 break;
1611 case 24:
1612 case 32:
1614 DWORD *srcpixel;
1615 LPWORD ptr = (LPWORD)dstbits;
1616 DWORD val;
1618 /* ==== 24/32 BGR bitmap to 555 BGR dib ==== */
1619 if (bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff)
1621 for (h = lines - 1; h >= 0; h--) {
1622 srcpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line);
1623 for (x = 0; x < srcwidth; x++, ptr++) {
1624 val = *srcpixel++;
1625 *ptr = ((val >> 9) & 0x7c00) | /* Red */
1626 ((val >> 6) & 0x03e0) | /* Green */
1627 ((val >> 3) & 0x001f); /* Blue */
1629 ptr = (LPWORD)(dstbits += linebytes);
1632 /* ==== 24/32 RGB bitmap to 555 BGR dib ==== */
1633 else if (bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000)
1635 for (h = lines - 1; h >= 0; h--) {
1636 srcpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line);
1637 for (x = 0; x < srcwidth; x++, ptr++) {
1638 val = *srcpixel++;
1639 *ptr = ((val << 7) & 0x7c00) | /* Red */
1640 ((val >> 6) & 0x03e0) | /* Green */
1641 ((val >> 19) & 0x001f); /* Blue */
1643 ptr = (LPWORD) (dstbits += linebytes);
1646 else goto notsupported;
1648 break;
1650 case 1:
1651 /* ==== monochrome bitmap to 16 BGR dib ==== */
1652 case 4:
1653 /* ==== 4 colormap bitmap to 16 BGR dib ==== */
1654 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
1656 LPWORD ptr = (LPWORD)dstbits;
1657 PALETTEENTRY val;
1659 for (h = lines - 1; h >= 0; h--) {
1660 for (x = 0; x < dstwidth; x++) {
1661 val = srccolors[XGetPixel(bmpImage, x, h)];
1662 *ptr++ = ((val.peRed << 7) & 0x7c00) |
1663 ((val.peGreen << 2) & 0x03e0) |
1664 ((val.peBlue >> 3) & 0x001f);
1666 ptr = (LPWORD)(dstbits += linebytes);
1669 else goto notsupported;
1671 break;
1673 case 8:
1674 /* ==== 8 colormap bitmap to 16 BGR dib ==== */
1675 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
1677 LPWORD ptr = (LPWORD)dstbits;
1678 BYTE *srcpixel;
1679 PALETTEENTRY val;
1681 for (h = lines - 1; h >= 0; h--) {
1682 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
1683 for (x = 0; x < dstwidth; x++) {
1684 val = srccolors[(int)*srcpixel++];
1685 *ptr++ = ((val.peRed << 7) & 0x7c00) |
1686 ((val.peGreen << 2) & 0x03e0) |
1687 ((val.peBlue >> 3) & 0x001f);
1689 ptr = (LPWORD)(dstbits += linebytes);
1692 else goto notsupported;
1694 break;
1696 default:
1697 notsupported:
1699 BYTE r,g, b;
1700 LPWORD ptr = (LPWORD)dstbits;
1702 FIXME("from %d bit bitmap with mask R,G,B %x,%x,%x to 16 bit DIB\n",
1703 bmpImage->depth, (int)bmpImage->red_mask,
1704 (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
1705 for (h = lines - 1; h >= 0; h--)
1707 for (x = 0; x < dstwidth; x++, ptr++)
1709 COLORREF pixel = X11DRV_PALETTE_ToLogical( XGetPixel( bmpImage, x, h ) );
1710 r = (BYTE) GetRValue(pixel);
1711 g = (BYTE) GetGValue(pixel);
1712 b = (BYTE) GetBValue(pixel);
1713 *ptr = ( ((r << 7) & 0x7c00) | ((g << 2) & 0x03e0) | ((b >> 3) & 0x001f) );
1715 ptr = (LPWORD) (dstbits += linebytes);
1718 break;
1723 /***********************************************************************
1724 * X11DRV_DIB_SetImageBits_24
1726 * SetDIBits for a 24-bit deep DIB.
1728 static void X11DRV_DIB_SetImageBits_24( int lines, const BYTE *srcbits,
1729 DWORD srcwidth, DWORD dstwidth, int left,
1730 DC *dc, XImage *bmpImage )
1732 DWORD x;
1733 int h;
1735 /* align to 32 bit */
1736 DWORD linebytes = (srcwidth * 3 + 3) & ~3;
1738 if (lines < 0 )
1740 lines = -lines;
1741 srcbits = srcbits + linebytes * (lines - 1);
1742 linebytes = -linebytes;
1745 switch ( bmpImage->depth )
1747 case 24:
1749 if (bmpImage->bits_per_pixel == 24) {
1750 int dstlinebytes = linebytes;
1751 BYTE *dstpixel;
1752 BYTE *ptr = (BYTE *)(srcbits+left*3);
1754 if (dstlinebytes < 0 ) dstlinebytes = -dstlinebytes;
1755 dstpixel = bmpImage->data + lines*dstlinebytes + left*3;
1756 for(h = lines ; h-- ; ) {
1757 dstpixel-=dstlinebytes;
1758 memcpy(dstpixel,ptr,dstwidth*3);
1759 ptr +=linebytes;
1761 break;
1764 case 32:
1766 if( bmpImage->blue_mask == 0xff && bmpImage->red_mask == 0xff0000 ) /* packed BGR to unpacked BGR */
1768 DWORD *dstpixel, val, buf;
1769 DWORD *ptr = (DWORD *)(srcbits + left*3);
1770 BYTE *bits;
1771 int div = dstwidth % 4;
1772 int divk;
1774 for(h = lines - 1; h >= 0; h--)
1776 dstpixel = (DWORD *) (bmpImage->data + h*bmpImage->bytes_per_line + left*4);
1778 for (x = 0; x < dstwidth/4; x++) { /* do 3 dwords source, 4 dwords dest at a time */
1779 buf = *ptr++;
1780 *dstpixel++ = buf&0x00ffffff; /* b1, g1, r1 */
1781 val = (buf >> 24); /* b2 */
1782 buf = *ptr++;
1783 *dstpixel++ = (val | (buf<<8)) &0x00ffffff; /* g2, r2 */
1784 val = (buf >> 16); /* b3, g3 */
1785 buf = *ptr++;
1786 *dstpixel++ = (val | (buf<<16)) &0x00ffffff; /* r3 */
1787 *dstpixel++ = (buf >> 8); /* b4, g4, r4 */
1789 for ( divk=div, bits=(BYTE*)ptr; divk>0; divk--, bits+=3 ) /* do remainder */
1791 *dstpixel++ = *(DWORD*)bits & 0x00ffffff; /* b, g, r */
1793 ptr = (DWORD*)((srcbits+=linebytes)+left*3);
1796 else if( bmpImage->blue_mask == 0xff0000 && bmpImage->red_mask == 0xff ) /* packed BGR to unpacked RGB */
1798 DWORD *dstpixel, val, buf;
1799 DWORD *ptr = (DWORD *)(srcbits + left*3);
1800 BYTE *bits;
1801 int div = dstwidth % 4;
1802 int divk;
1804 for(h = lines - 1; h >= 0; h--)
1806 dstpixel = (DWORD *) (bmpImage->data + h*bmpImage->bytes_per_line + left*4);
1808 for (x = 0; x < dstwidth/4; x++) { /* do 3 dwords source, 4 dwords dest at a time */
1809 buf = *ptr++;
1810 *dstpixel++ = ((buf&0xff)<<16) | (buf&0xff00) | ((buf&0xff0000)>>16); /* b1, g1, r1 */
1811 val = ((buf&0xff000000)>>8); /* b2 */
1812 buf = *ptr++;
1813 *dstpixel++ = val | ((buf&0xff)<<8) | ((buf&0xff00)>>8); /* g2, r2 */
1814 val = (buf&0xff0000) | ((buf&0xff000000)>>16); /* b3, g3 */
1815 buf = *ptr++;
1816 *dstpixel++ = val | (buf&0xff); /* r3 */
1817 *dstpixel++ = ((buf&0xff00)<<8) | ((buf&0xff0000)>>8) | (buf>>24); /* b4, g4, r4 */
1819 for ( divk=div, bits=(BYTE*)ptr; divk>0; divk--, bits+=3 ) /* do remainder */
1821 buf = *(DWORD*)bits;
1822 *dstpixel++ = ((buf&0xff)<<16) | (buf&0xff00) | ((buf&0xff0000)>>16); /* b, g, r */
1824 ptr = (DWORD*)((srcbits+=linebytes)+left*3);
1827 else
1828 goto notsupported;
1830 break;
1832 case 15:
1834 if( bmpImage->blue_mask == 0x7c00 && bmpImage->red_mask == 0x1f ) /* BGR888 to RGB555 */
1836 DWORD *ptr = (DWORD *)(srcbits + left*3), val;
1837 LPBYTE bits;
1838 LPWORD dstpixel;
1839 int div = dstwidth % 4;
1840 int divk;
1842 for (h = lines - 1; h >= 0; h--) { /* Do 4 pixels at a time */
1843 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1844 for (x = 0; x < dstwidth/4; x++) {
1845 *dstpixel++ = (WORD)((((val = *ptr++) << 7) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 19) & 0x1f));
1846 *dstpixel++ = (WORD)(((val >> 17) & 0x7c00) | (((val = *ptr++) << 2) & 0x03e0) | ((val >> 11) & 0x1f));
1847 *dstpixel++ = (WORD)(((val >> 9) & 0x07c00) | ((val >> 22) & 0x03e0) | (((val = *ptr++) >> 3) & 0x1f));
1848 *dstpixel++ = (WORD)(((val >> 1) & 0x07c00) | ((val >> 14) & 0x03e0) | ((val >> 27) & 0x1f));
1850 for (bits = (LPBYTE)ptr, divk=div; divk > 0; divk--, bits+=3) /* dstwidth not divisible by 4? */
1851 *dstpixel++ = (((WORD)bits[0] << 7) & 0x07c00) |
1852 (((WORD)bits[1] << 2) & 0x03e0) |
1853 (((WORD)bits[2] >> 3) & 0x001f);
1854 ptr = (DWORD *)((srcbits += linebytes) + left * 3);
1857 else if( bmpImage->blue_mask == 0x1f && bmpImage->red_mask == 0x7c00 ) /* BGR888 to BGR555 */
1859 DWORD *ptr = (DWORD *)(srcbits + left*3), val;
1860 LPBYTE bits;
1861 LPWORD dstpixel;
1862 int div = dstwidth % 4;
1863 int divk;
1865 for (h = lines - 1; h >= 0; h--) { /* Do 4 pixels at a time */
1866 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1867 for (x = 0; x < dstwidth/4; x++) {
1868 *dstpixel++ = (WORD)((((val = *ptr++) >> 3) & 0x1f) | ((val >> 6) & 0x03e0) | ((val >> 9) & 0x7c00));
1869 *dstpixel++ = (WORD)(((val >> 27) & 0x1f) | (((val = *ptr++) << 2) & 0x03e0) | ((val >> 1) & 0x7c00));
1870 *dstpixel++ = (WORD)(((val >> 19) & 0x1f) | ((val >> 22) & 0x03e0) | (((val = *ptr++) << 7) & 0x7c00));
1871 *dstpixel++ = (WORD)(((val >> 11) & 0x1f) | ((val >> 14) & 0x03e0) | ((val >> 17) & 0x7c00));
1873 for (bits = (LPBYTE)ptr, divk=div; divk > 0; divk--, bits+=3) /* dstwidth not divisible by 4? */
1874 *dstpixel++ = (((WORD)bits[2] << 7) & 0x07c00) |
1875 (((WORD)bits[1] << 2) & 0x03e0) |
1876 (((WORD)bits[0] >> 3) & 0x001f);
1877 ptr = (DWORD *)((srcbits += linebytes) + left * 3);
1880 else
1881 goto notsupported;
1883 break;
1885 case 16:
1887 DWORD *ptr = (DWORD *)(srcbits + left*3), val;
1888 LPBYTE bits;
1889 LPWORD dstpixel;
1890 int div = dstwidth % 4;
1891 int divk;
1893 if( bmpImage->blue_mask == 0x001f && bmpImage->red_mask == 0xf800 ) /* BGR888 to BGR565 */
1895 for (h = lines - 1; h >= 0; h--) { /* Do 4 pixels at a time */
1896 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1897 for (x = 0; x < dstwidth/4; x++) {
1898 *dstpixel++ = (WORD)((((val = *ptr++) >> 3) & 0x1f) | ((val >> 5) & 0x07e0) | ((val >> 8) & 0xf800));
1899 *dstpixel++ = (WORD)(((val >> 27) & 0x1f) | (((val = *ptr++) << 3) & 0x07e0) | ((val) & 0xf800));
1900 *dstpixel++ = (WORD)(((val >> 19) & 0x1f) | ((val >> 21) & 0x07e0) | (((val = *ptr++) << 8) & 0xf800));
1901 *dstpixel++ = (WORD)(((val >> 11) & 0x1f) | ((val >> 13) & 0x07e0) | ((val >> 16) & 0xf800));
1903 for ( bits = (LPBYTE)ptr, divk=div; divk > 0; divk--, bits+=3) /* dstwidth is not divisible by 4? */
1904 *dstpixel++ = (((WORD)bits[2] << 8) & 0xf800) |
1905 (((WORD)bits[1] << 3) & 0x07e0) |
1906 (((WORD)bits[0] >> 3) & 0x001f);
1907 ptr = (DWORD *)((srcbits += linebytes) + left * 3);
1910 else if( bmpImage->blue_mask == 0xf800 && bmpImage->red_mask == 0x001f ) /* BGR888 to RGB565 */
1912 for (h = lines - 1; h >= 0; h--) { /* Do 4 pixels at a time */
1913 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1914 for (x = 0; x < dstwidth/4; x++) {
1915 *dstpixel++ = (WORD)((((val = *ptr++) << 8) & 0xf800) | ((val >> 5) & 0x07e0) | ((val >> 19) & 0x1f));
1916 *dstpixel++ = (WORD)(((val >> 16) & 0xf800) | (((val = *ptr++) << 3) & 0x07e0) | ((val >> 11) & 0x1f));
1917 *dstpixel++ = (WORD)(((val >> 8) & 0xf800) | ((val >> 21) & 0x07e0) | (((val = *ptr++) >> 3) & 0x1f));
1918 *dstpixel++ = (WORD)((val & 0xf800) | ((val >> 13) & 0x07e0) | ((val >> 27) & 0x1f));
1920 for ( bits = (LPBYTE)ptr, divk=div; divk > 0; divk--, bits+=3) /* dstwidth is not divisible by 4? */
1921 *dstpixel++ = (((WORD)bits[0] << 8) & 0xf800) |
1922 (((WORD)bits[1] << 3) & 0x07e0) |
1923 (((WORD)bits[2] >> 3) & 0x001f);
1924 ptr = (DWORD *)((srcbits += linebytes) + left * 3);
1927 else
1928 goto notsupported;
1930 break;
1932 case 1:
1933 case 4:
1934 case 8:
1936 LPBYTE bits = (LPBYTE)srcbits + left*3;
1938 for (h = lines - 1; h >= 0; h--) {
1939 for (x = left; x < dstwidth+left; x++, bits+=3)
1940 XPutPixel( bmpImage, x, h,
1941 X11DRV_PALETTE_ToPhysical(dc, RGB(bits[2], bits[1], bits[0])));
1942 bits = (LPBYTE)(srcbits += linebytes) + left * 3;
1945 break;
1947 default:
1948 notsupported:
1949 FIXME("from 24 bit DIB to %d bit bitmap with mask R,G,B %x,%x,%x\n",
1950 bmpImage->bits_per_pixel, (int)bmpImage->red_mask,
1951 (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
1952 break;
1957 /***********************************************************************
1958 * X11DRV_DIB_GetImageBits_24
1960 * GetDIBits for an 24-bit deep DIB.
1962 static void X11DRV_DIB_GetImageBits_24( int lines, BYTE *dstbits,
1963 DWORD dstwidth, DWORD srcwidth,
1964 PALETTEENTRY *srccolors, XImage *bmpImage )
1966 DWORD x, val;
1967 int h;
1969 /* align to 32 bit */
1970 DWORD linebytes = (dstwidth * 3 + 3) & ~3;
1972 if (lines < 0 )
1974 lines = -lines;
1975 dstbits = dstbits + ( linebytes * (lines-1) );
1976 linebytes = -linebytes;
1979 switch ( bmpImage->depth )
1981 case 24:
1983 if (bmpImage->bits_per_pixel == 24) {
1984 int tocopy = linebytes;
1985 BYTE *srcpixel;
1986 BYTE *ptr = (LPBYTE)dstbits;
1988 if (tocopy < 0 ) tocopy = -tocopy;
1989 srcpixel = bmpImage->data + lines*tocopy;
1990 for(h = lines ; h-- ; ) {
1991 srcpixel-=tocopy;
1992 memcpy(ptr,srcpixel,tocopy);
1993 ptr = (LPBYTE)(dstbits+=linebytes);
1995 break;
1998 case 32:
2000 DWORD *srcpixel, buf;
2001 LPBYTE bits;
2002 DWORD *ptr=(DWORD *)dstbits;
2003 int quotient = dstwidth / 4;
2004 int remainder = dstwidth % 4;
2005 int remk;
2007 /* ==== 24/32 BGR bitmap to 24 BGR dib==== */
2008 if( bmpImage->blue_mask == 0xff && bmpImage->red_mask == 0xff0000 )
2010 for(h = lines - 1; h >= 0; h--)
2012 srcpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line);
2014 for (x = 0; x < quotient; x++) { /* do 4 dwords source, 3 dwords dest at a time */
2015 buf = ((*srcpixel++)&0x00ffffff); /* b1, g1, r1*/
2016 *ptr++ = buf | ((*srcpixel)<<24); /* b2 */
2017 buf = ((*srcpixel++>>8)&0x0000ffff); /* g2, r2 */
2018 *ptr++ = buf | ((*srcpixel)<<16); /* b3, g3 */
2019 buf = ((*srcpixel++>>16)&0x000000ff); /* r3 */
2020 *ptr++ = buf | ((*srcpixel++)<<8); /* b4, g4, r4 */
2022 for ( remk=remainder, bits=(BYTE*)ptr; remk>0; remk--, bits+=3 ) /* do remainder */
2024 buf=*srcpixel++;
2025 *(WORD*)bits = buf; /* b, g */
2026 *(bits+2) = buf>>16; /* r */
2028 ptr = (DWORD*)(dstbits+=linebytes);
2032 /* ==== 24/32 RGB bitmap to 24 BGR dib ==== */
2033 else if( bmpImage->blue_mask == 0xff0000 && bmpImage->red_mask == 0xff )
2035 for(h = lines - 1; h >= 0; h--)
2037 srcpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line);
2039 for (x = 0; x < quotient; x++) { /* do 4 dwords source, 3 dwords dest at a time */
2040 buf = *srcpixel++;
2041 val = ((buf&0xff0000)>>16) | (buf&0xff00) | ((buf&0xff)<<16); /* b1, g1, r1 */
2042 buf = *srcpixel++;
2043 *ptr++ = val | ((buf&0xff0000)<<8); /* b2 */
2044 val = ((buf&0xff00)>>8) | ((buf&0xff)<<8); /* g2, r2 */
2045 buf = *srcpixel++;
2046 *ptr++ = val | (buf&0xff0000) | ((buf&0xff00)<<16); /* b3, g3 */
2047 val = (buf&0xff); /* r3 */
2048 buf = *srcpixel++;
2049 *ptr++ = val | ((buf&0xff0000)>>8) | ((buf&0xff00)<<8) | (buf<<24); /* b4, g4, r4 */
2051 for ( remk=remainder, bits=(BYTE*)ptr; remk>0; remk--, bits+=3 ) /* do remainder */
2053 buf=*srcpixel++;
2054 *(WORD*)bits = (buf&0xff00) | ((buf&0xff0000)>>16) ; /* b, g */
2055 *(bits+2) = buf; /* r */
2057 ptr = (DWORD*)(dstbits+=linebytes);
2060 else goto notsupported;
2062 break;
2064 case 15:
2066 LPWORD srcpixel;
2067 LPBYTE bits = dstbits;
2068 WORD val;
2070 /* ==== 555 BGR bitmap to 24 BGR dib ==== */
2071 if( bmpImage->blue_mask == 0x1f && bmpImage->red_mask == 0x7c00 )
2073 for (h = lines - 1; h >= 0; h--) {
2074 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2075 for (x = 0; x < srcwidth; x++, bits += 3) {
2076 val = *srcpixel++;
2077 bits[2] = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07)); /*Red*/
2078 bits[1] = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07)); /*Green*/
2079 bits[0] = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07)); /*Blue*/
2081 bits = (dstbits += linebytes);
2084 /* ==== 555 RGB bitmap to 24 RGB dib==== */
2085 else if( bmpImage->blue_mask == 0x7c00 && bmpImage->red_mask == 0x1f )
2087 for (h = lines - 1; h >= 0; h--) {
2088 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2089 for (x = 0; x < srcwidth; x++, bits += 3) {
2090 val = *srcpixel++;
2091 bits[0] = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07)); /*Red*/
2092 bits[1] = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07)); /*Green*/
2093 bits[2] = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07)); /*Blue*/
2095 bits = (dstbits += linebytes);
2098 else goto notsupported;
2100 break;
2102 case 16:
2104 LPWORD srcpixel;
2105 LPBYTE bits = dstbits;
2106 WORD val;
2108 /* ==== 565 BGR bitmap to 24 BGR dib ==== */
2109 if( bmpImage->blue_mask == 0x1f && bmpImage->red_mask == 0xf800 )
2111 for (h = lines - 1; h >= 0; h--) {
2112 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2113 for (x = 0; x < srcwidth; x++, bits += 3) {
2114 val = *srcpixel++;
2115 bits[2] = (BYTE)(((val >> 8) & 0xf8) | ((val >> 13) & 0x07)); /*Red*/
2116 bits[1] = (BYTE)(((val >> 3) & 0xfc) | ((val >> 9) & 0x03)); /*Green*/
2117 bits[0] = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07)); /*Blue*/
2119 bits = (dstbits += linebytes);
2122 /* ==== 565 RGB bitmap to 24 BGR dib ==== */
2123 else if( bmpImage->blue_mask == 0xf800 && bmpImage->red_mask == 0x1f )
2125 for (h = lines - 1; h >= 0; h--) {
2126 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2127 for (x = 0; x < srcwidth; x++, bits += 3) {
2128 val = *srcpixel++;
2129 bits[0] = (BYTE)(((val >> 8) & 0xf8) | ((val >> 13) & 0x07)); /*Red*/
2130 bits[1] = (BYTE)(((val >> 3) & 0xfc) | ((val >> 9) & 0x03)); /*Green*/
2131 bits[2] = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07)); /*Blue*/
2133 bits = (dstbits += linebytes);
2136 else goto notsupported;
2138 break;
2140 case 1:
2141 /* ==== monochrome bitmap to 24 BGR dib ==== */
2142 case 4:
2143 /* ==== 4 colormap bitmap to 24 BGR dib ==== */
2144 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
2146 LPBYTE bits = dstbits;
2147 PALETTEENTRY val;
2149 for (h = lines - 1; h >= 0; h--) {
2150 for (x = 0; x < dstwidth; x++) {
2151 val = srccolors[XGetPixel(bmpImage, x, h)];
2152 *bits++ = val.peBlue;
2153 *bits++ = val.peGreen;
2154 *bits++ = val.peRed;
2156 bits = (dstbits += linebytes);
2159 else goto notsupported;
2161 break;
2163 case 8:
2164 /* ==== 8 colormap bitmap to 24 BGR dib ==== */
2165 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask == 0 && srccolors)
2167 BYTE *srcpixel;
2168 LPBYTE bits = dstbits;
2169 PALETTEENTRY val;
2171 for (h = lines - 1; h >= 0; h--) {
2172 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
2173 for (x = 0; x < dstwidth; x++ ) {
2174 val = srccolors[(int)*srcpixel++];
2175 *bits++ = val.peBlue; /*Blue*/
2176 *bits++ = val.peGreen; /*Green*/
2177 *bits++ = val.peRed; /*Red*/
2179 bits = (dstbits += linebytes);
2182 else goto notsupported;
2184 break;
2186 default:
2187 notsupported:
2189 LPBYTE bits = dstbits;
2191 FIXME("from %d bit bitmap with mask R,G,B %x,%x,%x to 24 bit DIB\n",
2192 bmpImage->depth, (int)bmpImage->red_mask,
2193 (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
2194 for (h = lines - 1; h >= 0; h--)
2196 for (x = 0; x < dstwidth; x++, bits += 3)
2198 COLORREF pixel = X11DRV_PALETTE_ToLogical( XGetPixel( bmpImage, x, h ) );
2199 bits[0] = GetBValue(pixel);
2200 bits[1] = GetGValue(pixel);
2201 bits[2] = GetRValue(pixel);
2203 bits = (dstbits += linebytes);
2206 break;
2211 /***********************************************************************
2212 * X11DRV_DIB_SetImageBits_32
2214 * SetDIBits for a 32-bit deep DIB.
2216 static void X11DRV_DIB_SetImageBits_32( int lines, const BYTE *srcbits,
2217 DWORD srcwidth, DWORD dstwidth, int left,
2218 DC *dc, XImage *bmpImage )
2220 DWORD x, *ptr;
2221 int h;
2223 DWORD linebytes = (srcwidth * 4);
2225 if (lines < 0 )
2227 lines = -lines;
2228 srcbits = srcbits + ( linebytes * (lines-1) );
2229 linebytes = -linebytes;
2232 ptr = (DWORD *) srcbits + left;
2234 switch ( bmpImage->depth )
2236 case 32:
2237 /* ==== 32 BGR dib to 24/32 BGR bitmap ==== */
2238 if (bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff) {
2239 for (h = lines - 1; h >= 0; h--, srcbits+=linebytes) {
2240 memcpy( bmpImage->data + h * bmpImage->bytes_per_line, srcbits + left*4, dstwidth*4 );
2244 /* ==== 32 BGR dib to 24/32 RGB bitmap ==== */
2245 else if (bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000)
2247 DWORD *dstpixel;
2249 for (h = lines - 1; h >= 0; h--) {
2250 dstpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line);
2251 for (x = 0; x < dstwidth; x++, ptr++) {
2252 *dstpixel++ = ((*ptr << 16) & 0xff0000) | (*ptr & 0xff00) | ((*ptr >> 16) & 0xff);
2254 ptr = (DWORD *) (srcbits += linebytes) + left;
2257 else goto notsupported;
2259 break;
2261 case 24:
2262 /* ==== 32 BGR dib to 24 (888) BGR bitmap ==== */
2263 /* we need to check that source mask matches destination */
2265 BYTE *bptr;
2267 ptr = (DWORD *) srcbits + left;
2268 bptr = bmpImage->data;
2270 for (h = lines - 1; h >= 0; h--) {
2271 for (x = 0; x < dstwidth; x++) {
2272 /* *ptr is a 32bit value */
2273 /* bptr points to first of 3 bytes */
2274 *bptr++ = (*ptr >> 16) & 0xff;
2275 *bptr++ = (*ptr >> 8) & 0xff;
2276 *bptr++ = (*ptr ) & 0xff;
2277 ptr++;
2279 ptr = (DWORD *) (srcbits += linebytes) + left;
2282 break;
2284 case 15:
2285 /* ==== 32 BGR dib to 555 BGR bitmap ==== */
2286 if (bmpImage->red_mask == 0x7c00 && bmpImage->blue_mask == 0x001f) {
2287 LPWORD dstpixel;
2289 for (h = lines - 1; h >= 0; h--) {
2290 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2291 for (x = 0; x < dstwidth; x++, ptr++) {
2292 *dstpixel++ = (WORD) (((*ptr >> 9) & 0x7c00) | ((*ptr >> 6) & 0x03e0) | ((*ptr >> 3) & 0x001f));
2294 ptr = (DWORD *) (srcbits += linebytes) + left;
2297 /* ==== 32 BGR dib to 555 RGB bitmap ==== */
2298 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0x7c00)
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 << 7) & 0x7c00) | ((*ptr >> 6) & 0x03e0) | ((*ptr >> 19) & 0x001f));
2307 ptr = (DWORD *) (srcbits += linebytes) + left;
2310 else goto notsupported;
2312 break;
2314 case 16:
2315 /* ==== 32 BGR dib to 565 BGR bitmap ==== */
2316 if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f)
2318 LPWORD dstpixel;
2320 for (h = lines - 1; h >= 0; h--) {
2321 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2322 for (x = 0; x < dstwidth; x++, ptr++) {
2323 *dstpixel++ = (WORD) (((*ptr >> 8) & 0xf800) | ((*ptr >> 5) & 0x07e0) | ((*ptr >> 3) & 0x001f));
2325 ptr = (DWORD *) (srcbits += linebytes) + left;
2328 /* ==== 32 BGR dib to 565 RGB bitmap ==== */
2329 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0xf800)
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 >> 19) & 0x001f));
2338 ptr = (DWORD *) (srcbits += linebytes) + left;
2341 else goto notsupported;
2343 break;
2345 case 1:
2346 case 4:
2347 case 8:
2349 LPBYTE bits = (LPBYTE)srcbits + left*4;
2351 for (h = lines - 1; h >= 0; h--) {
2352 for (x = left; x < dstwidth+left; x++, bits += 4)
2353 XPutPixel( bmpImage, x, h,
2354 X11DRV_PALETTE_ToPhysical(dc, RGB( bits[2], bits[1], *bits )));
2355 bits = (LPBYTE)(srcbits += linebytes) + left * 4;
2358 break;
2360 default:
2361 notsupported:
2362 FIXME("32 bit DIB %d bit bitmap\n", bmpImage->bits_per_pixel);
2363 break;
2368 /***********************************************************************
2369 * X11DRV_DIB_GetImageBits_32
2371 * GetDIBits for an 32-bit deep DIB.
2373 static void X11DRV_DIB_GetImageBits_32( int lines, BYTE *dstbits,
2374 DWORD dstwidth, DWORD srcwidth,
2375 PALETTEENTRY *srccolors, XImage *bmpImage )
2377 DWORD x;
2378 int h;
2379 BYTE *bits;
2381 /* align to 32 bit */
2382 DWORD linebytes = (srcwidth * 4);
2383 DWORD copybytes = linebytes;
2385 if (lines < 0 )
2387 lines = -lines;
2388 dstbits = dstbits + ( linebytes * (lines-1) );
2389 linebytes = -linebytes;
2392 bits = dstbits;
2394 switch ( bmpImage->depth )
2396 case 32:
2397 /* ==== 24/32 BGR bitmap to 32 BGR dib ==== */
2398 if ( bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff )
2399 for (h = lines - 1; h >= 0; h--, dstbits+=linebytes)
2400 memcpy( dstbits, bmpImage->data + h*bmpImage->bytes_per_line, copybytes );
2402 /* ==== 24/32 RGB bitmap to 32 BGR dib ==== */
2403 else if ( bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000 )
2405 LPBYTE srcbits;
2407 for (h = lines - 1; h >= 0; h--) {
2408 srcbits = bmpImage->data + h * bmpImage->bytes_per_line;
2409 for (x = 0; x < dstwidth; x++, bits+=4, srcbits+=2) {
2410 *(bits + 2) = *srcbits++;
2411 *(bits + 1) = *srcbits++;
2412 *bits = *srcbits;
2414 bits = (dstbits += linebytes);
2417 else goto notsupported;
2418 break;
2420 case 24:
2421 /* ==== 24 BGR bitmap to 32 (0888) BGR dib ==== */
2422 /* we need to check that source mask matches destination */
2424 DWORD *srcpixel;
2425 BYTE *bptr;
2426 DWORD srcdata;
2428 srcpixel = (DWORD *) dstbits;
2429 bptr = bmpImage->data;
2431 for (h = lines - 1; h >= 0; h--) {
2432 for (x = 0; x < dstwidth; x++) {
2433 /* *srcpixel is a 32bit value */
2434 /* bptr points to first of 3 bytes */
2435 srcdata = 0;
2436 srcdata = srcdata << 8 | *bptr++;
2437 srcdata = srcdata << 8 | *bptr++;
2438 srcdata = srcdata << 8 | *bptr++;
2440 *srcpixel++ = srcdata;
2442 srcpixel = (DWORD *) (dstbits += linebytes);
2445 break;
2447 case 15:
2449 LPWORD srcpixel;
2450 WORD val;
2452 /* ==== 555 BGR bitmap to 32 BGR dib ==== */
2453 if (bmpImage->red_mask == 0x7c00 && bmpImage->blue_mask == 0x001f)
2455 for (h = lines - 1; h >= 0; h--) {
2456 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2457 for (x = 0; x < dstwidth; x++, bits+=2) {
2458 val = *srcpixel++;
2459 *bits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x03)); /*Blue*/
2460 *bits++ = (BYTE)(((val >> 2) & 0xfc) | ((val >> 8) & 0x03)); /*Green*/
2461 *bits = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07)); /*Red*/
2463 bits = (dstbits += linebytes);
2466 /* ==== 555 RGB bitmap to 32 BGR dib ==== */
2467 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0x7c00)
2469 for (h = lines - 1; h >= 0; h--) {
2470 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2471 for (x = 0; x < dstwidth; x++, bits+=2) {
2472 val = *srcpixel++;
2473 *bits++ = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07));/*Blue*/
2474 *bits++ = (BYTE)(((val >> 2) & 0xfc) | ((val >> 8) & 0x03)); /*Green*/
2475 *bits = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x03)); /*Red*/
2477 bits = (dstbits += linebytes);
2480 else goto notsupported;
2482 break;
2484 case 16:
2486 LPWORD srcpixel;
2487 WORD val;
2489 /* ==== 565 BGR bitmap to 32 BGR dib ==== */
2490 if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f)
2492 for (h = lines - 1; h >= 0; h--) {
2493 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2494 for (x = 0; x < srcwidth; x++, bits+=2) {
2495 val = *srcpixel++;
2496 *bits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x03)); /*Blue*/
2497 *bits++ = (BYTE)(((val >> 3) & 0xfc) | ((val >> 9) & 0x03)); /*Green*/
2498 *bits = (BYTE)(((val >> 8) & 0xf8) | ((val >> 13) & 0x07)); /*Red*/
2500 bits = (dstbits += linebytes);
2503 /* ==== 565 RGB bitmap to 32 BGR dib ==== */
2504 else if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f)
2506 for (h = lines - 1; h >= 0; h--) {
2507 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2508 for (x = 0; x < srcwidth; x++, bits+=2) {
2509 val = *srcpixel++;
2510 *bits++ = (BYTE)(((val >> 8) & 0xf8) | ((val >> 13) & 0x07));/*Blue*/
2511 *bits++ = (BYTE)(((val >> 3) & 0xfc) | ((val >> 9) & 0x03)); /*Green*/
2512 *bits = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x03)); /*Red*/
2514 bits = (dstbits += linebytes);
2517 else goto notsupported;
2519 break;
2521 case 1:
2522 /* ==== monochrome bitmap to 32 BGR dib ==== */
2523 case 4:
2524 /* ==== 4 colormap bitmap to 32 BGR dib ==== */
2525 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
2527 PALETTEENTRY val;
2529 for (h = lines - 1; h >= 0; h--) {
2530 for (x = 0; x < dstwidth; x++) {
2531 val = srccolors[XGetPixel(bmpImage, x, h)];
2532 *bits++ = val.peBlue;
2533 *bits++ = val.peGreen;
2534 *bits++ = val.peRed;
2535 *bits++ = 0;
2537 bits = (dstbits += linebytes);
2540 else goto notsupported;
2542 break;
2544 case 8:
2545 /* ==== 8 colormap bitmap to 32 BGR dib ==== */
2546 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
2548 BYTE *srcpixel;
2549 PALETTEENTRY val;
2551 for (h = lines - 1; h >= 0; h--) {
2552 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
2553 for (x = 0; x < dstwidth; x++) {
2554 val = srccolors[(int)*srcpixel++];
2555 *bits++ = val.peBlue; /*Blue*/
2556 *bits++ = val.peGreen; /*Green*/
2557 *bits++ = val.peRed; /*Red*/
2558 *bits++ = 0;
2560 bits = (dstbits += linebytes);
2563 else goto notsupported;
2564 break;
2566 default:
2567 notsupported:
2568 FIXME("from %d bit bitmap with mask R,G,B %x,%x,%x to 32 bit DIB\n",
2569 bmpImage->depth, (int)bmpImage->red_mask,
2570 (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
2571 for (h = lines - 1; h >= 0; h--)
2573 for (x = 0; x < dstwidth; x++, bits += 4)
2575 COLORREF pixel = X11DRV_PALETTE_ToLogical( XGetPixel( bmpImage, x, h ) );
2576 bits[0] = GetBValue(pixel);
2577 bits[1] = GetGValue(pixel);
2578 bits[2] = GetRValue(pixel);
2580 bits = (dstbits += linebytes);
2582 break;
2586 /***********************************************************************
2587 * X11DRV_DIB_SetImageBits
2589 * Transfer the bits to an X image.
2590 * Helper function for SetDIBits() and SetDIBitsToDevice().
2591 * The Xlib critical section must be entered before calling this function.
2593 int X11DRV_DIB_SetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
2595 int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
2596 XImage *bmpImage;
2598 if (descr->image)
2599 bmpImage = descr->image;
2600 else {
2601 bmpImage = XCreateImage( display, X11DRV_GetVisual(), descr->depth, ZPixmap, 0, NULL,
2602 descr->infoWidth, lines, 32, 0 );
2603 bmpImage->data = calloc( lines, bmpImage->bytes_per_line );
2604 if(bmpImage->data == NULL) {
2605 ERR("Out of memory!\n");
2606 XDestroyImage( bmpImage );
2607 return lines;
2611 /* Transfer the pixels */
2612 switch(descr->infoBpp)
2614 case 1:
2615 X11DRV_DIB_SetImageBits_1( descr->lines, descr->bits, descr->infoWidth,
2616 descr->width, descr->xSrc, (int *)(descr->colorMap),
2617 bmpImage );
2618 break;
2619 case 4:
2620 if (descr->compression) {
2621 XGetSubImage( display, descr->drawable, descr->xDest, descr->yDest,
2622 descr->width, descr->height, AllPlanes, ZPixmap,
2623 bmpImage, descr->xSrc, descr->ySrc );
2625 X11DRV_DIB_SetImageBits_RLE4( descr->lines, descr->bits,
2626 descr->infoWidth, descr->width,
2627 descr->xSrc, (int *)(descr->colorMap),
2628 bmpImage );
2629 } else
2630 X11DRV_DIB_SetImageBits_4( descr->lines, descr->bits,
2631 descr->infoWidth, descr->width,
2632 descr->xSrc, (int*)(descr->colorMap),
2633 bmpImage );
2634 break;
2635 case 8:
2636 if (descr->compression) {
2637 XGetSubImage( display, descr->drawable, descr->xDest, descr->yDest,
2638 descr->width, descr->height, AllPlanes, ZPixmap,
2639 bmpImage, descr->xSrc, descr->ySrc );
2640 X11DRV_DIB_SetImageBits_RLE8( descr->lines, descr->bits,
2641 descr->infoWidth, descr->width,
2642 descr->xSrc, (int *)(descr->colorMap),
2643 bmpImage );
2644 } else
2645 X11DRV_DIB_SetImageBits_8( descr->lines, descr->bits,
2646 descr->infoWidth, descr->width,
2647 descr->xSrc, (int *)(descr->colorMap),
2648 bmpImage );
2649 break;
2650 case 15:
2651 case 16:
2652 X11DRV_DIB_SetImageBits_16( descr->lines, descr->bits,
2653 descr->infoWidth, descr->width,
2654 descr->xSrc, descr->dc,
2655 descr->rMask, descr->gMask, descr->bMask,
2656 bmpImage);
2657 break;
2658 case 24:
2659 X11DRV_DIB_SetImageBits_24( descr->lines, descr->bits,
2660 descr->infoWidth, descr->width,
2661 descr->xSrc, descr->dc, bmpImage );
2662 break;
2663 case 32:
2664 X11DRV_DIB_SetImageBits_32( descr->lines, descr->bits,
2665 descr->infoWidth, descr->width,
2666 descr->xSrc, descr->dc,
2667 bmpImage);
2668 break;
2669 default:
2670 WARN("(%d): Invalid depth\n", descr->infoBpp );
2671 break;
2674 if (descr->useShm)
2676 XShmPutImage( display, descr->drawable, descr->gc, bmpImage,
2677 descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
2678 descr->width, descr->height, FALSE );
2679 XSync( display, 0 );
2681 else
2682 XPutImage( display, descr->drawable, descr->gc, bmpImage,
2683 descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
2684 descr->width, descr->height );
2686 if (!descr->image) XDestroyImage( bmpImage );
2687 return lines;
2690 /***********************************************************************
2691 * X11DRV_DIB_GetImageBits
2693 * Transfer the bits from an X image.
2694 * The Xlib critical section must be entered before calling this function.
2696 int X11DRV_DIB_GetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
2698 int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
2699 XImage *bmpImage;
2701 if (descr->image)
2702 bmpImage = descr->image;
2703 else {
2704 bmpImage = XCreateImage( display, X11DRV_GetVisual(), descr->depth, ZPixmap, 0, NULL,
2705 descr->infoWidth, lines, 32, 0 );
2706 bmpImage->data = calloc( lines, bmpImage->bytes_per_line );
2707 if(bmpImage->data == NULL) {
2708 ERR("Out of memory!\n");
2709 XDestroyImage( bmpImage );
2710 return lines;
2713 XGetSubImage( display, descr->drawable, descr->xSrc, descr->ySrc,
2714 descr->width, lines, AllPlanes, ZPixmap,
2715 bmpImage, descr->xDest, descr->yDest );
2717 /* Transfer the pixels */
2718 switch(descr->infoBpp)
2720 case 1:
2721 X11DRV_DIB_GetImageBits_1( descr->lines,(LPVOID)descr->bits,
2722 descr->infoWidth, descr->width,
2723 descr->colorMap, descr->palentry,
2724 bmpImage );
2725 break;
2727 case 4:
2728 if (descr->compression)
2729 FIXME("Compression not yet supported!\n");
2730 else
2731 X11DRV_DIB_GetImageBits_4( descr->lines,(LPVOID)descr->bits,
2732 descr->infoWidth, descr->width,
2733 descr->colorMap, descr->palentry,
2734 bmpImage );
2735 break;
2737 case 8:
2738 if (descr->compression)
2739 FIXME("Compression not yet supported!\n");
2740 else
2741 X11DRV_DIB_GetImageBits_8( descr->lines, (LPVOID)descr->bits,
2742 descr->infoWidth, descr->width,
2743 descr->colorMap, descr->palentry,
2744 bmpImage );
2745 break;
2746 case 15:
2747 case 16:
2748 X11DRV_DIB_GetImageBits_16( descr->lines, (LPVOID)descr->bits,
2749 descr->infoWidth,descr->width,
2750 descr->palentry, bmpImage );
2751 break;
2753 case 24:
2754 X11DRV_DIB_GetImageBits_24( descr->lines, (LPVOID)descr->bits,
2755 descr->infoWidth,descr->width,
2756 descr->palentry, bmpImage );
2757 break;
2759 case 32:
2760 X11DRV_DIB_GetImageBits_32( descr->lines, (LPVOID)descr->bits,
2761 descr->infoWidth, descr->width,
2762 descr->palentry, bmpImage );
2763 break;
2765 default:
2766 WARN("(%d): Invalid depth\n", descr->infoBpp );
2767 break;
2770 if (!descr->image) XDestroyImage( bmpImage );
2771 return lines;
2774 /*************************************************************************
2775 * X11DRV_SetDIBitsToDevice
2778 INT X11DRV_SetDIBitsToDevice( DC *dc, INT xDest, INT yDest, DWORD cx,
2779 DWORD cy, INT xSrc, INT ySrc,
2780 UINT startscan, UINT lines, LPCVOID bits,
2781 const BITMAPINFO *info, UINT coloruse )
2783 X11DRV_DIB_IMAGEBITS_DESCR descr;
2784 DWORD width, oldcy = cy;
2785 INT result;
2786 int height, tmpheight;
2787 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
2790 if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height,
2791 &descr.infoBpp, &descr.compression ) == -1)
2792 return 0;
2793 tmpheight = height;
2794 if (height < 0) height = -height;
2795 if (!lines || (startscan >= height)) return 0;
2796 if (startscan + lines > height) lines = height - startscan;
2797 if (ySrc < startscan) ySrc = startscan;
2798 else if (ySrc >= startscan + lines) return 0;
2799 if (xSrc >= width) return 0;
2800 if (ySrc + cy >= startscan + lines) cy = startscan + lines - ySrc;
2801 if (xSrc + cx >= width) cx = width - xSrc;
2802 if (!cx || !cy) return 0;
2804 X11DRV_SetupGCForText( dc ); /* To have the correct colors */
2805 TSXSetFunction(display, physDev->gc, X11DRV_XROPfunction[dc->ROPmode-1]);
2807 switch (descr.infoBpp)
2809 case 1:
2810 case 4:
2811 case 8:
2812 descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap(
2813 coloruse == DIB_PAL_COLORS ? dc : NULL, coloruse,
2814 dc->bitsPerPixel, info, &descr.nColorMap );
2815 if (!descr.colorMap) return 0;
2816 descr.rMask = descr.gMask = descr.bMask = 0;
2817 break;
2818 case 15:
2819 case 16:
2820 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
2821 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x03e0;
2822 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x001f;
2823 descr.colorMap = 0;
2824 break;
2826 case 24:
2827 descr.rMask = descr.gMask = descr.bMask = 0;
2828 descr.colorMap = 0;
2829 break;
2831 case 32:
2832 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
2833 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0xff00;
2834 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0xff;
2835 descr.colorMap = 0;
2836 break;
2839 descr.dc = dc;
2840 descr.bits = bits;
2841 descr.image = NULL;
2842 descr.palentry = NULL;
2843 descr.lines = tmpheight >= 0 ? lines : -lines;
2844 descr.infoWidth = width;
2845 descr.depth = dc->bitsPerPixel;
2846 descr.drawable = physDev->drawable;
2847 descr.gc = physDev->gc;
2848 descr.xSrc = xSrc;
2849 descr.ySrc = tmpheight >= 0 ? lines-(ySrc-startscan)-cy+(oldcy-cy)
2850 : ySrc - startscan;
2851 descr.xDest = dc->DCOrgX + XLPTODP( dc, xDest );
2852 descr.yDest = dc->DCOrgY + YLPTODP( dc, yDest ) +
2853 (tmpheight >= 0 ? oldcy-cy : 0);
2854 descr.width = cx;
2855 descr.height = cy;
2856 descr.useShm = FALSE;
2858 EnterCriticalSection( &X11DRV_CritSection );
2859 result = CALL_LARGE_STACK( X11DRV_DIB_SetImageBits, &descr );
2860 LeaveCriticalSection( &X11DRV_CritSection );
2862 if (descr.infoBpp <= 8)
2863 HeapFree(GetProcessHeap(), 0, descr.colorMap);
2864 return result;
2867 /***********************************************************************
2868 * X11DRV_DIB_SetDIBits
2870 INT X11DRV_DIB_SetDIBits(
2871 BITMAPOBJ *bmp, DC *dc, UINT startscan,
2872 UINT lines, LPCVOID bits, const BITMAPINFO *info,
2873 UINT coloruse, HBITMAP hbitmap)
2875 X11DRV_DIB_IMAGEBITS_DESCR descr;
2876 int height, tmpheight;
2877 INT result;
2879 descr.dc = dc;
2881 if (DIB_GetBitmapInfo( &info->bmiHeader, &descr.infoWidth, &height,
2882 &descr.infoBpp, &descr.compression ) == -1)
2883 return 0;
2885 tmpheight = height;
2886 if (height < 0) height = -height;
2887 if (!lines || (startscan >= height))
2888 return 0;
2890 if (startscan + lines > height) lines = height - startscan;
2892 switch (descr.infoBpp)
2894 case 1:
2895 case 4:
2896 case 8:
2897 descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap(
2898 coloruse == DIB_PAL_COLORS ? descr.dc : NULL, coloruse,
2899 bmp->bitmap.bmBitsPixel,
2900 info, &descr.nColorMap );
2901 if (!descr.colorMap) return 0;
2902 descr.rMask = descr.gMask = descr.bMask = 0;
2903 break;
2904 case 15:
2905 case 16:
2906 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
2907 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x03e0;
2908 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x001f;
2909 descr.colorMap = 0;
2910 break;
2912 case 24:
2913 descr.rMask = descr.gMask = descr.bMask = 0;
2914 descr.colorMap = 0;
2915 break;
2917 case 32:
2918 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
2919 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0xff00;
2920 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0xff;
2921 descr.colorMap = 0;
2922 break;
2924 default: break;
2927 /* HACK for now */
2928 if(!bmp->physBitmap)
2929 X11DRV_CreateBitmap(hbitmap);
2931 descr.bits = bits;
2932 descr.image = NULL;
2933 descr.palentry = NULL;
2934 descr.lines = tmpheight >= 0 ? lines : -lines;
2935 descr.depth = bmp->bitmap.bmBitsPixel;
2936 descr.drawable = (Pixmap)bmp->physBitmap;
2937 descr.gc = BITMAP_GC(bmp);
2938 descr.xSrc = 0;
2939 descr.ySrc = 0;
2940 descr.xDest = 0;
2941 descr.yDest = height - startscan - lines;
2942 descr.width = bmp->bitmap.bmWidth;
2943 descr.height = lines;
2944 descr.useShm = FALSE;
2946 EnterCriticalSection( &X11DRV_CritSection );
2947 result = CALL_LARGE_STACK( X11DRV_DIB_SetImageBits, &descr );
2948 LeaveCriticalSection( &X11DRV_CritSection );
2950 if (descr.colorMap) HeapFree(GetProcessHeap(), 0, descr.colorMap);
2952 return result;
2955 /***********************************************************************
2956 * X11DRV_DIB_GetDIBits
2958 INT X11DRV_DIB_GetDIBits(
2959 BITMAPOBJ *bmp, DC *dc, UINT startscan,
2960 UINT lines, LPVOID bits, BITMAPINFO *info,
2961 UINT coloruse, HBITMAP hbitmap)
2963 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
2964 X11DRV_DIB_IMAGEBITS_DESCR descr;
2965 PALETTEOBJ * palette;
2967 TRACE("%u scanlines of (%i,%i) -> (%i,%i) starting from %u\n",
2968 lines, bmp->bitmap.bmWidth, bmp->bitmap.bmHeight,
2969 (int)info->bmiHeader.biWidth, (int)info->bmiHeader.biHeight,
2970 startscan );
2972 if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->hPalette, PALETTE_MAGIC )))
2973 return 0;
2975 if( lines > info->bmiHeader.biHeight ) lines = info->bmiHeader.biHeight;
2976 /* Top-down images have a negative biHeight, the scanlines of theses images
2977 * were inverted in X11DRV_DIB_GetImageBits_xx
2978 * To prevent this we simply change the sign of lines
2979 * (the number of scan lines to copy).
2980 * Negative lines are correctly handled by X11DRV_DIB_GetImageBits_xx.
2982 if( info->bmiHeader.biHeight < 0 && lines > 0) lines = -lines;
2984 if( startscan >= bmp->bitmap.bmHeight )
2986 lines = 0;
2987 goto done;
2990 if (DIB_GetBitmapInfo( &info->bmiHeader, &descr.infoWidth, &descr.lines,
2991 &descr.infoBpp, &descr.compression ) == -1)
2993 lines = 0;
2994 goto done;
2997 switch (descr.infoBpp)
2999 case 1:
3000 case 4:
3001 case 8:
3002 case 24:
3003 descr.rMask = descr.gMask = descr.bMask = 0;
3004 break;
3005 case 15:
3006 case 16:
3007 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
3008 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x03e0;
3009 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x001f;
3010 break;
3012 case 32:
3013 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
3014 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0xff00;
3015 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0xff;
3016 break;
3019 /* Hack for now */
3020 if(!bmp->physBitmap)
3021 X11DRV_CreateBitmap(hbitmap);
3024 descr.dc = dc;
3025 descr.palentry = palette->logpalette.palPalEntry;
3026 descr.bits = bits;
3027 descr.image = NULL;
3028 descr.lines = lines;
3029 descr.depth = bmp->bitmap.bmBitsPixel;
3030 descr.drawable = (Pixmap)bmp->physBitmap;
3031 descr.gc = BITMAP_GC(bmp);
3032 descr.width = bmp->bitmap.bmWidth;
3033 descr.height = bmp->bitmap.bmHeight;
3034 descr.colorMap = info->bmiColors;
3035 descr.xDest = 0;
3036 descr.yDest = 0;
3037 descr.xSrc = 0;
3039 if (descr.lines > 0)
3041 descr.ySrc = (descr.height-1) - (startscan + (lines-1));
3043 else
3045 descr.ySrc = startscan;
3048 if (dib)
3049 descr.useShm = (dib->shminfo.shmid != -1);
3050 else
3051 descr.useShm = FALSE;
3053 EnterCriticalSection( &X11DRV_CritSection );
3055 CALL_LARGE_STACK( X11DRV_DIB_GetImageBits, &descr );
3057 LeaveCriticalSection( &X11DRV_CritSection );
3059 if(info->bmiHeader.biSizeImage == 0) /* Fill in biSizeImage */
3060 info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(
3061 info->bmiHeader.biWidth,
3062 info->bmiHeader.biHeight,
3063 info->bmiHeader.biBitCount );
3065 info->bmiHeader.biCompression = 0;
3067 done:
3068 GDI_ReleaseObj( dc->hPalette );
3070 return lines;
3073 /***********************************************************************
3074 * DIB_DoProtectDIBSection
3076 static void X11DRV_DIB_DoProtectDIBSection( BITMAPOBJ *bmp, DWORD new_prot )
3078 DIBSECTION *dib = bmp->dib;
3079 INT effHeight = dib->dsBm.bmHeight >= 0? dib->dsBm.bmHeight
3080 : -dib->dsBm.bmHeight;
3081 /* use the biSizeImage data as the memory size only if we're dealing with a
3082 compressed image where the value is set. Otherwise, calculate based on
3083 width * height */
3084 INT totalSize = dib->dsBmih.biSizeImage && dib->dsBmih.biCompression != BI_RGB
3085 ? dib->dsBmih.biSizeImage
3086 : dib->dsBm.bmWidthBytes * effHeight;
3087 DWORD old_prot;
3089 VirtualProtect(dib->dsBm.bmBits, totalSize, new_prot, &old_prot);
3090 TRACE("Changed protection from %ld to %ld\n", old_prot, new_prot);
3093 /***********************************************************************
3094 * X11DRV_DIB_DoUpdateDIBSection
3096 static void X11DRV_DIB_DoUpdateDIBSection(BITMAPOBJ *bmp, BOOL toDIB)
3098 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
3099 X11DRV_DIB_IMAGEBITS_DESCR descr;
3101 if (DIB_GetBitmapInfo( &dib->dibSection.dsBmih, &descr.infoWidth, &descr.lines,
3102 &descr.infoBpp, &descr.compression ) == -1)
3103 return;
3105 descr.dc = NULL;
3106 descr.palentry = NULL;
3107 descr.image = dib->image;
3108 descr.colorMap = (RGBQUAD *)dib->colorMap;
3109 descr.nColorMap = dib->nColorMap;
3110 descr.bits = dib->dibSection.dsBm.bmBits;
3111 descr.depth = bmp->bitmap.bmBitsPixel;
3113 switch (descr.infoBpp)
3115 case 1:
3116 case 4:
3117 case 8:
3118 case 24:
3119 descr.rMask = descr.gMask = descr.bMask = 0;
3120 break;
3121 case 15:
3122 case 16:
3123 descr.rMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[0] : 0x7c00;
3124 descr.gMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[1] : 0x03e0;
3125 descr.bMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[2] : 0x001f;
3126 break;
3128 case 32:
3129 descr.rMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[0] : 0xff;
3130 descr.gMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[1] : 0xff00;
3131 descr.bMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[2] : 0xff0000;
3132 break;
3135 /* Hack for now */
3136 descr.drawable = (Pixmap)bmp->physBitmap;
3137 descr.gc = BITMAP_GC(bmp);
3138 descr.xSrc = 0;
3139 descr.ySrc = 0;
3140 descr.xDest = 0;
3141 descr.yDest = 0;
3142 descr.width = bmp->bitmap.bmWidth;
3143 descr.height = bmp->bitmap.bmHeight;
3144 descr.useShm = (dib->shminfo.shmid != -1);
3146 if (toDIB)
3148 TRACE("Copying from Pixmap to DIB bits\n");
3149 EnterCriticalSection( &X11DRV_CritSection );
3150 CALL_LARGE_STACK( X11DRV_DIB_GetImageBits, &descr );
3151 LeaveCriticalSection( &X11DRV_CritSection );
3153 else
3155 TRACE("Copying from DIB bits to Pixmap\n");
3156 EnterCriticalSection( &X11DRV_CritSection );
3157 CALL_LARGE_STACK( X11DRV_DIB_SetImageBits, &descr );
3158 LeaveCriticalSection( &X11DRV_CritSection );
3162 /***********************************************************************
3163 * X11DRV_DIB_FaultHandler
3165 static BOOL X11DRV_DIB_FaultHandler( LPVOID res, LPCVOID addr )
3167 BOOL handled = FALSE;
3168 BITMAPOBJ *bmp;
3170 bmp = (BITMAPOBJ *)GDI_GetObjPtr( (HBITMAP)res, BITMAP_MAGIC );
3171 if (!bmp) return FALSE;
3173 if (bmp->dib)
3174 switch (((X11DRV_DIBSECTION *) bmp->dib)->status)
3176 case X11DRV_DIB_GdiMod:
3177 TRACE("called in status DIB_GdiMod\n" );
3178 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
3179 X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
3180 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
3181 ((X11DRV_DIBSECTION *) bmp->dib)->status = X11DRV_DIB_InSync;
3182 handled = TRUE;
3183 break;
3185 case X11DRV_DIB_InSync:
3186 TRACE("called in status X11DRV_DIB_InSync\n" );
3187 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
3188 ((X11DRV_DIBSECTION *) bmp->dib)->status = X11DRV_DIB_AppMod;
3189 handled = TRUE;
3190 break;
3192 case X11DRV_DIB_AppMod:
3193 FIXME("called in status X11DRV_DIB_AppMod: this can't happen!\n" );
3194 break;
3196 case X11DRV_DIB_NoHandler:
3197 FIXME("called in status DIB_NoHandler: this can't happen!\n" );
3198 break;
3201 GDI_ReleaseObj( (HBITMAP)res );
3202 return handled;
3205 /***********************************************************************
3206 * X11DRV_DIB_CmnUpdateDIBSection
3208 static void X11DRV_DIB_CmnUpdateDIBSection(BITMAPOBJ *bmp, BOOL toDIB)
3210 if (!bmp) return;
3211 if (!bmp->dib) return;
3213 if (!toDIB)
3215 /* Prepare for access to the DIB by GDI functions */
3217 switch (((X11DRV_DIBSECTION *) bmp->dib)->status)
3219 default:
3220 case X11DRV_DIB_NoHandler:
3221 X11DRV_DIB_DoUpdateDIBSection( bmp, FALSE );
3222 break;
3224 case X11DRV_DIB_GdiMod:
3225 TRACE("fromDIB called in status X11DRV_DIB_GdiMod\n" );
3226 /* nothing to do */
3227 break;
3229 case X11DRV_DIB_InSync:
3230 TRACE("fromDIB called in status X11DRV_DIB_InSync\n" );
3231 /* nothing to do */
3232 break;
3234 case X11DRV_DIB_AppMod:
3235 TRACE("fromDIB called in status X11DRV_DIB_AppMod\n" );
3236 X11DRV_DIB_DoUpdateDIBSection( bmp, FALSE );
3237 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
3238 ((X11DRV_DIBSECTION *) bmp->dib)->status = X11DRV_DIB_InSync;
3239 break;
3242 else
3244 /* Acknowledge write access to the DIB by GDI functions */
3246 switch (((X11DRV_DIBSECTION *) bmp->dib)->status)
3248 default:
3249 case X11DRV_DIB_NoHandler:
3250 X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
3251 break;
3253 case X11DRV_DIB_GdiMod:
3254 TRACE(" toDIB called in status X11DRV_DIB_GdiMod\n" );
3255 /* nothing to do */
3256 break;
3258 case X11DRV_DIB_InSync:
3259 TRACE(" toDIB called in status X11DRV_DIB_InSync\n" );
3260 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
3261 ((X11DRV_DIBSECTION *) bmp->dib)->status = X11DRV_DIB_GdiMod;
3262 break;
3264 case X11DRV_DIB_AppMod:
3265 FIXME(" toDIB called in status X11DRV_DIB_AppMod: "
3266 "this can't happen!\n" );
3267 break;
3272 /***********************************************************************
3273 * X11DRV_DIB_UpdateDIBSection2
3275 void X11DRV_DIB_UpdateDIBSection2(HBITMAP hbmp, BOOL toDIB)
3277 BITMAPOBJ *bmp;
3279 bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbmp, BITMAP_MAGIC );
3280 if (!bmp) return;
3282 X11DRV_DIB_CmnUpdateDIBSection(bmp, toDIB);
3284 GDI_ReleaseObj(hbmp);
3287 /***********************************************************************
3288 * X11DRV_DIB_UpdateDIBSection
3290 void X11DRV_DIB_UpdateDIBSection(DC *dc, BOOL toDIB)
3292 /* Ensure this is a Compatible DC that has a DIB section selected */
3294 if (!dc) return;
3295 if (!(dc->flags & DC_MEMORY)) return;
3297 X11DRV_DIB_UpdateDIBSection2(dc->hBitmap, toDIB);
3300 /***********************************************************************
3301 * X11DRV_DIB_CreateDIBSection16
3303 HBITMAP16 X11DRV_DIB_CreateDIBSection16(
3304 DC *dc, BITMAPINFO *bmi, UINT16 usage,
3305 SEGPTR *bits, HANDLE section,
3306 DWORD offset, DWORD ovr_pitch)
3308 HBITMAP res = X11DRV_DIB_CreateDIBSection(dc, bmi, usage, NULL,
3309 section, offset, ovr_pitch);
3310 if ( res )
3312 BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr(res, BITMAP_MAGIC);
3313 if ( bmp && bmp->dib )
3315 DIBSECTION *dib = bmp->dib;
3316 INT height = dib->dsBm.bmHeight >= 0 ?
3317 dib->dsBm.bmHeight : -dib->dsBm.bmHeight;
3318 /* same as above - only use biSizeImage as the correct size if it a
3319 compressed image and it's currently non-zero. In other cases, use
3320 width * height as the value. */
3321 INT size = dib->dsBmih.biSizeImage && dib->dsBmih.biCompression != BI_RGB
3322 ? dib->dsBmih.biSizeImage
3323 : dib->dsBm.bmWidthBytes * height;
3324 if ( dib->dsBm.bmBits )
3326 ((X11DRV_DIBSECTION *) bmp->dib)->selector =
3327 SELECTOR_AllocBlock( dib->dsBm.bmBits, size, WINE_LDT_FLAGS_DATA );
3329 TRACE("ptr = %p, size =%d, selector = %04x, segptr = %ld\n",
3330 dib->dsBm.bmBits, size, ((X11DRV_DIBSECTION *) bmp->dib)->selector,
3331 PTR_SEG_OFF_TO_SEGPTR(((X11DRV_DIBSECTION *) bmp->dib)->selector, 0));
3332 if ( bits )
3333 *bits = PTR_SEG_OFF_TO_SEGPTR( ((X11DRV_DIBSECTION *) bmp->dib)->selector, 0 );
3335 if (bmp) GDI_ReleaseObj( res );
3338 return res;
3341 /***********************************************************************
3342 * X11DRV_XShmErrorHandler
3345 static int XShmErrorHandler(Display *dpy, XErrorEvent *event)
3347 XShmErrorFlag = 1;
3348 return 0;
3351 /***********************************************************************
3352 * X11DRV_XShmCreateImage
3356 extern BOOL X11DRV_XShmCreateImage(XImage** image, int width, int height, int bpp,
3357 XShmSegmentInfo* shminfo)
3359 int (*WineXHandler)(Display *, XErrorEvent *);
3361 *image = TSXShmCreateImage(display, X11DRV_GetVisual(), bpp, ZPixmap, NULL, shminfo, width, height);
3362 if( *image != NULL )
3364 EnterCriticalSection( &X11DRV_CritSection );
3365 shminfo->shmid = shmget(IPC_PRIVATE, (*image)->bytes_per_line * height,
3366 IPC_CREAT|0700);
3367 if( shminfo->shmid != -1 )
3369 shminfo->shmaddr = (*image)->data = shmat(shminfo->shmid, 0, 0);
3370 if( shminfo->shmaddr != (char*)-1 )
3372 shminfo->readOnly = FALSE;
3373 if( TSXShmAttach( display, shminfo ) != 0)
3375 /* Reset the error flag */
3376 XShmErrorFlag = 0;
3377 WineXHandler = XSetErrorHandler(XShmErrorHandler);
3378 XSync( display, 0 );
3380 if (!XShmErrorFlag)
3382 shmctl(shminfo->shmid, IPC_RMID, 0);
3384 XSetErrorHandler(WineXHandler);
3385 LeaveCriticalSection( &X11DRV_CritSection );
3387 return TRUE; /* Success! */
3389 /* An error occured */
3390 XShmErrorFlag = 0;
3391 XSetErrorHandler(WineXHandler);
3393 shmdt(shminfo->shmaddr);
3395 shmctl(shminfo->shmid, IPC_RMID, 0);
3397 XFlush(display);
3398 XDestroyImage(*image);
3399 LeaveCriticalSection( &X11DRV_CritSection );
3401 return FALSE;
3407 /***********************************************************************
3408 * X11DRV_DIB_CreateDIBSection
3410 HBITMAP X11DRV_DIB_CreateDIBSection(
3411 DC *dc, BITMAPINFO *bmi, UINT usage,
3412 LPVOID *bits, HANDLE section,
3413 DWORD offset, DWORD ovr_pitch)
3415 HBITMAP res = 0;
3416 BITMAPOBJ *bmp = NULL;
3417 X11DRV_DIBSECTION *dib = NULL;
3418 int *colorMap = NULL;
3419 int nColorMap;
3421 /* Fill BITMAP32 structure with DIB data */
3422 BITMAPINFOHEADER *bi = &bmi->bmiHeader;
3423 INT effHeight, totalSize;
3424 BITMAP bm;
3426 TRACE("format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
3427 bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
3428 bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
3430 effHeight = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
3431 bm.bmType = 0;
3432 bm.bmWidth = bi->biWidth;
3433 bm.bmHeight = effHeight;
3434 bm.bmWidthBytes = ovr_pitch ? ovr_pitch
3435 : DIB_GetDIBWidthBytes(bm.bmWidth, bi->biBitCount);
3436 bm.bmPlanes = bi->biPlanes;
3437 bm.bmBitsPixel = bi->biBitCount;
3438 bm.bmBits = NULL;
3440 /* Get storage location for DIB bits. Only use biSizeImage if it's valid and
3441 we're dealing with a compressed bitmap. Otherwise, use width * height. */
3442 totalSize = bi->biSizeImage && bi->biCompression != BI_RGB
3443 ? bi->biSizeImage : bm.bmWidthBytes * effHeight;
3445 if (section)
3446 bm.bmBits = MapViewOfFile(section, FILE_MAP_ALL_ACCESS,
3447 0L, offset, totalSize);
3448 else if (ovr_pitch && offset)
3449 bm.bmBits = (LPVOID) offset;
3450 else {
3451 offset = 0;
3452 bm.bmBits = VirtualAlloc(NULL, totalSize,
3453 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
3456 /* Create Color Map */
3457 if (bm.bmBits && bm.bmBitsPixel <= 8)
3458 colorMap = X11DRV_DIB_BuildColorMap( usage == DIB_PAL_COLORS? dc : NULL,
3459 usage, bm.bmBitsPixel, bmi, &nColorMap );
3461 /* Allocate Memory for DIB and fill structure */
3462 if (bm.bmBits)
3463 dib = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(X11DRV_DIBSECTION));
3464 if (dib)
3466 dib->dibSection.dsBm = bm;
3467 dib->dibSection.dsBmih = *bi;
3468 dib->dibSection.dsBmih.biSizeImage = totalSize;
3470 /* Set dsBitfields values */
3471 if ( usage == DIB_PAL_COLORS || bi->biBitCount <= 8)
3473 dib->dibSection.dsBitfields[0] = dib->dibSection.dsBitfields[1] = dib->dibSection.dsBitfields[2] = 0;
3475 else switch( bi->biBitCount )
3477 case 16:
3478 dib->dibSection.dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors : 0x7c00;
3479 dib->dibSection.dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0x03e0;
3480 dib->dibSection.dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0x001f;
3481 break;
3483 case 24:
3484 dib->dibSection.dsBitfields[0] = 0xff;
3485 dib->dibSection.dsBitfields[1] = 0xff00;
3486 dib->dibSection.dsBitfields[2] = 0xff0000;
3487 break;
3489 case 32:
3490 dib->dibSection.dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors : 0xff;
3491 dib->dibSection.dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0xff00;
3492 dib->dibSection.dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0xff0000;
3493 break;
3495 dib->dibSection.dshSection = section;
3496 dib->dibSection.dsOffset = offset;
3498 dib->status = X11DRV_DIB_NoHandler;
3499 dib->selector = 0;
3501 dib->nColorMap = nColorMap;
3502 dib->colorMap = colorMap;
3505 /* Create Device Dependent Bitmap and add DIB pointer */
3506 if (dib)
3508 res = CreateDIBitmap(dc->hSelf, bi, 0, NULL, bmi, usage);
3509 if (res)
3511 bmp = (BITMAPOBJ *) GDI_GetObjPtr(res, BITMAP_MAGIC);
3512 if (bmp)
3514 bmp->dib = (DIBSECTION *) dib;
3515 /* HACK for now */
3516 if(!bmp->physBitmap)
3517 X11DRV_CreateBitmap(res);
3522 /* Create XImage */
3523 if (dib && bmp)
3525 if (TSXShmQueryExtension(display) &&
3526 X11DRV_XShmCreateImage( &dib->image, bm.bmWidth, effHeight,
3527 bmp->bitmap.bmBitsPixel, &dib->shminfo ) )
3529 ; /* Created Image */
3530 } else {
3531 XCREATEIMAGE( dib->image, bm.bmWidth, effHeight, bmp->bitmap.bmBitsPixel );
3532 dib->shminfo.shmid = -1;
3536 /* Clean up in case of errors */
3537 if (!res || !bmp || !dib || !bm.bmBits || (bm.bmBitsPixel <= 8 && !colorMap))
3539 TRACE("got an error res=%08x, bmp=%p, dib=%p, bm.bmBits=%p\n",
3540 res, bmp, dib, bm.bmBits);
3541 if (bm.bmBits)
3543 if (section)
3544 UnmapViewOfFile(bm.bmBits), bm.bmBits = NULL;
3545 else if (!offset)
3546 VirtualFree(bm.bmBits, 0L, MEM_RELEASE), bm.bmBits = NULL;
3549 if (dib && dib->image) { XDestroyImage(dib->image); dib->image = NULL; }
3550 if (colorMap) { HeapFree(GetProcessHeap(), 0, colorMap); colorMap = NULL; }
3551 if (dib) { HeapFree(GetProcessHeap(), 0, dib); dib = NULL; }
3552 if (bmp) { GDI_ReleaseObj(res); bmp = NULL; }
3553 if (res) { DeleteObject(res); res = 0; }
3556 /* Install fault handler, if possible */
3557 if (bm.bmBits)
3559 if (VIRTUAL_SetFaultHandler(bm.bmBits, X11DRV_DIB_FaultHandler, (LPVOID)res))
3561 if (section || offset)
3563 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
3564 if (dib) dib->status = X11DRV_DIB_AppMod;
3566 else
3568 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
3569 if (dib) dib->status = X11DRV_DIB_InSync;
3574 /* Return BITMAP handle and storage location */
3575 if (bmp) GDI_ReleaseObj(res);
3576 if (bm.bmBits && bits) *bits = bm.bmBits;
3577 return res;
3580 /***********************************************************************
3581 * X11DRV_DIB_DeleteDIBSection
3583 void X11DRV_DIB_DeleteDIBSection(BITMAPOBJ *bmp)
3585 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
3587 if (dib->image)
3589 if (dib->shminfo.shmid != -1)
3591 TSXShmDetach (display, &(dib->shminfo));
3592 XDestroyImage (dib->image);
3593 shmdt (dib->shminfo.shmaddr);
3594 dib->shminfo.shmid = -1;
3596 else
3597 XDestroyImage( dib->image );
3600 if (dib->colorMap)
3601 HeapFree(GetProcessHeap(), 0, dib->colorMap);
3603 if (dib->selector) SELECTOR_FreeBlock( dib->selector );
3607 /**************************************************************************
3608 * X11DRV_DIB_CreateDIBFromPixmap
3610 * Allocates a packed DIB and copies the Pixmap data into it.
3611 * If bDeletePixmap is TRUE, the Pixmap passed in is deleted after the conversion.
3613 HGLOBAL X11DRV_DIB_CreateDIBFromPixmap(Pixmap pixmap, HDC hdc, BOOL bDeletePixmap)
3615 HBITMAP hBmp = 0;
3616 BITMAPOBJ *pBmp = NULL;
3617 HGLOBAL hPackedDIB = 0;
3619 /* Allocates an HBITMAP which references the Pixmap passed to us */
3620 hBmp = X11DRV_BITMAP_CreateBitmapHeaderFromPixmap(pixmap);
3621 if (!hBmp)
3623 TRACE("\tCould not create bitmap header for Pixmap\n");
3624 goto END;
3628 * Create a packed DIB from the Pixmap wrapper bitmap created above.
3629 * A packed DIB contains a BITMAPINFO structure followed immediately by
3630 * an optional color palette and the pixel data.
3632 hPackedDIB = DIB_CreateDIBFromBitmap(hdc, hBmp);
3634 /* Get a pointer to the BITMAPOBJ structure */
3635 pBmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
3637 /* We can now get rid of the HBITMAP wrapper we created earlier.
3638 * Note: Simply calling DeleteObject will free the embedded Pixmap as well.
3640 if (!bDeletePixmap)
3642 /* Clear the physBitmap to prevent the Pixmap from being deleted by DeleteObject */
3643 pBmp->physBitmap = NULL;
3644 pBmp->funcs = NULL;
3646 GDI_ReleaseObj( hBmp );
3647 DeleteObject(hBmp);
3649 END:
3650 TRACE("\tReturning packed DIB %x\n", hPackedDIB);
3651 return hPackedDIB;
3655 /**************************************************************************
3656 * X11DRV_DIB_CreatePixmapFromDIB
3658 * Creates a Pixmap from a packed DIB
3660 Pixmap X11DRV_DIB_CreatePixmapFromDIB( HGLOBAL hPackedDIB, HDC hdc )
3662 Pixmap pixmap = None;
3663 HBITMAP hBmp = 0;
3664 BITMAPOBJ *pBmp = NULL;
3665 LPBYTE pPackedDIB = NULL;
3666 LPBITMAPINFO pbmi = NULL;
3667 LPBITMAPINFOHEADER pbmiHeader = NULL;
3668 LPBYTE pbits = NULL;
3670 /* Get a pointer to the packed DIB's data */
3671 pPackedDIB = (LPBYTE)GlobalLock(hPackedDIB);
3672 pbmiHeader = (LPBITMAPINFOHEADER)pPackedDIB;
3673 pbmi = (LPBITMAPINFO)pPackedDIB;
3674 pbits = (LPBYTE)(pPackedDIB
3675 + DIB_BitmapInfoSize( (LPBITMAPINFO)pbmiHeader, DIB_RGB_COLORS ));
3677 /* Create a DDB from the DIB */
3679 hBmp = CreateDIBitmap(hdc,
3680 pbmiHeader,
3681 CBM_INIT,
3682 (LPVOID)pbits,
3683 pbmi,
3684 DIB_RGB_COLORS);
3686 GlobalUnlock(hPackedDIB);
3688 TRACE("CreateDIBitmap returned %x\n", hBmp);
3690 /* Retrieve the internal Pixmap from the DDB */
3692 pBmp = (BITMAPOBJ *) GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
3694 pixmap = (Pixmap)pBmp->physBitmap;
3695 /* clear the physBitmap so that we can steal its pixmap */
3696 pBmp->physBitmap = NULL;
3697 pBmp->funcs = NULL;
3699 /* Delete the DDB we created earlier now that we have stolen its pixmap */
3700 GDI_ReleaseObj( hBmp );
3701 DeleteObject(hBmp);
3703 TRACE("\tReturning Pixmap %ld\n", pixmap);
3704 return pixmap;