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 276008 5138ad90e360d3145e3991d188c420ee167d9578
parent 276007 b83f85dd329c42078bec8979ccbc03e61a71457a
child 276009 ef6fa56c99ca6c3db253d2a227928a3c6dccd061
push id69020
push usermpalmgren@mozilla.com
push dateWed, 09 Dec 2015 22:47:11 +0000
treeherdermozilla-inbound@3b487da5a6d4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmats
bugs978212
milestone45.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 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>