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