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