Handling for listviewstyles, view mode buttons in filedialogs
[wine/multimedia.git] / graphics / x11drv / dib.c
blob9b8103a6ff98307129ca8303faedb0631ea799cf
1 /*
2 * X11DRV device-independent bitmaps
4 * Copyright 1993,1994 Alexandre Julliard
5 */
7 #include "windows.h"
8 #include "bitmap.h"
9 #include "x11drv.h"
10 #include "ts_xlib.h"
11 #include "ts_xutil.h"
12 #include "debug.h"
13 #include "dc.h"
14 #include "color.h"
15 #include "callback.h"
17 static int bitmapDepthTable[] = { 8, 1, 32, 16, 24, 15, 4, 0 };
18 static int ximageDepthTable[] = { 0, 0, 0, 0, 0, 0, 0 };
20 /***********************************************************************
21 * X11DRV_DIB_Init
23 BOOL32 X11DRV_DIB_Init(void)
25 int i;
26 XImage* testimage;
28 for( i = 0; bitmapDepthTable[i]; i++ )
30 testimage = TSXCreateImage(display, DefaultVisualOfScreen(screen),
31 bitmapDepthTable[i], ZPixmap, 0, NULL, 1, 1, 32, 20 );
32 if( testimage ) ximageDepthTable[i] = testimage->bits_per_pixel;
33 else return FALSE;
34 TSXDestroyImage(testimage);
36 return TRUE;
40 /***********************************************************************
41 * X11DRV_DIB_GetXImageWidthBytes
43 * Return the width of an X image in bytes
45 int X11DRV_DIB_GetXImageWidthBytes( int width, int depth )
47 int i;
49 if (!ximageDepthTable[0]) {
50 X11DRV_DIB_Init();
52 for( i = 0; bitmapDepthTable[i] ; i++ )
53 if( bitmapDepthTable[i] == depth )
54 return (4 * ((width * ximageDepthTable[i] + 31)/32));
56 WARN(bitmap, "(%d): Unsupported depth\n", depth );
57 return (4 * width);
60 /***********************************************************************
61 * X11DRV_DIB_BuildColorMap
63 * Build the color map from the bitmap palette. Should not be called
64 * for a >8-bit deep bitmap.
66 int *X11DRV_DIB_BuildColorMap( DC *dc, WORD coloruse, WORD depth,
67 const BITMAPINFO *info, int *nColors )
69 int i, colors;
70 BOOL32 isInfo;
71 WORD *colorPtr;
72 int *colorMapping;
74 if ((isInfo = (info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))))
76 colors = info->bmiHeader.biClrUsed;
77 if (!colors) colors = 1 << info->bmiHeader.biBitCount;
78 colorPtr = (WORD *)info->bmiColors;
80 else /* assume BITMAPCOREINFO */
82 colors = 1 << ((BITMAPCOREHEADER *)&info->bmiHeader)->bcBitCount;
83 colorPtr = (WORD *)((BITMAPCOREINFO *)info)->bmciColors;
86 if (colors > 256)
88 ERR(bitmap, "called with >256 colors!\n");
89 return NULL;
92 if (!(colorMapping = (int *)HeapAlloc(GetProcessHeap(), 0,
93 colors * sizeof(int) )))
94 return NULL;
96 if (coloruse == DIB_RGB_COLORS)
98 if (isInfo)
100 RGBQUAD * rgb = (RGBQUAD *)colorPtr;
102 if (depth == 1) /* Monochrome */
103 for (i = 0; i < colors; i++, rgb++)
104 colorMapping[i] = (rgb->rgbRed + rgb->rgbGreen +
105 rgb->rgbBlue > 255*3/2);
106 else
107 for (i = 0; i < colors; i++, rgb++)
108 colorMapping[i] = COLOR_ToPhysical( dc, RGB(rgb->rgbRed,
109 rgb->rgbGreen,
110 rgb->rgbBlue));
112 else
114 RGBTRIPLE * rgb = (RGBTRIPLE *)colorPtr;
116 if (depth == 1) /* Monochrome */
117 for (i = 0; i < colors; i++, rgb++)
118 colorMapping[i] = (rgb->rgbtRed + rgb->rgbtGreen +
119 rgb->rgbtBlue > 255*3/2);
120 else
121 for (i = 0; i < colors; i++, rgb++)
122 colorMapping[i] = COLOR_ToPhysical( dc, RGB(rgb->rgbtRed,
123 rgb->rgbtGreen,
124 rgb->rgbtBlue));
127 else /* DIB_PAL_COLORS */
129 for (i = 0; i < colors; i++, colorPtr++)
130 colorMapping[i] = COLOR_ToPhysical( dc, PALETTEINDEX(*colorPtr) );
133 *nColors = colors;
134 return colorMapping;
138 /***********************************************************************
139 * X11DRV_DIB_MapColor
141 int X11DRV_DIB_MapColor( int *physMap, int nPhysMap, int phys )
143 int color;
145 for (color = 0; color < nPhysMap; color++)
146 if (physMap[color] == phys)
147 return color;
149 WARN(bitmap, "Strange color %08x\n", phys);
150 return 0;
155 /***********************************************************************
156 * X11DRV_DIB_SetImageBits_1_Line
158 * Handles a single line of 1 bit data.
160 static void X11DRV_DIB_SetImageBits_1_Line(DWORD dstwidth, int left, int *colors,
161 XImage *bmpImage, int h, const BYTE *bits)
163 BYTE pix;
164 DWORD i, x;
166 dstwidth += left; bits += left >> 3;
168 /* FIXME: should avoid putting x<left pixels (minor speed issue) */
169 for (i = dstwidth/8, x = left&~7; (i > 0); i--)
171 pix = *bits++;
172 XPutPixel( bmpImage, x++, h, colors[pix >> 7] );
173 XPutPixel( bmpImage, x++, h, colors[(pix >> 6) & 1] );
174 XPutPixel( bmpImage, x++, h, colors[(pix >> 5) & 1] );
175 XPutPixel( bmpImage, x++, h, colors[(pix >> 4) & 1] );
176 XPutPixel( bmpImage, x++, h, colors[(pix >> 3) & 1] );
177 XPutPixel( bmpImage, x++, h, colors[(pix >> 2) & 1] );
178 XPutPixel( bmpImage, x++, h, colors[(pix >> 1) & 1] );
179 XPutPixel( bmpImage, x++, h, colors[pix & 1] );
181 pix = *bits;
182 switch(dstwidth & 7)
184 case 7: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
185 case 6: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
186 case 5: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
187 case 4: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
188 case 3: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
189 case 2: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
190 case 1: XPutPixel( bmpImage, x++, h, colors[pix >> 7] );
194 /***********************************************************************
195 * X11DRV_DIB_SetImageBits_1
197 * SetDIBits for a 1-bit deep DIB.
199 static void X11DRV_DIB_SetImageBits_1( int lines, const BYTE *srcbits,
200 DWORD srcwidth, DWORD dstwidth, int left,
201 int *colors, XImage *bmpImage )
203 int h;
205 /* 32 bit aligned */
206 DWORD linebytes = ((srcwidth + 31) & ~31) / 8;
208 if (lines > 0) {
209 for (h = lines-1; h >=0; h--) {
210 X11DRV_DIB_SetImageBits_1_Line(dstwidth, left, colors, bmpImage, h,
211 srcbits);
212 srcbits += linebytes;
214 } else {
215 lines = -lines;
216 for (h = 0; h < lines; h++) {
217 X11DRV_DIB_SetImageBits_1_Line(dstwidth, left, colors, bmpImage, h,
218 srcbits);
219 srcbits += linebytes;
225 /***********************************************************************
226 * X11DRV_DIB_SetImageBits_4
228 * SetDIBits for a 4-bit deep DIB.
230 static void X11DRV_DIB_SetImageBits_4( int lines, const BYTE *srcbits,
231 DWORD srcwidth, DWORD dstwidth, int left,
232 int *colors, XImage *bmpImage )
234 DWORD i, x;
235 int h;
236 const BYTE *bits = srcbits + (left >> 1);
238 /* 32 bit aligned */
239 DWORD linebytes = ((srcwidth+7)&~7)/2;
241 dstwidth += left;
243 /* FIXME: should avoid putting x<left pixels (minor speed issue) */
244 if (lines > 0) {
245 for (h = lines-1; h >= 0; h--) {
246 for (i = dstwidth/2, x = left&~1; i > 0; i--) {
247 BYTE pix = *bits++;
248 XPutPixel( bmpImage, x++, h, colors[pix >> 4] );
249 XPutPixel( bmpImage, x++, h, colors[pix & 0x0f] );
251 if (dstwidth & 1) XPutPixel( bmpImage, x, h, colors[*bits >> 4] );
252 srcbits += linebytes;
253 bits = srcbits + (left >> 1);
255 } else {
256 lines = -lines;
257 for (h = 0; h < lines; h++) {
258 for (i = dstwidth/2, x = left&~1; i > 0; i--) {
259 BYTE pix = *bits++;
260 XPutPixel( bmpImage, x++, h, colors[pix >> 4] );
261 XPutPixel( bmpImage, x++, h, colors[pix & 0x0f] );
263 if (dstwidth & 1) XPutPixel( bmpImage, x, h, colors[*bits >> 4] );
264 srcbits += linebytes;
265 bits = srcbits + (left >> 1);
272 /***********************************************************************
273 * X11DRV_DIB_GetImageBits_4
275 * GetDIBits for a 4-bit deep DIB.
277 static void X11DRV_DIB_GetImageBits_4( int lines, BYTE *srcbits,
278 DWORD srcwidth, DWORD dstwidth, int left,
279 int *colors, int nColors, XImage *bmpImage )
281 DWORD i, x;
282 int h;
283 BYTE *bits = srcbits + (left >> 1);
285 /* 32 bit aligned */
286 DWORD linebytes = ((srcwidth+7)&~7)/2;
288 dstwidth += left;
290 /* FIXME: should avoid putting x<left pixels (minor speed issue) */
291 if (lines > 0) {
292 for (h = lines-1; h >= 0; h--) {
293 for (i = dstwidth/2, x = left&~1; i > 0; i--) {
294 *bits++ = (X11DRV_DIB_MapColor( colors, nColors,
295 XGetPixel( bmpImage, x++, h )) << 4)
296 | (X11DRV_DIB_MapColor( colors, nColors,
297 XGetPixel( bmpImage, x++, h )) & 0x0f);
299 if (dstwidth & 1)
300 *bits = (X11DRV_DIB_MapColor( colors, nColors,
301 XGetPixel( bmpImage, x++, h )) << 4);
302 srcbits += linebytes;
303 bits = srcbits + (left >> 1);
305 } else {
306 lines = -lines;
307 for (h = 0; h < lines; h++) {
308 for (i = dstwidth/2, x = left&~1; i > 0; i--) {
309 *bits++ = (X11DRV_DIB_MapColor( colors, nColors,
310 XGetPixel( bmpImage, x++, h ))
311 << 4)
312 | (X11DRV_DIB_MapColor( colors, nColors,
313 XGetPixel( bmpImage, x++, h )) & 0x0f);
315 if (dstwidth & 1)
316 *bits = (X11DRV_DIB_MapColor( colors, nColors,
317 XGetPixel( bmpImage, x++, h )) << 4);
318 srcbits += linebytes;
319 bits = srcbits + (left >> 1);
324 #define check_xy(x,y) \
325 if (x > width) { \
326 x = 0; \
327 if (lines) \
328 lines--; \
331 /***********************************************************************
332 * X11DRV_DIB_SetImageBits_RLE4
334 * SetDIBits for a 4-bit deep compressed DIB.
336 static void X11DRV_DIB_SetImageBits_RLE4( int lines, const BYTE *bits, DWORD width,
337 DWORD dstwidth, int left, int *colors, XImage *bmpImage )
339 int x = 0, c, length;
340 const BYTE *begin = bits;
342 dstwidth += left; /* FIXME: avoid putting x<left pixels */
344 lines--;
345 while ((int)lines >= 0)
347 length = *bits++;
348 if (length) { /* encoded */
349 c = *bits++;
350 while (length--) {
351 XPutPixel(bmpImage, x++, lines, colors[c >> 4]);
352 check_xy(x, y);
353 if (length) {
354 length--;
355 XPutPixel(bmpImage, x++, lines, colors[c & 0xf]);
356 check_xy(x, y);
359 } else {
360 length = *bits++;
361 switch (length) {
362 case 0: /* eol */
363 x = 0;
364 lines--;
365 continue;
367 case 1: /* eopicture */
368 return;
370 case 2: /* delta */
371 x += *bits++;
372 lines -= *bits++;
373 continue;
375 default: /* absolute */
376 while (length--) {
377 c = *bits++;
378 XPutPixel(bmpImage, x++, lines, colors[c >> 4]);
379 check_xy(x, y);
380 if (length) {
381 length--;
382 XPutPixel(bmpImage, x++, lines, colors[c & 0xf]);
383 check_xy(x, y);
386 if ((bits - begin) & 1)
387 bits++;
396 /***********************************************************************
397 * X11DRV_DIB_SetImageBits_8
399 * SetDIBits for an 8-bit deep DIB.
401 static void X11DRV_DIB_SetImageBits_8( int lines, const BYTE *srcbits,
402 DWORD srcwidth, DWORD dstwidth, int left,
403 int *colors, XImage *bmpImage )
405 DWORD x;
406 int h;
407 const BYTE *bits = srcbits + left;
409 /* align to 32 bit */
410 DWORD linebytes = (srcwidth + 3) & ~3;
412 dstwidth+=left;
414 if (lines > 0) {
415 for (h = lines - 1; h >= 0; h--) {
416 for (x = left; x < dstwidth; x++, bits++) {
417 XPutPixel( bmpImage, x, h, colors[*bits] );
419 bits = (srcbits += linebytes) + left;
421 } else {
422 lines = -lines;
423 for (h = 0; h < lines; h++) {
424 for (x = left; x < dstwidth; x++, bits++) {
425 XPutPixel( bmpImage, x, h, colors[*bits] );
427 bits = (srcbits += linebytes) + left;
432 /***********************************************************************
433 * X11DRV_DIB_GetImageBits_8
435 * GetDIBits for an 8-bit deep DIB.
437 static void X11DRV_DIB_GetImageBits_8( int lines, BYTE *srcbits,
438 DWORD srcwidth, DWORD dstwidth, int left,
439 int *colors, int nColors, XImage *bmpImage )
441 DWORD x;
442 int h;
443 BYTE *bits = srcbits + left;
445 /* align to 32 bit */
446 DWORD linebytes = (srcwidth + 3) & ~3;
448 dstwidth+=left;
450 if (lines > 0) {
451 for (h = lines - 1; h >= 0; h--) {
452 for (x = left; x < dstwidth; x++, bits++) {
453 if ( XGetPixel( bmpImage, x, h ) != colors[*bits] )
454 *bits = X11DRV_DIB_MapColor( colors, nColors,
455 XGetPixel( bmpImage, x, h ) );
457 bits = (srcbits += linebytes) + left;
459 } else {
460 lines = -lines;
461 for (h = 0; h < lines; h++) {
462 for (x = left; x < dstwidth; x++, bits++) {
463 if ( XGetPixel( bmpImage, x, h ) != colors[*bits] )
464 *bits = X11DRV_DIB_MapColor( colors, nColors,
465 XGetPixel( bmpImage, x, h ) );
467 bits = (srcbits += linebytes) + left;
472 /***********************************************************************
473 * X11DRV_DIB_SetImageBits_RLE8
475 * SetDIBits for an 8-bit deep compressed DIB.
477 * This function rewritten 941113 by James Youngman. WINE blew out when I
478 * first ran it because my desktop wallpaper is a (large) RLE8 bitmap.
480 * This was because the algorithm assumed that all RLE8 bitmaps end with the
481 * 'End of bitmap' escape code. This code is very much laxer in what it
482 * allows to end the expansion. Possibly too lax. See the note by
483 * case RleDelta. BTW, MS's documentation implies that a correct RLE8
484 * bitmap should end with RleEnd, but on the other hand, software exists
485 * that produces ones that don't and Windows 3.1 doesn't complain a bit
486 * about it.
488 * (No) apologies for my English spelling. [Emacs users: c-indent-level=4].
489 * James A. Youngman <mbcstjy@afs.man.ac.uk>
490 * [JAY]
493 enum Rle8_EscapeCodes
496 * Apologies for polluting your file's namespace...
498 RleEol = 0, /* End of line */
499 RleEnd = 1, /* End of bitmap */
500 RleDelta = 2 /* Delta */
503 static void X11DRV_DIB_SetImageBits_RLE8( int lines, const BYTE *bits,
504 DWORD width, DWORD dstwidth,
505 int left, int *colors,
506 XImage *bmpImage )
508 int x; /* X-positon on each line. Increases. */
509 int line; /* Line #. Starts at lines-1, decreases */
510 const BYTE *pIn = bits; /* Pointer to current position in bits */
511 BYTE length; /* The length pf a run */
512 BYTE color_index; /* index into colors[] as read from bits */
513 BYTE escape_code; /* See enum Rle8_EscapeCodes.*/
514 int color; /* value of colour[color_index] */
516 if (lines == 0) /* Let's hope this doesn't happen. */
517 return;
519 dstwidth += left; /* FIXME: avoid putting x<left pixels */
522 * Note that the bitmap data is stored by Windows starting at the
523 * bottom line of the bitmap and going upwards. Within each line,
524 * the data is stored left-to-right. That's the reason why line
525 * goes from lines-1 to 0. [JAY]
528 x = 0;
529 line = lines-1;
532 length = *pIn++;
535 * If the length byte is not zero (which is the escape value),
536 * We have a run of length pixels all the same colour. The colour
537 * index is stored next.
539 * If the length byte is zero, we need to read the next byte to
540 * know what to do. [JAY]
542 if (length != 0)
545 * [Run-Length] Encoded mode
547 color_index = (*pIn++); /* Get the colour index. */
548 color = colors[color_index];
550 while(length--)
551 XPutPixel(bmpImage, x++, line, color);
553 else
556 * Escape codes (may be an absolute sequence though)
558 escape_code = (*pIn++);
559 switch(escape_code)
561 case RleEol: /* =0, end of line */
563 x = 0;
564 line--;
565 break;
568 case RleEnd: /* =1, end of bitmap */
571 * Not all RLE8 bitmaps end with this
572 * code. For example, Paint Shop Pro
573 * produces some that don't. That's (I think)
574 * what caused the previous implementation to
575 * fail. [JAY]
577 line=-1; /* Cause exit from do loop. */
578 break;
581 case RleDelta: /* =2, a delta */
584 * Note that deltaing to line 0
585 * will cause an exit from the loop,
586 * which may not be what is intended.
587 * The fact that there is a delta in the bits
588 * almost certainly implies that there is data
589 * to follow. You may feel that we should
590 * jump to the top of the loop to avoid exiting
591 * in this case.
593 * TODO: Decide what to do here in that case. [JAY]
595 x += (*pIn++);
596 line -= (*pIn++);
597 if (line == 0)
599 TRACE(bitmap, "Delta to last line of bitmap "
600 "(wrongly?) causes loop exit\n");
602 break;
605 default: /* >2, switch to absolute mode */
608 * Absolute Mode
610 length = escape_code;
611 while(length--)
613 color_index = (*pIn++);
614 XPutPixel(bmpImage, x++, line,
615 colors[color_index]);
619 * If you think for a moment you'll realise that the
620 * only time we could ever possibly read an odd
621 * number of bytes is when there is a 0x00 (escape),
622 * a value >0x02 (absolute mode) and then an odd-
623 * length run. Therefore this is the only place we
624 * need to worry about it. Everywhere else the
625 * bytes are always read in pairs. [JAY]
627 if (escape_code & 1)
628 pIn++; /* Throw away the pad byte. */
629 break;
631 } /* switch (escape_code) : Escape sequence */
632 } /* process either an encoded sequence or an escape sequence */
634 /* We expect to come here more than once per line. */
635 } while (line >= 0); /* Do this until the bitmap is filled */
638 * Everybody comes here at the end.
639 * Check how we exited the loop and print a message if it's a bit odd.
640 * [JAY]
642 if ( (*(pIn-2) != 0/*escape*/) || (*(pIn-1)!= RleEnd) )
644 TRACE(bitmap, "End-of-bitmap "
645 "without (strictly) proper escape code. Last two "
646 "bytes were: %02X %02X.\n",
647 (int)*(pIn-2),
648 (int)*(pIn-1));
653 /***********************************************************************
654 * X11DRV_DIB_SetImageBits_16
656 * SetDIBits for a 16-bit deep DIB.
658 static void X11DRV_DIB_SetImageBits_16( int lines, const BYTE *srcbits,
659 DWORD srcwidth, DWORD dstwidth, int left,
660 DC *dc, XImage *bmpImage )
662 DWORD x;
663 LPWORD ptr;
664 WORD val;
665 int h;
666 BYTE r, g, b;
668 /* align to 32 bit */
669 DWORD linebytes = (srcwidth * 2 + 3) & ~3;
671 dstwidth += left;
673 ptr = (LPWORD) srcbits + left;
674 if (lines > 0) {
675 for (h = lines - 1; h >= 0; h--) {
676 for (x = left; x < dstwidth; x++, ptr++) {
677 val = *ptr;
678 r = (BYTE) ((val & 0x7c00) >> 7);
679 g = (BYTE) ((val & 0x03e0) >> 2);
680 b = (BYTE) ((val & 0x001f) << 3);
681 XPutPixel( bmpImage, x, h,
682 COLOR_ToPhysical(dc, RGB(r,g,b)) );
684 ptr = (LPWORD) (srcbits += linebytes) + left;
686 } else {
687 lines = -lines;
688 for (h = 0; h < lines; h++) {
689 for (x = left; x < dstwidth; x++, ptr++) {
690 val = *ptr;
691 r = (BYTE) ((val & 0x7c00) >> 7);
692 g = (BYTE) ((val & 0x03e0) >> 2);
693 b = (BYTE) ((val & 0x001f) << 3);
694 XPutPixel( bmpImage, x, h,
695 COLOR_ToPhysical(dc, RGB(r,g,b)) );
697 ptr = (LPWORD) (srcbits += linebytes) + left;
703 /***********************************************************************
704 * X11DRV_DIB_GetImageBits_16
706 * GetDIBits for an 16-bit deep DIB.
708 static void X11DRV_DIB_GetImageBits_16( int lines, BYTE *srcbits,
709 DWORD srcwidth, DWORD dstwidth, int left,
710 XImage *bmpImage )
712 DWORD x;
713 LPWORD ptr;
714 int h;
715 BYTE r, g, b;
717 /* align to 32 bit */
718 DWORD linebytes = (srcwidth * 2 + 3) & ~3;
720 dstwidth += left;
722 ptr = (LPWORD) srcbits + left;
723 if (lines > 0) {
724 for (h = lines - 1; h >= 0; h--)
726 for (x = left; x < dstwidth; x++, ptr++)
728 COLORREF pixel = COLOR_ToLogical( XGetPixel( bmpImage, x, h ) );
729 r = (BYTE) GetRValue(pixel);
730 g = (BYTE) GetGValue(pixel);
731 b = (BYTE) GetBValue(pixel);
732 *ptr = ( ((r << 7) & 0x7c00) | ((g << 2) & 0x03e0) | ((b >> 3) & 0x001f) );
734 ptr = (LPWORD) (srcbits += linebytes) + left;
736 } else {
737 lines = -lines;
738 for (h = 0; h < lines; h++)
740 for (x = left; x < dstwidth; x++, ptr++)
742 COLORREF pixel = COLOR_ToLogical( XGetPixel( bmpImage, x, h ) );
743 r = (BYTE) GetRValue(pixel);
744 g = (BYTE) GetGValue(pixel);
745 b = (BYTE) GetBValue(pixel);
746 *ptr = ( ((r << 7) & 0x7c00) | ((g << 2) & 0x03e0) | ((b >> 3) & 0x001f) );
749 ptr = (LPWORD) (srcbits += linebytes) + left;
756 /***********************************************************************
757 * X11DRV_DIB_SetImageBits_24
759 * SetDIBits for a 24-bit deep DIB.
761 static void X11DRV_DIB_SetImageBits_24( int lines, const BYTE *srcbits,
762 DWORD srcwidth, DWORD dstwidth, int left,
763 DC *dc, XImage *bmpImage )
765 DWORD x;
766 const BYTE *bits = srcbits + left * 3;
767 int h;
769 /* align to 32 bit */
770 DWORD linebytes = (srcwidth * 3 + 3) & ~3;
772 dstwidth += left;
774 /* "bits" order is reversed for some reason */
776 if (lines > 0) {
777 for (h = lines - 1; h >= 0; h--) {
778 for (x = left; x < dstwidth; x++, bits += 3) {
779 XPutPixel( bmpImage, x, h,
780 COLOR_ToPhysical(dc, RGB(bits[2],bits[1],bits[0])));
782 bits = (srcbits += linebytes) + left * 3;
784 } else {
785 lines = -lines;
786 for (h = 0; h < lines; h++) {
787 for (x = left; x < dstwidth; x++, bits += 3) {
788 XPutPixel( bmpImage, x, h,
789 COLOR_ToPhysical(dc, RGB(bits[2],bits[1],bits[0])));
791 bits = (srcbits += linebytes) + left * 3;
797 /***********************************************************************
798 * X11DRV_DIB_GetImageBits_24
800 * GetDIBits for an 24-bit deep DIB.
802 static void X11DRV_DIB_GetImageBits_24( int lines, BYTE *srcbits,
803 DWORD srcwidth, DWORD dstwidth, int left,
804 XImage *bmpImage )
806 DWORD x;
807 int h;
808 BYTE *bits = srcbits + (left * 3);
810 /* align to 32 bit */
811 DWORD linebytes = (srcwidth * 3 + 3) & ~3;
813 dstwidth += left;
815 if (lines > 0) {
816 for (h = lines - 1; h >= 0; h--)
818 for (x = left; x < dstwidth; x++, bits += 3)
820 COLORREF pixel = COLOR_ToLogical( XGetPixel( bmpImage, x, h ) );
821 bits[0] = GetRValue(pixel);
822 bits[1] = GetGValue(pixel);
823 bits[2] = GetBValue(pixel);
825 bits = (srcbits += linebytes) + (left * 3);
827 } else {
828 lines = -lines;
829 for (h = 0; h < lines; h++)
831 for (x = left; x < dstwidth; x++, bits += 3)
833 COLORREF pixel = COLOR_ToLogical( XGetPixel( bmpImage, x, h ) );
834 bits[0] = GetRValue(pixel);
835 bits[1] = GetGValue(pixel);
836 bits[2] = GetBValue(pixel);
839 bits = (srcbits += linebytes) + (left * 3);
845 /***********************************************************************
846 * X11DRV_DIB_SetImageBits_32
848 * SetDIBits for a 32-bit deep DIB.
850 static void X11DRV_DIB_SetImageBits_32( int lines, const BYTE *srcbits,
851 DWORD srcwidth, DWORD dstwidth, int left,
852 DC *dc, XImage *bmpImage )
854 DWORD x;
855 const BYTE *bits = srcbits + left * 4;
856 int h;
858 DWORD linebytes = (srcwidth * 4);
860 dstwidth += left;
862 if (lines > 0) {
863 for (h = lines - 1; h >= 0; h--) {
864 for (x = left; x < dstwidth; x++, bits += 4) {
865 XPutPixel( bmpImage, x, h,
866 COLOR_ToPhysical(dc, RGB(bits[2],bits[1],bits[0])));
868 bits = (srcbits += linebytes) + left * 4;
870 } else {
871 lines = -lines;
872 for (h = 0; h < lines; h++) {
873 for (x = left; x < dstwidth; x++, bits += 4) {
874 XPutPixel( bmpImage, x, h,
875 COLOR_ToPhysical(dc, RGB(bits[2],bits[1],bits[0])));
877 bits = (srcbits += linebytes) + left * 4;
883 /***********************************************************************
884 * X11DRV_DIB_GetImageBits_32
886 * GetDIBits for an 32-bit deep DIB.
888 static void X11DRV_DIB_GetImageBits_32( int lines, BYTE *srcbits,
889 DWORD srcwidth, DWORD dstwidth, int left,
890 XImage *bmpImage )
892 DWORD x;
893 int h;
894 BYTE *bits = srcbits + (left * 4);
896 /* align to 32 bit */
897 DWORD linebytes = (srcwidth * 4);
899 dstwidth += left;
901 if (lines > 0) {
902 for (h = lines - 1; h >= 0; h--)
904 for (x = left; x < dstwidth; x++, bits += 4)
906 COLORREF pixel = COLOR_ToLogical( XGetPixel( bmpImage, x, h ) );
907 bits[0] = GetRValue(pixel);
908 bits[1] = GetGValue(pixel);
909 bits[2] = GetBValue(pixel);
911 bits = (srcbits += linebytes) + (left * 4);
913 } else {
914 lines = -lines;
915 for (h = 0; h < lines; h++)
917 for (x = left; x < dstwidth; x++, bits += 4)
919 COLORREF pixel = COLOR_ToLogical( XGetPixel( bmpImage, x, h ) );
920 bits[0] = GetRValue(pixel);
921 bits[1] = GetGValue(pixel);
922 bits[2] = GetBValue(pixel);
925 bits = (srcbits += linebytes) + (left * 4);
931 /***********************************************************************
932 * X11DRV_DIB_SetImageBits
934 * Transfer the bits to an X image.
935 * Helper function for SetDIBits() and SetDIBitsToDevice().
936 * The Xlib critical section must be entered before calling this function.
938 int X11DRV_DIB_SetImageBits( const DIB_SETIMAGEBITS_DESCR *descr )
940 int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
941 XImage *bmpImage;
943 if ( descr->dc && descr->dc->w.flags & DC_DIRTY )
944 CLIPPING_UpdateGCRegion( descr->dc );
946 if (descr->image)
947 bmpImage = descr->image;
948 else
949 XCREATEIMAGE( bmpImage, descr->infoWidth, lines, descr->depth );
951 /* Transfer the pixels */
952 switch(descr->infoBpp)
954 case 1:
955 X11DRV_DIB_SetImageBits_1( descr->lines, descr->bits, descr->infoWidth,
956 descr->width, descr->xSrc, descr->colorMap,
957 bmpImage );
958 break;
959 case 4:
960 if (descr->compression)
961 X11DRV_DIB_SetImageBits_RLE4( descr->lines, descr->bits,
962 descr->infoWidth, descr->width,
963 descr->xSrc, descr->colorMap,
964 bmpImage );
965 else
966 X11DRV_DIB_SetImageBits_4( descr->lines, descr->bits,
967 descr->infoWidth, descr->width,
968 descr->xSrc, descr->colorMap,
969 bmpImage );
970 break;
971 case 8:
972 if (descr->compression)
973 X11DRV_DIB_SetImageBits_RLE8( descr->lines, descr->bits,
974 descr->infoWidth, descr->width,
975 descr->xSrc,
976 descr->colorMap, bmpImage );
977 else
978 X11DRV_DIB_SetImageBits_8( descr->lines, descr->bits,
979 descr->infoWidth, descr->width,
980 descr->xSrc, descr->colorMap,
981 bmpImage );
982 break;
983 case 15:
984 case 16:
985 X11DRV_DIB_SetImageBits_16( descr->lines, descr->bits,
986 descr->infoWidth, descr->width,
987 descr->xSrc, descr->dc, bmpImage);
988 break;
989 case 24:
990 X11DRV_DIB_SetImageBits_24( descr->lines, descr->bits,
991 descr->infoWidth, descr->width,
992 descr->xSrc, descr->dc, bmpImage );
993 break;
994 case 32:
995 X11DRV_DIB_SetImageBits_32( descr->lines, descr->bits,
996 descr->infoWidth, descr->width,
997 descr->xSrc, descr->dc, bmpImage);
998 break;
999 default:
1000 WARN(bitmap, "(%d): Invalid depth\n", descr->infoBpp );
1001 break;
1004 XPutImage( display, descr->drawable, descr->gc, bmpImage,
1005 descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
1006 descr->width, descr->height );
1008 if (!descr->image) XDestroyImage( bmpImage );
1009 return lines;
1012 /***********************************************************************
1013 * X11DRV_DIB_GetImageBits
1015 * Transfer the bits from an X image.
1016 * The Xlib critical section must be entered before calling this function.
1018 int X11DRV_DIB_GetImageBits( const DIB_SETIMAGEBITS_DESCR *descr )
1020 int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
1021 XImage *bmpImage;
1023 if (descr->image)
1024 bmpImage = descr->image;
1025 else
1026 XCREATEIMAGE( bmpImage, descr->infoWidth, lines, descr->depth );
1028 XGetSubImage( display, descr->drawable, descr->xDest, descr->yDest,
1029 descr->width, descr->height, AllPlanes, ZPixmap,
1030 bmpImage, descr->xSrc, descr->ySrc );
1032 /* Transfer the pixels */
1033 switch(descr->infoBpp)
1035 case 1:
1036 FIXME(bitmap, "Depth 1 not yet supported!\n");
1037 break;
1039 case 4:
1040 if (descr->compression)
1041 FIXME(bitmap, "Compression not yet supported!\n");
1042 else
1043 X11DRV_DIB_GetImageBits_4( descr->lines,
1044 (LPVOID)descr->bits, descr->infoWidth,
1045 descr->width, descr->xSrc,
1046 descr->colorMap, descr->nColorMap,
1047 bmpImage );
1048 break;
1050 case 8:
1051 if (descr->compression)
1052 FIXME(bitmap, "Compression not yet supported!\n");
1053 else
1054 X11DRV_DIB_GetImageBits_8( descr->lines, (LPVOID)descr->bits,
1055 descr->infoWidth, descr->width,
1056 descr->xSrc, descr->colorMap,
1057 descr->nColorMap, bmpImage );
1058 break;
1060 case 15:
1061 case 16:
1062 X11DRV_DIB_GetImageBits_16( descr->lines, (LPVOID)descr->bits,
1063 descr->infoWidth,
1064 descr->width, descr->xSrc, bmpImage );
1065 break;
1067 case 24:
1068 X11DRV_DIB_GetImageBits_24( descr->lines, (LPVOID)descr->bits,
1069 descr->infoWidth,
1070 descr->width, descr->xSrc, bmpImage );
1071 break;
1073 case 32:
1074 X11DRV_DIB_GetImageBits_32( descr->lines, (LPVOID)descr->bits,
1075 descr->infoWidth,
1076 descr->width, descr->xSrc, bmpImage );
1077 break;
1079 default:
1080 WARN(bitmap, "(%d): Invalid depth\n", descr->infoBpp );
1081 break;
1084 if (!descr->image) XDestroyImage( bmpImage );
1085 return lines;
1088 /*************************************************************************
1089 * X11DRV_SetDIBitsToDevice
1092 INT32 X11DRV_SetDIBitsToDevice( DC *dc, INT32 xDest, INT32 yDest, DWORD cx,
1093 DWORD cy, INT32 xSrc, INT32 ySrc,
1094 UINT32 startscan, UINT32 lines, LPCVOID bits,
1095 const BITMAPINFO *info, UINT32 coloruse )
1097 DIB_SETIMAGEBITS_DESCR descr;
1098 DWORD width, oldcy = cy;
1099 INT32 result;
1100 int height, tmpheight;
1103 if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height,
1104 &descr.infoBpp, &descr.compression ) == -1)
1105 return 0;
1106 tmpheight = height;
1107 if (height < 0) height = -height;
1108 if (!lines || (startscan >= height)) return 0;
1109 if (startscan + lines > height) lines = height - startscan;
1110 if (ySrc < startscan) ySrc = startscan;
1111 else if (ySrc >= startscan + lines) return 0;
1112 if (xSrc >= width) return 0;
1113 if (ySrc + cy >= startscan + lines) cy = startscan + lines - ySrc;
1114 if (xSrc + cx >= width) cx = width - xSrc;
1115 if (!cx || !cy) return 0;
1117 DC_SetupGCForText( dc ); /* To have the correct colors */
1118 TSXSetFunction( display, dc->u.x.gc, DC_XROPfunction[dc->w.ROPmode-1] );
1120 if (descr.infoBpp <= 8)
1122 descr.colorMap = X11DRV_DIB_BuildColorMap( dc, coloruse,
1123 dc->w.bitsPerPixel,
1124 info, &descr.nColorMap );
1125 if (!descr.colorMap)
1126 return 0;
1129 descr.dc = dc;
1130 descr.bits = bits;
1131 descr.image = NULL;
1132 descr.lines = tmpheight >= 0 ? lines : -lines;
1133 descr.infoWidth = width;
1134 descr.depth = dc->w.bitsPerPixel;
1135 descr.drawable = dc->u.x.drawable;
1136 descr.gc = dc->u.x.gc;
1137 descr.xSrc = xSrc;
1138 descr.ySrc = tmpheight >= 0 ? lines-(ySrc-startscan)-cy+(oldcy-cy)
1139 : ySrc - startscan;
1140 descr.xDest = dc->w.DCOrgX + XLPTODP( dc, xDest );
1141 descr.yDest = dc->w.DCOrgY + YLPTODP( dc, yDest ) +
1142 (tmpheight >= 0 ? oldcy-cy : 0);
1143 descr.width = cx;
1144 descr.height = cy;
1146 EnterCriticalSection( &X11DRV_CritSection );
1147 result = CALL_LARGE_STACK( X11DRV_DIB_SetImageBits, &descr );
1148 LeaveCriticalSection( &X11DRV_CritSection );
1150 HeapFree(GetProcessHeap(), 0, descr.colorMap);
1151 return result;