зеркало из https://github.com/mozilla/pjs.git
Support for Blending added. r=beard
This commit is contained in:
Родитель
9355e9d912
Коммит
6aef4d77aa
|
@ -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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче