Implemented Get/SetDIBColorTable.
[wine/wine64.git] / graphics / x11drv / dib.c
blob900d97ecc675cd45c3c30202b75db86da76c7e1f
1 /*
2 * X11DRV device-independent bitmaps
4 * Copyright 1993,1994 Alexandre Julliard
5 */
7 #include "config.h"
9 #include "ts_xlib.h"
10 #include "ts_xutil.h"
11 #ifdef HAVE_LIBXXSHM
12 # include "ts_xshm.h"
13 # ifdef HAVE_SYS_SHM_H
14 # include <sys/shm.h>
15 # endif
16 # ifdef HAVE_SYS_IPC_H
17 # include <sys/ipc.h>
18 # endif
19 #endif /* defined(HAVE_LIBXXSHM) */
21 #include <stdlib.h>
22 #include "windef.h"
23 #include "bitmap.h"
24 #include "x11drv.h"
25 #include "debugtools.h"
26 #include "gdi.h"
27 #include "color.h"
28 #include "callback.h"
29 #include "selectors.h"
30 #include "global.h"
32 DEFAULT_DEBUG_CHANNEL(bitmap);
33 DECLARE_DEBUG_CHANNEL(x11drv);
35 static int bitmapDepthTable[] = { 8, 1, 32, 16, 24, 15, 4, 0 };
36 static int ximageDepthTable[] = { 0, 0, 0, 0, 0, 0, 0 };
38 static int XShmErrorFlag = 0;
40 /***********************************************************************
41 * X11DRV_DIB_Init
43 BOOL X11DRV_DIB_Init(void)
45 int i;
46 XImage* testimage;
48 for( i = 0; bitmapDepthTable[i]; i++ )
50 testimage = TSXCreateImage(display, X11DRV_GetVisual(),
51 bitmapDepthTable[i], ZPixmap, 0, NULL, 1, 1, 32, 20 );
52 if( testimage ) ximageDepthTable[i] = testimage->bits_per_pixel;
53 else return FALSE;
54 TSXDestroyImage(testimage);
56 return TRUE;
60 /***********************************************************************
61 * X11DRV_DIB_GetXImageWidthBytes
63 * Return the width of an X image in bytes
65 int X11DRV_DIB_GetXImageWidthBytes( int width, int depth )
67 int i;
69 if (!ximageDepthTable[0]) {
70 X11DRV_DIB_Init();
72 for( i = 0; bitmapDepthTable[i] ; i++ )
73 if( bitmapDepthTable[i] == depth )
74 return (4 * ((width * ximageDepthTable[i] + 31)/32));
76 WARN("(%d): Unsupported depth\n", depth );
77 return (4 * width);
80 /***********************************************************************
81 * X11DRV_DIB_GenColorMap
83 * Fills the color map of a bitmap palette. Should not be called
84 * for a >8-bit deep bitmap.
86 int *X11DRV_DIB_GenColorMap( DC *dc, int *colorMapping,
87 WORD coloruse, WORD depth, BOOL quads,
88 const void *colorPtr, int start, int end )
90 int i;
92 if (coloruse == DIB_RGB_COLORS)
94 if (quads)
96 RGBQUAD * rgb = (RGBQUAD *)colorPtr;
98 if (depth == 1) /* Monochrome */
99 for (i = start; i < end; i++, rgb++)
100 colorMapping[i] = (rgb->rgbRed + rgb->rgbGreen +
101 rgb->rgbBlue > 255*3/2);
102 else
103 for (i = start; i < end; i++, rgb++)
104 colorMapping[i] = X11DRV_PALETTE_ToPhysical( dc, RGB(rgb->rgbRed,
105 rgb->rgbGreen,
106 rgb->rgbBlue));
108 else
110 RGBTRIPLE * rgb = (RGBTRIPLE *)colorPtr;
112 if (depth == 1) /* Monochrome */
113 for (i = start; i < end; i++, rgb++)
114 colorMapping[i] = (rgb->rgbtRed + rgb->rgbtGreen +
115 rgb->rgbtBlue > 255*3/2);
116 else
117 for (i = start; i < end; i++, rgb++)
118 colorMapping[i] = X11DRV_PALETTE_ToPhysical( dc, RGB(rgb->rgbtRed,
119 rgb->rgbtGreen,
120 rgb->rgbtBlue));
123 else /* DIB_PAL_COLORS */
125 WORD * index = (WORD *)colorPtr;
127 for (i = start; i < end; i++, index++)
128 colorMapping[i] = X11DRV_PALETTE_ToPhysical( dc, PALETTEINDEX(*index) );
131 return colorMapping;
134 /***********************************************************************
135 * X11DRV_DIB_BuildColorMap
137 * Build the color map from the bitmap palette. Should not be called
138 * for a >8-bit deep bitmap.
140 int *X11DRV_DIB_BuildColorMap( DC *dc, WORD coloruse, WORD depth,
141 const BITMAPINFO *info, int *nColors )
143 int colors;
144 BOOL isInfo;
145 WORD *colorPtr;
146 int *colorMapping;
148 if ((isInfo = (info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))))
150 colors = info->bmiHeader.biClrUsed;
151 if (!colors) colors = 1 << info->bmiHeader.biBitCount;
152 colorPtr = (WORD *)info->bmiColors;
154 else /* assume BITMAPCOREINFO */
156 colors = 1 << ((BITMAPCOREHEADER *)&info->bmiHeader)->bcBitCount;
157 colorPtr = (WORD *)((BITMAPCOREINFO *)info)->bmciColors;
160 if (colors > 256)
162 ERR("called with >256 colors!\n");
163 return NULL;
166 if (!(colorMapping = (int *)HeapAlloc(GetProcessHeap(), 0,
167 colors * sizeof(int) )))
168 return NULL;
170 *nColors = colors;
171 return X11DRV_DIB_GenColorMap( dc, colorMapping, coloruse, depth,
172 isInfo, colorPtr, 0, colors);
176 /***********************************************************************
177 * X11DRV_DIB_MapColor
179 int X11DRV_DIB_MapColor( int *physMap, int nPhysMap, int phys, int oldcol )
181 int color;
183 if ((oldcol < nPhysMap) && (physMap[oldcol] == phys))
184 return oldcol;
186 for (color = 0; color < nPhysMap; color++)
187 if (physMap[color] == phys)
188 return color;
190 WARN("Strange color %08x\n", phys);
191 return 0;
195 /*********************************************************************
196 * X11DRV_DIB_GetNearestIndex
198 * Helper for X11DRV_DIB_GetDIBits.
199 * Returns the nearest colour table index for a given RGB.
200 * Nearest is defined by minimizing the sum of the squares.
202 static INT X11DRV_DIB_GetNearestIndex(RGBQUAD *colormap, int numColors, BYTE r, BYTE g, BYTE b)
204 INT i, best = -1, diff, bestdiff = -1;
205 RGBQUAD *color;
207 for(color = colormap, i = 0; i < numColors; color++, i++) {
208 diff = (r - color->rgbRed) * (r - color->rgbRed) +
209 (g - color->rgbGreen) * (g - color->rgbGreen) +
210 (b - color->rgbBlue) * (b - color->rgbBlue);
211 if(diff == 0)
212 return i;
213 if(best == -1 || diff < bestdiff) {
214 best = i;
215 bestdiff = diff;
218 return best;
221 /***********************************************************************
222 * X11DRV_DIB_SetImageBits_1_Line
224 * Handles a single line of 1 bit data.
226 static void X11DRV_DIB_SetImageBits_1_Line(DWORD dstwidth, int left, int *colors,
227 XImage *bmpImage, int h, const BYTE *bits)
229 BYTE pix, extra;
230 DWORD i, x;
232 if((extra = (left & 7)) != 0) {
233 left &= ~7;
234 dstwidth += extra;
237 bits += left >> 3;
239 /* FIXME: should avoid putting x<left pixels (minor speed issue) */
240 for (i = dstwidth/8, x = left; i > 0; i--)
242 pix = *bits++;
243 XPutPixel( bmpImage, x++, h, colors[pix >> 7] );
244 XPutPixel( bmpImage, x++, h, colors[(pix >> 6) & 1] );
245 XPutPixel( bmpImage, x++, h, colors[(pix >> 5) & 1] );
246 XPutPixel( bmpImage, x++, h, colors[(pix >> 4) & 1] );
247 XPutPixel( bmpImage, x++, h, colors[(pix >> 3) & 1] );
248 XPutPixel( bmpImage, x++, h, colors[(pix >> 2) & 1] );
249 XPutPixel( bmpImage, x++, h, colors[(pix >> 1) & 1] );
250 XPutPixel( bmpImage, x++, h, colors[pix & 1] );
252 pix = *bits;
253 switch(dstwidth & 7)
255 case 7: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
256 case 6: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
257 case 5: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
258 case 4: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
259 case 3: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
260 case 2: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
261 case 1: XPutPixel( bmpImage, x++, h, colors[pix >> 7] );
265 /***********************************************************************
266 * X11DRV_DIB_SetImageBits_1
268 * SetDIBits for a 1-bit deep DIB.
270 static void X11DRV_DIB_SetImageBits_1( int lines, const BYTE *srcbits,
271 DWORD srcwidth, DWORD dstwidth, int left,
272 int *colors, XImage *bmpImage )
274 int h;
276 /* 32 bit aligned */
277 DWORD linebytes = ((srcwidth + 31) & ~31) / 8;
279 if (lines > 0) {
280 for (h = lines-1; h >=0; h--) {
281 X11DRV_DIB_SetImageBits_1_Line(dstwidth, left, colors, bmpImage, h,
282 srcbits);
283 srcbits += linebytes;
285 } else {
286 lines = -lines;
287 for (h = 0; h < lines; h++) {
288 X11DRV_DIB_SetImageBits_1_Line(dstwidth, left, colors, bmpImage, h,
289 srcbits);
290 srcbits += linebytes;
295 /***********************************************************************
296 * X11DRV_DIB_GetImageBits_1
298 * GetDIBits for a 1-bit deep DIB.
300 static void X11DRV_DIB_GetImageBits_1( int lines, BYTE *dstbits,
301 DWORD dstwidth, DWORD srcwidth,
302 RGBQUAD *colors, PALETTEENTRY *srccolors,
303 XImage *bmpImage )
305 DWORD x;
306 int h;
307 BYTE *bits;
309 /* 32 bit aligned */
310 DWORD linebytes = ((dstwidth + 31) & ~31) / 8;
312 if (lines < 0 ) {
313 lines = -lines;
314 dstbits = dstbits + linebytes * (lines - 1);
315 linebytes = -linebytes;
318 bits = dstbits;
320 switch(bmpImage->depth) {
322 case 1:
323 /* ==== monochrome bitmap to monochrome dib ==== */
324 case 4:
325 /* ==== 4 colormap bitmap to monochrome dib ==== */
326 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
328 PALETTEENTRY val;
330 for (h = lines - 1; h >= 0; h--) {
331 for (x = 0; x < dstwidth; x++) {
332 val = srccolors[XGetPixel(bmpImage, x, h)];
333 if (!(x&7)) *bits = 0;
334 *bits |= (X11DRV_DIB_GetNearestIndex(colors, 2,
335 val.peRed,
336 val.peGreen,
337 val.peBlue) << (7 - (x & 7)));
338 if ((x&7)==7) bits++;
340 bits = (dstbits += linebytes);
343 else goto notsupported;
345 break;
347 case 8:
348 /* ==== 8 colormap bitmap to monochrome dib ==== */
349 if ( bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
351 BYTE *srcpixel;
352 PALETTEENTRY val;
354 for( h = lines- 1; h >= 0; h-- ) {
355 srcpixel = bmpImage->data + (h*bmpImage->bytes_per_line);
356 for( x = 0; x < dstwidth; x++ ) {
357 if (!(x&7)) *bits = 0;
358 val = srccolors[(int)*srcpixel++];
359 *bits |= ( X11DRV_DIB_GetNearestIndex(colors, 2,
360 val.peRed,
361 val.peGreen,
362 val.peBlue) << (7-(x&7)) );
363 if ((x&7)==7) bits++;
365 bits = (dstbits += linebytes);
368 else goto notsupported;
370 break;
372 case 15:
374 LPWORD srcpixel;
375 WORD val;
377 /* ==== 555 BGR bitmap to monochrome dib ==== */
378 if (bmpImage->red_mask == 0x7c00 && bmpImage->blue_mask == 0x1f)
380 for( h = lines - 1; h >= 0; h--) {
381 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
382 for( x = 0; x < dstwidth; x++) {
383 if (!(x&7)) *bits = 0;
384 val = *srcpixel++;
385 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 2,
386 ((val >> 7) & 0xf8) |
387 ((val >> 12) & 0x7),
388 ((val >> 2) & 0xf8) |
389 ((val >> 7) & 0x3),
390 ((val << 3) & 0xf8) |
391 ((val >> 2) & 0x7) ) << (7-(x&7)) );
392 if ((x&7)==7) bits++;
394 bits = (dstbits += linebytes);
397 /* ==== 555 RGB bitmap to monochrome dib ==== */
398 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0xf800)
400 for( h = lines - 1; h >= 0; h--)
402 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
403 for( x = 0; x < dstwidth; x++) {
404 if (!(x&1)) *bits = 0;
405 val = *srcpixel++;
406 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 2,
407 ((val << 3) & 0xf8) |
408 ((val >> 2) & 0x7),
409 ((val >> 2) & 0xf8) |
410 ((val >> 7) & 0x3),
411 ((val >> 7) & 0xf8) |
412 ((val >> 12) & 0x7) ) << (7-(x&7)) );
413 if ((x&7)==7) bits++;
415 bits = (dstbits += linebytes);
418 else goto notsupported;
420 break;
422 case 16:
424 LPWORD srcpixel;
425 WORD val;
427 /* ==== 565 BGR bitmap to monochrome dib ==== */
428 if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f)
430 for( h = lines - 1; h >= 0; h--)
432 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
433 for( x = 0; x < dstwidth; x++) {
434 if (!(x&7)) *bits = 0;
435 val = *srcpixel++;
436 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 2,
437 ((val >> 8) & 0xf8) |
438 ((val >> 13) & 0x7),
439 ((val >> 3) & 0xfc) |
440 ((val >> 9) & 0x3),
441 ((val << 3) & 0xf8) |
442 ((val >> 2) & 0x7) ) << (7-(x&7)) );
443 if ((x&7)==7) bits++;
445 bits = (dstbits += linebytes);
448 /* ==== 565 RGB bitmap to monochrome dib ==== */
449 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0xf800)
451 for( h = lines - 1; h >= 0; h--)
453 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
454 for( x = 0; x < dstwidth; x++) {
455 if (!(x&7)) *bits = 0;
456 val = *srcpixel++;
457 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 2,
458 ((val << 3) & 0xf8) |
459 ((val >> 2) & 0x7),
460 ((val >> 3) & 0xfc) |
461 ((val >> 9) & 0x3),
462 ((val >> 8) & 0xf8) |
463 ((val >> 13) & 0x7) ) << (7-(x&7)) );
464 if ((x&7)==7) bits++;
466 bits = (dstbits += linebytes);
469 else goto notsupported;
471 break;
473 case 24:
474 case 32:
476 BYTE *srcpixel;
478 /* ==== 24/32 BGR bitmap to monochrome dib ==== */
479 if (bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff)
481 for (h = lines - 1; h >= 0; h--)
483 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
484 for (x = 0; x < dstwidth; x++, srcpixel+=4) {
485 if (!(x&7)) *bits = 0;
486 *bits |= (X11DRV_DIB_GetNearestIndex(colors, 2, srcpixel[2] , srcpixel[1], srcpixel[0]) << (7-(x&7)) );
487 if ((x&7)==7) bits++;
489 bits = (dstbits += linebytes);
492 /* ==== 24/32 RGB bitmap to monochrome dib ==== */
493 else if (bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000)
495 for (h = lines - 1; h >= 0; h--)
497 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
498 for (x = 0; x < dstwidth; x++, srcpixel+=4) {
499 if (!(x & 7)) *bits = 0;
500 *bits |= (X11DRV_DIB_GetNearestIndex(colors, 2, srcpixel[0] , srcpixel[1], srcpixel[2]) << (7-(x&7)) );
501 if ((x & 7) == 7) bits++;
503 bits = (dstbits += linebytes);
506 else goto notsupported;
508 break;
510 default: /* ? bit bmp -> monochrome DIB */
511 notsupported:
513 unsigned long white = (1 << bmpImage->bits_per_pixel) - 1;
515 FIXME("from %d bit bitmap with mask R,G,B %x,%x,%x to 1 bit DIB\n",
516 bmpImage->bits_per_pixel, (int)bmpImage->red_mask,
517 (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
519 for( h = lines - 1; h >= 0; h-- ) {
520 for( x = 0; x < dstwidth; x++ ) {
521 if (!(x&7)) *bits = 0;
522 *bits |= (XGetPixel( bmpImage, x, h) >= white)
523 << (7 - (x&7));
524 if ((x&7)==7) bits++;
526 bits = (dstbits += linebytes);
529 break;
533 /***********************************************************************
534 * X11DRV_DIB_SetImageBits_4
536 * SetDIBits for a 4-bit deep DIB.
538 static void X11DRV_DIB_SetImageBits_4( int lines, const BYTE *srcbits,
539 DWORD srcwidth, DWORD dstwidth, int left,
540 int *colors, XImage *bmpImage )
542 DWORD i, x;
543 int h;
544 const BYTE *bits = srcbits + (left >> 1);
546 /* 32 bit aligned */
547 DWORD linebytes = ((srcwidth+7)&~7)/2;
549 if(left & 1) {
550 left--;
551 dstwidth++;
554 if (lines > 0) {
555 for (h = lines-1; h >= 0; h--) {
556 for (i = dstwidth/2, x = left; i > 0; i--) {
557 BYTE pix = *bits++;
558 XPutPixel( bmpImage, x++, h, colors[pix >> 4] );
559 XPutPixel( bmpImage, x++, h, colors[pix & 0x0f] );
561 if (dstwidth & 1) XPutPixel( bmpImage, x, h, colors[*bits >> 4] );
562 srcbits += linebytes;
563 bits = srcbits + (left >> 1);
565 } else {
566 lines = -lines;
567 for (h = 0; h < lines; h++) {
568 for (i = dstwidth/2, x = left; i > 0; i--) {
569 BYTE pix = *bits++;
570 XPutPixel( bmpImage, x++, h, colors[pix >> 4] );
571 XPutPixel( bmpImage, x++, h, colors[pix & 0x0f] );
573 if (dstwidth & 1) XPutPixel( bmpImage, x, h, colors[*bits >> 4] );
574 srcbits += linebytes;
575 bits = srcbits + (left >> 1);
582 /***********************************************************************
583 * X11DRV_DIB_GetImageBits_4
585 * GetDIBits for a 4-bit deep DIB.
587 static void X11DRV_DIB_GetImageBits_4( int lines, BYTE *dstbits,
588 DWORD srcwidth, DWORD dstwidth,
589 RGBQUAD *colors, PALETTEENTRY *srccolors,
590 XImage *bmpImage )
592 DWORD x;
593 int h;
594 BYTE *bits;
595 LPBYTE srcpixel;
597 /* 32 bit aligned */
598 DWORD linebytes = ((srcwidth+7)&~7)/2;
600 if (lines < 0 )
602 lines = -lines;
603 dstbits = dstbits + ( linebytes * (lines-1) );
604 linebytes = -linebytes;
607 bits = dstbits;
609 switch(bmpImage->depth) {
611 case 1:
612 /* ==== monochrome bitmap to 4 colormap dib ==== */
613 case 4:
614 /* ==== 4 colormap bitmap to 4 colormap dib ==== */
615 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
617 PALETTEENTRY val;
619 for (h = lines-1; h >= 0; h--) {
620 for (x = 0; x < dstwidth; x++) {
621 if (!(x&1)) *bits = 0;
622 val = srccolors[XGetPixel(bmpImage, x, h)];
623 *bits |= (X11DRV_DIB_GetNearestIndex(colors, 16,
624 val.peRed,
625 val.peGreen,
626 val.peBlue) << (4-((x&1)<<2)));
627 if ((x&1)==1) bits++;
629 bits = (dstbits += linebytes);
632 else goto notsupported;
634 break;
636 case 8:
637 /* ==== 8 colormap bitmap to 4 colormap dib ==== */
638 if ( bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
640 PALETTEENTRY val;
642 for( h = lines - 1; h >= 0; h-- ) {
643 srcpixel = bmpImage->data + (h*bmpImage->bytes_per_line);
644 for( x = 0; x < dstwidth; x++ ) {
645 if (!(x&1)) *bits = 0;
646 val = srccolors[(int)*srcpixel++];
647 *bits |= ( X11DRV_DIB_GetNearestIndex(colors, 16,
648 val.peRed,
649 val.peGreen,
650 val.peBlue) << (4*(1-(x&1))) );
651 if ((x&1)==1) bits++;
653 bits = (dstbits += linebytes);
656 else goto notsupported;
658 break;
660 case 15:
662 LPWORD srcpixel;
663 WORD val;
665 /* ==== 555 BGR bitmap to 4 colormap dib ==== */
666 if (bmpImage->red_mask == 0x7c00 && bmpImage->blue_mask == 0x1f)
668 for( h = lines - 1; h >= 0; h--) {
669 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
670 for( x = 0; x < dstwidth; x++) {
671 if (!(x&1)) *bits = 0;
672 val = *srcpixel++;
673 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 16,
674 ((val >> 7) & 0xf8) |
675 ((val >> 12) & 0x7),
676 ((val >> 2) & 0xf8) |
677 ((val >> 7) & 0x3),
678 ((val << 3) & 0xf8) |
679 ((val >> 2) & 0x7) ) << ((1-(x&1))<<2) );
680 if ((x&1)==1) bits++;
682 bits = (dstbits += linebytes);
685 /* ==== 555 RGB bitmap to 4 colormap dib ==== */
686 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0x7c00)
688 for( h = lines - 1; h >= 0; h--)
690 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
691 for( x = 0; x < dstwidth; x++) {
692 if (!(x&1)) *bits = 0;
693 val = *srcpixel++;
694 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 16,
695 ((val << 3) & 0xf8) |
696 ((val >> 2) & 0x7),
697 ((val >> 2) & 0xfc) |
698 ((val >> 7) & 0x3),
699 ((val >> 7) & 0xf8) |
700 ((val >> 12) & 0x7) ) << ((1-(x&1))<<2) );
701 if ((x&1)==1) bits++;
703 bits = (dstbits += linebytes);
706 else goto notsupported;
708 break;
710 case 16:
712 LPWORD srcpixel;
713 WORD val;
715 /* ==== 565 BGR bitmap to 4 colormap dib ==== */
716 if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f)
718 for( h = lines - 1; h >= 0; h--)
720 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
721 for( x = 0; x < dstwidth; x++) {
722 if (!(x&1)) *bits = 0;
723 val = *srcpixel++;
724 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 16,
725 ((val >> 8) & 0xf8) |
726 ((val >> 13) & 0x7),
727 ((val >> 3) & 0xfc) |
728 ((val >> 9) & 0x3),
729 ((val << 3) & 0xf8) |
730 ((val >> 2) & 0x7) ) << ((1-(x&1))<<2) );
731 if ((x&1)==1) bits++;
733 bits = (dstbits += linebytes);
736 /* ==== 565 RGB bitmap to 4 colormap dib ==== */
737 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0xf800)
739 for( h = lines - 1; h >= 0; h--)
741 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
742 for( x = 0; x < dstwidth; x++) {
743 if (!(x&1)) *bits = 0;
744 val = *srcpixel++;
745 *bits |= (X11DRV_DIB_GetNearestIndex( colors, 16,
746 ((val << 3) & 0xf8) |
747 ((val >> 2) & 0x7),
748 ((val >> 3) & 0xfc) |
749 ((val >> 9) & 0x3),
750 ((val >> 8) & 0xf8) |
751 ((val >> 13) & 0x7) ) << ((1-(x&1))<<2) );
752 if ((x&1)==1) bits++;
754 bits = (dstbits += linebytes);
757 else goto notsupported;
759 break;
761 case 24:
762 case 32:
764 BYTE *srcpixel;
766 /* ==== 24/32 BGR bitmap to 4 colormap dib ==== */
767 if (bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff)
769 for (h = lines - 1; h >= 0; h--)
771 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
772 for (x = 0; x < dstwidth; x+=2, srcpixel+=8) /* 2 pixels at a time */
773 *bits++ = (X11DRV_DIB_GetNearestIndex(colors, 16, srcpixel[2] , srcpixel[1], srcpixel[0]) << 4) |
774 X11DRV_DIB_GetNearestIndex(colors, 16, srcpixel[6] , srcpixel[5], srcpixel[4]);
775 bits = (dstbits += linebytes);
778 /* ==== 24/32 RGB bitmap to 4 colormap dib ==== */
779 else if (bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000)
781 for (h = lines - 1; h >= 0; h--)
783 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
784 for (x = 0; x < dstwidth; x+=2, srcpixel+=8) /* 2 pixels at a time */
785 *bits++ = (X11DRV_DIB_GetNearestIndex(colors, 16, srcpixel[0] , srcpixel[1], srcpixel[2]) << 4) |
786 X11DRV_DIB_GetNearestIndex(colors, 16, srcpixel[4] , srcpixel[5], srcpixel[6]);
787 bits = (dstbits += linebytes);
790 else goto notsupported;
792 break;
794 default: /* ? bit bmp -> 4 bit DIB */
795 notsupported:
796 FIXME("from %d bit bitmap with mask R,G,B %x,%x,%x to 4 bit DIB\n",
797 bmpImage->bits_per_pixel, (int)bmpImage->red_mask,
798 (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
799 for (h = lines-1; h >= 0; h--) {
800 for (x = 0; x < dstwidth/2; x++) {
801 *bits++ = (X11DRV_DIB_MapColor((int *)colors, 16,
802 XGetPixel( bmpImage, x++, h ), 0) << 4)
803 | (X11DRV_DIB_MapColor((int *)colors, 16,
804 XGetPixel( bmpImage, x++, h ), 0) & 0x0f);
806 if (dstwidth & 1)
807 *bits = (X11DRV_DIB_MapColor((int *)colors, 16,
808 XGetPixel( bmpImage, x++, h ), 0) << 4);
809 bits = (dstbits += linebytes);
811 break;
815 /***********************************************************************
816 * X11DRV_DIB_SetImageBits_RLE4
818 * SetDIBits for a 4-bit deep compressed DIB.
820 static void X11DRV_DIB_SetImageBits_RLE4( int lines, const BYTE *bits,
821 DWORD width, DWORD dstwidth,
822 int left, int *colors,
823 XImage *bmpImage )
825 int x = 0, c, length;
826 const BYTE *begin = bits;
828 lines--;
830 while ((int)lines >= 0) {
831 length = *bits++;
832 if (length) { /* encoded */
833 c = *bits++;
834 while (length--) {
835 if(x >= width) {
836 x = 0;
837 if(--lines < 0)
838 return;
840 XPutPixel(bmpImage, x++, lines, colors[c >>4]);
841 if (length) {
842 length--;
843 if(x >= width) {
844 x = 0;
845 if(--lines < 0)
846 return;
848 XPutPixel(bmpImage, x++, lines, colors[c & 0xf]);
851 } else {
852 length = *bits++;
853 switch (length) {
854 case 0: /* eol */
855 x = 0;
856 lines--;
857 continue;
859 case 1: /* eopicture */
860 return;
862 case 2: /* delta */
863 x += *bits++;
864 if(x >= width) {
865 FIXME_(x11drv)("x-delta is too large?\n");
866 return;
868 lines -= *bits++;
869 continue;
871 default: /* absolute */
872 while (length--) {
873 c = *bits++;
874 if(x >= width) {
875 x = 0;
876 if(--lines < 0)
877 return;
879 XPutPixel(bmpImage, x++, lines, colors[c >> 4]);
880 if (length) {
881 length--;
882 if(x >= width) {
883 x = 0;
884 if(--lines < 0)
885 return;
887 XPutPixel(bmpImage, x++, lines, colors[c & 0xf]);
890 if ((bits - begin) & 1)
891 bits++;
899 /***********************************************************************
900 * X11DRV_DIB_SetImageBits_8
902 * SetDIBits for an 8-bit deep DIB.
904 static void X11DRV_DIB_SetImageBits_8( int lines, const BYTE *srcbits,
905 DWORD srcwidth, DWORD dstwidth, int left,
906 const int *colors, XImage *bmpImage )
908 DWORD x;
909 int h, color;
910 const BYTE *bits;
912 /* align to 32 bit */
913 DWORD linebytes = (srcwidth + 3) & ~3;
915 dstwidth += left;
917 if (lines < 0 )
919 lines = -lines;
920 srcbits = srcbits + ( linebytes * (lines-1) );
921 linebytes = -linebytes;
924 bits = srcbits + left;
926 switch (bmpImage->depth) {
927 case 15:
928 case 16:
929 #if defined(__i386__) && defined(__GNUC__)
930 /* Some X servers might have 32 bit/ 16bit deep pixel */
931 if (lines && (dstwidth!=left) && (bmpImage->bits_per_pixel == 16))
933 for (h = lines ; h--; ) {
934 int _cl1,_cl2; /* temp outputs for asm below */
935 /* Borrowed from DirectDraw */
936 __asm__ __volatile__(
937 "xor %%eax,%%eax\n"
938 "cld\n"
939 "1:\n"
940 " lodsb\n"
941 " movw (%%edx,%%eax,4),%%ax\n"
942 " stosw\n"
943 " xor %%eax,%%eax\n"
944 " loop 1b\n"
945 :"=S" (bits), "=D" (_cl1), "=c" (_cl2)
946 :"S" (bits),
947 "D" (bmpImage->data+h*bmpImage->bytes_per_line+left*2),
948 "c" (dstwidth-left),
949 "d" (colors)
950 :"eax", "cc", "memory"
952 bits = (srcbits += linebytes) + left;
954 return;
956 break;
957 #endif
958 default:
959 break; /* use slow generic case below */
962 for (h = lines - 1; h >= 0; h--) {
963 for (x = left; x < dstwidth; x++, bits++) {
964 color = colors[*bits];
965 XPutPixel( bmpImage, x, h, colors[*bits] );
967 bits = (srcbits += linebytes) + left;
971 /***********************************************************************
972 * X11DRV_DIB_GetImageBits_8
974 * GetDIBits for an 8-bit deep DIB.
976 static void X11DRV_DIB_GetImageBits_8( int lines, BYTE *dstbits,
977 DWORD srcwidth, DWORD dstwidth,
978 RGBQUAD *colors, PALETTEENTRY *srccolors,
979 XImage *bmpImage )
981 DWORD x;
982 int h;
983 BYTE *bits;
985 /* align to 32 bit */
986 DWORD linebytes = (srcwidth + 3) & ~3;
988 if (lines < 0 )
990 lines = -lines;
991 dstbits = dstbits + ( linebytes * (lines-1) );
992 linebytes = -linebytes;
995 bits = dstbits;
998 Hack for now
999 This condition is true when GetImageBits has been called by UpdateDIBSection.
1000 For now, GetNearestIndex is too slow to support 256 colormaps, so we'll just use for
1001 for GetDIBits calls. (In somes cases, in a updateDIBSection, the returned colors are bad too)
1003 if (!srccolors) goto updatesection;
1005 switch(bmpImage->depth) {
1007 case 1:
1008 /* ==== monochrome bitmap to 8 colormap dib ==== */
1009 case 4:
1010 /* ==== 4 colormap bitmap to 8 colormap dib ==== */
1011 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
1013 PALETTEENTRY val;
1015 for (h = lines - 1; h >= 0; h--) {
1016 for (x = 0; x < dstwidth; x++) {
1017 val = srccolors[XGetPixel(bmpImage, x, h)];
1018 *bits++ = X11DRV_DIB_GetNearestIndex(colors, 256, val.peRed,
1019 val.peGreen, val.peBlue);
1021 bits = (dstbits += linebytes);
1024 else goto notsupported;
1026 break;
1028 case 8:
1029 /* ==== 8 colormap bitmap to 8 colormap dib ==== */
1030 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
1032 BYTE *srcpixel;
1033 PALETTEENTRY val;
1035 for (h = lines - 1; h >= 0; h--) {
1036 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
1037 for (x = 0; x < dstwidth; x++) {
1038 val = srccolors[(int)*srcpixel++];
1039 *bits++ = X11DRV_DIB_GetNearestIndex(colors, 256, val.peRed,
1040 val.peGreen, val.peBlue);
1042 bits = (dstbits += linebytes);
1045 else goto notsupported;
1047 break;
1049 case 15:
1051 LPWORD srcpixel;
1052 WORD val;
1054 /* ==== 555 BGR bitmap to 8 colormap dib ==== */
1055 if (bmpImage->red_mask == 0x7c00 && bmpImage->blue_mask == 0x001f)
1057 for( h = lines - 1; h >= 0; h--)
1059 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
1060 for( x = 0; x < dstwidth; x++ )
1062 val = *srcpixel++;
1063 *bits++ = X11DRV_DIB_GetNearestIndex( colors, 256,
1064 ((val >> 7) & 0xf8) |
1065 ((val >> 12) & 0x7),
1066 ((val >> 2) & 0xf8) |
1067 ((val >> 7) & 0x3),
1068 ((val << 3) & 0xf8) |
1069 ((val >> 2) & 0x7) );
1071 bits = (dstbits += linebytes);
1074 /* ==== 555 RGB bitmap to 8 colormap dib ==== */
1075 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0x7c00)
1077 for( h = lines - 1; h >= 0; h--)
1079 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
1080 for( x = 0; x < dstwidth; x++ )
1082 val = *srcpixel++;
1083 *bits++ = X11DRV_DIB_GetNearestIndex( colors, 256,
1084 ((val << 3) & 0xf8) |
1085 ((val >> 2) & 0x7),
1086 ((val >> 2) & 0xf8) |
1087 ((val >> 7) & 0x3),
1088 ((val >> 7) & 0xf8) |
1089 ((val >> 12) & 0x7) );
1091 bits = (dstbits += linebytes);
1094 else goto notsupported;
1096 break;
1098 case 16:
1100 LPWORD srcpixel;
1101 WORD val;
1103 /* ==== 565 BGR bitmap to 8 colormap dib ==== */
1104 if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f)
1106 for( h = lines - 1; h >= 0; h--)
1108 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
1109 for( x = 0; x < dstwidth; x++ )
1111 val = *srcpixel++;
1112 *bits++ = X11DRV_DIB_GetNearestIndex( colors, 256,
1113 ((val >> 8) & 0xf8) |
1114 ((val >> 13) & 0x7),
1115 ((val >> 3) & 0xfc) |
1116 ((val >> 9) & 0x3),
1117 ((val << 3) & 0xf8) |
1118 ((val >> 2) & 0x7) );
1120 bits = (dstbits += linebytes);
1123 /* ==== 565 RGB bitmap to 8 colormap dib ==== */
1124 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0xf800)
1126 for( h = lines - 1; h >= 0; h--)
1128 srcpixel = (LPWORD)(bmpImage->data + h*bmpImage->bytes_per_line);
1129 for( x = 0; x < dstwidth; x++ )
1131 val = *srcpixel++;
1132 *bits++ = X11DRV_DIB_GetNearestIndex( colors, 256,
1133 ((val << 3) & 0xf8) |
1134 ((val >> 2) & 0x7),
1135 ((val >> 3) & 0x00fc) |
1136 ((val >> 9) & 0x3),
1137 ((val >> 8) & 0x00f8) |
1138 ((val >> 13) & 0x7) );
1140 bits = (dstbits += linebytes);
1143 else goto notsupported;
1145 break;
1147 case 24:
1148 case 32:
1150 BYTE *srcpixel;
1152 /* ==== 24/32 BGR bitmap to 8 colormap dib ==== */
1153 if (bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff)
1155 for (h = lines - 1; h >= 0; h--)
1157 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
1158 for (x = 0; x < dstwidth; x++, srcpixel+=4)
1159 *bits++ = X11DRV_DIB_GetNearestIndex(colors, 256,
1160 srcpixel[2] , srcpixel[1], *srcpixel);
1161 bits = (dstbits += linebytes);
1164 /* ==== 24/32 RGB bitmap to 8 colormap dib ==== */
1165 else if (bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000)
1167 for (h = lines - 1; h >= 0; h--)
1169 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
1170 for (x = 0; x < dstwidth; x++, srcpixel+=4)
1171 *bits++ = X11DRV_DIB_GetNearestIndex(colors, 256,
1172 *srcpixel, srcpixel[1], srcpixel[2]);
1173 bits = (dstbits += linebytes);
1177 else goto notsupported;
1179 break;
1181 default: /* ? bit bmp -> 8 bit DIB */
1182 notsupported:
1183 FIXME("from %d bit bitmap with mask R,G,B %x,%x,%x to 8 bit DIB\n",
1184 bmpImage->depth, (int)bmpImage->red_mask,
1185 (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
1186 updatesection:
1187 for (h = lines - 1; h >= 0; h--) {
1188 for (x = 0; x < dstwidth; x++, bits++) {
1189 *bits = X11DRV_DIB_MapColor((int *)colors, 256,
1190 XGetPixel( bmpImage, x, h ), *bits);
1192 bits = (dstbits += linebytes);
1194 break;
1198 /***********************************************************************
1199 * X11DRV_DIB_SetImageBits_RLE8
1201 * SetDIBits for an 8-bit deep compressed DIB.
1203 * This function rewritten 941113 by James Youngman. WINE blew out when I
1204 * first ran it because my desktop wallpaper is a (large) RLE8 bitmap.
1206 * This was because the algorithm assumed that all RLE8 bitmaps end with the
1207 * 'End of bitmap' escape code. This code is very much laxer in what it
1208 * allows to end the expansion. Possibly too lax. See the note by
1209 * case RleDelta. BTW, MS's documentation implies that a correct RLE8
1210 * bitmap should end with RleEnd, but on the other hand, software exists
1211 * that produces ones that don't and Windows 3.1 doesn't complain a bit
1212 * about it.
1214 * (No) apologies for my English spelling. [Emacs users: c-indent-level=4].
1215 * James A. Youngman <mbcstjy@afs.man.ac.uk>
1216 * [JAY]
1219 enum Rle8_EscapeCodes
1222 * Apologies for polluting your file's namespace...
1224 RleEol = 0, /* End of line */
1225 RleEnd = 1, /* End of bitmap */
1226 RleDelta = 2 /* Delta */
1229 static void X11DRV_DIB_SetImageBits_RLE8( int lines, const BYTE *bits,
1230 DWORD width, DWORD dstwidth,
1231 int left, int *colors,
1232 XImage *bmpImage )
1234 int x; /* X-positon on each line. Increases. */
1235 int line; /* Line #. Starts at lines-1, decreases */
1236 const BYTE *pIn = bits; /* Pointer to current position in bits */
1237 BYTE length; /* The length pf a run */
1238 BYTE color_index; /* index into colors[] as read from bits */
1239 BYTE escape_code; /* See enum Rle8_EscapeCodes.*/
1240 int color; /* value of colour[color_index] */
1242 if (lines == 0) /* Let's hope this doesn't happen. */
1243 return;
1246 * Note that the bitmap data is stored by Windows starting at the
1247 * bottom line of the bitmap and going upwards. Within each line,
1248 * the data is stored left-to-right. That's the reason why line
1249 * goes from lines-1 to 0. [JAY]
1252 x = 0;
1253 line = lines-1;
1256 length = *pIn++;
1259 * If the length byte is not zero (which is the escape value),
1260 * We have a run of length pixels all the same colour. The colour
1261 * index is stored next.
1263 * If the length byte is zero, we need to read the next byte to
1264 * know what to do. [JAY]
1266 if (length != 0)
1269 * [Run-Length] Encoded mode
1271 color_index = (*pIn++); /* Get the colour index. */
1272 color = colors[color_index];
1274 while(length--)
1276 if (x>=dstwidth)
1278 x=0;
1279 line--;
1281 XPutPixel(bmpImage, x++, line, color);
1284 else
1287 * Escape codes (may be an absolute sequence though)
1289 escape_code = (*pIn++);
1290 switch(escape_code)
1292 case RleEol: /* =0, end of line */
1294 x = 0;
1295 line--;
1296 break;
1299 case RleEnd: /* =1, end of bitmap */
1302 * Not all RLE8 bitmaps end with this
1303 * code. For example, Paint Shop Pro
1304 * produces some that don't. That's (I think)
1305 * what caused the previous implementation to
1306 * fail. [JAY]
1308 line=-1; /* Cause exit from do loop. */
1309 break;
1312 case RleDelta: /* =2, a delta */
1315 * Note that deltaing to line 0
1316 * will cause an exit from the loop,
1317 * which may not be what is intended.
1318 * The fact that there is a delta in the bits
1319 * almost certainly implies that there is data
1320 * to follow. You may feel that we should
1321 * jump to the top of the loop to avoid exiting
1322 * in this case.
1324 * TODO: Decide what to do here in that case. [JAY]
1326 x += (*pIn++);
1327 line -= (*pIn++);
1328 if (line == 0)
1330 TRACE("Delta to last line of bitmap "
1331 "(wrongly?) causes loop exit\n");
1333 break;
1336 default: /* >2, switch to absolute mode */
1339 * Absolute Mode
1341 length = escape_code;
1342 while(length--)
1344 color_index = (*pIn++);
1345 if (x>=dstwidth)
1347 x=0;
1348 line--;
1350 XPutPixel(bmpImage, x++, line,
1351 colors[color_index]);
1355 * If you think for a moment you'll realise that the
1356 * only time we could ever possibly read an odd
1357 * number of bytes is when there is a 0x00 (escape),
1358 * a value >0x02 (absolute mode) and then an odd-
1359 * length run. Therefore this is the only place we
1360 * need to worry about it. Everywhere else the
1361 * bytes are always read in pairs. [JAY]
1363 if (escape_code & 1)
1364 pIn++; /* Throw away the pad byte. */
1365 break;
1367 } /* switch (escape_code) : Escape sequence */
1368 } /* process either an encoded sequence or an escape sequence */
1370 /* We expect to come here more than once per line. */
1371 } while (line >= 0); /* Do this until the bitmap is filled */
1374 * Everybody comes here at the end.
1375 * Check how we exited the loop and print a message if it's a bit odd.
1376 * [JAY]
1378 if ( (*(pIn-2) != 0/*escape*/) || (*(pIn-1)!= RleEnd) )
1380 TRACE("End-of-bitmap without (strictly) proper escape code. Last two "
1381 "bytes were: %02X %02X.\n", (int)*(pIn-2),(int)*(pIn-1));
1386 /***********************************************************************
1387 * X11DRV_DIB_SetImageBits_16
1389 * SetDIBits for a 16-bit deep DIB.
1391 static void X11DRV_DIB_SetImageBits_16( int lines, const BYTE *srcbits,
1392 DWORD srcwidth, DWORD dstwidth, int left,
1393 DC *dc, DWORD rSrc, DWORD gSrc, DWORD bSrc,
1394 XImage *bmpImage )
1396 DWORD x;
1397 int h;
1399 /* align to 32 bit */
1400 DWORD linebytes = (srcwidth * 2 + 3) & ~3;
1402 if (lines < 0 )
1404 lines = -lines;
1405 srcbits = srcbits + ( linebytes * (lines-1));
1406 linebytes = -linebytes;
1409 switch ( bmpImage->depth )
1411 case 15:
1412 /* using same format as XImage */
1413 if (rSrc == bmpImage->red_mask && gSrc == bmpImage->green_mask && bSrc == bmpImage->blue_mask)
1414 for (h = lines - 1; h >= 0; h--, srcbits += linebytes)
1415 memcpy ( bmpImage->data + h * bmpImage->bytes_per_line + left*2, srcbits + left*2, dstwidth*2 );
1416 else /* We need to do a conversion from a 565 dib */
1418 LPDWORD dstpixel, ptr = (LPDWORD)(srcbits + left*2);
1419 DWORD val;
1420 int div = dstwidth % 2;
1422 for (h = lines - 1; h >= 0; h--) {
1423 dstpixel = (LPDWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1424 for (x = 0; x < dstwidth/2; x++) { /* Do 2 pixels at a time */
1425 val = *ptr++;
1426 *dstpixel++ = ((val >> 1) & 0x7fe07fe0) | (val & 0x001f001f); /* Red & Green & Blue */
1428 if (div != 0) /* Odd width? */
1429 *dstpixel = ((*(WORD *)ptr >> 1) & 0x7fe0) | (*(WORD *)ptr & 0x001f);
1430 ptr = (LPDWORD) ((srcbits += linebytes) + left*2);
1433 break;
1435 case 16:
1436 /* using same format as XImage */
1437 if (rSrc == bmpImage->red_mask && gSrc == bmpImage->green_mask && bSrc == bmpImage->blue_mask)
1438 for (h = lines - 1; h >= 0; h--, srcbits += linebytes)
1439 memcpy ( bmpImage->data + h * bmpImage->bytes_per_line + left*2, srcbits + left*2, dstwidth*2 );
1440 else /* We need to do a conversion from a 555 dib */
1442 LPDWORD dstpixel, ptr = (LPDWORD)(srcbits + left*2);
1443 DWORD val;
1444 int div = dstwidth % 2;
1446 for (h = lines - 1; h >= 0; h--) {
1447 dstpixel = (LPDWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1448 for (x = 0; x < dstwidth/2; x++) { /* Do 2 pixels at a time */
1449 val = *ptr++;
1450 *dstpixel++ = ((val << 1) & 0xffc0ffc0) | ((val >> 4) & 0x00200020) | /* Red & Green */
1451 (val & 0x001f001f); /* Blue */
1453 if (div != 0) /* Odd width? */
1454 *dstpixel = ((*(WORD *)ptr << 1) & 0xffc0) | ((*(WORD *)ptr >> 4) & 0x0020)
1455 | (*(WORD *)ptr & 0x001f);
1456 ptr = (LPDWORD) ((srcbits += linebytes) + left*2);
1459 break;
1461 case 24:
1462 case 32:
1464 DWORD *dstpixel;
1465 LPWORD ptr = (LPWORD)srcbits + left;
1466 DWORD val;
1468 /* ==== 555 BGR dib to 24/32 BGR bitmap ==== */
1469 if (bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff)
1471 for (h = lines - 1; h >= 0; h--) {
1472 dstpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line + left*4);
1473 for (x = 0; x < dstwidth; x++) {
1475 val = *ptr++;
1476 *dstpixel++ = ((val << 9) & 0xf80000) | ((val << 4) & 0x070000) | /* Red */
1477 ((val << 6) & 0x00f800) | ((val << 1) & 0x000700) | /* Green */
1478 ((val << 3) & 0x0000f8) | ((val >> 2) & 0x000007); /* Blue */
1480 ptr = (LPWORD)(srcbits += linebytes) + left;
1483 /* ==== 555 BGR dib to 24/32 RGB bitmap ==== */
1484 else if (bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000)
1486 for (h = lines - 1; h >= 0; h--) {
1487 dstpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line + left*4);
1488 for (x = 0; x < dstwidth; x++) {
1490 val = *ptr++;
1491 *dstpixel++ = ((val >> 7) & 0x0000f8) | ((val >> 12) & 0x000007) | /* Red */
1492 ((val << 6) & 0x00f800) | ((val << 1) & 0x000700) | /* Green */
1493 ((val << 19) & 0xf80000) | ((val >> 14) & 0x070000); /* Blue */
1495 ptr = (LPWORD)(srcbits += linebytes) + left;
1500 break;
1502 case 1:
1503 case 4:
1504 case 8:
1506 LPWORD ptr = (LPWORD)srcbits + left;
1507 WORD val;
1508 int sc1, sc2;
1510 /* Set color scaling values */
1511 if ( rSrc == 0x7c00 ) { sc1 = 7; sc2 = 2; } /* 555 dib */
1512 else { sc1 = 8; sc2 = 3; } /* 565 dib */
1514 for (h = lines - 1; h >= 0; h--) {
1515 for (x = left; x < dstwidth+left; x++) {
1516 val = *ptr++;
1517 XPutPixel( bmpImage, x, h,
1518 X11DRV_PALETTE_ToPhysical(dc, RGB(((val & rSrc) >> sc1), /* Red */
1519 ((val & gSrc) >> sc2), /* Green */
1520 ((val & bSrc) << 3)))); /* Blue */
1522 ptr = (LPWORD) (srcbits += linebytes) + left;
1525 break;
1527 default:
1528 FIXME("16 bit DIB %d bit bitmap\n", bmpImage->bits_per_pixel);
1529 break;
1535 /***********************************************************************
1536 * X11DRV_DIB_GetImageBits_16
1538 * GetDIBits for an 16-bit deep DIB.
1540 static void X11DRV_DIB_GetImageBits_16( int lines, BYTE *dstbits,
1541 DWORD dstwidth, DWORD srcwidth,
1542 PALETTEENTRY *srccolors, XImage *bmpImage )
1544 DWORD x;
1545 int h;
1547 /* align to 32 bit */
1548 DWORD linebytes = (dstwidth * 2 + 3) & ~3;
1550 if (lines < 0 )
1552 lines = -lines;
1553 dstbits = dstbits + ( linebytes * (lines-1));
1554 linebytes = -linebytes;
1557 switch ( bmpImage->depth )
1559 case 15:
1560 /* ==== 555 BGR bitmap to 555 BGR dib ==== */
1561 if (bmpImage->red_mask == 0x7c00 && bmpImage->blue_mask == 0x001f)
1562 for (h = lines - 1; h >= 0; h--, dstbits += linebytes)
1563 memcpy( dstbits, bmpImage->data + h*bmpImage->bytes_per_line, srcwidth*2 );
1565 /* ==== 555 RGB bitmap to 555 BGR dib ==== */
1566 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0x7c00)
1568 LPDWORD srcpixel, ptr = (LPDWORD)dstbits;
1569 DWORD val;
1570 int div = srcwidth % 2;
1572 for (h = lines - 1; h >= 0; h--) {
1573 srcpixel = (LPDWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
1574 for (x = 0; x < srcwidth/2; x++) { /* Do 2 pixels at a time */
1575 val = *srcpixel++;
1576 *ptr++ = ((val << 10) & 0xf800f800) | (val & 0x03e003e0) | /* Red & Green */
1577 ((val >> 10) & 0x001f001f); /* Blue */
1579 if (div != 0) /* Odd width? */
1580 *ptr = ((*(WORD *)srcpixel << 1) & 0xffc0) | ((*(WORD *)srcpixel >> 4) & 0x0020) |
1581 (*(WORD *)srcpixel & 0x001f);
1582 ptr = (LPDWORD)(dstbits += linebytes);
1585 else goto notsupported;
1587 break;
1589 case 16:
1591 LPDWORD srcpixel, ptr = (LPDWORD)dstbits;
1592 DWORD val;
1593 int div = srcwidth % 2;
1595 /* ==== 565 BGR bitmap to 555 BGR dib ==== */
1596 if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f )
1598 for (h = lines - 1; h >= 0; h--) {
1599 srcpixel = (LPDWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
1600 for (x = 0; x < srcwidth/2; x++) { /* Do 2 pixels at a time */
1601 val = *srcpixel++;
1602 *ptr++ = ((val >> 1) & 0x7fe07fe0) | /* Red & Green */
1603 (val & 0x001f001f); /* Blue */
1605 if (div != 0) /* Odd width? */
1606 *ptr = ((*(WORD *)srcpixel >> 1) & 0x7fe0) | (*(WORD *)srcpixel & 0x001f);
1607 ptr = (LPDWORD) (dstbits += linebytes);
1610 /* ==== 565 RGB bitmap to 555 BGR dib ==== */
1611 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0xf800)
1613 for (h = lines - 1; h >= 0; h--) {
1614 srcpixel = (LPDWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
1615 for (x = 0; x < srcwidth/2; x++) { /* Do 2 pixels at a time */
1616 val = *srcpixel++;
1617 *ptr++ = ((val << 10) & 0x7c007c00) | ((val >> 1) & 0x03e003e0) | /* Red & Green */
1618 ((val >> 11) & 0x001f001f); /* Blue */
1620 if (div != 0) /* Odd width? */
1621 *ptr = ((*(WORD *)srcpixel >> 1) & 0x7fe0) | (*(WORD *)srcpixel & 0x001f);
1622 ptr = (LPDWORD) (dstbits += linebytes);
1625 else goto notsupported;
1627 break;
1629 case 24:
1630 case 32:
1632 DWORD *srcpixel;
1633 LPWORD ptr = (LPWORD)dstbits;
1634 DWORD val;
1636 /* ==== 24/32 BGR bitmap to 555 BGR dib ==== */
1637 if (bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff)
1639 for (h = lines - 1; h >= 0; h--) {
1640 srcpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line);
1641 for (x = 0; x < srcwidth; x++, ptr++) {
1642 val = *srcpixel++;
1643 *ptr = ((val >> 9) & 0x7c00) | /* Red */
1644 ((val >> 6) & 0x03e0) | /* Green */
1645 ((val >> 3) & 0x001f); /* Blue */
1647 ptr = (LPWORD)(dstbits += linebytes);
1650 /* ==== 24/32 RGB bitmap to 555 BGR dib ==== */
1651 else if (bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000)
1653 for (h = lines - 1; h >= 0; h--) {
1654 srcpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line);
1655 for (x = 0; x < srcwidth; x++, ptr++) {
1656 val = *srcpixel++;
1657 *ptr = ((val << 7) & 0x7c00) | /* Red */
1658 ((val >> 6) & 0x03e0) | /* Green */
1659 ((val >> 19) & 0x001f); /* Blue */
1661 ptr = (LPWORD) (dstbits += linebytes);
1664 else goto notsupported;
1666 break;
1668 case 1:
1669 /* ==== monochrome bitmap to 16 BGR dib ==== */
1670 case 4:
1671 /* ==== 4 colormap bitmap to 16 BGR dib ==== */
1672 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
1674 LPWORD ptr = (LPWORD)dstbits;
1675 PALETTEENTRY val;
1677 for (h = lines - 1; h >= 0; h--) {
1678 for (x = 0; x < dstwidth; x++) {
1679 val = srccolors[XGetPixel(bmpImage, x, h)];
1680 *ptr++ = ((val.peRed << 7) & 0x7c00) |
1681 ((val.peGreen << 2) & 0x03e0) |
1682 ((val.peBlue >> 3) & 0x001f);
1684 ptr = (LPWORD)(dstbits += linebytes);
1687 else goto notsupported;
1689 break;
1691 case 8:
1692 /* ==== 8 colormap bitmap to 16 BGR dib ==== */
1693 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
1695 LPWORD ptr = (LPWORD)dstbits;
1696 BYTE *srcpixel;
1697 PALETTEENTRY val;
1699 for (h = lines - 1; h >= 0; h--) {
1700 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
1701 for (x = 0; x < dstwidth; x++) {
1702 val = srccolors[(int)*srcpixel++];
1703 *ptr++ = ((val.peRed << 7) & 0x7c00) |
1704 ((val.peGreen << 2) & 0x03e0) |
1705 ((val.peBlue >> 3) & 0x001f);
1707 ptr = (LPWORD)(dstbits += linebytes);
1710 else goto notsupported;
1712 break;
1714 default:
1715 notsupported:
1717 BYTE r,g, b;
1718 LPWORD ptr = (LPWORD)dstbits;
1720 FIXME("from %d bit bitmap with mask R,G,B %x,%x,%x to 16 bit DIB\n",
1721 bmpImage->depth, (int)bmpImage->red_mask,
1722 (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
1723 for (h = lines - 1; h >= 0; h--)
1725 for (x = 0; x < dstwidth; x++, ptr++)
1727 COLORREF pixel = X11DRV_PALETTE_ToLogical( XGetPixel( bmpImage, x, h ) );
1728 r = (BYTE) GetRValue(pixel);
1729 g = (BYTE) GetGValue(pixel);
1730 b = (BYTE) GetBValue(pixel);
1731 *ptr = ( ((r << 7) & 0x7c00) | ((g << 2) & 0x03e0) | ((b >> 3) & 0x001f) );
1733 ptr = (LPWORD) (dstbits += linebytes);
1736 break;
1741 /***********************************************************************
1742 * X11DRV_DIB_SetImageBits_24
1744 * SetDIBits for a 24-bit deep DIB.
1746 static void X11DRV_DIB_SetImageBits_24( int lines, const BYTE *srcbits,
1747 DWORD srcwidth, DWORD dstwidth, int left,
1748 DC *dc, XImage *bmpImage )
1750 DWORD x;
1751 int h;
1753 /* align to 32 bit */
1754 DWORD linebytes = (srcwidth * 3 + 3) & ~3;
1756 if (lines < 0 )
1758 lines = -lines;
1759 srcbits = srcbits + linebytes * (lines - 1);
1760 linebytes = -linebytes;
1763 switch ( bmpImage->depth )
1765 case 24:
1767 if (bmpImage->bits_per_pixel == 24) {
1768 int dstlinebytes = linebytes;
1769 BYTE *dstpixel;
1770 BYTE *ptr = (BYTE *)(srcbits+left*3);
1772 if (dstlinebytes < 0 ) dstlinebytes = -dstlinebytes;
1773 dstpixel = bmpImage->data + lines*dstlinebytes + left*3;
1774 for(h = lines ; h-- ; ) {
1775 dstpixel-=dstlinebytes;
1776 memcpy(dstpixel,ptr,dstwidth*3);
1777 ptr +=linebytes;
1779 break;
1782 case 32:
1784 if( bmpImage->blue_mask == 0xff && bmpImage->red_mask == 0xff0000 ) /* packed BGR to unpacked BGR */
1786 DWORD *dstpixel, val, buf;
1787 DWORD *ptr = (DWORD *)(srcbits + left*3);
1788 BYTE *bits;
1789 int div = dstwidth % 4;
1790 int divk;
1792 for(h = lines - 1; h >= 0; h--)
1794 dstpixel = (DWORD *) (bmpImage->data + h*bmpImage->bytes_per_line + left*4);
1796 for (x = 0; x < dstwidth/4; x++) { /* do 3 dwords source, 4 dwords dest at a time */
1797 buf = *ptr++;
1798 *dstpixel++ = buf&0x00ffffff; /* b1, g1, r1 */
1799 val = (buf >> 24); /* b2 */
1800 buf = *ptr++;
1801 *dstpixel++ = (val | (buf<<8)) &0x00ffffff; /* g2, r2 */
1802 val = (buf >> 16); /* b3, g3 */
1803 buf = *ptr++;
1804 *dstpixel++ = (val | (buf<<16)) &0x00ffffff; /* r3 */
1805 *dstpixel++ = (buf >> 8); /* b4, g4, r4 */
1807 for ( divk=div, bits=(BYTE*)ptr; divk>0; divk--, bits+=3 ) /* do remainder */
1809 *dstpixel++ = *(DWORD*)bits & 0x00ffffff; /* b, g, r */
1811 ptr = (DWORD*)((srcbits+=linebytes)+left*3);
1814 else if( bmpImage->blue_mask == 0xff0000 && bmpImage->red_mask == 0xff ) /* packed BGR to unpacked RGB */
1816 DWORD *dstpixel, val, buf;
1817 DWORD *ptr = (DWORD *)(srcbits + left*3);
1818 BYTE *bits;
1819 int div = dstwidth % 4;
1820 int divk;
1822 for(h = lines - 1; h >= 0; h--)
1824 dstpixel = (DWORD *) (bmpImage->data + h*bmpImage->bytes_per_line + left*4);
1826 for (x = 0; x < dstwidth/4; x++) { /* do 3 dwords source, 4 dwords dest at a time */
1827 buf = *ptr++;
1828 *dstpixel++ = ((buf&0xff)<<16) | (buf&0xff00) | ((buf&0xff0000)>>16); /* b1, g1, r1 */
1829 val = ((buf&0xff000000)>>8); /* b2 */
1830 buf = *ptr++;
1831 *dstpixel++ = val | ((buf&0xff)<<8) | ((buf&0xff00)>>8); /* g2, r2 */
1832 val = (buf&0xff0000) | ((buf&0xff000000)>>16); /* b3, g3 */
1833 buf = *ptr++;
1834 *dstpixel++ = val | (buf&0xff); /* r3 */
1835 *dstpixel++ = ((buf&0xff00)<<8) | ((buf&0xff0000)>>8) | (buf>>24); /* b4, g4, r4 */
1837 for ( divk=div, bits=(BYTE*)ptr; divk>0; divk--, bits+=3 ) /* do remainder */
1839 buf = *(DWORD*)bits;
1840 *dstpixel++ = ((buf&0xff)<<16) | (buf&0xff00) | ((buf&0xff0000)>>16); /* b, g, r */
1842 ptr = (DWORD*)((srcbits+=linebytes)+left*3);
1845 else
1846 goto notsupported;
1848 break;
1850 case 15:
1852 if( bmpImage->blue_mask == 0x7c00 && bmpImage->red_mask == 0x1f ) /* BGR888 to RGB555 */
1854 DWORD *ptr = (DWORD *)(srcbits + left*3), val;
1855 LPBYTE bits;
1856 LPWORD dstpixel;
1857 int div = dstwidth % 4;
1858 int divk;
1860 for (h = lines - 1; h >= 0; h--) { /* Do 4 pixels at a time */
1861 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1862 for (x = 0; x < dstwidth/4; x++) {
1863 *dstpixel++ = (WORD)((((val = *ptr++) << 7) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 19) & 0x1f));
1864 *dstpixel++ = (WORD)(((val >> 17) & 0x7c00) | (((val = *ptr++) << 2) & 0x03e0) | ((val >> 11) & 0x1f));
1865 *dstpixel++ = (WORD)(((val >> 9) & 0x07c00) | ((val >> 22) & 0x03e0) | (((val = *ptr++) >> 3) & 0x1f));
1866 *dstpixel++ = (WORD)(((val >> 1) & 0x07c00) | ((val >> 14) & 0x03e0) | ((val >> 27) & 0x1f));
1868 for (bits = (LPBYTE)ptr, divk=div; divk > 0; divk--, bits+=3) /* dstwidth not divisible by 4? */
1869 *dstpixel++ = (((WORD)bits[0] << 7) & 0x07c00) |
1870 (((WORD)bits[1] << 2) & 0x03e0) |
1871 (((WORD)bits[2] >> 3) & 0x001f);
1872 ptr = (DWORD *)((srcbits += linebytes) + left * 3);
1875 else if( bmpImage->blue_mask == 0x1f && bmpImage->red_mask == 0x7c00 ) /* BGR888 to BGR555 */
1877 DWORD *ptr = (DWORD *)(srcbits + left*3), val;
1878 LPBYTE bits;
1879 LPWORD dstpixel;
1880 int div = dstwidth % 4;
1881 int divk;
1883 for (h = lines - 1; h >= 0; h--) { /* Do 4 pixels at a time */
1884 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1885 for (x = 0; x < dstwidth/4; x++) {
1886 *dstpixel++ = (WORD)((((val = *ptr++) >> 3) & 0x1f) | ((val >> 6) & 0x03e0) | ((val >> 9) & 0x7c00));
1887 *dstpixel++ = (WORD)(((val >> 27) & 0x1f) | (((val = *ptr++) << 2) & 0x03e0) | ((val >> 1) & 0x7c00));
1888 *dstpixel++ = (WORD)(((val >> 19) & 0x1f) | ((val >> 22) & 0x03e0) | (((val = *ptr++) << 7) & 0x7c00));
1889 *dstpixel++ = (WORD)(((val >> 11) & 0x1f) | ((val >> 14) & 0x03e0) | ((val >> 17) & 0x7c00));
1891 for (bits = (LPBYTE)ptr, divk=div; divk > 0; divk--, bits+=3) /* dstwidth not divisible by 4? */
1892 *dstpixel++ = (((WORD)bits[2] << 7) & 0x07c00) |
1893 (((WORD)bits[1] << 2) & 0x03e0) |
1894 (((WORD)bits[0] >> 3) & 0x001f);
1895 ptr = (DWORD *)((srcbits += linebytes) + left * 3);
1898 else
1899 goto notsupported;
1901 break;
1903 case 16:
1905 DWORD *ptr = (DWORD *)(srcbits + left*3), val;
1906 LPBYTE bits;
1907 LPWORD dstpixel;
1908 int div = dstwidth % 4;
1909 int divk;
1911 if( bmpImage->blue_mask == 0x001f && bmpImage->red_mask == 0xf800 ) /* BGR888 to BGR565 */
1913 for (h = lines - 1; h >= 0; h--) { /* Do 4 pixels at a time */
1914 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1915 for (x = 0; x < dstwidth/4; x++) {
1916 *dstpixel++ = (WORD)((((val = *ptr++) >> 3) & 0x1f) | ((val >> 5) & 0x07e0) | ((val >> 8) & 0xf800));
1917 *dstpixel++ = (WORD)(((val >> 27) & 0x1f) | (((val = *ptr++) << 3) & 0x07e0) | ((val) & 0xf800));
1918 *dstpixel++ = (WORD)(((val >> 19) & 0x1f) | ((val >> 21) & 0x07e0) | (((val = *ptr++) << 8) & 0xf800));
1919 *dstpixel++ = (WORD)(((val >> 11) & 0x1f) | ((val >> 13) & 0x07e0) | ((val >> 16) & 0xf800));
1921 for ( bits = (LPBYTE)ptr, divk=div; divk > 0; divk--, bits+=3) /* dstwidth is not divisible by 4? */
1922 *dstpixel++ = (((WORD)bits[2] << 8) & 0xf800) |
1923 (((WORD)bits[1] << 3) & 0x07e0) |
1924 (((WORD)bits[0] >> 3) & 0x001f);
1925 ptr = (DWORD *)((srcbits += linebytes) + left * 3);
1928 else if( bmpImage->blue_mask == 0xf800 && bmpImage->red_mask == 0x001f ) /* BGR888 to RGB565 */
1930 for (h = lines - 1; h >= 0; h--) { /* Do 4 pixels at a time */
1931 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line + left*2);
1932 for (x = 0; x < dstwidth/4; x++) {
1933 *dstpixel++ = (WORD)((((val = *ptr++) << 8) & 0xf800) | ((val >> 5) & 0x07e0) | ((val >> 19) & 0x1f));
1934 *dstpixel++ = (WORD)(((val >> 16) & 0xf800) | (((val = *ptr++) << 3) & 0x07e0) | ((val >> 11) & 0x1f));
1935 *dstpixel++ = (WORD)(((val >> 8) & 0xf800) | ((val >> 21) & 0x07e0) | (((val = *ptr++) >> 3) & 0x1f));
1936 *dstpixel++ = (WORD)((val & 0xf800) | ((val >> 13) & 0x07e0) | ((val >> 27) & 0x1f));
1938 for ( bits = (LPBYTE)ptr, divk=div; divk > 0; divk--, bits+=3) /* dstwidth is not divisible by 4? */
1939 *dstpixel++ = (((WORD)bits[0] << 8) & 0xf800) |
1940 (((WORD)bits[1] << 3) & 0x07e0) |
1941 (((WORD)bits[2] >> 3) & 0x001f);
1942 ptr = (DWORD *)((srcbits += linebytes) + left * 3);
1945 else
1946 goto notsupported;
1948 break;
1950 case 1:
1951 case 4:
1952 case 8:
1954 LPBYTE bits = (LPBYTE)srcbits + left*3;
1956 for (h = lines - 1; h >= 0; h--) {
1957 for (x = left; x < dstwidth+left; x++, bits+=3)
1958 XPutPixel( bmpImage, x, h,
1959 X11DRV_PALETTE_ToPhysical(dc, RGB(bits[2], bits[1], bits[0])));
1960 bits = (LPBYTE)(srcbits += linebytes) + left * 3;
1963 break;
1965 default:
1966 notsupported:
1967 FIXME("from 24 bit DIB to %d bit bitmap with mask R,G,B %x,%x,%x\n",
1968 bmpImage->bits_per_pixel, (int)bmpImage->red_mask,
1969 (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
1970 break;
1975 /***********************************************************************
1976 * X11DRV_DIB_GetImageBits_24
1978 * GetDIBits for an 24-bit deep DIB.
1980 static void X11DRV_DIB_GetImageBits_24( int lines, BYTE *dstbits,
1981 DWORD dstwidth, DWORD srcwidth,
1982 PALETTEENTRY *srccolors, XImage *bmpImage )
1984 DWORD x, val;
1985 int h;
1987 /* align to 32 bit */
1988 DWORD linebytes = (dstwidth * 3 + 3) & ~3;
1990 if (lines < 0 )
1992 lines = -lines;
1993 dstbits = dstbits + ( linebytes * (lines-1) );
1994 linebytes = -linebytes;
1997 switch ( bmpImage->depth )
1999 case 24:
2001 if (bmpImage->bits_per_pixel == 24) {
2002 int tocopy = linebytes;
2003 BYTE *srcpixel;
2004 BYTE *ptr = (LPBYTE)dstbits;
2006 if (tocopy < 0 ) tocopy = -tocopy;
2007 srcpixel = bmpImage->data + lines*tocopy;
2008 for(h = lines ; h-- ; ) {
2009 srcpixel-=tocopy;
2010 memcpy(ptr,srcpixel,tocopy);
2011 ptr = (LPBYTE)(dstbits+=linebytes);
2013 break;
2016 case 32:
2018 DWORD *srcpixel, buf;
2019 LPBYTE bits;
2020 DWORD *ptr=(DWORD *)dstbits;
2021 int quotient = dstwidth / 4;
2022 int remainder = dstwidth % 4;
2023 int remk;
2025 /* ==== 24/32 BGR bitmap to 24 BGR dib==== */
2026 if( bmpImage->blue_mask == 0xff && bmpImage->red_mask == 0xff0000 )
2028 for(h = lines - 1; h >= 0; h--)
2030 srcpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line);
2032 for (x = 0; x < quotient; x++) { /* do 4 dwords source, 3 dwords dest at a time */
2033 buf = ((*srcpixel++)&0x00ffffff); /* b1, g1, r1*/
2034 *ptr++ = buf | ((*srcpixel)<<24); /* b2 */
2035 buf = ((*srcpixel++>>8)&0x0000ffff); /* g2, r2 */
2036 *ptr++ = buf | ((*srcpixel)<<16); /* b3, g3 */
2037 buf = ((*srcpixel++>>16)&0x000000ff); /* r3 */
2038 *ptr++ = buf | ((*srcpixel++)<<8); /* b4, g4, r4 */
2040 for ( remk=remainder, bits=(BYTE*)ptr; remk>0; remk--, bits+=3 ) /* do remainder */
2042 buf=*srcpixel++;
2043 *(WORD*)bits = buf; /* b, g */
2044 *(bits+2) = buf>>16; /* r */
2046 ptr = (DWORD*)(dstbits+=linebytes);
2050 /* ==== 24/32 RGB bitmap to 24 BGR dib ==== */
2051 else if( bmpImage->blue_mask == 0xff0000 && bmpImage->red_mask == 0xff )
2053 for(h = lines - 1; h >= 0; h--)
2055 srcpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line);
2057 for (x = 0; x < quotient; x++) { /* do 4 dwords source, 3 dwords dest at a time */
2058 buf = *srcpixel++;
2059 val = ((buf&0xff0000)>>16) | (buf&0xff00) | ((buf&0xff)<<16); /* b1, g1, r1 */
2060 buf = *srcpixel++;
2061 *ptr++ = val | ((buf&0xff0000)<<8); /* b2 */
2062 val = ((buf&0xff00)>>8) | ((buf&0xff)<<8); /* g2, r2 */
2063 buf = *srcpixel++;
2064 *ptr++ = val | (buf&0xff0000) | ((buf&0xff00)<<16); /* b3, g3 */
2065 val = (buf&0xff); /* r3 */
2066 buf = *srcpixel++;
2067 *ptr++ = val | ((buf&0xff0000)>>8) | ((buf&0xff00)<<8) | (buf<<24); /* b4, g4, r4 */
2069 for ( remk=remainder, bits=(BYTE*)ptr; remk>0; remk--, bits+=3 ) /* do remainder */
2071 buf=*srcpixel++;
2072 *(WORD*)bits = (buf&0xff00) | ((buf&0xff0000)>>16) ; /* b, g */
2073 *(bits+2) = buf; /* r */
2075 ptr = (DWORD*)(dstbits+=linebytes);
2078 else goto notsupported;
2080 break;
2082 case 15:
2084 LPWORD srcpixel;
2085 LPBYTE bits = dstbits;
2086 WORD val;
2088 /* ==== 555 BGR bitmap to 24 BGR dib ==== */
2089 if( bmpImage->blue_mask == 0x1f && bmpImage->red_mask == 0x7c00 )
2091 for (h = lines - 1; h >= 0; h--) {
2092 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2093 for (x = 0; x < srcwidth; x++, bits += 3) {
2094 val = *srcpixel++;
2095 bits[2] = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07)); /*Red*/
2096 bits[1] = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07)); /*Green*/
2097 bits[0] = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07)); /*Blue*/
2099 bits = (dstbits += linebytes);
2102 /* ==== 555 RGB bitmap to 24 RGB dib==== */
2103 else if( bmpImage->blue_mask == 0x7c00 && bmpImage->red_mask == 0x1f )
2105 for (h = lines - 1; h >= 0; h--) {
2106 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2107 for (x = 0; x < srcwidth; x++, bits += 3) {
2108 val = *srcpixel++;
2109 bits[0] = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07)); /*Red*/
2110 bits[1] = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07)); /*Green*/
2111 bits[2] = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07)); /*Blue*/
2113 bits = (dstbits += linebytes);
2116 else goto notsupported;
2118 break;
2120 case 16:
2122 LPWORD srcpixel;
2123 LPBYTE bits = dstbits;
2124 WORD val;
2126 /* ==== 565 BGR bitmap to 24 BGR dib ==== */
2127 if( bmpImage->blue_mask == 0x1f && bmpImage->red_mask == 0xf800 )
2129 for (h = lines - 1; h >= 0; h--) {
2130 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2131 for (x = 0; x < srcwidth; x++, bits += 3) {
2132 val = *srcpixel++;
2133 bits[2] = (BYTE)(((val >> 8) & 0xf8) | ((val >> 13) & 0x07)); /*Red*/
2134 bits[1] = (BYTE)(((val >> 3) & 0xfc) | ((val >> 9) & 0x03)); /*Green*/
2135 bits[0] = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07)); /*Blue*/
2137 bits = (dstbits += linebytes);
2140 /* ==== 565 RGB bitmap to 24 BGR dib ==== */
2141 else if( bmpImage->blue_mask == 0xf800 && bmpImage->red_mask == 0x1f )
2143 for (h = lines - 1; h >= 0; h--) {
2144 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2145 for (x = 0; x < srcwidth; x++, bits += 3) {
2146 val = *srcpixel++;
2147 bits[0] = (BYTE)(((val >> 8) & 0xf8) | ((val >> 13) & 0x07)); /*Red*/
2148 bits[1] = (BYTE)(((val >> 3) & 0xfc) | ((val >> 9) & 0x03)); /*Green*/
2149 bits[2] = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07)); /*Blue*/
2151 bits = (dstbits += linebytes);
2154 else goto notsupported;
2156 break;
2158 case 1:
2159 /* ==== monochrome bitmap to 24 BGR dib ==== */
2160 case 4:
2161 /* ==== 4 colormap bitmap to 24 BGR dib ==== */
2162 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
2164 LPBYTE bits = dstbits;
2165 PALETTEENTRY val;
2167 for (h = lines - 1; h >= 0; h--) {
2168 for (x = 0; x < dstwidth; x++) {
2169 val = srccolors[XGetPixel(bmpImage, x, h)];
2170 *bits++ = val.peBlue;
2171 *bits++ = val.peGreen;
2172 *bits++ = val.peRed;
2174 bits = (dstbits += linebytes);
2177 else goto notsupported;
2179 break;
2181 case 8:
2182 /* ==== 8 colormap bitmap to 24 BGR dib ==== */
2183 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask == 0 && srccolors)
2185 BYTE *srcpixel;
2186 LPBYTE bits = dstbits;
2187 PALETTEENTRY val;
2189 for (h = lines - 1; h >= 0; h--) {
2190 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
2191 for (x = 0; x < dstwidth; x++ ) {
2192 val = srccolors[(int)*srcpixel++];
2193 *bits++ = val.peBlue; /*Blue*/
2194 *bits++ = val.peGreen; /*Green*/
2195 *bits++ = val.peRed; /*Red*/
2197 bits = (dstbits += linebytes);
2200 else goto notsupported;
2202 break;
2204 default:
2205 notsupported:
2207 LPBYTE bits = dstbits;
2209 FIXME("from %d bit bitmap with mask R,G,B %x,%x,%x to 24 bit DIB\n",
2210 bmpImage->depth, (int)bmpImage->red_mask,
2211 (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
2212 for (h = lines - 1; h >= 0; h--)
2214 for (x = 0; x < dstwidth; x++, bits += 3)
2216 COLORREF pixel = X11DRV_PALETTE_ToLogical( XGetPixel( bmpImage, x, h ) );
2217 bits[0] = GetBValue(pixel);
2218 bits[1] = GetGValue(pixel);
2219 bits[2] = GetRValue(pixel);
2221 bits = (dstbits += linebytes);
2224 break;
2229 /***********************************************************************
2230 * X11DRV_DIB_SetImageBits_32
2232 * SetDIBits for a 32-bit deep DIB.
2234 static void X11DRV_DIB_SetImageBits_32( int lines, const BYTE *srcbits,
2235 DWORD srcwidth, DWORD dstwidth, int left,
2236 DC *dc, XImage *bmpImage )
2238 DWORD x, *ptr;
2239 int h;
2241 DWORD linebytes = (srcwidth * 4);
2243 if (lines < 0 )
2245 lines = -lines;
2246 srcbits = srcbits + ( linebytes * (lines-1) );
2247 linebytes = -linebytes;
2250 ptr = (DWORD *) srcbits + left;
2252 switch ( bmpImage->depth )
2254 case 32:
2255 /* ==== 32 BGR dib to 24/32 BGR bitmap ==== */
2256 if (bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff) {
2257 for (h = lines - 1; h >= 0; h--, srcbits+=linebytes) {
2258 memcpy( bmpImage->data + h * bmpImage->bytes_per_line, srcbits + left*4, dstwidth*4 );
2262 /* ==== 32 BGR dib to 24/32 RGB bitmap ==== */
2263 else if (bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000)
2265 DWORD *dstpixel;
2267 for (h = lines - 1; h >= 0; h--) {
2268 dstpixel = (DWORD *) (bmpImage->data + h * bmpImage->bytes_per_line);
2269 for (x = 0; x < dstwidth; x++, ptr++) {
2270 *dstpixel++ = ((*ptr << 16) & 0xff0000) | (*ptr & 0xff00) | ((*ptr >> 16) & 0xff);
2272 ptr = (DWORD *) (srcbits += linebytes) + left;
2275 else goto notsupported;
2277 break;
2279 case 24:
2280 /* ==== 32 BGR dib to 24 (888) BGR bitmap ==== */
2281 /* we need to check that source mask matches destination */
2283 BYTE *bptr;
2285 ptr = (DWORD *) srcbits + left;
2286 bptr = bmpImage->data;
2288 for (h = lines - 1; h >= 0; h--) {
2289 for (x = 0; x < dstwidth; x++) {
2290 /* *ptr is a 32bit value */
2291 /* bptr points to first of 3 bytes */
2292 *bptr++ = (*ptr >> 16) & 0xff;
2293 *bptr++ = (*ptr >> 8) & 0xff;
2294 *bptr++ = (*ptr ) & 0xff;
2295 ptr++;
2297 ptr = (DWORD *) (srcbits += linebytes) + left;
2300 break;
2302 case 15:
2303 /* ==== 32 BGR dib to 555 BGR bitmap ==== */
2304 if (bmpImage->red_mask == 0x7c00 && bmpImage->blue_mask == 0x001f) {
2305 LPWORD dstpixel;
2307 for (h = lines - 1; h >= 0; h--) {
2308 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2309 for (x = 0; x < dstwidth; x++, ptr++) {
2310 *dstpixel++ = (WORD) (((*ptr >> 9) & 0x7c00) | ((*ptr >> 6) & 0x03e0) | ((*ptr >> 3) & 0x001f));
2312 ptr = (DWORD *) (srcbits += linebytes) + left;
2315 /* ==== 32 BGR dib to 555 RGB bitmap ==== */
2316 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0x7c00)
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 << 7) & 0x7c00) | ((*ptr >> 6) & 0x03e0) | ((*ptr >> 19) & 0x001f));
2325 ptr = (DWORD *) (srcbits += linebytes) + left;
2328 else goto notsupported;
2330 break;
2332 case 16:
2333 /* ==== 32 BGR dib to 565 BGR bitmap ==== */
2334 if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f)
2336 LPWORD dstpixel;
2338 for (h = lines - 1; h >= 0; h--) {
2339 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2340 for (x = 0; x < dstwidth; x++, ptr++) {
2341 *dstpixel++ = (WORD) (((*ptr >> 8) & 0xf800) | ((*ptr >> 5) & 0x07e0) | ((*ptr >> 3) & 0x001f));
2343 ptr = (DWORD *) (srcbits += linebytes) + left;
2346 /* ==== 32 BGR dib to 565 RGB bitmap ==== */
2347 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0xf800)
2349 LPWORD dstpixel;
2351 for (h = lines - 1; h >= 0; h--) {
2352 dstpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2353 for (x = 0; x < dstwidth; x++, ptr++) {
2354 *dstpixel++ = (WORD) (((*ptr << 8) & 0xf800) | ((*ptr >> 5) & 0x07e0) | ((*ptr >> 19) & 0x001f));
2356 ptr = (DWORD *) (srcbits += linebytes) + left;
2359 else goto notsupported;
2361 break;
2363 case 1:
2364 case 4:
2365 case 8:
2367 LPBYTE bits = (LPBYTE)srcbits + left*4;
2369 for (h = lines - 1; h >= 0; h--) {
2370 for (x = left; x < dstwidth+left; x++, bits += 4)
2371 XPutPixel( bmpImage, x, h,
2372 X11DRV_PALETTE_ToPhysical(dc, RGB( bits[2], bits[1], *bits )));
2373 bits = (LPBYTE)(srcbits += linebytes) + left * 4;
2376 break;
2378 default:
2379 notsupported:
2380 FIXME("32 bit DIB %d bit bitmap\n", bmpImage->bits_per_pixel);
2381 break;
2386 /***********************************************************************
2387 * X11DRV_DIB_GetImageBits_32
2389 * GetDIBits for an 32-bit deep DIB.
2391 static void X11DRV_DIB_GetImageBits_32( int lines, BYTE *dstbits,
2392 DWORD dstwidth, DWORD srcwidth,
2393 PALETTEENTRY *srccolors, XImage *bmpImage )
2395 DWORD x;
2396 int h;
2397 BYTE *bits;
2399 /* align to 32 bit */
2400 DWORD linebytes = (srcwidth * 4);
2401 DWORD copybytes = linebytes;
2403 if (lines < 0 )
2405 lines = -lines;
2406 dstbits = dstbits + ( linebytes * (lines-1) );
2407 linebytes = -linebytes;
2410 bits = dstbits;
2412 switch ( bmpImage->depth )
2414 case 32:
2415 /* ==== 24/32 BGR bitmap to 32 BGR dib ==== */
2416 if ( bmpImage->red_mask == 0xff0000 && bmpImage->blue_mask == 0xff )
2417 for (h = lines - 1; h >= 0; h--, dstbits+=linebytes)
2418 memcpy( dstbits, bmpImage->data + h*bmpImage->bytes_per_line, copybytes );
2420 /* ==== 24/32 RGB bitmap to 32 BGR dib ==== */
2421 else if ( bmpImage->red_mask == 0xff && bmpImage->blue_mask == 0xff0000 )
2423 LPBYTE srcbits;
2425 for (h = lines - 1; h >= 0; h--) {
2426 srcbits = bmpImage->data + h * bmpImage->bytes_per_line;
2427 for (x = 0; x < dstwidth; x++, bits+=4, srcbits+=2) {
2428 *(bits + 2) = *srcbits++;
2429 *(bits + 1) = *srcbits++;
2430 *bits = *srcbits;
2432 bits = (dstbits += linebytes);
2435 else goto notsupported;
2436 break;
2438 case 24:
2439 /* ==== 24 BGR bitmap to 32 (0888) BGR dib ==== */
2440 /* we need to check that source mask matches destination */
2442 DWORD *srcpixel;
2443 BYTE *bptr;
2444 DWORD srcdata;
2446 srcpixel = (DWORD *) dstbits;
2447 bptr = bmpImage->data;
2449 for (h = lines - 1; h >= 0; h--) {
2450 for (x = 0; x < dstwidth; x++) {
2451 /* *srcpixel is a 32bit value */
2452 /* bptr points to first of 3 bytes */
2453 srcdata = 0;
2454 srcdata = srcdata << 8 | *bptr++;
2455 srcdata = srcdata << 8 | *bptr++;
2456 srcdata = srcdata << 8 | *bptr++;
2458 *srcpixel++ = srcdata;
2460 srcpixel = (DWORD *) (dstbits += linebytes);
2463 break;
2465 case 15:
2467 LPWORD srcpixel;
2468 WORD val;
2470 /* ==== 555 BGR bitmap to 32 BGR dib ==== */
2471 if (bmpImage->red_mask == 0x7c00 && bmpImage->blue_mask == 0x001f)
2473 for (h = lines - 1; h >= 0; h--) {
2474 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2475 for (x = 0; x < dstwidth; x++, bits+=2) {
2476 val = *srcpixel++;
2477 *bits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x03)); /*Blue*/
2478 *bits++ = (BYTE)(((val >> 2) & 0xfc) | ((val >> 8) & 0x03)); /*Green*/
2479 *bits = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07)); /*Red*/
2481 bits = (dstbits += linebytes);
2484 /* ==== 555 RGB bitmap to 32 BGR dib ==== */
2485 else if (bmpImage->red_mask == 0x001f && bmpImage->blue_mask == 0x7c00)
2487 for (h = lines - 1; h >= 0; h--) {
2488 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2489 for (x = 0; x < dstwidth; x++, bits+=2) {
2490 val = *srcpixel++;
2491 *bits++ = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07));/*Blue*/
2492 *bits++ = (BYTE)(((val >> 2) & 0xfc) | ((val >> 8) & 0x03)); /*Green*/
2493 *bits = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x03)); /*Red*/
2495 bits = (dstbits += linebytes);
2498 else goto notsupported;
2500 break;
2502 case 16:
2504 LPWORD srcpixel;
2505 WORD val;
2507 /* ==== 565 BGR bitmap to 32 BGR dib ==== */
2508 if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f)
2510 for (h = lines - 1; h >= 0; h--) {
2511 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2512 for (x = 0; x < srcwidth; x++, bits+=2) {
2513 val = *srcpixel++;
2514 *bits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x03)); /*Blue*/
2515 *bits++ = (BYTE)(((val >> 3) & 0xfc) | ((val >> 9) & 0x03)); /*Green*/
2516 *bits = (BYTE)(((val >> 8) & 0xf8) | ((val >> 13) & 0x07)); /*Red*/
2518 bits = (dstbits += linebytes);
2521 /* ==== 565 RGB bitmap to 32 BGR dib ==== */
2522 else if (bmpImage->red_mask == 0xf800 && bmpImage->blue_mask == 0x001f)
2524 for (h = lines - 1; h >= 0; h--) {
2525 srcpixel = (LPWORD) (bmpImage->data + h * bmpImage->bytes_per_line);
2526 for (x = 0; x < srcwidth; x++, bits+=2) {
2527 val = *srcpixel++;
2528 *bits++ = (BYTE)(((val >> 8) & 0xf8) | ((val >> 13) & 0x07));/*Blue*/
2529 *bits++ = (BYTE)(((val >> 3) & 0xfc) | ((val >> 9) & 0x03)); /*Green*/
2530 *bits = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x03)); /*Red*/
2532 bits = (dstbits += linebytes);
2535 else goto notsupported;
2537 break;
2539 case 1:
2540 /* ==== monochrome bitmap to 32 BGR dib ==== */
2541 case 4:
2542 /* ==== 4 colormap bitmap to 32 BGR dib ==== */
2543 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
2545 PALETTEENTRY val;
2547 for (h = lines - 1; h >= 0; h--) {
2548 for (x = 0; x < dstwidth; x++) {
2549 val = srccolors[XGetPixel(bmpImage, x, h)];
2550 *bits++ = val.peBlue;
2551 *bits++ = val.peGreen;
2552 *bits++ = val.peRed;
2553 *bits++ = 0;
2555 bits = (dstbits += linebytes);
2558 else goto notsupported;
2560 break;
2562 case 8:
2563 /* ==== 8 colormap bitmap to 32 BGR dib ==== */
2564 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors)
2566 BYTE *srcpixel;
2567 PALETTEENTRY val;
2569 for (h = lines - 1; h >= 0; h--) {
2570 srcpixel = bmpImage->data + h*bmpImage->bytes_per_line;
2571 for (x = 0; x < dstwidth; x++) {
2572 val = srccolors[(int)*srcpixel++];
2573 *bits++ = val.peBlue; /*Blue*/
2574 *bits++ = val.peGreen; /*Green*/
2575 *bits++ = val.peRed; /*Red*/
2576 *bits++ = 0;
2578 bits = (dstbits += linebytes);
2581 else goto notsupported;
2582 break;
2584 default:
2585 notsupported:
2586 FIXME("from %d bit bitmap with mask R,G,B %x,%x,%x to 32 bit DIB\n",
2587 bmpImage->depth, (int)bmpImage->red_mask,
2588 (int)bmpImage->green_mask, (int)bmpImage->blue_mask );
2589 for (h = lines - 1; h >= 0; h--)
2591 for (x = 0; x < dstwidth; x++, bits += 4)
2593 COLORREF pixel = X11DRV_PALETTE_ToLogical( XGetPixel( bmpImage, x, h ) );
2594 bits[0] = GetBValue(pixel);
2595 bits[1] = GetGValue(pixel);
2596 bits[2] = GetRValue(pixel);
2598 bits = (dstbits += linebytes);
2600 break;
2604 /***********************************************************************
2605 * X11DRV_DIB_SetImageBits
2607 * Transfer the bits to an X image.
2608 * Helper function for SetDIBits() and SetDIBitsToDevice().
2609 * The Xlib critical section must be entered before calling this function.
2611 int X11DRV_DIB_SetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
2613 int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
2614 XImage *bmpImage;
2616 if (descr->image)
2617 bmpImage = descr->image;
2618 else {
2619 bmpImage = XCreateImage( display, X11DRV_GetVisual(), descr->depth, ZPixmap, 0, NULL,
2620 descr->infoWidth, lines, 32, 0 );
2621 bmpImage->data = calloc( lines, bmpImage->bytes_per_line );
2622 if(bmpImage->data == NULL) {
2623 ERR("Out of memory!\n");
2624 XDestroyImage( bmpImage );
2625 return lines;
2629 /* Transfer the pixels */
2630 switch(descr->infoBpp)
2632 case 1:
2633 X11DRV_DIB_SetImageBits_1( descr->lines, descr->bits, descr->infoWidth,
2634 descr->width, descr->xSrc, (int *)(descr->colorMap),
2635 bmpImage );
2636 break;
2637 case 4:
2638 if (descr->compression) {
2639 XGetSubImage( display, descr->drawable, descr->xDest, descr->yDest,
2640 descr->width, descr->height, AllPlanes, ZPixmap,
2641 bmpImage, descr->xSrc, descr->ySrc );
2643 X11DRV_DIB_SetImageBits_RLE4( descr->lines, descr->bits,
2644 descr->infoWidth, descr->width,
2645 descr->xSrc, (int *)(descr->colorMap),
2646 bmpImage );
2647 } else
2648 X11DRV_DIB_SetImageBits_4( descr->lines, descr->bits,
2649 descr->infoWidth, descr->width,
2650 descr->xSrc, (int*)(descr->colorMap),
2651 bmpImage );
2652 break;
2653 case 8:
2654 if (descr->compression) {
2655 XGetSubImage( display, descr->drawable, descr->xDest, descr->yDest,
2656 descr->width, descr->height, AllPlanes, ZPixmap,
2657 bmpImage, descr->xSrc, descr->ySrc );
2658 X11DRV_DIB_SetImageBits_RLE8( descr->lines, descr->bits,
2659 descr->infoWidth, descr->width,
2660 descr->xSrc, (int *)(descr->colorMap),
2661 bmpImage );
2662 } else
2663 X11DRV_DIB_SetImageBits_8( descr->lines, descr->bits,
2664 descr->infoWidth, descr->width,
2665 descr->xSrc, (int *)(descr->colorMap),
2666 bmpImage );
2667 break;
2668 case 15:
2669 case 16:
2670 X11DRV_DIB_SetImageBits_16( descr->lines, descr->bits,
2671 descr->infoWidth, descr->width,
2672 descr->xSrc, descr->dc,
2673 descr->rMask, descr->gMask, descr->bMask,
2674 bmpImage);
2675 break;
2676 case 24:
2677 X11DRV_DIB_SetImageBits_24( descr->lines, descr->bits,
2678 descr->infoWidth, descr->width,
2679 descr->xSrc, descr->dc, bmpImage );
2680 break;
2681 case 32:
2682 X11DRV_DIB_SetImageBits_32( descr->lines, descr->bits,
2683 descr->infoWidth, descr->width,
2684 descr->xSrc, descr->dc,
2685 bmpImage);
2686 break;
2687 default:
2688 WARN("(%d): Invalid depth\n", descr->infoBpp );
2689 break;
2692 if (descr->useShm)
2694 XShmPutImage( display, descr->drawable, descr->gc, bmpImage,
2695 descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
2696 descr->width, descr->height, FALSE );
2697 XSync( display, 0 );
2699 else
2700 XPutImage( display, descr->drawable, descr->gc, bmpImage,
2701 descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
2702 descr->width, descr->height );
2704 if (!descr->image) XDestroyImage( bmpImage );
2705 return lines;
2708 /***********************************************************************
2709 * X11DRV_DIB_GetImageBits
2711 * Transfer the bits from an X image.
2712 * The Xlib critical section must be entered before calling this function.
2714 int X11DRV_DIB_GetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
2716 int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
2717 XImage *bmpImage;
2719 if (descr->image)
2720 bmpImage = descr->image;
2721 else {
2722 bmpImage = XCreateImage( display, X11DRV_GetVisual(), descr->depth, ZPixmap, 0, NULL,
2723 descr->infoWidth, lines, 32, 0 );
2724 bmpImage->data = calloc( lines, bmpImage->bytes_per_line );
2725 if(bmpImage->data == NULL) {
2726 ERR("Out of memory!\n");
2727 XDestroyImage( bmpImage );
2728 return lines;
2731 XGetSubImage( display, descr->drawable, descr->xSrc, descr->ySrc,
2732 descr->width, lines, AllPlanes, ZPixmap,
2733 bmpImage, descr->xDest, descr->yDest );
2735 /* Transfer the pixels */
2736 switch(descr->infoBpp)
2738 case 1:
2739 X11DRV_DIB_GetImageBits_1( descr->lines,(LPVOID)descr->bits,
2740 descr->infoWidth, descr->width,
2741 descr->colorMap, descr->palentry,
2742 bmpImage );
2743 break;
2745 case 4:
2746 if (descr->compression)
2747 FIXME("Compression not yet supported!\n");
2748 else
2749 X11DRV_DIB_GetImageBits_4( descr->lines,(LPVOID)descr->bits,
2750 descr->infoWidth, descr->width,
2751 descr->colorMap, descr->palentry,
2752 bmpImage );
2753 break;
2755 case 8:
2756 if (descr->compression)
2757 FIXME("Compression not yet supported!\n");
2758 else
2759 X11DRV_DIB_GetImageBits_8( descr->lines, (LPVOID)descr->bits,
2760 descr->infoWidth, descr->width,
2761 descr->colorMap, descr->palentry,
2762 bmpImage );
2763 break;
2764 case 15:
2765 case 16:
2766 X11DRV_DIB_GetImageBits_16( descr->lines, (LPVOID)descr->bits,
2767 descr->infoWidth,descr->width,
2768 descr->palentry, bmpImage );
2769 break;
2771 case 24:
2772 X11DRV_DIB_GetImageBits_24( descr->lines, (LPVOID)descr->bits,
2773 descr->infoWidth,descr->width,
2774 descr->palentry, bmpImage );
2775 break;
2777 case 32:
2778 X11DRV_DIB_GetImageBits_32( descr->lines, (LPVOID)descr->bits,
2779 descr->infoWidth, descr->width,
2780 descr->palentry, bmpImage );
2781 break;
2783 default:
2784 WARN("(%d): Invalid depth\n", descr->infoBpp );
2785 break;
2788 if (!descr->image) XDestroyImage( bmpImage );
2789 return lines;
2792 /*************************************************************************
2793 * X11DRV_SetDIBitsToDevice
2796 INT X11DRV_SetDIBitsToDevice( DC *dc, INT xDest, INT yDest, DWORD cx,
2797 DWORD cy, INT xSrc, INT ySrc,
2798 UINT startscan, UINT lines, LPCVOID bits,
2799 const BITMAPINFO *info, UINT coloruse )
2801 X11DRV_DIB_IMAGEBITS_DESCR descr;
2802 DWORD width, oldcy = cy;
2803 INT result;
2804 int height, tmpheight;
2805 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
2808 if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height,
2809 &descr.infoBpp, &descr.compression ) == -1)
2810 return 0;
2811 tmpheight = height;
2812 if (height < 0) height = -height;
2813 if (!lines || (startscan >= height)) return 0;
2814 if (startscan + lines > height) lines = height - startscan;
2815 if (ySrc < startscan) ySrc = startscan;
2816 else if (ySrc >= startscan + lines) return 0;
2817 if (xSrc >= width) return 0;
2818 if (ySrc + cy >= startscan + lines) cy = startscan + lines - ySrc;
2819 if (xSrc + cx >= width) cx = width - xSrc;
2820 if (!cx || !cy) return 0;
2822 X11DRV_SetupGCForText( dc ); /* To have the correct colors */
2823 TSXSetFunction(display, physDev->gc, X11DRV_XROPfunction[dc->ROPmode-1]);
2825 switch (descr.infoBpp)
2827 case 1:
2828 case 4:
2829 case 8:
2830 descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap(
2831 coloruse == DIB_PAL_COLORS ? dc : NULL, coloruse,
2832 dc->bitsPerPixel, info, &descr.nColorMap );
2833 if (!descr.colorMap) return 0;
2834 descr.rMask = descr.gMask = descr.bMask = 0;
2835 break;
2836 case 15:
2837 case 16:
2838 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
2839 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x03e0;
2840 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x001f;
2841 descr.colorMap = 0;
2842 break;
2844 case 24:
2845 descr.rMask = descr.gMask = descr.bMask = 0;
2846 descr.colorMap = 0;
2847 break;
2849 case 32:
2850 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
2851 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0xff00;
2852 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0xff;
2853 descr.colorMap = 0;
2854 break;
2857 descr.dc = dc;
2858 descr.bits = bits;
2859 descr.image = NULL;
2860 descr.palentry = NULL;
2861 descr.lines = tmpheight >= 0 ? lines : -lines;
2862 descr.infoWidth = width;
2863 descr.depth = dc->bitsPerPixel;
2864 descr.drawable = physDev->drawable;
2865 descr.gc = physDev->gc;
2866 descr.xSrc = xSrc;
2867 descr.ySrc = tmpheight >= 0 ? lines-(ySrc-startscan)-cy+(oldcy-cy)
2868 : ySrc - startscan;
2869 descr.xDest = dc->DCOrgX + XLPTODP( dc, xDest );
2870 descr.yDest = dc->DCOrgY + YLPTODP( dc, yDest ) +
2871 (tmpheight >= 0 ? oldcy-cy : 0);
2872 descr.width = cx;
2873 descr.height = cy;
2874 descr.useShm = FALSE;
2876 EnterCriticalSection( &X11DRV_CritSection );
2877 result = CALL_LARGE_STACK( X11DRV_DIB_SetImageBits, &descr );
2878 LeaveCriticalSection( &X11DRV_CritSection );
2880 if (descr.infoBpp <= 8)
2881 HeapFree(GetProcessHeap(), 0, descr.colorMap);
2882 return result;
2885 /***********************************************************************
2886 * X11DRV_DIB_SetDIBits
2888 INT X11DRV_DIB_SetDIBits(
2889 BITMAPOBJ *bmp, DC *dc, UINT startscan,
2890 UINT lines, LPCVOID bits, const BITMAPINFO *info,
2891 UINT coloruse, HBITMAP hbitmap)
2893 X11DRV_DIB_IMAGEBITS_DESCR descr;
2894 int height, tmpheight;
2895 INT result;
2897 descr.dc = dc;
2899 if (DIB_GetBitmapInfo( &info->bmiHeader, &descr.infoWidth, &height,
2900 &descr.infoBpp, &descr.compression ) == -1)
2901 return 0;
2903 tmpheight = height;
2904 if (height < 0) height = -height;
2905 if (!lines || (startscan >= height))
2906 return 0;
2908 if (startscan + lines > height) lines = height - startscan;
2910 switch (descr.infoBpp)
2912 case 1:
2913 case 4:
2914 case 8:
2915 descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap(
2916 coloruse == DIB_PAL_COLORS ? descr.dc : NULL, coloruse,
2917 bmp->bitmap.bmBitsPixel,
2918 info, &descr.nColorMap );
2919 if (!descr.colorMap) return 0;
2920 descr.rMask = descr.gMask = descr.bMask = 0;
2921 break;
2922 case 15:
2923 case 16:
2924 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
2925 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x03e0;
2926 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x001f;
2927 descr.colorMap = 0;
2928 break;
2930 case 24:
2931 descr.rMask = descr.gMask = descr.bMask = 0;
2932 descr.colorMap = 0;
2933 break;
2935 case 32:
2936 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
2937 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0xff00;
2938 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0xff;
2939 descr.colorMap = 0;
2940 break;
2942 default: break;
2945 /* HACK for now */
2946 if(!bmp->physBitmap)
2947 X11DRV_CreateBitmap(hbitmap);
2949 descr.bits = bits;
2950 descr.image = NULL;
2951 descr.palentry = NULL;
2952 descr.lines = tmpheight >= 0 ? lines : -lines;
2953 descr.depth = bmp->bitmap.bmBitsPixel;
2954 descr.drawable = (Pixmap)bmp->physBitmap;
2955 descr.gc = BITMAP_GC(bmp);
2956 descr.xSrc = 0;
2957 descr.ySrc = 0;
2958 descr.xDest = 0;
2959 descr.yDest = height - startscan - lines;
2960 descr.width = bmp->bitmap.bmWidth;
2961 descr.height = lines;
2962 descr.useShm = FALSE;
2964 EnterCriticalSection( &X11DRV_CritSection );
2965 result = CALL_LARGE_STACK( X11DRV_DIB_SetImageBits, &descr );
2966 LeaveCriticalSection( &X11DRV_CritSection );
2968 if (descr.colorMap) HeapFree(GetProcessHeap(), 0, descr.colorMap);
2970 return result;
2973 /***********************************************************************
2974 * X11DRV_DIB_GetDIBits
2976 INT X11DRV_DIB_GetDIBits(
2977 BITMAPOBJ *bmp, DC *dc, UINT startscan,
2978 UINT lines, LPVOID bits, BITMAPINFO *info,
2979 UINT coloruse, HBITMAP hbitmap)
2981 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
2982 X11DRV_DIB_IMAGEBITS_DESCR descr;
2983 PALETTEOBJ * palette;
2985 TRACE("%u scanlines of (%i,%i) -> (%i,%i) starting from %u\n",
2986 lines, bmp->bitmap.bmWidth, bmp->bitmap.bmHeight,
2987 (int)info->bmiHeader.biWidth, (int)info->bmiHeader.biHeight,
2988 startscan );
2990 if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->hPalette, PALETTE_MAGIC )))
2991 return 0;
2993 if( lines > info->bmiHeader.biHeight ) lines = info->bmiHeader.biHeight;
2994 /* Top-down images have a negative biHeight, the scanlines of theses images
2995 * were inverted in X11DRV_DIB_GetImageBits_xx
2996 * To prevent this we simply change the sign of lines
2997 * (the number of scan lines to copy).
2998 * Negative lines are correctly handled by X11DRV_DIB_GetImageBits_xx.
3000 if( info->bmiHeader.biHeight < 0 && lines > 0) lines = -lines;
3002 if( startscan >= bmp->bitmap.bmHeight )
3004 lines = 0;
3005 goto done;
3008 if (DIB_GetBitmapInfo( &info->bmiHeader, &descr.infoWidth, &descr.lines,
3009 &descr.infoBpp, &descr.compression ) == -1)
3011 lines = 0;
3012 goto done;
3015 switch (descr.infoBpp)
3017 case 1:
3018 case 4:
3019 case 8:
3020 case 24:
3021 descr.rMask = descr.gMask = descr.bMask = 0;
3022 break;
3023 case 15:
3024 case 16:
3025 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
3026 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x03e0;
3027 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x001f;
3028 break;
3030 case 32:
3031 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
3032 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0xff00;
3033 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0xff;
3034 break;
3037 /* Hack for now */
3038 if(!bmp->physBitmap)
3039 X11DRV_CreateBitmap(hbitmap);
3042 descr.dc = dc;
3043 descr.palentry = palette->logpalette.palPalEntry;
3044 descr.bits = bits;
3045 descr.image = NULL;
3046 descr.lines = lines;
3047 descr.depth = bmp->bitmap.bmBitsPixel;
3048 descr.drawable = (Pixmap)bmp->physBitmap;
3049 descr.gc = BITMAP_GC(bmp);
3050 descr.width = bmp->bitmap.bmWidth;
3051 descr.height = bmp->bitmap.bmHeight;
3052 descr.colorMap = info->bmiColors;
3053 descr.xDest = 0;
3054 descr.yDest = 0;
3055 descr.xSrc = 0;
3057 if (descr.lines > 0)
3059 descr.ySrc = (descr.height-1) - (startscan + (lines-1));
3061 else
3063 descr.ySrc = startscan;
3066 if (dib)
3067 descr.useShm = (dib->shminfo.shmid != -1);
3068 else
3069 descr.useShm = FALSE;
3071 EnterCriticalSection( &X11DRV_CritSection );
3073 CALL_LARGE_STACK( X11DRV_DIB_GetImageBits, &descr );
3075 LeaveCriticalSection( &X11DRV_CritSection );
3077 if(info->bmiHeader.biSizeImage == 0) /* Fill in biSizeImage */
3078 info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(
3079 info->bmiHeader.biWidth,
3080 info->bmiHeader.biHeight,
3081 info->bmiHeader.biBitCount );
3083 info->bmiHeader.biCompression = 0;
3085 done:
3086 GDI_ReleaseObj( dc->hPalette );
3088 return lines;
3091 /***********************************************************************
3092 * DIB_DoProtectDIBSection
3094 static void X11DRV_DIB_DoProtectDIBSection( BITMAPOBJ *bmp, DWORD new_prot )
3096 DIBSECTION *dib = bmp->dib;
3097 INT effHeight = dib->dsBm.bmHeight >= 0? dib->dsBm.bmHeight
3098 : -dib->dsBm.bmHeight;
3099 /* use the biSizeImage data as the memory size only if we're dealing with a
3100 compressed image where the value is set. Otherwise, calculate based on
3101 width * height */
3102 INT totalSize = dib->dsBmih.biSizeImage && dib->dsBmih.biCompression != BI_RGB
3103 ? dib->dsBmih.biSizeImage
3104 : dib->dsBm.bmWidthBytes * effHeight;
3105 DWORD old_prot;
3107 VirtualProtect(dib->dsBm.bmBits, totalSize, new_prot, &old_prot);
3108 TRACE("Changed protection from %ld to %ld\n", old_prot, new_prot);
3111 /***********************************************************************
3112 * X11DRV_DIB_DoUpdateDIBSection
3114 static void X11DRV_DIB_DoUpdateDIBSection(BITMAPOBJ *bmp, BOOL toDIB)
3116 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
3117 X11DRV_DIB_IMAGEBITS_DESCR descr;
3119 if (DIB_GetBitmapInfo( &dib->dibSection.dsBmih, &descr.infoWidth, &descr.lines,
3120 &descr.infoBpp, &descr.compression ) == -1)
3121 return;
3123 descr.dc = NULL;
3124 descr.palentry = NULL;
3125 descr.image = dib->image;
3126 descr.colorMap = (RGBQUAD *)dib->colorMap;
3127 descr.nColorMap = dib->nColorMap;
3128 descr.bits = dib->dibSection.dsBm.bmBits;
3129 descr.depth = bmp->bitmap.bmBitsPixel;
3131 switch (descr.infoBpp)
3133 case 1:
3134 case 4:
3135 case 8:
3136 case 24:
3137 descr.rMask = descr.gMask = descr.bMask = 0;
3138 break;
3139 case 15:
3140 case 16:
3141 descr.rMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[0] : 0x7c00;
3142 descr.gMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[1] : 0x03e0;
3143 descr.bMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[2] : 0x001f;
3144 break;
3146 case 32:
3147 descr.rMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[0] : 0xff;
3148 descr.gMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[1] : 0xff00;
3149 descr.bMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[2] : 0xff0000;
3150 break;
3153 /* Hack for now */
3154 descr.drawable = (Pixmap)bmp->physBitmap;
3155 descr.gc = BITMAP_GC(bmp);
3156 descr.xSrc = 0;
3157 descr.ySrc = 0;
3158 descr.xDest = 0;
3159 descr.yDest = 0;
3160 descr.width = bmp->bitmap.bmWidth;
3161 descr.height = bmp->bitmap.bmHeight;
3162 descr.useShm = (dib->shminfo.shmid != -1);
3164 if (toDIB)
3166 TRACE("Copying from Pixmap to DIB bits\n");
3167 EnterCriticalSection( &X11DRV_CritSection );
3168 CALL_LARGE_STACK( X11DRV_DIB_GetImageBits, &descr );
3169 LeaveCriticalSection( &X11DRV_CritSection );
3171 else
3173 TRACE("Copying from DIB bits to Pixmap\n");
3174 EnterCriticalSection( &X11DRV_CritSection );
3175 CALL_LARGE_STACK( X11DRV_DIB_SetImageBits, &descr );
3176 LeaveCriticalSection( &X11DRV_CritSection );
3180 /***********************************************************************
3181 * X11DRV_DIB_FaultHandler
3183 static BOOL X11DRV_DIB_FaultHandler( LPVOID res, LPCVOID addr )
3185 BOOL handled = FALSE;
3186 BITMAPOBJ *bmp;
3188 bmp = (BITMAPOBJ *)GDI_GetObjPtr( (HBITMAP)res, BITMAP_MAGIC );
3189 if (!bmp) return FALSE;
3191 if (bmp->dib)
3192 switch (((X11DRV_DIBSECTION *) bmp->dib)->status)
3194 case X11DRV_DIB_GdiMod:
3195 TRACE("called in status DIB_GdiMod\n" );
3196 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
3197 X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
3198 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
3199 ((X11DRV_DIBSECTION *) bmp->dib)->status = X11DRV_DIB_InSync;
3200 handled = TRUE;
3201 break;
3203 case X11DRV_DIB_InSync:
3204 TRACE("called in status X11DRV_DIB_InSync\n" );
3205 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
3206 ((X11DRV_DIBSECTION *) bmp->dib)->status = X11DRV_DIB_AppMod;
3207 handled = TRUE;
3208 break;
3210 case X11DRV_DIB_AppMod:
3211 FIXME("called in status X11DRV_DIB_AppMod: this can't happen!\n" );
3212 break;
3214 case X11DRV_DIB_NoHandler:
3215 FIXME("called in status DIB_NoHandler: this can't happen!\n" );
3216 break;
3219 GDI_ReleaseObj( (HBITMAP)res );
3220 return handled;
3223 /***********************************************************************
3224 * X11DRV_DIB_CmnUpdateDIBSection
3226 static void X11DRV_DIB_CmnUpdateDIBSection(BITMAPOBJ *bmp, BOOL toDIB)
3228 if (!bmp) return;
3229 if (!bmp->dib) return;
3231 if (!toDIB)
3233 /* Prepare for access to the DIB by GDI functions */
3235 switch (((X11DRV_DIBSECTION *) bmp->dib)->status)
3237 default:
3238 case X11DRV_DIB_NoHandler:
3239 X11DRV_DIB_DoUpdateDIBSection( bmp, FALSE );
3240 break;
3242 case X11DRV_DIB_GdiMod:
3243 TRACE("fromDIB called in status X11DRV_DIB_GdiMod\n" );
3244 /* nothing to do */
3245 break;
3247 case X11DRV_DIB_InSync:
3248 TRACE("fromDIB called in status X11DRV_DIB_InSync\n" );
3249 /* nothing to do */
3250 break;
3252 case X11DRV_DIB_AppMod:
3253 TRACE("fromDIB called in status X11DRV_DIB_AppMod\n" );
3254 X11DRV_DIB_DoUpdateDIBSection( bmp, FALSE );
3255 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
3256 ((X11DRV_DIBSECTION *) bmp->dib)->status = X11DRV_DIB_InSync;
3257 break;
3260 else
3262 /* Acknowledge write access to the DIB by GDI functions */
3264 switch (((X11DRV_DIBSECTION *) bmp->dib)->status)
3266 default:
3267 case X11DRV_DIB_NoHandler:
3268 X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
3269 break;
3271 case X11DRV_DIB_GdiMod:
3272 TRACE(" toDIB called in status X11DRV_DIB_GdiMod\n" );
3273 /* nothing to do */
3274 break;
3276 case X11DRV_DIB_InSync:
3277 TRACE(" toDIB called in status X11DRV_DIB_InSync\n" );
3278 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
3279 ((X11DRV_DIBSECTION *) bmp->dib)->status = X11DRV_DIB_GdiMod;
3280 break;
3282 case X11DRV_DIB_AppMod:
3283 FIXME(" toDIB called in status X11DRV_DIB_AppMod: "
3284 "this can't happen!\n" );
3285 break;
3290 /***********************************************************************
3291 * X11DRV_DIB_UpdateDIBSection2
3293 void X11DRV_DIB_UpdateDIBSection2(HBITMAP hbmp, BOOL toDIB)
3295 BITMAPOBJ *bmp;
3297 bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbmp, BITMAP_MAGIC );
3298 if (!bmp) return;
3300 X11DRV_DIB_CmnUpdateDIBSection(bmp, toDIB);
3302 GDI_ReleaseObj(hbmp);
3305 /***********************************************************************
3306 * X11DRV_DIB_UpdateDIBSection
3308 void X11DRV_DIB_UpdateDIBSection(DC *dc, BOOL toDIB)
3310 /* Ensure this is a Compatible DC that has a DIB section selected */
3312 if (!dc) return;
3313 if (!(dc->flags & DC_MEMORY)) return;
3315 X11DRV_DIB_UpdateDIBSection2(dc->hBitmap, toDIB);
3318 /***********************************************************************
3319 * X11DRV_DIB_CreateDIBSection16
3321 HBITMAP16 X11DRV_DIB_CreateDIBSection16(
3322 DC *dc, BITMAPINFO *bmi, UINT16 usage,
3323 SEGPTR *bits, HANDLE section,
3324 DWORD offset, DWORD ovr_pitch)
3326 HBITMAP res = X11DRV_DIB_CreateDIBSection(dc, bmi, usage, NULL,
3327 section, offset, ovr_pitch);
3328 if ( res )
3330 BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr(res, BITMAP_MAGIC);
3331 if ( bmp && bmp->dib )
3333 DIBSECTION *dib = bmp->dib;
3334 INT height = dib->dsBm.bmHeight >= 0 ?
3335 dib->dsBm.bmHeight : -dib->dsBm.bmHeight;
3336 /* same as above - only use biSizeImage as the correct size if it a
3337 compressed image and it's currently non-zero. In other cases, use
3338 width * height as the value. */
3339 INT size = dib->dsBmih.biSizeImage && dib->dsBmih.biCompression != BI_RGB
3340 ? dib->dsBmih.biSizeImage
3341 : dib->dsBm.bmWidthBytes * height;
3342 if ( dib->dsBm.bmBits )
3344 ((X11DRV_DIBSECTION *) bmp->dib)->selector =
3345 SELECTOR_AllocBlock( dib->dsBm.bmBits, size, WINE_LDT_FLAGS_DATA );
3347 TRACE("ptr = %p, size =%d, selector = %04x, segptr = %ld\n",
3348 dib->dsBm.bmBits, size, ((X11DRV_DIBSECTION *) bmp->dib)->selector,
3349 PTR_SEG_OFF_TO_SEGPTR(((X11DRV_DIBSECTION *) bmp->dib)->selector, 0));
3350 if ( bits )
3351 *bits = PTR_SEG_OFF_TO_SEGPTR( ((X11DRV_DIBSECTION *) bmp->dib)->selector, 0 );
3353 if (bmp) GDI_ReleaseObj( res );
3356 return res;
3359 /***********************************************************************
3360 * X11DRV_XShmErrorHandler
3363 static int XShmErrorHandler(Display *dpy, XErrorEvent *event)
3365 XShmErrorFlag = 1;
3366 return 0;
3369 /***********************************************************************
3370 * X11DRV_XShmCreateImage
3374 extern BOOL X11DRV_XShmCreateImage(XImage** image, int width, int height, int bpp,
3375 XShmSegmentInfo* shminfo)
3377 int (*WineXHandler)(Display *, XErrorEvent *);
3379 *image = TSXShmCreateImage(display, X11DRV_GetVisual(), bpp, ZPixmap, NULL, shminfo, width, height);
3380 if( *image != NULL )
3382 EnterCriticalSection( &X11DRV_CritSection );
3383 shminfo->shmid = shmget(IPC_PRIVATE, (*image)->bytes_per_line * height,
3384 IPC_CREAT|0700);
3385 if( shminfo->shmid != -1 )
3387 shminfo->shmaddr = (*image)->data = shmat(shminfo->shmid, 0, 0);
3388 if( shminfo->shmaddr != (char*)-1 )
3390 shminfo->readOnly = FALSE;
3391 if( TSXShmAttach( display, shminfo ) != 0)
3393 /* Reset the error flag */
3394 XShmErrorFlag = 0;
3395 WineXHandler = XSetErrorHandler(XShmErrorHandler);
3396 XSync( display, 0 );
3398 if (!XShmErrorFlag)
3400 shmctl(shminfo->shmid, IPC_RMID, 0);
3402 XSetErrorHandler(WineXHandler);
3403 LeaveCriticalSection( &X11DRV_CritSection );
3405 return TRUE; /* Success! */
3407 /* An error occured */
3408 XShmErrorFlag = 0;
3409 XSetErrorHandler(WineXHandler);
3411 shmdt(shminfo->shmaddr);
3413 shmctl(shminfo->shmid, IPC_RMID, 0);
3415 XFlush(display);
3416 XDestroyImage(*image);
3417 LeaveCriticalSection( &X11DRV_CritSection );
3419 return FALSE;
3425 /***********************************************************************
3426 * X11DRV_DIB_CreateDIBSection
3428 HBITMAP X11DRV_DIB_CreateDIBSection(
3429 DC *dc, BITMAPINFO *bmi, UINT usage,
3430 LPVOID *bits, HANDLE section,
3431 DWORD offset, DWORD ovr_pitch)
3433 HBITMAP res = 0;
3434 BITMAPOBJ *bmp = NULL;
3435 X11DRV_DIBSECTION *dib = NULL;
3436 int *colorMap = NULL;
3437 int nColorMap;
3439 /* Fill BITMAP32 structure with DIB data */
3440 BITMAPINFOHEADER *bi = &bmi->bmiHeader;
3441 INT effHeight, totalSize;
3442 BITMAP bm;
3444 TRACE("format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
3445 bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
3446 bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
3448 effHeight = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
3449 bm.bmType = 0;
3450 bm.bmWidth = bi->biWidth;
3451 bm.bmHeight = effHeight;
3452 bm.bmWidthBytes = ovr_pitch ? ovr_pitch
3453 : DIB_GetDIBWidthBytes(bm.bmWidth, bi->biBitCount);
3454 bm.bmPlanes = bi->biPlanes;
3455 bm.bmBitsPixel = bi->biBitCount;
3456 bm.bmBits = NULL;
3458 /* Get storage location for DIB bits. Only use biSizeImage if it's valid and
3459 we're dealing with a compressed bitmap. Otherwise, use width * height. */
3460 totalSize = bi->biSizeImage && bi->biCompression != BI_RGB
3461 ? bi->biSizeImage : bm.bmWidthBytes * effHeight;
3463 if (section)
3464 bm.bmBits = MapViewOfFile(section, FILE_MAP_ALL_ACCESS,
3465 0L, offset, totalSize);
3466 else if (ovr_pitch && offset)
3467 bm.bmBits = (LPVOID) offset;
3468 else {
3469 offset = 0;
3470 bm.bmBits = VirtualAlloc(NULL, totalSize,
3471 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
3474 /* Create Color Map */
3475 if (bm.bmBits && bm.bmBitsPixel <= 8)
3476 colorMap = X11DRV_DIB_BuildColorMap( usage == DIB_PAL_COLORS? dc : NULL,
3477 usage, bm.bmBitsPixel, bmi, &nColorMap );
3479 /* Allocate Memory for DIB and fill structure */
3480 if (bm.bmBits)
3481 dib = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(X11DRV_DIBSECTION));
3482 if (dib)
3484 dib->dibSection.dsBm = bm;
3485 dib->dibSection.dsBmih = *bi;
3486 dib->dibSection.dsBmih.biSizeImage = totalSize;
3488 /* Set dsBitfields values */
3489 if ( usage == DIB_PAL_COLORS || bi->biBitCount <= 8)
3491 dib->dibSection.dsBitfields[0] = dib->dibSection.dsBitfields[1] = dib->dibSection.dsBitfields[2] = 0;
3493 else switch( bi->biBitCount )
3495 case 16:
3496 dib->dibSection.dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors : 0x7c00;
3497 dib->dibSection.dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0x03e0;
3498 dib->dibSection.dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0x001f;
3499 break;
3501 case 24:
3502 dib->dibSection.dsBitfields[0] = 0xff;
3503 dib->dibSection.dsBitfields[1] = 0xff00;
3504 dib->dibSection.dsBitfields[2] = 0xff0000;
3505 break;
3507 case 32:
3508 dib->dibSection.dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors : 0xff;
3509 dib->dibSection.dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0xff00;
3510 dib->dibSection.dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0xff0000;
3511 break;
3513 dib->dibSection.dshSection = section;
3514 dib->dibSection.dsOffset = offset;
3516 dib->status = X11DRV_DIB_NoHandler;
3517 dib->selector = 0;
3519 dib->nColorMap = nColorMap;
3520 dib->colorMap = colorMap;
3523 /* Create Device Dependent Bitmap and add DIB pointer */
3524 if (dib)
3526 res = CreateDIBitmap(dc->hSelf, bi, 0, NULL, bmi, usage);
3527 if (res)
3529 bmp = (BITMAPOBJ *) GDI_GetObjPtr(res, BITMAP_MAGIC);
3530 if (bmp)
3532 bmp->dib = (DIBSECTION *) dib;
3533 /* HACK for now */
3534 if(!bmp->physBitmap)
3535 X11DRV_CreateBitmap(res);
3540 /* Create XImage */
3541 if (dib && bmp)
3543 if (TSXShmQueryExtension(display) &&
3544 X11DRV_XShmCreateImage( &dib->image, bm.bmWidth, effHeight,
3545 bmp->bitmap.bmBitsPixel, &dib->shminfo ) )
3547 ; /* Created Image */
3548 } else {
3549 XCREATEIMAGE( dib->image, bm.bmWidth, effHeight, bmp->bitmap.bmBitsPixel );
3550 dib->shminfo.shmid = -1;
3554 /* Clean up in case of errors */
3555 if (!res || !bmp || !dib || !bm.bmBits || (bm.bmBitsPixel <= 8 && !colorMap))
3557 TRACE("got an error res=%08x, bmp=%p, dib=%p, bm.bmBits=%p\n",
3558 res, bmp, dib, bm.bmBits);
3559 if (bm.bmBits)
3561 if (section)
3562 UnmapViewOfFile(bm.bmBits), bm.bmBits = NULL;
3563 else if (!offset)
3564 VirtualFree(bm.bmBits, 0L, MEM_RELEASE), bm.bmBits = NULL;
3567 if (dib && dib->image) { XDestroyImage(dib->image); dib->image = NULL; }
3568 if (colorMap) { HeapFree(GetProcessHeap(), 0, colorMap); colorMap = NULL; }
3569 if (dib) { HeapFree(GetProcessHeap(), 0, dib); dib = NULL; }
3570 if (bmp) { GDI_ReleaseObj(res); bmp = NULL; }
3571 if (res) { DeleteObject(res); res = 0; }
3574 /* Install fault handler, if possible */
3575 if (bm.bmBits)
3577 if (VIRTUAL_SetFaultHandler(bm.bmBits, X11DRV_DIB_FaultHandler, (LPVOID)res))
3579 if (section || offset)
3581 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
3582 if (dib) dib->status = X11DRV_DIB_AppMod;
3584 else
3586 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
3587 if (dib) dib->status = X11DRV_DIB_InSync;
3592 /* Return BITMAP handle and storage location */
3593 if (bmp) GDI_ReleaseObj(res);
3594 if (bm.bmBits && bits) *bits = bm.bmBits;
3595 return res;
3598 /***********************************************************************
3599 * X11DRV_DIB_DeleteDIBSection
3601 void X11DRV_DIB_DeleteDIBSection(BITMAPOBJ *bmp)
3603 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
3605 if (dib->image)
3607 if (dib->shminfo.shmid != -1)
3609 TSXShmDetach (display, &(dib->shminfo));
3610 XDestroyImage (dib->image);
3611 shmdt (dib->shminfo.shmaddr);
3612 dib->shminfo.shmid = -1;
3614 else
3615 XDestroyImage( dib->image );
3618 if (dib->colorMap)
3619 HeapFree(GetProcessHeap(), 0, dib->colorMap);
3621 if (dib->selector) SELECTOR_FreeBlock( dib->selector );
3624 /***********************************************************************
3625 * X11DRV_DIB_SetDIBColorTable
3627 UINT X11DRV_DIB_SetDIBColorTable(BITMAPOBJ *bmp, DC *dc, UINT start, UINT count, const RGBQUAD *colors)
3629 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
3631 if (dib && dib->colorMap) {
3632 X11DRV_DIB_GenColorMap( dc, dib->colorMap, DIB_RGB_COLORS, dib->dibSection.dsBm.bmBitsPixel,
3633 TRUE, colors, start, count - start );
3634 return count;
3636 return 0;
3639 /***********************************************************************
3640 * X11DRV_DIB_GetDIBColorTable
3642 UINT X11DRV_DIB_GetDIBColorTable(BITMAPOBJ *bmp, DC *dc, UINT start, UINT count, RGBQUAD *colors)
3644 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
3646 if (dib && dib->colorMap) {
3647 int i, end = count - start;
3648 for (i = start; i < end; i++,colors++) {
3649 COLORREF col = X11DRV_PALETTE_ToLogical( dib->colorMap[i] );
3650 colors->rgbBlue = GetBValue(col);
3651 colors->rgbGreen = GetGValue(col);
3652 colors->rgbRed = GetRValue(col);
3653 colors->rgbReserved = 0;
3655 return count;
3657 return 0;
3661 /**************************************************************************
3662 * X11DRV_DIB_CreateDIBFromPixmap
3664 * Allocates a packed DIB and copies the Pixmap data into it.
3665 * If bDeletePixmap is TRUE, the Pixmap passed in is deleted after the conversion.
3667 HGLOBAL X11DRV_DIB_CreateDIBFromPixmap(Pixmap pixmap, HDC hdc, BOOL bDeletePixmap)
3669 HBITMAP hBmp = 0;
3670 BITMAPOBJ *pBmp = NULL;
3671 HGLOBAL hPackedDIB = 0;
3673 /* Allocates an HBITMAP which references the Pixmap passed to us */
3674 hBmp = X11DRV_BITMAP_CreateBitmapHeaderFromPixmap(pixmap);
3675 if (!hBmp)
3677 TRACE("\tCould not create bitmap header for Pixmap\n");
3678 goto END;
3682 * Create a packed DIB from the Pixmap wrapper bitmap created above.
3683 * A packed DIB contains a BITMAPINFO structure followed immediately by
3684 * an optional color palette and the pixel data.
3686 hPackedDIB = DIB_CreateDIBFromBitmap(hdc, hBmp);
3688 /* Get a pointer to the BITMAPOBJ structure */
3689 pBmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
3691 /* We can now get rid of the HBITMAP wrapper we created earlier.
3692 * Note: Simply calling DeleteObject will free the embedded Pixmap as well.
3694 if (!bDeletePixmap)
3696 /* Clear the physBitmap to prevent the Pixmap from being deleted by DeleteObject */
3697 pBmp->physBitmap = NULL;
3698 pBmp->funcs = NULL;
3700 GDI_ReleaseObj( hBmp );
3701 DeleteObject(hBmp);
3703 END:
3704 TRACE("\tReturning packed DIB %x\n", hPackedDIB);
3705 return hPackedDIB;
3709 /**************************************************************************
3710 * X11DRV_DIB_CreatePixmapFromDIB
3712 * Creates a Pixmap from a packed DIB
3714 Pixmap X11DRV_DIB_CreatePixmapFromDIB( HGLOBAL hPackedDIB, HDC hdc )
3716 Pixmap pixmap = None;
3717 HBITMAP hBmp = 0;
3718 BITMAPOBJ *pBmp = NULL;
3719 LPBYTE pPackedDIB = NULL;
3720 LPBITMAPINFO pbmi = NULL;
3721 LPBITMAPINFOHEADER pbmiHeader = NULL;
3722 LPBYTE pbits = NULL;
3724 /* Get a pointer to the packed DIB's data */
3725 pPackedDIB = (LPBYTE)GlobalLock(hPackedDIB);
3726 pbmiHeader = (LPBITMAPINFOHEADER)pPackedDIB;
3727 pbmi = (LPBITMAPINFO)pPackedDIB;
3728 pbits = (LPBYTE)(pPackedDIB
3729 + DIB_BitmapInfoSize( (LPBITMAPINFO)pbmiHeader, DIB_RGB_COLORS ));
3731 /* Create a DDB from the DIB */
3733 hBmp = CreateDIBitmap(hdc,
3734 pbmiHeader,
3735 CBM_INIT,
3736 (LPVOID)pbits,
3737 pbmi,
3738 DIB_RGB_COLORS);
3740 GlobalUnlock(hPackedDIB);
3742 TRACE("CreateDIBitmap returned %x\n", hBmp);
3744 /* Retrieve the internal Pixmap from the DDB */
3746 pBmp = (BITMAPOBJ *) GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
3748 pixmap = (Pixmap)pBmp->physBitmap;
3749 /* clear the physBitmap so that we can steal its pixmap */
3750 pBmp->physBitmap = NULL;
3751 pBmp->funcs = NULL;
3753 /* Delete the DDB we created earlier now that we have stolen its pixmap */
3754 GDI_ReleaseObj( hBmp );
3755 DeleteObject(hBmp);
3757 TRACE("\tReturning Pixmap %ld\n", pixmap);
3758 return pixmap;