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:
@@ -341,6 +341,15 @@ IsFlexOrGridContainer(const nsIFrame* aFrame)
|
|||||||
t == nsGkAtoms::gridContainerFrame;
|
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
|
#if DEBUG
|
||||||
static void
|
static void
|
||||||
AssertAnonymousFlexOrGridItemParent(const nsIFrame* aChild,
|
AssertAnonymousFlexOrGridItemParent(const nsIFrame* aChild,
|
||||||
@@ -9752,10 +9761,13 @@ nsCSSFrameConstructor::CreateNeededAnonFlexOrGridItems(
|
|||||||
}
|
}
|
||||||
|
|
||||||
nsIAtom* containerType = aParentFrame->GetType();
|
nsIAtom* containerType = aParentFrame->GetType();
|
||||||
|
const bool isWebkitBox = IsWebkitBox(aParentFrame);
|
||||||
|
|
||||||
FCItemIterator iter(aItems);
|
FCItemIterator iter(aItems);
|
||||||
do {
|
do {
|
||||||
// Advance iter past children that don't want to be wrapped
|
// 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
|
// Hit the end of the items without finding any remaining children that
|
||||||
// need to be wrapped. We're finished!
|
// need to be wrapped. We're finished!
|
||||||
return;
|
return;
|
||||||
@@ -9777,8 +9789,10 @@ nsCSSFrameConstructor::CreateNeededAnonFlexOrGridItems(
|
|||||||
FCItemIterator afterWhitespaceIter(iter);
|
FCItemIterator afterWhitespaceIter(iter);
|
||||||
bool hitEnd = afterWhitespaceIter.SkipWhitespace(aState);
|
bool hitEnd = afterWhitespaceIter.SkipWhitespace(aState);
|
||||||
bool nextChildNeedsAnonItem =
|
bool nextChildNeedsAnonItem =
|
||||||
!hitEnd && afterWhitespaceIter.item().NeedsAnonFlexOrGridItem(aState,
|
!hitEnd &&
|
||||||
containerType);
|
afterWhitespaceIter.item().NeedsAnonFlexOrGridItem(aState,
|
||||||
|
containerType,
|
||||||
|
isWebkitBox);
|
||||||
|
|
||||||
if (!nextChildNeedsAnonItem) {
|
if (!nextChildNeedsAnonItem) {
|
||||||
// There's nothing after the whitespace that we need to wrap, so we
|
// 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
|
// we jump back to the beginning of the loop to skip over that child
|
||||||
// (and anything else non-wrappable after it)
|
// (and anything else non-wrappable after it)
|
||||||
MOZ_ASSERT(!iter.IsDone() &&
|
MOZ_ASSERT(!iter.IsDone() &&
|
||||||
!iter.item().NeedsAnonFlexOrGridItem(aState, containerType),
|
!iter.item().NeedsAnonFlexOrGridItem(aState, containerType,
|
||||||
|
isWebkitBox),
|
||||||
"hitEnd and/or nextChildNeedsAnonItem lied");
|
"hitEnd and/or nextChildNeedsAnonItem lied");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -9802,7 +9817,8 @@ nsCSSFrameConstructor::CreateNeededAnonFlexOrGridItems(
|
|||||||
// anonymous flex/grid item. Now we see how many children after it also want
|
// anonymous flex/grid item. Now we see how many children after it also want
|
||||||
// to be wrapped in an anonymous flex/grid item.
|
// to be wrapped in an anonymous flex/grid item.
|
||||||
FCItemIterator endIter(iter); // iterator to find the end of the group
|
FCItemIterator endIter(iter); // iterator to find the end of the group
|
||||||
endIter.SkipItemsThatNeedAnonFlexOrGridItem(aState, containerType);
|
endIter.SkipItemsThatNeedAnonFlexOrGridItem(aState, containerType,
|
||||||
|
isWebkitBox);
|
||||||
|
|
||||||
NS_ASSERTION(iter != endIter,
|
NS_ASSERTION(iter != endIter,
|
||||||
"Should've had at least one wrappable child to seek past");
|
"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
|
// 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).
|
// anonymous flex or grid item (which would need to absorb this content).
|
||||||
nsIAtom* containerType = aFrame->GetType();
|
nsIAtom* containerType = aFrame->GetType();
|
||||||
|
bool isWebkitBox = IsWebkitBox(aFrame);
|
||||||
if (aPrevSibling && IsAnonymousFlexOrGridItem(aPrevSibling) &&
|
if (aPrevSibling && IsAnonymousFlexOrGridItem(aPrevSibling) &&
|
||||||
iter.item().NeedsAnonFlexOrGridItem(aState, containerType)) {
|
iter.item().NeedsAnonFlexOrGridItem(aState, containerType,
|
||||||
|
isWebkitBox)) {
|
||||||
RecreateFramesForContent(aFrame->GetContent(), true,
|
RecreateFramesForContent(aFrame->GetContent(), true,
|
||||||
REMOVE_FOR_RECONSTRUCTION, nullptr);
|
REMOVE_FOR_RECONSTRUCTION, nullptr);
|
||||||
return true;
|
return true;
|
||||||
@@ -12055,7 +12073,8 @@ nsCSSFrameConstructor::WipeContainingBlock(nsFrameConstructorState& aState,
|
|||||||
// Jump to the last entry in the list
|
// Jump to the last entry in the list
|
||||||
iter.SetToEnd();
|
iter.SetToEnd();
|
||||||
iter.Prev();
|
iter.Prev();
|
||||||
if (iter.item().NeedsAnonFlexOrGridItem(aState, containerType)) {
|
if (iter.item().NeedsAnonFlexOrGridItem(aState, containerType,
|
||||||
|
isWebkitBox)) {
|
||||||
RecreateFramesForContent(aFrame->GetContent(), true,
|
RecreateFramesForContent(aFrame->GetContent(), true,
|
||||||
REMOVE_FOR_RECONSTRUCTION, nullptr);
|
REMOVE_FOR_RECONSTRUCTION, nullptr);
|
||||||
return true;
|
return true;
|
||||||
@@ -12082,7 +12101,8 @@ nsCSSFrameConstructor::WipeContainingBlock(nsFrameConstructorState& aState,
|
|||||||
// they're perfectly happy to go here -- they won't cause a reframe.
|
// they're perfectly happy to go here -- they won't cause a reframe.
|
||||||
nsIFrame* containerFrame = aFrame->GetParent();
|
nsIFrame* containerFrame = aFrame->GetParent();
|
||||||
if (!iter.SkipItemsThatNeedAnonFlexOrGridItem(aState,
|
if (!iter.SkipItemsThatNeedAnonFlexOrGridItem(aState,
|
||||||
containerFrame->GetType())) {
|
containerFrame->GetType(),
|
||||||
|
IsWebkitBox(containerFrame))) {
|
||||||
// We hit something that _doesn't_ need an anonymous flex item!
|
// We hit something that _doesn't_ need an anonymous flex item!
|
||||||
// Rebuild the flex container to bust it out.
|
// Rebuild the flex container to bust it out.
|
||||||
RecreateFramesForContent(containerFrame->GetContent(), true,
|
RecreateFramesForContent(containerFrame->GetContent(), true,
|
||||||
@@ -12534,10 +12554,14 @@ Iterator::SkipItemsNotWantingParentType(ParentType aParentType)
|
|||||||
return false;
|
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
|
bool
|
||||||
nsCSSFrameConstructor::FrameConstructionItem::
|
nsCSSFrameConstructor::FrameConstructionItem::
|
||||||
NeedsAnonFlexOrGridItem(const nsFrameConstructorState& aState,
|
NeedsAnonFlexOrGridItem(const nsFrameConstructorState& aState,
|
||||||
nsIAtom* aContainerType)
|
nsIAtom* aContainerType,
|
||||||
|
bool aIsWebkitBox)
|
||||||
{
|
{
|
||||||
if (mFCData->mBits & FCDATA_IS_LINE_PARTICIPANT) {
|
if (mFCData->mBits & FCDATA_IS_LINE_PARTICIPANT) {
|
||||||
// This will be an inline non-replaced box.
|
// This will be an inline non-replaced box.
|
||||||
@@ -12555,6 +12579,12 @@ nsCSSFrameConstructor::FrameConstructionItem::
|
|||||||
return true;
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -12562,10 +12592,12 @@ inline bool
|
|||||||
nsCSSFrameConstructor::FrameConstructionItemList::
|
nsCSSFrameConstructor::FrameConstructionItemList::
|
||||||
Iterator::SkipItemsThatNeedAnonFlexOrGridItem(
|
Iterator::SkipItemsThatNeedAnonFlexOrGridItem(
|
||||||
const nsFrameConstructorState& aState,
|
const nsFrameConstructorState& aState,
|
||||||
nsIAtom* aContainerType)
|
nsIAtom* aContainerType,
|
||||||
|
bool aIsWebkitBox)
|
||||||
{
|
{
|
||||||
NS_PRECONDITION(!IsDone(), "Shouldn't be done yet");
|
NS_PRECONDITION(!IsDone(), "Shouldn't be done yet");
|
||||||
while (item().NeedsAnonFlexOrGridItem(aState, aContainerType)) {
|
while (item().NeedsAnonFlexOrGridItem(aState, aContainerType,
|
||||||
|
aIsWebkitBox)) {
|
||||||
Next();
|
Next();
|
||||||
if (IsDone()) {
|
if (IsDone()) {
|
||||||
return true;
|
return true;
|
||||||
@@ -12578,10 +12610,12 @@ inline bool
|
|||||||
nsCSSFrameConstructor::FrameConstructionItemList::
|
nsCSSFrameConstructor::FrameConstructionItemList::
|
||||||
Iterator::SkipItemsThatDontNeedAnonFlexOrGridItem(
|
Iterator::SkipItemsThatDontNeedAnonFlexOrGridItem(
|
||||||
const nsFrameConstructorState& aState,
|
const nsFrameConstructorState& aState,
|
||||||
nsIAtom* aContainerType)
|
nsIAtom* aContainerType,
|
||||||
|
bool aIsWebkitBox)
|
||||||
{
|
{
|
||||||
NS_PRECONDITION(!IsDone(), "Shouldn't be done yet");
|
NS_PRECONDITION(!IsDone(), "Shouldn't be done yet");
|
||||||
while (!(item().NeedsAnonFlexOrGridItem(aState, aContainerType))) {
|
while (!(item().NeedsAnonFlexOrGridItem(aState, aContainerType,
|
||||||
|
aIsWebkitBox))) {
|
||||||
Next();
|
Next();
|
||||||
if (IsDone()) {
|
if (IsDone()) {
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -925,13 +925,15 @@ private:
|
|||||||
// Return whether the iterator is done after doing that.
|
// Return whether the iterator is done after doing that.
|
||||||
// The iterator must not be done when this is called.
|
// The iterator must not be done when this is called.
|
||||||
inline bool SkipItemsThatNeedAnonFlexOrGridItem(
|
inline bool SkipItemsThatNeedAnonFlexOrGridItem(
|
||||||
const nsFrameConstructorState& aState, nsIAtom* aContainerType);
|
const nsFrameConstructorState& aState, nsIAtom* aContainerType,
|
||||||
|
bool aIsWebkitBox);
|
||||||
|
|
||||||
// Skip to the first frame that is a non-replaced inline or is
|
// Skip to the first frame that is a non-replaced inline or is
|
||||||
// positioned. Return whether the iterator is done after doing that.
|
// positioned. Return whether the iterator is done after doing that.
|
||||||
// The iterator must not be done when this is called.
|
// The iterator must not be done when this is called.
|
||||||
inline bool SkipItemsThatDontNeedAnonFlexOrGridItem(
|
inline bool SkipItemsThatDontNeedAnonFlexOrGridItem(
|
||||||
const nsFrameConstructorState& aState, nsIAtom* aContainerType);
|
const nsFrameConstructorState& aState, nsIAtom* aContainerType,
|
||||||
|
bool aIsWebkitBox);
|
||||||
|
|
||||||
// Skip over all items that do not want a ruby parent. Return whether
|
// Skip over all items that do not want a ruby parent. Return whether
|
||||||
// the iterator is done after doing that. The iterator must not be done
|
// the iterator is done after doing that. The iterator must not be done
|
||||||
@@ -1067,9 +1069,13 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Indicates whether (when in a flex or grid container) this item needs
|
// Indicates whether (when in a flex or grid container) this item needs
|
||||||
// to be wrapped in an anonymous block.
|
// to be wrapped in an anonymous block. (Note that we implement
|
||||||
|
// -webkit-box/-webkit-inline-box using our standard flexbox frame class,
|
||||||
|
// but we use different rules for what gets wrapped. The aIsWebkitBox
|
||||||
|
// parameter here tells us whether to use those different rules.)
|
||||||
bool NeedsAnonFlexOrGridItem(const nsFrameConstructorState& aState,
|
bool NeedsAnonFlexOrGridItem(const nsFrameConstructorState& aState,
|
||||||
nsIAtom* aContainerType);
|
nsIAtom* aContainerType,
|
||||||
|
bool aIsWebkitBox);
|
||||||
|
|
||||||
// Don't call this unless the frametree really depends on the answer!
|
// Don't call this unless the frametree really depends on the answer!
|
||||||
// Especially so for generated content, where we don't want to reframe
|
// Especially so for generated content, where we don't want to reframe
|
||||||
|
|||||||
Reference in New Issue
Block a user