Moved DC_SetupGC functions to graphics/x11drv/graphics.c.
[wine] / graphics / x11drv / dib.c
1 /*
2  * X11DRV device-independent bitmaps
3  *
4  * Copyright 1993,1994  Alexandre Julliard
5  */
6
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"
16
17 static int bitmapDepthTable[] = { 8, 1, 32, 16, 24, 15, 4, 0 };
18 static int ximageDepthTable[] = { 0, 0, 0,  0,  0,  0,  0 };
19
20 /***********************************************************************
21  *           X11DRV_DIB_Init
22  */
23 BOOL32 X11DRV_DIB_Init(void)
24 {
25     int         i;
26     XImage*     testimage;
27
28     for( i = 0; bitmapDepthTable[i]; i++ )
29     {
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);
35     }
36     return TRUE;
37 }
38
39
40 /***********************************************************************
41  *           X11DRV_DIB_GetXImageWidthBytes
42  *
43  * Return the width of an X image in bytes
44  */
45 int X11DRV_DIB_GetXImageWidthBytes( int width, int depth )
46 {
47     int         i;
48
49     if (!ximageDepthTable[0]) {
50             X11DRV_DIB_Init();
51     }
52     for( i = 0; bitmapDepthTable[i] ; i++ )
53          if( bitmapDepthTable[i] == depth )
54              return (4 * ((width * ximageDepthTable[i] + 31)/32));
55     
56     WARN(bitmap, "(%d): Unsupported depth\n", depth );
57     return (4 * width);
58 }
59
60 /***********************************************************************
61  *           X11DRV_DIB_BuildColorMap
62  *
63  * Build the color map from the bitmap palette. Should not be called
64  * for a >8-bit deep bitmap.
65  */
66 int *X11DRV_DIB_BuildColorMap( DC *dc, WORD coloruse, WORD depth, 
67                                const BITMAPINFO *info, int *nColors )
68 {
69     int i, colors;
70     BOOL32 isInfo;
71     WORD *colorPtr;
72     int *colorMapping;
73
74     if ((isInfo = (info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))))
75     {
76         colors = info->bmiHeader.biClrUsed;
77         if (!colors) colors = 1 << info->bmiHeader.biBitCount;
78         colorPtr = (WORD *)info->bmiColors;
79     }
80     else  /* assume BITMAPCOREINFO */
81     {
82         colors = 1 << ((BITMAPCOREHEADER *)&info->bmiHeader)->bcBitCount;
83         colorPtr = (WORD *)((BITMAPCOREINFO *)info)->bmciColors;
84     }
85
86     if (colors > 256)
87     {
88         ERR(bitmap, "called with >256 colors!\n");
89         return NULL;
90     }
91
92     if (!(colorMapping = (int *)HeapAlloc(GetProcessHeap(), 0,
93                                           colors * sizeof(int) ))) 
94         return NULL;
95
96     if (coloruse == DIB_RGB_COLORS)
97     {
98         if (isInfo)
99         {
100             RGBQUAD * rgb = (RGBQUAD *)colorPtr;
101
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));
111         }
112         else
113         {
114             RGBTRIPLE * rgb = (RGBTRIPLE *)colorPtr;
115
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));
125         }
126     }
127     else  /* DIB_PAL_COLORS */
128     {
129         for (i = 0; i < colors; i++, colorPtr++)
130             colorMapping[i] = COLOR_ToPhysical( dc, PALETTEINDEX(*colorPtr) );
131     }
132
133     *nColors = colors;
134     return colorMapping;
135 }
136
137
138 /***********************************************************************
139  *           X11DRV_DIB_MapColor
140  */
141 int X11DRV_DIB_MapColor( int *physMap, int nPhysMap, int phys )
142 {
143     int color;
144
145     for (color = 0; color < nPhysMap; color++)
146         if (physMap[color] == phys)
147             return color;
148
149     WARN(bitmap, "Strange color %08x\n", phys);
150     return 0;
151 }
152
153
154
155 /***********************************************************************
156  *           X11DRV_DIB_SetImageBits_1_Line
157  *
158  * Handles a single line of 1 bit data.
159  */
160 static void X11DRV_DIB_SetImageBits_1_Line(DWORD dstwidth, int left, int *colors,
161                                     XImage *bmpImage, int h, const BYTE *bits)
162 {
163     BYTE pix;
164     DWORD i, x;
165
166     dstwidth += left; bits += left >> 3;
167
168     /* FIXME: should avoid putting x<left pixels (minor speed issue) */
169     for (i = dstwidth/8, x = left&~7; (i > 0); i--)
170     {
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] );
180     }
181     pix = *bits;
182     switch(dstwidth & 7)
183     {
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] );
191     }
192 }
193
194 /***********************************************************************
195  *           X11DRV_DIB_SetImageBits_1
196  *
197  * SetDIBits for a 1-bit deep DIB.
198  */
199 static void X11DRV_DIB_SetImageBits_1( int lines, const BYTE *srcbits,
200                                 DWORD srcwidth, DWORD dstwidth, int left,
201                                 int *colors, XImage *bmpImage )
202 {
203     int h;
204
205     /* 32 bit aligned */
206     DWORD linebytes = ((srcwidth + 31) & ~31) / 8;
207
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;
213         }
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;
220         }
221     }
222 }
223
224
225 /***********************************************************************
226  *           X11DRV_DIB_SetImageBits_4
227  *
228  * SetDIBits for a 4-bit deep DIB.
229  */
230 static void X11DRV_DIB_SetImageBits_4( int lines, const BYTE *srcbits,
231                                 DWORD srcwidth, DWORD dstwidth, int left,
232                                 int *colors, XImage *bmpImage )
233 {
234     DWORD i, x;
235     int h;
236     const BYTE *bits = srcbits + (left >> 1);
237   
238     /* 32 bit aligned */
239     DWORD linebytes = ((srcwidth+7)&~7)/2;
240
241     dstwidth += left;
242
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] );
250             }
251             if (dstwidth & 1) XPutPixel( bmpImage, x, h, colors[*bits >> 4] );
252             srcbits += linebytes;
253             bits         = srcbits + (left >> 1);
254         }
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] );
262             }
263             if (dstwidth & 1) XPutPixel( bmpImage, x, h, colors[*bits >> 4] );
264             srcbits += linebytes;
265             bits         = srcbits + (left >> 1);
266         }
267     }
268 }
269
270
271
272 /***********************************************************************
273  *           X11DRV_DIB_GetImageBits_4
274  *
275  * GetDIBits for a 4-bit deep DIB.
276  */
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 )
280 {
281     DWORD i, x;
282     int h;
283     BYTE *bits = srcbits + (left >> 1);
284
285     /* 32 bit aligned */
286     DWORD linebytes = ((srcwidth+7)&~7)/2;
287
288     dstwidth += left;
289
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);
298            }
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);
304        }
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);
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     }
322 }
323
324 #define check_xy(x,y) \
325         if (x > width) { \
326                 x = 0; \
327                 if (lines) \
328                         lines--; \
329         }
330
331 /***********************************************************************
332  *           X11DRV_DIB_SetImageBits_RLE4
333  *
334  * SetDIBits for a 4-bit deep compressed DIB.
335  */
336 static void X11DRV_DIB_SetImageBits_RLE4( int lines, const BYTE *bits, DWORD width,
337                                 DWORD dstwidth, int left, int *colors, XImage *bmpImage )
338 {
339         int x = 0, c, length;
340         const BYTE *begin = bits;
341
342         dstwidth += left; /* FIXME: avoid putting x<left pixels */
343
344         lines--;
345         while ((int)lines >= 0)
346         {
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);
357                                 }
358                         }
359                 } else {
360                         length = *bits++;
361                         switch (length) {
362                                 case 0: /* eol */
363                                         x = 0;
364                                         lines--;
365                                         continue;
366
367                                 case 1: /* eopicture */
368                                         return;
369
370                                 case 2: /* delta */
371                                         x += *bits++;
372                                         lines -= *bits++;
373                                         continue;
374
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);
384                                                 }
385                                         }
386                                         if ((bits - begin) & 1)
387                                                 bits++;
388                         }
389                 }
390         }
391 }
392
393
394
395
396 /***********************************************************************
397  *           X11DRV_DIB_SetImageBits_8
398  *
399  * SetDIBits for an 8-bit deep DIB.
400  */
401 static void X11DRV_DIB_SetImageBits_8( int lines, const BYTE *srcbits,
402                                 DWORD srcwidth, DWORD dstwidth, int left,
403                                 int *colors, XImage *bmpImage )
404 {
405     DWORD x;
406     int h;
407     const BYTE *bits = srcbits + left;
408
409     /* align to 32 bit */
410     DWORD linebytes = (srcwidth + 3) & ~3;
411
412     dstwidth+=left;
413
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] );
418             }
419             bits = (srcbits += linebytes) + left;
420         }
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] );
426             }
427             bits = (srcbits += linebytes) + left;
428         }
429     }
430 }
431
432 /***********************************************************************
433  *           X11DRV_DIB_GetImageBits_8
434  *
435  * GetDIBits for an 8-bit deep DIB.
436  */
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 )
440 {
441     DWORD x;
442     int h;
443     BYTE *bits = srcbits + left;
444
445     /* align to 32 bit */
446     DWORD linebytes = (srcwidth + 3) & ~3;
447
448     dstwidth+=left;
449
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 ) );
456            }
457            bits = (srcbits += linebytes) + left;
458        }
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 ) );
466            }
467            bits = (srcbits += linebytes) + left;
468        }
469     }
470 }
471
472 /***********************************************************************
473  *            X11DRV_DIB_SetImageBits_RLE8
474  *
475  * SetDIBits for an 8-bit deep compressed DIB.
476  *
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.  
479  *
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.
487  *
488  * (No) apologies for my English spelling.  [Emacs users: c-indent-level=4].
489  *                      James A. Youngman <mbcstjy@afs.man.ac.uk>
490  *                                              [JAY]
491  */
492
493 enum Rle8_EscapeCodes           
494 {
495   /* 
496    * Apologies for polluting your file's namespace...
497    */
498   RleEol        = 0,            /* End of line */
499   RleEnd        = 1,            /* End of bitmap */
500   RleDelta      = 2             /* Delta */
501 };
502   
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 )
507 {
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] */
515     
516     if (lines == 0)             /* Let's hope this doesn't happen. */
517       return;
518     
519     dstwidth += left; /* FIXME: avoid putting x<left pixels */
520
521     /*
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]
526      */
527     
528     x = 0;
529     line = lines-1;
530     do
531       {
532           length = *pIn++;
533           
534           /* 
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. 
538            *
539            * If the length byte is zero, we need to read the next byte to
540            * know what to do.                   [JAY]
541            */
542           if (length != 0) 
543             {                                   
544                 /* 
545                  * [Run-Length] Encoded mode 
546                  */
547                 color_index = (*pIn++); /* Get the colour index. */
548                 color = colors[color_index];
549
550                 while(length--)
551                   XPutPixel(bmpImage, x++, line, color);
552             }
553           else 
554             {    
555                 /* 
556                  * Escape codes (may be an absolute sequence though)
557                  */
558                 escape_code = (*pIn++);
559                 switch(escape_code)
560                   {
561                     case RleEol: /* =0, end of line */
562                       {
563                           x = 0;  
564                           line--;  
565                           break;
566                       }
567                       
568                     case RleEnd: /* =1, end of bitmap */
569                       {
570                           /*
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]
576                            */
577                           line=-1; /* Cause exit from do loop. */
578                           break;
579                       }
580                       
581                     case RleDelta: /* =2, a delta */
582                       {
583                           /* 
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.  
592                            *
593                            * TODO: Decide what to do here in that case. [JAY]
594                            */
595                           x     += (*pIn++); 
596                           line  -= (*pIn++);
597                           if (line == 0)
598                             {
599                               TRACE(bitmap, "Delta to last line of bitmap "
600                                            "(wrongly?) causes loop exit\n");
601                             }
602                           break;
603                       }
604                       
605                     default:    /* >2, switch to absolute mode */
606                       {
607                           /* 
608                            * Absolute Mode 
609                            */
610                           length = escape_code;
611                           while(length--)
612                             {
613                                 color_index = (*pIn++);
614                                 XPutPixel(bmpImage, x++, line, 
615                                           colors[color_index]);
616                             }
617                           
618                           /*
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]
626                            */
627                           if (escape_code & 1) 
628                             pIn++; /* Throw away the pad byte. */
629                           break;
630                       }
631                   } /* switch (escape_code) : Escape sequence */
632             }  /* process either an encoded sequence or an escape sequence */
633           
634           /* We expect to come here more than once per line. */
635       } while (line >= 0);  /* Do this until the bitmap is filled */
636     
637     /*
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]
641      */
642     if ( (*(pIn-2) != 0/*escape*/) || (*(pIn-1)!= RleEnd) )
643       {
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));           
649       }
650 }  
651
652
653 /***********************************************************************
654  *           X11DRV_DIB_SetImageBits_16
655  *
656  * SetDIBits for a 16-bit deep DIB.
657  */
658 static void X11DRV_DIB_SetImageBits_16( int lines, const BYTE *srcbits,
659                                  DWORD srcwidth, DWORD dstwidth, int left,
660                                  DC *dc, XImage *bmpImage )
661 {
662     DWORD x;
663     LPWORD ptr;
664     WORD val;
665     int h;
666     BYTE r, g, b;
667   
668     /* align to 32 bit */
669     DWORD linebytes = (srcwidth * 2 + 3) & ~3;
670
671     dstwidth += left;
672
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)) );
683             }
684             ptr = (LPWORD) (srcbits += linebytes) + left;
685         }
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)) );
696             }
697             ptr = (LPWORD) (srcbits += linebytes) + left;
698         }
699     }
700 }
701
702
703 /***********************************************************************
704  *           X11DRV_DIB_GetImageBits_16
705  *
706  * GetDIBits for an 16-bit deep DIB.
707  */
708 static void X11DRV_DIB_GetImageBits_16( int lines, BYTE *srcbits,
709                                  DWORD srcwidth, DWORD dstwidth, int left,
710                                  XImage *bmpImage )
711 {
712     DWORD x;
713     LPWORD ptr;
714     int h;
715     BYTE r, g, b;
716
717     /* align to 32 bit */
718     DWORD linebytes = (srcwidth * 2 + 3) & ~3;
719
720     dstwidth += left;
721
722     ptr = (LPWORD) srcbits + left;
723     if (lines > 0) {
724        for (h = lines - 1; h >= 0; h--)
725         {
726            for (x = left; x < dstwidth; x++, ptr++)
727             {
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) );
733            }
734            ptr = (LPWORD) (srcbits += linebytes) + left;
735        }
736     } else {
737        lines = -lines;
738        for (h = 0; h < lines; h++)
739         {
740            for (x = left; x < dstwidth; x++, ptr++)
741             {
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) );
747            }
748
749            ptr = (LPWORD) (srcbits += linebytes) + left;
750        }
751     }
752 }
753
754
755
756 /***********************************************************************
757  *           X11DRV_DIB_SetImageBits_24
758  *
759  * SetDIBits for a 24-bit deep DIB.
760  */
761 static void X11DRV_DIB_SetImageBits_24( int lines, const BYTE *srcbits,
762                                  DWORD srcwidth, DWORD dstwidth, int left,
763                                  DC *dc, XImage *bmpImage )
764 {
765     DWORD x;
766     const BYTE *bits = srcbits + left * 3;
767     int h;
768   
769     /* align to 32 bit */
770     DWORD linebytes = (srcwidth * 3 + 3) & ~3;
771
772     dstwidth += left;
773
774     /* "bits" order is reversed for some reason */
775
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])));
781             }
782             bits = (srcbits += linebytes) + left * 3;
783         }
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])));
790             }
791             bits = (srcbits += linebytes) + left * 3;
792         }
793     }
794 }
795
796
797 /***********************************************************************
798  *           X11DRV_DIB_GetImageBits_24
799  *
800  * GetDIBits for an 24-bit deep DIB.
801  */
802 static void X11DRV_DIB_GetImageBits_24( int lines, BYTE *srcbits,
803                                  DWORD srcwidth, DWORD dstwidth, int left,
804                                  XImage *bmpImage )
805 {
806     DWORD x;
807     int h;
808     BYTE *bits = srcbits + (left * 3);
809
810     /* align to 32 bit */
811     DWORD linebytes = (srcwidth * 3 + 3) & ~3;
812
813     dstwidth += left;
814
815     if (lines > 0) {
816        for (h = lines - 1; h >= 0; h--)
817         {
818            for (x = left; x < dstwidth; x++, bits += 3)
819             {
820                 COLORREF pixel = COLOR_ToLogical( XGetPixel( bmpImage, x, h ) );
821                 bits[0] = GetRValue(pixel);
822                 bits[1] = GetGValue(pixel);
823                 bits[2] = GetBValue(pixel);
824            }
825            bits = (srcbits += linebytes) + (left * 3);
826        }
827     } else {
828        lines = -lines;
829        for (h = 0; h < lines; h++)
830         {
831            for (x = left; x < dstwidth; x++, bits += 3)
832             {
833                 COLORREF pixel = COLOR_ToLogical( XGetPixel( bmpImage, x, h ) );
834                 bits[0] = GetRValue(pixel);
835                 bits[1] = GetGValue(pixel);
836                 bits[2] = GetBValue(pixel);
837            }
838
839            bits = (srcbits += linebytes) + (left * 3);
840        }
841     }
842 }
843
844
845 /***********************************************************************
846  *           X11DRV_DIB_SetImageBits_32
847  *
848  * SetDIBits for a 32-bit deep DIB.
849  */
850 static void X11DRV_DIB_SetImageBits_32( int lines, const BYTE *srcbits,
851                                  DWORD srcwidth, DWORD dstwidth, int left,
852                                  DC *dc, XImage *bmpImage )
853 {
854     DWORD x;
855     const BYTE *bits = srcbits + left * 4;
856     int h;
857   
858     DWORD linebytes = (srcwidth * 4);
859
860     dstwidth += left;
861
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])));
867             }
868             bits = (srcbits += linebytes) + left * 4;
869         }
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])));
876             }
877             bits = (srcbits += linebytes) + left * 4;
878         }
879     }
880 }
881
882
883 /***********************************************************************
884  *           X11DRV_DIB_GetImageBits_32
885  *
886  * GetDIBits for an 32-bit deep DIB.
887  */
888 static void X11DRV_DIB_GetImageBits_32( int lines, BYTE *srcbits,
889                                  DWORD srcwidth, DWORD dstwidth, int left,
890                                  XImage *bmpImage )
891 {
892     DWORD x;
893     int h;
894     BYTE *bits = srcbits + (left * 4);
895
896     /* align to 32 bit */
897     DWORD linebytes = (srcwidth * 4);
898
899     dstwidth += left;
900
901     if (lines > 0) {
902        for (h = lines - 1; h >= 0; h--)
903         {
904            for (x = left; x < dstwidth; x++, bits += 4)
905             {
906                 COLORREF pixel = COLOR_ToLogical( XGetPixel( bmpImage, x, h ) );
907                 bits[0] = GetRValue(pixel);
908                 bits[1] = GetGValue(pixel);
909                 bits[2] = GetBValue(pixel);
910            }
911            bits = (srcbits += linebytes) + (left * 4);
912        }
913     } else {
914        lines = -lines;
915        for (h = 0; h < lines; h++)
916         {
917            for (x = left; x < dstwidth; x++, bits += 4)
918             {
919                 COLORREF pixel = COLOR_ToLogical( XGetPixel( bmpImage, x, h ) );
920                 bits[0] = GetRValue(pixel);
921                 bits[1] = GetGValue(pixel);
922                 bits[2] = GetBValue(pixel);
923            }
924
925            bits = (srcbits += linebytes) + (left * 4);
926        }
927     }
928 }
929
930
931 /***********************************************************************
932  *           X11DRV_DIB_SetImageBits
933  *
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.
937  */
938 int X11DRV_DIB_SetImageBits( const DIB_SETIMAGEBITS_DESCR *descr )
939 {
940     int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
941     XImage *bmpImage;
942
943     if ( descr->dc && descr->dc->w.flags & DC_DIRTY ) 
944         CLIPPING_UpdateGCRegion( descr->dc );
945
946     if (descr->image)
947         bmpImage = descr->image;
948     else
949         XCREATEIMAGE( bmpImage, descr->infoWidth, lines, descr->depth );
950
951       /* Transfer the pixels */
952     switch(descr->infoBpp)
953     {
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;
1002     }
1003
1004     XPutImage( display, descr->drawable, descr->gc, bmpImage,
1005                descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
1006                descr->width, descr->height );
1007
1008     if (!descr->image) XDestroyImage( bmpImage );
1009     return lines;
1010 }
1011
1012 /***********************************************************************
1013  *           X11DRV_DIB_GetImageBits
1014  *
1015  * Transfer the bits from an X image.
1016  * The Xlib critical section must be entered before calling this function.
1017  */
1018 int X11DRV_DIB_GetImageBits( const DIB_SETIMAGEBITS_DESCR *descr )
1019 {
1020     int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
1021     XImage *bmpImage;
1022
1023     if (descr->image)
1024         bmpImage = descr->image;
1025     else
1026         XCREATEIMAGE( bmpImage, descr->infoWidth, lines, descr->depth );
1027
1028     XGetSubImage( display, descr->drawable, descr->xDest, descr->yDest,
1029                   descr->width, descr->height, AllPlanes, ZPixmap,
1030                   bmpImage, descr->xSrc, descr->ySrc );
1031
1032       /* Transfer the pixels */
1033     switch(descr->infoBpp)
1034     {
1035     case 1:
1036         FIXME(bitmap, "Depth 1 not yet supported!\n");
1037        break;
1038
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;
1049
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;
1059
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;
1066
1067     case 24:
1068        X11DRV_DIB_GetImageBits_24( descr->lines, (LPVOID)descr->bits,
1069                                    descr->infoWidth,
1070                                    descr->width, descr->xSrc, bmpImage );
1071        break;
1072
1073     case 32:
1074        X11DRV_DIB_GetImageBits_32( descr->lines, (LPVOID)descr->bits,
1075                                    descr->infoWidth,
1076                                    descr->width, descr->xSrc, bmpImage );
1077        break;
1078
1079     default:
1080         WARN(bitmap, "(%d): Invalid depth\n", descr->infoBpp );
1081         break;
1082     }
1083
1084     if (!descr->image) XDestroyImage( bmpImage );
1085     return lines;
1086 }
1087
1088 /*************************************************************************
1089  *              X11DRV_SetDIBitsToDevice
1090  *
1091  */
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 )
1096 {
1097     DIB_SETIMAGEBITS_DESCR descr;
1098     DWORD width, oldcy = cy;
1099     INT32 result;
1100     int height, tmpheight;
1101
1102
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;
1116
1117     X11DRV_SetupGCForText( dc );  /* To have the correct colors */
1118     TSXSetFunction(display, dc->u.x.gc, X11DRV_XROPfunction[dc->w.ROPmode-1]);
1119
1120     if (descr.infoBpp <= 8)
1121     {
1122         descr.colorMap = X11DRV_DIB_BuildColorMap( dc, coloruse,
1123                                                    dc->w.bitsPerPixel,
1124                                                    info, &descr.nColorMap );
1125         if (!descr.colorMap)
1126             return 0;
1127     }
1128
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;
1145
1146     EnterCriticalSection( &X11DRV_CritSection );
1147     result = CALL_LARGE_STACK( X11DRV_DIB_SetImageBits, &descr );
1148     LeaveCriticalSection( &X11DRV_CritSection );
1149
1150     HeapFree(GetProcessHeap(), 0, descr.colorMap);
1151     return result;
1152 }