[GDI32] Do not 'hard-assert' during the font-unit-test.
[reactos.git] / 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 || !GdiValidateHandle((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, Compression, DibSize;
407 WORD Planes, BitsPerPixel;
408 // PDC_ATTR pDc_Attr;
409 UINT cjBmpScanSize = 0;
410 HBITMAP hBitmap = NULL;
411 PBITMAPINFO pbmiConverted;
412 UINT cjInfoSize;
413
414 /* Convert the BITMAPINFO if it is a COREINFO */
415 pbmiConverted = ConvertBitmapInfo(Data, ColorUse, &cjInfoSize, FALSE);
416
417 /* Check for CBM_CREATDIB */
418 if (Init & CBM_CREATDIB)
419 {
420 if (cjInfoSize == 0)
421 {
422 goto Exit;
423 }
424 else if (Init & CBM_INIT)
425 {
426 if (Bits == NULL)
427 {
428 goto Exit;
429 }
430 }
431 else
432 {
433 Bits = NULL;
434 }
435
436 /* CBM_CREATDIB needs Data. */
437 if (pbmiConverted == NULL)
438 {
439 DPRINT1("CBM_CREATDIB needs a BITMAPINFO!\n");
440 goto Exit;
441 }
442
443 /* It only works with PAL or RGB */
444 if (ColorUse > DIB_PAL_COLORS)
445 {
446 DPRINT1("Invalid ColorUse: %lu\n", ColorUse);
447 GdiSetLastError(ERROR_INVALID_PARAMETER);
448 goto Exit;
449 }
450
451 /* Use the header from the data */
452 Header = &Data->bmiHeader;
453 }
454 else
455 {
456 if (Init & CBM_INIT)
457 {
458 if (Bits != NULL)
459 {
460 if (cjInfoSize == 0)
461 {
462 goto Exit;
463 }
464 }
465 else
466 {
467 Init &= ~CBM_INIT;
468 }
469 }
470 }
471
472 /* Header is required */
473 if (!Header)
474 {
475 DPRINT1("Header is NULL\n");
476 GdiSetLastError(ERROR_INVALID_PARAMETER);
477 goto Exit;
478 }
479
480 /* Get the bitmap format and dimensions */
481 if (DIB_GetBitmapInfo(Header, &Width, &Height, &Planes, &BitsPerPixel, &Compression, &DibSize) == -1)
482 {
483 DPRINT1("DIB_GetBitmapInfo failed!\n");
484 GdiSetLastError(ERROR_INVALID_PARAMETER);
485 goto Exit;
486 }
487
488 /* Check if the Compr is incompatible */
489 if ((Compression == BI_JPEG) || (Compression == BI_PNG) || (Compression == BI_BITFIELDS))
490 {
491 DPRINT1("Invalid compression: %lu!\n", Compression);
492 goto Exit;
493 }
494
495 /* Only DIB_RGB_COLORS (0), DIB_PAL_COLORS (1) and 2 are valid. */
496 if (ColorUse > DIB_PAL_COLORS + 1)
497 {
498 DPRINT1("Invalid compression: %lu!\n", Compression);
499 GdiSetLastError(ERROR_INVALID_PARAMETER);
500 goto Exit;
501 }
502
503 /* If some Bits are given, only DIB_PAL_COLORS and DIB_RGB_COLORS are valid */
504 if (Bits && (ColorUse > DIB_PAL_COLORS))
505 {
506 DPRINT1("Invalid ColorUse: %lu\n", ColorUse);
507 GdiSetLastError(ERROR_INVALID_PARAMETER);
508 goto Exit;
509 }
510
511 /* Negative width is not allowed */
512 if (Width < 0)
513 {
514 DPRINT1("Negative width: %li\n", Width);
515 goto Exit;
516 }
517
518 /* Top-down DIBs have a negative height. */
519 Height = abs(Height);
520
521 // For Icm support.
522 // GdiGetHandleUserData(hdc, GDI_OBJECT_TYPE_DC, (PVOID)&pDc_Attr))
523
524 cjBmpScanSize = GdiGetBitmapBitsSize(pbmiConverted);
525
526 DPRINT("pBMI %p, Size bpp %u, dibsize %d, Conv %u, BSS %u\n",
527 Data, BitsPerPixel, DibSize, cjInfoSize, cjBmpScanSize);
528
529 if (!Width || !Height)
530 {
531 hBitmap = GetStockObject(DEFAULT_BITMAP);
532 }
533 else
534 {
535 hBitmap = NtGdiCreateDIBitmapInternal(hDC,
536 Width,
537 Height,
538 Init,
539 (LPBYTE)Bits,
540 (LPBITMAPINFO)pbmiConverted,
541 ColorUse,
542 cjInfoSize,
543 cjBmpScanSize,
544 0, 0);
545 }
546
547 Exit:
548 /* Cleanup converted BITMAPINFO */
549 if ((pbmiConverted != NULL) && (pbmiConverted != Data))
550 {
551 RtlFreeHeap(RtlGetProcessHeap(), 0, pbmiConverted);
552 }
553
554 return hBitmap;
555 }
556
557 /*
558 * @implemented
559 */
560 INT
561 WINAPI
562 SetDIBits(
563 HDC hDC,
564 HBITMAP hBitmap,
565 UINT uStartScan,
566 UINT cScanLines,
567 CONST VOID *lpvBits,
568 CONST BITMAPINFO *lpbmi,
569 UINT fuColorUse)
570 {
571 HDC hDCc, SavehDC, nhDC;
572 DWORD dwWidth, dwHeight;
573 HGDIOBJ hOldBitmap;
574 HPALETTE hPal = NULL;
575 INT LinesCopied = 0;
576 BOOL newDC = FALSE;
577
578 if (!lpvBits || (GDI_HANDLE_GET_TYPE(hBitmap) != GDI_OBJECT_TYPE_BITMAP))
579 return 0;
580
581 if (lpbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER))
582 {
583 if (lpbmi->bmiHeader.biCompression == BI_JPEG
584 || lpbmi->bmiHeader.biCompression == BI_PNG)
585 {
586 SetLastError(ERROR_INVALID_PARAMETER);
587 return 0;
588 }
589 }
590
591 hDCc = NtGdiGetDCforBitmap(hBitmap); // hDC can be NULL, so, get it from the bitmap.
592 SavehDC = hDCc;
593 if (!hDCc) // No DC associated with bitmap, Clone or Create one.
594 {
595 nhDC = CreateCompatibleDC(hDC);
596 if (!nhDC)
597 return 0;
598 newDC = TRUE;
599 SavehDC = nhDC;
600 }
601 else if (!SaveDC(hDCc))
602 return 0;
603
604 hOldBitmap = SelectObject(SavehDC, hBitmap);
605
606 if (hOldBitmap)
607 {
608 if (hDC)
609 hPal = SelectPalette(SavehDC, (HPALETTE) GetCurrentObject(hDC, OBJ_PAL), FALSE);
610
611 if (lpbmi->bmiHeader.biSize < sizeof(BITMAPINFOHEADER))
612 {
613 PBITMAPCOREINFO pbci = (PBITMAPCOREINFO) lpbmi;
614 dwWidth = pbci->bmciHeader.bcWidth;
615 dwHeight = pbci->bmciHeader.bcHeight;
616 }
617 else
618 {
619 dwWidth = lpbmi->bmiHeader.biWidth;
620 dwHeight = abs(lpbmi->bmiHeader.biHeight);
621 }
622
623 LinesCopied = SetDIBitsToDevice(SavehDC, 0, 0, dwWidth, dwHeight, 0, 0, uStartScan,
624 cScanLines, (void *) lpvBits, (LPBITMAPINFO) lpbmi, fuColorUse);
625
626 if (hDC)
627 SelectPalette(SavehDC, hPal, FALSE);
628
629 SelectObject(SavehDC, hOldBitmap);
630 }
631
632 if (newDC)
633 DeleteDC(SavehDC);
634 else
635 RestoreDC(SavehDC, -1);
636
637 return LinesCopied;
638 }
639
640 /*
641 * @implemented
642 *
643 */
644 INT
645 WINAPI
646 SetDIBitsToDevice(
647 HDC hdc,
648 int XDest,
649 int YDest,
650 DWORD Width,
651 DWORD Height,
652 int XSrc,
653 int YSrc,
654 UINT StartScan,
655 UINT ScanLines,
656 CONST VOID *Bits,
657 CONST BITMAPINFO *lpbmi,
658 UINT ColorUse)
659 {
660 PDC_ATTR pDc_Attr;
661 PBITMAPINFO pConvertedInfo;
662 UINT ConvertedInfoSize;
663 INT LinesCopied = 0;
664 UINT cjBmpScanSize = 0;
665 BOOL Hit = FALSE;
666 PVOID pvSafeBits = (PVOID) Bits;
667
668 if (!ScanLines || !lpbmi || !Bits)
669 return 0;
670
671 if (ColorUse && ColorUse != DIB_PAL_COLORS && ColorUse != DIB_PAL_COLORS + 1)
672 return 0;
673
674 pConvertedInfo = ConvertBitmapInfo(lpbmi, ColorUse, &ConvertedInfoSize, FALSE);
675 if (!pConvertedInfo)
676 return 0;
677
678 HANDLE_METADC(INT,
679 SetDIBitsToDevice,
680 0,
681 hdc,
682 XDest,
683 YDest,
684 Width,
685 Height,
686 XSrc,
687 YSrc,
688 StartScan,
689 ScanLines,
690 Bits,
691 lpbmi,
692 ColorUse);
693
694 if ((pConvertedInfo->bmiHeader.biCompression == BI_RLE8) ||
695 (pConvertedInfo->bmiHeader.biCompression == BI_RLE4))
696 {
697 /* For compressed data, we must set the whole thing */
698 StartScan = 0;
699 ScanLines = pConvertedInfo->bmiHeader.biHeight;
700 }
701
702 cjBmpScanSize = DIB_BitmapMaxBitsSize((LPBITMAPINFO) lpbmi, ScanLines);
703
704 pvSafeBits = RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize);
705 if (pvSafeBits)
706 {
707 _SEH2_TRY
708 {
709 RtlCopyMemory(pvSafeBits, Bits, cjBmpScanSize);
710 }
711 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
712 {
713 Hit = TRUE;
714 }
715 _SEH2_END
716
717 if (Hit)
718 {
719 // We don't die, we continue on with a allocated safe pointer to kernel
720 // space.....
721 DPRINT1("SetDIBitsToDevice fail to read BitMapInfo: %p or Bits: %p & Size: %u\n",
722 pConvertedInfo, Bits, cjBmpScanSize);
723 }
724 DPRINT("SetDIBitsToDevice Allocate Bits %u!!!\n", cjBmpScanSize);
725 }
726
727 if (!GdiGetHandleUserData(hdc, GDI_OBJECT_TYPE_DC, (PVOID) & pDc_Attr))
728 {
729 SetLastError(ERROR_INVALID_PARAMETER);
730 return 0;
731 }
732 /*
733 if ( !pDc_Attr || // DC is Public
734 ColorUse == DIB_PAL_COLORS ||
735 ((pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
736 (pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
737 pConvertedInfo->bmiHeader.biCompression == BI_PNG )) )*/
738 {
739 LinesCopied = NtGdiSetDIBitsToDeviceInternal(hdc, XDest, YDest, Width, Height, XSrc, YSrc,
740 StartScan, ScanLines, (LPBYTE) pvSafeBits, (LPBITMAPINFO) pConvertedInfo, ColorUse,
741 cjBmpScanSize, ConvertedInfoSize,
742 TRUE,
743 NULL);
744 }
745 if (Bits != pvSafeBits)
746 RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits);
747 if (lpbmi != pConvertedInfo)
748 RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo);
749
750 return LinesCopied;
751 }
752
753 /*
754 * @unimplemented
755 */
756 int
757 WINAPI
758 StretchDIBits(
759 HDC hdc,
760 int XDest,
761 int YDest,
762 int nDestWidth,
763 int nDestHeight,
764 int XSrc,
765 int YSrc,
766 int nSrcWidth,
767 int nSrcHeight,
768 CONST VOID *lpBits,
769 CONST BITMAPINFO *lpBitsInfo,
770 UINT iUsage,
771 DWORD dwRop)
772
773 {
774 PDC_ATTR pDc_Attr;
775 PBITMAPINFO pConvertedInfo = NULL;
776 UINT ConvertedInfoSize = 0;
777 INT LinesCopied = 0;
778 UINT cjBmpScanSize = 0;
779 PVOID pvSafeBits = NULL;
780 BOOL Hit = FALSE;
781
782 DPRINT("StretchDIBits %p : %p : %u\n", lpBits, lpBitsInfo, iUsage);
783 #if 0
784 // Handle something other than a normal dc object.
785 if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC)
786 {
787 if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC)
788 return MFDRV_StretchBlt( hdc,
789 XDest,
790 YDest,
791 nDestWidth,
792 nDestHeight,
793 XSrc,
794 YSrc,
795 nSrcWidth,
796 nSrcHeight,
797 lpBits,
798 lpBitsInfo,
799 iUsage,
800 dwRop);
801 else
802 {
803 PLDC pLDC = GdiGetLDC(hdc);
804 if ( !pLDC )
805 {
806 SetLastError(ERROR_INVALID_HANDLE);
807 return 0;
808 }
809 if (pLDC->iType == LDC_EMFLDC)
810 {
811 return EMFDRV_StretchBlt(hdc,
812 XDest,
813 YDest,
814 nDestWidth,
815 nDestHeight,
816 XSrc,
817 YSrc,
818 nSrcWidth,
819 nSrcHeight,
820 lpBits,
821 lpBitsInfo,
822 iUsage,
823 dwRop);
824 }
825 return 0;
826 }
827 }
828 #endif
829 pConvertedInfo = ConvertBitmapInfo(lpBitsInfo, iUsage, &ConvertedInfoSize,
830 FALSE);
831 if (!pConvertedInfo)
832 {
833 return 0;
834 }
835
836 cjBmpScanSize = GdiGetBitmapBitsSize((BITMAPINFO *) pConvertedInfo);
837
838 if (lpBits)
839 {
840 pvSafeBits = RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize);
841 if (pvSafeBits)
842 {
843 _SEH2_TRY
844 {
845 RtlCopyMemory(pvSafeBits, lpBits, cjBmpScanSize);
846 }
847 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
848 {
849 Hit = TRUE;
850 }
851 _SEH2_END
852
853 if (Hit)
854 {
855 // We don't die, we continue on with a allocated safe pointer to kernel
856 // space.....
857 DPRINT1("StretchDIBits fail to read BitMapInfo: %p or Bits: %p & Size: %u\n",
858 pConvertedInfo, lpBits, cjBmpScanSize);
859 }
860 DPRINT("StretchDIBits Allocate Bits %u!!!\n", cjBmpScanSize);
861 }
862 }
863
864 if (!GdiGetHandleUserData(hdc, GDI_OBJECT_TYPE_DC, (PVOID) & pDc_Attr))
865 {
866 SetLastError(ERROR_INVALID_PARAMETER);
867 return 0;
868 }
869 /*
870 if ( !pDc_Attr ||
871 iUsage == DIB_PAL_COLORS ||
872 ((pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
873 (pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
874 pConvertedInfo->bmiHeader.biCompression == BI_PNG )) )*/
875 {
876 LinesCopied = NtGdiStretchDIBitsInternal(hdc, XDest, YDest, nDestWidth, nDestHeight, XSrc,
877 YSrc, nSrcWidth, nSrcHeight, pvSafeBits, pConvertedInfo, (DWORD) iUsage, dwRop,
878 ConvertedInfoSize, cjBmpScanSize,
879 NULL);
880 }
881 if (pvSafeBits)
882 RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits);
883 if (lpBitsInfo != pConvertedInfo)
884 RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo);
885
886 return LinesCopied;
887 }
888
889 /*
890 * @unimplemented
891 */
892 DWORD
893 WINAPI
894 GetBitmapAttributes(HBITMAP hbm)
895 {
896 UNIMPLEMENTED;
897 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
898 return 0;
899 }
900
901 /*
902 * @unimplemented
903 */
904 HBITMAP
905 WINAPI
906 SetBitmapAttributes(HBITMAP hbm, DWORD dwFlags)
907 {
908 UNIMPLEMENTED;
909 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
910 return 0;
911 }
912
913 /*
914 * @unimplemented
915 */
916 HBITMAP
917 WINAPI
918 ClearBitmapAttributes(HBITMAP hbm, DWORD dwFlags)
919 {
920 UNIMPLEMENTED;
921 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
922 return 0;
923 }
924
925 /*
926 * @unimplemented
927 *
928 */
929 HBITMAP
930 WINAPI
931 GdiConvertBitmapV5(
932 HBITMAP in_format_BitMap,
933 HBITMAP src_BitMap,
934 INT bpp,
935 INT unuse)
936 {
937 /* FIXME guessing the prototypes */
938
939 /*
940 * it have create a new bitmap with desired in format,
941 * then convert it src_bitmap to new format
942 * and return it as HBITMAP
943 */
944
945 return FALSE;
946 }
947