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