97cae2ceb1f4616088103edc0e38cfccae1b9897
[reactos.git] / 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;
465 UINT cjBmpScanSize;
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 _SEH2_TRY
481 {
482 cjBmpScanSize = DIB_BitmapBitsSize(Data);
483 CalculateColorTableSize(&Data->bmiHeader, &ColorUse, &InfoSize);
484 InfoSize += Data->bmiHeader.biSize;
485 }
486 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
487 {
488 Status = _SEH2_GetExceptionCode();
489 }
490 _SEH2_END
491
492 if(!NT_SUCCESS(Status))
493 {
494 GdiSetLastError(ERROR_INVALID_PARAMETER);
495 return NULL;
496 }
497
498 DPRINT("pBMI %x, Size bpp %d, dibsize %d, Conv %d, BSS %d\n", Data,bpp,dibsize,InfoSize,cjBmpScanSize);
499
500 if ( !width || !height )
501 hBmp = GetStockObject(DEFAULT_BITMAP);
502 else
503 {
504 hBmp = NtGdiCreateDIBitmapInternal(hDC,
505 width,
506 height,
507 Init,
508 (LPBYTE)Bits,
509 (LPBITMAPINFO)Data,
510 ColorUse,
511 InfoSize,
512 cjBmpScanSize,
513 0,
514 0);
515 }
516 return hBmp;
517 }
518
519 #if 0 // FIXME!!! This is a victim of the Win32k Initialization BUG!!!!!
520 /*
521 * @implemented
522 */
523 INT
524 WINAPI
525 SetDIBits(HDC hDC,
526 HBITMAP hBitmap,
527 UINT uStartScan,
528 UINT cScanLines,
529 CONST VOID *lpvBits,
530 CONST BITMAPINFO *lpbmi,
531 UINT fuColorUse)
532 {
533 HDC hDCc, SavehDC, nhDC;
534 DWORD dwWidth, dwHeight;
535 HGDIOBJ hOldBitmap;
536 HPALETTE hPal = NULL;
537 INT LinesCopied = 0;
538 BOOL newDC = FALSE;
539
540 if ( !lpvBits || (GDI_HANDLE_GET_TYPE(hBitmap) != GDI_OBJECT_TYPE_BITMAP) )
541 return 0;
542
543 if ( lpbmi )
544 {
545 if ( lpbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) )
546 {
547 if ( lpbmi->bmiHeader.biCompression == BI_JPEG || lpbmi->bmiHeader.biCompression == BI_PNG )
548 {
549 SetLastError(ERROR_INVALID_PARAMETER);
550 return 0;
551 }
552 }
553 }
554
555 hDCc = NtGdiGetDCforBitmap(hBitmap);
556 SavehDC = hDCc;
557 if ( !hDCc )
558 {
559 nhDC = CreateCompatibleDC(hDC);
560 if ( !nhDC ) return 0;
561 newDC = TRUE;
562 SavehDC = nhDC;
563 }
564 else if ( !SaveDC(hDCc) )
565 return 0;
566
567 hOldBitmap = SelectObject(SavehDC, hBitmap);
568
569 if ( hOldBitmap )
570 {
571 if ( hDC )
572 hPal = SelectPalette(SavehDC, (HPALETTE)GetDCObject(hDC, GDI_OBJECT_TYPE_PALETTE), FALSE);
573
574 if ( lpbmi->bmiHeader.biSize < sizeof(BITMAPINFOHEADER))
575 {
576 PBITMAPCOREINFO pbci = (PBITMAPCOREINFO) lpbmi;
577 dwWidth = pbci->bmciHeader.bcWidth;
578 dwHeight = pbci->bmciHeader.bcHeight;
579 }
580 else
581 {
582 dwWidth = lpbmi->bmiHeader.biWidth;
583 dwHeight = abs(lpbmi->bmiHeader.biHeight);
584 }
585
586 LinesCopied = SetDIBitsToDevice(SavehDC,
587 0,
588 0,
589 dwWidth,
590 dwHeight,
591 0,
592 0,
593 uStartScan,
594 cScanLines,
595 (void *)lpvBits,
596 (LPBITMAPINFO)lpbmi,
597 fuColorUse);
598
599 if ( hDC ) SelectPalette(SavehDC, hPal, FALSE);
600
601 SelectObject(SavehDC, hOldBitmap);
602 }
603
604 if ( newDC )
605 DeleteDC(SavehDC);
606 else
607 RestoreDC(SavehDC, -1);
608
609 return LinesCopied;
610 }
611 #endif
612
613 INT
614 WINAPI
615 SetDIBits(HDC hdc,
616 HBITMAP hbmp,
617 UINT uStartScan,
618 UINT cScanLines,
619 CONST VOID *lpvBits,
620 CONST BITMAPINFO *lpbmi,
621 UINT fuColorUse)
622 {
623 PBITMAPINFO pConvertedInfo;
624 UINT ConvertedInfoSize;
625 INT LinesCopied = 0;
626 UINT cjBmpScanSize = 0;
627 PVOID pvSafeBits = (PVOID)lpvBits;
628
629 // This needs to be almost the sames as SetDIBitsToDevice
630
631 if ( !cScanLines || !lpbmi || !lpvBits || (GDI_HANDLE_GET_TYPE(hbmp) != GDI_OBJECT_TYPE_BITMAP))
632 return 0;
633
634 if ( fuColorUse && fuColorUse != DIB_PAL_COLORS && fuColorUse != DIB_PAL_COLORS+1 )
635 return 0;
636
637 pConvertedInfo = ConvertBitmapInfo(lpbmi, fuColorUse,
638 &ConvertedInfoSize, FALSE);
639 if (!pConvertedInfo)
640 return 0;
641
642 cjBmpScanSize = DIB_BitmapMaxBitsSize((LPBITMAPINFO)lpbmi, cScanLines);
643
644 if ( lpvBits )
645 {
646 pvSafeBits = RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize);
647 if (pvSafeBits)
648 RtlCopyMemory( pvSafeBits, lpvBits, cjBmpScanSize);
649 }
650
651 LinesCopied = NtGdiSetDIBits( hdc,
652 hbmp,
653 uStartScan,
654 cScanLines,
655 pvSafeBits,
656 pConvertedInfo,
657 fuColorUse);
658
659 if ( lpvBits != pvSafeBits)
660 RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits);
661 if (lpbmi != pConvertedInfo)
662 RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo);
663 return LinesCopied;
664 }
665
666 /*
667 * @implemented
668 *
669 */
670 INT
671 WINAPI
672 SetDIBitsToDevice(
673 HDC hdc,
674 int XDest,
675 int YDest,
676 DWORD Width,
677 DWORD Height,
678 int XSrc,
679 int YSrc,
680 UINT StartScan,
681 UINT ScanLines,
682 CONST VOID *Bits,
683 CONST BITMAPINFO *lpbmi,
684 UINT ColorUse)
685 {
686 PDC_ATTR pDc_Attr;
687 PBITMAPINFO pConvertedInfo;
688 UINT ConvertedInfoSize;
689 INT LinesCopied = 0;
690 UINT cjBmpScanSize = 0;
691 PVOID pvSafeBits = (PVOID)Bits;
692
693 if ( !ScanLines || !lpbmi || !Bits )
694 return 0;
695
696 if ( ColorUse && ColorUse != DIB_PAL_COLORS && ColorUse != DIB_PAL_COLORS+1 )
697 return 0;
698
699 pConvertedInfo = ConvertBitmapInfo(lpbmi, ColorUse,
700 &ConvertedInfoSize, FALSE);
701 if (!pConvertedInfo)
702 return 0;
703
704 #if 0
705 // Handle something other than a normal dc object.
706 if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC)
707 {
708 if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC)
709 return MFDRV_SetDIBitsToDevice( hdc,
710 XDest,
711 YDest,
712 Width,
713 Height,
714 XSrc,
715 YSrc,
716 StartScan,
717 ScanLines,
718 Bits,
719 lpbmi,
720 ColorUse);
721 else
722 {
723 PLDC pLDC = GdiGetLDC(hdc);
724 if ( !pLDC )
725 {
726 SetLastError(ERROR_INVALID_HANDLE);
727 return 0;
728 }
729 if (pLDC->iType == LDC_EMFLDC)
730 {
731 return EMFDRV_SetDIBitsToDevice(hdc,
732 XDest,
733 YDest,
734 Width,
735 Height,
736 XSrc,
737 YSrc,
738 StartScan,
739 ScanLines,
740 Bits,
741 lpbmi,
742 ColorUse);
743 }
744 return 0;
745 }
746 }
747 #endif
748 cjBmpScanSize = DIB_BitmapMaxBitsSize((LPBITMAPINFO)lpbmi, ScanLines);
749
750 if ( Bits )
751 {
752 pvSafeBits = RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize);
753 if (pvSafeBits)
754 RtlCopyMemory( pvSafeBits, Bits, cjBmpScanSize);
755 }
756
757 if (!GdiGetHandleUserData(hdc, GDI_OBJECT_TYPE_DC, (PVOID)&pDc_Attr))
758 {
759 SetLastError(ERROR_INVALID_PARAMETER);
760 return 0;
761 }
762 /*
763 if ( !pDc_Attr ||
764 ((pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
765 (pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
766 pConvertedInfo->bmiHeader.biCompression == BI_PNG )) )*/
767 {
768 LinesCopied = NtGdiSetDIBitsToDeviceInternal( hdc,
769 XDest,
770 YDest,
771 Width,
772 Height,
773 XSrc,
774 YSrc,
775 StartScan,
776 ScanLines,
777 (LPBYTE)pvSafeBits,
778 (LPBITMAPINFO)pConvertedInfo,
779 ColorUse,
780 cjBmpScanSize,
781 ConvertedInfoSize,
782 TRUE,
783 NULL);
784 }
785 if ( Bits != pvSafeBits)
786 RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits);
787 if (lpbmi != pConvertedInfo)
788 RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo);
789
790 return LinesCopied;
791 }
792
793
794 /*
795 * @unimplemented
796 */
797 int
798 WINAPI
799 StretchDIBits(HDC hdc,
800 int XDest,
801 int YDest,
802 int nDestWidth,
803 int nDestHeight,
804 int XSrc,
805 int YSrc,
806 int nSrcWidth,
807 int nSrcHeight,
808 CONST VOID *lpBits,
809 CONST BITMAPINFO *lpBitsInfo,
810 UINT iUsage,
811 DWORD dwRop)
812
813 {
814 PDC_ATTR pDc_Attr;
815 PBITMAPINFO pConvertedInfo = NULL;
816 UINT ConvertedInfoSize = 0;
817 INT LinesCopied = 0;
818 UINT cjBmpScanSize = 0;
819 PVOID pvSafeBits = NULL;
820 BOOL Hit = FALSE;
821
822 DPRINT("StretchDIBits %x : %x : %d\n", lpBits, lpBitsInfo, iUsage);
823 #if 0
824 // Handle something other than a normal dc object.
825 if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC)
826 {
827 if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC)
828 return MFDRV_StretchBlt( hdc,
829 XDest,
830 YDest,
831 nDestWidth,
832 nDestHeight,
833 XSrc,
834 YSrc,
835 nSrcWidth,
836 nSrcHeight,
837 lpBits,
838 lpBitsInfo,
839 iUsage,
840 dwRop);
841 else
842 {
843 PLDC pLDC = GdiGetLDC(hdc);
844 if ( !pLDC )
845 {
846 SetLastError(ERROR_INVALID_HANDLE);
847 return 0;
848 }
849 if (pLDC->iType == LDC_EMFLDC)
850 {
851 return EMFDRV_StretchBlt(hdc,
852 XDest,
853 YDest,
854 nDestWidth,
855 nDestHeight,
856 XSrc,
857 YSrc,
858 nSrcWidth,
859 nSrcHeight,
860 lpBits,
861 lpBitsInfo,
862 iUsage,
863 dwRop);
864 }
865 return 0;
866 }
867 }
868 #endif
869 if ( iUsage ) // Save time, we only look at non RGB.
870 {
871 pConvertedInfo = ConvertBitmapInfo(lpBitsInfo, iUsage,
872 &ConvertedInfoSize, FALSE);
873 if (!pConvertedInfo)
874 {
875 return 0;
876 }
877 }
878 else
879 pConvertedInfo = (PBITMAPINFO)lpBitsInfo;
880
881 cjBmpScanSize = DIB_BitmapBitsSize((LPBITMAPINFO)pConvertedInfo);
882
883 if ( lpBits )
884 {
885 pvSafeBits = RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize);
886 if (pvSafeBits)
887 {
888 _SEH2_TRY
889 {
890 RtlCopyMemory( pvSafeBits, lpBits, cjBmpScanSize );
891 }
892 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
893 {
894 Hit = TRUE;
895 }
896 _SEH2_END
897
898 if (Hit)
899 {
900 // We don't die, we continue on with a allocated safe pointer to kernel
901 // space.....
902 DPRINT1("StretchDIBits fail to read BitMapInfo: %x or Bits: %x & Size: %d\n",pConvertedInfo,lpBits,cjBmpScanSize);
903 }
904 DPRINT("StretchDIBits Allocate Bits %d!!!\n", cjBmpScanSize);
905 }
906 }
907
908 if (!GdiGetHandleUserData(hdc, GDI_OBJECT_TYPE_DC, (PVOID)&pDc_Attr))
909 {
910 SetLastError(ERROR_INVALID_PARAMETER);
911 return 0;
912 }
913 /*
914 if ( !pDc_Attr ||
915 ((pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
916 (pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
917 pConvertedInfo->bmiHeader.biCompression == BI_PNG )) )*/
918 {
919 LinesCopied = NtGdiStretchDIBitsInternal( hdc,
920 XDest,
921 YDest,
922 nDestWidth,
923 nDestHeight,
924 XSrc,
925 YSrc,
926 nSrcWidth,
927 nSrcHeight,
928 pvSafeBits,
929 pConvertedInfo,
930 (DWORD)iUsage,
931 dwRop,
932 ConvertedInfoSize,
933 cjBmpScanSize,
934 NULL);
935 }
936 if ( pvSafeBits )
937 RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits);
938 if (lpBitsInfo != pConvertedInfo)
939 RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo);
940
941 return LinesCopied;
942 }
943