mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1009214 part 1 - [css-grid] Don't wrap placeholders in an anonymous grid item. r=dholbert
This commit is contained in:
parent
1d9dc5cf18
commit
16cb7dcfbc
@ -9579,7 +9579,7 @@ nsCSSFrameConstructor::CreateNeededAnonFlexOrGridItems(
|
||||
FCItemIterator iter(aItems);
|
||||
do {
|
||||
// Advance iter past children that don't want to be wrapped
|
||||
if (iter.SkipItemsThatDontNeedAnonFlexOrGridItem(aState)) {
|
||||
if (iter.SkipItemsThatDontNeedAnonFlexOrGridItem(aState, containerType)) {
|
||||
// Hit the end of the items without finding any remaining children that
|
||||
// need to be wrapped. We're finished!
|
||||
return;
|
||||
@ -9601,7 +9601,8 @@ nsCSSFrameConstructor::CreateNeededAnonFlexOrGridItems(
|
||||
FCItemIterator afterWhitespaceIter(iter);
|
||||
bool hitEnd = afterWhitespaceIter.SkipWhitespace(aState);
|
||||
bool nextChildNeedsAnonItem =
|
||||
!hitEnd && afterWhitespaceIter.item().NeedsAnonFlexOrGridItem(aState);
|
||||
!hitEnd && afterWhitespaceIter.item().NeedsAnonFlexOrGridItem(aState,
|
||||
containerType);
|
||||
|
||||
if (!nextChildNeedsAnonItem) {
|
||||
// There's nothing after the whitespace that we need to wrap, so we
|
||||
@ -9615,7 +9616,7 @@ 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),
|
||||
!iter.item().NeedsAnonFlexOrGridItem(aState, containerType),
|
||||
"hitEnd and/or nextChildNeedsAnonItem lied");
|
||||
continue;
|
||||
}
|
||||
@ -9625,7 +9626,7 @@ 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);
|
||||
endIter.SkipItemsThatNeedAnonFlexOrGridItem(aState, containerType);
|
||||
|
||||
NS_ASSERTION(iter != endIter,
|
||||
"Should've had at least one wrappable child to seek past");
|
||||
@ -11831,8 +11832,9 @@ 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();
|
||||
if (aPrevSibling && IsAnonymousFlexOrGridItem(aPrevSibling) &&
|
||||
iter.item().NeedsAnonFlexOrGridItem(aState)) {
|
||||
iter.item().NeedsAnonFlexOrGridItem(aState, containerType)) {
|
||||
RecreateFramesForContent(aFrame->GetContent(), true,
|
||||
REMOVE_FOR_RECONSTRUCTION, nullptr);
|
||||
return true;
|
||||
@ -11844,7 +11846,7 @@ nsCSSFrameConstructor::WipeContainingBlock(nsFrameConstructorState& aState,
|
||||
// Jump to the last entry in the list
|
||||
iter.SetToEnd();
|
||||
iter.Prev();
|
||||
if (iter.item().NeedsAnonFlexOrGridItem(aState)) {
|
||||
if (iter.item().NeedsAnonFlexOrGridItem(aState, containerType)) {
|
||||
RecreateFramesForContent(aFrame->GetContent(), true,
|
||||
REMOVE_FOR_RECONSTRUCTION, nullptr);
|
||||
return true;
|
||||
@ -11869,10 +11871,11 @@ nsCSSFrameConstructor::WipeContainingBlock(nsFrameConstructorState& aState,
|
||||
FCItemIterator iter(aItems);
|
||||
// Skip over things that _do_ need an anonymous flex item, because
|
||||
// they're perfectly happy to go here -- they won't cause a reframe.
|
||||
if (!iter.SkipItemsThatNeedAnonFlexOrGridItem(aState)) {
|
||||
nsIFrame* containerFrame = aFrame->GetParent();
|
||||
if (!iter.SkipItemsThatNeedAnonFlexOrGridItem(aState,
|
||||
containerFrame->GetType())) {
|
||||
// We hit something that _doesn't_ need an anonymous flex item!
|
||||
// Rebuild the flex container to bust it out.
|
||||
nsIFrame* containerFrame = aFrame->GetParent();
|
||||
RecreateFramesForContent(containerFrame->GetContent(), true,
|
||||
REMOVE_FOR_RECONSTRUCTION, nullptr);
|
||||
return true;
|
||||
@ -12324,14 +12327,17 @@ Iterator::SkipItemsNotWantingParentType(ParentType aParentType)
|
||||
|
||||
bool
|
||||
nsCSSFrameConstructor::FrameConstructionItem::
|
||||
NeedsAnonFlexOrGridItem(const nsFrameConstructorState& aState)
|
||||
NeedsAnonFlexOrGridItem(const nsFrameConstructorState& aState,
|
||||
nsIAtom* aContainerType)
|
||||
{
|
||||
if (mFCData->mBits & FCDATA_IS_LINE_PARTICIPANT) {
|
||||
// This will be an inline non-replaced box.
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(mFCData->mBits & FCDATA_DISALLOW_OUT_OF_FLOW) &&
|
||||
// Bug 874718: Flex containers still wrap placeholders; Grid containers don't.
|
||||
if (aContainerType == nsGkAtoms::flexContainerFrame &&
|
||||
!(mFCData->mBits & FCDATA_DISALLOW_OUT_OF_FLOW) &&
|
||||
aState.GetGeometricParent(mStyleContext->StyleDisplay(), nullptr)) {
|
||||
// We're abspos or fixedpos, which means we'll spawn a placeholder which
|
||||
// we'll need to wrap in an anonymous flex item. So, we just treat
|
||||
@ -12346,10 +12352,11 @@ nsCSSFrameConstructor::FrameConstructionItem::
|
||||
inline bool
|
||||
nsCSSFrameConstructor::FrameConstructionItemList::
|
||||
Iterator::SkipItemsThatNeedAnonFlexOrGridItem(
|
||||
const nsFrameConstructorState& aState)
|
||||
const nsFrameConstructorState& aState,
|
||||
nsIAtom* aContainerType)
|
||||
{
|
||||
NS_PRECONDITION(!IsDone(), "Shouldn't be done yet");
|
||||
while (item().NeedsAnonFlexOrGridItem(aState)) {
|
||||
while (item().NeedsAnonFlexOrGridItem(aState, aContainerType)) {
|
||||
Next();
|
||||
if (IsDone()) {
|
||||
return true;
|
||||
@ -12361,10 +12368,11 @@ Iterator::SkipItemsThatNeedAnonFlexOrGridItem(
|
||||
inline bool
|
||||
nsCSSFrameConstructor::FrameConstructionItemList::
|
||||
Iterator::SkipItemsThatDontNeedAnonFlexOrGridItem(
|
||||
const nsFrameConstructorState& aState)
|
||||
const nsFrameConstructorState& aState,
|
||||
nsIAtom* aContainerType)
|
||||
{
|
||||
NS_PRECONDITION(!IsDone(), "Shouldn't be done yet");
|
||||
while (!(item().NeedsAnonFlexOrGridItem(aState))) {
|
||||
while (!(item().NeedsAnonFlexOrGridItem(aState, aContainerType))) {
|
||||
Next();
|
||||
if (IsDone()) {
|
||||
return true;
|
||||
|
@ -931,13 +931,13 @@ private:
|
||||
// Return whether the iterator is done after doing that.
|
||||
// The iterator must not be done when this is called.
|
||||
inline bool SkipItemsThatNeedAnonFlexOrGridItem(
|
||||
const nsFrameConstructorState& aState);
|
||||
const nsFrameConstructorState& aState, nsIAtom* aContainerType);
|
||||
|
||||
// Skip to the first frame that is a non-replaced inline or is
|
||||
// positioned. Return whether the iterator is done after doing that.
|
||||
// The iterator must not be done when this is called.
|
||||
inline bool SkipItemsThatDontNeedAnonFlexOrGridItem(
|
||||
const nsFrameConstructorState& aState);
|
||||
const nsFrameConstructorState& aState, nsIAtom* aContainerType);
|
||||
|
||||
// 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
|
||||
@ -1074,7 +1074,8 @@ private:
|
||||
|
||||
// Indicates whether (when in a flex or grid container) this item needs
|
||||
// to be wrapped in an anonymous block.
|
||||
bool NeedsAnonFlexOrGridItem(const nsFrameConstructorState& aState);
|
||||
bool NeedsAnonFlexOrGridItem(const nsFrameConstructorState& aState,
|
||||
nsIAtom* aContainerType);
|
||||
|
||||
// Don't call this unless the frametree really depends on the answer!
|
||||
// Especially so for generated content, where we don't want to reframe
|
||||
|
@ -34,11 +34,14 @@ class nsGridContainerFrame::GridItemCSSOrderIterator
|
||||
{
|
||||
public:
|
||||
enum OrderState { eUnknownOrder, eKnownOrdered, eKnownUnordered };
|
||||
enum ChildFilter { eSkipPlaceholders, eIncludeAll };
|
||||
GridItemCSSOrderIterator(nsIFrame* aGridContainer,
|
||||
nsIFrame::ChildListID aListID,
|
||||
ChildFilter aFilter = eSkipPlaceholders,
|
||||
OrderState aState = eUnknownOrder)
|
||||
: mChildren(aGridContainer->GetChildList(aListID))
|
||||
, mArrayIndex(0)
|
||||
, mSkipPlaceholders(aFilter == eSkipPlaceholders)
|
||||
#ifdef DEBUG
|
||||
, mGridContainer(aGridContainer)
|
||||
, mListID(aListID)
|
||||
@ -69,6 +72,10 @@ public:
|
||||
// XXX replace this with nsTArray::StableSort when bug 1147091 is fixed.
|
||||
std::stable_sort(mArray->begin(), mArray->end(), IsCSSOrderLessThan);
|
||||
}
|
||||
|
||||
if (mSkipPlaceholders) {
|
||||
SkipPlaceholders();
|
||||
}
|
||||
}
|
||||
|
||||
nsIFrame* operator*() const
|
||||
@ -80,6 +87,28 @@ public:
|
||||
return (*mArray)[mArrayIndex];
|
||||
}
|
||||
|
||||
/**
|
||||
* Skip over placeholder children.
|
||||
*/
|
||||
void SkipPlaceholders()
|
||||
{
|
||||
if (mEnumerator) {
|
||||
for (; !mEnumerator->AtEnd(); mEnumerator->Next()) {
|
||||
nsIFrame* child = mEnumerator->get();
|
||||
if (child->GetType() != nsGkAtoms::placeholderFrame) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (; mArrayIndex < mArray->Length(); ++mArrayIndex) {
|
||||
nsIFrame* child = (*mArray)[mArrayIndex];
|
||||
if (child->GetType() != nsGkAtoms::placeholderFrame) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool AtEnd() const
|
||||
{
|
||||
MOZ_ASSERT(mEnumerator || mArrayIndex <= mArray->Length());
|
||||
@ -100,9 +129,12 @@ public:
|
||||
MOZ_ASSERT(mArrayIndex < mArray->Length(), "iterating past end");
|
||||
++mArrayIndex;
|
||||
}
|
||||
if (mSkipPlaceholders) {
|
||||
SkipPlaceholders();
|
||||
}
|
||||
}
|
||||
|
||||
void Reset()
|
||||
void Reset(ChildFilter aFilter = eSkipPlaceholders)
|
||||
{
|
||||
if (mEnumerator) {
|
||||
mEnumerator.reset();
|
||||
@ -110,6 +142,10 @@ public:
|
||||
} else {
|
||||
mArrayIndex = 0;
|
||||
}
|
||||
mSkipPlaceholders = aFilter == eSkipPlaceholders;
|
||||
if (mSkipPlaceholders) {
|
||||
SkipPlaceholders();
|
||||
}
|
||||
}
|
||||
|
||||
bool ItemsAreAlreadyInOrder() const { return mEnumerator.isSome(); }
|
||||
@ -124,6 +160,8 @@ private:
|
||||
// Used if child list is *not* in ascending 'order'.
|
||||
Maybe<nsTArray<nsIFrame*>> mArray;
|
||||
size_t mArrayIndex;
|
||||
// Skip placeholder children in the iteration?
|
||||
bool mSkipPlaceholders;
|
||||
#ifdef DEBUG
|
||||
nsIFrame* mGridContainer;
|
||||
nsIFrame::ChildListID mListID;
|
||||
@ -1213,13 +1251,19 @@ nsGridContainerFrame::ReflowChildren(GridItemCSSOrderIterator& aIter,
|
||||
nsPresContext* pc = PresContext();
|
||||
for (; !aIter.AtEnd(); aIter.Next()) {
|
||||
nsIFrame* child = *aIter;
|
||||
GridArea* area = GetGridAreaForChild(child);
|
||||
MOZ_ASSERT(area && area->IsDefinite());
|
||||
LogicalRect cb = ContainingBlockFor(wm, *area, aColSizes, aRowSizes);
|
||||
cb += gridOrigin;
|
||||
const bool isGridItem = child->GetType() != nsGkAtoms::placeholderFrame;
|
||||
LogicalRect cb(wm);
|
||||
if (MOZ_LIKELY(isGridItem)) {
|
||||
GridArea* area = GetGridAreaForChild(child);
|
||||
MOZ_ASSERT(area && area->IsDefinite());
|
||||
cb = ContainingBlockFor(wm, *area, aColSizes, aRowSizes);
|
||||
cb += gridOrigin;
|
||||
} else {
|
||||
cb = aContentArea;
|
||||
}
|
||||
nsHTMLReflowState childRS(pc, aReflowState, child, cb.Size(wm));
|
||||
const LogicalMargin margin = childRS.ComputedLogicalMargin();
|
||||
if (childRS.ComputedBSize() == NS_AUTOHEIGHT) {
|
||||
if (childRS.ComputedBSize() == NS_AUTOHEIGHT && MOZ_LIKELY(isGridItem)) {
|
||||
// XXX the start of an align-self:stretch impl. Needs min-/max-bsize
|
||||
// clamping though, and check the prop value is actually 'stretch'!
|
||||
LogicalMargin bp = childRS.ComputedLogicalBorderPadding();
|
||||
@ -1331,7 +1375,7 @@ nsGridContainerFrame::Reflow(nsPresContext* aPresContext,
|
||||
|
||||
LogicalRect contentArea(wm, bp.IStart(wm), bp.BStart(wm),
|
||||
computedISize, bSize);
|
||||
normalFlowIter.Reset();
|
||||
normalFlowIter.Reset(GridItemCSSOrderIterator::eIncludeAll);
|
||||
ReflowChildren(normalFlowIter, contentArea, colSizes, rowSizes, aDesiredSize,
|
||||
aReflowState, aStatus);
|
||||
|
||||
@ -1368,7 +1412,8 @@ nsGridContainerFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
typedef GridItemCSSOrderIterator::OrderState OrderState;
|
||||
OrderState order = mIsNormalFlowInCSSOrder ? OrderState::eKnownOrdered
|
||||
: OrderState::eKnownUnordered;
|
||||
GridItemCSSOrderIterator iter(this, kPrincipalList, order);
|
||||
GridItemCSSOrderIterator iter(this, kPrincipalList,
|
||||
GridItemCSSOrderIterator::eIncludeAll, order);
|
||||
for (; !iter.AtEnd(); iter.Next()) {
|
||||
nsIFrame* child = *iter;
|
||||
BuildDisplayListForChild(aBuilder, child, aDirtyRect, childLists,
|
||||
@ -1438,8 +1483,7 @@ FrameWantsToBeInAnonymousGridItem(nsIFrame* aFrame)
|
||||
{
|
||||
// Note: This needs to match the logic in
|
||||
// nsCSSFrameConstructor::FrameConstructionItem::NeedsAnonFlexOrGridItem()
|
||||
return (aFrame->IsFrameOfType(nsIFrame::eLineParticipant) ||
|
||||
nsGkAtoms::placeholderFrame == aFrame->GetType());
|
||||
return aFrame->IsFrameOfType(nsIFrame::eLineParticipant);
|
||||
}
|
||||
|
||||
// Debugging method, to let us assert that our anonymous grid items are
|
||||
|
Loading…
Reference in New Issue
Block a user