Need to handle absolutely positioned elements inside flexboxes
authortony@chromium.org <tony@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 10 Jan 2012 23:52:56 +0000 (23:52 +0000)
committertony@chromium.org <tony@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 10 Jan 2012 23:52:56 +0000 (23:52 +0000)
https://bugs.webkit.org/show_bug.cgi?id=70793

Reviewed by David Hyatt.

Source/WebCore:

Tests: css3/flexbox/insert-text-crash.html
       css3/flexbox/position-absolute-child.html

* rendering/RenderFlexibleBox.cpp:
(WebCore::RenderFlexibleBox::computePreferredMainAxisExtent): Skip the size of positioned elements.
(WebCore::RenderFlexibleBox::runFreeSpaceAllocationAlgorithm): Add placeholders for positioned elements.
(WebCore::RenderFlexibleBox::prepareChildForPositionedLayout): Positions the layer for the positioned child.
(WebCore::RenderFlexibleBox::layoutAndPlaceChildren): Handle positioned elements.
(WebCore::RenderFlexibleBox::layoutColumnReverse): Adjust the main axis offset of the layer for positioned elements.
* rendering/RenderFlexibleBox.h:

LayoutTests:

* css3/flexbox/insert-text-crash-expected.txt: Added.
* css3/flexbox/insert-text-crash.html: Added.
* css3/flexbox/position-absolute-child-expected.txt: Added.
* css3/flexbox/position-absolute-child.html: Added.

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

LayoutTests/ChangeLog
LayoutTests/css3/flexbox/insert-text-crash-expected.txt [new file with mode: 0644]
LayoutTests/css3/flexbox/insert-text-crash.html [new file with mode: 0644]
LayoutTests/css3/flexbox/position-absolute-child-expected.txt [new file with mode: 0644]
LayoutTests/css3/flexbox/position-absolute-child.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/rendering/RenderFlexibleBox.cpp
Source/WebCore/rendering/RenderFlexibleBox.h

index 0c881dc..92728a1 100644 (file)
@@ -1,3 +1,15 @@
+2012-01-10  Tony Chang  <tony@chromium.org>
+
+        Need to handle absolutely positioned elements inside flexboxes
+        https://bugs.webkit.org/show_bug.cgi?id=70793
+
+        Reviewed by David Hyatt.
+
+        * css3/flexbox/insert-text-crash-expected.txt: Added.
+        * css3/flexbox/insert-text-crash.html: Added.
+        * css3/flexbox/position-absolute-child-expected.txt: Added.
+        * css3/flexbox/position-absolute-child.html: Added.
+
 2012-01-10  Ryosuke Niwa  <rniwa@webkit.org>
 
         Chromium rebaseline after r104625.
