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