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 IN..0TERRUPTION) 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/RenderMultiColumnFlowThread.h"
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/RenderMultiColumnSet.h"
30926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
31c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink {
325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)RenderMultiColumnFlowThread::RenderMultiColumnFlowThread()
34d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    : m_columnCount(1)
35d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    , m_columnHeightAvailable(0)
36d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    , m_inBalancingPass(false)
37323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    , m_needsColumnHeightsRecalculation(false)
38197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    , m_progressionIsInline(true)
395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
40926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    setFlowThreadState(InsideInFlowThread);
415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)RenderMultiColumnFlowThread::~RenderMultiColumnFlowThread()
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
47d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)RenderMultiColumnFlowThread* RenderMultiColumnFlowThread::createAnonymous(Document& document, RenderStyle* parentStyle)
4853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
49f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    RenderMultiColumnFlowThread* renderer = new RenderMultiColumnFlowThread();
50d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    renderer->setDocumentForAnonymous(&document);
51d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    renderer->setStyle(RenderStyle::createAnonymousStyleWithDisplay(parentStyle, BLOCK));
5253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    return renderer;
5353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
5453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
55f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo LiuRenderMultiColumnSet* RenderMultiColumnFlowThread::firstMultiColumnSet() const
56f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu{
57f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    for (RenderObject* sibling = nextSibling(); sibling; sibling = sibling->nextSibling()) {
58f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        if (sibling->isRenderMultiColumnSet())
59f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            return toRenderMultiColumnSet(sibling);
60f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    }
61f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    return 0;
62f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu}
63f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu
64f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo LiuRenderMultiColumnSet* RenderMultiColumnFlowThread::lastMultiColumnSet() const
65f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu{
66f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    for (RenderObject* sibling = multiColumnBlockFlow()->lastChild(); sibling; sibling = sibling->previousSibling()) {
67f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        if (sibling->isRenderMultiColumnSet())
68f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            return toRenderMultiColumnSet(sibling);
69f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    }
70f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    return 0;
71f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu}
72f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu
73f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liuvoid RenderMultiColumnFlowThread::addChild(RenderObject* newChild, RenderObject* beforeChild)
74f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu{
75f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    RenderBlockFlow::addChild(newChild, beforeChild);
76f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    if (firstMultiColumnSet())
77f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        return;
78f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu
79f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    // For now we only create one column set. It's created as soon as the multicol container gets
80f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    // any content at all.
81f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    RenderMultiColumnSet* newSet = RenderMultiColumnSet::createAnonymous(this, multiColumnBlockFlow()->style());
82f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu
83f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    // Need to skip RenderBlockFlow's implementation of addChild(), or we'd get redirected right
84f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    // back here.
85f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    multiColumnBlockFlow()->RenderBlock::addChild(newSet);
86f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu
87f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    invalidateRegions();
88f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu}
89f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu
906f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdochvoid RenderMultiColumnFlowThread::populate()
916f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch{
926f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    RenderBlockFlow* multicolContainer = multiColumnBlockFlow();
936f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    ASSERT(!nextSibling());
946f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    // Reparent children preceding the flow thread into the flow thread. It's multicol content
956f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    // now. At this point there's obviously nothing after the flow thread, but renderers (column
966f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    // sets and spanners) will be inserted there as we insert elements into the flow thread.
976f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    multicolContainer->moveChildrenTo(this, multicolContainer->firstChild(), this, true);
986f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch}
996f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch
1006f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdochvoid RenderMultiColumnFlowThread::evacuateAndDestroy()
1016f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch{
1026f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    RenderBlockFlow* multicolContainer = multiColumnBlockFlow();
1036f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch
1046f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    // Remove all sets.
105f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    while (RenderMultiColumnSet* columnSet = firstMultiColumnSet())
106f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        columnSet->destroy();
1076f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch
1086f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    ASSERT(!previousSibling());
1096f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    ASSERT(!nextSibling());
1106f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch
1116f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    // Finally we can promote all flow thread's children. Before we move them to the flow thread's
1126f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    // container, we need to unregister the flow thread, so that they aren't just re-added again to
1136f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    // the flow thread that we're trying to empty.
1146f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    multicolContainer->resetMultiColumnFlowThread();
1156f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    moveAllChildrenTo(multicolContainer, true);
1166f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch
11710f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    // FIXME: it's scary that neither destroy() nor the move*Children* methods take care of this,
11810f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    // and instead leave you with dangling root line box pointers. But since this is how it is done
11910f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    // in other parts of the code that deal with reparenting renderers, let's do the cleanup on our
12010f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    // own here as well.
12110f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    deleteLineBoxTree();
12210f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch
1236f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    destroy();
1246f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch}
1256f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch
126f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo LiuLayoutSize RenderMultiColumnFlowThread::columnOffset(const LayoutPoint& point) const
127f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu{
128f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    if (!hasValidRegionInfo())
129f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        return LayoutSize(0, 0);
130f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu
131f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    LayoutPoint flowThreadPoint(point);
132f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    flipForWritingMode(flowThreadPoint);
133f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    LayoutUnit blockOffset = isHorizontalWritingMode() ? flowThreadPoint.y() : flowThreadPoint.x();
134197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    RenderMultiColumnSet* columnSet = columnSetAtBlockOffset(blockOffset);
135197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    if (!columnSet)
136f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        return LayoutSize(0, 0);
137197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    return columnSet->flowThreadTranslationAtOffset(blockOffset);
138f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu}
139f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu
140d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)bool RenderMultiColumnFlowThread::needsNewWidth() const
141d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
142d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    LayoutUnit newWidth;
143d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    unsigned dummyColumnCount; // We only care if used column-width changes.
144d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    calculateColumnCountAndWidth(newWidth, dummyColumnCount);
145d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    return newWidth != logicalWidth();
146d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)}
147d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
148d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)void RenderMultiColumnFlowThread::layoutColumns(bool relayoutChildren, SubtreeLayoutScope& layoutScope)
149d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles){
150d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (relayoutChildren)
151d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        layoutScope.setChildNeedsLayout(this);
152d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
153d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    if (!needsLayout()) {
154d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        // Just before the multicol container (our parent RenderBlockFlow) finishes laying out, it
155d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        // will call recalculateColumnHeights() on us unconditionally, but we only want that method
156d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        // to do any work if we actually laid out the flow thread. Otherwise, the balancing
157d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        // machinery would kick in needlessly, and trigger additional layout passes. Furthermore, we
158d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        // actually depend on a proper flowthread layout pass in order to do balancing, since it's
159d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        // flowthread layout that sets up content runs.
160d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        m_needsColumnHeightsRecalculation = false;
161d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        return;
162d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    }
163d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
164d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    for (RenderMultiColumnSet* columnSet = firstMultiColumnSet(); columnSet; columnSet = columnSet->nextSiblingMultiColumnSet()) {
165d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        if (!m_inBalancingPass) {
166d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            // This is the initial layout pass. We need to reset the column height, because contents
167d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            // typically have changed.
168d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            columnSet->resetColumnHeight();
169d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        }
170d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    }
171d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
172d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    invalidateRegions();
173197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    m_needsColumnHeightsRecalculation = heightIsAuto();
174d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    layout();
175d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
176d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
177d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)bool RenderMultiColumnFlowThread::recalculateColumnHeights()
178d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
179d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    // All column sets that needed layout have now been laid out, so we can finally validate them.
180d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    validateRegions();
181d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)
182323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    if (!m_needsColumnHeightsRecalculation)
183d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return false;
184d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
185d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // Column heights may change here because of balancing. We may have to do multiple layout
186d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // passes, depending on how the contents is fitted to the changed column heights. In most
187d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // cases, laying out again twice or even just once will suffice. Sometimes we need more
188d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // passes than that, though, but the number of retries should not exceed the number of
189d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // columns, unless we have a bug.
190d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    bool needsRelayout = false;
191f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    for (RenderMultiColumnSet* multicolSet = firstMultiColumnSet(); multicolSet; multicolSet = multicolSet->nextSiblingMultiColumnSet()) {
192d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        needsRelayout |= multicolSet->recalculateColumnHeight(m_inBalancingPass ? RenderMultiColumnSet::StretchBySpaceShortage : RenderMultiColumnSet::GuessFromFlowThreadPortion);
193d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        if (needsRelayout) {
194d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            // Once a column set gets a new column height, that column set and all successive column
195d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            // sets need to be laid out over again, since their logical top will be affected by
196d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            // this, and therefore their column heights may change as well, at least if the multicol
197d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            // height is constrained.
198f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            multicolSet->setChildNeedsLayout(MarkOnlyThis);
199d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        }
200d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    }
201d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
202d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (needsRelayout)
203d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        setChildNeedsLayout(MarkOnlyThis);
204d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
205d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    m_inBalancingPass = needsRelayout;
206d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    return needsRelayout;
207d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
208d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
209d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)void RenderMultiColumnFlowThread::calculateColumnCountAndWidth(LayoutUnit& width, unsigned& count) const
210d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles){
211d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    RenderBlock* columnBlock = multiColumnBlockFlow();
212d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    const RenderStyle* columnStyle = columnBlock->style();
213d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    LayoutUnit availableWidth = columnBlock->contentLogicalWidth();
214d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    LayoutUnit columnGap = columnBlock->columnGap();
215d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    LayoutUnit computedColumnWidth = max<LayoutUnit>(1, LayoutUnit(columnStyle->columnWidth()));
216d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    unsigned computedColumnCount = max<int>(1, columnStyle->columnCount());
217d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)
218d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    ASSERT(!columnStyle->hasAutoColumnCount() || !columnStyle->hasAutoColumnWidth());
219d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    if (columnStyle->hasAutoColumnWidth() && !columnStyle->hasAutoColumnCount()) {
220d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        count = computedColumnCount;
221d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        width = std::max<LayoutUnit>(0, (availableWidth - ((count - 1) * columnGap)) / count);
222d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    } else if (!columnStyle->hasAutoColumnWidth() && columnStyle->hasAutoColumnCount()) {
223d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        count = std::max<LayoutUnit>(1, (availableWidth + columnGap) / (computedColumnWidth + columnGap));
224d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        width = ((availableWidth + columnGap) / count) - columnGap;
225d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    } else {
226d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        count = std::max<LayoutUnit>(std::min<LayoutUnit>(computedColumnCount, (availableWidth + columnGap) / (computedColumnWidth + columnGap)), 1);
227d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        width = ((availableWidth + columnGap) / count) - columnGap;
228d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    }
229d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)}
230d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)
2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)const char* RenderMultiColumnFlowThread::renderName() const
23202772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch{
2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return "RenderMultiColumnFlowThread";
2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
236197021e6b966cfb06891637935ef33fff06433d1Ben Murdochvoid RenderMultiColumnFlowThread::addRegionToThread(RenderMultiColumnSet* columnSet)
237f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu{
238f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    if (RenderMultiColumnSet* nextSet = columnSet->nextSiblingMultiColumnSet()) {
239197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        RenderMultiColumnSetList::iterator it = m_multiColumnSetList.find(nextSet);
240197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        ASSERT(it != m_multiColumnSetList.end());
241197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        m_multiColumnSetList.insertBefore(it, columnSet);
242f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    } else {
243197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        m_multiColumnSetList.add(columnSet);
244f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    }
245197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    columnSet->setIsValid(true);
246f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu}
247f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu
248f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liuvoid RenderMultiColumnFlowThread::willBeRemovedFromTree()
249f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu{
250f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    // Detach all column sets from the flow thread. Cannot destroy them at this point, since they
251f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    // are siblings of this object, and there may be pointers to this object's sibling somewhere
252f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    // further up on the call stack.
253f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    for (RenderMultiColumnSet* columnSet = firstMultiColumnSet(); columnSet; columnSet = columnSet->nextSiblingMultiColumnSet())
254f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        columnSet->detachRegion();
255f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    multiColumnBlockFlow()->resetMultiColumnFlowThread();
256f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    RenderFlowThread::willBeRemovedFromTree();
257f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu}
258f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu
2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderMultiColumnFlowThread::computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues& computedValues) const
2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // We simply remain at our intrinsic height.
2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    computedValues.m_extent = logicalHeight;
2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    computedValues.m_position = logicalTop;
2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
266323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)void RenderMultiColumnFlowThread::updateLogicalWidth()
267926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
268d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    LayoutUnit columnWidth;
269d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    calculateColumnCountAndWidth(columnWidth, m_columnCount);
270d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    setLogicalWidth(columnWidth);
271323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)}
272323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)
273323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)void RenderMultiColumnFlowThread::layout()
274323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles){
275323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    RenderFlowThread::layout();
276323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    if (RenderMultiColumnSet* lastSet = lastMultiColumnSet())
277323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        lastSet->expandToEncompassFlowThreadContentsIfNeeded();
278926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
279926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
280591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochvoid RenderMultiColumnFlowThread::setPageBreak(LayoutUnit offset, LayoutUnit spaceShortage)
281591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
282d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    // Only positive values are interesting (and allowed) here. Zero space shortage may be reported
283d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    // when we're at the top of a column and the element has zero height. Ignore this, and also
284d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    // ignore any negative values, which may occur when we set an early break in order to honor
285d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    // widows in the next column.
286d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    if (spaceShortage <= 0)
287d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        return;
288d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)
289197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    if (RenderMultiColumnSet* multicolSet = columnSetAtBlockOffset(offset))
290591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        multicolSet->recordSpaceShortage(spaceShortage);
291591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
292591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
293591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochvoid RenderMultiColumnFlowThread::updateMinimumPageHeight(LayoutUnit offset, LayoutUnit minHeight)
294591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
295197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    if (RenderMultiColumnSet* multicolSet = columnSetAtBlockOffset(offset))
296591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        multicolSet->updateMinimumColumnHeight(minHeight);
297591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
298591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
299197021e6b966cfb06891637935ef33fff06433d1Ben MurdochRenderMultiColumnSet* RenderMultiColumnFlowThread::columnSetAtBlockOffset(LayoutUnit /*offset*/) const
300f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu{
301f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    // For now there's only one column set, so this is easy:
302f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    return firstMultiColumnSet();
303f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu}
304f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu
30509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)bool RenderMultiColumnFlowThread::addForcedRegionBreak(LayoutUnit offset, RenderObject* /*breakChild*/, bool /*isBefore*/, LayoutUnit* offsetBreakAdjustment)
30609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
307197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    if (RenderMultiColumnSet* multicolSet = columnSetAtBlockOffset(offset)) {
308d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        multicolSet->addContentRun(offset);
30909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        if (offsetBreakAdjustment)
31009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            *offsetBreakAdjustment = pageLogicalHeightForOffset(offset) ? pageRemainingLogicalHeightForOffset(offset, IncludePageBoundary) : LayoutUnit();
31109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return true;
31209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
31309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return false;
31409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
31509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
31607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdochbool RenderMultiColumnFlowThread::isPageLogicalHeightKnown() const
31707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch{
318f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    if (RenderMultiColumnSet* columnSet = lastMultiColumnSet())
319d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        return columnSet->pageLogicalHeight();
320f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    return false;
32107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch}
32207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
3235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
324