Added code to prevent invalidation of non-visible rectangles.

This is a performance enhancement for platforms where toolkit invalidate calls
are expensive. b=29847 r=rods@netscape.com.
This commit is contained in:
kmcclusk%netscape.com 2000-03-15 01:20:07 +00:00
Родитель 0a4b14d764
Коммит 619c64eaa3
6 изменённых файлов: 278 добавлений и 2 удалений

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

@ -59,6 +59,13 @@ nsScrollPortView::~nsScrollPortView()
NS_RELEASE(mListeners);
}
if (nsnull != mViewManager) {
nsIScrollableView* scrollingView;
mViewManager->GetRootScrollableView(&scrollingView);
if ((nsnull != scrollingView) && (this == scrollingView)) {
mViewManager->SetRootScrollableView(nsnull);
}
}
}
nsresult nsScrollPortView::QueryInterface(const nsIID& aIID, void** aInstancePtr)

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

@ -404,6 +404,14 @@ nsScrollingView::~nsScrollingView()
mListeners->Clear();
NS_RELEASE(mListeners);
}
if (nsnull != mViewManager) {
nsIScrollableView* scrollingView;
mViewManager->GetRootScrollableView(&scrollingView);
if ((nsnull != scrollingView) && (this == scrollingView)) {
mViewManager->SetRootScrollableView(nsnull);
}
}
}
nsresult nsScrollingView::QueryInterface(const nsIID& aIID, void** aInstancePtr)

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

