Bug 733607. Restructure logic to compute snapped bounds of display items in layer coordinates. Moves responsibility for computing snapped bounds from within the display items to callers of GetBounds/GetOpaqueRegion. r=tnikkel

Previously we snapped the results of nsDisplayItem::GetBounds and
nsDisplayItem::GetOpaqueRegion internally. By tracking which display items were
inside transforms, we disabled snapping quite conservatively whenever an ancestor
had a transform, which is undesirable.

With this patch, we don't snap inside GetBounds or GetOpaqueRegion, but just return
a boolean flag indicating whether the item will draw with snapping or not. This flag
is conservative so that "true" means we will snap (if the graphics context has a transform
that allows snapping), but "false" means we might or might not snap (so it's always safe
to return false).

FrameLayerBuilder takes over responsibility for snapping item bounds. When it converts
display item bounds to layer pixel coordinates, it checks the snap flag returned from
the display item and checks whether the transform when we draw into the layer will be
a known scale (the ContainerParameters scale factors) plus integer translation. If both
are true, we snap the item bounds when converting to layer pixel coordinates. With
this approach, we can snap item bounds even when the items have ancestors with active
transforms.
This commit is contained in:
Robert O'Callahan 2012-04-10 23:24:18 +12:00
parent a3c84c2617
commit 833e8a244f
25 changed files with 301 additions and 246 deletions

View File

