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