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

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: rebase master 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). There
240 // 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::isDescendantValidColumnSpanner(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 // First make sure that the renderer itself has the right properties and cha racteristics for
260 // becoming a spanner.
261 if (descendant->style()->columnSpan() != ColumnSpanAll || !descendant->isBox () || descendant->isInline() || descendant->isFloatingOrOutOfFlowPositioned())
262 return false;
263
264 if (!descendant->containingBlock()->isRenderBlockFlow()) {
265 // Needs to be in a block container, and not e.g. a table.
266 return false;
267 }
268
269 // This looks like a spanner, but if we're inside something unbreakable, it' s not to be treated as one.
270 for (RenderBox* ancestor = toRenderBox(descendant)->parentBox(); ancestor; a ncestor = ancestor->parentBox()) {
271 if (ancestor->isRenderFlowThread()) {
272 // Don't allow any intervening non-multicol fragmentation contexts. The spec doesn't say
273 // anything about disallowing this, but it's just going to be too co mplicated to
274 // implement (not to mention specify behavior).
275 return ancestor == this;
276 }
277 if (m_spannerMap.get(ancestor)) {
278 // FIXME: do we want to support nested spanners in a different way? The outer spanner
279 // has already broken out from the columns to become sized by the mu lticol container,
280 // which may be good enough for the inner spanner. But margins, bord ers, padding and
281 // explicit widths on the outer spanner, or on any children between the outer and inner
282 // spanner, will affect the width of the inner spanner this way, whi ch might be
283 // undesirable. The spec has nothing to say on the matter.
284 return false; // Ignore nested spanners.
285 }
286 if (ancestor->isUnsplittableForPagination())
287 return false;
288 }
289 ASSERT_NOT_REACHED();
290 return false;
291 }
292
230 const char* RenderMultiColumnFlowThread::renderName() const 293 const char* RenderMultiColumnFlowThread::renderName() const
231 { 294 {
232 return "RenderMultiColumnFlowThread"; 295 return "RenderMultiColumnFlowThread";
233 } 296 }
234 297
235 void RenderMultiColumnFlowThread::addRegionToThread(RenderMultiColumnSet* column Set) 298 void RenderMultiColumnFlowThread::addRegionToThread(RenderMultiColumnSet* column Set)
236 { 299 {
237 if (RenderMultiColumnSet* nextSet = columnSet->nextSiblingMultiColumnSet()) { 300 if (RenderMultiColumnSet* nextSet = columnSet->nextSiblingMultiColumnSet()) {
238 RenderMultiColumnSetList::iterator it = m_multiColumnSetList.find(nextSe t); 301 RenderMultiColumnSetList::iterator it = m_multiColumnSetList.find(nextSe t);
239 ASSERT(it != m_multiColumnSetList.end()); 302 ASSERT(it != m_multiColumnSetList.end());
240 m_multiColumnSetList.insertBefore(it, columnSet); 303 m_multiColumnSetList.insertBefore(it, columnSet);
241 } else { 304 } else {
242 m_multiColumnSetList.add(columnSet); 305 m_multiColumnSetList.add(columnSet);
243 } 306 }
244 columnSet->setIsValid(true); 307 columnSet->setIsValid(true);
245 } 308 }
246 309
247 void RenderMultiColumnFlowThread::willBeRemovedFromTree() 310 void RenderMultiColumnFlowThread::willBeRemovedFromTree()
248 { 311 {
312 m_spannerMap.clear();
249 // Detach all column sets from the flow thread. Cannot destroy them at this point, since they 313 // 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 314 // are siblings of this object, and there may be pointers to this object's s ibling somewhere
251 // further up on the call stack. 315 // further up on the call stack.
252 for (RenderMultiColumnSet* columnSet = firstMultiColumnSet(); columnSet; col umnSet = columnSet->nextSiblingMultiColumnSet()) 316 for (RenderMultiColumnSet* columnSet = firstMultiColumnSet(); columnSet; col umnSet = columnSet->nextSiblingMultiColumnSet())
253 columnSet->detachRegion(); 317 columnSet->detachRegion();
254 multiColumnBlockFlow()->resetMultiColumnFlowThread(); 318 multiColumnBlockFlow()->resetMultiColumnFlowThread();
255 RenderFlowThread::willBeRemovedFromTree(); 319 RenderFlowThread::willBeRemovedFromTree();
256 } 320 }
257 321
322 void RenderMultiColumnFlowThread::flowThreadDescendantWasInserted(RenderObject* descendant)
323 {
324 // Go through the subtree that was just inserted and create column sets (nee ded by regular
325 // column content) and spanner sets (one needed by each spanner).
326 for (RenderObject* renderer = descendant; renderer; renderer = renderer->nex tInPreOrder(descendant)) {
327 if (containingColumnSpannerSet(renderer))
328 continue; // Inside a column spanner set. Nothing to do, then.
329 if (isDescendantValidColumnSpanner(renderer)) {
330 // This renderer is a spanner, so it needs to establish a spanner se t.
331 createAndInsertSpannerSet(toRenderBox(renderer));
332 continue;
333 }
334 // This renderer is regular column content (i.e. not a spanner). Create a set if necessary.
335 RenderMultiColumnSet* lastSet = lastMultiColumnSet();
336 if (!lastSet || lastSet->isRenderMultiColumnSpannerSet())
337 createAndInsertMultiColumnSet();
338 }
339 }
340
258 void RenderMultiColumnFlowThread::computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues& computedValues) const 341 void RenderMultiColumnFlowThread::computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues& computedValues) const
259 { 342 {
260 // We simply remain at our intrinsic height. 343 // We simply remain at our intrinsic height.
261 computedValues.m_extent = logicalHeight; 344 computedValues.m_extent = logicalHeight;
262 computedValues.m_position = logicalTop; 345 computedValues.m_position = logicalTop;
263 } 346 }
264 347
265 void RenderMultiColumnFlowThread::updateLogicalWidth() 348 void RenderMultiColumnFlowThread::updateLogicalWidth()
266 { 349 {
267 LayoutUnit columnWidth; 350 LayoutUnit columnWidth;
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
313 } 396 }
314 397
315 bool RenderMultiColumnFlowThread::isPageLogicalHeightKnown() const 398 bool RenderMultiColumnFlowThread::isPageLogicalHeightKnown() const
316 { 399 {
317 if (RenderMultiColumnSet* columnSet = lastMultiColumnSet()) 400 if (RenderMultiColumnSet* columnSet = lastMultiColumnSet())
318 return columnSet->pageLogicalHeight(); 401 return columnSet->pageLogicalHeight();
319 return false; 402 return false;
320 } 403 }
321 404
322 } 405 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698