| 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 16 matching lines...) Expand all Loading... |
| 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 29 */ | 29 */ |
| 30 | 30 |
| 31 #include "sky/engine/config.h" | 31 #include "sky/engine/config.h" |
| 32 #include "sky/engine/core/rendering/RenderBlockFlow.h" | 32 #include "sky/engine/core/rendering/RenderBlockFlow.h" |
| 33 | 33 |
| 34 #include "sky/engine/core/frame/FrameView.h" | 34 #include "sky/engine/core/frame/FrameView.h" |
| 35 #include "sky/engine/core/frame/LocalFrame.h" | 35 #include "sky/engine/core/frame/LocalFrame.h" |
| 36 #include "sky/engine/core/frame/Settings.h" | 36 #include "sky/engine/core/frame/Settings.h" |
| 37 #include "sky/engine/core/rendering/BidiRun.h" |
| 37 #include "sky/engine/core/rendering/HitTestLocation.h" | 38 #include "sky/engine/core/rendering/HitTestLocation.h" |
| 38 #include "sky/engine/core/rendering/RenderLayer.h" | 39 #include "sky/engine/core/rendering/RenderLayer.h" |
| 39 #include "sky/engine/core/rendering/RenderText.h" | 40 #include "sky/engine/core/rendering/RenderText.h" |
| 40 #include "sky/engine/core/rendering/RenderView.h" | 41 #include "sky/engine/core/rendering/RenderView.h" |
| 41 #include "sky/engine/core/rendering/line/LineWidth.h" | 42 #include "sky/engine/core/rendering/line/LineWidth.h" |
| 42 #include "sky/engine/platform/text/BidiTextRun.h" | 43 #include "sky/engine/platform/text/BidiTextRun.h" |
| 43 | 44 |
| 44 namespace blink { | 45 namespace blink { |
| 45 | 46 |
| 46 RenderBlockFlow::RenderBlockFlow(ContainerNode* node) | 47 RenderBlockFlow::RenderBlockFlow(ContainerNode* node) |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 97 LayoutState state(*this, locationOffset(), logicalWidthChanged); | 98 LayoutState state(*this, locationOffset(), logicalWidthChanged); |
| 98 | 99 |
| 99 LayoutUnit beforeEdge = borderBefore() + paddingBefore(); | 100 LayoutUnit beforeEdge = borderBefore() + paddingBefore(); |
| 100 LayoutUnit afterEdge = borderAfter() + paddingAfter(); | 101 LayoutUnit afterEdge = borderAfter() + paddingAfter(); |
| 101 LayoutUnit previousHeight = logicalHeight(); | 102 LayoutUnit previousHeight = logicalHeight(); |
| 102 setLogicalHeight(beforeEdge); | 103 setLogicalHeight(beforeEdge); |
| 103 | 104 |
| 104 m_paintInvalidationLogicalTop = 0; | 105 m_paintInvalidationLogicalTop = 0; |
| 105 m_paintInvalidationLogicalBottom = 0; | 106 m_paintInvalidationLogicalBottom = 0; |
| 106 | 107 |
| 107 if (isRenderParagraph()) | 108 layoutChildren(relayoutChildren, layoutScope, m_paintInvalidationLogicalTop,
m_paintInvalidationLogicalBottom, beforeEdge, afterEdge); |
| 108 layoutInlineChildren(relayoutChildren, m_paintInvalidationLogicalTop, m_
paintInvalidationLogicalBottom, afterEdge); | |
| 109 else | |
| 110 layoutBlockChildren(relayoutChildren, layoutScope, beforeEdge, afterEdge
); | |
| 111 | 109 |
| 112 LayoutUnit oldClientAfterEdge = clientLogicalBottom(); | 110 LayoutUnit oldClientAfterEdge = clientLogicalBottom(); |
| 113 | 111 |
| 114 updateLogicalHeight(); | 112 updateLogicalHeight(); |
| 115 | 113 |
| 116 if (previousHeight != logicalHeight()) | 114 if (previousHeight != logicalHeight()) |
| 117 relayoutChildren = true; | 115 relayoutChildren = true; |
| 118 | 116 |
| 119 layoutPositionedObjects(relayoutChildren || isDocumentElement(), oldLeft !=
logicalLeft() ? ForcedLayoutAfterContainingBlockMoved : DefaultLayout); | 117 layoutPositionedObjects(relayoutChildren || isDocumentElement(), oldLeft !=
logicalLeft() ? ForcedLayoutAfterContainingBlockMoved : DefaultLayout); |
| 120 | 118 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 141 void RenderBlockFlow::layoutBlockChild(RenderBox* child) | 139 void RenderBlockFlow::layoutBlockChild(RenderBox* child) |
| 142 { | 140 { |
| 143 child->computeAndSetBlockDirectionMargins(this); | 141 child->computeAndSetBlockDirectionMargins(this); |
| 144 LayoutUnit marginBefore = marginBeforeForChild(child); | 142 LayoutUnit marginBefore = marginBeforeForChild(child); |
| 145 child->setY(logicalHeight() + marginBefore); | 143 child->setY(logicalHeight() + marginBefore); |
| 146 child->layoutIfNeeded(); | 144 child->layoutIfNeeded(); |
| 147 determineLogicalLeftPositionForChild(child); | 145 determineLogicalLeftPositionForChild(child); |
| 148 setLogicalHeight(logicalHeight() + marginBefore + logicalHeightForChild(chil
d) + marginAfterForChild(child)); | 146 setLogicalHeight(logicalHeight() + marginBefore + logicalHeightForChild(chil
d) + marginAfterForChild(child)); |
| 149 } | 147 } |
| 150 | 148 |
| 151 void RenderBlockFlow::layoutBlockChildren(bool relayoutChildren, SubtreeLayoutSc
ope& layoutScope, LayoutUnit beforeEdge, LayoutUnit afterEdge) | 149 void RenderBlockFlow::layoutChildren(bool relayoutChildren, SubtreeLayoutScope&
layoutScope, LayoutUnit& paintInvalidationLogicalTop, LayoutUnit& paintInvalidat
ionLogicalBottom, LayoutUnit beforeEdge, LayoutUnit afterEdge) |
| 152 { | 150 { |
| 153 dirtyForLayoutFromPercentageHeightDescendants(layoutScope); | 151 dirtyForLayoutFromPercentageHeightDescendants(layoutScope); |
| 154 | 152 |
| 155 RenderBox* next = firstChildBox(); | 153 RenderBox* next = firstChildBox(); |
| 156 RenderBox* lastNormalFlowChild = 0; | 154 RenderBox* lastNormalFlowChild = 0; |
| 157 | 155 |
| 158 while (next) { | 156 while (next) { |
| 159 RenderBox* child = next; | 157 RenderBox* child = next; |
| 160 next = child->nextSiblingBox(); | 158 next = child->nextSiblingBox(); |
| 161 | 159 |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 221 child->layer()->setStaticInlinePosition(inlinePosition); | 219 child->layer()->setStaticInlinePosition(inlinePosition); |
| 222 } | 220 } |
| 223 | 221 |
| 224 void RenderBlockFlow::addChild(RenderObject* newChild, RenderObject* beforeChild
) | 222 void RenderBlockFlow::addChild(RenderObject* newChild, RenderObject* beforeChild
) |
| 225 { | 223 { |
| 226 RenderBlock::addChild(newChild, beforeChild); | 224 RenderBlock::addChild(newChild, beforeChild); |
| 227 } | 225 } |
| 228 | 226 |
| 229 void RenderBlockFlow::invalidatePaintForOverflow() | 227 void RenderBlockFlow::invalidatePaintForOverflow() |
| 230 { | 228 { |
| 231 // FIXME: We could tighten up the left and right invalidation points if we l
et layoutInlineChildren fill them in based off the particular lines | 229 // FIXME: We could tighten up the left and right invalidation points if we l
et RenderParagraph::layoutChildren fill them in based off the particular lines |
| 232 // it had to lay out. We wouldn't need the hasOverflowClip() hack in that ca
se either. | 230 // it had to lay out. We wouldn't need the hasOverflowClip() hack in that ca
se either. |
| 233 LayoutUnit paintInvalidationLogicalLeft = logicalLeftVisualOverflow(); | 231 LayoutUnit paintInvalidationLogicalLeft = logicalLeftVisualOverflow(); |
| 234 LayoutUnit paintInvalidationLogicalRight = logicalRightVisualOverflow(); | 232 LayoutUnit paintInvalidationLogicalRight = logicalRightVisualOverflow(); |
| 235 if (hasOverflowClip()) { | 233 if (hasOverflowClip()) { |
| 236 // If we have clipped overflow, we should use layout overflow as well, s
ince visual overflow from lines didn't propagate to our block's overflow. | 234 // If we have clipped overflow, we should use layout overflow as well, s
ince visual overflow from lines didn't propagate to our block's overflow. |
| 237 // Note the old code did this as well but even for overflow:visible. The
addition of hasOverflowClip() at least tightens up the hack a bit. | 235 // Note the old code did this as well but even for overflow:visible. The
addition of hasOverflowClip() at least tightens up the hack a bit. |
| 238 // layoutInlineChildren should be patched to compute the entire paint in
validation rect. | 236 // RenderParagraph::layoutChildren should be patched to compute the enti
re paint invalidation rect. |
| 239 paintInvalidationLogicalLeft = std::min(paintInvalidationLogicalLeft, lo
gicalLeftLayoutOverflow()); | 237 paintInvalidationLogicalLeft = std::min(paintInvalidationLogicalLeft, lo
gicalLeftLayoutOverflow()); |
| 240 paintInvalidationLogicalRight = std::max(paintInvalidationLogicalRight,
logicalRightLayoutOverflow()); | 238 paintInvalidationLogicalRight = std::max(paintInvalidationLogicalRight,
logicalRightLayoutOverflow()); |
| 241 } | 239 } |
| 242 | 240 |
| 243 LayoutRect paintInvalidationRect = LayoutRect(paintInvalidationLogicalLeft,
m_paintInvalidationLogicalTop, paintInvalidationLogicalRight - paintInvalidation
LogicalLeft, m_paintInvalidationLogicalBottom - m_paintInvalidationLogicalTop); | 241 LayoutRect paintInvalidationRect = LayoutRect(paintInvalidationLogicalLeft,
m_paintInvalidationLogicalTop, paintInvalidationLogicalRight - paintInvalidation
LogicalLeft, m_paintInvalidationLogicalBottom - m_paintInvalidationLogicalTop); |
| 244 | 242 |
| 245 if (hasOverflowClip()) { | 243 if (hasOverflowClip()) { |
| 246 // Adjust the paint invalidation rect for scroll offset | 244 // Adjust the paint invalidation rect for scroll offset |
| 247 paintInvalidationRect.move(-scrolledContentOffset()); | 245 paintInvalidationRect.move(-scrolledContentOffset()); |
| 248 | 246 |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 343 cb = cb->containingBlock(); | 341 cb = cb->containingBlock(); |
| 344 } | 342 } |
| 345 return logicalRight; | 343 return logicalRight; |
| 346 } | 344 } |
| 347 | 345 |
| 348 RootInlineBox* RenderBlockFlow::createRootInlineBox() | 346 RootInlineBox* RenderBlockFlow::createRootInlineBox() |
| 349 { | 347 { |
| 350 return new RootInlineBox(*this); | 348 return new RootInlineBox(*this); |
| 351 } | 349 } |
| 352 | 350 |
| 351 static void updateLogicalWidthForLeftAlignedBlock(bool isLeftToRightDirection, B
idiRun* trailingSpaceRun, float& logicalLeft, float& totalLogicalWidth, float av
ailableLogicalWidth) |
| 352 { |
| 353 // The direction of the block should determine what happens with wide lines. |
| 354 // In particular with RTL blocks, wide lines should still spill out to the l
eft. |
| 355 if (isLeftToRightDirection) { |
| 356 if (totalLogicalWidth > availableLogicalWidth && trailingSpaceRun) |
| 357 trailingSpaceRun->m_box->setLogicalWidth(std::max<float>(0, trailing
SpaceRun->m_box->logicalWidth() - totalLogicalWidth + availableLogicalWidth)); |
| 358 return; |
| 359 } |
| 360 |
| 361 if (trailingSpaceRun) |
| 362 trailingSpaceRun->m_box->setLogicalWidth(0); |
| 363 else if (totalLogicalWidth > availableLogicalWidth) |
| 364 logicalLeft -= (totalLogicalWidth - availableLogicalWidth); |
| 365 } |
| 366 |
| 367 static void updateLogicalWidthForRightAlignedBlock(bool isLeftToRightDirection,
BidiRun* trailingSpaceRun, float& logicalLeft, float& totalLogicalWidth, float a
vailableLogicalWidth) |
| 368 { |
| 369 // Wide lines spill out of the block based off direction. |
| 370 // So even if text-align is right, if direction is LTR, wide lines should ov
erflow out of the right |
| 371 // side of the block. |
| 372 if (isLeftToRightDirection) { |
| 373 if (trailingSpaceRun) { |
| 374 totalLogicalWidth -= trailingSpaceRun->m_box->logicalWidth(); |
| 375 trailingSpaceRun->m_box->setLogicalWidth(0); |
| 376 } |
| 377 if (totalLogicalWidth < availableLogicalWidth) |
| 378 logicalLeft += availableLogicalWidth - totalLogicalWidth; |
| 379 return; |
| 380 } |
| 381 |
| 382 if (totalLogicalWidth > availableLogicalWidth && trailingSpaceRun) { |
| 383 trailingSpaceRun->m_box->setLogicalWidth(std::max<float>(0, trailingSpac
eRun->m_box->logicalWidth() - totalLogicalWidth + availableLogicalWidth)); |
| 384 totalLogicalWidth -= trailingSpaceRun->m_box->logicalWidth(); |
| 385 } else |
| 386 logicalLeft += availableLogicalWidth - totalLogicalWidth; |
| 387 } |
| 388 |
| 389 static void updateLogicalWidthForCenterAlignedBlock(bool isLeftToRightDirection,
BidiRun* trailingSpaceRun, float& logicalLeft, float& totalLogicalWidth, float
availableLogicalWidth) |
| 390 { |
| 391 float trailingSpaceWidth = 0; |
| 392 if (trailingSpaceRun) { |
| 393 totalLogicalWidth -= trailingSpaceRun->m_box->logicalWidth(); |
| 394 trailingSpaceWidth = std::min(trailingSpaceRun->m_box->logicalWidth(), (
availableLogicalWidth - totalLogicalWidth + 1) / 2); |
| 395 trailingSpaceRun->m_box->setLogicalWidth(std::max<float>(0, trailingSpac
eWidth)); |
| 396 } |
| 397 if (isLeftToRightDirection) |
| 398 logicalLeft += std::max<float>((availableLogicalWidth - totalLogicalWidt
h) / 2, 0); |
| 399 else |
| 400 logicalLeft += totalLogicalWidth > availableLogicalWidth ? (availableLog
icalWidth - totalLogicalWidth) : (availableLogicalWidth - totalLogicalWidth) / 2
- trailingSpaceWidth; |
| 401 } |
| 402 |
| 403 void RenderBlockFlow::updateLogicalWidthForAlignment(const ETextAlign& textAlign
, const RootInlineBox* rootInlineBox, BidiRun* trailingSpaceRun, float& logicalL
eft, float& totalLogicalWidth, float& availableLogicalWidth, unsigned expansionO
pportunityCount) |
| 404 { |
| 405 TextDirection direction; |
| 406 if (rootInlineBox && rootInlineBox->renderer().style()->unicodeBidi() == Pla
intext) |
| 407 direction = rootInlineBox->direction(); |
| 408 else |
| 409 direction = style()->direction(); |
| 410 |
| 411 // Armed with the total width of the line (without justification), |
| 412 // we now examine our text-align property in order to determine where to pos
ition the |
| 413 // objects horizontally. The total width of the line can be increased if we
end up |
| 414 // justifying text. |
| 415 switch (textAlign) { |
| 416 case LEFT: |
| 417 updateLogicalWidthForLeftAlignedBlock(style()->isLeftToRightDirection(),
trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth); |
| 418 break; |
| 419 case RIGHT: |
| 420 updateLogicalWidthForRightAlignedBlock(style()->isLeftToRightDirection()
, trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth); |
| 421 break; |
| 422 case CENTER: |
| 423 updateLogicalWidthForCenterAlignedBlock(style()->isLeftToRightDirection(
), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth); |
| 424 break; |
| 425 case JUSTIFY: |
| 426 adjustInlineDirectionLineBounds(expansionOpportunityCount, logicalLeft,
availableLogicalWidth); |
| 427 if (expansionOpportunityCount) { |
| 428 if (trailingSpaceRun) { |
| 429 totalLogicalWidth -= trailingSpaceRun->m_box->logicalWidth(); |
| 430 trailingSpaceRun->m_box->setLogicalWidth(0); |
| 431 } |
| 432 break; |
| 433 } |
| 434 // Fall through |
| 435 case TASTART: |
| 436 if (direction == LTR) |
| 437 updateLogicalWidthForLeftAlignedBlock(style()->isLeftToRightDirectio
n(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth); |
| 438 else |
| 439 updateLogicalWidthForRightAlignedBlock(style()->isLeftToRightDirecti
on(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth); |
| 440 break; |
| 441 case TAEND: |
| 442 if (direction == LTR) |
| 443 updateLogicalWidthForRightAlignedBlock(style()->isLeftToRightDirecti
on(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth); |
| 444 else |
| 445 updateLogicalWidthForLeftAlignedBlock(style()->isLeftToRightDirectio
n(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth); |
| 446 break; |
| 447 } |
| 448 } |
| 449 |
| 450 LayoutUnit RenderBlockFlow::startAlignedOffsetForLine(bool firstLine) |
| 451 { |
| 452 ETextAlign textAlign = style()->textAlign(); |
| 453 |
| 454 if (textAlign == TASTART) // FIXME: Handle TAEND here |
| 455 return startOffsetForLine(firstLine); |
| 456 |
| 457 // updateLogicalWidthForAlignment() handles the direction of the block so no
need to consider it here |
| 458 float totalLogicalWidth = 0; |
| 459 float logicalLeft = logicalLeftOffsetForLine(false).toFloat(); |
| 460 float availableLogicalWidth = logicalRightOffsetForLine(false) - logicalLeft
; |
| 461 updateLogicalWidthForAlignment(textAlign, 0, 0, logicalLeft, totalLogicalWid
th, availableLogicalWidth, 0); |
| 462 |
| 463 if (!style()->isLeftToRightDirection()) |
| 464 return logicalWidth() - logicalLeft; |
| 465 return logicalLeft; |
| 466 } |
| 467 |
| 353 } // namespace blink | 468 } // namespace blink |
| OLD | NEW |