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