diff --git a/LayoutTests/css3/flexbox/insert-text-crash-expected.txt b/LayoutTests/css3/flexbox/insert-text-crash-expected.txt
new file mode 100644 (file)
index 0000000..654ddf7
--- /dev/null
@@ -0,0 +1 @@
+This test passes if it does not crash.
diff --git a/LayoutTests/css3/flexbox/insert-text-crash.html b/LayoutTests/css3/flexbox/insert-text-crash.html
new file mode 100644 (file)
index 0000000..7810e8e
--- /dev/null
@@ -0,0 +1,20 @@
+<style>
+#el2 {
+    display: -webkit-flexbox;
+    border: 1px solid red;
+}
+#el3 {
+    position: absolute;
+    border: 1px solid green;
+}
+</style>
+<body contenteditable=true>
+<div id="el2"><div id="el3">AA </div></div>
+</body>
+<script>
+if (window.layoutTestController)
+    layoutTestController.dumpAsText();
+document.execCommand('selectall')
+document.execCommand('inserttext', '')
+document.body.innerText = "This test passes if it does not crash.";
+</script>
diff --git a/LayoutTests/css3/flexbox/position-absolute-child-expected.txt b/LayoutTests/css3/flexbox/position-absolute-child-expected.txt
new file mode 100644 (file)
index 0000000..8d7fc4f
--- /dev/null
@@ -0,0 +1,224 @@
+horizontal-tb ltr row
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+horizontal-tb rtl row
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+horizontal-tb ltr column
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+horizontal-tb rtl column
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+horizontal-tb ltr row-reverse
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+horizontal-tb rtl row-reverse
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+horizontal-tb ltr column-reverse
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+horizontal-tb rtl column-reverse
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+horizontal-bt ltr row
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+horizontal-bt rtl row
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+horizontal-bt ltr column
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+horizontal-bt rtl column
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+horizontal-bt ltr row-reverse
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+horizontal-bt rtl row-reverse
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+horizontal-bt ltr column-reverse
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+horizontal-bt rtl column-reverse
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+vertical-rl ltr row
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+vertical-rl rtl row
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+vertical-rl ltr column
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+vertical-rl rtl column
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+vertical-rl ltr row-reverse
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+vertical-rl rtl row-reverse
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+vertical-rl ltr column-reverse
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+vertical-rl rtl column-reverse
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+vertical-lr ltr row
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+vertical-lr rtl row
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+vertical-lr ltr column
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+vertical-lr rtl column
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+vertical-lr ltr row-reverse
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+vertical-lr rtl row-reverse
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+vertical-lr ltr column-reverse
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+vertical-lr rtl column-reverse
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
diff --git a/LayoutTests/css3/flexbox/position-absolute-child.html b/LayoutTests/css3/flexbox/position-absolute-child.html
new file mode 100644 (file)
index 0000000..d7155ed
--- /dev/null
@@ -0,0 +1,478 @@
+<!DOCTYPE html>
+<html>
+<style>
+body {
+    margin: 0;
+}
+
+.title {
+    margin-top: 1em;
+}
+
+.flexbox {
+    display: -webkit-flexbox;
+    background-color: #aaa;
+    position: relative;
+}
+.flexbox div {
+    border: 0;
+}
+
+.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;
+}
+
+.rtl {
+    direction: rtl;
+}
+.ltr {
+    direction: ltr;
+}
+
+</style>
+<script>
+if (window.layoutTestController)
+    layoutTestController.dumpAsText();
+</script>
+<script src="resources/flexbox.js"></script>
+<body onload="checkFlexBoxen()">
+
+<script>
+function getFlexDirection(flexFlow, writingMode)
+{
+    if (writingMode.indexOf('horizontal') != -1)
+        return (flexFlow.indexOf('row') != -1) ? 'width' : 'height';
+    return (flexFlow.indexOf('row') != -1) ? 'height' : 'width';
+}
+
+var writingModes = ['horizontal-tb', 'horizontal-bt', 'vertical-rl', 'vertical-lr'];
+var flexFlows = ['row', 'column', 'row-reverse', 'column-reverse'];
+var directions = ['ltr', 'rtl'];
+
+var expectations = {
+    'horizontal-tb': {
+        row: {
+            ltr: [
+                { offsets: [0, 0, 240], sizes: [0, 240, 360] },
+                { offsets: [0, 150, 150], sizes: [150, 0, 450] },
+                { offsets: [0, 200, 600], sizes: [200, 400, 0] },
+                { offsets: [0, 260, 560] },
+                { offsets: [0, 300, 560] },
+                { offsets: [0, 300, 600] },
+            ],
+            rtl: [
+                { offsets: [600, 360, 0], sizes: [0, 240, 360] },
+                { offsets: [450, 450, 0], sizes: [150, 0, 450] },
+                { offsets: [400, 0, 0], sizes: [200, 400, 0] },
+                { offsets: [580, 300, 0] },
+                { offsets: [560, 280, 0] },
+                { offsets: [560, 260, -20] },
+            ],
+        },
+        column: {
+            ltr: [
+                { offsets: [0, 0, 48], sizes: [0, 48, 72] },
+                { offsets: [0, 30, 30], sizes: [30, 0, 90] },
+                { offsets: [0, 40, 120], sizes: [40, 80, 0] },
+                { offsets: [0, 20, 80] },
+                { offsets: [0, 60, 80] },
+                { offsets: [0, 60, 120] },
+            ],
+            rtl: [
+                { offsets: [0, 0, 48], sizes: [0, 48, 72] },
+                { offsets: [0, 30, 30], sizes: [30, 0, 90] },
+                { offsets: [0, 40, 120], sizes: [40, 80, 0] },
+                { offsets: [0, 20, 80] },
+                { offsets: [0, 60, 80] },
+                { offsets: [0, 60, 120] },
+            ],
+        },
+        'row-reverse': {
+            ltr: [
+                { offsets: [600, 360, 0], sizes: [0, 240, 360] },
+                { offsets: [450, 450, 0], sizes: [150, 0, 450] },
+                { offsets: [400, 0, 0], sizes: [200, 400, 0] },
+                { offsets: [600, 300, 0] },
+                { offsets: [560, 300, 0] },
+                { offsets: [560, 260, 0] },
+            ],
+            rtl: [
+                { offsets: [0, 0, 240], sizes: [0, 240, 360] },
+                { offsets: [0, 150, 150], sizes: [150, 0, 450] },
+                { offsets: [0, 200, 600], sizes: [200, 400, 0] },
+                { offsets: [-20, 260, 560] },
+                { offsets: [0, 280, 560] },
+                { offsets: [0, 300, 580] },
+            ],
+        },
+        'column-reverse': {
+            ltr: [
+                { offsets: [120, 72, 0], sizes: [0, 48, 72] },
+                { offsets: [90, 90, 0], sizes: [30, 0, 90] },
+                { offsets: [80, 0, 0], sizes: [40, 80, 0] },
+                { offsets: [120, 60, 0] },
+                { offsets: [80, 60, 0] },
+                { offsets: [80, 20, 0] },
+            ],
+            rtl: [
+                { offsets: [120, 72, 0], sizes: [0, 48, 72] },
+                { offsets: [90, 90, 0], sizes: [30, 0, 90] },
+                { offsets: [80, 0, 0], sizes: [40, 80, 0] },
+                { offsets: [120, 60, 0] },
+                { offsets: [80, 60, 0] },
+                { offsets: [80, 20, 0] },
+            ],
+        },
+    },
+    'horizontal-bt': {
+        // This matches the horizontal-tb values above.
+        row: {
+            ltr: [
+                { offsets: [0, 0, 240], sizes: [0, 240, 360] },
+                { offsets: [0, 150, 150], sizes: [150, 0, 450] },
+                { offsets: [0, 200, 600], sizes: [200, 400, 0] },
+                { offsets: [0, 260, 560] },
+                { offsets: [0, 300, 560] },
+                { offsets: [0, 300, 600] },
+            ],
+            rtl: [
+                { offsets: [600, 360, 0], sizes: [0, 240, 360] },
+                { offsets: [450, 450, 0], sizes: [150, 0, 450] },
+                { offsets: [400, 0, 0], sizes: [200, 400, 0] },
+                { offsets: [580, 300, 0] },
+                { offsets: [560, 280, 0] },
+                { offsets: [560, 260, -20] },
+            ],
+        },
+        // horizontal-bt flips the main axis direction so the offsets are different from horizontal-tb.
+        column: {
+            ltr: [
+                { offsets: [120, 72, 0], sizes: [0, 48, 72] },
+                { offsets: [90, 90, 0], sizes: [30, 0, 90] },
+                { offsets: [80, 0, 0], sizes: [40, 80, 0] },
+                { offsets: [100, 60, 0] },
+                { offsets: [80, 40, 0] },
+                { offsets: [80, 20, -20] },
+            ],
+            rtl: [
+                { offsets: [120, 72, 0], sizes: [0, 48, 72] },
+                { offsets: [90, 90, 0], sizes: [30, 0, 90] },
+                { offsets: [80, 0, 0], sizes: [40, 80, 0] },
+                { offsets: [100, 60, 0] },
+                { offsets: [80, 40, 0] },
+                { offsets: [80, 20, -20] },
+            ],
+        },
+        'row-reverse': {
+            ltr: [
+                { offsets: [600, 360, 0], sizes: [0, 240, 360] },
+                { offsets: [450, 450, 0], sizes: [150, 0, 450] },
+                { offsets: [400, 0, 0], sizes: [200, 400, 0] },
+                { offsets: [600, 300, 0] },
+                { offsets: [560, 300, 0] },
+                { offsets: [560, 260, 0] },
+            ],
+            rtl: [
+                { offsets: [0, 0, 240], sizes: [0, 240, 360] },
+                { offsets: [0, 150, 150], sizes: [150, 0, 450] },
+                { offsets: [0, 200, 600], sizes: [200, 400, 0] },
+                { offsets: [-20, 260, 560] },
+                { offsets: [0, 280, 560] },
+                { offsets: [0, 300, 580] },
+            ],
+        },
+        'column-reverse': {
+            ltr: [
+                { offsets: [0, 0, 48], sizes: [0, 48, 72] },
+                { offsets: [0, 30, 30], sizes: [30, 0, 90] },
+                { offsets: [0, 40, 120], sizes: [40, 80, 0] },
+                { offsets: [-20, 20, 80] },
+                { offsets: [0, 40, 80] },
+                { offsets: [0, 60, 100] },
+            ],
+            rtl: [
+                { offsets: [0, 0, 48], sizes: [0, 48, 72] },
+                { offsets: [0, 30, 30], sizes: [30, 0, 90] },
+                { offsets: [0, 40, 120], sizes: [40, 80, 0] },
+                { offsets: [-20, 20, 80] },
+                { offsets: [0, 40, 80] },
+                { offsets: [0, 60, 100] },
+            ],
+        },
+    },
+    'vertical-rl': {
+        row: {
+            // The same as horizontal-tb + column.
+            ltr: [
+                { offsets: [0, 0, 48], sizes: [0, 48, 72] },
+                { offsets: [0, 30, 30], sizes: [30, 0, 90] },
+                { offsets: [0, 40, 120], sizes: [40, 80, 0] },
+                { offsets: [0, 20, 80] },
+                { offsets: [0, 60, 80] },
+                { offsets: [0, 60, 120] },
+            ],
+            rtl: [
+                { offsets: [120, 72, 0], sizes: [0, 48, 72] },
+                { offsets: [90, 90, 0], sizes: [30, 0, 90] },
+                { offsets: [80, 0, 0], sizes: [40, 80, 0] },
+                { offsets: [100, 60, 0] },
+                { offsets: [80, 40, 0] },
+                { offsets: [80, 20, -20] },
+            ],
+        },
+        column: {
+            // The same as horizontal-tb + row.
+            ltr: [
+                { offsets: [600, 360, 0], sizes: [0, 240, 360] },
+                { offsets: [450, 450, 0], sizes: [150, 0, 450] },
+                { offsets: [400, 0, 0], sizes: [200, 400, 0] },
+                { offsets: [580, 300, 0] },
+                { offsets: [560, 280, 0] },
+                { offsets: [560, 260, -20] },
+            ],
+            rtl: [
+                { offsets: [600, 360, 0], sizes: [0, 240, 360] },
+                { offsets: [450, 450, 0], sizes: [150, 0, 450] },
+                { offsets: [400, 0, 0], sizes: [200, 400, 0] },
+                { offsets: [580, 300, 0] },
+                { offsets: [560, 280, 0] },
+                { offsets: [560, 260, -20] },
+            ],
+        },
+        'row-reverse': {
+            ltr: [
+                { offsets: [120, 72, 0], sizes: [0, 48, 72] },
+                { offsets: [90, 90, 0], sizes: [30, 0, 90] },
+                { offsets: [80, 0, 0], sizes: [40, 80, 0] },
+                { offsets: [120, 60, 0] },
+                { offsets: [80, 60, 0] },
+                { offsets: [80, 20, 0] },
+            ],
+            rtl: [
+                { offsets: [0, 0, 48], sizes: [0, 48, 72] },
+                { offsets: [0, 30, 30], sizes: [30, 0, 90] },
+                { offsets: [0, 40, 120], sizes: [40, 80, 0] },
+                { offsets: [-20, 20, 80] },
+                { offsets: [0, 40, 80] },
+                { offsets: [0, 60, 100] },
+            ],
+        },
+        'column-reverse': {
+            ltr: [
+                { offsets: [0, 0, 240], sizes: [0, 240, 360] },
+                { offsets: [0, 150, 150], sizes: [150, 0, 450] },
+                { offsets: [0, 200, 600], sizes: [200, 400, 0] },
+                { offsets: [-20, 260, 560] },
+                { offsets: [0, 280, 560] },
+                { offsets: [0, 300, 580] },
+            ],
+            rtl: [
+                { offsets: [0, 0, 240], sizes: [0, 240, 360] },
+                { offsets: [0, 150, 150], sizes: [150, 0, 450] },
+                { offsets: [0, 200, 600], sizes: [200, 400, 0] },
+                { offsets: [-20, 260, 560] },
+                { offsets: [0, 280, 560] },
+                { offsets: [0, 300, 580] },
+            ],
+        }
+    },
+    'vertical-lr': {
+        row: {
+            // The same as horizontal-tb + column.
+            ltr: [
+                { offsets: [0, 0, 48], sizes: [0, 48, 72] },
+                { offsets: [0, 30, 30], sizes: [30, 0, 90] },
+                { offsets: [0, 40, 120], sizes: [40, 80, 0] },
+                { offsets: [0, 20, 80] },
+                { offsets: [0, 60, 80] },
+                { offsets: [0, 60, 120] },
+            ],
+            rtl: [
+                { offsets: [120, 72, 0], sizes: [0, 48, 72] },
+                { offsets: [90, 90, 0], sizes: [30, 0, 90] },
+                { offsets: [80, 0, 0], sizes: [40, 80, 0] },
+                { offsets: [100, 60, 0] },
+                { offsets: [80, 40, 0] },
+                { offsets: [80, 20, -20] },
+            ],
+        },
+        column: {
+            // The same as horizontal-bt + row.
+            ltr: [
+                { offsets: [0, 0, 240], sizes: [0, 240, 360] },
+                { offsets: [0, 150, 150], sizes: [150, 0, 450] },
+                { offsets: [0, 200, 600], sizes: [200, 400, 0] },
+                { offsets: [0, 260, 560] },
+                { offsets: [0, 300, 560] },
+                { offsets: [0, 300, 600] },
+            ],
+            rtl: [
+                { offsets: [0, 0, 240], sizes: [0, 240, 360] },
+                { offsets: [0, 150, 150], sizes: [150, 0, 450] },
+                { offsets: [0, 200, 600], sizes: [200, 400, 0] },
+                { offsets: [0, 260, 560] },
+                { offsets: [0, 300, 560] },
+                { offsets: [0, 300, 600] },
+            ],
+        },
+        'row-reverse': {
+            ltr: [
+                { offsets: [120, 72, 0], sizes: [0, 48, 72] },
+                { offsets: [90, 90, 0], sizes: [30, 0, 90] },
+                { offsets: [80, 0, 0], sizes: [40, 80, 0] },
+                { offsets: [120, 60, 0] },
+                { offsets: [80, 60, 0] },
+                { offsets: [80, 20, 0] },
+            ],
+            rtl: [
+                { offsets: [0, 0, 48], sizes: [0, 48, 72] },
+                { offsets: [0, 30, 30], sizes: [30, 0, 90] },
+                { offsets: [0, 40, 120], sizes: [40, 80, 0] },
+                { offsets: [-20, 20, 80] },
+                { offsets: [0, 40, 80] },
+                { offsets: [0, 60, 100] },
+            ],
+        },
+        'column-reverse': {
+            ltr: [
+                { offsets: [600, 360, 0], sizes: [0, 240, 360] },
+                { offsets: [450, 450, 0], sizes: [150, 0, 450] },
+                { offsets: [400, 0, 0], sizes: [200, 400, 0] },
+                { offsets: [600, 300, 0] },
+                { offsets: [560, 300, 0] },
+                { offsets: [560, 260, 0] },
+            ],
+            rtl: [
+                { offsets: [600, 360, 0], sizes: [0, 240, 360] },
+                { offsets: [450, 450, 0], sizes: [150, 0, 450] },
+                { offsets: [400, 0, 0], sizes: [200, 400, 0] },
+                { offsets: [600, 300, 0] },
+                { offsets: [560, 300, 0] },
+                { offsets: [560, 260, 0] },
+            ],
+        },
+    }
+};
+
+function setFlexboxSize(flexbox, flexDirection)
+{
+    if ('width' == flexDirection) {
+        flexbox.style.width = '600px';
+    } else {
+        flexbox.style.width = '100px';
+        flexbox.style.height = '120px';
+    }
+}
+
+function addFlexPackJustifyTests(writingMode, flexFlow, direction, flexDirection)
+{
+    var flexboxClassName = writingMode + ' ' + direction + ' ' + flexFlow;
+
+
+    for (var absoluteIndex = 1; absoluteIndex <= 3; ++absoluteIndex) {
+        var expected = expectations[writingMode][flexFlow][direction][2 + absoluteIndex];
+
+        // Absolute div is 20px, other divs should be 40px.
+        expected.sizes = [40, 40, 40];
+        expected.sizes[absoluteIndex - 1] = 20;
+
+        var flexbox = document.createElement('div');
+        flexbox.className = 'flexbox ' + flexboxClassName;
+        setFlexboxSize(flexbox, flexDirection);
+        flexbox.style.webkitFlexPack = 'justify';
+        for (var childIndex = 1; childIndex <= 3; ++childIndex) {
+            var child = document.createElement('div');
+            child.style[flexDirection] = '40px';
+            if (absoluteIndex == childIndex) {
+                child.style.position = 'absolute';
+                child.style[flexDirection] = '20px';
+                if ('height' == flexDirection)
+                    child.style.width = '100px';
+            }
+
+            if ('width' == flexDirection)
+                child.style.height = '20px';
+
+            child.setAttribute('data-offset-' + (flexDirection == 'width' ? 'x' : 'y'), expected.offsets[childIndex - 1]);
+            child.setAttribute('data-expected-' + flexDirection, expected.sizes[childIndex - 1]);
+            flexbox.appendChild(child);
+        }
+
+        document.body.appendChild(flexbox);
+    }
+}
+
+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 flexDirection = getFlexDirection(flexFlow, writingMode);
+
+            for (var absoluteIndex = 1; absoluteIndex <= 3; ++absoluteIndex) {
+                var expected = expectations[writingMode][flexFlow][direction][absoluteIndex - 1];
+
+                var flexbox = document.createElement('div');
+                flexbox.className = 'flexbox ' + flexboxClassName;
+                setFlexboxSize(flexbox, flexDirection);
+                for (var childIndex = 1; childIndex <= 3; ++childIndex) {
+                    var child = document.createElement('div');
+                    child.style[flexDirection] = '-webkit-flex(' + childIndex + ')';
+                    if (childIndex == absoluteIndex)
+                        child.style.position = 'absolute';
+
+                    if ('width' == flexDirection)
+                        child.style.height = '20px';
+
+                    child.setAttribute('data-offset-' + (flexDirection == 'width' ? 'x' : 'y'), expected.offsets[childIndex - 1]);
+                    child.setAttribute('data-expected-' + flexDirection, expected.sizes[childIndex - 1]);
+                    flexbox.appendChild(child);
+                }
+
+                document.body.appendChild(flexbox);
+            }
+            addFlexPackJustifyTests(writingMode, flexFlow, direction, flexDirection);
+        })
+    })
+})
+
+</script>
+
+</body>
+</html>
index 2273929..2d5c0e6 100644 (file)
@@ -1,3 +1,21 @@
+2012-01-10  Tony Chang  <tony@chromium.org>
+
+        Need to handle absolutely positioned elements inside flexboxes
+        https://bugs.webkit.org/show_bug.cgi?id=70793
+
+        Reviewed by David Hyatt.
+
+        Tests: css3/flexbox/insert-text-crash.html
+               css3/flexbox/position-absolute-child.html
+
+        * rendering/RenderFlexibleBox.cpp:
+        (WebCore::RenderFlexibleBox::computePreferredMainAxisExtent): Skip the size of positioned elements.
+        (WebCore::RenderFlexibleBox::runFreeSpaceAllocationAlgorithm): Add placeholders for positioned elements.
+        (WebCore::RenderFlexibleBox::prepareChildForPositionedLayout): Positions the layer for the positioned child.
+        (WebCore::RenderFlexibleBox::layoutAndPlaceChildren): Handle positioned elements.
+        (WebCore::RenderFlexibleBox::layoutColumnReverse): Adjust the main axis offset of the layer for positioned elements.
+        * rendering/RenderFlexibleBox.h:
+
 2012-01-10  Nat Duca  <nduca@chromium.org>
 
         [chromium] Reuse old timebase when activating CCDelayBasedTimeSource
