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

View file

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

View file

@ -11,161 +11,99 @@
#define NDEBUG #define NDEBUG
#include <debug.h> #include <debug.h>
int FASTCALL VOID
CLIPPING_UpdateGCRegion(DC* Dc) FASTCALL
GdiSelectVisRgn(
HDC hdc,
PREGION prgn)
{ {
PROSRGNDATA CombinedRegion; DC *dc;
//HRGN hRgnVis;
PREGION prgnClip, prgnGCClip;
/* Would prefer this, but the rest of the code sucks... */ if (!(dc = DC_LockDc(hdc)))
//ASSERT(Dc->rosdc.hGCClipRgn);
//ASSERT(Dc->rosdc.hClipRgn);
ASSERT(Dc->prgnVis);
//hRgnVis = Dc->prgnVis->BaseObject.hHmgr;
if (Dc->rosdc.hGCClipRgn == NULL)
Dc->rosdc.hGCClipRgn = IntSysCreateRectRgn(0, 0, 0, 0);
prgnGCClip = REGION_LockRgn(Dc->rosdc.hGCClipRgn);
ASSERT(prgnGCClip);
if (Dc->rosdc.hClipRgn == NULL)
IntGdiCombineRgn(prgnGCClip, Dc->prgnVis, NULL, RGN_COPY);
else
{ {
prgnClip = REGION_LockRgn(Dc->rosdc.hClipRgn); // FIXME: Locking order, ugh! EngSetLastError(ERROR_INVALID_HANDLE);
IntGdiCombineRgn(prgnGCClip, Dc->prgnVis, prgnClip, RGN_AND); return;
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) dc->fs |= DC_FLAG_DIRTY_RAO;
IntEngDeleteClipRegion(Dc->rosdc.CombinedClip);
Dc->rosdc.CombinedClip = CombinedClip ; ASSERT(dc->prgnVis != NULL);
} ASSERT(prgn != NULL);
return NtGdiOffsetRgn(Dc->rosdc.hGCClipRgn, -Dc->ptlDCOrig.x, -Dc->ptlDCOrig.y); IntGdiCombineRgn(dc->prgnVis, prgn, NULL, RGN_COPY);
IntGdiOffsetRgn(dc->prgnVis, -dc->ptlDCOrig.x, -dc->ptlDCOrig.y);
DC_UnlockDc(dc);
} }
INT FASTCALL
GdiSelectVisRgn(HDC hdc, HRGN hrgn) int
FASTCALL
IntGdiExtSelectClipRgn(
PDC dc,
PREGION prgn,
int fnMode)
{
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 (!dc->dclevel.prgnClip)
{
RECTL rect;
REGION_GetRgnBox(dc->prgnVis, &rect);
dc->dclevel.prgnClip = IntSysCreateRectpRgnIndirect(&rect);
}
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 retval; int retval;
DC *dc; DC *dc;
PREGION prgn; 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 )
{
IntGdiOffsetRgn(dc->prgnVis, -dc->ptlDCOrig.x, -dc->ptlDCOrig.y);
CLIPPING_UpdateGCRegion(dc);
}
DC_UnlockDc(dc);
return retval;
}
int FASTCALL GdiExtSelectClipRgn(PDC dc,
HRGN hrgn,
int fnMode)
{
// dc->fs &= ~DC_FLAG_DIRTY_RAO;
if (!hrgn)
{
if (fnMode == RGN_COPY)
{
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)
{
REGION_GetRgnBox(dc->prgnVis, &rect);
dc->rosdc.hClipRgn = IntSysCreateRectRgnIndirect(&rect);
}
else
{
dc->rosdc.hClipRgn = IntSysCreateRectRgn(0, 0, 0, 0);
}
}
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);
}
int APIENTRY NtGdiExtSelectClipRgn(HDC hDC,
HRGN hrgn,
int fnMode)
{
int retval;
DC *dc;
if (!(dc = DC_LockDc(hDC))) if (!(dc = DC_LockDc(hDC)))
{ {
EngSetLastError(ERROR_INVALID_HANDLE); EngSetLastError(ERROR_INVALID_HANDLE);
return ERROR; return ERROR;
} }
retval = GdiExtSelectClipRgn ( dc, hrgn, fnMode ); prgn = REGION_LockRgn(hrgn);
/* IntGdiExtSelectClipRgn takes care of checking for NULL region */
retval = IntGdiExtSelectClipRgn(dc, prgn, fnMode);
if (prgn)
REGION_UnlockRgn(prgn);
DC_UnlockDc(dc); DC_UnlockDc(dc);
return retval; return retval;
@ -177,7 +115,6 @@ GdiGetClipBox(HDC hDC, PRECTL rc)
INT retval; INT retval;
PDC dc; PDC dc;
PROSRGNDATA pRgnNew, pRgn = NULL; PROSRGNDATA pRgnNew, pRgn = NULL;
BOOL Unlock = FALSE; // Small HACK
if (!(dc = DC_LockDc(hDC))) if (!(dc = DC_LockDc(hDC)))
{ {
@ -193,10 +130,9 @@ GdiGetClipBox(HDC hDC, PRECTL rc)
{ {
pRgn = dc->dclevel.prgnMeta; pRgn = dc->dclevel.prgnMeta;
} }
else if (dc->rosdc.hClipRgn) else if (dc->dclevel.prgnClip) // CLIPRGN
{ {
Unlock = TRUE ; pRgn = dc->dclevel.prgnClip;
pRgn = REGION_LockRgn(dc->rosdc.hClipRgn); // CLIPRGN
} }
if (pRgn) if (pRgn)
@ -206,7 +142,6 @@ GdiGetClipBox(HDC hDC, PRECTL rc)
if (!pRgnNew) if (!pRgnNew)
{ {
DC_UnlockDc(dc); DC_UnlockDc(dc);
if(Unlock) REGION_UnlockRgn(pRgn);
return ERROR; return ERROR;
} }
@ -217,12 +152,11 @@ GdiGetClipBox(HDC hDC, PRECTL rc)
REGION_Delete(pRgnNew); REGION_Delete(pRgnNew);
DC_UnlockDc(dc); DC_UnlockDc(dc);
if(Unlock) REGION_UnlockRgn(pRgn);
return retval; return retval;
} }
retval = REGION_GetRgnBox(dc->prgnVis, rc); retval = REGION_GetRgnBox(dc->prgnVis, rc);
IntDPtoLP(dc, (LPPOINT)rc, 2);
DC_UnlockDc(dc); DC_UnlockDc(dc);
return retval; return retval;
@ -267,7 +201,7 @@ int APIENTRY NtGdiExcludeClipRect(HDC hDC,
{ {
INT Result; INT Result;
RECTL Rect; RECTL Rect;
PREGION prgnNew, prgnClip; PREGION prgnNew;
PDC dc = DC_LockDc(hDC); PDC dc = DC_LockDc(hDC);
if (!dc) if (!dc)
@ -290,24 +224,20 @@ int APIENTRY NtGdiExcludeClipRect(HDC hDC,
} }
else else
{ {
if (!dc->rosdc.hClipRgn) if (!dc->dclevel.prgnClip)
{ {
dc->rosdc.hClipRgn = IntSysCreateRectRgn(0, 0, 0, 0); dc->dclevel.prgnClip = IntSysCreateRectpRgn(0, 0, 0, 0);
prgnClip = REGION_LockRgn(dc->rosdc.hClipRgn); IntGdiCombineRgn(dc->dclevel.prgnClip, dc->prgnVis, prgnNew, RGN_DIFF);
IntGdiCombineRgn(prgnClip, dc->prgnVis, prgnNew, RGN_DIFF);
REGION_UnlockRgn(prgnClip);
Result = SIMPLEREGION; Result = SIMPLEREGION;
} }
else else
{ {
prgnClip = REGION_LockRgn(dc->rosdc.hClipRgn); Result = IntGdiCombineRgn(dc->dclevel.prgnClip, dc->dclevel.prgnClip, prgnNew, RGN_DIFF);
Result = IntGdiCombineRgn(prgnClip, prgnClip, prgnNew, RGN_DIFF);
REGION_UnlockRgn(prgnClip);
} }
REGION_Delete(prgnNew); REGION_Delete(prgnNew);
} }
if (Result != ERROR) if (Result != ERROR)
CLIPPING_UpdateGCRegion(dc); dc->fs |= DC_FLAG_DIRTY_RAO;
DC_UnlockDc(dc); DC_UnlockDc(dc);
@ -322,7 +252,7 @@ int APIENTRY NtGdiIntersectClipRect(HDC hDC,
{ {
INT Result; INT Result;
RECTL Rect; RECTL Rect;
HRGN NewRgn; PREGION pNewRgn;
PDC dc = DC_LockDc(hDC); PDC dc = DC_LockDc(hDC);
DPRINT("NtGdiIntersectClipRect(%p, %d,%d-%d,%d)\n", DPRINT("NtGdiIntersectClipRect(%p, %d,%d-%d,%d)\n",
@ -341,23 +271,23 @@ int APIENTRY NtGdiIntersectClipRect(HDC hDC,
IntLPtoDP(dc, (LPPOINT)&Rect, 2); IntLPtoDP(dc, (LPPOINT)&Rect, 2);
NewRgn = IntSysCreateRectRgnIndirect(&Rect); pNewRgn = IntSysCreateRectpRgnIndirect(&Rect);
if (!NewRgn) if (!pNewRgn)
{ {
Result = ERROR; Result = ERROR;
} }
else if (!dc->rosdc.hClipRgn) else if (!dc->dclevel.prgnClip)
{ {
dc->rosdc.hClipRgn = NewRgn; dc->dclevel.prgnClip = pNewRgn;
Result = SIMPLEREGION; Result = SIMPLEREGION;
} }
else else
{ {
Result = NtGdiCombineRgn(dc->rosdc.hClipRgn, dc->rosdc.hClipRgn, NewRgn, RGN_AND); Result = IntGdiCombineRgn(dc->dclevel.prgnClip, dc->dclevel.prgnClip, pNewRgn, RGN_AND);
GreDeleteObject(NewRgn); REGION_Delete(pNewRgn);
} }
if (Result != ERROR) if (Result != ERROR)
CLIPPING_UpdateGCRegion(dc); dc->fs |= DC_FLAG_DIRTY_RAO;
DC_UnlockDc(dc); DC_UnlockDc(dc);
@ -377,12 +307,12 @@ int APIENTRY NtGdiOffsetClipRgn(HDC hDC,
return ERROR; return ERROR;
} }
if(dc->rosdc.hClipRgn != NULL) if(dc->dclevel.prgnClip != NULL)
{ {
Result = NtGdiOffsetRgn(dc->rosdc.hClipRgn, Result = IntGdiOffsetRgn(dc->dclevel.prgnClip,
XOffset, XOffset,
YOffset); YOffset);
CLIPPING_UpdateGCRegion(dc); dc->fs |= DC_FLAG_DIRTY_RAO;
} }
else else
{ {
@ -397,8 +327,8 @@ BOOL APIENTRY NtGdiPtVisible(HDC hDC,
int X, int X,
int Y) int Y)
{ {
HRGN rgn; BOOL ret = FALSE;
DC *dc; PDC dc;
if(!(dc = DC_LockDc(hDC))) if(!(dc = DC_LockDc(hDC)))
{ {
@ -406,17 +336,25 @@ BOOL APIENTRY NtGdiPtVisible(HDC hDC,
return FALSE; return FALSE;
} }
rgn = dc->rosdc.hGCClipRgn; if (dc->prgnRao)
{
POINT pt = {X, Y};
IntLPtoDP(dc, &pt, 1);
ret = REGION_PtInRegion(dc->prgnRao, pt.x, pt.y);
}
DC_UnlockDc(dc); DC_UnlockDc(dc);
return (rgn ? NtGdiPtInRegion(rgn, X, Y) : FALSE); return ret;
} }
BOOL APIENTRY NtGdiRectVisible(HDC hDC, BOOL
APIENTRY
NtGdiRectVisible(
HDC hDC,
LPRECT UnsafeRect) LPRECT UnsafeRect)
{ {
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS;
PROSRGNDATA Rgn;
PDC dc = DC_LockDc(hDC); PDC dc = DC_LockDc(hDC);
BOOL Result = FALSE; BOOL Result = FALSE;
RECTL Rect; RECTL Rect;
@ -447,14 +385,13 @@ BOOL APIENTRY NtGdiRectVisible(HDC hDC,
return FALSE; return FALSE;
} }
if (dc->rosdc.hGCClipRgn) if (dc->fs & DC_FLAG_DIRTY_RAO)
{ CLIPPING_UpdateGCRegion(dc);
if((Rgn = (PROSRGNDATA)RGNOBJAPI_Lock(dc->rosdc.hGCClipRgn, NULL)))
if (dc->prgnRao)
{ {
IntLPtoDP(dc, (LPPOINT)&Rect, 2); IntLPtoDP(dc, (LPPOINT)&Rect, 2);
Result = REGION_RectInRegion(Rgn, &Rect); Result = REGION_RectInRegion(dc->prgnRao, &Rect);
RGNOBJAPI_Unlock(Rgn);
}
} }
DC_UnlockDc(dc); DC_UnlockDc(dc);
@ -466,38 +403,18 @@ FASTCALL
IntGdiSetMetaRgn(PDC pDC) IntGdiSetMetaRgn(PDC pDC)
{ {
INT Ret = ERROR; INT Ret = ERROR;
PROSRGNDATA TempRgn;
if ( pDC->dclevel.prgnMeta ) if ( pDC->dclevel.prgnMeta )
{ {
if ( pDC->dclevel.prgnClip ) if ( pDC->dclevel.prgnClip )
{ {
TempRgn = IntSysCreateRectpRgn(0,0,0,0); Ret = IntGdiCombineRgn(pDC->dclevel.prgnMeta, pDC->dclevel.prgnMeta, pDC->dclevel.prgnClip, RGN_AND);
if (TempRgn) if (Ret != ERROR)
{ {
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); REGION_Delete(pDC->dclevel.prgnClip);
pDC->dclevel.prgnClip = NULL; pDC->dclevel.prgnClip = NULL;
IntGdiReleaseRaoRgn(pDC); IntGdiReleaseRaoRgn(pDC);
} }
else
REGION_Delete(TempRgn);
}
} }
else else
Ret = REGION_Complexity(pDC->dclevel.prgnMeta); Ret = REGION_Complexity(pDC->dclevel.prgnMeta);
@ -513,6 +430,10 @@ IntGdiSetMetaRgn(PDC pDC)
else else
Ret = SIMPLEREGION; Ret = SIMPLEREGION;
} }
if (Ret != ERROR)
pDC->fs |= DC_FLAG_DIRTY_RAO;
return Ret; return Ret;
} }
@ -533,62 +454,71 @@ int APIENTRY NtGdiSetMetaRgn(HDC hDC)
return Ret; return Ret;
} }
INT FASTCALL VOID
NEW_CLIPPING_UpdateGCRegion(PDC pDC) FASTCALL
CLIPPING_UpdateGCRegion(PDC pDC)
{ {
CLIPOBJ * co; CLIPOBJ * co;
/* Must have VisRgn set to a valid state! */ /* Must have VisRgn set to a valid state! */
ASSERT (pDC->prgnVis); ASSERT (pDC->prgnVis);
// FIXME: this seems to be broken!
if (pDC->prgnAPI) if (pDC->prgnAPI)
{ {
REGION_Delete(pDC->prgnAPI); REGION_Delete(pDC->prgnAPI);
pDC->prgnAPI = IntSysCreateRectpRgn(0,0,0,0); pDC->prgnAPI = NULL;
} }
if (pDC->prgnRao) if (pDC->prgnRao)
{
REGION_Delete(pDC->prgnRao); REGION_Delete(pDC->prgnRao);
pDC->prgnRao = IntSysCreateRectpRgn(0,0,0,0); pDC->prgnRao = IntSysCreateRectpRgn(0,0,0,0);
}
if (!pDC->prgnRao) ASSERT(pDC->prgnRao);
{
return ERROR;
}
if (pDC->dclevel.prgnMeta && pDC->dclevel.prgnClip) if (pDC->dclevel.prgnMeta || pDC->dclevel.prgnClip)
{ {
IntGdiCombineRgn( pDC->prgnAPI, 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.prgnClip,
pDC->dclevel.prgnMeta, pDC->dclevel.prgnMeta,
RGN_AND); RGN_AND);
} }
}
if (pDC->prgnAPI)
{
IntGdiCombineRgn(pDC->prgnRao,
pDC->prgnVis,
pDC->prgnAPI,
RGN_AND);
}
else else
{ {
if (pDC->dclevel.prgnClip) IntGdiCombineRgn(pDC->prgnRao,
{ pDC->prgnVis,
IntGdiCombineRgn( pDC->prgnAPI,
pDC->dclevel.prgnClip,
NULL, NULL,
RGN_COPY); RGN_COPY);
} }
else if (pDC->dclevel.prgnMeta)
{
IntGdiCombineRgn( pDC->prgnAPI,
pDC->dclevel.prgnMeta,
NULL,
RGN_COPY);
}
}
IntGdiCombineRgn( pDC->prgnRao,
pDC->prgnVis, IntGdiOffsetRgn(pDC->prgnRao, pDC->ptlDCOrig.x, pDC->ptlDCOrig.y);
pDC->prgnAPI,
RGN_AND);
RtlCopyMemory(&pDC->erclClip, RtlCopyMemory(&pDC->erclClip,
&pDC->prgnRao->rdh.rcBound, &pDC->prgnRao->rdh.rcBound,
@ -596,8 +526,6 @@ NEW_CLIPPING_UpdateGCRegion(PDC pDC)
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 // pDC->co should be used. Example, CLIPOBJ_cEnumStart uses XCLIPOBJ to build
// the rects from region objects rects in pClipRgn->Buffer. // the rects from region objects rects in pClipRgn->Buffer.
// With pDC->co.pClipRgn->Buffer, // With pDC->co.pClipRgn->Buffer,
@ -614,7 +542,7 @@ NEW_CLIPPING_UpdateGCRegion(PDC pDC)
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 */ /* EOF */

View file

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

View file

@ -48,9 +48,6 @@ typedef enum _DCTYPE
typedef struct _ROS_DC_INFO typedef struct _ROS_DC_INFO
{ {
HRGN hClipRgn; /* Clip region (may be 0) */
HRGN hGCClipRgn; /* GC clip region (ClipRgn AND VisRgn) */
CLIPOBJ *CombinedClip; CLIPOBJ *CombinedClip;
} ROS_DC_INFO; } ROS_DC_INFO;
@ -199,9 +196,9 @@ BOOL FASTCALL IntGdiDeleteDC(HDC, BOOL);
BOOL FASTCALL DC_InvertXform(const XFORM *xformSrc, XFORM *xformDest); BOOL FASTCALL DC_InvertXform(const XFORM *xformSrc, XFORM *xformDest);
VOID FASTCALL DC_vUpdateViewportExt(PDC pdc); 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_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); VOID NTAPI DC_vRestoreDC(IN PDC pdc, INT iSaveLevel);

View file

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

View file

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

View file

@ -51,23 +51,26 @@ DC_vCopyState(PDC pdcSrc, PDC pdcDst, BOOL To)
pdcDst->dclevel.plfnt = pdcSrc->dclevel.plfnt; pdcDst->dclevel.plfnt = pdcSrc->dclevel.plfnt;
/* Get/SetDCState() don't change hVisRgn field ("Undoc. Windows" p.559). */ /* 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); REGION_Delete(pdcDst->dclevel.prgnMeta);
NtGdiCombineRgn(pdcDst->rosdc.hClipRgn, pdcSrc->rosdc.hClipRgn, 0, RGN_COPY); pdcDst->dclevel.prgnMeta = NULL;
} }
// FIXME: Handle prgnMeta! if (pdcSrc->dclevel.prgnMeta)
{
pdcDst->dclevel.prgnMeta = IntSysCreateRectpRgn(0, 0, 0, 0);
IntGdiCombineRgn(pdcDst->dclevel.prgnMeta, pdcSrc->dclevel.prgnMeta, NULL, RGN_COPY);
} }
else // Copy "!To" RestoreDC state. pdcDst->fs |= DC_FLAG_DIRTY_RAO;
{ /* The VisRectRegion field needs to be set to a valid state */
GdiExtSelectClipRgn(pdcDst, pdcSrc->rosdc.hClipRgn, RGN_COPY);
} }
} }
BOOL FASTCALL BOOL
FASTCALL
IntGdiCleanDC(HDC hDC) IntGdiCleanDC(HDC hDC)
{ {
PDC dc; PDC dc;
@ -87,6 +90,16 @@ IntGdiCleanDC(HDC hDC)
DC_vUpdateTextBrush(dc); 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); DC_UnlockDc(dc);
return TRUE; return TRUE;
@ -272,7 +285,7 @@ NtGdiSaveDC(
GDIOBJ_vSetObjectOwner(&pdcSave->BaseObject, GDI_OBJ_HMGR_PUBLIC); GDIOBJ_vSetObjectOwner(&pdcSave->BaseObject, GDI_OBJ_HMGR_PUBLIC);
/* Copy the current state */ /* Copy the current state */
DC_vCopyState(pdc, pdcSave, TRUE); DC_vCopyState(pdc, pdcSave, FALSE);
/* Only memory DC's change their surface */ /* Only memory DC's change their surface */
if (pdc->dctype == DCTYPE_MEMORY) if (pdc->dctype == DCTYPE_MEMORY)

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -27,6 +27,7 @@ PROSRGNDATA FASTCALL REGION_AllocUserRgnWithHandle(INT n);
VOID FASTCALL REGION_UnionRectWithRgn(ROSRGNDATA *rgn, const RECTL *rect); VOID FASTCALL REGION_UnionRectWithRgn(ROSRGNDATA *rgn, const RECTL *rect);
INT FASTCALL REGION_GetRgnBox(PROSRGNDATA Rgn, RECTL *pRect); INT FASTCALL REGION_GetRgnBox(PROSRGNDATA Rgn, RECTL *pRect);
BOOL FASTCALL REGION_RectInRegion(PROSRGNDATA Rgn, const RECTL *rc); 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); 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 FASTCALL REGION_SetRectRgn(PROSRGNDATA pRgn, INT LeftRect, INT TopRect, INT RightRect, INT BottomRect);
VOID NTAPI REGION_vCleanup(PVOID ObjectBody); VOID NTAPI REGION_vCleanup(PVOID ObjectBody);

View file

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

View file

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

View file

@ -51,3 +51,5 @@ void FASTCALL DceFreeClassDCE(HDC);
HWND FASTCALL UserGethWnd(HDC,PWNDOBJ*); HWND FASTCALL UserGethWnd(HDC,PWNDOBJ*);
void FASTCALL DceFreeWindowDCE(PWND); void FASTCALL DceFreeWindowDCE(PWND);
void FASTCALL DceFreeThreadDCE(PTHREADINFO); 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); 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 static
HRGN FASTCALL PREGION FASTCALL
DceGetVisRgn(PWND Window, ULONG Flags, HWND hWndChild, ULONG CFlags) DceGetVisRgn(PWND Window, ULONG Flags, HWND hWndChild, ULONG CFlags)
{ {
HRGN VisRgn; PREGION RetRgn;
HRGN hVisRgn;
VisRgn = VIS_ComputeVisibleRegion( Window, hVisRgn = VIS_ComputeVisibleRegion( Window,
0 == (Flags & DCX_WINDOW), 0 == (Flags & DCX_WINDOW),
0 != (Flags & DCX_CLIPCHILDREN), 0 != (Flags & DCX_CLIPCHILDREN),
0 != (Flags & DCX_CLIPSIBLINGS)); 0 != (Flags & DCX_CLIPSIBLINGS));
if (VisRgn == NULL) RetRgn = IntSysCreateRectpRgn(0, 0, 0, 0);
VisRgn = IntSysCreateRectRgn(0, 0, 0, 0);
return VisRgn; if (hVisRgn != NULL)
{
PREGION VisRgn = REGION_LockRgn(hVisRgn);
IntGdiCombineRgn(RetRgn, VisRgn, NULL, RGN_COPY);
REGION_UnlockRgn(VisRgn);
GreDeleteObject(hVisRgn);
}
return RetRgn;
} }
PDCE FASTCALL PDCE FASTCALL
@ -150,6 +176,7 @@ DceSetDrawable( PWND Window OPTIONAL,
dc->ptlDCOrig.y = Window->rcClient.top; dc->ptlDCOrig.y = Window->rcClient.top;
} }
} }
dc->fs |= DC_FLAG_DIRTY_RAO;
DC_UnlockDc(dc); DC_UnlockDc(dc);
} }
@ -175,10 +202,11 @@ DceDeleteClipRgn(DCE* Dce)
IntGdiSetHookFlags(Dce->hDC, DCHF_INVALIDATEVISRGN); IntGdiSetHookFlags(Dce->hDC, DCHF_INVALIDATEVISRGN);
} }
static VOID FASTCALL VOID
FASTCALL
DceUpdateVisRgn(DCE *Dce, PWND Window, ULONG Flags) DceUpdateVisRgn(DCE *Dce, PWND Window, ULONG Flags)
{ {
HANDLE hRgnVisible = NULL; PREGION RgnVisible = NULL;
ULONG DcxFlags; ULONG DcxFlags;
PWND DesktopWindow; PWND DesktopWindow;
@ -189,7 +217,7 @@ DceUpdateVisRgn(DCE *Dce, PWND Window, ULONG Flags)
Parent = Window->spwndParent; Parent = Window->spwndParent;
if(!Parent) if(!Parent)
{ {
hRgnVisible = NULL; RgnVisible = NULL;
goto noparent; goto noparent;
} }
@ -202,23 +230,23 @@ DceUpdateVisRgn(DCE *Dce, PWND Window, ULONG Flags)
{ {
DcxFlags = Flags & ~(DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN | DCX_WINDOW); 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) else if (Window == NULL)
{ {
DesktopWindow = UserGetWindowObject(IntGetDesktopWindow()); DesktopWindow = UserGetWindowObject(IntGetDesktopWindow());
if (NULL != DesktopWindow) if (NULL != DesktopWindow)
{ {
hRgnVisible = IntSysCreateRectRgnIndirect(&DesktopWindow->rcWindow); RgnVisible = IntSysCreateRectpRgnIndirect(&DesktopWindow->rcWindow);
} }
else else
{ {
hRgnVisible = NULL; RgnVisible = NULL;
} }
} }
else else
{ {
hRgnVisible = DceGetVisRgn(Window, Flags, 0, 0); RgnVisible = DceGetVisRgn(Window, Flags, 0, 0);
} }
noparent: noparent:
@ -226,33 +254,37 @@ noparent:
{ {
if(Dce->hrgnClip != NULL) 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 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; 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. if (VerifyWnd(Window)) // Window maybe dead by this time before finishing the DCE release.
{ {
IntEngWindowChanged(Window, WOC_RGN_CLIENT); 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; dc->ptlDCOrig.y = CurrentWindow->rcClient.top;
} }
if (NULL != dc->rosdc.hClipRgn) if (NULL != dc->dclevel.prgnClip)
{ {
NtGdiOffsetRgn(dc->rosdc.hClipRgn, DeltaX, DeltaY); IntGdiOffsetRgn(dc->dclevel.prgnClip, DeltaX, DeltaY);
CLIPPING_UpdateGCRegion(dc); dc->fs |= DC_FLAG_DIRTY_RAO;
} }
if (NULL != pDCE->hrgnClip) if (NULL != pDCE->hrgnClip)
{ {