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