@ -145,6 +145,13 @@ public:
mNextFreeRecycledThebesLayer(0), mNextFreeRecycledColorLayer(0),
mNextFreeRecycledImageLayer(0), mInvalidateAllThebesContent(false)
{
nsPresContext* presContext = aContainerFrame->PresContext();
mAppUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
// When AllowResidualTranslation is false, display items will be drawn
// scaled with a translation by integer pixels, so we know how the snapping
// will work.
mSnappingEnabled = aManager->IsSnappingEffectiveTransforms() &&
!mParameters.AllowResidualTranslation();
CollectOldLayers();
}
@ -176,6 +183,30 @@ public:
nsRect GetChildrenBounds() { return mBounds; }
nscoord GetAppUnitsPerDevPixel() { return mAppUnitsPerDevPixel; }
nsIntRect ScaleToNearestPixels(const nsRect& aRect)
{
return aRect.ScaleToNearestPixels(mParameters.mXScale, mParameters.mYScale,
mAppUnitsPerDevPixel);
}
nsIntRect ScaleToOutsidePixels(const nsRect& aRect, bool aSnap)
{
if (aSnap && mSnappingEnabled) {
return ScaleToNearestPixels(aRect);
}
return aRect.ScaleToOutsidePixels(mParameters.mXScale, mParameters.mYScale,
mAppUnitsPerDevPixel);
}
nsIntRect ScaleToInsidePixels(const nsRect& aRect, bool aSnap)
{
if (aSnap && mSnappingEnabled) {
return ScaleToNearestPixels(aRect);
}
return aRect.ScaleToInsidePixels(mParameters.mXScale, mParameters.mYScale,
mAppUnitsPerDevPixel);
}
protected:
/**
* We keep a stack of these to represent the ThebesLayers that are
@ -391,7 +422,9 @@ protected:
PRUint32 mNextFreeRecycledThebesLayer;
PRUint32 mNextFreeRecycledColorLayer;
PRUint32 mNextFreeRecycledImageLayer;
nscoord mAppUnitsPerDevPixel;
bool mInvalidateAllThebesContent;
bool mSnappingEnabled;
};
class ThebesDisplayItemLayerUserData : public LayerUserData
@ -851,11 +884,7 @@ ContainerState::CreateOrRecycleThebesLayer(nsIFrame* aActiveScrolledRoot)
}
data->mXScale = mParameters.mXScale;
data->mYScale = mParameters.mYScale;
// If we're in a transformed subtree, but no ancestor transform is actively
// changing, we'll use the residual translation when drawing into the
// ThebesLayer to ensure that snapping exactly matches the ideal transform.
layer->SetAllowResidualTranslation(
mParameters.mInTransformedSubtree && !mParameters.mInActiveTransformedSubtree);
layer->SetAllowResidualTranslation(mParameters.AllowResidualTranslation());
mBuilder->LayerBuilder()->SaveLastPaintOffset(layer);
@ -960,10 +989,8 @@ ContainerState::FindOpaqueBackgroundColorFor(PRInt32 aThebesLayerIndex)
// The candidate intersects our target. If any layer has a solid-color
// area behind our target, this must be it. Scan its display items.
nsPresContext* presContext = mContainerFrame->PresContext();
nscoord appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
nsRect rect =
target->mVisibleRegion.GetBounds().ToAppUnits(appUnitsPerDevPixel);
target->mVisibleRegion.GetBounds().ToAppUnits(mAppUnitsPerDevPixel);
rect.ScaleInverseRoundOut(mParameters.mXScale, mParameters.mYScale);
return mBuilder->LayerBuilder()->
FindOpaqueColorCovering(mBuilder, candidate->mLayer, rect);
@ -1009,10 +1036,7 @@ ContainerState::PopThebesLayerData()
NS_ASSERTION(data->mImageClip.mRoundedClipRects.IsEmpty(),
"How did we get rounded clip rects here?");
if (data->mImageClip.mHaveClipRect) {
nsPresContext* presContext = mContainerFrame->PresContext();
nscoord appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
nsIntRect clip = data->mImageClip.mClipRect.ScaleToNearestPixels(
mParameters.mXScale, mParameters.mYScale, appUnitsPerDevPixel);
nsIntRect clip = ScaleToNearestPixels(data->mImageClip.mClipRect);
imageLayer->IntersectClipRect(clip);
}
layer = imageLayer;
@ -1178,10 +1202,17 @@ ContainerState::ThebesLayerData::Accumulate(ContainerState* aState,
// below) but don't draw anything. They'll return true for isUniform but
// a color with opacity 0.
if (!isUniform || NS_GET_A(uniformColor) > 0) {
if (isUniform &&
aItem->GetBounds(aState->mBuilder).ScaleToInsidePixels(
aState->mParameters.mXScale, aState->mParameters.mYScale,
AppUnitsPerDevPixel(aItem)).Contains(aVisibleRect)) {
// Make sure that the visible area is covered by uniform pixels. In
// particular this excludes cases where the edges of the item are not
// pixel-aligned (thus the item will not be truly uniform).
if (isUniform) {
bool snap;
nsRect bounds = aItem->GetBounds(aState->mBuilder, &snap);
if (!aState->ScaleToInsidePixels(bounds, snap).Contains(aVisibleRect)) {
isUniform = false;
}
}
if (isUniform) {
if (mVisibleRegion.IsEmpty()) {
// This color is all we have
mSolidColor = uniformColor;
@ -1203,20 +1234,20 @@ ContainerState::ThebesLayerData::Accumulate(ContainerState* aState,
mDrawRegion.SimplifyOutward(4);
}
bool forceTransparentSurface = false;
nsRegion opaque = aItem->GetOpaqueRegion(aState->mBuilder, &forceTransparentSurface);
bool forceTransparentSurface;
bool snap;
nsRegion opaque = aItem->GetOpaqueRegion(aState->mBuilder, &snap,
&forceTransparentSurface);
if (!opaque.IsEmpty()) {
nsRegionRectIterator iter(opaque);
nscoord appUnitsPerDevPixel = AppUnitsPerDevPixel(aItem);
for (const nsRect* r = iter.Next(); r; r = iter.Next()) {
// We don't use SimplifyInward here since it's not defined exactly
// what it will discard. For our purposes the most important case
// is a large opaque background at the bottom of z-order (e.g.,
// a canvas background), so we need to make sure that the first rect
// we see doesn't get discarded.
nsIntRect rect = aClip.ApproximateIntersect(*r).ScaleToInsidePixels(
aState->mParameters.mXScale, aState->mParameters.mYScale,
appUnitsPerDevPixel);
nsIntRect rect =
aState->ScaleToInsidePixels(aClip.ApproximateIntersect(*r), snap);
nsIntRegion tmp;
tmp.Or(mOpaqueRegion, rect);
// Opaque display items in chrome documents whose window is partially
@ -1237,11 +1268,10 @@ ContainerState::ThebesLayerData::Accumulate(ContainerState* aState,
aItem->DisableComponentAlpha();
} else {
nsRect componentAlpha = aItem->GetComponentAlphaBounds(aState->mBuilder);
componentAlpha.IntersectRect(componentAlpha, aItem->GetVisibleRect());
if (!componentAlpha.IsEmpty()) {
nscoord appUnitsPerDevPixel = AppUnitsPerDevPixel(aItem);
if (!mOpaqueRegion.Contains(componentAlpha.ScaleToOutsidePixels(
aState->mParameters.mXScale, aState->mParameters.mYScale, appUnitsPerDevPixel))) {
nsIntRect componentAlphaRect =
aState->ScaleToOutsidePixels(componentAlpha, false).Intersect(aVisibleRect);
if (!mOpaqueRegion.Contains(componentAlphaRect)) {
if (SuppressComponentAlpha(aState->mBuilder, aItem, componentAlpha)) {
aItem->DisableComponentAlpha();
} else {
@ -1398,9 +1428,6 @@ void
ContainerState::ProcessDisplayItems(const nsDisplayList& aList,
FrameLayerBuilder::Clip& aClip)
{
PRInt32 appUnitsPerDevPixel =
mContainerFrame->PresContext()->AppUnitsPerDevPixel();
for (nsDisplayItem* item = aList.GetBottom(); item; item = item->GetAbove()) {
nsDisplayItem::Type type = item->GetType();
if (type == nsDisplayItem::TYPE_CLIP ||
@ -1410,19 +1437,20 @@ ContainerState::ProcessDisplayItems(const nsDisplayList& aList,
continue;
}
NS_ASSERTION(appUnitsPerDevPixel == AppUnitsPerDevPixel(item),
NS_ASSERTION(mAppUnitsPerDevPixel == AppUnitsPerDevPixel(item),
"items in a container layer should all have the same app units per dev pixel");
nsIntRect itemVisibleRect =
item->GetVisibleRect().ScaleToOutsidePixels(
mParameters.mXScale, mParameters.mYScale, appUnitsPerDevPixel);
nsRect itemContent = item->GetBounds(mBuilder);
ScaleToOutsidePixels(item->GetVisibleRect(), false);
bool snap;
nsRect itemContent = item->GetBounds(mBuilder, &snap);
if (aClip.mHaveClipRect) {
itemContent.IntersectRect(aClip.mClipRect, itemContent);
}
mBounds.UnionRect(mBounds, itemContent);
nsIntRect itemDrawRect = itemContent.ScaleToOutsidePixels(
mParameters.mXScale, mParameters.mYScale, appUnitsPerDevPixel);
nsIntRect itemDrawRect = ScaleToOutsidePixels(itemContent, snap);
itemVisibleRect.IntersectRect(itemVisibleRect, itemDrawRect);
LayerState layerState = item->GetLayerState(mBuilder, mManager);
nsIFrame* activeScrolledRoot =
@ -1481,8 +1509,7 @@ ContainerState::ProcessDisplayItems(const nsDisplayList& aList,
// It has its own layer. Update that layer's clip and visible rects.
if (aClip.mHaveClipRect) {
ownLayer->IntersectClipRect(
aClip.NonRoundedIntersection().ScaleToNearestPixels(
mParameters.mXScale, mParameters.mYScale, appUnitsPerDevPixel));
ScaleToNearestPixels(aClip.NonRoundedIntersection()));
}
ThebesLayerData* data = GetTopThebesLayerData();
if (data) {
@ -1542,8 +1569,8 @@ ContainerState::InvalidateForLayerChange(nsDisplayItem* aItem, Layer* aNewLayer)
// The bounds might have changed, but we assume that any difference
// in the bounds will have been invalidated for all Thebes layers
// in the container via regular frame invalidation.
nsRect bounds = aItem->GetBounds(mBuilder);
PRInt32 appUnitsPerDevPixel = AppUnitsPerDevPixel(aItem);
bool snap;
nsRect bounds = aItem->GetBounds(mBuilder, &snap);
ThebesLayer* t = oldLayer->AsThebesLayer();
if (t) {
@ -1553,7 +1580,7 @@ ContainerState::InvalidateForLayerChange(nsDisplayItem* aItem, Layer* aNewLayer)
// so it doesn't matter whether we are using the old scale at last paint
// or a new scale here
InvalidatePostTransformRegion(t,
bounds.ScaleToOutsidePixels(data->mXScale, data->mYScale, appUnitsPerDevPixel),
bounds.ScaleToOutsidePixels(data->mXScale, data->mYScale, mAppUnitsPerDevPixel),
mBuilder->LayerBuilder()->GetLastPaintOffset(t));
}
if (aNewLayer) {
@ -1562,14 +1589,11 @@ ContainerState::InvalidateForLayerChange(nsDisplayItem* aItem, Layer* aNewLayer)
ThebesDisplayItemLayerUserData* data =
static_cast<ThebesDisplayItemLayerUserData*>(newLayer->GetUserData(&gThebesDisplayItemLayerUserData));
InvalidatePostTransformRegion(newLayer,
bounds.ScaleToOutsidePixels(data->mXScale, data->mYScale, appUnitsPerDevPixel),
bounds.ScaleToOutsidePixels(data->mXScale, data->mYScale, mAppUnitsPerDevPixel),
GetTranslationForThebesLayer(newLayer));
}
}
NS_ASSERTION(appUnitsPerDevPixel ==
mContainerFrame->PresContext()->AppUnitsPerDevPixel(),
"app units per dev pixel should be constant in a container");
mContainerFrame->InvalidateWithFlags(
bounds - mBuilder->ToReferenceFrame(mContainerFrame),
nsIFrame::INVALIDATE_NO_THEBES_LAYERS |
@ -1860,7 +1884,6 @@ FrameLayerBuilder::BuildContainerLayerFor(nsDisplayListBuilder* aBuilder,
containerLayer);
ContainerState state(aBuilder, aManager, aContainerFrame, containerLayer,
scaleParameters);
nscoord appUnitsPerDevPixel = aContainerFrame->PresContext()->AppUnitsPerDevPixel();
if (aManager == mRetainingManager) {
DisplayItemDataEntry* entry = mNewDisplayItemData.PutEntry(aContainerFrame);
@ -1880,7 +1903,7 @@ FrameLayerBuilder::BuildContainerLayerFor(nsDisplayListBuilder* aBuilder,
invalidThebesContent->MoveBy(offset);
state.SetInvalidThebesContent(invalidThebesContent->
ScaleToOutsidePixels(scaleParameters.mXScale, scaleParameters.mYScale,
appUnitsPerDevPixel));
state.GetAppUnitsPerDevPixel()));
// We have to preserve the current contents of invalidThebesContent
// because there might be multiple container layers for the same
// frame and we need to invalidate the ThebesLayer children of all
@ -1905,15 +1928,13 @@ FrameLayerBuilder::BuildContainerLayerFor(nsDisplayListBuilder* aBuilder,
nsRect bounds = state.GetChildrenBounds();
NS_ASSERTION(bounds.IsEqualInterior(aChildren.GetBounds(aBuilder)), "Wrong bounds");
nsIntRect pixBounds =
bounds.ScaleToOutsidePixels(scaleParameters.mXScale, scaleParameters.mYScale,
appUnitsPerDevPixel);
nsIntRect pixBounds = state.ScaleToOutsidePixels(bounds, false);
containerLayer->SetVisibleRegion(pixBounds);
// Make sure that rounding the visible region out didn't add any area
// we won't paint
if (aChildren.IsOpaque() && !aChildren.NeedsTransparentSurface()) {
bounds.ScaleRoundIn(scaleParameters.mXScale, scaleParameters.mYScale);
if (bounds.Contains(pixBounds.ToAppUnits(appUnitsPerDevPixel))) {
if (bounds.Contains(pixBounds.ToAppUnits(state.GetAppUnitsPerDevPixel()))) {
// Clear CONTENT_COMPONENT_ALPHA
flags = Layer::CONTENT_OPAQUE;
}
@ -2046,7 +2067,8 @@ FrameLayerBuilder::GetDedicatedLayer(nsIFrame* aFrame, PRUint32 aDisplayItemKey)
#ifdef MOZ_DUMP_PAINTING
static void DebugPaintItem(nsRenderingContext* aDest, nsDisplayItem *aItem, nsDisplayListBuilder* aBuilder)
{
nsRect appUnitBounds = aItem->GetBounds(aBuilder);
bool snap;
nsRect appUnitBounds = aItem->GetBounds(aBuilder, &snap);
gfxRect bounds(appUnitBounds.x, appUnitBounds.y, appUnitBounds.width, appUnitBounds.height);
bounds.ScaleInverse(aDest->AppUnitsPerDevPixel());

View File

@ -163,6 +163,17 @@ public:
bool mInTransformedSubtree;
bool mInActiveTransformedSubtree;
bool mDisableSubpixelAntialiasingInDescendants;
/**
* When this is false, ThebesLayer coordinates are drawn to with an integer
* translation and the scale in mXScale/mYScale.
*/
bool AllowResidualTranslation()
{
// If we're in a transformed subtree, but no ancestor transform is actively
// changing, we'll use the residual translation when drawing into the
// ThebesLayer to ensure that snapping exactly matches the ideal transform.
return mInTransformedSubtree && !mInActiveTransformedSubtree;
}
};
/**
* Build a container layer for a display item that contains a child

View File

@ -88,7 +88,6 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame,
mInTransform(false),
mSyncDecodeImages(false),
mIsPaintingToWindow(false),
mSnappingEnabled(mMode != EVENT_DELIVERY),
mHasDisplayPort(false),
mHasFixedItems(false)
{
@ -415,7 +414,8 @@ nsRect
nsDisplayList::GetBounds(nsDisplayListBuilder* aBuilder) const {
nsRect bounds;
for (nsDisplayItem* i = GetBottom(); i != nsnull; i = i->GetAbove()) {
bounds.UnionRect(bounds, i->GetBounds(aBuilder));
bool snap;
bounds.UnionRect(bounds, i->GetBounds(aBuilder, &snap));
}
return bounds;
}
@ -432,7 +432,8 @@ static nsRegion
TreatAsOpaque(nsDisplayItem* aItem, nsDisplayListBuilder* aBuilder,
bool* aTransparentBackground)
{
nsRegion opaque = aItem->GetOpaqueRegion(aBuilder, aTransparentBackground);
bool snap;
nsRegion opaque = aItem->GetOpaqueRegion(aBuilder, &snap, aTransparentBackground);
if (aBuilder->IsForPluginGeometry()) {
// Treat all chrome items as opaque, unless their frames are opacity:0.
// Since opacity:0 frames generate an nsDisplayOpacity, that item will
@ -440,7 +441,7 @@ TreatAsOpaque(nsDisplayItem* aItem, nsDisplayListBuilder* aBuilder,
// effectively ignored, as it should be.
nsIFrame* f = aItem->GetUnderlyingFrame();
if (f && f->PresContext()->IsChrome() && f->GetStyleDisplay()->mOpacity != 0.0) {
opaque = aItem->GetBounds(aBuilder);
opaque = aItem->GetBounds(aBuilder, &snap);
}
}
return opaque;
@ -473,6 +474,7 @@ nsDisplayList::ComputeVisibilityForSublist(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion,
const nsRect& aListVisibleBounds,
const nsRect& aAllowVisibleRegionExpansion) {
bool snap;
#ifdef DEBUG
nsRegion r;
r.And(*aVisibleRegion, GetBounds(aBuilder));
@ -507,7 +509,7 @@ nsDisplayList::ComputeVisibilityForSublist(nsDisplayListBuilder* aBuilder,
continue;
}
nsRect bounds = item->GetBounds(aBuilder);
nsRect bounds = item->GetBounds(aBuilder, &snap);
nsRegion itemVisible;
if (ForceVisiblityForFixedItem(aBuilder, item)) {
@ -742,7 +744,8 @@ void nsDisplayList::HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
item = aState->mItemBuffer[i];
aState->mItemBuffer.SetLength(i);
if (aRect.Intersects(item->GetBounds(aBuilder))) {
bool snap;
if (aRect.Intersects(item->GetBounds(aBuilder, &snap))) {
nsAutoTArray<nsIFrame*, 16> outFrames;
item->HitTest(aBuilder, aRect, aState, &outFrames);
@ -895,7 +898,8 @@ void nsDisplayList::Sort(nsDisplayListBuilder* aBuilder,
bool nsDisplayItem::RecomputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion) {
nsRect bounds = GetBounds(aBuilder);
bool snap;
nsRect bounds = GetBounds(aBuilder, &snap);
nsRegion itemVisible;
if (ForceVisiblityForFixedItem(aBuilder, this)) {
@ -917,26 +921,11 @@ bool nsDisplayItem::RecomputeVisibility(nsDisplayListBuilder* aBuilder,
return true;
}
// Note that even if the rectangle we draw and snap is smaller than aRect,
// it's OK to call this to get a bounding rect for what we'll draw, because
// snapping a rectangle which is contained in R always gives you a
// rectangle which is contained in the snapped R.
static nsRect
SnapBounds(bool aSnappingEnabled, nsPresContext* aPresContext,
const nsRect& aRect) {
nsRect r = aRect;
if (aSnappingEnabled) {
nscoord appUnitsPerDevPixel = aPresContext->AppUnitsPerDevPixel();
r = r.ToNearestPixels(appUnitsPerDevPixel).ToAppUnits(appUnitsPerDevPixel);
}
return r;
}
nsRect
nsDisplaySolidColor::GetBounds(nsDisplayListBuilder* aBuilder)
nsDisplaySolidColor::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap)
{
nsPresContext* presContext = mFrame->PresContext();
return SnapBounds(mSnappingEnabled, presContext, mBounds);
*aSnap = true;
return mBounds;
}
void
@ -968,8 +957,7 @@ RegisterThemeGeometry(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
nsDisplayBackground::nsDisplayBackground(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame)
: nsDisplayItem(aBuilder, aFrame),
mSnappingEnabled(aBuilder->IsSnappingEnabled() && !aBuilder->IsInTransform())
: nsDisplayItem(aBuilder, aFrame)
{
MOZ_COUNT_CTOR(nsDisplayBackground);
const nsStyleDisplay* disp = mFrame->GetStyleDisplay();
@ -1126,7 +1114,8 @@ nsDisplayBackground::ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion
nsDisplayBackground::GetInsideClipRegion(nsPresContext* aPresContext,
PRUint8 aClip, const nsRect& aRect)
PRUint8 aClip, const nsRect& aRect,
bool* aSnap)
{
nsRegion result;
if (aRect.IsEmpty())
@ -1153,14 +1142,12 @@ nsDisplayBackground::GetInsideClipRegion(nsPresContext* aPresContext,
return result;
}
nsRect inputRect = SnapBounds(mSnappingEnabled, aPresContext, aRect);
clipRect = SnapBounds(mSnappingEnabled, aPresContext, clipRect);
if (haveRadii) {
result = nsLayoutUtils::RoundedRectIntersectRect(clipRect, radii, inputRect);
*aSnap = false;
result = nsLayoutUtils::RoundedRectIntersectRect(clipRect, radii, aRect);
} else {
nsRect r;
r.IntersectRect(clipRect, inputRect);
r.IntersectRect(clipRect, aRect);
result = r;
}
return result;
@ -1168,11 +1155,11 @@ nsDisplayBackground::GetInsideClipRegion(nsPresContext* aPresContext,
nsRegion
nsDisplayBackground::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
bool* aSnap,
bool* aForceTransparentSurface) {
nsRegion result;
if (aForceTransparentSurface) {
*aForceTransparentSurface = false;
}
*aSnap = false;
*aForceTransparentSurface = false;
// theme background overrides any other background
if (mIsThemed) {
if (aForceTransparentSurface) {
@ -1181,7 +1168,7 @@ nsDisplayBackground::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
disp->mAppearance == NS_THEME_WIN_GLASS;
}
if (mThemeTransparency == nsITheme::eOpaque) {
result = GetBounds(aBuilder);
result = GetBounds(aBuilder, aSnap);
}
return result;
}
@ -1193,10 +1180,12 @@ nsDisplayBackground::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
const nsStyleBackground* bg = bgSC->GetStyleBackground();
const nsStyleBackground::Layer& bottomLayer = bg->BottomLayer();
*aSnap = true;
nsRect borderBox = nsRect(ToReferenceFrame(), mFrame->GetSize());
if (NS_GET_A(bg->mBackgroundColor) == 255 &&
!nsCSSRendering::IsCanvasFrame(mFrame)) {
result = GetInsideClipRegion(presContext, bottomLayer.mClip, borderBox);
result = GetInsideClipRegion(presContext, bottomLayer.mClip, borderBox, aSnap);
}
// For policies other than EACH_BOX, don't try to optimize here, since
@ -1211,7 +1200,7 @@ nsDisplayBackground::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
if (layer.mImage.IsOpaque()) {
nsRect r = nsCSSRendering::GetBackgroundLayerRect(presContext, mFrame,
borderBox, *bg, layer);
result.Or(result, GetInsideClipRegion(presContext, layer.mClip, r));
result.Or(result, GetInsideClipRegion(presContext, layer.mClip, r, aSnap));
}
}
}
@ -1310,7 +1299,8 @@ nsDisplayBackground::ShouldFixToViewport(nsDisplayListBuilder* aBuilder)
if (nsLayoutUtils::HasNonZeroCorner(mFrame->GetStyleBorder()->mBorderRadius))
return false;
nsRect bounds = GetBounds(aBuilder);
bool snap;
nsRect bounds = GetBounds(aBuilder, &snap);
nsIFrame* rootScrollFrame = presContext->PresShell()->GetRootScrollFrame();
if (!rootScrollFrame)
return false;
@ -1337,7 +1327,7 @@ nsDisplayBackground::Paint(nsDisplayListBuilder* aBuilder,
}
nsRect
nsDisplayBackground::GetBounds(nsDisplayListBuilder* aBuilder) {
nsDisplayBackground::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) {
nsRect r(nsPoint(0,0), mFrame->GetSize());
nsPresContext* presContext = mFrame->PresContext();
@ -1347,11 +1337,13 @@ nsDisplayBackground::GetBounds(nsDisplayListBuilder* aBuilder) {
mFrame->GetStyleDisplay()->mAppearance, &r);
}
return SnapBounds(mSnappingEnabled, presContext, r + ToReferenceFrame());
*aSnap = true;
return r + ToReferenceFrame();
}
nsRect
nsDisplayOutline::GetBounds(nsDisplayListBuilder* aBuilder) {
nsDisplayOutline::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) {
*aSnap = false;
return mFrame->GetVisualOverflowRectRelativeToSelf() + ToReferenceFrame();
}
@ -1450,11 +1442,12 @@ nsDisplayBorder::Paint(nsDisplayListBuilder* aBuilder,
}
nsRect
nsDisplayBorder::GetBounds(nsDisplayListBuilder* aBuilder)
nsDisplayBorder::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap)
{
nsRect borderBounds(ToReferenceFrame(), mFrame->GetSize());
borderBounds.Inflate(mFrame->GetStyleBorder()->GetImageOutset());
return SnapBounds(mSnappingEnabled, mFrame->PresContext(), borderBounds);
*aSnap = true;
return borderBounds;
}
// Given a region, compute a conservative approximation to it as a list
@ -1507,7 +1500,8 @@ nsDisplayBoxShadowOuter::Paint(nsDisplayListBuilder* aBuilder,
}
nsRect
nsDisplayBoxShadowOuter::GetBounds(nsDisplayListBuilder* aBuilder) {
nsDisplayBoxShadowOuter::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) {
*aSnap = false;
return mFrame->GetVisualOverflowRectRelativeToSelf() + ToReferenceFrame();
}
@ -1599,7 +1593,8 @@ nsDisplayWrapList::HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
}
nsRect
nsDisplayWrapList::GetBounds(nsDisplayListBuilder* aBuilder) {
nsDisplayWrapList::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) {
*aSnap = false;
return mList.GetBounds(aBuilder);
}
@ -1614,13 +1609,13 @@ nsDisplayWrapList::ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion
nsDisplayWrapList::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
bool* aSnap,
bool* aForceTransparentSurface) {
if (aForceTransparentSurface) {
*aForceTransparentSurface = false;
}
*aForceTransparentSurface = false;
*aSnap = false;
nsRegion result;
if (mList.IsOpaque()) {
result = GetBounds(aBuilder);
result = GetBounds(aBuilder, aSnap);
}
return result;
}
@ -1760,10 +1755,10 @@ nsDisplayOpacity::~nsDisplayOpacity() {
#endif
nsRegion nsDisplayOpacity::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
bool* aSnap,
bool* aForceTransparentSurface) {
if (aForceTransparentSurface) {
*aForceTransparentSurface = false;
}
*aForceTransparentSurface = false;
*aSnap = false;
// We are never opaque, if our opacity was < 1 then we wouldn't have
// been created.
return nsRegion();
@ -1820,7 +1815,8 @@ nsDisplayOpacity::ComputeVisibility(nsDisplayListBuilder* aBuilder,
// our children in the temporary compositing buffer, because if our children
// paint our entire bounds opaquely then we don't need an alpha channel in
// the temporary compositing buffer.
nsRect bounds = GetBounds(aBuilder);
bool snap;
nsRect bounds = GetBounds(aBuilder, &snap);
nsRegion visibleUnderChildren;
visibleUnderChildren.And(*aVisibleRegion, bounds);
nsRect allowExpansion;
@ -2095,23 +2091,20 @@ nsDisplayScrollInfoLayer::ShouldFlattenAway(nsDisplayListBuilder* aBuilder)
nsDisplayClip::nsDisplayClip(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame, nsDisplayItem* aItem,
const nsRect& aRect)
: nsDisplayWrapList(aBuilder, aFrame, aItem) {
: nsDisplayWrapList(aBuilder, aFrame, aItem), mClip(aRect) {
MOZ_COUNT_CTOR(nsDisplayClip);
mClip = SnapBounds(aBuilder->IsSnappingEnabled() && !aBuilder->IsInTransform(),
aBuilder->CurrentPresContext(), aRect);
}
nsDisplayClip::nsDisplayClip(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame, nsDisplayList* aList,
const nsRect& aRect)
: nsDisplayWrapList(aBuilder, aFrame, aList) {
: nsDisplayWrapList(aBuilder, aFrame, aList), mClip(aRect) {
MOZ_COUNT_CTOR(nsDisplayClip);
mClip = SnapBounds(aBuilder->IsSnappingEnabled() && !aBuilder->IsInTransform(),
aBuilder->CurrentPresContext(), aRect);
}
nsRect nsDisplayClip::GetBounds(nsDisplayListBuilder* aBuilder) {
nsRect r = nsDisplayWrapList::GetBounds(aBuilder);
nsRect nsDisplayClip::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) {
nsRect r = nsDisplayWrapList::GetBounds(aBuilder, aSnap);
*aSnap = true;
r.IntersectRect(mClip, r);
return r;
}
@ -2193,11 +2186,11 @@ nsDisplayClipRoundedRect::~nsDisplayClipRoundedRect()
nsRegion
nsDisplayClipRoundedRect::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
bool* aSnap,
bool* aForceTransparentSurface)
{
if (aForceTransparentSurface) {
*aForceTransparentSurface = false;
}
*aSnap = false;
*aForceTransparentSurface = false;
return nsRegion();
}
@ -2267,9 +2260,10 @@ nsDisplayZoom::~nsDisplayZoom() {
}
#endif
nsRect nsDisplayZoom::GetBounds(nsDisplayListBuilder* aBuilder)
nsRect nsDisplayZoom::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap)
{
nsRect bounds = nsDisplayWrapList::GetBounds(aBuilder);
nsRect bounds = nsDisplayWrapList::GetBounds(aBuilder, aSnap);
*aSnap = false;
return bounds.ConvertAppUnitsRoundOut(mAPD, mParentAPD);
}
@ -2297,8 +2291,8 @@ void nsDisplayZoom::Paint(nsDisplayListBuilder* aBuilder,
}
bool nsDisplayZoom::ComputeVisibility(nsDisplayListBuilder *aBuilder,
nsRegion *aVisibleRegion,
const nsRect& aAllowVisibleRegionExpansion)
nsRegion *aVisibleRegion,
const nsRect& aAllowVisibleRegionExpansion)
{
// Convert the passed in visible region to our appunits.
nsRegion visibleRegion =
@ -2800,12 +2794,13 @@ nsDisplayTransform::GetHitDepthAtPoint(const nsPoint& aPoint)
/* The bounding rectangle for the object is the overflow rectangle translated
* by the reference point.
*/
nsRect nsDisplayTransform::GetBounds(nsDisplayListBuilder *aBuilder)
nsRect nsDisplayTransform::GetBounds(nsDisplayListBuilder *aBuilder, bool* aSnap)
{
nsRect untransformedBounds =
ShouldPrerenderTransformedContent(aBuilder, mFrame) ?
mFrame->GetVisualOverflowRectRelativeToSelf() + ToReferenceFrame() :
mStoredList.GetBounds(aBuilder);
mStoredList.GetBounds(aBuilder, aSnap);
*aSnap = false;
float factor = nsPresContext::AppUnitsPerCSSPixel();
return nsLayoutUtils::MatrixTransformRect(untransformedBounds,
GetTransform(factor),
@ -2829,11 +2824,11 @@ nsRect nsDisplayTransform::GetBounds(nsDisplayListBuilder *aBuilder)
* certainly contains the actual (non-axis-aligned) untransformed rect.
*/
nsRegion nsDisplayTransform::GetOpaqueRegion(nsDisplayListBuilder *aBuilder,
bool* aSnap,
bool* aForceTransparentSurface)
{
if (aForceTransparentSurface) {
*aForceTransparentSurface = false;
}
*aForceTransparentSurface = false;
*aSnap = false;
nsRect untransformedVisible;
float factor = nsPresContext::AppUnitsPerCSSPixel();
if (!UntransformRectMatrix(mVisibleRect, GetTransform(factor), factor, &untransformedVisible)) {
@ -2841,12 +2836,15 @@ nsRegion nsDisplayTransform::GetOpaqueRegion(nsDisplayListBuilder *aBuilder,
}
const gfx3DMatrix& matrix = GetTransform(nsPresContext::AppUnitsPerCSSPixel());
nsRegion result;
gfxMatrix matrix2d;
bool tmpSnap;
bool forceTransparentSurface;
if (matrix.Is2D(&matrix2d) &&
matrix2d.PreservesAxisAlignedRectangles() &&
mStoredList.GetOpaqueRegion(aBuilder).Contains(untransformedVisible)) {
mStoredList.GetOpaqueRegion(aBuilder, &tmpSnap, &forceTransparentSurface).
Contains(untransformedVisible)) {
result = mVisibleRect;
}
return result;
@ -3007,11 +3005,11 @@ nsDisplaySVGEffects::~nsDisplaySVGEffects()
#endif
nsRegion nsDisplaySVGEffects::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
bool* aSnap,
bool* aForceTransparentSurface)
{
if (aForceTransparentSurface) {
*aForceTransparentSurface = false;
}
*aForceTransparentSurface = false;
*aSnap = false;
return nsRegion();
}

View File

@ -306,16 +306,6 @@ public:
void SetHasFixedItems() { mHasFixedItems = true; }
bool GetHasFixedItems() { return mHasFixedItems; }
/**
* Returns true if snapping is enabled for the final drawing context.
* The default is true.
*/
bool IsSnappingEnabled() { return mSnappingEnabled; }
/**
* Set if snapping is enabled for the final drawing context.
*/
void SetSnappingEnabled(bool aSnappingEnabled) { mSnappingEnabled = aSnappingEnabled; }
/**
* @return true if images have been set to decode synchronously.
*/
@ -520,7 +510,6 @@ private:
bool mInTransform;
bool mSyncDecodeImages;
bool mIsPaintingToWindow;
bool mSnappingEnabled;
bool mHasDisplayPort;
bool mHasFixedItems;
};
@ -646,24 +635,33 @@ public:
inline nsIFrame* GetUnderlyingFrame() const { return mFrame; }
/**
* The default bounds is the frame border rect.
* @param aSnap *aSnap is set to true if the returned rect will be
* snapped to nearest device pixel edges during actual drawing.
* It might be set to false and snap anyway, so code computing the set of
* pixels affected by this display item needs to round outwards to pixel
* boundaries when *aSnap is set to false.
* @return a rectangle relative to aBuilder->ReferenceFrame() that
* contains the area drawn by this display item
*/
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder) {
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap)
{
*aSnap = false;
return nsRect(ToReferenceFrame(), GetUnderlyingFrame()->GetSize());
}
/**
* @param aSnap set to true if the edges of the rectangles of the opaque
* region would be snapped to device pixels when drawing
* @return a region of the item that is opaque --- every pixel painted
* with an opaque color. This is useful for determining when one piece
* of content completely obscures another so that we can do occlusion
* culling.
*/
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
bool* aForceTransparentSurface = nsnull)
bool* aSnap,
bool* aForceTransparentSurface)
{
if (aForceTransparentSurface) {
*aForceTransparentSurface = false;
}
*aSnap = false;
*aForceTransparentSurface = false;
return nsRegion();
}
/**
@ -1332,8 +1330,10 @@ public:
NS_DISPLAY_DECL_NAME(mName, mType)
virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) {
if (mType == nsDisplayItem::TYPE_HEADER_FOOTER)
return GetBounds(aBuilder);
if (mType == nsDisplayItem::TYPE_HEADER_FOOTER) {
bool snap;
return GetBounds(aBuilder, &snap);
}
return nsRect();
}
@ -1441,7 +1441,8 @@ public:
}
#endif
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder) {
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) {
*aSnap = false;
// The caret returns a rect in the coordinates of mFrame.
return mCaret->GetCaretRect() + ToReferenceFrame();
}
@ -1457,8 +1458,8 @@ protected:
class nsDisplayBorder : public nsDisplayItem {
public:
nsDisplayBorder(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame) :
nsDisplayItem(aBuilder, aFrame),
mSnappingEnabled(aBuilder->IsSnappingEnabled() && !aBuilder->IsInTransform()) {
nsDisplayItem(aBuilder, aFrame)
{
MOZ_COUNT_CTOR(nsDisplayBorder);
}
#ifdef NS_BUILD_REFCNT_LOGGING
@ -1467,15 +1468,12 @@ public:
}
#endif
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder);
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap);
virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx);
virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion,
const nsRect& aAllowVisibleRegionExpansion);
NS_DISPLAY_DECL_NAME("Border", TYPE_BORDER)
protected:
bool mSnappingEnabled;
};
/**
@ -1493,8 +1491,8 @@ class nsDisplaySolidColor : public nsDisplayItem {
public:
nsDisplaySolidColor(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
const nsRect& aBounds, nscolor aColor)
: nsDisplayItem(aBuilder, aFrame), mBounds(aBounds), mColor(aColor),
mSnappingEnabled(aBuilder->IsSnappingEnabled() && !aBuilder->IsInTransform()) {
: nsDisplayItem(aBuilder, aFrame), mBounds(aBounds), mColor(aColor)
{
NS_ASSERTION(NS_GET_A(aColor) > 0, "Don't create invisible nsDisplaySolidColors!");
MOZ_COUNT_CTOR(nsDisplaySolidColor);
}
@ -1504,16 +1502,16 @@ public:
}
#endif
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder);
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap);
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
bool* aOutTransparentBackground = nsnull) {
if (aOutTransparentBackground) {
*aOutTransparentBackground = false;
}
bool* aSnap,
bool* aOutTransparentBackground) {
*aSnap = false;
*aOutTransparentBackground = false;
nsRegion result;
if (NS_GET_A(mColor) == 255) {
result = GetBounds(aBuilder);
result = GetBounds(aBuilder, aSnap);
}
return result;
}
@ -1531,7 +1529,6 @@ public:
private:
nsRect mBounds;
nscolor mColor;
bool mSnappingEnabled;
};
/**
@ -1552,21 +1549,21 @@ public:
nsRegion* aVisibleRegion,
const nsRect& aAllowVisibleRegionExpansion);
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
bool* aForceTransparentSurface = nsnull);
bool* aSnap,
bool* aForceTransparentSurface);
virtual bool IsVaryingRelativeToMovingFrame(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame);
virtual bool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor);
virtual bool ShouldFixToViewport(nsDisplayListBuilder* aBuilder);
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder);
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap);
virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx);
NS_DISPLAY_DECL_NAME("Background", TYPE_BACKGROUND)
protected:
nsRegion GetInsideClipRegion(nsPresContext* aPresContext, PRUint8 aClip,
const nsRect& aRect);
const nsRect& aRect, bool* aSnap);
/* Used to cache mFrame->IsThemed() since it isn't a cheap call */
bool mIsThemed;
bool mSnappingEnabled;
nsITheme::Transparency mThemeTransparency;
};
@ -1586,7 +1583,7 @@ public:
#endif
virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx);
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder);
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap);
virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion,
const nsRect& aAllowVisibleRegionExpansion);
@ -1636,7 +1633,7 @@ public:
}
#endif
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder);
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap);
virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx);
virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion,
@ -1694,9 +1691,10 @@ public:
virtual ~nsDisplayWrapList();
virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames);
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder);
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap);
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
bool* aForceTransparentSurface = nsnull);
bool* aSnap,
bool* aForceTransparentSurface);
virtual bool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor);
virtual bool IsVaryingRelativeToMovingFrame(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame);
@ -1781,7 +1779,8 @@ public:
#endif
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
bool* aForceTransparentSurface = nsnull);
bool* aSnap,
bool* aForceTransparentSurface);
virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerParameters& aContainerParameters);
@ -1946,7 +1945,7 @@ public:
virtual ~nsDisplayClip();
#endif
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder);
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap);
virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx);
virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion,
@ -1987,7 +1986,8 @@ public:
#endif
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
bool* aForceTransparentSurface = nsnull);
bool* aSnap,
bool* aForceTransparentSurface);
virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames);
virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
@ -2027,7 +2027,7 @@ public:
virtual ~nsDisplayZoom();
#endif
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder);
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap);
virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx);
virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames);
@ -2058,10 +2058,12 @@ public:
#endif
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
bool* aForceTransparentSurface = nsnull);
bool* aSnap,
bool* aForceTransparentSurface);
virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames);
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder) {
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) {
*aSnap = false;
return mBounds + aBuilder->ToReferenceFrame(mEffectsFrame);
}
virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx);
@ -2130,16 +2132,18 @@ public:
{
if (mStoredList.GetComponentAlphaBounds(aBuilder).IsEmpty())
return nsRect();
return GetBounds(aBuilder);
bool snap;
return GetBounds(aBuilder, &snap);
}
nsDisplayWrapList* GetStoredList() { return &mStoredList; }
virtual void HitTest(nsDisplayListBuilder *aBuilder, const nsRect& aRect,
HitTestState *aState, nsTArray<nsIFrame*> *aOutFrames);
virtual nsRect GetBounds(nsDisplayListBuilder *aBuilder);
virtual nsRect GetBounds(nsDisplayListBuilder *aBuilder, bool* aSnap);
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder *aBuilder,
bool* aForceTransparentSurface = nsnull);
bool* aSnap,
bool* aForceTransparentSurface);
virtual bool IsUniform(nsDisplayListBuilder *aBuilder, nscolor* aColor);
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager);

