Release 960728
[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 "stackframe.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     BOOL 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( WORD lines, BYTE *bits, WORD width,
201                                 int *colors, XImage *bmpImage )
202 {
203     WORD 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( WORD lines, BYTE *bits, WORD width,
245                                 int *colors, XImage *bmpImage )
246 {
247     WORD 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( WORD lines, BYTE *bits, WORD width,
279                                    int *colors, XImage *bmpImage )
280 {
281         int x = 0, c, length;
282         BYTE *begin = bits;
283
284         lines--;
285         while ((short)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( WORD lines, BYTE *bits, WORD width,
339                                 int *colors, XImage *bmpImage )
340 {
341     WORD 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(WORD lines, 
384                                   BYTE *bits, 
385                                   WORD width,
386                                   int *colors, 
387                                   XImage *bmpImage)
388 {
389     int x;                      /* X-positon on each line.  Increases. */
390     int line;                   /* Line #.  Starts at lines-1, decreases */
391     BYTE *pIn = bits;           /* Pointer to current position in bits */
392     BYTE length;                /* The length pf a run */
393     BYTE color_index;           /* index into colors[] as read from bits */
394     BYTE escape_code;           /* See enum Rle8_EscapeCodes.*/
395     WORD color;                 /* value of colour[color_index] */
396     
397     if (lines == 0)             /* Let's hope this doesn't happen. */
398       return;
399     
400     /*
401      * Note that the bitmap data is stored by Windows starting at the
402      * bottom line of the bitmap and going upwards.  Within each line,
403      * the data is stored left-to-right.  That's the reason why line
404      * goes from lines-1 to 0.                  [JAY]
405      */
406     
407     x = 0;
408     line = lines-1;
409     do
410       {
411           length = *pIn++;
412           
413           /* 
414            * If the length byte is not zero (which is the escape value),
415            * We have a run of length pixels all the same colour.  The colour 
416            * index is stored next. 
417            *
418            * If the length byte is zero, we need to read the next byte to
419            * know what to do.                   [JAY]
420            */
421           if (length != 0) 
422             {                                   
423                 /* 
424                  * [Run-Length] Encoded mode 
425                  */
426                 color_index = (*pIn++); /* Get the colour index. */
427                 color = colors[color_index];
428
429                 while(length--)
430                   XPutPixel(bmpImage, x++, line, color);
431             }
432           else 
433             {    
434                 /* 
435                  * Escape codes (may be an absolute sequence though)
436                  */
437                 escape_code = (*pIn++);
438                 switch(escape_code)
439                   {
440                     case RleEol: /* =0, end of line */
441                       {
442                           x = 0;  
443                           line--;  
444                           break;
445                       }
446                       
447                     case RleEnd: /* =1, end of bitmap */
448                       {
449                           /*
450                            * Not all RLE8 bitmaps end with this 
451                            * code.  For example, Paint Shop Pro 
452                            * produces some that don't.  That's (I think)
453                            * what caused the previous implementation to 
454                            * fail.                      [JAY]
455                            */
456                           line=-1; /* Cause exit from do loop. */
457                           break;
458                       }
459                       
460                     case RleDelta: /* =2, a delta */
461                       {
462                           /* 
463                            * Note that deltaing to line 0 
464                            * will cause an exit from the loop, 
465                            * which may not be what is intended. 
466                            * The fact that there is a delta in the bits
467                            * almost certainly implies that there is data
468                            * to follow.  You may feel that we should 
469                            * jump to the top of the loop to avoid exiting
470                            * in this case.  
471                            *
472                            * TODO: Decide what to do here in that case. [JAY]
473                            */
474                           x     += (*pIn++); 
475                           line  -= (*pIn++);
476                           if (line == 0)
477                             {
478                               dprintf_bitmap(stddeb, 
479                                              "DIB_SetImageBits_RLE8(): "
480                                              "Delta to last line of bitmap "
481                                              "(wrongly?) causes loop exit\n");
482                             }
483                           break;
484                       }
485                       
486                     default:    /* >2, switch to absolute mode */
487                       {
488                           /* 
489                            * Absolute Mode 
490                            */
491                           length = escape_code;
492                           while(length--)
493                             {
494                                 color_index = (*pIn++);
495                                 XPutPixel(bmpImage, x++, line, 
496                                           colors[color_index]);
497                             }
498                           
499                           /*
500                            * If you think for a moment you'll realise that the
501                            * only time we could ever possibly read an odd
502                            * number of bytes is when there is a 0x00 (escape),
503                            * a value >0x02 (absolute mode) and then an odd-
504                            * length run.  Therefore this is the only place we
505                            * need to worry about it.  Everywhere else the
506                            * bytes are always read in pairs.  [JAY]
507                            */
508                           if (escape_code & 1) 
509                             pIn++; /* Throw away the pad byte. */
510                           break;
511                       }
512                   } /* switch (escape_code) : Escape sequence */
513             }  /* process either an encoded sequence or an escape sequence */
514           
515           /* We expect to come here more than once per line. */
516       } while (line >= 0);  /* Do this until the bitmap is filled */
517     
518     /*
519      * Everybody comes here at the end.
520      * Check how we exited the loop and print a message if it's a bit odd.
521      *                                          [JAY]
522      */
523     if ( (*(pIn-2) != 0/*escape*/) || (*(pIn-1)!= RleEnd) )
524       {
525         dprintf_bitmap(stddeb, "DIB_SetImageBits_RLE8(): End-of-bitmap "
526                        "without (strictly) proper escape code.  Last two "
527                        "bytes were: %02X %02X.\n",
528                        (int)*(pIn-2),
529                        (int)*(pIn-1));           
530       }
531 }  
532
533
534 /***********************************************************************
535  *           DIB_SetImageBits_24
536  *
537  * SetDIBits for a 24-bit deep DIB.
538  */
539 static void DIB_SetImageBits_24( WORD lines, BYTE *bits, WORD width,
540                                  DC *dc, XImage *bmpImage )
541 {
542     WORD x;
543     BYTE pad = (4 - ((width*3) & 3)) & 3;
544
545     /* "bits" order is reversed for some reason */
546
547     while (lines--)
548     {
549         for (x = 0; x < width; x++, bits += 3)
550             XPutPixel( bmpImage, x, lines, 
551                        COLOR_ToPhysical(dc, RGB(bits[2],bits[1],bits[0])) );
552
553         bits += pad;
554     }
555 }
556
557
558 /***********************************************************************
559  *           DIB_SetImageBits
560  *
561  * Transfer the bits to an X image.
562  * Helper function for SetDIBits() and SetDIBitsToDevice().
563  */
564 static int DIB_SetImageBits( DC *dc, WORD lines, WORD depth, LPSTR bits,
565                              DWORD infoWidth, WORD infoBpp, DWORD compression,
566                              BITMAPINFO *info, WORD coloruse,
567                              Drawable drawable, GC gc, int xSrc, int ySrc,
568                              int xDest, int yDest, int width, int height )
569 {
570     int *colorMapping;
571     XImage *bmpImage;
572
573       /* Build the color mapping table */
574
575     if (infoBpp == 24) colorMapping = NULL;
576     else
577         if (!(colorMapping = DIB_BuildColorMap( dc, coloruse, depth, info )))
578             return 0;
579
580     if( dc->w.flags & DC_DIRTY ) CLIPPING_UpdateGCRegion(dc);
581
582       /* Transfer the pixels */
583     XCREATEIMAGE(bmpImage, infoWidth, lines, depth );
584
585     switch(infoBpp)
586     {
587     case 1:
588         DIB_SetImageBits_1( lines, bits, infoWidth,
589                             colorMapping, bmpImage );
590         break;
591     case 4:
592         if (compression) DIB_SetImageBits_RLE4( lines, bits, infoWidth,
593                                                 colorMapping, bmpImage );
594         else DIB_SetImageBits_4( lines, bits, infoWidth,
595                                  colorMapping, bmpImage );
596         break;
597     case 8:
598         if (compression) DIB_SetImageBits_RLE8( lines, bits, infoWidth,
599                                                 colorMapping, bmpImage );
600         else DIB_SetImageBits_8( lines, bits, infoWidth,
601                                  colorMapping, bmpImage );
602         break;
603     case 24:
604         DIB_SetImageBits_24( lines, bits, infoWidth, dc, bmpImage );
605         break;
606     default:
607         fprintf( stderr, "Invalid depth %d for SetDIBits!\n", infoBpp );
608         break;
609     }
610     if (colorMapping) free(colorMapping);
611     XPutImage( display, drawable, gc, bmpImage, xSrc, ySrc,
612                xDest, yDest, width, height );
613     XDestroyImage( bmpImage );
614     return lines;
615 }
616
617
618 /***********************************************************************
619  *           StretchDIBits      (GDI.439)
620  */
621 int StretchDIBits( HDC hdc, 
622         WORD xDest, WORD yDest, WORD wDestWidth, WORD wDestHeight,
623         WORD xSrc, WORD ySrc, WORD wSrcWidth, WORD wSrcHeight,
624         LPSTR bits, LPBITMAPINFO info, WORD wUsage, DWORD dwRop )
625 {
626     HBITMAP hBitmap, hOldBitmap;
627     HDC hdcMem;
628
629     hBitmap = CreateDIBitmap( hdc, &info->bmiHeader, CBM_INIT,
630                               bits, info, wUsage );
631     hdcMem = CreateCompatibleDC( hdc );
632     hOldBitmap = SelectObject( hdcMem, hBitmap );
633     StretchBlt( hdc, xDest, yDest, wDestWidth, wDestHeight,
634                 hdcMem, xSrc, ySrc, wSrcWidth, wSrcHeight, dwRop );
635     SelectObject( hdcMem, hOldBitmap );
636     DeleteDC( hdcMem );
637     DeleteObject( hBitmap );
638     return wSrcHeight;
639 }
640
641
642 /***********************************************************************
643  *           SetDIBits    (GDI.440) (GDI32.312)
644  */
645 INT16 SetDIBits( HDC32 hdc, HBITMAP32 hbitmap, UINT32 startscan, UINT32 lines,
646                  LPCVOID bits, const BITMAPINFO *info, UINT32 coloruse )
647 {
648     DC * dc;
649     BITMAPOBJ * bmp;
650     DWORD width, height, compression = 0;
651     WORD bpp;
652
653       /* Check parameters */
654
655     if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
656     if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
657         return 0;
658     if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &bpp ) == -1)
659         return 0;
660     if (info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
661         compression = info->bmiHeader.biCompression;
662     if (!lines || (startscan >= (WORD)height)) return 0;
663     if (startscan + lines > height) lines = height - startscan;
664
665     return CallTo32_LargeStack( (int(*)())DIB_SetImageBits, 17,
666                                 dc, lines, bmp->bitmap.bmBitsPixel,
667                                 bits, width, bpp, compression, info,
668                                 coloruse, bmp->pixmap, BITMAP_GC(bmp), 0, 0, 0,
669                                 startscan, bmp->bitmap.bmWidth, lines );
670 }
671
672
673 /***********************************************************************
674  *           SetDIBitsToDevice    (GDI.443) (GDI32.313)
675  */
676 INT16 SetDIBitsToDevice( HDC32 hdc, INT32 xDest, INT32 yDest, DWORD cx,
677                          DWORD cy, INT32 xSrc, INT32 ySrc, UINT32 startscan,
678                          UINT32 lines, LPCVOID bits, const BITMAPINFO *info,
679                          UINT32 coloruse )
680 {
681     DC * dc;
682     DWORD width, height, compression = 0;
683     WORD bpp;
684
685       /* Check parameters */
686
687     if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
688     if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &bpp ) == -1)
689         return 0;
690     if (info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
691         compression = info->bmiHeader.biCompression;
692     if (!lines || (startscan >= height)) return 0;
693     if (startscan + lines > height) lines = height - startscan;
694     if (ySrc < startscan) ySrc = startscan;
695     else if (ySrc >= startscan + lines) return 0;
696     if (xSrc >= width) return 0;
697     if (ySrc + cy >= startscan + lines) cy = startscan + lines - ySrc;
698     if (xSrc + cx >= width) cx = width - xSrc;
699     if (!cx || !cy) return 0;
700
701     DC_SetupGCForText( dc );  /* To have the correct colors */
702     XSetFunction( display, dc->u.x.gc, DC_XROPfunction[dc->w.ROPmode-1] );
703     return CallTo32_LargeStack( (int(*)())DIB_SetImageBits, 17,
704                                 dc, lines, dc->w.bitsPerPixel, bits, width,
705                                 bpp, compression, info, coloruse,
706                                 dc->u.x.drawable, dc->u.x.gc,
707                                 xSrc, ySrc - startscan,
708                                 dc->w.DCOrgX + XLPTODP( dc, xDest ),
709                                 dc->w.DCOrgY + YLPTODP( dc, yDest ),
710                                 cx, cy );
711 }
712
713
714
715 /***********************************************************************
716  *           GetDIBits    (GDI.441)
717  */
718 int GetDIBits( HDC hdc, HBITMAP hbitmap, WORD startscan, WORD lines,
719                LPSTR bits, BITMAPINFO * info, WORD coloruse )
720 {
721     DC * dc;
722     BITMAPOBJ * bmp;
723     PALETTEENTRY * palEntry;
724     PALETTEOBJ * palette;
725     XImage * bmpImage, * dibImage;
726     int i, x, y;
727         
728     if (!lines) return 0;
729     if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
730     if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
731         return 0;
732     if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->w.hPalette, PALETTE_MAGIC )))
733         return 0;
734
735       /* Transfer color info */
736     
737     palEntry = palette->logpalette.palPalEntry;
738     for (i = 0; i < info->bmiHeader.biClrUsed; i++, palEntry++)
739     {
740         if (coloruse == DIB_RGB_COLORS)
741         {
742             info->bmiColors[i].rgbRed      = palEntry->peRed;
743             info->bmiColors[i].rgbGreen    = palEntry->peGreen;
744             info->bmiColors[i].rgbBlue     = palEntry->peBlue;
745             info->bmiColors[i].rgbReserved = 0;
746         }
747         else ((WORD *)info->bmiColors)[i] = (WORD)i;
748     }
749     
750       /* Transfer the pixels (very slow...) */
751
752     if (bits)
753     {   
754         bmpImage = (XImage *)CallTo32_LargeStack( (int (*)())XGetImage, 8, 
755                                display, bmp->pixmap, 0, 0, bmp->bitmap.bmWidth,
756                                bmp->bitmap.bmHeight, AllPlanes, ZPixmap );
757         dibImage = DIB_DIBmpToImage( &info->bmiHeader, bits );
758
759         for (y = 0; y < lines; y++)
760         {
761             for (x = 0; x < info->bmiHeader.biWidth; x++)
762             {
763                 XPutPixel( dibImage, x, y,
764                   XGetPixel(bmpImage, x, bmp->bitmap.bmHeight-startscan-y-1) );
765                 
766             }
767         }
768         
769         dibImage->data = NULL;
770         XDestroyImage( dibImage );
771         XDestroyImage( bmpImage );
772     }
773     info->bmiHeader.biCompression = 0;
774     return lines;
775 }
776
777
778 /***********************************************************************
779  *           CreateDIBitmap    (GDI.442)
780  */
781 HBITMAP CreateDIBitmap( HDC hdc, BITMAPINFOHEADER * header, DWORD init,
782                         LPVOID bits, BITMAPINFO * data, UINT coloruse )
783 {
784     HBITMAP handle;
785     BOOL fColor;
786     DWORD width, height;
787     WORD bpp;
788
789     if (DIB_GetBitmapInfo( header, &width, &height, &bpp ) == -1) return 0;
790
791     /* Check if we should create a monochrome or color bitmap. */
792     /* We create a monochrome bitmap only if it has exactly 2  */
793     /* colors, which are either black or white, nothing else.  */
794     /* In all other cases, we create a color bitmap.           */
795
796     if (bpp != 1) fColor = TRUE;
797     else if ((coloruse != DIB_RGB_COLORS) ||
798              (init != CBM_INIT) || !data) fColor = FALSE;
799     else
800     {
801         if (data->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
802         {
803             RGBQUAD *rgb = data->bmiColors;
804             DWORD col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
805             if ((col == RGB(0,0,0)) || (col == RGB(0xff,0xff,0xff)))
806             {
807                 rgb++;
808                 col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
809                 fColor = ((col != RGB(0,0,0)) && (col != RGB(0xff,0xff,0xff)));
810             }
811             else fColor = TRUE;
812         }
813         else if (data->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
814         {
815             RGBTRIPLE *rgb = ((BITMAPCOREINFO *)data)->bmciColors;
816             DWORD col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue );
817             if ((col == RGB(0,0,0)) || (col == RGB(0xff,0xff,0xff)))
818             {
819                 rgb++;
820                 col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue );
821                 fColor = ((col != RGB(0,0,0)) && (col != RGB(0xff,0xff,0xff)));
822             }
823             else fColor = TRUE;
824         }
825         else
826         {
827             fprintf( stderr, "CreateDIBitmap: wrong size (%ld) for data\n",
828                      data->bmiHeader.biSize );
829             return 0;
830         }
831     }
832
833     /* Now create the bitmap */
834
835     handle = fColor ? CreateCompatibleBitmap( hdc, width, height ) :
836                       CreateBitmap( width, height, 1, 1, NULL );
837     if (!handle) return 0;
838
839     if (init == CBM_INIT)
840         SetDIBits( hdc, handle, 0, height, bits, data, coloruse );
841     return handle;
842 }