OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google 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 are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
68 struct SameSizeAsMarginInfo { | 68 struct SameSizeAsMarginInfo { |
69 uint16_t bitfields; | 69 uint16_t bitfields; |
70 LayoutUnit margins[2]; | 70 LayoutUnit margins[2]; |
71 }; | 71 }; |
72 | 72 |
73 static_assert(sizeof(LayoutBlockFlow::MarginValues) == sizeof(LayoutUnit[4]), | 73 static_assert(sizeof(LayoutBlockFlow::MarginValues) == sizeof(LayoutUnit[4]), |
74 "MarginValues should stay small"); | 74 "MarginValues should stay small"); |
75 | 75 |
76 // Caches all our current margin collapsing state. | 76 // Caches all our current margin collapsing state. |
77 class MarginInfo { | 77 class MarginInfo { |
78 // Collapsing flags for whether we can collapse our margins with our children'
s margins. | 78 // Collapsing flags for whether we can collapse our margins with our |
| 79 // children's margins. |
79 bool m_canCollapseWithChildren : 1; | 80 bool m_canCollapseWithChildren : 1; |
80 bool m_canCollapseMarginBeforeWithChildren : 1; | 81 bool m_canCollapseMarginBeforeWithChildren : 1; |
81 bool m_canCollapseMarginAfterWithChildren : 1; | 82 bool m_canCollapseMarginAfterWithChildren : 1; |
82 bool m_canCollapseMarginAfterWithLastChild : 1; | 83 bool m_canCollapseMarginAfterWithLastChild : 1; |
83 | 84 |
84 // Whether or not we are a quirky container, i.e., do we collapse away top and
bottom | 85 // Whether or not we are a quirky container, i.e., do we collapse away top and |
85 // margins in our container. Table cells and the body are the common examples.
We | 86 // bottom margins in our container. Table cells and the body are the common |
86 // also have a custom style property for Safari RSS to deal with TypePad blog
articles. | 87 // examples. We also have a custom style property for Safari RSS to deal with |
| 88 // TypePad blog articles. |
87 bool m_quirkContainer : 1; | 89 bool m_quirkContainer : 1; |
88 | 90 |
89 // This flag tracks whether we are still looking at child margins that can all
collapse together at the beginning of a block. | 91 // This flag tracks whether we are still looking at child margins that can all |
90 // They may or may not collapse with the top margin of the block (|m_canCollap
seTopWithChildren| tells us that), but they will | 92 // collapse together at the beginning of a block. They may or may not collapse |
91 // always be collapsing with one another. This variable can remain set to true
through multiple iterations | 93 // with the top margin of the block (|m_canCollapseTopWithChildren| tells us |
92 // as long as we keep encountering self-collapsing blocks. | 94 // that), but they will always be collapsing with one another. This variable |
| 95 // can remain set to true through multiple iterations as long as we keep |
| 96 // encountering self-collapsing blocks. |
93 bool m_atBeforeSideOfBlock : 1; | 97 bool m_atBeforeSideOfBlock : 1; |
94 | 98 |
95 // This flag is set when we know we're examining bottom margins and we know we
're at the bottom of the block. | 99 // This flag is set when we know we're examining bottom margins and we know |
| 100 // we're at the bottom of the block. |
96 bool m_atAfterSideOfBlock : 1; | 101 bool m_atAfterSideOfBlock : 1; |
97 | 102 |
98 // These variables are used to detect quirky margins that we need to collapse
away (in table cells | 103 // These variables are used to detect quirky margins that we need to collapse |
| 104 // away (in table cells |
99 // and in the body element). | 105 // and in the body element). |
100 bool m_hasMarginBeforeQuirk : 1; | 106 bool m_hasMarginBeforeQuirk : 1; |
101 bool m_hasMarginAfterQuirk : 1; | 107 bool m_hasMarginAfterQuirk : 1; |
102 bool m_determinedMarginBeforeQuirk : 1; | 108 bool m_determinedMarginBeforeQuirk : 1; |
103 | 109 |
104 bool m_discardMargin : 1; | 110 bool m_discardMargin : 1; |
105 bool m_lastChildIsSelfCollapsingBlockWithClearance : 1; | 111 bool m_lastChildIsSelfCollapsingBlockWithClearance : 1; |
106 | 112 |
107 // These flags track the previous maximal positive and negative margins. | 113 // These flags track the previous maximal positive and negative margins. |
108 LayoutUnit m_positiveMargin; | 114 LayoutUnit m_positiveMargin; |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
183 bool discardMargin() const { return m_discardMargin; } | 189 bool discardMargin() const { return m_discardMargin; } |
184 LayoutUnit margin() const { return m_positiveMargin - m_negativeMargin; } | 190 LayoutUnit margin() const { return m_positiveMargin - m_negativeMargin; } |
185 void setLastChildIsSelfCollapsingBlockWithClearance(bool value) { | 191 void setLastChildIsSelfCollapsingBlockWithClearance(bool value) { |
186 m_lastChildIsSelfCollapsingBlockWithClearance = value; | 192 m_lastChildIsSelfCollapsingBlockWithClearance = value; |
187 } | 193 } |
188 bool lastChildIsSelfCollapsingBlockWithClearance() const { | 194 bool lastChildIsSelfCollapsingBlockWithClearance() const { |
189 return m_lastChildIsSelfCollapsingBlockWithClearance; | 195 return m_lastChildIsSelfCollapsingBlockWithClearance; |
190 } | 196 } |
191 }; | 197 }; |
192 | 198 |
193 // Some features, such as floats, margin collapsing and fragmentation, require s
ome knowledge about | 199 // Some features, such as floats, margin collapsing and fragmentation, require |
194 // things that happened when laying out previous block child siblings. Only look
ing at the object | 200 // some knowledge about things that happened when laying out previous block |
195 // currently being laid out isn't always enough. | 201 // child siblings. Only looking at the object currently being laid out isn't |
| 202 // always enough. |
196 class BlockChildrenLayoutInfo { | 203 class BlockChildrenLayoutInfo { |
197 public: | 204 public: |
198 BlockChildrenLayoutInfo(LayoutBlockFlow* blockFlow, | 205 BlockChildrenLayoutInfo(LayoutBlockFlow* blockFlow, |
199 LayoutUnit beforeEdge, | 206 LayoutUnit beforeEdge, |
200 LayoutUnit afterEdge) | 207 LayoutUnit afterEdge) |
201 : m_marginInfo(blockFlow, beforeEdge, afterEdge), | 208 : m_marginInfo(blockFlow, beforeEdge, afterEdge), |
202 m_previousBreakAfterValue(BreakAuto), | 209 m_previousBreakAfterValue(BreakAuto), |
203 m_isAtFirstInFlowChild(true) {} | 210 m_isAtFirstInFlowChild(true) {} |
204 | 211 |
205 // Store multicol layout state before first layout of a block child. The child
may contain a | 212 // Store multicol layout state before first layout of a block child. The child |
206 // column spanner. If we need to re-lay out the block child because our initia
l logical top | 213 // may contain a column spanner. If we need to re-lay out the block child |
207 // estimate was wrong, we need to roll back to how things were before laying o
ut the child. | 214 // because our initial logical top estimate was wrong, we need to roll back to |
| 215 // how things were before laying out the child. |
208 void storeMultiColumnLayoutState(const LayoutFlowThread& flowThread) { | 216 void storeMultiColumnLayoutState(const LayoutFlowThread& flowThread) { |
209 m_multiColumnLayoutState = flowThread.multiColumnLayoutState(); | 217 m_multiColumnLayoutState = flowThread.multiColumnLayoutState(); |
210 } | 218 } |
211 void rollBackToInitialMultiColumnLayoutState(LayoutFlowThread& flowThread) { | 219 void rollBackToInitialMultiColumnLayoutState(LayoutFlowThread& flowThread) { |
212 flowThread.restoreMultiColumnLayoutState(m_multiColumnLayoutState); | 220 flowThread.restoreMultiColumnLayoutState(m_multiColumnLayoutState); |
213 } | 221 } |
214 | 222 |
215 const MarginInfo& marginInfo() const { return m_marginInfo; } | 223 const MarginInfo& marginInfo() const { return m_marginInfo; } |
216 MarginInfo& marginInfo() { return m_marginInfo; } | 224 MarginInfo& marginInfo() { return m_marginInfo; } |
217 LayoutUnit& previousFloatLogicalBottom() { | 225 LayoutUnit& previousFloatLogicalBottom() { |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
267 return true; | 275 return true; |
268 } | 276 } |
269 return relayoutChildren; | 277 return relayoutChildren; |
270 } | 278 } |
271 | 279 |
272 void LayoutBlockFlow::checkForPaginationLogicalHeightChange( | 280 void LayoutBlockFlow::checkForPaginationLogicalHeightChange( |
273 LayoutUnit& pageLogicalHeight, | 281 LayoutUnit& pageLogicalHeight, |
274 bool& pageLogicalHeightChanged, | 282 bool& pageLogicalHeightChanged, |
275 bool& hasSpecifiedPageLogicalHeight) { | 283 bool& hasSpecifiedPageLogicalHeight) { |
276 if (LayoutMultiColumnFlowThread* flowThread = multiColumnFlowThread()) { | 284 if (LayoutMultiColumnFlowThread* flowThread = multiColumnFlowThread()) { |
277 // Calculate the non-auto content box height, or set it to 0 if it's auto. W
e need to know | 285 // Calculate the non-auto content box height, or set it to 0 if it's auto. |
278 // this before layout, so that we can figure out where to insert column brea
ks. We also | 286 // We need to know this before layout, so that we can figure out where to |
279 // treat LayoutView (which may be paginated, which uses the multicol implmen
tation) as | 287 // insert column breaks. We also treat LayoutView (which may be paginated, |
280 // having non-auto height, since its height is deduced from the viewport hei
ght. We use | 288 // which uses the multicol implmentation) as having non-auto height, since |
281 // computeLogicalHeight() to calculate the content box height. That method w
ill clamp | 289 // its height is deduced from the viewport height. |
282 // against max-height and min-height. Since we're now at the beginning of la
yout, and we | 290 // We use computeLogicalHeight() to calculate the content box height. That |
283 // don't know the actual height of the content yet, only call that method wh
en height is | 291 // method will clamp against max-height and min-height. Since we're now at |
284 // definite, or we might fool ourselves into believing that columns have a d
efinite height | 292 // the beginning of layout, and we don't know the actual height of the |
285 // when they in fact don't. | 293 // content yet, only call that method when height is definite, or we might |
| 294 // fool ourselves into believing that columns have a definite height when |
| 295 // they in fact don't. |
286 LayoutUnit columnHeight; | 296 LayoutUnit columnHeight; |
287 if (hasDefiniteLogicalHeight() || isLayoutView()) { | 297 if (hasDefiniteLogicalHeight() || isLayoutView()) { |
288 LogicalExtentComputedValues computedValues; | 298 LogicalExtentComputedValues computedValues; |
289 computeLogicalHeight(LayoutUnit(), logicalTop(), computedValues); | 299 computeLogicalHeight(LayoutUnit(), logicalTop(), computedValues); |
290 columnHeight = computedValues.m_extent - borderAndPaddingLogicalHeight() - | 300 columnHeight = computedValues.m_extent - borderAndPaddingLogicalHeight() - |
291 scrollbarLogicalHeight(); | 301 scrollbarLogicalHeight(); |
292 } | 302 } |
293 pageLogicalHeightChanged = | 303 pageLogicalHeightChanged = |
294 columnHeight != flowThread->columnHeightAvailable(); | 304 columnHeight != flowThread->columnHeightAvailable(); |
295 flowThread->setColumnHeightAvailable(std::max(columnHeight, LayoutUnit())); | 305 flowThread->setColumnHeightAvailable(std::max(columnHeight, LayoutUnit())); |
296 } else if (isLayoutFlowThread()) { | 306 } else if (isLayoutFlowThread()) { |
297 LayoutFlowThread* flowThread = toLayoutFlowThread(this); | 307 LayoutFlowThread* flowThread = toLayoutFlowThread(this); |
298 | 308 |
299 // FIXME: This is a hack to always make sure we have a page logical height,
if said height | 309 // FIXME: This is a hack to always make sure we have a page logical height, |
300 // is known. The page logical height thing in LayoutState is meaningless for
flow | 310 // if said height is known. The page logical height thing in LayoutState is |
301 // thread-based pagination (page height isn't necessarily uniform throughout
the flow | 311 // meaningless for flow thread-based pagination (page height isn't |
302 // thread), but as long as it is used universally as a means to determine wh
ether page | 312 // necessarily uniform throughout the flow thread), but as long as it is |
303 // height is known or not, we need this. Page height is unknown when column
balancing is | 313 // used universally as a means to determine whether page height is known or |
304 // enabled and flow thread height is still unknown (i.e. during the first la
yout pass). When | 314 // not, we need this. Page height is unknown when column balancing is |
305 // it's unknown, we need to prevent the pagination code from assuming page b
reaks everywhere | 315 // enabled and flow thread height is still unknown (i.e. during the first |
306 // and thereby eating every top margin. It should be trivial to clean up and
get rid of this | 316 // layout pass). When it's unknown, we need to prevent the pagination code |
307 // hack once the old multicol implementation is gone. | 317 // from assuming page breaks everywhere and thereby eating every top margin. |
| 318 // It should be trivial to clean up and get rid of this hack once the old |
| 319 // multicol implementation is gone. |
308 pageLogicalHeight = | 320 pageLogicalHeight = |
309 flowThread->isPageLogicalHeightKnown() ? LayoutUnit(1) : LayoutUnit(); | 321 flowThread->isPageLogicalHeightKnown() ? LayoutUnit(1) : LayoutUnit(); |
310 | 322 |
311 pageLogicalHeightChanged = flowThread->pageLogicalSizeChanged(); | 323 pageLogicalHeightChanged = flowThread->pageLogicalSizeChanged(); |
312 } | 324 } |
313 } | 325 } |
314 | 326 |
315 void LayoutBlockFlow::setBreakAtLineToAvoidWidow(int lineToBreak) { | 327 void LayoutBlockFlow::setBreakAtLineToAvoidWidow(int lineToBreak) { |
316 ASSERT(lineToBreak >= 0); | 328 ASSERT(lineToBreak >= 0); |
317 ensureRareData(); | 329 ensureRareData(); |
318 ASSERT(!m_rareData->m_didBreakAtLineToAvoidWidow); | 330 ASSERT(!m_rareData->m_didBreakAtLineToAvoidWidow); |
319 m_rareData->m_lineBreakToAvoidWidow = lineToBreak; | 331 m_rareData->m_lineBreakToAvoidWidow = lineToBreak; |
320 } | 332 } |
321 | 333 |
322 void LayoutBlockFlow::setDidBreakAtLineToAvoidWidow() { | 334 void LayoutBlockFlow::setDidBreakAtLineToAvoidWidow() { |
323 ASSERT(!shouldBreakAtLineToAvoidWidow()); | 335 ASSERT(!shouldBreakAtLineToAvoidWidow()); |
324 | 336 |
325 // This function should be called only after a break was applied to avoid wido
ws | 337 // This function should be called only after a break was applied to avoid |
326 // so assert |m_rareData| exists. | 338 // widows so assert |m_rareData| exists. |
327 ASSERT(m_rareData); | 339 ASSERT(m_rareData); |
328 | 340 |
329 m_rareData->m_didBreakAtLineToAvoidWidow = true; | 341 m_rareData->m_didBreakAtLineToAvoidWidow = true; |
330 } | 342 } |
331 | 343 |
332 void LayoutBlockFlow::clearDidBreakAtLineToAvoidWidow() { | 344 void LayoutBlockFlow::clearDidBreakAtLineToAvoidWidow() { |
333 if (!m_rareData) | 345 if (!m_rareData) |
334 return; | 346 return; |
335 | 347 |
336 m_rareData->m_didBreakAtLineToAvoidWidow = false; | 348 m_rareData->m_didBreakAtLineToAvoidWidow = false; |
337 } | 349 } |
338 | 350 |
339 void LayoutBlockFlow::clearShouldBreakAtLineToAvoidWidow() const { | 351 void LayoutBlockFlow::clearShouldBreakAtLineToAvoidWidow() const { |
340 ASSERT(shouldBreakAtLineToAvoidWidow()); | 352 ASSERT(shouldBreakAtLineToAvoidWidow()); |
341 if (!m_rareData) | 353 if (!m_rareData) |
342 return; | 354 return; |
343 | 355 |
344 m_rareData->m_lineBreakToAvoidWidow = -1; | 356 m_rareData->m_lineBreakToAvoidWidow = -1; |
345 } | 357 } |
346 | 358 |
347 bool LayoutBlockFlow::isSelfCollapsingBlock() const { | 359 bool LayoutBlockFlow::isSelfCollapsingBlock() const { |
348 if (needsLayout()) { | 360 if (needsLayout()) { |
349 // Sometimes we don't lay out objects in DOM order (column spanners being on
e such relevant | 361 // Sometimes we don't lay out objects in DOM order (column spanners being |
350 // type of object right here). As long as the object in question establishes
a new | 362 // one such relevant type of object right here). As long as the object in |
351 // formatting context, that's nothing to worry about, though. | 363 // question establishes a new formatting context, that's nothing to worry |
| 364 // about, though. |
352 ASSERT(createsNewFormattingContext()); | 365 ASSERT(createsNewFormattingContext()); |
353 return false; | 366 return false; |
354 } | 367 } |
355 ASSERT(!m_isSelfCollapsing == !checkIfIsSelfCollapsingBlock()); | 368 ASSERT(!m_isSelfCollapsing == !checkIfIsSelfCollapsingBlock()); |
356 return m_isSelfCollapsing; | 369 return m_isSelfCollapsing; |
357 } | 370 } |
358 | 371 |
359 bool LayoutBlockFlow::checkIfIsSelfCollapsingBlock() const { | 372 bool LayoutBlockFlow::checkIfIsSelfCollapsingBlock() const { |
360 // We are not self-collapsing if we | 373 // We are not self-collapsing if we |
361 // (a) have a non-zero height according to layout (an optimization to avoid wa
sting time) | 374 // (a) have a non-zero height according to layout (an optimization to avoid |
| 375 // wasting time) |
362 // (b) have border/padding, | 376 // (b) have border/padding, |
363 // (c) have a min-height | 377 // (c) have a min-height |
364 // (d) have specified that one of our margins can't collapse using a CSS exten
sion | 378 // (d) have specified that one of our margins can't collapse using a CSS |
| 379 // extension |
365 // (e) establish a new block formatting context. | 380 // (e) establish a new block formatting context. |
366 | 381 |
367 // The early exit must be done before we check for clean layout. | 382 // The early exit must be done before we check for clean layout. |
368 // We should be able to give a quick answer if the box is a relayout boundary. | 383 // We should be able to give a quick answer if the box is a relayout boundary. |
369 // Being a relayout boundary implies a block formatting context, and also | 384 // Being a relayout boundary implies a block formatting context, and also |
370 // our internal layout shouldn't affect our container in any way. | 385 // our internal layout shouldn't affect our container in any way. |
371 if (createsNewFormattingContext()) | 386 if (createsNewFormattingContext()) |
372 return false; | 387 return false; |
373 | 388 |
374 // Placeholder elements are not laid out until the dimensions of their parent
text control are known, so they | 389 // Placeholder elements are not laid out until the dimensions of their parent |
375 // don't get layout until their parent has had layout - this is unique in the
layout tree and means | 390 // text control are known, so they don't get layout until their parent has had |
376 // when we call isSelfCollapsingBlock on them we find that they still need lay
out. | 391 // layout - this is unique in the layout tree and means when we call |
| 392 // isSelfCollapsingBlock on them we find that they still need layout. |
377 ASSERT(!needsLayout() || | 393 ASSERT(!needsLayout() || |
378 (node() && node()->isElementNode() && | 394 (node() && node()->isElementNode() && |
379 toElement(node())->shadowPseudoId() == "-webkit-input-placeholder")); | 395 toElement(node())->shadowPseudoId() == "-webkit-input-placeholder")); |
380 | 396 |
381 if (logicalHeight() > LayoutUnit() || borderAndPaddingLogicalHeight() || | 397 if (logicalHeight() > LayoutUnit() || borderAndPaddingLogicalHeight() || |
382 style()->logicalMinHeight().isPositive() || | 398 style()->logicalMinHeight().isPositive() || |
383 style()->marginBeforeCollapse() == MarginCollapseSeparate || | 399 style()->marginBeforeCollapse() == MarginCollapseSeparate || |
384 style()->marginAfterCollapse() == MarginCollapseSeparate) | 400 style()->marginAfterCollapse() == MarginCollapseSeparate) |
385 return false; | 401 return false; |
386 | 402 |
387 Length logicalHeightLength = style()->logicalHeight(); | 403 Length logicalHeightLength = style()->logicalHeight(); |
388 bool hasAutoHeight = logicalHeightLength.isAuto(); | 404 bool hasAutoHeight = logicalHeightLength.isAuto(); |
389 if (logicalHeightLength.isPercentOrCalc() && !document().inQuirksMode()) { | 405 if (logicalHeightLength.isPercentOrCalc() && !document().inQuirksMode()) { |
390 hasAutoHeight = true; | 406 hasAutoHeight = true; |
391 for (LayoutBlock* cb = containingBlock(); !cb->isLayoutView(); | 407 for (LayoutBlock* cb = containingBlock(); !cb->isLayoutView(); |
392 cb = cb->containingBlock()) { | 408 cb = cb->containingBlock()) { |
393 if (cb->style()->logicalHeight().isFixed() || cb->isTableCell()) | 409 if (cb->style()->logicalHeight().isFixed() || cb->isTableCell()) |
394 hasAutoHeight = false; | 410 hasAutoHeight = false; |
395 } | 411 } |
396 } | 412 } |
397 | 413 |
398 // If the height is 0 or auto, then whether or not we are a self-collapsing bl
ock depends | 414 // If the height is 0 or auto, then whether or not we are a self-collapsing |
399 // on whether we have content that is all self-collapsing or not. | 415 // block depends on whether we have content that is all self-collapsing. |
400 // TODO(alancutter): Make this work correctly for calc lengths. | 416 // TODO(alancutter): Make this work correctly for calc lengths. |
401 if (hasAutoHeight || ((logicalHeightLength.isFixed() || | 417 if (hasAutoHeight || ((logicalHeightLength.isFixed() || |
402 logicalHeightLength.isPercentOrCalc()) && | 418 logicalHeightLength.isPercentOrCalc()) && |
403 logicalHeightLength.isZero())) { | 419 logicalHeightLength.isZero())) { |
404 // If the block has inline children, see if we generated any line boxes. If
we have any | 420 // If the block has inline children, see if we generated any line boxes. |
405 // line boxes, then we can't be self-collapsing, since we have content. | 421 // If we have any line boxes, then we can't be self-collapsing, since we |
| 422 // have content. |
406 if (childrenInline()) | 423 if (childrenInline()) |
407 return !firstLineBox(); | 424 return !firstLineBox(); |
408 | 425 |
409 // Whether or not we collapse is dependent on whether all our normal flow ch
ildren | 426 // Whether or not we collapse is dependent on whether all our normal flow |
| 427 // children |
410 // are also self-collapsing. | 428 // are also self-collapsing. |
411 for (LayoutBox* child = firstChildBox(); child; | 429 for (LayoutBox* child = firstChildBox(); child; |
412 child = child->nextSiblingBox()) { | 430 child = child->nextSiblingBox()) { |
413 if (child->isFloatingOrOutOfFlowPositioned()) | 431 if (child->isFloatingOrOutOfFlowPositioned()) |
414 continue; | 432 continue; |
415 if (!child->isSelfCollapsingBlock()) | 433 if (!child->isSelfCollapsingBlock()) |
416 return false; | 434 return false; |
417 } | 435 } |
418 return true; | 436 return true; |
419 } | 437 } |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
467 bool hasSpecifiedPageLogicalHeight = false; | 485 bool hasSpecifiedPageLogicalHeight = false; |
468 checkForPaginationLogicalHeightChange(pageLogicalHeight, | 486 checkForPaginationLogicalHeightChange(pageLogicalHeight, |
469 pageLogicalHeightChanged, | 487 pageLogicalHeightChanged, |
470 hasSpecifiedPageLogicalHeight); | 488 hasSpecifiedPageLogicalHeight); |
471 if (pageLogicalHeightChanged) | 489 if (pageLogicalHeightChanged) |
472 relayoutChildren = true; | 490 relayoutChildren = true; |
473 | 491 |
474 LayoutState state(*this, locationOffset(), pageLogicalHeight, | 492 LayoutState state(*this, locationOffset(), pageLogicalHeight, |
475 pageLogicalHeightChanged, logicalWidthChanged); | 493 pageLogicalHeightChanged, logicalWidthChanged); |
476 | 494 |
477 // We use four values, maxTopPos, maxTopNeg, maxBottomPos, and maxBottomNeg, t
o track | 495 // We use four values, maxTopPos, maxTopNeg, maxBottomPos, and maxBottomNeg, |
478 // our current maximal positive and negative margins. These values are used wh
en we | 496 // to track our current maximal positive and negative margins. These values |
479 // are collapsed with adjacent blocks, so for example, if you have block A and
B | 497 // are used when we are collapsed with adjacent blocks, so for example, if you |
480 // collapsing together, then you'd take the maximal positive margin from both
A and B | 498 // have block A and B collapsing together, then you'd take the maximal |
481 // and subtract it from the maximal negative margin from both A and B to get t
he | 499 // positive margin from both A and B and subtract it from the maximal negative |
482 // true collapsed margin. This algorithm is recursive, so when we finish layou
t() | 500 // margin from both A and B to get the true collapsed margin. This algorithm |
483 // our block knows its current maximal positive/negative values. | 501 // is recursive, so when we finish layout() our block knows its current |
| 502 // maximal positive/negative values. |
484 // | 503 // |
485 // Start out by setting our margin values to our current margins. Table cells
have | 504 // Start out by setting our margin values to our current margins. Table cells |
486 // no margins, so we don't fill in the values for table cells. | 505 // have no margins, so we don't fill in the values for table cells. |
487 if (!isTableCell()) { | 506 if (!isTableCell()) { |
488 initMaxMarginValues(); | 507 initMaxMarginValues(); |
489 setHasMarginBeforeQuirk(style()->hasMarginBeforeQuirk()); | 508 setHasMarginBeforeQuirk(style()->hasMarginBeforeQuirk()); |
490 setHasMarginAfterQuirk(style()->hasMarginAfterQuirk()); | 509 setHasMarginAfterQuirk(style()->hasMarginAfterQuirk()); |
491 } | 510 } |
492 | 511 |
493 if (state.isPaginated()) { | 512 if (state.isPaginated()) { |
494 setPaginationStrutPropagatedFromChild(LayoutUnit()); | 513 setPaginationStrutPropagatedFromChild(LayoutUnit()); |
495 | 514 |
496 // Start with any applicable computed break-after and break-before values fo
r this | 515 // Start with any applicable computed break-after and break-before values |
497 // object. During child layout, breakBefore will be joined with the breakBef
ore value of | 516 // for this object. During child layout, breakBefore will be joined with the |
498 // the first in-flow child, and breakAfter will be joined with the breakAfte
r value of the | 517 // breakBefore value of the first in-flow child, and breakAfter will be |
499 // last in-flow child. This is done in order to honor the requirement that a
class A break | 518 // joined with the breakAfter value of the last in-flow child. This is done |
500 // point [1] may only exists *between* in-flow siblings (i.e. not before the
first child | 519 // in order to honor the requirement that a class A break point [1] may only |
501 // and not after the last child). | 520 // exists *between* in-flow siblings (i.e. not before the first child and |
| 521 // not after the last child). |
502 // | 522 // |
503 // [1] https://drafts.csswg.org/css-break/#possible-breaks | 523 // [1] https://drafts.csswg.org/css-break/#possible-breaks |
504 setBreakBefore(LayoutBlock::breakBefore()); | 524 setBreakBefore(LayoutBlock::breakBefore()); |
505 setBreakAfter(LayoutBlock::breakAfter()); | 525 setBreakAfter(LayoutBlock::breakAfter()); |
506 } | 526 } |
507 | 527 |
508 LayoutUnit beforeEdge = borderBefore() + paddingBefore(); | 528 LayoutUnit beforeEdge = borderBefore() + paddingBefore(); |
509 LayoutUnit afterEdge = | 529 LayoutUnit afterEdge = |
510 borderAfter() + paddingAfter() + scrollbarLogicalHeight(); | 530 borderAfter() + paddingAfter() + scrollbarLogicalHeight(); |
511 LayoutUnit previousHeight = logicalHeight(); | 531 LayoutUnit previousHeight = logicalHeight(); |
(...skipping 10 matching lines...) Expand all Loading... |
522 // all inline children are removed from this block. | 542 // all inline children are removed from this block. |
523 setContainsInlineWithOutlineAndContinuation(false); | 543 setContainsInlineWithOutlineAndContinuation(false); |
524 if (childrenInline()) | 544 if (childrenInline()) |
525 layoutInlineChildren(relayoutChildren, afterEdge); | 545 layoutInlineChildren(relayoutChildren, afterEdge); |
526 else | 546 else |
527 layoutBlockChildren(relayoutChildren, layoutScope, beforeEdge, afterEdge); | 547 layoutBlockChildren(relayoutChildren, layoutScope, beforeEdge, afterEdge); |
528 | 548 |
529 bool preferredLogicalWidthsBecameDirty = | 549 bool preferredLogicalWidthsBecameDirty = |
530 !preferredLogicalWidthsWereDirty && preferredLogicalWidthsDirty(); | 550 !preferredLogicalWidthsWereDirty && preferredLogicalWidthsDirty(); |
531 if (preferredLogicalWidthsBecameDirty) { | 551 if (preferredLogicalWidthsBecameDirty) { |
532 // The only thing that should dirty preferred widths at this point is the ad
dition of | 552 // The only thing that should dirty preferred widths at this point is the |
533 // overflow:auto scrollbars in a descendant. To avoid a potential infinite
loop, | 553 // addition of overflow:auto scrollbars in a descendant. To avoid a |
534 // run layout again with auto scrollbars frozen in their current state. | 554 // potential infinite loop, run layout again with auto scrollbars frozen in |
| 555 // their current state. |
535 PaintLayerScrollableArea::FreezeScrollbarsScope freezeScrollbars; | 556 PaintLayerScrollableArea::FreezeScrollbarsScope freezeScrollbars; |
536 return layoutBlockFlow(relayoutChildren, pageLogicalHeight, layoutScope); | 557 return layoutBlockFlow(relayoutChildren, pageLogicalHeight, layoutScope); |
537 } | 558 } |
538 | 559 |
539 // Expand our intrinsic height to encompass floats. | 560 // Expand our intrinsic height to encompass floats. |
540 if (lowestFloatLogicalBottom() > (logicalHeight() - afterEdge) && | 561 if (lowestFloatLogicalBottom() > (logicalHeight() - afterEdge) && |
541 createsNewFormattingContext()) | 562 createsNewFormattingContext()) |
542 setLogicalHeight(lowestFloatLogicalBottom() + afterEdge); | 563 setLogicalHeight(lowestFloatLogicalBottom() + afterEdge); |
543 | 564 |
544 if (LayoutMultiColumnFlowThread* flowThread = multiColumnFlowThread()) { | 565 if (LayoutMultiColumnFlowThread* flowThread = multiColumnFlowThread()) { |
(...skipping 13 matching lines...) Expand all Loading... |
558 LayoutUnit oldClientAfterEdge = clientLogicalBottom(); | 579 LayoutUnit oldClientAfterEdge = clientLogicalBottom(); |
559 | 580 |
560 updateLogicalHeight(); | 581 updateLogicalHeight(); |
561 LayoutUnit newHeight = logicalHeight(); | 582 LayoutUnit newHeight = logicalHeight(); |
562 if (!childrenInline()) { | 583 if (!childrenInline()) { |
563 LayoutBlockFlow* lowestBlock = nullptr; | 584 LayoutBlockFlow* lowestBlock = nullptr; |
564 bool addedOverhangingFloats = false; | 585 bool addedOverhangingFloats = false; |
565 // One of our children's floats may have become an overhanging float for us. | 586 // One of our children's floats may have become an overhanging float for us. |
566 for (LayoutObject* child = lastChild(); child; | 587 for (LayoutObject* child = lastChild(); child; |
567 child = child->previousSibling()) { | 588 child = child->previousSibling()) { |
568 // TODO(robhogan): We should exclude blocks that create formatting context
s, not just out of flow or floating blocks. | 589 // TODO(robhogan): We should exclude blocks that create formatting |
| 590 // contexts, not just out of flow or floating blocks. |
569 if (child->isLayoutBlockFlow() && | 591 if (child->isLayoutBlockFlow() && |
570 !child->isFloatingOrOutOfFlowPositioned()) { | 592 !child->isFloatingOrOutOfFlowPositioned()) { |
571 LayoutBlockFlow* block = toLayoutBlockFlow(child); | 593 LayoutBlockFlow* block = toLayoutBlockFlow(child); |
572 if (!block->containsFloats()) | 594 if (!block->containsFloats()) |
573 continue; | 595 continue; |
574 lowestBlock = block; | 596 lowestBlock = block; |
575 if (oldHeight <= newHeight || | 597 if (oldHeight <= newHeight || |
576 block->lowestFloatLogicalBottom() + block->logicalTop() <= | 598 block->lowestFloatLogicalBottom() + block->logicalTop() <= |
577 newHeight) | 599 newHeight) |
578 break; | 600 break; |
579 addOverhangingFloats(block, false); | 601 addOverhangingFloats(block, false); |
580 addedOverhangingFloats = true; | 602 addedOverhangingFloats = true; |
581 } | 603 } |
582 } | 604 } |
583 // If we have no overhanging floats we still pass a record of the lowest non
-overhanging float up the tree so we can enclose it if | 605 // If we have no overhanging floats we still pass a record of the lowest |
584 // we are a formatting context and allow siblings to avoid it if they have n
egative margin and find themselves in its vicinity. | 606 // non-overhanging float up the tree so we can enclose it if we are a |
| 607 // formatting context and allow siblings to avoid it if they have negative |
| 608 // margin and find themselves in its vicinity. |
585 if (!addedOverhangingFloats) | 609 if (!addedOverhangingFloats) |
586 addLowestFloatFromChildren(lowestBlock); | 610 addLowestFloatFromChildren(lowestBlock); |
587 } | 611 } |
588 | 612 |
589 bool heightChanged = (previousHeight != newHeight); | 613 bool heightChanged = (previousHeight != newHeight); |
590 if (heightChanged) | 614 if (heightChanged) |
591 relayoutChildren = true; | 615 relayoutChildren = true; |
592 | 616 |
593 layoutPositionedObjects(relayoutChildren || isDocumentElement(), | 617 layoutPositionedObjects(relayoutChildren || isDocumentElement(), |
594 oldLeft != logicalLeft() | 618 oldLeft != logicalLeft() |
595 ? ForcedLayoutAfterContainingBlockMoved | 619 ? ForcedLayoutAfterContainingBlockMoved |
596 : DefaultLayout); | 620 : DefaultLayout); |
597 | 621 |
598 // Add overflow from children (unless we're multi-column, since in that case a
ll our child overflow is clipped anyway). | 622 // Add overflow from children (unless we're multi-column, since in that case |
| 623 // all our child overflow is clipped anyway). |
599 computeOverflow(oldClientAfterEdge); | 624 computeOverflow(oldClientAfterEdge); |
600 | 625 |
601 m_descendantsWithFloatsMarkedForLayout = false; | 626 m_descendantsWithFloatsMarkedForLayout = false; |
602 return true; | 627 return true; |
603 } | 628 } |
604 | 629 |
605 void LayoutBlockFlow::addLowestFloatFromChildren(LayoutBlockFlow* block) { | 630 void LayoutBlockFlow::addLowestFloatFromChildren(LayoutBlockFlow* block) { |
606 // TODO(robhogan): Make createsNewFormattingContext an ASSERT. | 631 // TODO(robhogan): Make createsNewFormattingContext an ASSERT. |
607 if (!block || !block->containsFloats() || | 632 if (!block || !block->containsFloats() || |
608 block->createsNewFormattingContext()) | 633 block->createsNewFormattingContext()) |
(...skipping 25 matching lines...) Expand all Loading... |
634 borderAndPaddingLogicalWidth() + availableLogicalWidth(); | 659 borderAndPaddingLogicalWidth() + availableLogicalWidth(); |
635 | 660 |
636 LayoutUnit childMarginStart = marginStartForChild(child); | 661 LayoutUnit childMarginStart = marginStartForChild(child); |
637 LayoutUnit newPosition = startPosition + childMarginStart; | 662 LayoutUnit newPosition = startPosition + childMarginStart; |
638 | 663 |
639 if (child.avoidsFloats() && containsFloats()) { | 664 if (child.avoidsFloats() && containsFloats()) { |
640 LayoutUnit positionToAvoidFloats = | 665 LayoutUnit positionToAvoidFloats = |
641 startOffsetForLine(logicalTopForChild(child), DoNotIndentText, | 666 startOffsetForLine(logicalTopForChild(child), DoNotIndentText, |
642 logicalHeightForChild(child)); | 667 logicalHeightForChild(child)); |
643 | 668 |
644 // If the child has an offset from the content edge to avoid floats then use
that, otherwise let any negative | 669 // If the child has an offset from the content edge to avoid floats then use |
645 // margin pull it back over the content edge or any positive margin push it
out. | 670 // that, otherwise let any negative margin pull it back over the content |
646 // If the child is being centred then the margin calculated to do that has f
actored in any offset required to | 671 // edge or any positive margin push it out. |
647 // avoid floats, so use it if necessary. | 672 // If the child is being centred then the margin calculated to do that has |
| 673 // factored in any offset required to avoid floats, so use it if necessary. |
648 if (style()->textAlign() == WEBKIT_CENTER || | 674 if (style()->textAlign() == WEBKIT_CENTER || |
649 child.style()->marginStartUsing(style()).isAuto()) | 675 child.style()->marginStartUsing(style()).isAuto()) |
650 newPosition = | 676 newPosition = |
651 std::max(newPosition, positionToAvoidFloats + childMarginStart); | 677 std::max(newPosition, positionToAvoidFloats + childMarginStart); |
652 else if (positionToAvoidFloats > initialStartPosition) | 678 else if (positionToAvoidFloats > initialStartPosition) |
653 newPosition = std::max(newPosition, positionToAvoidFloats); | 679 newPosition = std::max(newPosition, positionToAvoidFloats); |
654 } | 680 } |
655 | 681 |
656 setLogicalLeftForChild(child, style()->isLeftToRightDirection() | 682 setLogicalLeftForChild(child, style()->isLeftToRightDirection() |
657 ? newPosition | 683 ? newPosition |
(...skipping 16 matching lines...) Expand all Loading... |
674 child.setY(logicalTop); | 700 child.setY(logicalTop); |
675 } else { | 701 } else { |
676 child.setX(logicalTop); | 702 child.setX(logicalTop); |
677 } | 703 } |
678 } | 704 } |
679 | 705 |
680 void LayoutBlockFlow::markDescendantsWithFloatsForLayoutIfNeeded( | 706 void LayoutBlockFlow::markDescendantsWithFloatsForLayoutIfNeeded( |
681 LayoutBlockFlow& child, | 707 LayoutBlockFlow& child, |
682 LayoutUnit newLogicalTop, | 708 LayoutUnit newLogicalTop, |
683 LayoutUnit previousFloatLogicalBottom) { | 709 LayoutUnit previousFloatLogicalBottom) { |
684 // TODO(mstensho): rework the code to return early when there is no need for m
arking, instead | 710 // TODO(mstensho): rework the code to return early when there is no need for |
685 // of this |markDescendantsWithFloats| flag. | 711 // marking, instead of this |markDescendantsWithFloats| flag. |
686 bool markDescendantsWithFloats = false; | 712 bool markDescendantsWithFloats = false; |
687 if (newLogicalTop != child.logicalTop() && !child.avoidsFloats() && | 713 if (newLogicalTop != child.logicalTop() && !child.avoidsFloats() && |
688 child.containsFloats()) { | 714 child.containsFloats()) { |
689 markDescendantsWithFloats = true; | 715 markDescendantsWithFloats = true; |
690 } else if (UNLIKELY(newLogicalTop.mightBeSaturated())) { | 716 } else if (UNLIKELY(newLogicalTop.mightBeSaturated())) { |
691 // The logical top might be saturated for very large elements. Comparing wit
h the old | 717 // The logical top might be saturated for very large elements. Comparing |
692 // logical top might then yield a false negative, as adding and removing mar
gins, borders | 718 // with the old logical top might then yield a false negative, as adding and |
693 // etc. from a saturated number might yield incorrect results. If this is th
e case, always | 719 // removing margins, borders etc. from a saturated number might yield |
694 // mark for layout. | 720 // incorrect results. If this is the case, always mark for layout. |
695 markDescendantsWithFloats = true; | 721 markDescendantsWithFloats = true; |
696 } else if (!child.avoidsFloats() || child.shrinkToAvoidFloats()) { | 722 } else if (!child.avoidsFloats() || child.shrinkToAvoidFloats()) { |
697 // If an element might be affected by the presence of floats, then always ma
rk it for | 723 // If an element might be affected by the presence of floats, then always |
698 // layout. | 724 // mark it for layout. |
699 if (std::max(previousFloatLogicalBottom, lowestFloatLogicalBottom()) > | 725 if (std::max(previousFloatLogicalBottom, lowestFloatLogicalBottom()) > |
700 newLogicalTop) | 726 newLogicalTop) |
701 markDescendantsWithFloats = true; | 727 markDescendantsWithFloats = true; |
702 } | 728 } |
703 | 729 |
704 if (markDescendantsWithFloats) | 730 if (markDescendantsWithFloats) |
705 child.markAllDescendantsWithFloatsForLayout(); | 731 child.markAllDescendantsWithFloatsForLayout(); |
706 } | 732 } |
707 | 733 |
708 bool LayoutBlockFlow::positionAndLayoutOnceIfNeeded( | 734 bool LayoutBlockFlow::positionAndLayoutOnceIfNeeded( |
709 LayoutBox& child, | 735 LayoutBox& child, |
710 LayoutUnit newLogicalTop, | 736 LayoutUnit newLogicalTop, |
711 BlockChildrenLayoutInfo& layoutInfo) { | 737 BlockChildrenLayoutInfo& layoutInfo) { |
712 if (LayoutFlowThread* flowThread = flowThreadContainingBlock()) | 738 if (LayoutFlowThread* flowThread = flowThreadContainingBlock()) |
713 layoutInfo.rollBackToInitialMultiColumnLayoutState(*flowThread); | 739 layoutInfo.rollBackToInitialMultiColumnLayoutState(*flowThread); |
714 | 740 |
715 if (child.isLayoutBlockFlow()) { | 741 if (child.isLayoutBlockFlow()) { |
716 LayoutUnit& previousFloatLogicalBottom = | 742 LayoutUnit& previousFloatLogicalBottom = |
717 layoutInfo.previousFloatLogicalBottom(); | 743 layoutInfo.previousFloatLogicalBottom(); |
718 LayoutBlockFlow& childBlockFlow = toLayoutBlockFlow(child); | 744 LayoutBlockFlow& childBlockFlow = toLayoutBlockFlow(child); |
719 if (childBlockFlow.containsFloats() || containsFloats()) | 745 if (childBlockFlow.containsFloats() || containsFloats()) |
720 markDescendantsWithFloatsForLayoutIfNeeded(childBlockFlow, newLogicalTop, | 746 markDescendantsWithFloatsForLayoutIfNeeded(childBlockFlow, newLogicalTop, |
721 previousFloatLogicalBottom); | 747 previousFloatLogicalBottom); |
722 | 748 |
723 // TODO(mstensho): A writing mode root is one thing, but we should be able t
o skip anything | 749 // TODO(mstensho): A writing mode root is one thing, but we should be able |
724 // that establishes a new block formatting context here. Their floats don't
affect us. | 750 // to skip anything that establishes a new block formatting context here. |
| 751 // Their floats don't affect us. |
725 if (!childBlockFlow.isWritingModeRoot()) | 752 if (!childBlockFlow.isWritingModeRoot()) |
726 previousFloatLogicalBottom = | 753 previousFloatLogicalBottom = |
727 std::max(previousFloatLogicalBottom, | 754 std::max(previousFloatLogicalBottom, |
728 childBlockFlow.logicalTop() + | 755 childBlockFlow.logicalTop() + |
729 childBlockFlow.lowestFloatLogicalBottom()); | 756 childBlockFlow.lowestFloatLogicalBottom()); |
730 } | 757 } |
731 | 758 |
732 LayoutUnit oldLogicalTop = logicalTopForChild(child); | 759 LayoutUnit oldLogicalTop = logicalTopForChild(child); |
733 setLogicalTopForChild(child, newLogicalTop); | 760 setLogicalTopForChild(child, newLogicalTop); |
734 | 761 |
735 SubtreeLayoutScope layoutScope(child); | 762 SubtreeLayoutScope layoutScope(child); |
736 if (!child.needsLayout()) { | 763 if (!child.needsLayout()) { |
737 if (newLogicalTop != oldLogicalTop && child.shrinkToAvoidFloats()) { | 764 if (newLogicalTop != oldLogicalTop && child.shrinkToAvoidFloats()) { |
738 // The child's width is affected by adjacent floats. When the child shifts
to clear an | 765 // The child's width is affected by adjacent floats. When the child shifts |
739 // item, its width can change (because it has more available width). | 766 // to clear an item, its width can change (because it has more available |
| 767 // width). |
740 layoutScope.setChildNeedsLayout(&child); | 768 layoutScope.setChildNeedsLayout(&child); |
741 } else { | 769 } else { |
742 markChildForPaginationRelayoutIfNeeded(child, layoutScope); | 770 markChildForPaginationRelayoutIfNeeded(child, layoutScope); |
743 } | 771 } |
744 } | 772 } |
745 | 773 |
746 if (!child.needsLayout()) | 774 if (!child.needsLayout()) |
747 return false; | 775 return false; |
748 child.layout(); | 776 child.layout(); |
749 return true; | 777 return true; |
750 } | 778 } |
751 | 779 |
752 void LayoutBlockFlow::insertForcedBreakBeforeChildIfNeeded( | 780 void LayoutBlockFlow::insertForcedBreakBeforeChildIfNeeded( |
753 LayoutBox& child, | 781 LayoutBox& child, |
754 BlockChildrenLayoutInfo& layoutInfo) { | 782 BlockChildrenLayoutInfo& layoutInfo) { |
755 if (layoutInfo.isAtFirstInFlowChild()) { | 783 if (layoutInfo.isAtFirstInFlowChild()) { |
756 // There's no class A break point before the first child (only *between* sib
lings), so | 784 // There's no class A break point before the first child (only *between* |
757 // steal its break value and join it with what we already have here. | 785 // siblings), so steal its break value and join it with what we already have |
| 786 // here. |
758 setBreakBefore( | 787 setBreakBefore( |
759 joinFragmentainerBreakValues(breakBefore(), child.breakBefore())); | 788 joinFragmentainerBreakValues(breakBefore(), child.breakBefore())); |
760 return; | 789 return; |
761 } | 790 } |
762 | 791 |
763 // Figure out if a forced break should be inserted in front of the child. If w
e insert a forced | 792 // Figure out if a forced break should be inserted in front of the child. If |
764 // break, the margins on this child may not collapse with those preceding the
break. | 793 // we insert a forced break, the margins on this child may not collapse with |
| 794 // those preceding the break. |
765 EBreak classABreakPointValue = | 795 EBreak classABreakPointValue = |
766 child.classABreakPointValue(layoutInfo.previousBreakAfterValue()); | 796 child.classABreakPointValue(layoutInfo.previousBreakAfterValue()); |
767 if (isForcedFragmentainerBreakValue(classABreakPointValue)) { | 797 if (isForcedFragmentainerBreakValue(classABreakPointValue)) { |
768 layoutInfo.marginInfo().clearMargin(); | 798 layoutInfo.marginInfo().clearMargin(); |
769 LayoutUnit oldLogicalTop = logicalHeight(); | 799 LayoutUnit oldLogicalTop = logicalHeight(); |
770 LayoutUnit newLogicalTop = | 800 LayoutUnit newLogicalTop = |
771 applyForcedBreak(oldLogicalTop, classABreakPointValue); | 801 applyForcedBreak(oldLogicalTop, classABreakPointValue); |
772 setLogicalHeight(newLogicalTop); | 802 setLogicalHeight(newLogicalTop); |
773 LayoutUnit paginationStrut = newLogicalTop - oldLogicalTop; | 803 LayoutUnit paginationStrut = newLogicalTop - oldLogicalTop; |
774 child.setPaginationStrut(paginationStrut); | 804 child.setPaginationStrut(paginationStrut); |
775 } | 805 } |
776 } | 806 } |
777 | 807 |
778 void LayoutBlockFlow::layoutBlockChild(LayoutBox& child, | 808 void LayoutBlockFlow::layoutBlockChild(LayoutBox& child, |
779 BlockChildrenLayoutInfo& layoutInfo) { | 809 BlockChildrenLayoutInfo& layoutInfo) { |
780 MarginInfo& marginInfo = layoutInfo.marginInfo(); | 810 MarginInfo& marginInfo = layoutInfo.marginInfo(); |
781 LayoutBlockFlow* childLayoutBlockFlow = | 811 LayoutBlockFlow* childLayoutBlockFlow = |
782 child.isLayoutBlockFlow() ? toLayoutBlockFlow(&child) : nullptr; | 812 child.isLayoutBlockFlow() ? toLayoutBlockFlow(&child) : nullptr; |
783 LayoutUnit oldPosMarginBefore = maxPositiveMarginBefore(); | 813 LayoutUnit oldPosMarginBefore = maxPositiveMarginBefore(); |
784 LayoutUnit oldNegMarginBefore = maxNegativeMarginBefore(); | 814 LayoutUnit oldNegMarginBefore = maxNegativeMarginBefore(); |
785 | 815 |
786 // The child is a normal flow object. Compute the margins we will use for coll
apsing now. | 816 // The child is a normal flow object. Compute the margins we will use for |
| 817 // collapsing now. |
787 child.computeAndSetBlockDirectionMargins(this); | 818 child.computeAndSetBlockDirectionMargins(this); |
788 | 819 |
789 // Try to guess our correct logical top position. In most cases this guess wil
l | 820 // Try to guess our correct logical top position. In most cases this guess |
790 // be correct. Only if we're wrong (when we compute the real logical top posit
ion) | 821 // will be correct. Only if we're wrong (when we compute the real logical top |
791 // will we have to potentially relayout. | 822 // position) will we have to potentially relayout. |
792 LayoutUnit estimateWithoutPagination; | 823 LayoutUnit estimateWithoutPagination; |
793 LayoutUnit logicalTopEstimate = | 824 LayoutUnit logicalTopEstimate = |
794 estimateLogicalTopPosition(child, layoutInfo, estimateWithoutPagination); | 825 estimateLogicalTopPosition(child, layoutInfo, estimateWithoutPagination); |
795 | 826 |
796 // Cache our old rect so that we can dirty the proper paint invalidation rects
if the child moves. | 827 // Cache our old rect so that we can dirty the proper paint invalidation rects |
| 828 // if the child moves. |
797 LayoutRect oldRect = child.frameRect(); | 829 LayoutRect oldRect = child.frameRect(); |
798 | 830 |
799 if (LayoutFlowThread* flowThread = flowThreadContainingBlock()) | 831 if (LayoutFlowThread* flowThread = flowThreadContainingBlock()) |
800 layoutInfo.storeMultiColumnLayoutState(*flowThread); | 832 layoutInfo.storeMultiColumnLayoutState(*flowThread); |
801 | 833 |
802 // Use the estimated block position and lay out the child if needed. After chi
ld layout, when | 834 // Use the estimated block position and lay out the child if needed. After |
803 // we have enough information to perform proper margin collapsing, float clear
ing and | 835 // child layout, when we have enough information to perform proper margin |
804 // pagination, we may have to reposition and lay out again if the estimate was
wrong. | 836 // collapsing, float clearing and pagination, we may have to reposition and |
| 837 // lay out again if the estimate was wrong. |
805 bool childNeededLayout = | 838 bool childNeededLayout = |
806 positionAndLayoutOnceIfNeeded(child, logicalTopEstimate, layoutInfo); | 839 positionAndLayoutOnceIfNeeded(child, logicalTopEstimate, layoutInfo); |
807 | 840 |
808 // Cache if we are at the top of the block right now. | 841 // Cache if we are at the top of the block right now. |
809 bool atBeforeSideOfBlock = marginInfo.atBeforeSideOfBlock(); | 842 bool atBeforeSideOfBlock = marginInfo.atBeforeSideOfBlock(); |
810 bool childIsSelfCollapsing = child.isSelfCollapsingBlock(); | 843 bool childIsSelfCollapsing = child.isSelfCollapsingBlock(); |
811 bool childDiscardMarginBefore = mustDiscardMarginBeforeForChild(child); | 844 bool childDiscardMarginBefore = mustDiscardMarginBeforeForChild(child); |
812 bool childDiscardMarginAfter = mustDiscardMarginAfterForChild(child); | 845 bool childDiscardMarginAfter = mustDiscardMarginAfterForChild(child); |
813 bool paginated = view()->layoutState()->isPaginated(); | 846 bool paginated = view()->layoutState()->isPaginated(); |
814 | 847 |
815 // If there should be a forced break before the child, we need to insert it be
fore attempting | 848 // If there should be a forced break before the child, we need to insert it |
816 // to collapse margins or apply clearance. | 849 // before attempting to collapse margins or apply clearance. |
817 if (paginated) { | 850 if (paginated) { |
818 // We will now insert the strut needed by any forced break. After this opera
tion, we will | 851 // We will now insert the strut needed by any forced break. After this |
819 // have calculated the offset where we can apply margin collapsing and clear
ance. After | 852 // operation, we will have calculated the offset where we can apply margin |
820 // having applied those things, we'll be at the position where we can honor
requirements of | 853 // collapsing and clearance. After having applied those things, we'll be at |
821 // unbreakable content, which may extend the strut further. | 854 // the position where we can honor requirements of unbreakable content, |
| 855 // which may extend the strut further. |
822 child.resetPaginationStrut(); | 856 child.resetPaginationStrut(); |
823 insertForcedBreakBeforeChildIfNeeded(child, layoutInfo); | 857 insertForcedBreakBeforeChildIfNeeded(child, layoutInfo); |
824 } | 858 } |
825 | 859 |
826 // Now determine the correct ypos based off examination of collapsing margin | 860 // Now determine the correct ypos based off examination of collapsing margin |
827 // values. | 861 // values. |
828 LayoutUnit logicalTopBeforeClear = | 862 LayoutUnit logicalTopBeforeClear = |
829 collapseMargins(child, marginInfo, childIsSelfCollapsing, | 863 collapseMargins(child, marginInfo, childIsSelfCollapsing, |
830 childDiscardMarginBefore, childDiscardMarginAfter); | 864 childDiscardMarginBefore, childDiscardMarginAfter); |
831 | 865 |
832 // Now check for clear. | 866 // Now check for clear. |
833 bool childDiscardMargin = childDiscardMarginBefore || childDiscardMarginAfter; | 867 bool childDiscardMargin = childDiscardMarginBefore || childDiscardMarginAfter; |
834 LayoutUnit newLogicalTop = clearFloatsIfNeeded( | 868 LayoutUnit newLogicalTop = clearFloatsIfNeeded( |
835 child, marginInfo, oldPosMarginBefore, oldNegMarginBefore, | 869 child, marginInfo, oldPosMarginBefore, oldNegMarginBefore, |
836 logicalTopBeforeClear, childIsSelfCollapsing, childDiscardMargin); | 870 logicalTopBeforeClear, childIsSelfCollapsing, childDiscardMargin); |
837 | 871 |
838 // If there's a forced break in front of this child, its final position has al
ready been | 872 // If there's a forced break in front of this child, its final position has |
839 // determined. Otherwise, see if there are other reasons for breaking before i
t | 873 // already been determined. Otherwise, see if there are other reasons for |
840 // (break-inside:avoid, or not enough space for the first piece of child conte
nt to fit in the | 874 // breaking before it (break-inside:avoid, or not enough space for the first |
841 // current fragmentainer), and adjust the position accordingly. | 875 // piece of child content to fit in the current fragmentainer), and adjust the |
| 876 // position accordingly. |
842 if (paginated) { | 877 if (paginated) { |
843 if (estimateWithoutPagination != newLogicalTop) { | 878 if (estimateWithoutPagination != newLogicalTop) { |
844 // We got a new position due to clearance or margin collapsing. Before we
attempt to | 879 // We got a new position due to clearance or margin collapsing. Before we |
845 // paginate (which may result in the position changing again), let's try a
gain at the | 880 // attempt to paginate (which may result in the position changing again), |
846 // new position (since a new position may result in a new logical height). | 881 // let's try again at the new position (since a new position may result in |
| 882 // a new logical height). |
847 positionAndLayoutOnceIfNeeded(child, newLogicalTop, layoutInfo); | 883 positionAndLayoutOnceIfNeeded(child, newLogicalTop, layoutInfo); |
848 } | 884 } |
849 | 885 |
850 // We have now applied forced breaks, margin collapsing and clearance, and w
e're at the | 886 // We have now applied forced breaks, margin collapsing and clearance, and |
851 // position where we can honor requirements of unbreakable content. | 887 // we're at the position where we can honor requirements of unbreakable |
| 888 // content. |
852 newLogicalTop = adjustBlockChildForPagination( | 889 newLogicalTop = adjustBlockChildForPagination( |
853 newLogicalTop, child, layoutInfo, | 890 newLogicalTop, child, layoutInfo, |
854 atBeforeSideOfBlock && logicalTopBeforeClear == newLogicalTop); | 891 atBeforeSideOfBlock && logicalTopBeforeClear == newLogicalTop); |
855 } | 892 } |
856 | 893 |
857 // Clearance, margin collapsing or pagination may have given us a new logical
top, in which | 894 // Clearance, margin collapsing or pagination may have given us a new logical |
858 // case we may have to reposition and possibly relayout as well. If we determi
ned during child | 895 // top, in which case we may have to reposition and possibly relayout as well. |
859 // layout that we need to insert a break to honor widows, we also need to rela
yout. | 896 // If we determined during child layout that we need to insert a break to |
| 897 // honor widows, we also need to relayout. |
860 if (newLogicalTop != logicalTopEstimate || child.needsLayout() || | 898 if (newLogicalTop != logicalTopEstimate || child.needsLayout() || |
861 (paginated && childLayoutBlockFlow && | 899 (paginated && childLayoutBlockFlow && |
862 childLayoutBlockFlow->shouldBreakAtLineToAvoidWidow())) { | 900 childLayoutBlockFlow->shouldBreakAtLineToAvoidWidow())) { |
863 positionAndLayoutOnceIfNeeded(child, newLogicalTop, layoutInfo); | 901 positionAndLayoutOnceIfNeeded(child, newLogicalTop, layoutInfo); |
864 } | 902 } |
865 | 903 |
866 // If we previously encountered a self-collapsing sibling of this child that h
ad clearance then | 904 // If we previously encountered a self-collapsing sibling of this child that |
867 // we set this bit to ensure we would not collapse the child's margins, and th
ose of any subsequent | 905 // had clearance then we set this bit to ensure we would not collapse the |
868 // self-collapsing siblings, with our parent. If this child is not self-collap
sing then it can | 906 // child's margins, and those of any subsequent self-collapsing siblings, with |
869 // collapse its margins with the parent so reset the bit. | 907 // our parent. If this child is not self-collapsing then it can collapse its |
| 908 // margins with the parent so reset the bit. |
870 if (!marginInfo.canCollapseMarginAfterWithLastChild() && | 909 if (!marginInfo.canCollapseMarginAfterWithLastChild() && |
871 !childIsSelfCollapsing) | 910 !childIsSelfCollapsing) |
872 marginInfo.setCanCollapseMarginAfterWithLastChild(true); | 911 marginInfo.setCanCollapseMarginAfterWithLastChild(true); |
873 | 912 |
874 // We are no longer at the top of the block if we encounter a non-empty child. | 913 // We are no longer at the top of the block if we encounter a non-empty child. |
875 // This has to be done after checking for clear, so that margins can be reset
if a clear occurred. | 914 // This has to be done after checking for clear, so that margins can be reset |
| 915 // if a clear occurred. |
876 if (marginInfo.atBeforeSideOfBlock() && !childIsSelfCollapsing) | 916 if (marginInfo.atBeforeSideOfBlock() && !childIsSelfCollapsing) |
877 marginInfo.setAtBeforeSideOfBlock(false); | 917 marginInfo.setAtBeforeSideOfBlock(false); |
878 | 918 |
879 // Now place the child in the correct left position | 919 // Now place the child in the correct left position |
880 determineLogicalLeftPositionForChild(child); | 920 determineLogicalLeftPositionForChild(child); |
881 | 921 |
882 LayoutSize childOffset = child.location() - oldRect.location(); | 922 LayoutSize childOffset = child.location() - oldRect.location(); |
883 | 923 |
884 // Update our height now that the child has been placed in the correct positio
n. | 924 // Update our height now that the child has been placed in the correct |
| 925 // position. |
885 setLogicalHeight(logicalHeight() + logicalHeightForChild(child)); | 926 setLogicalHeight(logicalHeight() + logicalHeightForChild(child)); |
886 if (mustSeparateMarginAfterForChild(child)) { | 927 if (mustSeparateMarginAfterForChild(child)) { |
887 setLogicalHeight(logicalHeight() + marginAfterForChild(child)); | 928 setLogicalHeight(logicalHeight() + marginAfterForChild(child)); |
888 marginInfo.clearMargin(); | 929 marginInfo.clearMargin(); |
889 } | 930 } |
890 // If the child has overhanging floats that intrude into following siblings (o
r possibly out | 931 // If the child has overhanging floats that intrude into following siblings |
891 // of this block), then the parent gets notified of the floats now. | 932 // (or possibly out of this block), then the parent gets notified of the |
| 933 // floats now. |
892 if (childLayoutBlockFlow) | 934 if (childLayoutBlockFlow) |
893 addOverhangingFloats(childLayoutBlockFlow, !childNeededLayout); | 935 addOverhangingFloats(childLayoutBlockFlow, !childNeededLayout); |
894 | 936 |
895 // If the child moved, we have to invalidate its paint as well as any floating
/positioned | 937 // If the child moved, we have to invalidate its paint as well as any |
896 // descendants. An exception is if we need a layout. In this case, we know we'
re going to | 938 // floating/positioned descendants. An exception is if we need a layout. |
897 // invalidate our paint (and the child) anyway. | 939 // In this case, we know we're going to invalidate our paint (and the child) |
| 940 // anyway. |
898 if (!selfNeedsLayout() && (childOffset.width() || childOffset.height()) && | 941 if (!selfNeedsLayout() && (childOffset.width() || childOffset.height()) && |
899 child.isLayoutBlockFlow()) | 942 child.isLayoutBlockFlow()) |
900 BlockFlowPaintInvalidator(toLayoutBlockFlow(child)) | 943 BlockFlowPaintInvalidator(toLayoutBlockFlow(child)) |
901 .invalidatePaintForOverhangingFloats(); | 944 .invalidatePaintForOverhangingFloats(); |
902 | 945 |
903 if (paginated) { | 946 if (paginated) { |
904 // Keep track of the break-after value of the child, so that it can be joine
d with the | 947 // Keep track of the break-after value of the child, so that it can be |
905 // break-before value of the next in-flow object at the next class A break p
oint. | 948 // joined with the break-before value of the next in-flow object at the next |
| 949 // class A break point. |
906 layoutInfo.setPreviousBreakAfterValue(child.breakAfter()); | 950 layoutInfo.setPreviousBreakAfterValue(child.breakAfter()); |
907 | 951 |
908 paginatedContentWasLaidOut(child.logicalBottom()); | 952 paginatedContentWasLaidOut(child.logicalBottom()); |
909 } | 953 } |
910 | 954 |
911 if (child.isLayoutMultiColumnSpannerPlaceholder()) { | 955 if (child.isLayoutMultiColumnSpannerPlaceholder()) { |
912 // The actual column-span:all element is positioned by this placeholder chil
d. | 956 // The actual column-span:all element is positioned by this placeholder |
| 957 // child. |
913 positionSpannerDescendant(toLayoutMultiColumnSpannerPlaceholder(child)); | 958 positionSpannerDescendant(toLayoutMultiColumnSpannerPlaceholder(child)); |
914 } | 959 } |
915 } | 960 } |
916 | 961 |
917 LayoutUnit LayoutBlockFlow::adjustBlockChildForPagination( | 962 LayoutUnit LayoutBlockFlow::adjustBlockChildForPagination( |
918 LayoutUnit logicalTop, | 963 LayoutUnit logicalTop, |
919 LayoutBox& child, | 964 LayoutBox& child, |
920 BlockChildrenLayoutInfo& layoutInfo, | 965 BlockChildrenLayoutInfo& layoutInfo, |
921 bool atBeforeSideOfBlock) { | 966 bool atBeforeSideOfBlock) { |
922 LayoutBlockFlow* childBlockFlow = | 967 LayoutBlockFlow* childBlockFlow = |
923 child.isLayoutBlockFlow() ? toLayoutBlockFlow(&child) : 0; | 968 child.isLayoutBlockFlow() ? toLayoutBlockFlow(&child) : 0; |
924 | 969 |
925 // See if we need a soft (unforced) break in front of this child, and set the
pagination strut | 970 // See if we need a soft (unforced) break in front of this child, and set the |
926 // in that case. An unforced break may come from two sources: | 971 // pagination strut in that case. An unforced break may come from two sources: |
927 // 1. The first piece of content inside the child doesn't fit in the current p
age or column | 972 // 1. The first piece of content inside the child doesn't fit in the current |
928 // 2. The child itself has breaking restrictions (break-inside:avoid, replaced
content, etc.) | 973 // page or column |
929 // and doesn't fully fit in the current page or column. | 974 // 2. The child itself has breaking restrictions (break-inside:avoid, replaced |
| 975 // content, etc.) and doesn't fully fit in the current page or column. |
930 // | 976 // |
931 // No matter which source, if we need to insert a strut, it should always take
us to the exact | 977 // No matter which source, if we need to insert a strut, it should always take |
932 // top of a page or column further ahead, or be zero. | 978 // us to the exact top of a page or column further ahead, or be zero. |
933 | 979 |
934 // The first piece of content inside the child may have set a strut during lay
out. Currently, | 980 // The first piece of content inside the child may have set a strut during |
935 // only block flows support strut propagation, but this may (and should) chang
e in the future. | 981 // layout. Currently, only block flows support strut propagation, but this may |
936 // See crbug.com/539873 | 982 // (and should) change in the future. See crbug.com/539873 |
937 LayoutUnit strutFromContent = | 983 LayoutUnit strutFromContent = |
938 childBlockFlow ? childBlockFlow->paginationStrutPropagatedFromChild() | 984 childBlockFlow ? childBlockFlow->paginationStrutPropagatedFromChild() |
939 : LayoutUnit(); | 985 : LayoutUnit(); |
940 LayoutUnit logicalTopWithContentStrut = logicalTop + strutFromContent; | 986 LayoutUnit logicalTopWithContentStrut = logicalTop + strutFromContent; |
941 | 987 |
942 // For replaced elements and scrolled elements, we want to shift them to the n
ext page if they don't fit on the current one. | 988 // For replaced elements and scrolled elements, we want to shift them to the |
| 989 // next page if they don't fit on the current one. |
943 LayoutUnit logicalTopAfterUnsplittable = | 990 LayoutUnit logicalTopAfterUnsplittable = |
944 adjustForUnsplittableChild(child, logicalTop); | 991 adjustForUnsplittableChild(child, logicalTop); |
945 | 992 |
946 // Pick the largest offset. Tall unsplittable content may take us to a page or
column further | 993 // Pick the largest offset. Tall unsplittable content may take us to a page or |
947 // ahead than the next one. | 994 // column further ahead than the next one. |
948 LayoutUnit logicalTopAfterPagination = | 995 LayoutUnit logicalTopAfterPagination = |
949 std::max(logicalTopWithContentStrut, logicalTopAfterUnsplittable); | 996 std::max(logicalTopWithContentStrut, logicalTopAfterUnsplittable); |
950 LayoutUnit newLogicalTop = logicalTop; | 997 LayoutUnit newLogicalTop = logicalTop; |
951 | 998 |
952 // Forced breaks may already have caused a strut, and this needs to be added t
ogether with | 999 // Forced breaks may already have caused a strut, and this needs to be added |
953 // any strut detected here in this method. | 1000 // together with any strut detected here in this method. |
954 LayoutUnit previousStrut = child.paginationStrut(); | 1001 LayoutUnit previousStrut = child.paginationStrut(); |
955 | 1002 |
956 if (LayoutUnit paginationStrut = | 1003 if (LayoutUnit paginationStrut = |
957 logicalTopAfterPagination - logicalTop + previousStrut) { | 1004 logicalTopAfterPagination - logicalTop + previousStrut) { |
958 ASSERT(paginationStrut > 0); | 1005 ASSERT(paginationStrut > 0); |
959 // If we're not at the first in-flow child, there's a class A break point be
fore the child. If we *are* at the | 1006 // If we're not at the first in-flow child, there's a class A break point |
960 // first in-flow child, but the child isn't flush with the content edge of i
ts container, due to e.g. clearance, | 1007 // before the child. If we *are* at the first in-flow child, but the child |
961 // there's a class C break point before the child. Otherwise we should propa
gate the strut to our parent block, | 1008 // isn't flush with the content edge of its container, due to e.g. |
962 // and attempt to break there instead. See https://drafts.csswg.org/css-brea
k/#possible-breaks | 1009 // clearance, there's a class C break point before the child. Otherwise we |
| 1010 // should propagate the strut to our parent block, and attempt to break |
| 1011 // there instead. See https://drafts.csswg.org/css-break/#possible-breaks |
963 if (layoutInfo.isAtFirstInFlowChild() && atBeforeSideOfBlock && | 1012 if (layoutInfo.isAtFirstInFlowChild() && atBeforeSideOfBlock && |
964 allowsPaginationStrut()) { | 1013 allowsPaginationStrut()) { |
965 // FIXME: Should really check if we're exceeding the page height before pr
opagating the strut, but we don't | 1014 // FIXME: Should really check if we're exceeding the page height before |
966 // have all the information to do so (the strut only has the remaining amo
unt to push). Gecko gets this wrong too | 1015 // propagating the strut, but we don't have all the information to do so |
967 // and pushes to the next page anyway, so not too concerned about it. | 1016 // (the strut only has the remaining amount to push). Gecko gets this |
| 1017 // wrong too and pushes to the next page anyway, so not too concerned |
| 1018 // about it. |
968 paginationStrut += logicalTop + marginBeforeIfFloating(); | 1019 paginationStrut += logicalTop + marginBeforeIfFloating(); |
969 setPaginationStrutPropagatedFromChild(paginationStrut); | 1020 setPaginationStrutPropagatedFromChild(paginationStrut); |
970 child.resetPaginationStrut(); | 1021 child.resetPaginationStrut(); |
971 if (childBlockFlow) | 1022 if (childBlockFlow) |
972 childBlockFlow->setPaginationStrutPropagatedFromChild(LayoutUnit()); | 1023 childBlockFlow->setPaginationStrutPropagatedFromChild(LayoutUnit()); |
973 } else { | 1024 } else { |
974 child.setPaginationStrut(paginationStrut); | 1025 child.setPaginationStrut(paginationStrut); |
975 // |previousStrut| was already baked into the logical top, so don't add it
again. | 1026 // |previousStrut| was already baked into the logical top, so don't add it |
| 1027 // again. |
976 newLogicalTop += paginationStrut - previousStrut; | 1028 newLogicalTop += paginationStrut - previousStrut; |
977 } | 1029 } |
978 } | 1030 } |
979 | 1031 |
980 // Similar to how we apply clearance. Go ahead and boost height() to be the pl
ace where we're going to position the child. | 1032 // Similar to how we apply clearance. Go ahead and boost height() to be the |
| 1033 // place where we're going to position the child. |
981 setLogicalHeight(logicalHeight() + (newLogicalTop - logicalTop)); | 1034 setLogicalHeight(logicalHeight() + (newLogicalTop - logicalTop)); |
982 | 1035 |
983 // Return the final adjusted logical top. | 1036 // Return the final adjusted logical top. |
984 return newLogicalTop; | 1037 return newLogicalTop; |
985 } | 1038 } |
986 | 1039 |
987 static bool shouldSetStrutOnBlock(const LayoutBlockFlow& block, | 1040 static bool shouldSetStrutOnBlock(const LayoutBlockFlow& block, |
988 const RootInlineBox& lineBox, | 1041 const RootInlineBox& lineBox, |
989 LayoutUnit lineLogicalOffset, | 1042 LayoutUnit lineLogicalOffset, |
990 int lineIndex, | 1043 int lineIndex, |
991 LayoutUnit pageLogicalHeight) { | 1044 LayoutUnit pageLogicalHeight) { |
992 if (lineBox == block.firstRootBox()) { | 1045 if (lineBox == block.firstRootBox()) { |
993 // This is the first line in the block. We can take the whole block with us
to the next page | 1046 // This is the first line in the block. We can take the whole block with us |
994 // or column, rather than keeping a content-less portion of it in the previo
us one. Only do | 1047 // to the next page or column, rather than keeping a content-less portion of |
995 // this if the line is flush with the content edge of the block, though. If
it isn't, it | 1048 // it in the previous one. Only do this if the line is flush with the |
996 // means that the line was pushed downwards by preceding floats that didn't
fit beside the | 1049 // content edge of the block, though. If it isn't, it means that the line |
997 // line, and we don't want to move all that, since it has already been estab
lished that it | 1050 // was pushed downwards by preceding floats that didn't fit beside the line, |
998 // fits nicely where it is. In this case we have a class "C" break point [1]
in front of | 1051 // and we don't want to move all that, since it has already been established |
999 // this line. | 1052 // that it fits nicely where it is. In this case we have a class "C" break |
| 1053 // point [1] in front of this line. |
1000 // | 1054 // |
1001 // [1] https://drafts.csswg.org/css-break/#possible-breaks | 1055 // [1] https://drafts.csswg.org/css-break/#possible-breaks |
1002 if (lineLogicalOffset > block.borderAndPaddingBefore()) | 1056 if (lineLogicalOffset > block.borderAndPaddingBefore()) |
1003 return false; | 1057 return false; |
1004 | 1058 |
1005 LayoutUnit lineHeight = | 1059 LayoutUnit lineHeight = |
1006 lineBox.lineBottomWithLeading() - lineBox.lineTopWithLeading(); | 1060 lineBox.lineBottomWithLeading() - lineBox.lineTopWithLeading(); |
1007 LayoutUnit totalLogicalHeight = | 1061 LayoutUnit totalLogicalHeight = |
1008 lineHeight + lineLogicalOffset.clampNegativeToZero(); | 1062 lineHeight + lineLogicalOffset.clampNegativeToZero(); |
1009 // It's rather pointless to break before the block if the current line isn't
going to | 1063 // It's rather pointless to break before the block if the current line isn't |
1010 // fit in the same column or page, so check that as well. | 1064 // going to fit in the same column or page, so check that as well. |
1011 if (totalLogicalHeight > pageLogicalHeight) | 1065 if (totalLogicalHeight > pageLogicalHeight) |
1012 return false; | 1066 return false; |
1013 } else { | 1067 } else { |
1014 if (lineIndex > block.style()->orphans()) | 1068 if (lineIndex > block.style()->orphans()) |
1015 return false; | 1069 return false; |
1016 | 1070 |
1017 // Not enough orphans here. Push the entire block to the next column / page
as an attempt to | 1071 // Not enough orphans here. Push the entire block to the next column / page |
1018 // better satisfy the orphans requirement. | 1072 // as an attempt to better satisfy the orphans requirement. |
1019 // | 1073 // |
1020 // Note that we should ideally check if the first line in the block is flush
with the | 1074 // Note that we should ideally check if the first line in the block is flush |
1021 // content edge of the block here, because if it isn't, we should break at t
he class "C" | 1075 // with the content edge of the block here, because if it isn't, we should |
1022 // break point in front of the first line, rather than before the entire blo
ck. | 1076 // break at the class "C" break point in front of the first line, rather |
| 1077 // than before the entire block. |
1023 } | 1078 } |
1024 return block.allowsPaginationStrut(); | 1079 return block.allowsPaginationStrut(); |
1025 } | 1080 } |
1026 | 1081 |
1027 void LayoutBlockFlow::adjustLinePositionForPagination(RootInlineBox& lineBox, | 1082 void LayoutBlockFlow::adjustLinePositionForPagination(RootInlineBox& lineBox, |
1028 LayoutUnit& delta) { | 1083 LayoutUnit& delta) { |
1029 // TODO(mstensho): Pay attention to line overflow. It should be painted in the
same column as | 1084 // TODO(mstensho): Pay attention to line overflow. It should be painted in the |
1030 // the rest of the line, possibly overflowing the column. We currently only al
low overflow above | 1085 // same column as the rest of the line, possibly overflowing the column. We |
1031 // the first column. We clip at all other column boundaries, and that's how it
has to be for | 1086 // currently only allow overflow above the first column. We clip at all other |
1032 // now. The paint we have to do when a column has overflow has to be special.
We need to exclude | 1087 // column boundaries, and that's how it has to be for now. The paint we have |
1033 // content that paints in a previous column (and content that paints in the fo
llowing column). | 1088 // to do when a column has overflow has to be special. |
| 1089 // We need to exclude content that paints in a previous column (and content |
| 1090 // that paints in the following column). |
1034 // | 1091 // |
1035 // FIXME: Another problem with simply moving lines is that the available line
width may change (because of floats). | 1092 // FIXME: Another problem with simply moving lines is that the available line |
1036 // Technically if the location we move the line to has a different line width
than our old position, then we need to dirty the | 1093 // width may change (because of floats). Technically if the location we move |
1037 // line and all following lines. | 1094 // the line to has a different line width than our old position, then we need |
| 1095 // to dirty the line and all following lines. |
1038 LayoutUnit logicalOffset = lineBox.lineTopWithLeading(); | 1096 LayoutUnit logicalOffset = lineBox.lineTopWithLeading(); |
1039 LayoutUnit lineHeight = lineBox.lineBottomWithLeading() - logicalOffset; | 1097 LayoutUnit lineHeight = lineBox.lineBottomWithLeading() - logicalOffset; |
1040 logicalOffset += delta; | 1098 logicalOffset += delta; |
1041 lineBox.setPaginationStrut(LayoutUnit()); | 1099 lineBox.setPaginationStrut(LayoutUnit()); |
1042 lineBox.setIsFirstAfterPageBreak(false); | 1100 lineBox.setIsFirstAfterPageBreak(false); |
1043 LayoutUnit pageLogicalHeight = pageLogicalHeightForOffset(logicalOffset); | 1101 LayoutUnit pageLogicalHeight = pageLogicalHeightForOffset(logicalOffset); |
1044 if (!pageLogicalHeight) | 1102 if (!pageLogicalHeight) |
1045 return; | 1103 return; |
1046 LayoutUnit remainingLogicalHeight = pageRemainingLogicalHeightForOffset( | 1104 LayoutUnit remainingLogicalHeight = pageRemainingLogicalHeightForOffset( |
1047 logicalOffset, AssociateWithLatterPage); | 1105 logicalOffset, AssociateWithLatterPage); |
1048 int lineIndex = lineCount(&lineBox); | 1106 int lineIndex = lineCount(&lineBox); |
1049 if (remainingLogicalHeight < lineHeight || | 1107 if (remainingLogicalHeight < lineHeight || |
1050 (shouldBreakAtLineToAvoidWidow() && | 1108 (shouldBreakAtLineToAvoidWidow() && |
1051 lineBreakToAvoidWidow() == lineIndex)) { | 1109 lineBreakToAvoidWidow() == lineIndex)) { |
1052 LayoutUnit paginationStrut = calculatePaginationStrutToFitContent( | 1110 LayoutUnit paginationStrut = calculatePaginationStrutToFitContent( |
1053 logicalOffset, remainingLogicalHeight, lineHeight); | 1111 logicalOffset, remainingLogicalHeight, lineHeight); |
1054 LayoutUnit newLogicalOffset = logicalOffset + paginationStrut; | 1112 LayoutUnit newLogicalOffset = logicalOffset + paginationStrut; |
1055 // Moving to a different page or column may mean that its height is differen
t. | 1113 // Moving to a different page or column may mean that its height is |
| 1114 // different. |
1056 pageLogicalHeight = pageLogicalHeightForOffset(newLogicalOffset); | 1115 pageLogicalHeight = pageLogicalHeightForOffset(newLogicalOffset); |
1057 if (lineHeight > pageLogicalHeight) { | 1116 if (lineHeight > pageLogicalHeight) { |
1058 // Too tall to fit in one page / column. Give up. Don't push to the next p
age / column. | 1117 // Too tall to fit in one page / column. Give up. Don't push to the next |
1059 // TODO(mstensho): Get rid of this. This is just utter weirdness, but the
other browsers | 1118 // page / column. |
1060 // also do something slightly similar, although in much more specific case
s than we do here, | 1119 // TODO(mstensho): Get rid of this. This is just utter weirdness, but the |
1061 // and printing Google Docs depends on it. | 1120 // other browsers also do something slightly similar, although in much |
| 1121 // more specific cases than we do here, and printing Google Docs depends |
| 1122 // on it. |
1062 paginatedContentWasLaidOut(logicalOffset + lineHeight); | 1123 paginatedContentWasLaidOut(logicalOffset + lineHeight); |
1063 return; | 1124 return; |
1064 } | 1125 } |
1065 | 1126 |
1066 // We need to insert a break now, either because there's no room for the lin
e in the | 1127 // We need to insert a break now, either because there's no room for the |
1067 // current column / page, or because we have determined that we need a break
to satisfy | 1128 // line in the current column / page, or because we have determined that we |
1068 // widow requirements. | 1129 // need a break to satisfy widow requirements. |
1069 if (shouldBreakAtLineToAvoidWidow() && | 1130 if (shouldBreakAtLineToAvoidWidow() && |
1070 lineBreakToAvoidWidow() == lineIndex) { | 1131 lineBreakToAvoidWidow() == lineIndex) { |
1071 clearShouldBreakAtLineToAvoidWidow(); | 1132 clearShouldBreakAtLineToAvoidWidow(); |
1072 setDidBreakAtLineToAvoidWidow(); | 1133 setDidBreakAtLineToAvoidWidow(); |
1073 } | 1134 } |
1074 if (shouldSetStrutOnBlock(*this, lineBox, logicalOffset, lineIndex, | 1135 if (shouldSetStrutOnBlock(*this, lineBox, logicalOffset, lineIndex, |
1075 pageLogicalHeight)) { | 1136 pageLogicalHeight)) { |
1076 // Note that when setting the strut on a block, it may be propagated to pa
rent blocks | 1137 // Note that when setting the strut on a block, it may be propagated to |
1077 // later on, if a block's logical top is flush with that of its parent. We
don't want | 1138 // parent blocks later on, if a block's logical top is flush with that of |
1078 // content-less portions (struts) at the beginning of a block before a bre
ak, if it can | 1139 // its parent. We don't want content-less portions (struts) at the |
1079 // be avoided. After all, that's the reason for setting struts on blocks a
nd not lines | 1140 // beginning of a block before a break, if it can be avoided. After all, |
1080 // in the first place. | 1141 // that's the reason for setting struts on blocks and not lines in the |
| 1142 // first place. |
1081 LayoutUnit strut = | 1143 LayoutUnit strut = |
1082 paginationStrut + logicalOffset + marginBeforeIfFloating(); | 1144 paginationStrut + logicalOffset + marginBeforeIfFloating(); |
1083 setPaginationStrutPropagatedFromChild(strut); | 1145 setPaginationStrutPropagatedFromChild(strut); |
1084 } else { | 1146 } else { |
1085 delta += paginationStrut; | 1147 delta += paginationStrut; |
1086 lineBox.setPaginationStrut(paginationStrut); | 1148 lineBox.setPaginationStrut(paginationStrut); |
1087 lineBox.setIsFirstAfterPageBreak(true); | 1149 lineBox.setIsFirstAfterPageBreak(true); |
1088 } | 1150 } |
1089 paginatedContentWasLaidOut(newLogicalOffset + lineHeight); | 1151 paginatedContentWasLaidOut(newLogicalOffset + lineHeight); |
1090 return; | 1152 return; |
1091 } | 1153 } |
1092 | 1154 |
1093 LayoutUnit strutToPropagate; | 1155 LayoutUnit strutToPropagate; |
1094 if (remainingLogicalHeight == pageLogicalHeight) { | 1156 if (remainingLogicalHeight == pageLogicalHeight) { |
1095 // We're at the very top of a page or column. | 1157 // We're at the very top of a page or column. |
1096 if (lineBox != firstRootBox()) | 1158 if (lineBox != firstRootBox()) |
1097 lineBox.setIsFirstAfterPageBreak(true); | 1159 lineBox.setIsFirstAfterPageBreak(true); |
1098 // If this is the first line in the block, and the block has a top border, p
adding, or (in | 1160 // If this is the first line in the block, and the block has a top border, |
1099 // case it's a float) margin, we may want to set a strut on the block, so th
at everything | 1161 // padding, or (in case it's a float) margin, we may want to set a strut on |
1100 // ends up in the next column or page. Setting a strut on the block is also
important when | 1162 // the block, so that everything ends up in the next column or page. Setting |
1101 // it comes to satisfying orphan requirements. | 1163 // a strut on the block is also important when it comes to satisfying orphan |
| 1164 // requirements. |
1102 if (shouldSetStrutOnBlock(*this, lineBox, logicalOffset, lineIndex, | 1165 if (shouldSetStrutOnBlock(*this, lineBox, logicalOffset, lineIndex, |
1103 pageLogicalHeight)) | 1166 pageLogicalHeight)) |
1104 strutToPropagate = logicalOffset + marginBeforeIfFloating(); | 1167 strutToPropagate = logicalOffset + marginBeforeIfFloating(); |
1105 } else if (lineBox == firstRootBox() && allowsPaginationStrut()) { | 1168 } else if (lineBox == firstRootBox() && allowsPaginationStrut()) { |
1106 // This is the first line in the block. The block may still start in the pre
vious column or | 1169 // This is the first line in the block. The block may still start in the |
1107 // page, and if that's the case, attempt to pull it over to where this line
is, so that we | 1170 // previous column or page, and if that's the case, attempt to pull it over |
1108 // don't split the top border, padding, or (in case it's a float) margin. | 1171 // to where this line is, so that we don't split the top border, padding, or |
| 1172 // (in case it's a float) margin. |
1109 LayoutUnit totalLogicalOffset = logicalOffset + marginBeforeIfFloating(); | 1173 LayoutUnit totalLogicalOffset = logicalOffset + marginBeforeIfFloating(); |
1110 LayoutUnit strut = | 1174 LayoutUnit strut = |
1111 remainingLogicalHeight + totalLogicalOffset - pageLogicalHeight; | 1175 remainingLogicalHeight + totalLogicalOffset - pageLogicalHeight; |
1112 if (strut > 0) { | 1176 if (strut > 0) { |
1113 // The block starts in a previous column or page. Set a strut on the block
if there's | 1177 // The block starts in a previous column or page. Set a strut on the block |
1114 // room for the top border, padding and (if it's a float) margin and the l
ine in one | 1178 // if there's room for the top border, padding and (if it's a float) |
1115 // column or page. | 1179 // margin and the line in one column or page. |
1116 if (totalLogicalOffset + lineHeight <= pageLogicalHeight) | 1180 if (totalLogicalOffset + lineHeight <= pageLogicalHeight) |
1117 strutToPropagate = strut; | 1181 strutToPropagate = strut; |
1118 } | 1182 } |
1119 } | 1183 } |
1120 | 1184 |
1121 // If we found that some preceding content (lines, border and padding) belongs
together with | 1185 // If we found that some preceding content (lines, border and padding) belongs |
1122 // this line, we should pull the entire block with us to the fragmentainer we'
re currently | 1186 // together with this line, we should pull the entire block with us to the |
1123 // in. We need to avoid this when the block precedes the first fragmentainer,
though. We | 1187 // fragmentainer we're currently in. We need to avoid this when the block |
1124 // shouldn't fragment content there, but rather let it appear in the overflow
area before the | 1188 // precedes the first fragmentainer, though. We shouldn't fragment content |
1125 // first fragmentainer. | 1189 // there, but rather let it appear in the overflow area before the first |
| 1190 // fragmentainer. |
1126 if (strutToPropagate && offsetFromLogicalTopOfFirstPage() > LayoutUnit()) | 1191 if (strutToPropagate && offsetFromLogicalTopOfFirstPage() > LayoutUnit()) |
1127 setPaginationStrutPropagatedFromChild(strutToPropagate); | 1192 setPaginationStrutPropagatedFromChild(strutToPropagate); |
1128 | 1193 |
1129 paginatedContentWasLaidOut(logicalOffset + lineHeight); | 1194 paginatedContentWasLaidOut(logicalOffset + lineHeight); |
1130 } | 1195 } |
1131 | 1196 |
1132 LayoutUnit LayoutBlockFlow::adjustForUnsplittableChild( | 1197 LayoutUnit LayoutBlockFlow::adjustForUnsplittableChild( |
1133 LayoutBox& child, | 1198 LayoutBox& child, |
1134 LayoutUnit logicalOffset) const { | 1199 LayoutUnit logicalOffset) const { |
1135 if (child.getPaginationBreakability() == AllowAnyBreaks) | 1200 if (child.getPaginationBreakability() == AllowAnyBreaks) |
1136 return logicalOffset; | 1201 return logicalOffset; |
1137 LayoutUnit childLogicalHeight = logicalHeightForChild(child); | 1202 LayoutUnit childLogicalHeight = logicalHeightForChild(child); |
1138 // Floats' margins do not collapse with page or column boundaries. | 1203 // Floats' margins do not collapse with page or column boundaries. |
1139 if (child.isFloating()) | 1204 if (child.isFloating()) |
1140 childLogicalHeight += | 1205 childLogicalHeight += |
1141 marginBeforeForChild(child) + marginAfterForChild(child); | 1206 marginBeforeForChild(child) + marginAfterForChild(child); |
1142 LayoutUnit pageLogicalHeight = pageLogicalHeightForOffset(logicalOffset); | 1207 LayoutUnit pageLogicalHeight = pageLogicalHeightForOffset(logicalOffset); |
1143 if (!pageLogicalHeight) | 1208 if (!pageLogicalHeight) |
1144 return logicalOffset; | 1209 return logicalOffset; |
1145 LayoutUnit remainingLogicalHeight = pageRemainingLogicalHeightForOffset( | 1210 LayoutUnit remainingLogicalHeight = pageRemainingLogicalHeightForOffset( |
1146 logicalOffset, AssociateWithLatterPage); | 1211 logicalOffset, AssociateWithLatterPage); |
1147 if (remainingLogicalHeight >= childLogicalHeight) | 1212 if (remainingLogicalHeight >= childLogicalHeight) |
1148 return logicalOffset; // It fits fine where it is. No need to break. | 1213 return logicalOffset; // It fits fine where it is. No need to break. |
1149 LayoutUnit paginationStrut = calculatePaginationStrutToFitContent( | 1214 LayoutUnit paginationStrut = calculatePaginationStrutToFitContent( |
1150 logicalOffset, remainingLogicalHeight, childLogicalHeight); | 1215 logicalOffset, remainingLogicalHeight, childLogicalHeight); |
1151 if (paginationStrut == remainingLogicalHeight && | 1216 if (paginationStrut == remainingLogicalHeight && |
1152 remainingLogicalHeight == pageLogicalHeight) { | 1217 remainingLogicalHeight == pageLogicalHeight) { |
1153 // Don't break if we were at the top of a page, and we failed to fit the con
tent | 1218 // Don't break if we were at the top of a page, and we failed to fit the |
1154 // completely. No point in leaving a page completely blank. | 1219 // content completely. No point in leaving a page completely blank. |
1155 return logicalOffset; | 1220 return logicalOffset; |
1156 } | 1221 } |
1157 return logicalOffset + paginationStrut; | 1222 return logicalOffset + paginationStrut; |
1158 } | 1223 } |
1159 | 1224 |
1160 DISABLE_CFI_PERF | 1225 DISABLE_CFI_PERF |
1161 void LayoutBlockFlow::rebuildFloatsFromIntruding() { | 1226 void LayoutBlockFlow::rebuildFloatsFromIntruding() { |
1162 if (m_floatingObjects) | 1227 if (m_floatingObjects) |
1163 m_floatingObjects->setHorizontalWritingMode(isHorizontalWritingMode()); | 1228 m_floatingObjects->setHorizontalWritingMode(isHorizontalWritingMode()); |
1164 | 1229 |
1165 HashSet<LayoutBox*> oldIntrudingFloatSet; | 1230 HashSet<LayoutBox*> oldIntrudingFloatSet; |
1166 if (!childrenInline() && m_floatingObjects) { | 1231 if (!childrenInline() && m_floatingObjects) { |
1167 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); | 1232 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); |
1168 FloatingObjectSetIterator end = floatingObjectSet.end(); | 1233 FloatingObjectSetIterator end = floatingObjectSet.end(); |
1169 for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; | 1234 for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; |
1170 ++it) { | 1235 ++it) { |
1171 const FloatingObject& floatingObject = *it->get(); | 1236 const FloatingObject& floatingObject = *it->get(); |
1172 if (!floatingObject.isDescendant()) | 1237 if (!floatingObject.isDescendant()) |
1173 oldIntrudingFloatSet.add(floatingObject.layoutObject()); | 1238 oldIntrudingFloatSet.add(floatingObject.layoutObject()); |
1174 } | 1239 } |
1175 } | 1240 } |
1176 | 1241 |
1177 // Inline blocks are covered by the isAtomicInlineLevel() check in the avoidFl
oats method. | 1242 // Inline blocks are covered by the isAtomicInlineLevel() check in the |
| 1243 // avoidFloats method. |
1178 if (avoidsFloats() || isDocumentElement() || isLayoutView() || | 1244 if (avoidsFloats() || isDocumentElement() || isLayoutView() || |
1179 isFloatingOrOutOfFlowPositioned() || isTableCell()) { | 1245 isFloatingOrOutOfFlowPositioned() || isTableCell()) { |
1180 if (m_floatingObjects) { | 1246 if (m_floatingObjects) { |
1181 m_floatingObjects->clear(); | 1247 m_floatingObjects->clear(); |
1182 } | 1248 } |
1183 if (!oldIntrudingFloatSet.isEmpty()) | 1249 if (!oldIntrudingFloatSet.isEmpty()) |
1184 markAllDescendantsWithFloatsForLayout(); | 1250 markAllDescendantsWithFloatsForLayout(); |
1185 return; | 1251 return; |
1186 } | 1252 } |
1187 | 1253 |
1188 LayoutBoxToFloatInfoMap floatMap; | 1254 LayoutBoxToFloatInfoMap floatMap; |
1189 | 1255 |
1190 if (m_floatingObjects) { | 1256 if (m_floatingObjects) { |
1191 if (childrenInline()) | 1257 if (childrenInline()) |
1192 m_floatingObjects->moveAllToFloatInfoMap(floatMap); | 1258 m_floatingObjects->moveAllToFloatInfoMap(floatMap); |
1193 else | 1259 else |
1194 m_floatingObjects->clear(); | 1260 m_floatingObjects->clear(); |
1195 } | 1261 } |
1196 | 1262 |
1197 // We should not process floats if the parent node is not a LayoutBlockFlow. O
therwise, we will add | 1263 // We should not process floats if the parent node is not a LayoutBlockFlow. |
1198 // floats in an invalid context. This will cause a crash arising from a bad ca
st on the parent. | 1264 // Otherwise, we will add floats in an invalid context. This will cause a |
1199 // See <rdar://problem/8049753>, where float property is applied on a text nod
e in a SVG. | 1265 // crash arising from a bad cast on the parent. |
| 1266 // See <rdar://problem/8049753>, where float property is applied on a text |
| 1267 // node in a SVG. |
1200 if (!parent() || !parent()->isLayoutBlockFlow()) | 1268 if (!parent() || !parent()->isLayoutBlockFlow()) |
1201 return; | 1269 return; |
1202 | 1270 |
1203 // Attempt to locate a previous sibling with overhanging floats. We skip any e
lements that | 1271 // Attempt to locate a previous sibling with overhanging floats. We skip any |
1204 // may have shifted to avoid floats, and any objects whose floats cannot inter
act with objects | 1272 // elements that may have shifted to avoid floats, and any objects whose |
1205 // outside it (i.e. objects that create a new block formatting context). | 1273 // floats cannot interact with objects outside it (i.e. objects that create a |
| 1274 // new block formatting context). |
1206 LayoutBlockFlow* parentBlockFlow = toLayoutBlockFlow(parent()); | 1275 LayoutBlockFlow* parentBlockFlow = toLayoutBlockFlow(parent()); |
1207 bool siblingFloatMayIntrude = false; | 1276 bool siblingFloatMayIntrude = false; |
1208 LayoutObject* prev = previousSibling(); | 1277 LayoutObject* prev = previousSibling(); |
1209 while (prev && (!prev->isBox() || !prev->isLayoutBlock() || | 1278 while (prev && (!prev->isBox() || !prev->isLayoutBlock() || |
1210 toLayoutBlock(prev)->avoidsFloats() || | 1279 toLayoutBlock(prev)->avoidsFloats() || |
1211 toLayoutBlock(prev)->createsNewFormattingContext())) { | 1280 toLayoutBlock(prev)->createsNewFormattingContext())) { |
1212 if (prev->isFloating()) | 1281 if (prev->isFloating()) |
1213 siblingFloatMayIntrude = true; | 1282 siblingFloatMayIntrude = true; |
1214 prev = prev->previousSibling(); | 1283 prev = prev->previousSibling(); |
1215 } | 1284 } |
1216 | 1285 |
1217 // First add in floats from the parent. Self-collapsing blocks let their paren
t track any floats that intrude into | 1286 // First add in floats from the parent. Self-collapsing blocks let their |
1218 // them (as opposed to floats they contain themselves) so check for those here
too. If margin collapsing has moved | 1287 // parent track any floats that intrude into them (as opposed to floats they |
1219 // us up past the top a previous sibling then we need to check for floats from
the parent too. | 1288 // contain themselves) so check for those here too. If margin collapsing has |
| 1289 // moved us up past the top a previous sibling then we need to check for |
| 1290 // floats from the parent too. |
1220 bool parentFloatsMayIntrude = | 1291 bool parentFloatsMayIntrude = |
1221 !siblingFloatMayIntrude && | 1292 !siblingFloatMayIntrude && |
1222 (!prev || toLayoutBlockFlow(prev)->isSelfCollapsingBlock() || | 1293 (!prev || toLayoutBlockFlow(prev)->isSelfCollapsingBlock() || |
1223 toLayoutBlock(prev)->logicalTop() > logicalTop()) && | 1294 toLayoutBlock(prev)->logicalTop() > logicalTop()) && |
1224 parentBlockFlow->lowestFloatLogicalBottom() > logicalTop(); | 1295 parentBlockFlow->lowestFloatLogicalBottom() > logicalTop(); |
1225 if (siblingFloatMayIntrude || parentFloatsMayIntrude) | 1296 if (siblingFloatMayIntrude || parentFloatsMayIntrude) |
1226 addIntrudingFloats(parentBlockFlow, | 1297 addIntrudingFloats(parentBlockFlow, |
1227 parentBlockFlow->logicalLeftOffsetForContent(), | 1298 parentBlockFlow->logicalLeftOffsetForContent(), |
1228 logicalTop()); | 1299 logicalTop()); |
1229 | 1300 |
1230 // Add overhanging floats from the previous LayoutBlockFlow, but only if it ha
s a float that intrudes into our space. | 1301 // Add overhanging floats from the previous LayoutBlockFlow, but only if it |
| 1302 // has a float that intrudes into our space. |
1231 if (prev) { | 1303 if (prev) { |
1232 LayoutBlockFlow* previousBlockFlow = toLayoutBlockFlow(prev); | 1304 LayoutBlockFlow* previousBlockFlow = toLayoutBlockFlow(prev); |
1233 if (logicalTop() < previousBlockFlow->logicalTop() + | 1305 if (logicalTop() < previousBlockFlow->logicalTop() + |
1234 previousBlockFlow->lowestFloatLogicalBottom()) | 1306 previousBlockFlow->lowestFloatLogicalBottom()) |
1235 addIntrudingFloats(previousBlockFlow, LayoutUnit(), | 1307 addIntrudingFloats(previousBlockFlow, LayoutUnit(), |
1236 logicalTop() - previousBlockFlow->logicalTop()); | 1308 logicalTop() - previousBlockFlow->logicalTop()); |
1237 } | 1309 } |
1238 | 1310 |
1239 if (childrenInline()) { | 1311 if (childrenInline()) { |
1240 LayoutUnit changeLogicalTop = LayoutUnit::max(); | 1312 LayoutUnit changeLogicalTop = LayoutUnit::max(); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1297 std::unique_ptr<FloatingObject>& floatingObject = it->value; | 1369 std::unique_ptr<FloatingObject>& floatingObject = it->value; |
1298 if (!floatingObject->isDescendant()) { | 1370 if (!floatingObject->isDescendant()) { |
1299 changeLogicalTop = LayoutUnit(); | 1371 changeLogicalTop = LayoutUnit(); |
1300 changeLogicalBottom = std::max(changeLogicalBottom, | 1372 changeLogicalBottom = std::max(changeLogicalBottom, |
1301 logicalBottomForFloat(*floatingObject)); | 1373 logicalBottomForFloat(*floatingObject)); |
1302 } | 1374 } |
1303 } | 1375 } |
1304 | 1376 |
1305 markLinesDirtyInBlockRange(changeLogicalTop, changeLogicalBottom); | 1377 markLinesDirtyInBlockRange(changeLogicalTop, changeLogicalBottom); |
1306 } else if (!oldIntrudingFloatSet.isEmpty()) { | 1378 } else if (!oldIntrudingFloatSet.isEmpty()) { |
1307 // If there are previously intruding floats that no longer intrude, then chi
ldren with floats | 1379 // If there are previously intruding floats that no longer intrude, then |
1308 // should also get layout because they might need their floating object list
s cleared. | 1380 // children with floats should also get layout because they might need their |
| 1381 // floating object lists cleared. |
1309 if (m_floatingObjects->set().size() < oldIntrudingFloatSet.size()) { | 1382 if (m_floatingObjects->set().size() < oldIntrudingFloatSet.size()) { |
1310 markAllDescendantsWithFloatsForLayout(); | 1383 markAllDescendantsWithFloatsForLayout(); |
1311 } else { | 1384 } else { |
1312 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); | 1385 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); |
1313 FloatingObjectSetIterator end = floatingObjectSet.end(); | 1386 FloatingObjectSetIterator end = floatingObjectSet.end(); |
1314 for (FloatingObjectSetIterator it = floatingObjectSet.begin(); | 1387 for (FloatingObjectSetIterator it = floatingObjectSet.begin(); |
1315 it != end && !oldIntrudingFloatSet.isEmpty(); ++it) | 1388 it != end && !oldIntrudingFloatSet.isEmpty(); ++it) |
1316 oldIntrudingFloatSet.remove((*it)->layoutObject()); | 1389 oldIntrudingFloatSet.remove((*it)->layoutObject()); |
1317 if (!oldIntrudingFloatSet.isEmpty()) | 1390 if (!oldIntrudingFloatSet.isEmpty()) |
1318 markAllDescendantsWithFloatsForLayout(); | 1391 markAllDescendantsWithFloatsForLayout(); |
(...skipping 23 matching lines...) Expand all Loading... |
1342 | 1415 |
1343 while (next) { | 1416 while (next) { |
1344 LayoutBox* child = next; | 1417 LayoutBox* child = next; |
1345 LayoutObject* nextSibling = child->nextSibling(); | 1418 LayoutObject* nextSibling = child->nextSibling(); |
1346 CHECK(!nextSibling || nextSibling->isBox()); | 1419 CHECK(!nextSibling || nextSibling->isBox()); |
1347 next = toLayoutBox(nextSibling); | 1420 next = toLayoutBox(nextSibling); |
1348 | 1421 |
1349 child->setMayNeedPaintInvalidation(); | 1422 child->setMayNeedPaintInvalidation(); |
1350 | 1423 |
1351 if (childToExclude == child) | 1424 if (childToExclude == child) |
1352 continue; // Skip this child, since it will be positioned by the speciali
zed subclass (ruby runs). | 1425 continue; // Skip this child, since it will be positioned by the |
| 1426 // specialized subclass (ruby runs). |
1353 | 1427 |
1354 updateBlockChildDirtyBitsBeforeLayout(relayoutChildren, *child); | 1428 updateBlockChildDirtyBitsBeforeLayout(relayoutChildren, *child); |
1355 | 1429 |
1356 if (child->isOutOfFlowPositioned()) { | 1430 if (child->isOutOfFlowPositioned()) { |
1357 child->containingBlock()->insertPositionedObject(child); | 1431 child->containingBlock()->insertPositionedObject(child); |
1358 adjustPositionedBlock(*child, layoutInfo); | 1432 adjustPositionedBlock(*child, layoutInfo); |
1359 continue; | 1433 continue; |
1360 } | 1434 } |
1361 if (child->isFloating()) { | 1435 if (child->isFloating()) { |
1362 insertFloatingObject(*child); | 1436 insertFloatingObject(*child); |
1363 adjustFloatingBlock(marginInfo); | 1437 adjustFloatingBlock(marginInfo); |
1364 continue; | 1438 continue; |
1365 } | 1439 } |
1366 if (child->isColumnSpanAll()) { | 1440 if (child->isColumnSpanAll()) { |
1367 // This is not the containing block of the spanner. The spanner's placehol
der will lay | 1441 // This is not the containing block of the spanner. The spanner's |
1368 // it out in due course. For now we just need to consult our flow thread,
so that the | 1442 // placeholder will lay it out in due course. For now we just need to |
1369 // columns (if any) preceding and following the spanner are laid out corre
ctly. But | 1443 // consult our flow thread, so that the columns (if any) preceding and |
1370 // first we apply the pending margin, so that it's taken into consideratio
n and doesn't | 1444 // following the spanner are laid out correctly. But first we apply the |
1371 // end up on the other side of the spanner. | 1445 // pending margin, so that it's taken into consideration and doesn't end |
| 1446 // up on the other side of the spanner. |
1372 setLogicalHeight(logicalHeight() + marginInfo.margin()); | 1447 setLogicalHeight(logicalHeight() + marginInfo.margin()); |
1373 marginInfo.clearMargin(); | 1448 marginInfo.clearMargin(); |
1374 | 1449 |
1375 child->spannerPlaceholder()->flowThread()->skipColumnSpanner( | 1450 child->spannerPlaceholder()->flowThread()->skipColumnSpanner( |
1376 child, offsetFromLogicalTopOfFirstPage() + logicalHeight()); | 1451 child, offsetFromLogicalTopOfFirstPage() + logicalHeight()); |
1377 continue; | 1452 continue; |
1378 } | 1453 } |
1379 | 1454 |
1380 // Lay out the child. | 1455 // Lay out the child. |
1381 layoutBlockChild(*child, layoutInfo); | 1456 layoutBlockChild(*child, layoutInfo); |
1382 layoutInfo.clearIsAtFirstInFlowChild(); | 1457 layoutInfo.clearIsAtFirstInFlowChild(); |
1383 lastNormalFlowChild = child; | 1458 lastNormalFlowChild = child; |
1384 } | 1459 } |
1385 | 1460 |
1386 // Now do the handling of the bottom of the block, adding in our bottom border
/padding and | 1461 // Now do the handling of the bottom of the block, adding in our bottom |
1387 // determining the correct collapsed bottom margin information. | 1462 // border/padding and determining the correct collapsed bottom margin |
| 1463 // information. |
1388 handleAfterSideOfBlock(lastNormalFlowChild, beforeEdge, afterEdge, | 1464 handleAfterSideOfBlock(lastNormalFlowChild, beforeEdge, afterEdge, |
1389 marginInfo); | 1465 marginInfo); |
1390 } | 1466 } |
1391 | 1467 |
1392 // Our MarginInfo state used when laying out block children. | 1468 // Our MarginInfo state used when laying out block children. |
1393 MarginInfo::MarginInfo(LayoutBlockFlow* blockFlow, | 1469 MarginInfo::MarginInfo(LayoutBlockFlow* blockFlow, |
1394 LayoutUnit beforeBorderPadding, | 1470 LayoutUnit beforeBorderPadding, |
1395 LayoutUnit afterBorderPadding) | 1471 LayoutUnit afterBorderPadding) |
1396 : m_canCollapseMarginAfterWithLastChild(true), | 1472 : m_canCollapseMarginAfterWithLastChild(true), |
1397 m_atBeforeSideOfBlock(true), | 1473 m_atBeforeSideOfBlock(true), |
1398 m_atAfterSideOfBlock(false), | 1474 m_atAfterSideOfBlock(false), |
1399 m_hasMarginBeforeQuirk(false), | 1475 m_hasMarginBeforeQuirk(false), |
1400 m_hasMarginAfterQuirk(false), | 1476 m_hasMarginAfterQuirk(false), |
1401 m_determinedMarginBeforeQuirk(false), | 1477 m_determinedMarginBeforeQuirk(false), |
1402 m_discardMargin(false), | 1478 m_discardMargin(false), |
1403 m_lastChildIsSelfCollapsingBlockWithClearance(false) { | 1479 m_lastChildIsSelfCollapsingBlockWithClearance(false) { |
1404 const ComputedStyle& blockStyle = blockFlow->styleRef(); | 1480 const ComputedStyle& blockStyle = blockFlow->styleRef(); |
1405 ASSERT(blockFlow->isLayoutView() || blockFlow->parent()); | 1481 ASSERT(blockFlow->isLayoutView() || blockFlow->parent()); |
1406 m_canCollapseWithChildren = !blockFlow->createsNewFormattingContext() && | 1482 m_canCollapseWithChildren = !blockFlow->createsNewFormattingContext() && |
1407 !blockFlow->isLayoutFlowThread() && | 1483 !blockFlow->isLayoutFlowThread() && |
1408 !blockFlow->isLayoutView(); | 1484 !blockFlow->isLayoutView(); |
1409 | 1485 |
1410 m_canCollapseMarginBeforeWithChildren = | 1486 m_canCollapseMarginBeforeWithChildren = |
1411 m_canCollapseWithChildren && !beforeBorderPadding && | 1487 m_canCollapseWithChildren && !beforeBorderPadding && |
1412 blockStyle.marginBeforeCollapse() != MarginCollapseSeparate; | 1488 blockStyle.marginBeforeCollapse() != MarginCollapseSeparate; |
1413 | 1489 |
1414 // If any height other than auto is specified in CSS, then we don't collapse o
ur bottom | 1490 // If any height other than auto is specified in CSS, then we don't collapse |
1415 // margins with our children's margins. To do otherwise would be to risk odd v
isual | 1491 // our bottom margins with our children's margins. To do otherwise would be to |
1416 // effects when the children overflow out of the parent block and yet still co
llapse | 1492 // risk odd visual effects when the children overflow out of the parent block |
1417 // with it. We also don't collapse if we have any bottom border/padding. | 1493 // and yet still collapse with it. We also don't collapse if we have any |
| 1494 // bottom border/padding. |
1418 m_canCollapseMarginAfterWithChildren = | 1495 m_canCollapseMarginAfterWithChildren = |
1419 m_canCollapseWithChildren && !afterBorderPadding && | 1496 m_canCollapseWithChildren && !afterBorderPadding && |
1420 (blockStyle.logicalHeight().isAuto() && | 1497 (blockStyle.logicalHeight().isAuto() && |
1421 !blockStyle.logicalHeight().value()) && | 1498 !blockStyle.logicalHeight().value()) && |
1422 blockStyle.marginAfterCollapse() != MarginCollapseSeparate; | 1499 blockStyle.marginAfterCollapse() != MarginCollapseSeparate; |
1423 | 1500 |
1424 m_quirkContainer = blockFlow->isTableCell() || blockFlow->isBody(); | 1501 m_quirkContainer = blockFlow->isTableCell() || blockFlow->isBody(); |
1425 | 1502 |
1426 m_discardMargin = m_canCollapseMarginBeforeWithChildren && | 1503 m_discardMargin = m_canCollapseMarginBeforeWithChildren && |
1427 blockFlow->mustDiscardMarginBefore(); | 1504 blockFlow->mustDiscardMarginBefore(); |
(...skipping 14 matching lines...) Expand all Loading... |
1442 LayoutUnit childBeforeNegative; | 1519 LayoutUnit childBeforeNegative; |
1443 LayoutUnit childAfterPositive; | 1520 LayoutUnit childAfterPositive; |
1444 LayoutUnit childAfterNegative; | 1521 LayoutUnit childAfterNegative; |
1445 | 1522 |
1446 LayoutUnit beforeMargin; | 1523 LayoutUnit beforeMargin; |
1447 LayoutUnit afterMargin; | 1524 LayoutUnit afterMargin; |
1448 | 1525 |
1449 LayoutBlockFlow* childLayoutBlockFlow = | 1526 LayoutBlockFlow* childLayoutBlockFlow = |
1450 child.isLayoutBlockFlow() ? toLayoutBlockFlow(&child) : 0; | 1527 child.isLayoutBlockFlow() ? toLayoutBlockFlow(&child) : 0; |
1451 | 1528 |
1452 // If the child has the same directionality as we do, then we can just return
its | 1529 // If the child has the same directionality as we do, then we can just return |
1453 // margins in the same direction. | 1530 // its margins in the same direction. |
1454 if (!child.isWritingModeRoot()) { | 1531 if (!child.isWritingModeRoot()) { |
1455 if (childLayoutBlockFlow) { | 1532 if (childLayoutBlockFlow) { |
1456 childBeforePositive = childLayoutBlockFlow->maxPositiveMarginBefore(); | 1533 childBeforePositive = childLayoutBlockFlow->maxPositiveMarginBefore(); |
1457 childBeforeNegative = childLayoutBlockFlow->maxNegativeMarginBefore(); | 1534 childBeforeNegative = childLayoutBlockFlow->maxNegativeMarginBefore(); |
1458 childAfterPositive = childLayoutBlockFlow->maxPositiveMarginAfter(); | 1535 childAfterPositive = childLayoutBlockFlow->maxPositiveMarginAfter(); |
1459 childAfterNegative = childLayoutBlockFlow->maxNegativeMarginAfter(); | 1536 childAfterNegative = childLayoutBlockFlow->maxNegativeMarginAfter(); |
1460 } else { | 1537 } else { |
1461 beforeMargin = child.marginBefore(); | 1538 beforeMargin = child.marginBefore(); |
1462 afterMargin = child.marginAfter(); | 1539 afterMargin = child.marginAfter(); |
1463 } | 1540 } |
1464 } else if (child.isHorizontalWritingMode() == isHorizontalWritingMode()) { | 1541 } else if (child.isHorizontalWritingMode() == isHorizontalWritingMode()) { |
1465 // The child has a different directionality. If the child is parallel, then
it's just | 1542 // The child has a different directionality. If the child is parallel, then |
1466 // flipped relative to us. We can use the margins for the opposite edges. | 1543 // it's just flipped relative to us. We can use the margins for the opposite |
| 1544 // edges. |
1467 if (childLayoutBlockFlow) { | 1545 if (childLayoutBlockFlow) { |
1468 childBeforePositive = childLayoutBlockFlow->maxPositiveMarginAfter(); | 1546 childBeforePositive = childLayoutBlockFlow->maxPositiveMarginAfter(); |
1469 childBeforeNegative = childLayoutBlockFlow->maxNegativeMarginAfter(); | 1547 childBeforeNegative = childLayoutBlockFlow->maxNegativeMarginAfter(); |
1470 childAfterPositive = childLayoutBlockFlow->maxPositiveMarginBefore(); | 1548 childAfterPositive = childLayoutBlockFlow->maxPositiveMarginBefore(); |
1471 childAfterNegative = childLayoutBlockFlow->maxNegativeMarginBefore(); | 1549 childAfterNegative = childLayoutBlockFlow->maxNegativeMarginBefore(); |
1472 } else { | 1550 } else { |
1473 beforeMargin = child.marginAfter(); | 1551 beforeMargin = child.marginAfter(); |
1474 afterMargin = child.marginBefore(); | 1552 afterMargin = child.marginBefore(); |
1475 } | 1553 } |
1476 } else { | 1554 } else { |
1477 // The child is perpendicular to us, which means its margins don't collapse
but are on the | 1555 // The child is perpendicular to us, which means its margins don't collapse |
1478 // "logical left/right" sides of the child box. We can just return the raw m
argin in this case. | 1556 // but are on the "logical left/right" sides of the child box. We can just |
| 1557 // return the raw margin in this case. |
1479 beforeMargin = marginBeforeForChild(child); | 1558 beforeMargin = marginBeforeForChild(child); |
1480 afterMargin = marginAfterForChild(child); | 1559 afterMargin = marginAfterForChild(child); |
1481 } | 1560 } |
1482 | 1561 |
1483 // Resolve uncollapsing margins into their positive/negative buckets. | 1562 // Resolve uncollapsing margins into their positive/negative buckets. |
1484 if (beforeMargin) { | 1563 if (beforeMargin) { |
1485 if (beforeMargin > 0) | 1564 if (beforeMargin > 0) |
1486 childBeforePositive = beforeMargin; | 1565 childBeforePositive = beforeMargin; |
1487 else | 1566 else |
1488 childBeforeNegative = -beforeMargin; | 1567 childBeforeNegative = -beforeMargin; |
1489 } | 1568 } |
1490 if (afterMargin) { | 1569 if (afterMargin) { |
1491 if (afterMargin > 0) | 1570 if (afterMargin > 0) |
1492 childAfterPositive = afterMargin; | 1571 childAfterPositive = afterMargin; |
1493 else | 1572 else |
1494 childAfterNegative = -afterMargin; | 1573 childAfterNegative = -afterMargin; |
1495 } | 1574 } |
1496 | 1575 |
1497 return LayoutBlockFlow::MarginValues(childBeforePositive, childBeforeNegative, | 1576 return LayoutBlockFlow::MarginValues(childBeforePositive, childBeforeNegative, |
1498 childAfterPositive, childAfterNegative); | 1577 childAfterPositive, childAfterNegative); |
1499 } | 1578 } |
1500 | 1579 |
1501 LayoutUnit LayoutBlockFlow::collapseMargins(LayoutBox& child, | 1580 LayoutUnit LayoutBlockFlow::collapseMargins(LayoutBox& child, |
1502 MarginInfo& marginInfo, | 1581 MarginInfo& marginInfo, |
1503 bool childIsSelfCollapsing, | 1582 bool childIsSelfCollapsing, |
1504 bool childDiscardMarginBefore, | 1583 bool childDiscardMarginBefore, |
1505 bool childDiscardMarginAfter) { | 1584 bool childDiscardMarginAfter) { |
1506 // The child discards the before margin when the the after margin has discard
in the case of a self collapsing block. | 1585 // The child discards the before margin when the the after margin has discard |
| 1586 // in the case of a self collapsing block. |
1507 childDiscardMarginBefore = childDiscardMarginBefore || | 1587 childDiscardMarginBefore = childDiscardMarginBefore || |
1508 (childDiscardMarginAfter && childIsSelfCollapsing); | 1588 (childDiscardMarginAfter && childIsSelfCollapsing); |
1509 | 1589 |
1510 // Get the four margin values for the child and cache them. | 1590 // Get the four margin values for the child and cache them. |
1511 const LayoutBlockFlow::MarginValues childMargins = | 1591 const LayoutBlockFlow::MarginValues childMargins = |
1512 marginValuesForChild(child); | 1592 marginValuesForChild(child); |
1513 | 1593 |
1514 // Get our max pos and neg top margins. | 1594 // Get our max pos and neg top margins. |
1515 LayoutUnit posTop = childMargins.positiveMarginBefore(); | 1595 LayoutUnit posTop = childMargins.positiveMarginBefore(); |
1516 LayoutUnit negTop = childMargins.negativeMarginBefore(); | 1596 LayoutUnit negTop = childMargins.negativeMarginBefore(); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1549 if (!marginInfo.determinedMarginBeforeQuirk() && topQuirk && | 1629 if (!marginInfo.determinedMarginBeforeQuirk() && topQuirk && |
1550 !marginBefore()) { | 1630 !marginBefore()) { |
1551 // We have no top margin and our top child has a quirky margin. | 1631 // We have no top margin and our top child has a quirky margin. |
1552 // We will pick up this quirky margin and pass it through. | 1632 // We will pick up this quirky margin and pass it through. |
1553 // This deals with the <td><div><p> case. | 1633 // This deals with the <td><div><p> case. |
1554 // Don't do this for a block that split two inlines though. You do | 1634 // Don't do this for a block that split two inlines though. You do |
1555 // still apply margins in this case. | 1635 // still apply margins in this case. |
1556 setHasMarginBeforeQuirk(true); | 1636 setHasMarginBeforeQuirk(true); |
1557 } | 1637 } |
1558 } else { | 1638 } else { |
1559 // The before margin of the container will also discard all the margins it
is collapsing with. | 1639 // The before margin of the container will also discard all the margins it |
| 1640 // is collapsing with. |
1560 setMustDiscardMarginBefore(); | 1641 setMustDiscardMarginBefore(); |
1561 } | 1642 } |
1562 } | 1643 } |
1563 | 1644 |
1564 // Once we find a child with discardMarginBefore all the margins collapsing wi
th us must also discard. | 1645 // Once we find a child with discardMarginBefore all the margins collapsing |
| 1646 // with us must also discard. |
1565 if (childDiscardMarginBefore) { | 1647 if (childDiscardMarginBefore) { |
1566 marginInfo.setDiscardMargin(true); | 1648 marginInfo.setDiscardMargin(true); |
1567 marginInfo.clearMargin(); | 1649 marginInfo.clearMargin(); |
1568 } | 1650 } |
1569 | 1651 |
1570 if (marginInfo.quirkContainer() && marginInfo.atBeforeSideOfBlock() && | 1652 if (marginInfo.quirkContainer() && marginInfo.atBeforeSideOfBlock() && |
1571 (posTop - negTop)) | 1653 (posTop - negTop)) |
1572 marginInfo.setHasMarginBeforeQuirk(topQuirk); | 1654 marginInfo.setHasMarginBeforeQuirk(topQuirk); |
1573 | 1655 |
1574 LayoutUnit beforeCollapseLogicalTop = logicalHeight(); | 1656 LayoutUnit beforeCollapseLogicalTop = logicalHeight(); |
1575 LayoutUnit logicalTop = beforeCollapseLogicalTop; | 1657 LayoutUnit logicalTop = beforeCollapseLogicalTop; |
1576 | 1658 |
1577 LayoutObject* prev = child.previousSibling(); | 1659 LayoutObject* prev = child.previousSibling(); |
1578 LayoutBlockFlow* previousBlockFlow = | 1660 LayoutBlockFlow* previousBlockFlow = |
1579 prev && prev->isLayoutBlockFlow() && | 1661 prev && prev->isLayoutBlockFlow() && |
1580 !prev->isFloatingOrOutOfFlowPositioned() | 1662 !prev->isFloatingOrOutOfFlowPositioned() |
1581 ? toLayoutBlockFlow(prev) | 1663 ? toLayoutBlockFlow(prev) |
1582 : 0; | 1664 : 0; |
1583 // If the child's previous sibling is a self-collapsing block that cleared a f
loat then its top border edge has been set at the bottom border edge | 1665 // If the child's previous sibling is a self-collapsing block that cleared a |
1584 // of the float. Since we want to collapse the child's top margin with the sel
f-collapsing block's top and bottom margins we need to adjust our parent's heigh
t to match the | 1666 // float then its top border edge has been set at the bottom border edge of |
1585 // margin top of the self-collapsing block. If the resulting collapsed margin
leaves the child still intruding into the float then we will want to clear it. | 1667 // the float. Since we want to collapse the child's top margin with the self- |
| 1668 // collapsing block's top and bottom margins we need to adjust our parent's |
| 1669 // height to match the margin top of the self-collapsing block. If the |
| 1670 // resulting collapsed margin leaves the child still intruding into the float |
| 1671 // then we will want to clear it. |
1586 if (!marginInfo.canCollapseWithMarginBefore() && previousBlockFlow && | 1672 if (!marginInfo.canCollapseWithMarginBefore() && previousBlockFlow && |
1587 marginInfo.lastChildIsSelfCollapsingBlockWithClearance()) | 1673 marginInfo.lastChildIsSelfCollapsingBlockWithClearance()) |
1588 setLogicalHeight( | 1674 setLogicalHeight( |
1589 logicalHeight() - | 1675 logicalHeight() - |
1590 marginValuesForChild(*previousBlockFlow).positiveMarginBefore()); | 1676 marginValuesForChild(*previousBlockFlow).positiveMarginBefore()); |
1591 | 1677 |
1592 if (childIsSelfCollapsing) { | 1678 if (childIsSelfCollapsing) { |
1593 // For a self collapsing block both the before and after margins get discard
ed. The block doesn't contribute anything to the height of the block. | 1679 // For a self collapsing block both the before and after margins get |
1594 // Also, the child's top position equals the logical height of the container
. | 1680 // discarded. The block doesn't contribute anything to the height of the |
| 1681 // block. Also, the child's top position equals the logical height of the |
| 1682 // container. |
1595 if (!childDiscardMarginBefore && !marginInfo.discardMargin()) { | 1683 if (!childDiscardMarginBefore && !marginInfo.discardMargin()) { |
1596 // This child has no height. We need to compute our | 1684 // This child has no height. We need to compute our |
1597 // position before we collapse the child's margins together, | 1685 // position before we collapse the child's margins together, |
1598 // so that we can get an accurate position for the zero-height block. | 1686 // so that we can get an accurate position for the zero-height block. |
1599 LayoutUnit collapsedBeforePos = std::max( | 1687 LayoutUnit collapsedBeforePos = std::max( |
1600 marginInfo.positiveMargin(), childMargins.positiveMarginBefore()); | 1688 marginInfo.positiveMargin(), childMargins.positiveMarginBefore()); |
1601 LayoutUnit collapsedBeforeNeg = std::max( | 1689 LayoutUnit collapsedBeforeNeg = std::max( |
1602 marginInfo.negativeMargin(), childMargins.negativeMarginBefore()); | 1690 marginInfo.negativeMargin(), childMargins.negativeMarginBefore()); |
1603 marginInfo.setMargin(collapsedBeforePos, collapsedBeforeNeg); | 1691 marginInfo.setMargin(collapsedBeforePos, collapsedBeforeNeg); |
1604 | 1692 |
1605 // Now collapse the child's margins together, which means examining our | 1693 // Now collapse the child's margins together, which means examining our |
1606 // bottom margin values as well. | 1694 // bottom margin values as well. |
1607 marginInfo.setPositiveMarginIfLarger(childMargins.positiveMarginAfter()); | 1695 marginInfo.setPositiveMarginIfLarger(childMargins.positiveMarginAfter()); |
1608 marginInfo.setNegativeMarginIfLarger(childMargins.negativeMarginAfter()); | 1696 marginInfo.setNegativeMarginIfLarger(childMargins.negativeMarginAfter()); |
1609 | 1697 |
1610 if (!marginInfo.canCollapseWithMarginBefore()) { | 1698 if (!marginInfo.canCollapseWithMarginBefore()) { |
1611 // We need to make sure that the position of the self-collapsing block | 1699 // We need to make sure that the position of the self-collapsing block |
1612 // is correct, since it could have overflowing content | 1700 // is correct, since it could have overflowing content |
1613 // that needs to be positioned correctly (e.g., a block that | 1701 // that needs to be positioned correctly (e.g., a block that |
1614 // had a specified height of 0 but that actually had subcontent). | 1702 // had a specified height of 0 but that actually had subcontent). |
1615 logicalTop = logicalHeight() + collapsedBeforePos - collapsedBeforeNeg; | 1703 logicalTop = logicalHeight() + collapsedBeforePos - collapsedBeforeNeg; |
1616 } | 1704 } |
1617 } | 1705 } |
1618 } else { | 1706 } else { |
1619 if (mustSeparateMarginBeforeForChild(child)) { | 1707 if (mustSeparateMarginBeforeForChild(child)) { |
1620 ASSERT(!marginInfo.discardMargin() || | 1708 ASSERT(!marginInfo.discardMargin() || |
1621 (marginInfo.discardMargin() && !marginInfo.margin())); | 1709 (marginInfo.discardMargin() && !marginInfo.margin())); |
1622 // If we are at the before side of the block and we collapse, ignore the c
omputed margin | 1710 // If we are at the before side of the block and we collapse, ignore the |
1623 // and just add the child margin to the container height. This will correc
tly position | 1711 // computed margin and just add the child margin to the container height. |
1624 // the child inside the container. | 1712 // This will correctly position the child inside the container. |
1625 LayoutUnit separateMargin = !marginInfo.canCollapseWithMarginBefore() | 1713 LayoutUnit separateMargin = !marginInfo.canCollapseWithMarginBefore() |
1626 ? marginInfo.margin() | 1714 ? marginInfo.margin() |
1627 : LayoutUnit(); | 1715 : LayoutUnit(); |
1628 setLogicalHeight(logicalHeight() + separateMargin + | 1716 setLogicalHeight(logicalHeight() + separateMargin + |
1629 marginBeforeForChild(child)); | 1717 marginBeforeForChild(child)); |
1630 logicalTop = logicalHeight(); | 1718 logicalTop = logicalHeight(); |
1631 } else if (!marginInfo.discardMargin() && | 1719 } else if (!marginInfo.discardMargin() && |
1632 (!marginInfo.atBeforeSideOfBlock() || | 1720 (!marginInfo.atBeforeSideOfBlock() || |
1633 (!marginInfo.canCollapseMarginBeforeWithChildren() && | 1721 (!marginInfo.canCollapseMarginBeforeWithChildren() && |
1634 (!document().inQuirksMode() || !marginInfo.quirkContainer() || | 1722 (!document().inQuirksMode() || !marginInfo.quirkContainer() || |
(...skipping 12 matching lines...) Expand all Loading... |
1647 marginInfo.setPositiveMargin(childMargins.positiveMarginAfter()); | 1735 marginInfo.setPositiveMargin(childMargins.positiveMarginAfter()); |
1648 marginInfo.setNegativeMargin(childMargins.negativeMarginAfter()); | 1736 marginInfo.setNegativeMargin(childMargins.negativeMarginAfter()); |
1649 } else { | 1737 } else { |
1650 marginInfo.clearMargin(); | 1738 marginInfo.clearMargin(); |
1651 } | 1739 } |
1652 | 1740 |
1653 if (marginInfo.margin()) | 1741 if (marginInfo.margin()) |
1654 marginInfo.setHasMarginAfterQuirk(hasMarginAfterQuirk(&child)); | 1742 marginInfo.setHasMarginAfterQuirk(hasMarginAfterQuirk(&child)); |
1655 } | 1743 } |
1656 | 1744 |
1657 // If margins would pull us past the top of the next page, then we need to pul
l back and pretend like the margins | 1745 // If margins would pull us past the top of the next page, then we need to |
1658 // collapsed into the page edge. | 1746 // pull back and pretend like the margins collapsed into the page edge. |
1659 LayoutState* layoutState = view()->layoutState(); | 1747 LayoutState* layoutState = view()->layoutState(); |
1660 if (layoutState->isPaginated() && | 1748 if (layoutState->isPaginated() && |
1661 isPageLogicalHeightKnown(beforeCollapseLogicalTop) && | 1749 isPageLogicalHeightKnown(beforeCollapseLogicalTop) && |
1662 logicalTop > beforeCollapseLogicalTop) { | 1750 logicalTop > beforeCollapseLogicalTop) { |
1663 LayoutUnit oldLogicalTop = logicalTop; | 1751 LayoutUnit oldLogicalTop = logicalTop; |
1664 logicalTop = | 1752 logicalTop = |
1665 std::min(logicalTop, nextPageLogicalTop(beforeCollapseLogicalTop)); | 1753 std::min(logicalTop, nextPageLogicalTop(beforeCollapseLogicalTop)); |
1666 setLogicalHeight(logicalHeight() + (logicalTop - oldLogicalTop)); | 1754 setLogicalHeight(logicalHeight() + (logicalTop - oldLogicalTop)); |
1667 } | 1755 } |
1668 | 1756 |
1669 if (previousBlockFlow) { | 1757 if (previousBlockFlow) { |
1670 // If |child| is a self-collapsing block it may have collapsed into a previo
us sibling and although it hasn't reduced the height of the parent yet | 1758 // If |child| is a self-collapsing block it may have collapsed into a |
1671 // any floats from the parent will now overhang. | 1759 // previous sibling and although it hasn't reduced the height of the parent |
| 1760 // yet any floats from the parent will now overhang. |
1672 LayoutUnit oldLogicalHeight = logicalHeight(); | 1761 LayoutUnit oldLogicalHeight = logicalHeight(); |
1673 setLogicalHeight(logicalTop); | 1762 setLogicalHeight(logicalTop); |
1674 if (!previousBlockFlow->avoidsFloats() && | 1763 if (!previousBlockFlow->avoidsFloats() && |
1675 (previousBlockFlow->logicalTop() + | 1764 (previousBlockFlow->logicalTop() + |
1676 previousBlockFlow->lowestFloatLogicalBottom()) > logicalTop) | 1765 previousBlockFlow->lowestFloatLogicalBottom()) > logicalTop) |
1677 addOverhangingFloats(previousBlockFlow, false); | 1766 addOverhangingFloats(previousBlockFlow, false); |
1678 setLogicalHeight(oldLogicalHeight); | 1767 setLogicalHeight(oldLogicalHeight); |
1679 | 1768 |
1680 // If |child|'s previous sibling is or contains a self-collapsing block that
cleared a float and margin collapsing resulted in |child| moving up | 1769 // If |child|'s previous sibling is or contains a self-collapsing block that |
1681 // into the margin area of the self-collapsing block then the float it clear
s is now intruding into |child|. Layout again so that we can look for | 1770 // cleared a float and margin collapsing resulted in |child| moving up |
1682 // floats in the parent that overhang |child|'s new logical top. | 1771 // into the margin area of the self-collapsing block then the float it |
| 1772 // clears is now intruding into |child|. Layout again so that we can look |
| 1773 // for floats in the parent that overhang |child|'s new logical top. |
1683 bool logicalTopIntrudesIntoFloat = logicalTop < beforeCollapseLogicalTop; | 1774 bool logicalTopIntrudesIntoFloat = logicalTop < beforeCollapseLogicalTop; |
1684 if (logicalTopIntrudesIntoFloat && containsFloats() && | 1775 if (logicalTopIntrudesIntoFloat && containsFloats() && |
1685 !child.avoidsFloats() && lowestFloatLogicalBottom() > logicalTop) | 1776 !child.avoidsFloats() && lowestFloatLogicalBottom() > logicalTop) |
1686 child.setNeedsLayoutAndFullPaintInvalidation( | 1777 child.setNeedsLayoutAndFullPaintInvalidation( |
1687 LayoutInvalidationReason::AncestorMarginCollapsing); | 1778 LayoutInvalidationReason::AncestorMarginCollapsing); |
1688 } | 1779 } |
1689 | 1780 |
1690 return logicalTop; | 1781 return logicalTop; |
1691 } | 1782 } |
1692 | 1783 |
1693 void LayoutBlockFlow::adjustPositionedBlock( | 1784 void LayoutBlockFlow::adjustPositionedBlock( |
1694 LayoutBox& child, | 1785 LayoutBox& child, |
1695 const BlockChildrenLayoutInfo& layoutInfo) { | 1786 const BlockChildrenLayoutInfo& layoutInfo) { |
1696 LayoutUnit logicalTop = logicalHeight(); | 1787 LayoutUnit logicalTop = logicalHeight(); |
1697 | 1788 |
1698 // Forced breaks are only specified on in-flow objects, but auto-positioned ou
t-of-flow objects | 1789 // Forced breaks are only specified on in-flow objects, but auto-positioned |
1699 // may be affected by a break-after value of the previous in-flow object. | 1790 // out-of-flow objects may be affected by a break-after value of the previous |
| 1791 // in-flow object. |
1700 if (view()->layoutState()->isPaginated()) | 1792 if (view()->layoutState()->isPaginated()) |
1701 logicalTop = | 1793 logicalTop = |
1702 applyForcedBreak(logicalTop, layoutInfo.previousBreakAfterValue()); | 1794 applyForcedBreak(logicalTop, layoutInfo.previousBreakAfterValue()); |
1703 | 1795 |
1704 updateStaticInlinePositionForChild(child, logicalTop); | 1796 updateStaticInlinePositionForChild(child, logicalTop); |
1705 | 1797 |
1706 const MarginInfo& marginInfo = layoutInfo.marginInfo(); | 1798 const MarginInfo& marginInfo = layoutInfo.marginInfo(); |
1707 if (!marginInfo.canCollapseWithMarginBefore()) { | 1799 if (!marginInfo.canCollapseWithMarginBefore()) { |
1708 // Positioned blocks don't collapse margins, so add the margin provided by | 1800 // Positioned blocks don't collapse margins, so add the margin provided by |
1709 // the container now. The child's own margin is added later when calculating
its logical top. | 1801 // the container now. The child's own margin is added later when calculating |
| 1802 // its logical top. |
1710 LayoutUnit collapsedBeforePos = marginInfo.positiveMargin(); | 1803 LayoutUnit collapsedBeforePos = marginInfo.positiveMargin(); |
1711 LayoutUnit collapsedBeforeNeg = marginInfo.negativeMargin(); | 1804 LayoutUnit collapsedBeforeNeg = marginInfo.negativeMargin(); |
1712 logicalTop += collapsedBeforePos - collapsedBeforeNeg; | 1805 logicalTop += collapsedBeforePos - collapsedBeforeNeg; |
1713 } | 1806 } |
1714 | 1807 |
1715 PaintLayer* childLayer = child.layer(); | 1808 PaintLayer* childLayer = child.layer(); |
1716 if (childLayer->staticBlockPosition() != logicalTop) | 1809 if (childLayer->staticBlockPosition() != logicalTop) |
1717 childLayer->setStaticBlockPosition(logicalTop); | 1810 childLayer->setStaticBlockPosition(logicalTop); |
1718 } | 1811 } |
1719 | 1812 |
(...skipping 10 matching lines...) Expand all Loading... |
1730 if (!heightIncrease) | 1823 if (!heightIncrease) |
1731 return yPos; | 1824 return yPos; |
1732 | 1825 |
1733 if (childIsSelfCollapsing) { | 1826 if (childIsSelfCollapsing) { |
1734 marginInfo.setLastChildIsSelfCollapsingBlockWithClearance(true); | 1827 marginInfo.setLastChildIsSelfCollapsingBlockWithClearance(true); |
1735 marginInfo.setDiscardMargin(childDiscardMargin); | 1828 marginInfo.setDiscardMargin(childDiscardMargin); |
1736 | 1829 |
1737 // For self-collapsing blocks that clear, they can still collapse their | 1830 // For self-collapsing blocks that clear, they can still collapse their |
1738 // margins with following siblings. Reset the current margins to represent | 1831 // margins with following siblings. Reset the current margins to represent |
1739 // the self-collapsing block's margins only. | 1832 // the self-collapsing block's margins only. |
1740 // If DISCARD is specified for -webkit-margin-collapse, reset the margin val
ues. | 1833 // If DISCARD is specified for -webkit-margin-collapse, reset the margin |
| 1834 // values. |
1741 LayoutBlockFlow::MarginValues childMargins = marginValuesForChild(child); | 1835 LayoutBlockFlow::MarginValues childMargins = marginValuesForChild(child); |
1742 if (!childDiscardMargin) { | 1836 if (!childDiscardMargin) { |
1743 marginInfo.setPositiveMargin( | 1837 marginInfo.setPositiveMargin( |
1744 std::max(childMargins.positiveMarginBefore(), | 1838 std::max(childMargins.positiveMarginBefore(), |
1745 childMargins.positiveMarginAfter())); | 1839 childMargins.positiveMarginAfter())); |
1746 marginInfo.setNegativeMargin( | 1840 marginInfo.setNegativeMargin( |
1747 std::max(childMargins.negativeMarginBefore(), | 1841 std::max(childMargins.negativeMarginBefore(), |
1748 childMargins.negativeMarginAfter())); | 1842 childMargins.negativeMarginAfter())); |
1749 } else { | 1843 } else { |
1750 marginInfo.clearMargin(); | 1844 marginInfo.clearMargin(); |
1751 } | 1845 } |
1752 | 1846 |
1753 // CSS2.1 states: | 1847 // CSS2.1 states: |
1754 // "If the top and bottom margins of an element with clearance are adjoining
, its margins collapse with | 1848 // "If the top and bottom margins of an element with clearance are |
1755 // the adjoining margins of following siblings but that resulting margin doe
s not collapse with the bottom margin of the parent block." | 1849 // adjoining, its margins collapse with the adjoining margins of following |
1756 // So the parent's bottom margin cannot collapse through this block or any s
ubsequent self-collapsing blocks. Set a bit to ensure | 1850 // siblings but that resulting margin does not collapse with the bottom |
1757 // this happens; it will get reset if we encounter an in-flow sibling that i
s not self-collapsing. | 1851 // margin of the parent block." |
| 1852 // So the parent's bottom margin cannot collapse through this block or any |
| 1853 // subsequent self-collapsing blocks. Set a bit to ensure this happens; it |
| 1854 // will get reset if we encounter an in-flow sibling that is not |
| 1855 // self-collapsing. |
1758 marginInfo.setCanCollapseMarginAfterWithLastChild(false); | 1856 marginInfo.setCanCollapseMarginAfterWithLastChild(false); |
1759 | 1857 |
1760 // For now set the border-top of |child| flush with the bottom border-edge o
f the float so it can layout any floating or positioned children of | 1858 // For now set the border-top of |child| flush with the bottom border-edge |
1761 // its own at the correct vertical position. If subsequent siblings attempt
to collapse with |child|'s margins in |collapseMargins| we will | 1859 // of the float so it can layout any floating or positioned children of its |
1762 // adjust the height of the parent to |child|'s margin top (which if it is p
ositive sits up 'inside' the float it's clearing) so that all three | 1860 // own at the correct vertical position. If subsequent siblings attempt to |
1763 // margins can collapse at the correct vertical position. | 1861 // collapse with |child|'s margins in |collapseMargins| we will adjust the |
1764 // Per CSS2.1 we need to ensure that any negative margin-top clears |child|
beyond the bottom border-edge of the float so that the top border edge of the ch
ild | 1862 // height of the parent to |child|'s margin top (which if it is positive |
1765 // (i.e. its clearance) is at a position that satisfies the equation: "the
amount of clearance is set so that clearance + margin-top = [height of float], | 1863 // sits up 'inside' the float it's clearing) so that all three margins can |
| 1864 // collapse at the correct vertical position. |
| 1865 // Per CSS2.1 we need to ensure that any negative margin-top clears |child| |
| 1866 // beyond the bottom border-edge of the float so that the top border edge of |
| 1867 // the child (i.e. its clearance) is at a position that satisfies the |
| 1868 // equation: "the amount of clearance is set so that: |
| 1869 // clearance + margin-top = [height of float], |
1766 // i.e., clearance = [height of float] - margin-top". | 1870 // i.e., clearance = [height of float] - margin-top". |
1767 setLogicalHeight(child.logicalTop() + childMargins.negativeMarginBefore()); | 1871 setLogicalHeight(child.logicalTop() + childMargins.negativeMarginBefore()); |
1768 } else { | 1872 } else { |
1769 // Increase our height by the amount we had to clear. | 1873 // Increase our height by the amount we had to clear. |
1770 setLogicalHeight(logicalHeight() + heightIncrease); | 1874 setLogicalHeight(logicalHeight() + heightIncrease); |
1771 } | 1875 } |
1772 | 1876 |
1773 if (marginInfo.canCollapseWithMarginBefore()) { | 1877 if (marginInfo.canCollapseWithMarginBefore()) { |
1774 // We can no longer collapse with the top of the block since a clear | 1878 // We can no longer collapse with the top of the block since a clear |
1775 // occurred. The empty blocks collapse into the cleared block. | 1879 // occurred. The empty blocks collapse into the cleared block. |
1776 setMaxMarginBeforeValues(oldTopPosMargin, oldTopNegMargin); | 1880 setMaxMarginBeforeValues(oldTopPosMargin, oldTopNegMargin); |
1777 marginInfo.setAtBeforeSideOfBlock(false); | 1881 marginInfo.setAtBeforeSideOfBlock(false); |
1778 | 1882 |
1779 // In case the child discarded the before margin of the block we need to res
et the mustDiscardMarginBefore flag to the initial value. | 1883 // In case the child discarded the before margin of the block we need to |
| 1884 // reset the mustDiscardMarginBefore flag to the initial value. |
1780 setMustDiscardMarginBefore(style()->marginBeforeCollapse() == | 1885 setMustDiscardMarginBefore(style()->marginBeforeCollapse() == |
1781 MarginCollapseDiscard); | 1886 MarginCollapseDiscard); |
1782 } | 1887 } |
1783 | 1888 |
1784 return yPos + heightIncrease; | 1889 return yPos + heightIncrease; |
1785 } | 1890 } |
1786 | 1891 |
1787 void LayoutBlockFlow::setCollapsedBottomMargin(const MarginInfo& marginInfo) { | 1892 void LayoutBlockFlow::setCollapsedBottomMargin(const MarginInfo& marginInfo) { |
1788 if (marginInfo.canCollapseWithMarginAfter() && | 1893 if (marginInfo.canCollapseWithMarginAfter() && |
1789 !marginInfo.canCollapseWithMarginBefore()) { | 1894 !marginInfo.canCollapseWithMarginBefore()) { |
1790 // Update the after side margin of the container to discard if the after mar
gin of the last child also discards and we collapse with it. | 1895 // Update the after side margin of the container to discard if the after |
| 1896 // margin of the last child also discards and we collapse with it. |
1791 // Don't update the max margin values because we won't need them anyway. | 1897 // Don't update the max margin values because we won't need them anyway. |
1792 if (marginInfo.discardMargin()) { | 1898 if (marginInfo.discardMargin()) { |
1793 setMustDiscardMarginAfter(); | 1899 setMustDiscardMarginAfter(); |
1794 return; | 1900 return; |
1795 } | 1901 } |
1796 | 1902 |
1797 // Update our max pos/neg bottom margins, since we collapsed our bottom marg
ins | 1903 // Update our max pos/neg bottom margins, since we collapsed our bottom |
1798 // with our children. | 1904 // margins with our children. |
1799 setMaxMarginAfterValues( | 1905 setMaxMarginAfterValues( |
1800 std::max(maxPositiveMarginAfter(), marginInfo.positiveMargin()), | 1906 std::max(maxPositiveMarginAfter(), marginInfo.positiveMargin()), |
1801 std::max(maxNegativeMarginAfter(), marginInfo.negativeMargin())); | 1907 std::max(maxNegativeMarginAfter(), marginInfo.negativeMargin())); |
1802 | 1908 |
1803 if (!marginInfo.hasMarginAfterQuirk()) | 1909 if (!marginInfo.hasMarginAfterQuirk()) |
1804 setHasMarginAfterQuirk(false); | 1910 setHasMarginAfterQuirk(false); |
1805 | 1911 |
1806 if (marginInfo.hasMarginAfterQuirk() && !marginAfter()) { | 1912 if (marginInfo.hasMarginAfterQuirk() && !marginAfter()) { |
1807 // We have no bottom margin and our last child has a quirky margin. | 1913 // We have no bottom margin and our last child has a quirky margin. |
1808 // We will pick up this quirky margin and pass it through. | 1914 // We will pick up this quirky margin and pass it through. |
1809 // This deals with the <td><div><p> case. | 1915 // This deals with the <td><div><p> case. |
1810 setHasMarginAfterQuirk(true); | 1916 setHasMarginAfterQuirk(true); |
1811 } | 1917 } |
1812 } | 1918 } |
1813 } | 1919 } |
1814 | 1920 |
1815 DISABLE_CFI_PERF | 1921 DISABLE_CFI_PERF |
1816 void LayoutBlockFlow::marginBeforeEstimateForChild( | 1922 void LayoutBlockFlow::marginBeforeEstimateForChild( |
1817 LayoutBox& child, | 1923 LayoutBox& child, |
1818 LayoutUnit& positiveMarginBefore, | 1924 LayoutUnit& positiveMarginBefore, |
1819 LayoutUnit& negativeMarginBefore, | 1925 LayoutUnit& negativeMarginBefore, |
1820 bool& discardMarginBefore) const { | 1926 bool& discardMarginBefore) const { |
1821 // Give up if in quirks mode and we're a body/table cell and the top margin of
the child box is quirky. | 1927 // Give up if in quirks mode and we're a body/table cell and the top margin of |
1822 // Give up if the child specified -webkit-margin-collapse: separate that preve
nts collapsing. | 1928 // the child box is quirky. |
| 1929 // Give up if the child specified -webkit-margin-collapse: separate that |
| 1930 // prevents collapsing. |
1823 // FIXME: Use writing mode independent accessor for marginBeforeCollapse. | 1931 // FIXME: Use writing mode independent accessor for marginBeforeCollapse. |
1824 if ((document().inQuirksMode() && hasMarginBeforeQuirk(&child) && | 1932 if ((document().inQuirksMode() && hasMarginBeforeQuirk(&child) && |
1825 (isTableCell() || isBody())) || | 1933 (isTableCell() || isBody())) || |
1826 child.style()->marginBeforeCollapse() == MarginCollapseSeparate) | 1934 child.style()->marginBeforeCollapse() == MarginCollapseSeparate) |
1827 return; | 1935 return; |
1828 | 1936 |
1829 // The margins are discarded by a child that specified -webkit-margin-collapse
: discard. | 1937 // The margins are discarded by a child that specified |
| 1938 // -webkit-margin-collapse: discard. |
1830 // FIXME: Use writing mode independent accessor for marginBeforeCollapse. | 1939 // FIXME: Use writing mode independent accessor for marginBeforeCollapse. |
1831 if (child.style()->marginBeforeCollapse() == MarginCollapseDiscard) { | 1940 if (child.style()->marginBeforeCollapse() == MarginCollapseDiscard) { |
1832 positiveMarginBefore = LayoutUnit(); | 1941 positiveMarginBefore = LayoutUnit(); |
1833 negativeMarginBefore = LayoutUnit(); | 1942 negativeMarginBefore = LayoutUnit(); |
1834 discardMarginBefore = true; | 1943 discardMarginBefore = true; |
1835 return; | 1944 return; |
1836 } | 1945 } |
1837 | 1946 |
1838 LayoutUnit beforeChildMargin = marginBeforeForChild(child); | 1947 LayoutUnit beforeChildMargin = marginBeforeForChild(child); |
1839 positiveMarginBefore = std::max(positiveMarginBefore, beforeChildMargin); | 1948 positiveMarginBefore = std::max(positiveMarginBefore, beforeChildMargin); |
(...skipping 16 matching lines...) Expand all Loading... |
1856 LayoutBox* grandchildBox = childBlockFlow->firstChildBox(); | 1965 LayoutBox* grandchildBox = childBlockFlow->firstChildBox(); |
1857 for (; grandchildBox; grandchildBox = grandchildBox->nextSiblingBox()) { | 1966 for (; grandchildBox; grandchildBox = grandchildBox->nextSiblingBox()) { |
1858 if (!grandchildBox->isFloatingOrOutOfFlowPositioned() && | 1967 if (!grandchildBox->isFloatingOrOutOfFlowPositioned() && |
1859 !grandchildBox->isColumnSpanAll()) | 1968 !grandchildBox->isColumnSpanAll()) |
1860 break; | 1969 break; |
1861 } | 1970 } |
1862 | 1971 |
1863 if (!grandchildBox) | 1972 if (!grandchildBox) |
1864 return; | 1973 return; |
1865 | 1974 |
1866 // Make sure to update the block margins now for the grandchild box so that we
're looking at current values. | 1975 // Make sure to update the block margins now for the grandchild box so that |
| 1976 // we're looking at current values. |
1867 if (grandchildBox->needsLayout()) { | 1977 if (grandchildBox->needsLayout()) { |
1868 grandchildBox->computeAndSetBlockDirectionMargins(this); | 1978 grandchildBox->computeAndSetBlockDirectionMargins(this); |
1869 if (grandchildBox->isLayoutBlock()) { | 1979 if (grandchildBox->isLayoutBlock()) { |
1870 LayoutBlock* grandchildBlock = toLayoutBlock(grandchildBox); | 1980 LayoutBlock* grandchildBlock = toLayoutBlock(grandchildBox); |
1871 grandchildBlock->setHasMarginBeforeQuirk( | 1981 grandchildBlock->setHasMarginBeforeQuirk( |
1872 grandchildBox->style()->hasMarginBeforeQuirk()); | 1982 grandchildBox->style()->hasMarginBeforeQuirk()); |
1873 grandchildBlock->setHasMarginAfterQuirk( | 1983 grandchildBlock->setHasMarginAfterQuirk( |
1874 grandchildBox->style()->hasMarginAfterQuirk()); | 1984 grandchildBox->style()->hasMarginAfterQuirk()); |
1875 } | 1985 } |
1876 } | 1986 } |
1877 | 1987 |
1878 // If we have a 'clear' value but also have a margin we may not actually requi
re clearance to move past any floats. | 1988 // If we have a 'clear' value but also have a margin we may not actually |
1879 // If that's the case we want to be sure we estimate the correct position incl
uding margins after any floats rather | 1989 // require clearance to move past any floats. If that's the case we want to be |
1880 // than use 'clearance' later which could give us the wrong position. | 1990 // sure we estimate the correct position including margins after any floats |
| 1991 // rather than use 'clearance' later which could give us the wrong position. |
1881 if (grandchildBox->style()->clear() != ClearNone && | 1992 if (grandchildBox->style()->clear() != ClearNone && |
1882 childBlockFlow->marginBeforeForChild(*grandchildBox) == 0) | 1993 childBlockFlow->marginBeforeForChild(*grandchildBox) == 0) |
1883 return; | 1994 return; |
1884 | 1995 |
1885 // Collapse the margin of the grandchild box with our own to produce an estima
te. | 1996 // Collapse the margin of the grandchild box with our own to produce an |
| 1997 // estimate. |
1886 childBlockFlow->marginBeforeEstimateForChild( | 1998 childBlockFlow->marginBeforeEstimateForChild( |
1887 *grandchildBox, positiveMarginBefore, negativeMarginBefore, | 1999 *grandchildBox, positiveMarginBefore, negativeMarginBefore, |
1888 discardMarginBefore); | 2000 discardMarginBefore); |
1889 } | 2001 } |
1890 | 2002 |
1891 LayoutUnit LayoutBlockFlow::estimateLogicalTopPosition( | 2003 LayoutUnit LayoutBlockFlow::estimateLogicalTopPosition( |
1892 LayoutBox& child, | 2004 LayoutBox& child, |
1893 const BlockChildrenLayoutInfo& layoutInfo, | 2005 const BlockChildrenLayoutInfo& layoutInfo, |
1894 LayoutUnit& estimateWithoutPagination) { | 2006 LayoutUnit& estimateWithoutPagination) { |
1895 const MarginInfo& marginInfo = layoutInfo.marginInfo(); | 2007 const MarginInfo& marginInfo = layoutInfo.marginInfo(); |
1896 // FIXME: We need to eliminate the estimation of vertical position, because wh
en it's wrong we sometimes trigger a pathological | 2008 // FIXME: We need to eliminate the estimation of vertical position, because |
| 2009 // when it's wrong we sometimes trigger a pathological |
1897 // relayout if there are intruding floats. | 2010 // relayout if there are intruding floats. |
1898 LayoutUnit logicalTopEstimate = logicalHeight(); | 2011 LayoutUnit logicalTopEstimate = logicalHeight(); |
1899 LayoutUnit positiveMarginBefore; | 2012 LayoutUnit positiveMarginBefore; |
1900 LayoutUnit negativeMarginBefore; | 2013 LayoutUnit negativeMarginBefore; |
1901 bool discardMarginBefore = false; | 2014 bool discardMarginBefore = false; |
1902 if (!marginInfo.canCollapseWithMarginBefore()) { | 2015 if (!marginInfo.canCollapseWithMarginBefore()) { |
1903 if (child.selfNeedsLayout()) { | 2016 if (child.selfNeedsLayout()) { |
1904 // Try to do a basic estimation of how the collapse is going to go. | 2017 // Try to do a basic estimation of how the collapse is going to go. |
1905 marginBeforeEstimateForChild(child, positiveMarginBefore, | 2018 marginBeforeEstimateForChild(child, positiveMarginBefore, |
1906 negativeMarginBefore, discardMarginBefore); | 2019 negativeMarginBefore, discardMarginBefore); |
1907 } else { | 2020 } else { |
1908 // Use the cached collapsed margin values from a previous layout. Most of
the time they | 2021 // Use the cached collapsed margin values from a previous layout. Most of |
1909 // will be right. | 2022 // the time they will be right. |
1910 LayoutBlockFlow::MarginValues marginValues = marginValuesForChild(child); | 2023 LayoutBlockFlow::MarginValues marginValues = marginValuesForChild(child); |
1911 positiveMarginBefore = | 2024 positiveMarginBefore = |
1912 std::max(positiveMarginBefore, marginValues.positiveMarginBefore()); | 2025 std::max(positiveMarginBefore, marginValues.positiveMarginBefore()); |
1913 negativeMarginBefore = | 2026 negativeMarginBefore = |
1914 std::max(negativeMarginBefore, marginValues.negativeMarginBefore()); | 2027 std::max(negativeMarginBefore, marginValues.negativeMarginBefore()); |
1915 discardMarginBefore = mustDiscardMarginBeforeForChild(child); | 2028 discardMarginBefore = mustDiscardMarginBeforeForChild(child); |
1916 } | 2029 } |
1917 | 2030 |
1918 // Collapse the result with our current margins. | 2031 // Collapse the result with our current margins. |
1919 if (!discardMarginBefore) | 2032 if (!discardMarginBefore) |
1920 logicalTopEstimate += | 2033 logicalTopEstimate += |
1921 std::max(marginInfo.positiveMargin(), positiveMarginBefore) - | 2034 std::max(marginInfo.positiveMargin(), positiveMarginBefore) - |
1922 std::max(marginInfo.negativeMargin(), negativeMarginBefore); | 2035 std::max(marginInfo.negativeMargin(), negativeMarginBefore); |
1923 } | 2036 } |
1924 | 2037 |
1925 // Adjust logicalTopEstimate down to the next page if the margins are so large
that we don't fit on the current | 2038 // Adjust logicalTopEstimate down to the next page if the margins are so large |
1926 // page. | 2039 // that we don't fit on the current page. |
1927 LayoutState* layoutState = view()->layoutState(); | 2040 LayoutState* layoutState = view()->layoutState(); |
1928 if (layoutState->isPaginated() && isPageLogicalHeightKnown(logicalHeight()) && | 2041 if (layoutState->isPaginated() && isPageLogicalHeightKnown(logicalHeight()) && |
1929 logicalTopEstimate > logicalHeight()) | 2042 logicalTopEstimate > logicalHeight()) |
1930 logicalTopEstimate = | 2043 logicalTopEstimate = |
1931 std::min(logicalTopEstimate, nextPageLogicalTop(logicalHeight())); | 2044 std::min(logicalTopEstimate, nextPageLogicalTop(logicalHeight())); |
1932 | 2045 |
1933 logicalTopEstimate += getClearDelta(&child, logicalTopEstimate); | 2046 logicalTopEstimate += getClearDelta(&child, logicalTopEstimate); |
1934 | 2047 |
1935 estimateWithoutPagination = logicalTopEstimate; | 2048 estimateWithoutPagination = logicalTopEstimate; |
1936 | 2049 |
1937 if (layoutState->isPaginated()) { | 2050 if (layoutState->isPaginated()) { |
1938 if (!layoutInfo.isAtFirstInFlowChild()) { | 2051 if (!layoutInfo.isAtFirstInFlowChild()) { |
1939 // Estimate the need for a forced break in front of this child. The final
break policy | 2052 // Estimate the need for a forced break in front of this child. The final |
1940 // at this class A break point isn't known until we have laid out the chil
dren of | 2053 // break policy at this class A break point isn't known until we have laid |
1941 // |child|. There may be forced break-before values set on first-children
inside that | 2054 // out the children of |child|. There may be forced break-before values |
1942 // get propagated up to the child. Just make an estimate with what we know
so far. | 2055 // set on first-children inside that get propagated up to the child. |
| 2056 // Just make an estimate with what we know so far. |
1943 EBreak breakValue = | 2057 EBreak breakValue = |
1944 child.classABreakPointValue(layoutInfo.previousBreakAfterValue()); | 2058 child.classABreakPointValue(layoutInfo.previousBreakAfterValue()); |
1945 if (isForcedFragmentainerBreakValue(breakValue)) { | 2059 if (isForcedFragmentainerBreakValue(breakValue)) { |
1946 logicalTopEstimate = applyForcedBreak(logicalHeight(), breakValue); | 2060 logicalTopEstimate = applyForcedBreak(logicalHeight(), breakValue); |
1947 // Disregard previous margins, since they will collapse with the fragmen
tainer | 2061 // Disregard previous margins, since they will collapse with the |
1948 // boundary, due to the forced break. Only apply margins that have been
specified | 2062 // fragmentainer boundary, due to the forced break. Only apply margins |
1949 // on the child or its descendants. | 2063 // that have been specified on the child or its descendants. |
1950 if (!discardMarginBefore) | 2064 if (!discardMarginBefore) |
1951 logicalTopEstimate += positiveMarginBefore - negativeMarginBefore; | 2065 logicalTopEstimate += positiveMarginBefore - negativeMarginBefore; |
1952 | 2066 |
1953 // Clearance may already have taken us past the beginning of the next | 2067 // Clearance may already have taken us past the beginning of the next |
1954 // fragmentainer. | 2068 // fragmentainer. |
1955 return std::max(estimateWithoutPagination, logicalTopEstimate); | 2069 return std::max(estimateWithoutPagination, logicalTopEstimate); |
1956 } | 2070 } |
1957 } | 2071 } |
1958 | 2072 |
1959 // For replaced elements and scrolled elements, we want to shift them to the
next page if they don't fit on the current one. | 2073 // For replaced elements and scrolled elements, we want to shift them to the |
| 2074 // next page if they don't fit on the current one. |
1960 logicalTopEstimate = adjustForUnsplittableChild(child, logicalTopEstimate); | 2075 logicalTopEstimate = adjustForUnsplittableChild(child, logicalTopEstimate); |
1961 } | 2076 } |
1962 | 2077 |
1963 return logicalTopEstimate; | 2078 return logicalTopEstimate; |
1964 } | 2079 } |
1965 | 2080 |
1966 void LayoutBlockFlow::adjustFloatingBlock(const MarginInfo& marginInfo) { | 2081 void LayoutBlockFlow::adjustFloatingBlock(const MarginInfo& marginInfo) { |
1967 // The float should be positioned taking into account the bottom margin | 2082 // The float should be positioned taking into account the bottom margin |
1968 // of the previous flow. We add that margin into the height, get the | 2083 // of the previous flow. We add that margin into the height, get the |
1969 // float positioned properly, and then subtract the margin out of the | 2084 // float positioned properly, and then subtract the margin out of the |
1970 // height again. In the case of self-collapsing blocks, we always just | 2085 // height again. In the case of self-collapsing blocks, we always just |
1971 // use the top margins, since the self-collapsing block collapsed its | 2086 // use the top margins, since the self-collapsing block collapsed its |
1972 // own bottom margin into its top margin. | 2087 // own bottom margin into its top margin. |
1973 // | 2088 // |
1974 // Note also that the previous flow may collapse its margin into the top of | 2089 // Note also that the previous flow may collapse its margin into the top of |
1975 // our block. If this is the case, then we do not add the margin in to our | 2090 // our block. If this is the case, then we do not add the margin in to our |
1976 // height when computing the position of the float. This condition can be test
ed | 2091 // height when computing the position of the float. This condition can be |
1977 // for by simply calling canCollapseWithMarginBefore. See | 2092 // tested for by simply calling canCollapseWithMarginBefore. See |
1978 // http://www.hixie.ch/tests/adhoc/css/box/block/margin-collapse/046.html for | 2093 // http://www.hixie.ch/tests/adhoc/css/box/block/margin-collapse/046.html for |
1979 // an example of this scenario. | 2094 // an example of this scenario. |
1980 LayoutUnit marginOffset = marginInfo.canCollapseWithMarginBefore() | 2095 LayoutUnit marginOffset = marginInfo.canCollapseWithMarginBefore() |
1981 ? LayoutUnit() | 2096 ? LayoutUnit() |
1982 : marginInfo.margin(); | 2097 : marginInfo.margin(); |
1983 setLogicalHeight(logicalHeight() + marginOffset); | 2098 setLogicalHeight(logicalHeight() + marginOffset); |
1984 positionNewFloats(); | 2099 positionNewFloats(); |
1985 setLogicalHeight(logicalHeight() - marginOffset); | 2100 setLogicalHeight(logicalHeight() - marginOffset); |
1986 } | 2101 } |
1987 | 2102 |
1988 void LayoutBlockFlow::handleAfterSideOfBlock(LayoutBox* lastChild, | 2103 void LayoutBlockFlow::handleAfterSideOfBlock(LayoutBox* lastChild, |
1989 LayoutUnit beforeSide, | 2104 LayoutUnit beforeSide, |
1990 LayoutUnit afterSide, | 2105 LayoutUnit afterSide, |
1991 MarginInfo& marginInfo) { | 2106 MarginInfo& marginInfo) { |
1992 marginInfo.setAtAfterSideOfBlock(true); | 2107 marginInfo.setAtAfterSideOfBlock(true); |
1993 | 2108 |
1994 // If our last child was a self-collapsing block with clearance then our logic
al height is flush with the | 2109 // If our last child was a self-collapsing block with clearance then our |
1995 // bottom edge of the float that the child clears. The correct vertical positi
on for the margin-collapsing we want | 2110 // logical height is flush with the bottom edge of the float that the child |
1996 // to perform now is at the child's margin-top - so adjust our height to that
position. | 2111 // clears. The correct vertical position for the margin-collapsing we want to |
| 2112 // perform now is at the child's margin-top - so adjust our height to that |
| 2113 // position. |
1997 if (marginInfo.lastChildIsSelfCollapsingBlockWithClearance()) { | 2114 if (marginInfo.lastChildIsSelfCollapsingBlockWithClearance()) { |
1998 ASSERT(lastChild); | 2115 ASSERT(lastChild); |
1999 setLogicalHeight(logicalHeight() - | 2116 setLogicalHeight(logicalHeight() - |
2000 marginValuesForChild(*lastChild).positiveMarginBefore()); | 2117 marginValuesForChild(*lastChild).positiveMarginBefore()); |
2001 } | 2118 } |
2002 | 2119 |
2003 if (marginInfo.canCollapseMarginAfterWithChildren() && | 2120 if (marginInfo.canCollapseMarginAfterWithChildren() && |
2004 !marginInfo.canCollapseMarginAfterWithLastChild()) | 2121 !marginInfo.canCollapseMarginAfterWithLastChild()) |
2005 marginInfo.setCanCollapseMarginAfterWithChildren(false); | 2122 marginInfo.setCanCollapseMarginAfterWithChildren(false); |
2006 | 2123 |
2007 // If we can't collapse with children then go ahead and add in the bottom marg
in. | 2124 // If we can't collapse with children then go ahead and add in the bottom |
| 2125 // margin. |
2008 if (!marginInfo.discardMargin() && | 2126 if (!marginInfo.discardMargin() && |
2009 (!marginInfo.canCollapseWithMarginAfter() && | 2127 (!marginInfo.canCollapseWithMarginAfter() && |
2010 !marginInfo.canCollapseWithMarginBefore() && | 2128 !marginInfo.canCollapseWithMarginBefore() && |
2011 (!document().inQuirksMode() || !marginInfo.quirkContainer() || | 2129 (!document().inQuirksMode() || !marginInfo.quirkContainer() || |
2012 !marginInfo.hasMarginAfterQuirk()))) | 2130 !marginInfo.hasMarginAfterQuirk()))) |
2013 setLogicalHeight(logicalHeight() + marginInfo.margin()); | 2131 setLogicalHeight(logicalHeight() + marginInfo.margin()); |
2014 | 2132 |
2015 // Now add in our bottom border/padding. | 2133 // Now add in our bottom border/padding. |
2016 setLogicalHeight(logicalHeight() + afterSide); | 2134 setLogicalHeight(logicalHeight() + afterSide); |
2017 | 2135 |
2018 // Negative margins can cause our height to shrink below our minimal height (b
order/padding). | 2136 // Negative margins can cause our height to shrink below our minimal height |
2019 // If this happens, ensure that the computed height is increased to the minima
l height. | 2137 // (border/padding). If this happens, ensure that the computed height is |
| 2138 // increased to the minimal height. |
2020 setLogicalHeight(std::max(logicalHeight(), beforeSide + afterSide)); | 2139 setLogicalHeight(std::max(logicalHeight(), beforeSide + afterSide)); |
2021 | 2140 |
2022 // Update our bottom collapsed margin info. | 2141 // Update our bottom collapsed margin info. |
2023 setCollapsedBottomMargin(marginInfo); | 2142 setCollapsedBottomMargin(marginInfo); |
2024 | 2143 |
2025 // There's no class A break point right after the last child, only *between* s
iblings. So | 2144 // There's no class A break point right after the last child, only *between* |
2026 // propagate the break-after value, and keep looking for a class A break point
(at the next | 2145 // siblings. So propagate the break-after value, and keep looking for a class |
2027 // in-flow block-level object), where we'll join this break-after value with t
he break-before | 2146 // A break point (at the next in-flow block-level object), where we'll join |
2028 // value there. | 2147 // this break-after value with the break-before value there. |
2029 if (view()->layoutState()->isPaginated() && lastChild) | 2148 if (view()->layoutState()->isPaginated() && lastChild) |
2030 setBreakAfter( | 2149 setBreakAfter( |
2031 joinFragmentainerBreakValues(breakAfter(), lastChild->breakAfter())); | 2150 joinFragmentainerBreakValues(breakAfter(), lastChild->breakAfter())); |
2032 } | 2151 } |
2033 | 2152 |
2034 void LayoutBlockFlow::setMustDiscardMarginBefore(bool value) { | 2153 void LayoutBlockFlow::setMustDiscardMarginBefore(bool value) { |
2035 if (style()->marginBeforeCollapse() == MarginCollapseDiscard) { | 2154 if (style()->marginBeforeCollapse() == MarginCollapseDiscard) { |
2036 ASSERT(value); | 2155 ASSERT(value); |
2037 return; | 2156 return; |
2038 } | 2157 } |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2078 return child.isLayoutBlockFlow() | 2197 return child.isLayoutBlockFlow() |
2079 ? toLayoutBlockFlow(&child)->mustDiscardMarginBefore() | 2198 ? toLayoutBlockFlow(&child)->mustDiscardMarginBefore() |
2080 : (child.style()->marginBeforeCollapse() == | 2199 : (child.style()->marginBeforeCollapse() == |
2081 MarginCollapseDiscard); | 2200 MarginCollapseDiscard); |
2082 if (child.isHorizontalWritingMode() == isHorizontalWritingMode()) | 2201 if (child.isHorizontalWritingMode() == isHorizontalWritingMode()) |
2083 return child.isLayoutBlockFlow() | 2202 return child.isLayoutBlockFlow() |
2084 ? toLayoutBlockFlow(&child)->mustDiscardMarginAfter() | 2203 ? toLayoutBlockFlow(&child)->mustDiscardMarginAfter() |
2085 : (child.style()->marginAfterCollapse() == | 2204 : (child.style()->marginAfterCollapse() == |
2086 MarginCollapseDiscard); | 2205 MarginCollapseDiscard); |
2087 | 2206 |
2088 // FIXME: We return false here because the implementation is not geometrically
complete. We have values only for before/after, not start/end. | 2207 // FIXME: We return false here because the implementation is not geometrically |
2089 // In case the boxes are perpendicular we assume the property is not specified
. | 2208 // complete. We have values only for before/after, not start/end. |
| 2209 // In case the boxes are perpendicular we assume the property is not |
| 2210 // specified. |
2090 return false; | 2211 return false; |
2091 } | 2212 } |
2092 | 2213 |
2093 bool LayoutBlockFlow::mustDiscardMarginAfterForChild( | 2214 bool LayoutBlockFlow::mustDiscardMarginAfterForChild( |
2094 const LayoutBox& child) const { | 2215 const LayoutBox& child) const { |
2095 ASSERT(!child.selfNeedsLayout()); | 2216 ASSERT(!child.selfNeedsLayout()); |
2096 if (!child.isWritingModeRoot()) | 2217 if (!child.isWritingModeRoot()) |
2097 return child.isLayoutBlockFlow() | 2218 return child.isLayoutBlockFlow() |
2098 ? toLayoutBlockFlow(&child)->mustDiscardMarginAfter() | 2219 ? toLayoutBlockFlow(&child)->mustDiscardMarginAfter() |
2099 : (child.style()->marginAfterCollapse() == | 2220 : (child.style()->marginAfterCollapse() == |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2153 return childStyle.marginBeforeCollapse() == MarginCollapseSeparate; | 2274 return childStyle.marginBeforeCollapse() == MarginCollapseSeparate; |
2154 | 2275 |
2155 // FIXME: See |mustDiscardMarginBeforeForChild| above. | 2276 // FIXME: See |mustDiscardMarginBeforeForChild| above. |
2156 return false; | 2277 return false; |
2157 } | 2278 } |
2158 | 2279 |
2159 LayoutUnit LayoutBlockFlow::applyForcedBreak(LayoutUnit logicalOffset, | 2280 LayoutUnit LayoutBlockFlow::applyForcedBreak(LayoutUnit logicalOffset, |
2160 EBreak breakValue) { | 2281 EBreak breakValue) { |
2161 if (!isForcedFragmentainerBreakValue(breakValue)) | 2282 if (!isForcedFragmentainerBreakValue(breakValue)) |
2162 return logicalOffset; | 2283 return logicalOffset; |
2163 // TODO(mstensho): honor breakValue. There are different types of forced break
s. We currently | 2284 // TODO(mstensho): honor breakValue. There are different types of forced |
2164 // just assume that we want to break to the top of the next fragmentainer of t
he fragmentation | 2285 // breaks. We currently just assume that we want to break to the top of the |
2165 // context we're in. However, we may want to find the next left or right page
- even if we're | 2286 // next fragmentainer of the fragmentation context we're in. However, we may |
2166 // inside a multicol container when printing. | 2287 // want to find the next left or right page - even if we're inside a multicol |
| 2288 // container when printing. |
2167 LayoutUnit pageLogicalHeight = pageLogicalHeightForOffset(logicalOffset); | 2289 LayoutUnit pageLogicalHeight = pageLogicalHeightForOffset(logicalOffset); |
2168 if (!pageLogicalHeight) | 2290 if (!pageLogicalHeight) |
2169 return logicalOffset; // Page height is still unknown, so we cannot insert
forced breaks. | 2291 return logicalOffset; // Page height is still unknown, so we cannot insert |
| 2292 // forced breaks. |
2170 LayoutUnit remainingLogicalHeight = pageRemainingLogicalHeightForOffset( | 2293 LayoutUnit remainingLogicalHeight = pageRemainingLogicalHeightForOffset( |
2171 logicalOffset, AssociateWithLatterPage); | 2294 logicalOffset, AssociateWithLatterPage); |
2172 if (remainingLogicalHeight == pageLogicalHeight) | 2295 if (remainingLogicalHeight == pageLogicalHeight) |
2173 return logicalOffset; // Don't break if we're already at the block start of
a fragmentainer. | 2296 return logicalOffset; // Don't break if we're already at the block start of |
| 2297 // a fragmentainer. |
2174 return logicalOffset + remainingLogicalHeight; | 2298 return logicalOffset + remainingLogicalHeight; |
2175 } | 2299 } |
2176 | 2300 |
2177 void LayoutBlockFlow::setBreakBefore(EBreak breakValue) { | 2301 void LayoutBlockFlow::setBreakBefore(EBreak breakValue) { |
2178 if (breakValue != BreakAuto && !isBreakBetweenControllable(breakValue)) | 2302 if (breakValue != BreakAuto && !isBreakBetweenControllable(breakValue)) |
2179 breakValue = BreakAuto; | 2303 breakValue = BreakAuto; |
2180 if (breakValue == BreakAuto && !m_rareData) | 2304 if (breakValue == BreakAuto && !m_rareData) |
2181 return; | 2305 return; |
2182 ensureRareData().m_breakBefore = breakValue; | 2306 ensureRareData().m_breakBefore = breakValue; |
2183 } | 2307 } |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2231 | 2355 |
2232 if (!hasHorizontalLayoutOverflow() && !hasVerticalLayoutOverflow()) | 2356 if (!hasHorizontalLayoutOverflow() && !hasVerticalLayoutOverflow()) |
2233 return; | 2357 return; |
2234 | 2358 |
2235 for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) { | 2359 for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) { |
2236 LayoutUnit top = std::max<LayoutUnit>(curr->lineTop(), curr->top()); | 2360 LayoutUnit top = std::max<LayoutUnit>(curr->lineTop(), curr->top()); |
2237 LayoutUnit bottom = | 2361 LayoutUnit bottom = |
2238 std::min<LayoutUnit>(curr->lineBottom(), curr->top() + curr->height()); | 2362 std::min<LayoutUnit>(curr->lineBottom(), curr->top() + curr->height()); |
2239 LayoutRect rect(layerOffset.x() + curr->x(), layerOffset.y() + top, | 2363 LayoutRect rect(layerOffset.x() + curr->x(), layerOffset.y() + top, |
2240 curr->width(), bottom - top); | 2364 curr->width(), bottom - top); |
2241 // It's common for this rect to be entirely contained in our box, so exclude
that simple case. | 2365 // It's common for this rect to be entirely contained in our box, so exclude |
| 2366 // that simple case. |
2242 if (!rect.isEmpty() && (rects.isEmpty() || !rects[0].contains(rect))) | 2367 if (!rect.isEmpty() && (rects.isEmpty() || !rects[0].contains(rect))) |
2243 rects.append(rect); | 2368 rects.append(rect); |
2244 } | 2369 } |
2245 } | 2370 } |
2246 | 2371 |
2247 void LayoutBlockFlow::absoluteRects( | 2372 void LayoutBlockFlow::absoluteRects( |
2248 Vector<IntRect>& rects, | 2373 Vector<IntRect>& rects, |
2249 const LayoutPoint& accumulatedOffset) const { | 2374 const LayoutPoint& accumulatedOffset) const { |
2250 if (!isAnonymousBlockContinuation()) { | 2375 if (!isAnonymousBlockContinuation()) { |
2251 LayoutBlock::absoluteRects(rects, accumulatedOffset); | 2376 LayoutBlock::absoluteRects(rects, accumulatedOffset); |
2252 return; | 2377 return; |
2253 } | 2378 } |
2254 // For blocks inside inlines, we go ahead and include margins so that we run r
ight up to the | 2379 // For blocks inside inlines, we go ahead and include margins so that we run |
2255 // inline boxes above and below us (thus getting merged with them to form a si
ngle irregular | 2380 // right up to the inline boxes above and below us (thus getting merged with |
2256 // shape). | 2381 // them to form a single irregular shape). |
2257 // FIXME: This is wrong for vertical writing-modes. | 2382 // FIXME: This is wrong for vertical writing-modes. |
2258 // https://bugs.webkit.org/show_bug.cgi?id=46781 | 2383 // https://bugs.webkit.org/show_bug.cgi?id=46781 |
2259 LayoutRect rect(accumulatedOffset, size()); | 2384 LayoutRect rect(accumulatedOffset, size()); |
2260 rect.expand(collapsedMarginBoxLogicalOutsets()); | 2385 rect.expand(collapsedMarginBoxLogicalOutsets()); |
2261 rects.append(pixelSnappedIntRect(rect)); | 2386 rects.append(pixelSnappedIntRect(rect)); |
2262 continuation()->absoluteRects( | 2387 continuation()->absoluteRects( |
2263 rects, | 2388 rects, |
2264 accumulatedOffset - | 2389 accumulatedOffset - |
2265 toLayoutSize( | 2390 toLayoutSize( |
2266 location() + | 2391 location() + |
2267 inlineElementContinuation()->containingBlock()->location())); | 2392 inlineElementContinuation()->containingBlock()->location())); |
2268 } | 2393 } |
2269 | 2394 |
2270 void LayoutBlockFlow::absoluteQuads(Vector<FloatQuad>& quads) const { | 2395 void LayoutBlockFlow::absoluteQuads(Vector<FloatQuad>& quads) const { |
2271 if (!isAnonymousBlockContinuation()) { | 2396 if (!isAnonymousBlockContinuation()) { |
2272 LayoutBlock::absoluteQuads(quads); | 2397 LayoutBlock::absoluteQuads(quads); |
2273 return; | 2398 return; |
2274 } | 2399 } |
2275 // For blocks inside inlines, we go ahead and include margins so that we run r
ight up to the | 2400 // For blocks inside inlines, we go ahead and include margins so that we run |
2276 // inline boxes above and below us (thus getting merged with them to form a si
ngle irregular | 2401 // right up to the inline boxes above and below us (thus getting merged with |
2277 // shape). | 2402 // them to form a single irregular shape). |
2278 // FIXME: This is wrong for vertical writing-modes. | 2403 // FIXME: This is wrong for vertical writing-modes. |
2279 // https://bugs.webkit.org/show_bug.cgi?id=46781 | 2404 // https://bugs.webkit.org/show_bug.cgi?id=46781 |
2280 LayoutRect localRect(LayoutPoint(), size()); | 2405 LayoutRect localRect(LayoutPoint(), size()); |
2281 localRect.expand(collapsedMarginBoxLogicalOutsets()); | 2406 localRect.expand(collapsedMarginBoxLogicalOutsets()); |
2282 quads.append(localToAbsoluteQuad(FloatRect(localRect))); | 2407 quads.append(localToAbsoluteQuad(FloatRect(localRect))); |
2283 continuation()->absoluteQuads(quads); | 2408 continuation()->absoluteQuads(quads); |
2284 } | 2409 } |
2285 | 2410 |
2286 LayoutObject* LayoutBlockFlow::hoverAncestor() const { | 2411 LayoutObject* LayoutBlockFlow::hoverAncestor() const { |
2287 return isAnonymousBlockContinuation() ? continuation() | 2412 return isAnonymousBlockContinuation() ? continuation() |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2340 // either no in-flow line boxes or if its 'overflow' property has a computed | 2465 // either no in-flow line boxes or if its 'overflow' property has a computed |
2341 // value other than 'visible', in which case the baseline is the bottom | 2466 // value other than 'visible', in which case the baseline is the bottom |
2342 // margin edge. | 2467 // margin edge. |
2343 // We likewise avoid using the last line box in the case of size containment, | 2468 // We likewise avoid using the last line box in the case of size containment, |
2344 // where the block's contents shouldn't be considered when laying out its | 2469 // where the block's contents shouldn't be considered when laying out its |
2345 // ancestors or siblings. | 2470 // ancestors or siblings. |
2346 | 2471 |
2347 if ((!style()->isOverflowVisible() && | 2472 if ((!style()->isOverflowVisible() && |
2348 !shouldIgnoreOverflowPropertyForInlineBlockBaseline()) || | 2473 !shouldIgnoreOverflowPropertyForInlineBlockBaseline()) || |
2349 style()->containsSize()) { | 2474 style()->containsSize()) { |
2350 // We are not calling baselinePosition here because the caller should add th
e margin-top/margin-right, not us. | 2475 // We are not calling baselinePosition here because the caller should add |
| 2476 // the margin-top/margin-right, not us. |
2351 return (lineDirection == HorizontalLine ? size().height() + marginBottom() | 2477 return (lineDirection == HorizontalLine ? size().height() + marginBottom() |
2352 : size().width() + marginLeft()) | 2478 : size().width() + marginLeft()) |
2353 .toInt(); | 2479 .toInt(); |
2354 } | 2480 } |
2355 if (isWritingModeRoot() && !isRubyRun()) | 2481 if (isWritingModeRoot() && !isRubyRun()) |
2356 return -1; | 2482 return -1; |
2357 if (!childrenInline()) | 2483 if (!childrenInline()) |
2358 return LayoutBlock::inlineBlockBaseline(lineDirection); | 2484 return LayoutBlock::inlineBlockBaseline(lineDirection); |
2359 if (lastLineBox()) | 2485 if (lastLineBox()) |
2360 return (lastLineBox()->logicalTop() + | 2486 return (lastLineBox()->logicalTop() + |
(...skipping 12 matching lines...) Expand all Loading... |
2373 : borderRight() + paddingRight())) | 2499 : borderRight() + paddingRight())) |
2374 .toInt(); | 2500 .toInt(); |
2375 } | 2501 } |
2376 | 2502 |
2377 void LayoutBlockFlow::removeFloatingObjectsFromDescendants() { | 2503 void LayoutBlockFlow::removeFloatingObjectsFromDescendants() { |
2378 if (!containsFloats()) | 2504 if (!containsFloats()) |
2379 return; | 2505 return; |
2380 removeFloatingObjects(); | 2506 removeFloatingObjects(); |
2381 setChildNeedsLayout(MarkOnlyThis); | 2507 setChildNeedsLayout(MarkOnlyThis); |
2382 | 2508 |
2383 // If our children are inline, then the only boxes which could contain floats
are atomic inlines (e.g. inline-block, float etc.) | 2509 // If our children are inline, then the only boxes which could contain floats |
2384 // and these create formatting contexts, so can't pick up intruding floats fro
m ancestors/siblings - making them safe to skip. | 2510 // are atomic inlines (e.g. inline-block, float etc.) and these create |
| 2511 // formatting contexts, so can't pick up intruding floats from |
| 2512 // ancestors/siblings - making them safe to skip. |
2385 if (childrenInline()) | 2513 if (childrenInline()) |
2386 return; | 2514 return; |
2387 for (LayoutObject* child = firstChild(); child; | 2515 for (LayoutObject* child = firstChild(); child; |
2388 child = child->nextSibling()) { | 2516 child = child->nextSibling()) { |
2389 // We don't skip blocks that create formatting contexts as they may have onl
y recently | 2517 // We don't skip blocks that create formatting contexts as they may have |
2390 // changed style and their float lists may still contain floats from sibling
s and ancestors. | 2518 // only recently changed style and their float lists may still contain |
| 2519 // floats from siblings and ancestors. |
2391 if (child->isLayoutBlockFlow()) | 2520 if (child->isLayoutBlockFlow()) |
2392 toLayoutBlockFlow(child)->removeFloatingObjectsFromDescendants(); | 2521 toLayoutBlockFlow(child)->removeFloatingObjectsFromDescendants(); |
2393 } | 2522 } |
2394 } | 2523 } |
2395 | 2524 |
2396 void LayoutBlockFlow::markAllDescendantsWithFloatsForLayout( | 2525 void LayoutBlockFlow::markAllDescendantsWithFloatsForLayout( |
2397 LayoutBox* floatToRemove, | 2526 LayoutBox* floatToRemove, |
2398 bool inLayout) { | 2527 bool inLayout) { |
2399 if (!everHadLayout() && !containsFloats()) | 2528 if (!everHadLayout() && !containsFloats()) |
2400 return; | 2529 return; |
2401 | 2530 |
2402 if (m_descendantsWithFloatsMarkedForLayout && !floatToRemove) | 2531 if (m_descendantsWithFloatsMarkedForLayout && !floatToRemove) |
2403 return; | 2532 return; |
2404 m_descendantsWithFloatsMarkedForLayout |= !floatToRemove; | 2533 m_descendantsWithFloatsMarkedForLayout |= !floatToRemove; |
2405 | 2534 |
2406 MarkingBehavior markParents = inLayout ? MarkOnlyThis : MarkContainerChain; | 2535 MarkingBehavior markParents = inLayout ? MarkOnlyThis : MarkContainerChain; |
2407 setChildNeedsLayout(markParents); | 2536 setChildNeedsLayout(markParents); |
2408 | 2537 |
2409 if (floatToRemove) | 2538 if (floatToRemove) |
2410 removeFloatingObject(floatToRemove); | 2539 removeFloatingObject(floatToRemove); |
2411 | 2540 |
2412 // Iterate over our children and mark them as needed. If our children are inli
ne, then the | 2541 // Iterate over our children and mark them as needed. If our children are |
2413 // only boxes which could contain floats are atomic inlines (e.g. inline-block
, float etc.) and these create formatting | 2542 // inline, then the only boxes which could contain floats are atomic inlines |
2414 // contexts, so can't pick up intruding floats from ancestors/siblings - makin
g them safe to skip. | 2543 // (e.g. inline-block, float etc.) and these create formatting contexts, so |
| 2544 // can't pick up intruding floats from ancestors/siblings - making them safe |
| 2545 // to skip. |
2415 if (!childrenInline()) { | 2546 if (!childrenInline()) { |
2416 for (LayoutObject* child = firstChild(); child; | 2547 for (LayoutObject* child = firstChild(); child; |
2417 child = child->nextSibling()) { | 2548 child = child->nextSibling()) { |
2418 if ((!floatToRemove && child->isFloatingOrOutOfFlowPositioned()) || | 2549 if ((!floatToRemove && child->isFloatingOrOutOfFlowPositioned()) || |
2419 !child->isLayoutBlock()) | 2550 !child->isLayoutBlock()) |
2420 continue; | 2551 continue; |
2421 if (!child->isLayoutBlockFlow()) { | 2552 if (!child->isLayoutBlockFlow()) { |
2422 LayoutBlock* childBlock = toLayoutBlock(child); | 2553 LayoutBlock* childBlock = toLayoutBlock(child); |
2423 if (childBlock->shrinkToAvoidFloats() && childBlock->everHadLayout()) | 2554 if (childBlock->shrinkToAvoidFloats() && childBlock->everHadLayout()) |
2424 childBlock->setChildNeedsLayout(markParents); | 2555 childBlock->setChildNeedsLayout(markParents); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2459 } | 2590 } |
2460 } | 2591 } |
2461 } | 2592 } |
2462 | 2593 |
2463 LayoutUnit LayoutBlockFlow::getClearDelta(LayoutBox* child, | 2594 LayoutUnit LayoutBlockFlow::getClearDelta(LayoutBox* child, |
2464 LayoutUnit logicalTop) { | 2595 LayoutUnit logicalTop) { |
2465 // There is no need to compute clearance if we have no floats. | 2596 // There is no need to compute clearance if we have no floats. |
2466 if (!containsFloats()) | 2597 if (!containsFloats()) |
2467 return LayoutUnit(); | 2598 return LayoutUnit(); |
2468 | 2599 |
2469 // At least one float is present. We need to perform the clearance computation
. | 2600 // At least one float is present. We need to perform the clearance |
| 2601 // computation. |
2470 bool clearSet = child->style()->clear() != ClearNone; | 2602 bool clearSet = child->style()->clear() != ClearNone; |
2471 LayoutUnit logicalBottom; | 2603 LayoutUnit logicalBottom; |
2472 switch (child->style()->clear()) { | 2604 switch (child->style()->clear()) { |
2473 case ClearNone: | 2605 case ClearNone: |
2474 break; | 2606 break; |
2475 case ClearLeft: | 2607 case ClearLeft: |
2476 logicalBottom = lowestFloatLogicalBottom(FloatingObject::FloatLeft); | 2608 logicalBottom = lowestFloatLogicalBottom(FloatingObject::FloatLeft); |
2477 break; | 2609 break; |
2478 case ClearRight: | 2610 case ClearRight: |
2479 logicalBottom = lowestFloatLogicalBottom(FloatingObject::FloatRight); | 2611 logicalBottom = lowestFloatLogicalBottom(FloatingObject::FloatRight); |
2480 break; | 2612 break; |
2481 case ClearBoth: | 2613 case ClearBoth: |
2482 logicalBottom = lowestFloatLogicalBottom(); | 2614 logicalBottom = lowestFloatLogicalBottom(); |
2483 break; | 2615 break; |
2484 } | 2616 } |
2485 | 2617 |
2486 // We also clear floats if we are too big to sit on the same line as a float (
and wish to avoid floats by default). | 2618 // We also clear floats if we are too big to sit on the same line as a float |
| 2619 // (and wish to avoid floats by default). |
2487 LayoutUnit result = clearSet | 2620 LayoutUnit result = clearSet |
2488 ? (logicalBottom - logicalTop).clampNegativeToZero() | 2621 ? (logicalBottom - logicalTop).clampNegativeToZero() |
2489 : LayoutUnit(); | 2622 : LayoutUnit(); |
2490 if (!result && child->avoidsFloats()) { | 2623 if (!result && child->avoidsFloats()) { |
2491 LayoutUnit newLogicalTop = logicalTop; | 2624 LayoutUnit newLogicalTop = logicalTop; |
2492 LayoutRect borderBox = child->borderBoxRect(); | 2625 LayoutRect borderBox = child->borderBoxRect(); |
2493 LayoutUnit childLogicalWidthAtOldLogicalTopOffset = | 2626 LayoutUnit childLogicalWidthAtOldLogicalTopOffset = |
2494 isHorizontalWritingMode() ? borderBox.width() : borderBox.height(); | 2627 isHorizontalWritingMode() ? borderBox.width() : borderBox.height(); |
2495 while (true) { | 2628 while (true) { |
2496 LayoutUnit availableLogicalWidthAtNewLogicalTopOffset = | 2629 LayoutUnit availableLogicalWidthAtNewLogicalTopOffset = |
2497 availableLogicalWidthForLine(newLogicalTop, DoNotIndentText, | 2630 availableLogicalWidthForLine(newLogicalTop, DoNotIndentText, |
2498 logicalHeightForChild(*child)); | 2631 logicalHeightForChild(*child)); |
2499 if (availableLogicalWidthAtNewLogicalTopOffset == | 2632 if (availableLogicalWidthAtNewLogicalTopOffset == |
2500 availableLogicalWidthForContent()) | 2633 availableLogicalWidthForContent()) |
2501 return newLogicalTop - logicalTop; | 2634 return newLogicalTop - logicalTop; |
2502 | 2635 |
2503 LogicalExtentComputedValues computedValues; | 2636 LogicalExtentComputedValues computedValues; |
2504 child->logicalExtentAfterUpdatingLogicalWidth(newLogicalTop, | 2637 child->logicalExtentAfterUpdatingLogicalWidth(newLogicalTop, |
2505 computedValues); | 2638 computedValues); |
2506 LayoutUnit childLogicalWidthAtNewLogicalTopOffset = | 2639 LayoutUnit childLogicalWidthAtNewLogicalTopOffset = |
2507 computedValues.m_extent; | 2640 computedValues.m_extent; |
2508 | 2641 |
2509 if (childLogicalWidthAtNewLogicalTopOffset <= | 2642 if (childLogicalWidthAtNewLogicalTopOffset <= |
2510 availableLogicalWidthAtNewLogicalTopOffset) { | 2643 availableLogicalWidthAtNewLogicalTopOffset) { |
2511 // Even though we may not be moving, if the logical width did shrink bec
ause of the presence of new floats, then | 2644 // Even though we may not be moving, if the logical width did shrink |
2512 // we need to force a relayout as though we shifted. This happens becaus
e of the dynamic addition of overhanging floats | 2645 // because of the presence of new floats, then we need to force a |
2513 // from previous siblings when negative margins exist on a child (see th
e addOverhangingFloats call at the end of collapseMargins). | 2646 // relayout as though we shifted. This happens because of the dynamic |
| 2647 // addition of overhanging floats from previous siblings when negative |
| 2648 // margins exist on a child (see the addOverhangingFloats call at the |
| 2649 // end of collapseMargins). |
2514 if (childLogicalWidthAtOldLogicalTopOffset != | 2650 if (childLogicalWidthAtOldLogicalTopOffset != |
2515 childLogicalWidthAtNewLogicalTopOffset) | 2651 childLogicalWidthAtNewLogicalTopOffset) |
2516 child->setChildNeedsLayout(MarkOnlyThis); | 2652 child->setChildNeedsLayout(MarkOnlyThis); |
2517 return newLogicalTop - logicalTop; | 2653 return newLogicalTop - logicalTop; |
2518 } | 2654 } |
2519 | 2655 |
2520 newLogicalTop = nextFloatLogicalBottomBelowForBlock(newLogicalTop); | 2656 newLogicalTop = nextFloatLogicalBottomBelowForBlock(newLogicalTop); |
2521 ASSERT(newLogicalTop >= logicalTop); | 2657 ASSERT(newLogicalTop >= logicalTop); |
2522 if (newLogicalTop < logicalTop) | 2658 if (newLogicalTop < logicalTop) |
2523 break; | 2659 break; |
2524 } | 2660 } |
2525 ASSERT_NOT_REACHED(); | 2661 ASSERT_NOT_REACHED(); |
2526 } | 2662 } |
2527 return result; | 2663 return result; |
2528 } | 2664 } |
2529 | 2665 |
2530 void LayoutBlockFlow::createFloatingObjects() { | 2666 void LayoutBlockFlow::createFloatingObjects() { |
2531 m_floatingObjects = | 2667 m_floatingObjects = |
2532 wrapUnique(new FloatingObjects(this, isHorizontalWritingMode())); | 2668 wrapUnique(new FloatingObjects(this, isHorizontalWritingMode())); |
2533 } | 2669 } |
2534 | 2670 |
2535 void LayoutBlockFlow::willBeDestroyed() { | 2671 void LayoutBlockFlow::willBeDestroyed() { |
2536 // Mark as being destroyed to avoid trouble with merges in removeChild(). | 2672 // Mark as being destroyed to avoid trouble with merges in removeChild(). |
2537 m_beingDestroyed = true; | 2673 m_beingDestroyed = true; |
2538 | 2674 |
2539 // Make sure to destroy anonymous children first while they are still connecte
d to the rest of the tree, so that they will | 2675 // Make sure to destroy anonymous children first while they are still |
2540 // properly dirty line boxes that they are removed from. Effects that do :befo
re/:after only on hover could crash otherwise. | 2676 // connected to the rest of the tree, so that they will properly dirty line |
| 2677 // boxes that they are removed from. Effects that do :before/:after only on |
| 2678 // hover could crash otherwise. |
2541 children()->destroyLeftoverChildren(); | 2679 children()->destroyLeftoverChildren(); |
2542 | 2680 |
2543 // Destroy our continuation before anything other than anonymous children. | 2681 // Destroy our continuation before anything other than anonymous children. |
2544 // The reason we don't destroy it before anonymous children is that they may | 2682 // The reason we don't destroy it before anonymous children is that they may |
2545 // have continuations of their own that are anonymous children of our continua
tion. | 2683 // have continuations of their own that are anonymous children of our |
| 2684 // continuation. |
2546 LayoutBoxModelObject* continuation = this->continuation(); | 2685 LayoutBoxModelObject* continuation = this->continuation(); |
2547 if (continuation) { | 2686 if (continuation) { |
2548 continuation->destroy(); | 2687 continuation->destroy(); |
2549 setContinuation(nullptr); | 2688 setContinuation(nullptr); |
2550 } | 2689 } |
2551 | 2690 |
2552 if (!documentBeingDestroyed()) { | 2691 if (!documentBeingDestroyed()) { |
2553 // TODO(mstensho): figure out if we need this. We have no test coverage for
it. It looks | 2692 // TODO(mstensho): figure out if we need this. We have no test coverage for |
2554 // like all line boxes have been removed at this point. | 2693 // it. It looks like all line boxes have been removed at this point. |
2555 if (firstLineBox()) { | 2694 if (firstLineBox()) { |
2556 // We can't wait for LayoutBox::destroy to clear the selection, | 2695 // We can't wait for LayoutBox::destroy to clear the selection, |
2557 // because by then we will have nuked the line boxes. | 2696 // because by then we will have nuked the line boxes. |
2558 // FIXME: The FrameSelection should be responsible for this when it | 2697 // FIXME: The FrameSelection should be responsible for this when it |
2559 // is notified of DOM mutations. | 2698 // is notified of DOM mutations. |
2560 if (isSelectionBorder()) | 2699 if (isSelectionBorder()) |
2561 view()->clearSelection(); | 2700 view()->clearSelection(); |
2562 | 2701 |
2563 // If we are an anonymous block, then our line boxes might have children | 2702 // If we are an anonymous block, then our line boxes might have children |
2564 // that will outlast this block. In the non-anonymous block case those | 2703 // that will outlast this block. In the non-anonymous block case those |
(...skipping 26 matching lines...) Expand all Loading... |
2591 | 2730 |
2592 LayoutBlock::styleWillChange(diff, newStyle); | 2731 LayoutBlock::styleWillChange(diff, newStyle); |
2593 } | 2732 } |
2594 | 2733 |
2595 DISABLE_CFI_PERF | 2734 DISABLE_CFI_PERF |
2596 void LayoutBlockFlow::styleDidChange(StyleDifference diff, | 2735 void LayoutBlockFlow::styleDidChange(StyleDifference diff, |
2597 const ComputedStyle* oldStyle) { | 2736 const ComputedStyle* oldStyle) { |
2598 bool hadSelfPaintingLayer = hasSelfPaintingLayer(); | 2737 bool hadSelfPaintingLayer = hasSelfPaintingLayer(); |
2599 LayoutBlock::styleDidChange(diff, oldStyle); | 2738 LayoutBlock::styleDidChange(diff, oldStyle); |
2600 | 2739 |
2601 // After our style changed, if we lose our ability to propagate floats into ne
xt sibling | 2740 // After our style changed, if we lose our ability to propagate floats into |
2602 // blocks, then we need to find the top most parent containing that overhangin
g float and | 2741 // next sibling blocks, then we need to find the top most parent containing |
2603 // then mark its descendants with floats for layout and clear all floats from
its next | 2742 // that overhanging float and then mark its descendants with floats for layout |
2604 // sibling blocks that exist in our floating objects list. See bug 56299 and 6
2875. | 2743 // and clear all floats from its next sibling blocks that exist in our |
| 2744 // floating objects list. See crbug.com/56299 and crbug.com/62875. |
2605 bool canPropagateFloatIntoSibling = | 2745 bool canPropagateFloatIntoSibling = |
2606 !isFloatingOrOutOfFlowPositioned() && !avoidsFloats(); | 2746 !isFloatingOrOutOfFlowPositioned() && !avoidsFloats(); |
2607 bool siblingFloatPropagationChanged = | 2747 bool siblingFloatPropagationChanged = |
2608 diff.needsFullLayout() && s_canPropagateFloatIntoSibling && | 2748 diff.needsFullLayout() && s_canPropagateFloatIntoSibling && |
2609 !canPropagateFloatIntoSibling && hasOverhangingFloats(); | 2749 !canPropagateFloatIntoSibling && hasOverhangingFloats(); |
2610 | 2750 |
2611 // When this object's self-painting layer status changed, we should update Flo
atingObjects::shouldPaint() flags for | 2751 // When this object's self-painting layer status changed, we should update |
2612 // descendant overhanging floats in ancestors. | 2752 // FloatingObjects::shouldPaint() flags for descendant overhanging floats in |
| 2753 // ancestors. |
2613 bool needsUpdateAncestorFloatObjectShouldPaintFlags = false; | 2754 bool needsUpdateAncestorFloatObjectShouldPaintFlags = false; |
2614 if (hasSelfPaintingLayer() != hadSelfPaintingLayer && | 2755 if (hasSelfPaintingLayer() != hadSelfPaintingLayer && |
2615 hasOverhangingFloats()) { | 2756 hasOverhangingFloats()) { |
2616 setNeedsLayout(LayoutInvalidationReason::StyleChange); | 2757 setNeedsLayout(LayoutInvalidationReason::StyleChange); |
2617 if (hadSelfPaintingLayer) | 2758 if (hadSelfPaintingLayer) |
2618 markAllDescendantsWithFloatsForLayout(); | 2759 markAllDescendantsWithFloatsForLayout(); |
2619 else | 2760 else |
2620 needsUpdateAncestorFloatObjectShouldPaintFlags = true; | 2761 needsUpdateAncestorFloatObjectShouldPaintFlags = true; |
2621 } | 2762 } |
2622 | 2763 |
(...skipping 24 matching lines...) Expand all Loading... |
2647 parentBlockFlow->markAllDescendantsWithFloatsForLayout(); | 2788 parentBlockFlow->markAllDescendantsWithFloatsForLayout(); |
2648 if (siblingFloatPropagationChanged) | 2789 if (siblingFloatPropagationChanged) |
2649 parentBlockFlow->markSiblingsWithFloatsForLayout(); | 2790 parentBlockFlow->markSiblingsWithFloatsForLayout(); |
2650 } | 2791 } |
2651 | 2792 |
2652 if (diff.needsFullLayout() || !oldStyle) | 2793 if (diff.needsFullLayout() || !oldStyle) |
2653 createOrDestroyMultiColumnFlowThreadIfNeeded(oldStyle); | 2794 createOrDestroyMultiColumnFlowThreadIfNeeded(oldStyle); |
2654 if (oldStyle) { | 2795 if (oldStyle) { |
2655 if (LayoutMultiColumnFlowThread* flowThread = multiColumnFlowThread()) { | 2796 if (LayoutMultiColumnFlowThread* flowThread = multiColumnFlowThread()) { |
2656 if (!style()->columnRuleEquivalent(oldStyle)) { | 2797 if (!style()->columnRuleEquivalent(oldStyle)) { |
2657 // Column rules are painted by anonymous column set children of the mult
icol | 2798 // Column rules are painted by anonymous column set children of the |
2658 // container. We need to notify them. | 2799 // multicol container. We need to notify them. |
2659 flowThread->columnRuleStyleDidChange(); | 2800 flowThread->columnRuleStyleDidChange(); |
2660 } | 2801 } |
2661 } | 2802 } |
2662 } | 2803 } |
2663 } | 2804 } |
2664 | 2805 |
2665 void LayoutBlockFlow::updateBlockChildDirtyBitsBeforeLayout( | 2806 void LayoutBlockFlow::updateBlockChildDirtyBitsBeforeLayout( |
2666 bool relayoutChildren, | 2807 bool relayoutChildren, |
2667 LayoutBox& child) { | 2808 LayoutBox& child) { |
2668 if (child.isLayoutMultiColumnSpannerPlaceholder()) | 2809 if (child.isLayoutMultiColumnSpannerPlaceholder()) |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2704 return; | 2845 return; |
2705 } | 2846 } |
2706 | 2847 |
2707 if (beforeChild && beforeChild->parent() != this) { | 2848 if (beforeChild && beforeChild->parent() != this) { |
2708 addChildBeforeDescendant(newChild, beforeChild); | 2849 addChildBeforeDescendant(newChild, beforeChild); |
2709 return; | 2850 return; |
2710 } | 2851 } |
2711 | 2852 |
2712 bool madeBoxesNonInline = false; | 2853 bool madeBoxesNonInline = false; |
2713 | 2854 |
2714 // A block has to either have all of its children inline, or all of its childr
en as blocks. | 2855 // A block has to either have all of its children inline, or all of its |
2715 // So, if our children are currently inline and a block child has to be insert
ed, we move all our | 2856 // children as blocks. |
2716 // inline children into anonymous block boxes. | 2857 // So, if our children are currently inline and a block child has to be |
| 2858 // inserted, we move all our inline children into anonymous block boxes. |
2717 bool childIsBlockLevel = | 2859 bool childIsBlockLevel = |
2718 !newChild->isInline() && !newChild->isFloatingOrOutOfFlowPositioned(); | 2860 !newChild->isInline() && !newChild->isFloatingOrOutOfFlowPositioned(); |
2719 if (childrenInline()) { | 2861 if (childrenInline()) { |
2720 if (childIsBlockLevel) { | 2862 if (childIsBlockLevel) { |
2721 // Wrap the inline content in anonymous blocks, to allow for the new block
child to be | 2863 // Wrap the inline content in anonymous blocks, to allow for the new block |
2722 // inserted. | 2864 // child to be inserted. |
2723 makeChildrenNonInline(beforeChild); | 2865 makeChildrenNonInline(beforeChild); |
2724 madeBoxesNonInline = true; | 2866 madeBoxesNonInline = true; |
2725 | 2867 |
2726 if (beforeChild && beforeChild->parent() != this) { | 2868 if (beforeChild && beforeChild->parent() != this) { |
2727 beforeChild = beforeChild->parent(); | 2869 beforeChild = beforeChild->parent(); |
2728 ASSERT(beforeChild->isAnonymousBlock()); | 2870 ASSERT(beforeChild->isAnonymousBlock()); |
2729 ASSERT(beforeChild->parent() == this); | 2871 ASSERT(beforeChild->parent() == this); |
2730 } | 2872 } |
2731 } | 2873 } |
2732 } else if (!childIsBlockLevel) { | 2874 } else if (!childIsBlockLevel) { |
2733 // This block has block children. We may want to put the new child into an a
nomyous | 2875 // This block has block children. We may want to put the new child into an |
2734 // block. Floats and out-of-flow children may live among either block or inl
ine children, | 2876 // anomyous block. Floats and out-of-flow children may live among either |
2735 // so for such children, only put them inside an anonymous block if one alre
ady exists. If | 2877 // block or inline children, so for such children, only put them inside an |
2736 // the child is inline, on the other hand, we *have to* put it inside an ano
nymous block, | 2878 // anonymous block if one already exists. If the child is inline, on the |
2737 // so create a new one if there is none for us there already. | 2879 // other hand, we *have to* put it inside an anonymous block, so create a |
| 2880 // new one if there is none for us there already. |
2738 LayoutObject* afterChild = | 2881 LayoutObject* afterChild = |
2739 beforeChild ? beforeChild->previousSibling() : lastChild(); | 2882 beforeChild ? beforeChild->previousSibling() : lastChild(); |
2740 | 2883 |
2741 if (afterChild && afterChild->isAnonymousBlock()) { | 2884 if (afterChild && afterChild->isAnonymousBlock()) { |
2742 afterChild->addChild(newChild); | 2885 afterChild->addChild(newChild); |
2743 return; | 2886 return; |
2744 } | 2887 } |
2745 | 2888 |
2746 if (newChild->isInline()) { | 2889 if (newChild->isInline()) { |
2747 // No suitable existing anonymous box - create a new one. | 2890 // No suitable existing anonymous box - create a new one. |
2748 LayoutBlockFlow* newBlock = toLayoutBlockFlow(createAnonymousBlock()); | 2891 LayoutBlockFlow* newBlock = toLayoutBlockFlow(createAnonymousBlock()); |
2749 LayoutBox::addChild(newBlock, beforeChild); | 2892 LayoutBox::addChild(newBlock, beforeChild); |
2750 // Reparent adjacent floating or out-of-flow siblings to the new box. | 2893 // Reparent adjacent floating or out-of-flow siblings to the new box. |
2751 newBlock->reparentPrecedingFloatingOrOutOfFlowSiblings(); | 2894 newBlock->reparentPrecedingFloatingOrOutOfFlowSiblings(); |
2752 newBlock->addChild(newChild); | 2895 newBlock->addChild(newChild); |
2753 newBlock->reparentSubsequentFloatingOrOutOfFlowSiblings(); | 2896 newBlock->reparentSubsequentFloatingOrOutOfFlowSiblings(); |
2754 return; | 2897 return; |
2755 } | 2898 } |
2756 } | 2899 } |
2757 | 2900 |
2758 // Skip the LayoutBlock override, since that one deals with anonymous child in
sertion in a way | 2901 // Skip the LayoutBlock override, since that one deals with anonymous child |
2759 // that isn't sufficient for us, and can only cause trouble at this point. | 2902 // insertion in a way that isn't sufficient for us, and can only cause trouble |
| 2903 // at this point. |
2760 LayoutBox::addChild(newChild, beforeChild); | 2904 LayoutBox::addChild(newChild, beforeChild); |
2761 | 2905 |
2762 if (madeBoxesNonInline && parent() && isAnonymousBlock() && | 2906 if (madeBoxesNonInline && parent() && isAnonymousBlock() && |
2763 parent()->isLayoutBlock() && !parent()->createsAnonymousWrapper()) { | 2907 parent()->isLayoutBlock() && !parent()->createsAnonymousWrapper()) { |
2764 toLayoutBlock(parent())->removeLeftoverAnonymousBlock(this); | 2908 toLayoutBlock(parent())->removeLeftoverAnonymousBlock(this); |
2765 // |this| may be dead now. | 2909 // |this| may be dead now. |
2766 } | 2910 } |
2767 } | 2911 } |
2768 | 2912 |
2769 static bool isMergeableAnonymousBlock(const LayoutBlockFlow* block) { | 2913 static bool isMergeableAnonymousBlock(const LayoutBlockFlow* block) { |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2839 ASSERT_NOT_REACHED(); | 2983 ASSERT_NOT_REACHED(); |
2840 | 2984 |
2841 break; | 2985 break; |
2842 } | 2986 } |
2843 setContinuation(nullptr); | 2987 setContinuation(nullptr); |
2844 destroy(); | 2988 destroy(); |
2845 } | 2989 } |
2846 } else if (!beingDestroyed() && | 2990 } else if (!beingDestroyed() && |
2847 !oldChild->isFloatingOrOutOfFlowPositioned() && | 2991 !oldChild->isFloatingOrOutOfFlowPositioned() && |
2848 !oldChild->isAnonymousBlock()) { | 2992 !oldChild->isAnonymousBlock()) { |
2849 // If the child we're removing means that we can now treat all children as i
nline without the need for anonymous blocks, then do that. | 2993 // If the child we're removing means that we can now treat all children as |
| 2994 // inline without the need for anonymous blocks, then do that. |
2850 makeChildrenInlineIfPossible(); | 2995 makeChildrenInlineIfPossible(); |
2851 } | 2996 } |
2852 } | 2997 } |
2853 | 2998 |
2854 void LayoutBlockFlow::moveAllChildrenIncludingFloatsTo(LayoutBlock* toBlock, | 2999 void LayoutBlockFlow::moveAllChildrenIncludingFloatsTo(LayoutBlock* toBlock, |
2855 bool fullRemoveInsert) { | 3000 bool fullRemoveInsert) { |
2856 LayoutBlockFlow* toBlockFlow = toLayoutBlockFlow(toBlock); | 3001 LayoutBlockFlow* toBlockFlow = toLayoutBlockFlow(toBlock); |
2857 moveAllChildrenTo(toBlockFlow, fullRemoveInsert); | 3002 moveAllChildrenTo(toBlockFlow, fullRemoveInsert); |
2858 | 3003 |
2859 // When a portion of the layout tree is being detached, anonymous blocks | 3004 // When a portion of the layout tree is being detached, anonymous blocks |
2860 // will be combined as their children are deleted. In this process, the | 3005 // will be combined as their children are deleted. In this process, the |
2861 // anonymous block later in the tree is merged into the one preceding it. | 3006 // anonymous block later in the tree is merged into the one preceding it. |
2862 // It can happen that the later block (this) contains floats that the | 3007 // It can happen that the later block (this) contains floats that the |
2863 // previous block (toBlockFlow) did not contain, and thus are not in the | 3008 // previous block (toBlockFlow) did not contain, and thus are not in the |
2864 // floating objects list for toBlockFlow. This can result in toBlockFlow conta
ining | 3009 // floating objects list for toBlockFlow. This can result in toBlockFlow |
2865 // floats that are not in it's floating objects list, but are in the | 3010 // containing floats that are not in it's floating objects list, but are in |
2866 // floating objects lists of siblings and parents. This can cause problems | 3011 // the floating objects lists of siblings and parents. This can cause problems |
2867 // when the float itself is deleted, since the deletion code assumes that | 3012 // when the float itself is deleted, since the deletion code assumes that if a |
2868 // if a float is not in it's containing block's floating objects list, it | 3013 // float is not in it's containing block's floating objects list, it isn't in |
2869 // isn't in any floating objects list. In order to preserve this condition | 3014 // any floating objects list. In order to preserve this condition (removing it |
2870 // (removing it has serious performance implications), we need to copy the | 3015 // has serious performance implications), we need to copy the floating objects |
2871 // floating objects from the old block (this) to the new block (toBlockFlow). | 3016 // from the old block (this) to the new block (toBlockFlow). |
2872 // The float's metrics will likely all be wrong, but since toBlockFlow is | 3017 // The float's metrics will likely all be wrong, but since toBlockFlow is |
2873 // already marked for layout, this will get fixed before anything gets | 3018 // already marked for layout, this will get fixed before anything gets |
2874 // displayed. | 3019 // displayed. |
2875 // See bug https://code.google.com/p/chromium/issues/detail?id=230907 | 3020 // See bug https://code.google.com/p/chromium/issues/detail?id=230907 |
2876 if (m_floatingObjects) { | 3021 if (m_floatingObjects) { |
2877 if (!toBlockFlow->m_floatingObjects) | 3022 if (!toBlockFlow->m_floatingObjects) |
2878 toBlockFlow->createFloatingObjects(); | 3023 toBlockFlow->createFloatingObjects(); |
2879 | 3024 |
2880 const FloatingObjectSet& fromFloatingObjectSet = m_floatingObjects->set(); | 3025 const FloatingObjectSet& fromFloatingObjectSet = m_floatingObjects->set(); |
2881 FloatingObjectSetIterator end = fromFloatingObjectSet.end(); | 3026 FloatingObjectSetIterator end = fromFloatingObjectSet.end(); |
(...skipping 12 matching lines...) Expand all Loading... |
2894 } | 3039 } |
2895 | 3040 |
2896 void LayoutBlockFlow::childBecameFloatingOrOutOfFlow(LayoutBox* child) { | 3041 void LayoutBlockFlow::childBecameFloatingOrOutOfFlow(LayoutBox* child) { |
2897 makeChildrenInlineIfPossible(); | 3042 makeChildrenInlineIfPossible(); |
2898 | 3043 |
2899 // Reparent the child to an adjacent anonymous block if one is available. | 3044 // Reparent the child to an adjacent anonymous block if one is available. |
2900 LayoutObject* prev = child->previousSibling(); | 3045 LayoutObject* prev = child->previousSibling(); |
2901 if (prev && prev->isAnonymousBlock() && prev->isLayoutBlockFlow()) { | 3046 if (prev && prev->isAnonymousBlock() && prev->isLayoutBlockFlow()) { |
2902 LayoutBlockFlow* newContainer = toLayoutBlockFlow(prev); | 3047 LayoutBlockFlow* newContainer = toLayoutBlockFlow(prev); |
2903 moveChildTo(newContainer, child, nullptr, false); | 3048 moveChildTo(newContainer, child, nullptr, false); |
2904 // The anonymous block we've moved to may now be adjacent to former siblings
of ours | 3049 // The anonymous block we've moved to may now be adjacent to former siblings |
2905 // that it can contain also. | 3050 // of ours that it can contain also. |
2906 newContainer->reparentSubsequentFloatingOrOutOfFlowSiblings(); | 3051 newContainer->reparentSubsequentFloatingOrOutOfFlowSiblings(); |
2907 return; | 3052 return; |
2908 } | 3053 } |
2909 LayoutObject* next = child->nextSibling(); | 3054 LayoutObject* next = child->nextSibling(); |
2910 if (next && next->isAnonymousBlock() && next->isLayoutBlockFlow()) { | 3055 if (next && next->isAnonymousBlock() && next->isLayoutBlockFlow()) { |
2911 LayoutBlockFlow* newContainer = toLayoutBlockFlow(next); | 3056 LayoutBlockFlow* newContainer = toLayoutBlockFlow(next); |
2912 moveChildTo(newContainer, child, newContainer->firstChild(), false); | 3057 moveChildTo(newContainer, child, newContainer->firstChild(), false); |
2913 } | 3058 } |
2914 } | 3059 } |
2915 | 3060 |
2916 void LayoutBlockFlow::collapseAnonymousBlockChild(LayoutBlockFlow* child) { | 3061 void LayoutBlockFlow::collapseAnonymousBlockChild(LayoutBlockFlow* child) { |
2917 // It's possible that this block's destruction may have been triggered by the | 3062 // It's possible that this block's destruction may have been triggered by the |
2918 // child's removal. Just bail if the anonymous child block is already being | 3063 // child's removal. Just bail if the anonymous child block is already being |
2919 // destroyed. See crbug.com/282088 | 3064 // destroyed. See crbug.com/282088 |
2920 if (child->beingDestroyed()) | 3065 if (child->beingDestroyed()) |
2921 return; | 3066 return; |
2922 if (child->continuation()) | 3067 if (child->continuation()) |
2923 return; | 3068 return; |
2924 // Ruby elements use anonymous wrappers for ruby runs and ruby bases by design
, so we don't remove them. | 3069 // Ruby elements use anonymous wrappers for ruby runs and ruby bases by |
| 3070 // design, so we don't remove them. |
2925 if (child->isRubyRun() || child->isRubyBase()) | 3071 if (child->isRubyRun() || child->isRubyBase()) |
2926 return; | 3072 return; |
2927 setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation( | 3073 setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation( |
2928 LayoutInvalidationReason::ChildAnonymousBlockChanged); | 3074 LayoutInvalidationReason::ChildAnonymousBlockChanged); |
2929 | 3075 |
2930 child->moveAllChildrenTo(this, child->nextSibling(), child->hasLayer()); | 3076 child->moveAllChildrenTo(this, child->nextSibling(), child->hasLayer()); |
2931 setChildrenInline(child->childrenInline()); | 3077 setChildrenInline(child->childrenInline()); |
2932 | 3078 |
2933 children()->removeChildNode(this, child, child->hasLayer()); | 3079 children()->removeChildNode(this, child, child->hasLayer()); |
2934 child->destroy(); | 3080 child->destroy(); |
2935 } | 3081 } |
2936 | 3082 |
2937 bool LayoutBlockFlow::mergeSiblingContiguousAnonymousBlock( | 3083 bool LayoutBlockFlow::mergeSiblingContiguousAnonymousBlock( |
2938 LayoutBlockFlow* siblingThatMayBeDeleted) { | 3084 LayoutBlockFlow* siblingThatMayBeDeleted) { |
2939 // Note: |this| and |siblingThatMayBeDeleted| may not be adjacent siblings at
this point. There | 3085 // Note: |this| and |siblingThatMayBeDeleted| may not be adjacent siblings at |
2940 // may be an object between them which is about to be removed. | 3086 // this point. There may be an object between them which is about to be |
| 3087 // removed. |
2941 | 3088 |
2942 if (!isMergeableAnonymousBlock(this) || | 3089 if (!isMergeableAnonymousBlock(this) || |
2943 !isMergeableAnonymousBlock(siblingThatMayBeDeleted)) | 3090 !isMergeableAnonymousBlock(siblingThatMayBeDeleted)) |
2944 return false; | 3091 return false; |
2945 | 3092 |
2946 setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation( | 3093 setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation( |
2947 LayoutInvalidationReason::AnonymousBlockChange); | 3094 LayoutInvalidationReason::AnonymousBlockChange); |
2948 | 3095 |
2949 // If the inlineness of children of the two block don't match, we'd need speci
al code here | 3096 // If the inlineness of children of the two block don't match, we'd need |
2950 // (but there should be no need for it). | 3097 // special code here (but there should be no need for it). |
2951 ASSERT(siblingThatMayBeDeleted->childrenInline() == childrenInline()); | 3098 ASSERT(siblingThatMayBeDeleted->childrenInline() == childrenInline()); |
2952 // Take all the children out of the |next| block and put them in | 3099 // Take all the children out of the |next| block and put them in |
2953 // the |prev| block. | 3100 // the |prev| block. |
2954 siblingThatMayBeDeleted->moveAllChildrenIncludingFloatsTo( | 3101 siblingThatMayBeDeleted->moveAllChildrenIncludingFloatsTo( |
2955 this, siblingThatMayBeDeleted->hasLayer() || hasLayer()); | 3102 this, siblingThatMayBeDeleted->hasLayer() || hasLayer()); |
2956 // Delete the now-empty block's lines and nuke it. | 3103 // Delete the now-empty block's lines and nuke it. |
2957 siblingThatMayBeDeleted->deleteLineBoxTree(); | 3104 siblingThatMayBeDeleted->deleteLineBoxTree(); |
2958 siblingThatMayBeDeleted->destroy(); | 3105 siblingThatMayBeDeleted->destroy(); |
2959 return true; | 3106 return true; |
2960 } | 3107 } |
(...skipping 25 matching lines...) Expand all Loading... |
2986 LayoutBlockFlow* parentBlockFlow = toLayoutBlockFlow(parent()); | 3133 LayoutBlockFlow* parentBlockFlow = toLayoutBlockFlow(parent()); |
2987 LayoutObject* child = previousSibling(); | 3134 LayoutObject* child = previousSibling(); |
2988 while (child && child->isFloatingOrOutOfFlowPositioned()) { | 3135 while (child && child->isFloatingOrOutOfFlowPositioned()) { |
2989 LayoutObject* sibling = child->previousSibling(); | 3136 LayoutObject* sibling = child->previousSibling(); |
2990 parentBlockFlow->moveChildTo(this, child, firstChild(), false); | 3137 parentBlockFlow->moveChildTo(this, child, firstChild(), false); |
2991 child = sibling; | 3138 child = sibling; |
2992 } | 3139 } |
2993 } | 3140 } |
2994 | 3141 |
2995 void LayoutBlockFlow::makeChildrenInlineIfPossible() { | 3142 void LayoutBlockFlow::makeChildrenInlineIfPossible() { |
2996 // Collapsing away anonymous wrappers isn't relevant for the children of anony
mous blocks, unless they are ruby bases. | 3143 // Collapsing away anonymous wrappers isn't relevant for the children of |
| 3144 // anonymous blocks, unless they are ruby bases. |
2997 if (isAnonymousBlock() && !isRubyBase()) | 3145 if (isAnonymousBlock() && !isRubyBase()) |
2998 return; | 3146 return; |
2999 | 3147 |
3000 Vector<LayoutBlockFlow*, 3> blocksToRemove; | 3148 Vector<LayoutBlockFlow*, 3> blocksToRemove; |
3001 for (LayoutObject* child = firstChild(); child; | 3149 for (LayoutObject* child = firstChild(); child; |
3002 child = child->nextSibling()) { | 3150 child = child->nextSibling()) { |
3003 if (child->isFloating()) | 3151 if (child->isFloating()) |
3004 continue; | 3152 continue; |
3005 if (child->isOutOfFlowPositioned()) | 3153 if (child->isOutOfFlowPositioned()) |
3006 continue; | 3154 continue; |
3007 | 3155 |
3008 // There are still block children in the container, so any anonymous wrapper
s are still needed. | 3156 // There are still block children in the container, so any anonymous |
| 3157 // wrappers are still needed. |
3009 if (!child->isAnonymousBlock() || !child->isLayoutBlockFlow()) | 3158 if (!child->isAnonymousBlock() || !child->isLayoutBlockFlow()) |
3010 return; | 3159 return; |
3011 // If one of the children is being destroyed then it is unsafe to clean up a
nonymous wrappers as the | 3160 // If one of the children is being destroyed then it is unsafe to clean up |
| 3161 // anonymous wrappers as the |
3012 // entire branch may be being destroyed. | 3162 // entire branch may be being destroyed. |
3013 if (toLayoutBlockFlow(child)->beingDestroyed()) | 3163 if (toLayoutBlockFlow(child)->beingDestroyed()) |
3014 return; | 3164 return; |
3015 // We can't remove anonymous wrappers if they contain continuations as this
means there are block children present. | 3165 // We can't remove anonymous wrappers if they contain continuations as this |
| 3166 // means there are block children present. |
3016 if (toLayoutBlockFlow(child)->continuation()) | 3167 if (toLayoutBlockFlow(child)->continuation()) |
3017 return; | 3168 return; |
3018 // We are only interested in removing anonymous wrappers if there are inline
siblings underneath them. | 3169 // We are only interested in removing anonymous wrappers if there are inline |
| 3170 // siblings underneath them. |
3019 if (!child->childrenInline()) | 3171 if (!child->childrenInline()) |
3020 return; | 3172 return; |
3021 // Ruby elements use anonymous wrappers for ruby runs and ruby bases by desi
gn, so we don't remove them. | 3173 // Ruby elements use anonymous wrappers for ruby runs and ruby bases by |
| 3174 // design, so we don't remove them. |
3022 if (child->isRubyRun() || child->isRubyBase()) | 3175 if (child->isRubyRun() || child->isRubyBase()) |
3023 return; | 3176 return; |
3024 | 3177 |
3025 blocksToRemove.append(toLayoutBlockFlow(child)); | 3178 blocksToRemove.append(toLayoutBlockFlow(child)); |
3026 } | 3179 } |
3027 | 3180 |
3028 // If we make an object's children inline we are going to frustrate any future
attempts to remove | 3181 // If we make an object's children inline we are going to frustrate any future |
3029 // floats from its children's float-lists before the next layout happens so cl
ear down all the floatlists | 3182 // attempts to remove floats from its children's float-lists before the next |
3030 // now - they will be rebuilt at layout. | 3183 // layout happens so clear down all the floatlists now - they will be rebuilt |
| 3184 // at layout. |
3031 removeFloatingObjectsFromDescendants(); | 3185 removeFloatingObjectsFromDescendants(); |
3032 | 3186 |
3033 for (size_t i = 0; i < blocksToRemove.size(); i++) | 3187 for (size_t i = 0; i < blocksToRemove.size(); i++) |
3034 collapseAnonymousBlockChild(blocksToRemove[i]); | 3188 collapseAnonymousBlockChild(blocksToRemove[i]); |
3035 setChildrenInline(true); | 3189 setChildrenInline(true); |
3036 } | 3190 } |
3037 | 3191 |
3038 static void getInlineRun(LayoutObject* start, | 3192 static void getInlineRun(LayoutObject* start, |
3039 LayoutObject* boundary, | 3193 LayoutObject* boundary, |
3040 LayoutObject*& inlineRunStart, | 3194 LayoutObject*& inlineRunStart, |
3041 LayoutObject*& inlineRunEnd) { | 3195 LayoutObject*& inlineRunEnd) { |
3042 // Beginning at |start| we find the largest contiguous run of inlines that | 3196 // Beginning at |start| we find the largest contiguous run of inlines that |
3043 // we can. We denote the run with start and end points, |inlineRunStart| | 3197 // we can. We denote the run with start and end points, |inlineRunStart| |
3044 // and |inlineRunEnd|. Note that these two values may be the same if | 3198 // and |inlineRunEnd|. Note that these two values may be the same if |
3045 // we encounter only one inline. | 3199 // we encounter only one inline. |
3046 // | 3200 // |
3047 // We skip any non-inlines we encounter as long as we haven't found any | 3201 // We skip any non-inlines we encounter as long as we haven't found any |
3048 // inlines yet. | 3202 // inlines yet. |
3049 // | 3203 // |
3050 // |boundary| indicates a non-inclusive boundary point. Regardless of whether
|boundary| | 3204 // |boundary| indicates a non-inclusive boundary point. Regardless of whether |
3051 // is inline or not, we will not include it in a run with inlines before it.
It's as though we encountered | 3205 // |boundary| is inline or not, we will not include it in a run with inlines |
3052 // a non-inline. | 3206 // before it. It's as though we encountered a non-inline. |
3053 | 3207 |
3054 // Start by skipping as many non-inlines as we can. | 3208 // Start by skipping as many non-inlines as we can. |
3055 LayoutObject* curr = start; | 3209 LayoutObject* curr = start; |
3056 bool sawInline; | 3210 bool sawInline; |
3057 do { | 3211 do { |
3058 while (curr && | 3212 while (curr && |
3059 !(curr->isInline() || curr->isFloatingOrOutOfFlowPositioned())) | 3213 !(curr->isInline() || curr->isFloatingOrOutOfFlowPositioned())) |
3060 curr = curr->nextSibling(); | 3214 curr = curr->nextSibling(); |
3061 | 3215 |
3062 inlineRunStart = inlineRunEnd = curr; | 3216 inlineRunStart = inlineRunEnd = curr; |
(...skipping 10 matching lines...) Expand all Loading... |
3073 inlineRunEnd = curr; | 3227 inlineRunEnd = curr; |
3074 if (curr->isInline()) | 3228 if (curr->isInline()) |
3075 sawInline = true; | 3229 sawInline = true; |
3076 curr = curr->nextSibling(); | 3230 curr = curr->nextSibling(); |
3077 } | 3231 } |
3078 } while (!sawInline); | 3232 } while (!sawInline); |
3079 } | 3233 } |
3080 | 3234 |
3081 void LayoutBlockFlow::makeChildrenNonInline(LayoutObject* insertionPoint) { | 3235 void LayoutBlockFlow::makeChildrenNonInline(LayoutObject* insertionPoint) { |
3082 // makeChildrenNonInline takes a block whose children are *all* inline and it | 3236 // makeChildrenNonInline takes a block whose children are *all* inline and it |
3083 // makes sure that inline children are coalesced under anonymous | 3237 // makes sure that inline children are coalesced under anonymous blocks. |
3084 // blocks. If |insertionPoint| is defined, then it represents the insertion p
oint for | 3238 // If |insertionPoint| is defined, then it represents the insertion point for |
3085 // the new block child that is causing us to have to wrap all the inlines. Th
is | 3239 // the new block child that is causing us to have to wrap all the inlines. |
3086 // means that we cannot coalesce inlines before |insertionPoint| with inlines
following | 3240 // This means that we cannot coalesce inlines before |insertionPoint| with |
3087 // |insertionPoint|, because the new child is going to be inserted in between
the inlines, | 3241 // inlines following |insertionPoint|, because the new child is going to be |
3088 // splitting them. | 3242 // inserted in between the inlines, splitting them. |
3089 ASSERT(!isInline() || isAtomicInlineLevel()); | 3243 ASSERT(!isInline() || isAtomicInlineLevel()); |
3090 ASSERT(!insertionPoint || insertionPoint->parent() == this); | 3244 ASSERT(!insertionPoint || insertionPoint->parent() == this); |
3091 | 3245 |
3092 setChildrenInline(false); | 3246 setChildrenInline(false); |
3093 | 3247 |
3094 LayoutObject* child = firstChild(); | 3248 LayoutObject* child = firstChild(); |
3095 if (!child) | 3249 if (!child) |
3096 return; | 3250 return; |
3097 | 3251 |
3098 deleteLineBoxTree(); | 3252 deleteLineBoxTree(); |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3161 | 3315 |
3162 m_floatingObjects->clear(); | 3316 m_floatingObjects->clear(); |
3163 } | 3317 } |
3164 | 3318 |
3165 LayoutPoint LayoutBlockFlow::flipFloatForWritingModeForChild( | 3319 LayoutPoint LayoutBlockFlow::flipFloatForWritingModeForChild( |
3166 const FloatingObject& child, | 3320 const FloatingObject& child, |
3167 const LayoutPoint& point) const { | 3321 const LayoutPoint& point) const { |
3168 if (!style()->isFlippedBlocksWritingMode()) | 3322 if (!style()->isFlippedBlocksWritingMode()) |
3169 return point; | 3323 return point; |
3170 | 3324 |
3171 // This is similar to LayoutBox::flipForWritingModeForChild. We have to subtra
ct out our left offsets twice, since | 3325 // This is similar to LayoutBox::flipForWritingModeForChild. We have to |
3172 // it's going to get added back in. We hide this complication here so that the
calling code looks normal for the unflipped | 3326 // subtract out our left offsets twice, since it's going to get added back in. |
3173 // case. | 3327 // We hide this complication here so that the calling code looks normal for |
| 3328 // the unflipped case. |
3174 return LayoutPoint(point.x() + size().width() - | 3329 return LayoutPoint(point.x() + size().width() - |
3175 child.layoutObject()->size().width() - | 3330 child.layoutObject()->size().width() - |
3176 2 * xPositionForFloatIncludingMargin(child), | 3331 2 * xPositionForFloatIncludingMargin(child), |
3177 point.y()); | 3332 point.y()); |
3178 } | 3333 } |
3179 | 3334 |
3180 LayoutUnit LayoutBlockFlow::logicalLeftOffsetForPositioningFloat( | 3335 LayoutUnit LayoutBlockFlow::logicalLeftOffsetForPositioningFloat( |
3181 LayoutUnit logicalTop, | 3336 LayoutUnit logicalTop, |
3182 LayoutUnit fixedOffset, | 3337 LayoutUnit fixedOffset, |
3183 LayoutUnit* heightRemaining) const { | 3338 LayoutUnit* heightRemaining) const { |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3306 FloatingObjectSetIterator it = | 3461 FloatingObjectSetIterator it = |
3307 floatingObjectSet.find<FloatingObjectHashTranslator>(&floatBox); | 3462 floatingObjectSet.find<FloatingObjectHashTranslator>(&floatBox); |
3308 if (it != floatingObjectSet.end()) | 3463 if (it != floatingObjectSet.end()) |
3309 return it->get(); | 3464 return it->get(); |
3310 } | 3465 } |
3311 | 3466 |
3312 // Create the special object entry & append it to the list | 3467 // Create the special object entry & append it to the list |
3313 | 3468 |
3314 std::unique_ptr<FloatingObject> newObj = FloatingObject::create(&floatBox); | 3469 std::unique_ptr<FloatingObject> newObj = FloatingObject::create(&floatBox); |
3315 | 3470 |
3316 // Our location is irrelevant if we're unsplittable or no pagination is in eff
ect. | 3471 // Our location is irrelevant if we're unsplittable or no pagination is in |
3317 // Just go ahead and lay out the float. | 3472 // effect. Just go ahead and lay out the float. |
3318 bool isChildLayoutBlock = floatBox.isLayoutBlock(); | 3473 bool isChildLayoutBlock = floatBox.isLayoutBlock(); |
3319 if (isChildLayoutBlock && !floatBox.needsLayout() && | 3474 if (isChildLayoutBlock && !floatBox.needsLayout() && |
3320 view()->layoutState()->pageLogicalHeightChanged()) | 3475 view()->layoutState()->pageLogicalHeightChanged()) |
3321 floatBox.setChildNeedsLayout(MarkOnlyThis); | 3476 floatBox.setChildNeedsLayout(MarkOnlyThis); |
3322 | 3477 |
3323 floatBox.layoutIfNeeded(); | 3478 floatBox.layoutIfNeeded(); |
3324 | 3479 |
3325 setLogicalWidthForFloat(*newObj, logicalWidthForChild(floatBox) + | 3480 setLogicalWidthForFloat(*newObj, logicalWidthForChild(floatBox) + |
3326 marginStartForChild(floatBox) + | 3481 marginStartForChild(floatBox) + |
3327 marginEndForChild(floatBox)); | 3482 marginEndForChild(floatBox)); |
(...skipping 10 matching lines...) Expand all Loading... |
3338 FloatingObject& floatingObject = *it->get(); | 3493 FloatingObject& floatingObject = *it->get(); |
3339 if (childrenInline()) { | 3494 if (childrenInline()) { |
3340 LayoutUnit logicalTop = logicalTopForFloat(floatingObject); | 3495 LayoutUnit logicalTop = logicalTopForFloat(floatingObject); |
3341 LayoutUnit logicalBottom = logicalBottomForFloat(floatingObject); | 3496 LayoutUnit logicalBottom = logicalBottomForFloat(floatingObject); |
3342 | 3497 |
3343 // Fix for https://bugs.webkit.org/show_bug.cgi?id=54995. | 3498 // Fix for https://bugs.webkit.org/show_bug.cgi?id=54995. |
3344 if (logicalBottom < 0 || logicalBottom < logicalTop || | 3499 if (logicalBottom < 0 || logicalBottom < logicalTop || |
3345 logicalTop == LayoutUnit::max()) { | 3500 logicalTop == LayoutUnit::max()) { |
3346 logicalBottom = LayoutUnit::max(); | 3501 logicalBottom = LayoutUnit::max(); |
3347 } else { | 3502 } else { |
3348 // Special-case zero- and less-than-zero-height floats: those don't to
uch | 3503 // Special-case zero- and less-than-zero-height floats: those don't |
3349 // the line that they're on, but it still needs to be dirtied. This is | 3504 // touch the line that they're on, but it still needs to be dirtied. |
3350 // accomplished by pretending they have a height of 1. | 3505 // This is accomplished by pretending they have a height of 1. |
3351 logicalBottom = std::max(logicalBottom, logicalTop + 1); | 3506 logicalBottom = std::max(logicalBottom, logicalTop + 1); |
3352 } | 3507 } |
3353 if (floatingObject.originatingLine()) { | 3508 if (floatingObject.originatingLine()) { |
3354 if (!selfNeedsLayout()) { | 3509 if (!selfNeedsLayout()) { |
3355 ASSERT( | 3510 ASSERT( |
3356 floatingObject.originatingLine()->getLineLayoutItem().isEqual( | 3511 floatingObject.originatingLine()->getLineLayoutItem().isEqual( |
3357 this)); | 3512 this)); |
3358 floatingObject.originatingLine()->markDirty(); | 3513 floatingObject.originatingLine()->markDirty(); |
3359 } | 3514 } |
3360 #if ENABLE(ASSERT) | 3515 #if ENABLE(ASSERT) |
(...skipping 28 matching lines...) Expand all Loading... |
3389 return false; | 3544 return false; |
3390 | 3545 |
3391 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); | 3546 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); |
3392 if (floatingObjectSet.isEmpty()) | 3547 if (floatingObjectSet.isEmpty()) |
3393 return false; | 3548 return false; |
3394 | 3549 |
3395 // If all floats have already been positioned, then we have no work to do. | 3550 // If all floats have already been positioned, then we have no work to do. |
3396 if (floatingObjectSet.last()->isPlaced()) | 3551 if (floatingObjectSet.last()->isPlaced()) |
3397 return false; | 3552 return false; |
3398 | 3553 |
3399 // Move backwards through our floating object list until we find a float that
has | 3554 // Move backwards through our floating object list until we find a float that |
3400 // already been positioned. Then we'll be able to move forward, positioning al
l of | 3555 // has already been positioned. Then we'll be able to move forward, |
3401 // the new floats that need it. | 3556 // positioning all of the new floats that need it. |
3402 FloatingObjectSetIterator it = floatingObjectSet.end(); | 3557 FloatingObjectSetIterator it = floatingObjectSet.end(); |
3403 --it; // Go to last item. | 3558 --it; // Go to last item. |
3404 FloatingObjectSetIterator begin = floatingObjectSet.begin(); | 3559 FloatingObjectSetIterator begin = floatingObjectSet.begin(); |
3405 FloatingObject* lastPlacedFloatingObject = nullptr; | 3560 FloatingObject* lastPlacedFloatingObject = nullptr; |
3406 while (it != begin) { | 3561 while (it != begin) { |
3407 --it; | 3562 --it; |
3408 if ((*it)->isPlaced()) { | 3563 if ((*it)->isPlaced()) { |
3409 lastPlacedFloatingObject = it->get(); | 3564 lastPlacedFloatingObject = it->get(); |
3410 ++it; | 3565 ++it; |
3411 break; | 3566 break; |
3412 } | 3567 } |
3413 } | 3568 } |
3414 | 3569 |
3415 LayoutUnit logicalTop = logicalHeight(); | 3570 LayoutUnit logicalTop = logicalHeight(); |
3416 | 3571 |
3417 // The float cannot start above the top position of the last positioned float. | 3572 // The float cannot start above the top position of the last positioned float. |
3418 if (lastPlacedFloatingObject) | 3573 if (lastPlacedFloatingObject) |
3419 logicalTop = | 3574 logicalTop = |
3420 std::max(logicalTopForFloat(*lastPlacedFloatingObject), logicalTop); | 3575 std::max(logicalTopForFloat(*lastPlacedFloatingObject), logicalTop); |
3421 | 3576 |
3422 FloatingObjectSetIterator end = floatingObjectSet.end(); | 3577 FloatingObjectSetIterator end = floatingObjectSet.end(); |
3423 // Now walk through the set of unpositioned floats and place them. | 3578 // Now walk through the set of unpositioned floats and place them. |
3424 for (; it != end; ++it) { | 3579 for (; it != end; ++it) { |
3425 FloatingObject& floatingObject = *it->get(); | 3580 FloatingObject& floatingObject = *it->get(); |
3426 // The containing block is responsible for positioning floats, so if we have
floats in our | 3581 // The containing block is responsible for positioning floats, so if we have |
3427 // list that come from somewhere else, do not attempt to position them. | 3582 // floats in our list that come from somewhere else, do not attempt to |
| 3583 // position them. |
3428 if (floatingObject.layoutObject()->containingBlock() != this) | 3584 if (floatingObject.layoutObject()->containingBlock() != this) |
3429 continue; | 3585 continue; |
3430 | 3586 |
3431 LayoutBox* childBox = floatingObject.layoutObject(); | 3587 LayoutBox* childBox = floatingObject.layoutObject(); |
3432 | 3588 |
3433 // FIXME Investigate if this can be removed. crbug.com/370006 | 3589 // FIXME Investigate if this can be removed. crbug.com/370006 |
3434 childBox->setMayNeedPaintInvalidation(); | 3590 childBox->setMayNeedPaintInvalidation(); |
3435 | 3591 |
3436 LayoutUnit childLogicalLeftMargin = style()->isLeftToRightDirection() | 3592 LayoutUnit childLogicalLeftMargin = style()->isLeftToRightDirection() |
3437 ? marginStartForChild(*childBox) | 3593 ? marginStartForChild(*childBox) |
3438 : marginEndForChild(*childBox); | 3594 : marginEndForChild(*childBox); |
3439 if (childBox->style()->clear() & ClearLeft) | 3595 if (childBox->style()->clear() & ClearLeft) |
3440 logicalTop = std::max(lowestFloatLogicalBottom(FloatingObject::FloatLeft), | 3596 logicalTop = std::max(lowestFloatLogicalBottom(FloatingObject::FloatLeft), |
3441 logicalTop); | 3597 logicalTop); |
3442 if (childBox->style()->clear() & ClearRight) | 3598 if (childBox->style()->clear() & ClearRight) |
3443 logicalTop = std::max( | 3599 logicalTop = std::max( |
3444 lowestFloatLogicalBottom(FloatingObject::FloatRight), logicalTop); | 3600 lowestFloatLogicalBottom(FloatingObject::FloatRight), logicalTop); |
3445 | 3601 |
3446 bool isPaginated = view()->layoutState()->isPaginated(); | 3602 bool isPaginated = view()->layoutState()->isPaginated(); |
3447 if (isPaginated && !childrenInline()) { | 3603 if (isPaginated && !childrenInline()) { |
3448 // Forced breaks are inserted at class A break points. Floats may be affec
ted by a | 3604 // Forced breaks are inserted at class A break points. Floats may be |
3449 // break-after value on the previous in-flow sibling. | 3605 // affected by a break-after value on the previous in-flow sibling. |
3450 if (LayoutBox* previousInFlowBox = childBox->previousInFlowSiblingBox()) | 3606 if (LayoutBox* previousInFlowBox = childBox->previousInFlowSiblingBox()) |
3451 logicalTop = | 3607 logicalTop = |
3452 applyForcedBreak(logicalTop, previousInFlowBox->breakAfter()); | 3608 applyForcedBreak(logicalTop, previousInFlowBox->breakAfter()); |
3453 } | 3609 } |
3454 | 3610 |
3455 LayoutPoint floatLogicalLocation = | 3611 LayoutPoint floatLogicalLocation = |
3456 computeLogicalLocationForFloat(floatingObject, logicalTop); | 3612 computeLogicalLocationForFloat(floatingObject, logicalTop); |
3457 | 3613 |
3458 setLogicalLeftForFloat(floatingObject, floatLogicalLocation.x()); | 3614 setLogicalLeftForFloat(floatingObject, floatLogicalLocation.x()); |
3459 | 3615 |
3460 setLogicalLeftForChild(*childBox, | 3616 setLogicalLeftForChild(*childBox, |
3461 floatLogicalLocation.x() + childLogicalLeftMargin); | 3617 floatLogicalLocation.x() + childLogicalLeftMargin); |
3462 setLogicalTopForChild( | 3618 setLogicalTopForChild( |
3463 *childBox, floatLogicalLocation.y() + marginBeforeForChild(*childBox)); | 3619 *childBox, floatLogicalLocation.y() + marginBeforeForChild(*childBox)); |
3464 | 3620 |
3465 SubtreeLayoutScope layoutScope(*childBox); | 3621 SubtreeLayoutScope layoutScope(*childBox); |
3466 if (isPaginated && !childBox->needsLayout()) | 3622 if (isPaginated && !childBox->needsLayout()) |
3467 markChildForPaginationRelayoutIfNeeded(*childBox, layoutScope); | 3623 markChildForPaginationRelayoutIfNeeded(*childBox, layoutScope); |
3468 | 3624 |
3469 childBox->layoutIfNeeded(); | 3625 childBox->layoutIfNeeded(); |
3470 | 3626 |
3471 if (isPaginated) { | 3627 if (isPaginated) { |
3472 LayoutBlockFlow* childBlockFlow = | 3628 LayoutBlockFlow* childBlockFlow = |
3473 childBox->isLayoutBlockFlow() ? toLayoutBlockFlow(childBox) : nullptr; | 3629 childBox->isLayoutBlockFlow() ? toLayoutBlockFlow(childBox) : nullptr; |
3474 // The first piece of content inside the child may have set a strut during
layout. | 3630 // The first piece of content inside the child may have set a strut during |
| 3631 // layout. |
3475 LayoutUnit strut = | 3632 LayoutUnit strut = |
3476 childBlockFlow ? childBlockFlow->paginationStrutPropagatedFromChild() | 3633 childBlockFlow ? childBlockFlow->paginationStrutPropagatedFromChild() |
3477 : LayoutUnit(); | 3634 : LayoutUnit(); |
3478 if (!strut) { | 3635 if (!strut) { |
3479 // Otherwise, if we are unsplittable and don't fit, move to the next pag
e or column | 3636 // Otherwise, if we are unsplittable and don't fit, move to the next |
3480 // if that helps the situation. | 3637 // page or column if that helps the situation. |
3481 strut = | 3638 strut = |
3482 adjustForUnsplittableChild(*childBox, floatLogicalLocation.y()) - | 3639 adjustForUnsplittableChild(*childBox, floatLogicalLocation.y()) - |
3483 floatLogicalLocation.y(); | 3640 floatLogicalLocation.y(); |
3484 } | 3641 } |
3485 | 3642 |
3486 childBox->setPaginationStrut(strut); | 3643 childBox->setPaginationStrut(strut); |
3487 if (strut) { | 3644 if (strut) { |
3488 floatLogicalLocation = computeLogicalLocationForFloat( | 3645 floatLogicalLocation = computeLogicalLocationForFloat( |
3489 floatingObject, floatLogicalLocation.y() + strut); | 3646 floatingObject, floatLogicalLocation.y() + strut); |
3490 setLogicalLeftForFloat(floatingObject, floatLogicalLocation.x()); | 3647 setLogicalLeftForFloat(floatingObject, floatLogicalLocation.x()); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3529 return false; | 3686 return false; |
3530 | 3687 |
3531 return isOverhangingFloat(**it); | 3688 return isOverhangingFloat(**it); |
3532 } | 3689 } |
3533 | 3690 |
3534 void LayoutBlockFlow::addIntrudingFloats(LayoutBlockFlow* prev, | 3691 void LayoutBlockFlow::addIntrudingFloats(LayoutBlockFlow* prev, |
3535 LayoutUnit logicalLeftOffset, | 3692 LayoutUnit logicalLeftOffset, |
3536 LayoutUnit logicalTopOffset) { | 3693 LayoutUnit logicalTopOffset) { |
3537 ASSERT(!avoidsFloats()); | 3694 ASSERT(!avoidsFloats()); |
3538 | 3695 |
3539 // If we create our own block formatting context then our contents don't inter
act with floats outside it, even those from our parent. | 3696 // If we create our own block formatting context then our contents don't |
| 3697 // interact with floats outside it, even those from our parent. |
3540 if (createsNewFormattingContext()) | 3698 if (createsNewFormattingContext()) |
3541 return; | 3699 return; |
3542 | 3700 |
3543 // If the parent or previous sibling doesn't have any floats to add, don't bot
her. | 3701 // If the parent or previous sibling doesn't have any floats to add, don't |
| 3702 // bother. |
3544 if (!prev->m_floatingObjects) | 3703 if (!prev->m_floatingObjects) |
3545 return; | 3704 return; |
3546 | 3705 |
3547 logicalLeftOffset += marginLogicalLeft(); | 3706 logicalLeftOffset += marginLogicalLeft(); |
3548 | 3707 |
3549 const FloatingObjectSet& prevSet = prev->m_floatingObjects->set(); | 3708 const FloatingObjectSet& prevSet = prev->m_floatingObjects->set(); |
3550 FloatingObjectSetIterator prevEnd = prevSet.end(); | 3709 FloatingObjectSetIterator prevEnd = prevSet.end(); |
3551 for (FloatingObjectSetIterator prevIt = prevSet.begin(); prevIt != prevEnd; | 3710 for (FloatingObjectSetIterator prevIt = prevSet.begin(); prevIt != prevEnd; |
3552 ++prevIt) { | 3711 ++prevIt) { |
3553 FloatingObject& floatingObject = *prevIt->get(); | 3712 FloatingObject& floatingObject = *prevIt->get(); |
3554 if (logicalBottomForFloat(floatingObject) > logicalTopOffset) { | 3713 if (logicalBottomForFloat(floatingObject) > logicalTopOffset) { |
3555 if (!m_floatingObjects || | 3714 if (!m_floatingObjects || |
3556 !m_floatingObjects->set().contains(&floatingObject)) { | 3715 !m_floatingObjects->set().contains(&floatingObject)) { |
3557 // We create the floating object list lazily. | 3716 // We create the floating object list lazily. |
3558 if (!m_floatingObjects) | 3717 if (!m_floatingObjects) |
3559 createFloatingObjects(); | 3718 createFloatingObjects(); |
3560 | 3719 |
3561 // Applying the child's margin makes no sense in the case where the chil
d was passed in. | 3720 // Applying the child's margin makes no sense in the case where the |
3562 // since this margin was added already through the modification of the |
logicalLeftOffset| variable | 3721 // child was passed in since this margin was added already through the |
3563 // above. |logicalLeftOffset| will equal the margin in this case, so it'
s already been taken | 3722 // modification of the |logicalLeftOffset| variable above. |
3564 // into account. Only apply this code if prev is the parent, since other
wise the left margin | 3723 // |logicalLeftOffset| will equal the margin in this case, so it's |
3565 // will get applied twice. | 3724 // already been taken into account. Only apply this code if prev is the |
| 3725 // parent, since otherwise the left margin will get applied twice. |
3566 LayoutSize offset = | 3726 LayoutSize offset = |
3567 isHorizontalWritingMode() | 3727 isHorizontalWritingMode() |
3568 ? LayoutSize( | 3728 ? LayoutSize( |
3569 logicalLeftOffset - (prev != parent() ? prev->marginLeft() | 3729 logicalLeftOffset - (prev != parent() ? prev->marginLeft() |
3570 : LayoutUnit()), | 3730 : LayoutUnit()), |
3571 logicalTopOffset) | 3731 logicalTopOffset) |
3572 : LayoutSize( | 3732 : LayoutSize( |
3573 logicalTopOffset, | 3733 logicalTopOffset, |
3574 logicalLeftOffset - (prev != parent() ? prev->marginTop() | 3734 logicalLeftOffset - (prev != parent() ? prev->marginTop() |
3575 : LayoutUnit())); | 3735 : LayoutUnit())); |
3576 | 3736 |
3577 m_floatingObjects->add(floatingObject.copyToNewContainer(offset)); | 3737 m_floatingObjects->add(floatingObject.copyToNewContainer(offset)); |
3578 } | 3738 } |
3579 } | 3739 } |
3580 } | 3740 } |
3581 } | 3741 } |
3582 | 3742 |
3583 void LayoutBlockFlow::addOverhangingFloats(LayoutBlockFlow* child, | 3743 void LayoutBlockFlow::addOverhangingFloats(LayoutBlockFlow* child, |
3584 bool makeChildPaintOtherFloats) { | 3744 bool makeChildPaintOtherFloats) { |
3585 // Prevent floats from being added to the canvas by the root element, e.g., <h
tml>. | 3745 // Prevent floats from being added to the canvas by the root element, e.g., |
| 3746 // <html>. |
3586 if (!child->containsFloats() || child->createsNewFormattingContext()) | 3747 if (!child->containsFloats() || child->createsNewFormattingContext()) |
3587 return; | 3748 return; |
3588 | 3749 |
3589 LayoutUnit childLogicalTop = child->logicalTop(); | 3750 LayoutUnit childLogicalTop = child->logicalTop(); |
3590 LayoutUnit childLogicalLeft = child->logicalLeft(); | 3751 LayoutUnit childLogicalLeft = child->logicalLeft(); |
3591 | 3752 |
3592 // Floats that will remain the child's responsibility to paint should factor i
nto its | 3753 // Floats that will remain the child's responsibility to paint should factor |
3593 // overflow. | 3754 // into its overflow. |
3594 FloatingObjectSetIterator childEnd = child->m_floatingObjects->set().end(); | 3755 FloatingObjectSetIterator childEnd = child->m_floatingObjects->set().end(); |
3595 for (FloatingObjectSetIterator childIt = | 3756 for (FloatingObjectSetIterator childIt = |
3596 child->m_floatingObjects->set().begin(); | 3757 child->m_floatingObjects->set().begin(); |
3597 childIt != childEnd; ++childIt) { | 3758 childIt != childEnd; ++childIt) { |
3598 FloatingObject& floatingObject = *childIt->get(); | 3759 FloatingObject& floatingObject = *childIt->get(); |
3599 LayoutUnit logicalBottomForFloat = | 3760 LayoutUnit logicalBottomForFloat = |
3600 std::min(this->logicalBottomForFloat(floatingObject), | 3761 std::min(this->logicalBottomForFloat(floatingObject), |
3601 LayoutUnit::max() - childLogicalTop); | 3762 LayoutUnit::max() - childLogicalTop); |
3602 LayoutUnit logicalBottom = childLogicalTop + logicalBottomForFloat; | 3763 LayoutUnit logicalBottom = childLogicalTop + logicalBottomForFloat; |
3603 | 3764 |
3604 if (logicalBottom > logicalHeight()) { | 3765 if (logicalBottom > logicalHeight()) { |
3605 // If the object is not in the list, we add it now. | 3766 // If the object is not in the list, we add it now. |
3606 if (!containsFloat(floatingObject.layoutObject())) { | 3767 if (!containsFloat(floatingObject.layoutObject())) { |
3607 LayoutSize offset = | 3768 LayoutSize offset = |
3608 isHorizontalWritingMode() | 3769 isHorizontalWritingMode() |
3609 ? LayoutSize(-childLogicalLeft, -childLogicalTop) | 3770 ? LayoutSize(-childLogicalLeft, -childLogicalTop) |
3610 : LayoutSize(-childLogicalTop, -childLogicalLeft); | 3771 : LayoutSize(-childLogicalTop, -childLogicalLeft); |
3611 bool shouldPaint = false; | 3772 bool shouldPaint = false; |
3612 | 3773 |
3613 // The nearest enclosing layer always paints the float (so that zindex a
nd stacking | 3774 // The nearest enclosing layer always paints the float (so that zindex |
3614 // behaves properly). We always want to propagate the desire to paint th
e float as | 3775 // and stacking behaves properly). We always want to propagate the |
3615 // far out as we can, to the outermost block that overlaps the float, st
opping only | 3776 // desire to paint the float as far out as we can, to the outermost |
3616 // if we hit a self-painting layer boundary. | 3777 // block that overlaps the float, stopping only if we hit a |
| 3778 // self-painting layer boundary. |
3617 if (floatingObject.layoutObject()->enclosingFloatPaintingLayer() == | 3779 if (floatingObject.layoutObject()->enclosingFloatPaintingLayer() == |
3618 enclosingFloatPaintingLayer() && | 3780 enclosingFloatPaintingLayer() && |
3619 !floatingObject.isLowestNonOverhangingFloatInChild()) { | 3781 !floatingObject.isLowestNonOverhangingFloatInChild()) { |
3620 floatingObject.setShouldPaint(false); | 3782 floatingObject.setShouldPaint(false); |
3621 shouldPaint = true; | 3783 shouldPaint = true; |
3622 } | 3784 } |
3623 // We create the floating object list lazily. | 3785 // We create the floating object list lazily. |
3624 if (!m_floatingObjects) | 3786 if (!m_floatingObjects) |
3625 createFloatingObjects(); | 3787 createFloatingObjects(); |
3626 | 3788 |
3627 m_floatingObjects->add( | 3789 m_floatingObjects->add( |
3628 floatingObject.copyToNewContainer(offset, shouldPaint, true)); | 3790 floatingObject.copyToNewContainer(offset, shouldPaint, true)); |
3629 } | 3791 } |
3630 } else { | 3792 } else { |
3631 if (makeChildPaintOtherFloats && !floatingObject.shouldPaint() && | 3793 if (makeChildPaintOtherFloats && !floatingObject.shouldPaint() && |
3632 !floatingObject.layoutObject()->hasSelfPaintingLayer() && | 3794 !floatingObject.layoutObject()->hasSelfPaintingLayer() && |
3633 !floatingObject.isLowestNonOverhangingFloatInChild() && | 3795 !floatingObject.isLowestNonOverhangingFloatInChild() && |
3634 floatingObject.layoutObject()->isDescendantOf(child) && | 3796 floatingObject.layoutObject()->isDescendantOf(child) && |
3635 floatingObject.layoutObject()->enclosingFloatPaintingLayer() == | 3797 floatingObject.layoutObject()->enclosingFloatPaintingLayer() == |
3636 child->enclosingFloatPaintingLayer()) { | 3798 child->enclosingFloatPaintingLayer()) { |
3637 // The float is not overhanging from this block, so if it is a descendan
t of the child, the child should | 3799 // The float is not overhanging from this block, so if it is a |
3638 // paint it (the other case is that it is intruding into the child), unl
ess it has its own layer or enclosing | 3800 // descendant of the child, the child should paint it (the other case is |
3639 // layer. | 3801 // that it is intruding into the child), unless it has its own layer or |
3640 // If makeChildPaintOtherFloats is false, it means that the child must a
lready know about all the floats | 3802 // enclosing layer. |
3641 // it should paint. | 3803 // If makeChildPaintOtherFloats is false, it means that the child must |
| 3804 // already know about all the floats it should paint. |
3642 floatingObject.setShouldPaint(true); | 3805 floatingObject.setShouldPaint(true); |
3643 } | 3806 } |
3644 | 3807 |
3645 // Since the float doesn't overhang, it didn't get put into our list. We n
eed to go ahead and add its overflow in to the | 3808 // Since the float doesn't overhang, it didn't get put into our list. We |
3646 // child now. | 3809 // need to go ahead and add its overflow in to the child now. |
3647 if (floatingObject.isDescendant()) | 3810 if (floatingObject.isDescendant()) |
3648 child->addOverflowFromChild( | 3811 child->addOverflowFromChild( |
3649 floatingObject.layoutObject(), | 3812 floatingObject.layoutObject(), |
3650 LayoutSize(xPositionForFloatIncludingMargin(floatingObject), | 3813 LayoutSize(xPositionForFloatIncludingMargin(floatingObject), |
3651 yPositionForFloatIncludingMargin(floatingObject))); | 3814 yPositionForFloatIncludingMargin(floatingObject))); |
3652 } | 3815 } |
3653 } | 3816 } |
3654 } | 3817 } |
3655 | 3818 |
3656 LayoutUnit LayoutBlockFlow::lowestFloatLogicalBottom( | 3819 LayoutUnit LayoutBlockFlow::lowestFloatLogicalBottom( |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3799 if (!ancestorFloatingObjects) | 3962 if (!ancestorFloatingObjects) |
3800 break; | 3963 break; |
3801 FloatingObjectSet::iterator it = ancestorFloatingObjects->mutableSet() | 3964 FloatingObjectSet::iterator it = ancestorFloatingObjects->mutableSet() |
3802 .find<FloatingObjectHashTranslator>( | 3965 .find<FloatingObjectHashTranslator>( |
3803 const_cast<LayoutBox*>(&floatBox)); | 3966 const_cast<LayoutBox*>(&floatBox)); |
3804 if (it == ancestorFloatingObjects->mutableSet().end()) | 3967 if (it == ancestorFloatingObjects->mutableSet().end()) |
3805 break; | 3968 break; |
3806 | 3969 |
3807 FloatingObject& floatingObject = **it; | 3970 FloatingObject& floatingObject = **it; |
3808 if (!floatBoxIsSelfPaintingLayer) { | 3971 if (!floatBoxIsSelfPaintingLayer) { |
3809 // This repeats the logic in addOverhangingFloats() about shouldPaint flag
: | 3972 // This repeats the logic in addOverhangingFloats() about shouldPaint |
3810 // - The nearest enclosing block in which the float doesn't overhang paint
s the float; | 3973 // flag: |
3811 // - Or even if the float overhangs, if the ancestor block has self-painti
ng layer, it | 3974 // - The nearest enclosing block in which the float doesn't overhang |
3812 // paints the float. | 3975 // paints the float; |
| 3976 // - Or even if the float overhangs, if the ancestor block has |
| 3977 // self-painting layer, it paints the float. |
3813 if (ancestorBlock->hasSelfPaintingLayer() || | 3978 if (ancestorBlock->hasSelfPaintingLayer() || |
3814 !ancestorBlock->isOverhangingFloat(floatingObject)) { | 3979 !ancestorBlock->isOverhangingFloat(floatingObject)) { |
3815 floatingObject.setShouldPaint(true); | 3980 floatingObject.setShouldPaint(true); |
3816 return; | 3981 return; |
3817 } | 3982 } |
3818 } else { | 3983 } else { |
3819 floatingObject.setShouldPaint(false); | 3984 floatingObject.setShouldPaint(false); |
3820 } | 3985 } |
3821 } | 3986 } |
3822 } | 3987 } |
3823 | 3988 |
3824 bool LayoutBlockFlow::allowsPaginationStrut() const { | 3989 bool LayoutBlockFlow::allowsPaginationStrut() const { |
3825 // The block needs to be contained by a LayoutBlockFlow (and not by e.g. a fle
xbox, grid, or a | 3990 // The block needs to be contained by a LayoutBlockFlow (and not by e.g. a |
3826 // table (the latter being the case for table cell or table caption)). The rea
son for this | 3991 // flexbox, grid, or a table (the latter being the case for table cell or |
3827 // limitation is simply that LayoutBlockFlow child layout code is the only pla
ce where we pick | 3992 // table caption)). The reason for this limitation is simply that |
3828 // up the struts and handle them. We handle floats and regular in-flow childre
n, and that's | 3993 // LayoutBlockFlow child layout code is the only place where we pick up the |
3829 // all. We could handle this in other layout modes as well (and even for out-o
f-flow children), | 3994 // struts and handle them. We handle floats and regular in-flow children, and |
3830 // but currently we don't. | 3995 // that's all. We could handle this in other layout modes as well (and even |
| 3996 // for out-of-flow children), but currently we don't. |
3831 // TODO(mstensho): But we *should*. | 3997 // TODO(mstensho): But we *should*. |
3832 if (isOutOfFlowPositioned()) | 3998 if (isOutOfFlowPositioned()) |
3833 return false; | 3999 return false; |
3834 if (isLayoutFlowThread()) { | 4000 if (isLayoutFlowThread()) { |
3835 // Don't let the strut escape the fragmentation context and get lost. | 4001 // Don't let the strut escape the fragmentation context and get lost. |
3836 // TODO(mstensho): If we're in a nested fragmentation context, we should ide
ally convert | 4002 // TODO(mstensho): If we're in a nested fragmentation context, we should |
3837 // and propagate the strut to the outer fragmentation context, so that the i
nner one is | 4003 // ideally convert and propagate the strut to the outer fragmentation |
3838 // fully pushed to the next outer fragmentainer, instead of taking up unusab
le space in the | 4004 // context, so that the inner one is fully pushed to the next outer |
3839 // previous one. But currently we have no mechanism in place to handle this. | 4005 // fragmentainer, instead of taking up unusable space in the previous one. |
| 4006 // But currently we have no mechanism in place to handle this. |
3840 return false; | 4007 return false; |
3841 } | 4008 } |
3842 LayoutBlock* containingBlock = this->containingBlock(); | 4009 LayoutBlock* containingBlock = this->containingBlock(); |
3843 return containingBlock && containingBlock->isLayoutBlockFlow(); | 4010 return containingBlock && containingBlock->isLayoutBlockFlow(); |
3844 } | 4011 } |
3845 | 4012 |
3846 void LayoutBlockFlow::setPaginationStrutPropagatedFromChild(LayoutUnit strut) { | 4013 void LayoutBlockFlow::setPaginationStrutPropagatedFromChild(LayoutUnit strut) { |
3847 strut = std::max(strut, LayoutUnit()); | 4014 strut = std::max(strut, LayoutUnit()); |
3848 if (!m_rareData) { | 4015 if (!m_rareData) { |
3849 if (!strut) | 4016 if (!strut) |
3850 return; | 4017 return; |
3851 m_rareData = wrapUnique(new LayoutBlockFlowRareData(this)); | 4018 m_rareData = wrapUnique(new LayoutBlockFlowRareData(this)); |
3852 } | 4019 } |
3853 m_rareData->m_paginationStrutPropagatedFromChild = strut; | 4020 m_rareData->m_paginationStrutPropagatedFromChild = strut; |
3854 } | 4021 } |
3855 | 4022 |
3856 void LayoutBlockFlow::positionSpannerDescendant( | 4023 void LayoutBlockFlow::positionSpannerDescendant( |
3857 LayoutMultiColumnSpannerPlaceholder& child) { | 4024 LayoutMultiColumnSpannerPlaceholder& child) { |
3858 LayoutBox& spanner = *child.layoutObjectInFlowThread(); | 4025 LayoutBox& spanner = *child.layoutObjectInFlowThread(); |
3859 // FIXME: |spanner| is a descendant, but never a direct child, so the names he
re are bad, if | 4026 // FIXME: |spanner| is a descendant, but never a direct child, so the names |
3860 // nothing else. | 4027 // here are bad, if nothing else. |
3861 setLogicalTopForChild(spanner, child.logicalTop()); | 4028 setLogicalTopForChild(spanner, child.logicalTop()); |
3862 determineLogicalLeftPositionForChild(spanner); | 4029 determineLogicalLeftPositionForChild(spanner); |
3863 } | 4030 } |
3864 | 4031 |
3865 bool LayoutBlockFlow::avoidsFloats() const { | 4032 bool LayoutBlockFlow::avoidsFloats() const { |
3866 // Floats can't intrude into our box if we have a non-auto column count or wid
th. | 4033 // Floats can't intrude into our box if we have a non-auto column count or |
3867 // Note: we need to use LayoutBox::avoidsFloats here since LayoutBlock::avoids
Floats is always true. | 4034 // width. |
| 4035 // Note: we need to use LayoutBox::avoidsFloats here since |
| 4036 // LayoutBlock::avoidsFloats is always true. |
3868 return LayoutBox::avoidsFloats() || !style()->hasAutoColumnCount() || | 4037 return LayoutBox::avoidsFloats() || !style()->hasAutoColumnCount() || |
3869 !style()->hasAutoColumnWidth(); | 4038 !style()->hasAutoColumnWidth(); |
3870 } | 4039 } |
3871 | 4040 |
3872 void LayoutBlockFlow::moveChildrenTo(LayoutBoxModelObject* toBoxModelObject, | 4041 void LayoutBlockFlow::moveChildrenTo(LayoutBoxModelObject* toBoxModelObject, |
3873 LayoutObject* startChild, | 4042 LayoutObject* startChild, |
3874 LayoutObject* endChild, | 4043 LayoutObject* endChild, |
3875 LayoutObject* beforeChild, | 4044 LayoutObject* beforeChild, |
3876 bool fullRemoveInsert) { | 4045 bool fullRemoveInsert) { |
3877 if (childrenInline()) | 4046 if (childrenInline()) |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3939 // Paged overflow is currently done using the multicol implementation. | 4108 // Paged overflow is currently done using the multicol implementation. |
3940 return LayoutPagedFlowThread::createAnonymous(document(), styleRef()); | 4109 return LayoutPagedFlowThread::createAnonymous(document(), styleRef()); |
3941 default: | 4110 default: |
3942 ASSERT_NOT_REACHED(); | 4111 ASSERT_NOT_REACHED(); |
3943 return nullptr; | 4112 return nullptr; |
3944 } | 4113 } |
3945 } | 4114 } |
3946 | 4115 |
3947 void LayoutBlockFlow::createOrDestroyMultiColumnFlowThreadIfNeeded( | 4116 void LayoutBlockFlow::createOrDestroyMultiColumnFlowThreadIfNeeded( |
3948 const ComputedStyle* oldStyle) { | 4117 const ComputedStyle* oldStyle) { |
3949 // Paged overflow trumps multicol in this implementation. Ideally, it should b
e possible to have | 4118 // Paged overflow trumps multicol in this implementation. Ideally, it should |
3950 // both paged overflow and multicol on the same element, but then we need two
flow | 4119 // be possible to have both paged overflow and multicol on the same element, |
3951 // threads. Anyway, this is nothing to worry about until we can actually nest
multicol properly | 4120 // but then we need two flow threads. Anyway, this is nothing to worry about |
3952 // inside other fragmentation contexts. | 4121 // until we can actually nest multicol properly inside other fragmentation |
| 4122 // contexts. |
3953 FlowThreadType type = getFlowThreadType(styleRef()); | 4123 FlowThreadType type = getFlowThreadType(styleRef()); |
3954 | 4124 |
3955 if (multiColumnFlowThread()) { | 4125 if (multiColumnFlowThread()) { |
3956 ASSERT(oldStyle); | 4126 ASSERT(oldStyle); |
3957 if (type != getFlowThreadType(*oldStyle)) { | 4127 if (type != getFlowThreadType(*oldStyle)) { |
3958 // If we're no longer to be multicol/paged, destroy the flow thread. Also
destroy it | 4128 // If we're no longer to be multicol/paged, destroy the flow thread. Also |
3959 // when switching between multicol and paged, since that affects the colum
n set | 4129 // destroy it when switching between multicol and paged, since that |
3960 // structure (multicol containers may have spanners, paged containers may
not). | 4130 // affects the column set structure (multicol containers may have |
| 4131 // spanners, paged containers may not). |
3961 multiColumnFlowThread()->evacuateAndDestroy(); | 4132 multiColumnFlowThread()->evacuateAndDestroy(); |
3962 ASSERT(!multiColumnFlowThread()); | 4133 ASSERT(!multiColumnFlowThread()); |
3963 } | 4134 } |
3964 } | 4135 } |
3965 | 4136 |
3966 if (type == NoFlowThread || multiColumnFlowThread()) | 4137 if (type == NoFlowThread || multiColumnFlowThread()) |
3967 return; | 4138 return; |
3968 | 4139 |
3969 // Ruby elements manage child insertion in a special way, and would mess up in
sertion of the | 4140 // Ruby elements manage child insertion in a special way, and would mess up |
3970 // flow thread. The flow thread needs to be a direct child of the multicol blo
ck (|this|). | 4141 // insertion of the flow thread. The flow thread needs to be a direct child of |
| 4142 // the multicol block (|this|). |
3971 if (isRuby()) | 4143 if (isRuby()) |
3972 return; | 4144 return; |
3973 | 4145 |
3974 // Form controls are replaced content, and are therefore not supposed to suppo
rt multicol. | 4146 // Form controls are replaced content, and are therefore not supposed to |
| 4147 // support multicol. |
3975 if (isFileUploadControl() || isTextControl() || isListBox()) | 4148 if (isFileUploadControl() || isTextControl() || isListBox()) |
3976 return; | 4149 return; |
3977 | 4150 |
3978 LayoutMultiColumnFlowThread* flowThread = createMultiColumnFlowThread(type); | 4151 LayoutMultiColumnFlowThread* flowThread = createMultiColumnFlowThread(type); |
3979 addChild(flowThread); | 4152 addChild(flowThread); |
3980 | 4153 |
3981 // Check that addChild() put the flow thread as a direct child, and didn't do
fancy things. | 4154 // Check that addChild() put the flow thread as a direct child, and didn't do |
| 4155 // fancy things. |
3982 ASSERT(flowThread->parent() == this); | 4156 ASSERT(flowThread->parent() == this); |
3983 | 4157 |
3984 flowThread->populate(); | 4158 flowThread->populate(); |
3985 LayoutBlockFlowRareData& rareData = ensureRareData(); | 4159 LayoutBlockFlowRareData& rareData = ensureRareData(); |
3986 ASSERT(!rareData.m_multiColumnFlowThread); | 4160 ASSERT(!rareData.m_multiColumnFlowThread); |
3987 rareData.m_multiColumnFlowThread = flowThread; | 4161 rareData.m_multiColumnFlowThread = flowThread; |
3988 } | 4162 } |
3989 | 4163 |
3990 LayoutBlockFlow::LayoutBlockFlowRareData& LayoutBlockFlow::ensureRareData() { | 4164 LayoutBlockFlow::LayoutBlockFlowRareData& LayoutBlockFlow::ensureRareData() { |
3991 if (m_rareData) | 4165 if (m_rareData) |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4039 if (toLayoutBox(o)->inlineBoxWrapper()) { | 4213 if (toLayoutBox(o)->inlineBoxWrapper()) { |
4040 RootInlineBox& box = toLayoutBox(o)->inlineBoxWrapper()->root(); | 4214 RootInlineBox& box = toLayoutBox(o)->inlineBoxWrapper()->root(); |
4041 lineBoxes.add(&box); | 4215 lineBoxes.add(&box); |
4042 } | 4216 } |
4043 } else if (o->isText() || | 4217 } else if (o->isText() || |
4044 (o->isLayoutInline() && !walker.atEndOfInline())) { | 4218 (o->isLayoutInline() && !walker.atEndOfInline())) { |
4045 o->clearNeedsLayout(); | 4219 o->clearNeedsLayout(); |
4046 } | 4220 } |
4047 } | 4221 } |
4048 | 4222 |
4049 // FIXME: Glyph overflow will get lost in this case, but not really a big deal
. | 4223 // FIXME: Glyph overflow will get lost in this case, but not really a big |
| 4224 // deal. |
4050 GlyphOverflowAndFallbackFontsMap textBoxDataMap; | 4225 GlyphOverflowAndFallbackFontsMap textBoxDataMap; |
4051 for (ListHashSet<RootInlineBox*>::const_iterator it = lineBoxes.begin(); | 4226 for (ListHashSet<RootInlineBox*>::const_iterator it = lineBoxes.begin(); |
4052 it != lineBoxes.end(); ++it) { | 4227 it != lineBoxes.end(); ++it) { |
4053 RootInlineBox* box = *it; | 4228 RootInlineBox* box = *it; |
4054 box->computeOverflow(box->lineTop(), box->lineBottom(), textBoxDataMap); | 4229 box->computeOverflow(box->lineTop(), box->lineBottom(), textBoxDataMap); |
4055 } | 4230 } |
4056 } | 4231 } |
4057 | 4232 |
4058 bool LayoutBlockFlow::recalcInlineChildrenOverflowAfterStyleChange() { | 4233 bool LayoutBlockFlow::recalcInlineChildrenOverflowAfterStyleChange() { |
4059 ASSERT(childrenInline()); | 4234 ASSERT(childrenInline()); |
4060 bool childrenOverflowChanged = false; | 4235 bool childrenOverflowChanged = false; |
4061 ListHashSet<RootInlineBox*> lineBoxes; | 4236 ListHashSet<RootInlineBox*> lineBoxes; |
4062 for (InlineWalker walker(LineLayoutBlockFlow(this)); !walker.atEnd(); | 4237 for (InlineWalker walker(LineLayoutBlockFlow(this)); !walker.atEnd(); |
4063 walker.advance()) { | 4238 walker.advance()) { |
4064 LayoutObject* layoutObject = walker.current().layoutObject(); | 4239 LayoutObject* layoutObject = walker.current().layoutObject(); |
4065 if (recalcNormalFlowChildOverflowIfNeeded(layoutObject)) { | 4240 if (recalcNormalFlowChildOverflowIfNeeded(layoutObject)) { |
4066 childrenOverflowChanged = true; | 4241 childrenOverflowChanged = true; |
4067 if (InlineBox* inlineBoxWrapper = | 4242 if (InlineBox* inlineBoxWrapper = |
4068 toLayoutBlock(layoutObject)->inlineBoxWrapper()) | 4243 toLayoutBlock(layoutObject)->inlineBoxWrapper()) |
4069 lineBoxes.add(&inlineBoxWrapper->root()); | 4244 lineBoxes.add(&inlineBoxWrapper->root()); |
4070 } | 4245 } |
4071 } | 4246 } |
4072 | 4247 |
4073 // FIXME: Glyph overflow will get lost in this case, but not really a big deal
. | 4248 // FIXME: Glyph overflow will get lost in this case, but not really a big |
| 4249 // deal. |
4074 GlyphOverflowAndFallbackFontsMap textBoxDataMap; | 4250 GlyphOverflowAndFallbackFontsMap textBoxDataMap; |
4075 for (ListHashSet<RootInlineBox*>::const_iterator it = lineBoxes.begin(); | 4251 for (ListHashSet<RootInlineBox*>::const_iterator it = lineBoxes.begin(); |
4076 it != lineBoxes.end(); ++it) { | 4252 it != lineBoxes.end(); ++it) { |
4077 RootInlineBox* box = *it; | 4253 RootInlineBox* box = *it; |
4078 box->clearKnownToHaveNoOverflow(); | 4254 box->clearKnownToHaveNoOverflow(); |
4079 box->computeOverflow(box->lineTop(), box->lineBottom(), textBoxDataMap); | 4255 box->computeOverflow(box->lineTop(), box->lineBottom(), textBoxDataMap); |
4080 } | 4256 } |
4081 return childrenOverflowChanged; | 4257 return childrenOverflowChanged; |
4082 } | 4258 } |
4083 | 4259 |
(...skipping 13 matching lines...) Expand all Loading... |
4097 LayoutPoint pointInLogicalContents(pointInContents); | 4273 LayoutPoint pointInLogicalContents(pointInContents); |
4098 if (!isHorizontalWritingMode()) | 4274 if (!isHorizontalWritingMode()) |
4099 pointInLogicalContents = pointInLogicalContents.transposedPoint(); | 4275 pointInLogicalContents = pointInLogicalContents.transposedPoint(); |
4100 | 4276 |
4101 if (!firstRootBox()) | 4277 if (!firstRootBox()) |
4102 return createPositionWithAffinity(0); | 4278 return createPositionWithAffinity(0); |
4103 | 4279 |
4104 bool linesAreFlipped = style()->isFlippedLinesWritingMode(); | 4280 bool linesAreFlipped = style()->isFlippedLinesWritingMode(); |
4105 bool blocksAreFlipped = style()->isFlippedBlocksWritingMode(); | 4281 bool blocksAreFlipped = style()->isFlippedBlocksWritingMode(); |
4106 | 4282 |
4107 // look for the closest line box in the root box which is at the passed-in y c
oordinate | 4283 // look for the closest line box in the root box which is at the passed-in y |
| 4284 // coordinate |
4108 InlineBox* closestBox = nullptr; | 4285 InlineBox* closestBox = nullptr; |
4109 RootInlineBox* firstRootBoxWithChildren = nullptr; | 4286 RootInlineBox* firstRootBoxWithChildren = nullptr; |
4110 RootInlineBox* lastRootBoxWithChildren = nullptr; | 4287 RootInlineBox* lastRootBoxWithChildren = nullptr; |
4111 for (RootInlineBox* root = firstRootBox(); root; root = root->nextRootBox()) { | 4288 for (RootInlineBox* root = firstRootBox(); root; root = root->nextRootBox()) { |
4112 if (!root->firstLeafChild()) | 4289 if (!root->firstLeafChild()) |
4113 continue; | 4290 continue; |
4114 if (!firstRootBoxWithChildren) | 4291 if (!firstRootBoxWithChildren) |
4115 firstRootBoxWithChildren = root; | 4292 firstRootBoxWithChildren = root; |
4116 | 4293 |
4117 if (!linesAreFlipped && root->isFirstAfterPageBreak() && | 4294 if (!linesAreFlipped && root->isFirstAfterPageBreak() && |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4168 std::min<LayoutUnit>(firstRootBoxWithChildren->selectionTop(), | 4345 std::min<LayoutUnit>(firstRootBoxWithChildren->selectionTop(), |
4169 firstRootBoxWithChildren->logicalTop()); | 4346 firstRootBoxWithChildren->logicalTop()); |
4170 if (pointInLogicalContents.y() < firstRootBoxWithChildrenTop || | 4347 if (pointInLogicalContents.y() < firstRootBoxWithChildrenTop || |
4171 (blocksAreFlipped && | 4348 (blocksAreFlipped && |
4172 pointInLogicalContents.y() == firstRootBoxWithChildrenTop)) { | 4349 pointInLogicalContents.y() == firstRootBoxWithChildrenTop)) { |
4173 InlineBox* box = firstRootBoxWithChildren->firstLeafChild(); | 4350 InlineBox* box = firstRootBoxWithChildren->firstLeafChild(); |
4174 if (box->isLineBreak()) { | 4351 if (box->isLineBreak()) { |
4175 if (InlineBox* newBox = box->nextLeafChildIgnoringLineBreak()) | 4352 if (InlineBox* newBox = box->nextLeafChildIgnoringLineBreak()) |
4176 box = newBox; | 4353 box = newBox; |
4177 } | 4354 } |
4178 // y coordinate is above first root line box, so return the start of the
first | 4355 // y coordinate is above first root line box, so return the start of the |
| 4356 // first |
4179 return PositionWithAffinity(positionForBox(box, true)); | 4357 return PositionWithAffinity(positionForBox(box, true)); |
4180 } | 4358 } |
4181 } | 4359 } |
4182 | 4360 |
4183 // pass the box a top position that is inside it | 4361 // pass the box a top position that is inside it |
4184 LayoutPoint point(pointInLogicalContents.x(), | 4362 LayoutPoint point(pointInLogicalContents.x(), |
4185 closestBox->root().blockDirectionPointInLine()); | 4363 closestBox->root().blockDirectionPointInLine()); |
4186 if (!isHorizontalWritingMode()) | 4364 if (!isHorizontalWritingMode()) |
4187 point = point.transposedPoint(); | 4365 point = point.transposedPoint(); |
4188 if (closestBox->getLineLayoutItem().isAtomicInlineLevel()) | 4366 if (closestBox->getLineLayoutItem().isAtomicInlineLevel()) |
4189 return positionForPointRespectingEditingBoundaries( | 4367 return positionForPointRespectingEditingBoundaries( |
4190 LineLayoutBox(closestBox->getLineLayoutItem()), point); | 4368 LineLayoutBox(closestBox->getLineLayoutItem()), point); |
4191 return closestBox->getLineLayoutItem().positionForPoint(point); | 4369 return closestBox->getLineLayoutItem().positionForPoint(point); |
4192 } | 4370 } |
4193 | 4371 |
4194 if (lastRootBoxWithChildren) { | 4372 if (lastRootBoxWithChildren) { |
4195 // We hit this case for Mac behavior when the Y coordinate is below the last
box. | 4373 // We hit this case for Mac behavior when the Y coordinate is below the last |
| 4374 // box. |
4196 ASSERT(moveCaretToBoundary); | 4375 ASSERT(moveCaretToBoundary); |
4197 InlineBox* logicallyLastBox; | 4376 InlineBox* logicallyLastBox; |
4198 if (lastRootBoxWithChildren->getLogicalEndBoxWithNode(logicallyLastBox)) | 4377 if (lastRootBoxWithChildren->getLogicalEndBoxWithNode(logicallyLastBox)) |
4199 return PositionWithAffinity(positionForBox(logicallyLastBox, false)); | 4378 return PositionWithAffinity(positionForBox(logicallyLastBox, false)); |
4200 } | 4379 } |
4201 | 4380 |
4202 // Can't reach this. We have a root line box, but it has no kids. | 4381 // Can't reach this. We have a root line box, but it has no kids. |
4203 // FIXME: This should ASSERT_NOT_REACHED(), but clicking on placeholder text | 4382 // FIXME: This should ASSERT_NOT_REACHED(), but clicking on placeholder text |
4204 // seems to hit this code path. | 4383 // seems to hit this code path. |
4205 return createPositionWithAffinity(0); | 4384 return createPositionWithAffinity(0); |
(...skipping 12 matching lines...) Expand all Loading... |
4218 root->showLineTreeAndMark(markedBox1, markedLabel1, markedBox2, | 4397 root->showLineTreeAndMark(markedBox1, markedLabel1, markedBox2, |
4219 markedLabel2, obj, 1); | 4398 markedLabel2, obj, 1); |
4220 } | 4399 } |
4221 | 4400 |
4222 #endif | 4401 #endif |
4223 | 4402 |
4224 void LayoutBlockFlow::addOutlineRects( | 4403 void LayoutBlockFlow::addOutlineRects( |
4225 Vector<LayoutRect>& rects, | 4404 Vector<LayoutRect>& rects, |
4226 const LayoutPoint& additionalOffset, | 4405 const LayoutPoint& additionalOffset, |
4227 IncludeBlockVisualOverflowOrNot includeBlockOverflows) const { | 4406 IncludeBlockVisualOverflowOrNot includeBlockOverflows) const { |
4228 // For blocks inside inlines, we go ahead and include margins so that we run r
ight up to the | 4407 // For blocks inside inlines, we go ahead and include margins so that we run |
4229 // inline boxes above and below us (thus getting merged with them to form a si
ngle irregular | 4408 // right up to the inline boxes above and below us (thus getting merged with |
4230 // shape). | 4409 // them to form a single irregular shape). |
4231 const LayoutInline* inlineElementContinuation = | 4410 const LayoutInline* inlineElementContinuation = |
4232 this->inlineElementContinuation(); | 4411 this->inlineElementContinuation(); |
4233 if (inlineElementContinuation) { | 4412 if (inlineElementContinuation) { |
4234 // FIXME: This check really isn't accurate. | 4413 // FIXME: This check really isn't accurate. |
4235 bool nextInlineHasLineBox = inlineElementContinuation->firstLineBox(); | 4414 bool nextInlineHasLineBox = inlineElementContinuation->firstLineBox(); |
4236 // FIXME: This is wrong. The principal layoutObject may not be the continuat
ion preceding this block. | 4415 // FIXME: This is wrong. The principal layoutObject may not be the |
| 4416 // continuation preceding this block. |
4237 // FIXME: This is wrong for vertical writing-modes. | 4417 // FIXME: This is wrong for vertical writing-modes. |
4238 // https://bugs.webkit.org/show_bug.cgi?id=46781 | 4418 // https://bugs.webkit.org/show_bug.cgi?id=46781 |
4239 bool prevInlineHasLineBox = | 4419 bool prevInlineHasLineBox = |
4240 toLayoutInline(inlineElementContinuation->node()->layoutObject()) | 4420 toLayoutInline(inlineElementContinuation->node()->layoutObject()) |
4241 ->firstLineBox(); | 4421 ->firstLineBox(); |
4242 LayoutUnit topMargin = | 4422 LayoutUnit topMargin = |
4243 prevInlineHasLineBox ? collapsedMarginBefore() : LayoutUnit(); | 4423 prevInlineHasLineBox ? collapsedMarginBefore() : LayoutUnit(); |
4244 LayoutUnit bottomMargin = | 4424 LayoutUnit bottomMargin = |
4245 nextInlineHasLineBox ? collapsedMarginAfter() : LayoutUnit(); | 4425 nextInlineHasLineBox ? collapsedMarginAfter() : LayoutUnit(); |
4246 if (topMargin || bottomMargin) { | 4426 if (topMargin || bottomMargin) { |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4282 return LayoutBlock::invalidatePaintIfNeeded(paintInvalidationState); | 4462 return LayoutBlock::invalidatePaintIfNeeded(paintInvalidationState); |
4283 } | 4463 } |
4284 | 4464 |
4285 void LayoutBlockFlow::invalidateDisplayItemClients( | 4465 void LayoutBlockFlow::invalidateDisplayItemClients( |
4286 PaintInvalidationReason invalidationReason) const { | 4466 PaintInvalidationReason invalidationReason) const { |
4287 BlockFlowPaintInvalidator(*this).invalidateDisplayItemClients( | 4467 BlockFlowPaintInvalidator(*this).invalidateDisplayItemClients( |
4288 invalidationReason); | 4468 invalidationReason); |
4289 } | 4469 } |
4290 | 4470 |
4291 } // namespace blink | 4471 } // namespace blink |
OLD | NEW |