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