Bug 806056 - Add a frame bit that says if a frame is allowed to have abs/fixed pos. children when the style so indicates (position/transform usually). Copy the bit to next-in-flows. Don't call MarkAsAbsoluteContainingBlock for style changes on an existing frame unless that bit is set (style changes that recreates the frame resets it of course). Assert in MarkAs[Not]AbsoluteContainingBlock() that the bit is set. r=bz

This commit is contained in:
Mats Palmgren 2012-11-02 01:52:59 +01:00
Родитель 7eb78c7eb5
Коммит 1a123c0b7d
3 изменённых файлов: 25 добавлений и 11 удалений

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

@ -1942,6 +1942,7 @@ nsCSSFrameConstructor::ConstructTable(nsFrameConstructorState& aState,
const nsStyleDisplay* display = outerStyleContext->GetStyleDisplay();
// Mark the table frame as an absolute container if needed
newFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
if (display->IsPositioned(aParentFrame)) {
aState.PushAbsoluteContainingBlock(newFrame, absoluteSaveState);
}
@ -2387,6 +2388,7 @@ nsCSSFrameConstructor::ConstructDocElementFrame(Element* aDocEle
if (mHasRootAbsPosContainingBlock) {
// Push the absolute containing block now so we can absolutely position
// the root element
mDocElementContainingBlock->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
state.PushAbsoluteContainingBlock(mDocElementContainingBlock,
absoluteSaveState);
}
@ -2575,6 +2577,7 @@ nsCSSFrameConstructor::ConstructRootFrame(nsIFrame** aNewFrame)
// The viewport is the containing block for 'fixed' elements
mFixedContainingBlock = viewportFrame;
// Make it an absolute container for fixed-pos elements
mFixedContainingBlock->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
mFixedContainingBlock->MarkAsAbsoluteContainingBlock();
*aNewFrame = viewportFrame;
@ -2844,6 +2847,7 @@ nsCSSFrameConstructor::ConstructPageFrame(nsIPresShell* aPresShell,
SetInitialSingleChild(aPageFrame, pageContentFrame);
mFixedContainingBlock = pageContentFrame;
// Make it an absolute container for fixed-pos elements
mFixedContainingBlock->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
mFixedContainingBlock->MarkAsAbsoluteContainingBlock();
nsRefPtr<nsStyleContext> canvasPseudoStyle;
@ -3150,6 +3154,7 @@ nsCSSFrameConstructor::ConstructFieldSetFrame(nsFrameConstructorState& aState,
nsFrameConstructorSaveState absoluteSaveState;
nsFrameItems childItems;
newFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
if (newFrame->IsPositioned()) {
aState.PushAbsoluteContainingBlock(newFrame, absoluteSaveState);
}
@ -3726,11 +3731,12 @@ nsCSSFrameConstructor::ConstructFrameFromItemInternal(FrameConstructionItem& aIt
if (bits & FCDATA_FORCE_NULL_ABSPOS_CONTAINER) {
aState.PushAbsoluteContainingBlock(nullptr, absoluteSaveState);
} else if (!(bits & FCDATA_SKIP_ABSPOS_PUSH) &&
maybeAbsoluteContainingBlockDisplay->IsPositioned
(maybeAbsoluteContainingBlock)) {
aState.PushAbsoluteContainingBlock(maybeAbsoluteContainingBlock,
absoluteSaveState);
} else if (!(bits & FCDATA_SKIP_ABSPOS_PUSH)) {
nsIFrame* cb = maybeAbsoluteContainingBlock;
cb->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
if (maybeAbsoluteContainingBlockDisplay->IsPositioned(cb)) {
aState.PushAbsoluteContainingBlock(cb, absoluteSaveState);
}
}
if (bits & FCDATA_USE_CHILD_ITEMS) {
@ -8160,7 +8166,8 @@ nsCSSFrameConstructor::ProcessRestyledFrames(nsStyleChangeList& aChangeList)
// but we may be taking this path even if a transform has been
// removed. It's OK to add the bit even if it's not needed.
frame->AddStateBits(NS_FRAME_MAY_BE_TRANSFORMED);
if (!frame->IsAbsoluteContainer()) {
if (!frame->IsAbsoluteContainer() &&
(frame->GetStateBits() & NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN)) {
frame->MarkAsAbsoluteContainingBlock();
}
} else {
@ -11122,6 +11129,7 @@ nsCSSFrameConstructor::ConstructBlock(nsFrameConstructorState& aState,
// children. So use the block and try to compensate with hacks
// in nsBlockFrame::CalculateContainingBlockSizeForAbsolutes.
nsFrameConstructorSaveState absoluteSaveState;
(*aNewFrame)->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
if (aAbsPosContainer) {
// NS_ASSERTION(aRelPos, "should have made area frame for this");
aState.PushAbsoluteContainingBlock(*aNewFrame, absoluteSaveState);
@ -11226,6 +11234,7 @@ nsCSSFrameConstructor::ConstructInline(nsFrameConstructorState& aState,
// because the object's destructor is significant
// this is part of the fix for bug 42372
newFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
if (positioned) {
// Relatively positioned frames becomes a container for child
// frames that are positioned
@ -11339,8 +11348,8 @@ nsCSSFrameConstructor::CreateIBSiblings(nsFrameConstructorState& aState,
InitAndRestoreFrame(aState, content, parentFrame, nullptr, inlineFrame,
false);
inlineFrame->AddStateBits(NS_FRAME_MAY_HAVE_GENERATED_CONTENT);
inlineFrame->AddStateBits(NS_FRAME_MAY_HAVE_GENERATED_CONTENT |
NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
if (aIsPositioned) {
inlineFrame->MarkAsAbsoluteContainingBlock();
}

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

@ -251,6 +251,7 @@ nsIFrame::GetAbsoluteContainingBlock() const {
void
nsIFrame::MarkAsAbsoluteContainingBlock()
{
MOZ_ASSERT(GetStateBits() & NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
NS_ASSERTION(!Properties().Get(AbsoluteContainingBlockProperty()),
"Already has an abs-pos containing block property?");
NS_ASSERTION(!HasAnyStateBits(NS_FRAME_HAS_ABSPOS_CHILDREN),
@ -267,6 +268,7 @@ nsIFrame::MarkAsNotAbsoluteContainingBlock()
"Should have an abs-pos containing block property");
NS_ASSERTION(HasAnyStateBits(NS_FRAME_HAS_ABSPOS_CHILDREN),
"Should have NS_FRAME_HAS_ABSPOS_CHILDREN state bit");
MOZ_ASSERT(HasAnyStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN));
RemoveStateBits(NS_FRAME_HAS_ABSPOS_CHILDREN);
Properties().Delete(AbsoluteContainingBlockProperty());
}
@ -512,7 +514,8 @@ nsFrame::Init(nsIContent* aContent,
mState |= state & (NS_FRAME_INDEPENDENT_SELECTION |
NS_FRAME_IS_SPECIAL |
NS_FRAME_MAY_BE_TRANSFORMED |
NS_FRAME_MAY_HAVE_GENERATED_CONTENT);
NS_FRAME_MAY_HAVE_GENERATED_CONTENT |
NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
}
if (mParent) {
nsFrameState state = mParent->GetStateBits();

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

@ -164,8 +164,10 @@ typedef uint64_t nsFrameState;
// e.g., it is absolutely positioned or floated
#define NS_FRAME_OUT_OF_FLOW NS_FRAME_STATE_BIT(8)
// This bit is available for re-use.
//#define NS_FRAME_SELECTED_CONTENT NS_FRAME_STATE_BIT(9)
// Frame can be an abs/fixed pos. container, if its style says so.
// MarkAs[Not]AbsoluteContainingBlock will assert that this bit is set.
// NS_FRAME_HAS_ABSPOS_CHILDREN must not be set when this bit is unset.
#define NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN NS_FRAME_STATE_BIT(9)
// If this bit is set, then the frame and _all_ of its descendant frames need
// to be reflowed.