implement flex-flow:column
authorojan@chromium.org <ojan@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 18 Oct 2011 19:35:14 +0000 (19:35 +0000)
committerojan@chromium.org <ojan@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 18 Oct 2011 19:35:14 +0000 (19:35 +0000)
https://bugs.webkit.org/show_bug.cgi?id=70082

Reviewed by David Hyatt.

Source/WebCore:

There's still a bug with a FIXME where we don't compute the right
size for the container of the flexbox in the presence of
orthogonal flows. That's the cause of all the failing cases
in the tests.

Tests: css3/flexbox/flex-flow-border.html
       css3/flexbox/flex-flow-margins.html
       css3/flexbox/flex-flow-orientations.html
       css3/flexbox/flex-flow-overflow.html
       css3/flexbox/flex-flow-padding.html
       css3/flexbox/flex-flow.html

* rendering/RenderFlexibleBox.cpp:
(WebCore::RenderFlexibleBox::layoutBlock):
(WebCore::RenderFlexibleBox::hasOrthogonalFlow):
(WebCore::RenderFlexibleBox::isColumnFlow):
(WebCore::RenderFlexibleBox::isHorizontalFlow):
(WebCore::RenderFlexibleBox::isLeftToRightFlow):
Use isHorizontalFlow and isLeftToRightFlow so that methods like
flowAwareBorderStart look exactly like borderStart with
isHorizontalWritingMode and isLeftToRightDirection replaced.

(WebCore::RenderFlexibleBox::setFlowAwareLogicalHeight):
(WebCore::RenderFlexibleBox::flowAwareLogicalHeightForChild):
(WebCore::RenderFlexibleBox::flowAwareLogicalWidthForChild):
(WebCore::RenderFlexibleBox::flowAwareLogicalHeight):
(WebCore::RenderFlexibleBox::flowAwareLogicalWidth):
(WebCore::RenderFlexibleBox::flowAwareContentLogicalHeight):
(WebCore::RenderFlexibleBox::flowAwareContentLogicalWidth):
(WebCore::RenderFlexibleBox::transformedWritingMode):
Transform the writing-mode based of the flex-flow and direction
values. That methods like flowAwareBorderBefore look exactly like
borderBefore, except it switches over a different value.

(WebCore::RenderFlexibleBox::flowAwareBorderStart):
(WebCore::RenderFlexibleBox::flowAwareBorderBefore):
(WebCore::RenderFlexibleBox::flowAwareBorderAfter):
(WebCore::RenderFlexibleBox::flowAwarePaddingStart):
(WebCore::RenderFlexibleBox::flowAwarePaddingBefore):
(WebCore::RenderFlexibleBox::flowAwarePaddingAfter):
(WebCore::RenderFlexibleBox::flowAwareMarginStartForChild):
(WebCore::RenderFlexibleBox::flowAwareMarginEndForChild):
(WebCore::RenderFlexibleBox::flowAwareMarginBeforeForChild):
(WebCore::RenderFlexibleBox::flowAwareMarginAfterForChild):
(WebCore::RenderFlexibleBox::setFlowAwareMarginStartForChild):
(WebCore::RenderFlexibleBox::setFlowAwareMarginEndForChild):
(WebCore::RenderFlexibleBox::layoutAndPlaceChildrenInlineDirection):
(WebCore::RenderFlexibleBox::alignChildrenBlockDirection):
* rendering/RenderFlexibleBox.h:

LayoutTests:

* css3/flexbox/flex-flow-border-expected.txt: Added.
* css3/flexbox/flex-flow-border.html: Added.
Failures are due to not handling orthogonal flows correctly.
* css3/flexbox/flex-flow-expected.txt: Added.
* css3/flexbox/flex-flow-margins-expected.txt: Added.
* css3/flexbox/flex-flow-margins.html: Added.
* css3/flexbox/flex-flow-orientations-expected.txt: Added.
* css3/flexbox/flex-flow-orientations.html: Added.
* css3/flexbox/flex-flow-overflow-expected.txt: Added.
* css3/flexbox/flex-flow-overflow.html: Added.
* css3/flexbox/flex-flow-padding-expected.txt: Added.
* css3/flexbox/flex-flow-padding.html: Added.
Failures are due to not handling orthogonal flows correctly.
* css3/flexbox/flex-flow.html: Added.
* css3/flexbox/resources/flexbox.js:
Added the ability to check offsets that include clientLeft/clientTop
and for checking clientWidth/clientHeight. This is neede dfor the border tests.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@97783 268f45cc-cd09-0410-ab3c-d52691b4dbfc

17 files changed:
LayoutTests/ChangeLog
LayoutTests/css3/flexbox/flex-flow-border-expected.txt [new file with mode: 0644]
LayoutTests/css3/flexbox/flex-flow-border.html [new file with mode: 0644]
LayoutTests/css3/flexbox/flex-flow-expected.txt [new file with mode: 0644]
LayoutTests/css3/flexbox/flex-flow-margins-expected.txt [new file with mode: 0644]
LayoutTests/css3/flexbox/flex-flow-margins.html [new file with mode: 0644]
LayoutTests/css3/flexbox/flex-flow-orientations-expected.txt [new file with mode: 0644]
LayoutTests/css3/flexbox/flex-flow-orientations.html [new file with mode: 0644]
LayoutTests/css3/flexbox/flex-flow-overflow-expected.txt [new file with mode: 0644]
LayoutTests/css3/flexbox/flex-flow-overflow.html [new file with mode: 0644]
LayoutTests/css3/flexbox/flex-flow-padding-expected.txt [new file with mode: 0644]
LayoutTests/css3/flexbox/flex-flow-padding.html [new file with mode: 0644]
LayoutTests/css3/flexbox/flex-flow.html [new file with mode: 0644]
LayoutTests/css3/flexbox/resources/flexbox.js
Source/WebCore/ChangeLog
Source/WebCore/rendering/RenderFlexibleBox.cpp
Source/WebCore/rendering/RenderFlexibleBox.h

index 43ccf67..ed54559 100644 (file)
@@ -1,3 +1,28 @@
+2011-10-13  Ojan Vafai  <ojan@chromium.org>
+
+        implement flex-flow:column
+        https://bugs.webkit.org/show_bug.cgi?id=70082
+
+        Reviewed by David Hyatt.
+
+        * css3/flexbox/flex-flow-border-expected.txt: Added.
+        * css3/flexbox/flex-flow-border.html: Added.
+        Failures are due to not handling orthogonal flows correctly. 
+        * css3/flexbox/flex-flow-expected.txt: Added.
+        * css3/flexbox/flex-flow-margins-expected.txt: Added.
+        * css3/flexbox/flex-flow-margins.html: Added.
+        * css3/flexbox/flex-flow-orientations-expected.txt: Added.
+        * css3/flexbox/flex-flow-orientations.html: Added.
+        * css3/flexbox/flex-flow-overflow-expected.txt: Added.
+        * css3/flexbox/flex-flow-overflow.html: Added.
+        * css3/flexbox/flex-flow-padding-expected.txt: Added.
+        * css3/flexbox/flex-flow-padding.html: Added.
+        Failures are due to not handling orthogonal flows correctly. 
+        * css3/flexbox/flex-flow.html: Added.
+        * css3/flexbox/resources/flexbox.js:
+        Added the ability to check offsets that include clientLeft/clientTop
+        and for checking clientWidth/clientHeight. This is neede dfor the border tests.
+
 2011-10-18  Cary Clark  <caryclark@google.com>
 
         Rebaseline most remaining IMAGE diffs for chromium-mac (Skia)
