Large-scale renaming of all Win32 functions and types to use the
[wine/multimedia.git] / graphics / x11drv / dib.c
blobc639f5652f2a4b1f8396645842c5e58c221e7b58
1 /*
2 * X11DRV device-independent bitmaps
4 * Copyright 1993,1994 Alexandre Julliard
5 */
7 #include "config.h"
9 #ifndef X_DISPLAY_MISSING
11 #include "ts_xlib.h"
12 #include "ts_xutil.h"
14 #include "wintypes.h"
15 #include "bitmap.h"
16 #include "x11drv.h"
17 #include "debug.h"
18 #include "dc.h"
19 #include "color.h"
20 #include "callback.h"
21 #include "xmalloc.h"
23 static int bitmapDepthTable[] = { 8, 1, 32, 16, 24, 15, 4, 0 };
24 static int ximageDepthTable[] = { 0, 0, 0, 0, 0, 0, 0 };
26 /***********************************************************************
27 * X11DRV_DIB_Init
29 BOOL X11DRV_DIB_Init(void)
31 int i;
32 XImage* testimage;
34 for( i = 0; bitmapDepthTable[i]; i++ )
36 testimage = TSXCreateImage(display, DefaultVisualOfScreen(X11DRV_GetXScreen()),
37 bitmapDepthTable[i], ZPixmap, 0, NULL, 1, 1, 32, 20 );
38 if( testimage ) ximageDepthTable[i] = testimage->bits_per_pixel;
39 else return FALSE;
40 TSXDestroyImage(testimage);
42 return TRUE;
46 /***********************************************************************
47 * X11DRV_DIB_GetXImageWidthBytes
49 * Return the width of an X image in bytes
51 int X11DRV_DIB_GetXImageWidthBytes( int width, int depth )
53 int i;
55 if (!ximageDepthTable[0]) {
56 X11DRV_DIB_Init();
58 for( i = 0; bitmapDepthTable[i] ; i++ )
59 if( bitmapDepthTable[i] == depth )
60 return (4 * ((width * ximageDepthTable[i] + 31)/32));
62 WARN(bitmap, "(%d): Unsupported depth\n", depth );
63 return (4 * width);
66 /***********************************************************************
67 * X11DRV_DIB_BuildColorMap
69 * Build the color map from the bitmap palette. Should not be called
70 * for a >8-bit deep bitmap.
72 int *X11DRV_DIB_BuildColorMap( DC *dc, WORD coloruse, WORD depth,
73 const BITMAPINFO *info, int *nColors )
75 int i, colors;
76 BOOL isInfo;
77 WORD *colorPtr;
78 int *colorMapping;
80 if ((isInfo = (info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))))
82 colors = info->bmiHeader.biClrUsed;
83 if (!colors) colors = 1 << info->bmiHeader.biBitCount;
84 colorPtr = (WORD *)info->bmiColors;
86 else /* assume BITMAPCOREINFO */
88 colors = 1 << ((BITMAPCOREHEADER *)&info->bmiHeader)->bcBitCount;
89 colorPtr = (WORD *)((BITMAPCOREINFO *)info)->bmciColors;
92 if (colors > 256)
94 ERR(bitmap, "called with >256 colors!\n");
95 return NULL;
98 if (!(colorMapping = (int *)HeapAlloc(GetProcessHeap(), 0,
99 colors * sizeof(int) )))
100 return NULL;
102 if (coloruse == DIB_RGB_COLORS)
104 if (isInfo)
106 RGBQUAD * rgb = (RGBQUAD *)colorPtr;
108 if (depth == 1) /* Monochrome */
109 for (i = 0; i < colors; i++, rgb++)
110 colorMapping[i] = (rgb->rgbRed + rgb->rgbGreen +
111 rgb->rgbBlue > 255*3/2);
112 else
113 for (i = 0; i < colors; i++, rgb++)
114 colorMapping[i] = COLOR_ToPhysical( dc, RGB(rgb->rgbRed,
115 rgb->rgbGreen,
116 rgb->rgbBlue));
118 else
120 RGBTRIPLE * rgb = (RGBTRIPLE *)colorPtr;
122 if (depth == 1) /* Monochrome */
123 for (i = 0; i < colors; i++, rgb++)
124 colorMapping[i] = (rgb->rgbtRed + rgb->rgbtGreen +
125 rgb->rgbtBlue > 255*3/2);
126 else
127 for (i = 0; i < colors; i++, rgb++)
128 colorMapping[i] = COLOR_ToPhysical( dc, RGB(rgb->rgbtRed,
129 rgb->rgbtGreen,
130 rgb->rgbtBlue));
133 else /* DIB_PAL_COLORS */
135 for (i = 0; i < colors; i++, colorPtr++)
136 colorMapping[i] = COLOR_ToPhysical( dc, PALETTEINDEX(*colorPtr) );
139 *nColors = colors;
140 return colorMapping;
144 /***********************************************************************
145 * X11DRV_DIB_MapColor
147 int X11DRV_DIB_MapColor( int *physMap, int nPhysMap, int phys )
149 int color;
151 for (color = 0; color < nPhysMap; color++)
152 if (physMap[color] == phys)
153 return color;
155 WARN(bitmap, "Strange color %08x\n", phys);
156 return 0;
161 /***********************************************************************
162 * X11DRV_DIB_SetImageBits_1_Line
164 * Handles a single line of 1 bit data.
166 static void X11DRV_DIB_SetImageBits_1_Line(DWORD dstwidth, int left, int *colors,
167 XImage *bmpImage, int h, const BYTE *bits)
169 BYTE pix, extra;
170 DWORD i, x;
172 if((extra = (left & 7)) != 0) {
173 left &= ~7;
174 dstwidth += extra;
177 bits += left >> 3;
179 /* FIXME: should avoid putting x<left pixels (minor speed issue) */
180 for (i = dstwidth/8, x = left; i > 0; i--)
182 pix = *bits++;
183 XPutPixel( bmpImage, x++, h, colors[pix >> 7] );
184 XPutPixel( bmpImage, x++, h, colors[(pix >> 6) & 1] );
185 XPutPixel( bmpImage, x++, h, colors[(pix >> 5) & 1] );
186 XPutPixel( bmpImage, x++, h, colors[(pix >> 4) & 1] );
187 XPutPixel( bmpImage, x++, h, colors[(pix >> 3) & 1] );
188 XPutPixel( bmpImage, x++, h, colors[(pix >> 2) & 1] );
189 XPutPixel( bmpImage, x++, h, colors[(pix >> 1) & 1] );
190 XPutPixel( bmpImage, x++, h, colors[pix & 1] );
192 pix = *bits;
193 switch(dstwidth & 7)
195 case 7: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
196 case 6: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
197 case 5: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
198 case 4: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
199 case 3: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
200 case 2: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
201 case 1: XPutPixel( bmpImage, x++, h, colors[pix >> 7] );
205 /***********************************************************************
206 * X11DRV_DIB_SetImageBits_1
208 * SetDIBits for a 1-bit deep DIB.
210 static void X11DRV_DIB_SetImageBits_1( int lines, const BYTE *srcbits,
211 DWORD srcwidth, DWORD dstwidth, int left,
212 int *colors, XImage *bmpImage )
214 int h;
216 /* 32 bit aligned */
217 DWORD linebytes = ((srcwidth + 31) & ~31) / 8;
219 if (lines > 0) {
220 for (h = lines-1; h >=0; h--) {
221 X11DRV_DIB_SetImageBits_1_Line(dstwidth, left, colors, bmpImage, h,
222 srcbits);
223 srcbits += linebytes;
225 } else {
226 lines = -lines;
227 for (h = 0; h < lines; h++) {
228 X11DRV_DIB_SetImageBits_1_Line(dstwidth, left, colors, bmpImage, h,
229 srcbits);
230 srcbits += linebytes;
236 /***********************************************************************
237 * X11DRV_DIB_SetImageBits_4
239 * SetDIBits for a 4-bit deep DIB.
241 static void X11DRV_DIB_SetImageBits_4( int lines, const BYTE *srcbits,
242 DWORD srcwidth, DWORD dstwidth, int left,
243 int *colors, XImage *bmpImage )
245 DWORD i, x;
246 int h;
247 const BYTE *bits = srcbits + (left >> 1);
249 /* 32 bit aligned */
250 DWORD linebytes = ((srcwidth+7)&~7)/2;
252 if(left & 1) {
253 left--;
254 dstwidth++;
257 if (lines > 0) {
258 for (h = lines-1; h >= 0; h--) {
259 for (i = dstwidth/2, x = left; i > 0; i--) {
260 BYTE pix = *bits++;
261 XPutPixel( bmpImage, x++, h, colors[pix >> 4] );
262 XPutPixel( bmpImage, x++, h, colors[pix & 0x0f] );
264 if (dstwidth & 1) XPutPixel( bmpImage, x, h, colors[*bits >> 4] );
265 srcbits += linebytes;
266 bits = srcbits + (left >> 1);
268 } else {
269 lines = -lines;
270 for (h = 0; h < lines; h++) {
271 for (i = dstwidth/2, x = left; i > 0; i--) {
272 BYTE pix = *bits++;
273 XPutPixel( bmpImage, x++, h, colors[pix >> 4] );
274 XPutPixel( bmpImage, x++, h, colors[pix & 0x0f] );
276 if (dstwidth & 1) XPutPixel( bmpImage, x, h, colors[*bits >> 4] );
277 srcbits += linebytes;
278 bits = srcbits + (left >> 1);
285 /***********************************************************************
286 * X11DRV_DIB_GetImageBits_4
288 * GetDIBits for a 4-bit deep DIB.
290 static void X11DRV_DIB_GetImageBits_4( int lines, BYTE *srcbits,
291 DWORD srcwidth, DWORD dstwidth, int left,
292 int *colors, int nColors, XImage *bmpImage )
294 DWORD i, x;
295 int h;
296 BYTE *bits = srcbits + (left >> 1);
298 /* 32 bit aligned */
299 DWORD linebytes = ((srcwidth+7)&~7)/2;
301 if(left & 1) {
302 left--;
303 dstwidth++;
306 /* FIXME: should avoid putting x<left pixels (minor speed issue) */
307 if (lines > 0) {
308 for (h = lines-1; h >= 0; h--) {
309 for (i = dstwidth/2, x = left; i > 0; i--) {
310 *bits++ = (X11DRV_DIB_MapColor( colors, nColors,
311 XGetPixel( bmpImage, x++, h )) << 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);
321 } else {
322 lines = -lines;
323 for (h = 0; h < lines; h++) {
324 for (i = dstwidth/2, x = left; i > 0; i--) {
325 *bits++ = (X11DRV_DIB_MapColor( colors, nColors,
326 XGetPixel( bmpImage, x++, h ))
327 << 4)
328 | (X11DRV_DIB_MapColor( colors, nColors,
329 XGetPixel( bmpImage, x++, h )) & 0x0f);
331 if (dstwidth & 1)
332 *bits = (X11DRV_DIB_MapColor( colors, nColors,
333 XGetPixel( bmpImage, x++, h )) << 4);
334 srcbits += linebytes;
335 bits = srcbits + (left >> 1);
340 /***********************************************************************
341 * X11DRV_DIB_SetImageBits_RLE4
343 * SetDIBits for a 4-bit deep compressed DIB.
345 static void X11DRV_DIB_SetImageBits_RLE4( int lines, const BYTE *bits,
346 DWORD width, DWORD dstwidth,
347 int left, int *colors,
348 XImage *bmpImage )
350 int x = 0, c, length;
351 const BYTE *begin = bits;
353 lines--;
355 while ((int)lines >= 0) {
356 length = *bits++;
357 if (length) { /* encoded */
358 c = *bits++;
359 while (length--) {
360 if(x >= width) {
361 x = 0;
362 if(--lines < 0)
363 return;
365 XPutPixel(bmpImage, x++, lines, colors[c >>4]);
366 if (length) {
367 length--;
368 if(x >= width) {
369 x = 0;
370 if(--lines < 0)
371 return;
373 XPutPixel(bmpImage, x++, lines, colors[c & 0xf]);
376 } else {
377 length = *bits++;
378 switch (length) {
379 case 0: /* eol */
380 x = 0;
381 lines--;
382 continue;
384 case 1: /* eopicture */
385 return;
387 case 2: /* delta */
388 x += *bits++;
389 if(x >= width) {
390 FIXME(x11drv, "x-delta is too large?\n");
391 return;
393 lines -= *bits++;
394 continue;
396 default: /* absolute */
397 while (length--) {
398 c = *bits++;
399 if(x >= width) {
400 x = 0;
401 if(--lines < 0)
402 return;
404 XPutPixel(bmpImage, x++, lines, colors[c >> 4]);
405 if (length) {
406 length--;
407 if(x >= width) {
408 x = 0;
409 if(--lines < 0)
410 return;
412 XPutPixel(bmpImage, x++, lines, colors[c & 0xf]);
415 if ((bits - begin) & 1)
416 bits++;
424 /***********************************************************************
425 * X11DRV_DIB_SetImageBits_8
427 * SetDIBits for an 8-bit deep DIB.
429 static void X11DRV_DIB_SetImageBits_8( int lines, const BYTE *srcbits,
430 DWORD srcwidth, DWORD dstwidth, int left,
431 int *colors, XImage *bmpImage )
433 DWORD x;
434 int h;
435 const BYTE *bits = srcbits + left;
437 /* align to 32 bit */
438 DWORD linebytes = (srcwidth + 3) & ~3;
440 dstwidth += left;
442 if (lines > 0) {
443 for (h = lines - 1; h >= 0; h--) {
444 for (x = left; x < dstwidth; x++, bits++) {
445 XPutPixel( bmpImage, x, h, colors[*bits] );
447 bits = (srcbits += linebytes) + left;
449 } else {
450 lines = -lines;
451 for (h = 0; h < lines; h++) {
452 for (x = left; x < dstwidth; x++, bits++) {
453 XPutPixel( bmpImage, x, h, colors[*bits] );
455 bits = (srcbits += linebytes) + left;
460 /***********************************************************************
461 * X11DRV_DIB_GetImageBits_8
463 * GetDIBits for an 8-bit deep DIB.
465 static void X11DRV_DIB_GetImageBits_8( int lines, BYTE *srcbits,
466 DWORD srcwidth, DWORD dstwidth, int left,
467 int *colors, int nColors, XImage *bmpImage )
469 DWORD x;
470 int h;
471 BYTE *bits = srcbits + left;
473 /* align to 32 bit */
474 DWORD linebytes = (srcwidth + 3) & ~3;
476 dstwidth += left;
478 if (lines > 0) {
479 for (h = lines - 1; h >= 0; h--) {
480 for (x = left; x < dstwidth; x++, bits++) {
481 if ( XGetPixel( bmpImage, x, h ) != colors[*bits] )
482 *bits = X11DRV_DIB_MapColor( colors, nColors,
483 XGetPixel( bmpImage, x, h ) );
485 bits = (srcbits += linebytes) + left;
487 } else {
488 lines = -lines;
489 for (h = 0; h < lines; h++) {
490 for (x = left; x < dstwidth; x++, bits++) {
491 if ( XGetPixel( bmpImage, x, h ) != colors[*bits] )
492 *bits = X11DRV_DIB_MapColor( colors, nColors,
493 XGetPixel( bmpImage, x, h ) );
495 bits = (srcbits += linebytes) + left;
500 /***********************************************************************
501 * X11DRV_DIB_SetImageBits_RLE8
503 * SetDIBits for an 8-bit deep compressed DIB.
505 * This function rewritten 941113 by James Youngman. WINE blew out when I
506 * first ran it because my desktop wallpaper is a (large) RLE8 bitmap.
508 * This was because the algorithm assumed that all RLE8 bitmaps end with the
509 * 'End of bitmap' escape code. This code is very much laxer in what it
510 * allows to end the expansion. Possibly too lax. See the note by
511 * case RleDelta. BTW, MS's documentation implies that a correct RLE8
512 * bitmap should end with RleEnd, but on the other hand, software exists
513 * that produces ones that don't and Windows 3.1 doesn't complain a bit
514 * about it.
516 * (No) apologies for my English spelling. [Emacs users: c-indent-level=4].
517 * James A. Youngman <mbcstjy@afs.man.ac.uk>
518 * [JAY]
521 enum Rle8_EscapeCodes
524 * Apologies for polluting your file's namespace...
526 RleEol = 0, /* End of line */
527 RleEnd = 1, /* End of bitmap */
528 RleDelta = 2 /* Delta */
531 static void X11DRV_DIB_SetImageBits_RLE8( int lines, const BYTE *bits,
532 DWORD width, DWORD dstwidth,
533 int left, int *colors,
534 XImage *bmpImage )
536 int x; /* X-positon on each line. Increases. */
537 int line; /* Line #. Starts at lines-1, decreases */
538 const BYTE *pIn = bits; /* Pointer to current position in bits */
539 BYTE length; /* The length pf a run */
540 BYTE color_index; /* index into colors[] as read from bits */
541 BYTE escape_code; /* See enum Rle8_EscapeCodes.*/
542 int color; /* value of colour[color_index] */
544 if (lines == 0) /* Let's hope this doesn't happen. */
545 return;
548 * Note that the bitmap data is stored by Windows starting at the
549 * bottom line of the bitmap and going upwards. Within each line,
550 * the data is stored left-to-right. That's the reason why line
551 * goes from lines-1 to 0. [JAY]
554 x = 0;
555 line = lines-1;
558 length = *pIn++;
561 * If the length byte is not zero (which is the escape value),
562 * We have a run of length pixels all the same colour. The colour
563 * index is stored next.
565 * If the length byte is zero, we need to read the next byte to
566 * know what to do. [JAY]
568 if (length != 0)
571 * [Run-Length] Encoded mode
573 color_index = (*pIn++); /* Get the colour index. */
574 color = colors[color_index];
576 while(length--)
577 XPutPixel(bmpImage, x++, line, color);
579 else
582 * Escape codes (may be an absolute sequence though)
584 escape_code = (*pIn++);
585 switch(escape_code)
587 case RleEol: /* =0, end of line */
589 x = 0;
590 line--;
591 break;
594 case RleEnd: /* =1, end of bitmap */
597 * Not all RLE8 bitmaps end with this
598 * code. For example, Paint Shop Pro
599 * produces some that don't. That's (I think)
600 * what caused the previous implementation to
601 * fail. [JAY]
603 line=-1; /* Cause exit from do loop. */
604 break;
607 case RleDelta: /* =2, a delta */
610 * Note that deltaing to line 0
611 * will cause an exit from the loop,
612 * which may not be what is intended.
613 * The fact that there is a delta in the bits
614 * almost certainly implies that there is data
615 * to follow. You may feel that we should
616 * jump to the top of the loop to avoid exiting
617 * in this case.
619 * TODO: Decide what to do here in that case. [JAY]
621 x += (*pIn++);
622 line -= (*pIn++);
623 if (line == 0)
625 TRACE(bitmap, "Delta to last line of bitmap "
626 "(wrongly?) causes loop exit\n");
628 break;
631 default: /* >2, switch to absolute mode */
634 * Absolute Mode
636 length = escape_code;
637 while(length--)
639 color_index = (*pIn++);
640 XPutPixel(bmpImage, x++, line,
641 colors[color_index]);
645 * If you think for a moment you'll realise that the
646 * only time we could ever possibly read an odd
647 * number of bytes is when there is a 0x00 (escape),
648 * a value >0x02 (absolute mode) and then an odd-
649 * length run. Therefore this is the only place we
650 * need to worry about it. Everywhere else the
651 * bytes are always read in pairs. [JAY]
653 if (escape_code & 1)
654 pIn++; /* Throw away the pad byte. */
655 break;
657 } /* switch (escape_code) : Escape sequence */
658 } /* process either an encoded sequence or an escape sequence */
660 /* We expect to come here more than once per line. */
661 } while (line >= 0); /* Do this until the bitmap is filled */
664 * Everybody comes here at the end.
665 * Check how we exited the loop and print a message if it's a bit odd.
666 * [JAY]
668 if ( (*(pIn-2) != 0/*escape*/) || (*(pIn-1)!= RleEnd) )
670 TRACE(bitmap, "End-of-bitmap "
671 "without (strictly) proper escape code. Last two "
672 "bytes were: %02X %02X.\n",
673 (int)*(pIn-2),
674 (int)*(pIn-1));
679 /***********************************************************************
680 * X11DRV_DIB_SetImageBits_16
682 * SetDIBits for a 16-bit deep DIB.
684 static void X11DRV_DIB_SetImageBits_16( int lines, const BYTE *srcbits,
685 DWORD srcwidth, DWORD dstwidth, int left,
686 DC *dc, XImage *bmpImage )
688 DWORD x;
689 LPWORD ptr;
690 WORD val;
691 int h;
692 BYTE r, g, b;
694 /* align to 32 bit */
695 DWORD linebytes = (srcwidth * 2 + 3) & ~3;
697 dstwidth += left;
699 ptr = (LPWORD) srcbits + left;
700 if (lines > 0) {
701 for (h = lines - 1; h >= 0; h--) {
702 for (x = left; x < dstwidth; x++, ptr++) {
703 val = *ptr;
704 r = (BYTE) ((val & 0x7c00) >> 7);
705 g = (BYTE) ((val & 0x03e0) >> 2);
706 b = (BYTE) ((val & 0x001f) << 3);
707 XPutPixel( bmpImage, x, h,
708 COLOR_ToPhysical(dc, RGB(r,g,b)) );
710 ptr = (LPWORD) (srcbits += linebytes) + left;
712 } else {
713 lines = -lines;
714 for (h = 0; h < lines; h++) {
715 for (x = left; x < dstwidth; x++, ptr++) {
716 val = *ptr;
717 r = (BYTE) ((val & 0x7c00) >> 7);
718 g = (BYTE) ((val & 0x03e0) >> 2);
719 b = (BYTE) ((val & 0x001f) << 3);
720 XPutPixel( bmpImage, x, h,
721 COLOR_ToPhysical(dc, RGB(r,g,b)) );
723 ptr = (LPWORD) (srcbits += linebytes) + left;
729 /***********************************************************************
730 * X11DRV_DIB_GetImageBits_16
732 * GetDIBits for an 16-bit deep DIB.
734 static void X11DRV_DIB_GetImageBits_16( int lines, BYTE *srcbits,
735 DWORD srcwidth, DWORD dstwidth, int left,
736 XImage *bmpImage )
738 DWORD x;
739 LPWORD ptr;
740 int h;
741 BYTE r, g, b;
743 /* align to 32 bit */
744 DWORD linebytes = (srcwidth * 2 + 3) & ~3;
746 dstwidth += left;
748 ptr = (LPWORD) srcbits + left;
749 if (lines > 0) {
750 for (h = lines - 1; h >= 0; h--)
752 for (x = left; x < dstwidth; x++, ptr++)
754 COLORREF pixel = COLOR_ToLogical( XGetPixel( bmpImage, x, h ) );
755 r = (BYTE) GetRValue(pixel);
756 g = (BYTE) GetGValue(pixel);
757 b = (BYTE) GetBValue(pixel);
758 *ptr = ( ((r << 7) & 0x7c00) | ((g << 2) & 0x03e0) | ((b >> 3) & 0x001f) );
760 ptr = (LPWORD) (srcbits += linebytes) + left;
762 } else {
763 lines = -lines;
764 for (h = 0; h < lines; h++)
766 for (x = left; x < dstwidth; x++, ptr++)
768 COLORREF pixel = COLOR_ToLogical( XGetPixel( bmpImage, x, h ) );
769 r = (BYTE) GetRValue(pixel);
770 g = (BYTE) GetGValue(pixel);
771 b = (BYTE) GetBValue(pixel);
772 *ptr = ( ((r << 7) & 0x7c00) | ((g << 2) & 0x03e0) | ((b >> 3) & 0x001f) );
775 ptr = (LPWORD) (srcbits += linebytes) + left;
782 /***********************************************************************
783 * X11DRV_DIB_SetImageBits_24
785 * SetDIBits for a 24-bit deep DIB.
787 static void X11DRV_DIB_SetImageBits_24( int lines, const BYTE *srcbits,
788 DWORD srcwidth, DWORD dstwidth, int left,
789 DC *dc, XImage *bmpImage )
791 DWORD x;
792 const BYTE *bits = srcbits + left * 3;
793 int h;
795 /* align to 32 bit */
796 DWORD linebytes = (srcwidth * 3 + 3) & ~3;
798 dstwidth += left;
800 /* "bits" order is reversed for some reason */
802 if (lines > 0) {
803 for (h = lines - 1; h >= 0; h--) {
804 for (x = left; x < dstwidth; x++, bits += 3) {
805 XPutPixel( bmpImage, x, h,
806 COLOR_ToPhysical(dc, RGB(bits[2],bits[1],bits[0])));
808 bits = (srcbits += linebytes) + left * 3;
810 } else {
811 lines = -lines;
812 for (h = 0; h < lines; h++) {
813 for (x = left; x < dstwidth; x++, bits += 3) {
814 XPutPixel( bmpImage, x, h,
815 COLOR_ToPhysical(dc, RGB(bits[2],bits[1],bits[0])));
817 bits = (srcbits += linebytes) + left * 3;
823 /***********************************************************************
824 * X11DRV_DIB_GetImageBits_24
826 * GetDIBits for an 24-bit deep DIB.
828 static void X11DRV_DIB_GetImageBits_24( int lines, BYTE *srcbits,
829 DWORD srcwidth, DWORD dstwidth, int left,
830 XImage *bmpImage )
832 DWORD x;
833 int h;
834 BYTE *bits = srcbits + (left * 3);
836 /* align to 32 bit */
837 DWORD linebytes = (srcwidth * 3 + 3) & ~3;
839 dstwidth += left;
841 if (lines > 0) {
842 for (h = lines - 1; h >= 0; h--)
844 for (x = left; x < dstwidth; x++, bits += 3)
846 COLORREF pixel = COLOR_ToLogical( XGetPixel( bmpImage, x, h ) );
847 bits[0] = GetRValue(pixel);
848 bits[1] = GetGValue(pixel);
849 bits[2] = GetBValue(pixel);
851 bits = (srcbits += linebytes) + (left * 3);
853 } else {
854 lines = -lines;
855 for (h = 0; h < lines; h++)
857 for (x = left; x < dstwidth; x++, bits += 3)
859 COLORREF pixel = COLOR_ToLogical( XGetPixel( bmpImage, x, h ) );
860 bits[0] = GetRValue(pixel);
861 bits[1] = GetGValue(pixel);
862 bits[2] = GetBValue(pixel);
865 bits = (srcbits += linebytes) + (left * 3);
871 /***********************************************************************
872 * X11DRV_DIB_SetImageBits_32
874 * SetDIBits for a 32-bit deep DIB.
876 static void X11DRV_DIB_SetImageBits_32( int lines, const BYTE *srcbits,
877 DWORD srcwidth, DWORD dstwidth, int left,
878 DC *dc, XImage *bmpImage )
880 DWORD x;
881 const BYTE *bits = srcbits + left * 4;
882 int h;
884 DWORD linebytes = (srcwidth * 4);
886 dstwidth += left;
888 if (lines > 0) {
889 for (h = lines - 1; h >= 0; h--) {
890 for (x = left; x < dstwidth; x++, bits += 4) {
891 XPutPixel( bmpImage, x, h,
892 COLOR_ToPhysical(dc, RGB(bits[2],bits[1],bits[0])));
894 bits = (srcbits += linebytes) + left * 4;
896 } else {
897 lines = -lines;
898 for (h = 0; h < lines; h++) {
899 for (x = left; x < dstwidth; x++, bits += 4) {
900 XPutPixel( bmpImage, x, h,
901 COLOR_ToPhysical(dc, RGB(bits[2],bits[1],bits[0])));
903 bits = (srcbits += linebytes) + left * 4;
909 /***********************************************************************
910 * X11DRV_DIB_GetImageBits_32
912 * GetDIBits for an 32-bit deep DIB.
914 static void X11DRV_DIB_GetImageBits_32( int lines, BYTE *srcbits,
915 DWORD srcwidth, DWORD dstwidth, int left,
916 XImage *bmpImage )
918 DWORD x;
919 int h;
920 BYTE *bits = srcbits + (left * 4);
922 /* align to 32 bit */
923 DWORD linebytes = (srcwidth * 4);
925 dstwidth += left;
927 if (lines > 0) {
928 for (h = lines - 1; h >= 0; h--)
930 for (x = left; x < dstwidth; x++, bits += 4)
932 COLORREF pixel = COLOR_ToLogical( XGetPixel( bmpImage, x, h ) );
933 bits[0] = GetRValue(pixel);
934 bits[1] = GetGValue(pixel);
935 bits[2] = GetBValue(pixel);
937 bits = (srcbits += linebytes) + (left * 4);
939 } else {
940 lines = -lines;
941 for (h = 0; h < lines; h++)
943 for (x = left; x < dstwidth; x++, bits += 4)
945 COLORREF pixel = COLOR_ToLogical( XGetPixel( bmpImage, x, h ) );
946 bits[0] = GetRValue(pixel);
947 bits[1] = GetGValue(pixel);
948 bits[2] = GetBValue(pixel);
951 bits = (srcbits += linebytes) + (left * 4);
957 /***********************************************************************
958 * X11DRV_DIB_SetImageBits
960 * Transfer the bits to an X image.
961 * Helper function for SetDIBits() and SetDIBitsToDevice().
962 * The Xlib critical section must be entered before calling this function.
964 int X11DRV_DIB_SetImageBits( const DIB_SETIMAGEBITS_DESCR *descr )
966 int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
967 XImage *bmpImage;
969 if ( descr->dc && descr->dc->w.flags & DC_DIRTY )
970 CLIPPING_UpdateGCRegion( descr->dc );
972 if (descr->image)
973 bmpImage = descr->image;
974 else {
975 bmpImage = XCreateImage( display,
976 DefaultVisualOfScreen(X11DRV_GetXScreen()),
977 descr->depth, ZPixmap, 0, NULL,
978 descr->infoWidth, lines, 32, 0 );
979 bmpImage->data = xcalloc( bmpImage->bytes_per_line * lines );
982 /* Transfer the pixels */
983 switch(descr->infoBpp)
985 case 1:
986 X11DRV_DIB_SetImageBits_1( descr->lines, descr->bits, descr->infoWidth,
987 descr->width, descr->xSrc, descr->colorMap,
988 bmpImage );
989 break;
990 case 4:
991 if (descr->compression)
992 X11DRV_DIB_SetImageBits_RLE4( descr->lines, descr->bits,
993 descr->infoWidth, descr->width,
994 descr->xSrc, descr->colorMap,
995 bmpImage );
996 else
997 X11DRV_DIB_SetImageBits_4( descr->lines, descr->bits,
998 descr->infoWidth, descr->width,
999 descr->xSrc, descr->colorMap,
1000 bmpImage );
1001 break;
1002 case 8:
1003 if (descr->compression)
1004 X11DRV_DIB_SetImageBits_RLE8( descr->lines, descr->bits,
1005 descr->infoWidth, descr->width,
1006 descr->xSrc,
1007 descr->colorMap, bmpImage );
1008 else
1009 X11DRV_DIB_SetImageBits_8( descr->lines, descr->bits,
1010 descr->infoWidth, descr->width,
1011 descr->xSrc, descr->colorMap,
1012 bmpImage );
1013 break;
1014 case 15:
1015 case 16:
1016 X11DRV_DIB_SetImageBits_16( descr->lines, descr->bits,
1017 descr->infoWidth, descr->width,
1018 descr->xSrc, descr->dc, bmpImage);
1019 break;
1020 case 24:
1021 X11DRV_DIB_SetImageBits_24( descr->lines, descr->bits,
1022 descr->infoWidth, descr->width,
1023 descr->xSrc, descr->dc, bmpImage );
1024 break;
1025 case 32:
1026 X11DRV_DIB_SetImageBits_32( descr->lines, descr->bits,
1027 descr->infoWidth, descr->width,
1028 descr->xSrc, descr->dc, bmpImage);
1029 break;
1030 default:
1031 WARN(bitmap, "(%d): Invalid depth\n", descr->infoBpp );
1032 break;
1035 XPutImage( display, descr->drawable, descr->gc, bmpImage,
1036 descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
1037 descr->width, descr->height );
1039 if (!descr->image) XDestroyImage( bmpImage );
1040 return lines;
1043 /***********************************************************************
1044 * X11DRV_DIB_GetImageBits
1046 * Transfer the bits from an X image.
1047 * The Xlib critical section must be entered before calling this function.
1049 int X11DRV_DIB_GetImageBits( const DIB_SETIMAGEBITS_DESCR *descr )
1051 int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
1052 XImage *bmpImage;
1054 if (descr->image)
1055 bmpImage = descr->image;
1056 else {
1057 bmpImage = XCreateImage( display,
1058 DefaultVisualOfScreen(X11DRV_GetXScreen()),
1059 descr->depth, ZPixmap, 0, NULL,
1060 descr->infoWidth, lines, 32, 0 );
1061 bmpImage->data = xcalloc( bmpImage->bytes_per_line * lines );
1064 XGetSubImage( display, descr->drawable, descr->xDest, descr->yDest,
1065 descr->width, descr->height, AllPlanes, ZPixmap,
1066 bmpImage, descr->xSrc, descr->ySrc );
1068 /* Transfer the pixels */
1069 switch(descr->infoBpp)
1071 case 1:
1072 FIXME(bitmap, "Depth 1 not yet supported!\n");
1073 break;
1075 case 4:
1076 if (descr->compression)
1077 FIXME(bitmap, "Compression not yet supported!\n");
1078 else
1079 X11DRV_DIB_GetImageBits_4( descr->lines,
1080 (LPVOID)descr->bits, descr->infoWidth,
1081 descr->width, descr->xSrc,
1082 descr->colorMap, descr->nColorMap,
1083 bmpImage );
1084 break;
1086 case 8:
1087 if (descr->compression)
1088 FIXME(bitmap, "Compression not yet supported!\n");
1089 else
1090 X11DRV_DIB_GetImageBits_8( descr->lines, (LPVOID)descr->bits,
1091 descr->infoWidth, descr->width,
1092 descr->xSrc, descr->colorMap,
1093 descr->nColorMap, bmpImage );
1094 break;
1096 case 15:
1097 case 16:
1098 X11DRV_DIB_GetImageBits_16( descr->lines, (LPVOID)descr->bits,
1099 descr->infoWidth,
1100 descr->width, descr->xSrc, bmpImage );
1101 break;
1103 case 24:
1104 X11DRV_DIB_GetImageBits_24( descr->lines, (LPVOID)descr->bits,
1105 descr->infoWidth,
1106 descr->width, descr->xSrc, bmpImage );
1107 break;
1109 case 32:
1110 X11DRV_DIB_GetImageBits_32( descr->lines, (LPVOID)descr->bits,
1111 descr->infoWidth,
1112 descr->width, descr->xSrc, bmpImage );
1113 break;
1115 default:
1116 WARN(bitmap, "(%d): Invalid depth\n", descr->infoBpp );
1117 break;
1120 if (!descr->image) XDestroyImage( bmpImage );
1121 return lines;
1124 /*************************************************************************
1125 * X11DRV_SetDIBitsToDevice
1128 INT X11DRV_SetDIBitsToDevice( DC *dc, INT xDest, INT yDest, DWORD cx,
1129 DWORD cy, INT xSrc, INT ySrc,
1130 UINT startscan, UINT lines, LPCVOID bits,
1131 const BITMAPINFO *info, UINT coloruse )
1133 DIB_SETIMAGEBITS_DESCR descr;
1134 DWORD width, oldcy = cy;
1135 INT result;
1136 int height, tmpheight;
1137 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
1140 if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height,
1141 &descr.infoBpp, &descr.compression ) == -1)
1142 return 0;
1143 tmpheight = height;
1144 if (height < 0) height = -height;
1145 if (!lines || (startscan >= height)) return 0;
1146 if (startscan + lines > height) lines = height - startscan;
1147 if (ySrc < startscan) ySrc = startscan;
1148 else if (ySrc >= startscan + lines) return 0;
1149 if (xSrc >= width) return 0;
1150 if (ySrc + cy >= startscan + lines) cy = startscan + lines - ySrc;
1151 if (xSrc + cx >= width) cx = width - xSrc;
1152 if (!cx || !cy) return 0;
1154 X11DRV_SetupGCForText( dc ); /* To have the correct colors */
1155 TSXSetFunction(display, physDev->gc, X11DRV_XROPfunction[dc->w.ROPmode-1]);
1157 if (descr.infoBpp <= 8)
1159 descr.colorMap = X11DRV_DIB_BuildColorMap( dc, coloruse,
1160 dc->w.bitsPerPixel,
1161 info, &descr.nColorMap );
1162 if (!descr.colorMap)
1163 return 0;
1166 descr.dc = dc;
1167 descr.bits = bits;
1168 descr.image = NULL;
1169 descr.lines = tmpheight >= 0 ? lines : -lines;
1170 descr.infoWidth = width;
1171 descr.depth = dc->w.bitsPerPixel;
1172 descr.drawable = physDev->drawable;
1173 descr.gc = physDev->gc;
1174 descr.xSrc = xSrc;
1175 descr.ySrc = tmpheight >= 0 ? lines-(ySrc-startscan)-cy+(oldcy-cy)
1176 : ySrc - startscan;
1177 descr.xDest = dc->w.DCOrgX + XLPTODP( dc, xDest );
1178 descr.yDest = dc->w.DCOrgY + YLPTODP( dc, yDest ) +
1179 (tmpheight >= 0 ? oldcy-cy : 0);
1180 descr.width = cx;
1181 descr.height = cy;
1183 EnterCriticalSection( &X11DRV_CritSection );
1184 result = CALL_LARGE_STACK( X11DRV_DIB_SetImageBits, &descr );
1185 LeaveCriticalSection( &X11DRV_CritSection );
1187 HeapFree(GetProcessHeap(), 0, descr.colorMap);
1188 return result;
1191 #endif /* !defined(X_DISPLAY_MISSING) */