mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1107786 - part 1, [css-grid] Implement layout and painting per the CSS 'order' property for normal flow grid items. r=dholbert
This commit is contained in:
parent
8022fc884e
commit
ee70e64e09
@ -8,9 +8,12 @@
|
|||||||
|
|
||||||
#include "nsGridContainerFrame.h"
|
#include "nsGridContainerFrame.h"
|
||||||
|
|
||||||
|
#include <algorithm> // for std::stable_sort
|
||||||
|
#include <limits>
|
||||||
#include "mozilla/Maybe.h"
|
#include "mozilla/Maybe.h"
|
||||||
#include "nsAbsoluteContainingBlock.h"
|
#include "nsAbsoluteContainingBlock.h"
|
||||||
#include "nsAlgorithm.h" // for clamped()
|
#include "nsAlgorithm.h" // for clamped()
|
||||||
|
#include "nsAutoPtr.h"
|
||||||
#include "nsCSSAnonBoxes.h"
|
#include "nsCSSAnonBoxes.h"
|
||||||
#include "nsDataHashtable.h"
|
#include "nsDataHashtable.h"
|
||||||
#include "nsDisplayList.h"
|
#include "nsDisplayList.h"
|
||||||
@ -24,6 +27,106 @@
|
|||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
typedef nsGridContainerFrame::TrackSize TrackSize;
|
typedef nsGridContainerFrame::TrackSize TrackSize;
|
||||||
|
|
||||||
|
class nsGridContainerFrame::GridItemCSSOrderIterator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum OrderState { eUnknownOrder, eKnownOrdered, eKnownUnordered };
|
||||||
|
GridItemCSSOrderIterator(nsIFrame* aGridContainer,
|
||||||
|
nsIFrame::ChildListID aListID,
|
||||||
|
OrderState aState = eUnknownOrder)
|
||||||
|
: mChildren(aGridContainer->GetChildList(aListID))
|
||||||
|
, mArrayIndex(0)
|
||||||
|
#ifdef DEBUG
|
||||||
|
, mGridContainer(aGridContainer)
|
||||||
|
, mListID(aListID)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
size_t count = 0;
|
||||||
|
bool isOrdered = aState != eKnownUnordered;
|
||||||
|
if (aState == eUnknownOrder) {
|
||||||
|
auto maxOrder = std::numeric_limits<int32_t>::min();
|
||||||
|
for (nsFrameList::Enumerator e(mChildren); !e.AtEnd(); e.Next()) {
|
||||||
|
++count;
|
||||||
|
int32_t order = e.get()->StylePosition()->mOrder;
|
||||||
|
if (order < maxOrder) {
|
||||||
|
isOrdered = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
maxOrder = order;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isOrdered) {
|
||||||
|
mEnumerator.emplace(mChildren);
|
||||||
|
} else {
|
||||||
|
count *= 2; // XXX somewhat arbitrary estimate for now...
|
||||||
|
mArray.emplace(count);
|
||||||
|
for (nsFrameList::Enumerator e(mChildren); !e.AtEnd(); e.Next()) {
|
||||||
|
mArray->AppendElement(e.get());
|
||||||
|
}
|
||||||
|
// XXX replace this with nsTArray::StableSort when bug 1147091 is fixed.
|
||||||
|
std::stable_sort(mArray->begin(), mArray->end(), IsCSSOrderLessThan);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nsIFrame* operator*() const
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(!AtEnd());
|
||||||
|
if (mEnumerator) {
|
||||||
|
return mEnumerator->get();
|
||||||
|
}
|
||||||
|
return (*mArray)[mArrayIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AtEnd() const
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(mEnumerator || mArrayIndex <= mArray->Length());
|
||||||
|
return mEnumerator ? mEnumerator->AtEnd() : mArrayIndex >= mArray->Length();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Next()
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
nsFrameList list = mGridContainer->GetChildList(mListID);
|
||||||
|
MOZ_ASSERT(list.FirstChild() == mChildren.FirstChild() &&
|
||||||
|
list.LastChild() == mChildren.LastChild(),
|
||||||
|
"the list of child frames must not change while iterating!");
|
||||||
|
#endif
|
||||||
|
if (mEnumerator) {
|
||||||
|
mEnumerator->Next();
|
||||||
|
} else {
|
||||||
|
MOZ_ASSERT(mArrayIndex < mArray->Length(), "iterating past end");
|
||||||
|
++mArrayIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Reset()
|
||||||
|
{
|
||||||
|
if (mEnumerator) {
|
||||||
|
mEnumerator.reset();
|
||||||
|
mEnumerator.emplace(mChildren);
|
||||||
|
} else {
|
||||||
|
mArrayIndex = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ItemsAreAlreadyInOrder() const { return mEnumerator.isSome(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
static bool IsCSSOrderLessThan(nsIFrame* const& a, nsIFrame* const& b)
|
||||||
|
{ return a->StylePosition()->mOrder < b->StylePosition()->mOrder; }
|
||||||
|
|
||||||
|
nsFrameList mChildren;
|
||||||
|
// Used if child list is already in ascending 'order'.
|
||||||
|
Maybe<nsFrameList::Enumerator> mEnumerator;
|
||||||
|
// Used if child list is *not* in ascending 'order'.
|
||||||
|
Maybe<nsTArray<nsIFrame*>> mArray;
|
||||||
|
size_t mArrayIndex;
|
||||||
|
#ifdef DEBUG
|
||||||
|
nsIFrame* mGridContainer;
|
||||||
|
nsIFrame::ChildListID mListID;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Search for the aNth occurrence of aName in aNameList (forward), starting at
|
* Search for the aNth occurrence of aName in aNameList (forward), starting at
|
||||||
* the zero-based aFromIndex, and return the 1-based index (line number).
|
* the zero-based aFromIndex, and return the 1-based index (line number).
|
||||||
@ -690,15 +793,16 @@ nsGridContainerFrame::InitializeGridBounds(const nsStylePosition* aStyle)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsGridContainerFrame::PlaceGridItems(const nsStylePosition* aStyle)
|
nsGridContainerFrame::PlaceGridItems(GridItemCSSOrderIterator& aIter,
|
||||||
|
const nsStylePosition* aStyle)
|
||||||
{
|
{
|
||||||
mCellMap.ClearOccupied();
|
mCellMap.ClearOccupied();
|
||||||
InitializeGridBounds(aStyle);
|
InitializeGridBounds(aStyle);
|
||||||
|
|
||||||
// http://dev.w3.org/csswg/css-grid/#line-placement
|
// http://dev.w3.org/csswg/css-grid/#line-placement
|
||||||
// Resolve definite positions per spec chap 9.2.
|
// Resolve definite positions per spec chap 9.2.
|
||||||
for (nsFrameList::Enumerator e(PrincipalChildList()); !e.AtEnd(); e.Next()) {
|
for (; !aIter.AtEnd(); aIter.Next()) {
|
||||||
nsIFrame* child = e.get();
|
nsIFrame* child = *aIter;
|
||||||
const GridArea& area = PlaceDefinite(child, aStyle);
|
const GridArea& area = PlaceDefinite(child, aStyle);
|
||||||
GridArea* prop = GetGridAreaForChild(child);
|
GridArea* prop = GetGridAreaForChild(child);
|
||||||
if (prop) {
|
if (prop) {
|
||||||
@ -726,8 +830,9 @@ nsGridContainerFrame::PlaceGridItems(const nsStylePosition* aStyle)
|
|||||||
}
|
}
|
||||||
auto placeAutoMinorFunc = isRowOrder ? &nsGridContainerFrame::PlaceAutoCol
|
auto placeAutoMinorFunc = isRowOrder ? &nsGridContainerFrame::PlaceAutoCol
|
||||||
: &nsGridContainerFrame::PlaceAutoRow;
|
: &nsGridContainerFrame::PlaceAutoRow;
|
||||||
for (nsFrameList::Enumerator e(PrincipalChildList()); !e.AtEnd(); e.Next()) {
|
aIter.Reset();
|
||||||
nsIFrame* child = e.get();
|
for (; !aIter.AtEnd(); aIter.Next()) {
|
||||||
|
nsIFrame* child = *aIter;
|
||||||
GridArea* area = GetGridAreaForChild(child);
|
GridArea* area = GetGridAreaForChild(child);
|
||||||
LineRange& major = isRowOrder ? area->mRows : area->mCols;
|
LineRange& major = isRowOrder ? area->mRows : area->mCols;
|
||||||
LineRange& minor = isRowOrder ? area->mCols : area->mRows;
|
LineRange& minor = isRowOrder ? area->mCols : area->mRows;
|
||||||
@ -760,8 +865,9 @@ nsGridContainerFrame::PlaceGridItems(const nsStylePosition* aStyle)
|
|||||||
uint32_t cursorMinor = 1;
|
uint32_t cursorMinor = 1;
|
||||||
auto placeAutoMajorFunc = isRowOrder ? &nsGridContainerFrame::PlaceAutoRow
|
auto placeAutoMajorFunc = isRowOrder ? &nsGridContainerFrame::PlaceAutoRow
|
||||||
: &nsGridContainerFrame::PlaceAutoCol;
|
: &nsGridContainerFrame::PlaceAutoCol;
|
||||||
for (nsFrameList::Enumerator e(PrincipalChildList()); !e.AtEnd(); e.Next()) {
|
aIter.Reset();
|
||||||
nsIFrame* child = e.get();
|
for (; !aIter.AtEnd(); aIter.Next()) {
|
||||||
|
nsIFrame* child = *aIter;
|
||||||
GridArea* area = GetGridAreaForChild(child);
|
GridArea* area = GetGridAreaForChild(child);
|
||||||
LineRange& major = isRowOrder ? area->mRows : area->mCols;
|
LineRange& major = isRowOrder ? area->mRows : area->mCols;
|
||||||
LineRange& minor = isRowOrder ? area->mCols : area->mRows;
|
LineRange& minor = isRowOrder ? area->mCols : area->mRows;
|
||||||
@ -988,7 +1094,8 @@ nsGridContainerFrame::ContainingBlockForAbsPos(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsGridContainerFrame::ReflowChildren(const LogicalRect& aContentArea,
|
nsGridContainerFrame::ReflowChildren(GridItemCSSOrderIterator& aIter,
|
||||||
|
const LogicalRect& aContentArea,
|
||||||
const nsTArray<TrackSize>& aColSizes,
|
const nsTArray<TrackSize>& aColSizes,
|
||||||
const nsTArray<TrackSize>& aRowSizes,
|
const nsTArray<TrackSize>& aRowSizes,
|
||||||
nsHTMLReflowMetrics& aDesiredSize,
|
nsHTMLReflowMetrics& aDesiredSize,
|
||||||
@ -999,8 +1106,8 @@ nsGridContainerFrame::ReflowChildren(const LogicalRect& aContentArea,
|
|||||||
const LogicalPoint gridOrigin(aContentArea.Origin(wm));
|
const LogicalPoint gridOrigin(aContentArea.Origin(wm));
|
||||||
const nscoord gridWidth = aContentArea.Width(wm);
|
const nscoord gridWidth = aContentArea.Width(wm);
|
||||||
nsPresContext* pc = PresContext();
|
nsPresContext* pc = PresContext();
|
||||||
for (nsFrameList::Enumerator e(PrincipalChildList()); !e.AtEnd(); e.Next()) {
|
for (; !aIter.AtEnd(); aIter.Next()) {
|
||||||
nsIFrame* child = e.get();
|
nsIFrame* child = *aIter;
|
||||||
GridArea* area = GetGridAreaForChild(child);
|
GridArea* area = GetGridAreaForChild(child);
|
||||||
MOZ_ASSERT(area && area->IsDefinite());
|
MOZ_ASSERT(area && area->IsDefinite());
|
||||||
LogicalRect cb = ContainingBlockFor(wm, *area, aColSizes, aRowSizes);
|
LogicalRect cb = ContainingBlockFor(wm, *area, aColSizes, aRowSizes);
|
||||||
@ -1088,7 +1195,9 @@ nsGridContainerFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
bp.ApplySkipSides(GetLogicalSkipSides());
|
bp.ApplySkipSides(GetLogicalSkipSides());
|
||||||
const nsStylePosition* stylePos = aReflowState.mStylePosition;
|
const nsStylePosition* stylePos = aReflowState.mStylePosition;
|
||||||
InitImplicitNamedAreas(stylePos);
|
InitImplicitNamedAreas(stylePos);
|
||||||
PlaceGridItems(stylePos);
|
GridItemCSSOrderIterator normalFlowIter(this, kPrincipalList);
|
||||||
|
mIsNormalFlowInCSSOrder = normalFlowIter.ItemsAreAlreadyInOrder();
|
||||||
|
PlaceGridItems(normalFlowIter, stylePos);
|
||||||
|
|
||||||
nsAutoTArray<TrackSize, 32> colSizes;
|
nsAutoTArray<TrackSize, 32> colSizes;
|
||||||
nsAutoTArray<TrackSize, 32> rowSizes;
|
nsAutoTArray<TrackSize, 32> rowSizes;
|
||||||
@ -1115,7 +1224,8 @@ nsGridContainerFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
|
|
||||||
LogicalRect contentArea(wm, bp.IStart(wm), bp.BStart(wm),
|
LogicalRect contentArea(wm, bp.IStart(wm), bp.BStart(wm),
|
||||||
computedISize, bSize);
|
computedISize, bSize);
|
||||||
ReflowChildren(contentArea, colSizes, rowSizes, aDesiredSize,
|
normalFlowIter.Reset();
|
||||||
|
ReflowChildren(normalFlowIter, contentArea, colSizes, rowSizes, aDesiredSize,
|
||||||
aReflowState, aStatus);
|
aReflowState, aStatus);
|
||||||
|
|
||||||
FinishAndStoreOverflow(&aDesiredSize);
|
FinishAndStoreOverflow(&aDesiredSize);
|
||||||
@ -1140,8 +1250,12 @@ nsGridContainerFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|||||||
// inline-blocks in painting, so their borders/backgrounds all go on
|
// inline-blocks in painting, so their borders/backgrounds all go on
|
||||||
// the BlockBorderBackgrounds list.
|
// the BlockBorderBackgrounds list.
|
||||||
nsDisplayListSet childLists(aLists, aLists.BlockBorderBackgrounds());
|
nsDisplayListSet childLists(aLists, aLists.BlockBorderBackgrounds());
|
||||||
for (nsFrameList::Enumerator e(PrincipalChildList()); !e.AtEnd(); e.Next()) {
|
typedef GridItemCSSOrderIterator::OrderState OrderState;
|
||||||
nsIFrame* child = e.get();
|
OrderState order = mIsNormalFlowInCSSOrder ? OrderState::eKnownOrdered
|
||||||
|
: OrderState::eKnownUnordered;
|
||||||
|
GridItemCSSOrderIterator iter(this, kPrincipalList, order);
|
||||||
|
for (; !iter.AtEnd(); iter.Next()) {
|
||||||
|
nsIFrame* child = *iter;
|
||||||
BuildDisplayListForChild(aBuilder, child, aDirtyRect, childLists,
|
BuildDisplayListForChild(aBuilder, child, aDirtyRect, childLists,
|
||||||
::GetDisplayFlagsForGridItem(child));
|
::GetDisplayFlagsForGridItem(child));
|
||||||
}
|
}
|
||||||
|
@ -64,6 +64,7 @@ protected:
|
|||||||
typedef mozilla::LogicalRect LogicalRect;
|
typedef mozilla::LogicalRect LogicalRect;
|
||||||
typedef mozilla::WritingMode WritingMode;
|
typedef mozilla::WritingMode WritingMode;
|
||||||
typedef mozilla::css::GridNamedArea GridNamedArea;
|
typedef mozilla::css::GridNamedArea GridNamedArea;
|
||||||
|
class GridItemCSSOrderIterator;
|
||||||
friend nsContainerFrame* NS_NewGridContainerFrame(nsIPresShell* aPresShell,
|
friend nsContainerFrame* NS_NewGridContainerFrame(nsIPresShell* aPresShell,
|
||||||
nsStyleContext* aContext);
|
nsStyleContext* aContext);
|
||||||
explicit nsGridContainerFrame(nsStyleContext* aContext) : nsContainerFrame(aContext) {}
|
explicit nsGridContainerFrame(nsStyleContext* aContext) : nsContainerFrame(aContext) {}
|
||||||
@ -303,9 +304,11 @@ protected:
|
|||||||
* Place all child frames into the grid and expand the (implicit) grid as
|
* Place all child frames into the grid and expand the (implicit) grid as
|
||||||
* needed. The allocated GridAreas are stored in the GridAreaProperty
|
* needed. The allocated GridAreas are stored in the GridAreaProperty
|
||||||
* frame property on the child frame.
|
* frame property on the child frame.
|
||||||
|
* @param aIter a grid item iterator
|
||||||
* @param aStyle the StylePosition() for the grid container
|
* @param aStyle the StylePosition() for the grid container
|
||||||
*/
|
*/
|
||||||
void PlaceGridItems(const nsStylePosition* aStyle);
|
void PlaceGridItems(GridItemCSSOrderIterator& aIter,
|
||||||
|
const nsStylePosition* aStyle);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the end lines of the Explicit Grid (mExplicitGridCol[Row]End).
|
* Initialize the end lines of the Explicit Grid (mExplicitGridCol[Row]End).
|
||||||
@ -405,7 +408,8 @@ protected:
|
|||||||
/**
|
/**
|
||||||
* Reflow and place our children.
|
* Reflow and place our children.
|
||||||
*/
|
*/
|
||||||
void ReflowChildren(const LogicalRect& aContentArea,
|
void ReflowChildren(GridItemCSSOrderIterator& aIter,
|
||||||
|
const LogicalRect& aContentArea,
|
||||||
const nsTArray<TrackSize>& aColSizes,
|
const nsTArray<TrackSize>& aColSizes,
|
||||||
const nsTArray<TrackSize>& aRowSizes,
|
const nsTArray<TrackSize>& aRowSizes,
|
||||||
nsHTMLReflowMetrics& aDesiredSize,
|
nsHTMLReflowMetrics& aDesiredSize,
|
||||||
@ -435,6 +439,11 @@ private:
|
|||||||
// Same for the implicit grid
|
// Same for the implicit grid
|
||||||
uint32_t mGridColEnd; // always >= mExplicitGridColEnd
|
uint32_t mGridColEnd; // always >= mExplicitGridColEnd
|
||||||
uint32_t mGridRowEnd; // always >= mExplicitGridRowEnd
|
uint32_t mGridRowEnd; // always >= mExplicitGridRowEnd
|
||||||
|
/**
|
||||||
|
* True iff the normal flow children are already in CSS 'order' in the
|
||||||
|
* order they occur in the child frame list.
|
||||||
|
*/
|
||||||
|
bool mIsNormalFlowInCSSOrder : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* nsGridContainerFrame_h___ */
|
#endif /* nsGridContainerFrame_h___ */
|
||||||
|
Loading…
Reference in New Issue
Block a user