diff --git a/LayoutTests/css3/flexbox/flex-flow-border-expected.txt b/LayoutTests/css3/flexbox/flex-flow-border-expected.txt
new file mode 100644 (file)
index 0000000..7538e82
--- /dev/null
@@ -0,0 +1,65 @@
+horizontal-tb rtl row physical
+PASS
+horizontal-tb rtl row logical
+PASS
+horizontal-tb ltr row physical
+PASS
+horizontal-tb ltr row logical
+PASS
+horizontal-tb rtl column physical
+PASS
+horizontal-tb rtl column logical
+PASS
+horizontal-tb ltr column physical
+PASS
+horizontal-tb ltr column logical
+PASS
+horizontal-bt rtl row physical
+PASS
+horizontal-bt rtl row logical
+PASS
+horizontal-bt ltr row physical
+PASS
+horizontal-bt ltr row logical
+PASS
+horizontal-bt rtl column physical
+PASS
+horizontal-bt rtl column logical
+PASS
+horizontal-bt ltr column physical
+PASS
+horizontal-bt ltr column logical
+PASS
+vertical-lr rtl row physical
+PASS
+vertical-lr rtl row logical
+PASS
+vertical-lr ltr row physical
+PASS
+vertical-lr ltr row logical
+PASS
+vertical-lr rtl column physical
+PASS
+vertical-lr rtl column logical
+PASS
+vertical-lr ltr column physical
+PASS
+vertical-lr ltr column logical
+PASS
+vertical-rl rtl row physical
+PASS
+vertical-rl rtl row logical
+PASS
+vertical-rl ltr row physical
+PASS
+vertical-rl ltr row logical
+PASS
+vertical-rl rtl column physical
+PASS
+vertical-rl rtl column logical
+PASS
+vertical-rl ltr column physical
+PASS
+vertical-rl ltr column logical
+PASS
+
diff --git a/LayoutTests/css3/flexbox/flex-flow-border.html b/LayoutTests/css3/flexbox/flex-flow-border.html
new file mode 100644 (file)
index 0000000..aef36b4
--- /dev/null
@@ -0,0 +1,261 @@
+<!DOCTYPE html>
+<html>
+<style>
+.container {
+    position: relative;
+    background-color: pink;
+    outline: 1px solid red;
+    display: inline-block;
+}
+.flexbox {
+    display: -webkit-flexbox;
+    background-color: grey;
+    width: 100px;
+    height: 100px;
+    border-style: solid;
+}
+.flexbox * {
+    border-width: 0px;
+    border-style: solid;
+}
+.title {
+    margin-top: 1em;
+}
+.ltr {
+    direction: ltr;
+}
+.rtl {
+    direction: rtl;
+}
+.horizontal-tb {
+    -webkit-writing-mode: horizontal-tb;
+}
+.horizontal-bt {
+    -webkit-writing-mode: horizontal-bt;
+}
+.vertical-rl {
+    -webkit-writing-mode: vertical-rl;
+}
+.vertical-lr {
+    -webkit-writing-mode: vertical-lr;
+}
+.row {
+    -webkit-flex-flow: row;    
+}
+.row-reverse {
+    -webkit-flex-flow: row-reverse;
+}
+.column {
+    -webkit-flex-flow: column;
+}
+.column-reverse {
+    -webkit-flex-flow: column-reverse;
+}
+.physical {
+    border-width: 10px 20px 30px 40px;
+}
+.physical > div {
+    border-width: 13px 2px 17px 8px;
+}
+.logical {
+    -webkit-border-before-width: 10px;
+    -webkit-border-after-width: 30px;
+    -webkit-border-start-width: 40px;
+    -webkit-border-end-width: 20px;
+}
+.logical > div {
+    -webkit-border-before-width: 13px;
+    -webkit-border-after-width: 17px;
+    -webkit-border-start-width: 8px;
+    -webkit-border-end-width: 2px;
+}
+.flexbox > :nth-child(1) {
+    background-color: blue;
+}
+.flexbox > :nth-child(2) {
+    background-color: green;
+}
+.flexbox > :nth-child(3) {
+    background-color: red;
+}
+</style>
+<script>
+if (window.layoutTestController)
+    layoutTestController.dumpAsText();
+</script>
+<script src="resources/flexbox.js"></script>
+<body onload="checkFlexBoxen()">
+
+<script>
+function positionAsString(position)
+{
+    return 'data-total-x="' + position[0] + '" data-total-y="' + position[1] + '"';
+}
+
+function offsetSizeAsString(size)
+{
+    return 'data-expected-width="' + size[0] + '" data-expected-height="' + size[1] + '"';
+}
+
+function asString(expectations)
+{
+    return 'data-expected-client-width="' + expectations[0] + '" data-expected-client-height="' + expectations[1] + '" ' + positionAsString(expectations.slice(2, 4));
+}
+
+var physicalFlexBoxOffsetSize = [160, 140];
+var physicalFlexBoxClientPosition = [40, 10];
+
+var physicalExpectations = {
+    'horizontal-tb': {
+        rtl: {
+            size: physicalFlexBoxOffsetSize,
+            position: physicalFlexBoxClientPosition,
+            column: [20, 70, 118, 23],
+            row: [90, 20, 48, 23]
+        },
+        ltr : {
+            size: physicalFlexBoxOffsetSize,
+            position: physicalFlexBoxClientPosition,
+            column: [20, 70, 48, 23],
+            row: [90, 20, 48, 23]
+        }
+    },
+    'horizontal-bt': {
+        rtl: {
+            size: physicalFlexBoxOffsetSize,
+            position: physicalFlexBoxClientPosition,
+            column: [20, 70, 118, 23],
+            row: [90, 20, 48, 73]
+        },
+        ltr : {
+            size: physicalFlexBoxOffsetSize,
+            position: physicalFlexBoxClientPosition,
+            column: [20, 70, 48, 23],
+            row: [90, 20, 48, 73]
+        }
+    },
+    'vertical-lr': {
+        rtl: {
+            size: physicalFlexBoxOffsetSize,
+            position: physicalFlexBoxClientPosition,
+            column: [90, 20, 48, 73],
+            row: [20, 70, 48, 23]
+        },
+        ltr : {
+            size: physicalFlexBoxOffsetSize,
+            position: physicalFlexBoxClientPosition,
+            column: [90, 20, 48, 23],
+            row: [20, 70, 48, 23]
+        }
+    },
+    'vertical-rl': {
+        rtl: {
+            size: physicalFlexBoxOffsetSize,
+            position: physicalFlexBoxClientPosition,
+            column: [90, 20, 48, 73],
+            row: [20, 70, 118, 23]
+        },
+        ltr : {
+            size: physicalFlexBoxOffsetSize,
+            position: physicalFlexBoxClientPosition,
+            column: [90, 20, 48, 23],
+            row: [20, 70, 118, 23]
+        }
+    }
+}
+
+var logicalExpectations = {
+    'horizontal-tb': {
+        rtl: {
+            size: [160, 140],
+            position: [20, 10],
+            column: [20, 70, 92, 23],
+            row: [90, 20, 22, 23]
+        },
+        ltr : {
+            size: [160, 140],
+            position: [40, 10],
+            column: [20, 70, 48, 23],
+            row: [90, 20, 48, 23]
+        }
+    },
+    'horizontal-bt': {
+        rtl: {
+            size: [160, 140],
+            position: [20, 30],
+            column: [20, 70, 92, 47],
+            row: [90, 20, 22, 97]
+        },
+        ltr : {
+            size: [160, 140],
+            position: [40, 30],
+            column: [20, 70, 48, 47],
+            row: [90, 20, 48, 97]
+        }
+    },
+    'vertical-lr': {
+        rtl: {
+            size: [140, 160],
+            position: [10, 20],
+            column: [70, 20, 23, 92],
+            row: [20, 90, 23, 22]
+        },
+        ltr : {
+            size: [140, 160],
+            position: [10, 40],
+            column: [70, 20, 23, 48],
+            row: [20, 90, 23, 48]
+        }
+    },
+    'vertical-rl': {
+        rtl: {
+            size: [140, 160],
+            position: [30, 20],
+            column: [70, 20, 47, 92],
+            row: [20, 90, 97, 22]
+        },
+        ltr : {
+            size: [140, 160],
+            position: [30, 40],
+            column: [70, 20, 47, 48],
+            row: [20, 90, 97, 48]
+        }
+    }
+}
+
+var writingModes = ['horizontal-tb', 'horizontal-bt', 'vertical-lr', 'vertical-rl'];
+// FIXME: Test row-reverse and column-reverse.
+var flexFlows = ['row', 'column'];
+var directions = ['rtl', 'ltr'];
+var marginTypes = ['physical', 'logical'];
+
+writingModes.forEach(function(writingMode) {
+    flexFlows.forEach(function(flexFlow) {
+        directions.forEach(function(direction) {
+            marginTypes.forEach(function(marginType) {
+                var flexboxClassName = writingMode + ' ' + direction + ' ' + flexFlow + ' ' + marginType;
+                var title = document.createElement('div');
+                title.className = 'title';
+                title.innerHTML = flexboxClassName;
+                document.body.appendChild(title);
+
+                var expectations = (marginType == 'physical') ? physicalExpectations : logicalExpectations;
+                expectations = expectations[writingMode][direction];
+
+                var container = document.createElement('div');
+                container.className = 'container';
+                container.setAttribute('data-expected-width', expectations.size[0]);
+                container.setAttribute('data-expected-height', expectations.size[1]);
+
+                container.innerHTML = '\n<div class="flexbox ' + flexboxClassName + '" ' + positionAsString(expectations.position) + ' ' + offsetSizeAsString(expectations.size) + '>\n' +
+                    '<div style="width: -webkit-flex(1 20px); height: -webkit-flex(1 20px);" ' + asString(expectations[flexFlow]) + '></div>\n' +
+                '</div>\n';
+
+                document.body.appendChild(container);   
+            })
+        })
+    })
+})
+</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/LayoutTests/css3/flexbox/flex-flow-expected.txt b/LayoutTests/css3/flexbox/flex-flow-expected.txt
new file mode 100644 (file)
index 0000000..00e8b92
--- /dev/null
@@ -0,0 +1,6 @@
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
diff --git a/LayoutTests/css3/flexbox/flex-flow-margins-expected.txt b/LayoutTests/css3/flexbox/flex-flow-margins-expected.txt
new file mode 100644 (file)
index 0000000..7538e82
--- /dev/null
@@ -0,0 +1,65 @@
+horizontal-tb rtl row physical
+PASS
+horizontal-tb rtl row logical
+PASS
+horizontal-tb ltr row physical
+PASS
+horizontal-tb ltr row logical
+PASS
+horizontal-tb rtl column physical
+PASS
+horizontal-tb rtl column logical
+PASS
+horizontal-tb ltr column physical
+PASS
+horizontal-tb ltr column logical
+PASS
+horizontal-bt rtl row physical
+PASS
+horizontal-bt rtl row logical
+PASS
+horizontal-bt ltr row physical
+PASS
+horizontal-bt ltr row logical
+PASS
+horizontal-bt rtl column physical
+PASS
+horizontal-bt rtl column logical
+PASS
+horizontal-bt ltr column physical
+PASS
+horizontal-bt ltr column logical
+PASS
+vertical-lr rtl row physical
+PASS
+vertical-lr rtl row logical
+PASS
+vertical-lr ltr row physical
+PASS
+vertical-lr ltr row logical
+PASS
+vertical-lr rtl column physical
+PASS
+vertical-lr rtl column logical
+PASS
+vertical-lr ltr column physical
+PASS
+vertical-lr ltr column logical
+PASS
+vertical-rl rtl row physical
+PASS
+vertical-rl rtl row logical
+PASS
+vertical-rl ltr row physical
+PASS
+vertical-rl ltr row logical
+PASS
+vertical-rl rtl column physical
+PASS
+vertical-rl rtl column logical
+PASS
+vertical-rl ltr column physical
+PASS
+vertical-rl ltr column logical
+PASS
+
diff --git a/LayoutTests/css3/flexbox/flex-flow-margins.html b/LayoutTests/css3/flexbox/flex-flow-margins.html
new file mode 100644 (file)
index 0000000..b190370
--- /dev/null
@@ -0,0 +1,254 @@
+<!DOCTYPE html>
+<html>
+<style>
+.container {
+    position: relative;
+    background-color: pink;
+    outline: 1px solid black;
+    display: inline-block;
+}
+.flexbox {
+    display: -webkit-flexbox;
+    background-color: grey;
+    width: 100px;
+    height: 100px;
+}
+.title {
+    margin-top: 1em;
+}
+.ltr {
+    direction: ltr;
+}
+.rtl {
+    direction: rtl;
+}
+.horizontal-tb {
+    -webkit-writing-mode: horizontal-tb;
+}
+.horizontal-bt {
+    -webkit-writing-mode: horizontal-bt;
+}
+.vertical-rl {
+    -webkit-writing-mode: vertical-rl;
+}
+.vertical-lr {
+    -webkit-writing-mode: vertical-lr;
+}
+.row {
+    -webkit-flex-flow: row;    
+}
+.row-reverse {
+    -webkit-flex-flow: row-reverse;
+}
+.column {
+    -webkit-flex-flow: column;
+}
+.column-reverse {
+    -webkit-flex-flow: column-reverse;
+}
+.physical {
+    margin: 10px 20px 30px 40px;
+}
+.physical > div {
+    margin: 13px 2px 17px 8px;
+}
+.logical {
+    -webkit-margin-before: 10px;
+    -webkit-margin-after: 30px;
+    -webkit-margin-start: 40px;
+    -webkit-margin-end: 20px;
+}
+.logical > div {
+    -webkit-margin-before: 13px;
+    -webkit-margin-after: 17px;
+    -webkit-margin-start: 8px;
+    -webkit-margin-end: 2px;
+}
+.flexbox > :nth-child(1) {
+    background-color: blue;
+}
+.flexbox > :nth-child(2) {
+    background-color: green;
+}
+.flexbox > :nth-child(3) {
+    background-color: red;
+}
+</style>
+<script>
+if (window.layoutTestController)
+    layoutTestController.dumpAsText();
+</script>
+<script src="resources/flexbox.js"></script>
+<body onload="checkFlexBoxen()">
+
+<script>
+function positionAsString(position)
+{
+    return 'data-offset-x="' + position[0] + '" data-offset-y="' + position[1] + '"';
+}
+
+function asString(expectations)
+{
+    return 'data-expected-width="' + expectations[0] + '" data-expected-height="' + expectations[1] + '" ' + positionAsString(expectations.slice(2, 4));
+}
+
+var physicalContainerSize = [160, 140];
+var physicalFlexBoxPosition = [40, 10];
+
+var physicalExpectations = {
+    'horizontal-tb': {
+        rtl: {
+            container: physicalContainerSize,
+            flexbox: physicalFlexBoxPosition,
+            column: [20, 70, 118, 23],
+            row: [90, 20, 48, 23]
+        },
+        ltr : {
+            container: physicalContainerSize,
+            flexbox: physicalFlexBoxPosition,
+            column: [20, 70, 48, 23],
+            row: [90, 20, 48, 23]
+        }
+    },
+    'horizontal-bt': {
+        rtl: {
+            container: physicalContainerSize,
+            flexbox: physicalFlexBoxPosition,
+            column: [20, 70, 118, 23],
+            row: [90, 20, 48, 73]
+        },
+        ltr : {
+            container: physicalContainerSize,
+            flexbox: physicalFlexBoxPosition,
+            column: [20, 70, 48, 23],
+            row: [90, 20, 48, 73]
+        }
+    },
+    'vertical-lr': {
+        rtl: {
+            container: physicalContainerSize,
+            flexbox: physicalFlexBoxPosition,
+            column: [90, 20, 48, 73],
+            row: [20, 70, 48, 23]
+        },
+        ltr : {
+            container: physicalContainerSize,
+            flexbox: physicalFlexBoxPosition,
+            column: [90, 20, 48, 23],
+            row: [20, 70, 48, 23]
+        }
+    },
+    'vertical-rl': {
+        rtl: {
+            container: physicalContainerSize,
+            flexbox: physicalFlexBoxPosition,
+            column: [90, 20, 48, 73],
+            row: [20, 70, 118, 23]
+        },
+        ltr : {
+            container: physicalContainerSize,
+            flexbox: physicalFlexBoxPosition,
+            column: [90, 20, 48, 23],
+            row: [20, 70, 118, 23]
+        }
+    }
+}
+
+var logicalExpectations = {
+    'horizontal-tb': {
+        rtl: {
+            container: [160, 140],
+            flexbox: [20, 10],
+            column: [20, 70, 92, 23],
+            row: [90, 20, 22, 23]
+        },
+        ltr : {
+            container: [160, 140],
+            flexbox: [40, 10],
+            column: [20, 70, 48, 23],
+            row: [90, 20, 48, 23]
+        }
+    },
+    'horizontal-bt': {
+        rtl: {
+            container: [160, 140],
+            flexbox: [20, 30],
+            column: [20, 70, 92, 47],
+            row: [90, 20, 22, 97]
+        },
+        ltr : {
+            container: [160, 140],
+            flexbox: [40, 30],
+            column: [20, 70, 48, 47],
+            row: [90, 20, 48, 97]
+        }
+    },
+    'vertical-lr': {
+        rtl: {
+            container: [140, 160],
+            flexbox: [10, 20],
+            column: [70, 20, 23, 92],
+            row: [20, 90, 23, 22]
+        },
+        ltr : {
+            container: [140, 160],
+            flexbox: [10, 40],
+            column: [70, 20, 23, 48],
+            row: [20, 90, 23, 48]
+        }
+    },
+    'vertical-rl': {
+        rtl: {
+            container: [140, 160],
+            flexbox: [30, 20],
+            column: [70, 20, 47, 92],
+            row: [20, 90, 97, 22]
+        },
+        ltr : {
+            container: [140, 160],
+            flexbox: [30, 40],
+            column: [70, 20, 47, 48],
+            row: [20, 90, 97, 48]
+        }
+    }
+}
+
+var writingModes = ['horizontal-tb', 'horizontal-bt', 'vertical-lr', 'vertical-rl'];
+// FIXME: Test row-reverse and column-reverse.
+var flexFlows = ['row', 'column'];
+var directions = ['rtl', 'ltr'];
+var marginTypes = ['physical', 'logical'];
+
+writingModes.forEach(function(writingMode) {
+    flexFlows.forEach(function(flexFlow) {
+        directions.forEach(function(direction) {
+            marginTypes.forEach(function(marginType) {
+                var flexboxClassName = writingMode + ' ' + direction + ' ' + flexFlow + ' ' + marginType;
+                var title = document.createElement('div');
+                title.className = 'title';
+                title.innerHTML = flexboxClassName;
+                document.body.appendChild(title);
+                
+                var expectations = (marginType == 'physical') ? physicalExpectations : logicalExpectations;
+                expectations = expectations[writingMode][direction];
+                var flexboxExpectations = positionAsString(expectations.flexbox);
+
+                var flexItemExpectations = asString(expectations[flexFlow]);
+
+                var container = document.createElement('div');
+                container.className = 'container';
+                container.setAttribute('data-expected-width', expectations.container[0]);
+                container.setAttribute('data-expected-height', expectations.container[1]);
+
+                container.innerHTML = '<div class="flexbox ' + flexboxClassName + '" ' + flexboxExpectations + '>\n' +
+                    '<div style="width: -webkit-flex(1 20px); height: -webkit-flex(1 20px);" ' + flexItemExpectations + '></div>\n' +
+                '</div>';
+
+                document.body.appendChild(container);   
+            })
+        })
+    })
+})
+</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/LayoutTests/css3/flexbox/flex-flow-orientations-expected.txt b/LayoutTests/css3/flexbox/flex-flow-orientations-expected.txt
new file mode 100644 (file)
index 0000000..fe0f4e7
--- /dev/null
@@ -0,0 +1,33 @@
+horizontal-tb rtl row
+PASS
+horizontal-tb ltr row
+PASS
+horizontal-tb rtl column
+PASS
+horizontal-tb ltr column
+PASS
+horizontal-bt rtl row
+PASS
+horizontal-bt ltr row
+PASS
+horizontal-bt rtl column
+PASS
+horizontal-bt ltr column
+PASS
+vertical-lr rtl row
+PASS
+vertical-lr ltr row
+PASS
+vertical-lr rtl column
+PASS
+vertical-lr ltr column
+PASS
+vertical-rl rtl row
+PASS
+vertical-rl ltr row
+PASS
+vertical-rl rtl column
+PASS
+vertical-rl ltr column
+PASS
+
diff --git a/LayoutTests/css3/flexbox/flex-flow-orientations.html b/LayoutTests/css3/flexbox/flex-flow-orientations.html
new file mode 100644 (file)
index 0000000..7e29f8a
--- /dev/null
@@ -0,0 +1,161 @@
+<!DOCTYPE html>
+<html>
+<style>
+.container {
+    position: relative;
+    background-color: pink;
+    outline: 1px solid black;
+    display: inline-block;
+}
+.flexbox {
+    display: -webkit-flexbox;
+    background-color: grey;
+    width: 100px;
+    height: 100px;
+}
+.title {
+    margin-top: 1em;
+}
+.ltr {
+    direction: ltr;
+}
+.rtl {
+    direction: rtl;
+}
+.horizontal-tb {
+    -webkit-writing-mode: horizontal-tb;
+}
+.horizontal-bt {
+    -webkit-writing-mode: horizontal-bt;
+}
+.vertical-rl {
+    -webkit-writing-mode: vertical-rl;
+}
+.vertical-lr {
+    -webkit-writing-mode: vertical-lr;
+}
+.row {
+    -webkit-flex-flow: row;    
+}
+.row-reverse {
+    -webkit-flex-flow: row-reverse;
+}
+.column {
+    -webkit-flex-flow: column;
+}
+.column-reverse {
+    -webkit-flex-flow: column-reverse;
+}
+.flexbox > :nth-child(1) {
+    background-color: blue;
+}
+.flexbox > :nth-child(2) {
+    background-color: green;
+}
+.flexbox > :nth-child(3) {
+    background-color: red;
+}
+</style>
+<script>
+if (window.layoutTestController)
+    layoutTestController.dumpAsText();
+</script>
+<script src="resources/flexbox.js"></script>
+<body onload="checkFlexBoxen()">
+
+<script>
+function asString(position)
+{
+    return 'data-offset-x="' + position[0] + '" data-offset-y="' + position[1] + '"';
+}
+
+var expectations = {
+    'horizontal-tb': {
+        column: {
+            rtl: [[80, 0], [80, 20]],
+            ltr: [[0, 0], [0, 20]]
+        },
+        row: {
+            rtl: [[80, 0], [60, 0]],
+            ltr: [[0, 0], [20, 0]]
+        }
+    },
+    'horizontal-bt': {
+        column: {
+            rtl: [[80, 80], [80, 60]],
+            ltr: [[0, 80], [0, 60]]
+        },
+        row: {
+            rtl: [[80, 80], [60, 80]],
+            ltr: [[0, 80], [20, 80]]
+        }
+    },
+    'vertical-lr': {
+        column: {
+            rtl: [[0, 80], [20, 80]],
+            ltr: [[0, 0], [20, 0]]
+        },
+        row: {
+            rtl: [[0, 80], [0, 60]],
+            ltr: [[0, 0], [0, 20]]
+        }
+    },
+    'vertical-rl': {
+        column: {
+            rtl: [[80, 80], [60, 80]],
+            ltr: [[80, 0], [60, 0]]
+        },
+        row: {
+            rtl: [[80, 80], [80, 60]],
+            ltr: [[80, 0], [80, 20]]
+        }
+    }
+};
+
+var writingModes = ['horizontal-tb', 'horizontal-bt', 'vertical-lr', 'vertical-rl'];
+// FIXME: Test row-reverse and column-reverse.
+var flexFlows = ['row', 'column'];
+var directions = ['rtl', 'ltr'];
+
+function physicalWritingMode(writingMode, flexFlow, direction)
+{
+    if (flexFlow.indexOf('column') == -1)
+        return writingMode;
+
+    var isReverse = flexFlow.indexOf('reverse') != -1;
+    switch (writingMode) {
+    case 'horizontal-tb':
+    case 'horizontal-bt':
+        return isReverse ? 'vertical-rl' : 'vertical-lr';
+    case 'vertical-lr':
+    case 'vertical-rl':
+        return isReverse ? 'horizontal-bt' : 'horizontal-tb';
+    }
+}
+
+writingModes.forEach(function(writingMode) {
+    flexFlows.forEach(function(flexFlow) {
+        directions.forEach(function(direction) {
+            var flexboxClassName = writingMode + ' ' + direction + ' ' + flexFlow;
+            var title = document.createElement('div');
+            title.className = 'title';
+            title.innerHTML = flexboxClassName;
+            document.body.appendChild(title);
+
+
+            var flexItemExpectations = expectations[writingMode][flexFlow][direction];
+
+            var container = document.createElement('div');
+            container.className = 'container';
+            container.innerHTML = '<div class="flexbox ' + flexboxClassName + '">\n' +
+                '<div style="width: 20px; height: 20px;" ' + asString(flexItemExpectations[0]) + '></div>\n' +
+                '<div style="width: 20px; height: 20px;" ' + asString(flexItemExpectations[1]) + '></div>\n' +
+            '</div>';
+
+            document.body.appendChild(container);   
+        })
+    })
+})
+</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/LayoutTests/css3/flexbox/flex-flow-overflow-expected.txt b/LayoutTests/css3/flexbox/flex-flow-overflow-expected.txt
new file mode 100644 (file)
index 0000000..fe0f4e7
--- /dev/null
@@ -0,0 +1,33 @@
+horizontal-tb rtl row
+PASS
+horizontal-tb ltr row
+PASS
+horizontal-tb rtl column
+PASS
+horizontal-tb ltr column
+PASS
+horizontal-bt rtl row
+PASS
+horizontal-bt ltr row
+PASS
+horizontal-bt rtl column
+PASS
+horizontal-bt ltr column
+PASS
+vertical-lr rtl row
+PASS
+vertical-lr ltr row
+PASS
+vertical-lr rtl column
+PASS
+vertical-lr ltr column
+PASS
+vertical-rl rtl row
+PASS
+vertical-rl ltr row
+PASS
+vertical-rl rtl column
+PASS
+vertical-rl ltr column
+PASS
+
diff --git a/LayoutTests/css3/flexbox/flex-flow-overflow.html b/LayoutTests/css3/flexbox/flex-flow-overflow.html
new file mode 100644 (file)
index 0000000..ea7da61
--- /dev/null
@@ -0,0 +1,121 @@
+<!DOCTYPE html>
+<html>
+<style>
+.container {
+    position: relative;
+    background-color: pink;
+    outline: 1px solid red;
+    display: inline-block;
+}
+.flexbox {
+    display: -webkit-flexbox;
+    background-color: grey;
+    width: 100px;
+    height: 100px;
+}
+.title {
+    margin-top: 1em;
+}
+.ltr {
+    direction: ltr;
+}
+.rtl {
+    direction: rtl;
+}
+.horizontal-tb {
+    -webkit-writing-mode: horizontal-tb;
+}
+.horizontal-bt {
+    -webkit-writing-mode: horizontal-bt;
+}
+.vertical-rl {
+    -webkit-writing-mode: vertical-rl;
+}
+.vertical-lr {
+    -webkit-writing-mode: vertical-lr;
+}
+.row {
+    -webkit-flex-flow: row;    
+}
+.row-reverse {
+    -webkit-flex-flow: row-reverse;
+}
+.column {
+    -webkit-flex-flow: column;
+}
+.column-reverse {
+    -webkit-flex-flow: column-reverse;
+}
+.flexbox > :nth-child(1) {
+    background-color: blue;
+}
+</style>
+<script>
+if (window.layoutTestController)
+    layoutTestController.dumpAsText();
+</script>
+<script src="resources/flexbox.js"></script>
+<body onload="checkFlexBoxen()">
+
+<script>
+function positionAsString(position)
+{
+    return 'data-offset-x="' + position[0] + '" data-offset-y="' + position[1] + '"';
+}
+
+function sizeAsString(size)
+{
+    return 'data-expected-width="' + size[0] + '" data-expected-height="' + size[1] + '"';
+}
+
+var containerSize = [100, 100];
+
+var expectations = {
+    'horizontal-tb': {
+        rtl: [-5, 0],
+        ltr: [0, 0]
+    },
+    'horizontal-bt': {
+        rtl: [-5, -5],
+        ltr: [0, -5]
+    },
+    'vertical-lr': {
+        rtl: [0, -5],
+        ltr: [0, 0]
+    },
+    'vertical-rl': {
+        rtl: [-5, -5],
+        ltr: [-5, 0]
+    }
+}
+
+var writingModes = ['horizontal-tb', 'horizontal-bt', 'vertical-lr', 'vertical-rl'];
+// FIXME: Test row-reverse and column-reverse.
+var flexFlows = ['row', 'column'];
+var directions = ['rtl', 'ltr'];
+
+writingModes.forEach(function(writingMode) {
+    flexFlows.forEach(function(flexFlow) {
+        directions.forEach(function(direction) {
+            var flexboxClassName = writingMode + ' ' + direction + ' ' + flexFlow;
+            var title = document.createElement('div');
+            title.className = 'title';
+            title.innerHTML = flexboxClassName;
+            document.body.appendChild(title);
+
+            var container = document.createElement('div');
+            container.className = 'container';
+            container.setAttribute('data-expected-width', containerSize[0]);
+            container.setAttribute('data-expected-height', containerSize[1]);
+
+            container.innerHTML = '\n<div class="flexbox ' + flexboxClassName + '" ' + sizeAsString(containerSize) + '>\n' +
+                '<div style="width: -webkit-flex(1 105px); height: -webkit-flex(1 105px);" ' + sizeAsString([105, 105])  + ' ' + positionAsString(expectations[writingMode][direction]) + '></div>\n' +
+            '</div>\n';
+
+            document.body.appendChild(container);   
+        })
+    })
+})
+</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/LayoutTests/css3/flexbox/flex-flow-padding-expected.txt b/LayoutTests/css3/flexbox/flex-flow-padding-expected.txt
new file mode 100644 (file)
index 0000000..7538e82
--- /dev/null
@@ -0,0 +1,65 @@
+horizontal-tb rtl row physical
+PASS
+horizontal-tb rtl row logical
+PASS
+horizontal-tb ltr row physical
+PASS
+horizontal-tb ltr row logical
+PASS
+horizontal-tb rtl column physical
+PASS
+horizontal-tb rtl column logical
+PASS
+horizontal-tb ltr column physical
+PASS
+horizontal-tb ltr column logical
+PASS
+horizontal-bt rtl row physical
+PASS
+horizontal-bt rtl row logical
+PASS
+horizontal-bt ltr row physical
+PASS
+horizontal-bt ltr row logical
+PASS
+horizontal-bt rtl column physical
+PASS
+horizontal-bt rtl column logical
+PASS
+horizontal-bt ltr column physical
+PASS
+horizontal-bt ltr column logical
+PASS
+vertical-lr rtl row physical
+PASS
+vertical-lr rtl row logical
+PASS
+vertical-lr ltr row physical
+PASS
+vertical-lr ltr row logical
+PASS
+vertical-lr rtl column physical
+PASS
+vertical-lr rtl column logical
+PASS
+vertical-lr ltr column physical
+PASS
+vertical-lr ltr column logical
+PASS
+vertical-rl rtl row physical
+PASS
+vertical-rl rtl row logical
+PASS
+vertical-rl ltr row physical
+PASS
+vertical-rl ltr row logical
+PASS
+vertical-rl rtl column physical
+PASS
+vertical-rl rtl column logical
+PASS
+vertical-rl ltr column physical
+PASS
+vertical-rl ltr column logical
+PASS
+
diff --git a/LayoutTests/css3/flexbox/flex-flow-padding.html b/LayoutTests/css3/flexbox/flex-flow-padding.html
new file mode 100644 (file)
index 0000000..1eba813
--- /dev/null
@@ -0,0 +1,267 @@
+<!DOCTYPE html>
+<html>
+<style>
+.container {
+    position: relative;
+    background-color: pink;
+    outline: 1px solid red;
+    display: inline-block;
+}
+.flexbox {
+    display: -webkit-flexbox;
+    background-color: grey;
+    width: 100px;
+    height: 100px;
+}
+.title {
+    margin-top: 1em;
+}
+.ltr {
+    direction: ltr;
+}
+.rtl {
+    direction: rtl;
+}
+.horizontal-tb {
+    -webkit-writing-mode: horizontal-tb;
+}
+.horizontal-bt {
+    -webkit-writing-mode: horizontal-bt;
+}
+.vertical-rl {
+    -webkit-writing-mode: vertical-rl;
+}
+.vertical-lr {
+    -webkit-writing-mode: vertical-lr;
+}
+.row {
+    -webkit-flex-flow: row;    
+}
+.row-reverse {
+    -webkit-flex-flow: row-reverse;
+}
+.column {
+    -webkit-flex-flow: column;
+}
+.column-reverse {
+    -webkit-flex-flow: column-reverse;
+}
+.physical {
+    padding: 10px 20px 30px 40px;
+}
+.physical > div {
+    padding: 13px 2px 17px 8px;
+}
+.logical {
+    -webkit-padding-before: 10px;
+    -webkit-padding-after: 30px;
+    -webkit-padding-start: 40px;
+    -webkit-padding-end: 20px;
+}
+.logical > div {
+    -webkit-padding-before: 13px;
+    -webkit-padding-after: 17px;
+    -webkit-padding-start: 8px;
+    -webkit-padding-end: 2px;
+}
+.flexbox > :nth-child(1) {
+    background-color: blue;
+}
+.flexbox > div > div {
+    background-color: green;
+}
+</style>
+<script>
+if (window.layoutTestController)
+    layoutTestController.dumpAsText();
+</script>
+<script src="resources/flexbox.js"></script>
+<body onload="checkFlexBoxen()">
+
+<script>
+function positionAsString(position)
+{
+    return 'data-offset-x="' + position[0] + '" data-offset-y="' + position[1] + '"';
+}
+
+function asString(expectations)
+{
+    return 'data-expected-width="' + expectations[0] + '" data-expected-height="' + expectations[1] + '" ' + positionAsString(expectations.slice(2, 4));
+}
+
+var horizontalContainerSize = [160, 140];
+var verticalContainerSize = [140, 160];
+
+var physicalExpectations = {
+    'horizontal-tb': {
+        rtl: {
+            containersize: horizontalContainerSize,
+            flexitemcolumn: [30, 100, 110, 10],
+            flexitemrow: [100, 50, 40, 10],
+            childcolumn: [20, 20, 118, 23],
+            childrow: [90, 20, 48, 23]
+        },
+        ltr : {
+            containersize: horizontalContainerSize,
+            flexitemcolumn: [30, 100, 40, 10],
+            flexitemrow: [100, 50, 40, 10],
+            childcolumn: [20, 20, 48, 23],
+            childrow: [90, 20, 48, 23]
+        }
+    },
+    'horizontal-bt': {
+        rtl: {
+            containersize: horizontalContainerSize,
+            flexitemcolumn: [30, 100, 110, 10],
+            flexitemrow: [100, 50, 40, 60],
+            childcolumn: [20, 20, 118, 73],
+            childrow: [90, 20, 48, 73]
+        },
+        ltr : {
+            containersize: horizontalContainerSize,
+            flexitemcolumn: [30, 100, 40, 10],
+            flexitemrow: [100, 50, 40, 60],
+            childcolumn: [20, 20, 48, 73],
+            childrow: [90, 20, 48, 73]
+        }
+    },
+    'vertical-lr': {
+        rtl: {
+            containersize: horizontalContainerSize,
+            flexitemcolumn: [100, 50, 40, 60],
+            flexitemrow: [30, 100, 40, 10],
+            childcolumn: [20, 20, 48, 73],
+            childrow: [20, 70, 48, 23]
+        },
+        ltr : {
+            containersize: horizontalContainerSize,
+            flexitemcolumn: [100, 50, 40, 10],
+            flexitemrow: [30, 100, 40, 10],
+            childcolumn: [20, 20, 48, 23],
+            childrow: [20, 70, 48, 23]
+        }
+    },
+    'vertical-rl': {
+        rtl: {
+            containersize: horizontalContainerSize,
+            flexitemcolumn: [100, 50, 40, 60],
+            flexitemrow: [30, 100, 110, 10],
+            childcolumn: [20, 20, 118, 73],
+            childrow: [20, 70, 118, 23]
+        },
+        ltr : {
+            containersize: horizontalContainerSize,
+            flexitemcolumn: [100, 50, 40, 10],
+            flexitemrow: [30, 100, 110, 10],
+            childcolumn: [20, 20, 118, 23],
+            childrow: [20, 70, 118, 23]
+        }
+    }
+}
+
+var logicalExpectations = {
+    'horizontal-tb': {
+        rtl: {
+            containersize: horizontalContainerSize,
+            flexitemcolumn: [30, 100, 90, 10],
+            flexitemrow: [100, 50, 20, 10],
+            childcolumn: [20, 20, 92, 23],
+            childrow: [90, 20, 22, 23]
+        },
+        ltr : {
+            containersize: horizontalContainerSize,
+            flexitemcolumn: [30, 100, 40, 10],
+            flexitemrow: [100, 50, 40, 10],
+            childcolumn: [20, 20, 48, 23],
+            childrow: [90, 20, 48, 23]
+        }
+    },
+    'horizontal-bt': {
+        rtl: {
+            containersize: horizontalContainerSize,
+            flexitemcolumn: [30, 100, 90, 30],
+            flexitemrow: [100, 50, 20, 80],
+            childcolumn: [20, 20, 92, 97],
+            childrow: [90, 20, 22, 97]
+        },
+        ltr : {
+            containersize: horizontalContainerSize,
+            flexitemcolumn: [30, 100, 40, 30],
+            flexitemrow: [100, 50, 40, 80],
+            childcolumn: [20, 20, 48, 97],
+            childrow: [90, 20, 48, 97]
+        }
+    },
+    'vertical-lr': {
+        rtl: {
+            containersize: verticalContainerSize,
+            flexitemcolumn: [100, 30, 10, 90],
+            flexitemrow: [50, 100, 10, 20],
+            childcolumn: [20, 20, 23, 92],
+            childrow: [20, 90, 23, 22]
+        },
+        ltr : {
+            containersize: verticalContainerSize,
+            flexitemcolumn: [100, 30, 10, 40],
+            flexitemrow: [50, 100, 10, 40],
+            childcolumn: [20, 20, 23, 48],
+            childrow: [20, 90, 23, 48]
+        }
+    },
+    'vertical-rl': {
+        rtl: {
+            containersize: verticalContainerSize,
+            flexitemcolumn: [100, 30, 30, 90],
+            flexitemrow: [50, 100, 80, 20],
+            childcolumn: [20, 20, 97, 92],
+            childrow: [20, 90, 97, 22]
+        },
+        ltr : {
+            containersize: verticalContainerSize,
+            flexitemcolumn: [100, 30, 30, 40],
+            flexitemrow: [50, 100, 80, 40],
+            childcolumn: [20, 20, 97, 48],
+            childrow: [20, 90, 97, 48]
+        }
+    }
+}
+
+var writingModes = ['horizontal-tb', 'horizontal-bt', 'vertical-lr', 'vertical-rl'];
+// FIXME: Test row-reverse and column-reverse.
+var flexFlows = ['row', 'column'];
+var directions = ['rtl', 'ltr'];
+var marginTypes = ['physical', 'logical'];
+
+writingModes.forEach(function(writingMode) {
+    flexFlows.forEach(function(flexFlow) {
+        directions.forEach(function(direction) {
+            marginTypes.forEach(function(marginType) {
+                var flexboxClassName = writingMode + ' ' + direction + ' ' + flexFlow + ' ' + marginType;
+                var title = document.createElement('div');
+                title.className = 'title';
+                title.innerHTML = flexboxClassName;
+                document.body.appendChild(title);
+
+                var expectations = (marginType == 'physical') ? physicalExpectations : logicalExpectations;
+                expectations = expectations[writingMode][direction];
+
+                var container = document.createElement('div');
+                container.className = 'container';
+                container.setAttribute('data-expected-width', expectations.containersize[0]);
+                container.setAttribute('data-expected-height', expectations.containersize[1]);
+
+                // FIXME: In flex-flow column the innermost diff is always 20x20. Is that correct?
+                container.innerHTML = '\n<div class="flexbox ' + flexboxClassName + '">\n' +
+                    '<div style="width: -webkit-flex(1 20px); height: -webkit-flex(1 20px);" ' + asString(expectations['flexitem' + flexFlow]) + '>\n' +
+                        '<div style="width:100%; height:100%" ' + asString(expectations['child' + flexFlow]) + '></div>' +
+                    '</div>\n' +
+                '</div>\n';
+
+                document.body.appendChild(container);   
+            })
+        })
+    })
+})
+</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/LayoutTests/css3/flexbox/flex-flow.html b/LayoutTests/css3/flexbox/flex-flow.html
new file mode 100644 (file)
index 0000000..7414f02
--- /dev/null
@@ -0,0 +1,115 @@
+<!DOCTYPE html>
+<html>
+<style>
+body {
+    margin: 0;
+}
+.flexbox {
+    width: 600px;
+    display: -webkit-flexbox;
+    background-color: grey;
+}
+.flexbox > div {
+    height: 20px;
+    width: 20px;
+    border: 0;
+}
+
+.rtl {
+    direction: rtl;
+}
+
+.bt {
+    -webkit-writing-mode: horizontal-bt;
+}
+
+.vertical-rl, .vertical-lr, .column, .column-reverse {
+    height: 600px;
+}
+
+.vertical-rl {
+    -webkit-writing-mode: vertical-rl;
+}
+
+.vertical-lr {
+    -webkit-writing-mode: vertical-lr;
+}
+
+.row-reverse {
+    -webkit-flex-flow: row-reverse;
+}
+
+.column {
+    -webkit-flex-flow: column;
+}
+
+.column-reverse {
+    -webkit-flex-flow: column-reverse;
+}
+
+.flexbox > :nth-child(1) {
+    background-color: blue;
+}
+.flexbox > :nth-child(2) {
+    background-color: green;
+}
+.flexbox > :nth-child(3) {
+    background-color: red;
+}
+
+.flexbox > div > div {
+    background-color: orange;
+    height: 10px;
+}
+</style>
+<script>
+if (window.layoutTestController)
+    layoutTestController.dumpAsText();
+</script>
+<script src="resources/flexbox.js"></script>
+<body onload="checkFlexBoxen()">
+
+<div class="flexbox">
+  <div data-expected-width="75" data-offset-x="0" style="width: -webkit-flex(1 0 0); margin: 0 auto;"></div>
+  <div data-expected-width="350" data-offset-x="75" style="width: -webkit-flex(2 0 0); -webkit-padding-start: 200px"><div data-offset-x="275"></div></div>
+  <div data-expected-width="75" data-offset-x="425" style="width: -webkit-flex(1 0 0); -webkit-margin-end: 100px;"></div>
+</div>
+
+<div class="flexbox rtl">
+  <div data-expected-width="75" data-offset-x="525" style="width: -webkit-flex(1 0 0); margin: 0 auto;"></div>
+  <div data-expected-width="350" data-offset-x="175" style="width: -webkit-flex(2 0 0); -webkit-padding-start: 200px"><div data-offset-x="175"></div></div>
+  <div data-expected-width="75" data-offset-x="100" style="width: -webkit-flex(1 0 0); -webkit-margin-end: 100px;"></div>
+</div>
+
+<div style="position: relative;">
+<div class="flexbox column">
+  <div data-expected-height="150" data-offset-y="0" style="height: -webkit-flex(1 0 0); margin: auto 200px auto 150px;"></div>
+  <div data-expected-height="300" data-offset-y="150" style="height: -webkit-flex(2 0 0); -webkit-padding-start: 200px"><div data-offset-y="150" data-offset-x="200"></div></div>
+  <div data-expected-height="150" data-offset-y="450" style="height: -webkit-flex(1 0 0); -webkit-margin-end: 100px;"></div>
+</div>
+</div>
+
+<div style="position: relative;">
+<div class="flexbox column rtl">
+  <div data-expected-height="150" data-offset-y="0" data-offset-x="480" style="height: -webkit-flex(1 0 0); margin: auto 100px auto 50px;"></div>
+  <div data-expected-height="300" data-offset-y="150" style="height: -webkit-flex(2 0 0); -webkit-padding-start: 200px"><div data-offset-y="150" data-offset-x="380"></div></div>
+  <div data-expected-height="150" data-offset-y="450" data-offset-x="580" style="height: -webkit-flex(1 0 0); -webkit-margin-end: 100px;"></div>
+</div>
+</div>
+
+<div style="position: relative;">
+<div data-expected-height="600" class="flexbox vertical-lr column">
+  <div data-offset-x="0" data-expected-width="500" style="width: -webkit-flex(1 0 0); min-width: 300px"></div>
+  <div data-offset-x="500" data-offset-y="100" data-expected-width="100" style="width: -webkit-flex(1 0 200px); max-width: 100px; margin: 100px 0 50px 0;"></div>
+</div>
+</div>
+
+<div style="position: relative;">
+<div data-expected-height="600" class="flexbox vertical-rl column">
+  <div data-offset-x="100" data-expected-width="500" style="width: -webkit-flex(1 0 0); min-width: 300px; margin-bottom: 100px"></div>
+  <div data-offset-x="0" data-offset-y="100" data-expected-width="100" style="width: -webkit-flex(1 0 200px); max-width: 100px; margin: 100px 0 50px 0;"></div>
+</div>
+</div>
+
+</body>
+</html>
\ No newline at end of file
index e7c4611..380c9e7 100644 (file)
@@ -39,6 +39,32 @@ function checkExpectedValues(node, failures)
         if (node.offsetTop != parseInt(expectedOffset))
             failures.push("Expected " + expectedOffset + " for offsetTop, but got " + node.offsetTop + ". ");
     }
