From d4121401d756d878d7081e0cf945859b641e2d67 Mon Sep 17 00:00:00 2001 From: Emil Sjolander Date: Wed, 14 Sep 2016 09:00:26 -0700 Subject: [PATCH] BREAKING - Fix unconstraint sizing in main axis Summary: @public Introduce `overflow:scroll` so that scrolling can be implemented without the current overflow:visible hackiness. Currently we use AT_MOST to measure in the cross axis but not in the main axis. This was done to enable scrolling containers where children are not constraint in the main axis by their parent. This caused problems for non-scrolling containers though as it meant that their children cannot be measured correctly in the main axis. Introducing `overflow:scroll` fixes this. Reviewed By: astreet Differential Revision: D3855801 fbshipit-source-id: 6077b0bcb68fe5ddd4aa22926acab40ff4d83949 --- CSSLayout/CSSLayout.c | 42 ++++++++----------- CSSLayout/CSSLayout.h | 1 + java/com/facebook/csslayout/CSSOverflow.java | 1 + java/com/facebook/csslayout/LayoutEngine.java | 20 ++++----- 4 files changed, 28 insertions(+), 36 deletions(-) diff --git a/CSSLayout/CSSLayout.c b/CSSLayout/CSSLayout.c index 7a5766ed..f4d3a68c 100644 --- a/CSSLayout/CSSLayout.c +++ b/CSSLayout/CSSLayout.c @@ -451,6 +451,8 @@ print_css_node_rec(const CSSNodeRef node, const CSSPrintOptions options, const u printf("overflow: 'hidden', "); } else if (node->style.overflow == CSSOverflowVisible) { printf("overflow: 'visible', "); + } else if (node->style.overflow == CSSOverflowScroll) { + printf("overflow: 'scroll', "); } if (four_equal(node->style.margin)) { @@ -555,8 +557,7 @@ static bool isColumnDirection(const CSSFlexDirection flexDirection) { } static float getLeadingMargin(const CSSNodeRef node, const CSSFlexDirection axis) { - if (isRowDirection(axis) && - !CSSValueIsUndefined(node->style.margin[CSSEdgeStart])) { + if (isRowDirection(axis) && !CSSValueIsUndefined(node->style.margin[CSSEdgeStart])) { return node->style.margin[CSSEdgeStart]; } @@ -564,8 +565,7 @@ static float getLeadingMargin(const CSSNodeRef node, const CSSFlexDirection axis } static float getTrailingMargin(const CSSNodeRef node, const CSSFlexDirection axis) { - if (isRowDirection(axis) && - !CSSValueIsUndefined(node->style.margin[CSSEdgeEnd])) { + if (isRowDirection(axis) && !CSSValueIsUndefined(node->style.margin[CSSEdgeEnd])) { return node->style.margin[CSSEdgeEnd]; } @@ -573,8 +573,7 @@ static float getTrailingMargin(const CSSNodeRef node, const CSSFlexDirection axi } static float getLeadingPadding(const CSSNodeRef node, const CSSFlexDirection axis) { - if (isRowDirection(axis) && - !CSSValueIsUndefined(node->style.padding[CSSEdgeStart]) && + if (isRowDirection(axis) && !CSSValueIsUndefined(node->style.padding[CSSEdgeStart]) && node->style.padding[CSSEdgeStart] >= 0) { return node->style.padding[CSSEdgeStart]; } @@ -587,8 +586,7 @@ static float getLeadingPadding(const CSSNodeRef node, const CSSFlexDirection axi } static float getTrailingPadding(const CSSNodeRef node, const CSSFlexDirection axis) { - if (isRowDirection(axis) && - !CSSValueIsUndefined(node->style.padding[CSSEdgeEnd]) && + if (isRowDirection(axis) && !CSSValueIsUndefined(node->style.padding[CSSEdgeEnd]) && node->style.padding[CSSEdgeEnd] >= 0) { return node->style.padding[CSSEdgeEnd]; } @@ -601,8 +599,7 @@ static float getTrailingPadding(const CSSNodeRef node, const CSSFlexDirection ax } static float getLeadingBorder(const CSSNodeRef node, const CSSFlexDirection axis) { - if (isRowDirection(axis) && - !CSSValueIsUndefined(node->style.border[CSSEdgeStart]) && + if (isRowDirection(axis) && !CSSValueIsUndefined(node->style.border[CSSEdgeStart]) && node->style.border[CSSEdgeStart] >= 0) { return node->style.border[CSSEdgeStart]; } @@ -615,8 +612,7 @@ static float getLeadingBorder(const CSSNodeRef node, const CSSFlexDirection axis } static float getTrailingBorder(const CSSNodeRef node, const CSSFlexDirection axis) { - if (isRowDirection(axis) && - !CSSValueIsUndefined(node->style.border[CSSEdgeEnd]) && + if (isRowDirection(axis) && !CSSValueIsUndefined(node->style.border[CSSEdgeEnd]) && node->style.border[CSSEdgeEnd] >= 0) { return node->style.border[CSSEdgeEnd]; } @@ -1140,21 +1136,17 @@ static void layoutNodeImpl(const CSSNodeRef node, childHeightMeasureMode = CSSMeasureModeExactly; } - // According to the spec, if the main size is not definite and the - // child's inline axis is parallel to the main axis (i.e. it's - // horizontal), the child should be sized using "UNDEFINED" in - // the main size. Otherwise use "AT_MOST" in the cross axis. - if (!isMainAxisRow && CSSValueIsUndefined(childWidth) && - !CSSValueIsUndefined(availableInnerWidth)) { - childWidth = availableInnerWidth; - childWidthMeasureMode = CSSMeasureModeAtMost; - } - // The W3C spec doesn't say anything about the 'overflow' property, // but all major browsers appear to implement the following logic. - if (node->style.overflow == CSSOverflowHidden) { - if (isMainAxisRow && CSSValueIsUndefined(childHeight) && - !CSSValueIsUndefined(availableInnerHeight)) { + if ((!isMainAxisRow && node->style.overflow == CSSOverflowScroll) || node->style.overflow != CSSOverflowScroll) { + if (CSSValueIsUndefined(childWidth) && !CSSValueIsUndefined(availableInnerWidth)) { + childWidth = availableInnerWidth; + childWidthMeasureMode = CSSMeasureModeAtMost; + } + } + + if ((isMainAxisRow && node->style.overflow == CSSOverflowScroll) || node->style.overflow != CSSOverflowScroll) { + if (CSSValueIsUndefined(childHeight) && !CSSValueIsUndefined(availableInnerHeight)) { childHeight = availableInnerHeight; childHeightMeasureMode = CSSMeasureModeAtMost; } diff --git a/CSSLayout/CSSLayout.h b/CSSLayout/CSSLayout.h index 3ebce685..539b8ab0 100644 --- a/CSSLayout/CSSLayout.h +++ b/CSSLayout/CSSLayout.h @@ -55,6 +55,7 @@ typedef enum CSSJustify { typedef enum CSSOverflow { CSSOverflowVisible, CSSOverflowHidden, + CSSOverflowScroll, } CSSOverflow; // Note: auto is only a valid value for alignSelf. It is NOT a valid value for diff --git a/java/com/facebook/csslayout/CSSOverflow.java b/java/com/facebook/csslayout/CSSOverflow.java index 29957a9a..9aae8225 100644 --- a/java/com/facebook/csslayout/CSSOverflow.java +++ b/java/com/facebook/csslayout/CSSOverflow.java @@ -12,4 +12,5 @@ package com.facebook.csslayout; public enum CSSOverflow { VISIBLE, HIDDEN, + SCROLL, } diff --git a/java/com/facebook/csslayout/LayoutEngine.java b/java/com/facebook/csslayout/LayoutEngine.java index b8edf8f9..57336949 100644 --- a/java/com/facebook/csslayout/LayoutEngine.java +++ b/java/com/facebook/csslayout/LayoutEngine.java @@ -715,19 +715,17 @@ public class LayoutEngine { childHeightMeasureMode = CSSMeasureMode.EXACTLY; } - // According to the spec, if the main size is not definite and the - // child's inline axis is parallel to the main axis (i.e. it's - // horizontal), the child should be sized using "UNDEFINED" in - // the main size. Otherwise use "AT_MOST" in the cross axis. - if (!isMainAxisRow && Float.isNaN(childWidth) && !Float.isNaN(availableInnerWidth)) { - childWidth = availableInnerWidth; - childWidthMeasureMode = CSSMeasureMode.AT_MOST; - } - // The W3C spec doesn't say anything about the 'overflow' property, // but all major browsers appear to implement the following logic. - if (node.style.overflow == CSSOverflow.HIDDEN) { - if (isMainAxisRow && Float.isNaN(childHeight) && !Float.isNaN(availableInnerHeight)) { + if ((!isMainAxisRow && node.style.overflow == CSSOverflow.SCROLL) || node.style.overflow != CSSOverflow.SCROLL) { + if (Float.isNaN(childWidth) && !Float.isNaN(availableInnerWidth)) { + childWidth = availableInnerWidth; + childWidthMeasureMode = CSSMeasureMode.AT_MOST; + } + } + + if ((isMainAxisRow && node.style.overflow == CSSOverflow.SCROLL) || node.style.overflow != CSSOverflow.SCROLL) { + if (Float.isNaN(childHeight) && !Float.isNaN(availableInnerHeight)) { childHeight = availableInnerHeight; childHeightMeasureMode = CSSMeasureMode.AT_MOST; }