mirror of
https://github.com/reactos/reactos.git
synced 2025-08-03 22:56:00 +00:00
[WIN32K]
- Improve the "infamous RLE hack" in SetDIBitsToDevice by using a mask bitmap corresponding to the valid RLE data [GDI32] - Improve some input checks svn path=/trunk/; revision=63920
This commit is contained in:
parent
ea6842d69a
commit
ec5927ad19
3 changed files with 178 additions and 7 deletions
|
@ -671,8 +671,7 @@ SetDIBitsToDevice(
|
||||||
if (ColorUse && ColorUse != DIB_PAL_COLORS && ColorUse != DIB_PAL_COLORS + 1)
|
if (ColorUse && ColorUse != DIB_PAL_COLORS && ColorUse != DIB_PAL_COLORS + 1)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
pConvertedInfo = ConvertBitmapInfo(lpbmi, ColorUse, &ConvertedInfoSize,
|
pConvertedInfo = ConvertBitmapInfo(lpbmi, ColorUse, &ConvertedInfoSize, FALSE);
|
||||||
FALSE);
|
|
||||||
if (!pConvertedInfo)
|
if (!pConvertedInfo)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -720,6 +719,15 @@ SetDIBitsToDevice(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if ((pConvertedInfo->bmiHeader.biCompression == BI_RLE8) ||
|
||||||
|
(pConvertedInfo->bmiHeader.biCompression == BI_RLE4))
|
||||||
|
{
|
||||||
|
/* For compressed data, we must set the whole thing */
|
||||||
|
StartScan = 0;
|
||||||
|
ScanLines = pConvertedInfo->bmiHeader.biHeight;
|
||||||
|
}
|
||||||
|
|
||||||
cjBmpScanSize = DIB_BitmapMaxBitsSize((LPBITMAPINFO) lpbmi, ScanLines);
|
cjBmpScanSize = DIB_BitmapMaxBitsSize((LPBITMAPINFO) lpbmi, ScanLines);
|
||||||
|
|
||||||
pvSafeBits = RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize);
|
pvSafeBits = RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize);
|
||||||
|
|
|
@ -296,6 +296,35 @@ ConvertBitmapInfo(
|
||||||
RtlCopyMemory((PVOID)NewDataPtr, (PVOID)OldDataPtr, DataSize);
|
RtlCopyMemory((PVOID)NewDataPtr, (PVOID)OldDataPtr, DataSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Verify some data validity */
|
||||||
|
switch (BitmapInfo->bmiHeader.biCompression)
|
||||||
|
{
|
||||||
|
case BI_RLE8:
|
||||||
|
if (BitmapInfo->bmiHeader.biBitCount != 8)
|
||||||
|
return NULL;
|
||||||
|
if (BitmapInfo->bmiHeader.biHeight < 0)
|
||||||
|
return NULL;
|
||||||
|
break;
|
||||||
|
case BI_RLE4:
|
||||||
|
if (BitmapInfo->bmiHeader.biBitCount != 4)
|
||||||
|
return NULL;
|
||||||
|
if (BitmapInfo->bmiHeader.biHeight < 0)
|
||||||
|
return NULL;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Non "standard" formats must have a valid size set */
|
||||||
|
if ((BitmapInfo->bmiHeader.biCompression != BI_RGB) &&
|
||||||
|
(BitmapInfo->bmiHeader.biCompression != BI_BITFIELDS))
|
||||||
|
{
|
||||||
|
if (BitmapInfo->bmiHeader.biSizeImage == 0)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Size = NewBitmapInfo->bmiHeader.biSize;
|
Size = NewBitmapInfo->bmiHeader.biSize;
|
||||||
if (ColorSpec == DIB_RGB_COLORS)
|
if (ColorSpec == DIB_RGB_COLORS)
|
||||||
|
|
|
@ -375,6 +375,115 @@ cleanup:
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
HBITMAP
|
||||||
|
IntGdiCreateMaskFromRLE(
|
||||||
|
DWORD Width,
|
||||||
|
DWORD Height,
|
||||||
|
ULONG Compression,
|
||||||
|
const BYTE* Bits,
|
||||||
|
DWORD BitsSize)
|
||||||
|
{
|
||||||
|
HBITMAP Mask;
|
||||||
|
DWORD x, y;
|
||||||
|
SURFOBJ* SurfObj;
|
||||||
|
UINT i = 0;
|
||||||
|
BYTE Data, NumPixels, ToSkip;
|
||||||
|
|
||||||
|
ASSERT((Compression == BI_RLE8) || (Compression == BI_RLE4));
|
||||||
|
|
||||||
|
/* Create the bitmap */
|
||||||
|
Mask = GreCreateBitmapEx(Width, Height, 0, BMF_1BPP, 0, 0, NULL, 0);
|
||||||
|
if (!Mask)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
SurfObj = EngLockSurface((HSURF)Mask);
|
||||||
|
if (!SurfObj)
|
||||||
|
{
|
||||||
|
GreDeleteObject(Mask);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
ASSERT(SurfObj->pvBits != NULL);
|
||||||
|
|
||||||
|
x = y = 0;
|
||||||
|
|
||||||
|
while (i < BitsSize)
|
||||||
|
{
|
||||||
|
NumPixels = Bits[i];
|
||||||
|
Data = Bits[i + 1];
|
||||||
|
i += 2;
|
||||||
|
|
||||||
|
if (NumPixels != 0)
|
||||||
|
{
|
||||||
|
if ((x + NumPixels) > Width)
|
||||||
|
NumPixels = Width - x;
|
||||||
|
|
||||||
|
if (NumPixels == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
DIB_1BPP_HLine(SurfObj, x, x + NumPixels, y, 1);
|
||||||
|
x += NumPixels;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Data < 3)
|
||||||
|
{
|
||||||
|
switch (Data)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
/* End of line */
|
||||||
|
y++;
|
||||||
|
if (y == Height)
|
||||||
|
goto done;
|
||||||
|
x = 0;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
/* End of file */
|
||||||
|
goto done;
|
||||||
|
case 2:
|
||||||
|
/* Jump */
|
||||||
|
if (i >= (BitsSize - 1))
|
||||||
|
goto done;
|
||||||
|
x += Bits[i];
|
||||||
|
if (x > Width)
|
||||||
|
x = Width;
|
||||||
|
y += Bits[i + 1];
|
||||||
|
if (y >= Height)
|
||||||
|
goto done;
|
||||||
|
i += 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* Done for this run */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Embedded data into the RLE */
|
||||||
|
NumPixels = Data;
|
||||||
|
if (Compression == BI_RLE8)
|
||||||
|
ToSkip = NumPixels;
|
||||||
|
else
|
||||||
|
ToSkip = (NumPixels / 2) + (NumPixels & 1);
|
||||||
|
|
||||||
|
if ((i + ToSkip) > BitsSize)
|
||||||
|
goto done;
|
||||||
|
ToSkip = (ToSkip + 1) & ~1;
|
||||||
|
|
||||||
|
if ((x + NumPixels) > Width)
|
||||||
|
NumPixels = Width - x;
|
||||||
|
|
||||||
|
if (NumPixels != 0)
|
||||||
|
{
|
||||||
|
DIB_1BPP_HLine(SurfObj, x, x + NumPixels, y, 1);
|
||||||
|
x += NumPixels;
|
||||||
|
}
|
||||||
|
i += ToSkip;
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
EngUnlockSurface(SurfObj);
|
||||||
|
return Mask;
|
||||||
|
}
|
||||||
|
|
||||||
W32KAPI
|
W32KAPI
|
||||||
INT
|
INT
|
||||||
APIENTRY
|
APIENTRY
|
||||||
|
@ -399,8 +508,8 @@ NtGdiSetDIBitsToDeviceInternal(
|
||||||
INT ret = 0;
|
INT ret = 0;
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
PDC pDC;
|
PDC pDC;
|
||||||
HBITMAP hSourceBitmap = NULL;
|
HBITMAP hSourceBitmap = NULL, hMaskBitmap = NULL;
|
||||||
SURFOBJ *pDestSurf, *pSourceSurf = NULL;
|
SURFOBJ *pDestSurf, *pSourceSurf = NULL, *pMaskSurf = NULL;
|
||||||
SURFACE *pSurf;
|
SURFACE *pSurf;
|
||||||
RECTL rcDest;
|
RECTL rcDest;
|
||||||
POINTL ptSource;
|
POINTL ptSource;
|
||||||
|
@ -492,6 +601,29 @@ NtGdiSetDIBitsToDeviceInternal(
|
||||||
goto Exit;
|
goto Exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* HACK: If this is a RLE bitmap, only the relevant pixels must be set. */
|
||||||
|
if ((bmi->bmiHeader.biCompression == BI_RLE8) || (bmi->bmiHeader.biCompression == BI_RLE4))
|
||||||
|
{
|
||||||
|
ASSERT(ScanLines == bmi->bmiHeader.biHeight);
|
||||||
|
hMaskBitmap = IntGdiCreateMaskFromRLE(bmi->bmiHeader.biWidth,
|
||||||
|
ScanLines,
|
||||||
|
bmi->bmiHeader.biCompression,
|
||||||
|
Bits,
|
||||||
|
cjMaxBits);
|
||||||
|
if (!hMaskBitmap)
|
||||||
|
{
|
||||||
|
EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
|
||||||
|
Status = STATUS_NO_MEMORY;
|
||||||
|
goto Exit;
|
||||||
|
}
|
||||||
|
pMaskSurf = EngLockSurface((HSURF)hMaskBitmap);
|
||||||
|
if (!pMaskSurf)
|
||||||
|
{
|
||||||
|
Status = STATUS_UNSUCCESSFUL;
|
||||||
|
goto Exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Create a palette for the DIB */
|
/* Create a palette for the DIB */
|
||||||
ppalDIB = CreateDIBPalette(bmi, pDC, ColorUse);
|
ppalDIB = CreateDIBPalette(bmi, pDC, ColorUse);
|
||||||
if (!ppalDIB)
|
if (!ppalDIB)
|
||||||
|
@ -529,15 +661,15 @@ NtGdiSetDIBitsToDeviceInternal(
|
||||||
ptSource.x, ptSource.y, SourceSize.cx, SourceSize.cy);
|
ptSource.x, ptSource.y, SourceSize.cx, SourceSize.cy);
|
||||||
Status = IntEngBitBlt(pDestSurf,
|
Status = IntEngBitBlt(pDestSurf,
|
||||||
pSourceSurf,
|
pSourceSurf,
|
||||||
NULL,
|
pMaskSurf,
|
||||||
&pDC->co.ClipObj,
|
&pDC->co.ClipObj,
|
||||||
&exlo.xlo,
|
&exlo.xlo,
|
||||||
&rcDest,
|
&rcDest,
|
||||||
&ptSource,
|
&ptSource,
|
||||||
|
pMaskSurf ? &ptSource : NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
pMaskSurf ? ROP4_MASK : ROP4_FROM_INDEX(R3_OPINDEX_SRCCOPY));
|
||||||
ROP4_FROM_INDEX(R3_OPINDEX_SRCCOPY));
|
|
||||||
|
|
||||||
/* Cleanup EXLATEOBJ */
|
/* Cleanup EXLATEOBJ */
|
||||||
EXLATEOBJ_vCleanup(&exlo);
|
EXLATEOBJ_vCleanup(&exlo);
|
||||||
|
@ -555,6 +687,8 @@ Exit:
|
||||||
|
|
||||||
if (pSourceSurf) EngUnlockSurface(pSourceSurf);
|
if (pSourceSurf) EngUnlockSurface(pSourceSurf);
|
||||||
if (hSourceBitmap) EngDeleteSurface((HSURF)hSourceBitmap);
|
if (hSourceBitmap) EngDeleteSurface((HSURF)hSourceBitmap);
|
||||||
|
if (pMaskSurf) EngUnlockSurface(pMaskSurf);
|
||||||
|
if (hMaskBitmap) EngDeleteSurface((HSURF)hMaskBitmap);
|
||||||
DC_UnlockDc(pDC);
|
DC_UnlockDc(pDC);
|
||||||
Exit2:
|
Exit2:
|
||||||
ExFreePoolWithTag(pbmiSafe, 'pmTG');
|
ExFreePoolWithTag(pbmiSafe, 'pmTG');
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue