mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-01 08:42:13 +00:00
Bug 1202029 - Use the containing block for determining perspective for transformed elements. r=dbaron
--HG-- extra : rebase_source : f8a1403a77e71179aca097e26567bcb3b7c1848b
This commit is contained in:
parent
c7235f4a33
commit
6e6e6105aa
@ -4811,19 +4811,12 @@ nsDisplayTransform::GetDeltaToPerspectiveOrigin(const nsIFrame* aFrame,
|
||||
|
||||
//TODO: Should this be using our bounds or the parent's bounds?
|
||||
// How do we handle aBoundsOverride in the latter case?
|
||||
nsIFrame* parent;
|
||||
nsStyleContext* psc = aFrame->GetParentStyleContext(&parent);
|
||||
if (!psc) {
|
||||
nsIFrame* cbFrame = aFrame->GetContainingBlock(nsIFrame::SKIP_SCROLLED_FRAME);
|
||||
if (!cbFrame) {
|
||||
return Point3D();
|
||||
}
|
||||
if (!parent) {
|
||||
parent = aFrame->GetParent();
|
||||
if (!parent) {
|
||||
return Point3D();
|
||||
}
|
||||
}
|
||||
const nsStyleDisplay* display = psc->StyleDisplay();
|
||||
TransformReferenceBox refBox(parent);
|
||||
const nsStyleDisplay* display = cbFrame->StyleDisplay();
|
||||
TransformReferenceBox refBox(cbFrame);
|
||||
|
||||
/* Allows us to access named variables by index. */
|
||||
Point3D result;
|
||||
@ -4854,7 +4847,7 @@ nsDisplayTransform::GetDeltaToPerspectiveOrigin(const nsIFrame* aFrame,
|
||||
}
|
||||
}
|
||||
|
||||
nsPoint parentOffset = aFrame->GetOffsetTo(parent);
|
||||
nsPoint parentOffset = aFrame->GetOffsetTo(cbFrame);
|
||||
Point3D gfxOffset(
|
||||
NSAppUnitsToFloatPixels(parentOffset.x, aAppUnitsPerPixel),
|
||||
NSAppUnitsToFloatPixels(parentOffset.y, aAppUnitsPerPixel),
|
||||
@ -4871,17 +4864,16 @@ nsDisplayTransform::FrameTransformProperties::FrameTransformProperties(const nsI
|
||||
, mToTransformOrigin(GetDeltaToTransformOrigin(aFrame, aAppUnitsPerPixel, aBoundsOverride))
|
||||
, mChildPerspective(0)
|
||||
{
|
||||
const nsStyleDisplay* parentDisp = nullptr;
|
||||
nsStyleContext* parentStyleContext = aFrame->StyleContext()->GetParent();
|
||||
if (parentStyleContext) {
|
||||
parentDisp = parentStyleContext->StyleDisplay();
|
||||
}
|
||||
if (parentDisp && parentDisp->mChildPerspective.GetUnit() == eStyleUnit_Coord) {
|
||||
mChildPerspective = parentDisp->mChildPerspective.GetCoordValue();
|
||||
// Calling GetDeltaToPerspectiveOrigin can be expensive, so we avoid
|
||||
// calling it unnecessarily.
|
||||
if (mChildPerspective > 0.0) {
|
||||
mToPerspectiveOrigin = GetDeltaToPerspectiveOrigin(aFrame, aAppUnitsPerPixel);
|
||||
nsIFrame* cbFrame = aFrame->GetContainingBlock(nsIFrame::SKIP_SCROLLED_FRAME);
|
||||
if (cbFrame) {
|
||||
const nsStyleDisplay* display = cbFrame->StyleDisplay();
|
||||
if (display->mChildPerspective.GetUnit() == eStyleUnit_Coord) {
|
||||
mChildPerspective = display->mChildPerspective.GetCoordValue();
|
||||
// Calling GetDeltaToPerspectiveOrigin can be expensive, so we avoid
|
||||
// calling it unnecessarily.
|
||||
if (mChildPerspective > 0.0) {
|
||||
mToPerspectiveOrigin = GetDeltaToPerspectiveOrigin(aFrame, aAppUnitsPerPixel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4190,19 +4190,15 @@ GetPercentBSize(const nsStyleCoord& aStyle,
|
||||
MOZ_ASSERT(!aStyle.IsCalcUnit() || aStyle.CalcHasPercent(),
|
||||
"GetAbsoluteCoord should have handled this");
|
||||
|
||||
nsIFrame *f = aFrame->GetContainingBlock();
|
||||
if (!f) {
|
||||
NS_NOTREACHED("top of frame tree not a containing block");
|
||||
return false;
|
||||
}
|
||||
|
||||
// During reflow, nsHTMLScrollFrame::ReflowScrolledFrame uses
|
||||
// SetComputedHeight on the reflow state for its child to propagate its
|
||||
// computed height to the scrolled content. So here we skip to the scroll
|
||||
// frame that contains this scrolled content in order to get the same
|
||||
// behavior as layout when computing percentage heights.
|
||||
if (f->StyleContext()->GetPseudo() == nsCSSAnonBoxes::scrolledContent) {
|
||||
f = f->GetParent();
|
||||
nsIFrame *f = aFrame->GetContainingBlock(nsIFrame::SKIP_SCROLLED_FRAME);
|
||||
if (!f) {
|
||||
NS_NOTREACHED("top of frame tree not a containing block");
|
||||
return false;
|
||||
}
|
||||
|
||||
WritingMode wm = f->GetWritingMode();
|
||||
|
@ -1143,12 +1143,11 @@ nsIFrame::HasPerspective() const
|
||||
if (!IsTransformed()) {
|
||||
return false;
|
||||
}
|
||||
nsStyleContext* parentStyleContext = StyleContext()->GetParent();
|
||||
if (!parentStyleContext) {
|
||||
nsIFrame* containingBlock = GetContainingBlock(SKIP_SCROLLED_FRAME);
|
||||
if (!containingBlock) {
|
||||
return false;
|
||||
}
|
||||
const nsStyleDisplay* parentDisp = parentStyleContext->StyleDisplay();
|
||||
return parentDisp->mChildPerspective.GetUnit() == eStyleUnit_Coord;
|
||||
return containingBlock->ChildrenHavePerspective();
|
||||
}
|
||||
|
||||
bool
|
||||
@ -5705,16 +5704,27 @@ GetNearestBlockContainer(nsIFrame* frame)
|
||||
}
|
||||
|
||||
nsIFrame*
|
||||
nsIFrame::GetContainingBlock() const
|
||||
nsIFrame::GetContainingBlock(uint32_t aFlags) const
|
||||
{
|
||||
if (!GetParent()) {
|
||||
return nullptr;
|
||||
}
|
||||
// MathML frames might have absolute positioning style, but they would
|
||||
// still be in-flow. So we have to check to make sure that the frame
|
||||
// is really out-of-flow too.
|
||||
nsIFrame* f;
|
||||
if (IsAbsolutelyPositioned() &&
|
||||
(GetStateBits() & NS_FRAME_OUT_OF_FLOW)) {
|
||||
return GetParent(); // the parent is always the containing block
|
||||
f = GetParent(); // the parent is always the containing block
|
||||
} else {
|
||||
f = GetNearestBlockContainer(GetParent());
|
||||
}
|
||||
return GetNearestBlockContainer(GetParent());
|
||||
|
||||
if (aFlags & SKIP_SCROLLED_FRAME && f &&
|
||||
f->StyleContext()->GetPseudo() == nsCSSAnonBoxes::scrolledContent) {
|
||||
f = f->GetParent();
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_FRAME_DUMP
|
||||
@ -7632,7 +7642,7 @@ nsIFrame::FinishAndStoreOverflow(nsOverflowAreas& aOverflowAreas,
|
||||
nsRect bounds(nsPoint(0, 0), aNewSize);
|
||||
// Store the passed in overflow area if we are a preserve-3d frame or we have
|
||||
// a transform, and it's not just the frame bounds.
|
||||
if (Preserves3D() || HasPerspective() || IsTransformed()) {
|
||||
if (Preserves3D() || IsTransformed()) {
|
||||
if (!aOverflowAreas.VisualOverflow().IsEqualEdges(bounds) ||
|
||||
!aOverflowAreas.ScrollableOverflow().IsEqualEdges(bounds)) {
|
||||
nsOverflowAreas* initial =
|
||||
@ -7748,13 +7758,13 @@ nsIFrame::FinishAndStoreOverflow(nsOverflowAreas& aOverflowAreas,
|
||||
if (Preserves3DChildren()) {
|
||||
ComputePreserve3DChildrenOverflow(aOverflowAreas, newBounds);
|
||||
} else if (sizeChanged && ChildrenHavePerspective()) {
|
||||
RecomputePerspectiveChildrenOverflow(this->StyleContext(), &newBounds);
|
||||
RecomputePerspectiveChildrenOverflow(this, &newBounds);
|
||||
}
|
||||
} else {
|
||||
Properties().Delete(nsIFrame::PreTransformOverflowAreasProperty());
|
||||
if (ChildrenHavePerspective() && sizeChanged) {
|
||||
nsRect newBounds(nsPoint(0, 0), aNewSize);
|
||||
RecomputePerspectiveChildrenOverflow(this->StyleContext(), &newBounds);
|
||||
RecomputePerspectiveChildrenOverflow(this, &newBounds);
|
||||
}
|
||||
}
|
||||
|
||||
@ -7772,7 +7782,7 @@ nsIFrame::FinishAndStoreOverflow(nsOverflowAreas& aOverflowAreas,
|
||||
}
|
||||
|
||||
void
|
||||
nsIFrame::RecomputePerspectiveChildrenOverflow(const nsStyleContext* aStartStyle, const nsRect* aBounds)
|
||||
nsIFrame::RecomputePerspectiveChildrenOverflow(const nsIFrame* aStartFrame, const nsRect* aBounds)
|
||||
{
|
||||
// Children may check our size when getting our transform, make sure it's valid.
|
||||
nsSize oldSize = GetSize();
|
||||
@ -7799,14 +7809,13 @@ nsIFrame::RecomputePerspectiveChildrenOverflow(const nsStyleContext* aStartStyle
|
||||
boundsOverflow.SetAllTo(bounds);
|
||||
child->FinishAndStoreOverflow(boundsOverflow, bounds.Size());
|
||||
}
|
||||
} else if (child->StyleContext()->GetParent() == aStartStyle ||
|
||||
child->StyleContext() == aStartStyle) {
|
||||
} else if (child->GetContainingBlock(SKIP_SCROLLED_FRAME) == aStartFrame) {
|
||||
// If a frame is using perspective, then the size used to compute
|
||||
// perspective-origin is the size of the frame belonging to its parent
|
||||
// style context. We must find any descendant frames using our size
|
||||
// (by recurse into frames with the same style context, or a direct
|
||||
// child style context) to update their overflow rects too.
|
||||
child->RecomputePerspectiveChildrenOverflow(aStartStyle, nullptr);
|
||||
// (by recursing into frames that have the same containing block)
|
||||
// to update their overflow rects too.
|
||||
child->RecomputePerspectiveChildrenOverflow(aStartFrame, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2471,7 +2471,7 @@ ScrollFrameHelper::ScrollToImpl(nsPoint aPt, const nsRect& aRange, nsIAtom* aOri
|
||||
if (mOuter->ChildrenHavePerspective()) {
|
||||
// The overflow areas of descendants may depend on the scroll position,
|
||||
// so ensure they get updated.
|
||||
mOuter->RecomputePerspectiveChildrenOverflow(mOuter->StyleContext(), nullptr);
|
||||
mOuter->RecomputePerspectiveChildrenOverflow(mOuter, nullptr);
|
||||
}
|
||||
|
||||
ScheduleSyntheticMouseMove();
|
||||
|
@ -1267,7 +1267,7 @@ public:
|
||||
// Calculate the overflow size of all child frames, taking preserve-3d into account
|
||||
void ComputePreserve3DChildrenOverflow(nsOverflowAreas& aOverflowAreas, const nsRect& aBounds);
|
||||
|
||||
void RecomputePerspectiveChildrenOverflow(const nsStyleContext* aStartStyle, const nsRect* aBounds);
|
||||
void RecomputePerspectiveChildrenOverflow(const nsIFrame* aStartFrame, const nsRect* aBounds);
|
||||
|
||||
/**
|
||||
* Returns the number of ancestors between this and the root of our frame tree
|
||||
@ -2116,8 +2116,18 @@ public:
|
||||
*
|
||||
* NOTE: This is guaranteed to return a non-null pointer when invoked on any
|
||||
* frame other than the root frame.
|
||||
*
|
||||
* Requires SKIP_SCROLLED_FRAME to get behaviour matching the spec, otherwise
|
||||
* it can return anonymous inner scrolled frames. Bug 1204044 is filed for
|
||||
* investigating whether any of the callers actually require the default
|
||||
* behaviour.
|
||||
*/
|
||||
nsIFrame* GetContainingBlock() const;
|
||||
enum {
|
||||
// If the containing block is an anonymous scrolled frame, then skip over
|
||||
// this and return the outer scroll frame.
|
||||
SKIP_SCROLLED_FRAME = 0x01
|
||||
};
|
||||
nsIFrame* GetContainingBlock(uint32_t aFlags = 0) const;
|
||||
|
||||
/**
|
||||
* Is this frame a containing block for floating elements?
|
||||
|
Loading…
Reference in New Issue
Block a user