| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2000 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 2000 Lars Knoll (knoll@kde.org) |
| 3 * Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All r
ight reserved. | 3 * Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. |
| 4 * All right reserved. |
| 4 * Copyright (C) 2010 Google Inc. All rights reserved. | 5 * Copyright (C) 2010 Google Inc. All rights reserved. |
| 5 * | 6 * |
| 6 * This library is free software; you can redistribute it and/or | 7 * This library is free software; you can redistribute it and/or |
| 7 * modify it under the terms of the GNU Library General Public | 8 * modify it under the terms of the GNU Library General Public |
| 8 * License as published by the Free Software Foundation; either | 9 * License as published by the Free Software Foundation; either |
| 9 * version 2 of the License, or (at your option) any later version. | 10 * version 2 of the License, or (at your option) any later version. |
| 10 * | 11 * |
| 11 * This library is distributed in the hope that it will be useful, | 12 * This library is distributed in the hope that it will be useful, |
| 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 138 | 139 |
| 139 return LineLayoutInline(lineLayoutItem).createAndAppendInlineFlowBox(); | 140 return LineLayoutInline(lineLayoutItem).createAndAppendInlineFlowBox(); |
| 140 } | 141 } |
| 141 | 142 |
| 142 static inline InlineTextBox* createInlineBoxForText(BidiRun& run, | 143 static inline InlineTextBox* createInlineBoxForText(BidiRun& run, |
| 143 bool isOnlyRun) { | 144 bool isOnlyRun) { |
| 144 ASSERT(run.m_lineLayoutItem.isText()); | 145 ASSERT(run.m_lineLayoutItem.isText()); |
| 145 LineLayoutText text = LineLayoutText(run.m_lineLayoutItem); | 146 LineLayoutText text = LineLayoutText(run.m_lineLayoutItem); |
| 146 InlineTextBox* textBox = | 147 InlineTextBox* textBox = |
| 147 text.createInlineTextBox(run.m_start, run.m_stop - run.m_start); | 148 text.createInlineTextBox(run.m_start, run.m_stop - run.m_start); |
| 148 // We only treat a box as text for a <br> if we are on a line by ourself or in
strict mode | 149 // We only treat a box as text for a <br> if we are on a line by ourself or in |
| 149 // (Note the use of strict mode. In "almost strict" mode, we don't treat the
box for <br> as text.) | 150 // strict mode (Note the use of strict mode. In "almost strict" mode, we |
| 151 // don't treat the box for <br> as text.) |
| 150 if (text.isBR()) | 152 if (text.isBR()) |
| 151 textBox->setIsText(isOnlyRun || text.document().inNoQuirksMode()); | 153 textBox->setIsText(isOnlyRun || text.document().inNoQuirksMode()); |
| 152 textBox->setDirOverride( | 154 textBox->setDirOverride( |
| 153 run.dirOverride(text.style()->rtlOrdering() == VisualOrder)); | 155 run.dirOverride(text.style()->rtlOrdering() == VisualOrder)); |
| 154 if (run.m_hasHyphen) | 156 if (run.m_hasHyphen) |
| 155 textBox->setHasHyphen(true); | 157 textBox->setHasHyphen(true); |
| 156 return textBox; | 158 return textBox; |
| 157 } | 159 } |
| 158 | 160 |
| 159 static inline void dirtyLineBoxesForObject(LayoutObject* o, bool fullLayout) { | 161 static inline void dirtyLineBoxesForObject(LayoutObject* o, bool fullLayout) { |
| (...skipping 26 matching lines...) Expand all Loading... |
| 186 ASSERT_WITH_SECURITY_IMPLICATION(lineLayoutItem.isLayoutInline() || | 188 ASSERT_WITH_SECURITY_IMPLICATION(lineLayoutItem.isLayoutInline() || |
| 187 lineLayoutItem.isEqual(this)); | 189 lineLayoutItem.isEqual(this)); |
| 188 | 190 |
| 189 LineLayoutInline inlineFlow(!lineLayoutItem.isEqual(this) ? lineLayoutItem | 191 LineLayoutInline inlineFlow(!lineLayoutItem.isEqual(this) ? lineLayoutItem |
| 190 : nullptr); | 192 : nullptr); |
| 191 | 193 |
| 192 // Get the last box we made for this layout object. | 194 // Get the last box we made for this layout object. |
| 193 parentBox = inlineFlow ? inlineFlow.lastLineBox() | 195 parentBox = inlineFlow ? inlineFlow.lastLineBox() |
| 194 : LineLayoutBlockFlow(lineLayoutItem).lastLineBox(); | 196 : LineLayoutBlockFlow(lineLayoutItem).lastLineBox(); |
| 195 | 197 |
| 196 // If this box or its ancestor is constructed then it is from a previous lin
e, and we need | 198 // If this box or its ancestor is constructed then it is from a previous |
| 197 // to make a new box for our line. If this box or its ancestor is unconstru
cted but it has | 199 // line, and we need to make a new box for our line. If this box or its |
| 198 // something following it on the line, then we know we have to make a new bo
x | 200 // ancestor is unconstructed but it has something following it on the line, |
| 199 // as well. In this situation our inline has actually been split in two on | 201 // then we know we have to make a new box as well. In this situation our |
| 200 // the same line (this can happen with very fancy language mixtures). | 202 // inline has actually been split in two on the same line (this can happen |
| 203 // with very fancy language mixtures). |
| 201 bool constructedNewBox = false; | 204 bool constructedNewBox = false; |
| 202 bool allowedToConstructNewBox = | 205 bool allowedToConstructNewBox = |
| 203 !inlineFlow || inlineFlow.alwaysCreateLineBoxes(); | 206 !inlineFlow || inlineFlow.alwaysCreateLineBoxes(); |
| 204 bool canUseExistingParentBox = | 207 bool canUseExistingParentBox = |
| 205 parentBox && !parentIsConstructedOrHaveNext(parentBox); | 208 parentBox && !parentIsConstructedOrHaveNext(parentBox); |
| 206 if (allowedToConstructNewBox && !canUseExistingParentBox) { | 209 if (allowedToConstructNewBox && !canUseExistingParentBox) { |
| 207 // We need to make a new box for this layout object. Once | 210 // We need to make a new box for this layout object. Once |
| 208 // made, we need to place it at the end of the current line. | 211 // made, we need to place it at the end of the current line. |
| 209 InlineBox* newBox = createInlineBoxForLayoutObject( | 212 InlineBox* newBox = createInlineBoxForLayoutObject( |
| 210 LineLayoutItem(lineLayoutItem), lineLayoutItem.isEqual(this)); | 213 LineLayoutItem(lineLayoutItem), lineLayoutItem.isEqual(this)); |
| 211 ASSERT_WITH_SECURITY_IMPLICATION(newBox->isInlineFlowBox()); | 214 ASSERT_WITH_SECURITY_IMPLICATION(newBox->isInlineFlowBox()); |
| 212 parentBox = toInlineFlowBox(newBox); | 215 parentBox = toInlineFlowBox(newBox); |
| 213 parentBox->setFirstLineStyleBit(lineInfo.isFirstLine()); | 216 parentBox->setFirstLineStyleBit(lineInfo.isFirstLine()); |
| 214 parentBox->setIsHorizontal(isHorizontalWritingMode()); | 217 parentBox->setIsHorizontal(isHorizontalWritingMode()); |
| 215 constructedNewBox = true; | 218 constructedNewBox = true; |
| 216 } | 219 } |
| 217 | 220 |
| 218 if (constructedNewBox || canUseExistingParentBox) { | 221 if (constructedNewBox || canUseExistingParentBox) { |
| 219 if (!result) | 222 if (!result) |
| 220 result = parentBox; | 223 result = parentBox; |
| 221 | 224 |
| 222 // If we have hit the block itself, then |box| represents the root | 225 // If we have hit the block itself, then |box| represents the root |
| 223 // inline box for the line, and it doesn't have to be appended to any pare
nt | 226 // inline box for the line, and it doesn't have to be appended to any |
| 224 // inline. | 227 // parent inline. |
| 225 if (childBox) | 228 if (childBox) |
| 226 parentBox->addToLine(childBox); | 229 parentBox->addToLine(childBox); |
| 227 | 230 |
| 228 if (!constructedNewBox || lineLayoutItem.isEqual(this)) | 231 if (!constructedNewBox || lineLayoutItem.isEqual(this)) |
| 229 break; | 232 break; |
| 230 | 233 |
| 231 childBox = parentBox; | 234 childBox = parentBox; |
| 232 } | 235 } |
| 233 | 236 |
| 234 // If we've exceeded our line depth, then jump straight to the root and skip
all the remaining | 237 // If we've exceeded our line depth, then jump straight to the root and skip |
| 235 // intermediate inline flows. | 238 // all the remaining intermediate inline flows. |
| 236 lineLayoutItem = (++lineDepth >= cMaxLineDepth) ? LineLayoutItem(this) | 239 lineLayoutItem = (++lineDepth >= cMaxLineDepth) ? LineLayoutItem(this) |
| 237 : lineLayoutItem.parent(); | 240 : lineLayoutItem.parent(); |
| 238 | 241 |
| 239 } while (true); | 242 } while (true); |
| 240 | 243 |
| 241 return result; | 244 return result; |
| 242 } | 245 } |
| 243 | 246 |
| 244 template <typename CharacterType> | 247 template <typename CharacterType> |
| 245 static inline bool endsWithASCIISpaces(const CharacterType* characters, | 248 static inline bool endsWithASCIISpaces(const CharacterType* characters, |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 299 | 302 |
| 300 ASSERT(box); | 303 ASSERT(box); |
| 301 if (!box) | 304 if (!box) |
| 302 continue; | 305 continue; |
| 303 | 306 |
| 304 if (!rootHasSelectedChildren && | 307 if (!rootHasSelectedChildren && |
| 305 box->getLineLayoutItem().getSelectionState() != SelectionNone) | 308 box->getLineLayoutItem().getSelectionState() != SelectionNone) |
| 306 rootHasSelectedChildren = true; | 309 rootHasSelectedChildren = true; |
| 307 | 310 |
| 308 // If we have no parent box yet, or if the run is not simply a sibling, | 311 // If we have no parent box yet, or if the run is not simply a sibling, |
| 309 // then we need to construct inline boxes as necessary to properly enclose t
he | 312 // then we need to construct inline boxes as necessary to properly enclose |
| 310 // run's inline box. Segments can only be siblings at the root level, as | 313 // the run's inline box. Segments can only be siblings at the root level, as |
| 311 // they are positioned separately. | 314 // they are positioned separately. |
| 312 if (!parentBox || | 315 if (!parentBox || |
| 313 (parentBox->getLineLayoutItem() != r->m_lineLayoutItem.parent())) { | 316 (parentBox->getLineLayoutItem() != r->m_lineLayoutItem.parent())) { |
| 314 // Create new inline boxes all the way back to the appropriate insertion p
oint. | 317 // Create new inline boxes all the way back to the appropriate insertion |
| 318 // point. |
| 315 parentBox = createLineBoxes(r->m_lineLayoutItem.parent(), lineInfo, box); | 319 parentBox = createLineBoxes(r->m_lineLayoutItem.parent(), lineInfo, box); |
| 316 } else { | 320 } else { |
| 317 // Append the inline box to this line. | 321 // Append the inline box to this line. |
| 318 parentBox->addToLine(box); | 322 parentBox->addToLine(box); |
| 319 } | 323 } |
| 320 | 324 |
| 321 box->setBidiLevel(r->level()); | 325 box->setBidiLevel(r->level()); |
| 322 | 326 |
| 323 if (box->isInlineTextBox()) { | 327 if (box->isInlineTextBox()) { |
| 324 if (AXObjectCache* cache = document().existingAXObjectCache()) | 328 if (AXObjectCache* cache = document().existingAXObjectCache()) |
| 325 cache->inlineTextBoxesUpdated(r->m_lineLayoutItem); | 329 cache->inlineTextBoxesUpdated(r->m_lineLayoutItem); |
| 326 } | 330 } |
| 327 } | 331 } |
| 328 | 332 |
| 329 // We should have a root inline box. It should be unconstructed and | 333 // We should have a root inline box. It should be unconstructed and |
| 330 // be the last continuation of our line list. | 334 // be the last continuation of our line list. |
| 331 ASSERT(lastLineBox() && !lastLineBox()->isConstructed()); | 335 ASSERT(lastLineBox() && !lastLineBox()->isConstructed()); |
| 332 | 336 |
| 333 // Set the m_selectedChildren flag on the root inline box if one of the leaf i
nline box | 337 // Set the m_selectedChildren flag on the root inline box if one of the leaf |
| 334 // from the bidi runs walk above has a selection state. | 338 // inline box from the bidi runs walk above has a selection state. |
| 335 if (rootHasSelectedChildren) | 339 if (rootHasSelectedChildren) |
| 336 lastLineBox()->root().setHasSelectedChildren(true); | 340 lastLineBox()->root().setHasSelectedChildren(true); |
| 337 | 341 |
| 338 // Set bits on our inline flow boxes that indicate which sides should | 342 // Set bits on our inline flow boxes that indicate which sides should |
| 339 // paint borders/margins/padding. This knowledge will ultimately be used when | 343 // paint borders/margins/padding. This knowledge will ultimately be used when |
| 340 // we determine the horizontal positions and widths of all the inline boxes on | 344 // we determine the horizontal positions and widths of all the inline boxes on |
| 341 // the line. | 345 // the line. |
| 342 bool isLogicallyLastRunWrapped = | 346 bool isLogicallyLastRunWrapped = |
| 343 bidiRuns.logicallyLastRun()->m_lineLayoutItem && | 347 bidiRuns.logicallyLastRun()->m_lineLayoutItem && |
| 344 bidiRuns.logicallyLastRun()->m_lineLayoutItem.isText() | 348 bidiRuns.logicallyLastRun()->m_lineLayoutItem.isText() |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 383 return alignment; | 387 return alignment; |
| 384 } | 388 } |
| 385 | 389 |
| 386 static void updateLogicalWidthForLeftAlignedBlock( | 390 static void updateLogicalWidthForLeftAlignedBlock( |
| 387 bool isLeftToRightDirection, | 391 bool isLeftToRightDirection, |
| 388 BidiRun* trailingSpaceRun, | 392 BidiRun* trailingSpaceRun, |
| 389 LayoutUnit& logicalLeft, | 393 LayoutUnit& logicalLeft, |
| 390 LayoutUnit totalLogicalWidth, | 394 LayoutUnit totalLogicalWidth, |
| 391 LayoutUnit availableLogicalWidth) { | 395 LayoutUnit availableLogicalWidth) { |
| 392 // The direction of the block should determine what happens with wide lines. | 396 // The direction of the block should determine what happens with wide lines. |
| 393 // In particular with RTL blocks, wide lines should still spill out to the lef
t. | 397 // In particular with RTL blocks, wide lines should still spill out to the |
| 398 // left. |
| 394 if (isLeftToRightDirection) { | 399 if (isLeftToRightDirection) { |
| 395 if (totalLogicalWidth > availableLogicalWidth && trailingSpaceRun) | 400 if (totalLogicalWidth > availableLogicalWidth && trailingSpaceRun) |
| 396 trailingSpaceRun->m_box->setLogicalWidth(std::max( | 401 trailingSpaceRun->m_box->setLogicalWidth(std::max( |
| 397 LayoutUnit(), trailingSpaceRun->m_box->logicalWidth() - | 402 LayoutUnit(), trailingSpaceRun->m_box->logicalWidth() - |
| 398 totalLogicalWidth + availableLogicalWidth)); | 403 totalLogicalWidth + availableLogicalWidth)); |
| 399 return; | 404 return; |
| 400 } | 405 } |
| 401 | 406 |
| 402 if (trailingSpaceRun) | 407 if (trailingSpaceRun) |
| 403 trailingSpaceRun->m_box->setLogicalWidth(LayoutUnit()); | 408 trailingSpaceRun->m_box->setLogicalWidth(LayoutUnit()); |
| 404 else if (totalLogicalWidth > availableLogicalWidth) | 409 else if (totalLogicalWidth > availableLogicalWidth) |
| 405 logicalLeft -= (totalLogicalWidth - availableLogicalWidth); | 410 logicalLeft -= (totalLogicalWidth - availableLogicalWidth); |
| 406 } | 411 } |
| 407 | 412 |
| 408 static void updateLogicalWidthForRightAlignedBlock( | 413 static void updateLogicalWidthForRightAlignedBlock( |
| 409 bool isLeftToRightDirection, | 414 bool isLeftToRightDirection, |
| 410 BidiRun* trailingSpaceRun, | 415 BidiRun* trailingSpaceRun, |
| 411 LayoutUnit& logicalLeft, | 416 LayoutUnit& logicalLeft, |
| 412 LayoutUnit& totalLogicalWidth, | 417 LayoutUnit& totalLogicalWidth, |
| 413 LayoutUnit availableLogicalWidth) { | 418 LayoutUnit availableLogicalWidth) { |
| 414 // Wide lines spill out of the block based off direction. | 419 // Wide lines spill out of the block based off direction. |
| 415 // So even if text-align is right, if direction is LTR, wide lines should over
flow out of the right | 420 // So even if text-align is right, if direction is LTR, wide lines should |
| 416 // side of the block. | 421 // overflow out of the right side of the block. |
| 417 if (isLeftToRightDirection) { | 422 if (isLeftToRightDirection) { |
| 418 if (trailingSpaceRun) { | 423 if (trailingSpaceRun) { |
| 419 totalLogicalWidth -= trailingSpaceRun->m_box->logicalWidth(); | 424 totalLogicalWidth -= trailingSpaceRun->m_box->logicalWidth(); |
| 420 trailingSpaceRun->m_box->setLogicalWidth(LayoutUnit()); | 425 trailingSpaceRun->m_box->setLogicalWidth(LayoutUnit()); |
| 421 } | 426 } |
| 422 if (totalLogicalWidth < availableLogicalWidth) | 427 if (totalLogicalWidth < availableLogicalWidth) |
| 423 logicalLeft += availableLogicalWidth - totalLogicalWidth; | 428 logicalLeft += availableLogicalWidth - totalLogicalWidth; |
| 424 return; | 429 return; |
| 425 } | 430 } |
| 426 | 431 |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 536 if (toInlineTextBox(run->m_box)->hasHyphen()) | 541 if (toInlineTextBox(run->m_box)->hasHyphen()) |
| 537 hyphenWidth = LayoutUnit(layoutText.hyphenWidth(font, run->direction())); | 542 hyphenWidth = LayoutUnit(layoutText.hyphenWidth(font, run->direction())); |
| 538 | 543 |
| 539 float measuredWidth = 0; | 544 float measuredWidth = 0; |
| 540 FloatRect glyphBounds; | 545 FloatRect glyphBounds; |
| 541 | 546 |
| 542 bool kerningIsEnabled = | 547 bool kerningIsEnabled = |
| 543 font.getFontDescription().getTypesettingFeatures() & Kerning; | 548 font.getFontDescription().getTypesettingFeatures() & Kerning; |
| 544 | 549 |
| 545 #if OS(MACOSX) | 550 #if OS(MACOSX) |
| 546 // FIXME: Having any font feature settings enabled can lead to selection gaps
on | 551 // FIXME: Having any font feature settings enabled can lead to selection gaps |
| 547 // Chromium-mac. https://bugs.webkit.org/show_bug.cgi?id=113418 | 552 // on Chromium-mac. https://bugs.webkit.org/show_bug.cgi?id=113418 |
| 548 bool canUseCachedWordMeasurements = | 553 bool canUseCachedWordMeasurements = |
| 549 font.canShapeWordByWord() && !font.getFontDescription().featureSettings(); | 554 font.canShapeWordByWord() && !font.getFontDescription().featureSettings(); |
| 550 #else | 555 #else |
| 551 bool canUseCachedWordMeasurements = font.canShapeWordByWord(); | 556 bool canUseCachedWordMeasurements = font.canShapeWordByWord(); |
| 552 #endif | 557 #endif |
| 553 | 558 |
| 554 if (canUseCachedWordMeasurements) { | 559 if (canUseCachedWordMeasurements) { |
| 555 int lastEndOffset = run->m_start; | 560 int lastEndOffset = run->m_start; |
| 556 size_t i = findWordMeasurement(layoutText, lastEndOffset, wordMeasurements, | 561 size_t i = findWordMeasurement(layoutText, lastEndOffset, wordMeasurements, |
| 557 wordMeasurementsIndex); | 562 wordMeasurementsIndex); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 590 } | 595 } |
| 591 } | 596 } |
| 592 wordMeasurementsIndex = i; | 597 wordMeasurementsIndex = i; |
| 593 if (lastEndOffset != run->m_stop) { | 598 if (lastEndOffset != run->m_stop) { |
| 594 // If we don't have enough cached data, we'll measure the run again. | 599 // If we don't have enough cached data, we'll measure the run again. |
| 595 canUseCachedWordMeasurements = false; | 600 canUseCachedWordMeasurements = false; |
| 596 fallbackFonts.clear(); | 601 fallbackFonts.clear(); |
| 597 } | 602 } |
| 598 } | 603 } |
| 599 | 604 |
| 600 // Don't put this into 'else' part of the above 'if' because canUseCachedWordM
easurements may be modified in the 'if' block. | 605 // Don't put this into 'else' part of the above 'if' because |
| 606 // canUseCachedWordMeasurements may be modified in the 'if' block. |
| 601 if (!canUseCachedWordMeasurements) | 607 if (!canUseCachedWordMeasurements) |
| 602 measuredWidth = layoutText.width( | 608 measuredWidth = layoutText.width( |
| 603 run->m_start, run->m_stop - run->m_start, xPos, run->direction(), | 609 run->m_start, run->m_stop - run->m_start, xPos, run->direction(), |
| 604 lineInfo.isFirstLine(), &fallbackFonts, &glyphBounds); | 610 lineInfo.isFirstLine(), &fallbackFonts, &glyphBounds); |
| 605 | 611 |
| 606 // Negative word-spacing and/or letter-spacing may cause some glyphs to overfl
ow the left boundary and result | 612 // Negative word-spacing and/or letter-spacing may cause some glyphs to |
| 607 // negative measured width. Reset measured width to 0 and adjust glyph bounds
accordingly to cover the overflow. | 613 // overflow the left boundary and result negative measured width. Reset |
| 614 // measured width to 0 and adjust glyph bounds accordingly to cover the |
| 615 // overflow. |
| 608 if (measuredWidth < 0) { | 616 if (measuredWidth < 0) { |
| 609 if (measuredWidth < glyphBounds.x()) { | 617 if (measuredWidth < glyphBounds.x()) { |
| 610 glyphBounds.expand(glyphBounds.x() - measuredWidth, 0); | 618 glyphBounds.expand(glyphBounds.x() - measuredWidth, 0); |
| 611 glyphBounds.setX(measuredWidth); | 619 glyphBounds.setX(measuredWidth); |
| 612 } | 620 } |
| 613 measuredWidth = 0; | 621 measuredWidth = 0; |
| 614 } | 622 } |
| 615 | 623 |
| 616 glyphOverflow.setFromBounds(glyphBounds, font.getFontMetrics().floatAscent(), | 624 glyphOverflow.setFromBounds(glyphBounds, font.getFontMetrics().floatAscent(), |
| 617 font.getFontMetrics().floatDescent(), | 625 font.getFontMetrics().floatDescent(), |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 652 LayoutUnit& availableLogicalWidth, | 660 LayoutUnit& availableLogicalWidth, |
| 653 unsigned expansionOpportunityCount) { | 661 unsigned expansionOpportunityCount) { |
| 654 TextDirection direction; | 662 TextDirection direction; |
| 655 if (rootInlineBox && | 663 if (rootInlineBox && |
| 656 rootInlineBox->getLineLayoutItem().style()->unicodeBidi() == Plaintext) | 664 rootInlineBox->getLineLayoutItem().style()->unicodeBidi() == Plaintext) |
| 657 direction = rootInlineBox->direction(); | 665 direction = rootInlineBox->direction(); |
| 658 else | 666 else |
| 659 direction = style()->direction(); | 667 direction = style()->direction(); |
| 660 | 668 |
| 661 // Armed with the total width of the line (without justification), | 669 // Armed with the total width of the line (without justification), |
| 662 // we now examine our text-align property in order to determine where to posit
ion the | 670 // we now examine our text-align property in order to determine where to |
| 663 // objects horizontally. The total width of the line can be increased if we en
d up | 671 // position the objects horizontally. The total width of the line can be |
| 664 // justifying text. | 672 // increased if we end up justifying text. |
| 665 switch (textAlign) { | 673 switch (textAlign) { |
| 666 case LEFT: | 674 case LEFT: |
| 667 case WEBKIT_LEFT: | 675 case WEBKIT_LEFT: |
| 668 updateLogicalWidthForLeftAlignedBlock( | 676 updateLogicalWidthForLeftAlignedBlock( |
| 669 style()->isLeftToRightDirection(), trailingSpaceRun, logicalLeft, | 677 style()->isLeftToRightDirection(), trailingSpaceRun, logicalLeft, |
| 670 totalLogicalWidth, availableLogicalWidth); | 678 totalLogicalWidth, availableLogicalWidth); |
| 671 break; | 679 break; |
| 672 case RIGHT: | 680 case RIGHT: |
| 673 case WEBKIT_RIGHT: | 681 case WEBKIT_RIGHT: |
| 674 updateLogicalWidthForRightAlignedBlock( | 682 updateLogicalWidthForRightAlignedBlock( |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 738 const LineInfo& lineInfo, | 746 const LineInfo& lineInfo, |
| 739 BidiRun* firstRun, | 747 BidiRun* firstRun, |
| 740 BidiRun* trailingSpaceRun, | 748 BidiRun* trailingSpaceRun, |
| 741 bool reachedEnd, | 749 bool reachedEnd, |
| 742 GlyphOverflowAndFallbackFontsMap& textBoxDataMap, | 750 GlyphOverflowAndFallbackFontsMap& textBoxDataMap, |
| 743 VerticalPositionCache& verticalPositionCache, | 751 VerticalPositionCache& verticalPositionCache, |
| 744 WordMeasurements& wordMeasurements) { | 752 WordMeasurements& wordMeasurements) { |
| 745 ETextAlign textAlign = | 753 ETextAlign textAlign = |
| 746 textAlignmentForLine(!reachedEnd && !lineBox->endsWithBreak()); | 754 textAlignmentForLine(!reachedEnd && !lineBox->endsWithBreak()); |
| 747 | 755 |
| 748 // CSS 2.1: "'Text-indent' only affects a line if it is the first formatted li
ne of an element. For example, the first line of an anonymous block | 756 // CSS 2.1: "'Text-indent' only affects a line if it is the first formatted |
| 757 // line of an element. For example, the first line of an anonymous block |
| 749 // box is only affected if it is the first child of its parent element." | 758 // box is only affected if it is the first child of its parent element." |
| 750 // CSS3 "text-indent", "each-line" affects the first line of the block contain
er as well as each line after a forced line break, | 759 // CSS3 "text-indent", "each-line" affects the first line of the block |
| 751 // but does not affect lines after a soft wrap break. | 760 // container as well as each line after a forced line break, but does not |
| 761 // affect lines after a soft wrap break. |
| 752 bool isFirstLine = | 762 bool isFirstLine = |
| 753 lineInfo.isFirstLine() && | 763 lineInfo.isFirstLine() && |
| 754 !(isAnonymousBlock() && parent()->slowFirstChild() != this); | 764 !(isAnonymousBlock() && parent()->slowFirstChild() != this); |
| 755 bool isAfterHardLineBreak = | 765 bool isAfterHardLineBreak = |
| 756 lineBox->prevRootBox() && lineBox->prevRootBox()->endsWithBreak(); | 766 lineBox->prevRootBox() && lineBox->prevRootBox()->endsWithBreak(); |
| 757 IndentTextOrNot indentText = | 767 IndentTextOrNot indentText = |
| 758 requiresIndent(isFirstLine, isAfterHardLineBreak, styleRef()); | 768 requiresIndent(isFirstLine, isAfterHardLineBreak, styleRef()); |
| 759 LayoutUnit lineLogicalLeft; | 769 LayoutUnit lineLogicalLeft; |
| 760 LayoutUnit lineLogicalRight; | 770 LayoutUnit lineLogicalRight; |
| 761 LayoutUnit availableLogicalWidth; | 771 LayoutUnit availableLogicalWidth; |
| 762 updateLogicalInlinePositions(this, lineLogicalLeft, lineLogicalRight, | 772 updateLogicalInlinePositions(this, lineLogicalLeft, lineLogicalRight, |
| 763 availableLogicalWidth, isFirstLine, indentText, | 773 availableLogicalWidth, isFirstLine, indentText, |
| 764 LayoutUnit()); | 774 LayoutUnit()); |
| 765 bool needsWordSpacing; | 775 bool needsWordSpacing; |
| 766 | 776 |
| 767 if (firstRun && firstRun->m_lineLayoutItem.isAtomicInlineLevel()) { | 777 if (firstRun && firstRun->m_lineLayoutItem.isAtomicInlineLevel()) { |
| 768 LineLayoutBox layoutBox(firstRun->m_lineLayoutItem); | 778 LineLayoutBox layoutBox(firstRun->m_lineLayoutItem); |
| 769 updateLogicalInlinePositions(this, lineLogicalLeft, lineLogicalRight, | 779 updateLogicalInlinePositions(this, lineLogicalLeft, lineLogicalRight, |
| 770 availableLogicalWidth, isFirstLine, indentText, | 780 availableLogicalWidth, isFirstLine, indentText, |
| 771 layoutBox.logicalHeight()); | 781 layoutBox.logicalHeight()); |
| 772 } | 782 } |
| 773 | 783 |
| 774 computeInlineDirectionPositionsForSegment( | 784 computeInlineDirectionPositionsForSegment( |
| 775 lineBox, lineInfo, textAlign, lineLogicalLeft, availableLogicalWidth, | 785 lineBox, lineInfo, textAlign, lineLogicalLeft, availableLogicalWidth, |
| 776 firstRun, trailingSpaceRun, textBoxDataMap, verticalPositionCache, | 786 firstRun, trailingSpaceRun, textBoxDataMap, verticalPositionCache, |
| 777 wordMeasurements); | 787 wordMeasurements); |
| 778 // The widths of all runs are now known. We can now place every inline box (an
d | 788 // The widths of all runs are now known. We can now place every inline box |
| 779 // compute accurate widths for the inline flow boxes). | 789 // (and compute accurate widths for the inline flow boxes). |
| 780 needsWordSpacing = lineBox->isLeftToRightDirection() ? false : true; | 790 needsWordSpacing = lineBox->isLeftToRightDirection() ? false : true; |
| 781 lineBox->placeBoxesInInlineDirection(lineLogicalLeft, needsWordSpacing); | 791 lineBox->placeBoxesInInlineDirection(lineLogicalLeft, needsWordSpacing); |
| 782 } | 792 } |
| 783 | 793 |
| 784 BidiRun* LayoutBlockFlow::computeInlineDirectionPositionsForSegment( | 794 BidiRun* LayoutBlockFlow::computeInlineDirectionPositionsForSegment( |
| 785 RootInlineBox* lineBox, | 795 RootInlineBox* lineBox, |
| 786 const LineInfo& lineInfo, | 796 const LineInfo& lineInfo, |
| 787 ETextAlign textAlign, | 797 ETextAlign textAlign, |
| 788 LayoutUnit& logicalLeft, | 798 LayoutUnit& logicalLeft, |
| 789 LayoutUnit& availableLogicalWidth, | 799 LayoutUnit& availableLogicalWidth, |
| 790 BidiRun* firstRun, | 800 BidiRun* firstRun, |
| 791 BidiRun* trailingSpaceRun, | 801 BidiRun* trailingSpaceRun, |
| 792 GlyphOverflowAndFallbackFontsMap& textBoxDataMap, | 802 GlyphOverflowAndFallbackFontsMap& textBoxDataMap, |
| 793 VerticalPositionCache& verticalPositionCache, | 803 VerticalPositionCache& verticalPositionCache, |
| 794 WordMeasurements& wordMeasurements) { | 804 WordMeasurements& wordMeasurements) { |
| 795 bool needsWordSpacing = true; | 805 bool needsWordSpacing = true; |
| 796 LayoutUnit totalLogicalWidth = lineBox->getFlowSpacingLogicalWidth(); | 806 LayoutUnit totalLogicalWidth = lineBox->getFlowSpacingLogicalWidth(); |
| 797 bool isAfterExpansion = true; | 807 bool isAfterExpansion = true; |
| 798 ExpansionOpportunities expansions; | 808 ExpansionOpportunities expansions; |
| 799 LayoutObject* previousObject = nullptr; | 809 LayoutObject* previousObject = nullptr; |
| 800 TextJustify textJustify = style()->getTextJustify(); | 810 TextJustify textJustify = style()->getTextJustify(); |
| 801 | 811 |
| 802 BidiRun* r = firstRun; | 812 BidiRun* r = firstRun; |
| 803 size_t wordMeasurementsIndex = 0; | 813 size_t wordMeasurementsIndex = 0; |
| 804 for (; r; r = r->next()) { | 814 for (; r; r = r->next()) { |
| 805 if (!r->m_box || r->m_lineLayoutItem.isOutOfFlowPositioned() || | 815 if (!r->m_box || r->m_lineLayoutItem.isOutOfFlowPositioned() || |
| 806 r->m_box->isLineBreak()) { | 816 r->m_box->isLineBreak()) { |
| 807 continue; // Positioned objects are only participating to figure out thei
r | 817 continue; // Positioned objects are only participating to figure out |
| 808 // correct static x position. They have no effect on the width. | 818 // their correct static x position. They have no effect on the |
| 809 // Similarly, line break boxes have no effect on the width. | 819 // width. Similarly, line break boxes have no effect on the |
| 820 // width. |
| 810 } | 821 } |
| 811 if (r->m_lineLayoutItem.isText()) { | 822 if (r->m_lineLayoutItem.isText()) { |
| 812 LineLayoutText rt(r->m_lineLayoutItem); | 823 LineLayoutText rt(r->m_lineLayoutItem); |
| 813 if (textAlign == JUSTIFY && r != trailingSpaceRun && | 824 if (textAlign == JUSTIFY && r != trailingSpaceRun && |
| 814 textJustify != TextJustifyNone) { | 825 textJustify != TextJustifyNone) { |
| 815 if (!isAfterExpansion) | 826 if (!isAfterExpansion) |
| 816 toInlineTextBox(r->m_box)->setCanHaveLeadingExpansion(true); | 827 toInlineTextBox(r->m_box)->setCanHaveLeadingExpansion(true); |
| 817 expansions.addRunWithExpansions(*r, isAfterExpansion, textJustify); | 828 expansions.addRunWithExpansions(*r, isAfterExpansion, textJustify); |
| 818 } | 829 } |
| 819 | 830 |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 891 } | 902 } |
| 892 } | 903 } |
| 893 | 904 |
| 894 void LayoutBlockFlow::appendFloatingObjectToLastLine( | 905 void LayoutBlockFlow::appendFloatingObjectToLastLine( |
| 895 FloatingObject& floatingObject) { | 906 FloatingObject& floatingObject) { |
| 896 ASSERT(!floatingObject.originatingLine()); | 907 ASSERT(!floatingObject.originatingLine()); |
| 897 floatingObject.setOriginatingLine(lastRootBox()); | 908 floatingObject.setOriginatingLine(lastRootBox()); |
| 898 lastRootBox()->appendFloat(floatingObject.layoutObject()); | 909 lastRootBox()->appendFloat(floatingObject.layoutObject()); |
| 899 } | 910 } |
| 900 | 911 |
| 901 // This function constructs line boxes for all of the text runs in the resolver
and computes their position. | 912 // This function constructs line boxes for all of the text runs in the resolver |
| 913 // and computes their position. |
| 902 RootInlineBox* LayoutBlockFlow::createLineBoxesFromBidiRuns( | 914 RootInlineBox* LayoutBlockFlow::createLineBoxesFromBidiRuns( |
| 903 unsigned bidiLevel, | 915 unsigned bidiLevel, |
| 904 BidiRunList<BidiRun>& bidiRuns, | 916 BidiRunList<BidiRun>& bidiRuns, |
| 905 const InlineIterator& end, | 917 const InlineIterator& end, |
| 906 LineInfo& lineInfo, | 918 LineInfo& lineInfo, |
| 907 VerticalPositionCache& verticalPositionCache, | 919 VerticalPositionCache& verticalPositionCache, |
| 908 BidiRun* trailingSpaceRun, | 920 BidiRun* trailingSpaceRun, |
| 909 WordMeasurements& wordMeasurements) { | 921 WordMeasurements& wordMeasurements) { |
| 910 if (!bidiRuns.runCount()) | 922 if (!bidiRuns.runCount()) |
| 911 return nullptr; | 923 return nullptr; |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 949 textBoxDataMap); | 961 textBoxDataMap); |
| 950 | 962 |
| 951 return lineBox; | 963 return lineBox; |
| 952 } | 964 } |
| 953 | 965 |
| 954 static void deleteLineRange(LineLayoutState& layoutState, | 966 static void deleteLineRange(LineLayoutState& layoutState, |
| 955 RootInlineBox* startLine, | 967 RootInlineBox* startLine, |
| 956 RootInlineBox* stopLine = 0) { | 968 RootInlineBox* stopLine = 0) { |
| 957 RootInlineBox* boxToDelete = startLine; | 969 RootInlineBox* boxToDelete = startLine; |
| 958 while (boxToDelete && boxToDelete != stopLine) { | 970 while (boxToDelete && boxToDelete != stopLine) { |
| 959 // Note: deleteLineRange(firstRootBox()) is not identical to deleteLineBoxTr
ee(). | 971 // Note: deleteLineRange(firstRootBox()) is not identical to |
| 960 // deleteLineBoxTree uses nextLineBox() instead of nextRootBox() when traver
sing. | 972 // deleteLineBoxTree(). deleteLineBoxTree uses nextLineBox() instead of |
| 973 // nextRootBox() when traversing. |
| 961 RootInlineBox* next = boxToDelete->nextRootBox(); | 974 RootInlineBox* next = boxToDelete->nextRootBox(); |
| 962 boxToDelete->deleteLine(); | 975 boxToDelete->deleteLine(); |
| 963 boxToDelete = next; | 976 boxToDelete = next; |
| 964 } | 977 } |
| 965 } | 978 } |
| 966 | 979 |
| 967 void LayoutBlockFlow::layoutRunsAndFloats(LineLayoutState& layoutState) { | 980 void LayoutBlockFlow::layoutRunsAndFloats(LineLayoutState& layoutState) { |
| 968 // We want to skip ahead to the first dirty line | 981 // We want to skip ahead to the first dirty line |
| 969 InlineBidiResolver resolver; | 982 InlineBidiResolver resolver; |
| 970 RootInlineBox* startLine = determineStartPosition(layoutState, resolver); | 983 RootInlineBox* startLine = determineStartPosition(layoutState, resolver); |
| 971 | 984 |
| 972 if (containsFloats()) | 985 if (containsFloats()) |
| 973 layoutState.setLastFloat(m_floatingObjects->set().last().get()); | 986 layoutState.setLastFloat(m_floatingObjects->set().last().get()); |
| 974 | 987 |
| 975 // We also find the first clean line and extract these lines. We will add the
m back | 988 // We also find the first clean line and extract these lines. We will add |
| 976 // if we determine that we're able to synchronize after handling all our dirty
lines. | 989 // them back if we determine that we're able to synchronize after handling all |
| 990 // our dirty lines. |
| 977 InlineIterator cleanLineStart; | 991 InlineIterator cleanLineStart; |
| 978 BidiStatus cleanLineBidiStatus; | 992 BidiStatus cleanLineBidiStatus; |
| 979 if (!layoutState.isFullLayout() && startLine) | 993 if (!layoutState.isFullLayout() && startLine) |
| 980 determineEndPosition(layoutState, startLine, cleanLineStart, | 994 determineEndPosition(layoutState, startLine, cleanLineStart, |
| 981 cleanLineBidiStatus); | 995 cleanLineBidiStatus); |
| 982 | 996 |
| 983 if (startLine) | 997 if (startLine) |
| 984 deleteLineRange(layoutState, startLine); | 998 deleteLineRange(layoutState, startLine); |
| 985 | 999 |
| 986 layoutRunsAndFloatsInRange(layoutState, resolver, cleanLineStart, | 1000 layoutRunsAndFloatsInRange(layoutState, resolver, cleanLineStart, |
| 987 cleanLineBidiStatus); | 1001 cleanLineBidiStatus); |
| 988 linkToEndLineIfNeeded(layoutState); | 1002 linkToEndLineIfNeeded(layoutState); |
| 989 markDirtyFloatsForPaintInvalidation(layoutState.floats()); | 1003 markDirtyFloatsForPaintInvalidation(layoutState.floats()); |
| 990 } | 1004 } |
| 991 | 1005 |
| 992 // Before restarting the layout loop with a new logicalHeight, remove all floats
that were added and reset the resolver. | 1006 // Before restarting the layout loop with a new logicalHeight, remove all floats |
| 1007 // that were added and reset the resolver. |
| 993 inline const InlineIterator& LayoutBlockFlow::restartLayoutRunsAndFloatsInRange( | 1008 inline const InlineIterator& LayoutBlockFlow::restartLayoutRunsAndFloatsInRange( |
| 994 LayoutUnit oldLogicalHeight, | 1009 LayoutUnit oldLogicalHeight, |
| 995 LayoutUnit newLogicalHeight, | 1010 LayoutUnit newLogicalHeight, |
| 996 FloatingObject* lastFloatFromPreviousLine, | 1011 FloatingObject* lastFloatFromPreviousLine, |
| 997 InlineBidiResolver& resolver, | 1012 InlineBidiResolver& resolver, |
| 998 const InlineIterator& oldEnd) { | 1013 const InlineIterator& oldEnd) { |
| 999 removeFloatingObjectsBelow(lastFloatFromPreviousLine, | 1014 removeFloatingObjectsBelow(lastFloatFromPreviousLine, |
| 1000 oldLogicalHeight.toInt()); | 1015 oldLogicalHeight.toInt()); |
| 1001 setLogicalHeight(newLogicalHeight); | 1016 setLogicalHeight(newLogicalHeight); |
| 1002 resolver.setPositionIgnoringNestedIsolates(oldEnd); | 1017 resolver.setPositionIgnoringNestedIsolates(oldEnd); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1013 FloatingObjectSetIterator end = floatingObjectSet.end(); | 1028 FloatingObjectSetIterator end = floatingObjectSet.end(); |
| 1014 if (layoutState.lastFloat()) { | 1029 if (layoutState.lastFloat()) { |
| 1015 FloatingObjectSetIterator lastFloatIterator = | 1030 FloatingObjectSetIterator lastFloatIterator = |
| 1016 floatingObjectSet.find(layoutState.lastFloat()); | 1031 floatingObjectSet.find(layoutState.lastFloat()); |
| 1017 ASSERT(lastFloatIterator != end); | 1032 ASSERT(lastFloatIterator != end); |
| 1018 ++lastFloatIterator; | 1033 ++lastFloatIterator; |
| 1019 it = lastFloatIterator; | 1034 it = lastFloatIterator; |
| 1020 } | 1035 } |
| 1021 for (; it != end; ++it) { | 1036 for (; it != end; ++it) { |
| 1022 FloatingObject& floatingObject = *it->get(); | 1037 FloatingObject& floatingObject = *it->get(); |
| 1023 // If we've reached the start of clean lines any remaining floating children
belong to them. | 1038 // If we've reached the start of clean lines any remaining floating children |
| 1039 // belong to them. |
| 1024 if (cleanLineStart.getLineLayoutItem().isEqual( | 1040 if (cleanLineStart.getLineLayoutItem().isEqual( |
| 1025 floatingObject.layoutObject()) && | 1041 floatingObject.layoutObject()) && |
| 1026 layoutState.endLine()) { | 1042 layoutState.endLine()) { |
| 1027 layoutState.setEndLineMatched(layoutState.endLineMatched() || | 1043 layoutState.setEndLineMatched(layoutState.endLineMatched() || |
| 1028 matchedEndLine(layoutState, resolver, | 1044 matchedEndLine(layoutState, resolver, |
| 1029 cleanLineStart, | 1045 cleanLineStart, |
| 1030 cleanLineBidiStatus)); | 1046 cleanLineBidiStatus)); |
| 1031 if (layoutState.endLineMatched()) { | 1047 if (layoutState.endLineMatched()) { |
| 1032 layoutState.setLastFloat(&floatingObject); | 1048 layoutState.setLastFloat(&floatingObject); |
| 1033 return; | 1049 return; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1055 const InlineIterator& cleanLineStart, | 1071 const InlineIterator& cleanLineStart, |
| 1056 const BidiStatus& cleanLineBidiStatus) { | 1072 const BidiStatus& cleanLineBidiStatus) { |
| 1057 const ComputedStyle& styleToUse = styleRef(); | 1073 const ComputedStyle& styleToUse = styleRef(); |
| 1058 bool paginated = | 1074 bool paginated = |
| 1059 view()->layoutState() && view()->layoutState()->isPaginated(); | 1075 view()->layoutState() && view()->layoutState()->isPaginated(); |
| 1060 LineMidpointState& lineMidpointState = resolver.midpointState(); | 1076 LineMidpointState& lineMidpointState = resolver.midpointState(); |
| 1061 InlineIterator endOfLine = resolver.position(); | 1077 InlineIterator endOfLine = resolver.position(); |
| 1062 LayoutTextInfo layoutTextInfo; | 1078 LayoutTextInfo layoutTextInfo; |
| 1063 VerticalPositionCache verticalPositionCache; | 1079 VerticalPositionCache verticalPositionCache; |
| 1064 | 1080 |
| 1065 // Pagination may require us to delete and re-create a line due to floats. Whe
n this happens, | 1081 // Pagination may require us to delete and re-create a line due to floats. |
| 1082 // When this happens, |
| 1066 // we need to store the pagination strut in the meantime. | 1083 // we need to store the pagination strut in the meantime. |
| 1067 LayoutUnit paginationStrutFromDeletedLine; | 1084 LayoutUnit paginationStrutFromDeletedLine; |
| 1068 | 1085 |
| 1069 LineBreaker lineBreaker(LineLayoutBlockFlow(this)); | 1086 LineBreaker lineBreaker(LineLayoutBlockFlow(this)); |
| 1070 | 1087 |
| 1071 while (!endOfLine.atEnd()) { | 1088 while (!endOfLine.atEnd()) { |
| 1072 // The runs from the previous line should have been cleaned up. | 1089 // The runs from the previous line should have been cleaned up. |
| 1073 ASSERT(!resolver.runs().runCount()); | 1090 ASSERT(!resolver.runs().runCount()); |
| 1074 | 1091 |
| 1075 // FIXME: Is this check necessary before the first iteration or can it be mo
ved to the end? | 1092 // FIXME: Is this check necessary before the first iteration or can it be |
| 1093 // moved to the end? |
| 1076 if (layoutState.endLine()) { | 1094 if (layoutState.endLine()) { |
| 1077 layoutState.setEndLineMatched(layoutState.endLineMatched() || | 1095 layoutState.setEndLineMatched(layoutState.endLineMatched() || |
| 1078 matchedEndLine(layoutState, resolver, | 1096 matchedEndLine(layoutState, resolver, |
| 1079 cleanLineStart, | 1097 cleanLineStart, |
| 1080 cleanLineBidiStatus)); | 1098 cleanLineBidiStatus)); |
| 1081 if (layoutState.endLineMatched()) { | 1099 if (layoutState.endLineMatched()) { |
| 1082 resolver.setPosition(InlineIterator(resolver.position().root(), 0, 0), | 1100 resolver.setPosition(InlineIterator(resolver.position().root(), 0, 0), |
| 1083 0); | 1101 0); |
| 1084 break; | 1102 break; |
| 1085 } | 1103 } |
| 1086 } | 1104 } |
| 1087 | 1105 |
| 1088 lineMidpointState.reset(); | 1106 lineMidpointState.reset(); |
| 1089 | 1107 |
| 1090 layoutState.lineInfo().setEmpty(true); | 1108 layoutState.lineInfo().setEmpty(true); |
| 1091 layoutState.lineInfo().resetRunsFromLeadingWhitespace(); | 1109 layoutState.lineInfo().resetRunsFromLeadingWhitespace(); |
| 1092 | 1110 |
| 1093 const InlineIterator previousEndofLine = endOfLine; | 1111 const InlineIterator previousEndofLine = endOfLine; |
| 1094 bool isNewUBAParagraph = layoutState.lineInfo().previousLineBrokeCleanly(); | 1112 bool isNewUBAParagraph = layoutState.lineInfo().previousLineBrokeCleanly(); |
| 1095 FloatingObject* lastFloatFromPreviousLine = | 1113 FloatingObject* lastFloatFromPreviousLine = |
| 1096 (containsFloats()) ? m_floatingObjects->set().last().get() : 0; | 1114 (containsFloats()) ? m_floatingObjects->set().last().get() : 0; |
| 1097 | 1115 |
| 1098 WordMeasurements wordMeasurements; | 1116 WordMeasurements wordMeasurements; |
| 1099 endOfLine = lineBreaker.nextLineBreak(resolver, layoutState.lineInfo(), | 1117 endOfLine = lineBreaker.nextLineBreak(resolver, layoutState.lineInfo(), |
| 1100 layoutTextInfo, wordMeasurements); | 1118 layoutTextInfo, wordMeasurements); |
| 1101 layoutTextInfo.m_lineBreakIterator.resetPriorContext(); | 1119 layoutTextInfo.m_lineBreakIterator.resetPriorContext(); |
| 1102 if (resolver.position().atEnd()) { | 1120 if (resolver.position().atEnd()) { |
| 1103 // FIXME: We shouldn't be creating any runs in nextLineBreak to begin with
! | 1121 // FIXME: We shouldn't be creating any runs in nextLineBreak to begin |
| 1104 // Once BidiRunList is separated from BidiResolver this will not be needed
. | 1122 // with! Once BidiRunList is separated from BidiResolver this will not be |
| 1123 // needed. |
| 1105 resolver.runs().deleteRuns(); | 1124 resolver.runs().deleteRuns(); |
| 1106 resolver | 1125 resolver.markCurrentRunEmpty(); // FIXME: This can probably be replaced |
| 1107 .markCurrentRunEmpty(); // FIXME: This can probably be replaced by an
ASSERT (or just removed). | 1126 // by an ASSERT (or just removed). |
| 1108 resolver.setPosition(InlineIterator(resolver.position().root(), 0, 0), 0); | 1127 resolver.setPosition(InlineIterator(resolver.position().root(), 0, 0), 0); |
| 1109 break; | 1128 break; |
| 1110 } | 1129 } |
| 1111 | 1130 |
| 1112 ASSERT(endOfLine != resolver.position()); | 1131 ASSERT(endOfLine != resolver.position()); |
| 1113 RootInlineBox* lineBox = nullptr; | 1132 RootInlineBox* lineBox = nullptr; |
| 1114 | 1133 |
| 1115 // This is a short-cut for empty lines. | 1134 // This is a short-cut for empty lines. |
| 1116 if (layoutState.lineInfo().isEmpty()) { | 1135 if (layoutState.lineInfo().isEmpty()) { |
| 1117 ASSERT(!paginationStrutFromDeletedLine); | 1136 ASSERT(!paginationStrutFromDeletedLine); |
| 1118 if (lastRootBox()) | 1137 if (lastRootBox()) |
| 1119 lastRootBox()->setLineBreakInfo(endOfLine.getLineLayoutItem(), | 1138 lastRootBox()->setLineBreakInfo(endOfLine.getLineLayoutItem(), |
| 1120 endOfLine.offset(), resolver.status()); | 1139 endOfLine.offset(), resolver.status()); |
| 1121 resolver.runs().deleteRuns(); | 1140 resolver.runs().deleteRuns(); |
| 1122 } else { | 1141 } else { |
| 1123 VisualDirectionOverride override = | 1142 VisualDirectionOverride override = |
| 1124 (styleToUse.rtlOrdering() == VisualOrder | 1143 (styleToUse.rtlOrdering() == VisualOrder |
| 1125 ? (styleToUse.direction() == LTR ? VisualLeftToRightOverride | 1144 ? (styleToUse.direction() == LTR ? VisualLeftToRightOverride |
| 1126 : VisualRightToLeftOverride) | 1145 : VisualRightToLeftOverride) |
| 1127 : NoVisualOverride); | 1146 : NoVisualOverride); |
| 1128 if (isNewUBAParagraph && styleToUse.unicodeBidi() == Plaintext && | 1147 if (isNewUBAParagraph && styleToUse.unicodeBidi() == Plaintext && |
| 1129 !resolver.context()->parent()) { | 1148 !resolver.context()->parent()) { |
| 1130 TextDirection direction = determinePlaintextDirectionality( | 1149 TextDirection direction = determinePlaintextDirectionality( |
| 1131 resolver.position().root(), resolver.position().getLineLayoutItem(), | 1150 resolver.position().root(), resolver.position().getLineLayoutItem(), |
| 1132 resolver.position().offset()); | 1151 resolver.position().offset()); |
| 1133 resolver.setStatus( | 1152 resolver.setStatus( |
| 1134 BidiStatus(direction, isOverride(styleToUse.unicodeBidi()))); | 1153 BidiStatus(direction, isOverride(styleToUse.unicodeBidi()))); |
| 1135 } | 1154 } |
| 1136 // FIXME: This ownership is reversed. We should own the BidiRunList and pa
ss it to createBidiRunsForLine. | 1155 // FIXME: This ownership is reversed. We should own the BidiRunList and |
| 1156 // pass it to createBidiRunsForLine. |
| 1137 BidiRunList<BidiRun>& bidiRuns = resolver.runs(); | 1157 BidiRunList<BidiRun>& bidiRuns = resolver.runs(); |
| 1138 constructBidiRunsForLine( | 1158 constructBidiRunsForLine( |
| 1139 resolver, bidiRuns, endOfLine, override, | 1159 resolver, bidiRuns, endOfLine, override, |
| 1140 layoutState.lineInfo().previousLineBrokeCleanly(), isNewUBAParagraph); | 1160 layoutState.lineInfo().previousLineBrokeCleanly(), isNewUBAParagraph); |
| 1141 ASSERT(resolver.position() == endOfLine); | 1161 ASSERT(resolver.position() == endOfLine); |
| 1142 | 1162 |
| 1143 BidiRun* trailingSpaceRun = resolver.trailingSpaceRun(); | 1163 BidiRun* trailingSpaceRun = resolver.trailingSpaceRun(); |
| 1144 | 1164 |
| 1145 if (bidiRuns.runCount() && lineBreaker.lineWasHyphenated()) | 1165 if (bidiRuns.runCount() && lineBreaker.lineWasHyphenated()) |
| 1146 bidiRuns.logicallyLastRun()->m_hasHyphen = true; | 1166 bidiRuns.logicallyLastRun()->m_hasHyphen = true; |
| 1147 | 1167 |
| 1148 // Now that the runs have been ordered, we create the line boxes. | 1168 // Now that the runs have been ordered, we create the line boxes. |
| 1149 // At the same time we figure out where border/padding/margin should be ap
plied for | 1169 // At the same time we figure out where border/padding/margin should be |
| 1170 // applied for |
| 1150 // inline flow boxes. | 1171 // inline flow boxes. |
| 1151 | 1172 |
| 1152 LayoutUnit oldLogicalHeight = logicalHeight(); | 1173 LayoutUnit oldLogicalHeight = logicalHeight(); |
| 1153 lineBox = createLineBoxesFromBidiRuns( | 1174 lineBox = createLineBoxesFromBidiRuns( |
| 1154 resolver.status().context->level(), bidiRuns, endOfLine, | 1175 resolver.status().context->level(), bidiRuns, endOfLine, |
| 1155 layoutState.lineInfo(), verticalPositionCache, trailingSpaceRun, | 1176 layoutState.lineInfo(), verticalPositionCache, trailingSpaceRun, |
| 1156 wordMeasurements); | 1177 wordMeasurements); |
| 1157 | 1178 |
| 1158 bidiRuns.deleteRuns(); | 1179 bidiRuns.deleteRuns(); |
| 1159 resolver | 1180 resolver.markCurrentRunEmpty(); // FIXME: This can probably be replaced |
| 1160 .markCurrentRunEmpty(); // FIXME: This can probably be replaced by an
ASSERT (or just removed). | 1181 // by an ASSERT (or just removed). |
| 1161 | 1182 |
| 1162 // If we decided to re-create the line due to pagination, we better have a
new line now. | 1183 // If we decided to re-create the line due to pagination, we better have a |
| 1184 // new line now. |
| 1163 ASSERT(lineBox || !paginationStrutFromDeletedLine); | 1185 ASSERT(lineBox || !paginationStrutFromDeletedLine); |
| 1164 | 1186 |
| 1165 if (lineBox) { | 1187 if (lineBox) { |
| 1166 lineBox->setLineBreakInfo(endOfLine.getLineLayoutItem(), | 1188 lineBox->setLineBreakInfo(endOfLine.getLineLayoutItem(), |
| 1167 endOfLine.offset(), resolver.status()); | 1189 endOfLine.offset(), resolver.status()); |
| 1168 if (paginated) { | 1190 if (paginated) { |
| 1169 if (paginationStrutFromDeletedLine) { | 1191 if (paginationStrutFromDeletedLine) { |
| 1170 // This is a line that got re-created because it got pushed to the n
ext fragmentainer, and there | 1192 // This is a line that got re-created because it got pushed to the |
| 1171 // were floats in the vicinity that affected the available width. Re
store the pagination info | 1193 // next fragmentainer, and there were floats in the vicinity that |
| 1172 // for this line. | 1194 // affected the available width. |
| 1195 // Restore the pagination info for this line. |
| 1173 lineBox->setIsFirstAfterPageBreak(true); | 1196 lineBox->setIsFirstAfterPageBreak(true); |
| 1174 lineBox->setPaginationStrut(paginationStrutFromDeletedLine); | 1197 lineBox->setPaginationStrut(paginationStrutFromDeletedLine); |
| 1175 paginationStrutFromDeletedLine = LayoutUnit(); | 1198 paginationStrutFromDeletedLine = LayoutUnit(); |
| 1176 } else { | 1199 } else { |
| 1177 LayoutUnit adjustment; | 1200 LayoutUnit adjustment; |
| 1178 adjustLinePositionForPagination(*lineBox, adjustment); | 1201 adjustLinePositionForPagination(*lineBox, adjustment); |
| 1179 if (adjustment) { | 1202 if (adjustment) { |
| 1180 LayoutUnit oldLineWidth = availableLogicalWidthForLine( | 1203 LayoutUnit oldLineWidth = availableLogicalWidthForLine( |
| 1181 oldLogicalHeight, layoutState.lineInfo().isFirstLine() | 1204 oldLogicalHeight, layoutState.lineInfo().isFirstLine() |
| 1182 ? IndentText | 1205 ? IndentText |
| 1183 : DoNotIndentText); | 1206 : DoNotIndentText); |
| 1184 lineBox->moveInBlockDirection(adjustment); | 1207 lineBox->moveInBlockDirection(adjustment); |
| 1185 if (availableLogicalWidthForLine( | 1208 if (availableLogicalWidthForLine( |
| 1186 oldLogicalHeight + adjustment, | 1209 oldLogicalHeight + adjustment, |
| 1187 layoutState.lineInfo().isFirstLine() | 1210 layoutState.lineInfo().isFirstLine() |
| 1188 ? IndentText | 1211 ? IndentText |
| 1189 : DoNotIndentText) != oldLineWidth) { | 1212 : DoNotIndentText) != oldLineWidth) { |
| 1190 // We have to delete this line, remove all floats that got added
, and let line layout | 1213 // We have to delete this line, remove all floats that got |
| 1191 // re-run. We had just calculated the pagination strut for this
line, and we need to | 1214 // added, and let line layout re-run. We had just calculated the |
| 1192 // stow it away, so that we can re-apply it when the new line ha
s been created. | 1215 // pagination strut for this line, and we need to stow it away, |
| 1216 // so that we can re-apply it when the new line has been created
. |
| 1193 paginationStrutFromDeletedLine = lineBox->paginationStrut(); | 1217 paginationStrutFromDeletedLine = lineBox->paginationStrut(); |
| 1194 ASSERT(paginationStrutFromDeletedLine); | 1218 ASSERT(paginationStrutFromDeletedLine); |
| 1195 // We're also going to assume that we're right after a page brea
k when re-creating this | 1219 // We're also going to assume that we're right after a page |
| 1196 // line, so it better be so. | 1220 // break when re-creating this line, so it better be so. |
| 1197 ASSERT(lineBox->isFirstAfterPageBreak()); | 1221 ASSERT(lineBox->isFirstAfterPageBreak()); |
| 1198 lineBox->deleteLine(); | 1222 lineBox->deleteLine(); |
| 1199 endOfLine = restartLayoutRunsAndFloatsInRange( | 1223 endOfLine = restartLayoutRunsAndFloatsInRange( |
| 1200 oldLogicalHeight, oldLogicalHeight + adjustment, | 1224 oldLogicalHeight, oldLogicalHeight + adjustment, |
| 1201 lastFloatFromPreviousLine, resolver, previousEndofLine); | 1225 lastFloatFromPreviousLine, resolver, previousEndofLine); |
| 1202 } else { | 1226 } else { |
| 1203 setLogicalHeight(lineBox->lineBottomWithLeading()); | 1227 setLogicalHeight(lineBox->lineBottomWithLeading()); |
| 1204 } | 1228 } |
| 1205 } | 1229 } |
| 1206 } | 1230 } |
| 1207 } | 1231 } |
| 1208 } | 1232 } |
| 1209 } | 1233 } |
| 1210 | 1234 |
| 1211 if (!paginationStrutFromDeletedLine) { | 1235 if (!paginationStrutFromDeletedLine) { |
| 1212 for (const auto& positionedObject : lineBreaker.positionedObjects()) { | 1236 for (const auto& positionedObject : lineBreaker.positionedObjects()) { |
| 1213 if (positionedObject.style()->isOriginalDisplayInlineType()) { | 1237 if (positionedObject.style()->isOriginalDisplayInlineType()) { |
| 1214 // Auto-positioend "inline" out-of-flow objects have already been posi
tioned, | 1238 // Auto-positioend "inline" out-of-flow objects have already been |
| 1215 // but if we're paginated, we need to update their position now, since
the line | 1239 // positioned, but if we're paginated, we need to update their |
| 1216 // they "belong" to may have been pushed by a pagination strut. | 1240 // position now, since the line they "belong" to may have been pushed |
| 1241 // by a pagination strut. |
| 1217 if (paginated && lineBox) | 1242 if (paginated && lineBox) |
| 1218 positionedObject.layer()->setStaticBlockPosition( | 1243 positionedObject.layer()->setStaticBlockPosition( |
| 1219 lineBox->lineTopWithLeading()); | 1244 lineBox->lineTopWithLeading()); |
| 1220 continue; | 1245 continue; |
| 1221 } | 1246 } |
| 1222 setStaticPositions(LineLayoutBlockFlow(this), positionedObject, | 1247 setStaticPositions(LineLayoutBlockFlow(this), positionedObject, |
| 1223 DoNotIndentText); | 1248 DoNotIndentText); |
| 1224 } | 1249 } |
| 1225 | 1250 |
| 1226 if (!layoutState.lineInfo().isEmpty()) | 1251 if (!layoutState.lineInfo().isEmpty()) |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1237 } | 1262 } |
| 1238 } | 1263 } |
| 1239 | 1264 |
| 1240 lineMidpointState.reset(); | 1265 lineMidpointState.reset(); |
| 1241 resolver.setPosition(endOfLine, numberOfIsolateAncestors(endOfLine)); | 1266 resolver.setPosition(endOfLine, numberOfIsolateAncestors(endOfLine)); |
| 1242 } | 1267 } |
| 1243 | 1268 |
| 1244 // The resolver runs should have been cleared, otherwise they're leaking. | 1269 // The resolver runs should have been cleared, otherwise they're leaking. |
| 1245 ASSERT(!resolver.runs().runCount()); | 1270 ASSERT(!resolver.runs().runCount()); |
| 1246 | 1271 |
| 1247 // In case we already adjusted the line positions during this layout to avoid
widows | 1272 // In case we already adjusted the line positions during this layout to avoid |
| 1248 // then we need to ignore the possibility of having a new widows situation. | 1273 // widows then we need to ignore the possibility of having a new widows |
| 1249 // Otherwise, we risk leaving empty containers which is against the block frag
mentation principles. | 1274 // situation. Otherwise, we risk leaving empty containers which is against the |
| 1275 // block fragmentation principles. |
| 1250 if (paginated && style()->widows() > 1 && !didBreakAtLineToAvoidWidow()) { | 1276 if (paginated && style()->widows() > 1 && !didBreakAtLineToAvoidWidow()) { |
| 1251 // Check the line boxes to make sure we didn't create unacceptable widows. | 1277 // Check the line boxes to make sure we didn't create unacceptable widows. |
| 1252 // However, we'll prioritize orphans - so nothing we do here should create | 1278 // However, we'll prioritize orphans - so nothing we do here should create |
| 1253 // a new orphan. | 1279 // a new orphan. |
| 1254 | 1280 |
| 1255 RootInlineBox* lineBox = lastRootBox(); | 1281 RootInlineBox* lineBox = lastRootBox(); |
| 1256 | 1282 |
| 1257 // Count from the end of the block backwards, to see how many hanging | 1283 // Count from the end of the block backwards, to see how many hanging |
| 1258 // lines we have. | 1284 // lines we have. |
| 1259 RootInlineBox* firstLineInBlock = firstRootBox(); | 1285 RootInlineBox* firstLineInBlock = firstRootBox(); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1278 | 1304 |
| 1279 // Count the number of lines in the previous page. | 1305 // Count the number of lines in the previous page. |
| 1280 lineBox = lineBox->prevRootBox(); | 1306 lineBox = lineBox->prevRootBox(); |
| 1281 int numLinesInPreviousPage = 1; | 1307 int numLinesInPreviousPage = 1; |
| 1282 while (lineBox && lineBox != firstLineInBlock && | 1308 while (lineBox && lineBox != firstLineInBlock && |
| 1283 !lineBox->isFirstAfterPageBreak()) { | 1309 !lineBox->isFirstAfterPageBreak()) { |
| 1284 ++numLinesInPreviousPage; | 1310 ++numLinesInPreviousPage; |
| 1285 lineBox = lineBox->prevRootBox(); | 1311 lineBox = lineBox->prevRootBox(); |
| 1286 } | 1312 } |
| 1287 | 1313 |
| 1288 // If there was an explicit value for orphans, respect that. If not, we st
ill | 1314 // If there was an explicit value for orphans, respect that. If not, we |
| 1289 // shouldn't create a situation where we make an orphan bigger than the in
itial value. | 1315 // still shouldn't create a situation where we make an orphan bigger than |
| 1290 // This means that setting widows implies we also care about orphans, but
given | 1316 // the initial value. This means that setting widows implies we also care |
| 1291 // the specification says the initial orphan value is non-zero, this is ok
. The | 1317 // about orphans, but given the specification says the initial orphan |
| 1292 // author is always free to set orphans explicitly as well. | 1318 // value is non-zero, this is ok. The author is always free to set orphans |
| 1319 // explicitly as well. |
| 1293 int orphans = style()->orphans(); | 1320 int orphans = style()->orphans(); |
| 1294 int numLinesAvailable = numLinesInPreviousPage - orphans; | 1321 int numLinesAvailable = numLinesInPreviousPage - orphans; |
| 1295 if (numLinesAvailable <= 0) | 1322 if (numLinesAvailable <= 0) |
| 1296 return; | 1323 return; |
| 1297 | 1324 |
| 1298 int numLinesToTake = std::min(numLinesAvailable, numLinesNeeded); | 1325 int numLinesToTake = std::min(numLinesAvailable, numLinesNeeded); |
| 1299 // Wind back from our first widowed line. | 1326 // Wind back from our first widowed line. |
| 1300 lineBox = currentFirstLineOfNewPage; | 1327 lineBox = currentFirstLineOfNewPage; |
| 1301 for (int i = 0; i < numLinesToTake; ++i) | 1328 for (int i = 0; i < numLinesToTake; ++i) |
| 1302 lineBox = lineBox->prevRootBox(); | 1329 lineBox = lineBox->prevRootBox(); |
| 1303 | 1330 |
| 1304 // We now want to break at this line. Remember for next layout and trigger
relayout. | 1331 // We now want to break at this line. Remember for next layout and trigger |
| 1332 // relayout. |
| 1305 setBreakAtLineToAvoidWidow(lineCount(lineBox)); | 1333 setBreakAtLineToAvoidWidow(lineCount(lineBox)); |
| 1306 markLinesDirtyInBlockRange(lastRootBox()->lineBottomWithLeading(), | 1334 markLinesDirtyInBlockRange(lastRootBox()->lineBottomWithLeading(), |
| 1307 lineBox->lineBottomWithLeading(), lineBox); | 1335 lineBox->lineBottomWithLeading(), lineBox); |
| 1308 } | 1336 } |
| 1309 } | 1337 } |
| 1310 | 1338 |
| 1311 clearDidBreakAtLineToAvoidWidow(); | 1339 clearDidBreakAtLineToAvoidWidow(); |
| 1312 } | 1340 } |
| 1313 | 1341 |
| 1314 void LayoutBlockFlow::linkToEndLineIfNeeded(LineLayoutState& layoutState) { | 1342 void LayoutBlockFlow::linkToEndLineIfNeeded(LineLayoutState& layoutState) { |
| 1315 if (layoutState.endLine()) { | 1343 if (layoutState.endLine()) { |
| 1316 if (layoutState.endLineMatched()) { | 1344 if (layoutState.endLineMatched()) { |
| 1317 bool paginated = | 1345 bool paginated = |
| 1318 view()->layoutState() && view()->layoutState()->isPaginated(); | 1346 view()->layoutState() && view()->layoutState()->isPaginated(); |
| 1319 // Attach all the remaining lines, and then adjust their y-positions as ne
eded. | 1347 // Attach all the remaining lines, and then adjust their y-positions as |
| 1348 // needed. |
| 1320 LayoutUnit delta = logicalHeight() - layoutState.endLineLogicalTop(); | 1349 LayoutUnit delta = logicalHeight() - layoutState.endLineLogicalTop(); |
| 1321 for (RootInlineBox* line = layoutState.endLine(); line; | 1350 for (RootInlineBox* line = layoutState.endLine(); line; |
| 1322 line = line->nextRootBox()) { | 1351 line = line->nextRootBox()) { |
| 1323 line->attachLine(); | 1352 line->attachLine(); |
| 1324 if (paginated) { | 1353 if (paginated) { |
| 1325 delta -= line->paginationStrut(); | 1354 delta -= line->paginationStrut(); |
| 1326 adjustLinePositionForPagination(*line, delta); | 1355 adjustLinePositionForPagination(*line, delta); |
| 1327 } | 1356 } |
| 1328 if (delta) | 1357 if (delta) |
| 1329 line->moveInBlockDirection(delta); | 1358 line->moveInBlockDirection(delta); |
| 1330 if (Vector<LayoutBox*>* cleanLineFloats = line->floatsPtr()) { | 1359 if (Vector<LayoutBox*>* cleanLineFloats = line->floatsPtr()) { |
| 1331 for (auto* box : *cleanLineFloats) { | 1360 for (auto* box : *cleanLineFloats) { |
| 1332 FloatingObject* floatingObject = insertFloatingObject(*box); | 1361 FloatingObject* floatingObject = insertFloatingObject(*box); |
| 1333 ASSERT(!floatingObject->originatingLine()); | 1362 ASSERT(!floatingObject->originatingLine()); |
| 1334 floatingObject->setOriginatingLine(line); | 1363 floatingObject->setOriginatingLine(line); |
| 1335 setLogicalHeight(logicalTopForChild(*box) - | 1364 setLogicalHeight(logicalTopForChild(*box) - |
| 1336 marginBeforeForChild(*box) + delta); | 1365 marginBeforeForChild(*box) + delta); |
| 1337 positionNewFloats(); | 1366 positionNewFloats(); |
| 1338 } | 1367 } |
| 1339 } | 1368 } |
| 1340 } | 1369 } |
| 1341 setLogicalHeight(lastRootBox()->lineBottomWithLeading()); | 1370 setLogicalHeight(lastRootBox()->lineBottomWithLeading()); |
| 1342 } else { | 1371 } else { |
| 1343 // Delete all the remaining lines. | 1372 // Delete all the remaining lines. |
| 1344 deleteLineRange(layoutState, layoutState.endLine()); | 1373 deleteLineRange(layoutState, layoutState.endLine()); |
| 1345 } | 1374 } |
| 1346 } | 1375 } |
| 1347 | 1376 |
| 1348 // In case we have a float on the last line, it might not be positioned up to
now. | 1377 // In case we have a float on the last line, it might not be positioned up to |
| 1349 // This has to be done before adding in the bottom border/padding, or the floa
t will | 1378 // now. This has to be done before adding in the bottom border/padding, or the |
| 1379 // float will |
| 1350 // include the padding incorrectly. -dwh | 1380 // include the padding incorrectly. -dwh |
| 1351 if (positionNewFloats() && lastRootBox()) | 1381 if (positionNewFloats() && lastRootBox()) |
| 1352 appendFloatsToLastLine(layoutState, InlineIterator(), InlineBidiResolver(), | 1382 appendFloatsToLastLine(layoutState, InlineIterator(), InlineBidiResolver(), |
| 1353 BidiStatus()); | 1383 BidiStatus()); |
| 1354 } | 1384 } |
| 1355 | 1385 |
| 1356 void LayoutBlockFlow::markDirtyFloatsForPaintInvalidation( | 1386 void LayoutBlockFlow::markDirtyFloatsForPaintInvalidation( |
| 1357 Vector<FloatWithRect>& floats) { | 1387 Vector<FloatWithRect>& floats) { |
| 1358 size_t floatCount = floats.size(); | 1388 size_t floatCount = floats.size(); |
| 1359 // Floats that did not have layout did not paint invalidations when we laid th
em out. They would have | 1389 // Floats that did not have layout did not paint invalidations when we laid |
| 1360 // painted by now if they had moved, but if they stayed at (0, 0), they still
need to be | 1390 // them out. They would have painted by now if they had moved, but if they |
| 1361 // painted. | 1391 // stayed at (0, 0), they still need to be painted. |
| 1362 for (size_t i = 0; i < floatCount; ++i) { | 1392 for (size_t i = 0; i < floatCount; ++i) { |
| 1363 LayoutBox* f = floats[i].object; | 1393 LayoutBox* f = floats[i].object; |
| 1364 if (!floats[i].everHadLayout) { | 1394 if (!floats[i].everHadLayout) { |
| 1365 if (!f->location().x() && !f->location().y()) | 1395 if (!f->location().x() && !f->location().y()) |
| 1366 f->setShouldDoFullPaintInvalidation(); | 1396 f->setShouldDoFullPaintInvalidation(); |
| 1367 } | 1397 } |
| 1368 insertFloatingObject(*f); | 1398 insertFloatingObject(*f); |
| 1369 } | 1399 } |
| 1370 positionNewFloats(); | 1400 positionNewFloats(); |
| 1371 } | 1401 } |
| 1372 | 1402 |
| 1403 // InlineMinMaxIterator is a class that will iterate over all layout objects |
| 1404 // that contribute to inline min/max width calculations. Note the following |
| 1405 // about the way it walks: |
| 1406 // (1) Positioned content is skipped (since it does not contribute to min/max |
| 1407 // width of a block) |
| 1408 // (2) We do not drill into the children of floats or replaced elements, since |
| 1409 // you can't break in the middle of such an element. |
| 1410 // (3) Inline flows (e.g., <a>, <span>, <i>) are walked twice, since each side |
| 1411 // can have distinct borders/margin/padding that contribute to the min/max |
| 1412 // width. |
| 1373 struct InlineMinMaxIterator { | 1413 struct InlineMinMaxIterator { |
| 1374 /* InlineMinMaxIterator is a class that will iterate over all layout objects t
hat contribute to | |
| 1375 inline min/max width calculations. Note the following about the way it walks
: | |
| 1376 (1) Positioned content is skipped (since it does not contribute to min/max wi
dth of a block) | |
| 1377 (2) We do not drill into the children of floats or replaced elements, since y
ou can't break | |
| 1378 in the middle of such an element. | |
| 1379 (3) Inline flows (e.g., <a>, <span>, <i>) are walked twice, since each side c
an have | |
| 1380 distinct borders/margin/padding that contribute to the min/max width. | |
| 1381 */ | |
| 1382 LayoutObject* parent; | 1414 LayoutObject* parent; |
| 1383 LayoutObject* current; | 1415 LayoutObject* current; |
| 1384 bool endOfInline; | 1416 bool endOfInline; |
| 1385 | 1417 |
| 1386 InlineMinMaxIterator(LayoutObject* p, bool end = false) | 1418 InlineMinMaxIterator(LayoutObject* p, bool end = false) |
| 1387 : parent(p), current(p), endOfInline(end) {} | 1419 : parent(p), current(p), endOfInline(end) {} |
| 1388 | 1420 |
| 1389 LayoutObject* next(); | 1421 LayoutObject* next(); |
| 1390 }; | 1422 }; |
| 1391 | 1423 |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1481 constructTextRun(font, &trailingWhitespaceChar, 1, text->styleRef(), | 1513 constructTextRun(font, &trailingWhitespaceChar, 1, text->styleRef(), |
| 1482 text->style()->direction()); | 1514 text->style()->direction()); |
| 1483 float spaceWidth = font.width(run); | 1515 float spaceWidth = font.width(run); |
| 1484 inlineMax -= LayoutUnit::fromFloatCeil( | 1516 inlineMax -= LayoutUnit::fromFloatCeil( |
| 1485 spaceWidth + font.getFontDescription().wordSpacing()); | 1517 spaceWidth + font.getFontDescription().wordSpacing()); |
| 1486 if (inlineMin > inlineMax) | 1518 if (inlineMin > inlineMax) |
| 1487 inlineMin = inlineMax; | 1519 inlineMin = inlineMax; |
| 1488 } | 1520 } |
| 1489 } | 1521 } |
| 1490 | 1522 |
| 1491 // When converting between floating point and LayoutUnits we risk losing precisi
on | 1523 // When converting between floating point and LayoutUnits we risk losing |
| 1492 // with each conversion. When this occurs while accumulating our preferred width
s, | 1524 // precision with each conversion. When this occurs while accumulating our |
| 1493 // we can wind up with a line width that's larger than our maxPreferredWidth due
to | 1525 // preferred widths, we can wind up with a line width that's larger than our |
| 1494 // pure float accumulation. | 1526 // maxPreferredWidth due to pure float accumulation. |
| 1495 static inline LayoutUnit adjustFloatForSubPixelLayout(float value) { | 1527 static inline LayoutUnit adjustFloatForSubPixelLayout(float value) { |
| 1496 return LayoutUnit::fromFloatCeil(value); | 1528 return LayoutUnit::fromFloatCeil(value); |
| 1497 } | 1529 } |
| 1498 | 1530 |
| 1499 static inline void adjustMinMaxForInlineFlow(LayoutObject* child, | 1531 static inline void adjustMinMaxForInlineFlow(LayoutObject* child, |
| 1500 bool endOfInline, | 1532 bool endOfInline, |
| 1501 LayoutUnit& childMin, | 1533 LayoutUnit& childMin, |
| 1502 LayoutUnit& childMax) { | 1534 LayoutUnit& childMax) { |
| 1503 // Add in padding/border/margin from the appropriate side of | 1535 // Add in padding/border/margin from the appropriate side of |
| 1504 // the element. | 1536 // the element. |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1517 LayoutUnit margins; | 1549 LayoutUnit margins; |
| 1518 if (startMargin.isFixed()) | 1550 if (startMargin.isFixed()) |
| 1519 margins += adjustFloatForSubPixelLayout(startMargin.value()); | 1551 margins += adjustFloatForSubPixelLayout(startMargin.value()); |
| 1520 if (endMargin.isFixed()) | 1552 if (endMargin.isFixed()) |
| 1521 margins += adjustFloatForSubPixelLayout(endMargin.value()); | 1553 margins += adjustFloatForSubPixelLayout(endMargin.value()); |
| 1522 childMin += margins; | 1554 childMin += margins; |
| 1523 childMax += margins; | 1555 childMax += margins; |
| 1524 } | 1556 } |
| 1525 | 1557 |
| 1526 // FIXME: This function should be broken into something less monolithic. | 1558 // FIXME: This function should be broken into something less monolithic. |
| 1527 // FIXME: The main loop here is very similar to LineBreaker::nextSegmentBreak. T
hey can probably reuse code. | 1559 // FIXME: The main loop here is very similar to LineBreaker::nextSegmentBreak. |
| 1560 // They can probably reuse code. |
| 1528 DISABLE_CFI_PERF | 1561 DISABLE_CFI_PERF |
| 1529 void LayoutBlockFlow::computeInlinePreferredLogicalWidths( | 1562 void LayoutBlockFlow::computeInlinePreferredLogicalWidths( |
| 1530 LayoutUnit& minLogicalWidth, | 1563 LayoutUnit& minLogicalWidth, |
| 1531 LayoutUnit& maxLogicalWidth) { | 1564 LayoutUnit& maxLogicalWidth) { |
| 1532 LayoutUnit inlineMax; | 1565 LayoutUnit inlineMax; |
| 1533 LayoutUnit inlineMin; | 1566 LayoutUnit inlineMin; |
| 1534 | 1567 |
| 1535 const ComputedStyle& styleToUse = styleRef(); | 1568 const ComputedStyle& styleToUse = styleRef(); |
| 1536 LayoutBlock* containingBlock = this->containingBlock(); | 1569 LayoutBlock* containingBlock = this->containingBlock(); |
| 1537 LayoutUnit cw = | 1570 LayoutUnit cw = |
| 1538 containingBlock ? containingBlock->contentLogicalWidth() : LayoutUnit(); | 1571 containingBlock ? containingBlock->contentLogicalWidth() : LayoutUnit(); |
| 1539 | 1572 |
| 1540 // If we are at the start of a line, we want to ignore all white-space. | 1573 // If we are at the start of a line, we want to ignore all white-space. |
| 1541 // Also strip spaces if we previously had text that ended in a trailing space. | 1574 // Also strip spaces if we previously had text that ended in a trailing space. |
| 1542 bool stripFrontSpaces = true; | 1575 bool stripFrontSpaces = true; |
| 1543 LayoutObject* trailingSpaceChild = nullptr; | 1576 LayoutObject* trailingSpaceChild = nullptr; |
| 1544 | 1577 |
| 1545 // Firefox and Opera will allow a table cell to grow to fit an image inside it
under | 1578 // Firefox and Opera will allow a table cell to grow to fit an image inside it |
| 1546 // very specific cirucumstances (in order to match common WinIE layouts). | 1579 // under very specific cirucumstances (in order to match common WinIE |
| 1547 // Not supporting the quirk has caused us to mis-layout some real sites. (See
Bugzilla 10517.) | 1580 // layouts). Not supporting the quirk has caused us to mis-layout some real |
| 1581 // sites. (See Bugzilla 10517.) |
| 1548 bool allowImagesToBreak = !document().inQuirksMode() || !isTableCell() || | 1582 bool allowImagesToBreak = !document().inQuirksMode() || !isTableCell() || |
| 1549 !styleToUse.logicalWidth().isIntrinsicOrAuto(); | 1583 !styleToUse.logicalWidth().isIntrinsicOrAuto(); |
| 1550 | 1584 |
| 1551 bool autoWrap, oldAutoWrap; | 1585 bool autoWrap, oldAutoWrap; |
| 1552 autoWrap = oldAutoWrap = styleToUse.autoWrap(); | 1586 autoWrap = oldAutoWrap = styleToUse.autoWrap(); |
| 1553 | 1587 |
| 1554 InlineMinMaxIterator childIterator(this); | 1588 InlineMinMaxIterator childIterator(this); |
| 1555 | 1589 |
| 1556 // Only gets added to the max preffered width once. | 1590 // Only gets added to the max preffered width once. |
| 1557 bool addedTextIndent = false; | 1591 bool addedTextIndent = false; |
| 1558 // Signals the text indent was more negative than the min preferred width | 1592 // Signals the text indent was more negative than the min preferred width |
| 1559 bool hasRemainingNegativeTextIndent = false; | 1593 bool hasRemainingNegativeTextIndent = false; |
| 1560 | 1594 |
| 1561 LayoutUnit textIndent = minimumValueForLength(styleToUse.textIndent(), cw); | 1595 LayoutUnit textIndent = minimumValueForLength(styleToUse.textIndent(), cw); |
| 1562 LayoutObject* prevFloat = nullptr; | 1596 LayoutObject* prevFloat = nullptr; |
| 1563 bool isPrevChildInlineFlow = false; | 1597 bool isPrevChildInlineFlow = false; |
| 1564 bool shouldBreakLineAfterText = false; | 1598 bool shouldBreakLineAfterText = false; |
| 1565 while (LayoutObject* child = childIterator.next()) { | 1599 while (LayoutObject* child = childIterator.next()) { |
| 1566 autoWrap = child->isAtomicInlineLevel() | 1600 autoWrap = child->isAtomicInlineLevel() |
| 1567 ? child->parent()->style()->autoWrap() | 1601 ? child->parent()->style()->autoWrap() |
| 1568 : child->style()->autoWrap(); | 1602 : child->style()->autoWrap(); |
| 1569 | 1603 |
| 1570 if (!child->isBR()) { | 1604 if (!child->isBR()) { |
| 1571 // Step One: determine whether or not we need to go ahead and | 1605 // Step One: determine whether or not we need to go ahead and |
| 1572 // terminate our current line. Each discrete chunk can become | 1606 // terminate our current line. Each discrete chunk can become |
| 1573 // the new min-width, if it is the widest chunk seen so far, and | 1607 // the new min-width, if it is the widest chunk seen so far, and |
| 1574 // it can also become the max-width. | 1608 // it can also become the max-width. |
| 1575 | 1609 // |
| 1576 // Children fall into three categories: | 1610 // Children fall into three categories: |
| 1577 // (1) An inline flow object. These objects always have a min/max of 0, | 1611 // (1) An inline flow object. These objects always have a min/max of 0, |
| 1578 // and are included in the iteration solely so that their margins can | 1612 // and are included in the iteration solely so that their margins can |
| 1579 // be added in. | 1613 // be added in. |
| 1580 // | 1614 // |
| 1581 // (2) An inline non-text non-flow object, e.g., an inline replaced elemen
t. | 1615 // (2) An inline non-text non-flow object, e.g., an inline replaced |
| 1582 // These objects can always be on a line by themselves, so in this situati
on | 1616 // element. These objects can always be on a line by themselves, so in |
| 1583 // we need to go ahead and break the current line, and then add in our own | 1617 // this situation we need to go ahead and break the current line, and |
| 1584 // margins and min/max width on its own line, and then terminate the line. | 1618 // then add in our own margins and min/max width on its own line, and |
| 1619 // then terminate the line. |
| 1585 // | 1620 // |
| 1586 // (3) A text object. Text runs can have breakable characters at the start
, | 1621 // (3) A text object. Text runs can have breakable characters at the |
| 1587 // the middle or the end. They may also lose whitespace off the front if | 1622 // start, the middle or the end. They may also lose whitespace off the |
| 1588 // we're already ignoring whitespace. In order to compute accurate min-wid
th | 1623 // front if we're already ignoring whitespace. In order to compute |
| 1589 // information, we need three pieces of information. | 1624 // accurate min-width information, we need three pieces of |
| 1590 // (a) the min-width of the first non-breakable run. Should be 0 if the te
xt string | 1625 // information. |
| 1591 // starts with whitespace. | 1626 // (a) the min-width of the first non-breakable run. Should be 0 if |
| 1592 // (b) the min-width of the last non-breakable run. Should be 0 if the tex
t string | 1627 // the text string starts with whitespace. |
| 1593 // ends with whitespace. | 1628 // (b) the min-width of the last non-breakable run. Should be 0 if the |
| 1594 // (c) the min/max width of the string (trimmed for whitespace). | 1629 // text string ends with whitespace. |
| 1630 // (c) the min/max width of the string (trimmed for whitespace). |
| 1595 // | 1631 // |
| 1596 // If the text string starts with whitespace, then we need to go ahead and | 1632 // If the text string starts with whitespace, then we need to go ahead and |
| 1597 // terminate our current line (unless we're already in a whitespace stripp
ing | 1633 // terminate our current line (unless we're already in a whitespace |
| 1598 // mode. | 1634 // stripping mode. |
| 1599 // | 1635 // |
| 1600 // If the text string has a breakable character in the middle, but didn't
start | 1636 // If the text string has a breakable character in the middle, but didn't |
| 1601 // with whitespace, then we add the width of the first non-breakable run a
nd | 1637 // start with whitespace, then we add the width of the first non-breakable |
| 1602 // then end the current line. We then need to use the intermediate min/max
width | 1638 // run and then end the current line. We then need to use the intermediate |
| 1603 // values (if any of them are larger than our current min/max). We then lo
ok at | 1639 // min/max width values (if any of them are larger than our current |
| 1604 // the width of the last non-breakable run and use that to start a new lin
e | 1640 // min/max). We then look at the width of the last non-breakable run and |
| 1605 // (unless we end in whitespace). | 1641 // use that to start a new line (unless we end in whitespace). |
| 1606 LayoutUnit childMin; | 1642 LayoutUnit childMin; |
| 1607 LayoutUnit childMax; | 1643 LayoutUnit childMax; |
| 1608 | 1644 |
| 1609 if (!child->isText()) { | 1645 if (!child->isText()) { |
| 1610 // Case (1) and (2). Inline replaced and inline flow elements. | 1646 // Case (1) and (2). Inline replaced and inline flow elements. |
| 1611 if (child->isLayoutInline()) { | 1647 if (child->isLayoutInline()) { |
| 1612 adjustMinMaxForInlineFlow(child, childIterator.endOfInline, childMin, | 1648 adjustMinMaxForInlineFlow(child, childIterator.endOfInline, childMin, |
| 1613 childMax); | 1649 childMax); |
| 1614 inlineMin += childMin; | 1650 inlineMin += childMin; |
| 1615 inlineMax += childMax; | 1651 inlineMax += childMax; |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1645 } | 1681 } |
| 1646 | 1682 |
| 1647 bool canBreakReplacedElement = !child->isImage() || allowImagesToBreak; | 1683 bool canBreakReplacedElement = !child->isImage() || allowImagesToBreak; |
| 1648 if ((canBreakReplacedElement && (autoWrap || oldAutoWrap) && | 1684 if ((canBreakReplacedElement && (autoWrap || oldAutoWrap) && |
| 1649 (!isPrevChildInlineFlow || shouldBreakLineAfterText)) || | 1685 (!isPrevChildInlineFlow || shouldBreakLineAfterText)) || |
| 1650 clearPreviousFloat) { | 1686 clearPreviousFloat) { |
| 1651 minLogicalWidth = std::max(minLogicalWidth, inlineMin); | 1687 minLogicalWidth = std::max(minLogicalWidth, inlineMin); |
| 1652 inlineMin = LayoutUnit(); | 1688 inlineMin = LayoutUnit(); |
| 1653 } | 1689 } |
| 1654 | 1690 |
| 1655 // If we're supposed to clear the previous float, then terminate maxwidt
h as well. | 1691 // If we're supposed to clear the previous float, then terminate |
| 1692 // maxwidth as well. |
| 1656 if (clearPreviousFloat) { | 1693 if (clearPreviousFloat) { |
| 1657 maxLogicalWidth = std::max(maxLogicalWidth, inlineMax); | 1694 maxLogicalWidth = std::max(maxLogicalWidth, inlineMax); |
| 1658 inlineMax = LayoutUnit(); | 1695 inlineMax = LayoutUnit(); |
| 1659 } | 1696 } |
| 1660 | 1697 |
| 1661 // Add in text-indent. This is added in only once. | 1698 // Add in text-indent. This is added in only once. |
| 1662 if (!addedTextIndent && !child->isFloating()) { | 1699 if (!addedTextIndent && !child->isFloating()) { |
| 1663 childMin += textIndent; | 1700 childMin += textIndent; |
| 1664 childMax += textIndent; | 1701 childMax += textIndent; |
| 1665 | 1702 |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1715 bool hasBreakableChar, hasBreak; | 1752 bool hasBreakableChar, hasBreak; |
| 1716 LayoutUnit firstLineMinWidth, lastLineMinWidth; | 1753 LayoutUnit firstLineMinWidth, lastLineMinWidth; |
| 1717 bool hasBreakableStart, hasBreakableEnd; | 1754 bool hasBreakableStart, hasBreakableEnd; |
| 1718 LayoutUnit firstLineMaxWidth, lastLineMaxWidth; | 1755 LayoutUnit firstLineMaxWidth, lastLineMaxWidth; |
| 1719 t->trimmedPrefWidths(inlineMax, firstLineMinWidth, hasBreakableStart, | 1756 t->trimmedPrefWidths(inlineMax, firstLineMinWidth, hasBreakableStart, |
| 1720 lastLineMinWidth, hasBreakableEnd, | 1757 lastLineMinWidth, hasBreakableEnd, |
| 1721 hasBreakableChar, hasBreak, firstLineMaxWidth, | 1758 hasBreakableChar, hasBreak, firstLineMaxWidth, |
| 1722 lastLineMaxWidth, childMin, childMax, | 1759 lastLineMaxWidth, childMin, childMax, |
| 1723 stripFrontSpaces, styleToUse.direction()); | 1760 stripFrontSpaces, styleToUse.direction()); |
| 1724 | 1761 |
| 1725 // This text object will not be laid out, but it may still provide a bre
aking opportunity. | 1762 // This text object will not be laid out, but it may still provide a |
| 1763 // breaking opportunity. |
| 1726 if (!hasBreak && !childMax) { | 1764 if (!hasBreak && !childMax) { |
| 1727 if (autoWrap && (hasBreakableStart || hasBreakableEnd)) { | 1765 if (autoWrap && (hasBreakableStart || hasBreakableEnd)) { |
| 1728 minLogicalWidth = std::max(minLogicalWidth, inlineMin); | 1766 minLogicalWidth = std::max(minLogicalWidth, inlineMin); |
| 1729 inlineMin = LayoutUnit(); | 1767 inlineMin = LayoutUnit(); |
| 1730 } | 1768 } |
| 1731 continue; | 1769 continue; |
| 1732 } | 1770 } |
| 1733 | 1771 |
| 1734 if (stripFrontSpaces) | 1772 if (stripFrontSpaces) |
| 1735 trailingSpaceChild = child; | 1773 trailingSpaceChild = child; |
| 1736 else | 1774 else |
| 1737 trailingSpaceChild = nullptr; | 1775 trailingSpaceChild = nullptr; |
| 1738 | 1776 |
| 1739 // Add in text-indent. This is added in only once. | 1777 // Add in text-indent. This is added in only once. |
| 1740 LayoutUnit ti; | 1778 LayoutUnit ti; |
| 1741 if (!addedTextIndent || hasRemainingNegativeTextIndent) { | 1779 if (!addedTextIndent || hasRemainingNegativeTextIndent) { |
| 1742 ti = textIndent; | 1780 ti = textIndent; |
| 1743 childMin += ti; | 1781 childMin += ti; |
| 1744 firstLineMinWidth += ti; | 1782 firstLineMinWidth += ti; |
| 1745 | 1783 |
| 1746 // It the text indent negative and larger than the child minimum, we r
e-use the remainder | 1784 // It the text indent negative and larger than the child minimum, we |
| 1747 // in future minimum calculations, but using the negative value again
on the maximum | 1785 // re-use the remainder in future minimum calculations, but using the |
| 1748 // will lead to under-counting the max pref width. | 1786 // negative value again on the maximum will lead to under-counting the |
| 1787 // max pref width. |
| 1749 if (!addedTextIndent) { | 1788 if (!addedTextIndent) { |
| 1750 childMax += ti; | 1789 childMax += ti; |
| 1751 firstLineMaxWidth += ti; | 1790 firstLineMaxWidth += ti; |
| 1752 addedTextIndent = true; | 1791 addedTextIndent = true; |
| 1753 } | 1792 } |
| 1754 | 1793 |
| 1755 if (childMin < LayoutUnit()) { | 1794 if (childMin < LayoutUnit()) { |
| 1756 textIndent = childMin; | 1795 textIndent = childMin; |
| 1757 hasRemainingNegativeTextIndent = true; | 1796 hasRemainingNegativeTextIndent = true; |
| 1758 } | 1797 } |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1848 bool isFullLayout = !firstLineBox() || selfNeedsLayout() || relayoutChildren; | 1887 bool isFullLayout = !firstLineBox() || selfNeedsLayout() || relayoutChildren; |
| 1849 LineLayoutState layoutState(isFullLayout); | 1888 LineLayoutState layoutState(isFullLayout); |
| 1850 | 1889 |
| 1851 if (isFullLayout) { | 1890 if (isFullLayout) { |
| 1852 // Ensure the old line boxes will be erased. | 1891 // Ensure the old line boxes will be erased. |
| 1853 if (firstLineBox()) | 1892 if (firstLineBox()) |
| 1854 setShouldDoFullPaintInvalidation(); | 1893 setShouldDoFullPaintInvalidation(); |
| 1855 lineBoxes()->deleteLineBoxes(); | 1894 lineBoxes()->deleteLineBoxes(); |
| 1856 } | 1895 } |
| 1857 | 1896 |
| 1858 // Text truncation kicks in if overflow isn't visible and text-overflow isn't
'clip'. If this is | 1897 // Text truncation kicks in if overflow isn't visible and text-overflow isn't |
| 1859 // an anonymous block, we have to examine the parent. | 1898 // 'clip'. If this is an anonymous block, we have to examine the parent. |
| 1860 // FIXME: CSS3 says that descendants that are clipped must also know how to tr
uncate. This is insanely | 1899 // FIXME: CSS3 says that descendants that are clipped must also know how to |
| 1861 // difficult to figure out in general (especially in the middle of doing layou
t), so we only handle the | 1900 // truncate. This is insanely difficult to figure out in general (especially |
| 1862 // simple case of an anonymous block truncating when its parent is clipped. | 1901 // in the middle of doing layout), so we only handle the simple case of an |
| 1902 // anonymous block truncating when its parent is clipped. |
| 1863 bool hasTextOverflow = shouldTruncateOverflowingText(this); | 1903 bool hasTextOverflow = shouldTruncateOverflowingText(this); |
| 1864 | 1904 |
| 1865 // Walk all the lines and delete our ellipsis line boxes if they exist. | 1905 // Walk all the lines and delete our ellipsis line boxes if they exist. |
| 1866 if (hasTextOverflow) | 1906 if (hasTextOverflow) |
| 1867 deleteEllipsisLineBoxes(); | 1907 deleteEllipsisLineBoxes(); |
| 1868 | 1908 |
| 1869 if (firstChild()) { | 1909 if (firstChild()) { |
| 1870 for (InlineWalker walker(LineLayoutBlockFlow(this)); !walker.atEnd(); | 1910 for (InlineWalker walker(LineLayoutBlockFlow(this)); !walker.atEnd(); |
| 1871 walker.advance()) { | 1911 walker.advance()) { |
| 1872 LayoutObject* o = walker.current().layoutObject(); | 1912 LayoutObject* o = walker.current().layoutObject(); |
| 1873 | 1913 |
| 1874 if (!layoutState.hasInlineChild() && o->isInline()) | 1914 if (!layoutState.hasInlineChild() && o->isInline()) |
| 1875 layoutState.setHasInlineChild(true); | 1915 layoutState.setHasInlineChild(true); |
| 1876 | 1916 |
| 1877 if (o->isAtomicInlineLevel() || o->isFloating() || | 1917 if (o->isAtomicInlineLevel() || o->isFloating() || |
| 1878 o->isOutOfFlowPositioned()) { | 1918 o->isOutOfFlowPositioned()) { |
| 1879 LayoutBox* box = toLayoutBox(o); | 1919 LayoutBox* box = toLayoutBox(o); |
| 1880 box->setMayNeedPaintInvalidation(); | 1920 box->setMayNeedPaintInvalidation(); |
| 1881 | 1921 |
| 1882 updateBlockChildDirtyBitsBeforeLayout(relayoutChildren, *box); | 1922 updateBlockChildDirtyBitsBeforeLayout(relayoutChildren, *box); |
| 1883 | 1923 |
| 1884 if (o->isOutOfFlowPositioned()) { | 1924 if (o->isOutOfFlowPositioned()) { |
| 1885 o->containingBlock()->insertPositionedObject(box); | 1925 o->containingBlock()->insertPositionedObject(box); |
| 1886 } else if (o->isFloating()) { | 1926 } else if (o->isFloating()) { |
| 1887 layoutState.floats().append(FloatWithRect(box)); | 1927 layoutState.floats().append(FloatWithRect(box)); |
| 1888 if (box->needsLayout()) { | 1928 if (box->needsLayout()) { |
| 1889 box->layout(); | 1929 box->layout(); |
| 1890 // Dirty any lineboxes potentially affected by the float, but don't
search outside this | 1930 // Dirty any lineboxes potentially affected by the float, but don't |
| 1891 // object as we are only interested in dirtying lineboxes to which w
e may attach the float. | 1931 // search outside this object as we are only interested in dirtying |
| 1932 // lineboxes to which we may attach the float. |
| 1892 dirtyLinesFromChangedChild(box, MarkOnlyThis); | 1933 dirtyLinesFromChangedChild(box, MarkOnlyThis); |
| 1893 } | 1934 } |
| 1894 } else if (isFullLayout || o->needsLayout()) { | 1935 } else if (isFullLayout || o->needsLayout()) { |
| 1895 // Atomic inline. | 1936 // Atomic inline. |
| 1896 box->dirtyLineBoxes(isFullLayout); | 1937 box->dirtyLineBoxes(isFullLayout); |
| 1897 o->layoutIfNeeded(); | 1938 o->layoutIfNeeded(); |
| 1898 } | 1939 } |
| 1899 } else if (o->isText() || | 1940 } else if (o->isText() || |
| 1900 (o->isLayoutInline() && !walker.atEndOfInline())) { | 1941 (o->isLayoutInline() && !walker.atEndOfInline())) { |
| 1901 if (!o->isText()) | 1942 if (!o->isText()) |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1932 | 1973 |
| 1933 // Now add in the bottom border/padding. | 1974 // Now add in the bottom border/padding. |
| 1934 setLogicalHeight(logicalHeight() + lastLineAnnotationsAdjustment + afterEdge); | 1975 setLogicalHeight(logicalHeight() + lastLineAnnotationsAdjustment + afterEdge); |
| 1935 | 1976 |
| 1936 if (!firstLineBox() && hasLineIfEmpty()) | 1977 if (!firstLineBox() && hasLineIfEmpty()) |
| 1937 setLogicalHeight(logicalHeight() + | 1978 setLogicalHeight(logicalHeight() + |
| 1938 lineHeight(true, isHorizontalWritingMode() ? HorizontalLine | 1979 lineHeight(true, isHorizontalWritingMode() ? HorizontalLine |
| 1939 : VerticalLine, | 1980 : VerticalLine, |
| 1940 PositionOfInteriorLineBoxes)); | 1981 PositionOfInteriorLineBoxes)); |
| 1941 | 1982 |
| 1942 // See if we have any lines that spill out of our block. If we do, then we wi
ll possibly need to | 1983 // See if we have any lines that spill out of our block. If we do, then we |
| 1943 // truncate text. | 1984 // will possibly need to truncate text. |
| 1944 if (hasTextOverflow) | 1985 if (hasTextOverflow) |
| 1945 checkLinesForTextOverflow(); | 1986 checkLinesForTextOverflow(); |
| 1946 | 1987 |
| 1947 // Ensure the new line boxes will be painted. | 1988 // Ensure the new line boxes will be painted. |
| 1948 if (isFullLayout && firstLineBox()) | 1989 if (isFullLayout && firstLineBox()) |
| 1949 setShouldDoFullPaintInvalidation(); | 1990 setShouldDoFullPaintInvalidation(); |
| 1950 } | 1991 } |
| 1951 | 1992 |
| 1952 RootInlineBox* LayoutBlockFlow::determineStartPosition( | 1993 RootInlineBox* LayoutBlockFlow::determineStartPosition( |
| 1953 LineLayoutState& layoutState, | 1994 LineLayoutState& layoutState, |
| 1954 InlineBidiResolver& resolver) { | 1995 InlineBidiResolver& resolver) { |
| 1955 RootInlineBox* curr = nullptr; | 1996 RootInlineBox* curr = nullptr; |
| 1956 RootInlineBox* last = nullptr; | 1997 RootInlineBox* last = nullptr; |
| 1957 RootInlineBox* firstLineBoxWithBreakAndClearance = 0; | 1998 RootInlineBox* firstLineBoxWithBreakAndClearance = 0; |
| 1958 | 1999 |
| 1959 // FIXME: This entire float-checking block needs to be broken into a new funct
ion. | 2000 // FIXME: This entire float-checking block needs to be broken into a new |
| 2001 // function. |
| 1960 if (!layoutState.isFullLayout()) { | 2002 if (!layoutState.isFullLayout()) { |
| 1961 // Paginate all of the clean lines. | 2003 // Paginate all of the clean lines. |
| 1962 bool paginated = | 2004 bool paginated = |
| 1963 view()->layoutState() && view()->layoutState()->isPaginated(); | 2005 view()->layoutState() && view()->layoutState()->isPaginated(); |
| 1964 LayoutUnit paginationDelta; | 2006 LayoutUnit paginationDelta; |
| 1965 for (curr = firstRootBox(); curr && !curr->isDirty(); | 2007 for (curr = firstRootBox(); curr && !curr->isDirty(); |
| 1966 curr = curr->nextRootBox()) { | 2008 curr = curr->nextRootBox()) { |
| 1967 if (paginated) { | 2009 if (paginated) { |
| 1968 paginationDelta -= curr->paginationStrut(); | 2010 paginationDelta -= curr->paginationStrut(); |
| 1969 adjustLinePositionForPagination(*curr, paginationDelta); | 2011 adjustLinePositionForPagination(*curr, paginationDelta); |
| 1970 if (paginationDelta) { | 2012 if (paginationDelta) { |
| 1971 if (containsFloats() || !layoutState.floats().isEmpty()) { | 2013 if (containsFloats() || !layoutState.floats().isEmpty()) { |
| 1972 // FIXME: Do better eventually. For now if we ever shift because of
pagination and floats are present just go to a full layout. | 2014 // FIXME: Do better eventually. For now if we ever shift because of |
| 2015 // pagination and floats are present just go to a full layout. |
| 1973 layoutState.markForFullLayout(); | 2016 layoutState.markForFullLayout(); |
| 1974 break; | 2017 break; |
| 1975 } | 2018 } |
| 1976 curr->moveInBlockDirection(paginationDelta); | 2019 curr->moveInBlockDirection(paginationDelta); |
| 1977 } | 2020 } |
| 1978 } | 2021 } |
| 1979 | 2022 |
| 1980 // If the linebox breaks cleanly and with clearance then dirty from at lea
st this point onwards so that we can clear the correct floats without difficulty
. | 2023 // If the linebox breaks cleanly and with clearance then dirty from at |
| 2024 // least this point onwards so that we can clear the correct floats |
| 2025 // without difficulty. |
| 1981 if (!firstLineBoxWithBreakAndClearance && lineBoxHasBRWithClearance(curr)) | 2026 if (!firstLineBoxWithBreakAndClearance && lineBoxHasBRWithClearance(curr)) |
| 1982 firstLineBoxWithBreakAndClearance = curr; | 2027 firstLineBoxWithBreakAndClearance = curr; |
| 1983 | 2028 |
| 1984 if (layoutState.isFullLayout()) | 2029 if (layoutState.isFullLayout()) |
| 1985 break; | 2030 break; |
| 1986 } | 2031 } |
| 1987 } | 2032 } |
| 1988 | 2033 |
| 1989 if (layoutState.isFullLayout()) { | 2034 if (layoutState.isFullLayout()) { |
| 1990 // If we encountered a new float and have inline children, mark ourself to f
orce us to issue paint invalidations. | 2035 // If we encountered a new float and have inline children, mark ourself to |
| 2036 // force us to issue paint invalidations. |
| 1991 if (layoutState.hasInlineChild() && !selfNeedsLayout()) { | 2037 if (layoutState.hasInlineChild() && !selfNeedsLayout()) { |
| 1992 setNeedsLayoutAndFullPaintInvalidation( | 2038 setNeedsLayoutAndFullPaintInvalidation( |
| 1993 LayoutInvalidationReason::FloatDescendantChanged, MarkOnlyThis); | 2039 LayoutInvalidationReason::FloatDescendantChanged, MarkOnlyThis); |
| 1994 setShouldDoFullPaintInvalidation(); | 2040 setShouldDoFullPaintInvalidation(); |
| 1995 } | 2041 } |
| 1996 | 2042 |
| 1997 deleteLineBoxTree(); | 2043 deleteLineBoxTree(); |
| 1998 curr = nullptr; | 2044 curr = nullptr; |
| 1999 ASSERT(!firstLineBox() && !lastLineBox()); | 2045 ASSERT(!firstLineBox() && !lastLineBox()); |
| 2000 } else { | 2046 } else { |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2070 LineLayoutBlockFlow(this), | 2116 LineLayoutBlockFlow(this), |
| 2071 bidiFirstSkippingEmptyInlines(LineLayoutBlockFlow(this), | 2117 bidiFirstSkippingEmptyInlines(LineLayoutBlockFlow(this), |
| 2072 resolver.runs(), &resolver), | 2118 resolver.runs(), &resolver), |
| 2073 0); | 2119 0); |
| 2074 resolver.setPosition(iter, numberOfIsolateAncestors(iter)); | 2120 resolver.setPosition(iter, numberOfIsolateAncestors(iter)); |
| 2075 } | 2121 } |
| 2076 return curr; | 2122 return curr; |
| 2077 } | 2123 } |
| 2078 | 2124 |
| 2079 bool LayoutBlockFlow::lineBoxHasBRWithClearance(RootInlineBox* curr) { | 2125 bool LayoutBlockFlow::lineBoxHasBRWithClearance(RootInlineBox* curr) { |
| 2080 // If the linebox breaks cleanly and with clearance then dirty from at least t
his point onwards so that we can clear the correct floats without difficulty. | 2126 // If the linebox breaks cleanly and with clearance then dirty from at least |
| 2127 // this point onwards so that we can clear the correct floats without |
| 2128 // difficulty. |
| 2081 if (!curr->endsWithBreak()) | 2129 if (!curr->endsWithBreak()) |
| 2082 return false; | 2130 return false; |
| 2083 InlineBox* lastBox = style()->isLeftToRightDirection() | 2131 InlineBox* lastBox = style()->isLeftToRightDirection() |
| 2084 ? curr->lastLeafChild() | 2132 ? curr->lastLeafChild() |
| 2085 : curr->firstLeafChild(); | 2133 : curr->firstLeafChild(); |
| 2086 return lastBox && lastBox->getLineLayoutItem().isBR() && | 2134 return lastBox && lastBox->getLineLayoutItem().isBR() && |
| 2087 lastBox->getLineLayoutItem().style()->clear() != ClearNone; | 2135 lastBox->getLineLayoutItem().style()->clear() != ClearNone; |
| 2088 } | 2136 } |
| 2089 | 2137 |
| 2090 void LayoutBlockFlow::determineEndPosition(LineLayoutState& layoutState, | 2138 void LayoutBlockFlow::determineEndPosition(LineLayoutState& layoutState, |
| 2091 RootInlineBox* startLine, | 2139 RootInlineBox* startLine, |
| 2092 InlineIterator& cleanLineStart, | 2140 InlineIterator& cleanLineStart, |
| 2093 BidiStatus& cleanLineBidiStatus) { | 2141 BidiStatus& cleanLineBidiStatus) { |
| 2094 ASSERT(!layoutState.endLine()); | 2142 ASSERT(!layoutState.endLine()); |
| 2095 RootInlineBox* last = nullptr; | 2143 RootInlineBox* last = nullptr; |
| 2096 for (RootInlineBox* curr = startLine->nextRootBox(); curr; | 2144 for (RootInlineBox* curr = startLine->nextRootBox(); curr; |
| 2097 curr = curr->nextRootBox()) { | 2145 curr = curr->nextRootBox()) { |
| 2098 if (!curr->isDirty() && lineBoxHasBRWithClearance(curr)) | 2146 if (!curr->isDirty() && lineBoxHasBRWithClearance(curr)) |
| 2099 return; | 2147 return; |
| 2100 | 2148 |
| 2101 if (curr->isDirty()) | 2149 if (curr->isDirty()) |
| 2102 last = nullptr; | 2150 last = nullptr; |
| 2103 else if (!last) | 2151 else if (!last) |
| 2104 last = curr; | 2152 last = curr; |
| 2105 } | 2153 } |
| 2106 | 2154 |
| 2107 if (!last) | 2155 if (!last) |
| 2108 return; | 2156 return; |
| 2109 | 2157 |
| 2110 // At this point, |last| is the first line in a run of clean lines that ends w
ith the last line | 2158 // At this point, |last| is the first line in a run of clean lines that ends |
| 2111 // in the block. | 2159 // with the last line in the block. |
| 2112 | 2160 |
| 2113 RootInlineBox* prev = last->prevRootBox(); | 2161 RootInlineBox* prev = last->prevRootBox(); |
| 2114 cleanLineStart = | 2162 cleanLineStart = |
| 2115 InlineIterator(LineLayoutItem(this), LineLayoutItem(prev->lineBreakObj()), | 2163 InlineIterator(LineLayoutItem(this), LineLayoutItem(prev->lineBreakObj()), |
| 2116 prev->lineBreakPos()); | 2164 prev->lineBreakPos()); |
| 2117 cleanLineBidiStatus = prev->lineBreakBidiStatus(); | 2165 cleanLineBidiStatus = prev->lineBreakBidiStatus(); |
| 2118 layoutState.setEndLineLogicalTop(prev->lineBottomWithLeading()); | 2166 layoutState.setEndLineLogicalTop(prev->lineBottomWithLeading()); |
| 2119 | 2167 |
| 2120 for (RootInlineBox* line = last; line; line = line->nextRootBox()) | 2168 for (RootInlineBox* line = last; line; line = line->nextRootBox()) |
| 2121 line->extractLine(); // Disconnect all line boxes from their layout objects
while preserving | 2169 line->extractLine(); // Disconnect all line boxes from their layout objects |
| 2122 // their connections to one another. | 2170 // while preserving their connections to one another. |
| 2123 | 2171 |
| 2124 layoutState.setEndLine(last); | 2172 layoutState.setEndLine(last); |
| 2125 } | 2173 } |
| 2126 | 2174 |
| 2127 bool LayoutBlockFlow::checkPaginationAndFloatsAtEndLine( | 2175 bool LayoutBlockFlow::checkPaginationAndFloatsAtEndLine( |
| 2128 LineLayoutState& layoutState) { | 2176 LineLayoutState& layoutState) { |
| 2129 if (!m_floatingObjects || !layoutState.endLine()) | 2177 if (!m_floatingObjects || !layoutState.endLine()) |
| 2130 return true; | 2178 return true; |
| 2131 | 2179 |
| 2132 LayoutUnit lineDelta = logicalHeight() - layoutState.endLineLogicalTop(); | 2180 LayoutUnit lineDelta = logicalHeight() - layoutState.endLineLogicalTop(); |
| 2133 | 2181 |
| 2134 bool paginated = | 2182 bool paginated = |
| 2135 view()->layoutState() && view()->layoutState()->isPaginated(); | 2183 view()->layoutState() && view()->layoutState()->isPaginated(); |
| 2136 if (paginated) { | 2184 if (paginated) { |
| 2137 // Check all lines from here to the end, and see if the hypothetical new pos
ition for the lines will result | 2185 // Check all lines from here to the end, and see if the hypothetical new |
| 2186 // position for the lines will result |
| 2138 // in a different available line width. | 2187 // in a different available line width. |
| 2139 for (RootInlineBox* lineBox = layoutState.endLine(); lineBox; | 2188 for (RootInlineBox* lineBox = layoutState.endLine(); lineBox; |
| 2140 lineBox = lineBox->nextRootBox()) { | 2189 lineBox = lineBox->nextRootBox()) { |
| 2141 // This isn't the real move we're going to do, so don't update the line bo
x's pagination | 2190 // This isn't the real move we're going to do, so don't update the line |
| 2142 // strut yet. | 2191 // box's pagination strut yet. |
| 2143 LayoutUnit oldPaginationStrut = lineBox->paginationStrut(); | 2192 LayoutUnit oldPaginationStrut = lineBox->paginationStrut(); |
| 2144 lineDelta -= oldPaginationStrut; | 2193 lineDelta -= oldPaginationStrut; |
| 2145 adjustLinePositionForPagination(*lineBox, lineDelta); | 2194 adjustLinePositionForPagination(*lineBox, lineDelta); |
| 2146 lineBox->setPaginationStrut(oldPaginationStrut); | 2195 lineBox->setPaginationStrut(oldPaginationStrut); |
| 2147 } | 2196 } |
| 2148 } | 2197 } |
| 2149 if (!lineDelta) | 2198 if (!lineDelta) |
| 2150 return true; | 2199 return true; |
| 2151 | 2200 |
| 2152 // See if any floats end in the range along which we want to shift the lines v
ertically. | 2201 // See if any floats end in the range along which we want to shift the lines |
| 2202 // vertically. |
| 2153 LayoutUnit logicalTop = | 2203 LayoutUnit logicalTop = |
| 2154 std::min(logicalHeight(), layoutState.endLineLogicalTop()); | 2204 std::min(logicalHeight(), layoutState.endLineLogicalTop()); |
| 2155 | 2205 |
| 2156 RootInlineBox* lastLine = layoutState.endLine(); | 2206 RootInlineBox* lastLine = layoutState.endLine(); |
| 2157 while (RootInlineBox* nextLine = lastLine->nextRootBox()) | 2207 while (RootInlineBox* nextLine = lastLine->nextRootBox()) |
| 2158 lastLine = nextLine; | 2208 lastLine = nextLine; |
| 2159 | 2209 |
| 2160 LayoutUnit logicalBottom = | 2210 LayoutUnit logicalBottom = |
| 2161 lastLine->lineBottomWithLeading() + absoluteValue(lineDelta); | 2211 lastLine->lineBottomWithLeading() + absoluteValue(lineDelta); |
| 2162 | 2212 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 2177 const InlineBidiResolver& resolver, | 2227 const InlineBidiResolver& resolver, |
| 2178 const InlineIterator& endLineStart, | 2228 const InlineIterator& endLineStart, |
| 2179 const BidiStatus& endLineStatus) { | 2229 const BidiStatus& endLineStatus) { |
| 2180 if (resolver.position() == endLineStart) { | 2230 if (resolver.position() == endLineStart) { |
| 2181 if (resolver.status() != endLineStatus) | 2231 if (resolver.status() != endLineStatus) |
| 2182 return false; | 2232 return false; |
| 2183 | 2233 |
| 2184 return checkPaginationAndFloatsAtEndLine(layoutState); | 2234 return checkPaginationAndFloatsAtEndLine(layoutState); |
| 2185 } | 2235 } |
| 2186 | 2236 |
| 2187 // The first clean line doesn't match, but we can check a handful of following
lines to try | 2237 // The first clean line doesn't match, but we can check a handful of following |
| 2188 // to match back up. | 2238 // lines to try to match back up. |
| 2189 static int numLines = 8; // The # of lines we're willing to match against. | 2239 static int numLines = 8; // The # of lines we're willing to match against. |
| 2190 RootInlineBox* originalEndLine = layoutState.endLine(); | 2240 RootInlineBox* originalEndLine = layoutState.endLine(); |
| 2191 RootInlineBox* line = originalEndLine; | 2241 RootInlineBox* line = originalEndLine; |
| 2192 for (int i = 0; i < numLines && line; i++, line = line->nextRootBox()) { | 2242 for (int i = 0; i < numLines && line; i++, line = line->nextRootBox()) { |
| 2193 if (line->lineBreakObj() == resolver.position().getLineLayoutItem() && | 2243 if (line->lineBreakObj() == resolver.position().getLineLayoutItem() && |
| 2194 line->lineBreakPos() == resolver.position().offset()) { | 2244 line->lineBreakPos() == resolver.position().offset()) { |
| 2195 // We have a match. | 2245 // We have a match. |
| 2196 if (line->lineBreakBidiStatus() != resolver.status()) | 2246 if (line->lineBreakBidiStatus() != resolver.status()) |
| 2197 return false; // ...but the bidi state doesn't match. | 2247 return false; // ...but the bidi state doesn't match. |
| 2198 | 2248 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 2221 InlineIterator it(LineLayoutBlockFlow(this), LineLayoutItem(inlineObj), 0); | 2271 InlineIterator it(LineLayoutBlockFlow(this), LineLayoutItem(inlineObj), 0); |
| 2222 // FIXME: We should pass correct value for WhitespacePosition. | 2272 // FIXME: We should pass correct value for WhitespacePosition. |
| 2223 while (!it.atEnd() && !requiresLineBox(it)) | 2273 while (!it.atEnd() && !requiresLineBox(it)) |
| 2224 it.increment(); | 2274 it.increment(); |
| 2225 | 2275 |
| 2226 return !it.atEnd(); | 2276 return !it.atEnd(); |
| 2227 } | 2277 } |
| 2228 | 2278 |
| 2229 void LayoutBlockFlow::addOverflowFromInlineChildren() { | 2279 void LayoutBlockFlow::addOverflowFromInlineChildren() { |
| 2230 LayoutUnit endPadding = hasOverflowClip() ? paddingEnd() : LayoutUnit(); | 2280 LayoutUnit endPadding = hasOverflowClip() ? paddingEnd() : LayoutUnit(); |
| 2231 // FIXME: Need to find another way to do this, since scrollbars could show whe
n we don't want them to. | 2281 // FIXME: Need to find another way to do this, since scrollbars could show |
| 2282 // when we don't want them to. |
| 2232 if (hasOverflowClip() && !endPadding && node() && | 2283 if (hasOverflowClip() && !endPadding && node() && |
| 2233 isRootEditableElement(*node()) && style()->isLeftToRightDirection()) | 2284 isRootEditableElement(*node()) && style()->isLeftToRightDirection()) |
| 2234 endPadding = LayoutUnit(1); | 2285 endPadding = LayoutUnit(1); |
| 2235 for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) { | 2286 for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) { |
| 2236 addLayoutOverflow(curr->paddedLayoutOverflowRect(endPadding)); | 2287 addLayoutOverflow(curr->paddedLayoutOverflowRect(endPadding)); |
| 2237 LayoutRect visualOverflow = | 2288 LayoutRect visualOverflow = |
| 2238 curr->visualOverflowRect(curr->lineTop(), curr->lineBottom()); | 2289 curr->visualOverflowRect(curr->lineTop(), curr->lineBottom()); |
| 2239 addContentsVisualOverflow(visualOverflow); | 2290 addContentsVisualOverflow(visualOverflow); |
| 2240 } | 2291 } |
| 2241 | 2292 |
| 2242 if (!containsInlineWithOutlineAndContinuation()) | 2293 if (!containsInlineWithOutlineAndContinuation()) |
| 2243 return; | 2294 return; |
| 2244 | 2295 |
| 2245 // Add outline rects of continuations of descendant inlines into visual overfl
ow of this block. | 2296 // Add outline rects of continuations of descendant inlines into visual |
| 2297 // overflow of this block. |
| 2246 LayoutRect outlineBoundsOfAllContinuations; | 2298 LayoutRect outlineBoundsOfAllContinuations; |
| 2247 for (InlineWalker walker(LineLayoutBlockFlow(this)); !walker.atEnd(); | 2299 for (InlineWalker walker(LineLayoutBlockFlow(this)); !walker.atEnd(); |
| 2248 walker.advance()) { | 2300 walker.advance()) { |
| 2249 const LayoutObject& o = *walker.current().layoutObject(); | 2301 const LayoutObject& o = *walker.current().layoutObject(); |
| 2250 if (!isInlineWithOutlineAndContinuation(o)) | 2302 if (!isInlineWithOutlineAndContinuation(o)) |
| 2251 continue; | 2303 continue; |
| 2252 | 2304 |
| 2253 Vector<LayoutRect> outlineRects; | 2305 Vector<LayoutRect> outlineRects; |
| 2254 toLayoutInline(o).addOutlineRectsForContinuations( | 2306 toLayoutInline(o).addOutlineRectsForContinuations( |
| 2255 outlineRects, LayoutPoint(), | 2307 outlineRects, LayoutPoint(), |
| 2256 o.outlineRectsShouldIncludeBlockVisualOverflow()); | 2308 o.outlineRectsShouldIncludeBlockVisualOverflow()); |
| 2257 if (!outlineRects.isEmpty()) { | 2309 if (!outlineRects.isEmpty()) { |
| 2258 LayoutRect outlineBounds = unionRectEvenIfEmpty(outlineRects); | 2310 LayoutRect outlineBounds = unionRectEvenIfEmpty(outlineRects); |
| 2259 outlineBounds.inflate(LayoutUnit(o.styleRef().outlineOutsetExtent())); | 2311 outlineBounds.inflate(LayoutUnit(o.styleRef().outlineOutsetExtent())); |
| 2260 outlineBoundsOfAllContinuations.unite(outlineBounds); | 2312 outlineBoundsOfAllContinuations.unite(outlineBounds); |
| 2261 } | 2313 } |
| 2262 } | 2314 } |
| 2263 addContentsVisualOverflow(outlineBoundsOfAllContinuations); | 2315 addContentsVisualOverflow(outlineBoundsOfAllContinuations); |
| 2264 } | 2316 } |
| 2265 | 2317 |
| 2266 void LayoutBlockFlow::deleteEllipsisLineBoxes() { | 2318 void LayoutBlockFlow::deleteEllipsisLineBoxes() { |
| 2267 ETextAlign textAlign = style()->textAlign(); | 2319 ETextAlign textAlign = style()->textAlign(); |
| 2268 IndentTextOrNot indentText = IndentText; | 2320 IndentTextOrNot indentText = IndentText; |
| 2269 for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) { | 2321 for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) { |
| 2270 if (curr->hasEllipsisBox()) { | 2322 if (curr->hasEllipsisBox()) { |
| 2271 curr->clearTruncation(); | 2323 curr->clearTruncation(); |
| 2272 | 2324 |
| 2273 // Shift the line back where it belongs if we cannot accommodate an ellips
is. | 2325 // Shift the line back where it belongs if we cannot accommodate an |
| 2326 // ellipsis. |
| 2274 LayoutUnit logicalLeft = | 2327 LayoutUnit logicalLeft = |
| 2275 logicalLeftOffsetForLine(curr->lineTop(), indentText); | 2328 logicalLeftOffsetForLine(curr->lineTop(), indentText); |
| 2276 LayoutUnit availableLogicalWidth = | 2329 LayoutUnit availableLogicalWidth = |
| 2277 logicalRightOffsetForLine(curr->lineTop(), DoNotIndentText) - | 2330 logicalRightOffsetForLine(curr->lineTop(), DoNotIndentText) - |
| 2278 logicalLeft; | 2331 logicalLeft; |
| 2279 LayoutUnit totalLogicalWidth = curr->logicalWidth(); | 2332 LayoutUnit totalLogicalWidth = curr->logicalWidth(); |
| 2280 updateLogicalWidthForAlignment(textAlign, curr, 0, logicalLeft, | 2333 updateLogicalWidthForAlignment(textAlign, curr, 0, logicalLeft, |
| 2281 totalLogicalWidth, availableLogicalWidth, | 2334 totalLogicalWidth, availableLogicalWidth, |
| 2282 0); | 2335 0); |
| 2283 | 2336 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 2294 const size_t fullStopStringLength = 3; | 2347 const size_t fullStopStringLength = 3; |
| 2295 const UChar fullStopString[] = {fullstopCharacter, fullstopCharacter, | 2348 const UChar fullStopString[] = {fullstopCharacter, fullstopCharacter, |
| 2296 fullstopCharacter}; | 2349 fullstopCharacter}; |
| 2297 DEFINE_STATIC_LOCAL(AtomicString, fullstopCharacterStr, | 2350 DEFINE_STATIC_LOCAL(AtomicString, fullstopCharacterStr, |
| 2298 (fullStopString, fullStopStringLength)); | 2351 (fullStopString, fullStopStringLength)); |
| 2299 DEFINE_STATIC_LOCAL(AtomicString, ellipsisStr, | 2352 DEFINE_STATIC_LOCAL(AtomicString, ellipsisStr, |
| 2300 (&horizontalEllipsisCharacter, 1)); | 2353 (&horizontalEllipsisCharacter, 1)); |
| 2301 AtomicString& selectedEllipsisStr = ellipsisStr; | 2354 AtomicString& selectedEllipsisStr = ellipsisStr; |
| 2302 | 2355 |
| 2303 const Font& firstLineFont = firstLineStyle()->font(); | 2356 const Font& firstLineFont = firstLineStyle()->font(); |
| 2304 // FIXME: We should probably not hard-code the direction here. https://crbug.c
om/333004 | 2357 // FIXME: We should probably not hard-code the direction here. |
| 2358 // https://crbug.com/333004 |
| 2305 TextDirection ellipsisDirection = LTR; | 2359 TextDirection ellipsisDirection = LTR; |
| 2306 float firstLineEllipsisWidth = 0; | 2360 float firstLineEllipsisWidth = 0; |
| 2307 float ellipsisWidth = 0; | 2361 float ellipsisWidth = 0; |
| 2308 | 2362 |
| 2309 // As per CSS3 http://www.w3.org/TR/2003/CR-css3-text-20030514/ sequence of th
ree | 2363 // As per CSS3 http://www.w3.org/TR/2003/CR-css3-text-20030514/ sequence of |
| 2310 // Full Stops (002E) can be used. | 2364 // three Full Stops (002E) can be used. |
| 2311 ASSERT(firstLineFont.primaryFont()); | 2365 ASSERT(firstLineFont.primaryFont()); |
| 2312 if (firstLineFont.primaryFont()->glyphForCharacter( | 2366 if (firstLineFont.primaryFont()->glyphForCharacter( |
| 2313 horizontalEllipsisCharacter)) { | 2367 horizontalEllipsisCharacter)) { |
| 2314 firstLineEllipsisWidth = firstLineFont.width( | 2368 firstLineEllipsisWidth = firstLineFont.width( |
| 2315 constructTextRun(firstLineFont, &horizontalEllipsisCharacter, 1, | 2369 constructTextRun(firstLineFont, &horizontalEllipsisCharacter, 1, |
| 2316 *firstLineStyle(), ellipsisDirection)); | 2370 *firstLineStyle(), ellipsisDirection)); |
| 2317 } else { | 2371 } else { |
| 2318 selectedEllipsisStr = fullstopCharacterStr; | 2372 selectedEllipsisStr = fullstopCharacterStr; |
| 2319 firstLineEllipsisWidth = firstLineFont.width( | 2373 firstLineEllipsisWidth = firstLineFont.width( |
| 2320 constructTextRun(firstLineFont, fullStopString, fullStopStringLength, | 2374 constructTextRun(firstLineFont, fullStopString, fullStopStringLength, |
| 2321 *firstLineStyle(), ellipsisDirection)); | 2375 *firstLineStyle(), ellipsisDirection)); |
| 2322 } | 2376 } |
| 2323 ellipsisWidth = (font == firstLineFont) ? firstLineEllipsisWidth : 0; | 2377 ellipsisWidth = (font == firstLineFont) ? firstLineEllipsisWidth : 0; |
| 2324 | 2378 |
| 2325 if (!ellipsisWidth) { | 2379 if (!ellipsisWidth) { |
| 2326 ASSERT(font.primaryFont()); | 2380 ASSERT(font.primaryFont()); |
| 2327 if (font.primaryFont()->glyphForCharacter(horizontalEllipsisCharacter)) { | 2381 if (font.primaryFont()->glyphForCharacter(horizontalEllipsisCharacter)) { |
| 2328 selectedEllipsisStr = ellipsisStr; | 2382 selectedEllipsisStr = ellipsisStr; |
| 2329 ellipsisWidth = | 2383 ellipsisWidth = |
| 2330 font.width(constructTextRun(font, &horizontalEllipsisCharacter, 1, | 2384 font.width(constructTextRun(font, &horizontalEllipsisCharacter, 1, |
| 2331 styleRef(), ellipsisDirection)); | 2385 styleRef(), ellipsisDirection)); |
| 2332 } else { | 2386 } else { |
| 2333 selectedEllipsisStr = fullstopCharacterStr; | 2387 selectedEllipsisStr = fullstopCharacterStr; |
| 2334 ellipsisWidth = font.width( | 2388 ellipsisWidth = font.width( |
| 2335 constructTextRun(font, fullStopString, fullStopStringLength, | 2389 constructTextRun(font, fullStopString, fullStopStringLength, |
| 2336 styleRef(), ellipsisDirection)); | 2390 styleRef(), ellipsisDirection)); |
| 2337 } | 2391 } |
| 2338 } | 2392 } |
| 2339 | 2393 |
| 2340 // For LTR text truncation, we want to get the right edge of our padding box,
and then we want to see | 2394 // For LTR text truncation, we want to get the right edge of our padding box, |
| 2341 // if the right edge of a line box exceeds that. For RTL, we use the left edg
e of the padding box and | 2395 // and then we want to see if the right edge of a line box exceeds that. |
| 2342 // check the left edge of the line box to see if it is less | 2396 // For RTL, we use the left edge of the padding box and check the left edge of |
| 2343 // Include the scrollbar for overflow blocks, which means we want to use "cont
entWidth()" | 2397 // the line box to see if it is less Include the scrollbar for overflow |
| 2398 // blocks, which means we want to use "contentWidth()". |
| 2344 bool ltr = style()->isLeftToRightDirection(); | 2399 bool ltr = style()->isLeftToRightDirection(); |
| 2345 ETextAlign textAlign = style()->textAlign(); | 2400 ETextAlign textAlign = style()->textAlign(); |
| 2346 IndentTextOrNot indentText = IndentText; | 2401 IndentTextOrNot indentText = IndentText; |
| 2347 for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) { | 2402 for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) { |
| 2348 LayoutUnit currLogicalLeft = curr->logicalLeft(); | 2403 LayoutUnit currLogicalLeft = curr->logicalLeft(); |
| 2349 LayoutUnit blockRightEdge = | 2404 LayoutUnit blockRightEdge = |
| 2350 logicalRightOffsetForLine(curr->lineTop(), indentText); | 2405 logicalRightOffsetForLine(curr->lineTop(), indentText); |
| 2351 LayoutUnit blockLeftEdge = | 2406 LayoutUnit blockLeftEdge = |
| 2352 logicalLeftOffsetForLine(curr->lineTop(), indentText); | 2407 logicalLeftOffsetForLine(curr->lineTop(), indentText); |
| 2353 LayoutUnit lineBoxEdge = | 2408 LayoutUnit lineBoxEdge = |
| 2354 ltr ? currLogicalLeft + curr->logicalWidth() : currLogicalLeft; | 2409 ltr ? currLogicalLeft + curr->logicalWidth() : currLogicalLeft; |
| 2355 if ((ltr && lineBoxEdge > blockRightEdge) || | 2410 if ((ltr && lineBoxEdge > blockRightEdge) || |
| 2356 (!ltr && lineBoxEdge < blockLeftEdge)) { | 2411 (!ltr && lineBoxEdge < blockLeftEdge)) { |
| 2357 // This line spills out of our box in the appropriate direction. Now we n
eed to see if the line | 2412 // This line spills out of our box in the appropriate direction. Now we |
| 2358 // can be truncated. In order for truncation to be possible, the line mus
t have sufficient space to | 2413 // need to see if the line can be truncated. In order for truncation to |
| 2359 // accommodate our truncation string, and no replaced elements (images, ta
bles) can overlap the ellipsis | 2414 // be possible, the line must have sufficient space to accommodate our |
| 2360 // space. | 2415 // truncation string, and no replaced elements (images, tables) can |
| 2416 // overlap the ellipsis space. |
| 2361 | 2417 |
| 2362 LayoutUnit width(indentText == IndentText ? firstLineEllipsisWidth | 2418 LayoutUnit width(indentText == IndentText ? firstLineEllipsisWidth |
| 2363 : ellipsisWidth); | 2419 : ellipsisWidth); |
| 2364 LayoutUnit blockEdge = ltr ? blockRightEdge : blockLeftEdge; | 2420 LayoutUnit blockEdge = ltr ? blockRightEdge : blockLeftEdge; |
| 2365 if (curr->lineCanAccommodateEllipsis( | 2421 if (curr->lineCanAccommodateEllipsis( |
| 2366 ltr, blockEdge.toInt(), lineBoxEdge.toInt(), width.toInt())) { | 2422 ltr, blockEdge.toInt(), lineBoxEdge.toInt(), width.toInt())) { |
| 2367 LayoutUnit totalLogicalWidth = curr->placeEllipsis( | 2423 LayoutUnit totalLogicalWidth = curr->placeEllipsis( |
| 2368 selectedEllipsisStr, ltr, blockLeftEdge, blockRightEdge, width); | 2424 selectedEllipsisStr, ltr, blockLeftEdge, blockRightEdge, width); |
| 2369 LayoutUnit | 2425 LayoutUnit logicalLeft; // We are only interested in the delta from the |
| 2370 logicalLeft; // We are only interested in the delta from the base p
osition. | 2426 // base position. |
| 2371 LayoutUnit availableLogicalWidth = blockRightEdge - blockLeftEdge; | 2427 LayoutUnit availableLogicalWidth = blockRightEdge - blockLeftEdge; |
| 2372 updateLogicalWidthForAlignment(textAlign, curr, 0, logicalLeft, | 2428 updateLogicalWidthForAlignment(textAlign, curr, 0, logicalLeft, |
| 2373 totalLogicalWidth, availableLogicalWidth, | 2429 totalLogicalWidth, availableLogicalWidth, |
| 2374 0); | 2430 0); |
| 2375 if (ltr) | 2431 if (ltr) |
| 2376 curr->moveInInlineDirection(logicalLeft); | 2432 curr->moveInInlineDirection(logicalLeft); |
| 2377 else | 2433 else |
| 2378 curr->moveInInlineDirection( | 2434 curr->moveInInlineDirection( |
| 2379 logicalLeft - (availableLogicalWidth - totalLogicalWidth)); | 2435 logicalLeft - (availableLogicalWidth - totalLogicalWidth)); |
| 2380 } | 2436 } |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2424 case TASTART: | 2480 case TASTART: |
| 2425 applyIndentText = true; | 2481 applyIndentText = true; |
| 2426 break; | 2482 break; |
| 2427 default: | 2483 default: |
| 2428 applyIndentText = false; | 2484 applyIndentText = false; |
| 2429 } | 2485 } |
| 2430 | 2486 |
| 2431 if (applyIndentText) | 2487 if (applyIndentText) |
| 2432 return startOffsetForLine(position, indentText); | 2488 return startOffsetForLine(position, indentText); |
| 2433 | 2489 |
| 2434 // updateLogicalWidthForAlignment() handles the direction of the block so no n
eed to consider it here | 2490 // updateLogicalWidthForAlignment() handles the direction of the block so no |
| 2491 // need to consider it here |
| 2435 LayoutUnit totalLogicalWidth; | 2492 LayoutUnit totalLogicalWidth; |
| 2436 LayoutUnit logicalLeft = | 2493 LayoutUnit logicalLeft = |
| 2437 logicalLeftOffsetForLine(logicalHeight(), DoNotIndentText); | 2494 logicalLeftOffsetForLine(logicalHeight(), DoNotIndentText); |
| 2438 LayoutUnit availableLogicalWidth = | 2495 LayoutUnit availableLogicalWidth = |
| 2439 logicalRightOffsetForLine(logicalHeight(), DoNotIndentText) - logicalLeft; | 2496 logicalRightOffsetForLine(logicalHeight(), DoNotIndentText) - logicalLeft; |
| 2440 updateLogicalWidthForAlignment(textAlign, 0, 0, logicalLeft, | 2497 updateLogicalWidthForAlignment(textAlign, 0, 0, logicalLeft, |
| 2441 totalLogicalWidth, availableLogicalWidth, 0); | 2498 totalLogicalWidth, availableLogicalWidth, 0); |
| 2442 | 2499 |
| 2443 if (!style()->isLeftToRightDirection()) | 2500 if (!style()->isLeftToRightDirection()) |
| 2444 return logicalWidth() - logicalLeft; | 2501 return logicalWidth() - logicalLeft; |
| 2445 return logicalLeft; | 2502 return logicalLeft; |
| 2446 } | 2503 } |
| 2447 | 2504 |
| 2448 void LayoutBlockFlow::setShouldDoFullPaintInvalidationForFirstLine() { | 2505 void LayoutBlockFlow::setShouldDoFullPaintInvalidationForFirstLine() { |
| 2449 ASSERT(childrenInline()); | 2506 ASSERT(childrenInline()); |
| 2450 if (RootInlineBox* firstRootBox = this->firstRootBox()) | 2507 if (RootInlineBox* firstRootBox = this->firstRootBox()) |
| 2451 firstRootBox->setShouldDoFullPaintInvalidationRecursively(); | 2508 firstRootBox->setShouldDoFullPaintInvalidationRecursively(); |
| 2452 } | 2509 } |
| 2453 | 2510 |
| 2454 bool LayoutBlockFlow::paintedOutputOfObjectHasNoEffectRegardlessOfSize() const { | 2511 bool LayoutBlockFlow::paintedOutputOfObjectHasNoEffectRegardlessOfSize() const { |
| 2455 // LayoutBlockFlow is in charge of paint invalidation of the first line. | 2512 // LayoutBlockFlow is in charge of paint invalidation of the first line. |
| 2456 if (firstLineBox()) | 2513 if (firstLineBox()) |
| 2457 return false; | 2514 return false; |
| 2458 | 2515 |
| 2459 return LayoutBlock::paintedOutputOfObjectHasNoEffectRegardlessOfSize(); | 2516 return LayoutBlock::paintedOutputOfObjectHasNoEffectRegardlessOfSize(); |
| 2460 } | 2517 } |
| 2461 | 2518 |
| 2462 } // namespace blink | 2519 } // namespace blink |
| OLD | NEW |