View File

@ -170,7 +170,8 @@ PrintDisplayListTo(nsDisplayListBuilder* aBuilder, const nsDisplayList& aList,
f->GetFrameName(fName);
}
#endif
nsRect rect = i->GetBounds(aBuilder);
bool snap;
nsRect rect = i->GetBounds(aBuilder, &snap);
switch (i->GetType()) {
case nsDisplayItem::TYPE_CLIP:
case nsDisplayItem::TYPE_CLIP_ROUNDED_RECT: {
@ -191,7 +192,8 @@ PrintDisplayListTo(nsDisplayListBuilder* aBuilder, const nsDisplayList& aList,
}
#ifdef DEBUG
if (!list || list->DidComputeVisibility()) {
opaque = i->GetOpaqueRegion(aBuilder);
bool forceTransparentSurface;
opaque = i->GetOpaqueRegion(aBuilder, &snap, &forceTransparentSurface);
}
#endif
if (i->Painted()) {

View File

@ -1607,10 +1607,6 @@ nsLayoutUtils::PaintFrame(nsRenderingContext* aRenderingContext, nsIFrame* aFram
if (aFlags & PAINT_IGNORE_SUPPRESSION) {
builder.IgnorePaintSuppression();
}
if (aRenderingContext &&
aRenderingContext->ThebesContext()->GetFlags() & gfxContext::FLAG_DISABLE_SNAPPING) {
builder.SetSnappingEnabled(false);
}
nsRect canvasArea(nsPoint(0, 0), aFrame->GetSize());
#ifdef DEBUG

View File

@ -4603,7 +4603,8 @@ PresShell::ClipListToRange(nsDisplayListBuilder *aBuilder,
nsRange::CompareNodeToRange(content, aRange, &before, &after);
if (NS_SUCCEEDED(rv) && !before && !after) {
itemToInsert = i;
surfaceRect.UnionRect(surfaceRect, i->GetBounds(aBuilder));
bool snap;
surfaceRect.UnionRect(surfaceRect, i->GetBounds(aBuilder, &snap));
}
}
}

View File

@ -106,14 +106,15 @@ public:
virtual void Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx);
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder);
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap);
NS_DISPLAY_DECL_NAME("ButtonBoxShadowOuter", TYPE_BUTTON_BOX_SHADOW_OUTER)
private:
nsButtonFrameRenderer* mBFR;
};
nsRect
nsDisplayButtonBoxShadowOuter::GetBounds(nsDisplayListBuilder* aBuilder) {
nsDisplayButtonBoxShadowOuter::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) {
*aSnap = false;
return mFrame->GetVisualOverflowRectRelativeToSelf() + ToReferenceFrame();
}

