- New implementation of SendMessage, ReceiveMessage, ReplyMessage functions
[wine] / graphics / x11drv / dib.c
1 /*
2  * X11DRV device-independent bitmaps
3  *
4  * Copyright 1993,1994  Alexandre Julliard
5  */
6
7 #include "config.h"
8
9 #ifndef X_DISPLAY_MISSING
10
11 #include "ts_xlib.h"
12 #include "ts_xutil.h"
13
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"
22
23 static int bitmapDepthTable[] = { 8, 1, 32, 16, 24, 15, 4, 0 };
24 static int ximageDepthTable[] = { 0, 0, 0,  0,  0,  0,  0 };
25
26 /***********************************************************************
27  *           X11DRV_DIB_Init
28  */
29 BOOL32 X11DRV_DIB_Init(void)
30 {
31     int         i;
32     XImage*     testimage;
33
34     for( i = 0; bitmapDepthTable[i]; i++ )
35     {
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);
41     }
42     return TRUE;
43 }
44
45
46 /***********************************************************************
47  *           X11DRV_DIB_GetXImageWidthBytes
48  *
49  * Return the width of an X image in bytes
50  */
51 int X11DRV_DIB_GetXImageWidthBytes( int width, int depth )
52 {
53     int         i;
54
55     if (!ximageDepthTable[0]) {
56             X11DRV_DIB_Init();
57     }
58     for( i = 0; bitmapDepthTable[i] ; i++ )
59          if( bitmapDepthTable[i] == depth )
60              return (4 * ((width * ximageDepthTable[i] + 31)/32));
61     
62     WARN(bitmap, "(%d): Unsupported depth\n", depth );
63     return (4 * width);
64 }
65
66 /***********************************************************************
67  *           X11DRV_DIB_BuildColorMap
68  *
69  * Build the color map from the bitmap palette. Should not be called
70  * for a >8-bit deep bitmap.
71  */
72 int *X11DRV_DIB_BuildColorMap( DC *dc, WORD coloruse, WORD depth, 
73                                const BITMAPINFO *info, int *nColors )
74 {
75     int i, colors;
76     BOOL32 isInfo;
77     WORD *colorPtr;
78     int *colorMapping;
79
80     if ((isInfo = (info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))))
81     {
82         colors = info->bmiHeader.biClrUsed;
83         if (!colors) colors = 1 << info->bmiHeader.biBitCount;
84         colorPtr = (WORD *)info->bmiColors;
85     }
86     else  /* assume BITMAPCOREINFO */
87     {
88         colors = 1 << ((BITMAPCOREHEADER *)&info->bmiHeader)->bcBitCount;
89         colorPtr = (WORD *)((BITMAPCOREINFO *)info)->bmciColors;
90     }
91
92     if (colors > 256)
93     {
94         ERR(bitmap, "called with >256 colors!\n");
95         return NULL;
96     }
97
98     if (!(colorMapping = (int *)HeapAlloc(GetProcessHeap(), 0,
99                                           colors * sizeof(int) ))) 
100         return NULL;
101
102     if (coloruse == DIB_RGB_COLORS)
103     {
104         if (isInfo)
105         {
106             RGBQUAD * rgb = (RGBQUAD *)colorPtr;
107
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));
117         }
118         else
119         {
120             RGBTRIPLE * rgb = (RGBTRIPLE *)colorPtr;
121
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));
131         }
132     }
133     else  /* DIB_PAL_COLORS */
134     {
135         for (i = 0; i < colors; i++, colorPtr++)
136             colorMapping[i] = COLOR_ToPhysical( dc, PALETTEINDEX(*colorPtr) );
137     }
138
139     *nColors = colors;
140     return colorMapping;
141 }
142
143
144 /***********************************************************************
145  *           X11DRV_DIB_MapColor
146  */
147 int X11DRV_DIB_MapColor( int *physMap, int nPhysMap, int phys )
148 {
149     int color;
150
151     for (color = 0; color < nPhysMap; color++)
152         if (physMap[color] == phys)
153             return color;
154
155     WARN(bitmap, "Strange color %08x\n", phys);
156     return 0;
157 }
158
159
160
161 /***********************************************************************
162  *           X11DRV_DIB_SetImageBits_1_Line
163  *
164  * Handles a single line of 1 bit data.
165  */
166 static void X11DRV_DIB_SetImageBits_1_Line(DWORD dstwidth, int left, int *colors,
167                                     XImage *bmpImage, int h, const BYTE *bits)
168 {
169     BYTE pix, extra;
170     DWORD i, x;
171
172     if((extra = (left & 7)) != 0) {
173         left &= ~7;
174         dstwidth += extra;
175     }
176
177     bits += left >> 3;
178
179     /* FIXME: should avoid putting x<left pixels (minor speed issue) */
180     for (i = dstwidth/8, x = left; i > 0; i--)
181     {
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] );
191     }
192     pix = *bits;
193     switch(dstwidth & 7)
194     {
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] );
202     }
203 }
204
205 /***********************************************************************
206  *           X11DRV_DIB_SetImageBits_1
207  *
208  * SetDIBits for a 1-bit deep DIB.
209  */
210 static void X11DRV_DIB_SetImageBits_1( int lines, const BYTE *srcbits,
211                                 DWORD srcwidth, DWORD dstwidth, int left,
212                                 int *colors, XImage *bmpImage )
213 {
214     int h;
215
216     /* 32 bit aligned */
217     DWORD linebytes = ((srcwidth + 31) & ~31) / 8;
218
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;
224         }
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;
231         }
232     }
233 }
234
235
236 /***********************************************************************
237  *           X11DRV_DIB_SetImageBits_4
238  *
239  * SetDIBits for a 4-bit deep DIB.
240  */
241 static void X11DRV_DIB_SetImageBits_4( int lines, const BYTE *srcbits,
242                                 DWORD srcwidth, DWORD dstwidth, int left,
243                                 int *colors, XImage *bmpImage )
244 {
245     DWORD i, x;
246     int h;
247     const BYTE *bits = srcbits + (left >> 1);
248   
249     /* 32 bit aligned */
250     DWORD linebytes = ((srcwidth+7)&~7)/2;
251
252     if(left & 1) {
253         left--;
254         dstwidth++;
255     }
256
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] );
263             }
264             if (dstwidth & 1) XPutPixel( bmpImage, x, h, colors[*bits >> 4] );
265             srcbits += linebytes;
266             bits         = srcbits + (left >> 1);
267         }
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] );
275             }
276             if (dstwidth & 1) XPutPixel( bmpImage, x, h, colors[*bits >> 4] );
277             srcbits += linebytes;
278             bits         = srcbits + (left >> 1);
279         }
280     }
281 }
282
283
284
285 /***********************************************************************
286  *           X11DRV_DIB_GetImageBits_4
287  *
288  * GetDIBits for a 4-bit deep DIB.
289  */
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 )
293 {
294     DWORD i, x;
295     int h;
296     BYTE *bits = srcbits + (left >> 1);
297
298     /* 32 bit aligned */
299     DWORD linebytes = ((srcwidth+7)&~7)/2;
300
301     if(left & 1) {
302         left--;
303         dstwidth++;
304     }
305
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);
314            }
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);
320        }
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);
330            }
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);
336        }
337     }
338 }
339
340 /***********************************************************************
341  *           X11DRV_DIB_SetImageBits_RLE4
342  *
343  * SetDIBits for a 4-bit deep compressed DIB.
344  */
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 )
349 {
350     int x = 0, c, length;
351     const BYTE *begin = bits;
352
353     lines--;
354
355     while ((int)lines >= 0) {
356         length = *bits++;
357         if (length) {   /* encoded */
358             c = *bits++;
359             while (length--) {
360                 XPutPixel(bmpImage, x++, lines, colors[c >>4]);
361                 if(x >= width) {
362                     x = 0;
363                     if(--lines < 0)
364                         return;
365                 }
366                 if (length) {
367                     length--;
368                     XPutPixel(bmpImage, x++, lines, colors[c & 0xf]);
369                     if(x >= width) {
370                         x = 0;
371                         if(--lines < 0)
372                             return;
373                     }
374                 }
375             }
376         } else {
377             length = *bits++;
378             switch (length) {
379             case 0: /* eol */
380                 x = 0;
381                 lines--;
382                 continue;
383
384             case 1: /* eopicture */
385                 return;
386
387             case 2: /* delta */
388                 x += *bits++;
389                 if(x >= width) {
390                    FIXME(x11drv, "x-delta is too large?\n");
391                    return;
392                 }
393                 lines -= *bits++;
394                 continue;
395
396             default: /* absolute */
397                 while (length--) {
398                     c = *bits++;
399                     XPutPixel(bmpImage, x++, lines, colors[c >> 4]);
400                     if(x >= width) {
401                         x = 0;
402                         if(--lines < 0)
403                             return;
404                     }
405                     if (length) {
406                         length--;
407                         XPutPixel(bmpImage, x++, lines, colors[c & 0xf]);
408                         if(x >= width) {
409                             x = 0;
410                             if(--lines < 0)
411                                 return;
412                         }
413                     }
414                 }
415                 if ((bits - begin) & 1)
416                     bits++;
417             }
418         }
419     }
420 }
421
422
423
424 /***********************************************************************
425  *           X11DRV_DIB_SetImageBits_8
426  *
427  * SetDIBits for an 8-bit deep DIB.
428  */
429 static void X11DRV_DIB_SetImageBits_8( int lines, const BYTE *srcbits,
430                                 DWORD srcwidth, DWORD dstwidth, int left,
431                                 int *colors, XImage *bmpImage )
432 {
433     DWORD x;
434     int h;
435     const BYTE *bits = srcbits + left;
436
437     /* align to 32 bit */
438     DWORD linebytes = (srcwidth + 3) & ~3;
439
440     dstwidth += left;
441
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] );
446             }
447             bits = (srcbits += linebytes) + left;
448         }
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] );
454             }
455             bits = (srcbits += linebytes) + left;
456         }
457     }
458 }
459
460 /***********************************************************************
461  *           X11DRV_DIB_GetImageBits_8
462  *
463  * GetDIBits for an 8-bit deep DIB.
464  */
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 )
468 {
469     DWORD x;
470     int h;
471     BYTE *bits = srcbits + left;
472
473     /* align to 32 bit */
474     DWORD linebytes = (srcwidth + 3) & ~3;
475
476     dstwidth += left;
477
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 ) );
484            }
485            bits = (srcbits += linebytes) + left;
486        }
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 ) );
494            }
495            bits = (srcbits += linebytes) + left;
496        }
497     }
498 }
499
500 /***********************************************************************
501  *            X11DRV_DIB_SetImageBits_RLE8
502  *
503  * SetDIBits for an 8-bit deep compressed DIB.
504  *
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.  
507  *
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.
515  *
516  * (No) apologies for my English spelling.  [Emacs users: c-indent-level=4].
517  *                      James A. Youngman <mbcstjy@afs.man.ac.uk>
518  *                                              [JAY]
519  */
520
521 enum Rle8_EscapeCodes           
522 {
523   /* 
524    * Apologies for polluting your file's namespace...
525    */
526   RleEol        = 0,            /* End of line */
527   RleEnd        = 1,            /* End of bitmap */
528   RleDelta      = 2             /* Delta */
529 };
530   
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 )
535 {
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] */
543     
544     if (lines == 0)             /* Let's hope this doesn't happen. */
545       return;
546     
547     /*
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]
552      */
553     
554     x = 0;
555     line = lines-1;
556     do
557       {
558           length = *pIn++;
559           
560           /* 
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. 
564            *
565            * If the length byte is zero, we need to read the next byte to
566            * know what to do.                   [JAY]
567            */
568           if (length != 0) 
569             {                                   
570                 /* 
571                  * [Run-Length] Encoded mode 
572                  */
573                 color_index = (*pIn++); /* Get the colour index. */
574                 color = colors[color_index];
575
576                 while(length--)
577                   XPutPixel(bmpImage, x++, line, color);
578             }
579           else 
580             {    
581                 /* 
582                  * Escape codes (may be an absolute sequence though)
583                  */
584                 escape_code = (*pIn++);
585                 switch(escape_code)
586                   {
587                     case RleEol: /* =0, end of line */
588                       {
589                           x = 0;  
590                           line--;  
591                           break;
592                       }
593                       
594                     case RleEnd: /* =1, end of bitmap */
595                       {
596                           /*
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]
602                            */
603                           line=-1; /* Cause exit from do loop. */
604                           break;
605                       }
606                       
607                     case RleDelta: /* =2, a delta */
608                       {
609                           /* 
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.  
618                            *
619                            * TODO: Decide what to do here in that case. [JAY]
620                            */
621                           x     += (*pIn++); 
622                           line  -= (*pIn++);
623                           if (line == 0)
624                             {
625                               TRACE(bitmap, "Delta to last line of bitmap "
626                                            "(wrongly?) causes loop exit\n");
627                             }
628                           break;
629                       }
630                       
631                     default:    /* >2, switch to absolute mode */
632                       {
633                           /* 
634                            * Absolute Mode 
635                            */
636                           length = escape_code;
637                           while(length--)
638                             {
639                                 color_index = (*pIn++);
640                                 XPutPixel(bmpImage, x++, line, 
641                                           colors[color_index]);
642                             }
643                           
644                           /*
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]
652                            */
653                           if (escape_code & 1) 
654                             pIn++; /* Throw away the pad byte. */
655                           break;
656                       }
657                   } /* switch (escape_code) : Escape sequence */
658             }  /* process either an encoded sequence or an escape sequence */
659           
660           /* We expect to come here more than once per line. */
661       } while (line >= 0);  /* Do this until the bitmap is filled */
662     
663     /*
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]
667      */
668     if ( (*(pIn-2) != 0/*escape*/) || (*(pIn-1)!= RleEnd) )
669       {
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));           
675       }
676 }  
677
678
679 /***********************************************************************
680  *           X11DRV_DIB_SetImageBits_16
681  *
682  * SetDIBits for a 16-bit deep DIB.
683  */
684 static void X11DRV_DIB_SetImageBits_16( int lines, const BYTE *srcbits,
685                                  DWORD srcwidth, DWORD dstwidth, int left,
686                                  DC *dc, XImage *bmpImage )
687 {
688     DWORD x;
689     LPWORD ptr;
690     WORD val;
691     int h;
692     BYTE r, g, b;
693   
694     /* align to 32 bit */
695     DWORD linebytes = (srcwidth * 2 + 3) & ~3;
696
697     dstwidth += left;
698
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)) );
709             }
710             ptr = (LPWORD) (srcbits += linebytes) + left;
711         }
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)) );
722             }
723             ptr = (LPWORD) (srcbits += linebytes) + left;
724         }
725     }
726 }
727
728
729 /***********************************************************************
730  *           X11DRV_DIB_GetImageBits_16
731  *
732  * GetDIBits for an 16-bit deep DIB.
733  */
734 static void X11DRV_DIB_GetImageBits_16( int lines, BYTE *srcbits,
735                                  DWORD srcwidth, DWORD dstwidth, int left,
736                                  XImage *bmpImage )
737 {
738     DWORD x;
739     LPWORD ptr;
740     int h;
741     BYTE r, g, b;
742
743     /* align to 32 bit */
744     DWORD linebytes = (srcwidth * 2 + 3) & ~3;
745
746     dstwidth += left;
747
748     ptr = (LPWORD) srcbits + left;
749     if (lines > 0) {
750        for (h = lines - 1; h >= 0; h--)
751         {
752            for (x = left; x < dstwidth; x++, ptr++)
753             {
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) );
759            }
760            ptr = (LPWORD) (srcbits += linebytes) + left;
761        }
762     } else {
763        lines = -lines;
764        for (h = 0; h < lines; h++)
765         {
766            for (x = left; x < dstwidth; x++, ptr++)
767             {
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) );
773            }
774
775            ptr = (LPWORD) (srcbits += linebytes) + left;
776        }
777     }
778 }
779
780
781
782 /***********************************************************************
783  *           X11DRV_DIB_SetImageBits_24
784  *
785  * SetDIBits for a 24-bit deep DIB.
786  */
787 static void X11DRV_DIB_SetImageBits_24( int lines, const BYTE *srcbits,
788                                  DWORD srcwidth, DWORD dstwidth, int left,
789                                  DC *dc, XImage *bmpImage )
790 {
791     DWORD x;
792     const BYTE *bits = srcbits + left * 3;
793     int h;
794   
795     /* align to 32 bit */
796     DWORD linebytes = (srcwidth * 3 + 3) & ~3;
797
798     dstwidth += left;
799
800     /* "bits" order is reversed for some reason */
801
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])));
807             }
808             bits = (srcbits += linebytes) + left * 3;
809         }
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])));
816             }
817             bits = (srcbits += linebytes) + left * 3;
818         }
819     }
820 }
821
822
823 /***********************************************************************
824  *           X11DRV_DIB_GetImageBits_24
825  *
826  * GetDIBits for an 24-bit deep DIB.
827  */
828 static void X11DRV_DIB_GetImageBits_24( int lines, BYTE *srcbits,
829                                  DWORD srcwidth, DWORD dstwidth, int left,
830                                  XImage *bmpImage )
831 {
832     DWORD x;
833     int h;
834     BYTE *bits = srcbits + (left * 3);
835
836     /* align to 32 bit */
837     DWORD linebytes = (srcwidth * 3 + 3) & ~3;
838
839     dstwidth += left;
840
841     if (lines > 0) {
842        for (h = lines - 1; h >= 0; h--)
843         {
844            for (x = left; x < dstwidth; x++, bits += 3)
845             {
846                 COLORREF pixel = COLOR_ToLogical( XGetPixel( bmpImage, x, h ) );
847                 bits[0] = GetRValue(pixel);
848                 bits[1] = GetGValue(pixel);
849                 bits[2] = GetBValue(pixel);
850            }
851            bits = (srcbits += linebytes) + (left * 3);
852        }
853     } else {
854        lines = -lines;
855        for (h = 0; h < lines; h++)
856         {
857            for (x = left; x < dstwidth; x++, bits += 3)
858             {
859                 COLORREF pixel = COLOR_ToLogical( XGetPixel( bmpImage, x, h ) );
860                 bits[0] = GetRValue(pixel);
861                 bits[1] = GetGValue(pixel);
862                 bits[2] = GetBValue(pixel);
863            }
864
865            bits = (srcbits += linebytes) + (left * 3);
866        }
867     }
868 }
869
870
871 /***********************************************************************
872  *           X11DRV_DIB_SetImageBits_32
873  *
874  * SetDIBits for a 32-bit deep DIB.
875  */
876 static void X11DRV_DIB_SetImageBits_32( int lines, const BYTE *srcbits,
877                                  DWORD srcwidth, DWORD dstwidth, int left,
878                                  DC *dc, XImage *bmpImage )
879 {
880     DWORD x;
881     const BYTE *bits = srcbits + left * 4;
882     int h;
883   
884     DWORD linebytes = (srcwidth * 4);
885
886     dstwidth += left;
887
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])));
893             }
894             bits = (srcbits += linebytes) + left * 4;
895         }
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])));
902             }
903             bits = (srcbits += linebytes) + left * 4;
904         }
905     }
906 }
907
908
909 /***********************************************************************
910  *           X11DRV_DIB_GetImageBits_32
911  *
912  * GetDIBits for an 32-bit deep DIB.
913  */
914 static void X11DRV_DIB_GetImageBits_32( int lines, BYTE *srcbits,
915                                  DWORD srcwidth, DWORD dstwidth, int left,
916                                  XImage *bmpImage )
917 {
918     DWORD x;
919     int h;
920     BYTE *bits = srcbits + (left * 4);
921
922     /* align to 32 bit */
923     DWORD linebytes = (srcwidth * 4);
924
925     dstwidth += left;
926
927     if (lines > 0) {
928        for (h = lines - 1; h >= 0; h--)
929         {
930            for (x = left; x < dstwidth; x++, bits += 4)
931             {
932                 COLORREF pixel = COLOR_ToLogical( XGetPixel( bmpImage, x, h ) );
933                 bits[0] = GetRValue(pixel);
934                 bits[1] = GetGValue(pixel);
935                 bits[2] = GetBValue(pixel);
936            }
937            bits = (srcbits += linebytes) + (left * 4);
938        }
939     } else {
940        lines = -lines;
941        for (h = 0; h < lines; h++)
942         {
943            for (x = left; x < dstwidth; x++, bits += 4)
944             {
945                 COLORREF pixel = COLOR_ToLogical( XGetPixel( bmpImage, x, h ) );
946                 bits[0] = GetRValue(pixel);
947                 bits[1] = GetGValue(pixel);
948                 bits[2] = GetBValue(pixel);
949            }
950
951            bits = (srcbits += linebytes) + (left * 4);
952        }
953     }
954 }
955
956
957 /***********************************************************************
958  *           X11DRV_DIB_SetImageBits
959  *
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.
963  */
964 int X11DRV_DIB_SetImageBits( const DIB_SETIMAGEBITS_DESCR *descr )
965 {
966     int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
967     XImage *bmpImage;
968
969     if ( descr->dc && descr->dc->w.flags & DC_DIRTY ) 
970         CLIPPING_UpdateGCRegion( descr->dc );
971
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 );
980     }
981
982       /* Transfer the pixels */
983     switch(descr->infoBpp)
984     {
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;
1033     }
1034
1035     XPutImage( display, descr->drawable, descr->gc, bmpImage,
1036                descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
1037                descr->width, descr->height );
1038
1039     if (!descr->image) XDestroyImage( bmpImage );
1040     return lines;
1041 }
1042
1043 /***********************************************************************
1044  *           X11DRV_DIB_GetImageBits
1045  *
1046  * Transfer the bits from an X image.
1047  * The Xlib critical section must be entered before calling this function.
1048  */
1049 int X11DRV_DIB_GetImageBits( const DIB_SETIMAGEBITS_DESCR *descr )
1050 {
1051     int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
1052     XImage *bmpImage;
1053
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 );
1062     }
1063
1064     XGetSubImage( display, descr->drawable, descr->xDest, descr->yDest,
1065                   descr->width, descr->height, AllPlanes, ZPixmap,
1066                   bmpImage, descr->xSrc, descr->ySrc );
1067
1068       /* Transfer the pixels */
1069     switch(descr->infoBpp)
1070     {
1071     case 1:
1072         FIXME(bitmap, "Depth 1 not yet supported!\n");
1073        break;
1074
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;
1085
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;
1095
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;
1102
1103     case 24:
1104        X11DRV_DIB_GetImageBits_24( descr->lines, (LPVOID)descr->bits,
1105                                    descr->infoWidth,
1106                                    descr->width, descr->xSrc, bmpImage );
1107        break;
1108
1109     case 32:
1110        X11DRV_DIB_GetImageBits_32( descr->lines, (LPVOID)descr->bits,
1111                                    descr->infoWidth,
1112                                    descr->width, descr->xSrc, bmpImage );
1113        break;
1114
1115     default:
1116         WARN(bitmap, "(%d): Invalid depth\n", descr->infoBpp );
1117         break;
1118     }
1119
1120     if (!descr->image) XDestroyImage( bmpImage );
1121     return lines;
1122 }
1123
1124 /*************************************************************************
1125  *              X11DRV_SetDIBitsToDevice
1126  *
1127  */
1128 INT32 X11DRV_SetDIBitsToDevice( DC *dc, INT32 xDest, INT32 yDest, DWORD cx,
1129                                 DWORD cy, INT32 xSrc, INT32 ySrc,
1130                                 UINT32 startscan, UINT32 lines, LPCVOID bits,
1131                                 const BITMAPINFO *info, UINT32 coloruse )
1132 {
1133     DIB_SETIMAGEBITS_DESCR descr;
1134     DWORD width, oldcy = cy;
1135     INT32 result;
1136     int height, tmpheight;
1137     X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
1138
1139
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;
1153
1154     X11DRV_SetupGCForText( dc );  /* To have the correct colors */
1155     TSXSetFunction(display, physDev->gc, X11DRV_XROPfunction[dc->w.ROPmode-1]);
1156
1157     if (descr.infoBpp <= 8)
1158     {
1159         descr.colorMap = X11DRV_DIB_BuildColorMap( dc, coloruse,
1160                                                    dc->w.bitsPerPixel,
1161                                                    info, &descr.nColorMap );
1162         if (!descr.colorMap)
1163             return 0;
1164     }
1165
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;
1182
1183     EnterCriticalSection( &X11DRV_CritSection );
1184     result = CALL_LARGE_STACK( X11DRV_DIB_SetImageBits, &descr );
1185     LeaveCriticalSection( &X11DRV_CritSection );
1186
1187     HeapFree(GetProcessHeap(), 0, descr.colorMap);
1188     return result;
1189 }
1190
1191 #endif /* !defined(X_DISPLAY_MISSING) */