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. |
4 * All right reserved. | 4 * All right reserved. |
5 * Copyright (C) 2010 Google Inc. All rights reserved. | 5 * Copyright (C) 2010 Google Inc. All rights reserved. |
6 * | 6 * |
7 * This library is free software; you can redistribute it and/or | 7 * This library is free software; you can redistribute it and/or |
8 * modify it under the terms of the GNU Library General Public | 8 * modify it under the terms of the GNU Library General Public |
9 * License as published by the Free Software Foundation; either | 9 * License as published by the Free Software Foundation; either |
10 * version 2 of the License, or (at your option) any later version. | 10 * version 2 of the License, or (at your option) any later version. |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
118 private: | 118 private: |
119 Vector<unsigned, 16> m_runsWithExpansions; | 119 Vector<unsigned, 16> m_runsWithExpansions; |
120 unsigned m_totalOpportunities; | 120 unsigned m_totalOpportunities; |
121 }; | 121 }; |
122 | 122 |
123 static inline InlineBox* createInlineBoxForLayoutObject( | 123 static inline InlineBox* createInlineBoxForLayoutObject( |
124 LineLayoutItem lineLayoutItem, | 124 LineLayoutItem lineLayoutItem, |
125 bool isRootLineBox, | 125 bool isRootLineBox, |
126 bool isOnlyRun = false) { | 126 bool isOnlyRun = false) { |
127 // Callers should handle text themselves. | 127 // Callers should handle text themselves. |
128 ASSERT(!lineLayoutItem.isText()); | 128 DCHECK(!lineLayoutItem.isText()); |
129 | 129 |
130 if (isRootLineBox) | 130 if (isRootLineBox) |
131 return LineLayoutBlockFlow(lineLayoutItem).createAndAppendRootInlineBox(); | 131 return LineLayoutBlockFlow(lineLayoutItem).createAndAppendRootInlineBox(); |
132 | 132 |
133 if (lineLayoutItem.isBox()) | 133 if (lineLayoutItem.isBox()) |
134 return LineLayoutBox(lineLayoutItem).createInlineBox(); | 134 return LineLayoutBox(lineLayoutItem).createInlineBox(); |
135 | 135 |
136 return LineLayoutInline(lineLayoutItem).createAndAppendInlineFlowBox(); | 136 return LineLayoutInline(lineLayoutItem).createAndAppendInlineFlowBox(); |
137 } | 137 } |
138 | 138 |
139 static inline InlineTextBox* createInlineBoxForText(BidiRun& run, | 139 static inline InlineTextBox* createInlineBoxForText(BidiRun& run, |
140 bool isOnlyRun) { | 140 bool isOnlyRun) { |
141 ASSERT(run.m_lineLayoutItem.isText()); | 141 DCHECK(run.m_lineLayoutItem.isText()); |
142 LineLayoutText text = LineLayoutText(run.m_lineLayoutItem); | 142 LineLayoutText text = LineLayoutText(run.m_lineLayoutItem); |
143 InlineTextBox* textBox = | 143 InlineTextBox* textBox = |
144 text.createInlineTextBox(run.m_start, run.m_stop - run.m_start); | 144 text.createInlineTextBox(run.m_start, run.m_stop - run.m_start); |
145 // We only treat a box as text for a <br> if we are on a line by ourself or in | 145 // We only treat a box as text for a <br> if we are on a line by ourself or in |
146 // strict mode (Note the use of strict mode. In "almost strict" mode, we | 146 // strict mode (Note the use of strict mode. In "almost strict" mode, we |
147 // don't treat the box for <br> as text.) | 147 // don't treat the box for <br> as text.) |
148 if (text.isBR()) | 148 if (text.isBR()) |
149 textBox->setIsText(isOnlyRun || text.document().inNoQuirksMode()); | 149 textBox->setIsText(isOnlyRun || text.document().inNoQuirksMode()); |
150 textBox->setDirOverride( | 150 textBox->setDirOverride( |
151 run.dirOverride(text.style()->rtlOrdering() == EOrder::kVisual)); | 151 run.dirOverride(text.style()->rtlOrdering() == EOrder::kVisual)); |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
265 if (pos >= length) | 265 if (pos >= length) |
266 return true; | 266 return true; |
267 | 267 |
268 if (layoutText.is8Bit()) | 268 if (layoutText.is8Bit()) |
269 return endsWithASCIISpaces(layoutText.characters8(), pos, length); | 269 return endsWithASCIISpaces(layoutText.characters8(), pos, length); |
270 return endsWithASCIISpaces(layoutText.characters16(), pos, length); | 270 return endsWithASCIISpaces(layoutText.characters16(), pos, length); |
271 } | 271 } |
272 | 272 |
273 RootInlineBox* LayoutBlockFlow::constructLine(BidiRunList<BidiRun>& bidiRuns, | 273 RootInlineBox* LayoutBlockFlow::constructLine(BidiRunList<BidiRun>& bidiRuns, |
274 const LineInfo& lineInfo) { | 274 const LineInfo& lineInfo) { |
275 ASSERT(bidiRuns.firstRun()); | 275 DCHECK(bidiRuns.firstRun()); |
276 | 276 |
277 bool rootHasSelectedChildren = false; | 277 bool rootHasSelectedChildren = false; |
278 InlineFlowBox* parentBox = nullptr; | 278 InlineFlowBox* parentBox = nullptr; |
279 int runCount = bidiRuns.runCount() - lineInfo.runsFromLeadingWhitespace(); | 279 int runCount = bidiRuns.runCount() - lineInfo.runsFromLeadingWhitespace(); |
280 for (BidiRun* r = bidiRuns.firstRun(); r; r = r->next()) { | 280 for (BidiRun* r = bidiRuns.firstRun(); r; r = r->next()) { |
281 // Create a box for our object. | 281 // Create a box for our object. |
282 bool isOnlyRun = (runCount == 1); | 282 bool isOnlyRun = (runCount == 1); |
283 if (runCount == 2 && !r->m_lineLayoutItem.isListMarker()) | 283 if (runCount == 2 && !r->m_lineLayoutItem.isListMarker()) |
284 isOnlyRun = (!style()->isLeftToRightDirection() ? bidiRuns.lastRun() | 284 isOnlyRun = (!style()->isLeftToRightDirection() ? bidiRuns.lastRun() |
285 : bidiRuns.firstRun()) | 285 : bidiRuns.firstRun()) |
286 ->m_lineLayoutItem.isListMarker(); | 286 ->m_lineLayoutItem.isListMarker(); |
287 | 287 |
288 if (lineInfo.isEmpty()) | 288 if (lineInfo.isEmpty()) |
289 continue; | 289 continue; |
290 | 290 |
291 InlineBox* box; | 291 InlineBox* box; |
292 if (r->m_lineLayoutItem.isText()) | 292 if (r->m_lineLayoutItem.isText()) |
293 box = createInlineBoxForText(*r, isOnlyRun); | 293 box = createInlineBoxForText(*r, isOnlyRun); |
294 else | 294 else |
295 box = | 295 box = |
296 createInlineBoxForLayoutObject(r->m_lineLayoutItem, false, isOnlyRun); | 296 createInlineBoxForLayoutObject(r->m_lineLayoutItem, false, isOnlyRun); |
297 r->m_box = box; | 297 r->m_box = box; |
298 | 298 |
299 ASSERT(box); | 299 DCHECK(box); |
300 if (!box) | 300 if (!box) |
301 continue; | 301 continue; |
302 | 302 |
303 if (!rootHasSelectedChildren && | 303 if (!rootHasSelectedChildren && |
304 box->getLineLayoutItem().getSelectionState() != SelectionNone) | 304 box->getLineLayoutItem().getSelectionState() != SelectionNone) |
305 rootHasSelectedChildren = true; | 305 rootHasSelectedChildren = true; |
306 | 306 |
307 // If we have no parent box yet, or if the run is not simply a sibling, | 307 // If we have no parent box yet, or if the run is not simply a sibling, |
308 // then we need to construct inline boxes as necessary to properly enclose | 308 // then we need to construct inline boxes as necessary to properly enclose |
309 // the run's inline box. Segments can only be siblings at the root level, as | 309 // the run's inline box. Segments can only be siblings at the root level, as |
(...skipping 11 matching lines...) Expand all Loading... |
321 box->setBidiLevel(r->level()); | 321 box->setBidiLevel(r->level()); |
322 | 322 |
323 if (box->isInlineTextBox()) { | 323 if (box->isInlineTextBox()) { |
324 if (AXObjectCache* cache = document().existingAXObjectCache()) | 324 if (AXObjectCache* cache = document().existingAXObjectCache()) |
325 cache->inlineTextBoxesUpdated(r->m_lineLayoutItem); | 325 cache->inlineTextBoxesUpdated(r->m_lineLayoutItem); |
326 } | 326 } |
327 } | 327 } |
328 | 328 |
329 // 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 |
330 // be the last continuation of our line list. | 330 // be the last continuation of our line list. |
331 ASSERT(lastLineBox() && !lastLineBox()->isConstructed()); | 331 DCHECK(lastLineBox()); |
| 332 DCHECK(!lastLineBox()->isConstructed()); |
332 | 333 |
333 // Set the m_selectedChildren flag on the root inline box if one of the leaf | 334 // Set the m_selectedChildren flag on the root inline box if one of the leaf |
334 // inline box from the bidi runs walk above has a selection state. | 335 // inline box from the bidi runs walk above has a selection state. |
335 if (rootHasSelectedChildren) | 336 if (rootHasSelectedChildren) |
336 lastLineBox()->root().setHasSelectedChildren(true); | 337 lastLineBox()->root().setHasSelectedChildren(true); |
337 | 338 |
338 // Set bits on our inline flow boxes that indicate which sides should | 339 // Set bits on our inline flow boxes that indicate which sides should |
339 // paint borders/margins/padding. This knowledge will ultimately be used when | 340 // paint borders/margins/padding. This knowledge will ultimately be used when |
340 // we determine the horizontal positions and widths of all the inline boxes on | 341 // we determine the horizontal positions and widths of all the inline boxes on |
341 // the line. | 342 // the line. |
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
645 } | 646 } |
646 | 647 |
647 const SimpleFontData* fontData = font.primaryFont(); | 648 const SimpleFontData* fontData = font.primaryFont(); |
648 DCHECK(fontData); | 649 DCHECK(fontData); |
649 glyphOverflow.setFromBounds( | 650 glyphOverflow.setFromBounds( |
650 glyphBounds, fontData ? fontData->getFontMetrics().floatAscent() : 0, | 651 glyphBounds, fontData ? fontData->getFontMetrics().floatAscent() : 0, |
651 fontData ? fontData->getFontMetrics().floatDescent() : 0, measuredWidth); | 652 fontData ? fontData->getFontMetrics().floatDescent() : 0, measuredWidth); |
652 | 653 |
653 run->m_box->setLogicalWidth(LayoutUnit(measuredWidth) + hyphenWidth); | 654 run->m_box->setLogicalWidth(LayoutUnit(measuredWidth) + hyphenWidth); |
654 if (!fallbackFonts.isEmpty()) { | 655 if (!fallbackFonts.isEmpty()) { |
655 ASSERT(run->m_box->isText()); | 656 DCHECK(run->m_box->isText()); |
656 GlyphOverflowAndFallbackFontsMap::ValueType* it = | 657 GlyphOverflowAndFallbackFontsMap::ValueType* it = |
657 textBoxDataMap | 658 textBoxDataMap |
658 .insert(toInlineTextBox(run->m_box), | 659 .insert(toInlineTextBox(run->m_box), |
659 std::make_pair(Vector<const SimpleFontData*>(), | 660 std::make_pair(Vector<const SimpleFontData*>(), |
660 GlyphOverflow())) | 661 GlyphOverflow())) |
661 .storedValue; | 662 .storedValue; |
662 ASSERT(it->value.first.isEmpty()); | 663 DCHECK(it->value.first.isEmpty()); |
663 copyToVector(fallbackFonts, it->value.first); | 664 copyToVector(fallbackFonts, it->value.first); |
664 run->m_box->parent()->clearDescendantsHaveSameLineHeightAndBaseline(); | 665 run->m_box->parent()->clearDescendantsHaveSameLineHeightAndBaseline(); |
665 } | 666 } |
666 if (!glyphOverflow.isApproximatelyZero()) { | 667 if (!glyphOverflow.isApproximatelyZero()) { |
667 ASSERT(run->m_box->isText()); | 668 DCHECK(run->m_box->isText()); |
668 GlyphOverflowAndFallbackFontsMap::ValueType* it = | 669 GlyphOverflowAndFallbackFontsMap::ValueType* it = |
669 textBoxDataMap | 670 textBoxDataMap |
670 .insert(toInlineTextBox(run->m_box), | 671 .insert(toInlineTextBox(run->m_box), |
671 std::make_pair(Vector<const SimpleFontData*>(), | 672 std::make_pair(Vector<const SimpleFontData*>(), |
672 GlyphOverflow())) | 673 GlyphOverflow())) |
673 .storedValue; | 674 .storedValue; |
674 it->value.second = glyphOverflow; | 675 it->value.second = glyphOverflow; |
675 run->m_box->clearKnownToHaveNoOverflow(); | 676 run->m_box->clearKnownToHaveNoOverflow(); |
676 } | 677 } |
677 } | 678 } |
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
899 void LayoutBlockFlow::computeBlockDirectionPositionsForLine( | 900 void LayoutBlockFlow::computeBlockDirectionPositionsForLine( |
900 RootInlineBox* lineBox, | 901 RootInlineBox* lineBox, |
901 BidiRun* firstRun, | 902 BidiRun* firstRun, |
902 GlyphOverflowAndFallbackFontsMap& textBoxDataMap, | 903 GlyphOverflowAndFallbackFontsMap& textBoxDataMap, |
903 VerticalPositionCache& verticalPositionCache) { | 904 VerticalPositionCache& verticalPositionCache) { |
904 setLogicalHeight(lineBox->alignBoxesInBlockDirection( | 905 setLogicalHeight(lineBox->alignBoxesInBlockDirection( |
905 logicalHeight(), textBoxDataMap, verticalPositionCache)); | 906 logicalHeight(), textBoxDataMap, verticalPositionCache)); |
906 | 907 |
907 // Now make sure we place replaced layout objects correctly. | 908 // Now make sure we place replaced layout objects correctly. |
908 for (BidiRun* r = firstRun; r; r = r->next()) { | 909 for (BidiRun* r = firstRun; r; r = r->next()) { |
909 ASSERT(r->m_box); | 910 DCHECK(r->m_box); |
910 if (!r->m_box) | 911 if (!r->m_box) |
911 continue; // Skip runs with no line boxes. | 912 continue; // Skip runs with no line boxes. |
912 | 913 |
913 // Align positioned boxes with the top of the line box. This is | 914 // Align positioned boxes with the top of the line box. This is |
914 // a reasonable approximation of an appropriate y position. | 915 // a reasonable approximation of an appropriate y position. |
915 if (r->m_lineLayoutItem.isOutOfFlowPositioned()) | 916 if (r->m_lineLayoutItem.isOutOfFlowPositioned()) |
916 r->m_box->setLogicalTop(logicalHeight()); | 917 r->m_box->setLogicalTop(logicalHeight()); |
917 | 918 |
918 // Position is used to properly position both replaced elements and | 919 // Position is used to properly position both replaced elements and |
919 // to update the static normal flow x/y of positioned elements. | 920 // to update the static normal flow x/y of positioned elements. |
920 if (r->m_lineLayoutItem.isText()) | 921 if (r->m_lineLayoutItem.isText()) |
921 toLayoutText(r->m_lineLayoutItem.layoutObject()) | 922 toLayoutText(r->m_lineLayoutItem.layoutObject()) |
922 ->positionLineBox(r->m_box); | 923 ->positionLineBox(r->m_box); |
923 else if (r->m_lineLayoutItem.isBox()) | 924 else if (r->m_lineLayoutItem.isBox()) |
924 toLayoutBox(r->m_lineLayoutItem.layoutObject()) | 925 toLayoutBox(r->m_lineLayoutItem.layoutObject()) |
925 ->positionLineBox(r->m_box); | 926 ->positionLineBox(r->m_box); |
926 } | 927 } |
927 } | 928 } |
928 | 929 |
929 void LayoutBlockFlow::appendFloatingObjectToLastLine( | 930 void LayoutBlockFlow::appendFloatingObjectToLastLine( |
930 FloatingObject& floatingObject) { | 931 FloatingObject& floatingObject) { |
931 ASSERT(!floatingObject.originatingLine()); | 932 DCHECK(!floatingObject.originatingLine()); |
932 floatingObject.setOriginatingLine(lastRootBox()); | 933 floatingObject.setOriginatingLine(lastRootBox()); |
933 lastRootBox()->appendFloat(floatingObject.layoutObject()); | 934 lastRootBox()->appendFloat(floatingObject.layoutObject()); |
934 } | 935 } |
935 | 936 |
936 // This function constructs line boxes for all of the text runs in the resolver | 937 // This function constructs line boxes for all of the text runs in the resolver |
937 // and computes their position. | 938 // and computes their position. |
938 RootInlineBox* LayoutBlockFlow::createLineBoxesFromBidiRuns( | 939 RootInlineBox* LayoutBlockFlow::createLineBoxesFromBidiRuns( |
939 unsigned bidiLevel, | 940 unsigned bidiLevel, |
940 BidiRunList<BidiRun>& bidiRuns, | 941 BidiRunList<BidiRun>& bidiRuns, |
941 const InlineIterator& end, | 942 const InlineIterator& end, |
(...skipping 27 matching lines...) Expand all Loading... |
969 // Now position our text runs vertically. | 970 // Now position our text runs vertically. |
970 computeBlockDirectionPositionsForLine(lineBox, bidiRuns.firstRun(), | 971 computeBlockDirectionPositionsForLine(lineBox, bidiRuns.firstRun(), |
971 textBoxDataMap, verticalPositionCache); | 972 textBoxDataMap, verticalPositionCache); |
972 | 973 |
973 // SVG text layout code computes vertical & horizontal positions on its own. | 974 // SVG text layout code computes vertical & horizontal positions on its own. |
974 // Note that we still need to execute computeVerticalPositionsForLine() as | 975 // Note that we still need to execute computeVerticalPositionsForLine() as |
975 // it calls InlineTextBox::positionLineBox(), which tracks whether the box | 976 // it calls InlineTextBox::positionLineBox(), which tracks whether the box |
976 // contains reversed text or not. If we wouldn't do that editing and thus | 977 // contains reversed text or not. If we wouldn't do that editing and thus |
977 // text selection in RTL boxes would not work as expected. | 978 // text selection in RTL boxes would not work as expected. |
978 if (isSVGRootInlineBox) { | 979 if (isSVGRootInlineBox) { |
979 ASSERT(isSVGText()); | 980 DCHECK(isSVGText()); |
980 toSVGRootInlineBox(lineBox)->computePerCharacterLayoutInformation(); | 981 toSVGRootInlineBox(lineBox)->computePerCharacterLayoutInformation(); |
981 } | 982 } |
982 | 983 |
983 // Compute our overflow now. | 984 // Compute our overflow now. |
984 lineBox->computeOverflow(lineBox->lineTop(), lineBox->lineBottom(), | 985 lineBox->computeOverflow(lineBox->lineTop(), lineBox->lineBottom(), |
985 textBoxDataMap); | 986 textBoxDataMap); |
986 | 987 |
987 return lineBox; | 988 return lineBox; |
988 } | 989 } |
989 | 990 |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1045 LineLayoutState& layoutState, | 1046 LineLayoutState& layoutState, |
1046 const InlineIterator& cleanLineStart, | 1047 const InlineIterator& cleanLineStart, |
1047 const InlineBidiResolver& resolver, | 1048 const InlineBidiResolver& resolver, |
1048 const BidiStatus& cleanLineBidiStatus) { | 1049 const BidiStatus& cleanLineBidiStatus) { |
1049 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); | 1050 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); |
1050 FloatingObjectSetIterator it = floatingObjectSet.begin(); | 1051 FloatingObjectSetIterator it = floatingObjectSet.begin(); |
1051 FloatingObjectSetIterator end = floatingObjectSet.end(); | 1052 FloatingObjectSetIterator end = floatingObjectSet.end(); |
1052 if (layoutState.lastFloat()) { | 1053 if (layoutState.lastFloat()) { |
1053 FloatingObjectSetIterator lastFloatIterator = | 1054 FloatingObjectSetIterator lastFloatIterator = |
1054 floatingObjectSet.find(layoutState.lastFloat()); | 1055 floatingObjectSet.find(layoutState.lastFloat()); |
1055 ASSERT(lastFloatIterator != end); | 1056 DCHECK(lastFloatIterator != end); |
1056 ++lastFloatIterator; | 1057 ++lastFloatIterator; |
1057 it = lastFloatIterator; | 1058 it = lastFloatIterator; |
1058 } | 1059 } |
1059 for (; it != end; ++it) { | 1060 for (; it != end; ++it) { |
1060 FloatingObject& floatingObject = *it->get(); | 1061 FloatingObject& floatingObject = *it->get(); |
1061 // If we've reached the start of clean lines any remaining floating children | 1062 // If we've reached the start of clean lines any remaining floating children |
1062 // belong to them. | 1063 // belong to them. |
1063 if (cleanLineStart.getLineLayoutItem().isEqual( | 1064 if (cleanLineStart.getLineLayoutItem().isEqual( |
1064 floatingObject.layoutObject()) && | 1065 floatingObject.layoutObject()) && |
1065 layoutState.endLine()) { | 1066 layoutState.endLine()) { |
1066 layoutState.setEndLineMatched(layoutState.endLineMatched() || | 1067 layoutState.setEndLineMatched(layoutState.endLineMatched() || |
1067 matchedEndLine(layoutState, resolver, | 1068 matchedEndLine(layoutState, resolver, |
1068 cleanLineStart, | 1069 cleanLineStart, |
1069 cleanLineBidiStatus)); | 1070 cleanLineBidiStatus)); |
1070 if (layoutState.endLineMatched()) { | 1071 if (layoutState.endLineMatched()) { |
1071 layoutState.setLastFloat(&floatingObject); | 1072 layoutState.setLastFloat(&floatingObject); |
1072 return; | 1073 return; |
1073 } | 1074 } |
1074 } | 1075 } |
1075 appendFloatingObjectToLastLine(floatingObject); | 1076 appendFloatingObjectToLastLine(floatingObject); |
1076 ASSERT(floatingObject.layoutObject() == | 1077 DCHECK_EQ(floatingObject.layoutObject(), |
1077 layoutState.floats()[layoutState.floatIndex()].object); | 1078 layoutState.floats()[layoutState.floatIndex()].object); |
1078 // If a float's geometry has changed, give up on syncing with clean lines. | 1079 // If a float's geometry has changed, give up on syncing with clean lines. |
1079 if (layoutState.floats()[layoutState.floatIndex()].rect != | 1080 if (layoutState.floats()[layoutState.floatIndex()].rect != |
1080 floatingObject.frameRect()) { | 1081 floatingObject.frameRect()) { |
1081 // Delete all the remaining lines. | 1082 // Delete all the remaining lines. |
1082 deleteLineRange(layoutState, layoutState.endLine()); | 1083 deleteLineRange(layoutState, layoutState.endLine()); |
1083 layoutState.setEndLine(nullptr); | 1084 layoutState.setEndLine(nullptr); |
1084 } | 1085 } |
1085 layoutState.setFloatIndex(layoutState.floatIndex() + 1); | 1086 layoutState.setFloatIndex(layoutState.floatIndex() + 1); |
1086 } | 1087 } |
1087 layoutState.setLastFloat( | 1088 layoutState.setLastFloat( |
(...skipping 20 matching lines...) Expand all Loading... |
1108 LayoutUnit paginationStrutFromDeletedLine; | 1109 LayoutUnit paginationStrutFromDeletedLine; |
1109 | 1110 |
1110 LineBreaker lineBreaker(LineLayoutBlockFlow(this)); | 1111 LineBreaker lineBreaker(LineLayoutBlockFlow(this)); |
1111 | 1112 |
1112 // We avoid inline capacity to save the stack space. | 1113 // We avoid inline capacity to save the stack space. |
1113 WordMeasurements wordMeasurements; | 1114 WordMeasurements wordMeasurements; |
1114 wordMeasurements.reserveInitialCapacity(64); | 1115 wordMeasurements.reserveInitialCapacity(64); |
1115 | 1116 |
1116 while (!endOfLine.atEnd()) { | 1117 while (!endOfLine.atEnd()) { |
1117 // The runs from the previous line should have been cleaned up. | 1118 // The runs from the previous line should have been cleaned up. |
1118 ASSERT(!resolver.runs().runCount()); | 1119 DCHECK(!resolver.runs().runCount()); |
1119 | 1120 |
1120 // FIXME: Is this check necessary before the first iteration or can it be | 1121 // FIXME: Is this check necessary before the first iteration or can it be |
1121 // moved to the end? | 1122 // moved to the end? |
1122 if (layoutState.endLine()) { | 1123 if (layoutState.endLine()) { |
1123 layoutState.setEndLineMatched(layoutState.endLineMatched() || | 1124 layoutState.setEndLineMatched(layoutState.endLineMatched() || |
1124 matchedEndLine(layoutState, resolver, | 1125 matchedEndLine(layoutState, resolver, |
1125 cleanLineStart, | 1126 cleanLineStart, |
1126 cleanLineBidiStatus)); | 1127 cleanLineBidiStatus)); |
1127 if (layoutState.endLineMatched()) { | 1128 if (layoutState.endLineMatched()) { |
1128 resolver.setPosition(InlineIterator(resolver.position().root(), 0, 0), | 1129 resolver.setPosition(InlineIterator(resolver.position().root(), 0, 0), |
(...skipping 20 matching lines...) Expand all Loading... |
1149 // FIXME: We shouldn't be creating any runs in nextLineBreak to begin | 1150 // FIXME: We shouldn't be creating any runs in nextLineBreak to begin |
1150 // with! Once BidiRunList is separated from BidiResolver this will not be | 1151 // with! Once BidiRunList is separated from BidiResolver this will not be |
1151 // needed. | 1152 // needed. |
1152 resolver.runs().deleteRuns(); | 1153 resolver.runs().deleteRuns(); |
1153 resolver.markCurrentRunEmpty(); // FIXME: This can probably be replaced | 1154 resolver.markCurrentRunEmpty(); // FIXME: This can probably be replaced |
1154 // by an ASSERT (or just removed). | 1155 // by an ASSERT (or just removed). |
1155 resolver.setPosition(InlineIterator(resolver.position().root(), 0, 0), 0); | 1156 resolver.setPosition(InlineIterator(resolver.position().root(), 0, 0), 0); |
1156 break; | 1157 break; |
1157 } | 1158 } |
1158 | 1159 |
1159 ASSERT(endOfLine != resolver.position()); | 1160 DCHECK(endOfLine != resolver.position()); |
1160 RootInlineBox* lineBox = nullptr; | 1161 RootInlineBox* lineBox = nullptr; |
1161 | 1162 |
1162 // This is a short-cut for empty lines. | 1163 // This is a short-cut for empty lines. |
1163 if (layoutState.lineInfo().isEmpty()) { | 1164 if (layoutState.lineInfo().isEmpty()) { |
1164 ASSERT(!paginationStrutFromDeletedLine); | 1165 DCHECK(!paginationStrutFromDeletedLine); |
1165 if (lastRootBox()) | 1166 if (lastRootBox()) |
1166 lastRootBox()->setLineBreakInfo(endOfLine.getLineLayoutItem(), | 1167 lastRootBox()->setLineBreakInfo(endOfLine.getLineLayoutItem(), |
1167 endOfLine.offset(), resolver.status()); | 1168 endOfLine.offset(), resolver.status()); |
1168 resolver.runs().deleteRuns(); | 1169 resolver.runs().deleteRuns(); |
1169 } else { | 1170 } else { |
1170 VisualDirectionOverride override = | 1171 VisualDirectionOverride override = |
1171 (styleToUse.rtlOrdering() == EOrder::kVisual | 1172 (styleToUse.rtlOrdering() == EOrder::kVisual |
1172 ? (styleToUse.direction() == TextDirection::kLtr | 1173 ? (styleToUse.direction() == TextDirection::kLtr |
1173 ? VisualLeftToRightOverride | 1174 ? VisualLeftToRightOverride |
1174 : VisualRightToLeftOverride) | 1175 : VisualRightToLeftOverride) |
(...skipping 14 matching lines...) Expand all Loading... |
1189 layoutState.lineInfo().setTextAlign(textAlign); | 1190 layoutState.lineInfo().setTextAlign(textAlign); |
1190 resolver.setNeedsTrailingSpace( | 1191 resolver.setNeedsTrailingSpace( |
1191 textAlignmentNeedsTrailingSpace(textAlign, styleToUse)); | 1192 textAlignmentNeedsTrailingSpace(textAlign, styleToUse)); |
1192 | 1193 |
1193 // FIXME: This ownership is reversed. We should own the BidiRunList and | 1194 // FIXME: This ownership is reversed. We should own the BidiRunList and |
1194 // pass it to createBidiRunsForLine. | 1195 // pass it to createBidiRunsForLine. |
1195 BidiRunList<BidiRun>& bidiRuns = resolver.runs(); | 1196 BidiRunList<BidiRun>& bidiRuns = resolver.runs(); |
1196 constructBidiRunsForLine( | 1197 constructBidiRunsForLine( |
1197 resolver, bidiRuns, endOfLine, override, | 1198 resolver, bidiRuns, endOfLine, override, |
1198 layoutState.lineInfo().previousLineBrokeCleanly(), isNewUBAParagraph); | 1199 layoutState.lineInfo().previousLineBrokeCleanly(), isNewUBAParagraph); |
1199 ASSERT(resolver.position() == endOfLine); | 1200 DCHECK(resolver.position() == endOfLine); |
1200 | 1201 |
1201 BidiRun* trailingSpaceRun = resolver.trailingSpaceRun(); | 1202 BidiRun* trailingSpaceRun = resolver.trailingSpaceRun(); |
1202 | 1203 |
1203 if (bidiRuns.runCount() && lineBreaker.lineWasHyphenated()) | 1204 if (bidiRuns.runCount() && lineBreaker.lineWasHyphenated()) |
1204 bidiRuns.logicallyLastRun()->m_hasHyphen = true; | 1205 bidiRuns.logicallyLastRun()->m_hasHyphen = true; |
1205 | 1206 |
1206 // Now that the runs have been ordered, we create the line boxes. | 1207 // Now that the runs have been ordered, we create the line boxes. |
1207 // At the same time we figure out where border/padding/margin should be | 1208 // At the same time we figure out where border/padding/margin should be |
1208 // applied for | 1209 // applied for |
1209 // inline flow boxes. | 1210 // inline flow boxes. |
1210 | 1211 |
1211 LayoutUnit oldLogicalHeight = logicalHeight(); | 1212 LayoutUnit oldLogicalHeight = logicalHeight(); |
1212 lineBox = createLineBoxesFromBidiRuns( | 1213 lineBox = createLineBoxesFromBidiRuns( |
1213 resolver.status().context->level(), bidiRuns, endOfLine, | 1214 resolver.status().context->level(), bidiRuns, endOfLine, |
1214 layoutState.lineInfo(), verticalPositionCache, trailingSpaceRun, | 1215 layoutState.lineInfo(), verticalPositionCache, trailingSpaceRun, |
1215 wordMeasurements); | 1216 wordMeasurements); |
1216 | 1217 |
1217 bidiRuns.deleteRuns(); | 1218 bidiRuns.deleteRuns(); |
1218 resolver.markCurrentRunEmpty(); // FIXME: This can probably be replaced | 1219 resolver.markCurrentRunEmpty(); // FIXME: This can probably be replaced |
1219 // by an ASSERT (or just removed). | 1220 // by an ASSERT (or just removed). |
1220 | 1221 |
1221 // If we decided to re-create the line due to pagination, we better have a | 1222 // If we decided to re-create the line due to pagination, we better have a |
1222 // new line now. | 1223 // new line now. |
1223 ASSERT(lineBox || !paginationStrutFromDeletedLine); | 1224 DCHECK(lineBox || !paginationStrutFromDeletedLine); |
1224 | 1225 |
1225 if (lineBox) { | 1226 if (lineBox) { |
1226 lineBox->setLineBreakInfo(endOfLine.getLineLayoutItem(), | 1227 lineBox->setLineBreakInfo(endOfLine.getLineLayoutItem(), |
1227 endOfLine.offset(), resolver.status()); | 1228 endOfLine.offset(), resolver.status()); |
1228 if (recalculateStruts) { | 1229 if (recalculateStruts) { |
1229 if (paginationStrutFromDeletedLine) { | 1230 if (paginationStrutFromDeletedLine) { |
1230 // This is a line that got re-created because it got pushed to the | 1231 // This is a line that got re-created because it got pushed to the |
1231 // next fragmentainer, and there were floats in the vicinity that | 1232 // next fragmentainer, and there were floats in the vicinity that |
1232 // affected the available width. | 1233 // affected the available width. |
1233 // Restore the pagination info for this line. | 1234 // Restore the pagination info for this line. |
(...skipping 13 matching lines...) Expand all Loading... |
1247 oldLogicalHeight + adjustment, | 1248 oldLogicalHeight + adjustment, |
1248 layoutState.lineInfo().isFirstLine() | 1249 layoutState.lineInfo().isFirstLine() |
1249 ? IndentText | 1250 ? IndentText |
1250 : DoNotIndentText) != oldLineWidth) { | 1251 : DoNotIndentText) != oldLineWidth) { |
1251 // We have to delete this line, remove all floats that got | 1252 // We have to delete this line, remove all floats that got |
1252 // added, and let line layout re-run. We had just calculated the | 1253 // added, and let line layout re-run. We had just calculated the |
1253 // pagination strut for this line, and we need to stow it away, | 1254 // pagination strut for this line, and we need to stow it away, |
1254 // so that we can re-apply it when the new line has been | 1255 // so that we can re-apply it when the new line has been |
1255 // created. | 1256 // created. |
1256 paginationStrutFromDeletedLine = lineBox->paginationStrut(); | 1257 paginationStrutFromDeletedLine = lineBox->paginationStrut(); |
1257 ASSERT(paginationStrutFromDeletedLine); | 1258 DCHECK(paginationStrutFromDeletedLine); |
1258 // We're also going to assume that we're right after a page | 1259 // We're also going to assume that we're right after a page |
1259 // break when re-creating this line, so it better be so. | 1260 // break when re-creating this line, so it better be so. |
1260 ASSERT(lineBox->isFirstAfterPageBreak()); | 1261 DCHECK(lineBox->isFirstAfterPageBreak()); |
1261 lineBox->deleteLine(); | 1262 lineBox->deleteLine(); |
1262 endOfLine = restartLayoutRunsAndFloatsInRange( | 1263 endOfLine = restartLayoutRunsAndFloatsInRange( |
1263 oldLogicalHeight, oldLogicalHeight + adjustment, | 1264 oldLogicalHeight, oldLogicalHeight + adjustment, |
1264 lastFloatFromPreviousLine, resolver, previousEndofLine); | 1265 lastFloatFromPreviousLine, resolver, previousEndofLine); |
1265 } else { | 1266 } else { |
1266 setLogicalHeight(lineBox->lineBottomWithLeading()); | 1267 setLogicalHeight(lineBox->lineBottomWithLeading()); |
1267 } | 1268 } |
1268 } | 1269 } |
1269 } | 1270 } |
1270 } | 1271 } |
(...skipping 29 matching lines...) Expand all Loading... |
1300 appendFloatsToLastLine(layoutState, cleanLineStart, endOfLineResolver, | 1301 appendFloatsToLastLine(layoutState, cleanLineStart, endOfLineResolver, |
1301 cleanLineBidiStatus); | 1302 cleanLineBidiStatus); |
1302 } | 1303 } |
1303 } | 1304 } |
1304 | 1305 |
1305 lineMidpointState.reset(); | 1306 lineMidpointState.reset(); |
1306 resolver.setPosition(endOfLine, numberOfIsolateAncestors(endOfLine)); | 1307 resolver.setPosition(endOfLine, numberOfIsolateAncestors(endOfLine)); |
1307 } | 1308 } |
1308 | 1309 |
1309 // The resolver runs should have been cleared, otherwise they're leaking. | 1310 // The resolver runs should have been cleared, otherwise they're leaking. |
1310 ASSERT(!resolver.runs().runCount()); | 1311 DCHECK(!resolver.runs().runCount()); |
1311 | 1312 |
1312 // In case we already adjusted the line positions during this layout to avoid | 1313 // In case we already adjusted the line positions during this layout to avoid |
1313 // widows then we need to ignore the possibility of having a new widows | 1314 // widows then we need to ignore the possibility of having a new widows |
1314 // situation. Otherwise, we risk leaving empty containers which is against the | 1315 // situation. Otherwise, we risk leaving empty containers which is against the |
1315 // block fragmentation principles. | 1316 // block fragmentation principles. |
1316 if (paginated && style()->widows() > 1 && !didBreakAtLineToAvoidWidow()) { | 1317 if (paginated && style()->widows() > 1 && !didBreakAtLineToAvoidWidow()) { |
1317 // Check the line boxes to make sure we didn't create unacceptable widows. | 1318 // Check the line boxes to make sure we didn't create unacceptable widows. |
1318 // However, we'll prioritize orphans - so nothing we do here should create | 1319 // However, we'll prioritize orphans - so nothing we do here should create |
1319 // a new orphan. | 1320 // a new orphan. |
1320 | 1321 |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1391 line->attachLine(); | 1392 line->attachLine(); |
1392 if (recalculateStruts) { | 1393 if (recalculateStruts) { |
1393 delta -= line->paginationStrut(); | 1394 delta -= line->paginationStrut(); |
1394 adjustLinePositionForPagination(*line, delta); | 1395 adjustLinePositionForPagination(*line, delta); |
1395 } | 1396 } |
1396 if (delta) | 1397 if (delta) |
1397 line->moveInBlockDirection(delta); | 1398 line->moveInBlockDirection(delta); |
1398 if (Vector<LayoutBox*>* cleanLineFloats = line->floatsPtr()) { | 1399 if (Vector<LayoutBox*>* cleanLineFloats = line->floatsPtr()) { |
1399 for (auto* box : *cleanLineFloats) { | 1400 for (auto* box : *cleanLineFloats) { |
1400 FloatingObject* floatingObject = insertFloatingObject(*box); | 1401 FloatingObject* floatingObject = insertFloatingObject(*box); |
1401 ASSERT(!floatingObject->originatingLine()); | 1402 DCHECK(!floatingObject->originatingLine()); |
1402 floatingObject->setOriginatingLine(line); | 1403 floatingObject->setOriginatingLine(line); |
1403 LayoutUnit logicalTop = | 1404 LayoutUnit logicalTop = |
1404 logicalTopForChild(*box) - marginBeforeForChild(*box) + delta; | 1405 logicalTopForChild(*box) - marginBeforeForChild(*box) + delta; |
1405 placeNewFloats(logicalTop); | 1406 placeNewFloats(logicalTop); |
1406 } | 1407 } |
1407 } | 1408 } |
1408 } | 1409 } |
1409 setLogicalHeight(lastRootBox()->lineBottomWithLeading()); | 1410 setLogicalHeight(lastRootBox()->lineBottomWithLeading()); |
1410 } else { | 1411 } else { |
1411 // Delete all the remaining lines. | 1412 // Delete all the remaining lines. |
(...skipping 668 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2080 // If we encountered a new float and have inline children, mark ourself to | 2081 // If we encountered a new float and have inline children, mark ourself to |
2081 // force us to issue paint invalidations. | 2082 // force us to issue paint invalidations. |
2082 if (layoutState.hasInlineChild() && !selfNeedsLayout()) { | 2083 if (layoutState.hasInlineChild() && !selfNeedsLayout()) { |
2083 setNeedsLayoutAndFullPaintInvalidation( | 2084 setNeedsLayoutAndFullPaintInvalidation( |
2084 LayoutInvalidationReason::FloatDescendantChanged, MarkOnlyThis); | 2085 LayoutInvalidationReason::FloatDescendantChanged, MarkOnlyThis); |
2085 setShouldDoFullPaintInvalidation(); | 2086 setShouldDoFullPaintInvalidation(); |
2086 } | 2087 } |
2087 | 2088 |
2088 deleteLineBoxTree(); | 2089 deleteLineBoxTree(); |
2089 curr = nullptr; | 2090 curr = nullptr; |
2090 ASSERT(!firstLineBox() && !lastLineBox()); | 2091 DCHECK(!firstLineBox()); |
| 2092 DCHECK(!lastLineBox()); |
2091 } else { | 2093 } else { |
2092 if (firstLineBoxWithBreakAndClearance) | 2094 if (firstLineBoxWithBreakAndClearance) |
2093 curr = firstLineBoxWithBreakAndClearance; | 2095 curr = firstLineBoxWithBreakAndClearance; |
2094 if (curr) { | 2096 if (curr) { |
2095 // We have a dirty line. | 2097 // We have a dirty line. |
2096 if (RootInlineBox* prevRootBox = curr->prevRootBox()) { | 2098 if (RootInlineBox* prevRootBox = curr->prevRootBox()) { |
2097 // We have a previous line. | 2099 // We have a previous line. |
2098 if (!prevRootBox->endsWithBreak() || !prevRootBox->lineBreakObj() || | 2100 if (!prevRootBox->endsWithBreak() || !prevRootBox->lineBreakObj() || |
2099 (prevRootBox->lineBreakObj().isText() && | 2101 (prevRootBox->lineBreakObj().isText() && |
2100 prevRootBox->lineBreakPos() >= | 2102 prevRootBox->lineBreakPos() >= |
(...skipping 16 matching lines...) Expand all Loading... |
2117 } | 2119 } |
2118 | 2120 |
2119 unsigned numCleanFloats = 0; | 2121 unsigned numCleanFloats = 0; |
2120 if (!layoutState.floats().isEmpty()) { | 2122 if (!layoutState.floats().isEmpty()) { |
2121 // Restore floats from clean lines. | 2123 // Restore floats from clean lines. |
2122 RootInlineBox* line = firstRootBox(); | 2124 RootInlineBox* line = firstRootBox(); |
2123 while (line != curr) { | 2125 while (line != curr) { |
2124 if (Vector<LayoutBox*>* cleanLineFloats = line->floatsPtr()) { | 2126 if (Vector<LayoutBox*>* cleanLineFloats = line->floatsPtr()) { |
2125 for (auto* box : *cleanLineFloats) { | 2127 for (auto* box : *cleanLineFloats) { |
2126 FloatingObject* floatingObject = insertFloatingObject(*box); | 2128 FloatingObject* floatingObject = insertFloatingObject(*box); |
2127 ASSERT(!floatingObject->originatingLine()); | 2129 DCHECK(!floatingObject->originatingLine()); |
2128 floatingObject->setOriginatingLine(line); | 2130 floatingObject->setOriginatingLine(line); |
2129 LayoutUnit logicalTop = | 2131 LayoutUnit logicalTop = |
2130 logicalTopForChild(*box) - marginBeforeForChild(*box); | 2132 logicalTopForChild(*box) - marginBeforeForChild(*box); |
2131 placeNewFloats(logicalTop); | 2133 placeNewFloats(logicalTop); |
2132 ASSERT(layoutState.floats()[numCleanFloats].object == box); | 2134 DCHECK_EQ(layoutState.floats()[numCleanFloats].object, box); |
2133 numCleanFloats++; | 2135 numCleanFloats++; |
2134 } | 2136 } |
2135 } | 2137 } |
2136 line = line->nextRootBox(); | 2138 line = line->nextRootBox(); |
2137 } | 2139 } |
2138 } | 2140 } |
2139 layoutState.setFloatIndex(numCleanFloats); | 2141 layoutState.setFloatIndex(numCleanFloats); |
2140 | 2142 |
2141 layoutState.lineInfo().setFirstLine(!last); | 2143 layoutState.lineInfo().setFirstLine(!last); |
2142 layoutState.lineInfo().setPreviousLineBrokeCleanly(!last || | 2144 layoutState.lineInfo().setPreviousLineBrokeCleanly(!last || |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2175 ? curr->lastLeafChild() | 2177 ? curr->lastLeafChild() |
2176 : curr->firstLeafChild(); | 2178 : curr->firstLeafChild(); |
2177 return lastBox && lastBox->getLineLayoutItem().isBR() && | 2179 return lastBox && lastBox->getLineLayoutItem().isBR() && |
2178 lastBox->getLineLayoutItem().style()->clear() != EClear::kNone; | 2180 lastBox->getLineLayoutItem().style()->clear() != EClear::kNone; |
2179 } | 2181 } |
2180 | 2182 |
2181 void LayoutBlockFlow::determineEndPosition(LineLayoutState& layoutState, | 2183 void LayoutBlockFlow::determineEndPosition(LineLayoutState& layoutState, |
2182 RootInlineBox* startLine, | 2184 RootInlineBox* startLine, |
2183 InlineIterator& cleanLineStart, | 2185 InlineIterator& cleanLineStart, |
2184 BidiStatus& cleanLineBidiStatus) { | 2186 BidiStatus& cleanLineBidiStatus) { |
2185 ASSERT(!layoutState.endLine()); | 2187 DCHECK(!layoutState.endLine()); |
2186 RootInlineBox* last = nullptr; | 2188 RootInlineBox* last = nullptr; |
2187 for (RootInlineBox* curr = startLine->nextRootBox(); curr; | 2189 for (RootInlineBox* curr = startLine->nextRootBox(); curr; |
2188 curr = curr->nextRootBox()) { | 2190 curr = curr->nextRootBox()) { |
2189 if (!curr->isDirty() && lineBoxHasBRWithClearance(curr)) | 2191 if (!curr->isDirty() && lineBoxHasBRWithClearance(curr)) |
2190 return; | 2192 return; |
2191 | 2193 |
2192 if (curr->isDirty()) | 2194 if (curr->isDirty()) |
2193 last = nullptr; | 2195 last = nullptr; |
2194 else if (!last) | 2196 else if (!last) |
2195 last = curr; | 2197 last = curr; |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2300 return matched; | 2302 return matched; |
2301 } | 2303 } |
2302 } | 2304 } |
2303 | 2305 |
2304 return false; | 2306 return false; |
2305 } | 2307 } |
2306 | 2308 |
2307 bool LayoutBlockFlow::generatesLineBoxesForInlineChild(LayoutObject* inlineObj) | 2309 bool LayoutBlockFlow::generatesLineBoxesForInlineChild(LayoutObject* inlineObj) |
2308 | 2310 |
2309 { | 2311 { |
2310 ASSERT(inlineObj->parent() == this); | 2312 DCHECK_EQ(inlineObj->parent(), this); |
2311 | 2313 |
2312 InlineIterator it(LineLayoutBlockFlow(this), LineLayoutItem(inlineObj), 0); | 2314 InlineIterator it(LineLayoutBlockFlow(this), LineLayoutItem(inlineObj), 0); |
2313 // FIXME: We should pass correct value for WhitespacePosition. | 2315 // FIXME: We should pass correct value for WhitespacePosition. |
2314 while (!it.atEnd() && !requiresLineBox(it)) | 2316 while (!it.atEnd() && !requiresLineBox(it)) |
2315 it.increment(); | 2317 it.increment(); |
2316 | 2318 |
2317 return !it.atEnd(); | 2319 return !it.atEnd(); |
2318 } | 2320 } |
2319 | 2321 |
2320 void LayoutBlockFlow::addOverflowFromInlineChildren() { | 2322 void LayoutBlockFlow::addOverflowFromInlineChildren() { |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2409 *firstLineStyle(), ellipsisDirection)); | 2411 *firstLineStyle(), ellipsisDirection)); |
2410 } else { | 2412 } else { |
2411 selectedEllipsisStr = fullstopCharacterStr; | 2413 selectedEllipsisStr = fullstopCharacterStr; |
2412 firstLineEllipsisWidth = firstLineFont.width( | 2414 firstLineEllipsisWidth = firstLineFont.width( |
2413 constructTextRun(firstLineFont, fullStopString, fullStopStringLength, | 2415 constructTextRun(firstLineFont, fullStopString, fullStopStringLength, |
2414 *firstLineStyle(), ellipsisDirection)); | 2416 *firstLineStyle(), ellipsisDirection)); |
2415 } | 2417 } |
2416 ellipsisWidth = (font == firstLineFont) ? firstLineEllipsisWidth : 0; | 2418 ellipsisWidth = (font == firstLineFont) ? firstLineEllipsisWidth : 0; |
2417 | 2419 |
2418 if (!ellipsisWidth) { | 2420 if (!ellipsisWidth) { |
2419 ASSERT(font.primaryFont()); | 2421 DCHECK(font.primaryFont()); |
2420 if (font.primaryFont()->glyphForCharacter(horizontalEllipsisCharacter)) { | 2422 if (font.primaryFont()->glyphForCharacter(horizontalEllipsisCharacter)) { |
2421 ellipsisWidth = | 2423 ellipsisWidth = |
2422 font.width(constructTextRun(font, &horizontalEllipsisCharacter, 1, | 2424 font.width(constructTextRun(font, &horizontalEllipsisCharacter, 1, |
2423 styleRef(), ellipsisDirection)); | 2425 styleRef(), ellipsisDirection)); |
2424 } else { | 2426 } else { |
2425 selectedEllipsisStr = fullstopCharacterStr; | 2427 selectedEllipsisStr = fullstopCharacterStr; |
2426 ellipsisWidth = font.width( | 2428 ellipsisWidth = font.width( |
2427 constructTextRun(font, fullStopString, fullStopStringLength, | 2429 constructTextRun(font, fullStopString, fullStopStringLength, |
2428 styleRef(), ellipsisDirection)); | 2430 styleRef(), ellipsisDirection)); |
2429 } | 2431 } |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2607 logicalRightOffsetForLine(logicalHeight(), DoNotIndentText) - logicalLeft; | 2609 logicalRightOffsetForLine(logicalHeight(), DoNotIndentText) - logicalLeft; |
2608 updateLogicalWidthForAlignment(textAlign, 0, 0, logicalLeft, | 2610 updateLogicalWidthForAlignment(textAlign, 0, 0, logicalLeft, |
2609 totalLogicalWidth, availableLogicalWidth, 0); | 2611 totalLogicalWidth, availableLogicalWidth, 0); |
2610 | 2612 |
2611 if (!style()->isLeftToRightDirection()) | 2613 if (!style()->isLeftToRightDirection()) |
2612 return logicalWidth() - logicalLeft; | 2614 return logicalWidth() - logicalLeft; |
2613 return logicalLeft; | 2615 return logicalLeft; |
2614 } | 2616 } |
2615 | 2617 |
2616 void LayoutBlockFlow::setShouldDoFullPaintInvalidationForFirstLine() { | 2618 void LayoutBlockFlow::setShouldDoFullPaintInvalidationForFirstLine() { |
2617 ASSERT(childrenInline()); | 2619 DCHECK(childrenInline()); |
2618 if (RootInlineBox* firstRootBox = this->firstRootBox()) | 2620 if (RootInlineBox* firstRootBox = this->firstRootBox()) |
2619 firstRootBox->setShouldDoFullPaintInvalidationRecursively(); | 2621 firstRootBox->setShouldDoFullPaintInvalidationRecursively(); |
2620 } | 2622 } |
2621 | 2623 |
2622 bool LayoutBlockFlow::paintedOutputOfObjectHasNoEffectRegardlessOfSize() const { | 2624 bool LayoutBlockFlow::paintedOutputOfObjectHasNoEffectRegardlessOfSize() const { |
2623 // LayoutBlockFlow is in charge of paint invalidation of the first line. | 2625 // LayoutBlockFlow is in charge of paint invalidation of the first line. |
2624 if (firstLineBox()) | 2626 if (firstLineBox()) |
2625 return false; | 2627 return false; |
2626 | 2628 |
2627 return LayoutBlock::paintedOutputOfObjectHasNoEffectRegardlessOfSize(); | 2629 return LayoutBlock::paintedOutputOfObjectHasNoEffectRegardlessOfSize(); |
2628 } | 2630 } |
2629 | 2631 |
2630 } // namespace blink | 2632 } // namespace blink |
OLD | NEW |