Use LineLayoutTraversal for RenderText functions
[WebKit-https.git] / Source / WebCore / rendering / RenderText.cpp
1 /*
2  * (C) 1999 Lars Knoll (knoll@kde.org)
3  * (C) 2000 Dirk Mueller (mueller@kde.org)
4  * Copyright (C) 2004-2019 Apple Inc. All rights reserved.
5  * Copyright (C) 2006 Andrew Wellington (proton@wiretapped.net)
6  * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com)
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public License
19  * along with this library; see the file COPYING.LIB.  If not, write to
20  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22  *
23  */
24
25 #include "config.h"
26 #include "RenderText.h"
27
28 #include "AXObjectCache.h"
29 #include "BreakLines.h"
30 #include "BreakingContext.h"
31 #include "CharacterProperties.h"
32 #include "DocumentMarkerController.h"
33 #include "EllipsisBox.h"
34 #include "FloatQuad.h"
35 #include "Frame.h"
36 #include "FrameView.h"
37 #include "HTMLParserIdioms.h"
38 #include "Hyphenation.h"
39 #include "InlineTextBox.h"
40 #include "LineLayoutTraversal.h"
41 #include "Range.h"
42 #include "RenderBlock.h"
43 #include "RenderCombineText.h"
44 #include "RenderInline.h"
45 #include "RenderLayer.h"
46 #include "RenderView.h"
47 #include "RenderedDocumentMarker.h"
48 #include "Settings.h"
49 #include "SimpleLineLayoutFunctions.h"
50 #include "Text.h"
51 #include "TextResourceDecoder.h"
52 #include "VisiblePosition.h"
53 #include <wtf/IsoMallocInlines.h>
54 #include <wtf/NeverDestroyed.h>
55 #include <wtf/text/StringBuilder.h>
56 #include <wtf/text/TextBreakIterator.h>
57 #include <wtf/unicode/CharacterNames.h>
58
59 #if PLATFORM(IOS_FAMILY)
60 #include "Document.h"
61 #include "EditorClient.h"
62 #include "LogicalSelectionOffsetCaches.h"
63 #include "Page.h"
64 #include "SelectionRect.h"
65 #endif
66
67 namespace WebCore {
68
69 using namespace WTF::Unicode;
70
71 WTF_MAKE_ISO_ALLOCATED_IMPL(RenderText);
72
73 struct SameSizeAsRenderText : public RenderObject {
74     void* pointers[2];
75     uint32_t bitfields : 16;
76 #if ENABLE(TEXT_AUTOSIZING)
77     float candidateTextSize;
78 #endif
79     float widths[4];
80     String text;
81 };
82
83 COMPILE_ASSERT(sizeof(RenderText) == sizeof(SameSizeAsRenderText), RenderText_should_stay_small);
84
85 class SecureTextTimer final : private TimerBase {
86     WTF_MAKE_FAST_ALLOCATED;
87 public:
88     explicit SecureTextTimer(RenderText&);
89     void restart(unsigned offsetAfterLastTypedCharacter);
90
91     unsigned takeOffsetAfterLastTypedCharacter();
92
93 private:
94     void fired() override;
95     RenderText& m_renderer;
96     unsigned m_offsetAfterLastTypedCharacter { 0 };
97 };
98
99 typedef HashMap<RenderText*, std::unique_ptr<SecureTextTimer>> SecureTextTimerMap;
100
101 static SecureTextTimerMap& secureTextTimers()
102 {
103     static NeverDestroyed<SecureTextTimerMap> map;
104     return map.get();
105 }
106
107 inline SecureTextTimer::SecureTextTimer(RenderText& renderer)
108     : m_renderer(renderer)
109 {
110 }
111
112 inline void SecureTextTimer::restart(unsigned offsetAfterLastTypedCharacter)
113 {
114     m_offsetAfterLastTypedCharacter = offsetAfterLastTypedCharacter;
115     startOneShot(1_s * m_renderer.settings().passwordEchoDurationInSeconds());
116 }
117
118 inline unsigned SecureTextTimer::takeOffsetAfterLastTypedCharacter()
119 {
120     unsigned offset = m_offsetAfterLastTypedCharacter;
121     m_offsetAfterLastTypedCharacter = 0;
122     return offset;
123 }
124
125 void SecureTextTimer::fired()
126 {
127     ASSERT(secureTextTimers().get(&m_renderer) == this);
128     m_offsetAfterLastTypedCharacter = 0;
129     m_renderer.setText(m_renderer.text(), true /* forcing setting text as it may be masked later */);
130 }
131
132 static HashMap<const RenderText*, String>& originalTextMap()
133 {
134     static NeverDestroyed<HashMap<const RenderText*, String>> map;
135     return map;
136 }
137
138 static HashMap<const RenderText*, WeakPtr<RenderInline>>& inlineWrapperForDisplayContentsMap()
139 {
140     static NeverDestroyed<HashMap<const RenderText*, WeakPtr<RenderInline>>> map;
141     return map;
142 }
143
144 static constexpr UChar convertNoBreakSpaceToSpace(UChar character)
145 {
146     return character == noBreakSpace ? ' ' : character;
147 }
148
149 String capitalize(const String& string, UChar previousCharacter)
150 {
151     // FIXME: Change this to use u_strToTitle instead of u_totitle and to consider locale.
152
153     unsigned length = string.length();
154     auto& stringImpl = *string.impl();
155
156     static_assert(String::MaxLength < std::numeric_limits<unsigned>::max(), "Must be able to add one without overflowing unsigned");
157
158     // Replace NO BREAK SPACE with a normal spaces since ICU does not treat it as a word separator.
159     Vector<UChar> stringWithPrevious(length + 1);
160     stringWithPrevious[0] = convertNoBreakSpaceToSpace(previousCharacter);
161     for (unsigned i = 1; i < length + 1; i++)
162         stringWithPrevious[i] = convertNoBreakSpaceToSpace(stringImpl[i - 1]);
163
164     auto* breakIterator = wordBreakIterator(StringView { stringWithPrevious.data(), length + 1 });
165     if (!breakIterator)
166         return string;
167
168     StringBuilder result;
169     result.reserveCapacity(length);
170
171     int32_t startOfWord = ubrk_first(breakIterator);
172     int32_t endOfWord;
173     for (endOfWord = ubrk_next(breakIterator); endOfWord != UBRK_DONE; startOfWord = endOfWord, endOfWord = ubrk_next(breakIterator)) {
174         if (startOfWord) // Do not append the first character, since it's the previous character, not from this string.
175             result.appendCharacter(u_totitle(stringImpl[startOfWord - 1]));
176         for (int i = startOfWord + 1; i < endOfWord; i++)
177             result.append(stringImpl[i - 1]);
178     }
179
180     return result == string ? string : result.toString();
181 }
182
183 inline RenderText::RenderText(Node& node, const String& text)
184     : RenderObject(node)
185     , m_hasTab(false)
186     , m_linesDirty(false)
187     , m_containsReversedText(false)
188     , m_isAllASCII(text.impl()->isAllASCII())
189     , m_knownToHaveNoOverflowAndNoFallbackFonts(false)
190     , m_useBackslashAsYenSymbol(false)
191     , m_originalTextDiffersFromRendered(false)
192     , m_hasInlineWrapperForDisplayContents(false)
193     , m_text(text)
194 {
195     ASSERT(!m_text.isNull());
196     setIsText();
197     m_canUseSimpleFontCodePath = computeCanUseSimpleFontCodePath();
198
199     // FIXME: Find out how to increment the visually non empty character count when the font becomes available.
200     auto isTextVisible = false;
201     if (auto* parentElement = node.parentElement()) {
202         auto* style = parentElement->renderer() ? &parentElement->renderer()->style() : nullptr;
203         isTextVisible = style && style->visibility() == Visibility::Visible && !style->fontCascade().isLoadingCustomFonts();
204     }
205
206     if (isTextVisible)
207         view().frameView().incrementVisuallyNonEmptyCharacterCount(text);
208 }
209
210 RenderText::RenderText(Text& textNode, const String& text)
211     : RenderText(static_cast<Node&>(textNode), text)
212 {
213 }
214
215 RenderText::RenderText(Document& document, const String& text)
216     : RenderText(static_cast<Node&>(document), text)
217 {
218 }
219
220 RenderText::~RenderText()
221 {
222     // Do not add any code here. Add it to willBeDestroyed() instead.
223     ASSERT(!originalTextMap().contains(this));
224 }
225
226 const char* RenderText::renderName() const
227 {
228     return "RenderText";
229 }
230
231 Text* RenderText::textNode() const
232 {
233     return downcast<Text>(RenderObject::node());
234 }
235
236 bool RenderText::isTextFragment() const
237 {
238     return false;
239 }
240
241 bool RenderText::computeUseBackslashAsYenSymbol() const
242 {
243     const RenderStyle& style = this->style();
244     const auto& fontDescription = style.fontDescription();
245     if (style.fontCascade().useBackslashAsYenSymbol())
246         return true;
247     if (fontDescription.isSpecifiedFont())
248         return false;
249     const TextEncoding* encoding = document().decoder() ? &document().decoder()->encoding() : 0;
250     if (encoding && encoding->backslashAsCurrencySymbol() != '\\')
251         return true;
252     return false;
253 }
254
255 void RenderText::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
256 {
257     // There is no need to ever schedule repaints from a style change of a text run, since
258     // we already did this for the parent of the text run.
259     // We do have to schedule layouts, though, since a style change can force us to
260     // need to relayout.
261     if (diff == StyleDifference::Layout) {
262         setNeedsLayoutAndPrefWidthsRecalc();
263         m_knownToHaveNoOverflowAndNoFallbackFonts = false;
264     }
265
266     const RenderStyle& newStyle = style();
267     bool needsResetText = false;
268     if (!oldStyle) {
269         m_useBackslashAsYenSymbol = computeUseBackslashAsYenSymbol();
270         needsResetText = m_useBackslashAsYenSymbol;
271     } else if (oldStyle->fontCascade().useBackslashAsYenSymbol() != newStyle.fontCascade().useBackslashAsYenSymbol()) {
272         m_useBackslashAsYenSymbol = computeUseBackslashAsYenSymbol();
273         needsResetText = true;
274     }
275
276     if (!oldStyle || oldStyle->fontCascade() != newStyle.fontCascade())
277         m_canUseSimplifiedTextMeasuring = computeCanUseSimplifiedTextMeasuring();
278
279     TextTransform oldTransform = oldStyle ? oldStyle->textTransform() : TextTransform::None;
280     TextSecurity oldSecurity = oldStyle ? oldStyle->textSecurity() : TextSecurity::None;
281     if (needsResetText || oldTransform != newStyle.textTransform() || oldSecurity != newStyle.textSecurity())
282         RenderText::setText(originalText(), true);
283 }
284
285 void RenderText::removeAndDestroyTextBoxes()
286 {
287     if (!renderTreeBeingDestroyed())
288         m_lineBoxes.removeAllFromParent(*this);
289 #if !ASSERT_WITH_SECURITY_IMPLICATION_DISABLED
290     else
291         m_lineBoxes.invalidateParentChildLists();
292 #endif
293     m_lineBoxes.deleteAll();
294 }
295
296 void RenderText::willBeDestroyed()
297 {
298     secureTextTimers().remove(this);
299
300     removeAndDestroyTextBoxes();
301
302     if (m_originalTextDiffersFromRendered)
303         originalTextMap().remove(this);
304
305     setInlineWrapperForDisplayContents(nullptr);
306
307     RenderObject::willBeDestroyed();
308 }
309
310 void RenderText::deleteLineBoxesBeforeSimpleLineLayout()
311 {
312     m_lineBoxes.deleteAll();
313 }
314
315 String RenderText::originalText() const
316 {
317     return m_originalTextDiffersFromRendered ? originalTextMap().get(this) : m_text;
318 }
319
320 void RenderText::absoluteRects(Vector<IntRect>& rects, const LayoutPoint& accumulatedOffset) const
321 {
322     for (auto& box : LineLayoutTraversal::textBoxesFor(*this)) {
323         auto rect = box.rect();
324         rects.append(enclosingIntRect(FloatRect(accumulatedOffset + rect.location(), rect.size())));
325     }
326 }
327
328 Vector<IntRect> RenderText::absoluteRectsForRange(unsigned start, unsigned end, bool useSelectionHeight, bool* wasFixed) const
329 {
330     const_cast<RenderText&>(*this).ensureLineBoxes();
331
332     // Work around signed/unsigned issues. This function takes unsigneds, and is often passed UINT_MAX
333     // to mean "all the way to the end". InlineTextBox coordinates are unsigneds, so changing this 
334     // function to take ints causes various internal mismatches. But selectionRect takes ints, and 
335     // passing UINT_MAX to it causes trouble. Ideally we'd change selectionRect to take unsigneds, but 
336     // that would cause many ripple effects, so for now we'll just clamp our unsigned parameters to INT_MAX.
337     ASSERT(end == UINT_MAX || end <= INT_MAX);
338     ASSERT(start <= INT_MAX);
339     start = std::min(start, static_cast<unsigned>(INT_MAX));
340     end = std::min(end, static_cast<unsigned>(INT_MAX));
341     
342     return m_lineBoxes.absoluteRectsForRange(*this, start, end, useSelectionHeight, wasFixed);
343 }
344
345 #if PLATFORM(IOS_FAMILY)
346 // This function is similar in spirit to addLineBoxRects, but returns rectangles
347 // which are annotated with additional state which helps the iPhone draw selections in its unique way.
348 // Full annotations are added in this class.
349 void RenderText::collectSelectionRects(Vector<SelectionRect>& rects, unsigned start, unsigned end)
350 {
351     // FIXME: Work around signed/unsigned issues. This function takes unsigneds, and is often passed UINT_MAX
352     // to mean "all the way to the end". InlineTextBox coordinates are unsigneds, so changing this 
353     // function to take ints causes various internal mismatches. But selectionRect takes ints, and 
354     // passing UINT_MAX to it causes trouble. Ideally we'd change selectionRect to take unsigneds, but 
355     // that would cause many ripple effects, so for now we'll just clamp our unsigned parameters to INT_MAX.
356     ASSERT(end == std::numeric_limits<unsigned>::max() || end <= std::numeric_limits<int>::max());
357     ASSERT(start <= std::numeric_limits<int>::max());
358     start = std::min(start, static_cast<unsigned>(std::numeric_limits<int>::max()));
359     end = std::min(end, static_cast<unsigned>(std::numeric_limits<int>::max()));
360
361     for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) {
362         LayoutRect rect;
363         if (start <= box->start() && box->end() <= end)
364             rect = box->localSelectionRect(start, end);
365         else {
366             unsigned realEnd = std::min(box->end(), end);
367             rect = box->localSelectionRect(start, realEnd);
368             if (rect.isEmpty())
369                 continue;
370         }
371
372         if (box->root().isFirstAfterPageBreak()) {
373             if (box->isHorizontal())
374                 rect.shiftYEdgeTo(box->root().lineTopWithLeading());
375             else
376                 rect.shiftXEdgeTo(box->root().lineTopWithLeading());
377         }
378
379         RenderBlock* containingBlock = this->containingBlock();
380         // Map rect, extended left to leftOffset, and right to rightOffset, through transforms to get minX and maxX.
381         LogicalSelectionOffsetCaches cache(*containingBlock);
382         LayoutUnit leftOffset = containingBlock->logicalLeftSelectionOffset(*containingBlock, LayoutUnit(box->logicalTop()), cache);
383         LayoutUnit rightOffset = containingBlock->logicalRightSelectionOffset(*containingBlock, LayoutUnit(box->logicalTop()), cache);
384         LayoutRect extentsRect = rect;
385         if (box->isHorizontal()) {
386             extentsRect.setX(leftOffset);
387             extentsRect.setWidth(rightOffset - leftOffset);
388         } else {
389             extentsRect.setY(leftOffset);
390             extentsRect.setHeight(rightOffset - leftOffset);
391         }
392         extentsRect = localToAbsoluteQuad(FloatRect(extentsRect)).enclosingBoundingBox();
393         if (!box->isHorizontal())
394             extentsRect = extentsRect.transposedRect();
395         bool isFirstOnLine = !box->previousOnLineExists();
396         bool isLastOnLine = !box->nextOnLineExists();
397         if (containingBlock->isRubyBase() || containingBlock->isRubyText())
398             isLastOnLine = !containingBlock->containingBlock()->inlineBoxWrapper()->nextOnLineExists();
399
400         bool containsStart = box->start() <= start && box->end() >= start;
401         bool containsEnd = box->start() <= end && box->end() >= end;
402
403         bool isFixed = false;
404         IntRect absRect = localToAbsoluteQuad(FloatRect(rect), UseTransforms, &isFixed).enclosingBoundingBox();
405         bool boxIsHorizontal = !box->isSVGInlineTextBox() ? box->isHorizontal() : !style().isVerticalWritingMode();
406         // If the containing block is an inline element, we want to check the inlineBoxWrapper orientation
407         // to determine the orientation of the block. In this case we also use the inlineBoxWrapper to
408         // determine if the element is the last on the line.
409         if (containingBlock->inlineBoxWrapper()) {
410             if (containingBlock->inlineBoxWrapper()->isHorizontal() != boxIsHorizontal) {
411                 boxIsHorizontal = containingBlock->inlineBoxWrapper()->isHorizontal();
412                 isLastOnLine = !containingBlock->inlineBoxWrapper()->nextOnLineExists();
413             }
414         }
415
416         rects.append(SelectionRect(absRect, box->direction(), extentsRect.x(), extentsRect.maxX(), extentsRect.maxY(), 0, box->isLineBreak(), isFirstOnLine, isLastOnLine, containsStart, containsEnd, boxIsHorizontal, isFixed, containingBlock->isRubyText(), view().pageNumberForBlockProgressionOffset(absRect.x())));
417     }
418 }
419 #endif
420
421 Vector<FloatQuad> RenderText::absoluteQuadsClippedToEllipsis() const
422 {
423     if (auto* layout = simpleLineLayout()) {
424         ASSERT(style().textOverflow() != TextOverflow::Ellipsis);
425         return SimpleLineLayout::collectAbsoluteQuads(*this, *layout, nullptr);
426     }
427     return m_lineBoxes.absoluteQuads(*this, nullptr, RenderTextLineBoxes::ClipToEllipsis);
428 }
429
430 void RenderText::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed) const
431 {
432     if (auto* layout = simpleLineLayout()) {
433         quads.appendVector(SimpleLineLayout::collectAbsoluteQuads(*this, *layout, wasFixed));
434         return;
435     }
436     quads.appendVector(m_lineBoxes.absoluteQuads(*this, wasFixed, RenderTextLineBoxes::NoClipping));
437 }
438
439 Vector<FloatQuad> RenderText::absoluteQuadsForRange(unsigned start, unsigned end, bool useSelectionHeight, bool* wasFixed) const
440 {
441     // Work around signed/unsigned issues. This function takes unsigneds, and is often passed UINT_MAX
442     // to mean "all the way to the end". InlineTextBox coordinates are unsigneds, so changing this
443     // function to take ints causes various internal mismatches. But selectionRect takes ints, and
444     // passing UINT_MAX to it causes trouble. Ideally we'd change selectionRect to take unsigneds, but
445     // that would cause many ripple effects, so for now we'll just clamp our unsigned parameters to INT_MAX.
446     ASSERT(end == UINT_MAX || end <= INT_MAX);
447     ASSERT(start <= INT_MAX);
448     start = std::min(start, static_cast<unsigned>(INT_MAX));
449     end = std::min(end, static_cast<unsigned>(INT_MAX));
450     if (simpleLineLayout() && !useSelectionHeight)
451         return collectAbsoluteQuadsForRange(*this, start, end, *simpleLineLayout(), wasFixed);
452     const_cast<RenderText&>(*this).ensureLineBoxes();
453     return m_lineBoxes.absoluteQuadsForRange(*this, start, end, useSelectionHeight, wasFixed);
454 }
455
456 Position RenderText::positionForPoint(const LayoutPoint& point)
457 {
458     if (simpleLineLayout() && parent()->firstChild() == parent()->lastChild()) {
459         auto offset = SimpleLineLayout::textOffsetForPoint(point, *this, *simpleLineLayout());
460         // Did not find a valid offset. Fall back to the normal line layout based Position.
461         if (offset == text().length())
462             return positionForPoint(point, nullptr).deepEquivalent();
463         auto position = Position(textNode(), offset);
464         ASSERT(position == positionForPoint(point, nullptr).deepEquivalent());
465         return position;
466     }
467     return positionForPoint(point, nullptr).deepEquivalent();
468 }
469
470 VisiblePosition RenderText::positionForPoint(const LayoutPoint& point, const RenderFragmentContainer*)
471 {
472     ensureLineBoxes();
473     return m_lineBoxes.positionForPoint(*this, point);
474 }
475
476 LayoutRect RenderText::localCaretRect(InlineBox* inlineBox, unsigned caretOffset, LayoutUnit* extraWidthToEndOfLine)
477 {
478     if (!inlineBox)
479         return LayoutRect();
480
481     auto& box = downcast<InlineTextBox>(*inlineBox);
482     float left = box.positionForOffset(caretOffset);
483     return box.root().computeCaretRect(left, caretWidth, extraWidthToEndOfLine);
484 }
485
486 ALWAYS_INLINE float RenderText::widthFromCache(const FontCascade& f, unsigned start, unsigned len, float xPos, HashSet<const Font*>* fallbackFonts, GlyphOverflow* glyphOverflow, const RenderStyle& style) const
487 {
488     if (style.hasTextCombine() && is<RenderCombineText>(*this)) {
489         const RenderCombineText& combineText = downcast<RenderCombineText>(*this);
490         if (combineText.isCombined())
491             return combineText.combinedTextWidth(f);
492     }
493
494     if (f.isFixedPitch() && f.fontDescription().variantSettings().isAllNormal() && m_isAllASCII && (!glyphOverflow || !glyphOverflow->computeBounds)) {
495         float monospaceCharacterWidth = f.spaceWidth();
496         float w = 0;
497         bool isSpace;
498         for (unsigned i = start; i < start + len; i++) {
499             char c = text()[i];
500             if (c <= ' ') {
501                 if (c == ' ' || c == '\n') {
502                     w += monospaceCharacterWidth;
503                     isSpace = true;
504                 } else if (c == '\t') {
505                     if (style.collapseWhiteSpace()) {
506                         w += monospaceCharacterWidth;
507                         isSpace = true;
508                     } else {
509                         w += f.tabWidth(style.tabSize(), xPos + w);
510                         isSpace = false;
511                     }
512                 } else
513                     isSpace = false;
514             } else {
515                 w += monospaceCharacterWidth;
516                 isSpace = false;
517             }
518             if (isSpace && i > start)
519                 w += f.wordSpacing();
520         }
521         return w;
522     }
523
524     TextRun run = RenderBlock::constructTextRun(*this, start, len, style);
525     run.setCharacterScanForCodePath(!canUseSimpleFontCodePath());
526     run.setTabSize(!style.collapseWhiteSpace(), style.tabSize());
527     run.setXPos(xPos);
528     return f.width(run, fallbackFonts, glyphOverflow);
529 }
530
531 inline bool isHangablePunctuationAtLineStart(UChar c)
532 {
533     return U_GET_GC_MASK(c) & (U_GC_PS_MASK | U_GC_PI_MASK | U_GC_PF_MASK);
534 }
535
536 inline bool isHangablePunctuationAtLineEnd(UChar c)
537 {
538     return U_GET_GC_MASK(c) & (U_GC_PE_MASK | U_GC_PI_MASK | U_GC_PF_MASK);
539 }
540
541 float RenderText::hangablePunctuationStartWidth(unsigned index) const
542 {
543     unsigned length = text().length();
544     if (index >= length)
545         return 0;
546
547     if (!isHangablePunctuationAtLineStart(text()[index]))
548         return 0;
549
550     auto& style = this->style();
551     return widthFromCache(style.fontCascade(), index, 1, 0, 0, 0, style);
552 }
553
554 float RenderText::hangablePunctuationEndWidth(unsigned index) const
555 {
556     unsigned length = text().length();
557     if (index >= length)
558         return 0;
559
560     if (!isHangablePunctuationAtLineEnd(text()[index]))
561         return 0;
562
563     auto& style = this->style();
564     return widthFromCache(style.fontCascade(), index, 1, 0, 0, 0, style);
565 }
566
567 bool RenderText::isHangableStopOrComma(UChar c)
568 {
569     return c == 0x002C || c == 0x002E || c == 0x060C || c == 0x06D4 || c == 0x3001
570         || c == 0x3002 || c == 0xFF0C || c == 0xFF0E || c == 0xFE50 || c == 0xFE51
571         || c == 0xFE52 || c == 0xFF61 || c == 0xFF64;
572 }
573
574 unsigned RenderText::firstCharacterIndexStrippingSpaces() const
575 {
576     if (!style().collapseWhiteSpace())
577         return 0;
578
579     unsigned i = 0;
580     for (unsigned length = text().length() ; i < length; ++i) {
581         if (text()[i] != ' ' && (text()[i] != '\n' || style().preserveNewline()) && text()[i] != '\t')
582             break;
583     }
584     return i;
585 }
586
587 unsigned RenderText::lastCharacterIndexStrippingSpaces() const
588 {
589     if (!text().length())
590         return 0;
591
592     if (!style().collapseWhiteSpace())
593         return text().length() - 1;
594     
595     int i = text().length() - 1;
596     for ( ; i  >= 0; --i) {
597         if (text()[i] != ' ' && (text()[i] != '\n' || style().preserveNewline()) && text()[i] != '\t')
598             break;
599     }
600     return i;
601 }
602
603 RenderText::Widths RenderText::trimmedPreferredWidths(float leadWidth, bool& stripFrontSpaces)
604 {
605     auto& style = this->style();
606     bool collapseWhiteSpace = style.collapseWhiteSpace();
607
608     if (!collapseWhiteSpace)
609         stripFrontSpaces = false;
610
611     if (m_hasTab || preferredLogicalWidthsDirty())
612         computePreferredLogicalWidths(leadWidth);
613
614     Widths widths;
615
616     widths.beginWS = !stripFrontSpaces && m_hasBeginWS;
617     widths.endWS = m_hasEndWS;
618
619     unsigned length = this->length();
620
621     if (!length || (stripFrontSpaces && text().isAllSpecialCharacters<isHTMLSpace>()))
622         return widths;
623
624     widths.min = m_minWidth;
625     widths.max = m_maxWidth;
626
627     widths.beginMin = m_beginMinWidth;
628     widths.endMin = m_endMinWidth;
629
630     widths.hasBreakableChar = m_hasBreakableChar;
631     widths.hasBreak = m_hasBreak;
632
633     if (text()[0] == ' ' || (text()[0] == '\n' && !style.preserveNewline()) || text()[0] == '\t') {
634         auto& font = style.fontCascade(); // FIXME: This ignores first-line.
635         if (stripFrontSpaces)
636             widths.max -= font.width(RenderBlock::constructTextRun(&space, 1, style));
637         else
638             widths.max += font.wordSpacing();
639     }
640
641     stripFrontSpaces = collapseWhiteSpace && m_hasEndWS;
642
643     if (!style.autoWrap() || widths.min > widths.max)
644         widths.min = widths.max;
645
646     // Compute our max widths by scanning the string for newlines.
647     if (widths.hasBreak) {
648         auto& font = style.fontCascade(); // FIXME: This ignores first-line.
649         bool firstLine = true;
650         widths.beginMax = widths.max;
651         widths.endMax = widths.max;
652         for (unsigned i = 0; i < length; i++) {
653             unsigned lineLength = 0;
654             while (i + lineLength < length && text()[i + lineLength] != '\n')
655                 lineLength++;
656
657             if (lineLength) {
658                 widths.endMax = widthFromCache(font, i, lineLength, leadWidth + widths.endMax, 0, 0, style);
659                 if (firstLine) {
660                     firstLine = false;
661                     leadWidth = 0;
662                     widths.beginMax = widths.endMax;
663                 }
664                 i += lineLength;
665             } else if (firstLine) {
666                 widths.beginMax = 0;
667                 firstLine = false;
668                 leadWidth = 0;
669             }
670
671             if (i == length - 1) {
672                 // A <pre> run that ends with a newline, as in, e.g.,
673                 // <pre>Some text\n\n<span>More text</pre>
674                 widths.endMax = 0;
675             }
676         }
677     }
678
679     return widths;
680 }
681
682 static inline bool isSpaceAccordingToStyle(UChar c, const RenderStyle& style)
683 {
684     return c == ' ' || (c == noBreakSpace && style.nbspMode() == NBSPMode::Space);
685 }
686
687 float RenderText::minLogicalWidth() const
688 {
689     if (preferredLogicalWidthsDirty())
690         const_cast<RenderText*>(this)->computePreferredLogicalWidths(0);
691         
692     return m_minWidth;
693 }
694
695 float RenderText::maxLogicalWidth() const
696 {
697     if (preferredLogicalWidthsDirty())
698         const_cast<RenderText*>(this)->computePreferredLogicalWidths(0);
699         
700     return m_maxWidth;
701 }
702
703 LineBreakIteratorMode mapLineBreakToIteratorMode(LineBreak lineBreak)
704 {
705     switch (lineBreak) {
706     case LineBreak::Auto:
707     case LineBreak::AfterWhiteSpace:
708     case LineBreak::Anywhere:
709         return LineBreakIteratorMode::Default;
710     case LineBreak::Loose:
711         return LineBreakIteratorMode::Loose;
712     case LineBreak::Normal:
713         return LineBreakIteratorMode::Normal;
714     case LineBreak::Strict:
715         return LineBreakIteratorMode::Strict;
716     }
717     ASSERT_NOT_REACHED();
718     return LineBreakIteratorMode::Default;
719 }
720
721 void RenderText::computePreferredLogicalWidths(float leadWidth)
722 {
723     HashSet<const Font*> fallbackFonts;
724     GlyphOverflow glyphOverflow;
725     computePreferredLogicalWidths(leadWidth, fallbackFonts, glyphOverflow);
726     if (fallbackFonts.isEmpty() && !glyphOverflow.left && !glyphOverflow.right && !glyphOverflow.top && !glyphOverflow.bottom)
727         m_knownToHaveNoOverflowAndNoFallbackFonts = true;
728 }
729
730 static inline float hyphenWidth(RenderText& renderer, const FontCascade& font)
731 {
732     const RenderStyle& style = renderer.style();
733     auto textRun = RenderBlock::constructTextRun(style.hyphenString().string(), style);
734     return font.width(textRun);
735 }
736
737 static float maxWordFragmentWidth(RenderText& renderer, const RenderStyle& style, const FontCascade& font, StringView word, unsigned minimumPrefixLength, unsigned minimumSuffixLength, unsigned& suffixStart, HashSet<const Font*>& fallbackFonts, GlyphOverflow& glyphOverflow)
738 {
739     suffixStart = 0;
740     if (word.length() <= minimumSuffixLength)
741         return 0;
742
743     Vector<int, 8> hyphenLocations;
744     ASSERT(word.length() >= minimumSuffixLength);
745     unsigned hyphenLocation = word.length() - minimumSuffixLength;
746     while ((hyphenLocation = lastHyphenLocation(word, hyphenLocation, style.locale())) >= std::max(minimumPrefixLength, 1U))
747         hyphenLocations.append(hyphenLocation);
748
749     if (hyphenLocations.isEmpty())
750         return 0;
751
752     hyphenLocations.reverse();
753
754     // FIXME: Breaking the string at these places in the middle of words is completely broken with complex text.
755     float minimumFragmentWidthToConsider = font.pixelSize() * 5 / 4 + hyphenWidth(renderer, font);
756     float maxFragmentWidth = 0;
757     for (size_t k = 0; k < hyphenLocations.size(); ++k) {
758         int fragmentLength = hyphenLocations[k] - suffixStart;
759         StringBuilder fragmentWithHyphen;
760         fragmentWithHyphen.append(word.substring(suffixStart, fragmentLength));
761         fragmentWithHyphen.append(style.hyphenString());
762
763         TextRun run = RenderBlock::constructTextRun(fragmentWithHyphen.toString(), style);
764         run.setCharacterScanForCodePath(!renderer.canUseSimpleFontCodePath());
765         float fragmentWidth = font.width(run, &fallbackFonts, &glyphOverflow);
766
767         // Narrow prefixes are ignored. See tryHyphenating in RenderBlockLineLayout.cpp.
768         if (fragmentWidth <= minimumFragmentWidthToConsider)
769             continue;
770
771         suffixStart += fragmentLength;
772         maxFragmentWidth = std::max(maxFragmentWidth, fragmentWidth);
773     }
774
775     return maxFragmentWidth;
776 }
777
778 void RenderText::computePreferredLogicalWidths(float leadWidth, HashSet<const Font*>& fallbackFonts, GlyphOverflow& glyphOverflow)
779 {
780     ASSERT(m_hasTab || preferredLogicalWidthsDirty() || !m_knownToHaveNoOverflowAndNoFallbackFonts);
781
782     m_minWidth = 0;
783     m_beginMinWidth = 0;
784     m_endMinWidth = 0;
785     m_maxWidth = 0;
786
787     float currMaxWidth = 0;
788     m_hasBreakableChar = false;
789     m_hasBreak = false;
790     m_hasTab = false;
791     m_hasBeginWS = false;
792     m_hasEndWS = false;
793
794     auto& style = this->style();
795     auto& font = style.fontCascade(); // FIXME: This ignores first-line.
796     float wordSpacing = font.wordSpacing();
797     auto& string = text();
798     unsigned length = string.length();
799     auto iteratorMode = mapLineBreakToIteratorMode(style.lineBreak());
800     LazyLineBreakIterator breakIterator(string, style.locale(), iteratorMode);
801     bool needsWordSpacing = false;
802     bool ignoringSpaces = false;
803     bool isSpace = false;
804     bool firstWord = true;
805     bool firstLine = true;
806     Optional<unsigned> nextBreakable;
807     unsigned lastWordBoundary = 0;
808
809     WordTrailingSpace wordTrailingSpace(style);
810     // If automatic hyphenation is allowed, we keep track of the width of the widest word (or word
811     // fragment) encountered so far, and only try hyphenating words that are wider.
812     float maxWordWidth = std::numeric_limits<float>::max();
813     unsigned minimumPrefixLength = 0;
814     unsigned minimumSuffixLength = 0;
815     if (style.hyphens() == Hyphens::Auto && canHyphenate(style.locale())) {
816         maxWordWidth = 0;
817
818         // Map 'hyphenate-limit-{before,after}: auto;' to 2.
819         auto before = style.hyphenationLimitBefore();
820         minimumPrefixLength = before < 0 ? 2 : before;
821
822         auto after = style.hyphenationLimitAfter();
823         minimumSuffixLength = after < 0 ? 2 : after;
824     }
825
826     Optional<int> firstGlyphLeftOverflow;
827
828     bool breakNBSP = style.autoWrap() && style.nbspMode() == NBSPMode::Space;
829     
830     // Note the deliberate omission of word-wrap and overflow-wrap from this breakAll check. Those
831     // do not affect minimum preferred sizes. Note that break-word is a non-standard value for
832     // word-break, but we support it as though it means break-all.
833     bool breakAnywhere = style.lineBreak() == LineBreak::Anywhere && style.autoWrap();
834     bool breakAll = (style.wordBreak() == WordBreak::BreakAll || style.wordBreak() == WordBreak::BreakWord) && style.autoWrap();
835     bool keepAllWords = style.wordBreak() == WordBreak::KeepAll;
836     bool canUseLineBreakShortcut = iteratorMode == LineBreakIteratorMode::Default;
837
838     for (unsigned i = 0; i < length; i++) {
839         UChar c = string[i];
840
841         bool previousCharacterIsSpace = isSpace;
842
843         bool isNewline = false;
844         if (c == '\n') {
845             if (style.preserveNewline()) {
846                 m_hasBreak = true;
847                 isNewline = true;
848                 isSpace = false;
849             } else
850                 isSpace = true;
851         } else if (c == '\t') {
852             if (!style.collapseWhiteSpace()) {
853                 m_hasTab = true;
854                 isSpace = false;
855             } else
856                 isSpace = true;
857         } else
858             isSpace = c == ' ';
859
860         if ((isSpace || isNewline) && !i)
861             m_hasBeginWS = true;
862         if ((isSpace || isNewline) && i == length - 1)
863             m_hasEndWS = true;
864
865         ignoringSpaces |= style.collapseWhiteSpace() && previousCharacterIsSpace && isSpace;
866         ignoringSpaces &= isSpace;
867
868         // Ignore spaces and soft hyphens
869         if (ignoringSpaces) {
870             ASSERT(lastWordBoundary == i);
871             lastWordBoundary++;
872             continue;
873         } else if (c == softHyphen && style.hyphens() != Hyphens::None) {
874             ASSERT(i >= lastWordBoundary);
875             currMaxWidth += widthFromCache(font, lastWordBoundary, i - lastWordBoundary, leadWidth + currMaxWidth, &fallbackFonts, &glyphOverflow, style);
876             if (!firstGlyphLeftOverflow)
877                 firstGlyphLeftOverflow = glyphOverflow.left;
878             lastWordBoundary = i + 1;
879             continue;
880         }
881
882         bool hasBreak = breakAll || isBreakable(breakIterator, i, nextBreakable, breakNBSP, canUseLineBreakShortcut, keepAllWords, breakAnywhere);
883         bool betweenWords = true;
884         unsigned j = i;
885         while (c != '\n' && !isSpaceAccordingToStyle(c, style) && c != '\t' && (c != softHyphen || style.hyphens() == Hyphens::None)) {
886             j++;
887             if (j == length)
888                 break;
889             c = string[j];
890             if (isBreakable(breakIterator, j, nextBreakable, breakNBSP, canUseLineBreakShortcut, keepAllWords, breakAnywhere) && characterAt(j - 1) != softHyphen)
891                 break;
892             if (breakAll) {
893                 betweenWords = false;
894                 break;
895             }
896         }
897
898         unsigned wordLen = j - i;
899         if (wordLen) {
900             float currMinWidth = 0;
901             bool isSpace = (j < length) && isSpaceAccordingToStyle(c, style);
902             float w;
903             Optional<float> wordTrailingSpaceWidth;
904             if (isSpace)
905                 wordTrailingSpaceWidth = wordTrailingSpace.width(fallbackFonts);
906             if (wordTrailingSpaceWidth)
907                 w = widthFromCache(font, i, wordLen + 1, leadWidth + currMaxWidth, &fallbackFonts, &glyphOverflow, style) - wordTrailingSpaceWidth.value();
908             else {
909                 w = widthFromCache(font, i, wordLen, leadWidth + currMaxWidth, &fallbackFonts, &glyphOverflow, style);
910                 if (c == softHyphen && style.hyphens() != Hyphens::None)
911                     currMinWidth = hyphenWidth(*this, font);
912             }
913
914             if (w > maxWordWidth) {
915                 unsigned suffixStart;
916                 float maxFragmentWidth = maxWordFragmentWidth(*this, style, font, StringView(string).substring(i, wordLen), minimumPrefixLength, minimumSuffixLength, suffixStart, fallbackFonts, glyphOverflow);
917
918                 if (suffixStart) {
919                     float suffixWidth;
920                     Optional<float> wordTrailingSpaceWidth;
921                     if (isSpace)
922                         wordTrailingSpaceWidth = wordTrailingSpace.width(fallbackFonts);
923                     if (wordTrailingSpaceWidth)
924                         suffixWidth = widthFromCache(font, i + suffixStart, wordLen - suffixStart + 1, leadWidth + currMaxWidth, 0, 0, style) - wordTrailingSpaceWidth.value();
925                     else
926                         suffixWidth = widthFromCache(font, i + suffixStart, wordLen - suffixStart, leadWidth + currMaxWidth, 0, 0, style);
927
928                     maxFragmentWidth = std::max(maxFragmentWidth, suffixWidth);
929
930                     currMinWidth += maxFragmentWidth - w;
931                     maxWordWidth = std::max(maxWordWidth, maxFragmentWidth);
932                 } else
933                     maxWordWidth = w;
934             }
935
936             if (!firstGlyphLeftOverflow)
937                 firstGlyphLeftOverflow = glyphOverflow.left;
938             currMinWidth += w;
939             if (betweenWords) {
940                 if (lastWordBoundary == i)
941                     currMaxWidth += w;
942                 else {
943                     ASSERT(j >= lastWordBoundary);
944                     currMaxWidth += widthFromCache(font, lastWordBoundary, j - lastWordBoundary, leadWidth + currMaxWidth, &fallbackFonts, &glyphOverflow, style);
945                 }
946                 lastWordBoundary = j;
947             }
948
949             bool isCollapsibleWhiteSpace = (j < length) && style.isCollapsibleWhiteSpace(c);
950             if (j < length && style.autoWrap())
951                 m_hasBreakableChar = true;
952
953             // Add in wordSpacing to our currMaxWidth, but not if this is the last word on a line or the
954             // last word in the run.
955             if ((isSpace || isCollapsibleWhiteSpace) && !containsOnlyHTMLWhitespace(j, length - j))
956                 currMaxWidth += wordSpacing;
957
958             if (firstWord) {
959                 firstWord = false;
960                 // If the first character in the run is breakable, then we consider ourselves to have a beginning
961                 // minimum width of 0, since a break could occur right before our run starts, preventing us from ever
962                 // being appended to a previous text run when considering the total minimum width of the containing block.
963                 if (hasBreak)
964                     m_hasBreakableChar = true;
965                 m_beginMinWidth = hasBreak ? 0 : currMinWidth;
966             }
967             m_endMinWidth = currMinWidth;
968
969             m_minWidth = std::max(currMinWidth, m_minWidth);
970
971             i += wordLen - 1;
972         } else {
973             // Nowrap can never be broken, so don't bother setting the
974             // breakable character boolean. Pre can only be broken if we encounter a newline.
975             if (style.autoWrap() || isNewline)
976                 m_hasBreakableChar = true;
977
978             if (isNewline) { // Only set if preserveNewline was true and we saw a newline.
979                 if (firstLine) {
980                     firstLine = false;
981                     leadWidth = 0;
982                     if (!style.autoWrap())
983                         m_beginMinWidth = currMaxWidth;
984                 }
985
986                 if (currMaxWidth > m_maxWidth)
987                     m_maxWidth = currMaxWidth;
988                 currMaxWidth = 0;
989             } else {
990                 TextRun run = RenderBlock::constructTextRun(*this, i, 1, style);
991                 run.setTabSize(!style.collapseWhiteSpace(), style.tabSize());
992                 run.setXPos(leadWidth + currMaxWidth);
993
994                 currMaxWidth += font.width(run, &fallbackFonts);
995                 glyphOverflow.right = 0;
996                 needsWordSpacing = isSpace && !previousCharacterIsSpace && i == length - 1;
997             }
998             ASSERT(lastWordBoundary == i);
999             lastWordBoundary++;
1000         }
1001     }
1002
1003     glyphOverflow.left = firstGlyphLeftOverflow.valueOr(glyphOverflow.left);
1004
1005     if ((needsWordSpacing && length > 1) || (ignoringSpaces && !firstWord))
1006         currMaxWidth += wordSpacing;
1007
1008     m_maxWidth = std::max(currMaxWidth, m_maxWidth);
1009
1010     if (!style.autoWrap())
1011         m_minWidth = m_maxWidth;
1012
1013     if (style.whiteSpace() == WhiteSpace::Pre) {
1014         if (firstLine)
1015             m_beginMinWidth = m_maxWidth;
1016         m_endMinWidth = currMaxWidth;
1017     }
1018
1019     setPreferredLogicalWidthsDirty(false);
1020 }
1021
1022 template<typename CharacterType> static inline bool isAllCollapsibleWhitespace(const CharacterType* characters, unsigned length, const RenderStyle& style)
1023 {
1024     for (unsigned i = 0; i < length; ++i) {
1025         if (!style.isCollapsibleWhiteSpace(characters[i]))
1026             return false;
1027     }
1028     return true;
1029 }
1030
1031 bool RenderText::isAllCollapsibleWhitespace() const
1032 {
1033     if (text().is8Bit())
1034         return WebCore::isAllCollapsibleWhitespace(text().characters8(), text().length(), style());
1035     return WebCore::isAllCollapsibleWhitespace(text().characters16(), text().length(), style());
1036 }
1037
1038 template<typename CharacterType> static inline bool isAllPossiblyCollapsibleWhitespace(const CharacterType* characters, unsigned length)
1039 {
1040     for (unsigned i = 0; i < length; ++i) {
1041         if (!(characters[i] == '\n' || characters[i] == ' ' || characters[i] == '\t'))
1042             return false;
1043     }
1044     return true;
1045 }
1046
1047 bool RenderText::containsOnlyHTMLWhitespace(unsigned from, unsigned length) const
1048 {
1049     ASSERT(from <= text().length());
1050     ASSERT(length <= text().length());
1051     ASSERT(from + length <= text().length());
1052     if (text().is8Bit())
1053         return isAllPossiblyCollapsibleWhitespace(text().characters8() + from, length);
1054     return isAllPossiblyCollapsibleWhitespace(text().characters16() + from, length);
1055 }
1056
1057 Vector<std::pair<unsigned, unsigned>> RenderText::draggedContentRangesBetweenOffsets(unsigned startOffset, unsigned endOffset) const
1058 {
1059     if (!textNode())
1060         return { };
1061
1062     auto markers = document().markers().markersFor(*textNode(), DocumentMarker::DraggedContent);
1063     if (markers.isEmpty())
1064         return { };
1065
1066     Vector<std::pair<unsigned, unsigned>> draggedContentRanges;
1067     for (auto* marker : markers) {
1068         unsigned markerStart = std::max(marker->startOffset(), startOffset);
1069         unsigned markerEnd = std::min(marker->endOffset(), endOffset);
1070         if (markerStart >= markerEnd || markerStart > endOffset || markerEnd < startOffset)
1071             continue;
1072
1073         std::pair<unsigned, unsigned> draggedContentRange;
1074         draggedContentRange.first = markerStart;
1075         draggedContentRange.second = markerEnd;
1076         draggedContentRanges.append(draggedContentRange);
1077     }
1078     return draggedContentRanges;
1079 }
1080
1081 IntPoint RenderText::firstRunLocation() const
1082 {
1083     auto first = LineLayoutTraversal::firstTextBoxFor(*this);
1084     if (!first)
1085         return { };
1086     return IntPoint(first->rect().location());
1087 }
1088
1089 void RenderText::setSelectionState(SelectionState state)
1090 {
1091     if (state != SelectionNone)
1092         ensureLineBoxes();
1093
1094     RenderObject::setSelectionState(state);
1095
1096     if (canUpdateSelectionOnRootLineBoxes())
1097         m_lineBoxes.setSelectionState(*this, state);
1098
1099     // The containing block can be null in case of an orphaned tree.
1100     RenderBlock* containingBlock = this->containingBlock();
1101     if (containingBlock && !containingBlock->isRenderView())
1102         containingBlock->setSelectionState(state);
1103 }
1104
1105 void RenderText::setTextWithOffset(const String& newText, unsigned offset, unsigned length, bool force)
1106 {
1107     if (!force && text() == newText)
1108         return;
1109
1110     int delta = newText.length() - text().length();
1111     unsigned end = offset + length;
1112
1113     m_linesDirty = simpleLineLayout() || m_lineBoxes.dirtyRange(*this, offset, end, delta);
1114
1115     setText(newText, force || m_linesDirty);
1116 }
1117
1118 static inline bool isInlineFlowOrEmptyText(const RenderObject& renderer)
1119 {
1120     return is<RenderInline>(renderer) || (is<RenderText>(renderer) && downcast<RenderText>(renderer).text().isEmpty());
1121 }
1122
1123 UChar RenderText::previousCharacter() const
1124 {
1125     // find previous text renderer if one exists
1126     const RenderObject* previousText = this;
1127     while ((previousText = previousText->previousInPreOrder())) {
1128         if (!isInlineFlowOrEmptyText(*previousText))
1129             break;
1130     }
1131     if (!is<RenderText>(previousText))
1132         return ' ';
1133     auto& previousString = downcast<RenderText>(*previousText).text();
1134     return previousString[previousString.length() - 1];
1135 }
1136
1137 LayoutUnit RenderText::topOfFirstText() const
1138 {
1139     return firstTextBox()->root().lineTop();
1140 }
1141
1142 String applyTextTransform(const RenderStyle& style, const String& text, UChar previousCharacter)
1143 {
1144     switch (style.textTransform()) {
1145     case TextTransform::None:
1146         return text;
1147     case TextTransform::Capitalize:
1148         return capitalize(text, previousCharacter); // FIXME: Need to take locale into account.
1149     case TextTransform::Uppercase:
1150         return text.convertToUppercaseWithLocale(style.locale());
1151     case TextTransform::Lowercase:
1152         return text.convertToLowercaseWithLocale(style.locale());
1153     }
1154     ASSERT_NOT_REACHED();
1155     return text;
1156 }
1157
1158 void RenderText::setRenderedText(const String& newText)
1159 {
1160     ASSERT(!newText.isNull());
1161
1162     String originalText = this->originalText();
1163
1164     m_text = newText;
1165
1166     if (m_useBackslashAsYenSymbol)
1167         m_text.replace('\\', yenSign);
1168     
1169     const auto& style = this->style();
1170     if (style.textTransform() != TextTransform::None)
1171         m_text = applyTextTransform(style, m_text, previousCharacter());
1172
1173     switch (style.textSecurity()) {
1174     case TextSecurity::None:
1175         break;
1176 #if !PLATFORM(IOS_FAMILY)
1177     // We use the same characters here as for list markers.
1178     // See the listMarkerText function in RenderListMarker.cpp.
1179     case TextSecurity::Circle:
1180         secureText(whiteBullet);
1181         break;
1182     case TextSecurity::Disc:
1183         secureText(bullet);
1184         break;
1185     case TextSecurity::Square:
1186         secureText(blackSquare);
1187         break;
1188 #else
1189     // FIXME: Why this quirk on iOS?
1190     case TextSecurity::Circle:
1191     case TextSecurity::Disc:
1192     case TextSecurity::Square:
1193         secureText(blackCircle);
1194         break;
1195 #endif
1196     }
1197
1198     m_isAllASCII = text().isAllASCII();
1199     m_canUseSimpleFontCodePath = computeCanUseSimpleFontCodePath();
1200     m_canUseSimplifiedTextMeasuring = computeCanUseSimplifiedTextMeasuring();
1201     
1202     if (m_text != originalText) {
1203         originalTextMap().set(this, originalText);
1204         m_originalTextDiffersFromRendered = true;
1205     } else if (m_originalTextDiffersFromRendered) {
1206         originalTextMap().remove(this);
1207         m_originalTextDiffersFromRendered = false;
1208     }
1209 }
1210
1211 void RenderText::secureText(UChar maskingCharacter)
1212 {
1213     // This hides the text by replacing all the characters with the masking character.
1214     // Offsets within the hidden text have to match offsets within the original text
1215     // to handle things like carets and selection, so this won't work right if any
1216     // of the characters are surrogate pairs or combining marks. Thus, this function
1217     // does not attempt to handle either of those.
1218
1219     unsigned length = text().length();
1220     if (!length)
1221         return;
1222
1223     UChar characterToReveal = 0;
1224     unsigned revealedCharactersOffset = 0;
1225
1226     if (SecureTextTimer* timer = secureTextTimers().get(this)) {
1227         // We take the offset out of the timer to make this one-shot. We count on this being called only once.
1228         // If it's called a second time we assume the text is different and a character should not be revealed.
1229         revealedCharactersOffset = timer->takeOffsetAfterLastTypedCharacter();
1230         if (revealedCharactersOffset && revealedCharactersOffset <= length)
1231             characterToReveal = text()[--revealedCharactersOffset];
1232     }
1233
1234     UChar* characters;
1235     m_text = String::createUninitialized(length, characters);
1236
1237     for (unsigned i = 0; i < length; ++i)
1238         characters[i] = maskingCharacter;
1239     if (characterToReveal)
1240         characters[revealedCharactersOffset] = characterToReveal;
1241 }
1242
1243 bool RenderText::computeCanUseSimplifiedTextMeasuring() const
1244 {
1245     if (!m_canUseSimpleFontCodePath)
1246         return false;
1247     
1248     auto& font = style().fontCascade();
1249     if (font.wordSpacing() || font.letterSpacing())
1250         return false;
1251
1252     // Additional check on the font codepath.
1253     TextRun run(m_text);
1254     run.setCharacterScanForCodePath(false);
1255     if (font.codePath(run) != FontCascade::Simple)
1256         return false;
1257
1258     auto whitespaceIsCollapsed = style().collapseWhiteSpace();
1259     for (unsigned i = 0; i < text().length(); ++i) {
1260         if ((!whitespaceIsCollapsed && text()[i] == '\t') || text()[i] == noBreakSpace || text()[i] >= HiraganaLetterSmallA)
1261             return false;
1262     }
1263     return true;
1264 }
1265
1266 void RenderText::setText(const String& text, bool force)
1267 {
1268     ASSERT(!text.isNull());
1269
1270     if (!force && text == originalText())
1271         return;
1272
1273     m_text = text;
1274     if (m_originalTextDiffersFromRendered) {
1275         originalTextMap().remove(this);
1276         m_originalTextDiffersFromRendered = false;
1277     }
1278
1279     setRenderedText(text);
1280
1281     setNeedsLayoutAndPrefWidthsRecalc();
1282     m_knownToHaveNoOverflowAndNoFallbackFonts = false;
1283
1284     if (is<RenderBlockFlow>(*parent()))
1285         downcast<RenderBlockFlow>(*parent()).invalidateLineLayoutPath();
1286     
1287     if (AXObjectCache* cache = document().existingAXObjectCache())
1288         cache->deferTextChangedIfNeeded(textNode());
1289 }
1290
1291 String RenderText::textWithoutConvertingBackslashToYenSymbol() const
1292 {
1293     if (!m_useBackslashAsYenSymbol || style().textSecurity() != TextSecurity::None)
1294         return text();
1295
1296     if (style().textTransform() == TextTransform::None)
1297         return originalText();
1298
1299     return applyTextTransform(style(), originalText(), previousCharacter());
1300 }
1301
1302 void RenderText::dirtyLineBoxes(bool fullLayout)
1303 {
1304     if (fullLayout)
1305         m_lineBoxes.deleteAll();
1306     else if (!m_linesDirty)
1307         m_lineBoxes.dirtyAll();
1308     m_linesDirty = false;
1309 }
1310
1311 std::unique_ptr<InlineTextBox> RenderText::createTextBox()
1312 {
1313     return makeUnique<InlineTextBox>(*this);
1314 }
1315
1316 void RenderText::positionLineBox(InlineTextBox& textBox)
1317 {
1318     if (!textBox.hasTextContent())
1319         return;
1320     m_containsReversedText |= !textBox.isLeftToRightDirection();
1321 }
1322
1323 void RenderText::ensureLineBoxes()
1324 {
1325     if (!is<RenderBlockFlow>(*parent()))
1326         return;
1327     downcast<RenderBlockFlow>(*parent()).ensureLineBoxes();
1328 }
1329
1330 const SimpleLineLayout::Layout* RenderText::simpleLineLayout() const
1331 {
1332     if (!is<RenderBlockFlow>(*parent()))
1333         return nullptr;
1334     return downcast<RenderBlockFlow>(*parent()).simpleLineLayout();
1335 }
1336
1337 float RenderText::width(unsigned from, unsigned len, float xPos, bool firstLine, HashSet<const Font*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
1338 {
1339     if (from >= text().length())
1340         return 0;
1341
1342     if (from + len > text().length())
1343         len = text().length() - from;
1344
1345     const RenderStyle& lineStyle = firstLine ? firstLineStyle() : style();
1346     return width(from, len, lineStyle.fontCascade(), xPos, fallbackFonts, glyphOverflow);
1347 }
1348
1349 float RenderText::width(unsigned from, unsigned len, const FontCascade& f, float xPos, HashSet<const Font*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
1350 {
1351     ASSERT(from + len <= text().length());
1352     if (!text().length())
1353         return 0;
1354
1355     const RenderStyle& style = this->style();
1356     float w;
1357     if (&f == &style.fontCascade()) {
1358         if (!style.preserveNewline() && !from && len == text().length() && (!glyphOverflow || !glyphOverflow->computeBounds)) {
1359             if (fallbackFonts) {
1360                 ASSERT(glyphOverflow);
1361                 if (preferredLogicalWidthsDirty() || !m_knownToHaveNoOverflowAndNoFallbackFonts) {
1362                     const_cast<RenderText*>(this)->computePreferredLogicalWidths(0, *fallbackFonts, *glyphOverflow);
1363                     if (fallbackFonts->isEmpty() && !glyphOverflow->left && !glyphOverflow->right && !glyphOverflow->top && !glyphOverflow->bottom)
1364                         m_knownToHaveNoOverflowAndNoFallbackFonts = true;
1365                 }
1366                 w = m_maxWidth;
1367             } else
1368                 w = maxLogicalWidth();
1369         } else
1370             w = widthFromCache(f, from, len, xPos, fallbackFonts, glyphOverflow, style);
1371     } else {
1372         TextRun run = RenderBlock::constructTextRun(*this, from, len, style);
1373         run.setCharacterScanForCodePath(!canUseSimpleFontCodePath());
1374         run.setTabSize(!style.collapseWhiteSpace(), style.tabSize());
1375         run.setXPos(xPos);
1376
1377         w = f.width(run, fallbackFonts, glyphOverflow);
1378     }
1379
1380     return w;
1381 }
1382
1383 IntRect RenderText::linesBoundingBox() const
1384 {
1385     auto first = LineLayoutTraversal::firstTextBoxFor(*this);
1386     if (!first)
1387         return { };
1388
1389     auto boundingBox = first->rect();
1390     for (auto box = first; ++box;)
1391         boundingBox.uniteEvenIfEmpty(box->rect());
1392
1393     return enclosingIntRect(boundingBox);
1394 }
1395
1396 LayoutRect RenderText::linesVisualOverflowBoundingBox() const
1397 {
1398     ASSERT(!simpleLineLayout());
1399     return m_lineBoxes.visualOverflowBoundingBox(*this);
1400 }
1401
1402 LayoutRect RenderText::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const
1403 {
1404     RenderObject* rendererToRepaint = containingBlock();
1405
1406     // Do not cross self-painting layer boundaries.
1407     RenderObject& enclosingLayerRenderer = enclosingLayer()->renderer();
1408     if (&enclosingLayerRenderer != rendererToRepaint && !rendererToRepaint->isDescendantOf(&enclosingLayerRenderer))
1409         rendererToRepaint = &enclosingLayerRenderer;
1410
1411     // The renderer we chose to repaint may be an ancestor of repaintContainer, but we need to do a repaintContainer-relative repaint.
1412     if (repaintContainer && repaintContainer != rendererToRepaint && !rendererToRepaint->isDescendantOf(repaintContainer))
1413         return repaintContainer->clippedOverflowRectForRepaint(repaintContainer);
1414
1415     return rendererToRepaint->clippedOverflowRectForRepaint(repaintContainer);
1416 }
1417
1418 LayoutRect RenderText::collectSelectionRectsForLineBoxes(const RenderLayerModelObject* repaintContainer, bool clipToVisibleContent, Vector<LayoutRect>* rects)
1419 {
1420     ASSERT(!needsLayout());
1421     ASSERT(!simpleLineLayout());
1422
1423     if (selectionState() == SelectionNone)
1424         return LayoutRect();
1425     if (!containingBlock())
1426         return LayoutRect();
1427
1428     // Now calculate startPos and endPos for painting selection.
1429     // We include a selection while endPos > 0
1430     unsigned startPos;
1431     unsigned endPos;
1432     if (selectionState() == SelectionInside) {
1433         // We are fully selected.
1434         startPos = 0;
1435         endPos = text().length();
1436     } else {
1437         startPos = view().selection().startPosition();
1438         endPos = view().selection().endPosition();
1439         if (selectionState() == SelectionStart)
1440             endPos = text().length();
1441         else if (selectionState() == SelectionEnd)
1442             startPos = 0;
1443     }
1444
1445     if (startPos == endPos)
1446         return IntRect();
1447
1448     LayoutRect resultRect;
1449     if (!rects)
1450         resultRect = m_lineBoxes.selectionRectForRange(startPos, endPos);
1451     else {
1452         m_lineBoxes.collectSelectionRectsForRange(startPos, endPos, *rects);
1453         for (auto& rect : *rects) {
1454             resultRect.unite(rect);
1455             rect = localToContainerQuad(FloatRect(rect), repaintContainer).enclosingBoundingBox();
1456         }
1457     }
1458
1459     if (clipToVisibleContent)
1460         return computeRectForRepaint(resultRect, repaintContainer);
1461     return localToContainerQuad(FloatRect(resultRect), repaintContainer).enclosingBoundingBox();
1462 }
1463
1464 LayoutRect RenderText::collectSelectionRectsForLineBoxes(const RenderLayerModelObject* repaintContainer, bool clipToVisibleContent, Vector<LayoutRect>& rects)
1465 {
1466     return collectSelectionRectsForLineBoxes(repaintContainer, clipToVisibleContent, &rects);
1467 }
1468
1469 LayoutRect RenderText::selectionRectForRepaint(const RenderLayerModelObject* repaintContainer, bool clipToVisibleContent)
1470 {
1471     return collectSelectionRectsForLineBoxes(repaintContainer, clipToVisibleContent, nullptr);
1472 }
1473
1474 int RenderText::caretMinOffset() const
1475 {
1476     auto first = LineLayoutTraversal::firstTextBoxFor(*this);
1477     if (!first)
1478         return 0;
1479
1480     int minOffset = first->localStartOffset();
1481     for (auto box = first; ++box;)
1482         minOffset = std::min<int>(minOffset, box->localStartOffset());
1483
1484     return minOffset;
1485 }
1486
1487 int RenderText::caretMaxOffset() const
1488 {
1489     auto first = LineLayoutTraversal::firstTextBoxFor(*this);
1490     if (!first)
1491         return text().length();
1492
1493     int maxOffset = first->localEndOffset();
1494     for (auto box = first; ++box;)
1495         maxOffset = std::max<int>(maxOffset, box->localEndOffset());
1496
1497     return maxOffset;
1498 }
1499
1500 unsigned RenderText::countRenderedCharacterOffsetsUntil(unsigned offset) const
1501 {
1502     unsigned result = 0;
1503     for (auto& box : LineLayoutTraversal::textBoxesFor(*this)) {
1504         auto start = box.localStartOffset();
1505         auto length = box.length();
1506         if (offset < start)
1507             return result;
1508         if (offset <= start + length) {
1509             result += offset - start;
1510             return result;
1511         }
1512         result += length;
1513     }
1514     return result;
1515 }
1516
1517 enum class OffsetType { Character, Caret };
1518 static bool containsOffset(const RenderText& text, unsigned offset, OffsetType type)
1519 {
1520     for (auto box = LineLayoutTraversal::firstTextBoxInTextOrderFor(text); box; box.traverseNextInTextOrder()) {
1521         auto start = box->localStartOffset();
1522         if (offset < start)
1523             return false;
1524         unsigned end = box->localEndOffset();
1525         if (offset >= start && offset <= end) {
1526             if (offset == end && (type == OffsetType::Character || box->isLineBreak()))
1527                 continue;
1528             if (type == OffsetType::Character)
1529                 return true;
1530             // Return false for offsets inside composed characters.
1531             return !offset || offset == static_cast<unsigned>(text.nextOffset(text.previousOffset(offset)));
1532         }
1533     }
1534     return false;
1535 }
1536
1537 bool RenderText::containsRenderedCharacterOffset(unsigned offset) const
1538 {
1539     return containsOffset(*this, offset, OffsetType::Character);
1540 }
1541
1542 bool RenderText::containsCaretOffset(unsigned offset) const
1543 {
1544     return containsOffset(*this, offset, OffsetType::Caret);
1545 }
1546
1547 bool RenderText::hasRenderedText() const
1548 {
1549     for (auto& box : LineLayoutTraversal::textBoxesFor(*this)) {
1550         if (box.length())
1551             return true;
1552     }
1553     return false;
1554 }
1555
1556 int RenderText::previousOffset(int current) const
1557 {
1558     if (m_isAllASCII || text().is8Bit())
1559         return current - 1;
1560
1561     CachedTextBreakIterator iterator(text(), TextBreakIterator::Mode::Caret, nullAtom());
1562     return iterator.preceding(current).valueOr(current - 1);
1563 }
1564
1565 int RenderText::previousOffsetForBackwardDeletion(int current) const
1566 {
1567     CachedTextBreakIterator iterator(text(), TextBreakIterator::Mode::Delete, nullAtom());
1568     return iterator.preceding(current).valueOr(0);
1569 }
1570
1571 int RenderText::nextOffset(int current) const
1572 {
1573     if (m_isAllASCII || text().is8Bit())
1574         return current + 1;
1575
1576     CachedTextBreakIterator iterator(text(), TextBreakIterator::Mode::Caret, nullAtom());
1577     return iterator.following(current).valueOr(current + 1);
1578 }
1579
1580 bool RenderText::computeCanUseSimpleFontCodePath() const
1581 {
1582     if (m_isAllASCII || text().is8Bit())
1583         return true;
1584     return FontCascade::characterRangeCodePath(text().characters16(), length()) == FontCascade::Simple;
1585 }
1586
1587 void RenderText::momentarilyRevealLastTypedCharacter(unsigned offsetAfterLastTypedCharacter)
1588 {
1589     if (style().textSecurity() == TextSecurity::None)
1590         return;
1591     auto& secureTextTimer = secureTextTimers().add(this, nullptr).iterator->value;
1592     if (!secureTextTimer)
1593         secureTextTimer = makeUnique<SecureTextTimer>(*this);
1594     secureTextTimer->restart(offsetAfterLastTypedCharacter);
1595 }
1596
1597 StringView RenderText::stringView(unsigned start, Optional<unsigned> stop) const
1598 {
1599     unsigned destination = stop.valueOr(text().length());
1600     ASSERT(start <= length());
1601     ASSERT(destination <= length());
1602     ASSERT(start <= destination);
1603     if (text().is8Bit())
1604         return { text().characters8() + start, destination - start };
1605     return { text().characters16() + start, destination - start };
1606 }
1607
1608 RenderInline* RenderText::inlineWrapperForDisplayContents()
1609 {
1610     ASSERT(m_hasInlineWrapperForDisplayContents == inlineWrapperForDisplayContentsMap().contains(this));
1611
1612     if (!m_hasInlineWrapperForDisplayContents)
1613         return nullptr;
1614     return inlineWrapperForDisplayContentsMap().get(this).get();
1615 }
1616
1617 void RenderText::setInlineWrapperForDisplayContents(RenderInline* wrapper)
1618 {
1619     ASSERT(m_hasInlineWrapperForDisplayContents == inlineWrapperForDisplayContentsMap().contains(this));
1620
1621     if (!wrapper) {
1622         if (!m_hasInlineWrapperForDisplayContents)
1623             return;
1624         inlineWrapperForDisplayContentsMap().remove(this);
1625         m_hasInlineWrapperForDisplayContents = false;
1626         return;
1627     }
1628     inlineWrapperForDisplayContentsMap().add(this, makeWeakPtr(wrapper));
1629     m_hasInlineWrapperForDisplayContents = true;
1630 }
1631
1632 RenderText* RenderText::findByDisplayContentsInlineWrapperCandidate(RenderElement& renderer)
1633 {
1634     auto* firstChild = renderer.firstChild();
1635     if (!is<RenderText>(firstChild))
1636         return nullptr;
1637     auto& textRenderer = downcast<RenderText>(*firstChild);
1638     if (textRenderer.inlineWrapperForDisplayContents() != &renderer)
1639         return nullptr;
1640     ASSERT(textRenderer.textNode());
1641     ASSERT(renderer.firstChild() == renderer.lastChild());
1642     return &textRenderer;
1643
1644 }
1645
1646 } // namespace WebCore