https://bugs.webkit.org/show_bug.cgi?id=46938
authorhyatt@apple.com <hyatt@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 30 Sep 2010 22:24:22 +0000 (22:24 +0000)
committerhyatt@apple.com <hyatt@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 30 Sep 2010 22:24:22 +0000 (22:24 +0000)
Reviewed by Sam Weinig.

Rewrite margin collapsing to be block-flow-aware.  Eliminate a bunch of the margin functions on RenderBox in favor of a single
master function for grabbing all the margin values for a child: marginValuesForChild on RenderBlock.  Introduce a new
MarginValues struct to make returning the collection of 4 margin values easy.

fast/blockflow/inline-direction-positioning.html progresses to have the correct results.
Added fast/blockflow/margin-collapse.html

WebCore:

* rendering/RenderBlock.cpp:
(WebCore::RenderBlock::MarginInfo::MarginInfo):
(WebCore::RenderBlock::adjustPositionedBlock):
(WebCore::RenderBlock::collapseMargins):
(WebCore::RenderBlock::clearFloatsIfNeeded):
(WebCore::RenderBlock::setCollapsedBottomMargin):
(WebCore::RenderBlock::layoutBlockChild):
(WebCore::RenderBlock::setMaxMarginBeforeValues):
(WebCore::RenderBlock::setMaxMarginAfterValues):
(WebCore::RenderBlock::marginValuesForChild):
* rendering/RenderBlock.h:
(WebCore::RenderBlock::MarginValues::MarginValues):
(WebCore::RenderBlock::MarginValues::positiveMarginBefore):
(WebCore::RenderBlock::MarginValues::negativeMarginBefore):
(WebCore::RenderBlock::MarginValues::positiveMarginAfter):
(WebCore::RenderBlock::MarginValues::negativeMarginAfter):
(WebCore::RenderBlock::MarginValues::setPositiveMarginBefore):
(WebCore::RenderBlock::MarginValues::setNegativeMarginBefore):
(WebCore::RenderBlock::MarginValues::setPositiveMarginAfter):
(WebCore::RenderBlock::MarginValues::setNegativeMarginAfter):
(WebCore::RenderBlock::maxPositiveMarginBefore):
(WebCore::RenderBlock::maxNegativeMarginBefore):
(WebCore::RenderBlock::maxPositiveMarginAfter):
(WebCore::RenderBlock::maxNegativeMarginAfter):
(WebCore::RenderBlock::initMaxMarginValues):
(WebCore::RenderBlock::collapsedMarginBefore):
(WebCore::RenderBlock::collapsedMarginAfter):
(WebCore::RenderBlock::MarginInfo::clearMargin):
(WebCore::RenderBlock::MarginInfo::setPositiveMargin):
(WebCore::RenderBlock::MarginInfo::setNegativeMargin):
(WebCore::RenderBlock::MarginInfo::setPositiveMarginIfLarger):
(WebCore::RenderBlock::MarginInfo::setNegativeMarginIfLarger):
(WebCore::RenderBlock::MarginInfo::setMargin):
(WebCore::RenderBlock::MarginInfo::positiveMargin):
(WebCore::RenderBlock::MarginInfo::negativeMargin):
(WebCore::RenderBlock::MarginInfo::margin):
(WebCore::RenderBlock::RenderBlockRareData::RenderBlockRareData):
(WebCore::RenderBlock::RenderBlockRareData::positiveMarginBeforeDefault):
(WebCore::RenderBlock::RenderBlockRareData::negativeMarginBeforeDefault):
(WebCore::RenderBlock::RenderBlockRareData::positiveMarginAfterDefault):
(WebCore::RenderBlock::RenderBlockRareData::negativeMarginAfterDefault):
* rendering/RenderBox.h:
(WebCore::RenderBox::collapsedMarginBefore):
(WebCore::RenderBox::collapsedMarginAfter):
* rendering/RenderFlexibleBox.cpp:
(WebCore::RenderFlexibleBox::layoutBlock):

LayoutTests:

* fast/blockflow/margin-collapse.html: Added.
* platform/mac/fast/blockflow/inline-direction-positioning-expected.checksum:
* platform/mac/fast/blockflow/inline-direction-positioning-expected.png:
* platform/mac/fast/blockflow/inline-direction-positioning-expected.txt:
* platform/mac/fast/blockflow/margin-collapse-expected.checksum: Added.
* platform/mac/fast/blockflow/margin-collapse-expected.png: Added.
* platform/mac/fast/blockflow/margin-collapse-expected.txt: Added.

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

14 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/blockflow/margin-collapse.html [new file with mode: 0644]
LayoutTests/platform/mac/fast/blockflow/inline-direction-positioning-expected.checksum
LayoutTests/platform/mac/fast/blockflow/inline-direction-positioning-expected.png
LayoutTests/platform/mac/fast/blockflow/inline-direction-positioning-expected.txt
LayoutTests/platform/mac/fast/blockflow/margin-collapse-expected.checksum [new file with mode: 0644]
LayoutTests/platform/mac/fast/blockflow/margin-collapse-expected.png [new file with mode: 0644]
LayoutTests/platform/mac/fast/blockflow/margin-collapse-expected.txt [new file with mode: 0644]
WebCore/ChangeLog
WebCore/WebCore.xcodeproj/project.pbxproj
WebCore/rendering/RenderBlock.cpp
WebCore/rendering/RenderBlock.h
WebCore/rendering/RenderBox.h
WebCore/rendering/RenderFlexibleBox.cpp

