Fixed error handling in DGA_IDirectDraw2Impl_GetCaps().
[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 "windef.h"
15 #include "bitmap.h"
16 #include "x11drv.h"
17 #include "debugtools.h"
18 #include "dc.h"
19 #include "color.h"
20 #include "callback.h"
21 #include "selectors.h"
22 #include "global.h"
23 #include "xmalloc.h" /* for XCREATEIMAGE macro */
24
25 DECLARE_DEBUG_CHANNEL(bitmap)
26 DECLARE_DEBUG_CHANNEL(x11drv)
27
28 static int bitmapDepthTable[] = { 8, 1, 32, 16, 24, 15, 4, 0 };
29 static int ximageDepthTable[] = { 0, 0, 0,  0,  0,  0,  0 };
30
31 /***********************************************************************
32  *           X11DRV_DIB_Init
33  */
34 BOOL X11DRV_DIB_Init(void)
35 {
36     int         i;
37     XImage*     testimage;
38
39     for( i = 0; bitmapDepthTable[i]; i++ )
40     {
41          testimage = TSXCreateImage(display, DefaultVisualOfScreen(X11DRV_GetXScreen()),
42                          bitmapDepthTable[i], ZPixmap, 0, NULL, 1, 1, 32, 20 );
43          if( testimage ) ximageDepthTable[i] = testimage->bits_per_pixel;
44          else return FALSE;
45          TSXDestroyImage(testimage);
46     }
47     return TRUE;
48 }
49
50
51 /***********************************************************************
52  *           X11DRV_DIB_GetXImageWidthBytes
53  *
54  * Return the width of an X image in bytes
55  */
56 int X11DRV_DIB_GetXImageWidthBytes( int width, int depth )
57 {
58     int         i;
59
60     if (!ximageDepthTable[0]) {
61             X11DRV_DIB_Init();
62     }
63     for( i = 0; bitmapDepthTable[i] ; i++ )
64          if( bitmapDepthTable[i] == depth )
65              return (4 * ((width * ximageDepthTable[i] + 31)/32));
66     
67     WARN_(bitmap)("(%d): Unsupported depth\n", depth );
68     return (4 * width);
69 }
70
71 /***********************************************************************
72  *           X11DRV_DIB_BuildColorMap
73  *
74  * Build the color map from the bitmap palette. Should not be called
75  * for a >8-bit deep bitmap.
76  */
77 int *X11DRV_DIB_BuildColorMap( DC *dc, WORD coloruse, WORD depth, 
78                                const BITMAPINFO *info, int *nColors )
79 {
80     int i, colors;
81     BOOL isInfo;
82     WORD *colorPtr;
83     int *colorMapping;
84
85     if ((isInfo = (info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))))
86     {
87         colors = info->bmiHeader.biClrUsed;
88         if (!colors) colors = 1 << info->bmiHeader.biBitCount;
89         colorPtr = (WORD *)info->bmiColors;
90     }
91     else  /* assume BITMAPCOREINFO */
92     {
93         colors = 1 << ((BITMAPCOREHEADER *)&info->bmiHeader)->bcBitCount;
94         colorPtr = (WORD *)((BITMAPCOREINFO *)info)->bmciColors;
95     }
96
97     if (colors > 256)
98     {
99         ERR_(bitmap)("called with >256 colors!\n");
100         return NULL;
101     }
102
103     if (!(colorMapping = (int *)HeapAlloc(GetProcessHeap(), 0,
104                                           colors * sizeof(int) ))) 
105         return NULL;
106
107     if (coloruse == DIB_RGB_COLORS)
108     {
109         if (isInfo)
110         {
111             RGBQUAD * rgb = (RGBQUAD *)colorPtr;
112
113             if (depth == 1)  /* Monochrome */
114                 for (i = 0; i < colors; i++, rgb++)
115                     colorMapping[i] = (rgb->rgbRed + rgb->rgbGreen +
116                                        rgb->rgbBlue > 255*3/2);
117             else
118                 for (i = 0; i < colors; i++, rgb++)
119                     colorMapping[i] = X11DRV_PALETTE_ToPhysical( dc, RGB(rgb->rgbRed,
120                                                                 rgb->rgbGreen,
121                                                                 rgb->rgbBlue));
122         }
123         else
124         {
125             RGBTRIPLE * rgb = (RGBTRIPLE *)colorPtr;
126
127             if (depth == 1)  /* Monochrome */
128                 for (i = 0; i < colors; i++, rgb++)
129                     colorMapping[i] = (rgb->rgbtRed + rgb->rgbtGreen +
130                                        rgb->rgbtBlue > 255*3/2);
131             else
132                 for (i = 0; i < colors; i++, rgb++)
133                     colorMapping[i] = X11DRV_PALETTE_ToPhysical( dc, RGB(rgb->rgbtRed,
134                                                                rgb->rgbtGreen,
135                                                                rgb->rgbtBlue));
136         }
137     }
138     else  /* DIB_PAL_COLORS */
139     {
140         for (i = 0; i < colors; i++, colorPtr++)
141             colorMapping[i] = X11DRV_PALETTE_ToPhysical( dc, PALETTEINDEX(*colorPtr) );
142     }
143
144     *nColors = colors;
145     return colorMapping;
146 }
147
148
149 /***********************************************************************
150  *           X11DRV_DIB_MapColor
151  */
152 int X11DRV_DIB_MapColor( int *physMap, int nPhysMap, int phys )
153 {
154     int color;
155
156     for (color = 0; color < nPhysMap; color++)
157         if (physMap[color] == phys)
158             return color;
159
160     WARN_(bitmap)("Strange color %08x\n", phys);
161     return 0;
162 }
163
164
165
166 /***********************************************************************
167  *           X11DRV_DIB_SetImageBits_1_Line
168  *
169  * Handles a single line of 1 bit data.
170  */
171 static void X11DRV_DIB_SetImageBits_1_Line(DWORD dstwidth, int left, int *colors,
172                                     XImage *bmpImage, int h, const BYTE *bits)
173 {
174     BYTE pix, extra;
175     DWORD i, x;
176
177     if((extra = (left & 7)) != 0) {
178         left &= ~7;
179         dstwidth += extra;
180     }
181
182     bits += left >> 3;
183
184     /* FIXME: should avoid putting x<left pixels (minor speed issue) */
185     for (i = dstwidth/8, x = left; i > 0; i--)
186     {
187         pix = *bits++;
188         XPutPixel( bmpImage, x++, h, colors[pix >> 7] );
189         XPutPixel( bmpImage, x++, h, colors[(pix >> 6) & 1] );
190         XPutPixel( bmpImage, x++, h, colors[(pix >> 5) & 1] );
191         XPutPixel( bmpImage, x++, h, colors[(pix >> 4) & 1] );
192         XPutPixel( bmpImage, x++, h, colors[(pix >> 3) & 1] );
193         XPutPixel( bmpImage, x++, h, colors[(pix >> 2) & 1] );
194         XPutPixel( bmpImage, x++, h, colors[(pix >> 1) & 1] );
195         XPutPixel( bmpImage, x++, h, colors[pix & 1] );
196     }
197     pix = *bits;
198     switch(dstwidth & 7)
199     {
200     case 7: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
201     case 6: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
202     case 5: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
203     case 4: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
204     case 3: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
205     case 2: XPutPixel( bmpImage, x++, h, colors[pix >> 7] ); pix <<= 1;
206     case 1: XPutPixel( bmpImage, x++, h, colors[pix >> 7] );
207     }
208 }
209
210 /***********************************************************************
211  *           X11DRV_DIB_SetImageBits_1
212  *
213  * SetDIBits for a 1-bit deep DIB.
214  */
215 static void X11DRV_DIB_SetImageBits_1( int lines, const BYTE *srcbits,
216                                 DWORD srcwidth, DWORD dstwidth, int left,
217                                 int *colors, XImage *bmpImage )
218 {
219     int h;
220
221     /* 32 bit aligned */
222     DWORD linebytes = ((srcwidth + 31) & ~31) / 8;
223
224     if (lines > 0) {
225         for (h = lines-1; h >=0; h--) {
226             X11DRV_DIB_SetImageBits_1_Line(dstwidth, left, colors, bmpImage, h,
227                                            srcbits);
228             srcbits += linebytes;
229         }
230     } else {
231         lines = -lines;
232         for (h = 0; h < lines; h++) {
233             X11DRV_DIB_SetImageBits_1_Line(dstwidth, left, colors, bmpImage, h,
234                                            srcbits);
235             srcbits += linebytes;
236         }
237     }
238 }
239
240
241 /***********************************************************************
242  *           X11DRV_DIB_SetImageBits_4
243  *
244  * SetDIBits for a 4-bit deep DIB.
245  */
246 static void X11DRV_DIB_SetImageBits_4( int lines, const BYTE *srcbits,
247                                 DWORD srcwidth, DWORD dstwidth, int left,
248                                 int *colors, XImage *bmpImage )
249 {
250     DWORD i, x;
251     int h;
252     const BYTE *bits = srcbits + (left >> 1);
253   
254     /* 32 bit aligned */
255     DWORD linebytes = ((srcwidth+7)&~7)/2;
256
257     if(left & 1) {
258         left--;
259         dstwidth++;
260     }
261
262     if (lines > 0) {
263         for (h = lines-1; h >= 0; h--) {
264             for (i = dstwidth/2, x = left; i > 0; i--) {
265                 BYTE pix = *bits++;
266                 XPutPixel( bmpImage, x++, h, colors[pix >> 4] );
267                 XPutPixel( bmpImage, x++, h, colors[pix & 0x0f] );
268             }
269             if (dstwidth & 1) XPutPixel( bmpImage, x, h, colors[*bits >> 4] );
270             srcbits += linebytes;
271             bits         = srcbits + (left >> 1);
272         }
273     } else {
274         lines = -lines;
275         for (h = 0; h < lines; h++) {
276             for (i = dstwidth/2, x = left; i > 0; i--) {
277                 BYTE pix = *bits++;
278                 XPutPixel( bmpImage, x++, h, colors[pix >> 4] );
279                 XPutPixel( bmpImage, x++, h, colors[pix & 0x0f] );
280             }
281             if (dstwidth & 1) XPutPixel( bmpImage, x, h, colors[*bits >> 4] );
282             srcbits += linebytes;
283             bits         = srcbits + (left >> 1);
284         }
285     }
286 }
287
288
289
290 /***********************************************************************
291  *           X11DRV_DIB_GetImageBits_4
292  *
293  * GetDIBits for a 4-bit deep DIB.
294  */
295 static void X11DRV_DIB_GetImageBits_4( int lines, BYTE *srcbits,
296                                 DWORD srcwidth, DWORD dstwidth, int left,
297                                 int *colors, int nColors, XImage *bmpImage )
298 {
299     DWORD i, x;
300     int h;
301     BYTE *bits = srcbits + (left >> 1);
302
303     /* 32 bit aligned */
304     DWORD linebytes = ((srcwidth+7)&~7)/2;
305
306     if(left & 1) {
307         left--;
308         dstwidth++;
309     }
310
311     /* FIXME: should avoid putting x<left pixels (minor speed issue) */
312     if (lines > 0) {
313        for (h = lines-1; h >= 0; h--) {
314            for (i = dstwidth/2, x = left; i > 0; i--) {
315                *bits++ = (X11DRV_DIB_MapColor( colors, nColors, 
316                                         XGetPixel( bmpImage, x++, h )) << 4)
317                        | (X11DRV_DIB_MapColor( colors, nColors,
318                                         XGetPixel( bmpImage, x++, h )) & 0x0f);
319            }
320            if (dstwidth & 1)
321                *bits = (X11DRV_DIB_MapColor( colors, nColors,
322                                         XGetPixel( bmpImage, x++, h )) << 4);
323            srcbits += linebytes;
324            bits     = srcbits + (left >> 1);
325        }
326     } else {
327        lines = -lines;
328        for (h = 0; h < lines; h++) {
329            for (i = dstwidth/2, x = left; i > 0; i--) {
330                *bits++ = (X11DRV_DIB_MapColor( colors, nColors,
331                                         XGetPixel( bmpImage, x++, h ))
332                           << 4)
333                        | (X11DRV_DIB_MapColor( colors, nColors,
334                                         XGetPixel( bmpImage, x++, h )) & 0x0f);
335            }
336            if (dstwidth & 1)
337                *bits = (X11DRV_DIB_MapColor( colors, nColors,
338                                         XGetPixel( bmpImage, x++, h )) << 4);
339            srcbits += linebytes;
340            bits     = srcbits + (left >> 1);
341        }
342     }
343 }
344
345 /***********************************************************************
346  *           X11DRV_DIB_SetImageBits_RLE4
347  *
348  * SetDIBits for a 4-bit deep compressed DIB.
349  */
350 static void X11DRV_DIB_SetImageBits_RLE4( int lines, const BYTE *bits,
351                                           DWORD width, DWORD dstwidth,
352                                           int left, int *colors,
353                                           XImage *bmpImage )
354 {
355     int x = 0, c, length;
356     const BYTE *begin = bits;
357
358     lines--;
359
360     while ((int)lines >= 0) {
361         length = *bits++;
362         if (length) {   /* encoded */
363             c = *bits++;
364             while (length--) {
365                 if(x >= width) {
366                     x = 0;
367                     if(--lines < 0)
368                         return;
369                 }
370                 XPutPixel(bmpImage, x++, lines, colors[c >>4]);
371                 if (length) {
372                     length--;
373                     if(x >= width) {
374                         x = 0;
375                         if(--lines < 0)
376                             return;
377                     }
378                     XPutPixel(bmpImage, x++, lines, colors[c & 0xf]);
379                 }
380             }
381         } else {
382             length = *bits++;
383             switch (length) {
384             case 0: /* eol */
385                 x = 0;
386                 lines--;
387                 continue;
388
389             case 1: /* eopicture */
390                 return;
391
392             case 2: /* delta */
393                 x += *bits++;
394                 if(x >= width) {
395                    FIXME_(x11drv)("x-delta is too large?\n");
396                    return;
397                 }
398                 lines -= *bits++;
399                 continue;
400
401             default: /* absolute */
402                 while (length--) {
403                     c = *bits++;
404                     if(x >= width) {
405                         x = 0;
406                         if(--lines < 0)
407                             return;
408                     }
409                     XPutPixel(bmpImage, x++, lines, colors[c >> 4]);
410                     if (length) {
411                         length--;
412                         if(x >= width) {
413                             x = 0;
414                             if(--lines < 0)
415                                 return;
416                         }
417                         XPutPixel(bmpImage, x++, lines, colors[c & 0xf]);
418                     }
419                 }
420                 if ((bits - begin) & 1)
421                     bits++;
422             }
423         }
424     }
425 }
426
427
428
429 /***********************************************************************
430  *           X11DRV_DIB_SetImageBits_8
431  *
432  * SetDIBits for an 8-bit deep DIB.
433  */
434 static void X11DRV_DIB_SetImageBits_8( int lines, const BYTE *srcbits,
435                                 DWORD srcwidth, DWORD dstwidth, int left,
436                                 int *colors, XImage *bmpImage )
437 {
438     DWORD x;
439     int h;
440     const BYTE *bits = srcbits + left;
441
442     /* align to 32 bit */
443     DWORD linebytes = (srcwidth + 3) & ~3;
444
445     dstwidth += left;
446
447     if (lines > 0) {
448         for (h = lines - 1; h >= 0; h--) {
449             for (x = left; x < dstwidth; x++, bits++) {
450                 XPutPixel( bmpImage, x, h, colors[*bits] );
451             }
452             bits = (srcbits += linebytes) + left;
453         }
454     } else {
455         lines = -lines;
456         for (h = 0; h < lines; h++) {
457             for (x = left; x < dstwidth; x++, bits++) {
458                 XPutPixel( bmpImage, x, h, colors[*bits] );
459             }
460             bits = (srcbits += linebytes) + left;
461         }
462     }
463 }
464
465 /***********************************************************************
466  *           X11DRV_DIB_GetImageBits_8
467  *
468  * GetDIBits for an 8-bit deep DIB.
469  */
470 static void X11DRV_DIB_GetImageBits_8( int lines, BYTE *srcbits,
471                                 DWORD srcwidth, DWORD dstwidth, int left,
472                                 int *colors, int nColors, XImage *bmpImage )
473 {
474     DWORD x;
475     int h;
476     BYTE *bits = srcbits + left;
477
478     /* align to 32 bit */
479     DWORD linebytes = (srcwidth + 3) & ~3;
480
481     dstwidth += left;
482
483     if (lines > 0) {
484        for (h = lines - 1; h >= 0; h--) {
485            for (x = left; x < dstwidth; x++, bits++) {
486                if ( XGetPixel( bmpImage, x, h ) != colors[*bits] )
487                    *bits = X11DRV_DIB_MapColor( colors, nColors,
488                                           XGetPixel( bmpImage, x, h ) );
489            }
490            bits = (srcbits += linebytes) + left;
491        }
492     } else {
493        lines = -lines;
494        for (h = 0; h < lines; h++) {
495            for (x = left; x < dstwidth; x++, bits++) {
496                if ( XGetPixel( bmpImage, x, h ) != colors[*bits] )
497                    *bits = X11DRV_DIB_MapColor( colors, nColors,
498                                          XGetPixel( bmpImage, x, h ) );
499            }
500            bits = (srcbits += linebytes) + left;
501        }
502     }
503 }
504
505 /***********************************************************************
506  *            X11DRV_DIB_SetImageBits_RLE8
507  *
508  * SetDIBits for an 8-bit deep compressed DIB.
509  *
510  * This function rewritten 941113 by James Youngman.  WINE blew out when I
511  * first ran it because my desktop wallpaper is a (large) RLE8 bitmap.  
512  *
513  * This was because the algorithm assumed that all RLE8 bitmaps end with the  
514  * 'End of bitmap' escape code.  This code is very much laxer in what it
515  * allows to end the expansion.  Possibly too lax.  See the note by 
516  * case RleDelta.  BTW, MS's documentation implies that a correct RLE8
517  * bitmap should end with RleEnd, but on the other hand, software exists 
518  * that produces ones that don't and Windows 3.1 doesn't complain a bit
519  * about it.
520  *
521  * (No) apologies for my English spelling.  [Emacs users: c-indent-level=4].
522  *                      James A. Youngman <mbcstjy@afs.man.ac.uk>
523  *                                              [JAY]
524  */
525
526 enum Rle8_EscapeCodes           
527 {
528   /* 
529    * Apologies for polluting your file's namespace...
530    */
531   RleEol        = 0,            /* End of line */
532   RleEnd        = 1,            /* End of bitmap */
533   RleDelta      = 2             /* Delta */
534 };
535   
536 static void X11DRV_DIB_SetImageBits_RLE8( int lines, const BYTE *bits,
537                                           DWORD width, DWORD dstwidth,
538                                           int left, int *colors,
539                                           XImage *bmpImage )
540 {
541     int x;                      /* X-positon on each line.  Increases. */
542     int line;                   /* Line #.  Starts at lines-1, decreases */
543     const BYTE *pIn = bits;     /* Pointer to current position in bits */
544     BYTE length;                /* The length pf a run */
545     BYTE color_index;           /* index into colors[] as read from bits */
546     BYTE escape_code;           /* See enum Rle8_EscapeCodes.*/
547     int color;                  /* value of colour[color_index] */
548     
549     if (lines == 0)             /* Let's hope this doesn't happen. */
550       return;
551     
552     /*
553      * Note that the bitmap data is stored by Windows starting at the
554      * bottom line of the bitmap and going upwards.  Within each line,
555      * the data is stored left-to-right.  That's the reason why line
556      * goes from lines-1 to 0.                  [JAY]
557      */
558     
559     x = 0;
560     line = lines-1;
561     do
562       {
563           length = *pIn++;
564           
565           /* 
566            * If the length byte is not zero (which is the escape value),
567            * We have a run of length pixels all the same colour.  The colour 
568            * index is stored next. 
569            *
570            * If the length byte is zero, we need to read the next byte to
571            * know what to do.                   [JAY]
572            */
573           if (length != 0) 
574             {                                   
575                 /* 
576                  * [Run-Length] Encoded mode 
577                  */
578                 color_index = (*pIn++); /* Get the colour index. */
579                 color = colors[color_index];
580
581                 while(length--)
582                   XPutPixel(bmpImage, x++, line, color);
583             }
584           else 
585             {    
586                 /* 
587                  * Escape codes (may be an absolute sequence though)
588                  */
589                 escape_code = (*pIn++);
590                 switch(escape_code)
591                   {
592                     case RleEol: /* =0, end of line */
593                       {
594                           x = 0;  
595                           line--;  
596                           break;
597                       }
598                       
599                     case RleEnd: /* =1, end of bitmap */
600                       {
601                           /*
602                            * Not all RLE8 bitmaps end with this 
603                            * code.  For example, Paint Shop Pro 
604                            * produces some that don't.  That's (I think)
605                            * what caused the previous implementation to 
606                            * fail.                      [JAY]
607                            */
608                           line=-1; /* Cause exit from do loop. */
609                           break;
610                       }
611                       
612                     case RleDelta: /* =2, a delta */
613                       {
614                           /* 
615                            * Note that deltaing to line 0 
616                            * will cause an exit from the loop, 
617                            * which may not be what is intended. 
618                            * The fact that there is a delta in the bits
619                            * almost certainly implies that there is data
620                            * to follow.  You may feel that we should 
621                            * jump to the top of the loop to avoid exiting
622                            * in this case.  
623                            *
624                            * TODO: Decide what to do here in that case. [JAY]
625                            */
626                           x     += (*pIn++); 
627                           line  -= (*pIn++);
628                           if (line == 0)
629                             {
630                               TRACE_(bitmap)("Delta to last line of bitmap "
631                                            "(wrongly?) causes loop exit\n");
632                             }
633                           break;
634                       }
635                       
636                     default:    /* >2, switch to absolute mode */
637                       {
638                           /* 
639                            * Absolute Mode 
640                            */
641                           length = escape_code;
642                           while(length--)
643                             {
644                                 color_index = (*pIn++);
645                                 XPutPixel(bmpImage, x++, line, 
646                                           colors[color_index]);
647                             }
648                           
649                           /*
650                            * If you think for a moment you'll realise that the
651                            * only time we could ever possibly read an odd
652                            * number of bytes is when there is a 0x00 (escape),
653                            * a value >0x02 (absolute mode) and then an odd-
654                            * length run.  Therefore this is the only place we
655                            * need to worry about it.  Everywhere else the
656                            * bytes are always read in pairs.  [JAY]
657                            */
658                           if (escape_code & 1) 
659                             pIn++; /* Throw away the pad byte. */
660                           break;
661                       }
662                   } /* switch (escape_code) : Escape sequence */
663             }  /* process either an encoded sequence or an escape sequence */
664           
665           /* We expect to come here more than once per line. */
666       } while (line >= 0);  /* Do this until the bitmap is filled */
667     
668     /*
669      * Everybody comes here at the end.
670      * Check how we exited the loop and print a message if it's a bit odd.
671      *                                          [JAY]
672      */
673     if ( (*(pIn-2) != 0/*escape*/) || (*(pIn-1)!= RleEnd) )
674       {
675         TRACE_(bitmap)("End-of-bitmap "
676                        "without (strictly) proper escape code.  Last two "
677                        "bytes were: %02X %02X.\n",
678                        (int)*(pIn-2),
679                        (int)*(pIn-1));           
680       }
681 }  
682
683
684 /***********************************************************************
685  *           X11DRV_DIB_SetImageBits_16
686  *
687  * SetDIBits for a 16-bit deep DIB.
688  */
689 static void X11DRV_DIB_SetImageBits_16( int lines, const BYTE *srcbits,
690                                  DWORD srcwidth, DWORD dstwidth, int left,
691                                  DC *dc, XImage *bmpImage )
692 {
693     DWORD x;
694     LPWORD ptr;
695     WORD val;
696     int h;
697     BYTE r, g, b;
698   
699     /* align to 32 bit */
700     DWORD linebytes = (srcwidth * 2 + 3) & ~3;
701
702     dstwidth += left;
703
704     ptr = (LPWORD) srcbits + left;
705
706     if (bmpImage->format == ZPixmap)
707     {
708         unsigned short indA, indB, indC, indD;
709         BYTE *imageBits;
710         
711         switch (bmpImage->bits_per_pixel)
712         {
713         case 16:                
714             indA = (bmpImage->byte_order == LSBFirst) ? 1 : 0;
715             indB = (indA == 1) ? 0 : 1;
716
717             if (lines > 0) {
718                 imageBits = (BYTE *)(bmpImage->data + (lines - 1)*bmpImage->bytes_per_line);
719                 for (h = lines - 1; h >= 0; h--) {
720                     for (x = left; x < dstwidth; x++, ptr++) {
721                         val = *ptr;
722                         imageBits[(x << 1) + indA] = (BYTE)((val >> 7) & 0x00ff);
723                         imageBits[(x << 1) + indB] = (BYTE)(((val << 1) & 0x00c0) | (val & 0x001f));
724                     }
725                     ptr = (LPWORD)(srcbits += linebytes) + left;
726                     imageBits -= bmpImage->bytes_per_line;
727                 }
728             } else {
729                 lines = -lines;
730                 imageBits = (BYTE *)bmpImage->data;
731                 for (h = 0; h < lines; h++) {
732                     for (x = left; x < dstwidth; x++, ptr++) {
733                         val = *ptr;
734                         imageBits[(x << 1) + indA] = (BYTE)((val >> 7) & 0x00ff);
735                         imageBits[(x << 1) + indB] = (BYTE)(((val << 1) & 0x00c0) | (val & 0x001f));
736                     }
737                     ptr = (LPWORD)(srcbits += linebytes) + left;
738                     imageBits += bmpImage->bytes_per_line;
739                 }
740             }
741             return;
742
743         case 32:
744             indA = (bmpImage->byte_order == LSBFirst) ? 3 : 0;
745             indB = (indA == 3) ? 2 : 1;
746             indC = (indB == 2) ? 1 : 2;                                 
747             indD = (indC == 1) ? 0 : 3;
748
749             if (lines > 0) {
750                 imageBits = (BYTE *)(bmpImage->data + (lines - 1)*bmpImage->bytes_per_line);
751                 for (h = lines - 1; h >= 0; h--) {
752                     for (x = left; x < dstwidth; x++, ptr ++) {
753                         val = *ptr;
754                         imageBits[(x << 2) + indA] = 0x00; /* a */
755                         imageBits[(x << 2) + indB] = (BYTE)(((val >> 7) & 0x00f8) | ((val >> 12) & 0x0007));  /* red */
756                         imageBits[(x << 2) + indC] = (BYTE)(((val >> 2) & 0x00f8) | ((val >> 7) & 0x0007));   /* green */
757                         imageBits[(x << 2) + indD] = (BYTE)(((val << 3) & 0x00f8) | ((val >> 2) & 0x0007));   /* blue */
758                     }
759                     ptr = (LPWORD)(srcbits += linebytes) + left;
760                     imageBits -= bmpImage->bytes_per_line;
761                 }
762             } else {
763                 lines = -lines;
764                 imageBits = (BYTE *)bmpImage->data;
765                 for (h = 0; h < lines; h++) {
766                     for (x = left; x < dstwidth; x++, ptr ++) {
767                         val = *ptr;
768                         imageBits[(x << 2) + indA] = 0x00;
769                         imageBits[(x << 2) + indB] = (BYTE)(((val >> 7) & 0x00f8) | ((val >> 12) & 0x0007));
770                         imageBits[(x << 2) + indC] = (BYTE)(((val >> 2) & 0x00f8) | ((val >> 7) & 0x0007));
771                         imageBits[(x << 2) + indD] = (BYTE)(((val << 3) & 0x00f8) | ((val >> 2) & 0x0007));
772                     }
773                     ptr = (LPWORD)(srcbits += linebytes) + left;
774                     imageBits += bmpImage->bytes_per_line;
775                 }
776             }
777             return;
778         }
779     }
780
781     /* Not standard format or Not RGB */
782     if (lines > 0) {
783         for (h = lines - 1; h >= 0; h--) {
784             for (x = left; x < dstwidth; x++, ptr++) {
785                 val = *ptr;
786                 r = (BYTE) ((val & 0x7c00) >> 7);
787                 g = (BYTE) ((val & 0x03e0) >> 2);
788                 b = (BYTE) ((val & 0x001f) << 3);
789                 XPutPixel( bmpImage, x, h,
790                            X11DRV_PALETTE_ToPhysical(dc, RGB(r,g,b)) );
791             }
792             ptr = (LPWORD) (srcbits += linebytes) + left;
793         }
794     } else {
795         lines = -lines;
796         for (h = 0; h < lines; h++) {
797             for (x = left; x < dstwidth; x++, ptr++) {
798                 val = *ptr;
799                 r = (BYTE) ((val & 0x7c00) >> 7);
800                 g = (BYTE) ((val & 0x03e0) >> 2);
801                 b = (BYTE) ((val & 0x001f) << 3);
802                 XPutPixel( bmpImage, x, h,
803                            X11DRV_PALETTE_ToPhysical(dc, RGB(r,g,b)) );
804             }
805             ptr = (LPWORD) (srcbits += linebytes) + left;
806         }
807     }
808 }
809
810
811 /***********************************************************************
812  *           X11DRV_DIB_GetImageBits_16
813  *
814  * GetDIBits for an 16-bit deep DIB.
815  */
816 static void X11DRV_DIB_GetImageBits_16( int lines, BYTE *srcbits,
817                                  DWORD srcwidth, DWORD dstwidth, int left,
818                                  XImage *bmpImage )
819 {
820     DWORD x;
821     LPWORD ptr;
822     int h;
823     BYTE r, g, b;
824
825     /* align to 32 bit */
826     DWORD linebytes = (srcwidth * 2 + 3) & ~3;
827
828     dstwidth += left;
829
830     ptr = (LPWORD) srcbits + left;
831     if (lines > 0) {
832        for (h = lines - 1; h >= 0; h--)
833         {
834            for (x = left; x < dstwidth; x++, ptr++)
835             {
836                 COLORREF pixel = X11DRV_PALETTE_ToLogical( XGetPixel( bmpImage, x, h ) );
837                r = (BYTE) GetRValue(pixel);
838                g = (BYTE) GetGValue(pixel);
839                b = (BYTE) GetBValue(pixel);
840                 *ptr = ( ((r << 7) & 0x7c00) | ((g << 2) & 0x03e0) | ((b >> 3) & 0x001f) );
841            }
842            ptr = (LPWORD) (srcbits += linebytes) + left;
843        }
844     } else {
845        lines = -lines;
846        for (h = 0; h < lines; h++)
847         {
848            for (x = left; x < dstwidth; x++, ptr++)
849             {
850                 COLORREF pixel = X11DRV_PALETTE_ToLogical( XGetPixel( bmpImage, x, h ) );
851                r = (BYTE) GetRValue(pixel);
852                g = (BYTE) GetGValue(pixel);
853                b = (BYTE) GetBValue(pixel);
854                 *ptr = ( ((r << 7) & 0x7c00) | ((g << 2) & 0x03e0) | ((b >> 3) & 0x001f) );
855            }
856
857            ptr = (LPWORD) (srcbits += linebytes) + left;
858        }
859     }
860 }
861
862
863
864 /***********************************************************************
865  *           X11DRV_DIB_SetImageBits_24
866  *
867  * SetDIBits for a 24-bit deep DIB.
868  */
869 static void X11DRV_DIB_SetImageBits_24( int lines, const BYTE *srcbits,
870                                  DWORD srcwidth, DWORD dstwidth, int left,
871                                  DC *dc, XImage *bmpImage )
872 {
873     DWORD x;
874     const BYTE *bits = srcbits + left * 3;
875     int h;
876   
877     /* align to 32 bit */
878     DWORD linebytes = (srcwidth * 3 + 3) & ~3;
879
880     dstwidth += left;
881
882     /* "bits" order is reversed for some reason */
883
884     if (bmpImage->format == ZPixmap)
885     {
886         unsigned short indA, indB, indC, indD;
887         BYTE *imageBits;
888         
889         switch (bmpImage->bits_per_pixel)
890         {
891         case 16:                
892             indA = (bmpImage->byte_order == LSBFirst) ? 1 : 0;
893             indB = (indA == 1) ? 0 : 1;
894
895             if (lines > 0) {
896                 imageBits = (BYTE *)(bmpImage->data + (lines - 1)*bmpImage->bytes_per_line);
897                 for (h = lines - 1; h >= 0; h--) {
898                     for (x = left; x < dstwidth; x++, bits += 3) {
899                         imageBits[(x << 1) + indA] = (bits[0] & 0xf8) | ((bits[1] >> 5) & 0x07);
900                         imageBits[(x << 1) + indB] = ((bits[1] << 3) & 0xc0) | ((bits[2] >> 3) & 0x1f);
901                     }
902                     bits = (srcbits += linebytes) + left * 3;
903                     imageBits -= bmpImage->bytes_per_line;
904                 }
905             } else {
906                 lines = -lines;
907                 imageBits = (BYTE *)bmpImage->data;
908                 for (h = 0; h < lines; h++) {
909                     for (x = left; x < dstwidth; x++, bits += 3) {
910                         imageBits[(x << 1) + indA] = (bits[0] & 0xf8) | ((bits[1] >> 5) & 0x07);
911                         imageBits[(x << 1) + indB] = ((bits[1] << 3) & 0xc0) | ((bits[2] >> 3) & 0x1f);
912                     }
913                     bits = (srcbits += linebytes) + left * 3;
914                     imageBits += bmpImage->bytes_per_line;
915                 }
916             }
917             return;
918
919         case 32:
920             indA = (bmpImage->byte_order == LSBFirst) ? 3 : 0;
921             indB = (indA == 3) ? 2 : 1;
922             indC = (indB == 2) ? 1 : 2;
923             indD = (indC == 1) ? 0 : 3;
924
925             if (lines > 0) {
926                 imageBits = (BYTE *)(bmpImage->data + (lines - 1)*bmpImage->bytes_per_line);
927                 for (h = lines - 1; h >= 0; h--) {
928                     for (x = left; x < dstwidth; x++, bits += 3) {
929                         imageBits[(x << 2) + indA] = 0x00;      /*a*/
930                         imageBits[(x << 2) + indB] = bits[2];   /*red*/
931                         imageBits[(x << 2) + indC] = bits[1];   /*green*/
932                         imageBits[(x << 2) + indD] = bits[0];   /*blue*/
933                     }
934                     bits = (srcbits += linebytes) + left * 3;
935                     imageBits -= bmpImage->bytes_per_line;
936                 }
937             } else {
938                 lines = -lines;
939                 imageBits = (BYTE *)(bmpImage->data);
940                 for (h = 0; h < lines; h++) {
941                     for (x = left; x < dstwidth; x++, bits += 3) {
942                         imageBits[(x << 2) + indA] = 0x00;
943                         imageBits[(x << 2) + indB] = bits[2];
944                         imageBits[(x << 2) + indC] = bits[1];
945                         imageBits[(x << 2) + indD] = bits[0];
946                     }
947                     bits = (srcbits += linebytes) + left * 3;
948                     imageBits += bmpImage->bytes_per_line;
949                 }
950             }
951             return;
952         }
953     }
954         
955     /* Not standard format or Not RGB */
956     if (lines > 0) {
957         for (h = lines - 1; h >= 0; h--) {
958             for (x = left; x < dstwidth; x++, bits += 3) {
959                 XPutPixel( bmpImage, x, h, 
960                            X11DRV_PALETTE_ToPhysical(dc, RGB(bits[2],bits[1],bits[0])));
961             }
962             bits = (srcbits += linebytes) + left * 3;
963         }
964     } else {
965         lines = -lines;
966         for (h = 0; h < lines; h++) {
967             for (x = left; x < dstwidth; x++, bits += 3) {
968                 XPutPixel( bmpImage, x, h,
969                            X11DRV_PALETTE_ToPhysical(dc, RGB(bits[2],bits[1],bits[0])));
970             }
971             bits = (srcbits += linebytes) + left * 3;
972         }
973     }
974 }
975
976
977 /***********************************************************************
978  *           X11DRV_DIB_GetImageBits_24
979  *
980  * GetDIBits for an 24-bit deep DIB.
981  */
982 static void X11DRV_DIB_GetImageBits_24( int lines, BYTE *srcbits,
983                                  DWORD srcwidth, DWORD dstwidth, int left,
984                                  XImage *bmpImage )
985 {
986     DWORD x;
987     int h;
988     BYTE *bits = srcbits + (left * 3);
989
990     /* align to 32 bit */
991     DWORD linebytes = (srcwidth * 3 + 3) & ~3;
992
993     dstwidth += left;
994
995     if (lines > 0) {
996        for (h = lines - 1; h >= 0; h--)
997         {
998            for (x = left; x < dstwidth; x++, bits += 3)
999             {
1000                 COLORREF pixel = X11DRV_PALETTE_ToLogical( XGetPixel( bmpImage, x, h ) );
1001                 bits[0] = GetRValue(pixel);
1002                 bits[1] = GetGValue(pixel);
1003                 bits[2] = GetBValue(pixel);
1004            }
1005            bits = (srcbits += linebytes) + (left * 3);
1006        }
1007     } else {
1008        lines = -lines;
1009        for (h = 0; h < lines; h++)
1010         {
1011            for (x = left; x < dstwidth; x++, bits += 3)
1012             {
1013                 COLORREF pixel = X11DRV_PALETTE_ToLogical( XGetPixel( bmpImage, x, h ) );
1014                 bits[0] = GetRValue(pixel);
1015                 bits[1] = GetGValue(pixel);
1016                 bits[2] = GetBValue(pixel);
1017            }
1018
1019            bits = (srcbits += linebytes) + (left * 3);
1020        }
1021     }
1022 }
1023
1024
1025 /***********************************************************************
1026  *           X11DRV_DIB_SetImageBits_32
1027  *
1028  * SetDIBits for a 32-bit deep DIB.
1029  */
1030 static void X11DRV_DIB_SetImageBits_32( int lines, const BYTE *srcbits,
1031                                  DWORD srcwidth, DWORD dstwidth, int left,
1032                                  DC *dc, XImage *bmpImage )
1033 {
1034     DWORD x;
1035     const BYTE *bits = srcbits + left * 4;
1036     int h;
1037   
1038     DWORD linebytes = (srcwidth * 4);
1039
1040     dstwidth += left;
1041
1042     if (bmpImage->format == ZPixmap)
1043     {
1044         unsigned short indA, indB, indC, indD;
1045         BYTE *imageBits;
1046
1047         switch (bmpImage->bits_per_pixel)
1048         {
1049         case 16:                
1050             indA = (bmpImage->byte_order == LSBFirst) ? 1 : 0;
1051             indB = (indA == 1) ? 0 : 1;
1052
1053             if (lines > 0) {
1054                 imageBits = (BYTE *)(bmpImage->data + (lines - 1)*bmpImage->bytes_per_line);
1055                 for (h = lines - 1; h >= 0; h--) {
1056                     for (x = left; x < dstwidth; x++, bits += 4) {
1057                         imageBits[(x << 1) + indA] = (bits[0] & 0xf8) | ((bits[1] >> 5) & 0x07);
1058                         imageBits[(x << 1) + indB] = ((bits[1] << 3) & 0xc0) | ((bits[2] >> 3) & 0x1f);
1059                     }
1060                     bits = (srcbits += linebytes) + left * 4;
1061                     imageBits -= bmpImage->bytes_per_line;
1062                 }
1063             } else {
1064                 lines = -lines;
1065                 imageBits = (BYTE *)bmpImage->data;
1066                 for (h = 0; h < lines; h++) {
1067                     for (x = left; x < dstwidth; x++, bits += 4) {
1068                         imageBits[(x << 1) + indA] = (bits[0] & 0xf8) | ((bits[1] >> 5) & 0x07);
1069                         imageBits[(x << 1) + indB] = ((bits[1] << 3) & 0xc0) | ((bits[2] >> 3) & 0x1f);
1070                     }
1071                     bits = (srcbits += linebytes) + left * 4;
1072                     imageBits += bmpImage->bytes_per_line;
1073                 }
1074             }
1075             return;
1076
1077         case 32:
1078             indA = (bmpImage->byte_order == LSBFirst) ? 3 : 0;
1079             indB = (indA == 3) ? 2 : 1;
1080             indC = (indB == 2) ? 1 : 2;
1081             indD = (indC == 1) ? 0 : 3;
1082
1083             if (lines > 0) {
1084                 imageBits = (BYTE *)(bmpImage->data + (lines - 1)*bmpImage->bytes_per_line);
1085                 for (h = lines - 1; h >= 0; h--) {
1086                     for (x = left; x < dstwidth; x++, bits += 4) {
1087                         imageBits[(x << 2) + indA] = 0x00;      /*a*/
1088                         imageBits[(x << 2) + indB] = bits[2];   /*red*/
1089                         imageBits[(x << 2) + indC] = bits[1];   /*green*/
1090                         imageBits[(x << 2) + indD] = bits[0];   /*blue*/
1091                     }
1092                     bits = (srcbits += linebytes) + left * 4;
1093                     imageBits -= bmpImage->bytes_per_line;
1094                 }
1095             } else {
1096                 lines = -lines;
1097                 imageBits = (BYTE *)(bmpImage->data);
1098                 for (h = 0; h < lines; h++) {
1099                     for (x = left; x < dstwidth; x++, bits += 4) {
1100                         imageBits[(x << 2) + indA] = 0x00;
1101                         imageBits[(x << 2) + indB] = bits[2];
1102                         imageBits[(x << 2) + indC] = bits[1];
1103                         imageBits[(x << 2) + indD] = bits[0];
1104                     }
1105                     bits = (srcbits += linebytes) + left * 4;
1106                     imageBits += bmpImage->bytes_per_line;
1107                 }
1108             }
1109             return;
1110         }
1111     }
1112
1113     if (lines > 0) {
1114         for (h = lines - 1; h >= 0; h--) {
1115             for (x = left; x < dstwidth; x++, bits += 4) {
1116                 XPutPixel( bmpImage, x, h, 
1117                            X11DRV_PALETTE_ToPhysical(dc, RGB(bits[2],bits[1],bits[0])));
1118             }
1119             bits = (srcbits += linebytes) + left * 4;
1120         }
1121     } else {
1122         lines = -lines;
1123         for (h = 0; h < lines; h++) {
1124             for (x = left; x < dstwidth; x++, bits += 4) {
1125                 XPutPixel( bmpImage, x, h,
1126                            X11DRV_PALETTE_ToPhysical(dc, RGB(bits[2],bits[1],bits[0])));
1127             }
1128             bits = (srcbits += linebytes) + left * 4;
1129         }
1130     }
1131 }
1132
1133
1134 /***********************************************************************
1135  *           X11DRV_DIB_GetImageBits_32
1136  *
1137  * GetDIBits for an 32-bit deep DIB.
1138  */
1139 static void X11DRV_DIB_GetImageBits_32( int lines, BYTE *srcbits,
1140                                  DWORD srcwidth, DWORD dstwidth, int left,
1141                                  XImage *bmpImage )
1142 {
1143     DWORD x;
1144     int h;
1145     BYTE *bits = srcbits + (left * 4);
1146
1147     /* align to 32 bit */
1148     DWORD linebytes = (srcwidth * 4);
1149
1150     dstwidth += left;
1151
1152     if (lines > 0) {
1153        for (h = lines - 1; h >= 0; h--)
1154         {
1155            for (x = left; x < dstwidth; x++, bits += 4)
1156             {
1157                 COLORREF pixel = X11DRV_PALETTE_ToLogical( XGetPixel( bmpImage, x, h ) );
1158                 bits[0] = GetRValue(pixel);
1159                 bits[1] = GetGValue(pixel);
1160                 bits[2] = GetBValue(pixel);
1161            }
1162            bits = (srcbits += linebytes) + (left * 4);
1163        }
1164     } else {
1165        lines = -lines;
1166        for (h = 0; h < lines; h++)
1167         {
1168            for (x = left; x < dstwidth; x++, bits += 4)
1169             {
1170                 COLORREF pixel = X11DRV_PALETTE_ToLogical( XGetPixel( bmpImage, x, h ) );
1171                 bits[0] = GetRValue(pixel);
1172                 bits[1] = GetGValue(pixel);
1173                 bits[2] = GetBValue(pixel);
1174            }
1175
1176            bits = (srcbits += linebytes) + (left * 4);
1177        }
1178     }
1179 }
1180
1181
1182 /***********************************************************************
1183  *           X11DRV_DIB_SetImageBits
1184  *
1185  * Transfer the bits to an X image.
1186  * Helper function for SetDIBits() and SetDIBitsToDevice().
1187  * The Xlib critical section must be entered before calling this function.
1188  */
1189 int X11DRV_DIB_SetImageBits( const X11DRV_DIB_SETIMAGEBITS_DESCR *descr )
1190 {
1191     int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
1192     XImage *bmpImage;
1193
1194     if ( descr->dc && descr->dc->w.flags & DC_DIRTY ) 
1195         CLIPPING_UpdateGCRegion( descr->dc );
1196
1197     if (descr->image)
1198         bmpImage = descr->image;
1199     else {
1200         bmpImage = XCreateImage( display,
1201                                  DefaultVisualOfScreen(X11DRV_GetXScreen()),
1202                                  descr->depth, ZPixmap, 0, NULL,
1203                                  descr->infoWidth, lines, 32, 0 );
1204         bmpImage->data = xcalloc( bmpImage->bytes_per_line * lines );
1205     }
1206
1207       /* Transfer the pixels */
1208     switch(descr->infoBpp)
1209     {
1210     case 1:
1211         X11DRV_DIB_SetImageBits_1( descr->lines, descr->bits, descr->infoWidth,
1212                                    descr->width, descr->xSrc, descr->colorMap,
1213                                    bmpImage );
1214         break;
1215     case 4:
1216         if (descr->compression)
1217             X11DRV_DIB_SetImageBits_RLE4( descr->lines, descr->bits,
1218                                           descr->infoWidth, descr->width,
1219                                           descr->xSrc, descr->colorMap,
1220                                           bmpImage );
1221         else
1222             X11DRV_DIB_SetImageBits_4( descr->lines, descr->bits,
1223                                        descr->infoWidth, descr->width,
1224                                        descr->xSrc, descr->colorMap,
1225                                        bmpImage );
1226         break;
1227     case 8:
1228         if (descr->compression)
1229             X11DRV_DIB_SetImageBits_RLE8( descr->lines, descr->bits,
1230                                           descr->infoWidth, descr->width,
1231                                           descr->xSrc,
1232                                           descr->colorMap, bmpImage );
1233         else
1234             X11DRV_DIB_SetImageBits_8( descr->lines, descr->bits,
1235                                        descr->infoWidth, descr->width,
1236                                        descr->xSrc, descr->colorMap,
1237                                        bmpImage );
1238         break;
1239     case 15:
1240     case 16:
1241         X11DRV_DIB_SetImageBits_16( descr->lines, descr->bits,
1242                                     descr->infoWidth, descr->width,
1243                                     descr->xSrc, descr->dc, bmpImage);
1244         break;
1245     case 24:
1246         X11DRV_DIB_SetImageBits_24( descr->lines, descr->bits,
1247                                     descr->infoWidth, descr->width,
1248                                     descr->xSrc, descr->dc, bmpImage );
1249         break;
1250     case 32:
1251         X11DRV_DIB_SetImageBits_32( descr->lines, descr->bits,
1252                                     descr->infoWidth, descr->width,
1253                                     descr->xSrc, descr->dc, bmpImage);
1254         break;
1255     default:
1256         WARN_(bitmap)("(%d): Invalid depth\n", descr->infoBpp );
1257         break;
1258     }
1259
1260     XPutImage( display, descr->drawable, descr->gc, bmpImage,
1261                descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
1262                descr->width, descr->height );
1263
1264     if (!descr->image) XDestroyImage( bmpImage );
1265     return lines;
1266 }
1267
1268 /***********************************************************************
1269  *           X11DRV_DIB_GetImageBits
1270  *
1271  * Transfer the bits from an X image.
1272  * The Xlib critical section must be entered before calling this function.
1273  */
1274 int X11DRV_DIB_GetImageBits( const X11DRV_DIB_SETIMAGEBITS_DESCR *descr )
1275 {
1276     int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
1277     XImage *bmpImage;
1278
1279     if (descr->image)
1280         bmpImage = descr->image;
1281     else {
1282         bmpImage = XCreateImage( display,
1283                                  DefaultVisualOfScreen(X11DRV_GetXScreen()),
1284                                  descr->depth, ZPixmap, 0, NULL,
1285                                  descr->infoWidth, lines, 32, 0 );
1286         bmpImage->data = xcalloc( bmpImage->bytes_per_line * lines );
1287     }
1288
1289     XGetSubImage( display, descr->drawable, descr->xDest, descr->yDest,
1290                   descr->width, descr->height, AllPlanes, ZPixmap,
1291                   bmpImage, descr->xSrc, descr->ySrc );
1292
1293       /* Transfer the pixels */
1294     switch(descr->infoBpp)
1295     {
1296     case 1:
1297         FIXME_(bitmap)("Depth 1 not yet supported!\n");
1298        break;
1299
1300     case 4:
1301        if (descr->compression)
1302            FIXME_(bitmap)("Compression not yet supported!\n");
1303        else
1304            X11DRV_DIB_GetImageBits_4( descr->lines, 
1305                                       (LPVOID)descr->bits, descr->infoWidth,
1306                                       descr->width, descr->xSrc,
1307                                       descr->colorMap, descr->nColorMap,
1308                                       bmpImage );
1309        break;
1310
1311     case 8:
1312        if (descr->compression)
1313            FIXME_(bitmap)("Compression not yet supported!\n");
1314        else
1315            X11DRV_DIB_GetImageBits_8( descr->lines, (LPVOID)descr->bits,
1316                                       descr->infoWidth, descr->width,
1317                                       descr->xSrc, descr->colorMap,
1318                                       descr->nColorMap, bmpImage );
1319        break;
1320
1321     case 15:
1322     case 16:
1323        X11DRV_DIB_GetImageBits_16( descr->lines, (LPVOID)descr->bits,
1324                                    descr->infoWidth,
1325                                    descr->width, descr->xSrc, bmpImage );
1326        break;
1327
1328     case 24:
1329        X11DRV_DIB_GetImageBits_24( descr->lines, (LPVOID)descr->bits,
1330                                    descr->infoWidth,
1331                                    descr->width, descr->xSrc, bmpImage );
1332        break;
1333
1334     case 32:
1335        X11DRV_DIB_GetImageBits_32( descr->lines, (LPVOID)descr->bits,
1336                                    descr->infoWidth,
1337                                    descr->width, descr->xSrc, bmpImage );
1338        break;
1339
1340     default:
1341         WARN_(bitmap)("(%d): Invalid depth\n", descr->infoBpp );
1342         break;
1343     }
1344
1345     if (!descr->image) XDestroyImage( bmpImage );
1346     return lines;
1347 }
1348
1349 /*************************************************************************
1350  *              X11DRV_SetDIBitsToDevice
1351  *
1352  */
1353 INT X11DRV_SetDIBitsToDevice( DC *dc, INT xDest, INT yDest, DWORD cx,
1354                                 DWORD cy, INT xSrc, INT ySrc,
1355                                 UINT startscan, UINT lines, LPCVOID bits,
1356                                 const BITMAPINFO *info, UINT coloruse )
1357 {
1358     X11DRV_DIB_SETIMAGEBITS_DESCR descr;
1359     DWORD width, oldcy = cy;
1360     INT result;
1361     int height, tmpheight;
1362     X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
1363
1364
1365     if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, 
1366                            &descr.infoBpp, &descr.compression ) == -1)
1367         return 0;
1368     tmpheight = height;
1369     if (height < 0) height = -height;
1370     if (!lines || (startscan >= height)) return 0;
1371     if (startscan + lines > height) lines = height - startscan;
1372     if (ySrc < startscan) ySrc = startscan;
1373     else if (ySrc >= startscan + lines) return 0;
1374     if (xSrc >= width) return 0;
1375     if (ySrc + cy >= startscan + lines) cy = startscan + lines - ySrc;
1376     if (xSrc + cx >= width) cx = width - xSrc;
1377     if (!cx || !cy) return 0;
1378
1379     X11DRV_SetupGCForText( dc );  /* To have the correct colors */
1380     TSXSetFunction(display, physDev->gc, X11DRV_XROPfunction[dc->w.ROPmode-1]);
1381
1382     if (descr.infoBpp <= 8)
1383     {
1384         descr.colorMap = X11DRV_DIB_BuildColorMap( dc, coloruse,
1385                                                    dc->w.bitsPerPixel,
1386                                                    info, &descr.nColorMap );
1387         if (!descr.colorMap)
1388             return 0;
1389     }
1390
1391     descr.dc        = dc;
1392     descr.bits      = bits;
1393     descr.image     = NULL;
1394     descr.lines     = tmpheight >= 0 ? lines : -lines;
1395     descr.infoWidth = width;
1396     descr.depth     = dc->w.bitsPerPixel;
1397     descr.drawable  = physDev->drawable;
1398     descr.gc        = physDev->gc;
1399     descr.xSrc      = xSrc;
1400     descr.ySrc      = tmpheight >= 0 ? lines-(ySrc-startscan)-cy+(oldcy-cy) 
1401                                      : ySrc - startscan;
1402     descr.xDest     = dc->w.DCOrgX + XLPTODP( dc, xDest );
1403     descr.yDest     = dc->w.DCOrgY + YLPTODP( dc, yDest ) +
1404                                      (tmpheight >= 0 ? oldcy-cy : 0);
1405     descr.width     = cx;
1406     descr.height    = cy;
1407
1408     EnterCriticalSection( &X11DRV_CritSection );
1409     result = CALL_LARGE_STACK( X11DRV_DIB_SetImageBits, &descr );
1410     LeaveCriticalSection( &X11DRV_CritSection );
1411
1412     if (descr.infoBpp <= 8)
1413        HeapFree(GetProcessHeap(), 0, descr.colorMap);
1414     return result;
1415 }
1416
1417 /***********************************************************************
1418  *           X11DRV_DIB_SetDIBits
1419  */
1420 INT X11DRV_DIB_SetDIBits(
1421   BITMAPOBJ *bmp, DC *dc, UINT startscan,
1422   UINT lines, LPCVOID bits, const BITMAPINFO *info,
1423   UINT coloruse, HBITMAP hbitmap)
1424 {
1425   X11DRV_DIB_SETIMAGEBITS_DESCR descr;
1426   X11DRV_PHYSBITMAP *pbitmap;
1427   int height, tmpheight;
1428   INT result;
1429
1430   descr.dc = dc;
1431
1432   if (DIB_GetBitmapInfo( &info->bmiHeader, &descr.infoWidth, &height,
1433                          &descr.infoBpp, &descr.compression ) == -1)
1434       return 0;
1435
1436   tmpheight = height;
1437   if (height < 0) height = -height;
1438   if (!lines || (startscan >= height))
1439       return 0;
1440
1441   if (startscan + lines > height) lines = height - startscan;
1442
1443   if (descr.infoBpp <= 8)
1444     {
1445       descr.colorMap = X11DRV_DIB_BuildColorMap(
1446                 coloruse == DIB_PAL_COLORS? descr.dc : NULL,
1447                 coloruse, bmp->bitmap.bmBitsPixel, info, &descr.nColorMap );
1448       if (!descr.colorMap)
1449         {
1450           return 0;
1451         } 
1452     } else
1453       descr.colorMap = 0;
1454
1455   /* HACK for now */
1456   if(!bmp->DDBitmap)
1457     X11DRV_CreateBitmap(hbitmap);
1458
1459   pbitmap = bmp->DDBitmap->physBitmap;
1460   
1461   descr.bits      = bits;
1462   descr.image     = NULL;
1463   descr.lines     = tmpheight >= 0 ? lines : -lines;
1464   descr.depth     = bmp->bitmap.bmBitsPixel;
1465   descr.drawable  = pbitmap->pixmap;
1466   descr.gc        = BITMAP_GC(bmp);
1467   descr.xSrc      = 0;
1468   descr.ySrc      = 0;
1469   descr.xDest     = 0;
1470   descr.yDest     = height - startscan - lines;
1471   descr.width     = bmp->bitmap.bmWidth;
1472   descr.height    = lines;
1473   
1474   EnterCriticalSection( &X11DRV_CritSection );
1475   result = CALL_LARGE_STACK( X11DRV_DIB_SetImageBits, &descr );
1476   LeaveCriticalSection( &X11DRV_CritSection );
1477   
1478   if (descr.colorMap) HeapFree(GetProcessHeap(), 0, descr.colorMap);
1479
1480   return result;
1481 }
1482
1483
1484 /*********************************************************************
1485  *         X11DRV_DIB_GetNearestIndex
1486  *
1487  * Helper for X11DRV_DIB_GetDIBits.
1488  * Returns the nearest colour table index for a given RGB.
1489  * Nearest is defined by minimizing the sum of the squares.
1490  */
1491 static INT X11DRV_DIB_GetNearestIndex(BITMAPINFO *info, BYTE r, BYTE g, BYTE b)
1492 {
1493     INT i, best = -1, diff, bestdiff = -1;
1494     RGBQUAD *color;
1495
1496     for(color = info->bmiColors, i = 0; i < (1 << info->bmiHeader.biBitCount);
1497         color++, i++) {
1498         diff = (r - color->rgbRed) * (r - color->rgbRed) +
1499                (g - color->rgbGreen) * (g - color->rgbGreen) +
1500                (b - color->rgbBlue) * (b - color->rgbBlue);
1501         if(diff == 0)
1502             return i;
1503         if(best == -1 || diff < bestdiff) {
1504             best = i;
1505             bestdiff = diff;
1506         }
1507     }
1508     return best;
1509 }
1510
1511 /***********************************************************************
1512  *           X11DRV_DIB_GetDIBits
1513  */
1514 INT X11DRV_DIB_GetDIBits(
1515   BITMAPOBJ *bmp, DC *dc, UINT startscan, 
1516   UINT lines, LPVOID bits, BITMAPINFO *info,
1517   UINT coloruse, HBITMAP hbitmap)
1518 {
1519   XImage * bmpImage;
1520   int x, y;
1521   PALETTEENTRY * palEntry;
1522   PALETTEOBJ * palette;
1523   BYTE    *bbits = (BYTE*)bits, *linestart;
1524   int   dstwidth, yend, xend = bmp->bitmap.bmWidth;
1525   
1526   TRACE_(bitmap)("%u scanlines of (%i,%i) -> (%i,%i) starting from %u\n",
1527         lines, bmp->bitmap.bmWidth, bmp->bitmap.bmHeight,
1528         (int)info->bmiHeader.biWidth, (int)info->bmiHeader.biHeight,
1529         startscan );
1530
1531   if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->w.hPalette, PALETTE_MAGIC )))
1532       return 0;
1533
1534   /* adjust number of scanlines to copy */
1535   
1536   if( lines > info->bmiHeader.biHeight )
1537     lines = info->bmiHeader.biHeight;
1538   
1539   yend = startscan + lines;
1540   if( startscan >= bmp->bitmap.bmHeight ) 
1541     {
1542       return FALSE;
1543     }
1544   if( yend > bmp->bitmap.bmHeight ) yend = bmp->bitmap.bmHeight;
1545   
1546   /* adjust scanline width */
1547   
1548   if(bmp->bitmap.bmWidth > info->bmiHeader.biWidth)
1549     xend = info->bmiHeader.biWidth;
1550   
1551   /* HACK for now */
1552   if(!bmp->DDBitmap)
1553     X11DRV_CreateBitmap(hbitmap);
1554   
1555   dstwidth = DIB_GetDIBWidthBytes( info->bmiHeader.biWidth,
1556                                    info->bmiHeader.biBitCount );
1557
1558   EnterCriticalSection( &X11DRV_CritSection );
1559   bmpImage = (XImage *)CALL_LARGE_STACK( X11DRV_BITMAP_GetXImage, bmp );
1560   
1561   linestart = bbits;
1562   switch( info->bmiHeader.biBitCount ) {
1563
1564   case 1: /* 1 bit DIB */
1565     {
1566       unsigned long white = (1 << bmp->bitmap.bmBitsPixel) - 1;
1567       
1568       for( y = yend - 1; (int)y >= (int)startscan; y-- ) {
1569         for( x = 0; x < xend; x++ ) {
1570           if (!(x&7)) *bbits = 0;
1571           *bbits |= (XGetPixel( bmpImage, x, y) >= white) 
1572             << (7 - (x&7));
1573           if ((x&7)==7) bbits++;
1574         }
1575         bbits = (linestart += dstwidth);
1576       }
1577     }
1578     break;
1579     
1580     
1581   case 4: /* 4 bit DIB */
1582     switch(bmp->bitmap.bmBitsPixel) {
1583       
1584     case 1: /* 1/4 bit bmp -> 4 bit DIB */
1585     case 4:
1586       for( y = yend - 1; (int)y >= (int)startscan; y-- ) {
1587         for( x = 0; x < xend; x++ ) {
1588           if (!(x&1)) *bbits = 0;
1589           *bbits |= XGetPixel( bmpImage, x, y)<<(4*(1-(x&1)));
1590           if ((x&1)==1) bbits++;
1591         }
1592         bbits = (linestart += dstwidth);
1593       }
1594       break;
1595       
1596     case 8: /* 8 bit bmp -> 4 bit DIB */
1597       palEntry = palette->logpalette.palPalEntry;
1598       for( y = yend - 1; (int)y >= (int)startscan; y-- ) {
1599         for( x = 0; x < xend; x++ ) {
1600           unsigned long pixel = XGetPixel( bmpImage, x, y );
1601           if (!(x&1)) *bbits = 0;
1602           *bbits |= ( X11DRV_DIB_GetNearestIndex(info,
1603                                                  palEntry[pixel].peRed,
1604                                                  palEntry[pixel].peGreen,
1605                                                  palEntry[pixel].peBlue )
1606                       << (4*(1-(x&1))) );
1607           if ((x&1)==1) bbits++;
1608         }
1609         bbits = (linestart += dstwidth);
1610       }
1611       break;
1612       
1613     case 15: /* 15/16 bit bmp -> 4 bit DIB */
1614     case 16:
1615       for( y = yend - 1; (int)y >= (int)startscan; y-- ) {
1616         for( x = 0; x < xend; x++ ) {
1617           unsigned long pixel = XGetPixel( bmpImage, x, y );
1618           if (!(x&1)) *bbits = 0;
1619           *bbits |= ( X11DRV_DIB_GetNearestIndex(info,
1620                                                  ((pixel << 3) & 0xf8) |
1621                                                  ((pixel >> 2) &  0x7),
1622                                                  ((pixel >> 2) & 0xf8) |
1623                                                  ((pixel >> 7) & 0x7),
1624                                                  ((pixel >> 7) & 0xf8) |
1625                                                  ((pixel >> 12) & 0x7) ) 
1626                       << (4*(1-(x&1))) );
1627           if ((x&1)==1) bbits++;
1628         }
1629         bbits = (linestart += dstwidth);
1630       }
1631       break;
1632       
1633     case 24: /* 24/32 bit bmp -> 4 bit DIB */
1634     case 32:
1635       for( y = yend - 1; (int)y >= (int)startscan; y-- ) {
1636         for( x = 0; x < xend; x++ ) {
1637           unsigned long pixel = XGetPixel( bmpImage, x, y );
1638           if (!(x&1)) *bbits = 0;
1639           *bbits |= ( X11DRV_DIB_GetNearestIndex( info,
1640                                                   (pixel >> 16) & 0xff,
1641                                                   (pixel >>  8) & 0xff,
1642                                                   pixel & 0xff )
1643                       << (4*(1-(x&1))) );
1644           if ((x&1)==1) bbits++;
1645         }
1646         bbits = (linestart += dstwidth);
1647       }
1648       break;
1649
1650     default: /* ? bit bmp -> 4 bit DIB */
1651       FIXME_(bitmap)("4 bit DIB %d bit bitmap\n",
1652             bmp->bitmap.bmBitsPixel);
1653       break;
1654     }
1655     break;
1656
1657
1658   case 8: /* 8 bit DIB */
1659     switch(bmp->bitmap.bmBitsPixel) {
1660       
1661     case 1: /* 1/4/8 bit bmp -> 8 bit DIB */
1662     case 4:
1663     case 8:
1664       for( y = yend - 1; (int)y >= (int)startscan; y-- ) {
1665         for( x = 0; x < xend; x++ )
1666           *bbits++ = XGetPixel( bmpImage, x, y );
1667         bbits = (linestart += dstwidth);
1668       }
1669       break;
1670       
1671     case 15: /* 15/16 bit bmp -> 8 bit DIB */
1672     case 16:
1673       for( y = yend - 1; (int)y >= (int)startscan; y-- ) {
1674         for( x = 0; x < xend; x++ ) {
1675           unsigned long pixel = XGetPixel( bmpImage, x, y );
1676           *bbits++ = X11DRV_DIB_GetNearestIndex( info, 
1677                                                  ((pixel << 3) & 0xf8) |
1678                                                  ((pixel >> 2) &  0x7),
1679                                                  ((pixel >> 2) & 0xf8) |
1680                                                  ((pixel >> 7) & 0x7),
1681                                                  ((pixel >> 7) & 0xf8) |
1682                                                  ((pixel >> 12) & 0x7) );
1683         }
1684         bbits = (linestart += dstwidth);
1685       }
1686       break;
1687       
1688     case 24: /* 24/32 bit bmp -> 8 bit DIB */
1689     case 32:
1690       for( y = yend - 1; (int)y >= (int)startscan; y-- ) {
1691         for( x = 0; x < xend; x++ ) {
1692           unsigned long pixel = XGetPixel( bmpImage, x, y );
1693           *bbits++ = X11DRV_DIB_GetNearestIndex( info,
1694                                                  (pixel >> 16) & 0xff,
1695                                                  (pixel >>  8) & 0xff,
1696                                                  pixel & 0xff );
1697         }
1698         bbits = (linestart += dstwidth);
1699       }
1700       break;
1701       
1702     default: /* ? bit bmp -> 8 bit DIB */
1703       FIXME_(bitmap)("8 bit DIB %d bit bitmap\n",
1704             bmp->bitmap.bmBitsPixel);
1705       break;
1706     }
1707     break;
1708     
1709
1710   case 15: /* 15/16 bit DIB */
1711   case 16:
1712     switch(bmp->bitmap.bmBitsPixel) {
1713       
1714     case 15: /* 15/16 bit bmp -> 16 bit DIB */
1715     case 16:
1716       for( y = yend - 1; (int)y >= (int)startscan; y-- ) {
1717         for( x = 0; x < xend; x++ ) {
1718           unsigned long pixel=XGetPixel( bmpImage, x, y);
1719           *bbits++ = pixel & 0xff;
1720           *bbits++ = (pixel >> 8) & 0xff;
1721         }
1722         bbits = (linestart += dstwidth);
1723       }
1724       break;
1725       
1726     case 24: /* 24/32 bit bmp -> 16 bit DIB */
1727     case 32:
1728       for( y = yend - 1; (int)y >= (int)startscan; y-- ) {
1729         for( x = 0; x < xend; x++ ) {
1730           unsigned long pixel=XGetPixel( bmpImage, x, y);
1731           *bbits++ = ((pixel >> 6) & 0xe0) |
1732             ((pixel >> 3) & 0x1f);
1733           *bbits++ = ((pixel >> 17) & 0x7c) |
1734             ((pixel >> 14) & 0x3);
1735         }
1736         bbits = (linestart += dstwidth);
1737       }
1738       break;
1739       
1740     case 1: /* 1/4/8 bit bmp -> 16 bit DIB */
1741     case 4:
1742     case 8:
1743       palEntry = palette->logpalette.palPalEntry;
1744       for( y = yend - 1; (int)y >= (int)startscan; y-- ) {
1745         for( x = 0; x < xend; x++ ) {
1746           unsigned long pixel=XGetPixel( bmpImage, x, y);
1747           *bbits++ = ((palEntry[pixel].peBlue >> 3) & 0x1f) |
1748             ((palEntry[pixel].peGreen << 2) & 0xe0); 
1749           *bbits++ = ((palEntry[pixel].peGreen >> 6) & 0x3) |
1750             ((palEntry[pixel].peRed >> 1) & 0x7c);
1751         }
1752         bbits = (linestart += dstwidth);
1753       }
1754       break;
1755       
1756     default: /* ? bit bmp -> 16 bit DIB */
1757       FIXME_(bitmap)("15/16 bit DIB %d bit bitmap\n",
1758             bmp->bitmap.bmBitsPixel);
1759       break;
1760     }
1761     break;
1762     
1763
1764   case 24: /* 24 bit DIB */
1765     switch(bmp->bitmap.bmBitsPixel) {
1766       
1767     case 24: /* 24/32 bit bmp -> 24 bit DIB */
1768     case 32:
1769       for( y = yend - 1; (int)y >= (int)startscan; y-- ) {
1770         for( x = 0; x < xend; x++ ) {
1771           unsigned long pixel=XGetPixel( bmpImage, x, y);
1772           *bbits++ = (pixel >>16) & 0xff;
1773           *bbits++ = (pixel >> 8) & 0xff;
1774           *bbits++ =  pixel       & 0xff;
1775         }
1776         bbits = (linestart += dstwidth);
1777       }
1778       break;
1779       
1780     case 15: /* 15/16 bit bmp -> 24 bit DIB */
1781     case 16:
1782       for( y = yend - 1; (int)y >= (int)startscan; y-- ) {
1783         for( x = 0; x < xend; x++ ) {
1784           unsigned long pixel=XGetPixel( bmpImage, x, y);
1785           *bbits++ = ((pixel >> 7) & 0xf8) |
1786             ((pixel >> 12) & 0x7);
1787           *bbits++ = ((pixel >> 2) & 0xf8) |
1788             ((pixel >> 7) & 0x7);
1789           *bbits++ = ((pixel << 3) & 0xf8) |
1790             ((pixel >> 2) & 0x7);
1791         }
1792         bbits = (linestart += dstwidth);
1793       }
1794       break;
1795       
1796     case 1: /* 1/4/8 bit bmp -> 24 bit DIB */
1797     case 4:
1798     case 8:
1799       palEntry = palette->logpalette.palPalEntry;
1800       for( y = yend - 1; (int)y >= (int)startscan; y-- ) {
1801         for( x = 0; x < xend; x++ ) {
1802           unsigned long pixel=XGetPixel( bmpImage, x, y);
1803           *bbits++ = palEntry[pixel].peBlue;
1804           *bbits++ = palEntry[pixel].peGreen;
1805           *bbits++ = palEntry[pixel].peRed;
1806         }
1807         bbits = (linestart += dstwidth);
1808       }
1809       break;
1810       
1811     default: /* ? bit bmp -> 24 bit DIB */
1812       FIXME_(bitmap)("24 bit DIB %d bit bitmap\n",
1813             bmp->bitmap.bmBitsPixel);
1814       break;
1815     }
1816     break;
1817     
1818
1819   case 32: /* 32 bit DIB */
1820     switch(bmp->bitmap.bmBitsPixel) {
1821       
1822     case 24: /* 24/32 bit bmp -> 32 bit DIB */
1823     case 32:
1824       for( y = yend - 1; (int)y >= (int)startscan; y-- ) {
1825         for( x = 0; x < xend; x++ ) {
1826           unsigned long pixel=XGetPixel( bmpImage, x, y);
1827           *bbits++ = (pixel >>16) & 0xff;
1828           *bbits++ = (pixel >> 8) & 0xff;
1829           *bbits++ =  pixel       & 0xff;
1830           *bbits++ = 0;
1831         }
1832         bbits = (linestart += dstwidth);
1833       }
1834       break;
1835
1836     case 15: /* 15/16 bit bmp -> 32 bit DIB */
1837     case 16:
1838       for( y = yend - 1; (int)y >= (int)startscan; y-- ) {
1839         for( x = 0; x < xend; x++ ) {
1840           unsigned long pixel=XGetPixel( bmpImage, x, y);
1841           *bbits++ = ((pixel >> 7) & 0xf8) |
1842             ((pixel >> 12) & 0x7);
1843           *bbits++ = ((pixel >> 2) & 0xf8) |
1844             ((pixel >> 7) & 0x7);
1845           *bbits++ = ((pixel << 3) & 0xf8) |
1846             ((pixel >> 2) & 0x7);
1847           *bbits++ = 0;
1848         }
1849         bbits = (linestart += dstwidth);
1850       }
1851       break;
1852       
1853     case 1: /* 1/4/8 bit bmp -> 32 bit DIB */
1854     case 4:
1855     case 8:
1856       palEntry = palette->logpalette.palPalEntry;
1857       for( y = yend - 1; (int)y >= (int)startscan; y-- ) {
1858         for( x = 0; x < xend; x++ ) {
1859           unsigned long pixel=XGetPixel( bmpImage, x, y);
1860           *bbits++ = palEntry[pixel].peBlue;
1861           *bbits++ = palEntry[pixel].peGreen;
1862           *bbits++ = palEntry[pixel].peRed;
1863           *bbits++ = 0;
1864         }
1865         bbits = (linestart += dstwidth);
1866       }
1867       break;
1868
1869     default: /* ? bit bmp -> 32 bit DIB */
1870       FIXME_(bitmap)("32 bit DIB %d bit bitmap\n",
1871             bmp->bitmap.bmBitsPixel);
1872       break;
1873     }
1874     break;
1875
1876
1877   default: /* ? bit DIB */
1878     FIXME_(bitmap)("Unsupported DIB depth %d\n",
1879           info->bmiHeader.biBitCount);
1880     break;
1881   }
1882
1883   XDestroyImage( bmpImage );
1884   LeaveCriticalSection( &X11DRV_CritSection );
1885   
1886   if(info->bmiHeader.biSizeImage == 0) /* Fill in biSizeImage */
1887     info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(
1888                                          info->bmiHeader.biWidth,
1889                                          info->bmiHeader.biHeight,
1890                                          info->bmiHeader.biBitCount );
1891
1892   if(bbits - (BYTE *)bits > info->bmiHeader.biSizeImage)
1893     ERR_(bitmap)("Buffer overrun. Please investigate.\n");
1894
1895   info->bmiHeader.biCompression = 0;
1896
1897   GDI_HEAP_UNLOCK( dc->w.hPalette );
1898   
1899   return lines;
1900 }
1901
1902 /***********************************************************************
1903  *           DIB_DoProtectDIBSection
1904  */
1905 static void X11DRV_DIB_DoProtectDIBSection( BITMAPOBJ *bmp, DWORD new_prot )
1906 {
1907     DIBSECTION *dib = bmp->dib;
1908     INT effHeight = dib->dsBm.bmHeight >= 0? dib->dsBm.bmHeight
1909                                              : -dib->dsBm.bmHeight;
1910     INT totalSize = dib->dsBmih.biSizeImage? dib->dsBmih.biSizeImage
1911                          : dib->dsBm.bmWidthBytes * effHeight;
1912     DWORD old_prot;
1913
1914     VirtualProtect(dib->dsBm.bmBits, totalSize, new_prot, &old_prot);
1915     TRACE_(bitmap)("Changed protection from %ld to %ld\n", 
1916                   old_prot, new_prot);
1917 }
1918
1919 /***********************************************************************
1920  *           X11DRV_DIB_DoUpdateDIBSection
1921  */
1922 static void X11DRV_DIB_DoUpdateDIBSection(BITMAPOBJ *bmp, BOOL toDIB)
1923 {
1924   X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
1925   X11DRV_DIB_SETIMAGEBITS_DESCR descr;
1926   
1927   if (DIB_GetBitmapInfo( &dib->dibSection.dsBmih, &descr.infoWidth, &descr.lines,
1928                          &descr.infoBpp, &descr.compression ) == -1)
1929     return;
1930
1931   descr.dc        = NULL;
1932   descr.image     = dib->image;
1933   descr.colorMap  = dib->colorMap;
1934   descr.nColorMap = dib->nColorMap;
1935   descr.bits      = dib->dibSection.dsBm.bmBits;
1936   descr.depth     = bmp->bitmap.bmBitsPixel;
1937   
1938   /* Hack for now */
1939   descr.drawable  = ((X11DRV_PHYSBITMAP *)bmp->DDBitmap->physBitmap)->pixmap;
1940   descr.gc        = BITMAP_GC(bmp);
1941   descr.xSrc      = 0;
1942   descr.ySrc      = 0;
1943   descr.xDest     = 0;
1944   descr.yDest     = 0;
1945   descr.width     = bmp->bitmap.bmWidth;
1946   descr.height    = bmp->bitmap.bmHeight;
1947
1948   if (toDIB)
1949     {
1950       TRACE_(bitmap)("Copying from Pixmap to DIB bits\n");
1951       EnterCriticalSection( &X11DRV_CritSection );
1952       CALL_LARGE_STACK( X11DRV_DIB_GetImageBits, &descr );
1953       LeaveCriticalSection( &X11DRV_CritSection );
1954     }
1955   else
1956     {
1957       TRACE_(bitmap)("Copying from DIB bits to Pixmap\n"); 
1958       EnterCriticalSection( &X11DRV_CritSection );
1959       CALL_LARGE_STACK( X11DRV_DIB_SetImageBits, &descr );
1960       LeaveCriticalSection( &X11DRV_CritSection );
1961     }
1962 }
1963
1964 /***********************************************************************
1965  *           X11DRV_DIB_FaultHandler
1966  */
1967 static BOOL X11DRV_DIB_FaultHandler( LPVOID res, LPCVOID addr )
1968 {
1969   BOOL handled = FALSE;
1970   BITMAPOBJ *bmp;
1971   
1972   bmp = (BITMAPOBJ *)GDI_GetObjPtr( (HBITMAP)res, BITMAP_MAGIC );
1973   if (!bmp) return FALSE;
1974   
1975   if (bmp->dib)
1976     switch (((X11DRV_DIBSECTION *) bmp->dib)->status)
1977       {
1978       case X11DRV_DIB_GdiMod:
1979         TRACE_(bitmap)("called in status DIB_GdiMod\n" );
1980         X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
1981         X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
1982         X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
1983         ((X11DRV_DIBSECTION *) bmp->dib)->status = X11DRV_DIB_InSync;
1984         handled = TRUE;
1985         break;
1986         
1987       case X11DRV_DIB_InSync:
1988         TRACE_(bitmap)("called in status X11DRV_DIB_InSync\n" );
1989         X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
1990         ((X11DRV_DIBSECTION *) bmp->dib)->status = X11DRV_DIB_AppMod;
1991         handled = TRUE;
1992         break;
1993         
1994       case X11DRV_DIB_AppMod:
1995         FIXME_(bitmap)("called in status X11DRV_DIB_AppMod: "
1996                "this can't happen!\n" );
1997         break;
1998         
1999       case X11DRV_DIB_NoHandler:
2000         FIXME_(bitmap)("called in status DIB_NoHandler: "
2001                "this can't happen!\n" );
2002         break;
2003       }
2004   
2005   GDI_HEAP_UNLOCK( (HBITMAP)res );
2006   return handled;
2007 }
2008
2009 /***********************************************************************
2010  *           X11DRV_DIB_UpdateDIBSection
2011  */
2012 void X11DRV_DIB_UpdateDIBSection(DC *dc, BOOL toDIB)
2013 {
2014   BITMAPOBJ *bmp;
2015   
2016   /* Ensure this is a Compatible DC that has a DIB section selected */
2017   
2018   if (!dc) return;
2019   if (!(dc->w.flags & DC_MEMORY)) return;
2020   
2021   bmp = (BITMAPOBJ *)GDI_GetObjPtr( dc->w.hBitmap, BITMAP_MAGIC );
2022   if (!bmp) return;
2023   
2024   if (!bmp->dib)
2025     {
2026       GDI_HEAP_UNLOCK(dc->w.hBitmap);
2027       return;
2028     }
2029   
2030   if (!toDIB)
2031     {
2032       /* Prepare for access to the DIB by GDI functions */
2033       
2034       switch (((X11DRV_DIBSECTION *) bmp->dib)->status)
2035         {
2036         default:
2037         case X11DRV_DIB_NoHandler:
2038           X11DRV_DIB_DoUpdateDIBSection( bmp, FALSE );
2039           break;
2040           
2041         case X11DRV_DIB_GdiMod:
2042           TRACE_(bitmap)("fromDIB called in status X11DRV_DIB_GdiMod\n" );
2043           /* nothing to do */
2044           break;
2045           
2046         case X11DRV_DIB_InSync:
2047           TRACE_(bitmap)("fromDIB called in status X11DRV_DIB_InSync\n" );
2048           /* nothing to do */
2049           break;
2050           
2051         case X11DRV_DIB_AppMod:
2052           TRACE_(bitmap)("fromDIB called in status X11DRV_DIB_AppMod\n" );
2053           X11DRV_DIB_DoUpdateDIBSection( bmp, FALSE );
2054           X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
2055           ((X11DRV_DIBSECTION *) bmp->dib)->status = X11DRV_DIB_InSync;
2056           break;
2057         }
2058     }
2059   else
2060     {
2061       /* Acknowledge write access to the DIB by GDI functions */
2062       
2063       switch (((X11DRV_DIBSECTION *) bmp->dib)->status)
2064         {
2065         default:
2066         case X11DRV_DIB_NoHandler:
2067           X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
2068           break;
2069           
2070         case X11DRV_DIB_GdiMod:
2071           TRACE_(bitmap)("  toDIB called in status X11DRV_DIB_GdiMod\n" );
2072           /* nothing to do */
2073           break;
2074           
2075         case X11DRV_DIB_InSync:
2076           TRACE_(bitmap)("  toDIB called in status X11DRV_DIB_InSync\n" );
2077           X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
2078           ((X11DRV_DIBSECTION *) bmp->dib)->status = X11DRV_DIB_GdiMod;
2079           break;
2080           
2081         case X11DRV_DIB_AppMod:
2082           FIXME_(bitmap)("  toDIB called in status X11DRV_DIB_AppMod: "
2083                  "this can't happen!\n" );
2084           break;
2085         }
2086     }
2087
2088     GDI_HEAP_UNLOCK(dc->w.hBitmap);
2089 }
2090
2091 /***********************************************************************
2092  *           X11DRV_DIB_CreateDIBSection16
2093  */
2094 HBITMAP16 X11DRV_DIB_CreateDIBSection16(
2095   DC *dc, BITMAPINFO *bmi, UINT16 usage,
2096   SEGPTR *bits, HANDLE section,
2097   DWORD offset)
2098 {
2099   HBITMAP res = X11DRV_DIB_CreateDIBSection(dc, bmi, usage, NULL, 
2100                                             section, offset);
2101   if ( res )
2102     {
2103       BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr(res, BITMAP_MAGIC);
2104       if ( bmp && bmp->dib )
2105         {
2106           DIBSECTION *dib = bmp->dib;
2107           INT height = dib->dsBm.bmHeight >= 0 ?
2108             dib->dsBm.bmHeight : -dib->dsBm.bmHeight;
2109           INT size = dib->dsBmih.biSizeImage ?
2110             dib->dsBmih.biSizeImage : dib->dsBm.bmWidthBytes * height;
2111           if ( dib->dsBm.bmBits )
2112             {
2113               ((X11DRV_DIBSECTION *) bmp->dib)->selector = 
2114                 SELECTOR_AllocBlock( dib->dsBm.bmBits, size, 
2115                                      SEGMENT_DATA, FALSE, FALSE );
2116             }
2117           TRACE_(bitmap)("ptr = %p, size =%d, selector = %04x, segptr = %ld\n",
2118                          dib->dsBm.bmBits, size, ((X11DRV_DIBSECTION *) bmp->dib)->selector,
2119                          PTR_SEG_OFF_TO_SEGPTR(((X11DRV_DIBSECTION *) bmp->dib)->selector, 0));
2120         }
2121       GDI_HEAP_UNLOCK( res );
2122       
2123       if ( bits ) 
2124         *bits = PTR_SEG_OFF_TO_SEGPTR( ((X11DRV_DIBSECTION *) bmp->dib)->selector, 0 );
2125     }
2126
2127     return res;
2128 }
2129
2130
2131 /***********************************************************************
2132  *           X11DRV_DIB_CreateDIBSection
2133  */
2134 HBITMAP X11DRV_DIB_CreateDIBSection(
2135   DC *dc, BITMAPINFO *bmi, UINT usage,
2136   LPVOID *bits, HANDLE section,
2137   DWORD offset)
2138 {
2139   HBITMAP res = 0;
2140   BITMAPOBJ *bmp = NULL;
2141   X11DRV_DIBSECTION *dib = NULL;
2142   int *colorMap = NULL;
2143   int nColorMap;
2144   
2145   /* Fill BITMAP32 structure with DIB data */
2146   BITMAPINFOHEADER *bi = &bmi->bmiHeader;
2147   INT effHeight, totalSize;
2148   BITMAP bm;
2149   
2150   TRACE_(bitmap)("format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
2151         bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
2152         bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
2153   
2154   bm.bmType = 0;
2155   bm.bmWidth = bi->biWidth;
2156   bm.bmHeight = bi->biHeight;
2157   bm.bmWidthBytes = DIB_GetDIBWidthBytes(bm.bmWidth, bi->biBitCount);
2158   bm.bmPlanes = bi->biPlanes;
2159   bm.bmBitsPixel = bi->biBitCount;
2160   bm.bmBits = NULL;
2161   
2162   /* Get storage location for DIB bits */
2163   effHeight = bm.bmHeight >= 0 ? bm.bmHeight : -bm.bmHeight;
2164   totalSize = bi->biSizeImage? bi->biSizeImage : bm.bmWidthBytes * effHeight;
2165   
2166   if (section)
2167     bm.bmBits = MapViewOfFile(section, FILE_MAP_ALL_ACCESS, 
2168                               0L, offset, totalSize);
2169   else
2170     bm.bmBits = VirtualAlloc(NULL, totalSize, 
2171                              MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
2172   
2173   /* Create Color Map */
2174   if (bm.bmBits && bm.bmBitsPixel <= 8)
2175       colorMap = X11DRV_DIB_BuildColorMap( usage == DIB_PAL_COLORS? dc : NULL, 
2176                                 usage, bm.bmBitsPixel, bmi, &nColorMap );
2177
2178   /* Allocate Memory for DIB and fill structure */
2179   if (bm.bmBits)
2180     dib = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(X11DRV_DIBSECTION));
2181   if (dib)
2182     {
2183       dib->dibSection.dsBm = bm;
2184       dib->dibSection.dsBmih = *bi;
2185       /* FIXME: dib->dibSection.dsBitfields ??? */
2186       dib->dibSection.dshSection = section;
2187       dib->dibSection.dsOffset = offset;
2188       
2189       dib->status    = X11DRV_DIB_NoHandler;
2190       dib->selector  = 0;
2191       
2192       dib->nColorMap = nColorMap;
2193       dib->colorMap  = colorMap;
2194     }
2195   
2196   /* Create Device Dependent Bitmap and add DIB pointer */
2197   if (dib) 
2198     {
2199       res = CreateDIBitmap(dc->hSelf, bi, 0, NULL, bmi, usage);
2200       if (res)
2201         {
2202           bmp = (BITMAPOBJ *) GDI_GetObjPtr(res, BITMAP_MAGIC);
2203           if (bmp)
2204             {
2205               bmp->dib = (DIBSECTION *) dib;
2206               /* HACK for now */
2207               if(!bmp->DDBitmap)
2208                 X11DRV_CreateBitmap(res); 
2209             }
2210         }
2211     }
2212   
2213   /* Create XImage */
2214   if (dib && bmp)
2215     XCREATEIMAGE( dib->image, bm.bmWidth, effHeight, bmp->bitmap.bmBitsPixel );
2216   
2217   /* Clean up in case of errors */
2218   if (!res || !bmp || !dib || !bm.bmBits || (bm.bmBitsPixel <= 8 && !colorMap))
2219     {
2220       TRACE_(bitmap)("got an error res=%08x, bmp=%p, dib=%p, bm.bmBits=%p\n",
2221             res, bmp, dib, bm.bmBits);
2222       if (bm.bmBits)
2223         {
2224           if (section)
2225             UnmapViewOfFile(bm.bmBits), bm.bmBits = NULL;
2226           else
2227             VirtualFree(bm.bmBits, MEM_RELEASE, 0L), bm.bmBits = NULL;
2228         }
2229       
2230       if (dib && dib->image) { XDestroyImage(dib->image); dib->image = NULL; }
2231       if (colorMap) { HeapFree(GetProcessHeap(), 0, colorMap); colorMap = NULL; }
2232       if (dib) { HeapFree(GetProcessHeap(), 0, dib); dib = NULL; }
2233       if (res) { DeleteObject(res); res = 0; }
2234     }
2235   
2236   /* Install fault handler, if possible */
2237   if (bm.bmBits)
2238     {
2239       if (VIRTUAL_SetFaultHandler(bm.bmBits, X11DRV_DIB_FaultHandler, (LPVOID)res))
2240         {
2241           X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
2242           if (dib) dib->status = X11DRV_DIB_InSync;
2243         }
2244     }
2245
2246   /* Return BITMAP handle and storage location */
2247   if (res) GDI_HEAP_UNLOCK(res);
2248   if (bm.bmBits && bits) *bits = bm.bmBits;
2249   return res;
2250 }
2251
2252 /***********************************************************************
2253  *           X11DRV_DIB_DeleteDIBSection
2254  */
2255 void X11DRV_DIB_DeleteDIBSection(BITMAPOBJ *bmp)
2256 {
2257   X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
2258
2259   if (dib->image) 
2260     XDestroyImage( dib->image );
2261   
2262   if (dib->colorMap)
2263     HeapFree(GetProcessHeap(), 0, dib->colorMap);
2264   
2265   if (dib->selector)
2266     {
2267       WORD count = (GET_SEL_LIMIT( dib->selector ) >> 16) + 1;
2268       SELECTOR_FreeBlock( dib->selector, count );
2269     }
2270 }
2271
2272
2273 #endif /* !defined(X_DISPLAY_MISSING) */
2274
2275
2276