Release 970804
[wine] / objects / dib.c
1 /*
2  * GDI device-independent bitmaps
3  *
4  * Copyright 1993,1994  Alexandre Julliard
5  */
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <X11/Xlib.h>
10 #include <X11/Xutil.h>
11 #include "dc.h"
12 #include "bitmap.h"
13 #include "callback.h"
14 #include "palette.h"
15 #include "stddebug.h"
16 #include "color.h"
17 #include "debug.h"
18
19 extern void CLIPPING_UpdateGCRegion(DC* );
20
21 static int      bitmapDepthTable[] = { 8, 1, 32, 16, 24, 15, 4, 0 };
22 static int      ximageDepthTable[] = { 0, 0, 0,  0,  0,  0,  0 };
23
24 /***********************************************************************
25  *           DIB_Init
26  */
27 BOOL32 DIB_Init()
28 {
29     int         i;
30     XImage*     testimage;
31
32     for( i = 0; bitmapDepthTable[i]; i++ )
33     {
34          testimage = XCreateImage(display, DefaultVisualOfScreen(screen),
35                          bitmapDepthTable[i], ZPixmap, 0, NULL, 1, 1, 32, 20 );
36          if( testimage ) ximageDepthTable[i] = testimage->bits_per_pixel;
37          else return FALSE;
38          XDestroyImage(testimage);
39     }
40     return TRUE;
41 }
42
43 /***********************************************************************
44  *           DIB_GetXImageWidthBytes
45  *
46  * Return the width of an X image in bytes
47  */
48 int DIB_GetXImageWidthBytes( int width, int depth )
49 {
50     int         i;
51
52     if (!ximageDepthTable[0]) {
53             DIB_Init();
54     }
55     for( i = 0; bitmapDepthTable[i] ; i++ )
56          if( bitmapDepthTable[i] == depth )
57              return (4 * ((width * ximageDepthTable[i] + 31)/32));
58     fprintf(stderr, "DIB: unsupported depth %d.\n", depth );
59     return (4 * width);
60 }
61
62 /***********************************************************************
63  *           DIB_GetDIBWidthBytes
64  *
65  * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
66  * http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/struc/src/str01.htm
67  */
68 int DIB_GetDIBWidthBytes( int width, int depth )
69 {
70     int words;
71
72     switch(depth)
73     {
74         case 1:  words = (width + 31) / 32; break;
75         case 4:  words = (width + 7) / 8; break;
76         case 8:  words = (width + 3) / 4; break;
77         case 15:
78         case 16: words = (width + 1) / 2; break;
79         case 24: words = (width * 3 + 3)/4; break;
80
81         default:
82                 fprintf(stderr, "DIB: unsupported depth %d.\n", depth );
83         /* fall through */
84         case 32:
85                 words = width;
86     }
87     return 4 * words;
88 }
89
90
91 /***********************************************************************
92  *           DIB_BitmapInfoSize
93  *
94  * Return the size of the bitmap info structure including color table.
95  */
96 int DIB_BitmapInfoSize( BITMAPINFO * info, WORD coloruse )
97 {
98     int colors;
99
100     if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
101     {
102         BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)info;
103         colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
104         return sizeof(BITMAPCOREHEADER) + colors *
105              ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
106     }
107     else  /* assume BITMAPINFOHEADER */
108     {
109         colors = info->bmiHeader.biClrUsed;
110         if (!colors && (info->bmiHeader.biBitCount <= 8))
111             colors = 1 << info->bmiHeader.biBitCount;
112         return sizeof(BITMAPINFOHEADER) + colors *
113                ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
114     }
115 }
116
117
118 /***********************************************************************
119  *           DIB_GetBitmapInfo
120  *
121  * Get the info from a bitmap header.
122  * Return 1 for INFOHEADER, 0 for COREHEADER, -1 for error.
123  */
124 static int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, DWORD *width,
125                               DWORD *height, WORD *bpp )
126 {
127     if (header->biSize == sizeof(BITMAPINFOHEADER))
128     {
129         *width  = header->biWidth;
130         *height = header->biHeight;
131         *bpp    = header->biBitCount;
132         return 1;
133     }
134     if (header->biSize == sizeof(BITMAPCOREHEADER))
135     {
136         BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)header;
137         *width  = core->bcWidth;
138         *height = core->bcHeight;
139         *bpp    = core->bcBitCount;
140         return 0;
141     }
142     fprintf( stderr, "DIB_GetBitmapInfo: wrong size (%ld) for header\n",
143              header->biSize );
144     return -1;
145 }
146
147
148 /***********************************************************************
149  *           DIB_BuildColorMap
150  *
151  * Build the color map from the bitmap palette. Should not be called
152  * for a 24-bit deep bitmap.
153  */
154 static int *DIB_BuildColorMap( DC *dc, WORD coloruse, WORD depth,
155                                BITMAPINFO *info )
156 {
157     int i, colors;
158     BOOL32 isInfo;
159     WORD *colorPtr;
160     int *colorMapping;
161
162     if ((isInfo = (info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))))
163     {
164         colors = info->bmiHeader.biClrUsed;
165         if (!colors) colors = 1 << info->bmiHeader.biBitCount;
166         colorPtr = (WORD *)info->bmiColors;
167     }
168     else  /* assume BITMAPCOREINFO */
169     {
170         colors = 1 << ((BITMAPCOREHEADER *)&info->bmiHeader)->bcBitCount;
171         colorPtr = (WORD *)((BITMAPCOREINFO *)info)->bmciColors;
172     }
173     if (!(colorMapping = (int *)malloc( colors * sizeof(int) ))) return NULL;
174
175     if (coloruse == DIB_RGB_COLORS)
176     {
177         if (isInfo)
178         {
179             RGBQUAD * rgb = (RGBQUAD *)colorPtr;
180         
181             if (depth == 1)  /* Monochrome */
182                 for (i = 0; i < colors; i++, rgb++)
183                     colorMapping[i] = (rgb->rgbRed + rgb->rgbGreen + 
184                                        rgb->rgbBlue > 255*3/2);
185             else
186                 for (i = 0; i < colors; i++, rgb++)
187                     colorMapping[i] = COLOR_ToPhysical( dc, RGB(rgb->rgbRed,
188                                                                 rgb->rgbGreen,
189                                                                 rgb->rgbBlue));
190         }
191         else
192         {
193             RGBTRIPLE * rgb = (RGBTRIPLE *)colorPtr;
194         
195             if (depth == 1)  /* Monochrome */
196                 for (i = 0; i < colors; i++, rgb++)
197                     colorMapping[i] = (rgb->rgbtRed + rgb->rgbtGreen + 
198                                        rgb->rgbtBlue > 255*3/2);
199             else
200                 for (i = 0; i < colors; i++, rgb++)
201                     colorMapping[i] = COLOR_ToPhysical( dc, RGB(rgb->rgbtRed,
202                                                                rgb->rgbtGreen,
203                                                                rgb->rgbtBlue));
204         }
205     }
206     else  /* DIB_PAL_COLORS */
207     {
208         for (i = 0; i < colors; i++, colorPtr++)
209             colorMapping[i] = COLOR_ToPhysical( dc, PALETTEINDEX(*colorPtr) );
210     }
211     return colorMapping;
212 }
213
214
215 /***********************************************************************
216  *           DIB_SetImageBits_1
217  *
218  * SetDIBits for a 1-bit deep DIB.
219  */
220 static void DIB_SetImageBits_1( DWORD lines, BYTE *bits, DWORD width,
221                                 int *colors, XImage *bmpImage )
222 {
223     DWORD i, x;
224     BYTE pad, pix;
225
226     if (!(width & 31)) pad = 0;
227     else pad = ((32 - (width & 31)) + 7) / 8;
228
229     while (lines--)
230     {
231         for (i = width/8, x = 0; (i > 0); i--)
232         {
233             pix = *bits++;
234             XPutPixel( bmpImage, x++, lines, colors[pix >> 7] );
235             XPutPixel( bmpImage, x++, lines, colors[(pix >> 6) & 1] );
236             XPutPixel( bmpImage, x++, lines, colors[(pix >> 5) & 1] );
237             XPutPixel( bmpImage, x++, lines, colors[(pix >> 4) & 1] );
238             XPutPixel( bmpImage, x++, lines, colors[(pix >> 3) & 1] );
239             XPutPixel( bmpImage, x++, lines, colors[(pix >> 2) & 1] );
240             XPutPixel( bmpImage, x++, lines, colors[(pix >> 1) & 1] );
241             XPutPixel( bmpImage, x++, lines, colors[pix & 1] );
242         }
243         pix = *bits;
244         switch(width & 7)
245         {
246         case 7: XPutPixel( bmpImage, x++, lines, colors[pix >> 7] ); pix <<= 1;
247         case 6: XPutPixel( bmpImage, x++, lines, colors[pix >> 7] ); pix <<= 1;
248         case 5: XPutPixel( bmpImage, x++, lines, colors[pix >> 7] ); pix <<= 1;
249         case 4: XPutPixel( bmpImage, x++, lines, colors[pix >> 7] ); pix <<= 1;
250         case 3: XPutPixel( bmpImage, x++, lines, colors[pix >> 7] ); pix <<= 1;
251         case 2: XPutPixel( bmpImage, x++, lines, colors[pix >> 7] ); pix <<= 1;
252         case 1: XPutPixel( bmpImage, x++, lines, colors[pix >> 7] );
253         }
254         bits += pad;
255     }
256 }
257
258
259 /***********************************************************************
260  *           DIB_SetImageBits_4
261  *
262  * SetDIBits for a 4-bit deep DIB.
263  */
264 static void DIB_SetImageBits_4( DWORD lines, BYTE *bits, DWORD width,
265                                 int *colors, XImage *bmpImage )
266 {
267     DWORD i, x;
268     BYTE pad;
269
270     if (!(width & 7)) pad = 0;
271     else pad = ((8 - (width & 7)) + 1) / 2;
272
273     while (lines--)
274     {
275         for (i = width/2, x = 0; i > 0; i--)
276         {
277             BYTE pix = *bits++;
278             XPutPixel( bmpImage, x++, lines, colors[pix >> 4] );
279             XPutPixel( bmpImage, x++, lines, colors[pix & 0x0f] );
280         }
281         if (width & 1) XPutPixel( bmpImage, x, lines, colors[*bits >> 4] );
282         bits += pad;
283     }
284 }
285
286 #define check_xy(x,y) \
287         if (x > width) { \
288                 x = 0; \
289                 if (lines) \
290                         lines--; \
291         }
292
293 /***********************************************************************
294  *           DIB_SetImageBits_RLE4
295  *
296  * SetDIBits for a 4-bit deep compressed DIB.
297  */
298 static void DIB_SetImageBits_RLE4( DWORD lines, BYTE *bits, DWORD width,
299                                    int *colors, XImage *bmpImage )
300 {
301         int x = 0, c, length;
302         BYTE *begin = bits;
303
304         lines--;
305         while ((int)lines >= 0)
306         {
307                 length = *bits++;
308                 if (length) {   /* encoded */
309                         c = *bits++;
310                         while (length--) {
311                                 XPutPixel(bmpImage, x++, lines, colors[c >> 4]);
312                                 check_xy(x, y);
313                                 if (length) {
314                                         length--;
315                                         XPutPixel(bmpImage, x++, lines, colors[c & 0xf]);
316                                         check_xy(x, y);
317                                 }
318                         }
319                 } else {
320                         length = *bits++;
321                         switch (length) {
322                                 case 0: /* eol */
323                                         x = 0;
324                                         lines--;
325                                         continue;
326
327                                 case 1: /* eopicture */
328                                         return;
329
330                                 case 2: /* delta */
331                                         x += *bits++;
332                                         lines -= *bits++;
333                                         continue;
334
335                                 default: /* absolute */
336                                         while (length--) {
337                                                 c = *bits++;
338                                                 XPutPixel(bmpImage, x++, lines, colors[c >> 4]);
339                                                 check_xy(x, y);
340                                                 if (length) {
341                                                         length--;
342                                                         XPutPixel(bmpImage, x++, lines, colors[c & 0xf]);
343                                                         check_xy(x, y);
344                                                 }
345                                         }
346                                         if ((bits - begin) & 1)
347                                                 bits++;
348                         }
349                 }
350         }
351 }
352
353 /***********************************************************************
354  *           DIB_SetImageBits_8
355  *
356  * SetDIBits for an 8-bit deep DIB.
357  */
358 static void DIB_SetImageBits_8( DWORD lines, BYTE *bits, DWORD width,
359                                 int *colors, XImage *bmpImage )
360 {
361     DWORD x;
362     BYTE pad = (4 - (width & 3)) & 3;
363
364     while (lines--)
365     {
366         for (x = 0; x < width; x++)
367             XPutPixel( bmpImage, x, lines, colors[*bits++] );
368         bits += pad;
369     }
370 }
371
372 /***********************************************************************
373  *            DIB_SetImageBits_RLE8
374  *
375  * SetDIBits for an 8-bit deep compressed DIB.
376  *
377  * This function rewritten 941113 by James Youngman.  WINE blew out when I
378  * first ran it because my desktop wallpaper is a (large) RLE8 bitmap.  
379  *
380  * This was because the algorithm assumed that all RLE8 bitmaps end with the  
381  * 'End of bitmap' escape code.  This code is very much laxer in what it
382  * allows to end the expansion.  Possibly too lax.  See the note by 
383  * case RleDelta.  BTW, MS's documentation implies that a correct RLE8
384  * bitmap should end with RleEnd, but on the other hand, software exists 
385  * that produces ones that don't and Windows 3.1 doesn't complain a bit
386  * about it.
387  *
388  * (No) apologies for my English spelling.  [Emacs users: c-indent-level=4].
389  *                      James A. Youngman <mbcstjy@afs.man.ac.uk>
390  *                                              [JAY]
391  */
392
393 enum Rle8_EscapeCodes           
394 {
395   /* 
396    * Apologies for polluting your file's namespace...
397    */
398   RleEol        = 0,            /* End of line */
399   RleEnd        = 1,            /* End of bitmap */
400   RleDelta      = 2             /* Delta */
401 };
402   
403 static void DIB_SetImageBits_RLE8( DWORD lines, BYTE *bits, DWORD width,
404                                    int *colors, XImage *bmpImage )
405 {
406     int x;                      /* X-positon on each line.  Increases. */
407     int line;                   /* Line #.  Starts at lines-1, decreases */
408     BYTE *pIn = bits;           /* Pointer to current position in bits */
409     BYTE length;                /* The length pf a run */
410     BYTE color_index;           /* index into colors[] as read from bits */
411     BYTE escape_code;           /* See enum Rle8_EscapeCodes.*/
412     WORD color;                 /* value of colour[color_index] */
413     
414     if (lines == 0)             /* Let's hope this doesn't happen. */
415       return;
416     
417     /*
418      * Note that the bitmap data is stored by Windows starting at the
419      * bottom line of the bitmap and going upwards.  Within each line,
420      * the data is stored left-to-right.  That's the reason why line
421      * goes from lines-1 to 0.                  [JAY]
422      */
423     
424     x = 0;
425     line = lines-1;
426     do
427       {
428           length = *pIn++;
429           
430           /* 
431            * If the length byte is not zero (which is the escape value),
432            * We have a run of length pixels all the same colour.  The colour 
433            * index is stored next. 
434            *
435            * If the length byte is zero, we need to read the next byte to
436            * know what to do.                   [JAY]
437            */
438           if (length != 0) 
439             {                                   
440                 /* 
441                  * [Run-Length] Encoded mode 
442                  */
443                 color_index = (*pIn++); /* Get the colour index. */
444                 color = colors[color_index];
445
446                 while(length--)
447                   XPutPixel(bmpImage, x++, line, color);
448             }
449           else 
450             {    
451                 /* 
452                  * Escape codes (may be an absolute sequence though)
453                  */
454                 escape_code = (*pIn++);
455                 switch(escape_code)
456                   {
457                     case RleEol: /* =0, end of line */
458                       {
459                           x = 0;  
460                           line--;  
461                           break;
462                       }
463                       
464                     case RleEnd: /* =1, end of bitmap */
465                       {
466                           /*
467                            * Not all RLE8 bitmaps end with this 
468                            * code.  For example, Paint Shop Pro 
469                            * produces some that don't.  That's (I think)
470                            * what caused the previous implementation to 
471                            * fail.                      [JAY]
472                            */
473                           line=-1; /* Cause exit from do loop. */
474                           break;
475                       }
476                       
477                     case RleDelta: /* =2, a delta */
478                       {
479                           /* 
480                            * Note that deltaing to line 0 
481                            * will cause an exit from the loop, 
482                            * which may not be what is intended. 
483                            * The fact that there is a delta in the bits
484                            * almost certainly implies that there is data
485                            * to follow.  You may feel that we should 
486                            * jump to the top of the loop to avoid exiting
487                            * in this case.  
488                            *
489                            * TODO: Decide what to do here in that case. [JAY]
490                            */
491                           x     += (*pIn++); 
492                           line  -= (*pIn++);
493                           if (line == 0)
494                             {
495                               dprintf_bitmap(stddeb, 
496                                              "DIB_SetImageBits_RLE8(): "
497                                              "Delta to last line of bitmap "
498                                              "(wrongly?) causes loop exit\n");
499                             }
500                           break;
501                       }
502                       
503                     default:    /* >2, switch to absolute mode */
504                       {
505                           /* 
506                            * Absolute Mode 
507                            */
508                           length = escape_code;
509                           while(length--)
510                             {
511                                 color_index = (*pIn++);
512                                 XPutPixel(bmpImage, x++, line, 
513                                           colors[color_index]);
514                             }
515                           
516                           /*
517                            * If you think for a moment you'll realise that the
518                            * only time we could ever possibly read an odd
519                            * number of bytes is when there is a 0x00 (escape),
520                            * a value >0x02 (absolute mode) and then an odd-
521                            * length run.  Therefore this is the only place we
522                            * need to worry about it.  Everywhere else the
523                            * bytes are always read in pairs.  [JAY]
524                            */
525                           if (escape_code & 1) 
526                             pIn++; /* Throw away the pad byte. */
527                           break;
528                       }
529                   } /* switch (escape_code) : Escape sequence */
530             }  /* process either an encoded sequence or an escape sequence */
531           
532           /* We expect to come here more than once per line. */
533       } while (line >= 0);  /* Do this until the bitmap is filled */
534     
535     /*
536      * Everybody comes here at the end.
537      * Check how we exited the loop and print a message if it's a bit odd.
538      *                                          [JAY]
539      */
540     if ( (*(pIn-2) != 0/*escape*/) || (*(pIn-1)!= RleEnd) )
541       {
542         dprintf_bitmap(stddeb, "DIB_SetImageBits_RLE8(): End-of-bitmap "
543                        "without (strictly) proper escape code.  Last two "
544                        "bytes were: %02X %02X.\n",
545                        (int)*(pIn-2),
546                        (int)*(pIn-1));           
547       }
548 }  
549
550
551 /***********************************************************************
552  *           DIB_SetImageBits_24
553  *
554  * SetDIBits for a 24-bit deep DIB.
555  */
556 static void DIB_SetImageBits_24( DWORD lines, BYTE *bits, DWORD width,
557                                  DC *dc, XImage *bmpImage )
558 {
559     DWORD x;
560     BYTE pad = (4 - ((width*3) & 3)) & 3;
561
562     /* "bits" order is reversed for some reason */
563
564     while (lines--)
565     {
566         for (x = 0; x < width; x++, bits += 3)
567             XPutPixel( bmpImage, x, lines, 
568                        COLOR_ToPhysical(dc, RGB(bits[2],bits[1],bits[0])) );
569
570         bits += pad;
571     }
572 }
573
574
575 /***********************************************************************
576  *           DIB_SetImageBits
577  *
578  * Transfer the bits to an X image.
579  * Helper function for SetDIBits() and SetDIBitsToDevice().
580  */
581 static int DIB_SetImageBits( DC *dc, DWORD lines, WORD depth, LPSTR bits,
582                              DWORD infoWidth, WORD infoBpp,
583                              BITMAPINFO *info, WORD coloruse,
584                              Drawable drawable, GC gc, int xSrc, int ySrc,
585                              int xDest, int yDest, int width, int height )
586 {
587     int *colorMapping;
588     XImage *bmpImage;
589     DWORD compression = 0;
590
591     if (info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
592         compression = info->bmiHeader.biCompression;
593
594       /* Build the color mapping table */
595
596     if (infoBpp > 8) {
597                 colorMapping = NULL;
598     } else {
599         if (!(colorMapping = DIB_BuildColorMap( dc, coloruse, depth, info )))
600             return 0;
601     }
602
603     if( dc->w.flags & DC_DIRTY ) CLIPPING_UpdateGCRegion(dc);
604
605       /* Transfer the pixels */
606     XCREATEIMAGE(bmpImage, infoWidth, lines, depth );
607
608     switch(infoBpp)
609     {
610     case 1:
611         DIB_SetImageBits_1( lines, bits, infoWidth,
612                             colorMapping, bmpImage );
613         break;
614     case 4:
615         if (compression) DIB_SetImageBits_RLE4( lines, bits, infoWidth,
616                                                 colorMapping, bmpImage );
617         else DIB_SetImageBits_4( lines, bits, infoWidth,
618                                  colorMapping, bmpImage );
619         break;
620     case 8:
621         if (compression) DIB_SetImageBits_RLE8( lines, bits, infoWidth,
622                                                 colorMapping, bmpImage );
623         else DIB_SetImageBits_8( lines, bits, infoWidth,
624                                  colorMapping, bmpImage );
625         break;
626     case 24:
627         DIB_SetImageBits_24( lines, bits, infoWidth, dc, bmpImage );
628         break;
629     default:
630         fprintf( stderr, "Invalid depth %d for SetDIBits!\n", infoBpp );
631         break;
632     }
633     if (colorMapping) free(colorMapping);
634     XPutImage( display, drawable, gc, bmpImage, xSrc, ySrc,
635                xDest, yDest, width, height );
636     XDestroyImage( bmpImage );
637     return lines;
638 }
639
640
641 /***********************************************************************
642  *           StretchDIBits16   (GDI.439)
643  */
644 INT16 StretchDIBits16( HDC16 hdc, INT16 xDst, INT16 yDst, INT16 widthDst,
645                        INT16 heightDst, INT16 xSrc, INT16 ySrc, INT16 widthSrc,
646                        INT16 heightSrc, const VOID *bits,
647                        const BITMAPINFO *info, UINT16 wUsage, DWORD dwRop )
648 {
649     return (INT16)StretchDIBits32( hdc, xDst, yDst, widthDst, heightDst,
650                                    xSrc, ySrc, widthSrc, heightSrc, bits,
651                                    info, wUsage, dwRop );
652 }
653
654
655 /***********************************************************************
656  *           StretchDIBits32   (GDI32.351)
657  */
658 INT32 StretchDIBits32( HDC32 hdc, INT32 xDst, INT32 yDst, INT32 widthDst,
659                        INT32 heightDst, INT32 xSrc, INT32 ySrc, INT32 widthSrc,
660                        INT32 heightSrc, const void *bits,
661                        const BITMAPINFO *info, UINT32 wUsage, DWORD dwRop )
662 {
663     HBITMAP32 hBitmap, hOldBitmap;
664     HDC32 hdcMem;
665
666     hBitmap = CreateDIBitmap32( hdc, &info->bmiHeader, CBM_INIT,
667                                 bits, info, wUsage );
668     hdcMem = CreateCompatibleDC32( hdc );
669     hOldBitmap = SelectObject32( hdcMem, hBitmap );
670     StretchBlt32( hdc, xDst, yDst, widthDst, heightDst,
671                   hdcMem, xSrc, ySrc, widthSrc, heightSrc, dwRop );
672     SelectObject32( hdcMem, hOldBitmap );
673     DeleteDC32( hdcMem );
674     DeleteObject32( hBitmap );
675     return heightSrc;
676 }
677
678
679 /***********************************************************************
680  *           SetDIBits16    (GDI.440)
681  */
682 INT16 SetDIBits16( HDC16 hdc, HBITMAP16 hbitmap, UINT16 startscan,
683                    UINT16 lines, LPCVOID bits, const BITMAPINFO *info,
684                    UINT16 coloruse )
685 {
686     return SetDIBits32( hdc, hbitmap, startscan, lines, bits, info, coloruse );
687 }
688
689
690 /***********************************************************************
691  *           SetDIBits32   (GDI32.312)
692  */
693 INT32 SetDIBits32( HDC32 hdc, HBITMAP32 hbitmap, UINT32 startscan,
694                    UINT32 lines, LPCVOID bits, const BITMAPINFO *info,
695                    UINT32 coloruse )
696 {
697     DC * dc;
698     BITMAPOBJ * bmp;
699     DWORD width, height;
700     WORD bpp;
701
702       /* Check parameters */
703
704     dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
705     if (!dc) 
706     {
707         dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
708         if (!dc) return 0;
709     }
710     if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
711         return 0;
712     if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &bpp ) == -1)
713         return 0;
714     if (!lines || (startscan >= (WORD)height)) return 0;
715     if (startscan + lines > height) lines = height - startscan;
716
717     return CallTo32_LargeStack( (int(*)())DIB_SetImageBits, 16,
718                                 dc, lines, bmp->bitmap.bmBitsPixel,
719                                 bits, width, bpp, info,
720                                 coloruse, bmp->pixmap, BITMAP_GC(bmp), 0, 0, 0,
721                                 height - startscan - lines,
722                                 bmp->bitmap.bmWidth, lines );
723 }
724
725
726 /***********************************************************************
727  *           SetDIBitsToDevice16    (GDI.443)
728  */
729 INT16 SetDIBitsToDevice16( HDC16 hdc, INT16 xDest, INT16 yDest, INT16 cx,
730                            INT16 cy, INT16 xSrc, INT16 ySrc, UINT16 startscan,
731                            UINT16 lines, LPCVOID bits, const BITMAPINFO *info,
732                            UINT16 coloruse )
733 {
734     return SetDIBitsToDevice32( hdc, xDest, yDest, cx, cy, xSrc, ySrc,
735                                 startscan, lines, bits, info, coloruse );
736 }
737
738
739 /***********************************************************************
740  *           SetDIBitsToDevice32   (GDI32.313)
741  */
742 INT32 SetDIBitsToDevice32( HDC32 hdc, INT32 xDest, INT32 yDest, DWORD cx,
743                            DWORD cy, INT32 xSrc, INT32 ySrc, UINT32 startscan,
744                            UINT32 lines, LPCVOID bits, const BITMAPINFO *info,
745                            UINT32 coloruse )
746 {
747     DC * dc;
748     DWORD width, height;
749     WORD bpp;
750
751       /* Check parameters */
752
753     dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
754     if (!dc) 
755     {
756         dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
757         if (!dc) return 0;
758     }
759     if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &bpp ) == -1)
760         return 0;
761     if (!lines || (startscan >= height)) return 0;
762     if (startscan + lines > height) lines = height - startscan;
763     if (ySrc < startscan) ySrc = startscan;
764     else if (ySrc >= startscan + lines) return 0;
765     if (xSrc >= width) return 0;
766     if (ySrc + cy >= startscan + lines) cy = startscan + lines - ySrc;
767     if (xSrc + cx >= width) cx = width - xSrc;
768     if (!cx || !cy) return 0;
769
770     DC_SetupGCForText( dc );  /* To have the correct colors */
771     XSetFunction( display, dc->u.x.gc, DC_XROPfunction[dc->w.ROPmode-1] );
772     return CallTo32_LargeStack( (int(*)())DIB_SetImageBits, 16,
773                                 dc, lines, dc->w.bitsPerPixel, bits, width,
774                                 bpp, info, coloruse,
775                                 dc->u.x.drawable, dc->u.x.gc,
776                                 xSrc, ySrc - startscan,
777                                 dc->w.DCOrgX + XLPTODP( dc, xDest ),
778                                 dc->w.DCOrgY + YLPTODP( dc, yDest ),
779                                 cx, cy );
780 }
781
782
783
784 /***********************************************************************
785  *           GetDIBits16    (GDI.441)
786  */
787 INT16 GetDIBits16( HDC16 hdc, HBITMAP16 hbitmap, UINT16 startscan,
788                    UINT16 lines, LPSTR bits, BITMAPINFO * info,
789                    UINT16 coloruse )
790 {
791     return GetDIBits32( hdc, hbitmap, startscan, lines, bits, info, coloruse );
792 }
793
794
795 /***********************************************************************
796  *           GetDIBits32    (GDI32.170)
797  *
798  * http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/func/src/f30_14.htm
799  */
800 INT32 GetDIBits32( HDC32 hdc, HBITMAP32 hbitmap, UINT32 startscan,
801                    UINT32 lines, LPSTR bits, BITMAPINFO * info,
802                    UINT32 coloruse )
803 {
804     DC * dc;
805     BITMAPOBJ * bmp;
806     PALETTEENTRY * palEntry;
807     PALETTEOBJ * palette;
808     XImage * bmpImage;
809     int i, x, y;
810         
811     if (!lines) return 0;
812     dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
813     if (!dc) 
814     {
815         dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
816         if (!dc) return 0;
817     }
818     if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
819         return 0;
820     if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->w.hPalette, PALETTE_MAGIC )))
821         return 0;
822
823       /* Transfer color info */
824     
825     if (info->bmiHeader.biBitCount<=8) {
826         palEntry = palette->logpalette.palPalEntry;
827         for (i = 0; i < info->bmiHeader.biClrUsed; i++, palEntry++)
828         {
829             if (coloruse == DIB_RGB_COLORS)
830             {
831                 info->bmiColors[i].rgbRed      = palEntry->peRed;
832                 info->bmiColors[i].rgbGreen    = palEntry->peGreen;
833                 info->bmiColors[i].rgbBlue     = palEntry->peBlue;
834                 info->bmiColors[i].rgbReserved = 0;
835             }
836             else ((WORD *)info->bmiColors)[i] = (WORD)i;
837         }
838     }
839     
840     if (bits)
841     {   
842         BYTE*   bbits = bits;
843         int     pad, yend, xend = bmp->bitmap.bmWidth;
844
845         dprintf_bitmap(stddeb, "GetDIBits: %u scanlines of (%i,%i) -> (%i,%i) starting from %u\n",
846                             lines, bmp->bitmap.bmWidth, bmp->bitmap.bmHeight,
847                             (int)info->bmiHeader.biWidth, (int)info->bmiHeader.biHeight, startscan );
848
849         /* adjust number of scanlines to copy */
850
851         if( lines > info->bmiHeader.biHeight ) lines = info->bmiHeader.biHeight;
852         yend = startscan + lines;
853         if( startscan >= bmp->bitmap.bmHeight ) 
854             return FALSE;
855         if( yend > bmp->bitmap.bmHeight ) yend = bmp->bitmap.bmHeight;
856
857         /* adjust scanline width */
858
859         pad = info->bmiHeader.biWidth - bmp->bitmap.bmWidth;
860         if( pad < 0 ) 
861         {
862             /* bitmap is wider than DIB, copy only a part */
863
864             pad = 0; xend = info->bmiHeader.biWidth;
865         }
866
867         bmpImage = (XImage *)CallTo32_LargeStack( (int (*)())XGetImage, 8, 
868                                display, bmp->pixmap, 0, 0, bmp->bitmap.bmWidth,
869                                bmp->bitmap.bmHeight, AllPlanes, ZPixmap );
870
871         switch( info->bmiHeader.biBitCount )
872         {
873            case 8:
874                 /* pad up to 32 bit */
875                 pad += (4 - (info->bmiHeader.biWidth & 3)) & 3;
876                 for( y = yend - 1; (int)y >= (int)startscan; y-- )
877                 {
878                    for( x = 0; x < xend; x++ )
879                         *bbits++ = XGetPixel( bmpImage, x, y );
880                    bbits += pad;
881                 }
882                 break;
883            case 1:
884                 pad += ((32 - (info->bmiHeader.biWidth & 31)) / 8) & 3;
885                 for( y = yend - 1; (int)y >= (int)startscan; y-- )
886                 {
887                    *bbits = 0;
888                    for( x = 0; x < xend; x++ ) {
889                         
890                         *bbits |= XGetPixel( bmpImage, x, y)<<(7-(x&7));
891                         if ((x&7)==7) {
892                             bbits++;
893                             *bbits=0;
894                         }
895                    }
896                    bbits += pad;
897                 }
898                 break;
899            case 4:
900                 pad += ((8 - (info->bmiHeader.biWidth & 7)) / 2) & 3;
901                 for( y = yend - 1; (int)y >= (int)startscan; y-- )
902                 {
903                    *bbits = 0;
904                    for( x = 0; x < xend; x++ ) {
905                         
906                         *bbits |= XGetPixel( bmpImage, x, y)<<(4*(1-(x&1)));
907                         if ((x&1)==1) {
908                             bbits++;
909                             *bbits=0;
910                         }
911                    }
912                    bbits += pad;
913                 }
914                 break;
915            case 15:
916            case 16:
917                 pad += (4 - ((info->bmiHeader.biWidth*2) & 3)) & 3;
918                 for( y = yend - 1; (int)y >= (int)startscan; y-- )
919                 {
920                    *bbits = 0;
921                    for( x = 0; x < xend; x++ ) {
922                         unsigned long pixel=XGetPixel( bmpImage, x, y);
923                         *bbits++ = pixel & 0xff;
924                         *bbits++ = (pixel >> 8) & 0xff;
925                    }
926                    bbits += pad;
927                 }
928                 break;
929            case 24:
930                 pad += (4 - ((info->bmiHeader.biWidth*3) & 3)) & 3;
931                 for( y = yend - 1; (int)y >= (int)startscan; y-- )
932                 {
933                    *bbits = 0;
934                    for( x = 0; x < xend; x++ ) {
935                         unsigned long pixel=XGetPixel( bmpImage, x, y);
936                         *bbits++ = (pixel >>16) & 0xff;
937                         *bbits++ = (pixel >> 8) & 0xff;
938                         *bbits++ =  pixel       & 0xff;
939                    }
940                    bbits += pad;
941                 }
942                 break;
943            default:
944                 fprintf(stderr,"GetDIBits*: unsupported depth %d\n",
945                         info->bmiHeader.biBitCount
946                 );
947                 break;
948         }
949
950         XDestroyImage( bmpImage );
951
952         info->bmiHeader.biCompression = 0;
953     }
954     else if( info->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) ) 
955     {
956         /* fill in struct members */
957         
958         info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
959         info->bmiHeader.biHeight = bmp->bitmap.bmHeight;
960         info->bmiHeader.biPlanes = 1;
961         info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
962         info->bmiHeader.biSizeImage = bmp->bitmap.bmHeight *
963                              DIB_GetDIBWidthBytes( bmp->bitmap.bmWidth,
964                                                    bmp->bitmap.bmBitsPixel );
965         info->bmiHeader.biCompression = 0;
966     }
967
968     return lines;
969 }
970
971
972 /***********************************************************************
973  *           CreateDIBitmap16    (GDI.442)
974  */
975 HBITMAP16 CreateDIBitmap16( HDC16 hdc, const BITMAPINFOHEADER * header,
976                             DWORD init, LPCVOID bits, const BITMAPINFO * data,
977                             UINT16 coloruse )
978 {
979     return CreateDIBitmap32( hdc, header, init, bits, data, coloruse );
980 }
981
982
983 /***********************************************************************
984  *           CreateDIBitmap32    (GDI32.37)
985  */
986 HBITMAP32 CreateDIBitmap32( HDC32 hdc, const BITMAPINFOHEADER *header,
987                             DWORD init, LPCVOID bits, const BITMAPINFO *data,
988                             UINT32 coloruse )
989 {
990     HBITMAP32 handle;
991     BOOL32 fColor;
992     DWORD width, height;
993     WORD bpp;
994
995     if (DIB_GetBitmapInfo( header, &width, &height, &bpp ) == -1) return 0;
996
997     /* Check if we should create a monochrome or color bitmap. */
998     /* We create a monochrome bitmap only if it has exactly 2  */
999     /* colors, which are either black or white, nothing else.  */
1000     /* In all other cases, we create a color bitmap.           */
1001
1002     if (bpp != 1) fColor = TRUE;
1003     else if ((coloruse != DIB_RGB_COLORS) ||
1004              (init != CBM_INIT) || !data) fColor = FALSE;
1005     else
1006     {
1007         if (data->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
1008         {
1009             RGBQUAD *rgb = data->bmiColors;
1010             DWORD col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
1011             if ((col == RGB(0,0,0)) || (col == RGB(0xff,0xff,0xff)))
1012             {
1013                 rgb++;
1014                 col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
1015                 fColor = ((col != RGB(0,0,0)) && (col != RGB(0xff,0xff,0xff)));
1016             }
1017             else fColor = TRUE;
1018         }
1019         else if (data->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1020         {
1021             RGBTRIPLE *rgb = ((BITMAPCOREINFO *)data)->bmciColors;
1022             DWORD col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue );
1023             if ((col == RGB(0,0,0)) || (col == RGB(0xff,0xff,0xff)))
1024             {
1025                 rgb++;
1026                 col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue );
1027                 fColor = ((col != RGB(0,0,0)) && (col != RGB(0xff,0xff,0xff)));
1028             }
1029             else fColor = TRUE;
1030         }
1031         else
1032         {
1033             fprintf( stderr, "CreateDIBitmap: wrong size (%ld) for data\n",
1034                      data->bmiHeader.biSize );
1035             return 0;
1036         }
1037     }
1038
1039     /* Now create the bitmap */
1040
1041     handle = fColor ? CreateCompatibleBitmap32( hdc, width, height ) :
1042                       CreateBitmap32( width, height, 1, 1, NULL );
1043     if (!handle) return 0;
1044
1045     if (init == CBM_INIT)
1046         SetDIBits32( hdc, handle, 0, height, bits, data, coloruse );
1047     return handle;
1048 }