index 5fc12a2..0d8c08b 100644 (file)
@@ -1,3 +1,25 @@
+2010-09-30  David Hyatt  <hyatt@apple.com>
+
+        Reviewed by Sam Weinig.
+
+        https://bugs.webkit.org/show_bug.cgi?id=46938
+        
+        Rewrite margin collapsing to be block-flow-aware.  Eliminate a bunch of the margin functions on RenderBox in favor of a single
+        master function for grabbing all the margin values for a child: marginValuesForChild on RenderBlock.  Introduce a new
+        MarginValues struct to make returning the collection of 4 margin values easy.
+    
+        fast/blockflow/inline-direction-positioning.html progresses to have the correct results.
+        Added fast/blockflow/margin-collapse.html
+
+
+        * fast/blockflow/margin-collapse.html: Added.
+        * platform/mac/fast/blockflow/inline-direction-positioning-expected.checksum:
+        * platform/mac/fast/blockflow/inline-direction-positioning-expected.png:
+        * platform/mac/fast/blockflow/inline-direction-positioning-expected.txt:
+        * platform/mac/fast/blockflow/margin-collapse-expected.checksum: Added.
+        * platform/mac/fast/blockflow/margin-collapse-expected.png: Added.
+        * platform/mac/fast/blockflow/margin-collapse-expected.txt: Added.
+
 2010-09-30  Ryosuke Niwa  <rniwa@webkit.org>
 
         Unreviewed rebaseline for Qt and Windows platforms required by r68830.
diff --git a/LayoutTests/fast/blockflow/margin-collapse.html b/LayoutTests/fast/blockflow/margin-collapse.html
new file mode 100644 (file)
index 0000000..5d5e546
--- /dev/null
@@ -0,0 +1,14 @@
+<html>
+<head>
+<style>
+.block { width:100px; height:100px; margin:2em 1em; background-color:green }
+</style>
+<body>
+<div style="border:2px solid black">
+<div style="-webkit-block-flow:lr" class="block"></div>
+<div style="-webkit-block-flow:rl" class="block"></div>
+<div style="-webkit-block-flow:bt" class="block"></div>
+<div class="block"></div>
+</div>
+</body>
+</html>
index 00e44b3..08d3b00 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/blockflow/inline-direction-positioning-expected.png and b/LayoutTests/platform/mac/fast/blockflow/inline-direction-positioning-expected.png differ
index 60392c8..d4cfac8 100644 (file)
@@ -3,7 +3,7 @@ layer at (0,0) size 800x600
 layer at (0,0) size 800x600
   RenderBlock {HTML} at (0,0) size 800x600
     RenderBody {BODY} at (8,8) size 784x584