View File

@ -149,7 +149,8 @@ public:
}
#endif
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder) {
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) {
*aSnap = false;
// override bounds because the list item focus ring may extend outside
// the nsSelectsAreaFrame
nsListControlFrame* listFrame = GetEnclosingListFrame(GetUnderlyingFrame());

View File

@ -190,7 +190,8 @@ public:
MOZ_COUNT_DTOR(nsDisplayTextOverflowMarker);
}
#endif
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder) {
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) {
*aSnap = false;
nsRect shadowRect =
nsLayoutUtils::GetTextShadowRectsUnion(mRect, mFrame);
return mRect.Union(shadowRect);

View File

@ -213,8 +213,9 @@ public:
}
#endif
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder)
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap)
{
*aSnap = false;
return mFrame->GetVisualOverflowRectRelativeToSelf() + ToReferenceFrame();
}
virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
@ -227,7 +228,8 @@ public:
virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder)
{
return GetBounds(aBuilder);
bool snap;
return GetBounds(aBuilder, &snap);
}
};

View File

@ -253,8 +253,9 @@ public:
MOZ_COUNT_DTOR(nsDisplayCanvasFocus);
}
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder)
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap)
{
*aSnap = false;
// This is an overestimate, but that's not a problem.
nsCanvasFrame* frame = static_cast<nsCanvasFrame*>(mFrame);
return frame->CanvasArea() + ToReferenceFrame();

View File

@ -162,22 +162,23 @@ public:
}
virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion,
const nsRect& aAllowVisibleRegionExpansion)
nsRegion* aVisibleRegion,
const nsRect& aAllowVisibleRegionExpansion)
{
return NS_GET_A(mExtraBackgroundColor) > 0 ||
nsDisplayBackground::ComputeVisibility(aBuilder, aVisibleRegion,
aAllowVisibleRegionExpansion);
}
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
bool* aForceTransparentSurface = nsnull)
bool* aSnap,
bool* aForceTransparentSurface)
{
if (aForceTransparentSurface) {
if (NS_GET_A(mExtraBackgroundColor) == 255) {
*aForceTransparentSurface = false;
return nsRegion(GetBounds(aBuilder, aSnap));
}
if (NS_GET_A(mExtraBackgroundColor) == 255)
return nsRegion(GetBounds(aBuilder));
return nsDisplayBackground::GetOpaqueRegion(aBuilder);
return nsDisplayBackground::GetOpaqueRegion(aBuilder, aSnap,
aForceTransparentSurface);
}
virtual bool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor)
{
@ -190,15 +191,11 @@ public:
*aColor = mExtraBackgroundColor;
return true;
}
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder)
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap)
{
nsCanvasFrame* frame = static_cast<nsCanvasFrame*>(mFrame);
nsRect r = frame->CanvasArea() + ToReferenceFrame();
if (mSnappingEnabled) {
nscoord appUnitsPerDevPixel = frame->PresContext()->AppUnitsPerDevPixel();
r = r.ToNearestPixels(appUnitsPerDevPixel).ToAppUnits(appUnitsPerDevPixel);
}
return r;
*aSnap = true;
return frame->CanvasArea() + ToReferenceFrame();
}
virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames)

