5e2ed3041dd473d4dc491b27912a073e41da01bd
[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& flow)
94 {
95     if (!flow.frame().settings().simpleLineLayoutEnabled())
96         return false;
97     if (!flow.firstChild())
98         return false;
99     // This currently covers <blockflow>#text</blockflow>, <blockflow>#text<br></blockflow> and mutiple (sibling) RenderText cases.
100     // The <blockflow><inline>#text</inline></blockflow> case is also popular and should be relatively easy to cover.
101     for (const auto& renderer : childrenOfType<RenderObject>(flow)) {
102         if (is<RenderText>(renderer))
103             continue;
104         if (is<RenderLineBreak>(renderer) && !downcast<RenderLineBreak>(renderer).isWBR() && renderer.style().clear() == CNONE)
105             continue;
106         return false;
107     }
108     if (!flow.isHorizontalWritingMode())
109         return false;
110     if (flow.flowThreadState() != RenderObject::NotInsideFlowThread)
111         return false;
112     // Printing does pagination without a flow thread.
113     if (flow.document().paginated())
114         return false;
115     if (flow.hasOutline())
116         return false;
117     if (flow.isRubyText() || flow.isRubyBase())
118         return false;
119     if (flow.parent()->isDeprecatedFlexibleBox())
120         return false;
121     // FIXME: Implementation of wrap=hard looks into lineboxes.
122     if (flow.parent()->isTextArea() && flow.parent()->element()->fastHasAttribute(HTMLNames::wrapAttr))
123         return false;
124     // FIXME: Placeholders do something strange.
125     if (is<RenderTextControl>(*flow.parent()) && downcast<RenderTextControl>(*flow.parent()).textFormControlElement().placeholderElement())
126         return false;
127     const RenderStyle& style = flow.style();
128     if (style.textDecorationsInEffect() != TextDecorationNone)
129         return false;
130     if (style.textAlign() == JUSTIFY)
131         return false;
132     // Non-visible overflow should be pretty easy to support.
133     if (style.overflowX() != OVISIBLE || style.overflowY() != OVISIBLE)
134         return false;
135     if (!style.textIndent().isZero())
136         return false;
137     if (!style.wordSpacing().isZero() || style.letterSpacing())
138         return false;
139     if (!style.isLeftToRightDirection())
140         return false;
141     if (style.lineBoxContain() != RenderStyle::initialLineBoxContain())
142         return false;
143     if (style.writingMode() != TopToBottomWritingMode)
144         return false;
145     if (style.lineBreak() != LineBreakAuto)
146         return false;
147     if (style.wordBreak() != NormalWordBreak)
148         return false;
149     if (style.unicodeBidi() != UBNormal || style.rtlOrdering() != LogicalOrder)
150         return false;
151     if (style.lineAlign() != LineAlignNone || style.lineSnap() != LineSnapNone)
152         return false;
153     if (style.hyphens() == HyphensAuto)
154         return false;
155     if (style.textEmphasisFill() != TextEmphasisFillFilled || style.textEmphasisMark() != TextEmphasisMarkNone)
156         return false;
157     if (style.textShadow())
158         return false;
159     if (style.textOverflow() || (flow.isAnonymousBlock() && flow.parent()->style().textOverflow()))
160         return false;
161     if (style.hasPseudoStyle(FIRST_LINE) || style.hasPseudoStyle(FIRST_LETTER))
162         return false;
163     else if (flow.isAnonymous() && flow.firstLineBlock())
164         return false;
165     if (style.hasTextCombine())
166         return false;
167     if (style.backgroundClip() == TextFillBox)
168         return false;
169     if (style.borderFit() == BorderFitLines)
170         return false;
171     if (style.lineBreak() != LineBreakAuto)
172         return false;
173 #if ENABLE(CSS_TRAILING_WORD)
174     if (style.trailingWord() != TrailingWord::Auto)
175         return false;
176 #endif
177
178     // 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.
179     if (flow.containsFloats()) {
180         float minimumWidthNeeded = std::numeric_limits<float>::max();
181         for (const auto& textRenderer : childrenOfType<RenderText>(flow)) {
182             minimumWidthNeeded = std::min(minimumWidthNeeded, textRenderer.minLogicalWidth());
183
184             for (auto& floatingObject : *flow.floatingObjectSet()) {
185                 ASSERT(floatingObject);
186 #if ENABLE(CSS_SHAPES)
187                 // if a float has a shape, we cannot tell if content will need to be shifted until after we lay it out,
188                 // since the amount of space is not uniform for the height of the float.
189                 if (floatingObject->renderer().shapeOutsideInfo())
190                     return false;
191 #endif
192                 float availableWidth = flow.availableLogicalWidthForLine(floatingObject->y(), false);
193                 if (availableWidth < minimumWidthNeeded)
194                     return false;
195             }
196         }
197     }
198     if (style.fontCascade().primaryFont().isSVGFont())
199         return false;
200     // We assume that all lines have metrics based purely on the primary font.
201     auto& primaryFont = style.fontCascade().primaryFont();
202     if (primaryFont.isLoading())
203         return false;
204     for (const auto& textRenderer : childrenOfType<RenderText>(flow)) {
205         if (textRenderer.isCombineText() || textRenderer.isCounter() || textRenderer.isQuote() || textRenderer.isTextFragment()
206             || textRenderer.isSVGInlineText())
207             return false;
208         if (style.fontCascade().codePath(TextRun(textRenderer.text())) != FontCascade::Simple)
209             return false;
210         if (!canUseForText(textRenderer, primaryFont))
211             return false;
212     }
213     return true;
214 }
215
216 static float computeLineLeft(ETextAlign textAlign, float availableWidth, float committedWidth, float logicalLeftOffset)
217 {
218     float remainingWidth = availableWidth - committedWidth;
219     float left = logicalLeftOffset;
220     switch (textAlign) {
221     case LEFT:
222     case WEBKIT_LEFT:
223     case TASTART:
224         return left;
225     case RIGHT:
226     case WEBKIT_RIGHT:
227     case TAEND:
228         return left + std::max<float>(remainingWidth, 0);
229     case CENTER:
230     case WEBKIT_CENTER:
231         return left + std::max<float>(remainingWidth / 2, 0);
232     case JUSTIFY:
233         ASSERT_NOT_REACHED();
234         break;
235     }
236     ASSERT_NOT_REACHED();
237     return 0;
238 }
239
240 static void revertRuns(Layout::RunVector& runs, unsigned length, float width)
241 {
242     while (length) {
243         ASSERT(runs.size());
244         Run& lastRun = runs.last();
245         unsigned lastRunLength = lastRun.end - lastRun.start;
246         if (lastRunLength > length) {
247             lastRun.logicalRight -= width;
248             lastRun.end -= length;
249             break;
250         }
251         length -= lastRunLength;
252         width -= (lastRun.logicalRight - lastRun.logicalLeft);
253         runs.removeLast();
254     }
255 }
256
257 class LineState {
258 public:
259     void setAvailableWidth(float width) { m_availableWidth = width; }
260     void setCollapedWhitespaceWidth(float width) { m_collapsedWhitespaceWidth = width; }
261     void setLogicalLeftOffset(float offset) { m_logicalLeftOffset = offset; }
262     void setOverflowedFragment(const TextFragmentIterator::TextFragment& fragment) { m_overflowedFragment = fragment; }
263
264     float availableWidth() const { return m_availableWidth; }
265     float logicalLeftOffset() const { return m_logicalLeftOffset; }
266     const TextFragmentIterator::TextFragment& overflowedFragment() const { return m_overflowedFragment; }
267     bool hasTrailingWhitespace() const { return m_trailingWhitespaceLength; }
268     TextFragmentIterator::TextFragment lastFragment() const { return m_fragments.last(); }
269     bool isWhitespaceOnly() const { return m_trailingWhitespaceWidth && m_runsWidth == m_trailingWhitespaceWidth; }
270     bool fits(float extra) const { return m_availableWidth >= m_runsWidth + extra; }
271     bool firstCharacterFits() const { return m_firstCharacterFits; }
272     float width() const { return m_runsWidth; }
273     bool isEmpty() const
274     {
275         if (!m_fragments.size())
276             return true;
277         if (!m_lastCompleteFragment.isEmpty())
278             return false;
279         return m_fragments.last().overlapsToNextRenderer();
280     }
281
282     void appendFragmentAndCreateRunIfNeeded(const TextFragmentIterator::TextFragment& fragment, Layout::RunVector& runs)
283     {
284         // Adjust end position while collapsing.
285         unsigned endPosition = fragment.isCollapsed() ? fragment.start() + 1 : fragment.end();
286         // New line needs new run.
287         if (!m_runsWidth)
288             runs.append(Run(fragment.start(), endPosition, m_runsWidth, m_runsWidth + fragment.width(), false));
289         else {
290             const auto& lastFragment = m_fragments.last();
291             // Advance last completed fragment when the previous fragment is all set (including multiple parts across renderers)
292             if ((lastFragment.type() != fragment.type()) || !lastFragment.overlapsToNextRenderer())
293                 m_lastCompleteFragment = lastFragment;
294             // Collapse neighbouring whitespace, if they are across multiple renderers and are not collapsed yet.
295             if (lastFragment.isCollapsible() && fragment.isCollapsible()) {
296                 ASSERT(lastFragment.isLastInRenderer());
297                 if (!lastFragment.isCollapsed()) {
298                     // Line width needs to be reset so that now it takes collapsing into consideration.
299                     m_runsWidth -= (lastFragment.width() - m_collapsedWhitespaceWidth);
300                 }
301                 // This fragment is collapsed completely. No run is needed.
302                 return;
303             }
304             if (lastFragment.isLastInRenderer() || lastFragment.isCollapsed())
305                 runs.append(Run(fragment.start(), endPosition, m_runsWidth, m_runsWidth + fragment.width(), false));
306             else {
307                 Run& lastRun = runs.last();
308                 lastRun.end = endPosition;
309                 lastRun.logicalRight += fragment.width();
310             }
311         }
312         m_fragments.append(fragment);
313         m_runsWidth += fragment.width();
314
315         if (fragment.type() == TextFragmentIterator::TextFragment::Whitespace) {
316             m_trailingWhitespaceLength += endPosition - fragment.start();
317             m_trailingWhitespaceWidth += fragment.width();
318         } else {
319             m_trailingWhitespaceLength = 0;
320             m_trailingWhitespaceWidth = 0;
321         }
322
323         if (!m_firstCharacterFits)
324             m_firstCharacterFits = fragment.start() + 1 > endPosition || m_runsWidth <= m_availableWidth;
325     }
326
327     TextFragmentIterator::TextFragment revertToLastCompleteFragment(Layout::RunVector& runs)
328     {
329         ASSERT(m_fragments.size());
330         unsigned revertLength = 0;
331         float revertWidth = 0;
332         while (m_fragments.size()) {
333             const auto& current = m_fragments.last();
334             if (current == m_lastCompleteFragment)
335                 break;
336             revertLength += current.end() - current.start();
337             revertWidth += current.width();
338             m_fragments.removeLast();
339         }
340         m_runsWidth -= revertWidth;
341         if (revertLength)
342             revertRuns(runs, revertLength, revertWidth);
343         return m_lastCompleteFragment;
344     }
345
346     void removeTrailingWhitespace(Layout::RunVector& runs)
347     {
348         if (!m_trailingWhitespaceLength)
349             return;
350         revertRuns(runs, m_trailingWhitespaceLength, m_trailingWhitespaceWidth);
351         m_runsWidth -= m_trailingWhitespaceWidth;
352         ASSERT(m_fragments.last().type() == TextFragmentIterator::TextFragment::Whitespace);
353         while (m_fragments.size()) {
354             const auto& current = m_fragments.last();
355             if (current.type() != TextFragmentIterator::TextFragment::Whitespace)
356                 break;
357 #if !ASSERT_DISABLED
358             m_trailingWhitespaceLength -= (current.isCollapsed() ? 1 : current.end() - current.start());
359             m_trailingWhitespaceWidth -= current.width();
360 #endif
361             m_fragments.removeLast();
362         }
363 #if !ASSERT_DISABLED
364         ASSERT(!m_trailingWhitespaceLength);
365         ASSERT(!m_trailingWhitespaceWidth);
366 #endif
367         m_trailingWhitespaceLength = 0;
368         m_trailingWhitespaceWidth = 0;
369     }
370
371 private:
372     float m_availableWidth { 0 };
373     float m_logicalLeftOffset { 0 };
374     TextFragmentIterator::TextFragment m_overflowedFragment;
375     float m_runsWidth { 0 };
376     TextFragmentIterator::TextFragment m_lastCompleteFragment;
377     float m_trailingWhitespaceWidth { 0 }; // Use this to remove trailing whitespace without re-mesuring the text.
378     unsigned m_trailingWhitespaceLength { 0 };
379     float m_collapsedWhitespaceWidth { 0 };
380     // Having one character on the line does not necessarily mean it actually fits.
381     // First character of the first fragment might be forced on to the current line even if it does not fit.
382     bool m_firstCharacterFits { false };
383     Vector<TextFragmentIterator::TextFragment> m_fragments;
384 };
385
386 class FragmentForwardIterator : public std::iterator<std::forward_iterator_tag, unsigned> {
387 public:
388     FragmentForwardIterator(unsigned fragmentIndex)
389         : m_fragmentIndex(fragmentIndex)
390     {
391     }
392
393     FragmentForwardIterator& operator++()
394     {
395         ++m_fragmentIndex;
396         return *this;
397     }
398
399     bool operator!=(const FragmentForwardIterator& other) const { return m_fragmentIndex != other.m_fragmentIndex; }
400     unsigned operator*() const { return m_fragmentIndex; }
401
402 private:
403     unsigned m_fragmentIndex { 0 };
404 };
405
406 static FragmentForwardIterator begin(const TextFragmentIterator::TextFragment& fragment)  { return FragmentForwardIterator(fragment.start()); }
407 static FragmentForwardIterator end(const TextFragmentIterator::TextFragment& fragment)  { return FragmentForwardIterator(fragment.end()); }
408
409 static bool preWrap(const TextFragmentIterator::Style& style)
410 {
411     return style.wrapLines && !style.collapseWhitespace;
412 }
413     
414 static void removeTrailingWhitespace(LineState& lineState, Layout::RunVector& runs, const TextFragmentIterator& textFragmentIterator)
415 {
416     if (!lineState.hasTrailingWhitespace())
417         return;
418
419     // 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.
420     const auto& style = textFragmentIterator.style();
421     bool collapseWhitespace = style.collapseWhitespace | preWrap(style);
422     if (!collapseWhitespace)
423         return;
424
425     if (preWrap(style) && lineState.isWhitespaceOnly())
426         return;
427
428     lineState.removeTrailingWhitespace(runs);
429 }
430
431 static void updateLineConstrains(const RenderBlockFlow& flow, LineState& line)
432 {
433     LayoutUnit height = flow.logicalHeight();
434     LayoutUnit logicalHeight = flow.minLineHeightForReplacedRenderer(false, 0);
435     float logicalRightOffset = flow.logicalRightOffsetForLine(height, false, logicalHeight);
436     line.setLogicalLeftOffset(flow.logicalLeftOffsetForLine(height, false, logicalHeight));
437     line.setAvailableWidth(std::max<float>(0, logicalRightOffset - line.logicalLeftOffset()));
438 }
439
440 static TextFragmentIterator::TextFragment splitFragmentToFitLine(TextFragmentIterator::TextFragment& fragmentToSplit, float availableWidth, bool keepAtLeastOneCharacter, const TextFragmentIterator& textFragmentIterator)
441 {
442     // FIXME: add surrogate pair support.
443     unsigned start = fragmentToSplit.start();
444     auto it = std::upper_bound(begin(fragmentToSplit), end(fragmentToSplit), availableWidth, [&textFragmentIterator, start](float availableWidth, unsigned index) {
445         // FIXME: use the actual left position of the line (instead of 0) to calculated width. It might give false width for tab characters.
446         return availableWidth < textFragmentIterator.textWidth(start, index + 1, 0);
447     });
448     unsigned splitPosition = (*it);
449     if (keepAtLeastOneCharacter && splitPosition == fragmentToSplit.start())
450         ++splitPosition;
451     return fragmentToSplit.split(splitPosition, textFragmentIterator);
452 }
453
454 enum PreWrapLineBreakRule { Preserve, Ignore };
455
456 static TextFragmentIterator::TextFragment consumeLineBreakIfNeeded(const TextFragmentIterator::TextFragment& fragment, TextFragmentIterator& textFragmentIterator, LineState& line, Layout::RunVector& runs,
457     PreWrapLineBreakRule preWrapLineBreakRule = PreWrapLineBreakRule::Preserve)
458 {
459     if (!fragment.isLineBreak())
460         return fragment;
461
462     if (preWrap(textFragmentIterator.style()) && preWrapLineBreakRule != PreWrapLineBreakRule::Ignore)
463         return fragment;
464
465     // <br> always produces a run. (required by testing output)
466     if (fragment.type() == TextFragmentIterator::TextFragment::HardLineBreak)
467         line.appendFragmentAndCreateRunIfNeeded(fragment, runs);
468     return textFragmentIterator.nextTextFragment();
469 }
470
471 static TextFragmentIterator::TextFragment skipWhitespaceIfNeeded(const TextFragmentIterator::TextFragment& fragment, TextFragmentIterator& textFragmentIterator)
472 {
473     if (!textFragmentIterator.style().collapseWhitespace)
474         return fragment;
475
476     TextFragmentIterator::TextFragment firstNonWhitespaceFragment = fragment;
477     while (firstNonWhitespaceFragment.type() == TextFragmentIterator::TextFragment::Whitespace)
478         firstNonWhitespaceFragment = textFragmentIterator.nextTextFragment();
479     return firstNonWhitespaceFragment;
480 }
481
482 static TextFragmentIterator::TextFragment firstFragment(TextFragmentIterator& textFragmentIterator, LineState& currentLine, const LineState& previousLine, Layout::RunVector& runs)
483 {
484     // Handle overflowed fragment from previous line.
485     TextFragmentIterator::TextFragment firstFragment(previousLine.overflowedFragment());
486
487     if (firstFragment.isEmpty())
488         firstFragment = textFragmentIterator.nextTextFragment();
489     else if (firstFragment.type() == TextFragmentIterator::TextFragment::Whitespace && preWrap(textFragmentIterator.style()) && previousLine.firstCharacterFits()) {
490         // 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.
491         firstFragment = textFragmentIterator.nextTextFragment();
492         // If skipping the whitespace puts us on a newline, skip the newline too as we already wrapped the line.
493         firstFragment = consumeLineBreakIfNeeded(firstFragment, textFragmentIterator, currentLine, runs, PreWrapLineBreakRule::Ignore);
494     }
495     return skipWhitespaceIfNeeded(firstFragment, textFragmentIterator);
496 }
497
498 static void forceFragmentToLine(LineState& line, TextFragmentIterator& textFragmentIterator, Layout::RunVector& runs, const TextFragmentIterator::TextFragment& fragment)
499 {
500     line.appendFragmentAndCreateRunIfNeeded(fragment, runs);
501     // Check if there are more fragments to add to the current line.
502     auto nextFragment = textFragmentIterator.nextTextFragment();
503     if (fragment.overlapsToNextRenderer()) {
504         while (true) {
505             if (nextFragment.type() != fragment.type())
506                 break;
507             line.appendFragmentAndCreateRunIfNeeded(nextFragment, runs);
508             // Does it overlap to the next segment?
509             if (!nextFragment.overlapsToNextRenderer())
510                 return;
511             nextFragment = textFragmentIterator.nextTextFragment();
512         }
513     }
514     // 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.
515     nextFragment = skipWhitespaceIfNeeded(nextFragment, textFragmentIterator);
516     nextFragment = consumeLineBreakIfNeeded(nextFragment, textFragmentIterator, line, runs);
517     line.setOverflowedFragment(nextFragment);
518 }
519
520 static bool createLineRuns(LineState& line, const LineState& previousLine, Layout::RunVector& runs, TextFragmentIterator& textFragmentIterator)
521 {
522     const auto& style = textFragmentIterator.style();
523     line.setCollapedWhitespaceWidth(style.spaceWidth);
524     bool lineCanBeWrapped = style.wrapLines || style.breakWordOnOverflow;
525     auto fragment = firstFragment(textFragmentIterator, line, previousLine, runs);
526     while (fragment.type() != TextFragmentIterator::TextFragment::ContentEnd) {
527         // Hard linebreak.
528         if (fragment.isLineBreak()) {
529             // 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.)
530             if (line.isEmpty() || fragment.type() == TextFragmentIterator::TextFragment::HardLineBreak) {
531                 if (style.textAlign == RIGHT || style.textAlign == WEBKIT_RIGHT)
532                     line.removeTrailingWhitespace(runs);
533                 line.appendFragmentAndCreateRunIfNeeded(fragment, runs);
534             }
535             break;
536         }
537         if (lineCanBeWrapped && !line.fits(fragment.width())) {
538             // Overflow wrapping behaviour:
539             // 1. Whitesapce collapse on: whitespace is skipped. Jump to next line.
540             // 2. Whitespace collapse off: whitespace is wrapped.
541             // 3. First, non-whitespace fragment is either wrapped or kept on the line. (depends on overflow-wrap)
542             // 4. Non-whitespace fragment when there's already another fragment on the line gets pushed to the next line.
543             bool emptyLine = line.isEmpty();
544             // Whitespace fragment.
545             if (fragment.type() == TextFragmentIterator::TextFragment::Whitespace) {
546                 if (!style.collapseWhitespace) {
547                     // Split the fragment; (modified)fragment stays on this line, overflowedFragment is pushed to next line.
548                     line.setOverflowedFragment(splitFragmentToFitLine(fragment, line.availableWidth() - line.width(), emptyLine, textFragmentIterator));
549                     line.appendFragmentAndCreateRunIfNeeded(fragment, runs);
550                 }
551                 // When whitespace collapse is on, whitespace that doesn't fit is simply skipped.
552                 break;
553             }
554             // Non-whitespace fragment. (!style.wrapLines: bug138102(preserve existing behavior)
555             if ((emptyLine && style.breakWordOnOverflow) || !style.wrapLines) {
556                 // Split the fragment; (modified)fragment stays on this line, overflowedFragment is pushed to next line.
557                 line.setOverflowedFragment(splitFragmentToFitLine(fragment, line.availableWidth() - line.width(), emptyLine, textFragmentIterator));
558                 line.appendFragmentAndCreateRunIfNeeded(fragment, runs);
559                 break;
560             }
561             // Non-breakable non-whitespace first fragment. Add it to the current line. -it overflows though.
562             ASSERT(fragment.type() == TextFragmentIterator::TextFragment::NonWhitespace);
563             if (emptyLine) {
564                 forceFragmentToLine(line, textFragmentIterator, runs, fragment);
565                 break;
566             }
567             // Non-breakable non-whitespace fragment when there's already content on the line. Push it to the next line.
568             if (line.lastFragment().overlapsToNextRenderer()) {
569                 // Check if this fragment is a continuation of a previous segment. In such cases, we need to remove them all.
570                 const auto& lastCompleteFragment = line.revertToLastCompleteFragment(runs);
571                 textFragmentIterator.revertToEndOfFragment(lastCompleteFragment);
572                 break;
573             }
574             line.setOverflowedFragment(fragment);
575             break;
576         }
577         line.appendFragmentAndCreateRunIfNeeded(fragment, runs);
578         // Find the next text fragment.
579         fragment = textFragmentIterator.nextTextFragment(line.width());
580     }
581     return (fragment.type() == TextFragmentIterator::TextFragment::ContentEnd && line.overflowedFragment().isEmpty()) || line.overflowedFragment().type() == TextFragmentIterator::TextFragment::ContentEnd;
582 }
583
584 static void closeLineEndingAndAdjustRuns(LineState& line, Layout::RunVector& runs, unsigned previousRunCount, unsigned& lineCount, const TextFragmentIterator& textFragmentIterator)
585 {
586     if (previousRunCount == runs.size())
587         return;
588     ASSERT(runs.size());
589     removeTrailingWhitespace(line, runs, textFragmentIterator);
590     if (!runs.size())
591         return;
592     // Adjust runs' position by taking line's alignment into account.
593     if (float lineLogicalLeft = computeLineLeft(textFragmentIterator.style().textAlign, line.availableWidth(), line.width(), line.logicalLeftOffset())) {
594         for (unsigned i = previousRunCount; i < runs.size(); ++i) {
595             runs[i].logicalLeft += lineLogicalLeft;
596             runs[i].logicalRight += lineLogicalLeft;
597         }
598     }
599     runs.last().isEndOfLine = true;
600     ++lineCount;
601 }
602
603 static void createTextRuns(Layout::RunVector& runs, RenderBlockFlow& flow, unsigned& lineCount)
604 {
605     LayoutUnit borderAndPaddingBefore = flow.borderAndPaddingBefore();
606     LayoutUnit lineHeight = lineHeightFromFlow(flow);
607     LineState line;
608     bool isEndOfContent = false;
609     TextFragmentIterator textFragmentIterator = TextFragmentIterator(flow);
610
611     do {
612         flow.setLogicalHeight(lineHeight * lineCount + borderAndPaddingBefore);
613         LineState previousLine = line;
614         unsigned previousRunCount = runs.size();
615         line = LineState();
616         updateLineConstrains(flow, line);
617         isEndOfContent = createLineRuns(line, previousLine, runs, textFragmentIterator);
618         closeLineEndingAndAdjustRuns(line, runs, previousRunCount, lineCount, textFragmentIterator);
619     } while (!isEndOfContent);
620 }
621
622 std::unique_ptr<Layout> create(RenderBlockFlow& flow)
623 {
624     unsigned lineCount = 0;
625     Layout::RunVector runs;
626
627     createTextRuns(runs, flow, lineCount);
628     for (auto& renderer : childrenOfType<RenderObject>(flow)) {
629         ASSERT(is<RenderText>(renderer) || is<RenderLineBreak>(renderer));
630         renderer.clearNeedsLayout();
631     }
632     return Layout::create(runs, lineCount);
633 }
634
635 std::unique_ptr<Layout> Layout::create(const RunVector& runVector, unsigned lineCount)
636 {
637     void* slot = WTF::fastMalloc(sizeof(Layout) + sizeof(Run) * runVector.size());
638     return std::unique_ptr<Layout>(new (NotNull, slot) Layout(runVector, lineCount));
639 }
640
641 Layout::Layout(const RunVector& runVector, unsigned lineCount)
642     : m_lineCount(lineCount)
643     , m_runCount(runVector.size())
644 {
645     memcpy(m_runs, runVector.data(), m_runCount * sizeof(Run));
646 }
647
648 }
649 }