Bug 602757. Part 2: Detect display items over the transparent part of a window, and disable usage of component alpha (i.e., subpixel antialiasing) for those items. r=tnikkel,a=blocking

This commit is contained in:
Robert O'Callahan 2011-01-03 14:48:09 +13:00
Родитель 64c483c0b7
Коммит b81ded8225
6 изменённых файлов: 73 добавлений и 9 удалений

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

@ -895,6 +895,29 @@ ContainerState::PopThebesLayerData()
mThebesLayerDataStack.RemoveElementAt(lastIndex);
}
static PRBool
SuppressComponentAlpha(nsDisplayListBuilder* aBuilder,
nsDisplayItem* aItem)
{
const nsRegion* windowTransparentRegion = aBuilder->GetFinalTransparentRegion();
if (!windowTransparentRegion || windowTransparentRegion->IsEmpty())
return PR_FALSE;
// Suppress component alpha for items in the toplevel window that are over
// the window translucent area
nsIFrame* f = aItem->GetUnderlyingFrame();
nsIFrame* ref = aBuilder->ReferenceFrame();
if (f->PresContext() != ref->PresContext())
return PR_FALSE;
for (nsIFrame* t = f; t; t = t->GetParent()) {
if (t->IsTransformed())
return PR_FALSE;
}
return windowTransparentRegion->Intersects(aItem->GetBounds(aBuilder));
}
void
ContainerState::ThebesLayerData::Accumulate(nsDisplayListBuilder* aBuilder,
nsDisplayItem* aItem,
@ -937,7 +960,11 @@ ContainerState::ThebesLayerData::Accumulate(nsDisplayListBuilder* aBuilder,
}
} else if (aItem->HasText()) {
if (!mOpaqueRegion.Contains(aVisibleRect)) {
mNeedComponentAlpha = PR_TRUE;
if (SuppressComponentAlpha(aBuilder, aItem)) {
aItem->DisableComponentAlpha();
} else {
mNeedComponentAlpha = PR_TRUE;
}
}
}
mForceTransparentSurface = mForceTransparentSurface || forceTransparentSurface;

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

@ -73,6 +73,7 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame,
: mReferenceFrame(aReferenceFrame),
mIgnoreScrollFrame(nsnull),
mCurrentTableItem(nsnull),
mFinalTransparentRegion(nsnull),
mMode(aMode),
mBuildCaret(aBuildCaret),
mIgnoreSuppression(PR_FALSE),

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

@ -338,6 +338,19 @@ public:
*/
FrameLayerBuilder* LayerBuilder() { return &mLayerBuilder; }
/**
* Get the area of the final transparent region.
*/
const nsRegion* GetFinalTransparentRegion() { return mFinalTransparentRegion; }
/**
* Record the area of the final transparent region after all visibility
* calculations were performed.
*/
void SetFinalTransparentRegion(const nsRegion& aFinalTransparentRegion)
{
mFinalTransparentRegion = &aFinalTransparentRegion;
}
/**
* Returns true if we need to descend into this frame when building
* the display list, even though it doesn't intersect the dirty
@ -422,6 +435,7 @@ private:
nsAutoTArray<PresShellState,8> mPresShellStates;
nsAutoTArray<nsIFrame*,100> mFramesMarkedForDisplay;
nsDisplayTableItem* mCurrentTableItem;
const nsRegion* mFinalTransparentRegion;
Mode mMode;
PRPackedBool mBuildCaret;
PRPackedBool mIgnoreSuppression;
@ -702,6 +716,11 @@ public:
*/
virtual PRBool HasText() { return PR_FALSE; }
/**
* Disable usage of component alpha. Currently only relevant for items that have text.
*/
virtual void DisableComponentAlpha() {}
protected:
friend class nsDisplayList;

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

