Bug 1151204 part 2 - [css-grid] Add methods for finding the first/last grid item in Grid Order in this fragment. r=dholbert
authorMats Palmgren <mats@mozilla.com>
Sat, 01 Oct 2016 02:26:39 +0200
changeset 316102 33bd454be96a44c66a1651f3e1b4d098e4f45f07
parent 316101 bb3080bc1aad672b53575dc983f1bd2c3e1718a0
child 316103 5d2110357137d05ff2b9695cff79329cf907f98c
push id30759
push userphilringnalda@gmail.com
push dateSat, 01 Oct 2016 06:25:09 +0000
treeherdermozilla-central@fcc62bbf09ee [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdholbert
bugs1151204
milestone52.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1151204 part 2 - [css-grid] Add methods for finding the first/last grid item in Grid Order in this fragment. r=dholbert
layout/generic/nsGridContainerFrame.cpp
layout/generic/nsGridContainerFrame.h
--- a/layout/generic/nsGridContainerFrame.cpp
+++ b/layout/generic/nsGridContainerFrame.cpp
@@ -6361,16 +6361,83 @@ nsGridContainerFrame::MergeSortedExcessO
   if (eoc) {
     ::MergeSortedFrameLists(*eoc, aList, GetContent());
   } else {
     SetPropTableFrames(new (PresContext()->PresShell()) nsFrameList(aList),
                        ExcessOverflowContainersProperty());
   }
 }
 
