| 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 |
| 1064 // going to |
| 1010 // fit in the same column or page, so check that as well. | 1065 // fit in the same column or page, so check that as well. |
| 1011 if (totalLogicalHeight > pageLogicalHeight) | 1066 if (totalLogicalHeight > pageLogicalHeight) |
| 1012 return false; | 1067 return false; |
| 1013 } else { | 1068 } else { |
| 1014 if (lineIndex > block.style()->orphans()) | 1069 if (lineIndex > block.style()->orphans()) |
| 1015 return false; | 1070 return false; |
| 1016 | 1071 |
| 1017 // Not enough orphans here. Push the entire block to the next column / page
as an attempt to | 1072 // Not enough orphans here. Push the entire block to the next column / page |
| 1018 // better satisfy the orphans requirement. | 1073 // as an attempt to better satisfy the orphans requirement. |
| 1019 // | 1074 // |
| 1020 // Note that we should ideally check if the first line in the block is flush
with the | 1075 // 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" | 1076 // 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. | 1077 // break at the class "C" break point in front of the first line, rather |
| 1078 // than before the entire block. |
| 1023 } | 1079 } |
| 1024 return block.allowsPaginationStrut(); | 1080 return block.allowsPaginationStrut(); |
| 1025 } | 1081 } |
| 1026 | 1082 |
| 1027 void LayoutBlockFlow::adjustLinePositionForPagination(RootInlineBox& lineBox, | 1083 void LayoutBlockFlow::adjustLinePositionForPagination(RootInlineBox& lineBox, |
| 1028 LayoutUnit& delta) { | 1084 LayoutUnit& delta) { |
| 1029 // TODO(mstensho): Pay attention to line overflow. It should be painted in the
same column as | 1085 // 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 | 1086 // 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 | 1087 // 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 | 1088 // 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). | 1089 // to do when a column has overflow has to be special. |
| 1090 // We need to exclude content that paints in a previous column (and content |
| 1091 // that paints in the following column). |
| 1034 // | 1092 // |
| 1035 // FIXME: Another problem with simply moving lines is that the available line
width may change (because of floats). | 1093 // 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 | 1094 // width may change (because of floats). Technically if the location we move |
| 1037 // line and all following lines. | 1095 // the line to has a different line width than our old position, then we need |
| 1096 // to dirty the line and all following lines. |
| 1038 LayoutUnit logicalOffset = lineBox.lineTopWithLeading(); | 1097 LayoutUnit logicalOffset = lineBox.lineTopWithLeading(); |
| 1039 LayoutUnit lineHeight = lineBox.lineBottomWithLeading() - logicalOffset; | 1098 LayoutUnit lineHeight = lineBox.lineBottomWithLeading() - logicalOffset; |
| 1040 logicalOffset += delta; | 1099 logicalOffset += delta; |
| 1041 lineBox.setPaginationStrut(LayoutUnit()); | 1100 lineBox.setPaginationStrut(LayoutUnit()); |
| 1042 lineBox.setIsFirstAfterPageBreak(false); | 1101 lineBox.setIsFirstAfterPageBreak(false); |
| 1043 LayoutUnit pageLogicalHeight = pageLogicalHeightForOffset(logicalOffset); | 1102 LayoutUnit pageLogicalHeight = pageLogicalHeightForOffset(logicalOffset); |
| 1044 if (!pageLogicalHeight) | 1103 if (!pageLogicalHeight) |
| 1045 return; | 1104 return; |
| 1046 LayoutUnit remainingLogicalHeight = pageRemainingLogicalHeightForOffset( | 1105 LayoutUnit remainingLogicalHeight = pageRemainingLogicalHeightForOffset( |
| 1047 logicalOffset, AssociateWithLatterPage); | 1106 logicalOffset, AssociateWithLatterPage); |
| 1048 int lineIndex = lineCount(&lineBox); | 1107 int lineIndex = lineCount(&lineBox); |
| 1049 if (remainingLogicalHeight < lineHeight || | 1108 if (remainingLogicalHeight < lineHeight || |
| 1050 (shouldBreakAtLineToAvoidWidow() && | 1109 (shouldBreakAtLineToAvoidWidow() && |
| 1051 lineBreakToAvoidWidow() == lineIndex)) { | 1110 lineBreakToAvoidWidow() == lineIndex)) { |
| 1052 LayoutUnit paginationStrut = calculatePaginationStrutToFitContent( | 1111 LayoutUnit paginationStrut = calculatePaginationStrutToFitContent( |
| 1053 logicalOffset, remainingLogicalHeight, lineHeight); | 1112 logicalOffset, remainingLogicalHeight, lineHeight); |
| 1054 LayoutUnit newLogicalOffset = logicalOffset + paginationStrut; | 1113 LayoutUnit newLogicalOffset = logicalOffset + paginationStrut; |
| 1055 // Moving to a different page or column may mean that its height is differen
t. | 1114 // Moving to a different page or column may mean that its height is |
| 1115 // different. |
| 1056 pageLogicalHeight = pageLogicalHeightForOffset(newLogicalOffset); | 1116 pageLogicalHeight = pageLogicalHeightForOffset(newLogicalOffset); |
| 1057 if (lineHeight > pageLogicalHeight) { | 1117 if (lineHeight > pageLogicalHeight) { |
| 1058 // Too tall to fit in one page / column. Give up. Don't push to the next p
age / column. | 1118 // 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 | 1119 // page / column. |
| 1060 // also do something slightly similar, although in much more specific case
s than we do here, | 1120 // TODO(mstensho): Get rid of this. This is just utter weirdness, but the |
| 1061 // and printing Google Docs depends on it. | 1121 // other browsers also do something slightly similar, although in much |
| 1122 // more specific cases than we do here, and printing Google Docs depends |
| 1123 // on it. |
| 1062 paginatedContentWasLaidOut(logicalOffset + lineHeight); | 1124 paginatedContentWasLaidOut(logicalOffset + lineHeight); |
| 1063 return; | 1125 return; |
| 1064 } | 1126 } |
| 1065 | 1127 |
| 1066 // We need to insert a break now, either because there's no room for the lin
e in the | 1128 // 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 | 1129 // line in the current column / page, or because we have determined that we |
| 1068 // widow requirements. | 1130 // need a break to satisfy widow requirements. |
| 1069 if (shouldBreakAtLineToAvoidWidow() && | 1131 if (shouldBreakAtLineToAvoidWidow() && |
| 1070 lineBreakToAvoidWidow() == lineIndex) { | 1132 lineBreakToAvoidWidow() == lineIndex) { |
| 1071 clearShouldBreakAtLineToAvoidWidow(); | 1133 clearShouldBreakAtLineToAvoidWidow(); |
| 1072 setDidBreakAtLineToAvoidWidow(); | 1134 setDidBreakAtLineToAvoidWidow(); |
| 1073 } | 1135 } |
| 1074 if (shouldSetStrutOnBlock(*this, lineBox, logicalOffset, lineIndex, | 1136 if (shouldSetStrutOnBlock(*this, lineBox, logicalOffset, lineIndex, |
| 1075 pageLogicalHeight)) { | 1137 pageLogicalHeight)) { |
| 1076 // Note that when setting the strut on a block, it may be propagated to pa
rent blocks | 1138 // 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 | 1139 // 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 | 1140 // 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 | 1141 // beginning of a block before a break, if it can be avoided. After all, |
| 1080 // in the first place. | 1142 // that's the reason for setting struts on blocks and not lines in the |
| 1143 // first place. |
| 1081 LayoutUnit strut = | 1144 LayoutUnit strut = |
| 1082 paginationStrut + logicalOffset + marginBeforeIfFloating(); | 1145 paginationStrut + logicalOffset + marginBeforeIfFloating(); |
| 1083 setPaginationStrutPropagatedFromChild(strut); | 1146 setPaginationStrutPropagatedFromChild(strut); |
| 1084 } else { | 1147 } else { |
| 1085 delta += paginationStrut; | 1148 delta += paginationStrut; |
| 1086 lineBox.setPaginationStrut(paginationStrut); | 1149 lineBox.setPaginationStrut(paginationStrut); |
| 1087 lineBox.setIsFirstAfterPageBreak(true); | 1150 lineBox.setIsFirstAfterPageBreak(true); |
| 1088 } | 1151 } |
| 1089 paginatedContentWasLaidOut(newLogicalOffset + lineHeight); | 1152 paginatedContentWasLaidOut(newLogicalOffset + lineHeight); |
| 1090 return; | 1153 return; |
| 1091 } | 1154 } |
| 1092 | 1155 |
| 1093 LayoutUnit strutToPropagate; | 1156 LayoutUnit strutToPropagate; |
| 1094 if (remainingLogicalHeight == pageLogicalHeight) { | 1157 if (remainingLogicalHeight == pageLogicalHeight) { |
| 1095 // We're at the very top of a page or column. | 1158 // We're at the very top of a page or column. |
| 1096 if (lineBox != firstRootBox()) | 1159 if (lineBox != firstRootBox()) |
| 1097 lineBox.setIsFirstAfterPageBreak(true); | 1160 lineBox.setIsFirstAfterPageBreak(true); |
| 1098 // If this is the first line in the block, and the block has a top border, p
adding, or (in | 1161 // 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 | 1162 // 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 | 1163 // the block, so that everything ends up in the next column or page. Setting |
| 1101 // it comes to satisfying orphan requirements. | 1164 // a strut on the block is also important when it comes to satisfying orphan |
| 1165 // requirements. |
| 1102 if (shouldSetStrutOnBlock(*this, lineBox, logicalOffset, lineIndex, | 1166 if (shouldSetStrutOnBlock(*this, lineBox, logicalOffset, lineIndex, |
| 1103 pageLogicalHeight)) | 1167 pageLogicalHeight)) |
| 1104 strutToPropagate = logicalOffset + marginBeforeIfFloating(); | 1168 strutToPropagate = logicalOffset + marginBeforeIfFloating(); |
| 1105 } else if (lineBox == firstRootBox() && allowsPaginationStrut()) { | 1169 } 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 | 1170 // 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 | 1171 // 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. | 1172 // to where this line is, so that we don't split the top border, padding, or |
| 1173 // (in case it's a float) margin. |
| 1109 LayoutUnit totalLogicalOffset = logicalOffset + marginBeforeIfFloating(); | 1174 LayoutUnit totalLogicalOffset = logicalOffset + marginBeforeIfFloating(); |
| 1110 LayoutUnit strut = | 1175 LayoutUnit strut = |
| 1111 remainingLogicalHeight + totalLogicalOffset - pageLogicalHeight; | 1176 remainingLogicalHeight + totalLogicalOffset - pageLogicalHeight; |
| 1112 if (strut > 0) { | 1177 if (strut > 0) { |
| 1113 // The block starts in a previous column or page. Set a strut on the block
if there's | 1178 // 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 | 1179 // if there's room for the top border, padding and (if it's a float) |
| 1115 // column or page. | 1180 // margin and the line in one column or page. |
| 1116 if (totalLogicalOffset + lineHeight <= pageLogicalHeight) | 1181 if (totalLogicalOffset + lineHeight <= pageLogicalHeight) |
| 1117 strutToPropagate = strut; | 1182 strutToPropagate = strut; |
| 1118 } | 1183 } |
| 1119 } | 1184 } |
| 1120 | 1185 |
| 1121 // If we found that some preceding content (lines, border and padding) belongs
together with | 1186 // 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 | 1187 // 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 | 1188 // 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 | 1189 // precedes the first fragmentainer, though. We shouldn't fragment content |
| 1125 // first fragmentainer. | 1190 // there, but rather let it appear in the overflow area before the first |
| 1191 // fragmentainer. |
| 1126 if (strutToPropagate && offsetFromLogicalTopOfFirstPage() > LayoutUnit()) | 1192 if (strutToPropagate && offsetFromLogicalTopOfFirstPage() > LayoutUnit()) |
| 1127 setPaginationStrutPropagatedFromChild(strutToPropagate); | 1193 setPaginationStrutPropagatedFromChild(strutToPropagate); |
| 1128 | 1194 |
| 1129 paginatedContentWasLaidOut(logicalOffset + lineHeight); | 1195 paginatedContentWasLaidOut(logicalOffset + lineHeight); |
| 1130 } | 1196 } |
| 1131 | 1197 |
| 1132 LayoutUnit LayoutBlockFlow::adjustForUnsplittableChild( | 1198 LayoutUnit LayoutBlockFlow::adjustForUnsplittableChild( |
| 1133 LayoutBox& child, | 1199 LayoutBox& child, |
| 1134 LayoutUnit logicalOffset) const { | 1200 LayoutUnit logicalOffset) const { |
| 1135 if (child.getPaginationBreakability() == AllowAnyBreaks) | 1201 if (child.getPaginationBreakability() == AllowAnyBreaks) |
| 1136 return logicalOffset; | 1202 return logicalOffset; |
| 1137 LayoutUnit childLogicalHeight = logicalHeightForChild(child); | 1203 LayoutUnit childLogicalHeight = logicalHeightForChild(child); |
| 1138 // Floats' margins do not collapse with page or column boundaries. | 1204 // Floats' margins do not collapse with page or column boundaries. |
| 1139 if (child.isFloating()) | 1205 if (child.isFloating()) |
| 1140 childLogicalHeight += | 1206 childLogicalHeight += |
| 1141 marginBeforeForChild(child) + marginAfterForChild(child); | 1207 marginBeforeForChild(child) + marginAfterForChild(child); |
| 1142 LayoutUnit pageLogicalHeight = pageLogicalHeightForOffset(logicalOffset); | 1208 LayoutUnit pageLogicalHeight = pageLogicalHeightForOffset(logicalOffset); |
| 1143 if (!pageLogicalHeight) | 1209 if (!pageLogicalHeight) |
| 1144 return logicalOffset; | 1210 return logicalOffset; |
| 1145 LayoutUnit remainingLogicalHeight = pageRemainingLogicalHeightForOffset( | 1211 LayoutUnit remainingLogicalHeight = pageRemainingLogicalHeightForOffset( |
| 1146 logicalOffset, AssociateWithLatterPage); | 1212 logicalOffset, AssociateWithLatterPage); |
| 1147 if (remainingLogicalHeight >= childLogicalHeight) | 1213 if (remainingLogicalHeight >= childLogicalHeight) |
| 1148 return logicalOffset; // It fits fine where it is. No need to break. | 1214 return logicalOffset; // It fits fine where it is. No need to break. |
| 1149 LayoutUnit paginationStrut = calculatePaginationStrutToFitContent( | 1215 LayoutUnit paginationStrut = calculatePaginationStrutToFitContent( |
| 1150 logicalOffset, remainingLogicalHeight, childLogicalHeight); | 1216 logicalOffset, remainingLogicalHeight, childLogicalHeight); |
| 1151 if (paginationStrut == remainingLogicalHeight && | 1217 if (paginationStrut == remainingLogicalHeight && |
| 1152 remainingLogicalHeight == pageLogicalHeight) { | 1218 remainingLogicalHeight == pageLogicalHeight) { |
| 1153 // Don't break if we were at the top of a page, and we failed to fit the con
tent | 1219 // 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. | 1220 // content completely. No point in leaving a page completely blank. |
| 1155 return logicalOffset; | 1221 return logicalOffset; |
| 1156 } | 1222 } |
| 1157 return logicalOffset + paginationStrut; | 1223 return logicalOffset + paginationStrut; |
| 1158 } | 1224 } |
| 1159 | 1225 |
| 1160 DISABLE_CFI_PERF | 1226 DISABLE_CFI_PERF |
| 1161 void LayoutBlockFlow::rebuildFloatsFromIntruding() { | 1227 void LayoutBlockFlow::rebuildFloatsFromIntruding() { |
| 1162 if (m_floatingObjects) | 1228 if (m_floatingObjects) |
| 1163 m_floatingObjects->setHorizontalWritingMode(isHorizontalWritingMode()); | 1229 m_floatingObjects->setHorizontalWritingMode(isHorizontalWritingMode()); |
| 1164 | 1230 |
| 1165 HashSet<LayoutBox*> oldIntrudingFloatSet; | 1231 HashSet<LayoutBox*> oldIntrudingFloatSet; |
| 1166 if (!childrenInline() && m_floatingObjects) { | 1232 if (!childrenInline() && m_floatingObjects) { |
| 1167 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); | 1233 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); |
| 1168 FloatingObjectSetIterator end = floatingObjectSet.end(); | 1234 FloatingObjectSetIterator end = floatingObjectSet.end(); |
| 1169 for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; | 1235 for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; |
| 1170 ++it) { | 1236 ++it) { |
| 1171 const FloatingObject& floatingObject = *it->get(); | 1237 const FloatingObject& floatingObject = *it->get(); |
| 1172 if (!floatingObject.isDescendant()) | 1238 if (!floatingObject.isDescendant()) |
| 1173 oldIntrudingFloatSet.add(floatingObject.layoutObject()); | 1239 oldIntrudingFloatSet.add(floatingObject.layoutObject()); |
| 1174 } | 1240 } |
| 1175 } | 1241 } |
| 1176 | 1242 |
| 1177 // Inline blocks are covered by the isAtomicInlineLevel() check in the avoidFl
oats method. | 1243 // Inline blocks are covered by the isAtomicInlineLevel() check in the |
| 1244 // avoidFloats method. |
| 1178 if (avoidsFloats() || isDocumentElement() || isLayoutView() || | 1245 if (avoidsFloats() || isDocumentElement() || isLayoutView() || |
| 1179 isFloatingOrOutOfFlowPositioned() || isTableCell()) { | 1246 isFloatingOrOutOfFlowPositioned() || isTableCell()) { |
| 1180 if (m_floatingObjects) { | 1247 if (m_floatingObjects) { |
| 1181 m_floatingObjects->clear(); | 1248 m_floatingObjects->clear(); |
| 1182 } | 1249 } |
| 1183 if (!oldIntrudingFloatSet.isEmpty()) | 1250 if (!oldIntrudingFloatSet.isEmpty()) |
| 1184 markAllDescendantsWithFloatsForLayout(); | 1251 markAllDescendantsWithFloatsForLayout(); |
| 1185 return; | 1252 return; |
| 1186 } | 1253 } |
| 1187 | 1254 |
| 1188 LayoutBoxToFloatInfoMap floatMap; | 1255 LayoutBoxToFloatInfoMap floatMap; |
| 1189 | 1256 |
| 1190 if (m_floatingObjects) { | 1257 if (m_floatingObjects) { |
| 1191 if (childrenInline()) | 1258 if (childrenInline()) |
| 1192 m_floatingObjects->moveAllToFloatInfoMap(floatMap); | 1259 m_floatingObjects->moveAllToFloatInfoMap(floatMap); |
| 1193 else | 1260 else |
| 1194 m_floatingObjects->clear(); | 1261 m_floatingObjects->clear(); |
| 1195 } | 1262 } |
| 1196 | 1263 |
| 1197 // We should not process floats if the parent node is not a LayoutBlockFlow. O
therwise, we will add | 1264 // 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. | 1265 // 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. | 1266 // crash arising from a bad cast on the parent. |
| 1267 // See <rdar://problem/8049753>, where float property is applied on a text |
| 1268 // node in a SVG. |
| 1200 if (!parent() || !parent()->isLayoutBlockFlow()) | 1269 if (!parent() || !parent()->isLayoutBlockFlow()) |
| 1201 return; | 1270 return; |
| 1202 | 1271 |
| 1203 // Attempt to locate a previous sibling with overhanging floats. We skip any e
lements that | 1272 // 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 | 1273 // 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). | 1274 // floats cannot interact with objects outside it (i.e. objects that create a |
| 1275 // new block formatting context). |
| 1206 LayoutBlockFlow* parentBlockFlow = toLayoutBlockFlow(parent()); | 1276 LayoutBlockFlow* parentBlockFlow = toLayoutBlockFlow(parent()); |
| 1207 bool siblingFloatMayIntrude = false; | 1277 bool siblingFloatMayIntrude = false; |
| 1208 LayoutObject* prev = previousSibling(); | 1278 LayoutObject* prev = previousSibling(); |
| 1209 while (prev && (!prev->isBox() || !prev->isLayoutBlock() || | 1279 while (prev && (!prev->isBox() || !prev->isLayoutBlock() || |
| 1210 toLayoutBlock(prev)->avoidsFloats() || | 1280 toLayoutBlock(prev)->avoidsFloats() || |
| 1211 toLayoutBlock(prev)->createsNewFormattingContext())) { | 1281 toLayoutBlock(prev)->createsNewFormattingContext())) { |
| 1212 if (prev->isFloating()) | 1282 if (prev->isFloating()) |
| 1213 siblingFloatMayIntrude = true; | 1283 siblingFloatMayIntrude = true; |
| 1214 prev = prev->previousSibling(); | 1284 prev = prev->previousSibling(); |
| 1215 } | 1285 } |
| 1216 | 1286 |
| 1217 // First add in floats from the parent. Self-collapsing blocks let their paren
t track any floats that intrude into | 1287 // 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 | 1288 // 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. | 1289 // contain themselves) so check for those here too. If margin collapsing has |
| 1290 // moved us up past the top a previous sibling then we need to check for |
| 1291 // floats from the parent too. |
| 1220 bool parentFloatsMayIntrude = | 1292 bool parentFloatsMayIntrude = |
| 1221 !siblingFloatMayIntrude && | 1293 !siblingFloatMayIntrude && |
| 1222 (!prev || toLayoutBlockFlow(prev)->isSelfCollapsingBlock() || | 1294 (!prev || toLayoutBlockFlow(prev)->isSelfCollapsingBlock() || |
| 1223 toLayoutBlock(prev)->logicalTop() > logicalTop()) && | 1295 toLayoutBlock(prev)->logicalTop() > logicalTop()) && |
| 1224 parentBlockFlow->lowestFloatLogicalBottom() > logicalTop(); | 1296 parentBlockFlow->lowestFloatLogicalBottom() > logicalTop(); |
| 1225 if (siblingFloatMayIntrude || parentFloatsMayIntrude) | 1297 if (siblingFloatMayIntrude || parentFloatsMayIntrude) |
| 1226 addIntrudingFloats(parentBlockFlow, | 1298 addIntrudingFloats(parentBlockFlow, |
| 1227 parentBlockFlow->logicalLeftOffsetForContent(), | 1299 parentBlockFlow->logicalLeftOffsetForContent(), |
| 1228 logicalTop()); | 1300 logicalTop()); |
| 1229 | 1301 |
| 1230 // Add overhanging floats from the previous LayoutBlockFlow, but only if it ha
s a float that intrudes into our space. | 1302 // Add overhanging floats from the previous LayoutBlockFlow, but only if it |
| 1303 // has a float that intrudes into our space. |
| 1231 if (prev) { | 1304 if (prev) { |
| 1232 LayoutBlockFlow* previousBlockFlow = toLayoutBlockFlow(prev); | 1305 LayoutBlockFlow* previousBlockFlow = toLayoutBlockFlow(prev); |
| 1233 if (logicalTop() < previousBlockFlow->logicalTop() + | 1306 if (logicalTop() < previousBlockFlow->logicalTop() + |
| 1234 previousBlockFlow->lowestFloatLogicalBottom()) | 1307 previousBlockFlow->lowestFloatLogicalBottom()) |
| 1235 addIntrudingFloats(previousBlockFlow, LayoutUnit(), | 1308 addIntrudingFloats(previousBlockFlow, LayoutUnit(), |
| 1236 logicalTop() - previousBlockFlow->logicalTop()); | 1309 logicalTop() - previousBlockFlow->logicalTop()); |
| 1237 } | 1310 } |
| 1238 | 1311 |
| 1239 if (childrenInline()) { | 1312 if (childrenInline()) { |
| 1240 LayoutUnit changeLogicalTop = LayoutUnit::max(); | 1313 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; | 1370 std::unique_ptr<FloatingObject>& floatingObject = it->value; |
| 1298 if (!floatingObject->isDescendant()) { | 1371 if (!floatingObject->isDescendant()) { |
| 1299 changeLogicalTop = LayoutUnit(); | 1372 changeLogicalTop = LayoutUnit(); |
| 1300 changeLogicalBottom = std::max(changeLogicalBottom, | 1373 changeLogicalBottom = std::max(changeLogicalBottom, |
| 1301 logicalBottomForFloat(*floatingObject)); | 1374 logicalBottomForFloat(*floatingObject)); |
| 1302 } | 1375 } |
| 1303 } | 1376 } |
| 1304 | 1377 |
| 1305 markLinesDirtyInBlockRange(changeLogicalTop, changeLogicalBottom); | 1378 markLinesDirtyInBlockRange(changeLogicalTop, changeLogicalBottom); |
| 1306 } else if (!oldIntrudingFloatSet.isEmpty()) { | 1379 } else if (!oldIntrudingFloatSet.isEmpty()) { |
| 1307 // If there are previously intruding floats that no longer intrude, then chi
ldren with floats | 1380 // 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. | 1381 // children with floats should also get layout because they might need their |
| 1382 // floating object lists cleared. |
| 1309 if (m_floatingObjects->set().size() < oldIntrudingFloatSet.size()) { | 1383 if (m_floatingObjects->set().size() < oldIntrudingFloatSet.size()) { |
| 1310 markAllDescendantsWithFloatsForLayout(); | 1384 markAllDescendantsWithFloatsForLayout(); |
| 1311 } else { | 1385 } else { |
| 1312 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); | 1386 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); |
| 1313 FloatingObjectSetIterator end = floatingObjectSet.end(); | 1387 FloatingObjectSetIterator end = floatingObjectSet.end(); |
| 1314 for (FloatingObjectSetIterator it = floatingObjectSet.begin(); | 1388 for (FloatingObjectSetIterator it = floatingObjectSet.begin(); |
| 1315 it != end && !oldIntrudingFloatSet.isEmpty(); ++it) | 1389 it != end && !oldIntrudingFloatSet.isEmpty(); ++it) |
| 1316 oldIntrudingFloatSet.remove((*it)->layoutObject()); | 1390 oldIntrudingFloatSet.remove((*it)->layoutObject()); |
| 1317 if (!oldIntrudingFloatSet.isEmpty()) | 1391 if (!oldIntrudingFloatSet.isEmpty()) |
| 1318 markAllDescendantsWithFloatsForLayout(); | 1392 markAllDescendantsWithFloatsForLayout(); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1342 | 1416 |
| 1343 while (next) { | 1417 while (next) { |
| 1344 LayoutBox* child = next; | 1418 LayoutBox* child = next; |
| 1345 LayoutObject* nextSibling = child->nextSibling(); | 1419 LayoutObject* nextSibling = child->nextSibling(); |
| 1346 CHECK(!nextSibling || nextSibling->isBox()); | 1420 CHECK(!nextSibling || nextSibling->isBox()); |
| 1347 next = toLayoutBox(nextSibling); | 1421 next = toLayoutBox(nextSibling); |
| 1348 | 1422 |
| 1349 child->setMayNeedPaintInvalidation(); | 1423 child->setMayNeedPaintInvalidation(); |
| 1350 | 1424 |
| 1351 if (childToExclude == child) | 1425 if (childToExclude == child) |
| 1352 continue; // Skip this child, since it will be positioned by the speciali
zed subclass (ruby runs). | 1426 continue; // Skip this child, since it will be positioned by the |
| 1427 // specialized subclass (ruby runs). |
| 1353 | 1428 |
| 1354 updateBlockChildDirtyBitsBeforeLayout(relayoutChildren, *child); | 1429 updateBlockChildDirtyBitsBeforeLayout(relayoutChildren, *child); |
| 1355 | 1430 |
| 1356 if (child->isOutOfFlowPositioned()) { | 1431 if (child->isOutOfFlowPositioned()) { |
| 1357 child->containingBlock()->insertPositionedObject(child); | 1432 child->containingBlock()->insertPositionedObject(child); |
| 1358 adjustPositionedBlock(*child, layoutInfo); | 1433 adjustPositionedBlock(*child, layoutInfo); |
| 1359 continue; | 1434 continue; |
| 1360 } | 1435 } |
| 1361 if (child->isFloating()) { | 1436 if (child->isFloating()) { |
| 1362 insertFloatingObject(*child); | 1437 insertFloatingObject(*child); |
| 1363 adjustFloatingBlock(marginInfo); | 1438 adjustFloatingBlock(marginInfo); |
| 1364 continue; | 1439 continue; |
| 1365 } | 1440 } |
| 1366 if (child->isColumnSpanAll()) { | 1441 if (child->isColumnSpanAll()) { |
| 1367 // This is not the containing block of the spanner. The spanner's placehol
der will lay | 1442 // 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 | 1443 // 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 | 1444 // 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 | 1445 // following the spanner are laid out correctly. But first we apply the |
| 1371 // end up on the other side of the spanner. | 1446 // pending margin, so that it's taken into consideration and doesn't end |
| 1447 // up on the other side of the spanner. |
| 1372 setLogicalHeight(logicalHeight() + marginInfo.margin()); | 1448 setLogicalHeight(logicalHeight() + marginInfo.margin()); |
| 1373 marginInfo.clearMargin(); | 1449 marginInfo.clearMargin(); |
| 1374 | 1450 |
| 1375 child->spannerPlaceholder()->flowThread()->skipColumnSpanner( | 1451 child->spannerPlaceholder()->flowThread()->skipColumnSpanner( |
| 1376 child, offsetFromLogicalTopOfFirstPage() + logicalHeight()); | 1452 child, offsetFromLogicalTopOfFirstPage() + logicalHeight()); |
| 1377 continue; | 1453 continue; |
| 1378 } | 1454 } |
| 1379 | 1455 |
| 1380 // Lay out the child. | 1456 // Lay out the child. |
| 1381 layoutBlockChild(*child, layoutInfo); | 1457 layoutBlockChild(*child, layoutInfo); |
| 1382 layoutInfo.clearIsAtFirstInFlowChild(); | 1458 layoutInfo.clearIsAtFirstInFlowChild(); |
| 1383 lastNormalFlowChild = child; | 1459 lastNormalFlowChild = child; |
| 1384 } | 1460 } |
| 1385 | 1461 |
| 1386 // Now do the handling of the bottom of the block, adding in our bottom border
/padding and | 1462 // Now do the handling of the bottom of the block, adding in our bottom |
| 1387 // determining the correct collapsed bottom margin information. | 1463 // border/padding and determining the correct collapsed bottom margin |
| 1464 // information. |
| 1388 handleAfterSideOfBlock(lastNormalFlowChild, beforeEdge, afterEdge, | 1465 handleAfterSideOfBlock(lastNormalFlowChild, beforeEdge, afterEdge, |
| 1389 marginInfo); | 1466 marginInfo); |
| 1390 } | 1467 } |
| 1391 | 1468 |
| 1392 // Our MarginInfo state used when laying out block children. | 1469 // Our MarginInfo state used when laying out block children. |
| 1393 MarginInfo::MarginInfo(LayoutBlockFlow* blockFlow, | 1470 MarginInfo::MarginInfo(LayoutBlockFlow* blockFlow, |
| 1394 LayoutUnit beforeBorderPadding, | 1471 LayoutUnit beforeBorderPadding, |
| 1395 LayoutUnit afterBorderPadding) | 1472 LayoutUnit afterBorderPadding) |
| 1396 : m_canCollapseMarginAfterWithLastChild(true), | 1473 : m_canCollapseMarginAfterWithLastChild(true), |
| 1397 m_atBeforeSideOfBlock(true), | 1474 m_atBeforeSideOfBlock(true), |
| 1398 m_atAfterSideOfBlock(false), | 1475 m_atAfterSideOfBlock(false), |
| 1399 m_hasMarginBeforeQuirk(false), | 1476 m_hasMarginBeforeQuirk(false), |
| 1400 m_hasMarginAfterQuirk(false), | 1477 m_hasMarginAfterQuirk(false), |
| 1401 m_determinedMarginBeforeQuirk(false), | 1478 m_determinedMarginBeforeQuirk(false), |
| 1402 m_discardMargin(false), | 1479 m_discardMargin(false), |
| 1403 m_lastChildIsSelfCollapsingBlockWithClearance(false) { | 1480 m_lastChildIsSelfCollapsingBlockWithClearance(false) { |
| 1404 const ComputedStyle& blockStyle = blockFlow->styleRef(); | 1481 const ComputedStyle& blockStyle = blockFlow->styleRef(); |
| 1405 ASSERT(blockFlow->isLayoutView() || blockFlow->parent()); | 1482 ASSERT(blockFlow->isLayoutView() || blockFlow->parent()); |
| 1406 m_canCollapseWithChildren = !blockFlow->createsNewFormattingContext() && | 1483 m_canCollapseWithChildren = !blockFlow->createsNewFormattingContext() && |
| 1407 !blockFlow->isLayoutFlowThread() && | 1484 !blockFlow->isLayoutFlowThread() && |
| 1408 !blockFlow->isLayoutView(); | 1485 !blockFlow->isLayoutView(); |
| 1409 | 1486 |
| 1410 m_canCollapseMarginBeforeWithChildren = | 1487 m_canCollapseMarginBeforeWithChildren = |
| 1411 m_canCollapseWithChildren && !beforeBorderPadding && | 1488 m_canCollapseWithChildren && !beforeBorderPadding && |
| 1412 blockStyle.marginBeforeCollapse() != MarginCollapseSeparate; | 1489 blockStyle.marginBeforeCollapse() != MarginCollapseSeparate; |
| 1413 | 1490 |
| 1414 // If any height other than auto is specified in CSS, then we don't collapse o
ur bottom | 1491 // 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 | 1492 // 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 | 1493 // 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. | 1494 // and yet still collapse with it. We also don't collapse if we have any |
| 1495 // bottom border/padding. |
| 1418 m_canCollapseMarginAfterWithChildren = | 1496 m_canCollapseMarginAfterWithChildren = |
| 1419 m_canCollapseWithChildren && !afterBorderPadding && | 1497 m_canCollapseWithChildren && !afterBorderPadding && |
| 1420 (blockStyle.logicalHeight().isAuto() && | 1498 (blockStyle.logicalHeight().isAuto() && |
| 1421 !blockStyle.logicalHeight().value()) && | 1499 !blockStyle.logicalHeight().value()) && |
| 1422 blockStyle.marginAfterCollapse() != MarginCollapseSeparate; | 1500 blockStyle.marginAfterCollapse() != MarginCollapseSeparate; |
| 1423 | 1501 |
| 1424 m_quirkContainer = blockFlow->isTableCell() || blockFlow->isBody(); | 1502 m_quirkContainer = blockFlow->isTableCell() || blockFlow->isBody(); |
| 1425 | 1503 |
| 1426 m_discardMargin = m_canCollapseMarginBeforeWithChildren && | 1504 m_discardMargin = m_canCollapseMarginBeforeWithChildren && |
| 1427 blockFlow->mustDiscardMarginBefore(); | 1505 blockFlow->mustDiscardMarginBefore(); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1442 LayoutUnit childBeforeNegative; | 1520 LayoutUnit childBeforeNegative; |
| 1443 LayoutUnit childAfterPositive; | 1521 LayoutUnit childAfterPositive; |
| 1444 LayoutUnit childAfterNegative; | 1522 LayoutUnit childAfterNegative; |
| 1445 | 1523 |
| 1446 LayoutUnit beforeMargin; | 1524 LayoutUnit beforeMargin; |
| 1447 LayoutUnit afterMargin; | 1525 LayoutUnit afterMargin; |
| 1448 | 1526 |
| 1449 LayoutBlockFlow* childLayoutBlockFlow = | 1527 LayoutBlockFlow* childLayoutBlockFlow = |
| 1450 child.isLayoutBlockFlow() ? toLayoutBlockFlow(&child) : 0; | 1528 child.isLayoutBlockFlow() ? toLayoutBlockFlow(&child) : 0; |
| 1451 | 1529 |
| 1452 // If the child has the same directionality as we do, then we can just return
its | 1530 // If the child has the same directionality as we do, then we can just return |
| 1453 // margins in the same direction. | 1531 // its margins in the same direction. |
| 1454 if (!child.isWritingModeRoot()) { | 1532 if (!child.isWritingModeRoot()) { |
| 1455 if (childLayoutBlockFlow) { | 1533 if (childLayoutBlockFlow) { |
| 1456 childBeforePositive = childLayoutBlockFlow->maxPositiveMarginBefore(); | 1534 childBeforePositive = childLayoutBlockFlow->maxPositiveMarginBefore(); |
| 1457 childBeforeNegative = childLayoutBlockFlow->maxNegativeMarginBefore(); | 1535 childBeforeNegative = childLayoutBlockFlow->maxNegativeMarginBefore(); |
| 1458 childAfterPositive = childLayoutBlockFlow->maxPositiveMarginAfter(); | 1536 childAfterPositive = childLayoutBlockFlow->maxPositiveMarginAfter(); |
| 1459 childAfterNegative = childLayoutBlockFlow->maxNegativeMarginAfter(); | 1537 childAfterNegative = childLayoutBlockFlow->maxNegativeMarginAfter(); |
| 1460 } else { | 1538 } else { |
| 1461 beforeMargin = child.marginBefore(); | 1539 beforeMargin = child.marginBefore(); |
| 1462 afterMargin = child.marginAfter(); | 1540 afterMargin = child.marginAfter(); |
| 1463 } | 1541 } |
| 1464 } else if (child.isHorizontalWritingMode() == isHorizontalWritingMode()) { | 1542 } else if (child.isHorizontalWritingMode() == isHorizontalWritingMode()) { |
| 1465 // The child has a different directionality. If the child is parallel, then
it's just | 1543 // 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. | 1544 // it's just flipped relative to us. We can use the margins for the opposite |
| 1545 // edges. |
| 1467 if (childLayoutBlockFlow) { | 1546 if (childLayoutBlockFlow) { |
| 1468 childBeforePositive = childLayoutBlockFlow->maxPositiveMarginAfter(); | 1547 childBeforePositive = childLayoutBlockFlow->maxPositiveMarginAfter(); |
| 1469 childBeforeNegative = childLayoutBlockFlow->maxNegativeMarginAfter(); | 1548 childBeforeNegative = childLayoutBlockFlow->maxNegativeMarginAfter(); |
| 1470 childAfterPositive = childLayoutBlockFlow->maxPositiveMarginBefore(); | 1549 childAfterPositive = childLayoutBlockFlow->maxPositiveMarginBefore(); |
| 1471 childAfterNegative = childLayoutBlockFlow->maxNegativeMarginBefore(); | 1550 childAfterNegative = childLayoutBlockFlow->maxNegativeMarginBefore(); |
| 1472 } else { | 1551 } else { |
| 1473 beforeMargin = child.marginAfter(); | 1552 beforeMargin = child.marginAfter(); |
| 1474 afterMargin = child.marginBefore(); | 1553 afterMargin = child.marginBefore(); |
| 1475 } | 1554 } |
| 1476 } else { | 1555 } else { |
| 1477 // The child is perpendicular to us, which means its margins don't collapse
but are on the | 1556 // 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. | 1557 // but are on the "logical left/right" sides of the child box. We can just |
| 1558 // return the raw margin in this case. |
| 1479 beforeMargin = marginBeforeForChild(child); | 1559 beforeMargin = marginBeforeForChild(child); |
| 1480 afterMargin = marginAfterForChild(child); | 1560 afterMargin = marginAfterForChild(child); |
| 1481 } | 1561 } |
| 1482 | 1562 |
| 1483 // Resolve uncollapsing margins into their positive/negative buckets. | 1563 // Resolve uncollapsing margins into their positive/negative buckets. |
| 1484 if (beforeMargin) { | 1564 if (beforeMargin) { |
| 1485 if (beforeMargin > 0) | 1565 if (beforeMargin > 0) |
| 1486 childBeforePositive = beforeMargin; | 1566 childBeforePositive = beforeMargin; |
| 1487 else | 1567 else |
| 1488 childBeforeNegative = -beforeMargin; | 1568 childBeforeNegative = -beforeMargin; |
| 1489 } | 1569 } |
| 1490 if (afterMargin) { | 1570 if (afterMargin) { |
| 1491 if (afterMargin > 0) | 1571 if (afterMargin > 0) |
| 1492 childAfterPositive = afterMargin; | 1572 childAfterPositive = afterMargin; |
| 1493 else | 1573 else |
| 1494 childAfterNegative = -afterMargin; | 1574 childAfterNegative = -afterMargin; |
| 1495 } | 1575 } |
| 1496 | 1576 |
| 1497 return LayoutBlockFlow::MarginValues(childBeforePositive, childBeforeNegative, | 1577 return LayoutBlockFlow::MarginValues(childBeforePositive, childBeforeNegative, |
| 1498 childAfterPositive, childAfterNegative); | 1578 childAfterPositive, childAfterNegative); |
| 1499 } | 1579 } |
| 1500 | 1580 |
| 1501 LayoutUnit LayoutBlockFlow::collapseMargins(LayoutBox& child, | 1581 LayoutUnit LayoutBlockFlow::collapseMargins(LayoutBox& child, |
| 1502 MarginInfo& marginInfo, | 1582 MarginInfo& marginInfo, |
| 1503 bool childIsSelfCollapsing, | 1583 bool childIsSelfCollapsing, |
| 1504 bool childDiscardMarginBefore, | 1584 bool childDiscardMarginBefore, |
| 1505 bool childDiscardMarginAfter) { | 1585 bool childDiscardMarginAfter) { |
| 1506 // The child discards the before margin when the the after margin has discard
in the case of a self collapsing block. | 1586 // The child discards the before margin when the the after margin has discard |
| 1587 // in the case of a self collapsing block. |
| 1507 childDiscardMarginBefore = childDiscardMarginBefore || | 1588 childDiscardMarginBefore = childDiscardMarginBefore || |
| 1508 (childDiscardMarginAfter && childIsSelfCollapsing); | 1589 (childDiscardMarginAfter && childIsSelfCollapsing); |
| 1509 | 1590 |
| 1510 // Get the four margin values for the child and cache them. | 1591 // Get the four margin values for the child and cache them. |
| 1511 const LayoutBlockFlow::MarginValues childMargins = | 1592 const LayoutBlockFlow::MarginValues childMargins = |
| 1512 marginValuesForChild(child); | 1593 marginValuesForChild(child); |
| 1513 | 1594 |
| 1514 // Get our max pos and neg top margins. | 1595 // Get our max pos and neg top margins. |
| 1515 LayoutUnit posTop = childMargins.positiveMarginBefore(); | 1596 LayoutUnit posTop = childMargins.positiveMarginBefore(); |
| 1516 LayoutUnit negTop = childMargins.negativeMarginBefore(); | 1597 LayoutUnit negTop = childMargins.negativeMarginBefore(); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1549 if (!marginInfo.determinedMarginBeforeQuirk() && topQuirk && | 1630 if (!marginInfo.determinedMarginBeforeQuirk() && topQuirk && |
| 1550 !marginBefore()) { | 1631 !marginBefore()) { |
| 1551 // We have no top margin and our top child has a quirky margin. | 1632 // 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. | 1633 // We will pick up this quirky margin and pass it through. |
| 1553 // This deals with the <td><div><p> case. | 1634 // This deals with the <td><div><p> case. |
| 1554 // Don't do this for a block that split two inlines though. You do | 1635 // Don't do this for a block that split two inlines though. You do |
| 1555 // still apply margins in this case. | 1636 // still apply margins in this case. |
| 1556 setHasMarginBeforeQuirk(true); | 1637 setHasMarginBeforeQuirk(true); |
| 1557 } | 1638 } |
| 1558 } else { | 1639 } else { |
| 1559 // The before margin of the container will also discard all the margins it
is collapsing with. | 1640 // The before margin of the container will also discard all the margins it |
| 1641 // is collapsing with. |
| 1560 setMustDiscardMarginBefore(); | 1642 setMustDiscardMarginBefore(); |
| 1561 } | 1643 } |
| 1562 } | 1644 } |
| 1563 | 1645 |
| 1564 // Once we find a child with discardMarginBefore all the margins collapsing wi
th us must also discard. | 1646 // Once we find a child with discardMarginBefore all the margins collapsing |
| 1647 // with us must also discard. |
| 1565 if (childDiscardMarginBefore) { | 1648 if (childDiscardMarginBefore) { |
| 1566 marginInfo.setDiscardMargin(true); | 1649 marginInfo.setDiscardMargin(true); |
| 1567 marginInfo.clearMargin(); | 1650 marginInfo.clearMargin(); |
| 1568 } | 1651 } |
| 1569 | 1652 |
| 1570 if (marginInfo.quirkContainer() && marginInfo.atBeforeSideOfBlock() && | 1653 if (marginInfo.quirkContainer() && marginInfo.atBeforeSideOfBlock() && |
| 1571 (posTop - negTop)) | 1654 (posTop - negTop)) |
| 1572 marginInfo.setHasMarginBeforeQuirk(topQuirk); | 1655 marginInfo.setHasMarginBeforeQuirk(topQuirk); |
| 1573 | 1656 |
| 1574 LayoutUnit beforeCollapseLogicalTop = logicalHeight(); | 1657 LayoutUnit beforeCollapseLogicalTop = logicalHeight(); |
| 1575 LayoutUnit logicalTop = beforeCollapseLogicalTop; | 1658 LayoutUnit logicalTop = beforeCollapseLogicalTop; |
| 1576 | 1659 |
| 1577 LayoutObject* prev = child.previousSibling(); | 1660 LayoutObject* prev = child.previousSibling(); |
| 1578 LayoutBlockFlow* previousBlockFlow = | 1661 LayoutBlockFlow* previousBlockFlow = |
| 1579 prev && prev->isLayoutBlockFlow() && | 1662 prev && prev->isLayoutBlockFlow() && |
| 1580 !prev->isFloatingOrOutOfFlowPositioned() | 1663 !prev->isFloatingOrOutOfFlowPositioned() |
| 1581 ? toLayoutBlockFlow(prev) | 1664 ? toLayoutBlockFlow(prev) |
| 1582 : 0; | 1665 : 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 | 1666 // 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 | 1667 // 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. | 1668 // the float. Since we want to collapse the child's top margin with the self- |
| 1669 // collapsing block's top and bottom margins we need to adjust our parent's |
| 1670 // height to match the margin top of the self-collapsing block. If the |
| 1671 // resulting collapsed margin leaves the child still intruding into the float |
| 1672 // then we will want to clear it. |
| 1586 if (!marginInfo.canCollapseWithMarginBefore() && previousBlockFlow && | 1673 if (!marginInfo.canCollapseWithMarginBefore() && previousBlockFlow && |
| 1587 marginInfo.lastChildIsSelfCollapsingBlockWithClearance()) | 1674 marginInfo.lastChildIsSelfCollapsingBlockWithClearance()) |
| 1588 setLogicalHeight( | 1675 setLogicalHeight( |
| 1589 logicalHeight() - | 1676 logicalHeight() - |
| 1590 marginValuesForChild(*previousBlockFlow).positiveMarginBefore()); | 1677 marginValuesForChild(*previousBlockFlow).positiveMarginBefore()); |
| 1591 | 1678 |
| 1592 if (childIsSelfCollapsing) { | 1679 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. | 1680 // 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
. | 1681 // discarded. The block doesn't contribute anything to the height of the |
| 1682 // block. Also, the child's top position equals the logical height of the |
| 1683 // container. |
| 1595 if (!childDiscardMarginBefore && !marginInfo.discardMargin()) { | 1684 if (!childDiscardMarginBefore && !marginInfo.discardMargin()) { |
| 1596 // This child has no height. We need to compute our | 1685 // This child has no height. We need to compute our |
| 1597 // position before we collapse the child's margins together, | 1686 // position before we collapse the child's margins together, |
| 1598 // so that we can get an accurate position for the zero-height block. | 1687 // so that we can get an accurate position for the zero-height block. |
| 1599 LayoutUnit collapsedBeforePos = std::max( | 1688 LayoutUnit collapsedBeforePos = std::max( |
| 1600 marginInfo.positiveMargin(), childMargins.positiveMarginBefore()); | 1689 marginInfo.positiveMargin(), childMargins.positiveMarginBefore()); |
| 1601 LayoutUnit collapsedBeforeNeg = std::max( | 1690 LayoutUnit collapsedBeforeNeg = std::max( |
| 1602 marginInfo.negativeMargin(), childMargins.negativeMarginBefore()); | 1691 marginInfo.negativeMargin(), childMargins.negativeMarginBefore()); |
| 1603 marginInfo.setMargin(collapsedBeforePos, collapsedBeforeNeg); | 1692 marginInfo.setMargin(collapsedBeforePos, collapsedBeforeNeg); |
| 1604 | 1693 |
| 1605 // Now collapse the child's margins together, which means examining our | 1694 // Now collapse the child's margins together, which means examining our |
| 1606 // bottom margin values as well. | 1695 // bottom margin values as well. |
| 1607 marginInfo.setPositiveMarginIfLarger(childMargins.positiveMarginAfter()); | 1696 marginInfo.setPositiveMarginIfLarger(childMargins.positiveMarginAfter()); |
| 1608 marginInfo.setNegativeMarginIfLarger(childMargins.negativeMarginAfter()); | 1697 marginInfo.setNegativeMarginIfLarger(childMargins.negativeMarginAfter()); |
| 1609 | 1698 |
| 1610 if (!marginInfo.canCollapseWithMarginBefore()) { | 1699 if (!marginInfo.canCollapseWithMarginBefore()) { |
| 1611 // We need to make sure that the position of the self-collapsing block | 1700 // We need to make sure that the position of the self-collapsing block |
| 1612 // is correct, since it could have overflowing content | 1701 // is correct, since it could have overflowing content |
| 1613 // that needs to be positioned correctly (e.g., a block that | 1702 // that needs to be positioned correctly (e.g., a block that |
| 1614 // had a specified height of 0 but that actually had subcontent). | 1703 // had a specified height of 0 but that actually had subcontent). |
| 1615 logicalTop = logicalHeight() + collapsedBeforePos - collapsedBeforeNeg; | 1704 logicalTop = logicalHeight() + collapsedBeforePos - collapsedBeforeNeg; |
| 1616 } | 1705 } |
| 1617 } | 1706 } |
| 1618 } else { | 1707 } else { |
| 1619 if (mustSeparateMarginBeforeForChild(child)) { | 1708 if (mustSeparateMarginBeforeForChild(child)) { |
| 1620 ASSERT(!marginInfo.discardMargin() || | 1709 ASSERT(!marginInfo.discardMargin() || |
| 1621 (marginInfo.discardMargin() && !marginInfo.margin())); | 1710 (marginInfo.discardMargin() && !marginInfo.margin())); |
| 1622 // If we are at the before side of the block and we collapse, ignore the c
omputed margin | 1711 // 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 | 1712 // computed margin and just add the child margin to the container height. |
| 1624 // the child inside the container. | 1713 // This will correctly position the child inside the container. |
| 1625 LayoutUnit separateMargin = !marginInfo.canCollapseWithMarginBefore() | 1714 LayoutUnit separateMargin = !marginInfo.canCollapseWithMarginBefore() |
| 1626 ? marginInfo.margin() | 1715 ? marginInfo.margin() |
| 1627 : LayoutUnit(); | 1716 : LayoutUnit(); |
| 1628 setLogicalHeight(logicalHeight() + separateMargin + | 1717 setLogicalHeight(logicalHeight() + separateMargin + |
| 1629 marginBeforeForChild(child)); | 1718 marginBeforeForChild(child)); |
| 1630 logicalTop = logicalHeight(); | 1719 logicalTop = logicalHeight(); |
| 1631 } else if (!marginInfo.discardMargin() && | 1720 } else if (!marginInfo.discardMargin() && |
| 1632 (!marginInfo.atBeforeSideOfBlock() || | 1721 (!marginInfo.atBeforeSideOfBlock() || |
| 1633 (!marginInfo.canCollapseMarginBeforeWithChildren() && | 1722 (!marginInfo.canCollapseMarginBeforeWithChildren() && |
| 1634 (!document().inQuirksMode() || !marginInfo.quirkContainer() || | 1723 (!document().inQuirksMode() || !marginInfo.quirkContainer() || |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1647 marginInfo.setPositiveMargin(childMargins.positiveMarginAfter()); | 1736 marginInfo.setPositiveMargin(childMargins.positiveMarginAfter()); |
| 1648 marginInfo.setNegativeMargin(childMargins.negativeMarginAfter()); | 1737 marginInfo.setNegativeMargin(childMargins.negativeMarginAfter()); |
| 1649 } else { | 1738 } else { |
| 1650 marginInfo.clearMargin(); | 1739 marginInfo.clearMargin(); |
| 1651 } | 1740 } |
| 1652 | 1741 |
| 1653 if (marginInfo.margin()) | 1742 if (marginInfo.margin()) |
| 1654 marginInfo.setHasMarginAfterQuirk(hasMarginAfterQuirk(&child)); | 1743 marginInfo.setHasMarginAfterQuirk(hasMarginAfterQuirk(&child)); |
| 1655 } | 1744 } |
| 1656 | 1745 |
| 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 | 1746 // If margins would pull us past the top of the next page, then we need to |
| 1658 // collapsed into the page edge. | 1747 // pull back and pretend like the margins collapsed into the page edge. |
| 1659 LayoutState* layoutState = view()->layoutState(); | 1748 LayoutState* layoutState = view()->layoutState(); |
| 1660 if (layoutState->isPaginated() && | 1749 if (layoutState->isPaginated() && |
| 1661 isPageLogicalHeightKnown(beforeCollapseLogicalTop) && | 1750 isPageLogicalHeightKnown(beforeCollapseLogicalTop) && |
| 1662 logicalTop > beforeCollapseLogicalTop) { | 1751 logicalTop > beforeCollapseLogicalTop) { |
| 1663 LayoutUnit oldLogicalTop = logicalTop; | 1752 LayoutUnit oldLogicalTop = logicalTop; |
| 1664 logicalTop = | 1753 logicalTop = |
| 1665 std::min(logicalTop, nextPageLogicalTop(beforeCollapseLogicalTop)); | 1754 std::min(logicalTop, nextPageLogicalTop(beforeCollapseLogicalTop)); |
| 1666 setLogicalHeight(logicalHeight() + (logicalTop - oldLogicalTop)); | 1755 setLogicalHeight(logicalHeight() + (logicalTop - oldLogicalTop)); |
| 1667 } | 1756 } |
| 1668 | 1757 |
| 1669 if (previousBlockFlow) { | 1758 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 | 1759 // If |child| is a self-collapsing block it may have collapsed into a |
| 1671 // any floats from the parent will now overhang. | 1760 // previous sibling and although it hasn't reduced the height of the parent |
| 1761 // yet any floats from the parent will now overhang. |
| 1672 LayoutUnit oldLogicalHeight = logicalHeight(); | 1762 LayoutUnit oldLogicalHeight = logicalHeight(); |
| 1673 setLogicalHeight(logicalTop); | 1763 setLogicalHeight(logicalTop); |
| 1674 if (!previousBlockFlow->avoidsFloats() && | 1764 if (!previousBlockFlow->avoidsFloats() && |
| 1675 (previousBlockFlow->logicalTop() + | 1765 (previousBlockFlow->logicalTop() + |
| 1676 previousBlockFlow->lowestFloatLogicalBottom()) > logicalTop) | 1766 previousBlockFlow->lowestFloatLogicalBottom()) > logicalTop) |
| 1677 addOverhangingFloats(previousBlockFlow, false); | 1767 addOverhangingFloats(previousBlockFlow, false); |
| 1678 setLogicalHeight(oldLogicalHeight); | 1768 setLogicalHeight(oldLogicalHeight); |
| 1679 | 1769 |
| 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 | 1770 // 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 | 1771 // cleared a float and margin collapsing resulted in |child| moving up |
| 1682 // floats in the parent that overhang |child|'s new logical top. | 1772 // into the margin area of the self-collapsing block then the float it |
| 1773 // clears is now intruding into |child|. Layout again so that we can look |
| 1774 // for floats in the parent that overhang |child|'s new logical top. |
| 1683 bool logicalTopIntrudesIntoFloat = logicalTop < beforeCollapseLogicalTop; | 1775 bool logicalTopIntrudesIntoFloat = logicalTop < beforeCollapseLogicalTop; |
| 1684 if (logicalTopIntrudesIntoFloat && containsFloats() && | 1776 if (logicalTopIntrudesIntoFloat && containsFloats() && |
| 1685 !child.avoidsFloats() && lowestFloatLogicalBottom() > logicalTop) | 1777 !child.avoidsFloats() && lowestFloatLogicalBottom() > logicalTop) |
| 1686 child.setNeedsLayoutAndFullPaintInvalidation( | 1778 child.setNeedsLayoutAndFullPaintInvalidation( |
| 1687 LayoutInvalidationReason::AncestorMarginCollapsing); | 1779 LayoutInvalidationReason::AncestorMarginCollapsing); |
| 1688 } | 1780 } |
| 1689 | 1781 |
| 1690 return logicalTop; | 1782 return logicalTop; |
| 1691 } | 1783 } |
| 1692 | 1784 |
| 1693 void LayoutBlockFlow::adjustPositionedBlock( | 1785 void LayoutBlockFlow::adjustPositionedBlock( |
| 1694 LayoutBox& child, | 1786 LayoutBox& child, |
| 1695 const BlockChildrenLayoutInfo& layoutInfo) { | 1787 const BlockChildrenLayoutInfo& layoutInfo) { |
| 1696 LayoutUnit logicalTop = logicalHeight(); | 1788 LayoutUnit logicalTop = logicalHeight(); |
| 1697 | 1789 |
| 1698 // Forced breaks are only specified on in-flow objects, but auto-positioned ou
t-of-flow objects | 1790 // 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. | 1791 // out-of-flow objects may be affected by a break-after value of the previous |
| 1792 // in-flow object. |
| 1700 if (view()->layoutState()->isPaginated()) | 1793 if (view()->layoutState()->isPaginated()) |
| 1701 logicalTop = | 1794 logicalTop = |
| 1702 applyForcedBreak(logicalTop, layoutInfo.previousBreakAfterValue()); | 1795 applyForcedBreak(logicalTop, layoutInfo.previousBreakAfterValue()); |
| 1703 | 1796 |
| 1704 updateStaticInlinePositionForChild(child, logicalTop); | 1797 updateStaticInlinePositionForChild(child, logicalTop); |
| 1705 | 1798 |
| 1706 const MarginInfo& marginInfo = layoutInfo.marginInfo(); | 1799 const MarginInfo& marginInfo = layoutInfo.marginInfo(); |
| 1707 if (!marginInfo.canCollapseWithMarginBefore()) { | 1800 if (!marginInfo.canCollapseWithMarginBefore()) { |
| 1708 // Positioned blocks don't collapse margins, so add the margin provided by | 1801 // 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. | 1802 // the container now. The child's own margin is added later when calculating |
| 1803 // its logical top. |
| 1710 LayoutUnit collapsedBeforePos = marginInfo.positiveMargin(); | 1804 LayoutUnit collapsedBeforePos = marginInfo.positiveMargin(); |
| 1711 LayoutUnit collapsedBeforeNeg = marginInfo.negativeMargin(); | 1805 LayoutUnit collapsedBeforeNeg = marginInfo.negativeMargin(); |
| 1712 logicalTop += collapsedBeforePos - collapsedBeforeNeg; | 1806 logicalTop += collapsedBeforePos - collapsedBeforeNeg; |
| 1713 } | 1807 } |
| 1714 | 1808 |
| 1715 PaintLayer* childLayer = child.layer(); | 1809 PaintLayer* childLayer = child.layer(); |
| 1716 if (childLayer->staticBlockPosition() != logicalTop) | 1810 if (childLayer->staticBlockPosition() != logicalTop) |
| 1717 childLayer->setStaticBlockPosition(logicalTop); | 1811 childLayer->setStaticBlockPosition(logicalTop); |
| 1718 } | 1812 } |
| 1719 | 1813 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1730 if (!heightIncrease) | 1824 if (!heightIncrease) |
| 1731 return yPos; | 1825 return yPos; |
| 1732 | 1826 |
| 1733 if (childIsSelfCollapsing) { | 1827 if (childIsSelfCollapsing) { |
| 1734 marginInfo.setLastChildIsSelfCollapsingBlockWithClearance(true); | 1828 marginInfo.setLastChildIsSelfCollapsingBlockWithClearance(true); |
| 1735 marginInfo.setDiscardMargin(childDiscardMargin); | 1829 marginInfo.setDiscardMargin(childDiscardMargin); |
| 1736 | 1830 |
| 1737 // For self-collapsing blocks that clear, they can still collapse their | 1831 // For self-collapsing blocks that clear, they can still collapse their |
| 1738 // margins with following siblings. Reset the current margins to represent | 1832 // margins with following siblings. Reset the current margins to represent |
| 1739 // the self-collapsing block's margins only. | 1833 // the self-collapsing block's margins only. |
| 1740 // If DISCARD is specified for -webkit-margin-collapse, reset the margin val
ues. | 1834 // If DISCARD is specified for -webkit-margin-collapse, reset the margin |
| 1835 // values. |
| 1741 LayoutBlockFlow::MarginValues childMargins = marginValuesForChild(child); | 1836 LayoutBlockFlow::MarginValues childMargins = marginValuesForChild(child); |
| 1742 if (!childDiscardMargin) { | 1837 if (!childDiscardMargin) { |
| 1743 marginInfo.setPositiveMargin( | 1838 marginInfo.setPositiveMargin( |
| 1744 std::max(childMargins.positiveMarginBefore(), | 1839 std::max(childMargins.positiveMarginBefore(), |
| 1745 childMargins.positiveMarginAfter())); | 1840 childMargins.positiveMarginAfter())); |
| 1746 marginInfo.setNegativeMargin( | 1841 marginInfo.setNegativeMargin( |
| 1747 std::max(childMargins.negativeMarginBefore(), | 1842 std::max(childMargins.negativeMarginBefore(), |
| 1748 childMargins.negativeMarginAfter())); | 1843 childMargins.negativeMarginAfter())); |
| 1749 } else { | 1844 } else { |
| 1750 marginInfo.clearMargin(); | 1845 marginInfo.clearMargin(); |
| 1751 } | 1846 } |
| 1752 | 1847 |
| 1753 // CSS2.1 states: | 1848 // CSS2.1 states: |
| 1754 // "If the top and bottom margins of an element with clearance are adjoining
, its margins collapse with | 1849 // "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." | 1850 // 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 | 1851 // 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. | 1852 // margin of the parent block." |
| 1853 // So the parent's bottom margin cannot collapse through this block or any |
| 1854 // subsequent self-collapsing blocks. Set a bit to ensure this happens; it |
| 1855 // will get reset if we encounter an in-flow sibling that is not |
| 1856 // self-collapsing. |
| 1758 marginInfo.setCanCollapseMarginAfterWithLastChild(false); | 1857 marginInfo.setCanCollapseMarginAfterWithLastChild(false); |
| 1759 | 1858 |
| 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 | 1859 // 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 | 1860 // 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 | 1861 // own at the correct vertical position. If subsequent siblings attempt to |
| 1763 // margins can collapse at the correct vertical position. | 1862 // 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 | 1863 // 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], | 1864 // sits up 'inside' the float it's clearing) so that all three margins can |
| 1865 // collapse at the correct vertical position. |
| 1866 // Per CSS2.1 we need to ensure that any negative margin-top clears |child| |
| 1867 // beyond the bottom border-edge of the float so that the top border edge of |
| 1868 // the child (i.e. its clearance) is at a position that satisfies the |
| 1869 // equation: "the amount of clearance is set so that: |
| 1870 // clearance + margin-top = [height of float], |
| 1766 // i.e., clearance = [height of float] - margin-top". | 1871 // i.e., clearance = [height of float] - margin-top". |
| 1767 setLogicalHeight(child.logicalTop() + childMargins.negativeMarginBefore()); | 1872 setLogicalHeight(child.logicalTop() + childMargins.negativeMarginBefore()); |
| 1768 } else { | 1873 } else { |
| 1769 // Increase our height by the amount we had to clear. | 1874 // Increase our height by the amount we had to clear. |
| 1770 setLogicalHeight(logicalHeight() + heightIncrease); | 1875 setLogicalHeight(logicalHeight() + heightIncrease); |
| 1771 } | 1876 } |
| 1772 | 1877 |
| 1773 if (marginInfo.canCollapseWithMarginBefore()) { | 1878 if (marginInfo.canCollapseWithMarginBefore()) { |
| 1774 // We can no longer collapse with the top of the block since a clear | 1879 // We can no longer collapse with the top of the block since a clear |
| 1775 // occurred. The empty blocks collapse into the cleared block. | 1880 // occurred. The empty blocks collapse into the cleared block. |
| 1776 setMaxMarginBeforeValues(oldTopPosMargin, oldTopNegMargin); | 1881 setMaxMarginBeforeValues(oldTopPosMargin, oldTopNegMargin); |
| 1777 marginInfo.setAtBeforeSideOfBlock(false); | 1882 marginInfo.setAtBeforeSideOfBlock(false); |
| 1778 | 1883 |
| 1779 // In case the child discarded the before margin of the block we need to res
et the mustDiscardMarginBefore flag to the initial value. | 1884 // In case the child discarded the before margin of the block we need to |
| 1885 // reset the mustDiscardMarginBefore flag to the initial value. |
| 1780 setMustDiscardMarginBefore(style()->marginBeforeCollapse() == | 1886 setMustDiscardMarginBefore(style()->marginBeforeCollapse() == |
| 1781 MarginCollapseDiscard); | 1887 MarginCollapseDiscard); |
| 1782 } | 1888 } |
| 1783 | 1889 |
| 1784 return yPos + heightIncrease; | 1890 return yPos + heightIncrease; |
| 1785 } | 1891 } |
| 1786 | 1892 |
| 1787 void LayoutBlockFlow::setCollapsedBottomMargin(const MarginInfo& marginInfo) { | 1893 void LayoutBlockFlow::setCollapsedBottomMargin(const MarginInfo& marginInfo) { |
| 1788 if (marginInfo.canCollapseWithMarginAfter() && | 1894 if (marginInfo.canCollapseWithMarginAfter() && |
| 1789 !marginInfo.canCollapseWithMarginBefore()) { | 1895 !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. | 1896 // Update the after side margin of the container to discard if the after |
| 1897 // 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. | 1898 // Don't update the max margin values because we won't need them anyway. |
| 1792 if (marginInfo.discardMargin()) { | 1899 if (marginInfo.discardMargin()) { |
| 1793 setMustDiscardMarginAfter(); | 1900 setMustDiscardMarginAfter(); |
| 1794 return; | 1901 return; |
| 1795 } | 1902 } |
| 1796 | 1903 |
| 1797 // Update our max pos/neg bottom margins, since we collapsed our bottom marg
ins | 1904 // Update our max pos/neg bottom margins, since we collapsed our bottom |
| 1798 // with our children. | 1905 // margins with our children. |
| 1799 setMaxMarginAfterValues( | 1906 setMaxMarginAfterValues( |
| 1800 std::max(maxPositiveMarginAfter(), marginInfo.positiveMargin()), | 1907 std::max(maxPositiveMarginAfter(), marginInfo.positiveMargin()), |
| 1801 std::max(maxNegativeMarginAfter(), marginInfo.negativeMargin())); | 1908 std::max(maxNegativeMarginAfter(), marginInfo.negativeMargin())); |
| 1802 | 1909 |
| 1803 if (!marginInfo.hasMarginAfterQuirk()) | 1910 if (!marginInfo.hasMarginAfterQuirk()) |
| 1804 setHasMarginAfterQuirk(false); | 1911 setHasMarginAfterQuirk(false); |
| 1805 | 1912 |
| 1806 if (marginInfo.hasMarginAfterQuirk() && !marginAfter()) { | 1913 if (marginInfo.hasMarginAfterQuirk() && !marginAfter()) { |
| 1807 // We have no bottom margin and our last child has a quirky margin. | 1914 // 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. | 1915 // We will pick up this quirky margin and pass it through. |
| 1809 // This deals with the <td><div><p> case. | 1916 // This deals with the <td><div><p> case. |
| 1810 setHasMarginAfterQuirk(true); | 1917 setHasMarginAfterQuirk(true); |
| 1811 } | 1918 } |
| 1812 } | 1919 } |
| 1813 } | 1920 } |
| 1814 | 1921 |
| 1815 DISABLE_CFI_PERF | 1922 DISABLE_CFI_PERF |
| 1816 void LayoutBlockFlow::marginBeforeEstimateForChild( | 1923 void LayoutBlockFlow::marginBeforeEstimateForChild( |
| 1817 LayoutBox& child, | 1924 LayoutBox& child, |
| 1818 LayoutUnit& positiveMarginBefore, | 1925 LayoutUnit& positiveMarginBefore, |
| 1819 LayoutUnit& negativeMarginBefore, | 1926 LayoutUnit& negativeMarginBefore, |
| 1820 bool& discardMarginBefore) const { | 1927 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. | 1928 // 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. | 1929 // the child box is quirky. |
| 1930 // Give up if the child specified -webkit-margin-collapse: separate that |
| 1931 // prevents collapsing. |
| 1823 // FIXME: Use writing mode independent accessor for marginBeforeCollapse. | 1932 // FIXME: Use writing mode independent accessor for marginBeforeCollapse. |
| 1824 if ((document().inQuirksMode() && hasMarginBeforeQuirk(&child) && | 1933 if ((document().inQuirksMode() && hasMarginBeforeQuirk(&child) && |
| 1825 (isTableCell() || isBody())) || | 1934 (isTableCell() || isBody())) || |
| 1826 child.style()->marginBeforeCollapse() == MarginCollapseSeparate) | 1935 child.style()->marginBeforeCollapse() == MarginCollapseSeparate) |
| 1827 return; | 1936 return; |
| 1828 | 1937 |
| 1829 // The margins are discarded by a child that specified -webkit-margin-collapse
: discard. | 1938 // The margins are discarded by a child that specified |
| 1939 // -webkit-margin-collapse: discard. |
| 1830 // FIXME: Use writing mode independent accessor for marginBeforeCollapse. | 1940 // FIXME: Use writing mode independent accessor for marginBeforeCollapse. |
| 1831 if (child.style()->marginBeforeCollapse() == MarginCollapseDiscard) { | 1941 if (child.style()->marginBeforeCollapse() == MarginCollapseDiscard) { |
| 1832 positiveMarginBefore = LayoutUnit(); | 1942 positiveMarginBefore = LayoutUnit(); |
| 1833 negativeMarginBefore = LayoutUnit(); | 1943 negativeMarginBefore = LayoutUnit(); |
| 1834 discardMarginBefore = true; | 1944 discardMarginBefore = true; |
| 1835 return; | 1945 return; |
| 1836 } | 1946 } |
| 1837 | 1947 |
| 1838 LayoutUnit beforeChildMargin = marginBeforeForChild(child); | 1948 LayoutUnit beforeChildMargin = marginBeforeForChild(child); |
| 1839 positiveMarginBefore = std::max(positiveMarginBefore, beforeChildMargin); | 1949 positiveMarginBefore = std::max(positiveMarginBefore, beforeChildMargin); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1856 LayoutBox* grandchildBox = childBlockFlow->firstChildBox(); | 1966 LayoutBox* grandchildBox = childBlockFlow->firstChildBox(); |
| 1857 for (; grandchildBox; grandchildBox = grandchildBox->nextSiblingBox()) { | 1967 for (; grandchildBox; grandchildBox = grandchildBox->nextSiblingBox()) { |
| 1858 if (!grandchildBox->isFloatingOrOutOfFlowPositioned() && | 1968 if (!grandchildBox->isFloatingOrOutOfFlowPositioned() && |
| 1859 !grandchildBox->isColumnSpanAll()) | 1969 !grandchildBox->isColumnSpanAll()) |
| 1860 break; | 1970 break; |
| 1861 } | 1971 } |
| 1862 | 1972 |
| 1863 if (!grandchildBox) | 1973 if (!grandchildBox) |
| 1864 return; | 1974 return; |
| 1865 | 1975 |
| 1866 // Make sure to update the block margins now for the grandchild box so that we
're looking at current values. | 1976 // Make sure to update the block margins now for the grandchild box so that |
| 1977 // we're looking at current values. |
| 1867 if (grandchildBox->needsLayout()) { | 1978 if (grandchildBox->needsLayout()) { |
| 1868 grandchildBox->computeAndSetBlockDirectionMargins(this); | 1979 grandchildBox->computeAndSetBlockDirectionMargins(this); |
| 1869 if (grandchildBox->isLayoutBlock()) { | 1980 if (grandchildBox->isLayoutBlock()) { |
| 1870 LayoutBlock* grandchildBlock = toLayoutBlock(grandchildBox); | 1981 LayoutBlock* grandchildBlock = toLayoutBlock(grandchildBox); |
| 1871 grandchildBlock->setHasMarginBeforeQuirk( | 1982 grandchildBlock->setHasMarginBeforeQuirk( |
| 1872 grandchildBox->style()->hasMarginBeforeQuirk()); | 1983 grandchildBox->style()->hasMarginBeforeQuirk()); |
| 1873 grandchildBlock->setHasMarginAfterQuirk( | 1984 grandchildBlock->setHasMarginAfterQuirk( |
| 1874 grandchildBox->style()->hasMarginAfterQuirk()); | 1985 grandchildBox->style()->hasMarginAfterQuirk()); |
| 1875 } | 1986 } |
| 1876 } | 1987 } |
| 1877 | 1988 |
| 1878 // If we have a 'clear' value but also have a margin we may not actually requi
re clearance to move past any floats. | 1989 // 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 | 1990 // 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. | 1991 // sure we estimate the correct position including margins after any floats |
| 1992 // rather than use 'clearance' later which could give us the wrong position. |
| 1881 if (grandchildBox->style()->clear() != ClearNone && | 1993 if (grandchildBox->style()->clear() != ClearNone && |
| 1882 childBlockFlow->marginBeforeForChild(*grandchildBox) == 0) | 1994 childBlockFlow->marginBeforeForChild(*grandchildBox) == 0) |
| 1883 return; | 1995 return; |
| 1884 | 1996 |
| 1885 // Collapse the margin of the grandchild box with our own to produce an estima
te. | 1997 // Collapse the margin of the grandchild box with our own to produce an |
| 1998 // estimate. |
| 1886 childBlockFlow->marginBeforeEstimateForChild( | 1999 childBlockFlow->marginBeforeEstimateForChild( |
| 1887 *grandchildBox, positiveMarginBefore, negativeMarginBefore, | 2000 *grandchildBox, positiveMarginBefore, negativeMarginBefore, |
| 1888 discardMarginBefore); | 2001 discardMarginBefore); |
| 1889 } | 2002 } |
| 1890 | 2003 |
| 1891 LayoutUnit LayoutBlockFlow::estimateLogicalTopPosition( | 2004 LayoutUnit LayoutBlockFlow::estimateLogicalTopPosition( |
| 1892 LayoutBox& child, | 2005 LayoutBox& child, |
| 1893 const BlockChildrenLayoutInfo& layoutInfo, | 2006 const BlockChildrenLayoutInfo& layoutInfo, |
| 1894 LayoutUnit& estimateWithoutPagination) { | 2007 LayoutUnit& estimateWithoutPagination) { |
| 1895 const MarginInfo& marginInfo = layoutInfo.marginInfo(); | 2008 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 | 2009 // FIXME: We need to eliminate the estimation of vertical position, because |
| 2010 // when it's wrong we sometimes trigger a pathological |
| 1897 // relayout if there are intruding floats. | 2011 // relayout if there are intruding floats. |
| 1898 LayoutUnit logicalTopEstimate = logicalHeight(); | 2012 LayoutUnit logicalTopEstimate = logicalHeight(); |
| 1899 LayoutUnit positiveMarginBefore; | 2013 LayoutUnit positiveMarginBefore; |
| 1900 LayoutUnit negativeMarginBefore; | 2014 LayoutUnit negativeMarginBefore; |
| 1901 bool discardMarginBefore = false; | 2015 bool discardMarginBefore = false; |
| 1902 if (!marginInfo.canCollapseWithMarginBefore()) { | 2016 if (!marginInfo.canCollapseWithMarginBefore()) { |
| 1903 if (child.selfNeedsLayout()) { | 2017 if (child.selfNeedsLayout()) { |
| 1904 // Try to do a basic estimation of how the collapse is going to go. | 2018 // Try to do a basic estimation of how the collapse is going to go. |
| 1905 marginBeforeEstimateForChild(child, positiveMarginBefore, | 2019 marginBeforeEstimateForChild(child, positiveMarginBefore, |
| 1906 negativeMarginBefore, discardMarginBefore); | 2020 negativeMarginBefore, discardMarginBefore); |
| 1907 } else { | 2021 } else { |
| 1908 // Use the cached collapsed margin values from a previous layout. Most of
the time they | 2022 // Use the cached collapsed margin values from a previous layout. Most of |
| 1909 // will be right. | 2023 // the time they will be right. |
| 1910 LayoutBlockFlow::MarginValues marginValues = marginValuesForChild(child); | 2024 LayoutBlockFlow::MarginValues marginValues = marginValuesForChild(child); |
| 1911 positiveMarginBefore = | 2025 positiveMarginBefore = |
| 1912 std::max(positiveMarginBefore, marginValues.positiveMarginBefore()); | 2026 std::max(positiveMarginBefore, marginValues.positiveMarginBefore()); |
| 1913 negativeMarginBefore = | 2027 negativeMarginBefore = |
| 1914 std::max(negativeMarginBefore, marginValues.negativeMarginBefore()); | 2028 std::max(negativeMarginBefore, marginValues.negativeMarginBefore()); |
| 1915 discardMarginBefore = mustDiscardMarginBeforeForChild(child); | 2029 discardMarginBefore = mustDiscardMarginBeforeForChild(child); |
| 1916 } | 2030 } |
| 1917 | 2031 |
| 1918 // Collapse the result with our current margins. | 2032 // Collapse the result with our current margins. |
| 1919 if (!discardMarginBefore) | 2033 if (!discardMarginBefore) |
| 1920 logicalTopEstimate += | 2034 logicalTopEstimate += |
| 1921 std::max(marginInfo.positiveMargin(), positiveMarginBefore) - | 2035 std::max(marginInfo.positiveMargin(), positiveMarginBefore) - |
| 1922 std::max(marginInfo.negativeMargin(), negativeMarginBefore); | 2036 std::max(marginInfo.negativeMargin(), negativeMarginBefore); |
| 1923 } | 2037 } |
| 1924 | 2038 |
| 1925 // Adjust logicalTopEstimate down to the next page if the margins are so large
that we don't fit on the current | 2039 // Adjust logicalTopEstimate down to the next page if the margins are so large |
| 1926 // page. | 2040 // that we don't fit on the current page. |
| 1927 LayoutState* layoutState = view()->layoutState(); | 2041 LayoutState* layoutState = view()->layoutState(); |
| 1928 if (layoutState->isPaginated() && isPageLogicalHeightKnown(logicalHeight()) && | 2042 if (layoutState->isPaginated() && isPageLogicalHeightKnown(logicalHeight()) && |
| 1929 logicalTopEstimate > logicalHeight()) | 2043 logicalTopEstimate > logicalHeight()) |
| 1930 logicalTopEstimate = | 2044 logicalTopEstimate = |
| 1931 std::min(logicalTopEstimate, nextPageLogicalTop(logicalHeight())); | 2045 std::min(logicalTopEstimate, nextPageLogicalTop(logicalHeight())); |
| 1932 | 2046 |
| 1933 logicalTopEstimate += getClearDelta(&child, logicalTopEstimate); | 2047 logicalTopEstimate += getClearDelta(&child, logicalTopEstimate); |
| 1934 | 2048 |
| 1935 estimateWithoutPagination = logicalTopEstimate; | 2049 estimateWithoutPagination = logicalTopEstimate; |
| 1936 | 2050 |
| 1937 if (layoutState->isPaginated()) { | 2051 if (layoutState->isPaginated()) { |
| 1938 if (!layoutInfo.isAtFirstInFlowChild()) { | 2052 if (!layoutInfo.isAtFirstInFlowChild()) { |
| 1939 // Estimate the need for a forced break in front of this child. The final
break policy | 2053 // 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 | 2054 // 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 | 2055 // 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. | 2056 // set on first-children inside that get propagated up to the child. |
| 2057 // Just make an estimate with what we know so far. |
| 1943 EBreak breakValue = | 2058 EBreak breakValue = |
| 1944 child.classABreakPointValue(layoutInfo.previousBreakAfterValue()); | 2059 child.classABreakPointValue(layoutInfo.previousBreakAfterValue()); |
| 1945 if (isForcedFragmentainerBreakValue(breakValue)) { | 2060 if (isForcedFragmentainerBreakValue(breakValue)) { |
| 1946 logicalTopEstimate = applyForcedBreak(logicalHeight(), breakValue); | 2061 logicalTopEstimate = applyForcedBreak(logicalHeight(), breakValue); |
| 1947 // Disregard previous margins, since they will collapse with the fragmen
tainer | 2062 // Disregard previous margins, since they will collapse with the |
| 1948 // boundary, due to the forced break. Only apply margins that have been
specified | 2063 // fragmentainer boundary, due to the forced break. Only apply margins |
| 1949 // on the child or its descendants. | 2064 // that have been specified on the child or its descendants. |
| 1950 if (!discardMarginBefore) | 2065 if (!discardMarginBefore) |
| 1951 logicalTopEstimate += positiveMarginBefore - negativeMarginBefore; | 2066 logicalTopEstimate += positiveMarginBefore - negativeMarginBefore; |
| 1952 | 2067 |
| 1953 // Clearance may already have taken us past the beginning of the next | 2068 // Clearance may already have taken us past the beginning of the next |
| 1954 // fragmentainer. | 2069 // fragmentainer. |
| 1955 return std::max(estimateWithoutPagination, logicalTopEstimate); | 2070 return std::max(estimateWithoutPagination, logicalTopEstimate); |
| 1956 } | 2071 } |
| 1957 } | 2072 } |
| 1958 | 2073 |
| 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. | 2074 // For replaced elements and scrolled elements, we want to shift them to the |
| 2075 // next page if they don't fit on the current one. |
| 1960 logicalTopEstimate = adjustForUnsplittableChild(child, logicalTopEstimate); | 2076 logicalTopEstimate = adjustForUnsplittableChild(child, logicalTopEstimate); |
| 1961 } | 2077 } |
| 1962 | 2078 |
| 1963 return logicalTopEstimate; | 2079 return logicalTopEstimate; |
| 1964 } | 2080 } |
| 1965 | 2081 |
| 1966 void LayoutBlockFlow::adjustFloatingBlock(const MarginInfo& marginInfo) { | 2082 void LayoutBlockFlow::adjustFloatingBlock(const MarginInfo& marginInfo) { |
| 1967 // The float should be positioned taking into account the bottom margin | 2083 // 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 | 2084 // 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 | 2085 // float positioned properly, and then subtract the margin out of the |
| 1970 // height again. In the case of self-collapsing blocks, we always just | 2086 // height again. In the case of self-collapsing blocks, we always just |
| 1971 // use the top margins, since the self-collapsing block collapsed its | 2087 // use the top margins, since the self-collapsing block collapsed its |
| 1972 // own bottom margin into its top margin. | 2088 // own bottom margin into its top margin. |
| 1973 // | 2089 // |
| 1974 // Note also that the previous flow may collapse its margin into the top of | 2090 // 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 | 2091 // 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 | 2092 // height when computing the position of the float. This condition can be |
| 1977 // for by simply calling canCollapseWithMarginBefore. See | 2093 // tested for by simply calling canCollapseWithMarginBefore. See |
| 1978 // http://www.hixie.ch/tests/adhoc/css/box/block/margin-collapse/046.html for | 2094 // http://www.hixie.ch/tests/adhoc/css/box/block/margin-collapse/046.html for |
| 1979 // an example of this scenario. | 2095 // an example of this scenario. |
| 1980 LayoutUnit marginOffset = marginInfo.canCollapseWithMarginBefore() | 2096 LayoutUnit marginOffset = marginInfo.canCollapseWithMarginBefore() |
| 1981 ? LayoutUnit() | 2097 ? LayoutUnit() |
| 1982 : marginInfo.margin(); | 2098 : marginInfo.margin(); |
| 1983 setLogicalHeight(logicalHeight() + marginOffset); | 2099 setLogicalHeight(logicalHeight() + marginOffset); |
| 1984 positionNewFloats(); | 2100 positionNewFloats(); |
| 1985 setLogicalHeight(logicalHeight() - marginOffset); | 2101 setLogicalHeight(logicalHeight() - marginOffset); |
| 1986 } | 2102 } |
| 1987 | 2103 |
| 1988 void LayoutBlockFlow::handleAfterSideOfBlock(LayoutBox* lastChild, | 2104 void LayoutBlockFlow::handleAfterSideOfBlock(LayoutBox* lastChild, |
| 1989 LayoutUnit beforeSide, | 2105 LayoutUnit beforeSide, |
| 1990 LayoutUnit afterSide, | 2106 LayoutUnit afterSide, |
| 1991 MarginInfo& marginInfo) { | 2107 MarginInfo& marginInfo) { |
| 1992 marginInfo.setAtAfterSideOfBlock(true); | 2108 marginInfo.setAtAfterSideOfBlock(true); |
| 1993 | 2109 |
| 1994 // If our last child was a self-collapsing block with clearance then our logic
al height is flush with the | 2110 // 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 | 2111 // 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. | 2112 // clears. The correct vertical position for the margin-collapsing we want to |
| 2113 // perform now is at the child's margin-top - so adjust our height to that |
| 2114 // position. |
| 1997 if (marginInfo.lastChildIsSelfCollapsingBlockWithClearance()) { | 2115 if (marginInfo.lastChildIsSelfCollapsingBlockWithClearance()) { |
| 1998 ASSERT(lastChild); | 2116 ASSERT(lastChild); |
| 1999 setLogicalHeight(logicalHeight() - | 2117 setLogicalHeight(logicalHeight() - |
| 2000 marginValuesForChild(*lastChild).positiveMarginBefore()); | 2118 marginValuesForChild(*lastChild).positiveMarginBefore()); |
| 2001 } | 2119 } |
| 2002 | 2120 |
| 2003 if (marginInfo.canCollapseMarginAfterWithChildren() && | 2121 if (marginInfo.canCollapseMarginAfterWithChildren() && |
| 2004 !marginInfo.canCollapseMarginAfterWithLastChild()) | 2122 !marginInfo.canCollapseMarginAfterWithLastChild()) |
| 2005 marginInfo.setCanCollapseMarginAfterWithChildren(false); | 2123 marginInfo.setCanCollapseMarginAfterWithChildren(false); |
| 2006 | 2124 |
| 2007 // If we can't collapse with children then go ahead and add in the bottom marg
in. | 2125 // If we can't collapse with children then go ahead and add in the bottom |
| 2126 // margin. |
| 2008 if (!marginInfo.discardMargin() && | 2127 if (!marginInfo.discardMargin() && |
| 2009 (!marginInfo.canCollapseWithMarginAfter() && | 2128 (!marginInfo.canCollapseWithMarginAfter() && |
| 2010 !marginInfo.canCollapseWithMarginBefore() && | 2129 !marginInfo.canCollapseWithMarginBefore() && |
| 2011 (!document().inQuirksMode() || !marginInfo.quirkContainer() || | 2130 (!document().inQuirksMode() || !marginInfo.quirkContainer() || |
| 2012 !marginInfo.hasMarginAfterQuirk()))) | 2131 !marginInfo.hasMarginAfterQuirk()))) |
| 2013 setLogicalHeight(logicalHeight() + marginInfo.margin()); | 2132 setLogicalHeight(logicalHeight() + marginInfo.margin()); |
| 2014 | 2133 |
| 2015 // Now add in our bottom border/padding. | 2134 // Now add in our bottom border/padding. |
| 2016 setLogicalHeight(logicalHeight() + afterSide); | 2135 setLogicalHeight(logicalHeight() + afterSide); |
| 2017 | 2136 |
| 2018 // Negative margins can cause our height to shrink below our minimal height (b
order/padding). | 2137 // 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. | 2138 // (border/padding). If this happens, ensure that the computed height is |
| 2139 // increased to the minimal height. |
| 2020 setLogicalHeight(std::max(logicalHeight(), beforeSide + afterSide)); | 2140 setLogicalHeight(std::max(logicalHeight(), beforeSide + afterSide)); |
| 2021 | 2141 |
| 2022 // Update our bottom collapsed margin info. | 2142 // Update our bottom collapsed margin info. |
| 2023 setCollapsedBottomMargin(marginInfo); | 2143 setCollapsedBottomMargin(marginInfo); |
| 2024 | 2144 |
| 2025 // There's no class A break point right after the last child, only *between* s
iblings. So | 2145 // 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 | 2146 // 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 | 2147 // A break point (at the next in-flow block-level object), where we'll join |
| 2028 // value there. | 2148 // this break-after value with the break-before value there. |
| 2029 if (view()->layoutState()->isPaginated() && lastChild) | 2149 if (view()->layoutState()->isPaginated() && lastChild) |
| 2030 setBreakAfter( | 2150 setBreakAfter( |
| 2031 joinFragmentainerBreakValues(breakAfter(), lastChild->breakAfter())); | 2151 joinFragmentainerBreakValues(breakAfter(), lastChild->breakAfter())); |
| 2032 } | 2152 } |
| 2033 | 2153 |
| 2034 void LayoutBlockFlow::setMustDiscardMarginBefore(bool value) { | 2154 void LayoutBlockFlow::setMustDiscardMarginBefore(bool value) { |
| 2035 if (style()->marginBeforeCollapse() == MarginCollapseDiscard) { | 2155 if (style()->marginBeforeCollapse() == MarginCollapseDiscard) { |
| 2036 ASSERT(value); | 2156 ASSERT(value); |
| 2037 return; | 2157 return; |
| 2038 } | 2158 } |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2078 return child.isLayoutBlockFlow() | 2198 return child.isLayoutBlockFlow() |
| 2079 ? toLayoutBlockFlow(&child)->mustDiscardMarginBefore() | 2199 ? toLayoutBlockFlow(&child)->mustDiscardMarginBefore() |
| 2080 : (child.style()->marginBeforeCollapse() == | 2200 : (child.style()->marginBeforeCollapse() == |
| 2081 MarginCollapseDiscard); | 2201 MarginCollapseDiscard); |
| 2082 if (child.isHorizontalWritingMode() == isHorizontalWritingMode()) | 2202 if (child.isHorizontalWritingMode() == isHorizontalWritingMode()) |
| 2083 return child.isLayoutBlockFlow() | 2203 return child.isLayoutBlockFlow() |
| 2084 ? toLayoutBlockFlow(&child)->mustDiscardMarginAfter() | 2204 ? toLayoutBlockFlow(&child)->mustDiscardMarginAfter() |
| 2085 : (child.style()->marginAfterCollapse() == | 2205 : (child.style()->marginAfterCollapse() == |
| 2086 MarginCollapseDiscard); | 2206 MarginCollapseDiscard); |
| 2087 | 2207 |
| 2088 // FIXME: We return false here because the implementation is not geometrically
complete. We have values only for before/after, not start/end. | 2208 // 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
. | 2209 // complete. We have values only for before/after, not start/end. |
| 2210 // In case the boxes are perpendicular we assume the property is not |
| 2211 // specified. |
| 2090 return false; | 2212 return false; |
| 2091 } | 2213 } |
| 2092 | 2214 |
| 2093 bool LayoutBlockFlow::mustDiscardMarginAfterForChild( | 2215 bool LayoutBlockFlow::mustDiscardMarginAfterForChild( |
| 2094 const LayoutBox& child) const { | 2216 const LayoutBox& child) const { |
| 2095 ASSERT(!child.selfNeedsLayout()); | 2217 ASSERT(!child.selfNeedsLayout()); |
| 2096 if (!child.isWritingModeRoot()) | 2218 if (!child.isWritingModeRoot()) |
| 2097 return child.isLayoutBlockFlow() | 2219 return child.isLayoutBlockFlow() |
| 2098 ? toLayoutBlockFlow(&child)->mustDiscardMarginAfter() | 2220 ? toLayoutBlockFlow(&child)->mustDiscardMarginAfter() |
| 2099 : (child.style()->marginAfterCollapse() == | 2221 : (child.style()->marginAfterCollapse() == |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2153 return childStyle.marginBeforeCollapse() == MarginCollapseSeparate; | 2275 return childStyle.marginBeforeCollapse() == MarginCollapseSeparate; |
| 2154 | 2276 |
| 2155 // FIXME: See |mustDiscardMarginBeforeForChild| above. | 2277 // FIXME: See |mustDiscardMarginBeforeForChild| above. |
| 2156 return false; | 2278 return false; |
| 2157 } | 2279 } |
| 2158 | 2280 |
| 2159 LayoutUnit LayoutBlockFlow::applyForcedBreak(LayoutUnit logicalOffset, | 2281 LayoutUnit LayoutBlockFlow::applyForcedBreak(LayoutUnit logicalOffset, |
| 2160 EBreak breakValue) { | 2282 EBreak breakValue) { |
| 2161 if (!isForcedFragmentainerBreakValue(breakValue)) | 2283 if (!isForcedFragmentainerBreakValue(breakValue)) |
| 2162 return logicalOffset; | 2284 return logicalOffset; |
| 2163 // TODO(mstensho): honor breakValue. There are different types of forced break
s. We currently | 2285 // 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 | 2286 // 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 | 2287 // next fragmentainer of the fragmentation context we're in. However, we may |
| 2166 // inside a multicol container when printing. | 2288 // want to find the next left or right page - even if we're inside a multicol |
| 2289 // container when printing. |
| 2167 LayoutUnit pageLogicalHeight = pageLogicalHeightForOffset(logicalOffset); | 2290 LayoutUnit pageLogicalHeight = pageLogicalHeightForOffset(logicalOffset); |
| 2168 if (!pageLogicalHeight) | 2291 if (!pageLogicalHeight) |
| 2169 return logicalOffset; // Page height is still unknown, so we cannot insert
forced breaks. | 2292 return logicalOffset; // Page height is still unknown, so we cannot insert |
| 2293 // forced breaks. |
| 2170 LayoutUnit remainingLogicalHeight = pageRemainingLogicalHeightForOffset( | 2294 LayoutUnit remainingLogicalHeight = pageRemainingLogicalHeightForOffset( |
| 2171 logicalOffset, AssociateWithLatterPage); | 2295 logicalOffset, AssociateWithLatterPage); |
| 2172 if (remainingLogicalHeight == pageLogicalHeight) | 2296 if (remainingLogicalHeight == pageLogicalHeight) |
| 2173 return logicalOffset; // Don't break if we're already at the block start of
a fragmentainer. | 2297 return logicalOffset; // Don't break if we're already at the block start of |
| 2298 // a fragmentainer. |
| 2174 return logicalOffset + remainingLogicalHeight; | 2299 return logicalOffset + remainingLogicalHeight; |
| 2175 } | 2300 } |
| 2176 | 2301 |
| 2177 void LayoutBlockFlow::setBreakBefore(EBreak breakValue) { | 2302 void LayoutBlockFlow::setBreakBefore(EBreak breakValue) { |
| 2178 if (breakValue != BreakAuto && !isBreakBetweenControllable(breakValue)) | 2303 if (breakValue != BreakAuto && !isBreakBetweenControllable(breakValue)) |
| 2179 breakValue = BreakAuto; | 2304 breakValue = BreakAuto; |
| 2180 if (breakValue == BreakAuto && !m_rareData) | 2305 if (breakValue == BreakAuto && !m_rareData) |
| 2181 return; | 2306 return; |
| 2182 ensureRareData().m_breakBefore = breakValue; | 2307 ensureRareData().m_breakBefore = breakValue; |
| 2183 } | 2308 } |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2231 | 2356 |
| 2232 if (!hasHorizontalLayoutOverflow() && !hasVerticalLayoutOverflow()) | 2357 if (!hasHorizontalLayoutOverflow() && !hasVerticalLayoutOverflow()) |
| 2233 return; | 2358 return; |
| 2234 | 2359 |
| 2235 for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) { | 2360 for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) { |
| 2236 LayoutUnit top = std::max<LayoutUnit>(curr->lineTop(), curr->top()); | 2361 LayoutUnit top = std::max<LayoutUnit>(curr->lineTop(), curr->top()); |
| 2237 LayoutUnit bottom = | 2362 LayoutUnit bottom = |
| 2238 std::min<LayoutUnit>(curr->lineBottom(), curr->top() + curr->height()); | 2363 std::min<LayoutUnit>(curr->lineBottom(), curr->top() + curr->height()); |
| 2239 LayoutRect rect(layerOffset.x() + curr->x(), layerOffset.y() + top, | 2364 LayoutRect rect(layerOffset.x() + curr->x(), layerOffset.y() + top, |
| 2240 curr->width(), bottom - top); | 2365 curr->width(), bottom - top); |
| 2241 // It's common for this rect to be entirely contained in our box, so exclude
that simple case. | 2366 // It's common for this rect to be entirely contained in our box, so exclude |
| 2367 // that simple case. |
| 2242 if (!rect.isEmpty() && (rects.isEmpty() || !rects[0].contains(rect))) | 2368 if (!rect.isEmpty() && (rects.isEmpty() || !rects[0].contains(rect))) |
| 2243 rects.append(rect); | 2369 rects.append(rect); |
| 2244 } | 2370 } |
| 2245 } | 2371 } |
| 2246 | 2372 |
| 2247 void LayoutBlockFlow::absoluteRects( | 2373 void LayoutBlockFlow::absoluteRects( |
| 2248 Vector<IntRect>& rects, | 2374 Vector<IntRect>& rects, |
| 2249 const LayoutPoint& accumulatedOffset) const { | 2375 const LayoutPoint& accumulatedOffset) const { |
| 2250 if (!isAnonymousBlockContinuation()) { | 2376 if (!isAnonymousBlockContinuation()) { |
| 2251 LayoutBlock::absoluteRects(rects, accumulatedOffset); | 2377 LayoutBlock::absoluteRects(rects, accumulatedOffset); |
| 2252 return; | 2378 return; |
| 2253 } | 2379 } |
| 2254 // For blocks inside inlines, we go ahead and include margins so that we run r
ight up to the | 2380 // 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 | 2381 // right up to the inline boxes above and below us (thus getting merged with |
| 2256 // shape). | 2382 // them to form a single irregular shape). |
| 2257 // FIXME: This is wrong for vertical writing-modes. | 2383 // FIXME: This is wrong for vertical writing-modes. |
| 2258 // https://bugs.webkit.org/show_bug.cgi?id=46781 | 2384 // https://bugs.webkit.org/show_bug.cgi?id=46781 |
| 2259 LayoutRect rect(accumulatedOffset, size()); | 2385 LayoutRect rect(accumulatedOffset, size()); |
| 2260 rect.expand(collapsedMarginBoxLogicalOutsets()); | 2386 rect.expand(collapsedMarginBoxLogicalOutsets()); |
| 2261 rects.append(pixelSnappedIntRect(rect)); | 2387 rects.append(pixelSnappedIntRect(rect)); |
| 2262 continuation()->absoluteRects( | 2388 continuation()->absoluteRects( |
| 2263 rects, | 2389 rects, |
| 2264 accumulatedOffset - | 2390 accumulatedOffset - |
| 2265 toLayoutSize( | 2391 toLayoutSize( |
| 2266 location() + | 2392 location() + |
| 2267 inlineElementContinuation()->containingBlock()->location())); | 2393 inlineElementContinuation()->containingBlock()->location())); |
| 2268 } | 2394 } |
| 2269 | 2395 |
| 2270 void LayoutBlockFlow::absoluteQuads(Vector<FloatQuad>& quads) const { | 2396 void LayoutBlockFlow::absoluteQuads(Vector<FloatQuad>& quads) const { |
| 2271 if (!isAnonymousBlockContinuation()) { | 2397 if (!isAnonymousBlockContinuation()) { |
| 2272 LayoutBlock::absoluteQuads(quads); | 2398 LayoutBlock::absoluteQuads(quads); |
| 2273 return; | 2399 return; |
| 2274 } | 2400 } |
| 2275 // For blocks inside inlines, we go ahead and include margins so that we run r
ight up to the | 2401 // 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 | 2402 // right up to the inline boxes above and below us (thus getting merged with |
| 2277 // shape). | 2403 // them to form a single irregular shape). |
| 2278 // FIXME: This is wrong for vertical writing-modes. | 2404 // FIXME: This is wrong for vertical writing-modes. |
| 2279 // https://bugs.webkit.org/show_bug.cgi?id=46781 | 2405 // https://bugs.webkit.org/show_bug.cgi?id=46781 |
| 2280 LayoutRect localRect(LayoutPoint(), size()); | 2406 LayoutRect localRect(LayoutPoint(), size()); |
| 2281 localRect.expand(collapsedMarginBoxLogicalOutsets()); | 2407 localRect.expand(collapsedMarginBoxLogicalOutsets()); |
| 2282 quads.append(localToAbsoluteQuad(FloatRect(localRect))); | 2408 quads.append(localToAbsoluteQuad(FloatRect(localRect))); |
| 2283 continuation()->absoluteQuads(quads); | 2409 continuation()->absoluteQuads(quads); |
| 2284 } | 2410 } |
| 2285 | 2411 |
| 2286 LayoutObject* LayoutBlockFlow::hoverAncestor() const { | 2412 LayoutObject* LayoutBlockFlow::hoverAncestor() const { |
| 2287 return isAnonymousBlockContinuation() ? continuation() | 2413 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 | 2466 // 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 | 2467 // value other than 'visible', in which case the baseline is the bottom |
| 2342 // margin edge. | 2468 // margin edge. |
| 2343 // We likewise avoid using the last line box in the case of size containment, | 2469 // 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 | 2470 // where the block's contents shouldn't be considered when laying out its |
| 2345 // ancestors or siblings. | 2471 // ancestors or siblings. |
| 2346 | 2472 |
| 2347 if ((!style()->isOverflowVisible() && | 2473 if ((!style()->isOverflowVisible() && |
| 2348 !shouldIgnoreOverflowPropertyForInlineBlockBaseline()) || | 2474 !shouldIgnoreOverflowPropertyForInlineBlockBaseline()) || |
| 2349 style()->containsSize()) { | 2475 style()->containsSize()) { |
| 2350 // We are not calling baselinePosition here because the caller should add th
e margin-top/margin-right, not us. | 2476 // We are not calling baselinePosition here because the caller should add |
| 2477 // the margin-top/margin-right, not us. |
| 2351 return (lineDirection == HorizontalLine ? size().height() + marginBottom() | 2478 return (lineDirection == HorizontalLine ? size().height() + marginBottom() |
| 2352 : size().width() + marginLeft()) | 2479 : size().width() + marginLeft()) |
| 2353 .toInt(); | 2480 .toInt(); |
| 2354 } | 2481 } |
| 2355 if (isWritingModeRoot() && !isRubyRun()) | 2482 if (isWritingModeRoot() && !isRubyRun()) |
| 2356 return -1; | 2483 return -1; |
| 2357 if (!childrenInline()) | 2484 if (!childrenInline()) |
| 2358 return LayoutBlock::inlineBlockBaseline(lineDirection); | 2485 return LayoutBlock::inlineBlockBaseline(lineDirection); |
| 2359 if (lastLineBox()) | 2486 if (lastLineBox()) |
| 2360 return (lastLineBox()->logicalTop() + | 2487 return (lastLineBox()->logicalTop() + |
| (...skipping 12 matching lines...) Expand all Loading... |
| 2373 : borderRight() + paddingRight())) | 2500 : borderRight() + paddingRight())) |
| 2374 .toInt(); | 2501 .toInt(); |
| 2375 } | 2502 } |
| 2376 | 2503 |
| 2377 void LayoutBlockFlow::removeFloatingObjectsFromDescendants() { | 2504 void LayoutBlockFlow::removeFloatingObjectsFromDescendants() { |
| 2378 if (!containsFloats()) | 2505 if (!containsFloats()) |
| 2379 return; | 2506 return; |
| 2380 removeFloatingObjects(); | 2507 removeFloatingObjects(); |
| 2381 setChildNeedsLayout(MarkOnlyThis); | 2508 setChildNeedsLayout(MarkOnlyThis); |
| 2382 | 2509 |
| 2383 // If our children are inline, then the only boxes which could contain floats
are atomic inlines (e.g. inline-block, float etc.) | 2510 // 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. | 2511 // are atomic inlines (e.g. inline-block, float etc.) and these create |
| 2512 // formatting contexts, so can't pick up intruding floats from |
| 2513 // ancestors/siblings - making them safe to skip. |
| 2385 if (childrenInline()) | 2514 if (childrenInline()) |
| 2386 return; | 2515 return; |
| 2387 for (LayoutObject* child = firstChild(); child; | 2516 for (LayoutObject* child = firstChild(); child; |
| 2388 child = child->nextSibling()) { | 2517 child = child->nextSibling()) { |
| 2389 // We don't skip blocks that create formatting contexts as they may have onl
y recently | 2518 // 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. | 2519 // only recently changed style and their float lists may still contain |
| 2520 // floats from siblings and ancestors. |
| 2391 if (child->isLayoutBlockFlow()) | 2521 if (child->isLayoutBlockFlow()) |
| 2392 toLayoutBlockFlow(child)->removeFloatingObjectsFromDescendants(); | 2522 toLayoutBlockFlow(child)->removeFloatingObjectsFromDescendants(); |
| 2393 } | 2523 } |
| 2394 } | 2524 } |
| 2395 | 2525 |
| 2396 void LayoutBlockFlow::markAllDescendantsWithFloatsForLayout( | 2526 void LayoutBlockFlow::markAllDescendantsWithFloatsForLayout( |
| 2397 LayoutBox* floatToRemove, | 2527 LayoutBox* floatToRemove, |
| 2398 bool inLayout) { | 2528 bool inLayout) { |
| 2399 if (!everHadLayout() && !containsFloats()) | 2529 if (!everHadLayout() && !containsFloats()) |
| 2400 return; | 2530 return; |
| 2401 | 2531 |
| 2402 if (m_descendantsWithFloatsMarkedForLayout && !floatToRemove) | 2532 if (m_descendantsWithFloatsMarkedForLayout && !floatToRemove) |
| 2403 return; | 2533 return; |
| 2404 m_descendantsWithFloatsMarkedForLayout |= !floatToRemove; | 2534 m_descendantsWithFloatsMarkedForLayout |= !floatToRemove; |
| 2405 | 2535 |
| 2406 MarkingBehavior markParents = inLayout ? MarkOnlyThis : MarkContainerChain; | 2536 MarkingBehavior markParents = inLayout ? MarkOnlyThis : MarkContainerChain; |
| 2407 setChildNeedsLayout(markParents); | 2537 setChildNeedsLayout(markParents); |
| 2408 | 2538 |
| 2409 if (floatToRemove) | 2539 if (floatToRemove) |
| 2410 removeFloatingObject(floatToRemove); | 2540 removeFloatingObject(floatToRemove); |
| 2411 | 2541 |
| 2412 // Iterate over our children and mark them as needed. If our children are inli
ne, then the | 2542 // 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 | 2543 // 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. | 2544 // (e.g. inline-block, float etc.) and these create formatting contexts, so |
| 2545 // can't pick up intruding floats from ancestors/siblings - making them safe |
| 2546 // to skip. |
| 2415 if (!childrenInline()) { | 2547 if (!childrenInline()) { |
| 2416 for (LayoutObject* child = firstChild(); child; | 2548 for (LayoutObject* child = firstChild(); child; |
| 2417 child = child->nextSibling()) { | 2549 child = child->nextSibling()) { |
| 2418 if ((!floatToRemove && child->isFloatingOrOutOfFlowPositioned()) || | 2550 if ((!floatToRemove && child->isFloatingOrOutOfFlowPositioned()) || |
| 2419 !child->isLayoutBlock()) | 2551 !child->isLayoutBlock()) |
| 2420 continue; | 2552 continue; |
| 2421 if (!child->isLayoutBlockFlow()) { | 2553 if (!child->isLayoutBlockFlow()) { |
| 2422 LayoutBlock* childBlock = toLayoutBlock(child); | 2554 LayoutBlock* childBlock = toLayoutBlock(child); |
| 2423 if (childBlock->shrinkToAvoidFloats() && childBlock->everHadLayout()) | 2555 if (childBlock->shrinkToAvoidFloats() && childBlock->everHadLayout()) |
| 2424 childBlock->setChildNeedsLayout(markParents); | 2556 childBlock->setChildNeedsLayout(markParents); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2459 } | 2591 } |
| 2460 } | 2592 } |
| 2461 } | 2593 } |
| 2462 | 2594 |
| 2463 LayoutUnit LayoutBlockFlow::getClearDelta(LayoutBox* child, | 2595 LayoutUnit LayoutBlockFlow::getClearDelta(LayoutBox* child, |
| 2464 LayoutUnit logicalTop) { | 2596 LayoutUnit logicalTop) { |
| 2465 // There is no need to compute clearance if we have no floats. | 2597 // There is no need to compute clearance if we have no floats. |
| 2466 if (!containsFloats()) | 2598 if (!containsFloats()) |
| 2467 return LayoutUnit(); | 2599 return LayoutUnit(); |
| 2468 | 2600 |
| 2469 // At least one float is present. We need to perform the clearance computation
. | 2601 // At least one float is present. We need to perform the clearance |
| 2602 // computation. |
| 2470 bool clearSet = child->style()->clear() != ClearNone; | 2603 bool clearSet = child->style()->clear() != ClearNone; |
| 2471 LayoutUnit logicalBottom; | 2604 LayoutUnit logicalBottom; |
| 2472 switch (child->style()->clear()) { | 2605 switch (child->style()->clear()) { |
| 2473 case ClearNone: | 2606 case ClearNone: |
| 2474 break; | 2607 break; |
| 2475 case ClearLeft: | 2608 case ClearLeft: |
| 2476 logicalBottom = lowestFloatLogicalBottom(FloatingObject::FloatLeft); | 2609 logicalBottom = lowestFloatLogicalBottom(FloatingObject::FloatLeft); |
| 2477 break; | 2610 break; |
| 2478 case ClearRight: | 2611 case ClearRight: |
| 2479 logicalBottom = lowestFloatLogicalBottom(FloatingObject::FloatRight); | 2612 logicalBottom = lowestFloatLogicalBottom(FloatingObject::FloatRight); |
| 2480 break; | 2613 break; |
| 2481 case ClearBoth: | 2614 case ClearBoth: |
| 2482 logicalBottom = lowestFloatLogicalBottom(); | 2615 logicalBottom = lowestFloatLogicalBottom(); |
| 2483 break; | 2616 break; |
| 2484 } | 2617 } |
| 2485 | 2618 |
| 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). | 2619 // We also clear floats if we are too big to sit on the same line as a float |
| 2620 // (and wish to avoid floats by default). |
| 2487 LayoutUnit result = clearSet | 2621 LayoutUnit result = clearSet |
| 2488 ? (logicalBottom - logicalTop).clampNegativeToZero() | 2622 ? (logicalBottom - logicalTop).clampNegativeToZero() |
| 2489 : LayoutUnit(); | 2623 : LayoutUnit(); |
| 2490 if (!result && child->avoidsFloats()) { | 2624 if (!result && child->avoidsFloats()) { |
| 2491 LayoutUnit newLogicalTop = logicalTop; | 2625 LayoutUnit newLogicalTop = logicalTop; |
| 2492 LayoutRect borderBox = child->borderBoxRect(); | 2626 LayoutRect borderBox = child->borderBoxRect(); |
| 2493 LayoutUnit childLogicalWidthAtOldLogicalTopOffset = | 2627 LayoutUnit childLogicalWidthAtOldLogicalTopOffset = |
| 2494 isHorizontalWritingMode() ? borderBox.width() : borderBox.height(); | 2628 isHorizontalWritingMode() ? borderBox.width() : borderBox.height(); |
| 2495 while (true) { | 2629 while (true) { |
| 2496 LayoutUnit availableLogicalWidthAtNewLogicalTopOffset = | 2630 LayoutUnit availableLogicalWidthAtNewLogicalTopOffset = |
| 2497 availableLogicalWidthForLine(newLogicalTop, DoNotIndentText, | 2631 availableLogicalWidthForLine(newLogicalTop, DoNotIndentText, |
| 2498 logicalHeightForChild(*child)); | 2632 logicalHeightForChild(*child)); |
| 2499 if (availableLogicalWidthAtNewLogicalTopOffset == | 2633 if (availableLogicalWidthAtNewLogicalTopOffset == |
| 2500 availableLogicalWidthForContent()) | 2634 availableLogicalWidthForContent()) |
| 2501 return newLogicalTop - logicalTop; | 2635 return newLogicalTop - logicalTop; |
| 2502 | 2636 |
| 2503 LogicalExtentComputedValues computedValues; | 2637 LogicalExtentComputedValues computedValues; |
| 2504 child->logicalExtentAfterUpdatingLogicalWidth(newLogicalTop, | 2638 child->logicalExtentAfterUpdatingLogicalWidth(newLogicalTop, |
| 2505 computedValues); | 2639 computedValues); |
| 2506 LayoutUnit childLogicalWidthAtNewLogicalTopOffset = | 2640 LayoutUnit childLogicalWidthAtNewLogicalTopOffset = |
| 2507 computedValues.m_extent; | 2641 computedValues.m_extent; |
| 2508 | 2642 |
| 2509 if (childLogicalWidthAtNewLogicalTopOffset <= | 2643 if (childLogicalWidthAtNewLogicalTopOffset <= |
| 2510 availableLogicalWidthAtNewLogicalTopOffset) { | 2644 availableLogicalWidthAtNewLogicalTopOffset) { |
| 2511 // Even though we may not be moving, if the logical width did shrink bec
ause of the presence of new floats, then | 2645 // 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 | 2646 // 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). | 2647 // relayout as though we shifted. This happens because of the dynamic |
| 2648 // addition of overhanging floats from previous siblings when negative |
| 2649 // margins exist on a child (see the addOverhangingFloats call at the |
| 2650 // end of collapseMargins). |
| 2514 if (childLogicalWidthAtOldLogicalTopOffset != | 2651 if (childLogicalWidthAtOldLogicalTopOffset != |
| 2515 childLogicalWidthAtNewLogicalTopOffset) | 2652 childLogicalWidthAtNewLogicalTopOffset) |
| 2516 child->setChildNeedsLayout(MarkOnlyThis); | 2653 child->setChildNeedsLayout(MarkOnlyThis); |
| 2517 return newLogicalTop - logicalTop; | 2654 return newLogicalTop - logicalTop; |
| 2518 } | 2655 } |
| 2519 | 2656 |
| 2520 newLogicalTop = nextFloatLogicalBottomBelowForBlock(newLogicalTop); | 2657 newLogicalTop = nextFloatLogicalBottomBelowForBlock(newLogicalTop); |
| 2521 ASSERT(newLogicalTop >= logicalTop); | 2658 ASSERT(newLogicalTop >= logicalTop); |
| 2522 if (newLogicalTop < logicalTop) | 2659 if (newLogicalTop < logicalTop) |
| 2523 break; | 2660 break; |
| 2524 } | 2661 } |
| 2525 ASSERT_NOT_REACHED(); | 2662 ASSERT_NOT_REACHED(); |
| 2526 } | 2663 } |
| 2527 return result; | 2664 return result; |
| 2528 } | 2665 } |
| 2529 | 2666 |
| 2530 void LayoutBlockFlow::createFloatingObjects() { | 2667 void LayoutBlockFlow::createFloatingObjects() { |
| 2531 m_floatingObjects = | 2668 m_floatingObjects = |
| 2532 wrapUnique(new FloatingObjects(this, isHorizontalWritingMode())); | 2669 wrapUnique(new FloatingObjects(this, isHorizontalWritingMode())); |
| 2533 } | 2670 } |
| 2534 | 2671 |
| 2535 void LayoutBlockFlow::willBeDestroyed() { | 2672 void LayoutBlockFlow::willBeDestroyed() { |
| 2536 // Mark as being destroyed to avoid trouble with merges in removeChild(). | 2673 // Mark as being destroyed to avoid trouble with merges in removeChild(). |
| 2537 m_beingDestroyed = true; | 2674 m_beingDestroyed = true; |
| 2538 | 2675 |
| 2539 // Make sure to destroy anonymous children first while they are still connecte
d to the rest of the tree, so that they will | 2676 // 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. | 2677 // connected to the rest of the tree, so that they will properly dirty line |
| 2678 // boxes that they are removed from. Effects that do :before/:after only on |
| 2679 // hover could crash otherwise. |
| 2541 children()->destroyLeftoverChildren(); | 2680 children()->destroyLeftoverChildren(); |
| 2542 | 2681 |
| 2543 // Destroy our continuation before anything other than anonymous children. | 2682 // Destroy our continuation before anything other than anonymous children. |
| 2544 // The reason we don't destroy it before anonymous children is that they may | 2683 // 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. | 2684 // have continuations of their own that are anonymous children of our |
| 2685 // continuation. |
| 2546 LayoutBoxModelObject* continuation = this->continuation(); | 2686 LayoutBoxModelObject* continuation = this->continuation(); |
| 2547 if (continuation) { | 2687 if (continuation) { |
| 2548 continuation->destroy(); | 2688 continuation->destroy(); |
| 2549 setContinuation(nullptr); | 2689 setContinuation(nullptr); |
| 2550 } | 2690 } |
| 2551 | 2691 |
| 2552 if (!documentBeingDestroyed()) { | 2692 if (!documentBeingDestroyed()) { |
| 2553 // TODO(mstensho): figure out if we need this. We have no test coverage for
it. It looks | 2693 // 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. | 2694 // it. It looks like all line boxes have been removed at this point. |
| 2555 if (firstLineBox()) { | 2695 if (firstLineBox()) { |
| 2556 // We can't wait for LayoutBox::destroy to clear the selection, | 2696 // We can't wait for LayoutBox::destroy to clear the selection, |
| 2557 // because by then we will have nuked the line boxes. | 2697 // because by then we will have nuked the line boxes. |
| 2558 // FIXME: The FrameSelection should be responsible for this when it | 2698 // FIXME: The FrameSelection should be responsible for this when it |
| 2559 // is notified of DOM mutations. | 2699 // is notified of DOM mutations. |
| 2560 if (isSelectionBorder()) | 2700 if (isSelectionBorder()) |
| 2561 view()->clearSelection(); | 2701 view()->clearSelection(); |
| 2562 | 2702 |
| 2563 // If we are an anonymous block, then our line boxes might have children | 2703 // 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 | 2704 // that will outlast this block. In the non-anonymous block case those |
| (...skipping 26 matching lines...) Expand all Loading... |
| 2591 | 2731 |
| 2592 LayoutBlock::styleWillChange(diff, newStyle); | 2732 LayoutBlock::styleWillChange(diff, newStyle); |
| 2593 } | 2733 } |
| 2594 | 2734 |
| 2595 DISABLE_CFI_PERF | 2735 DISABLE_CFI_PERF |
| 2596 void LayoutBlockFlow::styleDidChange(StyleDifference diff, | 2736 void LayoutBlockFlow::styleDidChange(StyleDifference diff, |
| 2597 const ComputedStyle* oldStyle) { | 2737 const ComputedStyle* oldStyle) { |
| 2598 bool hadSelfPaintingLayer = hasSelfPaintingLayer(); | 2738 bool hadSelfPaintingLayer = hasSelfPaintingLayer(); |
| 2599 LayoutBlock::styleDidChange(diff, oldStyle); | 2739 LayoutBlock::styleDidChange(diff, oldStyle); |
| 2600 | 2740 |
| 2601 // After our style changed, if we lose our ability to propagate floats into ne
xt sibling | 2741 // 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 | 2742 // 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 | 2743 // 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. | 2744 // and clear all floats from its next sibling blocks that exist in our |
| 2745 // floating objects list. See crbug.com/56299 and crbug.com/62875. |
| 2605 bool canPropagateFloatIntoSibling = | 2746 bool canPropagateFloatIntoSibling = |
| 2606 !isFloatingOrOutOfFlowPositioned() && !avoidsFloats(); | 2747 !isFloatingOrOutOfFlowPositioned() && !avoidsFloats(); |
| 2607 bool siblingFloatPropagationChanged = | 2748 bool siblingFloatPropagationChanged = |
| 2608 diff.needsFullLayout() && s_canPropagateFloatIntoSibling && | 2749 diff.needsFullLayout() && s_canPropagateFloatIntoSibling && |
| 2609 !canPropagateFloatIntoSibling && hasOverhangingFloats(); | 2750 !canPropagateFloatIntoSibling && hasOverhangingFloats(); |
| 2610 | 2751 |
| 2611 // When this object's self-painting layer status changed, we should update Flo
atingObjects::shouldPaint() flags for | 2752 // When this object's self-painting layer status changed, we should update |
| 2612 // descendant overhanging floats in ancestors. | 2753 // FloatingObjects::shouldPaint() flags for descendant overhanging floats in |
| 2754 // ancestors. |
| 2613 bool needsUpdateAncestorFloatObjectShouldPaintFlags = false; | 2755 bool needsUpdateAncestorFloatObjectShouldPaintFlags = false; |
| 2614 if (hasSelfPaintingLayer() != hadSelfPaintingLayer && | 2756 if (hasSelfPaintingLayer() != hadSelfPaintingLayer && |
| 2615 hasOverhangingFloats()) { | 2757 hasOverhangingFloats()) { |
| 2616 setNeedsLayout(LayoutInvalidationReason::StyleChange); | 2758 setNeedsLayout(LayoutInvalidationReason::StyleChange); |
| 2617 if (hadSelfPaintingLayer) | 2759 if (hadSelfPaintingLayer) |
| 2618 markAllDescendantsWithFloatsForLayout(); | 2760 markAllDescendantsWithFloatsForLayout(); |
| 2619 else | 2761 else |
| 2620 needsUpdateAncestorFloatObjectShouldPaintFlags = true; | 2762 needsUpdateAncestorFloatObjectShouldPaintFlags = true; |
| 2621 } | 2763 } |
| 2622 | 2764 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 2647 parentBlockFlow->markAllDescendantsWithFloatsForLayout(); | 2789 parentBlockFlow->markAllDescendantsWithFloatsForLayout(); |
| 2648 if (siblingFloatPropagationChanged) | 2790 if (siblingFloatPropagationChanged) |
| 2649 parentBlockFlow->markSiblingsWithFloatsForLayout(); | 2791 parentBlockFlow->markSiblingsWithFloatsForLayout(); |
| 2650 } | 2792 } |
| 2651 | 2793 |
| 2652 if (diff.needsFullLayout() || !oldStyle) | 2794 if (diff.needsFullLayout() || !oldStyle) |
| 2653 createOrDestroyMultiColumnFlowThreadIfNeeded(oldStyle); | 2795 createOrDestroyMultiColumnFlowThreadIfNeeded(oldStyle); |
| 2654 if (oldStyle) { | 2796 if (oldStyle) { |
| 2655 if (LayoutMultiColumnFlowThread* flowThread = multiColumnFlowThread()) { | 2797 if (LayoutMultiColumnFlowThread* flowThread = multiColumnFlowThread()) { |
| 2656 if (!style()->columnRuleEquivalent(oldStyle)) { | 2798 if (!style()->columnRuleEquivalent(oldStyle)) { |
| 2657 // Column rules are painted by anonymous column set children of the mult
icol | 2799 // Column rules are painted by anonymous column set children of the |
| 2658 // container. We need to notify them. | 2800 // multicol container. We need to notify them. |
| 2659 flowThread->columnRuleStyleDidChange(); | 2801 flowThread->columnRuleStyleDidChange(); |
| 2660 } | 2802 } |
| 2661 } | 2803 } |
| 2662 } | 2804 } |
| 2663 } | 2805 } |
| 2664 | 2806 |
| 2665 void LayoutBlockFlow::updateBlockChildDirtyBitsBeforeLayout( | 2807 void LayoutBlockFlow::updateBlockChildDirtyBitsBeforeLayout( |
| 2666 bool relayoutChildren, | 2808 bool relayoutChildren, |
| 2667 LayoutBox& child) { | 2809 LayoutBox& child) { |
| 2668 if (child.isLayoutMultiColumnSpannerPlaceholder()) | 2810 if (child.isLayoutMultiColumnSpannerPlaceholder()) |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2704 return; | 2846 return; |
| 2705 } | 2847 } |
| 2706 | 2848 |
| 2707 if (beforeChild && beforeChild->parent() != this) { | 2849 if (beforeChild && beforeChild->parent() != this) { |
| 2708 addChildBeforeDescendant(newChild, beforeChild); | 2850 addChildBeforeDescendant(newChild, beforeChild); |
| 2709 return; | 2851 return; |
| 2710 } | 2852 } |
| 2711 | 2853 |
| 2712 bool madeBoxesNonInline = false; | 2854 bool madeBoxesNonInline = false; |
| 2713 | 2855 |
| 2714 // A block has to either have all of its children inline, or all of its childr
en as blocks. | 2856 // 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 | 2857 // children as blocks. |
| 2716 // inline children into anonymous block boxes. | 2858 // So, if our children are currently inline and a block child has to be |
| 2859 // inserted, we move all our inline children into anonymous block boxes. |
| 2717 bool childIsBlockLevel = | 2860 bool childIsBlockLevel = |
| 2718 !newChild->isInline() && !newChild->isFloatingOrOutOfFlowPositioned(); | 2861 !newChild->isInline() && !newChild->isFloatingOrOutOfFlowPositioned(); |
| 2719 if (childrenInline()) { | 2862 if (childrenInline()) { |
| 2720 if (childIsBlockLevel) { | 2863 if (childIsBlockLevel) { |
| 2721 // Wrap the inline content in anonymous blocks, to allow for the new block
child to be | 2864 // Wrap the inline content in anonymous blocks, to allow for the new block |
| 2722 // inserted. | 2865 // child to be inserted. |
| 2723 makeChildrenNonInline(beforeChild); | 2866 makeChildrenNonInline(beforeChild); |
| 2724 madeBoxesNonInline = true; | 2867 madeBoxesNonInline = true; |
| 2725 | 2868 |
| 2726 if (beforeChild && beforeChild->parent() != this) { | 2869 if (beforeChild && beforeChild->parent() != this) { |
| 2727 beforeChild = beforeChild->parent(); | 2870 beforeChild = beforeChild->parent(); |
| 2728 ASSERT(beforeChild->isAnonymousBlock()); | 2871 ASSERT(beforeChild->isAnonymousBlock()); |
| 2729 ASSERT(beforeChild->parent() == this); | 2872 ASSERT(beforeChild->parent() == this); |
| 2730 } | 2873 } |
| 2731 } | 2874 } |
| 2732 } else if (!childIsBlockLevel) { | 2875 } else if (!childIsBlockLevel) { |
| 2733 // This block has block children. We may want to put the new child into an a
nomyous | 2876 // 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, | 2877 // 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 | 2878 // 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, | 2879 // 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. | 2880 // other hand, we *have to* put it inside an anonymous block, so create a |
| 2881 // new one if there is none for us there already. |
| 2738 LayoutObject* afterChild = | 2882 LayoutObject* afterChild = |
| 2739 beforeChild ? beforeChild->previousSibling() : lastChild(); | 2883 beforeChild ? beforeChild->previousSibling() : lastChild(); |
| 2740 | 2884 |
| 2741 if (afterChild && afterChild->isAnonymousBlock()) { | 2885 if (afterChild && afterChild->isAnonymousBlock()) { |
| 2742 afterChild->addChild(newChild); | 2886 afterChild->addChild(newChild); |
| 2743 return; | 2887 return; |
| 2744 } | 2888 } |
| 2745 | 2889 |
| 2746 if (newChild->isInline()) { | 2890 if (newChild->isInline()) { |
| 2747 // No suitable existing anonymous box - create a new one. | 2891 // No suitable existing anonymous box - create a new one. |
| 2748 LayoutBlockFlow* newBlock = toLayoutBlockFlow(createAnonymousBlock()); | 2892 LayoutBlockFlow* newBlock = toLayoutBlockFlow(createAnonymousBlock()); |
| 2749 LayoutBox::addChild(newBlock, beforeChild); | 2893 LayoutBox::addChild(newBlock, beforeChild); |
| 2750 // Reparent adjacent floating or out-of-flow siblings to the new box. | 2894 // Reparent adjacent floating or out-of-flow siblings to the new box. |
| 2751 newBlock->reparentPrecedingFloatingOrOutOfFlowSiblings(); | 2895 newBlock->reparentPrecedingFloatingOrOutOfFlowSiblings(); |
| 2752 newBlock->addChild(newChild); | 2896 newBlock->addChild(newChild); |
| 2753 newBlock->reparentSubsequentFloatingOrOutOfFlowSiblings(); | 2897 newBlock->reparentSubsequentFloatingOrOutOfFlowSiblings(); |
| 2754 return; | 2898 return; |
| 2755 } | 2899 } |
| 2756 } | 2900 } |
| 2757 | 2901 |
| 2758 // Skip the LayoutBlock override, since that one deals with anonymous child in
sertion in a way | 2902 // 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. | 2903 // insertion in a way that isn't sufficient for us, and can only cause trouble |
| 2904 // at this point. |
| 2760 LayoutBox::addChild(newChild, beforeChild); | 2905 LayoutBox::addChild(newChild, beforeChild); |
| 2761 | 2906 |
| 2762 if (madeBoxesNonInline && parent() && isAnonymousBlock() && | 2907 if (madeBoxesNonInline && parent() && isAnonymousBlock() && |
| 2763 parent()->isLayoutBlock() && !parent()->createsAnonymousWrapper()) { | 2908 parent()->isLayoutBlock() && !parent()->createsAnonymousWrapper()) { |
| 2764 toLayoutBlock(parent())->removeLeftoverAnonymousBlock(this); | 2909 toLayoutBlock(parent())->removeLeftoverAnonymousBlock(this); |
| 2765 // |this| may be dead now. | 2910 // |this| may be dead now. |
| 2766 } | 2911 } |
| 2767 } | 2912 } |
| 2768 | 2913 |
| 2769 static bool isMergeableAnonymousBlock(const LayoutBlockFlow* block) { | 2914 static bool isMergeableAnonymousBlock(const LayoutBlockFlow* block) { |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2839 ASSERT_NOT_REACHED(); | 2984 ASSERT_NOT_REACHED(); |
| 2840 | 2985 |
| 2841 break; | 2986 break; |
| 2842 } | 2987 } |
| 2843 setContinuation(nullptr); | 2988 setContinuation(nullptr); |
| 2844 destroy(); | 2989 destroy(); |
| 2845 } | 2990 } |
| 2846 } else if (!beingDestroyed() && | 2991 } else if (!beingDestroyed() && |
| 2847 !oldChild->isFloatingOrOutOfFlowPositioned() && | 2992 !oldChild->isFloatingOrOutOfFlowPositioned() && |
| 2848 !oldChild->isAnonymousBlock()) { | 2993 !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. | 2994 // If the child we're removing means that we can now treat all children as |
| 2995 // inline without the need for anonymous blocks, then do that. |
| 2850 makeChildrenInlineIfPossible(); | 2996 makeChildrenInlineIfPossible(); |
| 2851 } | 2997 } |
| 2852 } | 2998 } |
| 2853 | 2999 |
| 2854 void LayoutBlockFlow::moveAllChildrenIncludingFloatsTo(LayoutBlock* toBlock, | 3000 void LayoutBlockFlow::moveAllChildrenIncludingFloatsTo(LayoutBlock* toBlock, |
| 2855 bool fullRemoveInsert) { | 3001 bool fullRemoveInsert) { |
| 2856 LayoutBlockFlow* toBlockFlow = toLayoutBlockFlow(toBlock); | 3002 LayoutBlockFlow* toBlockFlow = toLayoutBlockFlow(toBlock); |
| 2857 moveAllChildrenTo(toBlockFlow, fullRemoveInsert); | 3003 moveAllChildrenTo(toBlockFlow, fullRemoveInsert); |
| 2858 | 3004 |
| 2859 // When a portion of the layout tree is being detached, anonymous blocks | 3005 // 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 | 3006 // 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. | 3007 // 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 | 3008 // 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 | 3009 // 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 | 3010 // 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 | 3011 // 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 | 3012 // 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 | 3013 // 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 | 3014 // 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 | 3015 // any floating objects list. In order to preserve this condition (removing it |
| 2870 // (removing it has serious performance implications), we need to copy the | 3016 // has serious performance implications), we need to copy the floating objects |
| 2871 // floating objects from the old block (this) to the new block (toBlockFlow). | 3017 // from the old block (this) to the new block (toBlockFlow). |
| 2872 // The float's metrics will likely all be wrong, but since toBlockFlow is | 3018 // 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 | 3019 // already marked for layout, this will get fixed before anything gets |
| 2874 // displayed. | 3020 // displayed. |
| 2875 // See bug https://code.google.com/p/chromium/issues/detail?id=230907 | 3021 // See bug https://code.google.com/p/chromium/issues/detail?id=230907 |
| 2876 if (m_floatingObjects) { | 3022 if (m_floatingObjects) { |
| 2877 if (!toBlockFlow->m_floatingObjects) | 3023 if (!toBlockFlow->m_floatingObjects) |
| 2878 toBlockFlow->createFloatingObjects(); | 3024 toBlockFlow->createFloatingObjects(); |
| 2879 | 3025 |
| 2880 const FloatingObjectSet& fromFloatingObjectSet = m_floatingObjects->set(); | 3026 const FloatingObjectSet& fromFloatingObjectSet = m_floatingObjects->set(); |
| 2881 FloatingObjectSetIterator end = fromFloatingObjectSet.end(); | 3027 FloatingObjectSetIterator end = fromFloatingObjectSet.end(); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 2894 } | 3040 } |
| 2895 | 3041 |
| 2896 void LayoutBlockFlow::childBecameFloatingOrOutOfFlow(LayoutBox* child) { | 3042 void LayoutBlockFlow::childBecameFloatingOrOutOfFlow(LayoutBox* child) { |
| 2897 makeChildrenInlineIfPossible(); | 3043 makeChildrenInlineIfPossible(); |
| 2898 | 3044 |
| 2899 // Reparent the child to an adjacent anonymous block if one is available. | 3045 // Reparent the child to an adjacent anonymous block if one is available. |
| 2900 LayoutObject* prev = child->previousSibling(); | 3046 LayoutObject* prev = child->previousSibling(); |
| 2901 if (prev && prev->isAnonymousBlock() && prev->isLayoutBlockFlow()) { | 3047 if (prev && prev->isAnonymousBlock() && prev->isLayoutBlockFlow()) { |
| 2902 LayoutBlockFlow* newContainer = toLayoutBlockFlow(prev); | 3048 LayoutBlockFlow* newContainer = toLayoutBlockFlow(prev); |
| 2903 moveChildTo(newContainer, child, nullptr, false); | 3049 moveChildTo(newContainer, child, nullptr, false); |
| 2904 // The anonymous block we've moved to may now be adjacent to former siblings
of ours | 3050 // The anonymous block we've moved to may now be adjacent to former siblings |
| 2905 // that it can contain also. | 3051 // of ours that it can contain also. |
| 2906 newContainer->reparentSubsequentFloatingOrOutOfFlowSiblings(); | 3052 newContainer->reparentSubsequentFloatingOrOutOfFlowSiblings(); |
| 2907 return; | 3053 return; |
| 2908 } | 3054 } |
| 2909 LayoutObject* next = child->nextSibling(); | 3055 LayoutObject* next = child->nextSibling(); |
| 2910 if (next && next->isAnonymousBlock() && next->isLayoutBlockFlow()) { | 3056 if (next && next->isAnonymousBlock() && next->isLayoutBlockFlow()) { |
| 2911 LayoutBlockFlow* newContainer = toLayoutBlockFlow(next); | 3057 LayoutBlockFlow* newContainer = toLayoutBlockFlow(next); |
| 2912 moveChildTo(newContainer, child, newContainer->firstChild(), false); | 3058 moveChildTo(newContainer, child, newContainer->firstChild(), false); |
| 2913 } | 3059 } |
| 2914 } | 3060 } |
| 2915 | 3061 |
| 2916 void LayoutBlockFlow::collapseAnonymousBlockChild(LayoutBlockFlow* child) { | 3062 void LayoutBlockFlow::collapseAnonymousBlockChild(LayoutBlockFlow* child) { |
| 2917 // It's possible that this block's destruction may have been triggered by the | 3063 // 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 | 3064 // child's removal. Just bail if the anonymous child block is already being |
| 2919 // destroyed. See crbug.com/282088 | 3065 // destroyed. See crbug.com/282088 |
| 2920 if (child->beingDestroyed()) | 3066 if (child->beingDestroyed()) |
| 2921 return; | 3067 return; |
| 2922 if (child->continuation()) | 3068 if (child->continuation()) |
| 2923 return; | 3069 return; |
| 2924 // Ruby elements use anonymous wrappers for ruby runs and ruby bases by design
, so we don't remove them. | 3070 // Ruby elements use anonymous wrappers for ruby runs and ruby bases by |
| 3071 // design, so we don't remove them. |
| 2925 if (child->isRubyRun() || child->isRubyBase()) | 3072 if (child->isRubyRun() || child->isRubyBase()) |
| 2926 return; | 3073 return; |
| 2927 setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation( | 3074 setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation( |
| 2928 LayoutInvalidationReason::ChildAnonymousBlockChanged); | 3075 LayoutInvalidationReason::ChildAnonymousBlockChanged); |
| 2929 | 3076 |
| 2930 child->moveAllChildrenTo(this, child->nextSibling(), child->hasLayer()); | 3077 child->moveAllChildrenTo(this, child->nextSibling(), child->hasLayer()); |
| 2931 setChildrenInline(child->childrenInline()); | 3078 setChildrenInline(child->childrenInline()); |
| 2932 | 3079 |
| 2933 children()->removeChildNode(this, child, child->hasLayer()); | 3080 children()->removeChildNode(this, child, child->hasLayer()); |
| 2934 child->destroy(); | 3081 child->destroy(); |
| 2935 } | 3082 } |
| 2936 | 3083 |
| 2937 bool LayoutBlockFlow::mergeSiblingContiguousAnonymousBlock( | 3084 bool LayoutBlockFlow::mergeSiblingContiguousAnonymousBlock( |
| 2938 LayoutBlockFlow* siblingThatMayBeDeleted) { | 3085 LayoutBlockFlow* siblingThatMayBeDeleted) { |
| 2939 // Note: |this| and |siblingThatMayBeDeleted| may not be adjacent siblings at
this point. There | 3086 // Note: |this| and |siblingThatMayBeDeleted| may not be adjacent siblings at |
| 2940 // may be an object between them which is about to be removed. | 3087 // this point. There may be an object between them which is about to be |
| 3088 // removed. |
| 2941 | 3089 |
| 2942 if (!isMergeableAnonymousBlock(this) || | 3090 if (!isMergeableAnonymousBlock(this) || |
| 2943 !isMergeableAnonymousBlock(siblingThatMayBeDeleted)) | 3091 !isMergeableAnonymousBlock(siblingThatMayBeDeleted)) |
| 2944 return false; | 3092 return false; |
| 2945 | 3093 |
| 2946 setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation( | 3094 setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation( |
| 2947 LayoutInvalidationReason::AnonymousBlockChange); | 3095 LayoutInvalidationReason::AnonymousBlockChange); |
| 2948 | 3096 |
| 2949 // If the inlineness of children of the two block don't match, we'd need speci
al code here | 3097 // If the inlineness of children of the two block don't match, we'd need |
| 2950 // (but there should be no need for it). | 3098 // special code here (but there should be no need for it). |
| 2951 ASSERT(siblingThatMayBeDeleted->childrenInline() == childrenInline()); | 3099 ASSERT(siblingThatMayBeDeleted->childrenInline() == childrenInline()); |
| 2952 // Take all the children out of the |next| block and put them in | 3100 // Take all the children out of the |next| block and put them in |
| 2953 // the |prev| block. | 3101 // the |prev| block. |
| 2954 siblingThatMayBeDeleted->moveAllChildrenIncludingFloatsTo( | 3102 siblingThatMayBeDeleted->moveAllChildrenIncludingFloatsTo( |
| 2955 this, siblingThatMayBeDeleted->hasLayer() || hasLayer()); | 3103 this, siblingThatMayBeDeleted->hasLayer() || hasLayer()); |
| 2956 // Delete the now-empty block's lines and nuke it. | 3104 // Delete the now-empty block's lines and nuke it. |
| 2957 siblingThatMayBeDeleted->deleteLineBoxTree(); | 3105 siblingThatMayBeDeleted->deleteLineBoxTree(); |
| 2958 siblingThatMayBeDeleted->destroy(); | 3106 siblingThatMayBeDeleted->destroy(); |
| 2959 return true; | 3107 return true; |
| 2960 } | 3108 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 2986 LayoutBlockFlow* parentBlockFlow = toLayoutBlockFlow(parent()); | 3134 LayoutBlockFlow* parentBlockFlow = toLayoutBlockFlow(parent()); |
| 2987 LayoutObject* child = previousSibling(); | 3135 LayoutObject* child = previousSibling(); |
| 2988 while (child && child->isFloatingOrOutOfFlowPositioned()) { | 3136 while (child && child->isFloatingOrOutOfFlowPositioned()) { |
| 2989 LayoutObject* sibling = child->previousSibling(); | 3137 LayoutObject* sibling = child->previousSibling(); |
| 2990 parentBlockFlow->moveChildTo(this, child, firstChild(), false); | 3138 parentBlockFlow->moveChildTo(this, child, firstChild(), false); |
| 2991 child = sibling; | 3139 child = sibling; |
| 2992 } | 3140 } |
| 2993 } | 3141 } |
| 2994 | 3142 |
| 2995 void LayoutBlockFlow::makeChildrenInlineIfPossible() { | 3143 void LayoutBlockFlow::makeChildrenInlineIfPossible() { |
| 2996 // Collapsing away anonymous wrappers isn't relevant for the children of anony
mous blocks, unless they are ruby bases. | 3144 // Collapsing away anonymous wrappers isn't relevant for the children of |
| 3145 // anonymous blocks, unless they are ruby bases. |
| 2997 if (isAnonymousBlock() && !isRubyBase()) | 3146 if (isAnonymousBlock() && !isRubyBase()) |
| 2998 return; | 3147 return; |
| 2999 | 3148 |
| 3000 Vector<LayoutBlockFlow*, 3> blocksToRemove; | 3149 Vector<LayoutBlockFlow*, 3> blocksToRemove; |
| 3001 for (LayoutObject* child = firstChild(); child; | 3150 for (LayoutObject* child = firstChild(); child; |
| 3002 child = child->nextSibling()) { | 3151 child = child->nextSibling()) { |
| 3003 if (child->isFloating()) | 3152 if (child->isFloating()) |
| 3004 continue; | 3153 continue; |
| 3005 if (child->isOutOfFlowPositioned()) | 3154 if (child->isOutOfFlowPositioned()) |
| 3006 continue; | 3155 continue; |
| 3007 | 3156 |
| 3008 // There are still block children in the container, so any anonymous wrapper
s are still needed. | 3157 // There are still block children in the container, so any anonymous |
| 3158 // wrappers are still needed. |
| 3009 if (!child->isAnonymousBlock() || !child->isLayoutBlockFlow()) | 3159 if (!child->isAnonymousBlock() || !child->isLayoutBlockFlow()) |
| 3010 return; | 3160 return; |
| 3011 // If one of the children is being destroyed then it is unsafe to clean up a
nonymous wrappers as the | 3161 // If one of the children is being destroyed then it is unsafe to clean up |
| 3162 // anonymous wrappers as the |
| 3012 // entire branch may be being destroyed. | 3163 // entire branch may be being destroyed. |
| 3013 if (toLayoutBlockFlow(child)->beingDestroyed()) | 3164 if (toLayoutBlockFlow(child)->beingDestroyed()) |
| 3014 return; | 3165 return; |
| 3015 // We can't remove anonymous wrappers if they contain continuations as this
means there are block children present. | 3166 // We can't remove anonymous wrappers if they contain continuations as this |
| 3167 // means there are block children present. |
| 3016 if (toLayoutBlockFlow(child)->continuation()) | 3168 if (toLayoutBlockFlow(child)->continuation()) |
| 3017 return; | 3169 return; |
| 3018 // We are only interested in removing anonymous wrappers if there are inline
siblings underneath them. | 3170 // We are only interested in removing anonymous wrappers if there are inline |
| 3171 // siblings underneath them. |
| 3019 if (!child->childrenInline()) | 3172 if (!child->childrenInline()) |
| 3020 return; | 3173 return; |
| 3021 // Ruby elements use anonymous wrappers for ruby runs and ruby bases by desi
gn, so we don't remove them. | 3174 // Ruby elements use anonymous wrappers for ruby runs and ruby bases by |
| 3175 // design, so we don't remove them. |
| 3022 if (child->isRubyRun() || child->isRubyBase()) | 3176 if (child->isRubyRun() || child->isRubyBase()) |
| 3023 return; | 3177 return; |
| 3024 | 3178 |
| 3025 blocksToRemove.append(toLayoutBlockFlow(child)); | 3179 blocksToRemove.append(toLayoutBlockFlow(child)); |
| 3026 } | 3180 } |
| 3027 | 3181 |
| 3028 // If we make an object's children inline we are going to frustrate any future
attempts to remove | 3182 // 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 | 3183 // attempts to remove floats from its children's float-lists before the next |
| 3030 // now - they will be rebuilt at layout. | 3184 // layout happens so clear down all the floatlists now - they will be rebuilt |
| 3185 // at layout. |
| 3031 removeFloatingObjectsFromDescendants(); | 3186 removeFloatingObjectsFromDescendants(); |
| 3032 | 3187 |
| 3033 for (size_t i = 0; i < blocksToRemove.size(); i++) | 3188 for (size_t i = 0; i < blocksToRemove.size(); i++) |
| 3034 collapseAnonymousBlockChild(blocksToRemove[i]); | 3189 collapseAnonymousBlockChild(blocksToRemove[i]); |
| 3035 setChildrenInline(true); | 3190 setChildrenInline(true); |
| 3036 } | 3191 } |
| 3037 | 3192 |
| 3038 static void getInlineRun(LayoutObject* start, | 3193 static void getInlineRun(LayoutObject* start, |
| 3039 LayoutObject* boundary, | 3194 LayoutObject* boundary, |
| 3040 LayoutObject*& inlineRunStart, | 3195 LayoutObject*& inlineRunStart, |
| 3041 LayoutObject*& inlineRunEnd) { | 3196 LayoutObject*& inlineRunEnd) { |
| 3042 // Beginning at |start| we find the largest contiguous run of inlines that | 3197 // 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| | 3198 // 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 | 3199 // and |inlineRunEnd|. Note that these two values may be the same if |
| 3045 // we encounter only one inline. | 3200 // we encounter only one inline. |
| 3046 // | 3201 // |
| 3047 // We skip any non-inlines we encounter as long as we haven't found any | 3202 // We skip any non-inlines we encounter as long as we haven't found any |
| 3048 // inlines yet. | 3203 // inlines yet. |
| 3049 // | 3204 // |
| 3050 // |boundary| indicates a non-inclusive boundary point. Regardless of whether
|boundary| | 3205 // |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 | 3206 // |boundary| is inline or not, we will not include it in a run with inlines |
| 3052 // a non-inline. | 3207 // before it. It's as though we encountered a non-inline. |
| 3053 | 3208 |
| 3054 // Start by skipping as many non-inlines as we can. | 3209 // Start by skipping as many non-inlines as we can. |
| 3055 LayoutObject* curr = start; | 3210 LayoutObject* curr = start; |
| 3056 bool sawInline; | 3211 bool sawInline; |
| 3057 do { | 3212 do { |
| 3058 while (curr && | 3213 while (curr && |
| 3059 !(curr->isInline() || curr->isFloatingOrOutOfFlowPositioned())) | 3214 !(curr->isInline() || curr->isFloatingOrOutOfFlowPositioned())) |
| 3060 curr = curr->nextSibling(); | 3215 curr = curr->nextSibling(); |
| 3061 | 3216 |
| 3062 inlineRunStart = inlineRunEnd = curr; | 3217 inlineRunStart = inlineRunEnd = curr; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 3073 inlineRunEnd = curr; | 3228 inlineRunEnd = curr; |
| 3074 if (curr->isInline()) | 3229 if (curr->isInline()) |
| 3075 sawInline = true; | 3230 sawInline = true; |
| 3076 curr = curr->nextSibling(); | 3231 curr = curr->nextSibling(); |
| 3077 } | 3232 } |
| 3078 } while (!sawInline); | 3233 } while (!sawInline); |
| 3079 } | 3234 } |
| 3080 | 3235 |
| 3081 void LayoutBlockFlow::makeChildrenNonInline(LayoutObject* insertionPoint) { | 3236 void LayoutBlockFlow::makeChildrenNonInline(LayoutObject* insertionPoint) { |
| 3082 // makeChildrenNonInline takes a block whose children are *all* inline and it | 3237 // makeChildrenNonInline takes a block whose children are *all* inline and it |
| 3083 // makes sure that inline children are coalesced under anonymous | 3238 // makes sure that inline children are coalesced under anonymous blocks. |
| 3084 // blocks. If |insertionPoint| is defined, then it represents the insertion p
oint for | 3239 // 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 | 3240 // 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 | 3241 // 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, | 3242 // inlines following |insertionPoint|, because the new child is going to be |
| 3088 // splitting them. | 3243 // inserted in between the inlines, splitting them. |
| 3089 ASSERT(!isInline() || isAtomicInlineLevel()); | 3244 ASSERT(!isInline() || isAtomicInlineLevel()); |
| 3090 ASSERT(!insertionPoint || insertionPoint->parent() == this); | 3245 ASSERT(!insertionPoint || insertionPoint->parent() == this); |
| 3091 | 3246 |
| 3092 setChildrenInline(false); | 3247 setChildrenInline(false); |
| 3093 | 3248 |
| 3094 LayoutObject* child = firstChild(); | 3249 LayoutObject* child = firstChild(); |
| 3095 if (!child) | 3250 if (!child) |
| 3096 return; | 3251 return; |
| 3097 | 3252 |
| 3098 deleteLineBoxTree(); | 3253 deleteLineBoxTree(); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3161 | 3316 |
| 3162 m_floatingObjects->clear(); | 3317 m_floatingObjects->clear(); |
| 3163 } | 3318 } |
| 3164 | 3319 |
| 3165 LayoutPoint LayoutBlockFlow::flipFloatForWritingModeForChild( | 3320 LayoutPoint LayoutBlockFlow::flipFloatForWritingModeForChild( |
| 3166 const FloatingObject& child, | 3321 const FloatingObject& child, |
| 3167 const LayoutPoint& point) const { | 3322 const LayoutPoint& point) const { |
| 3168 if (!style()->isFlippedBlocksWritingMode()) | 3323 if (!style()->isFlippedBlocksWritingMode()) |
| 3169 return point; | 3324 return point; |
| 3170 | 3325 |
| 3171 // This is similar to LayoutBox::flipForWritingModeForChild. We have to subtra
ct out our left offsets twice, since | 3326 // 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 | 3327 // subtract out our left offsets twice, since it's going to get added back in. |
| 3173 // case. | 3328 // We hide this complication here so that the calling code looks normal for |
| 3329 // the unflipped case. |
| 3174 return LayoutPoint(point.x() + size().width() - | 3330 return LayoutPoint(point.x() + size().width() - |
| 3175 child.layoutObject()->size().width() - | 3331 child.layoutObject()->size().width() - |
| 3176 2 * xPositionForFloatIncludingMargin(child), | 3332 2 * xPositionForFloatIncludingMargin(child), |
| 3177 point.y()); | 3333 point.y()); |
| 3178 } | 3334 } |
| 3179 | 3335 |
| 3180 LayoutUnit LayoutBlockFlow::logicalLeftOffsetForPositioningFloat( | 3336 LayoutUnit LayoutBlockFlow::logicalLeftOffsetForPositioningFloat( |
| 3181 LayoutUnit logicalTop, | 3337 LayoutUnit logicalTop, |
| 3182 LayoutUnit fixedOffset, | 3338 LayoutUnit fixedOffset, |
| 3183 LayoutUnit* heightRemaining) const { | 3339 LayoutUnit* heightRemaining) const { |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3306 FloatingObjectSetIterator it = | 3462 FloatingObjectSetIterator it = |
| 3307 floatingObjectSet.find<FloatingObjectHashTranslator>(&floatBox); | 3463 floatingObjectSet.find<FloatingObjectHashTranslator>(&floatBox); |
| 3308 if (it != floatingObjectSet.end()) | 3464 if (it != floatingObjectSet.end()) |
| 3309 return it->get(); | 3465 return it->get(); |
| 3310 } | 3466 } |
| 3311 | 3467 |
| 3312 // Create the special object entry & append it to the list | 3468 // Create the special object entry & append it to the list |
| 3313 | 3469 |
| 3314 std::unique_ptr<FloatingObject> newObj = FloatingObject::create(&floatBox); | 3470 std::unique_ptr<FloatingObject> newObj = FloatingObject::create(&floatBox); |
| 3315 | 3471 |
| 3316 // Our location is irrelevant if we're unsplittable or no pagination is in eff
ect. | 3472 // Our location is irrelevant if we're unsplittable or no pagination is in |
| 3317 // Just go ahead and lay out the float. | 3473 // effect. Just go ahead and lay out the float. |
| 3318 bool isChildLayoutBlock = floatBox.isLayoutBlock(); | 3474 bool isChildLayoutBlock = floatBox.isLayoutBlock(); |
| 3319 if (isChildLayoutBlock && !floatBox.needsLayout() && | 3475 if (isChildLayoutBlock && !floatBox.needsLayout() && |
| 3320 view()->layoutState()->pageLogicalHeightChanged()) | 3476 view()->layoutState()->pageLogicalHeightChanged()) |
| 3321 floatBox.setChildNeedsLayout(MarkOnlyThis); | 3477 floatBox.setChildNeedsLayout(MarkOnlyThis); |
| 3322 | 3478 |
| 3323 floatBox.layoutIfNeeded(); | 3479 floatBox.layoutIfNeeded(); |
| 3324 | 3480 |
| 3325 setLogicalWidthForFloat(*newObj, logicalWidthForChild(floatBox) + | 3481 setLogicalWidthForFloat(*newObj, logicalWidthForChild(floatBox) + |
| 3326 marginStartForChild(floatBox) + | 3482 marginStartForChild(floatBox) + |
| 3327 marginEndForChild(floatBox)); | 3483 marginEndForChild(floatBox)); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 3338 FloatingObject& floatingObject = *it->get(); | 3494 FloatingObject& floatingObject = *it->get(); |
| 3339 if (childrenInline()) { | 3495 if (childrenInline()) { |
| 3340 LayoutUnit logicalTop = logicalTopForFloat(floatingObject); | 3496 LayoutUnit logicalTop = logicalTopForFloat(floatingObject); |
| 3341 LayoutUnit logicalBottom = logicalBottomForFloat(floatingObject); | 3497 LayoutUnit logicalBottom = logicalBottomForFloat(floatingObject); |
| 3342 | 3498 |
| 3343 // Fix for https://bugs.webkit.org/show_bug.cgi?id=54995. | 3499 // Fix for https://bugs.webkit.org/show_bug.cgi?id=54995. |
| 3344 if (logicalBottom < 0 || logicalBottom < logicalTop || | 3500 if (logicalBottom < 0 || logicalBottom < logicalTop || |
| 3345 logicalTop == LayoutUnit::max()) { | 3501 logicalTop == LayoutUnit::max()) { |
| 3346 logicalBottom = LayoutUnit::max(); | 3502 logicalBottom = LayoutUnit::max(); |
| 3347 } else { | 3503 } else { |
| 3348 // Special-case zero- and less-than-zero-height floats: those don't to
uch | 3504 // 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 | 3505 // touch the line that they're on, but it still needs to be dirtied. |
| 3350 // accomplished by pretending they have a height of 1. | 3506 // This is accomplished by pretending they have a height of 1. |
| 3351 logicalBottom = std::max(logicalBottom, logicalTop + 1); | 3507 logicalBottom = std::max(logicalBottom, logicalTop + 1); |
| 3352 } | 3508 } |
| 3353 if (floatingObject.originatingLine()) { | 3509 if (floatingObject.originatingLine()) { |
| 3354 if (!selfNeedsLayout()) { | 3510 if (!selfNeedsLayout()) { |
| 3355 ASSERT( | 3511 ASSERT( |
| 3356 floatingObject.originatingLine()->getLineLayoutItem().isEqual( | 3512 floatingObject.originatingLine()->getLineLayoutItem().isEqual( |
| 3357 this)); | 3513 this)); |
| 3358 floatingObject.originatingLine()->markDirty(); | 3514 floatingObject.originatingLine()->markDirty(); |
| 3359 } | 3515 } |
| 3360 #if ENABLE(ASSERT) | 3516 #if ENABLE(ASSERT) |
| (...skipping 28 matching lines...) Expand all Loading... |
| 3389 return false; | 3545 return false; |
| 3390 | 3546 |
| 3391 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); | 3547 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); |
| 3392 if (floatingObjectSet.isEmpty()) | 3548 if (floatingObjectSet.isEmpty()) |
| 3393 return false; | 3549 return false; |
| 3394 | 3550 |
| 3395 // If all floats have already been positioned, then we have no work to do. | 3551 // If all floats have already been positioned, then we have no work to do. |
| 3396 if (floatingObjectSet.last()->isPlaced()) | 3552 if (floatingObjectSet.last()->isPlaced()) |
| 3397 return false; | 3553 return false; |
| 3398 | 3554 |
| 3399 // Move backwards through our floating object list until we find a float that
has | 3555 // 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 | 3556 // has already been positioned. Then we'll be able to move forward, |
| 3401 // the new floats that need it. | 3557 // positioning all of the new floats that need it. |
| 3402 FloatingObjectSetIterator it = floatingObjectSet.end(); | 3558 FloatingObjectSetIterator it = floatingObjectSet.end(); |
| 3403 --it; // Go to last item. | 3559 --it; // Go to last item. |
| 3404 FloatingObjectSetIterator begin = floatingObjectSet.begin(); | 3560 FloatingObjectSetIterator begin = floatingObjectSet.begin(); |
| 3405 FloatingObject* lastPlacedFloatingObject = nullptr; | 3561 FloatingObject* lastPlacedFloatingObject = nullptr; |
| 3406 while (it != begin) { | 3562 while (it != begin) { |
| 3407 --it; | 3563 --it; |
| 3408 if ((*it)->isPlaced()) { | 3564 if ((*it)->isPlaced()) { |
| 3409 lastPlacedFloatingObject = it->get(); | 3565 lastPlacedFloatingObject = it->get(); |
| 3410 ++it; | 3566 ++it; |
| 3411 break; | 3567 break; |
| 3412 } | 3568 } |
| 3413 } | 3569 } |
| 3414 | 3570 |
| 3415 LayoutUnit logicalTop = logicalHeight(); | 3571 LayoutUnit logicalTop = logicalHeight(); |
| 3416 | 3572 |
| 3417 // The float cannot start above the top position of the last positioned float. | 3573 // The float cannot start above the top position of the last positioned float. |
| 3418 if (lastPlacedFloatingObject) | 3574 if (lastPlacedFloatingObject) |
| 3419 logicalTop = | 3575 logicalTop = |
| 3420 std::max(logicalTopForFloat(*lastPlacedFloatingObject), logicalTop); | 3576 std::max(logicalTopForFloat(*lastPlacedFloatingObject), logicalTop); |
| 3421 | 3577 |
| 3422 FloatingObjectSetIterator end = floatingObjectSet.end(); | 3578 FloatingObjectSetIterator end = floatingObjectSet.end(); |
| 3423 // Now walk through the set of unpositioned floats and place them. | 3579 // Now walk through the set of unpositioned floats and place them. |
| 3424 for (; it != end; ++it) { | 3580 for (; it != end; ++it) { |
| 3425 FloatingObject& floatingObject = *it->get(); | 3581 FloatingObject& floatingObject = *it->get(); |
| 3426 // The containing block is responsible for positioning floats, so if we have
floats in our | 3582 // 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. | 3583 // floats in our list that come from somewhere else, do not attempt to |
| 3584 // position them. |
| 3428 if (floatingObject.layoutObject()->containingBlock() != this) | 3585 if (floatingObject.layoutObject()->containingBlock() != this) |
| 3429 continue; | 3586 continue; |
| 3430 | 3587 |
| 3431 LayoutBox* childBox = floatingObject.layoutObject(); | 3588 LayoutBox* childBox = floatingObject.layoutObject(); |
| 3432 | 3589 |
| 3433 // FIXME Investigate if this can be removed. crbug.com/370006 | 3590 // FIXME Investigate if this can be removed. crbug.com/370006 |
| 3434 childBox->setMayNeedPaintInvalidation(); | 3591 childBox->setMayNeedPaintInvalidation(); |
| 3435 | 3592 |
| 3436 LayoutUnit childLogicalLeftMargin = style()->isLeftToRightDirection() | 3593 LayoutUnit childLogicalLeftMargin = style()->isLeftToRightDirection() |
| 3437 ? marginStartForChild(*childBox) | 3594 ? marginStartForChild(*childBox) |
| 3438 : marginEndForChild(*childBox); | 3595 : marginEndForChild(*childBox); |
| 3439 if (childBox->style()->clear() & ClearLeft) | 3596 if (childBox->style()->clear() & ClearLeft) |
| 3440 logicalTop = std::max(lowestFloatLogicalBottom(FloatingObject::FloatLeft), | 3597 logicalTop = std::max(lowestFloatLogicalBottom(FloatingObject::FloatLeft), |
| 3441 logicalTop); | 3598 logicalTop); |
| 3442 if (childBox->style()->clear() & ClearRight) | 3599 if (childBox->style()->clear() & ClearRight) |
| 3443 logicalTop = std::max( | 3600 logicalTop = std::max( |
| 3444 lowestFloatLogicalBottom(FloatingObject::FloatRight), logicalTop); | 3601 lowestFloatLogicalBottom(FloatingObject::FloatRight), logicalTop); |
| 3445 | 3602 |
| 3446 bool isPaginated = view()->layoutState()->isPaginated(); | 3603 bool isPaginated = view()->layoutState()->isPaginated(); |
| 3447 if (isPaginated && !childrenInline()) { | 3604 if (isPaginated && !childrenInline()) { |
| 3448 // Forced breaks are inserted at class A break points. Floats may be affec
ted by a | 3605 // Forced breaks are inserted at class A break points. Floats may be |
| 3449 // break-after value on the previous in-flow sibling. | 3606 // affected by a break-after value on the previous in-flow sibling. |
| 3450 if (LayoutBox* previousInFlowBox = childBox->previousInFlowSiblingBox()) | 3607 if (LayoutBox* previousInFlowBox = childBox->previousInFlowSiblingBox()) |
| 3451 logicalTop = | 3608 logicalTop = |
| 3452 applyForcedBreak(logicalTop, previousInFlowBox->breakAfter()); | 3609 applyForcedBreak(logicalTop, previousInFlowBox->breakAfter()); |
| 3453 } | 3610 } |
| 3454 | 3611 |
| 3455 LayoutPoint floatLogicalLocation = | 3612 LayoutPoint floatLogicalLocation = |
| 3456 computeLogicalLocationForFloat(floatingObject, logicalTop); | 3613 computeLogicalLocationForFloat(floatingObject, logicalTop); |
| 3457 | 3614 |
| 3458 setLogicalLeftForFloat(floatingObject, floatLogicalLocation.x()); | 3615 setLogicalLeftForFloat(floatingObject, floatLogicalLocation.x()); |
| 3459 | 3616 |
| 3460 setLogicalLeftForChild(*childBox, | 3617 setLogicalLeftForChild(*childBox, |
| 3461 floatLogicalLocation.x() + childLogicalLeftMargin); | 3618 floatLogicalLocation.x() + childLogicalLeftMargin); |
| 3462 setLogicalTopForChild( | 3619 setLogicalTopForChild( |
| 3463 *childBox, floatLogicalLocation.y() + marginBeforeForChild(*childBox)); | 3620 *childBox, floatLogicalLocation.y() + marginBeforeForChild(*childBox)); |
| 3464 | 3621 |
| 3465 SubtreeLayoutScope layoutScope(*childBox); | 3622 SubtreeLayoutScope layoutScope(*childBox); |
| 3466 if (isPaginated && !childBox->needsLayout()) | 3623 if (isPaginated && !childBox->needsLayout()) |
| 3467 markChildForPaginationRelayoutIfNeeded(*childBox, layoutScope); | 3624 markChildForPaginationRelayoutIfNeeded(*childBox, layoutScope); |
| 3468 | 3625 |
| 3469 childBox->layoutIfNeeded(); | 3626 childBox->layoutIfNeeded(); |
| 3470 | 3627 |
| 3471 if (isPaginated) { | 3628 if (isPaginated) { |
| 3472 LayoutBlockFlow* childBlockFlow = | 3629 LayoutBlockFlow* childBlockFlow = |
| 3473 childBox->isLayoutBlockFlow() ? toLayoutBlockFlow(childBox) : nullptr; | 3630 childBox->isLayoutBlockFlow() ? toLayoutBlockFlow(childBox) : nullptr; |
| 3474 // The first piece of content inside the child may have set a strut during
layout. | 3631 // The first piece of content inside the child may have set a strut during |
| 3632 // layout. |
| 3475 LayoutUnit strut = | 3633 LayoutUnit strut = |
| 3476 childBlockFlow ? childBlockFlow->paginationStrutPropagatedFromChild() | 3634 childBlockFlow ? childBlockFlow->paginationStrutPropagatedFromChild() |
| 3477 : LayoutUnit(); | 3635 : LayoutUnit(); |
| 3478 if (!strut) { | 3636 if (!strut) { |
| 3479 // Otherwise, if we are unsplittable and don't fit, move to the next pag
e or column | 3637 // Otherwise, if we are unsplittable and don't fit, move to the next |
| 3480 // if that helps the situation. | 3638 // page or column if that helps the situation. |
| 3481 strut = | 3639 strut = |
| 3482 adjustForUnsplittableChild(*childBox, floatLogicalLocation.y()) - | 3640 adjustForUnsplittableChild(*childBox, floatLogicalLocation.y()) - |
| 3483 floatLogicalLocation.y(); | 3641 floatLogicalLocation.y(); |
| 3484 } | 3642 } |
| 3485 | 3643 |
| 3486 childBox->setPaginationStrut(strut); | 3644 childBox->setPaginationStrut(strut); |
| 3487 if (strut) { | 3645 if (strut) { |
| 3488 floatLogicalLocation = computeLogicalLocationForFloat( | 3646 floatLogicalLocation = computeLogicalLocationForFloat( |
| 3489 floatingObject, floatLogicalLocation.y() + strut); | 3647 floatingObject, floatLogicalLocation.y() + strut); |
| 3490 setLogicalLeftForFloat(floatingObject, floatLogicalLocation.x()); | 3648 setLogicalLeftForFloat(floatingObject, floatLogicalLocation.x()); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3529 return false; | 3687 return false; |
| 3530 | 3688 |
| 3531 return isOverhangingFloat(**it); | 3689 return isOverhangingFloat(**it); |
| 3532 } | 3690 } |
| 3533 | 3691 |
| 3534 void LayoutBlockFlow::addIntrudingFloats(LayoutBlockFlow* prev, | 3692 void LayoutBlockFlow::addIntrudingFloats(LayoutBlockFlow* prev, |
| 3535 LayoutUnit logicalLeftOffset, | 3693 LayoutUnit logicalLeftOffset, |
| 3536 LayoutUnit logicalTopOffset) { | 3694 LayoutUnit logicalTopOffset) { |
| 3537 ASSERT(!avoidsFloats()); | 3695 ASSERT(!avoidsFloats()); |
| 3538 | 3696 |
| 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. | 3697 // If we create our own block formatting context then our contents don't |
| 3698 // interact with floats outside it, even those from our parent. |
| 3540 if (createsNewFormattingContext()) | 3699 if (createsNewFormattingContext()) |
| 3541 return; | 3700 return; |
| 3542 | 3701 |
| 3543 // If the parent or previous sibling doesn't have any floats to add, don't bot
her. | 3702 // If the parent or previous sibling doesn't have any floats to add, don't |
| 3703 // bother. |
| 3544 if (!prev->m_floatingObjects) | 3704 if (!prev->m_floatingObjects) |
| 3545 return; | 3705 return; |
| 3546 | 3706 |
| 3547 logicalLeftOffset += marginLogicalLeft(); | 3707 logicalLeftOffset += marginLogicalLeft(); |
| 3548 | 3708 |
| 3549 const FloatingObjectSet& prevSet = prev->m_floatingObjects->set(); | 3709 const FloatingObjectSet& prevSet = prev->m_floatingObjects->set(); |
| 3550 FloatingObjectSetIterator prevEnd = prevSet.end(); | 3710 FloatingObjectSetIterator prevEnd = prevSet.end(); |
| 3551 for (FloatingObjectSetIterator prevIt = prevSet.begin(); prevIt != prevEnd; | 3711 for (FloatingObjectSetIterator prevIt = prevSet.begin(); prevIt != prevEnd; |
| 3552 ++prevIt) { | 3712 ++prevIt) { |
| 3553 FloatingObject& floatingObject = *prevIt->get(); | 3713 FloatingObject& floatingObject = *prevIt->get(); |
| 3554 if (logicalBottomForFloat(floatingObject) > logicalTopOffset) { | 3714 if (logicalBottomForFloat(floatingObject) > logicalTopOffset) { |
| 3555 if (!m_floatingObjects || | 3715 if (!m_floatingObjects || |
| 3556 !m_floatingObjects->set().contains(&floatingObject)) { | 3716 !m_floatingObjects->set().contains(&floatingObject)) { |
| 3557 // We create the floating object list lazily. | 3717 // We create the floating object list lazily. |
| 3558 if (!m_floatingObjects) | 3718 if (!m_floatingObjects) |
| 3559 createFloatingObjects(); | 3719 createFloatingObjects(); |
| 3560 | 3720 |
| 3561 // Applying the child's margin makes no sense in the case where the chil
d was passed in. | 3721 // 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 | 3722 // 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 | 3723 // modification of the |logicalLeftOffset| variable above. |
| 3564 // into account. Only apply this code if prev is the parent, since other
wise the left margin | 3724 // |logicalLeftOffset| will equal the margin in this case, so it's |
| 3565 // will get applied twice. | 3725 // already been taken into account. Only apply this code if prev is the |
| 3726 // parent, since otherwise the left margin will get applied twice. |
| 3566 LayoutSize offset = | 3727 LayoutSize offset = |
| 3567 isHorizontalWritingMode() | 3728 isHorizontalWritingMode() |
| 3568 ? LayoutSize( | 3729 ? LayoutSize( |
| 3569 logicalLeftOffset - (prev != parent() ? prev->marginLeft() | 3730 logicalLeftOffset - (prev != parent() ? prev->marginLeft() |
| 3570 : LayoutUnit()), | 3731 : LayoutUnit()), |
| 3571 logicalTopOffset) | 3732 logicalTopOffset) |
| 3572 : LayoutSize( | 3733 : LayoutSize( |
| 3573 logicalTopOffset, | 3734 logicalTopOffset, |
| 3574 logicalLeftOffset - (prev != parent() ? prev->marginTop() | 3735 logicalLeftOffset - (prev != parent() ? prev->marginTop() |
| 3575 : LayoutUnit())); | 3736 : LayoutUnit())); |
| 3576 | 3737 |
| 3577 m_floatingObjects->add(floatingObject.copyToNewContainer(offset)); | 3738 m_floatingObjects->add(floatingObject.copyToNewContainer(offset)); |
| 3578 } | 3739 } |
| 3579 } | 3740 } |
| 3580 } | 3741 } |
| 3581 } | 3742 } |
| 3582 | 3743 |
| 3583 void LayoutBlockFlow::addOverhangingFloats(LayoutBlockFlow* child, | 3744 void LayoutBlockFlow::addOverhangingFloats(LayoutBlockFlow* child, |
| 3584 bool makeChildPaintOtherFloats) { | 3745 bool makeChildPaintOtherFloats) { |
| 3585 // Prevent floats from being added to the canvas by the root element, e.g., <h
tml>. | 3746 // Prevent floats from being added to the canvas by the root element, e.g., |
| 3747 // <html>. |
| 3586 if (!child->containsFloats() || child->createsNewFormattingContext()) | 3748 if (!child->containsFloats() || child->createsNewFormattingContext()) |
| 3587 return; | 3749 return; |
| 3588 | 3750 |
| 3589 LayoutUnit childLogicalTop = child->logicalTop(); | 3751 LayoutUnit childLogicalTop = child->logicalTop(); |
| 3590 LayoutUnit childLogicalLeft = child->logicalLeft(); | 3752 LayoutUnit childLogicalLeft = child->logicalLeft(); |
| 3591 | 3753 |
| 3592 // Floats that will remain the child's responsibility to paint should factor i
nto its | 3754 // Floats that will remain the child's responsibility to paint should factor |
| 3593 // overflow. | 3755 // into its overflow. |
| 3594 FloatingObjectSetIterator childEnd = child->m_floatingObjects->set().end(); | 3756 FloatingObjectSetIterator childEnd = child->m_floatingObjects->set().end(); |
| 3595 for (FloatingObjectSetIterator childIt = | 3757 for (FloatingObjectSetIterator childIt = |
| 3596 child->m_floatingObjects->set().begin(); | 3758 child->m_floatingObjects->set().begin(); |
| 3597 childIt != childEnd; ++childIt) { | 3759 childIt != childEnd; ++childIt) { |
| 3598 FloatingObject& floatingObject = *childIt->get(); | 3760 FloatingObject& floatingObject = *childIt->get(); |
| 3599 LayoutUnit logicalBottomForFloat = | 3761 LayoutUnit logicalBottomForFloat = |
| 3600 std::min(this->logicalBottomForFloat(floatingObject), | 3762 std::min(this->logicalBottomForFloat(floatingObject), |
| 3601 LayoutUnit::max() - childLogicalTop); | 3763 LayoutUnit::max() - childLogicalTop); |
| 3602 LayoutUnit logicalBottom = childLogicalTop + logicalBottomForFloat; | 3764 LayoutUnit logicalBottom = childLogicalTop + logicalBottomForFloat; |
| 3603 | 3765 |
| 3604 if (logicalBottom > logicalHeight()) { | 3766 if (logicalBottom > logicalHeight()) { |
| 3605 // If the object is not in the list, we add it now. | 3767 // If the object is not in the list, we add it now. |
| 3606 if (!containsFloat(floatingObject.layoutObject())) { | 3768 if (!containsFloat(floatingObject.layoutObject())) { |
| 3607 LayoutSize offset = | 3769 LayoutSize offset = |
| 3608 isHorizontalWritingMode() | 3770 isHorizontalWritingMode() |
| 3609 ? LayoutSize(-childLogicalLeft, -childLogicalTop) | 3771 ? LayoutSize(-childLogicalLeft, -childLogicalTop) |
| 3610 : LayoutSize(-childLogicalTop, -childLogicalLeft); | 3772 : LayoutSize(-childLogicalTop, -childLogicalLeft); |
| 3611 bool shouldPaint = false; | 3773 bool shouldPaint = false; |
| 3612 | 3774 |
| 3613 // The nearest enclosing layer always paints the float (so that zindex a
nd stacking | 3775 // 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 | 3776 // 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 | 3777 // desire to paint the float as far out as we can, to the outermost |
| 3616 // if we hit a self-painting layer boundary. | 3778 // block that overlaps the float, stopping only if we hit a |
| 3779 // self-painting layer boundary. |
| 3617 if (floatingObject.layoutObject()->enclosingFloatPaintingLayer() == | 3780 if (floatingObject.layoutObject()->enclosingFloatPaintingLayer() == |
| 3618 enclosingFloatPaintingLayer() && | 3781 enclosingFloatPaintingLayer() && |
| 3619 !floatingObject.isLowestNonOverhangingFloatInChild()) { | 3782 !floatingObject.isLowestNonOverhangingFloatInChild()) { |
| 3620 floatingObject.setShouldPaint(false); | 3783 floatingObject.setShouldPaint(false); |
| 3621 shouldPaint = true; | 3784 shouldPaint = true; |
| 3622 } | 3785 } |
| 3623 // We create the floating object list lazily. | 3786 // We create the floating object list lazily. |
| 3624 if (!m_floatingObjects) | 3787 if (!m_floatingObjects) |
| 3625 createFloatingObjects(); | 3788 createFloatingObjects(); |
| 3626 | 3789 |
| 3627 m_floatingObjects->add( | 3790 m_floatingObjects->add( |
| 3628 floatingObject.copyToNewContainer(offset, shouldPaint, true)); | 3791 floatingObject.copyToNewContainer(offset, shouldPaint, true)); |
| 3629 } | 3792 } |
| 3630 } else { | 3793 } else { |
| 3631 if (makeChildPaintOtherFloats && !floatingObject.shouldPaint() && | 3794 if (makeChildPaintOtherFloats && !floatingObject.shouldPaint() && |
| 3632 !floatingObject.layoutObject()->hasSelfPaintingLayer() && | 3795 !floatingObject.layoutObject()->hasSelfPaintingLayer() && |
| 3633 !floatingObject.isLowestNonOverhangingFloatInChild() && | 3796 !floatingObject.isLowestNonOverhangingFloatInChild() && |
| 3634 floatingObject.layoutObject()->isDescendantOf(child) && | 3797 floatingObject.layoutObject()->isDescendantOf(child) && |
| 3635 floatingObject.layoutObject()->enclosingFloatPaintingLayer() == | 3798 floatingObject.layoutObject()->enclosingFloatPaintingLayer() == |
| 3636 child->enclosingFloatPaintingLayer()) { | 3799 child->enclosingFloatPaintingLayer()) { |
| 3637 // The float is not overhanging from this block, so if it is a descendan
t of the child, the child should | 3800 // 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 | 3801 // descendant of the child, the child should paint it (the other case is |
| 3639 // layer. | 3802 // 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 | 3803 // enclosing layer. |
| 3641 // it should paint. | 3804 // If makeChildPaintOtherFloats is false, it means that the child must |
| 3805 // already know about all the floats it should paint. |
| 3642 floatingObject.setShouldPaint(true); | 3806 floatingObject.setShouldPaint(true); |
| 3643 } | 3807 } |
| 3644 | 3808 |
| 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 | 3809 // Since the float doesn't overhang, it didn't get put into our list. We |
| 3646 // child now. | 3810 // need to go ahead and add its overflow in to the child now. |
| 3647 if (floatingObject.isDescendant()) | 3811 if (floatingObject.isDescendant()) |
| 3648 child->addOverflowFromChild( | 3812 child->addOverflowFromChild( |
| 3649 floatingObject.layoutObject(), | 3813 floatingObject.layoutObject(), |
| 3650 LayoutSize(xPositionForFloatIncludingMargin(floatingObject), | 3814 LayoutSize(xPositionForFloatIncludingMargin(floatingObject), |
| 3651 yPositionForFloatIncludingMargin(floatingObject))); | 3815 yPositionForFloatIncludingMargin(floatingObject))); |
| 3652 } | 3816 } |
| 3653 } | 3817 } |
| 3654 } | 3818 } |
| 3655 | 3819 |
| 3656 LayoutUnit LayoutBlockFlow::lowestFloatLogicalBottom( | 3820 LayoutUnit LayoutBlockFlow::lowestFloatLogicalBottom( |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3799 if (!ancestorFloatingObjects) | 3963 if (!ancestorFloatingObjects) |
| 3800 break; | 3964 break; |
| 3801 FloatingObjectSet::iterator it = ancestorFloatingObjects->mutableSet() | 3965 FloatingObjectSet::iterator it = ancestorFloatingObjects->mutableSet() |
| 3802 .find<FloatingObjectHashTranslator>( | 3966 .find<FloatingObjectHashTranslator>( |
| 3803 const_cast<LayoutBox*>(&floatBox)); | 3967 const_cast<LayoutBox*>(&floatBox)); |
| 3804 if (it == ancestorFloatingObjects->mutableSet().end()) | 3968 if (it == ancestorFloatingObjects->mutableSet().end()) |
| 3805 break; | 3969 break; |
| 3806 | 3970 |
| 3807 FloatingObject& floatingObject = **it; | 3971 FloatingObject& floatingObject = **it; |
| 3808 if (!floatBoxIsSelfPaintingLayer) { | 3972 if (!floatBoxIsSelfPaintingLayer) { |
| 3809 // This repeats the logic in addOverhangingFloats() about shouldPaint flag
: | 3973 // This repeats the logic in addOverhangingFloats() about shouldPaint |
| 3810 // - The nearest enclosing block in which the float doesn't overhang paint
s the float; | 3974 // flag: |
| 3811 // - Or even if the float overhangs, if the ancestor block has self-painti
ng layer, it | 3975 // - The nearest enclosing block in which the float doesn't overhang |
| 3812 // paints the float. | 3976 // paints the float; |
| 3977 // - Or even if the float overhangs, if the ancestor block has |
| 3978 // self-painting layer, it paints the float. |
| 3813 if (ancestorBlock->hasSelfPaintingLayer() || | 3979 if (ancestorBlock->hasSelfPaintingLayer() || |
| 3814 !ancestorBlock->isOverhangingFloat(floatingObject)) { | 3980 !ancestorBlock->isOverhangingFloat(floatingObject)) { |
| 3815 floatingObject.setShouldPaint(true); | 3981 floatingObject.setShouldPaint(true); |
| 3816 return; | 3982 return; |
| 3817 } | 3983 } |
| 3818 } else { | 3984 } else { |
| 3819 floatingObject.setShouldPaint(false); | 3985 floatingObject.setShouldPaint(false); |
| 3820 } | 3986 } |
| 3821 } | 3987 } |
| 3822 } | 3988 } |
| 3823 | 3989 |
| 3824 bool LayoutBlockFlow::allowsPaginationStrut() const { | 3990 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 | 3991 // 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 | 3992 // 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 | 3993 // 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 | 3994 // 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), | 3995 // struts and handle them. We handle floats and regular in-flow children, and |
| 3830 // but currently we don't. | 3996 // that's all. We could handle this in other layout modes as well (and even |
| 3997 // for out-of-flow children), but currently we don't. |
| 3831 // TODO(mstensho): But we *should*. | 3998 // TODO(mstensho): But we *should*. |
| 3832 if (isOutOfFlowPositioned()) | 3999 if (isOutOfFlowPositioned()) |
| 3833 return false; | 4000 return false; |
| 3834 if (isLayoutFlowThread()) { | 4001 if (isLayoutFlowThread()) { |
| 3835 // Don't let the strut escape the fragmentation context and get lost. | 4002 // 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 | 4003 // 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 | 4004 // 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 | 4005 // 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. | 4006 // fragmentainer, instead of taking up unusable space in the previous one. |
| 4007 // But currently we have no mechanism in place to handle this. |
| 3840 return false; | 4008 return false; |
| 3841 } | 4009 } |
| 3842 LayoutBlock* containingBlock = this->containingBlock(); | 4010 LayoutBlock* containingBlock = this->containingBlock(); |
| 3843 return containingBlock && containingBlock->isLayoutBlockFlow(); | 4011 return containingBlock && containingBlock->isLayoutBlockFlow(); |
| 3844 } | 4012 } |
| 3845 | 4013 |
| 3846 void LayoutBlockFlow::setPaginationStrutPropagatedFromChild(LayoutUnit strut) { | 4014 void LayoutBlockFlow::setPaginationStrutPropagatedFromChild(LayoutUnit strut) { |
| 3847 strut = std::max(strut, LayoutUnit()); | 4015 strut = std::max(strut, LayoutUnit()); |
| 3848 if (!m_rareData) { | 4016 if (!m_rareData) { |
| 3849 if (!strut) | 4017 if (!strut) |
| 3850 return; | 4018 return; |
| 3851 m_rareData = wrapUnique(new LayoutBlockFlowRareData(this)); | 4019 m_rareData = wrapUnique(new LayoutBlockFlowRareData(this)); |
| 3852 } | 4020 } |
| 3853 m_rareData->m_paginationStrutPropagatedFromChild = strut; | 4021 m_rareData->m_paginationStrutPropagatedFromChild = strut; |
| 3854 } | 4022 } |
| 3855 | 4023 |
| 3856 void LayoutBlockFlow::positionSpannerDescendant( | 4024 void LayoutBlockFlow::positionSpannerDescendant( |
| 3857 LayoutMultiColumnSpannerPlaceholder& child) { | 4025 LayoutMultiColumnSpannerPlaceholder& child) { |
| 3858 LayoutBox& spanner = *child.layoutObjectInFlowThread(); | 4026 LayoutBox& spanner = *child.layoutObjectInFlowThread(); |
| 3859 // FIXME: |spanner| is a descendant, but never a direct child, so the names he
re are bad, if | 4027 // FIXME: |spanner| is a descendant, but never a direct child, so the names |
| 3860 // nothing else. | 4028 // here are bad, if nothing else. |
| 3861 setLogicalTopForChild(spanner, child.logicalTop()); | 4029 setLogicalTopForChild(spanner, child.logicalTop()); |
| 3862 determineLogicalLeftPositionForChild(spanner); | 4030 determineLogicalLeftPositionForChild(spanner); |
| 3863 } | 4031 } |
| 3864 | 4032 |
| 3865 bool LayoutBlockFlow::avoidsFloats() const { | 4033 bool LayoutBlockFlow::avoidsFloats() const { |
| 3866 // Floats can't intrude into our box if we have a non-auto column count or wid
th. | 4034 // 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. | 4035 // width. |
| 4036 // Note: we need to use LayoutBox::avoidsFloats here since |
| 4037 // LayoutBlock::avoidsFloats is always true. |
| 3868 return LayoutBox::avoidsFloats() || !style()->hasAutoColumnCount() || | 4038 return LayoutBox::avoidsFloats() || !style()->hasAutoColumnCount() || |
| 3869 !style()->hasAutoColumnWidth(); | 4039 !style()->hasAutoColumnWidth(); |
| 3870 } | 4040 } |
| 3871 | 4041 |
| 3872 void LayoutBlockFlow::moveChildrenTo(LayoutBoxModelObject* toBoxModelObject, | 4042 void LayoutBlockFlow::moveChildrenTo(LayoutBoxModelObject* toBoxModelObject, |
| 3873 LayoutObject* startChild, | 4043 LayoutObject* startChild, |
| 3874 LayoutObject* endChild, | 4044 LayoutObject* endChild, |
| 3875 LayoutObject* beforeChild, | 4045 LayoutObject* beforeChild, |
| 3876 bool fullRemoveInsert) { | 4046 bool fullRemoveInsert) { |
| 3877 if (childrenInline()) | 4047 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. | 4109 // Paged overflow is currently done using the multicol implementation. |
| 3940 return LayoutPagedFlowThread::createAnonymous(document(), styleRef()); | 4110 return LayoutPagedFlowThread::createAnonymous(document(), styleRef()); |
| 3941 default: | 4111 default: |
| 3942 ASSERT_NOT_REACHED(); | 4112 ASSERT_NOT_REACHED(); |
| 3943 return nullptr; | 4113 return nullptr; |
| 3944 } | 4114 } |
| 3945 } | 4115 } |
| 3946 | 4116 |
| 3947 void LayoutBlockFlow::createOrDestroyMultiColumnFlowThreadIfNeeded( | 4117 void LayoutBlockFlow::createOrDestroyMultiColumnFlowThreadIfNeeded( |
| 3948 const ComputedStyle* oldStyle) { | 4118 const ComputedStyle* oldStyle) { |
| 3949 // Paged overflow trumps multicol in this implementation. Ideally, it should b
e possible to have | 4119 // 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 | 4120 // 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 | 4121 // but then we need two flow threads. Anyway, this is nothing to worry about |
| 3952 // inside other fragmentation contexts. | 4122 // until we can actually nest multicol properly inside other fragmentation |
| 4123 // contexts. |
| 3953 FlowThreadType type = getFlowThreadType(styleRef()); | 4124 FlowThreadType type = getFlowThreadType(styleRef()); |
| 3954 | 4125 |
| 3955 if (multiColumnFlowThread()) { | 4126 if (multiColumnFlowThread()) { |
| 3956 ASSERT(oldStyle); | 4127 ASSERT(oldStyle); |
| 3957 if (type != getFlowThreadType(*oldStyle)) { | 4128 if (type != getFlowThreadType(*oldStyle)) { |
| 3958 // If we're no longer to be multicol/paged, destroy the flow thread. Also
destroy it | 4129 // 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 | 4130 // destroy it when switching between multicol and paged, since that |
| 3960 // structure (multicol containers may have spanners, paged containers may
not). | 4131 // affects the column set structure (multicol containers may have |
| 4132 // spanners, paged containers may not). |
| 3961 multiColumnFlowThread()->evacuateAndDestroy(); | 4133 multiColumnFlowThread()->evacuateAndDestroy(); |
| 3962 ASSERT(!multiColumnFlowThread()); | 4134 ASSERT(!multiColumnFlowThread()); |
| 3963 } | 4135 } |
| 3964 } | 4136 } |
| 3965 | 4137 |
| 3966 if (type == NoFlowThread || multiColumnFlowThread()) | 4138 if (type == NoFlowThread || multiColumnFlowThread()) |
| 3967 return; | 4139 return; |
| 3968 | 4140 |
| 3969 // Ruby elements manage child insertion in a special way, and would mess up in
sertion of the | 4141 // 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|). | 4142 // insertion of the flow thread. The flow thread needs to be a direct child of |
| 4143 // the multicol block (|this|). |
| 3971 if (isRuby()) | 4144 if (isRuby()) |
| 3972 return; | 4145 return; |
| 3973 | 4146 |
| 3974 // Form controls are replaced content, and are therefore not supposed to suppo
rt multicol. | 4147 // Form controls are replaced content, and are therefore not supposed to |
| 4148 // support multicol. |
| 3975 if (isFileUploadControl() || isTextControl() || isListBox()) | 4149 if (isFileUploadControl() || isTextControl() || isListBox()) |
| 3976 return; | 4150 return; |
| 3977 | 4151 |
| 3978 LayoutMultiColumnFlowThread* flowThread = createMultiColumnFlowThread(type); | 4152 LayoutMultiColumnFlowThread* flowThread = createMultiColumnFlowThread(type); |
| 3979 addChild(flowThread); | 4153 addChild(flowThread); |
| 3980 | 4154 |
| 3981 // Check that addChild() put the flow thread as a direct child, and didn't do
fancy things. | 4155 // Check that addChild() put the flow thread as a direct child, and didn't do |
| 4156 // fancy things. |
| 3982 ASSERT(flowThread->parent() == this); | 4157 ASSERT(flowThread->parent() == this); |
| 3983 | 4158 |
| 3984 flowThread->populate(); | 4159 flowThread->populate(); |
| 3985 LayoutBlockFlowRareData& rareData = ensureRareData(); | 4160 LayoutBlockFlowRareData& rareData = ensureRareData(); |
| 3986 ASSERT(!rareData.m_multiColumnFlowThread); | 4161 ASSERT(!rareData.m_multiColumnFlowThread); |
| 3987 rareData.m_multiColumnFlowThread = flowThread; | 4162 rareData.m_multiColumnFlowThread = flowThread; |
| 3988 } | 4163 } |
| 3989 | 4164 |
| 3990 LayoutBlockFlow::LayoutBlockFlowRareData& LayoutBlockFlow::ensureRareData() { | 4165 LayoutBlockFlow::LayoutBlockFlowRareData& LayoutBlockFlow::ensureRareData() { |
| 3991 if (m_rareData) | 4166 if (m_rareData) |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4039 if (toLayoutBox(o)->inlineBoxWrapper()) { | 4214 if (toLayoutBox(o)->inlineBoxWrapper()) { |
| 4040 RootInlineBox& box = toLayoutBox(o)->inlineBoxWrapper()->root(); | 4215 RootInlineBox& box = toLayoutBox(o)->inlineBoxWrapper()->root(); |
| 4041 lineBoxes.add(&box); | 4216 lineBoxes.add(&box); |
| 4042 } | 4217 } |
| 4043 } else if (o->isText() || | 4218 } else if (o->isText() || |
| 4044 (o->isLayoutInline() && !walker.atEndOfInline())) { | 4219 (o->isLayoutInline() && !walker.atEndOfInline())) { |
| 4045 o->clearNeedsLayout(); | 4220 o->clearNeedsLayout(); |
| 4046 } | 4221 } |
| 4047 } | 4222 } |
| 4048 | 4223 |
| 4049 // FIXME: Glyph overflow will get lost in this case, but not really a big deal
. | 4224 // FIXME: Glyph overflow will get lost in this case, but not really a big |
| 4225 // deal. |
| 4050 GlyphOverflowAndFallbackFontsMap textBoxDataMap; | 4226 GlyphOverflowAndFallbackFontsMap textBoxDataMap; |
| 4051 for (ListHashSet<RootInlineBox*>::const_iterator it = lineBoxes.begin(); | 4227 for (ListHashSet<RootInlineBox*>::const_iterator it = lineBoxes.begin(); |
| 4052 it != lineBoxes.end(); ++it) { | 4228 it != lineBoxes.end(); ++it) { |
| 4053 RootInlineBox* box = *it; | 4229 RootInlineBox* box = *it; |
| 4054 box->computeOverflow(box->lineTop(), box->lineBottom(), textBoxDataMap); | 4230 box->computeOverflow(box->lineTop(), box->lineBottom(), textBoxDataMap); |
| 4055 } | 4231 } |
| 4056 } | 4232 } |
| 4057 | 4233 |
| 4058 bool LayoutBlockFlow::recalcInlineChildrenOverflowAfterStyleChange() { | 4234 bool LayoutBlockFlow::recalcInlineChildrenOverflowAfterStyleChange() { |
| 4059 ASSERT(childrenInline()); | 4235 ASSERT(childrenInline()); |
| 4060 bool childrenOverflowChanged = false; | 4236 bool childrenOverflowChanged = false; |
| 4061 ListHashSet<RootInlineBox*> lineBoxes; | 4237 ListHashSet<RootInlineBox*> lineBoxes; |
| 4062 for (InlineWalker walker(LineLayoutBlockFlow(this)); !walker.atEnd(); | 4238 for (InlineWalker walker(LineLayoutBlockFlow(this)); !walker.atEnd(); |
| 4063 walker.advance()) { | 4239 walker.advance()) { |
| 4064 LayoutObject* layoutObject = walker.current().layoutObject(); | 4240 LayoutObject* layoutObject = walker.current().layoutObject(); |
| 4065 if (recalcNormalFlowChildOverflowIfNeeded(layoutObject)) { | 4241 if (recalcNormalFlowChildOverflowIfNeeded(layoutObject)) { |
| 4066 childrenOverflowChanged = true; | 4242 childrenOverflowChanged = true; |
| 4067 if (InlineBox* inlineBoxWrapper = | 4243 if (InlineBox* inlineBoxWrapper = |
| 4068 toLayoutBlock(layoutObject)->inlineBoxWrapper()) | 4244 toLayoutBlock(layoutObject)->inlineBoxWrapper()) |
| 4069 lineBoxes.add(&inlineBoxWrapper->root()); | 4245 lineBoxes.add(&inlineBoxWrapper->root()); |
| 4070 } | 4246 } |
| 4071 } | 4247 } |
| 4072 | 4248 |
| 4073 // FIXME: Glyph overflow will get lost in this case, but not really a big deal
. | 4249 // FIXME: Glyph overflow will get lost in this case, but not really a big |
| 4250 // deal. |
| 4074 GlyphOverflowAndFallbackFontsMap textBoxDataMap; | 4251 GlyphOverflowAndFallbackFontsMap textBoxDataMap; |
| 4075 for (ListHashSet<RootInlineBox*>::const_iterator it = lineBoxes.begin(); | 4252 for (ListHashSet<RootInlineBox*>::const_iterator it = lineBoxes.begin(); |
| 4076 it != lineBoxes.end(); ++it) { | 4253 it != lineBoxes.end(); ++it) { |
| 4077 RootInlineBox* box = *it; | 4254 RootInlineBox* box = *it; |
| 4078 box->clearKnownToHaveNoOverflow(); | 4255 box->clearKnownToHaveNoOverflow(); |
| 4079 box->computeOverflow(box->lineTop(), box->lineBottom(), textBoxDataMap); | 4256 box->computeOverflow(box->lineTop(), box->lineBottom(), textBoxDataMap); |
| 4080 } | 4257 } |
| 4081 return childrenOverflowChanged; | 4258 return childrenOverflowChanged; |
| 4082 } | 4259 } |
| 4083 | 4260 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 4097 LayoutPoint pointInLogicalContents(pointInContents); | 4274 LayoutPoint pointInLogicalContents(pointInContents); |
| 4098 if (!isHorizontalWritingMode()) | 4275 if (!isHorizontalWritingMode()) |
| 4099 pointInLogicalContents = pointInLogicalContents.transposedPoint(); | 4276 pointInLogicalContents = pointInLogicalContents.transposedPoint(); |
| 4100 | 4277 |
| 4101 if (!firstRootBox()) | 4278 if (!firstRootBox()) |
| 4102 return createPositionWithAffinity(0); | 4279 return createPositionWithAffinity(0); |
| 4103 | 4280 |
| 4104 bool linesAreFlipped = style()->isFlippedLinesWritingMode(); | 4281 bool linesAreFlipped = style()->isFlippedLinesWritingMode(); |
| 4105 bool blocksAreFlipped = style()->isFlippedBlocksWritingMode(); | 4282 bool blocksAreFlipped = style()->isFlippedBlocksWritingMode(); |
| 4106 | 4283 |
| 4107 // look for the closest line box in the root box which is at the passed-in y c
oordinate | 4284 // look for the closest line box in the root box which is at the passed-in y |
| 4285 // coordinate |
| 4108 InlineBox* closestBox = nullptr; | 4286 InlineBox* closestBox = nullptr; |
| 4109 RootInlineBox* firstRootBoxWithChildren = nullptr; | 4287 RootInlineBox* firstRootBoxWithChildren = nullptr; |
| 4110 RootInlineBox* lastRootBoxWithChildren = nullptr; | 4288 RootInlineBox* lastRootBoxWithChildren = nullptr; |
| 4111 for (RootInlineBox* root = firstRootBox(); root; root = root->nextRootBox()) { | 4289 for (RootInlineBox* root = firstRootBox(); root; root = root->nextRootBox()) { |
| 4112 if (!root->firstLeafChild()) | 4290 if (!root->firstLeafChild()) |
| 4113 continue; | 4291 continue; |
| 4114 if (!firstRootBoxWithChildren) | 4292 if (!firstRootBoxWithChildren) |
| 4115 firstRootBoxWithChildren = root; | 4293 firstRootBoxWithChildren = root; |
| 4116 | 4294 |
| 4117 if (!linesAreFlipped && root->isFirstAfterPageBreak() && | 4295 if (!linesAreFlipped && root->isFirstAfterPageBreak() && |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4168 std::min<LayoutUnit>(firstRootBoxWithChildren->selectionTop(), | 4346 std::min<LayoutUnit>(firstRootBoxWithChildren->selectionTop(), |
| 4169 firstRootBoxWithChildren->logicalTop()); | 4347 firstRootBoxWithChildren->logicalTop()); |
| 4170 if (pointInLogicalContents.y() < firstRootBoxWithChildrenTop || | 4348 if (pointInLogicalContents.y() < firstRootBoxWithChildrenTop || |
| 4171 (blocksAreFlipped && | 4349 (blocksAreFlipped && |
| 4172 pointInLogicalContents.y() == firstRootBoxWithChildrenTop)) { | 4350 pointInLogicalContents.y() == firstRootBoxWithChildrenTop)) { |
| 4173 InlineBox* box = firstRootBoxWithChildren->firstLeafChild(); | 4351 InlineBox* box = firstRootBoxWithChildren->firstLeafChild(); |
| 4174 if (box->isLineBreak()) { | 4352 if (box->isLineBreak()) { |
| 4175 if (InlineBox* newBox = box->nextLeafChildIgnoringLineBreak()) | 4353 if (InlineBox* newBox = box->nextLeafChildIgnoringLineBreak()) |
| 4176 box = newBox; | 4354 box = newBox; |
| 4177 } | 4355 } |
| 4178 // y coordinate is above first root line box, so return the start of the
first | 4356 // y coordinate is above first root line box, so return the start of the |
| 4357 // first |
| 4179 return PositionWithAffinity(positionForBox(box, true)); | 4358 return PositionWithAffinity(positionForBox(box, true)); |
| 4180 } | 4359 } |
| 4181 } | 4360 } |
| 4182 | 4361 |
| 4183 // pass the box a top position that is inside it | 4362 // pass the box a top position that is inside it |
| 4184 LayoutPoint point(pointInLogicalContents.x(), | 4363 LayoutPoint point(pointInLogicalContents.x(), |
| 4185 closestBox->root().blockDirectionPointInLine()); | 4364 closestBox->root().blockDirectionPointInLine()); |
| 4186 if (!isHorizontalWritingMode()) | 4365 if (!isHorizontalWritingMode()) |
| 4187 point = point.transposedPoint(); | 4366 point = point.transposedPoint(); |
| 4188 if (closestBox->getLineLayoutItem().isAtomicInlineLevel()) | 4367 if (closestBox->getLineLayoutItem().isAtomicInlineLevel()) |
| 4189 return positionForPointRespectingEditingBoundaries( | 4368 return positionForPointRespectingEditingBoundaries( |
| 4190 LineLayoutBox(closestBox->getLineLayoutItem()), point); | 4369 LineLayoutBox(closestBox->getLineLayoutItem()), point); |
| 4191 return closestBox->getLineLayoutItem().positionForPoint(point); | 4370 return closestBox->getLineLayoutItem().positionForPoint(point); |
| 4192 } | 4371 } |
| 4193 | 4372 |
| 4194 if (lastRootBoxWithChildren) { | 4373 if (lastRootBoxWithChildren) { |
| 4195 // We hit this case for Mac behavior when the Y coordinate is below the last
box. | 4374 // We hit this case for Mac behavior when the Y coordinate is below the last |
| 4375 // box. |
| 4196 ASSERT(moveCaretToBoundary); | 4376 ASSERT(moveCaretToBoundary); |
| 4197 InlineBox* logicallyLastBox; | 4377 InlineBox* logicallyLastBox; |
| 4198 if (lastRootBoxWithChildren->getLogicalEndBoxWithNode(logicallyLastBox)) | 4378 if (lastRootBoxWithChildren->getLogicalEndBoxWithNode(logicallyLastBox)) |
| 4199 return PositionWithAffinity(positionForBox(logicallyLastBox, false)); | 4379 return PositionWithAffinity(positionForBox(logicallyLastBox, false)); |
| 4200 } | 4380 } |
| 4201 | 4381 |
| 4202 // Can't reach this. We have a root line box, but it has no kids. | 4382 // 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 | 4383 // FIXME: This should ASSERT_NOT_REACHED(), but clicking on placeholder text |
| 4204 // seems to hit this code path. | 4384 // seems to hit this code path. |
| 4205 return createPositionWithAffinity(0); | 4385 return createPositionWithAffinity(0); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 4218 root->showLineTreeAndMark(markedBox1, markedLabel1, markedBox2, | 4398 root->showLineTreeAndMark(markedBox1, markedLabel1, markedBox2, |
| 4219 markedLabel2, obj, 1); | 4399 markedLabel2, obj, 1); |
| 4220 } | 4400 } |
| 4221 | 4401 |
| 4222 #endif | 4402 #endif |
| 4223 | 4403 |
| 4224 void LayoutBlockFlow::addOutlineRects( | 4404 void LayoutBlockFlow::addOutlineRects( |
| 4225 Vector<LayoutRect>& rects, | 4405 Vector<LayoutRect>& rects, |
| 4226 const LayoutPoint& additionalOffset, | 4406 const LayoutPoint& additionalOffset, |
| 4227 IncludeBlockVisualOverflowOrNot includeBlockOverflows) const { | 4407 IncludeBlockVisualOverflowOrNot includeBlockOverflows) const { |
| 4228 // For blocks inside inlines, we go ahead and include margins so that we run r
ight up to the | 4408 // 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 | 4409 // right up to the inline boxes above and below us (thus getting merged with |
| 4230 // shape). | 4410 // them to form a single irregular shape). |
| 4231 const LayoutInline* inlineElementContinuation = | 4411 const LayoutInline* inlineElementContinuation = |
| 4232 this->inlineElementContinuation(); | 4412 this->inlineElementContinuation(); |
| 4233 if (inlineElementContinuation) { | 4413 if (inlineElementContinuation) { |
| 4234 // FIXME: This check really isn't accurate. | 4414 // FIXME: This check really isn't accurate. |
| 4235 bool nextInlineHasLineBox = inlineElementContinuation->firstLineBox(); | 4415 bool nextInlineHasLineBox = inlineElementContinuation->firstLineBox(); |
| 4236 // FIXME: This is wrong. The principal layoutObject may not be the continuat
ion preceding this block. | 4416 // FIXME: This is wrong. The principal layoutObject may not be the |
| 4417 // continuation preceding this block. |
| 4237 // FIXME: This is wrong for vertical writing-modes. | 4418 // FIXME: This is wrong for vertical writing-modes. |
| 4238 // https://bugs.webkit.org/show_bug.cgi?id=46781 | 4419 // https://bugs.webkit.org/show_bug.cgi?id=46781 |
| 4239 bool prevInlineHasLineBox = | 4420 bool prevInlineHasLineBox = |
| 4240 toLayoutInline(inlineElementContinuation->node()->layoutObject()) | 4421 toLayoutInline(inlineElementContinuation->node()->layoutObject()) |
| 4241 ->firstLineBox(); | 4422 ->firstLineBox(); |
| 4242 LayoutUnit topMargin = | 4423 LayoutUnit topMargin = |
| 4243 prevInlineHasLineBox ? collapsedMarginBefore() : LayoutUnit(); | 4424 prevInlineHasLineBox ? collapsedMarginBefore() : LayoutUnit(); |
| 4244 LayoutUnit bottomMargin = | 4425 LayoutUnit bottomMargin = |
| 4245 nextInlineHasLineBox ? collapsedMarginAfter() : LayoutUnit(); | 4426 nextInlineHasLineBox ? collapsedMarginAfter() : LayoutUnit(); |
| 4246 if (topMargin || bottomMargin) { | 4427 if (topMargin || bottomMargin) { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4282 return LayoutBlock::invalidatePaintIfNeeded(paintInvalidationState); | 4463 return LayoutBlock::invalidatePaintIfNeeded(paintInvalidationState); |
| 4283 } | 4464 } |
| 4284 | 4465 |
| 4285 void LayoutBlockFlow::invalidateDisplayItemClients( | 4466 void LayoutBlockFlow::invalidateDisplayItemClients( |
| 4286 PaintInvalidationReason invalidationReason) const { | 4467 PaintInvalidationReason invalidationReason) const { |
| 4287 BlockFlowPaintInvalidator(*this).invalidateDisplayItemClients( | 4468 BlockFlowPaintInvalidator(*this).invalidateDisplayItemClients( |
| 4288 invalidationReason); | 4469 invalidationReason); |
| 4289 } | 4470 } |
| 4290 | 4471 |
| 4291 } // namespace blink | 4472 } // namespace blink |
| OLD | NEW |