View File

@ -82,20 +82,21 @@ public:
NS_DISPLAY_DECL_NAME("nsDisplayCanvas", TYPE_CANVAS)
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
bool* aForceTransparentSurface = nsnull) {
if (aForceTransparentSurface) {
*aForceTransparentSurface = false;
}
bool* aSnap,
bool* aForceTransparentSurface) {
*aForceTransparentSurface = false;
*aSnap = false;
nsIFrame* f = GetUnderlyingFrame();
nsHTMLCanvasElement *canvas = CanvasElementFromContent(f->GetContent());
nsRegion result;
if (canvas->GetIsOpaque()) {
result = GetBounds(aBuilder);
result = GetBounds(aBuilder, aSnap);
}
return result;
}
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder) {
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) {
*aSnap = false;
nsHTMLCanvasFrame* f = static_cast<nsHTMLCanvasFrame*>(GetUnderlyingFrame());
return f->GetInnerArea() + ToReferenceFrame();
}

View File

@ -917,7 +917,7 @@ public:
}
#endif
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder);
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap);
virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion,
const nsRect& aAllowVisibleRegionExpansion);
@ -946,8 +946,9 @@ GetDisplayItemBounds(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem, nsIFr
}
nsRect
nsDisplayPluginReadback::GetBounds(nsDisplayListBuilder* aBuilder)
nsDisplayPluginReadback::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap)
{
*aSnap = false;
return GetDisplayItemBounds(aBuilder, this, mFrame);
}
@ -961,7 +962,8 @@ nsDisplayPluginReadback::ComputeVisibility(nsDisplayListBuilder* aBuilder,
return false;
nsRect expand;
expand.IntersectRect(aAllowVisibleRegionExpansion, GetBounds(aBuilder));
bool snap;
expand.IntersectRect(aAllowVisibleRegionExpansion, GetBounds(aBuilder, &snap));
// *Add* our bounds to the visible region so that stuff underneath us is
// likely to be made visible, so we can use it for a background! This is
// a bit crazy since we normally only subtract from the visible region.
@ -970,8 +972,9 @@ nsDisplayPluginReadback::ComputeVisibility(nsDisplayListBuilder* aBuilder,
}
nsRect
nsDisplayPlugin::GetBounds(nsDisplayListBuilder* aBuilder)
nsDisplayPlugin::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap)
{
*aSnap = false;
return GetDisplayItemBounds(aBuilder, this, mFrame);
}
@ -980,7 +983,8 @@ nsDisplayPlugin::Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx)
{
nsObjectFrame* f = static_cast<nsObjectFrame*>(mFrame);
f->PaintPlugin(aBuilder, *aCtx, mVisibleRect, GetBounds(aBuilder));
bool snap;
f->PaintPlugin(aBuilder, *aCtx, mVisibleRect, GetBounds(aBuilder, &snap));
}
bool
@ -988,18 +992,19 @@ nsDisplayPlugin::ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion,
const nsRect& aAllowVisibleRegionExpansion)
{
mVisibleRegion.And(*aVisibleRegion, GetBounds(aBuilder));
bool snap;
mVisibleRegion.And(*aVisibleRegion, GetBounds(aBuilder, &snap));
return nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion,
aAllowVisibleRegionExpansion);
}
nsRegion
nsDisplayPlugin::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
bool* aSnap,
bool* aForceTransparentSurface)
{
if (aForceTransparentSurface) {
*aForceTransparentSurface = false;
}
*aForceTransparentSurface = false;
*aSnap = false;
nsRegion result;
nsObjectFrame* f = static_cast<nsObjectFrame*>(mFrame);
if (!aBuilder->IsForPluginGeometry()) {
@ -1018,11 +1023,13 @@ nsDisplayPlugin::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
}
}
}
if (f->IsOpaque() &&
(aBuilder->IsForPluginGeometry() ||
(f->GetPaintedRect(this) + ToReferenceFrame()).Contains(GetBounds(aBuilder)))) {
// We can treat this as opaque
result = GetBounds(aBuilder);
if (f->IsOpaque()) {
nsRect bounds = GetBounds(aBuilder, aSnap);
if (aBuilder->IsForPluginGeometry() ||
(f->GetPaintedRect(this) + ToReferenceFrame()).Contains(bounds)) {
// We can treat this as opaque
result = bounds;
}
}
return result;
}

