[YAROTOWS] Reintegrate the branch. For a brighter future.
[reactos.git] / reactos / dll / win32 / gdi32 / objects / bitmap.c
1 #include "precomp.h"
2
3 #define NDEBUG
4 #include <debug.h>
5
6 /*
7 * Return the full scan size for a bitmap.
8 *
9 * Based on Wine, Utils.c and Windows Graphics Prog pg 595, SDK amvideo.h.
10 */
11 UINT
12 FASTCALL
13 DIB_BitmapMaxBitsSize( PBITMAPINFO Info, UINT ScanLines )
14 {
15 UINT MaxBits = 0;
16
17 if (!Info) return 0;
18
19 if (Info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
20 {
21 PBITMAPCOREHEADER Core = (PBITMAPCOREHEADER)Info;
22 MaxBits = Core->bcBitCount * Core->bcPlanes * Core->bcWidth;
23 }
24 else /* assume BITMAPINFOHEADER */
25 {
26 if ((Info->bmiHeader.biCompression) && (Info->bmiHeader.biCompression != BI_BITFIELDS))
27 return Info->bmiHeader.biSizeImage;
28 // Planes are over looked by Yuan. I guess assumed always 1.
29 MaxBits = Info->bmiHeader.biBitCount * Info->bmiHeader.biPlanes * Info->bmiHeader.biWidth;
30 }
31 MaxBits = ((MaxBits + 31) & ~31 ) / 8; // From Yuan, ScanLineSize = (Width * bitcount + 31)/32
32 return (MaxBits * ScanLines); // ret the full Size.
33 }
34
35 UINT
36 FASTCALL
37 DIB_BitmapBitsSize( CONST BITMAPINFO* Info )
38 {
39 UINT Ret;
40
41 if (!Info) return 0;
42
43 if ( Info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
44 {
45 PBITMAPCOREHEADER Core = (PBITMAPCOREHEADER)Info;
46 Ret = Core->bcHeight *
47 ((Core->bcWidth * Core->bcPlanes * Core->bcBitCount + 31) & ~31 ) / 8;
48 }
49 else /* assume BITMAPINFOHEADER */
50 {
51 if ((Info->bmiHeader.biCompression) &&
52 (Info->bmiHeader.biCompression != BI_BITFIELDS))
53 return Info->bmiHeader.biSizeImage;
54 // Make Height positive always....
55 Ret = abs(Info->bmiHeader.biHeight) *
56 ((Info->bmiHeader.biWidth * Info->bmiHeader.biPlanes * Info->bmiHeader.biBitCount + 31) & ~31 ) / 8;
57 }
58 return Ret;
59 }
60
61
62 /*
63 * DIB_GetBitmapInfo is complete copy of wine cvs 2/9-2006
64 * from file dib.c from gdi32.dll or orginal version
65 * did not calc the info right for some headers.
66 */
67 INT
68 WINAPI
69 DIB_GetBitmapInfo(const BITMAPINFOHEADER *header,
70 PLONG width,
71 PLONG height,
72 PWORD planes,
73 PWORD bpp,
74 PLONG compr,
75 PLONG size )
76 {
77 if (header->biSize == sizeof(BITMAPCOREHEADER))
78 {
79 BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)header;
80 *width = core->bcWidth;
81 *height = core->bcHeight;
82 *planes = core->bcPlanes;
83 *bpp = core->bcBitCount;
84 *compr = 0;
85 *size = 0;
86 return 0;
87 }
88
89 if (header->biSize == sizeof(BITMAPINFOHEADER))
90 {
91 *width = header->biWidth;
92 *height = header->biHeight;
93 *planes = header->biPlanes;
94 *bpp = header->biBitCount;
95 *compr = header->biCompression;
96 *size = header->biSizeImage;
97 return 1;
98 }
99
100 if (header->biSize == sizeof(BITMAPV4HEADER))
101 {
102 BITMAPV4HEADER *v4hdr = (BITMAPV4HEADER *)header;
103 *width = v4hdr->bV4Width;
104 *height = v4hdr->bV4Height;
105 *planes = v4hdr->bV4Planes;
106 *bpp = v4hdr->bV4BitCount;
107 *compr = v4hdr->bV4V4Compression;
108 *size = v4hdr->bV4SizeImage;
109 return 4;
110 }
111
112 if (header->biSize == sizeof(BITMAPV5HEADER))
113 {
114 BITMAPV5HEADER *v5hdr = (BITMAPV5HEADER *)header;
115 *width = v5hdr->bV5Width;
116 *height = v5hdr->bV5Height;
117 *planes = v5hdr->bV5Planes;
118 *bpp = v5hdr->bV5BitCount;
119 *compr = v5hdr->bV5Compression;
120 *size = v5hdr->bV5SizeImage;
121 return 5;
122 }
123 DPRINT("(%ld): wrong size for header\n", header->biSize );
124 return -1;
125 }
126
127 /*
128 * @implemented
129 */
130 int
131 WINAPI
132 GdiGetBitmapBitsSize(BITMAPINFO *lpbmi)
133 {
134 int retSize;
135
136 if (lpbmi->bmiHeader.biSize == FIELD_OFFSET(BITMAPINFOHEADER, biPlanes))
137 {
138 /* Calc the bits Size and align it*/
139 retSize = HIWORD(lpbmi->bmiHeader.biWidth) * ((LOWORD(lpbmi->bmiHeader.biWidth) *
140 LOWORD(lpbmi->bmiHeader.biHeight) * HIWORD(lpbmi->bmiHeader.biHeight) + 31)
141 & -32) / 8;
142 }
143 else
144 {
145 if ( (lpbmi->bmiHeader.biCompression == BI_BITFIELDS) ||
146 (lpbmi->bmiHeader.biCompression == BI_RGB))
147 {
148 if (lpbmi->bmiHeader.biHeight >=0 )
149 {
150 /* Calc the bits Size and align it*/
151 retSize = lpbmi->bmiHeader.biHeight * ((lpbmi->bmiHeader.biWidth *
152 lpbmi->bmiHeader.biPlanes * lpbmi->bmiHeader.biBitCount + 31) & -32) / 8;
153 }
154 else
155 {
156 /* Make height postiive if it negitve then calc the bits Size and align it*/
157 retSize = (-lpbmi->bmiHeader.biHeight) * ((lpbmi->bmiHeader.biWidth *
158 lpbmi->bmiHeader.biPlanes * lpbmi->bmiHeader.biBitCount + 31) & -32) / 8;
159 }
160 }
161 else
162 {
163 retSize = lpbmi->bmiHeader.biSizeImage;
164 }
165 }
166 return retSize;
167 }
168
169 /*
170 * @implemented
171 */
172 HBITMAP WINAPI
173 CreateDIBSection(
174 HDC hDC,
175 CONST BITMAPINFO *BitmapInfo,
176 UINT Usage,
177 VOID **Bits,
178 HANDLE hSection,
179 DWORD dwOffset)
180 {
181 PBITMAPINFO pConvertedInfo;
182 UINT ConvertedInfoSize;
183 HBITMAP hBitmap = NULL;
184 PVOID bmBits = NULL;
185
186 pConvertedInfo = ConvertBitmapInfo(BitmapInfo, Usage,
187 &ConvertedInfoSize, FALSE);
188 if (pConvertedInfo)
189 { // Verify header due to converted may == info.
190 if ( pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) )
191 {
192 if ( pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
193 pConvertedInfo->bmiHeader.biCompression == BI_PNG )
194 {
195 SetLastError(ERROR_INVALID_PARAMETER);
196 return NULL;
197 }
198 }
199 bmBits = Bits;
200 hBitmap = NtGdiCreateDIBSection( hDC,
201 hSection,
202 dwOffset,
203 pConvertedInfo,
204 Usage,
205 0,
206 0,
207 0,
208 &bmBits);
209 if (BitmapInfo != pConvertedInfo)
210 RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo);
211
212 if (!hBitmap)
213 {
214 bmBits = NULL;
215 }
216 }
217
218 if (Bits) *Bits = bmBits;
219
220 return hBitmap;
221 }
222
223
224 /*
225 * @implemented
226 */
227 BOOL
228 WINAPI
229 BitBlt(HDC hdcDest, /* handle to destination DC */
230 int nXOriginDest, /* x-coord of destination upper-left corner */
231 int nYOriginDest, /* y-coord of destination upper-left corner */
232 int nWidthDest, /* width of destination rectangle */
233 int nHeightDest, /* height of destination rectangle */
234 HDC hdcSrc, /* handle to source DC */
235 int nXSrc, /* x-coordinate of source upper-left corner */
236 int nYSrc, /* y-coordinate of source upper-left corner */
237 DWORD dwRop) /* raster operation code */
238 {
239 /* use patBlt for no source blt Like windows does */
240 if (!ROP_USES_SOURCE(dwRop))
241 {
242 return PatBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, dwRop);
243 }
244
245 return NtGdiBitBlt(hdcDest,
246 nXOriginDest,
247 nYOriginDest,
248 nWidthDest,
249 nHeightDest,
250 hdcSrc,
251 nXSrc,
252 nYSrc,
253 dwRop,
254 0,
255 0);
256 }
257
258 /*
259 * @implemented
260 */
261 BOOL WINAPI
262 StretchBlt(
263 HDC hdcDest, /* handle to destination DC */
264 int nXOriginDest, /* x-coord of destination upper-left corner */
265 int nYOriginDest, /* y-coord of destination upper-left corner */
266 int nWidthDest, /* width of destination rectangle */
267 int nHeightDest, /* height of destination rectangle */
268 HDC hdcSrc, /* handle to source DC */
269 int nXOriginSrc, /* x-coord of source upper-left corner */
270 int nYOriginSrc, /* y-coord of source upper-left corner */
271 int nWidthSrc, /* width of source rectangle */
272 int nHeightSrc, /* height of source rectangle */
273 DWORD dwRop) /* raster operation code */
274
275 {
276 if ((nWidthDest != nWidthSrc) || (nHeightDest != nHeightSrc))
277 {
278 return NtGdiStretchBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest,
279 nHeightDest, hdcSrc, nXOriginSrc, nYOriginSrc,
280 nWidthSrc, nHeightSrc, dwRop, 0);
281 }
282
283 return NtGdiBitBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest,
284 nHeightDest, hdcSrc, nXOriginSrc, nYOriginSrc, dwRop, 0, 0);
285 }
286
287 /*
288 * @unimplemented
289 */
290 HBITMAP WINAPI
291 CreateBitmap(INT Width,
292 INT Height,
293 UINT Planes,
294 UINT BitsPixel,
295 CONST VOID* pUnsafeBits)
296 {
297 /* FIXME some part should be done in user mode */
298 if (Width && Height)
299 {
300 return NtGdiCreateBitmap(Width, Height, Planes, BitsPixel, (LPBYTE) pUnsafeBits);
301 }
302 else
303 {
304 /* Return 1x1 bitmap */
305 return GetStockObject(DEFAULT_BITMAP);
306 }
307 }
308
309 /*
310 * @implemented
311 */
312 HBITMAP WINAPI
313 CreateBitmapIndirect(const BITMAP *pbm)
314 {
315 HBITMAP bitmap = NULL;
316
317 /* Note windows xp/2003 does not check if pbm is NULL or not */
318 if ( (pbm->bmWidthBytes != 0) &&
319 (!(pbm->bmWidthBytes & 1)) )
320
321 {
322
323 bitmap = CreateBitmap(pbm->bmWidth,
324 pbm->bmHeight,
325 pbm->bmPlanes,
326 pbm->bmBitsPixel,
327 pbm->bmBits);
328 }
329 else
330 {
331 SetLastError(ERROR_INVALID_PARAMETER);
332 }
333
334 return bitmap;
335 }
336
337 HBITMAP WINAPI
338 CreateDiscardableBitmap(
339 HDC hDC,
340 INT Width,
341 INT Height)
342 {
343 return CreateCompatibleBitmap(hDC, Width, Height);
344 }
345
346
347 HBITMAP WINAPI
348 CreateCompatibleBitmap(
349 HDC hDC,
350 INT Width,
351 INT Height)
352 {
353 PDC_ATTR pDc_Attr;
354 HBITMAP hBmp = NULL;
355 DIBSECTION dibs;
356
357 if (!GdiGetHandleUserData(hDC, GDI_OBJECT_TYPE_DC, (PVOID)&pDc_Attr))
358 return NULL;
359
360 if ( !Width || !Height )
361 return GetStockObject(DEFAULT_BITMAP);
362
363 if (!(pDc_Attr->ulDirty_ & DC_DIBSECTION))
364 {
365 return NtGdiCreateCompatibleBitmap(hDC, Width, Height);
366 }
367
368 hBmp = NtGdiGetDCObject(hDC, GDI_OBJECT_TYPE_BITMAP);
369
370 if ( GetObjectA(hBmp, sizeof(DIBSECTION), &dibs) != sizeof(DIBSECTION) )
371 return NULL;
372
373 if ( dibs.dsBm.bmBitsPixel <= 8 )
374 GetDIBColorTable(hDC, 0, 256, (RGBQUAD *)&dibs.dsBitfields);
375
376 dibs.dsBmih.biWidth = Width;
377 dibs.dsBmih.biHeight = Height;
378
379 return CreateDIBSection(hDC, (CONST BITMAPINFO *)&dibs.dsBmih, 0, NULL, NULL, 0);
380 }
381
382
383 INT
384 WINAPI
385 GetDIBits(
386 HDC hDC,
387 HBITMAP hbmp,
388 UINT uStartScan,
389 UINT cScanLines,
390 LPVOID lpvBits,
391 LPBITMAPINFO lpbmi,
392 UINT uUsage)
393 {
394 INT Ret = 0;
395 UINT cjBmpScanSize;
396 PVOID pvSafeBits = lpvBits;
397
398 if (!hDC || !GdiIsHandleValid((HGDIOBJ)hDC))
399 {
400 GdiSetLastError(ERROR_INVALID_PARAMETER);
401 return Ret;
402 }
403
404 cjBmpScanSize = DIB_BitmapMaxBitsSize(lpbmi, cScanLines);
405
406 if ( lpvBits )
407 {
408 if ( lpbmi )
409 {
410 if ( lpbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) )
411 {
412 if ( lpbmi->bmiHeader.biCompression == BI_JPEG ||
413 lpbmi->bmiHeader.biCompression == BI_PNG )
414 {
415 SetLastError(ERROR_INVALID_PARAMETER);
416 return Ret;
417 }
418 }
419 }
420
421 if ((ULONG)lpvBits & (sizeof(DWORD) - 1))
422 {
423 pvSafeBits = RtlAllocateHeap(RtlGetProcessHeap(), 0, cjBmpScanSize);
424 if (!pvSafeBits)
425 return Ret;
426 }
427 }
428
429 Ret = NtGdiGetDIBitsInternal(hDC,
430 hbmp,
431 uStartScan,
432 cScanLines,
433 pvSafeBits,
434 lpbmi,
435 uUsage,
436 cjBmpScanSize,
437 0);
438 if (lpvBits != pvSafeBits)
439 {
440 if (Ret)
441 {
442 RtlCopyMemory(lpvBits, pvSafeBits, cjBmpScanSize);
443 }
444 RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits);
445 }
446 return Ret;
447 }
448
449 /*
450 * @implemented
451 */
452 HBITMAP
453 WINAPI
454 CreateDIBitmap( HDC hDC,
455 const BITMAPINFOHEADER *Header,
456 DWORD Init,
457 LPCVOID Bits,
458 const BITMAPINFO *Data,
459 UINT ColorUse)
460 {
461 LONG width, height, compr, dibsize;
462 WORD planes, bpp;
463 // PDC_ATTR pDc_Attr;
464 UINT InfoSize = 0;
465 UINT cjBmpScanSize = 0;
466 HBITMAP hBmp;
467 NTSTATUS Status = STATUS_SUCCESS;
468
469 if (!Header) return 0;
470
471 if (DIB_GetBitmapInfo(Header, &width, &height, &planes, &bpp, &compr, &dibsize) == -1)
472 {
473 GdiSetLastError(ERROR_INVALID_PARAMETER);
474 return NULL;
475 }
476
477 // For Icm support.
478 // GdiGetHandleUserData(hdc, GDI_OBJECT_TYPE_DC, (PVOID)&pDc_Attr))
479
480 if(Data)
481 {
482 _SEH2_TRY
483 {
484 cjBmpScanSize = DIB_BitmapBitsSize(Data);
485 CalculateColorTableSize(&Data->bmiHeader, &ColorUse, &InfoSize);
486 InfoSize += Data->bmiHeader.biSize;
487 }
488 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
489 {
490 Status = _SEH2_GetExceptionCode();
491 }
492 _SEH2_END
493 }
494
495 if(!NT_SUCCESS(Status))
496 {
497 GdiSetLastError(ERROR_INVALID_PARAMETER);
498 return NULL;
499 }
500
501 DPRINT("pBMI %x, Size bpp %d, dibsize %d, Conv %d, BSS %d\n", Data,bpp,dibsize,InfoSize,cjBmpScanSize);
502
503 if ( !width || !height )
504 hBmp = GetStockObject(DEFAULT_BITMAP);
505 else
506 {
507 hBmp = NtGdiCreateDIBitmapInternal(hDC,
508 width,
509 height,
510 Init,
511 (LPBYTE)Bits,
512 (LPBITMAPINFO)Data,
513 ColorUse,
514 InfoSize,
515 cjBmpScanSize,
516 0,
517 0);
518 }
519 return hBmp;
520 }
521
522 #if 0 // FIXME!!! This is a victim of the Win32k Initialization BUG!!!!!
523 /*
524 * @implemented
525 */
526 INT
527 WINAPI
528 SetDIBits(HDC hDC,
529 HBITMAP hBitmap,
530 UINT uStartScan,
531 UINT cScanLines,
532 CONST VOID *lpvBits,
533 CONST BITMAPINFO *lpbmi,
534 UINT fuColorUse)
535 {
536 HDC hDCc, SavehDC, nhDC;
537 DWORD dwWidth, dwHeight;
538 HGDIOBJ hOldBitmap;
539 HPALETTE hPal = NULL;
540 INT LinesCopied = 0;
541 BOOL newDC = FALSE;
542
543 if ( !lpvBits || (GDI_HANDLE_GET_TYPE(hBitmap) != GDI_OBJECT_TYPE_BITMAP) )
544 return 0;
545
546 if ( lpbmi )
547 {
548 if ( lpbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) )
549 {
550 if ( lpbmi->bmiHeader.biCompression == BI_JPEG || lpbmi->bmiHeader.biCompression == BI_PNG )
551 {
552 SetLastError(ERROR_INVALID_PARAMETER);
553 return 0;
554 }
555 }
556 }
557
558 hDCc = NtGdiGetDCforBitmap(hBitmap);
559 SavehDC = hDCc;
560 if ( !hDCc )
561 {
562 nhDC = CreateCompatibleDC(hDC);
563 if ( !nhDC ) return 0;
564 newDC = TRUE;
565 SavehDC = nhDC;
566 }
567 else if ( !SaveDC(hDCc) )
568 return 0;
569
570 hOldBitmap = SelectObject(SavehDC, hBitmap);
571
572 if ( hOldBitmap )
573 {
574 if ( hDC )
575 hPal = SelectPalette(SavehDC, (HPALETTE)GetDCObject(hDC, GDI_OBJECT_TYPE_PALETTE), FALSE);
576
577 if ( lpbmi->bmiHeader.biSize < sizeof(BITMAPINFOHEADER))
578 {
579 PBITMAPCOREINFO pbci = (PBITMAPCOREINFO) lpbmi;
580 dwWidth = pbci->bmciHeader.bcWidth;
581 dwHeight = pbci->bmciHeader.bcHeight;
582 }
583 else
584 {
585 dwWidth = lpbmi->bmiHeader.biWidth;
586 dwHeight = abs(lpbmi->bmiHeader.biHeight);
587 }
588
589 LinesCopied = SetDIBitsToDevice(SavehDC,
590 0,
591 0,
592 dwWidth,
593 dwHeight,
594 0,
595 0,
596 uStartScan,
597 cScanLines,
598 (void *)lpvBits,
599 (LPBITMAPINFO)lpbmi,
600 fuColorUse);
601
602 if ( hDC ) SelectPalette(SavehDC, hPal, FALSE);
603
604 SelectObject(SavehDC, hOldBitmap);
605 }
606
607 if ( newDC )
608 DeleteDC(SavehDC);
609 else
610 RestoreDC(SavehDC, -1);
611
612 return LinesCopied;
613 }
614 #endif
615
616 INT
617 WINAPI
618 SetDIBits(HDC hdc,
619 HBITMAP hbmp,
620 UINT uStartScan,
621 UINT cScanLines,
622 CONST VOID *lpvBits,
623 CONST BITMAPINFO *lpbmi,
624 UINT fuColorUse)
625 {
626 PBITMAPINFO pConvertedInfo;
627 UINT ConvertedInfoSize;
628 INT LinesCopied = 0;
629 UINT cjBmpScanSize = 0;
630 PVOID pvSafeBits = (PVOID)lpvBits;
631
632 // This needs to be almost the sames as SetDIBitsToDevice
633
634 if ( !cScanLines || !lpbmi || !lpvBits || (GDI_HANDLE_GET_TYPE(hbmp) != GDI_OBJECT_TYPE_BITMAP))
635 return 0;
636
637 if ( fuColorUse && fuColorUse != DIB_PAL_COLORS && fuColorUse != DIB_PAL_COLORS+1 )
638 return 0;
639
640 pConvertedInfo = ConvertBitmapInfo(lpbmi, fuColorUse,
641 &ConvertedInfoSize, FALSE);
642 if (!pConvertedInfo)
643 return 0;
644
645 cjBmpScanSize = DIB_BitmapMaxBitsSize((LPBITMAPINFO)lpbmi, cScanLines);
646
647 if ( lpvBits )
648 {
649 pvSafeBits = RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize);
650 if (pvSafeBits)
651 RtlCopyMemory( pvSafeBits, lpvBits, cjBmpScanSize);
652 }
653
654 LinesCopied = NtGdiSetDIBits( hdc,
655 hbmp,
656 uStartScan,
657 cScanLines,
658 pvSafeBits,
659 pConvertedInfo,
660 fuColorUse);
661
662 if ( lpvBits != pvSafeBits)
663 RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits);
664 if (lpbmi != pConvertedInfo)
665 RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo);
666 return LinesCopied;
667 }
668
669 /*
670 * @implemented
671 *
672 */
673 INT
674 WINAPI
675 SetDIBitsToDevice(
676 HDC hdc,
677 int XDest,
678 int YDest,
679 DWORD Width,
680 DWORD Height,
681 int XSrc,
682 int YSrc,
683 UINT StartScan,
684 UINT ScanLines,
685 CONST VOID *Bits,
686 CONST BITMAPINFO *lpbmi,
687 UINT ColorUse)
688 {
689 PDC_ATTR pDc_Attr;
690 PBITMAPINFO pConvertedInfo;
691 UINT ConvertedInfoSize;
692 INT LinesCopied = 0;
693 UINT cjBmpScanSize = 0;
694 PVOID pvSafeBits = (PVOID)Bits;
695
696 if ( !ScanLines || !lpbmi || !Bits )
697 return 0;
698
699 if ( ColorUse && ColorUse != DIB_PAL_COLORS && ColorUse != DIB_PAL_COLORS+1 )
700 return 0;
701
702 pConvertedInfo = ConvertBitmapInfo(lpbmi, ColorUse,
703 &ConvertedInfoSize, FALSE);
704 if (!pConvertedInfo)
705 return 0;
706
707 #if 0
708 // Handle something other than a normal dc object.
709 if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC)
710 {
711 if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC)
712 return MFDRV_SetDIBitsToDevice( hdc,
713 XDest,
714 YDest,
715 Width,
716 Height,
717 XSrc,
718 YSrc,
719 StartScan,
720 ScanLines,
721 Bits,
722 lpbmi,
723 ColorUse);
724 else
725 {
726 PLDC pLDC = GdiGetLDC(hdc);
727 if ( !pLDC )
728 {
729 SetLastError(ERROR_INVALID_HANDLE);
730 return 0;
731 }
732 if (pLDC->iType == LDC_EMFLDC)
733 {
734 return EMFDRV_SetDIBitsToDevice(hdc,
735 XDest,
736 YDest,
737 Width,
738 Height,
739 XSrc,
740 YSrc,
741 StartScan,
742 ScanLines,
743 Bits,
744 lpbmi,
745 ColorUse);
746 }
747 return 0;
748 }
749 }
750 #endif
751 cjBmpScanSize = DIB_BitmapMaxBitsSize((LPBITMAPINFO)lpbmi, ScanLines);
752
753 if ( Bits )
754 {
755 pvSafeBits = RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize);
756 if (pvSafeBits)
757 RtlCopyMemory( pvSafeBits, Bits, cjBmpScanSize);
758 }
759
760 if (!GdiGetHandleUserData(hdc, GDI_OBJECT_TYPE_DC, (PVOID)&pDc_Attr))
761 {
762 SetLastError(ERROR_INVALID_PARAMETER);
763 return 0;
764 }
765 /*
766 if ( !pDc_Attr ||
767 ((pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
768 (pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
769 pConvertedInfo->bmiHeader.biCompression == BI_PNG )) )*/
770 {
771 LinesCopied = NtGdiSetDIBitsToDeviceInternal( hdc,
772 XDest,
773 YDest,
774 Width,
775 Height,
776 XSrc,
777 YSrc,
778 StartScan,
779 ScanLines,
780 (LPBYTE)pvSafeBits,
781 (LPBITMAPINFO)pConvertedInfo,
782 ColorUse,
783 cjBmpScanSize,
784 ConvertedInfoSize,
785 TRUE,
786 NULL);
787 }
788 if ( Bits != pvSafeBits)
789 RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits);
790 if (lpbmi != pConvertedInfo)
791 RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo);
792
793 return LinesCopied;
794 }
795
796
797 /*
798 * @unimplemented
799 */
800 int
801 WINAPI
802 StretchDIBits(HDC hdc,
803 int XDest,
804 int YDest,
805 int nDestWidth,
806 int nDestHeight,
807 int XSrc,
808 int YSrc,
809 int nSrcWidth,
810 int nSrcHeight,
811 CONST VOID *lpBits,
812 CONST BITMAPINFO *lpBitsInfo,
813 UINT iUsage,
814 DWORD dwRop)
815
816 {
817 PDC_ATTR pDc_Attr;
818 PBITMAPINFO pConvertedInfo = NULL;
819 UINT ConvertedInfoSize = 0;
820 INT LinesCopied = 0;
821 UINT cjBmpScanSize = 0;
822 PVOID pvSafeBits = NULL;
823 BOOL Hit = FALSE;
824
825 DPRINT("StretchDIBits %x : %x : %d\n", lpBits, lpBitsInfo, iUsage);
826 #if 0
827 // Handle something other than a normal dc object.
828 if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC)
829 {
830 if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC)
831 return MFDRV_StretchBlt( hdc,
832 XDest,
833 YDest,
834 nDestWidth,
835 nDestHeight,
836 XSrc,
837 YSrc,
838 nSrcWidth,
839 nSrcHeight,
840 lpBits,
841 lpBitsInfo,
842 iUsage,
843 dwRop);
844 else
845 {
846 PLDC pLDC = GdiGetLDC(hdc);
847 if ( !pLDC )
848 {
849 SetLastError(ERROR_INVALID_HANDLE);
850 return 0;
851 }
852 if (pLDC->iType == LDC_EMFLDC)
853 {
854 return EMFDRV_StretchBlt(hdc,
855 XDest,
856 YDest,
857 nDestWidth,
858 nDestHeight,
859 XSrc,
860 YSrc,
861 nSrcWidth,
862 nSrcHeight,
863 lpBits,
864 lpBitsInfo,
865 iUsage,
866 dwRop);
867 }
868 return 0;
869 }
870 }
871 #endif
872 pConvertedInfo = ConvertBitmapInfo(lpBitsInfo, iUsage,
873 &ConvertedInfoSize, FALSE);
874 if (!pConvertedInfo)
875 {
876 return 0;
877 }
878
879 cjBmpScanSize = DIB_BitmapBitsSize((LPBITMAPINFO)pConvertedInfo);
880
881 if ( lpBits )
882 {
883 pvSafeBits = RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize);
884 if (pvSafeBits)
885 {
886 _SEH2_TRY
887 {
888 RtlCopyMemory( pvSafeBits, lpBits, cjBmpScanSize );
889 }
890 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
891 {
892 Hit = TRUE;
893 }
894 _SEH2_END
895
896 if (Hit)
897 {
898 // We don't die, we continue on with a allocated safe pointer to kernel
899 // space.....
900 DPRINT1("StretchDIBits fail to read BitMapInfo: %x or Bits: %x & Size: %d\n",pConvertedInfo,lpBits,cjBmpScanSize);
901 }
902 DPRINT("StretchDIBits Allocate Bits %d!!!\n", cjBmpScanSize);
903 }
904 }
905
906 if (!GdiGetHandleUserData(hdc, GDI_OBJECT_TYPE_DC, (PVOID)&pDc_Attr))
907 {
908 SetLastError(ERROR_INVALID_PARAMETER);
909 return 0;
910 }
911 /*
912 if ( !pDc_Attr ||
913 ((pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
914 (pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
915 pConvertedInfo->bmiHeader.biCompression == BI_PNG )) )*/
916 {
917 LinesCopied = NtGdiStretchDIBitsInternal( hdc,
918 XDest,
919 YDest,
920 nDestWidth,
921 nDestHeight,
922 XSrc,
923 YSrc,
924 nSrcWidth,
925 nSrcHeight,
926 pvSafeBits,
927 pConvertedInfo,
928 (DWORD)iUsage,
929 dwRop,
930 ConvertedInfoSize,
931 cjBmpScanSize,
932 NULL);
933 }
934 if ( pvSafeBits )
935 RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits);
936 if (lpBitsInfo != pConvertedInfo)
937 RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo);
938
939 return LinesCopied;
940 }
941