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