View File

@ -299,9 +299,10 @@ public:
}
#endif
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder);
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap);
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
bool* aForceTransparentSurface = nsnull);
bool* aSnap,
bool* aForceTransparentSurface);
virtual void Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx);
virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,

View File

@ -4389,7 +4389,8 @@ public:
}
#endif
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder) {
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) {
*aSnap = false;
return mFrame->GetVisualOverflowRectRelativeToSelf() + ToReferenceFrame();
}
virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
@ -4404,7 +4405,8 @@ public:
virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder)
{
return GetBounds(aBuilder);
bool snap;
return GetBounds(aBuilder, &snap);
}
virtual void DisableComponentAlpha() { mDisableSubpixelAA = true; }

View File

@ -345,8 +345,9 @@ public:
// away completely (e.g. because of a decoder error). The problem would
// be especially acute if we have off-main-thread rendering.
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder)
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap)
{
*aSnap = false;
nsIFrame* f = GetUnderlyingFrame();
return f->GetContentRect() - f->GetPosition() + ToReferenceFrame();
}

View File

@ -198,8 +198,9 @@ public:
, mId(aId)
{}
NS_OVERRIDE nsRect GetBounds(nsDisplayListBuilder* aBuilder)
NS_OVERRIDE nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap)
{
*aSnap = false;
return mRect;
}

