15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2012 Apple Inc.  All rights reserved.
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * are met:
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 1. Redistributions of source code must retain the above copyright
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    notice, this list of conditions and the following disclaimer.
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 2. Redistributions in binary form must reproduce the above copyright
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    notice, this list of conditions and the following disclaimer in the
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    documentation and/or other materials provided with the distribution.
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
2753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/RenderMultiColumnSet.h"
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
297242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "core/paint/BoxPainter.h"
307242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "core/paint/MultiColumnSetPainter.h"
317242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "core/paint/ObjectPainter.h"
3253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/PaintInfo.h"
3353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/RenderLayer.h"
3453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/RenderMultiColumnFlowThread.h"
355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
36c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink {
375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
38926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)RenderMultiColumnSet::RenderMultiColumnSet(RenderFlowThread* flowThread)
39323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    : RenderRegion(0, flowThread)
40d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    , m_columnHeight(0)
4109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    , m_maxColumnHeight(RenderFlowThread::maxLogicalHeight())
4209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    , m_minSpaceShortage(RenderFlowThread::maxLogicalHeight())
43926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    , m_minimumColumnHeight(0)
44926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
45926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
46926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
47f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo LiuRenderMultiColumnSet* RenderMultiColumnSet::createAnonymous(RenderFlowThread* flowThread, RenderStyle* parentStyle)
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
498abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    Document& document = flowThread->document();
50f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    RenderMultiColumnSet* renderer = new RenderMultiColumnSet(flowThread);
518abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    renderer->setDocumentForAnonymous(&document);
52f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    renderer->setStyle(RenderStyle::createAnonymousStyleWithDisplay(parentStyle, BLOCK));
53926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return renderer;
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
56f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo LiuRenderMultiColumnSet* RenderMultiColumnSet::nextSiblingMultiColumnSet() const
57f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu{
58f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    for (RenderObject* sibling = nextSibling(); sibling; sibling = sibling->nextSibling()) {
59f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        if (sibling->isRenderMultiColumnSet())
60f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            return toRenderMultiColumnSet(sibling);
61f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    }
62f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    return 0;
63f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu}
64f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu
65d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)RenderMultiColumnSet* RenderMultiColumnSet::previousSiblingMultiColumnSet() const
66d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles){
67d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    for (RenderObject* sibling = previousSibling(); sibling; sibling = sibling->previousSibling()) {
68d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        if (sibling->isRenderMultiColumnSet())
69d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            return toRenderMultiColumnSet(sibling);
70d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    }
71d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    return 0;
72d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)}
73d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)
74f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo LiuLayoutSize RenderMultiColumnSet::flowThreadTranslationAtOffset(LayoutUnit blockOffset) const
75f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu{
76f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    unsigned columnIndex = columnIndexAtOffset(blockOffset);
77f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    LayoutRect portionRect(flowThreadPortionRectAt(columnIndex));
78f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    flipForWritingMode(portionRect);
79f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    LayoutRect columnRect(columnRectAt(columnIndex));
80f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    flipForWritingMode(columnRect);
81f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    return contentBoxRect().location() + columnRect.location() - portionRect.location();
82f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu}
83f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu
84591b958dee2cf159d33a0b931e6231072eaf38d5Ben MurdochLayoutUnit RenderMultiColumnSet::heightAdjustedForSetOffset(LayoutUnit height) const
85591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
86d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    // Adjust for the top offset within the content box of the multicol container (containing
87d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    // block), unless this is the first set. We know that the top offset for the first set will be
88d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    // zero, but if the multicol container has non-zero top border or padding, the set's top offset
89d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    // (initially being 0 and relative to the border box) will be negative until it has been laid
90d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    // out. Had we used this bogus offset, we would calculate the wrong height, and risk performing
91d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    // a wasted layout iteration. Of course all other sets (if any) have this problem in the first
92d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    // layout pass too, but there's really nothing we can do there until the flow thread has been
93d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    // laid out anyway.
94d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    if (previousSiblingMultiColumnSet()) {
95d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        RenderBlockFlow* multicolBlock = multiColumnBlockFlow();
96d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        LayoutUnit contentLogicalTop = logicalTop() - multicolBlock->borderAndPaddingBefore();
97d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        height -= contentLogicalTop;
98d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    }
99591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    return max(height, LayoutUnit(1)); // Let's avoid zero height, as that would probably cause an infinite amount of columns to be created.
100591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
101591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)LayoutUnit RenderMultiColumnSet::pageLogicalTopForOffset(LayoutUnit offset) const
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
104591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    unsigned columnIndex = columnIndexAtOffset(offset, AssumeNewColumns);
105d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    return logicalTopInFlowThread() + columnIndex * pageLogicalHeight();
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
108591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochvoid RenderMultiColumnSet::setAndConstrainColumnHeight(LayoutUnit newHeight)
109591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
110d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    m_columnHeight = newHeight;
111d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    if (m_columnHeight > m_maxColumnHeight)
112d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        m_columnHeight = m_maxColumnHeight;
113591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    // FIXME: the height may also be affected by the enclosing pagination context, if any.
114591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
115591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
11609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)unsigned RenderMultiColumnSet::findRunWithTallestColumns() const
117591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
11809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    unsigned indexWithLargestHeight = 0;
11909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    LayoutUnit largestHeight;
120d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    LayoutUnit previousOffset = logicalTopInFlowThread();
12109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    size_t runCount = m_contentRuns.size();
12209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    ASSERT(runCount);
12309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    for (size_t i = 0; i < runCount; i++) {
12409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        const ContentRun& run = m_contentRuns[i];
12509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        LayoutUnit height = run.columnLogicalHeight(previousOffset);
12609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        if (largestHeight < height) {
12709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            largestHeight = height;
12809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            indexWithLargestHeight = i;
12909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        }
13009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        previousOffset = run.breakOffset();
13109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
13209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return indexWithLargestHeight;
13309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
13409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
13509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void RenderMultiColumnSet::distributeImplicitBreaks()
13609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
137197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#if ENABLE(ASSERT)
13809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // There should be no implicit breaks assumed at this point.
139d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    for (unsigned i = 0; i < m_contentRuns.size(); i++)
14009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        ASSERT(!m_contentRuns[i].assumedImplicitBreaks());
141197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#endif // ENABLE(ASSERT)
14209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
143323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // Insert a final content run to encompass all content. This will include overflow if this is
144323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // the last set.
145d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    addContentRun(logicalBottomInFlowThread());
146d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    unsigned columnCount = m_contentRuns.size();
14709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
14809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // If there is room for more breaks (to reach the used value of column-count), imagine that we
14909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // insert implicit breaks at suitable locations. At any given time, the content run with the
15009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // currently tallest columns will get another implicit break "inserted", which will increase its
15109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // column count by one and shrink its columns' height. Repeat until we have the desired total
15209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // number of breaks. The largest column height among the runs will then be the initial column
15309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // height for the balancer to use.
154d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    while (columnCount < usedColumnCount()) {
15509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        unsigned index = findRunWithTallestColumns();
15609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        m_contentRuns[index].assumeAnotherImplicitBreak();
157d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        columnCount++;
15809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
15909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
160591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
161d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)LayoutUnit RenderMultiColumnSet::calculateColumnHeight(BalancedHeightCalculation calculationMode) const
16209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
163d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    if (calculationMode == GuessFromFlowThreadPortion) {
164d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        // Initial balancing. Start with the lowest imaginable column height. We use the tallest
165d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        // content run (after having "inserted" implicit breaks), and find its start offset (by
166d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        // looking at the previous run's end offset, or, if there's no previous run, the set's start
167d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        // offset in the flow thread).
16809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        unsigned index = findRunWithTallestColumns();
169d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        LayoutUnit startOffset = index > 0 ? m_contentRuns[index - 1].breakOffset() : logicalTopInFlowThread();
17009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return std::max<LayoutUnit>(m_contentRuns[index].columnLogicalHeight(startOffset), m_minimumColumnHeight);
171591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    }
172591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
173d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    if (actualColumnCount() <= usedColumnCount()) {
174591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        // With the current column height, the content fits without creating overflowing columns. We're done.
175d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        return m_columnHeight;
17609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
17709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
178d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    if (m_contentRuns.size() >= usedColumnCount()) {
17909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        // Too many forced breaks to allow any implicit breaks. Initial balancing should already
18009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        // have set a good height. There's nothing more we should do.
181d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        return m_columnHeight;
182591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    }
183591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
184591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    // If the initial guessed column height wasn't enough, stretch it now. Stretch by the lowest
185591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    // amount of space shortage found during layout.
186591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
18709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    ASSERT(m_minSpaceShortage > 0); // We should never _shrink_ the height!
18809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    ASSERT(m_minSpaceShortage != RenderFlowThread::maxLogicalHeight()); // If this happens, we probably have a bug.
18909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (m_minSpaceShortage == RenderFlowThread::maxLogicalHeight())
190d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        return m_columnHeight; // So bail out rather than looping infinitely.
191591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
192d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    return m_columnHeight + m_minSpaceShortage;
19309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
19409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
195d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)void RenderMultiColumnSet::addContentRun(LayoutUnit endOffsetFromFirstPage)
19609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
197197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    if (!multiColumnFlowThread()->heightIsAuto())
19809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return;
199d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    if (!m_contentRuns.isEmpty() && endOffsetFromFirstPage <= m_contentRuns.last().breakOffset())
20009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return;
20109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // Append another item as long as we haven't exceeded used column count. What ends up in the
20209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // overflow area shouldn't affect column balancing.
203d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    if (m_contentRuns.size() < usedColumnCount())
204d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        m_contentRuns.append(ContentRun(endOffsetFromFirstPage));
20509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
20609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
207d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)bool RenderMultiColumnSet::recalculateColumnHeight(BalancedHeightCalculation calculationMode)
20809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
209197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    ASSERT(multiColumnFlowThread()->heightIsAuto());
21009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
211d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    LayoutUnit oldColumnHeight = m_columnHeight;
212d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    if (calculationMode == GuessFromFlowThreadPortion) {
213d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        // Post-process the content runs and find out where the implicit breaks will occur.
21409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        distributeImplicitBreaks();
215d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    }
216d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    LayoutUnit newColumnHeight = calculateColumnHeight(calculationMode);
21709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    setAndConstrainColumnHeight(newColumnHeight);
21809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
21909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // After having calculated an initial column height, the multicol container typically needs at
22009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // least one more layout pass with a new column height, but if a height was specified, we only
22109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // need to do this if we think that we need less space than specified. Conversely, if we
22209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // determined that the columns need to be as tall as the specified height of the container, we
22309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // have already laid it out correctly, and there's no need for another pass.
22409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
225d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    // We can get rid of the content runs now, if we haven't already done so. They are only needed
226d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    // to calculate the initial balanced column height. In fact, we have to get rid of them before
227d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    // the next layout pass, since each pass will rebuild this.
228d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    m_contentRuns.clear();
229d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)
230d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    if (m_columnHeight == oldColumnHeight)
23109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return false; // No change. We're done.
23209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
23309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    m_minSpaceShortage = RenderFlowThread::maxLogicalHeight();
23409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return true; // Need another pass.
235591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
236591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
237591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochvoid RenderMultiColumnSet::recordSpaceShortage(LayoutUnit spaceShortage)
238591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
239591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    if (spaceShortage >= m_minSpaceShortage)
240591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        return;
241591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
242591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    // The space shortage is what we use as our stretch amount. We need a positive number here in
243591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    // order to get anywhere.
244591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    ASSERT(spaceShortage > 0);
245591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
246591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    m_minSpaceShortage = spaceShortage;
247591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
248591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
249d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)void RenderMultiColumnSet::resetColumnHeight()
2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
251d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    // Nuke previously stored minimum column height. Contents may have changed for all we know.
252d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    m_minimumColumnHeight = 0;
253591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
254d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    m_maxColumnHeight = calculateMaxColumnHeight();
255591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
256d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    LayoutUnit oldColumnHeight = pageLogicalHeight();
257591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
258197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    if (multiColumnFlowThread()->heightIsAuto())
259d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        m_columnHeight = 0;
260d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    else
261f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        setAndConstrainColumnHeight(heightAdjustedForSetOffset(multiColumnFlowThread()->columnHeightAvailable()));
262591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
263d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    if (pageLogicalHeight() != oldColumnHeight)
264d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        setChildNeedsLayout(MarkOnlyThis);
26509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
266d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    // Content runs are only needed in the initial layout pass, in order to find an initial column
267d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    // height, and should have been deleted afterwards. We're about to rebuild the content runs, so
268d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    // the list needs to be empty.
269d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    ASSERT(m_contentRuns.isEmpty());
2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
272323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)void RenderMultiColumnSet::expandToEncompassFlowThreadContentsIfNeeded()
273323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles){
274323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    ASSERT(multiColumnFlowThread()->lastMultiColumnSet() == this);
275323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    LayoutRect rect(flowThreadPortionRect());
276323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)
277323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // Get the offset within the flow thread in its block progression direction. Then get the
278323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // flow thread's remaining logical height including its overflow and expand our rect
279323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // to encompass that remaining height and overflow. The idea is that we will generate
280323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // additional columns and pages to hold that overflow, since people do write bad
281323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // content like <body style="height:0px"> in multi-column layouts.
282323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    bool isHorizontal = flowThread()->isHorizontalWritingMode();
283323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    LayoutUnit logicalTopOffset = isHorizontal ? rect.y() : rect.x();
284323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    LayoutRect layoutRect = flowThread()->layoutOverflowRect();
285323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    LayoutUnit logicalHeightWithOverflow = (isHorizontal ? layoutRect.maxY() : layoutRect.maxX()) - logicalTopOffset;
286323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    setFlowThreadPortionRect(LayoutRect(rect.x(), rect.y(), isHorizontal ? rect.width() : logicalHeightWithOverflow, isHorizontal ? logicalHeightWithOverflow : rect.height()));
287323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)}
288323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)
289591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochvoid RenderMultiColumnSet::computeLogicalHeight(LayoutUnit, LayoutUnit logicalTop, LogicalExtentComputedValues& computedValues) const
2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
291d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    computedValues.m_extent = m_columnHeight;
292591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    computedValues.m_position = logicalTop;
2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
295d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)LayoutUnit RenderMultiColumnSet::calculateMaxColumnHeight() const
296d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles){
297d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    RenderBlockFlow* multicolBlock = multiColumnBlockFlow();
298d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    RenderStyle* multicolStyle = multicolBlock->style();
299d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    LayoutUnit availableHeight = multiColumnFlowThread()->columnHeightAvailable();
300d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    LayoutUnit maxColumnHeight = availableHeight ? availableHeight : RenderFlowThread::maxLogicalHeight();
3019e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    if (!multicolStyle->logicalMaxHeight().isMaxSizeNone()) {
302d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        LayoutUnit logicalMaxHeight = multicolBlock->computeContentLogicalHeight(multicolStyle->logicalMaxHeight(), -1);
303d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        if (logicalMaxHeight != -1 && maxColumnHeight > logicalMaxHeight)
304d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            maxColumnHeight = logicalMaxHeight;
305d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    }
306d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    return heightAdjustedForSetOffset(maxColumnHeight);
307d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)}
308d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)
3095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)LayoutUnit RenderMultiColumnSet::columnGap() const
3105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
311d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    RenderBlockFlow* parentBlock = multiColumnBlockFlow();
312926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (parentBlock->style()->hasNormalColumnGap())
313926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return parentBlock->style()->fontDescription().computedPixelSize(); // "1em" is recommended as the normal gap setting. Matches <p> margins.
314926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return parentBlock->style()->columnGap();
3155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
317d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)unsigned RenderMultiColumnSet::actualColumnCount() const
3185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
319591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    // We must always return a value of 1 or greater. Column count = 0 is a meaningless situation,
320591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    // and will confuse and cause problems in other parts of the code.
321d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    if (!pageLogicalHeight())
322591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        return 1;
323591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
324926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // Our portion rect determines our column count. We have as many columns as needed to fit all the content.
3255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    LayoutUnit logicalHeightInColumns = flowThread()->isHorizontalWritingMode() ? flowThreadPortionRect().height() : flowThreadPortionRect().width();
326d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (!logicalHeightInColumns)
327d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return 1;
328d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
329d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    unsigned count = ceil(logicalHeightInColumns.toFloat() / pageLogicalHeight().toFloat());
330591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    ASSERT(count >= 1);
331591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    return count;
3325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)LayoutRect RenderMultiColumnSet::columnRectAt(unsigned index) const
3355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
336d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    LayoutUnit colLogicalWidth = pageLogicalWidth();
337d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    LayoutUnit colLogicalHeight = pageLogicalHeight();
3385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    LayoutUnit colLogicalTop = borderBefore() + paddingBefore();
3395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    LayoutUnit colLogicalLeft = borderAndPaddingLogicalLeft();
340926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    LayoutUnit colGap = columnGap();
341197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
342197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    if (multiColumnFlowThread()->progressionIsInline()) {
343197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        if (style()->isLeftToRightDirection())
344197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            colLogicalLeft += index * (colLogicalWidth + colGap);
345197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        else
346197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            colLogicalLeft += contentLogicalWidth() - colLogicalWidth - index * (colLogicalWidth + colGap);
347197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    } else {
348197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        colLogicalTop += index * (colLogicalHeight + colGap);
349197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    }
3505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (isHorizontalWritingMode())
3525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return LayoutRect(colLogicalLeft, colLogicalTop, colLogicalWidth, colLogicalHeight);
3535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return LayoutRect(colLogicalTop, colLogicalLeft, colLogicalHeight, colLogicalWidth);
3545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
356591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochunsigned RenderMultiColumnSet::columnIndexAtOffset(LayoutUnit offset, ColumnIndexCalculationMode mode) const
3575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    LayoutRect portionRect(flowThreadPortionRect());
359591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
3605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Handle the offset being out of range.
361591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    LayoutUnit flowThreadLogicalTop = isHorizontalWritingMode() ? portionRect.y() : portionRect.x();
3625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (offset < flowThreadLogicalTop)
3635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
364591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    // If we're laying out right now, we cannot constrain against some logical bottom, since it
365591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    // isn't known yet. Otherwise, just return the last column if we're past the logical bottom.
366591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    if (mode == ClampToExistingColumns) {
367591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        LayoutUnit flowThreadLogicalBottom = isHorizontalWritingMode() ? portionRect.maxY() : portionRect.maxX();
368591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        if (offset >= flowThreadLogicalBottom)
369d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            return actualColumnCount() - 1;
370591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    }
371591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
3725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Just divide by the column height to determine the correct column.
373d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    return (offset - flowThreadLogicalTop).toFloat() / pageLogicalHeight().toFloat();
3745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)LayoutRect RenderMultiColumnSet::flowThreadPortionRectAt(unsigned index) const
3775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    LayoutRect portionRect = flowThreadPortionRect();
3795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (isHorizontalWritingMode())
380d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        portionRect = LayoutRect(portionRect.x(), portionRect.y() + index * pageLogicalHeight(), portionRect.width(), pageLogicalHeight());
3815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else
382d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        portionRect = LayoutRect(portionRect.x() + index * pageLogicalHeight(), portionRect.y(), pageLogicalHeight(), portionRect.height());
3835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return portionRect;
3845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
386926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)LayoutRect RenderMultiColumnSet::flowThreadPortionOverflowRect(const LayoutRect& portionRect, unsigned index, unsigned colCount, LayoutUnit colGap) const
3875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // This function determines the portion of the flow thread that paints for the column. Along the inline axis, columns are
3895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // unclipped at outside edges (i.e., the first and last column in the set), and they clip to half the column
3905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // gap along interior edges.
3915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //
3925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // In the block direction, we will not clip overflow out of the top of the first column, or out of the bottom of
3935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // the last column. This applies only to the true first column and last column across all column sets.
3945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //
3955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // FIXME: Eventually we will know overflow on a per-column basis, but we can't do this until we have a painting
3965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // mode that understands not to paint contents from a previous column in the overflow area of a following column.
3975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // This problem applies to regions and pages as well and is not unique to columns.
3985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool isFirstColumn = !index;
3995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool isLastColumn = index == colCount - 1;
400926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    bool isLeftmostColumn = style()->isLeftToRightDirection() ? isFirstColumn : isLastColumn;
401926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    bool isRightmostColumn = style()->isLeftToRightDirection() ? isLastColumn : isFirstColumn;
4021e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)
4031e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    // Calculate the overflow rectangle, based on the flow thread's, clipped at column logical
4041e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    // top/bottom unless it's the first/last column.
4051e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    LayoutRect overflowRect = overflowRectForFlowThreadPortion(portionRect, isFirstColumn && isFirstRegion(), isLastColumn && isLastRegion());
4061e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)
4071e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    // Avoid overflowing into neighboring columns, by clipping in the middle of adjacent column
4081e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    // gaps. Also make sure that we avoid rounding errors.
4095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (isHorizontalWritingMode()) {
4101e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        if (!isLeftmostColumn)
4115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            overflowRect.shiftXEdgeTo(portionRect.x() - colGap / 2);
4121e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        if (!isRightmostColumn)
4131e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)            overflowRect.shiftMaxXEdgeTo(portionRect.maxX() + colGap - colGap / 2);
4145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else {
4151e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        if (!isLeftmostColumn)
4165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            overflowRect.shiftYEdgeTo(portionRect.y() - colGap / 2);
4171e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        if (!isRightmostColumn)
4181e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)            overflowRect.shiftMaxYEdgeTo(portionRect.maxY() + colGap - colGap / 2);
4195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4201e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    return overflowRect;
4215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
423926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)void RenderMultiColumnSet::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
4245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4257242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    MultiColumnSetPainter(*this).paintObject(paintInfo, paintOffset);
4265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4289e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)void RenderMultiColumnSet::paintInvalidationForFlowThreadContent(const LayoutRect& paintInvalidationRect) const
4295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Figure out the start and end columns and only check within that range so that we don't walk the
4319e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    // entire column set. Put the paint invalidation rect into flow thread coordinates by flipping it first.
4329e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    LayoutRect flowThreadPaintInvalidationRect(paintInvalidationRect);
4339e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    flowThread()->flipForWritingMode(flowThreadPaintInvalidationRect);
43402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
4355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Now we can compare this rect with the flow thread portions owned by each column. First let's
4369e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    // just see if the paint invalidation rect intersects our flow thread portion at all.
4379e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    LayoutRect clippedRect(flowThreadPaintInvalidationRect);
4385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    clippedRect.intersect(RenderRegion::flowThreadPortionOverflowRect());
4395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (clippedRect.isEmpty())
4405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
44102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
4425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Now we know we intersect at least one column. Let's figure out the logical top and logical
4439e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    // bottom of the area in which we're issuing paint invalidations.
4449e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    LayoutUnit paintInvalidationLogicalTop = isHorizontalWritingMode() ? flowThreadPaintInvalidationRect.y() : flowThreadPaintInvalidationRect.x();
4459e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    LayoutUnit paintInvalidationLogicalBottom = (isHorizontalWritingMode() ? flowThreadPaintInvalidationRect.maxY() : flowThreadPaintInvalidationRect.maxX()) - 1;
44602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
4479e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    unsigned startColumn = columnIndexAtOffset(paintInvalidationLogicalTop);
4489e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    unsigned endColumn = columnIndexAtOffset(paintInvalidationLogicalBottom);
44902772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
4505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    LayoutUnit colGap = columnGap();
451d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    unsigned colCount = actualColumnCount();
4525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (unsigned i = startColumn; i <= endColumn; i++) {
4535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        LayoutRect colRect = columnRectAt(i);
45402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
4555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Get the portion of the flow thread that corresponds to this column.
4565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        LayoutRect flowThreadPortion = flowThreadPortionRectAt(i);
45702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
4585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Now get the overflow rect that corresponds to the column.
4595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        LayoutRect flowThreadOverflowPortion = flowThreadPortionOverflowRect(flowThreadPortion, i, colCount, colGap);
4605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4619e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)        // Do a paint invalidation for this specific column.
4627242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        paintInvalidationOfFlowThreadContentRectangle(paintInvalidationRect, flowThreadPortion, flowThreadOverflowPortion, colRect.location());
4635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
466926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)void RenderMultiColumnSet::collectLayerFragments(LayerFragments& fragments, const LayoutRect& layerBoundingBox, const LayoutRect& dirtyRect)
467926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
4681e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    // The two rectangles passed to this method are physical, except that we pretend that there's
4691e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    // only one long column (that's how a flow thread works).
4701e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    //
4711e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    // Then there's the output from this method - the stuff we put into the list of fragments. The
4721e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    // fragment.paginationOffset point is the actual physical translation required to get from a
4731e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    // location in the flow thread to a location in a given column. The fragment.paginationClip
4741e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    // rectangle, on the other hand, is in the same coordinate system as the two rectangles passed
4751e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    // to this method (flow thread coordinates).
4761e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    //
4771e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    // All other rectangles in this method are sized physically, and the inline direction coordinate
4781e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    // is physical too, but the block direction coordinate is "logical top". This is the same as
4791e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    // e.g. RenderBox::frameRect(). These rectangles also pretend that there's only one long column,
4801e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    // i.e. they are for the flow thread.
4811e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)
4821e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    // Put the layer bounds into flow thread-local coordinates by flipping it first. Since we're in
4831e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    // a renderer, most rectangles are represented this way.
484926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    LayoutRect layerBoundsInFlowThread(layerBoundingBox);
485926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    flowThread()->flipForWritingMode(layerBoundsInFlowThread);
486926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
487926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // Now we can compare with the flow thread portions owned by each column. First let's
488926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // see if the rect intersects our flow thread portion at all.
489926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    LayoutRect clippedRect(layerBoundsInFlowThread);
490926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    clippedRect.intersect(RenderRegion::flowThreadPortionOverflowRect());
491926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (clippedRect.isEmpty())
492926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
49302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
494926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // Now we know we intersect at least one column. Let's figure out the logical top and logical
495926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // bottom of the area we're checking.
496926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    LayoutUnit layerLogicalTop = isHorizontalWritingMode() ? layerBoundsInFlowThread.y() : layerBoundsInFlowThread.x();
497926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    LayoutUnit layerLogicalBottom = (isHorizontalWritingMode() ? layerBoundsInFlowThread.maxY() : layerBoundsInFlowThread.maxX()) - 1;
49802772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
499926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // Figure out the start and end columns and only check within that range so that we don't walk the
500926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // entire column set.
501926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    unsigned startColumn = columnIndexAtOffset(layerLogicalTop);
502926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    unsigned endColumn = columnIndexAtOffset(layerLogicalBottom);
50302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
504d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    LayoutUnit colLogicalWidth = pageLogicalWidth();
505926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    LayoutUnit colGap = columnGap();
506d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    unsigned colCount = actualColumnCount();
50702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
508197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    RenderMultiColumnFlowThread* flowThread = multiColumnFlowThread();
509197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    bool progressionIsInline = flowThread->progressionIsInline();
510197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    bool leftToRight = style()->isLeftToRightDirection();
511197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
512197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    LayoutUnit initialBlockOffset = logicalTop() - flowThread->logicalTop();
513197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
514926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    for (unsigned i = startColumn; i <= endColumn; i++) {
515926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        // Get the portion of the flow thread that corresponds to this column.
516926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        LayoutRect flowThreadPortion = flowThreadPortionRectAt(i);
51702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
518926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        // Now get the overflow rect that corresponds to the column.
519926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        LayoutRect flowThreadOverflowPortion = flowThreadPortionOverflowRect(flowThreadPortion, i, colCount, colGap);
520926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
521926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        // In order to create a fragment we must intersect the portion painted by this column.
522926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        LayoutRect clippedRect(layerBoundsInFlowThread);
523926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        clippedRect.intersect(flowThreadOverflowPortion);
524926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (clippedRect.isEmpty())
525926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            continue;
52602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
527926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        // We also need to intersect the dirty rect. We have to apply a translation and shift based off
528926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        // our column index.
529926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        LayoutPoint translationOffset;
530197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        LayoutUnit inlineOffset = progressionIsInline ? i * (colLogicalWidth + colGap) : LayoutUnit();
531197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        if (!leftToRight)
532926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            inlineOffset = -inlineOffset;
533926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        translationOffset.setX(inlineOffset);
534197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        LayoutUnit blockOffset;
535197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        if (progressionIsInline) {
536197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            blockOffset = initialBlockOffset + (isHorizontalWritingMode() ? -flowThreadPortion.y() : -flowThreadPortion.x());
537197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        } else {
538197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            // Column gap can apply in the block direction for page fragmentainers.
539197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            // There is currently no spec which calls for column-gap to apply
540197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            // for page fragmentainers at all, but it's applied here for compatibility
541197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            // with the old multicolumn implementation.
542197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            blockOffset = i * colGap;
543197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        }
544926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (isFlippedBlocksWritingMode(style()->writingMode()))
545926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            blockOffset = -blockOffset;
546926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        translationOffset.setY(blockOffset);
547926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (!isHorizontalWritingMode())
548926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            translationOffset = translationOffset.transposedPoint();
549926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        // FIXME: The translation needs to include the multicolumn set's content offset within the
550926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        // multicolumn block as well. This won't be an issue until we start creating multiple multicolumn sets.
551926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
552926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        // Shift the dirty rect to be in flow thread coordinates with this translation applied.
5531e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        LayoutRect translatedDirtyRect(dirtyRect);
554926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        translatedDirtyRect.moveBy(-translationOffset);
55502772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
556926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        // See if we intersect the dirty rect.
5571e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        clippedRect = layerBoundingBox;
558926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        clippedRect.intersect(translatedDirtyRect);
559926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (clippedRect.isEmpty())
560926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            continue;
56102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
562926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        // Something does need to paint in this column. Make a fragment now and supply the physical translation
563926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        // offset and the clip rect for the column with that offset applied.
564926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        LayerFragment fragment;
565926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        fragment.paginationOffset = translationOffset;
56602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
567926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        LayoutRect flippedFlowThreadOverflowPortion(flowThreadOverflowPortion);
5681e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        // Flip it into more a physical (RenderLayer-style) rectangle.
569197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        flowThread->flipForWritingMode(flippedFlowThreadOverflowPortion);
570926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        fragment.paginationClip = flippedFlowThreadOverflowPortion;
571926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        fragments.append(fragment);
572926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
573926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
574926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
575d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)void RenderMultiColumnSet::addOverflowFromChildren()
576d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles){
577d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    unsigned colCount = actualColumnCount();
578d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    if (!colCount)
579d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        return;
580d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)
581d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    LayoutRect lastRect = columnRectAt(colCount - 1);
582d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    addLayoutOverflow(lastRect);
583d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    if (!hasOverflowClip())
584d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        addVisualOverflow(lastRect);
585d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)}
586d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)
5875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)const char* RenderMultiColumnSet::renderName() const
58802772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch{
5895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return "RenderMultiColumnSet";
5905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
592197021e6b966cfb06891637935ef33fff06433d1Ben Murdochvoid RenderMultiColumnSet::insertedIntoTree()
593197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch{
594197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    RenderRegion::insertedIntoTree();
595197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
596197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    attachRegion();
597197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch}
598197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
599197021e6b966cfb06891637935ef33fff06433d1Ben Murdochvoid RenderMultiColumnSet::willBeRemovedFromTree()
600197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch{
601197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    RenderRegion::willBeRemovedFromTree();
602197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
603197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    detachRegion();
604197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch}
605197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
606197021e6b966cfb06891637935ef33fff06433d1Ben Murdochvoid RenderMultiColumnSet::attachRegion()
607197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch{
608197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    if (documentBeingDestroyed())
609197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        return;
610197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
611197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // A region starts off invalid.
612197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    setIsValid(false);
613197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
614197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    if (!m_flowThread)
615197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        return;
616197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
617197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // Only after adding the region to the thread, the region is marked to be valid.
618197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    m_flowThread->addRegionToThread(this);
619197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch}
620197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
621197021e6b966cfb06891637935ef33fff06433d1Ben Murdochvoid RenderMultiColumnSet::detachRegion()
622197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch{
623197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    if (m_flowThread) {
624197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        m_flowThread->removeRegionFromThread(this);
625197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        m_flowThread = 0;
626197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    }
627197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch}
628197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
6295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
630