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