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