Added regedit unit test, a couple minor changes to regedit.
[wine] / dlls / msvideo / drawdib.c
1 /*
2  * Copyright 2000 Bradley Baetz
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  *
18  * FIXME: Some flags are ignored
19  *
20  * Handle palettes
21  */
22
23 #include <string.h>
24 #include "windef.h"
25 #include "winbase.h"
26 #include "wingdi.h"
27 #include "winuser.h"
28 #include "wine/winbase16.h"
29 #include "wine/debug.h"
30 #include "vfw.h"
31 #include "vfw16.h"
32 #include "windef.h"
33
34 WINE_DEFAULT_DEBUG_CHANNEL(msvideo);
35
36 typedef struct {
37         HDC hdc;
38         INT dxDst;
39         INT dyDst;
40         LPBITMAPINFOHEADER lpbi;
41         INT dxSrc;
42         INT dySrc;
43         HPALETTE hpal;                          /* Palette to use for the DIB */
44         BOOL begun;                                     /* DrawDibBegin has been called */
45         LPBITMAPINFOHEADER lpbiOut;     /* Output format */
46         HIC hic;                                        /* HIC for decompression */
47         HDC hMemDC;                                     /* DC for buffering */
48         HBITMAP hOldDib;                        /* Original Dib */
49         HBITMAP hDib;                           /* DibSection */
50         LPVOID lpvbits;                         /* Buffer for holding decompressed dib */
51 } WINE_HDD;
52
53 /***********************************************************************
54  *              DrawDibOpen             [MSVFW32.@]
55  */
56 HDRAWDIB VFWAPI DrawDibOpen(void) {
57         HDRAWDIB hdd;
58
59         TRACE("(void)\n");
60         hdd = GlobalAlloc16(GHND,sizeof(WINE_HDD));
61         TRACE("=> %d\n",hdd);
62         return hdd;
63 }
64
65 /***********************************************************************
66  *              DrawDibOpen             [MSVIDEO.102]
67  */
68 HDRAWDIB16 VFWAPI DrawDibOpen16(void) {
69         return (HDRAWDIB16)DrawDibOpen();
70 }
71
72 /***********************************************************************
73  *              DrawDibClose            [MSVFW32.@]
74  */
75 BOOL VFWAPI DrawDibClose(HDRAWDIB hdd) {
76         WINE_HDD *whdd = GlobalLock16(hdd);
77
78         TRACE("(0x%08lx)\n",(DWORD)hdd);
79
80         if (!whdd)
81                 return FALSE;
82
83         if (whdd->begun)
84                 DrawDibEnd(hdd);
85
86         GlobalUnlock16(hdd);
87         GlobalFree16(hdd);
88         return TRUE;
89 }
90
91 /***********************************************************************
92  *              DrawDibClose            [MSVIDEO.103]
93  */
94 BOOL16 VFWAPI DrawDibClose16(HDRAWDIB16 hdd) {
95         return DrawDibClose(hdd);
96 }
97
98 /***********************************************************************
99  *              DrawDibEnd              [MSVFW32.@]
100  */
101 BOOL VFWAPI DrawDibEnd(HDRAWDIB hdd) {
102         BOOL ret = TRUE;
103         WINE_HDD *whdd = GlobalLock16(hdd);
104
105         TRACE("(0x%08lx)\n",(DWORD)hdd);
106
107         whdd->hpal = 0; /* Do not free this */
108         whdd->hdc = 0;
109         if (whdd->lpbi) {
110                 HeapFree(GetProcessHeap(),0,whdd->lpbi);
111                 whdd->lpbi = NULL;
112         }
113         if (whdd->lpbiOut) {
114                 HeapFree(GetProcessHeap(),0,whdd->lpbiOut);
115                 whdd->lpbiOut = NULL;
116         }
117
118         whdd->begun = FALSE;
119
120         /*if (whdd->lpvbits)
121           HeapFree(GetProcessHeap(),0,whdd->lpvbuf);*/
122
123         if (whdd->hMemDC) {
124                 SelectObject(whdd->hMemDC,whdd->hOldDib);
125                 DeleteDC(whdd->hMemDC);
126         }
127
128         if (whdd->hDib)
129                 DeleteObject(whdd->hDib);
130
131         if (whdd->hic) {
132                 ICDecompressEnd(whdd->hic);
133                 ICClose(whdd->hic);
134         }
135
136         whdd->lpvbits = NULL;
137
138         GlobalUnlock16(hdd);
139         return ret;
140 }
141
142 /***********************************************************************
143  *              DrawDibEnd              [MSVIDEO.105]
144  */
145 BOOL16 VFWAPI DrawDibEnd16(HDRAWDIB16 hdd) {
146         return DrawDibEnd(hdd);
147 }
148
149 /***********************************************************************
150  *              DrawDibBegin            [MSVFW32.@]
151  */
152 BOOL VFWAPI DrawDibBegin(HDRAWDIB hdd,
153                                                  HDC      hdc,
154                                                  INT      dxDst,
155                                                  INT      dyDst,
156                                                  LPBITMAPINFOHEADER lpbi,
157                                                  INT      dxSrc,
158                                                  INT      dySrc,
159                                                  UINT     wFlags) {
160         BOOL ret = TRUE;
161         WINE_HDD *whdd;
162
163         TRACE("(%d,0x%lx,%d,%d,%p,%d,%d,0x%08lx)\n",
164                 hdd,(DWORD)hdc,dxDst,dyDst,lpbi,dxSrc,dySrc,(DWORD)wFlags
165         );
166         TRACE("lpbi: %ld,%ld/%ld,%d,%d,%ld,%ld,%ld,%ld,%ld,%ld\n",
167                   lpbi->biSize, lpbi->biWidth, lpbi->biHeight, lpbi->biPlanes,
168                   lpbi->biBitCount, lpbi->biCompression, lpbi->biSizeImage,
169                   lpbi->biXPelsPerMeter, lpbi->biYPelsPerMeter, lpbi->biClrUsed,
170                   lpbi->biClrImportant);
171
172         if (wFlags & ~(DDF_BUFFER))
173                 FIXME("wFlags == 0x%08x not handled\n", wFlags & ~(DDF_BUFFER));
174
175         whdd = (WINE_HDD*)GlobalLock16(hdd);
176         if (!whdd) return FALSE;
177
178         if (whdd->begun)
179                 DrawDibEnd(hdd);
180
181         if (lpbi->biCompression) {
182                 DWORD size = 0;
183
184                 whdd->hic = ICOpen(ICTYPE_VIDEO,lpbi->biCompression,ICMODE_DECOMPRESS);
185                 if (!whdd->hic) {
186                         WARN("Could not open IC. biCompression == 0x%08lx\n",lpbi->biCompression);
187                         ret = FALSE;
188                 }
189
190                 if (ret) {
191                         size = ICDecompressGetFormat(whdd->hic,lpbi,NULL);
192                         if (size == ICERR_UNSUPPORTED) {
193                                 WARN("Codec doesn't support GetFormat, giving up.\n");
194                                 ret = FALSE;
195                         }
196                 }
197
198                 if (ret) {
199                         whdd->lpbiOut = HeapAlloc(GetProcessHeap(),0,size);
200
201                         if (ICDecompressGetFormat(whdd->hic,lpbi,whdd->lpbiOut) != ICERR_OK)
202                                 ret = FALSE;
203                 }
204
205                 if (ret) {
206                         /* FIXME: Use Ex functions if available? */
207                         if (ICDecompressBegin(whdd->hic,lpbi,whdd->lpbiOut) != ICERR_OK)
208                                 ret = FALSE;
209
210                         TRACE("biSizeImage == %ld\n",whdd->lpbiOut->biSizeImage);
211                         TRACE("biCompression == %ld\n",whdd->lpbiOut->biCompression);
212                         TRACE("biBitCount == %d\n",whdd->lpbiOut->biBitCount);
213                 }
214         } else {
215                 DWORD dwSize;
216                 /* No compression */
217                 TRACE("Not compressed!\n");
218                 dwSize = lpbi->biSize + lpbi->biClrUsed*sizeof(RGBQUAD);
219                 whdd->lpbiOut = HeapAlloc(GetProcessHeap(),0,dwSize);
220                 memcpy(whdd->lpbiOut,lpbi,dwSize);
221         }
222
223         if (ret) {
224                 /*whdd->lpvbuf = HeapAlloc(GetProcessHeap(),0,whdd->lpbiOut->biSizeImage);*/
225
226                 whdd->hMemDC = CreateCompatibleDC(hdc);
227                 TRACE("Creating: %ld,%p\n",whdd->lpbiOut->biSize,whdd->lpvbits);
228                 whdd->hDib = CreateDIBSection(whdd->hMemDC,(BITMAPINFO *)whdd->lpbiOut,DIB_RGB_COLORS,&(whdd->lpvbits),0,0);
229                 if (!whdd->hDib) {
230                         TRACE("Error: %ld\n",GetLastError());
231                 }
232                 TRACE("Created: %d,%p\n",whdd->hDib,whdd->lpvbits);
233                 whdd->hOldDib = SelectObject(whdd->hMemDC,whdd->hDib);
234         }
235
236         if (ret) {
237                 whdd->hdc = hdc;
238                 whdd->dxDst = dxDst;
239                 whdd->dyDst = dyDst;
240                 whdd->lpbi = HeapAlloc(GetProcessHeap(),0,lpbi->biSize);
241                 memcpy(whdd->lpbi,lpbi,lpbi->biSize);
242                 whdd->dxSrc = dxSrc;
243                 whdd->dySrc = dySrc;
244                 whdd->begun = TRUE;
245                 whdd->hpal = 0;
246         } else {
247                 if (whdd->hic)
248                         ICClose(whdd->hic);
249                 if (whdd->lpbiOut) {
250                         HeapFree(GetProcessHeap(),0,whdd->lpbiOut);
251                         whdd->lpbiOut = NULL;
252                 }
253         }
254
255         GlobalUnlock16(hdd);
256
257         return ret;
258 }
259
260 /************************************************************************
261  *              DrawDibBegin            [MSVIDEO.104]
262  */
263 BOOL16 VFWAPI DrawDibBegin16(HDRAWDIB16 hdd,
264                                                    HDC16      hdc,
265                                                    INT16      dxDst,
266                                                    INT16      dyDst,
267                                                    LPBITMAPINFOHEADER lpbi,
268                                                    INT16      dxSrc,
269                                                    INT16      dySrc,
270                                                    UINT16     wFlags) {
271         return DrawDibBegin(hdd,hdc,dxDst,dyDst,lpbi,dxSrc,dySrc,wFlags);
272 }
273
274 /**********************************************************************
275  *              DrawDibDraw             [MSVFW32.@]
276  */
277 BOOL VFWAPI DrawDibDraw(HDRAWDIB hdd, HDC hdc,
278         INT xDst, INT yDst, INT dxDst, INT dyDst,
279         LPBITMAPINFOHEADER lpbi,
280         LPVOID lpBits,
281         INT xSrc, INT ySrc, INT dxSrc, INT dySrc,
282         UINT wFlags
283 ) {
284         WINE_HDD *whdd;
285         BOOL ret = TRUE;
286
287         TRACE("(%d,0x%lx,%d,%d,%d,%d,%p,%p,%d,%d,%d,%d,0x%08lx)\n",
288                   hdd,(DWORD)hdc,xDst,yDst,dxDst,dyDst,lpbi,lpBits,xSrc,ySrc,dxSrc,dySrc,(DWORD)wFlags
289         );
290
291         if (wFlags & ~(DDF_SAME_HDC | DDF_SAME_DRAW | DDF_NOTKEYFRAME |
292                                    DDF_UPDATE | DDF_DONTDRAW))
293                 FIXME("wFlags == 0x%08lx not handled\n",(DWORD)wFlags);
294
295         if (!lpBits) {
296                 /* Undocumented? */
297                 lpBits = (LPSTR)lpbi + (WORD)(lpbi->biSize) + (WORD)(lpbi->biClrUsed*sizeof(RGBQUAD));
298         }
299
300         whdd = GlobalLock16(hdd);
301
302 #define CHANGED(x) (whdd->x != x)
303
304         if ((!whdd->begun) || (!(wFlags & DDF_SAME_HDC) && CHANGED(hdc)) || (!(wFlags & DDF_SAME_DRAW) &&
305                  (CHANGED(lpbi) || CHANGED(dxSrc) || CHANGED(dySrc) || CHANGED(dxDst) || CHANGED(dyDst)))) {
306                 TRACE("Something changed!\n");
307                 ret = DrawDibBegin(hdd,hdc,dxDst,dyDst,lpbi,dxSrc,dySrc,0);
308         }
309
310 #undef CHANGED
311
312         if ((dxDst == -1) && (dyDst == -1)) {
313                 dxDst = dxSrc;
314                 dyDst = dySrc;
315         }
316
317         if (!(wFlags & DDF_UPDATE)) {
318             /* biSizeImage may be set to 0 for BI_RGB (uncompressed) bitmaps */
319             if ((lpbi->biCompression == BI_RGB) && (lpbi->biSizeImage == 0))
320                     lpbi->biSizeImage = ((lpbi->biWidth * lpbi->biBitCount + 31) / 32) * 4 * lpbi->biHeight;
321
322                 if (lpbi->biCompression) {
323                     DWORD flags = 0;
324
325                         TRACE("Compression == 0x%08lx\n",lpbi->biCompression);
326
327                         if (wFlags & DDF_NOTKEYFRAME)
328                             flags |= ICDECOMPRESS_NOTKEYFRAME;
329
330                         ICDecompress(whdd->hic,flags,lpbi,lpBits,whdd->lpbiOut,whdd->lpvbits);
331                 } else {
332                     memcpy(whdd->lpvbits,lpBits,lpbi->biSizeImage);
333                 }
334         }
335         if (!(wFlags & DDF_DONTDRAW) && whdd->hpal)
336             SelectPalette(hdc,whdd->hpal,FALSE);
337
338         if (!(StretchBlt(whdd->hdc,xDst,yDst,dxDst,dyDst,whdd->hMemDC,xSrc,ySrc,dxSrc,dySrc,SRCCOPY)))
339             ret = FALSE;
340
341         GlobalUnlock16(hdd);
342         return ret;
343 }
344
345 /**********************************************************************
346  *              DrawDibDraw             [MSVIDEO.106]
347  */
348 BOOL16 VFWAPI DrawDibDraw16(HDRAWDIB16 hdd,
349                                                   HDC16 hdc,
350                                                   INT16 xDst,
351                                                   INT16 yDst,
352                                                   INT16 dxDst,
353                                                   INT16 dyDst,
354                                                   LPBITMAPINFOHEADER lpbi,
355                                                   LPVOID lpBits,
356                                                   INT16 xSrc,
357                                                   INT16 ySrc,
358                                                   INT16 dxSrc,
359                                                   INT16 dySrc,
360                                                   UINT16 wFlags) {
361         return DrawDibDraw(hdd,hdc,xDst,yDst,dxDst,dyDst,lpbi,lpBits,xSrc,ySrc,dxSrc,dySrc,wFlags);
362 }
363
364 /*************************************************************************
365  *              DrawDibStart            [MSVFW32.@]
366  */
367 BOOL VFWAPI DrawDibStart(HDRAWDIB hdd, DWORD rate) {
368         FIXME("(0x%08lx,%ld), stub\n",(DWORD)hdd,rate);
369         return TRUE;
370 }
371
372 /*************************************************************************
373  *              DrawDibStart            [MSVIDEO.118]
374  */
375 BOOL16 VFWAPI DrawDibStart16(HDRAWDIB16 hdd, DWORD rate) {
376         return DrawDibStart(hdd,rate);
377 }
378
379 /*************************************************************************
380  *              DrawDibStop             [MSVFW32.@]
381  */
382 BOOL VFWAPI DrawDibStop(HDRAWDIB hdd) {
383         FIXME("(0x%08lx), stub\n",(DWORD)hdd);
384         return TRUE;
385 }
386
387 /*************************************************************************
388  *              DrawDibStop             [MSVIDEO.119]
389  */
390 BOOL16 DrawDibStop16(HDRAWDIB16 hdd) {
391         return DrawDibStop(hdd);
392 }
393
394 /***********************************************************************
395  *              DrawDibSetPalette       [MSVFW32.@]
396  */
397 BOOL VFWAPI DrawDibSetPalette(HDRAWDIB hdd, HPALETTE hpal) {
398         WINE_HDD *whdd;
399
400         TRACE("(0x%08lx,0x%08lx)\n",(DWORD)hdd,(DWORD)hpal);
401
402         whdd = GlobalLock16(hdd);
403         whdd->hpal = hpal;
404
405         if (whdd->begun) {
406                 SelectPalette(whdd->hdc,hpal,0);
407                 RealizePalette(whdd->hdc);
408         }
409         GlobalUnlock16(hdd);
410         return TRUE;
411 }
412
413 /***********************************************************************
414  *              DrawDibSetPalette       [MSVIDEO.110]
415  */
416 BOOL16 VFWAPI DrawDibSetPalette16(HDRAWDIB16 hdd, HPALETTE16 hpal) {
417         return DrawDibSetPalette(hdd,hpal);
418 }
419
420 /***********************************************************************
421  *              DrawDibGetPalette       [MSVFW32.@]
422  */
423 HPALETTE VFWAPI DrawDibGetPalette(HDRAWDIB hdd) {
424         WINE_HDD *whdd;
425         HPALETTE ret;
426
427         TRACE("(0x%08lx)\n",(DWORD)hdd);
428
429         whdd = GlobalLock16(hdd);
430         ret = whdd->hpal;
431         GlobalUnlock16(hdd);
432         return ret;
433 }
434
435 /***********************************************************************
436  *              DrawDibGetPalette       [MSVIDEO.108]
437  */
438 HPALETTE16 VFWAPI DrawDibGetPalette16(HDRAWDIB16 hdd) {
439         return (HPALETTE16)DrawDibGetPalette(hdd);
440 }
441
442 /***********************************************************************
443  *              DrawDibRealize          [MSVFW32.@]
444  */
445 UINT VFWAPI DrawDibRealize(HDRAWDIB hdd, HDC hdc, BOOL fBackground) {
446         WINE_HDD *whdd;
447         HPALETTE oldPal;
448         UINT ret = 0;
449
450         FIXME("(%d,0x%08lx,%d), stub\n",hdd,(DWORD)hdc,fBackground);
451
452         whdd = GlobalLock16(hdd);
453
454         if (!whdd || !(whdd->begun)) {
455                 ret = 0;
456                 goto out;
457         }
458
459         if (!whdd->hpal)
460                 whdd->hpal = CreateHalftonePalette(hdc);
461
462         oldPal = SelectPalette(hdc,whdd->hpal,fBackground);
463         ret = RealizePalette(hdc);
464
465  out:
466         GlobalUnlock16(hdd);
467
468         TRACE("=> %u\n",ret);
469         return ret;
470 }
471
472 /***********************************************************************
473  *              DrawDibRealize          [MSVIDEO.112]
474  */
475 UINT16 VFWAPI DrawDibRealize16(HDRAWDIB16 hdd, HDC16 hdc, BOOL16 fBackground) {
476         return (UINT16)DrawDibRealize(hdd,hdc,fBackground);
477 }