Title: [127008] trunk/Source/WebCore
Revision
127008
Author
hy...@apple.com
Date
2012-08-29 10:09:12 -0700 (Wed, 29 Aug 2012)

Log Message

[New Multicolumn] Implement column contents painting.
https://bugs.webkit.org/show_bug.cgi?id=95251

Reviewed by Simon Fraser.

This patch implements paintColumnContents for the new multicolumn blocks. There are a number of
improvements made over the current multi-column implementation. They include the fact that left
and right columns will now be unclipped, so contents of columns can actually spill out of the block now.
Outlines now also work properly. The contents of the first column and last column can also now overflow
visually out of the top and bottom of those columns respectively.

* rendering/RenderMultiColumnSet.cpp:
(WebCore::RenderMultiColumnSet::flowThreadPortionRectAt):
This method returns the exact portion of the flow thread that matches the column dimensions.
The width and height are the column width and height. It is equivalent to RenderRegion::flowThreadPortionRect,
but is applied only for a specific column in the set.

(WebCore::RenderMultiColumnSet::flowThreadPortionOverflowRect):
This method expands the flowThreadPortionRect to unclip the edges of left and right columns, the top and
bottom edges of first and last columns, and it also expands the painting to go into half of the column
gap. It is analogous to RenderRegion::flowThreadPortionOverflowRect, but it's doing the right thing
for each individual column.

(WebCore::RenderMultiColumnSet::paintColumnContents):
The implementation of column contents painting. Each column is iterated over, and the two rects above
are computed and passed in to RenderFlowThread::paintFlowThreadPortionInRegion. This code does the right
thing with offsets and clipping when handed these two rects and handles all of the rest.

* rendering/RenderMultiColumnSet.h:
Declare the new functions that return the flow thread portion rects.

* rendering/RenderRegion.cpp:
(WebCore::RenderRegion::flowThreadPortionOverflowRect):
(WebCore):
(WebCore::RenderRegion::overflowRectForFlowThreadPortion):
* rendering/RenderRegion.h:
(RenderRegion):
* rendering/RenderRegionSet.cpp:
Refactor this so that it can be invoked by column sets and operate on the first and last columns instead
of only being tied to the first and last regions.

(WebCore::RenderRegionSet::expandToEncompassFlowThreadContentsIfNeeded):
Fix a bug here where the flowThread.y() should not have been subtracted. We're in local flow thread
coordinates.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (127007 => 127008)


--- trunk/Source/WebCore/ChangeLog	2012-08-29 16:46:11 UTC (rev 127007)
+++ trunk/Source/WebCore/ChangeLog	2012-08-29 17:09:12 UTC (rev 127008)
@@ -1,3 +1,50 @@
+2012-08-28  David Hyatt  <hy...@apple.com>
+
+        [New Multicolumn] Implement column contents painting.
+        https://bugs.webkit.org/show_bug.cgi?id=95251
+
+        Reviewed by Simon Fraser.
+
+        This patch implements paintColumnContents for the new multicolumn blocks. There are a number of
+        improvements made over the current multi-column implementation. They include the fact that left
+        and right columns will now be unclipped, so contents of columns can actually spill out of the block now.
+        Outlines now also work properly. The contents of the first column and last column can also now overflow
+        visually out of the top and bottom of those columns respectively.
+
+        * rendering/RenderMultiColumnSet.cpp:
+        (WebCore::RenderMultiColumnSet::flowThreadPortionRectAt):
+        This method returns the exact portion of the flow thread that matches the column dimensions.
+        The width and height are the column width and height. It is equivalent to RenderRegion::flowThreadPortionRect,
+        but is applied only for a specific column in the set.
+
+        (WebCore::RenderMultiColumnSet::flowThreadPortionOverflowRect):
+        This method expands the flowThreadPortionRect to unclip the edges of left and right columns, the top and
+        bottom edges of first and last columns, and it also expands the painting to go into half of the column
+        gap. It is analogous to RenderRegion::flowThreadPortionOverflowRect, but it's doing the right thing
+        for each individual column.
+
+        (WebCore::RenderMultiColumnSet::paintColumnContents):
+        The implementation of column contents painting. Each column is iterated over, and the two rects above
+        are computed and passed in to RenderFlowThread::paintFlowThreadPortionInRegion. This code does the right
+        thing with offsets and clipping when handed these two rects and handles all of the rest.
+
+        * rendering/RenderMultiColumnSet.h:
+        Declare the new functions that return the flow thread portion rects.
+
+        * rendering/RenderRegion.cpp:
+        (WebCore::RenderRegion::flowThreadPortionOverflowRect):
+        (WebCore):
+        (WebCore::RenderRegion::overflowRectForFlowThreadPortion):
+        * rendering/RenderRegion.h:
+        (RenderRegion):
+        * rendering/RenderRegionSet.cpp:
+        Refactor this so that it can be invoked by column sets and operate on the first and last columns instead
+        of only being tied to the first and last regions.
+
+        (WebCore::RenderRegionSet::expandToEncompassFlowThreadContentsIfNeeded):
+        Fix a bug here where the flowThread.y() should not have been subtracted. We're in local flow thread
+        coordinates.
+
 2012-08-29  Sheriff Bot  <webkit.review....@gmail.com>
 
         Unreviewed, rolling out r126972.

