OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2000 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 2000 Lars Knoll (knoll@kde.org) |
3 * Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All r
ight reserved. | 3 * Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All r
ight reserved. |
4 * Copyright (C) 2010 Google Inc. All rights reserved. | 4 * Copyright (C) 2010 Google Inc. All rights reserved. |
5 * | 5 * |
6 * This library is free software; you can redistribute it and/or | 6 * This library is free software; you can redistribute it and/or |
7 * modify it under the terms of the GNU Library General Public | 7 * modify it under the terms of the GNU Library General Public |
8 * License as published by the Free Software Foundation; either | 8 * License as published by the Free Software Foundation; either |
9 * 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. |
10 * | 10 * |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
59 // Destruction of m_layout requires TextLayout to be a complete type, so the
constructor and destructor are made non-inline to avoid compilation errors. | 59 // Destruction of m_layout requires TextLayout to be a complete type, so the
constructor and destructor are made non-inline to avoid compilation errors. |
60 RenderTextInfo(); | 60 RenderTextInfo(); |
61 ~RenderTextInfo(); | 61 ~RenderTextInfo(); |
62 | 62 |
63 RenderText* m_text; | 63 RenderText* m_text; |
64 OwnPtr<TextLayout> m_layout; | 64 OwnPtr<TextLayout> m_layout; |
65 LazyLineBreakIterator m_lineBreakIterator; | 65 LazyLineBreakIterator m_lineBreakIterator; |
66 const Font* m_font; | 66 const Font* m_font; |
67 }; | 67 }; |
68 | 68 |
69 class LineBreaker { | 69 class TrailingObjects { |
70 public: | 70 public: |
71 LineBreaker(RenderBlock* block) | 71 TrailingObjects(); |
72 : m_block(block) | 72 void setTrailingWhitespace(RenderText*); |
73 { | 73 void clear(); |
74 reset(); | 74 void appendBoxIfNeeded(RenderBox*); |
75 } | |
76 | 75 |
77 InlineIterator nextLineBreak(InlineBidiResolver&, LineInfo&, RenderTextInfo&
, FloatingObject* lastFloatFromPreviousLine, unsigned consecutiveHyphenatedLines
, WordMeasurements&); | 76 enum CollapseFirstSpaceOrNot { DoNotCollapseFirstSpace, CollapseFirstSpace }
; |
78 | 77 |
79 bool lineWasHyphenated() { return m_hyphenated; } | 78 void updateMidpointsForTrailingBoxes(LineMidpointState&, const InlineIterato
r& lBreak, CollapseFirstSpaceOrNot); |
80 const Vector<RenderBox*>& positionedObjects() { return m_positionedObjects;
} | 79 |
81 EClear clear() { return m_clear; } | |
82 private: | 80 private: |
83 void reset(); | 81 RenderText* m_whitespace; |
84 | 82 Vector<RenderBox*, 4> m_boxes; |
85 InlineIterator nextSegmentBreak(InlineBidiResolver&, LineInfo&, RenderTextIn
fo&, FloatingObject* lastFloatFromPreviousLine, unsigned consecutiveHyphenatedLi
nes, WordMeasurements&); | |
86 void skipTrailingWhitespace(InlineIterator&, const LineInfo&); | |
87 void skipLeadingWhitespace(InlineBidiResolver&, LineInfo&, FloatingObject* l
astFloatFromPreviousLine, LineWidth&); | |
88 | |
89 RenderBlock* m_block; | |
90 bool m_hyphenated; | |
91 EClear m_clear; | |
92 Vector<RenderBox*> m_positionedObjects; | |
93 }; | 83 }; |
94 | 84 |
95 ShapeInsideInfo* RenderBlock::layoutShapeInsideInfo() const | |
96 { | |
97 ShapeInsideInfo* shapeInsideInfo = view()->layoutState()->shapeInsideInfo(); | |
98 | |
99 if (!shapeInsideInfo && flowThreadContainingBlock() && allowsShapeInsideInfo
Sharing()) { | |
100 LayoutUnit lineHeight = this->lineHeight(false, isHorizontalWritingMode(
) ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes); | |
101 // regionAtBlockOffset returns regions like an array first={0,N-1}, seco
nd={N,M-1}, ... | |
102 LayoutUnit offset = logicalHeight() + lineHeight - LayoutUnit(1); | |
103 RenderRegion* region = regionAtBlockOffset(offset); | |
104 if (region) | |
105 shapeInsideInfo = region->shapeInsideInfo(); | |
106 } | |
107 | |
108 return shapeInsideInfo; | |
109 } | |
110 | |
111 class LineInfo { | 85 class LineInfo { |
112 public: | 86 public: |
113 LineInfo() | 87 LineInfo() |
114 : m_isFirstLine(true) | 88 : m_isFirstLine(true) |
115 , m_isLastLine(false) | 89 , m_isLastLine(false) |
116 , m_isEmpty(true) | 90 , m_isEmpty(true) |
117 , m_previousLineBrokeCleanly(true) | 91 , m_previousLineBrokeCleanly(true) |
118 , m_floatPaginationStrut(0) | 92 , m_floatPaginationStrut(0) |
119 , m_runsFromLeadingWhitespace(0) | 93 , m_runsFromLeadingWhitespace(0) |
120 { } | 94 { } |
(...skipping 26 matching lines...) Expand all Loading... |
147 | 121 |
148 private: | 122 private: |
149 bool m_isFirstLine; | 123 bool m_isFirstLine; |
150 bool m_isLastLine; | 124 bool m_isLastLine; |
151 bool m_isEmpty; | 125 bool m_isEmpty; |
152 bool m_previousLineBrokeCleanly; | 126 bool m_previousLineBrokeCleanly; |
153 LayoutUnit m_floatPaginationStrut; | 127 LayoutUnit m_floatPaginationStrut; |
154 unsigned m_runsFromLeadingWhitespace; | 128 unsigned m_runsFromLeadingWhitespace; |
155 }; | 129 }; |
156 | 130 |
| 131 static IndentTextOrNot requiresIndent(bool isFirstLine, bool isAfterHardLineBrea
k, RenderStyle* style) |
| 132 { |
| 133 if (isFirstLine) |
| 134 return IndentText; |
| 135 if (isAfterHardLineBreak && style->textIndentLine() == TextIndentEachLine) |
| 136 return IndentText; |
| 137 |
| 138 return DoNotIndentText; |
| 139 } |
| 140 |
| 141 class LineBreaker { |
| 142 public: |
| 143 LineBreaker(RenderBlock* block) |
| 144 : m_block(block) |
| 145 { |
| 146 reset(); |
| 147 } |
| 148 |
| 149 InlineIterator nextLineBreak(InlineBidiResolver&, LineInfo&, RenderTextInfo&
, FloatingObject* lastFloatFromPreviousLine, unsigned consecutiveHyphenatedLines
, WordMeasurements&); |
| 150 |
| 151 bool lineWasHyphenated() { return m_hyphenated; } |
| 152 const Vector<RenderBox*>& positionedObjects() { return m_positionedObjects;
} |
| 153 EClear clear() { return m_clear; } |
| 154 private: |
| 155 void reset(); |
| 156 |
| 157 InlineIterator nextSegmentBreak(InlineBidiResolver&, LineInfo&, RenderTextIn
fo&, FloatingObject* lastFloatFromPreviousLine, unsigned consecutiveHyphenatedLi
nes, WordMeasurements&); |
| 158 |
| 159 class BreakingContext { |
| 160 public: |
| 161 BreakingContext(InlineBidiResolver& resolver, LineInfo& inLineInfo, Line
Width& lineWidth, RenderTextInfo& inRenderTextInfo, FloatingObject* inLastFloatF
romPreviousLine, bool appliedStartWidth, RenderBlock* block) |
| 162 : m_resolver(resolver) |
| 163 , m_current(resolver.position()) |
| 164 , m_lineBreak(resolver.position()) |
| 165 , m_lastObject(m_current.m_obj) |
| 166 , m_block(block) |
| 167 , m_blockStyle(block->style()) |
| 168 , m_lineInfo(inLineInfo) |
| 169 , m_renderTextInfo(inRenderTextInfo) |
| 170 , m_lastFloatFromPreviousLine(inLastFloatFromPreviousLine) |
| 171 , m_width(lineWidth) |
| 172 , m_preservesNewline(m_current.m_obj->isSVGInlineText() ? false : Re
nderStyle::preserveNewline(m_currWS)) |
| 173 , m_atStart(true) |
| 174 , m_ignoringSpaces(false) |
| 175 , m_currentCharacterIsSpace(false) |
| 176 , m_currentCharacterShouldCollapseIfPreWap(false) |
| 177 , m_appliedStartWidth(appliedStartWidth) |
| 178 , m_includeEndWidth(true) |
| 179 , m_autoWrap(RenderStyle::autoWrap(m_currWS)) |
| 180 , m_autoWrapWasEverTrueOnLine(m_autoWrap) |
| 181 , m_floatsFitOnLine(true) |
| 182 , m_collapseWhiteSpace(RenderStyle::collapseWhiteSpace(m_currWS)) |
| 183 , m_startingNewParagraph(m_lineInfo.previousLineBrokeCleanly()) |
| 184 , m_allowImagesToBreak(!block->document().inQuirksMode() || !block->
isTableCell() || !m_blockStyle->logicalWidth().isIntrinsicOrAuto()) |
| 185 , m_atEnd(false) |
| 186 , m_lineMidpointState(resolver.midpointState()) |
| 187 { |
| 188 m_lineInfo.setPreviousLineBrokeCleanly(false); |
| 189 } |
| 190 |
| 191 void setupContext(); |
| 192 |
| 193 RenderObject* currentObject() { return m_current.m_obj; } |
| 194 InlineIterator lineBreak() { return m_lineBreak; } |
| 195 bool atEnd() { return m_atEnd; } |
| 196 |
| 197 void initializeForCurrentObject(); |
| 198 |
| 199 void increment(); |
| 200 |
| 201 void handleBR(EClear&); |
| 202 void handleOutOfFlowPositioned(Vector<RenderBox*>& positionedObjects); |
| 203 void handleFloat(); |
| 204 void handleEmptyInline(); |
| 205 void handleReplaced(); |
| 206 bool handleText(WordMeasurements&, bool& hyphenated); |
| 207 void commitAndUpdateLineBreakIfNeeded(); |
| 208 InlineIterator handleEndOfLine(); |
| 209 |
| 210 void clearLineBreakIfFitsOnLine() |
| 211 { |
| 212 if (m_width.fitsOnLine() || m_lastWS == NOWRAP) |
| 213 m_lineBreak.clear(); |
| 214 } |
| 215 |
| 216 private: |
| 217 void skipTrailingWhitespace(InlineIterator&, const LineInfo&); |
| 218 |
| 219 InlineBidiResolver& m_resolver; |
| 220 |
| 221 InlineIterator m_current; |
| 222 InlineIterator m_lineBreak; |
| 223 InlineIterator m_startOfIgnoredSpaces; |
| 224 |
| 225 RenderBlock* m_block; |
| 226 RenderObject* m_lastObject; |
| 227 RenderObject* m_nextObject; |
| 228 |
| 229 RenderStyle* m_currentStyle; |
| 230 RenderStyle* m_blockStyle; |
| 231 |
| 232 LineInfo& m_lineInfo; |
| 233 |
| 234 RenderTextInfo& m_renderTextInfo; |
| 235 |
| 236 FloatingObject* m_lastFloatFromPreviousLine; |
| 237 |
| 238 LineWidth m_width; |
| 239 |
| 240 EWhiteSpace m_currWS; |
| 241 EWhiteSpace m_lastWS; |
| 242 |
| 243 bool m_preservesNewline; |
| 244 bool m_atStart; |
| 245 bool m_ignoringSpaces; |
| 246 bool m_currentCharacterIsSpace; |
| 247 bool m_currentCharacterShouldCollapseIfPreWap; |
| 248 bool m_appliedStartWidth; |
| 249 bool m_includeEndWidth; |
| 250 bool m_autoWrap; |
| 251 bool m_autoWrapWasEverTrueOnLine; |
| 252 bool m_floatsFitOnLine; |
| 253 bool m_collapseWhiteSpace; |
| 254 bool m_startingNewParagraph; |
| 255 bool m_allowImagesToBreak; |
| 256 bool m_atEnd; |
| 257 |
| 258 LineMidpointState& m_lineMidpointState; |
| 259 |
| 260 TrailingObjects m_trailingObjects; |
| 261 }; |
| 262 |
| 263 void skipLeadingWhitespace(InlineBidiResolver&, LineInfo&, FloatingObject* l
astFloatFromPreviousLine, LineWidth&); |
| 264 |
| 265 RenderBlock* m_block; |
| 266 bool m_hyphenated; |
| 267 EClear m_clear; |
| 268 Vector<RenderBox*> m_positionedObjects; |
| 269 }; |
| 270 |
| 271 inline void LineBreaker::BreakingContext::initializeForCurrentObject() |
| 272 { |
| 273 m_currentStyle = m_current.m_obj->style(); |
| 274 m_nextObject = bidiNextSkippingEmptyInlines(m_block, m_current.m_obj); |
| 275 if (m_nextObject && m_nextObject->parent() && !m_nextObject->parent()->isDes
cendantOf(m_current.m_obj->parent())) |
| 276 m_includeEndWidth = true; |
| 277 |
| 278 m_currWS = m_current.m_obj->isReplaced() ? m_current.m_obj->parent()->style(
)->whiteSpace() : m_currentStyle->whiteSpace(); |
| 279 m_lastWS = m_lastObject->isReplaced() ? m_lastObject->parent()->style()->whi
teSpace() : m_lastObject->style()->whiteSpace(); |
| 280 |
| 281 m_autoWrap = RenderStyle::autoWrap(m_currWS); |
| 282 m_autoWrapWasEverTrueOnLine = m_autoWrapWasEverTrueOnLine || m_autoWrap; |
| 283 |
| 284 m_preservesNewline = m_current.m_obj->isSVGInlineText() ? false : RenderStyl
e::preserveNewline(m_currWS); |
| 285 |
| 286 m_collapseWhiteSpace = RenderStyle::collapseWhiteSpace(m_currWS); |
| 287 } |
| 288 |
| 289 inline void LineBreaker::BreakingContext::increment() |
| 290 { |
| 291 // Clear out our character space bool, since inline <pre>s don't collapse wh
itespace |
| 292 // with adjacent inline normal/nowrap spans. |
| 293 if (!m_collapseWhiteSpace) |
| 294 m_currentCharacterIsSpace = false; |
| 295 |
| 296 m_current.moveToStartOf(m_nextObject); |
| 297 m_atStart = false; |
| 298 } |
| 299 |
| 300 ShapeInsideInfo* RenderBlock::layoutShapeInsideInfo() const |
| 301 { |
| 302 ShapeInsideInfo* shapeInsideInfo = view()->layoutState()->shapeInsideInfo(); |
| 303 |
| 304 if (!shapeInsideInfo && flowThreadContainingBlock() && allowsShapeInsideInfo
Sharing()) { |
| 305 LayoutUnit lineHeight = this->lineHeight(false, isHorizontalWritingMode(
) ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes); |
| 306 // regionAtBlockOffset returns regions like an array first={0,N-1}, seco
nd={N,M-1}, ... |
| 307 LayoutUnit offset = logicalHeight() + lineHeight - LayoutUnit(1); |
| 308 RenderRegion* region = regionAtBlockOffset(offset); |
| 309 if (region) |
| 310 shapeInsideInfo = region->shapeInsideInfo(); |
| 311 } |
| 312 |
| 313 return shapeInsideInfo; |
| 314 } |
| 315 |
157 static inline LayoutUnit borderPaddingMarginStart(RenderInline* child) | 316 static inline LayoutUnit borderPaddingMarginStart(RenderInline* child) |
158 { | 317 { |
159 return child->marginStart() + child->paddingStart() + child->borderStart(); | 318 return child->marginStart() + child->paddingStart() + child->borderStart(); |
160 } | 319 } |
161 | 320 |
162 static inline LayoutUnit borderPaddingMarginEnd(RenderInline* child) | 321 static inline LayoutUnit borderPaddingMarginEnd(RenderInline* child) |
163 { | 322 { |
164 return child->marginEnd() + child->paddingEnd() + child->borderEnd(); | 323 return child->marginEnd() + child->paddingEnd() + child->borderEnd(); |
165 } | 324 } |
166 | 325 |
(...skipping 658 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
825 break; | 984 break; |
826 case TAEND: | 985 case TAEND: |
827 if (direction == LTR) | 986 if (direction == LTR) |
828 updateLogicalWidthForRightAlignedBlock(style()->isLeftToRightDirecti
on(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth); | 987 updateLogicalWidthForRightAlignedBlock(style()->isLeftToRightDirecti
on(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth); |
829 else | 988 else |
830 updateLogicalWidthForLeftAlignedBlock(style()->isLeftToRightDirectio
n(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth); | 989 updateLogicalWidthForLeftAlignedBlock(style()->isLeftToRightDirectio
n(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth); |
831 break; | 990 break; |
832 } | 991 } |
833 } | 992 } |
834 | 993 |
835 static IndentTextOrNot requiresIndent(bool isFirstLine, bool isAfterHardLineBrea
k, RenderStyle* style) | |
836 { | |
837 if (isFirstLine) | |
838 return IndentText; | |
839 if (isAfterHardLineBreak && style->textIndentLine() == TextIndentEachLine) | |
840 return IndentText; | |
841 | |
842 return DoNotIndentText; | |
843 } | |
844 | |
845 static void updateLogicalInlinePositions(RenderBlock* block, float& lineLogicalL
eft, float& lineLogicalRight, float& availableLogicalWidth, bool firstLine, Inde
ntTextOrNot shouldIndentText, LayoutUnit boxLogicalHeight) | 994 static void updateLogicalInlinePositions(RenderBlock* block, float& lineLogicalL
eft, float& lineLogicalRight, float& availableLogicalWidth, bool firstLine, Inde
ntTextOrNot shouldIndentText, LayoutUnit boxLogicalHeight) |
846 { | 995 { |
847 LayoutUnit lineLogicalHeight = block->minLineHeightForReplacedRenderer(first
Line, boxLogicalHeight); | 996 LayoutUnit lineLogicalHeight = block->minLineHeightForReplacedRenderer(first
Line, boxLogicalHeight); |
848 lineLogicalLeft = block->pixelSnappedLogicalLeftOffsetForLine(block->logical
Height(), shouldIndentText == IndentText, lineLogicalHeight); | 997 lineLogicalLeft = block->pixelSnappedLogicalLeftOffsetForLine(block->logical
Height(), shouldIndentText == IndentText, lineLogicalHeight); |
849 lineLogicalRight = block->pixelSnappedLogicalRightOffsetForLine(block->logic
alHeight(), shouldIndentText == IndentText, lineLogicalHeight); | 998 lineLogicalRight = block->pixelSnappedLogicalRightOffsetForLine(block->logic
alHeight(), shouldIndentText == IndentText, lineLogicalHeight); |
850 availableLogicalWidth = lineLogicalRight - lineLogicalLeft; | 999 availableLogicalWidth = lineLogicalRight - lineLogicalLeft; |
851 } | 1000 } |
852 | 1001 |
853 void RenderBlock::computeInlineDirectionPositionsForLine(RootInlineBox* lineBox,
const LineInfo& lineInfo, BidiRun* firstRun, BidiRun* trailingSpaceRun, bool re
achedEnd, | 1002 void RenderBlock::computeInlineDirectionPositionsForLine(RootInlineBox* lineBox,
const LineInfo& lineInfo, BidiRun* firstRun, BidiRun* trailingSpaceRun, bool re
achedEnd, |
854 GlyphOverflowAndFallbac
kFontsMap& textBoxDataMap, VerticalPositionCache& verticalPositionCache, WordMea
surements& wordMeasurements) | 1003 GlyphOverflowAndFallbac
kFontsMap& textBoxDataMap, VerticalPositionCache& verticalPositionCache, WordMea
surements& wordMeasurements) |
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1104 floatingObject->setOriginatingLine(lastRootBox()); | 1253 floatingObject->setOriginatingLine(lastRootBox()); |
1105 lastRootBox()->appendFloat(floatingObject->renderer()); | 1254 lastRootBox()->appendFloat(floatingObject->renderer()); |
1106 } | 1255 } |
1107 | 1256 |
1108 // FIXME: This should be a BidiStatus constructor or create method. | 1257 // FIXME: This should be a BidiStatus constructor or create method. |
1109 static inline BidiStatus statusWithDirection(TextDirection textDirection, bool i
sOverride) | 1258 static inline BidiStatus statusWithDirection(TextDirection textDirection, bool i
sOverride) |
1110 { | 1259 { |
1111 WTF::Unicode::Direction direction = textDirection == LTR ? LeftToRight : Rig
htToLeft; | 1260 WTF::Unicode::Direction direction = textDirection == LTR ? LeftToRight : Rig
htToLeft; |
1112 RefPtr<BidiContext> context = BidiContext::create(textDirection == LTR ? 0 :
1, direction, isOverride, FromStyleOrDOM); | 1261 RefPtr<BidiContext> context = BidiContext::create(textDirection == LTR ? 0 :
1, direction, isOverride, FromStyleOrDOM); |
1113 | 1262 |
1114 // This copies BidiStatus and may churn the ref on BidiContext. I doubt it m
atters. | 1263 // This copies BidiStatus and may churn the ref on BidiContext I doubt it ma
tters. |
1115 return BidiStatus(direction, direction, direction, context.release()); | 1264 return BidiStatus(direction, direction, direction, context.release()); |
1116 } | 1265 } |
1117 | 1266 |
1118 static inline void setupResolverToResumeInIsolate(InlineBidiResolver& resolver,
RenderObject* root, RenderObject* startObject) | 1267 static inline void setupResolverToResumeInIsolate(InlineBidiResolver& resolver,
RenderObject* root, RenderObject* startObject) |
1119 { | 1268 { |
1120 if (root != startObject) { | 1269 if (root != startObject) { |
1121 RenderObject* parent = startObject->parent(); | 1270 RenderObject* parent = startObject->parent(); |
1122 setupResolverToResumeInIsolate(resolver, root, parent); | 1271 setupResolverToResumeInIsolate(resolver, root, parent); |
1123 notifyObserverEnteredObject(&resolver, startObject); | 1272 notifyObserverEnteredObject(&resolver, startObject); |
1124 } | 1273 } |
(...skipping 1230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2355 | 2504 |
2356 return !it.atEnd(); | 2505 return !it.atEnd(); |
2357 } | 2506 } |
2358 | 2507 |
2359 // FIXME: The entire concept of the skipTrailingWhitespace function is flawed, s
ince we really need to be building | 2508 // FIXME: The entire concept of the skipTrailingWhitespace function is flawed, s
ince we really need to be building |
2360 // line boxes even for containers that may ultimately collapse away. Otherwise w
e'll never get positioned | 2509 // line boxes even for containers that may ultimately collapse away. Otherwise w
e'll never get positioned |
2361 // elements quite right. In other words, we need to build this function's work i
nto the normal line | 2510 // elements quite right. In other words, we need to build this function's work i
nto the normal line |
2362 // object iteration process. | 2511 // object iteration process. |
2363 // NB. this function will insert any floating elements that would otherwise | 2512 // NB. this function will insert any floating elements that would otherwise |
2364 // be skipped but it will not position them. | 2513 // be skipped but it will not position them. |
2365 void LineBreaker::skipTrailingWhitespace(InlineIterator& iterator, const LineInf
o& lineInfo) | 2514 inline void LineBreaker::BreakingContext::skipTrailingWhitespace(InlineIterator&
iterator, const LineInfo& lineInfo) |
2366 { | 2515 { |
2367 while (!iterator.atEnd() && !requiresLineBox(iterator, lineInfo, TrailingWhi
tespace)) { | 2516 while (!iterator.atEnd() && !requiresLineBox(iterator, lineInfo, TrailingWhi
tespace)) { |
2368 RenderObject* object = iterator.m_obj; | 2517 RenderObject* object = iterator.m_obj; |
2369 if (object->isOutOfFlowPositioned()) | 2518 if (object->isOutOfFlowPositioned()) |
2370 setStaticPositions(m_block, toRenderBox(object)); | 2519 setStaticPositions(m_block, toRenderBox(object)); |
2371 else if (object->isFloating()) | 2520 else if (object->isFloating()) |
2372 m_block->insertFloatingObject(toRenderBox(object)); | 2521 m_block->insertFloatingObject(toRenderBox(object)); |
2373 iterator.increment(); | 2522 iterator.increment(); |
2374 } | 2523 } |
2375 } | 2524 } |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2435 TextRun run = RenderBlock::constructTextRun(text, font, text, from, len, tex
t->style()); | 2584 TextRun run = RenderBlock::constructTextRun(text, font, text, from, len, tex
t->style()); |
2436 run.setCharactersLength(text->textLength() - from); | 2585 run.setCharactersLength(text->textLength() - from); |
2437 ASSERT(run.charactersLength() >= run.length()); | 2586 ASSERT(run.charactersLength() >= run.length()); |
2438 | 2587 |
2439 run.setCharacterScanForCodePath(!text->canUseSimpleFontCodePath()); | 2588 run.setCharacterScanForCodePath(!text->canUseSimpleFontCodePath()); |
2440 run.setTabSize(!collapseWhiteSpace, text->style()->tabSize()); | 2589 run.setTabSize(!collapseWhiteSpace, text->style()->tabSize()); |
2441 run.setXPos(xPos); | 2590 run.setXPos(xPos); |
2442 return font.width(run, fallbackFonts, &glyphOverflow); | 2591 return font.width(run, fallbackFonts, &glyphOverflow); |
2443 } | 2592 } |
2444 | 2593 |
2445 class TrailingObjects { | |
2446 public: | |
2447 TrailingObjects(); | |
2448 void setTrailingWhitespace(RenderText*); | |
2449 void clear(); | |
2450 void appendBoxIfNeeded(RenderBox*); | |
2451 | |
2452 enum CollapseFirstSpaceOrNot { DoNotCollapseFirstSpace, CollapseFirstSpace }
; | |
2453 | |
2454 void updateMidpointsForTrailingBoxes(LineMidpointState&, const InlineIterato
r& lBreak, CollapseFirstSpaceOrNot); | |
2455 | |
2456 private: | |
2457 RenderText* m_whitespace; | |
2458 Vector<RenderBox*, 4> m_boxes; | |
2459 }; | |
2460 | |
2461 TrailingObjects::TrailingObjects() | 2594 TrailingObjects::TrailingObjects() |
2462 : m_whitespace(0) | 2595 : m_whitespace(0) |
2463 { | 2596 { |
2464 } | 2597 } |
2465 | 2598 |
2466 inline void TrailingObjects::setTrailingWhitespace(RenderText* whitespace) | 2599 inline void TrailingObjects::setTrailingWhitespace(RenderText* whitespace) |
2467 { | 2600 { |
2468 ASSERT(whitespace); | 2601 ASSERT(whitespace); |
2469 m_whitespace = whitespace; | 2602 m_whitespace = whitespace; |
2470 } | 2603 } |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2581 } | 2714 } |
2582 resolver.setPositionIgnoringNestedIsolates(oldEnd); | 2715 resolver.setPositionIgnoringNestedIsolates(oldEnd); |
2583 return end; | 2716 return end; |
2584 } | 2717 } |
2585 | 2718 |
2586 static inline bool iteratorIsBeyondEndOfRenderCombineText(const InlineIterator&
iter, RenderCombineText* renderer) | 2719 static inline bool iteratorIsBeyondEndOfRenderCombineText(const InlineIterator&
iter, RenderCombineText* renderer) |
2587 { | 2720 { |
2588 return iter.m_obj == renderer && iter.m_pos >= renderer->textLength(); | 2721 return iter.m_obj == renderer && iter.m_pos >= renderer->textLength(); |
2589 } | 2722 } |
2590 | 2723 |
2591 InlineIterator LineBreaker::nextSegmentBreak(InlineBidiResolver& resolver, LineI
nfo& lineInfo, RenderTextInfo& renderTextInfo, FloatingObject* lastFloatFromPrev
iousLine, unsigned consecutiveHyphenatedLines, WordMeasurements& wordMeasurement
s) | 2724 inline void LineBreaker::BreakingContext::handleBR(EClear& clear) |
2592 { | 2725 { |
2593 reset(); | 2726 if (m_width.fitsOnLine()) { |
2594 | 2727 RenderObject* br = m_current.m_obj; |
2595 ASSERT(resolver.position().root() == m_block); | 2728 m_lineBreak.moveToStartOf(br); |
2596 | 2729 m_lineBreak.increment(); |
2597 bool appliedStartWidth = resolver.position().m_pos > 0; | 2730 |
2598 bool includeEndWidth = true; | 2731 // A <br> always breaks a line, so don't let the line be collapsed |
2599 LineMidpointState& lineMidpointState = resolver.midpointState(); | 2732 // away. Also, the space at the end of a line with a <br> does not |
2600 | 2733 // get collapsed away. It only does this if the previous line broke |
2601 LineWidth width(*m_block, lineInfo.isFirstLine(), requiresIndent(lineInfo.is
FirstLine(), lineInfo.previousLineBrokeCleanly(), m_block->style())); | 2734 // cleanly. Otherwise the <br> has no effect on whether the line is |
2602 | 2735 // empty or not. |
2603 skipLeadingWhitespace(resolver, lineInfo, lastFloatFromPreviousLine, width); | 2736 if (m_startingNewParagraph) |
2604 | 2737 m_lineInfo.setEmpty(false, m_block, &m_width); |
2605 if (resolver.position().atEnd()) | 2738 m_trailingObjects.clear(); |
2606 return resolver.position(); | 2739 m_lineInfo.setPreviousLineBrokeCleanly(true); |
2607 | 2740 |
2608 // This variable is used only if whitespace isn't set to PRE, and it tells u
s whether | 2741 // A <br> with clearance always needs a linebox in case the lines below
it get dirtied later and |
2609 // or not we are currently ignoring whitespace. | 2742 // need to check for floats to clear - so if we're ignoring spaces, stop
ignoring them and add a |
2610 bool ignoringSpaces = false; | 2743 // run for this object. |
2611 InlineIterator ignoreStart; | 2744 if (m_ignoringSpaces && m_currentStyle->clear() != CNONE) |
2612 | 2745 ensureLineBoxInsideIgnoredSpaces(m_lineMidpointState, br); |
2613 // This variable tracks whether the very last character we saw was a space.
We use | 2746 |
2614 // this to detect when we encounter a second space so we know we have to ter
minate | 2747 if (!m_lineInfo.isEmpty()) |
2615 // a run. | 2748 clear = m_currentStyle->clear(); |
2616 bool currentCharacterIsSpace = false; | 2749 } |
2617 bool currentCharacterShouldCollapseIfPreWap = false; | 2750 m_atEnd = true; |
2618 TrailingObjects trailingObjects; | 2751 } |
2619 | 2752 |
2620 InlineIterator lBreak = resolver.position(); | 2753 inline void LineBreaker::BreakingContext::handleOutOfFlowPositioned(Vector<Rende
rBox*>& positionedObjects) |
2621 | 2754 { |
2622 // FIXME: It is error-prone to split the position object out like this. | 2755 // If our original display wasn't an inline type, then we can |
2623 // Teach this code to work with objects instead of this split tuple. | 2756 // go ahead and determine our static inline position now. |
2624 InlineIterator current = resolver.position(); | 2757 RenderBox* box = toRenderBox(m_current.m_obj); |
2625 RenderObject* last = current.m_obj; | 2758 bool isInlineType = box->style()->isOriginalDisplayInlineType(); |
2626 bool atStart = true; | 2759 if (!isInlineType) { |
2627 | 2760 m_block->setStaticInlinePositionForChild(box, m_block->logicalHeight(),
m_block->startOffsetForContent(m_block->logicalHeight())); |
2628 bool startingNewParagraph = lineInfo.previousLineBrokeCleanly(); | 2761 } else { |
2629 lineInfo.setPreviousLineBrokeCleanly(false); | 2762 // If our original display was an INLINE type, then we can go ahead |
2630 | 2763 // and determine our static y position now. |
2631 bool autoWrapWasEverTrueOnLine = false; | 2764 box->layer()->setStaticBlockPosition(m_block->logicalHeight()); |
2632 bool floatsFitOnLine = true; | 2765 } |
2633 | 2766 |
2634 // Firefox and Opera will allow a table cell to grow to fit an image inside
it under | 2767 // If we're ignoring spaces, we have to stop and include this object and |
2635 // very specific circumstances (in order to match common WinIE renderings). | 2768 // then start ignoring spaces again. |
2636 // Not supporting the quirk has caused us to mis-render some real sites. (Se
e Bugzilla 10517.) | 2769 if (isInlineType || box->container()->isRenderInline()) { |
2637 RenderStyle* blockStyle = m_block->style(); | 2770 if (m_ignoringSpaces) |
2638 bool allowImagesToBreak = !m_block->document().inQuirksMode() || !m_block->i
sTableCell() || !blockStyle->logicalWidth().isIntrinsicOrAuto(); | 2771 ensureLineBoxInsideIgnoredSpaces(m_lineMidpointState, box); |
2639 | 2772 m_trailingObjects.appendBoxIfNeeded(box); |
2640 EWhiteSpace currWS = blockStyle->whiteSpace(); | 2773 } else { |
2641 EWhiteSpace lastWS = currWS; | 2774 positionedObjects.append(box); |
2642 while (current.m_obj) { | 2775 } |
2643 RenderStyle* currentStyle = current.m_obj->style(); | 2776 m_width.addUncommittedWidth(inlineLogicalWidth(box)); |
2644 RenderObject* next = bidiNextSkippingEmptyInlines(m_block, current.m_obj
); | 2777 // Reset prior line break context characters. |
2645 if (next && next->parent() && !next->parent()->isDescendantOf(current.m_
obj->parent())) | 2778 m_renderTextInfo.m_lineBreakIterator.resetPriorContext(); |
2646 includeEndWidth = true; | 2779 } |
2647 | 2780 |
2648 currWS = current.m_obj->isReplaced() ? current.m_obj->parent()->style()-
>whiteSpace() : currentStyle->whiteSpace(); | 2781 inline void LineBreaker::BreakingContext::handleFloat() |
2649 lastWS = last->isReplaced() ? last->parent()->style()->whiteSpace() : la
st->style()->whiteSpace(); | 2782 { |
2650 | 2783 RenderBox* floatBox = toRenderBox(m_current.m_obj); |
2651 bool autoWrap = RenderStyle::autoWrap(currWS); | 2784 FloatingObject* floatingObject = m_block->insertFloatingObject(floatBox); |
2652 autoWrapWasEverTrueOnLine = autoWrapWasEverTrueOnLine || autoWrap; | 2785 // check if it fits in the current line. |
2653 | 2786 // If it does, position it now, otherwise, position |
2654 bool preserveNewline = current.m_obj->isSVGInlineText() ? false : Render
Style::preserveNewline(currWS); | 2787 // it after moving to next line (in newLine() func) |
2655 | 2788 // FIXME: Bug 110372: Properly position multiple stacked floats with non-rec
tangular shape outside. |
2656 bool collapseWhiteSpace = RenderStyle::collapseWhiteSpace(currWS); | 2789 if (m_floatsFitOnLine && m_width.fitsOnLine(floatingObject->logicalWidth(m_b
lock->isHorizontalWritingMode()))) { |
2657 | 2790 m_block->positionNewFloatOnLine(floatingObject, m_lastFloatFromPreviousL
ine, m_lineInfo, m_width); |
2658 if (current.m_obj->isBR()) { | 2791 if (m_lineBreak.m_obj == m_current.m_obj) { |
2659 if (width.fitsOnLine()) { | 2792 ASSERT(!m_lineBreak.m_pos); |
2660 lBreak.moveToStartOf(current.m_obj); | 2793 m_lineBreak.increment(); |
2661 lBreak.increment(); | 2794 } |
2662 | 2795 } else { |
2663 // A <br> always breaks a line, so don't let the line be collaps
ed | 2796 m_floatsFitOnLine = false; |
2664 // away. Also, the space at the end of a line with a <br> does n
ot | 2797 } |
2665 // get collapsed away. It only does this if the previous line b
roke | 2798 // Update prior line break context characters, using U+FFFD (OBJECT REPLACEM
ENT CHARACTER) for floating element. |
2666 // cleanly. Otherwise the <br> has no effect on whether the lin
e is | 2799 m_renderTextInfo.m_lineBreakIterator.updatePriorContext(replacementCharacter
); |
2667 // empty or not. | 2800 } |
2668 if (startingNewParagraph) | 2801 |
2669 lineInfo.setEmpty(false, m_block, &width); | 2802 inline void LineBreaker::BreakingContext::handleEmptyInline() |
2670 trailingObjects.clear(); | 2803 { |
2671 lineInfo.setPreviousLineBrokeCleanly(true); | 2804 // This should only end up being called on empty inlines |
2672 | 2805 ASSERT(isEmptyInline(m_current.m_obj)); |
2673 // A <br> with clearance always needs a linebox in case the line
s below it get dirtied later and | 2806 |
2674 // need to check for floats to clear - so if we're ignoring spac
es, stop ignoring them and add a | 2807 RenderInline* flowBox = toRenderInline(m_current.m_obj); |
2675 // run for this object. | 2808 |
2676 if (ignoringSpaces && currentStyle->clear() != CNONE) | 2809 // Now that some inline flows have line boxes, if we are already ignoring sp
aces, we need |
2677 ensureLineBoxInsideIgnoredSpaces(lineMidpointState, current.
m_obj); | 2810 // to make sure that we stop to include this object and then start ignoring
spaces again. |
2678 | 2811 // If this object is at the start of the line, we need to behave like list m
arkers and |
2679 if (!lineInfo.isEmpty()) | 2812 // start ignoring spaces. |
2680 m_clear = currentStyle->clear(); | 2813 bool requiresLineBox = alwaysRequiresLineBox(m_current.m_obj); |
2681 } | 2814 if (requiresLineBox || requiresLineBoxForContent(flowBox, m_lineInfo)) { |
2682 goto end; | 2815 // An empty inline that only has line-height, vertical-align or font-met
rics will only get a |
2683 } | 2816 // line box to affect the height of the line if the rest of the line is
not empty. |
2684 | 2817 if (requiresLineBox) |
2685 if (current.m_obj->isOutOfFlowPositioned()) { | 2818 m_lineInfo.setEmpty(false, m_block, &m_width); |
2686 // If our original display wasn't an inline type, then we can | 2819 if (m_ignoringSpaces) { |
2687 // go ahead and determine our static inline position now. | 2820 m_trailingObjects.clear(); |
2688 RenderBox* box = toRenderBox(current.m_obj); | 2821 ensureLineBoxInsideIgnoredSpaces(m_lineMidpointState, m_current.m_ob
j); |
2689 bool isInlineType = box->style()->isOriginalDisplayInlineType(); | 2822 } else if (m_blockStyle->collapseWhiteSpace() && m_resolver.position().m
_obj == m_current.m_obj |
2690 if (!isInlineType) | 2823 && shouldSkipWhitespaceAfterStartObject(m_block, m_current.m_obj, m_
lineMidpointState)) { |
2691 m_block->setStaticInlinePositionForChild(box, m_block->logicalHe
ight(), m_block->startOffsetForContent(m_block->logicalHeight())); | 2824 // Like with list markers, we start ignoring spaces to make sure tha
t any |
2692 else { | 2825 // additional spaces we see will be discarded. |
2693 // If our original display was an INLINE type, then we can go ah
ead | 2826 m_currentCharacterShouldCollapseIfPreWap = m_currentCharacterIsSpace
= true; |
2694 // and determine our static y position now. | 2827 m_ignoringSpaces = true; |
2695 box->layer()->setStaticBlockPosition(m_block->logicalHeight()); | 2828 } |
2696 } | 2829 } |
2697 | 2830 |
2698 // If we're ignoring spaces, we have to stop and include this object
and | 2831 m_width.addUncommittedWidth(inlineLogicalWidth(m_current.m_obj) + borderPadd
ingMarginStart(flowBox) + borderPaddingMarginEnd(flowBox)); |
2699 // then start ignoring spaces again. | 2832 } |
2700 if (isInlineType || current.m_obj->container()->isRenderInline()) { | 2833 |
2701 if (ignoringSpaces) | 2834 inline void LineBreaker::BreakingContext::handleReplaced() |
2702 ensureLineBoxInsideIgnoredSpaces(lineMidpointState, current.
m_obj); | 2835 { |
2703 trailingObjects.appendBoxIfNeeded(box); | 2836 RenderBox* replacedBox = toRenderBox(m_current.m_obj); |
2704 } else | 2837 |
2705 m_positionedObjects.append(box); | 2838 if (m_atStart) |
2706 width.addUncommittedWidth(inlineLogicalWidth(current.m_obj)); | 2839 m_width.updateAvailableWidth(replacedBox->logicalHeight()); |
2707 // Reset prior line break context characters. | 2840 |
2708 renderTextInfo.m_lineBreakIterator.resetPriorContext(); | 2841 // Break on replaced elements if either has normal white-space. |
2709 } else if (current.m_obj->isFloating()) { | 2842 if ((m_autoWrap || RenderStyle::autoWrap(m_lastWS)) && (!m_current.m_obj->is
Image() || m_allowImagesToBreak)) { |
2710 RenderBox* floatBox = toRenderBox(current.m_obj); | 2843 m_width.commit(); |
2711 FloatingObject* f = m_block->insertFloatingObject(floatBox); | 2844 m_lineBreak.moveToStartOf(m_current.m_obj); |
2712 // check if it fits in the current line. | 2845 } |
2713 // If it does, position it now, otherwise, position | 2846 |
2714 // it after moving to next line (in newLine() func) | 2847 if (m_ignoringSpaces) |
2715 // FIXME: Bug 110372: Properly position multiple stacked floats with
non-rectangular shape outside. | 2848 stopIgnoringSpaces(m_lineMidpointState, InlineIterator(0, m_current.m_ob
j, 0)); |
2716 if (floatsFitOnLine && width.fitsOnLine(f->logicalWidth(m_block->isH
orizontalWritingMode()))) { | 2849 |
2717 m_block->positionNewFloatOnLine(f, lastFloatFromPreviousLine, li
neInfo, width); | 2850 m_lineInfo.setEmpty(false, m_block, &m_width); |
2718 if (lBreak.m_obj == current.m_obj) { | 2851 m_ignoringSpaces = false; |
2719 ASSERT(!lBreak.m_pos); | 2852 m_currentCharacterShouldCollapseIfPreWap = m_currentCharacterIsSpace = false
; |
2720 lBreak.increment(); | 2853 m_trailingObjects.clear(); |
| 2854 |
| 2855 // Optimize for a common case. If we can't find whitespace after the list |
| 2856 // item, then this is all moot. |
| 2857 LayoutUnit replacedLogicalWidth = m_block->logicalWidthForChild(replacedBox)
+ m_block->marginStartForChild(replacedBox) + m_block->marginEndForChild(replac
edBox) + inlineLogicalWidth(m_current.m_obj); |
| 2858 if (m_current.m_obj->isListMarker()) { |
| 2859 if (m_blockStyle->collapseWhiteSpace() && shouldSkipWhitespaceAfterStart
Object(m_block, m_current.m_obj, m_lineMidpointState)) { |
| 2860 // Like with inline flows, we start ignoring spaces to make sure tha
t any |
| 2861 // additional spaces we see will be discarded. |
| 2862 m_currentCharacterShouldCollapseIfPreWap = m_currentCharacterIsSpace
= true; |
| 2863 m_ignoringSpaces = true; |
| 2864 } |
| 2865 if (toRenderListMarker(m_current.m_obj)->isInside()) |
| 2866 m_width.addUncommittedWidth(replacedLogicalWidth); |
| 2867 } else { |
| 2868 m_width.addUncommittedWidth(replacedLogicalWidth); |
| 2869 } |
| 2870 if (m_current.m_obj->isRubyRun()) |
| 2871 m_width.applyOverhang(toRenderRubyRun(m_current.m_obj), m_lastObject, m_
nextObject); |
| 2872 // Update prior line break context characters, using U+FFFD (OBJECT REPLACEM
ENT CHARACTER) for replaced element. |
| 2873 m_renderTextInfo.m_lineBreakIterator.updatePriorContext(replacementCharacter
); |
| 2874 } |
| 2875 |
| 2876 static inline void nextCharacter(UChar& currentCharacter, UChar& lastCharacter,
UChar& secondToLastCharacter) |
| 2877 { |
| 2878 secondToLastCharacter = lastCharacter; |
| 2879 lastCharacter = currentCharacter; |
| 2880 } |
| 2881 |
| 2882 inline bool LineBreaker::BreakingContext::handleText(WordMeasurements& wordMeasu
rements, bool& hyphenated) |
| 2883 { |
| 2884 if (!m_current.m_pos) |
| 2885 m_appliedStartWidth = false; |
| 2886 |
| 2887 RenderText* renderText = toRenderText(m_current.m_obj); |
| 2888 |
| 2889 bool isSVGText = renderText->isSVGInlineText(); |
| 2890 |
| 2891 if (renderText->style()->hasTextCombine() && m_current.m_obj->isCombineText(
) && !toRenderCombineText(m_current.m_obj)->isCombined()) { |
| 2892 RenderCombineText* combineRenderer = toRenderCombineText(m_current.m_obj
); |
| 2893 combineRenderer->combineText(); |
| 2894 // The length of the renderer's text may have changed. Increment stale i
terator positions |
| 2895 if (iteratorIsBeyondEndOfRenderCombineText(m_lineBreak, combineRenderer)
) { |
| 2896 ASSERT(iteratorIsBeyondEndOfRenderCombineText(m_resolver.position(),
combineRenderer)); |
| 2897 m_lineBreak.increment(); |
| 2898 m_resolver.position().increment(&m_resolver); |
| 2899 } |
| 2900 } |
| 2901 |
| 2902 RenderStyle* style = renderText->style(m_lineInfo.isFirstLine()); |
| 2903 const Font& font = style->font(); |
| 2904 bool isFixedPitch = font.isFixedPitch(); |
| 2905 |
| 2906 unsigned lastSpace = m_current.m_pos; |
| 2907 float wordSpacing = m_currentStyle->wordSpacing(); |
| 2908 float lastSpaceWordSpacing = 0; |
| 2909 float wordSpacingForWordMeasurement = 0; |
| 2910 |
| 2911 float wrapW = m_width.uncommittedWidth() + inlineLogicalWidth(m_current.m_ob
j, !m_appliedStartWidth, true); |
| 2912 float charWidth = 0; |
| 2913 // Auto-wrapping text should wrap in the middle of a word only if it could n
ot wrap before the word, |
| 2914 // which is only possible if the word is the first thing on the line, that i
s, if |w| is zero. |
| 2915 bool breakWords = m_currentStyle->breakWords() && ((m_autoWrap && !m_width.c
ommittedWidth()) || m_currWS == PRE); |
| 2916 bool midWordBreak = false; |
| 2917 bool breakAll = m_currentStyle->wordBreak() == BreakAllWordBreak && m_autoWr
ap; |
| 2918 float hyphenWidth = 0; |
| 2919 |
| 2920 if (isSVGText) { |
| 2921 breakWords = false; |
| 2922 breakAll = false; |
| 2923 } |
| 2924 |
| 2925 if (renderText->isWordBreak()) { |
| 2926 m_width.commit(); |
| 2927 m_lineBreak.moveToStartOf(m_current.m_obj); |
| 2928 ASSERT(m_current.m_pos == renderText->textLength()); |
| 2929 } |
| 2930 |
| 2931 if (m_renderTextInfo.m_text != renderText) { |
| 2932 m_renderTextInfo.m_text = renderText; |
| 2933 m_renderTextInfo.m_font = &font; |
| 2934 m_renderTextInfo.m_layout = font.createLayout(renderText, m_width.curren
tWidth(), m_collapseWhiteSpace); |
| 2935 m_renderTextInfo.m_lineBreakIterator.resetStringAndReleaseIterator(rende
rText->text(), style->locale()); |
| 2936 } else if (m_renderTextInfo.m_layout && m_renderTextInfo.m_font != &font) { |
| 2937 m_renderTextInfo.m_font = &font; |
| 2938 m_renderTextInfo.m_layout = font.createLayout(renderText, m_width.curren
tWidth(), m_collapseWhiteSpace); |
| 2939 } |
| 2940 |
| 2941 TextLayout* textLayout = m_renderTextInfo.m_layout.get(); |
| 2942 |
| 2943 // Non-zero only when kerning is enabled and TextLayout isn't used, in which
case we measure |
| 2944 // words with their trailing space, then subtract its width. |
| 2945 float wordTrailingSpaceWidth = (font.typesettingFeatures() & Kerning) && !te
xtLayout ? font.width(RenderBlock::constructTextRun(renderText, font, &space, 1,
style)) + wordSpacing : 0; |
| 2946 |
| 2947 UChar lastCharacter = m_renderTextInfo.m_lineBreakIterator.lastCharacter(); |
| 2948 UChar secondToLastCharacter = m_renderTextInfo.m_lineBreakIterator.secondToL
astCharacter(); |
| 2949 for (; m_current.m_pos < renderText->textLength(); m_current.fastIncrementIn
TextNode()) { |
| 2950 bool previousCharacterIsSpace = m_currentCharacterIsSpace; |
| 2951 bool previousCharacterShouldCollapseIfPreWap = m_currentCharacterShouldC
ollapseIfPreWap; |
| 2952 UChar c = m_current.current(); |
| 2953 m_currentCharacterShouldCollapseIfPreWap = m_currentCharacterIsSpace = c
== ' ' || c == '\t' || (!m_preservesNewline && (c == '\n')); |
| 2954 |
| 2955 if (!m_collapseWhiteSpace || !m_currentCharacterIsSpace) |
| 2956 m_lineInfo.setEmpty(false, m_block, &m_width); |
| 2957 |
| 2958 if (c == softHyphen && m_autoWrap && !hyphenWidth) { |
| 2959 hyphenWidth = measureHyphenWidth(renderText, font); |
| 2960 m_width.addUncommittedWidth(hyphenWidth); |
| 2961 } |
| 2962 |
| 2963 bool applyWordSpacing = false; |
| 2964 |
| 2965 if ((breakAll || breakWords) && !midWordBreak) { |
| 2966 wrapW += charWidth; |
| 2967 bool midWordBreakIsBeforeSurrogatePair = U16_IS_LEAD(c) && m_current
.m_pos + 1 < renderText->textLength() && U16_IS_TRAIL((*renderText)[m_current.m_
pos + 1]); |
| 2968 charWidth = textWidth(renderText, m_current.m_pos, midWordBreakIsBef
oreSurrogatePair ? 2 : 1, font, m_width.committedWidth() + wrapW, isFixedPitch,
m_collapseWhiteSpace, 0, textLayout); |
| 2969 midWordBreak = m_width.committedWidth() + wrapW + charWidth > m_widt
h.availableWidth(); |
| 2970 } |
| 2971 |
| 2972 bool betweenWords = c == '\n' || (m_currWS != PRE && !m_atStart && isBre
akable(m_renderTextInfo.m_lineBreakIterator, m_current.m_pos, m_current.m_nextBr
eakablePosition)); |
| 2973 |
| 2974 if (betweenWords || midWordBreak) { |
| 2975 bool stoppedIgnoringSpaces = false; |
| 2976 if (m_ignoringSpaces) { |
| 2977 lastSpaceWordSpacing = 0; |
| 2978 if (!m_currentCharacterIsSpace) { |
| 2979 // Stop ignoring spaces and begin at this |
| 2980 // new point. |
| 2981 m_ignoringSpaces = false; |
| 2982 wordSpacingForWordMeasurement = 0; |
| 2983 lastSpace = m_current.m_pos; // e.g., "Foo goo", don't ad
d in any of the ignored spaces. |
| 2984 stopIgnoringSpaces(m_lineMidpointState, InlineIterator(0, m_
current.m_obj, m_current.m_pos)); |
| 2985 stoppedIgnoringSpaces = true; |
| 2986 } else { |
| 2987 // Just keep ignoring these spaces. |
| 2988 nextCharacter(c, lastCharacter, secondToLastCharacter); |
| 2989 continue; |
2721 } | 2990 } |
2722 } else | 2991 } |
2723 floatsFitOnLine = false; | 2992 |
2724 // Update prior line break context characters, using U+FFFD (OBJECT
REPLACEMENT CHARACTER) for floating element. | 2993 wordMeasurements.grow(wordMeasurements.size() + 1); |
2725 renderTextInfo.m_lineBreakIterator.updatePriorContext(replacementCha
racter); | 2994 WordMeasurement& wordMeasurement = wordMeasurements.last(); |
2726 } else if (current.m_obj->isRenderInline()) { | 2995 |
2727 // Right now, we should only encounter empty inlines here. | 2996 wordMeasurement.renderer = renderText; |
2728 ASSERT(isEmptyInline(current.m_obj)); | 2997 wordMeasurement.endOffset = m_current.m_pos; |
2729 | 2998 wordMeasurement.startOffset = lastSpace; |
2730 RenderInline* flowBox = toRenderInline(current.m_obj); | 2999 |
2731 | 3000 float additionalTmpW; |
2732 // Now that some inline flows have line boxes, if we are already ign
oring spaces, we need | 3001 if (wordTrailingSpaceWidth && c == ' ') |
2733 // to make sure that we stop to include this object and then start i
gnoring spaces again. | 3002 additionalTmpW = textWidth(renderText, lastSpace, m_current.m_po
s + 1 - lastSpace, font, m_width.currentWidth(), isFixedPitch, m_collapseWhiteSp
ace, &wordMeasurement.fallbackFonts, textLayout) - wordTrailingSpaceWidth; |
2734 // If this object is at the start of the line, we need to behave lik
e list markers and | 3003 else |
2735 // start ignoring spaces. | 3004 additionalTmpW = textWidth(renderText, lastSpace, m_current.m_po
s - lastSpace, font, m_width.currentWidth(), isFixedPitch, m_collapseWhiteSpace,
&wordMeasurement.fallbackFonts, textLayout); |
2736 bool requiresLineBox = alwaysRequiresLineBox(current.m_obj); | 3005 |
2737 if (requiresLineBox || requiresLineBoxForContent(flowBox, lineInfo))
{ | 3006 wordMeasurement.width = additionalTmpW + wordSpacingForWordMeasureme
nt; |
2738 // An empty inline that only has line-height, vertical-align or
font-metrics will only get a | 3007 additionalTmpW += lastSpaceWordSpacing; |
2739 // line box to affect the height of the line if the rest of the
line is not empty. | 3008 m_width.addUncommittedWidth(additionalTmpW); |
2740 if (requiresLineBox) | 3009 if (!m_appliedStartWidth) { |
2741 lineInfo.setEmpty(false, m_block, &width); | 3010 m_width.addUncommittedWidth(inlineLogicalWidth(m_current.m_obj,
true, false)); |
2742 if (ignoringSpaces) { | 3011 m_appliedStartWidth = true; |
2743 trailingObjects.clear(); | 3012 } |
2744 ensureLineBoxInsideIgnoredSpaces(lineMidpointState, current.
m_obj); | 3013 |
2745 } else if (blockStyle->collapseWhiteSpace() && resolver.position
().m_obj == current.m_obj | 3014 applyWordSpacing = wordSpacing && m_currentCharacterIsSpace; |
2746 && shouldSkipWhitespaceAfterStartObject(m_block, current.m_o
bj, lineMidpointState)) { | 3015 |
2747 // Like with list markers, we start ignoring spaces to make
sure that any | 3016 if (!m_width.committedWidth() && m_autoWrap && !m_width.fitsOnLine()
) |
2748 // additional spaces we see will be discarded. | 3017 m_width.fitBelowFloats(); |
2749 currentCharacterShouldCollapseIfPreWap = currentCharacterIsS
pace = true; | 3018 |
2750 ignoringSpaces = true; | 3019 if (m_autoWrap || breakWords) { |
| 3020 // If we break only after white-space, consider the current char
acter |
| 3021 // as candidate width for this line. |
| 3022 bool lineWasTooWide = false; |
| 3023 if (m_width.fitsOnLine() && m_currentCharacterIsSpace && m_curre
ntStyle->breakOnlyAfterWhiteSpace() && !midWordBreak) { |
| 3024 float charWidth = textWidth(renderText, m_current.m_pos, 1,
font, m_width.currentWidth(), isFixedPitch, m_collapseWhiteSpace, &wordMeasureme
nt.fallbackFonts, textLayout) + (applyWordSpacing ? wordSpacing : 0); |
| 3025 // Check if line is too big even without the extra space |
| 3026 // at the end of the line. If it is not, do nothing. |
| 3027 // If the line needs the extra whitespace to be too long, |
| 3028 // then move the line break to the space and skip all |
| 3029 // additional whitespace. |
| 3030 if (!m_width.fitsOnLine(charWidth)) { |
| 3031 lineWasTooWide = true; |
| 3032 m_lineBreak.moveTo(m_current.m_obj, m_current.m_pos, m_c
urrent.m_nextBreakablePosition); |
| 3033 skipTrailingWhitespace(m_lineBreak, m_lineInfo); |
| 3034 } |
2751 } | 3035 } |
2752 } | 3036 if (lineWasTooWide || !m_width.fitsOnLine()) { |
2753 | 3037 if (m_lineBreak.atTextParagraphSeparator()) { |
2754 width.addUncommittedWidth(inlineLogicalWidth(current.m_obj) + border
PaddingMarginStart(flowBox) + borderPaddingMarginEnd(flowBox)); | 3038 if (!stoppedIgnoringSpaces && m_current.m_pos > 0) |
2755 } else if (current.m_obj->isReplaced()) { | 3039 ensureCharacterGetsLineBox(m_lineMidpointState, m_cu
rrent); |
2756 RenderBox* replacedBox = toRenderBox(current.m_obj); | 3040 m_lineBreak.increment(); |
2757 | 3041 m_lineInfo.setPreviousLineBrokeCleanly(true); |
2758 if (atStart) | 3042 wordMeasurement.endOffset = m_lineBreak.m_pos; |
2759 width.updateAvailableWidth(replacedBox->logicalHeight()); | 3043 } |
2760 | 3044 if (m_lineBreak.m_obj && m_lineBreak.m_pos && m_lineBreak.m_
obj->isText() && toRenderText(m_lineBreak.m_obj)->textLength() && toRenderText(m
_lineBreak.m_obj)->characterAt(m_lineBreak.m_pos - 1) == softHyphen) |
2761 // Break on replaced elements if either has normal white-space. | 3045 hyphenated = true; |
2762 if ((autoWrap || RenderStyle::autoWrap(lastWS)) && (!current.m_obj->
isImage() || allowImagesToBreak)) { | 3046 if (m_lineBreak.m_pos && m_lineBreak.m_pos != (unsigned)word
Measurement.endOffset && !wordMeasurement.width) { |
2763 width.commit(); | 3047 if (charWidth) { |
2764 lBreak.moveToStartOf(current.m_obj); | 3048 wordMeasurement.endOffset = m_lineBreak.m_pos; |
2765 } | 3049 wordMeasurement.width = charWidth; |
2766 | |
2767 if (ignoringSpaces) | |
2768 stopIgnoringSpaces(lineMidpointState, InlineIterator(0, current.
m_obj, 0)); | |
2769 | |
2770 lineInfo.setEmpty(false, m_block, &width); | |
2771 ignoringSpaces = false; | |
2772 currentCharacterShouldCollapseIfPreWap = currentCharacterIsSpace = f
alse; | |
2773 trailingObjects.clear(); | |
2774 | |
2775 // Optimize for a common case. If we can't find whitespace after the
list | |
2776 // item, then this is all moot. | |
2777 LayoutUnit replacedLogicalWidth = m_block->logicalWidthForChild(repl
acedBox) + m_block->marginStartForChild(replacedBox) + m_block->marginEndForChil
d(replacedBox) + inlineLogicalWidth(current.m_obj); | |
2778 if (current.m_obj->isListMarker()) { | |
2779 if (blockStyle->collapseWhiteSpace() && shouldSkipWhitespaceAfte
rStartObject(m_block, current.m_obj, lineMidpointState)) { | |
2780 // Like with inline flows, we start ignoring spaces to make
sure that any | |
2781 // additional spaces we see will be discarded. | |
2782 currentCharacterShouldCollapseIfPreWap = currentCharacterIsS
pace = true; | |
2783 ignoringSpaces = true; | |
2784 } | |
2785 if (toRenderListMarker(current.m_obj)->isInside()) | |
2786 width.addUncommittedWidth(replacedLogicalWidth); | |
2787 } else | |
2788 width.addUncommittedWidth(replacedLogicalWidth); | |
2789 if (current.m_obj->isRubyRun()) | |
2790 width.applyOverhang(toRenderRubyRun(current.m_obj), last, next); | |
2791 // Update prior line break context characters, using U+FFFD (OBJECT
REPLACEMENT CHARACTER) for replaced element. | |
2792 renderTextInfo.m_lineBreakIterator.updatePriorContext(replacementCha
racter); | |
2793 } else if (current.m_obj->isText()) { | |
2794 if (!current.m_pos) | |
2795 appliedStartWidth = false; | |
2796 | |
2797 RenderText* t = toRenderText(current.m_obj); | |
2798 | |
2799 bool isSVGText = t->isSVGInlineText(); | |
2800 | |
2801 if (t->style()->hasTextCombine() && current.m_obj->isCombineText() &
& !toRenderCombineText(current.m_obj)->isCombined()) { | |
2802 RenderCombineText* combineRenderer = toRenderCombineText(current
.m_obj); | |
2803 combineRenderer->combineText(); | |
2804 // The length of the renderer's text may have changed. Increment
stale iterator positions | |
2805 if (iteratorIsBeyondEndOfRenderCombineText(lBreak, combineRender
er)) { | |
2806 ASSERT(iteratorIsBeyondEndOfRenderCombineText(resolver.posit
ion(), combineRenderer)); | |
2807 lBreak.increment(); | |
2808 resolver.position().increment(&resolver); | |
2809 } | |
2810 } | |
2811 | |
2812 RenderStyle* style = t->style(lineInfo.isFirstLine()); | |
2813 const Font& f = style->font(); | |
2814 bool isFixedPitch = f.isFixedPitch(); | |
2815 | |
2816 unsigned lastSpace = current.m_pos; | |
2817 float wordSpacing = currentStyle->wordSpacing(); | |
2818 float lastSpaceWordSpacing = 0; | |
2819 float wordSpacingForWordMeasurement = 0; | |
2820 | |
2821 float wrapW = width.uncommittedWidth() + inlineLogicalWidth(current.
m_obj, !appliedStartWidth, true); | |
2822 float charWidth = 0; | |
2823 // Auto-wrapping text should wrap in the middle of a word only if it
could not wrap before the word, | |
2824 // which is only possible if the word is the first thing on the line
, that is, if |w| is zero. | |
2825 bool breakWords = currentStyle->breakWords() && ((autoWrap && !width
.committedWidth()) || currWS == PRE); | |
2826 bool midWordBreak = false; | |
2827 bool breakAll = currentStyle->wordBreak() == BreakAllWordBreak && au
toWrap; | |
2828 float hyphenWidth = 0; | |
2829 | |
2830 if (isSVGText) { | |
2831 breakWords = false; | |
2832 breakAll = false; | |
2833 } | |
2834 | |
2835 if (t->isWordBreak()) { | |
2836 width.commit(); | |
2837 lBreak.moveToStartOf(current.m_obj); | |
2838 ASSERT(current.m_pos == t->textLength()); | |
2839 } | |
2840 | |
2841 if (renderTextInfo.m_text != t) { | |
2842 renderTextInfo.m_text = t; | |
2843 renderTextInfo.m_font = &f; | |
2844 renderTextInfo.m_layout = f.createLayout(t, width.currentWidth()
, collapseWhiteSpace); | |
2845 renderTextInfo.m_lineBreakIterator.resetStringAndReleaseIterator
(t->text(), style->locale()); | |
2846 } else if (renderTextInfo.m_layout && renderTextInfo.m_font != &f) { | |
2847 renderTextInfo.m_font = &f; | |
2848 renderTextInfo.m_layout = f.createLayout(t, width.currentWidth()
, collapseWhiteSpace); | |
2849 } | |
2850 | |
2851 TextLayout* textLayout = renderTextInfo.m_layout.get(); | |
2852 | |
2853 // Non-zero only when kerning is enabled and TextLayout isn't used,
in which case we measure | |
2854 // words with their trailing space, then subtract its width. | |
2855 float wordTrailingSpaceWidth = (f.typesettingFeatures() & Kerning) &
& !textLayout ? f.width(RenderBlock::constructTextRun(t, f, &space, 1, style)) +
wordSpacing : 0; | |
2856 | |
2857 UChar lastCharacter = renderTextInfo.m_lineBreakIterator.lastCharact
er(); | |
2858 UChar secondToLastCharacter = renderTextInfo.m_lineBreakIterator.sec
ondToLastCharacter(); | |
2859 for (; current.m_pos < t->textLength(); current.fastIncrementInTextN
ode()) { | |
2860 bool previousCharacterIsSpace = currentCharacterIsSpace; | |
2861 bool previousCharacterShouldCollapseIfPreWap = currentCharacterS
houldCollapseIfPreWap; | |
2862 UChar c = current.current(); | |
2863 currentCharacterShouldCollapseIfPreWap = currentCharacterIsSpace
= c == ' ' || c == '\t' || (!preserveNewline && (c == '\n')); | |
2864 | |
2865 if (!collapseWhiteSpace || !currentCharacterIsSpace) | |
2866 lineInfo.setEmpty(false, m_block, &width); | |
2867 | |
2868 if (c == softHyphen && autoWrap && !hyphenWidth) { | |
2869 hyphenWidth = measureHyphenWidth(t, f); | |
2870 width.addUncommittedWidth(hyphenWidth); | |
2871 } | |
2872 | |
2873 bool applyWordSpacing = false; | |
2874 | |
2875 if ((breakAll || breakWords) && !midWordBreak) { | |
2876 wrapW += charWidth; | |
2877 bool midWordBreakIsBeforeSurrogatePair = U16_IS_LEAD(c) && c
urrent.m_pos + 1 < t->textLength() && U16_IS_TRAIL((*t)[current.m_pos + 1]); | |
2878 charWidth = textWidth(t, current.m_pos, midWordBreakIsBefore
SurrogatePair ? 2 : 1, f, width.committedWidth() + wrapW, isFixedPitch, collapse
WhiteSpace, 0, textLayout); | |
2879 midWordBreak = width.committedWidth() + wrapW + charWidth >
width.availableWidth(); | |
2880 } | |
2881 | |
2882 bool betweenWords = c == '\n' || (currWS != PRE && !atStart && i
sBreakable(renderTextInfo.m_lineBreakIterator, current.m_pos, current.m_nextBrea
kablePosition)); | |
2883 | |
2884 if (betweenWords || midWordBreak) { | |
2885 bool stoppedIgnoringSpaces = false; | |
2886 if (ignoringSpaces) { | |
2887 lastSpaceWordSpacing = 0; | |
2888 if (!currentCharacterIsSpace) { | |
2889 // Stop ignoring spaces and begin at this | |
2890 // new point. | |
2891 ignoringSpaces = false; | |
2892 wordSpacingForWordMeasurement = 0; | |
2893 lastSpace = current.m_pos; // e.g., "Foo goo", do
n't add in any of the ignored spaces. | |
2894 stopIgnoringSpaces(lineMidpointState, InlineIterator
(0, current.m_obj, current.m_pos)); | |
2895 stoppedIgnoringSpaces = true; | |
2896 } else { | |
2897 // Just keep ignoring these spaces. | |
2898 goto nextCharacter; | |
2899 } | 3050 } |
2900 } | 3051 } |
2901 | 3052 // Didn't fit. Jump to the end unless there's still an oppor
tunity to collapse whitespace. |
2902 wordMeasurements.grow(wordMeasurements.size() + 1); | 3053 if (m_ignoringSpaces || !m_collapseWhiteSpace || !m_currentC
haracterIsSpace || !previousCharacterIsSpace) { |
2903 WordMeasurement& wordMeasurement = wordMeasurements.last(); | 3054 m_atEnd = true; |
2904 | 3055 return false; |
2905 wordMeasurement.renderer = t; | |
2906 wordMeasurement.endOffset = current.m_pos; | |
2907 wordMeasurement.startOffset = lastSpace; | |
2908 | |
2909 float additionalTmpW; | |
2910 if (wordTrailingSpaceWidth && c == ' ') | |
2911 additionalTmpW = textWidth(t, lastSpace, current.m_pos +
1 - lastSpace, f, width.currentWidth(), isFixedPitch, collapseWhiteSpace, &word
Measurement.fallbackFonts, textLayout) - wordTrailingSpaceWidth; | |
2912 else | |
2913 additionalTmpW = textWidth(t, lastSpace, current.m_pos -
lastSpace, f, width.currentWidth(), isFixedPitch, collapseWhiteSpace, &wordMeas
urement.fallbackFonts, textLayout); | |
2914 | |
2915 wordMeasurement.width = additionalTmpW + wordSpacingForWordM
easurement; | |
2916 additionalTmpW += lastSpaceWordSpacing; | |
2917 width.addUncommittedWidth(additionalTmpW); | |
2918 if (!appliedStartWidth) { | |
2919 width.addUncommittedWidth(inlineLogicalWidth(current.m_o
bj, true, false)); | |
2920 appliedStartWidth = true; | |
2921 } | 3056 } |
2922 | 3057 } else { |
2923 applyWordSpacing = wordSpacing && currentCharacterIsSpace; | 3058 if (!betweenWords || (midWordBreak && !m_autoWrap)) |
2924 | 3059 m_width.addUncommittedWidth(-additionalTmpW); |
2925 if (!width.committedWidth() && autoWrap && !width.fitsOnLine
()) | 3060 if (hyphenWidth) { |
2926 width.fitBelowFloats(); | 3061 // Subtract the width of the soft hyphen out since we fi
t on a line. |
2927 | 3062 m_width.addUncommittedWidth(-hyphenWidth); |
2928 if (autoWrap || breakWords) { | 3063 hyphenWidth = 0; |
2929 // If we break only after white-space, consider the curr
ent character | |
2930 // as candidate width for this line. | |
2931 bool lineWasTooWide = false; | |
2932 if (width.fitsOnLine() && currentCharacterIsSpace && cur
rentStyle->breakOnlyAfterWhiteSpace() && !midWordBreak) { | |
2933 float charWidth = textWidth(t, current.m_pos, 1, f,
width.currentWidth(), isFixedPitch, collapseWhiteSpace, &wordMeasurement.fallbac
kFonts, textLayout) + (applyWordSpacing ? wordSpacing : 0); | |
2934 // Check if line is too big even without the extra s
pace | |
2935 // at the end of the line. If it is not, do nothing. | |
2936 // If the line needs the extra whitespace to be too
long, | |
2937 // then move the line break to the space and skip al
l | |
2938 // additional whitespace. | |
2939 if (!width.fitsOnLine(charWidth)) { | |
2940 lineWasTooWide = true; | |
2941 lBreak.moveTo(current.m_obj, current.m_pos, curr
ent.m_nextBreakablePosition); | |
2942 skipTrailingWhitespace(lBreak, lineInfo); | |
2943 } | |
2944 } | |
2945 if (lineWasTooWide || !width.fitsOnLine()) { | |
2946 if (lBreak.atTextParagraphSeparator()) { | |
2947 if (!stoppedIgnoringSpaces && current.m_pos > 0) | |
2948 ensureCharacterGetsLineBox(lineMidpointState
, current); | |
2949 lBreak.increment(); | |
2950 lineInfo.setPreviousLineBrokeCleanly(true); | |
2951 wordMeasurement.endOffset = lBreak.m_pos; | |
2952 } | |
2953 if (lBreak.m_obj && lBreak.m_pos && lBreak.m_obj->is
Text() && toRenderText(lBreak.m_obj)->textLength() && toRenderText(lBreak.m_obj)
->characterAt(lBreak.m_pos - 1) == softHyphen) | |
2954 m_hyphenated = true; | |
2955 if (lBreak.m_pos && lBreak.m_pos != (unsigned)wordMe
asurement.endOffset && !wordMeasurement.width) { | |
2956 if (charWidth) { | |
2957 wordMeasurement.endOffset = lBreak.m_pos; | |
2958 wordMeasurement.width = charWidth; | |
2959 } | |
2960 } | |
2961 // Didn't fit. Jump to the end unless there's still
an opportunity to collapse whitespace. | |
2962 if (ignoringSpaces || !collapseWhiteSpace || !curren
tCharacterIsSpace || !previousCharacterIsSpace) | |
2963 goto end; | |
2964 } else { | |
2965 if (!betweenWords || (midWordBreak && !autoWrap)) | |
2966 width.addUncommittedWidth(-additionalTmpW); | |
2967 if (hyphenWidth) { | |
2968 // Subtract the width of the soft hyphen out sin
ce we fit on a line. | |
2969 width.addUncommittedWidth(-hyphenWidth); | |
2970 hyphenWidth = 0; | |
2971 } | |
2972 } | |
2973 } | 3064 } |
2974 | |
2975 if (c == '\n' && preserveNewline) { | |
2976 if (!stoppedIgnoringSpaces && current.m_pos > 0) | |
2977 ensureCharacterGetsLineBox(lineMidpointState, curren
t); | |
2978 lBreak.moveTo(current.m_obj, current.m_pos, current.m_ne
xtBreakablePosition); | |
2979 lBreak.increment(); | |
2980 lineInfo.setPreviousLineBrokeCleanly(true); | |
2981 return lBreak; | |
2982 } | |
2983 | |
2984 if (autoWrap && betweenWords) { | |
2985 width.commit(); | |
2986 wrapW = 0; | |
2987 lBreak.moveTo(current.m_obj, current.m_pos, current.m_ne
xtBreakablePosition); | |
2988 // Auto-wrapping text should not wrap in the middle of a
word once it has had an | |
2989 // opportunity to break after a word. | |
2990 breakWords = false; | |
2991 } | |
2992 | |
2993 if (midWordBreak && !U16_IS_TRAIL(c) && !(category(c) & (Mar
k_NonSpacing | Mark_Enclosing | Mark_SpacingCombining))) { | |
2994 // Remember this as a breakable position in case | |
2995 // adding the end width forces a break. | |
2996 lBreak.moveTo(current.m_obj, current.m_pos, current.m_ne
xtBreakablePosition); | |
2997 midWordBreak &= (breakWords || breakAll); | |
2998 } | |
2999 | |
3000 if (betweenWords) { | |
3001 lastSpaceWordSpacing = applyWordSpacing ? wordSpacing :
0; | |
3002 wordSpacingForWordMeasurement = (applyWordSpacing && wor
dMeasurement.width) ? wordSpacing : 0; | |
3003 lastSpace = current.m_pos; | |
3004 } | |
3005 | |
3006 if (!ignoringSpaces && currentStyle->collapseWhiteSpace()) { | |
3007 // If we encounter a newline, or if we encounter a | |
3008 // second space, we need to go ahead and break up this | |
3009 // run and enter a mode where we start collapsing spaces
. | |
3010 if (currentCharacterIsSpace && previousCharacterIsSpace)
{ | |
3011 ignoringSpaces = true; | |
3012 | |
3013 // We just entered a mode where we are ignoring | |
3014 // spaces. Create a midpoint to terminate the run | |
3015 // before the second space. | |
3016 startIgnoringSpaces(lineMidpointState, ignoreStart); | |
3017 trailingObjects.updateMidpointsForTrailingBoxes(line
MidpointState, InlineIterator(), TrailingObjects::DoNotCollapseFirstSpace); | |
3018 } | |
3019 } | |
3020 } else if (ignoringSpaces) { | |
3021 // Stop ignoring spaces and begin at this | |
3022 // new point. | |
3023 ignoringSpaces = false; | |
3024 lastSpaceWordSpacing = applyWordSpacing ? wordSpacing : 0; | |
3025 wordSpacingForWordMeasurement = (applyWordSpacing && wordMea
surements.last().width) ? wordSpacing : 0; | |
3026 lastSpace = current.m_pos; // e.g., "Foo goo", don't add
in any of the ignored spaces. | |
3027 stopIgnoringSpaces(lineMidpointState, InlineIterator(0, curr
ent.m_obj, current.m_pos)); | |
3028 } | 3065 } |
3029 | 3066 } |
3030 if (isSVGText && current.m_pos > 0) { | 3067 |
3031 // Force creation of new InlineBoxes for each absolute posit
ioned character (those that start new text chunks). | 3068 if (c == '\n' && m_preservesNewline) { |
3032 if (toRenderSVGInlineText(t)->characterStartsNewTextChunk(cu
rrent.m_pos)) | 3069 if (!stoppedIgnoringSpaces && m_current.m_pos > 0) |
3033 ensureCharacterGetsLineBox(lineMidpointState, current); | 3070 ensureCharacterGetsLineBox(m_lineMidpointState, m_current); |
| 3071 m_lineBreak.moveTo(m_current.m_obj, m_current.m_pos, m_current.m
_nextBreakablePosition); |
| 3072 m_lineBreak.increment(); |
| 3073 m_lineInfo.setPreviousLineBrokeCleanly(true); |
| 3074 return true; |
| 3075 } |
| 3076 |
| 3077 if (m_autoWrap && betweenWords) { |
| 3078 m_width.commit(); |
| 3079 wrapW = 0; |
| 3080 m_lineBreak.moveTo(m_current.m_obj, m_current.m_pos, m_current.m
_nextBreakablePosition); |
| 3081 // Auto-wrapping text should not wrap in the middle of a word on
ce it has had an |
| 3082 // opportunity to break after a word. |
| 3083 breakWords = false; |
| 3084 } |
| 3085 |
| 3086 if (midWordBreak && !U16_IS_TRAIL(c) && !(category(c) & (Mark_NonSpa
cing | Mark_Enclosing | Mark_SpacingCombining))) { |
| 3087 // Remember this as a breakable position in case |
| 3088 // adding the end width forces a break. |
| 3089 m_lineBreak.moveTo(m_current.m_obj, m_current.m_pos, m_current.m
_nextBreakablePosition); |
| 3090 midWordBreak &= (breakWords || breakAll); |
| 3091 } |
| 3092 |
| 3093 if (betweenWords) { |
| 3094 lastSpaceWordSpacing = applyWordSpacing ? wordSpacing : 0; |
| 3095 wordSpacingForWordMeasurement = (applyWordSpacing && wordMeasure
ment.width) ? wordSpacing : 0; |
| 3096 lastSpace = m_current.m_pos; |
| 3097 } |
| 3098 |
| 3099 if (!m_ignoringSpaces && m_currentStyle->collapseWhiteSpace()) { |
| 3100 // If we encounter a newline, or if we encounter a |
| 3101 // second space, we need to go ahead and break up this |
| 3102 // run and enter a mode where we start collapsing spaces. |
| 3103 if (m_currentCharacterIsSpace && previousCharacterIsSpace) { |
| 3104 m_ignoringSpaces = true; |
| 3105 |
| 3106 // We just entered a mode where we are ignoring |
| 3107 // spaces. Create a midpoint to terminate the run |
| 3108 // before the second space. |
| 3109 startIgnoringSpaces(m_lineMidpointState, m_startOfIgnoredSpa
ces); |
| 3110 m_trailingObjects.updateMidpointsForTrailingBoxes(m_lineMidp
ointState, InlineIterator(), TrailingObjects::DoNotCollapseFirstSpace); |
3034 } | 3111 } |
3035 | 3112 } |
3036 if (currentCharacterIsSpace && !previousCharacterIsSpace) { | 3113 } else if (m_ignoringSpaces) { |
3037 ignoreStart.m_obj = current.m_obj; | 3114 // Stop ignoring spaces and begin at this |
3038 ignoreStart.m_pos = current.m_pos; | 3115 // new point. |
3039 } | 3116 m_ignoringSpaces = false; |
3040 | 3117 lastSpaceWordSpacing = applyWordSpacing ? wordSpacing : 0; |
3041 if (!currentCharacterIsSpace && previousCharacterShouldCollapseI
fPreWap) { | 3118 wordSpacingForWordMeasurement = (applyWordSpacing && wordMeasurement
s.last().width) ? wordSpacing : 0; |
3042 if (autoWrap && currentStyle->breakOnlyAfterWhiteSpace()) | 3119 lastSpace = m_current.m_pos; // e.g., "Foo goo", don't add in any
of the ignored spaces. |
3043 lBreak.moveTo(current.m_obj, current.m_pos, current.m_ne
xtBreakablePosition); | 3120 stopIgnoringSpaces(m_lineMidpointState, InlineIterator(0, m_current.
m_obj, m_current.m_pos)); |
3044 } | 3121 } |
3045 | 3122 |
3046 if (collapseWhiteSpace && currentCharacterIsSpace && !ignoringSp
aces) | 3123 if (isSVGText && m_current.m_pos > 0) { |
3047 trailingObjects.setTrailingWhitespace(toRenderText(current.m
_obj)); | 3124 // Force creation of new InlineBoxes for each absolute positioned ch
aracter (those that start new text chunks). |
3048 else if (!currentStyle->collapseWhiteSpace() || !currentCharacte
rIsSpace) | 3125 if (toRenderSVGInlineText(renderText)->characterStartsNewTextChunk(m
_current.m_pos)) |
3049 trailingObjects.clear(); | 3126 ensureCharacterGetsLineBox(m_lineMidpointState, m_current); |
3050 | 3127 } |
3051 atStart = false; | 3128 |
3052 nextCharacter: | 3129 if (m_currentCharacterIsSpace && !previousCharacterIsSpace) { |
3053 secondToLastCharacter = lastCharacter; | 3130 m_startOfIgnoredSpaces.m_obj = m_current.m_obj; |
3054 lastCharacter = c; | 3131 m_startOfIgnoredSpaces.m_pos = m_current.m_pos; |
3055 } | 3132 } |
3056 | 3133 |
3057 renderTextInfo.m_lineBreakIterator.setPriorContext(lastCharacter, se
condToLastCharacter); | 3134 if (!m_currentCharacterIsSpace && previousCharacterShouldCollapseIfPreWa
p) { |
3058 | 3135 if (m_autoWrap && m_currentStyle->breakOnlyAfterWhiteSpace()) |
3059 wordMeasurements.grow(wordMeasurements.size() + 1); | 3136 m_lineBreak.moveTo(m_current.m_obj, m_current.m_pos, m_current.m
_nextBreakablePosition); |
3060 WordMeasurement& wordMeasurement = wordMeasurements.last(); | 3137 } |
3061 wordMeasurement.renderer = t; | 3138 |
3062 | 3139 if (m_collapseWhiteSpace && m_currentCharacterIsSpace && !m_ignoringSpac
es) |
3063 // IMPORTANT: current.m_pos is > length here! | 3140 m_trailingObjects.setTrailingWhitespace(toRenderText(m_current.m_obj
)); |
3064 float additionalTmpW = ignoringSpaces ? 0 : textWidth(t, lastSpace,
current.m_pos - lastSpace, f, width.currentWidth(), isFixedPitch, collapseWhiteS
pace, &wordMeasurement.fallbackFonts, textLayout); | 3141 else if (!m_currentStyle->collapseWhiteSpace() || !m_currentCharacterIsS
pace) |
3065 wordMeasurement.startOffset = lastSpace; | 3142 m_trailingObjects.clear(); |
3066 wordMeasurement.endOffset = current.m_pos; | 3143 |
3067 wordMeasurement.width = ignoringSpaces ? 0 : additionalTmpW + wordSp
acingForWordMeasurement; | 3144 m_atStart = false; |
3068 additionalTmpW += lastSpaceWordSpacing; | 3145 nextCharacter(c, lastCharacter, secondToLastCharacter); |
3069 width.addUncommittedWidth(additionalTmpW + inlineLogicalWidth(curren
t.m_obj, !appliedStartWidth, includeEndWidth)); | 3146 } |
3070 includeEndWidth = false; | 3147 |
3071 | 3148 m_renderTextInfo.m_lineBreakIterator.setPriorContext(lastCharacter, secondTo
LastCharacter); |
3072 if (!width.fitsOnLine()) { | 3149 |
3073 if (!m_hyphenated && lBreak.previousInSameNode() == softHyphen) | 3150 wordMeasurements.grow(wordMeasurements.size() + 1); |
3074 m_hyphenated = true; | 3151 WordMeasurement& wordMeasurement = wordMeasurements.last(); |
3075 | 3152 wordMeasurement.renderer = renderText; |
3076 if (m_hyphenated) | 3153 |
3077 goto end; | 3154 // IMPORTANT: current.m_pos is > length here! |
3078 } | 3155 float additionalTmpW = m_ignoringSpaces ? 0 : textWidth(renderText, lastSpac
e, m_current.m_pos - lastSpace, font, m_width.currentWidth(), isFixedPitch, m_co
llapseWhiteSpace, &wordMeasurement.fallbackFonts, textLayout); |
3079 } else | 3156 wordMeasurement.startOffset = lastSpace; |
3080 ASSERT_NOT_REACHED(); | 3157 wordMeasurement.endOffset = m_current.m_pos; |
3081 | 3158 wordMeasurement.width = m_ignoringSpaces ? 0 : additionalTmpW + wordSpacingF
orWordMeasurement; |
3082 bool checkForBreak = autoWrap; | 3159 additionalTmpW += lastSpaceWordSpacing; |
3083 if (width.committedWidth() && !width.fitsOnLine() && lBreak.m_obj && cur
rWS == NOWRAP) | 3160 m_width.addUncommittedWidth(additionalTmpW + inlineLogicalWidth(m_current.m_
obj, !m_appliedStartWidth, m_includeEndWidth)); |
| 3161 m_includeEndWidth = false; |
| 3162 |
| 3163 if (!m_width.fitsOnLine()) { |
| 3164 if (!hyphenated && m_lineBreak.previousInSameNode() == softHyphen) { |
| 3165 hyphenated = true; |
| 3166 m_atEnd = true; |
| 3167 } |
| 3168 } |
| 3169 return false; |
| 3170 } |
| 3171 |
| 3172 inline void LineBreaker::BreakingContext::commitAndUpdateLineBreakIfNeeded() |
| 3173 { |
| 3174 bool checkForBreak = m_autoWrap; |
| 3175 if (m_width.committedWidth() && !m_width.fitsOnLine() && m_lineBreak.m_obj &
& m_currWS == NOWRAP) { |
| 3176 checkForBreak = true; |
| 3177 } else if (m_nextObject && m_current.m_obj->isText() && m_nextObject->isText
() && !m_nextObject->isBR() && (m_autoWrap || m_nextObject->style()->autoWrap())
) { |
| 3178 if (m_autoWrap && m_currentCharacterIsSpace) { |
3084 checkForBreak = true; | 3179 checkForBreak = true; |
3085 else if (next && current.m_obj->isText() && next->isText() && !next->isB
R() && (autoWrap || next->style()->autoWrap())) { | 3180 } else { |
3086 if (autoWrap && currentCharacterIsSpace) | 3181 RenderText* nextText = toRenderText(m_nextObject); |
| 3182 if (nextText->textLength()) { |
| 3183 UChar c = nextText->characterAt(0); |
| 3184 // If the next item on the line is text, and if we did not end w
ith |
| 3185 // a space, then the next text run continues our word (and so it
needs to |
| 3186 // keep adding to the uncommitted width. Just update and continu
e. |
| 3187 checkForBreak = !m_currentCharacterIsSpace && (c == ' ' || c ==
'\t' || (c == '\n' && !m_nextObject->preservesNewline())); |
| 3188 } else if (nextText->isWordBreak()) { |
3087 checkForBreak = true; | 3189 checkForBreak = true; |
3088 else { | 3190 } |
3089 RenderText* nextText = toRenderText(next); | 3191 |
3090 if (nextText->textLength()) { | 3192 if (!m_width.fitsOnLine() && !m_width.committedWidth()) |
3091 UChar c = nextText->characterAt(0); | 3193 m_width.fitBelowFloats(); |
3092 // If the next item on the line is text, and if we did not e
nd with | 3194 |
3093 // a space, then the next text run continues our word (and s
o it needs to | 3195 bool canPlaceOnLine = m_width.fitsOnLine() || !m_autoWrapWasEverTrue
OnLine; |
3094 // keep adding to the uncommitted width. Just update and con
tinue. | 3196 if (canPlaceOnLine && checkForBreak) { |
3095 checkForBreak = !currentCharacterIsSpace && (c == ' ' || c =
= '\t' || (c == '\n' && !next->preservesNewline())); | 3197 m_width.commit(); |
3096 } else if (nextText->isWordBreak()) | 3198 m_lineBreak.moveToStartOf(m_nextObject); |
3097 checkForBreak = true; | 3199 } |
3098 | 3200 } |
3099 if (!width.fitsOnLine() && !width.committedWidth()) | 3201 } |
3100 width.fitBelowFloats(); | 3202 |
3101 | 3203 if (checkForBreak && !m_width.fitsOnLine()) { |
3102 bool canPlaceOnLine = width.fitsOnLine() || !autoWrapWasEverTrue
OnLine; | 3204 // if we have floats, try to get below them. |
3103 if (canPlaceOnLine && checkForBreak) { | 3205 if (m_currentCharacterIsSpace && !m_ignoringSpaces && m_currentStyle->co
llapseWhiteSpace()) |
3104 width.commit(); | 3206 m_trailingObjects.clear(); |
3105 lBreak.moveToStartOf(next); | 3207 |
3106 } | 3208 if (m_width.committedWidth()) { |
3107 } | 3209 m_atEnd = true; |
3108 } | 3210 return; |
3109 | 3211 } |
3110 if (checkForBreak && !width.fitsOnLine()) { | 3212 |
3111 // if we have floats, try to get below them. | 3213 m_width.fitBelowFloats(); |
3112 if (currentCharacterIsSpace && !ignoringSpaces && currentStyle->coll
apseWhiteSpace()) | 3214 |
3113 trailingObjects.clear(); | 3215 // |width| may have been adjusted because we got shoved down past a floa
t (thus |
3114 | 3216 // giving us more room), so we need to retest, and only jump to |
3115 if (width.committedWidth()) | 3217 // the end label if we still don't fit on the line. -dwh |
3116 goto end; | 3218 if (!m_width.fitsOnLine()) { |
3117 | 3219 m_atEnd = true; |
3118 width.fitBelowFloats(); | 3220 return; |
3119 | 3221 } |
3120 // |width| may have been adjusted because we got shoved down past a
float (thus | 3222 } else if (m_blockStyle->autoWrap() && !m_width.fitsOnLine() && !m_width.com
mittedWidth()) { |
3121 // giving us more room), so we need to retest, and only jump to | 3223 // If the container autowraps but the current child does not then we sti
ll need to ensure that it |
3122 // the end label if we still don't fit on the line. -dwh | 3224 // wraps and moves below any floats. |
3123 if (!width.fitsOnLine()) | 3225 m_width.fitBelowFloats(); |
3124 goto end; | 3226 } |
3125 } else if (blockStyle->autoWrap() && !width.fitsOnLine() && !width.commi
ttedWidth()) { | 3227 |
3126 // If the container autowraps but the current child does not then we
still need to ensure that it | 3228 if (!m_current.m_obj->isFloatingOrOutOfFlowPositioned()) { |
3127 // wraps and moves below any floats. | 3229 m_lastObject = m_current.m_obj; |
3128 width.fitBelowFloats(); | 3230 if (m_lastObject->isReplaced() && m_autoWrap && (!m_lastObject->isImage(
) || m_allowImagesToBreak) && (!m_lastObject->isListMarker() || toRenderListMark
er(m_lastObject)->isInside())) { |
3129 } | 3231 m_width.commit(); |
3130 | 3232 m_lineBreak.moveToStartOf(m_nextObject); |
3131 if (!current.m_obj->isFloatingOrOutOfFlowPositioned()) { | 3233 } |
3132 last = current.m_obj; | 3234 } |
3133 if (last->isReplaced() && autoWrap && (!last->isImage() || allowImag
esToBreak) && (!last->isListMarker() || toRenderListMarker(last)->isInside())) { | 3235 } |
3134 width.commit(); | 3236 |
3135 lBreak.moveToStartOf(next); | 3237 InlineIterator LineBreaker::BreakingContext::handleEndOfLine() |
3136 } | 3238 { |
3137 } | |
3138 | |
3139 // Clear out our character space bool, since inline <pre>s don't collaps
e whitespace | |
3140 // with adjacent inline normal/nowrap spans. | |
3141 if (!collapseWhiteSpace) | |
3142 currentCharacterIsSpace = false; | |
3143 | |
3144 current.moveToStartOf(next); | |
3145 atStart = false; | |
3146 } | |
3147 | |
3148 if (width.fitsOnLine() || lastWS == NOWRAP) | |
3149 lBreak.clear(); | |
3150 | |
3151 end: | |
3152 ShapeInsideInfo* shapeInfo = m_block->layoutShapeInsideInfo(); | 3239 ShapeInsideInfo* shapeInfo = m_block->layoutShapeInsideInfo(); |
3153 bool segmentAllowsOverflow = !shapeInfo || !shapeInfo->hasSegments(); | 3240 bool segmentAllowsOverflow = !shapeInfo || !shapeInfo->hasSegments(); |
3154 | 3241 |
3155 if (lBreak == resolver.position() && (!lBreak.m_obj || !lBreak.m_obj->isBR()
) && segmentAllowsOverflow) { | 3242 if (m_lineBreak == m_resolver.position() && (!m_lineBreak.m_obj || !m_lineBr
eak.m_obj->isBR()) && segmentAllowsOverflow) { |
3156 // we just add as much as possible | 3243 // we just add as much as possible |
3157 if (blockStyle->whiteSpace() == PRE && !current.m_pos) { | 3244 if (m_blockStyle->whiteSpace() == PRE && !m_current.m_pos) { |
3158 lBreak.moveTo(last, last->isText() ? last->length() : 0); | 3245 m_lineBreak.moveTo(m_lastObject, m_lastObject->isText() ? m_lastObje
ct->length() : 0); |
3159 } else if (lBreak.m_obj) { | 3246 } else if (m_lineBreak.m_obj) { |
3160 // Don't ever break in the middle of a word if we can help it. | 3247 // Don't ever break in the middle of a word if we can help it. |
3161 // There's no room at all. We just have to be on this line, | 3248 // There's no room at all. We just have to be on this line, |
3162 // even though we'll spill out. | 3249 // even though we'll spill out. |
3163 lBreak.moveTo(current.m_obj, current.m_pos); | 3250 m_lineBreak.moveTo(m_current.m_obj, m_current.m_pos); |
3164 } | 3251 } |
3165 } | 3252 } |
3166 | 3253 |
3167 // FIXME Bug 100049: We do not need to consume input in a multi-segment line | 3254 // FIXME Bug 100049: We do not need to consume input in a multi-segment line |
3168 // unless no segment will. | 3255 // unless no segment will. |
3169 // make sure we consume at least one char/object. | 3256 // make sure we consume at least one char/object. |
3170 if (lBreak == resolver.position() && segmentAllowsOverflow) | 3257 if (m_lineBreak == m_resolver.position() && segmentAllowsOverflow) |
3171 lBreak.increment(); | 3258 m_lineBreak.increment(); |
3172 | 3259 |
3173 // Sanity check our midpoints. | 3260 // Sanity check our midpoints. |
3174 checkMidpoints(lineMidpointState, lBreak); | 3261 checkMidpoints(m_lineMidpointState, m_lineBreak); |
3175 | 3262 |
3176 trailingObjects.updateMidpointsForTrailingBoxes(lineMidpointState, lBreak, T
railingObjects::CollapseFirstSpace); | 3263 m_trailingObjects.updateMidpointsForTrailingBoxes(m_lineMidpointState, m_lin
eBreak, TrailingObjects::CollapseFirstSpace); |
3177 | 3264 |
3178 // We might have made lBreak an iterator that points past the end | 3265 // We might have made lineBreak an iterator that points past the end |
3179 // of the object. Do this adjustment to make it point to the start | 3266 // of the object. Do this adjustment to make it point to the start |
3180 // of the next object instead to avoid confusing the rest of the | 3267 // of the next object instead to avoid confusing the rest of the |
3181 // code. | 3268 // code. |
3182 if (lBreak.m_pos > 0) { | 3269 if (m_lineBreak.m_pos > 0) { |
3183 lBreak.m_pos--; | 3270 m_lineBreak.m_pos--; |
3184 lBreak.increment(); | 3271 m_lineBreak.increment(); |
3185 } | 3272 } |
3186 | 3273 |
3187 return lBreak; | 3274 return m_lineBreak; |
| 3275 } |
| 3276 |
| 3277 InlineIterator LineBreaker::nextSegmentBreak(InlineBidiResolver& resolver, LineI
nfo& lineInfo, RenderTextInfo& renderTextInfo, FloatingObject* lastFloatFromPrev
iousLine, unsigned consecutiveHyphenatedLines, WordMeasurements& wordMeasurement
s) |
| 3278 { |
| 3279 reset(); |
| 3280 |
| 3281 ASSERT(resolver.position().root() == m_block); |
| 3282 |
| 3283 bool appliedStartWidth = resolver.position().m_pos > 0; |
| 3284 |
| 3285 LineWidth width(*m_block, lineInfo.isFirstLine(), requiresIndent(lineInfo.is
FirstLine(), lineInfo.previousLineBrokeCleanly(), m_block->style())); |
| 3286 |
| 3287 skipLeadingWhitespace(resolver, lineInfo, lastFloatFromPreviousLine, width); |
| 3288 |
| 3289 if (resolver.position().atEnd()) |
| 3290 return resolver.position(); |
| 3291 |
| 3292 BreakingContext context(resolver, lineInfo, width, renderTextInfo, lastFloat
FromPreviousLine, appliedStartWidth, m_block); |
| 3293 |
| 3294 while (context.currentObject()) { |
| 3295 context.initializeForCurrentObject(); |
| 3296 if (context.currentObject()->isBR()) { |
| 3297 context.handleBR(m_clear); |
| 3298 } else if (context.currentObject()->isOutOfFlowPositioned()) { |
| 3299 context.handleOutOfFlowPositioned(m_positionedObjects); |
| 3300 } else if (context.currentObject()->isFloating()) { |
| 3301 context.handleFloat(); |
| 3302 } else if (context.currentObject()->isRenderInline()) { |
| 3303 context.handleEmptyInline(); |
| 3304 } else if (context.currentObject()->isReplaced()) { |
| 3305 context.handleReplaced(); |
| 3306 } else if (context.currentObject()->isText()) { |
| 3307 if (context.handleText(wordMeasurements, m_hyphenated)) { |
| 3308 // We've hit a hard text line break. Our line break iterator is
updated, so go ahead and early return. |
| 3309 return context.lineBreak(); |
| 3310 } |
| 3311 } else { |
| 3312 ASSERT_NOT_REACHED(); |
| 3313 } |
| 3314 |
| 3315 if (context.atEnd()) |
| 3316 return context.handleEndOfLine(); |
| 3317 |
| 3318 context.commitAndUpdateLineBreakIfNeeded(); |
| 3319 |
| 3320 if (context.atEnd()) |
| 3321 return context.handleEndOfLine(); |
| 3322 |
| 3323 context.increment(); |
| 3324 } |
| 3325 |
| 3326 context.clearLineBreakIfFitsOnLine(); |
| 3327 |
| 3328 return context.handleEndOfLine(); |
3188 } | 3329 } |
3189 | 3330 |
3190 void RenderBlock::addOverflowFromInlineChildren() | 3331 void RenderBlock::addOverflowFromInlineChildren() |
3191 { | 3332 { |
3192 LayoutUnit endPadding = hasOverflowClip() ? paddingEnd() : LayoutUnit(); | 3333 LayoutUnit endPadding = hasOverflowClip() ? paddingEnd() : LayoutUnit(); |
3193 // FIXME: Need to find another way to do this, since scrollbars could show w
hen we don't want them to. | 3334 // FIXME: Need to find another way to do this, since scrollbars could show w
hen we don't want them to. |
3194 if (hasOverflowClip() && !endPadding && node() && node()->isRootEditableElem
ent() && style()->isLeftToRightDirection()) | 3335 if (hasOverflowClip() && !endPadding && node() && node()->isRootEditableElem
ent() && style()->isLeftToRightDirection()) |
3195 endPadding = 1; | 3336 endPadding = 1; |
3196 for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox())
{ | 3337 for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox())
{ |
3197 addLayoutOverflow(curr->paddedLayoutOverflowRect(endPadding)); | 3338 addLayoutOverflow(curr->paddedLayoutOverflowRect(endPadding)); |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3360 lineGridBox->alignBoxesInBlockDirection(logicalHeight(), textBoxDataMap, ver
ticalPositionCache); | 3501 lineGridBox->alignBoxesInBlockDirection(logicalHeight(), textBoxDataMap, ver
ticalPositionCache); |
3361 | 3502 |
3362 setLineGridBox(lineGridBox); | 3503 setLineGridBox(lineGridBox); |
3363 | 3504 |
3364 // FIXME: If any of the characteristics of the box change compared to the ol
d one, then we need to do a deep dirtying | 3505 // FIXME: If any of the characteristics of the box change compared to the ol
d one, then we need to do a deep dirtying |
3365 // (similar to what happens when the page height changes). Ideally, though,
we only do this if someone is actually snapping | 3506 // (similar to what happens when the page height changes). Ideally, though,
we only do this if someone is actually snapping |
3366 // to this grid. | 3507 // to this grid. |
3367 } | 3508 } |
3368 | 3509 |
3369 } | 3510 } |
OLD | NEW |