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

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 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
221 width = std::max<LayoutUnit>(0, (availableWidth - ((count - 1) * columnG ap)) / count); 223 width = std::max<LayoutUnit>(0, (availableWidth - ((count - 1) * columnG ap)) / count);
222 } else if (!columnStyle->hasAutoColumnWidth() && columnStyle->hasAutoColumnC ount()) { 224 } else if (!columnStyle->hasAutoColumnWidth() && columnStyle->hasAutoColumnC ount()) {
223 count = std::max<LayoutUnit>(1, (availableWidth + columnGap) / (computed ColumnWidth + columnGap)); 225 count = std::max<LayoutUnit>(1, (availableWidth + columnGap) / (computed ColumnWidth + columnGap));
224 width = ((availableWidth + columnGap) / count) - columnGap; 226 width = ((availableWidth + columnGap) / count) - columnGap;
225 } else { 227 } else {
226 count = std::max<LayoutUnit>(std::min<LayoutUnit>(computedColumnCount, ( availableWidth + columnGap) / (computedColumnWidth + columnGap)), 1); 228 count = std::max<LayoutUnit>(std::min<LayoutUnit>(computedColumnCount, ( availableWidth + columnGap) / (computedColumnWidth + columnGap)), 1);
227 width = ((availableWidth + columnGap) / count) - columnGap; 229 width = ((availableWidth + columnGap) / count) - columnGap;
228 } 230 }
229 } 231 }
230 232
233 void RenderMultiColumnFlowThread::createAndInsertMultiColumnSet()
234 {
235 RenderBlockFlow* multicolContainer = multiColumnBlockFlow();
236 RenderMultiColumnSet* newSet = RenderMultiColumnSet::createAnonymous(this, m ulticolContainer->style());
237 multicolContainer->RenderBlock::addChild(newSet);
238 invalidateRegions();
239
240 // We cannot handle immediate column set siblings (and there's no need for i t, either). There
Julien - ping for review 2014/11/05 16:52:38 Nit: Let's move 'There' to the next line so that w
mstensho (USE GERRIT) 2014/11/05 21:43:06 Done.
241 // has to be at least one spanner separating them.
242 ASSERT(!newSet->previousSiblingMultiColumnSet() || newSet->previousSiblingMu ltiColumnSet()->isRenderMultiColumnSpannerSet());
243 ASSERT(!newSet->nextSiblingMultiColumnSet() || newSet->nextSiblingMultiColum nSet()->isRenderMultiColumnSpannerSet());
244 }
245
246 void RenderMultiColumnFlowThread::createAndInsertSpannerSet(RenderBox* spanner)
247 {
248 RenderBlockFlow* multicolContainer = multiColumnBlockFlow();
249 RenderMultiColumnSpannerSet* newSpannerSet = RenderMultiColumnSpannerSet::cr eateAnonymous(this, multicolContainer->style(), spanner);
250 multicolContainer->RenderBlock::addChild(newSpannerSet);
251 m_spannerMap.add(spanner, newSpannerSet);
252 invalidateRegions();
253 }
254
255 bool RenderMultiColumnFlowThread::isDescendantValidColumnSpanner(RenderObject* d escendant) const
256 {
257 // We assume that we're inside the flow thread. This function is not to be c alled otherwise.
258 ASSERT(descendant->isDescendantOf(this));
259
260 // First make sure that the renderer itself has the right properties and cha racteristics for
261 // becoming a spanner.
Julien - ping for review 2014/11/05 16:52:38 I would be good to quote from the specification as
mstensho (USE GERRIT) 2014/11/05 21:43:06 Done.
262 if (descendant->style()->columnSpan() != ColumnSpanAll || !descendant->isBox () || descendant->isInline() || descendant->isFloatingOrOutOfFlowPositioned())
263 return false;
264
265 if (!descendant->containingBlock()->isRenderBlockFlow()) {
266 // Needs to be in a block container, and not e.g. a table.
Julien - ping for review 2014/11/05 16:52:38 It should be: block-flow container
mstensho (USE GERRIT) 2014/11/05 21:43:06 Done. The spec calls those things "block containe
267 return false;
268 }
269
270 // This looks like a spanner, but if we're inside something unbreakable, it' s not to be treated as one.
271 for (RenderBox* ancestor = toRenderBox(descendant)->parentBox(); ancestor; a ncestor = ancestor->parentBox()) {
Julien - ping for review 2014/11/05 16:52:38 I don't think you should not use parentBox as it d
mstensho (USE GERRIT) 2014/11/05 21:43:06 The spec doesn't have much to offer regarding this
272 if (ancestor->isRenderFlowThread()) {
Julien - ping for review 2014/11/05 16:52:38 Shouldn't we just check flowThreadState()? If that
mstensho (USE GERRIT) 2014/11/05 21:43:06 flowThreadState() just tells you if you're a flow
273 // Don't allow any intervening non-multicol fragmentation contexts. The spec doesn't say
Julien - ping for review 2014/11/05 16:52:38 We don't allow non-multicol fragmentation contexts
mstensho (USE GERRIT) 2014/11/05 21:43:06 There's paged containers (overflow:-webkit-paged-[
mstensho (USE GERRIT) 2014/11/05 23:16:22 Nonono! Wrong! Well, yes, there may be paged conta
274 // anything about disallowing this, but it's just going to be too co mplicated to
275 // implement (not to mention specify behavior).
276 return ancestor == this;
277 }
278 if (m_spannerMap.get(ancestor)) {
279 // FIXME: do we want to support nested spanners in a different way? The outer spanner
280 // has already broken out from the columns to become sized by the mu lticol container,
281 // which may be good enough for the inner spanner. But margins, bord ers, padding and
282 // explicit widths on the outer spanner, or on any children between the outer and inner
283 // spanner, will affect the width of the inner spanner this way, whi ch might be
284 // undesirable. The spec has nothing to say on the matter.
285 return false; // Ignore nested spanners.
286 }
287 if (ancestor->isUnsplittableForPagination())
288 return false;
289 }
290 ASSERT_NOT_REACHED();
291 return false;
292 }
293
231 const char* RenderMultiColumnFlowThread::renderName() const 294 const char* RenderMultiColumnFlowThread::renderName() const
232 { 295 {
233 return "RenderMultiColumnFlowThread"; 296 return "RenderMultiColumnFlowThread";
234 } 297 }
235 298
236 void RenderMultiColumnFlowThread::addRegionToThread(RenderMultiColumnSet* column Set) 299 void RenderMultiColumnFlowThread::addRegionToThread(RenderMultiColumnSet* column Set)
237 { 300 {
238 if (RenderMultiColumnSet* nextSet = columnSet->nextSiblingMultiColumnSet()) { 301 if (RenderMultiColumnSet* nextSet = columnSet->nextSiblingMultiColumnSet()) {
239 RenderMultiColumnSetList::iterator it = m_multiColumnSetList.find(nextSe t); 302 RenderMultiColumnSetList::iterator it = m_multiColumnSetList.find(nextSe t);
240 ASSERT(it != m_multiColumnSetList.end()); 303 ASSERT(it != m_multiColumnSetList.end());
241 m_multiColumnSetList.insertBefore(it, columnSet); 304 m_multiColumnSetList.insertBefore(it, columnSet);
242 } else { 305 } else {
243 m_multiColumnSetList.add(columnSet); 306 m_multiColumnSetList.add(columnSet);
244 } 307 }
245 columnSet->setIsValid(true); 308 columnSet->setIsValid(true);
246 } 309 }
247 310
248 void RenderMultiColumnFlowThread::willBeRemovedFromTree() 311 void RenderMultiColumnFlowThread::willBeRemovedFromTree()
249 { 312 {
313 m_spannerMap.clear();
250 // Detach all column sets from the flow thread. Cannot destroy them at this point, since they 314 // Detach all column sets from the flow thread. Cannot destroy them at this point, since they
251 // are siblings of this object, and there may be pointers to this object's s ibling somewhere 315 // are siblings of this object, and there may be pointers to this object's s ibling somewhere
252 // further up on the call stack. 316 // further up on the call stack.
253 for (RenderMultiColumnSet* columnSet = firstMultiColumnSet(); columnSet; col umnSet = columnSet->nextSiblingMultiColumnSet()) 317 for (RenderMultiColumnSet* columnSet = firstMultiColumnSet(); columnSet; col umnSet = columnSet->nextSiblingMultiColumnSet())
254 columnSet->detachRegion(); 318 columnSet->detachRegion();
255 multiColumnBlockFlow()->resetMultiColumnFlowThread(); 319 multiColumnBlockFlow()->resetMultiColumnFlowThread();
256 RenderFlowThread::willBeRemovedFromTree(); 320 RenderFlowThread::willBeRemovedFromTree();
257 } 321 }
258 322
323 void RenderMultiColumnFlowThread::flowThreadDescendantWasInserted(RenderObject* descendant)
324 {
325 // Go through the subtree that was just inserted and create column sets (nee ded by regular
326 // column content) and spanner sets (one needed by each spanner).
327 for (RenderObject* renderer = descendant; renderer; renderer = renderer->nex tInPreOrder(descendant)) {
328 if (containingColumnSpannerSet(renderer))
329 continue; // Inside a column spanner set. Nothing to do, then.
330 if (isDescendantValidColumnSpanner(renderer)) {
331 // This renderer is a spanner, so it needs to establish a spanner se t.
332 createAndInsertSpannerSet(toRenderBox(renderer));
333 continue;
334 }
335 // This renderer is regular column content (i.e. not a spanner). Create a set if necessary.
336 RenderMultiColumnSet* lastSet = lastMultiColumnSet();
337 if (!lastSet || lastSet->isRenderMultiColumnSpannerSet())
338 createAndInsertMultiColumnSet();
339 }
340 }
341
259 void RenderMultiColumnFlowThread::computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues& computedValues) const 342 void RenderMultiColumnFlowThread::computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues& computedValues) const
260 { 343 {
261 // We simply remain at our intrinsic height. 344 // We simply remain at our intrinsic height.
262 computedValues.m_extent = logicalHeight; 345 computedValues.m_extent = logicalHeight;
263 computedValues.m_position = logicalTop; 346 computedValues.m_position = logicalTop;
264 } 347 }
265 348
266 void RenderMultiColumnFlowThread::updateLogicalWidth() 349 void RenderMultiColumnFlowThread::updateLogicalWidth()
267 { 350 {
268 LayoutUnit columnWidth; 351 LayoutUnit columnWidth;
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
314 } 397 }
315 398
316 bool RenderMultiColumnFlowThread::isPageLogicalHeightKnown() const 399 bool RenderMultiColumnFlowThread::isPageLogicalHeightKnown() const
317 { 400 {
318 if (RenderMultiColumnSet* columnSet = lastMultiColumnSet()) 401 if (RenderMultiColumnSet* columnSet = lastMultiColumnSet())
319 return columnSet->pageLogicalHeight(); 402 return columnSet->pageLogicalHeight();
320 return false; 403 return false;
321 } 404 }
322 405
323 } 406 }
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