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