added suport for alpha blending of views.

This commit is contained in:
michaelp%netscape.com 1998-10-23 17:58:44 +00:00
Родитель 2812cd80c1
Коммит e415ee4d2c
2 изменённых файлов: 154 добавлений и 68 удалений

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

@ -31,6 +31,8 @@
#include "nsTransform2D.h"
#include "nsIScrollableView.h"
#include "nsVoidArray.h"
#include "nsGfxCIID.h"
#include "nsIBlender.h"
#include "nsIRegion.h"
static NS_DEFINE_IID(kIViewIID, NS_IVIEW_IID);
@ -296,6 +298,11 @@ NS_IMETHODIMP nsView :: Paint(nsIRenderingContext& rc, const nsRect& rect,
}
else if (mVis == nsViewVisibility_kShow)
{
float opacity;
GetOpacity(opacity);
if (opacity == 1.0f)
{
nsRect brect;
GetBounds(brect);
@ -313,6 +320,7 @@ NS_IMETHODIMP nsView :: Paint(nsIRenderingContext& rc, const nsRect& rect,
}
else if (this != pRoot)
clipres = rc.SetClipRect(brect, nsClipCombine_kIntersect);
}
}
if (clipres == PR_FALSE)
@ -383,13 +391,61 @@ NS_IMETHODIMP nsView :: Paint(nsIRenderingContext& rc, const nsRect& rect,
float opacity;
GetOpacity(opacity);
if (opacity > 0.0f)
//don't render things that can't be seen...
if ((opacity > 0.0f) && (mBounds.width > 1) && (mBounds.height > 1))
{
nsIRenderingContext *localcx = nsnull;
nsDrawingSurface surf = nsnull;
nsDrawingSurface redsurf = nsnull;
PRBool hasTransparency;
rc.PushState();
PRBool hasTransparency;
HasTransparency(hasTransparency);
if (opacity < 1.0f)
{
nsIDeviceContext *dx = nsnull;
nsIView *rootview = nsnull;
//create offscreen bitmap to render view into
mViewManager->GetDeviceContext(dx);
mViewManager->GetRootView(rootview);
if ((nsnull != dx) && (nsnull != rootview))
{
dx->CreateRenderingContext(rootview, localcx);
if (nsnull != localcx)
{
float t2p;
nscoord width, height;
//create offscreen buffer for blending...
dx->GetAppUnitsToDevUnits(t2p);
width = NSToCoordRound(mBounds.width * t2p);
height = NSToCoordRound(mBounds.height * t2p);
nsRect bitrect = nsRect(0, 0, width, height);
surf = localcx->CreateDrawingSurface(&bitrect, NS_CREATEDRAWINGSURFACE_FOR_PIXEL_ACCESS);
redsurf = localcx->CreateDrawingSurface(&bitrect, NS_CREATEDRAWINGSURFACE_FOR_PIXEL_ACCESS);
if (nsnull != surf)
localcx->SelectOffScreenDrawingSurface(surf);
}
NS_RELEASE(dx);
}
}
if (nsnull == localcx)
localcx = &rc;
if (hasTransparency || (opacity < 1.0f))
{
//overview of algorithm:
@ -412,7 +468,7 @@ NS_IMETHODIMP nsView :: Paint(nsIRenderingContext& rc, const nsRect& rect,
nscoord posx, posy;
nsRect damRect = rect;
rc.PushState();
localcx->PushState();
GetPosition(&posx, &posy);
@ -421,7 +477,7 @@ NS_IMETHODIMP nsView :: Paint(nsIRenderingContext& rc, const nsRect& rect,
damRect.x += posx;
damRect.y += posy;
rc.Translate(-posx, -posy);
localcx->Translate(-posx, -posy);
GetNextSibling(curview);
@ -438,7 +494,7 @@ NS_IMETHODIMP nsView :: Paint(nsIRenderingContext& rc, const nsRect& rect,
damRect.x += prect.x;
damRect.y += prect.y;
rc.Translate(-prect.x, -prect.y);
localcx->Translate(-prect.x, -prect.y);
}
}
@ -452,18 +508,20 @@ NS_IMETHODIMP nsView :: Paint(nsIRenderingContext& rc, const nsRect& rect,
if (overlap == PR_TRUE)
{
// Translate damage area into kid's coordinate system
nsRect kidDamageArea(damageArea.x - kidRect.x, damageArea.y - kidRect.y,
damageArea.width, damageArea.height);
// nsRect kidDamageArea(damageArea.x - kidRect.x, damageArea.y - kidRect.y,
// damageArea.width, damageArea.height);
nsRect kidDamageArea(damRect.x - kidRect.x, damRect.y - kidRect.y,
damRect.width, damRect.height);
//we will pop the states on the back to front pass...
rc.PushState();
localcx->PushState();
if (nsnull != views)
views->AppendElement(curview);
rects->AppendElement(new nsRect(kidDamageArea));
curview->Paint(rc, kidDamageArea, aPaintFlags | NS_VIEW_FLAG_FRONT_TO_BACK, clipres);
curview->Paint(*localcx, kidDamageArea, aPaintFlags | NS_VIEW_FLAG_FRONT_TO_BACK, clipres);
}
if (clipres == PR_TRUE)
@ -486,7 +544,7 @@ NS_IMETHODIMP nsView :: Paint(nsIRenderingContext& rc, const nsRect& rect,
damRect.x += prect.x;
damRect.y += prect.y;
rc.Translate(-prect.x, -prect.y);
localcx->Translate(-prect.x, -prect.y);
}
}
}
@ -509,7 +567,7 @@ NS_IMETHODIMP nsView :: Paint(nsIRenderingContext& rc, const nsRect& rect,
nsRect *trect = (nsRect *)rects->ElementAt(--idx);
delete trect;
rc.PopState();
localcx->PopState();
isfirst = PR_FALSE;
}
else
@ -517,12 +575,12 @@ NS_IMETHODIMP nsView :: Paint(nsIRenderingContext& rc, const nsRect& rect,
curview = (nsIView *)views->ElementAt(--idx);
nsRect *trect = (nsRect *)rects->ElementAt(idx);
curview->Paint(rc, *trect, aPaintFlags | NS_VIEW_FLAG_BACK_TO_FRONT, clipres);
curview->Paint(*localcx, *trect, aPaintFlags | NS_VIEW_FLAG_BACK_TO_FRONT, clipres);
delete trect;
//pop the state pushed on the front to back pass...
rc.PopState();
localcx->PopState();
}
}
@ -530,9 +588,12 @@ NS_IMETHODIMP nsView :: Paint(nsIRenderingContext& rc, const nsRect& rect,
delete views;
}
rc.PopState();
localcx->PopState();
}
if (nsnull != redsurf)
localcx->SelectOffScreenDrawingSurface(redsurf);
//now draw ourself...
if (nsnull != mClientData)
@ -541,11 +602,68 @@ NS_IMETHODIMP nsView :: Paint(nsIRenderingContext& rc, const nsRect& rect,
if (NS_OK == mViewManager->GetViewObserver(obs))
{
obs->Paint((nsIView *)this, rc, rect);
obs->Paint((nsIView *)this, *localcx, rect);
NS_RELEASE(obs);
}
}
if (localcx != &rc)
{
// localcx->SelectOffScreenDrawingSurface(nsnull);
NS_RELEASE(localcx);
}
else
localcx = nsnull;
//kill offscreen buffer
if ((nsnull != surf) && (nsnull != redsurf))
{
nsRect brect;
brect.x = brect.y = 0;
brect.width = mBounds.width;
brect.height = mBounds.height;
static NS_DEFINE_IID(kBlenderCID, NS_BLENDER_CID);
static NS_DEFINE_IID(kIBlenderIID, NS_IBLENDER_IID);
nsIBlender *blender = nsnull;
nsresult rv;
rv = nsRepository::CreateInstance(kBlenderCID, nsnull, kIBlenderIID, (void **)&blender);
if (NS_OK == rv)
{
nsIDeviceContext *dx;
mViewManager->GetDeviceContext(dx);
float t2p;
nscoord width, height;
dx->GetAppUnitsToDevUnits(t2p);
width = NSToCoordRound(mBounds.width * t2p);
height = NSToCoordRound(mBounds.height * t2p);
blender->Init(surf, redsurf);
blender->Blend(0, 0, width, height, redsurf, 0, 0, opacity, PR_FALSE);
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.DestroyDrawingSurface(surf);
rc.DestroyDrawingSurface(redsurf);
surf = nsnull;
redsurf = nsnull;
}
#ifdef SHOW_VIEW_BORDERS
{
nscoord x, y, w, h;
@ -1043,7 +1161,9 @@ nsresult nsView :: LoadWidget(const nsCID &aClassIID)
static NS_DEFINE_IID(kIWidgetIID, NS_IWIDGET_IID);
rv = nsRepository::CreateInstance(aClassIID, nsnull, kIWidgetIID, (void**)&mWindow);
if (NS_OK == rv) {
if (NS_OK == rv)
{
// Set the widget's client data
mWindow->SetClientData((void*)this);
}

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

@ -259,6 +259,7 @@ void nsViewManager :: Refresh(nsIView *aView, nsIRenderingContext *aContext, nsI
nsRect wrect;
nsIRenderingContext *localcx = nsnull;
float scale;
nsDrawingSurface ds = nsnull;
if (PR_FALSE == mRefreshEnabled)
return;
@ -293,7 +294,7 @@ void nsViewManager :: Refresh(nsIView *aView, nsIRenderingContext *aContext, nsI
if (aUpdateFlags & NS_VMREFRESH_DOUBLE_BUFFER)
{
mRootWindow->GetBounds(wrect);
nsDrawingSurface ds = GetDrawingSurface(*localcx, wrect);
ds = GetDrawingSurface(*localcx, wrect);
localcx->SelectOffScreenDrawingSurface(ds);
}
@ -314,7 +315,7 @@ void nsViewManager :: Refresh(nsIView *aView, nsIRenderingContext *aContext, nsI
aView->Paint(*localcx, trect, NS_VIEW_FLAG_CLIP_SET, result);
if (aUpdateFlags & NS_VMREFRESH_DOUBLE_BUFFER)
localcx->CopyOffScreenBits(wrect);
localcx->CopyOffScreenBits(ds, wrect.x, wrect.y, wrect, NS_COPYBITS_USE_SOURCE_CLIP_REGION);
if (localcx != aContext)
NS_RELEASE(localcx);
@ -340,6 +341,7 @@ void nsViewManager :: Refresh(nsIView *aView, nsIRenderingContext *aContext, con
{
nsRect wrect;
nsIRenderingContext *localcx = nsnull;
nsDrawingSurface ds = nsnull;
if (PR_FALSE == mRefreshEnabled)
return;
@ -376,7 +378,7 @@ void nsViewManager :: Refresh(nsIView *aView, nsIRenderingContext *aContext, con
if (aUpdateFlags & NS_VMREFRESH_DOUBLE_BUFFER)
{
mRootWindow->GetBounds(wrect);
nsDrawingSurface ds = GetDrawingSurface(*localcx, wrect);
ds = GetDrawingSurface(*localcx, wrect);
localcx->SelectOffScreenDrawingSurface(ds);
}
@ -389,7 +391,7 @@ void nsViewManager :: Refresh(nsIView *aView, nsIRenderingContext *aContext, con
aView->Paint(*localcx, trect, NS_VIEW_FLAG_CLIP_SET, result);
if (aUpdateFlags & NS_VMREFRESH_DOUBLE_BUFFER)
localcx->CopyOffScreenBits(wrect);
localcx->CopyOffScreenBits(ds, wrect.x, wrect.y, wrect, NS_COPYBITS_USE_SOURCE_CLIP_REGION);
if (localcx != aContext)
NS_RELEASE(localcx);
@ -397,6 +399,7 @@ void nsViewManager :: Refresh(nsIView *aView, nsIRenderingContext *aContext, con
// Subtract the area we just painted from the dirty region
nsIRegion *dirtyRegion;
aView->GetDirtyRegion(dirtyRegion);
if ((nsnull != dirtyRegion) && !dirtyRegion->IsEmpty())
{
nsRect pixrect = trect;
@ -959,58 +962,19 @@ NS_IMETHODIMP nsViewManager :: GetViewClipAbsolute(nsIView *aView, nsRect *rect,
NS_IMETHODIMP nsViewManager :: SetViewContentTransparency(nsIView *aView, PRBool aTransparent)
{
PRBool hasTransparency;
aView->HasTransparency(hasTransparency);
if (aTransparent != hasTransparency)
{
if (aTransparent == PR_FALSE)
{
//going opaque
mTransCnt--;
}
else
{
//going transparent
mTransCnt++;
}
UpdateTransCnt(aView, nsnull);
aView->SetContentTransparency(aTransparent);
UpdateTransCnt(nsnull, aView);
aView->SetContentTransparency(aTransparent);
}
return NS_OK;
}
NS_IMETHODIMP nsViewManager :: SetViewOpacity(nsIView *aView, float aOpacity)
{
PRBool newopaque, oldopaque;
float oldopacity;
if ((aOpacity == 1.0f) || (aOpacity == 0.0f))
newopaque = PR_TRUE;
else
newopaque = PR_FALSE;
aView->GetOpacity(oldopacity);
if ((oldopacity == 1.0f) || (oldopacity == 0.0f))
oldopaque = PR_TRUE;
else
oldopaque = PR_FALSE;
if (newopaque != oldopaque)
{
if (newopaque == PR_FALSE)
{
//going transparent
mTransCnt++;
}
else
{
//going opaque
mTransCnt--;
}
}
UpdateTransCnt(aView, nsnull);
aView->SetOpacity(aOpacity);
UpdateTransCnt(nsnull, aView);
return NS_OK;
}
@ -1050,7 +1014,7 @@ nsDrawingSurface nsViewManager :: GetDrawingSurface(nsIRenderingContext &aContex
aContext.DestroyDrawingSurface(mDrawingSurface);
}
mDrawingSurface = aContext.CreateDrawingSurface(&aBounds);
mDrawingSurface = aContext.CreateDrawingSurface(&aBounds, 0);
mDSBounds = aBounds;
}
@ -1177,7 +1141,8 @@ void nsViewManager :: AddRectToDirtyRegion(nsIView* aView, const nsRect &aRect)
void nsViewManager :: UpdateTransCnt(nsIView *oldview, nsIView *newview)
{
if (nsnull != oldview) {
if (nsnull != oldview)
{
PRBool hasTransparency;
float opacity;
@ -1188,7 +1153,8 @@ void nsViewManager :: UpdateTransCnt(nsIView *oldview, nsIView *newview)
mTransCnt--;
}
if (nsnull != newview) {
if (nsnull != newview)
{
PRBool hasTransparency;
float opacity;