| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "sky/engine/config.h" | 5 #include "sky/engine/config.h" |
| 6 #include "sky/engine/core/rendering/RenderParagraph.h" | 6 #include "sky/engine/core/rendering/RenderParagraph.h" |
| 7 | 7 |
| 8 #include "sky/engine/core/rendering/BidiRunForLine.h" | 8 #include "sky/engine/core/rendering/BidiRunForLine.h" |
| 9 #include "sky/engine/core/rendering/InlineIterator.h" | 9 #include "sky/engine/core/rendering/InlineIterator.h" |
| 10 #include "sky/engine/core/rendering/RenderLayer.h" | 10 #include "sky/engine/core/rendering/RenderLayer.h" |
| 11 #include "sky/engine/core/rendering/RenderObjectInlines.h" | 11 #include "sky/engine/core/rendering/RenderObjectInlines.h" |
| 12 #include "sky/engine/core/rendering/RenderView.h" | 12 #include "sky/engine/core/rendering/RenderView.h" |
| 13 #include "sky/engine/core/rendering/TextRunConstructor.h" | 13 #include "sky/engine/core/rendering/TextRunConstructor.h" |
| 14 #include "sky/engine/core/rendering/TrailingFloatsRootInlineBox.h" | |
| 15 #include "sky/engine/core/rendering/VerticalPositionCache.h" | 14 #include "sky/engine/core/rendering/VerticalPositionCache.h" |
| 16 #include "sky/engine/core/rendering/line/BreakingContextInlineHeaders.h" | 15 #include "sky/engine/core/rendering/line/BreakingContextInlineHeaders.h" |
| 17 #include "sky/engine/core/rendering/line/LineLayoutState.h" | 16 #include "sky/engine/core/rendering/line/LineLayoutState.h" |
| 18 #include "sky/engine/core/rendering/line/LineWidth.h" | 17 #include "sky/engine/core/rendering/line/LineWidth.h" |
| 19 #include "sky/engine/core/rendering/line/RenderTextInfo.h" | 18 #include "sky/engine/core/rendering/line/RenderTextInfo.h" |
| 20 #include "sky/engine/core/rendering/line/WordMeasurement.h" | 19 #include "sky/engine/core/rendering/line/WordMeasurement.h" |
| 21 #include "sky/engine/platform/fonts/Character.h" | 20 #include "sky/engine/platform/fonts/Character.h" |
| 22 #include "sky/engine/platform/text/BidiResolver.h" | 21 #include "sky/engine/platform/text/BidiResolver.h" |
| 23 #include "sky/engine/wtf/RefCountedLeakCounter.h" | 22 #include "sky/engine/wtf/RefCountedLeakCounter.h" |
| 24 #include "sky/engine/wtf/StdLibExtras.h" | 23 #include "sky/engine/wtf/StdLibExtras.h" |
| 25 #include "sky/engine/wtf/Vector.h" | 24 #include "sky/engine/wtf/Vector.h" |
| 26 #include "sky/engine/wtf/unicode/CharacterNames.h" | 25 #include "sky/engine/wtf/unicode/CharacterNames.h" |
| 27 | 26 |
| 28 | 27 |
| 29 namespace blink { | 28 namespace blink { |
| 30 | 29 |
| 31 using namespace WTF::Unicode; | 30 using namespace WTF::Unicode; |
| 32 | 31 |
| 33 RenderParagraph::RenderParagraph(ContainerNode* node) | 32 RenderParagraph::RenderParagraph(ContainerNode* node) |
| 34 : RenderBlockFlow(node) | 33 : RenderBlock(node) |
| 35 { | 34 { |
| 36 } | 35 } |
| 37 | 36 |
| 38 RenderParagraph::~RenderParagraph() | 37 RenderParagraph::~RenderParagraph() |
| 39 { | 38 { |
| 40 } | 39 } |
| 41 | 40 |
| 42 const char* RenderParagraph::renderName() const | 41 const char* RenderParagraph::renderName() const |
| 43 { | 42 { |
| 44 if (isAnonymous()) | 43 if (isAnonymous()) |
| 45 return "RenderParagraph (anonymous)"; | 44 return "RenderParagraph (anonymous)"; |
| 46 return "RenderParagraph"; | 45 return "RenderParagraph"; |
| 47 } | 46 } |
| 48 | 47 |
| 49 RenderParagraph* RenderParagraph::createAnonymous(Document& document) | 48 RenderParagraph* RenderParagraph::createAnonymous(Document& document) |
| 50 { | 49 { |
| 51 RenderParagraph* renderer = new RenderParagraph(0); | 50 RenderParagraph* renderer = new RenderParagraph(0); |
| 52 renderer->setDocumentForAnonymous(&document); | 51 renderer->setDocumentForAnonymous(&document); |
| 53 return renderer; | 52 return renderer; |
| 54 } | 53 } |
| 55 | 54 |
| 55 LayoutUnit RenderParagraph::logicalLeftSelectionOffset(RenderBlock* rootBlock, L
ayoutUnit position) |
| 56 { |
| 57 LayoutUnit logicalLeft = logicalLeftOffsetForLine(false); |
| 58 if (logicalLeft == logicalLeftOffsetForContent()) |
| 59 return RenderBlock::logicalLeftSelectionOffset(rootBlock, position); |
| 60 |
| 61 RenderBlock* cb = this; |
| 62 while (cb != rootBlock) { |
| 63 logicalLeft += cb->logicalLeft(); |
| 64 cb = cb->containingBlock(); |
| 65 } |
| 66 return logicalLeft; |
| 67 } |
| 68 |
| 69 LayoutUnit RenderParagraph::logicalRightSelectionOffset(RenderBlock* rootBlock,
LayoutUnit position) |
| 70 { |
| 71 LayoutUnit logicalRight = logicalRightOffsetForLine(false); |
| 72 if (logicalRight == logicalRightOffsetForContent()) |
| 73 return RenderBlock::logicalRightSelectionOffset(rootBlock, position); |
| 74 |
| 75 RenderBlock* cb = this; |
| 76 while (cb != rootBlock) { |
| 77 logicalRight += cb->logicalLeft(); |
| 78 cb = cb->containingBlock(); |
| 79 } |
| 80 return logicalRight; |
| 81 } |
| 82 |
| 56 RootInlineBox* RenderParagraph::lineAtIndex(int i) const | 83 RootInlineBox* RenderParagraph::lineAtIndex(int i) const |
| 57 { | 84 { |
| 58 ASSERT(i >= 0); | 85 ASSERT(i >= 0); |
| 59 | 86 |
| 60 for (RootInlineBox* box = firstRootBox(); box; box = box->nextRootBox()) { | 87 for (RootInlineBox* box = firstRootBox(); box; box = box->nextRootBox()) { |
| 61 if (!i--) | 88 if (!i--) |
| 62 return box; | 89 return box; |
| 63 } | 90 } |
| 64 | 91 |
| 65 return 0; | 92 return 0; |
| 66 } | 93 } |
| 67 | 94 |
| 68 int RenderParagraph::lineCount(const RootInlineBox* stopRootInlineBox, bool* fou
nd) const | 95 int RenderParagraph::lineCount(const RootInlineBox* stopRootInlineBox, bool* fou
nd) const |
| 69 { | 96 { |
| 70 int count = 0; | 97 int count = 0; |
| 71 for (RootInlineBox* box = firstRootBox(); box; box = box->nextRootBox()) { | 98 for (RootInlineBox* box = firstRootBox(); box; box = box->nextRootBox()) { |
| 72 count++; | 99 count++; |
| 73 if (box == stopRootInlineBox) { | 100 if (box == stopRootInlineBox) { |
| 74 if (found) | 101 if (found) |
| 75 *found = true; | 102 *found = true; |
| 76 break; | 103 break; |
| 77 } | 104 } |
| 78 } | 105 } |
| 79 | 106 |
| 80 return count; | 107 return count; |
| 81 } | 108 } |
| 82 | 109 |
| 110 void RenderParagraph::deleteLineBoxTree() |
| 111 { |
| 112 m_lineBoxes.deleteLineBoxTree(); |
| 113 } |
| 114 |
| 83 GapRects RenderParagraph::inlineSelectionGaps(RenderBlock* rootBlock, const Layo
utPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock, | 115 GapRects RenderParagraph::inlineSelectionGaps(RenderBlock* rootBlock, const Layo
utPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock, |
| 84 LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLog
icalRight, const PaintInfo* paintInfo) | 116 LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLog
icalRight, const PaintInfo* paintInfo) |
| 85 { | 117 { |
| 86 GapRects result; | 118 GapRects result; |
| 87 | 119 |
| 88 bool containsStart = selectionState() == SelectionStart || selectionState()
== SelectionBoth; | 120 bool containsStart = selectionState() == SelectionStart || selectionState()
== SelectionBoth; |
| 89 | 121 |
| 90 if (!firstLineBox()) { | 122 if (!firstLineBox()) { |
| 91 if (containsStart) { | 123 if (containsStart) { |
| 92 // Go ahead and update our lastLogicalTop to be the bottom of the bl
ock. <hr>s or empty blocks with height can trip this | 124 // Go ahead and update our lastLogicalTop to be the bottom of the bl
ock. <hr>s or empty blocks with height can trip this |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 204 afterLowest = lowestDirtyLine; | 236 afterLowest = lowestDirtyLine; |
| 205 lowestDirtyLine = lowestDirtyLine->prevRootBox(); | 237 lowestDirtyLine = lowestDirtyLine->prevRootBox(); |
| 206 } | 238 } |
| 207 | 239 |
| 208 while (afterLowest && afterLowest != highest && (afterLowest->lineBottomWith
Leading() >= logicalTop || afterLowest->lineBottomWithLeading() < 0)) { | 240 while (afterLowest && afterLowest != highest && (afterLowest->lineBottomWith
Leading() >= logicalTop || afterLowest->lineBottomWithLeading() < 0)) { |
| 209 afterLowest->markDirty(); | 241 afterLowest->markDirty(); |
| 210 afterLowest = afterLowest->prevRootBox(); | 242 afterLowest = afterLowest->prevRootBox(); |
| 211 } | 243 } |
| 212 } | 244 } |
| 213 | 245 |
| 214 static inline InlineBox* createInlineBoxForRenderer(RenderObject* obj, bool isRo
otLineBox, bool isOnlyRun = false) | 246 static void updateLogicalWidthForLeftAlignedBlock(bool isLeftToRightDirection, B
idiRun* trailingSpaceRun, float& logicalLeft, float& totalLogicalWidth, float av
ailableLogicalWidth) |
| 247 { |
| 248 // The direction of the block should determine what happens with wide lines. |
| 249 // In particular with RTL blocks, wide lines should still spill out to the l
eft. |
| 250 if (isLeftToRightDirection) { |
| 251 if (totalLogicalWidth > availableLogicalWidth && trailingSpaceRun) |
| 252 trailingSpaceRun->m_box->setLogicalWidth(std::max<float>(0, trailing
SpaceRun->m_box->logicalWidth() - totalLogicalWidth + availableLogicalWidth)); |
| 253 return; |
| 254 } |
| 255 |
| 256 if (trailingSpaceRun) |
| 257 trailingSpaceRun->m_box->setLogicalWidth(0); |
| 258 else if (totalLogicalWidth > availableLogicalWidth) |
| 259 logicalLeft -= (totalLogicalWidth - availableLogicalWidth); |
| 260 } |
| 261 |
| 262 static void updateLogicalWidthForRightAlignedBlock(bool isLeftToRightDirection,
BidiRun* trailingSpaceRun, float& logicalLeft, float& totalLogicalWidth, float a
vailableLogicalWidth) |
| 263 { |
| 264 // Wide lines spill out of the block based off direction. |
| 265 // So even if text-align is right, if direction is LTR, wide lines should ov
erflow out of the right |
| 266 // side of the block. |
| 267 if (isLeftToRightDirection) { |
| 268 if (trailingSpaceRun) { |
| 269 totalLogicalWidth -= trailingSpaceRun->m_box->logicalWidth(); |
| 270 trailingSpaceRun->m_box->setLogicalWidth(0); |
| 271 } |
| 272 if (totalLogicalWidth < availableLogicalWidth) |
| 273 logicalLeft += availableLogicalWidth - totalLogicalWidth; |
| 274 return; |
| 275 } |
| 276 |
| 277 if (totalLogicalWidth > availableLogicalWidth && trailingSpaceRun) { |
| 278 trailingSpaceRun->m_box->setLogicalWidth(std::max<float>(0, trailingSpac
eRun->m_box->logicalWidth() - totalLogicalWidth + availableLogicalWidth)); |
| 279 totalLogicalWidth -= trailingSpaceRun->m_box->logicalWidth(); |
| 280 } else |
| 281 logicalLeft += availableLogicalWidth - totalLogicalWidth; |
| 282 } |
| 283 |
| 284 static void updateLogicalWidthForCenterAlignedBlock(bool isLeftToRightDirection,
BidiRun* trailingSpaceRun, float& logicalLeft, float& totalLogicalWidth, float
availableLogicalWidth) |
| 285 { |
| 286 float trailingSpaceWidth = 0; |
| 287 if (trailingSpaceRun) { |
| 288 totalLogicalWidth -= trailingSpaceRun->m_box->logicalWidth(); |
| 289 trailingSpaceWidth = std::min(trailingSpaceRun->m_box->logicalWidth(), (
availableLogicalWidth - totalLogicalWidth + 1) / 2); |
| 290 trailingSpaceRun->m_box->setLogicalWidth(std::max<float>(0, trailingSpac
eWidth)); |
| 291 } |
| 292 if (isLeftToRightDirection) |
| 293 logicalLeft += std::max<float>((availableLogicalWidth - totalLogicalWidt
h) / 2, 0); |
| 294 else |
| 295 logicalLeft += totalLogicalWidth > availableLogicalWidth ? (availableLog
icalWidth - totalLogicalWidth) : (availableLogicalWidth - totalLogicalWidth) / 2
- trailingSpaceWidth; |
| 296 } |
| 297 |
| 298 void RenderParagraph::updateLogicalWidthForAlignment(const ETextAlign& textAlign
, const RootInlineBox* rootInlineBox, BidiRun* trailingSpaceRun, float& logicalL
eft, float& totalLogicalWidth, float& availableLogicalWidth, unsigned expansionO
pportunityCount) |
| 299 { |
| 300 TextDirection direction; |
| 301 if (rootInlineBox && rootInlineBox->renderer().style()->unicodeBidi() == Pla
intext) |
| 302 direction = rootInlineBox->direction(); |
| 303 else |
| 304 direction = style()->direction(); |
| 305 |
| 306 // Armed with the total width of the line (without justification), |
| 307 // we now examine our text-align property in order to determine where to pos
ition the |
| 308 // objects horizontally. The total width of the line can be increased if we
end up |
| 309 // justifying text. |
| 310 switch (textAlign) { |
| 311 case LEFT: |
| 312 updateLogicalWidthForLeftAlignedBlock(style()->isLeftToRightDirection(),
trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth); |
| 313 break; |
| 314 case RIGHT: |
| 315 updateLogicalWidthForRightAlignedBlock(style()->isLeftToRightDirection()
, trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth); |
| 316 break; |
| 317 case CENTER: |
| 318 updateLogicalWidthForCenterAlignedBlock(style()->isLeftToRightDirection(
), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth); |
| 319 break; |
| 320 case JUSTIFY: |
| 321 adjustInlineDirectionLineBounds(expansionOpportunityCount, logicalLeft,
availableLogicalWidth); |
| 322 if (expansionOpportunityCount) { |
| 323 if (trailingSpaceRun) { |
| 324 totalLogicalWidth -= trailingSpaceRun->m_box->logicalWidth(); |
| 325 trailingSpaceRun->m_box->setLogicalWidth(0); |
| 326 } |
| 327 break; |
| 328 } |
| 329 // Fall through |
| 330 case TASTART: |
| 331 if (direction == LTR) |
| 332 updateLogicalWidthForLeftAlignedBlock(style()->isLeftToRightDirectio
n(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth); |
| 333 else |
| 334 updateLogicalWidthForRightAlignedBlock(style()->isLeftToRightDirecti
on(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth); |
| 335 break; |
| 336 case TAEND: |
| 337 if (direction == LTR) |
| 338 updateLogicalWidthForRightAlignedBlock(style()->isLeftToRightDirecti
on(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth); |
| 339 else |
| 340 updateLogicalWidthForLeftAlignedBlock(style()->isLeftToRightDirectio
n(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth); |
| 341 break; |
| 342 } |
| 343 } |
| 344 |
| 345 RootInlineBox* RenderParagraph::createAndAppendRootInlineBox() |
| 346 { |
| 347 RootInlineBox* rootBox = createRootInlineBox(); |
| 348 m_lineBoxes.appendLineBox(rootBox); |
| 349 return rootBox; |
| 350 } |
| 351 |
| 352 RootInlineBox* RenderParagraph::createRootInlineBox() |
| 353 { |
| 354 return new RootInlineBox(*this); |
| 355 } |
| 356 |
| 357 InlineBox* RenderParagraph::createInlineBoxForRenderer(RenderObject* obj, bool i
sRootLineBox, bool isOnlyRun) |
| 215 { | 358 { |
| 216 if (isRootLineBox) | 359 if (isRootLineBox) |
| 217 return toRenderBlockFlow(obj)->createAndAppendRootInlineBox(); | 360 return toRenderParagraph(obj)->createAndAppendRootInlineBox(); |
| 218 | 361 |
| 219 if (obj->isText()) { | 362 if (obj->isText()) { |
| 220 InlineTextBox* textBox = toRenderText(obj)->createInlineTextBox(); | 363 InlineTextBox* textBox = toRenderText(obj)->createInlineTextBox(); |
| 221 // We only treat a box as text for a <br> if we are on a line by ourself
or in strict mode | 364 // We only treat a box as text for a <br> if we are on a line by ourself
or in strict mode |
| 222 // (Note the use of strict mode. In "almost strict" mode, we don't trea
t the box for <br> as text.) | 365 // (Note the use of strict mode. In "almost strict" mode, we don't trea
t the box for <br> as text.) |
| 223 return textBox; | 366 return textBox; |
| 224 } | 367 } |
| 225 | 368 |
| 226 if (obj->isBox()) | 369 if (obj->isBox()) |
| 227 return toRenderBox(obj)->createInlineBox(); | 370 return toRenderBox(obj)->createInlineBox(); |
| (...skipping 549 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 777 | 920 |
| 778 WordMeasurements wordMeasurements; | 921 WordMeasurements wordMeasurements; |
| 779 endOfLine = lineBreaker.nextLineBreak(resolver, layoutState.lineInfo(),
renderTextInfo, | 922 endOfLine = lineBreaker.nextLineBreak(resolver, layoutState.lineInfo(),
renderTextInfo, |
| 780 lastFloatFromPreviousLine, wordMeasurements); | 923 lastFloatFromPreviousLine, wordMeasurements); |
| 781 renderTextInfo.m_lineBreakIterator.resetPriorContext(); | 924 renderTextInfo.m_lineBreakIterator.resetPriorContext(); |
| 782 if (resolver.position().atEnd()) { | 925 if (resolver.position().atEnd()) { |
| 783 // FIXME: We shouldn't be creating any runs in nextLineBreak to begi
n with! | 926 // FIXME: We shouldn't be creating any runs in nextLineBreak to begi
n with! |
| 784 // Once BidiRunList is separated from BidiResolver this will not be
needed. | 927 // Once BidiRunList is separated from BidiResolver this will not be
needed. |
| 785 resolver.runs().deleteRuns(); | 928 resolver.runs().deleteRuns(); |
| 786 resolver.markCurrentRunEmpty(); // FIXME: This can probably be repla
ced by an ASSERT (or just removed). | 929 resolver.markCurrentRunEmpty(); // FIXME: This can probably be repla
ced by an ASSERT (or just removed). |
| 787 layoutState.setCheckForFloatsFromLastLine(true); | |
| 788 resolver.setPosition(InlineIterator(resolver.position().root(), 0, 0
), 0); | 930 resolver.setPosition(InlineIterator(resolver.position().root(), 0, 0
), 0); |
| 789 break; | 931 break; |
| 790 } | 932 } |
| 791 | 933 |
| 792 ASSERT(endOfLine != resolver.position()); | 934 ASSERT(endOfLine != resolver.position()); |
| 793 | 935 |
| 794 // This is a short-cut for empty lines. | 936 // This is a short-cut for empty lines. |
| 795 if (layoutState.lineInfo().isEmpty()) { | 937 if (layoutState.lineInfo().isEmpty()) { |
| 796 if (lastRootBox()) | 938 if (lastRootBox()) |
| 797 lastRootBox()->setLineBreakInfo(endOfLine.object(), endOfLine.of
fset(), resolver.status()); | 939 lastRootBox()->setLineBreakInfo(endOfLine.object(), endOfLine.of
fset(), resolver.status()); |
| (...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1235 const FontMetrics& fontMetrics = firstLineStyle()->fontMetrics(); | 1377 const FontMetrics& fontMetrics = firstLineStyle()->fontMetrics(); |
| 1236 return fontMetrics.ascent() | 1378 return fontMetrics.ascent() |
| 1237 + (lineHeight(true, lineDirection, PositionOfInteriorLineBoxes) - f
ontMetrics.height()) / 2 | 1379 + (lineHeight(true, lineDirection, PositionOfInteriorLineBoxes) - f
ontMetrics.height()) / 2 |
| 1238 + (lineDirection == HorizontalLine ? borderTop() + paddingTop() : b
orderRight() + paddingRight()); | 1380 + (lineDirection == HorizontalLine ? borderTop() + paddingTop() : b
orderRight() + paddingRight()); |
| 1239 } | 1381 } |
| 1240 if (lastLineBox()) | 1382 if (lastLineBox()) |
| 1241 return lastLineBox()->logicalTop() + style(lastLineBox() == firstLineBox
())->fontMetrics().ascent(lastRootBox()->baselineType()); | 1383 return lastLineBox()->logicalTop() + style(lastLineBox() == firstLineBox
())->fontMetrics().ascent(lastRootBox()->baselineType()); |
| 1242 return -1; | 1384 return -1; |
| 1243 } | 1385 } |
| 1244 | 1386 |
| 1387 void RenderParagraph::layout() |
| 1388 { |
| 1389 ASSERT(needsLayout()); |
| 1390 ASSERT(isInlineBlock() || !isInline()); |
| 1391 |
| 1392 if (simplifiedLayout()) |
| 1393 return; |
| 1394 |
| 1395 SubtreeLayoutScope layoutScope(*this); |
| 1396 |
| 1397 LayoutUnit oldLeft = logicalLeft(); |
| 1398 bool logicalWidthChanged = updateLogicalWidthAndColumnWidth(); |
| 1399 bool relayoutChildren = logicalWidthChanged; |
| 1400 |
| 1401 LayoutUnit beforeEdge = borderBefore() + paddingBefore(); |
| 1402 LayoutUnit afterEdge = borderAfter() + paddingAfter(); |
| 1403 LayoutUnit previousHeight = logicalHeight(); |
| 1404 setLogicalHeight(beforeEdge); |
| 1405 |
| 1406 layoutChildren(relayoutChildren, layoutScope, beforeEdge, afterEdge); |
| 1407 |
| 1408 LayoutUnit oldClientAfterEdge = clientLogicalBottom(); |
| 1409 |
| 1410 updateLogicalHeight(); |
| 1411 |
| 1412 if (previousHeight != logicalHeight()) |
| 1413 relayoutChildren = true; |
| 1414 |
| 1415 layoutPositionedObjects(relayoutChildren, oldLeft != logicalLeft() ? ForcedL
ayoutAfterContainingBlockMoved : DefaultLayout); |
| 1416 |
| 1417 // Add overflow from children (unless we're multi-column, since in that case
all our child overflow is clipped anyway). |
| 1418 computeOverflow(oldClientAfterEdge); |
| 1419 |
| 1420 updateLayerTransformAfterLayout(); |
| 1421 |
| 1422 clearNeedsLayout(); |
| 1423 } |
| 1424 |
| 1245 void RenderParagraph::layoutChildren(bool relayoutChildren, SubtreeLayoutScope&
layoutScope, LayoutUnit beforeEdge, LayoutUnit afterEdge) | 1425 void RenderParagraph::layoutChildren(bool relayoutChildren, SubtreeLayoutScope&
layoutScope, LayoutUnit beforeEdge, LayoutUnit afterEdge) |
| 1246 { | 1426 { |
| 1247 // Figure out if we should clear out our line boxes. | 1427 // Figure out if we should clear out our line boxes. |
| 1248 // FIXME: Handle resize eventually! | 1428 // FIXME: Handle resize eventually! |
| 1249 bool isFullLayout = !firstLineBox() || selfNeedsLayout() || relayoutChildren
; | 1429 bool isFullLayout = !firstLineBox() || selfNeedsLayout() || relayoutChildren
; |
| 1250 LineLayoutState layoutState(isFullLayout); | 1430 LineLayoutState layoutState(isFullLayout); |
| 1251 | 1431 |
| 1252 if (isFullLayout) | 1432 if (isFullLayout) |
| 1253 lineBoxes()->deleteLineBoxes(); | 1433 lineBoxes()->deleteLineBoxes(); |
| 1254 | 1434 |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1320 | 1500 |
| 1321 if (!firstLineBox() && hasLineIfEmpty()) | 1501 if (!firstLineBox() && hasLineIfEmpty()) |
| 1322 setLogicalHeight(logicalHeight() + lineHeight(true, HorizontalLine, Posi
tionOfInteriorLineBoxes)); | 1502 setLogicalHeight(logicalHeight() + lineHeight(true, HorizontalLine, Posi
tionOfInteriorLineBoxes)); |
| 1323 | 1503 |
| 1324 // See if we have any lines that spill out of our block. If we do, then we
will possibly need to | 1504 // See if we have any lines that spill out of our block. If we do, then we
will possibly need to |
| 1325 // truncate text. | 1505 // truncate text. |
| 1326 if (hasTextOverflow) | 1506 if (hasTextOverflow) |
| 1327 checkLinesForTextOverflow(); | 1507 checkLinesForTextOverflow(); |
| 1328 } | 1508 } |
| 1329 | 1509 |
| 1330 void RenderParagraph::checkFloatsInCleanLine(RootInlineBox* line, Vector<FloatWi
thRect>& floats, size_t& floatIndex, bool& encounteredNewFloat, bool& dirtiedByF
loat) | |
| 1331 { | |
| 1332 Vector<RenderBox*>* cleanLineFloats = line->floatsPtr(); | |
| 1333 if (!cleanLineFloats) | |
| 1334 return; | |
| 1335 | |
| 1336 Vector<RenderBox*>::iterator end = cleanLineFloats->end(); | |
| 1337 for (Vector<RenderBox*>::iterator it = cleanLineFloats->begin(); it != end;
++it) { | |
| 1338 RenderBox* floatingBox = *it; | |
| 1339 floatingBox->layoutIfNeeded(); | |
| 1340 LayoutSize newSize(floatingBox->width() + floatingBox->marginWidth(), fl
oatingBox->height() + floatingBox->marginHeight()); | |
| 1341 if (floats[floatIndex].object != floatingBox) { | |
| 1342 encounteredNewFloat = true; | |
| 1343 return; | |
| 1344 } | |
| 1345 | |
| 1346 if (floats[floatIndex].rect.size() != newSize) { | |
| 1347 LayoutUnit floatTop = floats[floatIndex].rect.y(); | |
| 1348 LayoutUnit floatHeight = std::max(floats[floatIndex].rect.height(),
newSize.height()); | |
| 1349 floatHeight = std::min(floatHeight, LayoutUnit::max() - floatTop); | |
| 1350 line->markDirty(); | |
| 1351 markLinesDirtyInBlockRange(line->lineBottomWithLeading(), floatTop +
floatHeight, line); | |
| 1352 floats[floatIndex].rect.setSize(newSize); | |
| 1353 dirtiedByFloat = true; | |
| 1354 } | |
| 1355 floatIndex++; | |
| 1356 } | |
| 1357 } | |
| 1358 | |
| 1359 RootInlineBox* RenderParagraph::determineStartPosition(LineLayoutState& layoutSt
ate, InlineBidiResolver& resolver) | 1510 RootInlineBox* RenderParagraph::determineStartPosition(LineLayoutState& layoutSt
ate, InlineBidiResolver& resolver) |
| 1360 { | 1511 { |
| 1361 RootInlineBox* curr = 0; | 1512 RootInlineBox* curr = 0; |
| 1362 RootInlineBox* last = 0; | 1513 RootInlineBox* last = 0; |
| 1363 | 1514 |
| 1364 // FIXME: This entire float-checking block needs to be broken into a new fun
ction. | |
| 1365 bool dirtiedByFloat = false; | |
| 1366 if (!layoutState.isFullLayout()) { | |
| 1367 size_t floatIndex = 0; | |
| 1368 for (curr = firstRootBox(); curr && !curr->isDirty(); curr = curr->nextR
ootBox()) { | |
| 1369 // If a new float has been inserted before this line or before its l
ast known float, just do a full layout. | |
| 1370 bool encounteredNewFloat = false; | |
| 1371 checkFloatsInCleanLine(curr, layoutState.floats(), floatIndex, encou
nteredNewFloat, dirtiedByFloat); | |
| 1372 if (encounteredNewFloat) | |
| 1373 layoutState.markForFullLayout(); | |
| 1374 | |
| 1375 if (dirtiedByFloat || layoutState.isFullLayout()) | |
| 1376 break; | |
| 1377 } | |
| 1378 // Check if a new float has been inserted after the last known float. | |
| 1379 if (!curr && floatIndex < layoutState.floats().size()) | |
| 1380 layoutState.markForFullLayout(); | |
| 1381 } | |
| 1382 | |
| 1383 if (layoutState.isFullLayout()) { | 1515 if (layoutState.isFullLayout()) { |
| 1384 // If we encountered a new float and have inline children, mark ourself
to force us to issue paint invalidations. | 1516 // If we encountered a new float and have inline children, mark ourself
to force us to issue paint invalidations. |
| 1385 if (layoutState.hasInlineChild() && !selfNeedsLayout()) { | 1517 if (layoutState.hasInlineChild() && !selfNeedsLayout()) { |
| 1386 setNeedsLayout(MarkOnlyThis); | 1518 setNeedsLayout(MarkOnlyThis); |
| 1387 } | 1519 } |
| 1388 | 1520 |
| 1389 // FIXME: This should just call deleteLineBoxTree, but that causes | 1521 // FIXME: This should just call deleteLineBoxTree, but that causes |
| 1390 // crashes for fast/repaint tests. | 1522 // crashes for fast/repaint tests. |
| 1391 curr = firstRootBox(); | 1523 curr = firstRootBox(); |
| 1392 while (curr) { | 1524 while (curr) { |
| 1393 // Note: This uses nextRootBox() insted of nextLineBox() like delete
LineBoxTree does. | 1525 // Note: This uses nextRootBox() insted of nextLineBox() like delete
LineBoxTree does. |
| 1394 RootInlineBox* next = curr->nextRootBox(); | 1526 RootInlineBox* next = curr->nextRootBox(); |
| 1395 curr->deleteLine(); | 1527 curr->deleteLine(); |
| 1396 curr = next; | 1528 curr = next; |
| 1397 } | 1529 } |
| 1398 ASSERT(!firstLineBox() && !lastLineBox()); | 1530 ASSERT(!firstLineBox() && !lastLineBox()); |
| 1399 } else { | 1531 } else { |
| 1400 if (curr) { | 1532 if (curr) { |
| 1401 // We have a dirty line. | 1533 // We have a dirty line. |
| 1402 if (RootInlineBox* prevRootBox = curr->prevRootBox()) { | 1534 if (RootInlineBox* prevRootBox = curr->prevRootBox()) { |
| 1403 // We have a previous line. | 1535 // We have a previous line. |
| 1404 if (!dirtiedByFloat && (!prevRootBox->endsWithBreak() || !prevRo
otBox->lineBreakObj() || (prevRootBox->lineBreakObj()->isText() && prevRootBox->
lineBreakPos() >= toRenderText(prevRootBox->lineBreakObj())->textLength()))) | 1536 if (!prevRootBox->endsWithBreak() || !prevRootBox->lineBreakObj(
) || (prevRootBox->lineBreakObj()->isText() && prevRootBox->lineBreakPos() >= to
RenderText(prevRootBox->lineBreakObj())->textLength())) |
| 1405 // The previous line didn't break cleanly or broke at a newl
ine | 1537 // The previous line didn't break cleanly or broke at a newl
ine |
| 1406 // that has been deleted, so treat it as dirty too. | 1538 // that has been deleted, so treat it as dirty too. |
| 1407 curr = prevRootBox; | 1539 curr = prevRootBox; |
| 1408 } | 1540 } |
| 1409 } else { | 1541 } else { |
| 1410 // No dirty lines were found. | 1542 // No dirty lines were found. |
| 1411 // If the last line didn't break cleanly, treat it as dirty. | 1543 // If the last line didn't break cleanly, treat it as dirty. |
| 1412 if (lastRootBox() && !lastRootBox()->endsWithBreak()) | 1544 if (lastRootBox() && !lastRootBox()->endsWithBreak()) |
| 1413 curr = lastRootBox(); | 1545 curr = lastRootBox(); |
| 1414 } | 1546 } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1432 resolver.setStatus(BidiStatus(direction, isOverride(style()->unicodeBidi
()))); | 1564 resolver.setStatus(BidiStatus(direction, isOverride(style()->unicodeBidi
()))); |
| 1433 InlineIterator iter = InlineIterator(this, bidiFirstSkippingEmptyInlines
(this, resolver.runs(), &resolver), 0); | 1565 InlineIterator iter = InlineIterator(this, bidiFirstSkippingEmptyInlines
(this, resolver.runs(), &resolver), 0); |
| 1434 resolver.setPosition(iter, numberOfIsolateAncestors(iter)); | 1566 resolver.setPosition(iter, numberOfIsolateAncestors(iter)); |
| 1435 } | 1567 } |
| 1436 return curr; | 1568 return curr; |
| 1437 } | 1569 } |
| 1438 | 1570 |
| 1439 void RenderParagraph::determineEndPosition(LineLayoutState& layoutState, RootInl
ineBox* startLine, InlineIterator& cleanLineStart, BidiStatus& cleanLineBidiStat
us) | 1571 void RenderParagraph::determineEndPosition(LineLayoutState& layoutState, RootInl
ineBox* startLine, InlineIterator& cleanLineStart, BidiStatus& cleanLineBidiStat
us) |
| 1440 { | 1572 { |
| 1441 ASSERT(!layoutState.endLine()); | 1573 ASSERT(!layoutState.endLine()); |
| 1442 size_t floatIndex = layoutState.floatIndex(); | |
| 1443 RootInlineBox* last = 0; | 1574 RootInlineBox* last = 0; |
| 1444 for (RootInlineBox* curr = startLine->nextRootBox(); curr; curr = curr->next
RootBox()) { | 1575 for (RootInlineBox* curr = startLine->nextRootBox(); curr; curr = curr->next
RootBox()) { |
| 1445 if (!curr->isDirty()) { | |
| 1446 bool encounteredNewFloat = false; | |
| 1447 bool dirtiedByFloat = false; | |
| 1448 checkFloatsInCleanLine(curr, layoutState.floats(), floatIndex, encou
nteredNewFloat, dirtiedByFloat); | |
| 1449 if (encounteredNewFloat) | |
| 1450 return; | |
| 1451 } | |
| 1452 if (curr->isDirty()) | 1576 if (curr->isDirty()) |
| 1453 last = 0; | 1577 last = 0; |
| 1454 else if (!last) | 1578 else if (!last) |
| 1455 last = curr; | 1579 last = curr; |
| 1456 } | 1580 } |
| 1457 | 1581 |
| 1458 if (!last) | 1582 if (!last) |
| 1459 return; | 1583 return; |
| 1460 | 1584 |
| 1461 // At this point, |last| is the first line in a run of clean lines that ends
with the last line | 1585 // At this point, |last| is the first line in a run of clean lines that ends
with the last line |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1581 curr->adjustLogicalPosition(logicalLeft, 0); | 1705 curr->adjustLogicalPosition(logicalLeft, 0); |
| 1582 else | 1706 else |
| 1583 curr->adjustLogicalPosition(logicalLeft - (availableLogicalW
idth - totalLogicalWidth), 0); | 1707 curr->adjustLogicalPosition(logicalLeft - (availableLogicalW
idth - totalLogicalWidth), 0); |
| 1584 } | 1708 } |
| 1585 } | 1709 } |
| 1586 firstLine = false; | 1710 firstLine = false; |
| 1587 } | 1711 } |
| 1588 } | 1712 } |
| 1589 | 1713 |
| 1590 } // namespace blink | 1714 } // namespace blink |
| OLD | NEW |