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 |