[GDI32]
[reactos.git] / reactos / dll / win32 / gdi32 / objects / bitmap.c
1 #include "precomp.h"
2
3 #define NDEBUG
4 #include <debug.h>
5
6 // From Yuan, ScanLineSize = (Width * bitcount + 31)/32
7 #define WIDTH_BYTES_ALIGN32(cx, bpp) ((((cx) * (bpp) + 31) & ~31) >> 3)
8
9 /*
10 * DIB_BitmapInfoSize
11 *
12 * Return the size of the bitmap info structure including color table.
13 * 11/16/1999 (RJJ) lifted from wine
14 */
15
16 INT FASTCALL DIB_BitmapInfoSize(const BITMAPINFO * info, WORD coloruse)
17 {
18 unsigned int colors, size, masks = 0;
19
20 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
21 {
22 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
23 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
24 return sizeof(BITMAPCOREHEADER) + colors *
25 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
26 }
27 else /* assume BITMAPINFOHEADER */
28 {
29 colors = info->bmiHeader.biClrUsed;
30 if (colors > 256) colors = 256;
31 if (!colors && (info->bmiHeader.biBitCount <= 8))
32 colors = 1 << info->bmiHeader.biBitCount;
33 if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3;
34 size = max( info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) );
35 return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
36 }
37 }
38
39 /*
40 * Return the full scan size for a bitmap.
41 *
42 * Based on Wine, Utils.c and Windows Graphics Prog pg 595, SDK amvideo.h.
43 */
44 UINT
45 FASTCALL
46 DIB_BitmapMaxBitsSize( PBITMAPINFO Info, UINT ScanLines )
47 {
48 UINT Ret;
49
50 if (!Info) return 0;
51
52 if ( Info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
53 {
54 PBITMAPCOREHEADER Core = (PBITMAPCOREHEADER)Info;
55 Ret = WIDTH_BYTES_ALIGN32(Core->bcWidth * Core->bcPlanes, Core->bcBitCount) * ScanLines;
56 }
57 else /* assume BITMAPINFOHEADER */
58 {
59 if (!(Info->bmiHeader.biCompression) || (Info->bmiHeader.biCompression == BI_BITFIELDS))
60 {
61 Ret = WIDTH_BYTES_ALIGN32(Info->bmiHeader.biWidth * Info->bmiHeader.biPlanes, Info->bmiHeader.biBitCount) * ScanLines;
62 }
63 else
64 {
65 Ret = Info->bmiHeader.biSizeImage;
66 }
67 }
68 return Ret;
69 }
70
71 /*
72 * DIB_GetBitmapInfo is complete copy of wine cvs 2/9-2006
73 * from file dib.c from gdi32.dll or orginal version
74 * did not calc the info right for some headers.
75 */
76 INT
77 WINAPI
78 DIB_GetBitmapInfo(const BITMAPINFOHEADER *header,
79 PLONG width,
80 PLONG height,
81 PWORD planes,
82 PWORD bpp,
83 PLONG compr,
84 PLONG size )
85 {
86 if (header->biSize == sizeof(BITMAPCOREHEADER))
87 {
88 BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)header;
89 *width = core->bcWidth;
90 *height = core->bcHeight;
91 *planes = core->bcPlanes;
92 *bpp = core->bcBitCount;
93 *compr = 0;
94 *size = 0;
95 return 0;
96 }
97
98 if (header->biSize == sizeof(BITMAPINFOHEADER))
99 {
100 *width = header->biWidth;
101 *height = header->biHeight;
102 *planes = header->biPlanes;
103 *bpp = header->biBitCount;
104 *compr = header->biCompression;
105 *size = header->biSizeImage;
106 return 1;
107 }
108
109 if (header->biSize == sizeof(BITMAPV4HEADER))
110 {
111 BITMAPV4HEADER *v4hdr = (BITMAPV4HEADER *)header;
112 *width = v4hdr->bV4Width;
113 *height = v4hdr->bV4Height;
114 *planes = v4hdr->bV4Planes;
115 *bpp = v4hdr->bV4BitCount;
116 *compr = v4hdr->bV4V4Compression;
117 *size = v4hdr->bV4SizeImage;
118 return 4;
119 }
120
121 if (header->biSize == sizeof(BITMAPV5HEADER))
122 {
123 BITMAPV5HEADER *v5hdr = (BITMAPV5HEADER *)header;
124 *width = v5hdr->bV5Width;
125 *height = v5hdr->bV5Height;
126 *planes = v5hdr->bV5Planes;
127 *bpp = v5hdr->bV5BitCount;
128 *compr = v5hdr->bV5Compression;
129 *size = v5hdr->bV5SizeImage;
130 return 5;
131 }
132 DPRINT("(%ld): wrong size for header\n", header->biSize );
133 return -1;
134 }
135
136 /*
137 * @implemented
138 */
139 int
140 WINAPI
141 GdiGetBitmapBitsSize(BITMAPINFO *lpbmi)
142 {
143 UINT Ret;
144
145 if (!lpbmi) return 0;
146
147 if ( lpbmi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
148 {
149 PBITMAPCOREHEADER Core = (PBITMAPCOREHEADER)lpbmi;
150 Ret = WIDTH_BYTES_ALIGN32(Core->bcWidth * Core->bcPlanes, Core->bcBitCount) * Core->bcHeight;
151 }
152 else /* assume BITMAPINFOHEADER */
153 {
154 if (!(lpbmi->bmiHeader.biCompression) || (lpbmi->bmiHeader.biCompression == BI_BITFIELDS))
155 {
156 Ret = WIDTH_BYTES_ALIGN32(lpbmi->bmiHeader.biWidth * lpbmi->bmiHeader.biPlanes, lpbmi->bmiHeader.biBitCount) * abs(lpbmi->bmiHeader.biHeight);
157 }
158 else
159 {
160 Ret = lpbmi->bmiHeader.biSizeImage;
161 }
162 }
163 return Ret;
164 }
165
166 /*
167 * @implemented
168 */
169 HBITMAP WINAPI
170 CreateDIBSection(
171 HDC hDC,
172 CONST BITMAPINFO *BitmapInfo,
173 UINT Usage,
174 VOID **Bits,
175 HANDLE hSection,
176 DWORD dwOffset)
177 {
178 PBITMAPINFO pConvertedInfo;
179 UINT ConvertedInfoSize;
180 HBITMAP hBitmap = NULL;
181 PVOID bmBits = NULL;
182
183 pConvertedInfo = ConvertBitmapInfo(BitmapInfo, Usage,
184 &ConvertedInfoSize, FALSE);
185 if (pConvertedInfo)
186 {
187 // Verify header due to converted may == info.
188 if ( pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) )
189 {
190 if ( pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
191 pConvertedInfo->bmiHeader.biCompression == BI_PNG )
192 {
193 SetLastError(ERROR_INVALID_PARAMETER);
194 return NULL;
195 }
196 }
197 bmBits = Bits;
198 hBitmap = NtGdiCreateDIBSection( hDC,
199 hSection,
200 dwOffset,
201 pConvertedInfo,
202 Usage,
203 0,
204 0,
205 0,
206 &bmBits);
207 if (BitmapInfo != pConvertedInfo)
208 RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo);
209
210 if (!hBitmap)
211 {
212 bmBits = NULL;
213 }
214 }
215
216 if (Bits) *Bits = bmBits;
217
218 return hBitmap;
219 }
220
221
222 /*
223 * @implemented
224 */
225 BOOL
226 WINAPI
227 BitBlt(HDC hdcDest, /* handle to destination DC */
228 int nXOriginDest, /* x-coord of destination upper-left corner */
229 int nYOriginDest, /* y-coord of destination upper-left corner */
230 int nWidthDest, /* width of destination rectangle */
231 int nHeightDest, /* height of destination rectangle */
232 HDC hdcSrc, /* handle to source DC */
233 int nXSrc, /* x-coordinate of source upper-left corner */
234 int nYSrc, /* y-coordinate of source upper-left corner */
235 DWORD dwRop) /* raster operation code */
236 {
237 /* use patBlt for no source blt Like windows does */
238 if (!ROP_USES_SOURCE(dwRop))
239 {
240 return PatBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, dwRop);
241 }
242
243 return NtGdiBitBlt(hdcDest,
244 nXOriginDest,
245 nYOriginDest,
246 nWidthDest,
247 nHeightDest,
248 hdcSrc,
249 nXSrc,
250 nYSrc,
251 dwRop,
252 0,
253 0);
254 }
255
256 /*
257 * @implemented
258 */
259 BOOL WINAPI
260 StretchBlt(
261 HDC hdcDest, /* handle to destination DC */
262 int nXOriginDest, /* x-coord of destination upper-left corner */
263 int nYOriginDest, /* y-coord of destination upper-left corner */
264 int nWidthDest, /* width of destination rectangle */
265 int nHeightDest, /* height of destination rectangle */
266 HDC hdcSrc, /* handle to source DC */
267 int nXOriginSrc, /* x-coord of source upper-left corner */
268 int nYOriginSrc, /* y-coord of source upper-left corner */
269 int nWidthSrc, /* width of source rectangle */
270 int nHeightSrc, /* height of source rectangle */
271 DWORD dwRop) /* raster operation code */
272
273 {
274 if ((nWidthDest != nWidthSrc) || (nHeightDest != nHeightSrc))
275 {
276 return NtGdiStretchBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest,
277 nHeightDest, hdcSrc, nXOriginSrc, nYOriginSrc,
278 nWidthSrc, nHeightSrc, dwRop, 0);
279 }
280
281 return NtGdiBitBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest,
282 nHeightDest, hdcSrc, nXOriginSrc, nYOriginSrc, dwRop, 0, 0);
283 }
284
285 /*
286 * @implemented
287 */
288 HBITMAP WINAPI
289 CreateBitmap(INT Width,
290 INT Height,
291 UINT Planes,
292 UINT BitsPixel,
293 CONST VOID* pUnsafeBits)
294 {
295 if (Width && Height)
296 {
297 return NtGdiCreateBitmap(Width, Height, Planes, BitsPixel, (LPBYTE) pUnsafeBits);
298 }
299 else
300 {
301 /* Return 1x1 bitmap */
302 return GetStockObject(DEFAULT_BITMAP);
303 }
304 }
305
306 /*
307 * @implemented
308 */
309 HBITMAP WINAPI
310 CreateBitmapIndirect(const BITMAP *pbm)
311 {
312 HBITMAP bitmap = NULL;
313
314 /* Note windows xp/2003 does not check if pbm is NULL or not */
315 if ( (pbm->bmWidthBytes != 0) &&
316 (!(pbm->bmWidthBytes & 1)) )
317
318 {
319
320 bitmap = CreateBitmap(pbm->bmWidth,
321 pbm->bmHeight,
322 pbm->bmPlanes,
323 pbm->bmBitsPixel,
324 pbm->bmBits);
325 }
326 else
327 {
328 SetLastError(ERROR_INVALID_PARAMETER);
329 }
330
331 return bitmap;
332 }
333
334 HBITMAP WINAPI
335 CreateDiscardableBitmap(
336 HDC hDC,
337 INT Width,
338 INT Height)
339 {
340 return CreateCompatibleBitmap(hDC, Width, Height);
341 }
342
343
344 HBITMAP WINAPI
345 CreateCompatibleBitmap(
346 HDC hDC,
347 INT Width,
348 INT Height)
349 {
350 PDC_ATTR pDc_Attr;
351
352 if (!GdiGetHandleUserData(hDC, GDI_OBJECT_TYPE_DC, (PVOID)&pDc_Attr))
353 return NULL;
354
355 if ( !Width || !Height )
356 return GetStockObject(DEFAULT_BITMAP);
357
358 if (!(pDc_Attr->ulDirty_ & DC_DIBSECTION))
359 {
360 return NtGdiCreateCompatibleBitmap(hDC, Width, Height);
361 }
362 else
363 {
364 HBITMAP hBmp = NULL;
365 char buffer[sizeof(DIBSECTION) + 256*sizeof(RGBQUAD)];
366 DIBSECTION* pDIBs = (DIBSECTION*)buffer;
367
368 hBmp = NtGdiGetDCObject(hDC, GDI_OBJECT_TYPE_BITMAP);
369
370 if ( GetObjectA(hBmp, sizeof(DIBSECTION), pDIBs) != sizeof(DIBSECTION) )
371 return NULL;
372
373 if ( pDIBs->dsBm.bmBitsPixel <= 8 )
374 GetDIBColorTable(hDC, 0, 256, (RGBQUAD *)&pDIBs->dsBitfields[0]);
375
376 pDIBs->dsBmih.biWidth = Width;
377 pDIBs->dsBmih.biHeight = Height;
378
379 return CreateDIBSection(hDC, (CONST BITMAPINFO *)&pDIBs->dsBmih, 0, NULL, NULL, 0);
380 }
381 return NULL;
382 }
383
384
385 INT
386 WINAPI
387 GetDIBits(
388 HDC hDC,
389 HBITMAP hbmp,
390 UINT uStartScan,
391 UINT cScanLines,
392 LPVOID lpvBits,
393 LPBITMAPINFO lpbmi,
394 UINT uUsage)
395 {
396 UINT cjBmpScanSize;
397 UINT cjInfoSize;
398
399 if (!hDC || !GdiIsHandleValid((HGDIOBJ)hDC) || !lpbmi)
400 {
401 GdiSetLastError(ERROR_INVALID_PARAMETER);
402 return 0;
403 }
404
405 cjBmpScanSize = DIB_BitmapMaxBitsSize(lpbmi, cScanLines);
406 cjInfoSize = DIB_BitmapInfoSize(lpbmi, uUsage);
407
408 if ( lpvBits )
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 0;
417 }
418 }
419 }
420
421 return NtGdiGetDIBitsInternal(hDC,
422 hbmp,
423 uStartScan,
424 cScanLines,
425 lpvBits,
426 lpbmi,
427 uUsage,
428 cjBmpScanSize,
429 cjInfoSize);
430 }
431
432 /*
433 * @implemented
434 */
435 HBITMAP
436 WINAPI
437 CreateDIBitmap( HDC hDC,
438 const BITMAPINFOHEADER *Header,
439 DWORD Init,
440 LPCVOID Bits,
441 const BITMAPINFO *Data,
442 UINT ColorUse)
443 {
444 LONG width, height, compr, dibsize;
445 WORD planes, bpp;
446 // PDC_ATTR pDc_Attr;
447 UINT InfoSize = 0;
448 UINT cjBmpScanSize = 0;
449 HBITMAP hBmp;
450 NTSTATUS Status = STATUS_SUCCESS;
451
452 if (!Header) return 0;
453
454 if (DIB_GetBitmapInfo(Header, &width, &height, &planes, &bpp, &compr, &dibsize) == -1)
455 {
456 GdiSetLastError(ERROR_INVALID_PARAMETER);
457 return NULL;
458 }
459
460 // For Icm support.
461 // GdiGetHandleUserData(hdc, GDI_OBJECT_TYPE_DC, (PVOID)&pDc_Attr))
462
463 if(Data)
464 {
465 _SEH2_TRY
466 {
467 cjBmpScanSize = GdiGetBitmapBitsSize((BITMAPINFO *)Data);
468 CalculateColorTableSize(&Data->bmiHeader, &ColorUse, &InfoSize);
469 InfoSize += Data->bmiHeader.biSize;
470 }
471 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
472 {
473 Status = _SEH2_GetExceptionCode();
474 }
475 _SEH2_END
476 }
477
478 if(!NT_SUCCESS(Status))
479 {
480 GdiSetLastError(ERROR_INVALID_PARAMETER);
481 return NULL;
482 }
483
484 DPRINT("pBMI %x, Size bpp %d, dibsize %d, Conv %d, BSS %d\n", Data,bpp,dibsize,InfoSize,cjBmpScanSize);
485
486 if ( !width || !height )
487 hBmp = GetStockObject(DEFAULT_BITMAP);
488 else
489 {
490 hBmp = NtGdiCreateDIBitmapInternal(hDC,
491 width,
492 height,
493 Init,
494 (LPBYTE)Bits,
495 (LPBITMAPINFO)Data,
496 ColorUse,
497 InfoSize,
498 cjBmpScanSize,
499 0,
500 0);
501 }
502 return hBmp;
503 }
504
505 /*
506 * @implemented
507 */
508 INT
509 WINAPI
510 SetDIBits(HDC hDC,
511 HBITMAP hBitmap,
512 UINT uStartScan,
513 UINT cScanLines,
514 CONST VOID *lpvBits,
515 CONST BITMAPINFO *lpbmi,
516 UINT fuColorUse)
517 {
518 HDC hDCc, SavehDC, nhDC;
519 DWORD dwWidth, dwHeight;
520 HGDIOBJ hOldBitmap;
521 HPALETTE hPal = NULL;
522 INT LinesCopied = 0;
523 BOOL newDC = FALSE;
524
525 if ( !lpvBits || (GDI_HANDLE_GET_TYPE(hBitmap) != GDI_OBJECT_TYPE_BITMAP) )
526 return 0;
527
528 if ( lpbmi )
529 {
530 if ( lpbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) )
531 {
532 if ( lpbmi->bmiHeader.biCompression == BI_JPEG || lpbmi->bmiHeader.biCompression == BI_PNG )
533 {
534 SetLastError(ERROR_INVALID_PARAMETER);
535 return 0;
536 }
537 }
538 }
539
540 hDCc = NtGdiGetDCforBitmap(hBitmap); // hDC can be NULL, so, get it from the bitmap.
541 SavehDC = hDCc;
542 if ( !hDCc ) // No DC associated with bitmap, Clone or Create one.
543 {
544 nhDC = CreateCompatibleDC(hDC);
545 if ( !nhDC ) return 0;
546 newDC = TRUE;
547 SavehDC = nhDC;
548 }
549 else if ( !SaveDC(hDCc) )
550 return 0;
551
552 hOldBitmap = SelectObject(SavehDC, hBitmap);
553
554 if ( hOldBitmap )
555 {
556 if ( hDC )
557 hPal = SelectPalette(SavehDC, (HPALETTE)GetDCObject(hDC, GDI_OBJECT_TYPE_PALETTE), FALSE);
558
559 if ( lpbmi->bmiHeader.biSize < sizeof(BITMAPINFOHEADER))
560 {
561 PBITMAPCOREINFO pbci = (PBITMAPCOREINFO) lpbmi;
562 dwWidth = pbci->bmciHeader.bcWidth;
563 dwHeight = pbci->bmciHeader.bcHeight;
564 }
565 else
566 {
567 dwWidth = lpbmi->bmiHeader.biWidth;
568 dwHeight = abs(lpbmi->bmiHeader.biHeight);
569 }
570
571 LinesCopied = SetDIBitsToDevice(SavehDC,
572 0,
573 0,
574 dwWidth,
575 dwHeight,
576 0,
577 0,
578 uStartScan,
579 cScanLines,
580 (void *)lpvBits,
581 (LPBITMAPINFO)lpbmi,
582 fuColorUse);
583
584 if ( hDC ) SelectPalette(SavehDC, hPal, FALSE);
585
586 SelectObject(SavehDC, hOldBitmap);
587 }
588
589 if ( newDC )
590 DeleteDC(SavehDC);
591 else
592 RestoreDC(SavehDC, -1);
593
594 return LinesCopied;
595 }
596
597 /*
598 * @implemented
599 *
600 */
601 INT
602 WINAPI
603 SetDIBitsToDevice(
604 HDC hdc,
605 int XDest,
606 int YDest,
607 DWORD Width,
608 DWORD Height,
609 int XSrc,
610 int YSrc,
611 UINT StartScan,
612 UINT ScanLines,
613 CONST VOID *Bits,
614 CONST BITMAPINFO *lpbmi,
615 UINT ColorUse)
616 {
617 PDC_ATTR pDc_Attr;
618 PBITMAPINFO pConvertedInfo;
619 UINT ConvertedInfoSize;
620 INT LinesCopied = 0;
621 UINT cjBmpScanSize = 0;
622 BOOL Hit = FALSE;
623 PVOID pvSafeBits = (PVOID)Bits;
624
625 if ( !ScanLines || !lpbmi || !Bits )
626 return 0;
627
628 if ( ColorUse && ColorUse != DIB_PAL_COLORS && ColorUse != DIB_PAL_COLORS+1 )
629 return 0;
630
631 pConvertedInfo = ConvertBitmapInfo(lpbmi, ColorUse,
632 &ConvertedInfoSize, FALSE);
633 if (!pConvertedInfo)
634 return 0;
635
636 #if 0
637 // Handle something other than a normal dc object.
638 if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC)
639 {
640 if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC)
641 return MFDRV_SetDIBitsToDevice( hdc,
642 XDest,
643 YDest,
644 Width,
645 Height,
646 XSrc,
647 YSrc,
648 StartScan,
649 ScanLines,
650 Bits,
651 lpbmi,
652 ColorUse);
653 else
654 {
655 PLDC pLDC = GdiGetLDC(hdc);
656 if ( !pLDC )
657 {
658 SetLastError(ERROR_INVALID_HANDLE);
659 return 0;
660 }
661 if (pLDC->iType == LDC_EMFLDC)
662 {
663 return EMFDRV_SetDIBitsToDevice(hdc,
664 XDest,
665 YDest,
666 Width,
667 Height,
668 XSrc,
669 YSrc,
670 StartScan,
671 ScanLines,
672 Bits,
673 lpbmi,
674 ColorUse);
675 }
676 return 0;
677 }
678 }
679 #endif
680 cjBmpScanSize = DIB_BitmapMaxBitsSize((LPBITMAPINFO)lpbmi, ScanLines);
681
682 if ( Bits )
683 {
684 pvSafeBits = RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize);
685 if (pvSafeBits)
686 {
687 _SEH2_TRY
688 {
689 RtlCopyMemory( pvSafeBits, Bits, cjBmpScanSize);
690 }
691 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
692 {
693 Hit = TRUE;
694 }
695 _SEH2_END
696
697 if (Hit)
698 {
699 // We don't die, we continue on with a allocated safe pointer to kernel
700 // space.....
701 DPRINT1("SetDIBitsToDevice fail to read BitMapInfo: %x or Bits: %x & Size: %d\n",pConvertedInfo,Bits,cjBmpScanSize);
702 }
703 DPRINT("SetDIBitsToDevice Allocate Bits %d!!!\n", cjBmpScanSize);
704 }
705
706 }
707
708 if (!GdiGetHandleUserData(hdc, GDI_OBJECT_TYPE_DC, (PVOID)&pDc_Attr))
709 {
710 SetLastError(ERROR_INVALID_PARAMETER);
711 return 0;
712 }
713 /*
714 if ( !pDc_Attr || // DC is Public
715 ColorUse == DIB_PAL_COLORS ||
716 ((pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
717 (pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
718 pConvertedInfo->bmiHeader.biCompression == BI_PNG )) )*/
719 {
720 LinesCopied = NtGdiSetDIBitsToDeviceInternal( hdc,
721 XDest,
722 YDest,
723 Width,
724 Height,
725 XSrc,
726 YSrc,
727 StartScan,
728 ScanLines,
729 (LPBYTE)pvSafeBits,
730 (LPBITMAPINFO)pConvertedInfo,
731 ColorUse,
732 cjBmpScanSize,
733 ConvertedInfoSize,
734 TRUE,
735 NULL);
736 }
737 if ( Bits != pvSafeBits)
738 RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits);
739 if (lpbmi != pConvertedInfo)
740 RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo);
741
742 return LinesCopied;
743 }
744
745
746 /*
747 * @unimplemented
748 */
749 int
750 WINAPI
751 StretchDIBits(HDC hdc,
752 int XDest,
753 int YDest,
754 int nDestWidth,
755 int nDestHeight,
756 int XSrc,
757 int YSrc,
758 int nSrcWidth,
759 int nSrcHeight,
760 CONST VOID *lpBits,
761 CONST BITMAPINFO *lpBitsInfo,
762 UINT iUsage,
763 DWORD dwRop)
764
765 {
766 PDC_ATTR pDc_Attr;
767 PBITMAPINFO pConvertedInfo = NULL;
768 UINT ConvertedInfoSize = 0;
769 INT LinesCopied = 0;
770 UINT cjBmpScanSize = 0;
771 PVOID pvSafeBits = NULL;
772 BOOL Hit = FALSE;
773
774 DPRINT("StretchDIBits %x : %x : %d\n", lpBits, lpBitsInfo, iUsage);
775 #if 0
776 // Handle something other than a normal dc object.
777 if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC)
778 {
779 if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC)
780 return MFDRV_StretchBlt( hdc,
781 XDest,
782 YDest,
783 nDestWidth,
784 nDestHeight,
785 XSrc,
786 YSrc,
787 nSrcWidth,
788 nSrcHeight,
789 lpBits,
790 lpBitsInfo,
791 iUsage,
792 dwRop);
793 else
794 {
795 PLDC pLDC = GdiGetLDC(hdc);
796 if ( !pLDC )
797 {
798 SetLastError(ERROR_INVALID_HANDLE);
799 return 0;
800 }
801 if (pLDC->iType == LDC_EMFLDC)
802 {
803 return EMFDRV_StretchBlt(hdc,
804 XDest,
805 YDest,
806 nDestWidth,
807 nDestHeight,
808 XSrc,
809 YSrc,
810 nSrcWidth,
811 nSrcHeight,
812 lpBits,
813 lpBitsInfo,
814 iUsage,
815 dwRop);
816 }
817 return 0;
818 }
819 }
820 #endif
821 pConvertedInfo = ConvertBitmapInfo(lpBitsInfo, iUsage,
822 &ConvertedInfoSize, FALSE);
823 if (!pConvertedInfo)
824 {
825 return 0;
826 }
827
828 cjBmpScanSize = GdiGetBitmapBitsSize((BITMAPINFO *)pConvertedInfo);
829
830 if ( lpBits )
831 {
832 pvSafeBits = RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize);
833 if (pvSafeBits)
834 {
835 _SEH2_TRY
836 {
837 RtlCopyMemory( pvSafeBits, lpBits, cjBmpScanSize );
838 }
839 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
840 {
841 Hit = TRUE;
842 }
843 _SEH2_END
844
845 if (Hit)
846 {
847 // We don't die, we continue on with a allocated safe pointer to kernel
848 // space.....
849 DPRINT1("StretchDIBits fail to read BitMapInfo: %x or Bits: %x & Size: %d\n",pConvertedInfo,lpBits,cjBmpScanSize);
850 }
851 DPRINT("StretchDIBits Allocate Bits %d!!!\n", cjBmpScanSize);
852 }
853 }
854
855 if (!GdiGetHandleUserData(hdc, GDI_OBJECT_TYPE_DC, (PVOID)&pDc_Attr))
856 {
857 SetLastError(ERROR_INVALID_PARAMETER);
858 return 0;
859 }
860 /*
861 if ( !pDc_Attr ||
862 iUsage == DIB_PAL_COLORS ||
863 ((pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
864 (pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
865 pConvertedInfo->bmiHeader.biCompression == BI_PNG )) )*/
866 {
867 LinesCopied = NtGdiStretchDIBitsInternal( hdc,
868 XDest,
869 YDest,
870 nDestWidth,
871 nDestHeight,
872 XSrc,
873 YSrc,
874 nSrcWidth,
875 nSrcHeight,
876 pvSafeBits,
877 pConvertedInfo,
878 (DWORD)iUsage,
879 dwRop,
880 ConvertedInfoSize,
881 cjBmpScanSize,
882 NULL);
883 }
884 if ( pvSafeBits )
885 RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits);
886 if (lpBitsInfo != pConvertedInfo)
887 RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo);
888
889 return LinesCopied;
890 }
891