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