mirror of
https://github.com/reactos/reactos.git
synced 2025-02-25 01:39:30 +00:00
[WIN32K]
- Rewrite NtGdiFillRgn and IntGdiPaintRgn We now properly support painting regions on DCs with arbitrary world transforms, with pattern brushes and we respect the foreground ROP and mode of the DC. And we don't run into deadlocks due to having an exclusive region lock while trying to lock a DC. LOCKING MUST BE DONE IN PROPER ORDER! svn path=/trunk/; revision=65730
This commit is contained in:
parent
c3d2353ed6
commit
c6f684e727
1 changed files with 98 additions and 55 deletions
|
@ -1021,103 +1021,146 @@ REGION_LPTODP(
|
||||||
if (IntGdiCombineRgn(prgnDest, prgnSrc, NULL, RGN_COPY) == ERROR)
|
if (IntGdiCombineRgn(prgnDest, prgnSrc, NULL, RGN_COPY) == ERROR)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
return REGION_bXformRgn(prgnDest, &pdc->dclevel.mxWorldToDevice);
|
return REGION_bXformRgn(prgnDest, DC_pmxWorldToDevice(pdc));
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL
|
BOOL
|
||||||
FASTCALL
|
IntGdiFillRgn(
|
||||||
IntGdiPaintRgn(
|
_In_ PDC pdc,
|
||||||
PDC dc,
|
_In_ PREGION prgn,
|
||||||
PREGION Rgn)
|
_In_ BRUSHOBJ *pbo)
|
||||||
{
|
{
|
||||||
PREGION VisRgn;
|
PREGION prgnClip;
|
||||||
XCLIPOBJ ClipRegion;
|
XCLIPOBJ xcoClip;
|
||||||
BOOL bRet = FALSE;
|
BOOL bRet;
|
||||||
POINTL BrushOrigin;
|
PSURFACE psurf;
|
||||||
SURFACE *psurf;
|
DWORD rop2Fg;
|
||||||
PDC_ATTR pdcattr;
|
MIX mix;
|
||||||
|
|
||||||
if ((dc == NULL) || (Rgn == NULL))
|
NT_ASSERT((pdc != NULL) && (prgn != NULL));
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
pdcattr = dc->pdcattr;
|
psurf = pdc->dclevel.pSurface;
|
||||||
|
if (psurf == NULL)
|
||||||
|
{
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
ASSERT(!(pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY)));
|
prgnClip = IntSysCreateRectpRgn(0, 0, 0, 0);
|
||||||
|
if (prgnClip == NULL)
|
||||||
VisRgn = IntSysCreateRectpRgn(0, 0, 0, 0);
|
|
||||||
if (VisRgn == NULL)
|
|
||||||
{
|
{
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transform region into device co-ords
|
/* Transform region into device coordinates */
|
||||||
if (!REGION_LPTODP(dc, VisRgn, Rgn) ||
|
if (!REGION_LPTODP(pdc, prgnClip, prgn) ||
|
||||||
IntGdiOffsetRgn(VisRgn, dc->ptlDCOrig.x, dc->ptlDCOrig.y) == ERROR)
|
IntGdiOffsetRgn(prgnClip, pdc->ptlDCOrig.x, pdc->ptlDCOrig.y) == ERROR)
|
||||||
{
|
{
|
||||||
REGION_Delete(VisRgn);
|
REGION_Delete(prgnClip);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dc->prgnRao)
|
/* Intersect with the system or RAO region */
|
||||||
IntGdiCombineRgn(VisRgn, VisRgn, dc->prgnRao, RGN_AND);
|
if (pdc->prgnRao)
|
||||||
|
IntGdiCombineRgn(prgnClip, prgnClip, pdc->prgnRao, RGN_AND);
|
||||||
|
else
|
||||||
|
IntGdiCombineRgn(prgnClip, prgnClip, pdc->prgnVis, RGN_AND);
|
||||||
|
|
||||||
IntEngInitClipObj(&ClipRegion);
|
IntEngInitClipObj(&xcoClip);
|
||||||
IntEngUpdateClipRegion(&ClipRegion,
|
IntEngUpdateClipRegion(&xcoClip,
|
||||||
VisRgn->rdh.nCount,
|
prgnClip->rdh.nCount,
|
||||||
VisRgn->Buffer,
|
prgnClip->Buffer,
|
||||||
&VisRgn->rdh.rcBound );
|
&prgnClip->rdh.rcBound );
|
||||||
|
|
||||||
BrushOrigin.x = pdcattr->ptlBrushOrigin.x;
|
/* Get the FG rop and create a MIX based on the BK mode */
|
||||||
BrushOrigin.y = pdcattr->ptlBrushOrigin.y;
|
rop2Fg = pdc->pdcattr->jROP2;
|
||||||
psurf = dc->dclevel.pSurface;
|
mix = rop2Fg | (pdc->pdcattr->jBkMode == OPAQUE ? rop2Fg : R2_NOP) << 8;
|
||||||
/* FIXME: Handle psurf == NULL !!!! */
|
|
||||||
|
|
||||||
|
/* Call the internal function */
|
||||||
bRet = IntEngPaint(&psurf->SurfObj,
|
bRet = IntEngPaint(&psurf->SurfObj,
|
||||||
&ClipRegion.ClipObj,
|
&xcoClip.ClipObj,
|
||||||
&dc->eboFill.BrushObject,
|
pbo,
|
||||||
&BrushOrigin,
|
&pdc->pdcattr->ptlBrushOrigin,
|
||||||
0xFFFF); // FIXME: Don't know what to put here
|
mix);
|
||||||
|
|
||||||
REGION_Delete(VisRgn);
|
REGION_Delete(prgnClip);
|
||||||
IntEngFreeClipResources(&ClipRegion);
|
IntEngFreeClipResources(&xcoClip);
|
||||||
|
|
||||||
// Fill the region
|
// Fill the region
|
||||||
return bRet;
|
return bRet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
FASTCALL
|
||||||
|
IntGdiPaintRgn(
|
||||||
|
_In_ PDC pdc,
|
||||||
|
_In_ PREGION prgn)
|
||||||
|
{
|
||||||
|
if (pdc->pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
|
||||||
|
DC_vUpdateFillBrush(pdc);
|
||||||
|
|
||||||
|
return IntGdiFillRgn(pdc, prgn, &pdc->eboFill.BrushObject);
|
||||||
|
}
|
||||||
|
|
||||||
BOOL
|
BOOL
|
||||||
APIENTRY
|
APIENTRY
|
||||||
NtGdiFillRgn(
|
NtGdiFillRgn(
|
||||||
HDC hDC,
|
_In_ HDC hdc,
|
||||||
HRGN hRgn,
|
_In_ HRGN hrgn,
|
||||||
HBRUSH hBrush)
|
_In_ HBRUSH hbrush)
|
||||||
{
|
{
|
||||||
HBRUSH oldhBrush;
|
PDC pdc;
|
||||||
PREGION rgn;
|
PREGION prgn;
|
||||||
PRECTL r;
|
PBRUSH pbrFill;
|
||||||
|
EBRUSHOBJ eboFill;
|
||||||
|
BOOL bResult;
|
||||||
|
|
||||||
rgn = RGNOBJAPI_Lock(hRgn, NULL);
|
/* Lock the DC */
|
||||||
if (rgn == NULL)
|
pdc = DC_LockDc(hdc);
|
||||||
|
if (pdc == NULL)
|
||||||
{
|
{
|
||||||
|
ERR("Failed to lock hdc %p\n", hdc);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
oldhBrush = NtGdiSelectBrush(hDC, hBrush);
|
/* Check if the DC has no surface (empty mem or info DC) */
|
||||||
if (oldhBrush == NULL)
|
if (pdc->dclevel.pSurface == NULL)
|
||||||
{
|
{
|
||||||
RGNOBJAPI_Unlock(rgn);
|
DC_UnlockDc(pdc);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Lock the region */
|
||||||
|
prgn = RGNOBJAPI_Lock(hrgn, NULL);
|
||||||
|
if (prgn == NULL)
|
||||||
|
{
|
||||||
|
ERR("Failed to lock hrgn %p\n", hrgn);
|
||||||
|
DC_UnlockDc(pdc);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (r = rgn->Buffer; r < rgn->Buffer + rgn->rdh.nCount; r++)
|
/* Lock the brush */
|
||||||
|
pbrFill = BRUSH_ShareLockBrush(hbrush);
|
||||||
|
if (pbrFill == NULL)
|
||||||
{
|
{
|
||||||
NtGdiPatBlt(hDC, r->left, r->top, r->right - r->left, r->bottom - r->top, PATCOPY);
|
ERR("Failed to lock hbrush %p\n", hbrush);
|
||||||
|
RGNOBJAPI_Unlock(prgn);
|
||||||
|
DC_UnlockDc(pdc);
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
RGNOBJAPI_Unlock(rgn);
|
/* Initialize the brush object */
|
||||||
NtGdiSelectBrush(hDC, oldhBrush);
|
/// \todo Check parameters
|
||||||
|
EBRUSHOBJ_vInit(&eboFill, pbrFill, pdc->dclevel.pSurface, 0x00FFFFFF, 0, NULL);
|
||||||
|
|
||||||
return TRUE;
|
/* Call the internal function */
|
||||||
|
bResult = IntGdiFillRgn(pdc, prgn, &eboFill.BrushObject);
|
||||||
|
|
||||||
|
/* Cleanup locks */
|
||||||
|
BRUSH_ShareUnlockBrush(pbrFill);
|
||||||
|
RGNOBJAPI_Unlock(prgn);
|
||||||
|
DC_UnlockDc(pdc);
|
||||||
|
|
||||||
|
return bResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL
|
BOOL
|
||||||
|
|
Loading…
Reference in a new issue