From 8cecc274d8b6b1baaaf655b8b91e2e367085e5c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gardou?= Date: Tue, 8 Jun 2010 00:40:42 +0000 Subject: [PATCH] [WIN32K] - remove duplicate prototypes. - Add missing trail to debug print - replace some now superfluous checks on bitmap palette with sanity ASSERTS - begin using BITMAPV5HEADER as a default bitmap format, and introduce conversion to and from everything prior that. Congratulations to BITMAPCOREHEADER, for its backward compatibility personal failure. svn path=/branches/reactos-yarotows/; revision=47690 --- subsystems/win32/win32k/include/bitmaps.h | 11 +- subsystems/win32/win32k/misc/file.c | 143 +----- subsystems/win32/win32k/objects/bitblt.c | 2 +- subsystems/win32/win32k/objects/dibobj.c | 571 ++++++++++++++-------- 4 files changed, 379 insertions(+), 348 deletions(-) diff --git a/subsystems/win32/win32k/include/bitmaps.h b/subsystems/win32/win32k/include/bitmaps.h index 11b0585bec3..cc3b47b8393 100644 --- a/subsystems/win32/win32k/include/bitmaps.h +++ b/subsystems/win32/win32k/include/bitmaps.h @@ -2,14 +2,19 @@ #include "surface.h" -INT FASTCALL DIB_GetDIBWidthBytes (INT width, INT depth); -int APIENTRY DIB_GetDIBImageBytes (INT width, INT height, INT depth); -INT FASTCALL DIB_BitmapInfoSize (const BITMAPINFO * info, WORD coloruse); +typedef struct tagBITMAPV5INFO +{ + BITMAPV5HEADER bmiHeader; + RGBQUAD bmiColors[256]; +} BITMAPV5INFO, *PBITMAPV5INFO; + INT APIENTRY BITMAP_GetObject(SURFACE * bmp, INT count, LPVOID buffer); HBITMAP FASTCALL IntCreateBitmap(IN SIZEL Size, IN LONG Width, IN ULONG Format, IN ULONG Flags, IN PVOID Bits); HBITMAP FASTCALL BITMAP_CopyBitmap (HBITMAP hBitmap); UINT FASTCALL BITMAP_GetRealBitsPixel(UINT nBitsPixel); INT FASTCALL BITMAP_GetWidthBytes (INT bmWidth, INT bpp); +NTSTATUS FASTCALL ProbeAndConvertToBitmapV5Info( OUT PBITMAPV5INFO pbmiDst, IN CONST BITMAPINFO* pbmiUnsafe, IN DWORD dwUse); +VOID FASTCALL GetBMIFromBitmapV5Info(IN PBITMAPV5INFO pbmiSrc, OUT PBITMAPINFO pbmiDst, IN DWORD dwUse); HBITMAP APIENTRY diff --git a/subsystems/win32/win32k/misc/file.c b/subsystems/win32/win32k/misc/file.c index d6de6c88c01..f8b932545fa 100644 --- a/subsystems/win32/win32k/misc/file.c +++ b/subsystems/win32/win32k/misc/file.c @@ -149,144 +149,8 @@ W32kMapViewOfSection( return pvBase; } -typedef struct tagBITMAPV5INFO -{ - BITMAPV5HEADER bmiHeader; - RGBQUAD bmiColors[256]; -} BITMAPV5INFO, *PBITMAPV5INFO; - // FIXME: this should go to dibobj.c -NTSTATUS -ProbeAndConvertBitmapInfo( - OUT BITMAPV5HEADER *pbmhDst, - OUT RGBQUAD *pbmiColorsDst, - ULONG cColors, - IN PBITMAPINFO pbmiUnsafe) -{ - DWORD dwSize; - RGBQUAD *pbmiColors; - ULONG ulWidthBytes; - /* Get the size and probe */ - ProbeForRead(&pbmiUnsafe->bmiHeader.biSize, sizeof(DWORD), 1); - dwSize = pbmiUnsafe->bmiHeader.biSize; - ProbeForRead(pbmiUnsafe, dwSize, 1); - - /* Check the size */ - // FIXME: are intermediate sizes allowed? As what are they interpreted? - // make sure we don't use a too big dwSize later - if (dwSize != sizeof(BITMAPCOREHEADER) && - dwSize != sizeof(BITMAPINFOHEADER) && - dwSize != sizeof(BITMAPV4HEADER) && - dwSize != sizeof(BITMAPV5HEADER)) - { - return STATUS_INVALID_PARAMETER; - } - - pbmiColors = (RGBQUAD*)((PCHAR)pbmiUnsafe + dwSize); - - pbmhDst->bV5Size = sizeof(BITMAPV5HEADER); - - if (dwSize == sizeof(BITMAPCOREHEADER)) - { - PBITMAPCOREHEADER pbch = (PBITMAPCOREHEADER)pbmiUnsafe; - - /* Manually copy the fields that are present */ - pbmhDst->bV5Width = pbch->bcWidth; - pbmhDst->bV5Height = pbch->bcHeight; - pbmhDst->bV5Planes = pbch->bcPlanes; - pbmhDst->bV5BitCount = pbch->bcBitCount; - - /* Set some default values */ - pbmhDst->bV5Compression = BI_RGB; - pbmhDst->bV5SizeImage = 0; - pbmhDst->bV5XPelsPerMeter = 72; - pbmhDst->bV5YPelsPerMeter = 72; - pbmhDst->bV5ClrUsed = 0; - pbmhDst->bV5ClrImportant = 0; - } - else - { - /* Copy valid fields */ - memcpy(pbmhDst, pbmiUnsafe, dwSize); - - /* Zero out the rest of the V5 header */ - memset((char*)pbmhDst + dwSize, 0, sizeof(BITMAPV5HEADER) - dwSize); - } - - - if (dwSize < sizeof(BITMAPV4HEADER)) - { - if (pbmhDst->bV5Compression == BI_BITFIELDS) - { - DWORD *pMasks = (DWORD*)pbmiColors; - pbmhDst->bV5RedMask = pMasks[0]; - pbmhDst->bV5GreenMask = pMasks[1]; - pbmhDst->bV5BlueMask = pMasks[2]; - pbmhDst->bV5AlphaMask = 0; - pbmhDst->bV5ClrUsed = 0; - } - -// pbmhDst->bV5CSType; -// pbmhDst->bV5Endpoints; -// pbmhDst->bV5GammaRed; -// pbmhDst->bV5GammaGreen; -// pbmhDst->bV5GammaBlue; - } - - if (dwSize < sizeof(BITMAPV5HEADER)) - { -// pbmhDst->bV5Intent; -// pbmhDst->bV5ProfileData; -// pbmhDst->bV5ProfileSize; -// pbmhDst->bV5Reserved; - } - - ulWidthBytes = ((pbmhDst->bV5Width * pbmhDst->bV5Planes * - pbmhDst->bV5BitCount + 31) & ~31) / 8; - - if (pbmhDst->bV5SizeImage == 0) - pbmhDst->bV5SizeImage = abs(ulWidthBytes * pbmhDst->bV5Height); - - if (pbmhDst->bV5ClrUsed == 0) - pbmhDst->bV5ClrUsed = pbmhDst->bV5BitCount == 1 ? 2 : - (pbmhDst->bV5BitCount == 4 ? 16 : - (pbmhDst->bV5BitCount == 8 ? 256 : 0)); - - if (pbmhDst->bV5Planes != 1) - { - return STATUS_INVALID_PARAMETER; - } - - if (pbmhDst->bV5BitCount != 0 && pbmhDst->bV5BitCount != 1 && - pbmhDst->bV5BitCount != 4 && pbmhDst->bV5BitCount != 8 && - pbmhDst->bV5BitCount != 16 && pbmhDst->bV5BitCount != 24 && - pbmhDst->bV5BitCount != 32) - { - DPRINT("Invalid bit count: %d\n", pbmhDst->bV5BitCount); - return STATUS_INVALID_PARAMETER; - } - - if ((pbmhDst->bV5BitCount == 0 && - pbmhDst->bV5Compression != BI_JPEG && pbmhDst->bV5Compression != BI_PNG)) - { - DPRINT("Bit count 0 is invalid for compression %d.\n", pbmhDst->bV5Compression); - return STATUS_INVALID_PARAMETER; - } - - if (pbmhDst->bV5Compression == BI_BITFIELDS && - pbmhDst->bV5BitCount != 16 && pbmhDst->bV5BitCount != 32) - { - DPRINT("Bit count %d is invalid for compression BI_BITFIELDS.\n", pbmhDst->bV5BitCount); - return STATUS_INVALID_PARAMETER; - } - - /* Copy Colors */ - cColors = min(cColors, pbmhDst->bV5ClrUsed); - memcpy(pbmiColorsDst, pbmiColors, cColors * sizeof(RGBQUAD)); - - return STATUS_SUCCESS; -} HBITMAP @@ -333,10 +197,9 @@ UserLoadImage(PCWSTR pwszName) /* Create a normalized local BITMAPINFO */ _SEH2_TRY { - Status = ProbeAndConvertBitmapInfo(&bmiLocal.bmiHeader, - bmiLocal.bmiColors, - 256, - pbmi); + Status = ProbeAndConvertToBitmapV5Info(&bmiLocal, + pbmi, + DIB_RGB_COLORS); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { diff --git a/subsystems/win32/win32k/objects/bitblt.c b/subsystems/win32/win32k/objects/bitblt.c index d1fb79735a8..5b59a592396 100644 --- a/subsystems/win32/win32k/objects/bitblt.c +++ b/subsystems/win32/win32k/objects/bitblt.c @@ -757,7 +757,7 @@ GreStretchBltMask( } else if(DCSrc) { - DPRINT1("Getting a valid Source handle without using source!!!"); + DPRINT1("Getting a valid Source handle without using source!!!\n"); GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject); DCSrc = NULL ; } diff --git a/subsystems/win32/win32k/objects/dibobj.c b/subsystems/win32/win32k/objects/dibobj.c index f5816dabe8e..66a77660efd 100644 --- a/subsystems/win32/win32k/objects/dibobj.c +++ b/subsystems/win32/win32k/objects/dibobj.c @@ -221,16 +221,16 @@ IntSetDIBits( CONST BITMAPINFO *bmi, UINT ColorUse) { - SURFACE *bitmap; + SURFACE *bitmap; HBITMAP SourceBitmap; INT result = 0; BOOL copyBitsResult; - SURFOBJ *DestSurf, *SourceSurf; + SURFOBJ *DestSurf, *SourceSurf; SIZEL SourceSize; POINTL ZeroPoint; RECTL DestRect; EXLATEOBJ exlo; - PPALETTE ppalDDB, ppalDIB; + PPALETTE ppalDIB; //RGBQUAD *lpRGB; HPALETTE DIB_Palette; ULONG DIB_Palette_Type; @@ -278,32 +278,15 @@ IntSetDIBits( return 0; } - if (bitmap->ppal) - { - ppalDDB = bitmap->ppal; - GDIOBJ_IncrementShareCount(&ppalDDB->BaseObject); - } - else - // Destination palette obtained from the hDC - ppalDDB = PALETTE_ShareLockPalette(DC->ppdev->devinfo.hpalDefault); - - if (NULL == ppalDDB) - { - EngUnlockSurface(SourceSurf); - EngDeleteSurface((HSURF)SourceBitmap); - SURFACE_UnlockSurface(bitmap); - SetLastWin32Error(ERROR_INVALID_HANDLE); - return 0; - } + ASSERT(bitmap->ppal); // Source palette obtained from the BITMAPINFO - DIB_Palette = BuildDIBPalette((PBITMAPINFO)bmi, (PINT)&DIB_Palette_Type); + DIB_Palette = BuildDIBPalette(bmi, (PINT)&DIB_Palette_Type); if (NULL == DIB_Palette) { EngUnlockSurface(SourceSurf); EngDeleteSurface((HSURF)SourceBitmap); SURFACE_UnlockSurface(bitmap); - PALETTE_ShareUnlockPalette(ppalDDB); SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES); return 0; } @@ -311,7 +294,7 @@ IntSetDIBits( ppalDIB = PALETTE_LockPalette(DIB_Palette); /* Initialize XLATEOBJ for color translation */ - EXLATEOBJ_vInitialize(&exlo, ppalDIB, ppalDDB, 0, 0, 0); + EXLATEOBJ_vInitialize(&exlo, ppalDIB, bitmap->ppal, 0, 0, 0); // Zero point ZeroPoint.x = 0; @@ -336,7 +319,6 @@ IntSetDIBits( // Clean up EXLATEOBJ_vCleanup(&exlo); PALETTE_UnlockPalette(ppalDIB); - PALETTE_ShareUnlockPalette(ppalDDB); PALETTE_FreePaletteByHandle(DIB_Palette); EngUnlockSurface(SourceSurf); EngDeleteSurface((HSURF)SourceBitmap); @@ -366,17 +348,13 @@ NtGdiSetDIBits( PDC Dc; INT Ret; NTSTATUS Status = STATUS_SUCCESS; - UINT cjBits; + BITMAPV5INFO bmiLocal; if (!Bits) return 0; _SEH2_TRY - { // FYI: We converted from CORE in gdi. - ProbeForRead(bmi, sizeof(BITMAPINFO), 1); - cjBits = bmi->bmiHeader.biBitCount * bmi->bmiHeader.biPlanes * bmi->bmiHeader.biWidth; - cjBits = ((cjBits + 31) & ~31) / 8; - cjBits *= ScanLines; - ProbeForRead(Bits, cjBits, 1); + { + Status = ProbeAndConvertToBitmapV5Info(&bmiLocal, bmi, ColorUse); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { @@ -401,7 +379,7 @@ NtGdiSetDIBits( return 0; } - Ret = IntSetDIBits(Dc, hBitmap, StartScan, ScanLines, Bits, bmi, ColorUse); + Ret = IntSetDIBits(Dc, hBitmap, StartScan, ScanLines, Bits, (PBITMAPINFO)&bmiLocal, ColorUse); DC_UnlockDc(Dc); @@ -440,16 +418,16 @@ NtGdiSetDIBitsToDeviceInternal( INT DIBWidth; SIZEL SourceSize; EXLATEOBJ exlo; - PPALETTE ppalDDB = NULL, ppalDIB = NULL; + PPALETTE ppalDIB = NULL; HPALETTE hpalDIB = NULL; ULONG DIBPaletteType; + BITMAPV5INFO bmiLocal ; if (!Bits) return 0; _SEH2_TRY { - ProbeForRead(bmi, cjMaxInfo , 1); - ProbeForRead(Bits, cjMaxBits, 1); + Status = ProbeAndConvertToBitmapV5Info(&bmiLocal, bmi, ColorUse); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { @@ -478,7 +456,7 @@ NtGdiSetDIBitsToDeviceInternal( pDestSurf = pSurf ? &pSurf->SurfObj : NULL; - ScanLines = min(ScanLines, abs(bmi->bmiHeader.biHeight) - StartScan); + ScanLines = min(ScanLines, abs(bmiLocal.bmiHeader.bV5Height) - StartScan); rcDest.left = XDest; rcDest.top = YDest; @@ -495,15 +473,16 @@ NtGdiSetDIBitsToDeviceInternal( ptSource.x = XSrc; ptSource.y = YSrc; - SourceSize.cx = bmi->bmiHeader.biWidth; + SourceSize.cx = bmiLocal.bmiHeader.bV5Width; SourceSize.cy = ScanLines; - DIBWidth = DIB_GetDIBWidthBytes(SourceSize.cx, bmi->bmiHeader.biBitCount); + DIBWidth = DIB_GetDIBWidthBytes(SourceSize.cx, bmiLocal.bmiHeader.bV5BitCount); hSourceBitmap = EngCreateBitmap(SourceSize, DIBWidth, - BitmapFormat(bmi->bmiHeader.biBitCount, bmi->bmiHeader.biCompression), - bmi->bmiHeader.biHeight < 0 ? BMF_TOPDOWN : 0, + BitmapFormat(bmiLocal.bmiHeader.bV5BitCount, + bmiLocal.bmiHeader.bV5Compression), + bmiLocal.bmiHeader.bV5Height < 0 ? BMF_TOPDOWN : 0, (PVOID) Bits); if (!hSourceBitmap) { @@ -519,24 +498,10 @@ NtGdiSetDIBitsToDeviceInternal( goto Exit; } - /* Obtain destination palette */ - if (pSurf && pSurf->ppal) - { - ppalDDB = pSurf->ppal; - GDIOBJ_IncrementShareCount(&ppalDDB->BaseObject); - } - else - ppalDDB = PALETTE_ShareLockPalette(pDC->ppdev->devinfo.hpalDefault); - - if (!ppalDDB) - { - SetLastWin32Error(ERROR_INVALID_HANDLE); - Status = STATUS_UNSUCCESSFUL; - goto Exit; - } + ASSERT(pSurf->ppal); /* Create a palette for the DIB */ - hpalDIB = BuildDIBPalette(bmi, (PINT)&DIBPaletteType); + hpalDIB = BuildDIBPalette((PBITMAPINFO)&bmiLocal, (PINT)&DIBPaletteType); if (!hpalDIB) { SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES); @@ -554,7 +519,7 @@ NtGdiSetDIBitsToDeviceInternal( } /* Initialize EXLATEOBJ */ - EXLATEOBJ_vInitialize(&exlo, ppalDIB, ppalDDB, 0, 0, 0); + EXLATEOBJ_vInitialize(&exlo, ppalDIB, pSurf->ppal, 0, 0, 0); /* Copy the bits */ DPRINT("BitsToDev with dstsurf=(%d|%d) (%d|%d), src=(%d|%d) w=%d h=%d\n", @@ -582,7 +547,6 @@ Exit: } if (ppalDIB) PALETTE_UnlockPalette(ppalDIB); - if (ppalDDB) PALETTE_ShareUnlockPalette(ppalDDB); if (pSourceSurf) EngUnlockSurface(pSourceSurf); if (hSourceBitmap) EngDeleteSurface((HSURF)hSourceBitmap); @@ -611,14 +575,12 @@ NtGdiGetDIBitsInternal( SURFACE *psurf = NULL; HBITMAP hDestBitmap = NULL; HPALETTE hDestPalette = NULL; - PPALETTE ppalSrc = NULL; + BITMAPV5INFO bmiLocal ; PPALETTE ppalDst = NULL; NTSTATUS Status = STATUS_SUCCESS; ULONG Result = 0; BOOL bPaletteMatch = FALSE; PBYTE ChkBits = Bits; - PVOID ColorPtr; - RGBQUAD *rgbQuads; ULONG DestPaletteType; ULONG Index; @@ -633,9 +595,7 @@ NtGdiGetDIBitsInternal( _SEH2_TRY { - ProbeForRead(&Info->bmiHeader.biSize, sizeof(DWORD), 1); - - ProbeForWrite(Info, Info->bmiHeader.biSize, 1); // Comp for Core. + Status = ProbeAndConvertToBitmapV5Info(&bmiLocal, Info, Usage); if (ChkBits) ProbeForWrite(ChkBits, MaxBits, 1); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) @@ -665,74 +625,59 @@ NtGdiGetDIBitsInternal( return 0; } - if (psurf->ppal) - { - ppalSrc = psurf->ppal; - GDIOBJ_IncrementShareCount(&ppalSrc->BaseObject); - } - else - ppalSrc = PALETTE_ShareLockPalette(Dc->ppdev->devinfo.hpalDefault); + ASSERT(psurf->ppal); DC_UnlockDc(Dc); - ASSERT(ppalSrc != NULL); - - ColorPtr = ((PBYTE)Info + Info->bmiHeader.biSize); - rgbQuads = (RGBQUAD *)ColorPtr; - /* Copy palette information * Always create a palette for 15 & 16 bit. */ if ((Info->bmiHeader.biBitCount == BitsPerFormat(psurf->SurfObj.iBitmapFormat) && Info->bmiHeader.biBitCount != 15 && Info->bmiHeader.biBitCount != 16) || !ChkBits) { - ppalDst = ppalSrc; + ppalDst = psurf->ppal; bPaletteMatch = TRUE; } else - hDestPalette = BuildDIBPalette(Info, (PINT)&DestPaletteType); //hDestPalette = Dc->DevInfo->hpalDefault; - - if (!bPaletteMatch) { + hDestPalette = BuildDIBPalette((PBITMAPINFO)&bmiLocal, (PINT)&DestPaletteType); ppalDst = PALETTE_LockPalette(hDestPalette); - /* FIXME - ppalDst can be NULL!!!! Don't assert here!!! */ - DPRINT("ppalDst : %p\n", ppalDst); - ASSERT(ppalDst); } + DPRINT("ppalDst : %p\n", ppalDst); + ASSERT(ppalDst); + /* Copy palette. */ - /* FIXME: This is largely incomplete. ATM no Core!*/ - switch (Info->bmiHeader.biBitCount) + switch (bmiLocal.bmiHeader.bV5BitCount) { case 1: case 4: case 8: - Info->bmiHeader.biClrUsed = 0; + bmiLocal.bmiHeader.bV5ClrUsed = 0; if (psurf->hSecure && - BitsPerFormat(psurf->SurfObj.iBitmapFormat) == Info->bmiHeader.biBitCount) + BitsPerFormat(psurf->SurfObj.iBitmapFormat) == bmiLocal.bmiHeader.bV5BitCount) { if (Usage == DIB_RGB_COLORS) { - if (ppalDst->NumColors != 1 << Info->bmiHeader.biBitCount) - Info->bmiHeader.biClrUsed = ppalDst->NumColors; + if (ppalDst->NumColors != 1 << bmiLocal.bmiHeader.bV5BitCount) + bmiLocal.bmiHeader.bV5ClrUsed = ppalDst->NumColors; for (Index = 0; - Index < (1 << Info->bmiHeader.biBitCount) && Index < ppalDst->NumColors; + Index < (1 << bmiLocal.bmiHeader.bV5BitCount) && Index < ppalDst->NumColors; Index++) { - rgbQuads[Index].rgbRed = ppalDst->IndexedColors[Index].peRed; - rgbQuads[Index].rgbGreen = ppalDst->IndexedColors[Index].peGreen; - rgbQuads[Index].rgbBlue = ppalDst->IndexedColors[Index].peBlue; - rgbQuads[Index].rgbReserved = 0; + bmiLocal.bmiColors[Index].rgbRed = ppalDst->IndexedColors[Index].peRed; + bmiLocal.bmiColors[Index].rgbGreen = ppalDst->IndexedColors[Index].peGreen; + bmiLocal.bmiColors[Index].rgbBlue = ppalDst->IndexedColors[Index].peBlue; + bmiLocal.bmiColors[Index].rgbReserved = 0; } } else { - PWORD Ptr = ColorPtr; for (Index = 0; Index < (1 << Info->bmiHeader.biBitCount); Index++) { - Ptr[Index] = (WORD)Index; + ((WORD*)bmiLocal.bmiColors)[Index] = Index; } } } @@ -740,12 +685,11 @@ NtGdiGetDIBitsInternal( { if (Usage == DIB_PAL_COLORS) { - PWORD Ptr = ColorPtr; for (Index = 0; Index < (1 << Info->bmiHeader.biBitCount); Index++) { - Ptr[Index] = (WORD)Index; + ((WORD*)bmiLocal.bmiColors)[Index] = (WORD)Index; } } else if (Info->bmiHeader.biBitCount > 1 && bPaletteMatch) @@ -754,33 +698,37 @@ NtGdiGetDIBitsInternal( Index < (1 << Info->bmiHeader.biBitCount) && Index < ppalDst->NumColors; Index++) { - Info->bmiColors[Index].rgbRed = ppalDst->IndexedColors[Index].peRed; - Info->bmiColors[Index].rgbGreen = ppalDst->IndexedColors[Index].peGreen; - Info->bmiColors[Index].rgbBlue = ppalDst->IndexedColors[Index].peBlue; - Info->bmiColors[Index].rgbReserved = 0; + bmiLocal.bmiColors[Index].rgbRed = ppalDst->IndexedColors[Index].peRed; + bmiLocal.bmiColors[Index].rgbGreen = ppalDst->IndexedColors[Index].peGreen; + bmiLocal.bmiColors[Index].rgbBlue = ppalDst->IndexedColors[Index].peBlue; + bmiLocal.bmiColors[Index].rgbReserved = 0; } } else { - switch (Info->bmiHeader.biBitCount) + switch (bmiLocal.bmiHeader.bV5BitCount) { case 1: - rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen = rgbQuads[0].rgbBlue = 0; - rgbQuads[0].rgbReserved = 0; - rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen = rgbQuads[1].rgbBlue = 0xff; - rgbQuads[1].rgbReserved = 0; + bmiLocal.bmiColors[0].rgbRed =0 ; + bmiLocal.bmiColors[0].rgbGreen = 0; + bmiLocal.bmiColors[0].rgbBlue = 0; + bmiLocal.bmiColors[0].rgbReserved = 0; + bmiLocal.bmiColors[1].rgbRed =0xFF ; + bmiLocal.bmiColors[1].rgbGreen = 0xFF; + bmiLocal.bmiColors[1].rgbBlue = 0xFF; + bmiLocal.bmiColors[1].rgbReserved = 0; break; case 4: - RtlCopyMemory(ColorPtr, EGAColorsQuads, sizeof(EGAColorsQuads)); + RtlCopyMemory(bmiLocal.bmiColors, EGAColorsQuads, sizeof(EGAColorsQuads)); break; case 8: { INT r, g, b; RGBQUAD *color; - RtlCopyMemory(rgbQuads, DefLogPaletteQuads, 10 * sizeof(RGBQUAD)); - RtlCopyMemory(rgbQuads + 246, DefLogPaletteQuads + 10, 10 * sizeof(RGBQUAD)); - color = rgbQuads + 10; + RtlCopyMemory(bmiLocal.bmiColors, DefLogPaletteQuads, 10 * sizeof(RGBQUAD)); + RtlCopyMemory(bmiLocal.bmiColors + 246, DefLogPaletteQuads + 10, 10 * sizeof(RGBQUAD)); + color = bmiLocal.bmiColors + 10; for (r = 0; r <= 5; r++) /* FIXME */ for (g = 0; g <= 5; g++) for (b = 0; b <= 5; b++) @@ -798,20 +746,20 @@ NtGdiGetDIBitsInternal( } case 15: - if (Info->bmiHeader.biCompression == BI_BITFIELDS) + if (bmiLocal.bmiHeader.bV5Compression == BI_BITFIELDS) { - ((PDWORD)Info->bmiColors)[0] = 0x7c00; - ((PDWORD)Info->bmiColors)[1] = 0x03e0; - ((PDWORD)Info->bmiColors)[2] = 0x001f; + bmiLocal.bmiHeader.bV5RedMask = 0x7c00; + bmiLocal.bmiHeader.bV5GreenMask = 0x03e0; + bmiLocal.bmiHeader.bV5BlueMask = 0x001f; } break; case 16: if (Info->bmiHeader.biCompression == BI_BITFIELDS) { - ((PDWORD)Info->bmiColors)[0] = 0xf800; - ((PDWORD)Info->bmiColors)[1] = 0x07e0; - ((PDWORD)Info->bmiColors)[2] = 0x001f; + bmiLocal.bmiHeader.bV5RedMask = 0xf800; + bmiLocal.bmiHeader.bV5GreenMask = 0x07e0; + bmiLocal.bmiHeader.bV5BlueMask = 0x001f; } break; @@ -819,71 +767,54 @@ NtGdiGetDIBitsInternal( case 32: if (Info->bmiHeader.biCompression == BI_BITFIELDS) { - ((PDWORD)Info->bmiColors)[0] = 0xff0000; - ((PDWORD)Info->bmiColors)[1] = 0x00ff00; - ((PDWORD)Info->bmiColors)[2] = 0x0000ff; + bmiLocal.bmiHeader.bV5RedMask = 0xff0000; + bmiLocal.bmiHeader.bV5GreenMask = 0x00ff00; + bmiLocal.bmiHeader.bV5BlueMask = 0x0000ff; } break; } - if (!bPaletteMatch) - PALETTE_UnlockPalette(ppalDst); - /* fill out the BITMAPINFO struct */ if (!ChkBits) - { // Core or not to Core? We have converted from Core in Gdi~ so? - if (Info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) + { + bmiLocal.bmiHeader.bV5Width = psurf->SurfObj.sizlBitmap.cx; + bmiLocal.bmiHeader.bV5Height = psurf->SurfObj.sizlBitmap.cy; + bmiLocal.bmiHeader.bV5Planes = 1; + bmiLocal.bmiHeader.bV5BitCount = BitsPerFormat(psurf->SurfObj.iBitmapFormat); + switch (psurf->SurfObj.iBitmapFormat) { - BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) Info; - coreheader->bcWidth = psurf->SurfObj.sizlBitmap.cx; - coreheader->bcPlanes = 1; - coreheader->bcBitCount = BitsPerFormat(psurf->SurfObj.iBitmapFormat); - coreheader->bcHeight = psurf->SurfObj.sizlBitmap.cy; - if (psurf->SurfObj.lDelta > 0) - coreheader->bcHeight = -coreheader->bcHeight; - } - - if (Info->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) - { - Info->bmiHeader.biWidth = psurf->SurfObj.sizlBitmap.cx; - Info->bmiHeader.biHeight = psurf->SurfObj.sizlBitmap.cy; - Info->bmiHeader.biPlanes = 1; - Info->bmiHeader.biBitCount = BitsPerFormat(psurf->SurfObj.iBitmapFormat); - switch (psurf->SurfObj.iBitmapFormat) - { - /* FIXME: What about BI_BITFIELDS? */ - case BMF_1BPP: - case BMF_4BPP: - case BMF_8BPP: - case BMF_16BPP: - case BMF_24BPP: - case BMF_32BPP: - Info->bmiHeader.biCompression = BI_RGB; - break; - case BMF_4RLE: - Info->bmiHeader.biCompression = BI_RLE4; - break; - case BMF_8RLE: - Info->bmiHeader.biCompression = BI_RLE8; - break; - case BMF_JPEG: - Info->bmiHeader.biCompression = BI_JPEG; - break; - case BMF_PNG: - Info->bmiHeader.biCompression = BI_PNG; - break; - } - /* Image size has to be calculated */ - Info->bmiHeader.biSizeImage = DIB_GetDIBWidthBytes(Info->bmiHeader.biWidth, - Info->bmiHeader.biBitCount) * Info->bmiHeader.biHeight; - Info->bmiHeader.biXPelsPerMeter = 0; /* FIXME */ - Info->bmiHeader.biYPelsPerMeter = 0; /* FIXME */ - Info->bmiHeader.biClrUsed = 0; - Info->bmiHeader.biClrImportant = 1 << Info->bmiHeader.biBitCount; /* FIXME */ - /* Report negtive height for top-down bitmaps. */ - if (psurf->SurfObj.lDelta > 0) - Info->bmiHeader.biHeight = -Info->bmiHeader.biHeight; + /* FIXME: What about BI_BITFIELDS? */ + case BMF_1BPP: + case BMF_4BPP: + case BMF_8BPP: + case BMF_16BPP: + case BMF_24BPP: + case BMF_32BPP: + bmiLocal.bmiHeader.bV5Compression = BI_RGB; + break; + case BMF_4RLE: + bmiLocal.bmiHeader.bV5Compression = BI_RLE4; + break; + case BMF_8RLE: + bmiLocal.bmiHeader.bV5Compression = BI_RLE8; + break; + case BMF_JPEG: + bmiLocal.bmiHeader.bV5Compression = BI_JPEG; + break; + case BMF_PNG: + bmiLocal.bmiHeader.bV5Compression = BI_PNG; + break; } + /* Image size has to be calculated */ + bmiLocal.bmiHeader.bV5SizeImage = DIB_GetDIBWidthBytes(Info->bmiHeader.biWidth, + Info->bmiHeader.biBitCount) * Info->bmiHeader.biHeight; + bmiLocal.bmiHeader.bV5XPelsPerMeter = 0; /* FIXME */ + bmiLocal.bmiHeader.bV5YPelsPerMeter = 0; /* FIXME */ + bmiLocal.bmiHeader.bV5ClrUsed = 0; + bmiLocal.bmiHeader.bV5ClrImportant = 1 << Info->bmiHeader.biBitCount; /* FIXME */ + /* Report negative height for top-down bitmaps. */ + if (psurf->SurfObj.lDelta > 0) + bmiLocal.bmiHeader.bV5Height *= -1; Result = psurf->SurfObj.sizlBitmap.cy; } else @@ -907,27 +838,14 @@ NtGdiGetDIBitsInternal( hDestBitmap = NULL; - if (Info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) - { - BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) Info; - hDestBitmap = EngCreateBitmap(DestSize, - DIB_GetDIBWidthBytes(DestSize.cx, coreheader->bcBitCount), - BitmapFormat(coreheader->bcBitCount, BI_RGB), - 0 < coreheader->bcHeight ? 0 : BMF_TOPDOWN, - Bits); - } - - if (Info->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) - { - Info->bmiHeader.biSizeImage = DIB_GetDIBWidthBytes(DestSize.cx, + bmiLocal.bmiHeader.bV5SizeImage = DIB_GetDIBWidthBytes(DestSize.cx, Info->bmiHeader.biBitCount) * DestSize.cy; - hDestBitmap = EngCreateBitmap(DestSize, - DIB_GetDIBWidthBytes(DestSize.cx, Info->bmiHeader.biBitCount), - BitmapFormat(Info->bmiHeader.biBitCount, Info->bmiHeader.biCompression), - 0 < Info->bmiHeader.biHeight ? 0 : BMF_TOPDOWN, - Bits); - } + hDestBitmap = EngCreateBitmap(DestSize, + DIB_GetDIBWidthBytes(DestSize.cx, Info->bmiHeader.biBitCount), + BitmapFormat(Info->bmiHeader.biBitCount, Info->bmiHeader.biCompression), + 0 < Info->bmiHeader.biHeight ? 0 : BMF_TOPDOWN, + Bits); if (hDestBitmap == NULL) goto cleanup; @@ -939,7 +857,7 @@ NtGdiGetDIBitsInternal( SURFOBJ *DestSurfObj; RECTL DestRect; - EXLATEOBJ_vInitialize(&exlo, ppalSrc, ppalDst, 0, 0, 0); + EXLATEOBJ_vInitialize(&exlo, psurf->ppal, ppalDst, 0, 0, 0); SourcePoint.x = 0; SourcePoint.y = psurf->SurfObj.sizlBitmap.cy - (StartScan + ScanLines); @@ -967,14 +885,19 @@ NtGdiGetDIBitsInternal( EngUnlockSurface(DestSurfObj); } } + /* Now that everything is over, get back the information to caller */ + /* Note : Info has already been probed */ + GetBMIFromBitmapV5Info(&bmiLocal, Info, Usage); cleanup: - PALETTE_ShareUnlockPalette(ppalSrc); if (hDestBitmap != NULL) EngDeleteSurface((HSURF)hDestBitmap); - if (hDestPalette != NULL && bPaletteMatch == FALSE) + if (hDestPalette != NULL && !bPaletteMatch) + { + PALETTE_UnlockPalette(ppalDst); PALETTE_FreePaletteByHandle(hDestPalette); + } SURFACE_UnlockSurface(psurf); @@ -1653,7 +1576,7 @@ INT FASTCALL DIB_BitmapInfoSize(const BITMAPINFO * info, WORD coloruse) { colors = info->bmiHeader.biClrUsed; if (!colors && (info->bmiHeader.biBitCount <= 8)) colors = 1 << info->bmiHeader.biBitCount; - return sizeof(BITMAPINFOHEADER) + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD)); + return info->bmiHeader.biSize + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD)); } } @@ -1722,9 +1645,9 @@ BuildDIBPalette(CONST BITMAPINFO *bmi, PINT paletteType) { BYTE bits; ULONG ColorCount; - PALETTEENTRY *palEntries = NULL; HPALETTE hPal; ULONG RedMask, GreenMask, BlueMask; + PDWORD pdwColors = (PDWORD)((PBYTE)bmi + bmi->bmiHeader.biSize); // Determine Bits Per Pixel bits = bmi->bmiHeader.biBitCount; @@ -1738,9 +1661,9 @@ BuildDIBPalette(CONST BITMAPINFO *bmi, PINT paletteType) else if (bmi->bmiHeader.biCompression == BI_BITFIELDS) { *paletteType = PAL_BITFIELDS; - RedMask = ((ULONG *)bmi->bmiColors)[0]; - GreenMask = ((ULONG *)bmi->bmiColors)[1]; - BlueMask = ((ULONG *)bmi->bmiColors)[2]; + RedMask = pdwColors[0]; + GreenMask = pdwColors[1]; + BlueMask = pdwColors[2]; } else if (bits == 15) { @@ -1775,16 +1698,256 @@ BuildDIBPalette(CONST BITMAPINFO *bmi, PINT paletteType) if (PAL_INDEXED == *paletteType) { - hPal = PALETTE_AllocPaletteIndexedRGB(ColorCount, (RGBQUAD*)bmi->bmiColors); + hPal = PALETTE_AllocPaletteIndexedRGB(ColorCount, (RGBQUAD*)pdwColors); } else { hPal = PALETTE_AllocPalette(*paletteType, ColorCount, - (ULONG*) palEntries, + NULL, RedMask, GreenMask, BlueMask); } return hPal; } +FORCEINLINE +DWORD +GetBMIColor(CONST BITMAPINFO* pbmi, INT i) +{ + DWORD dwRet = 0; + INT size; + if(pbmi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) + { + /* BITMAPCOREINFO holds RGBTRIPLE values */ + size = sizeof(RGBTRIPLE); + } + else + { + size = sizeof(RGBQUAD); + } + memcpy(&dwRet, (PBYTE)pbmi + pbmi->bmiHeader.biSize + i*size, size); + return dwRet; +} + +FORCEINLINE +VOID +SetBMIColor(CONST BITMAPINFO* pbmi, DWORD* color, INT i) +{ + if(pbmi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) + { + *(RGBTRIPLE*)((PBYTE)pbmi + pbmi->bmiHeader.biSize + i*sizeof(RGBTRIPLE)) = *(RGBTRIPLE*)color; + } + else + { + *(RGBQUAD*)((PBYTE)pbmi + pbmi->bmiHeader.biSize + i*sizeof(RGBQUAD)) = *(RGBQUAD*)color; + } +} + +NTSTATUS +FASTCALL +ProbeAndConvertToBitmapV5Info( + OUT PBITMAPV5INFO pbmiDst, + IN CONST BITMAPINFO* pbmiUnsafe, + IN DWORD dwColorUse) +{ + DWORD dwSize; + ULONG ulWidthBytes; + PBITMAPV5HEADER pbmhDst = &pbmiDst->bmiHeader; + + /* Get the size and probe */ + ProbeForRead(&pbmiUnsafe->bmiHeader.biSize, sizeof(DWORD), 1); + dwSize = pbmiUnsafe->bmiHeader.biSize; + ProbeForRead(pbmiUnsafe, dwSize, 1); + + /* Check the size */ + // FIXME: are intermediate sizes allowed? As what are they interpreted? + // make sure we don't use a too big dwSize later + if (dwSize != sizeof(BITMAPCOREHEADER) && + dwSize != sizeof(BITMAPINFOHEADER) && + dwSize != sizeof(BITMAPV4HEADER) && + dwSize != sizeof(BITMAPV5HEADER)) + { + return STATUS_INVALID_PARAMETER; + } + + if (dwSize == sizeof(BITMAPCOREHEADER)) + { + PBITMAPCOREHEADER pbch = (PBITMAPCOREHEADER)pbmiUnsafe; + + /* Manually copy the fields that are present */ + pbmhDst->bV5Width = pbch->bcWidth; + pbmhDst->bV5Height = pbch->bcHeight; + pbmhDst->bV5Planes = pbch->bcPlanes; + pbmhDst->bV5BitCount = pbch->bcBitCount; + + /* Set some default values */ + pbmhDst->bV5Compression = BI_RGB; + pbmhDst->bV5SizeImage = 0; + pbmhDst->bV5XPelsPerMeter = 72; + pbmhDst->bV5YPelsPerMeter = 72; + pbmhDst->bV5ClrUsed = 0; + pbmhDst->bV5ClrImportant = 0; + } + else + { + /* Copy valid fields */ + memcpy(pbmiDst, pbmiUnsafe, dwSize); + + if(dwSize < sizeof(BITMAPV5HEADER)) + { + /* Zero out the rest of the V5 header */ + memset((char*)pbmiDst + dwSize, 0, sizeof(BITMAPV5HEADER) - dwSize); + } + } + pbmhDst->bV5Size = sizeof(BITMAPV5HEADER); + + + if (dwSize < sizeof(BITMAPV4HEADER)) + { + if (pbmhDst->bV5Compression == BI_BITFIELDS) + { + pbmhDst->bV5RedMask = GetBMIColor(pbmiUnsafe, 0); + pbmhDst->bV5GreenMask = GetBMIColor(pbmiUnsafe, 1); + pbmhDst->bV5BlueMask = GetBMIColor(pbmiUnsafe, 2); + pbmhDst->bV5AlphaMask = 0; + pbmhDst->bV5ClrUsed = 0; + } + +// pbmhDst->bV5CSType; +// pbmhDst->bV5Endpoints; +// pbmhDst->bV5GammaRed; +// pbmhDst->bV5GammaGreen; +// pbmhDst->bV5GammaBlue; + } + + if (dwSize < sizeof(BITMAPV5HEADER)) + { +// pbmhDst->bV5Intent; +// pbmhDst->bV5ProfileData; +// pbmhDst->bV5ProfileSize; +// pbmhDst->bV5Reserved; + } + + ulWidthBytes = ((pbmhDst->bV5Width * pbmhDst->bV5Planes * + pbmhDst->bV5BitCount + 31) & ~31) / 8; + + if (pbmhDst->bV5SizeImage == 0) + pbmhDst->bV5SizeImage = abs(ulWidthBytes * pbmhDst->bV5Height); + + if (pbmhDst->bV5ClrUsed == 0) + { + switch(pbmhDst->bV5BitCount) + { + case 1: + pbmhDst->bV5ClrUsed = 2; + break; + case 4: + pbmhDst->bV5ClrUsed = 16; + break; + case 8: + pbmhDst->bV5ClrUsed = 256; + break; + default: + pbmhDst->bV5ClrUsed = 0; + break; + } + } + + if (pbmhDst->bV5Planes != 1) + { + return STATUS_INVALID_PARAMETER; + } + + if (pbmhDst->bV5BitCount != 0 && pbmhDst->bV5BitCount != 1 && + pbmhDst->bV5BitCount != 4 && pbmhDst->bV5BitCount != 8 && + pbmhDst->bV5BitCount != 16 && pbmhDst->bV5BitCount != 24 && + pbmhDst->bV5BitCount != 32) + { + DPRINT("Invalid bit count: %d\n", pbmhDst->bV5BitCount); + return STATUS_INVALID_PARAMETER; + } + + if ((pbmhDst->bV5BitCount == 0 && + pbmhDst->bV5Compression != BI_JPEG && pbmhDst->bV5Compression != BI_PNG)) + { + DPRINT("Bit count 0 is invalid for compression %d.\n", pbmhDst->bV5Compression); + return STATUS_INVALID_PARAMETER; + } + + if (pbmhDst->bV5Compression == BI_BITFIELDS && + pbmhDst->bV5BitCount != 16 && pbmhDst->bV5BitCount != 32) + { + DPRINT("Bit count %d is invalid for compression BI_BITFIELDS.\n", pbmhDst->bV5BitCount); + return STATUS_INVALID_PARAMETER; + } + + /* Copy Colors */ + if(pbmhDst->bV5ClrUsed) + { + INT i; + if(dwColorUse == DIB_PAL_COLORS) + { + RtlCopyMemory(pbmiDst->bmiColors, + pbmiUnsafe->bmiColors, + pbmhDst->bV5ClrUsed * sizeof(WORD)); + } + else + { + for(i = 0; i < pbmhDst->bV5ClrUsed; i++) + { + ((DWORD*)pbmiDst->bmiColors)[i] = GetBMIColor(pbmiUnsafe, i); + } + } + } + + return STATUS_SUCCESS; +} + +VOID +FASTCALL +GetBMIFromBitmapV5Info(IN PBITMAPV5INFO pbmiSrc, + OUT PBITMAPINFO pbmiDst, + IN DWORD dwColorUse) +{ + if(pbmiDst->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) + { + /* Manually set value */ + BITMAPCOREHEADER* pbmhCore = (BITMAPCOREHEADER*)&pbmiDst->bmiHeader; + pbmhCore->bcWidth = pbmiSrc->bmiHeader.bV5Width; + pbmhCore->bcHeight = pbmiSrc->bmiHeader.bV5Height; + pbmhCore->bcPlanes = pbmiSrc->bmiHeader.bV5Planes; + pbmhCore->bcBitCount = pbmiSrc->bmiHeader.bV5BitCount; + } + else + { + /* Copy valid Fields, keep bmiHeader.biSize safe */ + RtlCopyMemory((PBYTE)pbmiDst + sizeof(DWORD), pbmiSrc, pbmiDst->bmiHeader.biSize - sizeof(DWORD)); + } + if((pbmiDst->bmiHeader.biSize < sizeof(BITMAPV4HEADER)) && + (pbmiSrc->bmiHeader.bV5Compression == BI_BITFIELDS)) + { + /* Masks are already set in V4 and V5 headers */ + SetBMIColor(pbmiDst, &pbmiSrc->bmiHeader.bV5RedMask, 0); + SetBMIColor(pbmiDst, &pbmiSrc->bmiHeader.bV5GreenMask, 1); + SetBMIColor(pbmiDst, &pbmiSrc->bmiHeader.bV5BlueMask, 2); + } + else + { + INT i; + if(dwColorUse == DIB_PAL_COLORS) + { + RtlCopyMemory(pbmiDst->bmiColors, + pbmiSrc->bmiColors, + pbmiSrc->bmiHeader.bV5ClrUsed * sizeof(WORD)); + } + else + { + for(i = 0; i < pbmiSrc->bmiHeader.bV5ClrUsed; i++) + { + SetBMIColor(pbmiDst, (DWORD*)pbmiSrc->bmiColors + i, i); + } + } + } +} + /* EOF */