Added initial version of Delnode plus some tests.
[wine.git] / dlls / msvideo / drawdib.c
blob67732123e206485579c4581b3d313ee89a7fab48
1 /*
2 * Copyright 2000 Bradley Baetz
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.
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.
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
18 * FIXME: Some flags are ignored
20 * Handle palettes
23 #include <string.h>
24 #include "msvideo_private.h"
26 #include "wingdi.h"
27 #include "winuser.h"
29 #include "wine/debug.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(msvideo);
33 typedef struct tagWINE_HDD {
34 HDC hdc;
35 INT dxDst;
36 INT dyDst;
37 LPBITMAPINFOHEADER lpbi;
38 INT dxSrc;
39 INT dySrc;
40 HPALETTE hpal; /* Palette to use for the DIB */
41 BOOL begun; /* DrawDibBegin has been called */
42 LPBITMAPINFOHEADER lpbiOut; /* Output format */
43 HIC hic; /* HIC for decompression */
44 HDC hMemDC; /* DC for buffering */
45 HBITMAP hOldDib; /* Original Dib */
46 HBITMAP hDib; /* DibSection */
47 LPVOID lpvbits; /* Buffer for holding decompressed dib */
48 HDRAWDIB hSelf;
49 struct tagWINE_HDD* next;
50 } WINE_HDD;
52 int num_colours(LPBITMAPINFOHEADER lpbi)
54 if(lpbi->biClrUsed)
55 return lpbi->biClrUsed;
56 if(lpbi->biBitCount<=8)
57 return 1<<lpbi->biBitCount;
58 return 0;
61 static WINE_HDD* HDD_FirstHdd /* = NULL */;
63 static WINE_HDD* MSVIDEO_GetHddPtr(HDRAWDIB hd)
65 WINE_HDD* hdd;
67 for (hdd = HDD_FirstHdd; hdd != NULL && hdd->hSelf != hd; hdd = hdd->next);
68 return hdd;
71 static DWORD HDD_HandleRef = 1;
73 /***********************************************************************
74 * DrawDibOpen [MSVFW32.@]
76 HDRAWDIB VFWAPI DrawDibOpen(void)
78 WINE_HDD* whdd;
80 TRACE("(void)\n");
82 whdd = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WINE_HDD));
83 TRACE("=> %p\n", whdd);
85 while (MSVIDEO_GetHddPtr((HDRAWDIB)HDD_HandleRef) != NULL) HDD_HandleRef++;
86 whdd->hSelf = (HDRAWDIB)HDD_HandleRef++;
88 whdd->next = HDD_FirstHdd;
89 HDD_FirstHdd = whdd;
91 return whdd->hSelf;
94 /***********************************************************************
95 * DrawDibClose [MSVFW32.@]
97 BOOL VFWAPI DrawDibClose(HDRAWDIB hdd)
99 WINE_HDD* whdd = MSVIDEO_GetHddPtr(hdd);
100 WINE_HDD** p;
102 TRACE("(%p)\n", hdd);
104 if (!whdd) return FALSE;
106 if (whdd->begun) DrawDibEnd(hdd);
108 for (p = &HDD_FirstHdd; *p != NULL; p = &((*p)->next))
110 if (*p == whdd)
112 *p = whdd->next;
113 break;
117 HeapFree(GetProcessHeap(), 0, whdd);
119 return TRUE;
122 /***********************************************************************
123 * DrawDibEnd [MSVFW32.@]
125 BOOL VFWAPI DrawDibEnd(HDRAWDIB hdd)
127 BOOL ret = TRUE;
128 WINE_HDD *whdd = MSVIDEO_GetHddPtr(hdd);
130 TRACE("(%p)\n", hdd);
132 whdd->hpal = 0; /* Do not free this */
133 whdd->hdc = 0;
134 HeapFree(GetProcessHeap(), 0, whdd->lpbi);
135 whdd->lpbi = NULL;
136 HeapFree(GetProcessHeap(), 0, whdd->lpbiOut);
137 whdd->lpbiOut = NULL;
139 whdd->begun = FALSE;
141 /*if (whdd->lpvbits)
142 HeapFree(GetProcessHeap(), 0, whdd->lpvbuf);*/
144 if (whdd->hMemDC)
146 SelectObject(whdd->hMemDC, whdd->hOldDib);
147 DeleteDC(whdd->hMemDC);
148 whdd->hMemDC = 0;
151 if (whdd->hDib) DeleteObject(whdd->hDib);
152 whdd->hDib = 0;
154 if (whdd->hic)
156 ICDecompressEnd(whdd->hic);
157 ICClose(whdd->hic);
158 whdd->hic = 0;
161 whdd->lpvbits = NULL;
163 return ret;
166 /***********************************************************************
167 * DrawDibBegin [MSVFW32.@]
169 BOOL VFWAPI DrawDibBegin(HDRAWDIB hdd,
170 HDC hdc,
171 INT dxDst,
172 INT dyDst,
173 LPBITMAPINFOHEADER lpbi,
174 INT dxSrc,
175 INT dySrc,
176 UINT wFlags)
178 BOOL ret = TRUE;
179 WINE_HDD *whdd;
181 TRACE("(%p,%p,%d,%d,%p,%d,%d,0x%08lx)\n",
182 hdd, hdc, dxDst, dyDst, lpbi, dxSrc, dySrc, (DWORD)wFlags);
184 TRACE("lpbi: %ld,%ld/%ld,%d,%d,%ld,%ld,%ld,%ld,%ld,%ld\n",
185 lpbi->biSize, lpbi->biWidth, lpbi->biHeight, lpbi->biPlanes,
186 lpbi->biBitCount, lpbi->biCompression, lpbi->biSizeImage,
187 lpbi->biXPelsPerMeter, lpbi->biYPelsPerMeter, lpbi->biClrUsed,
188 lpbi->biClrImportant);
190 if (wFlags & ~(DDF_BUFFER))
191 FIXME("wFlags == 0x%08x not handled\n", wFlags & ~(DDF_BUFFER));
193 whdd = MSVIDEO_GetHddPtr(hdd);
194 if (!whdd) return FALSE;
196 if (whdd->begun) DrawDibEnd(hdd);
198 if (lpbi->biCompression)
200 DWORD size = 0;
202 whdd->hic = ICOpen(ICTYPE_VIDEO, lpbi->biCompression, ICMODE_DECOMPRESS);
203 if (!whdd->hic)
205 WARN("Could not open IC. biCompression == 0x%08lx\n", lpbi->biCompression);
206 ret = FALSE;
209 if (ret)
211 size = ICDecompressGetFormat(whdd->hic, lpbi, NULL);
212 if (size == ICERR_UNSUPPORTED)
214 WARN("Codec doesn't support GetFormat, giving up.\n");
215 ret = FALSE;
219 if (ret)
221 whdd->lpbiOut = HeapAlloc(GetProcessHeap(), 0, size);
223 if (ICDecompressGetFormat(whdd->hic, lpbi, whdd->lpbiOut) != ICERR_OK)
224 ret = FALSE;
227 if (ret)
229 /* FIXME: Use Ex functions if available? */
230 if (ICDecompressBegin(whdd->hic, lpbi, whdd->lpbiOut) != ICERR_OK)
231 ret = FALSE;
233 TRACE("biSizeImage == %ld\n", whdd->lpbiOut->biSizeImage);
234 TRACE("biCompression == %ld\n", whdd->lpbiOut->biCompression);
235 TRACE("biBitCount == %d\n", whdd->lpbiOut->biBitCount);
238 else
240 DWORD dwSize;
241 /* No compression */
242 TRACE("Not compressed!\n");
243 dwSize = lpbi->biSize + num_colours(lpbi)*sizeof(RGBQUAD);
244 whdd->lpbiOut = HeapAlloc(GetProcessHeap(), 0, dwSize);
245 memcpy(whdd->lpbiOut, lpbi, dwSize);
248 if (ret)
250 /*whdd->lpvbuf = HeapAlloc(GetProcessHeap(), 0, whdd->lpbiOut->biSizeImage);*/
252 whdd->hMemDC = CreateCompatibleDC(hdc);
253 TRACE("Creating: %ld, %p\n", whdd->lpbiOut->biSize, whdd->lpvbits);
254 whdd->hDib = CreateDIBSection(whdd->hMemDC, (BITMAPINFO *)whdd->lpbiOut, DIB_RGB_COLORS, &(whdd->lpvbits), 0, 0);
255 if (!whdd->hDib)
257 TRACE("Error: %ld\n", GetLastError());
259 TRACE("Created: %p,%p\n", whdd->hDib, whdd->lpvbits);
260 whdd->hOldDib = SelectObject(whdd->hMemDC, whdd->hDib);
263 if (ret)
265 whdd->hdc = hdc;
266 whdd->dxDst = dxDst;
267 whdd->dyDst = dyDst;
268 whdd->lpbi = HeapAlloc(GetProcessHeap(), 0, lpbi->biSize);
269 memcpy(whdd->lpbi, lpbi, lpbi->biSize);
270 whdd->dxSrc = dxSrc;
271 whdd->dySrc = dySrc;
272 whdd->begun = TRUE;
273 whdd->hpal = 0;
275 else
277 if (whdd->hic)
278 ICClose(whdd->hic);
279 HeapFree(GetProcessHeap(), 0, whdd->lpbiOut);
280 whdd->lpbiOut = NULL;
283 return ret;
286 /**********************************************************************
287 * DrawDibDraw [MSVFW32.@]
289 BOOL VFWAPI DrawDibDraw(HDRAWDIB hdd, HDC hdc,
290 INT xDst, INT yDst, INT dxDst, INT dyDst,
291 LPBITMAPINFOHEADER lpbi,
292 LPVOID lpBits,
293 INT xSrc, INT ySrc, INT dxSrc, INT dySrc,
294 UINT wFlags)
296 WINE_HDD *whdd;
297 BOOL ret = TRUE;
299 TRACE("(%p,%p,%d,%d,%d,%d,%p,%p,%d,%d,%d,%d,0x%08lx)\n",
300 hdd, hdc, xDst, yDst, dxDst, dyDst, lpbi, lpBits, xSrc, ySrc, dxSrc, dySrc, (DWORD)wFlags);
302 whdd = MSVIDEO_GetHddPtr(hdd);
303 if (!whdd) return FALSE;
305 if (wFlags & ~(DDF_SAME_HDC | DDF_SAME_DRAW | DDF_NOTKEYFRAME | DDF_UPDATE | DDF_DONTDRAW | DDF_BACKGROUNDPAL))
306 FIXME("wFlags == 0x%08lx not handled\n", (DWORD)wFlags);
308 if (!lpBits)
310 /* Undocumented? */
311 lpBits = (LPSTR)lpbi + (WORD)(lpbi->biSize) + (WORD)(num_colours(lpbi)*sizeof(RGBQUAD));
315 #define CHANGED(x) (whdd->x != x)
317 if ((!whdd->begun) ||
318 (!(wFlags & DDF_SAME_HDC) && CHANGED(hdc)) ||
319 (!(wFlags & DDF_SAME_DRAW) && (CHANGED(lpbi) || CHANGED(dxSrc) || CHANGED(dySrc) || CHANGED(dxDst) || CHANGED(dyDst))))
321 TRACE("Something changed!\n");
322 ret = DrawDibBegin(hdd, hdc, dxDst, dyDst, lpbi, dxSrc, dySrc, 0);
325 #undef CHANGED
327 if ((dxDst == -1) && (dyDst == -1))
329 dxDst = dxSrc;
330 dyDst = dySrc;
333 if (!(wFlags & DDF_UPDATE))
335 /* biSizeImage may be set to 0 for BI_RGB (uncompressed) bitmaps */
336 if ((lpbi->biCompression == BI_RGB) && (lpbi->biSizeImage == 0))
337 lpbi->biSizeImage = ((lpbi->biWidth * lpbi->biBitCount + 31) / 32) * 4 * lpbi->biHeight;
339 if (lpbi->biCompression)
341 DWORD flags = 0;
343 TRACE("Compression == 0x%08lx\n", lpbi->biCompression);
345 if (wFlags & DDF_NOTKEYFRAME)
346 flags |= ICDECOMPRESS_NOTKEYFRAME;
348 ICDecompress(whdd->hic, flags, lpbi, lpBits, whdd->lpbiOut, whdd->lpvbits);
350 else
352 memcpy(whdd->lpvbits, lpBits, lpbi->biSizeImage);
355 if (!(wFlags & DDF_DONTDRAW) && whdd->hpal)
357 if ((wFlags & DDF_BACKGROUNDPAL) && ! (wFlags & DDF_SAME_HDC))
358 SelectPalette(hdc, whdd->hpal, TRUE);
359 else
360 SelectPalette(hdc, whdd->hpal, FALSE);
363 if (!(StretchBlt(whdd->hdc, xDst, yDst, dxDst, dyDst, whdd->hMemDC, xSrc, ySrc, dxSrc, dySrc, SRCCOPY)))
364 ret = FALSE;
366 return ret;
369 /*************************************************************************
370 * DrawDibStart [MSVFW32.@]
372 BOOL VFWAPI DrawDibStart(HDRAWDIB hdd, DWORD rate) {
373 FIXME("(%p, %ld), stub\n", hdd, rate);
374 return TRUE;
377 /*************************************************************************
378 * DrawDibStop [MSVFW32.@]
380 BOOL VFWAPI DrawDibStop(HDRAWDIB hdd) {
381 FIXME("(%p), stub\n", hdd);
382 return TRUE;
385 /***********************************************************************
386 * DrawDibChangePalette [MSVFW32.@]
388 BOOL VFWAPI DrawDibChangePalette(HDRAWDIB hdd, int iStart, int iLen, LPPALETTEENTRY lppe)
390 FIXME("(%p, 0x%08x, 0x%08x, %p), stub\n", hdd, iStart, iLen, lppe);
391 return TRUE;
394 /***********************************************************************
395 * DrawDibSetPalette [MSVFW32.@]
397 BOOL VFWAPI DrawDibSetPalette(HDRAWDIB hdd, HPALETTE hpal)
399 WINE_HDD *whdd;
401 TRACE("(%p, %p)\n", hdd, hpal);
403 whdd = MSVIDEO_GetHddPtr(hdd);
404 if (!whdd) return FALSE;
406 whdd->hpal = hpal;
408 if (whdd->begun)
410 SelectPalette(whdd->hdc, hpal, 0);
411 RealizePalette(whdd->hdc);
414 return TRUE;
417 /***********************************************************************
418 * DrawDibGetBuffer [MSVFW32.@]
420 LPVOID VFWAPI DrawDibGetBuffer(HDRAWDIB hdd, LPBITMAPINFOHEADER lpbi, DWORD dwSize, DWORD dwFlags)
422 FIXME("(%p, %p, 0x%08lx, 0x%08lx), stub\n", hdd, lpbi, dwSize, dwFlags);
423 return NULL;
426 /***********************************************************************
427 * DrawDibGetPalette [MSVFW32.@]
429 HPALETTE VFWAPI DrawDibGetPalette(HDRAWDIB hdd)
431 WINE_HDD *whdd;
433 TRACE("(%p)\n", hdd);
435 whdd = MSVIDEO_GetHddPtr(hdd);
436 if (!whdd) return FALSE;
438 return whdd->hpal;
441 /***********************************************************************
442 * DrawDibRealize [MSVFW32.@]
444 UINT VFWAPI DrawDibRealize(HDRAWDIB hdd, HDC hdc, BOOL fBackground)
446 WINE_HDD *whdd;
447 HPALETTE oldPal;
448 UINT ret = 0;
450 FIXME("(%p, %p, %d), stub\n", hdd, hdc, fBackground);
452 whdd = MSVIDEO_GetHddPtr(hdd);
453 if (!whdd) return FALSE;
455 if (!whdd || !(whdd->begun))
457 ret = 0;
458 goto out;
461 if (!whdd->hpal)
462 whdd->hpal = CreateHalftonePalette(hdc);
464 oldPal = SelectPalette(hdc, whdd->hpal, fBackground);
465 ret = RealizePalette(hdc);
467 out:
468 TRACE("=> %u\n", ret);
469 return ret;
472 /***********************************************************************
473 * DrawDibTime [MSVFW32.@]
475 BOOL VFWAPI DrawDibTime(HDRAWDIB hdd, LPDRAWDIBTIME lpddtime)
477 FIXME("(%p, %p) stub\n", hdd, lpddtime);
478 return FALSE;
481 /***********************************************************************
482 * DrawDibProfileDisplay [MSVFW32.@]
484 DWORD VFWAPI DrawDibProfileDisplay(LPBITMAPINFOHEADER lpbi)
486 FIXME("(%p) stub\n", lpbi);
488 return PD_CAN_DRAW_DIB;