- Correctly use the Clip, Meta, Rao, API and Vis Regions in DCs
     - Update the DC clipping object on demand each time a blt is performed
     - Reduce the number of region allocated with handles when it's not needed
This commit fixes numerous bugs regarding clipping, most notably SetDIBitsToDevice overlapping foreground windows
CORE-8353 #resolve #comment There are still a few quirks in winetests which will get fixed in a next commit
CORE-7628 #comment should be fixed in rev 63731, please confirm.

svn path=/trunk/; revision=63731
This commit is contained in:
Jérôme Gardou 2014-07-23 16:05:47 +00:00
parent 022f198f1e
commit df7f9319c2
20 changed files with 610 additions and 614 deletions

View file

@ -335,8 +335,7 @@ NtGdiAngleArc(
worker.l = dwStartAngle;
worker1.l = dwSweepAngle;
DC_vPrepareDCsForBlit(pDC, pDC->rosdc.CombinedClip->rclBounds,
NULL, pDC->rosdc.CombinedClip->rclBounds);
DC_vPrepareDCsForBlit(pDC, NULL, NULL, NULL);
if (pDC->pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
DC_vUpdateFillBrush(pDC);
if (pDC->pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
@ -381,8 +380,7 @@ NtGdiArcInternal(
return TRUE;
}
DC_vPrepareDCsForBlit(dc, dc->rosdc.CombinedClip->rclBounds,
NULL, dc->rosdc.CombinedClip->rclBounds);
DC_vPrepareDCsForBlit(dc, NULL, NULL, NULL);
if (dc->pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
DC_vUpdateFillBrush(dc);

View file

@ -107,7 +107,7 @@ NtGdiAlphaBlend(
/* Prepare DCs for blit */
TRACE("Preparing DCs for blit\n");
DC_vPrepareDCsForBlit(DCDest, DestRect, DCSrc, SourceRect);
DC_vPrepareDCsForBlit(DCDest, &DestRect, DCSrc, &SourceRect);
/* Determine surfaces to be used in the bitblt */
BitmapDest = DCDest->dclevel.pSurface;
@ -268,7 +268,7 @@ NtGdiTransparentBlt(
rcSrc.bottom += DCSrc->ptlDCOrig.y;
/* Prepare for blit */
DC_vPrepareDCsForBlit(DCDest, rcDest, DCSrc, rcSrc);
DC_vPrepareDCsForBlit(DCDest, &rcDest, DCSrc, &rcSrc);
BitmapDest = DCDest->dclevel.pSurface;
if (!BitmapDest)
@ -456,7 +456,7 @@ NtGdiMaskBlt(
}
/* Prepare blit */
DC_vPrepareDCsForBlit(DCDest, DestRect, DCSrc, SourceRect);
DC_vPrepareDCsForBlit(DCDest, &DestRect, DCSrc, &SourceRect);
if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
DC_vUpdateFillBrush(DCDest);
@ -647,7 +647,7 @@ GreStretchBltMask(
BrushOrigin.y = 0;
/* Only prepare Source and Dest, hdcMask represents a DIB */
DC_vPrepareDCsForBlit(DCDest, DestRect, DCSrc, SourceRect);
DC_vPrepareDCsForBlit(DCDest, &DestRect, DCSrc, &SourceRect);
if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
DC_vUpdateFillBrush(DCDest);
@ -826,7 +826,7 @@ IntPatBlt(
BrushOrigin.y = pbrush->ptOrigin.y + pdc->ptlDCOrig.y;
#endif
DC_vPrepareDCsForBlit(pdc, DestRect, NULL, DestRect);
DC_vPrepareDCsForBlit(pdc, &DestRect, NULL, NULL);
psurf = pdc->dclevel.pSurface;

View file

@ -11,164 +11,102 @@
#define NDEBUG
#include <debug.h>
int FASTCALL
CLIPPING_UpdateGCRegion(DC* Dc)
VOID
FASTCALL
GdiSelectVisRgn(
HDC hdc,
PREGION prgn)
{
PROSRGNDATA CombinedRegion;
//HRGN hRgnVis;
PREGION prgnClip, prgnGCClip;
DC *dc;
/* Would prefer this, but the rest of the code sucks... */
//ASSERT(Dc->rosdc.hGCClipRgn);
//ASSERT(Dc->rosdc.hClipRgn);
ASSERT(Dc->prgnVis);
//hRgnVis = Dc->prgnVis->BaseObject.hHmgr;
if (!(dc = DC_LockDc(hdc)))
{
EngSetLastError(ERROR_INVALID_HANDLE);
return;
}
if (Dc->rosdc.hGCClipRgn == NULL)
Dc->rosdc.hGCClipRgn = IntSysCreateRectRgn(0, 0, 0, 0);
dc->fs |= DC_FLAG_DIRTY_RAO;
prgnGCClip = REGION_LockRgn(Dc->rosdc.hGCClipRgn);
ASSERT(prgnGCClip);
ASSERT(dc->prgnVis != NULL);
ASSERT(prgn != NULL);
if (Dc->rosdc.hClipRgn == NULL)
IntGdiCombineRgn(prgnGCClip, Dc->prgnVis, NULL, RGN_COPY);
else
{
prgnClip = REGION_LockRgn(Dc->rosdc.hClipRgn); // FIXME: Locking order, ugh!
IntGdiCombineRgn(prgnGCClip, Dc->prgnVis, prgnClip, RGN_AND);
REGION_UnlockRgn(prgnClip);
}
REGION_UnlockRgn(prgnGCClip);
NtGdiOffsetRgn(Dc->rosdc.hGCClipRgn, Dc->ptlDCOrig.x, Dc->ptlDCOrig.y);
if((CombinedRegion = RGNOBJAPI_Lock(Dc->rosdc.hGCClipRgn, NULL)))
{
CLIPOBJ *CombinedClip;
CombinedClip = IntEngCreateClipRegion(CombinedRegion->rdh.nCount,
CombinedRegion->Buffer,
&CombinedRegion->rdh.rcBound);
RGNOBJAPI_Unlock(CombinedRegion);
if ( !CombinedClip )
{
DPRINT1("IntEngCreateClipRegion() failed\n");
return ERROR;
}
if(Dc->rosdc.CombinedClip != NULL)
IntEngDeleteClipRegion(Dc->rosdc.CombinedClip);
Dc->rosdc.CombinedClip = CombinedClip ;
}
return NtGdiOffsetRgn(Dc->rosdc.hGCClipRgn, -Dc->ptlDCOrig.x, -Dc->ptlDCOrig.y);
}
INT FASTCALL
GdiSelectVisRgn(HDC hdc, HRGN hrgn)
{
int retval;
DC *dc;
PREGION prgn;
if (!hrgn)
{
EngSetLastError(ERROR_INVALID_PARAMETER);
return ERROR;
}
if (!(dc = DC_LockDc(hdc)))
{
EngSetLastError(ERROR_INVALID_HANDLE);
return ERROR;
}
dc->fs &= ~DC_FLAG_DIRTY_RAO;
ASSERT (dc->prgnVis != NULL);
prgn = RGNOBJAPI_Lock(hrgn, NULL);
retval = prgn ? IntGdiCombineRgn(dc->prgnVis, prgn, NULL, RGN_COPY) : ERROR;
RGNOBJAPI_Unlock(prgn);
if ( retval != ERROR )
{
IntGdiCombineRgn(dc->prgnVis, prgn, NULL, RGN_COPY);
IntGdiOffsetRgn(dc->prgnVis, -dc->ptlDCOrig.x, -dc->ptlDCOrig.y);
CLIPPING_UpdateGCRegion(dc);
}
DC_UnlockDc(dc);
return retval;
DC_UnlockDc(dc);
}
int FASTCALL GdiExtSelectClipRgn(PDC dc,
HRGN hrgn,
int fnMode)
int
FASTCALL
IntGdiExtSelectClipRgn(
PDC dc,
PREGION prgn,
int fnMode)
{
// dc->fs &= ~DC_FLAG_DIRTY_RAO;
if (!prgn)
{
if (fnMode == RGN_COPY)
{
if (dc->dclevel.prgnClip != NULL)
{
REGION_Delete(dc->dclevel.prgnClip);
dc->dclevel.prgnClip = NULL;
dc->fs |= DC_FLAG_DIRTY_RAO;
}
return SIMPLEREGION;
}
else
{
EngSetLastError(ERROR_INVALID_PARAMETER);
return ERROR;
}
}
if (!hrgn)
{
if (fnMode == RGN_COPY)
if (!dc->dclevel.prgnClip)
{
if (dc->rosdc.hClipRgn != NULL)
{
GreDeleteObject(dc->rosdc.hClipRgn);
dc->rosdc.hClipRgn = NULL;
}
}
else
{
EngSetLastError(ERROR_INVALID_PARAMETER);
return ERROR;
}
}
else
{
if (!dc->rosdc.hClipRgn)
{
RECTL rect;
if(dc->prgnVis)
{
RECTL rect;
REGION_GetRgnBox(dc->prgnVis, &rect);
dc->rosdc.hClipRgn = IntSysCreateRectRgnIndirect(&rect);
}
else
{
dc->rosdc.hClipRgn = IntSysCreateRectRgn(0, 0, 0, 0);
}
dc->dclevel.prgnClip = IntSysCreateRectpRgnIndirect(&rect);
}
if(fnMode == RGN_COPY)
{
NtGdiCombineRgn(dc->rosdc.hClipRgn, hrgn, 0, fnMode);
}
else
NtGdiCombineRgn(dc->rosdc.hClipRgn, dc->rosdc.hClipRgn, hrgn, fnMode);
}
return CLIPPING_UpdateGCRegion(dc);
dc->fs |= DC_FLAG_DIRTY_RAO;
if(fnMode == RGN_COPY)
return IntGdiCombineRgn(dc->dclevel.prgnClip, prgn, 0, fnMode);
return IntGdiCombineRgn(dc->dclevel.prgnClip, dc->dclevel.prgnClip, prgn, fnMode);
}
int APIENTRY NtGdiExtSelectClipRgn(HDC hDC,
HRGN hrgn,
int fnMode)
int
APIENTRY
NtGdiExtSelectClipRgn(
HDC hDC,
HRGN hrgn,
int fnMode)
{
int retval;
DC *dc;
int retval;
DC *dc;
PREGION prgn;
if (!(dc = DC_LockDc(hDC)))
{
EngSetLastError(ERROR_INVALID_HANDLE);
return ERROR;
}
if (!(dc = DC_LockDc(hDC)))
{
EngSetLastError(ERROR_INVALID_HANDLE);
return ERROR;
}
retval = GdiExtSelectClipRgn ( dc, hrgn, fnMode );
prgn = REGION_LockRgn(hrgn);
DC_UnlockDc(dc);
return retval;
/* IntGdiExtSelectClipRgn takes care of checking for NULL region */
retval = IntGdiExtSelectClipRgn(dc, prgn, fnMode);
if (prgn)
REGION_UnlockRgn(prgn);
DC_UnlockDc(dc);
return retval;
}
INT FASTCALL
@ -177,7 +115,6 @@ GdiGetClipBox(HDC hDC, PRECTL rc)
INT retval;
PDC dc;
PROSRGNDATA pRgnNew, pRgn = NULL;
BOOL Unlock = FALSE; // Small HACK
if (!(dc = DC_LockDc(hDC)))
{
@ -193,10 +130,9 @@ GdiGetClipBox(HDC hDC, PRECTL rc)
{
pRgn = dc->dclevel.prgnMeta;
}
else if (dc->rosdc.hClipRgn)
else if (dc->dclevel.prgnClip) // CLIPRGN
{
Unlock = TRUE ;
pRgn = REGION_LockRgn(dc->rosdc.hClipRgn); // CLIPRGN
pRgn = dc->dclevel.prgnClip;
}
if (pRgn)
@ -206,7 +142,6 @@ GdiGetClipBox(HDC hDC, PRECTL rc)
if (!pRgnNew)
{
DC_UnlockDc(dc);
if(Unlock) REGION_UnlockRgn(pRgn);
return ERROR;
}
@ -217,12 +152,11 @@ GdiGetClipBox(HDC hDC, PRECTL rc)
REGION_Delete(pRgnNew);
DC_UnlockDc(dc);
if(Unlock) REGION_UnlockRgn(pRgn);
return retval;
}
retval = REGION_GetRgnBox(dc->prgnVis, rc);
IntDPtoLP(dc, (LPPOINT)rc, 2);
DC_UnlockDc(dc);
return retval;
@ -265,53 +199,49 @@ int APIENTRY NtGdiExcludeClipRect(HDC hDC,
int RightRect,
int BottomRect)
{
INT Result;
RECTL Rect;
PREGION prgnNew, prgnClip;
PDC dc = DC_LockDc(hDC);
INT Result;
RECTL Rect;
PREGION prgnNew;
PDC dc = DC_LockDc(hDC);
if (!dc)
{
EngSetLastError(ERROR_INVALID_HANDLE);
return ERROR;
}
if (!dc)
{
EngSetLastError(ERROR_INVALID_HANDLE);
return ERROR;
}
Rect.left = LeftRect;
Rect.top = TopRect;
Rect.right = RightRect;
Rect.bottom = BottomRect;
Rect.left = LeftRect;
Rect.top = TopRect;
Rect.right = RightRect;
Rect.bottom = BottomRect;
IntLPtoDP(dc, (LPPOINT)&Rect, 2);
IntLPtoDP(dc, (LPPOINT)&Rect, 2);
prgnNew = IntSysCreateRectpRgnIndirect(&Rect);
if (!prgnNew)
{
Result = ERROR;
}
else
{
if (!dc->rosdc.hClipRgn)
{
dc->rosdc.hClipRgn = IntSysCreateRectRgn(0, 0, 0, 0);
prgnClip = REGION_LockRgn(dc->rosdc.hClipRgn);
IntGdiCombineRgn(prgnClip, dc->prgnVis, prgnNew, RGN_DIFF);
REGION_UnlockRgn(prgnClip);
Result = SIMPLEREGION;
}
else
{
prgnClip = REGION_LockRgn(dc->rosdc.hClipRgn);
Result = IntGdiCombineRgn(prgnClip, prgnClip, prgnNew, RGN_DIFF);
REGION_UnlockRgn(prgnClip);
}
REGION_Delete(prgnNew);
}
if (Result != ERROR)
CLIPPING_UpdateGCRegion(dc);
prgnNew = IntSysCreateRectpRgnIndirect(&Rect);
if (!prgnNew)
{
Result = ERROR;
}
else
{
if (!dc->dclevel.prgnClip)
{
dc->dclevel.prgnClip = IntSysCreateRectpRgn(0, 0, 0, 0);
IntGdiCombineRgn(dc->dclevel.prgnClip, dc->prgnVis, prgnNew, RGN_DIFF);
Result = SIMPLEREGION;
}
else
{
Result = IntGdiCombineRgn(dc->dclevel.prgnClip, dc->dclevel.prgnClip, prgnNew, RGN_DIFF);
}
REGION_Delete(prgnNew);
}
if (Result != ERROR)
dc->fs |= DC_FLAG_DIRTY_RAO;
DC_UnlockDc(dc);
DC_UnlockDc(dc);
return Result;
return Result;
}
int APIENTRY NtGdiIntersectClipRect(HDC hDC,
@ -320,200 +250,191 @@ int APIENTRY NtGdiIntersectClipRect(HDC hDC,
int RightRect,
int BottomRect)
{
INT Result;
RECTL Rect;
HRGN NewRgn;
PDC dc = DC_LockDc(hDC);
INT Result;
RECTL Rect;
PREGION pNewRgn;
PDC dc = DC_LockDc(hDC);
DPRINT("NtGdiIntersectClipRect(%p, %d,%d-%d,%d)\n",
hDC, LeftRect, TopRect, RightRect, BottomRect);
DPRINT("NtGdiIntersectClipRect(%p, %d,%d-%d,%d)\n",
hDC, LeftRect, TopRect, RightRect, BottomRect);
if (!dc)
{
EngSetLastError(ERROR_INVALID_HANDLE);
return ERROR;
}
if (!dc)
{
EngSetLastError(ERROR_INVALID_HANDLE);
return ERROR;
}
Rect.left = LeftRect;
Rect.top = TopRect;
Rect.right = RightRect;
Rect.bottom = BottomRect;
Rect.left = LeftRect;
Rect.top = TopRect;
Rect.right = RightRect;
Rect.bottom = BottomRect;
IntLPtoDP(dc, (LPPOINT)&Rect, 2);
IntLPtoDP(dc, (LPPOINT)&Rect, 2);
NewRgn = IntSysCreateRectRgnIndirect(&Rect);
if (!NewRgn)
{
Result = ERROR;
}
else if (!dc->rosdc.hClipRgn)
{
dc->rosdc.hClipRgn = NewRgn;
Result = SIMPLEREGION;
}
else
{
Result = NtGdiCombineRgn(dc->rosdc.hClipRgn, dc->rosdc.hClipRgn, NewRgn, RGN_AND);
GreDeleteObject(NewRgn);
}
if (Result != ERROR)
CLIPPING_UpdateGCRegion(dc);
pNewRgn = IntSysCreateRectpRgnIndirect(&Rect);
if (!pNewRgn)
{
Result = ERROR;
}
else if (!dc->dclevel.prgnClip)
{
dc->dclevel.prgnClip = pNewRgn;
Result = SIMPLEREGION;
}
else
{
Result = IntGdiCombineRgn(dc->dclevel.prgnClip, dc->dclevel.prgnClip, pNewRgn, RGN_AND);
REGION_Delete(pNewRgn);
}
if (Result != ERROR)
dc->fs |= DC_FLAG_DIRTY_RAO;
DC_UnlockDc(dc);
DC_UnlockDc(dc);
return Result;
return Result;
}
int APIENTRY NtGdiOffsetClipRgn(HDC hDC,
int XOffset,
int YOffset)
{
INT Result;
DC *dc;
INT Result;
DC *dc;
if(!(dc = DC_LockDc(hDC)))
{
EngSetLastError(ERROR_INVALID_HANDLE);
return ERROR;
}
if(!(dc = DC_LockDc(hDC)))
{
EngSetLastError(ERROR_INVALID_HANDLE);
return ERROR;
}
if(dc->rosdc.hClipRgn != NULL)
{
Result = NtGdiOffsetRgn(dc->rosdc.hClipRgn,
XOffset,
YOffset);
CLIPPING_UpdateGCRegion(dc);
}
else
{
Result = NULLREGION;
}
if(dc->dclevel.prgnClip != NULL)
{
Result = IntGdiOffsetRgn(dc->dclevel.prgnClip,
XOffset,
YOffset);
dc->fs |= DC_FLAG_DIRTY_RAO;
}
else
{
Result = NULLREGION;
}
DC_UnlockDc(dc);
return Result;
DC_UnlockDc(dc);
return Result;
}
BOOL APIENTRY NtGdiPtVisible(HDC hDC,
int X,
int Y)
{
HRGN rgn;
DC *dc;
BOOL ret = FALSE;
PDC dc;
if(!(dc = DC_LockDc(hDC)))
{
EngSetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
if(!(dc = DC_LockDc(hDC)))
{
EngSetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
rgn = dc->rosdc.hGCClipRgn;
DC_UnlockDc(dc);
if (dc->prgnRao)
{
POINT pt = {X, Y};
IntLPtoDP(dc, &pt, 1);
ret = REGION_PtInRegion(dc->prgnRao, pt.x, pt.y);
}
return (rgn ? NtGdiPtInRegion(rgn, X, Y) : FALSE);
DC_UnlockDc(dc);
return ret;
}
BOOL APIENTRY NtGdiRectVisible(HDC hDC,
LPRECT UnsafeRect)
BOOL
APIENTRY
NtGdiRectVisible(
HDC hDC,
LPRECT UnsafeRect)
{
NTSTATUS Status = STATUS_SUCCESS;
PROSRGNDATA Rgn;
PDC dc = DC_LockDc(hDC);
BOOL Result = FALSE;
RECTL Rect;
NTSTATUS Status = STATUS_SUCCESS;
PDC dc = DC_LockDc(hDC);
BOOL Result = FALSE;
RECTL Rect;
if (!dc)
{
EngSetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
if (!dc)
{
EngSetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
_SEH2_TRY
{
ProbeForRead(UnsafeRect,
_SEH2_TRY
{
ProbeForRead(UnsafeRect,
sizeof(RECT),
1);
Rect = *UnsafeRect;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
Rect = *UnsafeRect;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
if(!NT_SUCCESS(Status))
{
DC_UnlockDc(dc);
SetLastNtError(Status);
return FALSE;
}
if(!NT_SUCCESS(Status))
{
DC_UnlockDc(dc);
SetLastNtError(Status);
return FALSE;
}
if (dc->rosdc.hGCClipRgn)
{
if((Rgn = (PROSRGNDATA)RGNOBJAPI_Lock(dc->rosdc.hGCClipRgn, NULL)))
{
if (dc->fs & DC_FLAG_DIRTY_RAO)
CLIPPING_UpdateGCRegion(dc);
if (dc->prgnRao)
{
IntLPtoDP(dc, (LPPOINT)&Rect, 2);
Result = REGION_RectInRegion(Rgn, &Rect);
RGNOBJAPI_Unlock(Rgn);
}
}
DC_UnlockDc(dc);
Result = REGION_RectInRegion(dc->prgnRao, &Rect);
}
DC_UnlockDc(dc);
return Result;
return Result;
}
int
FASTCALL
IntGdiSetMetaRgn(PDC pDC)
{
INT Ret = ERROR;
PROSRGNDATA TempRgn;
INT Ret = ERROR;
if ( pDC->dclevel.prgnMeta )
{
if ( pDC->dclevel.prgnClip )
{
TempRgn = IntSysCreateRectpRgn(0,0,0,0);
if (TempRgn)
if ( pDC->dclevel.prgnMeta )
{
if ( pDC->dclevel.prgnClip )
{
Ret = IntGdiCombineRgn( TempRgn,
pDC->dclevel.prgnMeta,
pDC->dclevel.prgnClip,
RGN_AND);
if ( Ret )
{
GDIOBJ_vDereferenceObject(&pDC->dclevel.prgnMeta->BaseObject);
if (!((PROSRGNDATA)pDC->dclevel.prgnMeta)->BaseObject.ulShareCount)
REGION_Delete(pDC->dclevel.prgnMeta);
pDC->dclevel.prgnMeta = TempRgn;
GDIOBJ_vDereferenceObject(&pDC->dclevel.prgnClip->BaseObject);
if (!((PROSRGNDATA)pDC->dclevel.prgnClip)->BaseObject.ulShareCount)
REGION_Delete(pDC->dclevel.prgnClip);
pDC->dclevel.prgnClip = NULL;
IntGdiReleaseRaoRgn(pDC);
}
else
REGION_Delete(TempRgn);
Ret = IntGdiCombineRgn(pDC->dclevel.prgnMeta, pDC->dclevel.prgnMeta, pDC->dclevel.prgnClip, RGN_AND);
if (Ret != ERROR)
{
REGION_Delete(pDC->dclevel.prgnClip);
pDC->dclevel.prgnClip = NULL;
IntGdiReleaseRaoRgn(pDC);
}
}
}
else
Ret = REGION_Complexity(pDC->dclevel.prgnMeta);
}
else
{
if ( pDC->dclevel.prgnClip )
{
Ret = REGION_Complexity(pDC->dclevel.prgnClip);
pDC->dclevel.prgnMeta = pDC->dclevel.prgnClip;
pDC->dclevel.prgnClip = NULL;
}
else
Ret = SIMPLEREGION;
}
return Ret;
else
Ret = REGION_Complexity(pDC->dclevel.prgnMeta);
}
else
{
if ( pDC->dclevel.prgnClip )
{
Ret = REGION_Complexity(pDC->dclevel.prgnClip);
pDC->dclevel.prgnMeta = pDC->dclevel.prgnClip;
pDC->dclevel.prgnClip = NULL;
}
else
Ret = SIMPLEREGION;
}
if (Ret != ERROR)
pDC->fs |= DC_FLAG_DIRTY_RAO;
return Ret;
}
@ -533,88 +454,95 @@ int APIENTRY NtGdiSetMetaRgn(HDC hDC)
return Ret;
}
INT FASTCALL
NEW_CLIPPING_UpdateGCRegion(PDC pDC)
VOID
FASTCALL
CLIPPING_UpdateGCRegion(PDC pDC)
{
CLIPOBJ * co;
CLIPOBJ * co;
/* Must have VisRgn set to a valid state! */
ASSERT (pDC->prgnVis);
/* Must have VisRgn set to a valid state! */
ASSERT (pDC->prgnVis);
// FIXME: this seems to be broken!
if (pDC->prgnAPI)
{
REGION_Delete(pDC->prgnAPI);
pDC->prgnAPI = NULL;
}
if (pDC->prgnAPI)
{
REGION_Delete(pDC->prgnAPI);
pDC->prgnAPI = IntSysCreateRectpRgn(0,0,0,0);
}
if (pDC->prgnRao)
REGION_Delete(pDC->prgnRao);
if (pDC->prgnRao)
{
REGION_Delete(pDC->prgnRao);
pDC->prgnRao = IntSysCreateRectpRgn(0,0,0,0);
}
pDC->prgnRao = IntSysCreateRectpRgn(0,0,0,0);
if (!pDC->prgnRao)
{
return ERROR;
}
ASSERT(pDC->prgnRao);
if (pDC->dclevel.prgnMeta && pDC->dclevel.prgnClip)
{
IntGdiCombineRgn( pDC->prgnAPI,
pDC->dclevel.prgnClip,
pDC->dclevel.prgnMeta,
RGN_AND);
}
else
{
if (pDC->dclevel.prgnClip)
{
IntGdiCombineRgn( pDC->prgnAPI,
pDC->dclevel.prgnClip,
NULL,
RGN_COPY);
}
else if (pDC->dclevel.prgnMeta)
{
IntGdiCombineRgn( pDC->prgnAPI,
pDC->dclevel.prgnMeta,
NULL,
RGN_COPY);
}
}
if (pDC->dclevel.prgnMeta || pDC->dclevel.prgnClip)
{
pDC->prgnAPI = IntSysCreateRectpRgn(0,0,0,0);
if (!pDC->dclevel.prgnMeta)
{
IntGdiCombineRgn(pDC->prgnAPI,
pDC->dclevel.prgnClip,
NULL,
RGN_COPY);
}
else if (!pDC->dclevel.prgnClip)
{
IntGdiCombineRgn(pDC->prgnAPI,
pDC->dclevel.prgnMeta,
NULL,
RGN_COPY);
}
else
{
IntGdiCombineRgn(pDC->prgnAPI,
pDC->dclevel.prgnClip,
pDC->dclevel.prgnMeta,
RGN_AND);
}
}
IntGdiCombineRgn( pDC->prgnRao,
pDC->prgnVis,
pDC->prgnAPI,
RGN_AND);
if (pDC->prgnAPI)
{
IntGdiCombineRgn(pDC->prgnRao,
pDC->prgnVis,
pDC->prgnAPI,
RGN_AND);
}
else
{
IntGdiCombineRgn(pDC->prgnRao,
pDC->prgnVis,
NULL,
RGN_COPY);
}
RtlCopyMemory(&pDC->erclClip,
IntGdiOffsetRgn(pDC->prgnRao, pDC->ptlDCOrig.x, pDC->ptlDCOrig.y);
RtlCopyMemory(&pDC->erclClip,
&pDC->prgnRao->rdh.rcBound,
sizeof(RECTL));
pDC->fs &= ~DC_FLAG_DIRTY_RAO;
pDC->fs &= ~DC_FLAG_DIRTY_RAO;
IntGdiOffsetRgn(pDC->prgnRao, pDC->ptlDCOrig.x, pDC->ptlDCOrig.y);
// pDC->co should be used. Example, CLIPOBJ_cEnumStart uses XCLIPOBJ to build
// the rects from region objects rects in pClipRgn->Buffer.
// With pDC->co.pClipRgn->Buffer,
// pDC->co.pClipRgn = pDC->prgnRao ? pDC->prgnRao : pDC->prgnVis;
// pDC->co should be used. Example, CLIPOBJ_cEnumStart uses XCLIPOBJ to build
// the rects from region objects rects in pClipRgn->Buffer.
// With pDC->co.pClipRgn->Buffer,
// pDC->co.pClipRgn = pDC->prgnRao ? pDC->prgnRao : pDC->prgnVis;
co = IntEngCreateClipRegion(pDC->prgnRao->rdh.nCount,
pDC->prgnRao->Buffer,
&pDC->erclClip);
if (co)
{
if (pDC->rosdc.CombinedClip != NULL)
IntEngDeleteClipRegion(pDC->rosdc.CombinedClip);
co = IntEngCreateClipRegion(pDC->prgnRao->rdh.nCount,
pDC->prgnRao->Buffer,
&pDC->erclClip);
if (co)
{
if (pDC->rosdc.CombinedClip != NULL)
IntEngDeleteClipRegion(pDC->rosdc.CombinedClip);
pDC->rosdc.CombinedClip = co;
}
pDC->rosdc.CombinedClip = co;
}
return IntGdiOffsetRgn(pDC->prgnRao, -pDC->ptlDCOrig.x, -pDC->ptlDCOrig.y);
IntGdiOffsetRgn(pDC->prgnRao, -pDC->ptlDCOrig.x, -pDC->ptlDCOrig.y);
}
/* EOF */

View file

@ -1,6 +1,6 @@
#pragma once
INT FASTCALL GdiGetClipBox(HDC hDC, RECTL *rc);
INT FASTCALL GdiSelectVisRgn(HDC hdc, HRGN hrgn);
INT FASTCALL GdiExtSelectClipRgn (PDC dc, HRGN hrgn, int fnMode);
int FASTCALL CLIPPING_UpdateGCRegion(DC* Dc);
VOID FASTCALL GdiSelectVisRgn(HDC hdc, PREGION prgn);
INT FASTCALL IntGdiExtSelectClipRgn (PDC dc, PREGION prgn, int fnMode);
VOID FASTCALL CLIPPING_UpdateGCRegion(DC* Dc);

View file

@ -48,9 +48,6 @@ typedef enum _DCTYPE
typedef struct _ROS_DC_INFO
{
HRGN hClipRgn; /* Clip region (may be 0) */
HRGN hGCClipRgn; /* GC clip region (ClipRgn AND VisRgn) */
CLIPOBJ *CombinedClip;
} ROS_DC_INFO;
@ -199,9 +196,9 @@ BOOL FASTCALL IntGdiDeleteDC(HDC, BOOL);
BOOL FASTCALL DC_InvertXform(const XFORM *xformSrc, XFORM *xformDest);
VOID FASTCALL DC_vUpdateViewportExt(PDC pdc);
VOID FASTCALL DC_vCopyState(PDC pdcSrc, PDC pdcDst, BOOL to);
VOID FASTCALL DC_vCopyState(PDC pdcSrc, PDC pdcDst, BOOL To);
VOID FASTCALL DC_vFinishBlit(PDC pdc1, PDC pdc2);
VOID FASTCALL DC_vPrepareDCsForBlit(PDC pdc1, RECT rc1, PDC pdc2, RECT rc2);
VOID FASTCALL DC_vPrepareDCsForBlit(PDC pdcDest, const RECT* rcDest, PDC pdcSrc, const RECT* rcSrc);
VOID NTAPI DC_vRestoreDC(IN PDC pdc, INT iSaveLevel);

View file

@ -95,22 +95,11 @@ DC_AllocDcWithHandle()
void
DC_InitHack(PDC pdc)
{
HRGN hVisRgn;
TextIntRealizeFont(pdc->pdcattr->hlfntNew,NULL);
pdc->pdcattr->iCS_CP = ftGdiGetTextCharsetInfo(pdc,NULL,0);
/* This should never fail */
ASSERT(pdc->dclevel.ppal);
/* Select regions */
pdc->rosdc.hClipRgn = NULL;
pdc->rosdc.hGCClipRgn = NULL;
hVisRgn = IntSysCreateRectRgn(0, 0, 1, 1);
ASSERT(hVisRgn);
GdiSelectVisRgn(pdc->BaseObject.hHmgr, hVisRgn);
GreDeleteObject(hVisRgn);
}
VOID
@ -170,7 +159,7 @@ DC_vInitDc(
pdc->erclBoundsApp.right = 0x00007ffc; // FIXME
pdc->erclBoundsApp.bottom = 0x00000333; // FIXME
pdc->erclClip = pdc->erclBounds;
// pdc->co
pdc->co = gxcoTrivial;
pdc->fs |= DC_SYNCHRONIZEACCESS | DC_ACCUM_APP | DC_PERMANANT | DC_DISPLAY;
}
@ -185,7 +174,7 @@ DC_vInitDc(
pdc->erclBounds.bottom = 0;
pdc->erclBoundsApp = pdc->erclBounds;
pdc->erclClip = pdc->erclWindow;
//pdc->co = NULL
pdc->co = gxcoTrivial;
}
//pdc->dcattr.VisRectRegion:
@ -237,6 +226,8 @@ DC_vInitDc(
/* Setup regions */
pdc->prgnAPI = NULL;
pdc->prgnRao = NULL;
pdc->dclevel.prgnClip = NULL;
pdc->dclevel.prgnMeta = NULL;
/* Allocate a Vis region */
pdc->prgnVis = IntSysCreateRectpRgn(0, 0, pdc->dclevel.sizl.cx, pdc->dclevel.sizl.cy);
ASSERT(pdc->prgnVis);
@ -372,17 +363,17 @@ DC_vCleanup(PVOID ObjectBody)
LFONT_ShareUnlockFont(pdc->dclevel.plfnt);
/* Free regions */
if (pdc->rosdc.hClipRgn && GreIsHandleValid(pdc->rosdc.hClipRgn))
GreDeleteObject(pdc->rosdc.hClipRgn);
if (pdc->dclevel.prgnClip)
REGION_Delete(pdc->dclevel.prgnClip);
if (pdc->dclevel.prgnMeta)
REGION_Delete(pdc->dclevel.prgnMeta);
if (pdc->prgnVis)
{
REGION_Delete(pdc->prgnVis);
}
if (pdc->rosdc.hGCClipRgn && GreIsHandleValid(pdc->rosdc.hGCClipRgn))
{
GreDeleteObject(pdc->rosdc.hGCClipRgn);
}
if (NULL != pdc->rosdc.CombinedClip)
if (pdc->prgnRao)
REGION_Delete(pdc->prgnRao);
if (pdc->prgnAPI)
REGION_Delete(pdc->prgnAPI);
if (pdc->rosdc.CombinedClip)
IntEngDeleteClipRegion(pdc->rosdc.CombinedClip);
PATH_Delete(pdc->dclevel.hPath);
@ -397,17 +388,6 @@ VOID
NTAPI
DC_vSetOwner(PDC pdc, ULONG ulOwner)
{
if (pdc->rosdc.hClipRgn)
{
IntGdiSetRegionOwner(pdc->rosdc.hClipRgn, ulOwner);
}
if (pdc->rosdc.hGCClipRgn)
{
IntGdiSetRegionOwner(pdc->rosdc.hGCClipRgn, ulOwner);
}
if (pdc->dclevel.hPath)
{
GreSetObjectOwner(pdc->dclevel.hPath, ulOwner);
@ -466,7 +446,7 @@ static
void
DC_vUpdateDC(PDC pdc)
{
HRGN hVisRgn ;
// PREGION VisRgn ;
PPDEVOBJ ppdev = pdc->ppdev ;
pdc->dhpdev = ppdev->dhpdev;
@ -475,10 +455,12 @@ DC_vUpdateDC(PDC pdc)
pdc->dclevel.pSurface = PDEVOBJ_pSurface(ppdev);
PDEVOBJ_sizl(pdc->ppdev, &pdc->dclevel.sizl);
hVisRgn = NtGdiCreateRectRgn(0, 0, pdc->dclevel.sizl.cx, pdc->dclevel.sizl.cy);
ASSERT(hVisRgn);
GdiSelectVisRgn(pdc->BaseObject.hHmgr, hVisRgn);
GreDeleteObject(hVisRgn);
#if 0
VisRgn = IntSysCreateRectpRgn(0, 0, pdc->dclevel.sizl.cx, pdc->dclevel.sizl.cy);
ASSERT(VisRgn);
GdiSelectVisRgn(pdc->BaseObject.hHmgr, VisRgn);
REGION_Delete(VisRgn);
#endif
pdc->flGraphicsCaps = ppdev->devinfo.flGraphicsCaps;
pdc->flGraphicsCaps2 = ppdev->devinfo.flGraphicsCaps2;
@ -492,76 +474,107 @@ DC_vUpdateDC(PDC pdc)
* from where we take pixels. */
VOID
FASTCALL
DC_vPrepareDCsForBlit(PDC pdc1,
RECT rc1,
PDC pdc2,
RECT rc2)
DC_vPrepareDCsForBlit(
PDC pdcDest,
const RECT* rcDest,
PDC pdcSrc,
const RECT* rcSrc)
{
PDC pdcFirst, pdcSecond;
PRECT prcFirst, prcSecond;
const RECT *prcFirst, *prcSecond;
/* Update brushes */
if (pdc1->pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
DC_vUpdateFillBrush(pdc1);
if (pdc1->pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
DC_vUpdateLineBrush(pdc1);
if(pdc1->pdcattr->ulDirty_ & DIRTY_TEXT)
DC_vUpdateTextBrush(pdc1);
if (pdcDest->pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
DC_vUpdateFillBrush(pdcDest);
if (pdcDest->pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
DC_vUpdateLineBrush(pdcDest);
if(pdcDest->pdcattr->ulDirty_ & DIRTY_TEXT)
DC_vUpdateTextBrush(pdcDest);
/* Lock them in good order */
if(pdc2)
if(pdcSrc)
{
if((ULONG_PTR)pdc1->ppdev->hsemDevLock >= (ULONG_PTR)pdc2->ppdev->hsemDevLock)
if((ULONG_PTR)pdcDest->ppdev->hsemDevLock >= (ULONG_PTR)pdcSrc->ppdev->hsemDevLock)
{
pdcFirst = pdc1;
prcFirst = &rc1;
pdcSecond = pdc2;
prcSecond = &rc2;
pdcFirst = pdcDest;
prcFirst = rcDest;
pdcSecond = pdcSrc;
prcSecond = rcSrc;
}
else
{
pdcFirst = pdc2;
prcFirst = &rc2;
pdcSecond = pdc1;
prcSecond = &rc1;
pdcFirst = pdcSrc;
prcFirst = rcSrc;
pdcSecond = pdcDest;
prcSecond = rcDest;
}
}
else
{
pdcFirst = pdc1 ;
prcFirst = &rc1;
pdcFirst = pdcDest ;
prcFirst = rcDest;
pdcSecond = NULL;
prcSecond = NULL;
}
if(pdcFirst && pdcFirst->dctype == DCTYPE_DIRECT)
/* Update clipping of dest DC if needed */
if (pdcDest->dctype == DCTYPE_DIRECT)
{
DCE* dce = DceGetDceFromDC(pdcDest->BaseObject.hHmgr);
if (dce)
DceUpdateVisRgn(dce, dce->pwndOrg, dce->DCXFlags);
}
if (pdcDest->fs & DC_FLAG_DIRTY_RAO)
CLIPPING_UpdateGCRegion(pdcDest);
/* Lock and update first DC */
if(pdcFirst->dctype == DCTYPE_DIRECT)
{
EngAcquireSemaphore(pdcFirst->ppdev->hsemDevLock);
MouseSafetyOnDrawStart(pdcFirst->ppdev,
prcFirst->left,
prcFirst->top,
prcFirst->right,
prcFirst->bottom) ;
/* Update surface if needed */
if(pdcFirst->ppdev->pSurface != pdcFirst->dclevel.pSurface)
{
DC_vUpdateDC(pdcFirst);
}
}
if(pdcSecond && pdcSecond->dctype == DCTYPE_DIRECT)
if(pdcFirst->dctype == DCTYPE_DIRECT)
{
if (!prcFirst)
prcFirst = &pdcFirst->erclClip;
MouseSafetyOnDrawStart(pdcFirst->ppdev,
prcFirst->left,
prcFirst->top,
prcFirst->right,
prcFirst->bottom) ;
}
if (!pdcSecond)
return;
/* Lock and update second DC */
if(pdcSecond->dctype == DCTYPE_DIRECT)
{
EngAcquireSemaphore(pdcSecond->ppdev->hsemDevLock);
MouseSafetyOnDrawStart(pdcSecond->ppdev,
prcSecond->left,
prcSecond->top,
prcSecond->right,
prcSecond->bottom) ;
/* Update surface if needed */
if(pdcSecond->ppdev->pSurface != pdcSecond->dclevel.pSurface)
{
DC_vUpdateDC(pdcSecond);
}
}
if(pdcSecond->dctype == DCTYPE_DIRECT)
{
if (!prcSecond)
prcSecond = &pdcSecond->erclClip;
MouseSafetyOnDrawStart(pdcSecond->ppdev,
prcSecond->left,
prcSecond->top,
prcSecond->right,
prcSecond->bottom) ;
}
}
/* Finishes a blit for one or two DCs */

View file

@ -330,7 +330,7 @@ NtGdiSelectBitmap(
PDC pdc;
HBITMAP hbmpOld;
PSURFACE psurfNew, psurfOld;
HRGN hVisRgn;
PREGION VisRgn;
HDC hdcOld;
ULONG cBitsPixel;
ASSERT_NOGDILOCKS();
@ -452,15 +452,15 @@ NtGdiSelectBitmap(
pdc->pdcattr->ulDirty_ |= DIRTY_FILL | DIRTY_LINE;
/* FIXME: Improve by using a region without a handle and selecting it */
hVisRgn = IntSysCreateRectRgn( 0,
VisRgn = IntSysCreateRectpRgn( 0,
0,
pdc->dclevel.sizl.cx,
pdc->dclevel.sizl.cy);
if (hVisRgn)
if (VisRgn)
{
GdiSelectVisRgn(hdc, hVisRgn);
GreDeleteObject(hVisRgn);
GdiSelectVisRgn(hdc, VisRgn);
REGION_Delete(VisRgn);
}
/* Unlock the DC */
@ -509,7 +509,10 @@ NtGdiSelectClipPath(
/* Construct a region from the path */
else if (PATH_PathToRegion(pPath, pdcattr->jFillMode, &hrgnPath))
{
success = GdiExtSelectClipRgn(pdc, hrgnPath, Mode) != ERROR;
PREGION prgnPath = REGION_LockRgn(hrgnPath);
ASSERT(prgnPath);
success = IntGdiExtSelectClipRgn(pdc, prgnPath, Mode) != ERROR;
REGION_UnlockRgn(prgnPath);
GreDeleteObject( hrgnPath );
/* Empty the path */
@ -693,9 +696,7 @@ NtGdiGetRandomRgn(
{
INT ret = 0;
PDC pdc;
HRGN hrgnSrc = NULL;
PREGION prgnSrc = NULL;
POINTL ptlOrg;
pdc = DC_LockDc(hdc);
if (!pdc)
@ -707,8 +708,7 @@ NtGdiGetRandomRgn(
switch (iCode)
{
case CLIPRGN:
hrgnSrc = pdc->rosdc.hClipRgn;
// if (pdc->dclevel.prgnClip) prgnSrc = pdc->dclevel.prgnClip;
prgnSrc = pdc->dclevel.prgnClip;
break;
case METARGN:
@ -716,14 +716,15 @@ NtGdiGetRandomRgn(
break;
case APIRGN:
if (pdc->fs & DC_FLAG_DIRTY_RAO)
CLIPPING_UpdateGCRegion(pdc);
if (pdc->prgnAPI)
{
prgnSrc = pdc->prgnAPI;
}
// else if (pdc->dclevel.prgnClip) prgnSrc = pdc->dclevel.prgnClip;
else if (pdc->rosdc.hClipRgn)
else if (pdc->dclevel.prgnClip)
{
hrgnSrc = pdc->rosdc.hClipRgn;
prgnSrc = pdc->dclevel.prgnClip;
}
else if (pdc->dclevel.prgnMeta)
{
@ -739,28 +740,20 @@ NtGdiGetRandomRgn(
break;
}
if (hrgnSrc)
{
ret = NtGdiCombineRgn(hrgnDest, hrgnSrc, 0, RGN_COPY) == ERROR ? -1 : 1;
}
else if (prgnSrc)
if (prgnSrc)
{
PREGION prgnDest = REGION_LockRgn(hrgnDest);
if (prgnDest)
{
ret = IntGdiCombineRgn(prgnDest, prgnSrc, 0, RGN_COPY) == ERROR ? -1 : 1;
if ((ret == 1) && (iCode == SYSRGN))
IntGdiOffsetRgn(prgnDest, pdc->ptlDCOrig.x, pdc->ptlDCOrig.y);
REGION_UnlockRgn(prgnDest);
}
else
ret = -1;
}
if (iCode == SYSRGN)
{
ptlOrg = pdc->ptlDCOrig;
NtGdiOffsetRgn(hrgnDest, ptlOrg.x, ptlOrg.y );
}
DC_UnlockDc(pdc);
return ret;

View file

@ -51,23 +51,26 @@ DC_vCopyState(PDC pdcSrc, PDC pdcDst, BOOL To)
pdcDst->dclevel.plfnt = pdcSrc->dclevel.plfnt;
/* Get/SetDCState() don't change hVisRgn field ("Undoc. Windows" p.559). */
if (To) // Copy "To" SaveDC state.
if (!To)
{
if (pdcSrc->rosdc.hClipRgn)
IntGdiExtSelectClipRgn(pdcDst, pdcSrc->dclevel.prgnClip, RGN_COPY);
if (pdcDst->dclevel.prgnMeta)
{
pdcDst->rosdc.hClipRgn = IntSysCreateRectRgn(0, 0, 0, 0);
NtGdiCombineRgn(pdcDst->rosdc.hClipRgn, pdcSrc->rosdc.hClipRgn, 0, RGN_COPY);
REGION_Delete(pdcDst->dclevel.prgnMeta);
pdcDst->dclevel.prgnMeta = NULL;
}
// FIXME: Handle prgnMeta!
}
else // Copy "!To" RestoreDC state.
{ /* The VisRectRegion field needs to be set to a valid state */
GdiExtSelectClipRgn(pdcDst, pdcSrc->rosdc.hClipRgn, RGN_COPY);
if (pdcSrc->dclevel.prgnMeta)
{
pdcDst->dclevel.prgnMeta = IntSysCreateRectpRgn(0, 0, 0, 0);
IntGdiCombineRgn(pdcDst->dclevel.prgnMeta, pdcSrc->dclevel.prgnMeta, NULL, RGN_COPY);
}
pdcDst->fs |= DC_FLAG_DIRTY_RAO;
}
}
BOOL FASTCALL
BOOL
FASTCALL
IntGdiCleanDC(HDC hDC)
{
PDC dc;
@ -87,6 +90,16 @@ IntGdiCleanDC(HDC hDC)
DC_vUpdateTextBrush(dc);
}
/* DC_vCopyState frees the Clip rgn and the Meta rgn. Take care of the other ones
* There is no need to clear prgnVis, as UserGetDC updates it immediately. */
if (dc->prgnRao)
REGION_Delete(dc->prgnRao);
if (dc->prgnAPI)
REGION_Delete(dc->prgnAPI);
dc->prgnRao = dc->prgnAPI = NULL;
dc->fs |= DC_FLAG_DIRTY_RAO;
DC_UnlockDc(dc);
return TRUE;
@ -272,7 +285,7 @@ NtGdiSaveDC(
GDIOBJ_vSetObjectOwner(&pdcSave->BaseObject, GDI_OBJ_HMGR_PUBLIC);
/* Copy the current state */
DC_vCopyState(pdc, pdcSave, TRUE);
DC_vCopyState(pdc, pdcSave, FALSE);
/* Only memory DC's change their surface */
if (pdc->dctype == DCTYPE_MEMORY)

View file

@ -367,7 +367,7 @@ IntGdiSetHookFlags(HDC hDC, WORD Flags)
}
else if (Flags & DCHF_VALIDATEVISRGN || 0 == Flags)
{
dc->fs &= ~DC_FLAG_DIRTY_RAO;
//dc->fs &= ~DC_FLAG_DIRTY_RAO;
}
DC_UnlockDc(dc);

View file

@ -502,7 +502,7 @@ NtGdiSetDIBitsToDeviceInternal(
}
/* This is actually a blit */
DC_vPrepareDCsForBlit(pDC, rcDest, NULL, rcDest);
DC_vPrepareDCsForBlit(pDC, &rcDest, NULL, NULL);
pSurf = pDC->dclevel.pSurface;
if (!pSurf)
{
@ -1184,7 +1184,7 @@ NtGdiStretchDIBitsInternal(
}
/* Prepare DC for blit */
DC_vPrepareDCsForBlit(pdc, rcDst, NULL, rcSrc);
DC_vPrepareDCsForBlit(pdc, &rcDst, NULL, NULL);
psurfDst = pdc->dclevel.pSurface;

View file

@ -307,7 +307,7 @@ NtGdiEllipse(
tmpFillBrushObj.ptOrigin.x += dc->ptlDCOrig.x;
tmpFillBrushObj.ptOrigin.y += dc->ptlDCOrig.y;
DC_vPrepareDCsForBlit(dc, RectBounds, NULL, RectBounds);
DC_vPrepareDCsForBlit(dc, &RectBounds, NULL, NULL);
ret = IntFillEllipse( dc,
CenterX - RadiusX,
@ -480,8 +480,7 @@ NtGdiPolyPolyDraw( IN HDC hDC,
return TRUE;
}
DC_vPrepareDCsForBlit(dc, dc->rosdc.CombinedClip->rclBounds,
NULL, dc->rosdc.CombinedClip->rclBounds);
DC_vPrepareDCsForBlit(dc, NULL, NULL, NULL);
if (dc->pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
DC_vUpdateFillBrush(dc);
@ -567,7 +566,7 @@ IntRectangle(PDC dc,
DestRect.bottom--;
}
DC_vPrepareDCsForBlit(dc, DestRect, NULL, DestRect);
DC_vPrepareDCsForBlit(dc, &DestRect, NULL, NULL);
if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
DC_vUpdateFillBrush(dc);
@ -796,7 +795,7 @@ IntRoundRect(
else
{
DC_vPrepareDCsForBlit(dc, RectBounds, NULL, RectBounds);
DC_vPrepareDCsForBlit(dc, &RectBounds, NULL, NULL);
RtlCopyMemory(&brushTemp, pbrFill, sizeof(brushTemp));
brushTemp.ptOrigin.x += RectBounds.left - Left;
@ -962,9 +961,9 @@ GreGradientFill(
EXLATEOBJ_vInitialize(&exlo, &gpalRGB, psurf->ppal, 0, 0, 0);
ASSERT(pdc->rosdc.CombinedClip);
DC_vPrepareDCsForBlit(pdc, &rclExtent, NULL, NULL);
DC_vPrepareDCsForBlit(pdc, rclExtent, NULL, rclExtent);
ASSERT(pdc->rosdc.CombinedClip);
bRet = IntEngGradientFill(&psurf->SurfObj,
pdc->rosdc.CombinedClip,
@ -1091,6 +1090,13 @@ NtGdiExtFloodFill(
return TRUE;
}
psurf = dc->dclevel.pSurface;
if (!psurf)
{
Ret = FALSE;
goto cleanup;
}
pdcattr = dc->pdcattr;
if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
@ -1103,20 +1109,18 @@ NtGdiExtFloodFill(
Pt.y = YStart;
IntLPtoDP(dc, (LPPOINT)&Pt, 1);
Ret = NtGdiPtInRegion(dc->rosdc.hGCClipRgn, Pt.x, Pt.y);
if (Ret)
IntGdiGetRgnBox(dc->rosdc.hGCClipRgn,(LPRECT)&DestRect);
else
goto cleanup;
DC_vPrepareDCsForBlit(dc, DestRect, NULL, DestRect);
psurf = dc->dclevel.pSurface;
if (!psurf)
if (dc->prgnRao)
{
Ret = FALSE;
goto cleanup;
Ret = REGION_PtInRegion(dc->prgnRao, Pt.x, Pt.y);
if (Ret)
REGION_GetRgnBox(dc->prgnRao ,(LPRECT)&DestRect);
else
goto cleanup;
}
else
RECTL_vSetRect(&DestRect, 0, psurf->SurfObj.sizlBitmap.cx, 0, psurf->SurfObj.sizlBitmap.cy);
DC_vPrepareDCsForBlit(dc, &DestRect, NULL, NULL);
EXLATEOBJ_vInitialize(&exlo, &gpalRGB, psurf->ppal, 0, 0xffffff, 0);
@ -1127,10 +1131,11 @@ NtGdiExtFloodFill(
ConvColor = XLATEOBJ_iXlate(&exlo.xlo, Color);
Ret = DIB_XXBPP_FloodFillSolid(&psurf->SurfObj, &dc->eboFill.BrushObject, &DestRect, &Pt, ConvColor, FillType);
DC_vFinishBlit(dc, NULL);
EXLATEOBJ_vCleanup(&exlo);
cleanup:
DC_vFinishBlit(dc, NULL);
DC_UnlockDc(dc);
return Ret;
}

View file

@ -3212,7 +3212,7 @@ GreExtTextOutW(
LONGLONG TextLeft, RealXStart;
ULONG TextTop, previous, BackgroundLeft;
FT_Bool use_kerning;
RECTL DestRect, MaskRect, DummyRect = {0, 0, 0, 0};
RECTL DestRect, MaskRect;
POINTL SourcePoint, BrushOrigin;
HBITMAP HSourceGlyph;
SURFOBJ *SourceGlyphSurf;
@ -3308,7 +3308,7 @@ GreExtTextOutW(
DestRect.right += dc->ptlDCOrig.x;
DestRect.bottom += dc->ptlDCOrig.y;
DC_vPrepareDCsForBlit(dc, DestRect, NULL, DestRect);
DC_vPrepareDCsForBlit(dc, &DestRect, NULL, NULL);
if (pdcattr->ulDirty_ & DIRTY_BACKGROUND)
DC_vUpdateBackgroundBrush(dc);
@ -3502,7 +3502,7 @@ GreExtTextOutW(
BackgroundLeft = (RealXStart + 32) >> 6;
/* Lock blit with a dummy rect */
DC_vPrepareDCsForBlit(dc, DummyRect, NULL, DummyRect);
DC_vPrepareDCsForBlit(dc, NULL, NULL, NULL);
psurf = dc->dclevel.pSurface ;
if(!psurf) psurf = psurfDefaultBitmap;

View file

@ -257,8 +257,7 @@ IntGdiPolyline(DC *dc,
if (PATH_IsPathOpen(dc->dclevel))
return PATH_Polyline(dc, pt, Count);
DC_vPrepareDCsForBlit(dc, dc->rosdc.CombinedClip->rclBounds,
NULL, dc->rosdc.CombinedClip->rclBounds);
DC_vPrepareDCsForBlit(dc, NULL, NULL, NULL);
if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
DC_vUpdateFillBrush(dc);
@ -411,7 +410,7 @@ NtGdiLineTo(HDC hDC,
rcLockRect.right += dc->ptlDCOrig.x;
rcLockRect.bottom += dc->ptlDCOrig.y;
DC_vPrepareDCsForBlit(dc, rcLockRect, NULL, rcLockRect);
DC_vPrepareDCsForBlit(dc, &rcLockRect, NULL, NULL);
if (dc->pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
DC_vUpdateLineBrush(dc);

View file

@ -2511,8 +2511,7 @@ NtGdiFillPath(HDC hDC)
return FALSE;
}
DC_vPrepareDCsForBlit(dc, dc->rosdc.CombinedClip->rclBounds,
NULL, dc->rosdc.CombinedClip->rclBounds);
DC_vPrepareDCsForBlit(dc, NULL, NULL, NULL);
pdcattr = dc->pdcattr;
@ -2777,8 +2776,7 @@ NtGdiStrokeAndFillPath(HDC hDC)
return FALSE;
}
DC_vPrepareDCsForBlit(pDc, pDc->rosdc.CombinedClip->rclBounds,
NULL, pDc->rosdc.CombinedClip->rclBounds);
DC_vPrepareDCsForBlit(pDc, NULL, NULL, NULL);
pdcattr = pDc->pdcattr;
@ -2822,8 +2820,7 @@ NtGdiStrokePath(HDC hDC)
return FALSE;
}
DC_vPrepareDCsForBlit(pDc, pDc->rosdc.CombinedClip->rclBounds,
NULL, pDc->rosdc.CombinedClip->rclBounds);
DC_vPrepareDCsForBlit(pDc, NULL, NULL, NULL);
pdcattr = pDc->pdcattr;

View file

@ -2300,11 +2300,13 @@ REGION_Delete(PROSRGNDATA pRgn)
VOID FASTCALL
IntGdiReleaseRaoRgn(PDC pDC)
{
INT Index = GDI_HANDLE_GET_INDEX(pDC->BaseObject.hHmgr);
PGDI_TABLE_ENTRY Entry = &GdiHandleTable->Entries[Index];
pDC->fs |= DC_FLAG_DIRTY_RAO;
Entry->Flags |= GDI_ENTRY_VALIDATE_VIS;
RECTL_vSetEmptyRect(&pDC->erclClip);
INT Index = GDI_HANDLE_GET_INDEX(pDC->BaseObject.hHmgr);
PGDI_TABLE_ENTRY Entry = &GdiHandleTable->Entries[Index];
pDC->fs |= DC_FLAG_DIRTY_RAO;
Entry->Flags |= GDI_ENTRY_VALIDATE_VIS;
RECTL_vSetEmptyRect(&pDC->erclClip);
REGION_Delete(pDC->prgnRao);
pDC->prgnRao = NULL;
}
VOID FASTCALL
@ -2503,8 +2505,6 @@ IntGdiPaintRgn(
return FALSE;
}
NtGdiCombineRgn(tmpVisRgn, tmpVisRgn, dc->rosdc.hGCClipRgn, RGN_AND);
visrgn = RGNOBJAPI_Lock(tmpVisRgn, NULL);
if (visrgn == NULL)
{
@ -2512,6 +2512,9 @@ IntGdiPaintRgn(
return FALSE;
}
if (dc->prgnRao)
IntGdiCombineRgn(visrgn, visrgn, dc->prgnRao, RGN_AND);
ClipRegion = IntEngCreateClipRegion(visrgn->rdh.nCount,
visrgn->Buffer,
&visrgn->rdh.rcBound );
@ -2535,6 +2538,29 @@ IntGdiPaintRgn(
return bRet;
}
BOOL
FASTCALL
REGION_PtInRegion(
PREGION prgn,
INT X,
INT Y)
{
ULONG i;
PRECT r;
if (prgn->rdh.nCount > 0 && INRECT(prgn->rdh.rcBound, X, Y))
{
r = prgn->Buffer;
for (i = 0; i < prgn->rdh.nCount; i++)
{
if (INRECT(r[i], X, Y))
return TRUE;
}
}
return FALSE;
}
BOOL
FASTCALL
REGION_RectInRegion(
@ -3861,27 +3887,19 @@ NtGdiPtInRegion(
INT Y
)
{
PROSRGNDATA rgn;
ULONG i;
PRECTL r;
PREGION prgn;
BOOL ret;
if (!(rgn = RGNOBJAPI_Lock(hRgn, NULL) ) )
if (!(prgn = RGNOBJAPI_Lock(hRgn, NULL) ) )
return FALSE;
if (rgn->rdh.nCount > 0 && INRECT(rgn->rdh.rcBound, X, Y))
{
r = rgn->Buffer;
for (i = 0; i < rgn->rdh.nCount; i++)
{
if (INRECT(*r, X, Y))
{
RGNOBJAPI_Unlock(rgn);
return TRUE;
}
r++;
}
}
RGNOBJAPI_Unlock(rgn);
ret = REGION_PtInRegion(prgn, X, Y);
RGNOBJAPI_Unlock(prgn);
return ret;
RGNOBJAPI_Unlock(prgn);
return FALSE;
}

View file

@ -27,6 +27,7 @@ PROSRGNDATA FASTCALL REGION_AllocUserRgnWithHandle(INT n);
VOID FASTCALL REGION_UnionRectWithRgn(ROSRGNDATA *rgn, const RECTL *rect);
INT FASTCALL REGION_GetRgnBox(PROSRGNDATA Rgn, RECTL *pRect);
BOOL FASTCALL REGION_RectInRegion(PROSRGNDATA Rgn, const RECTL *rc);
BOOL FASTCALL REGION_PtInRegion(PREGION, INT, INT);
BOOL FASTCALL REGION_CropAndOffsetRegion(PROSRGNDATA rgnDst, PROSRGNDATA rgnSrc, const RECTL *rect, const POINT *off);
VOID FASTCALL REGION_SetRectRgn(PROSRGNDATA pRgn, INT LeftRect, INT TopRect, INT RightRect, INT BottomRect);
VOID NTAPI REGION_vCleanup(PVOID ObjectBody);

View file

@ -1287,7 +1287,7 @@ UserDrawIconEx(
RECTL_vOffsetRect(&rcDest, pdc->ptlDCOrig.x, pdc->ptlDCOrig.y);
/* Prepare the underlying surface */
DC_vPrepareDCsForBlit(pdc, rcDest, NULL, rcDest);
DC_vPrepareDCsForBlit(pdc, &rcDest, NULL, NULL);
/* Get the clip object */
pdcClipObj = pdc->rosdc.CombinedClip;
@ -1472,7 +1472,7 @@ done:
RECTL_vOffsetRect(&rcDest, pdc->ptlDCOrig.x, pdc->ptlDCOrig.y);
/* Prepare the underlying surface */
DC_vPrepareDCsForBlit(pdc, rcDest, NULL, rcDest);
DC_vPrepareDCsForBlit(pdc, &rcDest, NULL, NULL);
/* Get the clip object */
pdcClipObj = pdc->rosdc.CombinedClip;

View file

@ -1195,7 +1195,7 @@ UserDrawIconEx(
RECTL_vOffsetRect(&rcDest, pdc->ptlDCOrig.x, pdc->ptlDCOrig.y);
/* Prepare the underlying surface */
DC_vPrepareDCsForBlit(pdc, rcDest, NULL, rcDest);
DC_vPrepareDCsForBlit(pdc, &rcDest, NULL, NULL);
/* We now have our destination surface and rectangle */
psurfDest = pdc->dclevel.pSurface;

View file

@ -51,3 +51,5 @@ void FASTCALL DceFreeClassDCE(HDC);
HWND FASTCALL UserGethWnd(HDC,PWNDOBJ*);
void FASTCALL DceFreeWindowDCE(PWND);
void FASTCALL DceFreeThreadDCE(PTHREADINFO);
VOID FASTCALL DceUpdateVisRgn(DCE *Dce, PWND Window, ULONG Flags);
DCE* FASTCALL DceGetDceFromDC(HDC hdc);

View file

@ -46,21 +46,47 @@ DceCreateDisplayDC(VOID)
return IntGdiCreateDC(&DriverName, NULL, NULL, NULL, FALSE);
}
/* Returns the DCE pointer from the HDC handle */
DCE*
FASTCALL
DceGetDceFromDC(HDC hdc)
{
LIST_ENTRY* Entry = LEDce.Flink;
DCE* dce;
while (Entry != &LEDce)
{
dce = CONTAINING_RECORD(Entry, DCE, List);
if (dce->hDC == hdc)
return dce;
Entry = Entry->Flink;
}
return NULL;
}
static
HRGN FASTCALL
PREGION FASTCALL
DceGetVisRgn(PWND Window, ULONG Flags, HWND hWndChild, ULONG CFlags)
{
HRGN VisRgn;
PREGION RetRgn;
HRGN hVisRgn;
hVisRgn = VIS_ComputeVisibleRegion( Window,
0 == (Flags & DCX_WINDOW),
0 != (Flags & DCX_CLIPCHILDREN),
0 != (Flags & DCX_CLIPSIBLINGS));
VisRgn = VIS_ComputeVisibleRegion( Window,
0 == (Flags & DCX_WINDOW),
0 != (Flags & DCX_CLIPCHILDREN),
0 != (Flags & DCX_CLIPSIBLINGS));
RetRgn = IntSysCreateRectpRgn(0, 0, 0, 0);
if (VisRgn == NULL)
VisRgn = IntSysCreateRectRgn(0, 0, 0, 0);
if (hVisRgn != NULL)
{
PREGION VisRgn = REGION_LockRgn(hVisRgn);
IntGdiCombineRgn(RetRgn, VisRgn, NULL, RGN_COPY);
REGION_UnlockRgn(VisRgn);
GreDeleteObject(hVisRgn);
}
return VisRgn;
return RetRgn;
}
PDCE FASTCALL
@ -150,6 +176,7 @@ DceSetDrawable( PWND Window OPTIONAL,
dc->ptlDCOrig.y = Window->rcClient.top;
}
}
dc->fs |= DC_FLAG_DIRTY_RAO;
DC_UnlockDc(dc);
}
@ -175,10 +202,11 @@ DceDeleteClipRgn(DCE* Dce)
IntGdiSetHookFlags(Dce->hDC, DCHF_INVALIDATEVISRGN);
}
static VOID FASTCALL
VOID
FASTCALL
DceUpdateVisRgn(DCE *Dce, PWND Window, ULONG Flags)
{
HANDLE hRgnVisible = NULL;
PREGION RgnVisible = NULL;
ULONG DcxFlags;
PWND DesktopWindow;
@ -189,7 +217,7 @@ DceUpdateVisRgn(DCE *Dce, PWND Window, ULONG Flags)
Parent = Window->spwndParent;
if(!Parent)
{
hRgnVisible = NULL;
RgnVisible = NULL;
goto noparent;
}
@ -202,23 +230,23 @@ DceUpdateVisRgn(DCE *Dce, PWND Window, ULONG Flags)
{
DcxFlags = Flags & ~(DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN | DCX_WINDOW);
}
hRgnVisible = DceGetVisRgn(Parent, DcxFlags, Window->head.h, Flags);
RgnVisible = DceGetVisRgn(Parent, DcxFlags, Window->head.h, Flags);
}
else if (Window == NULL)
{
DesktopWindow = UserGetWindowObject(IntGetDesktopWindow());
if (NULL != DesktopWindow)
{
hRgnVisible = IntSysCreateRectRgnIndirect(&DesktopWindow->rcWindow);
RgnVisible = IntSysCreateRectpRgnIndirect(&DesktopWindow->rcWindow);
}
else
{
hRgnVisible = NULL;
RgnVisible = NULL;
}
}
else
{
hRgnVisible = DceGetVisRgn(Window, Flags, 0, 0);
RgnVisible = DceGetVisRgn(Window, Flags, 0, 0);
}
noparent:
@ -226,33 +254,37 @@ noparent:
{
if(Dce->hrgnClip != NULL)
{
NtGdiCombineRgn(hRgnVisible, hRgnVisible, Dce->hrgnClip, RGN_AND);
PREGION RgnClip = REGION_LockRgn(Dce->hrgnClip);
IntGdiCombineRgn(RgnVisible, RgnVisible, RgnClip, RGN_AND);
REGION_UnlockRgn(RgnClip);
}
else
{
if(hRgnVisible != NULL)
if(RgnVisible != NULL)
{
GreDeleteObject(hRgnVisible);
REGION_Delete(RgnVisible);
}
hRgnVisible = IntSysCreateRectRgn(0, 0, 0, 0);
RgnVisible = IntSysCreateRectpRgn(0, 0, 0, 0);
}
}
else if (Flags & DCX_EXCLUDERGN && Dce->hrgnClip != NULL)
else if ((Flags & DCX_EXCLUDERGN) && Dce->hrgnClip != NULL)
{
NtGdiCombineRgn(hRgnVisible, hRgnVisible, Dce->hrgnClip, RGN_DIFF);
PREGION RgnClip = REGION_LockRgn(Dce->hrgnClip);
IntGdiCombineRgn(RgnVisible, RgnVisible, RgnClip, RGN_DIFF);
REGION_UnlockRgn(RgnClip);
}
Dce->DCXFlags &= ~DCX_DCEDIRTY;
GdiSelectVisRgn(Dce->hDC, hRgnVisible);
GdiSelectVisRgn(Dce->hDC, RgnVisible);
if (VerifyWnd(Window)) // Window maybe dead by this time before finishing the DCE release.
{
IntEngWindowChanged(Window, WOC_RGN_CLIENT);
}
if (hRgnVisible != NULL)
if (RgnVisible != NULL)
{
GreDeleteObject(hRgnVisible);
REGION_Delete(RgnVisible);
}
}
@ -889,10 +921,10 @@ DceResetActiveDCEs(PWND Window)
dc->ptlDCOrig.y = CurrentWindow->rcClient.top;
}
if (NULL != dc->rosdc.hClipRgn)
if (NULL != dc->dclevel.prgnClip)
{
NtGdiOffsetRgn(dc->rosdc.hClipRgn, DeltaX, DeltaY);
CLIPPING_UpdateGCRegion(dc);
IntGdiOffsetRgn(dc->dclevel.prgnClip, DeltaX, DeltaY);
dc->fs |= DC_FLAG_DIRTY_RAO;
}
if (NULL != pDCE->hrgnClip)
{