View File

@ -1909,7 +1909,8 @@ public:
}
#endif
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder) {
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) {
*aSnap = false;
nsRect rect;
mChar->GetRect(rect);
nsPoint offset = ToReferenceFrame() + rect.TopLeft();
@ -1930,7 +1931,8 @@ public:
virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder)
{
return GetBounds(aBuilder);
bool snap;
return GetBounds(aBuilder, &snap);
}
private:

View File

@ -7,7 +7,7 @@ HTTP(..) == scroll-rounding.html scroll-rounding-ref.html
HTTP(..) == anonymous-block.html anonymous-block-ref.html
HTTP(..) == false-marker-overlap.html false-marker-overlap-ref.html
HTTP(..) == visibility-hidden.html visibility-hidden-ref.html
fails-if(Android&&layersOpenGL) HTTP(..) == block-padding.html block-padding-ref.html
fails-if(Android) HTTP(..) == block-padding.html block-padding-ref.html
HTTP(..) == quirks-decorations.html quirks-decorations-ref.html
HTTP(..) == quirks-line-height.html quirks-line-height-ref.html
HTTP(..) == standards-decorations.html standards-decorations-ref.html

View File

@ -401,7 +401,7 @@ public:
}
virtual void Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx);
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder);
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap);
NS_DISPLAY_DECL_NAME("TableCellBackground", TYPE_TABLE_CELL_BACKGROUND)
};
@ -415,11 +415,12 @@ void nsDisplayTableCellBackground::Paint(nsDisplayListBuilder* aBuilder,
}
nsRect
nsDisplayTableCellBackground::GetBounds(nsDisplayListBuilder* aBuilder)
nsDisplayTableCellBackground::GetBounds(nsDisplayListBuilder* aBuilder,
bool* aSnap)
{
// revert from nsDisplayTableItem's implementation ... cell backgrounds
// don't overflow the cell
return nsDisplayItem::GetBounds(aBuilder);
return nsDisplayItem::GetBounds(aBuilder, aSnap);
}
static void