+
+    var expectedWidth = node.getAttribute && node.getAttribute("data-expected-client-width");
+    if (expectedWidth) {
+        if (node.clientWidth != parseInt(expectedWidth))
+            failures.push("Expected " + expectedWidth + " for clientWidth, but got " + node.clientWidth + ". ");
+    }
+
+    var expectedHeight = node.getAttribute && node.getAttribute("data-expected-client-height");
+    if (expectedHeight) {
+        if (node.clientHeight != parseInt(expectedHeight))
+            failures.push("Expected " + expectedHeight + " for clientHeight, but got " + node.clientHeight + ". ");
+    }
+
+    var expectedOffset = node.getAttribute && node.getAttribute("data-total-x");
+    if (expectedOffset) {
+        var totalLeft = node.clientLeft + node.offsetLeft;
+        if (totalLeft != parseInt(expectedOffset))
+            failures.push("Expected " + expectedOffset + " for clientLeft+offsetLeft, but got " + totalLeft + ", clientLeft: " + node.clientLeft + ", offsetLeft: " + node.offsetLeft + ". ");
+    }
+
+    var expectedOffset = node.getAttribute && node.getAttribute("data-total-y");
+    if (expectedOffset) {
+        var totalTop = node.clientTop + node.offsetTop;
+        if (totalTop != parseInt(expectedOffset))
+            failures.push("Expected " + expectedOffset + " for clientTop+offsetTop, but got " + totalTop + ", clientTop: " + node.clientTop + ", + offsetTop: " + node.offsetTop + ". ");
+    }
 }
 
 function checkFlexBoxen()
