[WIN32K]
[reactos.git] / reactos / win32ss / gdi / ntgdi / dibobj.c
1 /*
2 * PROJECT: ReactOS win32 kernel mode subsystem
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: subsystems/win32/win32k/objects/dibobj.c
5 * PURPOSE: Dib object functions
6 * PROGRAMMER:
7 */
8
9 #include <win32k.h>
10
11 #define NDEBUG
12 #include <debug.h>
13
14 static const RGBQUAD EGAColorsQuads[16] =
15 {
16 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
17 { 0x00, 0x00, 0x00, 0x00 },
18 { 0x00, 0x00, 0x80, 0x00 },
19 { 0x00, 0x80, 0x00, 0x00 },
20 { 0x00, 0x80, 0x80, 0x00 },
21 { 0x80, 0x00, 0x00, 0x00 },
22 { 0x80, 0x00, 0x80, 0x00 },
23 { 0x80, 0x80, 0x00, 0x00 },
24 { 0x80, 0x80, 0x80, 0x00 },
25 { 0xc0, 0xc0, 0xc0, 0x00 },
26 { 0x00, 0x00, 0xff, 0x00 },
27 { 0x00, 0xff, 0x00, 0x00 },
28 { 0x00, 0xff, 0xff, 0x00 },
29 { 0xff, 0x00, 0x00, 0x00 },
30 { 0xff, 0x00, 0xff, 0x00 },
31 { 0xff, 0xff, 0x00, 0x00 },
32 { 0xff, 0xff, 0xff, 0x00 }
33 };
34
35 static const RGBTRIPLE EGAColorsTriples[16] =
36 {
37 /* rgbBlue, rgbGreen, rgbRed */
38 { 0x00, 0x00, 0x00 },
39 { 0x00, 0x00, 0x80 },
40 { 0x00, 0x80, 0x00 },
41 { 0x00, 0x80, 0x80 },
42 { 0x80, 0x00, 0x00 },
43 { 0x80, 0x00, 0x80 },
44 { 0x80, 0x80, 0x00 },
45 { 0x80, 0x80, 0x80 },
46 { 0xc0, 0xc0, 0xc0 },
47 { 0x00, 0x00, 0xff },
48 { 0x00, 0xff, 0x00 },
49 { 0x00, 0xff, 0xff },
50 { 0xff, 0x00, 0x00 },
51 { 0xff, 0x00, 0xff },
52 { 0xff, 0xff, 0x00 },
53 { 0xff, 0xff, 0xff }
54 };
55
56 static const RGBQUAD DefLogPaletteQuads[20] = /* Copy of Default Logical Palette */
57 {
58 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
59 { 0x00, 0x00, 0x00, 0x00 },
60 { 0x00, 0x00, 0x80, 0x00 },
61 { 0x00, 0x80, 0x00, 0x00 },
62 { 0x00, 0x80, 0x80, 0x00 },
63 { 0x80, 0x00, 0x00, 0x00 },
64 { 0x80, 0x00, 0x80, 0x00 },
65 { 0x80, 0x80, 0x00, 0x00 },
66 { 0xc0, 0xc0, 0xc0, 0x00 },
67 { 0xc0, 0xdc, 0xc0, 0x00 },
68 { 0xf0, 0xca, 0xa6, 0x00 },
69 { 0xf0, 0xfb, 0xff, 0x00 },
70 { 0xa4, 0xa0, 0xa0, 0x00 },
71 { 0x80, 0x80, 0x80, 0x00 },
72 { 0x00, 0x00, 0xf0, 0x00 },
73 { 0x00, 0xff, 0x00, 0x00 },
74 { 0x00, 0xff, 0xff, 0x00 },
75 { 0xff, 0x00, 0x00, 0x00 },
76 { 0xff, 0x00, 0xff, 0x00 },
77 { 0xff, 0xff, 0x00, 0x00 },
78 { 0xff, 0xff, 0xff, 0x00 }
79 };
80
81 static const RGBQUAD DefLogPaletteTriples[20] = /* Copy of Default Logical Palette */
82 {
83 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
84 { 0x00, 0x00, 0x00 },
85 { 0x00, 0x00, 0x80 },
86 { 0x00, 0x80, 0x00 },
87 { 0x00, 0x80, 0x80 },
88 { 0x80, 0x00, 0x00 },
89 { 0x80, 0x00, 0x80 },
90 { 0x80, 0x80, 0x00 },
91 { 0xc0, 0xc0, 0xc0 },
92 { 0xc0, 0xdc, 0xc0 },
93 { 0xf0, 0xca, 0xa6 },
94 { 0xf0, 0xfb, 0xff },
95 { 0xa4, 0xa0, 0xa0 },
96 { 0x80, 0x80, 0x80 },
97 { 0x00, 0x00, 0xf0 },
98 { 0x00, 0xff, 0x00 },
99 { 0x00, 0xff, 0xff },
100 { 0xff, 0x00, 0x00 },
101 { 0xff, 0x00, 0xff },
102 { 0xff, 0xff, 0x00 },
103 { 0xff, 0xff, 0xff }
104 };
105
106 PPALETTE
107 NTAPI
108 CreateDIBPalette(
109 _In_ const BITMAPINFO *pbmi,
110 _In_ PDC pdc,
111 _In_ ULONG iUsage)
112 {
113 PPALETTE ppal;
114 ULONG i, cBitsPixel, cColors;
115
116 if (pbmi->bmiHeader.biSize < sizeof(BITMAPINFOHEADER))
117 {
118 PBITMAPCOREINFO pbci = (PBITMAPCOREINFO)pbmi;
119 cBitsPixel = pbci->bmciHeader.bcBitCount;
120 }
121 else
122 {
123 cBitsPixel = pbmi->bmiHeader.biBitCount;
124 }
125
126 /* Check if the colors are indexed */
127 if (cBitsPixel <= 8)
128 {
129 /* We create a "full" palette */
130 cColors = 1 << cBitsPixel;
131
132 /* Allocate the palette */
133 ppal = PALETTE_AllocPalette(PAL_INDEXED,
134 cColors,
135 NULL,
136 0,
137 0,
138 0);
139
140 /* Check if the BITMAPINFO specifies how many colors to use */
141 if ((pbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
142 (pbmi->bmiHeader.biClrUsed != 0))
143 {
144 /* This is how many colors we can actually process */
145 cColors = min(cColors, pbmi->bmiHeader.biClrUsed);
146 }
147
148 /* Check how to use the colors */
149 if (iUsage == DIB_PAL_COLORS)
150 {
151 COLORREF crColor;
152
153 /* The colors are an array of WORD indices into the DC palette */
154 PWORD pwColors = (PWORD)((PCHAR)pbmi + pbmi->bmiHeader.biSize);
155
156 /* Use the DCs palette or, if no DC is given, the default one */
157 PPALETTE ppalDC = pdc ? pdc->dclevel.ppal : gppalDefault;
158
159 /* Loop all color indices in the DIB */
160 for (i = 0; i < cColors; i++)
161 {
162 /* Get the palette index and handle wraparound when exceeding
163 the number of colors in the DC palette */
164 WORD wIndex = pwColors[i] % ppalDC->NumColors;
165
166 /* USe the RGB value from the DC palette */
167 crColor = PALETTE_ulGetRGBColorFromIndex(ppalDC, wIndex);
168 PALETTE_vSetRGBColorForIndex(ppal, i, crColor);
169 }
170 }
171 else if (iUsage == DIB_PAL_BRUSHHACK)
172 {
173 /* The colors are an array of WORD indices into the DC palette */
174 PWORD pwColors = (PWORD)((PCHAR)pbmi + pbmi->bmiHeader.biSize);
175
176 /* Loop all color indices in the DIB */
177 for (i = 0; i < cColors; i++)
178 {
179 /* Set the index directly as the RGB color, the real palette
180 containing RGB values will be calculated when the brush is
181 realized */
182 PALETTE_vSetRGBColorForIndex(ppal, i, pwColors[i]);
183 }
184
185 /* Mark the palette as a brush hack palette */
186 ppal->flFlags |= PAL_BRUSHHACK;
187 }
188 // else if (iUsage == 2)
189 // {
190 // FIXME: this one is undocumented
191 // ASSERT(FALSE);
192 // }
193 else if (pbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER))
194 {
195 /* The colors are an array of RGBQUAD values */
196 RGBQUAD *prgb = (RGBQUAD*)((PCHAR)pbmi + pbmi->bmiHeader.biSize);
197
198 // FIXME: do we need to handle PALETTEINDEX / PALETTERGB macro?
199
200 /* Loop all color indices in the DIB */
201 for (i = 0; i < cColors; i++)
202 {
203 /* Get the color value and translate it to a COLORREF */
204 RGBQUAD rgb = prgb[i];
205 COLORREF crColor = RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
206
207 /* Set the RGB value in the palette */
208 PALETTE_vSetRGBColorForIndex(ppal, i, crColor);
209 }
210 }
211 else
212 {
213 /* The colors are an array of RGBTRIPLE values */
214 RGBTRIPLE *prgb = (RGBTRIPLE*)((PCHAR)pbmi + pbmi->bmiHeader.biSize);
215
216 /* Loop all color indices in the DIB */
217 for (i = 0; i < cColors; i++)
218 {
219 /* Get the color value and translate it to a COLORREF */
220 RGBTRIPLE rgb = prgb[i];
221 COLORREF crColor = RGB(rgb.rgbtRed, rgb.rgbtGreen, rgb.rgbtBlue);
222
223 /* Set the RGB value in the palette */
224 PALETTE_vSetRGBColorForIndex(ppal, i, crColor);
225 }
226 }
227 }
228 else
229 {
230 /* This is a bitfield / RGB palette */
231 ULONG flRedMask, flGreenMask, flBlueMask;
232
233 /* Check if the DIB contains bitfield values */
234 if ((pbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
235 (pbmi->bmiHeader.biCompression == BI_BITFIELDS))
236 {
237 /* Check if we have a v4/v5 header */
238 if (pbmi->bmiHeader.biSize >= sizeof(BITMAPV4HEADER))
239 {
240 /* The masks are dedicated fields in the header */
241 PBITMAPV4HEADER pbmV4Header = (PBITMAPV4HEADER)&pbmi->bmiHeader;
242 flRedMask = pbmV4Header->bV4RedMask;
243 flGreenMask = pbmV4Header->bV4GreenMask;
244 flBlueMask = pbmV4Header->bV4BlueMask;
245 }
246 else
247 {
248 /* The masks are the first 3 values in the DIB color table */
249 PDWORD pdwColors = (PVOID)((PCHAR)pbmi + pbmi->bmiHeader.biSize);
250 flRedMask = pdwColors[0];
251 flGreenMask = pdwColors[1];
252 flBlueMask = pdwColors[2];
253 }
254 }
255 else
256 {
257 /* Check what bit depth we have. Note: optimization flags are
258 calculated in PALETTE_AllocPalette() */
259 if (cBitsPixel == 16)
260 {
261 /* This is an RGB 555 palette */
262 flRedMask = 0x7C00;
263 flGreenMask = 0x03E0;
264 flBlueMask = 0x001F;
265 }
266 else
267 {
268 /* This is an RGB 888 palette */
269 flRedMask = 0xFF0000;
270 flGreenMask = 0x00FF00;
271 flBlueMask = 0x0000FF;
272 }
273 }
274
275 /* Allocate the bitfield palette */
276 ppal = PALETTE_AllocPalette(PAL_BITFIELDS,
277 0,
278 NULL,
279 flRedMask,
280 flGreenMask,
281 flBlueMask);
282 }
283
284 /* We're done, return the palette */
285 return ppal;
286 }
287
288 // Converts a DIB to a device-dependent bitmap
289 static INT
290 FASTCALL
291 IntSetDIBits(
292 PDC DC,
293 HBITMAP hBitmap,
294 UINT StartScan,
295 UINT ScanLines,
296 CONST VOID *Bits,
297 CONST BITMAPINFO *bmi,
298 UINT ColorUse)
299 {
300 HBITMAP SourceBitmap;
301 PSURFACE psurfDst, psurfSrc;
302 INT result = 0;
303 RECT rcDst;
304 POINTL ptSrc;
305 EXLATEOBJ exlo;
306 PPALETTE ppalDIB = 0;
307
308 if (!bmi) return 0;
309
310 SourceBitmap = GreCreateBitmapEx(bmi->bmiHeader.biWidth,
311 ScanLines,
312 0,
313 BitmapFormat(bmi->bmiHeader.biBitCount,
314 bmi->bmiHeader.biCompression),
315 bmi->bmiHeader.biHeight < 0 ? BMF_TOPDOWN : 0,
316 bmi->bmiHeader.biSizeImage,
317 (PVOID)Bits,
318 0);
319 if (!SourceBitmap)
320 {
321 DPRINT1("Error: Could not create a bitmap.\n");
322 EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
323 return 0;
324 }
325
326 psurfDst = SURFACE_ShareLockSurface(hBitmap);
327 psurfSrc = SURFACE_ShareLockSurface(SourceBitmap);
328
329 if(!(psurfSrc && psurfDst))
330 {
331 DPRINT1("Error: Could not lock surfaces\n");
332 goto cleanup;
333 }
334
335 /* Create a palette for the DIB */
336 ppalDIB = CreateDIBPalette(bmi, DC, ColorUse);
337 if (!ppalDIB)
338 {
339 EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
340 goto cleanup;
341 }
342
343 /* Initialize EXLATEOBJ */
344 EXLATEOBJ_vInitialize(&exlo,
345 ppalDIB,
346 psurfDst->ppal,
347 RGB(0xff, 0xff, 0xff),
348 RGB(0xff, 0xff, 0xff), //DC->pdcattr->crBackgroundClr,
349 0); // DC->pdcattr->crForegroundClr);
350
351 rcDst.top = StartScan;
352 rcDst.left = 0;
353 rcDst.bottom = rcDst.top + ScanLines;
354 rcDst.right = psurfDst->SurfObj.sizlBitmap.cx;
355 ptSrc.x = 0;
356 ptSrc.y = 0;
357
358 result = IntEngCopyBits(&psurfDst->SurfObj,
359 &psurfSrc->SurfObj,
360 NULL,
361 &exlo.xlo,
362 &rcDst,
363 &ptSrc);
364 if(result)
365 result = ScanLines;
366
367 EXLATEOBJ_vCleanup(&exlo);
368
369 cleanup:
370 if (ppalDIB) PALETTE_ShareUnlockPalette(ppalDIB);
371 if(psurfSrc) SURFACE_ShareUnlockSurface(psurfSrc);
372 if(psurfDst) SURFACE_ShareUnlockSurface(psurfDst);
373 GreDeleteObject(SourceBitmap);
374
375 return result;
376 }
377
378 static
379 HBITMAP
380 IntGdiCreateMaskFromRLE(
381 DWORD Width,
382 DWORD Height,
383 ULONG Compression,
384 const BYTE* Bits,
385 DWORD BitsSize)
386 {
387 HBITMAP Mask;
388 DWORD x, y;
389 SURFOBJ* SurfObj;
390 UINT i = 0;
391 BYTE Data, NumPixels, ToSkip;
392
393 ASSERT((Compression == BI_RLE8) || (Compression == BI_RLE4));
394
395 /* Create the bitmap */
396 Mask = GreCreateBitmapEx(Width, Height, 0, BMF_1BPP, 0, 0, NULL, 0);
397 if (!Mask)
398 return NULL;
399
400 SurfObj = EngLockSurface((HSURF)Mask);
401 if (!SurfObj)
402 {
403 GreDeleteObject(Mask);
404 return NULL;
405 }
406 ASSERT(SurfObj->pvBits != NULL);
407
408 x = y = 0;
409
410 while (i < BitsSize)
411 {
412 NumPixels = Bits[i];
413 Data = Bits[i + 1];
414 i += 2;
415
416 if (NumPixels != 0)
417 {
418 if ((x + NumPixels) > Width)
419 NumPixels = Width - x;
420
421 if (NumPixels == 0)
422 continue;
423
424 DIB_1BPP_HLine(SurfObj, x, x + NumPixels, y, 1);
425 x += NumPixels;
426 continue;
427 }
428
429 if (Data < 3)
430 {
431 switch (Data)
432 {
433 case 0:
434 /* End of line */
435 y++;
436 if (y == Height)
437 goto done;
438 x = 0;
439 break;
440 case 1:
441 /* End of file */
442 goto done;
443 case 2:
444 /* Jump */
445 if (i >= (BitsSize - 1))
446 goto done;
447 x += Bits[i];
448 if (x > Width)
449 x = Width;
450 y += Bits[i + 1];
451 if (y >= Height)
452 goto done;
453 i += 2;
454 break;
455 }
456 /* Done for this run */
457 continue;
458 }
459
460 /* Embedded data into the RLE */
461 NumPixels = Data;
462 if (Compression == BI_RLE8)
463 ToSkip = NumPixels;
464 else
465 ToSkip = (NumPixels / 2) + (NumPixels & 1);
466
467 if ((i + ToSkip) > BitsSize)
468 goto done;
469 ToSkip = (ToSkip + 1) & ~1;
470
471 if ((x + NumPixels) > Width)
472 NumPixels = Width - x;
473
474 if (NumPixels != 0)
475 {
476 DIB_1BPP_HLine(SurfObj, x, x + NumPixels, y, 1);
477 x += NumPixels;
478 }
479 i += ToSkip;
480 }
481
482 done:
483 EngUnlockSurface(SurfObj);
484 return Mask;
485 }
486
487 W32KAPI
488 INT
489 APIENTRY
490 NtGdiSetDIBitsToDeviceInternal(
491 IN HDC hDC,
492 IN INT XDest,
493 IN INT YDest,
494 IN DWORD Width,
495 IN DWORD Height,
496 IN INT XSrc,
497 IN INT YSrc,
498 IN DWORD StartScan,
499 IN DWORD ScanLines,
500 IN LPBYTE Bits,
501 IN LPBITMAPINFO bmi,
502 IN DWORD ColorUse,
503 IN UINT cjMaxBits,
504 IN UINT cjMaxInfo,
505 IN BOOL bTransformCoordinates,
506 IN OPTIONAL HANDLE hcmXform)
507 {
508 INT ret = 0;
509 NTSTATUS Status = STATUS_SUCCESS;
510 PDC pDC;
511 HBITMAP hSourceBitmap = NULL, hMaskBitmap = NULL;
512 SURFOBJ *pDestSurf, *pSourceSurf = NULL, *pMaskSurf = NULL;
513 SURFACE *pSurf;
514 RECTL rcDest;
515 POINTL ptSource;
516 //INT DIBWidth;
517 SIZEL SourceSize;
518 EXLATEOBJ exlo;
519 PPALETTE ppalDIB = NULL;
520 LPBITMAPINFO pbmiSafe;
521
522 if (!Bits) return 0;
523
524 pbmiSafe = ExAllocatePoolWithTag(PagedPool, cjMaxInfo, 'pmTG');
525 if (!pbmiSafe) return 0;
526
527 _SEH2_TRY
528 {
529 ProbeForRead(bmi, cjMaxInfo, 1);
530 ProbeForRead(Bits, cjMaxBits, 1);
531 RtlCopyMemory(pbmiSafe, bmi, cjMaxInfo);
532 bmi = pbmiSafe;
533 }
534 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
535 {
536 Status = _SEH2_GetExceptionCode();
537 }
538 _SEH2_END
539
540 if (!NT_SUCCESS(Status))
541 {
542 goto Exit2;
543 }
544
545 ScanLines = min(ScanLines, abs(bmi->bmiHeader.biHeight) - StartScan);
546
547 pDC = DC_LockDc(hDC);
548 if (!pDC)
549 {
550 EngSetLastError(ERROR_INVALID_HANDLE);
551 goto Exit2;
552 }
553
554 if (pDC->dctype == DC_TYPE_INFO)
555 {
556 DC_UnlockDc(pDC);
557 goto Exit;
558 }
559
560 rcDest.left = XDest;
561 rcDest.top = YDest;
562 if (bTransformCoordinates)
563 {
564 IntLPtoDP(pDC, (LPPOINT)&rcDest, 2);
565 }
566 rcDest.left += pDC->ptlDCOrig.x;
567 rcDest.top += pDC->ptlDCOrig.y;
568 rcDest.right = rcDest.left + Width;
569 rcDest.bottom = rcDest.top + Height;
570 rcDest.top += StartScan;
571
572 ptSource.x = XSrc;
573 ptSource.y = YSrc;
574
575 SourceSize.cx = bmi->bmiHeader.biWidth;
576 SourceSize.cy = ScanLines;
577
578 //DIBWidth = WIDTH_BYTES_ALIGN32(SourceSize.cx, bmi->bmiHeader.biBitCount);
579
580 hSourceBitmap = GreCreateBitmapEx(bmi->bmiHeader.biWidth,
581 ScanLines,
582 0,
583 BitmapFormat(bmi->bmiHeader.biBitCount,
584 bmi->bmiHeader.biCompression),
585 bmi->bmiHeader.biHeight < 0 ? BMF_TOPDOWN : 0,
586 bmi->bmiHeader.biSizeImage,
587 Bits,
588 0);
589
590 if (!hSourceBitmap)
591 {
592 EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
593 Status = STATUS_NO_MEMORY;
594 goto Exit;
595 }
596
597 pSourceSurf = EngLockSurface((HSURF)hSourceBitmap);
598 if (!pSourceSurf)
599 {
600 Status = STATUS_UNSUCCESSFUL;
601 goto Exit;
602 }
603
604 /* HACK: If this is a RLE bitmap, only the relevant pixels must be set. */
605 if ((bmi->bmiHeader.biCompression == BI_RLE8) || (bmi->bmiHeader.biCompression == BI_RLE4))
606 {
607 ASSERT(ScanLines == bmi->bmiHeader.biHeight);
608 hMaskBitmap = IntGdiCreateMaskFromRLE(bmi->bmiHeader.biWidth,
609 ScanLines,
610 bmi->bmiHeader.biCompression,
611 Bits,
612 cjMaxBits);
613 if (!hMaskBitmap)
614 {
615 EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
616 Status = STATUS_NO_MEMORY;
617 goto Exit;
618 }
619 pMaskSurf = EngLockSurface((HSURF)hMaskBitmap);
620 if (!pMaskSurf)
621 {
622 Status = STATUS_UNSUCCESSFUL;
623 goto Exit;
624 }
625 }
626
627 /* Create a palette for the DIB */
628 ppalDIB = CreateDIBPalette(bmi, pDC, ColorUse);
629 if (!ppalDIB)
630 {
631 EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
632 Status = STATUS_NO_MEMORY;
633 goto Exit;
634 }
635
636 /* This is actually a blit */
637 DC_vPrepareDCsForBlit(pDC, &rcDest, NULL, NULL);
638 pSurf = pDC->dclevel.pSurface;
639 if (!pSurf)
640 {
641 DC_vFinishBlit(pDC, NULL);
642 ret = ScanLines;
643 goto Exit;
644 }
645
646 ASSERT(pSurf->ppal);
647
648 /* Initialize EXLATEOBJ */
649 EXLATEOBJ_vInitialize(&exlo,
650 ppalDIB,
651 pSurf->ppal,
652 RGB(0xff, 0xff, 0xff),
653 pDC->pdcattr->crBackgroundClr,
654 pDC->pdcattr->crForegroundClr);
655
656 pDestSurf = &pSurf->SurfObj;
657
658 /* Copy the bits */
659 DPRINT("BitsToDev with dstsurf=(%d|%d) (%d|%d), src=(%d|%d) w=%d h=%d\n",
660 rcDest.left, rcDest.top, rcDest.right, rcDest.bottom,
661 ptSource.x, ptSource.y, SourceSize.cx, SourceSize.cy);
662 Status = IntEngBitBlt(pDestSurf,
663 pSourceSurf,
664 pMaskSurf,
665 &pDC->co.ClipObj,
666 &exlo.xlo,
667 &rcDest,
668 &ptSource,
669 pMaskSurf ? &ptSource : NULL,
670 NULL,
671 NULL,
672 pMaskSurf ? ROP4_MASK : ROP4_FROM_INDEX(R3_OPINDEX_SRCCOPY));
673
674 /* Cleanup EXLATEOBJ */
675 EXLATEOBJ_vCleanup(&exlo);
676
677 /* We're done */
678 DC_vFinishBlit(pDC, NULL);
679
680 Exit:
681 if (NT_SUCCESS(Status))
682 {
683 ret = ScanLines;
684 }
685
686 if (ppalDIB) PALETTE_ShareUnlockPalette(ppalDIB);
687
688 if (pSourceSurf) EngUnlockSurface(pSourceSurf);
689 if (hSourceBitmap) EngDeleteSurface((HSURF)hSourceBitmap);
690 if (pMaskSurf) EngUnlockSurface(pMaskSurf);
691 if (hMaskBitmap) EngDeleteSurface((HSURF)hMaskBitmap);
692 DC_UnlockDc(pDC);
693 Exit2:
694 ExFreePoolWithTag(pbmiSafe, 'pmTG');
695 return ret;
696 }
697
698
699 /* Converts a device-dependent bitmap to a DIB */
700 INT
701 APIENTRY
702 GreGetDIBitsInternal(
703 HDC hDC,
704 HBITMAP hBitmap,
705 UINT StartScan,
706 UINT ScanLines,
707 LPBYTE Bits,
708 LPBITMAPINFO Info,
709 UINT Usage,
710 UINT MaxBits,
711 UINT MaxInfo)
712 {
713 BITMAPCOREINFO* pbmci = NULL;
714 PSURFACE psurf = NULL;
715 PDC pDC;
716 LONG width, height;
717 WORD planes, bpp;
718 DWORD compr, size ;
719 USHORT i;
720 int bitmap_type;
721 RGBQUAD* rgbQuads;
722 VOID* colorPtr;
723
724 DPRINT("Entered NtGdiGetDIBitsInternal()\n");
725
726 if ((Usage && Usage != DIB_PAL_COLORS) || !Info || !hBitmap)
727 return 0;
728
729 colorPtr = (LPBYTE)Info + Info->bmiHeader.biSize;
730 rgbQuads = colorPtr;
731
732 bitmap_type = DIB_GetBitmapInfo(&Info->bmiHeader,
733 &width,
734 &height,
735 &planes,
736 &bpp,
737 &compr,
738 &size);
739 if(bitmap_type == -1)
740 {
741 DPRINT("Wrong bitmap format\n");
742 EngSetLastError(ERROR_INVALID_PARAMETER);
743 return 0;
744 }
745 else if(bitmap_type == 0)
746 {
747 /* We need a BITMAPINFO to create a DIB, but we have to fill
748 * the BITMAPCOREINFO we're provided */
749 pbmci = (BITMAPCOREINFO*)Info;
750 Info = DIB_ConvertBitmapInfo((BITMAPINFO*)pbmci, Usage);
751 if(Info == NULL)
752 {
753 DPRINT1("Error, could not convert the BITMAPCOREINFO!\n");
754 return 0;
755 }
756 rgbQuads = Info->bmiColors;
757 }
758
759 pDC = DC_LockDc(hDC);
760 if (pDC == NULL || pDC->dctype == DC_TYPE_INFO)
761 {
762 ScanLines = 0;
763 goto done;
764 }
765
766 /* Get a pointer to the source bitmap object */
767 psurf = SURFACE_ShareLockSurface(hBitmap);
768 if (psurf == NULL)
769 {
770 ScanLines = 0;
771 goto done;
772 }
773
774 /* Fill in the structure */
775 switch(bpp)
776 {
777 case 0: /* Only info */
778 Info->bmiHeader.biWidth = psurf->SurfObj.sizlBitmap.cx;
779 Info->bmiHeader.biHeight = (psurf->SurfObj.fjBitmap & BMF_TOPDOWN) ?
780 -psurf->SurfObj.sizlBitmap.cy :
781 psurf->SurfObj.sizlBitmap.cy;;
782 Info->bmiHeader.biPlanes = 1;
783 Info->bmiHeader.biBitCount = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
784 Info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes( Info->bmiHeader.biWidth,
785 Info->bmiHeader.biHeight,
786 Info->bmiHeader.biBitCount);
787 if(psurf->hSecure)
788 {
789 switch(Info->bmiHeader.biBitCount)
790 {
791 case 16:
792 case 32:
793 Info->bmiHeader.biCompression = BI_BITFIELDS;
794 break;
795 default:
796 Info->bmiHeader.biCompression = BI_RGB;
797 break;
798 }
799 }
800 else if(Info->bmiHeader.biBitCount > 8)
801 {
802 Info->bmiHeader.biCompression = BI_BITFIELDS;
803 }
804 else
805 {
806 Info->bmiHeader.biCompression = BI_RGB;
807 }
808 Info->bmiHeader.biXPelsPerMeter = 0;
809 Info->bmiHeader.biYPelsPerMeter = 0;
810 Info->bmiHeader.biClrUsed = 0;
811 Info->bmiHeader.biClrImportant = 0;
812 ScanLines = abs(Info->bmiHeader.biHeight);
813 goto done;
814
815 case 1:
816 case 4:
817 case 8:
818 Info->bmiHeader.biClrUsed = 0;
819
820 /* If the bitmap if a DIB section and has the same format than what
821 * we're asked, go ahead! */
822 if((psurf->hSecure) &&
823 (BitsPerFormat(psurf->SurfObj.iBitmapFormat) == bpp))
824 {
825 if(Usage == DIB_RGB_COLORS)
826 {
827 ULONG colors = min(psurf->ppal->NumColors, 256);
828 if(colors != 256) Info->bmiHeader.biClrUsed = colors;
829 for(i = 0; i < colors; i++)
830 {
831 rgbQuads[i].rgbRed = psurf->ppal->IndexedColors[i].peRed;
832 rgbQuads[i].rgbGreen = psurf->ppal->IndexedColors[i].peGreen;
833 rgbQuads[i].rgbBlue = psurf->ppal->IndexedColors[i].peBlue;
834 rgbQuads[i].rgbReserved = 0;
835 }
836 }
837 else
838 {
839 for(i = 0; i < 256; i++)
840 ((WORD*)rgbQuads)[i] = i;
841 }
842 }
843 else
844 {
845 if(Usage == DIB_PAL_COLORS)
846 {
847 for(i = 0; i < 256; i++)
848 {
849 ((WORD*)rgbQuads)[i] = i;
850 }
851 }
852 else if(bpp > 1 && bpp == BitsPerFormat(psurf->SurfObj.iBitmapFormat))
853 {
854 /* For color DDBs in native depth (mono DDBs always have
855 a black/white palette):
856 Generate the color map from the selected palette */
857 PPALETTE pDcPal = PALETTE_ShareLockPalette(pDC->dclevel.hpal);
858 if(!pDcPal)
859 {
860 ScanLines = 0 ;
861 goto done ;
862 }
863 for (i = 0; i < pDcPal->NumColors; i++)
864 {
865 rgbQuads[i].rgbRed = pDcPal->IndexedColors[i].peRed;
866 rgbQuads[i].rgbGreen = pDcPal->IndexedColors[i].peGreen;
867 rgbQuads[i].rgbBlue = pDcPal->IndexedColors[i].peBlue;
868 rgbQuads[i].rgbReserved = 0;
869 }
870 PALETTE_ShareUnlockPalette(pDcPal);
871 }
872 else
873 {
874 switch (bpp)
875 {
876 case 1:
877 rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen = rgbQuads[0].rgbBlue = 0;
878 rgbQuads[0].rgbReserved = 0;
879 rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen = rgbQuads[1].rgbBlue = 0xff;
880 rgbQuads[1].rgbReserved = 0;
881 break;
882
883 case 4:
884 RtlCopyMemory(rgbQuads, EGAColorsQuads, sizeof(EGAColorsQuads));
885 break;
886
887 case 8:
888 {
889 INT r, g, b;
890 RGBQUAD *color;
891 memcpy(rgbQuads, DefLogPaletteQuads,
892 10 * sizeof(RGBQUAD));
893 memcpy(rgbQuads + 246, DefLogPaletteQuads + 10,
894 10 * sizeof(RGBQUAD));
895 color = rgbQuads + 10;
896 for(r = 0; r <= 5; r++) /* FIXME */
897 {
898 for(g = 0; g <= 5; g++)
899 {
900 for(b = 0; b <= 5; b++)
901 {
902 color->rgbRed = (r * 0xff) / 5;
903 color->rgbGreen = (g * 0xff) / 5;
904 color->rgbBlue = (b * 0xff) / 5;
905 color->rgbReserved = 0;
906 color++;
907 }
908 }
909 }
910 }
911 }
912 }
913 }
914 break;
915
916 case 15:
917 if (Info->bmiHeader.biCompression == BI_BITFIELDS)
918 {
919 ((PDWORD)Info->bmiColors)[0] = 0x7c00;
920 ((PDWORD)Info->bmiColors)[1] = 0x03e0;
921 ((PDWORD)Info->bmiColors)[2] = 0x001f;
922 }
923 break;
924
925 case 16:
926 if (Info->bmiHeader.biCompression == BI_BITFIELDS)
927 {
928 if (psurf->hSecure)
929 {
930 ((PDWORD)Info->bmiColors)[0] = psurf->ppal->RedMask;
931 ((PDWORD)Info->bmiColors)[1] = psurf->ppal->GreenMask;
932 ((PDWORD)Info->bmiColors)[2] = psurf->ppal->BlueMask;
933 }
934 else
935 {
936 ((PDWORD)Info->bmiColors)[0] = 0xf800;
937 ((PDWORD)Info->bmiColors)[1] = 0x07e0;
938 ((PDWORD)Info->bmiColors)[2] = 0x001f;
939 }
940 }
941 break;
942
943 case 24:
944 case 32:
945 if (Info->bmiHeader.biCompression == BI_BITFIELDS)
946 {
947 if (psurf->hSecure)
948 {
949 ((PDWORD)Info->bmiColors)[0] = psurf->ppal->RedMask;
950 ((PDWORD)Info->bmiColors)[1] = psurf->ppal->GreenMask;
951 ((PDWORD)Info->bmiColors)[2] = psurf->ppal->BlueMask;
952 }
953 else
954 {
955 ((PDWORD)Info->bmiColors)[0] = 0xff0000;
956 ((PDWORD)Info->bmiColors)[1] = 0x00ff00;
957 ((PDWORD)Info->bmiColors)[2] = 0x0000ff;
958 }
959 }
960 break;
961 }
962 Info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(width, height, bpp);
963
964 if(Bits && ScanLines)
965 {
966 /* Create a DIBSECTION, blt it, profit */
967 PVOID pDIBits ;
968 HBITMAP hBmpDest;
969 PSURFACE psurfDest;
970 EXLATEOBJ exlo;
971 RECT rcDest;
972 POINTL srcPoint;
973 BOOL ret ;
974
975 if (StartScan > (ULONG)psurf->SurfObj.sizlBitmap.cy)
976 {
977 ScanLines = 0;
978 goto done;
979 }
980 else
981 {
982 ScanLines = min(ScanLines, psurf->SurfObj.sizlBitmap.cy - StartScan);
983 }
984
985 /* Fixup values */
986 Info->bmiHeader.biWidth = psurf->SurfObj.sizlBitmap.cx;
987 Info->bmiHeader.biHeight = (height < 0) ?
988 -(LONG)ScanLines : ScanLines;
989 /* Create the DIB */
990 hBmpDest = DIB_CreateDIBSection(pDC, Info, Usage, &pDIBits, NULL, 0, 0);
991 /* Restore them */
992 Info->bmiHeader.biWidth = width;
993 Info->bmiHeader.biHeight = height;
994
995 if(!hBmpDest)
996 {
997 DPRINT1("Unable to create a DIB Section!\n");
998 EngSetLastError(ERROR_INVALID_PARAMETER);
999 ScanLines = 0;
1000 goto done ;
1001 }
1002
1003 psurfDest = SURFACE_ShareLockSurface(hBmpDest);
1004
1005 RECTL_vSetRect(&rcDest, 0, 0, psurf->SurfObj.sizlBitmap.cx, ScanLines);
1006
1007 srcPoint.x = 0;
1008
1009 if(height < 0)
1010 {
1011 srcPoint.y = 0;
1012
1013 if(ScanLines <= StartScan)
1014 {
1015 ScanLines = 1;
1016 SURFACE_ShareUnlockSurface(psurfDest);
1017 GreDeleteObject(hBmpDest);
1018 goto done;
1019 }
1020
1021 ScanLines -= StartScan;
1022 }
1023 else
1024 {
1025 srcPoint.y = StartScan;
1026 }
1027
1028 EXLATEOBJ_vInitialize(&exlo, psurf->ppal, psurfDest->ppal, 0xffffff, 0xffffff, 0);
1029
1030 ret = IntEngCopyBits(&psurfDest->SurfObj,
1031 &psurf->SurfObj,
1032 NULL,
1033 &exlo.xlo,
1034 &rcDest,
1035 &srcPoint);
1036
1037 SURFACE_ShareUnlockSurface(psurfDest);
1038
1039 if(!ret)
1040 ScanLines = 0;
1041 else
1042 {
1043 RtlCopyMemory(Bits, pDIBits, DIB_GetDIBImageBytes (width, ScanLines, bpp));
1044 }
1045
1046 GreDeleteObject(hBmpDest);
1047 EXLATEOBJ_vCleanup(&exlo);
1048 }
1049 else ScanLines = abs(height);
1050
1051 done:
1052
1053 if(pDC) DC_UnlockDc(pDC);
1054 if(psurf) SURFACE_ShareUnlockSurface(psurf);
1055 if(pbmci) DIB_FreeConvertedBitmapInfo(Info, (BITMAPINFO*)pbmci, Usage);
1056
1057 return ScanLines;
1058 }
1059
1060 INT
1061 APIENTRY
1062 NtGdiGetDIBitsInternal(
1063 _In_ HDC hdc,
1064 _In_ HBITMAP hbm,
1065 _In_ UINT iStartScan,
1066 _In_ UINT cScans,
1067 _Out_opt_ LPBYTE pjBits,
1068 _Inout_ LPBITMAPINFO pbmiUser,
1069 _In_ UINT iUsage,
1070 _In_ UINT cjMaxBits,
1071 _In_ UINT cjMaxInfo)
1072 {
1073 PBITMAPINFO pbmi;
1074 HANDLE hSecure = NULL;
1075 INT iResult = 0;
1076 UINT cjAlloc;
1077
1078 /* Check for bad iUsage */
1079 if (iUsage > 2) return 0;
1080
1081 /* Check if the size of the bitmap info is large enough */
1082 if (cjMaxInfo < sizeof(BITMAPCOREHEADER))
1083 {
1084 return 0;
1085 }
1086
1087 /* Use maximum size */
1088 cjMaxInfo = min(cjMaxInfo, sizeof(BITMAPV5HEADER) + 256 * sizeof(RGBQUAD));
1089
1090 // HACK: the underlying code sucks and doesn't care for the size, so we
1091 // give it the maximum ever needed
1092 cjAlloc = sizeof(BITMAPV5HEADER) + 256 * sizeof(RGBQUAD);
1093
1094 /* Allocate a buffer the bitmapinfo */
1095 pbmi = ExAllocatePoolWithTag(PagedPool, cjAlloc, 'imBG');
1096 if (!pbmi)
1097 {
1098 /* Fail */
1099 return 0;
1100 }
1101
1102 /* Use SEH */
1103 _SEH2_TRY
1104 {
1105 /* Probe and copy the BITMAPINFO */
1106 ProbeForRead(pbmiUser, cjMaxInfo, 1);
1107 RtlCopyMemory(pbmi, pbmiUser, cjMaxInfo);
1108 }
1109 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1110 {
1111 _SEH2_YIELD(goto cleanup;)
1112 }
1113 _SEH2_END;
1114
1115 /* Check if the header size is large enough */
1116 if ((pbmi->bmiHeader.biSize < sizeof(BITMAPCOREHEADER)) ||
1117 (pbmi->bmiHeader.biSize > cjMaxInfo))
1118 {
1119 goto cleanup;
1120 }
1121
1122 /* Check if the caller provided bitmap bits */
1123 if (pjBits)
1124 {
1125 /* Secure the user mode memory */
1126 hSecure = EngSecureMem(pjBits, cjMaxBits);
1127 if (!hSecure)
1128 {
1129 goto cleanup;
1130 }
1131 }
1132
1133 /* Now call the internal function */
1134 iResult = GreGetDIBitsInternal(hdc,
1135 hbm,
1136 iStartScan,
1137 cScans,
1138 pjBits,
1139 pbmi,
1140 iUsage,
1141 cjMaxBits,
1142 cjMaxInfo);
1143
1144 /* Check for success */
1145 if (iResult)
1146 {
1147 /* Use SEH to copy back to user mode */
1148 _SEH2_TRY
1149 {
1150 /* Copy the data back */
1151 ProbeForWrite(pbmiUser, cjMaxInfo, 1);
1152 RtlCopyMemory(pbmiUser, pbmi, cjMaxInfo);
1153 }
1154 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1155 {
1156 /* Ignore */
1157 }
1158 _SEH2_END;
1159 }
1160
1161 cleanup:
1162 if (hSecure) EngUnsecureMem(hSecure);
1163 ExFreePoolWithTag(pbmi, 'imBG');
1164
1165 return iResult;
1166 }
1167
1168
1169 #define ROP_TO_ROP4(Rop) ((Rop) >> 16)
1170
1171 W32KAPI
1172 INT
1173 APIENTRY
1174 NtGdiStretchDIBitsInternal(
1175 IN HDC hdc,
1176 IN INT xDst,
1177 IN INT yDst,
1178 IN INT cxDst,
1179 IN INT cyDst,
1180 IN INT xSrc,
1181 IN INT ySrc,
1182 IN INT cxSrc,
1183 IN INT cySrc,
1184 IN OPTIONAL LPBYTE pjInit,
1185 IN LPBITMAPINFO pbmi,
1186 IN DWORD dwUsage,
1187 IN DWORD dwRop, // MS ntgdi.h says dwRop4(?)
1188 IN UINT cjMaxInfo,
1189 IN UINT cjMaxBits,
1190 IN HANDLE hcmXform)
1191 {
1192 BOOL bResult = FALSE;
1193 SIZEL sizel;
1194 RECTL rcSrc, rcDst;
1195 PDC pdc;
1196 HBITMAP hbmTmp = 0;
1197 PSURFACE psurfTmp = 0, psurfDst = 0;
1198 PPALETTE ppalDIB = 0;
1199 EXLATEOBJ exlo;
1200 PVOID pvBits;
1201
1202 if (!(pdc = DC_LockDc(hdc)))
1203 {
1204 EngSetLastError(ERROR_INVALID_HANDLE);
1205 return 0;
1206 }
1207
1208 /* Check for info / mem DC without surface */
1209 if (!pdc->dclevel.pSurface)
1210 {
1211 DC_UnlockDc(pdc);
1212 // CHECKME
1213 return TRUE;
1214 }
1215
1216 /* Transform dest size */
1217 sizel.cx = cxDst;
1218 sizel.cy = cyDst;
1219 IntLPtoDP(pdc, (POINTL*)&sizel, 1);
1220 DC_UnlockDc(pdc);
1221
1222 /* Check if we can use NtGdiSetDIBitsToDeviceInternal */
1223 if (sizel.cx == cxSrc && sizel.cy == cySrc && dwRop == SRCCOPY)
1224 {
1225 /* Yes, we can! */
1226 return NtGdiSetDIBitsToDeviceInternal(hdc,
1227 xDst,
1228 yDst,
1229 cxDst,
1230 cyDst,
1231 xSrc,
1232 ySrc,
1233 0,
1234 cySrc,
1235 pjInit,
1236 pbmi,
1237 dwUsage,
1238 cjMaxBits,
1239 cjMaxInfo,
1240 TRUE,
1241 hcmXform);
1242 }
1243
1244 if (pjInit && (cjMaxBits > 0))
1245 {
1246 pvBits = ExAllocatePoolWithTag(PagedPool, cjMaxBits, 'pmeT');
1247 if (!pvBits)
1248 {
1249 return 0;
1250 }
1251
1252 _SEH2_TRY
1253 {
1254 ProbeForRead(pjInit, cjMaxBits, 1);
1255 RtlCopyMemory(pvBits, pjInit, cjMaxBits);
1256 }
1257 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1258 {
1259 ExFreePoolWithTag(pvBits, 'pmeT');
1260 _SEH2_YIELD(return 0);
1261 }
1262 _SEH2_END
1263 }
1264 else
1265 {
1266 pvBits = NULL;
1267 }
1268
1269 /* FIXME: Locking twice is cheesy, coord tranlation in UM will fix it */
1270 if (!(pdc = DC_LockDc(hdc)))
1271 {
1272 DPRINT1("Could not lock dc\n");
1273 EngSetLastError(ERROR_INVALID_HANDLE);
1274 goto cleanup;
1275 }
1276
1277 /* Calculate source and destination rect */
1278 rcSrc.left = xSrc;
1279 rcSrc.top = ySrc;
1280 rcSrc.right = xSrc + abs(cxSrc);
1281 rcSrc.bottom = ySrc + abs(cySrc);
1282 rcDst.left = xDst;
1283 rcDst.top = yDst;
1284 rcDst.right = rcDst.left + cxDst;
1285 rcDst.bottom = rcDst.top + cyDst;
1286 IntLPtoDP(pdc, (POINTL*)&rcDst, 2);
1287 RECTL_vOffsetRect(&rcDst, pdc->ptlDCOrig.x, pdc->ptlDCOrig.y);
1288
1289 hbmTmp = GreCreateBitmapEx(pbmi->bmiHeader.biWidth,
1290 pbmi->bmiHeader.biHeight,
1291 0,
1292 BitmapFormat(pbmi->bmiHeader.biBitCount,
1293 pbmi->bmiHeader.biCompression),
1294 pbmi->bmiHeader.biHeight < 0 ? BMF_TOPDOWN : 0,
1295 pbmi->bmiHeader.biSizeImage,
1296 pvBits,
1297 0);
1298
1299 if (!hbmTmp)
1300 {
1301 bResult = FALSE;
1302 goto cleanup;
1303 }
1304
1305 psurfTmp = SURFACE_ShareLockSurface(hbmTmp);
1306 if (!psurfTmp)
1307 {
1308 bResult = FALSE;
1309 goto cleanup;
1310 }
1311
1312 /* Create a palette for the DIB */
1313 ppalDIB = CreateDIBPalette(pbmi, pdc, dwUsage);
1314 if (!ppalDIB)
1315 {
1316 bResult = FALSE;
1317 goto cleanup;
1318 }
1319
1320 /* Prepare DC for blit */
1321 DC_vPrepareDCsForBlit(pdc, &rcDst, NULL, NULL);
1322
1323 psurfDst = pdc->dclevel.pSurface;
1324
1325 /* Initialize XLATEOBJ */
1326 EXLATEOBJ_vInitialize(&exlo,
1327 ppalDIB,
1328 psurfDst->ppal,
1329 RGB(0xff, 0xff, 0xff),
1330 pdc->pdcattr->crBackgroundClr,
1331 pdc->pdcattr->crForegroundClr);
1332
1333 /* Perform the stretch operation */
1334 bResult = IntEngStretchBlt(&psurfDst->SurfObj,
1335 &psurfTmp->SurfObj,
1336 NULL,
1337 &pdc->co.ClipObj,
1338 &exlo.xlo,
1339 &pdc->dclevel.ca,
1340 &rcDst,
1341 &rcSrc,
1342 NULL,
1343 &pdc->eboFill.BrushObject,
1344 NULL,
1345 ROP_TO_ROP4(dwRop));
1346
1347 /* Cleanup */
1348 DC_vFinishBlit(pdc, NULL);
1349 EXLATEOBJ_vCleanup(&exlo);
1350 cleanup:
1351 if (ppalDIB) PALETTE_ShareUnlockPalette(ppalDIB);
1352 if (psurfTmp) SURFACE_ShareUnlockSurface(psurfTmp);
1353 if (hbmTmp) GreDeleteObject(hbmTmp);
1354 if (pdc) DC_UnlockDc(pdc);
1355 if (pvBits) ExFreePoolWithTag(pvBits, 'pmeT');
1356
1357 return bResult;
1358 }
1359
1360
1361 HBITMAP
1362 FASTCALL
1363 IntCreateDIBitmap(
1364 PDC Dc,
1365 INT width,
1366 INT height,
1367 UINT bpp,
1368 DWORD init,
1369 LPBYTE bits,
1370 PBITMAPINFO data,
1371 DWORD coloruse)
1372 {
1373 HBITMAP handle;
1374 BOOL fColor;
1375
1376 // Check if we should create a monochrome or color bitmap. We create a monochrome bitmap only if it has exactly 2
1377 // colors, which are black followed by white, nothing else. In all other cases, we create a color bitmap.
1378
1379 if (bpp != 1) fColor = TRUE;
1380 else if ((coloruse != DIB_RGB_COLORS) || (init != CBM_INIT) || !data) fColor = FALSE;
1381 else
1382 {
1383 const RGBQUAD *rgb = (RGBQUAD*)((PBYTE)data + data->bmiHeader.biSize);
1384 DWORD col = RGB(rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue);
1385
1386 // Check if the first color of the colormap is black
1387 if ((col == RGB(0, 0, 0)))
1388 {
1389 rgb++;
1390 col = RGB(rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue);
1391
1392 // If the second color is white, create a monochrome bitmap
1393 fColor = (col != RGB(0xff,0xff,0xff));
1394 }
1395 else fColor = TRUE;
1396 }
1397
1398 // Now create the bitmap
1399 if (fColor)
1400 {
1401 handle = IntCreateCompatibleBitmap(Dc, width, height);
1402 }
1403 else
1404 {
1405 handle = GreCreateBitmap(width,
1406 height,
1407 1,
1408 1,
1409 NULL);
1410 }
1411
1412 if (height < 0)
1413 height = -height;
1414
1415 if (NULL != handle && CBM_INIT == init)
1416 {
1417 IntSetDIBits(Dc, handle, 0, height, bits, data, coloruse);
1418 }
1419
1420 return handle;
1421 }
1422
1423 // The CreateDIBitmap function creates a device-dependent bitmap (DDB) from a DIB and, optionally, sets the bitmap bits
1424 // The DDB that is created will be whatever bit depth your reference DC is
1425 HBITMAP
1426 APIENTRY
1427 NtGdiCreateDIBitmapInternal(
1428 IN HDC hDc,
1429 IN INT cx,
1430 IN INT cy,
1431 IN DWORD fInit,
1432 IN OPTIONAL LPBYTE pjInit,
1433 IN OPTIONAL LPBITMAPINFO pbmi,
1434 IN DWORD iUsage,
1435 IN UINT cjMaxInitInfo,
1436 IN UINT cjMaxBits,
1437 IN FLONG fl,
1438 IN HANDLE hcmXform)
1439 {
1440 NTSTATUS Status = STATUS_SUCCESS;
1441 PBYTE safeBits = NULL;
1442 HBITMAP hbmResult = NULL;
1443
1444 if(pjInit && (fInit == CBM_INIT))
1445 {
1446 if (cjMaxBits == 0) return NULL;
1447 safeBits = ExAllocatePoolWithTag(PagedPool, cjMaxBits, TAG_DIB);
1448 if(!safeBits)
1449 {
1450 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
1451 return NULL;
1452 }
1453 }
1454
1455 _SEH2_TRY
1456 {
1457 if(pbmi) ProbeForRead(pbmi, cjMaxInitInfo, 1);
1458 if(pjInit && (fInit == CBM_INIT))
1459 {
1460 ProbeForRead(pjInit, cjMaxBits, 1);
1461 RtlCopyMemory(safeBits, pjInit, cjMaxBits);
1462 }
1463 }
1464 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1465 {
1466 Status = _SEH2_GetExceptionCode();
1467 }
1468 _SEH2_END
1469
1470 if(!NT_SUCCESS(Status))
1471 {
1472 SetLastNtError(Status);
1473 goto cleanup;
1474 }
1475
1476 hbmResult = GreCreateDIBitmapInternal(hDc,
1477 cx,
1478 cy,
1479 fInit,
1480 safeBits,
1481 pbmi,
1482 iUsage,
1483 fl,
1484 cjMaxBits,
1485 hcmXform);
1486
1487 cleanup:
1488 if (safeBits) ExFreePoolWithTag(safeBits, TAG_DIB);
1489 return hbmResult;
1490 }
1491
1492 HBITMAP
1493 NTAPI
1494 GreCreateDIBitmapInternal(
1495 IN HDC hDc,
1496 IN INT cx,
1497 IN INT cy,
1498 IN DWORD fInit,
1499 IN OPTIONAL LPBYTE pjInit,
1500 IN OPTIONAL PBITMAPINFO pbmi,
1501 IN DWORD iUsage,
1502 IN FLONG fl,
1503 IN UINT cjMaxBits,
1504 IN HANDLE hcmXform)
1505 {
1506 PDC Dc;
1507 HBITMAP Bmp;
1508 WORD bpp;
1509 HDC hdcDest;
1510
1511 if (!hDc) /* 1bpp monochrome bitmap */
1512 {
1513 // Should use System Bitmap DC hSystemBM, with CreateCompatibleDC for this.
1514 hdcDest = NtGdiCreateCompatibleDC(0);
1515 if(!hdcDest)
1516 {
1517 return NULL;
1518 }
1519 }
1520 else
1521 {
1522 hdcDest = hDc;
1523 }
1524
1525 Dc = DC_LockDc(hdcDest);
1526 if (!Dc)
1527 {
1528 EngSetLastError(ERROR_INVALID_HANDLE);
1529 return NULL;
1530 }
1531 /* It's OK to set bpp=0 here, as IntCreateDIBitmap will create a compatible Bitmap
1532 * if bpp != 1 and ignore the real value that was passed */
1533 if (pbmi)
1534 bpp = pbmi->bmiHeader.biBitCount;
1535 else
1536 bpp = 0;
1537 Bmp = IntCreateDIBitmap(Dc, cx, cy, bpp, fInit, pjInit, pbmi, iUsage);
1538 DC_UnlockDc(Dc);
1539
1540 if(!hDc)
1541 {
1542 NtGdiDeleteObjectApp(hdcDest);
1543 }
1544 return Bmp;
1545 }
1546
1547
1548 HBITMAP
1549 APIENTRY
1550 NtGdiCreateDIBSection(
1551 IN HDC hDC,
1552 IN OPTIONAL HANDLE hSection,
1553 IN DWORD dwOffset,
1554 IN BITMAPINFO* bmi,
1555 IN DWORD Usage,
1556 IN UINT cjHeader,
1557 IN FLONG fl,
1558 IN ULONG_PTR dwColorSpace,
1559 OUT PVOID *Bits)
1560 {
1561 HBITMAP hbitmap = 0;
1562 DC *dc;
1563 BOOL bDesktopDC = FALSE;
1564 NTSTATUS Status = STATUS_SUCCESS;
1565
1566 if (!bmi) return hbitmap; // Make sure.
1567
1568 _SEH2_TRY
1569 {
1570 ProbeForRead(&bmi->bmiHeader.biSize, sizeof(DWORD), 1);
1571 ProbeForRead(bmi, bmi->bmiHeader.biSize, 1);
1572 ProbeForRead(bmi, DIB_BitmapInfoSize(bmi, (WORD)Usage), 1);
1573 }
1574 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1575 {
1576 Status = _SEH2_GetExceptionCode();
1577 }
1578 _SEH2_END
1579
1580 if(!NT_SUCCESS(Status))
1581 {
1582 SetLastNtError(Status);
1583 return NULL;
1584 }
1585
1586 // If the reference hdc is null, take the desktop dc
1587 if (hDC == 0)
1588 {
1589 hDC = NtGdiCreateCompatibleDC(0);
1590 bDesktopDC = TRUE;
1591 }
1592
1593 if ((dc = DC_LockDc(hDC)))
1594 {
1595 hbitmap = DIB_CreateDIBSection(dc,
1596 bmi,
1597 Usage,
1598 Bits,
1599 hSection,
1600 dwOffset,
1601 0);
1602 DC_UnlockDc(dc);
1603 }
1604 else
1605 {
1606 EngSetLastError(ERROR_INVALID_HANDLE);
1607 }
1608
1609 if (bDesktopDC)
1610 NtGdiDeleteObjectApp(hDC);
1611
1612 return hbitmap;
1613 }
1614
1615 HBITMAP
1616 APIENTRY
1617 DIB_CreateDIBSection(
1618 PDC dc,
1619 CONST BITMAPINFO *bmi,
1620 UINT usage,
1621 LPVOID *bits,
1622 HANDLE section,
1623 DWORD offset,
1624 DWORD ovr_pitch)
1625 {
1626 HBITMAP res = 0;
1627 SURFACE *bmp = NULL;
1628 void *mapBits = NULL;
1629 PPALETTE ppalDIB = NULL;
1630
1631 // Fill BITMAP32 structure with DIB data
1632 CONST BITMAPINFOHEADER *bi = &bmi->bmiHeader;
1633 INT effHeight;
1634 ULONG totalSize;
1635 BITMAP bm;
1636 //SIZEL Size;
1637 HANDLE hSecure;
1638
1639 DPRINT("format (%ld,%ld), planes %u, bpp %u, size %lu, colors %lu (%s)\n",
1640 bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
1641 bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1642
1643 /* CreateDIBSection should fail for compressed formats */
1644 if (bi->biCompression == BI_RLE4 || bi->biCompression == BI_RLE8)
1645 {
1646 DPRINT1("no compressed format allowed\n");
1647 return (HBITMAP)NULL;
1648 }
1649
1650 effHeight = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
1651 bm.bmType = 0;
1652 bm.bmWidth = bi->biWidth;
1653 bm.bmHeight = effHeight;
1654 bm.bmWidthBytes = ovr_pitch ? ovr_pitch : WIDTH_BYTES_ALIGN32(bm.bmWidth, bi->biBitCount);
1655
1656 bm.bmPlanes = bi->biPlanes;
1657 bm.bmBitsPixel = bi->biBitCount;
1658 bm.bmBits = NULL;
1659
1660 // Get storage location for DIB bits. Only use biSizeImage if it's valid and
1661 // we're dealing with a compressed bitmap. Otherwise, use width * height.
1662 totalSize = bi->biSizeImage && bi->biCompression != BI_RGB && bi->biCompression != BI_BITFIELDS
1663 ? bi->biSizeImage : (ULONG)(bm.bmWidthBytes * effHeight);
1664
1665 if (section)
1666 {
1667 SYSTEM_BASIC_INFORMATION Sbi;
1668 NTSTATUS Status;
1669 DWORD mapOffset;
1670 LARGE_INTEGER SectionOffset;
1671 SIZE_T mapSize;
1672
1673 Status = ZwQuerySystemInformation(SystemBasicInformation,
1674 &Sbi,
1675 sizeof Sbi,
1676 0);
1677 if (!NT_SUCCESS(Status))
1678 {
1679 DPRINT1("ZwQuerySystemInformation failed (0x%lx)\n", Status);
1680 return NULL;
1681 }
1682
1683 mapOffset = offset - (offset % Sbi.AllocationGranularity);
1684 mapSize = bi->biSizeImage + (offset - mapOffset);
1685
1686 SectionOffset.LowPart = mapOffset;
1687 SectionOffset.HighPart = 0;
1688
1689 Status = ZwMapViewOfSection(section,
1690 NtCurrentProcess(),
1691 &mapBits,
1692 0,
1693 0,
1694 &SectionOffset,
1695 &mapSize,
1696 ViewShare,
1697 0,
1698 PAGE_READWRITE);
1699 if (!NT_SUCCESS(Status))
1700 {
1701 DPRINT1("ZwMapViewOfSection failed (0x%lx)\n", Status);
1702 EngSetLastError(ERROR_INVALID_PARAMETER);
1703 return NULL;
1704 }
1705
1706 if (mapBits) bm.bmBits = (char *)mapBits + (offset - mapOffset);
1707 }
1708 else if (ovr_pitch && offset)
1709 bm.bmBits = (LPVOID) offset;
1710 else
1711 {
1712 offset = 0;
1713 bm.bmBits = EngAllocUserMem(totalSize, 0);
1714 if(!bm.bmBits)
1715 {
1716 DPRINT1("Failed to allocate memory\n");
1717 goto cleanup;
1718 }
1719 }
1720
1721 // hSecure = MmSecureVirtualMemory(bm.bmBits, totalSize, PAGE_READWRITE);
1722 hSecure = (HANDLE)0x1; // HACK OF UNIMPLEMENTED KERNEL STUFF !!!!
1723
1724
1725 // Create Device Dependent Bitmap and add DIB pointer
1726 //Size.cx = bm.bmWidth;
1727 //Size.cy = abs(bm.bmHeight);
1728 res = GreCreateBitmapEx(bm.bmWidth,
1729 abs(bm.bmHeight),
1730 bm.bmWidthBytes,
1731 BitmapFormat(bi->biBitCount * bi->biPlanes, bi->biCompression),
1732 BMF_DONTCACHE | BMF_USERMEM | BMF_NOZEROINIT |
1733 ((bi->biHeight < 0) ? BMF_TOPDOWN : 0),
1734 bi->biSizeImage,
1735 bm.bmBits,
1736 0);
1737 if (!res)
1738 {
1739 DPRINT1("GreCreateBitmapEx failed\n");
1740 EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
1741 goto cleanup;
1742 }
1743 bmp = SURFACE_ShareLockSurface(res); // HACK
1744 if (NULL == bmp)
1745 {
1746 DPRINT1("SURFACE_LockSurface failed\n");
1747 EngSetLastError(ERROR_INVALID_HANDLE);
1748 goto cleanup;
1749 }
1750
1751 /* WINE NOTE: WINE makes use of a colormap, which is a color translation
1752 table between the DIB and the X physical device. Obviously,
1753 this is left out of the ReactOS implementation. Instead,
1754 we call NtGdiSetDIBColorTable. */
1755 bmp->hDIBSection = section;
1756 bmp->hSecure = hSecure;
1757 bmp->dwOffset = offset;
1758 bmp->flags = API_BITMAP;
1759 bmp->biClrImportant = bi->biClrImportant;
1760
1761 /* Create a palette for the DIB */
1762 ppalDIB = CreateDIBPalette(bmi, dc, usage);
1763
1764 // Clean up in case of errors
1765 cleanup:
1766 if (!res || !bmp || !bm.bmBits || !ppalDIB)
1767 {
1768 DPRINT("Got an error res=%p, bmp=%p, bm.bmBits=%p\n", res, bmp, bm.bmBits);
1769 if (bm.bmBits)
1770 {
1771 // MmUnsecureVirtualMemory(hSecure); // FIXME: Implement this!
1772 if (section)
1773 {
1774 ZwUnmapViewOfSection(NtCurrentProcess(), mapBits);
1775 bm.bmBits = NULL;
1776 }
1777 else if (!offset)
1778 EngFreeUserMem(bm.bmBits), bm.bmBits = NULL;
1779 }
1780
1781 if (bmp)
1782 {
1783 SURFACE_ShareUnlockSurface(bmp);
1784 bmp = NULL;
1785 }
1786
1787 if (res)
1788 {
1789 GreDeleteObject(res);
1790 res = 0;
1791 }
1792
1793 if(ppalDIB)
1794 {
1795 PALETTE_ShareUnlockPalette(ppalDIB);
1796 }
1797 }
1798
1799 if (bmp)
1800 {
1801 /* If we're here, everything went fine */
1802 SURFACE_vSetPalette(bmp, ppalDIB);
1803 PALETTE_ShareUnlockPalette(ppalDIB);
1804 SURFACE_ShareUnlockSurface(bmp);
1805 }
1806
1807 // Return BITMAP handle and storage location
1808 if (NULL != bm.bmBits && NULL != bits)
1809 {
1810 *bits = bm.bmBits;
1811 }
1812
1813 return res;
1814 }
1815
1816 /***********************************************************************
1817 * DIB_GetBitmapInfo
1818 *
1819 * Get the info from a bitmap header.
1820 * Return 0 for COREHEADER, 1 for INFOHEADER, -1 for error.
1821 */
1822 int
1823 FASTCALL
1824 DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
1825 LONG *height, WORD *planes, WORD *bpp, DWORD *compr, DWORD *size )
1826 {
1827 if (header->biSize == sizeof(BITMAPCOREHEADER))
1828 {
1829 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)header;
1830 *width = core->bcWidth;
1831 *height = core->bcHeight;
1832 *planes = core->bcPlanes;
1833 *bpp = core->bcBitCount;
1834 *compr = BI_RGB;
1835 *size = 0;
1836 return 0;
1837 }
1838 if (header->biSize >= sizeof(BITMAPINFOHEADER)) /* Assume BITMAPINFOHEADER */
1839 {
1840 *width = header->biWidth;
1841 *height = header->biHeight;
1842 *planes = header->biPlanes;
1843 *bpp = header->biBitCount;
1844 *compr = header->biCompression;
1845 *size = header->biSizeImage;
1846 return 1;
1847 }
1848 DPRINT1("(%u): unknown/wrong size for header\n", header->biSize );
1849 return -1;
1850 }
1851
1852 /***********************************************************************
1853 * DIB_GetDIBImageBytes
1854 *
1855 * Return the number of bytes used to hold the image in a DIB bitmap.
1856 * 11/16/1999 (RJJ) lifted from wine
1857 */
1858
1859 INT APIENTRY DIB_GetDIBImageBytes(INT width, INT height, INT depth)
1860 {
1861 return WIDTH_BYTES_ALIGN32(width, depth) * (height < 0 ? -height : height);
1862 }
1863
1864 /***********************************************************************
1865 * DIB_BitmapInfoSize
1866 *
1867 * Return the size of the bitmap info structure including color table.
1868 * 11/16/1999 (RJJ) lifted from wine
1869 */
1870
1871 INT FASTCALL DIB_BitmapInfoSize(const BITMAPINFO * info, WORD coloruse)
1872 {
1873 unsigned int colors, size, masks = 0;
1874
1875 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1876 {
1877 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
1878 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
1879 return sizeof(BITMAPCOREHEADER) + colors *
1880 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
1881 }
1882 else /* Assume BITMAPINFOHEADER */
1883 {
1884 colors = info->bmiHeader.biClrUsed;
1885 if (colors > 256) colors = 256;
1886 if (!colors && (info->bmiHeader.biBitCount <= 8))
1887 colors = 1 << info->bmiHeader.biBitCount;
1888 if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3;
1889 size = max( info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) );
1890 return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
1891 }
1892 }
1893
1894 HPALETTE
1895 FASTCALL
1896 DIB_MapPaletteColors(PPALETTE ppalDc, CONST BITMAPINFO* lpbmi)
1897 {
1898 PPALETTE ppalNew;
1899 ULONG nNumColors,i;
1900 USHORT *lpIndex;
1901 HPALETTE hpal;
1902
1903 if (!(ppalDc->flFlags & PAL_INDEXED))
1904 {
1905 return NULL;
1906 }
1907
1908 nNumColors = 1 << lpbmi->bmiHeader.biBitCount;
1909 if (lpbmi->bmiHeader.biClrUsed)
1910 {
1911 nNumColors = min(nNumColors, lpbmi->bmiHeader.biClrUsed);
1912 }
1913
1914 ppalNew = PALETTE_AllocPalWithHandle(PAL_INDEXED, nNumColors, NULL, 0, 0, 0);
1915 if (ppalNew == NULL)
1916 {
1917 DPRINT1("Could not allocate palette\n");
1918 return NULL;
1919 }
1920
1921 lpIndex = (USHORT *)((PBYTE)lpbmi + lpbmi->bmiHeader.biSize);
1922
1923 for (i = 0; i < nNumColors; i++)
1924 {
1925 ULONG iColorIndex = *lpIndex % ppalDc->NumColors;
1926 ppalNew->IndexedColors[i] = ppalDc->IndexedColors[iColorIndex];
1927 lpIndex++;
1928 }
1929
1930 hpal = ppalNew->BaseObject.hHmgr;
1931 PALETTE_UnlockPalette(ppalNew);
1932
1933 return hpal;
1934 }
1935
1936 /* Converts a BITMAPCOREINFO to a BITMAPINFO structure,
1937 * or does nothing if it's already a BITMAPINFO (or V4 or V5) */
1938 BITMAPINFO*
1939 FASTCALL
1940 DIB_ConvertBitmapInfo (CONST BITMAPINFO* pbmi, DWORD Usage)
1941 {
1942 CONST BITMAPCOREINFO* pbmci = (BITMAPCOREINFO*)pbmi;
1943 BITMAPINFO* pNewBmi ;
1944 UINT numColors = 0, ColorsSize = 0;
1945
1946 if(pbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) return (BITMAPINFO*)pbmi;
1947 if(pbmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) return NULL;
1948
1949 if(pbmci->bmciHeader.bcBitCount <= 8)
1950 {
1951 numColors = 1 << pbmci->bmciHeader.bcBitCount;
1952 if(Usage == DIB_PAL_COLORS)
1953 {
1954 ColorsSize = numColors * sizeof(WORD);
1955 }
1956 else
1957 {
1958 ColorsSize = numColors * sizeof(RGBQUAD);
1959 }
1960 }
1961 else if (Usage == DIB_PAL_COLORS)
1962 {
1963 /* Invalid at high-res */
1964 return NULL;
1965 }
1966
1967 pNewBmi = ExAllocatePoolWithTag(PagedPool, sizeof(BITMAPINFOHEADER) + ColorsSize, TAG_DIB);
1968 if(!pNewBmi) return NULL;
1969
1970 RtlZeroMemory(pNewBmi, sizeof(BITMAPINFOHEADER) + ColorsSize);
1971
1972 pNewBmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1973 pNewBmi->bmiHeader.biBitCount = pbmci->bmciHeader.bcBitCount;
1974 pNewBmi->bmiHeader.biWidth = pbmci->bmciHeader.bcWidth;
1975 pNewBmi->bmiHeader.biHeight = pbmci->bmciHeader.bcHeight;
1976 pNewBmi->bmiHeader.biPlanes = pbmci->bmciHeader.bcPlanes;
1977 pNewBmi->bmiHeader.biCompression = BI_RGB ;
1978 pNewBmi->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(pNewBmi->bmiHeader.biWidth,
1979 pNewBmi->bmiHeader.biHeight,
1980 pNewBmi->bmiHeader.biBitCount);
1981
1982 if(Usage == DIB_PAL_COLORS)
1983 {
1984 RtlCopyMemory(pNewBmi->bmiColors, pbmci->bmciColors, ColorsSize);
1985 }
1986 else
1987 {
1988 UINT i;
1989 for(i=0; i<numColors; i++)
1990 {
1991 pNewBmi->bmiColors[i].rgbRed = pbmci->bmciColors[i].rgbtRed;
1992 pNewBmi->bmiColors[i].rgbGreen = pbmci->bmciColors[i].rgbtGreen;
1993 pNewBmi->bmiColors[i].rgbBlue = pbmci->bmciColors[i].rgbtBlue;
1994 }
1995 }
1996
1997 return pNewBmi ;
1998 }
1999
2000 /* Frees a BITMAPINFO created with DIB_ConvertBitmapInfo */
2001 VOID
2002 FASTCALL
2003 DIB_FreeConvertedBitmapInfo(BITMAPINFO* converted, BITMAPINFO* orig, DWORD usage)
2004 {
2005 BITMAPCOREINFO* pbmci;
2006 if(converted == orig)
2007 return;
2008
2009 if(usage == -1)
2010 {
2011 /* Caller don't want any conversion */
2012 ExFreePoolWithTag(converted, TAG_DIB);
2013 return;
2014 }
2015
2016 /* Perform inverse conversion */
2017 pbmci = (BITMAPCOREINFO*)orig;
2018
2019 ASSERT(pbmci->bmciHeader.bcSize == sizeof(BITMAPCOREHEADER));
2020 pbmci->bmciHeader.bcBitCount = converted->bmiHeader.biBitCount;
2021 pbmci->bmciHeader.bcWidth = converted->bmiHeader.biWidth;
2022 pbmci->bmciHeader.bcHeight = converted->bmiHeader.biHeight;
2023 pbmci->bmciHeader.bcPlanes = converted->bmiHeader.biPlanes;
2024
2025 if(pbmci->bmciHeader.bcBitCount <= 8)
2026 {
2027 UINT numColors = converted->bmiHeader.biClrUsed;
2028 if(!numColors) numColors = 1 << pbmci->bmciHeader.bcBitCount;
2029 if(usage == DIB_PAL_COLORS)
2030 {
2031 RtlZeroMemory(pbmci->bmciColors, (1 << pbmci->bmciHeader.bcBitCount) * sizeof(WORD));
2032 RtlCopyMemory(pbmci->bmciColors, converted->bmiColors, numColors * sizeof(WORD));
2033 }
2034 else
2035 {
2036 UINT i;
2037 RtlZeroMemory(pbmci->bmciColors, (1 << pbmci->bmciHeader.bcBitCount) * sizeof(RGBTRIPLE));
2038 for(i=0; i<numColors; i++)
2039 {
2040 pbmci->bmciColors[i].rgbtRed = converted->bmiColors[i].rgbRed;
2041 pbmci->bmciColors[i].rgbtGreen = converted->bmiColors[i].rgbGreen;
2042 pbmci->bmciColors[i].rgbtBlue = converted->bmiColors[i].rgbBlue;
2043 }
2044 }
2045 }
2046 /* Now free it, it's not needed anymore */
2047 ExFreePoolWithTag(converted, TAG_DIB);
2048 }
2049
2050 /* EOF */