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

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

Issue 246403015: [New Multicolumn] Create RenderMultiColumnSet during renderer creation, not during layout. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Rebase master Created 6 years, 8 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
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
45 } 45 }
46 46
47 RenderMultiColumnFlowThread* RenderMultiColumnFlowThread::createAnonymous(Docume nt& document, RenderStyle* parentStyle) 47 RenderMultiColumnFlowThread* RenderMultiColumnFlowThread::createAnonymous(Docume nt& document, RenderStyle* parentStyle)
48 { 48 {
49 RenderMultiColumnFlowThread* renderer = new RenderMultiColumnFlowThread(); 49 RenderMultiColumnFlowThread* renderer = new RenderMultiColumnFlowThread();
50 renderer->setDocumentForAnonymous(&document); 50 renderer->setDocumentForAnonymous(&document);
51 renderer->setStyle(RenderStyle::createAnonymousStyleWithDisplay(parentStyle, BLOCK)); 51 renderer->setStyle(RenderStyle::createAnonymousStyleWithDisplay(parentStyle, BLOCK));
52 return renderer; 52 return renderer;
53 } 53 }
54 54
55 RenderMultiColumnSet* RenderMultiColumnFlowThread::firstMultiColumnSet() const
56 {
57 for (RenderObject* sibling = nextSibling(); sibling; sibling = sibling->next Sibling()) {
58 if (sibling->isRenderMultiColumnSet())
59 return toRenderMultiColumnSet(sibling);
60 }
61 return 0;
62 }
63
64 RenderMultiColumnSet* RenderMultiColumnFlowThread::lastMultiColumnSet() const
65 {
66 for (RenderObject* sibling = multiColumnBlockFlow()->lastChild(); sibling; s ibling = sibling->previousSibling()) {
67 if (sibling->isRenderMultiColumnSet())
68 return toRenderMultiColumnSet(sibling);
69 }
70 return 0;
71 }
72
73 void RenderMultiColumnFlowThread::addChild(RenderObject* newChild, RenderObject* beforeChild)
74 {
75 RenderBlockFlow::addChild(newChild, beforeChild);
76 if (firstMultiColumnSet())
77 return;
78
79 // For now we only create one column set. It's created as soon as the multic ol container gets
80 // any content at all.
81 RenderMultiColumnSet* newSet = RenderMultiColumnSet::createAnonymous(this, m ultiColumnBlockFlow()->style());
82
83 // Need to skip RenderBlockFlow's implementation of addChild(), or we'd get redirected right
84 // back here.
85 multiColumnBlockFlow()->RenderBlock::addChild(newSet);
86
87 invalidateRegions();
88 }
89
55 void RenderMultiColumnFlowThread::populate() 90 void RenderMultiColumnFlowThread::populate()
56 { 91 {
57 RenderBlockFlow* multicolContainer = multiColumnBlockFlow(); 92 RenderBlockFlow* multicolContainer = multiColumnBlockFlow();
58 ASSERT(!nextSibling()); 93 ASSERT(!nextSibling());
59 // Reparent children preceding the flow thread into the flow thread. It's mu lticol content 94 // Reparent children preceding the flow thread into the flow thread. It's mu lticol content
60 // now. At this point there's obviously nothing after the flow thread, but r enderers (column 95 // now. At this point there's obviously nothing after the flow thread, but r enderers (column
61 // sets and spanners) will be inserted there as we insert elements into the flow thread. 96 // sets and spanners) will be inserted there as we insert elements into the flow thread.
62 multicolContainer->moveChildrenTo(this, multicolContainer->firstChild(), thi s, true); 97 multicolContainer->moveChildrenTo(this, multicolContainer->firstChild(), thi s, true);
63 } 98 }
64 99
65 void RenderMultiColumnFlowThread::evacuateAndDestroy() 100 void RenderMultiColumnFlowThread::evacuateAndDestroy()
66 { 101 {
67 RenderBlockFlow* multicolContainer = multiColumnBlockFlow(); 102 RenderBlockFlow* multicolContainer = multiColumnBlockFlow();
68 103
69 // Remove all sets. 104 // Remove all sets.
70 for (RenderBox* sibling = nextSiblingBox(); sibling;) { 105 while (RenderMultiColumnSet* columnSet = firstMultiColumnSet())
71 RenderBox* nextSibling = sibling->nextSiblingBox(); 106 columnSet->destroy();
72 if (sibling->isRenderMultiColumnSet())
73 sibling->destroy();
74 sibling = nextSibling;
75 }
76 107
77 ASSERT(!previousSibling()); 108 ASSERT(!previousSibling());
78 ASSERT(!nextSibling()); 109 ASSERT(!nextSibling());
79 110
80 // Finally we can promote all flow thread's children. Before we move them to the flow thread's 111 // Finally we can promote all flow thread's children. Before we move them to the flow thread's
81 // container, we need to unregister the flow thread, so that they aren't jus t re-added again to 112 // container, we need to unregister the flow thread, so that they aren't jus t re-added again to
82 // the flow thread that we're trying to empty. 113 // the flow thread that we're trying to empty.
83 multicolContainer->resetMultiColumnFlowThread(); 114 multicolContainer->resetMultiColumnFlowThread();
84 moveAllChildrenTo(multicolContainer, true); 115 moveAllChildrenTo(multicolContainer, true);
85 116
86 // FIXME: it's scary that neither destroy() nor the move*Children* methods t ake care of this, 117 // FIXME: it's scary that neither destroy() nor the move*Children* methods t ake care of this,
87 // and instead leave you with dangling root line box pointers. But since thi s is how it is done 118 // and instead leave you with dangling root line box pointers. But since thi s is how it is done
88 // in other parts of the code that deal with reparenting renderers, let's do the cleanup on our 119 // in other parts of the code that deal with reparenting renderers, let's do the cleanup on our
89 // own here as well. 120 // own here as well.
90 deleteLineBoxTree(); 121 deleteLineBoxTree();
91 122
92 destroy(); 123 destroy();
93 } 124 }
94 125
95 void RenderMultiColumnFlowThread::layoutColumns(bool relayoutChildren, SubtreeLa youtScope& layoutScope) 126 void RenderMultiColumnFlowThread::layoutColumns(bool relayoutChildren, SubtreeLa youtScope& layoutScope)
96 { 127 {
97 // Update the dimensions of our regions before we lay out the flow thread. 128 // Update the dimensions of our regions before we lay out the flow thread.
98 // FIXME: Eventually this is going to get way more complicated, and we will be destroying regions 129 // FIXME: Eventually this is going to get way more complicated, and we will be destroying regions
99 // instead of trying to keep them around. 130 // instead of trying to keep them around.
100 RenderBlockFlow* container = multiColumnBlockFlow();
101 bool shouldInvalidateRegions = false; 131 bool shouldInvalidateRegions = false;
102 for (RenderBox* childBox = container->firstChildBox(); childBox; childBox = childBox->nextSiblingBox()) { 132 for (RenderMultiColumnSet* columnSet = firstMultiColumnSet(); columnSet; col umnSet = columnSet->nextSiblingMultiColumnSet()) {
103 if (childBox == this) 133 if (relayoutChildren || columnSet->needsLayout()) {
104 continue; 134 if (!m_inBalancingPass)
105 135 columnSet->prepareForLayout();
106 if (relayoutChildren || childBox->needsLayout()) {
107 if (!m_inBalancingPass && childBox->isRenderMultiColumnSet())
108 toRenderMultiColumnSet(childBox)->prepareForLayout();
109 shouldInvalidateRegions = true; 136 shouldInvalidateRegions = true;
110 } 137 }
111 } 138 }
112 139
113 if (shouldInvalidateRegions) 140 if (shouldInvalidateRegions)
114 invalidateRegions(); 141 invalidateRegions();
115 142
116 if (relayoutChildren) 143 if (relayoutChildren)
117 layoutScope.setChildNeedsLayout(this); 144 layoutScope.setChildNeedsLayout(this);
118 145
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
166 { 193 {
167 if (!m_needsRebalancing) 194 if (!m_needsRebalancing)
168 return false; 195 return false;
169 196
170 // Column heights may change here because of balancing. We may have to do mu ltiple layout 197 // Column heights may change here because of balancing. We may have to do mu ltiple layout
171 // passes, depending on how the contents is fitted to the changed column hei ghts. In most 198 // passes, depending on how the contents is fitted to the changed column hei ghts. In most
172 // cases, laying out again twice or even just once will suffice. Sometimes w e need more 199 // cases, laying out again twice or even just once will suffice. Sometimes w e need more
173 // passes than that, though, but the number of retries should not exceed the number of 200 // passes than that, though, but the number of retries should not exceed the number of
174 // columns, unless we have a bug. 201 // columns, unless we have a bug.
175 bool needsRelayout = false; 202 bool needsRelayout = false;
176 for (RenderBox* childBox = multiColumnBlockFlow()->firstChildBox(); childBox ; childBox = childBox->nextSiblingBox()) { 203 for (RenderMultiColumnSet* multicolSet = firstMultiColumnSet(); multicolSet; multicolSet = multicolSet->nextSiblingMultiColumnSet()) {
177 if (childBox != this && childBox->isRenderMultiColumnSet()) { 204 if (multicolSet->recalculateBalancedHeight(!m_inBalancingPass)) {
178 RenderMultiColumnSet* multicolSet = toRenderMultiColumnSet(childBox) ; 205 multicolSet->setChildNeedsLayout(MarkOnlyThis);
179 if (multicolSet->recalculateBalancedHeight(!m_inBalancingPass)) { 206 needsRelayout = true;
180 multicolSet->setChildNeedsLayout(MarkOnlyThis);
181 needsRelayout = true;
182 }
183 } 207 }
184 } 208 }
185 209
186 if (needsRelayout) 210 if (needsRelayout)
187 setChildNeedsLayout(MarkOnlyThis); 211 setChildNeedsLayout(MarkOnlyThis);
188 212
189 m_inBalancingPass = needsRelayout; 213 m_inBalancingPass = needsRelayout;
190 return needsRelayout; 214 return needsRelayout;
191 } 215 }
192 216
193 const char* RenderMultiColumnFlowThread::renderName() const 217 const char* RenderMultiColumnFlowThread::renderName() const
194 { 218 {
195 return "RenderMultiColumnFlowThread"; 219 return "RenderMultiColumnFlowThread";
196 } 220 }
197 221
222 void RenderMultiColumnFlowThread::addRegionToThread(RenderRegion* renderRegion)
223 {
224 RenderMultiColumnSet* columnSet = toRenderMultiColumnSet(renderRegion);
225 if (RenderMultiColumnSet* nextSet = columnSet->nextSiblingMultiColumnSet()) {
226 RenderRegionList::iterator it = m_regionList.find(nextSet);
227 ASSERT(it != m_regionList.end());
228 m_regionList.insertBefore(it, columnSet);
229 } else {
230 m_regionList.add(columnSet);
231 }
232 renderRegion->setIsValid(true);
233 }
234
235 void RenderMultiColumnFlowThread::willBeRemovedFromTree()
236 {
237 // Detach all column sets from the flow thread. Cannot destroy them at this point, since they
238 // are siblings of this object, and there may be pointers to this object's s ibling somewhere
239 // further up on the call stack.
240 for (RenderMultiColumnSet* columnSet = firstMultiColumnSet(); columnSet; col umnSet = columnSet->nextSiblingMultiColumnSet())
241 columnSet->detachRegion();
242 multiColumnBlockFlow()->resetMultiColumnFlowThread();
243 RenderFlowThread::willBeRemovedFromTree();
244 }
245
198 void RenderMultiColumnFlowThread::computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues& computedValues) const 246 void RenderMultiColumnFlowThread::computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues& computedValues) const
199 { 247 {
200 // We simply remain at our intrinsic height. 248 // We simply remain at our intrinsic height.
201 computedValues.m_extent = logicalHeight; 249 computedValues.m_extent = logicalHeight;
202 computedValues.m_position = logicalTop; 250 computedValues.m_position = logicalTop;
203 } 251 }
204 252
205 LayoutUnit RenderMultiColumnFlowThread::initialLogicalWidth() const 253 LayoutUnit RenderMultiColumnFlowThread::initialLogicalWidth() const
206 { 254 {
207 return columnWidth(); 255 return columnWidth();
208 } 256 }
209 257
210 void RenderMultiColumnFlowThread::autoGenerateRegionsToBlockOffset(LayoutUnit /* offset*/)
211 {
212 // This function ensures we have the correct column set information at all t imes.
213 // For a simple multi-column layout in continuous media, only one column set child is required.
214 // Once a column is nested inside an enclosing pagination context, the numbe r of column sets
215 // required becomes 2n-1, where n is the total number of nested pagination c ontexts. For example:
216 //
217 // Column layout with no enclosing pagination model = 2 * 1 - 1 = 1 column s et.
218 // Columns inside pages = 2 * 2 - 1 = 3 column sets (bottom of first page, a ll the subsequent pages, then the last page).
219 // Columns inside columns inside pages = 2 * 3 - 1 = 5 column sets.
220 //
221 // In addition, column spans will force a column set to "split" into before/ after sets around the spanning element.
222 //
223 // Finally, we will need to deal with columns inside regions. If regions hav e variable widths, then there will need
224 // to be unique column sets created inside any region whose width is differe nt from its surrounding regions. This is
225 // actually pretty similar to the spanning case, in that we break up the col umn sets whenever the width varies.
226 //
227 // FIXME: For now just make one column set. This matches the old multi-colum n code.
228 // Right now our goal is just feature parity with the old multi-column code so that we can switch over to the
229 // new code as soon as possible.
230 RenderMultiColumnSet* firstSet = toRenderMultiColumnSet(firstRegion());
231 if (firstSet)
232 return;
233
234 invalidateRegions();
235
236 RenderBlockFlow* parentBlock = multiColumnBlockFlow();
237 firstSet = RenderMultiColumnSet::createAnonymous(this);
238 firstSet->setStyle(RenderStyle::createAnonymousStyleWithDisplay(parentBlock- >style(), BLOCK));
239 parentBlock->RenderBlock::addChild(firstSet);
240
241 // Even though we aren't placed yet, we can go ahead and set up our size. At this point we're
242 // typically in the middle of laying out the thread, attempting to paginate, and we need to do
243 // some rudimentary "layout" of the set now, so that pagination will work.
244 firstSet->prepareForLayout();
245
246 validateRegions();
247 }
248
249 void RenderMultiColumnFlowThread::setPageBreak(LayoutUnit offset, LayoutUnit spa ceShortage) 258 void RenderMultiColumnFlowThread::setPageBreak(LayoutUnit offset, LayoutUnit spa ceShortage)
250 { 259 {
251 if (RenderMultiColumnSet* multicolSet = toRenderMultiColumnSet(regionAtBlock Offset(offset))) 260 if (RenderMultiColumnSet* multicolSet = toRenderMultiColumnSet(regionAtBlock Offset(offset)))
252 multicolSet->recordSpaceShortage(spaceShortage); 261 multicolSet->recordSpaceShortage(spaceShortage);
253 } 262 }
254 263
255 void RenderMultiColumnFlowThread::updateMinimumPageHeight(LayoutUnit offset, Lay outUnit minHeight) 264 void RenderMultiColumnFlowThread::updateMinimumPageHeight(LayoutUnit offset, Lay outUnit minHeight)
256 { 265 {
257 if (RenderMultiColumnSet* multicolSet = toRenderMultiColumnSet(regionAtBlock Offset(offset))) 266 if (RenderMultiColumnSet* multicolSet = toRenderMultiColumnSet(regionAtBlock Offset(offset)))
258 multicolSet->updateMinimumColumnHeight(minHeight); 267 multicolSet->updateMinimumColumnHeight(minHeight);
259 } 268 }
260 269
270 RenderRegion* RenderMultiColumnFlowThread::regionAtBlockOffset(LayoutUnit /*offs et*/) const
271 {
272 // For now there's only one column set, so this is easy:
273 return firstMultiColumnSet();
274 }
275
261 bool RenderMultiColumnFlowThread::addForcedRegionBreak(LayoutUnit offset, Render Object* /*breakChild*/, bool /*isBefore*/, LayoutUnit* offsetBreakAdjustment) 276 bool RenderMultiColumnFlowThread::addForcedRegionBreak(LayoutUnit offset, Render Object* /*breakChild*/, bool /*isBefore*/, LayoutUnit* offsetBreakAdjustment)
262 { 277 {
263 if (RenderMultiColumnSet* multicolSet = toRenderMultiColumnSet(regionAtBlock Offset(offset))) { 278 if (RenderMultiColumnSet* multicolSet = toRenderMultiColumnSet(regionAtBlock Offset(offset))) {
264 multicolSet->addForcedBreak(offset); 279 multicolSet->addForcedBreak(offset);
265 if (offsetBreakAdjustment) 280 if (offsetBreakAdjustment)
266 *offsetBreakAdjustment = pageLogicalHeightForOffset(offset) ? pageRe mainingLogicalHeightForOffset(offset, IncludePageBoundary) : LayoutUnit(); 281 *offsetBreakAdjustment = pageLogicalHeightForOffset(offset) ? pageRe mainingLogicalHeightForOffset(offset, IncludePageBoundary) : LayoutUnit();
267 return true; 282 return true;
268 } 283 }
269 return false; 284 return false;
270 } 285 }
271 286
272 bool RenderMultiColumnFlowThread::isPageLogicalHeightKnown() const 287 bool RenderMultiColumnFlowThread::isPageLogicalHeightKnown() const
273 { 288 {
274 for (RenderBox* renderer = parentBox()->lastChildBox(); renderer; renderer = renderer->previousSiblingBox()) { 289 if (RenderMultiColumnSet* columnSet = lastMultiColumnSet())
275 if (renderer->isRenderMultiColumnSet()) 290 return columnSet->computedColumnHeight();
276 return toRenderMultiColumnSet(renderer)->computedColumnHeight(); 291 return false;
277 }
278 // A column set hasn't been created yet. Height may already be known if colu mn-fill is 'auto', though.
279 return !requiresBalancing();
280 } 292 }
281 293
282 } 294 }
OLDNEW
« no previous file with comments | « Source/core/rendering/RenderMultiColumnFlowThread.h ('k') | Source/core/rendering/RenderMultiColumnSet.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698