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

Side by Side Diff: third_party/WebKit/Source/core/layout/LayoutMultiColumnFlowThread.cpp

Issue 2394263004: Reformat comments in core/layout up until LayoutMultiColumnFlowThread (Closed)
Patch Set: Rebase w/HEAD Created 4 years, 2 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
11 * documentation and/or other materials provided with the distribution. 11 * documentation and/or other materials provided with the distribution.
12 * 12 *
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
71 } 71 }
72 return nullptr; 72 return nullptr;
73 } 73 }
74 74
75 static inline bool isMultiColumnContainer(const LayoutObject& object) { 75 static inline bool isMultiColumnContainer(const LayoutObject& object) {
76 if (!object.isLayoutBlockFlow()) 76 if (!object.isLayoutBlockFlow())
77 return false; 77 return false;
78 return toLayoutBlockFlow(object).multiColumnFlowThread(); 78 return toLayoutBlockFlow(object).multiColumnFlowThread();
79 } 79 }
80 80
81 // Return true if there's nothing that prevents the specified object from being in the ancestor 81 // Return true if there's nothing that prevents the specified object from being
82 // chain between some column spanner and its containing multicol container. A co lumn spanner needs 82 // in the ancestor chain between some column spanner and its containing multicol
83 // the multicol container to be its containing block, so that the spanner is abl e to escape the flow 83 // container. A column spanner needs the multicol container to be its containing
84 // thread. (Everything contained by the flow thread is split into columns, but t his is precisely 84 // block, so that the spanner is able to escape the flow thread. (Everything
85 // what shouldn't be done to a spanner, since it's supposed to span all columns. ) 85 // contained by the flow thread is split into columns, but this is precisely
86 // what shouldn't be done to a spanner, since it's supposed to span all
87 // columns.)
86 // 88 //
87 // We require that the parent of the spanner participate in the block formatting context established 89 // We require that the parent of the spanner participate in the block formatting
88 // by the multicol container (i.e. that there are no BFCs or other formatting co ntexts 90 // context established by the multicol container (i.e. that there are no BFCs or
89 // in-between). We also require that there be no transforms, since transforms in sist on being in the 91 // other formatting contexts in-between). We also require that there be no
90 // containing block chain for everything inside it, which conflicts with a spann ers's need to have 92 // transforms, since transforms insist on being in the containing block chain
91 // the multicol container as its direct containing block. We may also not put sp anners inside 93 // for everything inside it, which conflicts with a spanners's need to have the
92 // objects that don't support fragmentation. 94 // multicol container as its direct containing block. We may also not put
95 // spanners inside objects that don't support fragmentation.
93 static inline bool canContainSpannerInParentFragmentationContext( 96 static inline bool canContainSpannerInParentFragmentationContext(
94 const LayoutObject& object) { 97 const LayoutObject& object) {
95 if (!object.isLayoutBlockFlow()) 98 if (!object.isLayoutBlockFlow())
96 return false; 99 return false;
97 const LayoutBlockFlow& blockFlow = toLayoutBlockFlow(object); 100 const LayoutBlockFlow& blockFlow = toLayoutBlockFlow(object);
98 return !blockFlow.createsNewFormattingContext() && 101 return !blockFlow.createsNewFormattingContext() &&
99 !blockFlow.hasTransformRelatedProperty() && 102 !blockFlow.hasTransformRelatedProperty() &&
100 blockFlow.getPaginationBreakability() != LayoutBox::ForbidBreaks && 103 blockFlow.getPaginationBreakability() != LayoutBox::ForbidBreaks &&
101 !isMultiColumnContainer(blockFlow); 104 !isMultiColumnContainer(blockFlow);
102 } 105 }
103 106
104 static inline bool hasAnyColumnSpanners( 107 static inline bool hasAnyColumnSpanners(
105 const LayoutMultiColumnFlowThread& flowThread) { 108 const LayoutMultiColumnFlowThread& flowThread) {
106 LayoutBox* firstBox = flowThread.firstMultiColumnBox(); 109 LayoutBox* firstBox = flowThread.firstMultiColumnBox();
107 return firstBox && (firstBox != flowThread.lastMultiColumnBox() || 110 return firstBox && (firstBox != flowThread.lastMultiColumnBox() ||
108 firstBox->isLayoutMultiColumnSpannerPlaceholder()); 111 firstBox->isLayoutMultiColumnSpannerPlaceholder());
109 } 112 }
110 113
111 // Find the next layout object that has the multicol container in its containing block chain, skipping nested multicol containers. 114 // Find the next layout object that has the multicol container in its containing
115 // block chain, skipping nested multicol containers.
112 static LayoutObject* nextInPreOrderAfterChildrenSkippingOutOfFlow( 116 static LayoutObject* nextInPreOrderAfterChildrenSkippingOutOfFlow(
113 LayoutMultiColumnFlowThread* flowThread, 117 LayoutMultiColumnFlowThread* flowThread,
114 LayoutObject* descendant) { 118 LayoutObject* descendant) {
115 ASSERT(descendant->isDescendantOf(flowThread)); 119 ASSERT(descendant->isDescendantOf(flowThread));
116 LayoutObject* object = descendant->nextInPreOrderAfterChildren(flowThread); 120 LayoutObject* object = descendant->nextInPreOrderAfterChildren(flowThread);
117 while (object) { 121 while (object) {
118 // Walk through the siblings and find the first one which is either in-flow or has this 122 // Walk through the siblings and find the first one which is either in-flow
119 // flow thread as its containing block flow thread. 123 // or has this flow thread as its containing block flow thread.
120 if (!object->isOutOfFlowPositioned()) 124 if (!object->isOutOfFlowPositioned())
121 break; 125 break;
122 if (object->containingBlock()->flowThreadContainingBlock() == flowThread) { 126 if (object->containingBlock()->flowThreadContainingBlock() == flowThread) {
123 // This out-of-flow object is still part of the flow thread, because its c ontaining 127 // This out-of-flow object is still part of the flow thread, because its
124 // block (probably relatively positioned) is part of the flow thread. 128 // containing block (probably relatively positioned) is part of the flow
129 // thread.
125 break; 130 break;
126 } 131 }
127 object = object->nextInPreOrderAfterChildren(flowThread); 132 object = object->nextInPreOrderAfterChildren(flowThread);
128 } 133 }
129 if (!object) 134 if (!object)
130 return nullptr; 135 return nullptr;
131 #if ENABLE(ASSERT) 136 #if ENABLE(ASSERT)
132 // Make sure that we didn't stumble into an inner multicol container. 137 // Make sure that we didn't stumble into an inner multicol container.
133 for (LayoutObject* walker = object->parent(); walker && walker != flowThread; 138 for (LayoutObject* walker = object->parent(); walker && walker != flowThread;
134 walker = walker->parent()) 139 walker = walker->parent())
135 ASSERT(!isMultiColumnContainer(*walker)); 140 ASSERT(!isMultiColumnContainer(*walker));
136 #endif 141 #endif
137 return object; 142 return object;
138 } 143 }
139 144
140 // Find the previous layout object that has the multicol container in its contai ning block chain, skipping nested multicol containers. 145 // Find the previous layout object that has the multicol container in its
146 // containing block chain, skipping nested multicol containers.
141 static LayoutObject* previousInPreOrderSkippingOutOfFlow( 147 static LayoutObject* previousInPreOrderSkippingOutOfFlow(
142 LayoutMultiColumnFlowThread* flowThread, 148 LayoutMultiColumnFlowThread* flowThread,
143 LayoutObject* descendant) { 149 LayoutObject* descendant) {
144 ASSERT(descendant->isDescendantOf(flowThread)); 150 ASSERT(descendant->isDescendantOf(flowThread));
145 LayoutObject* object = descendant->previousInPreOrder(flowThread); 151 LayoutObject* object = descendant->previousInPreOrder(flowThread);
146 while (object && object != flowThread) { 152 while (object && object != flowThread) {
147 if (object->isColumnSpanAll()) { 153 if (object->isColumnSpanAll()) {
148 LayoutMultiColumnFlowThread* placeholderFlowThread = 154 LayoutMultiColumnFlowThread* placeholderFlowThread =
149 toLayoutBox(object)->spannerPlaceholder()->flowThread(); 155 toLayoutBox(object)->spannerPlaceholder()->flowThread();
150 if (placeholderFlowThread == flowThread) 156 if (placeholderFlowThread == flowThread)
151 break; 157 break;
152 // We're inside an inner multicol container. We have no business there. Co ntinue on the outside. 158 // We're inside an inner multicol container. We have no business there.
159 // Continue on the outside.
153 object = placeholderFlowThread->parent(); 160 object = placeholderFlowThread->parent();
154 ASSERT(object->isDescendantOf(flowThread)); 161 ASSERT(object->isDescendantOf(flowThread));
155 continue; 162 continue;
156 } 163 }
157 if (object->flowThreadContainingBlock() == flowThread) { 164 if (object->flowThreadContainingBlock() == flowThread) {
158 LayoutObject* ancestor; 165 LayoutObject* ancestor;
159 for (ancestor = object->parent();; ancestor = ancestor->parent()) { 166 for (ancestor = object->parent();; ancestor = ancestor->parent()) {
160 if (ancestor == flowThread) 167 if (ancestor == flowThread)
161 return object; 168 return object;
162 if (isMultiColumnContainer(*ancestor)) { 169 if (isMultiColumnContainer(*ancestor)) {
163 // We're inside an inner multicol container. We have no business there . 170 // We're inside an inner multicol container. We have no business
171 // there.
164 break; 172 break;
165 } 173 }
166 } 174 }
167 object = ancestor; 175 object = ancestor;
168 ASSERT(ancestor->isDescendantOf(flowThread)); 176 ASSERT(ancestor->isDescendantOf(flowThread));
169 continue; // Continue on the outside of the inner flow thread. 177 continue; // Continue on the outside of the inner flow thread.
170 } 178 }
171 // We're inside something that's out-of-flow. Keep looking upwards and backw ards in the tree. 179 // We're inside something that's out-of-flow. Keep looking upwards and
180 // backwards in the tree.
172 object = object->previousInPreOrder(flowThread); 181 object = object->previousInPreOrder(flowThread);
173 } 182 }
174 if (!object || object == flowThread) 183 if (!object || object == flowThread)
175 return nullptr; 184 return nullptr;
176 #if ENABLE(ASSERT) 185 #if ENABLE(ASSERT)
177 // Make sure that we didn't stumble into an inner multicol container. 186 // Make sure that we didn't stumble into an inner multicol container.
178 for (LayoutObject* walker = object->parent(); walker && walker != flowThread; 187 for (LayoutObject* walker = object->parent(); walker && walker != flowThread;
179 walker = walker->parent()) 188 walker = walker->parent())
180 ASSERT(!isMultiColumnContainer(*walker)); 189 ASSERT(!isMultiColumnContainer(*walker));
181 #endif 190 #endif
182 return object; 191 return object;
183 } 192 }
184 193
185 static LayoutObject* firstLayoutObjectInSet(LayoutMultiColumnSet* multicolSet) { 194 static LayoutObject* firstLayoutObjectInSet(LayoutMultiColumnSet* multicolSet) {
186 LayoutBox* sibling = multicolSet->previousSiblingMultiColumnBox(); 195 LayoutBox* sibling = multicolSet->previousSiblingMultiColumnBox();
187 if (!sibling) 196 if (!sibling)
188 return multicolSet->flowThread()->firstChild(); 197 return multicolSet->flowThread()->firstChild();
189 // Adjacent column content sets should not occur. We would have no way of figu ring out what each 198 // Adjacent column content sets should not occur. We would have no way of
190 // of them contains then. 199 // figuring out what each of them contains then.
191 ASSERT(sibling->isLayoutMultiColumnSpannerPlaceholder()); 200 ASSERT(sibling->isLayoutMultiColumnSpannerPlaceholder());
192 LayoutBox* spanner = toLayoutMultiColumnSpannerPlaceholder(sibling) 201 LayoutBox* spanner = toLayoutMultiColumnSpannerPlaceholder(sibling)
193 ->layoutObjectInFlowThread(); 202 ->layoutObjectInFlowThread();
194 return nextInPreOrderAfterChildrenSkippingOutOfFlow( 203 return nextInPreOrderAfterChildrenSkippingOutOfFlow(
195 multicolSet->multiColumnFlowThread(), spanner); 204 multicolSet->multiColumnFlowThread(), spanner);
196 } 205 }
197 206
198 static LayoutObject* lastLayoutObjectInSet(LayoutMultiColumnSet* multicolSet) { 207 static LayoutObject* lastLayoutObjectInSet(LayoutMultiColumnSet* multicolSet) {
199 LayoutBox* sibling = multicolSet->nextSiblingMultiColumnBox(); 208 LayoutBox* sibling = multicolSet->nextSiblingMultiColumnBox();
209 // By right we should return lastLeafChild() here, but the caller doesn't
210 // care, so just return nullptr.
200 if (!sibling) 211 if (!sibling)
201 return nullptr; // By right we should return lastLeafChild() here, but the caller doesn't care, so just return 0. 212 return nullptr;
202 // Adjacent column content sets should not occur. We would have no way of figu ring out what each 213 // Adjacent column content sets should not occur. We would have no way of
203 // of them contains then. 214 // figuring out what each of them contains then.
204 ASSERT(sibling->isLayoutMultiColumnSpannerPlaceholder()); 215 ASSERT(sibling->isLayoutMultiColumnSpannerPlaceholder());
205 LayoutBox* spanner = toLayoutMultiColumnSpannerPlaceholder(sibling) 216 LayoutBox* spanner = toLayoutMultiColumnSpannerPlaceholder(sibling)
206 ->layoutObjectInFlowThread(); 217 ->layoutObjectInFlowThread();
207 return previousInPreOrderSkippingOutOfFlow( 218 return previousInPreOrderSkippingOutOfFlow(
208 multicolSet->multiColumnFlowThread(), spanner); 219 multicolSet->multiColumnFlowThread(), spanner);
209 } 220 }
210 221
211 LayoutMultiColumnSet* LayoutMultiColumnFlowThread::mapDescendantToColumnSet( 222 LayoutMultiColumnSet* LayoutMultiColumnFlowThread::mapDescendantToColumnSet(
212 LayoutObject* layoutObject) const { 223 LayoutObject* layoutObject) const {
213 ASSERT(!containingColumnSpannerPlaceholder( 224 // Should not be used for spanners or content inside them.
214 layoutObject)); // should not be used for spanners or content inside them . 225 DCHECK(!containingColumnSpannerPlaceholder(layoutObject));
215 ASSERT(layoutObject != this); 226 DCHECK(layoutObject != this);
216 ASSERT(layoutObject->isDescendantOf(this)); 227 DCHECK(layoutObject->isDescendantOf(this));
217 ASSERT(layoutObject->containingBlock()->isDescendantOf( 228 // Out-of-flow objects don't belong in column sets.
218 this)); // Out-of-flow objects don't belong in column sets. 229 DCHECK(layoutObject->containingBlock()->isDescendantOf(this));
219 ASSERT(layoutObject->flowThreadContainingBlock() == this); 230 DCHECK(layoutObject->flowThreadContainingBlock() == this);
220 ASSERT(!layoutObject->isLayoutMultiColumnSet()); 231 DCHECK(!layoutObject->isLayoutMultiColumnSet());
221 ASSERT(!layoutObject->isLayoutMultiColumnSpannerPlaceholder()); 232 DCHECK(!layoutObject->isLayoutMultiColumnSpannerPlaceholder());
222 LayoutMultiColumnSet* multicolSet = firstMultiColumnSet(); 233 LayoutMultiColumnSet* multicolSet = firstMultiColumnSet();
223 if (!multicolSet) 234 if (!multicolSet)
224 return nullptr; 235 return nullptr;
225 if (!multicolSet->nextSiblingMultiColumnSet()) 236 if (!multicolSet->nextSiblingMultiColumnSet())
226 return multicolSet; 237 return multicolSet;
227 238
228 // This is potentially SLOW! But luckily very uncommon. You would have to dyna mically insert a 239 // This is potentially SLOW! But luckily very uncommon. You would have to
229 // spanner into the middle of column contents to need this. 240 // dynamically insert a spanner into the middle of column contents to need
241 // this.
230 for (; multicolSet; multicolSet = multicolSet->nextSiblingMultiColumnSet()) { 242 for (; multicolSet; multicolSet = multicolSet->nextSiblingMultiColumnSet()) {
231 LayoutObject* firstLayoutObject = firstLayoutObjectInSet(multicolSet); 243 LayoutObject* firstLayoutObject = firstLayoutObjectInSet(multicolSet);
232 LayoutObject* lastLayoutObject = lastLayoutObjectInSet(multicolSet); 244 LayoutObject* lastLayoutObject = lastLayoutObjectInSet(multicolSet);
233 ASSERT(firstLayoutObject); 245 ASSERT(firstLayoutObject);
234 246
235 for (LayoutObject* walker = firstLayoutObject; walker; 247 for (LayoutObject* walker = firstLayoutObject; walker;
236 walker = walker->nextInPreOrder(this)) { 248 walker = walker->nextInPreOrder(this)) {
237 if (walker == layoutObject) 249 if (walker == layoutObject)
238 return multicolSet; 250 return multicolSet;
239 if (walker == lastLayoutObject) 251 if (walker == lastLayoutObject)
240 break; 252 break;
241 } 253 }
242 } 254 }
243 255
244 return nullptr; 256 return nullptr;
245 } 257 }
246 258
247 LayoutMultiColumnSpannerPlaceholder* 259 LayoutMultiColumnSpannerPlaceholder*
248 LayoutMultiColumnFlowThread::containingColumnSpannerPlaceholder( 260 LayoutMultiColumnFlowThread::containingColumnSpannerPlaceholder(
249 const LayoutObject* descendant) const { 261 const LayoutObject* descendant) const {
250 ASSERT(descendant->isDescendantOf(this)); 262 ASSERT(descendant->isDescendantOf(this));
251 263
252 if (!hasAnyColumnSpanners(*this)) 264 if (!hasAnyColumnSpanners(*this))
253 return nullptr; 265 return nullptr;
254 266
255 // We have spanners. See if the layoutObject in question is one or inside of o ne then. 267 // We have spanners. See if the layoutObject in question is one or inside of
268 // one then.
256 for (const LayoutObject* ancestor = descendant; ancestor && ancestor != this; 269 for (const LayoutObject* ancestor = descendant; ancestor && ancestor != this;
257 ancestor = ancestor->parent()) { 270 ancestor = ancestor->parent()) {
258 if (LayoutMultiColumnSpannerPlaceholder* placeholder = 271 if (LayoutMultiColumnSpannerPlaceholder* placeholder =
259 ancestor->spannerPlaceholder()) 272 ancestor->spannerPlaceholder())
260 return placeholder; 273 return placeholder;
261 } 274 }
262 return nullptr; 275 return nullptr;
263 } 276 }
264 277
265 void LayoutMultiColumnFlowThread::populate() { 278 void LayoutMultiColumnFlowThread::populate() {
266 LayoutBlockFlow* multicolContainer = multiColumnBlockFlow(); 279 LayoutBlockFlow* multicolContainer = multiColumnBlockFlow();
267 ASSERT(!nextSibling()); 280 ASSERT(!nextSibling());
268 // Reparent children preceding the flow thread into the flow thread. It's mult icol content 281 // Reparent children preceding the flow thread into the flow thread. It's
269 // now. At this point there's obviously nothing after the flow thread, but lay outObjects (column 282 // multicol content now. At this point there's obviously nothing after the
270 // sets and spanners) will be inserted there as we insert elements into the fl ow thread. 283 // flow thread, but layoutObjects (column sets and spanners) will be inserted
284 // there as we insert elements into the flow thread.
271 multicolContainer->removeFloatingObjectsFromDescendants(); 285 multicolContainer->removeFloatingObjectsFromDescendants();
272 multicolContainer->moveChildrenTo(this, multicolContainer->firstChild(), this, 286 multicolContainer->moveChildrenTo(this, multicolContainer->firstChild(), this,
273 true); 287 true);
274 } 288 }
275 289
276 void LayoutMultiColumnFlowThread::evacuateAndDestroy() { 290 void LayoutMultiColumnFlowThread::evacuateAndDestroy() {
277 LayoutBlockFlow* multicolContainer = multiColumnBlockFlow(); 291 LayoutBlockFlow* multicolContainer = multiColumnBlockFlow();
278 m_isBeingEvacuated = true; 292 m_isBeingEvacuated = true;
279 293
280 // Remove all sets and spanners. 294 // Remove all sets and spanners.
281 while (LayoutBox* columnBox = firstMultiColumnBox()) { 295 while (LayoutBox* columnBox = firstMultiColumnBox()) {
282 ASSERT(columnBox->isAnonymous()); 296 ASSERT(columnBox->isAnonymous());
283 columnBox->destroy(); 297 columnBox->destroy();
284 } 298 }
285 299
286 ASSERT(!previousSibling()); 300 ASSERT(!previousSibling());
287 ASSERT(!nextSibling()); 301 ASSERT(!nextSibling());
288 302
289 // Finally we can promote all flow thread's children. Before we move them to t he flow thread's 303 // Finally we can promote all flow thread's children. Before we move them to
290 // container, we need to unregister the flow thread, so that they aren't just re-added again to 304 // the flow thread's container, we need to unregister the flow thread, so that
291 // the flow thread that we're trying to empty. 305 // they aren't just re-added again to the flow thread that we're trying to
306 // empty.
292 multicolContainer->resetMultiColumnFlowThread(); 307 multicolContainer->resetMultiColumnFlowThread();
293 moveAllChildrenTo(multicolContainer, true); 308 moveAllChildrenTo(multicolContainer, true);
294 309
295 // We used to manually nuke the line box tree here, but that should happen aut omatically when 310 // We used to manually nuke the line box tree here, but that should happen
296 // moving children around (the code above). 311 // automatically when moving children around (the code above).
297 ASSERT(!firstLineBox()); 312 ASSERT(!firstLineBox());
298 313
299 destroy(); 314 destroy();
300 } 315 }
301 316
302 LayoutUnit LayoutMultiColumnFlowThread::maxColumnLogicalHeight() const { 317 LayoutUnit LayoutMultiColumnFlowThread::maxColumnLogicalHeight() const {
303 if (m_columnHeightAvailable) { 318 if (m_columnHeightAvailable) {
304 // If height is non-auto, it's already constrained against max-height as wel l. 319 // If height is non-auto, it's already constrained against max-height as
305 // Just return it. 320 // well. Just return it.
306 return m_columnHeightAvailable; 321 return m_columnHeightAvailable;
307 } 322 }
308 const LayoutBlockFlow* multicolBlock = multiColumnBlockFlow(); 323 const LayoutBlockFlow* multicolBlock = multiColumnBlockFlow();
309 Length logicalMaxHeight = multicolBlock->style()->logicalMaxHeight(); 324 Length logicalMaxHeight = multicolBlock->style()->logicalMaxHeight();
310 if (!logicalMaxHeight.isMaxSizeNone()) { 325 if (!logicalMaxHeight.isMaxSizeNone()) {
311 LayoutUnit resolvedLogicalMaxHeight = 326 LayoutUnit resolvedLogicalMaxHeight =
312 multicolBlock->computeContentLogicalHeight(MaxSize, logicalMaxHeight, 327 multicolBlock->computeContentLogicalHeight(MaxSize, logicalMaxHeight,
313 LayoutUnit(-1)); 328 LayoutUnit(-1));
314 if (resolvedLogicalMaxHeight != -1) 329 if (resolvedLogicalMaxHeight != -1)
315 return resolvedLogicalMaxHeight; 330 return resolvedLogicalMaxHeight;
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
358 mode); 373 mode);
359 } 374 }
360 375
361 LayoutSize LayoutMultiColumnFlowThread::flowThreadTranslationAtPoint( 376 LayoutSize LayoutMultiColumnFlowThread::flowThreadTranslationAtPoint(
362 const LayoutPoint& flowThreadPoint, 377 const LayoutPoint& flowThreadPoint,
363 CoordinateSpaceConversion mode) const { 378 CoordinateSpaceConversion mode) const {
364 LayoutPoint flippedPoint = flipForWritingMode(flowThreadPoint); 379 LayoutPoint flippedPoint = flipForWritingMode(flowThreadPoint);
365 LayoutUnit blockOffset = 380 LayoutUnit blockOffset =
366 isHorizontalWritingMode() ? flippedPoint.y() : flippedPoint.x(); 381 isHorizontalWritingMode() ? flippedPoint.y() : flippedPoint.x();
367 382
368 // If block direction is flipped, points at a column boundary belong in the fo rmer column, not 383 // If block direction is flipped, points at a column boundary belong in the
369 // the latter. 384 // former column, not the latter.
370 PageBoundaryRule rule = hasFlippedBlocksWritingMode() 385 PageBoundaryRule rule = hasFlippedBlocksWritingMode()
371 ? AssociateWithFormerPage 386 ? AssociateWithFormerPage
372 : AssociateWithLatterPage; 387 : AssociateWithLatterPage;
373 388
374 return flowThreadTranslationAtOffset(blockOffset, rule, mode); 389 return flowThreadTranslationAtOffset(blockOffset, rule, mode);
375 } 390 }
376 391
377 LayoutPoint LayoutMultiColumnFlowThread::flowThreadPointToVisualPoint( 392 LayoutPoint LayoutMultiColumnFlowThread::flowThreadPointToVisualPoint(
378 const LayoutPoint& flowThreadPoint) const { 393 const LayoutPoint& flowThreadPoint) const {
379 return flowThreadPoint + 394 return flowThreadPoint +
(...skipping 29 matching lines...) Expand all
409 return (baselineInFlowThread - 424 return (baselineInFlowThread -
410 columnSet->pageLogicalTopForOffset(baselineInFlowThread)) 425 columnSet->pageLogicalTopForOffset(baselineInFlowThread))
411 .ceil(); 426 .ceil();
412 } 427 }
413 428
414 LayoutMultiColumnSet* LayoutMultiColumnFlowThread::columnSetAtBlockOffset( 429 LayoutMultiColumnSet* LayoutMultiColumnFlowThread::columnSetAtBlockOffset(
415 LayoutUnit offset, 430 LayoutUnit offset,
416 PageBoundaryRule pageBoundaryRule) const { 431 PageBoundaryRule pageBoundaryRule) const {
417 LayoutMultiColumnSet* columnSet = m_lastSetWorkedOn; 432 LayoutMultiColumnSet* columnSet = m_lastSetWorkedOn;
418 if (columnSet) { 433 if (columnSet) {
419 // Layout in progress. We are calculating the set heights as we speak, so th e column set range 434 // Layout in progress. We are calculating the set heights as we speak, so
420 // information is not up to date. 435 // the column set range information is not up to date.
421 while (columnSet->logicalTopInFlowThread() > offset) { 436 while (columnSet->logicalTopInFlowThread() > offset) {
422 // Sometimes we have to use a previous set. This happens when we're workin g with a block 437 // Sometimes we have to use a previous set. This happens when we're
423 // that contains a spanner (so that there's a column set both before and a fter the 438 // working with a block that contains a spanner (so that there's a column
424 // spanner, and both sets contain said block). 439 // set both before and after the spanner, and both sets contain said
440 // block).
425 LayoutMultiColumnSet* previousSet = 441 LayoutMultiColumnSet* previousSet =
426 columnSet->previousSiblingMultiColumnSet(); 442 columnSet->previousSiblingMultiColumnSet();
427 if (!previousSet) 443 if (!previousSet)
428 break; 444 break;
429 columnSet = previousSet; 445 columnSet = previousSet;
430 } 446 }
431 } else { 447 } else {
432 DCHECK(!m_columnSetsInvalidated); 448 DCHECK(!m_columnSetsInvalidated);
433 if (m_multiColumnSetList.isEmpty()) 449 if (m_multiColumnSetList.isEmpty())
434 return nullptr; 450 return nullptr;
435 if (offset < LayoutUnit()) 451 if (offset < LayoutUnit())
436 return m_multiColumnSetList.first(); 452 return m_multiColumnSetList.first();
437 453
438 MultiColumnSetSearchAdapter adapter(offset); 454 MultiColumnSetSearchAdapter adapter(offset);
439 m_multiColumnSetIntervalTree 455 m_multiColumnSetIntervalTree
440 .allOverlapsWithAdapter<MultiColumnSetSearchAdapter>(adapter); 456 .allOverlapsWithAdapter<MultiColumnSetSearchAdapter>(adapter);
441 457
442 // If no set was found, the offset is in the flow thread overflow. 458 // If no set was found, the offset is in the flow thread overflow.
443 if (!adapter.result() && !m_multiColumnSetList.isEmpty()) 459 if (!adapter.result() && !m_multiColumnSetList.isEmpty())
444 return m_multiColumnSetList.last(); 460 return m_multiColumnSetList.last();
445 columnSet = adapter.result(); 461 columnSet = adapter.result();
446 } 462 }
447 if (pageBoundaryRule == AssociateWithFormerPage && columnSet && 463 if (pageBoundaryRule == AssociateWithFormerPage && columnSet &&
448 offset == columnSet->logicalTopInFlowThread()) { 464 offset == columnSet->logicalTopInFlowThread()) {
449 // The column set that we found starts at the exact same flow thread offset as we specified. 465 // The column set that we found starts at the exact same flow thread offset
450 // Since we are to associate offsets at boundaries with the former fragmenta iner, the 466 // as we specified. Since we are to associate offsets at boundaries with the
451 // fragmentainer we're looking for is in the previous column set. 467 // former fragmentainer, the fragmentainer we're looking for is in the
468 // previous column set.
452 if (LayoutMultiColumnSet* previousSet = 469 if (LayoutMultiColumnSet* previousSet =
453 columnSet->previousSiblingMultiColumnSet()) 470 columnSet->previousSiblingMultiColumnSet())
454 return previousSet; 471 return previousSet;
455 } 472 }
456 return columnSet; 473 return columnSet;
457 } 474 }
458 475
459 void LayoutMultiColumnFlowThread::layoutColumns( 476 void LayoutMultiColumnFlowThread::layoutColumns(
460 SubtreeLayoutScope& layoutScope) { 477 SubtreeLayoutScope& layoutScope) {
461 // Since we ended up here, it means that the multicol container (our parent) n eeded 478 // Since we ended up here, it means that the multicol container (our parent)
462 // layout. Since contents of the multicol container are diverted to the flow t hread, the flow 479 // needed layout. Since contents of the multicol container are diverted to the
463 // thread needs layout as well. 480 // flow thread, the flow thread needs layout as well.
464 layoutScope.setChildNeedsLayout(this); 481 layoutScope.setChildNeedsLayout(this);
465 482
466 if (FragmentationContext* enclosingFragmentationContext = 483 if (FragmentationContext* enclosingFragmentationContext =
467 this->enclosingFragmentationContext()) { 484 this->enclosingFragmentationContext()) {
468 m_blockOffsetInEnclosingFragmentationContext = 485 m_blockOffsetInEnclosingFragmentationContext =
469 multiColumnBlockFlow()->offsetFromLogicalTopOfFirstPage(); 486 multiColumnBlockFlow()->offsetFromLogicalTopOfFirstPage();
470 m_blockOffsetInEnclosingFragmentationContext += 487 m_blockOffsetInEnclosingFragmentationContext +=
471 multiColumnBlockFlow()->borderAndPaddingBefore(); 488 multiColumnBlockFlow()->borderAndPaddingBefore();
472 489
473 if (LayoutMultiColumnFlowThread* enclosingFlowThread = 490 if (LayoutMultiColumnFlowThread* enclosingFlowThread =
474 enclosingFragmentationContext->associatedFlowThread()) { 491 enclosingFragmentationContext->associatedFlowThread()) {
475 if (LayoutMultiColumnSet* firstSet = firstMultiColumnSet()) { 492 if (LayoutMultiColumnSet* firstSet = firstMultiColumnSet()) {
476 // Before we can start to lay out the contents of this multicol containe r, we need 493 // Before we can start to lay out the contents of this multicol
477 // to make sure that all ancestor multicol containers have established a row to hold 494 // container, we need to make sure that all ancestor multicol containers
478 // the first column contents of this container (this multicol container may start at 495 // have established a row to hold the first column contents of this
479 // the beginning of a new outer row). Without sufficient rows in all anc estor 496 // container (this multicol container may start at the beginning of a
480 // multicol containers, we may use the wrong column height. 497 // new outer row). Without sufficient rows in all ancestor multicol
498 // containers, we may use the wrong column height.
481 LayoutUnit offset = m_blockOffsetInEnclosingFragmentationContext + 499 LayoutUnit offset = m_blockOffsetInEnclosingFragmentationContext +
482 firstSet->logicalTopFromMulticolContentEdge(); 500 firstSet->logicalTopFromMulticolContentEdge();
483 enclosingFlowThread->appendNewFragmentainerGroupIfNeeded( 501 enclosingFlowThread->appendNewFragmentainerGroupIfNeeded(
484 offset, AssociateWithLatterPage); 502 offset, AssociateWithLatterPage);
485 } 503 }
486 } 504 }
487 } 505 }
488 506
489 for (LayoutBox* columnBox = firstMultiColumnBox(); columnBox; 507 for (LayoutBox* columnBox = firstMultiColumnBox(); columnBox;
490 columnBox = columnBox->nextSiblingMultiColumnBox()) { 508 columnBox = columnBox->nextSiblingMultiColumnBox()) {
491 if (!columnBox->isLayoutMultiColumnSet()) { 509 if (!columnBox->isLayoutMultiColumnSet()) {
492 ASSERT( 510 // No other type is expected.
493 columnBox 511 DCHECK(columnBox->isLayoutMultiColumnSpannerPlaceholder());
494 ->isLayoutMultiColumnSpannerPlaceholder()); // no other type is e xpected.
495 continue; 512 continue;
496 } 513 }
497 LayoutMultiColumnSet* columnSet = toLayoutMultiColumnSet(columnBox); 514 LayoutMultiColumnSet* columnSet = toLayoutMultiColumnSet(columnBox);
498 layoutScope.setChildNeedsLayout(columnSet); 515 layoutScope.setChildNeedsLayout(columnSet);
499 if (!m_columnHeightsChanged) { 516 if (!m_columnHeightsChanged) {
500 // This is the initial layout pass. We need to reset the column height, be cause contents 517 // This is the initial layout pass. We need to reset the column height,
501 // typically have changed. 518 // because contents typically have changed.
502 columnSet->resetColumnHeight(); 519 columnSet->resetColumnHeight();
503 } 520 }
504 // Since column sets are regular block flow objects, and their position is c hanged in 521 // Since column sets are regular block flow objects, and their position is
505 // regular block layout code (with no means for the multicol code to notice unless we add 522 // changed in regular block layout code (with no means for the multicol code
506 // hooks there), store the previous position now. If it changes in the immin ent layout 523 // to notice unless we add hooks there), store the previous position now. If
507 // pass, we may have to rebalance its columns. 524 // it changes in the imminent layout pass, we may have to rebalance its
525 // columns.
508 columnSet->storeOldPosition(); 526 columnSet->storeOldPosition();
509 } 527 }
510 528
511 m_columnHeightsChanged = false; 529 m_columnHeightsChanged = false;
512 invalidateColumnSets(); 530 invalidateColumnSets();
513 layout(); 531 layout();
514 validateColumnSets(); 532 validateColumnSets();
515 } 533 }
516 534
517 void LayoutMultiColumnFlowThread::columnRuleStyleDidChange() { 535 void LayoutMultiColumnFlowThread::columnRuleStyleDidChange() {
518 for (LayoutMultiColumnSet* columnSet = firstMultiColumnSet(); columnSet; 536 for (LayoutMultiColumnSet* columnSet = firstMultiColumnSet(); columnSet;
519 columnSet = columnSet->nextSiblingMultiColumnSet()) 537 columnSet = columnSet->nextSiblingMultiColumnSet())
520 columnSet->setShouldDoFullPaintInvalidation(PaintInvalidationStyleChange); 538 columnSet->setShouldDoFullPaintInvalidation(PaintInvalidationStyleChange);
521 } 539 }
522 540
523 bool LayoutMultiColumnFlowThread::removeSpannerPlaceholderIfNoLongerValid( 541 bool LayoutMultiColumnFlowThread::removeSpannerPlaceholderIfNoLongerValid(
524 LayoutBox* spannerObjectInFlowThread) { 542 LayoutBox* spannerObjectInFlowThread) {
525 ASSERT(spannerObjectInFlowThread->spannerPlaceholder()); 543 ASSERT(spannerObjectInFlowThread->spannerPlaceholder());
526 if (descendantIsValidColumnSpanner(spannerObjectInFlowThread)) 544 if (descendantIsValidColumnSpanner(spannerObjectInFlowThread))
527 return false; // Still a valid spanner. 545 return false; // Still a valid spanner.
528 546
529 // No longer a valid spanner. Get rid of the placeholder. 547 // No longer a valid spanner. Get rid of the placeholder.
530 destroySpannerPlaceholder(spannerObjectInFlowThread->spannerPlaceholder()); 548 destroySpannerPlaceholder(spannerObjectInFlowThread->spannerPlaceholder());
531 ASSERT(!spannerObjectInFlowThread->spannerPlaceholder()); 549 ASSERT(!spannerObjectInFlowThread->spannerPlaceholder());
532 550
533 // We may have a new containing block, since we're no longer a spanner. Mark i t for relayout. 551 // We may have a new containing block, since we're no longer a spanner. Mark
552 // it for relayout.
534 spannerObjectInFlowThread->containingBlock() 553 spannerObjectInFlowThread->containingBlock()
535 ->setNeedsLayoutAndPrefWidthsRecalc( 554 ->setNeedsLayoutAndPrefWidthsRecalc(
536 LayoutInvalidationReason::ColumnsChanged); 555 LayoutInvalidationReason::ColumnsChanged);
537 556
538 // Now generate a column set for this ex-spanner, if needed and none is there for us already. 557 // Now generate a column set for this ex-spanner, if needed and none is there
558 // for us already.
539 flowThreadDescendantWasInserted(spannerObjectInFlowThread); 559 flowThreadDescendantWasInserted(spannerObjectInFlowThread);
540 560
541 return true; 561 return true;
542 } 562 }
543 563
544 LayoutMultiColumnFlowThread* LayoutMultiColumnFlowThread::enclosingFlowThread() 564 LayoutMultiColumnFlowThread* LayoutMultiColumnFlowThread::enclosingFlowThread()
545 const { 565 const {
546 if (isLayoutPagedFlowThread()) { 566 if (isLayoutPagedFlowThread()) {
547 // Paged overflow containers should never be fragmented by enclosing fragmen tation 567 // Paged overflow containers should never be fragmented by enclosing
548 // contexts. They are to be treated as unbreakable content. 568 // fragmentation contexts. They are to be treated as unbreakable content.
549 return nullptr; 569 return nullptr;
550 } 570 }
551 if (multiColumnBlockFlow()->isInsideFlowThread()) 571 if (multiColumnBlockFlow()->isInsideFlowThread())
552 return toLayoutMultiColumnFlowThread( 572 return toLayoutMultiColumnFlowThread(
553 locateFlowThreadContainingBlockOf(*multiColumnBlockFlow())); 573 locateFlowThreadContainingBlockOf(*multiColumnBlockFlow()));
554 return nullptr; 574 return nullptr;
555 } 575 }
556 576
557 FragmentationContext* 577 FragmentationContext*
558 LayoutMultiColumnFlowThread::enclosingFragmentationContext() const { 578 LayoutMultiColumnFlowThread::enclosingFragmentationContext() const {
559 if (LayoutMultiColumnFlowThread* enclosingFlowThread = 579 if (LayoutMultiColumnFlowThread* enclosingFlowThread =
560 this->enclosingFlowThread()) 580 this->enclosingFlowThread())
561 return enclosingFlowThread; 581 return enclosingFlowThread;
562 return view()->fragmentationContext(); 582 return view()->fragmentationContext();
563 } 583 }
564 584
565 void LayoutMultiColumnFlowThread::appendNewFragmentainerGroupIfNeeded( 585 void LayoutMultiColumnFlowThread::appendNewFragmentainerGroupIfNeeded(
566 LayoutUnit offsetInFlowThread, 586 LayoutUnit offsetInFlowThread,
567 PageBoundaryRule pageBoundaryRule) { 587 PageBoundaryRule pageBoundaryRule) {
568 if (!isPageLogicalHeightKnown()) { 588 if (!isPageLogicalHeightKnown()) {
569 // If we have no clue about the height of the multicol container, bail. This situation 589 // If we have no clue about the height of the multicol container, bail. This
570 // occurs initially when an auto-height multicol container is nested inside another 590 // situation occurs initially when an auto-height multicol container is
571 // auto-height multicol container. We need at least an estimated height of t he outer 591 // nested inside another auto-height multicol container. We need at least an
572 // multicol container before we can check what an inner fragmentainer group has room for. 592 // estimated height of the outer multicol container before we can check what
593 // an inner fragmentainer group has room for.
573 // Its height is indefinite for now. 594 // Its height is indefinite for now.
574 return; 595 return;
575 } 596 }
576 LayoutMultiColumnSet* columnSet = 597 LayoutMultiColumnSet* columnSet =
577 columnSetAtBlockOffset(offsetInFlowThread, pageBoundaryRule); 598 columnSetAtBlockOffset(offsetInFlowThread, pageBoundaryRule);
578 if (columnSet->isInitialHeightCalculated()) { 599 if (columnSet->isInitialHeightCalculated()) {
579 // We only insert additional fragmentainer groups in the initial layout pass . We only want 600 // We only insert additional fragmentainer groups in the initial layout
580 // to balance columns in the last fragmentainer group (if we need to balance at all), so we 601 // pass. We only want to balance columns in the last fragmentainer group (if
581 // want that last fragmentainer group to be the same one in all layout passe s that follow. 602 // we need to balance at all), so we want that last fragmentainer group to
603 // be the same one in all layout passes that follow.
582 return; 604 return;
583 } 605 }
584 606
585 if (!columnSet->hasFragmentainerGroupForColumnAt(offsetInFlowThread, 607 if (!columnSet->hasFragmentainerGroupForColumnAt(offsetInFlowThread,
586 pageBoundaryRule)) { 608 pageBoundaryRule)) {
587 FragmentationContext* enclosingFragmentationContext = 609 FragmentationContext* enclosingFragmentationContext =
588 this->enclosingFragmentationContext(); 610 this->enclosingFragmentationContext();
611 // Not nested. We'll never need more rows than the one we already have then.
589 if (!enclosingFragmentationContext) 612 if (!enclosingFragmentationContext)
590 return; // Not nested. We'll never need more rows than the one we already have then. 613 return;
591 ASSERT(!isLayoutPagedFlowThread()); 614 ASSERT(!isLayoutPagedFlowThread());
592 615
593 // We have run out of columns here, so we need to add at least one more row to hold more 616 // We have run out of columns here, so we need to add at least one more row
594 // columns. 617 // to hold more columns.
595 LayoutMultiColumnFlowThread* enclosingFlowThread = 618 LayoutMultiColumnFlowThread* enclosingFlowThread =
596 enclosingFragmentationContext->associatedFlowThread(); 619 enclosingFragmentationContext->associatedFlowThread();
597 do { 620 do {
598 if (enclosingFlowThread) { 621 if (enclosingFlowThread) {
599 // When we add a new row here, it implicitly means that we're inserting another 622 // When we add a new row here, it implicitly means that we're inserting
600 // column in our enclosing multicol container. That in turn may mean tha t we've run 623 // another column in our enclosing multicol container. That in turn may
601 // out of columns there too. Need to insert additional rows in ancestral multicol 624 // mean that we've run out of columns there too. Need to insert
602 // containers before doing it in the descendants, in order to get the he ight 625 // additional rows in ancestral multicol containers before doing it in
603 // constraints right down there. 626 // the descendants, in order to get the height constraints right down
627 // there.
604 const MultiColumnFragmentainerGroup& lastRow = 628 const MultiColumnFragmentainerGroup& lastRow =
605 columnSet->lastFragmentainerGroup(); 629 columnSet->lastFragmentainerGroup();
606 // The top offset where where the new fragmentainer group will start in this column 630 // The top offset where where the new fragmentainer group will start in
607 // set, converted to the coordinate space of the enclosing multicol cont ainer. 631 // this column set, converted to the coordinate space of the enclosing
632 // multicol container.
608 LayoutUnit logicalOffsetInOuter = 633 LayoutUnit logicalOffsetInOuter =
609 lastRow.blockOffsetInEnclosingFragmentationContext() + 634 lastRow.blockOffsetInEnclosingFragmentationContext() +
610 lastRow.logicalHeight(); 635 lastRow.logicalHeight();
611 enclosingFlowThread->appendNewFragmentainerGroupIfNeeded( 636 enclosingFlowThread->appendNewFragmentainerGroupIfNeeded(
612 logicalOffsetInOuter, AssociateWithLatterPage); 637 logicalOffsetInOuter, AssociateWithLatterPage);
613 } 638 }
614 639
615 const MultiColumnFragmentainerGroup& newRow = 640 const MultiColumnFragmentainerGroup& newRow =
616 columnSet->appendNewFragmentainerGroup(); 641 columnSet->appendNewFragmentainerGroup();
617 // Zero-height rows should really not occur here, but if it does anyway, b reak, so that 642 // Zero-height rows should really not occur here, but if it does anyway,
618 // we don't get stuck in an infinite loop. 643 // break, so that we don't get stuck in an infinite loop.
619 ASSERT(newRow.logicalHeight() > 0); 644 ASSERT(newRow.logicalHeight() > 0);
620 if (newRow.logicalHeight() <= 0) 645 if (newRow.logicalHeight() <= 0)
621 break; 646 break;
622 } while (!columnSet->hasFragmentainerGroupForColumnAt(offsetInFlowThread, 647 } while (!columnSet->hasFragmentainerGroupForColumnAt(offsetInFlowThread,
623 pageBoundaryRule)); 648 pageBoundaryRule));
624 } 649 }
625 } 650 }
626 651
627 bool LayoutMultiColumnFlowThread::isFragmentainerLogicalHeightKnown() { 652 bool LayoutMultiColumnFlowThread::isFragmentainerLogicalHeightKnown() {
628 return isPageLogicalHeightKnown(); 653 return isPageLogicalHeightKnown();
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
673 } 698 }
674 699
675 void LayoutMultiColumnFlowThread::createAndInsertMultiColumnSet( 700 void LayoutMultiColumnFlowThread::createAndInsertMultiColumnSet(
676 LayoutBox* insertBefore) { 701 LayoutBox* insertBefore) {
677 LayoutBlockFlow* multicolContainer = multiColumnBlockFlow(); 702 LayoutBlockFlow* multicolContainer = multiColumnBlockFlow();
678 LayoutMultiColumnSet* newSet = LayoutMultiColumnSet::createAnonymous( 703 LayoutMultiColumnSet* newSet = LayoutMultiColumnSet::createAnonymous(
679 *this, multicolContainer->styleRef()); 704 *this, multicolContainer->styleRef());
680 multicolContainer->LayoutBlock::addChild(newSet, insertBefore); 705 multicolContainer->LayoutBlock::addChild(newSet, insertBefore);
681 invalidateColumnSets(); 706 invalidateColumnSets();
682 707
683 // We cannot handle immediate column set siblings (and there's no need for it, either). 708 // We cannot handle immediate column set siblings (and there's no need for it,
684 // There has to be at least one spanner separating them. 709 // either). There has to be at least one spanner separating them.
685 ASSERT(!newSet->previousSiblingMultiColumnBox() || 710 ASSERT(!newSet->previousSiblingMultiColumnBox() ||
686 !newSet->previousSiblingMultiColumnBox()->isLayoutMultiColumnSet()); 711 !newSet->previousSiblingMultiColumnBox()->isLayoutMultiColumnSet());
687 ASSERT(!newSet->nextSiblingMultiColumnBox() || 712 ASSERT(!newSet->nextSiblingMultiColumnBox() ||
688 !newSet->nextSiblingMultiColumnBox()->isLayoutMultiColumnSet()); 713 !newSet->nextSiblingMultiColumnBox()->isLayoutMultiColumnSet());
689 } 714 }
690 715
691 void LayoutMultiColumnFlowThread::createAndInsertSpannerPlaceholder( 716 void LayoutMultiColumnFlowThread::createAndInsertSpannerPlaceholder(
692 LayoutBox* spannerObjectInFlowThread, 717 LayoutBox* spannerObjectInFlowThread,
693 LayoutObject* insertedBeforeInFlowThread) { 718 LayoutObject* insertedBeforeInFlowThread) {
694 LayoutBox* insertBeforeColumnBox = nullptr; 719 LayoutBox* insertBeforeColumnBox = nullptr;
695 LayoutMultiColumnSet* setToSplit = nullptr; 720 LayoutMultiColumnSet* setToSplit = nullptr;
696 if (insertedBeforeInFlowThread) { 721 if (insertedBeforeInFlowThread) {
697 // The spanner is inserted before something. Figure out what this entails. I f the 722 // The spanner is inserted before something. Figure out what this entails.
698 // next object is a spanner too, it means that we can simply insert a new sp anner 723 // If the next object is a spanner too, it means that we can simply insert a
699 // placeholder in front of its placeholder. 724 // new spanner placeholder in front of its placeholder.
700 insertBeforeColumnBox = insertedBeforeInFlowThread->spannerPlaceholder(); 725 insertBeforeColumnBox = insertedBeforeInFlowThread->spannerPlaceholder();
701 if (!insertBeforeColumnBox) { 726 if (!insertBeforeColumnBox) {
702 // The next object isn't a spanner; it's regular column content. Examine w hat 727 // The next object isn't a spanner; it's regular column content. Examine
703 // comes right before us in the flow thread, then. 728 // what comes right before us in the flow thread, then.
704 LayoutObject* previousLayoutObject = 729 LayoutObject* previousLayoutObject =
705 previousInPreOrderSkippingOutOfFlow(this, spannerObjectInFlowThread); 730 previousInPreOrderSkippingOutOfFlow(this, spannerObjectInFlowThread);
706 if (!previousLayoutObject || previousLayoutObject == this) { 731 if (!previousLayoutObject || previousLayoutObject == this) {
707 // The spanner is inserted as the first child of the multicol container, 732 // The spanner is inserted as the first child of the multicol container,
708 // which means that we simply insert a new spanner placeholder at the 733 // which means that we simply insert a new spanner placeholder at the
709 // beginning. 734 // beginning.
710 insertBeforeColumnBox = firstMultiColumnBox(); 735 insertBeforeColumnBox = firstMultiColumnBox();
711 } else if (LayoutMultiColumnSpannerPlaceholder* previousPlaceholder = 736 } else if (LayoutMultiColumnSpannerPlaceholder* previousPlaceholder =
712 containingColumnSpannerPlaceholder(previousLayoutObject)) { 737 containingColumnSpannerPlaceholder(previousLayoutObject)) {
713 // Before us is another spanner. We belong right after it then. 738 // Before us is another spanner. We belong right after it then.
714 insertBeforeColumnBox = 739 insertBeforeColumnBox =
715 previousPlaceholder->nextSiblingMultiColumnBox(); 740 previousPlaceholder->nextSiblingMultiColumnBox();
716 } else { 741 } else {
717 // We're inside regular column content with both feet. Find out which co lumn 742 // We're inside regular column content with both feet. Find out which
718 // set this is. It needs to be split it into two sets, so that we can in sert 743 // column set this is. It needs to be split it into two sets, so that we
719 // a new spanner placeholder between them. 744 // can insert a new spanner placeholder between them.
720 setToSplit = mapDescendantToColumnSet(previousLayoutObject); 745 setToSplit = mapDescendantToColumnSet(previousLayoutObject);
721 ASSERT(setToSplit == 746 ASSERT(setToSplit ==
722 mapDescendantToColumnSet(insertedBeforeInFlowThread)); 747 mapDescendantToColumnSet(insertedBeforeInFlowThread));
723 insertBeforeColumnBox = setToSplit->nextSiblingMultiColumnBox(); 748 insertBeforeColumnBox = setToSplit->nextSiblingMultiColumnBox();
724 // We've found out which set that needs to be split. Now proceed to 749 // We've found out which set that needs to be split. Now proceed to
725 // inserting the spanner placeholder, and then insert a second column se t. 750 // inserting the spanner placeholder, and then insert a second column
751 // set.
726 } 752 }
727 } 753 }
728 ASSERT(setToSplit || insertBeforeColumnBox); 754 ASSERT(setToSplit || insertBeforeColumnBox);
729 } 755 }
730 756
731 LayoutBlockFlow* multicolContainer = multiColumnBlockFlow(); 757 LayoutBlockFlow* multicolContainer = multiColumnBlockFlow();
732 LayoutMultiColumnSpannerPlaceholder* newPlaceholder = 758 LayoutMultiColumnSpannerPlaceholder* newPlaceholder =
733 LayoutMultiColumnSpannerPlaceholder::createAnonymous( 759 LayoutMultiColumnSpannerPlaceholder::createAnonymous(
734 multicolContainer->styleRef(), *spannerObjectInFlowThread); 760 multicolContainer->styleRef(), *spannerObjectInFlowThread);
735 ASSERT(!insertBeforeColumnBox || 761 ASSERT(!insertBeforeColumnBox ||
(...skipping 16 matching lines...) Expand all
752 nextColumnBox->destroy(); 778 nextColumnBox->destroy();
753 invalidateColumnSets(); 779 invalidateColumnSets();
754 } 780 }
755 } 781 }
756 placeholder->destroy(); 782 placeholder->destroy();
757 } 783 }
758 784
759 bool LayoutMultiColumnFlowThread::descendantIsValidColumnSpanner( 785 bool LayoutMultiColumnFlowThread::descendantIsValidColumnSpanner(
760 LayoutObject* descendant) const { 786 LayoutObject* descendant) const {
761 // This method needs to behave correctly in the following situations: 787 // This method needs to behave correctly in the following situations:
762 // - When the descendant doesn't have a spanner placeholder but should have on e (return true) 788 // - When the descendant doesn't have a spanner placeholder but should have
763 // - When the descendant doesn't have a spanner placeholder and still should n ot have one (return false) 789 // one (return true).
764 // - When the descendant has a spanner placeholder but should no longer have o ne (return false) 790 // - When the descendant doesn't have a spanner placeholder and still should
765 // - When the descendant has a spanner placeholder and should still have one ( return true) 791 // not have one (return false).
792 // - When the descendant has a spanner placeholder but should no longer have
793 // one (return false).
794 // - When the descendant has a spanner placeholder and should still have one
795 // (return true).
766 796
767 // We assume that we're inside the flow thread. This function is not to be cal led otherwise. 797 // We assume that we're inside the flow thread. This function is not to be
798 // called otherwise.
768 ASSERT(descendant->isDescendantOf(this)); 799 ASSERT(descendant->isDescendantOf(this));
769 800
770 // The spec says that column-span only applies to in-flow block-level elements . 801 // The spec says that column-span only applies to in-flow block-level
802 // elements.
771 if (descendant->style()->getColumnSpan() != ColumnSpanAll || 803 if (descendant->style()->getColumnSpan() != ColumnSpanAll ||
772 !descendant->isBox() || descendant->isInline() || 804 !descendant->isBox() || descendant->isInline() ||
773 descendant->isFloatingOrOutOfFlowPositioned()) 805 descendant->isFloatingOrOutOfFlowPositioned())
774 return false; 806 return false;
775 807
776 if (!descendant->containingBlock()->isLayoutBlockFlow()) { 808 if (!descendant->containingBlock()->isLayoutBlockFlow()) {
777 // Needs to be in a block-flow container, and not e.g. a table. 809 // Needs to be in a block-flow container, and not e.g. a table.
778 return false; 810 return false;
779 } 811 }
780 812
781 // This looks like a spanner, but if we're inside something unbreakable or som ething that 813 // This looks like a spanner, but if we're inside something unbreakable or
782 // establishes a new formatting context, it's not to be treated as one. 814 // something that establishes a new formatting context, it's not to be treated
815 // as one.
783 for (LayoutBox* ancestor = toLayoutBox(descendant)->parentBox(); ancestor; 816 for (LayoutBox* ancestor = toLayoutBox(descendant)->parentBox(); ancestor;
784 ancestor = ancestor->containingBlock()) { 817 ancestor = ancestor->containingBlock()) {
785 if (ancestor->isLayoutFlowThread()) { 818 if (ancestor->isLayoutFlowThread()) {
786 ASSERT(ancestor == this); 819 ASSERT(ancestor == this);
787 return true; 820 return true;
788 } 821 }
789 if (!canContainSpannerInParentFragmentationContext(*ancestor)) 822 if (!canContainSpannerInParentFragmentationContext(*ancestor))
790 return false; 823 return false;
791 } 824 }
792 ASSERT_NOT_REACHED(); 825 ASSERT_NOT_REACHED();
793 return false; 826 return false;
794 } 827 }
795 828
796 void LayoutMultiColumnFlowThread::addColumnSetToThread( 829 void LayoutMultiColumnFlowThread::addColumnSetToThread(
797 LayoutMultiColumnSet* columnSet) { 830 LayoutMultiColumnSet* columnSet) {
798 if (LayoutMultiColumnSet* nextSet = columnSet->nextSiblingMultiColumnSet()) { 831 if (LayoutMultiColumnSet* nextSet = columnSet->nextSiblingMultiColumnSet()) {
799 LayoutMultiColumnSetList::iterator it = m_multiColumnSetList.find(nextSet); 832 LayoutMultiColumnSetList::iterator it = m_multiColumnSetList.find(nextSet);
800 ASSERT(it != m_multiColumnSetList.end()); 833 ASSERT(it != m_multiColumnSetList.end());
801 m_multiColumnSetList.insertBefore(it, columnSet); 834 m_multiColumnSetList.insertBefore(it, columnSet);
802 } else { 835 } else {
803 m_multiColumnSetList.add(columnSet); 836 m_multiColumnSetList.add(columnSet);
804 } 837 }
805 } 838 }
806 839
807 void LayoutMultiColumnFlowThread::willBeRemovedFromTree() { 840 void LayoutMultiColumnFlowThread::willBeRemovedFromTree() {
808 // Detach all column sets from the flow thread. Cannot destroy them at this po int, since they 841 // Detach all column sets from the flow thread. Cannot destroy them at this
809 // are siblings of this object, and there may be pointers to this object's sib ling somewhere 842 // point, since they are siblings of this object, and there may be pointers to
810 // further up on the call stack. 843 // this object's sibling somewhere further up on the call stack.
811 for (LayoutMultiColumnSet* columnSet = firstMultiColumnSet(); columnSet; 844 for (LayoutMultiColumnSet* columnSet = firstMultiColumnSet(); columnSet;
812 columnSet = columnSet->nextSiblingMultiColumnSet()) 845 columnSet = columnSet->nextSiblingMultiColumnSet())
813 columnSet->detachFromFlowThread(); 846 columnSet->detachFromFlowThread();
814 multiColumnBlockFlow()->resetMultiColumnFlowThread(); 847 multiColumnBlockFlow()->resetMultiColumnFlowThread();
815 LayoutFlowThread::willBeRemovedFromTree(); 848 LayoutFlowThread::willBeRemovedFromTree();
816 } 849 }
817 850
818 void LayoutMultiColumnFlowThread::skipColumnSpanner( 851 void LayoutMultiColumnFlowThread::skipColumnSpanner(
819 LayoutBox* layoutObject, 852 LayoutBox* layoutObject,
820 LayoutUnit logicalTopInFlowThread) { 853 LayoutUnit logicalTopInFlowThread) {
821 ASSERT(layoutObject->isColumnSpanAll()); 854 ASSERT(layoutObject->isColumnSpanAll());
822 LayoutMultiColumnSpannerPlaceholder* placeholder = 855 LayoutMultiColumnSpannerPlaceholder* placeholder =
823 layoutObject->spannerPlaceholder(); 856 layoutObject->spannerPlaceholder();
824 LayoutBox* previousColumnBox = placeholder->previousSiblingMultiColumnBox(); 857 LayoutBox* previousColumnBox = placeholder->previousSiblingMultiColumnBox();
825 if (previousColumnBox && previousColumnBox->isLayoutMultiColumnSet()) { 858 if (previousColumnBox && previousColumnBox->isLayoutMultiColumnSet()) {
826 LayoutMultiColumnSet* columnSet = toLayoutMultiColumnSet(previousColumnBox); 859 LayoutMultiColumnSet* columnSet = toLayoutMultiColumnSet(previousColumnBox);
860 // Negative margins may cause this.
827 if (logicalTopInFlowThread < columnSet->logicalTopInFlowThread()) 861 if (logicalTopInFlowThread < columnSet->logicalTopInFlowThread())
828 logicalTopInFlowThread = 862 logicalTopInFlowThread = columnSet->logicalTopInFlowThread();
829 columnSet
830 ->logicalTopInFlowThread(); // Negative margins may cause this.
831 columnSet->endFlow(logicalTopInFlowThread); 863 columnSet->endFlow(logicalTopInFlowThread);
832 } 864 }
833 LayoutBox* nextColumnBox = placeholder->nextSiblingMultiColumnBox(); 865 LayoutBox* nextColumnBox = placeholder->nextSiblingMultiColumnBox();
834 if (nextColumnBox && nextColumnBox->isLayoutMultiColumnSet()) { 866 if (nextColumnBox && nextColumnBox->isLayoutMultiColumnSet()) {
835 LayoutMultiColumnSet* nextSet = toLayoutMultiColumnSet(nextColumnBox); 867 LayoutMultiColumnSet* nextSet = toLayoutMultiColumnSet(nextColumnBox);
836 m_lastSetWorkedOn = nextSet; 868 m_lastSetWorkedOn = nextSet;
837 nextSet->beginFlow(logicalTopInFlowThread); 869 nextSet->beginFlow(logicalTopInFlowThread);
838 } 870 }
839 871
840 // We'll lay out of spanners after flow thread layout has finished (during lay out of the spanner 872 // We'll lay out of spanners after flow thread layout has finished (during
841 // placeholders). There may be containing blocks for out-of-flow positioned de scendants of the 873 // layout of the spanner placeholders). There may be containing blocks for
842 // spanner in the flow thread, so that out-of-flow objects inside the spanner will be laid out 874 // out-of-flow positioned descendants of the spanner in the flow thread, so
843 // as part of flow thread layout (even if the spanner itself won't). We need t o add such 875 // that out-of-flow objects inside the spanner will be laid out as part of
844 // out-of-flow positioned objects to their containing blocks now, or they'll n ever get laid 876 // flow thread layout (even if the spanner itself won't). We need to add such
845 // out. Since it's non-trivial to determine if we need this, and where such ou t-of-flow objects 877 // out-of-flow positioned objects to their containing blocks now, or they'll
846 // might be, just go through the whole subtree. 878 // never get laid out. Since it's non-trivial to determine if we need this,
879 // and where such out-of-flow objects might be, just go through the whole
880 // subtree.
847 for (LayoutObject* descendant = layoutObject->slowFirstChild(); descendant; 881 for (LayoutObject* descendant = layoutObject->slowFirstChild(); descendant;
848 descendant = descendant->nextInPreOrder()) { 882 descendant = descendant->nextInPreOrder()) {
849 if (descendant->isBox() && descendant->isOutOfFlowPositioned()) 883 if (descendant->isBox() && descendant->isOutOfFlowPositioned())
850 descendant->containingBlock()->insertPositionedObject( 884 descendant->containingBlock()->insertPositionedObject(
851 toLayoutBox(descendant)); 885 toLayoutBox(descendant));
852 } 886 }
853 } 887 }
854 888
855 // When processing layout objects to remove or when processing layout objects th at have just been 889 // When processing layout objects to remove or when processing layout objects
856 // inserted, certain types of objects should be skipped. 890 // that have just been inserted, certain types of objects should be skipped.
857 static bool shouldSkipInsertedOrRemovedChild( 891 static bool shouldSkipInsertedOrRemovedChild(
858 LayoutMultiColumnFlowThread* flowThread, 892 LayoutMultiColumnFlowThread* flowThread,
859 const LayoutObject& child) { 893 const LayoutObject& child) {
860 if (child.isSVG() && !child.isSVGRoot()) { 894 if (child.isSVG() && !child.isSVGRoot()) {
861 // Don't descend into SVG objects. What's in there is of no interest, and th ere might even 895 // Don't descend into SVG objects. What's in there is of no interest, and
862 // be a foreignObject there with column-span:all, which doesn't apply to us. 896 // there might even be a foreignObject there with column-span:all, which
897 // doesn't apply to us.
863 return true; 898 return true;
864 } 899 }
865 if (child.isLayoutFlowThread()) { 900 if (child.isLayoutFlowThread()) {
866 // Found an inner flow thread. We need to skip it and its descendants. 901 // Found an inner flow thread. We need to skip it and its descendants.
867 return true; 902 return true;
868 } 903 }
869 if (child.isLayoutMultiColumnSet() || 904 if (child.isLayoutMultiColumnSet() ||
870 child.isLayoutMultiColumnSpannerPlaceholder()) { 905 child.isLayoutMultiColumnSpannerPlaceholder()) {
871 // Column sets and spanner placeholders in a child multicol context don't af fect the parent 906 // Column sets and spanner placeholders in a child multicol context don't
872 // flow thread. 907 // affect the parent flow thread.
873 return true; 908 return true;
874 } 909 }
875 if (child.isOutOfFlowPositioned() && 910 if (child.isOutOfFlowPositioned() &&
876 child.containingBlock()->flowThreadContainingBlock() != flowThread) { 911 child.containingBlock()->flowThreadContainingBlock() != flowThread) {
877 // Out-of-flow with its containing block on the outside of the multicol cont ainer. 912 // Out-of-flow with its containing block on the outside of the multicol
913 // container.
878 return true; 914 return true;
879 } 915 }
880 return false; 916 return false;
881 } 917 }
882 918
883 void LayoutMultiColumnFlowThread::flowThreadDescendantWasInserted( 919 void LayoutMultiColumnFlowThread::flowThreadDescendantWasInserted(
884 LayoutObject* descendant) { 920 LayoutObject* descendant) {
885 ASSERT(!m_isBeingEvacuated); 921 ASSERT(!m_isBeingEvacuated);
886 // This method ensures that the list of column sets and spanner placeholders r eflects the 922 // This method ensures that the list of column sets and spanner placeholders
887 // multicol content after having inserted a descendant (or descendant subtree) . See the header 923 // reflects the multicol content after having inserted a descendant (or
888 // file for more information. Go through the subtree that was just inserted an d create column 924 // descendant subtree). See the header file for more information. Go through
889 // sets (needed by regular column content) and spanner placeholders (one neede d by each spanner) 925 // the subtree that was just inserted and create column sets (needed by
890 // where needed. 926 // regular column content) and spanner placeholders (one needed by each
927 // spanner) where needed.
891 if (shouldSkipInsertedOrRemovedChild(this, *descendant)) 928 if (shouldSkipInsertedOrRemovedChild(this, *descendant))
892 return; 929 return;
893 LayoutObject* objectAfterSubtree = 930 LayoutObject* objectAfterSubtree =
894 nextInPreOrderAfterChildrenSkippingOutOfFlow(this, descendant); 931 nextInPreOrderAfterChildrenSkippingOutOfFlow(this, descendant);
895 LayoutObject* next; 932 LayoutObject* next;
896 for (LayoutObject* layoutObject = descendant; layoutObject; 933 for (LayoutObject* layoutObject = descendant; layoutObject;
897 layoutObject = next) { 934 layoutObject = next) {
898 if (layoutObject != descendant && 935 if (layoutObject != descendant &&
899 shouldSkipInsertedOrRemovedChild(this, *layoutObject)) { 936 shouldSkipInsertedOrRemovedChild(this, *layoutObject)) {
900 next = layoutObject->nextInPreOrderAfterChildren(descendant); 937 next = layoutObject->nextInPreOrderAfterChildren(descendant);
901 continue; 938 continue;
902 } 939 }
903 next = layoutObject->nextInPreOrder(descendant); 940 next = layoutObject->nextInPreOrder(descendant);
904 if (containingColumnSpannerPlaceholder(layoutObject)) 941 if (containingColumnSpannerPlaceholder(layoutObject))
905 continue; // Inside a column spanner. Nothing to do, then. 942 continue; // Inside a column spanner. Nothing to do, then.
906 if (descendantIsValidColumnSpanner(layoutObject)) { 943 if (descendantIsValidColumnSpanner(layoutObject)) {
907 // This layoutObject is a spanner, so it needs to establish a spanner plac eholder. 944 // This layoutObject is a spanner, so it needs to establish a spanner
945 // placeholder.
908 createAndInsertSpannerPlaceholder(toLayoutBox(layoutObject), 946 createAndInsertSpannerPlaceholder(toLayoutBox(layoutObject),
909 objectAfterSubtree); 947 objectAfterSubtree);
910 continue; 948 continue;
911 } 949 }
912 // This layoutObject is regular column content (i.e. not a spanner). Create a set if necessary. 950 // This layoutObject is regular column content (i.e. not a spanner). Create
951 // a set if necessary.
913 if (objectAfterSubtree) { 952 if (objectAfterSubtree) {
914 if (LayoutMultiColumnSpannerPlaceholder* placeholder = 953 if (LayoutMultiColumnSpannerPlaceholder* placeholder =
915 objectAfterSubtree->spannerPlaceholder()) { 954 objectAfterSubtree->spannerPlaceholder()) {
916 // If inserted right before a spanner, we need to make sure that there's a set for us there. 955 // If inserted right before a spanner, we need to make sure that there's
956 // a set for us there.
917 LayoutBox* previous = placeholder->previousSiblingMultiColumnBox(); 957 LayoutBox* previous = placeholder->previousSiblingMultiColumnBox();
918 if (!previous || !previous->isLayoutMultiColumnSet()) 958 if (!previous || !previous->isLayoutMultiColumnSet())
919 createAndInsertMultiColumnSet(placeholder); 959 createAndInsertMultiColumnSet(placeholder);
920 } else { 960 } else {
921 // Otherwise, since |objectAfterSubtree| isn't a spanner, it has to mean that there's 961 // Otherwise, since |objectAfterSubtree| isn't a spanner, it has to mean
922 // already a set for that content. We can use it for this layoutObject t oo. 962 // that there's already a set for that content. We can use it for this
963 // layoutObject too.
923 ASSERT(mapDescendantToColumnSet(objectAfterSubtree)); 964 ASSERT(mapDescendantToColumnSet(objectAfterSubtree));
924 ASSERT(mapDescendantToColumnSet(layoutObject) == 965 ASSERT(mapDescendantToColumnSet(layoutObject) ==
925 mapDescendantToColumnSet(objectAfterSubtree)); 966 mapDescendantToColumnSet(objectAfterSubtree));
926 } 967 }
927 } else { 968 } else {
928 // Inserting at the end. Then we just need to make sure that there's a col umn set at the end. 969 // Inserting at the end. Then we just need to make sure that there's a
970 // column set at the end.
929 LayoutBox* lastColumnBox = lastMultiColumnBox(); 971 LayoutBox* lastColumnBox = lastMultiColumnBox();
930 if (!lastColumnBox || !lastColumnBox->isLayoutMultiColumnSet()) 972 if (!lastColumnBox || !lastColumnBox->isLayoutMultiColumnSet())
931 createAndInsertMultiColumnSet(); 973 createAndInsertMultiColumnSet();
932 } 974 }
933 } 975 }
934 } 976 }
935 977
936 void LayoutMultiColumnFlowThread::flowThreadDescendantWillBeRemoved( 978 void LayoutMultiColumnFlowThread::flowThreadDescendantWillBeRemoved(
937 LayoutObject* descendant) { 979 LayoutObject* descendant) {
938 // This method ensures that the list of column sets and spanner placeholders r eflects the 980 // This method ensures that the list of column sets and spanner placeholders
939 // multicol content that we'll be left with after removal of a descendant (or descendant 981 // reflects the multicol content that we'll be left with after removal of a
940 // subtree). See the header file for more information. Removing content may me an that we need to 982 // descendant (or descendant subtree). See the header file for more
941 // remove column sets and/or spanner placeholders. 983 // information. Removing content may mean that we need to remove column sets
984 // and/or spanner placeholders.
942 if (m_isBeingEvacuated) 985 if (m_isBeingEvacuated)
943 return; 986 return;
944 if (shouldSkipInsertedOrRemovedChild(this, *descendant)) 987 if (shouldSkipInsertedOrRemovedChild(this, *descendant))
945 return; 988 return;
946 bool hadContainingPlaceholder = 989 bool hadContainingPlaceholder =
947 containingColumnSpannerPlaceholder(descendant); 990 containingColumnSpannerPlaceholder(descendant);
948 bool processedSomething = false; 991 bool processedSomething = false;
949 LayoutObject* next; 992 LayoutObject* next;
950 // Remove spanner placeholders that are no longer needed, and merge column set s around them. 993 // Remove spanner placeholders that are no longer needed, and merge column
994 // sets around them.
951 for (LayoutObject* layoutObject = descendant; layoutObject; 995 for (LayoutObject* layoutObject = descendant; layoutObject;
952 layoutObject = next) { 996 layoutObject = next) {
953 if (layoutObject != descendant && 997 if (layoutObject != descendant &&
954 shouldSkipInsertedOrRemovedChild(this, *layoutObject)) { 998 shouldSkipInsertedOrRemovedChild(this, *layoutObject)) {
955 next = layoutObject->nextInPreOrderAfterChildren(descendant); 999 next = layoutObject->nextInPreOrderAfterChildren(descendant);
956 continue; 1000 continue;
957 } 1001 }
958 processedSomething = true; 1002 processedSomething = true;
959 LayoutMultiColumnSpannerPlaceholder* placeholder = 1003 LayoutMultiColumnSpannerPlaceholder* placeholder =
960 layoutObject->spannerPlaceholder(); 1004 layoutObject->spannerPlaceholder();
961 if (!placeholder) { 1005 if (!placeholder) {
962 next = layoutObject->nextInPreOrder(descendant); 1006 next = layoutObject->nextInPreOrder(descendant);
963 continue; 1007 continue;
964 } 1008 }
965 next = layoutObject->nextInPreOrderAfterChildren( 1009 next = layoutObject->nextInPreOrderAfterChildren(
966 descendant); // It's a spanner. Its children are of no interest to us. 1010 descendant); // It's a spanner. Its children are of no interest to us.
967 destroySpannerPlaceholder(placeholder); 1011 destroySpannerPlaceholder(placeholder);
968 } 1012 }
969 if (hadContainingPlaceholder || !processedSomething) 1013 if (hadContainingPlaceholder || !processedSomething)
970 return; // No column content will be removed, so we can stop here. 1014 return; // No column content will be removed, so we can stop here.
971 1015
972 // Column content will be removed. Does this mean that we should destroy a col umn set? 1016 // Column content will be removed. Does this mean that we should destroy a
1017 // column set?
973 LayoutMultiColumnSpannerPlaceholder* adjacentPreviousSpannerPlaceholder = 1018 LayoutMultiColumnSpannerPlaceholder* adjacentPreviousSpannerPlaceholder =
974 nullptr; 1019 nullptr;
975 LayoutObject* previousLayoutObject = 1020 LayoutObject* previousLayoutObject =
976 previousInPreOrderSkippingOutOfFlow(this, descendant); 1021 previousInPreOrderSkippingOutOfFlow(this, descendant);
977 if (previousLayoutObject && previousLayoutObject != this) { 1022 if (previousLayoutObject && previousLayoutObject != this) {
978 adjacentPreviousSpannerPlaceholder = 1023 adjacentPreviousSpannerPlaceholder =
979 containingColumnSpannerPlaceholder(previousLayoutObject); 1024 containingColumnSpannerPlaceholder(previousLayoutObject);
980 if (!adjacentPreviousSpannerPlaceholder) 1025 if (!adjacentPreviousSpannerPlaceholder)
981 return; // Preceded by column content. Set still needed. 1026 return; // Preceded by column content. Set still needed.
982 } 1027 }
983 LayoutMultiColumnSpannerPlaceholder* adjacentNextSpannerPlaceholder = nullptr; 1028 LayoutMultiColumnSpannerPlaceholder* adjacentNextSpannerPlaceholder = nullptr;
984 LayoutObject* nextLayoutObject = 1029 LayoutObject* nextLayoutObject =
985 nextInPreOrderAfterChildrenSkippingOutOfFlow(this, descendant); 1030 nextInPreOrderAfterChildrenSkippingOutOfFlow(this, descendant);
986 if (nextLayoutObject) { 1031 if (nextLayoutObject) {
987 adjacentNextSpannerPlaceholder = 1032 adjacentNextSpannerPlaceholder =
988 containingColumnSpannerPlaceholder(nextLayoutObject); 1033 containingColumnSpannerPlaceholder(nextLayoutObject);
989 if (!adjacentNextSpannerPlaceholder) 1034 if (!adjacentNextSpannerPlaceholder)
990 return; // Followed by column content. Set still needed. 1035 return; // Followed by column content. Set still needed.
991 } 1036 }
992 // We have now determined that, with the removal of |descendant|, we should re move a column 1037 // We have now determined that, with the removal of |descendant|, we should
993 // set. Locate it and remove it. Do it without involving mapDescendantToColumn Set(), as that 1038 // remove a column set. Locate it and remove it. Do it without involving
994 // might be very slow. Deduce the right set from the spanner placeholders that we've already 1039 // mapDescendantToColumnSet(), as that might be very slow. Deduce the right
995 // found. 1040 // set from the spanner placeholders that we've already found.
996 LayoutMultiColumnSet* columnSetToRemove; 1041 LayoutMultiColumnSet* columnSetToRemove;
997 if (adjacentNextSpannerPlaceholder) { 1042 if (adjacentNextSpannerPlaceholder) {
998 columnSetToRemove = toLayoutMultiColumnSet( 1043 columnSetToRemove = toLayoutMultiColumnSet(
999 adjacentNextSpannerPlaceholder->previousSiblingMultiColumnBox()); 1044 adjacentNextSpannerPlaceholder->previousSiblingMultiColumnBox());
1000 ASSERT(!adjacentPreviousSpannerPlaceholder || 1045 ASSERT(!adjacentPreviousSpannerPlaceholder ||
1001 columnSetToRemove == 1046 columnSetToRemove ==
1002 adjacentPreviousSpannerPlaceholder->nextSiblingMultiColumnBox()); 1047 adjacentPreviousSpannerPlaceholder->nextSiblingMultiColumnBox());
1003 } else if (adjacentPreviousSpannerPlaceholder) { 1048 } else if (adjacentPreviousSpannerPlaceholder) {
1004 columnSetToRemove = toLayoutMultiColumnSet( 1049 columnSetToRemove = toLayoutMultiColumnSet(
1005 adjacentPreviousSpannerPlaceholder->nextSiblingMultiColumnBox()); 1050 adjacentPreviousSpannerPlaceholder->nextSiblingMultiColumnBox());
1006 } else { 1051 } else {
1007 // If there were no adjacent spanners, it has to mean that there's only one column set, 1052 // If there were no adjacent spanners, it has to mean that there's only one
1008 // since it's only spanners that may cause creation of multiple sets. 1053 // column set, since it's only spanners that may cause creation of
1054 // multiple sets.
1009 columnSetToRemove = firstMultiColumnSet(); 1055 columnSetToRemove = firstMultiColumnSet();
1010 ASSERT(columnSetToRemove); 1056 ASSERT(columnSetToRemove);
1011 ASSERT(!columnSetToRemove->nextSiblingMultiColumnSet()); 1057 ASSERT(!columnSetToRemove->nextSiblingMultiColumnSet());
1012 } 1058 }
1013 ASSERT(columnSetToRemove); 1059 ASSERT(columnSetToRemove);
1014 columnSetToRemove->destroy(); 1060 columnSetToRemove->destroy();
1015 } 1061 }
1016 1062
1017 static inline bool needsToReinsertIntoFlowThread( 1063 static inline bool needsToReinsertIntoFlowThread(
1018 const ComputedStyle& oldStyle, 1064 const ComputedStyle& oldStyle,
1019 const ComputedStyle& newStyle) { 1065 const ComputedStyle& newStyle) {
1020 // If we've become (or are about to become) a container for absolutely positio ned descendants, 1066 // If we've become (or are about to become) a container for absolutely
1021 // or if we're no longer going to be one, we need to re-evaluate the need for column 1067 // positioned descendants, or if we're no longer going to be one, we need to
1022 // sets. There may be out-of-flow descendants further down that become part of the flow thread, 1068 // re-evaluate the need for column sets. There may be out-of-flow descendants
1023 // or cease to be part of the flow thread, because of this change. 1069 // further down that become part of the flow thread, or cease to be part of
1070 // the flow thread, because of this change.
1024 if (oldStyle.hasTransformRelatedProperty() != 1071 if (oldStyle.hasTransformRelatedProperty() !=
1025 newStyle.hasTransformRelatedProperty()) 1072 newStyle.hasTransformRelatedProperty())
1026 return true; 1073 return true;
1027 return (oldStyle.hasInFlowPosition() && 1074 return (oldStyle.hasInFlowPosition() &&
1028 newStyle.position() == StaticPosition) || 1075 newStyle.position() == StaticPosition) ||
1029 (newStyle.hasInFlowPosition() && 1076 (newStyle.hasInFlowPosition() &&
1030 oldStyle.position() == StaticPosition); 1077 oldStyle.position() == StaticPosition);
1031 } 1078 }
1032 1079
1033 static inline bool needsToRemoveFromFlowThread(const ComputedStyle& oldStyle, 1080 static inline bool needsToRemoveFromFlowThread(const ComputedStyle& oldStyle,
1034 const ComputedStyle& newStyle) { 1081 const ComputedStyle& newStyle) {
1035 // If an in-flow descendant goes out-of-flow, we may have to remove column set s and spanner placeholders. 1082 // If an in-flow descendant goes out-of-flow, we may have to remove column
1083 // sets and spanner placeholders.
1036 return (newStyle.hasOutOfFlowPosition() && 1084 return (newStyle.hasOutOfFlowPosition() &&
1037 !oldStyle.hasOutOfFlowPosition()) || 1085 !oldStyle.hasOutOfFlowPosition()) ||
1038 needsToReinsertIntoFlowThread(oldStyle, newStyle); 1086 needsToReinsertIntoFlowThread(oldStyle, newStyle);
1039 } 1087 }
1040 1088
1041 static inline bool needsToInsertIntoFlowThread(const ComputedStyle& oldStyle, 1089 static inline bool needsToInsertIntoFlowThread(const ComputedStyle& oldStyle,
1042 const ComputedStyle& newStyle) { 1090 const ComputedStyle& newStyle) {
1043 // If an out-of-flow descendant goes in-flow, we may have to insert column set s and spanner placeholders. 1091 // If an out-of-flow descendant goes in-flow, we may have to insert column
1092 // sets and spanner placeholders.
1044 return (!newStyle.hasOutOfFlowPosition() && 1093 return (!newStyle.hasOutOfFlowPosition() &&
1045 oldStyle.hasOutOfFlowPosition()) || 1094 oldStyle.hasOutOfFlowPosition()) ||
1046 needsToReinsertIntoFlowThread(oldStyle, newStyle); 1095 needsToReinsertIntoFlowThread(oldStyle, newStyle);
1047 } 1096 }
1048 1097
1049 void LayoutMultiColumnFlowThread::flowThreadDescendantStyleWillChange( 1098 void LayoutMultiColumnFlowThread::flowThreadDescendantStyleWillChange(
1050 LayoutBox* descendant, 1099 LayoutBox* descendant,
1051 StyleDifference diff, 1100 StyleDifference diff,
1052 const ComputedStyle& newStyle) { 1101 const ComputedStyle& newStyle) {
1053 if (needsToRemoveFromFlowThread(descendant->styleRef(), newStyle)) 1102 if (needsToRemoveFromFlowThread(descendant->styleRef(), newStyle))
1054 flowThreadDescendantWillBeRemoved(descendant); 1103 flowThreadDescendantWillBeRemoved(descendant);
1055 } 1104 }
1056 1105
1057 void LayoutMultiColumnFlowThread::flowThreadDescendantStyleDidChange( 1106 void LayoutMultiColumnFlowThread::flowThreadDescendantStyleDidChange(
1058 LayoutBox* descendant, 1107 LayoutBox* descendant,
1059 StyleDifference diff, 1108 StyleDifference diff,
1060 const ComputedStyle& oldStyle) { 1109 const ComputedStyle& oldStyle) {
1061 if (needsToInsertIntoFlowThread(oldStyle, descendant->styleRef())) { 1110 if (needsToInsertIntoFlowThread(oldStyle, descendant->styleRef())) {
1062 flowThreadDescendantWasInserted(descendant); 1111 flowThreadDescendantWasInserted(descendant);
1063 return; 1112 return;
1064 } 1113 }
1065 if (descendantIsValidColumnSpanner(descendant)) { 1114 if (descendantIsValidColumnSpanner(descendant)) {
1066 // We went from being regular column content to becoming a spanner. 1115 // We went from being regular column content to becoming a spanner.
1067 ASSERT(!descendant->spannerPlaceholder()); 1116 ASSERT(!descendant->spannerPlaceholder());
1068 1117
1069 // First remove this as regular column content. Note that this will walk the entire subtree 1118 // First remove this as regular column content. Note that this will walk the
1070 // of |descendant|. There might be spanners there (which won't be spanners a nymore, since 1119 // entire subtree of |descendant|. There might be spanners there (which
1071 // we're not allowed to nest spanners), whose placeholders must die. 1120 // won't be spanners anymore, since we're not allowed to nest spanners),
1121 // whose placeholders must die.
1072 flowThreadDescendantWillBeRemoved(descendant); 1122 flowThreadDescendantWillBeRemoved(descendant);
1073 1123
1074 createAndInsertSpannerPlaceholder( 1124 createAndInsertSpannerPlaceholder(
1075 descendant, 1125 descendant,
1076 nextInPreOrderAfterChildrenSkippingOutOfFlow(this, descendant)); 1126 nextInPreOrderAfterChildrenSkippingOutOfFlow(this, descendant));
1077 } 1127 }
1078 } 1128 }
1079 1129
1080 void LayoutMultiColumnFlowThread::computePreferredLogicalWidths() { 1130 void LayoutMultiColumnFlowThread::computePreferredLogicalWidths() {
1081 LayoutFlowThread::computePreferredLogicalWidths(); 1131 LayoutFlowThread::computePreferredLogicalWidths();
1082 1132
1083 // The min/max intrinsic widths calculated really tell how much space elements need when 1133 // The min/max intrinsic widths calculated really tell how much space elements
1084 // laid out inside the columns. In order to eventually end up with the desired column width, 1134 // need when laid out inside the columns. In order to eventually end up with
1085 // we need to convert them to values pertaining to the multicol container. 1135 // the desired column width, we need to convert them to values pertaining to
1136 // the multicol container.
1086 const LayoutBlockFlow* multicolContainer = multiColumnBlockFlow(); 1137 const LayoutBlockFlow* multicolContainer = multiColumnBlockFlow();
1087 const ComputedStyle* multicolStyle = multicolContainer->style(); 1138 const ComputedStyle* multicolStyle = multicolContainer->style();
1088 int columnCount = 1139 int columnCount =
1089 multicolStyle->hasAutoColumnCount() ? 1 : multicolStyle->columnCount(); 1140 multicolStyle->hasAutoColumnCount() ? 1 : multicolStyle->columnCount();
1090 LayoutUnit columnWidth; 1141 LayoutUnit columnWidth;
1091 LayoutUnit gapExtra = 1142 LayoutUnit gapExtra =
1092 LayoutUnit((columnCount - 1) * multicolContainer->columnGap()); 1143 LayoutUnit((columnCount - 1) * multicolContainer->columnGap());
1093 if (multicolStyle->hasAutoColumnWidth()) { 1144 if (multicolStyle->hasAutoColumnWidth()) {
1094 m_minPreferredLogicalWidth = 1145 m_minPreferredLogicalWidth =
1095 m_minPreferredLogicalWidth * columnCount + gapExtra; 1146 m_minPreferredLogicalWidth * columnCount + gapExtra;
1096 } else { 1147 } else {
1097 columnWidth = LayoutUnit(multicolStyle->columnWidth()); 1148 columnWidth = LayoutUnit(multicolStyle->columnWidth());
1098 m_minPreferredLogicalWidth = 1149 m_minPreferredLogicalWidth =
1099 std::min(m_minPreferredLogicalWidth, columnWidth); 1150 std::min(m_minPreferredLogicalWidth, columnWidth);
1100 } 1151 }
1101 // Note that if column-count is auto here, we should resolve it to calculate t he maximum 1152 // Note that if column-count is auto here, we should resolve it to calculate
1102 // intrinsic width, instead of pretending that it's 1. The only way to do that is by performing 1153 // the maximum intrinsic width, instead of pretending that it's 1. The only
1103 // a layout pass, but this is not an appropriate time or place for layout. The good news is that 1154 // way to do that is by performing a layout pass, but this is not an
1104 // if height is unconstrained and there are no explicit breaks, the resolved c olumn-count really 1155 // appropriate time or place for layout. The good news is that if height is
1105 // should be 1. 1156 // unconstrained and there are no explicit breaks, the resolved column-count
1157 // really should be 1.
1106 m_maxPreferredLogicalWidth = 1158 m_maxPreferredLogicalWidth =
1107 std::max(m_maxPreferredLogicalWidth, columnWidth) * columnCount + 1159 std::max(m_maxPreferredLogicalWidth, columnWidth) * columnCount +
1108 gapExtra; 1160 gapExtra;
1109 } 1161 }
1110 1162
1111 void LayoutMultiColumnFlowThread::computeLogicalHeight( 1163 void LayoutMultiColumnFlowThread::computeLogicalHeight(
1112 LayoutUnit logicalHeight, 1164 LayoutUnit logicalHeight,
1113 LayoutUnit logicalTop, 1165 LayoutUnit logicalTop,
1114 LogicalExtentComputedValues& computedValues) const { 1166 LogicalExtentComputedValues& computedValues) const {
1115 // We simply remain at our intrinsic height. 1167 // We simply remain at our intrinsic height.
1116 computedValues.m_extent = logicalHeight; 1168 computedValues.m_extent = logicalHeight;
1117 computedValues.m_position = logicalTop; 1169 computedValues.m_position = logicalTop;
1118 } 1170 }
1119 1171
1120 void LayoutMultiColumnFlowThread::updateLogicalWidth() { 1172 void LayoutMultiColumnFlowThread::updateLogicalWidth() {
1121 LayoutUnit columnWidth; 1173 LayoutUnit columnWidth;
1122 calculateColumnCountAndWidth(columnWidth, m_columnCount); 1174 calculateColumnCountAndWidth(columnWidth, m_columnCount);
1123 setLogicalWidth(columnWidth); 1175 setLogicalWidth(columnWidth);
1124 } 1176 }
1125 1177
1126 void LayoutMultiColumnFlowThread::layout() { 1178 void LayoutMultiColumnFlowThread::layout() {
1127 ASSERT(!m_lastSetWorkedOn); 1179 ASSERT(!m_lastSetWorkedOn);
1128 m_lastSetWorkedOn = firstMultiColumnSet(); 1180 m_lastSetWorkedOn = firstMultiColumnSet();
1129 if (m_lastSetWorkedOn) 1181 if (m_lastSetWorkedOn)
1130 m_lastSetWorkedOn->beginFlow(LayoutUnit()); 1182 m_lastSetWorkedOn->beginFlow(LayoutUnit());
1131 LayoutFlowThread::layout(); 1183 LayoutFlowThread::layout();
1132 if (LayoutMultiColumnSet* lastSet = lastMultiColumnSet()) { 1184 if (LayoutMultiColumnSet* lastSet = lastMultiColumnSet()) {
1133 ASSERT(lastSet == m_lastSetWorkedOn); 1185 ASSERT(lastSet == m_lastSetWorkedOn);
1134 if (!lastSet->nextSiblingMultiColumnBox()) { 1186 if (!lastSet->nextSiblingMultiColumnBox()) {
1135 // Include trailing overflow in the last column set. The idea is that we w ill generate 1187 // Include trailing overflow in the last column set. The idea is that we
1136 // additional columns and pages to hold that overflow, since people do wri te bad content 1188 // will generate additional columns and pages to hold that overflow, since
1137 // like <body style="height:0px"> in multi-column layouts. 1189 // people do write bad content like <body style="height:0px"> in
1138 // TODO(mstensho): Once we support nested multicol, adding in overflow her e may result 1190 // multi-column layouts.
1139 // in the need for creating additional rows, since there may not be enough space 1191 // TODO(mstensho): Once we support nested multicol, adding in overflow
1140 // remaining in the currently last row. 1192 // here may result in the need for creating additional rows, since there
1193 // may not be enough space remaining in the currently last row.
1141 LayoutRect layoutRect = layoutOverflowRect(); 1194 LayoutRect layoutRect = layoutOverflowRect();
1142 LayoutUnit logicalBottomInFlowThread = 1195 LayoutUnit logicalBottomInFlowThread =
1143 isHorizontalWritingMode() ? layoutRect.maxY() : layoutRect.maxX(); 1196 isHorizontalWritingMode() ? layoutRect.maxY() : layoutRect.maxX();
1144 ASSERT(logicalBottomInFlowThread >= logicalHeight()); 1197 ASSERT(logicalBottomInFlowThread >= logicalHeight());
1145 lastSet->endFlow(logicalBottomInFlowThread); 1198 lastSet->endFlow(logicalBottomInFlowThread);
1146 } 1199 }
1147 } 1200 }
1148 m_lastSetWorkedOn = nullptr; 1201 m_lastSetWorkedOn = nullptr;
1149 } 1202 }
1150 1203
1151 void LayoutMultiColumnFlowThread::contentWasLaidOut( 1204 void LayoutMultiColumnFlowThread::contentWasLaidOut(
1152 LayoutUnit logicalBottomInFlowThreadAfterPagination) { 1205 LayoutUnit logicalBottomInFlowThreadAfterPagination) {
1153 // Check if we need another fragmentainer group. If we've run out of columns i n the last 1206 // Check if we need another fragmentainer group. If we've run out of columns
1154 // fragmentainer group (column row), we need to insert another fragmentainer g roup to hold more 1207 // in the last fragmentainer group (column row), we need to insert another
1155 // columns. 1208 // fragmentainer group to hold more columns.
1156 1209
1157 // First figure out if there's any chance that we're nested at all. If we can be sure that 1210 // First figure out if there's any chance that we're nested at all. If we can
1158 // we're not, bail early. This code is run very often, and since locating a co ntaining flow 1211 // be sure that we're not, bail early. This code is run very often, and since
1159 // thread has some cost (depending on tree depth), avoid calling 1212 // locating a containing flow thread has some cost (depending on tree depth),
1160 // enclosingFragmentationContext() right away. This test may give some false p ositives (hence 1213 // avoid calling enclosingFragmentationContext() right away. This test may
1161 // the "mayBe"), if we're in an out-of-flow subtree and have an outer multicol container that 1214 // give some false positives (hence the "mayBe"), if we're in an out-of-flow
1162 // doesn't affect us, but that's okay. We'll discover that further down the ro ad when trying to 1215 // subtree and have an outer multicol container that doesn't affect us, but
1216 // that's okay. We'll discover that further down the road when trying to
1163 // locate our enclosing flow thread for real. 1217 // locate our enclosing flow thread for real.
1164 bool mayBeNested = multiColumnBlockFlow()->isInsideFlowThread() || 1218 bool mayBeNested = multiColumnBlockFlow()->isInsideFlowThread() ||
1165 view()->fragmentationContext(); 1219 view()->fragmentationContext();
1166 if (!mayBeNested) 1220 if (!mayBeNested)
1167 return; 1221 return;
1168 appendNewFragmentainerGroupIfNeeded(logicalBottomInFlowThreadAfterPagination, 1222 appendNewFragmentainerGroupIfNeeded(logicalBottomInFlowThreadAfterPagination,
1169 AssociateWithFormerPage); 1223 AssociateWithFormerPage);
1170 } 1224 }
1171 1225
1172 bool LayoutMultiColumnFlowThread::canSkipLayout(const LayoutBox& root) const { 1226 bool LayoutMultiColumnFlowThread::canSkipLayout(const LayoutBox& root) const {
1173 // Objects containing spanners is all we need to worry about, so if there are no spanners at all 1227 // Objects containing spanners is all we need to worry about, so if there are
1174 // in this multicol container, we can just return the good news right away. 1228 // no spanners at all in this multicol container, we can just return the good
1229 // news right away.
1175 if (!hasAnyColumnSpanners(*this)) 1230 if (!hasAnyColumnSpanners(*this))
1176 return true; 1231 return true;
1177 1232
1178 LayoutObject* next; 1233 LayoutObject* next;
1179 for (const LayoutObject* object = &root; object; object = next) { 1234 for (const LayoutObject* object = &root; object; object = next) {
1180 if (object->isColumnSpanAll()) { 1235 if (object->isColumnSpanAll()) {
1181 // A spanner potentially ends one fragmentainer group and begins a new one , and thus 1236 // A spanner potentially ends one fragmentainer group and begins a new
1182 // determines the flow thread portion bottom and top of adjacent fragmenta iner 1237 // one, and thus determines the flow thread portion bottom and top of
1183 // groups. It's just too hard to guess these values without laying out. 1238 // adjacent fragmentainer groups. It's just too hard to guess these values
1239 // without laying out.
1184 return false; 1240 return false;
1185 } 1241 }
1186 if (canContainSpannerInParentFragmentationContext(*object)) 1242 if (canContainSpannerInParentFragmentationContext(*object))
1187 next = object->nextInPreOrder(&root); 1243 next = object->nextInPreOrder(&root);
1188 else 1244 else
1189 next = object->nextInPreOrderAfterChildren(&root); 1245 next = object->nextInPreOrderAfterChildren(&root);
1190 } 1246 }
1191 return true; 1247 return true;
1192 } 1248 }
1193 1249
1194 MultiColumnLayoutState LayoutMultiColumnFlowThread::multiColumnLayoutState() 1250 MultiColumnLayoutState LayoutMultiColumnFlowThread::multiColumnLayoutState()
1195 const { 1251 const {
1196 return MultiColumnLayoutState(m_lastSetWorkedOn); 1252 return MultiColumnLayoutState(m_lastSetWorkedOn);
1197 } 1253 }
1198 1254
1199 void LayoutMultiColumnFlowThread::restoreMultiColumnLayoutState( 1255 void LayoutMultiColumnFlowThread::restoreMultiColumnLayoutState(
1200 const MultiColumnLayoutState& state) { 1256 const MultiColumnLayoutState& state) {
1201 m_lastSetWorkedOn = state.columnSet(); 1257 m_lastSetWorkedOn = state.columnSet();
1202 } 1258 }
1203 1259
1204 } // namespace blink 1260 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698