Modified: trunk/Source/WebCore/rendering/RenderMultiColumnSet.cpp (127007 => 127008)


--- trunk/Source/WebCore/rendering/RenderMultiColumnSet.cpp	2012-08-29 16:46:11 UTC (rev 127007)
+++ trunk/Source/WebCore/rendering/RenderMultiColumnSet.cpp	2012-08-29 17:09:12 UTC (rev 127008)
@@ -29,6 +29,9 @@
 #include "RenderMultiColumnSet.h"
 #include "RenderMultiColumnBlock.h"
 
+using std::min;
+using std::max;
+
 namespace WebCore {
 
 RenderMultiColumnSet::RenderMultiColumnSet(Node* node, RenderFlowThread* flowThread)
@@ -96,6 +99,65 @@
     return LayoutRect(colLogicalTop, colLogicalLeft, colLogicalHeight, colLogicalWidth);
 }
 
+LayoutRect RenderMultiColumnSet::flowThreadPortionRectAt(unsigned index) const
+{
+    LayoutRect portionRect = flowThreadPortionRect();
+    if (isHorizontalWritingMode())
+        portionRect = LayoutRect(portionRect.x(), portionRect.y() + index * computedColumnHeight(), portionRect.width(), computedColumnHeight());
+    else
+        portionRect = LayoutRect(portionRect.x() + index * computedColumnHeight(), portionRect.y(), computedColumnHeight(), portionRect.height());
+    return portionRect;
+}
+
+LayoutRect RenderMultiColumnSet::flowThreadPortionOverflowRect(const LayoutRect& portionRect, unsigned index, unsigned colCount, int colGap) const
+{
+    // This function determines the portion of the flow thread that paints for the column. Along the inline axis, columns are
+    // unclipped at outside edges (i.e., the first and last column in the set), and they clip to half the column
+    // gap along interior edges.
+    //
+    // In the block direction, we will not clip overflow out of the top of the first column, or out of the bottom of
+    // the last column. This applies only to the true first column and last column across all column sets.
+    //
+    // FIXME: Eventually we will know overflow on a per-column basis, but we can't do this until we have a painting
+    // mode that understands not to paint contents from a previous column in the overflow area of a following column.
+    // This problem applies to regions and pages as well and is not unique to columns.
+    bool isFirstColumn = !index;
+    bool isLastColumn = index == colCount - 1;
+    LayoutRect overflowRect(portionRect);
+    if (isHorizontalWritingMode()) {
+        if (isFirstColumn) {
+            // Shift to the logical left overflow of the flow thread to make sure it's all covered.
+            overflowRect.shiftXEdgeTo(min(flowThread()->visualOverflowRect().x(), portionRect.x()));
+        } else {
+            // Expand into half of the logical left column gap.
+            overflowRect.shiftXEdgeTo(portionRect.x() - colGap / 2);
+        }
+        if (isLastColumn) {
+            // Shift to the logical right overflow of the flow thread to ensure content can spill out of the column.
+            overflowRect.shiftMaxXEdgeTo(max(flowThread()->visualOverflowRect().maxX(), portionRect.maxX()));
+        } else {
+            // Expand into half of the logical right column gap.
+            overflowRect.shiftMaxXEdgeTo(portionRect.maxX() + colGap / 2);
+        }
+    } else {
+        if (isFirstColumn) {
+            // Shift to the logical left overflow of the flow thread to make sure it's all covered.
+            overflowRect.shiftYEdgeTo(min(flowThread()->visualOverflowRect().y(), portionRect.y()));
+        } else {
+            // Expand into half of the logical left column gap.
+            overflowRect.shiftYEdgeTo(portionRect.y() - colGap / 2);
+        }
+        if (isLastColumn) {
+            // Shift to the logical right overflow of the flow thread to ensure content can spill out of the column.
+            overflowRect.shiftMaxYEdgeTo(max(flowThread()->visualOverflowRect().maxY(), portionRect.maxY()));
+        } else {
+            // Expand into half of the logical right column gap.
+            overflowRect.shiftMaxYEdgeTo(portionRect.maxY() + colGap / 2);
+        }
+    }
+    return overflowRectForFlowThreadPortion(overflowRect, isFirstRegion() && isFirstColumn, isLastRegion() && isLastColumn);
+}
+
 void RenderMultiColumnSet::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
 {
     // FIXME: RenderRegions are replaced elements right now and so they only paint in the foreground phase.
@@ -164,7 +226,7 @@
     }
 }
 
