Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(81)

Side by Side Diff: Source/core/rendering/RenderMultiColumnFlowThread.cpp

Issue 179993006: [New multicol] Eliminate the need for RenderMultiColumnBlock. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Code review Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2012 Apple Inc. All rights reserved. 2 * Copyright (C) 2012 Apple Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 1. Redistributions of source code must retain the above copyright 7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright 9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution. 11 * documentation and/or other materials provided with the distribution.
12 * 12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS IN..0TERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 20 * PROFITS; OR BUSINESS IN..0TERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */ 24 */
25 25
26 #include "config.h" 26 #include "config.h"
27 #include "core/rendering/RenderMultiColumnFlowThread.h" 27 #include "core/rendering/RenderMultiColumnFlowThread.h"
28 28
29 #include "core/rendering/RenderMultiColumnBlock.h"
30 #include "core/rendering/RenderMultiColumnSet.h" 29 #include "core/rendering/RenderMultiColumnSet.h"
31 30
32 namespace WebCore { 31 namespace WebCore {
33 32
34 RenderMultiColumnFlowThread::RenderMultiColumnFlowThread() 33 RenderMultiColumnFlowThread::RenderMultiColumnFlowThread()
34 : m_columnCount(1)
35 , m_columnWidth(0)
36 , m_columnHeightAvailable(0)
37 , m_inBalancingPass(false)
38 , m_needsRebalancing(false)
35 { 39 {
36 setFlowThreadState(InsideInFlowThread); 40 setFlowThreadState(InsideInFlowThread);
37 } 41 }
38 42
39 RenderMultiColumnFlowThread::~RenderMultiColumnFlowThread() 43 RenderMultiColumnFlowThread::~RenderMultiColumnFlowThread()
40 { 44 {
41 } 45 }
42 46
43 RenderMultiColumnFlowThread* RenderMultiColumnFlowThread::createAnonymous(Docume nt* document) 47 RenderMultiColumnFlowThread* RenderMultiColumnFlowThread::createAnonymous(Docume nt& document, RenderStyle* parentStyle)
44 { 48 {
45 RenderMultiColumnFlowThread* renderer = new RenderMultiColumnFlowThread(); 49 RenderMultiColumnFlowThread* renderer = new RenderMultiColumnFlowThread();
46 renderer->setDocumentForAnonymous(document); 50 renderer->setDocumentForAnonymous(&document);
51 renderer->setStyle(RenderStyle::createAnonymousStyleWithDisplay(parentStyle, BLOCK));
47 return renderer; 52 return renderer;
48 } 53 }
49 54
55 void RenderMultiColumnFlowThread::layoutColumns(bool relayoutChildren, SubtreeLa youtScope& layoutScope)
56 {
57 // Update the dimensions of our regions before we lay out the flow thread.
58 // FIXME: Eventually this is going to get way more complicated, and we will be destroying regions
59 // instead of trying to keep them around.
60 RenderBlockFlow* container = multiColumnBlockFlow();
61 bool shouldInvalidateRegions = false;
62 for (RenderBox* childBox = container->firstChildBox(); childBox; childBox = childBox->nextSiblingBox()) {
63 if (childBox == this)
64 continue;
65
66 if (relayoutChildren || childBox->needsLayout()) {
67 if (!m_inBalancingPass && childBox->isRenderMultiColumnSet())
68 toRenderMultiColumnSet(childBox)->prepareForLayout();
69 shouldInvalidateRegions = true;
70 }
71 }
72
73 if (shouldInvalidateRegions)
74 invalidateRegions();
75
76 if (relayoutChildren)
77 layoutScope.setChildNeedsLayout(this);
78
79 if (requiresBalancing()) {
80 // At the end of multicol layout, relayoutForPagination() is called unco nditionally, but if
81 // no children are to be laid out (e.g. fixed width with layout already being up-to-date),
82 // we want to prevent it from doing any work, so that the column balanci ng machinery doesn't
83 // kick in and trigger additional unnecessary layout passes. Actually, i t's not just a good
84 // idea in general to not waste time on balancing content that hasn't be en re-laid out; we
85 // are actually required to guarantee this. The calculation of implicit breaks needs to be
86 // preceded by a proper layout pass, since it's layout that sets up cont ent runs, and the
87 // runs get deleted right after every pass.
88 m_needsRebalancing = shouldInvalidateRegions || needsLayout();
89 }
90
91 layoutIfNeeded();
92 }
93
94 bool RenderMultiColumnFlowThread::computeColumnCountAndWidth()
95 {
96 RenderBlock* columnBlock = multiColumnBlockFlow();
97 LayoutUnit oldColumnWidth = m_columnWidth;
98
99 // Calculate our column width and column count.
100 m_columnCount = 1;
101 m_columnWidth = columnBlock->contentLogicalWidth();
102
103 const RenderStyle* columnStyle = columnBlock->style();
104 ASSERT(!columnStyle->hasAutoColumnCount() || !columnStyle->hasAutoColumnWidt h());
105
106 LayoutUnit availWidth = m_columnWidth;
107 LayoutUnit colGap = columnBlock->columnGap();
108 LayoutUnit colWidth = max<LayoutUnit>(1, LayoutUnit(columnStyle->columnWidth ()));
109 int colCount = max<int>(1, columnStyle->columnCount());
110
111 if (columnStyle->hasAutoColumnWidth() && !columnStyle->hasAutoColumnCount()) {
112 m_columnCount = colCount;
113 m_columnWidth = std::max<LayoutUnit>(0, (availWidth - ((m_columnCount - 1) * colGap)) / m_columnCount);
114 } else if (!columnStyle->hasAutoColumnWidth() && columnStyle->hasAutoColumnC ount()) {
115 m_columnCount = std::max<LayoutUnit>(1, (availWidth + colGap) / (colWidt h + colGap));
116 m_columnWidth = ((availWidth + colGap) / m_columnCount) - colGap;
117 } else {
118 m_columnCount = std::max<LayoutUnit>(std::min<LayoutUnit>(colCount, (ava ilWidth + colGap) / (colWidth + colGap)), 1);
119 m_columnWidth = ((availWidth + colGap) / m_columnCount) - colGap;
120 }
121
122 return m_columnWidth != oldColumnWidth;
123 }
124
125 bool RenderMultiColumnFlowThread::recalculateColumnHeights()
126 {
127 if (!m_needsRebalancing)
128 return false;
129
130 // Column heights may change here because of balancing. We may have to do mu ltiple layout
131 // passes, depending on how the contents is fitted to the changed column hei ghts. In most
132 // cases, laying out again twice or even just once will suffice. Sometimes w e need more
133 // passes than that, though, but the number of retries should not exceed the number of
134 // columns, unless we have a bug.
135 bool needsRelayout = false;
136 for (RenderBox* childBox = multiColumnBlockFlow()->firstChildBox(); childBox ; childBox = childBox->nextSiblingBox()) {
137 if (childBox != this && childBox->isRenderMultiColumnSet()) {
138 RenderMultiColumnSet* multicolSet = toRenderMultiColumnSet(childBox) ;
139 if (multicolSet->recalculateBalancedHeight(!m_inBalancingPass)) {
140 multicolSet->setChildNeedsLayout(MarkOnlyThis);
141 needsRelayout = true;
142 }
143 }
144 }
145
146 if (needsRelayout)
147 setChildNeedsLayout(MarkOnlyThis);
148
149 m_inBalancingPass = needsRelayout;
150 return needsRelayout;
151 }
152
50 const char* RenderMultiColumnFlowThread::renderName() const 153 const char* RenderMultiColumnFlowThread::renderName() const
51 { 154 {
52 return "RenderMultiColumnFlowThread"; 155 return "RenderMultiColumnFlowThread";
53 } 156 }
54 157
55 void RenderMultiColumnFlowThread::computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues& computedValues) const 158 void RenderMultiColumnFlowThread::computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues& computedValues) const
56 { 159 {
57 // We simply remain at our intrinsic height. 160 // We simply remain at our intrinsic height.
58 computedValues.m_extent = logicalHeight; 161 computedValues.m_extent = logicalHeight;
59 computedValues.m_position = logicalTop; 162 computedValues.m_position = logicalTop;
60 } 163 }
61 164
62 LayoutUnit RenderMultiColumnFlowThread::initialLogicalWidth() const 165 LayoutUnit RenderMultiColumnFlowThread::initialLogicalWidth() const
63 { 166 {
64 RenderMultiColumnBlock* parentBlock = toRenderMultiColumnBlock(parent()); 167 return columnWidth();
65 return parentBlock->columnWidth();
66 } 168 }
67 169
68 void RenderMultiColumnFlowThread::autoGenerateRegionsToBlockOffset(LayoutUnit /* offset*/) 170 void RenderMultiColumnFlowThread::autoGenerateRegionsToBlockOffset(LayoutUnit /* offset*/)
69 { 171 {
70 // This function ensures we have the correct column set information at all t imes. 172 // This function ensures we have the correct column set information at all t imes.
71 // For a simple multi-column layout in continuous media, only one column set child is required. 173 // For a simple multi-column layout in continuous media, only one column set child is required.
72 // Once a column is nested inside an enclosing pagination context, the numbe r of column sets 174 // Once a column is nested inside an enclosing pagination context, the numbe r of column sets
73 // required becomes 2n-1, where n is the total number of nested pagination c ontexts. For example: 175 // required becomes 2n-1, where n is the total number of nested pagination c ontexts. For example:
74 // 176 //
75 // Column layout with no enclosing pagination model = 2 * 1 - 1 = 1 column s et. 177 // Column layout with no enclosing pagination model = 2 * 1 - 1 = 1 column s et.
76 // Columns inside pages = 2 * 2 - 1 = 3 column sets (bottom of first page, a ll the subsequent pages, then the last page). 178 // Columns inside pages = 2 * 2 - 1 = 3 column sets (bottom of first page, a ll the subsequent pages, then the last page).
77 // Columns inside columns inside pages = 2 * 3 - 1 = 5 column sets. 179 // Columns inside columns inside pages = 2 * 3 - 1 = 5 column sets.
78 // 180 //
79 // In addition, column spans will force a column set to "split" into before/ after sets around the spanning element. 181 // In addition, column spans will force a column set to "split" into before/ after sets around the spanning element.
80 // 182 //
81 // Finally, we will need to deal with columns inside regions. If regions hav e variable widths, then there will need 183 // Finally, we will need to deal with columns inside regions. If regions hav e variable widths, then there will need
82 // to be unique column sets created inside any region whose width is differe nt from its surrounding regions. This is 184 // to be unique column sets created inside any region whose width is differe nt from its surrounding regions. This is
83 // actually pretty similar to the spanning case, in that we break up the col umn sets whenever the width varies. 185 // actually pretty similar to the spanning case, in that we break up the col umn sets whenever the width varies.
84 // 186 //
85 // FIXME: For now just make one column set. This matches the old multi-colum n code. 187 // FIXME: For now just make one column set. This matches the old multi-colum n code.
86 // Right now our goal is just feature parity with the old multi-column code so that we can switch over to the 188 // Right now our goal is just feature parity with the old multi-column code so that we can switch over to the
87 // new code as soon as possible. 189 // new code as soon as possible.
88 RenderMultiColumnSet* firstSet = toRenderMultiColumnSet(firstRegion()); 190 RenderMultiColumnSet* firstSet = toRenderMultiColumnSet(firstRegion());
89 if (firstSet) 191 if (firstSet)
90 return; 192 return;
91 193
92 invalidateRegions(); 194 invalidateRegions();
93 195
94 RenderMultiColumnBlock* parentBlock = toRenderMultiColumnBlock(parent()); 196 RenderBlockFlow* parentBlock = multiColumnBlockFlow();
95 firstSet = RenderMultiColumnSet::createAnonymous(this); 197 firstSet = RenderMultiColumnSet::createAnonymous(this);
96 firstSet->setStyle(RenderStyle::createAnonymousStyleWithDisplay(parentBlock- >style(), BLOCK)); 198 firstSet->setStyle(RenderStyle::createAnonymousStyleWithDisplay(parentBlock- >style(), BLOCK));
97 parentBlock->RenderBlock::addChild(firstSet); 199 parentBlock->RenderBlock::addChild(firstSet);
98 200
99 // Even though we aren't placed yet, we can go ahead and set up our size. At this point we're 201 // Even though we aren't placed yet, we can go ahead and set up our size. At this point we're
100 // typically in the middle of laying out the thread, attempting to paginate, and we need to do 202 // typically in the middle of laying out the thread, attempting to paginate, and we need to do
101 // some rudimentary "layout" of the set now, so that pagination will work. 203 // some rudimentary "layout" of the set now, so that pagination will work.
102 firstSet->prepareForLayout(); 204 firstSet->prepareForLayout();
103 205
104 validateRegions(); 206 validateRegions();
(...skipping 16 matching lines...) Expand all
121 if (RenderMultiColumnSet* multicolSet = toRenderMultiColumnSet(regionAtBlock Offset(offset))) { 223 if (RenderMultiColumnSet* multicolSet = toRenderMultiColumnSet(regionAtBlock Offset(offset))) {
122 multicolSet->addForcedBreak(offset); 224 multicolSet->addForcedBreak(offset);
123 if (offsetBreakAdjustment) 225 if (offsetBreakAdjustment)
124 *offsetBreakAdjustment = pageLogicalHeightForOffset(offset) ? pageRe mainingLogicalHeightForOffset(offset, IncludePageBoundary) : LayoutUnit(); 226 *offsetBreakAdjustment = pageLogicalHeightForOffset(offset) ? pageRe mainingLogicalHeightForOffset(offset, IncludePageBoundary) : LayoutUnit();
125 return true; 227 return true;
126 } 228 }
127 return false; 229 return false;
128 } 230 }
129 231
130 } 232 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698