9650f14504678958b0ea2488a2a8351a9f9a1fad
[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
78 if (header->biSize == sizeof(BITMAPCOREHEADER))
79 {
80 BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)header;
81 *width = core->bcWidth;
82 *height = core->bcHeight;
83 *planes = core->bcPlanes;
84 *bpp = core->bcBitCount;
85 *compr = 0;
86 *size = 0;
87 return 0;
88 }
89
90 if (header->biSize == sizeof(BITMAPINFOHEADER))
91 {
92 *width = header->biWidth;
93 *height = header->biHeight;
94 *planes = header->biPlanes;
95 *bpp = header->biBitCount;
96 *compr = header->biCompression;
97 *size = header->biSizeImage;
98 return 1;
99 }
100
101 if (header->biSize == sizeof(BITMAPV4HEADER))
102 {
103 BITMAPV4HEADER *v4hdr = (BITMAPV4HEADER *)header;
104 *width = v4hdr->bV4Width;
105 *height = v4hdr->bV4Height;
106 *planes = v4hdr->bV4Planes;
107 *bpp = v4hdr->bV4BitCount;
108 *compr = v4hdr->bV4V4Compression;
109 *size = v4hdr->bV4SizeImage;
110 return 4;
111 }
112
113 if (header->biSize == sizeof(BITMAPV5HEADER))
114 {
115 BITMAPV5HEADER *v5hdr = (BITMAPV5HEADER *)header;
116 *width = v5hdr->bV5Width;
117 *height = v5hdr->bV5Height;
118 *planes = v5hdr->bV5Planes;
119 *bpp = v5hdr->bV5BitCount;
120 *compr = v5hdr->bV5Compression;
121 *size = v5hdr->bV5SizeImage;
122 return 5;
123 }
124 DPRINT("(%ld): wrong size for header\n", header->biSize );
125 return -1;
126 }
127
128 /*
129 * @implemented
130 */
131 int
132 WINAPI
133 GdiGetBitmapBitsSize(BITMAPINFO *lpbmi)
134 {
135 int retSize;
136
137 if (lpbmi->bmiHeader.biSize == FIELD_OFFSET(BITMAPINFOHEADER, biPlanes))
138 {
139 /* Calc the bits Size and align it*/
140 retSize = HIWORD(lpbmi->bmiHeader.biWidth) * ((LOWORD(lpbmi->bmiHeader.biWidth) *
141 LOWORD(lpbmi->bmiHeader.biHeight) * HIWORD(lpbmi->bmiHeader.biHeight) + 31)
142 & -32) / 8;
143 }
144 else
145 {
146 if ( (lpbmi->bmiHeader.biCompression == BI_BITFIELDS) ||
147 (lpbmi->bmiHeader.biCompression == BI_RGB))
148 {
149 if (lpbmi->bmiHeader.biHeight >=0 )
150 {
151 /* Calc the bits Size and align it*/
152 retSize = lpbmi->bmiHeader.biHeight * ((lpbmi->bmiHeader.biWidth *
153 lpbmi->bmiHeader.biPlanes * lpbmi->bmiHeader.biBitCount + 31) & -32) / 8;
154 }
155 else
156 {
157 /* Make height postiive if it negitve then calc the bits Size and align it*/
158 retSize = (-lpbmi->bmiHeader.biHeight) * ((lpbmi->bmiHeader.biWidth *
159 lpbmi->bmiHeader.biPlanes * lpbmi->bmiHeader.biBitCount + 31) & -32) / 8;
160 }
161 }
162 else
163 {
164 retSize = lpbmi->bmiHeader.biSizeImage;
165 }
166 }
167 return retSize;
168 }
169
170 /*
171 * @implemented
172 */
173 HBITMAP WINAPI
174 CreateDIBSection(
175 HDC hDC,
176 CONST BITMAPINFO *BitmapInfo,
177 UINT Usage,
178 VOID **Bits,
179 HANDLE hSection,
180 DWORD dwOffset)
181 {
182 PBITMAPINFO pConvertedInfo;
183 UINT ConvertedInfoSize;
184 HBITMAP hBitmap = NULL;
185 PVOID bmBits = NULL;
186
187 pConvertedInfo = ConvertBitmapInfo(BitmapInfo, Usage,
188 &ConvertedInfoSize, FALSE);
189 if (pConvertedInfo)
190 { // Verify header due to converted may == info.
191 if ( pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) )
192 {
193 if ( pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
194 pConvertedInfo->bmiHeader.biCompression == BI_PNG )
195 {
196 SetLastError(ERROR_INVALID_PARAMETER);
197 return NULL;
198 }
199 }
200 bmBits = Bits;
201 hBitmap = NtGdiCreateDIBSection( hDC,
202 hSection,
203 dwOffset,
204 pConvertedInfo,
205 Usage,
206 0,
207 0,
208 0,
209 &bmBits);
210 if (BitmapInfo != pConvertedInfo)
211 RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo);
212
213 if (!hBitmap)
214 {
215 bmBits = NULL;
216 }
217 }
218
219 if (Bits) *Bits = bmBits;
220
221 return hBitmap;
222 }
223
224
225 /*
226 * @implemented
227 */
228 BOOL
229 WINAPI
230 BitBlt(HDC hdcDest, /* handle to destination DC */
231 int nXOriginDest, /* x-coord of destination upper-left corner */
232 int nYOriginDest, /* y-coord of destination upper-left corner */
233 int nWidthDest, /* width of destination rectangle */
234 int nHeightDest, /* height of destination rectangle */
235 HDC hdcSrc, /* handle to source DC */
236 int nXSrc, /* x-coordinate of source upper-left corner */
237 int nYSrc, /* y-coordinate of source upper-left corner */
238 DWORD dwRop) /* raster operation code */
239 {
240 /* use patBlt for no source blt Like windows does */
241 if (!ROP_USES_SOURCE(dwRop))
242 {
243 return PatBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, dwRop);
244 }
245
246 return NtGdiBitBlt(hdcDest,
247 nXOriginDest,
248 nYOriginDest,
249 nWidthDest,
250 nHeightDest,
251 hdcSrc,
252 nXSrc,
253 nYSrc,
254 dwRop,
255 0,
256 0);
257 }
258
259 /*
260 * @implemented
261 */
262 BOOL WINAPI
263 StretchBlt(
264 HDC hdcDest, /* handle to destination DC */
265 int nXOriginDest, /* x-coord of destination upper-left corner */
266 int nYOriginDest, /* y-coord of destination upper-left corner */
267 int nWidthDest, /* width of destination rectangle */
268 int nHeightDest, /* height of destination rectangle */
269 HDC hdcSrc, /* handle to source DC */
270 int nXOriginSrc, /* x-coord of source upper-left corner */
271 int nYOriginSrc, /* y-coord of source upper-left corner */
272 int nWidthSrc, /* width of source rectangle */
273 int nHeightSrc, /* height of source rectangle */
274 DWORD dwRop) /* raster operation code */
275
276 {
277 if ((nWidthDest != nWidthSrc) || (nHeightDest != nHeightSrc))
278 {
279 return NtGdiStretchBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest,
280 nHeightDest, hdcSrc, nXOriginSrc, nYOriginSrc,
281 nWidthSrc, nHeightSrc, dwRop, 0);
282 }
283
284 return NtGdiBitBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest,
285 nHeightDest, hdcSrc, nXOriginSrc, nYOriginSrc, dwRop, 0, 0);
286 }
287
288 /*
289 * @unimplemented
290 */
291 HBITMAP WINAPI
292 CreateBitmap(INT Width,
293 INT Height,
294 UINT Planes,
295 UINT BitsPixel,
296 PCVOID pUnsafeBits)
297 {
298 /* FIXME some part should be done in user mode */
299 if (Width && Height)
300 {
301 return NtGdiCreateBitmap(Width, Height, Planes, BitsPixel, (LPBYTE) pUnsafeBits);
302 }
303 else
304 {
305 /* Return 1x1 bitmap */
306 return GetStockObject(DEFAULT_BITMAP);
307 }
308 }
309
310 /*
311 * @implemented
312 */
313 HBITMAP WINAPI
314 CreateBitmapIndirect(const BITMAP *pbm)
315 {
316 HBITMAP bitmap = NULL;
317
318 /* Note windows xp/2003 does not check if pbm is NULL or not */
319 if ( (pbm->bmWidthBytes != 0) &&
320 (!(pbm->bmWidthBytes & 1)) )
321
322 {
323
324 bitmap = CreateBitmap(pbm->bmWidth,
325 pbm->bmHeight,
326 pbm->bmPlanes,
327 pbm->bmBitsPixel,
328 pbm->bmBits);
329 }
330 else
331 {
332 SetLastError(ERROR_INVALID_PARAMETER);
333 }
334
335 return bitmap;
336 }
337
338 HBITMAP WINAPI
339 CreateDiscardableBitmap(
340 HDC hDC,
341 INT Width,
342 INT Height)
343 {
344 return CreateCompatibleBitmap(hDC, Width, Height);
345 }
346
347
348 HBITMAP WINAPI
349 CreateCompatibleBitmap(
350 HDC hDC,
351 INT Width,
352 INT Height)
353 {
354 PDC_ATTR pDc_Attr;
355 HBITMAP hBmp = NULL;
356 DIBSECTION dibs;
357
358 if (!GdiGetHandleUserData(hDC, GDI_OBJECT_TYPE_DC, (PVOID)&pDc_Attr))
359 return NULL;
360
361 if ( !Width || !Height )
362 return GetStockObject(DEFAULT_BITMAP);
363
364 if (!(pDc_Attr->ulDirty_ & DC_DIBSECTION))
365 {
366 return NtGdiCreateCompatibleBitmap(hDC, Width, Height);
367 }
368
369 hBmp = NtGdiGetDCObject(hDC, GDI_OBJECT_TYPE_BITMAP);
370
371 if ( GetObjectA(hBmp, sizeof(DIBSECTION), &dibs) != sizeof(DIBSECTION) )
372 return NULL;
373
374 if ( dibs.dsBm.bmBitsPixel <= 8 )
375 GetDIBColorTable(hDC, 0, 256, (RGBQUAD *)&dibs.dsBitfields);
376
377 dibs.dsBmih.biWidth = Width;
378 dibs.dsBmih.biHeight = Height;
379
380 return CreateDIBSection(hDC, (CONST BITMAPINFO *)&dibs.dsBmih, 0, NULL, NULL, 0);
381 }
382
383
384 INT
385 WINAPI
386 GetDIBits(
387 HDC hDC,
388 HBITMAP hbmp,
389 UINT uStartScan,
390 UINT cScanLines,
391 LPVOID lpvBits,
392 LPBITMAPINFO lpbmi,
393 UINT uUsage)
394 {
395 INT Ret = 0;
396 UINT cjBmpScanSize;
397 PVOID pvSafeBits = lpvBits;
398
399 if (!hDC || !GdiIsHandleValid((HGDIOBJ)hDC))
400 {
401 GdiSetLastError(ERROR_INVALID_PARAMETER);
402 return Ret;
403 }
404
405 cjBmpScanSize = DIB_BitmapMaxBitsSize(lpbmi, cScanLines);
406
407 if ( lpvBits )
408 {
409 if ( lpbmi )
410 {
411 if ( lpbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) )
412 {
413 if ( lpbmi->bmiHeader.biCompression == BI_JPEG ||
414 lpbmi->bmiHeader.biCompression == BI_PNG )
415 {
416 SetLastError(ERROR_INVALID_PARAMETER);
417 return Ret;
418 }
419 }
420 }
421 pvSafeBits = RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize);
422 }
423
424 Ret = NtGdiGetDIBitsInternal(hDC,
425 hbmp,
426 uStartScan,
427 cScanLines,
428 pvSafeBits,
429 lpbmi,
430 uUsage,
431 cjBmpScanSize,
432 0);
433 if ( lpvBits != pvSafeBits)
434 {
435 RtlCopyMemory( lpvBits, pvSafeBits, cjBmpScanSize);
436 RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits);
437 }
438 return Ret;
439 }
440
441 /*
442 * @implemented
443 */
444 HBITMAP
445 WINAPI
446 CreateDIBitmap( HDC hDC,
447 const BITMAPINFOHEADER *Header,
448 DWORD Init,
449 LPCVOID Bits,
450 const BITMAPINFO *Data,
451 UINT ColorUse)
452 {
453 LONG width, height, compr, dibsize;
454 WORD planes, bpp;
455 // PDC_ATTR pDc_Attr;
456 PBITMAPINFO pConvertedInfo;
457 UINT ConvertedInfoSize;
458 UINT cjBmpScanSize;
459 PVOID pvSafeBits = NULL;
460 HBITMAP hBmp;
461
462 pConvertedInfo = ConvertBitmapInfo(Data, ColorUse,
463 &ConvertedInfoSize, FALSE);
464
465 if (DIB_GetBitmapInfo(Header, &width, &height, &planes, &bpp, &compr, &dibsize) == -1)
466 {
467 GdiSetLastError(ERROR_INVALID_PARAMETER);
468 return NULL;
469 }
470
471 if ( pConvertedInfo )
472 {
473 if ( pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) )
474 {
475 if ( pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
476 pConvertedInfo->bmiHeader.biCompression == BI_PNG )
477 {
478 hBmp = NULL;
479 goto Exit;
480 }
481 }
482 }
483
484 // For Icm support.
485 // GdiGetHandleUserData(hdc, GDI_OBJECT_TYPE_DC, (PVOID)&pDc_Attr))
486
487 cjBmpScanSize = DIB_BitmapBitsSize((LPBITMAPINFO)pConvertedInfo);
488 DPRINT("pBMI %x, Size bpp %d, dibsize %d, Conv %d, BSS %d\n", pConvertedInfo,bpp,dibsize,ConvertedInfoSize,cjBmpScanSize);
489
490 if ( !width || !height )
491 hBmp = GetStockObject(DEFAULT_BITMAP);
492 else
493 {
494 if ( Bits )
495 {
496 pvSafeBits = RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize);
497 if ( pvSafeBits )
498 RtlCopyMemory( pvSafeBits, Bits, cjBmpScanSize);
499 }
500
501 hBmp = NtGdiCreateDIBitmapInternal(hDC,
502 width,
503 height,
504 Init,
505 (LPBYTE)pvSafeBits,
506 (PBITMAPINFO)pConvertedInfo,
507 ColorUse,
508 ConvertedInfoSize,
509 cjBmpScanSize,
510 0,
511 0);
512
513 if ( Bits )
514 RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits);
515 }
516 Exit:
517 if (Data != pConvertedInfo)
518 RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo);
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 if ( iUsage ) // Save time, we only look at non RGB.
873 {
874 pConvertedInfo = ConvertBitmapInfo(lpBitsInfo, iUsage,
875 &ConvertedInfoSize, FALSE);
876 if (!pConvertedInfo)
877 {
878 return 0;
879 }
880 }
881 else
882 pConvertedInfo = (PBITMAPINFO)lpBitsInfo;
883
884 cjBmpScanSize = DIB_BitmapBitsSize((LPBITMAPINFO)pConvertedInfo);
885
886 if ( lpBits )
887 {
888 pvSafeBits = RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize);
889 if (pvSafeBits)
890 {
891 _SEH2_TRY
892 {
893 RtlCopyMemory( pvSafeBits, lpBits, cjBmpScanSize );
894 }
895 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
896 {
897 Hit = TRUE;
898 }
899 _SEH2_END
900
901 if (Hit)
902 {
903 // We don't die, we continue on with a allocated safe pointer to kernel
904 // space.....
905 DPRINT1("StretchDIBits fail to read BitMapInfo: %x or Bits: %x & Size: %d\n",pConvertedInfo,lpBits,cjBmpScanSize);
906 }
907 DPRINT("StretchDIBits Allocate Bits %d!!!\n", cjBmpScanSize);
908 }
909 }
910
911 if (!GdiGetHandleUserData(hdc, GDI_OBJECT_TYPE_DC, (PVOID)&pDc_Attr))
912 {
913 SetLastError(ERROR_INVALID_PARAMETER);
914 return 0;
915 }
916 /*
917 if ( !pDc_Attr ||
918 ((pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
919 (pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
920 pConvertedInfo->bmiHeader.biCompression == BI_PNG )) )*/
921 {
922 LinesCopied = NtGdiStretchDIBitsInternal( hdc,
923 XDest,
924 YDest,
925 nDestWidth,
926 nDestHeight,
927 XSrc,
928 YSrc,
929 nSrcWidth,
930 nSrcHeight,
931 pvSafeBits,
932 pConvertedInfo,
933 (DWORD)iUsage,
934 dwRop,
935 ConvertedInfoSize,
936 cjBmpScanSize,
937 NULL);
938 }
939 if ( pvSafeBits )
940 RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits);
941 if (lpBitsInfo != pConvertedInfo)
942 RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo);
943
944 return LinesCopied;
945 }
946