Author: jgardou
Date: Sat Aug 23 14:20:16 2014
New Revision: 63920
URL:
http://svn.reactos.org/svn/reactos?rev=63920&view=rev
Log:
[WIN32K]
- Improve the "infamous RLE hack" in SetDIBitsToDevice by using a mask bitmap
corresponding to the valid RLE data
[GDI32]
- Improve some input checks
Modified:
trunk/reactos/win32ss/gdi/gdi32/objects/bitmap.c
trunk/reactos/win32ss/gdi/gdi32/objects/utils.c
trunk/reactos/win32ss/gdi/ntgdi/dibobj.c
Modified: trunk/reactos/win32ss/gdi/gdi32/objects/bitmap.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/gdi/gdi32/objects/…
==============================================================================
--- trunk/reactos/win32ss/gdi/gdi32/objects/bitmap.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/gdi/gdi32/objects/bitmap.c [iso-8859-1] Sat Aug 23 14:20:16
2014
@@ -671,8 +671,7 @@
if (ColorUse && ColorUse != DIB_PAL_COLORS && ColorUse !=
DIB_PAL_COLORS + 1)
return 0;
- pConvertedInfo = ConvertBitmapInfo(lpbmi, ColorUse, &ConvertedInfoSize,
- FALSE);
+ pConvertedInfo = ConvertBitmapInfo(lpbmi, ColorUse, &ConvertedInfoSize, FALSE);
if (!pConvertedInfo)
return 0;
@@ -720,6 +719,15 @@
}
}
#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);
pvSafeBits = RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize);
Modified: trunk/reactos/win32ss/gdi/gdi32/objects/utils.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/gdi/gdi32/objects/…
==============================================================================
--- trunk/reactos/win32ss/gdi/gdi32/objects/utils.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/gdi/gdi32/objects/utils.c [iso-8859-1] Sat Aug 23 14:20:16 2014
@@ -296,6 +296,35 @@
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;
if (ColorSpec == DIB_RGB_COLORS)
Modified: trunk/reactos/win32ss/gdi/ntgdi/dibobj.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/gdi/ntgdi/dibobj.c…
==============================================================================
--- trunk/reactos/win32ss/gdi/ntgdi/dibobj.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/gdi/ntgdi/dibobj.c [iso-8859-1] Sat Aug 23 14:20:16 2014
@@ -375,6 +375,115 @@
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
INT
APIENTRY
@@ -399,8 +508,8 @@
INT ret = 0;
NTSTATUS Status = STATUS_SUCCESS;
PDC pDC;
- HBITMAP hSourceBitmap = NULL;
- SURFOBJ *pDestSurf, *pSourceSurf = NULL;
+ HBITMAP hSourceBitmap = NULL, hMaskBitmap = NULL;
+ SURFOBJ *pDestSurf, *pSourceSurf = NULL, *pMaskSurf = NULL;
SURFACE *pSurf;
RECTL rcDest;
POINTL ptSource;
@@ -492,6 +601,29 @@
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 */
ppalDIB = CreateDIBPalette(bmi, pDC, ColorUse);
if (!ppalDIB)
@@ -529,15 +661,15 @@
ptSource.x, ptSource.y, SourceSize.cx, SourceSize.cy);
Status = IntEngBitBlt(pDestSurf,
pSourceSurf,
- NULL,
+ pMaskSurf,
&pDC->co.ClipObj,
&exlo.xlo,
&rcDest,
&ptSource,
+ pMaskSurf ? &ptSource : NULL,
NULL,
NULL,
- NULL,
- ROP4_FROM_INDEX(R3_OPINDEX_SRCCOPY));
+ pMaskSurf ? ROP4_MASK : ROP4_FROM_INDEX(R3_OPINDEX_SRCCOPY));
/* Cleanup EXLATEOBJ */
EXLATEOBJ_vCleanup(&exlo);
@@ -555,6 +687,8 @@
if (pSourceSurf) EngUnlockSurface(pSourceSurf);
if (hSourceBitmap) EngDeleteSurface((HSURF)hSourceBitmap);
+ if (pMaskSurf) EngUnlockSurface(pMaskSurf);
+ if (hMaskBitmap) EngDeleteSurface((HSURF)hMaskBitmap);
DC_UnlockDc(pDC);
Exit2:
ExFreePoolWithTag(pbmiSafe, 'pmTG');