| 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 25 matching lines...) Expand all Loading... |
| 36 #include "core/frame/Settings.h" | 36 #include "core/frame/Settings.h" |
| 37 #include "core/rendering/HitTestLocation.h" | 37 #include "core/rendering/HitTestLocation.h" |
| 38 #include "core/rendering/RenderLayer.h" | 38 #include "core/rendering/RenderLayer.h" |
| 39 #include "core/rendering/RenderText.h" | 39 #include "core/rendering/RenderText.h" |
| 40 #include "core/rendering/RenderView.h" | 40 #include "core/rendering/RenderView.h" |
| 41 #include "core/rendering/line/LineWidth.h" | 41 #include "core/rendering/line/LineWidth.h" |
| 42 #include "platform/text/BidiTextRun.h" | 42 #include "platform/text/BidiTextRun.h" |
| 43 | 43 |
| 44 namespace blink { | 44 namespace blink { |
| 45 | 45 |
| 46 struct SameSizeAsMarginInfo { | |
| 47 uint16_t bitfields; | |
| 48 LayoutUnit margins[2]; | |
| 49 }; | |
| 50 | |
| 51 COMPILE_ASSERT(sizeof(RenderBlockFlow::MarginValues) == sizeof(LayoutUnit[4]), M
arginValues_should_stay_small); | |
| 52 | |
| 53 class MarginInfo { | |
| 54 // Collapsing flags for whether we can collapse our margins with our childre
n's margins. | |
| 55 bool m_canCollapseWithChildren : 1; | |
| 56 bool m_canCollapseMarginBeforeWithChildren : 1; | |
| 57 bool m_canCollapseMarginAfterWithChildren : 1; | |
| 58 bool m_canCollapseMarginAfterWithLastChild: 1; | |
| 59 | |
| 60 // This flag tracks whether we are still looking at child margins that can a
ll collapse together at the beginning of a block. | |
| 61 // They may or may not collapse with the top margin of the block (|m_canColl
apseTopWithChildren| tells us that), but they will | |
| 62 // always be collapsing with one another. This variable can remain set to tr
ue through multiple iterations | |
| 63 // as long as we keep encountering self-collapsing blocks. | |
| 64 bool m_atBeforeSideOfBlock : 1; | |
| 65 | |
| 66 // This flag is set when we know we're examining bottom margins and we know
we're at the bottom of the block. | |
| 67 bool m_atAfterSideOfBlock : 1; | |
| 68 | |
| 69 // These variables are used to detect quirky margins that we need to collaps
e away (in table cells | |
| 70 // and in the body element). | |
| 71 bool m_hasMarginBeforeQuirk : 1; | |
| 72 bool m_hasMarginAfterQuirk : 1; | |
| 73 bool m_determinedMarginBeforeQuirk : 1; | |
| 74 | |
| 75 bool m_discardMargin : 1; | |
| 76 | |
| 77 // These flags track the previous maximal positive and negative margins. | |
| 78 LayoutUnit m_positiveMargin; | |
| 79 LayoutUnit m_negativeMargin; | |
| 80 | |
| 81 public: | |
| 82 MarginInfo(RenderBlockFlow*, LayoutUnit beforeBorderPadding, LayoutUnit afte
rBorderPadding); | |
| 83 | |
| 84 void setAtBeforeSideOfBlock(bool b) { m_atBeforeSideOfBlock = b; } | |
| 85 void setAtAfterSideOfBlock(bool b) { m_atAfterSideOfBlock = b; } | |
| 86 void clearMargin() | |
| 87 { | |
| 88 m_positiveMargin = 0; | |
| 89 m_negativeMargin = 0; | |
| 90 } | |
| 91 void setHasMarginBeforeQuirk(bool b) { m_hasMarginBeforeQuirk = b; } | |
| 92 void setHasMarginAfterQuirk(bool b) { m_hasMarginAfterQuirk = b; } | |
| 93 void setDeterminedMarginBeforeQuirk(bool b) { m_determinedMarginBeforeQuirk
= b; } | |
| 94 void setPositiveMargin(LayoutUnit p) { ASSERT(!m_discardMargin); m_positiveM
argin = p; } | |
| 95 void setNegativeMargin(LayoutUnit n) { ASSERT(!m_discardMargin); m_negativeM
argin = n; } | |
| 96 void setPositiveMarginIfLarger(LayoutUnit p) | |
| 97 { | |
| 98 ASSERT(!m_discardMargin); | |
| 99 if (p > m_positiveMargin) | |
| 100 m_positiveMargin = p; | |
| 101 } | |
| 102 void setNegativeMarginIfLarger(LayoutUnit n) | |
| 103 { | |
| 104 ASSERT(!m_discardMargin); | |
| 105 if (n > m_negativeMargin) | |
| 106 m_negativeMargin = n; | |
| 107 } | |
| 108 | |
| 109 void setMargin(LayoutUnit p, LayoutUnit n) { ASSERT(!m_discardMargin); m_pos
itiveMargin = p; m_negativeMargin = n; } | |
| 110 void setCanCollapseMarginAfterWithChildren(bool collapse) { m_canCollapseMar
ginAfterWithChildren = collapse; } | |
| 111 void setCanCollapseMarginAfterWithLastChild(bool collapse) { m_canCollapseMa
rginAfterWithLastChild = collapse; } | |
| 112 void setDiscardMargin(bool value) { m_discardMargin = value; } | |
| 113 | |
| 114 bool atBeforeSideOfBlock() const { return m_atBeforeSideOfBlock; } | |
| 115 bool canCollapseWithMarginBefore() const { return m_atBeforeSideOfBlock && m
_canCollapseMarginBeforeWithChildren; } | |
| 116 bool canCollapseWithMarginAfter() const { return m_atAfterSideOfBlock && m_c
anCollapseMarginAfterWithChildren; } | |
| 117 bool canCollapseMarginBeforeWithChildren() const { return m_canCollapseMargi
nBeforeWithChildren; } | |
| 118 bool canCollapseMarginAfterWithChildren() const { return m_canCollapseMargin
AfterWithChildren; } | |
| 119 bool canCollapseMarginAfterWithLastChild() const { return m_canCollapseMargi
nAfterWithLastChild; } | |
| 120 bool determinedMarginBeforeQuirk() const { return m_determinedMarginBeforeQu
irk; } | |
| 121 bool hasMarginBeforeQuirk() const { return m_hasMarginBeforeQuirk; } | |
| 122 bool hasMarginAfterQuirk() const { return m_hasMarginAfterQuirk; } | |
| 123 LayoutUnit positiveMargin() const { return m_positiveMargin; } | |
| 124 LayoutUnit negativeMargin() const { return m_negativeMargin; } | |
| 125 bool discardMargin() const { return m_discardMargin; } | |
| 126 LayoutUnit margin() const { return m_positiveMargin - m_negativeMargin; } | |
| 127 }; | |
| 128 | |
| 129 void RenderBlockFlow::RenderBlockFlowRareData::trace(Visitor* visitor) | |
| 130 { | |
| 131 } | |
| 132 | |
| 133 RenderBlockFlow::RenderBlockFlow(ContainerNode* node) | 46 RenderBlockFlow::RenderBlockFlow(ContainerNode* node) |
| 134 : RenderBlock(node) | 47 : RenderBlock(node) |
| 135 { | 48 { |
| 136 COMPILE_ASSERT(sizeof(MarginInfo) == sizeof(SameSizeAsMarginInfo), MarginInf
o_should_stay_small); | |
| 137 setChildrenInline(true); | 49 setChildrenInline(true); |
| 138 } | 50 } |
| 139 | 51 |
| 140 RenderBlockFlow::~RenderBlockFlow() | 52 RenderBlockFlow::~RenderBlockFlow() |
| 141 { | 53 { |
| 142 } | 54 } |
| 143 | 55 |
| 144 void RenderBlockFlow::trace(Visitor* visitor) | |
| 145 { | |
| 146 visitor->trace(m_rareData); | |
| 147 RenderBlock::trace(visitor); | |
| 148 } | |
| 149 | |
| 150 RenderBlockFlow* RenderBlockFlow::createAnonymous(Document* document) | 56 RenderBlockFlow* RenderBlockFlow::createAnonymous(Document* document) |
| 151 { | 57 { |
| 152 RenderBlockFlow* renderer = new RenderBlockFlow(0); | 58 RenderBlockFlow* renderer = new RenderBlockFlow(0); |
| 153 renderer->setDocumentForAnonymous(document); | 59 renderer->setDocumentForAnonymous(document); |
| 154 return renderer; | 60 return renderer; |
| 155 } | 61 } |
| 156 | 62 |
| 157 bool RenderBlockFlow::updateLogicalWidthAndColumnWidth() | 63 bool RenderBlockFlow::updateLogicalWidthAndColumnWidth() |
| 158 { | 64 { |
| 159 return RenderBlock::updateLogicalWidthAndColumnWidth(); | 65 return RenderBlock::updateLogicalWidthAndColumnWidth(); |
| 160 } | 66 } |
| 161 | 67 |
| 162 bool RenderBlockFlow::isSelfCollapsingBlock() const | |
| 163 { | |
| 164 m_hasOnlySelfCollapsingChildren = RenderBlock::isSelfCollapsingBlock(); | |
| 165 return m_hasOnlySelfCollapsingChildren; | |
| 166 } | |
| 167 | |
| 168 void RenderBlockFlow::layoutBlock(bool relayoutChildren) | 68 void RenderBlockFlow::layoutBlock(bool relayoutChildren) |
| 169 { | 69 { |
| 170 ASSERT(needsLayout()); | 70 ASSERT(needsLayout()); |
| 171 ASSERT(isInlineBlock() || !isInline()); | 71 ASSERT(isInlineBlock() || !isInline()); |
| 172 | 72 |
| 173 // If we are self-collapsing with self-collapsing descendants this will get
set to save us burrowing through our | |
| 174 // descendants every time in |isSelfCollapsingBlock|. We reset it here so th
at |isSelfCollapsingBlock| attempts to burrow | |
| 175 // at least once and so that it always gives a reliable result reflecting th
e latest layout. | |
| 176 m_hasOnlySelfCollapsingChildren = false; | |
| 177 | |
| 178 if (!relayoutChildren && simplifiedLayout()) | 73 if (!relayoutChildren && simplifiedLayout()) |
| 179 return; | 74 return; |
| 180 | 75 |
| 181 SubtreeLayoutScope layoutScope(*this); | 76 SubtreeLayoutScope layoutScope(*this); |
| 182 | 77 |
| 183 layoutBlockFlow(relayoutChildren, layoutScope); | 78 layoutBlockFlow(relayoutChildren, layoutScope); |
| 184 | 79 |
| 185 updateLayerTransformAfterLayout(); | 80 updateLayerTransformAfterLayout(); |
| 186 | 81 |
| 187 // Update our scroll information if we're overflow:auto/scroll/hidden now th
at we know if | 82 // Update our scroll information if we're overflow:auto/scroll/hidden now th
at we know if |
| 188 // we overflow or not. | 83 // we overflow or not. |
| 189 updateScrollInfoAfterLayout(); | 84 updateScrollInfoAfterLayout(); |
| 190 | 85 |
| 191 if (m_paintInvalidationLogicalTop != m_paintInvalidationLogicalBottom) | 86 if (m_paintInvalidationLogicalTop != m_paintInvalidationLogicalBottom) |
| 192 setShouldInvalidateOverflowForPaint(true); | 87 setShouldInvalidateOverflowForPaint(true); |
| 193 | 88 |
| 194 clearNeedsLayout(); | 89 clearNeedsLayout(); |
| 195 } | 90 } |
| 196 | 91 |
| 197 inline void RenderBlockFlow::layoutBlockFlow(bool relayoutChildren, SubtreeLayou
tScope& layoutScope) | 92 inline void RenderBlockFlow::layoutBlockFlow(bool relayoutChildren, SubtreeLayou
tScope& layoutScope) |
| 198 { | 93 { |
| 199 LayoutUnit oldLeft = logicalLeft(); | 94 LayoutUnit oldLeft = logicalLeft(); |
| 200 bool logicalWidthChanged = updateLogicalWidthAndColumnWidth(); | 95 bool logicalWidthChanged = updateLogicalWidthAndColumnWidth(); |
| 201 relayoutChildren |= logicalWidthChanged; | 96 relayoutChildren |= logicalWidthChanged; |
| 202 | 97 |
| 203 LayoutState state(*this, locationOffset(), logicalWidthChanged); | 98 LayoutState state(*this, locationOffset(), logicalWidthChanged); |
| 204 | 99 |
| 205 // We use four values, maxTopPos, maxTopNeg, maxBottomPos, and maxBottomNeg,
to track | |
| 206 // our current maximal positive and negative margins. These values are used
when we | |
| 207 // are collapsed with adjacent blocks, so for example, if you have block A a
nd B | |
| 208 // collapsing together, then you'd take the maximal positive margin from bot
h A and B | |
| 209 // and subtract it from the maximal negative margin from both A and B to get
the | |
| 210 // true collapsed margin. This algorithm is recursive, so when we finish lay
out() | |
| 211 // our block knows its current maximal positive/negative values. | |
| 212 initMaxMarginValues(); | |
| 213 setHasMarginBeforeQuirk(style()->hasMarginBeforeQuirk()); | |
| 214 setHasMarginAfterQuirk(style()->hasMarginAfterQuirk()); | |
| 215 | |
| 216 LayoutUnit beforeEdge = borderBefore() + paddingBefore(); | 100 LayoutUnit beforeEdge = borderBefore() + paddingBefore(); |
| 217 LayoutUnit afterEdge = borderAfter() + paddingAfter() + scrollbarLogicalHeig
ht(); | 101 LayoutUnit afterEdge = borderAfter() + paddingAfter() + scrollbarLogicalHeig
ht(); |
| 218 LayoutUnit previousHeight = logicalHeight(); | 102 LayoutUnit previousHeight = logicalHeight(); |
| 219 setLogicalHeight(beforeEdge); | 103 setLogicalHeight(beforeEdge); |
| 220 | 104 |
| 221 m_paintInvalidationLogicalTop = 0; | 105 m_paintInvalidationLogicalTop = 0; |
| 222 m_paintInvalidationLogicalBottom = 0; | 106 m_paintInvalidationLogicalBottom = 0; |
| 223 if (!firstChild() && !isAnonymousBlock()) | 107 if (!firstChild() && !isAnonymousBlock()) |
| 224 setChildrenInline(true); | 108 setChildrenInline(true); |
| 225 | 109 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 254 // If the child has an offset from the content edge to avoid floats then use
that, otherwise let any negative | 138 // If the child has an offset from the content edge to avoid floats then use
that, otherwise let any negative |
| 255 // margin pull it back over the content edge or any positive margin push it
out. | 139 // margin pull it back over the content edge or any positive margin push it
out. |
| 256 // If the child is being centred then the margin calculated to do that has f
actored in any offset required to | 140 // If the child is being centred then the margin calculated to do that has f
actored in any offset required to |
| 257 // avoid floats, so use it if necessary. | 141 // avoid floats, so use it if necessary. |
| 258 if (style()->textAlign() == WEBKIT_CENTER || child->style()->marginStartUsin
g(style()).isAuto()) | 142 if (style()->textAlign() == WEBKIT_CENTER || child->style()->marginStartUsin
g(style()).isAuto()) |
| 259 newPosition = std::max(newPosition, childMarginStart); | 143 newPosition = std::max(newPosition, childMarginStart); |
| 260 | 144 |
| 261 child->setX(style()->isLeftToRightDirection() ? newPosition : totalAvailable
LogicalWidth - newPosition - logicalWidthForChild(child)); | 145 child->setX(style()->isLeftToRightDirection() ? newPosition : totalAvailable
LogicalWidth - newPosition - logicalWidthForChild(child)); |
| 262 } | 146 } |
| 263 | 147 |
| 264 void RenderBlockFlow::layoutBlockChild(RenderBox* child, MarginInfo& marginInfo) | 148 void RenderBlockFlow::layoutBlockChild(RenderBox* child) |
| 265 { | 149 { |
| 266 // The child is a normal flow object. Compute the margins we will use for co
llapsing now. | |
| 267 child->computeAndSetBlockDirectionMargins(this); | 150 child->computeAndSetBlockDirectionMargins(this); |
| 268 | 151 LayoutUnit marginBefore = marginBeforeForChild(child); |
| 269 // Try to guess our correct logical top position. In most cases this guess w
ill | 152 child->setY(logicalHeight() + marginBefore); |
| 270 // be correct. Only if we're wrong (when we compute the real logical top pos
ition) | |
| 271 // will we have to potentially relayout. | |
| 272 // Go ahead and position the child as though it didn't collapse with the top
. | |
| 273 child->setY(estimateLogicalTopPosition(child, marginInfo)); | |
| 274 | |
| 275 child->layoutIfNeeded(); | 153 child->layoutIfNeeded(); |
| 276 | |
| 277 // Cache if we are at the top of the block right now. | |
| 278 bool childIsSelfCollapsing = child->isSelfCollapsingBlock(); | |
| 279 | |
| 280 // Now determine the correct ypos based off examination of collapsing margin | |
| 281 // values. | |
| 282 child->setY(collapseMargins(child, marginInfo, childIsSelfCollapsing)); | |
| 283 | |
| 284 // FIXME(sky): Is it still actually possible for the child to need layout he
re? | |
| 285 // This used to be needed for floats and/or margin collapsing. | |
| 286 child->layoutIfNeeded(); | |
| 287 | |
| 288 // If we previously encountered a self-collapsing sibling of this child that
had clearance then | |
| 289 // we set this bit to ensure we would not collapse the child's margins, and
those of any subsequent | |
| 290 // self-collapsing siblings, with our parent. If this child is not self-coll
apsing then it can | |
| 291 // collapse its margins with the parent so reset the bit. | |
| 292 if (!marginInfo.canCollapseMarginAfterWithLastChild() && !childIsSelfCollaps
ing) | |
| 293 marginInfo.setCanCollapseMarginAfterWithLastChild(true); | |
| 294 | |
| 295 // We are no longer at the top of the block if we encounter a non-empty chil
d. | |
| 296 // This has to be done after checking for clear, so that margins can be rese
t if a clear occurred. | |
| 297 if (marginInfo.atBeforeSideOfBlock() && !childIsSelfCollapsing) | |
| 298 marginInfo.setAtBeforeSideOfBlock(false); | |
| 299 | |
| 300 // Now place the child in the correct left position | |
| 301 determineLogicalLeftPositionForChild(child); | 154 determineLogicalLeftPositionForChild(child); |
| 302 | 155 setLogicalHeight(logicalHeight() + marginBefore + logicalHeightForChild(chil
d) + marginAfterForChild(child)); |
| 303 // Update our height now that the child has been placed in the correct posit
ion. | |
| 304 setLogicalHeight(logicalHeight() + logicalHeightForChild(child)); | |
| 305 if (mustSeparateMarginAfterForChild(child)) { | |
| 306 setLogicalHeight(logicalHeight() + marginAfterForChild(child)); | |
| 307 marginInfo.clearMargin(); | |
| 308 } | |
| 309 } | 156 } |
| 310 | 157 |
| 311 void RenderBlockFlow::layoutBlockChildren(bool relayoutChildren, SubtreeLayoutSc
ope& layoutScope, LayoutUnit beforeEdge, LayoutUnit afterEdge) | 158 void RenderBlockFlow::layoutBlockChildren(bool relayoutChildren, SubtreeLayoutSc
ope& layoutScope, LayoutUnit beforeEdge, LayoutUnit afterEdge) |
| 312 { | 159 { |
| 313 dirtyForLayoutFromPercentageHeightDescendants(layoutScope); | 160 dirtyForLayoutFromPercentageHeightDescendants(layoutScope); |
| 314 | 161 |
| 315 // The margin struct caches all our current margin collapsing state. The com
pact struct caches state when we encounter compacts, | |
| 316 MarginInfo marginInfo(this, beforeEdge, afterEdge); | |
| 317 | |
| 318 RenderBox* next = firstChildBox(); | 162 RenderBox* next = firstChildBox(); |
| 319 RenderBox* lastNormalFlowChild = 0; | 163 RenderBox* lastNormalFlowChild = 0; |
| 320 | 164 |
| 321 while (next) { | 165 while (next) { |
| 322 RenderBox* child = next; | 166 RenderBox* child = next; |
| 323 next = child->nextSiblingBox(); | 167 next = child->nextSiblingBox(); |
| 324 | 168 |
| 325 // FIXME: this should only be set from clearNeedsLayout crbug.com/361250 | 169 // FIXME: this should only be set from clearNeedsLayout crbug.com/361250 |
| 326 child->setLayoutDidGetCalled(true); | 170 child->setLayoutDidGetCalled(true); |
| 327 | 171 |
| 328 updateBlockChildDirtyBitsBeforeLayout(relayoutChildren, child); | 172 updateBlockChildDirtyBitsBeforeLayout(relayoutChildren, child); |
| 329 | 173 |
| 330 if (child->isOutOfFlowPositioned()) { | 174 if (child->isOutOfFlowPositioned()) { |
| 331 child->containingBlock()->insertPositionedObject(child); | 175 child->containingBlock()->insertPositionedObject(child); |
| 332 adjustPositionedBlock(child, marginInfo); | 176 adjustPositionedBlock(child); |
| 333 continue; | 177 continue; |
| 334 } | 178 } |
| 335 | 179 |
| 336 // Lay out the child. | 180 // Lay out the child. |
| 337 layoutBlockChild(child, marginInfo); | 181 layoutBlockChild(child); |
| 338 lastNormalFlowChild = child; | 182 lastNormalFlowChild = child; |
| 339 } | 183 } |
| 340 | 184 |
| 341 // Now do the handling of the bottom of the block, adding in our bottom bord
er/padding and | 185 // Negative margins can cause our height to shrink below our minimal height
(border/padding). |
| 342 // determining the correct collapsed bottom margin information. | 186 // If this happens, ensure that the computed height is increased to the mini
mal height. |
| 343 handleAfterSideOfBlock(lastNormalFlowChild, beforeEdge, afterEdge, marginInf
o); | 187 setLogicalHeight(std::max(logicalHeight() + afterEdge, beforeEdge + afterEdg
e)); |
| 344 } | 188 } |
| 345 | 189 |
| 346 // Our MarginInfo state used when laying out block children. | 190 void RenderBlockFlow::adjustPositionedBlock(RenderBox* child) |
| 347 MarginInfo::MarginInfo(RenderBlockFlow* blockFlow, LayoutUnit beforeBorderPaddin
g, LayoutUnit afterBorderPadding) | |
| 348 : m_canCollapseMarginAfterWithLastChild(true) | |
| 349 , m_atBeforeSideOfBlock(true) | |
| 350 , m_atAfterSideOfBlock(false) | |
| 351 , m_hasMarginBeforeQuirk(false) | |
| 352 , m_hasMarginAfterQuirk(false) | |
| 353 , m_determinedMarginBeforeQuirk(false) | |
| 354 , m_discardMargin(false) | |
| 355 { | |
| 356 RenderStyle* blockStyle = blockFlow->style(); | |
| 357 ASSERT(blockFlow->isRenderView() || blockFlow->parent()); | |
| 358 m_canCollapseWithChildren = !blockFlow->createsBlockFormattingContext() && !
blockFlow->isRenderView(); | |
| 359 | |
| 360 m_canCollapseMarginBeforeWithChildren = m_canCollapseWithChildren && !before
BorderPadding && blockStyle->marginBeforeCollapse() != MSEPARATE; | |
| 361 | |
| 362 // If any height other than auto is specified in CSS, then we don't collapse
our bottom | |
| 363 // margins with our children's margins. To do otherwise would be to risk odd
visual | |
| 364 // effects when the children overflow out of the parent block and yet still
collapse | |
| 365 // with it. We also don't collapse if we have any bottom border/padding. | |
| 366 m_canCollapseMarginAfterWithChildren = m_canCollapseWithChildren && !afterBo
rderPadding | |
| 367 && (blockStyle->logicalHeight().isAuto() && !blockStyle->logicalHeight()
.value()) && blockStyle->marginAfterCollapse() != MSEPARATE; | |
| 368 | |
| 369 m_discardMargin = m_canCollapseMarginBeforeWithChildren && blockFlow->mustDi
scardMarginBefore(); | |
| 370 | |
| 371 m_positiveMargin = (m_canCollapseMarginBeforeWithChildren && !blockFlow->mus
tDiscardMarginBefore()) ? blockFlow->maxPositiveMarginBefore() : LayoutUnit(); | |
| 372 m_negativeMargin = (m_canCollapseMarginBeforeWithChildren && !blockFlow->mus
tDiscardMarginBefore()) ? blockFlow->maxNegativeMarginBefore() : LayoutUnit(); | |
| 373 } | |
| 374 | |
| 375 RenderBlockFlow::MarginValues RenderBlockFlow::marginValuesForChild(RenderBox* c
hild) const | |
| 376 { | |
| 377 LayoutUnit childBeforePositive = 0; | |
| 378 LayoutUnit childBeforeNegative = 0; | |
| 379 LayoutUnit childAfterPositive = 0; | |
| 380 LayoutUnit childAfterNegative = 0; | |
| 381 | |
| 382 LayoutUnit beforeMargin = 0; | |
| 383 LayoutUnit afterMargin = 0; | |
| 384 | |
| 385 RenderBlockFlow* childRenderBlockFlow = child->isRenderBlockFlow() ? toRende
rBlockFlow(child) : 0; | |
| 386 | |
| 387 if (childRenderBlockFlow) { | |
| 388 childBeforePositive = childRenderBlockFlow->maxPositiveMarginBefore(); | |
| 389 childBeforeNegative = childRenderBlockFlow->maxNegativeMarginBefore(); | |
| 390 childAfterPositive = childRenderBlockFlow->maxPositiveMarginAfter(); | |
| 391 childAfterNegative = childRenderBlockFlow->maxNegativeMarginAfter(); | |
| 392 } else { | |
| 393 beforeMargin = child->marginBefore(); | |
| 394 afterMargin = child->marginAfter(); | |
| 395 } | |
| 396 | |
| 397 // Resolve uncollapsing margins into their positive/negative buckets. | |
| 398 if (beforeMargin) { | |
| 399 if (beforeMargin > 0) | |
| 400 childBeforePositive = beforeMargin; | |
| 401 else | |
| 402 childBeforeNegative = -beforeMargin; | |
| 403 } | |
| 404 if (afterMargin) { | |
| 405 if (afterMargin > 0) | |
| 406 childAfterPositive = afterMargin; | |
| 407 else | |
| 408 childAfterNegative = -afterMargin; | |
| 409 } | |
| 410 | |
| 411 return RenderBlockFlow::MarginValues(childBeforePositive, childBeforeNegativ
e, childAfterPositive, childAfterNegative); | |
| 412 } | |
| 413 | |
| 414 LayoutUnit RenderBlockFlow::collapseMargins(RenderBox* child, MarginInfo& margin
Info, bool childIsSelfCollapsing) | |
| 415 { | |
| 416 bool childDiscardMarginBefore = mustDiscardMarginBeforeForChild(child); | |
| 417 bool childDiscardMarginAfter = mustDiscardMarginAfterForChild(child); | |
| 418 | |
| 419 // The child discards the before margin when the the after margin has discar
d in the case of a self collapsing block. | |
| 420 childDiscardMarginBefore = childDiscardMarginBefore || (childDiscardMarginAf
ter && childIsSelfCollapsing); | |
| 421 | |
| 422 // Get the four margin values for the child and cache them. | |
| 423 const RenderBlockFlow::MarginValues childMargins = marginValuesForChild(chil
d); | |
| 424 | |
| 425 // Get our max pos and neg top margins. | |
| 426 LayoutUnit posTop = childMargins.positiveMarginBefore(); | |
| 427 LayoutUnit negTop = childMargins.negativeMarginBefore(); | |
| 428 | |
| 429 // For self-collapsing blocks, collapse our bottom margins into our | |
| 430 // top to get new posTop and negTop values. | |
| 431 if (childIsSelfCollapsing) { | |
| 432 posTop = std::max(posTop, childMargins.positiveMarginAfter()); | |
| 433 negTop = std::max(negTop, childMargins.negativeMarginAfter()); | |
| 434 } | |
| 435 | |
| 436 // See if the top margin is quirky. We only care if this child has | |
| 437 // margins that will collapse with us. | |
| 438 bool topQuirk = hasMarginBeforeQuirk(child); | |
| 439 | |
| 440 if (marginInfo.canCollapseWithMarginBefore()) { | |
| 441 if (!childDiscardMarginBefore && !marginInfo.discardMargin()) { | |
| 442 // This child is collapsing with the top of the | |
| 443 // block. If it has larger margin values, then we need to update | |
| 444 // our own maximal values. | |
| 445 setMaxMarginBeforeValues(std::max(posTop, maxPositiveMarginBefore())
, std::max(negTop, maxNegativeMarginBefore())); | |
| 446 | |
| 447 // The minute any of the margins involved isn't a quirk, don't | |
| 448 // collapse it away, even if the margin is smaller (www.webreference
.com | |
| 449 // has an example of this, a <dt> with 0.8em author-specified inside | |
| 450 // a <dl> inside a <td>. | |
| 451 if (!marginInfo.determinedMarginBeforeQuirk() && !topQuirk && (posTo
p - negTop)) { | |
| 452 setHasMarginBeforeQuirk(false); | |
| 453 marginInfo.setDeterminedMarginBeforeQuirk(true); | |
| 454 } | |
| 455 | |
| 456 if (!marginInfo.determinedMarginBeforeQuirk() && topQuirk && !margin
Before()) { | |
| 457 // We have no top margin and our top child has a quirky margin. | |
| 458 // We will pick up this quirky margin and pass it through. | |
| 459 // This deals with the <td><div><p> case. | |
| 460 // Don't do this for a block that split two inlines though. You
do | |
| 461 // still apply margins in this case. | |
| 462 setHasMarginBeforeQuirk(true); | |
| 463 } | |
| 464 } else { | |
| 465 // The before margin of the container will also discard all the marg
ins it is collapsing with. | |
| 466 setMustDiscardMarginBefore(); | |
| 467 } | |
| 468 } | |
| 469 | |
| 470 // Once we find a child with discardMarginBefore all the margins collapsing
with us must also discard. | |
| 471 if (childDiscardMarginBefore) { | |
| 472 marginInfo.setDiscardMargin(true); | |
| 473 marginInfo.clearMargin(); | |
| 474 } | |
| 475 | |
| 476 LayoutUnit beforeCollapseLogicalTop = logicalHeight(); | |
| 477 LayoutUnit logicalTop = beforeCollapseLogicalTop; | |
| 478 | |
| 479 LayoutUnit clearanceForSelfCollapsingBlock; | |
| 480 RenderObject* prev = child->previousSibling(); | |
| 481 RenderBlockFlow* previousBlockFlow = prev && prev->isRenderBlockFlow() && !
prev->isFloatingOrOutOfFlowPositioned() ? toRenderBlockFlow(prev) : 0; | |
| 482 // If the child's previous sibling is a self-collapsing block that cleared a
float then its top border edge has been set at the bottom border edge | |
| 483 // of the float. Since we want to collapse the child's top margin with the s
elf-collapsing block's top and bottom margins we need to adjust our parent's hei
ght to match the | |
| 484 // margin top of the self-collapsing block. If the resulting collapsed margi
n leaves the child still intruding into the float then we will want to clear it. | |
| 485 if (!marginInfo.canCollapseWithMarginBefore() && previousBlockFlow && previo
usBlockFlow->isSelfCollapsingBlock()) { | |
| 486 clearanceForSelfCollapsingBlock = previousBlockFlow->marginOffsetForSelf
CollapsingBlock(); | |
| 487 setLogicalHeight(logicalHeight() - clearanceForSelfCollapsingBlock); | |
| 488 } | |
| 489 | |
| 490 if (childIsSelfCollapsing) { | |
| 491 // For a self collapsing block both the before and after margins get dis
carded. The block doesn't contribute anything to the height of the block. | |
| 492 // Also, the child's top position equals the logical height of the conta
iner. | |
| 493 if (!childDiscardMarginBefore && !marginInfo.discardMargin()) { | |
| 494 // This child has no height. We need to compute our | |
| 495 // position before we collapse the child's margins together, | |
| 496 // so that we can get an accurate position for the zero-height block
. | |
| 497 LayoutUnit collapsedBeforePos = std::max(marginInfo.positiveMargin()
, childMargins.positiveMarginBefore()); | |
| 498 LayoutUnit collapsedBeforeNeg = std::max(marginInfo.negativeMargin()
, childMargins.negativeMarginBefore()); | |
| 499 marginInfo.setMargin(collapsedBeforePos, collapsedBeforeNeg); | |
| 500 | |
| 501 // Now collapse the child's margins together, which means examining
our | |
| 502 // bottom margin values as well. | |
| 503 marginInfo.setPositiveMarginIfLarger(childMargins.positiveMarginAfte
r()); | |
| 504 marginInfo.setNegativeMarginIfLarger(childMargins.negativeMarginAfte
r()); | |
| 505 | |
| 506 if (!marginInfo.canCollapseWithMarginBefore()) { | |
| 507 // We need to make sure that the position of the self-collapsing
block | |
| 508 // is correct, since it could have overflowing content | |
| 509 // that needs to be positioned correctly (e.g., a block that | |
| 510 // had a specified height of 0 but that actually had subcontent)
. | |
| 511 logicalTop = logicalHeight() + collapsedBeforePos - collapsedBef
oreNeg; | |
| 512 } | |
| 513 } | |
| 514 } else { | |
| 515 if (mustSeparateMarginBeforeForChild(child)) { | |
| 516 ASSERT(!marginInfo.discardMargin() || (marginInfo.discardMargin() &&
!marginInfo.margin())); | |
| 517 // If we are at the before side of the block and we collapse, ignore
the computed margin | |
| 518 // and just add the child margin to the container height. This will
correctly position | |
| 519 // the child inside the container. | |
| 520 LayoutUnit separateMargin = !marginInfo.canCollapseWithMarginBefore(
) ? marginInfo.margin() : LayoutUnit(0); | |
| 521 setLogicalHeight(logicalHeight() + separateMargin + marginBeforeForC
hild(child)); | |
| 522 logicalTop = logicalHeight(); | |
| 523 } else if (!marginInfo.discardMargin() && (!marginInfo.atBeforeSideOfBlo
ck() | |
| 524 || (!marginInfo.canCollapseMarginBeforeWithChildren()))) { | |
| 525 // We're collapsing with a previous sibling's margins and not | |
| 526 // with the top of the block. | |
| 527 setLogicalHeight(logicalHeight() + std::max(marginInfo.positiveMargi
n(), posTop) - std::max(marginInfo.negativeMargin(), negTop)); | |
| 528 logicalTop = logicalHeight(); | |
| 529 } | |
| 530 | |
| 531 marginInfo.setDiscardMargin(childDiscardMarginAfter); | |
| 532 | |
| 533 if (!marginInfo.discardMargin()) { | |
| 534 marginInfo.setPositiveMargin(childMargins.positiveMarginAfter()); | |
| 535 marginInfo.setNegativeMargin(childMargins.negativeMarginAfter()); | |
| 536 } else { | |
| 537 marginInfo.clearMargin(); | |
| 538 } | |
| 539 | |
| 540 if (marginInfo.margin()) | |
| 541 marginInfo.setHasMarginAfterQuirk(hasMarginAfterQuirk(child)); | |
| 542 } | |
| 543 | |
| 544 return logicalTop; | |
| 545 } | |
| 546 | |
| 547 void RenderBlockFlow::adjustPositionedBlock(RenderBox* child, const MarginInfo&
marginInfo) | |
| 548 { | 191 { |
| 549 bool hasStaticBlockPosition = child->style()->hasStaticBlockPosition(); | 192 bool hasStaticBlockPosition = child->style()->hasStaticBlockPosition(); |
| 550 | 193 |
| 551 LayoutUnit logicalTop = logicalHeight(); | 194 LayoutUnit logicalTop = logicalHeight(); |
| 552 updateStaticInlinePositionForChild(child, logicalTop); | 195 updateStaticInlinePositionForChild(child, logicalTop); |
| 553 | 196 |
| 554 if (!marginInfo.canCollapseWithMarginBefore()) { | |
| 555 // Positioned blocks don't collapse margins, so add the margin provided
by | |
| 556 // the container now. The child's own margin is added later when calcula
ting its logical top. | |
| 557 LayoutUnit collapsedBeforePos = marginInfo.positiveMargin(); | |
| 558 LayoutUnit collapsedBeforeNeg = marginInfo.negativeMargin(); | |
| 559 logicalTop += collapsedBeforePos - collapsedBeforeNeg; | |
| 560 } | |
| 561 | |
| 562 RenderLayer* childLayer = child->layer(); | 197 RenderLayer* childLayer = child->layer(); |
| 563 if (childLayer->staticBlockPosition() != logicalTop) { | 198 if (childLayer->staticBlockPosition() != logicalTop) { |
| 564 childLayer->setStaticBlockPosition(logicalTop); | 199 childLayer->setStaticBlockPosition(logicalTop); |
| 565 if (hasStaticBlockPosition) | 200 if (hasStaticBlockPosition) |
| 566 child->setChildNeedsLayout(MarkOnlyThis); | 201 child->setChildNeedsLayout(MarkOnlyThis); |
| 567 } | 202 } |
| 568 } | 203 } |
| 569 | 204 |
| 570 void RenderBlockFlow::setCollapsedBottomMargin(const MarginInfo& marginInfo) | |
| 571 { | |
| 572 if (marginInfo.canCollapseWithMarginAfter() && !marginInfo.canCollapseWithMa
rginBefore()) { | |
| 573 // Update the after side margin of the container to discard if the after
margin of the last child also discards and we collapse with it. | |
| 574 // Don't update the max margin values because we won't need them anyway. | |
| 575 if (marginInfo.discardMargin()) { | |
| 576 setMustDiscardMarginAfter(); | |
| 577 return; | |
| 578 } | |
| 579 | |
| 580 // Update our max pos/neg bottom margins, since we collapsed our bottom
margins | |
| 581 // with our children. | |
| 582 setMaxMarginAfterValues(std::max(maxPositiveMarginAfter(), marginInfo.po
sitiveMargin()), std::max(maxNegativeMarginAfter(), marginInfo.negativeMargin())
); | |
| 583 | |
| 584 if (!marginInfo.hasMarginAfterQuirk()) | |
| 585 setHasMarginAfterQuirk(false); | |
| 586 | |
| 587 if (marginInfo.hasMarginAfterQuirk() && !marginAfter()) { | |
| 588 // We have no bottom margin and our last child has a quirky margin. | |
| 589 // We will pick up this quirky margin and pass it through. | |
| 590 // This deals with the <td><div><p> case. | |
| 591 setHasMarginAfterQuirk(true); | |
| 592 } | |
| 593 } | |
| 594 } | |
| 595 | |
| 596 void RenderBlockFlow::marginBeforeEstimateForChild(RenderBox* child, LayoutUnit&
positiveMarginBefore, LayoutUnit& negativeMarginBefore, bool& discardMarginBefo
re) const | |
| 597 { | |
| 598 // Give up if in quirks mode and we're a body/table cell and the top margin
of the child box is quirky. | |
| 599 // Give up if the child specified -webkit-margin-collapse: separate that pre
vents collapsing. | |
| 600 // FIXME: Use writing mode independent accessor for marginBeforeCollapse. | |
| 601 if (child->style()->marginBeforeCollapse() == MSEPARATE) | |
| 602 return; | |
| 603 | |
| 604 // The margins are discarded by a child that specified -webkit-margin-collap
se: discard. | |
| 605 // FIXME: Use writing mode independent accessor for marginBeforeCollapse. | |
| 606 if (child->style()->marginBeforeCollapse() == MDISCARD) { | |
| 607 positiveMarginBefore = 0; | |
| 608 negativeMarginBefore = 0; | |
| 609 discardMarginBefore = true; | |
| 610 return; | |
| 611 } | |
| 612 | |
| 613 LayoutUnit beforeChildMargin = marginBeforeForChild(child); | |
| 614 positiveMarginBefore = std::max(positiveMarginBefore, beforeChildMargin); | |
| 615 negativeMarginBefore = std::max(negativeMarginBefore, -beforeChildMargin); | |
| 616 | |
| 617 if (!child->isRenderBlockFlow()) | |
| 618 return; | |
| 619 | |
| 620 RenderBlockFlow* childBlockFlow = toRenderBlockFlow(child); | |
| 621 if (childBlockFlow->childrenInline()) | |
| 622 return; | |
| 623 | |
| 624 MarginInfo childMarginInfo(childBlockFlow, childBlockFlow->borderBefore() +
childBlockFlow->paddingBefore(), childBlockFlow->borderAfter() + childBlockFlow-
>paddingAfter()); | |
| 625 if (!childMarginInfo.canCollapseMarginBeforeWithChildren()) | |
| 626 return; | |
| 627 | |
| 628 RenderBox* grandchildBox = childBlockFlow->firstChildBox(); | |
| 629 for ( ; grandchildBox; grandchildBox = grandchildBox->nextSiblingBox()) { | |
| 630 if (!grandchildBox->isFloatingOrOutOfFlowPositioned()) | |
| 631 break; | |
| 632 } | |
| 633 | |
| 634 if (!grandchildBox) | |
| 635 return; | |
| 636 | |
| 637 // Make sure to update the block margins now for the grandchild box so that
we're looking at current values. | |
| 638 if (grandchildBox->needsLayout()) { | |
| 639 grandchildBox->computeAndSetBlockDirectionMargins(this); | |
| 640 if (grandchildBox->isRenderBlock()) { | |
| 641 RenderBlock* grandchildBlock = toRenderBlock(grandchildBox); | |
| 642 grandchildBlock->setHasMarginBeforeQuirk(grandchildBox->style()->has
MarginBeforeQuirk()); | |
| 643 grandchildBlock->setHasMarginAfterQuirk(grandchildBox->style()->hasM
arginAfterQuirk()); | |
| 644 } | |
| 645 } | |
| 646 | |
| 647 // Collapse the margin of the grandchild box with our own to produce an esti
mate. | |
| 648 childBlockFlow->marginBeforeEstimateForChild(grandchildBox, positiveMarginBe
fore, negativeMarginBefore, discardMarginBefore); | |
| 649 } | |
| 650 | |
| 651 LayoutUnit RenderBlockFlow::estimateLogicalTopPosition(RenderBox* child, const M
arginInfo& marginInfo) | |
| 652 { | |
| 653 // FIXME: We need to eliminate the estimation of vertical position, because
when it's wrong we sometimes trigger a pathological | |
| 654 // relayout if there are intruding floats. | |
| 655 LayoutUnit logicalTopEstimate = logicalHeight(); | |
| 656 if (!marginInfo.canCollapseWithMarginBefore()) { | |
| 657 LayoutUnit positiveMarginBefore = 0; | |
| 658 LayoutUnit negativeMarginBefore = 0; | |
| 659 bool discardMarginBefore = false; | |
| 660 if (child->selfNeedsLayout()) { | |
| 661 // Try to do a basic estimation of how the collapse is going to go. | |
| 662 marginBeforeEstimateForChild(child, positiveMarginBefore, negativeMa
rginBefore, discardMarginBefore); | |
| 663 } else { | |
| 664 // Use the cached collapsed margin values from a previous layout. Mo
st of the time they | |
| 665 // will be right. | |
| 666 RenderBlockFlow::MarginValues marginValues = marginValuesForChild(ch
ild); | |
| 667 positiveMarginBefore = std::max(positiveMarginBefore, marginValues.p
ositiveMarginBefore()); | |
| 668 negativeMarginBefore = std::max(negativeMarginBefore, marginValues.n
egativeMarginBefore()); | |
| 669 discardMarginBefore = mustDiscardMarginBeforeForChild(child); | |
| 670 } | |
| 671 | |
| 672 // Collapse the result with our current margins. | |
| 673 if (!discardMarginBefore) | |
| 674 logicalTopEstimate += std::max(marginInfo.positiveMargin(), positive
MarginBefore) - std::max(marginInfo.negativeMargin(), negativeMarginBefore); | |
| 675 } | |
| 676 | |
| 677 return logicalTopEstimate; | |
| 678 } | |
| 679 | |
| 680 LayoutUnit RenderBlockFlow::marginOffsetForSelfCollapsingBlock() | |
| 681 { | |
| 682 // FIXME(sky): Remove | |
| 683 ASSERT(isSelfCollapsingBlock()); | |
| 684 return LayoutUnit(); | |
| 685 } | |
| 686 | |
| 687 void RenderBlockFlow::handleAfterSideOfBlock(RenderBox* lastChild, LayoutUnit be
foreSide, LayoutUnit afterSide, MarginInfo& marginInfo) | |
| 688 { | |
| 689 marginInfo.setAtAfterSideOfBlock(true); | |
| 690 | |
| 691 // If our last child was a self-collapsing block with clearance then our log
ical height is flush with the | |
| 692 // bottom edge of the float that the child clears. The correct vertical posi
tion for the margin-collapsing we want | |
| 693 // to perform now is at the child's margin-top - so adjust our height to tha
t position. | |
| 694 if (lastChild && lastChild->isRenderBlockFlow() && lastChild->isSelfCollapsi
ngBlock()) | |
| 695 setLogicalHeight(logicalHeight() - toRenderBlockFlow(lastChild)->marginO
ffsetForSelfCollapsingBlock()); | |
| 696 | |
| 697 if (marginInfo.canCollapseMarginAfterWithChildren() && !marginInfo.canCollap
seMarginAfterWithLastChild()) | |
| 698 marginInfo.setCanCollapseMarginAfterWithChildren(false); | |
| 699 | |
| 700 // If we can't collapse with children then go ahead and add in the bottom ma
rgin. | |
| 701 if (!marginInfo.discardMargin() && (!marginInfo.canCollapseWithMarginAfter()
&& !marginInfo.canCollapseWithMarginBefore())) | |
| 702 setLogicalHeight(logicalHeight() + marginInfo.margin()); | |
| 703 | |
| 704 // Now add in our bottom border/padding. | |
| 705 setLogicalHeight(logicalHeight() + afterSide); | |
| 706 | |
| 707 // Negative margins can cause our height to shrink below our minimal height
(border/padding). | |
| 708 // If this happens, ensure that the computed height is increased to the mini
mal height. | |
| 709 setLogicalHeight(std::max(logicalHeight(), beforeSide + afterSide)); | |
| 710 | |
| 711 // Update our bottom collapsed margin info. | |
| 712 setCollapsedBottomMargin(marginInfo); | |
| 713 } | |
| 714 | |
| 715 void RenderBlockFlow::setMustDiscardMarginBefore(bool value) | |
| 716 { | |
| 717 if (style()->marginBeforeCollapse() == MDISCARD) { | |
| 718 ASSERT(value); | |
| 719 return; | |
| 720 } | |
| 721 | |
| 722 if (!m_rareData && !value) | |
| 723 return; | |
| 724 | |
| 725 if (!m_rareData) | |
| 726 m_rareData = adoptPtr(new RenderBlockFlowRareData(this)); | |
| 727 | |
| 728 m_rareData->m_discardMarginBefore = value; | |
| 729 } | |
| 730 | |
| 731 void RenderBlockFlow::setMustDiscardMarginAfter(bool value) | |
| 732 { | |
| 733 if (style()->marginAfterCollapse() == MDISCARD) { | |
| 734 ASSERT(value); | |
| 735 return; | |
| 736 } | |
| 737 | |
| 738 if (!m_rareData && !value) | |
| 739 return; | |
| 740 | |
| 741 if (!m_rareData) | |
| 742 m_rareData = adoptPtr(new RenderBlockFlowRareData(this)); | |
| 743 | |
| 744 m_rareData->m_discardMarginAfter = value; | |
| 745 } | |
| 746 | |
| 747 bool RenderBlockFlow::mustDiscardMarginBefore() const | |
| 748 { | |
| 749 return style()->marginBeforeCollapse() == MDISCARD || (m_rareData && m_rareD
ata->m_discardMarginBefore); | |
| 750 } | |
| 751 | |
| 752 bool RenderBlockFlow::mustDiscardMarginAfter() const | |
| 753 { | |
| 754 return style()->marginAfterCollapse() == MDISCARD || (m_rareData && m_rareDa
ta->m_discardMarginAfter); | |
| 755 } | |
| 756 | |
| 757 bool RenderBlockFlow::mustDiscardMarginBeforeForChild(const RenderBox* child) co
nst | |
| 758 { | |
| 759 ASSERT(!child->selfNeedsLayout()); | |
| 760 return child->isRenderBlockFlow() ? toRenderBlockFlow(child)->mustDiscardMar
ginBefore() : (child->style()->marginBeforeCollapse() == MDISCARD); | |
| 761 } | |
| 762 | |
| 763 bool RenderBlockFlow::mustDiscardMarginAfterForChild(const RenderBox* child) con
st | |
| 764 { | |
| 765 ASSERT(!child->selfNeedsLayout()); | |
| 766 return child->isRenderBlockFlow() ? toRenderBlockFlow(child)->mustDiscardMar
ginAfter() : (child->style()->marginAfterCollapse() == MDISCARD); | |
| 767 } | |
| 768 | |
| 769 void RenderBlockFlow::setMaxMarginBeforeValues(LayoutUnit pos, LayoutUnit neg) | |
| 770 { | |
| 771 if (!m_rareData) { | |
| 772 if (pos == RenderBlockFlowRareData::positiveMarginBeforeDefault(this) &&
neg == RenderBlockFlowRareData::negativeMarginBeforeDefault(this)) | |
| 773 return; | |
| 774 m_rareData = adoptPtr(new RenderBlockFlowRareData(this)); | |
| 775 } | |
| 776 m_rareData->m_margins.setPositiveMarginBefore(pos); | |
| 777 m_rareData->m_margins.setNegativeMarginBefore(neg); | |
| 778 } | |
| 779 | |
| 780 void RenderBlockFlow::setMaxMarginAfterValues(LayoutUnit pos, LayoutUnit neg) | |
| 781 { | |
| 782 if (!m_rareData) { | |
| 783 if (pos == RenderBlockFlowRareData::positiveMarginAfterDefault(this) &&
neg == RenderBlockFlowRareData::negativeMarginAfterDefault(this)) | |
| 784 return; | |
| 785 m_rareData = adoptPtr(new RenderBlockFlowRareData(this)); | |
| 786 } | |
| 787 m_rareData->m_margins.setPositiveMarginAfter(pos); | |
| 788 m_rareData->m_margins.setNegativeMarginAfter(neg); | |
| 789 } | |
| 790 | |
| 791 bool RenderBlockFlow::mustSeparateMarginBeforeForChild(const RenderBox* child) c
onst | |
| 792 { | |
| 793 ASSERT(!child->selfNeedsLayout()); | |
| 794 const RenderStyle* childStyle = child->style(); | |
| 795 return childStyle->marginBeforeCollapse() == MSEPARATE; | |
| 796 } | |
| 797 | |
| 798 bool RenderBlockFlow::mustSeparateMarginAfterForChild(const RenderBox* child) co
nst | |
| 799 { | |
| 800 ASSERT(!child->selfNeedsLayout()); | |
| 801 const RenderStyle* childStyle = child->style(); | |
| 802 return childStyle->marginAfterCollapse() == MSEPARATE; | |
| 803 } | |
| 804 | |
| 805 RootInlineBox* RenderBlockFlow::createAndAppendRootInlineBox() | 205 RootInlineBox* RenderBlockFlow::createAndAppendRootInlineBox() |
| 806 { | 206 { |
| 807 RootInlineBox* rootBox = createRootInlineBox(); | 207 RootInlineBox* rootBox = createRootInlineBox(); |
| 808 m_lineBoxes.appendLineBox(rootBox); | 208 m_lineBoxes.appendLineBox(rootBox); |
| 809 | 209 |
| 810 return rootBox; | 210 return rootBox; |
| 811 } | 211 } |
| 812 | 212 |
| 813 void RenderBlockFlow::deleteLineBoxTree() | 213 void RenderBlockFlow::deleteLineBoxTree() |
| 814 { | 214 { |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1014 cb = cb->containingBlock(); | 414 cb = cb->containingBlock(); |
| 1015 } | 415 } |
| 1016 return logicalRight; | 416 return logicalRight; |
| 1017 } | 417 } |
| 1018 | 418 |
| 1019 RootInlineBox* RenderBlockFlow::createRootInlineBox() | 419 RootInlineBox* RenderBlockFlow::createRootInlineBox() |
| 1020 { | 420 { |
| 1021 return new RootInlineBox(*this); | 421 return new RootInlineBox(*this); |
| 1022 } | 422 } |
| 1023 | 423 |
| 1024 RenderBlockFlow::RenderBlockFlowRareData& RenderBlockFlow::ensureRareData() | |
| 1025 { | |
| 1026 if (m_rareData) | |
| 1027 return *m_rareData; | |
| 1028 | |
| 1029 m_rareData = adoptPtr(new RenderBlockFlowRareData(this)); | |
| 1030 return *m_rareData; | |
| 1031 } | |
| 1032 | |
| 1033 } // namespace blink | 424 } // namespace blink |
| OLD | NEW |