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