-void RenderMultiColumnSet::paintColumnContents(PaintInfo& /*paintInfo*/, const LayoutPoint& /*paintOffset*/)
+void RenderMultiColumnSet::paintColumnContents(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
 {
     // For each rectangle, set it as the region rectangle and then let flow thread painting do the rest.
     // We make multiple calls to paintFlowThreadPortionInRegion, changing the rectangles each time.
@@ -172,7 +234,23 @@
     if (!colCount)
         return;
 
-    // FIXME: Implement.
+    LayoutUnit colGap = columnGap();
+    for (unsigned i = 0; i < colCount; i++) {
+        // First we get the column rect, which is in our local coordinate space, and we make it physical and apply
+        // the paint offset to it. That gives us the physical location that we want to paint the column at.
+        LayoutRect colRect = columnRectAt(i);
+        flipForWritingMode(colRect);
+        colRect.moveBy(paintOffset);
+        
+        // Next we get the portion of the flow thread that corresponds to this column.
+        LayoutRect flowThreadPortion = flowThreadPortionRectAt(i);
+        
+        // Now get the overflow rect that corresponds to the column.
+        LayoutRect flowThreadOverflowPortion = flowThreadPortionOverflowRect(flowThreadPortion, i, colCount, colGap);
+
+        // Do the paint with the computed rects.
+        flowThread()->paintFlowThreadPortionInRegion(paintInfo, this, flowThreadPortion, flowThreadOverflowPortion, colRect.location());
+    }
 }
 
 const char* RenderMultiColumnSet::renderName() const

Modified: trunk/Source/WebCore/rendering/RenderMultiColumnSet.h (127007 => 127008)


--- trunk/Source/WebCore/rendering/RenderMultiColumnSet.h	2012-08-29 16:46:11 UTC (rev 127007)
+++ trunk/Source/WebCore/rendering/RenderMultiColumnSet.h	2012-08-29 17:09:12 UTC (rev 127008)
@@ -79,6 +79,9 @@
     LayoutRect columnRectAt(unsigned index) const;
     unsigned columnCount() const;
 
+    LayoutRect flowThreadPortionRectAt(unsigned index) const;
+    LayoutRect flowThreadPortionOverflowRect(const LayoutRect& flowThreadPortion, unsigned index, unsigned colCount, int colGap) const;
+
     unsigned m_computedColumnCount;
     LayoutUnit m_computedColumnWidth;
     LayoutUnit m_computedColumnHeight;

Modified: trunk/Source/WebCore/rendering/RenderRegion.cpp (127007 => 127008)


--- trunk/Source/WebCore/rendering/RenderRegion.cpp	2012-08-29 16:46:11 UTC (rev 127007)
+++ trunk/Source/WebCore/rendering/RenderRegion.cpp	2012-08-29 17:09:12 UTC (rev 127008)
@@ -64,13 +64,18 @@
 
 LayoutRect RenderRegion::flowThreadPortionOverflowRect() const
 {
+    return overflowRectForFlowThreadPortion(flowThreadPortionRect(), isFirstRegion(), isLastRegion());
+}
+
+LayoutRect RenderRegion::overflowRectForFlowThreadPortion(LayoutRect flowThreadPortionRect, bool isFirstPortion, bool isLastPortion) const
+{
     // FIXME: Would like to just use hasOverflowClip() but we aren't a block yet. When RenderRegion is eliminated and
     // folded into RenderBlock, switch to hasOverflowClip().
     bool clipX = style()->overflowX() != OVISIBLE;
     bool clipY = style()->overflowY() != OVISIBLE;
-    bool isLastRegionWithRegionOverflowBreak = (isLastRegion() && (style()->regionOverflow() == BreakRegionOverflow));
+    bool isLastRegionWithRegionOverflowBreak = (isLastPortion && (style()->regionOverflow() == BreakRegionOverflow));
     if ((clipX && clipY) || !isValid() || !m_flowThread || isLastRegionWithRegionOverflowBreak)
-        return flowThreadPortionRect();
+        return flowThreadPortionRect;
 
     LayoutRect flowThreadOverflow = m_flowThread->visualOverflowRect();
 
@@ -78,16 +83,16 @@
     LayoutUnit outlineSize = maximalOutlineSize(PaintPhaseOutline);
     LayoutRect clipRect;
     if (m_flowThread->isHorizontalWritingMode()) {
-        LayoutUnit minY = isFirstRegion() ? (flowThreadOverflow.y() - outlineSize) : flowThreadPortionRect().y();
-        LayoutUnit maxY = isLastRegion() ? max(flowThreadPortionRect().maxY(), flowThreadOverflow.maxY()) + outlineSize : flowThreadPortionRect().maxY();
-        LayoutUnit minX = clipX ? flowThreadPortionRect().x() : (flowThreadOverflow.x() - outlineSize);
-        LayoutUnit maxX = clipX ? flowThreadPortionRect().maxX() : (flowThreadOverflow.maxX() + outlineSize);
+        LayoutUnit minY = isFirstPortion ? (flowThreadOverflow.y() - outlineSize) : flowThreadPortionRect.y();
+        LayoutUnit maxY = isLastPortion ? max(flowThreadPortionRect.maxY(), flowThreadOverflow.maxY()) + outlineSize : flowThreadPortionRect.maxY();
+        LayoutUnit minX = clipX ? flowThreadPortionRect.x() : (flowThreadOverflow.x() - outlineSize);
+        LayoutUnit maxX = clipX ? flowThreadPortionRect.maxX() : (flowThreadOverflow.maxX() + outlineSize);
         clipRect = LayoutRect(minX, minY, maxX - minX, maxY - minY);
     } else {
-        LayoutUnit minX = isFirstRegion() ? (flowThreadOverflow.x() - outlineSize) : flowThreadPortionRect().x();
-        LayoutUnit maxX = isLastRegion() ? max(flowThreadPortionRect().maxX(), flowThreadOverflow.maxX()) + outlineSize : flowThreadPortionRect().maxX();
-        LayoutUnit minY = clipY ? flowThreadPortionRect().y() : (flowThreadOverflow.y() - outlineSize);
-        LayoutUnit maxY = clipY ? flowThreadPortionRect().maxY() : (flowThreadOverflow.maxY() + outlineSize);
+        LayoutUnit minX = isFirstPortion ? (flowThreadOverflow.x() - outlineSize) : flowThreadPortionRect.x();
+        LayoutUnit maxX = isLastPortion ? max(flowThreadPortionRect.maxX(), flowThreadOverflow.maxX()) + outlineSize : flowThreadPortionRect.maxX();
+        LayoutUnit minY = clipY ? flowThreadPortionRect.y() : (flowThreadOverflow.y() - outlineSize);
+        LayoutUnit maxY = clipY ? flowThreadPortionRect.maxY() : (flowThreadOverflow.maxY() + outlineSize);
         clipRect = LayoutRect(minX, minY, maxX - minX, maxY - minY);
     }
 

Modified: trunk/Source/WebCore/rendering/RenderRegion.h (127007 => 127008)


--- trunk/Source/WebCore/rendering/RenderRegion.h	2012-08-29 16:46:11 UTC (rev 127007)
+++ trunk/Source/WebCore/rendering/RenderRegion.h	2012-08-29 17:09:12 UTC (rev 127008)
@@ -104,6 +104,8 @@
     void setRegionObjectsRegionStyle();
     void restoreRegionObjectsOriginalStyle();
 
+    LayoutRect overflowRectForFlowThreadPortion(LayoutRect flowThreadPortionRect, bool isFirstPortion, bool isLastPortion) const;
+
 private:
     virtual const char* renderName() const { return "RenderRegion"; }
 

Modified: trunk/Source/WebCore/rendering/RenderRegionSet.cpp (127007 => 127008)


--- trunk/Source/WebCore/rendering/RenderRegionSet.cpp	2012-08-29 16:46:11 UTC (rev 127007)
+++ trunk/Source/WebCore/rendering/RenderRegionSet.cpp	2012-08-29 17:09:12 UTC (rev 127008)
@@ -56,7 +56,7 @@
     bool isHorizontal = flowThread()->isHorizontalWritingMode();
     LayoutUnit logicalTopOffset = isHorizontal ? rect.y() : rect.x();
     LayoutRect layoutRect = flowThread()->layoutOverflowRect();
-    LayoutUnit logicalHeightWithOverflow = (isHorizontal ? layoutRect.maxY() - flowThread()->y() : layoutRect.maxX() - flowThread()->x()) - logicalTopOffset;
+    LayoutUnit logicalHeightWithOverflow = (isHorizontal ? layoutRect.maxY() : layoutRect.maxX()) - logicalTopOffset;
     setFlowThreadPortionRect(LayoutRect(rect.x(), rect.y(), isHorizontal ? rect.width() : logicalHeightWithOverflow, isHorizontal ? logicalHeightWithOverflow : rect.height()));
 }
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to