Release 960606
[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( 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     while (lines--)
546     {
547         for (x = 0; x < width; x++, bits += 3)
548         {
549             XPutPixel( bmpImage, x, lines,
550                        COLOR_ToPhysical( dc, RGB(bits[0],bits[1],bits[2]) ));
551         }
552         bits += pad;
553     }
554 }
555
556
557 /***********************************************************************
558  *           DIB_SetImageBits
559  *
560  * Transfer the bits to an X image.
561  * Helper function for SetDIBits() and SetDIBitsToDevice().
562  */
563 static int DIB_SetImageBits( DC *dc, WORD lines, WORD depth, LPSTR bits,
564                              DWORD infoWidth, WORD infoBpp, DWORD compression,
565                              BITMAPINFO *info, WORD coloruse,
566                              Drawable drawable, GC gc, int xSrc, int ySrc,
567                              int xDest, int yDest, int width, int height )
568 {
569     int *colorMapping;
570     XImage *bmpImage;
571
572       /* Build the color mapping table */
573
574     if (infoBpp == 24) colorMapping = NULL;
575     else
576         if (!(colorMapping = DIB_BuildColorMap( dc, coloruse, depth, info )))
577             return 0;
578
579     if( dc->w.flags & DC_DIRTY ) CLIPPING_UpdateGCRegion(dc);
580
581       /* Transfer the pixels */
582     XCREATEIMAGE(bmpImage, infoWidth, lines, depth );
583
584     switch(infoBpp)
585     {
586     case 1:
587         DIB_SetImageBits_1( lines, bits, infoWidth,
588                             colorMapping, bmpImage );
589         break;
590     case 4:
591         if (compression) DIB_SetImageBits_RLE4( lines, bits, infoWidth,
592                                                 colorMapping, bmpImage );
593         else DIB_SetImageBits_4( lines, bits, infoWidth,
594                                  colorMapping, bmpImage );
595         break;
596     case 8:
597         if (compression) DIB_SetImageBits_RLE8( lines, bits, infoWidth,
598                                                 colorMapping, bmpImage );
599         else DIB_SetImageBits_8( lines, bits, infoWidth,
600                                  colorMapping, bmpImage );
601         break;
602     case 24:
603         DIB_SetImageBits_24( lines, bits, infoWidth, dc, bmpImage );
604         break;
605     default:
606         fprintf( stderr, "Invalid depth %d for SetDIBits!\n", infoBpp );
607         break;
608     }
609     if (colorMapping) free(colorMapping);
610     XPutImage( display, drawable, gc, bmpImage, xSrc, ySrc,
611                xDest, yDest, width, height );
612     XDestroyImage( bmpImage );
613     return lines;
614 }
615
616
617 /***********************************************************************
618  *           StretchDIBits      (GDI.439)
619  */
620 int StretchDIBits( HDC hdc, 
621         WORD xDest, WORD yDest, WORD wDestWidth, WORD wDestHeight,
622         WORD xSrc, WORD ySrc, WORD wSrcWidth, WORD wSrcHeight,
623         LPSTR bits, LPBITMAPINFO info, WORD wUsage, DWORD dwRop )
624 {
625     HBITMAP hBitmap, hOldBitmap;
626     HDC hdcMem;
627
628     hBitmap = CreateDIBitmap( hdc, &info->bmiHeader, CBM_INIT,
629                               bits, info, wUsage );
630     hdcMem = CreateCompatibleDC( hdc );
631     hOldBitmap = SelectObject( hdcMem, hBitmap );
632     StretchBlt( hdc, xDest, yDest, wDestWidth, wDestHeight,
633                 hdcMem, xSrc, ySrc, wSrcWidth, wSrcHeight, dwRop );
634     SelectObject( hdcMem, hOldBitmap );
635     DeleteDC( hdcMem );
636     DeleteObject( hBitmap );
637     return wSrcHeight;
638 }
639
640
641 /***********************************************************************
642  *           SetDIBits    (GDI.440)
643  */
644 int SetDIBits( HDC hdc, HBITMAP hbitmap, WORD startscan, WORD lines,
645                LPSTR bits, BITMAPINFO * info, WORD coloruse )
646 {
647     DC * dc;
648     BITMAPOBJ * bmp;
649     DWORD width, height, compression = 0;
650     WORD bpp;
651
652       /* Check parameters */
653
654     if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
655     if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
656         return 0;
657     if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &bpp ) == -1)
658         return 0;
659     if (info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
660         compression = info->bmiHeader.biCompression;
661     if (!lines || (startscan >= (WORD)height)) return 0;
662     if (startscan + lines > height) lines = height - startscan;
663
664     return CallTo32_LargeStack( (int(*)())DIB_SetImageBits, 17,
665                                 dc, lines, bmp->bitmap.bmBitsPixel,
666                                 bits, width, bpp, compression, info,
667                                 coloruse, bmp->pixmap, BITMAP_GC(bmp), 0, 0, 0,
668                                 startscan, bmp->bitmap.bmWidth, lines );
669 }
670
671
672 /***********************************************************************
673  *           SetDIBitsToDevice    (GDI.443)
674  */
675 int SetDIBitsToDevice( HDC hdc, short xDest, short yDest, WORD cx, WORD cy,
676                        WORD xSrc, WORD ySrc, WORD startscan, WORD lines,
677                        LPSTR bits, BITMAPINFO * info, WORD coloruse )
678 {
679     DC * dc;
680     DWORD width, height, compression = 0;
681     WORD bpp;
682
683       /* Check parameters */
684
685     if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
686     if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &bpp ) == -1)
687         return 0;
688     if (info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
689         compression = info->bmiHeader.biCompression;
690     if (!lines || (startscan >= height)) return 0;
691     if (startscan + lines > height) lines = height - startscan;
692     if (ySrc < startscan) ySrc = startscan;
693     else if (ySrc >= startscan + lines) return 0;
694     if (xSrc >= width) return 0;
695     if (ySrc + cy >= startscan + lines) cy = startscan + lines - ySrc;
696     if (xSrc + cx >= width) cx = width - xSrc;
697     if (!cx || !cy) return 0;
698
699     DC_SetupGCForText( dc );  /* To have the correct colors */
700     XSetFunction( display, dc->u.x.gc, DC_XROPfunction[dc->w.ROPmode-1] );
701     return CallTo32_LargeStack( (int(*)())DIB_SetImageBits, 17,
702                                 dc, lines, dc->w.bitsPerPixel, bits, width,
703                                 bpp, compression, info, coloruse,
704                                 dc->u.x.drawable, dc->u.x.gc,
705                                 xSrc, ySrc - startscan,
706                                 dc->w.DCOrgX + XLPTODP( dc, xDest ),
707                                 dc->w.DCOrgY + YLPTODP( dc, yDest ),
708                                 cx, cy );
709 }
710
711
712
713 /***********************************************************************
714  *           GetDIBits    (GDI.441)
715  */
716 int GetDIBits( HDC hdc, HBITMAP hbitmap, WORD startscan, WORD lines,
717                LPSTR bits, BITMAPINFO * info, WORD coloruse )
718 {
719     DC * dc;
720     BITMAPOBJ * bmp;
721     PALETTEENTRY * palEntry;
722     PALETTEOBJ * palette;
723     XImage * bmpImage, * dibImage;
724     int i, x, y;
725         
726     if (!lines) return 0;
727     if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
728     if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
729         return 0;
730     if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->w.hPalette, PALETTE_MAGIC )))
731         return 0;
732
733       /* Transfer color info */
734     
735     palEntry = palette->logpalette.palPalEntry;
736     for (i = 0; i < info->bmiHeader.biClrUsed; i++, palEntry++)
737     {
738         if (coloruse == DIB_RGB_COLORS)
739         {
740             info->bmiColors[i].rgbRed      = palEntry->peRed;
741             info->bmiColors[i].rgbGreen    = palEntry->peGreen;
742             info->bmiColors[i].rgbBlue     = palEntry->peBlue;
743             info->bmiColors[i].rgbReserved = 0;
744         }
745         else ((WORD *)info->bmiColors)[i] = (WORD)i;
746     }
747     
748       /* Transfer the pixels (very slow...) */
749
750     if (bits)
751     {   
752         bmpImage = (XImage *)CallTo32_LargeStack( (int (*)())XGetImage, 8, 
753                                display, bmp->pixmap, 0, 0, bmp->bitmap.bmWidth,
754                                bmp->bitmap.bmHeight, AllPlanes, ZPixmap );
755         dibImage = DIB_DIBmpToImage( &info->bmiHeader, bits );
756
757         for (y = 0; y < lines; y++)
758         {
759             for (x = 0; x < info->bmiHeader.biWidth; x++)
760             {
761                 XPutPixel( dibImage, x, y,
762                   XGetPixel(bmpImage, x, bmp->bitmap.bmHeight-startscan-y-1) );
763                 
764             }
765         }
766         
767         dibImage->data = NULL;
768         XDestroyImage( dibImage );
769         XDestroyImage( bmpImage );
770     }
771     info->bmiHeader.biCompression = 0;
772     return lines;
773 }
774
775
776 /***********************************************************************
777  *           CreateDIBitmap    (GDI.442)
778  */
779 HBITMAP CreateDIBitmap( HDC hdc, BITMAPINFOHEADER * header, DWORD init,
780                         LPVOID bits, BITMAPINFO * data, UINT coloruse )
781 {
782     HBITMAP handle;
783     BOOL fColor;
784     DWORD width, height;
785     WORD bpp;
786
787     if (DIB_GetBitmapInfo( header, &width, &height, &bpp ) == -1) return 0;
788
789     /* Check if we should create a monochrome or color bitmap. */
790     /* We create a monochrome bitmap only if it has exactly 2  */
791     /* colors, which are either black or white, nothing else.  */
792     /* In all other cases, we create a color bitmap.           */
793
794     if (bpp != 1) fColor = TRUE;
795     else if ((coloruse != DIB_RGB_COLORS) ||
796              (init != CBM_INIT) || !data) fColor = FALSE;
797     else
798     {
799         if (data->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
800         {
801             RGBQUAD *rgb = data->bmiColors;
802             DWORD col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
803             if ((col == RGB(0,0,0)) || (col == RGB(0xff,0xff,0xff)))
804             {
805                 rgb++;
806                 col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
807                 fColor = ((col != RGB(0,0,0)) && (col != RGB(0xff,0xff,0xff)));
808             }
809             else fColor = TRUE;
810         }
811         else if (data->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
812         {
813             RGBTRIPLE *rgb = ((BITMAPCOREINFO *)data)->bmciColors;
814             DWORD col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue );
815             if ((col == RGB(0,0,0)) || (col == RGB(0xff,0xff,0xff)))
816             {
817                 rgb++;
818                 col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue );
819                 fColor = ((col != RGB(0,0,0)) && (col != RGB(0xff,0xff,0xff)));
820             }
821             else fColor = TRUE;
822         }
823         else
824         {
825             fprintf( stderr, "CreateDIBitmap: wrong size (%ld) for data\n",
826                      data->bmiHeader.biSize );
827             return 0;
828         }
829     }
830
831     /* Now create the bitmap */
832
833     handle = fColor ? CreateCompatibleBitmap( hdc, width, height ) :
834                       CreateBitmap( width, height, 1, 1, NULL );
835     if (!handle) return 0;
836
837     if (init == CBM_INIT)
838         SetDIBits( hdc, handle, 0, height, bits, data, coloruse );
839     return handle;
840 }