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