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 |