@@ -49,8 +75,15 @@ function checkFlexBoxen()
         checkExpectedValues(flexbox.parentNode, failures);
         checkSubtreeExpectedValues(flexbox, failures);
 
+        var container = flexbox.parentNode.className == 'container' ? flexbox.parentNode : flexbox;
+
         var pre = document.createElement('pre');
-        pre.appendChild(document.createTextNode(failures.length ? "FAIL:\n" + failures.join('\n') + '\n\n' + flexbox.outerHTML : "PASS"));
-        insertAfter(pre, flexbox);
+        if (failures.length)
+            pre.className = 'FAIL';
+        pre.appendChild(document.createTextNode(failures.length ? "FAIL:\n" + failures.join('\n') + '\n\n' + container.outerHTML : "PASS"));
+        insertAfter(pre, container);
     });
+    var pre = document.querySelector('.FAIL');
+    if (pre)
+        setTimeout(function() { pre.previousSibling.scrollIntoView(); }, 0);
 }
index 0c7f798..9d5a199 100644 (file)
@@ -1,3 +1,60 @@
+2011-10-13  Ojan Vafai  <ojan@chromium.org>
+
+        implement flex-flow:column
+        https://bugs.webkit.org/show_bug.cgi?id=70082
+
+        Reviewed by David Hyatt.
+
+        There's still a bug with a FIXME where we don't compute the right
+        size for the container of the flexbox in the presence of
+        orthogonal flows. That's the cause of all the failing cases
+        in the tests.
+
+        Tests: css3/flexbox/flex-flow-border.html
+               css3/flexbox/flex-flow-margins.html
+               css3/flexbox/flex-flow-orientations.html
+               css3/flexbox/flex-flow-overflow.html
+               css3/flexbox/flex-flow-padding.html
+               css3/flexbox/flex-flow.html
+
+        * rendering/RenderFlexibleBox.cpp:
+        (WebCore::RenderFlexibleBox::layoutBlock):
+        (WebCore::RenderFlexibleBox::hasOrthogonalFlow):
+        (WebCore::RenderFlexibleBox::isColumnFlow):
+        (WebCore::RenderFlexibleBox::isHorizontalFlow):
+        (WebCore::RenderFlexibleBox::isLeftToRightFlow):
+        Use isHorizontalFlow and isLeftToRightFlow so that methods like
+        flowAwareBorderStart look exactly like borderStart with
+        isHorizontalWritingMode and isLeftToRightDirection replaced.
+
+        (WebCore::RenderFlexibleBox::setFlowAwareLogicalHeight):
+        (WebCore::RenderFlexibleBox::flowAwareLogicalHeightForChild):
+        (WebCore::RenderFlexibleBox::flowAwareLogicalWidthForChild):
+        (WebCore::RenderFlexibleBox::flowAwareLogicalHeight):
+        (WebCore::RenderFlexibleBox::flowAwareLogicalWidth):
+        (WebCore::RenderFlexibleBox::flowAwareContentLogicalHeight):
+        (WebCore::RenderFlexibleBox::flowAwareContentLogicalWidth):
+        (WebCore::RenderFlexibleBox::transformedWritingMode):
+        Transform the writing-mode based of the flex-flow and direction
+        values. That methods like flowAwareBorderBefore look exactly like
+        borderBefore, except it switches over a different value.
+
+        (WebCore::RenderFlexibleBox::flowAwareBorderStart):
+        (WebCore::RenderFlexibleBox::flowAwareBorderBefore):
+        (WebCore::RenderFlexibleBox::flowAwareBorderAfter):
+        (WebCore::RenderFlexibleBox::flowAwarePaddingStart):
+        (WebCore::RenderFlexibleBox::flowAwarePaddingBefore):
+        (WebCore::RenderFlexibleBox::flowAwarePaddingAfter):
+        (WebCore::RenderFlexibleBox::flowAwareMarginStartForChild):
+        (WebCore::RenderFlexibleBox::flowAwareMarginEndForChild):
+        (WebCore::RenderFlexibleBox::flowAwareMarginBeforeForChild):
+        (WebCore::RenderFlexibleBox::flowAwareMarginAfterForChild):
+        (WebCore::RenderFlexibleBox::setFlowAwareMarginStartForChild):
+        (WebCore::RenderFlexibleBox::setFlowAwareMarginEndForChild):
+        (WebCore::RenderFlexibleBox::layoutAndPlaceChildrenInlineDirection):
+        (WebCore::RenderFlexibleBox::alignChildrenBlockDirection):
+        * rendering/RenderFlexibleBox.h:
+
 2011-10-18  Shawn Singh  <shawnsingh@chromium.org>
 
         [chromium] Tracking update rects in LayerChromium and CCLayerImpl.
