mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 01:55:19 +00:00
[WIN32K] Revert NtGdiStretchDIBitsInternal to Previous Logic (#3774)
Fixes gdi32:dib / gdi32:bitmap tests and SIMS graphics. JIRA issue: CORE-16236
This commit is contained in:
parent
650cd77234
commit
847b037fe9
1 changed files with 242 additions and 119 deletions
|
@ -512,7 +512,7 @@ NtGdiSetDIBitsToDeviceInternal(
|
|||
ret = 0;
|
||||
goto Exit;
|
||||
}
|
||||
_SEH2_END
|
||||
_SEH2_END;
|
||||
|
||||
ScanLines = min(ScanLines, abs(bmi->bmiHeader.biHeight) - StartScan);
|
||||
if (ScanLines == 0)
|
||||
|
@ -1131,7 +1131,7 @@ NtGdiGetDIBitsInternal(
|
|||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
_SEH2_YIELD(goto cleanup;)
|
||||
goto cleanup;
|
||||
}
|
||||
_SEH2_END;
|
||||
|
||||
|
@ -1212,7 +1212,6 @@ NtGdiStretchDIBitsInternal(
|
|||
IN UINT cjMaxBits,
|
||||
IN HANDLE hcmXform)
|
||||
{
|
||||
BOOL bResult = FALSE;
|
||||
SIZEL sizel;
|
||||
RECTL rcSrc, rcDst;
|
||||
PDC pdc;
|
||||
|
@ -1220,7 +1219,69 @@ NtGdiStretchDIBitsInternal(
|
|||
PSURFACE psurfTmp = 0, psurfDst = 0;
|
||||
PPALETTE ppalDIB = 0;
|
||||
EXLATEOBJ exlo;
|
||||
PVOID pvBits;
|
||||
PBYTE pvBits;
|
||||
|
||||
LPBITMAPINFO pbmiSafe;
|
||||
UINT cjAlloc;
|
||||
HBITMAP hBitmap, hOldBitmap = NULL;
|
||||
HDC hdcMem;
|
||||
HPALETTE hPal = NULL;
|
||||
ULONG BmpFormat = 0;
|
||||
INT LinesCopied = 0;
|
||||
|
||||
/* Check for bad iUsage */
|
||||
if (dwUsage > 2) return 0;
|
||||
|
||||
/* We must have LPBITMAPINFO */
|
||||
if (!pbmi)
|
||||
{
|
||||
DPRINT1("Error, Invalid Parameter.\n");
|
||||
EngSetLastError(ERROR_INVALID_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check if the size of the bitmap info is large enough */
|
||||
if (cjMaxInfo < sizeof(BITMAPCOREHEADER))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Use maximum size */
|
||||
cjMaxInfo = min(cjMaxInfo, sizeof(BITMAPV5HEADER) + 256 * sizeof(RGBQUAD));
|
||||
|
||||
// HACK: the underlying code sucks and doesn't care for the size, so we
|
||||
// give it the maximum ever needed
|
||||
cjAlloc = sizeof(BITMAPV5HEADER) + 256 * sizeof(RGBQUAD);
|
||||
|
||||
/* Allocate a buffer the bitmapinfo */
|
||||
pbmiSafe = ExAllocatePoolWithTag(PagedPool, cjAlloc, 'imBG');
|
||||
if (!pbmiSafe)
|
||||
{
|
||||
/* Fail */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Use SEH */
|
||||
_SEH2_TRY
|
||||
{
|
||||
/* Probe and copy the BITMAPINFO */
|
||||
ProbeForRead(pbmi, cjMaxInfo, 1);
|
||||
RtlCopyMemory(pbmiSafe, pbmi, cjMaxInfo);
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
ExFreePoolWithTag(pbmiSafe, 'imBG');
|
||||
return 0;
|
||||
}
|
||||
_SEH2_END;
|
||||
|
||||
/* Check if the header size is large enough */
|
||||
if ((pbmiSafe->bmiHeader.biSize < sizeof(BITMAPCOREHEADER)) ||
|
||||
(pbmiSafe->bmiHeader.biSize > cjMaxInfo))
|
||||
{
|
||||
ExFreePoolWithTag(pbmiSafe, 'imBG');
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(pdc = DC_LockDc(hdc)))
|
||||
{
|
||||
|
@ -1242,31 +1303,9 @@ NtGdiStretchDIBitsInternal(
|
|||
IntLPtoDP(pdc, (POINTL*)&sizel, 1);
|
||||
DC_UnlockDc(pdc);
|
||||
|
||||
/* Check if we can use NtGdiSetDIBitsToDeviceInternal */
|
||||
if ((sizel.cx == cxSrc) && (sizel.cy == cySrc) && (dwRop == SRCCOPY))
|
||||
{
|
||||
/* Yes, we can! */
|
||||
return NtGdiSetDIBitsToDeviceInternal(hdc,
|
||||
xDst,
|
||||
yDst,
|
||||
cxDst,
|
||||
cyDst,
|
||||
xSrc,
|
||||
ySrc,
|
||||
0,
|
||||
cySrc,
|
||||
pjInit,
|
||||
pbmi,
|
||||
dwUsage,
|
||||
cjMaxBits,
|
||||
cjMaxInfo,
|
||||
TRUE,
|
||||
hcmXform);
|
||||
}
|
||||
|
||||
if (pjInit && (cjMaxBits > 0))
|
||||
{
|
||||
pvBits = ExAllocatePoolWithTag(PagedPool, cjMaxBits, 'pmeT');
|
||||
pvBits = ExAllocatePoolWithTag(PagedPool, cjMaxBits, TAG_DIB);
|
||||
if (!pvBits)
|
||||
{
|
||||
return 0;
|
||||
|
@ -1279,110 +1318,194 @@ NtGdiStretchDIBitsInternal(
|
|||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
ExFreePoolWithTag(pvBits, 'pmeT');
|
||||
_SEH2_YIELD(return 0);
|
||||
ExFreePoolWithTag(pvBits, TAG_DIB);
|
||||
return 0;
|
||||
}
|
||||
_SEH2_END
|
||||
_SEH2_END;
|
||||
}
|
||||
else
|
||||
{
|
||||
pvBits = NULL;
|
||||
}
|
||||
|
||||
/* FIXME: Locking twice is cheesy, coord tranlation in UM will fix it */
|
||||
if (!(pdc = DC_LockDc(hdc)))
|
||||
/* Here we select between the dwRop with SRCCOPY or not. */
|
||||
if (dwRop == SRCCOPY)
|
||||
{
|
||||
DPRINT1("Could not lock dc\n");
|
||||
EngSetLastError(ERROR_INVALID_HANDLE);
|
||||
goto cleanup;
|
||||
hdcMem = NtGdiCreateCompatibleDC(hdc);
|
||||
if (hdcMem == NULL)
|
||||
{
|
||||
DPRINT1("NtGdiCreateCompatibleDC failed to create hdc.\n");
|
||||
EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
|
||||
return 0;
|
||||
}
|
||||
|
||||
hBitmap = NtGdiCreateCompatibleBitmap(hdc,
|
||||
abs(pbmiSafe->bmiHeader.biWidth),
|
||||
abs(pbmiSafe->bmiHeader.biHeight));
|
||||
if (hBitmap == NULL)
|
||||
{
|
||||
DPRINT1("NtGdiCreateCompatibleBitmap failed to create bitmap.\n");
|
||||
DPRINT1("hdc : 0x%08x \n", hdc);
|
||||
DPRINT1("width : 0x%08x \n", pbmiSafe->bmiHeader.biWidth);
|
||||
DPRINT1("height : 0x%08x \n", pbmiSafe->bmiHeader.biHeight);
|
||||
EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Select the bitmap into hdcMem, and save a handle to the old bitmap */
|
||||
hOldBitmap = NtGdiSelectBitmap(hdcMem, hBitmap);
|
||||
|
||||
if (dwUsage == DIB_PAL_COLORS)
|
||||
{
|
||||
hPal = NtGdiGetDCObject(hdc, GDI_OBJECT_TYPE_PALETTE);
|
||||
hPal = GdiSelectPalette(hdcMem, hPal, FALSE);
|
||||
}
|
||||
|
||||
pdc = DC_LockDc(hdcMem);
|
||||
if (pdc != NULL)
|
||||
{
|
||||
IntSetDIBits(pdc, hBitmap, 0, abs(pbmiSafe->bmiHeader.biHeight), pvBits,
|
||||
cjMaxBits, pbmiSafe, dwUsage);
|
||||
DC_UnlockDc(pdc);
|
||||
}
|
||||
|
||||
/* Origin for DIBitmap may be bottom left (positive biHeight) or top
|
||||
left (negative biHeight) */
|
||||
if (cxSrc == cxDst && cySrc == cyDst)
|
||||
{
|
||||
NtGdiBitBlt(hdc, xDst, yDst, cxDst, cyDst,
|
||||
hdcMem, xSrc, abs(pbmiSafe->bmiHeader.biHeight) - cySrc - ySrc,
|
||||
dwRop, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
NtGdiStretchBlt(hdc, xDst, yDst, cxDst, cyDst,
|
||||
hdcMem, xSrc, abs(pbmiSafe->bmiHeader.biHeight) - cySrc - ySrc,
|
||||
cxSrc, cySrc, dwRop, 0);
|
||||
}
|
||||
|
||||
/* cleanup */
|
||||
if (hPal)
|
||||
GdiSelectPalette(hdcMem, hPal, FALSE);
|
||||
|
||||
if (hOldBitmap)
|
||||
NtGdiSelectBitmap(hdcMem, hOldBitmap);
|
||||
|
||||
NtGdiDeleteObjectApp(hdcMem);
|
||||
GreDeleteObject(hBitmap);
|
||||
|
||||
} /* End of dwRop == SRCCOPY */
|
||||
else
|
||||
{ /* Start of dwRop != SRCCOPY */
|
||||
/* FIXME: Locking twice is cheesy, coord tranlation in UM will fix it */
|
||||
if (!(pdc = DC_LockDc(hdc)))
|
||||
{
|
||||
DPRINT1("Could not lock dc\n");
|
||||
EngSetLastError(ERROR_INVALID_HANDLE);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Calculate source and destination rect */
|
||||
rcSrc.left = xSrc;
|
||||
rcSrc.top = ySrc;
|
||||
rcSrc.right = xSrc + abs(cxSrc);
|
||||
rcSrc.bottom = ySrc + abs(cySrc);
|
||||
rcDst.left = xDst;
|
||||
rcDst.top = yDst;
|
||||
rcDst.right = rcDst.left + cxDst;
|
||||
rcDst.bottom = rcDst.top + cyDst;
|
||||
IntLPtoDP(pdc, (POINTL*)&rcDst, 2);
|
||||
RECTL_vOffsetRect(&rcDst, pdc->ptlDCOrig.x, pdc->ptlDCOrig.y);
|
||||
|
||||
if (pdc->fs & (DC_ACCUM_APP|DC_ACCUM_WMGR))
|
||||
{
|
||||
IntUpdateBoundsRect(pdc, &rcDst);
|
||||
}
|
||||
|
||||
BmpFormat = BitmapFormat(pbmiSafe->bmiHeader.biBitCount,
|
||||
pbmiSafe->bmiHeader.biCompression);
|
||||
|
||||
hbmTmp = GreCreateBitmapEx(pbmiSafe->bmiHeader.biWidth,
|
||||
abs(pbmiSafe->bmiHeader.biHeight),
|
||||
0,
|
||||
BmpFormat,
|
||||
pbmiSafe->bmiHeader.biHeight < 0 ? BMF_TOPDOWN : 0,
|
||||
cjMaxBits,
|
||||
pvBits,
|
||||
0);
|
||||
|
||||
if (!hbmTmp)
|
||||
{
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
psurfTmp = SURFACE_ShareLockSurface(hbmTmp);
|
||||
if (!psurfTmp)
|
||||
{
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Create a palette for the DIB */
|
||||
ppalDIB = CreateDIBPalette(pbmiSafe, pdc, dwUsage);
|
||||
if (!ppalDIB)
|
||||
{
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Prepare DC for blit */
|
||||
DC_vPrepareDCsForBlit(pdc, &rcDst, NULL, NULL);
|
||||
|
||||
psurfDst = pdc->dclevel.pSurface;
|
||||
|
||||
/* Initialize XLATEOBJ */
|
||||
EXLATEOBJ_vInitialize(&exlo,
|
||||
ppalDIB,
|
||||
psurfDst->ppal,
|
||||
RGB(0xff, 0xff, 0xff),
|
||||
pdc->pdcattr->crBackgroundClr,
|
||||
pdc->pdcattr->crForegroundClr);
|
||||
|
||||
/* Perform the stretch operation */
|
||||
IntEngStretchBlt(&psurfDst->SurfObj,
|
||||
&psurfTmp->SurfObj,
|
||||
NULL,
|
||||
(CLIPOBJ *)&pdc->co,
|
||||
&exlo.xlo,
|
||||
&pdc->dclevel.ca,
|
||||
&rcDst,
|
||||
&rcSrc,
|
||||
NULL,
|
||||
&pdc->eboFill.BrushObject,
|
||||
NULL,
|
||||
WIN32_ROP3_TO_ENG_ROP4(dwRop));
|
||||
|
||||
/* Cleanup */
|
||||
DC_vFinishBlit(pdc, NULL);
|
||||
EXLATEOBJ_vCleanup(&exlo);
|
||||
|
||||
cleanup:
|
||||
if (ppalDIB) PALETTE_ShareUnlockPalette(ppalDIB);
|
||||
if (psurfTmp) SURFACE_ShareUnlockSurface(psurfTmp);
|
||||
if (hbmTmp) GreDeleteObject(hbmTmp);
|
||||
if (pdc) DC_UnlockDc(pdc);
|
||||
}
|
||||
|
||||
/* Calculate source and destination rect */
|
||||
rcSrc.left = xSrc;
|
||||
rcSrc.top = ySrc;
|
||||
rcSrc.right = xSrc + abs(cxSrc);
|
||||
rcSrc.bottom = ySrc + abs(cySrc);
|
||||
rcDst.left = xDst;
|
||||
rcDst.top = yDst;
|
||||
rcDst.right = rcDst.left + cxDst;
|
||||
rcDst.bottom = rcDst.top + cyDst;
|
||||
IntLPtoDP(pdc, (POINTL*)&rcDst, 2);
|
||||
RECTL_vOffsetRect(&rcDst, pdc->ptlDCOrig.x, pdc->ptlDCOrig.y);
|
||||
if (pbmiSafe) ExFreePoolWithTag(pbmiSafe, 'imBG');
|
||||
if (pvBits) ExFreePoolWithTag(pvBits, TAG_DIB);
|
||||
|
||||
if (pdc->fs & (DC_ACCUM_APP|DC_ACCUM_WMGR))
|
||||
/* This is not what MSDN says is returned from this function, but it
|
||||
* follows Wine's dlls/gdi32/dib.c function nulldrv_StretchDIBits
|
||||
* and it fixes over 100 gdi32:dib regression tests. */
|
||||
if (dwRop == SRCCOPY)
|
||||
{
|
||||
IntUpdateBoundsRect(pdc, &rcDst);
|
||||
LinesCopied = abs(pbmiSafe->bmiHeader.biHeight);
|
||||
}
|
||||
else
|
||||
{
|
||||
LinesCopied = pbmiSafe->bmiHeader.biHeight;
|
||||
}
|
||||
|
||||
hbmTmp = GreCreateBitmapEx(pbmi->bmiHeader.biWidth,
|
||||
abs(pbmi->bmiHeader.biHeight),
|
||||
0,
|
||||
BitmapFormat(pbmi->bmiHeader.biBitCount,
|
||||
pbmi->bmiHeader.biCompression),
|
||||
pbmi->bmiHeader.biHeight < 0 ? BMF_TOPDOWN : 0,
|
||||
cjMaxBits,
|
||||
pvBits,
|
||||
0);
|
||||
|
||||
if (!hbmTmp)
|
||||
{
|
||||
bResult = FALSE;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
psurfTmp = SURFACE_ShareLockSurface(hbmTmp);
|
||||
if (!psurfTmp)
|
||||
{
|
||||
bResult = FALSE;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Create a palette for the DIB */
|
||||
ppalDIB = CreateDIBPalette(pbmi, pdc, dwUsage);
|
||||
if (!ppalDIB)
|
||||
{
|
||||
bResult = FALSE;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Prepare DC for blit */
|
||||
DC_vPrepareDCsForBlit(pdc, &rcDst, NULL, NULL);
|
||||
|
||||
psurfDst = pdc->dclevel.pSurface;
|
||||
|
||||
/* Initialize XLATEOBJ */
|
||||
EXLATEOBJ_vInitialize(&exlo,
|
||||
ppalDIB,
|
||||
psurfDst->ppal,
|
||||
RGB(0xff, 0xff, 0xff),
|
||||
pdc->pdcattr->crBackgroundClr,
|
||||
pdc->pdcattr->crForegroundClr);
|
||||
|
||||
/* Perform the stretch operation */
|
||||
bResult = IntEngStretchBlt(&psurfDst->SurfObj,
|
||||
&psurfTmp->SurfObj,
|
||||
NULL,
|
||||
(CLIPOBJ *)&pdc->co,
|
||||
&exlo.xlo,
|
||||
&pdc->dclevel.ca,
|
||||
&rcDst,
|
||||
&rcSrc,
|
||||
NULL,
|
||||
&pdc->eboFill.BrushObject,
|
||||
NULL,
|
||||
WIN32_ROP3_TO_ENG_ROP4(dwRop));
|
||||
|
||||
/* Cleanup */
|
||||
DC_vFinishBlit(pdc, NULL);
|
||||
EXLATEOBJ_vCleanup(&exlo);
|
||||
cleanup:
|
||||
if (ppalDIB) PALETTE_ShareUnlockPalette(ppalDIB);
|
||||
if (psurfTmp) SURFACE_ShareUnlockSurface(psurfTmp);
|
||||
if (hbmTmp) GreDeleteObject(hbmTmp);
|
||||
if (pdc) DC_UnlockDc(pdc);
|
||||
if (pvBits) ExFreePoolWithTag(pvBits, 'pmeT');
|
||||
|
||||
return bResult;
|
||||
return LinesCopied;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1533,7 +1656,7 @@ NtGdiCreateDIBitmapInternal(
|
|||
{
|
||||
Status = _SEH2_GetExceptionCode();
|
||||
}
|
||||
_SEH2_END
|
||||
_SEH2_END;
|
||||
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
|
@ -1715,7 +1838,7 @@ NtGdiCreateDIBSection(
|
|||
{
|
||||
Status = _SEH2_GetExceptionCode();
|
||||
}
|
||||
_SEH2_END
|
||||
_SEH2_END;
|
||||
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue