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