зеркало из https://github.com/mozilla/gecko-dev.git
added support of irregular damage regions to viewmanager.
This commit is contained in:
Родитель
0f5c5f61ce
Коммит
33a0103e30
|
@ -66,6 +66,10 @@ void nsRegionUnix :: Subtract(const nsIRegion &aRegion)
|
|||
{
|
||||
}
|
||||
|
||||
void nsRegionUnix :: Subtract(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight)
|
||||
{
|
||||
}
|
||||
|
||||
PRBool nsRegionUnix :: IsEmpty(void)
|
||||
{
|
||||
return PR_FALSE;
|
||||
|
|
|
@ -119,6 +119,19 @@ public:
|
|||
**/
|
||||
|
||||
virtual void Subtract(const nsIRegion &aRegion) = 0;
|
||||
|
||||
/**
|
||||
* destructively subtract a rect from this region
|
||||
*
|
||||
* @param aX xoffset of rect to subtract with region
|
||||
* @param aY yoffset of rect to subtract with region
|
||||
* @param aWidth width of rect to subtract with region
|
||||
* @param aHeight height of rect to subtract with region
|
||||
* @return void
|
||||
*
|
||||
**/
|
||||
|
||||
virtual void Subtract(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight) = 0;
|
||||
|
||||
/**
|
||||
* is this region empty? i.e. does it contain any pixels
|
||||
|
|
|
@ -69,7 +69,7 @@ void nsRegionWin :: Intersect(const nsIRegion &aRegion)
|
|||
{
|
||||
nsRegionWin *pRegion = (nsRegionWin *)&aRegion;
|
||||
|
||||
mRegionType = ::CombineRgn(mRegion, pRegion->mRegion, mRegion, RGN_AND);
|
||||
mRegionType = ::CombineRgn(mRegion, mRegion, pRegion->mRegion, RGN_AND);
|
||||
}
|
||||
|
||||
void nsRegionWin :: Intersect(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight)
|
||||
|
@ -77,7 +77,7 @@ void nsRegionWin :: Intersect(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aH
|
|||
HRGN tRegion;
|
||||
|
||||
tRegion = ::CreateRectRgn(aX, aY, aX + aWidth, aY + aHeight);
|
||||
mRegionType = ::CombineRgn(mRegion, tRegion, mRegion, RGN_AND);
|
||||
mRegionType = ::CombineRgn(mRegion, mRegion, tRegion, RGN_AND);
|
||||
|
||||
::DeleteObject(tRegion);
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ void nsRegionWin :: Union(const nsIRegion &aRegion)
|
|||
{
|
||||
nsRegionWin *pRegion = (nsRegionWin *)&aRegion;
|
||||
|
||||
mRegionType = ::CombineRgn(mRegion, pRegion->mRegion, mRegion, RGN_OR);
|
||||
mRegionType = ::CombineRgn(mRegion, mRegion, pRegion->mRegion, RGN_OR);
|
||||
}
|
||||
|
||||
void nsRegionWin :: Union(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight)
|
||||
|
@ -94,7 +94,7 @@ void nsRegionWin :: Union(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeigh
|
|||
HRGN tRegion;
|
||||
|
||||
tRegion = ::CreateRectRgn(aX, aY, aX + aWidth, aY + aHeight);
|
||||
mRegionType = ::CombineRgn(mRegion, tRegion, mRegion, RGN_OR);
|
||||
mRegionType = ::CombineRgn(mRegion, mRegion, tRegion, RGN_OR);
|
||||
|
||||
::DeleteObject(tRegion);
|
||||
}
|
||||
|
@ -106,6 +106,16 @@ void nsRegionWin :: Subtract(const nsIRegion &aRegion)
|
|||
mRegionType = ::CombineRgn(mRegion, mRegion, pRegion->mRegion, RGN_DIFF);
|
||||
}
|
||||
|
||||
void nsRegionWin :: Subtract(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight)
|
||||
{
|
||||
HRGN tRegion;
|
||||
|
||||
tRegion = ::CreateRectRgn(aX, aY, aX + aWidth, aY + aHeight);
|
||||
mRegionType = ::CombineRgn(mRegion, mRegion, tRegion, RGN_DIFF);
|
||||
|
||||
::DeleteObject(tRegion);
|
||||
}
|
||||
|
||||
PRBool nsRegionWin :: IsEmpty(void)
|
||||
{
|
||||
return (mRegionType == NULLREGION) ? PR_TRUE : PR_FALSE;
|
||||
|
|
|
@ -38,6 +38,7 @@ public:
|
|||
virtual void Union(const nsIRegion &aRegion);
|
||||
virtual void Union(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight);
|
||||
virtual void Subtract(const nsIRegion &aRegion);
|
||||
virtual void Subtract(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight);
|
||||
virtual PRBool IsEmpty(void);
|
||||
virtual PRBool IsEqual(const nsIRegion &aRegion);
|
||||
virtual void GetBoundingBox(PRInt32 *aX, PRInt32 *aY, PRInt32 *aWidth, PRInt32 *aHeight);
|
||||
|
|
|
@ -475,12 +475,33 @@ void nsRenderingContextWin :: SetClipRegion(const nsIRegion& aRegion, nsClipComb
|
|||
{
|
||||
nsRegionWin *pRegion = (nsRegionWin *)&aRegion;
|
||||
HRGN hrgn = pRegion->GetHRGN();
|
||||
int cmode;
|
||||
|
||||
switch (aCombine)
|
||||
{
|
||||
case nsClipCombine_kIntersect:
|
||||
cmode = RGN_AND;
|
||||
break;
|
||||
|
||||
case nsClipCombine_kUnion:
|
||||
cmode = RGN_OR;
|
||||
break;
|
||||
|
||||
case nsClipCombine_kSubtract:
|
||||
cmode = RGN_DIFF;
|
||||
break;
|
||||
|
||||
default:
|
||||
case nsClipCombine_kReplace:
|
||||
cmode = RGN_COPY;
|
||||
break;
|
||||
}
|
||||
|
||||
if (NULL != hrgn)
|
||||
{
|
||||
mStates->mFlags &= ~FLAG_LOCAL_CLIP_VALID;
|
||||
PushClipState();
|
||||
::SelectClipRgn(mDC, hrgn);
|
||||
::ExtSelectClipRgn(mDC, hrgn, cmode);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -134,8 +134,8 @@ public:
|
|||
* @param region nsIRegion to be updated
|
||||
* @param aUpdateFlags see bottom of nsIViewManager.h for description
|
||||
*/
|
||||
virtual void Refresh(nsIRenderingContext *aContext, nsIRegion *region,
|
||||
PRUint32 aUpdateFlags) = 0;
|
||||
virtual void Refresh(nsIView *aView, nsIRenderingContext *aContext,
|
||||
nsIRegion *region, PRUint32 aUpdateFlags) = 0;
|
||||
|
||||
/**
|
||||
* Called to refresh an area of the root window. Often called in
|
||||
|
@ -352,5 +352,7 @@ public:
|
|||
#define NS_VMREFRESH_SCREEN_RECT 0x0002
|
||||
//update view now?
|
||||
#define NS_VMREFRESH_IMMEDIATE 0x0004
|
||||
//prevent "sync painting"
|
||||
#define NS_VMREFRESH_NO_SYNC 0x0008
|
||||
|
||||
#endif // nsIViewManager_h___
|
||||
|
|
|
@ -86,10 +86,7 @@ nsEventStatus PR_CALLBACK HandleEvent(nsGUIEvent *aEvent)
|
|||
nsRect vrect, trect = *((nsPaintEvent*)aEvent)->rect;
|
||||
nsIDeviceContext *dx = px->GetDeviceContext();
|
||||
|
||||
trect.x = NS_TO_INT_ROUND(trect.x * convert);
|
||||
trect.y = NS_TO_INT_ROUND(trect.y * convert);
|
||||
trect.width = NS_TO_INT_ROUND(trect.width * convert);
|
||||
trect.height = NS_TO_INT_ROUND(trect.height * convert);
|
||||
trect *= convert;
|
||||
|
||||
//see if the paint region is greater than .75 the area of our root view.
|
||||
//if so, enable double buffered painting.
|
||||
|
|
|
@ -24,11 +24,14 @@
|
|||
#include "nsIDeviceContext.h"
|
||||
#include "nsGfxCIID.h"
|
||||
#include "nsIScrollableView.h"
|
||||
#include "nsIRegion.h"
|
||||
|
||||
static const PRBool gsDebug = PR_FALSE;
|
||||
|
||||
#define UPDATE_QUANTUM 1000 / 40
|
||||
|
||||
//#define USE_DIRTY_RECT
|
||||
|
||||
static void vm_timer_callback(nsITimer *aTimer, void *aClosure)
|
||||
{
|
||||
nsViewManager *vm = (nsViewManager *)aClosure;
|
||||
|
@ -58,6 +61,7 @@ nsViewManager :: ~nsViewManager()
|
|||
|
||||
NS_IF_RELEASE(mRootWindow);
|
||||
NS_IF_RELEASE(mRootView);
|
||||
NS_IF_RELEASE(mDirtyRegion);
|
||||
|
||||
if (nsnull != mDrawingSurface)
|
||||
{
|
||||
|
@ -272,8 +276,69 @@ void nsViewManager :: ResetScrolling(void)
|
|||
}
|
||||
}
|
||||
|
||||
void nsViewManager :: Refresh(nsIRenderingContext *aContext, nsIRegion *region, PRUint32 aUpdateFlags)
|
||||
void nsViewManager :: Refresh(nsIView *aView, nsIRenderingContext *aContext, nsIRegion *region, PRUint32 aUpdateFlags)
|
||||
{
|
||||
nsRect wrect;
|
||||
nsIRenderingContext *localcx = nsnull;
|
||||
nscoord xoff, yoff;
|
||||
float scale;
|
||||
|
||||
if (nsnull == aContext)
|
||||
{
|
||||
localcx = CreateRenderingContext(*aView);
|
||||
|
||||
//couldn't get rendering context. ack.
|
||||
|
||||
if (nsnull == localcx)
|
||||
{
|
||||
NS_ASSERTION(PR_FALSE, "unable to create rendering context.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
localcx = aContext;
|
||||
|
||||
if (aUpdateFlags & NS_VMREFRESH_DOUBLE_BUFFER)
|
||||
{
|
||||
mRootWindow->GetBounds(wrect);
|
||||
nsDrawingSurface ds = GetDrawingSurface(*localcx, wrect);
|
||||
localcx->SelectOffScreenDrawingSurface(ds);
|
||||
}
|
||||
|
||||
scale = mContext->GetTwipsToPixels();
|
||||
|
||||
GetWindowOffsets(&xoff, &yoff);
|
||||
|
||||
region->Offset(NS_TO_INT_ROUND(-xoff * scale), NS_TO_INT_ROUND(-yoff * scale));
|
||||
// localcx->SetClipRegion(*region, nsClipCombine_kIntersect);
|
||||
localcx->SetClipRegion(*region, nsClipCombine_kReplace);
|
||||
region->Offset(NS_TO_INT_ROUND(xoff * scale), NS_TO_INT_ROUND(yoff * scale));
|
||||
|
||||
localcx->Translate(-xoff, -yoff);
|
||||
|
||||
nsRect trect;
|
||||
|
||||
region->GetBoundingBox(&trect.x, &trect.y, &trect.width, &trect.height);
|
||||
trect *= mContext->GetPixelsToTwips();
|
||||
|
||||
localcx->PushState();
|
||||
aView->Paint(*localcx, trect, 0);
|
||||
localcx->PopState();
|
||||
|
||||
if (aUpdateFlags & NS_VMREFRESH_DOUBLE_BUFFER)
|
||||
localcx->CopyOffScreenBits(wrect);
|
||||
|
||||
if (localcx != aContext)
|
||||
NS_RELEASE(localcx);
|
||||
|
||||
//is the dirty region the same as the region we just painted?
|
||||
|
||||
if ((region == mDirtyRegion) || region->IsEqual(*mDirtyRegion))
|
||||
ClearDirtyRegion();
|
||||
else
|
||||
mDirtyRegion->Subtract(*region);
|
||||
|
||||
mLastRefresh = PR_Now();
|
||||
}
|
||||
|
||||
void nsViewManager :: Refresh(nsIView *aView, nsIRenderingContext *aContext, nsRect *rect, PRUint32 aUpdateFlags)
|
||||
|
@ -289,10 +354,10 @@ void nsViewManager :: Refresh(nsIView *aView, nsIRenderingContext *aContext, nsR
|
|||
//couldn't get rendering context. ack.
|
||||
|
||||
if (nsnull == localcx)
|
||||
{
|
||||
printf("unable to get rc\n");
|
||||
{
|
||||
NS_ASSERTION(PR_FALSE, "unable to create rendering context.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
localcx = aContext;
|
||||
|
@ -328,6 +393,8 @@ printf("unable to get rc\n");
|
|||
if (localcx != aContext)
|
||||
NS_RELEASE(localcx);
|
||||
|
||||
#ifdef USE_DIRTY_RECT
|
||||
|
||||
nsRect updaterect = *rect;
|
||||
|
||||
//does our dirty rect intersect the rect we just painted?
|
||||
|
@ -341,13 +408,36 @@ printf("unable to get rc\n");
|
|||
ClearDirtyRegion();
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
//subtract the area we just painted from the dirty region
|
||||
|
||||
if ((nsnull != mDirtyRegion) && !mDirtyRegion->IsEmpty())
|
||||
{
|
||||
nsRect pixrect = trect;
|
||||
|
||||
pixrect *= mContext->GetTwipsToPixels();
|
||||
mDirtyRegion->Subtract(pixrect.x, pixrect.y, pixrect.width, pixrect.height);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
mLastRefresh = PR_Now();
|
||||
}
|
||||
|
||||
void nsViewManager :: Composite()
|
||||
{
|
||||
if ((nsnull != mRootView) && (mDirtyRect.IsEmpty() == PR_FALSE))
|
||||
#ifdef USE_DIRTY_RECT
|
||||
|
||||
if ((nsnull != mRootView) && !mDirtyRect.IsEmpty())
|
||||
Refresh(mRootView, nsnull, &mDirtyRect, NS_VMREFRESH_DOUBLE_BUFFER);
|
||||
|
||||
#else
|
||||
|
||||
if ((nsnull != mRootView) && (nsnull != mDirtyRegion) && !mDirtyRegion->IsEmpty())
|
||||
Refresh(mRootView, nsnull, mDirtyRegion, NS_VMREFRESH_DOUBLE_BUFFER);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void nsViewManager :: UpdateView(nsIView *aView, nsIRegion *aRegion, PRUint32 aUpdateFlags)
|
||||
|
@ -388,16 +478,28 @@ void nsViewManager :: UpdateView(nsIView *aView, const nsRect &aRect, PRUint32 a
|
|||
while (par = par->GetParent());
|
||||
}
|
||||
|
||||
#ifdef USE_DIRTY_RECT
|
||||
|
||||
if (mDirtyRect.IsEmpty())
|
||||
mDirtyRect = trect;
|
||||
else
|
||||
mDirtyRect.UnionRect(mDirtyRect, trect);
|
||||
|
||||
#else
|
||||
|
||||
AddRectToDirtyRegion(trect);
|
||||
|
||||
#endif
|
||||
|
||||
if (nsnull != mContext)
|
||||
{
|
||||
if (aUpdateFlags & NS_VMREFRESH_IMMEDIATE)
|
||||
#ifdef USE_DIRTY_RECT
|
||||
Refresh(mRootView, nsnull, &mDirtyRect, aUpdateFlags & NS_VMREFRESH_DOUBLE_BUFFER);
|
||||
else if (mFrameRate > 0)
|
||||
#else
|
||||
Refresh(mRootView, nsnull, mDirtyRegion, aUpdateFlags & NS_VMREFRESH_DOUBLE_BUFFER);
|
||||
#endif
|
||||
else if ((mFrameRate > 0) && !(aUpdateFlags & NS_VMREFRESH_NO_SYNC))
|
||||
{
|
||||
PRTime now = PR_Now();
|
||||
PRTime conversion, ustoms;
|
||||
|
@ -524,7 +626,7 @@ void nsViewManager :: RemoveChild(nsIView *parent, nsIView *child)
|
|||
|
||||
if ((nsnull != parent) && (nsnull != child))
|
||||
{
|
||||
UpdateView(child, nsnull, 0);
|
||||
UpdateView(child, nsnull, NS_VMREFRESH_NO_SYNC);
|
||||
parent->RemoveChild(child);
|
||||
}
|
||||
}
|
||||
|
@ -678,10 +780,19 @@ nsDrawingSurface nsViewManager :: GetDrawingSurface(nsIRenderingContext &aContex
|
|||
|
||||
void nsViewManager :: ClearDirtyRegion()
|
||||
{
|
||||
#ifdef USE_DIRTY_RECT
|
||||
|
||||
mDirtyRect.x = 0;
|
||||
mDirtyRect.y = 0;
|
||||
mDirtyRect.width = 0;
|
||||
mDirtyRect.height = 0;
|
||||
|
||||
#else
|
||||
|
||||
if (nsnull != mDirtyRegion)
|
||||
mDirtyRegion->SetTo(0, 0, 0, 0);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
nsIRenderingContext * nsViewManager :: CreateRenderingContext(nsIView &aView)
|
||||
|
@ -727,3 +838,25 @@ nsIRenderingContext * nsViewManager :: CreateRenderingContext(nsIView &aView)
|
|||
|
||||
return cx;
|
||||
}
|
||||
|
||||
void nsViewManager :: AddRectToDirtyRegion(nsRect &aRect)
|
||||
{
|
||||
if (nsnull == mDirtyRegion)
|
||||
{
|
||||
static NS_DEFINE_IID(kRegionCID, NS_REGION_CID);
|
||||
static NS_DEFINE_IID(kIRegionIID, NS_IREGION_IID);
|
||||
|
||||
nsresult rv = NSRepository::CreateInstance(kRegionCID,
|
||||
nsnull,
|
||||
kIRegionIID,
|
||||
(void **)&mDirtyRegion);
|
||||
|
||||
if (NS_OK != rv)
|
||||
return;
|
||||
}
|
||||
|
||||
nsRect trect = aRect;
|
||||
|
||||
trect *= mContext->GetTwipsToPixels();
|
||||
mDirtyRegion->Union(trect.x, trect.y, trect.width, trect.height);
|
||||
}
|
||||
|
|
|
@ -73,8 +73,8 @@ public:
|
|||
// the region or rectangle passed in should be in the window's
|
||||
// coordinate space. Often called in response to a paint/redraw event
|
||||
// from the native windowing system.
|
||||
virtual void Refresh(nsIRenderingContext *aContext, nsIRegion *region,
|
||||
PRUint32 aUpdateFlags);
|
||||
virtual void Refresh(nsIView *aView, nsIRenderingContext *aContext,
|
||||
nsIRegion *region, PRUint32 aUpdateFlags);
|
||||
virtual void Refresh(nsIView* aView, nsIRenderingContext *aContext,
|
||||
nsRect *rect, PRUint32 aUpdateFlags);
|
||||
|
||||
|
@ -170,12 +170,14 @@ public:
|
|||
private:
|
||||
~nsViewManager();
|
||||
nsIRenderingContext *CreateRenderingContext(nsIView &aView);
|
||||
void AddRectToDirtyRegion(nsRect &aRect);
|
||||
|
||||
nsIPresContext *mContext;
|
||||
nsIWidget *mRootWindow;
|
||||
nsRect mDSBounds;
|
||||
nsDrawingSurface mDrawingSurface;
|
||||
PRTime mLastRefresh;
|
||||
nsIRegion *mDirtyRegion;
|
||||
|
||||
public:
|
||||
//these are public so that our timer callback can poke them.
|
||||
|
|
Загрузка…
Ссылка в новой задаче