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