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 Bidim_ I doubt it matters . |
eae
2013/09/27 23:09:04
Over reaching search/replace?
| |
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 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2523 for (size_t i = 0; i < m_boxes.size(); ++i) { | 2656 for (size_t i = 0; i < m_boxes.size(); ++i) { |
2524 ensureLineBoxInsideIgnoredSpaces(lineMidpointState, m_boxes[i]); | 2657 ensureLineBoxInsideIgnoredSpaces(lineMidpointState, m_boxes[i]); |
2525 } | 2658 } |
2526 } | 2659 } |
2527 } | 2660 } |
2528 | 2661 |
2529 void LineBreaker::reset() | 2662 void LineBreaker::reset() |
2530 { | 2663 { |
2531 m_positionedObjects.clear(); | 2664 m_positionedObjects.clear(); |
2532 m_hyphenated = false; | 2665 m_hyphenated = false; |
2533 m_clear = CNONE; | |
eae
2013/09/27 23:09:04
Where did this go?
| |
2534 } | 2666 } |
2535 | 2667 |
2536 InlineIterator LineBreaker::nextLineBreak(InlineBidiResolver& resolver, LineInfo & lineInfo, RenderTextInfo& renderTextInfo, FloatingObject* lastFloatFromPreviou sLine, unsigned consecutiveHyphenatedLines, WordMeasurements& wordMeasurements) | 2668 InlineIterator LineBreaker::nextLineBreak(InlineBidiResolver& resolver, LineInfo & lineInfo, RenderTextInfo& renderTextInfo, FloatingObject* lastFloatFromPreviou sLine, unsigned consecutiveHyphenatedLines, WordMeasurements& wordMeasurements) |
2537 { | 2669 { |
2538 ShapeInsideInfo* shapeInsideInfo = m_block->layoutShapeInsideInfo(); | 2670 ShapeInsideInfo* shapeInsideInfo = m_block->layoutShapeInsideInfo(); |
2539 | 2671 |
2540 if (!shapeInsideInfo || !shapeInsideInfo->lineOverlapsShapeBounds()) | 2672 if (!shapeInsideInfo || !shapeInsideInfo->lineOverlapsShapeBounds()) |
2541 return nextSegmentBreak(resolver, lineInfo, renderTextInfo, lastFloatFro mPreviousLine, consecutiveHyphenatedLines, wordMeasurements); | 2673 return nextSegmentBreak(resolver, lineInfo, renderTextInfo, lastFloatFro mPreviousLine, consecutiveHyphenatedLines, wordMeasurements); |
2542 | 2674 |
2543 InlineIterator end = resolver.position(); | 2675 InlineIterator end = resolver.position(); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2581 } | 2713 } |
2582 resolver.setPositionIgnoringNestedIsolates(oldEnd); | 2714 resolver.setPositionIgnoringNestedIsolates(oldEnd); |
2583 return end; | 2715 return end; |
2584 } | 2716 } |
2585 | 2717 |
2586 static inline bool iteratorIsBeyondEndOfRenderCombineText(const InlineIterator& iter, RenderCombineText* renderer) | 2718 static inline bool iteratorIsBeyondEndOfRenderCombineText(const InlineIterator& iter, RenderCombineText* renderer) |
2587 { | 2719 { |
2588 return iter.m_obj == renderer && iter.m_pos >= renderer->textLength(); | 2720 return iter.m_obj == renderer && iter.m_pos >= renderer->textLength(); |
2589 } | 2721 } |
2590 | 2722 |
2591 InlineIterator LineBreaker::nextSegmentBreak(InlineBidiResolver& resolver, LineI nfo& lineInfo, RenderTextInfo& renderTextInfo, FloatingObject* lastFloatFromPrev iousLine, unsigned consecutiveHyphenatedLines, WordMeasurements& wordMeasurement s) | 2723 inline void LineBreaker::BreakingContext::handleBR(EClear& clear) |
2592 { | 2724 { |
2593 reset(); | 2725 if (m_width.fitsOnLine()) { |
2594 | 2726 RenderObject* br = m_current.m_obj; |
2595 ASSERT(resolver.position().root() == m_block); | 2727 m_lineBreak.moveToStartOf(br); |
2596 | 2728 m_lineBreak.increment(); |
2597 bool appliedStartWidth = resolver.position().m_pos > 0; | 2729 |
2598 bool includeEndWidth = true; | 2730 // A <br> always breaks a line, so don't let the line be collapsed |
2599 LineMidpointState& lineMidpointState = resolver.midpointState(); | 2731 // away. Also, the space at the end of a line with a <br> does not |
2600 | 2732 // 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())); | 2733 // cleanly. Otherwise the <br> has no effect on whether the line is |
2602 | 2734 // empty or not. |
2603 skipLeadingWhitespace(resolver, lineInfo, lastFloatFromPreviousLine, width); | 2735 if (m_startingNewParagraph) |
2604 | 2736 m_lineInfo.setEmpty(false, m_block, &m_width); |
2605 if (resolver.position().atEnd()) | 2737 m_trailingObjects.clear(); |
2606 return resolver.position(); | 2738 m_lineInfo.setPreviousLineBrokeCleanly(true); |
2607 | 2739 |
2608 // This variable is used only if whitespace isn't set to PRE, and it tells u s whether | 2740 // 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. | 2741 // need to check for floats to clear - so if we're ignoring spaces, stop ignoring them and add a |
2610 bool ignoringSpaces = false; | 2742 // run for this object. |
2611 InlineIterator ignoreStart; | 2743 if (m_ignoringSpaces && m_currentStyle->clear() != CNONE) |
2612 | 2744 ensureLineBoxInsideIgnoredSpaces(m_lineMidpointState, br); |
2613 // This variable tracks whether the very last character we saw was a space. We use | 2745 |
2614 // this to detect when we encounter a second space so we know we have to ter minate | 2746 if (!m_lineInfo.isEmpty()) |
2615 // a run. | 2747 clear = m_currentStyle->clear(); |
2616 bool currentCharacterIsSpace = false; | 2748 } |
2617 bool currentCharacterShouldCollapseIfPreWap = false; | 2749 m_atEnd = true; |
2618 TrailingObjects trailingObjects; | 2750 } |
2619 | 2751 |
2620 InlineIterator lBreak = resolver.position(); | 2752 inline void LineBreaker::BreakingContext::handleOutOfFlowPositioned(Vector<Rende rBox*>& positionedObjects) |
2621 | 2753 { |
2622 // FIXME: It is error-prone to split the position object out like this. | 2754 // 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. | 2755 // go ahead and determine our static inline position now. |
2624 InlineIterator current = resolver.position(); | 2756 RenderBox* box = toRenderBox(m_current.m_obj); |
2625 RenderObject* last = current.m_obj; | 2757 bool isInlineType = box->style()->isOriginalDisplayInlineType(); |
2626 bool atStart = true; | 2758 if (!isInlineType) { |
2627 | 2759 m_block->setStaticInlinePositionForChild(box, m_block->logicalHeight(), m_block->startOffsetForContent(m_block->logicalHeight())); |
2628 bool startingNewParagraph = lineInfo.previousLineBrokeCleanly(); | 2760 } else { |
2629 lineInfo.setPreviousLineBrokeCleanly(false); | 2761 // If our original display was an INLINE type, then we can go ahead |
2630 | 2762 // and determine our static y position now. |
2631 bool autoWrapWasEverTrueOnLine = false; | 2763 box->layer()->setStaticBlockPosition(m_block->logicalHeight()); |
2632 bool floatsFitOnLine = true; | 2764 } |
2633 | 2765 |
2634 // Firefox and Opera will allow a table cell to grow to fit an image inside it under | 2766 // 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). | 2767 // then start ignoring spaces again. |
2636 // Not supporting the quirk has caused us to mis-render some real sites. (Se e Bugzilla 10517.) | 2768 if (isInlineType || box->container()->isRenderInline()) { |
2637 RenderStyle* blockStyle = m_block->style(); | 2769 if (m_ignoringSpaces) |
2638 bool allowImagesToBreak = !m_block->document().inQuirksMode() || !m_block->i sTableCell() || !blockStyle->logicalWidth().isIntrinsicOrAuto(); | 2770 ensureLineBoxInsideIgnoredSpaces(m_lineMidpointState, box); |
2639 | 2771 m_trailingObjects.appendBoxIfNeeded(box); |
2640 EWhiteSpace currWS = blockStyle->whiteSpace(); | 2772 } else { |
2641 EWhiteSpace lastWS = currWS; | 2773 positionedObjects.append(box); |
2642 while (current.m_obj) { | 2774 } |
2643 RenderStyle* currentStyle = current.m_obj->style(); | 2775 m_width.addUncommittedWidth(inlineLogicalWidth(box)); |
2644 RenderObject* next = bidiNextSkippingEmptyInlines(m_block, current.m_obj ); | 2776 // Reset prior line break context characters. |
2645 if (next && next->parent() && !next->parent()->isDescendantOf(current.m_ obj->parent())) | 2777 m_renderTextInfo.m_lineBreakIterator.resetPriorContext(); |
2646 includeEndWidth = true; | 2778 } |
2647 | 2779 |
2648 currWS = current.m_obj->isReplaced() ? current.m_obj->parent()->style()- >whiteSpace() : currentStyle->whiteSpace(); | 2780 inline void LineBreaker::BreakingContext::handleFloat() |
2649 lastWS = last->isReplaced() ? last->parent()->style()->whiteSpace() : la st->style()->whiteSpace(); | 2781 { |
2650 | 2782 RenderBox* floatBox = toRenderBox(m_current.m_obj); |
2651 bool autoWrap = RenderStyle::autoWrap(currWS); | 2783 FloatingObject* floatingObject = m_block->insertFloatingObject(floatBox); |
2652 autoWrapWasEverTrueOnLine = autoWrapWasEverTrueOnLine || autoWrap; | 2784 // check if it fits in the current line. |
2653 | 2785 // If it does, position it now, otherwise, position |
2654 bool preserveNewline = current.m_obj->isSVGInlineText() ? false : Render Style::preserveNewline(currWS); | 2786 // it after moving to next line (in newLine() func) |
2655 | 2787 // FIXME: Bug 110372: Properly position multiple stacked floats with non-rec tangular shape outside. |
2656 bool collapseWhiteSpace = RenderStyle::collapseWhiteSpace(currWS); | 2788 if (m_floatsFitOnLine && m_width.fitsOnLine(floatingObject->logicalWidth(m_b lock->isHorizontalWritingMode()))) { |
2657 | 2789 m_block->positionNewFloatOnLine(floatingObject, m_lastFloatFromPreviousL ine, m_lineInfo, m_width); |
2658 if (current.m_obj->isBR()) { | 2790 if (m_lineBreak.m_obj == m_current.m_obj) { |
2659 if (width.fitsOnLine()) { | 2791 ASSERT(!m_lineBreak.m_pos); |
2660 lBreak.moveToStartOf(current.m_obj); | 2792 m_lineBreak.increment(); |
2661 lBreak.increment(); | 2793 } |
2662 | 2794 } else { |
2663 // A <br> always breaks a line, so don't let the line be collaps ed | 2795 m_floatsFitOnLine = false; |
2664 // away. Also, the space at the end of a line with a <br> does n ot | 2796 } |
2665 // get collapsed away. It only does this if the previous line b roke | 2797 // 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 | 2798 m_renderTextInfo.m_lineBreakIterator.updatePriorContext(replacementCharacter ); |
2667 // empty or not. | 2799 } |
2668 if (startingNewParagraph) | 2800 |
2669 lineInfo.setEmpty(false, m_block, &width); | 2801 inline void LineBreaker::BreakingContext::handleEmptyInline() |
2670 trailingObjects.clear(); | 2802 { |
2671 lineInfo.setPreviousLineBrokeCleanly(true); | 2803 // This should only end up being called on empty inlines |
2672 | 2804 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 | 2805 |
2674 // need to check for floats to clear - so if we're ignoring spac es, stop ignoring them and add a | 2806 RenderInline* flowBox = toRenderInline(m_current.m_obj); |
2675 // run for this object. | 2807 |
2676 if (ignoringSpaces && currentStyle->clear() != CNONE) | 2808 // Now that some inline flows have line boxes, if we are already ignoring sp aces, we need |
2677 ensureLineBoxInsideIgnoredSpaces(lineMidpointState, current. m_obj); | 2809 // to make sure that we stop to include this object and then start ignoring spaces again. |
2678 | 2810 // If this object is at the start of the line, we need to behave like list m arkers and |
2679 if (!lineInfo.isEmpty()) | 2811 // start ignoring spaces. |
2680 m_clear = currentStyle->clear(); | 2812 bool requiresLineBox = alwaysRequiresLineBox(m_current.m_obj); |
2681 } | 2813 if (requiresLineBox || requiresLineBoxForContent(flowBox, m_lineInfo)) { |
2682 goto end; | 2814 // An empty inline that only has line-height, vertical-align or font-met rics will only get a |
2683 } | 2815 // line box to affect the height of the line if the rest of the line is not empty. |
2684 | 2816 if (requiresLineBox) |
2685 if (current.m_obj->isOutOfFlowPositioned()) { | 2817 m_lineInfo.setEmpty(false, m_block, &m_width); |
2686 // If our original display wasn't an inline type, then we can | 2818 if (m_ignoringSpaces) { |
2687 // go ahead and determine our static inline position now. | 2819 m_trailingObjects.clear(); |
2688 RenderBox* box = toRenderBox(current.m_obj); | 2820 ensureLineBoxInsideIgnoredSpaces(m_lineMidpointState, m_current.m_ob j); |
2689 bool isInlineType = box->style()->isOriginalDisplayInlineType(); | 2821 } else if (m_blockStyle->collapseWhiteSpace() && m_resolver.position().m _obj == m_current.m_obj |
2690 if (!isInlineType) | 2822 && shouldSkipWhitespaceAfterStartObject(m_block, m_current.m_obj, m_ lineMidpointState)) { |
2691 m_block->setStaticInlinePositionForChild(box, m_block->logicalHe ight(), m_block->startOffsetForContent(m_block->logicalHeight())); | 2823 // Like with list markers, we start ignoring spaces to make sure tha t any |
2692 else { | 2824 // additional spaces we see will be discarded. |
2693 // If our original display was an INLINE type, then we can go ah ead | 2825 m_currentCharacterShouldCollapseIfPreWap = m_currentCharacterIsSpace = true; |
2694 // and determine our static y position now. | 2826 m_ignoringSpaces = true; |
2695 box->layer()->setStaticBlockPosition(m_block->logicalHeight()); | 2827 } |
2696 } | 2828 } |
2697 | 2829 |
2698 // If we're ignoring spaces, we have to stop and include this object and | 2830 m_width.addUncommittedWidth(inlineLogicalWidth(m_current.m_obj) + borderPadd ingMarginStart(flowBox) + borderPaddingMarginEnd(flowBox)); |
2699 // then start ignoring spaces again. | 2831 } |
2700 if (isInlineType || current.m_obj->container()->isRenderInline()) { | 2832 |
2701 if (ignoringSpaces) | 2833 inline void LineBreaker::BreakingContext::handleReplaced() |
2702 ensureLineBoxInsideIgnoredSpaces(lineMidpointState, current. m_obj); | 2834 { |
2703 trailingObjects.appendBoxIfNeeded(box); | 2835 RenderBox* replacedBox = toRenderBox(m_current.m_obj); |
2704 } else | 2836 |
2705 m_positionedObjects.append(box); | 2837 if (m_atStart) |
2706 width.addUncommittedWidth(inlineLogicalWidth(current.m_obj)); | 2838 m_width.updateAvailableWidth(replacedBox->logicalHeight()); |
2707 // Reset prior line break context characters. | 2839 |
2708 renderTextInfo.m_lineBreakIterator.resetPriorContext(); | 2840 // Break on replaced elements if either has normal white-space. |
2709 } else if (current.m_obj->isFloating()) { | 2841 if ((m_autoWrap || RenderStyle::autoWrap(m_lastWS)) && (!m_current.m_obj->is Image() || m_allowImagesToBreak)) { |
2710 RenderBox* floatBox = toRenderBox(current.m_obj); | 2842 m_width.commit(); |
2711 FloatingObject* f = m_block->insertFloatingObject(floatBox); | 2843 m_lineBreak.moveToStartOf(m_current.m_obj); |
2712 // check if it fits in the current line. | 2844 } |
2713 // If it does, position it now, otherwise, position | 2845 |
2714 // it after moving to next line (in newLine() func) | 2846 if (m_ignoringSpaces) |
2715 // FIXME: Bug 110372: Properly position multiple stacked floats with non-rectangular shape outside. | 2847 stopIgnoringSpaces(m_lineMidpointState, InlineIterator(0, m_current.m_ob j, 0)); |
2716 if (floatsFitOnLine && width.fitsOnLine(f->logicalWidth(m_block->isH orizontalWritingMode()))) { | 2848 |
2717 m_block->positionNewFloatOnLine(f, lastFloatFromPreviousLine, li neInfo, width); | 2849 m_lineInfo.setEmpty(false, m_block, &m_width); |
2718 if (lBreak.m_obj == current.m_obj) { | 2850 m_ignoringSpaces = false; |
2719 ASSERT(!lBreak.m_pos); | 2851 m_currentCharacterShouldCollapseIfPreWap = m_currentCharacterIsSpace = false ; |
2720 lBreak.increment(); | 2852 m_trailingObjects.clear(); |
2853 | |
2854 // Optimize for a common case. If we can't find whitespace after the list | |
2855 // item, then this is all moot. | |
2856 LayoutUnit replacedLogicalWidth = m_block->logicalWidthForChild(replacedBox) + m_block->marginStartForChild(replacedBox) + m_block->marginEndForChild(replac edBox) + inlineLogicalWidth(m_current.m_obj); | |
2857 if (m_current.m_obj->isListMarker()) { | |
2858 if (m_blockStyle->collapseWhiteSpace() && shouldSkipWhitespaceAfterStart Object(m_block, m_current.m_obj, m_lineMidpointState)) { | |
2859 // Like with inline flows, we start ignoring spaces to make sure tha t any | |
2860 // additional spaces we see will be discarded. | |
2861 m_currentCharacterShouldCollapseIfPreWap = m_currentCharacterIsSpace = true; | |
2862 m_ignoringSpaces = true; | |
2863 } | |
2864 if (toRenderListMarker(m_current.m_obj)->isInside()) | |
2865 m_width.addUncommittedWidth(replacedLogicalWidth); | |
2866 } else { | |
2867 m_width.addUncommittedWidth(replacedLogicalWidth); | |
2868 } | |
2869 if (m_current.m_obj->isRubyRun()) | |
2870 m_width.applyOverhang(toRenderRubyRun(m_current.m_obj), m_lastObject, m_ nextObject); | |
2871 // Update prior line break context characters, using U+FFFD (OBJECT REPLACEM ENT CHARACTER) for replaced element. | |
2872 m_renderTextInfo.m_lineBreakIterator.updatePriorContext(replacementCharacter ); | |
2873 } | |
2874 | |
2875 static inline void nextCharacter(UChar& currentCharacter, UChar& lastCharacter, UChar& secondToLastCharacter) | |
2876 { | |
2877 secondToLastCharacter = lastCharacter; | |
2878 lastCharacter = currentCharacter; | |
2879 } | |
2880 | |
2881 inline bool LineBreaker::BreakingContext::handleText(WordMeasurements& wordMeasu rements, bool& hyphenated) | |
2882 { | |
2883 if (!m_current.m_pos) | |
2884 m_appliedStartWidth = false; | |
2885 | |
2886 RenderText* renderText = toRenderText(m_current.m_obj); | |
2887 | |
2888 bool isSVGText = renderText->isSVGInlineText(); | |
2889 | |
2890 if (renderText->style()->hasTextCombine() && m_current.m_obj->isCombineText( ) && !toRenderCombineText(m_current.m_obj)->isCombined()) { | |
2891 RenderCombineText* combineRenderer = toRenderCombineText(m_current.m_obj ); | |
2892 combineRenderer->combineText(); | |
2893 // The length of the renderer's text may have changed. Increment stale i terator positions | |
2894 if (iteratorIsBeyondEndOfRenderCombineText(m_lineBreak, combineRenderer) ) { | |
2895 ASSERT(iteratorIsBeyondEndOfRenderCombineText(m_resolver.position(), combineRenderer)); | |
2896 m_lineBreak.increment(); | |
2897 m_resolver.position().increment(&m_resolver); | |
2898 } | |
2899 } | |
2900 | |
2901 RenderStyle* style = renderText->style(m_lineInfo.isFirstLine()); | |
2902 const Font& font = style->font(); | |
2903 bool isFixedPitch = font.isFixedPitch(); | |
2904 | |
2905 unsigned lastSpace = m_current.m_pos; | |
2906 float wordSpacing = m_currentStyle->wordSpacing(); | |
2907 float lastSpaceWordSpacing = 0; | |
2908 float wordSpacingForWordMeasurement = 0; | |
2909 | |
2910 float wrapW = m_width.uncommittedWidth() + inlineLogicalWidth(m_current.m_ob j, !m_appliedStartWidth, true); | |
2911 float charWidth = 0; | |
2912 // Auto-wrapping text should wrap in the middle of a word only if it could n ot wrap before the word, | |
2913 // which is only possible if the word is the first thing on the line, that i s, if |w| is zero. | |
2914 bool breakWords = m_currentStyle->breakWords() && ((m_autoWrap && !m_width.c ommittedWidth()) || m_currWS == PRE); | |
2915 bool midWordBreak = false; | |
2916 bool breakAll = m_currentStyle->wordBreak() == BreakAllWordBreak && m_autoWr ap; | |
2917 float hyphenWidth = 0; | |
2918 | |
2919 if (isSVGText) { | |
2920 breakWords = false; | |
2921 breakAll = false; | |
2922 } | |
2923 | |
2924 if (renderText->isWordBreak()) { | |
2925 m_width.commit(); | |
2926 m_lineBreak.moveToStartOf(m_current.m_obj); | |
2927 ASSERT(m_current.m_pos == renderText->textLength()); | |
2928 } | |
2929 | |
2930 if (m_renderTextInfo.m_text != renderText) { | |
2931 m_renderTextInfo.m_text = renderText; | |
2932 m_renderTextInfo.m_font = &font; | |
2933 m_renderTextInfo.m_layout = font.createLayout(renderText, m_width.curren tWidth(), m_collapseWhiteSpace); | |
2934 m_renderTextInfo.m_lineBreakIterator.resetStringAndReleaseIterator(rende rText->text(), style->locale()); | |
2935 } else if (m_renderTextInfo.m_layout && m_renderTextInfo.m_font != &font) { | |
2936 m_renderTextInfo.m_font = &font; | |
2937 m_renderTextInfo.m_layout = font.createLayout(renderText, m_width.curren tWidth(), m_collapseWhiteSpace); | |
2938 } | |
2939 | |
2940 TextLayout* textLayout = m_renderTextInfo.m_layout.get(); | |
2941 | |
2942 // Non-zero only when kerning is enabled and TextLayout isn't used, in which case we measure | |
2943 // words with their trailing space, then subtract its width. | |
2944 float wordTrailingSpaceWidth = (font.typesettingFeatures() & Kerning) && !te xtLayout ? font.width(RenderBlock::constructTextRun(renderText, font, &space, 1, style)) + wordSpacing : 0; | |
2945 | |
2946 UChar lastCharacter = m_renderTextInfo.m_lineBreakIterator.lastCharacter(); | |
2947 UChar secondToLastCharacter = m_renderTextInfo.m_lineBreakIterator.secondToL astCharacter(); | |
2948 for (; m_current.m_pos < renderText->textLength(); m_current.fastIncrementIn TextNode()) { | |
2949 bool previousCharacterIsSpace = m_currentCharacterIsSpace; | |
2950 bool previousCharacterShouldCollapseIfPreWap = m_currentCharacterShouldC ollapseIfPreWap; | |
2951 UChar c = m_current.current(); | |
2952 m_currentCharacterShouldCollapseIfPreWap = m_currentCharacterIsSpace = c == ' ' || c == '\t' || (!m_preservesNewline && (c == '\n')); | |
2953 | |
2954 if (!m_collapseWhiteSpace || !m_currentCharacterIsSpace) | |
2955 m_lineInfo.setEmpty(false, m_block, &m_width); | |
2956 | |
2957 if (c == softHyphen && m_autoWrap && !hyphenWidth) { | |
2958 hyphenWidth = measureHyphenWidth(renderText, font); | |
2959 m_width.addUncommittedWidth(hyphenWidth); | |
2960 } | |
2961 | |
2962 bool applyWordSpacing = false; | |
2963 | |
2964 if ((breakAll || breakWords) && !midWordBreak) { | |
2965 wrapW += charWidth; | |
2966 bool midWordBreakIsBeforeSurrogatePair = U16_IS_LEAD(c) && m_current .m_pos + 1 < renderText->textLength() && U16_IS_TRAIL((*renderText)[m_current.m_ pos + 1]); | |
2967 charWidth = textWidth(renderText, m_current.m_pos, midWordBreakIsBef oreSurrogatePair ? 2 : 1, font, m_width.committedWidth() + wrapW, isFixedPitch, m_collapseWhiteSpace, 0, textLayout); | |
2968 midWordBreak = m_width.committedWidth() + wrapW + charWidth > m_widt h.availableWidth(); | |
2969 } | |
2970 | |
2971 bool betweenWords = c == '\n' || (m_currWS != PRE && !m_atStart && isBre akable(m_renderTextInfo.m_lineBreakIterator, m_current.m_pos, m_current.m_nextBr eakablePosition)); | |
2972 | |
2973 if (betweenWords || midWordBreak) { | |
2974 bool stoppedIgnoringSpaces = false; | |
2975 if (m_ignoringSpaces) { | |
2976 lastSpaceWordSpacing = 0; | |
2977 if (!m_currentCharacterIsSpace) { | |
2978 // Stop ignoring spaces and begin at this | |
2979 // new point. | |
2980 m_ignoringSpaces = false; | |
2981 wordSpacingForWordMeasurement = 0; | |
2982 lastSpace = m_current.m_pos; // e.g., "Foo goo", don't ad d in any of the ignored spaces. | |
2983 stopIgnoringSpaces(m_lineMidpointState, InlineIterator(0, m_ current.m_obj, m_current.m_pos)); | |
2984 stoppedIgnoringSpaces = true; | |
2985 } else { | |
2986 // Just keep ignoring these spaces. | |
2987 nextCharacter(c, lastCharacter, secondToLastCharacter); | |
2988 continue; | |
2721 } | 2989 } |
2722 } else | 2990 } |
2723 floatsFitOnLine = false; | 2991 |
2724 // Update prior line break context characters, using U+FFFD (OBJECT REPLACEMENT CHARACTER) for floating element. | 2992 wordMeasurements.grow(wordMeasurements.size() + 1); |
2725 renderTextInfo.m_lineBreakIterator.updatePriorContext(replacementCha racter); | 2993 WordMeasurement& wordMeasurement = wordMeasurements.last(); |
2726 } else if (current.m_obj->isRenderInline()) { | 2994 |
2727 // Right now, we should only encounter empty inlines here. | 2995 wordMeasurement.renderer = renderText; |
2728 ASSERT(isEmptyInline(current.m_obj)); | 2996 wordMeasurement.endOffset = m_current.m_pos; |
2729 | 2997 wordMeasurement.startOffset = lastSpace; |
2730 RenderInline* flowBox = toRenderInline(current.m_obj); | 2998 |
2731 | 2999 float additionalTmpW; |
2732 // Now that some inline flows have line boxes, if we are already ign oring spaces, we need | 3000 if (wordTrailingSpaceWidth && c == ' ') |
2733 // to make sure that we stop to include this object and then start i gnoring spaces again. | 3001 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 | 3002 else |
2735 // start ignoring spaces. | 3003 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); | 3004 |
2737 if (requiresLineBox || requiresLineBoxForContent(flowBox, lineInfo)) { | 3005 wordMeasurement.width = additionalTmpW + wordSpacingForWordMeasureme nt; |
2738 // An empty inline that only has line-height, vertical-align or font-metrics will only get a | 3006 additionalTmpW += lastSpaceWordSpacing; |
2739 // line box to affect the height of the line if the rest of the line is not empty. | 3007 m_width.addUncommittedWidth(additionalTmpW); |
2740 if (requiresLineBox) | 3008 if (!m_appliedStartWidth) { |
2741 lineInfo.setEmpty(false, m_block, &width); | 3009 m_width.addUncommittedWidth(inlineLogicalWidth(m_current.m_obj, true, false)); |
2742 if (ignoringSpaces) { | 3010 m_appliedStartWidth = true; |
2743 trailingObjects.clear(); | 3011 } |
2744 ensureLineBoxInsideIgnoredSpaces(lineMidpointState, current. m_obj); | 3012 |
2745 } else if (blockStyle->collapseWhiteSpace() && resolver.position ().m_obj == current.m_obj | 3013 applyWordSpacing = wordSpacing && m_currentCharacterIsSpace; |
2746 && shouldSkipWhitespaceAfterStartObject(m_block, current.m_o bj, lineMidpointState)) { | 3014 |
2747 // Like with list markers, we start ignoring spaces to make sure that any | 3015 if (!m_width.committedWidth() && m_autoWrap && !m_width.fitsOnLine() ) |
2748 // additional spaces we see will be discarded. | 3016 m_width.fitBelowFloats(); |
2749 currentCharacterShouldCollapseIfPreWap = currentCharacterIsS pace = true; | 3017 |
2750 ignoringSpaces = true; | 3018 if (m_autoWrap || breakWords) { |
3019 // If we break only after white-space, consider the current char acter | |
3020 // as candidate width for this line. | |
3021 bool lineWasTooWide = false; | |
3022 if (m_width.fitsOnLine() && m_currentCharacterIsSpace && m_curre ntStyle->breakOnlyAfterWhiteSpace() && !midWordBreak) { | |
3023 float charWidth = textWidth(renderText, m_current.m_pos, 1, font, m_width.currentWidth(), isFixedPitch, m_collapseWhiteSpace, &wordMeasureme nt.fallbackFonts, textLayout) + (applyWordSpacing ? wordSpacing : 0); | |
3024 // Check if line is too big even without the extra space | |
3025 // at the end of the line. If it is not, do nothing. | |
3026 // If the line needs the extra whitespace to be too long, | |
3027 // then move the line break to the space and skip all | |
3028 // additional whitespace. | |
3029 if (!m_width.fitsOnLine(charWidth)) { | |
3030 lineWasTooWide = true; | |
3031 m_lineBreak.moveTo(m_current.m_obj, m_current.m_pos, m_c urrent.m_nextBreakablePosition); | |
3032 skipTrailingWhitespace(m_lineBreak, m_lineInfo); | |
3033 } | |
2751 } | 3034 } |
2752 } | 3035 if (lineWasTooWide || !m_width.fitsOnLine()) { |
2753 | 3036 if (m_lineBreak.atTextParagraphSeparator()) { |
2754 width.addUncommittedWidth(inlineLogicalWidth(current.m_obj) + border PaddingMarginStart(flowBox) + borderPaddingMarginEnd(flowBox)); | 3037 if (!stoppedIgnoringSpaces && m_current.m_pos > 0) |
2755 } else if (current.m_obj->isReplaced()) { | 3038 ensureCharacterGetsLineBox(m_lineMidpointState, m_cu rrent); |
2756 RenderBox* replacedBox = toRenderBox(current.m_obj); | 3039 m_lineBreak.increment(); |
2757 | 3040 m_lineInfo.setPreviousLineBrokeCleanly(true); |
2758 if (atStart) | 3041 wordMeasurement.endOffset = m_lineBreak.m_pos; |
2759 width.updateAvailableWidth(replacedBox->logicalHeight()); | 3042 } |
2760 | 3043 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. | 3044 hyphenated = true; |
2762 if ((autoWrap || RenderStyle::autoWrap(lastWS)) && (!current.m_obj-> isImage() || allowImagesToBreak)) { | 3045 if (m_lineBreak.m_pos && m_lineBreak.m_pos != (unsigned)word Measurement.endOffset && !wordMeasurement.width) { |
2763 width.commit(); | 3046 if (charWidth) { |
2764 lBreak.moveToStartOf(current.m_obj); | 3047 wordMeasurement.endOffset = m_lineBreak.m_pos; |
2765 } | 3048 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 } | 3049 } |
2900 } | 3050 } |
2901 | 3051 // Didn't fit. Jump to the end unless there's still an oppor tunity to collapse whitespace. |
2902 wordMeasurements.grow(wordMeasurements.size() + 1); | 3052 if (m_ignoringSpaces || !m_collapseWhiteSpace || !m_currentC haracterIsSpace || !previousCharacterIsSpace) { |
2903 WordMeasurement& wordMeasurement = wordMeasurements.last(); | 3053 m_atEnd = true; |
2904 | 3054 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 } | 3055 } |
2922 | 3056 } else { |
2923 applyWordSpacing = wordSpacing && currentCharacterIsSpace; | 3057 if (!betweenWords || (midWordBreak && !m_autoWrap)) |
2924 | 3058 m_width.addUncommittedWidth(-additionalTmpW); |
2925 if (!width.committedWidth() && autoWrap && !width.fitsOnLine ()) | 3059 if (hyphenWidth) { |
2926 width.fitBelowFloats(); | 3060 // Subtract the width of the soft hyphen out since we fi t on a line. |
2927 | 3061 m_width.addUncommittedWidth(-hyphenWidth); |
2928 if (autoWrap || breakWords) { | 3062 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 } | 3063 } |
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 } | 3064 } |
3029 | 3065 } |
3030 if (isSVGText && current.m_pos > 0) { | 3066 |
3031 // Force creation of new InlineBoxes for each absolute posit ioned character (those that start new text chunks). | 3067 if (c == '\n' && m_preservesNewline) { |
3032 if (toRenderSVGInlineText(t)->characterStartsNewTextChunk(cu rrent.m_pos)) | 3068 if (!stoppedIgnoringSpaces && m_current.m_pos > 0) |
3033 ensureCharacterGetsLineBox(lineMidpointState, current); | 3069 ensureCharacterGetsLineBox(m_lineMidpointState, m_current); |
3070 m_lineBreak.moveTo(m_current.m_obj, m_current.m_pos, m_current.m _nextBreakablePosition); | |
3071 m_lineBreak.increment(); | |
3072 m_lineInfo.setPreviousLineBrokeCleanly(true); | |
3073 return true; | |
3074 } | |
3075 | |
3076 if (m_autoWrap && betweenWords) { | |
3077 m_width.commit(); | |
3078 wrapW = 0; | |
3079 m_lineBreak.moveTo(m_current.m_obj, m_current.m_pos, m_current.m _nextBreakablePosition); | |
3080 // Auto-wrapping text should not wrap in the middle of a word on ce it has had an | |
3081 // opportunity to break after a word. | |
3082 breakWords = false; | |
3083 } | |
3084 | |
3085 if (midWordBreak && !U16_IS_TRAIL(c) && !(category(c) & (Mark_NonSpa cing | Mark_Enclosing | Mark_SpacingCombining))) { | |
3086 // Remember this as a breakable position in case | |
3087 // adding the end width forces a break. | |
3088 m_lineBreak.moveTo(m_current.m_obj, m_current.m_pos, m_current.m _nextBreakablePosition); | |
3089 midWordBreak &= (breakWords || breakAll); | |
3090 } | |
3091 | |
3092 if (betweenWords) { | |
3093 lastSpaceWordSpacing = applyWordSpacing ? wordSpacing : 0; | |
3094 wordSpacingForWordMeasurement = (applyWordSpacing && wordMeasure ment.width) ? wordSpacing : 0; | |
3095 lastSpace = m_current.m_pos; | |
3096 } | |
3097 | |
3098 if (!m_ignoringSpaces && m_currentStyle->collapseWhiteSpace()) { | |
3099 // If we encounter a newline, or if we encounter a | |
3100 // second space, we need to go ahead and break up this | |
3101 // run and enter a mode where we start collapsing spaces. | |
3102 if (m_currentCharacterIsSpace && previousCharacterIsSpace) { | |
3103 m_ignoringSpaces = true; | |
3104 | |
3105 // We just entered a mode where we are ignoring | |
3106 // spaces. Create a midpoint to terminate the run | |
3107 // before the second space. | |
3108 startIgnoringSpaces(m_lineMidpointState, m_startOfIgnoredSpa ces); | |
3109 m_trailingObjects.updateMidpointsForTrailingBoxes(m_lineMidp ointState, InlineIterator(), TrailingObjects::DoNotCollapseFirstSpace); | |
3034 } | 3110 } |
3035 | 3111 } |
3036 if (currentCharacterIsSpace && !previousCharacterIsSpace) { | 3112 } else if (m_ignoringSpaces) { |
3037 ignoreStart.m_obj = current.m_obj; | 3113 // Stop ignoring spaces and begin at this |
3038 ignoreStart.m_pos = current.m_pos; | 3114 // new point. |
3039 } | 3115 m_ignoringSpaces = false; |
3040 | 3116 lastSpaceWordSpacing = applyWordSpacing ? wordSpacing : 0; |
3041 if (!currentCharacterIsSpace && previousCharacterShouldCollapseI fPreWap) { | 3117 wordSpacingForWordMeasurement = (applyWordSpacing && wordMeasurement s.last().width) ? wordSpacing : 0; |
3042 if (autoWrap && currentStyle->breakOnlyAfterWhiteSpace()) | 3118 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); | 3119 stopIgnoringSpaces(m_lineMidpointState, InlineIterator(0, m_current. m_obj, m_current.m_pos)); |
3044 } | 3120 } |
3045 | 3121 |
3046 if (collapseWhiteSpace && currentCharacterIsSpace && !ignoringSp aces) | 3122 if (isSVGText && m_current.m_pos > 0) { |
3047 trailingObjects.setTrailingWhitespace(toRenderText(current.m _obj)); | 3123 // Force creation of new InlineBoxes for each absolute positioned ch aracter (those that start new text chunks). |
3048 else if (!currentStyle->collapseWhiteSpace() || !currentCharacte rIsSpace) | 3124 if (toRenderSVGInlineText(renderText)->characterStartsNewTextChunk(m _current.m_pos)) |
3049 trailingObjects.clear(); | 3125 ensureCharacterGetsLineBox(m_lineMidpointState, m_current); |
3050 | 3126 } |
3051 atStart = false; | 3127 |
3052 nextCharacter: | 3128 if (m_currentCharacterIsSpace && !previousCharacterIsSpace) { |
3053 secondToLastCharacter = lastCharacter; | 3129 m_startOfIgnoredSpaces.m_obj = m_current.m_obj; |
3054 lastCharacter = c; | 3130 m_startOfIgnoredSpaces.m_pos = m_current.m_pos; |
3055 } | 3131 } |
3056 | 3132 |
3057 renderTextInfo.m_lineBreakIterator.setPriorContext(lastCharacter, se condToLastCharacter); | 3133 if (!m_currentCharacterIsSpace && previousCharacterShouldCollapseIfPreWa p) { |
3058 | 3134 if (m_autoWrap && m_currentStyle->breakOnlyAfterWhiteSpace()) |
3059 wordMeasurements.grow(wordMeasurements.size() + 1); | 3135 m_lineBreak.moveTo(m_current.m_obj, m_current.m_pos, m_current.m _nextBreakablePosition); |
3060 WordMeasurement& wordMeasurement = wordMeasurements.last(); | 3136 } |
3061 wordMeasurement.renderer = t; | 3137 |
3062 | 3138 if (m_collapseWhiteSpace && m_currentCharacterIsSpace && !m_ignoringSpac es) |
3063 // IMPORTANT: current.m_pos is > length here! | 3139 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); | 3140 else if (!m_currentStyle->collapseWhiteSpace() || !m_currentCharacterIsS pace) |
3065 wordMeasurement.startOffset = lastSpace; | 3141 m_trailingObjects.clear(); |
3066 wordMeasurement.endOffset = current.m_pos; | 3142 |
3067 wordMeasurement.width = ignoringSpaces ? 0 : additionalTmpW + wordSp acingForWordMeasurement; | 3143 m_atStart = false; |
3068 additionalTmpW += lastSpaceWordSpacing; | 3144 nextCharacter(c, lastCharacter, secondToLastCharacter); |
3069 width.addUncommittedWidth(additionalTmpW + inlineLogicalWidth(curren t.m_obj, !appliedStartWidth, includeEndWidth)); | 3145 } |
3070 includeEndWidth = false; | 3146 |
3071 | 3147 m_renderTextInfo.m_lineBreakIterator.setPriorContext(lastCharacter, secondTo LastCharacter); |
3072 if (!width.fitsOnLine()) { | 3148 |
3073 if (!m_hyphenated && lBreak.previousInSameNode() == softHyphen) | 3149 wordMeasurements.grow(wordMeasurements.size() + 1); |
3074 m_hyphenated = true; | 3150 WordMeasurement& wordMeasurement = wordMeasurements.last(); |
3075 | 3151 wordMeasurement.renderer = renderText; |
3076 if (m_hyphenated) | 3152 |
3077 goto end; | 3153 // IMPORTANT: current.m_pos is > length here! |
3078 } | 3154 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 | 3155 wordMeasurement.startOffset = lastSpace; |
3080 ASSERT_NOT_REACHED(); | 3156 wordMeasurement.endOffset = m_current.m_pos; |
3081 | 3157 wordMeasurement.width = m_ignoringSpaces ? 0 : additionalTmpW + wordSpacingF orWordMeasurement; |
3082 bool checkForBreak = autoWrap; | 3158 additionalTmpW += lastSpaceWordSpacing; |
3083 if (width.committedWidth() && !width.fitsOnLine() && lBreak.m_obj && cur rWS == NOWRAP) | 3159 m_width.addUncommittedWidth(additionalTmpW + inlineLogicalWidth(m_current.m_ obj, !m_appliedStartWidth, m_includeEndWidth)); |
3160 m_includeEndWidth = false; | |
3161 | |
3162 if (!m_width.fitsOnLine()) { | |
3163 if (!hyphenated && m_lineBreak.previousInSameNode() == softHyphen) { | |
3164 hyphenated = true; | |
3165 m_atEnd = true; | |
3166 } | |
3167 } | |
3168 return false; | |
3169 } | |
3170 | |
3171 inline void LineBreaker::BreakingContext::commitAndUpdateLineBreakIfNeeded() | |
3172 { | |
3173 bool checkForBreak = m_autoWrap; | |
3174 if (m_width.committedWidth() && !m_width.fitsOnLine() && m_lineBreak.m_obj & & m_currWS == NOWRAP) { | |
3175 checkForBreak = true; | |
3176 } else if (m_nextObject && m_current.m_obj->isText() && m_nextObject->isText () && !m_nextObject->isBR() && (m_autoWrap || m_nextObject->style()->autoWrap()) ) { | |
3177 if (m_autoWrap && m_currentCharacterIsSpace) { | |
3084 checkForBreak = true; | 3178 checkForBreak = true; |
3085 else if (next && current.m_obj->isText() && next->isText() && !next->isB R() && (autoWrap || next->style()->autoWrap())) { | 3179 } else { |
3086 if (autoWrap && currentCharacterIsSpace) | 3180 RenderText* nextText = toRenderText(m_nextObject); |
3181 if (nextText->textLength()) { | |
3182 UChar c = nextText->characterAt(0); | |
3183 // If the next item on the line is text, and if we did not end w ith | |
3184 // a space, then the next text run continues our word (and so it needs to | |
3185 // keep adding to the uncommitted width. Just update and continu e. | |
3186 checkForBreak = !m_currentCharacterIsSpace && (c == ' ' || c == '\t' || (c == '\n' && !m_nextObject->preservesNewline())); | |
3187 } else if (nextText->isWordBreak()) { | |
3087 checkForBreak = true; | 3188 checkForBreak = true; |
3088 else { | 3189 } |
3089 RenderText* nextText = toRenderText(next); | 3190 |
3090 if (nextText->textLength()) { | 3191 if (!m_width.fitsOnLine() && !m_width.committedWidth()) |
3091 UChar c = nextText->characterAt(0); | 3192 m_width.fitBelowFloats(); |
3092 // If the next item on the line is text, and if we did not e nd with | 3193 |
3093 // a space, then the next text run continues our word (and s o it needs to | 3194 bool canPlaceOnLine = m_width.fitsOnLine() || !m_autoWrapWasEverTrue OnLine; |
3094 // keep adding to the uncommitted width. Just update and con tinue. | 3195 if (canPlaceOnLine && checkForBreak) { |
3095 checkForBreak = !currentCharacterIsSpace && (c == ' ' || c = = '\t' || (c == '\n' && !next->preservesNewline())); | 3196 m_width.commit(); |
3096 } else if (nextText->isWordBreak()) | 3197 m_lineBreak.moveToStartOf(m_nextObject); |
3097 checkForBreak = true; | 3198 } |
3098 | 3199 } |
3099 if (!width.fitsOnLine() && !width.committedWidth()) | 3200 } |
3100 width.fitBelowFloats(); | 3201 |
3101 | 3202 if (checkForBreak && !m_width.fitsOnLine()) { |
3102 bool canPlaceOnLine = width.fitsOnLine() || !autoWrapWasEverTrue OnLine; | 3203 // if we have floats, try to get below them. |
3103 if (canPlaceOnLine && checkForBreak) { | 3204 if (m_currentCharacterIsSpace && !m_ignoringSpaces && m_currentStyle->co llapseWhiteSpace()) |
3104 width.commit(); | 3205 m_trailingObjects.clear(); |
3105 lBreak.moveToStartOf(next); | 3206 |
3106 } | 3207 if (m_width.committedWidth()) { |
3107 } | 3208 m_atEnd = true; |
3108 } | 3209 return; |
3109 | 3210 } |
3110 if (checkForBreak && !width.fitsOnLine()) { | 3211 |
3111 // if we have floats, try to get below them. | 3212 m_width.fitBelowFloats(); |
3112 if (currentCharacterIsSpace && !ignoringSpaces && currentStyle->coll apseWhiteSpace()) | 3213 |
3113 trailingObjects.clear(); | 3214 // |width| may have been adjusted because we got shoved down past a floa t (thus |
3114 | 3215 // giving us more room), so we need to retest, and only jump to |
3115 if (width.committedWidth()) | 3216 // the end label if we still don't fit on the line. -dwh |
3116 goto end; | 3217 if (!m_width.fitsOnLine()) { |
3117 | 3218 m_atEnd = true; |
3118 width.fitBelowFloats(); | 3219 return; |
3119 | 3220 } |
3120 // |width| may have been adjusted because we got shoved down past a float (thus | 3221 } 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 | 3222 // 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 | 3223 // wraps and moves below any floats. |
3123 if (!width.fitsOnLine()) | 3224 m_width.fitBelowFloats(); |
3124 goto end; | 3225 } |
3125 } else if (blockStyle->autoWrap() && !width.fitsOnLine() && !width.commi ttedWidth()) { | 3226 |
3126 // If the container autowraps but the current child does not then we still need to ensure that it | 3227 if (!m_current.m_obj->isFloatingOrOutOfFlowPositioned()) { |
3127 // wraps and moves below any floats. | 3228 m_lastObject = m_current.m_obj; |
3128 width.fitBelowFloats(); | 3229 if (m_lastObject->isReplaced() && m_autoWrap && (!m_lastObject->isImage( ) || m_allowImagesToBreak) && (!m_lastObject->isListMarker() || toRenderListMark er(m_lastObject)->isInside())) { |
3129 } | 3230 m_width.commit(); |
3130 | 3231 m_lineBreak.moveToStartOf(m_nextObject); |
3131 if (!current.m_obj->isFloatingOrOutOfFlowPositioned()) { | 3232 } |
3132 last = current.m_obj; | 3233 } |
3133 if (last->isReplaced() && autoWrap && (!last->isImage() || allowImag esToBreak) && (!last->isListMarker() || toRenderListMarker(last)->isInside())) { | 3234 } |
3134 width.commit(); | 3235 |
3135 lBreak.moveToStartOf(next); | 3236 InlineIterator LineBreaker::BreakingContext::handleEndOfLine() |
3136 } | 3237 { |
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(); | 3238 ShapeInsideInfo* shapeInfo = m_block->layoutShapeInsideInfo(); |
3153 bool segmentAllowsOverflow = !shapeInfo || !shapeInfo->hasSegments(); | 3239 bool segmentAllowsOverflow = !shapeInfo || !shapeInfo->hasSegments(); |
3154 | 3240 |
3155 if (lBreak == resolver.position() && (!lBreak.m_obj || !lBreak.m_obj->isBR() ) && segmentAllowsOverflow) { | 3241 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 | 3242 // we just add as much as possible |
3157 if (blockStyle->whiteSpace() == PRE && !current.m_pos) { | 3243 if (m_blockStyle->whiteSpace() == PRE && !m_current.m_pos) { |
3158 lBreak.moveTo(last, last->isText() ? last->length() : 0); | 3244 m_lineBreak.moveTo(m_lastObject, m_lastObject->isText() ? m_lastObje ct->length() : 0); |
3159 } else if (lBreak.m_obj) { | 3245 } else if (m_lineBreak.m_obj) { |
3160 // Don't ever break in the middle of a word if we can help it. | 3246 // 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, | 3247 // There's no room at all. We just have to be on this line, |
3162 // even though we'll spill out. | 3248 // even though we'll spill out. |
3163 lBreak.moveTo(current.m_obj, current.m_pos); | 3249 m_lineBreak.moveTo(m_current.m_obj, m_current.m_pos); |
3164 } | 3250 } |
3165 } | 3251 } |
3166 | 3252 |
3167 // FIXME Bug 100049: We do not need to consume input in a multi-segment line | 3253 // FIXME Bug 100049: We do not need to consume input in a multi-segment line |
3168 // unless no segment will. | 3254 // unless no segment will. |
3169 // make sure we consume at least one char/object. | 3255 // make sure we consume at least one char/object. |
3170 if (lBreak == resolver.position() && segmentAllowsOverflow) | 3256 if (m_lineBreak == m_resolver.position() && segmentAllowsOverflow) |
3171 lBreak.increment(); | 3257 m_lineBreak.increment(); |
3172 | 3258 |
3173 // Sanity check our midpoints. | 3259 // Sanity check our midpoints. |
3174 checkMidpoints(lineMidpointState, lBreak); | 3260 checkMidpoints(m_lineMidpointState, m_lineBreak); |
3175 | 3261 |
3176 trailingObjects.updateMidpointsForTrailingBoxes(lineMidpointState, lBreak, T railingObjects::CollapseFirstSpace); | 3262 m_trailingObjects.updateMidpointsForTrailingBoxes(m_lineMidpointState, m_lin eBreak, TrailingObjects::CollapseFirstSpace); |
3177 | 3263 |
3178 // We might have made lBreak an iterator that points past the end | 3264 // 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 | 3265 // 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 | 3266 // of the next object instead to avoid confusing the rest of the |
3181 // code. | 3267 // code. |
3182 if (lBreak.m_pos > 0) { | 3268 if (m_lineBreak.m_pos > 0) { |
3183 lBreak.m_pos--; | 3269 m_lineBreak.m_pos--; |
3184 lBreak.increment(); | 3270 m_lineBreak.increment(); |
3185 } | 3271 } |
3186 | 3272 |
3187 return lBreak; | 3273 return m_lineBreak; |
3274 } | |
3275 | |
3276 InlineIterator LineBreaker::nextSegmentBreak(InlineBidiResolver& resolver, LineI nfo& lineInfo, RenderTextInfo& renderTextInfo, FloatingObject* lastFloatFromPrev iousLine, unsigned consecutiveHyphenatedLines, WordMeasurements& wordMeasurement s) | |
3277 { | |
3278 reset(); | |
3279 | |
3280 ASSERT(resolver.position().root() == m_block); | |
3281 | |
3282 bool appliedStartWidth = resolver.position().m_pos > 0; | |
3283 | |
3284 LineWidth width(*m_block, lineInfo.isFirstLine(), requiresIndent(lineInfo.is FirstLine(), lineInfo.previousLineBrokeCleanly(), m_block->style())); | |
3285 | |
3286 skipLeadingWhitespace(resolver, lineInfo, lastFloatFromPreviousLine, width); | |
3287 | |
3288 if (resolver.position().atEnd()) | |
3289 return resolver.position(); | |
3290 | |
3291 BreakingContext context(resolver, lineInfo, width, renderTextInfo, lastFloat FromPreviousLine, appliedStartWidth, m_block); | |
3292 | |
3293 while (context.currentObject()) { | |
3294 context.initializeForCurrentObject(); | |
3295 if (context.currentObject()->isBR()) { | |
3296 context.handleBR(m_clear); | |
3297 } else if (context.currentObject()->isOutOfFlowPositioned()) { | |
3298 context.handleOutOfFlowPositioned(m_positionedObjects); | |
3299 } else if (context.currentObject()->isFloating()) { | |
3300 context.handleFloat(); | |
3301 } else if (context.currentObject()->isRenderInline()) { | |
3302 context.handleEmptyInline(); | |
3303 } else if (context.currentObject()->isReplaced()) { | |
3304 context.handleReplaced(); | |
3305 } else if (context.currentObject()->isText()) { | |
3306 if (context.handleText(wordMeasurements, m_hyphenated)) { | |
3307 // We've hit a hard text line break. Our line break iterator is updated, so go ahead and early return. | |
3308 return context.lineBreak(); | |
3309 } | |
3310 } else { | |
3311 ASSERT_NOT_REACHED(); | |
3312 } | |
3313 | |
3314 if (context.atEnd()) | |
3315 return context.handleEndOfLine(); | |
3316 | |
3317 context.commitAndUpdateLineBreakIfNeeded(); | |
3318 | |
3319 if (context.atEnd()) | |
3320 return context.handleEndOfLine(); | |
3321 | |
3322 context.increment(); | |
3323 } | |
3324 | |
3325 context.clearLineBreakIfFitsOnLine(); | |
3326 | |
3327 return context.handleEndOfLine(); | |
3188 } | 3328 } |
3189 | 3329 |
3190 void RenderBlock::addOverflowFromInlineChildren() | 3330 void RenderBlock::addOverflowFromInlineChildren() |
3191 { | 3331 { |
3192 LayoutUnit endPadding = hasOverflowClip() ? paddingEnd() : LayoutUnit(); | 3332 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. | 3333 // 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()) | 3334 if (hasOverflowClip() && !endPadding && node() && node()->isRootEditableElem ent() && style()->isLeftToRightDirection()) |
3195 endPadding = 1; | 3335 endPadding = 1; |
3196 for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) { | 3336 for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) { |
3197 addLayoutOverflow(curr->paddedLayoutOverflowRect(endPadding)); | 3337 addLayoutOverflow(curr->paddedLayoutOverflowRect(endPadding)); |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3360 lineGridBox->alignBoxesInBlockDirection(logicalHeight(), textBoxDataMap, ver ticalPositionCache); | 3500 lineGridBox->alignBoxesInBlockDirection(logicalHeight(), textBoxDataMap, ver ticalPositionCache); |
3361 | 3501 |
3362 setLineGridBox(lineGridBox); | 3502 setLineGridBox(lineGridBox); |
3363 | 3503 |
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 | 3504 // 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 | 3505 // (similar to what happens when the page height changes). Ideally, though, we only do this if someone is actually snapping |
3366 // to this grid. | 3506 // to this grid. |
3367 } | 3507 } |
3368 | 3508 |
3369 } | 3509 } |
OLD | NEW |