View File

@ -1062,7 +1062,8 @@ nsTableFrame::GetChildLists(nsTArray<ChildList>* aLists) const
}
nsRect
nsDisplayTableItem::GetBounds(nsDisplayListBuilder* aBuilder) {
nsDisplayTableItem::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) {
*aSnap = false;
return mFrame->GetVisualOverflowRectRelativeToSelf() + ToReferenceFrame();
}

View File

@ -78,7 +78,7 @@ public:
// the table part frames, so allow this display element to blow out to our
// overflow rect. This is also useful for row frames that have spanning
// cells extending outside them.
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder);
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap);
void UpdateForFrameBackground(nsIFrame* aFrame);

View File

@ -325,7 +325,7 @@ public:
virtual void Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx);
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder);
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap);
NS_DISPLAY_DECL_NAME("XULTextBox", TYPE_XUL_TEXT_BOX)
virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder);
@ -378,7 +378,8 @@ nsDisplayXULTextBox::PaintTextToContext(nsRenderingContext* aCtx,
}
nsRect
nsDisplayXULTextBox::GetBounds(nsDisplayListBuilder* aBuilder) {
nsDisplayXULTextBox::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) {
*aSnap = false;
return mFrame->GetVisualOverflowRectRelativeToSelf() + ToReferenceFrame();
}