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