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