From e43f7b0dfaf9862cbf2c8fe8490979326550a30a Mon Sep 17 00:00:00 2001 From: Timo Kreuzer Date: Thu, 26 Apr 2012 16:19:22 +0000 Subject: [PATCH] [WIN32K] - Implement TranslateCOLORREF, based on IntHandleSpecialColorType, but now returning both the translated color and the resulting RGB color, correctly handling DIBINDEX, which will use the given value without translation. - Rewrite NtGdiSetPixel using IntPatBlt - Rewrite NtGdiGetPixel using IntEngCopyBits - Fix EXLATEOBJ_iXlateTable to return 0, when the palette index is too big, instead of wrapping around - Remove old debugcode svn path=/trunk/; revision=56429 --- reactos/win32ss/gdi/eng/engbrush.c | 4 +- reactos/win32ss/gdi/eng/xlate.c | 5 +- reactos/win32ss/gdi/ntgdi/bitblt.c | 217 ++++++- reactos/win32ss/gdi/ntgdi/bitmaps.c | 207 ------ reactos/win32ss/gdi/ntgdi/brush.h | 11 +- reactos/win32ss/gdi/ntgdi/dcobjs.c | 8 +- reactos/win32ss/gdi/ntgdi/patblt.c | 972 ++++++++++++++++++++++++++++ 7 files changed, 1201 insertions(+), 223 deletions(-) create mode 100644 reactos/win32ss/gdi/ntgdi/patblt.c diff --git a/reactos/win32ss/gdi/eng/engbrush.c b/reactos/win32ss/gdi/eng/engbrush.c index 522a3333f8c..898d9bbd85c 100644 --- a/reactos/win32ss/gdi/eng/engbrush.c +++ b/reactos/win32ss/gdi/eng/engbrush.c @@ -47,7 +47,7 @@ EBRUSHOBJ_vInit(EBRUSHOBJ *pebo, PBRUSH pbrush, PDC pdc) else if (pbrush->flAttrs & GDIBRUSH_IS_SOLID) { /* Set the RGB color */ - EBRUSHOBJ_vSetSolidBrushColor(pebo, pbrush->BrushAttr.lbColor); + EBRUSHOBJ_vSetSolidRGBColor(pebo, pbrush->BrushAttr.lbColor); } else { @@ -62,7 +62,7 @@ EBRUSHOBJ_vInit(EBRUSHOBJ *pebo, PBRUSH pbrush, PDC pdc) VOID FASTCALL -EBRUSHOBJ_vSetSolidBrushColor(EBRUSHOBJ *pebo, COLORREF crColor) +EBRUSHOBJ_vSetSolidRGBColor(EBRUSHOBJ *pebo, COLORREF crColor) { ULONG iSolidColor; EXLATEOBJ exlo; diff --git a/reactos/win32ss/gdi/eng/xlate.c b/reactos/win32ss/gdi/eng/xlate.c index b80e950800b..1125bc9bceb 100644 --- a/reactos/win32ss/gdi/eng/xlate.c +++ b/reactos/win32ss/gdi/eng/xlate.c @@ -49,10 +49,7 @@ ULONG FASTCALL EXLATEOBJ_iXlateTable(PEXLATEOBJ pexlo, ULONG iColor) { - if (iColor >= pexlo->xlo.cEntries) - { - iColor %= pexlo->xlo.cEntries; - } + if (iColor >= pexlo->xlo.cEntries) return 0; return pexlo->xlo.pulXlate[iColor]; } diff --git a/reactos/win32ss/gdi/ntgdi/bitblt.c b/reactos/win32ss/gdi/ntgdi/bitblt.c index 50a367669cc..0fbab55e865 100644 --- a/reactos/win32ss/gdi/ntgdi/bitblt.c +++ b/reactos/win32ss/gdi/ntgdi/bitblt.c @@ -17,6 +17,79 @@ #define FIXUP_ROP(Rop) if(((Rop) & 0xFF000000) == 0) Rop = MAKEROP4((Rop), (Rop)) #define ROP_TO_ROP4(Rop) ((Rop) >> 16) +ULONG +TranslateCOLORREF(PDC pdc, COLORREF *pcrColor) +{ + PPALETTE ppalDC, ppalSurface; + ULONG index, ulColor, iBitmapFormat; + COLORREF crColor = *pcrColor; + EXLATEOBJ exlo; + + switch (crColor >> 24) + { + case 0x00: /* RGB color */ + break; + + case 0x01: /* PALETTEINDEX */ + index = crColor & 0xFFFFFF; + ppalDC = pdc->dclevel.ppal; + if (index >= ppalDC->NumColors) index = 0; + + /* Get the RGB value */ + crColor = PALETTE_ulGetRGBColorFromIndex(ppalDC, index); + *pcrColor = crColor; + break; + + case 0x02: /* PALETTERGB */ + + /* First find the nearest index in the dc palette */ + ppalDC = pdc->dclevel.ppal; + index = PALETTE_ulGetNearestIndex(ppalDC, crColor & 0xFFFFFF); + + /* Get the RGB value */ + crColor = PALETTE_ulGetRGBColorFromIndex(ppalDC, index); + *pcrColor = crColor; + break; + + case 0x10: /* DIBINDEX */ + /* Mask the value to match the target bpp */ + iBitmapFormat = pdc->dclevel.pSurface->SurfObj.iBitmapFormat; + if (iBitmapFormat == BMF_1BPP) index = crColor & 0x1; + else if (iBitmapFormat == BMF_4BPP) index = crColor & 0xf; + else if (iBitmapFormat == BMF_8BPP) index = crColor & 0xFF; + else if (iBitmapFormat == BMF_16BPP) index = crColor & 0xFFFF; + else index = crColor & 0xFFFFFF; + + /* Translate the color to RGB for the caller */ + ppalSurface = pdc->dclevel.pSurface->ppal; + if (index < ppalSurface->NumColors) + *pcrColor = PALETTE_ulGetRGBColorFromIndex(ppalSurface, index); + else + *pcrColor = 0; + return index; + + default: + DPRINT("Unsupported color type %d passed\n", crColor >> 24); + return 0; + } + + /* Initialize an XLATEOBJ from RGB to the target surface */ + EXLATEOBJ_vInitialize(&exlo, + &gpalRGB, + pdc->dclevel.pSurface->ppal, + 0, + pdc->pdcattr->crBackgroundClr, + pdc->pdcattr->crForegroundClr); + + /* Translate the color to the target format */ + ulColor = XLATEOBJ_iXlate(&exlo.xlo, crColor); + + /* Cleanup and return the RGB value */ + EXLATEOBJ_vCleanup(&exlo); + return ulColor; +} + + BOOL APIENTRY NtGdiAlphaBlend( HDC hDCDest, @@ -874,17 +947,17 @@ NtGdiPatBlt( _In_ INT y, _In_ INT cx, _In_ INT cy, - _In_ DWORD rop4) + _In_ DWORD dwRop) { BOOL bResult; PDC pdc; /* Mask away everything except foreground rop index */ - rop4 = rop4 & 0x00FF0000; - rop4 |= rop4 << 8; + dwRop = dwRop & 0x00FF0000; + dwRop |= dwRop << 8; /* Check if the rop uses a source */ - if (ROP_USES_SOURCE(rop4)) + if (ROP_USES_SOURCE(dwRop)) { /* This is not possible */ return 0; @@ -911,7 +984,7 @@ NtGdiPatBlt( DC_vUpdateFillBrush(pdc); /* Call the internal function */ - bResult = IntPatBlt(pdc, x, y, cx, cy, rop4, &pdc->eboFill); + bResult = IntPatBlt(pdc, x, y, cx, cy, dwRop, &pdc->eboFill); /* Unlock the DC and return the result */ DC_UnlockDc(pdc); @@ -969,3 +1042,137 @@ NtGdiPolyPatBlt( return Ret; } + + +COLORREF +APIENTRY +NtGdiSetPixel( + _In_ HDC hdc, + _In_ INT x, + _In_ INT y, + _In_ COLORREF crColor) +{ + PDC pdc; + ULONG iOldColor, iSolidColor; + BOOL bResult; + PEBRUSHOBJ pebo; + ULONG ulDirty; + + /* Lock the DC */ + pdc = DC_LockDc(hdc); + if (!pdc) + { + EngSetLastError(ERROR_INVALID_HANDLE); + return -1; + } + + /* Check if the DC has no surface (empty mem or info DC) */ + if (pdc->dclevel.pSurface == NULL) + { + /* Fail! */ + DC_UnlockDc(pdc); + return -1; + } + + /* Translate the color to the target format and get the RGB value */ + iSolidColor = TranslateCOLORREF(pdc, &crColor); + + /* Use the DC's text brush, which is always a solid brush */ + pebo = &pdc->eboText; + + /* Save the old solid color and set the one for the pixel */ + iOldColor = EBRUSHOBJ_iSetSolidColor(pebo, iSolidColor); + + /* Save dirty flags and reset dirty text brush flag */ + ulDirty = pdc->pdcattr->ulDirty_; + pdc->pdcattr->ulDirty_ &= ~DIRTY_TEXT; + + /* Call the internal function */ + bResult = IntPatBlt(pdc, x, y, 1, 1, PATCOPY, pebo); + + /* Restore old text brush color and dirty flags */ + EBRUSHOBJ_iSetSolidColor(pebo, iOldColor); + pdc->pdcattr->ulDirty_ = ulDirty; + + /* Unlock the DC */ + DC_UnlockDc(pdc); + + /* Return the new RGB color or -1 on failure */ + return bResult ? crColor : -1; +} + +COLORREF +APIENTRY +NtGdiGetPixel( + _In_ HDC hdc, + _In_ INT x, + _In_ INT y) +{ + PDC pdc; + ULONG ulRGBColor; + BOOL bResult = FALSE; + POINTL ptlSrc; + PSURFACE psurfSrc, psurfDest; + + /* Lock the DC */ + pdc = DC_LockDc(hdc); + if (!pdc) + { + EngSetLastError(ERROR_INVALID_HANDLE); + return -1; + } + + /* Check if the DC has no surface (empty mem or info DC) */ + psurfSrc = pdc->dclevel.pSurface; + if (psurfSrc == NULL) + { + /* Fail! */ + DC_UnlockDc(pdc); + return -1; + } + + /* Get the logical coordinates */ + ptlSrc.x = x; + ptlSrc.y = y; + + /* Translate coordinates to device coordinates */ + IntLPtoDP(pdc, &ptlSrc, 1); + ptlSrc.x += pdc->ptlDCOrig.x; + ptlSrc.y += pdc->ptlDCOrig.y; + + /* Allocate a surface */ + psurfDest = SURFACE_AllocSurface(STYPE_BITMAP, 1, 1, BMF_32BPP); + if (psurfDest) + { + /* Set the bitmap bits */ + if (SURFACE_bSetBitmapBits(psurfDest, 0, 0, &ulRGBColor)) + { + RECTL rclDest = {0, 0, 1, 1}; + EXLATEOBJ exlo; + + /* Translate from the source palette to RGB color */ + EXLATEOBJ_vInitialize(&exlo, psurfSrc->ppal, &gpalRGB, 0, 0, 0); + + /* Call the copy bits function */ + bResult = IntEngCopyBits(&psurfDest->SurfObj, + &psurfSrc->SurfObj, + pdc->rosdc.CombinedClip, + &exlo.xlo, + &rclDest, + &ptlSrc); + + /* Cleanup the XLATEOBJ */ + EXLATEOBJ_vCleanup(&exlo); + } + + /* Delete the surface */ + GDIOBJ_vDeleteObject(&psurfDest->BaseObject); + } + + /* Unlock the DC */ + DC_UnlockDc(pdc); + + /* Return the new RGB color or -1 on failure */ + return bResult ? ulRGBColor : -1; +} + diff --git a/reactos/win32ss/gdi/ntgdi/bitmaps.c b/reactos/win32ss/gdi/ntgdi/bitmaps.c index 185ff6ecc28..141cc6df5a7 100644 --- a/reactos/win32ss/gdi/ntgdi/bitmaps.c +++ b/reactos/win32ss/gdi/ntgdi/bitmaps.c @@ -385,103 +385,6 @@ NtGdiGetBitmapDimension( return Ret; } -COLORREF APIENTRY -NtGdiGetPixel(HDC hDC, INT XPos, INT YPos) -{ - PDC dc = NULL; - COLORREF Result = (COLORREF)CLR_INVALID; // Default to failure - BOOL bInRect = FALSE; - SURFACE *psurf; - SURFOBJ *pso; - EXLATEOBJ exlo; - HBITMAP hBmpTmp; - - dc = DC_LockDc(hDC); - - if (!dc) - { - EngSetLastError(ERROR_INVALID_HANDLE); - return Result; - } - - if (dc->dctype == DC_TYPE_INFO) - { - DC_UnlockDc(dc); - return Result; - } - - XPos += dc->ptlDCOrig.x; - YPos += dc->ptlDCOrig.y; - if ((dc->rosdc.CombinedClip == NULL) || - (RECTL_bPointInRect(&dc->rosdc.CombinedClip->rclBounds, XPos, YPos))) - { - bInRect = TRUE; - psurf = dc->dclevel.pSurface; - if (psurf) - { - pso = &psurf->SurfObj; - EXLATEOBJ_vInitialize(&exlo, psurf->ppal, &gpalRGB, 0, 0xffffff, 0); - // Check if this DC has a DIB behind it... - if (pso->pvScan0) // STYPE_BITMAP == pso->iType - { - ASSERT(pso->lDelta); - Result = XLATEOBJ_iXlate(&exlo.xlo, - DibFunctionsForBitmapFormat[pso->iBitmapFormat].DIB_GetPixel(pso, XPos, YPos)); - } - - EXLATEOBJ_vCleanup(&exlo); - } - } - DC_UnlockDc(dc); - - // If Result is still CLR_INVALID, then the "quick" method above didn't work - if (bInRect && Result == CLR_INVALID) - { - // FIXME: create a 1x1 32BPP DIB, and blit to it - HDC hDCTmp = NtGdiCreateCompatibleDC(hDC); - if (hDCTmp) - { - static const BITMAPINFOHEADER bih = { sizeof(BITMAPINFOHEADER), 1, 1, 1, 32, BI_RGB, 0, 0, 0, 0, 0 }; - BITMAPINFO bi; - RtlMoveMemory(&(bi.bmiHeader), &bih, sizeof(bih)); - hBmpTmp = NtGdiCreateDIBitmapInternal(hDC, - bi.bmiHeader.biWidth, - bi.bmiHeader.biHeight, - 0, - NULL, - &bi, - DIB_RGB_COLORS, - bi.bmiHeader.biBitCount, - bi.bmiHeader.biSizeImage, - 0, - 0); - - //HBITMAP hBmpTmp = GreCreateBitmap(1, 1, 1, 32, NULL); - if (hBmpTmp) - { - HBITMAP hBmpOld = (HBITMAP)NtGdiSelectBitmap(hDCTmp, hBmpTmp); - if (hBmpOld) - { - NtGdiBitBlt(hDCTmp, 0, 0, 1, 1, hDC, XPos, YPos, SRCCOPY, 0, 0); - NtGdiSelectBitmap(hDCTmp, hBmpOld); - - // Our bitmap is no longer selected, so we can access it's stuff... - psurf = SURFACE_ShareLockSurface(hBmpTmp); - if (psurf) - { - // Dont you need to convert something here? - Result = *(COLORREF*)psurf->SurfObj.pvScan0; - SURFACE_ShareUnlockSurface(psurf); - } - } - GreDeleteObject(hBmpTmp); - } - NtGdiDeleteObjectApp(hDCTmp); - } - } - - return Result; -} VOID FASTCALL @@ -653,116 +556,6 @@ NtGdiSetBitmapDimension( return Ret; } -VOID IntHandleSpecialColorType(HDC hDC, COLORREF* Color) -{ - PDC pdc = NULL; - RGBQUAD quad; - PALETTEENTRY palEntry; - UINT index; - - switch (*Color >> 24) - { - case 0x10: /* DIBINDEX */ - if (IntGetDIBColorTable(hDC, LOWORD(*Color), 1, &quad) == 1) - { - *Color = RGB(quad.rgbRed, quad.rgbGreen, quad.rgbBlue); - } - else - { - /* Out of color table bounds - use black */ - *Color = RGB(0, 0, 0); - } - break; - case 0x02: /* PALETTERGB */ - pdc = DC_LockDc(hDC); - if (pdc->dclevel.hpal != NtGdiGetStockObject(DEFAULT_PALETTE)) - { - index = NtGdiGetNearestPaletteIndex(pdc->dclevel.hpal, *Color); - IntGetPaletteEntries(pdc->dclevel.hpal, index, 1, &palEntry); - *Color = RGB(palEntry.peRed, palEntry.peGreen, palEntry.peBlue); - } - else - { - /* Use the pure color */ - *Color = *Color & 0x00FFFFFF; - } - DC_UnlockDc(pdc); - break; - case 0x01: /* PALETTEINDEX */ - pdc = DC_LockDc(hDC); - if (IntGetPaletteEntries(pdc->dclevel.hpal, LOWORD(*Color), 1, &palEntry) == 1) - { - *Color = RGB(palEntry.peRed, palEntry.peGreen, palEntry.peBlue); - } - else - { - /* Index does not exist, use zero index */ - IntGetPaletteEntries(pdc->dclevel.hpal, 0, 1, &palEntry); - *Color = RGB(palEntry.peRed, palEntry.peGreen, palEntry.peBlue); - } - DC_UnlockDc(pdc); - break; - default: - DPRINT("Unsupported color type %d passed\n", *Color >> 24); - break; - } -} - -BOOL APIENTRY -GdiSetPixelV( - HDC hDC, - INT X, - INT Y, - COLORREF Color) -{ - HBRUSH hBrush; - HGDIOBJ OldBrush; - - if ((Color & 0xFF000000) != 0) - { - IntHandleSpecialColorType(hDC, &Color); - } - - hBrush = NtGdiCreateSolidBrush(Color, NULL); - if (hBrush == NULL) - return FALSE; - - OldBrush = NtGdiSelectBrush(hDC, hBrush); - if (OldBrush == NULL) - { - GreDeleteObject(hBrush); - return FALSE; - } - - NtGdiPatBlt(hDC, X, Y, 1, 1, PATCOPY); - NtGdiSelectBrush(hDC, OldBrush); - GreDeleteObject(hBrush); - - return TRUE; -} - -COLORREF APIENTRY -NtGdiSetPixel( - HDC hDC, - INT X, - INT Y, - COLORREF Color) -{ - DPRINT("0 NtGdiSetPixel X %ld Y %ld C %ld\n", X, Y, Color); - - if (GdiSetPixelV(hDC,X,Y,Color)) - { - Color = NtGdiGetPixel(hDC,X,Y); - DPRINT("1 NtGdiSetPixel X %ld Y %ld C %ld\n", X, Y, Color); - return Color; - } - - Color = (COLORREF)CLR_INVALID; - DPRINT("2 NtGdiSetPixel X %ld Y %ld C %ld\n", X, Y, Color); - return Color; -} - - /* Internal Functions */ HBITMAP diff --git a/reactos/win32ss/gdi/ntgdi/brush.h b/reactos/win32ss/gdi/ntgdi/brush.h index 64e161fe4a2..be4323aa7b7 100644 --- a/reactos/win32ss/gdi/ntgdi/brush.h +++ b/reactos/win32ss/gdi/ntgdi/brush.h @@ -104,7 +104,7 @@ EBRUSHOBJ_vInit(EBRUSHOBJ *pebo, PBRUSH pbrush, struct _DC *); VOID FASTCALL -EBRUSHOBJ_vSetSolidBrushColor(EBRUSHOBJ *pebo, COLORREF crColor); +EBRUSHOBJ_vSetSolidRGBColor(EBRUSHOBJ *pebo, COLORREF crColor); VOID NTAPI @@ -129,6 +129,15 @@ EBRUSHOBJ_psoPattern(EBRUSHOBJ *pebo); #define BRUSHOBJ_psoPattern(pbo) \ EBRUSHOBJ_psoPattern(CONTAINING_RECORD(pbo, EBRUSHOBJ, BrushObject)) +ULONG +FORCEINLINE +EBRUSHOBJ_iSetSolidColor(EBRUSHOBJ *pebo, ULONG iSolidColor) +{ + ULONG iOldColor = pebo->BrushObject.iSolidColor; + pebo->BrushObject.iSolidColor = iSolidColor; + return iOldColor; +} + BOOL FASTCALL IntGdiSetBrushOwner(PBRUSH,DWORD); BOOL FASTCALL GreSetBrushOwner(HBRUSH,DWORD); diff --git a/reactos/win32ss/gdi/ntgdi/dcobjs.c b/reactos/win32ss/gdi/ntgdi/dcobjs.c index 52611258760..29310c570fa 100644 --- a/reactos/win32ss/gdi/ntgdi/dcobjs.c +++ b/reactos/win32ss/gdi/ntgdi/dcobjs.c @@ -51,7 +51,7 @@ DC_vUpdateFillBrush(PDC pdc) { /* ROS HACK, should use surf xlate */ /* Update the eboFill's solid color */ - EBRUSHOBJ_vSetSolidBrushColor(&pdc->eboFill, pdcattr->crPenClr); + EBRUSHOBJ_vSetSolidRGBColor(&pdc->eboFill, pdcattr->crPenClr); } /* Clear flags */ @@ -97,7 +97,7 @@ DC_vUpdateLineBrush(PDC pdc) if (pdcattr->hpen == StockObjects[DC_PEN]) { /* Update the eboLine's solid color */ - EBRUSHOBJ_vSetSolidBrushColor(&pdc->eboLine, pdcattr->crPenClr); + EBRUSHOBJ_vSetSolidRGBColor(&pdc->eboLine, pdcattr->crPenClr); } /* Clear flags */ @@ -116,7 +116,7 @@ DC_vUpdateTextBrush(PDC pdc) EBRUSHOBJ_vUpdate(&pdc->eboText, pbrDefaultBrush, pdc); /* Update the eboText's solid color */ - EBRUSHOBJ_vSetSolidBrushColor(&pdc->eboText, pdcattr->crForegroundClr); + EBRUSHOBJ_vSetSolidRGBColor(&pdc->eboText, pdcattr->crForegroundClr); /* Clear flag */ pdcattr->ulDirty_ &= ~DIRTY_TEXT; @@ -132,7 +132,7 @@ DC_vUpdateBackgroundBrush(PDC pdc) EBRUSHOBJ_vUpdate(&pdc->eboBackground, pbrDefaultBrush, pdc); /* Update the eboBackground's solid color */ - EBRUSHOBJ_vSetSolidBrushColor(&pdc->eboBackground, pdcattr->crBackgroundClr); + EBRUSHOBJ_vSetSolidRGBColor(&pdc->eboBackground, pdcattr->crBackgroundClr); /* Clear flag */ pdcattr->ulDirty_ &= ~DIRTY_BACKGROUND; diff --git a/reactos/win32ss/gdi/ntgdi/patblt.c b/reactos/win32ss/gdi/ntgdi/patblt.c new file mode 100644 index 00000000000..b809395f3eb --- /dev/null +++ b/reactos/win32ss/gdi/ntgdi/patblt.c @@ -0,0 +1,972 @@ +/* + * COPYRIGHT: GNU GPL, See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Bit blit functions + * FILE: subsys/win32k/objects/bitblt.c + * PROGRAMER: Unknown + */ + +#include + +#define NDEBUG +#include + +#define ROP_USES_SOURCE(Rop) (((((Rop) & 0xCC0000) >> 2) != ((Rop) & 0x330000)) || ((((Rop) & 0xCC000000) >> 2) != ((Rop) & 0x33000000))) +#define ROP_USES_MASK(Rop) (((Rop) & 0xFF000000) != (((Rop) & 0xff0000) << 8)) + +#define FIXUP_ROP(Rop) if(((Rop) & 0xFF000000) == 0) Rop = MAKEROP4((Rop), (Rop)) +#define ROP_TO_ROP4(Rop) ((Rop) >> 16) + +BOOL APIENTRY +NtGdiAlphaBlend( + HDC hDCDest, + LONG XOriginDest, + LONG YOriginDest, + LONG WidthDest, + LONG HeightDest, + HDC hDCSrc, + LONG XOriginSrc, + LONG YOriginSrc, + LONG WidthSrc, + LONG HeightSrc, + BLENDFUNCTION BlendFunc, + HANDLE hcmXform) +{ + PDC DCDest; + PDC DCSrc; + HDC ahDC[2]; + PGDIOBJ apObj[2]; + SURFACE *BitmapDest, *BitmapSrc; + RECTL DestRect, SourceRect; + BOOL bResult; + EXLATEOBJ exlo; + BLENDOBJ BlendObj; + BlendObj.BlendFunction = BlendFunc; + + if (WidthDest < 0 || HeightDest < 0 || WidthSrc < 0 || HeightSrc < 0) + { + EngSetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + DPRINT("Locking DCs\n"); + ahDC[0] = hDCDest; + ahDC[1] = hDCSrc ; + if (!GDIOBJ_bLockMultipleObjects(2, ahDC, apObj, GDIObjType_DC_TYPE)) + { + DPRINT1("Invalid dc handle (dest=0x%08x, src=0x%08x) passed to NtGdiAlphaBlend\n", hDCDest, hDCSrc); + EngSetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + DCDest = apObj[0]; + DCSrc = apObj[1]; + + if (DCDest->dctype == DC_TYPE_INFO || DCDest->dctype == DCTYPE_INFO) + { + GDIOBJ_vUnlockObject(&DCSrc->BaseObject); + GDIOBJ_vUnlockObject(&DCDest->BaseObject); + /* Yes, Windows really returns TRUE in this case */ + return TRUE; + } + + DestRect.left = XOriginDest; + DestRect.top = YOriginDest; + DestRect.right = XOriginDest + WidthDest; + DestRect.bottom = YOriginDest + HeightDest; + IntLPtoDP(DCDest, (LPPOINT)&DestRect, 2); + + DestRect.left += DCDest->ptlDCOrig.x; + DestRect.top += DCDest->ptlDCOrig.y; + DestRect.right += DCDest->ptlDCOrig.x; + DestRect.bottom += DCDest->ptlDCOrig.y; + + SourceRect.left = XOriginSrc; + SourceRect.top = YOriginSrc; + SourceRect.right = XOriginSrc + WidthSrc; + SourceRect.bottom = YOriginSrc + HeightSrc; + IntLPtoDP(DCSrc, (LPPOINT)&SourceRect, 2); + + SourceRect.left += DCSrc->ptlDCOrig.x; + SourceRect.top += DCSrc->ptlDCOrig.y; + SourceRect.right += DCSrc->ptlDCOrig.x; + SourceRect.bottom += DCSrc->ptlDCOrig.y; + + if (!DestRect.right || + !DestRect.bottom || + !SourceRect.right || + !SourceRect.bottom) + { + GDIOBJ_vUnlockObject(&DCSrc->BaseObject); + GDIOBJ_vUnlockObject(&DCDest->BaseObject); + return TRUE; + } + + /* Prepare DCs for blit */ + DPRINT("Preparing DCs for blit\n"); + DC_vPrepareDCsForBlit(DCDest, DestRect, DCSrc, SourceRect); + + /* Determine surfaces to be used in the bitblt */ + BitmapDest = DCDest->dclevel.pSurface; + if (!BitmapDest) + { + bResult = FALSE ; + goto leave ; + } + + BitmapSrc = DCSrc->dclevel.pSurface; + if (!BitmapSrc) + { + bResult = FALSE; + goto leave; + } + + /* Create the XLATEOBJ. */ + EXLATEOBJ_vInitXlateFromDCs(&exlo, DCSrc, DCDest); + + /* Perform the alpha blend operation */ + DPRINT("Performing the alpha blend\n"); + bResult = IntEngAlphaBlend(&BitmapDest->SurfObj, + &BitmapSrc->SurfObj, + DCDest->rosdc.CombinedClip, + &exlo.xlo, + &DestRect, + &SourceRect, + &BlendObj); + + EXLATEOBJ_vCleanup(&exlo); +leave : + DPRINT("Finishing blit\n"); + DC_vFinishBlit(DCDest, DCSrc); + GDIOBJ_vUnlockObject(&DCSrc->BaseObject); + GDIOBJ_vUnlockObject(&DCDest->BaseObject); + + return bResult; +} + +BOOL APIENTRY +NtGdiBitBlt( + HDC hDCDest, + INT XDest, + INT YDest, + INT Width, + INT Height, + HDC hDCSrc, + INT XSrc, + INT YSrc, + DWORD ROP, + IN DWORD crBackColor, + IN FLONG fl) +{ + /* Forward to NtGdiMaskBlt */ + // TODO: What's fl for? + return NtGdiMaskBlt(hDCDest, + XDest, + YDest, + Width, + Height, + hDCSrc, + XSrc, + YSrc, + NULL, + 0, + 0, + ROP, + crBackColor); +} + +BOOL APIENTRY +NtGdiTransparentBlt( + HDC hdcDst, + INT xDst, + INT yDst, + INT cxDst, + INT cyDst, + HDC hdcSrc, + INT xSrc, + INT ySrc, + INT cxSrc, + INT cySrc, + COLORREF TransColor) +{ + PDC DCDest, DCSrc; + HDC ahDC[2]; + PGDIOBJ apObj[2]; + RECTL rcDest, rcSrc; + SURFACE *BitmapDest, *BitmapSrc = NULL; + ULONG TransparentColor = 0; + BOOL Ret = FALSE; + EXLATEOBJ exlo; + + DPRINT("Locking DCs\n"); + ahDC[0] = hdcDst; + ahDC[1] = hdcSrc ; + if (!GDIOBJ_bLockMultipleObjects(2, ahDC, apObj, GDIObjType_DC_TYPE)) + { + DPRINT1("Invalid dc handle (dest=0x%08x, src=0x%08x) passed to NtGdiAlphaBlend\n", hdcDst, hdcSrc); + EngSetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + DCDest = apObj[0]; + DCSrc = apObj[1]; + + if (DCDest->dctype == DC_TYPE_INFO || DCDest->dctype == DCTYPE_INFO) + { + GDIOBJ_vUnlockObject(&DCSrc->BaseObject); + GDIOBJ_vUnlockObject(&DCDest->BaseObject); + /* Yes, Windows really returns TRUE in this case */ + return TRUE; + } + + rcDest.left = xDst; + rcDest.top = yDst; + rcDest.right = rcDest.left + cxDst; + rcDest.bottom = rcDest.top + cyDst; + IntLPtoDP(DCDest, (LPPOINT)&rcDest, 2); + + rcDest.left += DCDest->ptlDCOrig.x; + rcDest.top += DCDest->ptlDCOrig.y; + rcDest.right += DCDest->ptlDCOrig.x; + rcDest.bottom += DCDest->ptlDCOrig.y; + + rcSrc.left = xSrc; + rcSrc.top = ySrc; + rcSrc.right = rcSrc.left + cxSrc; + rcSrc.bottom = rcSrc.top + cySrc; + IntLPtoDP(DCSrc, (LPPOINT)&rcSrc, 2); + + rcSrc.left += DCSrc->ptlDCOrig.x; + rcSrc.top += DCSrc->ptlDCOrig.y; + rcSrc.right += DCSrc->ptlDCOrig.x; + rcSrc.bottom += DCSrc->ptlDCOrig.y; + + /* Prepare for blit */ + DC_vPrepareDCsForBlit(DCDest, rcDest, DCSrc, rcSrc); + + BitmapDest = DCDest->dclevel.pSurface; + if (!BitmapDest) + { + goto done; + } + + BitmapSrc = DCSrc->dclevel.pSurface; + if (!BitmapSrc) + { + goto done; + } + + /* Translate Transparent (RGB) Color to the source palette */ + EXLATEOBJ_vInitialize(&exlo, &gpalRGB, BitmapSrc->ppal, 0, 0, 0); + TransparentColor = XLATEOBJ_iXlate(&exlo.xlo, (ULONG)TransColor); + EXLATEOBJ_vCleanup(&exlo); + + EXLATEOBJ_vInitXlateFromDCs(&exlo, DCSrc, DCDest); + + Ret = IntEngTransparentBlt(&BitmapDest->SurfObj, &BitmapSrc->SurfObj, + DCDest->rosdc.CombinedClip, &exlo.xlo, &rcDest, &rcSrc, + TransparentColor, 0); + + EXLATEOBJ_vCleanup(&exlo); + +done: + DC_vFinishBlit(DCDest, DCSrc); + GDIOBJ_vUnlockObject(&DCDest->BaseObject); + GDIOBJ_vUnlockObject(&DCSrc->BaseObject); + + return Ret; +} + +BOOL APIENTRY +NtGdiMaskBlt( + HDC hdcDest, + INT nXDest, + INT nYDest, + INT nWidth, + INT nHeight, + HDC hdcSrc, + INT nXSrc, + INT nYSrc, + HBITMAP hbmMask, + INT xMask, + INT yMask, + DWORD dwRop, + IN DWORD crBackColor) +{ + PDC DCDest; + PDC DCSrc = NULL; + HDC ahDC[2]; + PGDIOBJ apObj[2]; + PDC_ATTR pdcattr = NULL; + SURFACE *BitmapDest, *BitmapSrc = NULL, *psurfMask = NULL; + RECTL DestRect, SourceRect; + POINTL SourcePoint, MaskPoint; + BOOL Status = FALSE; + EXLATEOBJ exlo; + XLATEOBJ *XlateObj = NULL; + BOOL UsesSource = ROP_USES_SOURCE(dwRop); + BOOL UsesMask; + + FIXUP_ROP(dwRop); + + UsesMask = ROP_USES_MASK(dwRop); + + //DPRINT1("dwRop : 0x%08x\n", dwRop); + if (!hdcDest || (UsesSource && !hdcSrc)) + { + EngSetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + /* Take care of mask bitmap */ + if(hbmMask) + { + psurfMask = SURFACE_ShareLockSurface(hbmMask); + if(!psurfMask) + { + EngSetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + } + + if(UsesMask) + { + if(!psurfMask) + { + EngSetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + if(gajBitsPerFormat[psurfMask->SurfObj.iBitmapFormat] != 1) + { + EngSetLastError(ERROR_INVALID_PARAMETER); + SURFACE_ShareUnlockSurface(psurfMask); + return FALSE; + } + } + else if(psurfMask) + { + DPRINT1("Getting Mask bitmap without needing it?\n"); + SURFACE_ShareUnlockSurface(psurfMask); + psurfMask = NULL; + } + MaskPoint.x = xMask; + MaskPoint.y = yMask; + + /* Take care of source and destination bitmap */ + DPRINT("Locking DCs\n"); + ahDC[0] = hdcDest; + ahDC[1] = UsesSource ? hdcSrc : NULL; + if (!GDIOBJ_bLockMultipleObjects(2, ahDC, apObj, GDIObjType_DC_TYPE)) + { + DPRINT1("Invalid dc handle (dest=0x%08x, src=0x%08x) passed to NtGdiAlphaBlend\n", hdcDest, hdcSrc); + EngSetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + DCDest = apObj[0]; + DCSrc = apObj[1]; + + ASSERT(DCDest); + if (NULL == DCDest) + { + if(DCSrc) DC_UnlockDc(DCSrc); + DPRINT("Invalid destination dc handle (0x%08x) passed to NtGdiBitBlt\n", hdcDest); + return FALSE; + } + + if (DCDest->dctype == DC_TYPE_INFO) + { + if(DCSrc) DC_UnlockDc(DCSrc); + DC_UnlockDc(DCDest); + /* Yes, Windows really returns TRUE in this case */ + return TRUE; + } + + if (UsesSource) + { + ASSERT(DCSrc); + if (DCSrc->dctype == DC_TYPE_INFO) + { + DC_UnlockDc(DCDest); + DC_UnlockDc(DCSrc); + /* Yes, Windows really returns TRUE in this case */ + return TRUE; + } + } + + pdcattr = DCDest->pdcattr; + + DestRect.left = nXDest; + DestRect.top = nYDest; + DestRect.right = nXDest + nWidth; + DestRect.bottom = nYDest + nHeight; + IntLPtoDP(DCDest, (LPPOINT)&DestRect, 2); + + DestRect.left += DCDest->ptlDCOrig.x; + DestRect.top += DCDest->ptlDCOrig.y; + DestRect.right += DCDest->ptlDCOrig.x; + DestRect.bottom += DCDest->ptlDCOrig.y; + + SourcePoint.x = nXSrc; + SourcePoint.y = nYSrc; + + if (UsesSource) + { + IntLPtoDP(DCSrc, (LPPOINT)&SourcePoint, 1); + + SourcePoint.x += DCSrc->ptlDCOrig.x; + SourcePoint.y += DCSrc->ptlDCOrig.y; + /* Calculate Source Rect */ + SourceRect.left = SourcePoint.x; + SourceRect.top = SourcePoint.y; + SourceRect.right = SourcePoint.x + DestRect.right - DestRect.left; + SourceRect.bottom = SourcePoint.y + DestRect.bottom - DestRect.top ; + } + + /* Prepare blit */ + DC_vPrepareDCsForBlit(DCDest, DestRect, DCSrc, SourceRect); + + if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY)) + DC_vUpdateFillBrush(DCDest); + + /* Determine surfaces to be used in the bitblt */ + BitmapDest = DCDest->dclevel.pSurface; + if (!BitmapDest) + goto cleanup; + + if (UsesSource) + { + { + BitmapSrc = DCSrc->dclevel.pSurface; + if (!BitmapSrc) + goto cleanup; + } + } + + /* Create the XLATEOBJ. */ + if (UsesSource) + { + EXLATEOBJ_vInitXlateFromDCs(&exlo, DCSrc, DCDest); + XlateObj = &exlo.xlo; + } + + + /* Perform the bitblt operation */ + Status = IntEngBitBlt(&BitmapDest->SurfObj, + BitmapSrc ? &BitmapSrc->SurfObj : NULL, + psurfMask ? &psurfMask->SurfObj : NULL, + DCDest->rosdc.CombinedClip, + XlateObj, + &DestRect, + &SourcePoint, + &MaskPoint, + &DCDest->eboFill.BrushObject, + &DCDest->dclevel.pbrFill->ptOrigin, + ROP_TO_ROP4(dwRop)); + + if (UsesSource) + EXLATEOBJ_vCleanup(&exlo); +cleanup: + DC_vFinishBlit(DCDest, DCSrc); + if (UsesSource) + { + DC_UnlockDc(DCSrc); + } + DC_UnlockDc(DCDest); + if(psurfMask) SURFACE_ShareUnlockSurface(psurfMask); + + return Status; +} + +BOOL +APIENTRY +NtGdiPlgBlt( + IN HDC hdcTrg, + IN LPPOINT pptlTrg, + IN HDC hdcSrc, + IN INT xSrc, + IN INT ySrc, + IN INT cxSrc, + IN INT cySrc, + IN HBITMAP hbmMask, + IN INT xMask, + IN INT yMask, + IN DWORD crBackColor) +{ + UNIMPLEMENTED; + return FALSE; +} + +BOOL APIENTRY +GreStretchBltMask( + HDC hDCDest, + INT XOriginDest, + INT YOriginDest, + INT WidthDest, + INT HeightDest, + HDC hDCSrc, + INT XOriginSrc, + INT YOriginSrc, + INT WidthSrc, + INT HeightSrc, + DWORD ROP, + IN DWORD dwBackColor, + HDC hDCMask, + INT XOriginMask, + INT YOriginMask) +{ + PDC DCDest; + PDC DCSrc = NULL; + PDC DCMask = NULL; + HDC ahDC[3]; + PGDIOBJ apObj[3]; + PDC_ATTR pdcattr; + SURFACE *BitmapDest, *BitmapSrc = NULL; + SURFACE *BitmapMask = NULL; + RECTL DestRect; + RECTL SourceRect; + POINTL MaskPoint; + BOOL Status = FALSE; + EXLATEOBJ exlo; + XLATEOBJ *XlateObj = NULL; + POINTL BrushOrigin; + BOOL UsesSource; + BOOL UsesMask; + + FIXUP_ROP(ROP); + UsesSource = ROP_USES_SOURCE(ROP); + UsesMask = ROP_USES_MASK(ROP); + + if (0 == WidthDest || 0 == HeightDest || 0 == WidthSrc || 0 == HeightSrc) + { + EngSetLastError(ERROR_INVALID_PARAMETER); + return TRUE; + } + + if (!hDCDest || (UsesSource && !hDCSrc) || (UsesMask && !hDCMask)) + { + EngSetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + ahDC[0] = hDCDest; + ahDC[1] = UsesSource ? hDCSrc : NULL; + ahDC[2] = UsesMask ? hDCMask : NULL; + if (!GDIOBJ_bLockMultipleObjects(3, ahDC, apObj, GDIObjType_DC_TYPE)) + { + DPRINT1("Invalid dc handle (dest=0x%08x, src=0x%08x) passed to NtGdiAlphaBlend\n", hDCDest, hDCSrc); + EngSetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + DCDest = apObj[0]; + DCSrc = apObj[1]; + DCMask = apObj[2]; + + if (DCDest->dctype == DC_TYPE_INFO) + { + if(DCSrc) GDIOBJ_vUnlockObject(&DCSrc->BaseObject); + if(DCMask) GDIOBJ_vUnlockObject(&DCMask->BaseObject); + GDIOBJ_vUnlockObject(&DCDest->BaseObject); + /* Yes, Windows really returns TRUE in this case */ + return TRUE; + } + + if (UsesSource) + { + if (DCSrc->dctype == DC_TYPE_INFO) + { + GDIOBJ_vUnlockObject(&DCDest->BaseObject); + GDIOBJ_vUnlockObject(&DCSrc->BaseObject); + if(DCMask) GDIOBJ_vUnlockObject(&DCMask->BaseObject); + /* Yes, Windows really returns TRUE in this case */ + return TRUE; + } + } + + pdcattr = DCDest->pdcattr; + + DestRect.left = XOriginDest; + DestRect.top = YOriginDest; + DestRect.right = XOriginDest+WidthDest; + DestRect.bottom = YOriginDest+HeightDest; + IntLPtoDP(DCDest, (LPPOINT)&DestRect, 2); + + DestRect.left += DCDest->ptlDCOrig.x; + DestRect.top += DCDest->ptlDCOrig.y; + DestRect.right += DCDest->ptlDCOrig.x; + DestRect.bottom += DCDest->ptlDCOrig.y; + + SourceRect.left = XOriginSrc; + SourceRect.top = YOriginSrc; + SourceRect.right = XOriginSrc+WidthSrc; + SourceRect.bottom = YOriginSrc+HeightSrc; + + if (UsesSource) + { + IntLPtoDP(DCSrc, (LPPOINT)&SourceRect, 2); + + SourceRect.left += DCSrc->ptlDCOrig.x; + SourceRect.top += DCSrc->ptlDCOrig.y; + SourceRect.right += DCSrc->ptlDCOrig.x; + SourceRect.bottom += DCSrc->ptlDCOrig.y; + } + + BrushOrigin.x = 0; + BrushOrigin.y = 0; + + /* Only prepare Source and Dest, hdcMask represents a DIB */ + DC_vPrepareDCsForBlit(DCDest, DestRect, DCSrc, SourceRect); + + if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY)) + DC_vUpdateFillBrush(DCDest); + + /* Determine surfaces to be used in the bitblt */ + BitmapDest = DCDest->dclevel.pSurface; + if (BitmapDest == NULL) + goto failed; + if (UsesSource) + { + BitmapSrc = DCSrc->dclevel.pSurface; + if (BitmapSrc == NULL) + goto failed; + + /* Create the XLATEOBJ. */ + EXLATEOBJ_vInitXlateFromDCs(&exlo, DCSrc, DCDest); + XlateObj = &exlo.xlo; + } + + /* Offset the brush */ + BrushOrigin.x += DCDest->ptlDCOrig.x; + BrushOrigin.y += DCDest->ptlDCOrig.y; + + /* Make mask surface for source surface */ + if (BitmapSrc && DCMask) + { + BitmapMask = DCMask->dclevel.pSurface; + if (BitmapMask && + (BitmapMask->SurfObj.sizlBitmap.cx < WidthSrc || + BitmapMask->SurfObj.sizlBitmap.cy < HeightSrc)) + { + DPRINT1("%dx%d mask is smaller than %dx%d bitmap\n", + BitmapMask->SurfObj.sizlBitmap.cx, BitmapMask->SurfObj.sizlBitmap.cy, + WidthSrc, HeightSrc); + EXLATEOBJ_vCleanup(&exlo); + goto failed; + } + /* Create mask offset point */ + MaskPoint.x = XOriginMask; + MaskPoint.y = YOriginMask; + IntLPtoDP(DCMask, &MaskPoint, 1); + MaskPoint.x += DCMask->ptlDCOrig.x; + MaskPoint.y += DCMask->ptlDCOrig.y; + } + + /* Perform the bitblt operation */ + Status = IntEngStretchBlt(&BitmapDest->SurfObj, + &BitmapSrc->SurfObj, + BitmapMask ? &BitmapMask->SurfObj : NULL, + DCDest->rosdc.CombinedClip, + XlateObj, + &DestRect, + &SourceRect, + BitmapMask ? &MaskPoint : NULL, + &DCDest->eboFill.BrushObject, + &BrushOrigin, + ROP_TO_ROP4(ROP)); + if (UsesSource) + { + EXLATEOBJ_vCleanup(&exlo); + } + +failed: + DC_vFinishBlit(DCDest, DCSrc); + if (UsesSource) + { + DC_UnlockDc(DCSrc); + } + if (DCMask) + { + DC_UnlockDc(DCMask); + } + DC_UnlockDc(DCDest); + + return Status; +} + + +BOOL APIENTRY +NtGdiStretchBlt( + HDC hDCDest, + INT XOriginDest, + INT YOriginDest, + INT WidthDest, + INT HeightDest, + HDC hDCSrc, + INT XOriginSrc, + INT YOriginSrc, + INT WidthSrc, + INT HeightSrc, + DWORD ROP, + IN DWORD dwBackColor) +{ + return GreStretchBltMask( + hDCDest, + XOriginDest, + YOriginDest, + WidthDest, + HeightDest, + hDCSrc, + XOriginSrc, + YOriginSrc, + WidthSrc, + HeightSrc, + ROP, + dwBackColor, + NULL, + 0, + 0); +} + + +BOOL FASTCALL +IntPatBlt( + PDC pdc, + INT XLeft, + INT YLeft, + INT Width, + INT Height, + DWORD dwRop, + PBRUSH pbrush) +{ + RECTL DestRect; + SURFACE *psurf; + EBRUSHOBJ eboFill ; + POINTL BrushOrigin; + BOOL ret; + + ASSERT(pbrush); + + FIXUP_ROP(dwRop); + + if (pbrush->flAttrs & GDIBRUSH_IS_NULL) + { + return TRUE; + } + + if (Width > 0) + { + DestRect.left = XLeft; + DestRect.right = XLeft + Width; + } + else + { + DestRect.left = XLeft + Width + 1; + DestRect.right = XLeft + 1; + } + + if (Height > 0) + { + DestRect.top = YLeft; + DestRect.bottom = YLeft + Height; + } + else + { + DestRect.top = YLeft + Height + 1; + DestRect.bottom = YLeft + 1; + } + + IntLPtoDP(pdc, (LPPOINT)&DestRect, 2); + + DestRect.left += pdc->ptlDCOrig.x; + DestRect.top += pdc->ptlDCOrig.y; + DestRect.right += pdc->ptlDCOrig.x; + DestRect.bottom += pdc->ptlDCOrig.y; +#ifdef _USE_DIBLIB_ + BrushOrigin.x = pbrush->ptOrigin.x + pdc->ptlDCOrig.x + XLeft; + BrushOrigin.y = pbrush->ptOrigin.y + pdc->ptlDCOrig.y + YLeft; +#else + BrushOrigin.x = pbrush->ptOrigin.x + pdc->ptlDCOrig.x; + BrushOrigin.y = pbrush->ptOrigin.y + pdc->ptlDCOrig.y; +#endif + + DC_vPrepareDCsForBlit(pdc, DestRect, NULL, DestRect); + + psurf = pdc->dclevel.pSurface; + + if (pdc->pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY)) + DC_vUpdateFillBrush(pdc); + + EBRUSHOBJ_vInit(&eboFill, pbrush, pdc); + + ret = IntEngBitBlt( + &psurf->SurfObj, + NULL, + NULL, + pdc->rosdc.CombinedClip, + NULL, + &DestRect, + NULL, + NULL, + &eboFill.BrushObject, + &BrushOrigin, + ROP_TO_ROP4(dwRop)); + + DC_vFinishBlit(pdc, NULL); + + EBRUSHOBJ_vCleanup(&eboFill); + + return ret; +} + +BOOL FASTCALL +IntGdiPolyPatBlt( + HDC hDC, + DWORD dwRop, + PPATRECT pRects, + INT cRects, + ULONG Reserved) +{ + INT i; + PBRUSH pbrush; + PDC pdc; + + pdc = DC_LockDc(hDC); + if (!pdc) + { + EngSetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + + if (pdc->dctype == DC_TYPE_INFO) + { + DC_UnlockDc(pdc); + /* Yes, Windows really returns TRUE in this case */ + return TRUE; + } + + for (i = 0; i < cRects; i++) + { + pbrush = BRUSH_ShareLockBrush(pRects->hBrush); + if(pbrush != NULL) + { + IntPatBlt( + pdc, + pRects->r.left, + pRects->r.top, + pRects->r.right, + pRects->r.bottom, + dwRop, + pbrush); + BRUSH_ShareUnlockBrush(pbrush); + } + pRects++; + } + + DC_UnlockDc(pdc); + + return TRUE; +} + +BOOL APIENTRY +NtGdiPatBlt( + HDC hDC, + INT XLeft, + INT YLeft, + INT Width, + INT Height, + DWORD ROP) +{ + PBRUSH pbrush; + DC *dc; + PDC_ATTR pdcattr; + BOOL ret; + + BOOL UsesSource = ROP_USES_SOURCE(ROP); + if (UsesSource) + { + /* In this case we call on GdiMaskBlt */ + return NtGdiMaskBlt(hDC, XLeft, YLeft, Width, Height, 0,0,0,0,0,0,ROP,0); + } + + dc = DC_LockDc(hDC); + if (dc == NULL) + { + EngSetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + if (dc->dctype == DC_TYPE_INFO) + { + DC_UnlockDc(dc); + DPRINT1("NtGdiPatBlt on info DC!\n"); + /* Yes, Windows really returns TRUE in this case */ + return TRUE; + } + + pdcattr = dc->pdcattr; + + if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY)) + DC_vUpdateFillBrush(dc); + + pbrush = BRUSH_ShareLockBrush(pdcattr->hbrush); + if (pbrush == NULL) + { + EngSetLastError(ERROR_INVALID_HANDLE); + DC_UnlockDc(dc); + return FALSE; + } + + ret = IntPatBlt(dc, XLeft, YLeft, Width, Height, ROP, pbrush); + + BRUSH_ShareUnlockBrush(pbrush); + DC_UnlockDc(dc); + + return ret; +} + +BOOL APIENTRY +NtGdiPolyPatBlt( + HDC hDC, + DWORD dwRop, + IN PPOLYPATBLT pRects, + IN DWORD cRects, + IN DWORD Mode) +{ + PPATRECT rb = NULL; + NTSTATUS Status = STATUS_SUCCESS; + BOOL Ret; + + if (cRects > 0) + { + rb = ExAllocatePoolWithTag(PagedPool, sizeof(PATRECT) * cRects, GDITAG_PLGBLT_DATA); + if (!rb) + { + EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + _SEH2_TRY + { + ProbeForRead(pRects, + cRects * sizeof(PATRECT), + 1); + RtlCopyMemory(rb, + pRects, + cRects * sizeof(PATRECT)); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + Status = _SEH2_GetExceptionCode(); + } + _SEH2_END; + + if (!NT_SUCCESS(Status)) + { + ExFreePoolWithTag(rb, GDITAG_PLGBLT_DATA); + SetLastNtError(Status); + return FALSE; + } + } + + Ret = IntGdiPolyPatBlt(hDC, dwRop, rb, cRects, Mode); + + if (cRects > 0) + ExFreePoolWithTag(rb, GDITAG_PLGBLT_DATA); + + return Ret; +}