Bug 978212 - Resolved value of grid-template-{columns,rows} in px units. r=mats
☠☠ backed out by e68851ffbe37 ☠ ☠
authorTobias Schneider <schneider@jancona.com>
Thu, 03 Dec 2015 14:23:00 +0100
changeset 275883 c798c2576ad4228df74ac4dd69c702ebe9e3ecce
parent 275882 2e233e224c0e54b8c85081fae0ff607dbdcb6733
child 275884 3394473d21016267c9f430a269c209cf623646bd
push id68970
push usercbook@mozilla.com
push dateTue, 08 Dec 2015 08:07:19 +0000
treeherdermozilla-inbound@3394473d2101 [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 - 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,81 @@
+<!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, 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] 340px [b] 0px [b c d e] 30px 30px 0px 0px");
+    }, desc);
+  }
+
+  test_grid_template(assert_equals, 320, "test computed grid-template-{columns,rows} values");
+
+  gridElement.style.overflow = 'scroll';
+  test_grid_template(assert_equals, 320,
+                     "test computed grid-template-{columns,rows} values, overflow: scroll");
+
+  gridElement.style.width = '600px';
+  gridElement.style.overflow = 'visible';
+  test_grid_template(assert_equals, 420,
+                     "test computed grid-template-{columns,rows} values, after reflow");
+
+  gridElement.style.display = 'none';
+  test_grid_template(assert_not_equals, 420,
+                     "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,
+                     "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>