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