REGRESSION (r177876): store.apple.com profile and cart icons are missing
[WebKit-https.git] / Source / WebCore / rendering / SimpleLineLayout.cpp
1 /*
2  * Copyright (C) 2013 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "SimpleLineLayout.h"
28
29 #include "FontCache.h"
30 #include "Frame.h"
31 #include "GraphicsContext.h"
32 #include "HTMLTextFormControlElement.h"
33 #include "HitTestLocation.h"
34 #include "HitTestRequest.h"
35 #include "HitTestResult.h"
36 #include "InlineTextBox.h"
37 #include "LineWidth.h"
38 #include "PaintInfo.h"
39 #include "RenderBlockFlow.h"
40 #include "RenderChildIterator.h"
41 #include "RenderLineBreak.h"
42 #include "RenderStyle.h"
43 #include "RenderText.h"
44 #include "RenderTextControl.h"
45 #include "RenderView.h"
46 #include "Settings.h"
47 #include "SimpleLineLayoutFlowContents.h"
48 #include "SimpleLineLayoutFunctions.h"
49 #include "SimpleLineLayoutTextFragmentIterator.h"
50 #include "Text.h"
51 #include "TextPaintStyle.h"
52
53 namespace WebCore {
54 namespace SimpleLineLayout {
55
56 template <typename CharacterType>
57 static bool canUseForText(const CharacterType* text, unsigned length, const Font& font)
58 {
59     // FIXME: <textarea maxlength=0> generates empty text node.
60     if (!length)
61         return false;
62     for (unsigned i = 0; i < length; ++i) {
63         UChar character = text[i];
64         if (character == ' ')
65             continue;
66
67         // These would be easy to support.
68         if (character == noBreakSpace)
69             return false;
70         if (character == softHyphen)
71             return false;
72
73         UCharDirection direction = u_charDirection(character);
74         if (direction == U_RIGHT_TO_LEFT || direction == U_RIGHT_TO_LEFT_ARABIC
75             || direction == U_RIGHT_TO_LEFT_EMBEDDING || direction == U_RIGHT_TO_LEFT_OVERRIDE
76             || direction == U_LEFT_TO_RIGHT_EMBEDDING || direction == U_LEFT_TO_RIGHT_OVERRIDE
77             || direction == U_POP_DIRECTIONAL_FORMAT || direction == U_BOUNDARY_NEUTRAL)
78             return false;
79
80         if (!font.glyphForCharacter(character))
81             return false;
82     }
83     return true;
84 }
85 /*
86 static bool canUseForText(const RenderText& textRenderer, const Font& font)
87 {
88     if (textRenderer.is8Bit())
89         return canUseForText(textRenderer.characters8(), textRenderer.textLength(), font);
90     return canUseForText(textRenderer.characters16(), textRenderer.textLength(), font);
91 }
92 */
93 bool canUseFor(const RenderBlockFlow&)
94 {
95     return false; /*
96     if (!flow.frame().settings().simpleLineLayoutEnabled())
97         return false;
98     if (!flow.firstChild())
99         return false;
100     // This currently covers <blockflow>#text</blockflow>, <blockflow>#text<br></blockflow> and mutiple (sibling) RenderText cases.
101     // The <blockflow><inline>#text</inline></blockflow> case is also popular and should be relatively easy to cover.
102     for (const auto& renderer : childrenOfType<RenderObject>(flow)) {
103         if (is<RenderText>(renderer))
104             continue;
105         if (is<RenderLineBreak>(renderer) && !downcast<RenderLineBreak>(renderer).isWBR() && renderer.style().clear() == CNONE)
106             continue;
107         return false;
108     }
109     if (!flow.isHorizontalWritingMode())
110         return false;
111     if (flow.flowThreadState() != RenderObject::NotInsideFlowThread)
112         return false;
113     // Printing does pagination without a flow thread.
114     if (flow.document().paginated())
115         return false;
116     if (flow.hasOutline())
117         return false;
118     if (flow.isRubyText() || flow.isRubyBase())
119         return false;
120     if (flow.parent()->isDeprecatedFlexibleBox())
121         return false;
122     // FIXME: Implementation of wrap=hard looks into lineboxes.
123     if (flow.parent()->isTextArea() && flow.parent()->element()->fastHasAttribute(HTMLNames::wrapAttr))
124         return false;
125     // FIXME: Placeholders do something strange.
126     if (is<RenderTextControl>(*flow.parent()) && downcast<RenderTextControl>(*flow.parent()).textFormControlElement().placeholderElement())
127         return false;
128     const RenderStyle& style = flow.style();
129     if (style.textDecorationsInEffect() != TextDecorationNone)
130         return false;
131     if (style.textAlign() == JUSTIFY)
132         return false;
133     // Non-visible overflow should be pretty easy to support.
134     if (style.overflowX() != OVISIBLE || style.overflowY() != OVISIBLE)
135         return false;
136     if (!style.textIndent().isZero())
137         return false;
138     if (!style.wordSpacing().isZero() || style.letterSpacing())
139         return false;
140     if (!style.isLeftToRightDirection())
141         return false;
142     if (style.lineBoxContain() != RenderStyle::initialLineBoxContain())
143         return false;
144     if (style.writingMode() != TopToBottomWritingMode)
145         return false;
146     if (style.lineBreak() != LineBreakAuto)
147         return false;
148     if (style.wordBreak() != NormalWordBreak)
149         return false;
150     if (style.unicodeBidi() != UBNormal || style.rtlOrdering() != LogicalOrder)
151         return false;
152     if (style.lineAlign() != LineAlignNone || style.lineSnap() != LineSnapNone)
153         return false;
154     if (style.hyphens() == HyphensAuto)
155         return false;
156     if (style.textEmphasisFill() != TextEmphasisFillFilled || style.textEmphasisMark() != TextEmphasisMarkNone)
157         return false;
158     if (style.textShadow())
159         return false;
160     if (style.textOverflow() || (flow.isAnonymousBlock() && flow.parent()->style().textOverflow()))
161         return false;
162     if (style.hasPseudoStyle(FIRST_LINE) || style.hasPseudoStyle(FIRST_LETTER))
163         return false;
164     else if (flow.isAnonymous() && flow.firstLineBlock())
165         return false;
166     if (style.hasTextCombine())
167         return false;
168     if (style.backgroundClip() == TextFillBox)
169         return false;
170     if (style.borderFit() == BorderFitLines)
171         return false;
172     if (style.lineBreak() != LineBreakAuto)
173         return false;
174 #if ENABLE(CSS_TRAILING_WORD)
175     if (style.trailingWord() != TrailingWord::Auto)
176         return false;
177 #endif
178
179     // We can't use the code path if any lines would need to be shifted below floats. This is because we don't keep per-line y coordinates.
180     if (flow.containsFloats()) {
181         float minimumWidthNeeded = std::numeric_limits<float>::max();
182         for (const auto& textRenderer : childrenOfType<RenderText>(flow)) {
183             minimumWidthNeeded = std::min(minimumWidthNeeded, textRenderer.minLogicalWidth());
184
185             for (auto& floatingObject : *flow.floatingObjectSet()) {
186                 ASSERT(floatingObject);
187 #if ENABLE(CSS_SHAPES)
188                 // if a float has a shape, we cannot tell if content will need to be shifted until after we lay it out,
189                 // since the amount of space is not uniform for the height of the float.
190                 if (floatingObject->renderer().shapeOutsideInfo())
191                     return false;
192 #endif
193                 float availableWidth = flow.availableLogicalWidthForLine(floatingObject->y(), false);
194                 if (availableWidth < minimumWidthNeeded)
195                     return false;
196             }
197         }
198     }
199     if (style.fontCascade().primaryFont().isSVGFont())
200         return false;
201     // We assume that all lines have metrics based purely on the primary font.
202     auto& primaryFont = style.fontCascade().primaryFont();
203     if (primaryFont.isLoading())
204         return false;
205     for (const auto& textRenderer : childrenOfType<RenderText>(flow)) {
206         if (textRenderer.isCombineText() || textRenderer.isCounter() || textRenderer.isQuote() || textRenderer.isTextFragment()
207             || textRenderer.isSVGInlineText())
208             return false;
209         if (style.fontCascade().codePath(TextRun(textRenderer.text())) != FontCascade::Simple)
210             return false;
211         if (!canUseForText(textRenderer, primaryFont))
212             return false;
213     }
214     return true;
215     */
216 }
217
218 static float computeLineLeft(ETextAlign textAlign, float availableWidth, float committedWidth, float logicalLeftOffset)
219 {
220     float remainingWidth = availableWidth - committedWidth;
221     float left = logicalLeftOffset;
222     switch (textAlign) {
223     case LEFT:
224     case WEBKIT_LEFT:
225     case TASTART:
226         return left;
227     case RIGHT:
228     case WEBKIT_RIGHT:
229     case TAEND:
230         return left + std::max<float>(remainingWidth, 0);
231     case CENTER:
232     case WEBKIT_CENTER:
233         return left + std::max<float>(remainingWidth / 2, 0);
234     case JUSTIFY:
235         ASSERT_NOT_REACHED();
236         break;
237     }
238     ASSERT_NOT_REACHED();
239     return 0;
240 }
241
242 static void revertRuns(Layout::RunVector& runs, unsigned length, float width)
243 {
244     while (length) {
245         ASSERT(runs.size());
246         Run& lastRun = runs.last();
247         unsigned lastRunLength = lastRun.end - lastRun.start;
248         if (lastRunLength > length) {
249             lastRun.logicalRight -= width;
250             lastRun.end -= length;
251             break;
252         }
253         length -= lastRunLength;
254         width -= (lastRun.logicalRight - lastRun.logicalLeft);
255         runs.removeLast();
256     }
257 }
258
259 class LineState {
260 public:
261     void setAvailableWidth(float width) { m_availableWidth = width; }
262     void setCollapedWhitespaceWidth(float width) { m_collapsedWhitespaceWidth = width; }
263     void setLogicalLeftOffset(float offset) { m_logicalLeftOffset = offset; }
264     void setOverflowedFragment(const TextFragmentIterator::TextFragment& fragment) { m_overflowedFragment = fragment; }
265
266     float availableWidth() const { return m_availableWidth; }
267     float logicalLeftOffset() const { return m_logicalLeftOffset; }
268     const TextFragmentIterator::TextFragment& overflowedFragment() const { return m_overflowedFragment; }
269     bool hasTrailingWhitespace() const { return m_trailingWhitespaceLength; }
270     TextFragmentIterator::TextFragment lastFragment() const { return m_fragments.last(); }
271     bool isWhitespaceOnly() const { return m_trailingWhitespaceWidth && m_runsWidth == m_trailingWhitespaceWidth; }
272     bool fits(float extra) const { return m_availableWidth >= m_runsWidth + extra; }
273     bool firstCharacterFits() const { return m_firstCharacterFits; }
274     float width() const { return m_runsWidth; }
275     bool isEmpty() const
276     {
277         if (!m_fragments.size())
278             return true;
279         if (!m_lastCompleteFragment.isEmpty())
280             return false;
281         return m_fragments.last().overlapsToNextRenderer();
282     }
283
284     void appendFragmentAndCreateRunIfNeeded(const TextFragmentIterator::TextFragment& fragment, Layout::RunVector& runs)
285     {
286         // Adjust end position while collapsing.
287         unsigned endPosition = fragment.isCollapsed() ? fragment.start() + 1 : fragment.end();
288         // New line needs new run.
289         if (!m_runsWidth)
290             runs.append(Run(fragment.start(), endPosition, m_runsWidth, m_runsWidth + fragment.width(), false));
291         else {
292             const auto& lastFragment = m_fragments.last();
293             // Advance last completed fragment when the previous fragment is all set (including multiple parts across renderers)
294             if ((lastFragment.type() != fragment.type()) || !lastFragment.overlapsToNextRenderer())
295                 m_lastCompleteFragment = lastFragment;
296             // Collapse neighbouring whitespace, if they are across multiple renderers and are not collapsed yet.
297             if (lastFragment.isCollapsible() && fragment.isCollapsible()) {
298                 ASSERT(lastFragment.isLastInRenderer());
299                 if (!lastFragment.isCollapsed()) {
300                     // Line width needs to be reset so that now it takes collapsing into consideration.
301                     m_runsWidth -= (lastFragment.width() - m_collapsedWhitespaceWidth);
302                 }
303                 // This fragment is collapsed completely. No run is needed.
304                 return;
305             }
306             if (lastFragment.isLastInRenderer() || lastFragment.isCollapsed())
307                 runs.append(Run(fragment.start(), endPosition, m_runsWidth, m_runsWidth + fragment.width(), false));
308             else {
309                 Run& lastRun = runs.last();
310                 lastRun.end = endPosition;
311                 lastRun.logicalRight += fragment.width();
312             }
313         }
314         m_fragments.append(fragment);
315         m_runsWidth += fragment.width();
316
317         if (fragment.type() == TextFragmentIterator::TextFragment::Whitespace) {
318             m_trailingWhitespaceLength += endPosition - fragment.start();
319             m_trailingWhitespaceWidth += fragment.width();
320         } else {
321             m_trailingWhitespaceLength = 0;
322             m_trailingWhitespaceWidth = 0;
323         }
324
325         if (!m_firstCharacterFits)
326             m_firstCharacterFits = fragment.start() + 1 > endPosition || m_runsWidth <= m_availableWidth;
327     }
328
329     TextFragmentIterator::TextFragment revertToLastCompleteFragment(Layout::RunVector& runs)
330     {
331         ASSERT(m_fragments.size());
332         unsigned revertLength = 0;
333         float revertWidth = 0;
334         while (m_fragments.size()) {
335             const auto& current = m_fragments.last();
336             if (current == m_lastCompleteFragment)
337                 break;
338             revertLength += current.end() - current.start();
339             revertWidth += current.width();
340             m_fragments.removeLast();
341         }
342         m_runsWidth -= revertWidth;
343         if (revertLength)
344             revertRuns(runs, revertLength, revertWidth);
345         return m_lastCompleteFragment;
346     }
347
348     void removeTrailingWhitespace(Layout::RunVector& runs)
349     {
350         if (!m_trailingWhitespaceLength)
351             return;
352         revertRuns(runs, m_trailingWhitespaceLength, m_trailingWhitespaceWidth);
353         m_runsWidth -= m_trailingWhitespaceWidth;
354         ASSERT(m_fragments.last().type() == TextFragmentIterator::TextFragment::Whitespace);
355         while (m_fragments.size()) {
356             const auto& current = m_fragments.last();
357             if (current.type() != TextFragmentIterator::TextFragment::Whitespace)
358                 break;
359 #if !ASSERT_DISABLED
360             m_trailingWhitespaceLength -= (current.isCollapsed() ? 1 : current.end() - current.start());
361             m_trailingWhitespaceWidth -= current.width();
362 #endif
363             m_fragments.removeLast();
364         }
365 #if !ASSERT_DISABLED
366         ASSERT(!m_trailingWhitespaceLength);
367         ASSERT(!m_trailingWhitespaceWidth);
368 #endif
369         m_trailingWhitespaceLength = 0;
370         m_trailingWhitespaceWidth = 0;
371     }
372
373 private:
374     float m_availableWidth { 0 };
375     float m_logicalLeftOffset { 0 };
376     TextFragmentIterator::TextFragment m_overflowedFragment;
377     float m_runsWidth { 0 };
378     TextFragmentIterator::TextFragment m_lastCompleteFragment;
379     float m_trailingWhitespaceWidth { 0 }; // Use this to remove trailing whitespace without re-mesuring the text.
380     unsigned m_trailingWhitespaceLength { 0 };
381     float m_collapsedWhitespaceWidth { 0 };
382     // Having one character on the line does not necessarily mean it actually fits.
383     // First character of the first fragment might be forced on to the current line even if it does not fit.
384     bool m_firstCharacterFits { false };
385     Vector<TextFragmentIterator::TextFragment> m_fragments;
386 };
387
388 class FragmentForwardIterator : public std::iterator<std::forward_iterator_tag, unsigned> {
389 public:
390     FragmentForwardIterator(unsigned fragmentIndex)
391         : m_fragmentIndex(fragmentIndex)
392     {
393     }
394
395     FragmentForwardIterator& operator++()
396     {
397         ++m_fragmentIndex;
398         return *this;
399     }
400
401     bool operator!=(const FragmentForwardIterator& other) const { return m_fragmentIndex != other.m_fragmentIndex; }
402     unsigned operator*() const { return m_fragmentIndex; }
403
404 private:
405     unsigned m_fragmentIndex { 0 };
406 };
407
408 static FragmentForwardIterator begin(const TextFragmentIterator::TextFragment& fragment)  { return FragmentForwardIterator(fragment.start()); }
409 static FragmentForwardIterator end(const TextFragmentIterator::TextFragment& fragment)  { return FragmentForwardIterator(fragment.end()); }
410
411 static bool preWrap(const TextFragmentIterator::Style& style)
412 {
413     return style.wrapLines && !style.collapseWhitespace;
414 }
415     
416 static void removeTrailingWhitespace(LineState& lineState, Layout::RunVector& runs, const TextFragmentIterator& textFragmentIterator)
417 {
418     if (!lineState.hasTrailingWhitespace())
419         return;
420
421     // Remove collapsed whitespace, or non-collapsed pre-wrap whitespace, unless it's the only content on the line -so removing the whitesapce would produce an empty line.
422     const auto& style = textFragmentIterator.style();
423     bool collapseWhitespace = style.collapseWhitespace | preWrap(style);
424     if (!collapseWhitespace)
425         return;
426
427     if (preWrap(style) && lineState.isWhitespaceOnly())
428         return;
429
430     lineState.removeTrailingWhitespace(runs);
431 }
432
433 static void updateLineConstrains(const RenderBlockFlow& flow, LineState& line)
434 {
435     LayoutUnit height = flow.logicalHeight();
436     LayoutUnit logicalHeight = flow.minLineHeightForReplacedRenderer(false, 0);
437     float logicalRightOffset = flow.logicalRightOffsetForLine(height, false, logicalHeight);
438     line.setLogicalLeftOffset(flow.logicalLeftOffsetForLine(height, false, logicalHeight));
439     line.setAvailableWidth(std::max<float>(0, logicalRightOffset - line.logicalLeftOffset()));
440 }
441
442 static TextFragmentIterator::TextFragment splitFragmentToFitLine(TextFragmentIterator::TextFragment& fragmentToSplit, float availableWidth, bool keepAtLeastOneCharacter, const TextFragmentIterator& textFragmentIterator)
443 {
444     // FIXME: add surrogate pair support.
445     unsigned start = fragmentToSplit.start();
446     auto it = std::upper_bound(begin(fragmentToSplit), end(fragmentToSplit), availableWidth, [&textFragmentIterator, start](float availableWidth, unsigned index) {
447         // FIXME: use the actual left position of the line (instead of 0) to calculated width. It might give false width for tab characters.
448         return availableWidth < textFragmentIterator.textWidth(start, index + 1, 0);
449     });
450     unsigned splitPosition = (*it);
451     if (keepAtLeastOneCharacter && splitPosition == fragmentToSplit.start())
452         ++splitPosition;
453     return fragmentToSplit.split(splitPosition, textFragmentIterator);
454 }
455
456 enum PreWrapLineBreakRule { Preserve, Ignore };
457
458 static TextFragmentIterator::TextFragment consumeLineBreakIfNeeded(const TextFragmentIterator::TextFragment& fragment, TextFragmentIterator& textFragmentIterator, LineState& line, Layout::RunVector& runs,
459     PreWrapLineBreakRule preWrapLineBreakRule = PreWrapLineBreakRule::Preserve)
460 {
461     if (!fragment.isLineBreak())
462         return fragment;
463
464     if (preWrap(textFragmentIterator.style()) && preWrapLineBreakRule != PreWrapLineBreakRule::Ignore)
465         return fragment;
466
467     // <br> always produces a run. (required by testing output)
468     if (fragment.type() == TextFragmentIterator::TextFragment::HardLineBreak)
469         line.appendFragmentAndCreateRunIfNeeded(fragment, runs);
470     return textFragmentIterator.nextTextFragment();
471 }
472
473 static TextFragmentIterator::TextFragment skipWhitespaceIfNeeded(const TextFragmentIterator::TextFragment& fragment, TextFragmentIterator& textFragmentIterator)
474 {
475     if (!textFragmentIterator.style().collapseWhitespace)
476         return fragment;
477
478     TextFragmentIterator::TextFragment firstNonWhitespaceFragment = fragment;
479     while (firstNonWhitespaceFragment.type() == TextFragmentIterator::TextFragment::Whitespace)
480         firstNonWhitespaceFragment = textFragmentIterator.nextTextFragment();
481     return firstNonWhitespaceFragment;
482 }
483
484 static TextFragmentIterator::TextFragment firstFragment(TextFragmentIterator& textFragmentIterator, LineState& currentLine, const LineState& previousLine, Layout::RunVector& runs)
485 {
486     // Handle overflowed fragment from previous line.
487     TextFragmentIterator::TextFragment firstFragment(previousLine.overflowedFragment());
488
489     if (firstFragment.isEmpty())
490         firstFragment = textFragmentIterator.nextTextFragment();
491     else if (firstFragment.type() == TextFragmentIterator::TextFragment::Whitespace && preWrap(textFragmentIterator.style()) && previousLine.firstCharacterFits()) {
492         // Special overflow pre-wrap whitespace handling: skip the overflowed whitespace (even when style says not-collapsible) if we managed to fit at least one character on the previous line.
493         firstFragment = textFragmentIterator.nextTextFragment();
494         // If skipping the whitespace puts us on a newline, skip the newline too as we already wrapped the line.
495         firstFragment = consumeLineBreakIfNeeded(firstFragment, textFragmentIterator, currentLine, runs, PreWrapLineBreakRule::Ignore);
496     }
497     return skipWhitespaceIfNeeded(firstFragment, textFragmentIterator);
498 }
499
500 static void forceFragmentToLine(LineState& line, TextFragmentIterator& textFragmentIterator, Layout::RunVector& runs, const TextFragmentIterator::TextFragment& fragment)
501 {
502     line.appendFragmentAndCreateRunIfNeeded(fragment, runs);
503     // Check if there are more fragments to add to the current line.
504     auto nextFragment = textFragmentIterator.nextTextFragment();
505     if (fragment.overlapsToNextRenderer()) {
506         while (true) {
507             if (nextFragment.type() != fragment.type())
508                 break;
509             line.appendFragmentAndCreateRunIfNeeded(nextFragment, runs);
510             // Does it overlap to the next segment?
511             if (!nextFragment.overlapsToNextRenderer())
512                 return;
513             nextFragment = textFragmentIterator.nextTextFragment();
514         }
515     }
516     // When the forced fragment is followed by either whitespace and/or line break, consume them too, otherwise we end up with an extra whitespace and/or line break.
517     nextFragment = skipWhitespaceIfNeeded(nextFragment, textFragmentIterator);
518     nextFragment = consumeLineBreakIfNeeded(nextFragment, textFragmentIterator, line, runs);
519     line.setOverflowedFragment(nextFragment);
520 }
521
522 static bool createLineRuns(LineState& line, const LineState& previousLine, Layout::RunVector& runs, TextFragmentIterator& textFragmentIterator)
523 {
524     const auto& style = textFragmentIterator.style();
525     line.setCollapedWhitespaceWidth(style.spaceWidth);
526     bool lineCanBeWrapped = style.wrapLines || style.breakWordOnOverflow;
527     auto fragment = firstFragment(textFragmentIterator, line, previousLine, runs);
528     while (fragment.type() != TextFragmentIterator::TextFragment::ContentEnd) {
529         // Hard linebreak.
530         if (fragment.isLineBreak()) {
531             // Add the new line fragment only if there's nothing on the line. (otherwise the extra new line character would show up at the end of the content.)
532             if (line.isEmpty() || fragment.type() == TextFragmentIterator::TextFragment::HardLineBreak) {
533                 if (style.textAlign == RIGHT || style.textAlign == WEBKIT_RIGHT)
534                     line.removeTrailingWhitespace(runs);
535                 line.appendFragmentAndCreateRunIfNeeded(fragment, runs);
536             }
537             break;
538         }
539         if (lineCanBeWrapped && !line.fits(fragment.width())) {
540             // Overflow wrapping behaviour:
541             // 1. Whitesapce collapse on: whitespace is skipped. Jump to next line.
542             // 2. Whitespace collapse off: whitespace is wrapped.
543             // 3. First, non-whitespace fragment is either wrapped or kept on the line. (depends on overflow-wrap)
544             // 4. Non-whitespace fragment when there's already another fragment on the line gets pushed to the next line.
545             bool emptyLine = line.isEmpty();
546             // Whitespace fragment.
547             if (fragment.type() == TextFragmentIterator::TextFragment::Whitespace) {
548                 if (!style.collapseWhitespace) {
549                     // Split the fragment; (modified)fragment stays on this line, overflowedFragment is pushed to next line.
550                     line.setOverflowedFragment(splitFragmentToFitLine(fragment, line.availableWidth() - line.width(), emptyLine, textFragmentIterator));
551                     line.appendFragmentAndCreateRunIfNeeded(fragment, runs);
552                 }
553                 // When whitespace collapse is on, whitespace that doesn't fit is simply skipped.
554                 break;
555             }
556             // Non-whitespace fragment. (!style.wrapLines: bug138102(preserve existing behavior)
557             if ((emptyLine && style.breakWordOnOverflow) || !style.wrapLines) {
558                 // Split the fragment; (modified)fragment stays on this line, overflowedFragment is pushed to next line.
559                 line.setOverflowedFragment(splitFragmentToFitLine(fragment, line.availableWidth() - line.width(), emptyLine, textFragmentIterator));
560                 line.appendFragmentAndCreateRunIfNeeded(fragment, runs);
561                 break;
562             }
563             // Non-breakable non-whitespace first fragment. Add it to the current line. -it overflows though.
564             ASSERT(fragment.type() == TextFragmentIterator::TextFragment::NonWhitespace);
565             if (emptyLine) {
566                 forceFragmentToLine(line, textFragmentIterator, runs, fragment);
567                 break;
568             }
569             // Non-breakable non-whitespace fragment when there's already content on the line. Push it to the next line.
570             if (line.lastFragment().overlapsToNextRenderer()) {
571                 // Check if this fragment is a continuation of a previous segment. In such cases, we need to remove them all.
572                 const auto& lastCompleteFragment = line.revertToLastCompleteFragment(runs);
573                 textFragmentIterator.revertToEndOfFragment(lastCompleteFragment);
574                 break;
575             }
576             line.setOverflowedFragment(fragment);
577             break;
578         }
579         line.appendFragmentAndCreateRunIfNeeded(fragment, runs);
580         // Find the next text fragment.
581         fragment = textFragmentIterator.nextTextFragment(line.width());
582     }
583     return (fragment.type() == TextFragmentIterator::TextFragment::ContentEnd && line.overflowedFragment().isEmpty()) || line.overflowedFragment().type() == TextFragmentIterator::TextFragment::ContentEnd;
584 }
585
586 static void closeLineEndingAndAdjustRuns(LineState& line, Layout::RunVector& runs, unsigned previousRunCount, unsigned& lineCount, const TextFragmentIterator& textFragmentIterator)
587 {
588     if (previousRunCount == runs.size())
589         return;
590     ASSERT(runs.size());
591     removeTrailingWhitespace(line, runs, textFragmentIterator);
592     if (!runs.size())
593         return;
594     // Adjust runs' position by taking line's alignment into account.
595     if (float lineLogicalLeft = computeLineLeft(textFragmentIterator.style().textAlign, line.availableWidth(), line.width(), line.logicalLeftOffset())) {
596         for (unsigned i = previousRunCount; i < runs.size(); ++i) {
597             runs[i].logicalLeft += lineLogicalLeft;
598             runs[i].logicalRight += lineLogicalLeft;
599         }
600     }
601     runs.last().isEndOfLine = true;
602     ++lineCount;
603 }
604
605 static void createTextRuns(Layout::RunVector& runs, RenderBlockFlow& flow, unsigned& lineCount)
606 {
607     LayoutUnit borderAndPaddingBefore = flow.borderAndPaddingBefore();
608     LayoutUnit lineHeight = lineHeightFromFlow(flow);
609     LineState line;
610     bool isEndOfContent = false;
611     TextFragmentIterator textFragmentIterator = TextFragmentIterator(flow);
612
613     do {
614         flow.setLogicalHeight(lineHeight * lineCount + borderAndPaddingBefore);
615         LineState previousLine = line;
616         unsigned previousRunCount = runs.size();
617         line = LineState();
618         updateLineConstrains(flow, line);
619         isEndOfContent = createLineRuns(line, previousLine, runs, textFragmentIterator);
620         closeLineEndingAndAdjustRuns(line, runs, previousRunCount, lineCount, textFragmentIterator);
621     } while (!isEndOfContent);
622 }
623
624 std::unique_ptr<Layout> create(RenderBlockFlow& flow)
625 {
626     unsigned lineCount = 0;
627     Layout::RunVector runs;
628
629     createTextRuns(runs, flow, lineCount);
630     for (auto& renderer : childrenOfType<RenderObject>(flow)) {
631         ASSERT(is<RenderText>(renderer) || is<RenderLineBreak>(renderer));
632         renderer.clearNeedsLayout();
633     }
634     return Layout::create(runs, lineCount);
635 }
636
637 std::unique_ptr<Layout> Layout::create(const RunVector& runVector, unsigned lineCount)
638 {
639     void* slot = WTF::fastMalloc(sizeof(Layout) + sizeof(Run) * runVector.size());
640     return std::unique_ptr<Layout>(new (NotNull, slot) Layout(runVector, lineCount));
641 }
642
643 Layout::Layout(const RunVector& runVector, unsigned lineCount)
644     : m_lineCount(lineCount)
645     , m_runCount(runVector.size())
646 {
647     memcpy(m_runs, runVector.data(), m_runCount * sizeof(Run));
648 }
649
650 }
651 }