index 281fe9c..11cb040 100644 (file)
@@ -175,6 +175,9 @@ void RenderFlexibleBox::layoutBlock(bool relayoutChildren, int, BlockLayoutPass)
 
     layoutInlineDirection(relayoutChildren);
 
+    // FIXME: We should only need to call one of these for a given flex-flow + writing-mode combination.
+    // Is that true above as well?
+    computeLogicalWidth();
     computeLogicalHeight();
 
     if (size() != previousSize)
@@ -189,26 +192,30 @@ void RenderFlexibleBox::layoutBlock(bool relayoutChildren, int, BlockLayoutPass)
 
 bool RenderFlexibleBox::hasOrthogonalFlow(RenderBox* child) const
 {
-    // FIXME: Is the child->isHorizontalWritingMode() check correct if the child is a flexbox?
-    // Should it be using child->isHorizontalFlow in that case?
-    // Or do we only care about the parent's writing mode?
+    // FIXME: If the child is a flexbox, then we need to check isHorizontalFlow.
     return isHorizontalFlow() != child->isHorizontalWritingMode();
 }
 
+bool RenderFlexibleBox::isColumnFlow() const
+{
+    EFlexFlow flow = style()->flexFlow();
+    return flow == FlowColumn || flow == FlowColumnReverse;
+}
+
 bool RenderFlexibleBox::isHorizontalFlow() const
 {
-    // FIXME: Take flex-flow value into account.
-    return isHorizontalWritingMode();
+    if (isHorizontalWritingMode())
+        return !isColumnFlow();
+    return isColumnFlow();
 }
 
 bool RenderFlexibleBox::isLeftToRightFlow() const
 {
-    // FIXME: Take flex-flow value into account.
+    if (isColumnFlow())
+        return style()->writingMode() == TopToBottomWritingMode || style()->writingMode() == LeftToRightWritingMode;
     return style()->isLeftToRightDirection();
 }
 