index 55f8843..0a646d9 100644 (file)
@@ -32,6 +32,7 @@
 #include "RenderFlexibleBox.h"
 
 #include "LayoutRepainter.h"
+#include "RenderLayer.h"
 #include "RenderView.h"
 
 namespace WebCore {
@@ -488,6 +489,9 @@ void RenderFlexibleBox::computePreferredMainAxisExtent(bool relayoutChildren, Tr
 
     LayoutUnit flexboxAvailableContentExtent = mainAxisContentExtent();
     for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
+        if (child->isPositioned())
+            continue;
+
         child->clearOverrideSize();
         if (mainAxisLengthForChild(child).isAuto()) {
             if (!relayoutChildren)
@@ -523,6 +527,11 @@ bool RenderFlexibleBox::runFreeSpaceAllocationAlgorithm(FlexOrderIterator& itera
 
     LayoutUnit flexboxAvailableContentExtent = mainAxisContentExtent();
     for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
+        if (child->isPositioned()) {
+            childSizes.append(0);
+            continue;
+        }
+
         LayoutUnit childPreferredSize;
         if (inflexibleItems.contains(child))
             childPreferredSize = inflexibleItems.get(child);
@@ -591,6 +600,24 @@ void RenderFlexibleBox::setLogicalOverrideSize(RenderBox* child, LayoutUnit chil
         child->setOverrideWidth(childPreferredSize);
 }
 
+void RenderFlexibleBox::prepareChildForPositionedLayout(RenderBox* child, LayoutUnit mainAxisOffset, LayoutUnit crossAxisOffset)
+{
+    ASSERT(child->isPositioned());
+    child->containingBlock()->insertPositionedObject(child);
+    RenderLayer* childLayer = child->layer();
+    LayoutUnit inlinePosition = isColumnFlow() ? crossAxisOffset : mainAxisOffset;
+    if (style()->flexDirection() == FlowRowReverse)
+        inlinePosition = mainAxisExtent() - mainAxisOffset;
+    childLayer->setStaticInlinePosition(inlinePosition); // FIXME: Not right for regions.
+
+    LayoutUnit staticBlockPosition = isColumnFlow() ? mainAxisOffset : crossAxisOffset;
+    if (childLayer->staticBlockPosition() != staticBlockPosition) {
+        childLayer->setStaticBlockPosition(staticBlockPosition);
+        if (child->style()->hasStaticBlockPosition(style()->isHorizontalWritingMode()))
+            child->setChildNeedsLayout(true, false);
+    }
+}
+
 void RenderFlexibleBox::layoutAndPlaceChildren(FlexOrderIterator& iterator, const WTF::Vector<LayoutUnit>& childSizes, LayoutUnit availableFreeSpace, float totalPositiveFlexibility)
 {
     LayoutUnit mainAxisOffset = flowAwareBorderStart() + flowAwarePaddingStart();
@@ -602,6 +629,11 @@ void RenderFlexibleBox::layoutAndPlaceChildren(FlexOrderIterator& iterator, cons
     bool shouldFlipMainAxis = !isColumnFlow() && !isLeftToRightFlow();
     size_t i = 0;
     for (RenderBox* child = iterator.first(); child; child = iterator.next(), ++i) {
+        if (child->isPositioned()) {
+            prepareChildForPositionedLayout(child, mainAxisOffset, crossAxisOffset);
+            mainAxisOffset += packingSpaceBetweenChildren(availableFreeSpace, totalPositiveFlexibility, style()->flexPack(), childSizes.size());
+            continue;
+        }
         LayoutUnit childPreferredSize = childSizes[i] + mainAxisBorderAndPaddingExtentForChild(child);
         setLogicalOverrideSize(child, childPreferredSize);
         child->setChildNeedsLayout(true);
@@ -657,6 +689,11 @@ void RenderFlexibleBox::layoutColumnReverse(FlexOrderIterator& iterator, const W
     LayoutUnit crossAxisOffset = flowAwareBorderBefore() + flowAwarePaddingBefore();
     size_t i = 0;
     for (RenderBox* child = iterator.first(); child; child = iterator.next(), ++i) {
+        if (child->isPositioned()) {
+            child->layer()->setStaticBlockPosition(mainAxisOffset);
+            mainAxisOffset -= packingSpaceBetweenChildren(availableFreeSpace, totalPositiveFlexibility, style()->flexPack(), childSizes.size());
+            continue;
+        }
         mainAxisOffset -= mainAxisExtentForChild(child) + flowAwareMarginEndForChild(child);
 
         LayoutRect oldRect = child->frameRect();
index fe0dfa2..fd8a311 100644 (file)
@@ -96,6 +96,7 @@ private:
     void computePreferredMainAxisExtent(bool relayoutChildren, TreeOrderIterator&, LayoutUnit&, float& totalPositiveFlexibility, float& totalNegativeFlexibility);
     bool runFreeSpaceAllocationAlgorithm(FlexOrderIterator&, LayoutUnit& availableFreeSpace, float& totalPositiveFlexibility, float& totalNegativeFlexibility, InflexibleFlexItemSize&, WTF::Vector<LayoutUnit>& childSizes);
     void setLogicalOverrideSize(RenderBox* child, LayoutUnit childPreferredSize);
+    void prepareChildForPositionedLayout(RenderBox* child, LayoutUnit mainAxisOffset, LayoutUnit crossAxisOffset);
     void layoutAndPlaceChildren(FlexOrderIterator&, const WTF::Vector<LayoutUnit>& childSizes, LayoutUnit availableFreeSpace, float totalPositiveFlexibility);
     void layoutColumnReverse(FlexOrderIterator&, const WTF::Vector<LayoutUnit>& childSizes, LayoutUnit availableFreeSpace, float totalPositiveFlexibility);
     void alignChildren(FlexOrderIterator&, LayoutUnit maxAscent);