Bug 978212 - [css-grid] Resolved value of grid-template-{columns,rows} in px units. r=mats
authorTobias Schneider <schneider@jancona.com>
Tue, 24 Nov 2015 17:27:54 -0800
changeset 297691 5138ad90e360d3145e3991d188c420ee167d9578
parent 297690 b83f85dd329c42078bec8979ccbc03e61a71457a
child 297692 ef6fa56c99ca6c3db253d2a227928a3c6dccd061
push id8824
push userraliiev@mozilla.com
push dateMon, 14 Dec 2015 20:18:56 +0000
treeherdermozilla-aurora@e2031358e2a6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmats
bugs978212
milestone45.0a1
Bug 978212 - [css-grid] Resolved value of grid-template-{columns,rows} in px units. r=mats
layout/generic/nsGridContainerFrame.cpp
layout/generic/nsGridContainerFrame.h
layout/style/nsComputedDOMStyle.cpp
layout/style/nsComputedDOMStyle.h
layout/style/test/mochitest.ini
layout/style/test/test_grid_computed_values.html
--- a/layout/generic/nsGridContainerFrame.cpp
+++ b/layout/generic/nsGridContainerFrame.cpp
@@ -2993,16 +2993,31 @@ nsGridContainerFrame::Reflow(nsPresConte
   const nscoord computedBSize = aReflowState.ComputedBSize();
   const nscoord computedISize = aReflowState.ComputedISize();
   const WritingMode& wm = gridReflowState.mWM;
   gridReflowState.mIter.Reset();
   CalculateTrackSizes(gridReflowState,
                       LogicalSize(wm, computedISize, computedBSize),
                       nsLayoutUtils::PREF_ISIZE);
 
+  // FIXME bug 1229180: Instead of doing this on every reflow, we should only
+  // set these properties if they are needed.
+  nsTArray<nscoord> colTrackSizes(gridReflowState.mCols.mSizes.Length());
+  for (const TrackSize& sz : gridReflowState.mCols.mSizes) {
+    colTrackSizes.AppendElement(sz.mBase);
+  }
+  Properties().Set(GridColTrackSizes(),
+                   new nsTArray<nscoord>(mozilla::Move(colTrackSizes)));
+  nsTArray<nscoord> rowTrackSizes(gridReflowState.mRows.mSizes.Length());
+  for (const TrackSize& sz : gridReflowState.mRows.mSizes) {
+    rowTrackSizes.AppendElement(sz.mBase);
+  }
+  Properties().Set(GridRowTrackSizes(),
+                   new nsTArray<nscoord>(mozilla::Move(rowTrackSizes)));
+  
   nscoord bSize = 0;
   if (computedBSize == NS_AUTOHEIGHT) {
     for (uint32_t i = 0; i < mGridRowEnd; ++i) {
       bSize += gridReflowState.mRows.mSizes[i].mBase;
     }
     bSize += gridReflowState.mRows.SumOfGridGaps();
     bSize = NS_CSS_MINMAX(bSize,
                           aReflowState.ComputedMinBSize(),
--- a/layout/generic/nsGridContainerFrame.h
+++ b/layout/generic/nsGridContainerFrame.h
@@ -86,16 +86,30 @@ public:
     StateBits mState;
   };
 
   // @see nsAbsoluteContainingBlock::Reflow about this magic number
   static const nscoord VERY_LIKELY_A_GRID_CONTAINER = -123456789;
 
   NS_DECLARE_FRAME_PROPERTY(GridItemContainingBlockRect, DeleteValue<nsRect>)
 
+  NS_DECLARE_FRAME_PROPERTY(GridColTrackSizes, DeleteValue<nsTArray<nscoord>>)
+
+  const nsTArray<nscoord>* GetComputedTemplateColumns()
+  {
+    return static_cast<nsTArray<nscoord>*>(Properties().Get(GridColTrackSizes()));
+  }
+
+  NS_DECLARE_FRAME_PROPERTY(GridRowTrackSizes, DeleteValue<nsTArray<nscoord>>)
+
+  const nsTArray<nscoord>* GetComputedTemplateRows()
+  {
+    return static_cast<nsTArray<nscoord>*>(Properties().Get(GridRowTrackSizes()));
+  }
+
 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::WritingMode WritingMode;
   typedef mozilla::css::GridNamedArea GridNamedArea;
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -20,16 +20,17 @@
 #include "nsIScrollableFrame.h"
 #include "nsContentUtils.h"
 #include "nsIContent.h"
 
 #include "nsDOMCSSRect.h"
 #include "nsDOMCSSRGBColor.h"
 #include "nsDOMCSSValueList.h"
 #include "nsFlexContainerFrame.h"
+#include "nsGridContainerFrame.h"
 #include "nsGkAtoms.h"
 #include "nsHTMLReflowState.h"
 #include "nsStyleUtil.h"
 #include "nsStyleStructInlines.h"
 #include "nsROCSSPrimitiveValue.h"
 
 #include "nsPresContext.h"
 #include "nsIDocument.h"
@@ -2373,20 +2374,16 @@ nsComputedDOMStyle::GetGridLineNames(con
   val->SetString(lineNamesString);
   return val;
 }
 
 CSSValue*
 nsComputedDOMStyle::GetGridTrackSize(const nsStyleCoord& aMinValue,
                                      const nsStyleCoord& aMaxValue)
 {
-  // FIXME bug 978212: for grid-template-columns and grid-template-rows
-  // (not grid-auto-columns and grid-auto-rows), if we have frame,
-  // every <track-size> should be resolved into 'px' here,
-  // based on layout results.
   if (aMinValue == aMaxValue) {
     nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
     SetValueToCoord(val, aMinValue, true,
                     nullptr, nsCSSProps::kGridTrackBreadthKTable);
     return val;
   }
 
   nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
@@ -2406,17 +2403,18 @@ nsComputedDOMStyle::GetGridTrackSize(con
   minmaxStr.Append(argumentStr);
 
   minmaxStr.Append(char16_t(')'));
   val->SetString(minmaxStr);
   return val;
 }
 
 CSSValue*
-nsComputedDOMStyle::GetGridTemplateColumnsRows(const nsStyleGridTemplate& aTrackList)
+nsComputedDOMStyle::GetGridTemplateColumnsRows(const nsStyleGridTemplate& aTrackList,
+                                               const nsTArray<nscoord>* aTrackSizes)
 {
   if (aTrackList.mIsSubgrid) {
     NS_ASSERTION(aTrackList.mMinTrackSizingFunctions.IsEmpty() &&
                  aTrackList.mMaxTrackSizingFunctions.IsEmpty(),
                  "Unexpected sizing functions with subgrid");
     nsDOMCSSValueList* valueList = GetROCSSValueList(false);
 
     nsROCSSPrimitiveValue* subgridKeyword = new nsROCSSPrimitiveValue;
@@ -2439,26 +2437,41 @@ nsComputedDOMStyle::GetGridTemplateColum
     return val;
   }
 
   nsDOMCSSValueList* valueList = GetROCSSValueList(false);
   // Delimiting N tracks requires N+1 lines:
   // one before each track, plus one at the very end.
   MOZ_ASSERT(aTrackList.mLineNameLists.Length() == numSizes + 1,
              "Unexpected number of line name lists");
-  for (uint32_t i = 0;; i++) {
-    const nsTArray<nsString>& lineNames = aTrackList.mLineNameLists[i];
-    if (!lineNames.IsEmpty()) {
-      valueList->AppendCSSValue(GetGridLineNames(lineNames));
+  if (aTrackSizes) {
+    for (uint32_t i = 0;; i++) {
+      const nsTArray<nsString>& lineNames = aTrackList.mLineNameLists[i];
+      if (!lineNames.IsEmpty()) {
+        valueList->AppendCSSValue(GetGridLineNames(lineNames));
+      }
+      if (i == numSizes) {
+        break;
+      }
+      nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
+      val->SetAppUnits(aTrackSizes->ElementAt(i));
+      valueList->AppendCSSValue(val);
     }
-    if (i == numSizes) {
-      break;
+  } else {
+    for (uint32_t i = 0;; i++) {
+      const nsTArray<nsString>& lineNames = aTrackList.mLineNameLists[i];
+      if (!lineNames.IsEmpty()) {
+        valueList->AppendCSSValue(GetGridLineNames(lineNames));
+      }
+      if (i == numSizes) {
+        break;
+      }
+      valueList->AppendCSSValue(GetGridTrackSize(aTrackList.mMinTrackSizingFunctions[i],
+                                                 aTrackList.mMaxTrackSizingFunctions[i]));
     }
-    valueList->AppendCSSValue(GetGridTrackSize(aTrackList.mMinTrackSizingFunctions[i],
-                                               aTrackList.mMaxTrackSizingFunctions[i]));
   }
 
   return valueList;
 }
 
 CSSValue*
 nsComputedDOMStyle::DoGetGridAutoFlow()
 {
@@ -2485,23 +2498,41 @@ nsComputedDOMStyle::DoGetGridAutoRows()
 {
   return GetGridTrackSize(StylePosition()->mGridAutoRowsMin,
                           StylePosition()->mGridAutoRowsMax);
 }
 
 CSSValue*
 nsComputedDOMStyle::DoGetGridTemplateColumns()
 {
-  return GetGridTemplateColumnsRows(StylePosition()->mGridTemplateColumns);
+  const nsTArray<nscoord>* trackSizes = nullptr;
+  if (mInnerFrame) {
+    nsIFrame* gridContainerCandidate = mInnerFrame->GetContentInsertionFrame();
+    if (gridContainerCandidate &&
+        gridContainerCandidate->GetType() == nsGkAtoms::gridContainerFrame) {
+      auto gridContainer = static_cast<nsGridContainerFrame*>(gridContainerCandidate);
+      trackSizes = gridContainer->GetComputedTemplateColumns();
+    }
+  }
+  return GetGridTemplateColumnsRows(StylePosition()->mGridTemplateColumns, trackSizes);
 }
 
 CSSValue*
 nsComputedDOMStyle::DoGetGridTemplateRows()
 {
-  return GetGridTemplateColumnsRows(StylePosition()->mGridTemplateRows);
+  const nsTArray<nscoord>* trackSizes = nullptr;
+  if (mInnerFrame) {
+    nsIFrame* gridContainerCandidate = mInnerFrame->GetContentInsertionFrame();
+    if (gridContainerCandidate &&
+        gridContainerCandidate->GetType() == nsGkAtoms::gridContainerFrame) {
+      auto gridContainer = static_cast<nsGridContainerFrame*>(gridContainerCandidate);
+      trackSizes = gridContainer->GetComputedTemplateRows();
+    }
+  }
+  return GetGridTemplateColumnsRows(StylePosition()->mGridTemplateRows, trackSizes);
 }
 
 CSSValue*
 nsComputedDOMStyle::GetGridLine(const nsStyleGridLine& aGridLine)
 {
   if (aGridLine.IsAuto()) {
     nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
     val->SetIdent(eCSSKeyword_auto);
--- a/layout/style/nsComputedDOMStyle.h
+++ b/layout/style/nsComputedDOMStyle.h
@@ -174,17 +174,18 @@ private:
 
   mozilla::dom::CSSValue* GetMarginWidthFor(mozilla::css::Side aSide);
 
   mozilla::dom::CSSValue* GetSVGPaintFor(bool aFill);
 
   mozilla::dom::CSSValue* GetGridLineNames(const nsTArray<nsString>& aLineNames);
   mozilla::dom::CSSValue* GetGridTrackSize(const nsStyleCoord& aMinSize,
                                            const nsStyleCoord& aMaxSize);
-  mozilla::dom::CSSValue* GetGridTemplateColumnsRows(const nsStyleGridTemplate& aTrackList);
+  mozilla::dom::CSSValue* GetGridTemplateColumnsRows(const nsStyleGridTemplate& aTrackList,
+                                                     const nsTArray<nscoord>* aTrackSizes);
   mozilla::dom::CSSValue* GetGridLine(const nsStyleGridLine& aGridLine);
 
   bool GetLineHeightCoord(nscoord& aCoord);
 
   mozilla::dom::CSSValue* GetCSSShadowArray(nsCSSShadowArray* aArray,
                                             const nscolor& aDefaultColor,
                                             bool aIsBoxShadow);
 
--- a/layout/style/test/mochitest.ini
+++ b/layout/style/test/mochitest.ini
@@ -176,16 +176,17 @@ support-files = flexbox_layout_testcases
 support-files =
   BitPattern.woff
   file_font_loading_api_vframe.html
 [test_garbage_at_end_of_declarations.html]
 skip-if = (toolkit == 'gonk' && debug) # Bug 1186440
 [test_grid_container_shorthands.html]
 [test_grid_item_shorthands.html]
 [test_grid_shorthand_serialization.html]
+[test_grid_computed_values.html]
 [test_group_insertRule.html]
 [test_hover_quirk.html]
 [test_html_attribute_computed_values.html]
 [test_ident_escaping.html]
 [test_inherit_computation.html]
 skip-if = toolkit == 'android'
 [test_inherit_storage.html]
 [test_initial_computation.html]
new file mode 100644
--- /dev/null
+++ b/layout/style/test/test_grid_computed_values.html
@@ -0,0 +1,83 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta charset=utf-8>
+  <title>Test computed grid values</title>
+  <link rel="author" title="Tobias Schneider" href="mailto:schneider@jancona.com">
+  <script src="/resources/testharness.js"></script>
+  <script src="/resources/testharnessreport.js"></script>
+  <link rel='stylesheet' href='/resources/testharness.css'>
+  <style>
+  
+    #grid {
+      display: grid;
+      width: 500px;
+      height: 400px;
+      grid-template-columns:
+        [a]     auto
+        [b]     minmax(min-content, 1fr)
+        [b c d] repeat(2, [e] 40px)
+                repeat(5, auto);
+      grid-template-rows:
+        [a]       minmax(min-content, 1fr)
+        [b]       auto
+        [b c d e] 30px 30px
+                  auto auto;
+      grid-auto-columns: 3fr;
+      grid-auto-rows: 2fr;
+    }
+  
+  </style>
+</head>
+<body>
+
+<div>
+  <div id="grid">
+    <div style="grid-column-start:1; width:50px"></div>
+    <div style="grid-column-start:9; width:50px"></div>
+  </div>
+<div>
+
+<script>
+
+  var gridElement = document.getElementById("grid");
+
+  function test_grid_template(assert_fn, width, height, desc) {
+    test(function() {
+      assert_fn(getComputedStyle(gridElement).gridTemplateColumns,
+                "[a] 50px [b] " + width + "px [b c d e] 40px [e] 40px 0px 0px 0px 0px 50px");
+      assert_fn(getComputedStyle(gridElement).gridTemplateRows,
+                "[a] " + height + "px [b] 0px [b c d e] 30px 30px 0px 0px");
+    }, desc);
+  }
+
+  test_grid_template(assert_equals, 320, 340, "test computed grid-template-{columns,rows} values");
+
+  gridElement.style.overflow = 'scroll';
+  var v_scrollbar = gridElement.offsetWidth - gridElement.clientWidth;
+  var h_scrollbar = gridElement.offsetHeight - gridElement.clientHeight;
+  test_grid_template(assert_equals, 320 - v_scrollbar, 340 - h_scrollbar,
+                     "test computed grid-template-{columns,rows} values, overflow: scroll");
+
+  gridElement.style.width = '600px';
+  gridElement.style.overflow = 'visible';
+  test_grid_template(assert_equals, 420, 340,
+                     "test computed grid-template-{columns,rows} values, after reflow");
+
+  gridElement.style.display = 'none';
+  test_grid_template(assert_not_equals, 420, 340,
+                     "test computed grid-template-{columns,rows} values, display: none");
+
+  gridElement.style.display = 'grid';
+  gridElement.parentNode.style.display = 'none';
+  test_grid_template(assert_not_equals, 420, 340,
+                     "test computed grid-template-{columns,rows} values, display: none on parent");
+
+  test(function() {
+    assert_equals(getComputedStyle(gridElement).gridAutoColumns, "3fr");
+    assert_equals(getComputedStyle(gridElement).gridAutoRows, "2fr");
+  }, "test computed grid-auto-{columns,rows} values");
+
+</script>
+</body>
+</html>