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