+2012-02-08 David Hyatt <hyatt@apple.com>
+
+ https://bugs.webkit.org/show_bug.cgi?id=78157
+
+ Make multi-column layout work with line grids that are outside of the multi-column
+ block.
+
+ Reviewed by Dan Bernstein.
+
+ * fast/line-grid/line-grid-into-columns.html: Added.
+ * platform/mac/fast/line-grid/line-grid-into-columns-expected.png: Added.
+ * platform/mac/fast/line-grid/line-grid-into-columns-expected.txt: Added.
+
2012-02-08 Matt Falkenhagen <falken@chromium.org>
Improve http-equiv content-language parsing
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<style>
+.grid { -webkit-line-grid: simple; -webkit-line-grid-snap: baseline;
+ font-size:36px; position:relative; width:800px}</style>
+</head>
+<body style="margin:0">
+
+<div class="grid">
+<div style="position:absolute;left:0;right:0;top:0;bottom:0; font-family:'Ahem'; z-index:-1; color:lime; font-size:32px; white-space:nowrap; overflow:hidden">
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx<br>
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx<br>
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx<br>
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx<br>
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx<br>
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx<br>
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx<br>
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx<br>
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx<br>
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx<br>
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx<br>
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx<br>
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx<br>
+</div>
+<div style="height:500px; -webkit-column-count:2;padding:20px">
+<div style="font-size:16px">
+All of this text even though it's smaller should be on the 36px
+grid. The grid should reset at the top of the second column.<br>
+All of this text even though it's smaller should be on the 36px
+grid. The grid should reset at the top of the second column.<br>
+All of this text even though it's smaller should be on the 36px
+grid. The grid should reset at the top of the second column.<br>
+</div>
+<div style="font-size:24px">
+All of this text even though it's smaller should be on the 36px
+grid. The grid should reset at the top of the second column.<br>
+All of this text even though it's smaller should be on the 36px
+grid. The grid should reset at the top of the second column.<br>
+All of this text even though it's smaller should be on the 36px
+grid. The grid should reset at the top of the second column.<br>
+</div>
+<div style="font-size:10px">
+All of this text even though it's smaller should be on the 36px
+grid.
+</div>
+</div>
+</div>
+</body>
+</html>
--- /dev/null
+layer at (0,0) size 800x600
+ RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600 layerType: background only
+layer at (0,0) size 800x540 scrollWidth 1216
+ RenderBlock (positioned) zI: -1 {DIV} at (0,0) size 800x540 [color=#00FF00]
+ RenderText zI: -1 {#text} at (0,6) size 1216x32
+ text run at (0,6) width 1216: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ RenderBR {BR} at (0,0) size 0x0
+ RenderText zI: -1 {#text} at (0,47) size 1216x32
+ text run at (0,47) width 1216: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ RenderBR {BR} at (0,0) size 0x0
+ RenderText zI: -1 {#text} at (0,88) size 1216x32
+ text run at (0,88) width 1216: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ RenderBR {BR} at (0,0) size 0x0
+ RenderText zI: -1 {#text} at (0,129) size 1216x32
+ text run at (0,129) width 1216: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ RenderBR {BR} at (0,0) size 0x0
+ RenderText zI: -1 {#text} at (0,170) size 1216x32
+ text run at (0,170) width 1216: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ RenderBR {BR} at (0,0) size 0x0
+ RenderText zI: -1 {#text} at (0,211) size 1216x32
+ text run at (0,211) width 1216: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ RenderBR {BR} at (0,0) size 0x0
+ RenderText zI: -1 {#text} at (0,252) size 1216x32
+ text run at (0,252) width 1216: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ RenderBR {BR} at (0,0) size 0x0
+ RenderText zI: -1 {#text} at (0,293) size 1216x32
+ text run at (0,293) width 1216: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ RenderBR {BR} at (0,0) size 0x0
+ RenderText zI: -1 {#text} at (0,334) size 1216x32
+ text run at (0,334) width 1216: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ RenderBR {BR} at (0,0) size 0x0
+ RenderText zI: -1 {#text} at (0,375) size 1216x32
+ text run at (0,375) width 1216: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ RenderBR {BR} at (0,0) size 0x0
+ RenderText zI: -1 {#text} at (0,416) size 1216x32
+ text run at (0,416) width 1216: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ RenderBR {BR} at (0,0) size 0x0
+ RenderText zI: -1 {#text} at (0,457) size 1216x32
+ text run at (0,457) width 1216: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ RenderBR {BR} at (0,0) size 0x0
+ RenderText zI: -1 {#text} at (0,498) size 1216x32
+ text run at (0,498) width 1216: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ RenderBR {BR} at (0,0) size 0x0
+layer at (0,0) size 800x600 layerType: foreground only
+ RenderBlock {HTML} at (0,0) size 800x600
+ RenderBody {BODY} at (0,0) size 800x600
+layer at (0,0) size 800x540
+ RenderBlock (relative positioned) {DIV} at (0,0) size 800x540
+layer at (0,0) size 800x540
+ RenderBlock {DIV} at (0,0) size 800x540
+ RenderBlock {DIV} at (20,20) size 362x385
+ RenderText {#text} at (0,39) size 352x100
+ text run at (0,39) width 350: "All of this text even though it's smaller should be on the"
+ text run at (0,80) width 352: "36px grid. The grid should reset at the top of the second"
+ text run at (0,121) width 51: "column."
+ RenderBR {BR} at (51,135) size 0x0
+ RenderText {#text} at (0,162) size 352x100
+ text run at (0,162) width 350: "All of this text even though it's smaller should be on the"
+ text run at (0,203) width 352: "36px grid. The grid should reset at the top of the second"
+ text run at (0,244) width 51: "column."
+ RenderBR {BR} at (51,258) size 0x0
+ RenderText {#text} at (0,285) size 352x100
+ text run at (0,285) width 350: "All of this text even though it's smaller should be on the"
+ text run at (0,326) width 352: "36px grid. The grid should reset at the top of the second"
+ text run at (0,367) width 51: "column."
+ RenderBR {BR} at (51,381) size 0x0
+ RenderBlock {DIV} at (20,405) size 362x543
+ RenderText {#text} at (0,15) size 342x200
+ text run at (0,15) width 299: "All of this text even though it's"
+ text run at (0,56) width 342: "smaller should be on the 36px grid."
+ text run at (0,146) width 328: "The grid should reset at the top of"
+ text run at (0,187) width 188: "the second column."
+ RenderBR {BR} at (188,209) size 0x0
+ RenderText {#text} at (0,228) size 342x151
+ text run at (0,228) width 299: "All of this text even though it's"
+ text run at (0,269) width 342: "smaller should be on the 36px grid."
+ text run at (0,310) width 328: "The grid should reset at the top of"
+ text run at (0,351) width 188: "the second column."
+ RenderBR {BR} at (188,373) size 0x0
+ RenderText {#text} at (0,392) size 342x151
+ text run at (0,392) width 299: "All of this text even though it's"
+ text run at (0,433) width 342: "smaller should be on the 36px grid."
+ text run at (0,474) width 328: "The grid should reset at the top of"
+ text run at (0,515) width 188: "the second column."
+ RenderBR {BR} at (188,537) size 0x0
+ RenderBlock {DIV} at (20,948) size 362x38
+ RenderText {#text} at (0,25) size 274x13
+ text run at (0,25) width 274: "All of this text even though it's smaller should be on the 36px grid."
+2012-02-08 David Hyatt <hyatt@apple.com>
+
+ https://bugs.webkit.org/show_bug.cgi?id=78157
+
+ Make multi-column layout work with line grids that are outside of the multi-column
+ block.
+
+ Reviewed by Dan Bernstein.
+
+ Added new tests in fast/line-grid.
+
+ * rendering/LayoutState.cpp:
+ (WebCore::LayoutState::LayoutState):
+ (WebCore::LayoutState::propagateLineGridInfo):
+ (WebCore::LayoutState::establishLineGrid):
+ (WebCore):
+ (WebCore::LayoutState::computeLineGridPaginationOrigin):
+ * rendering/LayoutState.h:
+ (WebCore::LayoutState::LayoutState):
+ (WebCore::LayoutState::lineGrid):
+ (WebCore::LayoutState::lineGridOffset):
+ (WebCore::LayoutState::lineGridPaginationOrigin):
+ (WebCore::LayoutState::needsBlockDirectionLocationSetBeforeLayout):
+ (LayoutState):
+ * rendering/RenderBlock.cpp:
+ (WebCore::RenderBlock::layoutBlockChildren):
+ * rendering/RenderBlockLineLayout.cpp:
+ (WebCore::RenderBlock::layoutInlineChildren):
+ * rendering/RenderView.h:
+ (WebCore::RenderView::pushLayoutState):
+ * rendering/RootInlineBox.cpp:
+ (WebCore::RootInlineBox::lineGridSnapAdjustment):
+
2012-02-08 Matthew Delaney <mdelaney@apple.com>
GeneratorGeneratedImage::drawPattern does not factor in its destination context's scale when generating its image tiles
LayoutState::LayoutState(LayoutState* prev, RenderBox* renderer, const LayoutSize& offset, LayoutUnit pageLogicalHeight, bool pageLogicalHeightChanged, ColumnInfo* columnInfo)
: m_columnInfo(columnInfo)
- , m_currentLineGrid(0)
+ , m_lineGrid(0)
, m_next(prev)
#ifndef NDEBUG
, m_renderer(renderer)
m_pageLogicalHeight = 0;
}
+ // Propagate line grid information.
+ propagateLineGridInfo(renderer);
+
if (!m_columnInfo)
m_columnInfo = m_next->m_columnInfo;
m_isPaginated = m_pageLogicalHeight || m_columnInfo;
- // Propagate line grid information.
- propagateLineGridInfo(renderer);
+ if (lineGrid() && renderer->hasColumns() && renderer->style()->hasInlineColumnAxis())
+ computeLineGridPaginationOrigin(renderer);
// If we have a new grid to track, then add it to our set.
if (renderer->style()->lineGrid() != RenderStyle::initialLineGrid() && renderer->isBlockFlow())
, 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_currentLineGrid(0)
+ , m_lineGrid(0)
, m_next(prev)
#ifndef NDEBUG
, m_renderer(flowThread)
, m_pageLogicalHeight(0)
, m_pageLogicalHeightChanged(false)
, m_columnInfo(0)
- , m_currentLineGrid(0)
+ , m_lineGrid(0)
, m_next(0)
#ifndef NDEBUG
, m_renderer(root)
if (!m_next || renderer->isUnsplittableForPagination())
return;
- m_currentLineGrid = m_next->m_currentLineGrid;
- m_currentLineGridOffset = m_next->m_currentLineGridOffset;
+ m_lineGrid = m_next->m_lineGrid;
+ m_lineGridOffset = m_next->m_lineGridOffset;
+ m_lineGridPaginationOrigin = m_next->m_lineGridPaginationOrigin;
}
void LayoutState::establishLineGrid(RenderBlock* block)
{
// First check to see if this grid has been established already.
- if (m_currentLineGrid) {
- if (m_currentLineGrid->style()->lineGrid() == block->style()->lineGrid())
+ if (m_lineGrid) {
+ if (m_lineGrid->style()->lineGrid() == block->style()->lineGrid())
return;
- RenderBlock* currentGrid = m_currentLineGrid;
+ RenderBlock* currentGrid = m_lineGrid;
for (LayoutState* currentState = m_next; currentState; currentState = currentState->m_next) {
- if (currentState->m_currentLineGrid == currentGrid)
+ if (currentState->m_lineGrid == currentGrid)
continue;
- currentGrid = currentState->m_currentLineGrid;
+ currentGrid = currentState->m_lineGrid;
if (!currentGrid)
break;
if (currentGrid->style()->lineGrid() == block->style()->lineGrid()) {
- m_currentLineGrid = currentGrid;
- m_currentLineGridOffset = currentState->m_currentLineGridOffset;
+ m_lineGrid = currentGrid;
+ m_lineGridOffset = currentState->m_lineGridOffset;
return;
}
}
}
// We didn't find an already-established grid with this identifier. Our render object establishes the grid.
- m_currentLineGrid = block;
- m_currentLineGridOffset = m_layoutOffset;
+ m_lineGrid = block;
+ m_lineGridOffset = m_layoutOffset;
+}
+
+void LayoutState::computeLineGridPaginationOrigin(RenderBox* renderer)
+{
+ // We need to cache a line grid pagination origin so that we understand how to reset the line grid
+ // at the top of each column.
+ // Get the current line grid and offset.
+ if (!lineGrid() || lineGrid()->style()->writingMode() != renderer->style()->writingMode())
+ return;
+
+ // Get the hypothetical line box used to establish the grid.
+ RootInlineBox* lineGridBox = lineGrid()->lineGridBox();
+ if (!lineGridBox)
+ return;
+
+ bool isHorizontalWritingMode = lineGrid()->isHorizontalWritingMode();
+
+ LayoutUnit lineGridBlockOffset = isHorizontalWritingMode ? lineGridOffset().height() : lineGridOffset().width();
+
+ // Now determine our position on the grid. Our baseline needs to be adjusted to the nearest baseline multiple
+ // as established by the line box.
+ // FIXME: Need to handle crazy line-box-contain values that cause the root line box to not be considered. I assume
+ // the grid should honor line-box-contain.
+ LayoutUnit gridLineHeight = lineGridBox->lineBottomWithLeading() - lineGridBox->lineTopWithLeading();
+ if (!gridLineHeight)
+ return;
+
+ LayoutUnit firstLineTopWithLeading = lineGridBlockOffset + lineGridBox->lineTopWithLeading();
+
+ if (isPaginated() && pageLogicalHeight()) {
+ LayoutUnit pageLogicalTop = renderer->isHorizontalWritingMode() ? m_pageOffset.height() : m_pageOffset.width();
+ if (pageLogicalTop > firstLineTopWithLeading) {
+ // Shift to the next highest line grid multiple past the page logical top. Cache the delta
+ // between this new value and the page logical top as the pagination origin.
+ LayoutUnit remainder = (pageLogicalTop - firstLineTopWithLeading) % gridLineHeight;
+ LayoutUnit paginationDelta = gridLineHeight - remainder;
+ if (isHorizontalWritingMode)
+ m_lineGridPaginationOrigin.setHeight(paginationDelta);
+ else
+ m_lineGridPaginationOrigin.setWidth(paginationDelta);
+ }
+ }
}
} // namespace WebCore
, m_pageLogicalHeight(0)
, m_pageLogicalHeightChanged(false)
, m_columnInfo(0)
- , m_currentLineGrid(0)
+ , m_lineGrid(0)
, m_next(0)
#ifndef NDEBUG
, m_renderer(0)
LayoutUnit pageLogicalHeight() const { return m_pageLogicalHeight; }
bool pageLogicalHeightChanged() const { return m_pageLogicalHeightChanged; }
- RenderBlock* currentLineGrid() const { return m_currentLineGrid; }
- LayoutSize currentLineGridOffset() const { return m_currentLineGridOffset; }
+ RenderBlock* lineGrid() const { return m_lineGrid; }
+ LayoutSize lineGridOffset() const { return m_lineGridOffset; }
+ LayoutSize lineGridPaginationOrigin() const { return m_lineGridPaginationOrigin; }
LayoutSize layoutOffset() const { return m_layoutOffset; }
- bool needsBlockDirectionLocationSetBeforeLayout() const { return m_currentLineGrid || (m_isPaginated && m_pageLogicalHeight); }
+ bool needsBlockDirectionLocationSetBeforeLayout() const { return m_lineGrid || (m_isPaginated && m_pageLogicalHeight); }
private:
// The normal operator new is disallowed.
void propagateLineGridInfo(RenderBox*);
void establishLineGrid(RenderBlock*);
+ void computeLineGridPaginationOrigin(RenderBox*);
+
public:
bool m_clipped;
bool m_isPaginated;
ColumnInfo* m_columnInfo;
// The current line grid that we're snapping to and the offset of the start of the grid.
- RenderBlock* m_currentLineGrid;
- LayoutSize m_currentLineGridOffset;
-
+ RenderBlock* m_lineGrid;
+ LayoutSize m_lineGridOffset;
+ LayoutSize m_lineGridPaginationOrigin;
+
LayoutState* m_next;
#ifndef NDEBUG
RenderObject* m_renderer;
setLogicalHeight(beforeEdge);
// Lay out our hypothetical grid line as though it occurs at the top of the block.
- if (view()->layoutState()->currentLineGrid() == this)
+ if (view()->layoutState()->lineGrid() == this)
layoutLineGridBox();
// The margin struct caches all our current margin collapsing state. The compact struct caches state when we encounter compacts,
setLogicalHeight(borderBefore() + paddingBefore());
// Lay out our hypothetical grid line as though it occurs at the top of the block.
- if (view()->layoutState() && view()->layoutState()->currentLineGrid() == this)
+ if (view()->layoutState() && view()->layoutState()->lineGrid() == this)
layoutLineGridBox();
// Figure out if we should clear out our line boxes.
{
// We push LayoutState even if layoutState is disabled because it stores layoutDelta too.
if (!doingFullRepaint() || m_layoutState->isPaginated() || renderer->hasColumns() || renderer->inRenderFlowThread()
- || m_layoutState->currentLineGrid() || (renderer->style()->lineGrid() != RenderStyle::initialLineGrid() && renderer->isBlockFlow())) {
+ || m_layoutState->lineGrid() || (renderer->style()->lineGrid() != RenderStyle::initialLineGrid() && renderer->isBlockFlow())) {
m_layoutState = new (renderArena()) LayoutState(m_layoutState, renderer, offset, pageHeight, pageHeightChanged, colInfo);
return true;
}
// Get the current line grid and offset.
LayoutState* layoutState = block()->view()->layoutState();
- RenderBlock* lineGrid = layoutState->currentLineGrid();
- LayoutSize lineGridOffset = layoutState->currentLineGridOffset();
+ RenderBlock* lineGrid = layoutState->lineGrid();
+ LayoutSize lineGridOffset = layoutState->lineGridOffset();
if (!lineGrid || lineGrid->style()->writingMode() != block()->style()->writingMode())
return 0;
LayoutUnit lineGridFontAscent = lineGrid->style()->fontMetrics().ascent(baselineType());
LayoutUnit lineGridFontHeight = lineGridBox->logicalHeight();
LayoutUnit firstTextTop = lineGridBlockOffset + lineGridBox->logicalTop();
+ LayoutUnit firstLineTopWithLeading = lineGridBlockOffset + lineGridBox->lineTopWithLeading();
LayoutUnit firstBaselinePosition = firstTextTop + lineGridFontAscent;
LayoutUnit currentTextTop = blockOffset + logicalTop() + delta;
LayoutUnit currentFontAscent = block()->style()->fontMetrics().ascent(baselineType());
LayoutUnit currentBaselinePosition = currentTextTop + currentFontAscent;
+ LayoutUnit lineGridPaginationOrigin = isHorizontal() ? layoutState->lineGridPaginationOrigin().height() : layoutState->lineGridPaginationOrigin().width();
+
// If we're paginated, see if we're on a page after the first one. If so, the grid resets on subsequent pages.
// FIXME: If the grid is an ancestor of the pagination establisher, then this is incorrect.
LayoutUnit pageLogicalTop = 0;
if (layoutState->isPaginated() && layoutState->pageLogicalHeight()) {
- pageLogicalTop = block()->pageLogicalTopForOffset(logicalTop() + delta);
- if (pageLogicalTop > firstTextTop)
- firstTextTop = pageLogicalTop + lineGridBox->logicalTop() - lineGrid->borderBefore() - lineGrid->paddingBefore();
+ pageLogicalTop = block()->pageLogicalTopForOffset(lineTopWithLeading() + delta);
+ if (pageLogicalTop > firstLineTopWithLeading)
+ firstTextTop = pageLogicalTop + lineGridBox->logicalTop() - lineGrid->borderBefore() - lineGrid->paddingBefore() + lineGridPaginationOrigin;
}
if (block()->style()->lineGridSnap() == LineGridSnapContain) {
if (!layoutState->isPaginated() || !layoutState->pageLogicalHeight() || result == delta)
return result;
- // We may have shifted to a new page. We need to do a re-snap when that happens.
- LayoutUnit newPageLogicalTop = block()->pageLogicalTopForOffset(logicalTop() + result);
+ // We may end up shifted to a new page. We need to do a re-snap when that happens.
+ LayoutUnit newPageLogicalTop = block()->pageLogicalTopForOffset(lineBottomWithLeading() + result);
if (newPageLogicalTop == pageLogicalTop)
return result;
// Put ourselves at the top of the next page to force a snap onto the new grid established by that page.
- return lineGridSnapAdjustment(newPageLogicalTop - (blockOffset + logicalTop()));
+ return lineGridSnapAdjustment(newPageLogicalTop - (blockOffset + lineTopWithLeading()));
}
GapRects RootInlineBox::lineSelectionGap(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,