Bug 1236400 part 2: Extend NeedsAnonFlexOrGridItem() & related code to wrap all inline-level -webkit-box children in an anonymous flex item. r=mats

MozReview-Commit-ID: LK4VW0xSI5m
This commit is contained in:
Daniel Holbert
2016-03-24 09:55:11 -07:00
parent 22b6cb5f0f
commit ff3a1cedde
2 changed files with 57 additions and 17 deletions

View File

@@ -341,6 +341,15 @@ IsFlexOrGridContainer(const nsIFrame* aFrame)
t == nsGkAtoms::gridContainerFrame;
}
// Returns true if aFrame has "display: -webkit-{inline-}box"
static inline bool
IsWebkitBox(const nsIFrame* aFrame)
{
auto containerDisplay = aFrame->StyleDisplay()->mDisplay;
return containerDisplay == NS_STYLE_DISPLAY_WEBKIT_BOX ||
containerDisplay == NS_STYLE_DISPLAY_WEBKIT_INLINE_BOX;
}
#if DEBUG
static void
AssertAnonymousFlexOrGridItemParent(const nsIFrame* aChild,
@@ -9752,10 +9761,13 @@ nsCSSFrameConstructor::CreateNeededAnonFlexOrGridItems(
}
nsIAtom* containerType = aParentFrame->GetType();
const bool isWebkitBox = IsWebkitBox(aParentFrame);
FCItemIterator iter(aItems);
do {
// Advance iter past children that don't want to be wrapped
if (iter.SkipItemsThatDontNeedAnonFlexOrGridItem(aState, containerType)) {
if (iter.SkipItemsThatDontNeedAnonFlexOrGridItem(aState, containerType,
isWebkitBox)) {
// Hit the end of the items without finding any remaining children that
// need to be wrapped. We're finished!
return;
@@ -9777,8 +9789,10 @@ nsCSSFrameConstructor::CreateNeededAnonFlexOrGridItems(
FCItemIterator afterWhitespaceIter(iter);
bool hitEnd = afterWhitespaceIter.SkipWhitespace(aState);
bool nextChildNeedsAnonItem =
!hitEnd && afterWhitespaceIter.item().NeedsAnonFlexOrGridItem(aState,
containerType);
!hitEnd &&
afterWhitespaceIter.item().NeedsAnonFlexOrGridItem(aState,
containerType,
isWebkitBox);
if (!nextChildNeedsAnonItem) {
// There's nothing after the whitespace that we need to wrap, so we
@@ -9792,7 +9806,8 @@ nsCSSFrameConstructor::CreateNeededAnonFlexOrGridItems(
// we jump back to the beginning of the loop to skip over that child
// (and anything else non-wrappable after it)
MOZ_ASSERT(!iter.IsDone() &&
!iter.item().NeedsAnonFlexOrGridItem(aState, containerType),
!iter.item().NeedsAnonFlexOrGridItem(aState, containerType,
isWebkitBox),
"hitEnd and/or nextChildNeedsAnonItem lied");
continue;
}
@@ -9802,7 +9817,8 @@ nsCSSFrameConstructor::CreateNeededAnonFlexOrGridItems(
// anonymous flex/grid item. Now we see how many children after it also want
// to be wrapped in an anonymous flex/grid item.
FCItemIterator endIter(iter); // iterator to find the end of the group
endIter.SkipItemsThatNeedAnonFlexOrGridItem(aState, containerType);
endIter.SkipItemsThatNeedAnonFlexOrGridItem(aState, containerType,
isWebkitBox);
NS_ASSERTION(iter != endIter,
"Should've had at least one wrappable child to seek past");
@@ -12042,8 +12058,10 @@ nsCSSFrameConstructor::WipeContainingBlock(nsFrameConstructorState& aState,
// Check if we're adding to-be-wrapped content right *after* an existing
// anonymous flex or grid item (which would need to absorb this content).
nsIAtom* containerType = aFrame->GetType();
bool isWebkitBox = IsWebkitBox(aFrame);
if (aPrevSibling && IsAnonymousFlexOrGridItem(aPrevSibling) &&
iter.item().NeedsAnonFlexOrGridItem(aState, containerType)) {
iter.item().NeedsAnonFlexOrGridItem(aState, containerType,
isWebkitBox)) {
RecreateFramesForContent(aFrame->GetContent(), true,
REMOVE_FOR_RECONSTRUCTION, nullptr);
return true;
@@ -12055,7 +12073,8 @@ nsCSSFrameConstructor::WipeContainingBlock(nsFrameConstructorState& aState,
// Jump to the last entry in the list
iter.SetToEnd();
iter.Prev();
if (iter.item().NeedsAnonFlexOrGridItem(aState, containerType)) {
if (iter.item().NeedsAnonFlexOrGridItem(aState, containerType,
isWebkitBox)) {
RecreateFramesForContent(aFrame->GetContent(), true,
REMOVE_FOR_RECONSTRUCTION, nullptr);
return true;
@@ -12082,7 +12101,8 @@ nsCSSFrameConstructor::WipeContainingBlock(nsFrameConstructorState& aState,
// they're perfectly happy to go here -- they won't cause a reframe.
nsIFrame* containerFrame = aFrame->GetParent();
if (!iter.SkipItemsThatNeedAnonFlexOrGridItem(aState,
containerFrame->GetType())) {
containerFrame->GetType(),
IsWebkitBox(containerFrame))) {
// We hit something that _doesn't_ need an anonymous flex item!
// Rebuild the flex container to bust it out.
RecreateFramesForContent(containerFrame->GetContent(), true,
@@ -12534,10 +12554,14 @@ Iterator::SkipItemsNotWantingParentType(ParentType aParentType)
return false;
}
// Note: we implement -webkit-box & -webkit-inline-box using
// nsFlexContainerFrame, but we use different rules for what gets wrapped in an
// anonymous flex item.
bool
nsCSSFrameConstructor::FrameConstructionItem::
NeedsAnonFlexOrGridItem(const nsFrameConstructorState& aState,
nsIAtom* aContainerType)
nsIAtom* aContainerType,
bool aIsWebkitBox)
{
if (mFCData->mBits & FCDATA_IS_LINE_PARTICIPANT) {
// This will be an inline non-replaced box.
@@ -12555,6 +12579,12 @@ nsCSSFrameConstructor::FrameConstructionItem::
return true;
}
if (aIsWebkitBox &&
mStyleContext->StyleDisplay()->IsInlineOutsideStyle()) {
// In a -webkit-box, all inline-level content gets wrapped in an anon item.
return true;
}
return false;
}
@@ -12562,10 +12592,12 @@ inline bool
nsCSSFrameConstructor::FrameConstructionItemList::
Iterator::SkipItemsThatNeedAnonFlexOrGridItem(
const nsFrameConstructorState& aState,
nsIAtom* aContainerType)
nsIAtom* aContainerType,
bool aIsWebkitBox)
{
NS_PRECONDITION(!IsDone(), "Shouldn't be done yet");
while (item().NeedsAnonFlexOrGridItem(aState, aContainerType)) {
while (item().NeedsAnonFlexOrGridItem(aState, aContainerType,
aIsWebkitBox)) {
Next();
if (IsDone()) {
return true;
@@ -12578,10 +12610,12 @@ inline bool
nsCSSFrameConstructor::FrameConstructionItemList::
Iterator::SkipItemsThatDontNeedAnonFlexOrGridItem(
const nsFrameConstructorState& aState,
nsIAtom* aContainerType)
nsIAtom* aContainerType,
bool aIsWebkitBox)
{
NS_PRECONDITION(!IsDone(), "Shouldn't be done yet");
while (!(item().NeedsAnonFlexOrGridItem(aState, aContainerType))) {
while (!(item().NeedsAnonFlexOrGridItem(aState, aContainerType,
aIsWebkitBox))) {
Next();
if (IsDone()) {
return true;