Synchronize with trunk revision 59636 (just before Alex's CreateProcess revamp).
[reactos.git] / dll / win32 / msvfw32 / 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17 *
18 * FIXME: Some flags are ignored
19 *
20 * Handle palettes
21 */
22
23 #define WIN32_NO_STATUS
24 #define _INC_WINDOWS
25 #define COM_NO_WINDOWS_H
26
27 #include <stdarg.h>
28 //#include <stdio.h>
29 //#include <string.h>
30
31 #include <windef.h>
32 #include <winbase.h>
33 #include <wingdi.h>
34 //#include "winuser.h"
35 #include <vfw.h>
36
37 #include <wine/debug.h>
38
39 WINE_DEFAULT_DEBUG_CHANNEL(msvideo);
40
41 typedef struct tagWINE_HDD {
42 HDC hdc;
43 INT dxDst;
44 INT dyDst;
45 LPBITMAPINFOHEADER lpbi;
46 INT dxSrc;
47 INT dySrc;
48 HPALETTE hpal; /* Palette to use for the DIB */
49 BOOL begun; /* DrawDibBegin has been called */
50 LPBITMAPINFOHEADER lpbiOut; /* Output format */
51 HIC hic; /* HIC for decompression */
52 HDC hMemDC; /* DC for buffering */
53 HBITMAP hOldDib; /* Original Dib */
54 HBITMAP hDib; /* DibSection */
55 LPVOID lpvbits; /* Buffer for holding decompressed dib */
56 HDRAWDIB hSelf;
57 struct tagWINE_HDD* next;
58 } WINE_HDD;
59
60 static int num_colours(const BITMAPINFOHEADER *lpbi)
61 {
62 if(lpbi->biClrUsed)
63 return lpbi->biClrUsed;
64 if(lpbi->biBitCount<=8)
65 return 1<<lpbi->biBitCount;
66 return 0;
67 }
68
69 static WINE_HDD* HDD_FirstHdd /* = NULL */;
70
71 static WINE_HDD* MSVIDEO_GetHddPtr(HDRAWDIB hd)
72 {
73 WINE_HDD* hdd;
74
75 for (hdd = HDD_FirstHdd; hdd != NULL && hdd->hSelf != hd; hdd = hdd->next);
76 return hdd;
77 }
78
79 static UINT_PTR HDD_HandleRef = 1;
80
81 /***********************************************************************
82 * DrawDibOpen [MSVFW32.@]
83 */
84 HDRAWDIB VFWAPI DrawDibOpen(void)
85 {
86 WINE_HDD* whdd;
87
88 TRACE("(void)\n");
89
90 whdd = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WINE_HDD));
91 TRACE("=> %p\n", whdd);
92
93 while (MSVIDEO_GetHddPtr((HDRAWDIB)HDD_HandleRef) != NULL) HDD_HandleRef++;
94 whdd->hSelf = (HDRAWDIB)HDD_HandleRef++;
95
96 whdd->next = HDD_FirstHdd;
97 HDD_FirstHdd = whdd;
98
99 return whdd->hSelf;
100 }
101
102 /***********************************************************************
103 * DrawDibClose [MSVFW32.@]
104 */
105 BOOL VFWAPI DrawDibClose(HDRAWDIB hdd)
106 {
107 WINE_HDD* whdd = MSVIDEO_GetHddPtr(hdd);
108 WINE_HDD** p;
109
110 TRACE("(%p)\n", hdd);
111
112 if (!whdd) return FALSE;
113
114 if (whdd->begun) DrawDibEnd(hdd);
115
116 for (p = &HDD_FirstHdd; *p != NULL; p = &((*p)->next))
117 {
118 if (*p == whdd)
119 {
120 *p = whdd->next;
121 break;
122 }
123 }
124
125 HeapFree(GetProcessHeap(), 0, whdd);
126
127 return TRUE;
128 }
129
130 /***********************************************************************
131 * DrawDibEnd [MSVFW32.@]
132 */
133 BOOL VFWAPI DrawDibEnd(HDRAWDIB hdd)
134 {
135 BOOL ret = TRUE;
136 WINE_HDD *whdd = MSVIDEO_GetHddPtr(hdd);
137
138 TRACE("(%p)\n", hdd);
139
140 if (!whdd) return FALSE;
141
142 whdd->hpal = 0; /* Do not free this */
143 whdd->hdc = 0;
144 HeapFree(GetProcessHeap(), 0, whdd->lpbi);
145 whdd->lpbi = NULL;
146 HeapFree(GetProcessHeap(), 0, whdd->lpbiOut);
147 whdd->lpbiOut = NULL;
148
149 whdd->begun = FALSE;
150
151 /*if (whdd->lpvbits)
152 HeapFree(GetProcessHeap(), 0, whdd->lpvbuf);*/
153
154 if (whdd->hMemDC)
155 {
156 SelectObject(whdd->hMemDC, whdd->hOldDib);
157 DeleteDC(whdd->hMemDC);
158 whdd->hMemDC = 0;
159 }
160
161 if (whdd->hDib) DeleteObject(whdd->hDib);
162 whdd->hDib = 0;
163
164 if (whdd->hic)
165 {
166 ICDecompressEnd(whdd->hic);
167 ICClose(whdd->hic);
168 whdd->hic = 0;
169 }
170
171 whdd->lpvbits = NULL;
172
173 return ret;
174 }
175
176 /***********************************************************************
177 * DrawDibBegin [MSVFW32.@]
178 */
179 BOOL VFWAPI DrawDibBegin(HDRAWDIB hdd,
180 HDC hdc,
181 INT dxDst,
182 INT dyDst,
183 LPBITMAPINFOHEADER lpbi,
184 INT dxSrc,
185 INT dySrc,
186 UINT wFlags)
187 {
188 BOOL ret = TRUE;
189 WINE_HDD *whdd;
190
191 TRACE("(%p,%p,%d,%d,%p,%d,%d,0x%08x)\n",
192 hdd, hdc, dxDst, dyDst, lpbi, dxSrc, dySrc, wFlags);
193
194 TRACE("lpbi: %d,%d/%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
195 lpbi->biSize, lpbi->biWidth, lpbi->biHeight, lpbi->biPlanes,
196 lpbi->biBitCount, lpbi->biCompression, lpbi->biSizeImage,
197 lpbi->biXPelsPerMeter, lpbi->biYPelsPerMeter, lpbi->biClrUsed,
198 lpbi->biClrImportant);
199
200 if (wFlags & ~(DDF_BUFFER))
201 FIXME("wFlags == 0x%08x not handled\n", wFlags & ~(DDF_BUFFER));
202
203 whdd = MSVIDEO_GetHddPtr(hdd);
204 if (!whdd) return FALSE;
205
206 if (whdd->begun) DrawDibEnd(hdd);
207
208 if (lpbi->biCompression)
209 {
210 DWORD size = 0;
211
212 whdd->hic = ICOpen(ICTYPE_VIDEO, lpbi->biCompression, ICMODE_DECOMPRESS);
213 if (!whdd->hic)
214 {
215 WARN("Could not open IC. biCompression == 0x%08x\n", lpbi->biCompression);
216 ret = FALSE;
217 }
218
219 if (ret)
220 {
221 size = ICDecompressGetFormat(whdd->hic, lpbi, NULL);
222 if (size == ICERR_UNSUPPORTED)
223 {
224 WARN("Codec doesn't support GetFormat, giving up.\n");
225 ret = FALSE;
226 }
227 }
228
229 if (ret)
230 {
231 whdd->lpbiOut = HeapAlloc(GetProcessHeap(), 0, size);
232
233 if (ICDecompressGetFormat(whdd->hic, lpbi, whdd->lpbiOut) != ICERR_OK)
234 ret = FALSE;
235 }
236
237 if (ret)
238 {
239 /* FIXME: Use Ex functions if available? */
240 if (ICDecompressBegin(whdd->hic, lpbi, whdd->lpbiOut) != ICERR_OK)
241 ret = FALSE;
242
243 TRACE("biSizeImage == %d\n", whdd->lpbiOut->biSizeImage);
244 TRACE("biCompression == %d\n", whdd->lpbiOut->biCompression);
245 TRACE("biBitCount == %d\n", whdd->lpbiOut->biBitCount);
246 }
247 }
248 else
249 {
250 DWORD dwSize;
251 /* No compression */
252 TRACE("Not compressed!\n");
253 dwSize = lpbi->biSize + num_colours(lpbi)*sizeof(RGBQUAD);
254 whdd->lpbiOut = HeapAlloc(GetProcessHeap(), 0, dwSize);
255 memcpy(whdd->lpbiOut, lpbi, dwSize);
256 }
257
258 if (ret)
259 {
260 /*whdd->lpvbuf = HeapAlloc(GetProcessHeap(), 0, whdd->lpbiOut->biSizeImage);*/
261
262 whdd->hMemDC = CreateCompatibleDC(hdc);
263 TRACE("Creating: %d, %p\n", whdd->lpbiOut->biSize, whdd->lpvbits);
264 whdd->hDib = CreateDIBSection(whdd->hMemDC, (BITMAPINFO *)whdd->lpbiOut, DIB_RGB_COLORS, &(whdd->lpvbits), 0, 0);
265 if (whdd->hDib)
266 {
267 TRACE("Created: %p,%p\n", whdd->hDib, whdd->lpvbits);
268 }
269 else
270 {
271 ret = FALSE;
272 TRACE("Error: %d\n", GetLastError());
273 }
274 whdd->hOldDib = SelectObject(whdd->hMemDC, whdd->hDib);
275 }
276
277 if (ret)
278 {
279 whdd->hdc = hdc;
280 whdd->dxDst = dxDst;
281 whdd->dyDst = dyDst;
282 whdd->lpbi = HeapAlloc(GetProcessHeap(), 0, lpbi->biSize);
283 memcpy(whdd->lpbi, lpbi, lpbi->biSize);
284 whdd->dxSrc = dxSrc;
285 whdd->dySrc = dySrc;
286 whdd->begun = TRUE;
287 whdd->hpal = 0;
288 }
289 else
290 {
291 if (whdd->hic)
292 ICClose(whdd->hic);
293 HeapFree(GetProcessHeap(), 0, whdd->lpbiOut);
294 whdd->lpbiOut = NULL;
295 }
296
297 return ret;
298 }
299
300 /**********************************************************************
301 * DrawDibDraw [MSVFW32.@]
302 */
303 BOOL VFWAPI DrawDibDraw(HDRAWDIB hdd, HDC hdc,
304 INT xDst, INT yDst, INT dxDst, INT dyDst,
305 LPBITMAPINFOHEADER lpbi,
306 LPVOID lpBits,
307 INT xSrc, INT ySrc, INT dxSrc, INT dySrc,
308 UINT wFlags)
309 {
310 WINE_HDD *whdd;
311 BOOL ret = TRUE;
312
313 TRACE("(%p,%p,%d,%d,%d,%d,%p,%p,%d,%d,%d,%d,0x%08x)\n",
314 hdd, hdc, xDst, yDst, dxDst, dyDst, lpbi, lpBits, xSrc, ySrc, dxSrc, dySrc, wFlags);
315
316 whdd = MSVIDEO_GetHddPtr(hdd);
317 if (!whdd) return FALSE;
318
319 TRACE("whdd=%p\n", whdd);
320
321 if (wFlags & ~(DDF_SAME_HDC | DDF_SAME_DRAW | DDF_NOTKEYFRAME | DDF_UPDATE | DDF_DONTDRAW | DDF_BACKGROUNDPAL))
322 FIXME("wFlags == 0x%08x not handled\n", wFlags);
323
324 if (!lpBits)
325 {
326 /* Undocumented? */
327 lpBits = (LPSTR)lpbi + (WORD)(lpbi->biSize) + (WORD)(num_colours(lpbi)*sizeof(RGBQUAD));
328 }
329
330
331 #define CHANGED(x) (whdd->x != x)
332
333 if ((!whdd->begun) ||
334 (!(wFlags & DDF_SAME_HDC) && CHANGED(hdc)) ||
335 (!(wFlags & DDF_SAME_DRAW) && (CHANGED(lpbi) || CHANGED(dxSrc) || CHANGED(dySrc) || CHANGED(dxDst) || CHANGED(dyDst))))
336 {
337 TRACE("Something changed!\n");
338 ret = DrawDibBegin(hdd, hdc, dxDst, dyDst, lpbi, dxSrc, dySrc, 0);
339 }
340
341 #undef CHANGED
342
343 if ((dxDst == -1) && (dyDst == -1))
344 {
345 dxDst = dxSrc;
346 dyDst = dySrc;
347 }
348
349 if (!(wFlags & DDF_UPDATE))
350 {
351 DWORD biSizeImage = lpbi->biSizeImage;
352
353 /* biSizeImage may be set to 0 for BI_RGB (uncompressed) bitmaps */
354 if ((lpbi->biCompression == BI_RGB) && (biSizeImage == 0))
355 biSizeImage = ((lpbi->biWidth * lpbi->biBitCount + 31) / 32) * 4 * lpbi->biHeight;
356
357 if (lpbi->biCompression)
358 {
359 DWORD flags = 0;
360
361 TRACE("Compression == 0x%08x\n", lpbi->biCompression);
362
363 if (wFlags & DDF_NOTKEYFRAME)
364 flags |= ICDECOMPRESS_NOTKEYFRAME;
365
366 ICDecompress(whdd->hic, flags, lpbi, lpBits, whdd->lpbiOut, whdd->lpvbits);
367 }
368 else
369 {
370 memcpy(whdd->lpvbits, lpBits, biSizeImage);
371 }
372 }
373 if (!(wFlags & DDF_DONTDRAW) && whdd->hpal)
374 {
375 if ((wFlags & DDF_BACKGROUNDPAL) && ! (wFlags & DDF_SAME_HDC))
376 SelectPalette(hdc, whdd->hpal, TRUE);
377 else
378 SelectPalette(hdc, whdd->hpal, FALSE);
379 }
380
381 if (!(StretchBlt(whdd->hdc, xDst, yDst, dxDst, dyDst, whdd->hMemDC, xSrc, ySrc, dxSrc, dySrc, SRCCOPY)))
382 ret = FALSE;
383
384 return ret;
385 }
386
387 /*************************************************************************
388 * DrawDibStart [MSVFW32.@]
389 */
390 BOOL VFWAPI DrawDibStart(HDRAWDIB hdd, DWORD rate) {
391 FIXME("(%p, %d), stub\n", hdd, rate);
392 return TRUE;
393 }
394
395 /*************************************************************************
396 * DrawDibStop [MSVFW32.@]
397 */
398 BOOL VFWAPI DrawDibStop(HDRAWDIB hdd) {
399 FIXME("(%p), stub\n", hdd);
400 return TRUE;
401 }
402
403 /***********************************************************************
404 * DrawDibChangePalette [MSVFW32.@]
405 */
406 BOOL VFWAPI DrawDibChangePalette(HDRAWDIB hdd, int iStart, int iLen, LPPALETTEENTRY lppe)
407 {
408 FIXME("(%p, 0x%08x, 0x%08x, %p), stub\n", hdd, iStart, iLen, lppe);
409 return TRUE;
410 }
411
412 /***********************************************************************
413 * DrawDibSetPalette [MSVFW32.@]
414 */
415 BOOL VFWAPI DrawDibSetPalette(HDRAWDIB hdd, HPALETTE hpal)
416 {
417 WINE_HDD *whdd;
418
419 TRACE("(%p, %p)\n", hdd, hpal);
420
421 whdd = MSVIDEO_GetHddPtr(hdd);
422 if (!whdd) return FALSE;
423
424 whdd->hpal = hpal;
425
426 if (whdd->begun)
427 {
428 SelectPalette(whdd->hdc, hpal, 0);
429 RealizePalette(whdd->hdc);
430 }
431
432 return TRUE;
433 }
434
435 /***********************************************************************
436 * DrawDibGetBuffer [MSVFW32.@]
437 */
438 LPVOID VFWAPI DrawDibGetBuffer(HDRAWDIB hdd, LPBITMAPINFOHEADER lpbi, DWORD dwSize, DWORD dwFlags)
439 {
440 FIXME("(%p, %p, 0x%08x, 0x%08x), stub\n", hdd, lpbi, dwSize, dwFlags);
441 return NULL;
442 }
443
444 /***********************************************************************
445 * DrawDibGetPalette [MSVFW32.@]
446 */
447 HPALETTE VFWAPI DrawDibGetPalette(HDRAWDIB hdd)
448 {
449 WINE_HDD *whdd;
450
451 TRACE("(%p)\n", hdd);
452
453 whdd = MSVIDEO_GetHddPtr(hdd);
454 if (!whdd) return FALSE;
455
456 return whdd->hpal;
457 }
458
459 /***********************************************************************
460 * DrawDibRealize [MSVFW32.@]
461 */
462 UINT VFWAPI DrawDibRealize(HDRAWDIB hdd, HDC hdc, BOOL fBackground)
463 {
464 WINE_HDD *whdd;
465 UINT ret = 0;
466
467 FIXME("(%p, %p, %d), stub\n", hdd, hdc, fBackground);
468
469 whdd = MSVIDEO_GetHddPtr(hdd);
470 if (!whdd) return FALSE;
471
472 if (!whdd || !(whdd->begun))
473 {
474 ret = 0;
475 goto out;
476 }
477
478 if (!whdd->hpal)
479 whdd->hpal = CreateHalftonePalette(hdc);
480
481 SelectPalette(hdc, whdd->hpal, fBackground);
482 ret = RealizePalette(hdc);
483
484 out:
485 TRACE("=> %u\n", ret);
486 return ret;
487 }
488
489 /***********************************************************************
490 * DrawDibTime [MSVFW32.@]
491 */
492 BOOL VFWAPI DrawDibTime(HDRAWDIB hdd, LPDRAWDIBTIME lpddtime)
493 {
494 FIXME("(%p, %p) stub\n", hdd, lpddtime);
495 return FALSE;
496 }
497
498 /***********************************************************************
499 * DrawDibProfileDisplay [MSVFW32.@]
500 */
501 DWORD VFWAPI DrawDibProfileDisplay(LPBITMAPINFOHEADER lpbi)
502 {
503 FIXME("(%p) stub\n", lpbi);
504
505 return PD_CAN_DRAW_DIB;
506 }