d91bfe6e78fe32d204f806f1cd3d9907343c4a4a
[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, 2005, 2006, 2007 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 "EllipsisBox.h"
30 #include "FloatQuad.h"
31 #include "Frame.h"
32 #include "FrameView.h"
33 #include "Hyphenation.h"
34 #include "InlineTextBox.h"
35 #include "Range.h"
36 #include "RenderArena.h"
37 #include "RenderBlock.h"
38 #include "RenderCombineText.h"
39 #include "RenderLayer.h"
40 #include "RenderView.h"
41 #include "Settings.h"
42 #include "Text.h"
43 #include "TextBreakIterator.h"
44 #include "TextResourceDecoder.h"
45 #include "VisiblePosition.h"
46 #include "break_lines.h"
47 #include <wtf/text/StringBuffer.h>
48 #include <wtf/unicode/CharacterNames.h>
49
50 using namespace std;
51 using namespace WTF;
52 using namespace Unicode;
53
54 namespace WebCore {
55
56 struct SameSizeAsRenderText : public RenderObject {
57     uint32_t bitfields : 16;
58 #if ENABLE(IOS_TEXT_AUTOSIZING)
59     float candidateTextSize;
60 #endif
61     float widths[4];
62     String text;
63     void* pointers[2];
64 };
65
66 COMPILE_ASSERT(sizeof(RenderText) == sizeof(SameSizeAsRenderText), RenderText_should_stay_small);
67
68 class SecureTextTimer;
69 typedef HashMap<RenderText*, SecureTextTimer*> SecureTextTimerMap;
70 static SecureTextTimerMap* gSecureTextTimers = 0;
71
72 class SecureTextTimer : public TimerBase {
73 public:
74     SecureTextTimer(RenderText* renderText)
75         : m_renderText(renderText)
76         , m_lastTypedCharacterOffset(-1)
77     {
78     }
79
80     void restartWithNewText(unsigned lastTypedCharacterOffset)
81     {
82         m_lastTypedCharacterOffset = lastTypedCharacterOffset;
83         const Settings& settings = m_renderText->frame().settings();
84         startOneShot(settings.passwordEchoDurationInSeconds());
85     }
86     void invalidate() { m_lastTypedCharacterOffset = -1; }
87     unsigned lastTypedCharacterOffset() { return m_lastTypedCharacterOffset; }
88
89 private:
90     virtual void fired()
91     {
92         ASSERT(gSecureTextTimers->contains(m_renderText));
93         m_renderText->setText(m_renderText->text(), true /* forcing setting text as it may be masked later */);
94     }
95
96     RenderText* m_renderText;
97     int m_lastTypedCharacterOffset;
98 };
99
100 static void makeCapitalized(String* string, UChar previous)
101 {
102     // FIXME: Need to change this to use u_strToTitle instead of u_totitle and to consider locale.
103
104     if (string->isNull())
105         return;
106
107     unsigned length = string->length();
108     const StringImpl& stringImpl = *string->impl();
109
110     if (length >= numeric_limits<unsigned>::max())
111         CRASH();
112
113     StringBuffer<UChar> stringWithPrevious(length + 1);
114     stringWithPrevious[0] = previous == noBreakSpace ? ' ' : previous;
115     for (unsigned i = 1; i < length + 1; i++) {
116         // Replace &nbsp with a real space since ICU no longer treats &nbsp as a word separator.
117         if (stringImpl[i - 1] == noBreakSpace)
118             stringWithPrevious[i] = ' ';
119         else
120             stringWithPrevious[i] = stringImpl[i - 1];
121     }
122
123     TextBreakIterator* boundary = wordBreakIterator(stringWithPrevious.characters(), length + 1);
124     if (!boundary)
125         return;
126
127     StringBuilder result;
128     result.reserveCapacity(length);
129
130     int32_t endOfWord;
131     int32_t startOfWord = textBreakFirst(boundary);
132     for (endOfWord = textBreakNext(boundary); endOfWord != TextBreakDone; startOfWord = endOfWord, endOfWord = textBreakNext(boundary)) {
133         if (startOfWord) // Ignore first char of previous string
134             result.append(stringImpl[startOfWord - 1] == noBreakSpace ? noBreakSpace : u_totitle(stringWithPrevious[startOfWord]));
135         for (int i = startOfWord + 1; i < endOfWord; i++)
136             result.append(stringImpl[i - 1]);
137     }
138
139     *string = result.toString();
140 }
141
142 RenderText::RenderText(Text* textNode, const String& text)
143     : RenderObject(textNode)
144     , m_hasTab(false)
145     , m_linesDirty(false)
146     , m_containsReversedText(false)
147     , m_isAllASCII(text.containsOnlyASCII())
148     , m_knownToHaveNoOverflowAndNoFallbackFonts(false)
149     , m_useBackslashAsYenSymbol(false)
150 #if ENABLE(IOS_TEXT_AUTOSIZING)
151     , m_candidateComputedTextSize(0)
152 #endif
153     , m_minWidth(-1)
154     , m_maxWidth(-1)
155     , m_beginMinWidth(0)
156     , m_endMinWidth(0)
157     , m_text(text)
158 {
159     ASSERT(!m_text.isNull());
160
161     setIsText();
162
163     m_canUseSimpleFontCodePath = computeCanUseSimpleFontCodePath();
164
165     if (textNode)
166         view().frameView().incrementVisuallyNonEmptyCharacterCount(m_text.length());
167 }
168
169 #ifndef NDEBUG
170
171 RenderText::~RenderText()
172 {
173 }
174
175 #endif
176
177 RenderText* RenderText::createAnonymous(Document& document, const String& text)
178 {
179     RenderText* renderText = new (*document.renderArena()) RenderText(nullptr, text);
180     renderText->setDocumentForAnonymous(document);
181     renderText->view().frameView().incrementVisuallyNonEmptyCharacterCount(text.length());
182     return renderText;
183 }
184
185 const char* RenderText::renderName() const
186 {
187     return "RenderText";
188 }
189
190 Text* RenderText::textNode() const
191 {
192     return toText(RenderObject::node());
193 }
194
195 bool RenderText::isTextFragment() const
196 {
197     return false;
198 }
199
200 bool RenderText::computeUseBackslashAsYenSymbol() const
201 {
202     const FontDescription& fontDescription = style()->font().fontDescription();
203     if (style()->font().useBackslashAsYenSymbol())
204         return true;
205     if (fontDescription.isSpecifiedFont())
206         return false;
207     const TextEncoding* encoding = document().decoder() ? &document().decoder()->encoding() : 0;
208     if (encoding && encoding->backslashAsCurrencySymbol() != '\\')
209         return true;
210     return false;
211 }
212
213 void RenderText::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
214 {
215     // There is no need to ever schedule repaints from a style change of a text run, since
216     // we already did this for the parent of the text run.
217     // We do have to schedule layouts, though, since a style change can force us to
218     // need to relayout.
219     if (diff == StyleDifferenceLayout) {
220         setNeedsLayoutAndPrefWidthsRecalc();
221         m_knownToHaveNoOverflowAndNoFallbackFonts = false;
222     }
223
224     RenderStyle* newStyle = style();
225     bool needsResetText = false;
226     if (!oldStyle) {
227         m_useBackslashAsYenSymbol = computeUseBackslashAsYenSymbol();
228         needsResetText = m_useBackslashAsYenSymbol;
229     } else if (oldStyle->font().useBackslashAsYenSymbol() != newStyle->font().useBackslashAsYenSymbol()) {
230         m_useBackslashAsYenSymbol = computeUseBackslashAsYenSymbol();
231         needsResetText = true;
232     }
233
234     ETextTransform oldTransform = oldStyle ? oldStyle->textTransform() : TTNONE;
235     ETextSecurity oldSecurity = oldStyle ? oldStyle->textSecurity() : TSNONE;
236     if (needsResetText || oldTransform != newStyle->textTransform() || oldSecurity != newStyle->textSecurity()) 
237         transformText();
238 }
239
240 void RenderText::removeAndDestroyTextBoxes()
241 {
242     if (!documentBeingDestroyed()) {
243         if (firstTextBox()) {
244             for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox())
245                 box->remove();
246         } else if (parent())
247             parent()->dirtyLinesFromChangedChild(this);
248     }
249     m_lineBoxes.deleteAll(*this);
250 }
251
252 void RenderText::willBeDestroyed()
253 {
254     if (SecureTextTimer* secureTextTimer = gSecureTextTimers ? gSecureTextTimers->take(this) : 0)
255         delete secureTextTimer;
256
257     removeAndDestroyTextBoxes();
258     RenderObject::willBeDestroyed();
259 }
260
261 String RenderText::originalText() const
262 {
263     return textNode() ? textNode()->data() : String();
264 }
265
266 void RenderText::absoluteRects(Vector<IntRect>& rects, const LayoutPoint& accumulatedOffset) const
267 {
268     for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox())
269         rects.append(enclosingIntRect(FloatRect(accumulatedOffset + box->topLeft(), box->size())));
270 }
271
272 static FloatRect localQuadForTextBox(InlineTextBox* box, unsigned start, unsigned end, bool useSelectionHeight)
273 {
274     unsigned realEnd = min(box->end() + 1, end);
275     LayoutRect r = box->localSelectionRect(start, realEnd);
276     if (r.height()) {
277         if (!useSelectionHeight) {
278             // Change the height and y position (or width and x for vertical text)
279             // because selectionRect uses selection-specific values.
280             if (box->isHorizontal()) {
281                 r.setHeight(box->height());
282                 r.setY(box->y());
283             } else {
284                 r.setWidth(box->width());
285                 r.setX(box->x());
286             }
287         }
288         return FloatRect(r);
289     }
290     return FloatRect();
291 }
292
293 void RenderText::absoluteRectsForRange(Vector<IntRect>& rects, unsigned start, unsigned end, bool useSelectionHeight, bool* wasFixed)
294 {
295     // Work around signed/unsigned issues. This function takes unsigneds, and is often passed UINT_MAX
296     // to mean "all the way to the end". InlineTextBox coordinates are unsigneds, so changing this 
297     // function to take ints causes various internal mismatches. But selectionRect takes ints, and 
298     // passing UINT_MAX to it causes trouble. Ideally we'd change selectionRect to take unsigneds, but 
299     // that would cause many ripple effects, so for now we'll just clamp our unsigned parameters to INT_MAX.
300     ASSERT(end == UINT_MAX || end <= INT_MAX);
301     ASSERT(start <= INT_MAX);
302     start = min(start, static_cast<unsigned>(INT_MAX));
303     end = min(end, static_cast<unsigned>(INT_MAX));
304     
305     for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) {
306         // Note: box->end() returns the index of the last character, not the index past it
307         if (start <= box->start() && box->end() < end) {
308             FloatRect r = box->calculateBoundaries();
309             if (useSelectionHeight) {
310                 LayoutRect selectionRect = box->localSelectionRect(start, end);
311                 if (box->isHorizontal()) {
312                     r.setHeight(selectionRect.height());
313                     r.setY(selectionRect.y());
314                 } else {
315                     r.setWidth(selectionRect.width());
316                     r.setX(selectionRect.x());
317                 }
318             }
319             rects.append(localToAbsoluteQuad(r, 0, wasFixed).enclosingBoundingBox());
320         } else {
321             // FIXME: This code is wrong. It's converting local to absolute twice. http://webkit.org/b/65722
322             FloatRect rect = localQuadForTextBox(box, start, end, useSelectionHeight);
323             if (!rect.isZero())
324                 rects.append(localToAbsoluteQuad(rect, 0, wasFixed).enclosingBoundingBox());
325         }
326     }
327 }
328
329 static IntRect ellipsisRectForBox(InlineTextBox* box, unsigned startPos, unsigned endPos)
330 {
331     if (!box)
332         return IntRect();
333     
334     unsigned short truncation = box->truncation();
335     if (truncation == cNoTruncation)
336         return IntRect();
337     
338     IntRect rect;
339     if (EllipsisBox* ellipsis = box->root().ellipsisBox()) {
340         int ellipsisStartPosition = max<int>(startPos - box->start(), 0);
341         int ellipsisEndPosition = min<int>(endPos - box->start(), box->len());
342         
343         // The ellipsis should be considered to be selected if the end of
344         // the selection is past the beginning of the truncation and the
345         // beginning of the selection is before or at the beginning of the truncation.
346         if (ellipsisEndPosition >= truncation && ellipsisStartPosition <= truncation)
347             return ellipsis->selectionRect();
348     }
349     
350     return IntRect();
351 }
352     
353 void RenderText::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed, ClippingOption option) const
354 {
355     for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) {
356         FloatRect boundaries = box->calculateBoundaries();
357
358         // Shorten the width of this text box if it ends in an ellipsis.
359         // FIXME: ellipsisRectForBox should switch to return FloatRect soon with the subpixellayout branch.
360         IntRect ellipsisRect = (option == ClipToEllipsis) ? ellipsisRectForBox(box, 0, textLength()) : IntRect();
361         if (!ellipsisRect.isEmpty()) {
362             if (style()->isHorizontalWritingMode())
363                 boundaries.setWidth(ellipsisRect.maxX() - boundaries.x());
364             else
365                 boundaries.setHeight(ellipsisRect.maxY() - boundaries.y());
366         }
367         quads.append(localToAbsoluteQuad(boundaries, 0, wasFixed));
368     }
369 }
370     
371 void RenderText::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed) const
372 {
373     absoluteQuads(quads, wasFixed, NoClipping);
374 }
375
376 void RenderText::absoluteQuadsForRange(Vector<FloatQuad>& quads, unsigned start, unsigned end, bool useSelectionHeight, bool* wasFixed)
377 {
378     // Work around signed/unsigned issues. This function takes unsigneds, and is often passed UINT_MAX
379     // to mean "all the way to the end". InlineTextBox coordinates are unsigneds, so changing this 
380     // function to take ints causes various internal mismatches. But selectionRect takes ints, and 
381     // passing UINT_MAX to it causes trouble. Ideally we'd change selectionRect to take unsigneds, but 
382     // that would cause many ripple effects, so for now we'll just clamp our unsigned parameters to INT_MAX.
383     ASSERT(end == UINT_MAX || end <= INT_MAX);
384     ASSERT(start <= INT_MAX);
385     start = min(start, static_cast<unsigned>(INT_MAX));
386     end = min(end, static_cast<unsigned>(INT_MAX));
387     
388     for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) {
389         // Note: box->end() returns the index of the last character, not the index past it
390         if (start <= box->start() && box->end() < end) {
391             FloatRect r = box->calculateBoundaries();
392             if (useSelectionHeight) {
393                 LayoutRect selectionRect = box->localSelectionRect(start, end);
394                 if (box->isHorizontal()) {
395                     r.setHeight(selectionRect.height());
396                     r.setY(selectionRect.y());
397                 } else {
398                     r.setWidth(selectionRect.width());
399                     r.setX(selectionRect.x());
400                 }
401             }
402             quads.append(localToAbsoluteQuad(r, 0, wasFixed));
403         } else {
404             FloatRect rect = localQuadForTextBox(box, start, end, useSelectionHeight);
405             if (!rect.isZero())
406                 quads.append(localToAbsoluteQuad(rect, 0, wasFixed));
407         }
408     }
409 }
410
411 enum ShouldAffinityBeDownstream { AlwaysDownstream, AlwaysUpstream, UpstreamIfPositionIsNotAtStart };
412
413 static bool lineDirectionPointFitsInBox(int pointLineDirection, InlineTextBox* box, ShouldAffinityBeDownstream& shouldAffinityBeDownstream)
414 {
415     shouldAffinityBeDownstream = AlwaysDownstream;
416
417     // the x coordinate is equal to the left edge of this box
418     // the affinity must be downstream so the position doesn't jump back to the previous line
419     // except when box is the first box in the line
420     if (pointLineDirection <= box->logicalLeft()) {
421         shouldAffinityBeDownstream = !box->prevLeafChild() ? UpstreamIfPositionIsNotAtStart : AlwaysDownstream;
422         return true;
423     }
424
425     // and the x coordinate is to the left of the right edge of this box
426     // check to see if position goes in this box
427     if (pointLineDirection < box->logicalRight()) {
428         shouldAffinityBeDownstream = UpstreamIfPositionIsNotAtStart;
429         return true;
430     }
431
432     // box is first on line
433     // and the x coordinate is to the left of the first text box left edge
434     if (!box->prevLeafChildIgnoringLineBreak() && pointLineDirection < box->logicalLeft())
435         return true;
436
437     if (!box->nextLeafChildIgnoringLineBreak()) {
438         // box is last on line
439         // and the x coordinate is to the right of the last text box right edge
440         // generate VisiblePosition, use UPSTREAM affinity if possible
441         shouldAffinityBeDownstream = UpstreamIfPositionIsNotAtStart;
442         return true;
443     }
444
445     return false;
446 }
447
448 static VisiblePosition createVisiblePositionForBox(const InlineBox* box, int offset, ShouldAffinityBeDownstream shouldAffinityBeDownstream)
449 {
450     EAffinity affinity = VP_DEFAULT_AFFINITY;
451     switch (shouldAffinityBeDownstream) {
452     case AlwaysDownstream:
453         affinity = DOWNSTREAM;
454         break;
455     case AlwaysUpstream:
456         affinity = VP_UPSTREAM_IF_POSSIBLE;
457         break;
458     case UpstreamIfPositionIsNotAtStart:
459         affinity = offset > box->caretMinOffset() ? VP_UPSTREAM_IF_POSSIBLE : DOWNSTREAM;
460         break;
461     }
462     return box->renderer().createVisiblePosition(offset, affinity);
463 }
464
465 static VisiblePosition createVisiblePositionAfterAdjustingOffsetForBiDi(const InlineTextBox* box, int offset, ShouldAffinityBeDownstream shouldAffinityBeDownstream)
466 {
467     ASSERT(box);
468     ASSERT(offset >= 0);
469
470     if (offset && static_cast<unsigned>(offset) < box->len())
471         return createVisiblePositionForBox(box, box->start() + offset, shouldAffinityBeDownstream);
472
473     bool positionIsAtStartOfBox = !offset;
474     if (positionIsAtStartOfBox == box->isLeftToRightDirection()) {
475         // offset is on the left edge
476
477         const InlineBox* prevBox = box->prevLeafChildIgnoringLineBreak();
478         if ((prevBox && prevBox->bidiLevel() == box->bidiLevel())
479             || box->renderer().containingBlock()->style()->direction() == box->direction()) // FIXME: left on 12CBA
480             return createVisiblePositionForBox(box, box->caretLeftmostOffset(), shouldAffinityBeDownstream);
481
482         if (prevBox && prevBox->bidiLevel() > box->bidiLevel()) {
483             // e.g. left of B in aDC12BAb
484             const InlineBox* leftmostBox;
485             do {
486                 leftmostBox = prevBox;
487                 prevBox = leftmostBox->prevLeafChildIgnoringLineBreak();
488             } while (prevBox && prevBox->bidiLevel() > box->bidiLevel());
489             return createVisiblePositionForBox(leftmostBox, leftmostBox->caretRightmostOffset(), shouldAffinityBeDownstream);
490         }
491
492         if (!prevBox || prevBox->bidiLevel() < box->bidiLevel()) {
493             // e.g. left of D in aDC12BAb
494             const InlineBox* rightmostBox;
495             const InlineBox* nextBox = box;
496             do {
497                 rightmostBox = nextBox;
498                 nextBox = rightmostBox->nextLeafChildIgnoringLineBreak();
499             } while (nextBox && nextBox->bidiLevel() >= box->bidiLevel());
500             return createVisiblePositionForBox(rightmostBox,
501                 box->isLeftToRightDirection() ? rightmostBox->caretMaxOffset() : rightmostBox->caretMinOffset(), shouldAffinityBeDownstream);
502         }
503
504         return createVisiblePositionForBox(box, box->caretRightmostOffset(), shouldAffinityBeDownstream);
505     }
506
507     const InlineBox* nextBox = box->nextLeafChildIgnoringLineBreak();
508     if ((nextBox && nextBox->bidiLevel() == box->bidiLevel())
509         || box->renderer().containingBlock()->style()->direction() == box->direction())
510         return createVisiblePositionForBox(box, box->caretRightmostOffset(), shouldAffinityBeDownstream);
511
512     // offset is on the right edge
513     if (nextBox && nextBox->bidiLevel() > box->bidiLevel()) {
514         // e.g. right of C in aDC12BAb
515         const InlineBox* rightmostBox;
516         do {
517             rightmostBox = nextBox;
518             nextBox = rightmostBox->nextLeafChildIgnoringLineBreak();
519         } while (nextBox && nextBox->bidiLevel() > box->bidiLevel());
520         return createVisiblePositionForBox(rightmostBox, rightmostBox->caretLeftmostOffset(), shouldAffinityBeDownstream);
521     }
522
523     if (!nextBox || nextBox->bidiLevel() < box->bidiLevel()) {
524         // e.g. right of A in aDC12BAb
525         const InlineBox* leftmostBox;
526         const InlineBox* prevBox = box;
527         do {
528             leftmostBox = prevBox;
529             prevBox = leftmostBox->prevLeafChildIgnoringLineBreak();
530         } while (prevBox && prevBox->bidiLevel() >= box->bidiLevel());
531         return createVisiblePositionForBox(leftmostBox,
532             box->isLeftToRightDirection() ? leftmostBox->caretMinOffset() : leftmostBox->caretMaxOffset(), shouldAffinityBeDownstream);
533     }
534
535     return createVisiblePositionForBox(box, box->caretLeftmostOffset(), shouldAffinityBeDownstream);
536 }
537
538 VisiblePosition RenderText::positionForPoint(const LayoutPoint& point)
539 {
540     if (!firstTextBox() || textLength() == 0)
541         return createVisiblePosition(0, DOWNSTREAM);
542
543     LayoutUnit pointLineDirection = firstTextBox()->isHorizontal() ? point.x() : point.y();
544     LayoutUnit pointBlockDirection = firstTextBox()->isHorizontal() ? point.y() : point.x();
545     bool blocksAreFlipped = style()->isFlippedBlocksWritingMode();
546
547     InlineTextBox* lastBox = 0;
548     for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) {
549         if (box->isLineBreak() && !box->prevLeafChild() && box->nextLeafChild() && !box->nextLeafChild()->isLineBreak())
550             box = box->nextTextBox();
551
552         const RootInlineBox& rootBox = box->root();
553         LayoutUnit top = min(rootBox.selectionTop(), rootBox.lineTop());
554         if (pointBlockDirection > top || (!blocksAreFlipped && pointBlockDirection == top)) {
555             LayoutUnit bottom = rootBox.selectionBottom();
556             if (rootBox.nextRootBox())
557                 bottom = min(bottom, rootBox.nextRootBox()->lineTop());
558
559             if (pointBlockDirection < bottom || (blocksAreFlipped && pointBlockDirection == bottom)) {
560                 ShouldAffinityBeDownstream shouldAffinityBeDownstream;
561                 if (lineDirectionPointFitsInBox(pointLineDirection, box, shouldAffinityBeDownstream))
562                     return createVisiblePositionAfterAdjustingOffsetForBiDi(box, box->offsetForPosition(pointLineDirection), shouldAffinityBeDownstream);
563             }
564         }
565         lastBox = box;
566     }
567
568     if (lastBox) {
569         ShouldAffinityBeDownstream shouldAffinityBeDownstream;
570         lineDirectionPointFitsInBox(pointLineDirection, lastBox, shouldAffinityBeDownstream);
571         return createVisiblePositionAfterAdjustingOffsetForBiDi(lastBox, lastBox->offsetForPosition(pointLineDirection) + lastBox->start(), shouldAffinityBeDownstream);
572     }
573     return createVisiblePosition(0, DOWNSTREAM);
574 }
575
576 LayoutRect RenderText::localCaretRect(InlineBox* inlineBox, int caretOffset, LayoutUnit* extraWidthToEndOfLine)
577 {
578     if (!inlineBox)
579         return LayoutRect();
580
581     InlineTextBox* box = toInlineTextBox(inlineBox);
582     float left = box->positionForOffset(caretOffset);
583     return box->root().computeCaretRect(left, caretWidth, extraWidthToEndOfLine);
584 }
585
586 ALWAYS_INLINE float RenderText::widthFromCache(const Font& f, int start, int len, float xPos, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
587 {
588     if (style()->hasTextCombine() && isCombineText()) {
589         const RenderCombineText& combineText = toRenderCombineText(*this);
590         if (combineText.isCombined())
591             return combineText.combinedTextWidth(f);
592     }
593
594     if (f.isFixedPitch() && !f.isSmallCaps() && m_isAllASCII && (!glyphOverflow || !glyphOverflow->computeBounds)) {
595         float monospaceCharacterWidth = f.spaceWidth();
596         float w = 0;
597         bool isSpace;
598         ASSERT(m_text);
599         StringImpl& text = *m_text.impl();
600         for (int i = start; i < start + len; i++) {
601             char c = text[i];
602             if (c <= ' ') {
603                 if (c == ' ' || c == '\n') {
604                     w += monospaceCharacterWidth;
605                     isSpace = true;
606                 } else if (c == '\t') {
607                     if (style()->collapseWhiteSpace()) {
608                         w += monospaceCharacterWidth;
609                         isSpace = true;
610                     } else {
611                         w += f.tabWidth(style()->tabSize(), xPos + w);
612                         isSpace = false;
613                     }
614                 } else
615                     isSpace = false;
616             } else {
617                 w += monospaceCharacterWidth;
618                 isSpace = false;
619             }
620             if (isSpace && i > start)
621                 w += f.wordSpacing();
622         }
623         return w;
624     }
625
626     TextRun run = RenderBlock::constructTextRun(const_cast<RenderText*>(this), f, this, start, len, *style());
627     run.setCharactersLength(textLength() - start);
628     ASSERT(run.charactersLength() >= run.length());
629
630     run.setCharacterScanForCodePath(!canUseSimpleFontCodePath());
631     run.setTabSize(!style()->collapseWhiteSpace(), style()->tabSize());
632     run.setXPos(xPos);
633     return f.width(run, fallbackFonts, glyphOverflow);
634 }
635
636 void RenderText::trimmedPrefWidths(float leadWidth,
637                                    float& beginMinW, bool& beginWS,
638                                    float& endMinW, bool& endWS,
639                                    bool& hasBreakableChar, bool& hasBreak,
640                                    float& beginMaxW, float& endMaxW,
641                                    float& minW, float& maxW, bool& stripFrontSpaces)
642 {
643     bool collapseWhiteSpace = style()->collapseWhiteSpace();
644     if (!collapseWhiteSpace)
645         stripFrontSpaces = false;
646
647     if (m_hasTab || preferredLogicalWidthsDirty())
648         computePreferredLogicalWidths(leadWidth);
649
650     beginWS = !stripFrontSpaces && m_hasBeginWS;
651     endWS = m_hasEndWS;
652
653     int len = textLength();
654
655     if (!len || (stripFrontSpaces && text()->containsOnlyWhitespace())) {
656         beginMinW = 0;
657         endMinW = 0;
658         beginMaxW = 0;
659         endMaxW = 0;
660         minW = 0;
661         maxW = 0;
662         hasBreak = false;
663         return;
664     }
665
666     minW = m_minWidth;
667     maxW = m_maxWidth;
668
669     beginMinW = m_beginMinWidth;
670     endMinW = m_endMinWidth;
671
672     hasBreakableChar = m_hasBreakableChar;
673     hasBreak = m_hasBreak;
674
675     ASSERT(m_text);
676     StringImpl& text = *m_text.impl();
677     if (text[0] == ' ' || (text[0] == '\n' && !style()->preserveNewline()) || text[0] == '\t') {
678         const Font& font = style()->font(); // FIXME: This ignores first-line.
679         if (stripFrontSpaces) {
680             const UChar space = ' ';
681             float spaceWidth = font.width(RenderBlock::constructTextRun(this, font, &space, 1, *style()));
682             maxW -= spaceWidth;
683         } else
684             maxW += font.wordSpacing();
685     }
686
687     stripFrontSpaces = collapseWhiteSpace && m_hasEndWS;
688
689     if (!style()->autoWrap() || minW > maxW)
690         minW = maxW;
691
692     // Compute our max widths by scanning the string for newlines.
693     if (hasBreak) {
694         const Font& f = style()->font(); // FIXME: This ignores first-line.
695         bool firstLine = true;
696         beginMaxW = maxW;
697         endMaxW = maxW;
698         for (int i = 0; i < len; i++) {
699             int linelen = 0;
700             while (i + linelen < len && text[i + linelen] != '\n')
701                 linelen++;
702
703             if (linelen) {
704                 endMaxW = widthFromCache(f, i, linelen, leadWidth + endMaxW, 0, 0);
705                 if (firstLine) {
706                     firstLine = false;
707                     leadWidth = 0;
708                     beginMaxW = endMaxW;
709                 }
710                 i += linelen;
711             } else if (firstLine) {
712                 beginMaxW = 0;
713                 firstLine = false;
714                 leadWidth = 0;
715             }
716
717             if (i == len - 1)
718                 // A <pre> run that ends with a newline, as in, e.g.,
719                 // <pre>Some text\n\n<span>More text</pre>
720                 endMaxW = 0;
721         }
722     }
723 }
724
725 static inline bool isSpaceAccordingToStyle(UChar c, const RenderStyle& style)
726 {
727     return c == ' ' || (c == noBreakSpace && style.nbspMode() == SPACE);
728 }
729
730 float RenderText::minLogicalWidth() const
731 {
732     if (preferredLogicalWidthsDirty())
733         const_cast<RenderText*>(this)->computePreferredLogicalWidths(0);
734         
735     return m_minWidth;
736 }
737
738 float RenderText::maxLogicalWidth() const
739 {
740     if (preferredLogicalWidthsDirty())
741         const_cast<RenderText*>(this)->computePreferredLogicalWidths(0);
742         
743     return m_maxWidth;
744 }
745
746 void RenderText::computePreferredLogicalWidths(float leadWidth)
747 {
748     HashSet<const SimpleFontData*> fallbackFonts;
749     GlyphOverflow glyphOverflow;
750     computePreferredLogicalWidths(leadWidth, fallbackFonts, glyphOverflow);
751     if (fallbackFonts.isEmpty() && !glyphOverflow.left && !glyphOverflow.right && !glyphOverflow.top && !glyphOverflow.bottom)
752         m_knownToHaveNoOverflowAndNoFallbackFonts = true;
753 }
754
755 static inline float hyphenWidth(RenderText* renderer, const Font& font)
756 {
757     RenderStyle* style = renderer->style();
758     return font.width(RenderBlock::constructTextRun(renderer, font, style->hyphenString().string(), *style));
759 }
760
761 static float maxWordFragmentWidth(RenderText* renderer, const RenderStyle& style, const Font& font, const UChar* word, int wordLength, int minimumPrefixLength, int minimumSuffixLength, int& suffixStart, HashSet<const SimpleFontData*>& fallbackFonts, GlyphOverflow& glyphOverflow)
762 {
763     suffixStart = 0;
764     if (wordLength <= minimumSuffixLength)
765         return 0;
766
767     Vector<int, 8> hyphenLocations;
768     int hyphenLocation = wordLength - minimumSuffixLength;
769     while ((hyphenLocation = lastHyphenLocation(word, wordLength, hyphenLocation, style.locale())) >= minimumPrefixLength)
770         hyphenLocations.append(hyphenLocation);
771
772     if (hyphenLocations.isEmpty())
773         return 0;
774
775     hyphenLocations.reverse();
776
777     float minimumFragmentWidthToConsider = font.pixelSize() * 5 / 4 + hyphenWidth(renderer, font);
778     float maxFragmentWidth = 0;
779     for (size_t k = 0; k < hyphenLocations.size(); ++k) {
780         int fragmentLength = hyphenLocations[k] - suffixStart;
781         StringBuilder fragmentWithHyphen;
782         fragmentWithHyphen.append(word + suffixStart, fragmentLength);
783         fragmentWithHyphen.append(style.hyphenString());
784
785         TextRun run = RenderBlock::constructTextRun(renderer, font, fragmentWithHyphen.characters(), fragmentWithHyphen.length(), style);
786         run.setCharactersLength(fragmentWithHyphen.length());
787         run.setCharacterScanForCodePath(!renderer->canUseSimpleFontCodePath());
788         float fragmentWidth = font.width(run, &fallbackFonts, &glyphOverflow);
789
790         // Narrow prefixes are ignored. See tryHyphenating in RenderBlockLineLayout.cpp.
791         if (fragmentWidth <= minimumFragmentWidthToConsider)
792             continue;
793
794         suffixStart += fragmentLength;
795         maxFragmentWidth = max(maxFragmentWidth, fragmentWidth);
796     }
797
798     return maxFragmentWidth;
799 }
800
801 void RenderText::computePreferredLogicalWidths(float leadWidth, HashSet<const SimpleFontData*>& fallbackFonts, GlyphOverflow& glyphOverflow)
802 {
803     ASSERT(m_hasTab || preferredLogicalWidthsDirty() || !m_knownToHaveNoOverflowAndNoFallbackFonts);
804
805     m_minWidth = 0;
806     m_beginMinWidth = 0;
807     m_endMinWidth = 0;
808     m_maxWidth = 0;
809
810     float currMinWidth = 0;
811     float currMaxWidth = 0;
812     m_hasBreakableChar = false;
813     m_hasBreak = false;
814     m_hasTab = false;
815     m_hasBeginWS = false;
816     m_hasEndWS = false;
817
818     const RenderStyle& style = *this->style();
819     const Font& f = style.font(); // FIXME: This ignores first-line.
820     float wordSpacing = style.wordSpacing();
821     int len = textLength();
822     LazyLineBreakIterator breakIterator(m_text, style.locale());
823     bool needsWordSpacing = false;
824     bool ignoringSpaces = false;
825     bool isSpace = false;
826     bool firstWord = true;
827     bool firstLine = true;
828     int nextBreakable = -1;
829     int lastWordBoundary = 0;
830
831     // Non-zero only when kerning is enabled, in which case we measure words with their trailing
832     // space, then subtract its width.
833     float wordTrailingSpaceWidth = f.typesettingFeatures() & Kerning ? f.width(RenderBlock::constructTextRun(this, f, &space, 1, style), &fallbackFonts) + wordSpacing : 0;
834
835     // If automatic hyphenation is allowed, we keep track of the width of the widest word (or word
836     // fragment) encountered so far, and only try hyphenating words that are wider.
837     float maxWordWidth = numeric_limits<float>::max();
838     int minimumPrefixLength = 0;
839     int minimumSuffixLength = 0;
840     if (style.hyphens() == HyphensAuto && canHyphenate(style.locale())) {
841         maxWordWidth = 0;
842
843         // Map 'hyphenate-limit-{before,after}: auto;' to 2.
844         minimumPrefixLength = style.hyphenationLimitBefore();
845         if (minimumPrefixLength < 0)
846             minimumPrefixLength = 2;
847
848         minimumSuffixLength = style.hyphenationLimitAfter();
849         if (minimumSuffixLength < 0)
850             minimumSuffixLength = 2;
851     }
852
853     int firstGlyphLeftOverflow = -1;
854
855     bool breakNBSP = style.autoWrap() && style.nbspMode() == SPACE;
856     bool breakAll = (style.wordBreak() == BreakAllWordBreak || style.wordBreak() == BreakWordBreak) && style.autoWrap();
857
858     for (int i = 0; i < len; i++) {
859         UChar c = characterAt(i);
860
861         bool previousCharacterIsSpace = isSpace;
862
863         bool isNewline = false;
864         if (c == '\n') {
865             if (style.preserveNewline()) {
866                 m_hasBreak = true;
867                 isNewline = true;
868                 isSpace = false;
869             } else
870                 isSpace = true;
871         } else if (c == '\t') {
872             if (!style.collapseWhiteSpace()) {
873                 m_hasTab = true;
874                 isSpace = false;
875             } else
876                 isSpace = true;
877         } else
878             isSpace = c == ' ';
879
880         if ((isSpace || isNewline) && !i)
881             m_hasBeginWS = true;
882         if ((isSpace || isNewline) && i == len - 1)
883             m_hasEndWS = true;
884
885         if (!ignoringSpaces && style.collapseWhiteSpace() && previousCharacterIsSpace && isSpace)
886             ignoringSpaces = true;
887
888         if (ignoringSpaces && !isSpace)
889             ignoringSpaces = false;
890
891         // Ignore spaces and soft hyphens
892         if (ignoringSpaces) {
893             ASSERT(lastWordBoundary == i);
894             lastWordBoundary++;
895             continue;
896         } else if (c == softHyphen && style.hyphens() != HyphensNone) {
897             currMaxWidth += widthFromCache(f, lastWordBoundary, i - lastWordBoundary, leadWidth + currMaxWidth, &fallbackFonts, &glyphOverflow);
898             if (firstGlyphLeftOverflow < 0)
899                 firstGlyphLeftOverflow = glyphOverflow.left;
900             lastWordBoundary = i + 1;
901             continue;
902         }
903
904         bool hasBreak = breakAll || isBreakable(breakIterator, i, nextBreakable, breakNBSP);
905         bool betweenWords = true;
906         int j = i;
907         while (c != '\n' && !isSpaceAccordingToStyle(c, style) && c != '\t' && (c != softHyphen || style.hyphens() == HyphensNone)) {
908             j++;
909             if (j == len)
910                 break;
911             c = characterAt(j);
912             if (isBreakable(breakIterator, j, nextBreakable, breakNBSP) && characterAt(j - 1) != softHyphen)
913                 break;
914             if (breakAll) {
915                 betweenWords = false;
916                 break;
917             }
918         }
919
920         int wordLen = j - i;
921         if (wordLen) {
922             bool isSpace = (j < len) && isSpaceAccordingToStyle(c, style);
923             float w;
924             if (wordTrailingSpaceWidth && isSpace)
925                 w = widthFromCache(f, i, wordLen + 1, leadWidth + currMaxWidth, &fallbackFonts, &glyphOverflow) - wordTrailingSpaceWidth;
926             else {
927                 w = widthFromCache(f, i, wordLen, leadWidth + currMaxWidth, &fallbackFonts, &glyphOverflow);
928                 if (c == softHyphen && style.hyphens() != HyphensNone)
929                     currMinWidth += hyphenWidth(this, f);
930             }
931
932             if (w > maxWordWidth) {
933                 int suffixStart;
934                 float maxFragmentWidth = maxWordFragmentWidth(this, style, f, characters() + i, wordLen, minimumPrefixLength, minimumSuffixLength, suffixStart, fallbackFonts, glyphOverflow);
935
936                 if (suffixStart) {
937                     float suffixWidth;
938                     if (wordTrailingSpaceWidth && isSpace)
939                         suffixWidth = widthFromCache(f, i + suffixStart, wordLen - suffixStart + 1, leadWidth + currMaxWidth, 0, 0) - wordTrailingSpaceWidth;
940                     else
941                         suffixWidth = widthFromCache(f, i + suffixStart, wordLen - suffixStart, leadWidth + currMaxWidth, 0, 0);
942
943                     maxFragmentWidth = max(maxFragmentWidth, suffixWidth);
944
945                     currMinWidth += maxFragmentWidth - w;
946                     maxWordWidth = max(maxWordWidth, maxFragmentWidth);
947                 } else
948                     maxWordWidth = w;
949             }
950
951             if (firstGlyphLeftOverflow < 0)
952                 firstGlyphLeftOverflow = glyphOverflow.left;
953             currMinWidth += w;
954             if (betweenWords) {
955                 if (lastWordBoundary == i)
956                     currMaxWidth += w;
957                 else
958                     currMaxWidth += widthFromCache(f, lastWordBoundary, j - lastWordBoundary, leadWidth + currMaxWidth, &fallbackFonts, &glyphOverflow);
959                 lastWordBoundary = j;
960             }
961
962             bool isCollapsibleWhiteSpace = (j < len) && style.isCollapsibleWhiteSpace(c);
963             if (j < len && style.autoWrap())
964                 m_hasBreakableChar = true;
965
966             // Add in wordSpacing to our currMaxWidth, but not if this is the last word on a line or the
967             // last word in the run.
968             if (wordSpacing && (isSpace || isCollapsibleWhiteSpace) && !containsOnlyWhitespace(j, len-j))
969                 currMaxWidth += wordSpacing;
970
971             if (firstWord) {
972                 firstWord = false;
973                 // If the first character in the run is breakable, then we consider ourselves to have a beginning
974                 // minimum width of 0, since a break could occur right before our run starts, preventing us from ever
975                 // being appended to a previous text run when considering the total minimum width of the containing block.
976                 if (hasBreak)
977                     m_hasBreakableChar = true;
978                 m_beginMinWidth = hasBreak ? 0 : currMinWidth;
979             }
980             m_endMinWidth = currMinWidth;
981
982             if (currMinWidth > m_minWidth)
983                 m_minWidth = currMinWidth;
984             currMinWidth = 0;
985
986             i += wordLen - 1;
987         } else {
988             // Nowrap can never be broken, so don't bother setting the
989             // breakable character boolean. Pre can only be broken if we encounter a newline.
990             if (style.autoWrap() || isNewline)
991                 m_hasBreakableChar = true;
992
993             if (currMinWidth > m_minWidth)
994                 m_minWidth = currMinWidth;
995             currMinWidth = 0;
996
997             if (isNewline) { // Only set if preserveNewline was true and we saw a newline.
998                 if (firstLine) {
999                     firstLine = false;
1000                     leadWidth = 0;
1001                     if (!style.autoWrap())
1002                         m_beginMinWidth = currMaxWidth;
1003                 }
1004
1005                 if (currMaxWidth > m_maxWidth)
1006                     m_maxWidth = currMaxWidth;
1007                 currMaxWidth = 0;
1008             } else {
1009                 TextRun run = RenderBlock::constructTextRun(this, f, this, i, 1, style);
1010                 run.setCharactersLength(len - i);
1011                 ASSERT(run.charactersLength() >= run.length());
1012                 run.setTabSize(!style.collapseWhiteSpace(), style.tabSize());
1013                 run.setXPos(leadWidth + currMaxWidth);
1014
1015                 currMaxWidth += f.width(run, &fallbackFonts);
1016                 glyphOverflow.right = 0;
1017                 needsWordSpacing = isSpace && !previousCharacterIsSpace && i == len - 1;
1018             }
1019             ASSERT(lastWordBoundary == i);
1020             lastWordBoundary++;
1021         }
1022     }
1023
1024     if (firstGlyphLeftOverflow > 0)
1025         glyphOverflow.left = firstGlyphLeftOverflow;
1026
1027     if ((needsWordSpacing && len > 1) || (ignoringSpaces && !firstWord))
1028         currMaxWidth += wordSpacing;
1029
1030     m_minWidth = max(currMinWidth, m_minWidth);
1031     m_maxWidth = max(currMaxWidth, m_maxWidth);
1032
1033     if (!style.autoWrap())
1034         m_minWidth = m_maxWidth;
1035
1036     if (style.whiteSpace() == PRE) {
1037         if (firstLine)
1038             m_beginMinWidth = m_maxWidth;
1039         m_endMinWidth = currMaxWidth;
1040     }
1041
1042     setPreferredLogicalWidthsDirty(false);
1043 }
1044
1045 bool RenderText::isAllCollapsibleWhitespace() const
1046 {
1047     unsigned length = textLength();
1048     if (is8Bit()) {
1049         for (unsigned i = 0; i < length; ++i) {
1050             if (!style()->isCollapsibleWhiteSpace(characters8()[i]))
1051                 return false;
1052         }
1053         return true;
1054     }
1055     for (unsigned i = 0; i < length; ++i) {
1056         if (!style()->isCollapsibleWhiteSpace(characters16()[i]))
1057             return false;
1058     }
1059     return true;
1060 }
1061     
1062 bool RenderText::containsOnlyWhitespace(unsigned from, unsigned len) const
1063 {
1064     ASSERT(m_text);
1065     StringImpl& text = *m_text.impl();
1066     unsigned currPos;
1067     for (currPos = from;
1068          currPos < from + len && (text[currPos] == '\n' || text[currPos] == ' ' || text[currPos] == '\t');
1069          currPos++) { }
1070     return currPos >= (from + len);
1071 }
1072
1073 FloatPoint RenderText::firstRunOrigin() const
1074 {
1075     return IntPoint(firstRunX(), firstRunY());
1076 }
1077
1078 float RenderText::firstRunX() const
1079 {
1080     return firstTextBox() ? firstTextBox()->x() : 0;
1081 }
1082
1083 float RenderText::firstRunY() const
1084 {
1085     return firstTextBox() ? firstTextBox()->y() : 0;
1086 }
1087     
1088 void RenderText::setSelectionState(SelectionState state)
1089 {
1090     RenderObject::setSelectionState(state);
1091
1092     if (canUpdateSelectionOnRootLineBoxes()) {
1093         if (state == SelectionStart || state == SelectionEnd || state == SelectionBoth) {
1094             int startPos, endPos;
1095             selectionStartEnd(startPos, endPos);
1096             if (selectionState() == SelectionStart) {
1097                 endPos = textLength();
1098
1099                 // to handle selection from end of text to end of line
1100                 if (startPos && startPos == endPos)
1101                     startPos = endPos - 1;
1102             } else if (selectionState() == SelectionEnd)
1103                 startPos = 0;
1104
1105             for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) {
1106                 if (box->isSelected(startPos, endPos))
1107                     box->root().setHasSelectedChildren(true);
1108             }
1109         } else {
1110             for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) {
1111                 box->root().setHasSelectedChildren(state == SelectionInside);
1112             }
1113         }
1114     }
1115
1116     // The containing block can be null in case of an orphaned tree.
1117     RenderBlock* containingBlock = this->containingBlock();
1118     if (containingBlock && !containingBlock->isRenderView())
1119         containingBlock->setSelectionState(state);
1120 }
1121
1122 void RenderText::setTextWithOffset(const String& text, unsigned offset, unsigned len, bool force)
1123 {
1124     if (!force && m_text == text)
1125         return;
1126
1127     unsigned oldLen = textLength();
1128     unsigned newLen = text.length();
1129     int delta = newLen - oldLen;
1130     unsigned end = len ? offset + len - 1 : offset;
1131
1132     RootInlineBox* firstRootBox = 0;
1133     RootInlineBox* lastRootBox = 0;
1134
1135     bool dirtiedLines = false;
1136
1137     // Dirty all text boxes that include characters in between offset and offset+len.
1138     for (InlineTextBox* curr = firstTextBox(); curr; curr = curr->nextTextBox()) {
1139         // FIXME: This shouldn't rely on the end of a dirty line box. See https://bugs.webkit.org/show_bug.cgi?id=97264
1140         // Text run is entirely before the affected range.
1141         if (curr->end() < offset)
1142             continue;
1143
1144         // Text run is entirely after the affected range.
1145         if (curr->start() > end) {
1146             curr->offsetRun(delta);
1147             RootInlineBox& rootBox = curr->root();
1148             if (!firstRootBox) {
1149                 firstRootBox = &rootBox;
1150                 if (!dirtiedLines) {
1151                     // The affected area was in between two runs. Go ahead and mark the root box of
1152                     // the run after the affected area as dirty.
1153                     firstRootBox->markDirty();
1154                     dirtiedLines = true;
1155                 }
1156             }
1157             lastRootBox = &rootBox;
1158         } else if (curr->end() >= offset && curr->end() <= end) {
1159             // Text run overlaps with the left end of the affected range.
1160             curr->dirtyLineBoxes();
1161             dirtiedLines = true;
1162         } else if (curr->start() <= offset && curr->end() >= end) {
1163             // Text run subsumes the affected range.
1164             curr->dirtyLineBoxes();
1165             dirtiedLines = true;
1166         } else if (curr->start() <= end && curr->end() >= end) {
1167             // Text run overlaps with right end of the affected range.
1168             curr->dirtyLineBoxes();
1169             dirtiedLines = true;
1170         }
1171     }
1172
1173     // Now we have to walk all of the clean lines and adjust their cached line break information
1174     // to reflect our updated offsets.
1175     if (lastRootBox)
1176         lastRootBox = lastRootBox->nextRootBox();
1177     if (firstRootBox) {
1178         RootInlineBox* prev = firstRootBox->prevRootBox();
1179         if (prev)
1180             firstRootBox = prev;
1181     } else if (lastTextBox()) {
1182         ASSERT(!lastRootBox);
1183         firstRootBox = &lastTextBox()->root();
1184         firstRootBox->markDirty();
1185         dirtiedLines = true;
1186     }
1187     for (RootInlineBox* curr = firstRootBox; curr && curr != lastRootBox; curr = curr->nextRootBox()) {
1188         if (curr->lineBreakObj() == this && curr->lineBreakPos() > end)
1189             curr->setLineBreakPos(curr->lineBreakPos() + delta);
1190     }
1191
1192     // If the text node is empty, dirty the line where new text will be inserted.
1193     if (!firstTextBox() && parent()) {
1194         parent()->dirtyLinesFromChangedChild(this);
1195         dirtiedLines = true;
1196     }
1197
1198     m_linesDirty = dirtiedLines;
1199     setText(text, force || dirtiedLines);
1200 }
1201
1202 void RenderText::transformText()
1203 {
1204     String textToTransform = originalText();
1205     if (!textToTransform.isNull())
1206         setText(textToTransform, true);
1207 }
1208
1209 static inline bool isInlineFlowOrEmptyText(const RenderObject* o)
1210 {
1211     if (o->isRenderInline())
1212         return true;
1213     if (!o->isText())
1214         return false;
1215     StringImpl* text = toRenderText(o)->text();
1216     if (!text)
1217         return true;
1218     return !text->length();
1219 }
1220
1221 UChar RenderText::previousCharacter() const
1222 {
1223     // find previous text renderer if one exists
1224     const RenderObject* previousText = this;
1225     while ((previousText = previousText->previousInPreOrder()))
1226         if (!isInlineFlowOrEmptyText(previousText))
1227             break;
1228     UChar prev = ' ';
1229     if (previousText && previousText->isText())
1230         if (StringImpl* previousString = toRenderText(previousText)->text())
1231             prev = (*previousString)[previousString->length() - 1];
1232     return prev;
1233 }
1234
1235 void applyTextTransform(const RenderStyle* style, String& text, UChar previousCharacter)
1236 {
1237     if (!style)
1238         return;
1239
1240     switch (style->textTransform()) {
1241     case TTNONE:
1242         break;
1243     case CAPITALIZE:
1244         makeCapitalized(&text, previousCharacter);
1245         break;
1246     case UPPERCASE:
1247         text = text.upper(style->locale());
1248         break;
1249     case LOWERCASE:
1250         text = text.lower(style->locale());
1251         break;
1252     }
1253 }
1254
1255 void RenderText::setTextInternal(const String& text)
1256 {
1257     ASSERT(!text.isNull());
1258     m_text = text;
1259
1260     if (m_useBackslashAsYenSymbol)
1261         m_text.replace('\\', yenSign);
1262
1263     ASSERT(m_text);
1264
1265     if (style()) {
1266         applyTextTransform(style(), m_text, previousCharacter());
1267
1268         // We use the same characters here as for list markers.
1269         // See the listMarkerText function in RenderListMarker.cpp.
1270         switch (style()->textSecurity()) {
1271         case TSNONE:
1272             break;
1273         case TSCIRCLE:
1274             secureText(whiteBullet);
1275             break;
1276         case TSDISC:
1277             secureText(bullet);
1278             break;
1279         case TSSQUARE:
1280             secureText(blackSquare);
1281         }
1282     }
1283
1284     ASSERT(!m_text.isNull());
1285
1286     m_isAllASCII = m_text.containsOnlyASCII();
1287     m_canUseSimpleFontCodePath = computeCanUseSimpleFontCodePath();
1288 }
1289
1290 void RenderText::secureText(UChar mask)
1291 {
1292     if (!m_text.length())
1293         return;
1294
1295     int lastTypedCharacterOffsetToReveal = -1;
1296     String revealedText;
1297     SecureTextTimer* secureTextTimer = gSecureTextTimers ? gSecureTextTimers->get(this) : 0;
1298     if (secureTextTimer && secureTextTimer->isActive()) {
1299         lastTypedCharacterOffsetToReveal = secureTextTimer->lastTypedCharacterOffset();
1300         if (lastTypedCharacterOffsetToReveal >= 0)
1301             revealedText.append(m_text[lastTypedCharacterOffsetToReveal]);
1302     }
1303
1304     m_text.fill(mask);
1305     if (lastTypedCharacterOffsetToReveal >= 0) {
1306         m_text.replace(lastTypedCharacterOffsetToReveal, 1, revealedText);
1307         // m_text may be updated later before timer fires. We invalidate the lastTypedCharacterOffset to avoid inconsistency.
1308         secureTextTimer->invalidate();
1309     }
1310 }
1311
1312 void RenderText::setText(const String& text, bool force)
1313 {
1314     ASSERT(!text.isNull());
1315
1316     if (!force && m_text == text)
1317         return;
1318
1319     setTextInternal(text);
1320     setNeedsLayoutAndPrefWidthsRecalc();
1321     m_knownToHaveNoOverflowAndNoFallbackFonts = false;
1322     
1323     if (AXObjectCache* cache = document().existingAXObjectCache())
1324         cache->textChanged(this);
1325 }
1326
1327 String RenderText::textWithoutConvertingBackslashToYenSymbol() const
1328 {
1329     if (!m_useBackslashAsYenSymbol || style()->textSecurity() != TSNONE)
1330         return text();
1331
1332     String text = originalText();
1333     applyTextTransform(style(), text, previousCharacter());
1334     return text;
1335 }
1336
1337 void RenderText::dirtyLineBoxes(bool fullLayout)
1338 {
1339     if (fullLayout)
1340         m_lineBoxes.deleteAll(*this);
1341     else if (!m_linesDirty) {
1342         for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox())
1343             box->dirtyLineBoxes();
1344     }
1345     m_linesDirty = false;
1346 }
1347
1348 InlineTextBox* RenderText::createTextBox()
1349 {
1350     return new (renderArena()) InlineTextBox(*this);
1351 }
1352
1353 void RenderText::positionLineBox(InlineBox* box)
1354 {
1355     InlineTextBox* textBox = toInlineTextBox(box);
1356
1357     // FIXME: should not be needed!!!
1358     if (!textBox->len()) {
1359         // We want the box to be destroyed.
1360         textBox->remove();
1361         m_lineBoxes.remove(*textBox);
1362         textBox->destroy(renderArena());
1363         return;
1364     }
1365
1366     m_containsReversedText |= !textBox->isLeftToRightDirection();
1367 }
1368
1369 float RenderText::width(unsigned from, unsigned len, float xPos, bool firstLine, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
1370 {
1371     if (from >= textLength())
1372         return 0;
1373
1374     if (from + len > textLength())
1375         len = textLength() - from;
1376
1377     const RenderStyle& lineStyle = firstLine ? *firstLineStyle() : *style();
1378     return width(from, len, lineStyle.font(), xPos, fallbackFonts, glyphOverflow);
1379 }
1380
1381 float RenderText::width(unsigned from, unsigned len, const Font& f, float xPos, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
1382 {
1383     ASSERT(from + len <= textLength());
1384     if (!textLength())
1385         return 0;
1386
1387     float w;
1388     if (&f == &style()->font()) {
1389         if (!style()->preserveNewline() && !from && len == textLength() && (!glyphOverflow || !glyphOverflow->computeBounds)) {
1390             if (fallbackFonts) {
1391                 ASSERT(glyphOverflow);
1392                 if (preferredLogicalWidthsDirty() || !m_knownToHaveNoOverflowAndNoFallbackFonts) {
1393                     const_cast<RenderText*>(this)->computePreferredLogicalWidths(0, *fallbackFonts, *glyphOverflow);
1394                     if (fallbackFonts->isEmpty() && !glyphOverflow->left && !glyphOverflow->right && !glyphOverflow->top && !glyphOverflow->bottom)
1395                         m_knownToHaveNoOverflowAndNoFallbackFonts = true;
1396                 }
1397                 w = m_maxWidth;
1398             } else
1399                 w = maxLogicalWidth();
1400         } else
1401             w = widthFromCache(f, from, len, xPos, fallbackFonts, glyphOverflow);
1402     } else {
1403         TextRun run = RenderBlock::constructTextRun(const_cast<RenderText*>(this), f, this, from, len, *style());
1404         run.setCharactersLength(textLength() - from);
1405         ASSERT(run.charactersLength() >= run.length());
1406
1407         run.setCharacterScanForCodePath(!canUseSimpleFontCodePath());
1408         run.setTabSize(!style()->collapseWhiteSpace(), style()->tabSize());
1409         run.setXPos(xPos);
1410         w = f.width(run, fallbackFonts, glyphOverflow);
1411     }
1412
1413     return w;
1414 }
1415
1416 IntRect RenderText::linesBoundingBox() const
1417 {
1418     return m_lineBoxes.boundingBox(*this);
1419 }
1420
1421 LayoutRect RenderText::linesVisualOverflowBoundingBox() const
1422 {
1423     return m_lineBoxes.visualOverflowBoundingBox(*this);
1424 }
1425
1426 LayoutRect RenderText::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const
1427 {
1428     RenderObject* rendererToRepaint = containingBlock();
1429
1430     // Do not cross self-painting layer boundaries.
1431     RenderObject& enclosingLayerRenderer = enclosingLayer()->renderer();
1432     if (&enclosingLayerRenderer != rendererToRepaint && !rendererToRepaint->isDescendantOf(&enclosingLayerRenderer))
1433         rendererToRepaint = &enclosingLayerRenderer;
1434
1435     // The renderer we chose to repaint may be an ancestor of repaintContainer, but we need to do a repaintContainer-relative repaint.
1436     if (repaintContainer && repaintContainer != rendererToRepaint && !rendererToRepaint->isDescendantOf(repaintContainer))
1437         return repaintContainer->clippedOverflowRectForRepaint(repaintContainer);
1438
1439     return rendererToRepaint->clippedOverflowRectForRepaint(repaintContainer);
1440 }
1441
1442 LayoutRect RenderText::selectionRectForRepaint(const RenderLayerModelObject* repaintContainer, bool clipToVisibleContent)
1443 {
1444     ASSERT(!needsLayout());
1445
1446     if (selectionState() == SelectionNone)
1447         return LayoutRect();
1448     RenderBlock* cb = containingBlock();
1449     if (!cb)
1450         return LayoutRect();
1451
1452     // Now calculate startPos and endPos for painting selection.
1453     // We include a selection while endPos > 0
1454     int startPos, endPos;
1455     if (selectionState() == SelectionInside) {
1456         // We are fully selected.
1457         startPos = 0;
1458         endPos = textLength();
1459     } else {
1460         selectionStartEnd(startPos, endPos);
1461         if (selectionState() == SelectionStart)
1462             endPos = textLength();
1463         else if (selectionState() == SelectionEnd)
1464             startPos = 0;
1465     }
1466
1467     if (startPos == endPos)
1468         return IntRect();
1469
1470     LayoutRect rect;
1471     for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) {
1472         rect.unite(box->localSelectionRect(startPos, endPos));
1473         rect.unite(ellipsisRectForBox(box, startPos, endPos));
1474     }
1475
1476     if (clipToVisibleContent)
1477         computeRectForRepaint(repaintContainer, rect);
1478     else {
1479         if (cb->hasColumns())
1480             cb->adjustRectForColumns(rect);
1481
1482         rect = localToContainerQuad(FloatRect(rect), repaintContainer).enclosingBoundingBox();
1483     }
1484
1485     return rect;
1486 }
1487
1488 int RenderText::caretMinOffset() const
1489 {
1490     return m_lineBoxes.caretMinOffset();
1491 }
1492
1493 int RenderText::caretMaxOffset() const
1494 {
1495     return m_lineBoxes.caretMaxOffset(*this);
1496 }
1497
1498 bool RenderText::hasRenderedText() const
1499 {
1500     return m_lineBoxes.hasRenderedText();
1501 }
1502
1503 int RenderText::previousOffset(int current) const
1504 {
1505     if (isAllASCII() || m_text.is8Bit())
1506         return current - 1;
1507
1508     StringImpl* textImpl = m_text.impl();
1509     TextBreakIterator* iterator = cursorMovementIterator(textImpl->characters16(), textImpl->length());
1510     if (!iterator)
1511         return current - 1;
1512
1513     long result = textBreakPreceding(iterator, current);
1514     if (result == TextBreakDone)
1515         result = current - 1;
1516
1517
1518     return result;
1519 }
1520
1521 #if PLATFORM(MAC) || PLATFORM(EFL)
1522
1523 #define HANGUL_CHOSEONG_START (0x1100)
1524 #define HANGUL_CHOSEONG_END (0x115F)
1525 #define HANGUL_JUNGSEONG_START (0x1160)
1526 #define HANGUL_JUNGSEONG_END (0x11A2)
1527 #define HANGUL_JONGSEONG_START (0x11A8)
1528 #define HANGUL_JONGSEONG_END (0x11F9)
1529 #define HANGUL_SYLLABLE_START (0xAC00)
1530 #define HANGUL_SYLLABLE_END (0xD7AF)
1531 #define HANGUL_JONGSEONG_COUNT (28)
1532
1533 enum HangulState {
1534     HangulStateL,
1535     HangulStateV,
1536     HangulStateT,
1537     HangulStateLV,
1538     HangulStateLVT,
1539     HangulStateBreak
1540 };
1541
1542 inline bool isHangulLVT(UChar32 character)
1543 {
1544     return (character - HANGUL_SYLLABLE_START) % HANGUL_JONGSEONG_COUNT;
1545 }
1546
1547 inline bool isMark(UChar32 c)
1548 {
1549     int8_t charType = u_charType(c);
1550     return charType == U_NON_SPACING_MARK || charType == U_ENCLOSING_MARK || charType == U_COMBINING_SPACING_MARK;
1551 }
1552
1553 inline bool isRegionalIndicator(UChar32 c)
1554 {
1555     // National flag emoji each consists of a pair of regional indicator symbols.
1556     return 0x1F1E6 <= c && c <= 0x1F1FF;
1557 }
1558
1559 #endif
1560
1561 int RenderText::previousOffsetForBackwardDeletion(int current) const
1562 {
1563 #if PLATFORM(MAC) || PLATFORM(EFL)
1564     ASSERT(m_text);
1565     StringImpl& text = *m_text.impl();
1566     UChar32 character;
1567     bool sawRegionalIndicator = false;
1568     while (current > 0) {
1569         if (U16_IS_TRAIL(text[--current]))
1570             --current;
1571         if (current < 0)
1572             break;
1573
1574         UChar32 character = text.characterStartingAt(current);
1575
1576         if (sawRegionalIndicator) {
1577             // We don't check if the pair of regional indicator symbols before current position can actually be combined
1578             // into a flag, and just delete it. This may not agree with how the pair is rendered in edge cases,
1579             // but is good enough in practice.
1580             if (isRegionalIndicator(character))
1581                 break;
1582             // Don't delete a preceding character that isn't a regional indicator symbol.
1583             U16_FWD_1_UNSAFE(text, current);
1584         }
1585
1586         // We don't combine characters in Armenian ... Limbu range for backward deletion.
1587         if ((character >= 0x0530) && (character < 0x1950))
1588             break;
1589
1590         if (isRegionalIndicator(character)) {
1591             sawRegionalIndicator = true;
1592             continue;
1593         }
1594
1595         if (!isMark(character) && (character != 0xFF9E) && (character != 0xFF9F))
1596             break;
1597     }
1598
1599     if (current <= 0)
1600         return current;
1601
1602     // Hangul
1603     character = text.characterStartingAt(current);
1604     if (((character >= HANGUL_CHOSEONG_START) && (character <= HANGUL_JONGSEONG_END)) || ((character >= HANGUL_SYLLABLE_START) && (character <= HANGUL_SYLLABLE_END))) {
1605         HangulState state;
1606
1607         if (character < HANGUL_JUNGSEONG_START)
1608             state = HangulStateL;
1609         else if (character < HANGUL_JONGSEONG_START)
1610             state = HangulStateV;
1611         else if (character < HANGUL_SYLLABLE_START)
1612             state = HangulStateT;
1613         else
1614             state = isHangulLVT(character) ? HangulStateLVT : HangulStateLV;
1615
1616         while (current > 0 && ((character = text.characterStartingAt(current - 1)) >= HANGUL_CHOSEONG_START) && (character <= HANGUL_SYLLABLE_END) && ((character <= HANGUL_JONGSEONG_END) || (character >= HANGUL_SYLLABLE_START))) {
1617             switch (state) {
1618             case HangulStateV:
1619                 if (character <= HANGUL_CHOSEONG_END)
1620                     state = HangulStateL;
1621                 else if ((character >= HANGUL_SYLLABLE_START) && (character <= HANGUL_SYLLABLE_END) && !isHangulLVT(character))
1622                     state = HangulStateLV;
1623                 else if (character > HANGUL_JUNGSEONG_END)
1624                     state = HangulStateBreak;
1625                 break;
1626             case HangulStateT:
1627                 if ((character >= HANGUL_JUNGSEONG_START) && (character <= HANGUL_JUNGSEONG_END))
1628                     state = HangulStateV;
1629                 else if ((character >= HANGUL_SYLLABLE_START) && (character <= HANGUL_SYLLABLE_END))
1630                     state = (isHangulLVT(character) ? HangulStateLVT : HangulStateLV);
1631                 else if (character < HANGUL_JUNGSEONG_START)
1632                     state = HangulStateBreak;
1633                 break;
1634             default:
1635                 state = (character < HANGUL_JUNGSEONG_START) ? HangulStateL : HangulStateBreak;
1636                 break;
1637             }
1638             if (state == HangulStateBreak)
1639                 break;
1640
1641             --current;
1642         }
1643     }
1644
1645     return current;
1646 #else
1647     // Platforms other than Mac delete by one code point.
1648     if (U16_IS_TRAIL(m_text[--current]))
1649         --current;
1650     if (current < 0)
1651         current = 0;
1652     return current;
1653 #endif
1654 }
1655
1656 int RenderText::nextOffset(int current) const
1657 {
1658     if (isAllASCII() || m_text.is8Bit())
1659         return current + 1;
1660
1661     StringImpl* textImpl = m_text.impl();
1662     TextBreakIterator* iterator = cursorMovementIterator(textImpl->characters16(), textImpl->length());
1663     if (!iterator)
1664         return current + 1;
1665
1666     long result = textBreakFollowing(iterator, current);
1667     if (result == TextBreakDone)
1668         result = current + 1;
1669
1670     return result;
1671 }
1672
1673 bool RenderText::computeCanUseSimpleFontCodePath() const
1674 {
1675     if (isAllASCII() || m_text.is8Bit())
1676         return true;
1677     return Font::characterRangeCodePath(characters(), length()) == Font::Simple;
1678 }
1679
1680 void RenderText::momentarilyRevealLastTypedCharacter(unsigned lastTypedCharacterOffset)
1681 {
1682     if (!gSecureTextTimers)
1683         gSecureTextTimers = new SecureTextTimerMap;
1684
1685     SecureTextTimer* secureTextTimer = gSecureTextTimers->get(this);
1686     if (!secureTextTimer) {
1687         secureTextTimer = new SecureTextTimer(this);
1688         gSecureTextTimers->add(this, secureTextTimer);
1689     }
1690     secureTextTimer->restartWithNewText(lastTypedCharacterOffset);
1691 }
1692
1693 } // namespace WebCore