mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 10:44:56 +00:00
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:
parent
0a4b14d764
commit
619c64eaa3
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user