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

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: 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 multiColumnBlockFlow()->RenderBlock::addChild(newSet);
ojan 2014/04/24 21:38:43 Why do we need the RenderBlock version? Can the mu
mstensho (USE GERRIT) 2014/04/24 22:22:22 Yes, multiColumnBlockFlow() is the one that has a
83 invalidateRegions();
84 }
85
55 void RenderMultiColumnFlowThread::populate() 86 void RenderMultiColumnFlowThread::populate()
56 { 87 {
57 RenderBlockFlow* multicolContainer = multiColumnBlockFlow(); 88 RenderBlockFlow* multicolContainer = multiColumnBlockFlow();
58 ASSERT(!nextSibling()); 89 ASSERT(!nextSibling());
59 // Reparent children preceding the flow thread into the flow thread. It's mu lticol content 90 // 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 91 // 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. 92 // sets and spanners) will be inserted there as we insert elements into the flow thread.
62 multicolContainer->moveChildrenTo(this, multicolContainer->firstChild(), thi s, true); 93 multicolContainer->moveChildrenTo(this, multicolContainer->firstChild(), thi s, true);
63 } 94 }
64 95
65 void RenderMultiColumnFlowThread::evacuateAndDestroy() 96 void RenderMultiColumnFlowThread::evacuateAndDestroy()
66 { 97 {
67 RenderBlockFlow* multicolContainer = multiColumnBlockFlow(); 98 RenderBlockFlow* multicolContainer = multiColumnBlockFlow();
68 99
69 // Remove all sets. 100 // Remove all sets.
70 for (RenderBox* sibling = nextSiblingBox(); sibling;) { 101 while (RenderMultiColumnSet* columnSet = firstMultiColumnSet())
ojan 2014/04/24 21:38:43 How do we have multiple sets? It looks like addChi
mstensho (USE GERRIT) 2014/04/24 22:22:22 For now, only one set. In the (near) future, we ca
ojan 2014/04/24 22:46:59 It's just a bit weird to me to have a while loop t
71 RenderBox* nextSibling = sibling->nextSiblingBox(); 102 columnSet->destroy();
72 if (sibling->isRenderMultiColumnSet())
73 sibling->destroy();
74 sibling = nextSibling;
75 }
76 103
77 ASSERT(!previousSibling()); 104 ASSERT(!previousSibling());
78 ASSERT(!nextSibling()); 105 ASSERT(!nextSibling());
79 106
80 // Finally we can promote all flow thread's children. Before we move them to the flow thread's 107 // 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 108 // 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. 109 // the flow thread that we're trying to empty.
83 multicolContainer->resetMultiColumnFlowThread(); 110 multicolContainer->resetMultiColumnFlowThread();
84 moveAllChildrenTo(multicolContainer, true); 111 moveAllChildrenTo(multicolContainer, true);
85 112
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
160 { 187 {
161 if (!m_needsRebalancing) 188 if (!m_needsRebalancing)
162 return false; 189 return false;
163 190
164 // Column heights may change here because of balancing. We may have to do mu ltiple layout 191 // Column heights may change here because of balancing. We may have to do mu ltiple layout
165 // passes, depending on how the contents is fitted to the changed column hei ghts. In most 192 // passes, depending on how the contents is fitted to the changed column hei ghts. In most
166 // cases, laying out again twice or even just once will suffice. Sometimes w e need more 193 // cases, laying out again twice or even just once will suffice. Sometimes w e need more
167 // passes than that, though, but the number of retries should not exceed the number of 194 // passes than that, though, but the number of retries should not exceed the number of
168 // columns, unless we have a bug. 195 // columns, unless we have a bug.
169 bool needsRelayout = false; 196 bool needsRelayout = false;
170 for (RenderBox* childBox = multiColumnBlockFlow()->firstChildBox(); childBox ; childBox = childBox->nextSiblingBox()) { 197 for (RenderMultiColumnSet* multicolSet = firstMultiColumnSet(); multicolSet; multicolSet = multicolSet->nextSiblingMultiColumnSet()) {
171 if (childBox != this && childBox->isRenderMultiColumnSet()) { 198 if (multicolSet->recalculateBalancedHeight(!m_inBalancingPass)) {
172 RenderMultiColumnSet* multicolSet = toRenderMultiColumnSet(childBox) ; 199 multicolSet->setChildNeedsLayout(MarkOnlyThis);
173 if (multicolSet->recalculateBalancedHeight(!m_inBalancingPass)) { 200 needsRelayout = true;
174 multicolSet->setChildNeedsLayout(MarkOnlyThis);
175 needsRelayout = true;
176 }
177 } 201 }
178 } 202 }
179 203
180 if (needsRelayout) 204 if (needsRelayout)
181 setChildNeedsLayout(MarkOnlyThis); 205 setChildNeedsLayout(MarkOnlyThis);
182 206
183 m_inBalancingPass = needsRelayout; 207 m_inBalancingPass = needsRelayout;
184 return needsRelayout; 208 return needsRelayout;
185 } 209 }
186 210
187 const char* RenderMultiColumnFlowThread::renderName() const 211 const char* RenderMultiColumnFlowThread::renderName() const
188 { 212 {
189 return "RenderMultiColumnFlowThread"; 213 return "RenderMultiColumnFlowThread";
190 } 214 }
191 215
216 void RenderMultiColumnFlowThread::addRegionToThread(RenderRegion* renderRegion)
217 {
218 RenderMultiColumnSet* columnSet = toRenderMultiColumnSet(renderRegion);
219 if (RenderMultiColumnSet* nextSet = columnSet->nextSiblingMultiColumnSet()) {
220 RenderRegionList::iterator it = m_regionList.find(nextSet);
221 ASSERT(it != m_regionList.end());
222 m_regionList.insertBefore(it, columnSet);
223 } else {
224 m_regionList.add(columnSet);
225 }
226 renderRegion->setIsValid(true);
227 }
228
229 void RenderMultiColumnFlowThread::willBeRemovedFromTree()
230 {
231 // Detach all column sets from the flow thread. Cannot destroy them at this point, since they
232 // are siblings of this object, and there may be pointers to this object's s ibling somewhere
233 // further up on the call stack.
234 for (RenderMultiColumnSet* columnSet = firstMultiColumnSet(); columnSet; col umnSet = columnSet->nextSiblingMultiColumnSet())
235 columnSet->detachRegion();
236 multiColumnBlockFlow()->resetMultiColumnFlowThread();
237 RenderFlowThread::willBeRemovedFromTree();
238 }
239
192 void RenderMultiColumnFlowThread::computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues& computedValues) const 240 void RenderMultiColumnFlowThread::computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues& computedValues) const
193 { 241 {
194 // We simply remain at our intrinsic height. 242 // We simply remain at our intrinsic height.
195 computedValues.m_extent = logicalHeight; 243 computedValues.m_extent = logicalHeight;
196 computedValues.m_position = logicalTop; 244 computedValues.m_position = logicalTop;
197 } 245 }
198 246
199 LayoutUnit RenderMultiColumnFlowThread::initialLogicalWidth() const 247 LayoutUnit RenderMultiColumnFlowThread::initialLogicalWidth() const
200 { 248 {
201 return columnWidth(); 249 return columnWidth();
202 } 250 }
203 251
204 void RenderMultiColumnFlowThread::autoGenerateRegionsToBlockOffset(LayoutUnit /* offset*/)
205 {
206 // This function ensures we have the correct column set information at all t imes.
207 // For a simple multi-column layout in continuous media, only one column set child is required.
208 // Once a column is nested inside an enclosing pagination context, the numbe r of column sets
209 // required becomes 2n-1, where n is the total number of nested pagination c ontexts. For example:
210 //
211 // Column layout with no enclosing pagination model = 2 * 1 - 1 = 1 column s et.
212 // Columns inside pages = 2 * 2 - 1 = 3 column sets (bottom of first page, a ll the subsequent pages, then the last page).
213 // Columns inside columns inside pages = 2 * 3 - 1 = 5 column sets.
214 //
215 // In addition, column spans will force a column set to "split" into before/ after sets around the spanning element.
216 //
217 // Finally, we will need to deal with columns inside regions. If regions hav e variable widths, then there will need
218 // to be unique column sets created inside any region whose width is differe nt from its surrounding regions. This is
219 // actually pretty similar to the spanning case, in that we break up the col umn sets whenever the width varies.
220 //
221 // FIXME: For now just make one column set. This matches the old multi-colum n code.
222 // Right now our goal is just feature parity with the old multi-column code so that we can switch over to the
223 // new code as soon as possible.
224 RenderMultiColumnSet* firstSet = toRenderMultiColumnSet(firstRegion());
225 if (firstSet)
226 return;
227
228 invalidateRegions();
229
230 RenderBlockFlow* parentBlock = multiColumnBlockFlow();
231 firstSet = RenderMultiColumnSet::createAnonymous(this);
232 firstSet->setStyle(RenderStyle::createAnonymousStyleWithDisplay(parentBlock- >style(), BLOCK));
233 parentBlock->RenderBlock::addChild(firstSet);
234
235 // Even though we aren't placed yet, we can go ahead and set up our size. At this point we're
236 // typically in the middle of laying out the thread, attempting to paginate, and we need to do
237 // some rudimentary "layout" of the set now, so that pagination will work.
238 firstSet->prepareForLayout();
239
240 validateRegions();
241 }
242
243 void RenderMultiColumnFlowThread::setPageBreak(LayoutUnit offset, LayoutUnit spa ceShortage) 252 void RenderMultiColumnFlowThread::setPageBreak(LayoutUnit offset, LayoutUnit spa ceShortage)
244 { 253 {
245 if (RenderMultiColumnSet* multicolSet = toRenderMultiColumnSet(regionAtBlock Offset(offset))) 254 if (RenderMultiColumnSet* multicolSet = toRenderMultiColumnSet(regionAtBlock Offset(offset)))
246 multicolSet->recordSpaceShortage(spaceShortage); 255 multicolSet->recordSpaceShortage(spaceShortage);
247 } 256 }
248 257
249 void RenderMultiColumnFlowThread::updateMinimumPageHeight(LayoutUnit offset, Lay outUnit minHeight) 258 void RenderMultiColumnFlowThread::updateMinimumPageHeight(LayoutUnit offset, Lay outUnit minHeight)
250 { 259 {
251 if (RenderMultiColumnSet* multicolSet = toRenderMultiColumnSet(regionAtBlock Offset(offset))) 260 if (RenderMultiColumnSet* multicolSet = toRenderMultiColumnSet(regionAtBlock Offset(offset)))
252 multicolSet->updateMinimumColumnHeight(minHeight); 261 multicolSet->updateMinimumColumnHeight(minHeight);
253 } 262 }
254 263
264 RenderRegion* RenderMultiColumnFlowThread::regionAtBlockOffset(LayoutUnit /*offs et*/)
265 {
266 // For now there's only one column set, so this is easy:
267 return firstMultiColumnSet();
268 }
269
255 bool RenderMultiColumnFlowThread::addForcedRegionBreak(LayoutUnit offset, Render Object* /*breakChild*/, bool /*isBefore*/, LayoutUnit* offsetBreakAdjustment) 270 bool RenderMultiColumnFlowThread::addForcedRegionBreak(LayoutUnit offset, Render Object* /*breakChild*/, bool /*isBefore*/, LayoutUnit* offsetBreakAdjustment)
256 { 271 {
257 if (RenderMultiColumnSet* multicolSet = toRenderMultiColumnSet(regionAtBlock Offset(offset))) { 272 if (RenderMultiColumnSet* multicolSet = toRenderMultiColumnSet(regionAtBlock Offset(offset))) {
258 multicolSet->addForcedBreak(offset); 273 multicolSet->addForcedBreak(offset);
259 if (offsetBreakAdjustment) 274 if (offsetBreakAdjustment)
260 *offsetBreakAdjustment = pageLogicalHeightForOffset(offset) ? pageRe mainingLogicalHeightForOffset(offset, IncludePageBoundary) : LayoutUnit(); 275 *offsetBreakAdjustment = pageLogicalHeightForOffset(offset) ? pageRe mainingLogicalHeightForOffset(offset, IncludePageBoundary) : LayoutUnit();
261 return true; 276 return true;
262 } 277 }
263 return false; 278 return false;
264 } 279 }
265 280
266 bool RenderMultiColumnFlowThread::isPageLogicalHeightKnown() const 281 bool RenderMultiColumnFlowThread::isPageLogicalHeightKnown() const
267 { 282 {
268 for (RenderBox* renderer = parentBox()->lastChildBox(); renderer; renderer = renderer->previousSiblingBox()) { 283 if (RenderMultiColumnSet* columnSet = lastMultiColumnSet())
269 if (renderer->isRenderMultiColumnSet()) 284 return columnSet->computedColumnHeight();
270 return toRenderMultiColumnSet(renderer)->computedColumnHeight(); 285 return false;
271 }
272 // A column set hasn't been created yet. Height may already be known if colu mn-fill is 'auto', though.
273 return !requiresBalancing();
274 } 286 }
275 287
276 } 288 }
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