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

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

Issue 688703003: [New Multicolumn] Add RenderMultiColumnSpannerSet. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: There won't ever be any intervening non-multicol fragmentation contexts. Created 6 years, 1 month 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/RenderMultiColumnSet.h" 29 #include "core/rendering/RenderMultiColumnSet.h"
30 #include "core/rendering/RenderMultiColumnSpannerSet.h"
30 31
31 namespace blink { 32 namespace blink {
32 33
33 RenderMultiColumnFlowThread::RenderMultiColumnFlowThread() 34 RenderMultiColumnFlowThread::RenderMultiColumnFlowThread()
34 : m_columnCount(1) 35 : m_columnCount(1)
35 , m_columnHeightAvailable(0) 36 , m_columnHeightAvailable(0)
36 , m_inBalancingPass(false) 37 , m_inBalancingPass(false)
37 , m_needsColumnHeightsRecalculation(false) 38 , m_needsColumnHeightsRecalculation(false)
38 , m_progressionIsInline(true) 39 , m_progressionIsInline(true)
39 { 40 {
(...skipping 23 matching lines...) Expand all
63 64
64 RenderMultiColumnSet* RenderMultiColumnFlowThread::lastMultiColumnSet() const 65 RenderMultiColumnSet* RenderMultiColumnFlowThread::lastMultiColumnSet() const
65 { 66 {
66 for (RenderObject* sibling = multiColumnBlockFlow()->lastChild(); sibling; s ibling = sibling->previousSibling()) { 67 for (RenderObject* sibling = multiColumnBlockFlow()->lastChild(); sibling; s ibling = sibling->previousSibling()) {
67 if (sibling->isRenderMultiColumnSet()) 68 if (sibling->isRenderMultiColumnSet())
68 return toRenderMultiColumnSet(sibling); 69 return toRenderMultiColumnSet(sibling);
69 } 70 }
70 return 0; 71 return 0;
71 } 72 }
72 73
73 void RenderMultiColumnFlowThread::addChild(RenderObject* newChild, RenderObject* beforeChild) 74 RenderMultiColumnSpannerSet* RenderMultiColumnFlowThread::containingColumnSpanne rSet(const RenderObject* descendant) const
74 { 75 {
75 RenderBlockFlow::addChild(newChild, beforeChild); 76 ASSERT(descendant->isDescendantOf(this));
76 if (firstMultiColumnSet())
77 return;
78 77
79 // For now we only create one column set. It's created as soon as the multic ol container gets 78 // Before we spend time on searching the ancestry, see if there's a quick wa y to determine
80 // any content at all. 79 // whether there might be any spanners at all.
81 RenderMultiColumnSet* newSet = RenderMultiColumnSet::createAnonymous(this, m ultiColumnBlockFlow()->style()); 80 RenderMultiColumnSet* firstSet = firstMultiColumnSet();
81 if (!firstSet || (firstSet == lastMultiColumnSet() && !firstSet->isRenderMul tiColumnSpannerSet()))
82 return 0;
82 83
83 // Need to skip RenderBlockFlow's implementation of addChild(), or we'd get redirected right 84 // We have spanners. See if the renderer in question is one or inside of one then.
84 // back here. 85 for (const RenderObject* ancestor = descendant; ancestor && ancestor != this ; ancestor = ancestor->parent()) {
85 multiColumnBlockFlow()->RenderBlock::addChild(newSet); 86 if (RenderMultiColumnSpannerSet* spanner = m_spannerMap.get(ancestor))
86 87 return spanner;
87 invalidateRegions(); 88 }
89 return 0;
88 } 90 }
89 91
90 void RenderMultiColumnFlowThread::populate() 92 void RenderMultiColumnFlowThread::populate()
91 { 93 {
92 RenderBlockFlow* multicolContainer = multiColumnBlockFlow(); 94 RenderBlockFlow* multicolContainer = multiColumnBlockFlow();
93 ASSERT(!nextSibling()); 95 ASSERT(!nextSibling());
94 // Reparent children preceding the flow thread into the flow thread. It's mu lticol content 96 // Reparent children preceding the flow thread into the flow thread. It's mu lticol content
95 // now. At this point there's obviously nothing after the flow thread, but r enderers (column 97 // now. At this point there's obviously nothing after the flow thread, but r enderers (column
96 // sets and spanners) will be inserted there as we insert elements into the flow thread. 98 // sets and spanners) will be inserted there as we insert elements into the flow thread.
97 multicolContainer->moveChildrenTo(this, multicolContainer->firstChild(), thi s, true); 99 multicolContainer->moveChildrenTo(this, multicolContainer->firstChild(), thi s, true);
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
220 width = std::max<LayoutUnit>(0, (availableWidth - ((count - 1) * columnG ap)) / count); 222 width = std::max<LayoutUnit>(0, (availableWidth - ((count - 1) * columnG ap)) / count);
221 } else if (!columnStyle->hasAutoColumnWidth() && columnStyle->hasAutoColumnC ount()) { 223 } else if (!columnStyle->hasAutoColumnWidth() && columnStyle->hasAutoColumnC ount()) {
222 count = std::max<LayoutUnit>(1, (availableWidth + columnGap) / (computed ColumnWidth + columnGap)); 224 count = std::max<LayoutUnit>(1, (availableWidth + columnGap) / (computed ColumnWidth + columnGap));
223 width = ((availableWidth + columnGap) / count) - columnGap; 225 width = ((availableWidth + columnGap) / count) - columnGap;
224 } else { 226 } else {
225 count = std::max<LayoutUnit>(std::min<LayoutUnit>(computedColumnCount, ( availableWidth + columnGap) / (computedColumnWidth + columnGap)), 1); 227 count = std::max<LayoutUnit>(std::min<LayoutUnit>(computedColumnCount, ( availableWidth + columnGap) / (computedColumnWidth + columnGap)), 1);
226 width = ((availableWidth + columnGap) / count) - columnGap; 228 width = ((availableWidth + columnGap) / count) - columnGap;
227 } 229 }
228 } 230 }
229 231
232 void RenderMultiColumnFlowThread::createAndInsertMultiColumnSet()
233 {
234 RenderBlockFlow* multicolContainer = multiColumnBlockFlow();
235 RenderMultiColumnSet* newSet = RenderMultiColumnSet::createAnonymous(this, m ulticolContainer->style());
236 multicolContainer->RenderBlock::addChild(newSet);
237 invalidateRegions();
238
239 // We cannot handle immediate column set siblings (and there's no need for i t, either).
240 // There has to be at least one spanner separating them.
241 ASSERT(!newSet->previousSiblingMultiColumnSet() || newSet->previousSiblingMu ltiColumnSet()->isRenderMultiColumnSpannerSet());
242 ASSERT(!newSet->nextSiblingMultiColumnSet() || newSet->nextSiblingMultiColum nSet()->isRenderMultiColumnSpannerSet());
243 }
244
245 void RenderMultiColumnFlowThread::createAndInsertSpannerSet(RenderBox* spanner)
246 {
247 RenderBlockFlow* multicolContainer = multiColumnBlockFlow();
248 RenderMultiColumnSpannerSet* newSpannerSet = RenderMultiColumnSpannerSet::cr eateAnonymous(this, multicolContainer->style(), spanner);
249 multicolContainer->RenderBlock::addChild(newSpannerSet);
250 m_spannerMap.add(spanner, newSpannerSet);
251 invalidateRegions();
252 }
253
254 bool RenderMultiColumnFlowThread::descendantIsValidColumnSpanner(RenderObject* d escendant) const
255 {
256 // We assume that we're inside the flow thread. This function is not to be c alled otherwise.
257 ASSERT(descendant->isDescendantOf(this));
258
259 // The spec says that column-span only applies to in-flow block-level elemen ts.
260 if (descendant->style()->columnSpan() != ColumnSpanAll || !descendant->isBox () || descendant->isInline() || descendant->isFloatingOrOutOfFlowPositioned())
261 return false;
262
263 if (!descendant->containingBlock()->isRenderBlockFlow()) {
264 // Needs to be in a block-flow container, and not e.g. a table.
265 return false;
266 }
267
268 // This looks like a spanner, but if we're inside something unbreakable, it' s not to be treated as one.
269 for (RenderBlock* ancestor = descendant->containingBlock(); ancestor && ance stor->flowThreadContainingBlock() == this; ancestor = ancestor->containingBlock( )) {
270 if (ancestor->isRenderFlowThread()) {
271 ASSERT(ancestor == this);
272 return true;
273 }
274 if (m_spannerMap.get(ancestor)) {
275 // FIXME: do we want to support nested spanners in a different way? The outer spanner
276 // has already broken out from the columns to become sized by the mu lticol container,
277 // which may be good enough for the inner spanner. But margins, bord ers, padding and
278 // explicit widths on the outer spanner, or on any children between the outer and inner
279 // spanner, will affect the width of the inner spanner this way, whi ch might be
280 // undesirable. The spec has nothing to say on the matter.
281 return false; // Ignore nested spanners.
282 }
283 if (ancestor->isUnsplittableForPagination())
284 return false;
285 }
286 ASSERT_NOT_REACHED();
287 return false;
288 }
289
230 const char* RenderMultiColumnFlowThread::renderName() const 290 const char* RenderMultiColumnFlowThread::renderName() const
231 { 291 {
232 return "RenderMultiColumnFlowThread"; 292 return "RenderMultiColumnFlowThread";
233 } 293 }
234 294
235 void RenderMultiColumnFlowThread::addRegionToThread(RenderMultiColumnSet* column Set) 295 void RenderMultiColumnFlowThread::addRegionToThread(RenderMultiColumnSet* column Set)
236 { 296 {
237 if (RenderMultiColumnSet* nextSet = columnSet->nextSiblingMultiColumnSet()) { 297 if (RenderMultiColumnSet* nextSet = columnSet->nextSiblingMultiColumnSet()) {
238 RenderMultiColumnSetList::iterator it = m_multiColumnSetList.find(nextSe t); 298 RenderMultiColumnSetList::iterator it = m_multiColumnSetList.find(nextSe t);
239 ASSERT(it != m_multiColumnSetList.end()); 299 ASSERT(it != m_multiColumnSetList.end());
240 m_multiColumnSetList.insertBefore(it, columnSet); 300 m_multiColumnSetList.insertBefore(it, columnSet);
241 } else { 301 } else {
242 m_multiColumnSetList.add(columnSet); 302 m_multiColumnSetList.add(columnSet);
243 } 303 }
244 columnSet->setIsValid(true); 304 columnSet->setIsValid(true);
245 } 305 }
246 306
247 void RenderMultiColumnFlowThread::willBeRemovedFromTree() 307 void RenderMultiColumnFlowThread::willBeRemovedFromTree()
248 { 308 {
309 m_spannerMap.clear();
249 // Detach all column sets from the flow thread. Cannot destroy them at this point, since they 310 // Detach all column sets from the flow thread. Cannot destroy them at this point, since they
250 // are siblings of this object, and there may be pointers to this object's s ibling somewhere 311 // are siblings of this object, and there may be pointers to this object's s ibling somewhere
251 // further up on the call stack. 312 // further up on the call stack.
252 for (RenderMultiColumnSet* columnSet = firstMultiColumnSet(); columnSet; col umnSet = columnSet->nextSiblingMultiColumnSet()) 313 for (RenderMultiColumnSet* columnSet = firstMultiColumnSet(); columnSet; col umnSet = columnSet->nextSiblingMultiColumnSet())
253 columnSet->detachRegion(); 314 columnSet->detachRegion();
254 multiColumnBlockFlow()->resetMultiColumnFlowThread(); 315 multiColumnBlockFlow()->resetMultiColumnFlowThread();
255 RenderFlowThread::willBeRemovedFromTree(); 316 RenderFlowThread::willBeRemovedFromTree();
256 } 317 }
257 318
319 void RenderMultiColumnFlowThread::flowThreadDescendantWasInserted(RenderObject* descendant)
320 {
321 // Go through the subtree that was just inserted and create column sets (nee ded by regular
322 // column content) and spanner sets (one needed by each spanner).
323 for (RenderObject* renderer = descendant; renderer; renderer = renderer->nex tInPreOrder(descendant)) {
324 if (containingColumnSpannerSet(renderer))
325 continue; // Inside a column spanner set. Nothing to do, then.
326 if (descendantIsValidColumnSpanner(renderer)) {
327 // This renderer is a spanner, so it needs to establish a spanner se t.
328 createAndInsertSpannerSet(toRenderBox(renderer));
329 continue;
330 }
331 // This renderer is regular column content (i.e. not a spanner). Create a set if necessary.
332 RenderMultiColumnSet* lastSet = lastMultiColumnSet();
333 if (!lastSet || lastSet->isRenderMultiColumnSpannerSet())
334 createAndInsertMultiColumnSet();
335 }
336 }
337
258 void RenderMultiColumnFlowThread::computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues& computedValues) const 338 void RenderMultiColumnFlowThread::computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues& computedValues) const
259 { 339 {
260 // We simply remain at our intrinsic height. 340 // We simply remain at our intrinsic height.
261 computedValues.m_extent = logicalHeight; 341 computedValues.m_extent = logicalHeight;
262 computedValues.m_position = logicalTop; 342 computedValues.m_position = logicalTop;
263 } 343 }
264 344
265 void RenderMultiColumnFlowThread::updateLogicalWidth() 345 void RenderMultiColumnFlowThread::updateLogicalWidth()
266 { 346 {
267 LayoutUnit columnWidth; 347 LayoutUnit columnWidth;
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
313 } 393 }
314 394
315 bool RenderMultiColumnFlowThread::isPageLogicalHeightKnown() const 395 bool RenderMultiColumnFlowThread::isPageLogicalHeightKnown() const
316 { 396 {
317 if (RenderMultiColumnSet* columnSet = lastMultiColumnSet()) 397 if (RenderMultiColumnSet* columnSet = lastMultiColumnSet())
318 return columnSet->pageLogicalHeight(); 398 return columnSet->pageLogicalHeight();
319 return false; 399 return false;
320 } 400 }
321 401
322 } 402 }
OLDNEW
« no previous file with comments | « Source/core/rendering/RenderMultiColumnFlowThread.h ('k') | Source/core/rendering/RenderMultiColumnFlowThreadTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698