+/* static */ nsGridContainerFrame::FindItemInGridOrderResult
+nsGridContainerFrame::FindFirstItemInGridOrder(
+  GridItemCSSOrderIterator& aIter,
+  const nsTArray<GridItemInfo>& aGridItems,
+  LineRange GridArea::* aMajor,
+  LineRange GridArea::* aMinor,
+  uint32_t aFragmentStartTrack)
+{
+  FindItemInGridOrderResult result = { nullptr, false };
+  uint32_t minMajor = kTranslatedMaxLine + 1;
+  uint32_t minMinor = kTranslatedMaxLine + 1;
+  aIter.Reset();
+  for (; !aIter.AtEnd(); aIter.Next()) {
+    const GridItemInfo& item = aGridItems[aIter.GridItemIndex()];
+    if ((item.mArea.*aMajor).mEnd <= aFragmentStartTrack) {
+      continue; // item doesn't span any track in this fragment
+    }
+    uint32_t major = (item.mArea.*aMajor).mStart;
+    uint32_t minor = (item.mArea.*aMinor).mStart;
+    if (major < minMajor || (major == minMajor && minor < minMinor)) {
+      minMajor = major;
+      minMinor = minor;
+      result.mItem = &item;
+      result.mIsInEdgeTrack = major == 0U;
+    }
+  }
+  return result;
+}
+
+/* static */ nsGridContainerFrame::FindItemInGridOrderResult
+nsGridContainerFrame::FindLastItemInGridOrder(
+  ReverseGridItemCSSOrderIterator& aIter,
+  const nsTArray<GridItemInfo>& aGridItems,
+  LineRange GridArea::* aMajor,
+  LineRange GridArea::* aMinor,
+  uint32_t aFragmentStartTrack,
+  uint32_t aFirstExcludedTrack)
+{
+  FindItemInGridOrderResult result = { nullptr, false };
+  int32_t maxMajor = -1;
+  int32_t maxMinor = -1;
+  aIter.Reset();
+  int32_t lastMajorTrack = int32_t(aFirstExcludedTrack) - 1;
+  for (; !aIter.AtEnd(); aIter.Next()) {
+    const GridItemInfo& item = aGridItems[aIter.GridItemIndex()];
+    // Subtract 1 from the end line to get the item's last track index.
+    int32_t major = (item.mArea.*aMajor).mEnd - 1;
+    // Currently, this method is only called with aFirstExcludedTrack ==
+    // the first track in the next fragment, so we take the opportunity
+    // to assert this item really belongs to this fragment.
+    MOZ_ASSERT((item.mArea.*aMajor).mStart < aFirstExcludedTrack,
+               "found an item that belongs to some later fragment");
+    if (major < int32_t(aFragmentStartTrack)) {
+      continue; // item doesn't span any track in this fragment
+    }
+    int32_t minor = (item.mArea.*aMinor).mEnd - 1;
+    MOZ_ASSERT(minor >= 0 && major >= 0, "grid item must have span >= 1");
+    if (major > maxMajor || (major == maxMajor && minor > maxMinor)) {
+      maxMajor = major;
+      maxMinor = minor;
+      result.mItem = &item;
+      result.mIsInEdgeTrack = major == lastMajorTrack;
+    }
+  }
+  return result;
+}
+
 #ifdef DEBUG
 void
 nsGridContainerFrame::SetInitialChildList(ChildListID  aListID,
                                           nsFrameList& aChildList)
 {
   ChildListIDs supportedLists = kAbsoluteList | kFixedList | kPrincipalList;
   MOZ_ASSERT(supportedLists.Contains(aListID), "unexpected child list");
 
--- a/layout/generic/nsGridContainerFrame.h
+++ b/layout/generic/nsGridContainerFrame.h
@@ -189,16 +189,23 @@ public:
   struct TrackSize;
   struct GridItemInfo;
   struct GridReflowInput;
   template<typename Iterator> class GridItemCSSOrderIteratorT;
   typedef GridItemCSSOrderIteratorT<nsFrameList::iterator>
     GridItemCSSOrderIterator;
   typedef GridItemCSSOrderIteratorT<nsFrameList::reverse_iterator>
     ReverseGridItemCSSOrderIterator;
+  struct FindItemInGridOrderResult
+  {
+    // The first(last) item in (reverse) grid order.
+    const GridItemInfo* mItem;
+    // Does the above item span the first(last) track?
+    bool mIsInEdgeTrack;
+  };
 protected:
   static const uint32_t kAutoLine;
   // The maximum line number, in the zero-based translated grid.
   static const uint32_t kTranslatedMaxLine;
   typedef mozilla::LogicalPoint LogicalPoint;
   typedef mozilla::LogicalRect LogicalRect;
   typedef mozilla::LogicalSize LogicalSize;
   typedef mozilla::WritingMode WritingMode;
@@ -249,16 +256,44 @@ protected:
   // Helper for AppendFrames / InsertFrames.
   void NoteNewChildren(ChildListID aListID, const nsFrameList& aFrameList);
 
   // Helper to move child frames into the kOverflowList.
   void MergeSortedOverflow(nsFrameList& aList);
   // Helper to move child frames into the kExcessOverflowContainersList:.
   void MergeSortedExcessOverflowContainers(nsFrameList& aList);
 
+  /**
+   * Find the first item in Grid Order in this fragment.
+   * https://drafts.csswg.org/css-grid/#grid-order
+   * @param aFragmentStartTrack is the first track in this fragment in the same
+   * axis as aMajor.  Pass zero if that's not the axis we're fragmenting in.
+   */
+  static FindItemInGridOrderResult
+  FindFirstItemInGridOrder(GridItemCSSOrderIterator& aIter,
+                           const nsTArray<GridItemInfo>& aGridItems,
+                           LineRange GridArea::* aMajor,
+                           LineRange GridArea::* aMinor,
+                           uint32_t aFragmentStartTrack);
+  /**
+   * Find the last item in Grid Order in this fragment.
+   * @param aFragmentStartTrack is the first track in this fragment in the same
+   * axis as aMajor.  Pass zero if that's not the axis we're fragmenting in.
+   * @param aFirstExcludedTrack should be the first track in the next fragment
+   * or one beyond the final track in the last fragment, in aMajor's axis.
+   * Pass the number of tracks if that's not the axis we're fragmenting in.
+   */
+  static FindItemInGridOrderResult
+  FindLastItemInGridOrder(ReverseGridItemCSSOrderIterator& aIter,
+                          const nsTArray<GridItemInfo>& aGridItems,
+                          LineRange GridArea::* aMajor,
+                          LineRange GridArea::* aMinor,
+                          uint32_t aFragmentStartTrack,
+                          uint32_t aFirstExcludedTrack);
+
 #ifdef DEBUG
   void SanityCheckGridItemsBeforeReflow() const;
 #endif // DEBUG
 
 private:
   // Helpers for ReflowChildren
   struct Fragmentainer {
     /**