-// FIXME: Make all these flow aware methods actually be flow aware.
-
 bool RenderFlexibleBox::isFlowAwareLogicalHeightAuto() const
 {
     Length height = isHorizontalFlow() ? style()->height() : style()->width();
@@ -217,52 +224,97 @@ bool RenderFlexibleBox::isFlowAwareLogicalHeightAuto() const
 
 void RenderFlexibleBox::setFlowAwareLogicalHeight(LayoutUnit size)
 {
-    setLogicalHeight(size);
+    if (isHorizontalFlow())
+        setHeight(size);
+    else
+        setWidth(size);
 }
 
 LayoutUnit RenderFlexibleBox::flowAwareLogicalHeightForChild(RenderBox* child)
 {
-    return logicalHeightForChild(child);
+    return isHorizontalFlow() ? child->height() : child->width();
 }
 
 LayoutUnit RenderFlexibleBox::flowAwareLogicalWidthForChild(RenderBox* child)
 {
-    return logicalWidthForChild(child);
+    return isHorizontalFlow() ? child->width() : child->height();
 }
 
 LayoutUnit RenderFlexibleBox::flowAwareLogicalHeight() const
 {
-    return logicalHeight();
+    return isHorizontalFlow() ? height() : width();
 }
 
 LayoutUnit RenderFlexibleBox::flowAwareLogicalWidth() const
 {
-    return logicalWidth();
+    return isHorizontalFlow() ? width() : height();
 }
 
 LayoutUnit RenderFlexibleBox::flowAwareContentLogicalHeight() const
 {
-    return contentLogicalHeight();
+    return isHorizontalFlow() ? contentHeight() : contentWidth();
 }
 
 LayoutUnit RenderFlexibleBox::flowAwareContentLogicalWidth() const
 {
-    return contentLogicalWidth();
+    return isHorizontalFlow() ? contentWidth() : contentHeight();
+}
+
+WritingMode RenderFlexibleBox::transformedWritingMode() const
+{
+    WritingMode mode = style()->writingMode();
+    if (!isColumnFlow())
+        return mode;
+
+    switch (mode) {
+    case TopToBottomWritingMode:
+    case BottomToTopWritingMode:
+        return style()->isLeftToRightDirection() ? LeftToRightWritingMode : RightToLeftWritingMode;
+    case LeftToRightWritingMode:
+    case RightToLeftWritingMode:
+        return style()->isLeftToRightDirection() ? TopToBottomWritingMode : BottomToTopWritingMode;
+    }
+    ASSERT_NOT_REACHED();
+    return TopToBottomWritingMode;
 }
 
 LayoutUnit RenderFlexibleBox::flowAwareBorderStart() const
 {
-    return borderStart();
+    if (isHorizontalFlow())
+        return isLeftToRightFlow() ? borderLeft() : borderRight();
+    return isLeftToRightFlow() ? borderTop() : borderBottom();
 }
 
 LayoutUnit RenderFlexibleBox::flowAwareBorderBefore() const
 {
-    return borderBefore();
+    switch (transformedWritingMode()) {
+    case TopToBottomWritingMode:
+        return borderTop();
+    case BottomToTopWritingMode:
+        return borderBottom();
+    case LeftToRightWritingMode:
+        return borderLeft();
+    case RightToLeftWritingMode:
+        return borderRight();
+    }
+    ASSERT_NOT_REACHED();
+    return borderTop();
 }
 
 LayoutUnit RenderFlexibleBox::flowAwareBorderAfter() const
 {
-    return borderAfter();
+    switch (transformedWritingMode()) {
+    case TopToBottomWritingMode:
+        return borderBottom();
+    case BottomToTopWritingMode:
+        return borderTop();
+    case LeftToRightWritingMode:
+        return borderRight();
+    case RightToLeftWritingMode:
+        return borderLeft();
+    }
+    ASSERT_NOT_REACHED();
+    return borderBottom();
 }
 
 LayoutUnit RenderFlexibleBox::flowAwareBorderAndPaddingLogicalHeight() const
@@ -273,37 +325,87 @@ LayoutUnit RenderFlexibleBox::flowAwareBorderAndPaddingLogicalHeight() const
 
 LayoutUnit RenderFlexibleBox::flowAwarePaddingStart() const
 {
-    return paddingStart();
+    if (isHorizontalFlow())
+        return isLeftToRightFlow() ? paddingLeft() : paddingRight();
+    return isLeftToRightFlow() ? paddingTop() : paddingBottom();
 }
 
 LayoutUnit RenderFlexibleBox::flowAwarePaddingBefore() const
 {
-    return paddingBefore();
+    switch (transformedWritingMode()) {
+    case TopToBottomWritingMode:
+        return paddingTop();
+    case BottomToTopWritingMode:
+        return paddingBottom();
+    case LeftToRightWritingMode:
+        return paddingLeft();
+    case RightToLeftWritingMode:
+        return paddingRight();
+    }
+    ASSERT_NOT_REACHED();
+    return paddingTop();
 }
 
 LayoutUnit RenderFlexibleBox::flowAwarePaddingAfter() const
 {
-    return paddingAfter();
+    switch (transformedWritingMode()) {
+    case TopToBottomWritingMode:
+        return paddingBottom();
+    case BottomToTopWritingMode:
+        return paddingTop();
+    case LeftToRightWritingMode:
+        return paddingRight();
+    case RightToLeftWritingMode:
+        return paddingLeft();
+    }
+    ASSERT_NOT_REACHED();
+    return paddingBottom();
 }
 
 LayoutUnit RenderFlexibleBox::flowAwareMarginStartForChild(RenderBox* child) const
 {
-    return marginStartForChild(child);
+    if (isHorizontalFlow())
+        return isLeftToRightFlow() ? child->marginLeft() : child->marginRight();
+    return isLeftToRightFlow() ? child->marginTop() : child->marginBottom();
 }
 
 LayoutUnit RenderFlexibleBox::flowAwareMarginEndForChild(RenderBox* child) const
 {
-    return marginStartForChild(child);
+    if (isHorizontalFlow())
+        return isLeftToRightFlow() ? child->marginRight() : child->marginLeft();
+    return isLeftToRightFlow() ? child->marginBottom() : child->marginTop();
 }
 
 LayoutUnit RenderFlexibleBox::flowAwareMarginBeforeForChild(RenderBox* child) const
 {
-    return marginBeforeForChild(child);
+    switch (transformedWritingMode()) {
+    case TopToBottomWritingMode:
+        return child->marginTop();
+    case BottomToTopWritingMode:
+        return child->marginBottom();
+    case LeftToRightWritingMode:
+        return child->marginLeft();
+    case RightToLeftWritingMode:
+        return child->marginRight();
+    }
+    ASSERT_NOT_REACHED();
+    return marginTop();
 }
 
 LayoutUnit RenderFlexibleBox::flowAwareMarginAfterForChild(RenderBox* child) const
 {
-    return marginAfterForChild(child);
+    switch (transformedWritingMode()) {
+    case TopToBottomWritingMode:
+        return child->marginBottom();
+    case BottomToTopWritingMode:
+        return child->marginTop();
+    case LeftToRightWritingMode:
+        return child->marginRight();
+    case RightToLeftWritingMode:
+        return child->marginLeft();
+    }
+    ASSERT_NOT_REACHED();
+    return marginBottom();
 }
 
 LayoutUnit RenderFlexibleBox::flowAwareMarginLogicalHeightForChild(RenderBox* child) const
@@ -319,12 +421,32 @@ LayoutPoint RenderFlexibleBox::flowAwareLogicalLocationForChild(RenderBox* child
 
 void RenderFlexibleBox::setFlowAwareMarginStartForChild(RenderBox* child, LayoutUnit margin)
 {
-    setMarginStartForChild(child, margin);
+    if (isHorizontalFlow()) {
+        if (isLeftToRightFlow())
+            child->setMarginLeft(margin);
+        else
+            child->setMarginRight(margin);
+    } else {
+        if (isLeftToRightFlow())
+            child->setMarginTop(margin);
+        else
+            child->setMarginBottom(margin);
+    }
 }
 
 void RenderFlexibleBox::setFlowAwareMarginEndForChild(RenderBox* child, LayoutUnit margin)
 {
-    setMarginEndForChild(child, margin);
+    if (isHorizontalFlow()) {
+        if (isLeftToRightFlow())
+            child->setMarginRight(margin);
+        else
+            child->setMarginLeft(margin);
+    } else {
+        if (isLeftToRightFlow())
+            child->setMarginBottom(margin);
+        else
+            child->setMarginTop(margin);
+    }
 }
 
 void RenderFlexibleBox::setFlowAwareLogicalLocationForChild(RenderBox* child, const LayoutPoint& location)
@@ -547,11 +669,13 @@ void RenderFlexibleBox::layoutAndPlaceChildrenInlineDirection(FlexOrderIterator&
         startEdge += flowAwareMarginStartForChild(child);
 
         LayoutUnit childLogicalWidth = flowAwareLogicalWidthForChild(child);
-        LayoutUnit logicalLeft = isLeftToRightFlow() ? startEdge : totalLogicalWidth - startEdge - childLogicalWidth;
+        bool shouldFlipInlineDirection = isColumnFlow() ? true : isLeftToRightFlow();
+        LayoutUnit logicalLeft = shouldFlipInlineDirection ? startEdge : totalLogicalWidth - startEdge - childLogicalWidth;
+
         // FIXME: Do repaintDuringLayoutIfMoved.
         // FIXME: Supporting layout deltas.
         setFlowAwareLogicalLocationForChild(child, IntPoint(logicalLeft, logicalTop + flowAwareMarginBeforeForChild(child)));
-        startEdge += childLogicalWidth + marginEndForChild(child);
+        startEdge += childLogicalWidth + flowAwareMarginEndForChild(child);
 
         if (hasPackingSpace(availableFreeSpace, totalPositiveFlexibility) && style()->flexPack() == PackJustify && childSizes.size() > 1)
             startEdge += availableFreeSpace / (childSizes.size() - 1);
@@ -567,7 +691,17 @@ void RenderFlexibleBox::adjustLocationLogicalTopForChild(RenderBox* child, Layou
 
 void RenderFlexibleBox::alignChildrenBlockDirection(FlexOrderIterator& iterator, LayoutUnit maxAscent)
 {
+    LayoutUnit logicalHeight = flowAwareLogicalHeight();
+
     for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
+        // direction:rtl + flex-flow:column means the cross-axis direction is flipped.
+        if (!style()->isLeftToRightDirection() && isColumnFlow()) {
+            LayoutPoint location = flowAwareLogicalLocationForChild(child);
+            location.setY(logicalHeight - flowAwareLogicalHeightForChild(child) - location.y());
+            setFlowAwareLogicalLocationForChild(child, location);
+        }
+
+        // FIXME: Make sure this does the right thing with column flows.
         switch (child->style()->flexAlign()) {
         case AlignStretch: {
             Length height = isHorizontalFlow() ? child->style()->height() : child->style()->width();
index 9ff2575..b6c0a23 100644 (file)
@@ -53,7 +53,9 @@ private:
     class FlexOrderIterator;
     typedef WTF::HashMap<const RenderBox*, LayoutUnit> InflexibleFlexItemSize;
 
+    // FIXME: Implement computePreferredLogicalWidths since it needs to be flow-aware.
     bool hasOrthogonalFlow(RenderBox* child) const;
+    bool isColumnFlow() const;
     bool isHorizontalFlow() const;
     bool isLeftToRightFlow() const;
     bool isFlowAwareLogicalHeightAuto() const;
@@ -64,6 +66,7 @@ private:
     LayoutUnit flowAwareLogicalWidth() const;
     LayoutUnit flowAwareContentLogicalHeight() const;
     LayoutUnit flowAwareContentLogicalWidth() const;
+    WritingMode transformedWritingMode() const;
     LayoutUnit flowAwareBorderStart() const;
     LayoutUnit flowAwareBorderBefore() const;
     LayoutUnit flowAwareBorderAfter() const;