added support of irregular damage regions to viewmanager.

This commit is contained in:
michaelp 1998-06-03 03:12:52 +00:00
Родитель 0f5c5f61ce
Коммит 33a0103e30
9 изменённых файлов: 203 добавлений и 20 удалений

Просмотреть файл

@ -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.