@ -1409,11 +1409,8 @@ nsLayoutUtils::PaintFrame(nsIRenderingContext* aRenderingContext, nsIFrame* aFra
PRUint32 flags = nsDisplayList::PAINT_DEFAULT;
if (aFlags & PAINT_WIDGET_LAYERS) {
flags |= nsDisplayList::PAINT_USE_WIDGET_LAYERS;
nsIWidget *widget = aFrame->GetNearestWidget();
PRInt32 pixelRatio = presContext->AppUnitsPerDevPixel();
nsIntRegion visibleWindowRegion(visibleRegion.ToOutsidePixels(pixelRatio));
nsIntRegion dirtyWindowRegion(aDirtyRegion.ToOutsidePixels(pixelRatio));
nsIWidget *widget = aFrame->GetNearestWidget();
if (willFlushRetainedLayers) {
// The caller wanted to paint from retained layers, but set up
// the paint in such a way that we can't use them. We're going
@ -1426,6 +1423,10 @@ nsLayoutUtils::PaintFrame(nsIRenderingContext* aRenderingContext, nsIFrame* aFra
} else if (widget && !(aFlags & PAINT_DOCUMENT_RELATIVE)) {
// XXX we should simplify this API now that dirtyWindowRegion always
// covers the entire window
PRInt32 pixelRatio = presContext->AppUnitsPerDevPixel();
nsIntRegion visibleWindowRegion(visibleRegion.ToOutsidePixels(pixelRatio));
nsIntRegion dirtyWindowRegion(aDirtyRegion.ToOutsidePixels(pixelRatio));
builder.SetFinalTransparentRegion(visibleRegion);
widget->UpdatePossiblyTransparentRegion(dirtyWindowRegion, visibleWindowRegion);
}
}

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

@ -4039,7 +4039,8 @@ nsTextFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
class nsDisplayText : public nsDisplayItem {
public:
nsDisplayText(nsDisplayListBuilder* aBuilder, nsTextFrame* aFrame) :
nsDisplayItem(aBuilder, aFrame) {
nsDisplayItem(aBuilder, aFrame),
mDisableSubpixelAA(PR_FALSE) {
MOZ_COUNT_CTOR(nsDisplayText);
}
#ifdef NS_BUILD_REFCNT_LOGGING
@ -4062,6 +4063,10 @@ public:
NS_DISPLAY_DECL_NAME("Text", TYPE_TEXT)
virtual PRBool HasText() { return PR_TRUE; }
virtual void DisableComponentAlpha() { mDisableSubpixelAA = PR_TRUE; }
PRPackedBool mDisableSubpixelAA;
};
void
@ -4073,8 +4078,11 @@ nsDisplayText::Paint(nsDisplayListBuilder* aBuilder,
nsRect extraVisible = mVisibleRect;
nscoord appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
extraVisible.Inflate(appUnitsPerDevPixel, appUnitsPerDevPixel);
static_cast<nsTextFrame*>(mFrame)->
PaintText(aCtx, ToReferenceFrame(), extraVisible);
nsTextFrame* f = static_cast<nsTextFrame*>(mFrame);
gfxContextAutoDisableSubpixelAntialiasing disable(aCtx->ThebesContext(),
mDisableSubpixelAA);
f->PaintText(aCtx, ToReferenceFrame(), extraVisible);
}
NS_IMETHODIMP

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

@ -333,7 +333,9 @@ class nsDisplayXULTextBox : public nsDisplayItem {
public:
nsDisplayXULTextBox(nsDisplayListBuilder* aBuilder,
nsTextBoxFrame* aFrame) :
nsDisplayItem(aBuilder, aFrame) {
nsDisplayItem(aBuilder, aFrame),
mDisableSubpixelAA(PR_FALSE)
{
MOZ_COUNT_CTOR(nsDisplayXULTextBox);
}
#ifdef NS_BUILD_REFCNT_LOGGING
@ -348,12 +350,18 @@ public:
NS_DISPLAY_DECL_NAME("XULTextBox", TYPE_XUL_TEXT_BOX)
virtual PRBool HasText() { return PR_TRUE; }
virtual void DisableComponentAlpha() { mDisableSubpixelAA = PR_TRUE; }
PRPackedBool mDisableSubpixelAA;
};
void
nsDisplayXULTextBox::Paint(nsDisplayListBuilder* aBuilder,
nsIRenderingContext* aCtx)
{
gfxContextAutoDisableSubpixelAntialiasing disable(aCtx->ThebesContext(),
mDisableSubpixelAA);
static_cast<nsTextBoxFrame*>(mFrame)->
PaintTitle(*aCtx, mVisibleRect, ToReferenceFrame());
}