Diff
Modified: trunk/Source/WebCore/ChangeLog (127266 => 127267)
--- trunk/Source/WebCore/ChangeLog 2012-08-31 15:40:14 UTC (rev 127266)
+++ trunk/Source/WebCore/ChangeLog 2012-08-31 15:47:04 UTC (rev 127267)
@@ -1,3 +1,97 @@
+2012-08-30 David Hyatt <[email protected]>
+
+ [New Multicolumn] Implement unforced breaking in the new column layout.
+ https://bugs.webkit.org/show_bug.cgi?id=95498
+
+ Reviewed by Dan Bernstein.
+
+ This patch implements unforced breaking for lines and objects inside columns. Forced breaks are
+ not yet handled properly and will be covered in a separate patch.
+
+ * rendering/LayoutState.cpp:
+ (WebCore::LayoutState::LayoutState):
+ Eliminate the flow thread constructor for LayoutState. Flow threads were doing a double push of
+ layout states, once in RenderFlowThread::layout() and then again in RenderBlock::layout(). This
+ double push was unnecessary, so I refactored the code to ensure the RenderBlock push does the
+ right thing for RenderFlowThreads.
+
+ (WebCore):
+ * rendering/LayoutState.h:
+ (LayoutState):
+ Eliminate the flow thread constructor for LayoutState.
+
+ * rendering/RenderBlock.cpp:
+ (WebCore::RenderBlock::checkForPaginationLogicalHeightChange):
+ This function now handles RenderFlowThreads and properly sets a non-zero page height as well
+ as querying the flow thread to ask if the pagination logical height has changed. The flow thread
+ has a new member that it sets in layout() so that it can answer this question.
+
+ (WebCore::RenderBlock::hasNextPage):
+ Make sure RenderRegionSets always claim to have a next page when they are the last region, since
+ we know columns/pages can always generate additional boxes as needed.
+
+ * rendering/RenderFlowThread.cpp:
+ (WebCore::RenderFlowThread::RenderFlowThread):
+ Add the m_pageLogicalHeightChanged member variable for tracking whether regions changed dimensions,
+ thus forcing us to repaginate everything.
+
+ (WebCore::RenderFlowThread::layout):
+ Remove the redundant push of layout state now that RenderBlock's covers it.
+
+ (WebCore::RenderFlowThread::regionAtBlockOffset):
+ Always return the last region if it's a set, regardless of the extendLastRegion boolean.
+ This reflects the fact that the last region set can always generate new page/column boxes.
+
+ (WebCore::RenderFlowThread::pageLogicalTopForOffset):
+ Refactored to call into the region it finds for a given offset, so that the region itself
+ can answer the question of where the top of the page is. This enables sets to return the top of
+ specific columns/pages within the set.
+
+ (WebCore::RenderFlowThread::pageRemainingLogicalHeightForOffset):
+ Changed to be written in terms of pageLogicalTop and pageLogicalHeight so that it correctly uses
+ only the current column/page when determining remaining height.
+
+ * rendering/RenderFlowThread.h:
+ Added pageLogicalHeightChanged() so that RenderBlock can ask the flow thread if its regions changed
+ dimensions.
+
+ * rendering/RenderMultiColumnBlock.cpp:
+ (WebCore::RenderMultiColumnBlock::checkForPaginationLogicalHeightChange):
+ Tweaked to no longer turn on pagination, since the RenderMultiColumnFlowThread does that and we
+ want to avoid a double push of paginated states. Instead it now just sets the column height ahead
+ of time so that the RenderMultiColumnSets know how big their columns are.
+
+ * rendering/RenderMultiColumnSet.cpp:
+ (WebCore::RenderMultiColumnSet::pageLogicalTopForOffset):
+ Subclassed to return the top of a specific column.
+
+ (WebCore):
+ * rendering/RenderMultiColumnSet.h:
+ Add the subclassed method for pageLogicalTopForOffset.
+
+ * rendering/RenderRegion.cpp:
+ (WebCore::RenderRegion::pageLogicalTopForOffset):
+ The code from RenderFlow::pageLogicalTopForOffset moved here. Just returns the top of the flow
+ thread portion rect in the region (same as before).
+
+ (WebCore::RenderRegion::layout):
+ Changed to check only the page logical width and height, since we only consider a region as
+ invalidating how you break if there is an actual page height change.
+
+ * rendering/RenderRegion.h:
+ (WebCore::RenderRegion::isRenderRegionSet):
+ Added an isRenderRegionSet() virtual function so that we can test for sets.
+
+ * rendering/RenderRegionSet.h:
+ (WebCore::RenderRegionSet::isRenderRegionSet):
+ Subclassed isRenderRegionSet() to return true.
+
+ * rendering/RenderView.cpp:
+ * rendering/RenderView.h:
+ (LayoutStateMaintainer):
+ (WebCore::LayoutStateMaintainer::push):
+ Remove the pushes of LayoutState that were specific to RenderFlowThreads.
+
2012-08-31 Pavel Feldman <[email protected]>
Web Inspector: Update $ to alias to querySelector rather than getElementById
Modified: trunk/Source/WebCore/rendering/LayoutState.cpp (127266 => 127267)
--- trunk/Source/WebCore/rendering/LayoutState.cpp 2012-08-31 15:40:14 UTC (rev 127266)
+++ trunk/Source/WebCore/rendering/LayoutState.cpp 2012-08-31 15:47:04 UTC (rev 127267)
@@ -83,7 +83,7 @@
// If we establish a new page height, then cache the offset to the top of the first page.
// We can compare this later on to figure out what part of the page we're actually on,
- if (pageLogicalHeight || m_columnInfo) {
+ if (pageLogicalHeight || m_columnInfo || renderer->isRenderFlowThread()) {
m_pageLogicalHeight = pageLogicalHeight;
bool isFlipped = renderer->style()->isFlippedBlocksWritingMode();
m_pageOffset = LayoutSize(m_layoutOffset.width() + (!isFlipped ? renderer->borderLeft() + renderer->paddingLeft() : renderer->borderRight() + renderer->paddingRight()),
@@ -109,7 +109,7 @@
m_layoutDelta = m_next->m_layoutDelta;
- m_isPaginated = m_pageLogicalHeight || m_columnInfo;
+ m_isPaginated = m_pageLogicalHeight || m_columnInfo || renderer->isRenderFlowThread();
if (lineGrid() && renderer->hasColumns() && renderer->style()->hasInlineColumnAxis())
computeLineGridPaginationOrigin(renderer);
@@ -121,23 +121,6 @@
// FIXME: <http://bugs.webkit.org/show_bug.cgi?id=13443> Apply control clip if present.
}
-LayoutState::LayoutState(LayoutState* prev, RenderFlowThread* flowThread, bool regionsChanged)
- : m_clipped(false)
- , m_isPaginated(true)
- , m_pageLogicalHeight(1) // Use a fake height here. That value is not important, just needs to be non-zero.
- , m_pageLogicalHeightChanged(regionsChanged)
- , m_columnInfo(0)
- , m_lineGrid(0)
- , m_next(prev)
-#ifndef NDEBUG
- , m_renderer(flowThread)
-#endif
-{
-#ifdef NDEBUG
- UNUSED_PARAM(flowThread);
-#endif
-}
-
LayoutState::LayoutState(RenderObject* root)
: m_clipped(false)
, m_isPaginated(false)
Modified: trunk/Source/WebCore/rendering/LayoutState.h (127266 => 127267)
--- trunk/Source/WebCore/rendering/LayoutState.h 2012-08-31 15:40:14 UTC (rev 127266)
+++ trunk/Source/WebCore/rendering/LayoutState.h 2012-08-31 15:47:04 UTC (rev 127267)
@@ -57,7 +57,6 @@
}
LayoutState(LayoutState*, RenderBox*, const LayoutSize& offset, LayoutUnit pageHeight, bool pageHeightChanged, ColumnInfo*);
- LayoutState(LayoutState*, RenderFlowThread*, bool regionsChanged);
LayoutState(RenderObject*);
void destroy(RenderArena*);
Modified: trunk/Source/WebCore/rendering/RenderBlock.cpp (127266 => 127267)
--- trunk/Source/WebCore/rendering/RenderBlock.cpp 2012-08-31 15:40:14 UTC (rev 127266)
+++ trunk/Source/WebCore/rendering/RenderBlock.cpp 2012-08-31 15:47:04 UTC (rev 127267)
@@ -1450,6 +1450,9 @@
colInfo->clearForcedBreaks();
colInfo->setPaginationUnit(paginationUnit());
+ } else if (isRenderFlowThread()) {
+ pageLogicalHeight = 1; // This is just a hack to always make sure we have a page logical height.
+ pageLogicalHeightChanged = toRenderFlowThread(this)->pageLogicalHeightChanged();
}
}
@@ -6889,7 +6892,7 @@
if (!region)
return false;
if (region->isLastRegion())
- return region->style()->regionOverflow() == BreakRegionOverflow
+ return region->isRenderRegionSet() || region->style()->regionOverflow() == BreakRegionOverflow
|| (pageBoundaryRule == IncludePageBoundary && pageOffset == region->offsetFromLogicalTopOfFirstPage());
return true;
}
Modified: trunk/Source/WebCore/rendering/RenderFlowThread.cpp (127266 => 127267)
--- trunk/Source/WebCore/rendering/RenderFlowThread.cpp 2012-08-31 15:40:14 UTC (rev 127266)
+++ trunk/Source/WebCore/rendering/RenderFlowThread.cpp 2012-08-31 15:47:04 UTC (rev 127267)
@@ -54,6 +54,7 @@
, m_overset(true)
, m_hasRegionsWithStyling(false)
, m_dispatchRegionLayoutUpdateEvent(false)
+ , m_pageLogicalHeightChanged(false)
{
ASSERT(node->document()->cssRegionsEnabled());
setIsAnonymous(false);
@@ -132,7 +133,7 @@
void RenderFlowThread::layout()
{
- bool regionsChanged = m_regionsInvalidated && everHadLayout();
+ m_pageLogicalHeightChanged = m_regionsInvalidated && everHadLayout();
if (m_regionsInvalidated) {
m_regionsInvalidated = false;
m_hasValidRegions = false;
@@ -184,15 +185,15 @@
}
CurrentRenderFlowThreadMaintainer currentFlowThreadSetter(this);
- LayoutStateMaintainer statePusher(view(), this, regionsChanged);
RenderBlock::layout();
- statePusher.pop();
-
- if (shouldDispatchRegionLayoutUpdateEvent())
- dispatchRegionLayoutUpdateEvent();
-
+
+ m_pageLogicalHeightChanged = false;
+
if (lastRegion())
lastRegion()->expandToEncompassFlowThreadContentsIfNeeded();
+
+ if (shouldDispatchRegionLayoutUpdateEvent())
+ dispatchRegionLayoutUpdateEvent();
}
void RenderFlowThread::computeLogicalWidth()
@@ -365,11 +366,10 @@
return region;
LayoutRect regionRect = region->flowThreadPortionRect();
-
if ((useHorizontalWritingMode && offset < regionRect.maxY()) || (!useHorizontalWritingMode && offset < regionRect.maxX()))
return region;
- if (extendLastRegion)
+ if (extendLastRegion || region->isRenderRegionSet())
lastValidRegion = region;
}
@@ -379,9 +379,7 @@
LayoutUnit RenderFlowThread::pageLogicalTopForOffset(LayoutUnit offset) const
{
RenderRegion* region = regionAtBlockOffset(offset);
- if (!region)
- return ZERO_LAYOUT_UNIT;
- return isHorizontalWritingMode() ? region->flowThreadPortionRect().y() : region->flowThreadPortionRect().x();
+ return region ? region->pageLogicalTopForOffset(offset) : ZERO_LAYOUT_UNIT;
}
LayoutUnit RenderFlowThread::pageLogicalWidthForOffset(LayoutUnit offset) const
@@ -401,14 +399,15 @@
RenderRegion* region = regionAtBlockOffset(offset);
if (!region)
return ZERO_LAYOUT_UNIT;
-
- LayoutUnit regionLogicalBottom = isHorizontalWritingMode() ? region->flowThreadPortionRect().maxY() : region->flowThreadPortionRect().maxX();
- LayoutUnit remainingHeight = regionLogicalBottom - offset;
+
+ LayoutUnit pageLogicalTop = region->pageLogicalTopForOffset(offset);
+ LayoutUnit pageLogicalHeight = region->pageLogicalHeight();
+ LayoutUnit pageLogicalBottom = pageLogicalTop + pageLogicalHeight;
+ LayoutUnit remainingHeight = pageLogicalBottom - offset;
if (pageBoundaryRule == IncludePageBoundary) {
// If IncludePageBoundary is set, the line exactly on the top edge of a
// region will act as being part of the previous region.
- LayoutUnit regionHeight = isHorizontalWritingMode() ? region->flowThreadPortionRect().height() : region->flowThreadPortionRect().width();
- remainingHeight = intMod(remainingHeight, regionHeight);
+ remainingHeight = intMod(remainingHeight, pageLogicalHeight);
}
return remainingHeight;
}
Modified: trunk/Source/WebCore/rendering/RenderFlowThread.h (127266 => 127267)
--- trunk/Source/WebCore/rendering/RenderFlowThread.h 2012-08-31 15:40:14 UTC (rev 127266)
+++ trunk/Source/WebCore/rendering/RenderFlowThread.h 2012-08-31 15:47:04 UTC (rev 127267)
@@ -129,6 +129,8 @@
// Check if the object is in region and the region is part of this flow thread.
bool objectInFlowRegion(const RenderObject*, const RenderRegion*) const;
+ bool pageLogicalHeightChanged() const { return m_pageLogicalHeightChanged; }
+
protected:
virtual const char* renderName() const = 0;
@@ -180,6 +182,7 @@
bool m_overset;
bool m_hasRegionsWithStyling;
bool m_dispatchRegionLayoutUpdateEvent;
+ bool m_pageLogicalHeightChanged;
};
inline RenderFlowThread* toRenderFlowThread(RenderObject* object)
Modified: trunk/Source/WebCore/rendering/RenderMultiColumnBlock.cpp (127266 => 127267)
--- trunk/Source/WebCore/rendering/RenderMultiColumnBlock.cpp 2012-08-31 15:40:14 UTC (rev 127266)
+++ trunk/Source/WebCore/rendering/RenderMultiColumnBlock.cpp 2012-08-31 15:47:04 UTC (rev 127267)
@@ -78,23 +78,19 @@
return relayoutChildren;
}
-void RenderMultiColumnBlock::checkForPaginationLogicalHeightChange(LayoutUnit& pageLogicalHeight, bool& pageLogicalHeightChanged, bool& hasSpecifiedPageLogicalHeight)
+void RenderMultiColumnBlock::checkForPaginationLogicalHeightChange(LayoutUnit& /*pageLogicalHeight*/, bool& /*pageLogicalHeightChanged*/, bool& /*hasSpecifiedPageLogicalHeight*/)
{
- // We need to go ahead and set our explicit page height if one exists, so that we can
- // avoid doing multiple layout passes.
+ // We don't actually update any of the variables. We just subclassed to adjust our column height.
computeLogicalHeight();
LayoutUnit newContentLogicalHeight = contentLogicalHeight();
if (newContentLogicalHeight > ZERO_LAYOUT_UNIT) {
- pageLogicalHeight = newContentLogicalHeight;
- hasSpecifiedPageLogicalHeight = true;
+ // The regions will be invalidated when we lay them out and they change size to
+ // the new column height.
+ if (columnHeight() != newContentLogicalHeight)
+ setColumnHeight(newContentLogicalHeight);
}
setLogicalHeight(ZERO_LAYOUT_UNIT);
- if (columnHeight() != pageLogicalHeight && everHadLayout()) {
- setColumnHeight(pageLogicalHeight);
- pageLogicalHeightChanged = true;
- }
-
// Set up our column sets.
ensureColumnSets();
}
Modified: trunk/Source/WebCore/rendering/RenderMultiColumnSet.cpp (127266 => 127267)
--- trunk/Source/WebCore/rendering/RenderMultiColumnSet.cpp 2012-08-31 15:40:14 UTC (rev 127266)
+++ trunk/Source/WebCore/rendering/RenderMultiColumnSet.cpp 2012-08-31 15:47:04 UTC (rev 127267)
@@ -44,6 +44,13 @@
{
}
+LayoutUnit RenderMultiColumnSet::pageLogicalTopForOffset(LayoutUnit offset) const
+{
+ LayoutUnit portionLogicalTop = (isHorizontalWritingMode() ? flowThreadPortionRect().y() : flowThreadPortionRect().x());
+ unsigned columnIndex = (offset - portionLogicalTop) / computedColumnHeight();
+ return portionLogicalTop + columnIndex * computedColumnHeight();
+}
+
void RenderMultiColumnSet::computeLogicalWidth()
{
// Our logical width starts off matching the column block itself.
Modified: trunk/Source/WebCore/rendering/RenderMultiColumnSet.h (127266 => 127267)
--- trunk/Source/WebCore/rendering/RenderMultiColumnSet.h 2012-08-31 15:40:14 UTC (rev 127266)
+++ trunk/Source/WebCore/rendering/RenderMultiColumnSet.h 2012-08-31 15:47:04 UTC (rev 127267)
@@ -71,6 +71,8 @@
virtual LayoutUnit pageLogicalWidth() const OVERRIDE { return m_computedColumnWidth; }
virtual LayoutUnit pageLogicalHeight() const OVERRIDE { return m_computedColumnHeight; }
+ virtual LayoutUnit pageLogicalTopForOffset(LayoutUnit offset) const OVERRIDE;
+
// FIXME: This will change once we have column sets constrained by enclosing pages, etc.
virtual LayoutUnit logicalHeightOfAllFlowThreadContent() const OVERRIDE { return m_computedColumnHeight; }
Modified: trunk/Source/WebCore/rendering/RenderRegion.cpp (127266 => 127267)
--- trunk/Source/WebCore/rendering/RenderRegion.cpp 2012-08-31 15:40:14 UTC (rev 127266)
+++ trunk/Source/WebCore/rendering/RenderRegion.cpp 2012-08-31 15:47:04 UTC (rev 127267)
@@ -104,6 +104,11 @@
return clipRect;
}
+LayoutUnit RenderRegion::pageLogicalTopForOffset(LayoutUnit /* offset */) const
+{
+ return flowThread()->isHorizontalWritingMode() ? flowThreadPortionRect().y() : flowThreadPortionRect().x();
+}
+
bool RenderRegion::isFirstRegion() const
{
ASSERT(isValid() && m_flowThread);
@@ -186,7 +191,7 @@
LayoutRect oldRegionRect(flowThreadPortionRect());
if (!isHorizontalWritingMode())
oldRegionRect = oldRegionRect.transposedRect();
- if (oldRegionRect.width() != pageLogicalWidth() || oldRegionRect.height() != logicalHeightOfAllFlowThreadContent())
+ if (oldRegionRect.width() != pageLogicalWidth() || oldRegionRect.height() != pageLogicalHeight())
m_flowThread->invalidateRegions();
}
Modified: trunk/Source/WebCore/rendering/RenderRegion.h (127266 => 127267)
--- trunk/Source/WebCore/rendering/RenderRegion.h 2012-08-31 15:40:14 UTC (rev 127266)
+++ trunk/Source/WebCore/rendering/RenderRegion.h 2012-08-31 15:47:04 UTC (rev 127267)
@@ -106,8 +106,16 @@
// or columns added together.
virtual LayoutUnit logicalHeightOfAllFlowThreadContent() const;
+ // The top of the nearest page inside the region. For RenderRegions, this is just the logical top of the
+ // flow thread portion we contain. For sets, we have to figure out the top of the nearest column or
+ // page.
+ virtual LayoutUnit pageLogicalTopForOffset(LayoutUnit offset) const;
+
virtual void expandToEncompassFlowThreadContentsIfNeeded() {};
+ // Whether or not this region is a set.
+ virtual bool isRenderRegionSet() const { return false; }
+
protected:
void setRegionObjectsRegionStyle();
void restoreRegionObjectsOriginalStyle();
Modified: trunk/Source/WebCore/rendering/RenderRegionSet.h (127266 => 127267)
--- trunk/Source/WebCore/rendering/RenderRegionSet.h 2012-08-31 15:40:14 UTC (rev 127266)
+++ trunk/Source/WebCore/rendering/RenderRegionSet.h 2012-08-31 15:47:04 UTC (rev 127267)
@@ -55,6 +55,8 @@
virtual void expandToEncompassFlowThreadContentsIfNeeded() OVERRIDE;
virtual const char* renderName() const = 0;
+
+ virtual bool isRenderRegionSet() const OVERRIDE { return true; }
};
} // namespace WebCore
Modified: trunk/Source/WebCore/rendering/RenderView.cpp (127266 => 127267)
--- trunk/Source/WebCore/rendering/RenderView.cpp 2012-08-31 15:40:14 UTC (rev 127266)
+++ trunk/Source/WebCore/rendering/RenderView.cpp 2012-08-31 15:47:04 UTC (rev 127267)
@@ -816,11 +816,6 @@
m_layoutState = new (renderArena()) LayoutState(root);
}
-void RenderView::pushLayoutState(RenderFlowThread* flowThread, bool regionsChanged)
-{
- m_layoutState = new (renderArena()) LayoutState(m_layoutState, flowThread, regionsChanged);
-}
-
bool RenderView::shouldDisableLayoutStateForSubtree(RenderObject* renderer) const
{
RenderObject* o = renderer;
Modified: trunk/Source/WebCore/rendering/RenderView.h (127266 => 127267)
--- trunk/Source/WebCore/rendering/RenderView.h 2012-08-31 15:40:14 UTC (rev 127266)
+++ trunk/Source/WebCore/rendering/RenderView.h 2012-08-31 15:47:04 UTC (rev 127267)
@@ -351,17 +351,7 @@
, m_didCreateLayoutState(false)
{
}
-
- LayoutStateMaintainer(RenderView* view, RenderFlowThread* flowThread, bool regionsChanged)
- : m_view(view)
- , m_disabled(false)
- , m_didStart(false)
- , m_didEnd(false)
- , m_didCreateLayoutState(false)
- {
- push(flowThread, regionsChanged);
- }
-
+
~LayoutStateMaintainer()
{
ASSERT(m_didStart == m_didEnd); // if this fires, it means that someone did a push(), but forgot to pop().
@@ -376,14 +366,6 @@
m_view->disableLayoutState();
m_didStart = true;
}
-
- void push(RenderFlowThread* flowThread, bool regionsChanged)
- {
- ASSERT(!m_didStart);
- m_view->pushLayoutState(flowThread, regionsChanged);
- m_didCreateLayoutState = true;
- m_didStart = true;
- }
void pop()
{