-      RenderBlock {DIV} at (0,0) size 604x154 [border: (2px solid #000000)]
-        RenderBlock {DIV} at (52,52) size 100x100 [bgcolor=#008000]
-      RenderBlock {DIV} at (0,154) size 604x154 [border: (2px solid #000000)]
+      RenderBlock {DIV} at (0,0) size 604x104 [border: (2px solid #000000)]
+        RenderBlock {DIV} at (52,2) size 100x100 [bgcolor=#008000]
+      RenderBlock {DIV} at (0,104) size 604x104 [border: (2px solid #000000)]
         RenderBlock {DIV} at (452,2) size 100x100 [bgcolor=#008000]
diff --git a/LayoutTests/platform/mac/fast/blockflow/margin-collapse-expected.checksum b/LayoutTests/platform/mac/fast/blockflow/margin-collapse-expected.checksum
new file mode 100644 (file)
index 0000000..7d07ea9
--- /dev/null
@@ -0,0 +1 @@
+d38b466d3716123c8d883c04d4ad8f5a
\ No newline at end of file
diff --git a/LayoutTests/platform/mac/fast/blockflow/margin-collapse-expected.png b/LayoutTests/platform/mac/fast/blockflow/margin-collapse-expected.png
new file mode 100644 (file)
index 0000000..921a42d
Binary files /dev/null and b/LayoutTests/platform/mac/fast/blockflow/margin-collapse-expected.png differ
diff --git a/LayoutTests/platform/mac/fast/blockflow/margin-collapse-expected.txt b/LayoutTests/platform/mac/fast/blockflow/margin-collapse-expected.txt
new file mode 100644 (file)
index 0000000..efc822c
--- /dev/null
@@ -0,0 +1,10 @@
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  RenderBlock {HTML} at (0,0) size 800x600
+    RenderBody {BODY} at (8,8) size 784x584
+      RenderBlock {DIV} at (0,0) size 784x564 [border: (2px solid #000000)]
+        RenderBlock {DIV} at (18,34) size 100x100 [bgcolor=#008000]
+        RenderBlock {DIV} at (18,166) size 100x100 [bgcolor=#008000]
+        RenderBlock {DIV} at (18,298) size 100x100 [bgcolor=#008000]
+        RenderBlock {DIV} at (18,430) size 100x100 [bgcolor=#008000]
index ec2b180..d84943d 100644 (file)
@@ -1,3 +1,63 @@
+2010-09-30  David Hyatt  <hyatt@apple.com>
+
+        Reviewed by Sam Weinig.
+
+        https://bugs.webkit.org/show_bug.cgi?id=46938
+        
+        Rewrite margin collapsing to be block-flow-aware.  Eliminate a bunch of the margin functions on RenderBox in favor of a single
+        master function for grabbing all the margin values for a child: marginValuesForChild on RenderBlock.  Introduce a new
+        MarginValues struct to make returning the collection of 4 margin values easy.
+    
+        fast/blockflow/inline-direction-positioning.html progresses to have the correct results.
+        Added fast/blockflow/margin-collapse.html
+
+        * rendering/RenderBlock.cpp:
+        (WebCore::RenderBlock::MarginInfo::MarginInfo):
+        (WebCore::RenderBlock::adjustPositionedBlock):
+        (WebCore::RenderBlock::collapseMargins):
+        (WebCore::RenderBlock::clearFloatsIfNeeded):
+        (WebCore::RenderBlock::setCollapsedBottomMargin):
+        (WebCore::RenderBlock::layoutBlockChild):
+        (WebCore::RenderBlock::setMaxMarginBeforeValues):
+        (WebCore::RenderBlock::setMaxMarginAfterValues):
+        (WebCore::RenderBlock::marginValuesForChild):
+        * rendering/RenderBlock.h:
+        (WebCore::RenderBlock::MarginValues::MarginValues):
+        (WebCore::RenderBlock::MarginValues::positiveMarginBefore):
+        (WebCore::RenderBlock::MarginValues::negativeMarginBefore):
+        (WebCore::RenderBlock::MarginValues::positiveMarginAfter):
+        (WebCore::RenderBlock::MarginValues::negativeMarginAfter):
+        (WebCore::RenderBlock::MarginValues::setPositiveMarginBefore):
+        (WebCore::RenderBlock::MarginValues::setNegativeMarginBefore):
+        (WebCore::RenderBlock::MarginValues::setPositiveMarginAfter):
+        (WebCore::RenderBlock::MarginValues::setNegativeMarginAfter):
+        (WebCore::RenderBlock::maxPositiveMarginBefore):
+        (WebCore::RenderBlock::maxNegativeMarginBefore):
+        (WebCore::RenderBlock::maxPositiveMarginAfter):
+        (WebCore::RenderBlock::maxNegativeMarginAfter):
+        (WebCore::RenderBlock::initMaxMarginValues):
+        (WebCore::RenderBlock::collapsedMarginBefore):
+        (WebCore::RenderBlock::collapsedMarginAfter):
+        (WebCore::RenderBlock::MarginInfo::clearMargin):
+        (WebCore::RenderBlock::MarginInfo::setPositiveMargin):
+        (WebCore::RenderBlock::MarginInfo::setNegativeMargin):
+        (WebCore::RenderBlock::MarginInfo::setPositiveMarginIfLarger):
+        (WebCore::RenderBlock::MarginInfo::setNegativeMarginIfLarger):
+        (WebCore::RenderBlock::MarginInfo::setMargin):
+        (WebCore::RenderBlock::MarginInfo::positiveMargin):
+        (WebCore::RenderBlock::MarginInfo::negativeMargin):
+        (WebCore::RenderBlock::MarginInfo::margin):
+        (WebCore::RenderBlock::RenderBlockRareData::RenderBlockRareData):
+        (WebCore::RenderBlock::RenderBlockRareData::positiveMarginBeforeDefault):
+        (WebCore::RenderBlock::RenderBlockRareData::negativeMarginBeforeDefault):
+        (WebCore::RenderBlock::RenderBlockRareData::positiveMarginAfterDefault):
+        (WebCore::RenderBlock::RenderBlockRareData::negativeMarginAfterDefault):
+        * rendering/RenderBox.h:
+        (WebCore::RenderBox::collapsedMarginBefore):
+        (WebCore::RenderBox::collapsedMarginAfter):
+        * rendering/RenderFlexibleBox.cpp:
+        (WebCore::RenderFlexibleBox::layoutBlock):
+
 2010-09-30  Patrick Gansterer  <paroga@webkit.org>
 
         Reviewed by Adam Roben.
index 5e3ea11..4da1d29 100644 (file)
                        isa = PBXProject;
                        buildConfigurationList = 149C284308902B11008A9EFC /* Build configuration list for PBXProject "WebCore" */;
                        compatibilityVersion = "Xcode 2.4";
-                       developmentRegion = English;
                        hasScannedForEncodings = 1;
                        knownRegions = (
                                English,
index b14cbda..7827326 100644 (file)
@@ -104,8 +104,8 @@ RenderBlock::MarginInfo::MarginInfo(RenderBlock* block, int beforeBorderPadding,
     m_quirkContainer = block->isTableCell() || block->isBody() || block->style()->marginBeforeCollapse() == MDISCARD || 
         block->style()->marginAfterCollapse() == MDISCARD;
 
-    m_posMargin = m_canCollapseMarginBeforeWithChildren ? block->maxMarginBefore(RenderBox::PositiveMargin) : 0;
-    m_negMargin = m_canCollapseMarginBeforeWithChildren ? block->maxMarginBefore(RenderBox::NegativeMargin) : 0;
+    m_positiveMargin = m_canCollapseMarginBeforeWithChildren ? block->maxPositiveMarginBefore() : 0;
+    m_negativeMargin = m_canCollapseMarginBeforeWithChildren ? block->maxNegativeMarginBefore() : 0;
 }
 
 // -------------------------------------------------------------------------------------------------------
@@ -1335,8 +1335,8 @@ void RenderBlock::adjustPositionedBlock(RenderBox* child, const MarginInfo& marg
         if (!marginInfo.canCollapseWithMarginBefore()) {
             child->computeBlockDirectionMargins(this);
             int marginTop = child->marginTop();
-            int collapsedTopPos = marginInfo.posMargin();
-            int collapsedTopNeg = marginInfo.negMargin();
+            int collapsedTopPos = marginInfo.positiveMargin();
+            int collapsedTopNeg = marginInfo.negativeMargin();
             if (marginTop > 0) {
                 if (marginTop > collapsedTopPos)
                     collapsedTopPos = marginTop;
@@ -1466,15 +1466,18 @@ bool RenderBlock::handleRunInChild(RenderBox* child)
 
 int RenderBlock::collapseMargins(RenderBox* child, MarginInfo& marginInfo)
 {
+    // Get the four margin values for the child and cache them.
+    const MarginValues childMargins = marginValuesForChild(child);
+
     // Get our max pos and neg top margins.
-    int posTop = child->maxMarginBefore(PositiveMargin);
-    int negTop = child->maxMarginBefore(NegativeMargin);
+    int posTop = childMargins.positiveMarginBefore();
+    int negTop = childMargins.negativeMarginBefore();
 
     // For self-collapsing blocks, collapse our bottom margins into our
     // top to get new posTop and negTop values.
     if (child->isSelfCollapsingBlock()) {
-        posTop = max(posTop, child->maxMarginAfter(PositiveMargin));
-        negTop = max(negTop, child->maxMarginAfter(NegativeMargin));
+        posTop = max(posTop, childMargins.positiveMarginAfter());
+        negTop = max(negTop, childMargins.negativeMarginAfter());
     }
     
     // See if the top margin is quirky. We only care if this child has
@@ -1486,18 +1489,18 @@ int RenderBlock::collapseMargins(RenderBox* child, MarginInfo& marginInfo)
         // block.  If it has larger margin values, then we need to update
         // our own maximal values.
         if (!document()->inQuirksMode() || !marginInfo.quirkContainer() || !topQuirk)
-            setMaxMarginBeforeValues(max(posTop, maxPosMarginBefore()), max(negTop, maxNegMarginBefore()));
+            setMaxMarginBeforeValues(max(posTop, maxPositiveMarginBefore()), max(negTop, maxNegativeMarginBefore()));
 
         // The minute any of the margins involved isn't a quirk, don't
         // collapse it away, even if the margin is smaller (www.webreference.com
         // has an example of this, a <dt> with 0.8em author-specified inside
         // a <dl> inside a <td>.
-        if (!marginInfo.determinedMarginBeforeQuirk() && !topQuirk && (posTop-negTop)) {
+        if (!marginInfo.determinedMarginBeforeQuirk() && !topQuirk && (posTop - negTop)) {
             setMarginBeforeQuirk(false);
             marginInfo.setDeterminedMarginBeforeQuirk(true);
         }
 
-        if (!marginInfo.determinedMarginBeforeQuirk() && topQuirk && marginTop() == 0)
+        if (!marginInfo.determinedMarginBeforeQuirk() && topQuirk && !marginBefore())
             // We have no top margin and our top child has a quirky margin.
             // We will pick up this quirky margin and pass it through.
             // This deals with the <td><div><p> case.
@@ -1509,44 +1512,44 @@ int RenderBlock::collapseMargins(RenderBox* child, MarginInfo& marginInfo)
     if (marginInfo.quirkContainer() && marginInfo.atBeforeSideOfBlock() && (posTop - negTop))
         marginInfo.setMarginBeforeQuirk(topQuirk);
 
-    int beforeCollapseY = logicalHeight();
-    int ypos = beforeCollapseY;
+    int beforeCollapseLogicalTop = logicalHeight();
+    int logicalTop = beforeCollapseLogicalTop;
     if (child->isSelfCollapsingBlock()) {
         // This child has no height.  We need to compute our
         // position before we collapse the child's margins together,
         // so that we can get an accurate position for the zero-height block.
-        int collapsedTopPos = max(marginInfo.posMargin(), child->maxMarginBefore(PositiveMargin));
-        int collapsedTopNeg = max(marginInfo.negMargin(), child->maxMarginBefore(NegativeMargin));
-        marginInfo.setMargin(collapsedTopPos, collapsedTopNeg);
+        int collapsedBeforePos = max(marginInfo.positiveMargin(), childMargins.positiveMarginBefore());
+        int collapsedBeforeNeg = max(marginInfo.negativeMargin(), childMargins.negativeMarginBefore());
+        marginInfo.setMargin(collapsedBeforePos, collapsedBeforeNeg);
         
         // Now collapse the child's margins together, which means examining our
         // bottom margin values as well. 
-        marginInfo.setPosMarginIfLarger(child->maxMarginAfter(PositiveMargin));
-        marginInfo.setNegMarginIfLarger(child->maxMarginAfter(NegativeMargin));
+        marginInfo.setPositiveMarginIfLarger(childMargins.positiveMarginAfter());
+        marginInfo.setNegativeMarginIfLarger(childMargins.negativeMarginAfter());
 
         if (!marginInfo.canCollapseWithMarginBefore())
             // We need to make sure that the position of the self-collapsing block
             // is correct, since it could have overflowing content
             // that needs to be positioned correctly (e.g., a block that
             // had a specified height of 0 but that actually had subcontent).
-            ypos = logicalHeight() + collapsedTopPos - collapsedTopNeg;
+            logicalTop = logicalHeight() + collapsedBeforePos - collapsedBeforeNeg;
     }
     else {
         if (child->style()->marginBeforeCollapse() == MSEPARATE) {
-            setLogicalHeight(logicalHeight() + marginInfo.margin() + child->marginTop());
-            ypos = logicalHeight();
+            setLogicalHeight(logicalHeight() + marginInfo.margin() + marginBeforeForChild(child));
+            logicalTop = logicalHeight();
         }
         else if (!marginInfo.atBeforeSideOfBlock() ||
             (!marginInfo.canCollapseMarginBeforeWithChildren()
              && (!document()->inQuirksMode() || !marginInfo.quirkContainer() || !marginInfo.marginBeforeQuirk()))) {
             // We're collapsing with a previous sibling's margins and not
             // with the top of the block.
-            setLogicalHeight(logicalHeight() + max(marginInfo.posMargin(), posTop) - max(marginInfo.negMargin(), negTop));
-            ypos = logicalHeight();
+            setLogicalHeight(logicalHeight() + max(marginInfo.positiveMargin(), posTop) - max(marginInfo.negativeMargin(), negTop));
+            logicalTop = logicalHeight();
         }
 
-        marginInfo.setPosMargin(child->maxMarginAfter(PositiveMargin));
-        marginInfo.setNegMargin(child->maxMarginAfter(NegativeMargin));
+        marginInfo.setPositiveMargin(childMargins.positiveMarginAfter());
+        marginInfo.setNegativeMargin(childMargins.negativeMarginAfter());
 
         if (marginInfo.margin())
             marginInfo.setMarginAfterQuirk(child->isMarginAfterQuirk() || style()->marginAfterCollapse() == MDISCARD);
@@ -1555,12 +1558,12 @@ int RenderBlock::collapseMargins(RenderBox* child, MarginInfo& marginInfo)
     // If margins would pull us past the top of the next page, then we need to pull back and pretend like the margins
     // collapsed into the page edge.
     bool paginated = view()->layoutState()->isPaginated();
-    if (paginated && ypos > beforeCollapseY) {
-        int oldY = ypos;
-        ypos = min(ypos, nextPageTop(beforeCollapseY));
-        setLogicalHeight(logicalHeight() + (ypos - oldY));
+    if (paginated && logicalTop > beforeCollapseLogicalTop) {
+        int oldLogicalTop = logicalTop;
+        logicalTop = min(logicalTop, nextPageTop(beforeCollapseLogicalTop));
+        setLogicalHeight(logicalHeight() + (logicalTop - oldLogicalTop));
     }
-    return ypos;
+    return logicalTop;
 }
 
 int RenderBlock::clearFloatsIfNeeded(RenderBox* child, MarginInfo& marginInfo, int oldTopPosMargin, int oldTopNegMargin, int yPos)
@@ -1582,12 +1585,14 @@ int RenderBlock::clearFloatsIfNeeded(RenderBox* child, MarginInfo& marginInfo, i
             if (!curr->isFloatingOrPositioned())
                 atBottomOfBlock = false;
         }
+        
+        MarginValues childMargins = marginValuesForChild(child);
         if (atBottomOfBlock) {
-            marginInfo.setPosMargin(child->maxMarginAfter(PositiveMargin));
-            marginInfo.setNegMargin(child->maxMarginAfter(NegativeMargin));
+            marginInfo.setPositiveMargin(childMargins.positiveMarginAfter());
+            marginInfo.setNegativeMargin(childMargins.negativeMarginAfter());
         } else {
-            marginInfo.setPosMargin(max(child->maxMarginBefore(PositiveMargin), child->maxMarginAfter(PositiveMargin)));
-            marginInfo.setNegMargin(max(child->maxMarginBefore(NegativeMargin), child->maxMarginAfter(NegativeMargin)));
+            marginInfo.setPositiveMargin(max(childMargins.positiveMarginBefore(), childMargins.positiveMarginAfter()));
+            marginInfo.setNegativeMargin(max(childMargins.negativeMarginBefore(), childMargins.negativeMarginAfter()));
         }
         
         // Adjust our height such that we are ready to be collapsed with subsequent siblings (or the bottom
@@ -1679,7 +1684,7 @@ void RenderBlock::setCollapsedBottomMargin(const MarginInfo& marginInfo)
     if (marginInfo.canCollapseWithMarginAfter() && !marginInfo.canCollapseWithMarginBefore()) {
         // Update our max pos/neg bottom margins, since we collapsed our bottom margins
         // with our children.
-        setMaxMarginAfterValues(max(maxPosMarginAfter(), marginInfo.posMargin()), max(maxNegMarginAfter(), marginInfo.negMargin()));
+        setMaxMarginAfterValues(max(maxPositiveMarginAfter(), marginInfo.positiveMargin()), max(maxNegativeMarginAfter(), marginInfo.negativeMargin()));
 
         if (!marginInfo.marginAfterQuirk())
             setMarginAfterQuirk(false);
@@ -1806,8 +1811,8 @@ void RenderBlock::layoutBlockChildren(bool relayoutChildren, int& maxFloatBottom
 
 void RenderBlock::layoutBlockChild(RenderBox* child, MarginInfo& marginInfo, int& previousFloatBottom, int& maxFloatBottom)
 {
-    int oldPosMarginBefore = maxPosMarginBefore();
-    int oldNegMarginBefore = maxNegMarginBefore();
+    int oldPosMarginBefore = maxPositiveMarginBefore();
+    int oldNegMarginBefore = maxNegativeMarginBefore();
 
     // The child is a normal flow object.  Compute the margins we will use for collapsing now.
     child->computeBlockDirectionMargins(this);
@@ -5584,23 +5589,23 @@ void RenderBlock::clearTruncation()
 void RenderBlock::setMaxMarginBeforeValues(int pos, int neg)
 {
     if (!m_rareData) {
-        if (pos == RenderBlockRareData::beforePosDefault(this) && neg == RenderBlockRareData::beforeNegDefault(this))
+        if (pos == RenderBlockRareData::positiveMarginBeforeDefault(this) && neg == RenderBlockRareData::negativeMarginBeforeDefault(this))
             return;
         m_rareData = new RenderBlockRareData(this);
     }
-    m_rareData->m_beforePos = pos;
-    m_rareData->m_beforeNeg = neg;
+    m_rareData->m_margins.setPositiveMarginBefore(pos);
+    m_rareData->m_margins.setNegativeMarginBefore(neg);
 }
 
 void RenderBlock::setMaxMarginAfterValues(int pos, int neg)
 {
     if (!m_rareData) {
-        if (pos == RenderBlockRareData::afterPosDefault(this) && neg == RenderBlockRareData::afterNegDefault(this))
+        if (pos == RenderBlockRareData::positiveMarginAfterDefault(this) && neg == RenderBlockRareData::negativeMarginAfterDefault(this))
             return;
         m_rareData = new RenderBlockRareData(this);
     }
-    m_rareData->m_afterPos = pos;
-    m_rareData->m_afterNeg = neg;
+    m_rareData->m_margins.setPositiveMarginAfter(pos);
+    m_rareData->m_margins.setNegativeMarginAfter(neg);
 }
 
 void RenderBlock::setPaginationStrut(int strut)
@@ -6146,6 +6151,66 @@ void RenderBlock::setMarginAfterForChild(RenderBox* child, int margin)
     }
 }
 
+RenderBlock::MarginValues RenderBlock::marginValuesForChild(RenderBox* child)
+{
+    int childBeforePositive = 0;
+    int childBeforeNegative = 0;
+    int childAfterPositive = 0;
+    int childAfterNegative = 0;
+
+    int beforeMargin = 0;
+    int afterMargin = 0;
+
+    RenderBlock* childRenderBlock = child->isRenderBlock() ? toRenderBlock(child) : 0;
+    
+    // If the child has the same directionality as we do, then we can just return its
+    // margins in the same direction.
+    if (!child->isBlockFlowRoot()) {
+        if (childRenderBlock) {
+            childBeforePositive = childRenderBlock->maxPositiveMarginBefore();
+            childBeforeNegative = childRenderBlock->maxNegativeMarginBefore();
+            childAfterPositive = childRenderBlock->maxPositiveMarginAfter();
+            childAfterNegative = childRenderBlock->maxNegativeMarginAfter();
+        } else {
+            beforeMargin = child->marginBefore();
+            afterMargin = child->marginAfter();
+        }
+    } else if (child->style()->isVerticalBlockFlow() == style()->isVerticalBlockFlow()) {
+        // The child has a different directionality.  If the child is parallel, then it's just
+        // flipped relative to us.  We can use the margins for the opposite edges.
+        if (childRenderBlock) {
+            childBeforePositive = childRenderBlock->maxPositiveMarginAfter();
+            childBeforeNegative = childRenderBlock->maxNegativeMarginAfter();
+            childAfterPositive = childRenderBlock->maxPositiveMarginBefore();
+            childAfterNegative = childRenderBlock->maxNegativeMarginBefore();
+        } else {
+            beforeMargin = child->marginAfter();
+            afterMargin = child->marginBefore();
+        }
+    } else {
+        // The child is perpendicular to us, which means its margins don't collapse but are on the
+        // "logical left/right" sides of the child box.  We can just return the raw margin in this case.
+        beforeMargin = marginBeforeForChild(child);
+        afterMargin = marginAfterForChild(child);
+    }
+
+    // Resolve uncollapsing margins into their positive/negative buckets.
+    if (beforeMargin) {
+        if (beforeMargin > 0)
+            childBeforePositive = beforeMargin;
+        else
+            childBeforeNegative = -beforeMargin;
+    }
+    if (afterMargin) {
+        if (afterMargin > 0)
+            childAfterPositive = afterMargin;
+        else
+            childAfterNegative = -afterMargin;
+    }
+
+    return MarginValues(childBeforePositive, childBeforeNegative, childAfterPositive, childAfterNegative);
+}
+
 const char* RenderBlock::renderName() const
 {
     if (isBody())
index 752dc73..6c6829f 100644 (file)
@@ -185,6 +185,33 @@ public:
     void setMarginAfterForChild(RenderBox* child, int);
     int collapsedMarginBeforeForChild(RenderBox* child) const;
     int collapsedMarginAfterForChild(RenderBox* child) const;
+    
+    class MarginValues {
+    public:
+        MarginValues(int beforePos, int beforeNeg, int afterPos, int afterNeg)
+            : m_positiveMarginBefore(beforePos)
+            , m_negativeMarginBefore(beforeNeg)
+            , m_positiveMarginAfter(afterPos)
+            , m_negativeMarginAfter(afterNeg)
+        { }
+        
+        int positiveMarginBefore() const { return m_positiveMarginBefore; }
+        int negativeMarginBefore() const { return m_negativeMarginBefore; }
+        int positiveMarginAfter() const { return m_positiveMarginAfter; }
+        int negativeMarginAfter() const { return m_negativeMarginAfter; }
+        
+        void setPositiveMarginBefore(int pos) { m_positiveMarginBefore = pos; }
+        void setNegativeMarginBefore(int neg) { m_negativeMarginBefore = neg; }
+        void setPositiveMarginAfter(int pos) { m_positiveMarginAfter = pos; }
+        void setNegativeMarginAfter(int neg) { m_negativeMarginAfter = neg; }
+    
+    private:
+        int m_positiveMarginBefore;
+        int m_negativeMarginBefore;
+        int m_positiveMarginAfter;
+        int m_negativeMarginAfter;
+    };
+    MarginValues marginValuesForChild(RenderBox* child);
 
 protected:
     // These functions are only used internally to manipulate the render tree structure via remove/insert/appendChildNode.
@@ -211,10 +238,10 @@ protected:
     }
     void moveChildrenTo(RenderBlock* to, RenderObject* startChild, RenderObject* endChild, RenderObject* beforeChild, bool fullRemoveInsert = false);
     
-    int maxPosMarginBefore() const { return m_rareData ? m_rareData->m_beforePos : RenderBlockRareData::beforePosDefault(this); }
-    int maxNegMarginBefore() const { return m_rareData ? m_rareData->m_beforeNeg : RenderBlockRareData::beforeNegDefault(this); }
-    int maxPosMarginAfter() const { return m_rareData ? m_rareData->m_afterPos : RenderBlockRareData::afterPosDefault(this); }
-    int maxNegMarginAfter() const { return m_rareData ? m_rareData->m_afterNeg : RenderBlockRareData::afterNegDefault(this); }
+    int maxPositiveMarginBefore() const { return m_rareData ? m_rareData->m_margins.positiveMarginBefore() : RenderBlockRareData::positiveMarginBeforeDefault(this); }
+    int maxNegativeMarginBefore() const { return m_rareData ? m_rareData->m_margins.negativeMarginBefore() : RenderBlockRareData::negativeMarginBeforeDefault(this); }
+    int maxPositiveMarginAfter() const { return m_rareData ? m_rareData->m_margins.positiveMarginAfter() : RenderBlockRareData::positiveMarginAfterDefault(this); }
+    int maxNegativeMarginAfter() const { return m_rareData ? m_rareData->m_margins.negativeMarginAfter() : RenderBlockRareData::negativeMarginAfterDefault(this); }
     
     void setMaxMarginBeforeValues(int pos, int neg);
     void setMaxMarginAfterValues(int pos, int neg);
@@ -222,10 +249,8 @@ protected:
     void initMaxMarginValues()
     {
         if (m_rareData) {
-            m_rareData->m_beforePos = RenderBlockRareData::beforePosDefault(this);
-            m_rareData->m_beforeNeg = RenderBlockRareData::beforeNegDefault(this);
-            m_rareData->m_afterPos = RenderBlockRareData::afterPosDefault(this);
-            m_rareData->m_afterNeg = RenderBlockRareData::afterNegDefault(this);
+            m_rareData->m_margins = MarginValues(RenderBlockRareData::positiveMarginBeforeDefault(this) , RenderBlockRareData::negativeMarginBeforeDefault(this),
+                                                 RenderBlockRareData::positiveMarginAfterDefault(this), RenderBlockRareData::negativeMarginAfterDefault(this));
             m_rareData->m_paginationStrut = 0;
         }
     }
@@ -301,14 +326,8 @@ private:
     
     virtual bool isSelfCollapsingBlock() const;
 
-    virtual int maxMarginBefore(MarginSign sign) const
-    { 
-        return (sign == PositiveMargin) ? maxPosMarginBefore() : maxNegMarginBefore();
-    }
-    virtual int maxMarginAfter(MarginSign sign) const
-    {
-        return (sign == PositiveMargin) ? maxPosMarginAfter() : maxNegMarginAfter();
-    }
+    virtual int collapsedMarginBefore() const { return maxPositiveMarginBefore() - maxNegativeMarginBefore(); }
+    virtual int collapsedMarginAfter() const { return maxPositiveMarginAfter() - maxNegativeMarginAfter(); }
 
     virtual void repaintOverhangingFloats(bool paintAllDescendants);
 
@@ -541,24 +560,24 @@ private:
         bool m_determinedMarginBeforeQuirk : 1;
 
         // These flags track the previous maximal positive and negative margins.
-        int m_posMargin;
-        int m_negMargin;
+        int m_positiveMargin;
+        int m_negativeMargin;
 
     public:
         MarginInfo(RenderBlock* b, int beforeBorderPadding, int afterBorderPadding);
 
         void setAtBeforeSideOfBlock(bool b) { m_atBeforeSideOfBlock = b; }
         void setAtAfterSideOfBlock(bool b) { m_atAfterSideOfBlock = b; }
-        void clearMargin() { m_posMargin = m_negMargin = 0; }
+        void clearMargin() { m_positiveMargin = m_negativeMargin = 0; }
         void setMarginBeforeQuirk(bool b) { m_marginBeforeQuirk = b; }
         void setMarginAfterQuirk(bool b) { m_marginAfterQuirk = b; }
         void setDeterminedMarginBeforeQuirk(bool b) { m_determinedMarginBeforeQuirk = b; }
-        void setPosMargin(int p) { m_posMargin = p; }
-        void setNegMargin(int n) { m_negMargin = n; }
-        void setPosMarginIfLarger(int p) { if (p > m_posMargin) m_posMargin = p; }
-        void setNegMarginIfLarger(int n) { if (n > m_negMargin) m_negMargin = n; }
+        void setPositiveMargin(int p) { m_positiveMargin = p; }
+        void setNegativeMargin(int n) { m_negativeMargin = n; }
+        void setPositiveMarginIfLarger(int p) { if (p > m_positiveMargin) m_positiveMargin = p; }
+        void setNegativeMarginIfLarger(int n) { if (n > m_negativeMargin) m_negativeMargin = n; }
 
-        void setMargin(int p, int n) { m_posMargin = p; m_negMargin = n; }
+        void setMargin(int p, int n) { m_positiveMargin = p; m_negativeMargin = n; }
 
         bool atBeforeSideOfBlock() const { return m_atBeforeSideOfBlock; }
         bool canCollapseWithMarginBefore() const { return m_atBeforeSideOfBlock && m_canCollapseMarginBeforeWithChildren; }
@@ -569,9 +588,9 @@ private:
         bool determinedMarginBeforeQuirk() const { return m_determinedMarginBeforeQuirk; }
         bool marginBeforeQuirk() const { return m_marginBeforeQuirk; }
         bool marginAfterQuirk() const { return m_marginAfterQuirk; }
-        int posMargin() const { return m_posMargin; }
-        int negMargin() const { return m_negMargin; }
-        int margin() const { return m_posMargin - m_negMargin; }
+        int positiveMargin() const { return m_positiveMargin; }
+        int negativeMargin() const { return m_negativeMargin; }
+        int margin() const { return m_positiveMargin - m_negativeMargin; }
     };
 
     void layoutBlockChild(RenderBox* child, MarginInfo&, int& previousFloatBottom, int& maxFloatBottom);
@@ -606,41 +625,35 @@ private:
     // split into a sequence of inlines and blocks.  The continuation will either be
     // an anonymous block (that houses other blocks) or it will be an inline flow.
     RenderBoxModelObject* m_continuation;
-
+    
     // Allocated only when some of these fields have non-default values
     struct RenderBlockRareData : Noncopyable {
         RenderBlockRareData(const RenderBlock* block) 
-            : m_beforePos(beforePosDefault(block))
-            , m_beforeNeg(beforeNegDefault(block))
-            , m_afterPos(afterPosDefault(block))
-            , m_afterNeg(afterNegDefault(block))
+            : m_margins(positiveMarginBeforeDefault(block), negativeMarginBeforeDefault(block), positiveMarginAfterDefault(block), negativeMarginAfterDefault(block))
             , m_paginationStrut(0)
             , m_pageY(0)
         { 
         }
 
-        static int beforePosDefault(const RenderBlock* block)
+        static int positiveMarginBeforeDefault(const RenderBlock* block)
         { 
             return std::max(block->marginBefore(), 0);
         }
         
-        static int beforeNegDefault(const RenderBlock* block)
+        static int negativeMarginBeforeDefault(const RenderBlock* block)
         { 
             return std::max(-block->marginBefore(), 0);
         }
-        static int afterPosDefault(const RenderBlock* block)
+        static int positiveMarginAfterDefault(const RenderBlock* block)
         {
             return std::max(block->marginAfter(), 0);
         }
-        static int afterNegDefault(const RenderBlock* block)
+        static int negativeMarginAfterDefault(const RenderBlock* block)
         {
             return std::max(-block->marginAfter(), 0);
         }
         
-        int m_beforePos;
-        int m_beforeNeg;
-        int m_afterPos;
-        int m_afterNeg;
+        MarginValues m_margins;
         int m_paginationStrut;
         int m_pageY;
      };
index 9a69741..f964bc3 100644 (file)
@@ -202,24 +202,8 @@ public:
     // methods.
     enum MarginSign { PositiveMargin, NegativeMargin };
     virtual bool isSelfCollapsingBlock() const { return false; }
-    int collapsedMarginBefore() const
-    {
-        return maxMarginBefore(PositiveMargin) - maxMarginBefore(NegativeMargin);
-    }
-    int collapsedMarginAfter() const
-    { 
-        return maxMarginAfter(PositiveMargin) - maxMarginAfter(NegativeMargin);
-}
-    virtual int maxMarginBefore(MarginSign sign) const
-    { 
-        int beforeMargin = marginBefore();
-        return (sign == PositiveMargin) ? std::max(0, beforeMargin) : -std::min(0, beforeMargin);
-    }
-    virtual int maxMarginAfter(MarginSign sign) const
-    {
-        int afterMargin = marginAfter();
-        return (sign == PositiveMargin) ? std::max(0, afterMargin) : -std::min(0, afterMargin);
-    }
+    virtual int collapsedMarginBefore() const { return marginBefore(); }
+    virtual int collapsedMarginAfter() const { return marginAfter(); }
 
     virtual void absoluteRects(Vector<IntRect>&, int tx, int ty);
     virtual void absoluteQuads(Vector<FloatQuad>&);
index 1c303d6..843b971 100644 (file)
@@ -258,12 +258,12 @@ void RenderFlexibleBox::layoutBlock(bool relayoutChildren, int /*pageHeight FIXM
         // bottom margin max values to 0.  This way we don't factor in the values
         // twice when we collapse with our previous vertically adjacent and
         // following vertically adjacent blocks.
-        int pos = maxPosMarginBefore();
-        int neg = maxNegMarginBefore();
-        if (maxPosMarginAfter() > pos)
-            pos = maxPosMarginAfter();
-        if (maxNegMarginAfter() > neg)
-            neg = maxNegMarginAfter();
+        int pos = maxPositiveMarginBefore();
+        int neg = maxNegativeMarginBefore();
+        if (maxPositiveMarginAfter() > pos)
+            pos = maxPositiveMarginAfter();
+        if (maxNegativeMarginAfter() > neg)
+            neg = maxNegativeMarginAfter();
         setMaxMarginBeforeValues(pos, neg);
         setMaxMarginAfterValues(0, 0);
     }