Release 0.4.10
[wine] / objects / dib.c
1 /*
2  * GDI device independent bitmaps
3  *
4  * Copyright 1993 Alexandre Julliard
5  */
6
7 static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
8
9 #include <stdio.h>
10 #include <stdlib.h>
11
12 #include "gdi.h"
13 #include "icon.h"
14
15
16 extern XImage * BITMAP_BmpToImage( BITMAP *, void * );
17
18
19 /***********************************************************************
20  *           DIB_BitmapInfoSize
21  *
22  * Return the size of the bitmap info structure.
23  */
24 int DIB_BitmapInfoSize( BITMAPINFO * info, WORD coloruse )
25 {
26     int size = info->bmiHeader.biClrUsed;
27     if (!size && (info->bmiHeader.biBitCount != 24))
28         size = 1 << info->bmiHeader.biBitCount;
29     if (coloruse == DIB_RGB_COLORS) 
30         size = info->bmiHeader.biSize + size * sizeof(RGBQUAD);
31     else
32         size = info->bmiHeader.biSize + size * sizeof(WORD);
33     return size;
34 }
35
36
37 /***********************************************************************
38  *           DIB_DIBmpToImage
39  *
40  * Create an XImage pointing to the bitmap data.
41  */
42 XImage * DIB_DIBmpToImage( BITMAPINFOHEADER * bmp, void * bmpData )
43 {
44     XImage * image;
45     int bytesPerLine = (bmp->biWidth * bmp->biBitCount + 31) / 32 * 4;
46     
47     image = XCreateImage( XT_display, DefaultVisualOfScreen( XT_screen ),
48                           bmp->biBitCount, ZPixmap, 0, bmpData,
49                           bmp->biWidth, bmp->biHeight, 32, bytesPerLine );
50     if (!image) return 0;
51     image->byte_order = MSBFirst;
52     image->bitmap_bit_order = MSBFirst;
53     image->bitmap_unit = 16;
54     _XInitImageFuncPtrs(image);
55     return image;
56 }
57
58
59 /***********************************************************************
60  *           SetDIBits    (GDI.440)
61  */
62 int SetDIBits( HDC hdc, HBITMAP hbitmap, WORD startscan, WORD lines,
63                LPSTR bits, BITMAPINFO * info, WORD coloruse )
64 {
65     DC * dc;
66     BITMAPOBJ * bmpObj;
67     BITMAP * bmp;
68     WORD * colorMapping;
69     RGBQUAD * rgbPtr;
70     XImage * bmpImage, * dibImage;
71     int i, x, y, pixel, colors;
72         
73     if (!lines) return 0;
74     if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
75     if (!(bmpObj = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
76         return 0;
77     if (!(bmp = (BITMAP *) GlobalLock( bmpObj->hBitmap ))) return 0;
78
79       /* Build the color mapping table */
80
81     if (info->bmiHeader.biBitCount == 24) colorMapping = NULL;
82     else if (coloruse == DIB_RGB_COLORS)
83     {
84         colors = info->bmiHeader.biClrUsed;
85         if (!colors) colors = 1 << info->bmiHeader.biBitCount;
86         if (!(colorMapping = (WORD *)malloc( colors * sizeof(WORD) )))
87         {
88             GlobalUnlock( bmpObj->hBitmap );
89             return 0;
90         }
91         for (i = 0, rgbPtr = info->bmiColors; i < colors; i++, rgbPtr++)
92             colorMapping[i] = GetNearestPaletteIndex( dc->w.hPalette, 
93                                                      RGB(rgbPtr->rgbRed,
94                                                          rgbPtr->rgbGreen,
95                                                          rgbPtr->rgbBlue) );
96     }
97     else colorMapping = (WORD *)info->bmiColors;
98
99       /* Transfer the pixels (very slow...) */
100
101     bmpImage = BITMAP_BmpToImage( bmp, ((char *)bmp) + sizeof(BITMAP) );
102     dibImage = DIB_DIBmpToImage( &info->bmiHeader, bits );
103
104     for (y = 0; y < lines; y++)
105     {
106         for (x = 0; x < info->bmiHeader.biWidth; x++)
107         {
108             pixel = XGetPixel( dibImage, x, y );
109             if (colorMapping) pixel = colorMapping[pixel];
110             else pixel = GetNearestPaletteIndex(dc->w.hPalette,(COLORREF)pixel);
111             XPutPixel( bmpImage, x, bmp->bmHeight - startscan - y - 1, pixel );
112         }
113     }
114
115     bmpImage->data = NULL;
116     dibImage->data = NULL;
117     XDestroyImage( bmpImage );
118     XDestroyImage( dibImage );
119
120     if (colorMapping && (coloruse == DIB_RGB_COLORS)) free(colorMapping);
121     
122     GlobalUnlock( bmpObj->hBitmap );
123     return lines;
124 }
125
126
127 /***********************************************************************
128  *           GetDIBits    (GDI.441)
129  */
130 int GetDIBits( HDC hdc, HBITMAP hbitmap, WORD startscan, WORD lines,
131                LPSTR bits, BITMAPINFO * info, WORD coloruse )
132 {
133     DC * dc;
134     BITMAPOBJ * bmpObj;
135     BITMAP * bmp;
136     PALETTEENTRY * palEntry;
137     PALETTEOBJ * palette;
138     XImage * bmpImage, * dibImage;
139     int i, x, y;
140         
141     if (!lines) return 0;
142     if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
143     if (!(bmpObj = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
144         return 0;
145     if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->w.hPalette, PALETTE_MAGIC )))
146         return 0;
147     if (!(bmp = (BITMAP *) GlobalLock( bmpObj->hBitmap ))) return 0;
148
149       /* Transfer color info */
150     
151     palEntry = palette->logpalette.palPalEntry;
152     for (i = 0; i < info->bmiHeader.biClrUsed; i++, palEntry++)
153     {
154         if (coloruse == DIB_RGB_COLORS)
155         {
156             info->bmiColors[i].rgbRed      = palEntry->peRed;
157             info->bmiColors[i].rgbGreen    = palEntry->peGreen;
158             info->bmiColors[i].rgbBlue     = palEntry->peBlue;
159             info->bmiColors[i].rgbReserved = 0;
160         }
161         else ((WORD *)info->bmiColors)[i] = (WORD)i;
162     }
163     
164       /* Transfer the pixels (very slow...) */
165
166     if (bits)
167     {   
168         bmpImage = BITMAP_BmpToImage( bmp, ((char *)bmp) + sizeof(BITMAP) );
169         dibImage = DIB_DIBmpToImage( &info->bmiHeader, bits );
170
171         for (y = 0; y < lines; y++)
172         {
173             for (x = 0; x < info->bmiHeader.biWidth; x++)
174             {
175                 XPutPixel( dibImage, x, y,
176                          XGetPixel(bmpImage, x, bmp->bmHeight-startscan-y-1) );
177                 
178             }
179         }
180         
181         bmpImage->data = NULL;
182         dibImage->data = NULL;
183         XDestroyImage( bmpImage );
184         XDestroyImage( dibImage );
185     }
186
187     GlobalUnlock( bmpObj->hBitmap );
188     return lines;
189 }
190
191
192 /***********************************************************************
193  *           CreateDIBitmap    (GDI.442)
194  */
195 HBITMAP CreateDIBitmap( HDC hdc, BITMAPINFOHEADER * header, DWORD init,
196                         LPSTR bits, BITMAPINFO * data, WORD coloruse )
197 {
198     HBITMAP handle;
199     
200     handle = CreateCompatibleBitmap( hdc, header->biWidth, header->biHeight );
201     if (!handle) return 0;
202     if (init == CBM_INIT) SetDIBits( hdc, handle, 0, header->biHeight,
203                                     bits, data, coloruse );
204     return handle;
205 }
206
207 /***********************************************************************
208  *           DrawIcon    (USER.84)
209  */
210 BOOL DrawIcon(HDC hDC, short x, short y, HICON hIcon)
211 {
212     ICONALLOC   *lpico;
213     BITMAP      bm;
214     HBITMAP     hBitTemp;
215     HDC         hMemDC;
216     HDC         hMemDC2;
217 #ifdef DEBUG_ICON
218     printf("DrawIcon(%04X, %d, %d, %04X) \n", hDC, x, y, hIcon);
219 #endif
220     if (hIcon == (HICON)NULL) return FALSE;
221     lpico = (ICONALLOC *)GlobalLock(hIcon);
222     GetObject(lpico->hBitmap, sizeof(BITMAP), (LPSTR)&bm);
223 #ifdef DEBUG_ICON
224     printf("DrawIcon / x=%d y=%d\n", x, y);
225     printf("DrawIcon / icon Width=%d\n", (int)lpico->descriptor.Width);
226     printf("DrawIcon / icon Height=%d\n", (int)lpico->descriptor.Height);
227     printf("DrawIcon / icon ColorCount=%d\n", (int)lpico->descriptor.ColorCount);
228     printf("DrawIcon / icon icoDIBSize=%lX\n", (DWORD)lpico->descriptor.icoDIBSize);
229     printf("DrawIcon / icon icoDIBOffset=%lX\n", (DWORD)lpico->descriptor.icoDIBOffset);
230     printf("DrawIcon / bitmap bmWidth=%d bmHeight=%d\n", bm.bmWidth, bm.bmHeight);
231 #endif
232     hMemDC = CreateCompatibleDC(hDC);
233 #ifdef DEBUG_ICON
234     SelectObject(hMemDC, lpico->hBitmap);
235     BitBlt(hDC, x, y, bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
236     SelectObject(hMemDC, lpico->hBitMask);
237     BitBlt(hDC, x, y + bm.bmHeight, bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
238 #else
239     SelectObject(hMemDC, lpico->hBitMask);
240     BitBlt(hDC, x, y, bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCAND);
241     SelectObject(hMemDC, lpico->hBitmap);
242     BitBlt(hDC, x, y, bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCPAINT);
243 #endif
244     DeleteDC(hMemDC);
245     return TRUE;
246 }
247