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