From ddee55a0edf86c6506876f8514f9ff858c87463b Mon Sep 17 00:00:00 2001 From: "michaelp%netscape.com" Date: Mon, 23 Nov 1998 23:43:08 +0000 Subject: [PATCH] fixed display of black or garbage when resizing scrolled scrollingviews. git-svn-id: svn://10.0.0.236/trunk@15194 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/view/src/nsScrollingView.cpp | 2 +- mozilla/view/src/nsView.cpp | 176 +++++++++++++++++++++------ mozilla/view/src/nsView.h | 12 +- 3 files changed, 150 insertions(+), 40 deletions(-) diff --git a/mozilla/view/src/nsScrollingView.cpp b/mozilla/view/src/nsScrollingView.cpp index 6e7c9923332..beff6d04c0e 100644 --- a/mozilla/view/src/nsScrollingView.cpp +++ b/mozilla/view/src/nsScrollingView.cpp @@ -427,7 +427,7 @@ NS_IMETHODIMP nsScrollingView :: SetDimensions(nscoord width, nscoord height, PR //but unfortunately it will also cause scrollbar flashing. so long as //all resize operations happen through the viewmanager, this is not //an issue. we'll see. MMP -// ComputeContainerSize(); + ComputeContainerSize(); NS_RELEASE(dx); return NS_OK; diff --git a/mozilla/view/src/nsView.cpp b/mozilla/view/src/nsView.cpp index ebb1eda6992..3df2ac54226 100644 --- a/mozilla/view/src/nsView.cpp +++ b/mozilla/view/src/nsView.cpp @@ -65,8 +65,17 @@ nsEventStatus PR_CALLBACK HandleEvent(nsGUIEvent *aEvent) return result; } +PRInt32 nsView::gNumViews = 0; +PRInt32 nsView::gOffScreenWidth = 0; +PRInt32 nsView::gOffScreenHeight = 0; +nsDrawingSurface nsView::gOffScreen = nsnull; +nsDrawingSurface nsView::gRedSurf = nsnull; +nsDrawingSurface nsView::gBlueSurf = nsnull; + nsView :: nsView() { + gNumViews++; + mVis = nsViewVisibility_kShow; mXForm = nsnull; mVFlags = ~ALL_VIEW_FLAGS; @@ -137,7 +146,43 @@ nsView :: ~nsView() mWindow->Destroy(); NS_RELEASE(mWindow); } + NS_IF_RELEASE(mDirtyRegion); + + --gNumViews; + + NS_ASSERTION(!(gNumViews < 0), "underflow of views"); + + if (0 == gNumViews) + { + nsIRenderingContext *rc; + + static NS_DEFINE_IID(kRenderingContextCID, NS_RENDERING_CONTEXT_CID); + static NS_DEFINE_IID(kIRenderingContextIID, NS_IRENDERING_CONTEXT_IID); + + nsresult rv = nsRepository::CreateInstance(kRenderingContextCID, + nsnull, + kIRenderingContextIID, + (void **)&rc); + + if (NS_OK == rv) + { + if (nsnull != gOffScreen) + rc->DestroyDrawingSurface(gOffScreen); + + if (nsnull != gRedSurf) + rc->DestroyDrawingSurface(gRedSurf); + + if (nsnull != gBlueSurf) + rc->DestroyDrawingSurface(gBlueSurf); + + NS_RELEASE(rc); + } + + gOffScreen = nsnull; + gRedSurf = nsnull; + gBlueSurf = nsnull; + } } nsresult nsView :: QueryInterface(const nsIID& aIID, void** aInstancePtr) @@ -255,12 +300,14 @@ NS_IMETHODIMP nsView :: Paint(nsIRenderingContext& rc, const nsRect& rect, PRBool clipres = PR_FALSE; PRBool clipwasset = PR_FALSE; float opacity; + PRBool hasTransparency; mViewManager->GetRootView(pRoot); rc.PushState(); GetOpacity(opacity); + HasTransparency(hasTransparency); if (aPaintFlags & NS_VIEW_FLAG_CLIP_SET) { @@ -269,8 +316,8 @@ NS_IMETHODIMP nsView :: Paint(nsIRenderingContext& rc, const nsRect& rect, } else if (mVis == nsViewVisibility_kShow) { - if (opacity == 1.0f) - { +// if (!(aPaintFlags & (NS_VIEW_FLAG_FRONT_TO_BACK | NS_VIEW_FLAG_BACK_TO_FRONT))) +// { nsRect brect; GetBounds(brect); @@ -288,7 +335,7 @@ NS_IMETHODIMP nsView :: Paint(nsIRenderingContext& rc, const nsRect& rect, } else if (this != pRoot) rc.SetClipRect(brect, nsClipCombine_kIntersect, clipres); - } +// } } if (clipres == PR_FALSE) @@ -370,15 +417,13 @@ NS_IMETHODIMP nsView :: Paint(nsIRenderingContext& rc, const nsRect& rect, if ((opacity > 0.0f) && (mBounds.width > 1) && (mBounds.height > 1)) { nsIRenderingContext *localcx = nsnull; - nsDrawingSurface surf = nsnull; - nsDrawingSurface redsurf = nsnull; - PRBool hasTransparency; PRBool clipState; //for when we want to throw away the clip state + nsRect offscrRect = nsRect(0, 0, 0, 0); + PRBool useBlueSurf = PR_FALSE; + PRBool useBlendingSurfs = PR_FALSE; rc.PushState(); - HasTransparency(hasTransparency); - if (opacity < 1.0f) { nsIDeviceContext *dx = nsnull; @@ -405,13 +450,20 @@ NS_IMETHODIMP nsView :: Paint(nsIRenderingContext& rc, const nsRect& rect, width = NSToCoordRound(mBounds.width * t2p); height = NSToCoordRound(mBounds.height * t2p); - nsRect bitrect = nsRect(0, 0, width, height); + offscrRect = nsRect(0, 0, width, height); - localcx->CreateDrawingSurface(&bitrect, NS_CREATEDRAWINGSURFACE_FOR_PIXEL_ACCESS, surf); - localcx->CreateDrawingSurface(&bitrect, NS_CREATEDRAWINGSURFACE_FOR_PIXEL_ACCESS, redsurf); + CreateOffscreenSurfaces(*localcx, width, height); - if (nsnull != surf) - localcx->SelectOffScreenDrawingSurface(surf); + if ((PR_TRUE == hasTransparency) && (nsnull != gBlueSurf)) + useBlueSurf = PR_TRUE; + + if (nsnull != gOffScreen) + { + localcx->SelectOffScreenDrawingSurface(gOffScreen); + + if (nsnull != gRedSurf) + useBlendingSurfs = PR_TRUE; + } } NS_RELEASE(dx); @@ -421,7 +473,8 @@ NS_IMETHODIMP nsView :: Paint(nsIRenderingContext& rc, const nsRect& rect, if (nsnull == localcx) localcx = &rc; - if (hasTransparency || (opacity < 1.0f)) + if (((PR_TRUE == hasTransparency) || (opacity < 1.0f)) && + !(aPaintFlags & (NS_VIEW_FLAG_FRONT_TO_BACK | NS_VIEW_FLAG_BACK_TO_FRONT))) { //overview of algorithm: //1. clip is set to intersection of this view and whatever is @@ -566,9 +619,6 @@ NS_IMETHODIMP nsView :: Paint(nsIRenderingContext& rc, const nsRect& rect, localcx->PopState(clipState); } - if (nsnull != redsurf) - localcx->SelectOffScreenDrawingSurface(redsurf); - //now draw ourself... if (nsnull != mClientData) @@ -577,14 +627,35 @@ NS_IMETHODIMP nsView :: Paint(nsIRenderingContext& rc, const nsRect& rect, if (NS_OK == mViewManager->GetViewObserver(obs)) { + if (nsnull != gRedSurf) + { + localcx->SelectOffScreenDrawingSurface(gRedSurf); + + if (PR_TRUE == useBlueSurf) + { + localcx->SetColor(NS_RGB(255, 0, 0)); + localcx->FillRect(0, 0, mBounds.width, mBounds.height); + } + } + obs->Paint((nsIView *)this, *localcx, rect); + + if (PR_TRUE == useBlueSurf) + { + localcx->SelectOffScreenDrawingSurface(gBlueSurf); + + localcx->SetColor(NS_RGB(0, 0, 255)); + localcx->FillRect(0, 0, mBounds.width, mBounds.height); + + obs->Paint((nsIView *)this, *localcx, rect); + } + NS_RELEASE(obs); } } if (localcx != &rc) { -// localcx->SelectOffScreenDrawingSurface(nsnull); NS_RELEASE(localcx); } else @@ -592,7 +663,7 @@ NS_IMETHODIMP nsView :: Paint(nsIRenderingContext& rc, const nsRect& rect, //kill offscreen buffer - if ((nsnull != surf) && (nsnull != redsurf)) + if (PR_TRUE == useBlendingSurfs) { nsRect brect; @@ -614,29 +685,17 @@ NS_IMETHODIMP nsView :: Paint(nsIRenderingContext& rc, const nsRect& rect, mViewManager->GetDeviceContext(dx); - float t2p; - nscoord width, height; - - dx->GetAppUnitsToDevUnits(t2p); - - width = NSToCoordRound(mBounds.width * t2p); - height = NSToCoordRound(mBounds.height * t2p); - blender->Init(dx); - blender->Blend(0, 0, width, height,surf,redsurf, 0, 0, opacity, PR_FALSE); + blender->Blend(0, 0, offscrRect.width, offscrRect.height, gRedSurf, + gOffScreen, 0, 0, opacity, PR_FALSE, + (PR_TRUE == useBlueSurf) ? gBlueSurf : nsnull, + NS_RGB(255, 0, 0), NS_RGB(0, 0, 255)); NS_RELEASE(blender); NS_RELEASE(dx); -// rc.CopyOffScreenBits(surf, 0, 0, brect, NS_COPYBITS_XFORM_DEST_VALUES | NS_COPYBITS_TO_BACK_BUFFER); - rc.CopyOffScreenBits(redsurf, 0, 0, brect, NS_COPYBITS_XFORM_DEST_VALUES | NS_COPYBITS_TO_BACK_BUFFER); + rc.CopyOffScreenBits(gOffScreen, 0, 0, brect, NS_COPYBITS_XFORM_DEST_VALUES | NS_COPYBITS_TO_BACK_BUFFER); } - - rc.DestroyDrawingSurface(surf); - rc.DestroyDrawingSurface(redsurf); - - surf = nsnull; - redsurf = nsnull; } #ifdef SHOW_VIEW_BORDERS @@ -679,9 +738,10 @@ NS_IMETHODIMP nsView :: Paint(nsIRenderingContext& rc, const nsRect& rect, //paint process. only do this if this view is actually //visible and if there is no widget (like a scrollbar) here. - if (!clipwasset && (clipres == PR_FALSE) && + if ((PR_FALSE == clipwasset) && (PR_FALSE == clipres) && (mVis == nsViewVisibility_kShow) && (nsnull == mWindow) && - (opacity > 0.0f)) + (((opacity == 1.0f) && (PR_FALSE == hasTransparency)) || + !(aPaintFlags & (NS_VIEW_FLAG_BACK_TO_FRONT | NS_VIEW_FLAG_BACK_TO_FRONT)))) { nsRect brect; @@ -1288,3 +1348,43 @@ NS_IMETHODIMP nsView :: SetDirtyRegion(nsIRegion *aRegion) return NS_OK; } +#ifndef NS_MAX +#define NS_MAX(x, y) (((x) > (y)) ? (x) : (y)) +#endif + +nsresult nsView ::CreateOffscreenSurfaces(nsIRenderingContext &aRC, PRInt32 aWidth, PRInt32 aHeight) +{ + nsresult res = NS_ERROR_OUT_OF_MEMORY; + + if ((aWidth > gOffScreenWidth) || (aHeight > gOffScreenHeight)) + { + if (nsnull != gOffScreen) + aRC.DestroyDrawingSurface(gOffScreen); + + if (nsnull != gRedSurf) + aRC.DestroyDrawingSurface(gRedSurf); + + if (nsnull != gBlueSurf) + aRC.DestroyDrawingSurface(gBlueSurf); + + gOffScreen = nsnull; + gRedSurf = nsnull; + gBlueSurf = nsnull; + + gOffScreenWidth = NS_MAX(aWidth, gOffScreenWidth); + gOffScreenHeight = NS_MAX(aHeight, gOffScreenHeight); + + nsRect trect = nsRect(0, 0, gOffScreenWidth, gOffScreenHeight); + + aRC.CreateDrawingSurface(&trect, NS_CREATEDRAWINGSURFACE_FOR_PIXEL_ACCESS, gOffScreen); + aRC.CreateDrawingSurface(&trect, NS_CREATEDRAWINGSURFACE_FOR_PIXEL_ACCESS, gRedSurf); + aRC.CreateDrawingSurface(&trect, NS_CREATEDRAWINGSURFACE_FOR_PIXEL_ACCESS, gBlueSurf); + + if ((nsnull != gOffScreen) && (nsnull != gRedSurf) && (nsnull != gBlueSurf)) + res = NS_OK; + } + else + res = NS_OK; + + return res; +} diff --git a/mozilla/view/src/nsView.h b/mozilla/view/src/nsView.h index a276ddadae3..b5015930b97 100644 --- a/mozilla/view/src/nsView.h +++ b/mozilla/view/src/nsView.h @@ -102,8 +102,8 @@ public: protected: virtual ~nsView(); - // virtual nsresult LoadWidget(const nsCID &aClassIID); + nsresult CreateOffscreenSurfaces(nsIRenderingContext &aRC, PRInt32 aWidth, PRInt32 aHeight); protected: nsIViewManager *mViewManager; @@ -124,6 +124,16 @@ protected: PRInt32 mVFlags; nsIRegion* mDirtyRegion; +public: + //globals + + static PRInt32 gNumViews; + static PRInt32 gOffScreenWidth; + static PRInt32 gOffScreenHeight; + static nsDrawingSurface gOffScreen; + static nsDrawingSurface gRedSurf; + static nsDrawingSurface gBlueSurf; + private: NS_IMETHOD_(nsrefcnt) AddRef(void); NS_IMETHOD_(nsrefcnt) Release(void);