Support for Blending added. r=beard

This commit is contained in:
dcone%netscape.com 2000-03-16 05:05:12 +00:00
Родитель 9355e9d912
Коммит 6aef4d77aa
3 изменённых файлов: 1151 добавлений и 1077 удалений

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

@ -273,7 +273,7 @@ NS_IMETHODIMP nsView :: Paint(nsIRenderingContext& rc, const nsRect& rect,
if (nsnull != mClientData) {
nsCOMPtr<nsIViewObserver> observer;
if (NS_OK == mViewManager->GetViewObserver(*getter_AddRefs(observer))) {
if ((mClip.mLeft != 0) && (mClip.mRight != 0) && (mClip.mTop != 0) && (mClip.mBottom != 0)) {
if ((mClip.mLeft != mClip.mRight) && (mClip.mTop != mClip.mBottom)) {
nsRect crect;
crect.x = mClip.mLeft;
crect.y = mClip.mTop;
@ -972,9 +972,9 @@ NS_IMETHODIMP nsView :: SetClip(nscoord aLeft, nscoord aTop, nscoord aRight, nsc
NS_IMETHODIMP nsView :: GetClip(nscoord *aLeft, nscoord *aTop, nscoord *aRight, nscoord *aBottom,
PRBool &aResult) const
{
if ((mClip.mLeft == 0) && (mClip.mRight == 0) && (mClip.mTop == 0) && (mClip.mBottom == 0))
if ((mClip.mLeft == mClip.mRight) || (mClip.mTop == mClip.mBottom)) {
aResult = PR_FALSE;
else {
} else {
*aLeft = mClip.mLeft;
*aTop = mClip.mTop;
*aRight = mClip.mRight;

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

@ -1,4 +1,4 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: true; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
@ -50,16 +50,19 @@ static NS_DEFINE_IID(kRenderingContextCID, NS_RENDERING_CONTEXT_CID);
// Uncomment the following to use the nsIBlender. Turned off for now,
// so that we won't crash.
//#define SUPPORT_TRANSLUCENT_VIEWS
#define SUPPORT_TRANSLUCENT_VIEWS
// display list elements
struct DisplayListElement2 {
nsIView* mView;
nsRect mClip;
nsRect mBounds;
nsRect mDirty;
PRUint32 mFlags;
};
inline nscoord max(nscoord x, nscoord y) { return (x > y ? x : y); }
inline nscoord min(nscoord x, nscoord y) { return (x < y ? x : y); }
static void vm_timer_callback(nsITimer *aTimer, void *aClosure)
{
nsViewManager2 *vm = (nsViewManager2 *)aClosure;
@ -73,7 +76,7 @@ static void vm_timer_callback(nsITimer *aTimer, void *aClosure)
vm->mFrameRate = 0;
vm->SetFrameRate(fr);
}
//printf("timer composite...\n");
//printf("timer composite...\n");
#ifndef XP_MAC
//XXX temporary: The Mac doesn't need the timer to repaint but
// obviously this is not the good method to disable the thing.
@ -101,8 +104,8 @@ nsRect nsViewManager2::mDSBounds = nsRect(0, 0, 0, 0);
nsDrawingSurface nsViewManager2::gOffScreen = nsnull;
nsDrawingSurface nsViewManager2::gRed = nsnull;
nsDrawingSurface nsViewManager2::gBlue = nsnull;
PRInt32 nsViewManager2::gBlendWidth = 0;
PRInt32 nsViewManager2::gBlendHeight = 0;
nsSize nsViewManager2::gBlendSize = nsSize(0, 0);
nsSize nsViewManager2::gOffScreenSize = nsSize(0, 0);
static NS_DEFINE_IID(knsViewManagerIID, NS_IVIEWMANAGER_IID);
@ -157,8 +160,8 @@ nsViewManager2::~nsViewManager2()
gOffScreen = nsnull;
gRed = nsnull;
gBlue = nsnull;
gBlendWidth = 0;
gBlendHeight = 0;
gBlendSize.SizeTo(0, 0);
gOffScreenSize.SizeTo(0, 0);
}
mObserver = nsnull;
@ -201,7 +204,7 @@ nsViewManager2::~nsViewManager2()
NS_IMPL_QUERY_INTERFACE(nsViewManager2, knsViewManagerIID)
NS_IMPL_ADDREF(nsViewManager2);
NS_IMPL_ADDREF(nsViewManager2);
nsrefcnt nsViewManager2::Release(void)
{
@ -384,7 +387,7 @@ NS_IMETHODIMP nsViewManager2::SetWindowDimensions(nscoord width, nscoord height)
// Inform the presentation shell that we've been resized
if (nsnull != mObserver)
mObserver->ResizeReflow(mRootView, width, height);
//printf("reflow done\n");
//printf("reflow done\n");
return NS_OK;
}
@ -410,7 +413,7 @@ void nsViewManager2::Refresh(nsIView *aView, nsIRenderingContext *aContext, nsIR
mPainting = PR_TRUE;
//printf("refreshing region...\n");
//printf("refreshing region...\n");
//force double buffering because of non-opaque views?
if (mTransCnt > 0)
@ -425,8 +428,10 @@ void nsViewManager2::Refresh(nsIView *aView, nsIRenderingContext *aContext, nsIR
localcx = getter_AddRefs(CreateRenderingContext(*aView));
//couldn't get rendering context. this is ok at init time atleast
if (nsnull == localcx)
if (nsnull == localcx) {
mPainting = PR_FALSE;
return;
}
} else {
// plain assignment grabs another reference.
localcx = aContext;
@ -470,8 +475,7 @@ void nsViewManager2::Refresh(nsIView *aView, nsIRenderingContext *aContext, nsIR
localcx->CopyOffScreenBits(ds, wrect.x, wrect.y, wrect, NS_COPYBITS_USE_SOURCE_CLIP_REGION);
// Subtract the area we just painted from the dirty region
if ((nsnull != region) && !region->IsEmpty())
{
if ((nsnull != region) && !region->IsEmpty()) {
nsRect pixrect = trect;
float t2p;
@ -514,9 +518,9 @@ void nsViewManager2::Refresh(nsIView *aView, nsIRenderingContext *aContext, cons
//force double buffering because of non-opaque views?
//printf("refreshing rect... ");
//stdout << *rect;
//printf("\n");
//printf("refreshing rect... ");
//stdout << *rect;
//printf("\n");
if (mTransCnt > 0)
aUpdateFlags |= NS_VMREFRESH_DOUBLE_BUFFER;
@ -529,8 +533,10 @@ void nsViewManager2::Refresh(nsIView *aView, nsIRenderingContext *aContext, cons
localcx = getter_AddRefs(CreateRenderingContext(*aView));
//couldn't get rendering context. this is ok if at startup
if (nsnull == localcx)
if (nsnull == localcx) {
mPainting = PR_FALSE;
return;
}
} else {
// plain assignment adds a ref
localcx = aContext;
@ -636,8 +642,8 @@ void nsViewManager2::RenderViews(nsIView *aRootView, nsIRenderingContext& aRC, c
mDisplayListCount = 0;
mOpaqueViewCount = 0;
mTranslucentViewCount = 0;
mTranslucentBounds.x = mTranslucentBounds.y = 0;
mTranslucentBounds.width = mTranslucentBounds.width = 0;
mTranslucentArea.SetRect(0, 0, 0, 0);
mTranslucentSize.SizeTo(0, 0);
CreateDisplayList(mRootView, &mDisplayListCount, origin.x, origin.y, aRootView, &aRect);
@ -646,24 +652,43 @@ void nsViewManager2::RenderViews(nsIView *aRootView, nsIRenderingContext& aRC, c
if (mOpaqueViewCount > 0)
OptimizeDisplayList(aRect);
// create blending buffers, if necessary.
if (mTranslucentViewCount > 0) {
nsresult rv = CreateBlendingBuffers(aRC);
NS_ASSERTION((rv == NS_OK), "not enough memory to blend");
if (NS_FAILED(rv)) {
// fall back by just rendering with transparency.
mTranslucentViewCount = 0;
for (PRInt32 i = mDisplayListCount - 1; i>= 0; --i) {
DisplayListElement2* element = NS_STATIC_CAST(DisplayListElement2*, mDisplayList->ElementAt(i));
element->mFlags &= ~VIEW_TRANSLUCENT;
}
}
// DEBUGGING: fill in complete offscreen image in green, to see if we've got a blending bug.
//mOffScreenCX->SetColor(NS_RGB(0, 255, 0));
//mOffScreenCX->FillRect(nsRect(0, 0, gOffScreenSize.width, gOffScreenSize.height));
}
// draw all views in the display list, from back to front.
for (PRInt32 i = mDisplayListCount - 1; i>= 0; --i) {
DisplayListElement2* element = NS_STATIC_CAST(DisplayListElement2*, mDisplayList->ElementAt(i));
if (element->mFlags & VIEW_RENDERED) {
// typical case, just rendering a view.
// RenderView(element->mView, aRC, aRect, element->mClip, aResult);
// RenderView(element->mView, aRC, aRect, element->mBounds, aResult);
RenderDisplayListElement(element, aRC);
} else {
// special case, pushing or popping clipping.
if (element->mFlags & PUSH_CLIP) {
aRC.PushState();
aRC.SetClipRect(element->mClip, nsClipCombine_kIntersect, clipEmpty);
} else
aRC.SetClipRect(element->mBounds, nsClipCombine_kIntersect, clipEmpty);
} else {
if (element->mFlags & POP_CLIP) {
aRC.PopState(clipEmpty);
}
}
}
}
ComputeViewOffset(aRootView, nsnull, 0);
}
@ -693,68 +718,65 @@ void nsViewManager2::RenderView(nsIView *aView, nsIRenderingContext &aRC, const
void nsViewManager2::RenderDisplayListElement(DisplayListElement2* element, nsIRenderingContext &aRC)
{
PRBool isTranslucent = (element->mFlags & VIEW_TRANSLUCENT) != 0;
PRBool isTranslucent = (element->mFlags & VIEW_TRANSLUCENT) != 0, clipEmpty;
if (!isTranslucent) {
aRC.PushState();
nscoord x = element->mClip.x, y = element->mClip.y;
nscoord x = element->mBounds.x, y = element->mBounds.y;
aRC.Translate(x, y);
nsRect drect(element->mDirty.x - x, element->mDirty.y - y,
element->mDirty.width, element->mDirty.height);
PRBool unused;
element->mView->Paint(aRC, drect, NS_VIEW_FLAG_JUST_PAINT, unused);
aRC.PopState(unused);
element->mView->Paint(aRC, drect, NS_VIEW_FLAG_JUST_PAINT, clipEmpty);
aRC.PopState(clipEmpty);
}
#if defined(SUPPORT_TRANSLUCENT_VIEWS)
if (mTranslucentViewCount > 0 && (isTranslucent || mTranslucentBounds.Intersects(element->mDirty))) {
if (mTranslucentViewCount > 0 && (isTranslucent || mTranslucentArea.Intersects(element->mDirty))) {
// transluscency case. if this view is transluscent, have to use the nsIBlender, otherwise, just
// render in the offscreen. when we reach the last transluscent view, then we flush the bits
// to the onscreen rendering context.
if (mTranslucentBounds.width > gBlendWidth || mTranslucentBounds.height > gBlendHeight) {
nsresult rv = CreateBlendingBuffers(aRC);
NS_ASSERTION((rv == NS_OK), "not enough memory to blend");
if (NS_FAILED(rv)) {
// fall back by just rendering with transparency.
mTranslucentViewCount = 0;
RenderDisplayListElement(element, aRC);
return;
}
}
// compute the origin of the view, relative to the blending buffer, which has the
// same dimensions as mTranslucentBounds.
nscoord viewX = element->mClip.x - mTranslucentBounds.x, viewY = element->mClip.y - mTranslucentBounds.y;
// compute the origin of the view, relative to the offscreen buffer, which has the
// same dimensions as mTranslucentArea.
nscoord viewX = element->mBounds.x - mTranslucentArea.x, viewY = element->mBounds.y - mTranslucentArea.y;
nsRect damageRect(element->mDirty);
damageRect.IntersectRect(damageRect, mTranslucentBounds);
damageRect.x -= element->mClip.x, damageRect.y -= element->mClip.y;
damageRect.IntersectRect(damageRect, mTranslucentArea);
damageRect.x -= element->mBounds.x, damageRect.y -= element->mBounds.y;
if (element->mFlags & VIEW_TRANSLUCENT) {
nsRect blendRect(element->mDirty.x - mTranslucentBounds.x, element->mDirty.y - mTranslucentBounds.y,
element->mDirty.width, element->mDirty.height);
nsIView* view = element->mView;
nsRect blendRect(0, 0, element->mDirty.width, element->mDirty.height);
// paint the view twice, first in the red buffer, then the blue, the
// paint the view twice, first in the red buffer, then the blue;
// the blender will pick up the touched pixels only.
mRedCX->SetColor(NS_RGB(255, 0, 0));
mRedCX->FillRect(blendRect);
PaintView(element->mView, *mRedCX, viewX, viewY, damageRect);
PaintView(view, *mRedCX, 0, 0, damageRect);
// DEBUGGING ONLY
//aRC.CopyOffScreenBits(gRed, 0, 0, element->mDirty,
// NS_COPYBITS_XFORM_DEST_VALUES | NS_COPYBITS_TO_BACK_BUFFER);
mBlueCX->SetColor(NS_RGB(0, 0, 255));
mBlueCX->FillRect(blendRect);
PaintView(element->mView, *mBlueCX, viewX, viewY, damageRect);
PaintView(view, *mBlueCX, 0, 0, damageRect);
// DEBUGGING ONLY
//aRC.CopyOffScreenBits(gBlue, 0, 0, element->mDirty,
// NS_COPYBITS_XFORM_DEST_VALUES | NS_COPYBITS_TO_BACK_BUFFER);
//mOffScreenCX->CopyOffScreenBits(gBlue, 0, 0, nsRect(viewX, viewY, blendRect.width, blendRect.height),
// NS_COPYBITS_XFORM_DEST_VALUES | NS_COPYBITS_TO_BACK_BUFFER);
float opacity;
element->mView->GetOpacity(opacity);
view->GetOpacity(opacity);
// perform the blend itself.
blendRect *= mTwipsToPixels;
mBlender->Blend(blendRect.x, blendRect.y,
blendRect.width, blendRect.height,
mBlender->Blend(0, 0, blendRect.width, blendRect.height,
mRedCX, mOffScreenCX,
blendRect.x, blendRect.y,
viewX * mTwipsToPixels, viewY * mTwipsToPixels,
opacity, mBlueCX,
NS_RGB(255, 0, 0), NS_RGB(0, 0, 255));
@ -765,8 +787,15 @@ void nsViewManager2::RenderDisplayListElement(DisplayListElement2* element, nsIR
// flush the bits back to screen.
if (mTranslucentViewCount == 0) {
aRC.CopyOffScreenBits(gOffScreen, 0, 0, mTranslucentBounds,
NS_COPYBITS_XFORM_DEST_VALUES | NS_COPYBITS_TO_BACK_BUFFER);
// DEBUG: is this getting through?
// mOffScreenCX->SetColor(NS_RGB(0, 0, 0));
// mOffScreenCX->DrawRect(nsRect(0, 0, mTranslucentArea.width, mTranslucentArea.height));
aRC.CopyOffScreenBits(gOffScreen, 0, 0, mTranslucentArea,
NS_COPYBITS_XFORM_DEST_VALUES |
NS_COPYBITS_TO_BACK_BUFFER);
// DEBUG: what rectangle are we blitting?
// aRC.SetColor(NS_RGB(0, 0, 0));
// aRC.DrawRect(mTranslucentArea);
}
}
#endif
@ -790,30 +819,75 @@ inline PRInt32 nextPowerOf2(PRInt32 value)
return result;
}
static nsresult NewOffscreenContext(nsIDeviceContext* deviceContext, nsDrawingSurface surface,
const nsSize& size, nsIRenderingContext* *aResult)
{
nsresult rv;
nsIRenderingContext* context;
rv = nsComponentManager::CreateInstance(kRenderingContextCID, nsnull,
NS_GET_IID(nsIRenderingContext),
(void **)&context);
if (NS_FAILED(rv))
return rv;
rv = context->Init(deviceContext, surface);
if (NS_FAILED(rv))
return rv;
// always initialize clipping, linux won't draw images otherwise.
PRBool clipEmpty;
nsRect clip(0, 0, size.width, size.height);
context->SetClipRect(clip, nsClipCombine_kReplace, clipEmpty);
*aResult = context;
return NS_OK;
}
nsresult nsViewManager2::CreateBlendingBuffers(nsIRenderingContext &aRC)
{
nsresult rv;
// compute the new bounds of the blending buffers. should probably round the
// resulting
nsRect blenderBounds(0, 0, mTranslucentBounds.width, mTranslucentBounds.height);
blenderBounds.ScaleRoundOut(mTwipsToPixels);
// create a blender, if none exists already.
if (nsnull == mBlender) {
rv = nsComponentManager::CreateInstance(kBlenderCID, nsnull, NS_GET_IID(nsIBlender), (void **)&mBlender);
if (NS_FAILED(rv))
return rv;
rv = mBlender->Init(mContext);
if (NS_FAILED(rv))
return rv;
}
blenderBounds.width = nextPowerOf2(blenderBounds.width);
blenderBounds.height = nextPowerOf2(blenderBounds.height);
// ensure that the global drawing surfaces are large enough.
if (mTranslucentArea.width > gOffScreenSize.width || mTranslucentArea.height > gOffScreenSize.height) {
nsRect offscreenBounds(0, 0, mTranslucentArea.width, mTranslucentArea.height);
offscreenBounds.ScaleRoundOut(mTwipsToPixels);
offscreenBounds.width = nextPowerOf2(offscreenBounds.width);
offscreenBounds.height = nextPowerOf2(offscreenBounds.height);
NS_IF_RELEASE(mOffScreenCX);
NS_IF_RELEASE(mRedCX);
NS_IF_RELEASE(mBlueCX);
if (nsnull != gOffScreen) {
aRC.DestroyDrawingSurface(gOffScreen);
gOffScreen = nsnull;
}
rv = aRC.CreateDrawingSurface(&blenderBounds, NS_CREATEDRAWINGSURFACE_FOR_PIXEL_ACCESS, gOffScreen);
rv = aRC.CreateDrawingSurface(&offscreenBounds, NS_CREATEDRAWINGSURFACE_FOR_PIXEL_ACCESS, gOffScreen);
if (NS_FAILED(rv))
return rv;
offscreenBounds.ScaleRoundOut(mPixelsToTwips);
gOffScreenSize.width = offscreenBounds.width;
gOffScreenSize.height = offscreenBounds.height;
}
// ensure that the global blending drawing surfaces are large enough.
if (mTranslucentSize.width > gBlendSize.width || mTranslucentSize.height > gBlendSize.height) {
nsRect blenderBounds(0, 0, mTranslucentSize.width, mTranslucentSize.height);
blenderBounds.ScaleRoundOut(mTwipsToPixels);
blenderBounds.width = nextPowerOf2(blenderBounds.width);
blenderBounds.height = nextPowerOf2(blenderBounds.height);
NS_IF_RELEASE(mRedCX);
NS_IF_RELEASE(mBlueCX);
if (nsnull != gRed) {
aRC.DestroyDrawingSurface(gRed);
gRed = nsnull;
@ -830,31 +904,28 @@ nsresult nsViewManager2::CreateBlendingBuffers(nsIRenderingContext &aRC)
if (NS_FAILED(rv))
return rv;
// now create the blending offscreen rendering contexts.
rv = nsComponentManager::CreateInstance(kRenderingContextCID, nsnull, NS_GET_IID(nsIRenderingContext), (void **)&mOffScreenCX);
if (NS_FAILED(rv))
return rv;
mOffScreenCX->Init(mContext, gOffScreen);
rv = nsComponentManager::CreateInstance(kRenderingContextCID, nsnull, NS_GET_IID(nsIRenderingContext), (void **)&mRedCX);
if (NS_FAILED(rv))
return rv;
mRedCX->Init(mContext, gRed);
rv = nsComponentManager::CreateInstance(kRenderingContextCID, nsnull, NS_GET_IID(nsIRenderingContext), (void **)&mBlueCX);
if (NS_FAILED(rv))
return rv;
mBlueCX->Init(mContext, gBlue);
if (nsnull == mBlender) {
rv = nsComponentManager::CreateInstance(kBlenderCID, nsnull, NS_GET_IID(nsIBlender), (void **)&mBlender);
if (NS_FAILED(rv))
return rv;
mBlender->Init(mContext);
blenderBounds.ScaleRoundOut(mPixelsToTwips);
gBlendSize.width = blenderBounds.width;
gBlendSize.height = blenderBounds.height;
}
gBlendWidth = (PRInt32)(mTranslucentBounds.width * mPixelsToTwips);
gBlendHeight = (PRInt32)(mTranslucentBounds.height * mPixelsToTwips);
// recreate local offscreen & blending contexts, if necessary.
if (mOffScreenCX == nsnull) {
rv = NewOffscreenContext(mContext, gOffScreen, gOffScreenSize, &mOffScreenCX);
if (NS_FAILED(rv))
return rv;
}
if (mRedCX == nsnull) {
rv = NewOffscreenContext(mContext, gRed, gBlendSize, &mRedCX);
if (NS_FAILED(rv))
return rv;
}
if (mBlueCX == nsnull) {
rv = NewOffscreenContext(mContext, gBlue, gBlendSize, &mBlueCX);
if (NS_FAILED(rv))
return rv;
}
return NS_OK;
}
@ -1079,7 +1150,7 @@ NS_IMETHODIMP nsViewManager2::DispatchEvent(nsGUIEvent *aEvent, nsEventStatus *a
float p2t;
mContext->GetDevUnitsToAppUnits(p2t);
//printf("resize: (pix) %d, %d\n", width, height);
//printf("resize: (pix) %d, %d\n", width, height);
SetWindowDimensions(NSIntPixelsToTwips(width, p2t),
NSIntPixelsToTwips(height, p2t));
*aStatus = nsEventStatus_eConsumeNoDefault;
@ -1130,7 +1201,7 @@ NS_IMETHODIMP nsViewManager2::DispatchEvent(nsGUIEvent *aEvent, nsEventStatus *a
// XXX rods
updateFlags |= NS_VMREFRESH_DOUBLE_BUFFER;
//printf("refreshing: view: %x, %d, %d, %d, %d\n", view, trect.x, trect.y, trect.width, trect.height);
//printf("refreshing: view: %x, %d, %d, %d, %d\n", view, trect.x, trect.y, trect.width, trect.height);
// Refresh the view
Refresh(view, ((nsPaintEvent*)aEvent)->renderingContext, &damrect, updateFlags);
}
@ -1684,10 +1755,6 @@ NS_IMETHODIMP nsViewManager2::GetDeviceContext(nsIDeviceContext *&aContext)
return NS_OK;
}
#ifndef max
#define max(a, b) ((a) < (b) ? (b) : (a))
#endif
nsDrawingSurface nsViewManager2::GetDrawingSurface(nsIRenderingContext &aContext, nsRect& aBounds)
{
if ((nsnull == mDrawingSurface)
@ -1946,6 +2013,7 @@ NS_IMETHODIMP nsViewManager2::Display(nsIView* aView)
//couldn't get rendering context. this is ok if at startup
if (nsnull == localcx)
{
mPainting = PR_FALSE;
return NS_ERROR_FAILURE;
}
@ -2054,16 +2122,16 @@ PRBool nsViewManager2::CreateDisplayList(nsIView *aView, PRInt32 *aIndex,
if (!aTopView)
aTopView = aView;
nsRect lrect;
aView->GetBounds(lrect);
nsRect bounds;
aView->GetBounds(bounds);
if (aView == aTopView) {
lrect.x = 0;
lrect.y = 0;
bounds.x = 0;
bounds.y = 0;
}
lrect.x += aX;
lrect.y += aY;
bounds.x += aX;
bounds.y += aY;
// is this a clip view?
PRBool isClipView = IsClipView(aView);
@ -2080,16 +2148,16 @@ PRBool nsViewManager2::CreateDisplayList(nsIView *aView, PRInt32 *aIndex,
aView->GetChildCount(childCount);
if (childCount > 0) {
if (isClipView && (!hasWidget || (hasWidget && isParentView))) {
lrect.x -= aOriginX;
lrect.y -= aOriginY;
bounds.x -= aOriginX;
bounds.y -= aOriginY;
retval = AddToDisplayList(aIndex, aView, lrect, lrect, POP_CLIP);
retval = AddToDisplayList(aIndex, aView, bounds, bounds, POP_CLIP);
if (retval)
return retval;
lrect.x += aOriginX;
lrect.y += aOriginY;
bounds.x += aOriginX;
bounds.y += aOriginY;
}
if (!hasWidget || (hasWidget && isParentView))
@ -2102,20 +2170,20 @@ PRBool nsViewManager2::CreateDisplayList(nsIView *aView, PRInt32 *aIndex,
childView->GetZIndex(zindex);
if (zindex < 0)
break;
retval = CreateDisplayList(childView, aIndex, aOriginX, aOriginY, aRealView, aDamageRect, aTopView, lrect.x, lrect.y);
retval = CreateDisplayList(childView, aIndex, aOriginX, aOriginY, aRealView, aDamageRect, aTopView, bounds.x, bounds.y);
if (retval)
break;
}
}
}
lrect.x -= aOriginX;
lrect.y -= aOriginY;
bounds.x -= aOriginX;
bounds.y -= aOriginY;
// if (clipper)
if (isClipView && (!hasWidget || (hasWidget && isParentView))) {
if (childCount > 0)
retval = AddToDisplayList(aIndex, aView, lrect, lrect, PUSH_CLIP);
retval = AddToDisplayList(aIndex, aView, bounds, bounds, PUSH_CLIP);
} else if (!retval) {
nsViewVisibility visibility;
float opacity;
@ -2128,7 +2196,7 @@ PRBool nsViewManager2::CreateDisplayList(nsIView *aView, PRInt32 *aIndex,
aView->HasTransparency(transparent);
if (aDamageRect)
overlap = irect.IntersectRect(lrect, *aDamageRect);
overlap = irect.IntersectRect(bounds, *aDamageRect);
else
overlap = PR_TRUE;
@ -2140,7 +2208,7 @@ PRBool nsViewManager2::CreateDisplayList(nsIView *aView, PRInt32 *aIndex,
if (opacity < 1.0f)
flags |= VIEW_TRANSLUCENT;
#endif
retval = AddToDisplayList(aIndex, aView, lrect, irect, flags);
retval = AddToDisplayList(aIndex, aView, bounds, irect, flags);
if (retval || !transparent && (opacity == 1.0f) && (irect == *aDamageRect))
retval = PR_TRUE;
@ -2148,10 +2216,10 @@ PRBool nsViewManager2::CreateDisplayList(nsIView *aView, PRInt32 *aIndex,
// any children with negative z-indices?
if (!retval && nsnull != childView) {
lrect.x += aOriginX;
lrect.y += aOriginY;
bounds.x += aOriginX;
bounds.y += aOriginY;
for (; nsnull != childView; childView->GetNextSibling(childView)) {
retval = CreateDisplayList(childView, aIndex, aOriginX, aOriginY, aRealView, aDamageRect, aTopView, lrect.x, lrect.y);
retval = CreateDisplayList(childView, aIndex, aOriginX, aOriginY, aRealView, aDamageRect, aTopView, bounds.x, bounds.y);
if (retval)
break;
}
@ -2175,7 +2243,7 @@ PRBool nsViewManager2::AddToDisplayList(PRInt32 *aIndex, nsIView *aView, nsRect
}
element->mView = aView;
element->mClip = aClipRect;
element->mBounds = aClipRect;
element->mDirty = aDirtyRect;
element->mFlags = aFlags;
@ -2189,10 +2257,15 @@ PRBool nsViewManager2::AddToDisplayList(PRInt32 *aIndex, nsIView *aView, nsRect
// views need to be rendered into the blending
// buffers.
if (aFlags & VIEW_TRANSLUCENT) {
if (mTranslucentViewCount++ == 0)
mTranslucentBounds = aDirtyRect;
else
mTranslucentBounds.UnionRect(mTranslucentBounds, aDirtyRect);
if (mTranslucentViewCount++ == 0) {
mTranslucentArea = aDirtyRect;
mTranslucentSize.width = aDirtyRect.width;
mTranslucentSize.height = aDirtyRect.height;
} else {
mTranslucentArea.UnionRect(mTranslucentArea, aDirtyRect);
mTranslucentSize.width = max(mTranslucentSize.width, aDirtyRect.width);
mTranslucentSize.height = max(mTranslucentSize.height, aDirtyRect.height);
}
}
return PR_FALSE;
@ -2209,7 +2282,7 @@ nsresult nsViewManager2::OptimizeDisplayList(const nsRect& aDamageRect)
// a view is opaque if it is neither transparent nor transluscent
if (!(element->mFlags & (VIEW_TRANSPARENT | VIEW_TRANSLUCENT))) {
nsRect opaqueRect;
opaqueRect.IntersectRect(element->mClip, aDamageRect);
opaqueRect.IntersectRect(element->mBounds, aDamageRect);
nscoord top = opaqueRect.y, left = opaqueRect.x;
nscoord bottom = top + opaqueRect.height, right = left + opaqueRect.width;
// search for views behind this one, that are completely obscured by it.
@ -2217,7 +2290,7 @@ nsresult nsViewManager2::OptimizeDisplayList(const nsRect& aDamageRect)
DisplayListElement2* lowerElement = NS_STATIC_CAST(DisplayListElement2*, mDisplayList->ElementAt(j));
if (lowerElement->mFlags & VIEW_RENDERED) {
nsRect lowerRect;
lowerRect.IntersectRect(lowerElement->mClip, aDamageRect);
lowerRect.IntersectRect(lowerElement->mBounds, aDamageRect);
if (left <= lowerRect.x && top <= lowerRect.y &&
right >= (lowerRect.x + lowerRect.width) &&
bottom >= (lowerRect.y + lowerRect.height))
@ -2257,7 +2330,7 @@ void nsViewManager2::ShowDisplayList(PRInt32 flatlen)
DisplayListElement2* element = (DisplayListElement2*) mDisplayList->ElementAt(cnt);
view = element->mView;
rect = element->mClip;
rect = element->mBounds;
flags = element->mFlags;
nest[nestcnt << 1] = 0;

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

@ -1,4 +1,4 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: true; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
@ -240,7 +240,8 @@ private:
PRInt32 mDisplayListCount;
PRInt32 mOpaqueViewCount;
PRInt32 mTranslucentViewCount;
nsRect mTranslucentBounds;
nsRect mTranslucentArea; // bounding box of all translucent views.
nsSize mTranslucentSize; // size of the blending buffers.
nsIScrollableView *mRootScrollable;
//from here to public should be static and locked... MMP
@ -252,8 +253,8 @@ private:
static nsDrawingSurface gOffScreen;
static nsDrawingSurface gRed;
static nsDrawingSurface gBlue;
static PRInt32 gBlendWidth;
static PRInt32 gBlendHeight;
static nsSize gOffScreenSize;
static nsSize gBlendSize;
//compositor regions
nsIRegion *mTransRgn;