@ -1445,6 +1445,15 @@ NS_IMETHODIMP nsViewManager::UpdateView(nsIView *aView, PRUint32 aUpdateFlags)
NS_IMETHODIMP nsViewManager::UpdateView(nsIView *aView, const nsRect &aRect, PRUint32 aUpdateFlags)
{
NS_PRECONDITION(nsnull != aView, "null view");
// If the rectangle is not visible then abort
// without invalidating. This is a performance
// enhancement since invalidating a native widget
// can be expensive.
if (! IsRectVisible(aView, aRect)) {
return NS_OK;
}
if (!mRefreshEnabled) {
// accumulate this rectangle in the view's dirty region, so we can process it later.
if (aRect.width != 0 && aRect.height != 0) {
@ -2827,3 +2836,96 @@ void nsViewManager::ViewToWidget(nsIView *aView, nsIView* aWidgetView, nsRect &a
aRect.ScaleRoundOut(t2p);
}
nsresult nsViewManager::GetVisibleRect(nsRect& aVisibleRect)
{
nsresult rv = NS_OK;
// Get the viewport scroller
nsIScrollableView* scrollingView;
GetRootScrollableView(&scrollingView);
if (scrollingView) {
// Determine the visible rect in the scrolled view's coordinate space.
// The size of the visible area is the clip view size
const nsIView* clipView;
nsRect visibleRect;
scrollingView->GetScrollPosition(aVisibleRect.x, aVisibleRect.y);
scrollingView->GetClipView(&clipView);
clipView->GetDimensions(&aVisibleRect.width, &aVisibleRect.height);
} else {
rv = NS_ERROR_FAILURE;
}
return rv;
}
nsresult nsViewManager::GetAbsoluteRect(nsIView *aView, const nsRect &aRect,
nsRect& aAbsRect)
{
nsIScrollableView* scrollingView = nsnull;
nsIView* scrolledView = nsnull;
GetRootScrollableView(&scrollingView);
if (nsnull == scrollingView) {
return NS_ERROR_FAILURE;
}
scrollingView->GetScrolledView(scrolledView);
// Calculate the absolute coordinates of the aRect passed in.
// aRects values are relative to aView
aAbsRect = aRect;
nsIView *parentView = aView;
while ((parentView != nsnull) && (parentView != scrolledView)) {
nscoord x, y;
parentView->GetPosition(&x, &y);
aAbsRect.MoveBy(x, y);
parentView->GetParent(parentView);
}
if (parentView != scrolledView) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
PRBool nsViewManager::IsRectVisible(nsIView *aView, const nsRect &aRect)
{
// Calculate the absolute coordinates for the visible rectangle
nsRect visibleRect;
if (GetVisibleRect(visibleRect) == NS_ERROR_FAILURE) {
return PR_TRUE;
}
// Calculate the absolute coordinates of the aRect passed in.
// aRects values are relative to aView
nsRect absRect;
if ((GetAbsoluteRect(aView, aRect, absRect)) == NS_ERROR_FAILURE) {
return PR_TRUE;
}
// Compare the visible rect against the rect passed in.
PRBool overlaps = absRect.IntersectRect(absRect, visibleRect);
#if 0
// Debugging code
static int toggle = 0;
for (int i = 0; i < toggle; i++) {
printf(" ");
}
if (toggle == 10) {
toggle = 0;
} else {
toggle++;
}
printf("***overlaps %d\n", overlaps);
#endif
return overlaps;
}

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

@ -180,6 +180,35 @@ private:
void ViewToWidget(nsIView *aView, nsIView* aWidgetView, nsRect &aRect) const;
// void WidgetToView(nsIView* aView, nsRect &aWidgetRect);
/**
* Transforms a rectangle from specified view's coordinate system to
* an absolute coordinate rectangle which can be compared against the
* rectangle returned by GetVisibleRect to determine visibility.
* @param aView view that aRect coordinates are specified relative to
* @param aRect rectangle in twips to convert to absolute coordinates
* @param aAbsRect rectangle in absolute coorindates.
* @returns NS_OK if successful otherwise, NS_ERROR_FAILURE
*/
nsresult GetAbsoluteRect(nsIView *aView, const nsRect &aRect,
nsRect& aAbsRect);
/**
* Determine the visible rect
* @param aVisibleRect visible rectangle in twips
* @returns NS_OK if successful, otherwise NS_ERROR_FAILURE.
*/
nsresult GetVisibleRect(nsRect& aVisibleRect);
/**
* Determine if a rectangle specified in the view's coordinate system
* is completely, or partially visible.
* @param aView view that aRect coordinates are specified relative to
* @param aRect rectangle in twips to test for visibility
* @returns PR_TRUE if the rect is visible, PR_FALSE otherwise.
*/
PRBool IsRectVisible(nsIView *aView, const nsRect &aRect);
private:
nsIDeviceContext *mContext;
nsIViewObserver *mObserver;

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

@ -853,8 +853,8 @@ nsresult nsViewManager2::CreateBlendingBuffers(nsIRenderingContext &aRC)
mBlender->Init(mContext);
}
gBlendWidth = mTranslucentBounds.width * mPixelsToTwips;
gBlendHeight = mTranslucentBounds.height * mPixelsToTwips;
gBlendWidth = (PRInt32)(mTranslucentBounds.width * mPixelsToTwips);
gBlendHeight = (PRInt32)(mTranslucentBounds.height * mPixelsToTwips);
return NS_OK;
}
@ -946,6 +946,15 @@ NS_IMETHODIMP nsViewManager2::UpdateView(nsIView *aView, PRUint32 aUpdateFlags)
NS_IMETHODIMP nsViewManager2::UpdateView(nsIView *aView, const nsRect &aRect, PRUint32 aUpdateFlags)
{
NS_PRECONDITION(nsnull != aView, "null view");
// If the rectangle is not visible then abort
// without invalidating. This is a performance
// enhancement since invalidating a native widget
// can be expensive.
if (! IsRectVisible(aView, aRect)) {
return NS_OK;
}
if (!mRefreshEnabled) {
// accumulate this rectangle in the view's dirty region, so we can process it later.
if (aRect.width != 0 && aRect.height != 0) {
@ -2368,3 +2377,95 @@ void nsViewManager2::ViewToWidget(nsIView *aView, nsIView* aWidgetView, nsRect &
mContext->GetAppUnitsToDevUnits(t2p);
aRect.ScaleRoundOut(t2p);
}
nsresult nsViewManager2::GetVisibleRect(nsRect& aVisibleRect)
{
nsresult rv = NS_OK;
// Get the viewport scroller
nsIScrollableView* scrollingView;
GetRootScrollableView(&scrollingView);
if (scrollingView) {
// Determine the visible rect in the scrolled view's coordinate space.
// The size of the visible area is the clip view size
const nsIView* clipView;
nsRect visibleRect;
scrollingView->GetScrollPosition(aVisibleRect.x, aVisibleRect.y);
scrollingView->GetClipView(&clipView);
clipView->GetDimensions(&aVisibleRect.width, &aVisibleRect.height);
} else {
rv = NS_ERROR_FAILURE;
}
return rv;
}
nsresult nsViewManager2::GetAbsoluteRect(nsIView *aView, const nsRect &aRect,
nsRect& aAbsRect)
{
nsIScrollableView* scrollingView = nsnull;
nsIView* scrolledView = nsnull;
GetRootScrollableView(&scrollingView);
if (nsnull == scrollingView) {
return NS_ERROR_FAILURE;
}
scrollingView->GetScrolledView(scrolledView);
// Calculate the absolute coordinates of the aRect passed in.
// aRects values are relative to aView
aAbsRect = aRect;
nsIView *parentView = aView;
while ((parentView != nsnull) && (parentView != scrolledView)) {
nscoord x, y;
parentView->GetPosition(&x, &y);
aAbsRect.MoveBy(x, y);
parentView->GetParent(parentView);
}
if (parentView != scrolledView) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
PRBool nsViewManager2::IsRectVisible(nsIView *aView, const nsRect &aRect)
{
// Calculate the absolute coordinates for the visible rectangle
nsRect visibleRect;
if (GetVisibleRect(visibleRect) == NS_ERROR_FAILURE) {
return PR_TRUE;
}
// Calculate the absolute coordinates of the aRect passed in.
// aRects values are relative to aView
nsRect absRect;
if ((GetAbsoluteRect(aView, aRect, absRect)) == NS_ERROR_FAILURE) {
return PR_TRUE;
}
// Compare the visible rect against the rect passed in.
PRBool overlaps = absRect.IntersectRect(absRect, visibleRect);
#if 0
// Debugging code
static int toggle = 0;
for (int i = 0; i < toggle; i++) {
printf(" ");
}
if (toggle == 10) {
toggle = 0;
} else {
toggle++;
}
printf("***overlaps %d\n", overlaps);
#endif
return overlaps;
}

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

@ -193,6 +193,35 @@ private:
void ViewToWidget(nsIView *aView, nsIView* aWidgetView, nsRect &aRect) const;
// void WidgetToView(nsIView* aView, nsRect &aWidgetRect);
/**
* Transforms a rectangle from specified view's coordinate system to
* an absolute coordinate rectangle which can be compared against the
* rectangle returned by GetVisibleRect to determine visibility.
* @param aView view that aRect coordinates are specified relative to
* @param aRect rectangle in twips to convert to absolute coordinates
* @param aAbsRect rectangle in absolute coorindates.
* @returns NS_OK if successful otherwise, NS_ERROR_FAILURE
*/
nsresult GetAbsoluteRect(nsIView *aView, const nsRect &aRect,
nsRect& aAbsRect);
/**
* Determine the visible rect
* @param aVisibleRect visible rectangle in twips
* @returns NS_OK if successful, otherwise NS_ERROR_FAILURE.
*/
nsresult GetVisibleRect(nsRect& aVisibleRect);
/**
* Determine if a rectangle specified in the view's coordinate system
* is completely, or partially visible.
* @param aView view that aRect coordinates are specified relative to
* @param aRect rectangle in twips to test for visibility
* @returns PR_TRUE if the rect is visible, PR_FALSE otherwise.
*/
PRBool IsRectVisible(nsIView *aView, const nsRect &aRect);
private:
nsIDeviceContext *mContext;
float mTwipsToPixels;